Merge pull request #601 from knocte/sock_improvements
[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                 static readonly Encoding default_text_encoding = new UTF8Encoding ();
61                 Encoding text_encoding = default_text_encoding;
62                 TransferMode transfer_mode
63                          = TransferMode.Buffered;
64                 bool use_default_web_proxy = true;
65                 BasicHttpSecurity security;
66
67                 public BasicHttpBinding ()
68                         : this (BasicHttpSecurityMode.None)
69                 {
70                 }
71
72 #if !NET_2_1
73                 public BasicHttpBinding (string configurationName)
74                         : this ()
75                 {
76                         BindingsSection bindingsSection = ConfigUtil.BindingsSection;
77                         BasicHttpBindingElement el = 
78                                 bindingsSection.BasicHttpBinding.Bindings [configurationName];
79
80                         el.ApplyConfiguration (this);
81                 }
82 #endif
83
84                 public BasicHttpBinding (
85                         BasicHttpSecurityMode securityMode)
86                 {
87                         security = new BasicHttpSecurity (securityMode);
88                 }
89
90                 public bool AllowCookies {
91                         get { return allow_cookies; }
92                         set { allow_cookies = value; }
93                 }
94
95                 public bool BypassProxyOnLocal {
96                         get { return bypass_proxy_on_local; }
97                         set { bypass_proxy_on_local = value; }
98                 }
99
100 #if NET_2_1
101                 public bool EnableHttpCookieContainer {
102                         get; set;
103                 }
104 #elif NET_4_5
105                 [Obsolete ("Use AllowCookies.")]
106                 public bool EnableHttpCookieContainer {
107                         get { return AllowCookies; }
108                         set { AllowCookies = value; }
109                 }
110 #endif
111
112                 public HostNameComparisonMode HostNameComparisonMode {
113                         get { return host_name_comparison_mode; }
114                         set { host_name_comparison_mode = value; }
115                 }
116
117                 public long MaxBufferPoolSize {
118                         get { return max_buffer_pool_size; }
119                         set {
120                                 if (value <= 0)
121                                         throw new ArgumentOutOfRangeException ();
122                                 max_buffer_pool_size = value;
123                         }
124                 }
125
126                 public int MaxBufferSize {
127                         get { return max_buffer_size; }
128                         set {
129                                 if (value <= 0)
130                                         throw new ArgumentOutOfRangeException ();
131                                 max_buffer_size = value;
132                         }
133                 }
134
135                 public long MaxReceivedMessageSize {
136                         get { return max_recv_message_size; }
137                         set {
138                                 if (value <= 0)
139                                         throw new ArgumentOutOfRangeException ();
140                                 max_recv_message_size = value;
141                         }
142                 }
143
144                 public WSMessageEncoding MessageEncoding {
145                         get { return message_encoding; }
146                         set { message_encoding = value; }
147                 }
148
149                 public Uri ProxyAddress {
150                         get { return proxy_address; }
151                         set { proxy_address = value; }
152                 }
153
154                 public XmlDictionaryReaderQuotas ReaderQuotas {
155                         get { return reader_quotas; }
156                         set { reader_quotas = value; }
157                 }
158
159                 public override string Scheme {
160                         get {
161                                 switch (Security.Mode) {
162                                 case BasicHttpSecurityMode.Transport:
163                                 case BasicHttpSecurityMode.TransportWithMessageCredential:
164                                         return Uri.UriSchemeHttps;
165                                 default:
166                                         return Uri.UriSchemeHttp;
167                                 }
168                         }
169                 }
170
171                 public BasicHttpSecurity Security {
172                         get { return security; }
173                 }
174
175                 public EnvelopeVersion EnvelopeVersion {
176                         get { return env_version; }
177                 }
178
179                 internal static Encoding DefaultTextEncoding {
180                         get { return default_text_encoding; }
181                 }
182                 
183                 public Encoding TextEncoding {
184                         get { return text_encoding; }
185                         set { text_encoding = value; }
186                 }
187
188                 public TransferMode TransferMode {
189                         get { return transfer_mode; }
190                         set { transfer_mode = value; }
191                 }
192
193                 public bool UseDefaultWebProxy {
194                         get { return use_default_web_proxy; }
195                         set { use_default_web_proxy = value; }
196                 }
197
198                 public override BindingElementCollection
199                         CreateBindingElements ()
200                 {
201                         var list = new List<BindingElement> ();
202                         
203                         var security = CreateSecurityBindingElement ();
204                         if (security != null)
205                                 list.Add (security);
206
207 #if NET_2_1
208                         if (EnableHttpCookieContainer)
209                                 list.Add (new HttpCookieContainerBindingElement ());
210 #endif
211
212                         list.Add (BuildMessageEncodingBindingElement ());
213                         list.Add (GetTransport ());
214
215                         return new BindingElementCollection (list.ToArray ());
216                 }
217                 
218                 SecurityBindingElement CreateSecurityBindingElement () 
219                 {
220             SecurityBindingElement element;
221                         switch (Security.Mode) {
222 #if !NET_2_1
223                         case BasicHttpSecurityMode.Message:
224                                 if (Security.Message.ClientCredentialType != BasicHttpMessageCredentialType.Certificate)
225                                         throw new InvalidOperationException ("When Message security is enabled in a BasicHttpBinding, the message security credential type must be BasicHttpMessageCredentialType.Certificate.");
226                                 element = SecurityBindingElement.CreateMutualCertificateBindingElement (
227                                     MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10);
228                                 break;
229
230                         case BasicHttpSecurityMode.TransportWithMessageCredential:
231                                 if (Security.Message.ClientCredentialType != BasicHttpMessageCredentialType.Certificate)
232                                         // FIXME: pass proper security token parameters.
233                                         element = SecurityBindingElement.CreateCertificateOverTransportBindingElement ();
234                                 else
235                                         element = new AsymmetricSecurityBindingElement ();
236                                 break;
237 #endif
238                         default: 
239                                 return null;
240                         }
241
242 #if !NET_2_1
243                         element.SetKeyDerivation (false);
244                         element.SecurityHeaderLayout = SecurityHeaderLayout.Lax;
245 #endif
246                         return element;
247                 }
248
249                 MessageEncodingBindingElement BuildMessageEncodingBindingElement ()
250                 {
251                         if (MessageEncoding == WSMessageEncoding.Text) {
252                                 TextMessageEncodingBindingElement tm = new TextMessageEncodingBindingElement (
253                                         MessageVersion.CreateVersion (EnvelopeVersion, AddressingVersion.None), TextEncoding);
254 #if !NET_2_1
255                                 ReaderQuotas.CopyTo (tm.ReaderQuotas);
256 #endif
257                                 return tm;
258                         }
259                         else
260 #if NET_2_1
261                                 throw new SystemException ("INTERNAL ERROR: should not happen");
262 #else
263                                 return new MtomMessageEncodingBindingElement (
264                                         MessageVersion.CreateVersion (EnvelopeVersion, AddressingVersion.None), TextEncoding);
265 #endif
266                 }
267
268                 TransportBindingElement GetTransport ()
269                 {
270                         HttpTransportBindingElement h;
271                         switch (Security.Mode) {
272                         case BasicHttpSecurityMode.Transport:
273                         case BasicHttpSecurityMode.TransportWithMessageCredential:
274                                 h = new HttpsTransportBindingElement ();
275                                 break;
276                         default:
277                                 h = new HttpTransportBindingElement ();
278                                 break;
279                         }
280
281                         h.AllowCookies = AllowCookies;
282                         h.BypassProxyOnLocal = BypassProxyOnLocal;
283                         h.HostNameComparisonMode = HostNameComparisonMode;
284                         h.MaxBufferPoolSize = MaxBufferPoolSize;
285                         h.MaxBufferSize = MaxBufferSize;
286                         h.MaxReceivedMessageSize = MaxReceivedMessageSize;
287                         h.ProxyAddress = ProxyAddress;
288                         h.UseDefaultWebProxy = UseDefaultWebProxy;
289                         h.TransferMode = TransferMode;
290 #if NET_4_0
291                         h.ExtendedProtectionPolicy = Security.Transport.ExtendedProtectionPolicy;
292 #endif
293
294 #if !NET_2_1 || MOBILE
295                         switch (Security.Transport.ClientCredentialType) {
296                         case HttpClientCredentialType.Basic:
297                                 h.AuthenticationScheme = AuthenticationSchemes.Basic;
298                                 break;
299                         case HttpClientCredentialType.Ntlm:
300                                 h.AuthenticationScheme = AuthenticationSchemes.Ntlm;
301                                 break;
302                         case HttpClientCredentialType.Windows:
303                                 h.AuthenticationScheme = AuthenticationSchemes.Negotiate;
304                                 break;
305                         case HttpClientCredentialType.Digest:
306                                 h.AuthenticationScheme = AuthenticationSchemes.Digest;
307                                 break;
308                         case HttpClientCredentialType.Certificate:
309                                 switch (Security.Mode) {
310                                 case BasicHttpSecurityMode.Transport:
311                                         (h as HttpsTransportBindingElement).RequireClientCertificate = true;
312                                         break;
313                                 case BasicHttpSecurityMode.TransportCredentialOnly:
314                                         throw new InvalidOperationException ("Certificate-based client authentication is not supported by 'TransportCredentialOnly' mode.");
315                                 }
316                                 break;
317                         }
318 #endif
319
320                         return h;
321                 }
322
323                 // explicit interface implementations
324
325                 bool IBindingRuntimePreferences.ReceiveSynchronously {
326                         get { return false; }
327                 }
328         }
329 }
330 #endif