internal static extern CSecurityStatus AcquireCredentialsHandle(
     string principleName,
     string packageName,
     CCredentialUse credentialUse,
     IntPtr loginId,
     IntPtr packageData,
     IntPtr getKeyFunc,
     IntPtr getKeyData,
     ref CRawSspiHandle credentialHandle,
     ref CTimeStamp expiry
     );
Ejemplo n.º 2
0
 internal static extern CSecurityStatus AcceptSecurityContext_2(
     ref CRawSspiHandle credHandle,
     ref CRawSspiHandle oldContextHandle,
     IntPtr inputBuffer,
     CContextAttrib requestedAttribs,
     CSecureBufferDataRep dataRep,
     ref CRawSspiHandle newContextHandle,
     IntPtr outputBuffer,
     ref CContextAttrib outputAttribs,
     ref CTimeStamp expiry
     );
Ejemplo n.º 3
0
 internal static extern CSecurityStatus InitializeSecurityContext_2(
     ref CRawSspiHandle credentialHandle,
     ref CRawSspiHandle previousHandle,
     string serverPrincipleName,
     CContextAttrib requiredAttribs,
     int reserved1,
     CSecureBufferDataRep dataRep,
     IntPtr inputBuffer,
     int reserved2,
     ref CRawSspiHandle newContextHandle,
     IntPtr outputBuffer,
     ref CContextAttrib contextAttribs,
     ref CTimeStamp expiry
     );
        private void Init(CCredentialUse use)
        {
            string          packageName;
            CTimeStamp      rawExpiry = new CTimeStamp();
            CSecurityStatus status    = CSecurityStatus.InternalError;

            // -- Package --
            // Copy off for the call, since this.SecurityPackage is a property.
            packageName = this.SecurityPackage;

            this.Handle = new CSafeCredentialHandle();

            // The finally clause is the actual constrained region. The VM pre-allocates any stack space,
            // performs any allocations it needs to prepare methods for execution, and postpones any
            // instances of the 'uncatchable' exceptions (ThreadAbort, StackOverflow, OutOfMemory).
            RuntimeHelpers.PrepareConstrainedRegions();
            try { }
            finally
            {
                status = CCredentialNativeMethods.AcquireCredentialsHandle(
                    null,
                    packageName,
                    use,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    ref this.Handle.rawHandle,
                    ref rawExpiry
                    );
            }

            if (status != CSecurityStatus.OK)
            {
                throw new CSSPIException("Failed to call AcquireCredentialHandle", status);
            }

            this.Expiry = rawExpiry.ToDateTime();
        }
        /// <summary>
        /// Performs and continues the authentication cycle.
        /// </summary>
        /// <remarks>
        /// This method is performed iteratively to continue and end the authentication cycle with the
        /// client. Each stage works by acquiring a token from one side, presenting it to the other side
        /// which in turn may generate a new token.
        ///
        /// The cycle typically starts and ends with the client. On the first invocation on the client,
        /// no server token exists, and null is provided in its place. The client returns its status, providing
        /// its output token for the server. The server accepts the clients token as input and provides a
        /// token as output to send back to the client. This cycle continues until the server and client
        /// both indicate, typically, a SecurityStatus of 'OK'.
        /// </remarks>
        /// <param name="clientToken">The most recently received token from the client.</param>
        /// <param name="nextToken">The servers next authentication token in the cycle, that must
        /// be sent to the client.</param>
        /// <returns>A status message indicating the progression of the authentication cycle.
        /// A status of 'OK' indicates that the cycle is complete, from the servers's perspective. If the nextToken
        /// is not null, it must be sent to the client.
        /// A status of 'Continue' indicates that the output token should be sent to the client and
        /// a response should be anticipated.</returns>
        public CSecurityStatus AcceptToken(byte[] clientToken, out byte[] nextToken)
        {
            CSecureBuffer clientBuffer;
            CSecureBuffer outBuffer;

            CSecurityStatus status;
            CTimeStamp      rawExpiry = new CTimeStamp();

            CSecureBufferAdapter clientAdapter;
            CSecureBufferAdapter outAdapter;

            if (this.Disposed)
            {
                throw new ObjectDisposedException("ServerContext");
            }
            else if (this.Initialized)
            {
                throw new InvalidOperationException(
                          "Attempted to continue initialization of a ServerContext after initialization had completed."
                          );
            }

            clientBuffer = new CSecureBuffer(clientToken, CBufferType.Token);

            outBuffer = new CSecureBuffer(
                new byte[this.Credential.PackageInfo.MaxTokenLength],
                CBufferType.Token
                );

            using (clientAdapter = new CSecureBufferAdapter(clientBuffer))
            {
                using (outAdapter = new CSecureBufferAdapter(outBuffer))
                {
                    if (this.ContextHandle.IsInvalid)
                    {
                        status = CContextNativeMethods.AcceptSecurityContext_1(
                            ref this.Credential.Handle.rawHandle,
                            IntPtr.Zero,
                            clientAdapter.Handle,
                            requestedAttribs,
                            CSecureBufferDataRep.Network,
                            ref this.ContextHandle.rawHandle,
                            outAdapter.Handle,
                            ref this.finalAttribs,
                            ref rawExpiry
                            );
                    }
                    else
                    {
                        status = CContextNativeMethods.AcceptSecurityContext_2(
                            ref this.Credential.Handle.rawHandle,
                            ref this.ContextHandle.rawHandle,
                            clientAdapter.Handle,
                            requestedAttribs,
                            CSecureBufferDataRep.Network,
                            ref this.ContextHandle.rawHandle,
                            outAdapter.Handle,
                            ref this.finalAttribs,
                            ref rawExpiry
                            );
                    }
                }
            }

            if (status == CSecurityStatus.OK)
            {
                nextToken = null;

                base.Initialize(rawExpiry.ToDateTime());

                if (outBuffer.Length != 0)
                {
                    nextToken = new byte[outBuffer.Length];
                    Array.Copy(outBuffer.Buffer, nextToken, nextToken.Length);
                }
                else
                {
                    nextToken = null;
                }
            }
            else if (status == CSecurityStatus.ContinueNeeded)
            {
                nextToken = new byte[outBuffer.Length];
                Array.Copy(outBuffer.Buffer, nextToken, nextToken.Length);
            }
            else
            {
                throw new CSSPIException("Failed to call AcceptSecurityContext", status);
            }

            return(status);
        }
        /// <summary>
        /// Performs and continues the authentication cycle.
        /// </summary>
        /// <remarks>
        /// This method is performed iteratively to start, continue, and end the authentication cycle with the
        /// server. Each stage works by acquiring a token from one side, presenting it to the other side
        /// which in turn may generate a new token.
        ///
        /// The cycle typically starts and ends with the client. On the first invocation on the client,
        /// no server token exists, and null is provided in its place. The client returns its status, providing
        /// its output token for the server. The server accepts the clients token as input and provides a
        /// token as output to send back to the client. This cycle continues until the server and client
        /// both indicate, typically, a SecurityStatus of 'OK'.
        /// </remarks>
        /// <param name="serverToken">The most recently received token from the server, or null if beginning
        /// the authentication cycle.</param>
        /// <param name="outToken">The clients next authentication token in the authentication cycle.</param>
        /// <returns>A status message indicating the progression of the authentication cycle.
        /// A status of 'OK' indicates that the cycle is complete, from the client's perspective. If the outToken
        /// is not null, it must be sent to the server.
        /// A status of 'Continue' indicates that the output token should be sent to the server and
        /// a response should be anticipated.</returns>
        public CSecurityStatus Init(byte[] serverToken, out byte[] outToken)
        {
            CTimeStamp rawExpiry = new CTimeStamp();

            CSecurityStatus status;

            CSecureBuffer        outTokenBuffer;
            CSecureBufferAdapter outAdapter;

            CSecureBuffer        serverBuffer;
            CSecureBufferAdapter serverAdapter;

            if (this.Disposed)
            {
                throw new ObjectDisposedException("ClientContext");
            }
            else if ((serverToken != null) && (this.ContextHandle.IsInvalid))
            {
                throw new InvalidOperationException("Out-of-order usage detected - have a server token, but no previous client token had been created.");
            }
            else if ((serverToken == null) && (this.ContextHandle.IsInvalid == false))
            {
                throw new InvalidOperationException("Must provide the server's response when continuing the init process.");
            }

            // The security package tells us how big its biggest token will be. We'll allocate a buffer
            // that size, and it'll tell us how much it used.
            outTokenBuffer = new CSecureBuffer(
                new byte[this.Credential.PackageInfo.MaxTokenLength],
                CBufferType.Token
                );

            serverBuffer = null;
            if (serverToken != null)
            {
                serverBuffer = new CSecureBuffer(serverToken, CBufferType.Token);
            }

            // Some notes on handles and invoking InitializeSecurityContext
            //  - The first time around, the phContext parameter (the 'old' handle) is a null pointer to what
            //    would be an RawSspiHandle, to indicate this is the first time it's being called.
            //    The phNewContext is a pointer (reference) to an RawSspiHandle struct of where to write the
            //    new handle's values.
            //  - The next time you invoke ISC, it takes a pointer to the handle it gave you last time in phContext,
            //    and takes a pointer to where it should write the new handle's values in phNewContext.
            //  - After the first time, you can provide the same handle to both parameters. From MSDN:
            //       "On the second call, phNewContext can be the same as the handle specified in the phContext
            //        parameter."
            //    It will overwrite the handle you gave it with the new handle value.
            //  - All handle structures themselves are actually *two* pointer variables, eg, 64 bits on 32-bit
            //    Windows, 128 bits on 64-bit Windows.
            //  - So in the end, on a 64-bit machine, we're passing a 64-bit value (the pointer to the struct) that
            //    points to 128 bits of memory (the struct itself) for where to write the handle numbers.
            using (outAdapter = new CSecureBufferAdapter(outTokenBuffer))
            {
                if (this.ContextHandle.IsInvalid)
                {
                    status = CContextNativeMethods.InitializeSecurityContext_1(
                        ref this.Credential.Handle.rawHandle,
                        IntPtr.Zero,
                        this.serverPrinc,
                        this.requestedAttribs,
                        0,
                        CSecureBufferDataRep.Network,
                        IntPtr.Zero,
                        0,
                        ref this.ContextHandle.rawHandle,
                        outAdapter.Handle,
                        ref this.finalAttribs,
                        ref rawExpiry
                        );
                }
                else
                {
                    using (serverAdapter = new CSecureBufferAdapter(serverBuffer))
                    {
                        status = CContextNativeMethods.InitializeSecurityContext_2(
                            ref this.Credential.Handle.rawHandle,
                            ref this.ContextHandle.rawHandle,
                            this.serverPrinc,
                            this.requestedAttribs,
                            0,
                            CSecureBufferDataRep.Network,
                            serverAdapter.Handle,
                            0,
                            ref this.ContextHandle.rawHandle,
                            outAdapter.Handle,
                            ref this.finalAttribs,
                            ref rawExpiry
                            );
                    }
                }
            }

            if (status.IsError() == false)
            {
                if (status == CSecurityStatus.OK)
                {
                    base.Initialize(rawExpiry.ToDateTime());
                }

                outToken = null;

                if (outTokenBuffer.Length != 0)
                {
                    outToken = new byte[outTokenBuffer.Length];
                    Array.Copy(outTokenBuffer.Buffer, outToken, outToken.Length);
                }
            }
            else
            {
                throw new CSSPIException("Failed to invoke InitializeSecurityContext for a client", status);
            }

            return(status);
        }