| 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;
}