/**MOD+**********************************************************************/ /* Header: CLicense.cpp */ /* */ /* Purpose: Client License Manager implementation */ /* */ /* Copyright(C) Microsoft Corporation 1997-1999 */ /* */ /****************************************************************************/ #include extern "C" { #include #define TRC_GROUP TRC_GROUP_SECURITY #define TRC_FILE "clicense" #include #ifdef ENFORCE_LICENSE #include "license.h" #include "cryptkey.h" #include "hccontxt.h" #endif //ENFORCE_LICENSE } #include "clicense.h" #include "autil.h" #include "wui.h" #include "sl.h" /****************************************************************************/ /* License Handle Data */ /****************************************************************************/ typedef struct tagCLICENSE_DATA { int ANumber; } CLICENSE_DATA, * PCLICENSE_DATA; /****************************************************************************/ /* Define our memory alloc function */ /****************************************************************************/ #define MemoryAlloc(x) LocalAlloc(LMEM_FIXED, x) #define MemoryFree(x) LocalFree(x) CLic::CLic(CObjs* objs) { _pClientObjects = objs; } CLic::~CLic() { } /**PROC+*********************************************************************/ /* Name: CLicenseInit */ /* */ /* Purpose: Initialize ClientLicense Manager */ /* */ /* Returns: Handle to be passed to subsequent License Manager functions */ /* */ /* Params: None */ /* */ /* Operation: LicenseInit is called during Client initialization. Its */ /* purpose is to allow one-time initialization. It returns a */ /* handle which is subsequently passed to all License Manager */ /* functions. A typical use for this handle is as a pointer to */ /* memory containing per-instance data. */ /* */ /**PROC-*********************************************************************/ int CALL_TYPE CLic::CLicenseInit( HANDLE FAR * phContext ) { int nResult = LICENSE_OK; LICENSE_STATUS Status; DC_BEGIN_FN( "CLicenseInit" ); _pUt = _pClientObjects->_pUtObject; _pSl = _pClientObjects->_pSlObject; _pMcs = _pClientObjects->_pMCSObject; _pUi = _pClientObjects->_pUiObject; //Set only if server capability specifies it _fEncryptLicensePackets = FALSE; TRC_NRM( ( TB, _T("ClicenseInit Called\n") ) ); if( _pSl->_SL.encrypting ) { // // Security exchange has already taken place, so we do not // have to do the server authentication again. // Status = LicenseInitializeContext( phContext, LICENSE_CONTEXT_NO_SERVER_AUTHENTICATION ); if( LICENSE_STATUS_OK != Status ) { TRC_ERR( ( TB, _T("Error Initializing License Context: %d\n"), Status ) ); nResult = LICENSE_ERROR; } // // Keep track of the proprietory certificate or the public key that the // server has sent to us. // if( _pSl->_SL.pServerCert ) { Status = LicenseSetCertificate( *phContext, _pSl->_SL.pServerCert ); if( LICENSE_STATUS_OK != Status ) { TRC_ERR( ( TB, _T("Error setting server certificate: %d\n"), Status ) ); nResult = LICENSE_ERROR; } } else if( _pSl->_SL.pbServerPubKey ) { Status = LicenseSetPublicKey( *phContext, _pSl->_SL.cbServerPubKey, _pSl->_SL.pbServerPubKey ); if( LICENSE_STATUS_OK != Status ) { TRC_ERR( ( TB, _T("Error setting server public key: %d\n"), Status ) ); nResult = LICENSE_ERROR; } } else { TRC_ERR( ( TB, _T("Error: no server certificate or public key after security exchange\n") ) ); nResult = LICENSE_ERROR; } } else { Status = LicenseInitializeContext( phContext, 0 ); if( LICENSE_STATUS_OK != Status ) { TRC_ERR( ( TB, _T("Error Initializing License Context: %d\n"), Status ) ); nResult = LICENSE_ERROR; } } DC_END_FN(); return( nResult ); } /**PROC+*********************************************************************/ /* Name: CLicenseData */ /* */ /* Purpose: Handle license data received from the Server */ /* */ /* Returns: LICENSE_OK - License negotiation is complete */ /* LICENSE_CONTINUE - License negotiation will continue */ /* */ /* Params: pHandle - handle returned by LicenseInit */ /* pData - data received from Server */ /* dataLen - length of data received */ /* */ /* Operation: This function is passed all license packets received from the */ /* Server. It should parse the packet and respond (by calling */ /* suitable SL functions - see aslapi.h) as required. */ /* */ /* If license negotiation is complete, this function must return */ /* LICENSE_OK */ /* If license negotiation is not yet complete, return */ /* LICENSE_CONTINUE */ /* */ /* Incoming packets from the Client will continue to be */ /* interpreted as license packets until this function returns */ /* LICENSE_OK. */ /* */ /**PROC-*********************************************************************/ int CALL_TYPE CLic::CLicenseData( HANDLE hContext, LPVOID pData, DWORD dwDataLen, UINT32 *puiExtendedErrorInfo) { SL_BUFHND bufHandle; DWORD dwBufLen; DWORD dwHeaderLen, dwTotalLen, newDataLen; BYTE FAR * pbBuffer; LICENSE_STATUS lsReturn = LICENSE_STATUS_OK; PRNS_SECURITY_HEADER2 pSecHeader2; DC_BEGIN_FN("CLicenseData"); TRC_NRM((TB, _T("CLicenseData Called\n"))); TRC_NRM((TB, _T("CLicenseData called, length = %ld"), dwDataLen)); lsReturn = LicenseAcceptContext( hContext, puiExtendedErrorInfo, (BYTE FAR *)pData, dwDataLen, NULL, &dwBufLen); if( lsReturn == LICENSE_STATUS_OK) { TRC_NRM((TB, _T("License verification succeeded\n"))); DC_END_FN(); return LICENSE_OK; } if(lsReturn != LICENSE_STATUS_CONTINUE) { TRC_ERR((TB, _T("Error %d during license verification.\n"), lsReturn)); DC_END_FN(); return LICENSE_ERROR; } /************************************************************************/ /* Adjust requested length to account for SL header and */ /* get the buffer from NL */ /************************************************************************/ if (_pSl->_SL.encrypting) { if (_pSl->_SL.encryptionMethodSelected == SM_FIPS_ENCRYPTION_FLAG) { // If FIPS is used, // it must have room for an extra block dwHeaderLen = sizeof(RNS_SECURITY_HEADER2); newDataLen = TSCAPI_AdjustDataLen(dwBufLen); dwTotalLen = newDataLen + dwHeaderLen; } else { dwHeaderLen = sizeof(RNS_SECURITY_HEADER1); dwTotalLen = dwBufLen + dwHeaderLen; } TRC_DBG((TB, _T("Ask NL for %d (was %d) bytes"), dwTotalLen, dwBufLen)); } else { dwHeaderLen = sizeof(RNS_SECURITY_HEADER); dwTotalLen = dwBufLen + dwHeaderLen; TRC_DBG((TB, _T("Not encrypting, ask NL for %d bytes"), dwTotalLen)); } if( !_pMcs->NL_GetBuffer((DCUINT)(dwTotalLen), (PPDCUINT8)&pbBuffer, &bufHandle) ) { /********************************************************************/ /* Buffer not available so can't send, try later. */ /********************************************************************/ TRC_ALT((TB, _T("Failed to get buffer for licensing data\n"))); DC_END_FN(); return LICENSE_ERROR; } // Since FIPS need extra block, fill in the padding size if (_pSl->_SL.encryptionMethodSelected == SM_FIPS_ENCRYPTION_FLAG) { pSecHeader2 = (PRNS_SECURITY_HEADER2)pbBuffer; pSecHeader2->padlen = (TSUINT8)(newDataLen - dwBufLen); } /********************************************************************/ /* Adjust buffer pointer to account for SL header */ /********************************************************************/ pbBuffer += dwHeaderLen; lsReturn = LicenseAcceptContext(hContext, 0, (BYTE FAR *)pData, dwDataLen, pbBuffer, &dwBufLen); if( lsReturn != LICENSE_STATUS_CONTINUE ) { TRC_ERR((TB, _T("Error %d during license verification.\n"), lsReturn)); DC_END_FN(); return LICENSE_ERROR; } if(dwBufLen >0) { // // Now send the data // _pSl->SL_SendPacket( pbBuffer, (DCUINT)(dwBufLen), RNS_SEC_LICENSE_PKT | (_fEncryptLicensePackets ? RNS_SEC_ENCRYPT : 0 ), bufHandle, _pUi->UI_GetClientMCSID(), _pUi->UI_GetChannelID(), TS_LOWPRIORITY ); TRC_NRM((TB, _T("Sending license verification data, length = %ld"), dwBufLen)); TRC_NRM((TB, _T("Send License Verification data.\n"))); DC_END_FN(); DC_END_FN(); return LICENSE_CONTINUE; } DC_END_FN(); return(LICENSE_OK); } /**PROC+*********************************************************************/ /* Name: CLicenseTerm */ /* */ /* Purpose: Terminate Client License Manager */ /* */ /* Returns: None */ /* */ /* Params: pHandle - handle returned from LicenseInit */ /* */ /* Operation: This function is provided to do one-time termination of the */ /* License Manager. For example, if pHandle points to per- */ /* instance memory, this would be a good place to free it. */ /* */ /* Note that CLicenseTerm is called if CLicenseInit fails, hence */ /* it can be called with a NULL pHandle. */ /* */ /**PROC-*********************************************************************/ int CALL_TYPE CLic::CLicenseTerm( HANDLE hContext ) { LICENSE_STATUS lsReturn = LICENSE_STATUS_OK; DC_BEGIN_FN("CLicenseTerm"); TRC_NRM((TB, _T("CLicenseTerm called.\n"))); if( LICENSE_STATUS_OK != ( lsReturn = LicenseDeleteContext(hContext) ) ) { TRC_ERR((TB, _T("Error %d while deleting license context.\n"), lsReturn)); DC_END_FN(); return LICENSE_ERROR; } DC_END_FN(); return LICENSE_OK; }