Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1070 lines
44 KiB

/****************************************************************************/
/* slapi.cpp */
/* */
/* Security Layer API */
/* */
/* Copyright (C) 1997-1999 Microsoft Corporation */
/****************************************************************************/
#include <adcg.h>
extern "C" {
#define TRC_GROUP TRC_GROUP_SECURITY
#define TRC_FILE "aslapi"
#include <atrcapi.h>
}
#include "autil.h"
#include "wui.h"
#include "sl.h"
#include "nl.h"
#include "td.h"
#include "cd.h"
#include "clicense.h"
CSL::CSL(CObjs* objs)
{
_pClientObjects = objs;
_fSLInitComplete = FALSE;
}
CSL::~CSL()
{
}
/****************************************************************************/
/* Name: SL_Init */
/* */
/* Purpose: Initialize the Security Layer */
/* */
/* Params: pCallbacks - list of callbacks */
/* */
/* Operation: Called in the Send context */
/****************************************************************************/
DCVOID DCINTERNAL CSL::SL_Init(PSL_CALLBACKS pCallbacks)
{
SL_CALLBACKS myCallbacks;
DC_BEGIN_FN("SL_Init");
SL_DBG_SETINFO(SL_DBG_INIT_CALLED);
_pUt = _pClientObjects->_pUtObject;
_pUi = _pClientObjects->_pUiObject;
_pNl = _pClientObjects->_pNlObject;
_pUh = _pClientObjects->_pUHObject;
_pRcv = _pClientObjects->_pRcvObject;
_pCd = _pClientObjects->_pCdObject;
_pSnd = _pClientObjects->_pSndObject;
_pCc = _pClientObjects->_pCcObject;
_pIh = _pClientObjects->_pIhObject;
_pOr = _pClientObjects->_pOrObject;
_pSp = _pClientObjects->_pSPObject;
_pMcs = _pClientObjects->_pMCSObject;
_pTd = _pClientObjects->_pTDObject;
_pCo = _pClientObjects->_pCoObject;
_pClx = _pClientObjects->_pCLXObject;
_pLic = _pClientObjects->_pLicObject;
_pChan = _pClientObjects->_pChanObject;
/************************************************************************/
/* Initialize global data */
/************************************************************************/
DC_MEMSET(&_SL, 0, sizeof(_SL));
SL_CHECK_STATE(SL_EVENT_SL_INIT);
/************************************************************************/
/* Check parameters */
/************************************************************************/
TRC_ASSERT((pCallbacks != NULL), (TB, _T("Null callback list")));
TRC_ASSERT((pCallbacks->onInitialized != NULL),
(TB, _T("NULL onInitialized callback")));
TRC_ASSERT((pCallbacks->onTerminating != NULL),
(TB, _T("NULL onTerminating callback")));
TRC_ASSERT((pCallbacks->onConnected != NULL),
(TB, _T("NULL onConnected callback")));
TRC_ASSERT((pCallbacks->onDisconnected != NULL),
(TB, _T("NULL onDisconnected callback")));
TRC_ASSERT((pCallbacks->onPacketReceived != NULL),
(TB, _T("NULL onPacketReceived callback")));
TRC_ASSERT((pCallbacks->onBufferAvailable != NULL),
(TB, _T("NULL onBufferAvailable callback")));
/************************************************************************/
/* Store callbacks */
/************************************************************************/
DC_MEMCPY(&_SL.callbacks, pCallbacks, sizeof(_SL.callbacks));
/************************************************************************/
/* Initialize Security stuff. The call to SLInitSecurity will attempt */
/* to load the security DLL and find the required entry points. This */
/* may fail - in which case we just carry on but without any */
/* encryption. In either case we need to call SLInitCSUserData to set */
/* up the necessary user data. */
/************************************************************************/
SLInitSecurity();
SLInitCSUserData();
/************************************************************************/
/* Initialize list of callbacks to pass to NL */
/************************************************************************/
myCallbacks.onInitialized = CSL::SL_StaticOnInitialized;
myCallbacks.onTerminating = CSL::SL_StaticOnTerminating;
myCallbacks.onConnected = CSL::SL_StaticOnConnected;
myCallbacks.onDisconnected = CSL::SL_StaticOnDisconnected;
myCallbacks.onPacketReceived = CSL::SL_StaticOnPacketReceived;
myCallbacks.onBufferAvailable = CSL::SL_StaticOnBufferAvailable;
SL_SET_STATE(SL_STATE_INITIALIZING);
/************************************************************************/
/* Initialize NL */
/************************************************************************/
TRC_NRM((TB, _T("Initialize NL")));
_pNl->NL_Init(&myCallbacks);
_fSLInitComplete = TRUE;
SL_DBG_SETINFO(SL_DBG_INIT_DONE);
/************************************************************************/
/* Return to caller */
/************************************************************************/
DC_EXIT_POINT:
DC_END_FN();
return;
} /* SL_Init */
/****************************************************************************/
/* Name: SL_Term */
/* */
/* Purpose: Terminate the Security Layer */
/* */
/* Operation: Called in the Send context */
/****************************************************************************/
DCVOID DCAPI CSL::SL_Term(DCVOID)
{
DC_BEGIN_FN("SL_Term");
SL_DBG_SETINFO(SL_DBG_TERM_CALLED);
SL_CHECK_STATE(SL_EVENT_SL_TERM);
SL_SET_STATE(SL_STATE_TERMINATING);
TRC_NRM((TB, _T("Terminate NL")));
_pNl->NL_Term();
if (_SL.encryptionMethodSelected == SM_FIPS_ENCRYPTION_FLAG) {
TSCAPI_Term(&(_SL.SLCapiData));
}
SL_DBG_SETINFO(SL_DBG_TERM_DONE);
DC_EXIT_POINT:
SL_DBG_SETINFO(SL_DBG_TERM_DONE1);
DC_END_FN();
return;
} /* SL_Term */
/****************************************************************************/
/* Name: SL_Connect */
/* */
/* Purpose: Connect to a Server */
/* */
/* Params: bInitiateConnect - Initiate connection */
/* pServerAddress - address of the Server to connect to */
/* transportType - protocol type: SL_TRANSPORT_TCP */
/* pProtocolName - protocol name, one of */
/* - SL_PROTOCOL_T128 */
/* - Er, that's it. */
/* pUserData - user data to pass to Server Security Manager */
/* userDataLength - length of user data */
/* */
/* Operation: Called in the Send context */
/****************************************************************************/
DCVOID DCAPI CSL::SL_Connect(BOOL bInitiateConnect,
PDCTCHAR pServerAddress,
DCUINT transportType,
PDCTCHAR pProtocolName,
PDCUINT8 pUserData,
DCUINT userDataLength)
{
DCUINT newUserDataLength;
PDCUINT8 pUserDataOut = NULL;
DCBOOL userDataAllocated = FALSE;
DC_BEGIN_FN("SL_Connect");
SL_DBG_SETINFO(SL_DBG_CONNECT_CALLED);
SL_CHECK_STATE(SL_EVENT_SL_CONNECT);
if( bInitiateConnect )
{
TRC_ASSERT((pServerAddress != NULL), (TB, _T("NULL Server address")));
}
//
// Reset this for every connection
//
SL_SetEncSafeChecksumCS(FALSE);
SL_SetEncSafeChecksumSC(FALSE);
TRC_ASSERT((pProtocolName != NULL), (TB, _T("NULL protocol name")));
TRC_ASSERT((DC_TSTRCMP(pProtocolName, SL_PROTOCOL_T128) == 0),
(TB, _T("Unknown protocol %s"), pProtocolName));
TRC_ASSERT((transportType == SL_TRANSPORT_TCP),
(TB,_T("Illegal transport type %u"), transportType));
if( bInitiateConnect )
{
TRC_NRM((TB, _T("Connect Server %s, protocol %s, %u bytes user data"),
pServerAddress, pProtocolName, userDataLength));
}
else
{
TRC_NRM((TB, _T("Connect endpoint protocol %s, %u bytes user data"),
pProtocolName, userDataLength));
}
/************************************************************************/
/* Allocate space for all user data */
/************************************************************************/
if (_SL.CSUserDataLength != 0)
{
newUserDataLength = userDataLength + _SL.CSUserDataLength;
pUserDataOut = (PDCUINT8)UT_Malloc(_pUt, newUserDataLength);
if (pUserDataOut == NULL)
{
TRC_ERR((TB, _T("Failed to alloc %u bytes for user data"),
newUserDataLength));
/****************************************************************/
/* We've not tried to connect the lower layers yet so we need */
/* to do no more than just decouple to the receiver thread and */
/* generate a onDisconnected callback. */
/****************************************************************/
_pCd->CD_DecoupleSimpleNotification(CD_RCV_COMPONENT, this,
CD_NOTIFICATION_FUNC(CSL,SLIssueDisconnectedCallback),
(ULONG_PTR) SL_ERR_NOMEMFORSENDUD);
DC_QUIT;
}
TRC_NRM((TB, _T("Allocated %u bytes for user data"), newUserDataLength));
userDataAllocated = TRUE;
/********************************************************************/
/* Copy user data passed by Core (if any) to new user data buffer */
/********************************************************************/
if (pUserData != NULL)
{
TRC_NRM((TB, _T("Copy %u bytes of Core user data"), userDataLength));
DC_MEMCPY(pUserDataOut, pUserData, userDataLength);
}
/********************************************************************/
/* Copy security user data */
/********************************************************************/
TRC_NRM((TB, _T("Copy %u bytes of security user data"),
_SL.CSUserDataLength));
DC_MEMCPY(pUserDataOut + userDataLength,
_SL.pCSUserData,
_SL.CSUserDataLength);
}
else
{
/********************************************************************/
/* NO SL user data - just pass on Core data. */
/********************************************************************/
TRC_DBG((TB, _T("No SL user data")));
newUserDataLength = userDataLength;
pUserDataOut = pUserData;
}
/************************************************************************/
/* Next state */
/************************************************************************/
SL_SET_STATE(SL_STATE_NL_CONNECTING);
/************************************************************************/
/* Call NL */
/************************************************************************/
if( bInitiateConnect )
{
TRC_NRM((TB, _T("Connect to %s"), pServerAddress));
}
else
{
TRC_NRM((TB, _T("Connect with end point")));
}
_pNl->NL_Connect(
bInitiateConnect, // initate connection
pServerAddress,
transportType,
pProtocolName,
pUserDataOut,
newUserDataLength);
SL_DBG_SETINFO(SL_DBG_CONNECT_DONE);
DC_EXIT_POINT:
/************************************************************************/
/* Free user data (if any) */
/************************************************************************/
if ( userDataAllocated )
{
TRC_NRM((TB, _T("Free user data")));
UT_Free(_pUt, pUserDataOut);
}
DC_END_FN();
} /* SL_Connect */
/****************************************************************************/
/* Name: SL_Disconnect */
/* */
/* Purpose: Disconnect from the Server */
/* */
/* Operation: Called in the Send context */
/****************************************************************************/
DCVOID DCAPI CSL::SL_Disconnect(DCVOID)
{
DC_BEGIN_FN("SL_Disconnect");
SL_DBG_SETINFO(SL_DBG_DISCONNECT_CALLED);
SL_CHECK_STATE(SL_EVENT_SL_DISCONNECT);
SL_DBG_SETINFO(SL_DBG_DISCONNECT_DONE1);
DC_EXIT_POINT:
/************************************************************************/
/* Regardless of the outcome of the state check we want to try and */
/* disconnect - so always call NL_Disconnect. */
/************************************************************************/
TRC_NRM((TB, _T("Disconnect from Server")));
SL_SET_STATE(SL_STATE_DISCONNECTING);
_pNl->NL_Disconnect();
SL_DBG_SETINFO(SL_DBG_DISCONNECT_DONE2);
DC_END_FN();
} /* SL_Disconnect */
/****************************************************************************/
/* Name: SL_SendPacket */
/* */
/* Purpose: Send a packet */
/* */
/* Params: pData - pointer to data to send (buffer returned by */
/* SL_GetBuffer()) */
/* dataLen - length of data to send (excluding security */
/* header) */
/* flags - zero or more of the RNS_SEC flags */
/* bufHandle - buffer handle returned by SL_GetBuffer() */
/* userID - MCS user ID */
/* channel - channel ID to send data on */
/* priority - priority of data - one of */
/* - TS_LOWPRIORITY */
/* - TS_MEDPRIORITY */
/* - TS_HIGHPRIORITY */
/* */
/* Operation: Note that the contents of the packet are changed by this */
/* function. */
/* */
/* Called in the Send context */
/****************************************************************************/
DCVOID DCAPI CSL::SL_SendPacket(PDCUINT8 pData,
DCUINT dataLen,
DCUINT flags,
SL_BUFHND bufHandle,
DCUINT userID,
DCUINT channel,
DCUINT priority)
{
DCBOOL rc = FALSE;
DC_BEGIN_FN("SL_SendPacket");
SL_CHECK_STATE(SL_EVENT_SL_SENDPACKET);
/************************************************************************/
/* Check if we're encrypting this message */
/************************************************************************/
if (_SL.encrypting ||
(flags & RNS_SEC_INFO_PKT) ||
(flags & RNS_SEC_LICENSE_PKT))
{
TRC_DBG((TB, _T("Encrypting")));
if (_SL.encrypting && (flags & RNS_SEC_ENCRYPT))
{
PRNS_SECURITY_HEADER1 pSecHeader1;
PRNS_SECURITY_HEADER2 pSecHeader2;
TRC_DBG((TB, _T("Encrypt this message")));
if (_SL.encryptionMethodSelected == SM_FIPS_ENCRYPTION_FLAG) {
pSecHeader2 = (PRNS_SECURITY_HEADER2)
(pData - sizeof(RNS_SECURITY_HEADER2));
pSecHeader2->padlen = TSCAPI_AdjustDataLen(dataLen) - dataLen;
pSecHeader2->length = sizeof(RNS_SECURITY_HEADER2);
pSecHeader2->version = TSFIPS_VERSION1;
}
else {
pSecHeader1 = (PRNS_SECURITY_HEADER1)
(pData - sizeof(RNS_SECURITY_HEADER1));
}
/****************************************************************/
/* check to see we need to update the session key. */
/****************************************************************/
if( _SL.encryptCount == UPDATE_SESSION_KEY_COUNT ) {
TRC_ALT((TB, _T("Update Encrypt Session Key, Count=%d"),
_SL.encryptCount));
rc = TRUE;
// Don't need to update the session key if using FIPS
if (_SL.encryptionMethodSelected != SM_FIPS_ENCRYPTION_FLAG) {
rc = UpdateSessionKey(
_SL.startEncryptKey,
_SL.currentEncryptKey,
_SL.encryptionMethodSelected,
_SL.keyLength,
&_SL.rc4EncryptKey,
_SL.encryptionLevel);
}
if (rc) {
// Reset counter.
_SL.encryptCount = 0;
}
else {
TRC_ERR((TB, _T("SL failed to update session key")));
DC_QUIT;
}
}
TRC_ASSERT((_SL.encryptCount < UPDATE_SESSION_KEY_COUNT),
(TB, _T("Invalid encrypt count")));
TRC_DATA_DBG("Data buffer before encryption", pData, dataLen);
if (_SL.encryptionMethodSelected == SM_FIPS_ENCRYPTION_FLAG) {
DWORD dataLenTemp;
dataLenTemp = dataLen;
rc = TSCAPI_EncryptData(
&(_SL.SLCapiData),
pData,
&dataLenTemp,
dataLen + pSecHeader2->padlen,
(LPBYTE)pSecHeader2->dataSignature,
_SL.totalEncryptCount);
}
else {
rc = EncryptData(
_SL.encryptionLevel,
_SL.currentEncryptKey,
&_SL.rc4EncryptKey,
_SL.keyLength,
pData,
dataLen,
_SL.macSaltKey,
(LPBYTE)pSecHeader1->dataSignature,
SL_GetEncSafeChecksumCS(),
_SL.totalEncryptCount);
}
if (rc) {
TRC_DBG((TB, _T("Data encrypted")));
TRC_DATA_DBG("Data buffer after encryption", pData, dataLen);
// Increment the encryption counter.
_SL.encryptCount++;
_SL.totalEncryptCount++;
if (SL_GetEncSafeChecksumCS()) {
flags |= RDP_SEC_SECURE_CHECKSUM;
}
// Message encrypted successfully. Set up security header and
// NL data pointer and length.
if (_SL.encryptionMethodSelected == SM_FIPS_ENCRYPTION_FLAG) {
pSecHeader2->flags = (DCUINT16)flags;
pData = (PDCUINT8)pSecHeader2;
dataLen += (sizeof(RNS_SECURITY_HEADER2) + pSecHeader2->padlen);
}
else {
pSecHeader1->flags = (DCUINT16)flags;
pData = (PDCUINT8)pSecHeader1;
dataLen += sizeof(RNS_SECURITY_HEADER1);
}
}
else {
TRC_ERR((TB, _T("SM failed to encrypt data")));
//
// This call is made on the Send thread so there is no need
// to trigger an immediate disconnect with SL_DropLinkImmediate
//
SLSetReasonAndDisconnect(SL_ERR_ENCRYPTFAILED);
DC_QUIT;
}
}
else
{
PRNS_SECURITY_HEADER pSecHeader;
/****************************************************************/
/* Packet not encrypted - send flags, but not the signature. */
/****************************************************************/
pSecHeader = (PRNS_SECURITY_HEADER)
(pData - sizeof(RNS_SECURITY_HEADER));
/****************************************************************/
/* setup security headers and NL data pointer and length */
/****************************************************************/
pSecHeader->flags = (DCUINT16)flags;
pData = (PDCUINT8)pSecHeader;
dataLen += sizeof(RNS_SECURITY_HEADER);
TRC_DATA_DBG("Send unencrypted data", pData, dataLen);
}
}
/************************************************************************/
/* Trace out parameters and send the packet. */
/************************************************************************/
TRC_DBG((TB, _T("Send buf:%p len:%u flags:%#x handle:%#x userID:%u chan:%u")
_T("pri:%u"),
pData,
dataLen,
flags,
bufHandle,
userID,
channel,
priority));
//NL_SendPacket is a macro to an MCS function.
_pMcs->NL_SendPacket(pData,
dataLen,
flags,
bufHandle,
userID,
channel,
priority);
/************************************************************************/
/* No state change */
/************************************************************************/
DC_EXIT_POINT:
DC_END_FN();
} /* SL_SendPacket */
/****************************************************************************/
// SL_SendFastPathInputPacket
//
// Encrypts and assembles the security information and the final header
// format for a fast-path input packet before sending to TD. See at128.h for
// the fast-path input packet format.
/****************************************************************************/
void DCAPI CSL::SL_SendFastPathInputPacket(
BYTE FAR *pData,
unsigned PktLen,
unsigned NumEvents,
SL_BUFHND bufHandle)
{
DCBOOL rc;
unsigned flags;
DWORD dataLenTemp;
PBYTE pDataSignature;
DCUINT8 *pPadLen;
DC_BEGIN_FN("SL_SendFastPathInputPacket");
SL_CHECK_STATE(SL_EVENT_SL_SENDPACKET);
// We're encrypting if encyption enabled on this link.
if (_SL.encrypting) {
// Check to see we need to update the session key.
if (_SL.encryptCount == UPDATE_SESSION_KEY_COUNT) {
TRC_ALT((TB, _T("Update Encrypt Session Key, Count=%d"),
_SL.encryptCount));
rc = TRUE;
// Don't need to update the session key if using FIPS
if (_SL.encryptionMethodSelected != SM_FIPS_ENCRYPTION_FLAG) {
rc = UpdateSessionKey(
_SL.startEncryptKey,
_SL.currentEncryptKey,
_SL.encryptionMethodSelected,
_SL.keyLength,
&_SL.rc4EncryptKey,
_SL.encryptionLevel);
}
if (rc) {
// Reset counter.
_SL.encryptCount = 0;
}
else {
TRC_ERR((TB, _T("SL failed to update session key")));
DC_QUIT;
}
}
TRC_ASSERT((_SL.encryptCount < UPDATE_SESSION_KEY_COUNT),
(TB, _T("Invalid encrypt count")));
// We encrypt into the DATA_SIGNATURE_SIZE bytes immediately before
// the packet data. Unlike the regular send path, we don't waste 4
// extra bytes in an RNS_SECURITY_HEADER1 to contain the 'encrypted'
// bit.
if (_SL.encryptionMethodSelected == SM_FIPS_ENCRYPTION_FLAG) {
dataLenTemp = PktLen;
pDataSignature = pData - MAX_SIGN_SIZE;
pPadLen = (DCUINT8 *)(pDataSignature - sizeof(DCUINT8));
*pPadLen = (DCUINT8)(TSCAPI_AdjustDataLen(PktLen) - PktLen);
rc = TSCAPI_EncryptData(
&(_SL.SLCapiData),
pData,
&dataLenTemp,
PktLen + *pPadLen,
pDataSignature,
_SL.totalEncryptCount);
}
else {
rc = EncryptData(
_SL.encryptionLevel,
_SL.currentEncryptKey,
&_SL.rc4EncryptKey,
_SL.keyLength,
pData,
PktLen,
_SL.macSaltKey,
pData - DATA_SIGNATURE_SIZE,
SL_GetEncSafeChecksumCS(),
_SL.totalEncryptCount);
}
if (rc) {
// Increment the encryption counter.
_SL.encryptCount++;
_SL.totalEncryptCount++;
flags = TS_INPUT_FASTPATH_ENCRYPTED;
if (_SL.encryptionMethodSelected == SM_FIPS_ENCRYPTION_FLAG) {
pData -= (sizeof(RNS_SECURITY_HEADER2) - 4);
PktLen += (sizeof(RNS_SECURITY_HEADER2) - 4 + *pPadLen);
}
else {
pData -= DATA_SIGNATURE_SIZE;
PktLen += DATA_SIGNATURE_SIZE;
}
TRC_DBG((TB, _T("Data encrypted")));
}
else {
//
// This call is made on the Send thread so there is no need
// to trigger an immediate disconnect with SL_DropLinkImmediate
//
SLSetReasonAndDisconnect(SL_ERR_ENCRYPTFAILED);
TRC_ERR((TB, _T("SM failed to encrypt data")));
DC_QUIT;
}
}
else {
// No encryption flag.
flags = 0;
}
// Now prepend the fast-path header (2 or 3 bytes, see at128.h).
// Work backwards from where we are: First, the total packet length
// including the header.
if (PktLen <= 125) {
// 1-byte form of length, high bit 0.
PktLen += 2;
pData -= 2;
*(pData + 1) = (BYTE)PktLen;
}
else {
// 2-byte form of length, first byte has high bit 1 and 7 most
// significant bits.
PktLen += 3;
pData -= 3;
*(pData + 1) = (BYTE)(0x80 | ((PktLen & 0x7F00) >> 8));
*(pData + 2) = (BYTE)(PktLen & 0xFF);
}
// The header byte.
*pData = (BYTE)(flags | (NumEvents << 2));
//
// Flag if the packet has a checksum of encrypted bytes
//
if (SL_GetEncSafeChecksumCS()) {
*pData |= TS_INPUT_FASTPATH_SECURE_CHECKSUM;
}
// Direct-send the packet through the transport, no more parsing needed.
_pTd->TD_SendBuffer(pData, PktLen, bufHandle);
DC_EXIT_POINT:
DC_END_FN();
}
#ifdef DC_DEBUG
/****************************************************************************/
/* Name: SL_GetBufferDbg */
/* */
/* Purpose: Get a send buffer (debug version) */
/* */
/* Returns: see SL_GetBufferRtl */
/* */
/* Params: see SL_GetBufferRtl */
/* pCaller - name of calling function */
/****************************************************************************/
DCBOOL DCAPI CSL::SL_GetBufferDbg(DCUINT dataLen,
PPDCUINT8 ppBuffer,
PSL_BUFHND pBufHandle,
PDCTCHAR pCaller)
{
DCBOOL bRc;
DC_BEGIN_FN("SL_GetBufferDbg");
/************************************************************************/
/* First get a buffer */
/************************************************************************/
bRc = SL_GetBufferRtl(dataLen, ppBuffer, pBufHandle);
/************************************************************************/
/* If that worked, set its owner */
/************************************************************************/
if (bRc)
{
TRC_NRM((TB, _T("Buffer allocated - set its owner")));
_pTd->TD_SetBufferOwner(*pBufHandle, pCaller);
}
DC_END_FN();
return(bRc);
} /* SL_GetBufferDbg */
#endif /* DC_DEBUG */
/****************************************************************************/
/* Name: SL_GetBufferRtl */
/* */
/* Purpose: Get a send buffer (retail version) */
/* */
/* Returns: TRUE - buffer available */
/* FALSE - buffer not available */
/* */
/* Params: dataLen - Size of buffer required */
/* pBuffer - Pointer to the returned buffer */
/* pBufHandle - Pointer to the buffer handle */
/****************************************************************************/
DCBOOL DCAPI CSL::SL_GetBufferRtl(DCUINT dataLen,
PPDCUINT8 ppBuffer,
PSL_BUFHND pBufHandle)
{
DCBOOL rc = FALSE;
DCUINT myLen;
PDCUINT8 myBuffer;
DCUINT headerLen;
DCUINT newDataLen;
PRNS_SECURITY_HEADER2 pSecHeader2;
DC_BEGIN_FN("SL_GetBufferRtl");
SL_CHECK_STATE(SL_EVENT_SL_GETBUFFER);
/************************************************************************/
/* Adjust requested length to account for SL header */
/************************************************************************/
if (_SL.encrypting)
{
if (_SL.encryptionMethodSelected == SM_FIPS_ENCRYPTION_FLAG) {
// If FIPS is used,
// it must have room for an extra block
headerLen = sizeof(RNS_SECURITY_HEADER2);
newDataLen = TSCAPI_AdjustDataLen(dataLen);
myLen = newDataLen + headerLen;
}
else {
headerLen = sizeof(RNS_SECURITY_HEADER1);
myLen = dataLen + headerLen;
}
TRC_DBG((TB, _T("Ask NL for %d (was %d) bytes"), myLen, dataLen));
}
else
{
myLen = dataLen;
headerLen = 0;
TRC_DBG((TB, _T("Not encrypting, ask NL for %d bytes"), myLen));
}
/************************************************************************/
/* Get buffer from NL */
/************************************************************************/
rc = _pMcs->NL_GetBuffer(myLen, &myBuffer, pBufHandle);
if (rc)
{
/********************************************************************/
/* Adjust buffer pointer to account for SL header */
/********************************************************************/
*ppBuffer = myBuffer + headerLen;
// Since FIPS need extra block, fill in the padding size
if (_SL.encryptionMethodSelected == SM_FIPS_ENCRYPTION_FLAG) {
pSecHeader2 = (PRNS_SECURITY_HEADER2)myBuffer;
pSecHeader2->padlen = newDataLen - dataLen;
}
/********************************************************************/
/* Assert that NL has returned a correctly aligned buffer. */
/********************************************************************/
TRC_ASSERT(((ULONG_PTR)(*ppBuffer) % 4 == 2),
(TB, _T("non-aligned buffer")));
}
TRC_DBG((TB, _T("Return buffer %p (was %p), rc %d"),
*ppBuffer, myBuffer, rc));
/************************************************************************/
/* Return to caller */
/************************************************************************/
DC_EXIT_POINT:
DC_END_FN();
return(rc);
} /* SL_GetBufferRtl */
/****************************************************************************/
/* Name: SL_FreeBuffer */
/* */
/* Purpose: Frees a buffer previously allocated. */
/* */
/* Params: IN pBufHandle - pointer to the buffer handle. */
/****************************************************************************/
DCVOID DCAPI CSL::SL_FreeBuffer(SL_BUFHND bufHandle)
{
DC_BEGIN_FN("SL_FreeBuffer");
/************************************************************************/
/* Just call onto the NL equivalent. */
/************************************************************************/
_pMcs->NL_FreeBuffer((NL_BUFHND) bufHandle);
DC_END_FN();
} /* SL_FreeBuffer */
/****************************************************************************/
/* Name: SL_SendSecurityPacket */
/* */
/* Purpose: Sends a security packet in the Send context */
/* */
/* Params: pData - data from Receive context (packet to send) */
/* dataLength - length of data passed */
/****************************************************************************/
DCVOID DCAPI CSL::SL_SendSecurityPacket(PDCVOID pData, DCUINT dataLength)
{
DCBOOL rc;
PDCUINT8 pBuffer;
SL_BUFHND bufHnd;
DC_BEGIN_FN("SL_SendSecurityPacket");
/************************************************************************/
/* Get a buffer from NL */
/************************************************************************/
rc = _pMcs->NL_GetBuffer(dataLength, &pBuffer, &bufHnd);
/************************************************************************/
/* We don't expect this getBuffer to fail. However, it can do so in */
/* the following scenario. */
/* - SLSendSecurityPacket decouples to SL_SendSecurityPacket. */
/* - Session is disconnected. */
/* - CD calls SL_SendSecurityPacket. */
/************************************************************************/
if (!rc)
{
TRC_ERR((TB, _T("Failed to alloc buffer for security packet, state %d"),
_SL.state));
DC_QUIT;
}
/************************************************************************/
/* Send the packet */
/************************************************************************/
DC_MEMCPY(pBuffer, pData, dataLength);
TRC_NRM((TB, _T("Send security exchange packet")));
_pMcs->NL_SendPacket(pBuffer,
dataLength,
0,
bufHnd,
_pUi->UI_GetClientMCSID(),
_SL.channelID,
TS_HIGHPRIORITY);
DC_EXIT_POINT:
DC_END_FN();
}
/****************************************************************************/
/* Name: SL_SendSecInfoPacket */
/* */
/* Purpose: Sends an rns info pkt in the Send context */
/* */
/* Params: pData - data from Receive context (packet to send) */
/* dataLength - length of data passed */
/****************************************************************************/
DCVOID DCAPI CSL::SL_SendSecInfoPacket(PDCVOID pData, DCUINT dataLen)
{
PDCUINT8 pBuffer;
SL_BUFHND BufHandle;
DCUINT headerLen, newDataLen, TotalDataLen;
PRNS_SECURITY_HEADER2 pSecHeader2;
DC_BEGIN_FN("SL_SendSecInfoPacket");
/************************************************************************/
/* Adjust requested length to account for SL header and */
/* get the buffer from NL */
/************************************************************************/
if (_SL.encrypting)
{
if (_SL.encryptionMethodSelected == SM_FIPS_ENCRYPTION_FLAG) {
// If FIPS is used,
// it must have room for an extra block
headerLen = sizeof(RNS_SECURITY_HEADER2);
newDataLen = TSCAPI_AdjustDataLen(dataLen);
TotalDataLen = newDataLen + headerLen;
}
else {
headerLen = sizeof(RNS_SECURITY_HEADER1);
TotalDataLen = dataLen + headerLen;
}
}
else {
headerLen = sizeof(RNS_SECURITY_HEADER);
TotalDataLen = dataLen + headerLen;
}
if (!_pMcs->NL_GetBuffer(TotalDataLen, &pBuffer, &BufHandle))
{
TRC_ALT((TB, _T("Failed to get SendSecInfoPacket buffer")));
DC_QUIT;
}
// Since FIPS need extra block, fill in the padding size
if (_SL.encryptionMethodSelected == SM_FIPS_ENCRYPTION_FLAG) {
pSecHeader2 = (PRNS_SECURITY_HEADER2)pBuffer;
pSecHeader2->padlen = newDataLen - dataLen;
}
/********************************************************************/
/* Adjust buffer pointer to account for SL header */
/********************************************************************/
pBuffer += headerLen;
DC_MEMCPY(pBuffer, pData, dataLen);
SL_SendPacket(pBuffer,
dataLen,
RNS_SEC_ENCRYPT | RNS_SEC_INFO_PKT,
BufHandle,
_pUi->UI_GetClientMCSID(),
_SL.channelID,
TS_HIGHPRIORITY);
DC_EXIT_POINT:
DC_END_FN();
}
/****************************************************************************/
/* Name: SL_EnableEncryption */
/* */
/* Purpose: Enables or disables encryption */
/* */
/* Params: enableEncryption - IN - flag indicating whether encryption */
/* should be on or off */
/* 0 - disabled */
/* 1 - enabled */
/****************************************************************************/
DCVOID DCAPI CSL::SL_EnableEncryption(ULONG_PTR enableEncryption)
{
DC_BEGIN_FN("SL_EnableEncryption");
/************************************************************************/
/* @@@ ENH 13.8.97 Need to do something with this notification */
/************************************************************************/
_SL.encryptionEnabled = (DCBOOL) enableEncryption;
DC_END_FN();
} /* SL_EnableEncryption */
//
// SL_DropLinkImmediate
//
// Purpose: Immediately drops the link without doing a gracefull connection
// shutdown (i.e. no DPUm is sent and we don't transition to the SND
// thread at any point before dropping the link). Higher level components
// will still get all the usual disconnect notifications so they can
// be properly torn down.
//
// This call was added to trigger an immediate disconnect in cases
// where we detect invalid data that could be due to an attack, it
// ensures we won't receive any more data after the call returns
//
// Params: reason - SL disconnect reason code
//
// Returns: HRESULT
//
// Thread context: Call on RCV thread
//
HRESULT
CSL::SL_DropLinkImmediate(UINT reason)
{
HRESULT hr = E_FAIL;
DC_BEGIN_FN("SL_DropLinkImmediate");
TRC_NRM((TB, _T("Setting disconnect error code from %u->%u"),
_SL.disconnectErrorCode,
SL_MAKE_DISCONNECT_ERR(reason)));
// Check that the disconnectErrorCode has not already been set and then
// set it.
if (0 != _SL.disconnectErrorCode) {
TRC_ERR((TB, _T("Disconnect error code has already been set! Was %u"),
_SL.disconnectErrorCode));
}
_SL.disconnectErrorCode = SL_MAKE_DISCONNECT_ERR(reason);
TRC_ALT((TB,_T("Triggering immediate drop link")));
_pTd->TD_DropLink();
hr = S_OK;
DC_END_FN();
return hr;
}