2014-08-13 10:39:27 +01:00
//
// WSSecurityTokenSerializer.cs
//
// Author:
// Atsushi Enomoto <atsushi@ximian.com>
//
// Copyright (C) 2006-2007 Novell, Inc. http://www.novell.com
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System ;
using System.Collections.Generic ;
using System.IdentityModel.Selectors ;
using System.IdentityModel.Tokens ;
using System.Security.Cryptography.X509Certificates ;
using System.Security.Cryptography.Xml ;
using System.ServiceModel.Security.Tokens ;
using System.Text ;
using System.Xml ;
namespace System.ServiceModel.Security
{
public class WSSecurityTokenSerializer : SecurityTokenSerializer
{
static WSSecurityTokenSerializer default_instance =
new WSSecurityTokenSerializer ( ) ;
public static WSSecurityTokenSerializer DefaultInstance {
get { return default_instance ; }
}
const int defaultOffset = 64 ,
defaultLabelLength = 128 ,
defaultNonceLength = 128 ;
public WSSecurityTokenSerializer ( )
: this ( false )
{
}
public WSSecurityTokenSerializer ( bool emitBspRequiredAttributes )
: this ( SecurityVersion . WSSecurity11 , emitBspRequiredAttributes )
{
}
public WSSecurityTokenSerializer ( SecurityVersion securityVersion )
: this ( securityVersion , false )
{
}
public WSSecurityTokenSerializer ( SecurityVersion securityVersion , bool emitBspRequiredAttributes )
: this ( securityVersion , emitBspRequiredAttributes , new SamlSerializer ( ) )
{
}
public WSSecurityTokenSerializer (
SecurityVersion securityVersion ,
bool emitBspRequiredAttributes ,
SamlSerializer samlSerializer )
: this ( securityVersion , emitBspRequiredAttributes ,
samlSerializer , null , null )
{
}
public WSSecurityTokenSerializer (
SecurityVersion securityVersion ,
bool emitBspRequiredAttributes ,
SamlSerializer samlSerializer ,
SecurityStateEncoder securityStateEncoder ,
IEnumerable < Type > knownTypes )
: this ( securityVersion , emitBspRequiredAttributes ,
samlSerializer , securityStateEncoder ,
knownTypes , defaultOffset , defaultLabelLength ,
defaultNonceLength )
{
}
public WSSecurityTokenSerializer (
SecurityVersion securityVersion ,
bool emitBspRequiredAttributes ,
SamlSerializer samlSerializer ,
SecurityStateEncoder securityStateEncoder ,
IEnumerable < Type > knownTypes ,
int maximumKeyDerivationOffset ,
int maximumKeyDerivationLabelLength ,
int maximumKeyDerivationNonceLength )
{
security_version = securityVersion ;
emit_bsp = emitBspRequiredAttributes ;
saml_serializer = samlSerializer ;
encoder = securityStateEncoder ;
known_types = new List < Type > ( knownTypes ? ? Type . EmptyTypes ) ;
max_offset = maximumKeyDerivationOffset ;
max_label_length = maximumKeyDerivationLabelLength ;
max_nonce_length = maximumKeyDerivationNonceLength ;
if ( encoder = = null )
encoder = new DataProtectionSecurityStateEncoder ( ) ;
}
SecurityVersion security_version ;
bool emit_bsp ;
SamlSerializer saml_serializer ;
SecurityStateEncoder encoder ;
List < Type > known_types ;
int max_offset , max_label_length , max_nonce_length ;
bool WSS1_0 {
get { return SecurityVersion = = SecurityVersion . WSSecurity10 ; }
}
public bool EmitBspRequiredAttributes {
get { return emit_bsp ; }
}
public SecurityVersion SecurityVersion {
get { return security_version ; }
}
[MonoTODO]
public int MaximumKeyDerivationOffset {
get { return max_offset ; }
}
[MonoTODO]
public int MaximumKeyDerivationLabelLength {
get { return max_label_length ; }
}
[MonoTODO]
public int MaximumKeyDerivationNonceLength {
get { return max_nonce_length ; }
}
protected virtual string GetTokenTypeUri ( Type tokenType )
{
if ( tokenType = = typeof ( WrappedKeySecurityToken ) )
return Constants . WSSEncryptedKeyToken ;
if ( tokenType = = typeof ( X509SecurityToken ) )
return Constants . WSSX509Token ;
// if (tokenType == typeof (RsaSecurityToken))
// return null;
if ( tokenType = = typeof ( SamlSecurityToken ) )
return Constants . WSSSamlToken ;
if ( tokenType = = typeof ( SecurityContextSecurityToken ) )
return Constants . WsscContextToken ;
// if (tokenType == typeof (huh))
// return ServiceModelSecurityTokenTypes.SecureConversation;
// if (tokenType == typeof (hah))
// return ServiceModelSecurityTokenTypes.MutualSslnego;
// if (tokenType == typeof (whoa))
// return ServiceModelSecurityTokenTypes.AnonymousSslnego;
if ( tokenType = = typeof ( UserNameSecurityToken ) )
return Constants . WSSUserNameToken ;
// if (tokenType == typeof (uhoh))
// return ServiceModelSecurityTokenTypes.Spnego;
// if (tokenType == typeof (SspiSecurityToken))
// return ServiceModelSecurityTokenTypes.SspiCredential;
if ( tokenType = = typeof ( KerberosRequestorSecurityToken ) )
return Constants . WSSKerberosToken ;
return null ;
}
[MonoTODO]
protected override bool CanReadKeyIdentifierClauseCore ( XmlReader reader )
{
reader . MoveToContent ( ) ;
switch ( reader . NamespaceURI ) {
case EncryptedXml . XmlEncNamespaceUrl :
switch ( reader . LocalName ) {
case "EncryptedKey" :
return true ;
}
break ;
case Constants . WssNamespace :
switch ( reader . LocalName ) {
case "SecurityTokenReference" :
return true ;
}
break ;
}
return false ;
}
[MonoTODO]
protected override bool CanReadKeyIdentifierCore ( XmlReader reader )
{
throw new NotImplementedException ( ) ;
}
[MonoTODO]
protected override bool CanReadTokenCore ( XmlReader reader )
{
reader . MoveToContent ( ) ;
switch ( reader . NamespaceURI ) {
case Constants . WssNamespace :
switch ( reader . LocalName ) {
case "BinarySecurityToken" :
case "BinarySecret" :
case "UsernameToken" :
return true ;
}
break ;
case Constants . WsscNamespace :
switch ( reader . LocalName ) {
case "DerivedKeyToken" :
case "SecurityContextToken" :
return true ;
}
break ;
case EncryptedXml . XmlEncNamespaceUrl :
switch ( reader . LocalName ) {
case "EncryptedKey" :
return true ;
}
break ;
}
return false ;
}
[MonoTODO]
public virtual SecurityKeyIdentifierClause CreateKeyIdentifierClauseFromTokenXml (
2017-06-07 13:16:24 +00:00
XmlElement element , SecurityTokenReferenceStyle tokenReferenceStyle )
2014-08-13 10:39:27 +01:00
{
throw new NotImplementedException ( ) ;
}
[MonoTODO]
protected override SecurityKeyIdentifier ReadKeyIdentifierCore (
XmlReader reader )
{
throw new NotImplementedException ( ) ;
}
[MonoTODO]
protected override SecurityKeyIdentifierClause ReadKeyIdentifierClauseCore ( XmlReader reader )
{
reader . MoveToContent ( ) ;
switch ( reader . NamespaceURI ) {
case EncryptedXml . XmlEncNamespaceUrl :
switch ( reader . LocalName ) {
case "EncryptedKey" :
return ReadEncryptedKeyIdentifierClause ( reader ) ;
}
break ;
case Constants . WssNamespace :
switch ( reader . LocalName ) {
case "SecurityTokenReference" :
return ReadSecurityTokenReference ( reader ) ;
}
break ;
}
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 ) ) ;
}
SecurityKeyIdentifierClause ReadSecurityTokenReference ( XmlReader reader )
{
reader . ReadStartElement ( ) ;
reader . MoveToContent ( ) ;
if ( reader . NamespaceURI = = SignedXml . XmlDsigNamespaceUrl ) {
KeyInfoX509Data x509 = new KeyInfoX509Data ( ) ;
x509 . LoadXml ( new XmlDocument ( ) . ReadNode ( reader ) as XmlElement ) ;
if ( x509 . IssuerSerials . Count = = 0 )
throw new XmlException ( "'X509IssuerSerial' element is expected inside 'X509Data' element" ) ;
X509IssuerSerial s = ( X509IssuerSerial ) x509 . IssuerSerials [ 0 ] ;
reader . MoveToContent ( ) ;
reader . ReadEndElement ( ) ;
return new X509IssuerSerialKeyIdentifierClause ( s . IssuerName , s . SerialNumber ) ;
}
if ( reader . NamespaceURI ! = Constants . WssNamespace )
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 ) ) ;
switch ( reader . LocalName ) {
case "Reference" :
Type ownerType = null ;
// FIXME: there could be more token types.
if ( reader . MoveToAttribute ( "ValueType" ) ) {
switch ( reader . Value ) {
case Constants . WSSEncryptedKeyToken :
ownerType = typeof ( WrappedKeySecurityToken ) ;
break ;
case Constants . WSSX509Token :
ownerType = typeof ( X509SecurityToken ) ;
break ;
case Constants . WsscContextToken :
ownerType = typeof ( SecurityContextSecurityToken ) ;
break ;
default :
throw new XmlException ( String . Format ( "Unexpected ValueType in 'Reference' element: '{0}'" , reader . Value ) ) ;
}
}
reader . MoveToElement ( ) ;
string uri = reader . GetAttribute ( "URI" ) ;
if ( String . IsNullOrEmpty ( uri ) )
uri = "#" ;
SecurityKeyIdentifierClause ic = null ;
if ( ownerType = = typeof ( SecurityContextSecurityToken ) & & uri [ 0 ] ! = '#' )
// FIXME: Generation?
ic = new SecurityContextKeyIdentifierClause ( new UniqueId ( uri ) ) ;
else
ic = new LocalIdKeyIdentifierClause ( uri . Substring ( 1 ) , ownerType ) ;
reader . Skip ( ) ;
reader . MoveToContent ( ) ;
reader . ReadEndElement ( ) ;
return ic ;
case "KeyIdentifier" :
string valueType = reader . GetAttribute ( "ValueType" ) ;
string value = reader . ReadElementContentAsString ( ) ;
reader . MoveToContent ( ) ;
reader . ReadEndElement ( ) ; // consume </Reference>
switch ( valueType ) {
case Constants . WssKeyIdentifierX509Thumbptint :
return new X509ThumbprintKeyIdentifierClause ( Convert . FromBase64String ( value ) ) ;
case Constants . WssKeyIdentifierEncryptedKey :
return new InternalEncryptedKeyIdentifierClause ( Convert . FromBase64String ( value ) ) ;
case Constants . WssKeyIdentifierSamlAssertion :
return new SamlAssertionKeyIdentifierClause ( value ) ;
default :
// It is kinda weird but it throws XmlException here ...
throw new XmlException ( String . Format ( "KeyIdentifier type '{0}' is not supported in WSSecurityTokenSerializer." , valueType ) ) ;
}
default :
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 ) ) ;
}
}
EncryptedKeyIdentifierClause ReadEncryptedKeyIdentifierClause (
XmlReader reader )
{
string encNS = EncryptedXml . XmlEncNamespaceUrl ;
string id = reader . GetAttribute ( "Id" , Constants . WsuNamespace ) ;
reader . Read ( ) ;
reader . MoveToContent ( ) ;
string encMethod = reader . GetAttribute ( "Algorithm" ) ;
bool isEmpty = reader . IsEmptyElement ;
reader . ReadStartElement ( "EncryptionMethod" , encNS ) ;
string digMethod = null ;
if ( ! isEmpty ) {
reader . MoveToContent ( ) ;
if ( reader . LocalName = = "DigestMethod" & & reader . NamespaceURI = = SignedXml . XmlDsigNamespaceUrl )
digMethod = reader . GetAttribute ( "Algorithm" ) ;
while ( reader . NodeType ! = XmlNodeType . EndElement ) {
reader . Skip ( ) ;
reader . MoveToContent ( ) ;
}
reader . ReadEndElement ( ) ;
}
reader . MoveToContent ( ) ;
SecurityKeyIdentifier ki = null ;
if ( ! reader . IsEmptyElement ) {
reader . ReadStartElement ( "KeyInfo" , SignedXml . XmlDsigNamespaceUrl ) ;
reader . MoveToContent ( ) ;
SecurityKeyIdentifierClause kic = ReadKeyIdentifierClauseCore ( reader ) ;
ki = new SecurityKeyIdentifier ( ) ;
ki . Add ( kic ) ;
reader . MoveToContent ( ) ;
reader . ReadEndElement ( ) ; // </ds:KeyInfo>
reader . MoveToContent ( ) ;
}
byte [ ] keyValue = null ;
if ( ! reader . IsEmptyElement ) {
reader . ReadStartElement ( "CipherData" , encNS ) ;
reader . MoveToContent ( ) ;
keyValue = Convert . FromBase64String ( reader . ReadElementContentAsString ( "CipherValue" , encNS ) ) ;
reader . MoveToContent ( ) ;
reader . ReadEndElement ( ) ; // CipherData
}
string carriedKeyName = null ;
if ( ! reader . IsEmptyElement & & reader . LocalName = = "CarriedKeyName" & & reader . NamespaceURI = = encNS ) {
carriedKeyName = reader . ReadElementContentAsString ( ) ;
reader . MoveToContent ( ) ;
}
// FIXME: handle derived keys??
return new EncryptedKeyIdentifierClause ( keyValue , encMethod , ki , carriedKeyName ) ;
}
[MonoTODO]
protected override SecurityToken ReadTokenCore (
XmlReader reader ,
SecurityTokenResolver tokenResolver )
{
if ( ! CanReadToken ( reader ) )
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 ) ) ;
switch ( reader . NamespaceURI ) {
case Constants . WssNamespace :
switch ( reader . LocalName ) {
case "BinarySecurityToken" :
return ReadX509TokenCore ( reader , tokenResolver ) ;
case "BinarySecret" :
return ReadBinarySecretTokenCore ( reader , tokenResolver ) ;
case "UsernameToken" :
return ReadUserNameTokenCore ( reader , tokenResolver ) ;
}
break ;
case Constants . WsscNamespace :
if ( reader . LocalName = = "DerivedKeyToken" )
return ReadDerivedKeyToken ( reader , tokenResolver ) ;
if ( reader . LocalName = = "SecurityContextToken" )
return ReadSecurityContextToken ( reader , tokenResolver ) ;
break ;
case EncryptedXml . XmlEncNamespaceUrl :
switch ( reader . LocalName ) {
case "EncryptedKey" :
return ReadWrappedKeySecurityTokenCore ( reader , tokenResolver ) ;
}
break ;
}
throw new NotImplementedException ( ) ;
}
DerivedKeySecurityToken ReadDerivedKeyToken (
XmlReader reader , SecurityTokenResolver tokenResolver )
{
try {
return ReadDerivedKeyTokenCore ( reader , tokenResolver ) ;
} catch ( XmlException ) {
throw ;
} catch ( Exception ex ) {
throw new XmlException ( "Cannot read DerivedKeyToken" , ex ) ;
}
}
DerivedKeySecurityToken ReadDerivedKeyTokenCore (
XmlReader reader , SecurityTokenResolver tokenResolver )
{
if ( tokenResolver = = null )
throw new ArgumentNullException ( "tokenResolver" ) ;
string id = reader . GetAttribute ( "Id" , Constants . WsuNamespace ) ;
string algorithm = reader . MoveToAttribute ( "Algorithm" ) ? reader . Value : null ;
reader . MoveToElement ( ) ;
reader . ReadStartElement ( ) ;
reader . MoveToContent ( ) ;
SecurityKeyIdentifierClause kic = ReadKeyIdentifierClause ( reader ) ;
int? generation = null , offset = null , length = null ;
byte [ ] nonce = null ;
string name = null , label = null ;
for ( reader . MoveToContent ( ) ;
reader . NodeType ! = XmlNodeType . EndElement ;
reader . MoveToContent ( ) )
switch ( reader . LocalName ) {
case "Properties" :
reader . ReadStartElement ( "Properties" , Constants . WsscNamespace ) ;
for ( reader . MoveToContent ( ) ;
reader . NodeType ! = XmlNodeType . EndElement ;
reader . MoveToContent ( ) )
switch ( reader . LocalName ) {
case "Name" :
name = reader . ReadElementContentAsString ( "Name" , Constants . WsscNamespace ) ;
break ;
case "Label" :
label = reader . ReadElementContentAsString ( "Label" , Constants . WsscNamespace ) ;
break ;
case "Nonce" :
nonce = Convert . FromBase64String ( reader . ReadElementContentAsString ( "Nonce" , Constants . WsscNamespace ) ) ;
break ;
}
reader . ReadEndElement ( ) ;
break ;
case "Offset" :
offset = reader . ReadElementContentAsInt ( "Offset" , Constants . WsscNamespace ) ;
break ;
case "Length" :
length = reader . ReadElementContentAsInt ( "Length" , Constants . WsscNamespace ) ;
break ;
case "Nonce" :
nonce = Convert . FromBase64String ( reader . ReadElementContentAsString ( "Nonce" , Constants . WsscNamespace ) ) ;
break ;
case "Label" :
label = reader . ReadElementContentAsString ( "Label" , Constants . WsscNamespace ) ;
break ;
}
reader . ReadEndElement ( ) ;
// resolve key reference
SymmetricSecurityKey key = tokenResolver . ResolveSecurityKey ( kic ) as SymmetricSecurityKey ;
if ( key = = null )
throw new XmlException ( "Cannot resolve the security key referenced by the DerivedKeyToken as a symmetric key" ) ;
return new DerivedKeySecurityToken ( id , algorithm , kic , key , name , generation , offset , length , label , nonce ) ;
}
// since it cannot consume RequestSecurityTokenResponse,
// the token information cannot be complete.
SecurityContextSecurityToken ReadSecurityContextToken (
XmlReader reader , SecurityTokenResolver tokenResolver )
{
string id = reader . GetAttribute ( "Id" , Constants . WsuNamespace ) ;
reader . Read ( ) ;
// The input dnse:Cookie value is encrypted by the
// server's SecurityStateEncoder
// (setting error-raising encoder to ServiceCredentials.
// SecureConversationAuthentication.SecurityStateEncoder
// shows it).
UniqueId cid = null ;
byte [ ] cookie = null ;
while ( true ) {
reader . MoveToContent ( ) ;
if ( reader . NodeType ! = XmlNodeType . Element )
break ;
switch ( reader . NamespaceURI ) {
case Constants . WsscNamespace :
switch ( reader . LocalName ) {
case "Identifier" :
cid = new UniqueId ( reader . ReadElementContentAsString ( ) ) ;
continue ;
}
break ;
case Constants . MSTlsnegoTokenContent :
switch ( reader . LocalName ) {
case "Cookie" :
cookie = Convert . FromBase64String ( reader . ReadElementContentAsString ( ) ) ;
continue ;
}
break ;
}
throw new XmlException ( String . Format ( "Unexpected element {0} in namespace {1}" , reader . LocalName , reader . NamespaceURI ) ) ;
}
reader . ReadEndElement ( ) ;
// LAMESPEC: at client side there is no way to specify
// SecurityStateEncoder, so it must be guessed from
// its cookie content itself.
if ( encoder = = null ) throw new Exception ( ) ;
byte [ ] decoded =
cookie ! = null & & cookie . Length > 154 ?
encoder . DecodeSecurityState ( cookie ) :
cookie ;
return SslnegoCookieResolver . ResolveCookie ( decoded , cookie ) ;
}
WrappedKeySecurityToken ReadWrappedKeySecurityTokenCore (
XmlReader reader , SecurityTokenResolver tokenResolver )
{
if ( tokenResolver = = null )
throw new ArgumentNullException ( "tokenResolver" ) ;
EncryptedKey ek = new EncryptedKey ( ) ;
ek . LoadXml ( new XmlDocument ( ) . ReadNode ( reader ) as XmlElement ) ;
SecurityKeyIdentifier ki = new SecurityKeyIdentifier ( ) ;
foreach ( KeyInfoClause kic in ek . KeyInfo )
ki . Add ( ReadKeyIdentifierClause ( new XmlNodeReader ( kic . GetXml ( ) ) ) ) ;
SecurityToken token = tokenResolver . ResolveToken ( ki ) ;
string alg = ek . EncryptionMethod . KeyAlgorithm ;
foreach ( SecurityKey skey in token . SecurityKeys )
if ( skey . IsSupportedAlgorithm ( alg ) ) {
byte [ ] key = skey . DecryptKey ( alg , ek . CipherData . CipherValue ) ;
WrappedKeySecurityToken wk =
new WrappedKeySecurityToken ( ek . Id , key , alg , token , ki ) ;
// FIXME: This should not be required.
wk . SetWrappedKey ( ek . CipherData . CipherValue ) ;
wk . ReferenceList = ek . ReferenceList ;
return wk ;
}
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 ) ) ;
}
X509SecurityToken ReadX509TokenCore (
XmlReader reader , SecurityTokenResolver resolver )
{
string id = reader . GetAttribute ( "Id" , Constants . WsuNamespace ) ;
byte [ ] raw = Convert . FromBase64String ( reader . ReadElementContentAsString ( ) ) ;
return new X509SecurityToken ( new X509Certificate2 ( raw ) , id ) ;
}
UserNameSecurityToken ReadUserNameTokenCore (
XmlReader reader , SecurityTokenResolver resolver )
{
string id = reader . GetAttribute ( "Id" , Constants . WsuNamespace ) ;
if ( reader . IsEmptyElement )
throw new XmlException ( "At least UsernameToken must contain Username" ) ;
reader . Read ( ) ;
reader . MoveToContent ( ) ;
string user = reader . ReadElementContentAsString ( "Username" , Constants . WssNamespace ) ;
reader . MoveToContent ( ) ;
string pass = null ;
if ( reader . LocalName = = "Password" & & reader . NamespaceURI = = Constants . WssNamespace ) {
pass = reader . ReadElementContentAsString ( "Password" , Constants . WssNamespace ) ;
reader . MoveToContent ( ) ;
}
reader . ReadEndElement ( ) ;
return id ! = null ?
new UserNameSecurityToken ( user , pass , id ) :
new UserNameSecurityToken ( user , pass ) ;
}
BinarySecretSecurityToken ReadBinarySecretTokenCore (
XmlReader reader , SecurityTokenResolver resolver )
{
string id = reader . GetAttribute ( "Id" , Constants . WsuNamespace ) ;
byte [ ] data = Convert . FromBase64String ( reader . ReadElementContentAsString ( ) ) ;
return new BinarySecretSecurityToken ( id , data ) ;
}
[MonoTODO]
protected override bool CanWriteKeyIdentifierCore (
SecurityKeyIdentifier keyIdentifier )
{
throw new NotImplementedException ( ) ;
}
[MonoTODO]
protected override bool CanWriteKeyIdentifierClauseCore (
SecurityKeyIdentifierClause keyIdentifierClause )
{
if ( keyIdentifierClause = = null )
throw new ArgumentNullException ( "keyIdentifierClause" ) ;
if ( keyIdentifierClause is LocalIdKeyIdentifierClause | |
keyIdentifierClause is SecurityContextKeyIdentifierClause | |
keyIdentifierClause is X509IssuerSerialKeyIdentifierClause | |
( keyIdentifierClause is X509ThumbprintKeyIdentifierClause & & ! WSS1_0 ) | |
keyIdentifierClause is EncryptedKeyIdentifierClause | |
keyIdentifierClause is BinarySecretKeyIdentifierClause | |
keyIdentifierClause is InternalEncryptedKeyIdentifierClause | |
keyIdentifierClause is SamlAssertionKeyIdentifierClause )
return true ;
else
return false ;
}
[MonoTODO]
protected override bool CanWriteTokenCore ( SecurityToken token )
{
throw new NotImplementedException ( ) ;
}
[MonoTODO]
protected override void WriteKeyIdentifierCore (
XmlWriter writer ,
SecurityKeyIdentifier keyIdentifier )
{
throw new NotImplementedException ( ) ;
}
[MonoTODO]
protected override void WriteKeyIdentifierClauseCore (
XmlWriter writer ,
SecurityKeyIdentifierClause keyIdentifierClause )
{
string errorReason = null ;
if ( keyIdentifierClause = = null )
throw new ArgumentNullException ( "keyIdentifierClause" ) ;
if ( keyIdentifierClause is LocalIdKeyIdentifierClause )
WriteLocalIdKeyIdentifierClause ( writer , ( LocalIdKeyIdentifierClause ) keyIdentifierClause ) ;
else if ( keyIdentifierClause is SecurityContextKeyIdentifierClause )
WriteSecurityContextKeyIdentifierClause ( writer , ( SecurityContextKeyIdentifierClause ) keyIdentifierClause ) ;
else if ( keyIdentifierClause is X509IssuerSerialKeyIdentifierClause )
WriteX509IssuerSerialKeyIdentifierClause ( writer , ( X509IssuerSerialKeyIdentifierClause ) keyIdentifierClause ) ;
else if ( keyIdentifierClause is X509ThumbprintKeyIdentifierClause ) {
if ( WSS1_0 )
errorReason = String . Format ( "Security key identifier clause '{0}' is not supported in this serializer." , keyIdentifierClause . GetType ( ) ) ;
else
WriteX509ThumbprintKeyIdentifierClause ( writer , ( X509ThumbprintKeyIdentifierClause ) keyIdentifierClause ) ;
}
else if ( keyIdentifierClause is EncryptedKeyIdentifierClause )
WriteEncryptedKeyIdentifierClause ( writer , ( EncryptedKeyIdentifierClause ) keyIdentifierClause ) ;
else if ( keyIdentifierClause is BinarySecretKeyIdentifierClause )
WriteBinarySecretKeyIdentifierClause ( writer , ( BinarySecretKeyIdentifierClause ) keyIdentifierClause ) ;
else if ( keyIdentifierClause is InternalEncryptedKeyIdentifierClause )
WriteInternalEncryptedKeyIdentifierClause ( writer , ( InternalEncryptedKeyIdentifierClause ) keyIdentifierClause ) ;
else if ( keyIdentifierClause is SamlAssertionKeyIdentifierClause )
WriteSamlAssertionKeyIdentifierClause ( writer , ( SamlAssertionKeyIdentifierClause ) keyIdentifierClause ) ;
else
throw new NotImplementedException ( String . Format ( "Security key identifier clause '{0}' is not either implemented or supported." , keyIdentifierClause . GetType ( ) ) ) ;
if ( errorReason ! = null )
throw new InvalidOperationException ( errorReason ) ;
}
void WriteX509IssuerSerialKeyIdentifierClause (
XmlWriter w , X509IssuerSerialKeyIdentifierClause ic )
{
w . WriteStartElement ( "o" , "SecurityTokenReference" , Constants . WssNamespace ) ;
w . WriteStartElement ( "X509Data" , Constants . XmlDsig ) ;
w . WriteStartElement ( "X509IssuerSerial" , Constants . XmlDsig ) ;
w . WriteStartElement ( "X509IssuerName" , Constants . XmlDsig ) ;
w . WriteString ( ic . IssuerName ) ;
w . WriteEndElement ( ) ;
w . WriteStartElement ( "X509SerialNumber" , Constants . XmlDsig ) ;
w . WriteString ( ic . IssuerSerialNumber ) ;
w . WriteEndElement ( ) ;
w . WriteEndElement ( ) ;
w . WriteEndElement ( ) ;
w . WriteEndElement ( ) ;
}
void WriteX509ThumbprintKeyIdentifierClause (
XmlWriter w , X509ThumbprintKeyIdentifierClause ic )
{
w . WriteStartElement ( "o" , "SecurityTokenReference" , Constants . WssNamespace ) ;
w . WriteStartElement ( "o" , "KeyIdentifier" , Constants . WssNamespace ) ;
w . WriteAttributeString ( "ValueType" , Constants . WssKeyIdentifierX509Thumbptint ) ;
if ( EmitBspRequiredAttributes )
w . WriteAttributeString ( "EncodingType" , Constants . WssBase64BinaryEncodingType ) ;
w . WriteString ( Convert . ToBase64String ( ic . GetX509Thumbprint ( ) ) ) ;
w . WriteEndElement ( ) ;
w . WriteEndElement ( ) ;
}
void WriteLocalIdKeyIdentifierClause (
XmlWriter w , LocalIdKeyIdentifierClause ic )
{
w . WriteStartElement ( "o" , "SecurityTokenReference" , Constants . WssNamespace ) ;
w . WriteStartElement ( "o" , "Reference" , Constants . WssNamespace ) ;
if ( EmitBspRequiredAttributes & & ic . OwnerType ! = null ) {
string vt = GetTokenTypeUri ( ic . OwnerType ) ;
if ( vt ! = null )
w . WriteAttributeString ( "ValueType" , vt ) ;
}
w . WriteAttributeString ( "URI" , "#" + ic . LocalId ) ;
w . WriteEndElement ( ) ;
w . WriteEndElement ( ) ;
}
void WriteSecurityContextKeyIdentifierClause (
XmlWriter w , SecurityContextKeyIdentifierClause ic )
{
w . WriteStartElement ( "o" , "SecurityTokenReference" , Constants . WssNamespace ) ;
w . WriteStartElement ( "o" , "Reference" , Constants . WssNamespace ) ;
w . WriteAttributeString ( "URI" , ic . ContextId . ToString ( ) ) ;
string vt = GetTokenTypeUri ( typeof ( SecurityContextSecurityToken ) ) ;
w . WriteAttributeString ( "ValueType" , vt ) ;
w . WriteEndElement ( ) ;
w . WriteEndElement ( ) ;
}
void WriteEncryptedKeyIdentifierClause (
XmlWriter w , EncryptedKeyIdentifierClause ic )
{
w . WriteStartElement ( "e" , "EncryptedKey" , EncryptedXml . XmlEncNamespaceUrl ) ;
w . WriteStartElement ( "EncryptionMethod" , EncryptedXml . XmlEncNamespaceUrl ) ;
w . WriteAttributeString ( "Algorithm" , ic . EncryptionMethod ) ;
w . WriteEndElement ( ) ;
if ( ic . EncryptingKeyIdentifier ! = null ) {
w . WriteStartElement ( "KeyInfo" , SignedXml . XmlDsigNamespaceUrl ) ;
foreach ( SecurityKeyIdentifierClause ckic in ic . EncryptingKeyIdentifier )
WriteKeyIdentifierClause ( w , ckic ) ;
w . WriteEndElement ( ) ;
}
w . WriteStartElement ( "CipherData" , EncryptedXml . XmlEncNamespaceUrl ) ;
w . WriteStartElement ( "CipherValue" , EncryptedXml . XmlEncNamespaceUrl ) ;
w . WriteString ( Convert . ToBase64String ( ic . GetEncryptedKey ( ) ) ) ;
w . WriteEndElement ( ) ;
w . WriteEndElement ( ) ;
if ( ic . CarriedKeyName ! = null )
w . WriteElementString ( "CarriedKeyName" , EncryptedXml . XmlEncNamespaceUrl , ic . CarriedKeyName ) ;
w . WriteEndElement ( ) ;
}
void WriteBinarySecretKeyIdentifierClause (
XmlWriter w , BinarySecretKeyIdentifierClause ic )
{
w . WriteStartElement ( "t" , "BinarySecret" , Constants . WstNamespace ) ;
w . WriteString ( Convert . ToBase64String ( ic . GetBuffer ( ) ) ) ;
w . WriteEndElement ( ) ;
}
void WriteInternalEncryptedKeyIdentifierClause (
XmlWriter w , InternalEncryptedKeyIdentifierClause ic )
{
w . WriteStartElement ( "o" , "SecurityTokenReference" , Constants . WssNamespace ) ;
w . WriteStartElement ( "o" , "KeyIdentifier" , Constants . WssNamespace ) ;
w . WriteAttributeString ( "ValueType" , Constants . WssKeyIdentifierEncryptedKey ) ;
w . WriteString ( Convert . ToBase64String ( ic . GetBuffer ( ) ) ) ;
w . WriteEndElement ( ) ;
w . WriteEndElement ( ) ;
}
void WriteSamlAssertionKeyIdentifierClause ( XmlWriter w , SamlAssertionKeyIdentifierClause ic )
{
w . WriteStartElement ( "o" , "SecurityTokenReference" , Constants . WssNamespace ) ;
w . WriteStartElement ( "o" , "KeyIdentifier" , Constants . WssNamespace ) ;
w . WriteAttributeString ( "ValueType" , Constants . WssKeyIdentifierSamlAssertion ) ;
w . WriteString ( ic . AssertionId ) ;
w . WriteEndElement ( ) ;
w . WriteEndElement ( ) ;
}
[MonoTODO]
protected override void WriteTokenCore (
XmlWriter writer , SecurityToken token )
{
// WSSecurity supports:
// - UsernameToken : S.IM.T.UserNameSecurityToken
// - X509SecurityToken : S.IM.T.X509SecurityToken
// - SAML Assertion : S.IM.T.SamlSecurityToken
// - Kerberos : S.IM.T.KerberosRequestorSecurityToken
// - Rights Expression Language (REL) : N/A
// - SOAP with Attachments : N/A
// they are part of standards support:
// - WrappedKey (EncryptedKey)
// - BinarySecret (WS-Trust)
// - SecurityContext (WS-SecureConversation)
// additionally there are extra token types in WCF:
// - GenericXml
// - Windows
// - Sspi
// not supported in this class:
// - Rsa
if ( token is UserNameSecurityToken )
WriteUserNameSecurityToken ( writer , ( ( UserNameSecurityToken ) token ) ) ;
else if ( token is X509SecurityToken )
WriteX509SecurityToken ( writer , ( ( X509SecurityToken ) token ) ) ;
else if ( token is BinarySecretSecurityToken )
WriteBinarySecretSecurityToken ( writer , ( ( BinarySecretSecurityToken ) token ) ) ;
else if ( token is SamlSecurityToken )
throw new NotImplementedException ( "WriteTokenCore() is not implemented for " + token ) ;
else if ( token is GenericXmlSecurityToken )
( ( GenericXmlSecurityToken ) token ) . TokenXml . WriteTo ( writer ) ;
else if ( token is WrappedKeySecurityToken )
WriteWrappedKeySecurityToken ( writer , ( WrappedKeySecurityToken ) token ) ;
else if ( token is DerivedKeySecurityToken )
WriteDerivedKeySecurityToken ( writer , ( DerivedKeySecurityToken ) token ) ;
else if ( token is SecurityContextSecurityToken )
WriteSecurityContextSecurityToken ( writer , ( SecurityContextSecurityToken ) token ) ;
else if ( token is SspiSecurityToken )
throw new NotImplementedException ( "WriteTokenCore() is not implemented for " + token ) ;
else if ( token is KerberosRequestorSecurityToken )
throw new NotImplementedException ( "WriteTokenCore() is not implemented for " + token ) ;
else if ( token is WindowsSecurityToken )
throw new NotImplementedException ( "WriteTokenCore() is not implemented for " + token ) ;
else
throw new InvalidOperationException ( String . Format ( "This SecurityTokenSerializer does not support security token '{0}'." , token ) ) ;
}
void WriteUserNameSecurityToken ( XmlWriter w , UserNameSecurityToken token )
{
w . WriteStartElement ( "o" , "UsernameToken" , Constants . WssNamespace ) ;
w . WriteAttributeString ( "u" , "Id" , Constants . WsuNamespace , token . Id ) ;
w . WriteStartElement ( "o" , "Username" , Constants . WssNamespace ) ;
w . WriteString ( token . UserName ) ;
w . WriteEndElement ( ) ;
w . WriteStartElement ( "o" , "Password" , Constants . WssNamespace ) ;
w . WriteString ( token . Password ) ;
w . WriteEndElement ( ) ;
w . WriteEndElement ( ) ;
}
void WriteX509SecurityToken ( XmlWriter w , X509SecurityToken token )
{
w . WriteStartElement ( "o" , "BinarySecurityToken" , Constants . WssNamespace ) ;
w . WriteAttributeString ( "u" , "Id" , Constants . WsuNamespace , token . Id ) ;
w . WriteAttributeString ( "ValueType" , Constants . WSSX509Token ) ;
w . WriteString ( Convert . ToBase64String ( token . Certificate . RawData ) ) ;
w . WriteEndElement ( ) ;
}
void WriteBinarySecretSecurityToken ( XmlWriter w , BinarySecretSecurityToken token )
{
w . WriteStartElement ( "t" , "BinarySecret" , Constants . WstNamespace ) ;
w . WriteAttributeString ( "u" , "Id" , Constants . WsuNamespace , token . Id ) ;
w . WriteString ( Convert . ToBase64String ( token . GetKeyBytes ( ) ) ) ;
w . WriteEndElement ( ) ;
}
void WriteDerivedKeySecurityToken ( XmlWriter w , DerivedKeySecurityToken token )
{
string ns = Constants . WsscNamespace ;
w . WriteStartElement ( "c" , "DerivedKeyToken" , ns ) ;
w . WriteAttributeString ( "u" , "Id" , Constants . WsuNamespace , token . Id ) ;
WriteKeyIdentifierClause ( w , token . TokenReference ) ;
if ( token . Name ! = null ) {
w . WriteStartElement ( "Properties" , ns ) ;
w . WriteElementString ( "Name" , ns , token . Name ) ;
w . WriteEndElement ( ) ;
}
if ( token . Offset ! = null )
w . WriteElementString ( "Offset" , ns , Convert . ToString ( token . Offset ) ) ;
if ( token . Length ! = null )
w . WriteElementString ( "Length" , ns , Convert . ToString ( token . Length ) ) ;
if ( token . Label ! = null )
w . WriteElementString ( "Label" , ns , token . Label ) ;
w . WriteElementString ( "Nonce" , ns , Convert . ToBase64String ( token . Nonce ) ) ;
w . WriteEndElement ( ) ;
}
void WriteWrappedKeySecurityToken ( XmlWriter w , WrappedKeySecurityToken token )
{
string encNS = EncryptedXml . XmlEncNamespaceUrl ;
w . WriteStartElement ( "e" , "EncryptedKey" , encNS ) ;
w . WriteAttributeString ( "Id" , token . Id ) ;
w . WriteStartElement ( "EncryptionMethod" , encNS ) ;
w . WriteAttributeString ( "Algorithm" , token . WrappingAlgorithm ) ;
w . WriteStartElement ( "DigestMethod" , SignedXml . XmlDsigNamespaceUrl ) ;
w . WriteAttributeString ( "Algorithm" , SignedXml . XmlDsigSHA1Url ) ;
w . WriteEndElement ( ) ;
w . WriteEndElement ( ) ;
w . WriteStartElement ( "KeyInfo" , SignedXml . XmlDsigNamespaceUrl ) ;
if ( token . WrappingTokenReference ! = null )
foreach ( SecurityKeyIdentifierClause kic in token . WrappingTokenReference )
WriteKeyIdentifierClause ( w , kic ) ;
w . WriteEndElement ( ) ;
w . WriteStartElement ( "CipherData" , encNS ) ;
w . WriteStartElement ( "CipherValue" , encNS ) ;
w . WriteString ( Convert . ToBase64String ( token . GetWrappedKey ( ) ) ) ;
w . WriteEndElement ( ) ;
w . WriteEndElement ( ) ;
if ( token . ReferenceList ! = null ) {
w . WriteStartElement ( "e" , "ReferenceList" , encNS ) ;
foreach ( DataReference er in token . ReferenceList ) {
w . WriteStartElement ( "DataReference" , encNS ) ;
w . WriteAttributeString ( "URI" , er . Uri ) ;
w . WriteEndElement ( ) ;
}
w . WriteEndElement ( ) ;
}
w . WriteEndElement ( ) ;
}
void WriteSecurityContextSecurityToken ( XmlWriter w , SecurityContextSecurityToken token )
{
string ns = Constants . WsscNamespace ;
w . WriteStartElement ( "c" , "SecurityContextToken" , ns ) ;
w . WriteAttributeString ( "u" , "Id" , Constants . WsuNamespace , token . Id ) ;
w . WriteElementString ( "Identifier" , ns , token . ContextId . ToString ( ) ) ;
// FIXME: add Cookie output (from CreateCookieSecurityContextToken() method)
if ( token . Cookie ! = null )
w . WriteElementString ( "dnse" , "Cookie" , Constants . MSTlsnegoTokenContent , Convert . ToBase64String ( token . Cookie ) ) ;
w . WriteEndElement ( ) ;
}
}
}