/// <summary> /// Performs and/or continues the authentication cycle. /// </summary> /// <param name="clientToken">The most recent token from the client.</param> /// <returns>The client's next authentication token in the cycle.</returns> /// <exception cref="ArgumentNullException"><paramref name="clientToken" /> is null.</exception> /// <exception cref="SspiException"> /// This method was called after this context was fully initialized. /// <para>or</para> /// The underlying SSPI operation failed. /// </exception> /// <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 and presenting it to the other side, which in turn may generate a new token. /// The cycle continues until the client and server both indicate that they are done. /// </remarks> public SspiToken AcceptToken(SspiToken clientToken) { if (clientToken == null) { throw new ArgumentNullException(nameof(clientToken)); } if (Disposed) { throw new ObjectDisposedException(nameof(SecurityContext)); } else if (Initialized) { throw new SspiException("Attempted to call Initialize on a server context that was already initialized."); } SecureBuffer clientBuffer = new SecureBuffer(clientToken.Token, SecureBufferType.Token); SecureBuffer outputBuffer = new SecureBuffer(new byte[Credential.PackageInfo.MaxTokenLength], SecureBufferType.Token); SecurityStatus status = Handle.AcceptSecurityContext(outputBuffer, clientBuffer, Credential.Handle, _requestedAttributes); if (!status.IsError()) { if (status == SecurityStatus.Ok) { Initialized = true; } return(new SspiToken(outputBuffer)); } else { throw new SspiException("Failed to initialize security context for a server."); } }
/// <summary> /// Initializes a new instance of the <see cref="SspiToken" /> class. /// </summary> /// <param name="tokenBuffer">The token buffer.</param> internal SspiToken(SecureBuffer tokenBuffer) { if (tokenBuffer.Length > 0) { Token = new byte[tokenBuffer.Length]; Array.Copy(tokenBuffer.Buffer, Token, Token.Length); } }
private SspiToken Initialize(byte[] serverToken) { if (Disposed) { throw new ObjectDisposedException(nameof(ClientSecurityContext)); } else if (Initialized) { throw new SspiException("Attempted to call Initialize on a client context that was already initialized."); } // The security package tells us how long its biggest token will be. // Allocate a buffer that size, and it will tell us how much it used. SecureBuffer outputBuffer = new SecureBuffer(new byte[Credential.PackageInfo.MaxTokenLength], SecureBufferType.Token); SecurityStatus status; if (serverToken == null) { // First time calling initialize - no server token yet status = Handle.InitializeSecurityContext(outputBuffer, Credential.Handle, _serverPrinciple, _requestedAttributes); } else { // Subsequent calls - server token has been provided SecureBuffer serverBuffer = new SecureBuffer(serverToken, SecureBufferType.Token); status = Handle.InitializeSecurityContext(outputBuffer, serverBuffer, Credential.Handle, _serverPrinciple, _requestedAttributes); } if (!status.IsError()) { if (status == SecurityStatus.Ok) { Initialized = true; } return(new SspiToken(outputBuffer)); } else { throw new SspiException("Failed to initialize security context for a client."); } }
/// <summary> /// Establishes a security context between the server and a remote client. /// </summary> /// <param name="outputBuffer">The buffer that will hold the output token.</param> /// <param name="clientBuffer">The buffer containing the input data from the client.</param> /// <param name="credential">The credential handle.</param> /// <param name="requestedAttributes">The requested attributes.</param> /// <returns>A <see cref="SecurityStatus" /> representing the result of the operation.</returns> public SecurityStatus AcceptSecurityContext(SecureBuffer outputBuffer, SecureBuffer clientBuffer, SafeCredentialHandle credential, SecurityContextAttributes requestedAttributes) { SecurityContextAttributes finalAttributes = SecurityContextAttributes.None; Timestamp expiry = new Timestamp(); using (SecureBufferAdapter outputAdapter = new SecureBufferAdapter(outputBuffer)) { using (SecureBufferAdapter clientAdapter = new SecureBufferAdapter(clientBuffer)) { if (this.IsInvalid) { return(NativeMethods.AcceptSecurityContext_1 ( ref credential.RawHandle, IntPtr.Zero, clientAdapter.Handle, requestedAttributes, NativeMethods.SecureBufferDataRep.Network, ref RawHandle, outputAdapter.Handle, ref finalAttributes, ref expiry )); } else { return(NativeMethods.AcceptSecurityContext_2 ( ref credential.RawHandle, ref RawHandle, clientAdapter.Handle, requestedAttributes, NativeMethods.SecureBufferDataRep.Network, ref RawHandle, outputAdapter.Handle, ref finalAttributes, ref expiry )); } } } }
/// <summary> /// Initializes the client-side security context from a credental handle. /// </summary> /// <param name="outputBuffer">The buffer that will hold the output token.</param> /// <param name="credential">The credential handle.</param> /// <param name="serverPrincipal">The server principal.</param> /// <param name="requestedAttributes">The requested attributes.</param> /// <returns>A <see cref="SecurityStatus" /> representing the result of the operation.</returns> public SecurityStatus InitializeSecurityContext(SecureBuffer outputBuffer, SafeCredentialHandle credential, string serverPrincipal, SecurityContextAttributes requestedAttributes) { SecurityContextAttributes finalAttributes = SecurityContextAttributes.None; Timestamp expiry = new Timestamp(); using (SecureBufferAdapter outputAdapter = new SecureBufferAdapter(outputBuffer)) { return(NativeMethods.InitializeSecurityContext_1 ( ref credential.RawHandle, IntPtr.Zero, serverPrincipal, requestedAttributes, 0, NativeMethods.SecureBufferDataRep.Network, IntPtr.Zero, 0, ref RawHandle, outputAdapter.Handle, ref finalAttributes, ref expiry )); } }
/// <summary> /// Initializes a new instance of the <see cref="SecureBufferAdapter" /> class. /// </summary> /// <param name="buffer">The buffer.</param> public SecureBufferAdapter(SecureBuffer buffer) : this(new List <SecureBuffer> { buffer }) { }