Platform SDK: Logon Authentication |
The InitializeSecurityContext function initiates the outbound, client security context from a credential handle. The function establishes a security context between the client application and a remote peer. The InitializeSecurityContext function returns a token that the client must pass to the remote peer, which in turn submits it to the local security implementation through the AcceptSecurityContext call. The token generated is opaque to all callers.
*SecBufferDesc InBuffer; SecBuffer InBuffers[2]; SecBufferDesc OutBuffer; SecBuffer OutBuffers[1]; DWORD dwSSPIFlags; DWORD dwSSPIOutFlags; TimeStamp tsExpiry; SECURITY_STATUS scRet; DWORD cbData; BOOL fDoRead = FALSE; dwSSPIFlags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM; cbIoBuffer = 0; scRet = SEC_I_CONTINUE_NEEDED; while(scRet == SEC_I_CONTINUE_NEEDED || scRet == SEC_E_INCOMPLETE_MESSAGE || scRet == SEC_I_INCOMPLETE_CREDENTIALS) { //-------------------------------------------------------------------- // If the i/o buffer is empty, or it contains a fragment of a // handshake message, read more data from the server. if(0 == cbIoBuffer || scRet == SEC_E_INCOMPLETE_MESSAGE) { if(fDoRead) { BytesRead = ReadDataFromClient(IoBuffer + cbIoBuffer); cbIoBuffer += BytesRead; } else { fDoRead = TRUE; } } //-------------------------------------------------------------------- // Set up the input buffers. Buffer 0 is used to pass in data // received from the server. Schannel will consume some or all // of this. Leftover data (if any) will be placed in buffer 1 and // given a buffer type of SECBUFFER_EXTRA. InBuffers[0].pvBuffer = IoBuffer; InBuffers[0].cbBuffer = cbIoBuffer; InBuffers[0].BufferType = SECBUFFER_TOKEN; InBuffers[1].pvBuffer = NULL; InBuffers[1].cbBuffer = 0; InBuffers[1].BufferType = SECBUFFER_EMPTY; InBuffer.cBuffers = 2; InBuffer.pBuffers = InBuffers; InBuffer.ulVersion = SECBUFFER_VERSION; //-------------------------------------------------------------------- // Set up the output buffers. These are initialized to NULL OutBuffers[0].pvBuffer = NULL; OutBuffers[0].BufferType = SECBUFFER_TOKEN; OutBuffers[0].cbBuffer = 0; OutBuffer.cBuffers = 1; OutBuffer.pBuffers = OutBuffers; OutBuffer.ulVersion = SECBUFFER_VERSION; //-------------------------------------------------------------------- // Call InitializeSecurityContext. scRet = g_SecurityFunc.InitializeSecurityContextA( phCreds, phContext, NULL, dwSSPIFlags, 0, SECURITY_NATIVE_DREP, &InBuffer, 0, NULL, &OutBuffer, &dwSSPIOutFlags, &tsExpiry); //-------------------------------------------------------------------- // If InitializeSecurityContext was successful (or if the error was // one of the special extended ones), send the contents of the output // buffer to the server. if(scRet == SEC_E_OK || scRet == SEC_I_CONTINUE_NEEDED || FAILED(scRet) && (dwSSPIOutFlags & ISC_RET_EXTENDED_ERROR)) { if(OutBuffers[0].cbBuffer != 0 && OutBuffers[0].pvBuffer != NULL) { //-------------------------------------------------------------------- // Send response to client if there is one SendToClient(OutBuffers[0].pvBuffer, OutBuffers[0].cbBuffer); //-------------------------------------------------------------------- // Free the output buffer. g_SecurityFunc.FreeContextBuffer(OutBuffers[0].pvBuffer); OutBuffers[0].pvBuffer = NULL; } } //-------------------------------------------------------------------- // If InitializeSecurityContext returned SEC_E_INCOMPLETE_MESSAGE, // read more data from the server and try again. if(scRet == SEC_E_INCOMPLETE_MESSAGE) { continue; } //-------------------------------------------------------------------- // If InitializeSecurityContext returned SEC_E_OK, the // handshake completed successfully. if(scRet == SEC_E_OK) { //-------------------------------------------------------------------- // If the "extra" buffer contains data, this is encrypted application // protocol layer information. It needs to be saved. The // application layer will later decrypt it with DecryptMessage. if(InBuffers[1].BufferType == SECBUFFER_EXTRA) { MoveMemory( rgbIoBuffer, (LPBYTE)(rgbIoBuffer + (cbIoBuffer - InBuffers[1].cbBuffer)), InBuffers[1].cbBuffer); cbIoBuffer = InBuffers[1].cbBuffer; } else { cbIoBuffer = 0; } //-------------------------------------------------------------------- // The handshake is over. return TRUE; } //-------------------------------------------------------------------- // Check for fatal error. if(FAILED(scRet)) { printf("**** Error 0x%x returned by InitializeSecurityContext\n", scRet); break; } //-------------------------------------------------------------------- // If InitializeSecurityContext returned SEC_I_INCOMPLETE_CREDENTIALS, // the server just requested client authentication. if(scRet == SEC_I_INCOMPLETE_CREDENTIALS) { //-------------------------------------------------------------------- // The user could be prompted to select a client certificate and // obtain a new credential handle at this pont. fDoRead = FALSE; scRet = SEC_I_CONTINUE_NEEDED; continue; } //-------------------------------------------------------------------- // Copy any leftover data from the "extra" buffer, and go around // again. if ( InBuffers[1].BufferType == SECBUFFER_EXTRA ) { MoveMemory(IoBuffer, IoBuffer + (cbIoBuffer - InBuffers[1].cbBuffer), InBuffers[1].cbBuffer); cbIoBuffer = InBuffers[1].cbBuffer; } else { cbIoBuffer = 0; } }