2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / class / System.ServiceModel / System.ServiceModel.Security / WSSecurityTokenSerializer.cs
blob026daa9a8225a8cd4176fadb296b321bfe39bcc6
1 //
2 // WSSecurityTokenSerializer.cs
3 //
4 // Author:
5 // Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // Copyright (C) 2006-2007 Novell, Inc. http://www.novell.com
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 using System;
29 using System.Collections.Generic;
30 using System.IdentityModel.Selectors;
31 using System.IdentityModel.Tokens;
32 using System.Security.Cryptography.X509Certificates;
33 using System.Security.Cryptography.Xml;
34 using System.ServiceModel.Security.Tokens;
35 using System.Text;
36 using System.Xml;
38 namespace System.ServiceModel.Security
40 public class WSSecurityTokenSerializer : SecurityTokenSerializer
42 static WSSecurityTokenSerializer default_instance =
43 new WSSecurityTokenSerializer ();
45 public static WSSecurityTokenSerializer DefaultInstance {
46 get { return default_instance; }
49 const int defaultOffset = 64,
50 defaultLabelLength = 128,
51 defaultNonceLength = 128;
53 public WSSecurityTokenSerializer ()
54 : this (false)
58 public WSSecurityTokenSerializer (bool emitBspRequiredAttributes)
59 : this (SecurityVersion.WSSecurity11, emitBspRequiredAttributes)
63 public WSSecurityTokenSerializer (SecurityVersion securityVersion)
64 : this (securityVersion, false)
68 public WSSecurityTokenSerializer (SecurityVersion securityVersion, bool emitBspRequiredAttributes)
69 : this (securityVersion, emitBspRequiredAttributes, new SamlSerializer ())
73 public WSSecurityTokenSerializer (
74 SecurityVersion securityVersion,
75 bool emitBspRequiredAttributes,
76 SamlSerializer samlSerializer)
77 : this (securityVersion, emitBspRequiredAttributes,
78 samlSerializer, null, null)
82 public WSSecurityTokenSerializer (
83 SecurityVersion securityVersion,
84 bool emitBspRequiredAttributes,
85 SamlSerializer samlSerializer,
86 SecurityStateEncoder securityStateEncoder,
87 IEnumerable<Type> knownTypes)
88 : this (securityVersion, emitBspRequiredAttributes,
89 samlSerializer, securityStateEncoder,
90 knownTypes, defaultOffset, defaultLabelLength,
91 defaultNonceLength)
95 public WSSecurityTokenSerializer (
96 SecurityVersion securityVersion,
97 bool emitBspRequiredAttributes,
98 SamlSerializer samlSerializer,
99 SecurityStateEncoder securityStateEncoder,
100 IEnumerable<Type> knownTypes,
101 int maximumKeyDerivationOffset,
102 int maximumKeyDerivationLabelLength,
103 int maximumKeyDerivationNonceLength)
105 security_version = securityVersion;
106 emit_bsp = emitBspRequiredAttributes;
107 saml_serializer = samlSerializer;
108 encoder = securityStateEncoder;
109 known_types = new List<Type> (knownTypes ?? Type.EmptyTypes);
110 max_offset = maximumKeyDerivationOffset;
111 max_label_length = maximumKeyDerivationLabelLength;
112 max_nonce_length = maximumKeyDerivationNonceLength;
114 if (encoder == null)
115 encoder = new DataProtectionSecurityStateEncoder ();
118 SecurityVersion security_version;
119 bool emit_bsp;
120 SamlSerializer saml_serializer;
121 SecurityStateEncoder encoder;
122 List<Type> known_types;
123 int max_offset, max_label_length, max_nonce_length;
125 bool WSS1_0 {
126 get { return SecurityVersion == SecurityVersion.WSSecurity10; }
129 public bool EmitBspRequiredAttributes {
130 get { return emit_bsp; }
133 public SecurityVersion SecurityVersion {
134 get { return security_version; }
137 [MonoTODO]
138 public int MaximumKeyDerivationOffset {
139 get { return max_offset; }
142 [MonoTODO]
143 public int MaximumKeyDerivationLabelLength {
144 get { return max_label_length; }
147 [MonoTODO]
148 public int MaximumKeyDerivationNonceLength {
149 get { return max_nonce_length; }
152 protected virtual string GetTokenTypeUri (Type tokenType)
154 if (tokenType == typeof (WrappedKeySecurityToken))
155 return Constants.WSSEncryptedKeyToken;
156 if (tokenType == typeof (X509SecurityToken))
157 return Constants.WSSX509Token;
158 // if (tokenType == typeof (RsaSecurityToken))
159 // return null;
160 if (tokenType == typeof (SamlSecurityToken))
161 return Constants.WSSSamlToken;
162 if (tokenType == typeof (SecurityContextSecurityToken))
163 return Constants.WsscContextToken;
164 // if (tokenType == typeof (huh))
165 // return ServiceModelSecurityTokenTypes.SecureConversation;
166 // if (tokenType == typeof (hah))
167 // return ServiceModelSecurityTokenTypes.MutualSslnego;
168 // if (tokenType == typeof (whoa))
169 // return ServiceModelSecurityTokenTypes.AnonymousSslnego;
170 if (tokenType == typeof (UserNameSecurityToken))
171 return Constants.WSSUserNameToken;
172 // if (tokenType == typeof (uhoh))
173 // return ServiceModelSecurityTokenTypes.Spnego;
174 // if (tokenType == typeof (SspiSecurityToken))
175 // return ServiceModelSecurityTokenTypes.SspiCredential;
176 if (tokenType == typeof (KerberosRequestorSecurityToken))
177 return Constants.WSSKerberosToken;
178 return null;
181 [MonoTODO]
182 protected override bool CanReadKeyIdentifierClauseCore (XmlReader reader)
184 reader.MoveToContent ();
185 switch (reader.NamespaceURI) {
186 case EncryptedXml.XmlEncNamespaceUrl:
187 switch (reader.LocalName) {
188 case "EncryptedKey":
189 return true;
191 break;
192 case Constants.WssNamespace:
193 switch (reader.LocalName) {
194 case "SecurityTokenReference":
195 return true;
197 break;
200 return false;
203 [MonoTODO]
204 protected override bool CanReadKeyIdentifierCore (XmlReader reader)
206 throw new NotImplementedException ();
209 [MonoTODO]
210 protected override bool CanReadTokenCore (XmlReader reader)
212 reader.MoveToContent ();
214 switch (reader.NamespaceURI) {
215 case Constants.WssNamespace:
216 switch (reader.LocalName) {
217 case "BinarySecurityToken":
218 case "BinarySecret":
219 case "UsernameToken":
220 return true;
222 break;
223 case Constants.WsscNamespace:
224 switch (reader.LocalName) {
225 case "DerivedKeyToken":
226 case "SecurityContextToken":
227 return true;
229 break;
230 case EncryptedXml.XmlEncNamespaceUrl:
231 switch (reader.LocalName) {
232 case "EncryptedKey":
233 return true;
235 break;
237 return false;
240 [MonoTODO]
241 public virtual SecurityKeyIdentifierClause CreateKeyIdentifierClauseFromTokenXml (
242 XmlElement tokenXml, SecurityTokenReferenceStyle referenceStyle)
244 throw new NotImplementedException ();
247 [MonoTODO]
248 protected override SecurityKeyIdentifier ReadKeyIdentifierCore (
249 XmlReader reader)
251 throw new NotImplementedException ();
254 [MonoTODO]
255 protected override SecurityKeyIdentifierClause ReadKeyIdentifierClauseCore (XmlReader reader)
257 reader.MoveToContent ();
258 switch (reader.NamespaceURI) {
259 case EncryptedXml.XmlEncNamespaceUrl:
260 switch (reader.LocalName) {
261 case "EncryptedKey":
262 return ReadEncryptedKeyIdentifierClause (reader);
264 break;
265 case Constants.WssNamespace:
266 switch (reader.LocalName) {
267 case "SecurityTokenReference":
268 return ReadSecurityTokenReference (reader);
270 break;
273 throw new NotImplementedException (String.Format ("Security key identifier clause element '{0}' in namespace '{1}' is either not implemented or not supported.", reader.LocalName, reader.NamespaceURI));
276 SecurityKeyIdentifierClause ReadSecurityTokenReference (XmlReader reader)
278 reader.ReadStartElement ();
279 reader.MoveToContent ();
280 if (reader.NamespaceURI == SignedXml.XmlDsigNamespaceUrl) {
281 KeyInfoX509Data x509 = new KeyInfoX509Data ();
282 x509.LoadXml (new XmlDocument ().ReadNode (reader) as XmlElement);
283 if (x509.IssuerSerials.Count == 0)
284 throw new XmlException ("'X509IssuerSerial' element is expected inside 'X509Data' element");
285 X509IssuerSerial s = (X509IssuerSerial) x509.IssuerSerials [0];
286 reader.MoveToContent ();
287 reader.ReadEndElement ();
288 return new X509IssuerSerialKeyIdentifierClause (s.IssuerName, s.SerialNumber);
290 if (reader.NamespaceURI != Constants.WssNamespace)
291 throw new XmlException (String.Format ("Unexpected SecurityTokenReference content: expected local name 'Reference' and namespace URI '{0}' but found local name '{1}' and namespace '{2}'.", Constants.WssNamespace, reader.LocalName, reader.NamespaceURI));
293 switch (reader.LocalName) {
294 case "Reference":
295 Type ownerType = null;
296 // FIXME: there could be more token types.
297 if (reader.MoveToAttribute ("ValueType")) {
298 switch (reader.Value) {
299 case Constants.WSSEncryptedKeyToken:
300 ownerType = typeof (WrappedKeySecurityToken);
301 break;
302 case Constants.WSSX509Token:
303 ownerType = typeof (X509SecurityToken);
304 break;
305 case Constants.WsscContextToken:
306 ownerType = typeof (SecurityContextSecurityToken);
307 break;
308 default:
309 throw new XmlException (String.Format ("Unexpected ValueType in 'Reference' element: '{0}'", reader.Value));
312 reader.MoveToElement ();
313 string uri = reader.GetAttribute ("URI");
314 if (String.IsNullOrEmpty (uri))
315 uri = "#";
316 SecurityKeyIdentifierClause ic = null;
317 if (ownerType == typeof (SecurityContextSecurityToken) && uri [0] != '#')
318 // FIXME: Generation?
319 ic = new SecurityContextKeyIdentifierClause (new UniqueId (uri));
320 else
321 ic = new LocalIdKeyIdentifierClause (uri.Substring (1), ownerType);
322 reader.Skip ();
323 reader.MoveToContent ();
324 reader.ReadEndElement ();
325 return ic;
326 case "KeyIdentifier":
327 string valueType = reader.GetAttribute ("ValueType");
328 string value = reader.ReadElementContentAsString ();
329 reader.MoveToContent ();
330 reader.ReadEndElement (); // consume </Reference>
331 switch (valueType) {
332 case Constants.WssKeyIdentifierX509Thumbptint:
333 return new X509ThumbprintKeyIdentifierClause (Convert.FromBase64String (value));
334 case Constants.WssKeyIdentifierEncryptedKey:
335 return new InternalEncryptedKeyIdentifierClause (Convert.FromBase64String (value));
336 case Constants.WssKeyIdentifierSamlAssertion:
337 return new SamlAssertionKeyIdentifierClause (value);
338 default:
339 // It is kinda weird but it throws XmlException here ...
340 throw new XmlException (String.Format ("KeyIdentifier type '{0}' is not supported in WSSecurityTokenSerializer.", valueType));
342 default:
343 throw new XmlException (String.Format ("Unexpected SecurityTokenReference content: expected local name 'Reference' and namespace URI '{0}' but found local name '{1}' and namespace '{2}'.", Constants.WssNamespace, reader.LocalName, reader.NamespaceURI));
347 EncryptedKeyIdentifierClause ReadEncryptedKeyIdentifierClause (
348 XmlReader reader)
350 string encNS = EncryptedXml.XmlEncNamespaceUrl;
352 string id = reader.GetAttribute ("Id", Constants.WsuNamespace);
353 reader.Read ();
354 reader.MoveToContent ();
355 string encMethod = reader.GetAttribute ("Algorithm");
356 bool isEmpty = reader.IsEmptyElement;
357 reader.ReadStartElement ("EncryptionMethod", encNS);
358 string digMethod = null;
359 if (!isEmpty) {
360 reader.MoveToContent ();
361 if (reader.LocalName == "DigestMethod" && reader.NamespaceURI == SignedXml.XmlDsigNamespaceUrl)
362 digMethod = reader.GetAttribute ("Algorithm");
363 while (reader.NodeType != XmlNodeType.EndElement) {
364 reader.Skip ();
365 reader.MoveToContent ();
367 reader.ReadEndElement ();
369 reader.MoveToContent ();
370 SecurityKeyIdentifier ki = null;
371 if (!reader.IsEmptyElement) {
372 reader.ReadStartElement ("KeyInfo", SignedXml.XmlDsigNamespaceUrl);
373 reader.MoveToContent ();
374 SecurityKeyIdentifierClause kic = ReadKeyIdentifierClauseCore (reader);
375 ki = new SecurityKeyIdentifier ();
376 ki.Add (kic);
377 reader.MoveToContent ();
378 reader.ReadEndElement (); // </ds:KeyInfo>
379 reader.MoveToContent ();
381 byte [] keyValue = null;
382 if (!reader.IsEmptyElement) {
383 reader.ReadStartElement ("CipherData", encNS);
384 reader.MoveToContent ();
385 keyValue = Convert.FromBase64String (reader.ReadElementContentAsString ("CipherValue", encNS));
386 reader.MoveToContent ();
387 reader.ReadEndElement (); // CipherData
389 string carriedKeyName = null;
390 if (!reader.IsEmptyElement && reader.LocalName == "CarriedKeyName" && reader.NamespaceURI == encNS) {
391 carriedKeyName = reader.ReadElementContentAsString ();
392 reader.MoveToContent ();
394 // FIXME: handle derived keys??
395 return new EncryptedKeyIdentifierClause (keyValue, encMethod, ki, carriedKeyName);
398 [MonoTODO]
399 protected override SecurityToken ReadTokenCore (
400 XmlReader reader,
401 SecurityTokenResolver tokenResolver)
403 if (!CanReadToken (reader))
404 throw new XmlException (String.Format ("Cannot read security token from {0} node of name '{1}' and namespace URI '{2}'", reader.NodeType, reader.LocalName, reader.NamespaceURI));
406 switch (reader.NamespaceURI) {
407 case Constants.WssNamespace:
408 switch (reader.LocalName) {
409 case "BinarySecurityToken":
410 return ReadX509TokenCore (reader, tokenResolver);
411 case "BinarySecret":
412 return ReadBinarySecretTokenCore (reader, tokenResolver);
413 case "UsernameToken":
414 return ReadUserNameTokenCore (reader, tokenResolver);
416 break;
417 case Constants.WsscNamespace:
418 if (reader.LocalName == "DerivedKeyToken")
419 return ReadDerivedKeyToken (reader, tokenResolver);
420 if (reader.LocalName == "SecurityContextToken")
421 return ReadSecurityContextToken (reader, tokenResolver);
422 break;
423 case EncryptedXml.XmlEncNamespaceUrl:
424 switch (reader.LocalName) {
425 case "EncryptedKey":
426 return ReadWrappedKeySecurityTokenCore (reader, tokenResolver);
428 break;
431 throw new NotImplementedException ();
434 DerivedKeySecurityToken ReadDerivedKeyToken (
435 XmlReader reader, SecurityTokenResolver tokenResolver)
437 try {
438 return ReadDerivedKeyTokenCore (reader, tokenResolver);
439 } catch (XmlException) {
440 throw;
441 } catch (Exception ex) {
442 throw new XmlException ("Cannot read DerivedKeyToken", ex);
446 DerivedKeySecurityToken ReadDerivedKeyTokenCore (
447 XmlReader reader, SecurityTokenResolver tokenResolver)
449 if (tokenResolver == null)
450 throw new ArgumentNullException ("tokenResolver");
451 string id = reader.GetAttribute ("Id", Constants.WsuNamespace);
452 string algorithm = reader.MoveToAttribute ("Algorithm") ? reader.Value : null;
453 reader.MoveToElement ();
454 reader.ReadStartElement ();
455 reader.MoveToContent ();
456 SecurityKeyIdentifierClause kic = ReadKeyIdentifierClause (reader);
457 int? generation = null, offset = null, length = null;
458 byte [] nonce = null;
459 string name = null, label = null;
460 for (reader.MoveToContent ();
461 reader.NodeType != XmlNodeType.EndElement;
462 reader.MoveToContent ())
463 switch (reader.LocalName) {
464 case "Properties":
465 reader.ReadStartElement ("Properties", Constants.WsscNamespace);
466 for (reader.MoveToContent ();
467 reader.NodeType != XmlNodeType.EndElement;
468 reader.MoveToContent ())
469 switch (reader.LocalName) {
470 case "Name":
471 name = reader.ReadElementContentAsString ("Name", Constants.WsscNamespace);
472 break;
473 case "Label":
474 label = reader.ReadElementContentAsString ("Label", Constants.WsscNamespace);
475 break;
476 case "Nonce":
477 nonce = Convert.FromBase64String (reader.ReadElementContentAsString ("Nonce", Constants.WsscNamespace));
478 break;
480 reader.ReadEndElement ();
481 break;
482 case "Offset":
483 offset = reader.ReadElementContentAsInt ("Offset", Constants.WsscNamespace);
484 break;
485 case "Length":
486 length = reader.ReadElementContentAsInt ("Length", Constants.WsscNamespace);
487 break;
488 case "Nonce":
489 nonce = Convert.FromBase64String (reader.ReadElementContentAsString ("Nonce", Constants.WsscNamespace));
490 break;
491 case "Label":
492 label = reader.ReadElementContentAsString ("Label", Constants.WsscNamespace);
493 break;
495 reader.ReadEndElement ();
497 // resolve key reference
498 SymmetricSecurityKey key = tokenResolver.ResolveSecurityKey (kic) as SymmetricSecurityKey;
499 if (key == null)
500 throw new XmlException ("Cannot resolve the security key referenced by the DerivedKeyToken as a symmetric key");
502 return new DerivedKeySecurityToken (id, algorithm, kic, key, name, generation, offset, length, label, nonce);
505 // since it cannot consume RequestSecurityTokenResponse,
506 // the token information cannot be complete.
507 SecurityContextSecurityToken ReadSecurityContextToken (
508 XmlReader reader, SecurityTokenResolver tokenResolver)
510 string id = reader.GetAttribute ("Id", Constants.WsuNamespace);
511 reader.Read ();
513 // The input dnse:Cookie value is encrypted by the
514 // server's SecurityStateEncoder
515 // (setting error-raising encoder to ServiceCredentials.
516 // SecureConversationAuthentication.SecurityStateEncoder
517 // shows it).
518 UniqueId cid = null;
519 byte [] cookie = null;
520 while (true) {
521 reader.MoveToContent ();
522 if (reader.NodeType != XmlNodeType.Element)
523 break;
524 switch (reader.NamespaceURI) {
525 case Constants.WsscNamespace:
526 switch (reader.LocalName) {
527 case "Identifier":
528 cid = new UniqueId (reader.ReadElementContentAsString ());
529 continue;
531 break;
532 case Constants.MSTlsnegoTokenContent:
533 switch (reader.LocalName) {
534 case "Cookie":
535 cookie = Convert.FromBase64String (reader.ReadElementContentAsString ());
536 continue;
538 break;
540 throw new XmlException (String.Format ("Unexpected element {0} in namespace {1}", reader.LocalName, reader.NamespaceURI));
542 reader.ReadEndElement ();
544 // LAMESPEC: at client side there is no way to specify
545 // SecurityStateEncoder, so it must be guessed from
546 // its cookie content itself.
547 if (encoder == null) throw new Exception ();
548 byte [] decoded =
549 cookie != null && cookie.Length > 154 ?
550 encoder.DecodeSecurityState (cookie) :
551 cookie;
552 return SslnegoCookieResolver.ResolveCookie (decoded, cookie);
555 WrappedKeySecurityToken ReadWrappedKeySecurityTokenCore (
556 XmlReader reader, SecurityTokenResolver tokenResolver)
558 if (tokenResolver == null)
559 throw new ArgumentNullException ("tokenResolver");
560 EncryptedKey ek = new EncryptedKey ();
561 ek.LoadXml (new XmlDocument ().ReadNode (reader) as XmlElement);
562 SecurityKeyIdentifier ki = new SecurityKeyIdentifier ();
563 foreach (KeyInfoClause kic in ek.KeyInfo)
564 ki.Add (ReadKeyIdentifierClause (new XmlNodeReader (kic.GetXml ())));
565 SecurityToken token = tokenResolver.ResolveToken (ki);
566 string alg = ek.EncryptionMethod.KeyAlgorithm;
567 foreach (SecurityKey skey in token.SecurityKeys)
568 if (skey.IsSupportedAlgorithm (alg)) {
569 byte [] key = skey.DecryptKey (alg, ek.CipherData.CipherValue);
570 WrappedKeySecurityToken wk =
571 new WrappedKeySecurityToken (ek.Id, key, alg, token, ki);
572 // FIXME: This should not be required.
573 wk.SetWrappedKey (ek.CipherData.CipherValue);
574 wk.ReferenceList = ek.ReferenceList;
575 return wk;
577 throw new InvalidOperationException (String.Format ("Cannot resolve security key with the resolved SecurityToken specified by the key identifier in the EncryptedKey XML. The key identifier is: {0}", ki));
580 X509SecurityToken ReadX509TokenCore (
581 XmlReader reader, SecurityTokenResolver resolver)
583 string id = reader.GetAttribute ("Id", Constants.WsuNamespace);
584 byte [] raw = Convert.FromBase64String (reader.ReadElementContentAsString ());
585 return new X509SecurityToken (new X509Certificate2 (raw), id);
588 UserNameSecurityToken ReadUserNameTokenCore (
589 XmlReader reader, SecurityTokenResolver resolver)
591 string id = reader.GetAttribute ("Id", Constants.WsuNamespace);
592 if (reader.IsEmptyElement)
593 throw new XmlException ("At least UsernameToken must contain Username");
594 reader.Read ();
595 reader.MoveToContent ();
596 string user = reader.ReadElementContentAsString ("Username", Constants.WssNamespace);
597 reader.MoveToContent ();
598 string pass = null;
599 if (reader.LocalName == "Password" && reader.NamespaceURI == Constants.WssNamespace) {
600 pass = reader.ReadElementContentAsString ("Password", Constants.WssNamespace);
601 reader.MoveToContent ();
603 reader.ReadEndElement ();
604 return id != null ?
605 new UserNameSecurityToken (user, pass, id) :
606 new UserNameSecurityToken (user, pass);
609 BinarySecretSecurityToken ReadBinarySecretTokenCore (
610 XmlReader reader, SecurityTokenResolver resolver)
612 string id = reader.GetAttribute ("Id", Constants.WsuNamespace);
613 byte [] data = Convert.FromBase64String (reader.ReadElementContentAsString ());
614 return new BinarySecretSecurityToken (id, data);
617 [MonoTODO]
618 protected override bool CanWriteKeyIdentifierCore (
619 SecurityKeyIdentifier keyIdentifier)
621 throw new NotImplementedException ();
624 [MonoTODO]
625 protected override bool CanWriteKeyIdentifierClauseCore (
626 SecurityKeyIdentifierClause keyIdentifierClause)
628 if (keyIdentifierClause == null)
629 throw new ArgumentNullException ("keyIdentifierClause");
630 if (keyIdentifierClause is LocalIdKeyIdentifierClause ||
631 keyIdentifierClause is SecurityContextKeyIdentifierClause ||
632 keyIdentifierClause is X509IssuerSerialKeyIdentifierClause ||
633 (keyIdentifierClause is X509ThumbprintKeyIdentifierClause && !WSS1_0) ||
634 keyIdentifierClause is EncryptedKeyIdentifierClause ||
635 keyIdentifierClause is BinarySecretKeyIdentifierClause ||
636 keyIdentifierClause is InternalEncryptedKeyIdentifierClause ||
637 keyIdentifierClause is SamlAssertionKeyIdentifierClause)
638 return true;
639 else
640 return false;
643 [MonoTODO]
644 protected override bool CanWriteTokenCore (SecurityToken token)
646 throw new NotImplementedException ();
649 [MonoTODO]
650 protected override void WriteKeyIdentifierCore (
651 XmlWriter writer,
652 SecurityKeyIdentifier keyIdentifier)
654 throw new NotImplementedException ();
657 [MonoTODO]
658 protected override void WriteKeyIdentifierClauseCore (
659 XmlWriter writer,
660 SecurityKeyIdentifierClause keyIdentifierClause)
662 string errorReason = null;
664 if (keyIdentifierClause == null)
665 throw new ArgumentNullException ("keyIdentifierClause");
666 if (keyIdentifierClause is LocalIdKeyIdentifierClause)
667 WriteLocalIdKeyIdentifierClause (writer, (LocalIdKeyIdentifierClause) keyIdentifierClause);
668 else if (keyIdentifierClause is SecurityContextKeyIdentifierClause)
669 WriteSecurityContextKeyIdentifierClause (writer, (SecurityContextKeyIdentifierClause) keyIdentifierClause);
670 else if (keyIdentifierClause is X509IssuerSerialKeyIdentifierClause)
671 WriteX509IssuerSerialKeyIdentifierClause (writer, (X509IssuerSerialKeyIdentifierClause) keyIdentifierClause);
672 else if (keyIdentifierClause is X509ThumbprintKeyIdentifierClause) {
673 if (WSS1_0)
674 errorReason = String.Format ("Security key identifier clause '{0}' is not supported in this serializer.", keyIdentifierClause.GetType ());
675 else
676 WriteX509ThumbprintKeyIdentifierClause (writer, (X509ThumbprintKeyIdentifierClause) keyIdentifierClause);
678 else if (keyIdentifierClause is EncryptedKeyIdentifierClause)
679 WriteEncryptedKeyIdentifierClause (writer, (EncryptedKeyIdentifierClause) keyIdentifierClause);
680 else if (keyIdentifierClause is BinarySecretKeyIdentifierClause)
681 WriteBinarySecretKeyIdentifierClause (writer, (BinarySecretKeyIdentifierClause) keyIdentifierClause);
682 else if (keyIdentifierClause is InternalEncryptedKeyIdentifierClause)
683 WriteInternalEncryptedKeyIdentifierClause (writer, (InternalEncryptedKeyIdentifierClause) keyIdentifierClause);
684 else if (keyIdentifierClause is SamlAssertionKeyIdentifierClause)
685 WriteSamlAssertionKeyIdentifierClause (writer, (SamlAssertionKeyIdentifierClause) keyIdentifierClause);
686 else
687 throw new NotImplementedException (String.Format ("Security key identifier clause '{0}' is not either implemented or supported.", keyIdentifierClause.GetType ()));
689 if (errorReason != null)
690 throw new InvalidOperationException (errorReason);
693 void WriteX509IssuerSerialKeyIdentifierClause (
694 XmlWriter w, X509IssuerSerialKeyIdentifierClause ic)
696 w.WriteStartElement ("o", "SecurityTokenReference", Constants.WssNamespace);
697 w.WriteStartElement ("X509Data", Constants.XmlDsig);
698 w.WriteStartElement ("X509IssuerSerial", Constants.XmlDsig);
699 w.WriteStartElement ("X509IssuerName", Constants.XmlDsig);
700 w.WriteString (ic.IssuerName);
701 w.WriteEndElement ();
702 w.WriteStartElement ("X509SerialNumber", Constants.XmlDsig);
703 w.WriteString (ic.IssuerSerialNumber);
704 w.WriteEndElement ();
705 w.WriteEndElement ();
706 w.WriteEndElement ();
707 w.WriteEndElement ();
710 void WriteX509ThumbprintKeyIdentifierClause (
711 XmlWriter w, X509ThumbprintKeyIdentifierClause ic)
713 w.WriteStartElement ("o", "SecurityTokenReference", Constants.WssNamespace);
714 w.WriteStartElement ("o", "KeyIdentifier", Constants.WssNamespace);
715 w.WriteAttributeString ("ValueType", Constants.WssKeyIdentifierX509Thumbptint);
716 if (EmitBspRequiredAttributes)
717 w.WriteAttributeString ("EncodingType", Constants.WssBase64BinaryEncodingType);
718 w.WriteString (Convert.ToBase64String (ic.GetX509Thumbprint ()));
719 w.WriteEndElement ();
720 w.WriteEndElement ();
723 void WriteLocalIdKeyIdentifierClause (
724 XmlWriter w, LocalIdKeyIdentifierClause ic)
726 w.WriteStartElement ("o", "SecurityTokenReference", Constants.WssNamespace);
727 w.WriteStartElement ("o", "Reference", Constants.WssNamespace);
728 if (EmitBspRequiredAttributes && ic.OwnerType != null) {
729 string vt = GetTokenTypeUri (ic.OwnerType);
730 if (vt != null)
731 w.WriteAttributeString ("ValueType", vt);
733 w.WriteAttributeString ("URI", "#" + ic.LocalId);
734 w.WriteEndElement ();
735 w.WriteEndElement ();
738 void WriteSecurityContextKeyIdentifierClause (
739 XmlWriter w, SecurityContextKeyIdentifierClause ic)
741 w.WriteStartElement ("o", "SecurityTokenReference", Constants.WssNamespace);
742 w.WriteStartElement ("o", "Reference", Constants.WssNamespace);
743 w.WriteAttributeString ("URI", ic.ContextId.ToString ());
744 string vt = GetTokenTypeUri (typeof (SecurityContextSecurityToken));
745 w.WriteAttributeString ("ValueType", vt);
746 w.WriteEndElement ();
747 w.WriteEndElement ();
750 void WriteEncryptedKeyIdentifierClause (
751 XmlWriter w, EncryptedKeyIdentifierClause ic)
753 w.WriteStartElement ("e", "EncryptedKey", EncryptedXml.XmlEncNamespaceUrl);
754 w.WriteStartElement ("EncryptionMethod", EncryptedXml.XmlEncNamespaceUrl);
755 w.WriteAttributeString ("Algorithm", ic.EncryptionMethod);
756 w.WriteEndElement ();
757 if (ic.EncryptingKeyIdentifier != null) {
758 w.WriteStartElement ("KeyInfo", SignedXml.XmlDsigNamespaceUrl);
759 foreach (SecurityKeyIdentifierClause ckic in ic.EncryptingKeyIdentifier)
760 WriteKeyIdentifierClause (w, ckic);
761 w.WriteEndElement ();
763 w.WriteStartElement ("CipherData", EncryptedXml.XmlEncNamespaceUrl);
764 w.WriteStartElement ("CipherValue", EncryptedXml.XmlEncNamespaceUrl);
765 w.WriteString (Convert.ToBase64String (ic.GetEncryptedKey ()));
766 w.WriteEndElement ();
767 w.WriteEndElement ();
768 if (ic.CarriedKeyName != null)
769 w.WriteElementString ("CarriedKeyName", EncryptedXml.XmlEncNamespaceUrl, ic.CarriedKeyName);
770 w.WriteEndElement ();
773 void WriteBinarySecretKeyIdentifierClause (
774 XmlWriter w, BinarySecretKeyIdentifierClause ic)
776 w.WriteStartElement ("t", "BinarySecret", Constants.WstNamespace);
777 w.WriteString (Convert.ToBase64String (ic.GetBuffer ()));
778 w.WriteEndElement ();
781 void WriteInternalEncryptedKeyIdentifierClause (
782 XmlWriter w, InternalEncryptedKeyIdentifierClause ic)
784 w.WriteStartElement ("o", "SecurityTokenReference", Constants.WssNamespace);
785 w.WriteStartElement ("o", "KeyIdentifier", Constants.WssNamespace);
786 w.WriteAttributeString ("ValueType", Constants.WssKeyIdentifierEncryptedKey);
787 w.WriteString (Convert.ToBase64String (ic.GetBuffer ()));
788 w.WriteEndElement ();
789 w.WriteEndElement ();
792 void WriteSamlAssertionKeyIdentifierClause (XmlWriter w, SamlAssertionKeyIdentifierClause ic)
794 w.WriteStartElement ("o", "SecurityTokenReference", Constants.WssNamespace);
795 w.WriteStartElement ("o", "KeyIdentifier", Constants.WssNamespace);
796 w.WriteAttributeString ("ValueType", Constants.WssKeyIdentifierSamlAssertion);
797 w.WriteString (ic.AssertionId);
798 w.WriteEndElement ();
799 w.WriteEndElement ();
802 [MonoTODO]
803 protected override void WriteTokenCore (
804 XmlWriter writer, SecurityToken token)
806 // WSSecurity supports:
807 // - UsernameToken : S.IM.T.UserNameSecurityToken
808 // - X509SecurityToken : S.IM.T.X509SecurityToken
809 // - SAML Assertion : S.IM.T.SamlSecurityToken
810 // - Kerberos : S.IM.T.KerberosRequestorSecurityToken
811 // - Rights Expression Language (REL) : N/A
812 // - SOAP with Attachments : N/A
813 // they are part of standards support:
814 // - WrappedKey (EncryptedKey)
815 // - BinarySecret (WS-Trust)
816 // - SecurityContext (WS-SecureConversation)
817 // additionally there are extra token types in WCF:
818 // - GenericXml
819 // - Windows
820 // - Sspi
821 // not supported in this class:
822 // - Rsa
824 if (token is UserNameSecurityToken)
825 WriteUserNameSecurityToken (writer, ((UserNameSecurityToken) token));
826 else if (token is X509SecurityToken)
827 WriteX509SecurityToken (writer, ((X509SecurityToken) token));
828 else if (token is BinarySecretSecurityToken)
829 WriteBinarySecretSecurityToken (writer, ((BinarySecretSecurityToken) token));
830 else if (token is SamlSecurityToken)
831 throw new NotImplementedException ("WriteTokenCore() is not implemented for " + token);
832 else if (token is GenericXmlSecurityToken)
833 ((GenericXmlSecurityToken) token).TokenXml.WriteTo (writer);
834 else if (token is WrappedKeySecurityToken)
835 WriteWrappedKeySecurityToken (writer, (WrappedKeySecurityToken) token);
836 else if (token is DerivedKeySecurityToken)
837 WriteDerivedKeySecurityToken (writer, (DerivedKeySecurityToken) token);
838 else if (token is SecurityContextSecurityToken)
839 WriteSecurityContextSecurityToken (writer, (SecurityContextSecurityToken) token);
840 else if (token is SspiSecurityToken)
841 throw new NotImplementedException ("WriteTokenCore() is not implemented for " + token);
842 else if (token is KerberosRequestorSecurityToken)
843 throw new NotImplementedException ("WriteTokenCore() is not implemented for " + token);
844 else if (token is WindowsSecurityToken)
845 throw new NotImplementedException ("WriteTokenCore() is not implemented for " + token);
846 else
847 throw new InvalidOperationException (String.Format ("This SecurityTokenSerializer does not support security token '{0}'.", token));
850 void WriteUserNameSecurityToken (XmlWriter w, UserNameSecurityToken token)
852 w.WriteStartElement ("o", "UsernameToken", Constants.WssNamespace);
853 w.WriteAttributeString ("u", "Id", Constants.WsuNamespace, token.Id);
854 w.WriteStartElement ("o", "Username", Constants.WssNamespace);
855 w.WriteString (token.UserName);
856 w.WriteEndElement ();
857 w.WriteStartElement ("o", "Password", Constants.WssNamespace);
858 w.WriteString (token.Password);
859 w.WriteEndElement ();
860 w.WriteEndElement ();
863 void WriteX509SecurityToken (XmlWriter w, X509SecurityToken token)
865 w.WriteStartElement ("o", "BinarySecurityToken", Constants.WssNamespace);
866 w.WriteAttributeString ("u", "Id", Constants.WsuNamespace, token.Id);
867 w.WriteAttributeString ("ValueType", Constants.WSSX509Token);
868 w.WriteString (Convert.ToBase64String (token.Certificate.RawData));
869 w.WriteEndElement ();
872 void WriteBinarySecretSecurityToken (XmlWriter w, BinarySecretSecurityToken token)
874 w.WriteStartElement ("t", "BinarySecret", Constants.WstNamespace);
875 w.WriteAttributeString ("u", "Id", Constants.WsuNamespace, token.Id);
876 w.WriteString (Convert.ToBase64String (token.GetKeyBytes ()));
877 w.WriteEndElement ();
880 void WriteDerivedKeySecurityToken (XmlWriter w, DerivedKeySecurityToken token)
882 string ns = Constants.WsscNamespace;
883 w.WriteStartElement ("c", "DerivedKeyToken", ns);
884 w.WriteAttributeString ("u", "Id", Constants.WsuNamespace, token.Id);
885 WriteKeyIdentifierClause (w, token.TokenReference);
886 if (token.Name != null) {
887 w.WriteStartElement ("Properties", ns);
888 w.WriteElementString ("Name", ns, token.Name);
889 w.WriteEndElement ();
891 if (token.Offset != null)
892 w.WriteElementString ("Offset", ns, Convert.ToString (token.Offset));
893 if (token.Length != null)
894 w.WriteElementString ("Length", ns, Convert.ToString (token.Length));
895 if (token.Label != null)
896 w.WriteElementString ("Label", ns, token.Label);
897 w.WriteElementString ("Nonce", ns, Convert.ToBase64String (token.Nonce));
898 w.WriteEndElement ();
901 void WriteWrappedKeySecurityToken (XmlWriter w, WrappedKeySecurityToken token)
903 string encNS = EncryptedXml.XmlEncNamespaceUrl;
904 w.WriteStartElement ("e", "EncryptedKey", encNS);
905 w.WriteAttributeString ("Id", token.Id);
906 w.WriteStartElement ("EncryptionMethod", encNS);
907 w.WriteAttributeString ("Algorithm", token.WrappingAlgorithm);
908 w.WriteStartElement ("DigestMethod", SignedXml.XmlDsigNamespaceUrl);
909 w.WriteAttributeString ("Algorithm", SignedXml.XmlDsigSHA1Url);
910 w.WriteEndElement ();
911 w.WriteEndElement ();
913 w.WriteStartElement ("KeyInfo", SignedXml.XmlDsigNamespaceUrl);
914 if (token.WrappingTokenReference != null)
915 foreach (SecurityKeyIdentifierClause kic in token.WrappingTokenReference)
916 WriteKeyIdentifierClause (w, kic);
917 w.WriteEndElement ();
918 w.WriteStartElement ("CipherData", encNS);
919 w.WriteStartElement ("CipherValue", encNS);
920 w.WriteString (Convert.ToBase64String (token.GetWrappedKey ()));
921 w.WriteEndElement ();
922 w.WriteEndElement ();
923 if (token.ReferenceList != null) {
924 w.WriteStartElement ("e", "ReferenceList", encNS);
925 foreach (DataReference er in token.ReferenceList) {
926 w.WriteStartElement ("DataReference", encNS);
927 w.WriteAttributeString ("URI", er.Uri);
928 w.WriteEndElement ();
930 w.WriteEndElement ();
932 w.WriteEndElement ();
935 void WriteSecurityContextSecurityToken (XmlWriter w, SecurityContextSecurityToken token)
937 string ns = Constants.WsscNamespace;
938 w.WriteStartElement ("c", "SecurityContextToken", ns);
939 w.WriteAttributeString ("u", "Id", Constants.WsuNamespace, token.Id);
940 w.WriteElementString ("Identifier", ns, token.ContextId.ToString ());
941 // FIXME: add Cookie output (from CreateCookieSecurityContextToken() method)
942 if (token.Cookie != null)
943 w.WriteElementString ("dnse", "Cookie", Constants.MSTlsnegoTokenContent, Convert.ToBase64String (token.Cookie));
944 w.WriteEndElement ();