1 // <copyright>
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 // </copyright>
4 
5 namespace System.ServiceModel
6 {
7     using System;
8     using System.ComponentModel;
9     using System.Diagnostics.CodeAnalysis;
10     using System.Runtime;
11     using System.ServiceModel.Channels;
12     using System.ServiceModel.Configuration;
13     using System.Text;
14     using System.Xml;
15 
16     public abstract class HttpBindingBase : Binding, IBindingRuntimePreferences
17     {
18         // private BindingElements
19         HttpTransportBindingElement httpTransport;
20         HttpsTransportBindingElement httpsTransport;
21         TextMessageEncodingBindingElement textEncoding;
22         MtomMessageEncodingBindingElement mtomEncoding;
23 
HttpBindingBase()24         internal HttpBindingBase()
25         {
26             this.httpTransport = new HttpTransportBindingElement();
27             this.httpsTransport = new HttpsTransportBindingElement();
28 
29             this.textEncoding = new TextMessageEncodingBindingElement();
30             this.textEncoding.MessageVersion = MessageVersion.Soap11;
31             this.mtomEncoding = new MtomMessageEncodingBindingElement();
32             this.mtomEncoding.MessageVersion = MessageVersion.Soap11;
33 
34             this.httpsTransport.WebSocketSettings = this.httpTransport.WebSocketSettings;
35         }
36 
37         [DefaultValue(HttpTransportDefaults.AllowCookies)]
38         public bool AllowCookies
39         {
40             get
41             {
42                 return this.httpTransport.AllowCookies;
43             }
44 
45             set
46             {
47                 this.httpTransport.AllowCookies = value;
48                 this.httpsTransport.AllowCookies = value;
49             }
50         }
51 
52         [DefaultValue(HttpTransportDefaults.BypassProxyOnLocal)]
53         public bool BypassProxyOnLocal
54         {
55             get
56             {
57                 return this.httpTransport.BypassProxyOnLocal;
58             }
59 
60             set
61             {
62                 this.httpTransport.BypassProxyOnLocal = value;
63                 this.httpsTransport.BypassProxyOnLocal = value;
64             }
65         }
66 
67         [DefaultValue(HttpTransportDefaults.HostNameComparisonMode)]
68         public HostNameComparisonMode HostNameComparisonMode
69         {
70             get
71             {
72                 return this.httpTransport.HostNameComparisonMode;
73             }
74 
75             set
76             {
77                 this.httpTransport.HostNameComparisonMode = value;
78                 this.httpsTransport.HostNameComparisonMode = value;
79             }
80         }
81 
82         [DefaultValue(TransportDefaults.MaxBufferSize)]
83         public int MaxBufferSize
84         {
85             get
86             {
87                 return this.httpTransport.MaxBufferSize;
88             }
89 
90             set
91             {
92                 this.httpTransport.MaxBufferSize = value;
93                 this.httpsTransport.MaxBufferSize = value;
94                 this.mtomEncoding.MaxBufferSize = value;
95             }
96         }
97 
98         [DefaultValue(TransportDefaults.MaxBufferPoolSize)]
99         public long MaxBufferPoolSize
100         {
101             get
102             {
103                 return this.httpTransport.MaxBufferPoolSize;
104             }
105 
106             set
107             {
108                 this.httpTransport.MaxBufferPoolSize = value;
109                 this.httpsTransport.MaxBufferPoolSize = value;
110             }
111         }
112 
113         [DefaultValue(TransportDefaults.MaxReceivedMessageSize)]
114         public long MaxReceivedMessageSize
115         {
116             get
117             {
118                 return this.httpTransport.MaxReceivedMessageSize;
119             }
120 
121             set
122             {
123                 this.httpTransport.MaxReceivedMessageSize = value;
124                 this.httpsTransport.MaxReceivedMessageSize = value;
125             }
126         }
127 
128         [DefaultValue(HttpTransportDefaults.ProxyAddress)]
129         [TypeConverter(typeof(UriTypeConverter))]
130         public Uri ProxyAddress
131         {
132             get
133             {
134                 return this.httpTransport.ProxyAddress;
135             }
136 
137             set
138             {
139                 this.httpTransport.ProxyAddress = value;
140                 this.httpsTransport.ProxyAddress = value;
141             }
142         }
143 
144         public XmlDictionaryReaderQuotas ReaderQuotas
145         {
146             get
147             {
148                 return this.textEncoding.ReaderQuotas;
149             }
150 
151             set
152             {
153                 if (value == null)
154                 {
155                     throw FxTrace.Exception.ArgumentNull("value");
156                 }
157 
158                 value.CopyTo(this.textEncoding.ReaderQuotas);
159                 value.CopyTo(this.mtomEncoding.ReaderQuotas);
160 
161                 this.SetReaderQuotas(value);
162             }
163         }
164 
165         public override string Scheme
166         {
167             get
168             {
169                 return this.GetTransport().Scheme;
170             }
171         }
172 
173         public EnvelopeVersion EnvelopeVersion
174         {
175             get { return this.GetEnvelopeVersion(); }
176         }
177 
178         [TypeConverter(typeof(EncodingConverter))]
179         public Encoding TextEncoding
180         {
181             get
182             {
183                 return this.textEncoding.WriteEncoding;
184             }
185 
186             set
187             {
188                 this.textEncoding.WriteEncoding = value;
189                 this.mtomEncoding.WriteEncoding = value;
190             }
191         }
192 
193         [DefaultValue(HttpTransportDefaults.TransferMode)]
194         public TransferMode TransferMode
195         {
196             get
197             {
198                 return this.httpTransport.TransferMode;
199             }
200 
201             set
202             {
203                 this.httpTransport.TransferMode = value;
204                 this.httpsTransport.TransferMode = value;
205             }
206         }
207 
208         [DefaultValue(HttpTransportDefaults.UseDefaultWebProxy)]
209         public bool UseDefaultWebProxy
210         {
211             get
212             {
213                 return this.httpTransport.UseDefaultWebProxy;
214             }
215 
216             set
217             {
218                 this.httpTransport.UseDefaultWebProxy = value;
219                 this.httpsTransport.UseDefaultWebProxy = value;
220             }
221         }
222 
223         bool IBindingRuntimePreferences.ReceiveSynchronously
224         {
225             get { return false; }
226         }
227 
228         internal TextMessageEncodingBindingElement TextMessageEncodingBindingElement
229         {
230             get
231             {
232                 return this.textEncoding;
233             }
234         }
235 
236         internal MtomMessageEncodingBindingElement MtomMessageEncodingBindingElement
237         {
238             get
239             {
240                 return this.mtomEncoding;
241             }
242         }
243 
244         internal abstract BasicHttpSecurity BasicHttpSecurity
245         {
246             get;
247         }
248 
249         internal WebSocketTransportSettings InternalWebSocketSettings
250         {
251             get
252             {
253                 return this.httpTransport.WebSocketSettings;
254             }
255         }
256 
257         [EditorBrowsable(EditorBrowsableState.Never)]
ShouldSerializeReaderQuotas()258         public bool ShouldSerializeReaderQuotas()
259         {
260             return !EncoderDefaults.IsDefaultReaderQuotas(this.ReaderQuotas);
261         }
262 
263         [EditorBrowsable(EditorBrowsableState.Never)]
ShouldSerializeTextEncoding()264         public bool ShouldSerializeTextEncoding()
265         {
266             return !this.TextEncoding.Equals(BasicHttpBindingDefaults.TextEncoding);
267         }
268 
GetSecurityModeFromTransport(HttpTransportBindingElement http, HttpTransportSecurity transportSecurity, out UnifiedSecurityMode mode)269         internal static bool GetSecurityModeFromTransport(HttpTransportBindingElement http, HttpTransportSecurity transportSecurity, out UnifiedSecurityMode mode)
270         {
271             mode = UnifiedSecurityMode.None;
272             if (http == null)
273             {
274                 return false;
275             }
276 
277             Fx.Assert(http.AuthenticationScheme.IsSingleton(), "authenticationScheme used in an Http(s)ChannelFactory must be a singleton value.");
278 
279             if (http is HttpsTransportBindingElement)
280             {
281                 mode = UnifiedSecurityMode.Transport | UnifiedSecurityMode.TransportWithMessageCredential;
282                 BasicHttpSecurity.EnableTransportSecurity((HttpsTransportBindingElement)http, transportSecurity);
283             }
284             else if (HttpTransportSecurity.IsDisabledTransportAuthentication(http))
285             {
286                 mode = UnifiedSecurityMode.Message | UnifiedSecurityMode.None;
287             }
288             else if (!BasicHttpSecurity.IsEnabledTransportAuthentication(http, transportSecurity))
289             {
290                 return false;
291             }
292             else
293             {
294                 mode = UnifiedSecurityMode.TransportCredentialOnly;
295             }
296 
297             return true;
298         }
299 
TryCreateSecurity(SecurityBindingElement securityElement, UnifiedSecurityMode mode, HttpTransportSecurity transportSecurity, out BasicHttpSecurity security)300         internal static bool TryCreateSecurity(SecurityBindingElement securityElement, UnifiedSecurityMode mode, HttpTransportSecurity transportSecurity, out BasicHttpSecurity security)
301         {
302             return BasicHttpSecurity.TryCreate(securityElement, mode, transportSecurity, out security);
303         }
304 
GetTransport()305         internal TransportBindingElement GetTransport()
306         {
307             Fx.Assert(this.BasicHttpSecurity != null, "this.BasicHttpSecurity should not return null from a derived class.");
308 
309             BasicHttpSecurity basicHttpSecurity = this.BasicHttpSecurity;
310             if (basicHttpSecurity.Mode == BasicHttpSecurityMode.Transport || basicHttpSecurity.Mode == BasicHttpSecurityMode.TransportWithMessageCredential)
311             {
312                 basicHttpSecurity.EnableTransportSecurity(this.httpsTransport);
313                 return this.httpsTransport;
314             }
315             else if (basicHttpSecurity.Mode == BasicHttpSecurityMode.TransportCredentialOnly)
316             {
317                 basicHttpSecurity.EnableTransportAuthentication(this.httpTransport);
318                 return this.httpTransport;
319             }
320             else
321             {
322                 // ensure that there is no transport security
323                 basicHttpSecurity.DisableTransportAuthentication(this.httpTransport);
324                 return this.httpTransport;
325             }
326         }
327 
GetEnvelopeVersion()328         internal abstract EnvelopeVersion GetEnvelopeVersion();
329 
SetReaderQuotas(XmlDictionaryReaderQuotas readerQuotas)330         internal virtual void SetReaderQuotas(XmlDictionaryReaderQuotas readerQuotas)
331         {
332         }
333 
InitializeFrom(HttpTransportBindingElement transport, MessageEncodingBindingElement encoding)334         internal virtual void InitializeFrom(HttpTransportBindingElement transport, MessageEncodingBindingElement encoding)
335         {
336             this.BypassProxyOnLocal = transport.BypassProxyOnLocal;
337             this.HostNameComparisonMode = transport.HostNameComparisonMode;
338             this.MaxBufferPoolSize = transport.MaxBufferPoolSize;
339             this.MaxBufferSize = transport.MaxBufferSize;
340             this.MaxReceivedMessageSize = transport.MaxReceivedMessageSize;
341             this.ProxyAddress = transport.ProxyAddress;
342             this.TransferMode = transport.TransferMode;
343             this.UseDefaultWebProxy = transport.UseDefaultWebProxy;
344             this.httpTransport.WebSocketSettings = transport.WebSocketSettings;
345             this.httpsTransport.WebSocketSettings = transport.WebSocketSettings;
346 
347             if (encoding is TextMessageEncodingBindingElement)
348             {
349                 TextMessageEncodingBindingElement text = (TextMessageEncodingBindingElement)encoding;
350                 this.TextEncoding = text.WriteEncoding;
351                 this.ReaderQuotas = text.ReaderQuotas;
352             }
353             else if (encoding is MtomMessageEncodingBindingElement)
354             {
355                 MtomMessageEncodingBindingElement mtom = (MtomMessageEncodingBindingElement)encoding;
356                 this.TextEncoding = mtom.WriteEncoding;
357                 this.ReaderQuotas = mtom.ReaderQuotas;
358             }
359 
360             this.BasicHttpSecurity.Transport.ExtendedProtectionPolicy = transport.ExtendedProtectionPolicy;
361         }
362 
363         // In the Win8 profile, some settings for the binding security are not supported.
CheckSettings()364         internal virtual void CheckSettings()
365         {
366             if (!UnsafeNativeMethods.IsTailoredApplication.Value)
367             {
368                 return;
369             }
370 
371             BasicHttpSecurity security = this.BasicHttpSecurity;
372             if (security == null)
373             {
374                 return;
375             }
376 
377             BasicHttpSecurityMode mode = security.Mode;
378             if (mode == BasicHttpSecurityMode.None)
379             {
380                 return;
381             }
382             else if (mode == BasicHttpSecurityMode.Message)
383             {
384                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.UnsupportedSecuritySetting, "Mode", mode)));
385             }
386 
387             // Message.ClientCredentialType = Certificate is not supported.
388             if (mode == BasicHttpSecurityMode.TransportWithMessageCredential)
389             {
390                 BasicHttpMessageSecurity message = security.Message;
391                 if ((message != null) && (message.ClientCredentialType == BasicHttpMessageCredentialType.Certificate))
392                 {
393                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.UnsupportedSecuritySetting, "Message.ClientCredentialType", message.ClientCredentialType)));
394                 }
395             }
396 
397             // Transport.ClientCredentialType = Certificate or InheritedFromHost are not supported.
398             Fx.Assert(
399                 (mode == BasicHttpSecurityMode.Transport) || (mode == BasicHttpSecurityMode.TransportCredentialOnly) || (mode == BasicHttpSecurityMode.TransportWithMessageCredential),
400                 "Unexpected BasicHttpSecurityMode value: " + mode);
401             HttpTransportSecurity transport = security.Transport;
402             if ((transport != null) && ((transport.ClientCredentialType == HttpClientCredentialType.Certificate) || (transport.ClientCredentialType == HttpClientCredentialType.InheritedFromHost)))
403             {
404                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.UnsupportedSecuritySetting, "Transport.ClientCredentialType", transport.ClientCredentialType)));
405             }
406         }
407     }
408 }
409