| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406 |
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace System.ServiceModel.Security
- {
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.IdentityModel.Policy;
- using System.IdentityModel.Selectors;
- using System.IdentityModel.Tokens;
- using System.IO;
- using System.Runtime;
- using System.Runtime.Serialization;
- using System.Security.Authentication.ExtendedProtection;
- using System.Security.Cryptography;
- using System.ServiceModel;
- using System.ServiceModel.Channels;
- using System.ServiceModel.Diagnostics;
- using System.ServiceModel.Dispatcher;
- using System.ServiceModel.Security.Tokens;
- using System.Xml;
- using CanonicalizationDriver = System.IdentityModel.CanonicalizationDriver;
- using Psha1DerivedKeyGenerator = System.IdentityModel.Psha1DerivedKeyGenerator;
- abstract class SspiNegotiationTokenAuthenticator : NegotiationTokenAuthenticator<SspiNegotiationTokenAuthenticatorState>
- {
- ExtendedProtectionPolicy extendedProtectionPolicy;
- string defaultServiceBinding;
- Object thisLock = new Object();
- protected SspiNegotiationTokenAuthenticator()
- : base()
- {
- }
- public ExtendedProtectionPolicy ExtendedProtectionPolicy
- {
- get { return this.extendedProtectionPolicy; }
- set { this.extendedProtectionPolicy = value; }
- }
- protected Object ThisLock
- {
- get { return this.thisLock; }
- }
- public string DefaultServiceBinding
- {
- get
- {
- if (this.defaultServiceBinding == null)
- {
- lock (ThisLock)
- {
- if (this.defaultServiceBinding == null)
- {
- this.defaultServiceBinding = SecurityUtils.GetSpnFromIdentity(
- SecurityUtils.CreateWindowsIdentity(),
- new EndpointAddress(ListenUri));
- }
- }
- }
- return this.defaultServiceBinding;
- }
- set { this.defaultServiceBinding = value; }
- }
- // abstract methods
- public abstract XmlDictionaryString NegotiationValueType { get; }
- protected abstract ReadOnlyCollection<IAuthorizationPolicy> ValidateSspiNegotiation(ISspiNegotiation sspiNegotiation);
- protected abstract SspiNegotiationTokenAuthenticatorState CreateSspiState(byte[] incomingBlob, string incomingValueTypeUri);
- // helpers
- protected virtual void IssueServiceToken(SspiNegotiationTokenAuthenticatorState sspiState, ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies, out SecurityContextSecurityToken serviceToken, out WrappedKeySecurityToken proofToken,
- out int issuedKeySize)
- {
- UniqueId contextId = SecurityUtils.GenerateUniqueId();
- string id = SecurityUtils.GenerateId();
- if (sspiState.RequestedKeySize == 0)
- {
- issuedKeySize = this.SecurityAlgorithmSuite.DefaultSymmetricKeyLength;
- }
- else
- {
- issuedKeySize = sspiState.RequestedKeySize;
- }
- byte[] key = new byte[issuedKeySize / 8];
- CryptoHelper.FillRandomBytes(key);
- DateTime effectiveTime = DateTime.UtcNow;
- DateTime expirationTime = TimeoutHelper.Add(effectiveTime, this.ServiceTokenLifetime);
- serviceToken = IssueSecurityContextToken(contextId, id, key, effectiveTime, expirationTime, authorizationPolicies, this.EncryptStateInServiceToken);
- proofToken = new WrappedKeySecurityToken(string.Empty, key, sspiState.SspiNegotiation);
- }
- protected virtual void ValidateIncomingBinaryNegotiation(BinaryNegotiation incomingNego)
- {
- if (incomingNego == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.NoBinaryNegoToReceive)));
- }
- incomingNego.Validate(this.NegotiationValueType);
- }
- protected virtual BinaryNegotiation GetOutgoingBinaryNegotiation(ISspiNegotiation sspiNegotiation, byte[] outgoingBlob)
- {
- return new BinaryNegotiation(this.NegotiationValueType, outgoingBlob);
- }
- static void AddToDigest(HashAlgorithm negotiationDigest, Stream stream)
- {
- stream.Flush();
- stream.Seek(0, SeekOrigin.Begin);
- CanonicalizationDriver canonicalizer = new CanonicalizationDriver();
- canonicalizer.SetInput(stream);
- byte[] canonicalizedData = canonicalizer.GetBytes();
- lock (negotiationDigest)
- {
- negotiationDigest.TransformBlock(canonicalizedData, 0, canonicalizedData.Length, canonicalizedData, 0);
- }
- }
- static void AddToDigest(SspiNegotiationTokenAuthenticatorState sspiState, RequestSecurityToken rst)
- {
- MemoryStream stream = new MemoryStream();
- XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(stream);
- rst.RequestSecurityTokenXml.WriteTo(writer);
- writer.Flush();
- AddToDigest(sspiState.NegotiationDigest, stream);
- }
- static void AddToDigest(SspiNegotiationTokenAuthenticatorState sspiState, RequestSecurityTokenResponse rstr, bool wasReceived)
- {
- MemoryStream stream = new MemoryStream();
- XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(stream);
- if (wasReceived)
- {
- rstr.RequestSecurityTokenResponseXml.WriteTo(writer);
- }
- else
- {
- rstr.WriteTo(writer);
- }
- writer.Flush();
- AddToDigest(sspiState.NegotiationDigest, stream);
- }
- static byte[] ComputeAuthenticator(SspiNegotiationTokenAuthenticatorState sspiState, byte[] key)
- {
- byte[] negotiationHash;
- lock (sspiState.NegotiationDigest)
- {
- sspiState.NegotiationDigest.TransformFinalBlock(CryptoHelper.EmptyBuffer, 0, 0);
- negotiationHash = sspiState.NegotiationDigest.Hash;
- }
- Psha1DerivedKeyGenerator generator = new Psha1DerivedKeyGenerator(key);
- return generator.GenerateDerivedKey(SecurityUtils.CombinedHashLabel, negotiationHash, SecurityNegotiationConstants.NegotiationAuthenticatorSize, 0);
- }
- // overrides
- protected override bool IsMultiLegNegotiation
- {
- get
- {
- return true;
- }
- }
- protected override Binding GetNegotiationBinding(Binding binding)
- {
- return binding;
- }
- protected override MessageFilter GetListenerFilter()
- {
- return new SspiNegotiationFilter(this);
- }
- protected override BodyWriter ProcessRequestSecurityToken(Message request, RequestSecurityToken requestSecurityToken, out SspiNegotiationTokenAuthenticatorState negotiationState)
- {
- if (request == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("request");
- }
- if (requestSecurityToken == null)
- {
- throw TraceUtility.ThrowHelperArgumentNull("requestSecurityToken", request);
- }
- if (requestSecurityToken.RequestType != null && requestSecurityToken.RequestType != this.StandardsManager.TrustDriver.RequestTypeIssue)
- {
- throw TraceUtility.ThrowHelperWarning(new SecurityNegotiationException(SR.GetString(SR.InvalidRstRequestType, requestSecurityToken.RequestType)), request);
- }
- BinaryNegotiation incomingNego = requestSecurityToken.GetBinaryNegotiation();
- ValidateIncomingBinaryNegotiation(incomingNego);
- negotiationState = CreateSspiState(incomingNego.GetNegotiationData(), incomingNego.ValueTypeUri);
- AddToDigest(negotiationState, requestSecurityToken);
- negotiationState.Context = requestSecurityToken.Context;
- if (requestSecurityToken.KeySize != 0)
- {
- WSTrust.Driver.ValidateRequestedKeySize(requestSecurityToken.KeySize, this.SecurityAlgorithmSuite);
- }
- negotiationState.RequestedKeySize = requestSecurityToken.KeySize;
- string appliesToName;
- string appliesToNamespace;
- requestSecurityToken.GetAppliesToQName(out appliesToName, out appliesToNamespace);
- if (appliesToName == AddressingStrings.EndpointReference && appliesToNamespace == request.Version.Addressing.Namespace)
- {
- DataContractSerializer serializer;
- if (request.Version.Addressing == AddressingVersion.WSAddressing10)
- {
- serializer = DataContractSerializerDefaults.CreateSerializer(typeof(EndpointAddress10), DataContractSerializerDefaults.MaxItemsInObjectGraph);
- negotiationState.AppliesTo = requestSecurityToken.GetAppliesTo<EndpointAddress10>(serializer).ToEndpointAddress();
- }
- else if (request.Version.Addressing == AddressingVersion.WSAddressingAugust2004)
- {
- serializer = DataContractSerializerDefaults.CreateSerializer(typeof(EndpointAddressAugust2004), DataContractSerializerDefaults.MaxItemsInObjectGraph);
- negotiationState.AppliesTo = requestSecurityToken.GetAppliesTo<EndpointAddressAugust2004>(serializer).ToEndpointAddress();
- }
- else
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new ProtocolException(SR.GetString(SR.AddressingVersionNotSupported, request.Version.Addressing)));
- }
- negotiationState.AppliesToSerializer = serializer;
- }
- return ProcessNegotiation(negotiationState, request, incomingNego);
- }
- protected override BodyWriter ProcessRequestSecurityTokenResponse(SspiNegotiationTokenAuthenticatorState negotiationState, Message request, RequestSecurityTokenResponse requestSecurityTokenResponse)
- {
- if (request == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("request");
- }
- if (requestSecurityTokenResponse == null)
- {
- throw TraceUtility.ThrowHelperArgumentNull("requestSecurityTokenResponse", request);
- }
- if (requestSecurityTokenResponse.Context != negotiationState.Context)
- {
- throw TraceUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.BadSecurityNegotiationContext)), request);
- }
- AddToDigest(negotiationState, requestSecurityTokenResponse, true);
- BinaryNegotiation incomingNego = requestSecurityTokenResponse.GetBinaryNegotiation();
- ValidateIncomingBinaryNegotiation(incomingNego);
- return ProcessNegotiation(negotiationState, request, incomingNego);
- }
- BodyWriter ProcessNegotiation(SspiNegotiationTokenAuthenticatorState negotiationState, Message incomingMessage, BinaryNegotiation incomingNego)
- {
- ISspiNegotiation sspiNegotiation = negotiationState.SspiNegotiation;
-
- byte[] outgoingBlob = sspiNegotiation.GetOutgoingBlob(incomingNego.GetNegotiationData(),
- SecurityUtils.GetChannelBindingFromMessage(incomingMessage),
- this.extendedProtectionPolicy);
- if (sspiNegotiation.IsValidContext == false)
- {
- throw TraceUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.InvalidSspiNegotiation)), incomingMessage);
- }
- // if there is no blob to send back the nego must be complete from the server side
- if (outgoingBlob == null && sspiNegotiation.IsCompleted == false)
- {
- throw TraceUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.NoBinaryNegoToSend)), incomingMessage);
- }
- BinaryNegotiation outgoingBinaryNegotiation;
- if (outgoingBlob != null)
- {
- outgoingBinaryNegotiation = GetOutgoingBinaryNegotiation(sspiNegotiation, outgoingBlob);
- }
- else
- {
- outgoingBinaryNegotiation = null;
- }
- BodyWriter replyBody;
- if (sspiNegotiation.IsCompleted)
- {
- ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies = ValidateSspiNegotiation(sspiNegotiation);
- SecurityContextSecurityToken serviceToken;
- WrappedKeySecurityToken proofToken;
- int issuedKeySize;
- IssueServiceToken(negotiationState, authorizationPolicies, out serviceToken, out proofToken, out issuedKeySize);
- negotiationState.SetServiceToken(serviceToken);
-
- SecurityKeyIdentifierClause externalTokenReference = this.IssuedSecurityTokenParameters.CreateKeyIdentifierClause(serviceToken, SecurityTokenReferenceStyle.External);
- SecurityKeyIdentifierClause internalTokenReference = this.IssuedSecurityTokenParameters.CreateKeyIdentifierClause(serviceToken, SecurityTokenReferenceStyle.Internal);
- RequestSecurityTokenResponse dummyRstr = new RequestSecurityTokenResponse(this.StandardsManager);
- dummyRstr.Context = negotiationState.Context;
- dummyRstr.KeySize = issuedKeySize;
- dummyRstr.TokenType = this.SecurityContextTokenUri;
- if (outgoingBinaryNegotiation != null)
- {
- dummyRstr.SetBinaryNegotiation(outgoingBinaryNegotiation);
- }
- dummyRstr.RequestedUnattachedReference = externalTokenReference;
- dummyRstr.RequestedAttachedReference = internalTokenReference;
- dummyRstr.SetLifetime(serviceToken.ValidFrom, serviceToken.ValidTo);
- if (negotiationState.AppliesTo != null)
- {
- if (incomingMessage.Version.Addressing == AddressingVersion.WSAddressing10)
- {
- dummyRstr.SetAppliesTo<EndpointAddress10>(EndpointAddress10.FromEndpointAddress(
- negotiationState.AppliesTo),
- negotiationState.AppliesToSerializer);
- }
- else if (incomingMessage.Version.Addressing == AddressingVersion.WSAddressingAugust2004)
- {
- dummyRstr.SetAppliesTo<EndpointAddressAugust2004>(EndpointAddressAugust2004.FromEndpointAddress(
- negotiationState.AppliesTo),
- negotiationState.AppliesToSerializer);
- }
- else
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new ProtocolException(SR.GetString(SR.AddressingVersionNotSupported, incomingMessage.Version.Addressing)));
- }
- }
- dummyRstr.MakeReadOnly();
- AddToDigest(negotiationState, dummyRstr, false);
- RequestSecurityTokenResponse negotiationRstr = new RequestSecurityTokenResponse(this.StandardsManager);
- negotiationRstr.RequestedSecurityToken = serviceToken;
- negotiationRstr.RequestedProofToken = proofToken;
- negotiationRstr.Context = negotiationState.Context;
- negotiationRstr.KeySize = issuedKeySize;
- negotiationRstr.TokenType = this.SecurityContextTokenUri;
- if (outgoingBinaryNegotiation != null)
- {
- negotiationRstr.SetBinaryNegotiation(outgoingBinaryNegotiation);
- }
- negotiationRstr.RequestedAttachedReference = internalTokenReference;
- negotiationRstr.RequestedUnattachedReference = externalTokenReference;
- if (negotiationState.AppliesTo != null)
- {
- if (incomingMessage.Version.Addressing == AddressingVersion.WSAddressing10)
- {
- negotiationRstr.SetAppliesTo<EndpointAddress10>(
- EndpointAddress10.FromEndpointAddress(negotiationState.AppliesTo),
- negotiationState.AppliesToSerializer);
- }
- else if (incomingMessage.Version.Addressing == AddressingVersion.WSAddressingAugust2004)
- {
- negotiationRstr.SetAppliesTo<EndpointAddressAugust2004>(
- EndpointAddressAugust2004.FromEndpointAddress(negotiationState.AppliesTo),
- negotiationState.AppliesToSerializer);
- }
- else
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new ProtocolException(SR.GetString(SR.AddressingVersionNotSupported, incomingMessage.Version.Addressing)));
- }
- }
- negotiationRstr.MakeReadOnly();
- byte[] authenticator = ComputeAuthenticator(negotiationState, serviceToken.GetKeyBytes());
- RequestSecurityTokenResponse authenticatorRstr = new RequestSecurityTokenResponse(this.StandardsManager);
- authenticatorRstr.Context = negotiationState.Context;
- authenticatorRstr.SetAuthenticator(authenticator);
- authenticatorRstr.MakeReadOnly();
- List<RequestSecurityTokenResponse> rstrList = new List<RequestSecurityTokenResponse>(2);
- rstrList.Add(negotiationRstr);
- rstrList.Add(authenticatorRstr);
- replyBody = new RequestSecurityTokenResponseCollection(rstrList, this.StandardsManager);
-
- }
- else
- {
- RequestSecurityTokenResponse rstr = new RequestSecurityTokenResponse(this.StandardsManager);
- rstr.Context = negotiationState.Context;
- rstr.SetBinaryNegotiation(outgoingBinaryNegotiation);
- rstr.MakeReadOnly();
- AddToDigest(negotiationState, rstr, false);
- replyBody = rstr;
- }
- return replyBody;
- }
- class SspiNegotiationFilter : HeaderFilter
- {
- SspiNegotiationTokenAuthenticator authenticator;
-
- public SspiNegotiationFilter(SspiNegotiationTokenAuthenticator authenticator)
- {
- this.authenticator = authenticator;
- }
- public override bool Match(Message message)
- {
- if (message.Headers.Action == authenticator.RequestSecurityTokenAction.Value
- || message.Headers.Action == authenticator.RequestSecurityTokenResponseAction.Value)
- {
- return !SecurityVersion.Default.DoesMessageContainSecurityHeader(message);
- }
- else
- {
- return false;
- }
- }
- }
- }
- }
|