Platform SDK: Logon Authentication |
The AcceptSecurityContext function enables the server to establish a security context between the server and a remote client. The remote client uses the InitializeSecurityContext function to start the process of establishing a security context. The server might need one or more reply tokens from the remote client to completely establish the security context.
TimeStamp tsExpiry; SECURITY_STATUS scRet; SecBufferDesc InBuffer; SecBuffer InBuffers[2]; SecBufferDesc OutBuffer; SecBuffer OutBuffers[1]; BOOL fInitContext = TRUE; DWORD dwSSPIFlags DWORD dwSSPIOutFlags; dwSSPIFlags = ASC_REQ_SEQUENCE_DETECT | ASC_REQ_REPLAY_DETECT | ASC_REQ_CONFIDENTIALITY | ASC_REQ_EXTENDED_ERROR | ASC_REQ_ALLOCATE_MEMORY | ASC_REQ_STREAM; if(fClientAuth) { dwSSPIFlags |= ASC_REQ_MUTUAL_AUTH; } cbIoBuffer = 0; scRet = SEC_I_CONTINUE_NEEDED; while(scRet == SEC_I_CONTINUE_NEEDED || scRet == SEC_E_INCOMPLETE_MESSAGE) { //-------------------------------------------------------------------- // If the i/o buffer is empty, or it contains a fragment of a // handshake message, read more data from the client. if(0 == cbIoBuffer || scRet == SEC_E_INCOMPLETE_MESSAGE) { BytesRead = ReadDataFromClient(IoBuffer + cbIoBuffer); cbIoBuffer += BytesRead; } //-------------------------------------------------------------------- // Set up the input and output buffers. InBuffers[0].pvBuffer = rgbIoBuffer; 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; OutBuffers[0].pvBuffer = NULL; OutBuffers[0].BufferType = SECBUFFER_TOKEN; OutBuffers[0].cbBuffer = 0; OutBuffer.cBuffers = 1; OutBuffer.pBuffers = OutBuffers; OutBuffer.ulVersion = SECBUFFER_VERSION; scRet = g_SecurityFunc.AcceptSecurityContext( phCred, fInitContext ? NULL : phContext, &InBuffer, dwSSPIFlags, SECURITY_NATIVE_DREP, fInitContext ? phContext : NULL, &OutBuffer, &dwSSPIOutFlags, &tsExpiry); fInitContext = FALSE; //-------------------------------------------------------------------- // If AcceptSecurityContext was successful (or if the error was // one of the special extended ones), send the contents // of the output buffer to the client. if(scRet == SEC_E_OK || scRet == SEC_I_CONTINUE_NEEDED || (FAILED(scRet) && (0 != (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(scRet == SEC_E_OK) { if(InBuffers[1].BufferType == SECBUFFER_EXTRA) { // The extra buffer contains leftover data from the input // buffer that was not consumed. Put this data back in the // i/o buffer, so it can get processed later by //DecryptMessage. MoveMemory(rgbIoBuffer, (LPBYTE)(rgbIoBuffer + (cbIoBuffer - InBuffers[1].cbBuffer)), InBuffers[1].cbBuffer); cbIoBuffer = InBuffers[1].cbBuffer; } else { cbIoBuffer = 0; } // The handshake is over. return TRUE; } if(FAILED(scRet) && (scRet != SEC_E_INCOMPLETE_MESSAGE)) { printf("AcceptSecurityContext failed with error code %lx\n", scRet); return FALSE; } if(scRet != SEC_E_INCOMPLETE_MESSAGE) { if(InBuffers[1].BufferType == SECBUFFER_EXTRA) { // The extra buffer contains leftover data from the input // buffer that was not consumed. Put this data back in the // i/o buffer, so it can get processed on the next pass. MoveMemory(rgbIoBuffer, (LPBYTE)(rgbIoBuffer + (cbIoBuffer - InBuffers[1].cbBuffer)), InBuffers[1].cbBuffer); cbIoBuffer = InBuffers[1].cbBuffer; } else { cbIoBuffer = 0; } } // Go around again. continue; }