/// <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="serverBuffer">The buffer containing the input data from the server.</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, SecureBuffer serverBuffer, SafeCredentialHandle credential, string serverPrincipal, SecurityContextAttributes requestedAttributes) { SecurityContextAttributes finalAttributes = SecurityContextAttributes.None; Timestamp expiry = new Timestamp(); using (SecureBufferAdapter outputAdapter = new SecureBufferAdapter(outputBuffer)) { using (SecureBufferAdapter serverAdapter = new SecureBufferAdapter(serverBuffer)) { return(NativeMethods.InitializeSecurityContext_2 ( ref credential.RawHandle, ref RawHandle, serverPrincipal, requestedAttributes, 0, NativeMethods.SecureBufferDataRep.Network, serverAdapter.Handle, 0, ref RawHandle, outputAdapter.Handle, ref finalAttributes, ref expiry )); } } }
/// <summary> /// Returns context requirements /// </summary> private static uint GetContextRequirements(bool serverContext, SecurityContextAttributes contextAttributes) { if (serverContext) { uint contextReq = SSPINative.ISC_REQ_USE_DCE_STYLE | SSPINative.ISC_REQ_CONFIDENTIALITY | SSPINative.ISC_REQ_REPLAY_DETECT | SSPINative.ISC_REQ_SEQUENCE_DETECT | SSPINative.ISC_REQ_CONNECTION; if ((contextAttributes & SecurityContextAttributes.Delegate) != 0) { contextReq = contextReq | SSPINative.ISC_REQ_DELEGATE | SSPINative.ISC_REQ_MUTUAL_AUTH; } if ((contextAttributes & SecurityContextAttributes.MutualAuthentication) != 0) { contextReq = contextReq | SSPINative.ISC_REQ_MUTUAL_AUTH; } if ((contextAttributes & SecurityContextAttributes.Identify) != 0) { contextReq = contextReq | SSPINative.ISC_REQ_IDENTIFY; } return(contextReq); } else { uint contextReq = SSPINative.ASC_REQ_USE_DCE_STYLE | SSPINative.ASC_REQ_CONFIDENTIALITY | SSPINative.ASC_REQ_REPLAY_DETECT | SSPINative.ASC_REQ_SEQUENCE_DETECT | SSPINative.ASC_REQ_CONNECTION; if ((contextAttributes & SecurityContextAttributes.Delegate) != 0) { contextReq = contextReq | SSPINative.ASC_REQ_DELEGATE | SSPINative.ASC_REQ_MUTUAL_AUTH; } if ((contextAttributes & SecurityContextAttributes.MutualAuthentication) != 0) { contextReq = contextReq | SSPINative.ASC_REQ_MUTUAL_AUTH; } if ((contextAttributes & SecurityContextAttributes.Identify) != 0) { contextReq = contextReq | SSPINative.ASC_REQ_IDENTIFY; } return(contextReq); } }
internal static extern SecurityStatus AcceptSecurityContext_2 ( ref RawSspiHandle phCredential, ref RawSspiHandle phContext, IntPtr pInput, SecurityContextAttributes fContextReq, SecureBufferDataRep targetDataRep, ref RawSspiHandle phNewContext, IntPtr pOutput, ref SecurityContextAttributes pfContextAttr, ref Timestamp ptsTimeStamp );
internal static extern SecurityStatus InitializeSecurityContext_2 ( ref RawSspiHandle phCredential, ref RawSspiHandle phContext, string pszTargetName, SecurityContextAttributes fContextReq, int reserved1, SecureBufferDataRep targetDataRep, IntPtr pInput, int reserved2, ref RawSspiHandle phNewContext, IntPtr pOutput, ref SecurityContextAttributes pfContextAttr, ref Timestamp ptsExpiry );
/// <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> /// Creates security context, proceeds client token and generates server token /// </summary> public SecurityContext AcceptSecurityContext( SecurityCredentials credentials, SecurityContextAttributes contextAttributes, byte[] inputToken, out byte[] outputToken) { // parameters validation if (credentials == null) { throw new ArgumentNullException("credentials"); } if (inputToken == null) { throw new ArgumentNullException("inputToken"); } // prepare requirements for context uint contextReq = GetContextRequirements(true, contextAttributes); // prepare buffers SecurityBuffers inputBuffers = new SecurityBuffers(1); inputBuffers.SetBuffer(0, (int)SSPINative.SECBUFFER_TOKEN, inputToken); SecurityBuffers outputBuffers = new SecurityBuffers(1); outputBuffers.SetBuffer(0, (int)SSPINative.SECBUFFER_TOKEN, _secPackage.MaxToken); // create context Int64 credHandle = credentials.Handle; Int64 newContextHandle; Int64 contextExpiry; uint contextAttribs; int error = SSPINative.AcceptSecurityContext( ref credHandle, IntPtr.Zero, inputBuffers, contextReq, SSPINative.SECURITY_NETWORK_DREP, out newContextHandle, outputBuffers, out contextAttribs, out contextExpiry); inputBuffers.Dispose(); // check context state bool continueNeeded = false; bool completeNeeded = false; switch (error) { case Win32.ERROR_SUCCESS: break; case SSPINative.SEC_I_CONTINUE_NEEDED: continueNeeded = true; break; case SSPINative.SEC_I_COMPLETE_NEEDED: completeNeeded = true; break; case SSPINative.SEC_I_COMPLETE_AND_CONTINUE: continueNeeded = true; completeNeeded = true; break; default: throw new SSPIException(error, "Could not accept security context"); } if (completeNeeded) { // complete context error = SSPINative.CompleteAuthToken(ref newContextHandle, outputBuffers); if (error < 0) { throw new SSPIException(error, "Could not complete security context"); } } // get output token outputToken = outputBuffers.GetBuffer(0); outputBuffers.Dispose(); // create context object SecurityContextState contextState = (continueNeeded ? SecurityContextState.ContinueNeeded : SecurityContextState.Completed); return(new SecurityContext(credentials, newContextHandle, contextExpiry, SecurityContextType.Server, contextState)); }
/// <summary> /// Updates security context, proceeds input token and generates output token /// </summary> public void UpdateSecurityContext( SecurityContext context, SecurityContextAttributes contextAttributes, byte[] inputToken, out byte[] outputToken) { // parameters validation if (context == null) { throw new ArgumentNullException("credentials"); } if (inputToken == null) { throw new ArgumentNullException("inputToken"); } // prepare requirements for context uint contextReq = GetContextRequirements(context.Type == SecurityContextType.Server, contextAttributes); // prepare buffers SecurityBuffers inputBuffers = new SecurityBuffers(1); inputBuffers.SetBuffer(0, (int)SSPINative.SECBUFFER_TOKEN, inputToken); SecurityBuffers outputBuffers = new SecurityBuffers(1); outputBuffers.SetBuffer(0, (int)SSPINative.SECBUFFER_TOKEN, _secPackage.MaxToken); // update context Int64 credHandle = context.credentials.Handle; Int64 contextHandle = context.Handle; uint contextAttribs; int error; if (context.Type == SecurityContextType.Client) { error = SSPINative.InitializeSecurityContext( ref credHandle, ref contextHandle, null, contextReq, 0, SSPINative.SECURITY_NETWORK_DREP, inputBuffers, 0, IntPtr.Zero, outputBuffers, out contextAttribs, IntPtr.Zero); } else { error = SSPINative.AcceptSecurityContext( ref credHandle, ref contextHandle, inputBuffers, contextReq, SSPINative.SECURITY_NETWORK_DREP, IntPtr.Zero, outputBuffers, out contextAttribs, IntPtr.Zero); } inputBuffers.Dispose(); // check context state bool continueNeeded = false; bool completeNeeded = false; switch (error) { case Win32.ERROR_SUCCESS: break; case SSPINative.SEC_I_CONTINUE_NEEDED: continueNeeded = true; break; case SSPINative.SEC_I_COMPLETE_NEEDED: completeNeeded = true; break; case SSPINative.SEC_I_COMPLETE_AND_CONTINUE: continueNeeded = true; completeNeeded = true; break; default: throw new SSPIException(error, "Could not update security context"); } if (completeNeeded) { // complete context error = SSPINative.CompleteAuthToken(ref contextHandle, outputBuffers); if (error < 0) { throw new SSPIException(error, "Could not complete security context"); } } // get output token outputToken = outputBuffers.GetBuffer(0); outputBuffers.Dispose(); // update context object state if (!continueNeeded) { context.SetCompleted(); } }
/// <summary> /// Initializes a new instance of the <see cref="ClientSecurityContext" /> class. /// </summary> /// <param name="credential">The security credential to use for authentication.</param> /// <param name="serverPrinciple">The principle name of the server to connect to, or null for any.</param> /// <param name="requestedAttributes">The desired properties of the context once it is established.</param> public ClientSecurityContext(SecurityCredential credential, string serverPrinciple, SecurityContextAttributes requestedAttributes) : base(credential) { _serverPrinciple = serverPrinciple; _requestedAttributes = requestedAttributes; }
/// <summary> /// Initializes a new instance of the <see cref="ServerSecurityContext" /> class. /// </summary> /// <param name="credential">The security credential to use for authentication.</param> /// <param name="requestedAttributes">The desired properties of the context once it is established.</param> public ServerSecurityContext(SecurityCredential credential, SecurityContextAttributes requestedAttributes) : base(credential) { _requestedAttributes = requestedAttributes; }
/// <summary> /// Creates security context and generates client token /// </summary> public SecurityContext CreateSecurityContext( SecurityCredentials credentials, SecurityContextAttributes contextAttributes, string targetName, out byte[] outputToken) { // parameters validation if (credentials == null) throw new ArgumentNullException("credentials"); // prepare requirements for context uint contextReq = GetContextRequirements(false, contextAttributes); // prepare buffers SecurityBuffers outputBuffers = new SecurityBuffers(1); outputBuffers.SetBuffer(0, (int)SSPINative.SECBUFFER_TOKEN, _secPackage.MaxToken); // create context Int64 credHandle = credentials.Handle; Int64 newContextHandle; Int64 contextExpiry; uint contextAttribs; int error = SSPINative.InitializeSecurityContext( ref credHandle, IntPtr.Zero, targetName, contextReq, 0, SSPINative.SECURITY_NETWORK_DREP, null, 0, out newContextHandle, outputBuffers, out contextAttribs, out contextExpiry); // check context state bool continueNeeded = false; bool completeNeeded = false; switch (error) { case Win32.ERROR_SUCCESS: break; case SSPINative.SEC_I_CONTINUE_NEEDED: continueNeeded = true; break; case SSPINative.SEC_I_COMPLETE_NEEDED: completeNeeded = true; break; case SSPINative.SEC_I_COMPLETE_AND_CONTINUE: continueNeeded = true; completeNeeded = true; break; default: throw new SSPIException(error, "Could not create security context"); } if (completeNeeded) { // complete context error = SSPINative.CompleteAuthToken(ref newContextHandle, outputBuffers); if (error < 0) throw new SSPIException(error, "Could not complete security context"); } // get output token outputToken = outputBuffers.GetBuffer(0); outputBuffers.Dispose(); // create context object SecurityContextState contextState = (continueNeeded ? SecurityContextState.ContinueNeeded : SecurityContextState.Completed); return new SecurityContext(credentials, newContextHandle, contextExpiry, SecurityContextType.Client, contextState); }
/// <summary> /// Returns context requirements /// </summary> private static uint GetContextRequirements(bool serverContext, SecurityContextAttributes contextAttributes) { if (serverContext) { uint contextReq = SSPINative.ISC_REQ_USE_DCE_STYLE | SSPINative.ISC_REQ_CONFIDENTIALITY | SSPINative.ISC_REQ_REPLAY_DETECT | SSPINative.ISC_REQ_SEQUENCE_DETECT | SSPINative.ISC_REQ_CONNECTION; if ((contextAttributes & SecurityContextAttributes.Delegate) != 0) contextReq = contextReq | SSPINative.ISC_REQ_DELEGATE | SSPINative.ISC_REQ_MUTUAL_AUTH; if ((contextAttributes & SecurityContextAttributes.MutualAuthentication) != 0) contextReq = contextReq | SSPINative.ISC_REQ_MUTUAL_AUTH; if ((contextAttributes & SecurityContextAttributes.Identify) != 0) contextReq = contextReq | SSPINative.ISC_REQ_IDENTIFY; return contextReq; } else { uint contextReq = SSPINative.ASC_REQ_USE_DCE_STYLE | SSPINative.ASC_REQ_CONFIDENTIALITY | SSPINative.ASC_REQ_REPLAY_DETECT | SSPINative.ASC_REQ_SEQUENCE_DETECT | SSPINative.ASC_REQ_CONNECTION; if ((contextAttributes & SecurityContextAttributes.Delegate) != 0) contextReq = contextReq | SSPINative.ASC_REQ_DELEGATE | SSPINative.ASC_REQ_MUTUAL_AUTH; if ((contextAttributes & SecurityContextAttributes.MutualAuthentication) != 0) contextReq = contextReq | SSPINative.ASC_REQ_MUTUAL_AUTH; if ((contextAttributes & SecurityContextAttributes.Identify) != 0) contextReq = contextReq | SSPINative.ASC_REQ_IDENTIFY; return contextReq; } }
/// <summary> /// Updates security context, proceeds input token and generates output token /// </summary> public void UpdateSecurityContext( SecurityContext context, SecurityContextAttributes contextAttributes, byte[] inputToken, out byte[] outputToken) { // parameters validation if (context == null) throw new ArgumentNullException("credentials"); if (inputToken == null) throw new ArgumentNullException("inputToken"); // prepare requirements for context uint contextReq = GetContextRequirements(context.Type == SecurityContextType.Server, contextAttributes); // prepare buffers SecurityBuffers inputBuffers = new SecurityBuffers(1); inputBuffers.SetBuffer(0, (int)SSPINative.SECBUFFER_TOKEN, inputToken); SecurityBuffers outputBuffers = new SecurityBuffers(1); outputBuffers.SetBuffer(0, (int)SSPINative.SECBUFFER_TOKEN, _secPackage.MaxToken); // update context Int64 credHandle = context.credentials.Handle; Int64 contextHandle = context.Handle; uint contextAttribs; int error; if (context.Type == SecurityContextType.Client) { error = SSPINative.InitializeSecurityContext( ref credHandle, ref contextHandle, null, contextReq, 0, SSPINative.SECURITY_NETWORK_DREP, inputBuffers, 0, IntPtr.Zero, outputBuffers, out contextAttribs, IntPtr.Zero); } else { error = SSPINative.AcceptSecurityContext( ref credHandle, ref contextHandle, inputBuffers, contextReq, SSPINative.SECURITY_NETWORK_DREP, IntPtr.Zero, outputBuffers, out contextAttribs, IntPtr.Zero); } inputBuffers.Dispose(); // check context state bool continueNeeded = false; bool completeNeeded = false; switch (error) { case Win32.ERROR_SUCCESS: break; case SSPINative.SEC_I_CONTINUE_NEEDED: continueNeeded = true; break; case SSPINative.SEC_I_COMPLETE_NEEDED: completeNeeded = true; break; case SSPINative.SEC_I_COMPLETE_AND_CONTINUE: continueNeeded = true; completeNeeded = true; break; default: throw new SSPIException(error, "Could not update security context"); } if (completeNeeded) { // complete context error = SSPINative.CompleteAuthToken(ref contextHandle, outputBuffers); if (error < 0) throw new SSPIException(error, "Could not complete security context"); } // get output token outputToken = outputBuffers.GetBuffer(0); outputBuffers.Dispose(); // update context object state if (!continueNeeded) { context.SetCompleted(); } }