1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------
4 namespace System.ServiceModel
5 {
6     using System;
7     using System.ComponentModel;
8     using System.Security.Authentication.ExtendedProtection;
9     using System.ServiceModel.Channels;
10     using System.ServiceModel.Security;
11     using System.Net;
12     using System.Net.Security;
13 
14     public sealed class HttpTransportSecurity
15     {
16         internal const HttpClientCredentialType DefaultClientCredentialType = HttpClientCredentialType.None;
17         internal const HttpProxyCredentialType DefaultProxyCredentialType = HttpProxyCredentialType.None;
18         internal const string DefaultRealm = System.ServiceModel.Channels.HttpTransportDefaults.Realm;
19 
20         HttpClientCredentialType clientCredentialType;
21         HttpProxyCredentialType proxyCredentialType;
22         string realm;
23         ExtendedProtectionPolicy extendedProtectionPolicy;
24 
HttpTransportSecurity()25         public HttpTransportSecurity()
26         {
27             this.clientCredentialType = DefaultClientCredentialType;
28             this.proxyCredentialType = DefaultProxyCredentialType;
29             this.realm = DefaultRealm;
30             this.extendedProtectionPolicy = ChannelBindingUtility.DefaultPolicy;
31         }
32 
33         public HttpClientCredentialType ClientCredentialType
34         {
35             get { return this.clientCredentialType; }
36             set
37             {
38                 if (!HttpClientCredentialTypeHelper.IsDefined(value))
39                 {
40                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value"));
41                 }
42                 this.clientCredentialType = value;
43             }
44         }
45 
46         public HttpProxyCredentialType ProxyCredentialType
47         {
48             get { return this.proxyCredentialType; }
49             set
50             {
51                 if (!HttpProxyCredentialTypeHelper.IsDefined(value))
52                 {
53                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value"));
54                 }
55                 this.proxyCredentialType = value;
56             }
57         }
58 
59         public string Realm
60         {
61             get { return this.realm; }
62             set { this.realm = value; }
63         }
64 
65         public ExtendedProtectionPolicy ExtendedProtectionPolicy
66         {
67             get
68             {
69                 return this.extendedProtectionPolicy;
70             }
71             set
72             {
73                 if (value == null)
74                 {
75                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
76                 }
77 
78                 if (value.PolicyEnforcement == PolicyEnforcement.Always &&
79                     !System.Security.Authentication.ExtendedProtection.ExtendedProtectionPolicy.OSSupportsExtendedProtection)
80                 {
81                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
82                         new PlatformNotSupportedException(SR.GetString(SR.ExtendedProtectionNotSupported)));
83                 }
84 
85                 this.extendedProtectionPolicy = value;
86             }
87         }
88 
ConfigureTransportProtectionOnly(HttpsTransportBindingElement https)89         internal void ConfigureTransportProtectionOnly(HttpsTransportBindingElement https)
90         {
91             DisableAuthentication(https);
92             https.RequireClientCertificate = false;
93         }
94 
ConfigureAuthentication(HttpTransportBindingElement http)95         void ConfigureAuthentication(HttpTransportBindingElement http)
96         {
97             http.AuthenticationScheme = HttpClientCredentialTypeHelper.MapToAuthenticationScheme(this.clientCredentialType);
98             http.ProxyAuthenticationScheme = HttpProxyCredentialTypeHelper.MapToAuthenticationScheme(this.proxyCredentialType);
99             http.Realm = this.Realm;
100             http.ExtendedProtectionPolicy = this.extendedProtectionPolicy;
101         }
102 
ConfigureAuthentication(HttpTransportBindingElement http, HttpTransportSecurity transportSecurity)103         static void ConfigureAuthentication(HttpTransportBindingElement http, HttpTransportSecurity transportSecurity)
104         {
105             transportSecurity.clientCredentialType = HttpClientCredentialTypeHelper.MapToClientCredentialType(http.AuthenticationScheme);
106             transportSecurity.proxyCredentialType = HttpProxyCredentialTypeHelper.MapToProxyCredentialType(http.ProxyAuthenticationScheme);
107             transportSecurity.Realm = http.Realm;
108             transportSecurity.extendedProtectionPolicy = http.ExtendedProtectionPolicy;
109         }
110 
DisableAuthentication(HttpTransportBindingElement http)111         void DisableAuthentication(HttpTransportBindingElement http)
112         {
113             http.AuthenticationScheme = AuthenticationSchemes.Anonymous;
114             http.ProxyAuthenticationScheme = AuthenticationSchemes.Anonymous;
115             http.Realm = DefaultRealm;
116             //ExtendedProtectionPolicy is always copied - even for security mode None, Message and TransportWithMessageCredential,
117             //because the settings for ExtendedProtectionPolicy are always below the <security><transport> element
118             http.ExtendedProtectionPolicy = this.extendedProtectionPolicy;
119         }
120 
IsDisabledAuthentication(HttpTransportBindingElement http)121         static bool IsDisabledAuthentication(HttpTransportBindingElement http)
122         {
123             return http.AuthenticationScheme == AuthenticationSchemes.Anonymous && http.ProxyAuthenticationScheme == AuthenticationSchemes.Anonymous && http.Realm == DefaultRealm;
124         }
125 
ConfigureTransportProtectionAndAuthentication(HttpsTransportBindingElement https)126         internal void ConfigureTransportProtectionAndAuthentication(HttpsTransportBindingElement https)
127         {
128             ConfigureAuthentication(https);
129             https.RequireClientCertificate = (this.clientCredentialType == HttpClientCredentialType.Certificate);
130         }
131 
ConfigureTransportProtectionAndAuthentication(HttpsTransportBindingElement https, HttpTransportSecurity transportSecurity)132         internal static void ConfigureTransportProtectionAndAuthentication(HttpsTransportBindingElement https, HttpTransportSecurity transportSecurity)
133         {
134             ConfigureAuthentication(https, transportSecurity);
135             if (https.RequireClientCertificate)
136                 transportSecurity.ClientCredentialType = HttpClientCredentialType.Certificate;
137         }
138 
ConfigureTransportAuthentication(HttpTransportBindingElement http)139         internal void ConfigureTransportAuthentication(HttpTransportBindingElement http)
140         {
141             if (this.clientCredentialType == HttpClientCredentialType.Certificate)
142             {
143                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.CertificateUnsupportedForHttpTransportCredentialOnly)));
144             }
145             ConfigureAuthentication(http);
146         }
147 
IsConfiguredTransportAuthentication(HttpTransportBindingElement http, HttpTransportSecurity transportSecurity)148         internal static bool IsConfiguredTransportAuthentication(HttpTransportBindingElement http, HttpTransportSecurity transportSecurity)
149         {
150             if (HttpClientCredentialTypeHelper.MapToClientCredentialType(http.AuthenticationScheme) == HttpClientCredentialType.Certificate)
151                 return false;
152             ConfigureAuthentication(http, transportSecurity);
153             return true;
154         }
155 
DisableTransportAuthentication(HttpTransportBindingElement http)156         internal void DisableTransportAuthentication(HttpTransportBindingElement http)
157         {
158             DisableAuthentication(http);
159         }
160 
IsDisabledTransportAuthentication(HttpTransportBindingElement http)161         internal static bool IsDisabledTransportAuthentication(HttpTransportBindingElement http)
162         {
163             return IsDisabledAuthentication(http);
164         }
165 
InternalShouldSerialize()166         internal bool InternalShouldSerialize()
167         {
168             return this.ShouldSerializeClientCredentialType()
169                 || this.ShouldSerializeProxyCredentialType()
170                 || this.ShouldSerializeRealm()
171                 || this.ShouldSerializeExtendedProtectionPolicy();
172         }
173 
174         [EditorBrowsable(EditorBrowsableState.Never)]
ShouldSerializeClientCredentialType()175         public bool ShouldSerializeClientCredentialType()
176         {
177             return this.ClientCredentialType != DefaultClientCredentialType;
178         }
179 
180         [EditorBrowsable(EditorBrowsableState.Never)]
ShouldSerializeProxyCredentialType()181         public bool ShouldSerializeProxyCredentialType()
182         {
183             return this.proxyCredentialType != DefaultProxyCredentialType;
184         }
185 
186         [EditorBrowsable(EditorBrowsableState.Never)]
ShouldSerializeRealm()187         public bool ShouldSerializeRealm()
188         {
189             return this.Realm != DefaultRealm;
190         }
191 
192         [EditorBrowsable(EditorBrowsableState.Never)]
ShouldSerializeExtendedProtectionPolicy()193         public bool ShouldSerializeExtendedProtectionPolicy()
194         {
195             return !ChannelBindingUtility.AreEqual(this.ExtendedProtectionPolicy, ChannelBindingUtility.DefaultPolicy);
196         }
197     }
198 }
199