Merge pull request #3389 from lambdageek/bug-43099
[mono.git] / mcs / class / referencesource / System.ServiceModel / System / ServiceModel / Security / WSSecurityPolicy.cs
1 //-----------------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //-----------------------------------------------------------------------------
4
5 namespace System.ServiceModel.Security
6 {
7     using System.Collections.Generic;
8     using System.Collections.ObjectModel;
9     using System.IO;
10     using System.Runtime;
11     using System.ServiceModel;
12     using System.ServiceModel.Channels;
13     using System.ServiceModel.Description;
14     using System.ServiceModel.Security.Tokens;
15     using System.Xml;
16
17     abstract class WSSecurityPolicy
18     {
19         public static ContractDescription NullContract = new ContractDescription("null");
20         public static ServiceEndpoint NullServiceEndpoint = new ServiceEndpoint(NullContract);
21         public static XmlDocument doc = new XmlDocument();
22         public const string WsspPrefix = "sp";
23         public const string WspNamespace = MetadataStrings.WSPolicy.NamespaceUri; //@"http://schemas.xmlsoap.org/ws/2004/09/policy";
24         public const string Wsp15Namespace = MetadataStrings.WSPolicy.NamespaceUri15;
25         public const string WspPrefix = MetadataStrings.WSPolicy.Prefix; //"wsp";
26         public const string MsspNamespace = @"http://schemas.microsoft.com/ws/2005/07/securitypolicy";
27         public const string MsspPrefix = "mssp";
28         public const string PolicyName = MetadataStrings.WSPolicy.Elements.Policy; //"Policy";
29         public const string OptionalName = "Optional";
30         public const string TrueName = "true";
31         public const string FalseName = "false";
32         public const string SymmetricBindingName = "SymmetricBinding";
33         public const string AsymmetricBindingName = "AsymmetricBinding";
34         public const string TransportBindingName = "TransportBinding";
35         public const string OnlySignEntireHeadersAndBodyName = "OnlySignEntireHeadersAndBody";
36         public const string ProtectionTokenName = "ProtectionToken";
37         public const string InitiatorTokenName = "InitiatorToken";
38         public const string RecipientTokenName = "RecipientToken";
39         public const string TransportTokenName = "TransportToken";
40         public const string AlgorithmSuiteName = "AlgorithmSuite";
41         public const string LaxName = "Lax";
42         public const string LaxTsLastName = "LaxTsLast";
43         public const string LaxTsFirstName = "LaxTsFirst";
44         public const string StrictName = "Strict";
45         public const string IncludeTimestampName = "IncludeTimestamp";
46         public const string EncryptBeforeSigningName = "EncryptBeforeSigning";
47         public const string ProtectTokens = "ProtectTokens";
48         public const string EncryptSignatureName = "EncryptSignature";
49         public const string SignedSupportingTokensName = "SignedSupportingTokens";
50         public const string EndorsingSupportingTokensName = "EndorsingSupportingTokens";
51         public const string SignedEndorsingSupportingTokensName = "SignedEndorsingSupportingTokens";
52         public const string Wss10Name = "Wss10";
53         public const string MustSupportRefKeyIdentifierName = "MustSupportRefKeyIdentifier";
54         public const string MustSupportRefIssuerSerialName = "MustSupportRefIssuerSerial";
55         public const string MustSupportRefThumbprintName = "MustSupportRefThumbprint";
56         public const string MustSupportRefEncryptedKeyName = "MustSupportRefEncryptedKey";
57         public const string RequireSignatureConfirmationName = "RequireSignatureConfirmation";
58         public const string MustSupportIssuedTokensName = "MustSupportIssuedTokens";
59         public const string RequireClientEntropyName = "RequireClientEntropy";
60         public const string RequireServerEntropyName = "RequireServerEntropy";
61         public const string Wss11Name = "Wss11";
62         public const string Trust10Name = "Trust10";
63         public const string Trust13Name = "Trust13";
64         public const string RequireAppliesTo = "RequireAppliesTo";
65         public const string SignedPartsName = "SignedParts";
66         public const string EncryptedPartsName = "EncryptedParts";
67         public const string BodyName = "Body";
68         public const string HeaderName = "Header";
69         public const string NameName = "Name";
70         public const string NamespaceName = "Namespace";
71         public const string Basic128Name = "Basic128";
72         public const string Basic192Name = "Basic192";
73         public const string Basic256Name = "Basic256";
74         public const string TripleDesName = "TripleDes";
75         public const string Basic128Rsa15Name = "Basic128Rsa15";
76         public const string Basic192Rsa15Name = "Basic192Rsa15";
77         public const string Basic256Rsa15Name = "Basic256Rsa15";
78         public const string TripleDesRsa15Name = "TripleDesRsa15";
79         public const string Basic128Sha256Name = "Basic128Sha256";
80         public const string Basic192Sha256Name = "Basic192Sha256";
81         public const string Basic256Sha256Name = "Basic256Sha256";
82         public const string TripleDesSha256Name = "TripleDesSha256";
83         public const string Basic128Sha256Rsa15Name = "Basic128Sha256Rsa15";
84         public const string Basic192Sha256Rsa15Name = "Basic192Sha256Rsa15";
85         public const string Basic256Sha256Rsa15Name = "Basic256Sha256Rsa15";
86         public const string TripleDesSha256Rsa15Name = "TripleDesSha256Rsa15";
87         public const string IncludeTokenName = "IncludeToken";
88         public const string KerberosTokenName = "KerberosToken";
89         public const string X509TokenName = "X509Token";
90         public const string IssuedTokenName = "IssuedToken";
91         public const string UsernameTokenName = "UsernameToken";
92         public const string RsaTokenName = "RsaToken";
93         public const string KeyValueTokenName = "KeyValueToken";
94         public const string SpnegoContextTokenName = "SpnegoContextToken";
95         public const string SslContextTokenName = "SslContextToken";
96         public const string SecureConversationTokenName = "SecureConversationToken";
97         public const string WssGssKerberosV5ApReqToken11Name = "WssGssKerberosV5ApReqToken11";
98         public const string RequireDerivedKeysName = "RequireDerivedKeys";
99         public const string RequireIssuerSerialReferenceName = "RequireIssuerSerialReference";
100         public const string RequireKeyIdentifierReferenceName = "RequireKeyIdentifierReference";
101         public const string RequireThumbprintReferenceName = "RequireThumbprintReference";
102         public const string WssX509V3Token10Name = "WssX509V3Token10";
103         public const string WssUsernameToken10Name = "WssUsernameToken10";
104         public const string RequestSecurityTokenTemplateName = "RequestSecurityTokenTemplate";
105         public const string RequireExternalReferenceName = "RequireExternalReference";
106         public const string RequireInternalReferenceName = "RequireInternalReference";
107         public const string IssuerName = "Issuer";
108         public const string RequireClientCertificateName = "RequireClientCertificate";
109         public const string MustNotSendCancelName = "MustNotSendCancel";
110         public const string MustNotSendAmendName = "MustNotSendAmend";
111         public const string MustNotSendRenewName = "MustNotSendRenew";
112         public const string LayoutName = "Layout";
113         public const string BootstrapPolicyName = "BootstrapPolicy";
114         public const string HttpsTokenName = "HttpsToken";
115         public const string HttpBasicAuthenticationName = "HttpBasicAuthentication";
116         public const string HttpDigestAuthenticationName = "HttpDigestAuthentication";
117
118         bool _mustSupportRefKeyIdentifierName = false;
119         bool _mustSupportRefIssuerSerialName = false;
120         bool _mustSupportRefThumbprintName = false;
121         bool _protectionTokenHasAsymmetricKey = false;
122
123         public virtual XmlElement CreateWsspAssertion(string name)
124         {
125             return doc.CreateElement(WsspPrefix, name, this.WsspNamespaceUri);
126         }
127
128         public virtual bool IsWsspAssertion(XmlElement assertion)
129         {
130             return assertion.NamespaceURI == this.WsspNamespaceUri;
131         }
132
133         public virtual bool IsWsspAssertion(XmlElement assertion, string name)
134         {
135             return assertion.NamespaceURI == this.WsspNamespaceUri && assertion.LocalName == name;
136         }
137
138         public virtual bool IsMsspAssertion(XmlElement assertion, string name)
139         {
140             return assertion.NamespaceURI == MsspNamespace && assertion.LocalName == name;
141         }
142
143         public virtual bool TryImportWsspAssertion(ICollection<XmlElement> assertions, string name, out XmlElement assertion)
144         {
145             assertion = null;
146
147             foreach (XmlElement e in assertions)
148             {
149                 if (e.LocalName == name && e.NamespaceURI == this.WsspNamespaceUri)
150                 {
151                     assertion = e;
152                     assertions.Remove(e);
153                     return true;
154                 }
155             }
156
157             return false;
158         }
159
160         public virtual bool TryImportWsspAssertion(ICollection<XmlElement> assertions, string name)
161         {
162             return TryImportWsspAssertion(assertions, name, false);
163         }
164
165         public virtual bool TryImportWsspAssertion(ICollection<XmlElement> assertions, string name, bool isOptional)
166         {
167             foreach (XmlElement e in assertions)
168             {
169                 if (e.LocalName == name && e.NamespaceURI == this.WsspNamespaceUri)
170                 {
171                     assertions.Remove(e);
172                     return true;
173                 }
174             }
175
176             return isOptional;
177         }
178
179         public virtual XmlElement CreateMsspAssertion(string name)
180         {
181             return doc.CreateElement(MsspPrefix, name, MsspNamespace);
182         }
183
184         public virtual bool CanImportAssertion(ICollection<XmlElement> assertions)
185         {
186             foreach (XmlElement e in assertions)
187             {
188                 if (e.NamespaceURI == this.WsspNamespaceUri || e.NamespaceURI == WSSecurityPolicy.MsspNamespace)
189                 {
190                     return true;
191                 }
192             }
193
194             return false;
195         }
196
197         public abstract bool IsSecurityVersionSupported(MessageSecurityVersion version);
198
199         public abstract MessageSecurityVersion GetSupportedMessageSecurityVersion(SecurityVersion version);
200
201         public abstract string WsspNamespaceUri { get; }
202
203         public abstract TrustDriver TrustDriver { get; }
204
205         public virtual string AlwaysToRecipientUri
206         {
207             get { return this.WsspNamespaceUri + @"/IncludeToken/AlwaysToRecipient"; }
208         }
209
210         public virtual string NeverUri
211         {
212             get { return this.WsspNamespaceUri + @"/IncludeToken/Never"; }
213         }
214
215         public virtual string OnceUri
216         {
217             get { return this.WsspNamespaceUri + @"/IncludeToken/Once"; }
218         }
219
220         public virtual string AlwaysToInitiatorUri
221         {
222             get { return this.WsspNamespaceUri + @"/IncludeToken/AlwaysToInitiator"; }
223         }
224
225         public virtual bool TryImportMsspAssertion(ICollection<XmlElement> assertions, string name)
226         {
227             foreach (XmlElement e in assertions)
228             {
229                 if (e.LocalName == name && e.NamespaceURI == MsspNamespace)
230                 {
231                     assertions.Remove(e);
232                     return true;
233                 }
234             }
235
236             return false;
237         }
238
239         public virtual XmlElement CreateWspPolicyWrapper(MetadataExporter exporter, params XmlElement[] nestedAssertions)
240         {
241             XmlElement result = doc.CreateElement(WspPrefix, PolicyName, exporter.PolicyVersion.Namespace);
242
243             if (nestedAssertions != null)
244             {
245                 foreach (XmlElement e in nestedAssertions)
246                 {
247                     if (e != null)
248                     {
249                         result.AppendChild(e);
250                     }
251                 }
252             }
253
254             return result;
255         }
256
257         public virtual XmlElement CreateWsspSignedPartsAssertion(MessagePartSpecification parts)
258         {
259             if (parts == null)
260             {
261                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parts");
262             }
263
264             XmlElement result;
265
266             if (parts.IsEmpty())
267             {
268                 result = null;
269             }
270             else
271             {
272                 result = CreateWsspAssertion(SignedPartsName);
273                 if (parts.IsBodyIncluded)
274                 {
275                     result.AppendChild(CreateWsspAssertion(BodyName));
276                 }
277                 foreach (XmlQualifiedName header in parts.HeaderTypes)
278                 {
279                     result.AppendChild(CreateWsspHeaderAssertion(header));
280                 }
281             }
282             return result;
283         }
284
285         public virtual XmlElement CreateWsspEncryptedPartsAssertion(MessagePartSpecification parts)
286         {
287             if (parts == null)
288             {
289                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parts");
290             }
291
292             XmlElement result;
293
294             if (parts.IsEmpty())
295             {
296                 result = null;
297             }
298             else
299             {
300                 result = CreateWsspAssertion(EncryptedPartsName);
301                 if (parts.IsBodyIncluded)
302                 {
303                     result.AppendChild(CreateWsspAssertion(BodyName));
304                 }
305                 foreach (XmlQualifiedName header in parts.HeaderTypes)
306                 {
307                     result.AppendChild(CreateWsspHeaderAssertion(header));
308                 }
309             }
310             return result;
311         }
312
313         public virtual MessagePartSpecification TryGetProtectedParts(XmlElement assertion)
314         {
315             MessagePartSpecification parts = new MessagePartSpecification();
316
317             foreach (XmlNode node in assertion.ChildNodes)
318             {
319                 if (node.NodeType == XmlNodeType.Whitespace || node.NodeType == XmlNodeType.Comment)
320                 {
321                     continue;
322                 }
323                 else if (node is XmlElement)
324                 {
325                     XmlElement element = (XmlElement)node;
326                     if (IsWsspAssertion(element, BodyName))
327                     {
328                         parts.IsBodyIncluded = true;
329                     }
330                     else if (IsWsspAssertion(element, HeaderName))
331                     {
332                         string name = element.GetAttribute(NameName);
333                         string ns = element.GetAttribute(NamespaceName);
334
335                         if (ns == null)
336                         {
337                             parts = null;
338                             break;
339                         }
340
341                         parts.HeaderTypes.Add(new XmlQualifiedName(name, ns));
342                     }
343                     else
344                     {
345                         parts = null;
346                         break;
347                     }
348                 }
349                 else
350                 {
351                     parts = null;
352                     break;
353                 }
354             }
355
356             return parts;
357         }
358
359         public virtual bool TryImportWsspEncryptedPartsAssertion(ICollection<XmlElement> assertions, out MessagePartSpecification parts, out XmlElement assertion)
360         {
361             if (TryImportWsspAssertion(assertions, EncryptedPartsName, out assertion))
362             {
363                 parts = TryGetProtectedParts(assertion);
364             }
365             else
366             {
367                 parts = null;
368             }
369
370             return parts != null;
371         }
372
373         public virtual bool TryImportWsspSignedPartsAssertion(ICollection<XmlElement> assertions, out MessagePartSpecification parts, out XmlElement assertion)
374         {
375             if (TryImportWsspAssertion(assertions, SignedPartsName, out assertion))
376             {
377                 parts = TryGetProtectedParts(assertion);
378             }
379             else
380             {
381                 parts = null;
382             }
383
384             return parts != null;
385         }
386
387         public virtual XmlElement CreateWsspHeaderAssertion(XmlQualifiedName header)
388         {
389             XmlElement result = CreateWsspAssertion(HeaderName);
390             result.SetAttribute(NameName, header.Name);
391             result.SetAttribute(NamespaceName, header.Namespace);
392
393             return result;
394         }
395
396         public virtual XmlElement CreateWsspSymmetricBindingAssertion(MetadataExporter exporter, PolicyConversionContext policyContext, SymmetricSecurityBindingElement binding)
397         {
398             if (binding == null)
399             {
400                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("binding");
401             }
402
403             XmlElement result = CreateWsspAssertion(SymmetricBindingName);
404             result.AppendChild(
405                 CreateWspPolicyWrapper(
406                     exporter,
407                     CreateWsspProtectionTokenAssertion(exporter, binding.ProtectionTokenParameters),
408                     CreateWsspAlgorithmSuiteAssertion(exporter, binding.DefaultAlgorithmSuite),
409                     CreateWsspLayoutAssertion(exporter, binding.SecurityHeaderLayout),
410                     CreateWsspIncludeTimestampAssertion(binding.IncludeTimestamp),
411                     CreateWsspEncryptBeforeSigningAssertion(binding.MessageProtectionOrder),
412                     CreateWsspEncryptSignatureAssertion(policyContext, binding),
413                     CreateWsspProtectTokensAssertion(binding),
414                     CreateWsspAssertion(OnlySignEntireHeadersAndBodyName)
415             ));
416
417             return result;
418         }
419
420         public virtual bool TryGetNestedPolicyAlternatives(MetadataImporter importer, XmlElement assertion, out Collection<Collection<XmlElement>> alternatives)
421         {
422             alternatives = null;
423
424             XmlElement policyElement = null;
425             foreach (XmlNode node in assertion.ChildNodes)
426             {
427                 if (node is XmlElement && node.LocalName == PolicyName && (node.NamespaceURI == WspNamespace || node.NamespaceURI == Wsp15Namespace))
428                 {
429                     policyElement = (XmlElement)node;
430                     break;
431                 }
432             }
433
434             if (policyElement == null)
435             {
436                 alternatives = null;
437             }
438             else
439             {
440                 IEnumerable<IEnumerable<XmlElement>> enumerableAlternatives = importer.NormalizePolicy(new XmlElement[] { policyElement });
441
442                 alternatives = new Collection<Collection<XmlElement>>();
443                 foreach (IEnumerable<XmlElement> enumerableAlternative in enumerableAlternatives)
444                 {
445                     Collection<XmlElement> alternative = new Collection<XmlElement>();
446                     alternatives.Add(alternative);
447                     foreach (XmlElement e in enumerableAlternative)
448                     {
449                         alternative.Add(e);
450                     }
451                 }
452             }
453
454             return alternatives != null;
455         }
456
457         public virtual bool TryImportWsspSymmetricBindingAssertion(MetadataImporter importer, PolicyConversionContext policyContext, ICollection<XmlElement> assertions, out SymmetricSecurityBindingElement binding, out XmlElement assertion)
458         {
459             binding = null;
460
461             Collection<Collection<XmlElement>> alternatives;
462
463             if (TryImportWsspAssertion(assertions, SymmetricBindingName, out assertion)
464                 && TryGetNestedPolicyAlternatives(importer, assertion, out alternatives))
465             {
466                 foreach (Collection<XmlElement> alternative in alternatives)
467                 {
468                     MessageProtectionOrder order;
469                     bool protectTokens;
470                     binding = new SymmetricSecurityBindingElement();
471                     if (TryImportWsspProtectionTokenAssertion(importer, policyContext, alternative, binding)
472                         && TryImportWsspAlgorithmSuiteAssertion(importer, alternative, binding)
473                         && TryImportWsspLayoutAssertion(importer, alternative, binding)
474                         && TryImportWsspIncludeTimestampAssertion(alternative, binding)
475                         && TryImportMessageProtectionOrderAssertions(alternative, out order)
476                         && TryImportWsspProtectTokensAssertion(alternative, out protectTokens)
477                         && TryImportWsspAssertion(alternative, OnlySignEntireHeadersAndBodyName, true)
478                         && alternative.Count == 0)
479                     {
480                         binding.MessageProtectionOrder = order;
481                         binding.ProtectTokens = protectTokens;
482                         break;
483                     }
484                     else
485                     {
486                         binding = null;
487                     }
488                 }
489             }
490
491             return binding != null;
492         }
493
494         public virtual XmlElement CreateWsspAsymmetricBindingAssertion(MetadataExporter exporter, PolicyConversionContext policyContext, AsymmetricSecurityBindingElement binding)
495         {
496             if (binding == null)
497             {
498                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("binding");
499             }
500
501             XmlElement result = CreateWsspAssertion(AsymmetricBindingName);
502             result.AppendChild(
503                 CreateWspPolicyWrapper(
504                     exporter,
505                     CreateWsspInitiatorTokenAssertion(exporter, binding.InitiatorTokenParameters),
506                     CreateWsspRecipientTokenAssertion(exporter, binding.RecipientTokenParameters),
507                     CreateWsspAlgorithmSuiteAssertion(exporter, binding.DefaultAlgorithmSuite),
508                     CreateWsspLayoutAssertion(exporter, binding.SecurityHeaderLayout),
509                     CreateWsspIncludeTimestampAssertion(binding.IncludeTimestamp),
510                     CreateWsspEncryptBeforeSigningAssertion(binding.MessageProtectionOrder),
511                     CreateWsspEncryptSignatureAssertion(policyContext, binding),
512                     CreateWsspProtectTokensAssertion(binding),
513                     CreateWsspAssertion(OnlySignEntireHeadersAndBodyName)
514             ));
515
516             return result;
517         }
518
519         public virtual bool TryImportWsspAsymmetricBindingAssertion(MetadataImporter importer, PolicyConversionContext policyContext, ICollection<XmlElement> assertions, out AsymmetricSecurityBindingElement binding, out XmlElement assertion)
520         {
521             binding = null;
522
523             Collection<Collection<XmlElement>> alternatives;
524
525             if (TryImportWsspAssertion(assertions, AsymmetricBindingName, out assertion)
526                 && TryGetNestedPolicyAlternatives(importer, assertion, out alternatives))
527             {
528                 foreach (Collection<XmlElement> alternative in alternatives)
529                 {
530                     MessageProtectionOrder order;
531                     bool protectTokens;
532                     binding = new AsymmetricSecurityBindingElement();
533                     if (TryImportWsspInitiatorTokenAssertion(importer, policyContext, alternative, binding)
534                         && TryImportWsspRecipientTokenAssertion(importer, policyContext, alternative, binding)
535                         && TryImportWsspAlgorithmSuiteAssertion(importer, alternative, binding)
536                         && TryImportWsspLayoutAssertion(importer, alternative, binding)
537                         && TryImportWsspIncludeTimestampAssertion(alternative, binding)
538                         && TryImportMessageProtectionOrderAssertions(alternative, out order)
539                         && TryImportWsspProtectTokensAssertion(alternative, out protectTokens)
540                         && TryImportWsspAssertion(alternative, OnlySignEntireHeadersAndBodyName, true)
541                         && alternative.Count == 0)
542                     {
543                         binding.MessageProtectionOrder = order;
544                         binding.ProtectTokens = protectTokens;
545                         break;
546                     }
547                     else
548                     {
549                         binding = null;
550                     }
551                 }
552             }
553
554             return binding != null;
555         }
556
557         public virtual XmlElement CreateWsspTransportBindingAssertion(MetadataExporter exporter, TransportSecurityBindingElement binding, XmlElement transportTokenAssertion)
558         {
559             XmlElement result = CreateWsspAssertion(TransportBindingName);
560             result.AppendChild(
561                 CreateWspPolicyWrapper(
562                     exporter,
563                     CreateWsspTransportTokenAssertion(exporter, transportTokenAssertion),
564                     CreateWsspAlgorithmSuiteAssertion(exporter, binding.DefaultAlgorithmSuite),
565                     CreateWsspLayoutAssertion(exporter, binding.SecurityHeaderLayout),
566                     CreateWsspIncludeTimestampAssertion(binding.IncludeTimestamp)
567             ));
568
569             return result;
570         }
571
572         public virtual bool TryImportWsspTransportBindingAssertion(MetadataImporter importer, ICollection<XmlElement> assertions, out TransportSecurityBindingElement binding, out XmlElement assertion)
573         {
574             binding = null;
575
576             Collection<Collection<XmlElement>> alternatives;
577
578             if (TryImportWsspAssertion(assertions, TransportBindingName, out assertion)
579                 && TryGetNestedPolicyAlternatives(importer, assertion, out alternatives))
580             {
581                 foreach (Collection<XmlElement> alternative in alternatives)
582                 {
583                     XmlElement transportTokenAssertion;
584                     binding = new TransportSecurityBindingElement();
585                     if (TryImportWsspTransportTokenAssertion(importer, alternative, out transportTokenAssertion)
586                         && TryImportWsspAlgorithmSuiteAssertion(importer, alternative, binding)
587                         && TryImportWsspLayoutAssertion(importer, alternative, binding)
588                         && TryImportWsspIncludeTimestampAssertion(alternative, binding)
589                         && alternative.Count == 0)
590                     {
591                         if (false == importer.State.ContainsKey(SecurityBindingElementImporter.InSecureConversationBootstrapBindingImportMode))
592                         {
593                             // The transportTokenAssertion should be consumed by the transport binding importer
594                             // for all primary bindings. However, for secure conversation bootstrap bindings
595                             // the bootstrap policy does not contain any transport assertions, so adding the
596                             // transport token assertion to the collection of unimported assertions would
597                             // increase the likelihood of policy import failure due to unrecognized assertions. 
598                             assertions.Add(transportTokenAssertion);
599                         }
600                         break;
601                     }
602                     else
603                     {
604                         binding = null;
605                     }
606                 }
607             }
608
609             return binding != null;
610         }
611
612         public virtual XmlElement CreateWsspWssAssertion(MetadataExporter exporter, SecurityBindingElement binding)
613         {
614             if (binding == null)
615             {
616                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("binding");
617             }
618
619             if (binding.MessageSecurityVersion.SecurityVersion == SecurityVersion.WSSecurity10)
620             {
621                 return CreateWsspWss10Assertion(exporter);
622             }
623             else if (binding.MessageSecurityVersion.SecurityVersion == SecurityVersion.WSSecurity11)
624             {
625                 if (binding is SymmetricSecurityBindingElement)
626                 {
627                     return CreateWsspWss11Assertion(exporter, ((SymmetricSecurityBindingElement)binding).RequireSignatureConfirmation);
628                 }
629                 else if (binding is AsymmetricSecurityBindingElement)
630                 {
631                     return CreateWsspWss11Assertion(exporter, ((AsymmetricSecurityBindingElement)binding).RequireSignatureConfirmation);
632                 }
633                 else
634                 {
635                     return CreateWsspWss11Assertion(exporter, false);
636                 }
637             }
638             else
639             {
640                 return null;
641             }
642         }
643
644         public virtual bool TryImportWsspWssAssertion(MetadataImporter importer, ICollection<XmlElement> assertions, SecurityBindingElement binding, out XmlElement assertion)
645         {
646             if (binding == null)
647             {
648                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("binding");
649             }
650             if (assertions == null)
651             {
652                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("assertions");
653             }
654
655             bool result = true;
656             Collection<Collection<XmlElement>> alternatives;
657
658             if (TryImportWsspAssertion(assertions, Wss10Name, out assertion))
659             {
660                 if (TryGetNestedPolicyAlternatives(importer, assertion, out alternatives))
661                 {
662                     foreach (Collection<XmlElement> alternative in alternatives)
663                     {
664                         TryImportWsspAssertion(alternative, MustSupportRefKeyIdentifierName);
665                         TryImportWsspAssertion(alternative, MustSupportRefIssuerSerialName);
666                         if (alternative.Count == 0)
667                         {
668                             binding.MessageSecurityVersion = this.GetSupportedMessageSecurityVersion(SecurityVersion.WSSecurity10);
669                             result = true;
670                             break;
671                         }
672                         else
673                         {
674                             result = false;
675                         }
676                     }
677                 }
678             }
679             else if (TryImportWsspAssertion(assertions, Wss11Name, out assertion))
680             {
681                 if (TryGetNestedPolicyAlternatives(importer, assertion, out alternatives))
682                 {
683                     foreach (Collection<XmlElement> alternative in alternatives)
684                     {
685                         TryImportWsspAssertion(alternative, MustSupportRefKeyIdentifierName);
686                         TryImportWsspAssertion(alternative, MustSupportRefIssuerSerialName);
687                         TryImportWsspAssertion(alternative, MustSupportRefThumbprintName);
688                         TryImportWsspAssertion(alternative, MustSupportRefEncryptedKeyName);
689                         bool requireSignatureConfirmation = TryImportWsspAssertion(alternative, RequireSignatureConfirmationName);
690                         if (alternative.Count == 0)
691                         {
692                             binding.MessageSecurityVersion = this.GetSupportedMessageSecurityVersion(SecurityVersion.WSSecurity11);
693                             if (binding is SymmetricSecurityBindingElement)
694                             {
695                                 ((SymmetricSecurityBindingElement)binding).RequireSignatureConfirmation = requireSignatureConfirmation;
696                             }
697                             else if (binding is AsymmetricSecurityBindingElement)
698                             {
699                                 ((AsymmetricSecurityBindingElement)binding).RequireSignatureConfirmation = requireSignatureConfirmation;
700                             }
701                             result = true;
702                             break;
703                         }
704                         else
705                         {
706                             result = false;
707                         }
708                     }
709                 }
710             }
711
712             return result;
713         }
714
715         public virtual XmlElement CreateWsspWss10Assertion(MetadataExporter exporter)
716         {
717             XmlElement result = CreateWsspAssertion(Wss10Name);
718             result.AppendChild(
719                 CreateWspPolicyWrapper(
720                     exporter,
721                     CreateWsspAssertionMustSupportRefKeyIdentifierName(),
722                     CreateWsspAssertionMustSupportRefIssuerSerialName()
723             ));
724
725             return result;
726         }
727
728         public virtual XmlElement CreateWsspWss11Assertion(MetadataExporter exporter, bool requireSignatureConfirmation)
729         {
730             XmlElement result = CreateWsspAssertion(Wss11Name);
731             result.AppendChild(
732                 CreateWspPolicyWrapper(
733                     exporter,
734                     CreateWsspAssertionMustSupportRefKeyIdentifierName(),
735                     CreateWsspAssertionMustSupportRefIssuerSerialName(),
736                     CreateWsspAssertionMustSupportRefThumbprintName(),
737                     CreateWsspAssertionMustSupportRefEncryptedKeyName(),
738                     CreateWsspRequireSignatureConformationAssertion(requireSignatureConfirmation)
739             ));
740
741             return result;
742         }
743         public virtual XmlElement CreateWsspAssertionMustSupportRefKeyIdentifierName()
744         {
745             if (_mustSupportRefKeyIdentifierName)
746             {
747                 return CreateWsspAssertion(MustSupportRefKeyIdentifierName);
748             }
749             else
750             {
751                 return null;
752             }
753         }
754
755         public virtual XmlElement CreateWsspAssertionMustSupportRefIssuerSerialName()
756         {
757             if (_mustSupportRefIssuerSerialName)
758             {
759                 return CreateWsspAssertion(MustSupportRefIssuerSerialName);
760             }
761             else
762             {
763                 return null;
764             }
765         }
766
767         public virtual XmlElement CreateWsspAssertionMustSupportRefThumbprintName()
768         {
769             if (_mustSupportRefThumbprintName)
770             {
771                 return CreateWsspAssertion(MustSupportRefThumbprintName);
772             }
773             else
774             {
775                 return null;
776             }
777         }
778
779         public virtual XmlElement CreateWsspAssertionMustSupportRefEncryptedKeyName()
780         {
781             // protectionTokenHasAsymmetricKey is only set to true for a SymmetricBindingElement having an asymmetric key
782             if (_protectionTokenHasAsymmetricKey)
783             {
784                 return CreateWsspAssertion(MustSupportRefEncryptedKeyName);
785             }
786             else
787             {
788                 return null;
789             }
790         }
791
792         public virtual XmlElement CreateWsspRequireSignatureConformationAssertion(bool requireSignatureConfirmation)
793         {
794             if (requireSignatureConfirmation)
795             {
796                 return CreateWsspAssertion(RequireSignatureConfirmationName);
797             }
798             else
799             {
800                 return null;
801             }
802         }
803
804         public abstract XmlElement CreateWsspTrustAssertion(MetadataExporter exporter, SecurityKeyEntropyMode keyEntropyMode);
805
806         public abstract bool TryImportWsspTrustAssertion(MetadataImporter importer, ICollection<XmlElement> assertions, SecurityBindingElement binding, out XmlElement assertion);
807
808         protected XmlElement CreateWsspTrustAssertion(string trustName, MetadataExporter exporter, SecurityKeyEntropyMode keyEntropyMode)
809         {
810             XmlElement result = CreateWsspAssertion(trustName);
811             result.AppendChild(
812                 CreateWspPolicyWrapper(
813                     exporter,
814                     CreateWsspAssertion(MustSupportIssuedTokensName),
815                     CreateWsspRequireClientEntropyAssertion(keyEntropyMode),
816                     CreateWsspRequireServerEntropyAssertion(keyEntropyMode)
817             ));
818
819             return result;
820         }
821
822         protected bool TryImportWsspTrustAssertion(string trustName, MetadataImporter importer, ICollection<XmlElement> assertions, SecurityBindingElement binding, out XmlElement assertion)
823         {
824             if (binding == null)
825             {
826                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("binding");
827             }
828             if (assertions == null)
829             {
830                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("assertions");
831             }
832
833             bool result = true;
834             Collection<Collection<XmlElement>> alternatives;
835
836             if (TryImportWsspAssertion(assertions, trustName, out assertion)
837                 && TryGetNestedPolicyAlternatives(importer, assertion, out alternatives))
838             {
839                 foreach (Collection<XmlElement> alternative in alternatives)
840                 {
841                     TryImportWsspAssertion(alternative, MustSupportIssuedTokensName);
842                     bool requireClientEntropy = TryImportWsspAssertion(alternative, RequireClientEntropyName);
843                     bool requireServerEntropy = TryImportWsspAssertion(alternative, RequireServerEntropyName);
844                     if (trustName == Trust13Name)
845                     {
846                         // We are just reading this optional element.
847                         TryImportWsspAssertion(alternative, RequireAppliesTo);
848                     }
849                     if (alternative.Count == 0)
850                     {
851                         if (requireClientEntropy)
852                         {
853                             if (requireServerEntropy)
854                             {
855                                 binding.KeyEntropyMode = SecurityKeyEntropyMode.CombinedEntropy;
856                             }
857                             else
858                             {
859                                 binding.KeyEntropyMode = SecurityKeyEntropyMode.ClientEntropy;
860                             }
861                         }
862                         else if (requireServerEntropy)
863                         {
864                             binding.KeyEntropyMode = SecurityKeyEntropyMode.ServerEntropy;
865                         }
866
867                         result = true;
868                         break;
869                     }
870                     else
871                     {
872                         result = false;
873                     }
874                 }
875             }
876
877             return result;
878         }
879
880         public virtual XmlElement CreateWsspRequireClientEntropyAssertion(SecurityKeyEntropyMode keyEntropyMode)
881         {
882             if (keyEntropyMode == SecurityKeyEntropyMode.ClientEntropy || keyEntropyMode == SecurityKeyEntropyMode.CombinedEntropy)
883             {
884                 return CreateWsspAssertion(RequireClientEntropyName);
885             }
886             else
887             {
888                 return null;
889             }
890         }
891
892         public virtual XmlElement CreateWsspRequireServerEntropyAssertion(SecurityKeyEntropyMode keyEntropyMode)
893         {
894             if (keyEntropyMode == SecurityKeyEntropyMode.ServerEntropy || keyEntropyMode == SecurityKeyEntropyMode.CombinedEntropy)
895             {
896                 return CreateWsspAssertion(RequireServerEntropyName);
897             }
898             else
899             {
900                 return null;
901             }
902         }
903
904         public virtual Collection<XmlElement> CreateWsspSupportingTokensAssertion(MetadataExporter exporter, Collection<SecurityTokenParameters> signed, Collection<SecurityTokenParameters> signedEncrypted, Collection<SecurityTokenParameters> endorsing, Collection<SecurityTokenParameters> signedEndorsing, Collection<SecurityTokenParameters> optionalSigned, Collection<SecurityTokenParameters> optionalSignedEncrypted, Collection<SecurityTokenParameters> optionalEndorsing, Collection<SecurityTokenParameters> optionalSignedEndorsing)
905         {
906             return CreateWsspSupportingTokensAssertion(exporter, signed, signedEncrypted, endorsing, signedEndorsing, optionalSigned, optionalSignedEncrypted, optionalEndorsing, optionalSignedEndorsing, null);
907         }
908
909         public virtual Collection<XmlElement> CreateWsspSupportingTokensAssertion(MetadataExporter exporter, Collection<SecurityTokenParameters> signed, Collection<SecurityTokenParameters> signedEncrypted, Collection<SecurityTokenParameters> endorsing, Collection<SecurityTokenParameters> signedEndorsing, Collection<SecurityTokenParameters> optionalSigned, Collection<SecurityTokenParameters> optionalSignedEncrypted, Collection<SecurityTokenParameters> optionalEndorsing, Collection<SecurityTokenParameters> optionalSignedEndorsing, AddressingVersion addressingVersion)
910         {
911             Collection<XmlElement> supportingTokenAssertions = new Collection<XmlElement>();
912
913             // Signed Supporting Tokens
914             XmlElement supportingTokenAssertion = CreateWsspSignedSupportingTokensAssertion(exporter, signed, signedEncrypted, optionalSigned, optionalSignedEncrypted);
915             if (supportingTokenAssertion != null)
916                 supportingTokenAssertions.Add(supportingTokenAssertion);
917
918             // Endorsing Supporting Tokens.
919             supportingTokenAssertion = CreateWsspEndorsingSupportingTokensAssertion(exporter, endorsing, optionalEndorsing, addressingVersion);
920             if (supportingTokenAssertion != null)
921                 supportingTokenAssertions.Add(supportingTokenAssertion);
922
923             // Signed Endorsing Supporting Tokens.
924             supportingTokenAssertion = CreateWsspSignedEndorsingSupportingTokensAssertion(exporter, signedEndorsing, optionalSignedEndorsing, addressingVersion);
925             if (supportingTokenAssertion != null)
926                 supportingTokenAssertions.Add(supportingTokenAssertion);
927
928             return supportingTokenAssertions;
929         }
930
931         protected XmlElement CreateWsspSignedSupportingTokensAssertion(MetadataExporter exporter, Collection<SecurityTokenParameters> signed, Collection<SecurityTokenParameters> signedEncrypted, Collection<SecurityTokenParameters> optionalSigned, Collection<SecurityTokenParameters> optionalSignedEncrypted)
932         {
933             XmlElement result;
934
935             if ((signed == null || signed.Count == 0)
936                 && (signedEncrypted == null || signedEncrypted.Count == 0)
937                 && (optionalSigned == null || optionalSigned.Count == 0)
938                 && (optionalSignedEncrypted == null || optionalSignedEncrypted.Count == 0))
939             {
940                 result = null;
941             }
942             else
943             {
944                 XmlElement policy = CreateWspPolicyWrapper(exporter);
945
946                 if (signed != null)
947                 {
948                     foreach (SecurityTokenParameters p in signed)
949                     {
950                         policy.AppendChild(CreateTokenAssertion(exporter, p));
951                     }
952                 }
953                 if (signedEncrypted != null)
954                 {
955                     foreach (SecurityTokenParameters p in signedEncrypted)
956                     {
957                         policy.AppendChild(CreateTokenAssertion(exporter, p));
958                     }
959                 }
960                 if (optionalSigned != null)
961                 {
962                     foreach (SecurityTokenParameters p in optionalSigned)
963                     {
964                         policy.AppendChild(CreateTokenAssertion(exporter, p, true));
965                     }
966                 }
967                 if (optionalSignedEncrypted != null)
968                 {
969                     foreach (SecurityTokenParameters p in optionalSignedEncrypted)
970                     {
971                         policy.AppendChild(CreateTokenAssertion(exporter, p, true));
972                     }
973                 }
974
975                 result = CreateWsspAssertion(SignedSupportingTokensName);
976                 result.AppendChild(policy);
977             }
978
979             return result;
980         }
981
982         protected XmlElement CreateWsspEndorsingSupportingTokensAssertion(MetadataExporter exporter, Collection<SecurityTokenParameters> endorsing, Collection<SecurityTokenParameters> optionalEndorsing, AddressingVersion addressingVersion)
983         {
984             return CreateWsspiSupportingTokensAssertion(exporter, endorsing, optionalEndorsing, addressingVersion, EndorsingSupportingTokensName);
985         }
986
987         protected XmlElement CreateWsspSignedEndorsingSupportingTokensAssertion(MetadataExporter exporter, Collection<SecurityTokenParameters> signedEndorsing, Collection<SecurityTokenParameters> optionalSignedEndorsing, AddressingVersion addressingVersion)
988         {
989             return CreateWsspiSupportingTokensAssertion(exporter, signedEndorsing, optionalSignedEndorsing, addressingVersion, SignedEndorsingSupportingTokensName);
990         }
991
992         protected XmlElement CreateWsspiSupportingTokensAssertion(MetadataExporter exporter, Collection<SecurityTokenParameters> endorsing, Collection<SecurityTokenParameters> optionalEndorsing, AddressingVersion addressingVersion, string assertionName)
993         {
994             XmlElement result;
995             bool hasAssymetricKey = false;
996
997             if ((endorsing == null || endorsing.Count == 0)
998                 && (optionalEndorsing == null || optionalEndorsing.Count == 0))
999             {
1000                 result = null;
1001             }
1002             else
1003             {
1004                 XmlElement policy = CreateWspPolicyWrapper(exporter);
1005
1006                 if (endorsing != null)
1007                 {
1008                     foreach (SecurityTokenParameters p in endorsing)
1009                     {
1010                         if (p.HasAsymmetricKey)
1011                             hasAssymetricKey = true;
1012
1013                         policy.AppendChild(CreateTokenAssertion(exporter, p));
1014                     }
1015                 }
1016                 if (optionalEndorsing != null)
1017                 {
1018                     foreach (SecurityTokenParameters p in optionalEndorsing)
1019                     {
1020                         if (p.HasAsymmetricKey)
1021                             hasAssymetricKey = true;
1022
1023                         policy.AppendChild(CreateTokenAssertion(exporter, p, true));
1024                     }
1025                 }
1026                 if (addressingVersion != null && AddressingVersion.None != addressingVersion)
1027                 {
1028                     // only add assertion to sign the 'To' only if an assymetric key is found
1029                     if (hasAssymetricKey)
1030                     {
1031                         policy.AppendChild(
1032                             CreateWsspSignedPartsAssertion(
1033                                 new MessagePartSpecification(new XmlQualifiedName(AddressingStrings.To, addressingVersion.Namespace))));
1034                     }
1035                 }
1036
1037                 result = CreateWsspAssertion(assertionName);
1038                 result.AppendChild(policy);
1039             }
1040
1041             return result;
1042         }
1043
1044         public virtual bool TryImportWsspSupportingTokensAssertion(MetadataImporter importer, PolicyConversionContext policyContext, ICollection<XmlElement> assertions, Collection<SecurityTokenParameters> signed, Collection<SecurityTokenParameters> signedEncrypted, Collection<SecurityTokenParameters> endorsing, Collection<SecurityTokenParameters> signedEndorsing, Collection<SecurityTokenParameters> optionalSigned, Collection<SecurityTokenParameters> optionalSignedEncrypted, Collection<SecurityTokenParameters> optionalEndorsing, Collection<SecurityTokenParameters> optionalSignedEndorsing)
1045         {
1046             XmlElement assertion;
1047
1048             if (!TryImportWsspSignedSupportingTokensAssertion(
1049                 importer,
1050                 policyContext,
1051                 assertions,
1052                 signed,
1053                 signedEncrypted,
1054                 optionalSigned,
1055                 optionalSignedEncrypted,
1056                 out assertion)
1057                 && assertion != null)
1058             {
1059                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.UnsupportedSecurityPolicyAssertion, assertion.OuterXml)));
1060             }
1061
1062             if (!TryImportWsspEndorsingSupportingTokensAssertion(
1063                 importer,
1064                 policyContext,
1065                 assertions,
1066                 endorsing,
1067                 optionalEndorsing,
1068                 out assertion)
1069                 && assertion != null)
1070             {
1071                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.UnsupportedSecurityPolicyAssertion, assertion.OuterXml)));
1072             }
1073
1074             if (!TryImportWsspSignedEndorsingSupportingTokensAssertion(
1075                 importer,
1076                 policyContext,
1077                 assertions,
1078                 signedEndorsing,
1079                 optionalSignedEndorsing,
1080                 out assertion)
1081                 && assertion != null)
1082             {
1083                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.UnsupportedSecurityPolicyAssertion, assertion.OuterXml)));
1084             }
1085
1086             return true;
1087         }
1088
1089         protected bool TryImportWsspSignedSupportingTokensAssertion(MetadataImporter importer, PolicyConversionContext policyContext, ICollection<XmlElement> assertions, Collection<SecurityTokenParameters> signed, Collection<SecurityTokenParameters> signedEncrypted, Collection<SecurityTokenParameters> optionalSigned, Collection<SecurityTokenParameters> optionalSignedEncrypted, out XmlElement assertion)
1090         {
1091             if (signed == null)
1092             {
1093                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("signed");
1094             }
1095             if (signedEncrypted == null)
1096             {
1097                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("signedEncrypted");
1098             }
1099             if (optionalSigned == null)
1100             {
1101                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("optionalSigned");
1102             }
1103             if (optionalSignedEncrypted == null)
1104             {
1105                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("optionalSignedEncrypted");
1106             }
1107
1108             bool result = true;
1109
1110             Collection<Collection<XmlElement>> alternatives;
1111
1112             if (TryImportWsspAssertion(assertions, SignedSupportingTokensName, out assertion)
1113                 && TryGetNestedPolicyAlternatives(importer, assertion, out alternatives))
1114             {
1115                 foreach (Collection<XmlElement> alternative in alternatives)
1116                 {
1117                     Collection<SecurityTokenParameters> signedSupportingTokens = new Collection<SecurityTokenParameters>();
1118                     Collection<SecurityTokenParameters> optionalSignedSupportingTokens = new Collection<SecurityTokenParameters>();
1119                     SecurityTokenParameters parameters;
1120                     bool isOptional;
1121                     while (alternative.Count > 0 && TryImportTokenAssertion(importer, policyContext, alternative, out parameters, out isOptional))
1122                     {
1123                         if (isOptional)
1124                         {
1125                             optionalSignedSupportingTokens.Add(parameters);
1126                         }
1127                         else
1128                         {
1129                             signedSupportingTokens.Add(parameters);
1130                         }
1131                     }
1132                     if (alternative.Count == 0)
1133                     {
1134                         foreach (SecurityTokenParameters p in signedSupportingTokens)
1135                         {
1136                             if (p is UserNameSecurityTokenParameters)
1137                             {
1138                                 signedEncrypted.Add(p);
1139                             }
1140                             else
1141                             {
1142                                 signed.Add(p);
1143                             }
1144                         }
1145                         foreach (SecurityTokenParameters p in optionalSignedSupportingTokens)
1146                         {
1147                             if (p is UserNameSecurityTokenParameters)
1148                             {
1149                                 optionalSignedEncrypted.Add(p);
1150                             }
1151                             else
1152                             {
1153                                 optionalSigned.Add(p);
1154                             }
1155                         }
1156                         result = true;
1157                         break;
1158                     }
1159                     else
1160                     {
1161                         result = false;
1162                     }
1163                 }
1164             }
1165
1166             return result;
1167         }
1168
1169         protected bool TryImportWsspEndorsingSupportingTokensAssertion(MetadataImporter importer, PolicyConversionContext policyContext, ICollection<XmlElement> assertions, Collection<SecurityTokenParameters> endorsing, Collection<SecurityTokenParameters> optionalEndorsing, out XmlElement assertion)
1170         {
1171             if (endorsing == null)
1172             {
1173                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endorsing");
1174             }
1175             if (optionalEndorsing == null)
1176             {
1177                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("optionalEndorsing");
1178             }
1179
1180             bool result = true;
1181
1182             Collection<Collection<XmlElement>> alternatives;
1183
1184             if (TryImportWsspAssertion(assertions, EndorsingSupportingTokensName, out assertion)
1185                 && TryGetNestedPolicyAlternatives(importer, assertion, out alternatives))
1186             {
1187                 foreach (Collection<XmlElement> alternative in alternatives)
1188                 {
1189                     MessagePartSpecification signedParts;
1190                     if (!TryImportWsspSignedPartsAssertion(alternative, out signedParts, out assertion) && assertion != null)
1191                     {
1192                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.UnsupportedSecurityPolicyAssertion, assertion.OuterXml)));
1193                     }
1194
1195                     Collection<SecurityTokenParameters> supportingTokens = new Collection<SecurityTokenParameters>();
1196                     Collection<SecurityTokenParameters> optionalSupportingTokens = new Collection<SecurityTokenParameters>();
1197                     SecurityTokenParameters parameters;
1198                     bool isOptional;
1199                     while (alternative.Count > 0 && TryImportTokenAssertion(importer, policyContext, alternative, out parameters, out isOptional))
1200                     {
1201                         if (isOptional)
1202                         {
1203                             optionalSupportingTokens.Add(parameters);
1204                         }
1205                         else
1206                         {
1207                             supportingTokens.Add(parameters);
1208                         }
1209                     }
1210                     if (alternative.Count == 0)
1211                     {
1212                         foreach (SecurityTokenParameters p in supportingTokens)
1213                         {
1214                             endorsing.Add(p);
1215                         }
1216                         foreach (SecurityTokenParameters p in optionalSupportingTokens)
1217                         {
1218                             optionalEndorsing.Add(p);
1219                         }
1220                         result = true;
1221                         break;
1222                     }
1223                     else
1224                     {
1225                         result = false;
1226                     }
1227                 }
1228             }
1229
1230             return result;
1231         }
1232
1233         protected bool TryImportWsspSignedEndorsingSupportingTokensAssertion(MetadataImporter importer, PolicyConversionContext policyContext, ICollection<XmlElement> assertions, Collection<SecurityTokenParameters> signedEndorsing, Collection<SecurityTokenParameters> optionalSignedEndorsing, out XmlElement assertion)
1234         {
1235             if (signedEndorsing == null)
1236             {
1237                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("signedEndorsing");
1238             }
1239             if (optionalSignedEndorsing == null)
1240             {
1241                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("optionalSignedEndorsing");
1242             }
1243
1244             bool result = true;
1245
1246             Collection<Collection<XmlElement>> alternatives;
1247
1248             if (TryImportWsspAssertion(assertions, SignedEndorsingSupportingTokensName, out assertion)
1249                 && TryGetNestedPolicyAlternatives(importer, assertion, out alternatives))
1250             {
1251                 foreach (Collection<XmlElement> alternative in alternatives)
1252                 {
1253                     MessagePartSpecification signedParts;
1254                     if (!TryImportWsspSignedPartsAssertion(alternative, out signedParts, out assertion) && assertion != null)
1255                     {
1256                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.UnsupportedSecurityPolicyAssertion, assertion.OuterXml)));
1257                     }
1258
1259                     Collection<SecurityTokenParameters> supportingTokens = new Collection<SecurityTokenParameters>();
1260                     Collection<SecurityTokenParameters> optionalSupportingTokens = new Collection<SecurityTokenParameters>();
1261                     SecurityTokenParameters parameters;
1262                     bool isOptional;
1263                     while (alternative.Count > 0 && TryImportTokenAssertion(importer, policyContext, alternative, out parameters, out isOptional))
1264                     {
1265                         if (isOptional)
1266                         {
1267                             optionalSupportingTokens.Add(parameters);
1268                         }
1269                         else
1270                         {
1271                             supportingTokens.Add(parameters);
1272                         }
1273                     }
1274                     if (alternative.Count == 0)
1275                     {
1276                         foreach (SecurityTokenParameters p in supportingTokens)
1277                         {
1278                             signedEndorsing.Add(p);
1279                         }
1280                         foreach (SecurityTokenParameters p in optionalSupportingTokens)
1281                         {
1282                             optionalSignedEndorsing.Add(p);
1283                         }
1284                         result = true;
1285                         break;
1286                     }
1287                     else
1288                     {
1289                         result = false;
1290                     }
1291                 }
1292             }
1293
1294             return result;
1295         }
1296
1297         public virtual XmlElement CreateWsspEncryptSignatureAssertion(PolicyConversionContext policyContext, SecurityBindingElement binding)
1298         {
1299             MessageProtectionOrder protectionOrder;
1300             if (binding is SymmetricSecurityBindingElement)
1301             {
1302                 protectionOrder = ((SymmetricSecurityBindingElement)binding).MessageProtectionOrder;
1303             }
1304             else
1305             {
1306                 protectionOrder = ((AsymmetricSecurityBindingElement)binding).MessageProtectionOrder;
1307             }
1308
1309             if (protectionOrder == MessageProtectionOrder.SignBeforeEncryptAndEncryptSignature 
1310                 && ContainsEncryptionParts(policyContext, binding))
1311             {
1312                 return CreateWsspAssertion(EncryptSignatureName);
1313             }
1314             else
1315             {
1316                 return null;
1317             }
1318         }
1319
1320         // This api checks whether or not the message will or may contain Encrypted parts
1321         // to decide whether or not to emit sp:EncryptSignature on Binding assertion.
1322         // 1) (Optional)EndpointSupporting.
1323         // 2) (Optional)OperationSupporting.
1324         // 3) In/Out/Fault Message ProtectionLevel for each Operation.
1325         bool ContainsEncryptionParts(PolicyConversionContext policyContext, SecurityBindingElement security)
1326         {
1327             // special case for RST/RSTR since we hard coded the security for them
1328             if (policyContext.Contract == NullContract)
1329                 return true;
1330
1331             if (security.EndpointSupportingTokenParameters.SignedEncrypted.Count > 0 ||
1332                 security.OptionalEndpointSupportingTokenParameters.SignedEncrypted.Count > 0)
1333             {
1334                 return true;
1335             }
1336             foreach (SupportingTokenParameters r in security.OperationSupportingTokenParameters.Values)
1337             {
1338                 if (r.SignedEncrypted.Count > 0)
1339                 {
1340                     return true;
1341                 }
1342             }
1343             foreach (SupportingTokenParameters r in security.OptionalOperationSupportingTokenParameters.Values)
1344             {
1345                 if (r.SignedEncrypted.Count > 0)
1346                 {
1347                     return true;
1348                 }
1349             }
1350
1351             BindingParameterCollection bindingParameters = new BindingParameterCollection();
1352             bindingParameters.Add(ChannelProtectionRequirements.CreateFromContract(policyContext.Contract, policyContext.BindingElements.Find<SecurityBindingElement>().GetIndividualProperty<ISecurityCapabilities>(), false));
1353             ChannelProtectionRequirements protectionRequirements = SecurityBindingElement.ComputeProtectionRequirements(security, bindingParameters, policyContext.BindingElements, true);
1354             protectionRequirements.MakeReadOnly();
1355
1356             WSSecurityPolicy sp = WSSecurityPolicy.GetSecurityPolicyDriver(security.MessageSecurityVersion);
1357
1358             foreach (OperationDescription operation in policyContext.Contract.Operations)
1359             {
1360                 // export policy for application messages
1361                 foreach (MessageDescription message in operation.Messages)
1362                 {
1363                     MessagePartSpecification parts;
1364                     ScopedMessagePartSpecification scopedParts;
1365
1366                     // confidentiality
1367                     if (message.Direction == MessageDirection.Input)
1368                     {
1369                         scopedParts = protectionRequirements.IncomingEncryptionParts;
1370                     }
1371                     else
1372                     {
1373                         scopedParts = protectionRequirements.OutgoingEncryptionParts;
1374                     }
1375
1376                     if (scopedParts.TryGetParts(message.Action, out parts))
1377                     {
1378                         if (!parts.IsEmpty())
1379                         {
1380                             return true;
1381                         }
1382                     }
1383                 }
1384
1385                 // export policy for faults
1386                 foreach (FaultDescription fault in operation.Faults)
1387                 {
1388                     MessagePartSpecification parts;
1389
1390                     // confidentiality
1391                     if (protectionRequirements.OutgoingEncryptionParts.TryGetParts(fault.Action, out parts))
1392                     {
1393                         if (!parts.IsEmpty())
1394                         {
1395                             return true;
1396                         }
1397                     }
1398                 }
1399             }
1400             return false;
1401         }
1402
1403         public virtual XmlElement CreateWsspEncryptBeforeSigningAssertion(MessageProtectionOrder protectionOrder)
1404         {
1405             if (protectionOrder == MessageProtectionOrder.EncryptBeforeSign)
1406             {
1407                 return CreateWsspAssertion(EncryptBeforeSigningName);
1408             }
1409             else
1410             {
1411                 return null;
1412             }
1413         }
1414
1415         public virtual XmlElement CreateWsspProtectTokensAssertion(SecurityBindingElement sbe)
1416         {
1417             if (sbe.ProtectTokens)
1418             {
1419                 return CreateWsspAssertion(ProtectTokens);
1420             }
1421             else
1422             {
1423                 return null;
1424             }
1425         }
1426
1427
1428         public virtual bool TryImportMessageProtectionOrderAssertions(ICollection<XmlElement> assertions, out MessageProtectionOrder order)
1429         {
1430             if (TryImportWsspAssertion(assertions, EncryptBeforeSigningName))
1431             {
1432                 order = MessageProtectionOrder.EncryptBeforeSign;
1433             }
1434             else if (TryImportWsspAssertion(assertions, EncryptSignatureName))
1435             {
1436                 order = MessageProtectionOrder.SignBeforeEncryptAndEncryptSignature;
1437             }
1438             else
1439             {
1440                 order = MessageProtectionOrder.SignBeforeEncrypt;
1441             }
1442
1443             return true;
1444         }
1445
1446         public virtual XmlElement CreateWsspIncludeTimestampAssertion(bool includeTimestamp)
1447         {
1448             if (includeTimestamp)
1449             {
1450                 return CreateWsspAssertion(IncludeTimestampName);
1451             }
1452             else
1453             {
1454                 return null;
1455             }
1456         }
1457
1458         public virtual bool TryImportWsspIncludeTimestampAssertion(ICollection<XmlElement> assertions, SecurityBindingElement binding)
1459         {
1460             binding.IncludeTimestamp = TryImportWsspAssertion(assertions, IncludeTimestampName);
1461             return true;
1462         }
1463
1464         public virtual bool TryImportWsspProtectTokensAssertion(ICollection<XmlElement> assertions, out bool protectTokens)
1465         {
1466             if (TryImportWsspAssertion(assertions, ProtectTokens))
1467             {
1468                 protectTokens = true;
1469             }
1470             else
1471             {
1472                 protectTokens = false;
1473             }
1474
1475             return true;
1476         }
1477
1478         public virtual XmlElement CreateWsspLayoutAssertion(MetadataExporter exporter, SecurityHeaderLayout layout)
1479         {
1480             XmlElement result = CreateWsspAssertion(LayoutName);
1481             result.AppendChild(
1482                 CreateWspPolicyWrapper(
1483                     exporter,
1484                     CreateLayoutAssertion(layout)
1485             ));
1486
1487             return result;
1488         }
1489
1490         public virtual bool TryImportWsspLayoutAssertion(MetadataImporter importer, ICollection<XmlElement> assertions, SecurityBindingElement binding)
1491         {
1492             bool result = false;
1493             XmlElement assertion;
1494
1495             if (TryImportWsspAssertion(assertions, LayoutName, out assertion))
1496             {
1497                 SecurityHeaderLayout layout;
1498                 Collection<Collection<XmlElement>> alternatives;
1499
1500                 if (TryGetNestedPolicyAlternatives(importer, assertion, out alternatives))
1501                 {
1502                     foreach (Collection<XmlElement> alternative in alternatives)
1503                     {
1504                         if (TryImportLayoutAssertion(alternative, out layout)
1505                             && alternative.Count == 0)
1506                         {
1507                             binding.SecurityHeaderLayout = layout;
1508                             result = true;
1509                             break;
1510                         }
1511                     }
1512                 }
1513             }
1514             else
1515             {
1516                 binding.SecurityHeaderLayout = SecurityHeaderLayout.Lax;
1517                 result = true;
1518             }
1519
1520             return result;
1521         }
1522
1523         public virtual XmlElement CreateLayoutAssertion(SecurityHeaderLayout layout)
1524         {
1525             switch (layout)
1526             {
1527                 default:
1528                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("layout"));
1529                 case SecurityHeaderLayout.Lax:
1530                     return CreateWsspAssertion(LaxName);
1531                 case SecurityHeaderLayout.LaxTimestampFirst:
1532                     return CreateWsspAssertion(LaxTsFirstName);
1533                 case SecurityHeaderLayout.LaxTimestampLast:
1534                     return CreateWsspAssertion(LaxTsLastName);
1535                 case SecurityHeaderLayout.Strict:
1536                     return CreateWsspAssertion(StrictName);
1537             }
1538         }
1539
1540         public virtual bool TryImportLayoutAssertion(ICollection<XmlElement> assertions, out SecurityHeaderLayout layout)
1541         {
1542             bool result = true;
1543             layout = SecurityHeaderLayout.Lax;
1544
1545             if (TryImportWsspAssertion(assertions, LaxName))
1546             {
1547                 layout = SecurityHeaderLayout.Lax;
1548             }
1549             else if (TryImportWsspAssertion(assertions, LaxTsFirstName))
1550             {
1551                 layout = SecurityHeaderLayout.LaxTimestampFirst;
1552             }
1553             else if (TryImportWsspAssertion(assertions, LaxTsLastName))
1554             {
1555                 layout = SecurityHeaderLayout.LaxTimestampLast;
1556             }
1557             else if (TryImportWsspAssertion(assertions, StrictName))
1558             {
1559                 layout = SecurityHeaderLayout.Strict;
1560             }
1561             else
1562             {
1563                 result = false;
1564             }
1565
1566             return result;
1567         }
1568
1569         public virtual XmlElement CreateWsspAlgorithmSuiteAssertion(MetadataExporter exporter, SecurityAlgorithmSuite suite)
1570         {
1571             XmlElement result = CreateWsspAssertion(AlgorithmSuiteName);
1572             result.AppendChild(
1573                 CreateWspPolicyWrapper(
1574                     exporter,
1575                     CreateAlgorithmSuiteAssertion(suite)
1576             ));
1577
1578             return result;
1579         }
1580
1581         public virtual bool TryImportWsspAlgorithmSuiteAssertion(MetadataImporter importer, ICollection<XmlElement> assertions, SecurityBindingElement binding)
1582         {
1583             SecurityAlgorithmSuite suite = null;
1584             XmlElement assertion;
1585             Collection<Collection<XmlElement>> alternatives;
1586
1587             if (TryImportWsspAssertion(assertions, AlgorithmSuiteName, out assertion)
1588                 && TryGetNestedPolicyAlternatives(importer, assertion, out alternatives))
1589             {
1590                 foreach (Collection<XmlElement> alternative in alternatives)
1591                 {
1592                     if (TryImportAlgorithmSuiteAssertion(alternative, out suite)
1593                         && alternative.Count == 0)
1594                     {
1595                         binding.DefaultAlgorithmSuite = suite;
1596                         break;
1597                     }
1598                     else
1599                     {
1600                         suite = null;
1601                     }
1602                 }
1603             }
1604
1605             return suite != null;
1606         }
1607
1608         public virtual XmlElement CreateAlgorithmSuiteAssertion(SecurityAlgorithmSuite suite)
1609         {
1610             if (suite == null)
1611             {
1612                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("suite");
1613             }
1614
1615             XmlElement result;
1616
1617             if (suite == SecurityAlgorithmSuite.Basic256)
1618                 result = CreateWsspAssertion(Basic256Name);
1619             else if (suite == SecurityAlgorithmSuite.Basic192)
1620                 result = CreateWsspAssertion(Basic192Name);
1621             else if (suite == SecurityAlgorithmSuite.Basic128)
1622                 result = CreateWsspAssertion(Basic128Name);
1623             else if (suite == SecurityAlgorithmSuite.TripleDes)
1624                 result = CreateWsspAssertion(TripleDesName);
1625             else if (suite == SecurityAlgorithmSuite.Basic256Rsa15)
1626                 result = CreateWsspAssertion(Basic256Rsa15Name);
1627             else if (suite == SecurityAlgorithmSuite.Basic192Rsa15)
1628                 result = CreateWsspAssertion(Basic192Rsa15Name);
1629             else if (suite == SecurityAlgorithmSuite.Basic128Rsa15)
1630                 result = CreateWsspAssertion(Basic128Rsa15Name);
1631             else if (suite == SecurityAlgorithmSuite.TripleDesRsa15)
1632                 result = CreateWsspAssertion(TripleDesRsa15Name);
1633             else if (suite == SecurityAlgorithmSuite.Basic256Sha256)
1634                 result = CreateWsspAssertion(Basic256Sha256Name);
1635             else if (suite == SecurityAlgorithmSuite.Basic192Sha256)
1636                 result = CreateWsspAssertion(Basic192Sha256Name);
1637             else if (suite == SecurityAlgorithmSuite.Basic128Sha256)
1638                 result = CreateWsspAssertion(Basic128Sha256Name);
1639             else if (suite == SecurityAlgorithmSuite.TripleDesSha256)
1640                 result = CreateWsspAssertion(TripleDesSha256Name);
1641             else if (suite == SecurityAlgorithmSuite.Basic256Sha256Rsa15)
1642                 result = CreateWsspAssertion(Basic256Sha256Rsa15Name);
1643             else if (suite == SecurityAlgorithmSuite.Basic192Sha256Rsa15)
1644                 result = CreateWsspAssertion(Basic192Sha256Rsa15Name);
1645             else if (suite == SecurityAlgorithmSuite.Basic128Sha256Rsa15)
1646                 result = CreateWsspAssertion(Basic128Sha256Rsa15Name);
1647             else if (suite == SecurityAlgorithmSuite.TripleDesSha256Rsa15)
1648                 result = CreateWsspAssertion(TripleDesSha256Rsa15Name);
1649             else
1650             {
1651                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("suite"));
1652             }
1653
1654             return result;
1655         }
1656
1657         public virtual bool TryImportAlgorithmSuiteAssertion(ICollection<XmlElement> assertions, out SecurityAlgorithmSuite suite)
1658         {
1659             if (TryImportWsspAssertion(assertions, Basic256Name))
1660                 suite = SecurityAlgorithmSuite.Basic256;
1661             else if (TryImportWsspAssertion(assertions, Basic192Name))
1662                 suite = SecurityAlgorithmSuite.Basic192;
1663             else if (TryImportWsspAssertion(assertions, Basic128Name))
1664                 suite = SecurityAlgorithmSuite.Basic128;
1665             else if (TryImportWsspAssertion(assertions, TripleDesName))
1666                 suite = SecurityAlgorithmSuite.TripleDes;
1667             else if (TryImportWsspAssertion(assertions, Basic256Rsa15Name))
1668                 suite = SecurityAlgorithmSuite.Basic256Rsa15;
1669             else if (TryImportWsspAssertion(assertions, Basic192Rsa15Name))
1670                 suite = SecurityAlgorithmSuite.Basic192Rsa15;
1671             else if (TryImportWsspAssertion(assertions, Basic128Rsa15Name))
1672                 suite = SecurityAlgorithmSuite.Basic128Rsa15;
1673             else if (TryImportWsspAssertion(assertions, TripleDesRsa15Name))
1674                 suite = SecurityAlgorithmSuite.TripleDesRsa15;
1675             else if (TryImportWsspAssertion(assertions, Basic256Sha256Name))
1676                 suite = SecurityAlgorithmSuite.Basic256Sha256;
1677             else if (TryImportWsspAssertion(assertions, Basic192Sha256Name))
1678                 suite = SecurityAlgorithmSuite.Basic192Sha256;
1679             else if (TryImportWsspAssertion(assertions, Basic128Sha256Name))
1680                 suite = SecurityAlgorithmSuite.Basic128Sha256;
1681             else if (TryImportWsspAssertion(assertions, TripleDesSha256Name))
1682                 suite = SecurityAlgorithmSuite.TripleDesSha256;
1683             else if (TryImportWsspAssertion(assertions, Basic256Sha256Rsa15Name))
1684                 suite = SecurityAlgorithmSuite.Basic256Sha256Rsa15;
1685             else if (TryImportWsspAssertion(assertions, Basic192Sha256Rsa15Name))
1686                 suite = SecurityAlgorithmSuite.Basic192Sha256Rsa15;
1687             else if (TryImportWsspAssertion(assertions, Basic128Sha256Rsa15Name))
1688                 suite = SecurityAlgorithmSuite.Basic128Sha256Rsa15;
1689             else if (TryImportWsspAssertion(assertions, TripleDesSha256Rsa15Name))
1690                 suite = SecurityAlgorithmSuite.TripleDesSha256Rsa15;
1691             else
1692                 suite = null;
1693
1694             return suite != null;
1695         }
1696
1697         public virtual XmlElement CreateWsspProtectionTokenAssertion(MetadataExporter exporter, SecurityTokenParameters parameters)
1698         {
1699             XmlElement result = CreateWsspAssertion(ProtectionTokenName);
1700
1701             result.AppendChild(
1702                 CreateWspPolicyWrapper(
1703                     exporter,
1704                     CreateTokenAssertion(exporter, parameters)
1705             ));
1706             _protectionTokenHasAsymmetricKey = parameters.HasAsymmetricKey;
1707
1708             return result;
1709         }
1710
1711         public virtual bool TryImportWsspProtectionTokenAssertion(MetadataImporter importer, PolicyConversionContext policyContext, ICollection<XmlElement> assertions, SymmetricSecurityBindingElement binding)
1712         {
1713             bool result = false;
1714
1715             XmlElement assertion;
1716             Collection<Collection<XmlElement>> alternatives;
1717             if (TryImportWsspAssertion(assertions, ProtectionTokenName, out assertion)
1718                 && TryGetNestedPolicyAlternatives(importer, assertion, out alternatives))
1719             {
1720                 foreach (Collection<XmlElement> alternative in alternatives)
1721                 {
1722                     SecurityTokenParameters tokenParameters;
1723                     bool isOptional;
1724                     if (TryImportTokenAssertion(importer, policyContext, alternative, out tokenParameters, out isOptional)
1725                         && alternative.Count == 0)
1726                     {
1727                         result = true;
1728                         binding.ProtectionTokenParameters = tokenParameters;
1729                         break;
1730                     }
1731                 }
1732             }
1733
1734             return result;
1735         }
1736
1737         public virtual bool TryImportWsspInitiatorTokenAssertion(MetadataImporter importer, PolicyConversionContext policyContext, ICollection<XmlElement> assertions, AsymmetricSecurityBindingElement binding)
1738         {
1739             bool result = false;
1740
1741             XmlElement assertion;
1742             Collection<Collection<XmlElement>> alternatives;
1743             if (TryImportWsspAssertion(assertions, InitiatorTokenName, out assertion)
1744                 && TryGetNestedPolicyAlternatives(importer, assertion, out alternatives))
1745             {
1746                 foreach (Collection<XmlElement> alternative in alternatives)
1747                 {
1748                     SecurityTokenParameters tokenParameters;
1749                     bool isOptional;
1750                     if (TryImportTokenAssertion(importer, policyContext, alternative, out tokenParameters, out isOptional)
1751                         && alternative.Count == 0)
1752                     {
1753                         result = true;
1754                         binding.InitiatorTokenParameters = tokenParameters;
1755                         break;
1756                     }
1757                 }
1758             }
1759
1760             return result;
1761         }
1762
1763         public virtual bool TryImportWsspRecipientTokenAssertion(MetadataImporter importer, PolicyConversionContext policyContext, ICollection<XmlElement> assertions, AsymmetricSecurityBindingElement binding)
1764         {
1765             bool result = false;
1766
1767             XmlElement assertion;
1768             Collection<Collection<XmlElement>> alternatives;
1769             if (TryImportWsspAssertion(assertions, RecipientTokenName, out assertion)
1770                 && TryGetNestedPolicyAlternatives(importer, assertion, out alternatives))
1771             {
1772                 foreach (Collection<XmlElement> alternative in alternatives)
1773                 {
1774                     SecurityTokenParameters tokenParameters;
1775                     bool isOptional;
1776                     if (TryImportTokenAssertion(importer, policyContext, alternative, out tokenParameters, out isOptional)
1777                         && alternative.Count == 0)
1778                     {
1779                         result = true;
1780                         binding.RecipientTokenParameters = tokenParameters;
1781                         break;
1782                     }
1783                 }
1784             }
1785
1786             return result;
1787         }
1788
1789         public virtual XmlElement CreateWsspInitiatorTokenAssertion(MetadataExporter exporter, SecurityTokenParameters parameters)
1790         {
1791             XmlElement result = CreateWsspAssertion(InitiatorTokenName);
1792
1793             result.AppendChild(
1794                 CreateWspPolicyWrapper(
1795                     exporter,
1796                     CreateTokenAssertion(exporter, parameters)
1797             ));
1798
1799             return result;
1800         }
1801
1802         public virtual XmlElement CreateWsspRecipientTokenAssertion(MetadataExporter exporter, SecurityTokenParameters parameters)
1803         {
1804             XmlElement result = CreateWsspAssertion(RecipientTokenName);
1805
1806             result.AppendChild(
1807                 CreateWspPolicyWrapper(
1808                     exporter,
1809                     CreateTokenAssertion(exporter, parameters)
1810             ));
1811
1812             return result;
1813         }
1814
1815         public virtual XmlElement CreateWsspTransportTokenAssertion(MetadataExporter exporter, XmlElement transportTokenAssertion)
1816         {
1817             if (transportTokenAssertion == null)
1818             {
1819                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("transportTokenAssertion");
1820             }
1821
1822             XmlElement result = CreateWsspAssertion(TransportTokenName);
1823
1824             result.AppendChild(
1825                 CreateWspPolicyWrapper(
1826                     exporter,
1827                     (XmlElement)(doc.ImportNode(transportTokenAssertion, true))
1828             ));
1829
1830             return result;
1831         }
1832
1833         public virtual bool TryImportWsspTransportTokenAssertion(MetadataImporter importer, ICollection<XmlElement> assertions, out XmlElement transportBindingAssertion)
1834         {
1835             transportBindingAssertion = null;
1836
1837             XmlElement assertion;
1838             Collection<Collection<XmlElement>> alternatives;
1839             if (TryImportWsspAssertion(assertions, TransportTokenName, out assertion)
1840                 && TryGetNestedPolicyAlternatives(importer, assertion, out alternatives)
1841                 && alternatives.Count == 1
1842                 && alternatives[0].Count == 1)
1843             {
1844                 // we cannot process choices of transport tokens due to the current contract between 
1845                 // security and transport binding element converters
1846                 transportBindingAssertion = alternatives[0][0];
1847             }
1848
1849             return transportBindingAssertion != null;
1850         }
1851
1852         public virtual XmlElement CreateTokenAssertion(MetadataExporter exporter, SecurityTokenParameters parameters)
1853         {
1854             return CreateTokenAssertion(exporter, parameters, false);
1855         }
1856
1857         public virtual XmlElement CreateTokenAssertion(MetadataExporter exporter, SecurityTokenParameters parameters, bool isOptional)
1858         {
1859             if (parameters == null)
1860             {
1861                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parameters");
1862             }
1863
1864             XmlElement result;
1865
1866             if (parameters is KerberosSecurityTokenParameters)
1867             {
1868                 result = CreateWsspKerberosTokenAssertion(exporter, (KerberosSecurityTokenParameters)parameters);
1869             }
1870             else if (parameters is X509SecurityTokenParameters)
1871             {
1872                 result = CreateWsspX509TokenAssertion(exporter, (X509SecurityTokenParameters)parameters);
1873             }
1874             else if (parameters is UserNameSecurityTokenParameters)
1875             {
1876                 result = CreateWsspUsernameTokenAssertion(exporter, (UserNameSecurityTokenParameters)parameters);
1877             }
1878             else if (parameters is IssuedSecurityTokenParameters)
1879             {
1880                 result = CreateWsspIssuedTokenAssertion(exporter, (IssuedSecurityTokenParameters)parameters);
1881             }
1882             else if (parameters is SspiSecurityTokenParameters)
1883             {
1884                 result = CreateWsspSpnegoContextTokenAssertion(exporter, (SspiSecurityTokenParameters)parameters);
1885             }
1886             else if (parameters is SslSecurityTokenParameters)
1887             {
1888                 result = CreateMsspSslContextTokenAssertion(exporter, (SslSecurityTokenParameters)parameters);
1889             }
1890             else if (parameters is SecureConversationSecurityTokenParameters)
1891             {
1892                 result = CreateWsspSecureConversationTokenAssertion(exporter, (SecureConversationSecurityTokenParameters)parameters);
1893             }
1894             else if (parameters is RsaSecurityTokenParameters)
1895             {
1896                 result = CreateWsspRsaTokenAssertion((RsaSecurityTokenParameters)parameters);
1897             }
1898             else
1899             {
1900                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("parameters"));
1901             }
1902
1903             if (result != null && isOptional)
1904             {
1905                 result.SetAttribute(OptionalName, exporter.PolicyVersion.Namespace, TrueName);
1906             }
1907
1908             return result;
1909         }
1910
1911         public virtual bool TryImportTokenAssertion(MetadataImporter importer, PolicyConversionContext policyContext, Collection<XmlElement> assertions, out SecurityTokenParameters parameters, out bool isOptional)
1912         {
1913             parameters = null;
1914             isOptional = false;
1915
1916             if (assertions.Count >= 1)
1917             {
1918                 XmlElement tokenAssertion = assertions[0];
1919                 if (TryImportWsspKerberosTokenAssertion(importer, tokenAssertion, out parameters)
1920                     || TryImportWsspX509TokenAssertion(importer, tokenAssertion, out parameters)
1921                     || TryImportWsspUsernameTokenAssertion(importer, tokenAssertion, out parameters)
1922                     || TryImportWsspIssuedTokenAssertion(importer, policyContext, tokenAssertion, out parameters)
1923                     || TryImportWsspSpnegoContextTokenAssertion(importer, tokenAssertion, out parameters)
1924                     || TryImportMsspSslContextTokenAssertion(importer, tokenAssertion, out parameters)
1925                     || TryImportWsspSecureConversationTokenAssertion(importer, tokenAssertion, out parameters)
1926                     || TryImportWsspRsaTokenAssertion(importer, tokenAssertion, out parameters))
1927                 {
1928                     string optionalAttribute = tokenAssertion.GetAttribute(OptionalName, WspNamespace);
1929
1930                     if (String.IsNullOrEmpty(optionalAttribute))
1931                     {
1932                         optionalAttribute = tokenAssertion.GetAttribute(OptionalName, Wsp15Namespace);
1933                     }
1934
1935                     try
1936                     {
1937                         isOptional = XmlUtil.IsTrue(optionalAttribute);
1938                     }
1939                     catch ( Exception e )
1940                     {
1941                         if (Fx.IsFatal(e))
1942                             throw;
1943                         if (e is NullReferenceException)
1944                             throw;
1945
1946                         importer.Errors.Add(new MetadataConversionError(SR.GetString(SR.UnsupportedBooleanAttribute, OptionalName, e.Message), false));
1947                         return false;
1948                     }
1949
1950                     assertions.RemoveAt(0);
1951                 }
1952             }
1953
1954             return (parameters != null);
1955         }
1956         
1957         public virtual void SetIncludeTokenValue(XmlElement tokenAssertion, SecurityTokenInclusionMode inclusionMode)
1958         {
1959             switch (inclusionMode)
1960             {
1961                 default:
1962                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("inclusionMode"));
1963                 case SecurityTokenInclusionMode.AlwaysToInitiator:
1964                     tokenAssertion.SetAttribute(IncludeTokenName, this.WsspNamespaceUri, AlwaysToInitiatorUri);
1965                     break;
1966                 case SecurityTokenInclusionMode.AlwaysToRecipient:
1967                     tokenAssertion.SetAttribute(IncludeTokenName, this.WsspNamespaceUri, AlwaysToRecipientUri);
1968                     break;
1969                 case SecurityTokenInclusionMode.Never:
1970                     tokenAssertion.SetAttribute(IncludeTokenName, this.WsspNamespaceUri, NeverUri);
1971                     break;
1972                 case SecurityTokenInclusionMode.Once:
1973                     tokenAssertion.SetAttribute(IncludeTokenName, this.WsspNamespaceUri, OnceUri);
1974                     break;
1975             }
1976         }
1977
1978         public virtual bool TryGetIncludeTokenValue(XmlElement assertion, out SecurityTokenInclusionMode mode)
1979         {
1980             string includeTokenUri = assertion.GetAttribute(IncludeTokenName, this.WsspNamespaceUri);
1981
1982             if (includeTokenUri == AlwaysToInitiatorUri)
1983             {
1984                 mode = SecurityTokenInclusionMode.AlwaysToInitiator;
1985                 return true;
1986             }
1987             else if (includeTokenUri == AlwaysToRecipientUri)
1988             {
1989                 mode = SecurityTokenInclusionMode.AlwaysToRecipient;
1990                 return true;
1991             }
1992             else if (includeTokenUri == NeverUri)
1993             {
1994                 mode = SecurityTokenInclusionMode.Never;
1995                 return true;
1996             }
1997             else if (includeTokenUri == OnceUri)
1998             {
1999                 mode = SecurityTokenInclusionMode.Once;
2000                 return true;
2001             }
2002             else
2003             {
2004                 mode = SecurityTokenInclusionMode.Never;
2005                 return false;
2006             }
2007         }
2008
2009         public virtual XmlElement CreateWsspRequireDerivedKeysAssertion(bool requireDerivedKeys)
2010         {
2011             if (requireDerivedKeys)
2012             {
2013                 return CreateWsspAssertion(RequireDerivedKeysName);
2014             }
2015             else
2016             {
2017                 return null;
2018             }
2019         }
2020
2021         public virtual bool TryImportWsspRequireDerivedKeysAssertion(ICollection<XmlElement> assertions, SecurityTokenParameters parameters)
2022         {
2023             parameters.RequireDerivedKeys = TryImportWsspAssertion(assertions, RequireDerivedKeysName);
2024             return true;
2025         }
2026
2027         public virtual XmlElement CreateWsspKerberosTokenAssertion(MetadataExporter exporter, KerberosSecurityTokenParameters parameters)
2028         {
2029             XmlElement result = CreateWsspAssertion(KerberosTokenName);
2030             SetIncludeTokenValue(result, parameters.InclusionMode);
2031             result.AppendChild(
2032                 CreateWspPolicyWrapper(
2033                     exporter,
2034                     CreateWsspRequireDerivedKeysAssertion(parameters.RequireDerivedKeys),
2035                     CreateWsspAssertion(WssGssKerberosV5ApReqToken11Name)
2036             ));
2037             return result;
2038         }
2039
2040         public virtual bool TryImportWsspKerberosTokenAssertion(MetadataImporter importer, XmlElement assertion, out SecurityTokenParameters parameters)
2041         {
2042             parameters = null;
2043
2044             SecurityTokenInclusionMode inclusionMode;
2045             Collection<Collection<XmlElement>> alternatives;
2046
2047             if (IsWsspAssertion(assertion, KerberosTokenName)
2048                 && TryGetIncludeTokenValue(assertion, out inclusionMode))
2049             {
2050                 if (TryGetNestedPolicyAlternatives(importer, assertion, out alternatives))
2051                 {
2052                     foreach (Collection<XmlElement> alternative in alternatives)
2053                     {
2054                         parameters = new KerberosSecurityTokenParameters();
2055                         if (TryImportWsspRequireDerivedKeysAssertion(alternative, parameters)
2056                             && TryImportWsspAssertion(alternative, WssGssKerberosV5ApReqToken11Name, true)
2057                             && alternative.Count == 0)
2058                         {
2059                             parameters.InclusionMode = inclusionMode;
2060                             break;
2061                         }
2062                         else
2063                         {
2064                             parameters = null;
2065                         }
2066                     }
2067                 }
2068                 else
2069                 {
2070                     parameters = new KerberosSecurityTokenParameters();
2071                     parameters.RequireDerivedKeys = false;
2072                     parameters.InclusionMode = inclusionMode;
2073                 }
2074             }
2075
2076             return parameters != null;
2077         }
2078
2079         public virtual XmlElement CreateX509ReferenceStyleAssertion(X509KeyIdentifierClauseType referenceStyle)
2080         {
2081             switch (referenceStyle)
2082             {
2083                 default:
2084                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("referenceStyle"));
2085                 case X509KeyIdentifierClauseType.IssuerSerial:
2086                     _mustSupportRefIssuerSerialName = true;
2087                     return CreateWsspAssertion(RequireIssuerSerialReferenceName);
2088                 case X509KeyIdentifierClauseType.SubjectKeyIdentifier:
2089                     _mustSupportRefKeyIdentifierName = true;
2090                     return CreateWsspAssertion(RequireKeyIdentifierReferenceName);
2091                 case X509KeyIdentifierClauseType.Thumbprint:
2092                     _mustSupportRefThumbprintName = true;
2093                     return CreateWsspAssertion(RequireThumbprintReferenceName);
2094                 case X509KeyIdentifierClauseType.Any:
2095                     _mustSupportRefIssuerSerialName = true;
2096                     _mustSupportRefKeyIdentifierName = true;
2097                     _mustSupportRefThumbprintName = true;
2098                     return null;
2099             }
2100         }
2101
2102         public virtual bool TryImportX509ReferenceStyleAssertion(ICollection<XmlElement> assertions, X509SecurityTokenParameters parameters)
2103         {
2104             if (TryImportWsspAssertion(assertions, RequireIssuerSerialReferenceName))
2105             {
2106                 parameters.X509ReferenceStyle = X509KeyIdentifierClauseType.IssuerSerial;
2107             }
2108             else if (TryImportWsspAssertion(assertions, RequireKeyIdentifierReferenceName))
2109             {
2110                 parameters.X509ReferenceStyle = X509KeyIdentifierClauseType.SubjectKeyIdentifier;
2111             }
2112             else if (TryImportWsspAssertion(assertions, RequireThumbprintReferenceName))
2113             {
2114                 parameters.X509ReferenceStyle = X509KeyIdentifierClauseType.Thumbprint;
2115             }
2116
2117             return true;
2118         }
2119
2120         public virtual XmlElement CreateWsspX509TokenAssertion(MetadataExporter exporter, X509SecurityTokenParameters parameters)
2121         {
2122             XmlElement result = CreateWsspAssertion(X509TokenName);
2123             SetIncludeTokenValue(result, parameters.InclusionMode);
2124             result.AppendChild(
2125                 CreateWspPolicyWrapper(
2126                     exporter,
2127                     CreateWsspRequireDerivedKeysAssertion(parameters.RequireDerivedKeys),
2128                     CreateX509ReferenceStyleAssertion(parameters.X509ReferenceStyle),
2129                     CreateWsspAssertion(WssX509V3Token10Name)
2130             ));
2131             return result;
2132         }
2133
2134         public virtual bool TryImportWsspX509TokenAssertion(MetadataImporter importer, XmlElement assertion, out SecurityTokenParameters parameters)
2135         {
2136             parameters = null;
2137
2138             SecurityTokenInclusionMode inclusionMode;
2139             Collection<Collection<XmlElement>> alternatives;
2140
2141             if (IsWsspAssertion(assertion, X509TokenName)
2142                 && TryGetIncludeTokenValue(assertion, out inclusionMode))
2143             {
2144                 if (TryGetNestedPolicyAlternatives(importer, assertion, out alternatives))
2145                 {
2146                     foreach (Collection<XmlElement> alternative in alternatives)
2147                     {
2148                         X509SecurityTokenParameters x509 = new X509SecurityTokenParameters();
2149                         parameters = x509;
2150                         if (TryImportWsspRequireDerivedKeysAssertion(alternative, x509)
2151                             && TryImportX509ReferenceStyleAssertion(alternative, x509)
2152                             && TryImportWsspAssertion(alternative, WssX509V3Token10Name, true)
2153                             && alternative.Count == 0)
2154                         {
2155                             parameters.InclusionMode = inclusionMode;
2156                             break;
2157                         }
2158                         else
2159                         {
2160                             parameters = null;
2161                         }
2162                     }
2163                 }
2164                 else
2165                 {
2166                     parameters = new X509SecurityTokenParameters();
2167                     parameters.RequireDerivedKeys = false;
2168                     parameters.InclusionMode = inclusionMode;
2169                 }
2170             }
2171
2172             return parameters != null;
2173         }
2174
2175         public virtual XmlElement CreateWsspUsernameTokenAssertion(MetadataExporter exporter, UserNameSecurityTokenParameters parameters)
2176         {
2177             XmlElement result = CreateWsspAssertion(UsernameTokenName);
2178             SetIncludeTokenValue(result, parameters.InclusionMode);
2179             result.AppendChild(
2180                 CreateWspPolicyWrapper(
2181                     exporter,
2182                     CreateWsspAssertion(WssUsernameToken10Name)
2183             ));
2184             return result;
2185         }
2186
2187         public virtual bool TryImportWsspUsernameTokenAssertion(MetadataImporter importer, XmlElement assertion, out SecurityTokenParameters parameters)
2188         {
2189             parameters = null;
2190
2191             SecurityTokenInclusionMode inclusionMode;
2192             Collection<Collection<XmlElement>> alternatives;
2193
2194             if (IsWsspAssertion(assertion, UsernameTokenName)
2195                 && TryGetIncludeTokenValue(assertion, out inclusionMode))
2196             {
2197                 if (TryGetNestedPolicyAlternatives(importer, assertion, out alternatives))
2198                 {
2199                     foreach (Collection<XmlElement> alternative in alternatives)
2200                     {
2201                         if (TryImportWsspAssertion(alternative, WssUsernameToken10Name)
2202                             && alternative.Count == 0)
2203                         {
2204                             parameters = new UserNameSecurityTokenParameters();
2205                             parameters.InclusionMode = inclusionMode;
2206                             break;
2207                         }
2208                     }
2209                 }
2210                 else
2211                 {
2212                     parameters = new UserNameSecurityTokenParameters();
2213                     parameters.InclusionMode = inclusionMode;
2214                 }
2215             }
2216
2217             return parameters != null;
2218         }
2219
2220         public virtual XmlElement CreateWsspRsaTokenAssertion(RsaSecurityTokenParameters parameters)
2221         {
2222             XmlElement result = CreateMsspAssertion(RsaTokenName);
2223             SetIncludeTokenValue(result, parameters.InclusionMode);
2224             return result;
2225         }
2226
2227         public virtual bool TryImportWsspRsaTokenAssertion(MetadataImporter importer, XmlElement assertion, out SecurityTokenParameters parameters)
2228         {
2229             parameters = null;
2230
2231             SecurityTokenInclusionMode inclusionMode;
2232             Collection<Collection<XmlElement>> alternatives;
2233
2234             if (IsMsspAssertion(assertion, RsaTokenName)
2235                 && TryGetIncludeTokenValue(assertion, out inclusionMode)
2236                 && TryGetNestedPolicyAlternatives(importer, assertion, out alternatives) == false)
2237             {
2238                 parameters = new RsaSecurityTokenParameters();
2239                 parameters.InclusionMode = inclusionMode;
2240             }
2241
2242             return parameters != null;
2243         }
2244
2245         public virtual XmlElement CreateReferenceStyleAssertion(SecurityTokenReferenceStyle referenceStyle)
2246         {
2247             switch (referenceStyle)
2248             {
2249                 default:
2250                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("referenceStyle"));
2251                 case SecurityTokenReferenceStyle.External:
2252                     return CreateWsspAssertion(RequireExternalReferenceName);
2253                 case SecurityTokenReferenceStyle.Internal:
2254                     return CreateWsspAssertion(RequireInternalReferenceName);
2255             }
2256         }
2257
2258         public virtual bool TryImportReferenceStyleAssertion(ICollection<XmlElement> assertions, IssuedSecurityTokenParameters parameters)
2259         {
2260             if (TryImportWsspAssertion(assertions, RequireExternalReferenceName))
2261             {
2262                 parameters.ReferenceStyle = SecurityTokenReferenceStyle.External;
2263             }
2264             else if (TryImportWsspAssertion(assertions, RequireInternalReferenceName))
2265             {
2266                 parameters.ReferenceStyle = SecurityTokenReferenceStyle.Internal;
2267             }
2268
2269             return true;
2270         }
2271
2272         public virtual XmlElement CreateWsspIssuerElement(EndpointAddress issuerAddress, EndpointAddress issuerMetadataAddress)
2273         {
2274             XmlElement result;
2275             if (issuerAddress == null && issuerMetadataAddress == null)
2276             {
2277                 result = null;
2278             }
2279             else
2280             {
2281                 EndpointAddress addressToSerialize;
2282                 addressToSerialize = issuerAddress == null ? EndpointAddress.AnonymousAddress : issuerAddress;
2283
2284                 MemoryStream stream;
2285                 XmlWriter writer;
2286
2287                 if (issuerMetadataAddress != null)
2288                 {
2289                     MetadataSet metadataSet = new MetadataSet();
2290                     metadataSet.MetadataSections.Add(new MetadataSection(null, null, new MetadataReference(issuerMetadataAddress, AddressingVersion.WSAddressing10)));
2291
2292                     stream = new MemoryStream();
2293                     writer = new XmlTextWriter(stream, System.Text.Encoding.UTF8);
2294                     metadataSet.WriteTo(XmlDictionaryWriter.CreateDictionaryWriter(writer));
2295                     writer.Flush();
2296                     stream.Seek(0, SeekOrigin.Begin);
2297
2298                     addressToSerialize = new EndpointAddress(
2299                         addressToSerialize.Uri,
2300                         addressToSerialize.Identity,
2301                         addressToSerialize.Headers,
2302                         XmlDictionaryReader.CreateDictionaryReader(XmlReader.Create(stream)),
2303                         addressToSerialize.GetReaderAtExtensions());
2304                 }
2305
2306                 stream = new MemoryStream();
2307                 writer = new XmlTextWriter(stream, System.Text.Encoding.UTF8);
2308                 writer.WriteStartElement(IssuerName, this.WsspNamespaceUri);
2309                 addressToSerialize.WriteContentsTo(AddressingVersion.WSAddressing10, writer);
2310                 writer.WriteEndElement();
2311                 writer.Flush();
2312                 stream.Seek(0, SeekOrigin.Begin);
2313                 result = (XmlElement)doc.ReadNode(new XmlTextReader(stream) { DtdProcessing = DtdProcessing.Prohibit });
2314             }
2315             return result;
2316         }
2317
2318         public virtual bool TryGetIssuer(XmlElement assertion, out EndpointAddress issuer, out EndpointAddress issuerMetadata)
2319         {
2320             bool result = true;
2321             issuer = null;
2322             issuerMetadata = null;
2323
2324             foreach (XmlNode node in assertion.ChildNodes)
2325             {
2326                 if (node is XmlElement && IsWsspAssertion((XmlElement)node, IssuerName))
2327                 {
2328                     try
2329                     {
2330                         issuer = EndpointAddress.ReadFrom(XmlDictionaryReader.CreateDictionaryReader(new XmlNodeReader(node)));
2331                         XmlDictionaryReader metadataReader = issuer.GetReaderAtMetadata();
2332                         if (metadataReader != null)
2333                         {
2334                             while (metadataReader.MoveToContent() == XmlNodeType.Element)
2335                             {
2336                                 if (metadataReader.LocalName == MetadataStrings.MetadataExchangeStrings.Metadata
2337                                     && metadataReader.NamespaceURI == MetadataStrings.MetadataExchangeStrings.Namespace)
2338                                 {
2339                                     MetadataSet metadataSet = MetadataSet.ReadFrom(metadataReader);
2340                                     foreach (MetadataSection section in metadataSet.MetadataSections)
2341                                     {
2342                                         if (section.Metadata is MetadataReference)
2343                                         {
2344                                             issuerMetadata = ((MetadataReference)section.Metadata).Address;
2345                                         }
2346                                     }
2347
2348                                     break;
2349                                 }
2350                                 else
2351                                 {
2352                                     metadataReader.Skip();
2353                                 }
2354                             }
2355                         }
2356                     }
2357                     catch (Exception e)
2358                     {
2359                         if (Fx.IsFatal(e))
2360                             throw;
2361                         if (e is NullReferenceException)
2362                             throw;
2363                         result = false;
2364                     }
2365                     break;
2366                 }
2367             }
2368
2369             return result;
2370         }
2371
2372         public virtual XmlElement CreateWsspIssuedTokenAssertion(MetadataExporter exporter, IssuedSecurityTokenParameters parameters)
2373         {
2374             XmlElement result = CreateWsspAssertion(IssuedTokenName);
2375             SetIncludeTokenValue(result, parameters.InclusionMode);
2376             XmlElement issuerAssertion = CreateWsspIssuerElement(parameters.IssuerAddress, parameters.IssuerMetadataAddress);
2377             if (issuerAssertion != null)
2378             {
2379                 result.AppendChild(issuerAssertion);
2380             }
2381             XmlElement tokenTemplate = CreateWsspAssertion(RequestSecurityTokenTemplateName);
2382             TrustDriver driver = this.TrustDriver;
2383             foreach (XmlElement p in parameters.CreateRequestParameters(driver))
2384             {
2385                 tokenTemplate.AppendChild(doc.ImportNode(p, true));
2386             }
2387             result.AppendChild(tokenTemplate);
2388             result.AppendChild(
2389                 CreateWspPolicyWrapper(
2390                     exporter,
2391                     CreateWsspRequireDerivedKeysAssertion(parameters.RequireDerivedKeys),
2392                     CreateReferenceStyleAssertion(parameters.ReferenceStyle)
2393             ));
2394             return result;
2395         }
2396
2397         public virtual bool TryGetRequestSecurityTokenTemplate(XmlElement assertion, out Collection<XmlElement> requestParameters)
2398         {
2399             requestParameters = null;
2400
2401             foreach (XmlNode node in assertion.ChildNodes)
2402             {
2403                 if (node is XmlElement && IsWsspAssertion((XmlElement)node, RequestSecurityTokenTemplateName))
2404                 {
2405                     requestParameters = new Collection<XmlElement>();
2406                     foreach (XmlNode p in node.ChildNodes)
2407                     {
2408                         if (p is XmlElement)
2409                         {
2410                             requestParameters.Add((XmlElement)p);
2411                         }
2412                     }
2413                 }
2414             }
2415
2416             return requestParameters != null;
2417         }
2418
2419         public virtual bool TryImportWsspIssuedTokenAssertion(MetadataImporter importer, PolicyConversionContext policyContext, XmlElement assertion, out SecurityTokenParameters parameters)
2420         {
2421             parameters = null;
2422
2423             SecurityTokenInclusionMode inclusionMode;
2424             Collection<Collection<XmlElement>> alternatives;
2425             EndpointAddress issuer;
2426             EndpointAddress issuerMetadata;
2427             Collection<XmlElement> requestSecurityTokenTemplate;
2428
2429             if (IsWsspAssertion(assertion, IssuedTokenName)
2430                 && TryGetIncludeTokenValue(assertion, out inclusionMode)
2431                 && TryGetIssuer(assertion, out issuer, out issuerMetadata)
2432                 && TryGetRequestSecurityTokenTemplate(assertion, out requestSecurityTokenTemplate))
2433             {
2434                 if (TryGetNestedPolicyAlternatives(importer, assertion, out alternatives))
2435                 {
2436                     foreach (Collection<XmlElement> alternative in alternatives)
2437                     {
2438                         IssuedSecurityTokenParameters issued = new IssuedSecurityTokenParameters();
2439                         parameters = issued;
2440                         if (TryImportWsspRequireDerivedKeysAssertion(alternative, issued)
2441                             && TryImportReferenceStyleAssertion(alternative, issued)
2442                             && alternative.Count == 0)
2443                         {
2444                             issued.InclusionMode = inclusionMode;
2445                             issued.IssuerAddress = issuer;
2446                             issued.IssuerMetadataAddress = issuerMetadata;
2447                             issued.SetRequestParameters(requestSecurityTokenTemplate, this.TrustDriver);
2448
2449                             TokenIssuerPolicyResolver policyResolver = new TokenIssuerPolicyResolver(this.TrustDriver);
2450                             policyResolver.ResolveTokenIssuerPolicy(importer, policyContext, issued);
2451
2452                             break;
2453                         }
2454                         else
2455                         {
2456                             parameters = null;
2457                         }
2458                     }
2459                 }
2460                 else
2461                 {
2462                     IssuedSecurityTokenParameters issued = new IssuedSecurityTokenParameters();
2463                     parameters = issued;
2464                     issued.InclusionMode = inclusionMode;
2465                     issued.IssuerAddress = issuer;
2466                     issued.IssuerMetadataAddress = issuerMetadata;
2467                     issued.SetRequestParameters(requestSecurityTokenTemplate, this.TrustDriver);
2468                     issued.RequireDerivedKeys = false;
2469                 }
2470             }
2471
2472             return parameters != null;
2473         }
2474
2475         public virtual XmlElement CreateWsspMustNotSendCancelAssertion(bool requireCancel)
2476         {
2477             if (!requireCancel)
2478             {
2479                 XmlElement result = CreateWsspAssertion(MustNotSendCancelName);
2480                 return result;
2481             }
2482             else
2483             {
2484                 return null;
2485             }
2486         }
2487
2488         public virtual bool TryImportWsspMustNotSendCancelAssertion(ICollection<XmlElement> assertions, out bool requireCancellation)
2489         {
2490             requireCancellation = !TryImportWsspAssertion(assertions, MustNotSendCancelName);
2491             return true;
2492         }
2493
2494         public virtual XmlElement CreateWsspSpnegoContextTokenAssertion(MetadataExporter exporter, SspiSecurityTokenParameters parameters)
2495         {
2496             XmlElement result = CreateWsspAssertion(SpnegoContextTokenName);
2497             SetIncludeTokenValue(result, parameters.InclusionMode);
2498             result.AppendChild(
2499                 CreateWspPolicyWrapper(
2500                     exporter,
2501                     CreateWsspRequireDerivedKeysAssertion(parameters.RequireDerivedKeys),
2502                     CreateWsspMustNotSendCancelAssertion(parameters.RequireCancellation)
2503             ));
2504             return result;
2505         }
2506
2507         public virtual bool TryImportWsspSpnegoContextTokenAssertion(MetadataImporter importer, XmlElement assertion, out SecurityTokenParameters parameters)
2508         {
2509             parameters = null;
2510
2511             SecurityTokenInclusionMode inclusionMode;
2512             Collection<Collection<XmlElement>> alternatives;
2513
2514             if (IsWsspAssertion(assertion, SpnegoContextTokenName)
2515                 && TryGetIncludeTokenValue(assertion, out inclusionMode))
2516             {
2517                 if (TryGetNestedPolicyAlternatives(importer, assertion, out alternatives))
2518                 {
2519                     foreach (Collection<XmlElement> alternative in alternatives)
2520                     {
2521                         SspiSecurityTokenParameters sspi = new SspiSecurityTokenParameters();
2522                         parameters = sspi;
2523                         bool requireCancellation;
2524                         if (TryImportWsspRequireDerivedKeysAssertion(alternative, sspi)
2525                             && TryImportWsspMustNotSendCancelAssertion(alternative, out requireCancellation)
2526                             && alternative.Count == 0)
2527                         {
2528                             sspi.RequireCancellation = requireCancellation;
2529                             sspi.InclusionMode = inclusionMode;
2530                             break;
2531                         }
2532                         else
2533                         {
2534                             parameters = null;
2535                         }
2536                     }
2537                 }
2538                 else
2539                 {
2540                     parameters = new SspiSecurityTokenParameters();
2541                     parameters.RequireDerivedKeys = false;
2542                     parameters.InclusionMode = inclusionMode;
2543                 }
2544             }
2545
2546             return parameters != null;
2547         }
2548
2549         public abstract XmlElement CreateWsspHttpsTokenAssertion(MetadataExporter exporter, HttpsTransportBindingElement httpsBinding);
2550
2551         public abstract bool TryImportWsspHttpsTokenAssertion(MetadataImporter importer, ICollection<XmlElement> assertions, HttpsTransportBindingElement httpsBinding);
2552
2553         public virtual bool ContainsWsspHttpsTokenAssertion(ICollection<XmlElement> assertions)
2554         {
2555             return (PolicyConversionContext.FindAssertion(assertions, HttpsTokenName, this.WsspNamespaceUri, false) != null);
2556         }
2557
2558         public virtual XmlElement CreateMsspRequireClientCertificateAssertion(bool requireClientCertificate)
2559         {
2560             if (requireClientCertificate)
2561             {
2562                 return CreateMsspAssertion(RequireClientCertificateName);
2563             }
2564             else
2565             {
2566                 return null;
2567             }
2568         }
2569
2570         public virtual bool TryImportMsspRequireClientCertificateAssertion(ICollection<XmlElement> assertions, SslSecurityTokenParameters parameters)
2571         {
2572             parameters.RequireClientCertificate = TryImportMsspAssertion(assertions, RequireClientCertificateName);
2573             return true;
2574         }
2575
2576         public virtual XmlElement CreateMsspSslContextTokenAssertion(MetadataExporter exporter, SslSecurityTokenParameters parameters)
2577         {
2578             XmlElement result = CreateMsspAssertion(SslContextTokenName);
2579             SetIncludeTokenValue(result, parameters.InclusionMode);
2580             result.AppendChild(
2581                 CreateWspPolicyWrapper(
2582                     exporter,
2583                     CreateWsspRequireDerivedKeysAssertion(parameters.RequireDerivedKeys),
2584                     CreateWsspMustNotSendCancelAssertion(parameters.RequireCancellation),
2585                     CreateMsspRequireClientCertificateAssertion(parameters.RequireClientCertificate)
2586             ));
2587             return result;
2588         }
2589
2590         public virtual bool TryImportMsspSslContextTokenAssertion(MetadataImporter importer, XmlElement assertion, out SecurityTokenParameters parameters)
2591         {
2592             parameters = null;
2593
2594             SecurityTokenInclusionMode inclusionMode;
2595             Collection<Collection<XmlElement>> alternatives;
2596
2597             if (IsMsspAssertion(assertion, SslContextTokenName)
2598                 && TryGetIncludeTokenValue(assertion, out inclusionMode))
2599             {
2600                 if (TryGetNestedPolicyAlternatives(importer, assertion, out alternatives))
2601                 {
2602                     foreach (Collection<XmlElement> alternative in alternatives)
2603                     {
2604                         SslSecurityTokenParameters ssl = new SslSecurityTokenParameters();
2605                         parameters = ssl;
2606                         bool requireCancellation;
2607                         if (TryImportWsspRequireDerivedKeysAssertion(alternative, ssl)
2608                             && TryImportWsspMustNotSendCancelAssertion(alternative, out requireCancellation)
2609                             && TryImportMsspRequireClientCertificateAssertion(alternative, ssl)
2610                             && alternative.Count == 0)
2611                         {
2612                             ssl.RequireCancellation = requireCancellation;
2613                             ssl.InclusionMode = inclusionMode;
2614                             break;
2615                         }
2616                         else
2617                         {
2618                             parameters = null;
2619                         }
2620                     }
2621                 }
2622                 else
2623                 {
2624                     parameters = new SslSecurityTokenParameters();
2625                     parameters.RequireDerivedKeys = false;
2626                     parameters.InclusionMode = inclusionMode;
2627                 }
2628             }
2629
2630             return parameters != null;
2631         }
2632
2633         public virtual XmlElement CreateWsspBootstrapPolicyAssertion(MetadataExporter exporter, SecurityBindingElement bootstrapSecurity)
2634         {
2635             if (bootstrapSecurity == null)
2636                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("bootstrapBinding");
2637
2638             WSSecurityPolicy sp = WSSecurityPolicy.GetSecurityPolicyDriver(bootstrapSecurity.MessageSecurityVersion);
2639
2640             // create complete bootstrap binding
2641
2642             CustomBinding bootstrapBinding = new CustomBinding(bootstrapSecurity);
2643             if (exporter.State.ContainsKey(SecurityPolicyStrings.SecureConversationBootstrapBindingElementsBelowSecurityKey))
2644             {
2645                 BindingElementCollection bindingElementsBelowSecurity = exporter.State[SecurityPolicyStrings.SecureConversationBootstrapBindingElementsBelowSecurityKey] as BindingElementCollection;
2646                 if (bindingElementsBelowSecurity != null)
2647                 {
2648                     foreach (BindingElement be in bindingElementsBelowSecurity)
2649                     {
2650                         bootstrapBinding.Elements.Add(be);
2651                     }
2652                 }
2653             }
2654
2655             // generate policy for the "how" of security 
2656
2657             ServiceEndpoint bootstrapEndpoint = new ServiceEndpoint(NullContract);
2658             bootstrapEndpoint.Binding = bootstrapBinding;
2659             PolicyConversionContext policyContext = exporter.ExportPolicy(bootstrapEndpoint);
2660
2661             // generate policy for the "what" of security (protection assertions)
2662
2663             // hard-coded requirements in V1: sign and encrypt RST and RSTR body
2664             ChannelProtectionRequirements bootstrapProtection = new ChannelProtectionRequirements();
2665             bootstrapProtection.IncomingEncryptionParts.AddParts(new MessagePartSpecification(true));
2666             bootstrapProtection.OutgoingEncryptionParts.AddParts(new MessagePartSpecification(true));
2667             bootstrapProtection.IncomingSignatureParts.AddParts(new MessagePartSpecification(true));
2668             bootstrapProtection.OutgoingSignatureParts.AddParts(new MessagePartSpecification(true));
2669
2670             // add boostrap binding protection requirements (e.g. addressing headers)
2671             ChannelProtectionRequirements cpr = bootstrapBinding.GetProperty<ChannelProtectionRequirements>(new BindingParameterCollection());
2672             if (cpr != null)
2673             {
2674                 bootstrapProtection.Add(cpr);
2675             }
2676
2677             // extract channel-scope protection requirements and union them across request and response
2678             MessagePartSpecification encryption = new MessagePartSpecification();
2679             encryption.Union(bootstrapProtection.IncomingEncryptionParts.ChannelParts);
2680             encryption.Union(bootstrapProtection.OutgoingEncryptionParts.ChannelParts);
2681             encryption.MakeReadOnly();
2682             MessagePartSpecification signature = new MessagePartSpecification();
2683             signature.Union(bootstrapProtection.IncomingSignatureParts.ChannelParts);
2684             signature.Union(bootstrapProtection.OutgoingSignatureParts.ChannelParts);
2685             signature.MakeReadOnly();
2686
2687             // create final boostrap policy assertion
2688
2689             XmlElement nestedPolicy = CreateWspPolicyWrapper(
2690                     exporter,
2691                     sp.CreateWsspSignedPartsAssertion(signature),
2692                     sp.CreateWsspEncryptedPartsAssertion(encryption));
2693             foreach (XmlElement e in sp.FilterWsspPolicyAssertions(policyContext.GetBindingAssertions()))
2694             {
2695                 nestedPolicy.AppendChild(e);
2696             }
2697             XmlElement result = CreateWsspAssertion(BootstrapPolicyName);
2698             result.AppendChild(nestedPolicy);
2699
2700             return result;
2701         }
2702
2703         public virtual ICollection<XmlElement> FilterWsspPolicyAssertions(ICollection<XmlElement> policyAssertions)
2704         {
2705             Collection<XmlElement> result = new Collection<XmlElement>();
2706
2707             foreach (XmlElement assertion in policyAssertions)
2708                 if (IsWsspAssertion(assertion))
2709                     result.Add(assertion);
2710
2711             return result;
2712         }
2713
2714         public virtual bool TryImportWsspBootstrapPolicyAssertion(MetadataImporter importer, ICollection<XmlElement> assertions, SecureConversationSecurityTokenParameters parameters)
2715         {
2716             bool result = false;
2717
2718             XmlElement assertion;
2719             Collection<Collection<XmlElement>> alternatives;
2720
2721             if (TryImportWsspAssertion(assertions, BootstrapPolicyName, out assertion)
2722                 && TryGetNestedPolicyAlternatives(importer, assertion, out alternatives))
2723             {
2724                 BindingElementCollection bindingElements;
2725                 importer.State[SecurityBindingElementImporter.InSecureConversationBootstrapBindingImportMode] = SecurityBindingElementImporter.InSecureConversationBootstrapBindingImportMode;
2726                 try
2727                 {
2728                     bindingElements = importer.ImportPolicy(NullServiceEndpoint, alternatives);
2729                     if (importer.State.ContainsKey(SecurityBindingElementImporter.SecureConversationBootstrapEncryptionRequirements))
2730                     {
2731                         MessagePartSpecification encryption = (MessagePartSpecification)importer.State[SecurityBindingElementImporter.SecureConversationBootstrapEncryptionRequirements];
2732                         if (encryption.IsBodyIncluded != true)
2733                         {
2734                             importer.Errors.Add(new MetadataConversionError(SR.GetString(SR.UnsupportedSecureConversationBootstrapProtectionRequirements), false));
2735                             bindingElements = null;
2736                         }
2737                     }
2738                     if (importer.State.ContainsKey(SecurityBindingElementImporter.SecureConversationBootstrapSignatureRequirements))
2739                     {
2740                         MessagePartSpecification signature = (MessagePartSpecification)importer.State[SecurityBindingElementImporter.SecureConversationBootstrapSignatureRequirements];
2741                         if (signature.IsBodyIncluded != true)
2742                         {
2743                             importer.Errors.Add(new MetadataConversionError(SR.GetString(SR.UnsupportedSecureConversationBootstrapProtectionRequirements), false));
2744                             bindingElements = null;
2745                         }
2746                     }
2747                 }
2748                 finally
2749                 {
2750                     importer.State.Remove(SecurityBindingElementImporter.InSecureConversationBootstrapBindingImportMode);
2751                     if (importer.State.ContainsKey(SecurityBindingElementImporter.SecureConversationBootstrapEncryptionRequirements))
2752                         importer.State.Remove(SecurityBindingElementImporter.SecureConversationBootstrapEncryptionRequirements);
2753                     if (importer.State.ContainsKey(SecurityBindingElementImporter.SecureConversationBootstrapSignatureRequirements))
2754                         importer.State.Remove(SecurityBindingElementImporter.SecureConversationBootstrapSignatureRequirements);
2755                 }
2756                 if (bindingElements != null)
2757                 {
2758                     parameters.BootstrapSecurityBindingElement = bindingElements.Find<SecurityBindingElement>();
2759                     return true;
2760                 }
2761                 else
2762                 {
2763                     parameters.BootstrapSecurityBindingElement = null;
2764                     return true; // Consider returning false here.
2765                 }
2766             }
2767
2768             return result;
2769         }
2770
2771         public virtual XmlElement CreateWsspSecureConversationTokenAssertion(MetadataExporter exporter, SecureConversationSecurityTokenParameters parameters)
2772         {
2773             XmlElement result = CreateWsspAssertion(SecureConversationTokenName);
2774             SetIncludeTokenValue(result, parameters.InclusionMode);
2775             result.AppendChild(
2776                 CreateWspPolicyWrapper(
2777                     exporter,
2778                     CreateWsspRequireDerivedKeysAssertion(parameters.RequireDerivedKeys),
2779                     CreateWsspMustNotSendCancelAssertion(parameters.RequireCancellation),
2780                     CreateWsspBootstrapPolicyAssertion(exporter, parameters.BootstrapSecurityBindingElement)
2781             ));
2782             return result;
2783         }
2784
2785         public virtual bool TryImportWsspSecureConversationTokenAssertion(MetadataImporter importer, XmlElement assertion, out SecurityTokenParameters parameters)
2786         {
2787             parameters = null;
2788
2789             SecurityTokenInclusionMode inclusionMode;
2790             Collection<Collection<XmlElement>> alternatives;
2791
2792             if (IsWsspAssertion(assertion, SecureConversationTokenName)
2793                 && TryGetIncludeTokenValue(assertion, out inclusionMode))
2794             {
2795                 if (TryGetNestedPolicyAlternatives(importer, assertion, out alternatives))
2796                 {
2797                     foreach (Collection<XmlElement> alternative in alternatives)
2798                     {
2799                         SecureConversationSecurityTokenParameters sc = new SecureConversationSecurityTokenParameters();
2800                         parameters = sc;
2801                         bool requireCancellation;
2802                         if (TryImportWsspRequireDerivedKeysAssertion(alternative, sc)
2803                             && TryImportWsspMustNotSendCancelAssertion(alternative, out requireCancellation)
2804                             && TryImportWsspBootstrapPolicyAssertion(importer, alternative, sc)
2805                             && alternative.Count == 0)
2806                         {
2807                             sc.RequireCancellation = requireCancellation;
2808                             sc.InclusionMode = inclusionMode;
2809                             break;
2810                         }
2811                         else
2812                         {
2813                             parameters = null;
2814                         }
2815                     }
2816                 }
2817                 else
2818                 {
2819                     parameters = new SecureConversationSecurityTokenParameters();
2820                     parameters.InclusionMode = inclusionMode;
2821                     parameters.RequireDerivedKeys = false;
2822                 }
2823             }
2824
2825             return parameters != null;
2826         }
2827
2828         class TokenIssuerPolicyResolver
2829         {
2830             const string WSIdentityNamespace = @"http://schemas.xmlsoap.org/ws/2005/05/identity";
2831             static readonly Uri SelfIssuerUri = new Uri(WSIdentityNamespace + "/issuer/self");
2832
2833             TrustDriver trustDriver;
2834
2835             public TokenIssuerPolicyResolver(TrustDriver driver)
2836             {
2837                 this.trustDriver = driver;
2838             }
2839
2840             public void ResolveTokenIssuerPolicy(MetadataImporter importer, PolicyConversionContext policyContext, IssuedSecurityTokenParameters parameters)
2841             {
2842                 if (policyContext == null)
2843                 {
2844                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("policyContext");
2845                 }
2846                 if (parameters == null)
2847                 {
2848                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parameters");
2849                 }
2850
2851                 EndpointAddress mexAddress = (parameters.IssuerMetadataAddress != null) ? parameters.IssuerMetadataAddress : parameters.IssuerAddress;
2852                 if (mexAddress == null || mexAddress.IsAnonymous || mexAddress.Uri.Equals(SelfIssuerUri))
2853                 {
2854                     return;
2855                 }
2856                 int maximumRedirections = (int)importer.State[SecurityBindingElementImporter.MaxPolicyRedirectionsKey];
2857
2858                 if (maximumRedirections <= 0)
2859                 {
2860                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MaximumPolicyRedirectionsExceeded)));
2861                 }
2862                 --maximumRedirections;
2863
2864                 //
2865                 // Try to retrieve the proxy from the importer.State bag so that we can have secure mex
2866                 // and it fails, then we can create a default one
2867                 //
2868                 MetadataExchangeClient policyFetcher = null;
2869                 if ((importer.State != null) && (importer.State.ContainsKey(MetadataExchangeClient.MetadataExchangeClientKey)))
2870                 {
2871                     policyFetcher = importer.State[MetadataExchangeClient.MetadataExchangeClientKey] as MetadataExchangeClient;
2872                 }
2873
2874                 if (policyFetcher == null)
2875                     policyFetcher = new MetadataExchangeClient(mexAddress);
2876
2877                 ServiceEndpointCollection federationEndpoints = null;
2878                 MetadataSet metadataSet = null;
2879                 Exception mexException = null;
2880                 try
2881                 {
2882                     metadataSet = policyFetcher.GetMetadata(mexAddress);
2883                 }
2884                 catch (Exception e)
2885                 {
2886                     if (Fx.IsFatal(e))
2887                         throw;
2888                     if (e is NullReferenceException)
2889                         throw;
2890
2891                     mexException = e;
2892                 }
2893
2894                 //
2895                 // DCR 6729: Try the http get option here if mex failed.
2896                 //
2897                 if (metadataSet == null )
2898                 {
2899                     try
2900                     {
2901                         metadataSet = policyFetcher.GetMetadata(mexAddress.Uri, MetadataExchangeClientMode.HttpGet);
2902                     }
2903                     catch (Exception e)
2904                     {
2905                         if (Fx.IsFatal(e))
2906                             throw;
2907                         if (e is NullReferenceException)
2908                             throw;
2909
2910                         if (mexException == null)
2911                             mexException = e;
2912                     }
2913                 }
2914
2915                 if (metadataSet == null)
2916                 {
2917                     //
2918                     // we could not retrieve the metadata from the issuer for some reason
2919                     //
2920                     if (mexException != null)
2921                         importer.Errors.Add(new MetadataConversionError(SR.GetString(SR.UnableToObtainIssuerMetadata, mexAddress, mexException), false));
2922    
2923                     return;
2924                 }
2925                 WsdlImporter wsdlImporter;
2926                 // NOTE: [....], Policy import/export is seperate from WSDL however, this policy importer
2927                 //      invokes the WsdlImporter. In the event that the current MetadataImporter is a WsdlImporter,
2928                 //      we should use it's collection of extensions for the import process. Other wise
2929                 WsdlImporter currentWsdlImporter = importer as WsdlImporter;
2930                 if (currentWsdlImporter != null)
2931                 {
2932                     wsdlImporter = new WsdlImporter(metadataSet, importer.PolicyImportExtensions, currentWsdlImporter.WsdlImportExtensions);
2933                 }
2934                 else
2935                 {
2936                     wsdlImporter = new WsdlImporter(metadataSet, importer.PolicyImportExtensions, null);
2937                 }
2938
2939                 //
2940                 // Copy the State from the first importer to the second one so that the state can be passed to the second round wsdl retrieval
2941                 //
2942                 if ((importer.State != null) && (importer.State.ContainsKey(MetadataExchangeClient.MetadataExchangeClientKey)))
2943                 {
2944                     wsdlImporter.State.Add(MetadataExchangeClient.MetadataExchangeClientKey, importer.State[MetadataExchangeClient.MetadataExchangeClientKey]);
2945                 }
2946
2947                 wsdlImporter.State.Add(SecurityBindingElementImporter.MaxPolicyRedirectionsKey, maximumRedirections);
2948
2949                 federationEndpoints = wsdlImporter.ImportAllEndpoints();
2950
2951                 // copy all the import errors into the current metadata importer
2952                 for (int i = 0; i < wsdlImporter.Errors.Count; ++i)
2953                 {
2954                     MetadataConversionError error = wsdlImporter.Errors[i];
2955                     importer.Errors.Add(new MetadataConversionError(SR.GetString(SR.ErrorImportingIssuerMetadata, mexAddress, InsertEllipsisIfTooLong(error.Message)), error.IsWarning));
2956                 }
2957
2958                 if (federationEndpoints != null)
2959                 {
2960                     AddCompatibleFederationEndpoints(federationEndpoints, parameters);
2961                     if (parameters.AlternativeIssuerEndpoints != null && parameters.AlternativeIssuerEndpoints.Count > 0)
2962                     {
2963                         importer.Errors.Add(new MetadataConversionError(SR.GetString(SR.MultipleIssuerEndpointsFound, mexAddress)));
2964                     }
2965                 }
2966             }
2967
2968             static string InsertEllipsisIfTooLong(string message)
2969             {
2970                 const int MaxLength = 1024;
2971                 const string Ellipsis = "....";
2972
2973                 if (message != null && message.Length > MaxLength)
2974                 {
2975                     return String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}",
2976                         message.Substring(0, (MaxLength - Ellipsis.Length) / 2),
2977                         Ellipsis,
2978                         message.Substring(message.Length - (MaxLength - Ellipsis.Length) / 2));
2979                 }
2980                 return message;
2981             }
2982
2983             void AddCompatibleFederationEndpoints(ServiceEndpointCollection serviceEndpoints, IssuedSecurityTokenParameters parameters)
2984             {
2985                 // check if an explicit issuer address has been specified. If so,add the endpoint corresponding to that address only. If not add all acceptable endpoints.
2986
2987                 bool isIssuerSpecified = (parameters.IssuerAddress != null && !parameters.IssuerAddress.IsAnonymous);
2988                 foreach (ServiceEndpoint endpoint in serviceEndpoints)
2989                 {
2990                     TrustDriver trustDriver;
2991                     if (!TryGetTrustDriver(endpoint, out trustDriver))
2992                     {
2993                         // if endpoint does not have trustDriver, assume
2994                         // parent trustDriver.
2995                         trustDriver = this.trustDriver;
2996                     }
2997                     bool isFederationContract = false;
2998                     ContractDescription contract = endpoint.Contract;
2999                     for (int j = 0; j < contract.Operations.Count; ++j)
3000                     {
3001                         OperationDescription operation = contract.Operations[j];
3002                         bool hasIncomingRst = false;
3003                         bool hasOutgoingRstr = false;
3004                         for (int k = 0; k < operation.Messages.Count; ++k)
3005                         {
3006                             MessageDescription message = operation.Messages[k];
3007                             if (message.Action == trustDriver.RequestSecurityTokenAction.Value && message.Direction == MessageDirection.Input)
3008                             {
3009                                 hasIncomingRst = true;
3010                             }
3011                             else if ((((trustDriver.StandardsManager.TrustVersion == TrustVersion.WSTrustFeb2005) && (message.Action == trustDriver.RequestSecurityTokenResponseAction.Value)) || 
3012                                 ((trustDriver.StandardsManager.TrustVersion == TrustVersion.WSTrust13) && (message.Action == trustDriver.RequestSecurityTokenResponseFinalAction.Value))) && 
3013                                 message.Direction == MessageDirection.Output)
3014                             {
3015                                 hasOutgoingRstr = true;
3016                             }
3017                         }
3018                         if (hasIncomingRst && hasOutgoingRstr)
3019                         {
3020                             isFederationContract = true;
3021                             break;
3022                         }
3023                     }
3024                     if (isFederationContract)
3025                     {
3026                         // skip if it is not an acceptable endpoint
3027                         if (isIssuerSpecified && !parameters.IssuerAddress.Uri.Equals(endpoint.Address.Uri))
3028                         {
3029                             continue;
3030                         }
3031
3032                         if (parameters.IssuerBinding == null)
3033                         {
3034                             parameters.IssuerAddress = endpoint.Address;
3035                             parameters.IssuerBinding = endpoint.Binding;
3036                         }
3037                         else
3038                         {
3039                             IssuedSecurityTokenParameters.AlternativeIssuerEndpoint endpointInfo = new IssuedSecurityTokenParameters.AlternativeIssuerEndpoint();
3040                             endpointInfo.IssuerAddress = endpoint.Address;
3041                             endpointInfo.IssuerBinding = endpoint.Binding;
3042                             parameters.AlternativeIssuerEndpoints.Add(endpointInfo);
3043                         }
3044                     }
3045                 }
3046             }
3047
3048             bool TryGetTrustDriver(ServiceEndpoint endpoint, out TrustDriver trustDriver)
3049             {
3050                 SecurityBindingElement sbe = endpoint.Binding.CreateBindingElements().Find<SecurityBindingElement>();
3051                 trustDriver = null;
3052                 if (sbe != null)
3053                 {
3054                     MessageSecurityVersion messageSecurityVersion = sbe.MessageSecurityVersion;
3055                     if (messageSecurityVersion.TrustVersion == TrustVersion.WSTrustFeb2005)
3056                     {
3057                         trustDriver = new WSTrustFeb2005.DriverFeb2005(new SecurityStandardsManager(messageSecurityVersion, WSSecurityTokenSerializer.DefaultInstance));
3058                     }
3059                     else if (messageSecurityVersion.TrustVersion == TrustVersion.WSTrust13)
3060                     {
3061                         trustDriver = new WSTrustDec2005.DriverDec2005(new SecurityStandardsManager(messageSecurityVersion, WSSecurityTokenSerializer.DefaultInstance));
3062                     }
3063                 }
3064                 return trustDriver != null;
3065             }
3066         }
3067
3068         public static bool TryGetSecurityPolicyDriver(ICollection<XmlElement> assertions, out WSSecurityPolicy securityPolicy)
3069         {
3070             SecurityPolicyManager policyManager = new SecurityPolicyManager();
3071             return policyManager.TryGetSecurityPolicyDriver(assertions, out securityPolicy); 
3072         }
3073
3074         public static WSSecurityPolicy GetSecurityPolicyDriver(MessageSecurityVersion version)
3075         {
3076             SecurityPolicyManager policyManager = new SecurityPolicyManager();
3077             return policyManager.GetSecurityPolicyDriver(version);
3078         }
3079
3080         class SecurityPolicyManager
3081         {
3082             List<WSSecurityPolicy> drivers;
3083
3084             public SecurityPolicyManager()
3085             {
3086                 this.drivers = new List<WSSecurityPolicy>();
3087                 Initialize();
3088             }
3089
3090             public void Initialize()
3091             {
3092                 this.drivers.Add(new WSSecurityPolicy11());
3093                 this.drivers.Add(new WSSecurityPolicy12());
3094             }
3095
3096             public bool TryGetSecurityPolicyDriver(ICollection<XmlElement> assertions, out WSSecurityPolicy securityPolicy)
3097             {
3098                 securityPolicy = null;
3099
3100                 for (int i = 0; i < this.drivers.Count; ++i)
3101                 {
3102                     if (this.drivers[i].CanImportAssertion(assertions))
3103                     {
3104                         securityPolicy = this.drivers[i];
3105                         return true;
3106                     }
3107                 }
3108
3109                 return false;
3110             }
3111
3112             public WSSecurityPolicy GetSecurityPolicyDriver(MessageSecurityVersion version)
3113             {
3114                 for (int i = 0; i < this.drivers.Count; ++i)
3115                 {
3116                     if (this.drivers[i].IsSecurityVersionSupported(version))
3117                     {
3118                         return this.drivers[i];
3119                     }
3120                 }
3121
3122                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
3123             }
3124
3125         }
3126     }
3127
3128     static class SecurityPolicyStrings
3129     {
3130         public const string SecureConversationBootstrapBindingElementsBelowSecurityKey = "SecureConversationBootstrapBindingElementsBelowSecurityKey";
3131     }
3132
3133 }