KerberosReceiverSecurityToken.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WCF / IdentityModel / System / IdentityModel / Tokens / KerberosReceiverSecurityToken.cs / 1305376 / KerberosReceiverSecurityToken.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------

namespace System.IdentityModel.Tokens 
{
    using System.Collections.Generic; 
    using System.Collections.ObjectModel; 
    using System.ComponentModel;
    using System.Security.Authentication.ExtendedProtection; 
    using System.Security.Principal;

    public class KerberosReceiverSecurityToken : WindowsSecurityToken
    { 
        string id;
        byte[] request; 
        SymmetricSecurityKey symmetricSecurityKey = null; 
        ReadOnlyCollection securityKeys = null;
        bool isAuthenticated = false; 
        string valueTypeUri = null;
        ChannelBinding channelBinding;
        ExtendedProtectionPolicy extendedProtectionPolicy;
 
        public KerberosReceiverSecurityToken(byte[] request)
            : this(request, SecurityUniqueId.Create().Value) 
        { } 

        public KerberosReceiverSecurityToken(byte[] request, string id) 
            : this(request, id, true, null)
        {
        }
 
        public KerberosReceiverSecurityToken(byte[] request, string id, string valueTypeUri)
            : this(request, id, true, valueTypeUri) 
        { 
        }
 
        internal KerberosReceiverSecurityToken( byte[] request, string id, bool doAuthenticate, string valueTypeUri )
            : this(request, id, doAuthenticate, valueTypeUri, null, null)
        { }
 
        internal KerberosReceiverSecurityToken(
                                byte[] request, 
                                string id, 
                                bool doAuthenticate,
                                string valueTypeUri, 
                                ChannelBinding channelBinding,
                                ExtendedProtectionPolicy extendedProtectionPolicy )
        {
            if (request == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("request"));
            if (id == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("id")); 

            this.id = id; 
            this.request = request;
            this.valueTypeUri = valueTypeUri;
            this.channelBinding = channelBinding;
            this.extendedProtectionPolicy = extendedProtectionPolicy; 

            if (doAuthenticate) 
            { 
                Initialize(null, channelBinding, extendedProtectionPolicy);
            } 
        }

        public override ReadOnlyCollection SecurityKeys
        { 
            get
            { 
                if (this.securityKeys == null) 
                {
                    List temp = new List(1); 
                    temp.Add(this.SecurityKey);
                    this.securityKeys = temp.AsReadOnly();
                }
                return this.securityKeys; 
            }
        } 
 
        public SymmetricSecurityKey SecurityKey
        { 
            get
            {
                if (!this.isAuthenticated)
                { 
                    Initialize(null, this.channelBinding, this.extendedProtectionPolicy);
                } 
                return this.symmetricSecurityKey; 
            }
        } 

        public override DateTime ValidFrom
        {
            get 
            {
                if (!this.isAuthenticated) 
                { 
                    Initialize(null, this.channelBinding, this.extendedProtectionPolicy);
                } 
                return base.ValidFrom;
            }
        }
 
        public override DateTime ValidTo
        { 
            get 
            {
                if (!this.isAuthenticated) 
                {
                    Initialize(null, this.channelBinding, this.extendedProtectionPolicy);
                }
                return base.ValidTo; 
            }
        } 
 
        public override WindowsIdentity WindowsIdentity
        { 
            get
            {
                ThrowIfDisposed();
                if (!this.isAuthenticated) 
                {
                    Initialize(null, this.channelBinding, this.extendedProtectionPolicy); 
                } 
                return base.WindowsIdentity;
            } 
        }

        /// 
        /// The Uri that defines the ValueType of the kerberos blob. 
        /// 
        public string ValueTypeUri 
        { 
            get
            { 
                return valueTypeUri;
            }
        }
 
        public byte[] GetRequest()
        { 
            return SecurityUtils.CloneBuffer(this.request); 
        }
 
        // This internal API is not thread-safe.  It is acceptable since ..
        // 1) From public OM, Initialize happens at ctor time.
        // 2) From internal OM (Sfx), Initialize happens right after ctor (single thread env).
        //    i.e. ReadToken and then AuthenticateToken. 
        internal void Initialize( SafeFreeCredentials credentialsHandle, ChannelBinding channelBinding, ExtendedProtectionPolicy extendedProtectionPolicy )
        { 
            if (this.isAuthenticated) 
            {
                return; 
            }
            bool ownCredentialsHandle = false;
            SafeDeleteContext securityContext = null;
            SafeCloseHandle tokenHandle = null; 

#if RECOMPUTEGSS 
            int tokenSize = DEREncoding.TokenSize(this.request.Length); 
            byte[] rawRequest = new byte[tokenSize];
            int offset = 0; 
            int len = this.request.Length;
            DEREncoding.MakeTokenHeader(this.request.Length, rawRequest, ref offset, ref len);
            System.Buffer.BlockCopy(this.request, 0, rawRequest, offset, this.request.Length);
#else 
            byte[] rawRequest = this.request;
#endif 
 
            try
            { 
                if (credentialsHandle == null)
                {
                    credentialsHandle = SspiWrapper.AcquireDefaultCredential("Kerberos", CredentialUse.Inbound);
                    ownCredentialsHandle = true; 
                }
 
                SspiContextFlags fContextReq = SspiContextFlags.AllocateMemory | SspiContextFlags.Confidentiality 
                                             | SspiContextFlags.Confidentiality
                                             | SspiContextFlags.ReplayDetect 
                                             | SspiContextFlags.SequenceDetect;

                ExtendedProtectionPolicyHelper policyHelper = new ExtendedProtectionPolicyHelper(channelBinding, extendedProtectionPolicy);
 
                if (policyHelper.PolicyEnforcement == PolicyEnforcement.Always && policyHelper.ChannelBinding == null && policyHelper.ProtectionScenario != ProtectionScenario.TrustedProxy)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.SecurityChannelBindingMissing))); 
                }
 
                if (policyHelper.PolicyEnforcement == PolicyEnforcement.WhenSupported)
                {
                    fContextReq |= SspiContextFlags.ChannelBindingAllowMissingBindings;
                } 

                if (policyHelper.ProtectionScenario == ProtectionScenario.TrustedProxy) 
                { 
                    fContextReq |= SspiContextFlags.ChannelBindingProxyBindings;
                } 

                SspiContextFlags contextFlags = SspiContextFlags.Zero;
                SecurityBuffer outSecurityBuffer = new SecurityBuffer(0, BufferType.Token);
 
                List list = new List(2);
                list.Add(new SecurityBuffer(rawRequest, BufferType.Token)); 
 
                if (policyHelper.ShouldAddChannelBindingToASC())
                { 
                    list.Add(new SecurityBuffer(policyHelper.ChannelBinding));
                }

                SecurityBuffer[] inSecurityBuffer = null; 
                if (list.Count > 0)
                { 
                    inSecurityBuffer = list.ToArray(); 
                }
 


                int statusCode = SspiWrapper.AcceptSecurityContext(credentialsHandle,
                    ref securityContext, 
                    fContextReq,
                    Endianness.Native, 
                    inSecurityBuffer, 
                    outSecurityBuffer,
                    ref contextFlags); 

                if (statusCode != (int)SecurityStatus.OK)
                {
                    if (statusCode == (int)SecurityStatus.ContinueNeeded) 
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                            new SecurityTokenException(SR.GetString(SR.KerberosMultilegsNotSupported), new Win32Exception(statusCode))); 
                    }
                    else if (statusCode == (int)SecurityStatus.OutOfMemory) 
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                            new SecurityTokenException(SR.GetString(SR.KerberosApReqInvalidOrOutOfMemory), new Win32Exception(statusCode)));
                    } 
                    else
                    { 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                            new SecurityTokenException(SR.GetString(SR.FailAcceptSecurityContext), new Win32Exception(statusCode)));
                    } 
                }

                // Expiration
                LifeSpan lifeSpan = (LifeSpan)SspiWrapper.QueryContextAttributes(securityContext, ContextAttribute.Lifespan); 
                DateTime effectiveTime = lifeSpan.EffectiveTimeUtc;
                DateTime expirationTime = lifeSpan.ExpiryTimeUtc; 
 
                // SessionKey
                SecuritySessionKeyClass sessionKey = (SecuritySessionKeyClass)SspiWrapper.QueryContextAttributes(securityContext, ContextAttribute.SessionKey); 
                this.symmetricSecurityKey = new InMemorySymmetricSecurityKey(sessionKey.SessionKey);

                // WindowsSecurityToken
                statusCode = SspiWrapper.QuerySecurityContextToken(securityContext, out tokenHandle); 
                if (statusCode != (int)SecurityStatus.OK)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(statusCode)); 
                }
 
                WindowsIdentity windowsIdentity = new WindowsIdentity( tokenHandle.DangerousGetHandle(), SecurityUtils.AuthTypeKerberos);
                Initialize(this.id, SecurityUtils.AuthTypeKerberos, effectiveTime, expirationTime, windowsIdentity, false);

                // Authenticated 
                this.isAuthenticated = true;
            } 
            finally 
            {
                if (tokenHandle != null) 
                    tokenHandle.Close();

                if (securityContext != null)
                    securityContext.Close(); 

                if (ownCredentialsHandle && credentialsHandle != null) 
                    credentialsHandle.Close(); 
            }
        } 

        public override bool CanCreateKeyIdentifierClause()
        {
            if (typeof(T) == typeof(KerberosTicketHashKeyIdentifierClause)) 
                return true;
 
            return base.CanCreateKeyIdentifierClause(); 
        }
 
        public override T CreateKeyIdentifierClause()
        {
            if (typeof(T) == typeof(KerberosTicketHashKeyIdentifierClause))
                return new KerberosTicketHashKeyIdentifierClause(CryptoHelper.ComputeHash(this.request), false, null, 0) as T; 

            return base.CreateKeyIdentifierClause(); 
        } 

        public override bool MatchesKeyIdentifierClause(SecurityKeyIdentifierClause keyIdentifierClause) 
        {
            KerberosTicketHashKeyIdentifierClause kerbKeyIdentifierClause = keyIdentifierClause as KerberosTicketHashKeyIdentifierClause;
            if (kerbKeyIdentifierClause != null)
                return kerbKeyIdentifierClause.Matches(CryptoHelper.ComputeHash(this.request)); 

            return base.MatchesKeyIdentifierClause(keyIdentifierClause); 
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------

namespace System.IdentityModel.Tokens 
{
    using System.Collections.Generic; 
    using System.Collections.ObjectModel; 
    using System.ComponentModel;
    using System.Security.Authentication.ExtendedProtection; 
    using System.Security.Principal;

    public class KerberosReceiverSecurityToken : WindowsSecurityToken
    { 
        string id;
        byte[] request; 
        SymmetricSecurityKey symmetricSecurityKey = null; 
        ReadOnlyCollection securityKeys = null;
        bool isAuthenticated = false; 
        string valueTypeUri = null;
        ChannelBinding channelBinding;
        ExtendedProtectionPolicy extendedProtectionPolicy;
 
        public KerberosReceiverSecurityToken(byte[] request)
            : this(request, SecurityUniqueId.Create().Value) 
        { } 

        public KerberosReceiverSecurityToken(byte[] request, string id) 
            : this(request, id, true, null)
        {
        }
 
        public KerberosReceiverSecurityToken(byte[] request, string id, string valueTypeUri)
            : this(request, id, true, valueTypeUri) 
        { 
        }
 
        internal KerberosReceiverSecurityToken( byte[] request, string id, bool doAuthenticate, string valueTypeUri )
            : this(request, id, doAuthenticate, valueTypeUri, null, null)
        { }
 
        internal KerberosReceiverSecurityToken(
                                byte[] request, 
                                string id, 
                                bool doAuthenticate,
                                string valueTypeUri, 
                                ChannelBinding channelBinding,
                                ExtendedProtectionPolicy extendedProtectionPolicy )
        {
            if (request == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("request"));
            if (id == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("id")); 

            this.id = id; 
            this.request = request;
            this.valueTypeUri = valueTypeUri;
            this.channelBinding = channelBinding;
            this.extendedProtectionPolicy = extendedProtectionPolicy; 

            if (doAuthenticate) 
            { 
                Initialize(null, channelBinding, extendedProtectionPolicy);
            } 
        }

        public override ReadOnlyCollection SecurityKeys
        { 
            get
            { 
                if (this.securityKeys == null) 
                {
                    List temp = new List(1); 
                    temp.Add(this.SecurityKey);
                    this.securityKeys = temp.AsReadOnly();
                }
                return this.securityKeys; 
            }
        } 
 
        public SymmetricSecurityKey SecurityKey
        { 
            get
            {
                if (!this.isAuthenticated)
                { 
                    Initialize(null, this.channelBinding, this.extendedProtectionPolicy);
                } 
                return this.symmetricSecurityKey; 
            }
        } 

        public override DateTime ValidFrom
        {
            get 
            {
                if (!this.isAuthenticated) 
                { 
                    Initialize(null, this.channelBinding, this.extendedProtectionPolicy);
                } 
                return base.ValidFrom;
            }
        }
 
        public override DateTime ValidTo
        { 
            get 
            {
                if (!this.isAuthenticated) 
                {
                    Initialize(null, this.channelBinding, this.extendedProtectionPolicy);
                }
                return base.ValidTo; 
            }
        } 
 
        public override WindowsIdentity WindowsIdentity
        { 
            get
            {
                ThrowIfDisposed();
                if (!this.isAuthenticated) 
                {
                    Initialize(null, this.channelBinding, this.extendedProtectionPolicy); 
                } 
                return base.WindowsIdentity;
            } 
        }

        /// 
        /// The Uri that defines the ValueType of the kerberos blob. 
        /// 
        public string ValueTypeUri 
        { 
            get
            { 
                return valueTypeUri;
            }
        }
 
        public byte[] GetRequest()
        { 
            return SecurityUtils.CloneBuffer(this.request); 
        }
 
        // This internal API is not thread-safe.  It is acceptable since ..
        // 1) From public OM, Initialize happens at ctor time.
        // 2) From internal OM (Sfx), Initialize happens right after ctor (single thread env).
        //    i.e. ReadToken and then AuthenticateToken. 
        internal void Initialize( SafeFreeCredentials credentialsHandle, ChannelBinding channelBinding, ExtendedProtectionPolicy extendedProtectionPolicy )
        { 
            if (this.isAuthenticated) 
            {
                return; 
            }
            bool ownCredentialsHandle = false;
            SafeDeleteContext securityContext = null;
            SafeCloseHandle tokenHandle = null; 

#if RECOMPUTEGSS 
            int tokenSize = DEREncoding.TokenSize(this.request.Length); 
            byte[] rawRequest = new byte[tokenSize];
            int offset = 0; 
            int len = this.request.Length;
            DEREncoding.MakeTokenHeader(this.request.Length, rawRequest, ref offset, ref len);
            System.Buffer.BlockCopy(this.request, 0, rawRequest, offset, this.request.Length);
#else 
            byte[] rawRequest = this.request;
#endif 
 
            try
            { 
                if (credentialsHandle == null)
                {
                    credentialsHandle = SspiWrapper.AcquireDefaultCredential("Kerberos", CredentialUse.Inbound);
                    ownCredentialsHandle = true; 
                }
 
                SspiContextFlags fContextReq = SspiContextFlags.AllocateMemory | SspiContextFlags.Confidentiality 
                                             | SspiContextFlags.Confidentiality
                                             | SspiContextFlags.ReplayDetect 
                                             | SspiContextFlags.SequenceDetect;

                ExtendedProtectionPolicyHelper policyHelper = new ExtendedProtectionPolicyHelper(channelBinding, extendedProtectionPolicy);
 
                if (policyHelper.PolicyEnforcement == PolicyEnforcement.Always && policyHelper.ChannelBinding == null && policyHelper.ProtectionScenario != ProtectionScenario.TrustedProxy)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.SecurityChannelBindingMissing))); 
                }
 
                if (policyHelper.PolicyEnforcement == PolicyEnforcement.WhenSupported)
                {
                    fContextReq |= SspiContextFlags.ChannelBindingAllowMissingBindings;
                } 

                if (policyHelper.ProtectionScenario == ProtectionScenario.TrustedProxy) 
                { 
                    fContextReq |= SspiContextFlags.ChannelBindingProxyBindings;
                } 

                SspiContextFlags contextFlags = SspiContextFlags.Zero;
                SecurityBuffer outSecurityBuffer = new SecurityBuffer(0, BufferType.Token);
 
                List list = new List(2);
                list.Add(new SecurityBuffer(rawRequest, BufferType.Token)); 
 
                if (policyHelper.ShouldAddChannelBindingToASC())
                { 
                    list.Add(new SecurityBuffer(policyHelper.ChannelBinding));
                }

                SecurityBuffer[] inSecurityBuffer = null; 
                if (list.Count > 0)
                { 
                    inSecurityBuffer = list.ToArray(); 
                }
 


                int statusCode = SspiWrapper.AcceptSecurityContext(credentialsHandle,
                    ref securityContext, 
                    fContextReq,
                    Endianness.Native, 
                    inSecurityBuffer, 
                    outSecurityBuffer,
                    ref contextFlags); 

                if (statusCode != (int)SecurityStatus.OK)
                {
                    if (statusCode == (int)SecurityStatus.ContinueNeeded) 
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                            new SecurityTokenException(SR.GetString(SR.KerberosMultilegsNotSupported), new Win32Exception(statusCode))); 
                    }
                    else if (statusCode == (int)SecurityStatus.OutOfMemory) 
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                            new SecurityTokenException(SR.GetString(SR.KerberosApReqInvalidOrOutOfMemory), new Win32Exception(statusCode)));
                    } 
                    else
                    { 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                            new SecurityTokenException(SR.GetString(SR.FailAcceptSecurityContext), new Win32Exception(statusCode)));
                    } 
                }

                // Expiration
                LifeSpan lifeSpan = (LifeSpan)SspiWrapper.QueryContextAttributes(securityContext, ContextAttribute.Lifespan); 
                DateTime effectiveTime = lifeSpan.EffectiveTimeUtc;
                DateTime expirationTime = lifeSpan.ExpiryTimeUtc; 
 
                // SessionKey
                SecuritySessionKeyClass sessionKey = (SecuritySessionKeyClass)SspiWrapper.QueryContextAttributes(securityContext, ContextAttribute.SessionKey); 
                this.symmetricSecurityKey = new InMemorySymmetricSecurityKey(sessionKey.SessionKey);

                // WindowsSecurityToken
                statusCode = SspiWrapper.QuerySecurityContextToken(securityContext, out tokenHandle); 
                if (statusCode != (int)SecurityStatus.OK)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(statusCode)); 
                }
 
                WindowsIdentity windowsIdentity = new WindowsIdentity( tokenHandle.DangerousGetHandle(), SecurityUtils.AuthTypeKerberos);
                Initialize(this.id, SecurityUtils.AuthTypeKerberos, effectiveTime, expirationTime, windowsIdentity, false);

                // Authenticated 
                this.isAuthenticated = true;
            } 
            finally 
            {
                if (tokenHandle != null) 
                    tokenHandle.Close();

                if (securityContext != null)
                    securityContext.Close(); 

                if (ownCredentialsHandle && credentialsHandle != null) 
                    credentialsHandle.Close(); 
            }
        } 

        public override bool CanCreateKeyIdentifierClause()
        {
            if (typeof(T) == typeof(KerberosTicketHashKeyIdentifierClause)) 
                return true;
 
            return base.CanCreateKeyIdentifierClause(); 
        }
 
        public override T CreateKeyIdentifierClause()
        {
            if (typeof(T) == typeof(KerberosTicketHashKeyIdentifierClause))
                return new KerberosTicketHashKeyIdentifierClause(CryptoHelper.ComputeHash(this.request), false, null, 0) as T; 

            return base.CreateKeyIdentifierClause(); 
        } 

        public override bool MatchesKeyIdentifierClause(SecurityKeyIdentifierClause keyIdentifierClause) 
        {
            KerberosTicketHashKeyIdentifierClause kerbKeyIdentifierClause = keyIdentifierClause as KerberosTicketHashKeyIdentifierClause;
            if (kerbKeyIdentifierClause != null)
                return kerbKeyIdentifierClause.Matches(CryptoHelper.ComputeHash(this.request)); 

            return base.MatchesKeyIdentifierClause(keyIdentifierClause); 
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK