/// <summary> /// Acquire an existing Windows security context. /// </summary> /// <param name="context"></param> /// <param name="contextAttributes"></param> /// <param name="contextLifetime"></param> /// <param name="continueNeeded"></param> /// <param name="securityPackage"></param> /// <param name="token"></param> public WindowsSecurityContext( Secur32.SecHandle context, uint contextAttributes, Secur32.SECURITY_INTEGER contextLifetime, Secur32.SecBufferDesc token, string securityPackage, bool continueNeeded) { _context = context; _contextAttributes = contextAttributes; _contextLifetime = contextLifetime; _securityPackage = securityPackage; _token = token; _continue = continueNeeded; }
/// <summary> /// Validate a security token and return the windows account of the user that generated the token. /// Implementation of <see cref="T:Waffle.Windows.AuthProvider.IWindowsAuthProvider.ValidateNegotiateToken" />. /// </summary> /// <remarks> /// This function supports AcceptSecurityToken continuation on the same thread. /// </remarks> /// <param name="connectionId">Connection id.</param> /// <param name="token">Security token.</param> /// <param name="securityPackage">Security package, eg. "Negotiate".</param> /// <param name="fContextReq"></param> /// <param name="targetDataRep"></param> /// <returns></returns> public IWindowsSecurityContext AcceptSecurityToken(string connectionId, byte[] token, string securityPackage, int fContextReq, int targetDataRep) { Secur32.SecHandle newContext = Secur32.SecHandle.Zero; Secur32.SecBufferDesc serverToken = Secur32.SecBufferDesc.Zero; Secur32.SecBufferDesc clientToken = Secur32.SecBufferDesc.Zero; Secur32.SECURITY_INTEGER serverLifetime = Secur32.SECURITY_INTEGER.Zero; WindowsCredentialsHandle credentialsHandle = new WindowsCredentialsHandle( string.Empty, Secur32.SECPKG_CRED_INBOUND, securityPackage); var tokenSize = Secur32.MAX_TOKEN_SIZE; var rc = 0; do { serverToken = new Secur32.SecBufferDesc(tokenSize); clientToken = new Secur32.SecBufferDesc(token); uint serverContextAttributes = 0; Secur32.SecHandle continueSecHandle = Secur32.SecHandle.Zero; lock (_continueSecHandles) { _continueSecHandles.TryGetValue(connectionId, out continueSecHandle); } if (continueSecHandle == Secur32.SecHandle.Zero) { rc = Secur32.AcceptSecurityContext( ref credentialsHandle.Handle, IntPtr.Zero, ref clientToken, fContextReq, targetDataRep, ref newContext, ref serverToken, out serverContextAttributes, out serverLifetime); } else { rc = Secur32.AcceptSecurityContext( ref credentialsHandle.Handle, ref continueSecHandle, ref clientToken, fContextReq, targetDataRep, ref newContext, ref serverToken, out serverContextAttributes, out serverLifetime); } switch (rc) { case Secur32.SEC_E_INSUFFICIENT_MEMORY: tokenSize += Secur32.MAX_TOKEN_SIZE; break; case Secur32.SEC_E_OK: lock (_continueSecHandles) { _continueSecHandles.Remove(connectionId); } return(new WindowsSecurityContext( newContext, serverContextAttributes, serverLifetime, serverToken, securityPackage, false)); case Secur32.SEC_I_CONTINUE_NEEDED: lock (_continueSecHandles) { _continueSecHandles[connectionId] = newContext; } return(new WindowsSecurityContext( newContext, serverContextAttributes, serverLifetime, serverToken, securityPackage, true)); default: lock (_continueSecHandles) { _continueSecHandles.Remove(connectionId); } throw new Win32Exception(rc); } } while (rc == Secur32.SEC_E_INSUFFICIENT_MEMORY); return(null); }