WindowsSspiNegotiation.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Security / WindowsSspiNegotiation.cs / 2 / WindowsSspiNegotiation.cs

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

namespace System.ServiceModel.Security 
{
    using System.Runtime.InteropServices; 
    using System.ServiceModel.Channels; 
    using System.ServiceModel;
    using System.ServiceModel.Diagnostics; 
    using System.Diagnostics;
    using System.Text;
    using System.Threading;
    using System.Globalization; 
    using System.ComponentModel;
    using System.Security.Principal; 
    using System.IdentityModel.Tokens; 
    using System.Net;
    using System.IdentityModel; 

    using DiagnosticUtility = System.ServiceModel.DiagnosticUtility;
    using SR = System.ServiceModel.SR;
 
    internal sealed class WindowsSspiNegotiation : ISspiNegotiation
    { 
        SspiContextFlags contextFlags; 
        SafeFreeCredentials credentialsHandle;
        bool disposed = false; 
        bool doMutualAuth;
        TokenImpersonationLevel impersonationLevel;
        bool isCompleted;
        bool isServer; 
        LifeSpan lifespan;
        string protocolName; 
        SafeDeleteContext securityContext; 
        string servicePrincipalName;
        SecSizes sizes; 
        Object syncObject = new Object();
        int tokenSize;

        ///  
        /// Client side ctor
        ///  
        internal WindowsSspiNegotiation(string package, SafeFreeCredentials credentialsHandle, TokenImpersonationLevel impersonationLevel, string servicePrincipalName, bool doMutualAuth) 
            : this(false, package, credentialsHandle, impersonationLevel, servicePrincipalName, doMutualAuth)
        { } 

        /// 
        /// Server side ctor
        ///  
        internal WindowsSspiNegotiation(string package, SafeFreeCredentials credentialsHandle)
            : this(true, package, credentialsHandle, TokenImpersonationLevel.Delegation, null, false) 
        { } 

        WindowsSspiNegotiation(bool isServer, string package, SafeFreeCredentials credentialsHandle, TokenImpersonationLevel impersonationLevel, string servicePrincipalName, bool doMutualAuth) 
        {
            this.tokenSize = SspiWrapper.GetVerifyPackageInfo(package).MaxToken;
            this.isServer = isServer;
            this.servicePrincipalName = servicePrincipalName; 
            this.securityContext = null;
            if (isServer) 
            { 
                this.impersonationLevel = TokenImpersonationLevel.Delegation;
                this.doMutualAuth = false; 
            }
            else
            {
                this.impersonationLevel = impersonationLevel; 
                this.doMutualAuth = doMutualAuth;
            } 
            this.credentialsHandle = credentialsHandle; 
        }
 
        public DateTime ExpirationTimeUtc
        {
            get
            { 
                ThrowIfDisposed();
                if (this.LifeSpan == null) 
                { 
                    return SecurityUtils.MaxUtcDateTime;
                } 
                else
                {
                    return this.LifeSpan.ExpiryTimeUtc;
                } 
            }
        } 
 
        public bool IsCompleted
        { 
            get
            {
                ThrowIfDisposed();
                return this.isCompleted; 
            }
        } 
 
        public bool IsDelegationFlag
        { 
            get
            {
                ThrowIfDisposed();
                return (this.contextFlags & SspiContextFlags.Delegate) != 0; 
            }
        } 
 
        public bool IsIdentifyFlag
        { 
            get
            {
                ThrowIfDisposed();
                return (this.contextFlags & (this.isServer ? SspiContextFlags.AcceptIdentify : SspiContextFlags.InitIdentify)) != 0; 
            }
        } 
 
        public bool IsMutualAuthFlag
        { 
            get
            {
                ThrowIfDisposed();
                return (this.contextFlags & SspiContextFlags.MutualAuth) != 0; 
            }
        } 
 
        public bool IsValidContext
        { 
            get
            {
                return (this.securityContext != null && this.securityContext.IsInvalid == false);
            } 
        }
 
        public string KeyEncryptionAlgorithm 
        {
            get 
            {
                return SecurityAlgorithms.WindowsSspiKeyWrap;
            }
        } 

        public LifeSpan LifeSpan 
        { 
            get
            { 
                ThrowIfDisposed();
                if (this.lifespan == null)
                {
                    LifeSpan tmpLifeSpan = (LifeSpan) SspiWrapper.QueryContextAttributes(this.securityContext, ContextAttribute.Lifespan); 

                    if (IsCompleted) 
                    { 
                        // cache it only when it's completed
                        this.lifespan = tmpLifeSpan; 
                    }

                    return tmpLifeSpan;
                } 

                return this.lifespan; 
            } 
        }
 
        public string ProtocolName
        {
            get
            { 
                ThrowIfDisposed();
                if (this.protocolName == null) 
                { 
                    NegotiationInfoClass negotiationInfo = SspiWrapper.QueryContextAttributes(this.securityContext, ContextAttribute.NegotiationInfo) as NegotiationInfoClass;
 
                    if (IsCompleted)
                    {
                        // cache it only when it's completed
                        this.protocolName = negotiationInfo.AuthenticationPackage; 
                    }
 
                    return negotiationInfo.AuthenticationPackage; 
                }
 
                return this.protocolName;
            }
        }
 
        public string ServicePrincipalName
        { 
            get 
            {
                ThrowIfDisposed(); 
                return this.servicePrincipalName;
            }
        }
 
        SecSizes SecuritySizes
        { 
            get 
            {
                ThrowIfDisposed(); 
                if (this.sizes == null)
                {
                    SecSizes tmpSizes = (SecSizes) SspiWrapper.QueryContextAttributes(this.securityContext, ContextAttribute.Sizes);
 
                    if (IsCompleted)
                    { 
                        // cache it only when it's completed 
                        this.sizes = tmpSizes;
                    } 

                    return tmpSizes;
                }
 
                return this.sizes;
            } 
        } 

        public string GetRemoteIdentityName() 
        {
            if (!this.isServer)
            {
                return this.servicePrincipalName; 
            }
 
            if (IsValidContext) 
            {
                using (SafeCloseHandle contextToken = GetContextToken()) 
                {
                    using (WindowsIdentity windowsIdentity = new WindowsIdentity(contextToken.DangerousGetHandle()))
                    {
                        return windowsIdentity.Name; 
                    }
                } 
            } 
            return String.Empty;
        } 

        public byte[] Decrypt(byte[] encryptedContent)
        {
            if (encryptedContent == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("encryptedContent");
            ThrowIfDisposed(); 
 
            SecurityBuffer[] securityBuffer = new SecurityBuffer[2];
            securityBuffer[0] = new SecurityBuffer(encryptedContent, 0, encryptedContent.Length, BufferType.Stream); 
            securityBuffer[1] = new SecurityBuffer(0, BufferType.Data);
            int errorCode = SspiWrapper.DecryptMessage(this.securityContext, securityBuffer, 0, true);
            if (errorCode != 0)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(errorCode));
            } 
 
            for (int i = 0; i < securityBuffer.Length; ++i)
            { 
                if (securityBuffer[i].type == BufferType.Data)
                {
                    return securityBuffer[i].token;
                } 
            }
            OnBadData(); 
            return null; 
        }
 
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this); 
        }
 
        public byte[] Encrypt(byte[] input) 
        {
            if (input == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("input");
            ThrowIfDisposed();
            SecurityBuffer[] securityBuffer = new SecurityBuffer[3];
 
            byte[] tokenBuffer = DiagnosticUtility.Utility.AllocateByteArray(SecuritySizes.SecurityTrailer);
            securityBuffer[0] = new SecurityBuffer(tokenBuffer, 0, tokenBuffer.Length, BufferType.Token); 
            byte[] dataBuffer = DiagnosticUtility.Utility.AllocateByteArray(input.Length); 
            Buffer.BlockCopy(input, 0, dataBuffer, 0, input.Length);
            securityBuffer[1] = new SecurityBuffer(dataBuffer, 0, dataBuffer.Length, BufferType.Data); 
            byte[] paddingBuffer = DiagnosticUtility.Utility.AllocateByteArray(SecuritySizes.BlockSize);
            securityBuffer[2] = new SecurityBuffer(paddingBuffer, 0, paddingBuffer.Length, BufferType.Padding);

            int errorCode = SspiWrapper.EncryptMessage(this.securityContext, securityBuffer, 0); 
            if (errorCode != 0)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(errorCode)); 
            }
 
            int tokenLen = 0;
            int paddingLen = 0;
            for (int i = 0; i < securityBuffer.Length; ++i)
            { 
                if (securityBuffer[i].type == BufferType.Token)
                    tokenLen = securityBuffer[i].size; 
                else if (securityBuffer[i].type == BufferType.Padding) 
                    paddingLen = securityBuffer[i].size;
            } 
            byte[] encryptedData = DiagnosticUtility.Utility.AllocateByteArray(checked(tokenLen + dataBuffer.Length + paddingLen));

            Buffer.BlockCopy(tokenBuffer, 0, encryptedData, 0, tokenLen);
            Buffer.BlockCopy(dataBuffer, 0, encryptedData, tokenLen, dataBuffer.Length); 
            Buffer.BlockCopy(paddingBuffer, 0, encryptedData, tokenLen + dataBuffer.Length, paddingLen);
 
            return encryptedData; 
        }
 
        public byte[] GetOutgoingBlob(byte[] incomingBlob)
        {
            ThrowIfDisposed();
            SspiContextFlags requestedFlags = SspiContextFlags.Zero; 
            if (this.doMutualAuth)
            { 
                requestedFlags |= SspiContextFlags.MutualAuth; 
            }
 
            if (this.impersonationLevel == TokenImpersonationLevel.Delegation)
            {
                requestedFlags |= SspiContextFlags.Delegate;
            } 
            else if (this.isServer == false && this.impersonationLevel == TokenImpersonationLevel.Identification)
            { 
                requestedFlags |= SspiContextFlags.InitIdentify; 
            }
            else if (this.isServer == false && this.impersonationLevel == TokenImpersonationLevel.Anonymous) 
            {
                requestedFlags |= SspiContextFlags.InitAnonymous;
            }
 
            // use the confidentiality option to ensure we can encrypt messages
            requestedFlags |= SspiContextFlags.Confidentiality; 
            requestedFlags |= SspiContextFlags.ReplayDetect; 
            requestedFlags |= SspiContextFlags.SequenceDetect;
            requestedFlags |= SspiContextFlags.ReplayDetect; 
            requestedFlags |= SspiContextFlags.SequenceDetect;

            SecurityBuffer inSecurityBuffer = null;
            int statusCode; 

            if (incomingBlob != null) 
            { 
                inSecurityBuffer = new SecurityBuffer(incomingBlob, BufferType.Token);
            } 

            SecurityBuffer outSecurityBuffer = new SecurityBuffer(this.tokenSize, BufferType.Token);

            if (!this.isServer) 
            {
                // client side 
                statusCode = SspiWrapper.InitializeSecurityContext(this.credentialsHandle, ref this.securityContext, this.servicePrincipalName, requestedFlags, Endianness.Network, inSecurityBuffer, outSecurityBuffer, ref this.contextFlags); 
            }
            else 
            {
                // server session
                statusCode = SspiWrapper.AcceptSecurityContext(this.credentialsHandle, ref this.securityContext, requestedFlags, Endianness.Network, inSecurityBuffer, outSecurityBuffer, ref this.contextFlags);
            } 

            if ((statusCode & unchecked((int) 0x80000000)) != 0) 
            { 
                CloseContext();
                this.isCompleted = true; 
                if (!this.isServer && (statusCode == (int) SecurityStatus.NoCredentials
                    || statusCode == (int) SecurityStatus.TargetUnknown
                    || statusCode == (int) SecurityStatus.WrongPrincipal))
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(statusCode, SR.GetString(SR.IncorrectSpnOrUpnSpecified, this.servicePrincipalName)));
                } 
                else 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(statusCode, SR.GetString(SR.InvalidSspiNegotiation))); 
                }
            }

            if (statusCode ==(int) SecurityStatus.OK) 
            {
                // we're done 
                this.isCompleted = true; 
                //this.contextFlags = (SspiContextFlags) SspiWrapper.QueryContextAttributes(this.securityContext, ContextAttribute.Flags);
            } 
            else
            {
                // we need to continue
            } 

            return outSecurityBuffer.token; 
        } 

        public void ImpersonateContext() 
        {
            ThrowIfDisposed();
            if (!IsValidContext)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception((int) SecurityStatus.InvalidHandle));
            } 
 
            SspiWrapper.ImpersonateSecurityContext(this.securityContext);
        } 

        internal void CloseContext()
        {
            ThrowIfDisposed(); 
            try
            { 
                if (this.securityContext != null) 
                {
                    this.securityContext.Close(); 
                }
            }
            finally
            { 
                this.securityContext = null;
            } 
        } 

 
        private void Dispose(bool disposing)
        {
            lock (this.syncObject)
            { 
                if (this.disposed == false)
                { 
                    if (disposing) 
                    {
                        this.CloseContext(); 
                    }

                    // set to null any references that aren't finalizable
                    this.protocolName = null; 
                    this.servicePrincipalName = null;
                    this.sizes = null; 
                    this.disposed = true; 
                }
            } 
        }

        internal SafeCloseHandle GetContextToken()
        { 
            if (!IsValidContext)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception((int) SecurityStatus.InvalidHandle)); 
            }
 
            SafeCloseHandle token;
            SecurityStatus status = (SecurityStatus) SspiWrapper.QuerySecurityContextToken(this.securityContext, out token);
            if (status != SecurityStatus.OK)
            { 
                Utility.CloseInvalidOutSafeHandle(token);
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception((int) status)); 
            } 
            return token;
        } 

        void OnBadData()
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.BadData))); 
        }
 
        void ThrowIfDisposed() 
        {
            lock (this.syncObject) 
            {
                if (this.disposed)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ObjectDisposedException(null)); 
                }
            } 
        } 
    }
} 

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

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