247 lines
7.8 KiB
C
247 lines
7.8 KiB
C
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1995.
|
|
//
|
|
// File: srvprot.c
|
|
//
|
|
// Contents:
|
|
//
|
|
// Classes:
|
|
//
|
|
// Functions:
|
|
//
|
|
// History: 09-26-97 jbanes LSA integration stuff.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include <spbase.h>
|
|
#include <pct1msg.h>
|
|
#include <pct1prot.h>
|
|
#include <ssl2msg.h>
|
|
#include <ssl3msg.h>
|
|
#include <ssl2prot.h>
|
|
|
|
|
|
/* The main purpose of this handler is to determine what kind of protocol
|
|
* the client hello is
|
|
*/
|
|
|
|
SP_STATUS WINAPI
|
|
ServerProtocolHandler(
|
|
PSPContext pContext,
|
|
PSPBuffer pCommInput,
|
|
PSPBuffer pCommOutput)
|
|
{
|
|
SP_STATUS pctRet = PCT_INT_ILLEGAL_MSG;
|
|
PBYTE pb;
|
|
PBYTE pbClientHello;
|
|
DWORD dwVersion;
|
|
DWORD dwEnabledProtocols;
|
|
|
|
|
|
/* PCTv1.0 Hello starts with
|
|
* RECORD_LENGTH_MSB (ignore)
|
|
* RECORD_LENGTH_LSB (ignore)
|
|
* PCT1_CLIENT_HELLO (must be equal)
|
|
* PCT1_CLIENT_VERSION_MSB (if version greater than PCTv1)
|
|
* PCT1_CLIENT_VERSION_LSB (if version greater than PCTv1)
|
|
*
|
|
* ... PCT hello ...
|
|
*/
|
|
|
|
/* Microsft Unihello starts with
|
|
* RECORD_LENGTH_MSB (ignore)
|
|
* RECORD_LENGTH_LSB (ignore)
|
|
* SSL2_CLIENT_HELLO (must be equal)
|
|
* SSL2_CLIENT_VERSION_MSB (if version greater than SSLv2) ( or v3)
|
|
* SSL2_CLIENT_VERSION_LSB (if version greater than SSLv2) ( or v3)
|
|
*
|
|
* ... SSLv2 Compatable Hello ...
|
|
*/
|
|
|
|
/* SSLv2 Hello starts with
|
|
* RECORD_LENGTH_MSB (ignore)
|
|
* RECORD_LENGTH_LSB (ignore)
|
|
* SSL2_CLIENT_HELLO (must be equal)
|
|
* SSL2_CLIENT_VERSION_MSB (if version greater than SSLv2) ( or v3)
|
|
* SSL2_CLIENT_VERSION_LSB (if version greater than SSLv2) ( or v3)
|
|
*
|
|
* ... SSLv2 Hello ...
|
|
*/
|
|
|
|
/* SSLv3 Type 2 Hello starts with
|
|
* RECORD_LENGTH_MSB (ignore)
|
|
* RECORD_LENGTH_LSB (ignore)
|
|
* SSL2_CLIENT_HELLO (must be equal)
|
|
* SSL2_CLIENT_VERSION_MSB (if version greater than SSLv3)
|
|
* SSL2_CLIENT_VERSION_LSB (if version greater than SSLv3)
|
|
*
|
|
* ... SSLv2 Compatable Hello ...
|
|
*/
|
|
|
|
/* SSLv3 Type 3 Hello starts with
|
|
* 0x15 Hex (HANDSHAKE MESSAGE)
|
|
* VERSION MSB
|
|
* VERSION LSB
|
|
* RECORD_LENGTH_MSB (ignore)
|
|
* RECORD_LENGTH_LSB (ignore)
|
|
* HS TYPE (CLIENT_HELLO)
|
|
* 3 bytes HS record length
|
|
* HS Version
|
|
* HS Version
|
|
*/
|
|
|
|
dwEnabledProtocols = pContext->pCredGroup->grbitEnabledProtocols;
|
|
|
|
// We need at least 5 bytes to determine what we have.
|
|
if (pCommInput->cbData < 5)
|
|
{
|
|
return(PCT_INT_INCOMPLETE_MSG);
|
|
}
|
|
|
|
pb = pCommInput->pvBuffer;
|
|
|
|
// If the first byte is 0x15, then check if we have a
|
|
// SSLv3 Type3 client hello
|
|
if(pb[0] == SSL3_CT_HANDSHAKE)
|
|
{
|
|
//
|
|
// This is an SSL3 ClientHello.
|
|
//
|
|
|
|
// We need at least foo bytes to determine what we have.
|
|
if (pCommInput->cbData < sizeof(SWRAP) + sizeof(SHSH) + 2)
|
|
{
|
|
return(PCT_INT_INCOMPLETE_MSG);
|
|
}
|
|
pbClientHello = pb + sizeof(SWRAP) + sizeof(SHSH);
|
|
|
|
dwVersion = COMBINEBYTES(pbClientHello[0], pbClientHello[1]);
|
|
if(dwVersion > 0x300 && (0 != (SP_PROT_TLS1_SERVER & dwEnabledProtocols)))
|
|
{
|
|
DebugLog((DEB_TRACE, "SSL3 ClientHello received, selected TLS\n"));
|
|
pContext->dwProtocol = SP_PROT_TLS1_SERVER;
|
|
}
|
|
else if(0 != (SP_PROT_SSL3_SERVER & dwEnabledProtocols))
|
|
{
|
|
DebugLog((DEB_TRACE, "SSL3 ClientHello received, selected SSL3\n"));
|
|
pContext->dwProtocol = SP_PROT_SSL3_SERVER;
|
|
}
|
|
else
|
|
{
|
|
return SP_LOG_RESULT(PCT_INT_SPECS_MISMATCH);
|
|
}
|
|
|
|
pContext->ProtocolHandler = Ssl3ProtocolHandler;
|
|
pContext->DecryptHandler = Ssl3DecryptHandler;
|
|
pctRet = Ssl3ProtocolHandler(pContext, pCommInput, pCommOutput);
|
|
return(pctRet);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Assuming SSL2 (or compatible) ClientHello
|
|
//
|
|
|
|
dwVersion = COMBINEBYTES(pb[3], pb[4]);
|
|
}
|
|
|
|
if(dwVersion >= PCT_VERSION_1)
|
|
{
|
|
//
|
|
// This is a PCT ClientHello.
|
|
//
|
|
|
|
if(!(SP_PROT_PCT1_SERVER & dwEnabledProtocols))
|
|
{
|
|
return SP_LOG_RESULT(PCT_ERR_SPECS_MISMATCH);
|
|
}
|
|
|
|
// We're running PCT, so set up the PCT handlers
|
|
DebugLog((DEB_TRACE, "PCT ClientHello received, selected PCT\n"));
|
|
pContext->dwProtocol = SP_PROT_PCT1_SERVER;
|
|
pContext->ProtocolHandler = Pct1ServerProtocolHandler;
|
|
pContext->DecryptHandler = Pct1DecryptHandler;
|
|
return(Pct1ServerProtocolHandler(pContext, pCommInput, pCommOutput));
|
|
}
|
|
|
|
if(dwVersion >= SSL2_CLIENT_VERSION)
|
|
{
|
|
// we're either receiving ssl2, ssl3, or pct1 compat
|
|
|
|
PSSL2_CLIENT_HELLO pRawHello = pCommInput->pvBuffer;
|
|
|
|
// Do we have one client hello message with at least one
|
|
// cipher spec.
|
|
if (pCommInput->cbData < (sizeof(SSL2_CLIENT_HELLO)+2))
|
|
{
|
|
return(PCT_INT_INCOMPLETE_MSG);
|
|
}
|
|
|
|
// We must have at least one cipher spec
|
|
if(COMBINEBYTES(pRawHello->CipherSpecsLenMsb, pRawHello->CipherSpecsLenLsb) < 1)
|
|
{
|
|
return(SP_LOG_RESULT(PCT_INT_ILLEGAL_MSG));
|
|
}
|
|
|
|
// Does client support TLS?
|
|
if((dwVersion >= TLS1_CLIENT_VERSION) &&
|
|
(0 != (SP_PROT_TLS1_SERVER & dwEnabledProtocols)))
|
|
{
|
|
DebugLog((DEB_TRACE, "SSL2 ClientHello received, selected TLS\n"));
|
|
pContext->State = UNI_STATE_RECVD_UNIHELLO;
|
|
pContext->dwProtocol = SP_PROT_TLS1_SERVER;
|
|
pContext->ProtocolHandler = Ssl3ProtocolHandler;
|
|
pContext->DecryptHandler = Ssl3DecryptHandler;
|
|
return(Ssl3ProtocolHandler(pContext, pCommInput, pCommOutput));
|
|
}
|
|
|
|
// Does client support SSL3?
|
|
if((dwVersion >= SSL3_CLIENT_VERSION) &&
|
|
(0 != (SP_PROT_SSL3TLS1_SERVERS & dwEnabledProtocols)))
|
|
{
|
|
DebugLog((DEB_TRACE, "SSL2 ClientHello received, selected SSL3\n"));
|
|
pContext->State = UNI_STATE_RECVD_UNIHELLO;
|
|
pContext->dwProtocol = SP_PROT_SSL3_SERVER;
|
|
pContext->ProtocolHandler = Ssl3ProtocolHandler;
|
|
pContext->DecryptHandler = Ssl3DecryptHandler;
|
|
return(Ssl3ProtocolHandler(pContext, pCommInput, pCommOutput));
|
|
}
|
|
|
|
// Is the PCT compatability flag set?
|
|
if(pRawHello->VariantData[0] == PCT_SSL_COMPAT)
|
|
{
|
|
// Get the pct version.
|
|
dwVersion = COMBINEBYTES(pRawHello->VariantData[1], pRawHello->VariantData[2]);
|
|
}
|
|
|
|
// Does client support PCT?
|
|
if((dwVersion >= PCT_VERSION_1) &&
|
|
(0 != (SP_PROT_PCT1_SERVER & dwEnabledProtocols)))
|
|
{
|
|
DebugLog((DEB_TRACE, "SSL2 ClientHello received, selected PCT\n"));
|
|
pContext->State = UNI_STATE_RECVD_UNIHELLO;
|
|
pContext->dwProtocol = SP_PROT_PCT1_SERVER;
|
|
pContext->ProtocolHandler = Pct1ServerProtocolHandler;
|
|
pContext->DecryptHandler = Pct1DecryptHandler;
|
|
return(Pct1ServerProtocolHandler(pContext, pCommInput, pCommOutput));
|
|
}
|
|
|
|
// Does client support SSL2?
|
|
if((dwVersion >= SSL2_CLIENT_VERSION) &&
|
|
(0 != (SP_PROT_SSL2_SERVER & dwEnabledProtocols)))
|
|
{
|
|
DebugLog((DEB_TRACE, "SSL2 ClientHello received, selected SSL2\n"));
|
|
pContext->dwProtocol = SP_PROT_SSL2_SERVER;
|
|
pContext->ProtocolHandler = Ssl2ServerProtocolHandler;
|
|
pContext->DecryptHandler = Ssl2DecryptHandler;
|
|
return(Ssl2ServerProtocolHandler(pContext, pCommInput, pCommOutput));
|
|
}
|
|
|
|
return(SP_LOG_RESULT(PCT_INT_ILLEGAL_MSG));
|
|
}
|
|
|
|
return (pctRet);
|
|
}
|