| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- //------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------
- namespace System.ServiceModel.Security
- {
- using System.IdentityModel.Tokens;
- using System.ServiceModel;
- using System.IdentityModel.Selectors;
- using System.ServiceModel.Security.Tokens;
- using System.IO;
- using System.Globalization;
- using System.Security.Cryptography.X509Certificates;
- internal sealed class SecurityHeaderTokenResolver : SecurityTokenResolver, System.IdentityModel.IWrappedTokenKeyResolver
- {
- const int InitialTokenArraySize = 10;
- int tokenCount;
- SecurityTokenEntry[] tokens;
- SecurityToken expectedWrapper;
- SecurityTokenParameters expectedWrapperTokenParameters;
- ReceiveSecurityHeader securityHeader;
- public SecurityHeaderTokenResolver()
- : this(null)
- {
- }
- public SecurityHeaderTokenResolver(ReceiveSecurityHeader securityHeader)
- {
- this.tokens = new SecurityTokenEntry[InitialTokenArraySize];
- this.securityHeader = securityHeader;
- }
- public SecurityToken ExpectedWrapper
- {
- get { return this.expectedWrapper; }
- set { this.expectedWrapper = value; }
- }
- public SecurityTokenParameters ExpectedWrapperTokenParameters
- {
- get { return this.expectedWrapperTokenParameters; }
- set { this.expectedWrapperTokenParameters = value; }
- }
- public void Add(SecurityToken token)
- {
- Add(token, SecurityTokenReferenceStyle.Internal, null);
- }
- public void Add(SecurityToken token, SecurityTokenReferenceStyle allowedReferenceStyle, SecurityTokenParameters tokenParameters)
- {
- if (token == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("token");
- }
- if ((allowedReferenceStyle == SecurityTokenReferenceStyle.External) && (tokenParameters == null))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.ResolvingExternalTokensRequireSecurityTokenParameters));
- }
- EnsureCapacityToAddToken();
- this.tokens[this.tokenCount++] = new SecurityTokenEntry(token, tokenParameters, allowedReferenceStyle);
- }
- void EnsureCapacityToAddToken()
- {
- if (this.tokenCount == this.tokens.Length)
- {
- SecurityTokenEntry[] newTokens = new SecurityTokenEntry[this.tokens.Length * 2];
- Array.Copy(this.tokens, 0, newTokens, 0, this.tokenCount);
- this.tokens = newTokens;
- }
- }
- public bool CheckExternalWrapperMatch(SecurityKeyIdentifier keyIdentifier)
- {
- if (this.expectedWrapper == null || this.expectedWrapperTokenParameters == null)
- {
- return false;
- }
- for (int i = 0; i < keyIdentifier.Count; i++)
- {
- if (this.expectedWrapperTokenParameters.MatchesKeyIdentifierClause(this.expectedWrapper, keyIdentifier[i], SecurityTokenReferenceStyle.External))
- {
- return true;
- }
- }
- return false;
- }
- internal SecurityToken ResolveToken(SecurityKeyIdentifier keyIdentifier, bool matchOnlyExternalTokens, bool resolveIntrinsicKeyClause)
- {
- if (keyIdentifier == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("keyIdentifier");
- }
- for (int i = 0; i < keyIdentifier.Count; i++)
- {
- SecurityToken token = ResolveToken(keyIdentifier[i], matchOnlyExternalTokens, resolveIntrinsicKeyClause);
- if (token != null)
- {
- return token;
- }
- }
- return null;
- }
- SecurityKey ResolveSecurityKeyCore(SecurityKeyIdentifierClause keyIdentifierClause, bool createIntrinsicKeys)
- {
- if (keyIdentifierClause == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("keyIdentifierClause"));
- }
- SecurityKey securityKey;
- for (int i = 0; i < this.tokenCount; i++)
- {
- securityKey = this.tokens[i].Token.ResolveKeyIdentifierClause(keyIdentifierClause);
- if (securityKey != null)
- {
- return securityKey;
- }
- }
- if (createIntrinsicKeys)
- {
- if (SecurityUtils.TryCreateKeyFromIntrinsicKeyClause(keyIdentifierClause, this, out securityKey))
- {
- return securityKey;
- }
- }
- return null;
- }
- bool MatchDirectReference(SecurityToken token, SecurityKeyIdentifierClause keyClause)
- {
- LocalIdKeyIdentifierClause localClause = keyClause as LocalIdKeyIdentifierClause;
- if (localClause == null) return false;
- return token.MatchesKeyIdentifierClause(localClause);
- }
- internal SecurityToken ResolveToken(SecurityKeyIdentifierClause keyIdentifierClause, bool matchOnlyExternal, bool resolveIntrinsicKeyClause)
- {
- if (keyIdentifierClause == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("keyIdentifierClause");
- }
- SecurityToken resolvedToken = null;
- for (int i = 0; i < this.tokenCount; i++)
- {
- if (matchOnlyExternal && tokens[i].AllowedReferenceStyle != SecurityTokenReferenceStyle.External)
- {
- continue;
- }
- SecurityToken token = tokens[i].Token;
- if (tokens[i].TokenParameters != null && tokens[i].TokenParameters.MatchesKeyIdentifierClause(token, keyIdentifierClause, tokens[i].AllowedReferenceStyle))
- {
- resolvedToken = token;
- break;
- }
- else if (tokens[i].TokenParameters == null)
- {
- // match it according to the allowed reference style
- if (tokens[i].AllowedReferenceStyle == SecurityTokenReferenceStyle.Internal && MatchDirectReference(token, keyIdentifierClause))
- {
- resolvedToken = token;
- break;
- }
- }
- }
- if ((resolvedToken == null) && (keyIdentifierClause is EncryptedKeyIdentifierClause))
- {
- EncryptedKeyIdentifierClause keyClause = (EncryptedKeyIdentifierClause)keyIdentifierClause;
- SecurityKeyIdentifier wrappingTokenReference = keyClause.EncryptingKeyIdentifier;
- SecurityToken unwrappingToken;
- if (this.expectedWrapper != null
- && CheckExternalWrapperMatch(wrappingTokenReference))
- unwrappingToken = this.expectedWrapper;
- else
- unwrappingToken = ResolveToken(wrappingTokenReference, true, resolveIntrinsicKeyClause);
- if (unwrappingToken != null)
- {
- resolvedToken = SecurityUtils.CreateTokenFromEncryptedKeyClause(keyClause, unwrappingToken);
- }
- }
- if ((resolvedToken == null) && (keyIdentifierClause is X509RawDataKeyIdentifierClause) && (!matchOnlyExternal) && (resolveIntrinsicKeyClause))
- {
- resolvedToken = new X509SecurityToken(new X509Certificate2(((X509RawDataKeyIdentifierClause)keyIdentifierClause).GetX509RawData()));
- }
- byte[] derivationNonce = keyIdentifierClause.GetDerivationNonce();
- if ((resolvedToken != null) && (derivationNonce != null))
- {
- // A Implicit Derived Key is specified. Create a derived key off of the resolve token.
- if (SecurityUtils.GetSecurityKey<SymmetricSecurityKey>(resolvedToken) == null)
- {
- // The resolved token contains no Symmetric Security key and thus we cannot create
- // a derived key off of it.
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.UnableToDeriveKeyFromKeyInfoClause, keyIdentifierClause, resolvedToken)));
- }
- int derivationLength = (keyIdentifierClause.DerivationLength == 0) ? DerivedKeySecurityToken.DefaultDerivedKeyLength : keyIdentifierClause.DerivationLength;
- if (derivationLength > this.securityHeader.MaxDerivedKeyLength)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.DerivedKeyLengthSpecifiedInImplicitDerivedKeyClauseTooLong, keyIdentifierClause.ToString(), derivationLength, this.securityHeader.MaxDerivedKeyLength)));
- bool alreadyDerived = false;
- for (int i = 0; i < this.tokenCount; ++i)
- {
- DerivedKeySecurityToken derivedKeyToken = this.tokens[i].Token as DerivedKeySecurityToken;
- if (derivedKeyToken != null)
- {
- if ((derivedKeyToken.Length == derivationLength) &&
- (CryptoHelper.IsEqual(derivedKeyToken.Nonce, derivationNonce)) &&
- (derivedKeyToken.TokenToDerive.MatchesKeyIdentifierClause(keyIdentifierClause)))
- {
- // This is a implcit derived key for which we have already derived the
- // token.
- resolvedToken = this.tokens[i].Token;
- alreadyDerived = true;
- break;
- }
- }
- }
- if (!alreadyDerived)
- {
- string psha1Algorithm = SecurityUtils.GetKeyDerivationAlgorithm(this.securityHeader.StandardsManager.MessageSecurityVersion.SecureConversationVersion);
- resolvedToken = new DerivedKeySecurityToken(-1, 0, derivationLength, null, derivationNonce, resolvedToken, keyIdentifierClause, psha1Algorithm, SecurityUtils.GenerateId());
- ((DerivedKeySecurityToken)resolvedToken).InitializeDerivedKey(derivationLength);
- Add(resolvedToken, SecurityTokenReferenceStyle.Internal, null);
- this.securityHeader.EnsureDerivedKeyLimitNotReached();
- }
- }
- return resolvedToken;
- }
- public override string ToString()
- {
- using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture))
- {
- writer.WriteLine("SecurityTokenResolver");
- writer.WriteLine(" (");
- writer.WriteLine(" TokenCount = {0},", this.tokenCount);
- for (int i = 0; i < this.tokenCount; i++)
- {
- writer.WriteLine(" TokenEntry[{0}] = (AllowedReferenceStyle={1}, Token={2}, Parameters={3})",
- i, this.tokens[i].AllowedReferenceStyle, this.tokens[i].Token.GetType(), tokens[i].TokenParameters);
- }
- writer.WriteLine(" )");
- return writer.ToString();
- }
- }
- protected override bool TryResolveTokenCore(SecurityKeyIdentifier keyIdentifier, out SecurityToken token)
- {
- token = ResolveToken(keyIdentifier, false, true);
- return token != null;
- }
- internal bool TryResolveToken(SecurityKeyIdentifier keyIdentifier, bool matchOnlyExternalTokens, bool resolveIntrinsicKeyClause, out SecurityToken token)
- {
- token = ResolveToken(keyIdentifier, matchOnlyExternalTokens, resolveIntrinsicKeyClause);
- return token != null;
- }
- protected override bool TryResolveTokenCore(SecurityKeyIdentifierClause keyIdentifierClause, out SecurityToken token)
- {
- token = ResolveToken(keyIdentifierClause, false, true);
- return token != null;
- }
- internal bool TryResolveToken(SecurityKeyIdentifierClause keyIdentifierClause, bool matchOnlyExternalTokens, bool resolveIntrinsicKeyClause, out SecurityToken token)
- {
- token = ResolveToken(keyIdentifierClause, matchOnlyExternalTokens, resolveIntrinsicKeyClause);
- return token != null;
- }
- internal bool TryResolveSecurityKey(SecurityKeyIdentifierClause keyIdentifierClause, bool createIntrinsicKeys, out SecurityKey key)
- {
- if (keyIdentifierClause == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("keyIdentifierClause");
- }
- key = this.ResolveSecurityKeyCore(keyIdentifierClause, createIntrinsicKeys);
- return key != null;
- }
- protected override bool TryResolveSecurityKeyCore(SecurityKeyIdentifierClause keyIdentifierClause, out SecurityKey key)
- {
- key = ResolveSecurityKeyCore(keyIdentifierClause, true);
- return key != null;
- }
- struct SecurityTokenEntry
- {
- SecurityTokenParameters tokenParameters;
- SecurityToken token;
- SecurityTokenReferenceStyle allowedReferenceStyle;
- public SecurityTokenEntry(SecurityToken token, SecurityTokenParameters tokenParameters, SecurityTokenReferenceStyle allowedReferenceStyle)
- {
- this.token = token;
- this.tokenParameters = tokenParameters;
- this.allowedReferenceStyle = allowedReferenceStyle;
- }
- public SecurityToken Token
- {
- get { return this.token; }
- }
- public SecurityTokenParameters TokenParameters
- {
- get { return this.tokenParameters; }
- }
- public SecurityTokenReferenceStyle AllowedReferenceStyle
- {
- get { return this.allowedReferenceStyle; }
- }
- }
- }
- }
|