Merge pull request #496 from nicolas-raoul/unit-test-for-issue2907
[mono.git] / mcs / class / System.ServiceModel / System.ServiceModel / BasicHttpBinding.cs
1 //
2 // BasicHttpBinding.cs
3 //
4 // See BasicHttpBinding_4_5.cs and HttpBindingBase.cs for the .NET 4.5
5 // version of this class.
6 //
7 // Author:
8 //      Atsushi Enomoto <atsushi@ximian.com>
9 //
10 // Copyright (C) 2005-2006 Novell, Inc.  http://www.novell.com
11 // Copyright 2011 Xamarin Inc (http://www.xamarin.com).
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32 #if !NET_4_5 || MOBILE
33 using System;
34 using System.Collections.Generic;
35 using System.Net;
36 using System.Net.Security;
37 using System.ServiceModel.Channels;
38 using System.ServiceModel.Description;
39 using System.Text;
40 using System.Xml;
41 using System.ServiceModel.Configuration;
42
43 namespace System.ServiceModel
44 {
45         public class BasicHttpBinding : Binding,
46                 IBindingRuntimePreferences
47         {
48                 bool allow_cookies, bypass_proxy_on_local;
49                 HostNameComparisonMode host_name_comparison_mode
50                         = HostNameComparisonMode.StrongWildcard;
51                 long max_buffer_pool_size = 0x80000;
52                 int max_buffer_size = 0x10000;
53                 long max_recv_message_size = 0x10000;
54                 WSMessageEncoding message_encoding
55                         = WSMessageEncoding.Text;
56                 Uri proxy_address;
57                 XmlDictionaryReaderQuotas reader_quotas
58                         = new XmlDictionaryReaderQuotas ();
59                 EnvelopeVersion env_version = EnvelopeVersion.Soap11;
60                 Encoding text_encoding = new UTF8Encoding ();
61                 TransferMode transfer_mode
62                          = TransferMode.Buffered;
63                 bool use_default_web_proxy = true;
64                 BasicHttpSecurity security;
65
66                 public BasicHttpBinding ()
67                         : this (BasicHttpSecurityMode.None)
68                 {
69                 }
70
71 #if !NET_2_1
72                 public BasicHttpBinding (string configurationName)
73                         : this ()
74                 {
75                         BindingsSection bindingsSection = ConfigUtil.BindingsSection;
76                         BasicHttpBindingElement el = 
77                                 bindingsSection.BasicHttpBinding.Bindings [configurationName];
78
79                         el.ApplyConfiguration (this);
80                 }
81 #endif
82
83                 public BasicHttpBinding (
84                         BasicHttpSecurityMode securityMode)
85                 {
86                         security = new BasicHttpSecurity (securityMode);
87                 }
88
89                 public bool AllowCookies {
90                         get { return allow_cookies; }
91                         set { allow_cookies = value; }
92                 }
93
94                 public bool BypassProxyOnLocal {
95                         get { return bypass_proxy_on_local; }
96                         set { bypass_proxy_on_local = value; }
97                 }
98
99 #if NET_2_1
100                 public bool EnableHttpCookieContainer { get; set; }
101 #endif
102
103                 public HostNameComparisonMode HostNameComparisonMode {
104                         get { return host_name_comparison_mode; }
105                         set { host_name_comparison_mode = value; }
106                 }
107
108                 public long MaxBufferPoolSize {
109                         get { return max_buffer_pool_size; }
110                         set {
111                                 if (value <= 0)
112                                         throw new ArgumentOutOfRangeException ();
113                                 max_buffer_pool_size = value;
114                         }
115                 }
116
117                 public int MaxBufferSize {
118                         get { return max_buffer_size; }
119                         set {
120                                 if (value <= 0)
121                                         throw new ArgumentOutOfRangeException ();
122                                 max_buffer_size = value;
123                         }
124                 }
125
126                 public long MaxReceivedMessageSize {
127                         get { return max_recv_message_size; }
128                         set {
129                                 if (value <= 0)
130                                         throw new ArgumentOutOfRangeException ();
131                                 max_recv_message_size = value;
132                         }
133                 }
134
135                 public WSMessageEncoding MessageEncoding {
136                         get { return message_encoding; }
137                         set { message_encoding = value; }
138                 }
139
140                 public Uri ProxyAddress {
141                         get { return proxy_address; }
142                         set { proxy_address = value; }
143                 }
144
145                 public XmlDictionaryReaderQuotas ReaderQuotas {
146                         get { return reader_quotas; }
147                         set { reader_quotas = value; }
148                 }
149
150                 public override string Scheme {
151                         get {
152                                 switch (Security.Mode) {
153                                 case BasicHttpSecurityMode.Transport:
154                                 case BasicHttpSecurityMode.TransportWithMessageCredential:
155                                         return Uri.UriSchemeHttps;
156                                 default:
157                                         return Uri.UriSchemeHttp;
158                                 }
159                         }
160                 }
161
162                 public BasicHttpSecurity Security {
163                         get { return security; }
164                 }
165
166                 public EnvelopeVersion EnvelopeVersion {
167                         get { return env_version; }
168                 }
169
170                 public Encoding TextEncoding {
171                         get { return text_encoding; }
172                         set { text_encoding = value; }
173                 }
174
175                 public TransferMode TransferMode {
176                         get { return transfer_mode; }
177                         set { transfer_mode = value; }
178                 }
179
180                 public bool UseDefaultWebProxy {
181                         get { return use_default_web_proxy; }
182                         set { use_default_web_proxy = value; }
183                 }
184
185                 public override BindingElementCollection
186                         CreateBindingElements ()
187                 {
188                         var list = new List<BindingElement> ();
189                         
190                         var security = CreateSecurityBindingElement ();
191                         if (security != null)
192                                 list.Add (security);
193
194 #if NET_2_1
195                         if (EnableHttpCookieContainer)
196                                 list.Add (new HttpCookieContainerBindingElement ());
197 #endif
198
199                         list.Add (BuildMessageEncodingBindingElement ());
200                         list.Add (GetTransport ());
201
202                         return new BindingElementCollection (list.ToArray ());
203                 }
204                 
205                 SecurityBindingElement CreateSecurityBindingElement () 
206                 {
207             SecurityBindingElement element;
208                         switch (Security.Mode) {
209 #if !NET_2_1
210                         case BasicHttpSecurityMode.Message:
211                                 if (Security.Message.ClientCredentialType != BasicHttpMessageCredentialType.Certificate)
212                                         throw new InvalidOperationException ("When Message security is enabled in a BasicHttpBinding, the message security credential type must be BasicHttpMessageCredentialType.Certificate.");
213                                 element = SecurityBindingElement.CreateMutualCertificateBindingElement (
214                                     MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10);
215                                 break;
216
217                         case BasicHttpSecurityMode.TransportWithMessageCredential:
218                                 if (Security.Message.ClientCredentialType != BasicHttpMessageCredentialType.Certificate)
219                                         // FIXME: pass proper security token parameters.
220                                         element = SecurityBindingElement.CreateCertificateOverTransportBindingElement ();
221                                 else
222                                         element = new AsymmetricSecurityBindingElement ();
223                                 break;
224 #endif
225                         default: 
226                                 return null;
227                         }
228
229 #if !NET_2_1
230                         element.SetKeyDerivation (false);
231                         element.SecurityHeaderLayout = SecurityHeaderLayout.Lax;
232 #endif
233                         return element;
234                 }
235
236                 MessageEncodingBindingElement BuildMessageEncodingBindingElement ()
237                 {
238                         if (MessageEncoding == WSMessageEncoding.Text) {
239                                 TextMessageEncodingBindingElement tm = new TextMessageEncodingBindingElement (
240                                         MessageVersion.CreateVersion (EnvelopeVersion, AddressingVersion.None), TextEncoding);
241 #if !NET_2_1
242                                 ReaderQuotas.CopyTo (tm.ReaderQuotas);
243 #endif
244                                 return tm;
245                         }
246                         else
247 #if NET_2_1
248                                 throw new SystemException ("INTERNAL ERROR: should not happen");
249 #else
250                                 return new MtomMessageEncodingBindingElement (
251                                         MessageVersion.CreateVersion (EnvelopeVersion, AddressingVersion.None), TextEncoding);
252 #endif
253                 }
254
255                 TransportBindingElement GetTransport ()
256                 {
257                         HttpTransportBindingElement h;
258                         switch (Security.Mode) {
259                         case BasicHttpSecurityMode.Transport:
260                         case BasicHttpSecurityMode.TransportWithMessageCredential:
261                                 h = new HttpsTransportBindingElement ();
262                                 break;
263                         default:
264                                 h = new HttpTransportBindingElement ();
265                                 break;
266                         }
267
268                         h.AllowCookies = AllowCookies;
269                         h.BypassProxyOnLocal = BypassProxyOnLocal;
270                         h.HostNameComparisonMode = HostNameComparisonMode;
271                         h.MaxBufferPoolSize = MaxBufferPoolSize;
272                         h.MaxBufferSize = MaxBufferSize;
273                         h.MaxReceivedMessageSize = MaxReceivedMessageSize;
274                         h.ProxyAddress = ProxyAddress;
275                         h.UseDefaultWebProxy = UseDefaultWebProxy;
276                         h.TransferMode = TransferMode;
277 #if NET_4_0
278                         h.ExtendedProtectionPolicy = Security.Transport.ExtendedProtectionPolicy;
279 #endif
280
281 #if !NET_2_1 || MOBILE
282                         switch (Security.Transport.ClientCredentialType) {
283                         case HttpClientCredentialType.Basic:
284                                 h.AuthenticationScheme = AuthenticationSchemes.Basic;
285                                 break;
286                         case HttpClientCredentialType.Ntlm:
287                                 h.AuthenticationScheme = AuthenticationSchemes.Ntlm;
288                                 break;
289                         case HttpClientCredentialType.Windows:
290                                 h.AuthenticationScheme = AuthenticationSchemes.Negotiate;
291                                 break;
292                         case HttpClientCredentialType.Digest:
293                                 h.AuthenticationScheme = AuthenticationSchemes.Digest;
294                                 break;
295                         case HttpClientCredentialType.Certificate:
296                                 switch (Security.Mode) {
297                                 case BasicHttpSecurityMode.Transport:
298                                         (h as HttpsTransportBindingElement).RequireClientCertificate = true;
299                                         break;
300                                 case BasicHttpSecurityMode.TransportCredentialOnly:
301                                         throw new InvalidOperationException ("Certificate-based client authentication is not supported by 'TransportCredentialOnly' mode.");
302                                 }
303                                 break;
304                         }
305 #endif
306
307                         return h;
308                 }
309
310                 // explicit interface implementations
311
312                 bool IBindingRuntimePreferences.ReceiveSynchronously {
313                         get { return false; }
314                 }
315         }
316 }
317 #endif