windows-nt/Source/XPSP1/NT/termsrv/license/tlserver/server/tlsrpc.cpp
2020-09-26 16:20:57 +08:00

7585 lines
207 KiB
C++

//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996-1996
//
// File: tlsrpc.c
//
// Contents: Various RPC function to accept client request
//
// History: 12-09-98 HueiWang Created
//
//---------------------------------------------------------------------------
#include "pch.cpp"
#include "server.h"
#include "gencert.h"
#include "kp.h"
#include "keypack.h"
#include "clilic.h"
#include "postjob.h"
#include "srvlist.h"
#include "utils.h"
#include "misc.h"
#include "licreq.h"
#include "conlic.h"
#include "globals.h"
#include "db.h"
#include "tlscert.h"
#include "permlic.h"
#include "remotedb.h"
CCMutex g_AdminLock;
CCMutex g_RpcLock;
CCEvent g_ServerShutDown(TRUE, FALSE);
BOOL
VerifyLicenseRequest(
PTLSLICENSEREQUEST pLicenseRequest
)
/*++
--*/
{
BOOL bValid = FALSE;
if(pLicenseRequest == NULL)
{
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("VerifyLicenseRequest() invalid input\n")
);
goto cleanup;
}
if( pLicenseRequest->cbEncryptedHwid == 0 ||
pLicenseRequest->pbEncryptedHwid == NULL)
{
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("VerifyLicenseRequest() invalid HWID\n")
);
goto cleanup;
}
if( pLicenseRequest->ProductInfo.cbCompanyName == 0 ||
pLicenseRequest->ProductInfo.pbCompanyName == NULL )
{
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("VerifyLicenseRequest() invalid company name\n")
);
goto cleanup;
}
if( pLicenseRequest->ProductInfo.cbProductID == 0 ||
pLicenseRequest->ProductInfo.pbProductID == NULL )
{
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("VerifyLicenseRequest() invalid product id\n")
);
goto cleanup;
}
bValid = TRUE;
cleanup:
return bValid;
}
/////////////////////////////////////////////////////////////////////////////
BOOL
WaitForMyTurnOrShutdown(
HANDLE hHandle,
DWORD dwWaitTime
)
/*
*/
{
//
// Shutdown event is first one in the wait list
// reason is when service thread signal shutdow, at the same time,
// there might be a RPC call entering WaitForMultipleObjects() call and
// it will return WAIT_OBJECT_0 and continue on, this is not desirable
// since we want it to return can't get handle and exit RPC call immediately
//
HANDLE waitHandles[2]={g_ServerShutDown.hEvent, hHandle};
DWORD dwStatus;
//
// Could be return shutting down...
//
dwStatus=WaitForMultipleObjects(
sizeof(waitHandles)/sizeof(waitHandles[0]),
waitHandles,
FALSE,
dwWaitTime
);
return (dwStatus == WAIT_OBJECT_0 + 1) || (dwStatus == WAIT_ABANDONED_0 + 1);
}
//////////////////////////////////////////////////////
HANDLE
GetServiceShutdownHandle()
{
return g_ServerShutDown.hEvent;
}
void
ServiceSignalShutdown()
{
g_ServerShutDown.SetEvent();
}
void
ServiceResetShutdownEvent()
{
g_ServerShutDown.ResetEvent();
}
BOOL
IsServiceShuttingdown()
{
return (WaitForSingleObject(g_ServerShutDown.hEvent, 0) == WAIT_OBJECT_0);
}
//////////////////////////////////////////////////////
BOOL
AcquireRPCExclusiveLock(
IN DWORD dwWaitTime
)
/*++
Abstract:
Acquire exclusive lock for RPC interface.
Parameter:
dwWaitTime : Wait time.
Return:
TRUE/FALSE
--*/
{
return WaitForMyTurnOrShutdown(
g_RpcLock.hMutex,
dwWaitTime
);
}
//////////////////////////////////////////////////////
void
ReleaseRPCExclusiveLock()
{
g_RpcLock.Unlock();
}
//////////////////////////////////////////////////////
BOOL
AcquireAdministrativeLock(
IN DWORD dwWaitTime
)
/*++
Abstract:
Acquire lock for administrative action.
Parameter:
dwWaitTime : Time to wait for the lock.
Returns:
TRUE/FALSE.
--*/
{
return WaitForMyTurnOrShutdown(
g_AdminLock.hMutex,
dwWaitTime
);
}
//////////////////////////////////////////////////////
void
ReleaseAdministrativeLock()
/*++
--*/
{
g_AdminLock.Unlock();
}
//-----------------------------------------------------------------------
DWORD
TLSVerifyHydraCertificate(
PBYTE pHSCert,
DWORD cbHSCert
)
/*
*/
{
DWORD dwStatus;
dwStatus = TLSVerifyProprietyChainedCertificate(
g_hCryptProv,
pHSCert,
cbHSCert
);
if(dwStatus != ERROR_SUCCESS)
{
Hydra_Server_Cert hCert;
memset(&hCert, 0, sizeof(Hydra_Server_Cert));
dwStatus=UnpackHydraServerCertificate(pHSCert, cbHSCert, &hCert);
if(dwStatus == LICENSE_STATUS_OK)
{
dwStatus=LicenseVerifyServerCert(&hCert);
if(hCert.PublicKeyData.pBlob)
free(hCert.PublicKeyData.pBlob);
if(hCert.SignatureBlob.pBlob)
free(hCert.SignatureBlob.pBlob);
}
}
return dwStatus;
}
//-------------------------------------------------------------------------
//
// General RPC routines
//
void * __RPC_USER
MIDL_user_allocate(size_t size)
{
void* ptr=AllocateMemory(size);
// DBGPrintf(0xFFFFFFFF, _TEXT("Allocate 0x%08x, size %d\n"), ptr, size);
return ptr;
}
void __RPC_USER
MIDL_user_free(void *pointer)
{
FreeMemory(pointer);
}
//-------------------------------------------------------------------------
BOOL
ValidContextHandle(
IN PCONTEXT_HANDLE phContext
)
/*++
Description:
Verify client context handle.
Arguments:
phContext - client context handle return from TLSRpcConnect().
Return:
TRUE/FALSE
++*/
{
#if DBG
BOOL bValid;
LPCLIENTCONTEXT lpClientContext = (LPCLIENTCONTEXT)phContext;
bValid = (lpClientContext->m_PreDbg[0] == 0xcdcdcdcd && lpClientContext->m_PreDbg[1] == 0xcdcdcdcd &&
lpClientContext->m_PostDbg[0] == 0xcdcdcdcd && lpClientContext->m_PostDbg[1] == 0xcdcdcdcd);
if(!bValid)
{
DBGPrintf(
DBG_ERROR,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("ValidContextHandle : Bad client context\n")
);
TLSASSERT(FALSE);
}
return bValid;
#else
return TRUE;
#endif
}
//-------------------------------------------------------------------------
void
__RPC_USER PCONTEXT_HANDLE_rundown(
PCONTEXT_HANDLE phContext
)
/*++
Description:
Client context handle cleanup, called when client disconnect normally
or abnormally, see context handle rundown routine help on RPC
Argument:
phContext - client context handle.
Returns:
None
++*/
{
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("PCONTEXT_HANDLE_rundown...\n")
);
TLSASSERT(phContext != NULL);
try {
//
// If service is shutting down, exit right away without freeing up memory,
//
// Durning shutdown, RPC wait until all call completed but it does not wait
// until all open connection has 'rundown' if client is still in enumeration,
// this will cause ReleaseWorkSpace() to assert. Instead of using one more
// HANDLE to wait until all open connection has been rundown, we return right
// away to speed up shutdown time
//
if( phContext && ValidContextHandle(phContext) )
{
LPCLIENTCONTEXT lpClientContext = (LPCLIENTCONTEXT)phContext;
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("Disconnect from %s\n"),
lpClientContext->m_Client
);
assert(lpClientContext->m_RefCount == 0);
if( IsServiceShuttingdown() == FALSE )
{
switch(lpClientContext->m_ContextType)
{
case CONTEXTHANDLE_LICENSE_ENUM_TYPE:
{
PTLSDbWorkSpace pDbWkSpace = (PTLSDbWorkSpace)lpClientContext->m_ContextHandle;
if( IsValidAllocatedWorkspace(pDbWkSpace) == TRUE )
{
ReleaseWorkSpace(&pDbWkSpace);
}
}
break;
case CONTEXTHANDLE_KEYPACK_ENUM_TYPE:
{
LPENUMHANDLE hEnum=(LPENUMHANDLE)lpClientContext->m_ContextHandle;
if( IsValidAllocatedWorkspace(hEnum->pbWorkSpace) == TRUE )
{
TLSDBLicenseKeyPackEnumEnd(hEnum);
}
lpClientContext->m_ContextType = CONTEXTHANDLE_EMPTY_TYPE;
lpClientContext->m_ContextHandle=NULL;
}
break;
case CONTEXTHANDLE_HYDRA_REQUESTCERT_TYPE:
{
LPTERMSERVCERTREQHANDLE lpHandle=(LPTERMSERVCERTREQHANDLE)lpClientContext->m_ContextHandle;
midl_user_free(lpHandle->pCertRequest);
midl_user_free(lpHandle->pbChallengeData);
FreeMemory(lpHandle);
}
break;
case CONTEXTHANDLE_CHALLENGE_SERVER_TYPE:
case CONTEXTHANDLE_CHALLENGE_LRWIZ_TYPE:
case CONTEXTHANDLE_CHALLENGE_TERMSRV_TYPE:
{
PTLSCHALLENGEDATA pChallengeData = (PTLSCHALLENGEDATA) lpClientContext->m_ContextHandle;
if(pChallengeData)
{
FreeMemory(pChallengeData->pbChallengeData);
FreeMemory(pChallengeData);
}
}
}
}
else
{
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("PCONTEXT_HANDLE_rundown while shutting down...\n")
);
}
if( lpClientContext->m_Client )
{
FreeMemory(lpClientContext->m_Client);
}
midl_user_free(lpClientContext);
}
}
catch(...) {
SetLastError(TLS_E_INTERNAL);
}
return;
}
//----------------------------------------------------------------------------------
DWORD
GetClientPrivilege(
IN handle_t hRpcBinding
)
/*++
Description:
Return client's privilege level
Arguments:
hRpcBinding - Client's RPC binding handle.
Return:
Client's privilege level
++*/
{
DWORD dwStatus = CLIENT_ACCESS_USER;
BOOL bAdmin=FALSE;
RPC_STATUS rpc_status;
// If a value of zero is specified, the server impersonates the client that
// is being served by this server thread
rpc_status = RpcImpersonateClient(hRpcBinding);
if(rpc_status == RPC_S_OK)
{
IsAdmin(&bAdmin);
dwStatus = (bAdmin) ? CLIENT_ACCESS_ADMIN : CLIENT_ACCESS_USER;
RpcRevertToSelfEx(hRpcBinding);
}
return dwStatus;
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcConnect(
/* [in] */ handle_t binding,
/* [out] */ PCONTEXT_HANDLE __RPC_FAR *pphContext
)
/*++
Description:
Connect client and allocate/return client context handle.
Arguments:
hRPCBinding - RPC binding handle
pphContext - client context handle.
Returns via dwErrCode.
RPC_S_ACCESS_DENIED or LSERVER_S_SUCCESS.
++*/
{
DWORD status=ERROR_SUCCESS;
DWORD dwPriv;
RPC_BINDING_HANDLE hClient=NULL;
WCHAR * pszRpcStrBinding=NULL;
LPTSTR pszClient=NULL;
if(RpcBindingServerFromClient(binding, &hClient) == RPC_S_OK)
{
status = RpcBindingToStringBinding( hClient, &pszRpcStrBinding );
RpcBindingFree(&hClient);
if (status != RPC_S_OK)
{
goto cleanup;
}
}
//
// need to load from resource file
//
pszClient = (LPTSTR)AllocateMemory(
(_tcslen((pszRpcStrBinding) ? pszRpcStrBinding : _TEXT("Unknown")) + 1) * sizeof(TCHAR)
);
if(pszClient == NULL)
{
status = ERROR_OUTOFMEMORY;
goto cleanup;
}
_tcscpy(pszClient,
(pszRpcStrBinding) ? pszRpcStrBinding : _TEXT("Unknown")
);
if(pszRpcStrBinding)
{
RpcStringFree(&pszRpcStrBinding);
}
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("Connect from client %s\n"),
pszClient
);
dwPriv=GetClientPrivilege(binding);
LPCLIENTCONTEXT lpContext;
lpContext=(LPCLIENTCONTEXT)midl_user_allocate(sizeof(CLIENTCONTEXT));
if(lpContext == NULL)
{
status = ERROR_OUTOFMEMORY;
goto cleanup;
}
#if DBG
lpContext->m_LastCall = RPC_CALL_CONNECT;
lpContext->m_PreDbg[0] = 0xcdcdcdcd;
lpContext->m_PreDbg[1] = 0xcdcdcdcd;
lpContext->m_PostDbg[0] = 0xcdcdcdcd;
lpContext->m_PostDbg[1] = 0xcdcdcdcd;
#endif
lpContext->m_Client = pszClient;
lpContext->m_RefCount = 0;
*pphContext=lpContext;
lpContext->m_ContextType = CONTEXTHANDLE_EMPTY_TYPE;
lpContext->m_ClientFlags = dwPriv;
cleanup:
if(status != ERROR_SUCCESS)
{
FreeMemory(pszClient);
}
return TLSMapReturnCode(status);
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcDisconnect(
/* [out][in] */ PPCONTEXT_HANDLE pphContext
)
/*++
Description:
Disconnect client and FreeMemory all memory allocated on the behalf of client
Arguments:
pphContext - pointer to client context handle
Returns:
LSERVER_S_SUCCESS or ERROR_INVALID_HANDLE
++*/
{
DWORD Status=ERROR_SUCCESS;
try {
if(!ValidContextHandle(*pphContext) || *pphContext == NULL)
{
Status = ERROR_INVALID_HANDLE;
}
else
{
PCONTEXT_HANDLE_rundown(*pphContext);
*pphContext = NULL;
}
}
catch(...) {
Status = TLS_E_INTERNAL;
}
return TLSMapReturnCode(Status);
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcGetVersion(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [ref][out][in] */ PDWORD pdwVersion
)
/*++
++*/
{
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
InterlockedIncrement( &lpContext->m_RefCount );
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcGetVersion\n"),
lpContext->m_Client
);
if(TLSIsBetaNTServer() == TRUE)
{
*pdwVersion = TLS_CURRENT_VERSION;
}
else
{
*pdwVersion = TLS_CURRENT_VERSION_RTM;
}
if(g_SrvRole & TLSERVER_ENTERPRISE_SERVER)
{
*pdwVersion |= TLS_VERSION_ENTERPRISE_BIT;
}
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_DETAILSIMPLE,
_TEXT("%s : TLSRpcGetVersion return 0x%08x\n"),
lpContext->m_Client,
*pdwVersion
);
InterlockedDecrement( &lpContext->m_RefCount );
return RPC_S_OK;
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcGetSupportFlags(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [ref][out] */ DWORD *pdwSupportFlags
)
/*++
++*/
{
error_status_t status = RPC_S_OK;
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
InterlockedIncrement( &lpContext->m_RefCount );
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcGetSupportFlags\n"),
lpContext->m_Client
);
if (NULL != pdwSupportFlags)
{
*pdwSupportFlags = ALL_KNOWN_SUPPORT_FLAGS;
}
else
{
status = ERROR_INVALID_PARAMETER;
}
InterlockedDecrement( &lpContext->m_RefCount );
return status;
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcSendServerCertificate(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ DWORD cbCert,
/* [size_is][in] */ PBYTE pbCert,
/* [ref][out][in] */ PDWORD dwErrCode
)
/*++
Description:
This routine is for License Server to identify hydra server, hydra server
need to send its certificate in order to gain certificate request privilege.
Arguments:
phContext - client context handle.
cbCert - size of hydra server certificate.
pbCert - hydra server's self-created certificate.
dwErrCode - return code.
Returns via dwErrCode
LSERVER_E_INVALID_DATA.
++*/
{
DWORD status=ERROR_SUCCESS;
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
InterlockedIncrement( &lpContext->m_RefCount );
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcSendServerCertificate\n"),
lpContext->m_Client
);
try {
if(pbCert == NULL || cbCert == 0 ||
TLSVerifyHydraCertificate(pbCert, cbCert) != LICENSE_STATUS_OK)
{
DBGPrintf(
DBG_WARNING,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_DETAILSIMPLE,
_TEXT("TLSRpcSendServerCertificate : client %s send invalid certificate\n"),
lpContext->m_Client
);
status = TLS_E_INVALID_DATA;
}
else
{
lpContext->m_ClientFlags |= CLIENT_ACCESS_REQUEST;
}
}
catch(...) {
status = TLS_E_INVALID_DATA;
}
// midl_user_free(pbCert);
lpContext->m_LastError=status;
InterlockedDecrement( &lpContext->m_RefCount );
#if DBG
lpContext->m_LastCall = RPC_CALL_SEND_CERTIFICATE;
#endif
*dwErrCode = TLSMapReturnCode(status);
return RPC_S_OK;
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcGetServerName(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [size_is][string][out][in] */ LPTSTR szMachineName,
/* [out][in] */ PDWORD cbSize,
/* [ref][out][in] */ PDWORD dwErrCode
)
/*++
Description:
Return server's machine name.
Arguments:
phContext - Client context handle
szMachineName - return server's machine name, must be at least
MAX_COMPUTERNAME_LENGTH + 1 in length
Return:
TLS_E_INVALID_DATA - buffer size too small.
++*/
{
// TODO: no need for this buffer - use caller's buffer instead
TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH+2];
DWORD dwBufferSize=MAX_COMPUTERNAME_LENGTH+1;
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcGetServerName\n"),
lpContext->m_Client
);
if(lpContext->m_ContextType != CONTEXTHANDLE_CHALLENGE_SERVER_TYPE)
{
*dwErrCode = TLSMapReturnCode(TLS_E_INVALID_DATA);
return RPC_S_OK;
}
*dwErrCode = ERROR_SUCCESS;
if(!GetComputerName(szComputerName, &dwBufferSize))
{
*dwErrCode = GetLastError();
}
//
// return buffer must be big enough for NULL,
// dwBufferSize return does not include NULL.
//
if(*cbSize <= dwBufferSize)
{
DBGPrintf(
DBG_WARNING,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_DETAILSIMPLE,
_TEXT("TLSRpcGetServerName : Client %s invalid parameter\n"),
lpContext->m_Client
);
*dwErrCode = TLSMapReturnCode(TLS_E_INVALID_DATA);
}
else
{
_tcsncpy(szMachineName, szComputerName, min(_tcslen(szComputerName), *cbSize));
szMachineName[min(_tcslen(szComputerName), *cbSize - 1)] = _TEXT('\0');
}
*cbSize = _tcslen(szComputerName) + 1; // include NULL terminate string
#if DBG
lpContext->m_LastCall = RPC_CALL_GET_SERVERNAME;
#endif
return RPC_S_OK;
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcGetServerNameEx(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [size_is][string][out][in] */ LPTSTR szMachineName,
/* [out][in] */ PDWORD cbSize,
/* [ref][out][in] */ PDWORD dwErrCode
)
/*++
Description:
Return server's machine name.
Arguments:
phContext - Client context handle
szMachineName - return server's machine name, must be at least
MAX_COMPUTERNAME_LENGTH + 1 in length
Return:
TLS_E_INVALID_DATA - buffer size too small.
++*/
{
// TODO: no need for this buffer - use caller's buffer instead
TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH+2];
DWORD dwBufferSize=MAX_COMPUTERNAME_LENGTH+1;
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcGetServerNameEx\n"),
lpContext->m_Client
);
*dwErrCode = ERROR_SUCCESS;
if(!GetComputerName(szComputerName, &dwBufferSize))
{
*dwErrCode = GetLastError();
}
//
// return buffer must be big enough for NULL,
// dwBufferSize return does not include NULL.
//
if(*cbSize <= dwBufferSize)
{
DBGPrintf(
DBG_WARNING,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_DETAILSIMPLE,
_TEXT("TLSRpcGetServerNameEx : Client %s invalid parameter\n"),
lpContext->m_Client
);
*dwErrCode = TLSMapReturnCode(TLS_E_INVALID_DATA);
}
else
{
_tcsncpy(szMachineName, szComputerName, min(_tcslen(szComputerName), *cbSize));
szMachineName[min(_tcslen(szComputerName), *cbSize - 1)] = _TEXT('\0');
}
*cbSize = _tcslen(szComputerName) + 1; // include NULL terminate string
#if DBG
lpContext->m_LastCall = RPC_CALL_GET_SERVERNAME;
#endif
return RPC_S_OK;
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcGetServerScope(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [size_is][string][out][in] */ LPTSTR szScopeName,
/* [out][in] */ PDWORD cbSize,
/* [ref][out][in] */ PDWORD dwErrCode
)
/*++
Description:
Return License Server's scope
Arguments:
phContext - Client context
szScopeName - return server's scope, must be at least
MAX_COMPUTERNAME_LENGTH in length
Return:
LSERVER_S_SUCCESS or error code from WideCharToMultiByte()
TLS_E_INVALID_DATA - buffer size too small.
++*/
{
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcGetServerScope\n"),
lpContext->m_Client
);
*dwErrCode = ERROR_SUCCESS;
if(*cbSize <= _tcslen(g_pszScope))
{
*dwErrCode = TLSMapReturnCode(TLS_E_INVALID_DATA);
}
else
{
_tcsncpy(szScopeName, g_pszScope, min(_tcslen(g_pszScope), *cbSize));
szScopeName[min(_tcslen(g_pszScope), *cbSize-1)] = _TEXT('\0');
}
*cbSize = _tcslen(g_pszScope) + 1; // include NULL terminate string
#if DBG
lpContext->m_LastCall = RPC_CALL_GET_SERVERSCOPE;
#endif
return RPC_S_OK;
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcGetInfo(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ DWORD cbHSCert,
/* [size_is][in] */ PBYTE pHSCert,
/* [ref][out] */ DWORD __RPC_FAR *pcbLSCert,
/* [size_is][size_is][out] */ BYTE __RPC_FAR *__RPC_FAR *pLSCert,
/* [ref][out] */ DWORD __RPC_FAR *pcbLSSecretKey,
/* [size_is][size_is][out] */ BYTE __RPC_FAR *__RPC_FAR *pLSSecretKey,
/* [ref][out][in] */ PDWORD dwErrCode
)
/*++
Description:
Routine to exchange Hydra server's certificate and License server's
certificate/private key for signing client machine's hardware ID.
Arguments:
phContext - client context handle
cbHSCert - size of Hydra Server's certificate
pHSCert - Hydra Server's certificate
pcbLSCert - return size of License Server's certificate
pLSCert - return License Server's certificate
pcbLSSecretKey - return size of License Server's private key.
pLSSecretKey - retrun License Server's private key
Return Value:
LSERVER_S_SUCCESS success
LSERVER_E_INVALID_DATA Invalid hydra server certificate
LSERVER_E_OUTOFMEMORY Can't allocate required memory
TLS_E_INTERNAL Internal error occurred in License Server
++*/
{
DWORD status=ERROR_SUCCESS;
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcGetInfo\n"),
lpContext->m_Client
);
try {
do {
if( pHSCert == NULL || cbHSCert == 0 ||
TLSVerifyHydraCertificate(pHSCert, cbHSCert) != LICENSE_STATUS_OK)
{
status= TLS_E_INVALID_DATA;
break;
}
*pcbLSCert = g_cbSignatureEncodedCert;
*pLSCert = (PBYTE)midl_user_allocate(*pcbLSCert);
if(!*pLSCert)
{
status = ERROR_OUTOFMEMORY;
break;
}
memcpy(*pLSCert, (PBYTE)g_pbSignatureEncodedCert, *pcbLSCert);
*pcbLSSecretKey=0;
*pLSSecretKey=NULL;
} while(FALSE);
if(status != ERROR_SUCCESS)
{
if(*pLSCert)
midl_user_free(*pLSCert);
if(*pLSSecretKey)
midl_user_free(*pLSSecretKey);
*pcbLSCert=0;
*pcbLSSecretKey=0;
*pLSCert=NULL;
*pLSSecretKey=NULL;
}
}
catch(...) {
status = TLS_E_INTERNAL;
}
// midl_user_free(pHSCert);
#if DBG
lpContext->m_LastCall = RPC_CALL_GETINFO;
#endif
lpContext->m_LastError = status;
*dwErrCode = TLSMapReturnCode(status);
return RPC_S_OK;
}
//-------------------------------------------------------------------------------
#define RANDOM_CHALLENGE_DATA _TEXT("TEST")
DWORD
TLSGenerateChallengeData(
IN DWORD ClientInfo,
OUT PDWORD pcbChallengeData,
IN OUT PBYTE* pChallengeData
)
{
DWORD hr=ERROR_SUCCESS;
*pcbChallengeData = (_tcslen(RANDOM_CHALLENGE_DATA) + 1) * sizeof(WCHAR);
*pChallengeData=(PBYTE)midl_user_allocate(*pcbChallengeData);
if(*pChallengeData)
{
memcpy(*pChallengeData, RANDOM_CHALLENGE_DATA, *pcbChallengeData);
}
else
{
SetLastError(hr=ERROR_OUTOFMEMORY);
}
return hr;
}
//++----------------------------------------------------------------------------
DWORD
TLSVerifyChallengeDataGetWantedLicenseLevel(
IN const CHALLENGE_CONTEXT ChallengeContext,
IN const DWORD cbChallengeData,
IN const PBYTE pbChallengeData,
OUT WORD* pwLicenseDetail
)
/*++
--*/
{
DWORD dwStatus = ERROR_SUCCESS;
DWORD dwChallengeDataSize = (_tcslen(RANDOM_CHALLENGE_DATA) + 1) * sizeof(WCHAR);
PPlatformChallengeResponseData pChallengeResponse;
if( cbChallengeData < dwChallengeDataSize || pbChallengeData == NULL )
{
//
// Assume old client, new client always send back our challenge data
//
*pwLicenseDetail = LICENSE_DETAIL_SIMPLE;
}
else if( cbChallengeData == dwChallengeDataSize &&
_tcsicmp( (LPCTSTR)pbChallengeData, RANDOM_CHALLENGE_DATA ) == 0 )
{
//
// old client, set license chain to LICENSE_DETAIL_SIMPLE
//
*pwLicenseDetail = LICENSE_DETAIL_SIMPLE;
}
else
{
BOOL bValidStruct = TRUE;
//
// we still don't have a good challenge so ignore actual verification
//
pChallengeResponse = (PPlatformChallengeResponseData) pbChallengeData;
bValidStruct = (pChallengeResponse->wVersion == CURRENT_PLATFORMCHALLENGE_VERSION);
if( bValidStruct == TRUE )
{
bValidStruct = (pChallengeResponse->cbChallenge + offsetof(PlatformChallengeResponseData, pbChallenge) == cbChallengeData);
}
if (bValidStruct == TRUE )
{
if( pChallengeResponse->wClientType == WIN32_PLATFORMCHALLENGE_TYPE ||
pChallengeResponse->wClientType == WIN16_PLATFORMCHALLENGE_TYPE ||
pChallengeResponse->wClientType == WINCE_PLATFORMCHALLENGE_TYPE ||
pChallengeResponse->wClientType == OTHER_PLATFORMCHALLENGE_TYPE )
{
bValidStruct = TRUE;
}
else
{
bValidStruct = FALSE;
}
}
if( bValidStruct == TRUE )
{
if( pChallengeResponse->wLicenseDetailLevel == LICENSE_DETAIL_SIMPLE ||
pChallengeResponse->wLicenseDetailLevel == LICENSE_DETAIL_MODERATE ||
pChallengeResponse->wLicenseDetailLevel == LICENSE_DETAIL_DETAIL )
{
bValidStruct = TRUE;
}
else
{
bValidStruct = FALSE;
}
}
//
// For now, we simply let it go thru, assert or deny request once
// we settle down of challenge
//
if( bValidStruct == FALSE )
{
// bad data, assume old client
*pwLicenseDetail = LICENSE_DETAIL_SIMPLE;
}
//else if( pChallengeResponse->wClientType == WINCE_PLATFORMCHALLENGE_TYPE )
//{
//
// UN-comment this to limit WINCE to get a self-signed certificate
//
// *pwLicenseDetail = LICENSE_DETAIL_SIMPLE;
//}
else
{
*pwLicenseDetail = pChallengeResponse->wLicenseDetailLevel;
}
}
return dwStatus;
}
//++----------------------------------------------------------------------------
error_status_t
TLSRpcIssuePlatformChallenge(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ DWORD dwClientInfo,
/* [ref][out] */ PCHALLENGE_CONTEXT pChallengeContext,
/* [out] */ PDWORD pcbChallengeData,
/* [size_is][size_is][out] */ BYTE __RPC_FAR *__RPC_FAR *pChallengeData,
/* [ref][out][in] */ PDWORD dwErrCode
)
/*++
Description:
Issue a platform challenge to hydra client.
Arguments:
phContext - client context handle
dwClientInfo - client info.
pChallengeContext - pointer to client challenge context.
pcbChallengeData - size of challenge data.
pChallengeData - random client challenge data.
Returns via dwErrCode:
LSERVER_S_SUCCESS
LSERVER_E_OUTOFMEMORY Out of memory
LSERVER_E_INVALID_DATA Invalid client info.
LSERVER_E_SERVER_BUSY Server is busy
++*/
{
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
LPCLIENTCHALLENGECONTEXT lpChallenge=NULL;
DWORD status=ERROR_SUCCESS;
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcIssuePlatformChallenge\n"),
lpContext->m_Client
);
InterlockedIncrement( &lpContext->m_RefCount );
try {
do {
status=TLSGenerateChallengeData(
dwClientInfo,
pcbChallengeData,
pChallengeData
);
if(status != ERROR_SUCCESS)
{
break;
}
*pChallengeContext = dwClientInfo;
} while (FALSE);
if(status != ERROR_SUCCESS)
{
if(*pChallengeData)
{
midl_user_free(*pChallengeData);
*pChallengeData = NULL;
}
*pcbChallengeData=0;
}
}
catch(...) {
status = TLS_E_INTERNAL;
}
lpContext->m_LastError=status;
#if DBG
lpContext->m_LastCall = RPC_CALL_ISSUEPLATFORMCHLLENGE;
#endif
InterlockedDecrement( &lpContext->m_RefCount );
*dwErrCode = TLSMapReturnCode(status);
return RPC_S_OK;
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcRequestNewLicense(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ const CHALLENGE_CONTEXT ChallengeContext,
/* [in] */ TLSLICENSEREQUEST __RPC_FAR *pRequest,
/* [string][in] */ LPTSTR szMachineName,
/* [string][in] */ LPTSTR szUserName,
/* [in] */ const DWORD cbChallengeResponse,
/* [size_is][in] */ const PBYTE pbChallenge,
/* [in] */ BOOL bAcceptTemporaryLicense,
/* [out] */ PDWORD pcbLicense,
/* [size_is][size_is][out] */ BYTE __RPC_FAR *__RPC_FAR *ppbLicense,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
Description:
Routine to issue new license to hydra client based on product requested,
it returns existing license if client already has a license and the
license is not expired/returned/revoked, if request product has not been
installed, it will issue a temporary license, if license found is temporary
or expired, it will tried to upgrade/re-issue a new license with latest
version of requested product, if the existing license is temporary and
no license can be issued, it returns LSERVER_E_LICENSE_EXPIRED
Arguments:
phContext - client context handle.
ChallengeContext - client challenge context handle, return from
call TLSRpcIssuePlatformChallenge()
pRequest - product license request.
pMachineName - client's machine name.
pUserName - client user name.
cbChallengeResponse - size of the client's response to license server's
platform challenge.
pbChallenge - client's response to license server's platform challenge
bAcceptTemporaryLicense - TRUE if client wants temp. license FALSE otherwise.
pcbLicense - size of return license.
ppLicense - return license, could be old license
Return Value:
LSERVER_S_SUCCESS
LSERVER_E_OUTOFMEMORY
LSERVER_E_SERVER_BUSY Server is busy to process request.
LSERVER_E_INVALID_DATA Invalid platform challenge response.
LSERVER_E_NO_LICENSE No license available.
LSERVER_E_NO_PRODUCT Request product is not installed on server.
LSERVER_E_LICENSE_REJECTED License request is rejected by cert. server
LSERVER_E_LICENSE_REVOKED Old license found and has been revoked
LSERVER_E_LICENSE_EXPIRED Request product's license has expired
LSERVER_E_CORRUPT_DATABASE Corrupted database.
LSERVER_E_INTERNAL_ERROR Internal error in license server
LSERVER_I_PROXIMATE_LICENSE Closest match license returned.
LSERVER_I_TEMPORARY_LICENSE Temporary license has been issued
LSERVER_I_LICENSE_UPGRADED Old license has been upgraded.
++*/
{
DWORD dwSupportFlags = 0;
return TLSRpcRequestNewLicenseEx(
phContext,
&dwSupportFlags,
ChallengeContext,
pRequest,
szMachineName,
szUserName,
cbChallengeResponse,
pbChallenge,
bAcceptTemporaryLicense,
1, // dwQuantity
pcbLicense,
ppbLicense,
pdwErrCode
);
}
error_status_t
TLSRpcRequestNewLicenseEx(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in, out] */ DWORD *pdwSupportFlags,
/* [in] */ const CHALLENGE_CONTEXT ChallengeContext,
/* [in] */ TLSLICENSEREQUEST __RPC_FAR *pRequest,
/* [string][in] */ LPTSTR szMachineName,
/* [string][in] */ LPTSTR szUserName,
/* [in] */ const DWORD cbChallengeResponse,
/* [size_is][in] */ const PBYTE pbChallenge,
/* [in] */ BOOL bAcceptTemporaryLicense,
/* [in] */ DWORD dwQuantity,
/* [out] */ PDWORD pcbLicense,
/* [size_is][size_is][out] */ BYTE __RPC_FAR *__RPC_FAR *ppbLicense,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
Description:
Routine to issue new license to hydra client based on product requested
and input support flags.
*pdwSupportFlags == 0:
it returns existing license if client already has a license and the
license is not expired/returned/revoked, if request product has not
been installed, it will issue a temporary license, if license found is
temporary or expired, it will tried to upgrade/re-issue a new license
with latest version of requested product, if the existing license is
temporary and no license can be issued, it returns
LSERVER_E_LICENSE_EXPIRED
*pdwSupportFlags & SUPPORT_PER_SEAT_POST_LOGON:
For non-per-seat licenses, it behaves as if the flag wasn't set.
For per-seat licenses, if bAcceptTemporaryLicense is TRUE, it always
returns a temporary license. If bAcceptTemporaryLicense if FALSE, it
returns LSERVER_E_NO_LICENSE.
Arguments:
phContext - client context handle.
pdwSupportFlags - on input, abilities supported by TS. on output,
abilities supported by both TS and LS
ChallengeContext - client challenge context handle, return from
call TLSRpcIssuePlatformChallenge()
pRequest - product license request.
pMachineName - client's machine name.
pUserName - client user name.
cbChallengeResponse - size of the client's response to license server's
platform challenge.
pbChallenge - client's response to license server's platform challenge
bAcceptTemporaryLicense - TRUE if client wants temp. license FALSE
otherwise.
dwQuantity - number of licenses to allocate
pcbLicense - size of return license.
ppLicense - return license, could be old license
Return Value:
LSERVER_S_SUCCESS
LSERVER_E_OUTOFMEMORY
LSERVER_E_SERVER_BUSY Server is busy to process request.
LSERVER_E_INVALID_DATA Invalid platform challenge response.
LSERVER_E_NO_LICENSE No license available.
LSERVER_E_NO_PRODUCT Request product is not installed on server.
LSERVER_E_LICENSE_REJECTED License request is rejected by cert. server
LSERVER_E_LICENSE_REVOKED Old license found and has been revoked
LSERVER_E_LICENSE_EXPIRED Request product's license has expired
LSERVER_E_CORRUPT_DATABASE Corrupted database.
LSERVER_E_INTERNAL_ERROR Internal error in license server
LSERVER_I_PROXIMATE_LICENSE Closest match license returned.
LSERVER_I_TEMPORARY_LICENSE Temporary license has been issued
LSERVER_I_LICENSE_UPGRADED Old license has been upgraded.
++*/
{
return TLSRpcRequestNewLicenseExEx(
phContext,
pdwSupportFlags,
ChallengeContext,
pRequest,
szMachineName,
szUserName,
cbChallengeResponse,
pbChallenge,
bAcceptTemporaryLicense,
FALSE, // bAcceptFewerLicense
&dwQuantity,
pcbLicense,
ppbLicense,
pdwErrCode
);
}
error_status_t
TLSRpcRequestNewLicenseExEx(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in, out] */ DWORD *pdwSupportFlags,
/* [in] */ const CHALLENGE_CONTEXT ChallengeContext,
/* [in] */ TLSLICENSEREQUEST __RPC_FAR *pRequest,
/* [string][in] */ LPTSTR szMachineName,
/* [string][in] */ LPTSTR szUserName,
/* [in] */ const DWORD cbChallengeResponse,
/* [size_is][in] */ const PBYTE pbChallenge,
/* [in] */ BOOL bAcceptTemporaryLicense,
/* [in] */ BOOL bAcceptFewerLicenses,
/* [in,out] */ DWORD *pdwQuantity,
/* [out] */ PDWORD pcbLicense,
/* [size_is][size_is][out] */ BYTE __RPC_FAR *__RPC_FAR *ppbLicense,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
Description:
Routine to issue new license to hydra client based on product requested
and input support flags.
*pdwSupportFlags == 0:
it returns existing license if client already has a license and the
license is not expired/returned/revoked, if request product has not
been installed, it will issue a temporary license, if license found is
temporary or expired, it will tried to upgrade/re-issue a new license
with latest version of requested product, if the existing license is
temporary and no license can be issued, it returns
LSERVER_E_LICENSE_EXPIRED
*pdwSupportFlags & SUPPORT_PER_SEAT_POST_LOGON:
For non-per-seat licenses, it behaves as if the flag wasn't set.
For per-seat licenses, if bAcceptTemporaryLicense is TRUE, it always
returns a temporary license. If bAcceptTemporaryLicense if FALSE, it
returns LSERVER_E_NO_LICENSE.
Arguments:
phContext - client context handle.
pdwSupportFlags - on input, abilities supported by TS. on output,
abilities supported by both TS and LS
ChallengeContext - client challenge context handle, return from
call TLSRpcIssuePlatformChallenge()
pRequest - product license request.
pMachineName - client's machine name.
pUserName - client user name.
cbChallengeResponse - size of the client's response to license server's
platform challenge.
pbChallenge - client's response to license server's platform challenge
bAcceptTemporaryLicense - TRUE if client wants temp. license FALSE
otherwise.
bAcceptFewerLicenses - TRUE if succeeding with fewer licenses than
requested is acceptable
pdwQuantity - on input, number of licenses to allocate. on output,
number of licenses actually allocated
pcbLicense - size of return license.
ppLicense - return license, could be old license
Return Value:
LSERVER_S_SUCCESS
LSERVER_E_OUTOFMEMORY
LSERVER_E_SERVER_BUSY Server is busy to process request.
LSERVER_E_INVALID_DATA Invalid platform challenge response.
LSERVER_E_NO_LICENSE No license available.
LSERVER_E_NO_PRODUCT Request product is not installed on server.
LSERVER_E_LICENSE_REJECTED License request is rejected by cert. server
LSERVER_E_LICENSE_REVOKED Old license found and has been revoked
LSERVER_E_LICENSE_EXPIRED Request product's license has expired
LSERVER_E_CORRUPT_DATABASE Corrupted database.
LSERVER_E_INTERNAL_ERROR Internal error in license server
LSERVER_I_PROXIMATE_LICENSE Closest match license returned.
LSERVER_I_TEMPORARY_LICENSE Temporary license has been issued
LSERVER_I_LICENSE_UPGRADED Old license has been upgraded.
++*/
{
PMHANDLE hClient;
DWORD status=ERROR_SUCCESS;
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
TCHAR szUnknown[LSERVER_MAX_STRING_SIZE+1];
TCHAR szClientMachineName[LSERVER_MAX_STRING_SIZE];
TCHAR szClientUserName[LSERVER_MAX_STRING_SIZE];
TCHAR szCompanyName[LSERVER_MAX_STRING_SIZE+1];
TCHAR szProductId[LSERVER_MAX_STRING_SIZE+1];
TLSForwardNewLicenseRequest Forward;
TLSDBLICENSEREQUEST LsLicenseRequest;
CTLSPolicy* pPolicy=NULL;
PMLICENSEREQUEST PMLicenseRequest;
PPMLICENSEREQUEST pAdjustedRequest;
BOOL bForwardRequest = TRUE;
_se_translator_function old_trans_se_func = NULL;
old_trans_se_func = _set_se_translator( trans_se_func );
#ifdef DBG
DWORD dwStartTime=GetTickCount();
#endif
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcRequestNewLicense\n"),
lpContext->m_Client
);
InterlockedIncrement( &lpContext->m_RefCount );
if ((NULL == pdwQuantity) || (0 == *pdwQuantity))
{
status = TLS_E_INVALID_DATA;
goto cleanup;
}
if(VerifyLicenseRequest(pRequest) == FALSE)
{
status = TLS_E_INVALID_DATA;
goto cleanup;
}
if(NULL == pdwSupportFlags)
{
status = TLS_E_INVALID_DATA;
goto cleanup;
}
*pdwSupportFlags &= ALL_KNOWN_SUPPORT_FLAGS;
if(!(lpContext->m_ClientFlags & CLIENT_ACCESS_REQUEST))
{
status = TLS_E_ACCESS_DENIED;
goto cleanup;
}
if(lpContext->m_ClientFlags == CLIENT_ACCESS_LSERVER)
{
//
// do not forward any request or infinite loop might
// occur.
//
bForwardRequest = FALSE;
}
Forward.m_ChallengeContext = ChallengeContext;
Forward.m_pRequest = pRequest;
Forward.m_szMachineName = szMachineName;
Forward.m_szUserName = szUserName;
Forward.m_cbChallengeResponse = cbChallengeResponse;
Forward.m_pbChallengeResponse = pbChallenge;
memset(szCompanyName, 0, sizeof(szCompanyName));
memset(szProductId, 0, sizeof(szProductId));
memcpy(
szCompanyName,
pRequest->ProductInfo.pbCompanyName,
min(pRequest->ProductInfo.cbCompanyName, sizeof(szCompanyName)-sizeof(TCHAR))
);
memcpy(
szProductId,
pRequest->ProductInfo.pbProductID,
min(pRequest->ProductInfo.cbProductID, sizeof(szProductId)-sizeof(TCHAR))
);
//
// Acquire policy module, a default policy module will
// be returned.
//
pPolicy = AcquirePolicyModule(
szCompanyName, //(LPCTSTR)pRequest->ProductInfo.pbCompanyName,
szProductId, //(LPCTSTR)pRequest->ProductInfo.pbProductID
FALSE
);
if(pPolicy == NULL)
{
status = TLS_E_INTERNAL;
goto cleanup;
}
hClient = GenerateClientId();
//
// return error if string is too big.
//
LoadResourceString(
IDS_UNKNOWN_STRING,
szUnknown,
sizeof(szUnknown)/sizeof(szUnknown[0])
);
_tcsncpy(szClientMachineName,
(szMachineName) ? szMachineName : szUnknown,
LSERVER_MAX_STRING_SIZE
);
szClientMachineName[LSERVER_MAX_STRING_SIZE-1] = 0;
_tcsncpy(szClientUserName,
(szUserName) ? szUserName : szUnknown,
LSERVER_MAX_STRING_SIZE
);
szClientUserName[LSERVER_MAX_STRING_SIZE-1] = 0;
//
// Convert request to PMLICENSEREQUEST
//
TlsLicenseRequestToPMLicenseRequest(
LICENSETYPE_LICENSE,
pRequest,
szClientMachineName,
szClientUserName,
*pdwSupportFlags,
&PMLicenseRequest
);
//
// Inform Policy module start of new license request
//
status = pPolicy->PMLicenseRequest(
hClient,
REQUEST_NEW,
(PVOID) &PMLicenseRequest,
(PVOID *) &pAdjustedRequest
);
if(status != ERROR_SUCCESS)
{
goto cleanup;
}
if(pAdjustedRequest != NULL)
{
if(_tcsicmp(PMLicenseRequest.pszCompanyName,pAdjustedRequest->pszCompanyName) != 0)
{
// try to steal license from other company???
TLSLogEvent(
EVENTLOG_ERROR_TYPE,
TLS_E_POLICYERROR,
status = TLS_E_POLICYMODULEERROR,
pPolicy->GetCompanyName(),
pPolicy->GetProductId()
);
goto cleanup;
}
}
else
{
pAdjustedRequest = &PMLicenseRequest;
}
//
// form DB request structure
//
status = TLSFormDBRequest(
pRequest->pbEncryptedHwid,
pRequest->cbEncryptedHwid,
pAdjustedRequest->dwProductVersion,
pAdjustedRequest->pszCompanyName,
pAdjustedRequest->pszProductId,
pAdjustedRequest->dwLanguageId,
pAdjustedRequest->dwPlatformId,
pAdjustedRequest->pszMachineName,
pAdjustedRequest->pszUserName,
&LsLicenseRequest
);
if(status != ERROR_SUCCESS)
{
goto cleanup;
}
LsLicenseRequest.pPolicy = pPolicy;
LsLicenseRequest.hClient = hClient;
LsLicenseRequest.pPolicyLicenseRequest = pAdjustedRequest;
LsLicenseRequest.pClientLicenseRequest = &PMLicenseRequest;
try {
status = TLSVerifyChallengeDataGetWantedLicenseLevel(
ChallengeContext,
cbChallengeResponse,
pbChallenge,
&LsLicenseRequest.wLicenseDetail
);
if( status == ERROR_SUCCESS )
{
status = TLSNewLicenseRequest(
bForwardRequest,
pdwSupportFlags,
&Forward,
&LsLicenseRequest,
bAcceptTemporaryLicense,
pAdjustedRequest->fTemporary,
TRUE, // bFindLostLicense
bAcceptFewerLicenses,
pdwQuantity,
pcbLicense,
ppbLicense
);
}
}
catch( SE_Exception e ) {
status = e.getSeNumber();
}
catch(...) {
status = TLS_E_INTERNAL;
}
cleanup:
lpContext->m_LastError=status;
InterlockedDecrement( &lpContext->m_RefCount );
#if DBG
lpContext->m_LastCall = RPC_CALL_ISSUENEWLICENSE;
#endif
#ifdef DBG
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_DETAILSIMPLE,
_TEXT("\t%s : TLSRpcRequestNewLicense() takes %dms\n"),
lpContext->m_Client,
GetTickCount() - dwStartTime
);
#endif
*pdwErrCode = TLSMapReturnCode(status);
if(pPolicy)
{
pPolicy->PMLicenseRequest(
hClient,
REQUEST_COMPLETE,
UlongToPtr(status),
NULL
);
ReleasePolicyModule(pPolicy);
}
//
// Reset SE translator
//
_set_se_translator(old_trans_se_func);
return RPC_S_OK;
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcUpgradeLicense(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ TLSLICENSEREQUEST __RPC_FAR *pRequest,
/* [in] */ const CHALLENGE_CONTEXT ChallengeContext,
/* [in] */ const DWORD cbChallengeResponse,
/* [size_is][in] */ const PBYTE pbChallenge,
/* [in] */ DWORD cbOldLicense,
/* [size_is][in] */ PBYTE pbOldLicense,
/* [out] */ PDWORD pcbNewLicense,
/* [size_is][size_is][out] */ PBYTE __RPC_FAR *ppbNewLicense,
/* [ref][out][in] */ PDWORD dwErrCode
)
/*++
Description:
Update an old license.
Arguments:
Return Value:
LSERVER_S_SUCCESS
TLS_E_INTERNAL
LSERVER_E_INTERNAL_ERROR
LSERVER_E_INVALID_DATA old license is invalid.
LSERVER_E_NO_LICENSE no available license
LSERVER_E_NO_PRODUCT request product not install in current server.
LSERVER_E_CORRUPT_DATABASE Corrupted database.
LSERVER_E_LICENSE_REJECTED License request rejected by cert. server.
LSERVER_E_SERVER_BUSY
++*/
{
DWORD dwSupportFlags = 0;
return TLSRpcUpgradeLicenseEx(
phContext,
&dwSupportFlags,
pRequest,
ChallengeContext,
cbChallengeResponse,
pbChallenge,
cbOldLicense,
pbOldLicense,
1, // dwQuantity
pcbNewLicense,
ppbNewLicense,
dwErrCode
);
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcUpgradeLicenseEx(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in,out] */ DWORD *pdwSupportFlags,
/* [in] */ TLSLICENSEREQUEST __RPC_FAR *pRequest,
/* [in] */ const CHALLENGE_CONTEXT ChallengeContext,
/* [in] */ const DWORD cbChallengeResponse,
/* [size_is][in] */ const PBYTE pbChallenge,
/* [in] */ DWORD cbOldLicense,
/* [size_is][in] */ PBYTE pbOldLicense,
/* [in] */ DWORD dwQuantity,
/* [out] */ PDWORD pcbNewLicense,
/* [size_is][size_is][out] */ PBYTE __RPC_FAR *ppbNewLicense,
/* [ref][out][in] */ PDWORD dwErrCode
)
/*++
Description:
Update an old license. Behavior varies depending on product requested,
the old license, and input support flags.
*pdwSupportFlags == 0:
it returns existing license if client already has a current-version
license and the license is not expired/returned/revoked. if requested
product has not been installed, it will issue a temporary license (if
the client doesn't already have one). if old license is temporary
or expired, it will try to upgrade/re-issue a new license
with latest version of requested product. if the existing license is
temporary and no license can be issued, it returns
LSERVER_E_LICENSE_EXPIRED
*pdwSupportFlags & SUPPORT_PER_SEAT_POST_LOGON:
For non-per-seat licenses, it behaves as if the flag wasn't set.
For per-seat licenses, if the old license isn't current-version
temporary, it also behaves as if the flag wasn't set.
Otherwise, it checks that the temporary license was marked as having
been authenticated. If so, it tries to issue a permanent license.
If a license can't be issued, or if he temporary license wasn't marked,
it returns the old license.
Arguments:
phContext - client context handle.
pdwSupportFlags - on input, abilities supported by TS. on output,
abilities supported by both TS and LS
pRequest - product license request.
ChallengeContext - client challenge context handle, return from
call TLSRpcIssuePlatformChallenge()
cbChallengeResponse - size of the client's response to license server's
platform challenge.
pbChallenge - client's response to license server's platform challenge
cbOldLicense - size of old license.
pbOldLicense - old license
dwQuantity - number of licenses to allocate
pcbNewLicense - size of return license.
ppbNewLicense - return license, could be old license
Return Value:
LSERVER_S_SUCCESS
TLS_E_INTERNAL
LSERVER_E_INTERNAL_ERROR
LSERVER_E_INVALID_DATA old license is invalid.
LSERVER_E_NO_LICENSE no available license
LSERVER_E_NO_PRODUCT request product not install in current server.
LSERVER_E_CORRUPT_DATABASE Corrupted database.
LSERVER_E_LICENSE_REJECTED License request rejected by cert. server.
LSERVER_E_SERVER_BUSY
++*/
{
DWORD status = ERROR_SUCCESS;
BOOL bTemporaryLicense;
PMUPGRADEREQUEST pmRequestUpgrade;
PMLICENSEREQUEST pmLicenseRequest;
PPMLICENSEREQUEST pmAdjustedRequest;
PPMLICENSEDPRODUCT ppmLicensedProduct=NULL;
DWORD dwNumLicensedProduct=0;
PLICENSEDPRODUCT pLicensedProduct=NULL;
TLSDBLICENSEREQUEST LsLicenseRequest;
PMHANDLE hClient;
CTLSPolicy* pPolicy=NULL;
DWORD dwNumPermLicense;
DWORD dwNumTempLicense;
TLSForwardUpgradeLicenseRequest Forward;
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
LICENSEDCLIENT license;
LICENSEPACK keypack;
DWORD index;
BOOL bForwardRequest = TRUE;
_se_translator_function old_trans_se_func = NULL;
old_trans_se_func = _set_se_translator( trans_se_func );
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcUpgradeLicense\n"),
lpContext->m_Client
);
InterlockedIncrement( &lpContext->m_RefCount );
if (1 != dwQuantity)
{
status = TLS_E_INVALID_DATA;
goto cleanup;
}
if(VerifyLicenseRequest(pRequest) == FALSE)
{
status = TLS_E_INVALID_DATA;
goto cleanup;
}
if(NULL == pdwSupportFlags)
{
status = TLS_E_INVALID_DATA;
goto cleanup;
}
*pdwSupportFlags &= ALL_KNOWN_SUPPORT_FLAGS;
if(!(lpContext->m_ClientFlags & CLIENT_ACCESS_REQUEST))
{
status = TLS_E_ACCESS_DENIED;
goto cleanup;
}
if(lpContext->m_ClientFlags == CLIENT_ACCESS_LSERVER)
{
//
// do not forward any request or infinite loop might
// occur.
//
bForwardRequest = FALSE;
}
//
// Convert blob to licensed product structure
//
status = LSVerifyDecodeClientLicense(
pbOldLicense,
cbOldLicense,
g_pbSecretKey,
g_cbSecretKey,
&dwNumLicensedProduct,
NULL
);
if(status != LICENSE_STATUS_OK || dwNumLicensedProduct == 0)
{
status = TLS_E_INVALID_LICENSE;
goto cleanup;
}
pLicensedProduct = (PLICENSEDPRODUCT)AllocateMemory(
dwNumLicensedProduct * sizeof(LICENSEDPRODUCT)
);
if(pLicensedProduct == NULL)
{
status = TLS_E_ALLOCATE_MEMORY;
goto cleanup;
}
status = LSVerifyDecodeClientLicense(
pbOldLicense,
cbOldLicense,
g_pbSecretKey,
g_cbSecretKey,
&dwNumLicensedProduct,
pLicensedProduct
);
if(status != LICENSE_STATUS_OK)
{
status = TLS_E_INVALID_LICENSE;
goto cleanup;
}
//
// Verify licensed product array.
//
for(index = 1; index < dwNumLicensedProduct; index++)
{
//
// licensed product array always sorted in decending order
//
//
// Product ID in original request in licensed product must
// be the same otherwise invalid license.
//
if(pLicensedProduct->cbOrgProductID != (pLicensedProduct-1)->cbOrgProductID)
{
status = TLS_E_INVALID_LICENSE;
break;
}
if( memcmp(
pLicensedProduct->pbOrgProductID,
(pLicensedProduct-1)->pbOrgProductID,
pLicensedProduct->cbOrgProductID) != 0 )
{
status = TLS_E_INVALID_LICENSE;
goto cleanup;
}
if( (pLicensedProduct->pLicensedVersion->dwFlags & LICENSED_VERSION_TEMPORARY) )
{
//
// only latest licensed version can be temporary
//
status = TLS_E_INVALID_LICENSE;
goto cleanup;
}
}
//
// Find the policy module
//
hClient = GenerateClientId();
TCHAR szCompanyName[LSERVER_MAX_STRING_SIZE+1];
TCHAR szProductId[LSERVER_MAX_STRING_SIZE+1];
memset(szCompanyName, 0, sizeof(szCompanyName));
memset(szProductId, 0, sizeof(szProductId));
memcpy(
szCompanyName,
pRequest->ProductInfo.pbCompanyName,
min(pRequest->ProductInfo.cbCompanyName, sizeof(szCompanyName)-sizeof(TCHAR))
);
memcpy(
szProductId,
pRequest->ProductInfo.pbProductID,
min(pRequest->ProductInfo.cbProductID, sizeof(szProductId)-sizeof(TCHAR))
);
//
// Acquire policy module, a default policy module will
// be returned.
//
pPolicy = AcquirePolicyModule(
szCompanyName, // (LPCTSTR) pLicensedProduct->LicensedProduct.pProductInfo->pbCompanyName,
szProductId, // (LPCTSTR) pLicensedProduct->pbOrgProductID
FALSE
);
if(pPolicy == NULL)
{
//
// Must have a policy module, default policy module always there
//
status = TLS_E_INTERNAL;
goto cleanup;
}
//
// Convert request to PMLICENSEREQUEST
//
TlsLicenseRequestToPMLicenseRequest(
LICENSETYPE_LICENSE,
pRequest,
pLicensedProduct->szLicensedClient,
pLicensedProduct->szLicensedUser,
*pdwSupportFlags,
&pmLicenseRequest
);
//
// generate PMUPGRADEREQUEST and pass it to Policy Module
//
memset(&pmRequestUpgrade, 0, sizeof(pmRequestUpgrade));
ppmLicensedProduct = (PPMLICENSEDPRODUCT)AllocateMemory(sizeof(PMLICENSEDPRODUCT)*dwNumLicensedProduct);
if(ppmLicensedProduct == NULL)
{
status = TLS_E_ALLOCATE_MEMORY;
goto cleanup;
}
for(index=0; index < dwNumLicensedProduct; index++)
{
ppmLicensedProduct[index].pbData =
pLicensedProduct[index].pbPolicyData;
ppmLicensedProduct[index].cbData =
pLicensedProduct[index].cbPolicyData;
ppmLicensedProduct[index].bTemporary =
((pLicensedProduct[index].pLicensedVersion->dwFlags & LICENSED_VERSION_TEMPORARY) != 0);
// treat license issued from beta server as temporary
if(ppmLicensedProduct[index].bTemporary == FALSE && TLSIsBetaNTServer() == FALSE)
{
if(IS_LICENSE_ISSUER_RTM(pLicensedProduct[index].pLicensedVersion->dwFlags) == FALSE)
{
ppmLicensedProduct[index].bTemporary = TRUE;
}
}
ppmLicensedProduct[index].ucMarked = 0;
if (0 == index)
{
// for first license, check markings on license
status = TLSCheckLicenseMarkRequest(
TRUE, // forward request if necessary
pLicensedProduct,
cbOldLicense,
pbOldLicense,
&(ppmLicensedProduct[index].ucMarked)
);
}
ppmLicensedProduct[index].LicensedProduct.dwProductVersion =
pLicensedProduct[index].LicensedProduct.pProductInfo->dwVersion;
ppmLicensedProduct[index].LicensedProduct.pszProductId =
(LPTSTR)(pLicensedProduct[index].LicensedProduct.pProductInfo->pbProductID);
ppmLicensedProduct[index].LicensedProduct.pszCompanyName =
(LPTSTR)(pLicensedProduct[index].LicensedProduct.pProductInfo->pbCompanyName);
ppmLicensedProduct[index].LicensedProduct.dwLanguageId =
pLicensedProduct[index].LicensedProduct.dwLanguageID;
ppmLicensedProduct[index].LicensedProduct.dwPlatformId =
pLicensedProduct[index].LicensedProduct.dwPlatformID;
ppmLicensedProduct[index].LicensedProduct.pszMachineName =
pLicensedProduct[index].szLicensedClient;
ppmLicensedProduct[index].LicensedProduct.pszUserName =
pLicensedProduct[index].szLicensedUser;
}
pmRequestUpgrade.pbOldLicense = pbOldLicense;
pmRequestUpgrade.cbOldLicense = cbOldLicense;
pmRequestUpgrade.pUpgradeRequest = &pmLicenseRequest;
pmRequestUpgrade.dwNumProduct = dwNumLicensedProduct;
pmRequestUpgrade.pProduct = ppmLicensedProduct;
status = pPolicy->PMLicenseUpgrade(
hClient,
REQUEST_UPGRADE,
(PVOID)&pmRequestUpgrade,
(PVOID *) &pmAdjustedRequest
);
if(status != ERROR_SUCCESS)
{
goto cleanup;
}
if(pmAdjustedRequest != NULL)
{
if(_tcsicmp(
pmLicenseRequest.pszCompanyName,
pmAdjustedRequest->pszCompanyName
) != 0)
{
//
// Try to steal license from other company???
//
TLSLogEvent(
EVENTLOG_ERROR_TYPE,
TLS_E_POLICYERROR,
status = TLS_E_POLICYMODULEERROR,
pPolicy->GetCompanyName(),
pPolicy->GetProductId()
);
goto cleanup;
}
}
else
{
pmAdjustedRequest = &pmLicenseRequest;
}
for(index =0; index < dwNumLicensedProduct; index++)
{
DWORD tExpireDate;
FileTimeToLicenseDate(&(pLicensedProduct[index].NotAfter),
&tExpireDate);
if( CompareTLSVersions(pmAdjustedRequest->dwProductVersion, pLicensedProduct[index].LicensedProduct.pProductInfo->dwVersion) <= 0 &&
!(pLicensedProduct[index].pLicensedVersion->dwFlags & LICENSED_VERSION_TEMPORARY) &&
_tcscmp(pmAdjustedRequest->pszProductId, (LPTSTR)(pLicensedProduct[index].LicensedProduct.pProductInfo->pbProductID)) == 0 &&
tExpireDate-g_dwReissueLeaseLeeway >= ((DWORD)time(NULL)) )
{
if( TLSIsBetaNTServer() == TRUE ||
IS_LICENSE_ISSUER_RTM(pLicensedProduct[index].pLicensedVersion->dwFlags) == TRUE )
{
//
// Blob already contain perm. license that is >= version
// requested.
//
*ppbNewLicense = (PBYTE)midl_user_allocate(cbOldLicense);
if(*ppbNewLicense != NULL)
{
memcpy(*ppbNewLicense, pbOldLicense, cbOldLicense);
*pcbNewLicense = cbOldLicense;
status = ERROR_SUCCESS;
}
else
{
status = TLS_E_ALLOCATE_MEMORY;
}
goto cleanup;
}
}
}
memset(&LsLicenseRequest, 0, sizeof(TLSDBLICENSEREQUEST));
status = TLSFormDBRequest(
pRequest->pbEncryptedHwid,
pRequest->cbEncryptedHwid,
pmAdjustedRequest->dwProductVersion,
pmAdjustedRequest->pszCompanyName,
pmAdjustedRequest->pszProductId,
pmAdjustedRequest->dwLanguageId,
pmAdjustedRequest->dwPlatformId,
pmAdjustedRequest->pszMachineName,
pmAdjustedRequest->pszUserName,
&LsLicenseRequest
);
if(status != ERROR_SUCCESS)
{
goto cleanup;
}
LsLicenseRequest.pPolicy = pPolicy;
LsLicenseRequest.hClient = hClient;
LsLicenseRequest.pPolicyLicenseRequest = pmAdjustedRequest;
LsLicenseRequest.pClientLicenseRequest = &pmLicenseRequest;
memset(&keypack, 0, sizeof(keypack));
try {
status = TLSVerifyChallengeDataGetWantedLicenseLevel(
ChallengeContext,
cbChallengeResponse,
pbChallenge,
&LsLicenseRequest.wLicenseDetail
);
if( status == ERROR_SUCCESS )
{
//
// if client challenge context handle is 0xFFFFFFFF,
// cbChallenge = 0 and pbChallenge is NULL.
// client is old version, don't verify challenge
//
Forward.m_pRequest = pRequest;
Forward.m_ChallengeContext = ChallengeContext;
Forward.m_cbChallengeResponse = cbChallengeResponse;
Forward.m_pbChallengeResponse = pbChallenge;
Forward.m_cbOldLicense = cbOldLicense;
Forward.m_pbOldLicense = pbOldLicense;
status = TLSUpgradeLicenseRequest(
bForwardRequest,
&Forward,
pdwSupportFlags,
&LsLicenseRequest,
pbOldLicense,
cbOldLicense,
dwNumLicensedProduct,
pLicensedProduct,
pmAdjustedRequest->fTemporary,
pcbNewLicense,
ppbNewLicense
);
}
} // end try
catch( SE_Exception e ) {
status = e.getSeNumber();
}
catch(...)
{
status = TLS_E_INTERNAL;
}
cleanup:
FreeMemory(ppmLicensedProduct);
for(index =0; index < dwNumLicensedProduct; index++)
{
LSFreeLicensedProduct(pLicensedProduct+index);
}
FreeMemory(pLicensedProduct);
lpContext->m_LastError=status;
InterlockedDecrement( &lpContext->m_RefCount );
#if DBG
lpContext->m_LastCall = RPC_CALL_UPGRADELICENSE;
#endif
*dwErrCode = TLSMapReturnCode(status);
if(pPolicy)
{
pPolicy->PMLicenseRequest(
hClient,
REQUEST_COMPLETE,
UlongToPtr (status),
NULL
);
ReleasePolicyModule(pPolicy);
}
//
// Reset SE translator
//
_set_se_translator(old_trans_se_func);
return RPC_S_OK;
}
//-----------------------------------------------------------------------------
error_status_t
TLSRpcCheckLicenseMark(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ const DWORD cbLicense,
/* [in, size_is(cbLicense)] */ PBYTE pbLicense,
/* [out] */ UCHAR *pucMarkFlags,
/* [in, out, ref] */ PDWORD pdwErrCode
)
/*++
Description:
Check markings on the passed in license
Arguments:
phContext - client context handle
cbLicense - size of license to be checked
pbLicense - license to be checked
pucMarkFlags - markings on license
Return via pdwErrCode:
LSERVER_S_SUCCESS
LSERVER_E_INVALID_DATA Invalid parameter.
LSERVER_E_INVALID_LICENSE License passed in is bad
LSERVER_E_DATANOTFOUND license not found in database
LSERVER_E_CORRUPT_DATABASE Corrupt database
LSERVER_E_INTERNAL_ERROR Internal error in license server
Note:
This function forwards the request to the issuing license server. If
the issuer isn't available, or doesn't have the license in the database,
it searches in the local database for a license with the same HWID.
++*/
{
DWORD status = ERROR_SUCCESS;
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
DWORD dwNumLicensedProduct = 0;
PLICENSEDPRODUCT pLicensedProduct=NULL;
DWORD index;
_se_translator_function old_trans_se_func = NULL;
old_trans_se_func = _set_se_translator( trans_se_func );
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcCheckLicenseMark\n"),
lpContext->m_Client
);
InterlockedIncrement( &lpContext->m_RefCount );
if(!(lpContext->m_ClientFlags & CLIENT_ACCESS_LSERVER))
{
status = TLS_E_ACCESS_DENIED;
goto cleanup;
}
if (NULL == pucMarkFlags)
{
status = TLS_E_INVALID_DATA;
goto cleanup;
}
//
// Convert blob to licensed product structure
//
status=LSVerifyDecodeClientLicense(
pbLicense,
cbLicense,
g_pbSecretKey,
g_cbSecretKey,
&dwNumLicensedProduct,
NULL // find size to allocate
);
if(status != LICENSE_STATUS_OK || dwNumLicensedProduct == 0)
{
status = TLS_E_INVALID_LICENSE;
goto cleanup;
}
pLicensedProduct = (PLICENSEDPRODUCT)AllocateMemory(
dwNumLicensedProduct * sizeof(LICENSEDPRODUCT)
);
if(pLicensedProduct == NULL)
{
status = TLS_E_ALLOCATE_MEMORY;
goto cleanup;
}
status=LSVerifyDecodeClientLicense(
pbLicense,
cbLicense,
g_pbSecretKey,
g_cbSecretKey,
&dwNumLicensedProduct,
pLicensedProduct
);
if(status != LICENSE_STATUS_OK)
{
status = TLS_E_INVALID_LICENSE;
goto cleanup;
}
try {
status = TLSCheckLicenseMarkRequest(
FALSE, // don't forward the request
pLicensedProduct,
cbLicense,
pbLicense,
pucMarkFlags
);
} // end try
catch( SE_Exception e ) {
status = e.getSeNumber();
}
catch(...)
{
status = TLS_E_INTERNAL;
}
cleanup:
for(index =0; index < dwNumLicensedProduct; index++)
{
LSFreeLicensedProduct(pLicensedProduct+index);
}
FreeMemory(pLicensedProduct);
lpContext->m_LastError=status;
*pdwErrCode = TLSMapReturnCode(status);
InterlockedDecrement( &lpContext->m_RefCount );
//
// Reset SE translator
//
_set_se_translator(old_trans_se_func);
return RPC_S_OK;
}
//-----------------------------------------------------------------------------
error_status_t
TLSRpcMarkLicense(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ UCHAR ucMarkFlags,
/* [in] */ const DWORD cbLicense,
/* [in, size_is(cbLicense)] */ PBYTE pbLicense,
/* [in, out, ref] */ PDWORD pdwErrCode
)
/*++
Description:
Set markings on the passed in license
Arguments:
phContext - client context handle
ucMarkFlags - markings on license
cbLicense - size of license to be checked
pbLicense - license to be checked
Return via pdwErrCode:
LSERVER_S_SUCCESS
LSERVER_E_INVALID_DATA Invalid parameter.
LSERVER_E_INVALID_LICENSE License passed in is bad
LSERVER_E_DATANOTFOUND license not found in database
LSERVER_E_CORRUPT_DATABASE Corrupt database
LSERVER_E_INTERNAL_ERROR Internal error in license server
Note:
This function forwards the request to the issuing license server. The
issuer modifies the database entry of the license to set the markings.
++*/
{
DWORD status = ERROR_SUCCESS;
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
BOOL bForwardRequest = TRUE;
DWORD dwNumLicensedProduct = 0;
PLICENSEDPRODUCT pLicensedProduct=NULL;
DWORD index;
_se_translator_function old_trans_se_func = NULL;
old_trans_se_func = _set_se_translator( trans_se_func );
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcMarkLicense\n"),
lpContext->m_Client
);
InterlockedIncrement( &lpContext->m_RefCount );
if(!(lpContext->m_ClientFlags & CLIENT_ACCESS_REQUEST))
{
status = TLS_E_ACCESS_DENIED;
goto cleanup;
}
if(lpContext->m_ClientFlags == CLIENT_ACCESS_LSERVER)
{
//
// do not forward any request or infinite loop might
// occur.
//
bForwardRequest = FALSE;
}
//
// Convert blob to licensed product structure
//
status=LSVerifyDecodeClientLicense(
pbLicense,
cbLicense,
g_pbSecretKey,
g_cbSecretKey,
&dwNumLicensedProduct,
NULL // find size to allocate
);
if(status != LICENSE_STATUS_OK || dwNumLicensedProduct == 0)
{
status = TLS_E_INVALID_LICENSE;
goto cleanup;
}
pLicensedProduct = (PLICENSEDPRODUCT)AllocateMemory(
dwNumLicensedProduct * sizeof(LICENSEDPRODUCT)
);
if(pLicensedProduct == NULL)
{
status = TLS_E_ALLOCATE_MEMORY;
goto cleanup;
}
status=LSVerifyDecodeClientLicense(
pbLicense,
cbLicense,
g_pbSecretKey,
g_cbSecretKey,
&dwNumLicensedProduct,
pLicensedProduct
);
if(status != LICENSE_STATUS_OK)
{
status = TLS_E_INVALID_LICENSE;
goto cleanup;
}
try {
status = TLSMarkLicenseRequest(
bForwardRequest,
ucMarkFlags,
pLicensedProduct,
cbLicense,
pbLicense
);
} // end try
catch( SE_Exception e ) {
status = e.getSeNumber();
}
catch(...)
{
status = TLS_E_INTERNAL;
}
cleanup:
for(index =0; index < dwNumLicensedProduct; index++)
{
LSFreeLicensedProduct(pLicensedProduct+index);
}
FreeMemory(pLicensedProduct);
lpContext->m_LastError=status;
*pdwErrCode = TLSMapReturnCode(status);
InterlockedDecrement( &lpContext->m_RefCount );
//
// Reset SE translator
//
_set_se_translator(old_trans_se_func);
return RPC_S_OK;
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcAllocateConcurrentLicense(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [string][in] */ LPTSTR szHydraServer,
/* [in] */ TLSLICENSEREQUEST __RPC_FAR *pRequest,
/* [ref][out][in] */ LONG __RPC_FAR *pdwQuantity,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
Description:
Allocate concurrent licenses base on product.
Arguments:
phContext - client context handle
szHydraServer - name of hydra server requesting concurrent licenses
pRequest - product to request for concurrent license.
dwQuantity - See note
Return via dwErrCode:
LSERVER_S_SUCCESS
LSERVER_E_INVALID_DATA Invalid parameter.
LSERVER_E_NO_PRODUCT request product not installed
LSERVER_E_NO_LICNESE no available license for request product
LSERVER_E_LICENSE_REVOKED Request license has been revoked
LSERVER_E_LICENSE_EXPIRED Request license has expired
LSERVER_E_CORRUPT_DATABASE Corrupt database
LSERVER_E_INTERNAL_ERROR Internal error in license server
Note:
dwQuantity
Input Output
------------------------- -----------------------------------------
0 Total number of concurrent license
issued to hydra server.
> 0, number of license Actual number of license allocated
requested
< 0, number of license Actual number of license returned, always
to return positive value.
++*/
{
#if 1
*pdwErrCode = TLSMapReturnCode(TLS_E_NOTSUPPORTED);
return RPC_S_OK;
#else
PMHANDLE hClient;
DWORD status=ERROR_SUCCESS;
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
PTLSDbWorkSpace pDbWorkSpace;
TLSDBLICENSEREQUEST LsLicenseRequest;
TCHAR szUnknown[LSERVER_MAX_STRING_SIZE+1];
TCHAR szClientMachineName[LSERVER_MAX_STRING_SIZE];
TCHAR szClientUserName[LSERVER_MAX_STRING_SIZE];
TCHAR szCompanyName[LSERVER_MAX_STRING_SIZE+1];
TCHAR szProductId[LSERVER_MAX_STRING_SIZE+1];
_se_translator_function old_trans_se_func = NULL;
old_trans_se_func = _set_se_translator( trans_se_func );
CTLSPolicy* pPolicy = NULL;
BOOL bAllocateLicense = TRUE;
PMLICENSEREQUEST PMLicenseRequest;
PPMLICENSEREQUEST pAdjustedRequest;
#ifdef DBG
DWORD dwStartTime=GetTickCount();
#endif
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcAllocateConcurrentLicense\n"),
lpContext->m_Client
);
if(*pdwQuantity > 1)
{
TLSASSERT(*pdwQuantity > 1);
}
InterlockedIncrement( &lpContext->m_RefCount );
if(!(lpContext->m_ClientFlags & CLIENT_ACCESS_REQUEST))
{
status = TLS_E_ACCESS_DENIED;
goto cleanup;
}
memset(szCompanyName, 0, sizeof(szCompanyName));
memset(szProductId, 0, sizeof(szProductId));
memcpy(
szCompanyName,
pRequest->ProductInfo.pbCompanyName,
min(pRequest->ProductInfo.cbCompanyName, sizeof(szCompanyName)-sizeof(TCHAR))
);
memcpy(
szProductId,
pRequest->ProductInfo.pbProductID,
min(pRequest->ProductInfo.cbProductID, sizeof(szProductId)-sizeof(TCHAR))
);
//
// Acquire policy module, a default policy module will
// be returned.
//
pPolicy = AcquirePolicyModule(
szCompanyName, //(LPCTSTR)pRequest->ProductInfo.pbCompanyName,
szProductId, //(LPCTSTR)pRequest->ProductInfo.pbProductID
TRUE
);
if(pPolicy == NULL)
{
status = GetLastError();
goto cleanup;
}
hClient = GenerateClientId();
//
// return error if string is too big.
//
LoadResourceString(
IDS_UNKNOWN_STRING,
szUnknown,
sizeof(szUnknown)/sizeof(szUnknown[0])
);
_tcsncpy(
szClientMachineName,
(szHydraServer) ? szHydraServer : szUnknown,
LSERVER_MAX_STRING_SIZE
);
_tcsncpy(
szClientUserName,
(szHydraServer) ? szHydraServer : szUnknown,
LSERVER_MAX_STRING_SIZE
);
//
// Convert request to PMLICENSEREQUEST
//
TlsLicenseRequestToPMLicenseRequest(
LICENSETYPE_LICENSE,
pRequest,
szClientMachineName,
szClientUserName,
0,
&PMLicenseRequest
);
//
// Inform Policy module start of new license request
//
status = pPolicy->PMLicenseRequest(
hClient,
REQUEST_NEW,
(PVOID) &PMLicenseRequest,
(PVOID *) &pAdjustedRequest
);
if(status != ERROR_SUCCESS)
{
goto cleanup;
}
if(pAdjustedRequest != NULL)
{
if(_tcsicmp(PMLicenseRequest.pszCompanyName,pAdjustedRequest->pszCompanyName) != 0)
{
// try to steal license from other company???
TLSLogEvent(
EVENTLOG_ERROR_TYPE,
TLS_E_POLICYERROR,
status = TLS_E_POLICYMODULEERROR,
pPolicy->GetCompanyName(),
pPolicy->GetProductId()
);
goto cleanup;
}
}
else
{
pAdjustedRequest = &PMLicenseRequest;
}
//
// form DB request structure
//
status = TLSFormDBRequest(
pRequest->pbEncryptedHwid,
pRequest->cbEncryptedHwid,
pAdjustedRequest->dwProductVersion,
pAdjustedRequest->pszCompanyName,
pAdjustedRequest->pszProductId,
pAdjustedRequest->dwLanguageId,
pAdjustedRequest->dwPlatformId,
pAdjustedRequest->pszMachineName,
pAdjustedRequest->pszUserName,
&LsLicenseRequest
);
if(status != ERROR_SUCCESS)
{
goto cleanup;
}
LsLicenseRequest.pPolicy = pPolicy;
LsLicenseRequest.hClient = hClient;
LsLicenseRequest.pPolicyLicenseRequest = pAdjustedRequest;
LsLicenseRequest.pClientLicenseRequest = &PMLicenseRequest;
if(!ALLOCATEDBHANDLE(pDbWkSpace, g_GeneralDbTimeout))
{
status=TLS_E_ALLOCATE_HANDLE;
goto cleanup;
}
bAllocateLicense = (*pdwQuantity) > 0;
CLEANUPSTMT;
BEGIN_TRANSACTION(pDbWorkSpace);
try {
status = TLSDBAllocateConcurrentLicense(
USEHANDLE(pDbWorkSpace),
szHydraServer,
&LsLicenseRequest,
pdwQuantity
);
}
catch( SE_Exception e ) {
status = e.getSeNumber();
}
catch(...) {
SetLastError(status = TLS_E_INTERNAL);
}
if(TLS_ERROR(status))
{
ROLLBACK_TRANSACTION(pDbWorkSpace);
}
else
{
COMMIT_TRANSACTION(pDbWorkSpace);
}
FREEDBHANDLE(pDbWorkSpace);
cleanup:
#if DBG
lpContext->m_LastCall = RPC_CALL_ALLOCATECONCURRENT;
#endif
#ifdef DBG
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_DETAILSIMPLE,
_TEXT("\t%s : TLSRpcRequestNewLicense() takes %dms\n"),
lpContext->m_Client,
GetTickCount() - dwStartTime
);
#endif
lpContext->m_LastError=status;
InterlockedDecrement( &lpContext->m_RefCount );
*dwErrCode = TLSMapReturnCode(status);
if(pPolicy)
{
pPolicy->PMLicenseRequest(
hClient,
REQUEST_COMPLETE,
(PVOID) status,
NULL
);
ReleasePolicyModule(pPolicy);
}
//
// Reset SE translator
//
_set_se_translator(old_trans_se_func);
return RPC_S_OK;
#endif
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcGetLastError(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [ref][out][in] */ PDWORD cbBufferSize,
/* [size_is][string][out][in] */ LPTSTR szBuffer,
/* [ref][out][in] */ PDWORD dwErrCode
)
/*++
Description:
Return error description text for client's last LSXXX call
Arguments:
IN phContext - Client context
IN cbBufferSize - max. size of szBuffer
IN OUT szBuffer - Pointer to a buffer to receive the
null-terminated character string containing
error description
Returns via dwErrCode:
LSERVER_S_SUCCESS
TLS_E_INTERNAL No error or can't find corresponding error
description.
Error code from WideCharToMultiByte().
++*/
{
DWORD status=ERROR_SUCCESS;
LPTSTR lpMsgBuf=NULL;
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcGetLastError\n"),
lpContext->m_Client
);
try {
DWORD dwRet;
dwRet=FormatMessage(
FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL,
lpContext->m_LastError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0,
NULL
);
if(dwRet == 0)
{
status = GetLastError();
}
else
{
_tcsncpy(
szBuffer,
(LPTSTR)lpMsgBuf,
min(_tcslen((LPTSTR)lpMsgBuf), *cbBufferSize-1)
);
szBuffer[min(_tcslen((LPTSTR)lpMsgBuf), *cbBufferSize-1)] = _TEXT('\0');
*cbBufferSize = _tcslen(szBuffer) + 1;
}
}
catch(...) {
status = TLS_E_INTERNAL;
}
if(lpMsgBuf)
LocalFree(lpMsgBuf);
#if DBG
lpContext->m_LastCall = RPC_CALL_GET_LASTERROR;
#endif
lpContext->m_LastError=status;
*dwErrCode = TLSMapReturnCode(status);
return RPC_S_OK;
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcKeyPackEnumBegin(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ DWORD dwSearchParm,
/* [in] */ BOOL bMatchAll,
/* [ref][in] */ LPLSKeyPackSearchParm lpSearchParm,
/* [ref][out][in] */ PDWORD dwErrCode
)
/*++
Description:
Function to begin enumerate through all key pack installed on server
based on search criterial.
Arguments:
phContext - client context handle.
dwSearchParm - search criterial.
bMatchAll - match all search criterial.
lpSearchParm - search parameter.
Return Value:
LSERVER_S_SUCCESS
LSERVER_E_SERVER_BUSY Server is too busy to process request
LSERVER_E_OUTOFMEMORY
TLS_E_INTERNAL
LSERVER_E_INTERNAL_ERROR
LSERVER_E_INVALID_DATA Invalid data in search parameter
LSERVER_E_INVALID_SEQUENCE Invalid calling sequence, likely, previous
enumeration has not ended.
++*/
{
DWORD status=ERROR_SUCCESS;
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
InterlockedIncrement( &lpContext->m_RefCount );
_se_translator_function old_trans_se_func = NULL;
old_trans_se_func = _set_se_translator( trans_se_func );
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcKeyPackEnumBegin\n"),
lpContext->m_Client
);
//
// This will use cached db connection, in-consistency may occurred,
// visibility of changes in one connection may not appear right away
// on another connection handle, this is expected behavoir for Jet and
// so are we, user can always re-fresh.
//
do {
if(lpContext->m_ContextType != CONTEXTHANDLE_EMPTY_TYPE)
{
SetLastError(status=TLS_E_INVALID_SEQUENCE);
break;
}
try {
LPENUMHANDLE hEnum;
hEnum = TLSDBLicenseKeyPackEnumBegin(
bMatchAll,
dwSearchParm,
lpSearchParm
);
if(hEnum)
{
lpContext->m_ContextType = CONTEXTHANDLE_KEYPACK_ENUM_TYPE;
lpContext->m_ContextHandle = (PVOID)hEnum;
}
else
{
status = GetLastError();
}
}
catch( SE_Exception e ) {
status = e.getSeNumber();
}
catch(...) {
status = TLS_E_INTERNAL;
}
} while(FALSE);
lpContext->m_LastError=status;
InterlockedDecrement( &lpContext->m_RefCount );
#if DBG
lpContext->m_LastCall = RPC_CALL_KEYPACKENUMBEGIN;
#endif
*dwErrCode = TLSMapReturnCode(status);
//
// Reset SE translator
//
_set_se_translator(old_trans_se_func);
return RPC_S_OK;
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcKeyPackEnumNext(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [ref][out] */ LPLSKeyPack lpKeyPack,
/* [ref][out][in] */ PDWORD dwErrCode
)
/*++
Description:
Return next key pack that match search criterial
Arguments:
phContext - client context handle
lpKeyPack - key pack that match search criterial
Return Value:
LSERVER_S_SUCCESS
LSERVER_I_NO_MORE_DATA No more keypack match search criterial
TLS_E_INTERNAL General error in license server
LSERVER_E_INTERNAL_ERROR Internal error in license server
LSERVER_E_SERVER_BUSY License server is too busy to process request
LSERVER_E_OUTOFMEMORY Can't process request due to insufficient memory
LSERVER_E_INVALID_SEQUENCE Invalid calling sequence, must call
LSKeyPackEnumBegin().
++*/
{
DWORD status = ERROR_SUCCESS;
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
BOOL bShowAll = FALSE;
_se_translator_function old_trans_se_func = NULL;
old_trans_se_func = _set_se_translator( trans_se_func );
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcKeyPackEnumNext\n"),
lpContext->m_Client
);
InterlockedIncrement( &lpContext->m_RefCount );
if(lpContext->m_ClientFlags == CLIENT_ACCESS_LSERVER)
{
bShowAll = TRUE;
}
// this one might cause access violation
memset(lpKeyPack, 0, sizeof(LSKeyPack));
if(lpContext->m_ContextType != CONTEXTHANDLE_KEYPACK_ENUM_TYPE)
{
SetLastError(status=TLS_E_INVALID_SEQUENCE);
}
else
{
do {
try {
LPENUMHANDLE hEnum=(LPENUMHANDLE)lpContext->m_ContextHandle;
status=TLSDBLicenseKeyPackEnumNext(
hEnum,
lpKeyPack,
bShowAll
);
}
catch( SE_Exception e ) {
status = e.getSeNumber();
}
catch(...) {
status = TLS_E_INTERNAL;
}
} while(status == TLS_I_MORE_DATA);
}
lpContext->m_LastError=GetLastError();
InterlockedDecrement( &lpContext->m_RefCount );
#if DBG
lpContext->m_LastCall = RPC_CALL_KEYPACKENUMNEXT;
#endif
*dwErrCode = TLSMapReturnCode(status);
//
// Reset SE translator
//
_set_se_translator(old_trans_se_func);
return RPC_S_OK;
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcKeyPackEnumEnd(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [ref][out][in] */ PDWORD dwErrCode
)
/*++
++*/
{
DWORD status=ERROR_SUCCESS;
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcKeyPackEnumEnd\n"),
lpContext->m_Client
);
InterlockedIncrement( &lpContext->m_RefCount );
try {
if(lpContext->m_ContextType != CONTEXTHANDLE_KEYPACK_ENUM_TYPE)
{
SetLastError(status=ERROR_INVALID_HANDLE);
}
else
{
LPENUMHANDLE hEnum=(LPENUMHANDLE)lpContext->m_ContextHandle;
TLSDBLicenseKeyPackEnumEnd(hEnum);
lpContext->m_ContextType = CONTEXTHANDLE_EMPTY_TYPE;
lpContext->m_ContextHandle=NULL;
}
}
catch(...) {
status = TLS_E_INTERNAL;
}
lpContext->m_LastError=GetLastError();
InterlockedDecrement( &lpContext->m_RefCount );
#if DBG
lpContext->m_LastCall = RPC_CALL_KEYPACKENUMEND;
#endif
*dwErrCode = TLSMapReturnCode(status);
return RPC_S_OK;
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcKeyPackAdd(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [ref][out][in] */ LPLSKeyPack lpKeypack,
/* [ref][out][in] */ PDWORD dwErrCode
)
/*++
Description:
Add a license key pack.
Arguments:
phContext - client context handle.
lpKeyPack - key pack to be added.
Return Value:
LSERVER_S_SUCCESS
LSERVER_E_INTERNAL_ERROR
TLS_E_INTERNAL
LSERVER_E_SERVER_BUSY
LSERVER_E_DUPLICATE Product already installed.
LSERVER_E_INVALID_DATA
LSERVER_E_CORRUPT_DATABASE
Note:
Application must call LSKeyPackSetStatus() to activate keypack
++*/
{
PTLSDbWorkSpace pDbWkSpace=NULL;
DWORD status=ERROR_SUCCESS;
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
InterlockedIncrement( &lpContext->m_RefCount );
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcKeyPackAdd\n"),
lpContext->m_Client
);
if(!(lpContext->m_ClientFlags & CLIENT_ACCESS_ADMIN))
{
status = TLS_E_ACCESS_DENIED;
}
else
{
if(!ALLOCATEDBHANDLE(pDbWkSpace, g_GeneralDbTimeout))
{
status=TLS_E_ALLOCATE_HANDLE;
}
else
{
CLEANUPSTMT;
BEGIN_TRANSACTION(pDbWkSpace);
try {
if(lpKeypack->ucKeyPackStatus == LSKEYPACKSTATUS_ADD_LICENSE ||
lpKeypack->ucKeyPackStatus == LSKEYPACKSTATUS_REMOVE_LICENSE)
{
status = TLSDBLicenseKeyPackUpdateLicenses(
USEHANDLE(pDbWkSpace),
lpKeypack->ucKeyPackStatus == LSKEYPACKSTATUS_ADD_LICENSE,
lpKeypack
);
}
else
{
status = TLSDBLicenseKeyPackAdd(
USEHANDLE(pDbWkSpace),
lpKeypack
);
}
if(status == ERROR_SUCCESS)
{
if( _tcsicmp( lpKeypack->szCompanyName, PRODUCT_INFO_COMPANY_NAME ) == 0 )
{
//
// check with known termsrv product ID.
//
if( _tcsnicmp( lpKeypack->szProductId,
TERMSERV_PRODUCTID_SKU,
_tcslen(TERMSERV_PRODUCTID_SKU)) == 0 )
{
TLSResetLogLowLicenseWarning(
lpKeypack->szCompanyName,
TERMSERV_PRODUCTID_SKU,
MAKELONG(lpKeypack->wMinorVersion, lpKeypack->wMajorVersion),
FALSE
);
}
else if(_tcsnicmp( lpKeypack->szProductId,
TERMSERV_PRODUCTID_INTERNET_SKU,
_tcslen(TERMSERV_PRODUCTID_INTERNET_SKU)) == 0 )
{
TLSResetLogLowLicenseWarning(
lpKeypack->szCompanyName,
TERMSERV_PRODUCTID_INTERNET_SKU,
MAKELONG(lpKeypack->wMinorVersion, lpKeypack->wMajorVersion),
FALSE
);
}
else
{
TLSResetLogLowLicenseWarning(
lpKeypack->szCompanyName,
lpKeypack->szProductId,
MAKELONG(lpKeypack->wMinorVersion, lpKeypack->wMajorVersion),
FALSE
);
}
}
else
{
TLSResetLogLowLicenseWarning(
lpKeypack->szCompanyName,
lpKeypack->szProductId,
MAKELONG(lpKeypack->wMinorVersion, lpKeypack->wMajorVersion),
FALSE
);
}
}
}
catch(...) {
status = TLS_E_INTERNAL;
}
if(TLS_ERROR(status))
{
ROLLBACK_TRANSACTION(pDbWkSpace);
}
else
{
COMMIT_TRANSACTION(pDbWkSpace);
}
FREEDBHANDLE(pDbWkSpace);
}
}
//
// Post a sync work object
//
if( status == ERROR_SUCCESS )
{
if( lpKeypack->ucKeyPackType != LSKEYPACKTYPE_FREE )
{
if(TLSAnnounceLKPToAllRemoteServer(
lpKeypack->dwKeyPackId,
0
) != ERROR_SUCCESS)
{
TLSLogWarningEvent(TLS_W_ANNOUNCELKP_FAILED);
}
}
}
#if DBG
lpContext->m_LastCall = RPC_CALL_KEYPACKADD;
#endif
lpContext->m_LastError=status;
InterlockedDecrement( &lpContext->m_RefCount );
*dwErrCode = TLSMapReturnCode(status);
return RPC_S_OK;
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcKeyPackSetStatus(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ DWORD dwSetParm,
/* [ref][in] */ LPLSKeyPack lpKeyPack,
/* [ref][out][in] */ PDWORD dwErrCode
)
/*++
Description:
Routine to activate/deactivated a key pack.
Arguments:
phContext - client context handle
dwSetParam - type of key pack status to be set.
lpKeyPack - new key pack status.
Return Value:
LSERVER_S_SUCCESS
LSERVER_E_INTERNAL_ERROR
TLS_E_INTERNAL
LSERVER_E_INVALID_DATA
LSERVER_E_SERVER_BUSY
LSERVER_E_DATANOTFOUND Key pack is not in server
LSERVER_E_CORRUPT_DATABASE
++*/
{
PTLSDbWorkSpace pDbWkSpace=NULL;
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
DWORD status=ERROR_SUCCESS;
InterlockedIncrement( &lpContext->m_RefCount );
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcKeyPackSetStatus\n"),
lpContext->m_Client
);
if(!(lpContext->m_ClientFlags & CLIENT_ACCESS_ADMIN))
{
status = TLS_E_ACCESS_DENIED;
}
else if( (dwSetParm & ~(LSKEYPACK_SET_KEYPACKSTATUS | LSKEYPACK_SET_ACTIVATEDATE | LSKEYPACK_SET_EXPIREDATE)) &&
!(lpContext->m_ClientFlags & CLIENT_ACCESS_LRWIZ) )
{
status = TLS_E_INVALID_DATA;
}
else
{
if(!ALLOCATEDBHANDLE(pDbWkSpace, g_GeneralDbTimeout))
{
status=TLS_E_ALLOCATE_HANDLE;
}
else
{
CLEANUPSTMT;
BEGIN_TRANSACTION(pDbWkSpace);
try {
status=TLSDBLicenseKeyPackSetStatus(
USEHANDLE(pDbWkSpace),
dwSetParm,
lpKeyPack
);
}
catch(...) {
status = TLS_E_INTERNAL;
}
if(TLS_ERROR(status))
{
ROLLBACK_TRANSACTION(pDbWkSpace);
}
else
{
COMMIT_TRANSACTION(pDbWkSpace);
}
FREEDBHANDLE(pDbWkSpace);
}
}
#if DBG
lpContext->m_LastCall = RPC_CALL_KEYPACKSETSTATUS;
#endif
lpContext->m_LastError=status;
InterlockedDecrement( &lpContext->m_RefCount );
*dwErrCode = TLSMapReturnCode(status);
return RPC_S_OK;
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcLicenseEnumBegin(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ DWORD dwSearchParm,
/* [in] */ BOOL bMatchAll,
/* [ref][in] */ LPLSLicenseSearchParm lpSearchParm,
/* [ref][out][in] */ PDWORD dwErrCode
)
/*++
Description:
Begin enumeration of license issued based on search criterial
Arguments:
phContext - client context handle
dwSearchParm - license search criterial.
bMatchAll - match all search criterial
lpSearchParm - license(s) to be enumerated.
Return Value:
Same as LSKeyPackEnumBegin().
++*/
{
PTLSDbWorkSpace pDbWkSpace = NULL;
DWORD status=ERROR_SUCCESS;
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
_se_translator_function old_trans_se_func = NULL;
old_trans_se_func = _set_se_translator( trans_se_func );
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcLicenseEnumBegin\n"),
lpContext->m_Client
);
InterlockedIncrement( &lpContext->m_RefCount );
//
// This will use cached db connection, in-consistency may occurred,
// visibility of changes in one connection may not appear right away
// on another connection handle, this is expected behavoir for Jet and
// so are we, user can always re-fresh.
//
do {
if(lpContext->m_ContextType != CONTEXTHANDLE_EMPTY_TYPE)
{
SetLastError(status=TLS_E_INVALID_SEQUENCE);
break;
}
pDbWkSpace = AllocateWorkSpace(g_EnumDbTimeout);
// allocate ODBC connections
if(pDbWkSpace == NULL)
{
status=TLS_E_ALLOCATE_HANDLE;
break;
}
try {
LICENSEDCLIENT license;
ConvertLSLicenseToLicense(lpSearchParm, &license);
status = TLSDBLicenseEnumBegin(
pDbWkSpace,
bMatchAll,
dwSearchParm & LICENSE_TABLE_EXTERN_SEARCH_MASK,
&license
);
}
catch( SE_Exception e ) {
status = e.getSeNumber();
}
catch(...) {
status = TLS_E_INTERNAL;
}
if(status == ERROR_SUCCESS)
{
lpContext->m_ContextType = CONTEXTHANDLE_LICENSE_ENUM_TYPE;
lpContext->m_ContextHandle = (PVOID)pDbWkSpace;
}
} while(FALSE);
if(status != ERROR_SUCCESS)
{
if(pDbWkSpace)
{
ReleaseWorkSpace(&pDbWkSpace);
}
}
#if DBG
lpContext->m_LastCall = RPC_CALL_LICENSEENUMBEGIN;
#endif
InterlockedDecrement( &lpContext->m_RefCount );
lpContext->m_LastError=status;
*dwErrCode = TLSMapReturnCode(status);
//
// Reset SE translator
//
_set_se_translator(old_trans_se_func);
return RPC_S_OK;
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcLicenseEnumNext(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [ref][out] */ LPLSLicense lpLicense,
/* [ref][out][in] */ PDWORD dwErrCode
)
/*++
Abstract:
Fetch next record match enumeration criterial.
Parameters:
phContext : Client context handle.
lpLicense : return next record that match enumeration criterial.
dwErrCode : error code.
Returns:
Function returns RPC status, dwErrCode return error code.
Note:
Must have call TLSRpcLicenseEnumBegin().
++*/
{
DWORD status=ERROR_SUCCESS;
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
InterlockedIncrement( &lpContext->m_RefCount );
_se_translator_function old_trans_se_func = NULL;
old_trans_se_func = _set_se_translator( trans_se_func );
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcLicenseEnumNext\n"),
lpContext->m_Client
);
if(lpContext->m_ContextType != CONTEXTHANDLE_LICENSE_ENUM_TYPE)
{
SetLastError(status=TLS_E_INVALID_SEQUENCE);
}
else
{
PTLSDbWorkSpace pDbWkSpace=(PTLSDbWorkSpace)lpContext->m_ContextHandle;
try {
LICENSEDCLIENT license;
memset(lpLicense, 0, sizeof(LSLicense));
status=TLSDBLicenseEnumNext(
pDbWkSpace,
&license
);
if(status == ERROR_SUCCESS)
{
ConvertLicenseToLSLicense(&license, lpLicense);
}
}
catch( SE_Exception e ) {
status = e.getSeNumber();
}
catch(...) {
status = TLS_E_INTERNAL;
}
}
#if DBG
lpContext->m_LastCall = RPC_CALL_LICENSEENUMNEXT;
#endif
lpContext->m_LastError=status;
InterlockedDecrement( &lpContext->m_RefCount );
*dwErrCode = TLSMapReturnCode(status);
//
// Reset SE translator
//
_set_se_translator(old_trans_se_func);
return RPC_S_OK;
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcLicenseEnumNextEx(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [ref][out] */ LPLSLicenseEx lpLicense,
/* [ref][out][in] */ PDWORD dwErrCode
)
/*++
Abstract:
Fetch next record match enumeration criterial.
Parameters:
phContext : Client context handle.
lpLicense : return next record that match enumeration criterial.
dwErrCode : error code.
Returns:
Function returns RPC status, dwErrCode return error code.
Note:
Must have call TLSRpcLicenseEnumBegin().
++*/
{
DWORD status=ERROR_SUCCESS;
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
InterlockedIncrement( &lpContext->m_RefCount );
_se_translator_function old_trans_se_func = NULL;
old_trans_se_func = _set_se_translator( trans_se_func );
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcLicenseEnumNextEx\n"),
lpContext->m_Client
);
if(lpContext->m_ContextType != CONTEXTHANDLE_LICENSE_ENUM_TYPE)
{
SetLastError(status=TLS_E_INVALID_SEQUENCE);
}
else
{
PTLSDbWorkSpace pDbWkSpace=(PTLSDbWorkSpace)lpContext->m_ContextHandle;
try {
LICENSEDCLIENT license;
memset(lpLicense, 0, sizeof(LSLicenseEx));
status=TLSDBLicenseEnumNext(
pDbWkSpace,
&license
);
if(status == ERROR_SUCCESS)
{
ConvertLicenseToLSLicenseEx(&license, lpLicense);
}
}
catch( SE_Exception e ) {
status = e.getSeNumber();
}
catch(...) {
status = TLS_E_INTERNAL;
}
}
#if DBG
lpContext->m_LastCall = RPC_CALL_LICENSEENUMNEXT;
#endif
lpContext->m_LastError=status;
InterlockedDecrement( &lpContext->m_RefCount );
*dwErrCode = TLSMapReturnCode(status);
//
// Reset SE translator
//
_set_se_translator(old_trans_se_func);
return RPC_S_OK;
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcLicenseEnumEnd(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [ref][out][in] */ PDWORD dwErrCode
)
/*++
Abstract:
Terminate a enumeration.
Parameters:
phContext :
dwErrCode :
Returns:
Note
++*/
{
DWORD status=ERROR_SUCCESS;
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
InterlockedIncrement( &lpContext->m_RefCount );
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcLicenseEnumEnd\n"),
lpContext->m_Client
);
try {
if(lpContext->m_ContextType != CONTEXTHANDLE_LICENSE_ENUM_TYPE)
{
SetLastError(status=ERROR_INVALID_HANDLE);
}
else
{
PTLSDbWorkSpace pDbWkSpace = (PTLSDbWorkSpace)lpContext->m_ContextHandle;
TLSDBLicenseEnumEnd(pDbWkSpace);
ReleaseWorkSpace(&pDbWkSpace);
lpContext->m_ContextType = CONTEXTHANDLE_EMPTY_TYPE;
}
}
catch(...) {
status = TLS_E_INTERNAL;
}
#if DBG
lpContext->m_LastCall = RPC_CALL_LICENSEENUMEND;
#endif
lpContext->m_LastError=status;
InterlockedDecrement( &lpContext->m_RefCount );
*dwErrCode = TLSMapReturnCode(status);
return RPC_S_OK;
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcLicenseSetStatus(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ DWORD dwSetParam,
/* [in] */ LPLSLicense lpLicense,
/* [ref][out][in] */ PDWORD dwErrCode
)
/*++
++*/
{
PTLSDbWorkSpace pDbWkSpace=NULL;
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
DWORD status=ERROR_SUCCESS;
InterlockedIncrement( &lpContext->m_RefCount );
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcLicenseSetStatus\n"),
lpContext->m_Client
);
if(!(lpContext->m_ClientFlags & CLIENT_ACCESS_ADMIN))
{
status = TLS_E_ACCESS_DENIED;
}
else if(dwSetParam != LSLICENSE_EXSEARCH_LICENSESTATUS)
{
status = TLS_E_INVALID_DATA;
}
else
{
if(!ALLOCATEDBHANDLE(pDbWkSpace, g_GeneralDbTimeout))
{
status=TLS_E_ALLOCATE_HANDLE;
}
else
{
CLEANUPSTMT;
BEGIN_TRANSACTION(pDbWkSpace);
try {
LICENSEDCLIENT license;
ConvertLSLicenseToLicense(lpLicense, &license);
status=TLSDBLicenseSetValue(
USEHANDLE(pDbWkSpace),
dwSetParam,
&license,
FALSE
);
}
catch(...) {
status = TLS_E_INTERNAL;
}
if(TLS_ERROR(status))
{
ROLLBACK_TRANSACTION(pDbWkSpace);
}
else
{
COMMIT_TRANSACTION(pDbWkSpace);
}
FREEDBHANDLE(pDbWkSpace);
}
}
#if DBG
lpContext->m_LastCall = RPC_CALL_LICENSESETSTATUS;
#endif
lpContext->m_LastError = status;
InterlockedDecrement( &lpContext->m_RefCount );
*dwErrCode = TLSMapReturnCode(status);
return RPC_S_OK;
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcGetAvailableLicenses(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ DWORD dwSearchParm,
/* [ref][in] */ LPLSKeyPack lplsKeyPack,
/* [ref][out] */ LPDWORD lpdwAvail,
/* [ref][out][in] */ PDWORD dwErrCode
)
/*++
++*/
{
PTLSDbWorkSpace pDbWkSpace=NULL;
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
DWORD status=ERROR_SUCCESS;
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcGetAvailableLicenses\n"),
lpContext->m_Client
);
InterlockedIncrement( &lpContext->m_RefCount );
//
// Don't use global cached DB connection handle, it is possible
// to get in-consistent value using other DB handle, however, it is
// also possible that during the time that this function return and
// the time that client actually make the call to allocate license,
// all available licenses were allocated by other client.
//
pDbWkSpace = AllocateWorkSpace(g_GeneralDbTimeout);
if(pDbWkSpace == NULL)
{
status=TLS_E_ALLOCATE_HANDLE;
}
else
{
try {
LICENSEPACK keypack;
memset(&keypack, 0, sizeof(keypack));
ConvertLsKeyPackToKeyPack(
lplsKeyPack,
&keypack,
NULL
);
status = TLSDBKeyPackGetAvailableLicenses(
pDbWkSpace,
dwSearchParm,
&keypack,
lpdwAvail
);
//FreeTlsLicensePack(&keypack);
}
catch(...) {
status = TLS_E_INTERNAL;
}
ReleaseWorkSpace(&pDbWkSpace);
}
lpContext->m_LastError=status;
InterlockedDecrement( &lpContext->m_RefCount );
*dwErrCode = TLSMapReturnCode(status);
return RPC_S_OK;
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcGetRevokeKeyPackList(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [out][in] */ PDWORD pcbNumberOfRange,
/* [size_is][out] */ LPLSRange __RPC_FAR *ppRevokeRange,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
++*/
{
*pdwErrCode = TLSMapReturnCode(TLS_E_NOTSUPPORTED);
return RPC_S_OK;
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcGetRevokeLicenseList(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [out][in] */ PDWORD pcbNumberOfRange,
/* [size_is][out] */ LPLSRange __RPC_FAR *ppRevokeRange,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
++*/
{
*pdwErrCode = TLSMapReturnCode(TLS_E_NOTSUPPORTED);
return RPC_S_OK;
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcReturnKeyPack(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ DWORD dwKeyPackId,
/* [in] */ DWORD dwReturnReason,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
++*/
{
*pdwErrCode = TLSMapReturnCode(TLS_E_NOTSUPPORTED);
return RPC_S_OK;
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcReturnLicense(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ DWORD dwKeyPackId,
/* [in] */ DWORD dwLicenseId,
/* [in] */ DWORD dwReturnReason,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
++*/
{
*pdwErrCode = TLSMapReturnCode(TLS_E_NOTSUPPORTED);
return RPC_S_OK;
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcInstallCertificate(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ DWORD dwCertType,
/* [in] */ DWORD dwCertLevel,
/* [in] */ DWORD cbSignCert,
/* [size_is][in] */ PBYTE pbSignCert,
/* [in] */ DWORD cbExchCert,
/* [size_is][in] */ PBYTE pbExchCert,
/* [ref][out][in] */ PDWORD dwErrCode
)
/*++
++*/
{
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
DWORD status=ERROR_SUCCESS;
_se_translator_function old_trans_se_func = NULL;
old_trans_se_func = _set_se_translator( trans_se_func );
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcInstallCertificate\n"),
lpContext->m_Client
);
InterlockedIncrement( &lpContext->m_RefCount );
DWORD cbLsSignCert=0;
PBYTE pbLsSignCert=NULL;
DWORD cbLsExchCert=0;
PBYTE pbLsExchCert=NULL;
if(!(lpContext->m_ClientFlags & CLIENT_ACCESS_ADMIN))
{
status = TLS_E_ACCESS_DENIED;
goto cleanup;
}
if(pbSignCert == NULL || pbExchCert == NULL)
{
status = TLS_E_INVALID_DATA;
goto cleanup;
}
#if DBG
//
// Verify input data
//
status = TLSVerifyCertChainInMomory(
g_hCryptProv,
pbSignCert,
cbSignCert
);
if(status != ERROR_SUCCESS)
{
status = TLS_E_INVALID_DATA;
}
//
// Verify input data
//
status = TLSVerifyCertChainInMomory(
g_hCryptProv,
pbExchCert,
cbExchCert
);
if(status != ERROR_SUCCESS)
{
status = TLS_E_INVALID_DATA;
}
#endif
//
// Block RPC call to serialize install certificate
//
if(AcquireRPCExclusiveLock(INFINITE) == FALSE)
{
status=TLS_E_ALLOCATE_HANDLE;
goto cleanup;
}
if(AcquireAdministrativeLock(INFINITE) == TRUE)
{
try {
if(dwCertLevel == 0)
{
status = TLSSaveRootCertificatesToStore(
g_hCryptProv,
cbSignCert,
pbSignCert,
cbExchCert,
pbExchCert
);
}
else
{
status = TLSSaveCertificatesToStore(
g_hCryptProv,
dwCertType,
dwCertLevel,
cbSignCert,
pbSignCert,
cbExchCert,
pbExchCert
);
if(status == ERROR_SUCCESS && dwCertType == CERTIFICATE_CA_TYPE)
{
if(cbSignCert)
{
status = IsCertificateLicenseServerCertificate(
g_hCryptProv,
AT_SIGNATURE,
cbSignCert,
pbSignCert,
&cbLsSignCert,
&pbLsSignCert
);
}
if(status == ERROR_SUCCESS && cbExchCert)
{
status = IsCertificateLicenseServerCertificate(
g_hCryptProv,
AT_KEYEXCHANGE,
cbExchCert,
pbExchCert,
&cbLsExchCert,
&pbLsExchCert
);
}
//
// Install what we have here.
//
if(status == ERROR_SUCCESS && (cbLsExchCert || pbLsExchCert))
{
status = TLSInstallLsCertificate(
cbLsSignCert,
pbLsSignCert,
cbLsExchCert,
pbLsExchCert
);
}
#ifdef ENFORCE_LICENSING
// enforce version, check what's installed and restore backup if necessary
// non-enforce, just install, we won't use it anyway.
if(status == ERROR_SUCCESS && (cbLsExchCert || pbLsExchCert))
{
// reload certificate
if(TLSLoadVerifyLicenseServerCertificates() != ERROR_SUCCESS)
{
status = TLS_E_INVALID_DATA;
// delete the primary certificate registry key
TLSRegDeleteKey(
HKEY_LOCAL_MACHINE,
LSERVER_SERVER_CERTIFICATE_REGKEY
);
//
// reload certificate, if anything goes wrong, we will goes
// back to unregister mode.
//
if(TLSLoadServerCertificate() == FALSE)
{
// critical error occurred
TLSLogErrorEvent(TLS_E_LOAD_CERTIFICATE);
// initiate self-shutdown
GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
}
}
else
{
DWORD dwStatus;
// make sure our backup is up to date.
dwStatus = TLSRestoreLicenseServerCertificate(
LSERVER_SERVER_CERTIFICATE_REGKEY,
LSERVER_SERVER_CERTIFICATE_REGKEY_BACKUP1
);
if(dwStatus != ERROR_SUCCESS)
{
TLSLogWarningEvent(TLS_W_BACKUPCERTIFICATE);
TLSRegDeleteKey(
HKEY_LOCAL_MACHINE,
LSERVER_SERVER_CERTIFICATE_REGKEY_BACKUP1
);
}
dwStatus = TLSRestoreLicenseServerCertificate(
LSERVER_SERVER_CERTIFICATE_REGKEY,
LSERVER_SERVER_CERTIFICATE_REGKEY_BACKUP2
);
if(dwStatus != ERROR_SUCCESS)
{
TLSLogWarningEvent(TLS_W_BACKUPCERTIFICATE);
TLSRegDeleteKey(
HKEY_LOCAL_MACHINE,
LSERVER_SERVER_CERTIFICATE_REGKEY_BACKUP2
);
}
}
}
#endif
if(pbLsSignCert)
{
FreeMemory(pbLsSignCert);
}
if(pbLsExchCert)
{
FreeMemory(pbLsExchCert);
}
}
}
}
catch( SE_Exception e ) {
status = e.getSeNumber();
}
catch(...) {
status = TLS_E_INTERNAL;
}
ReleaseAdministrativeLock();
}
else
{
status=TLS_E_ALLOCATE_HANDLE;
}
ReleaseRPCExclusiveLock();
cleanup:
lpContext->m_LastError=status;
#if DBG
lpContext->m_LastCall = RPC_CALL_INSTALL_SERV_CERT;
#endif
InterlockedDecrement( &lpContext->m_RefCount );
*dwErrCode = TLSMapReturnCode(status);
//
// Reset SE translator
//
_set_se_translator(old_trans_se_func);
return RPC_S_OK;
}
//-------------------------------------------------------------------------------
error_status_t
TLSRpcGetServerCertificate(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ BOOL bSignCert,
/* [size_is][size_is][out] */ LPBYTE __RPC_FAR *ppCertBlob,
/* [ref][out] */ LPDWORD lpdwCertBlobLen,
/* [ref][out][in] */ PDWORD dwErrCode
)
/*++
++*/
{
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
DWORD status=ERROR_SUCCESS;
_se_translator_function old_trans_se_func = NULL;
old_trans_se_func = _set_se_translator( trans_se_func );
InterlockedIncrement( &lpContext->m_RefCount );
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcGetServerCertificate\n"),
lpContext->m_Client
);
if(!(lpContext->m_ClientFlags & CLIENT_ACCESS_ADMIN))
{
status = TLS_E_ACCESS_DENIED;
}
else if(!g_pbExchangeEncodedCert || !g_cbExchangeEncodedCert ||
!g_pbSignatureEncodedCert || !g_cbSignatureEncodedCert)
{
status = TLS_E_NO_CERTIFICATE;
}
else
{
if(AcquireAdministrativeLock(INFINITE) == TRUE)
{
try{
status = TLSSaveCertAsPKCS7(
(bSignCert) ? g_pbSignatureEncodedCert : g_pbExchangeEncodedCert,
(bSignCert) ? g_cbSignatureEncodedCert : g_cbExchangeEncodedCert,
ppCertBlob,
lpdwCertBlobLen
);
// hack so that we can continue testing...
if(g_bHasHydraCert == FALSE)
{
if(g_pbServerSPK != NULL && g_cbServerSPK != 0)
{
status = TLS_W_SELFSIGN_CERTIFICATE;
}
else
{
status = TLS_W_TEMP_SELFSIGN_CERT;
}
}
}
catch( SE_Exception e ) {
status = e.getSeNumber();
}
catch(...)
{
status = TLS_E_INTERNAL;
}
ReleaseAdministrativeLock();
}
else
{
status = TLS_E_ALLOCATE_HANDLE;
}
}
lpContext->m_LastError=status;
#if DBG
lpContext->m_LastCall = RPC_CALL_GETSERV_CERT;
#endif
InterlockedDecrement( &lpContext->m_RefCount );
*dwErrCode = TLSMapReturnCode(status);
//
// Reset SE translator
//
_set_se_translator(old_trans_se_func);
return RPC_S_OK;
}
//-------------------------------------------------------------------------------
void
MyFreeLicenseKeyPack(
PLicense_KeyPack pLicenseKeyPack
)
/*
*/
{
DWORD i;
PKeyPack_Description pKpDesc;
if( pLicenseKeyPack->pDescription )
{
for( i = 0, pKpDesc = pLicenseKeyPack->pDescription;
i < pLicenseKeyPack->dwDescriptionCount;
i++, pKpDesc++ )
{
if(pKpDesc->pDescription)
LocalFree( pKpDesc->pDescription );
if(pKpDesc->pbProductName)
LocalFree( pKpDesc->pbProductName );
}
}
if(pLicenseKeyPack->pDescription)
LocalFree( pLicenseKeyPack->pDescription );
if(pLicenseKeyPack->pbManufacturer && pLicenseKeyPack->cbManufacturer != 0)
LocalFree( pLicenseKeyPack->pbManufacturer );
if(pLicenseKeyPack->pbManufacturerData && pLicenseKeyPack->cbManufacturerData != 0)
LocalFree( pLicenseKeyPack->pbManufacturerData );
if(pLicenseKeyPack->pbProductId && pLicenseKeyPack->cbProductId != 0)
LocalFree( pLicenseKeyPack->pbProductId );
return;
}
//---------------------------------------------------------------------
error_status_t
TLSRpcRegisterLicenseKeyPack(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [size_is][in] */ LPBYTE pbCHCertBlob,
/* [in] */ DWORD cbCHCertBlobSize,
/* [size_is][in] */ LPBYTE pbRootCertBlob,
/* [in] */ DWORD cbRootCertBlob,
/* [size_is][in] */ LPBYTE lpKeyPackBlob,
/* [in] */ DWORD dwKeyPackBlobLen,
/* [ref][out][in] */ PDWORD dwErrCode
)
/*++
++*/
{
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
DWORD status=ERROR_SUCCESS;
LSKeyPack keypack;
_se_translator_function old_trans_se_func = NULL;
old_trans_se_func = _set_se_translator( trans_se_func );
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcRegisterLicenseKeyPack\n"),
lpContext->m_Client
);
PTLSDbWorkSpace pDbWkSpace;
InterlockedIncrement( &lpContext->m_RefCount );
if(!(lpContext->m_ClientFlags & CLIENT_ACCESS_ADMIN))
{
status = TLS_E_ACCESS_DENIED;
goto cleanup;
}
if(!ALLOCATEDBHANDLE(pDbWkSpace, g_GeneralDbTimeout))
{
status=TLS_E_ALLOCATE_HANDLE;
}
else
{
License_KeyPack pLicenseKeyPack;
LicensePackDecodeParm LkpDecodeParm;
memset(
&LkpDecodeParm,
0,
sizeof(LicensePackDecodeParm)
);
LkpDecodeParm.hCryptProv = g_hCryptProv;
LkpDecodeParm.pbDecryptParm = (PBYTE)g_pszServerPid;
LkpDecodeParm.cbDecryptParm = (lstrlen(g_pszServerPid) * sizeof(TCHAR));
LkpDecodeParm.cbClearingHouseCert = cbCHCertBlobSize;
LkpDecodeParm.pbClearingHouseCert = pbCHCertBlob;
LkpDecodeParm.pbRootCertificate = pbRootCertBlob;
LkpDecodeParm.cbRootCertificate = cbRootCertBlob;
//
// make code clean, always start a transaction
//
CLEANUPSTMT;
BEGIN_TRANSACTION(pDbWkSpace);
try {
status = DecodeLicenseKeyPackEx(
&pLicenseKeyPack,
&LkpDecodeParm,
dwKeyPackBlobLen,
lpKeyPackBlob
);
if(status != LICENSE_STATUS_OK)
{
status = TLS_E_DECODE_KEYPACKBLOB;
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_DETAILSIMPLE,
_TEXT("Can't decode key pack blob - %d...\n"),
status);
}
else
{
status=TLSDBRegisterLicenseKeyPack(
USEHANDLE(pDbWkSpace),
&pLicenseKeyPack,
&keypack
);
MyFreeLicenseKeyPack(&pLicenseKeyPack);
}
}
catch( SE_Exception e ) {
status = e.getSeNumber();
}
catch(...) {
status = TLS_E_INTERNAL;
}
if(TLS_ERROR(status))
{
ROLLBACK_TRANSACTION(pDbWkSpace);
}
else
{
COMMIT_TRANSACTION(pDbWkSpace);
}
FREEDBHANDLE(pDbWkSpace);
}
//
// Post a sync work object
//
if(status == ERROR_SUCCESS)
{
if(TLSAnnounceLKPToAllRemoteServer(
keypack.dwKeyPackId,
0
) != ERROR_SUCCESS)
{
TLSLogWarningEvent(TLS_W_ANNOUNCELKP_FAILED);
}
}
cleanup:
lpContext->m_LastError=status;
#if DBG
lpContext->m_LastCall = RPC_CALL_REGISTER_LICENSE_PACK;
#endif
InterlockedDecrement( &lpContext->m_RefCount );
*dwErrCode = TLSMapReturnCode(status);
//
// Reset SE translator
//
_set_se_translator(old_trans_se_func);
return RPC_S_OK;
}
////////////////////////////////////////////////////////////////////////////
error_status_t
TLSRpcRequestTermServCert(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ LPTLSHYDRACERTREQUEST pRequest,
/* [ref][out][in] */ PDWORD pcbChallengeData,
/* [size_is][out] */ PBYTE* ppbChallengeData,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
Abstract:
Private routine to issue certificate to Terminal Server.
Parameter:
phContext : Client context handle.
pRequest : Terminal Server specific certificate request.
pcbChallengeData : size of Server randomly generated challenge data
to Terminal Server.
ppbChallengeData : Server randomly generated challenge data to Terminal
server.
pdwErrCode : Error code.
Returns:
Function always return RPC_S_OK, actual error code is returned in
pdwErrCode.
Note:
Routine does not actually issue a license to Terminal Server, Terminal
Server must call TLSRpcRetrieveTermServCert() to retrieve its own
license.
--*/
{
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
DWORD status=ERROR_SUCCESS;
LPTERMSERVCERTREQHANDLE lpHandle=NULL;
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcRequestTermServCert\n"),
lpContext->m_Client
);
*ppbChallengeData = NULL;
*pcbChallengeData = 0;
// verify client handle
InterlockedIncrement( &lpContext->m_RefCount );
if(lpContext->m_ContextType != CONTEXTHANDLE_EMPTY_TYPE)
{
SetLastError(status=TLS_E_INVALID_SEQUENCE);
goto cleanup;
}
lpHandle = (LPTERMSERVCERTREQHANDLE)AllocateMemory(
sizeof(TERMSERVCERTREQHANDLE)
);
if(lpHandle == NULL)
{
SetLastError(status = ERROR_OUTOFMEMORY);
goto cleanup;
}
//
// Generate Challenge Data
//
lpHandle->pCertRequest = pRequest;
status = TLSGenerateChallengeData(
CLIENT_INFO_HYDRA_SERVER,
&lpHandle->cbChallengeData,
&lpHandle->pbChallengeData
);
if(status != ERROR_SUCCESS)
{
goto cleanup;
}
// return challenge data
*pcbChallengeData = lpHandle->cbChallengeData;
*ppbChallengeData = (PBYTE)midl_user_allocate(*pcbChallengeData);
if(*ppbChallengeData == NULL)
{
SetLastError(status = ERROR_OUTOFMEMORY);
goto cleanup;
}
memcpy( *ppbChallengeData,
lpHandle->pbChallengeData,
lpHandle->cbChallengeData);
lpContext->m_ContextHandle = (HANDLE)lpHandle;
lpContext->m_ContextType = CONTEXTHANDLE_HYDRA_REQUESTCERT_TYPE;
cleanup:
if(status != ERROR_SUCCESS)
{
// frees up memory.
// Can't overwrite context type.
//lpContext->m_ContextType = CONTEXTHANDLE_EMPTY_TYPE;
if(lpHandle != NULL)
{
FreeMemory(lpHandle->pbChallengeData);
FreeMemory(lpHandle);
}
if(*ppbChallengeData != NULL)
{
midl_user_free(*ppbChallengeData);
}
if(pRequest != NULL)
{
midl_user_free(pRequest);
}
*ppbChallengeData = NULL;
*pcbChallengeData = 0;
}
InterlockedDecrement( &lpContext->m_RefCount );
lpContext->m_LastError=status;
#if DBG
lpContext->m_LastCall = RPC_CALL_REQUEST_TERMSRV_CERT;
#endif
*pdwErrCode = TLSMapReturnCode(status);
return RPC_S_OK;
}
////////////////////////////////////////////////////////////////////////////
error_status_t
TLSRpcRetrieveTermServCert(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ DWORD cbResponseData,
/* [size_is][in] */ PBYTE pbResponseData,
/* [ref][out][in] */ PDWORD pcbCert,
/* [size_is][out] */ PBYTE* ppbCert,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
Abstract:
Private routine to retrieve Terminal Server's license.
Parameters:
phContext : client context handle.
cbResponseData : size of Terminal Server responses data to
license server's challenge.
pbResponseData : Terminal Server responses data to license
server's challenge.
pcbCert : Size of Terminal Server's license in bytes.
ppbCert : Terminal Server's license.
pdwErrCode : error code if fail.
Returns:
Function returns RPC_S_OK, actual error code returns in
pdwErrCode.
Note:
Must have call TLSRpcRequestTermServCert().
--*/
{
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
DWORD status=ERROR_SUCCESS;
LPTERMSERVCERTREQHANDLE lpHandle=NULL;
CTLSPolicy* pPolicy=NULL;
PMHANDLE hClient;
PBYTE pbPkcs7=NULL;
DWORD cbPkcs7=0;
TLSDBLICENSEREQUEST LicenseRequest;
DWORD dwQuantity = 1;
TLSPRODUCTINFO ProductInfo;
TCHAR szCompanyName[LSERVER_MAX_STRING_SIZE];
TCHAR szMachineName[MAXCOMPUTERNAMELENGTH];
TCHAR szUserName[MAXUSERNAMELENGTH];
PTLSDbWorkSpace pDbWkSpace;
PMLICENSEREQUEST PMLicenseRequest;
PPMLICENSEREQUEST pAdjustedRequest;
TLSDBLICENSEDPRODUCT LicensedProduct;
_se_translator_function old_trans_se_func = NULL;
old_trans_se_func = _set_se_translator( trans_se_func );
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcRetrieveTermServCert\n"),
lpContext->m_Client
);
// verify client handle
InterlockedIncrement( &lpContext->m_RefCount );
if(lpContext->m_ContextType != CONTEXTHANDLE_HYDRA_REQUESTCERT_TYPE)
{
SetLastError(status = TLS_E_INVALID_SEQUENCE);
goto cleanup;
}
lpHandle = (LPTERMSERVCERTREQHANDLE)lpContext->m_ContextHandle;
if( lpHandle == NULL || lpHandle->pCertRequest == NULL ||
lpHandle->pCertRequest->pbEncryptedHwid == NULL ||
lpHandle->pCertRequest->cbEncryptedHwid == 0 )
{
SetLastError(status = TLS_E_INVALID_SEQUENCE);
goto cleanup;
}
//
// Verify challenge response data
//
//
// Request a license from specific key pack
//
memset(&LicenseRequest, 0, sizeof(TLSDBLICENSEREQUEST));
if(!LoadResourceString(
IDS_HS_COMPANYNAME,
szCompanyName,
sizeof(szCompanyName) / sizeof(szCompanyName[0])))
{
SetLastError(status = TLS_E_INTERNAL);
goto cleanup;
}
if(lpContext->m_Client == NULL)
{
if(!LoadResourceString(
IDS_HS_MACHINENAME,
LicenseRequest.szMachineName,
sizeof(LicenseRequest.szMachineName)/sizeof(LicenseRequest.szMachineName[0])))
{
SetLastError(status = TLS_E_INTERNAL);
goto cleanup;
}
if(!LoadResourceString(
IDS_HS_USERNAME,
LicenseRequest.szUserName,
sizeof(LicenseRequest.szUserName)/sizeof(LicenseRequest.szUserName[0])))
{
SetLastError(status = TLS_E_INTERNAL);
goto cleanup;
}
}
else
{
SAFESTRCPY(LicenseRequest.szMachineName, lpContext->m_Client);
SAFESTRCPY(LicenseRequest.szUserName, lpContext->m_Client);
}
LicenseRequest.dwProductVersion = HYDRACERT_PRODUCT_VERSION;
LicenseRequest.pszProductId = HYDRAPRODUCT_HS_CERTIFICATE_SKU;
LicenseRequest.pszCompanyName = szCompanyName;
LicenseRequest.dwLanguageID = GetSystemDefaultLangID(); // ignore
LicenseRequest.dwPlatformID = CLIENT_PLATFORMID_WINDOWS_NT_FREE; // WINDOWS
LicenseRequest.pbEncryptedHwid = lpHandle->pCertRequest->pbEncryptedHwid;
LicenseRequest.cbEncryptedHwid = lpHandle->pCertRequest->cbEncryptedHwid;
status=LicenseDecryptHwid(
&LicenseRequest.hWid,
LicenseRequest.cbEncryptedHwid,
LicenseRequest.pbEncryptedHwid,
g_cbSecretKey,
g_pbSecretKey
);
if(status != ERROR_SUCCESS)
{
status = ERROR_INVALID_PARAMETER;
goto cleanup;
}
LicenseRequest.pClientPublicKey = (PCERT_PUBLIC_KEY_INFO)lpHandle->pCertRequest->pSubjectPublicKeyInfo;
LicenseRequest.clientCertRdn.type = LSCERT_RDN_STRING_TYPE;
LicenseRequest.clientCertRdn.szRdn = lpHandle->pCertRequest->szSubjectRdn;
LicenseRequest.dwNumExtensions = lpHandle->pCertRequest->dwNumCertExtension;
LicenseRequest.pExtensions = (PCERT_EXTENSION)lpHandle->pCertRequest->pCertExtensions;
hClient = GenerateClientId();
pPolicy = AcquirePolicyModule(NULL, NULL, FALSE);
if(pPolicy == NULL)
{
SetLastError(status = TLS_E_INTERNAL);
goto cleanup;
}
PMLicenseRequest.dwProductVersion = LicenseRequest.dwProductVersion;
PMLicenseRequest.pszProductId = LicenseRequest.pszProductId;
PMLicenseRequest.pszCompanyName = LicenseRequest.pszCompanyName;
PMLicenseRequest.dwLanguageId = LicenseRequest.dwLanguageID;
PMLicenseRequest.dwPlatformId = LicenseRequest.dwPlatformID;
PMLicenseRequest.pszMachineName = LicenseRequest.szMachineName;
PMLicenseRequest.pszUserName = LicenseRequest.szUserName;
PMLicenseRequest.dwLicenseType = LICENSETYPE_LICENSE;
//
// Inform Policy module start of new license request
//
status = pPolicy->PMLicenseRequest(
hClient,
REQUEST_NEW,
(PVOID) &PMLicenseRequest,
(PVOID *) &pAdjustedRequest
);
if(status != ERROR_SUCCESS)
{
goto cleanup;
}
LicenseRequest.pPolicy = pPolicy;
LicenseRequest.hClient = hClient;
LicenseRequest.pPolicyLicenseRequest = pAdjustedRequest;
LicenseRequest.pClientLicenseRequest = &PMLicenseRequest;
// Call issue new license from sepcific keypack
if(!ALLOCATEDBHANDLE(pDbWkSpace, g_GeneralDbTimeout))
{
status = TLS_E_ALLOCATE_HANDLE;
goto cleanup;
}
CLEANUPSTMT;
BEGIN_TRANSACTION(pDbWkSpace);
try {
status = TLSDBIssuePermanentLicense(
USEHANDLE(pDbWkSpace),
&LicenseRequest,
FALSE, // bLatestVersion
FALSE, // bAcceptFewerLicenses
&dwQuantity,
&LicensedProduct,
0
);
}
catch( SE_Exception e ) {
status = e.getSeNumber();
}
catch(...) {
status = TLS_E_INTERNAL;
}
if(TLS_ERROR(status))
{
ROLLBACK_TRANSACTION(pDbWkSpace);
}
else
{
COMMIT_TRANSACTION(pDbWkSpace);
}
FREEDBHANDLE(pDbWkSpace);
if(status == ERROR_SUCCESS)
{
LicensedProduct.pSubjectPublicKeyInfo = (PCERT_PUBLIC_KEY_INFO)lpHandle->pCertRequest->pSubjectPublicKeyInfo;
//
// Generate client certificate
//
status = TLSGenerateClientCertificate(
g_hCryptProv,
1,
&LicensedProduct,
LICENSE_DETAIL_DETAIL,
&pbPkcs7,
&cbPkcs7
);
if(TLS_ERROR(status) == TRUE)
{
goto cleanup;
}
status = TLSChainProprietyCertificate(
g_hCryptProv,
(CanIssuePermLicense() == FALSE),
pbPkcs7,
cbPkcs7,
ppbCert,
pcbCert
);
if(status == ERROR_SUCCESS)
{
if(CanIssuePermLicense() == FALSE)
{
status = TLS_W_SELFSIGN_CERTIFICATE;
}
}
}
cleanup:
FreeMemory(pbPkcs7);
if(pPolicy)
{
ReleasePolicyModule(pPolicy);
}
//
// Free up Hydra Certificate Request handle,
// all_nodes attribute so single free.
//
if(lpHandle)
{
if(lpHandle->pCertRequest)
{
midl_user_free(lpHandle->pCertRequest);
}
if(lpHandle->pbChallengeData)
{
midl_user_free(lpHandle->pbChallengeData);
}
FreeMemory(lpHandle);
}
if(lpContext->m_ContextType == CONTEXTHANDLE_HYDRA_REQUESTCERT_TYPE)
{
//
// force calling TLSRpcRequestTermServCert() again
//
lpContext->m_ContextType = CONTEXTHANDLE_EMPTY_TYPE;
lpContext->m_ContextHandle = NULL;
}
InterlockedDecrement( &lpContext->m_RefCount );
lpContext->m_LastError=status;
#if DBG
lpContext->m_LastCall = RPC_CALL_RETRIEVE_TERMSRV_CERT;
#endif
*pdwErrCode = TLSMapReturnCode(status);
//
// Reset SE translator
//
_set_se_translator(old_trans_se_func);
return RPC_S_OK;
}
////////////////////////////////////////////////////////////////////////////
error_status_t
TLSRpcAuditLicenseKeyPack(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ DWORD dwKeyPackId,
/* [in] */ FILETIME ftStartTime,
/* [in] */ FILETIME ftEndTime,
/* [in] */ BOOL bResetCounter,
/* [ref][out][in] */ LPTLSKeyPackAudit lplsAudit,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
Not implemented yet!.
--*/
{
*pdwErrCode = TLSMapReturnCode(TLS_E_NOTSUPPORTED);
return RPC_S_OK;
}
////////////////////////////////////////////////////////////////////////////
error_status_t
TLSRpcGetLSPKCS10CertRequest(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ DWORD dwCertType,
/* [ref][out][in] */ PDWORD pcbData,
/* [size_is][size_is][out] */ PBYTE __RPC_FAR *ppbData,
/* [ref][out][in] */ PDWORD dwErrCode
)
/*
Abstract:
Note:
Only return our key at this time, not a PKCS10 request
*/
{
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
DWORD status=ERROR_SUCCESS;
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcGetLSPKCS10CertRequest\n"),
lpContext->m_Client
);
InterlockedIncrement( &lpContext->m_RefCount );
if(!(lpContext->m_ClientFlags & CLIENT_ACCESS_ADMIN))
{
status = TLS_E_ACCESS_DENIED;
goto cleanup;
}
if(AcquireAdministrativeLock(INFINITE) == TRUE)
{
status = RetrieveKey(
(dwCertType == TLSCERT_TYPE_EXCHANGE) ?
LSERVER_LSA_PRIVATEKEY_EXCHANGE :
LSERVER_LSA_PRIVATEKEY_SIGNATURE,
ppbData,
pcbData
);
ReleaseAdministrativeLock();
}
else
{
status = TLS_E_ALLOCATE_HANDLE;
}
cleanup:
lpContext->m_LastError=status;
InterlockedDecrement( &lpContext->m_RefCount );
#if DBG
lpContext->m_LastCall = RPC_CALL_GETPKCS10CERT_REQUEST;
#endif
*dwErrCode = TLSMapReturnCode(status);
return RPC_S_OK;
}
//////////////////////////////////////////////////////////////////////////////
//
// Replication function
//
////////////////////////////////////////////////////////////////////////////
error_status_t
TLSRpcBeginReplication(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [string][in] */ LPTSTR pszLsSetupId,
/* [string][in] */ LPTSTR pszLsServerName,
/* [in] */ DWORD cbDomainSid,
/* [size_is][in] */ PBYTE pbDomainSid,
/* [ref][out][in] */ FILETIME __RPC_FAR *pftLastBackupTime,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
++*/
{
*pdwErrCode = TLSMapReturnCode(TLS_E_NOTSUPPORTED);
return RPC_S_OK;
}
////////////////////////////////////////////////////////////////////////////
error_status_t
TLSRpcEndReplication(
/* [in] */ PCONTEXT_HANDLE phContext
)
/*++
++*/
{
return RPC_S_OK;
}
////////////////////////////////////////////////////////////////////////////
error_status_t
TLSRpcReplicateRecord(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [ref][in] */ PTLSReplRecord pReplRecord,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
++*/
{
*pdwErrCode = TLSMapReturnCode(TLS_E_NOTSUPPORTED);
return RPC_S_OK;
}
////////////////////////////////////////////////////////////////////////////
error_status_t
TLSRpcTableEnumBegin(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ DWORD dwSearchParam,
/* [ref][in] */ PTLSReplRecord pRecord,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
++*/
{
*pdwErrCode = TLSMapReturnCode(TLS_E_NOTSUPPORTED);
return RPC_S_OK;
}
////////////////////////////////////////////////////////////////////////////
error_status_t
TLSRpcTableEnumNext(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [ref][out][in] */ PTLSReplRecord pRecord,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
++*/
{
*pdwErrCode = TLSMapReturnCode(TLS_E_NOTSUPPORTED);
return RPC_S_OK;
}
////////////////////////////////////////////////////////////////////////////
error_status_t
TLSRpcTableEnumEnd(
/* [in] */ PCONTEXT_HANDLE phContext
)
/*++
++*/
{
return RPC_S_OK;
}
////////////////////////////////////////////////////////////////////////////
error_status_t
TLSRpcInstallPolicyModule(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [string][in] */ LPTSTR pszCompanyName,
/* [string][in] */ LPTSTR pszProductId,
/* [string][in] */ LPTSTR pszPolicyDllName,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
++*/
{
*pdwErrCode = TLSMapReturnCode(TLS_E_NOTSUPPORTED);
return RPC_S_OK;
}
////////////////////////////////////////////////////////////////////////////
error_status_t
TLSRpcAnnounceServer(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ DWORD dwAnnounceType,
/* [in] */ FILETIME __RPC_FAR *pLastStartupTime,
/* [string][in] */ LPTSTR pszSetupId,
/* [string][in] */ LPTSTR pszDomainName,
/* [string][in] */ LPTSTR pszLserverName,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
Abstract:
Private routine for other license server to announce presence of
itself.
Parameters:
Returns:
Note:
++*/
{
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
DWORD status = ERROR_SUCCESS;
BOOL bSuccess = TRUE;
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcAnnounceServer\n"),
lpContext->m_Client
);
InterlockedIncrement( &lpContext->m_RefCount );
__try {
//
// Verify it is a license server
//
if(lpContext->m_ClientFlags != CLIENT_ACCESS_LSERVER)
{
status = TLS_E_ACCESS_DENIED;
}
if( status == ERROR_SUCCESS &&
(dwAnnounceType == TLSANNOUNCE_TYPE_STARTUP || dwAnnounceType == TLSANNOUNCE_TYPE_RESPONSE) )
{
status = TLSRegisterServerWithName(
pszSetupId,
pszDomainName,
pszLserverName
);
if(status == TLS_E_DUPLICATE_RECORD)
{
status = ERROR_SUCCESS;
}
}
if(status == ERROR_SUCCESS)
{
if(dwAnnounceType == TLSANNOUNCE_TYPE_STARTUP)
{
//
// Prevent loop back, use job to response announce
//
status = TLSStartAnnounceResponseJob(
pszSetupId,
pszDomainName,
pszLserverName,
&g_ftLastShutdownTime
);
}
if(status == ERROR_SUCCESS)
{
// Create a CSSync workobject to sync. local LKP
status = TLSPushSyncLocalLkpToServer(
pszSetupId,
pszDomainName,
pszLserverName,
pLastStartupTime
);
}
else
{
// reset error code, can't connect back to server -
// server might be available anymore.
status = ERROR_SUCCESS;
}
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
status = GetExceptionCode();
}
lpContext->m_LastError=status;
InterlockedDecrement( &lpContext->m_RefCount );
#if DBG
lpContext->m_LastCall = RPC_CALL_ANNOUNCE_SERVER;
#endif
*pdwErrCode = TLSMapReturnCode(status);
return RPC_S_OK;
}
////////////////////////////////////////////////////////////////////////////
error_status_t
TLSRpcLookupServer(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [string][in] */ LPTSTR pszLookupSetupId,
/* [size_is][string][out][in] */ LPTSTR pszLsSetupId,
/* [out][in] */ PDWORD pcbSetupId,
/* [size_is][string][out][in] */ LPTSTR pszDomainName,
/* [ref][out][in] */ PDWORD pcbDomainName,
/* [size_is][string][out][in] */ LPTSTR pszMachineName,
/* [ref][out][in] */ PDWORD pcbMachineName,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
Abstract:
Look up a license server via a license server's setupId.
Parameters:
Returns:
Note:
++*/
{
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcLookupServer\n"),
lpContext->m_Client
);
InterlockedIncrement( &lpContext->m_RefCount );
TLServerInfo ServerInfo;
DWORD dwStatus = ERROR_SUCCESS;
__try {
if(_tcsicmp(pszLookupSetupId, g_pszServerPid) == 0)
{
_tcsncpy(
pszLsSetupId,
g_pszServerPid,
min(_tcslen(g_pszServerPid), *pcbSetupId)
);
if(*pcbSetupId <= _tcslen(g_pszServerPid))
{
dwStatus = TLS_E_INVALID_DATA;
}
else
{
pszLsSetupId[min(_tcslen(g_pszServerPid), *pcbSetupId - 1)] = _TEXT('\0');
}
*pcbSetupId = _tcslen(g_pszServerPid) + 1;
//--------------------------------------------------------------
_tcsncpy(
pszDomainName,
g_szScope,
min(_tcslen(g_szScope), *pcbDomainName)
);
if(*pcbDomainName <= _tcslen(g_szScope))
{
dwStatus = TLS_E_INVALID_DATA;
}
else
{
pszDomainName[min(_tcslen(g_szScope), *pcbDomainName - 1)] = _TEXT('\0');
}
*pcbDomainName = _tcslen(g_szScope) + 1;
//--------------------------------------------------------------
_tcsncpy(
pszMachineName,
g_szComputerName,
min(_tcslen(g_szComputerName), *pcbMachineName)
);
if(*pcbMachineName <= _tcslen(g_szComputerName))
{
dwStatus = TLS_E_INVALID_DATA;
}
else
{
pszMachineName[min(_tcslen(g_szComputerName), *pcbMachineName - 1)] = _TEXT('\0');
}
*pcbMachineName = _tcslen(g_szComputerName) + 1;
}
else
{
dwStatus = TLSLookupRegisteredServer(
pszLookupSetupId,
NULL,
pszMachineName,
&ServerInfo
);
if(dwStatus == ERROR_SUCCESS)
{
_tcsncpy(
pszLsSetupId,
ServerInfo.GetServerId(),
min(_tcslen(ServerInfo.GetServerId()), *pcbSetupId)
);
if(*pcbSetupId <= _tcslen(ServerInfo.GetServerId()))
{
dwStatus = TLS_E_INVALID_DATA;
}
else
{
pszLsSetupId[min(_tcslen(ServerInfo.GetServerId()), *pcbSetupId - 1)] = _TEXT('\0');
}
*pcbSetupId = _tcslen(ServerInfo.GetServerId()) + 1;
//--------------------------------------------------------------
_tcsncpy(
pszDomainName,
ServerInfo.GetServerDomain(),
min(_tcslen(ServerInfo.GetServerDomain()), *pcbDomainName)
);
if(*pcbDomainName <= _tcslen(ServerInfo.GetServerDomain()))
{
dwStatus = TLS_E_INVALID_DATA;
}
else
{
pszDomainName[min(_tcslen(ServerInfo.GetServerDomain()), *pcbDomainName - 1)] = _TEXT('\0');
}
*pcbDomainName = _tcslen(ServerInfo.GetServerDomain()) + 1;
//--------------------------------------------------------------
_tcsncpy(
pszMachineName,
ServerInfo.GetServerName(),
min(_tcslen(ServerInfo.GetServerName()), *pcbMachineName)
);
if(*pcbMachineName <= _tcslen(ServerInfo.GetServerName()))
{
dwStatus = TLS_E_INVALID_DATA;
}
else
{
pszMachineName[min(_tcslen(ServerInfo.GetServerName()), *pcbMachineName - 1)] = _TEXT('\0');
}
*pcbMachineName = _tcslen(ServerInfo.GetServerName()) + 1;
}
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
dwStatus = GetExceptionCode();
}
lpContext->m_LastError=dwStatus;
InterlockedDecrement( &lpContext->m_RefCount );
#if DBG
lpContext->m_LastCall = RPC_CALL_SERVERLOOKUP;
#endif
*pdwErrCode = TLSMapReturnCode(dwStatus);
return RPC_S_OK;
}
////////////////////////////////////////////////////////////////////////////
error_status_t
TLSRpcAnnounceLicensePack(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ PTLSReplRecord pReplRecord,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
Abstract:
Private routine for one license server to announce it has particular
License Pack.
Parameters:
Returns:
++*/
{
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
DWORD dwStatus=ERROR_SUCCESS;
PTLSDbWorkSpace pDbWkSpace=NULL;
_se_translator_function old_trans_se_func = NULL;
old_trans_se_func = _set_se_translator( trans_se_func );
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcAnnounceLicensePack\n"),
lpContext->m_Client
);
InterlockedIncrement( &lpContext->m_RefCount );
if(lpContext->m_ClientFlags != CLIENT_ACCESS_LSERVER)
{
dwStatus = TLS_E_ACCESS_DENIED;
goto cleanup;
}
if(pReplRecord->dwUnionType != UNION_TYPE_LICENSEPACK)
{
dwStatus = TLS_E_INVALID_DATA;
goto cleanup;
}
if(!ALLOCATEDBHANDLE(pDbWkSpace, g_GeneralDbTimeout))
{
dwStatus = TLS_E_ALLOCATE_HANDLE;
goto cleanup;
}
CLEANUPSTMT;
BEGIN_TRANSACTION(pDbWkSpace);
try {
TLSLICENSEPACK LicPack;
LicPack = pReplRecord->w.ReplLicPack;
//
// TODO - verify input parameters
//
dwStatus = TLSDBRemoteKeyPackAdd(
USEHANDLE(pDbWkSpace),
&LicPack
);
}
catch( SE_Exception e ) {
dwStatus = e.getSeNumber();
}
catch(...) {
dwStatus = TLS_E_INTERNAL;
}
if(TLS_ERROR(dwStatus) && dwStatus != TLS_E_DUPLICATE_RECORD)
{
ROLLBACK_TRANSACTION(pDbWkSpace);
}
else
{
COMMIT_TRANSACTION(pDbWkSpace);
}
FREEDBHANDLE(pDbWkSpace);
cleanup:
lpContext->m_LastError=dwStatus;
InterlockedDecrement( &lpContext->m_RefCount );
#if DBG
lpContext->m_LastCall = RPC_CALL_ANNOUNCELICENSEPACK;
#endif
*pdwErrCode = TLSMapReturnCode(dwStatus);
//
// Reset SE translator
//
_set_se_translator(old_trans_se_func);
return RPC_S_OK;
}
////////////////////////////////////////////////////////////////////////////
error_status_t
TLSRpcReturnLicensedProduct(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ PTLSLicenseToBeReturn pClientLicense,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
++*/
{
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
DWORD dwStatus=ERROR_SUCCESS;
CTLSPolicy* pPolicy=NULL;
PTLSDbWorkSpace pDbWorkSpace;
PMHANDLE hClient;
_se_translator_function old_trans_se_func = NULL;
old_trans_se_func = _set_se_translator( trans_se_func );
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcReturnLicensedProduct\n"),
lpContext->m_Client
);
InterlockedIncrement( &lpContext->m_RefCount );
if(lpContext->m_ClientFlags != CLIENT_ACCESS_LSERVER)
{
dwStatus = TLS_E_ACCESS_DENIED;
goto cleanup;
}
pPolicy = AcquirePolicyModule(
pClientLicense->pszCompanyName,
pClientLicense->pszOrgProductId,
FALSE
);
if(pPolicy == NULL)
{
dwStatus = GetLastError();
goto cleanup;
}
hClient = GenerateClientId();
if(!ALLOCATEDBHANDLE(pDbWkSpace, g_GeneralDbTimeout))
{
dwStatus=TLS_E_ALLOCATE_HANDLE;
goto cleanup;
}
CLEANUPSTMT;
BEGIN_TRANSACTION(pDbWorkSpace);
try {
dwStatus = TLSReturnClientLicensedProduct(
USEHANDLE(pDbWkSpace),
hClient,
pPolicy,
pClientLicense
);
}
catch( SE_Exception e ) {
dwStatus = e.getSeNumber();
}
catch(...) {
SetLastError(dwStatus = TLS_E_INTERNAL);
}
if(TLS_ERROR(dwStatus))
{
ROLLBACK_TRANSACTION(pDbWorkSpace);
}
else
{
COMMIT_TRANSACTION(pDbWorkSpace);
}
FREEDBHANDLE(pDbWorkSpace);
cleanup:
lpContext->m_LastError=dwStatus;
InterlockedDecrement( &lpContext->m_RefCount );
#if DBG
lpContext->m_LastCall = RPC_CALL_RETURNLICENSE;
#endif
*pdwErrCode = TLSMapReturnCode(dwStatus);
if(pPolicy)
{
pPolicy->PMLicenseRequest(
hClient,
REQUEST_COMPLETE,
UlongToPtr (dwStatus),
NULL
);
ReleasePolicyModule(pPolicy);
}
_set_se_translator(old_trans_se_func);
return RPC_S_OK;
}
////////////////////////////////////////////////////////////////////////////
error_status_t
TLSRpcChallengeServer(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ DWORD dwClientType,
/* [in] */ PTLSCHALLENGEDATA pClientChallenge,
/* [out][in] */ PTLSCHALLENGERESPONSEDATA* pServerResponse,
/* [out][in] */ PTLSCHALLENGEDATA* pServerChallenge,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
Abstract:
Private routine for client to challenge server in order for client
confirm server's identity. License Server, in addition to response to
client's challenge, also generate random challenge data based on
client's self-declare type back to client.
Parameter:
phContext : Client's context handle.
dwClientType : Client self-pronounce type, valid values are ...
pClientChallenge : Client challenge data.
pServerResponse : Server's responses to client's challenge.
pServerChallenge : Server's challenge to client.
pdwErrCode : Error code if failed.
Returns:
Notes:
Private routine for LrWiz and License Server to identify itself.
--*/
{
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
DWORD status=ERROR_SUCCESS;
PTLSCHALLENGEDATA pChallenge=NULL;
PTLSCHALLENGERESPONSEDATA pResponse = NULL;
HCRYPTPROV hProv = NULL;
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcChallengeServer\n"),
lpContext->m_Client
);
InterlockedIncrement( &lpContext->m_RefCount );
//if(!(lpContext->m_ClientFlags & CLIENT_ACCESS_ADMIN))
//{
// status = TLS_E_ACCESS_DENIED;
// goto cleanup;
//}
if(lpContext->m_ContextType != CONTEXTHANDLE_EMPTY_TYPE)
{
status = TLS_E_INVALID_SEQUENCE;
goto cleanup;
}
//
// Input parameters...
//
if( pClientChallenge == NULL ||
pServerResponse == NULL ||
pServerChallenge == NULL )
{
status = TLS_E_INVALID_DATA;
goto cleanup;
}
//
// Verify Data send by client
//
if( pClientChallenge->dwVersion != TLS_CURRENT_CHALLENGE_VERSION ||
pClientChallenge->cbChallengeData == 0 ||
pClientChallenge->pbChallengeData == NULL )
{
status = TLS_E_INVALID_DATA;
goto cleanup;
}
pResponse = (PTLSCHALLENGERESPONSEDATA)midl_user_allocate(sizeof(TLSCHALLENGERESPONSEDATA));
if(pResponse == NULL)
{
status = GetLastError();
goto cleanup;
}
pChallenge = (PTLSCHALLENGEDATA)AllocateMemory(sizeof(TLSCHALLENGEDATA));
if(pChallenge == NULL)
{
status = GetLastError();
goto cleanup;
}
*pServerChallenge = (PTLSCHALLENGEDATA)midl_user_allocate(sizeof(TLSCHALLENGEDATA));
if(*pServerChallenge == NULL)
{
status = GetLastError();
goto cleanup;
}
//
// Generate Challenge response data
//
status = TLSGenerateChallengeResponseData(
g_hCryptProv,
dwClientType,
pClientChallenge,
&(pResponse->pbResponseData),
&(pResponse->cbResponseData)
);
if(status != ERROR_SUCCESS)
{
status = TLS_E_INVALID_DATA;
goto cleanup;
}
//
// Generate Server side challenge data
//
pChallenge->dwVersion = TLS_CURRENT_CHALLENGE_VERSION;
if (CryptAcquireContext(&hProv,NULL,NULL,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT)) {
if (!CryptGenRandom(hProv,sizeof(pChallenge->dwRandom), (BYTE *) &pChallenge->dwRandom)) {
status = TLS_E_INTERNAL;
goto cleanup;
}
} else {
status = TLS_E_INTERNAL;
goto cleanup;
}
//
// This must range from 1 to 128, as it's used as an offset into the
// challenge data buffer
//
pChallenge->dwRandom %= RANDOM_CHALLENGE_DATASIZE;
pChallenge->dwRandom++;
status = TLSGenerateRandomChallengeData(
g_hCryptProv,
&(pChallenge->pbChallengeData),
&(pChallenge->cbChallengeData)
);
// base on type, mark this handle...
if(dwClientType == CLIENT_TYPE_LRWIZ)
{
lpContext->m_ContextType = CONTEXTHANDLE_CHALLENGE_LRWIZ_TYPE;
}
else
{
lpContext->m_ContextType = CONTEXTHANDLE_CHALLENGE_SERVER_TYPE;
}
(*pServerChallenge)->pbChallengeData = (PBYTE)midl_user_allocate(pChallenge->cbChallengeData);
if((*pServerChallenge)->pbChallengeData == NULL)
{
status = GetLastError();
goto cleanup;
}
(*pServerChallenge)->dwVersion = TLS_CURRENT_CHALLENGE_VERSION;
(*pServerChallenge)->dwRandom = pChallenge->dwRandom;
(*pServerChallenge)->cbChallengeData = pChallenge->cbChallengeData;
memcpy(
(*pServerChallenge)->pbChallengeData,
pChallenge->pbChallengeData,
pChallenge->cbChallengeData
);
lpContext->m_ContextHandle = (HANDLE)(pChallenge);
*pServerResponse = pResponse;
cleanup:
if(status != ERROR_SUCCESS)
{
if(pChallenge)
{
if(pChallenge->pbChallengeData)
{
FreeMemory(pChallenge->pbChallengeData);
}
if(pChallenge->pbReservedData)
{
FreeMemory(pChallenge->pbReservedData);
}
FreeMemory(pChallenge);
}
if(pResponse)
{
if(pResponse->pbResponseData)
{
FreeMemory(pResponse->pbResponseData);
}
if(pResponse->pbReservedData)
{
FreeMemory(pResponse->pbReservedData);
}
midl_user_free(pResponse);
}
}
if (hProv)
CryptReleaseContext(hProv,0);
lpContext->m_LastError=status;
InterlockedDecrement( &lpContext->m_RefCount );
#if DBG
lpContext->m_LastCall = RPC_CALL_CHALLENGESERVER;
#endif
*pdwErrCode = TLSMapReturnCode(status);
return RPC_S_OK;
}
////////////////////////////////////////////////////////////////////////////
error_status_t
TLSRpcResponseServerChallenge(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ PTLSCHALLENGERESPONSEDATA pClientResponse,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
Abstract:
Client's responses to Server challenge returned TLSRpcChallengeServer(),
must have call TLSRpcChallengeServer().
Parameter:
phContext:
pClientResponses: Client's response to server's challenge.
pdwErrCode : Return error code.
Returns:
Note:
--*/
{
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
DWORD status=ERROR_SUCCESS;
DWORD dwClientType;
PTLSCHALLENGEDATA pServerToClientChallenge;
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcResponseServerChallenge\n"),
lpContext->m_Client
);
InterlockedIncrement( &lpContext->m_RefCount );
//if(!(lpContext->m_ClientFlags & CLIENT_ACCESS_ADMIN))
//{
// status = TLS_E_ACCESS_DENIED;
// goto cleanup;
//}
if( pClientResponse == NULL ||
pClientResponse->pbResponseData == NULL ||
pClientResponse->cbResponseData == 0 )
{
status = TLS_E_INVALID_DATA;
goto cleanup;
}
if(lpContext->m_ContextType != CONTEXTHANDLE_CHALLENGE_SERVER_TYPE &&
lpContext->m_ContextType != CONTEXTHANDLE_CHALLENGE_LRWIZ_TYPE)
{
status = TLS_E_INVALID_SEQUENCE;
goto cleanup;
}
if(lpContext->m_ContextHandle == NULL)
{
status = TLS_E_INTERNAL;
goto cleanup;
}
if(lpContext->m_ContextType == CONTEXTHANDLE_CHALLENGE_LRWIZ_TYPE)
{
dwClientType = CLIENT_TYPE_LRWIZ;
}
else
{
dwClientType = CLIENT_TYPE_TLSERVER;
}
pServerToClientChallenge = (PTLSCHALLENGEDATA)lpContext->m_ContextHandle;
//
// base on client type, verify challenge response data
//
status = TLSVerifyChallengeResponse(
g_hCryptProv,
dwClientType,
pServerToClientChallenge,
pClientResponse
);
if(status != ERROR_SUCCESS)
{
status = TLS_E_INVALID_DATA;
}
else
{
if(dwClientType == CLIENT_TYPE_LRWIZ)
{
lpContext->m_ClientFlags |= CLIENT_ACCESS_LRWIZ;
}
else
{
lpContext->m_ClientFlags |= CLIENT_ACCESS_LSERVER;
}
}
if(pServerToClientChallenge != NULL)
{
FreeMemory(pServerToClientChallenge->pbChallengeData);
FreeMemory(pServerToClientChallenge);
}
lpContext->m_ContextHandle = NULL;
lpContext->m_ContextType = CONTEXTHANDLE_EMPTY_TYPE;
cleanup:
lpContext->m_LastError=status;
InterlockedDecrement( &lpContext->m_RefCount );
#if DBG
lpContext->m_LastCall = RPC_CALL_RESPONSESERVERCHALLENGE;
#endif
*pdwErrCode = TLSMapReturnCode(status);
return RPC_S_OK;
}
////////////////////////////////////////////////////////////////////////////
error_status_t
TLSRpcGetTlsPrivateData(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ DWORD dwPrivateDataType,
/* [switch_is][in] */ PTLSPrivateDataUnion pSearchData,
/* [ref][out][in] */ PDWORD pdwRetDataType,
/* [switch_is][out] */ PTLSPrivateDataUnion __RPC_FAR *ppPrivateData,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
Abstract:
Retrieve license server's private data, this include Server's
unique ID, PID, and registered SPK if any.
Parameters:
phContext : Client's context handle.
dwPrivateDataType : Type of private data interested.
pSearchData : Type of data to search, currently ignore.
pdwRetDataType : Return data type.
ppPrivateData : License Server's private data.
pdwErrCode : Error Code.
Returns:
Note:
Only LrWiz and License Server can invoke this RPC call.
--*/
{
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
DWORD status=ERROR_SUCCESS;
DWORD cbSource=0;
PBYTE pbSource=NULL;
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcGetTlsPrivateData\n"),
lpContext->m_Client
);
InterlockedIncrement( &lpContext->m_RefCount );
//
// relax restriction on who can get private data
//
if( dwPrivateDataType != TLS_PRIVATEDATA_PID &&
dwPrivateDataType != TLS_PRIVATEDATA_UNIQUEID )
{
if(!(lpContext->m_ClientFlags & CLIENT_ACCESS_LRWIZ))
{
status = TLS_E_ACCESS_DENIED;
goto cleanup;
}
}
if( dwPrivateDataType < TLS_PRIVATEDATA_MIN ||
dwPrivateDataType > TLS_PRIVATEDATA_MAX )
{
status = TLS_E_INVALID_DATA;
goto cleanup;
}
//
// Not supported yet...
//
if(dwPrivateDataType == TLS_PRIVATEDATA_INSTALLED_CERT)
{
status = TLS_E_NOTSUPPORTED;
goto cleanup;
}
//
// Don't really need this but we might need to support
// re-generate of License Server ID
//
if(!AcquireAdministrativeLock(INFINITE))
{
status = TLS_E_ALLOCATE_HANDLE;
goto cleanup;
}
switch(dwPrivateDataType)
{
case TLS_PRIVATEDATA_UNIQUEID:
pbSource = (PBYTE)g_pszServerUniqueId;
cbSource = g_cbServerUniqueId;
break;
case TLS_PRIVATEDATA_PID:
pbSource = (PBYTE)g_pszServerPid;
cbSource = g_cbServerPid;
break;
case TLS_PRIVATEDATA_SPK:
pbSource = g_pbServerSPK;
cbSource = g_cbServerSPK;
}
//
// Currently, what you ask is what you get.
//
*pdwRetDataType = dwPrivateDataType;
if( (dwPrivateDataType != TLS_PRIVATEDATA_SYSTEMLANGID) &&
(pbSource == NULL || cbSource == 0) )
{
status = TLS_E_RECORD_NOTFOUND;
}
else
{
*ppPrivateData = (PTLSPrivateDataUnion)midl_user_allocate(sizeof(TLSPrivateDataUnion));
if(*ppPrivateData != NULL)
{
memset(
*ppPrivateData,
0,
sizeof(TLSPrivateDataUnion)
);
if(*pdwRetDataType == TLS_PRIVATEDATA_SYSTEMLANGID)
{
(*ppPrivateData)->systemLangId = GetSystemDefaultLangID();
}
else if(*pdwRetDataType == TLS_PRIVATEDATA_SPK)
{
(*ppPrivateData)->SPK.cbSPK = cbSource;
(*ppPrivateData)->SPK.pbSPK = pbSource;
(*ppPrivateData)->SPK.pCertExtensions = g_pCertExtensions;
//(*ppPrivateData)->SPK.pCertExtensions = (PTLSCERT_EXTENSIONS)midl_user_allocate(g_cbCertExtensions);
//memcpy(
// (*ppPrivateData)->SPK.pCertExtensions,
// g_pCertExtensions,
// g_cbCertExtensions
// );
}
else
{
(*ppPrivateData)->BinaryData.cbData = cbSource;
(*ppPrivateData)->BinaryData.pbData = pbSource;
}
}
else
{
status = ERROR_OUTOFMEMORY;
}
}
ReleaseAdministrativeLock();
cleanup:
lpContext->m_LastError=status;
InterlockedDecrement( &lpContext->m_RefCount );
#if DBG
lpContext->m_LastCall = RPC_CALL_GETPRIVATEDATA;
#endif
*pdwErrCode = TLSMapReturnCode(status);
return RPC_S_OK;
}
////////////////////////////////////////////////////////////////////////////
error_status_t
TLSRpcSetTlsPrivateData(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ DWORD dwPrivateDataType,
/* [switch_is][in] */ PTLSPrivateDataUnion pPrivateData,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
Abstract:
Private routine for LrWiz to set license server's private data.
Parameter:
phContext: Client context handle.
dwPrivateDataType : Type of private data to set.
pPrivateData : Private data to set/install.
pdwErrCode : Server return code.
Returns:
Note:
Only support installing of SPK/Extension at this time.
--*/
{
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
DWORD status=ERROR_SUCCESS;
DWORD dwSpkVerifyResult;
_se_translator_function old_trans_se_func = NULL;
old_trans_se_func = _set_se_translator( trans_se_func );
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcDepositeSPK\n"),
lpContext->m_Client
);
InterlockedIncrement( &lpContext->m_RefCount );
if(!(lpContext->m_ClientFlags & CLIENT_ACCESS_LRWIZ))
{
status = TLS_E_ACCESS_DENIED;
goto cleanup;
}
//
// Only support SPK at this time
//
if(dwPrivateDataType != TLS_PRIVATEDATA_SPK)
{
status = TLS_E_INVALID_DATA;
goto cleanup;
}
//
// Lock all RPC calls related to issuing certificate
//
if(!AcquireRPCExclusiveLock(INFINITE))
{
status = TLS_E_ALLOCATE_HANDLE;
goto cleanup;
}
do {
//if(g_pbServerSPK != NULL && g_cbServerSPK != 0)
//{
// status = TLS_E_SPKALREADYEXIST;
// break;
//}
if(AcquireAdministrativeLock(INFINITE))
{
try {
status = TLSReGenSelfSignCert(
g_hCryptProv,
pPrivateData->SPK.pbSPK,
pPrivateData->SPK.cbSPK,
pPrivateData->SPK.pCertExtensions->cExtension,
pPrivateData->SPK.pCertExtensions->rgExtension
);
}
catch( SE_Exception e ) {
status = e.getSeNumber();
}
catch(...) {
status = TLS_E_INTERNAL;
}
ReleaseAdministrativeLock();
}
else
{
status = TLS_E_ALLOCATE_HANDLE;
}
} while(FALSE);
ReleaseRPCExclusiveLock();
cleanup:
lpContext->m_LastError=status;
InterlockedDecrement( &lpContext->m_RefCount );
#if DBG
lpContext->m_LastCall = RPC_CALL_SETPRIVATEDATA;
#endif
*pdwErrCode = TLSMapReturnCode(status);
//
// Reset SE translator
//
_set_se_translator(old_trans_se_func);
return RPC_S_OK;
}
////////////////////////////////////////////////////////////////////////////
error_status_t
TLSRpcTriggerReGenKey(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ BOOL bRegenKey,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
Abstract:
Private routine to force license server to re-generate its
public/private key pair, all installed certificates/SPK are
deleted, User are required to re-register license server.
Parameters:
phContext : Client context handle.
bKeepSPKAndExtension : For future use only.
pdwErrCode : Return error code.
Returns:
++*/
{
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
DWORD status=ERROR_SUCCESS;
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcTriggerReGenKey\n"),
lpContext->m_Client
);
_se_translator_function old_trans_se_func = NULL;
old_trans_se_func = _set_se_translator( trans_se_func );
InterlockedIncrement( &lpContext->m_RefCount );
if(!(lpContext->m_ClientFlags & CLIENT_ACCESS_LRWIZ))
{
status = TLS_E_ACCESS_DENIED;
goto cleanup;
}
LPCTSTR pString[1];
pString[0] = lpContext->m_Client;
TLSLogEventString(
EVENTLOG_INFORMATION_TYPE,
TLS_I_TRIGGER_REGENKEY,
1,
pString
);
//
// Block ALL RPC calls
//
if(!AcquireRPCExclusiveLock(INFINITE))
{
status=TLS_E_ALLOCATE_HANDLE;
goto cleanup;
}
do {
if(!AcquireAdministrativeLock(INFINITE))
{
status = TLS_E_ALLOCATE_HANDLE;
break;
}
try {
status = TLSReGenKeysAndReloadServerCert(
bRegenKey
);
}
catch( SE_Exception e ) {
status = e.getSeNumber();
}
catch(...) {
status = TLS_E_INTERNAL;
}
ReleaseAdministrativeLock();
} while(FALSE);
ReleaseRPCExclusiveLock();
cleanup:
lpContext->m_LastError=status;
InterlockedDecrement( &lpContext->m_RefCount );
#if DBG
lpContext->m_LastCall = RPC_CALL_TRIGGERREGENKEY;
#endif
*pdwErrCode = TLSMapReturnCode(status);
//
// Reset SE translator
//
_set_se_translator(old_trans_se_func);
return RPC_S_OK;
}
////////////////////////////////////////////////////////////////////////////
error_status_t
TLSRpcTelephoneRegisterLKP(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ DWORD cbData,
/* [size_is][in] */ PBYTE pbData,
/* [ref][out] */ PDWORD pdwErrCode
)
/*++
--*/
{
DWORD status=ERROR_SUCCESS;
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
PTLSDbWorkSpace pDbWkSpace;
LSKeyPack keypack;
_se_translator_function old_trans_se_func = NULL;
old_trans_se_func = _set_se_translator( trans_se_func );
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcTelephoneRegisterLKP\n"),
lpContext->m_Client
);
InterlockedIncrement( &lpContext->m_RefCount );
if(!(lpContext->m_ClientFlags & CLIENT_ACCESS_LRWIZ))
{
status = TLS_E_ACCESS_DENIED;
goto cleanup;
}
if(!ALLOCATEDBHANDLE(pDbWkSpace, g_GeneralDbTimeout))
{
status=TLS_E_ALLOCATE_HANDLE;
goto cleanup;
}
CLEANUPSTMT;
BEGIN_TRANSACTION(pDbWkSpace);
try {
status = TLSDBTelephoneRegisterLicenseKeyPack(
USEHANDLE(pDbWkSpace),
g_pszServerPid,
pbData,
cbData,
&keypack
);
}
catch( SE_Exception e ) {
status = e.getSeNumber();
}
catch(...) {
status = TLS_E_INTERNAL;
}
if(TLS_ERROR(status))
{
ROLLBACK_TRANSACTION(pDbWkSpace);
}
else
{
COMMIT_TRANSACTION(pDbWkSpace);
}
FREEDBHANDLE(pDbWkSpace);
//
// Post a sync work object
//
if(status == ERROR_SUCCESS)
{
if(TLSAnnounceLKPToAllRemoteServer(
keypack.dwKeyPackId,
0
) != ERROR_SUCCESS)
{
TLSLogWarningEvent(TLS_W_ANNOUNCELKP_FAILED);
}
}
cleanup:
lpContext->m_LastError=status;
InterlockedDecrement( &lpContext->m_RefCount );
#if DBG
lpContext->m_LastCall = RPC_CALL_TELEPHONEREGISTERLKP;
#endif
*pdwErrCode = TLSMapReturnCode(status);
//
// Reset SE translator
//
_set_se_translator(old_trans_se_func);
return RPC_S_OK;
}
////////////////////////////////////////////////////////////////////////////
error_status_t
TLSRpcAllocateInternetLicense(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ const CHALLENGE_CONTEXT ChallengeContext,
/* [in] */ const PTLSLICENSEREQUEST pRequest,
/* [string][in] */ LPTSTR pMachineName,
/* [string][in] */ LPTSTR pUserName,
/* [in] */ const DWORD cbChallengeResponse,
/* [size_is][in] */ const PBYTE pbChallengeResponse,
/* [out] */ PDWORD pcbLicense,
/* [size_is][size_is][out] */ BYTE __RPC_FAR *__RPC_FAR *pbLicense,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
--*/
{
return TLSRpcRequestNewLicense(
phContext,
ChallengeContext,
pRequest,
pMachineName,
pUserName,
cbChallengeResponse,
pbChallengeResponse,
FALSE,
pcbLicense,
pbLicense,
pdwErrCode
);
}
////////////////////////////////////////////////////////////////////////////
error_status_t
TLSRpcAllocateInternetLicenseEx(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ const CHALLENGE_CONTEXT ChallengeContext,
/* [in] */ const PTLSLICENSEREQUEST pRequest,
/* [string][in] */ LPTSTR pMachineName,
/* [string][in] */ LPTSTR pUserName,
/* [in] */ const DWORD cbChallengeResponse,
/* [size_is][in] */ const PBYTE pbChallengeResponse,
/* [ref][out] */ PTLSInternetLicense pInternetLicense,
/* [ref][out] */ PDWORD pdwErrCode
)
/*++
--*/
{
PBYTE pbLicense = NULL;
DWORD cbLicense = 0;
DWORD dwStatus = ERROR_SUCCESS;
DWORD index = 0;
PLICENSEDPRODUCT pLicensedProduct = NULL;
DWORD dwNumLicensedProduct = 0;
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
if(lpContext == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto cleanup;
}
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcAllocateInternetLicenseEx\n"),
lpContext->m_Client
);
//
// Internally forward the request.
//
dwStatus = TLSRpcAllocateInternetLicense(
phContext,
ChallengeContext,
pRequest,
pMachineName,
pUserName,
cbChallengeResponse,
pbChallengeResponse,
&cbLicense,
&pbLicense,
pdwErrCode
);
if(*pdwErrCode >= LSERVER_ERROR_BASE)
{
goto cleanup;
}
//
// decode the license.
//
dwStatus = LSVerifyDecodeClientLicense(
pbLicense,
cbLicense,
g_pbSecretKey,
g_cbSecretKey,
&dwNumLicensedProduct,
pLicensedProduct
);
//
// Internet license can only have one licensed product
//
if(dwStatus != LICENSE_STATUS_OK || dwNumLicensedProduct == 0 || dwNumLicensedProduct > 1)
{
dwStatus = TLS_E_INTERNAL;
goto cleanup;
}
pLicensedProduct = (PLICENSEDPRODUCT)AllocateMemory(
dwNumLicensedProduct * sizeof(LICENSEDPRODUCT)
);
if(pLicensedProduct == NULL)
{
dwStatus = TLS_E_ALLOCATE_MEMORY;
goto cleanup;
}
dwStatus = LSVerifyDecodeClientLicense(
pbLicense,
cbLicense,
g_pbSecretKey,
g_cbSecretKey,
&dwNumLicensedProduct,
pLicensedProduct
);
if(dwStatus != LICENSE_STATUS_OK)
{
dwStatus = TLS_E_INTERNAL;
goto cleanup;
}
//
// Sets up returns.
//
SAFESTRCPY(pInternetLicense->szServerId, pLicensedProduct->szIssuerId);
SAFESTRCPY(pInternetLicense->szServerName, pLicensedProduct->szIssuer);
pInternetLicense->ulSerialNumber = pLicensedProduct->ulSerialNumber;
pInternetLicense->dwQuantity = pLicensedProduct->dwQuantity;
cleanup:
lpContext->m_LastError=dwStatus;
InterlockedDecrement( &lpContext->m_RefCount );
#if DBG
lpContext->m_LastCall = RPC_CALL_ALLOCATEINTERNETLICNESEEX;
#endif
if(*pdwErrCode == ERROR_SUCCESS)
{
*pdwErrCode = TLSMapReturnCode(dwStatus);
}
if(pLicensedProduct != NULL)
{
for(index =0; index < dwNumLicensedProduct; index++)
{
LSFreeLicensedProduct(pLicensedProduct+index);
}
FreeMemory(pLicensedProduct);
}
if(pbLicense != NULL)
{
midl_user_free(pbLicense);
}
return RPC_S_OK;
}
////////////////////////////////////////////////////////////////////////////
error_status_t
TLSRpcReturnInternetLicenseEx(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ const PTLSLICENSEREQUEST pRequest,
/* [in] */ const ULARGE_INTEGER __RPC_FAR *pulSerialNumber,
/* [in] */ DWORD dwQuantity,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
--*/
{
DWORD dwStatus = ERROR_SUCCESS;
TLSLicenseToBeReturn TobeReturn;
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
PTLSDbWorkSpace pDbWorkSpace = NULL;
CTLSPolicy* pPolicy = NULL;
PMHANDLE hClient;
PMLICENSEREQUEST PMLicenseRequest;
PPMLICENSEREQUEST pAdjustedRequest;
TCHAR szCompanyName[LSERVER_MAX_STRING_SIZE+2];
TCHAR szProductId[LSERVER_MAX_STRING_SIZE+2];
_se_translator_function old_trans_se_func = NULL;
old_trans_se_func = _set_se_translator( trans_se_func );
if(VerifyLicenseRequest(pRequest) == FALSE)
{
SetLastError(dwStatus = TLS_E_INVALID_DATA);
goto cleanup;
}
if(lpContext == NULL)
{
SetLastError(dwStatus = ERROR_INVALID_PARAMETER);
goto cleanup;
}
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcReturnInternetLicenseEx\n"),
lpContext->m_Client
);
InterlockedIncrement( &lpContext->m_RefCount );
if(!(lpContext->m_ClientFlags & CLIENT_ACCESS_REQUEST))
{
dwStatus = TLS_E_ACCESS_DENIED;
goto cleanup;
}
memset(szCompanyName, 0, sizeof(szCompanyName));
memset(szProductId, 0, sizeof(szProductId));
memcpy(
szCompanyName,
pRequest->ProductInfo.pbCompanyName,
min(pRequest->ProductInfo.cbCompanyName, sizeof(szCompanyName)-sizeof(TCHAR))
);
memcpy(
szProductId,
pRequest->ProductInfo.pbProductID,
min(pRequest->ProductInfo.cbProductID, sizeof(szProductId)-sizeof(TCHAR))
);
//
// Allocate policy module, must have the right policy module to
// return license.
//
pPolicy = AcquirePolicyModule(
szCompanyName,
szProductId,
TRUE
);
if(pPolicy == NULL)
{
dwStatus = GetLastError();
goto cleanup;
}
hClient = GenerateClientId();
//
// Convert request to PMLICENSEREQUEST
//
TlsLicenseRequestToPMLicenseRequest(
LICENSETYPE_LICENSE,
pRequest,
_TEXT(""),
_TEXT(""),
0,
&PMLicenseRequest
);
//
// Ask policy module the actual product ID
//
dwStatus = pPolicy->PMLicenseRequest(
hClient,
REQUEST_NEW,
(PVOID) &PMLicenseRequest,
(PVOID *) &pAdjustedRequest
);
memset(&TobeReturn, 0, sizeof(TobeReturn));
TobeReturn.dwQuantity = dwQuantity;
TobeReturn.dwKeyPackId = pulSerialNumber->HighPart;
TobeReturn.dwLicenseId = pulSerialNumber->LowPart;
TobeReturn.dwPlatformID = pAdjustedRequest->dwPlatformId;
TobeReturn.cbEncryptedHwid = pRequest->cbEncryptedHwid;
TobeReturn.pbEncryptedHwid = pRequest->pbEncryptedHwid;
TobeReturn.dwProductVersion = pAdjustedRequest->dwProductVersion;
TobeReturn.pszOrgProductId = szProductId;
TobeReturn.pszCompanyName = szCompanyName;
TobeReturn.pszProductId = pAdjustedRequest->pszProductId;
//
// Allocate DB handle
//
if(!ALLOCATEDBHANDLE(pDbWkSpace, g_GeneralDbTimeout))
{
dwStatus = TLS_E_ALLOCATE_HANDLE;
goto cleanup;
}
CLEANUPSTMT;
BEGIN_TRANSACTION(pDbWorkSpace);
try {
dwStatus = TLSReturnClientLicensedProduct(
USEHANDLE(pDbWkSpace),
hClient,
pPolicy,
&TobeReturn
);
}
catch( SE_Exception e ) {
dwStatus = e.getSeNumber();
}
catch(...) {
SetLastError(dwStatus = TLS_E_INTERNAL);
}
if(TLS_ERROR(dwStatus))
{
ROLLBACK_TRANSACTION(pDbWorkSpace);
}
else
{
COMMIT_TRANSACTION(pDbWorkSpace);
}
FREEDBHANDLE(pDbWorkSpace);
cleanup:
lpContext->m_LastError=dwStatus;
InterlockedDecrement( &lpContext->m_RefCount );
#if DBG
lpContext->m_LastCall = RPC_CALL_RETURNINTERNETLICENSEEX;
#endif
*pdwErrCode = TLSMapReturnCode(dwStatus);
if(pPolicy)
{
pPolicy->PMLicenseRequest(
hClient,
REQUEST_COMPLETE,
UlongToPtr (dwStatus),
NULL
);
ReleasePolicyModule(pPolicy);
}
//
// Reset SE translator
//
_set_se_translator(old_trans_se_func);
return RPC_S_OK;
}
////////////////////////////////////////////////////////////////////////////
error_status_t
TLSRpcReturnInternetLicense(
/* [in] */ PCONTEXT_HANDLE phContext,
/* [in] */ DWORD cbLicense,
/* [size_is][in] */ PBYTE pbLicense,
/* [ref][out][in] */ PDWORD pdwErrCode
)
/*++
--*/
{
DWORD dwStatus = ERROR_SUCCESS;
DWORD index = 0;
PLICENSEDPRODUCT pLicensedProduct = NULL;
DWORD dwNumLicensedProduct = 0;
TLSLicenseToBeReturn TobeReturn;
LPCLIENTCONTEXT lpContext = (LPCLIENTCONTEXT)phContext;
PTLSDbWorkSpace pDbWorkSpace = NULL;
CTLSPolicy* pPolicy = NULL;
PMHANDLE hClient;
_se_translator_function old_trans_se_func = NULL;
old_trans_se_func = _set_se_translator( trans_se_func );
if(lpContext == NULL)
{
SetLastError(dwStatus = ERROR_INVALID_PARAMETER);
goto cleanup;
}
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_TRACE,
_TEXT("%s : TLSRpcReturnInternetLicense\n"),
lpContext->m_Client
);
InterlockedIncrement( &lpContext->m_RefCount );
if(!(lpContext->m_ClientFlags & CLIENT_ACCESS_REQUEST))
{
dwStatus = TLS_E_ACCESS_DENIED;
goto cleanup;
}
// -------------------------------------------------------
// decode the license.
// -------------------------------------------------------
dwStatus = LSVerifyDecodeClientLicense(
pbLicense,
cbLicense,
g_pbSecretKey,
g_cbSecretKey,
&dwNumLicensedProduct,
pLicensedProduct
);
// -------------------------------------------------------
// Internet license can only have one licensed product
// -------------------------------------------------------
if(dwStatus != LICENSE_STATUS_OK || dwNumLicensedProduct == 0 || dwNumLicensedProduct > 1)
{
dwStatus = TLS_E_INVALID_LICENSE;
goto cleanup;
}
pLicensedProduct = (PLICENSEDPRODUCT)AllocateMemory(
dwNumLicensedProduct * sizeof(LICENSEDPRODUCT)
);
if(pLicensedProduct == NULL)
{
dwStatus = TLS_E_ALLOCATE_MEMORY;
goto cleanup;
}
dwStatus = LSVerifyDecodeClientLicense(
pbLicense,
cbLicense,
g_pbSecretKey,
g_cbSecretKey,
&dwNumLicensedProduct,
pLicensedProduct
);
if(dwStatus != LICENSE_STATUS_OK)
{
dwStatus = TLS_E_INVALID_LICENSE;
goto cleanup;
}
TobeReturn.dwQuantity = pLicensedProduct->dwQuantity;
TobeReturn.dwKeyPackId = pLicensedProduct->ulSerialNumber.HighPart;
TobeReturn.dwLicenseId = pLicensedProduct->ulSerialNumber.LowPart;
TobeReturn.dwPlatformID = pLicensedProduct->LicensedProduct.dwPlatformID;
TobeReturn.cbEncryptedHwid = pLicensedProduct->LicensedProduct.cbEncryptedHwid;
TobeReturn.pbEncryptedHwid = pLicensedProduct->LicensedProduct.pbEncryptedHwid;
TobeReturn.dwProductVersion = MAKELONG(
pLicensedProduct->pLicensedVersion->wMinorVersion,
pLicensedProduct->pLicensedVersion->wMajorVersion
);
TobeReturn.pszOrgProductId = (LPTSTR) pLicensedProduct->pbOrgProductID;
TobeReturn.pszCompanyName = (LPTSTR) pLicensedProduct->LicensedProduct.pProductInfo->pbCompanyName;
TobeReturn.pszProductId = (LPTSTR) pLicensedProduct->LicensedProduct.pProductInfo->pbProductID;
TobeReturn.pszUserName = (LPTSTR) pLicensedProduct->szLicensedUser;
TobeReturn.pszMachineName = pLicensedProduct->szLicensedClient;
//
// Allocate policy module, must have the right policy module to
// return license.
//
pPolicy = AcquirePolicyModule(
TobeReturn.pszCompanyName,
TobeReturn.pszOrgProductId,
TRUE
);
if(pPolicy == NULL)
{
dwStatus = GetLastError();
goto cleanup;
}
hClient = GenerateClientId();
//
// Allocate DB handle
//
if(!ALLOCATEDBHANDLE(pDbWkSpace, g_GeneralDbTimeout))
{
dwStatus = TLS_E_ALLOCATE_HANDLE;
goto cleanup;
}
CLEANUPSTMT;
BEGIN_TRANSACTION(pDbWorkSpace);
try {
dwStatus = TLSReturnClientLicensedProduct(
USEHANDLE(pDbWkSpace),
hClient,
pPolicy,
&TobeReturn
);
}
catch( SE_Exception e ) {
dwStatus = e.getSeNumber();
}
catch(...) {
SetLastError(dwStatus = TLS_E_INTERNAL);
}
if(TLS_ERROR(dwStatus))
{
ROLLBACK_TRANSACTION(pDbWorkSpace);
}
else
{
COMMIT_TRANSACTION(pDbWorkSpace);
}
FREEDBHANDLE(pDbWorkSpace);
cleanup:
lpContext->m_LastError=dwStatus;
InterlockedDecrement( &lpContext->m_RefCount );
#if DBG
lpContext->m_LastCall = RPC_CALL_RETURNINTERNETLICENSE;
#endif
*pdwErrCode = TLSMapReturnCode(dwStatus);
if(pLicensedProduct != NULL)
{
for(index =0; index < dwNumLicensedProduct; index++)
{
LSFreeLicensedProduct(pLicensedProduct+index);
}
FreeMemory(pLicensedProduct);
}
if(pPolicy)
{
pPolicy->PMLicenseRequest(
hClient,
REQUEST_COMPLETE,
UlongToPtr (dwStatus),
NULL
);
ReleasePolicyModule(pPolicy);
}
//
// Reset SE translator
//
_set_se_translator(old_trans_se_func);
return RPC_S_OK;
}