f27d8b8a471224cdba35e4707460e0c004b77ccb
[mono.git] / mcs / class / referencesource / System.ServiceModel / System / ServiceModel / Configuration / SecurityElementBase.cs
1 //------------------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------------------------
4
5 namespace System.ServiceModel.Configuration
6 {
7     using System.Collections.Generic;
8     using System.Collections.ObjectModel;
9     using System.ComponentModel;
10     using System.Configuration;
11     using System.IdentityModel.Tokens;
12     using System.Runtime;
13     using System.ServiceModel.Channels;
14     using System.ServiceModel.Security;
15     using System.ServiceModel.Security.Tokens;
16     using System.Xml;
17     using System.Linq;
18
19     public partial class SecurityElementBase : BindingElementExtensionElement
20     {
21         internal const AuthenticationMode defaultAuthenticationMode = AuthenticationMode.SspiNegotiated;
22
23         // if you add another variable, make sure to adjust: CopyFrom and UnMerge methods.
24         SecurityBindingElement failedSecurityBindingElement = null;
25         bool willX509IssuerReferenceAssertionBeWritten;
26         SecurityKeyType templateKeyType = IssuedSecurityTokenParameters.defaultKeyType;
27                 
28         internal SecurityElementBase()
29         {
30         }
31
32         internal bool HasImportFailed { get { return this.failedSecurityBindingElement != null; } }
33
34         internal bool IsSecurityElementBootstrap { get; set; } // Used in serialization path to optimize Xml representation
35
36         [ConfigurationProperty(ConfigurationStrings.DefaultAlgorithmSuite, DefaultValue = SecurityBindingElement.defaultAlgorithmSuiteString)]
37         [TypeConverter(typeof(SecurityAlgorithmSuiteConverter))]
38         public SecurityAlgorithmSuite DefaultAlgorithmSuite
39         {
40             get { return (SecurityAlgorithmSuite)base[ConfigurationStrings.DefaultAlgorithmSuite]; }
41             set { base[ConfigurationStrings.DefaultAlgorithmSuite] = value; }
42         }
43
44         [ConfigurationProperty(ConfigurationStrings.AllowSerializedSigningTokenOnReply, DefaultValue = AsymmetricSecurityBindingElement.defaultAllowSerializedSigningTokenOnReply)]
45         public bool AllowSerializedSigningTokenOnReply
46         {
47             get { return (bool)base[ConfigurationStrings.AllowSerializedSigningTokenOnReply]; }
48             set { base[ConfigurationStrings.AllowSerializedSigningTokenOnReply] = value; }
49         }
50
51         [ConfigurationProperty(ConfigurationStrings.EnableUnsecuredResponse, DefaultValue = SecurityBindingElement.defaultEnableUnsecuredResponse)]
52         public bool EnableUnsecuredResponse
53         {
54             get { return (bool)base[ConfigurationStrings.EnableUnsecuredResponse]; }
55             set { base[ConfigurationStrings.EnableUnsecuredResponse] = value; }
56         }
57
58         [ConfigurationProperty(ConfigurationStrings.AuthenticationMode, DefaultValue = defaultAuthenticationMode)]
59         [ServiceModelEnumValidator(typeof(AuthenticationModeHelper))]
60         public AuthenticationMode AuthenticationMode
61         {
62             get { return (AuthenticationMode)base[ConfigurationStrings.AuthenticationMode]; }
63             set { base[ConfigurationStrings.AuthenticationMode] = value; }
64         }
65
66         public override Type BindingElementType
67         {
68             get { return typeof(SecurityBindingElement); }
69         }
70
71         [ConfigurationProperty(ConfigurationStrings.RequireDerivedKeys, DefaultValue = SecurityTokenParameters.defaultRequireDerivedKeys)]
72         public bool RequireDerivedKeys
73         {
74             get { return (bool)base[ConfigurationStrings.RequireDerivedKeys]; }
75             set { base[ConfigurationStrings.RequireDerivedKeys] = value; }
76         }
77
78         [ConfigurationProperty(ConfigurationStrings.SecurityHeaderLayout, DefaultValue = SecurityProtocolFactory.defaultSecurityHeaderLayout)]
79         [ServiceModelEnumValidator(typeof(SecurityHeaderLayoutHelper))]
80         public SecurityHeaderLayout SecurityHeaderLayout
81         {
82             get { return (SecurityHeaderLayout)base[ConfigurationStrings.SecurityHeaderLayout]; }
83             set { base[ConfigurationStrings.SecurityHeaderLayout] = value; }
84         }
85
86         [ConfigurationProperty(ConfigurationStrings.IncludeTimestamp, DefaultValue = SecurityBindingElement.defaultIncludeTimestamp)]
87         public bool IncludeTimestamp
88         {
89             get { return (bool)base[ConfigurationStrings.IncludeTimestamp]; }
90             set { base[ConfigurationStrings.IncludeTimestamp] = value; }
91         }
92
93         [ConfigurationProperty(ConfigurationStrings.AllowInsecureTransport, DefaultValue = SecurityBindingElement.defaultAllowInsecureTransport)]
94         public bool AllowInsecureTransport
95         {
96             get { return (bool)base[ConfigurationStrings.AllowInsecureTransport]; }
97             set { base[ConfigurationStrings.AllowInsecureTransport] = value; }
98         }
99
100         [ConfigurationProperty(ConfigurationStrings.KeyEntropyMode, DefaultValue = System.ServiceModel.Security.AcceleratedTokenProvider.defaultKeyEntropyMode)]
101         [ServiceModelEnumValidator(typeof(SecurityKeyEntropyModeHelper))]
102         public SecurityKeyEntropyMode KeyEntropyMode
103         {
104             get { return (SecurityKeyEntropyMode)base[ConfigurationStrings.KeyEntropyMode]; }
105             set { base[ConfigurationStrings.KeyEntropyMode] = value; }
106         }
107
108         [ConfigurationProperty(ConfigurationStrings.IssuedTokenParameters)]
109         public IssuedTokenParametersElement IssuedTokenParameters
110         {
111             get { return (IssuedTokenParametersElement)base[ConfigurationStrings.IssuedTokenParameters]; }
112         }
113
114         [ConfigurationProperty(ConfigurationStrings.LocalClientSettings)]
115         public LocalClientSecuritySettingsElement LocalClientSettings
116         {
117             get { return (LocalClientSecuritySettingsElement)base[ConfigurationStrings.LocalClientSettings]; }
118         }
119
120         [ConfigurationProperty(ConfigurationStrings.LocalServiceSettings)]
121         public LocalServiceSecuritySettingsElement LocalServiceSettings
122         {
123             get { return (LocalServiceSecuritySettingsElement)base[ConfigurationStrings.LocalServiceSettings]; }
124         }
125
126         [ConfigurationProperty(ConfigurationStrings.MessageProtectionOrder, DefaultValue = SecurityBindingElement.defaultMessageProtectionOrder)]
127         [ServiceModelEnumValidator(typeof(MessageProtectionOrderHelper))]
128         public MessageProtectionOrder MessageProtectionOrder
129         {
130             get { return (MessageProtectionOrder)base[ConfigurationStrings.MessageProtectionOrder]; }
131             set { base[ConfigurationStrings.MessageProtectionOrder] = value; }
132         }
133
134         [ConfigurationProperty(ConfigurationStrings.ProtectTokens, DefaultValue = false)]
135         public bool ProtectTokens
136         {
137             get { return (bool)base[ConfigurationStrings.ProtectTokens]; }
138             set { base[ConfigurationStrings.ProtectTokens] = value; }
139         }
140
141         [ConfigurationProperty(ConfigurationStrings.MessageSecurityVersion, DefaultValue = ConfigurationStrings.Default)]
142         [TypeConverter(typeof(MessageSecurityVersionConverter))]
143         public MessageSecurityVersion MessageSecurityVersion
144         {
145             get { return (MessageSecurityVersion)base[ConfigurationStrings.MessageSecurityVersion]; }
146             set { base[ConfigurationStrings.MessageSecurityVersion] = value; }
147         }
148
149         [ConfigurationProperty(ConfigurationStrings.RequireSecurityContextCancellation, DefaultValue = SecureConversationSecurityTokenParameters.defaultRequireCancellation)]
150         public bool RequireSecurityContextCancellation
151         {
152             get { return (bool)base[ConfigurationStrings.RequireSecurityContextCancellation]; }
153             set { base[ConfigurationStrings.RequireSecurityContextCancellation] = value; }
154         }
155
156         [ConfigurationProperty(ConfigurationStrings.RequireSignatureConfirmation, DefaultValue = SecurityBindingElement.defaultRequireSignatureConfirmation)]
157         public bool RequireSignatureConfirmation
158         {
159             get { return (bool)base[ConfigurationStrings.RequireSignatureConfirmation]; }
160             set { base[ConfigurationStrings.RequireSignatureConfirmation] = value; }
161         }
162
163         [ConfigurationProperty(ConfigurationStrings.CanRenewSecurityContextToken, DefaultValue = SecureConversationSecurityTokenParameters.defaultCanRenewSession)]
164         public bool CanRenewSecurityContextToken
165         {
166             get { return (bool)base[ConfigurationStrings.CanRenewSecurityContextToken]; }
167             set { base[ConfigurationStrings.CanRenewSecurityContextToken] = value; }
168         }
169
170         public override void ApplyConfiguration(BindingElement bindingElement)
171         {
172             base.ApplyConfiguration(bindingElement);
173
174             SecurityBindingElement sbe = (SecurityBindingElement)bindingElement;
175
176 #pragma warning disable 56506 //Microsoft; base.CopyFrom() checks for 'from' being null
177             if (PropertyValueOrigin.Default != this.ElementInformation.Properties[ConfigurationStrings.DefaultAlgorithmSuite].ValueOrigin)
178                 sbe.DefaultAlgorithmSuite = this.DefaultAlgorithmSuite;
179             if (PropertyValueOrigin.Default != this.ElementInformation.Properties[ConfigurationStrings.IncludeTimestamp].ValueOrigin)
180                 sbe.IncludeTimestamp = this.IncludeTimestamp;
181             if (PropertyValueOrigin.Default != this.ElementInformation.Properties[ConfigurationStrings.MessageSecurityVersion].ValueOrigin)
182                 sbe.MessageSecurityVersion = this.MessageSecurityVersion;
183             if (PropertyValueOrigin.Default != this.ElementInformation.Properties[ConfigurationStrings.KeyEntropyMode].ValueOrigin)
184                 sbe.KeyEntropyMode = this.KeyEntropyMode;
185             if (PropertyValueOrigin.Default != this.ElementInformation.Properties[ConfigurationStrings.SecurityHeaderLayout].ValueOrigin)
186                 sbe.SecurityHeaderLayout = this.SecurityHeaderLayout;
187             if (PropertyValueOrigin.Default != this.ElementInformation.Properties[ConfigurationStrings.RequireDerivedKeys].ValueOrigin)
188                 sbe.SetKeyDerivation(this.RequireDerivedKeys);
189             if (PropertyValueOrigin.Default != this.ElementInformation.Properties[ConfigurationStrings.AllowInsecureTransport].ValueOrigin)
190                 sbe.AllowInsecureTransport = this.AllowInsecureTransport;
191             if (PropertyValueOrigin.Default != this.ElementInformation.Properties[ConfigurationStrings.EnableUnsecuredResponse].ValueOrigin)
192                 sbe.EnableUnsecuredResponse = this.EnableUnsecuredResponse;
193             if (PropertyValueOrigin.Default != this.ElementInformation.Properties[ConfigurationStrings.ProtectTokens].ValueOrigin)
194                 sbe.ProtectTokens = this.ProtectTokens;
195 #pragma warning restore
196
197             SymmetricSecurityBindingElement ssbe = sbe as SymmetricSecurityBindingElement;
198
199             if (ssbe != null)
200             {
201                 if (PropertyValueOrigin.Default != this.ElementInformation.Properties[ConfigurationStrings.MessageProtectionOrder].ValueOrigin)
202                     ssbe.MessageProtectionOrder = this.MessageProtectionOrder;
203                 if (PropertyValueOrigin.Default != this.ElementInformation.Properties[ConfigurationStrings.RequireSignatureConfirmation].ValueOrigin)
204                     ssbe.RequireSignatureConfirmation = this.RequireSignatureConfirmation;
205                 SecureConversationSecurityTokenParameters scParameters = ssbe.ProtectionTokenParameters as SecureConversationSecurityTokenParameters;
206                 if (scParameters != null)
207                 {
208                     scParameters.CanRenewSession = this.CanRenewSecurityContextToken;
209                 }
210             }
211
212             AsymmetricSecurityBindingElement asbe = sbe as AsymmetricSecurityBindingElement;
213
214             if (asbe != null)
215             {
216                 if (PropertyValueOrigin.Default != this.ElementInformation.Properties[ConfigurationStrings.MessageProtectionOrder].ValueOrigin)
217                     asbe.MessageProtectionOrder = this.MessageProtectionOrder;
218                 if (PropertyValueOrigin.Default != this.ElementInformation.Properties[ConfigurationStrings.RequireSignatureConfirmation].ValueOrigin)
219                     asbe.RequireSignatureConfirmation = this.RequireSignatureConfirmation;
220                 if (PropertyValueOrigin.Default != this.ElementInformation.Properties[ConfigurationStrings.AllowSerializedSigningTokenOnReply].ValueOrigin)
221                     asbe.AllowSerializedSigningTokenOnReply = this.AllowSerializedSigningTokenOnReply;
222             }
223
224             TransportSecurityBindingElement tsbe = sbe as TransportSecurityBindingElement;
225
226             if (tsbe != null)
227             {
228                 if (tsbe.EndpointSupportingTokenParameters.Endorsing.Count == 1)
229                 {
230                     SecureConversationSecurityTokenParameters scParameters = tsbe.EndpointSupportingTokenParameters.Endorsing[0] as SecureConversationSecurityTokenParameters;
231                     if (scParameters != null)
232                     {
233                         scParameters.CanRenewSession = this.CanRenewSecurityContextToken;
234                     }
235                 }
236             }
237
238             if (PropertyValueOrigin.Default != this.ElementInformation.Properties[ConfigurationStrings.LocalClientSettings].ValueOrigin)
239             {
240                 this.LocalClientSettings.ApplyConfiguration(sbe.LocalClientSettings);
241             }
242
243             if (PropertyValueOrigin.Default != this.ElementInformation.Properties[ConfigurationStrings.LocalServiceSettings].ValueOrigin)
244             {
245                 this.LocalServiceSettings.ApplyConfiguration(sbe.LocalServiceSettings);
246             }
247         }
248
249         public override void CopyFrom(ServiceModelExtensionElement from)
250         {
251             base.CopyFrom(from);
252
253             SecurityElementBase source = (SecurityElementBase)from;
254
255             if (PropertyValueOrigin.Default != source.ElementInformation.Properties[ConfigurationStrings.AllowSerializedSigningTokenOnReply].ValueOrigin)
256                 this.AllowSerializedSigningTokenOnReply = source.AllowSerializedSigningTokenOnReply;
257             if (PropertyValueOrigin.Default != source.ElementInformation.Properties[ConfigurationStrings.DefaultAlgorithmSuite].ValueOrigin)
258                 this.DefaultAlgorithmSuite = source.DefaultAlgorithmSuite;
259             if (PropertyValueOrigin.Default != source.ElementInformation.Properties[ConfigurationStrings.EnableUnsecuredResponse].ValueOrigin)
260                 this.EnableUnsecuredResponse = source.EnableUnsecuredResponse;
261             if (PropertyValueOrigin.Default != source.ElementInformation.Properties[ConfigurationStrings.AllowInsecureTransport].ValueOrigin)
262                 this.AllowInsecureTransport = source.AllowInsecureTransport;
263             if (PropertyValueOrigin.Default != source.ElementInformation.Properties[ConfigurationStrings.RequireDerivedKeys].ValueOrigin)
264                 this.RequireDerivedKeys = source.RequireDerivedKeys;
265             if (PropertyValueOrigin.Default != source.ElementInformation.Properties[ConfigurationStrings.IncludeTimestamp].ValueOrigin)
266                 this.IncludeTimestamp = source.IncludeTimestamp;
267             if (PropertyValueOrigin.Default != source.ElementInformation.Properties[ConfigurationStrings.IssuedTokenParameters].ValueOrigin)
268                 this.IssuedTokenParameters.Copy(source.IssuedTokenParameters);
269             if (PropertyValueOrigin.Default != source.ElementInformation.Properties[ConfigurationStrings.MessageProtectionOrder].ValueOrigin)
270                 this.MessageProtectionOrder = source.MessageProtectionOrder;
271             if (PropertyValueOrigin.Default != source.ElementInformation.Properties[ConfigurationStrings.ProtectTokens].ValueOrigin)
272                 this.ProtectTokens = source.ProtectTokens;
273             if (PropertyValueOrigin.Default != source.ElementInformation.Properties[ConfigurationStrings.MessageSecurityVersion].ValueOrigin)
274                 this.MessageSecurityVersion = source.MessageSecurityVersion;
275             if (PropertyValueOrigin.Default != source.ElementInformation.Properties[ConfigurationStrings.RequireSignatureConfirmation].ValueOrigin)
276                 this.RequireSignatureConfirmation = source.RequireSignatureConfirmation;
277             if (PropertyValueOrigin.Default != source.ElementInformation.Properties[ConfigurationStrings.RequireSecurityContextCancellation].ValueOrigin)
278                 this.RequireSecurityContextCancellation = source.RequireSecurityContextCancellation;
279             if (PropertyValueOrigin.Default != source.ElementInformation.Properties[ConfigurationStrings.CanRenewSecurityContextToken].ValueOrigin)
280                 this.CanRenewSecurityContextToken = source.CanRenewSecurityContextToken;
281             if (PropertyValueOrigin.Default != source.ElementInformation.Properties[ConfigurationStrings.KeyEntropyMode].ValueOrigin)
282                 this.KeyEntropyMode = source.KeyEntropyMode;
283             if (PropertyValueOrigin.Default != source.ElementInformation.Properties[ConfigurationStrings.SecurityHeaderLayout].ValueOrigin)
284                 this.SecurityHeaderLayout = source.SecurityHeaderLayout;
285             if (PropertyValueOrigin.Default != source.ElementInformation.Properties[ConfigurationStrings.LocalClientSettings].ValueOrigin)
286                 this.LocalClientSettings.CopyFrom(source.LocalClientSettings);
287             if (PropertyValueOrigin.Default != source.ElementInformation.Properties[ConfigurationStrings.LocalServiceSettings].ValueOrigin)
288                 this.LocalServiceSettings.CopyFrom(source.LocalServiceSettings);
289             
290             this.failedSecurityBindingElement = source.failedSecurityBindingElement;
291             this.willX509IssuerReferenceAssertionBeWritten = source.willX509IssuerReferenceAssertionBeWritten;
292         }
293
294         protected internal override BindingElement CreateBindingElement()
295         {
296             return this.CreateBindingElement(false);
297         }
298
299         protected internal virtual BindingElement CreateBindingElement(bool createTemplateOnly)
300         {
301             SecurityBindingElement result;
302             switch (this.AuthenticationMode)
303             {
304                 case AuthenticationMode.AnonymousForCertificate:
305                     result = SecurityBindingElement.CreateAnonymousForCertificateBindingElement();
306                     break;
307                 case AuthenticationMode.AnonymousForSslNegotiated:
308                     result = SecurityBindingElement.CreateSslNegotiationBindingElement(false, this.RequireSecurityContextCancellation);
309                     break;
310                 case AuthenticationMode.CertificateOverTransport:
311                     result = SecurityBindingElement.CreateCertificateOverTransportBindingElement(this.MessageSecurityVersion);
312                     break;
313                 case AuthenticationMode.IssuedToken:
314                     result = SecurityBindingElement.CreateIssuedTokenBindingElement(this.IssuedTokenParameters.Create(createTemplateOnly, this.templateKeyType));
315                     break;
316                 case AuthenticationMode.IssuedTokenForCertificate:
317                     result = SecurityBindingElement.CreateIssuedTokenForCertificateBindingElement(this.IssuedTokenParameters.Create(createTemplateOnly, this.templateKeyType));
318                     break;
319                 case AuthenticationMode.IssuedTokenForSslNegotiated:
320                     result = SecurityBindingElement.CreateIssuedTokenForSslBindingElement(this.IssuedTokenParameters.Create(createTemplateOnly, this.templateKeyType), this.RequireSecurityContextCancellation);
321                     break;
322                 case AuthenticationMode.IssuedTokenOverTransport:
323                     result = SecurityBindingElement.CreateIssuedTokenOverTransportBindingElement(this.IssuedTokenParameters.Create(createTemplateOnly, this.templateKeyType));
324                     break;
325                 case AuthenticationMode.Kerberos:
326                     result = SecurityBindingElement.CreateKerberosBindingElement();
327                     break;
328                 case AuthenticationMode.KerberosOverTransport:
329                     result = SecurityBindingElement.CreateKerberosOverTransportBindingElement();
330                     break;
331                 case AuthenticationMode.MutualCertificateDuplex:
332                     result = SecurityBindingElement.CreateMutualCertificateDuplexBindingElement(this.MessageSecurityVersion);
333                     break;
334                 case AuthenticationMode.MutualCertificate:
335                     result = SecurityBindingElement.CreateMutualCertificateBindingElement(this.MessageSecurityVersion);
336                     break;
337                 case AuthenticationMode.MutualSslNegotiated:
338                     result = SecurityBindingElement.CreateSslNegotiationBindingElement(true, this.RequireSecurityContextCancellation);
339                     break;
340                 case AuthenticationMode.SspiNegotiated:
341                     result = SecurityBindingElement.CreateSspiNegotiationBindingElement(this.RequireSecurityContextCancellation);
342                     break;
343                 case AuthenticationMode.UserNameForCertificate:
344                     result = SecurityBindingElement.CreateUserNameForCertificateBindingElement();
345                     break;
346                 case AuthenticationMode.UserNameForSslNegotiated:
347                     result = SecurityBindingElement.CreateUserNameForSslBindingElement(this.RequireSecurityContextCancellation);
348                     break;
349                 case AuthenticationMode.UserNameOverTransport:
350                     result = SecurityBindingElement.CreateUserNameOverTransportBindingElement();
351                     break;
352                 case AuthenticationMode.SspiNegotiatedOverTransport:
353                     result = SecurityBindingElement.CreateSspiNegotiationOverTransportBindingElement(this.RequireSecurityContextCancellation);
354                     break;
355                 default:
356                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException("AuthenticationMode", (int)this.AuthenticationMode, typeof(AuthenticationMode)));
357             }
358
359             this.ApplyConfiguration(result);
360
361             return result;
362         }
363
364         protected void AddBindingTemplate(Dictionary<AuthenticationMode, SecurityBindingElement> bindingTemplates, AuthenticationMode mode)
365         {
366             this.AuthenticationMode = mode;
367             try
368             {
369                 bindingTemplates[mode] = (SecurityBindingElement)this.CreateBindingElement(true);
370             }
371 #pragma warning suppress 56500 // covered by FxCOP
372             catch (Exception e)
373             {
374                 if (Fx.IsFatal(e))
375                 {
376                     throw;
377                 }
378             }
379         }
380
381         static bool AreTokenParametersMatching(SecurityTokenParameters p1, SecurityTokenParameters p2, bool skipRequireDerivedKeysComparison, bool exactMessageSecurityVersion)
382         {
383             if (p1 == null || p2 == null)
384                 return false;
385
386             if (p1.GetType() != p2.GetType())
387                 return false;
388
389             if (p1.InclusionMode != p2.InclusionMode)
390                 return false;
391
392             if (skipRequireDerivedKeysComparison == false && p1.RequireDerivedKeys != p2.RequireDerivedKeys)
393                 return false;
394
395             if (p1.ReferenceStyle != p2.ReferenceStyle)
396                 return false;
397
398             // mutual ssl and anonymous ssl differ in the client cert requirement
399             if (p1 is SslSecurityTokenParameters)
400             {
401                 if (((SslSecurityTokenParameters)p1).RequireClientCertificate != ((SslSecurityTokenParameters)p2).RequireClientCertificate)
402                     return false;
403             }
404             else if (p1 is SecureConversationSecurityTokenParameters)
405             {
406                 SecureConversationSecurityTokenParameters sc1 = (SecureConversationSecurityTokenParameters)p1;
407                 SecureConversationSecurityTokenParameters sc2 = (SecureConversationSecurityTokenParameters)p2;
408
409                 if (sc1.RequireCancellation != sc2.RequireCancellation)
410                     return false;
411
412                 if (sc1.CanRenewSession != sc2.CanRenewSession)
413                     return false;
414
415
416                 if (!AreBindingsMatching(sc1.BootstrapSecurityBindingElement, sc2.BootstrapSecurityBindingElement, exactMessageSecurityVersion))
417                     return false;
418             }
419             else if (p1 is IssuedSecurityTokenParameters)
420             {
421                 if (((IssuedSecurityTokenParameters)p1).KeyType != ((IssuedSecurityTokenParameters)p2).KeyType)
422                     return false;
423             }
424
425             return true;
426         }
427
428         static bool AreTokenParameterCollectionsMatching(Collection<SecurityTokenParameters> c1, Collection<SecurityTokenParameters> c2, bool exactMessageSecurityVersion)
429         {
430             if (c1.Count != c2.Count)
431                 return false;
432
433             for (int i = 0; i < c1.Count; i++)
434                 if (!AreTokenParametersMatching(c1[i], c2[i], true, exactMessageSecurityVersion))
435                     return false;
436
437             return true;
438         }
439
440         internal static bool AreBindingsMatching(SecurityBindingElement b1, SecurityBindingElement b2)
441         {
442             return AreBindingsMatching(b1, b2, true);
443         }
444
445         internal static bool AreBindingsMatching(SecurityBindingElement b1, SecurityBindingElement b2, bool exactMessageSecurityVersion)
446         {
447             if (b1 == null || b2 == null)
448                 return b1 == b2;
449  
450             if (b1.GetType() != b2.GetType())
451                 return false;
452
453             if (b1.MessageSecurityVersion != b2.MessageSecurityVersion)
454             {
455                 // exactMessageSecurityVersion meant that BSP mismatch could be ignored
456                 if (exactMessageSecurityVersion)
457                     return false;
458
459                 if (b1.MessageSecurityVersion.SecurityVersion != b2.MessageSecurityVersion.SecurityVersion
460                  || b1.MessageSecurityVersion.TrustVersion != b2.MessageSecurityVersion.TrustVersion
461                  || b1.MessageSecurityVersion.SecureConversationVersion != b2.MessageSecurityVersion.SecureConversationVersion
462                  || b1.MessageSecurityVersion.SecurityPolicyVersion != b2.MessageSecurityVersion.SecurityPolicyVersion)
463                 {
464                     return false;
465                 }
466             }
467
468             if (b1.SecurityHeaderLayout != b2.SecurityHeaderLayout)
469                 return false;
470
471             if (b1.DefaultAlgorithmSuite != b2.DefaultAlgorithmSuite)
472                 return false;
473
474             if (b1.IncludeTimestamp != b2.IncludeTimestamp)
475                 return false;
476
477             if (b1.SecurityHeaderLayout != b2.SecurityHeaderLayout)
478                 return false;
479
480             if (b1.KeyEntropyMode != b2.KeyEntropyMode)
481                 return false;
482
483             if (!AreTokenParameterCollectionsMatching(b1.EndpointSupportingTokenParameters.Endorsing, b2.EndpointSupportingTokenParameters.Endorsing, exactMessageSecurityVersion))
484                 return false;
485
486             if (!AreTokenParameterCollectionsMatching(b1.EndpointSupportingTokenParameters.SignedEncrypted, b2.EndpointSupportingTokenParameters.SignedEncrypted, exactMessageSecurityVersion))
487                 return false;
488
489             if (!AreTokenParameterCollectionsMatching(b1.EndpointSupportingTokenParameters.Signed, b2.EndpointSupportingTokenParameters.Signed, exactMessageSecurityVersion))
490                 return false;
491
492             if (!AreTokenParameterCollectionsMatching(b1.EndpointSupportingTokenParameters.SignedEndorsing, b2.EndpointSupportingTokenParameters.SignedEndorsing, exactMessageSecurityVersion))
493                 return false;
494
495             if (b1.OperationSupportingTokenParameters.Count != b2.OperationSupportingTokenParameters.Count)
496                 return false;
497
498             foreach (KeyValuePair<string, SupportingTokenParameters> operation1 in b1.OperationSupportingTokenParameters)
499             {
500                 if (!b2.OperationSupportingTokenParameters.ContainsKey(operation1.Key))
501                     return false;
502
503                 SupportingTokenParameters stp2 = b2.OperationSupportingTokenParameters[operation1.Key];
504
505                 if (!AreTokenParameterCollectionsMatching(operation1.Value.Endorsing, stp2.Endorsing, exactMessageSecurityVersion))
506                     return false;
507
508                 if (!AreTokenParameterCollectionsMatching(operation1.Value.SignedEncrypted, stp2.SignedEncrypted, exactMessageSecurityVersion))
509                     return false;
510
511                 if (!AreTokenParameterCollectionsMatching(operation1.Value.Signed, stp2.Signed, exactMessageSecurityVersion))
512                     return false;
513
514                 if (!AreTokenParameterCollectionsMatching(operation1.Value.SignedEndorsing, stp2.SignedEndorsing, exactMessageSecurityVersion))
515                     return false;
516             }
517
518             SymmetricSecurityBindingElement ssbe1 = b1 as SymmetricSecurityBindingElement;            
519             if (ssbe1 != null)
520             {
521                 SymmetricSecurityBindingElement ssbe2 = (SymmetricSecurityBindingElement)b2;
522
523                 if (ssbe1.MessageProtectionOrder != ssbe2.MessageProtectionOrder)
524                     return false;
525
526                 if (!AreTokenParametersMatching(ssbe1.ProtectionTokenParameters, ssbe2.ProtectionTokenParameters, false, exactMessageSecurityVersion))
527                     return false;
528             }
529
530             AsymmetricSecurityBindingElement asbe1 = b1 as AsymmetricSecurityBindingElement;
531             if (asbe1 != null)
532             {
533                 AsymmetricSecurityBindingElement asbe2 = (AsymmetricSecurityBindingElement)b2;
534
535                 if (asbe1.MessageProtectionOrder != asbe2.MessageProtectionOrder)
536                     return false;
537
538                 if (asbe1.RequireSignatureConfirmation != asbe2.RequireSignatureConfirmation)
539                     return false;
540
541                 if (!AreTokenParametersMatching(asbe1.InitiatorTokenParameters, asbe2.InitiatorTokenParameters, true, exactMessageSecurityVersion)
542                     || !AreTokenParametersMatching(asbe1.RecipientTokenParameters, asbe2.RecipientTokenParameters, true, exactMessageSecurityVersion))
543                     return false;
544             }
545
546             return true;
547         }
548
549         protected virtual void AddBindingTemplates(Dictionary<AuthenticationMode, SecurityBindingElement> bindingTemplates)
550         {
551             AddBindingTemplate(bindingTemplates, AuthenticationMode.AnonymousForCertificate);
552             AddBindingTemplate(bindingTemplates, AuthenticationMode.AnonymousForSslNegotiated);
553             AddBindingTemplate(bindingTemplates, AuthenticationMode.CertificateOverTransport);
554             if (this.templateKeyType == SecurityKeyType.SymmetricKey)
555             {
556                 AddBindingTemplate(bindingTemplates, AuthenticationMode.IssuedToken);
557             }
558             AddBindingTemplate(bindingTemplates, AuthenticationMode.IssuedTokenForCertificate);
559             AddBindingTemplate(bindingTemplates, AuthenticationMode.IssuedTokenForSslNegotiated);
560             AddBindingTemplate(bindingTemplates, AuthenticationMode.IssuedTokenOverTransport);
561             AddBindingTemplate(bindingTemplates, AuthenticationMode.Kerberos);
562             AddBindingTemplate(bindingTemplates, AuthenticationMode.KerberosOverTransport);
563             AddBindingTemplate(bindingTemplates, AuthenticationMode.MutualCertificate);
564             AddBindingTemplate(bindingTemplates, AuthenticationMode.MutualCertificateDuplex);
565             AddBindingTemplate(bindingTemplates, AuthenticationMode.MutualSslNegotiated);
566             AddBindingTemplate(bindingTemplates, AuthenticationMode.SspiNegotiated);
567             AddBindingTemplate(bindingTemplates, AuthenticationMode.UserNameForCertificate);
568             AddBindingTemplate(bindingTemplates, AuthenticationMode.UserNameForSslNegotiated);
569             AddBindingTemplate(bindingTemplates, AuthenticationMode.UserNameOverTransport);
570             AddBindingTemplate(bindingTemplates, AuthenticationMode.SspiNegotiatedOverTransport);
571         }
572
573         bool TryInitializeAuthenticationMode(SecurityBindingElement sbe)
574         {
575             bool result;
576
577             if (sbe.OperationSupportingTokenParameters.Count > 0)
578                 result = false;
579             else
580             {
581                 SetIssuedTokenKeyType(sbe);
582
583                 Dictionary<AuthenticationMode, SecurityBindingElement> bindingTemplates = new Dictionary<AuthenticationMode, SecurityBindingElement>();
584                 this.AddBindingTemplates(bindingTemplates);
585
586                 result = false;
587                 foreach (AuthenticationMode mode in bindingTemplates.Keys)
588                 {
589                     SecurityBindingElement candidate = bindingTemplates[mode];
590                     if (AreBindingsMatching(sbe, candidate))
591                     {
592                         this.AuthenticationMode = mode;
593                         result = true;
594                         break;
595                     }
596                 }
597             }
598
599             return result;
600         }
601
602         void SetIssuedTokenKeyType(SecurityBindingElement sbe)
603         {
604             // Set the keyType for building the template for IssuedToken binding.
605             // The reason is the different supporting token is defined depending on keyType.
606             if (sbe.EndpointSupportingTokenParameters.Endorsing.Count > 0 &&
607                 sbe.EndpointSupportingTokenParameters.Endorsing[0] is IssuedSecurityTokenParameters)
608             {
609                 this.templateKeyType = ((IssuedSecurityTokenParameters)sbe.EndpointSupportingTokenParameters.Endorsing[0]).KeyType;
610             }
611             else if (sbe.EndpointSupportingTokenParameters.Signed.Count > 0 &&
612                 sbe.EndpointSupportingTokenParameters.Signed[0] is IssuedSecurityTokenParameters)
613             {
614                 this.templateKeyType = ((IssuedSecurityTokenParameters)sbe.EndpointSupportingTokenParameters.Signed[0]).KeyType;
615             }
616             else if (sbe.EndpointSupportingTokenParameters.SignedEncrypted.Count > 0 &&
617                 sbe.EndpointSupportingTokenParameters.SignedEncrypted[0] is IssuedSecurityTokenParameters)
618             {
619                 this.templateKeyType = ((IssuedSecurityTokenParameters)sbe.EndpointSupportingTokenParameters.SignedEncrypted[0]).KeyType;
620             }
621             else
622             {
623                 this.templateKeyType = IssuedSecurityTokenParameters.defaultKeyType;
624             }
625         }
626
627         protected virtual void InitializeNestedTokenParameterSettings(SecurityTokenParameters sp, bool initializeNestedBindings)
628         {
629             if (sp is SspiSecurityTokenParameters)
630                 SetPropertyValueIfNotDefaultValue(ConfigurationStrings.RequireSecurityContextCancellation, ((SspiSecurityTokenParameters)sp).RequireCancellation);
631             else if (sp is SslSecurityTokenParameters)
632                 SetPropertyValueIfNotDefaultValue(ConfigurationStrings.RequireSecurityContextCancellation, ((SslSecurityTokenParameters)sp).RequireCancellation);
633             else if (sp is IssuedSecurityTokenParameters)
634                 this.IssuedTokenParameters.InitializeFrom((IssuedSecurityTokenParameters)sp, initializeNestedBindings);
635         }
636
637         internal void InitializeFrom(BindingElement bindingElement, bool initializeNestedBindings)
638         {
639             if (bindingElement == null)
640             {
641                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("bindingElement");
642             }
643             SecurityBindingElement sbe = (SecurityBindingElement)bindingElement;
644
645             // Can't apply default value optimization to properties like DefaultAlgorithmSuite because the defaults are computed at runtime and don't match config defaults
646             this.DefaultAlgorithmSuite = sbe.DefaultAlgorithmSuite;
647             this.IncludeTimestamp = sbe.IncludeTimestamp;
648             if (sbe.MessageSecurityVersion != MessageSecurityVersion.Default)
649             {
650                 this.MessageSecurityVersion = sbe.MessageSecurityVersion;
651             }            
652             // Still safe to apply the optimization here because the runtime defaults are the same as config defaults in all cases
653             SetPropertyValueIfNotDefaultValue(ConfigurationStrings.KeyEntropyMode, sbe.KeyEntropyMode);
654             SetPropertyValueIfNotDefaultValue(ConfigurationStrings.SecurityHeaderLayout, sbe.SecurityHeaderLayout);
655             SetPropertyValueIfNotDefaultValue(ConfigurationStrings.ProtectTokens, sbe.ProtectTokens);
656             SetPropertyValueIfNotDefaultValue(ConfigurationStrings.AllowInsecureTransport, sbe.AllowInsecureTransport);
657             SetPropertyValueIfNotDefaultValue(ConfigurationStrings.EnableUnsecuredResponse, sbe.EnableUnsecuredResponse);
658
659
660             Nullable<bool> requireDerivedKeys = new Nullable<bool>();
661
662             if (sbe.EndpointSupportingTokenParameters.Endorsing.Count == 1)
663             {
664                 this.InitializeNestedTokenParameterSettings(sbe.EndpointSupportingTokenParameters.Endorsing[0], initializeNestedBindings);
665             }
666             else if (sbe.EndpointSupportingTokenParameters.SignedEncrypted.Count == 1)
667             {
668                 this.InitializeNestedTokenParameterSettings(sbe.EndpointSupportingTokenParameters.SignedEncrypted[0], initializeNestedBindings);
669             }
670             else if (sbe.EndpointSupportingTokenParameters.Signed.Count == 1)
671             {
672                 this.InitializeNestedTokenParameterSettings(sbe.EndpointSupportingTokenParameters.Signed[0], initializeNestedBindings);
673             }
674
675             bool initializationFailure = false;
676
677             foreach (SecurityTokenParameters t in sbe.EndpointSupportingTokenParameters.Endorsing)
678             {
679                 if (t.HasAsymmetricKey == false)
680                 {
681                     if (requireDerivedKeys.HasValue && requireDerivedKeys.Value != t.RequireDerivedKeys)
682                         initializationFailure = true;
683                     else
684                         requireDerivedKeys = t.RequireDerivedKeys;
685                 }                
686             }
687
688             SymmetricSecurityBindingElement ssbe = sbe as SymmetricSecurityBindingElement;
689             if ( ssbe != null )
690             {
691                 SetPropertyValueIfNotDefaultValue(ConfigurationStrings.MessageProtectionOrder, ssbe.MessageProtectionOrder);
692                 this.RequireSignatureConfirmation = ssbe.RequireSignatureConfirmation;
693                 if ( ssbe.ProtectionTokenParameters != null )
694                 {
695                     this.InitializeNestedTokenParameterSettings( ssbe.ProtectionTokenParameters, initializeNestedBindings );
696                     if ( requireDerivedKeys.HasValue && requireDerivedKeys.Value != ssbe.ProtectionTokenParameters.RequireDerivedKeys )
697                         initializationFailure = true;
698                     else
699                         requireDerivedKeys = ssbe.ProtectionTokenParameters.RequireDerivedKeys;
700
701                 }
702             }
703             else
704             {
705                 AsymmetricSecurityBindingElement asbe = sbe as AsymmetricSecurityBindingElement;
706                 if ( asbe != null )
707                 {
708                     SetPropertyValueIfNotDefaultValue(ConfigurationStrings.MessageProtectionOrder, asbe.MessageProtectionOrder);
709                     this.RequireSignatureConfirmation = asbe.RequireSignatureConfirmation;
710                     if ( asbe.InitiatorTokenParameters != null )
711                     {
712                         this.InitializeNestedTokenParameterSettings( asbe.InitiatorTokenParameters, initializeNestedBindings );
713
714                         //
715                         // Copy the derived key token bool flag from the token parameters. The token parameter was set from
716                         // importing WSDL during SecurityBindingElementImporter.ImportPolicy time
717                         //
718                         if ( requireDerivedKeys.HasValue && requireDerivedKeys.Value != asbe.InitiatorTokenParameters.RequireDerivedKeys )
719                             initializationFailure = true;
720                         else
721                             requireDerivedKeys = asbe.InitiatorTokenParameters.RequireDerivedKeys;
722                     }
723                 }
724             }
725
726             this.willX509IssuerReferenceAssertionBeWritten = DoesSecurityBindingElementContainClauseTypeofIssuerSerial(sbe);
727             this.RequireDerivedKeys = requireDerivedKeys.GetValueOrDefault(SecurityTokenParameters.defaultRequireDerivedKeys);
728             this.LocalClientSettings.InitializeFrom(sbe.LocalClientSettings);
729             this.LocalServiceSettings.InitializeFrom(sbe.LocalServiceSettings);
730
731             if (!initializationFailure)
732                 initializationFailure = !this.TryInitializeAuthenticationMode(sbe);
733
734             if (initializationFailure)
735                 this.failedSecurityBindingElement = sbe;
736         }
737
738         protected internal override void InitializeFrom(BindingElement bindingElement)
739         {
740             this.InitializeFrom(bindingElement, true);
741         }
742
743         /// <summary>
744         /// returns true if one of the xxxSupportingTokenParameters.yyy is of type IssuerSerial
745         /// </summary>
746         /// <param name="sbe"></param>
747         /// <returns></returns>
748         bool DoesSecurityBindingElementContainClauseTypeofIssuerSerial( SecurityBindingElement sbe )
749         {
750             if ( sbe == null )
751                 return false;
752             
753             if ( sbe is SymmetricSecurityBindingElement )
754             {
755                 X509SecurityTokenParameters tokenParamameters = ( (SymmetricSecurityBindingElement)sbe ).ProtectionTokenParameters as X509SecurityTokenParameters;
756                 if ( tokenParamameters != null && tokenParamameters.X509ReferenceStyle == X509KeyIdentifierClauseType.IssuerSerial )
757                     return true;
758             }
759             else if ( sbe is AsymmetricSecurityBindingElement )
760             {
761                 X509SecurityTokenParameters initiatorParamameters = ( (AsymmetricSecurityBindingElement)sbe ).InitiatorTokenParameters as X509SecurityTokenParameters;
762                 if ( initiatorParamameters != null && initiatorParamameters.X509ReferenceStyle == X509KeyIdentifierClauseType.IssuerSerial )
763                     return true;
764
765                 X509SecurityTokenParameters recepientParamameters = ( (AsymmetricSecurityBindingElement)sbe ).RecipientTokenParameters as X509SecurityTokenParameters;
766                 if ( recepientParamameters != null && recepientParamameters.X509ReferenceStyle == X509KeyIdentifierClauseType.IssuerSerial )
767                     return true;
768             }
769
770             if ( DoesX509TokenParametersContainClauseTypeofIssuerSerial( sbe.EndpointSupportingTokenParameters.Endorsing ) )
771                 return true;
772
773             if ( DoesX509TokenParametersContainClauseTypeofIssuerSerial( sbe.EndpointSupportingTokenParameters.Signed ) )
774                 return true;
775
776             if ( DoesX509TokenParametersContainClauseTypeofIssuerSerial( sbe.EndpointSupportingTokenParameters.SignedEncrypted ) )
777                 return true;
778
779             if ( DoesX509TokenParametersContainClauseTypeofIssuerSerial( sbe.EndpointSupportingTokenParameters.SignedEndorsing ) )
780                 return true;
781
782             if ( DoesX509TokenParametersContainClauseTypeofIssuerSerial( sbe.OptionalEndpointSupportingTokenParameters.Endorsing ) )
783                 return true;
784
785             if ( DoesX509TokenParametersContainClauseTypeofIssuerSerial( sbe.OptionalEndpointSupportingTokenParameters.Signed ) )
786                 return true;
787
788             if ( DoesX509TokenParametersContainClauseTypeofIssuerSerial( sbe.OptionalEndpointSupportingTokenParameters.SignedEncrypted ) )
789                 return true;
790
791             if ( DoesX509TokenParametersContainClauseTypeofIssuerSerial( sbe.OptionalEndpointSupportingTokenParameters.SignedEndorsing ) )
792                 return true;
793
794             return false;
795         }
796
797         bool DoesX509TokenParametersContainClauseTypeofIssuerSerial( Collection<SecurityTokenParameters> tokenParameters )
798         {
799             foreach ( SecurityTokenParameters tokenParameter in tokenParameters )
800             {
801                 X509SecurityTokenParameters x509TokenParameter = tokenParameter as X509SecurityTokenParameters;
802                 if ( x509TokenParameter != null )
803                 {
804                     if ( x509TokenParameter.X509ReferenceStyle == X509KeyIdentifierClauseType.IssuerSerial )
805                         return true;
806                 }
807             }
808
809             return false;
810         }
811
812         protected override bool SerializeToXmlElement(XmlWriter writer, String elementName)
813         {
814             bool result;
815
816             if (this.failedSecurityBindingElement != null && writer != null)
817             {
818                 writer.WriteComment(SR.GetString(SR.ConfigurationSchemaInsuffientForSecurityBindingElementInstance));
819                 writer.WriteComment(this.failedSecurityBindingElement.ToString());
820                 result = true;
821             }
822             else
823             {
824                 if ( writer != null && this.willX509IssuerReferenceAssertionBeWritten )
825                     writer.WriteComment( SR.GetString(SR.ConfigurationSchemaContainsX509IssuerSerialReference));
826
827                 result = base.SerializeToXmlElement(writer, elementName);
828             }
829
830             return result;
831         }
832                 
833         protected override bool SerializeElement(XmlWriter writer, bool serializeCollectionKey)
834         {
835             bool nontrivial = base.SerializeElement(writer, serializeCollectionKey);
836
837             // A SecurityElement can copy properties from a "bootstrap" SecurityBaseElement.
838             // In this case, a trivial bootstrap (no properties set) is equivalent to not having one at all so we can omit it.
839             Func<PropertyInformation, bool> nontrivialProperty = property => property.ValueOrigin == PropertyValueOrigin.SetHere;
840             if (this.IsSecurityElementBootstrap && !this.ElementInformation.Properties.OfType<PropertyInformation>().Any(nontrivialProperty))
841             {
842                 nontrivial = false;
843             }
844             return nontrivial;
845         }
846         
847
848         protected override void Unmerge(ConfigurationElement sourceElement, ConfigurationElement parentElement, ConfigurationSaveMode saveMode)
849         {
850             if ( sourceElement is SecurityElementBase )
851             {
852                 this.failedSecurityBindingElement = ( (SecurityElementBase)sourceElement ).failedSecurityBindingElement;
853                 this.willX509IssuerReferenceAssertionBeWritten = ( (SecurityElementBase)sourceElement ).willX509IssuerReferenceAssertionBeWritten;
854             }
855
856             base.Unmerge(sourceElement, parentElement, saveMode);
857         }
858     }
859 }
860
861
862