Merge pull request #3389 from lambdageek/bug-43099
[mono.git] / mcs / class / referencesource / System.ServiceModel / System / ServiceModel / Security / WSTrust.cs
1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------
4
5 namespace System.ServiceModel.Security
6 {
7     using System;
8     using System.ServiceModel;
9     using System.ServiceModel.Description;
10     using System.ServiceModel.Dispatcher;
11     using System.Collections;
12     using System.Collections.Generic;
13     using System.Collections.ObjectModel;
14     using System.Diagnostics;
15     using System.Globalization;
16     using System.IO;
17     using System.Text;
18     using System.Threading;
19     using System.Xml;
20     using System.Runtime;
21     using System.Security.Cryptography;
22     using System.IdentityModel.Claims;
23     using System.IdentityModel.Policy;
24     using System.IdentityModel.Selectors;
25     using System.IdentityModel.Tokens;
26     using System.Security.Cryptography.X509Certificates;
27     using System.ServiceModel.Security.Tokens;
28     using HexBinary = System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary;
29     using System.ServiceModel.Channels;
30     using System.ServiceModel.Security;
31     using System.Runtime.Serialization;
32
33     using KeyIdentifierEntry = WSSecurityTokenSerializer.KeyIdentifierEntry;
34     using KeyIdentifierClauseEntry = WSSecurityTokenSerializer.KeyIdentifierClauseEntry;
35     using TokenEntry = WSSecurityTokenSerializer.TokenEntry;
36     using StrEntry = WSSecurityTokenSerializer.StrEntry;
37     using Psha1DerivedKeyGenerator = System.IdentityModel.Psha1DerivedKeyGenerator;
38
39     abstract class WSTrust : WSSecurityTokenSerializer.SerializerEntries
40     {
41         WSSecurityTokenSerializer tokenSerializer;
42
43         public WSTrust(WSSecurityTokenSerializer tokenSerializer)
44         {
45             this.tokenSerializer = tokenSerializer;
46         }
47
48         public WSSecurityTokenSerializer WSSecurityTokenSerializer
49         {
50             get { return this.tokenSerializer; }
51         }
52
53         public abstract TrustDictionary SerializerDictionary
54         {
55             get;
56         }
57
58         public override void PopulateTokenEntries(IList<TokenEntry> tokenEntryList)
59         {
60             tokenEntryList.Add(new BinarySecretTokenEntry(this));
61         }
62
63         class BinarySecretTokenEntry : TokenEntry
64         {
65             WSTrust parent;
66             TrustDictionary otherDictionary;
67
68             public BinarySecretTokenEntry(WSTrust parent)
69             {
70                 this.parent = parent;
71                 this.otherDictionary = null;
72
73                 if (parent.SerializerDictionary is TrustDec2005Dictionary)
74                 {
75                     this.otherDictionary = XD.TrustFeb2005Dictionary;
76                 }
77
78                 if (parent.SerializerDictionary is TrustFeb2005Dictionary)
79                 {
80                     this.otherDictionary = DXD.TrustDec2005Dictionary;
81                 }
82
83                 // always set it, so we don't have to worry about null
84                 if (this.otherDictionary == null)
85                     this.otherDictionary = this.parent.SerializerDictionary;
86             }
87
88             protected override XmlDictionaryString LocalName { get { return parent.SerializerDictionary.BinarySecret; } }
89             protected override XmlDictionaryString NamespaceUri { get { return parent.SerializerDictionary.Namespace; } }
90             protected override Type[] GetTokenTypesCore() { return new Type[] { typeof(BinarySecretSecurityToken) }; }
91             public override string TokenTypeUri { get { return null; } }
92             protected override string ValueTypeUri { get { return null; } }
93
94             public override bool CanReadTokenCore(XmlElement element)
95             {
96                 string valueTypeUri = null;
97
98                 if (element.HasAttribute(SecurityJan2004Strings.ValueType, null))
99                 {
100                     valueTypeUri = element.GetAttribute(SecurityJan2004Strings.ValueType, null);
101                 }
102
103                 return element.LocalName == LocalName.Value && (element.NamespaceURI == NamespaceUri.Value || element.NamespaceURI == this.otherDictionary.Namespace.Value) && valueTypeUri == this.ValueTypeUri;
104             }
105
106             public override bool CanReadTokenCore(XmlDictionaryReader reader)
107             {
108                 return (reader.IsStartElement(this.LocalName, this.NamespaceUri) || reader.IsStartElement(this.LocalName, this.otherDictionary.Namespace)) &&
109                        reader.GetAttribute(XD.SecurityJan2004Dictionary.ValueType, null) == this.ValueTypeUri;
110             }
111
112
113             public override SecurityKeyIdentifierClause CreateKeyIdentifierClauseFromTokenXmlCore(XmlElement issuedTokenXml,
114                 SecurityTokenReferenceStyle tokenReferenceStyle)
115             {
116                 TokenReferenceStyleHelper.Validate(tokenReferenceStyle);
117
118                 switch (tokenReferenceStyle)
119                 {
120                     case SecurityTokenReferenceStyle.Internal:
121                         return CreateDirectReference(issuedTokenXml, UtilityStrings.IdAttribute, UtilityStrings.Namespace, typeof(GenericXmlSecurityToken));
122                     case SecurityTokenReferenceStyle.External:
123                         // Binary Secret tokens aren't referred to externally
124                         return null;
125                     default:
126                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("tokenReferenceStyle"));
127                 }
128             }
129
130             public override SecurityToken ReadTokenCore(XmlDictionaryReader reader, SecurityTokenResolver tokenResolver)
131             {
132                 string secretType = reader.GetAttribute(XD.SecurityJan2004Dictionary.TypeAttribute, null);
133                 string id = reader.GetAttribute(XD.UtilityDictionary.IdAttribute, XD.UtilityDictionary.Namespace);
134                 bool isNonce = false;
135
136                 if (secretType != null && secretType.Length > 0)
137                 {
138                     if (secretType == parent.SerializerDictionary.NonceBinarySecret.Value || secretType == otherDictionary.NonceBinarySecret.Value)
139                     {
140                         isNonce = true;
141                     }
142                     else if (secretType != parent.SerializerDictionary.SymmetricKeyBinarySecret.Value && secretType != otherDictionary.SymmetricKeyBinarySecret.Value)
143                     {
144                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.UnexpectedBinarySecretType, parent.SerializerDictionary.SymmetricKeyBinarySecret.Value, secretType)));
145                     }
146                 }
147
148                 byte[] secret = reader.ReadElementContentAsBase64();
149                 if (isNonce)
150                 {
151                     return new NonceToken(id, secret);
152                 }
153                 else
154                 {
155                     return new BinarySecretSecurityToken(id, secret);
156                 }
157             }
158
159             public override void WriteTokenCore(XmlDictionaryWriter writer, SecurityToken token)
160             {
161                 BinarySecretSecurityToken simpleToken = token as BinarySecretSecurityToken;
162                 byte[] secret = simpleToken.GetKeyBytes();
163                 writer.WriteStartElement(parent.SerializerDictionary.Prefix.Value, parent.SerializerDictionary.BinarySecret, parent.SerializerDictionary.Namespace);
164                 if (simpleToken.Id != null)
165                 {
166                     writer.WriteAttributeString(XD.UtilityDictionary.Prefix.Value, XD.UtilityDictionary.IdAttribute, XD.UtilityDictionary.Namespace, simpleToken.Id);
167                 }
168                 if (token is NonceToken)
169                 {
170                     writer.WriteAttributeString(XD.SecurityJan2004Dictionary.TypeAttribute, null, parent.SerializerDictionary.NonceBinarySecret.Value);
171                 }
172                 writer.WriteBase64(secret, 0, secret.Length);
173                 writer.WriteEndElement();
174             }
175
176         }
177
178         public abstract class Driver : TrustDriver
179         {
180             static readonly string base64Uri = SecurityJan2004Strings.EncodingTypeValueBase64Binary;
181             static readonly string hexBinaryUri = SecurityJan2004Strings.EncodingTypeValueHexBinary;
182
183
184             SecurityStandardsManager standardsManager;
185             List<SecurityTokenAuthenticator> entropyAuthenticators;
186
187             public Driver(SecurityStandardsManager standardsManager)
188             {
189                 this.standardsManager = standardsManager;
190                 this.entropyAuthenticators = new List<SecurityTokenAuthenticator>(2);
191             }
192
193             public abstract TrustDictionary DriverDictionary
194             {
195                 get;
196             }
197
198             public override XmlDictionaryString RequestSecurityTokenAction
199             {
200                 get
201                 {
202                     return DriverDictionary.RequestSecurityTokenIssuance;
203                 }
204             }
205
206             public override XmlDictionaryString RequestSecurityTokenResponseAction
207             {
208                 get
209                 {
210                     return DriverDictionary.RequestSecurityTokenIssuanceResponse;
211                 }
212             }
213
214             public override string RequestTypeIssue
215             {
216                 get
217                 {
218                     return DriverDictionary.RequestTypeIssue.Value;
219                 }
220             }
221
222             public override string ComputedKeyAlgorithm
223             {
224                 get { return DriverDictionary.Psha1ComputedKeyUri.Value; }
225             }
226
227             public override SecurityStandardsManager StandardsManager
228             {
229                 get
230                 {
231                     return this.standardsManager;
232                 }
233             }
234
235             public override XmlDictionaryString Namespace
236             {
237                 get { return DriverDictionary.Namespace; }
238             }
239
240             public override RequestSecurityToken CreateRequestSecurityToken(XmlReader xmlReader)
241             {
242                 XmlDictionaryReader reader = XmlDictionaryReader.CreateDictionaryReader(xmlReader);
243                 reader.MoveToStartElement(DriverDictionary.RequestSecurityToken, DriverDictionary.Namespace);
244                 string context = null;
245                 string tokenTypeUri = null;
246                 string requestType = null;
247                 int keySize = 0;
248                 XmlDocument doc = new XmlDocument();
249                 XmlElement rstXml = (doc.ReadNode(reader) as XmlElement);
250                 SecurityKeyIdentifierClause renewTarget = null;
251                 SecurityKeyIdentifierClause closeTarget = null;
252                 for (int i = 0; i < rstXml.Attributes.Count; ++i)
253                 {
254                     XmlAttribute attr = rstXml.Attributes[i];
255                     if (attr.LocalName == DriverDictionary.Context.Value)
256                     {
257                         context = attr.Value;
258                     }
259                 }
260                 for (int i = 0; i < rstXml.ChildNodes.Count; ++i)
261                 {
262                     XmlElement child = (rstXml.ChildNodes[i] as XmlElement);
263                     if (child != null)
264                     {
265                         if (child.LocalName == DriverDictionary.TokenType.Value && child.NamespaceURI == DriverDictionary.Namespace.Value)
266                             tokenTypeUri = XmlHelper.ReadTextElementAsTrimmedString(child);
267                         else if (child.LocalName == DriverDictionary.RequestType.Value && child.NamespaceURI == DriverDictionary.Namespace.Value)
268                             requestType = XmlHelper.ReadTextElementAsTrimmedString(child);
269                         else if (child.LocalName == DriverDictionary.KeySize.Value && child.NamespaceURI == DriverDictionary.Namespace.Value)
270                             keySize = Int32.Parse(XmlHelper.ReadTextElementAsTrimmedString(child), NumberFormatInfo.InvariantInfo);
271                     }
272                 }
273
274                 ReadTargets(rstXml, out renewTarget, out closeTarget);
275
276                 RequestSecurityToken rst = new RequestSecurityToken(standardsManager, rstXml, context, tokenTypeUri, requestType, keySize, renewTarget, closeTarget);
277                 return rst;
278             }
279
280             System.IdentityModel.XmlBuffer GetIssuedTokenBuffer(System.IdentityModel.XmlBuffer rstrBuffer)
281             {
282                 System.IdentityModel.XmlBuffer issuedTokenBuffer = null;
283                 using (XmlDictionaryReader reader = rstrBuffer.GetReader(0))
284                 {
285                     reader.ReadFullStartElement();
286                     while (reader.IsStartElement())
287                     {
288                         if (reader.IsStartElement(this.DriverDictionary.RequestedSecurityToken, this.DriverDictionary.Namespace))
289                         {
290                             reader.ReadStartElement();
291                             reader.MoveToContent();
292                             issuedTokenBuffer = new System.IdentityModel.XmlBuffer(Int32.MaxValue);
293                             using (XmlDictionaryWriter writer = issuedTokenBuffer.OpenSection(reader.Quotas))
294                             {
295                                 writer.WriteNode(reader, false);
296                                 issuedTokenBuffer.CloseSection();
297                                 issuedTokenBuffer.Close();
298                             }
299                             reader.ReadEndElement();
300                             break;
301                         }
302                         else
303                         {
304                             reader.Skip();
305                         }
306                     }
307                 }
308                 return issuedTokenBuffer;
309             }
310
311             public override RequestSecurityTokenResponse CreateRequestSecurityTokenResponse(XmlReader xmlReader)
312             {
313                 if (xmlReader == null)
314                 {
315                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("xmlReader");
316                 }
317                 XmlDictionaryReader reader = XmlDictionaryReader.CreateDictionaryReader(xmlReader);
318                 if (reader.IsStartElement(DriverDictionary.RequestSecurityTokenResponse, DriverDictionary.Namespace) == false)
319                 {
320                     XmlHelper.OnRequiredElementMissing(DriverDictionary.RequestSecurityTokenResponse.Value, DriverDictionary.Namespace.Value);
321                 }
322
323                 System.IdentityModel.XmlBuffer rstrBuffer = new System.IdentityModel.XmlBuffer(Int32.MaxValue);
324                 using (XmlDictionaryWriter writer = rstrBuffer.OpenSection(reader.Quotas))
325                 {
326                     writer.WriteNode(reader, false);
327                     rstrBuffer.CloseSection();
328                     rstrBuffer.Close();
329                 }
330                 XmlDocument doc = new XmlDocument();
331                 XmlElement rstrXml;
332                 using (XmlReader reader2 = rstrBuffer.GetReader(0))
333                 {
334                     rstrXml = (doc.ReadNode(reader2) as XmlElement);
335                 }
336
337                 System.IdentityModel.XmlBuffer issuedTokenBuffer = GetIssuedTokenBuffer(rstrBuffer);
338                 string context = null;
339                 string tokenTypeUri = null;
340                 int keySize = 0;
341                 SecurityKeyIdentifierClause requestedAttachedReference = null;
342                 SecurityKeyIdentifierClause requestedUnattachedReference = null;
343                 bool computeKey = false;
344                 DateTime created = DateTime.UtcNow;
345                 DateTime expires = SecurityUtils.MaxUtcDateTime;
346                 bool isRequestedTokenClosed = false;
347                 for (int i = 0; i < rstrXml.Attributes.Count; ++i)
348                 {
349                     XmlAttribute attr = rstrXml.Attributes[i];
350                     if (attr.LocalName == DriverDictionary.Context.Value)
351                     {
352                         context = attr.Value;
353                     }
354                 }
355
356                 for (int i = 0; i < rstrXml.ChildNodes.Count; ++i)
357                 {
358                     XmlElement child = (rstrXml.ChildNodes[i] as XmlElement);
359                     if (child != null)
360                     {
361                         if (child.LocalName == DriverDictionary.TokenType.Value && child.NamespaceURI == DriverDictionary.Namespace.Value)
362                             tokenTypeUri = XmlHelper.ReadTextElementAsTrimmedString(child);
363                         else if (child.LocalName == DriverDictionary.KeySize.Value && child.NamespaceURI == DriverDictionary.Namespace.Value)
364                             keySize = Int32.Parse(XmlHelper.ReadTextElementAsTrimmedString(child), NumberFormatInfo.InvariantInfo);
365                         else if (child.LocalName == DriverDictionary.RequestedProofToken.Value && child.NamespaceURI == DriverDictionary.Namespace.Value)
366                         {
367                             XmlElement proofXml = XmlHelper.GetChildElement(child);
368                             if (proofXml.LocalName == DriverDictionary.ComputedKey.Value && proofXml.NamespaceURI == DriverDictionary.Namespace.Value)
369                             {
370                                 string computedKeyAlgorithm = XmlHelper.ReadTextElementAsTrimmedString(proofXml);
371                                 if (computedKeyAlgorithm != this.DriverDictionary.Psha1ComputedKeyUri.Value)
372                                 {
373                                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new SecurityNegotiationException(SR.GetString(SR.UnknownComputedKeyAlgorithm, computedKeyAlgorithm)));
374                                 }
375                                 computeKey = true;
376                             }
377                         }
378                         else if (child.LocalName == DriverDictionary.Lifetime.Value && child.NamespaceURI == DriverDictionary.Namespace.Value)
379                         {
380                             XmlElement createdXml = XmlHelper.GetChildElement(child, UtilityStrings.CreatedElement, UtilityStrings.Namespace);
381                             if (createdXml != null)
382                             {
383                                 created = DateTime.ParseExact(XmlHelper.ReadTextElementAsTrimmedString(createdXml),
384                                     WSUtilitySpecificationVersion.AcceptedDateTimeFormats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None).ToUniversalTime();
385                             }
386                             XmlElement expiresXml = XmlHelper.GetChildElement(child, UtilityStrings.ExpiresElement, UtilityStrings.Namespace);
387                             if (expiresXml != null)
388                             {
389                                 expires = DateTime.ParseExact(XmlHelper.ReadTextElementAsTrimmedString(expiresXml),
390                                     WSUtilitySpecificationVersion.AcceptedDateTimeFormats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None).ToUniversalTime();
391                             }
392                         }
393                     }
394                 }
395
396                 isRequestedTokenClosed = ReadRequestedTokenClosed(rstrXml);
397                 ReadReferences(rstrXml, out requestedAttachedReference, out requestedUnattachedReference);
398
399                 return new RequestSecurityTokenResponse(standardsManager, rstrXml, context, tokenTypeUri, keySize, requestedAttachedReference, requestedUnattachedReference,
400                                                         computeKey, created, expires, isRequestedTokenClosed, issuedTokenBuffer);
401             }
402
403             public override RequestSecurityTokenResponseCollection CreateRequestSecurityTokenResponseCollection(XmlReader xmlReader)
404             {
405                 XmlDictionaryReader reader = XmlDictionaryReader.CreateDictionaryReader(xmlReader);
406                 List<RequestSecurityTokenResponse> rstrCollection = new List<RequestSecurityTokenResponse>(2);
407                 string rootName = reader.Name;
408                 reader.ReadStartElement(DriverDictionary.RequestSecurityTokenResponseCollection, DriverDictionary.Namespace);
409                 while (reader.IsStartElement(DriverDictionary.RequestSecurityTokenResponse.Value, DriverDictionary.Namespace.Value))
410                 {
411                     RequestSecurityTokenResponse rstr = this.CreateRequestSecurityTokenResponse(reader);
412                     rstrCollection.Add(rstr);
413                 }
414                 reader.ReadEndElement();
415                 if (rstrCollection.Count == 0)
416                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.NoRequestSecurityTokenResponseElements)));
417                 return new RequestSecurityTokenResponseCollection(rstrCollection.AsReadOnly(), this.StandardsManager);
418             }
419
420             XmlElement GetAppliesToElement(XmlElement rootElement)
421             {
422                 if (rootElement == null)
423                 {
424                     return null;
425                 }
426                 for (int i = 0; i < rootElement.ChildNodes.Count; ++i)
427                 {
428                     XmlElement elem = (rootElement.ChildNodes[i] as XmlElement);
429                     if (elem != null)
430                     {
431                         if (elem.LocalName == DriverDictionary.AppliesTo.Value && elem.NamespaceURI == Namespaces.WSPolicy)
432                         {
433                             return elem;
434                         }
435                     }
436                 }
437                 return null;
438             }
439
440             T GetAppliesTo<T>(XmlElement rootXml, XmlObjectSerializer serializer)
441             {
442                 XmlElement appliesToElement = GetAppliesToElement(rootXml);
443                 if (appliesToElement != null)
444                 {
445                     using (XmlReader reader = new XmlNodeReader(appliesToElement))
446                     {
447                         reader.ReadStartElement();
448                         lock (serializer)
449                         {
450                             return (T)serializer.ReadObject(reader);
451                         }
452                     }
453                 }
454                 else
455                 {
456                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.NoAppliesToPresent)));
457                 }
458             }
459
460             public override T GetAppliesTo<T>(RequestSecurityToken rst, XmlObjectSerializer serializer)
461             {
462                 if (rst == null)
463                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("rst");
464
465                 return GetAppliesTo<T>(rst.RequestSecurityTokenXml, serializer);
466             }
467
468             public override T GetAppliesTo<T>(RequestSecurityTokenResponse rstr, XmlObjectSerializer serializer)
469             {
470                 if (rstr == null)
471                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("rstr");
472
473                 return GetAppliesTo<T>(rstr.RequestSecurityTokenResponseXml, serializer);
474             }
475
476             public override bool IsAppliesTo(string localName, string namespaceUri)
477             {
478                 return (localName == DriverDictionary.AppliesTo.Value && namespaceUri == Namespaces.WSPolicy);
479             }
480
481             void GetAppliesToQName(XmlElement rootElement, out string localName, out string namespaceUri)
482             {
483                 localName = namespaceUri = null;
484                 XmlElement appliesToElement = GetAppliesToElement(rootElement);
485                 if (appliesToElement != null)
486                 {
487                     using (XmlReader reader = new XmlNodeReader(appliesToElement))
488                     {
489                         reader.ReadStartElement();
490                         reader.MoveToContent();
491                         localName = reader.LocalName;
492                         namespaceUri = reader.NamespaceURI;
493                     }
494                 }
495             }
496
497             public override void GetAppliesToQName(RequestSecurityToken rst, out string localName, out string namespaceUri)
498             {
499                 if (rst == null)
500                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("rst");
501
502                 GetAppliesToQName(rst.RequestSecurityTokenXml, out localName, out namespaceUri);
503             }
504
505             public override void GetAppliesToQName(RequestSecurityTokenResponse rstr, out string localName, out string namespaceUri)
506             {
507                 if (rstr == null)
508                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("rstr");
509
510                 GetAppliesToQName(rstr.RequestSecurityTokenResponseXml, out localName, out namespaceUri);
511             }
512
513             public override byte[] GetAuthenticator(RequestSecurityTokenResponse rstr)
514             {
515                 if (rstr != null && rstr.RequestSecurityTokenResponseXml != null && rstr.RequestSecurityTokenResponseXml.ChildNodes != null)
516                 {
517                     for (int i = 0; i < rstr.RequestSecurityTokenResponseXml.ChildNodes.Count; ++i)
518                     {
519                         XmlElement element = rstr.RequestSecurityTokenResponseXml.ChildNodes[i] as XmlElement;
520                         if (element != null)
521                         {
522                             if (element.LocalName == DriverDictionary.Authenticator.Value && element.NamespaceURI == DriverDictionary.Namespace.Value)
523                             {
524                                 XmlElement combinedHashElement = XmlHelper.GetChildElement(element);
525                                 if (combinedHashElement.LocalName == DriverDictionary.CombinedHash.Value && combinedHashElement.NamespaceURI == DriverDictionary.Namespace.Value)
526                                 {
527                                     string authenticatorString = XmlHelper.ReadTextElementAsTrimmedString(combinedHashElement);
528                                     return Convert.FromBase64String(authenticatorString);
529                                 }
530                             }
531                         }
532                     }
533                 }
534                 return null;
535             }
536
537             public override BinaryNegotiation GetBinaryNegotiation(RequestSecurityTokenResponse rstr)
538             {
539                 if (rstr == null)
540                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("rstr");
541
542                 return GetBinaryNegotiation(rstr.RequestSecurityTokenResponseXml);
543             }
544
545             public override BinaryNegotiation GetBinaryNegotiation(RequestSecurityToken rst)
546             {
547                 if (rst == null)
548                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("rst");
549
550                 return GetBinaryNegotiation(rst.RequestSecurityTokenXml);
551             }
552
553             BinaryNegotiation GetBinaryNegotiation(XmlElement rootElement)
554             {
555                 if (rootElement == null)
556                 {
557                     return null;
558                 }
559                 for (int i = 0; i < rootElement.ChildNodes.Count; ++i)
560                 {
561                     XmlElement elem = rootElement.ChildNodes[i] as XmlElement;
562                     if (elem != null)
563                     {
564                         if (elem.LocalName == DriverDictionary.BinaryExchange.Value && elem.NamespaceURI == DriverDictionary.Namespace.Value)
565                         {
566                             return ReadBinaryNegotiation(elem);
567                         }
568                     }
569                 }
570                 return null;
571             }
572
573             public override SecurityToken GetEntropy(RequestSecurityToken rst, SecurityTokenResolver resolver)
574             {
575                 if (rst == null)
576                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("rst");
577
578                 return GetEntropy(rst.RequestSecurityTokenXml, resolver);
579             }
580
581             public override SecurityToken GetEntropy(RequestSecurityTokenResponse rstr, SecurityTokenResolver resolver)
582             {
583                 if (rstr == null)
584                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("rstr");
585
586                 return GetEntropy(rstr.RequestSecurityTokenResponseXml, resolver);
587             }
588
589             SecurityToken GetEntropy(XmlElement rootElement, SecurityTokenResolver resolver)
590             {
591                 if (rootElement == null || rootElement.ChildNodes == null)
592                 {
593                     return null;
594                 }
595                 for (int i = 0; i < rootElement.ChildNodes.Count; ++i)
596                 {
597                     XmlElement element = rootElement.ChildNodes[i] as XmlElement;
598                     if (element != null)
599                     {
600                         if (element.LocalName == DriverDictionary.Entropy.Value && element.NamespaceURI == DriverDictionary.Namespace.Value)
601                         {
602                             XmlElement tokenXml = XmlHelper.GetChildElement(element);
603                             string valueTypeUri = element.GetAttribute(SecurityJan2004Strings.ValueType);
604                             if (valueTypeUri.Length == 0)
605                                 valueTypeUri = null;
606                             return standardsManager.SecurityTokenSerializer.ReadToken(new XmlNodeReader(tokenXml), resolver);
607                         }
608                     }
609                 }
610                 return null;
611             }
612
613             void GetIssuedAndProofXml(RequestSecurityTokenResponse rstr, out XmlElement issuedTokenXml, out XmlElement proofTokenXml)
614             {
615                 issuedTokenXml = null;
616                 proofTokenXml = null;
617                 if ((rstr.RequestSecurityTokenResponseXml != null) && (rstr.RequestSecurityTokenResponseXml.ChildNodes != null))
618                 {
619                     for (int i = 0; i < rstr.RequestSecurityTokenResponseXml.ChildNodes.Count; ++i)
620                     {
621                         XmlElement elem = rstr.RequestSecurityTokenResponseXml.ChildNodes[i] as XmlElement;
622                         if (elem != null)
623                         {
624                             if (elem.LocalName == DriverDictionary.RequestedSecurityToken.Value && elem.NamespaceURI == DriverDictionary.Namespace.Value)
625                             {
626                                 if (issuedTokenXml != null)
627                                 {
628                                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.RstrHasMultipleIssuedTokens)));
629                                 }
630                                 issuedTokenXml = XmlHelper.GetChildElement(elem);
631                             }
632                             else if (elem.LocalName == DriverDictionary.RequestedProofToken.Value && elem.NamespaceURI == DriverDictionary.Namespace.Value)
633                             {
634                                 if (proofTokenXml != null)
635                                 {
636                                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.RstrHasMultipleProofTokens)));
637                                 }
638                                 proofTokenXml = XmlHelper.GetChildElement(elem);
639                             }
640                         }
641                     }
642                 }
643             }
644
645             /// <summary>
646             /// The algorithm for computing the key is:
647             /// 1. If there is requestorEntropy:
648             ///    a. If there is no <RequestedProofToken> use the requestorEntropy as the key
649             ///    b. If there is a <RequestedProofToken> with a ComputedKeyUri, combine the client and server entropies
650             ///    c. Anything else, throw
651             /// 2. If there is no requestorEntropy:
652             ///    a. THere has to be a <RequestedProofToken> that contains the proof key
653             /// </summary>
654             public override GenericXmlSecurityToken GetIssuedToken(RequestSecurityTokenResponse rstr, SecurityTokenResolver resolver, IList<SecurityTokenAuthenticator> allowedAuthenticators, SecurityKeyEntropyMode keyEntropyMode, byte[] requestorEntropy, string expectedTokenType,
655                 ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies, int defaultKeySize, bool isBearerKeyType)
656             {
657
658                 SecurityKeyEntropyModeHelper.Validate(keyEntropyMode);
659
660                 if (defaultKeySize < 0)
661                 {
662                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("defaultKeySize", SR.GetString(SR.ValueMustBeNonNegative)));
663                 }
664
665                 if (rstr == null)
666                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("rstr");
667
668                 string tokenType;
669                 if (rstr.TokenType != null)
670                 {
671                     if (expectedTokenType != null && expectedTokenType != rstr.TokenType)
672                     {
673                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.BadIssuedTokenType, rstr.TokenType, expectedTokenType)));
674                     }
675                     tokenType = rstr.TokenType;
676                 }
677                 else
678                 {
679                     tokenType = expectedTokenType;
680                 }
681
682                 // search the response elements for licenseXml, proofXml, and lifetime
683                 DateTime created = rstr.ValidFrom;
684                 DateTime expires = rstr.ValidTo;
685                 XmlElement proofXml;
686                 XmlElement issuedTokenXml;
687                 GetIssuedAndProofXml(rstr, out issuedTokenXml, out proofXml);
688
689                 if (issuedTokenXml == null)
690                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.NoLicenseXml)));
691
692                 if (isBearerKeyType)
693                 {
694                     if (proofXml != null)
695                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.BearerKeyTypeCannotHaveProofKey)));
696
697                     return new GenericXmlSecurityToken(issuedTokenXml, null, created, expires, rstr.RequestedAttachedReference, rstr.RequestedUnattachedReference, authorizationPolicies);
698                 }
699
700                 SecurityToken proofToken;
701                 SecurityToken entropyToken = GetEntropy(rstr, resolver);
702                 if (keyEntropyMode == SecurityKeyEntropyMode.ClientEntropy)
703                 {
704                     if (requestorEntropy == null)
705                     {
706                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.EntropyModeRequiresRequestorEntropy, keyEntropyMode)));
707                     }
708                     // enforce that there is no entropy or proof token in the RSTR
709                     if (proofXml != null || entropyToken != null)
710                     {
711                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.EntropyModeCannotHaveProofTokenOrIssuerEntropy, keyEntropyMode)));
712                     }
713                     proofToken = new BinarySecretSecurityToken(requestorEntropy);
714                 }
715                 else if (keyEntropyMode == SecurityKeyEntropyMode.ServerEntropy)
716                 {
717                     if (requestorEntropy != null)
718                     {
719                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.EntropyModeCannotHaveRequestorEntropy, keyEntropyMode)));
720                     }
721                     if (rstr.ComputeKey || entropyToken != null)
722                     {
723                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.EntropyModeCannotHaveComputedKey, keyEntropyMode)));
724                     }
725                     if (proofXml == null)
726                     {
727                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.EntropyModeRequiresProofToken, keyEntropyMode)));
728                     }
729                     string valueTypeUri = proofXml.GetAttribute(SecurityJan2004Strings.ValueType);
730                     if (valueTypeUri.Length == 0)
731                         valueTypeUri = null;
732                     proofToken = standardsManager.SecurityTokenSerializer.ReadToken(new XmlNodeReader(proofXml), resolver);
733                 }
734                 else
735                 {
736                     if (!rstr.ComputeKey)
737                     {
738                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.EntropyModeRequiresComputedKey, keyEntropyMode)));
739                     }
740                     if (entropyToken == null)
741                     {
742                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.EntropyModeRequiresIssuerEntropy, keyEntropyMode)));
743                     }
744                     if (requestorEntropy == null)
745                     {
746                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.EntropyModeRequiresRequestorEntropy, keyEntropyMode)));
747                     }
748                     if (rstr.KeySize == 0 && defaultKeySize == 0)
749                     {
750                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.RstrKeySizeNotProvided)));
751                     }
752                     int issuedKeySize = (rstr.KeySize != 0) ? rstr.KeySize : defaultKeySize;
753                     byte[] issuerEntropy;
754                     if (entropyToken is BinarySecretSecurityToken)
755                         issuerEntropy = ((BinarySecretSecurityToken)entropyToken).GetKeyBytes();
756                     else if (entropyToken is WrappedKeySecurityToken)
757                         issuerEntropy = ((WrappedKeySecurityToken)entropyToken).GetWrappedKey();
758                     else
759                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.UnsupportedIssuerEntropyType)));
760                     // compute the PSHA1 derived key
761                     byte[] issuedKey = RequestSecurityTokenResponse.ComputeCombinedKey(requestorEntropy, issuerEntropy, issuedKeySize);
762                     proofToken = new BinarySecretSecurityToken(issuedKey);
763                 }
764
765                 SecurityKeyIdentifierClause internalReference = rstr.RequestedAttachedReference;
766                 SecurityKeyIdentifierClause externalReference = rstr.RequestedUnattachedReference;
767
768                 return new BufferedGenericXmlSecurityToken(issuedTokenXml, proofToken, created, expires, internalReference, externalReference, authorizationPolicies, rstr.IssuedTokenBuffer);
769             }
770
771             public override GenericXmlSecurityToken GetIssuedToken(RequestSecurityTokenResponse rstr, string expectedTokenType,
772                 ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies, RSA clientKey)
773             {
774                 if (rstr == null)
775                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("rstr"));
776
777                 string tokenType;
778                 if (rstr.TokenType != null)
779                 {
780                     if (expectedTokenType != null && expectedTokenType != rstr.TokenType)
781                     {
782                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.BadIssuedTokenType, rstr.TokenType, expectedTokenType)));
783                     }
784                     tokenType = rstr.TokenType;
785                 }
786                 else
787                 {
788                     tokenType = expectedTokenType;
789                 }
790
791                 // search the response elements for licenseXml, proofXml, and lifetime
792                 DateTime created = rstr.ValidFrom;
793                 DateTime expires = rstr.ValidTo;
794                 XmlElement proofXml;
795                 XmlElement issuedTokenXml;
796                 GetIssuedAndProofXml(rstr, out issuedTokenXml, out proofXml);
797
798                 if (issuedTokenXml == null)
799                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.NoLicenseXml)));
800
801                 // enforce that there is no proof token in the RSTR
802                 if (proofXml != null)
803                 {
804                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ProofTokenXmlUnexpectedInRstr)));
805                 }
806                 SecurityKeyIdentifierClause internalReference = rstr.RequestedAttachedReference;
807                 SecurityKeyIdentifierClause externalReference = rstr.RequestedUnattachedReference;
808
809                 SecurityToken proofToken = new RsaSecurityToken(clientKey);
810                 return new BufferedGenericXmlSecurityToken(issuedTokenXml, proofToken, created, expires, internalReference, externalReference, authorizationPolicies, rstr.IssuedTokenBuffer);
811             }
812
813             public override bool IsAtRequestSecurityTokenResponse(XmlReader reader)
814             {
815                 if (reader == null)
816                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
817
818                 return reader.IsStartElement(DriverDictionary.RequestSecurityTokenResponse.Value, DriverDictionary.Namespace.Value);
819             }
820
821             public override bool IsAtRequestSecurityTokenResponseCollection(XmlReader reader)
822             {
823                 if (reader == null)
824                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
825
826                 return reader.IsStartElement(DriverDictionary.RequestSecurityTokenResponseCollection.Value, DriverDictionary.Namespace.Value);
827             }
828
829             public override bool IsRequestedSecurityTokenElement(string name, string nameSpace)
830             {
831                 return (name == DriverDictionary.RequestedSecurityToken.Value && nameSpace == DriverDictionary.Namespace.Value);
832             }
833
834             public override bool IsRequestedProofTokenElement(string name, string nameSpace)
835             {
836                 return (name == DriverDictionary.RequestedProofToken.Value && nameSpace == DriverDictionary.Namespace.Value);
837             }
838
839             public static BinaryNegotiation ReadBinaryNegotiation(XmlElement elem)
840             {
841                 if (elem == null)
842                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("elem");
843
844                 // get the encoding and valueType attributes
845                 string encodingUri = null;
846                 string valueTypeUri = null;
847                 byte[] negotiationData = null;
848                 if (elem.Attributes != null)
849                 {
850                     for (int i = 0; i < elem.Attributes.Count; ++i)
851                     {
852                         XmlAttribute attr = elem.Attributes[i];
853                         if (attr.LocalName == SecurityJan2004Strings.EncodingType && attr.NamespaceURI.Length == 0)
854                         {
855                             encodingUri = attr.Value;
856                             if (encodingUri != base64Uri && encodingUri != hexBinaryUri)
857                             {
858                                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.UnsupportedBinaryEncoding, encodingUri)));
859                             }
860                         }
861                         else if (attr.LocalName == SecurityJan2004Strings.ValueType && attr.NamespaceURI.Length == 0)
862                         {
863                             valueTypeUri = attr.Value;
864                         }
865                         // ignore all other attributes
866                     }
867                 }
868                 if (encodingUri == null)
869                 {
870                     XmlHelper.OnRequiredAttributeMissing("EncodingType", elem.Name);
871                 }
872                 if (valueTypeUri == null)
873                 {
874                     XmlHelper.OnRequiredAttributeMissing("ValueType", elem.Name);
875                 }
876                 string encodedBlob = XmlHelper.ReadTextElementAsTrimmedString(elem);
877                 if (encodingUri == base64Uri)
878                 {
879                     negotiationData = Convert.FromBase64String(encodedBlob);
880                 }
881                 else
882                 {
883                     negotiationData = HexBinary.Parse(encodedBlob).Value;
884                 }
885                 return new BinaryNegotiation(valueTypeUri, negotiationData);
886             }
887
888             // Note in Apr2004, internal & external references aren't supported - 
889             // our strategy is to see if there's a token reference (and use it for external ref) and backup is to scan the token xml to compute reference
890             protected virtual void ReadReferences(XmlElement rstrXml, out SecurityKeyIdentifierClause requestedAttachedReference,
891                     out SecurityKeyIdentifierClause requestedUnattachedReference)
892             {
893                 XmlElement issuedTokenXml = null;
894                 requestedAttachedReference = null;
895                 requestedUnattachedReference = null;
896                 for (int i = 0; i < rstrXml.ChildNodes.Count; ++i)
897                 {
898                     XmlElement child = rstrXml.ChildNodes[i] as XmlElement;
899                     if (child != null)
900                     {
901                         if (child.LocalName == DriverDictionary.RequestedSecurityToken.Value && child.NamespaceURI == DriverDictionary.Namespace.Value)
902                         {
903                             issuedTokenXml = XmlHelper.GetChildElement(child);
904                         }
905                         else if (child.LocalName == DriverDictionary.RequestedTokenReference.Value && child.NamespaceURI == DriverDictionary.Namespace.Value)
906                         {
907                             requestedUnattachedReference = GetKeyIdentifierXmlReferenceClause(XmlHelper.GetChildElement(child));
908                         }
909                     }
910                 }
911
912                 if (issuedTokenXml != null)
913                 {
914                     requestedAttachedReference = standardsManager.CreateKeyIdentifierClauseFromTokenXml(issuedTokenXml, SecurityTokenReferenceStyle.Internal);
915                     if (requestedUnattachedReference == null)
916                     {
917                         try
918                         {
919                             requestedUnattachedReference = standardsManager.CreateKeyIdentifierClauseFromTokenXml(issuedTokenXml, SecurityTokenReferenceStyle.External);
920                         }
921                         catch (XmlException)
922                         {
923                             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.TrustDriverIsUnableToCreatedNecessaryAttachedOrUnattachedReferences, issuedTokenXml.ToString())));
924                         }
925                     }
926                 }
927             }
928
929             internal bool TryReadKeyIdentifierClause(XmlNodeReader reader, out SecurityKeyIdentifierClause keyIdentifierClause)
930             {
931                 keyIdentifierClause = null;
932
933                 try
934                 {
935                     keyIdentifierClause = standardsManager.SecurityTokenSerializer.ReadKeyIdentifierClause(reader);
936                 }
937                 catch (XmlException e)
938                 {
939                     if (Fx.IsFatal(e))
940                     {
941                         throw;
942                     }
943
944                     keyIdentifierClause = null;
945                     return false;
946                 }
947                 catch (Exception e)
948                 {
949                     if (Fx.IsFatal(e))
950                     {
951                         throw;
952                     }
953
954                     keyIdentifierClause = null;
955                     return false;
956                 }
957
958                 return true;
959             }
960
961             internal SecurityKeyIdentifierClause CreateGenericXmlSecurityKeyIdentifierClause(XmlNodeReader reader, XmlElement keyIdentifierReferenceXmlElement)
962             {
963                 SecurityKeyIdentifierClause keyIdentifierClause = null;
964                 XmlDictionaryReader localReader = XmlDictionaryReader.CreateDictionaryReader(reader);
965                 string strId = localReader.GetAttribute(XD.UtilityDictionary.IdAttribute, XD.UtilityDictionary.Namespace);
966                 keyIdentifierClause = new GenericXmlSecurityKeyIdentifierClause(keyIdentifierReferenceXmlElement);
967                 if (!String.IsNullOrEmpty(strId))
968                 {
969                     keyIdentifierClause.Id = strId;
970                 }
971                 return keyIdentifierClause;
972             }
973
974             internal SecurityKeyIdentifierClause GetKeyIdentifierXmlReferenceClause(XmlElement keyIdentifierReferenceXmlElement)
975             {
976                 SecurityKeyIdentifierClause keyIdentifierClause = null;
977                 XmlNodeReader reader = new XmlNodeReader(keyIdentifierReferenceXmlElement);
978                 if (!this.TryReadKeyIdentifierClause(reader, out keyIdentifierClause))
979                 {
980                     keyIdentifierClause = CreateGenericXmlSecurityKeyIdentifierClause(new XmlNodeReader(keyIdentifierReferenceXmlElement), keyIdentifierReferenceXmlElement);
981                 }
982
983                 return keyIdentifierClause;
984             }
985
986             protected virtual bool ReadRequestedTokenClosed(XmlElement rstrXml)
987             {
988                 return false;
989             }
990
991             protected virtual void ReadTargets(XmlElement rstXml, out SecurityKeyIdentifierClause renewTarget, out SecurityKeyIdentifierClause closeTarget)
992             {
993                 renewTarget = null;
994                 closeTarget = null;
995             }
996
997             public override void OnRSTRorRSTRCMissingException()
998             {
999                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.ExpectedOneOfTwoElementsFromNamespace,
1000                     DriverDictionary.RequestSecurityTokenResponse, DriverDictionary.RequestSecurityTokenResponseCollection,
1001                     DriverDictionary.Namespace)));
1002             }
1003
1004             void WriteAppliesTo(object appliesTo, Type appliesToType, XmlObjectSerializer serializer, XmlWriter xmlWriter)
1005             {
1006                 XmlDictionaryWriter writer = XmlDictionaryWriter.CreateDictionaryWriter(xmlWriter);
1007                 writer.WriteStartElement(Namespaces.WSPolicyPrefix, DriverDictionary.AppliesTo.Value, Namespaces.WSPolicy);
1008                 lock (serializer)
1009                 {
1010                     serializer.WriteObject(writer, appliesTo);
1011                 }
1012                 writer.WriteEndElement();
1013             }
1014
1015             public void WriteBinaryNegotiation(BinaryNegotiation negotiation, XmlWriter xmlWriter)
1016             {
1017                 if (negotiation == null)
1018                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("negotiation");
1019
1020                 XmlDictionaryWriter writer = XmlDictionaryWriter.CreateDictionaryWriter(xmlWriter);
1021                 negotiation.WriteTo(writer, this.DriverDictionary.Prefix.Value,
1022                                             this.DriverDictionary.BinaryExchange, this.DriverDictionary.Namespace,
1023                                             XD.SecurityJan2004Dictionary.ValueType, null);
1024             }
1025
1026             public override void WriteRequestSecurityToken(RequestSecurityToken rst, XmlWriter xmlWriter)
1027             {
1028                 if (rst == null)
1029                 {
1030                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("rst");
1031                 }
1032                 if (xmlWriter == null)
1033                 {
1034                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("xmlWriter");
1035                 }
1036                 XmlDictionaryWriter writer = XmlDictionaryWriter.CreateDictionaryWriter(xmlWriter);
1037                 if (rst.IsReceiver)
1038                 {
1039                     rst.WriteTo(writer);
1040                     return;
1041                 }
1042                 writer.WriteStartElement(DriverDictionary.Prefix.Value, DriverDictionary.RequestSecurityToken, DriverDictionary.Namespace);
1043                 XmlHelper.AddNamespaceDeclaration(writer, DriverDictionary.Prefix.Value, DriverDictionary.Namespace);
1044                 if (rst.Context != null)
1045                     writer.WriteAttributeString(DriverDictionary.Context, null, rst.Context);
1046
1047                 rst.OnWriteCustomAttributes(writer);
1048                 if (rst.TokenType != null)
1049                 {
1050                     writer.WriteStartElement(DriverDictionary.Prefix.Value, DriverDictionary.TokenType, DriverDictionary.Namespace);
1051                     writer.WriteString(rst.TokenType);
1052                     writer.WriteEndElement();
1053                 }
1054                 if (rst.RequestType != null)
1055                 {
1056                     writer.WriteStartElement(DriverDictionary.Prefix.Value, DriverDictionary.RequestType, DriverDictionary.Namespace);
1057                     writer.WriteString(rst.RequestType);
1058                     writer.WriteEndElement();
1059                 }
1060
1061                 if (rst.AppliesTo != null)
1062                 {
1063                     WriteAppliesTo(rst.AppliesTo, rst.AppliesToType, rst.AppliesToSerializer, writer);
1064                 }
1065
1066                 SecurityToken entropyToken = rst.GetRequestorEntropy();
1067                 if (entropyToken != null)
1068                 {
1069                     writer.WriteStartElement(DriverDictionary.Prefix.Value, DriverDictionary.Entropy, DriverDictionary.Namespace);
1070                     standardsManager.SecurityTokenSerializer.WriteToken(writer, entropyToken);
1071                     writer.WriteEndElement();
1072                 }
1073
1074                 if (rst.KeySize != 0)
1075                 {
1076                     writer.WriteStartElement(DriverDictionary.Prefix.Value, DriverDictionary.KeySize, DriverDictionary.Namespace);
1077                     writer.WriteValue(rst.KeySize);
1078                     writer.WriteEndElement();
1079                 }
1080
1081                 BinaryNegotiation negotiationData = rst.GetBinaryNegotiation();
1082                 if (negotiationData != null)
1083                     WriteBinaryNegotiation(negotiationData, writer);
1084
1085                 WriteTargets(rst, writer);
1086
1087                 if (rst.RequestProperties != null)
1088                 {
1089                     foreach (XmlElement property in rst.RequestProperties)
1090                     {
1091                         property.WriteTo(writer);
1092                     }
1093                 }
1094
1095                 rst.OnWriteCustomElements(writer);
1096                 writer.WriteEndElement();
1097             }
1098
1099             protected virtual void WriteTargets(RequestSecurityToken rst, XmlDictionaryWriter writer)
1100             {
1101             }
1102
1103             // Note in Apr2004, internal & external references aren't supported - our strategy is to generate the external ref as the TokenReference.
1104             protected virtual void WriteReferences(RequestSecurityTokenResponse rstr, XmlDictionaryWriter writer)
1105             {
1106                 if (rstr.RequestedUnattachedReference != null)
1107                 {
1108                     writer.WriteStartElement(DriverDictionary.Prefix.Value, DriverDictionary.RequestedTokenReference, DriverDictionary.Namespace);
1109                     standardsManager.SecurityTokenSerializer.WriteKeyIdentifierClause(writer, rstr.RequestedUnattachedReference);
1110                     writer.WriteEndElement();
1111                 }
1112             }
1113
1114             protected virtual void WriteRequestedTokenClosed(RequestSecurityTokenResponse rstr, XmlDictionaryWriter writer)
1115             {
1116             }
1117
1118             public override void WriteRequestSecurityTokenResponse(RequestSecurityTokenResponse rstr, XmlWriter xmlWriter)
1119             {
1120                 if (rstr == null)
1121                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("rstr");
1122                 if (xmlWriter == null)
1123                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("xmlWriter");
1124                 XmlDictionaryWriter writer = XmlDictionaryWriter.CreateDictionaryWriter(xmlWriter);
1125                 if (rstr.IsReceiver)
1126                 {
1127                     rstr.WriteTo(writer);
1128                     return;
1129                 }
1130                 writer.WriteStartElement(DriverDictionary.Prefix.Value, DriverDictionary.RequestSecurityTokenResponse, DriverDictionary.Namespace);
1131                 if (rstr.Context != null)
1132                 {
1133                     writer.WriteAttributeString(DriverDictionary.Context, null, rstr.Context);
1134                 }
1135                 // define WSUtility at the top level to avoid multiple definitions below
1136                 XmlHelper.AddNamespaceDeclaration(writer, UtilityStrings.Prefix, XD.UtilityDictionary.Namespace);
1137                 rstr.OnWriteCustomAttributes(writer);
1138
1139                 if (rstr.TokenType != null)
1140                     writer.WriteElementString(DriverDictionary.Prefix.Value, DriverDictionary.TokenType, DriverDictionary.Namespace, rstr.TokenType);
1141
1142                 if (rstr.RequestedSecurityToken != null)
1143                 {
1144                     writer.WriteStartElement(DriverDictionary.Prefix.Value, DriverDictionary.RequestedSecurityToken, DriverDictionary.Namespace);
1145                     standardsManager.SecurityTokenSerializer.WriteToken(writer, rstr.RequestedSecurityToken);
1146                     writer.WriteEndElement();
1147                 }
1148
1149                 if (rstr.AppliesTo != null)
1150                 {
1151                     WriteAppliesTo(rstr.AppliesTo, rstr.AppliesToType, rstr.AppliesToSerializer, writer);
1152                 }
1153
1154                 WriteReferences(rstr, writer);
1155
1156                 if (rstr.ComputeKey || rstr.RequestedProofToken != null)
1157                 {
1158                     writer.WriteStartElement(DriverDictionary.Prefix.Value, DriverDictionary.RequestedProofToken, DriverDictionary.Namespace);
1159                     if (rstr.ComputeKey)
1160                     {
1161                         writer.WriteElementString(DriverDictionary.Prefix.Value, DriverDictionary.ComputedKey, DriverDictionary.Namespace, DriverDictionary.Psha1ComputedKeyUri.Value);
1162                     }
1163                     else
1164                     {
1165                         standardsManager.SecurityTokenSerializer.WriteToken(writer, rstr.RequestedProofToken);
1166                     }
1167                     writer.WriteEndElement();
1168                 }
1169
1170                 SecurityToken entropyToken = rstr.GetIssuerEntropy();
1171                 if (entropyToken != null)
1172                 {
1173                     writer.WriteStartElement(DriverDictionary.Prefix.Value, DriverDictionary.Entropy, DriverDictionary.Namespace);
1174                     standardsManager.SecurityTokenSerializer.WriteToken(writer, entropyToken);
1175                     writer.WriteEndElement();
1176                 }
1177
1178                 // To write out the lifetime, the following algorithm is used
1179                 //   1. If the lifetime is explicitly set, write it out.
1180                 //   2. Else, if a token/tokenbuilder has been set, use the lifetime in that.
1181                 //   3. Else do not serialize lifetime
1182                 if (rstr.IsLifetimeSet || rstr.RequestedSecurityToken != null)
1183                 {
1184                     DateTime effectiveTime = SecurityUtils.MinUtcDateTime;
1185                     DateTime expirationTime = SecurityUtils.MaxUtcDateTime;
1186
1187                     if (rstr.IsLifetimeSet)
1188                     {
1189                         effectiveTime = rstr.ValidFrom.ToUniversalTime();
1190                         expirationTime = rstr.ValidTo.ToUniversalTime();
1191                     }
1192                     else if (rstr.RequestedSecurityToken != null)
1193                     {
1194                         effectiveTime = rstr.RequestedSecurityToken.ValidFrom.ToUniversalTime();
1195                         expirationTime = rstr.RequestedSecurityToken.ValidTo.ToUniversalTime();
1196                     }
1197
1198                     // write out the lifetime
1199                     writer.WriteStartElement(DriverDictionary.Prefix.Value, DriverDictionary.Lifetime, DriverDictionary.Namespace);
1200                     // write out Created
1201                     writer.WriteStartElement(XD.UtilityDictionary.Prefix.Value, XD.UtilityDictionary.CreatedElement, XD.UtilityDictionary.Namespace);
1202                     writer.WriteString(effectiveTime.ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture.DateTimeFormat));
1203                     writer.WriteEndElement(); // wsu:Created
1204                     // write out Expires
1205                     writer.WriteStartElement(XD.UtilityDictionary.Prefix.Value, XD.UtilityDictionary.ExpiresElement, XD.UtilityDictionary.Namespace);
1206                     writer.WriteString(expirationTime.ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture.DateTimeFormat));
1207                     writer.WriteEndElement(); // wsu:Expires
1208                     writer.WriteEndElement(); // wsse:Lifetime
1209                 }
1210
1211                 byte[] authenticator = rstr.GetAuthenticator();
1212                 if (authenticator != null)
1213                 {
1214                     writer.WriteStartElement(DriverDictionary.Prefix.Value, DriverDictionary.Authenticator, DriverDictionary.Namespace);
1215                     writer.WriteStartElement(DriverDictionary.Prefix.Value, DriverDictionary.CombinedHash, DriverDictionary.Namespace);
1216                     writer.WriteBase64(authenticator, 0, authenticator.Length);
1217                     writer.WriteEndElement();
1218                     writer.WriteEndElement();
1219                 }
1220
1221                 if (rstr.KeySize > 0)
1222                 {
1223                     writer.WriteStartElement(DriverDictionary.Prefix.Value, DriverDictionary.KeySize, DriverDictionary.Namespace);
1224                     writer.WriteValue(rstr.KeySize);
1225                     writer.WriteEndElement();
1226                 }
1227
1228                 WriteRequestedTokenClosed(rstr, writer);
1229
1230                 BinaryNegotiation negotiationData = rstr.GetBinaryNegotiation();
1231                 if (negotiationData != null)
1232                     WriteBinaryNegotiation(negotiationData, writer);
1233
1234                 rstr.OnWriteCustomElements(writer);
1235                 writer.WriteEndElement();
1236             }
1237
1238             public override void WriteRequestSecurityTokenResponseCollection(RequestSecurityTokenResponseCollection rstrCollection, XmlWriter xmlWriter)
1239             {
1240                 if (rstrCollection == null)
1241                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("rstrCollection");
1242
1243                 XmlDictionaryWriter writer = XmlDictionaryWriter.CreateDictionaryWriter(xmlWriter);
1244                 writer.WriteStartElement(DriverDictionary.Prefix.Value, DriverDictionary.RequestSecurityTokenResponseCollection, DriverDictionary.Namespace);
1245                 foreach (RequestSecurityTokenResponse rstr in rstrCollection.RstrCollection)
1246                 {
1247                     rstr.WriteTo(writer);
1248                 }
1249                 writer.WriteEndElement();
1250             }
1251
1252             protected void SetProtectionLevelForFederation(OperationDescriptionCollection operations)
1253             {
1254                 foreach (OperationDescription operation in operations)
1255                 {
1256                     foreach (MessageDescription message in operation.Messages)
1257                     {
1258                         if (message.Body.Parts.Count > 0)
1259                         {
1260                             foreach (MessagePartDescription part in message.Body.Parts)
1261                             {
1262                                 part.ProtectionLevel = System.Net.Security.ProtectionLevel.EncryptAndSign;
1263                             }
1264                         }
1265                         if (OperationFormatter.IsValidReturnValue(message.Body.ReturnValue))
1266                         {
1267                             message.Body.ReturnValue.ProtectionLevel = System.Net.Security.ProtectionLevel.EncryptAndSign;
1268                         }
1269                     }
1270                 }
1271             }
1272
1273             public override bool TryParseKeySizeElement(XmlElement element, out int keySize)
1274             {
1275                 if (element == null)
1276                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("element");
1277
1278                 if (element.LocalName == this.DriverDictionary.KeySize.Value
1279                     && element.NamespaceURI == this.DriverDictionary.Namespace.Value)
1280                 {
1281                     keySize = Int32.Parse(XmlHelper.ReadTextElementAsTrimmedString(element), NumberFormatInfo.InvariantInfo);
1282                     return true;
1283                 }
1284
1285                 keySize = 0;
1286                 return false;
1287             }
1288
1289             public override XmlElement CreateKeySizeElement(int keySize)
1290             {
1291                 if (keySize < 0)
1292                 {
1293                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("keySize", SR.GetString(SR.ValueMustBeNonNegative)));
1294                 }
1295                 XmlDocument doc = new XmlDocument();
1296                 XmlElement result = doc.CreateElement(this.DriverDictionary.Prefix.Value, this.DriverDictionary.KeySize.Value,
1297                     this.DriverDictionary.Namespace.Value);
1298                 result.AppendChild(doc.CreateTextNode(keySize.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat)));
1299                 return result;
1300             }
1301
1302             public override XmlElement CreateKeyTypeElement(SecurityKeyType keyType)
1303             {
1304                 if (keyType == SecurityKeyType.SymmetricKey)
1305                     return CreateSymmetricKeyTypeElement();
1306                 else if (keyType == SecurityKeyType.AsymmetricKey)
1307                     return CreatePublicKeyTypeElement();
1308                 else
1309                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.UnableToCreateKeyTypeElementForUnknownKeyType, keyType.ToString())));
1310             }
1311
1312             public override bool TryParseKeyTypeElement(XmlElement element, out SecurityKeyType keyType)
1313             {
1314                 if (element == null)
1315                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("element");
1316
1317                 if (TryParseSymmetricKeyElement(element))
1318                 {
1319                     keyType = SecurityKeyType.SymmetricKey;
1320                     return true;
1321                 }
1322                 else if (TryParsePublicKeyElement(element))
1323                 {
1324                     keyType = SecurityKeyType.AsymmetricKey;
1325                     return true;
1326                 }
1327
1328                 keyType = SecurityKeyType.SymmetricKey;
1329                 return false;
1330
1331             }
1332
1333             public bool TryParseSymmetricKeyElement(XmlElement element)
1334             {
1335                 if (element == null)
1336                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("element");
1337
1338                 return element.LocalName == this.DriverDictionary.KeyType.Value
1339                     && element.NamespaceURI == this.DriverDictionary.Namespace.Value
1340                     && element.InnerText == this.DriverDictionary.SymmetricKeyType.Value;
1341             }
1342
1343             XmlElement CreateSymmetricKeyTypeElement()
1344             {
1345                 XmlDocument doc = new XmlDocument();
1346                 XmlElement result = doc.CreateElement(this.DriverDictionary.Prefix.Value, this.DriverDictionary.KeyType.Value,
1347                     this.DriverDictionary.Namespace.Value);
1348                 result.AppendChild(doc.CreateTextNode(this.DriverDictionary.SymmetricKeyType.Value));
1349                 return result;
1350             }
1351
1352             bool TryParsePublicKeyElement(XmlElement element)
1353             {
1354                 if (element == null)
1355                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("element");
1356
1357                 return element.LocalName == this.DriverDictionary.KeyType.Value
1358                     && element.NamespaceURI == this.DriverDictionary.Namespace.Value
1359                     && element.InnerText == this.DriverDictionary.PublicKeyType.Value;
1360             }
1361
1362             XmlElement CreatePublicKeyTypeElement()
1363             {
1364                 XmlDocument doc = new XmlDocument();
1365                 XmlElement result = doc.CreateElement(this.DriverDictionary.Prefix.Value, this.DriverDictionary.KeyType.Value,
1366                     this.DriverDictionary.Namespace.Value);
1367                 result.AppendChild(doc.CreateTextNode(this.DriverDictionary.PublicKeyType.Value));
1368                 return result;
1369             }
1370
1371             public override bool TryParseTokenTypeElement(XmlElement element, out string tokenType)
1372             {
1373                 if (element == null)
1374                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("element");
1375
1376                 if (element.LocalName == this.DriverDictionary.TokenType.Value
1377                     && element.NamespaceURI == this.DriverDictionary.Namespace.Value)
1378                 {
1379                     tokenType = element.InnerText;
1380                     return true;
1381                 }
1382
1383                 tokenType = null;
1384                 return false;
1385             }
1386
1387             public override XmlElement CreateTokenTypeElement(string tokenTypeUri)
1388             {
1389                 if (tokenTypeUri == null)
1390                 {
1391                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("tokenTypeUri");
1392                 }
1393                 XmlDocument doc = new XmlDocument();
1394                 XmlElement result = doc.CreateElement(this.DriverDictionary.Prefix.Value, this.DriverDictionary.TokenType.Value,
1395                     this.DriverDictionary.Namespace.Value);
1396                 result.AppendChild(doc.CreateTextNode(tokenTypeUri));
1397                 return result;
1398             }
1399
1400             public override XmlElement CreateUseKeyElement(SecurityKeyIdentifier keyIdentifier, SecurityStandardsManager standardsManager)
1401             {
1402                 if (keyIdentifier == null)
1403                 {
1404                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("keyIdentifier");
1405                 }
1406                 if (standardsManager == null)
1407                 {
1408                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("standardsManager");
1409                 }
1410                 XmlDocument doc = new XmlDocument();
1411                 XmlElement result = doc.CreateElement(this.DriverDictionary.UseKey.Value, this.DriverDictionary.Namespace.Value);
1412                 MemoryStream stream = new MemoryStream();
1413                 using (XmlDictionaryWriter writer = XmlDictionaryWriter.CreateDictionaryWriter(new XmlTextWriter(stream, Encoding.UTF8)))
1414                 {
1415 #pragma warning suppress 56506 // standardsManager.SecurityTokenSerializer can never be null.
1416                     standardsManager.SecurityTokenSerializer.WriteKeyIdentifier(writer, keyIdentifier);
1417                     writer.Flush();
1418                     stream.Seek(0, SeekOrigin.Begin);
1419                     XmlNode skiNode;
1420                     using (XmlDictionaryReader reader = XmlDictionaryReader.CreateDictionaryReader(new XmlTextReader(stream) { DtdProcessing = DtdProcessing.Prohibit }))
1421                     {
1422                         reader.MoveToContent();
1423                         skiNode = doc.ReadNode(reader);
1424                     }
1425                     result.AppendChild(skiNode);
1426                 }
1427                 return result;
1428             }
1429
1430             public override XmlElement CreateSignWithElement(string signatureAlgorithm)
1431             {
1432                 if (signatureAlgorithm == null)
1433                 {
1434                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("signatureAlgorithm");
1435                 }
1436                 XmlDocument doc = new XmlDocument();
1437                 XmlElement result = doc.CreateElement(this.DriverDictionary.Prefix.Value, this.DriverDictionary.SignWith.Value,
1438                     this.DriverDictionary.Namespace.Value);
1439                 result.AppendChild(doc.CreateTextNode(signatureAlgorithm));
1440                 return result;
1441             }
1442
1443             internal override bool IsSignWithElement(XmlElement element, out string signatureAlgorithm)
1444             {
1445                 return CheckElement(element, this.DriverDictionary.SignWith.Value, this.DriverDictionary.Namespace.Value, out signatureAlgorithm);
1446             }
1447
1448             public override XmlElement CreateEncryptWithElement(string encryptionAlgorithm)
1449             {
1450                 if (encryptionAlgorithm == null)
1451                 {
1452                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("encryptionAlgorithm");
1453                 }
1454                 XmlDocument doc = new XmlDocument();
1455                 XmlElement result = doc.CreateElement(this.DriverDictionary.Prefix.Value, this.DriverDictionary.EncryptWith.Value,
1456                     this.DriverDictionary.Namespace.Value);
1457                 result.AppendChild(doc.CreateTextNode(encryptionAlgorithm));
1458                 return result;
1459             }
1460
1461             public override XmlElement CreateEncryptionAlgorithmElement(string encryptionAlgorithm)
1462             {
1463                 if (encryptionAlgorithm == null)
1464                 {
1465                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("encryptionAlgorithm");
1466                 }
1467                 XmlDocument doc = new XmlDocument();
1468                 XmlElement result = doc.CreateElement(this.DriverDictionary.Prefix.Value, this.DriverDictionary.EncryptionAlgorithm.Value,
1469                     this.DriverDictionary.Namespace.Value);
1470                 result.AppendChild(doc.CreateTextNode(encryptionAlgorithm));
1471                 return result;
1472             }
1473
1474             internal override bool IsEncryptWithElement(XmlElement element, out string encryptWithAlgorithm)
1475             {
1476                 return CheckElement(element, this.DriverDictionary.EncryptWith.Value, this.DriverDictionary.Namespace.Value, out encryptWithAlgorithm);
1477             }
1478
1479             internal override bool IsEncryptionAlgorithmElement(XmlElement element, out string encryptionAlgorithm)
1480             {
1481                 return CheckElement(element, this.DriverDictionary.EncryptionAlgorithm.Value, this.DriverDictionary.Namespace.Value, out encryptionAlgorithm);
1482             }
1483
1484             public override XmlElement CreateComputedKeyAlgorithmElement(string algorithm)
1485             {
1486                 if (algorithm == null)
1487                 {
1488                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("algorithm");
1489                 }
1490                 XmlDocument doc = new XmlDocument();
1491                 XmlElement result = doc.CreateElement(this.DriverDictionary.Prefix.Value, this.DriverDictionary.ComputedKeyAlgorithm.Value,
1492                     this.DriverDictionary.Namespace.Value);
1493                 result.AppendChild(doc.CreateTextNode(algorithm));
1494                 return result;
1495             }
1496
1497             public override XmlElement CreateCanonicalizationAlgorithmElement(string algorithm)
1498             {
1499                 if (algorithm == null)
1500                 {
1501                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("algorithm");
1502                 }
1503                 XmlDocument doc = new XmlDocument();
1504                 XmlElement result = doc.CreateElement(this.DriverDictionary.Prefix.Value, this.DriverDictionary.CanonicalizationAlgorithm.Value,
1505                     this.DriverDictionary.Namespace.Value);
1506                 result.AppendChild(doc.CreateTextNode(algorithm));
1507                 return result;
1508             }
1509
1510             internal override bool IsCanonicalizationAlgorithmElement(XmlElement element, out string canonicalizationAlgorithm)
1511             {
1512                 return CheckElement(element, this.DriverDictionary.CanonicalizationAlgorithm.Value, this.DriverDictionary.Namespace.Value, out canonicalizationAlgorithm);
1513             }
1514
1515             public override bool TryParseRequiredClaimsElement(XmlElement element, out System.Collections.ObjectModel.Collection<XmlElement> requiredClaims)
1516             {
1517                 if (element == null)
1518                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("element");
1519
1520                 if (element.LocalName == this.DriverDictionary.Claims.Value
1521                     && element.NamespaceURI == this.DriverDictionary.Namespace.Value)
1522                 {
1523                     requiredClaims = new System.Collections.ObjectModel.Collection<XmlElement>();
1524                     foreach (XmlNode node in element.ChildNodes)
1525                         if (node is XmlElement)
1526                         {
1527                             // PreSharp Bug: Parameter 'requiredClaims' to this public method must be validated: A null-dereference can occur here.
1528 #pragma warning suppress 56506
1529                             requiredClaims.Add((XmlElement)node);
1530                         }
1531                     return true;
1532                 }
1533
1534                 requiredClaims = null;
1535                 return false;
1536             }
1537
1538             public override XmlElement CreateRequiredClaimsElement(IEnumerable<XmlElement> claimsList)
1539             {
1540                 if (claimsList == null)
1541                 {
1542                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("claimsList");
1543                 }
1544                 XmlDocument doc = new XmlDocument();
1545                 XmlElement result = doc.CreateElement(this.DriverDictionary.Prefix.Value, this.DriverDictionary.Claims.Value,
1546                     this.DriverDictionary.Namespace.Value);
1547                 foreach (XmlElement claimElement in claimsList)
1548                 {
1549                     XmlElement element = (XmlElement)doc.ImportNode(claimElement, true);
1550                     result.AppendChild(element);
1551                 }
1552                 return result;
1553             }
1554
1555             internal static void ValidateRequestedKeySize(int keySize, SecurityAlgorithmSuite algorithmSuite)
1556             {
1557                 if ((keySize % 8 == 0) && algorithmSuite.IsSymmetricKeyLengthSupported(keySize))
1558                 {
1559                     return;
1560                 }
1561                 else
1562                 {
1563                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new SecurityNegotiationException(SR.GetString(SR.InvalidKeyLengthRequested, keySize)));
1564                 }
1565             }
1566
1567             static void ValidateRequestorEntropy(SecurityToken entropy, SecurityKeyEntropyMode mode)
1568             {
1569                 if ((mode == SecurityKeyEntropyMode.ClientEntropy || mode == SecurityKeyEntropyMode.CombinedEntropy)
1570                     && (entropy == null))
1571                 {
1572                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.EntropyModeRequiresRequestorEntropy, mode)));
1573                 }
1574                 if (mode == SecurityKeyEntropyMode.ServerEntropy && entropy != null)
1575                 {
1576                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.EntropyModeCannotHaveRequestorEntropy, mode)));
1577                 }
1578             }
1579
1580             internal static void ProcessRstAndIssueKey(RequestSecurityToken requestSecurityToken, SecurityTokenResolver resolver, SecurityKeyEntropyMode keyEntropyMode, SecurityAlgorithmSuite algorithmSuite, out int issuedKeySize, out byte[] issuerEntropy, out byte[] proofKey,
1581                 out SecurityToken proofToken)
1582             {
1583                 SecurityToken requestorEntropyToken = requestSecurityToken.GetRequestorEntropy(resolver);
1584                 ValidateRequestorEntropy(requestorEntropyToken, keyEntropyMode);
1585                 byte[] requestorEntropy;
1586                 if (requestorEntropyToken != null)
1587                 {
1588                     if (requestorEntropyToken is BinarySecretSecurityToken)
1589                     {
1590                         BinarySecretSecurityToken skToken = (BinarySecretSecurityToken)requestorEntropyToken;
1591                         requestorEntropy = skToken.GetKeyBytes();
1592                     }
1593                     else if (requestorEntropyToken is WrappedKeySecurityToken)
1594                     {
1595                         requestorEntropy = ((WrappedKeySecurityToken)requestorEntropyToken).GetWrappedKey();
1596                     }
1597                     else
1598                     {
1599                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.TokenCannotCreateSymmetricCrypto, requestorEntropyToken)));
1600                     }
1601                 }
1602                 else
1603                 {
1604                     requestorEntropy = null;
1605                 }
1606
1607                 if (keyEntropyMode == SecurityKeyEntropyMode.ClientEntropy)
1608                 {
1609                     if (requestorEntropy != null)
1610                     {
1611                         // validate that the entropy length matches the algorithm suite
1612                         ValidateRequestedKeySize(requestorEntropy.Length * 8, algorithmSuite);
1613                     }
1614                     proofKey = requestorEntropy;
1615                     issuerEntropy = null;
1616                     issuedKeySize = 0;
1617                     proofToken = null;
1618                 }
1619                 else
1620                 {
1621                     if (requestSecurityToken.KeySize != 0)
1622                     {
1623                         ValidateRequestedKeySize(requestSecurityToken.KeySize, algorithmSuite);
1624                         issuedKeySize = requestSecurityToken.KeySize;
1625                     }
1626                     else
1627                     {
1628                         issuedKeySize = algorithmSuite.DefaultSymmetricKeyLength;
1629                     }
1630                     RNGCryptoServiceProvider random = new RNGCryptoServiceProvider();
1631                     if (keyEntropyMode == SecurityKeyEntropyMode.ServerEntropy)
1632                     {
1633                         proofKey = new byte[issuedKeySize / 8];
1634                         // proof key is completely issued by the server
1635                         random.GetNonZeroBytes(proofKey);
1636                         issuerEntropy = null;
1637                         proofToken = new BinarySecretSecurityToken(proofKey);
1638                     }
1639                     else
1640                     {
1641                         issuerEntropy = new byte[issuedKeySize / 8];
1642                         random.GetNonZeroBytes(issuerEntropy);
1643                         proofKey = RequestSecurityTokenResponse.ComputeCombinedKey(requestorEntropy, issuerEntropy, issuedKeySize);
1644                         proofToken = null;
1645                     }
1646                 }
1647             }
1648
1649         }
1650
1651         protected static bool CheckElement(XmlElement element, string name, string ns, out string value)
1652         {
1653             value = null;
1654             if (element.LocalName != name || element.NamespaceURI != ns)
1655                 return false;
1656             if (element.FirstChild is XmlText)
1657             {
1658                 value = ((XmlText)element.FirstChild).Value;
1659                 return true;
1660             }
1661             return false;
1662         }
1663     }
1664 }