windows-nt/Source/XPSP1/NT/termsrv/license/tlserver/server/licreq.cpp

1695 lines
52 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996-1998
//
// File: licreq.cpp
//
// Contents:
// New license request
//
// History:
// 09/13/98 HueiWang Created
//---------------------------------------------------------------------------
#include "pch.cpp"
#include "licreq.h"
#include "db.h"
#include "findlost.h"
#include "permlic.h"
#include "templic.h"
#include "gencert.h"
#include "globals.h"
#include "forward.h"
#include "postjob.h"
#include "cryptkey.h"
#include "init.h"
#include "clilic.h"
DWORD
TLSDBIssueNewLicenseFromLocal(
IN PTLSDbWorkSpace pDbWkSpace,
IN PTLSDBLICENSEREQUEST pRequest,
IN BOOL bFindLostLicense,
IN BOOL bRequireTempLicense,
IN BOOL bAcceptFewerLicenses,
IN OUT DWORD *pdwQuantity,
OUT PTLSDBLICENSEDPRODUCT pLicensedProduct,
IN DWORD dwSupportFlags
);
//
// State of issuing function - used for counters
//
#define NONE_TRIED 0
#define PERMANENT_ISSUE_TRIED 1
#define TEMPORARY_ISSUE_TRIED 2
#define PERMANENT_REISSUE_TRIED 3
////////////////////////////////////////////////////////////////////
void
TLSLicenseTobeReturnToPMLicenseToBeReturn(
PTLSLicenseToBeReturn pTlsLicense,
BOOL bTempLicense,
PPMLICENSETOBERETURN pPmLicense
)
/*++
--*/
{
pPmLicense->dwQuantity = pTlsLicense->dwQuantity;
pPmLicense->dwProductVersion = pTlsLicense->dwProductVersion;
pPmLicense->pszOrgProductId = pTlsLicense->pszOrgProductId;
pPmLicense->pszCompanyName = pTlsLicense->pszCompanyName;
pPmLicense->pszProductId = pTlsLicense->pszProductId;
pPmLicense->pszUserName = pTlsLicense->pszUserName;
pPmLicense->pszMachineName = pTlsLicense->pszMachineName;
pPmLicense->dwPlatformID = pTlsLicense->dwPlatformID;
pPmLicense->bTemp = bTempLicense;
return;
}
////////////////////////////////////////////////////////////////////
DWORD
TLSReturnClientLicensedProduct(
IN PTLSDbWorkSpace pDbWkSpace,
IN PMHANDLE hClient,
IN CTLSPolicy* pPolicy,
IN PTLSLicenseToBeReturn pClientLicense
)
/*++
--*/
{
DWORD dwStatus = ERROR_SUCCESS;
DWORD dwPolicyLicenseStatus;
ULARGE_INTEGER serialNumber;
HWID hwid;
LICENSEREQUEST LicensedProduct;
Product_Info ProductInfo;
TLSLICENSEPACK LicensePack;
LICENSEDCLIENT LicenseClient;
PMLICENSETOBERETURN pmLicToBeReturn;
DWORD dwLicenseStatus;
dwStatus = LicenseDecryptHwid(
&hwid,
pClientLicense->cbEncryptedHwid,
pClientLicense->pbEncryptedHwid,
g_cbSecretKey,
g_pbSecretKey
);
if(dwStatus != ERROR_SUCCESS)
{
SetLastError(dwStatus = TLS_E_INVALID_LICENSE);
goto cleanup;
}
LicensedProduct.pbEncryptedHwid = pClientLicense->pbEncryptedHwid;
LicensedProduct.cbEncryptedHwid = pClientLicense->cbEncryptedHwid;
LicensedProduct.dwLanguageID = 0;
LicensedProduct.dwPlatformID = pClientLicense->dwPlatformID;
LicensedProduct.pProductInfo = &ProductInfo;
ProductInfo.cbCompanyName = (lstrlen(pClientLicense->pszCompanyName) + 1) * sizeof(TCHAR);
ProductInfo.pbCompanyName = (PBYTE)pClientLicense->pszCompanyName;
ProductInfo.cbProductID = (lstrlen(pClientLicense->pszProductId) + 1) * sizeof(TCHAR);
ProductInfo.pbProductID = (PBYTE)pClientLicense->pszProductId;
//
// Verify with local database
//
dwStatus = TLSDBValidateLicense(
pDbWkSpace,
&hwid,
&LicensedProduct,
pClientLicense->dwKeyPackId,
pClientLicense->dwLicenseId,
&LicensePack,
&LicenseClient
);
if(dwStatus != ERROR_SUCCESS)
{
// tell caller this record is wrong.
SetLastError(dwStatus = TLS_E_RECORD_NOTFOUND);
goto cleanup;
}
if( LicenseClient.ucLicenseStatus == LSLICENSE_STATUS_UPGRADED ||
LicenseClient.ucLicenseStatus == LSLICENSE_STATUS_REVOKE ||
LicenseClient.ucLicenseStatus == LSLICENSE_STATUS_UNKNOWN )
{
// License already been return/revoke
dwStatus = ERROR_SUCCESS;
goto cleanup;
}
//
//
// only inform policy module if license status is
// active, temporary, active_pending, concurrent
// TODO - pass all status to policy module
//
if( LicenseClient.ucLicenseStatus == LSLICENSE_STATUS_TEMPORARY ||
LicenseClient.ucLicenseStatus == LSLICENSE_STATUS_ACTIVE ||
//LicenseClient.ucLicenseStatus == LSLICENSE_STATUS_PENDING_ACTIVE ||
LicenseClient.ucLicenseStatus == LSLICENSE_STATUS_CONCURRENT )
{
serialNumber.HighPart = pClientLicense->dwKeyPackId;
serialNumber.LowPart = pClientLicense->dwLicenseId;
TLSLicenseTobeReturnToPMLicenseToBeReturn(
pClientLicense,
LicenseClient.ucLicenseStatus == LSLICENSE_STATUS_TEMPORARY,
&pmLicToBeReturn
);
dwStatus = pPolicy->PMReturnLicense(
hClient,
&serialNumber,
&pmLicToBeReturn,
&dwPolicyLicenseStatus
);
if(dwStatus != ERROR_SUCCESS)
{
goto cleanup;
}
//
// delete license on request.
//
dwLicenseStatus = (dwPolicyLicenseStatus == LICENSE_RETURN_KEEP) ?
LSLICENSE_STATUS_UPGRADED : LSLICENSESTATUS_DELETE;
}
if (LicenseClient.dwNumLicenses == pClientLicense->dwQuantity)
{
// delete the whole license
dwStatus = TLSDBReturnLicense(
pDbWkSpace,
pClientLicense->dwKeyPackId,
pClientLicense->dwLicenseId,
dwLicenseStatus
);
}
else
{
dwStatus = TLSDBReturnLicenseToKeyPack(
pDbWkSpace,
pClientLicense->dwKeyPackId,
pClientLicense->dwQuantity
);
if (dwStatus == ERROR_SUCCESS)
{
// Set number of CALs in license
LICENSEDCLIENT license;
license.dwLicenseId = pClientLicense->dwLicenseId;
license.dwNumLicenses = LicenseClient.dwNumLicenses - pClientLicense->dwQuantity;
license.ucLicenseStatus = LSLICENSE_STATUS_UPGRADED;
dwStatus = TLSDBLicenseSetValue(pDbWkSpace,
LSLICENSE_SEARCH_NUMLICENSES,
&license,
FALSE // bPointerOnRecord
);
}
}
cleanup:
return dwStatus;
}
////////////////////////////////////////////////////////////////////
DWORD
TLSDBMarkClientLicenseUpgraded(
IN PTLSDbWorkSpace pDbWkSpace,
IN PTLSDBLICENSEREQUEST pRequest,
IN PTLSDBLICENSEDPRODUCT pLicensedProduct
)
/*++
--*/
{
DWORD dwStatus = ERROR_SUCCESS;
DWORD dwLicenseStatus;
PMLICENSETOBERETURN pmLicense;
if(pRequest == NULL || pRequest->pPolicy == NULL)
{
SetLastError(dwStatus = ERROR_INVALID_PARAMETER);
return dwStatus;
}
pmLicense.dwQuantity = pLicensedProduct->dwQuantity;
pmLicense.dwProductVersion = pLicensedProduct->dwProductVersion;
pmLicense.pszOrgProductId = pLicensedProduct->szRequestProductId;
pmLicense.pszCompanyName = pLicensedProduct->szCompanyName;
pmLicense.pszProductId = pLicensedProduct->szLicensedProductId;
pmLicense.pszUserName = pLicensedProduct->szUserName;
pmLicense.pszMachineName = pLicensedProduct->szMachineName;
pmLicense.dwPlatformID = pLicensedProduct->dwPlatformID;
pmLicense.bTemp = pLicensedProduct->bTemp;
//
// Ask if we can delete the old license
//
dwStatus = pRequest->pPolicy->PMReturnLicense(
pRequest->hClient,
&pLicensedProduct->ulSerialNumber,
&pmLicense,
&dwLicenseStatus
);
//
// MarkClientLicenseUpgrade() can only be called by FindLostLicense() which will only
// return valid licenses.
// TODO - Check license status.
//
if(dwStatus == ERROR_SUCCESS)
{
// Temporary license - delete license and don't bother about
// Permenant license - keep license and DO NOT return license to keypack
dwStatus = TLSDBReturnLicense(
pDbWkSpace,
pLicensedProduct->dwKeyPackId,
pLicensedProduct->dwLicenseId,
(dwLicenseStatus == LICENSE_RETURN_KEEP) ? LSLICENSE_STATUS_UPGRADED : LSLICENSESTATUS_DELETE
);
}
return dwStatus;
}
//////////////////////////////////////////////////////////////
DWORD
TLSDBUpgradeClientLicense(
IN PTLSDbWorkSpace pDbWkSpace,
IN PTLSDBLICENSEREQUEST pRequest,
IN PTLSDBLICENSEDPRODUCT pLicensedProduct,
IN BOOL bAcceptFewerLicenses,
IN OUT DWORD *pdwQuantity,
IN OUT PTLSDBLICENSEDPRODUCT pUpgradedProduct,
IN DWORD dwSupportFlags
)
/*
Abstract:
Upgrade a license - issue a new license and return old license
Parameters:
Returns
*/
{
DWORD dwStatus=ERROR_SUCCESS;
dwStatus=TLSDBIssuePermanentLicense(
pDbWkSpace,
pRequest,
TRUE, // bLatestVersion
bAcceptFewerLicenses,
pdwQuantity,
pUpgradedProduct,
dwSupportFlags
);
if (dwStatus == ERROR_SUCCESS)
{
//
// Return license to keypack
//
dwStatus = TLSDBMarkClientLicenseUpgraded(
pDbWkSpace,
pRequest,
pLicensedProduct
);
}
return dwStatus;
}
//--------------------------------------------------------------------
void
LicensedProductToDbLicensedProduct(
PLICENSEDPRODUCT pSrc,
PTLSDBLICENSEDPRODUCT pDest
)
/*++
++*/
{
pDest->dwQuantity = pSrc->dwQuantity;
pDest->ulSerialNumber = pSrc->ulSerialNumber;
pDest->dwKeyPackId = pSrc->ulSerialNumber.HighPart;
pDest->dwLicenseId = pSrc->ulSerialNumber.LowPart;
pDest->ClientHwid = pSrc->Hwid;
pDest->NotBefore = pSrc->NotBefore;
pDest->NotAfter = pSrc->NotAfter;
pDest->bTemp = ((pSrc->pLicensedVersion->dwFlags & LICENSED_VERSION_TEMPORARY) != 0);
pDest->dwProductVersion = pSrc->LicensedProduct.pProductInfo->dwVersion;
SAFESTRCPY(
pDest->szCompanyName,
(LPTSTR)(pSrc->LicensedProduct.pProductInfo->pbCompanyName)
);
SAFESTRCPY(
pDest->szLicensedProductId,
(LPTSTR)(pSrc->LicensedProduct.pProductInfo->pbProductID)
);
SAFESTRCPY(
pDest->szRequestProductId,
(LPTSTR)(pSrc->pbOrgProductID)
);
SAFESTRCPY(
pDest->szUserName,
pSrc->szLicensedUser
);
SAFESTRCPY(
pDest->szMachineName,
pSrc->szLicensedClient
);
pDest->dwLanguageID = pSrc->LicensedProduct.dwLanguageID;
pDest->dwPlatformID = pSrc->LicensedProduct.dwPlatformID;
pDest->pbPolicyData = pSrc->pbPolicyData;
pDest->cbPolicyData = pSrc->cbPolicyData;
}
//--------------------------------------------------------------------
void
CopyDbLicensedProduct(
PTLSDBLICENSEDPRODUCT pSrc,
PTLSDBLICENSEDPRODUCT pDest
)
/*++
++*/
{
pDest->dwQuantity = pSrc->dwQuantity;
pDest->ulSerialNumber = pSrc->ulSerialNumber;
pDest->dwKeyPackId = pSrc->dwKeyPackId;
pDest->dwLicenseId = pSrc->dwLicenseId;
pDest->ClientHwid = pSrc->ClientHwid;
pDest->NotBefore = pSrc->NotBefore;
pDest->NotAfter = pSrc->NotAfter;
pDest->bTemp = pSrc->bTemp;
pDest->dwProductVersion = pSrc->dwProductVersion;
SAFESTRCPY(
pDest->szCompanyName,
pSrc->szCompanyName
);
SAFESTRCPY(
pDest->szLicensedProductId,
pSrc->szLicensedProductId
);
SAFESTRCPY(
pDest->szRequestProductId,
pSrc->szRequestProductId
);
SAFESTRCPY(
pDest->szUserName,
pSrc->szUserName
);
SAFESTRCPY(
pDest->szMachineName,
pSrc->szMachineName
);
pDest->dwLanguageID = pSrc->dwLanguageID;
pDest->dwPlatformID = pSrc->dwPlatformID;
pDest->pbPolicyData = pSrc->pbPolicyData;
pDest->cbPolicyData = pSrc->cbPolicyData;
}
//------------------------------------------------------------------
DWORD
TLSDBIssueNewLicenseFromLocal(
IN PTLSDbWorkSpace pDbWkSpace,
IN PTLSDBLICENSEREQUEST pRequest,
IN BOOL bFindLostLicense,
IN BOOL bRequireTempLicense,
IN BOOL bAcceptFewerLicenses,
IN OUT DWORD *pdwQuantity,
IN OUT PTLSDBLICENSEDPRODUCT pLicensedProduct,
IN DWORD dwSupportFlags
)
/*++
Abstract:
Allocate a license from locally installed license pack.
Parameters:
pDbWkSpace - workspace handle
lpLsLicenseRequest - license request
bAcceptTemporaryLicense - accept temporary license
bFindLostLicense - TRUE if find lost license before issuing a new one
bRequireTempLicense -TRUE if permanent license can't be issued (DoS fix)
bAcceptFewerLicenses - TRUE if succeeding with fewer licenses than
requested is acceptable
pdwQuantity - on input, number of licenses requested
on output, number of licenses actually allocated
pLicensedProduct - return licensed product
Returns:
++*/
{
DWORD status=TLS_E_RECORD_NOTFOUND;
UCHAR ucMarked;
if(bFindLostLicense == TRUE)
{
//
// Try to find the lost license
//
status=TLSDBFindLostLicense(
pDbWkSpace,
pRequest,
&pRequest->hWid,
pLicensedProduct,
&ucMarked
);
if( status != TLS_E_RECORD_NOTFOUND &&
status != TLS_E_LICENSE_EXPIRED &&
status != TLS_I_FOUND_TEMPORARY_LICENSE &&
status != ERROR_SUCCESS)
{
goto cleanup;
}
//
// If license has been expired or it is a temporary license,
// try to allocate a new permanent one.
//
if ( status == TLS_E_LICENSE_EXPIRED
|| status == TLS_I_FOUND_TEMPORARY_LICENSE)
{
if ((!pLicensedProduct->bTemp) && CanIssuePermLicense())
{
TLSDBLICENSEDPRODUCT upgradeProduct;
//
// expired permanent
//
status = TLSDBReissueFoundPermanentLicense(
USEHANDLE(pDbWkSpace),
pLicensedProduct,
&upgradeProduct
);
if (ERROR_SUCCESS == status)
{
*pLicensedProduct = upgradeProduct;
status = TLS_I_LICENSE_UPGRADED;
}
else
{
//
// reissuance failed, try to issue a new permanent
//
status = TLS_E_RECORD_NOTFOUND;
}
}
//
// no upgrade if license server hasn't been registered
// or if DoS fix required and license isn't marked
//
else if (((!bRequireTempLicense)
|| (ucMarked & MARK_FLAG_USER_AUTHENTICATED))
&& CanIssuePermLicense())
{
DWORD upgrade_status;
TLSDBLICENSEDPRODUCT upgradeProduct;
upgrade_status = TLSDBUpgradeClientLicense(
pDbWkSpace,
pRequest,
pLicensedProduct,
bAcceptFewerLicenses,
pdwQuantity,
&upgradeProduct,
dwSupportFlags
);
if(upgrade_status == ERROR_SUCCESS)
{
*pLicensedProduct = upgradeProduct;
status = TLS_I_LICENSE_UPGRADED;
}
else if(upgrade_status != TLS_E_NO_LICENSE &&
upgrade_status != TLS_E_PRODUCT_NOTINSTALL)
{
//
// Error in upgrade license.
//
status = upgrade_status;
}
goto cleanup;
}
//
// Temporary license has expired and can't allocate permanent
// license, refuse connection
//
if( status == TLS_E_LICENSE_EXPIRED )
{
goto cleanup;
}
}
else if ((status == ERROR_SUCCESS)
&& (pLicensedProduct->dwQuantity != *pdwQuantity))
{
// user has wrong number of licenses
if (*pdwQuantity > pLicensedProduct->dwQuantity)
{
if (bRequireTempLicense || !CanIssuePermLicense())
{
goto try_next;
}
#define NUM_KEYPACKS 5
DWORD upgrade_status;
TLSDBLicenseAllocation allocation;
DWORD dwAllocation[NUM_KEYPACKS];
TLSLICENSEPACK keypack[NUM_KEYPACKS];
TLSDBAllocateRequest AllocateRequest;
for (int i=0; i < NUM_KEYPACKS; i++)
{
keypack[i].pbDomainSid = NULL;
}
memset(&allocation,0,sizeof(allocation));
allocation.dwBufSize = NUM_KEYPACKS;
allocation.pdwAllocationVector = dwAllocation;
allocation.lpAllocateKeyPack = keypack;
AllocateRequest.szCompanyName
= (LPTSTR)pRequest->pszCompanyName;
AllocateRequest.szProductId
= (LPTSTR)pRequest->pszProductId;
AllocateRequest.dwVersion
= pRequest->dwProductVersion;
AllocateRequest.dwPlatformId
= pRequest->dwPlatformID;
AllocateRequest.dwLangId
= pRequest->dwLanguageID;
AllocateRequest.dwNumLicenses
= *pdwQuantity - pLicensedProduct->dwQuantity;
AllocateRequest.dwScheme
= ALLOCATE_ANY_GREATER_VERSION;
AllocateRequest.ucAgreementType
= LSKEYPACKTYPE_UNKNOWN;
upgrade_status = AllocateLicensesFromDB(
pDbWkSpace,
&AllocateRequest,
FALSE, // fCheckAgreementType
&allocation
);
if ((upgrade_status == ERROR_SUCCESS)
&& ((allocation.dwTotalAllocated == 0)
|| (!bAcceptFewerLicenses
&& (allocation.dwTotalAllocated != *pdwQuantity-pLicensedProduct->dwQuantity))))
{
status = TLS_E_NO_LICENSE;
goto cleanup;
}
else
{
*pdwQuantity = pLicensedProduct->dwQuantity + allocation.dwTotalAllocated;
}
if (TLS_I_NO_MORE_DATA == upgrade_status)
{
status = TLS_E_NO_LICENSE;
goto cleanup;
}
if(upgrade_status == ERROR_SUCCESS)
{
status = TLS_I_LICENSE_UPGRADED;
}
else
{
//
// Error in upgrade license.
//
status = upgrade_status;
goto cleanup;
}
}
else
{
// return unwanted licenses to keypack
status = TLSDBReturnLicenseToKeyPack(
pDbWkSpace,
pLicensedProduct->dwKeyPackId,
pLicensedProduct->dwQuantity - *pdwQuantity
);
if (status != ERROR_SUCCESS)
{
goto cleanup;
}
}
{
// Set number of CALs in license
LICENSEDCLIENT license;
license.dwLicenseId = pLicensedProduct->dwLicenseId;
license.dwNumLicenses = *pdwQuantity;
license.ucLicenseStatus = LSLICENSE_STATUS_UPGRADED;
status = TLSDBLicenseSetValue(pDbWkSpace,
LSLICENSE_SEARCH_NUMLICENSES,
&license,
FALSE // bPointerOnRecord
);
}
goto cleanup;
}
}
try_next:
//
// Issue permanent license only if license server has been registered
// and user is allowed to have one
//
if((status == TLS_E_RECORD_NOTFOUND) && (!bRequireTempLicense))
{
if(CanIssuePermLicense() == FALSE)
{
SetLastError(status = TLS_E_NO_CERTIFICATE);
}
else
{
status=TLSDBIssuePermanentLicense(
pDbWkSpace,
pRequest,
FALSE,
bAcceptFewerLicenses,
pdwQuantity,
pLicensedProduct,
dwSupportFlags
);
}
}
cleanup:
return status;
}
//////////////////////////////////////////////////////////////////////
DWORD
TLSUpgradeLicenseRequest(
IN BOOL bForwardRequest,
IN PTLSForwardUpgradeLicenseRequest pForward,
IN OUT DWORD *pdwSupportFlags,
IN PTLSDBLICENSEREQUEST pRequest,
IN PBYTE pbOldLicense,
IN DWORD cbOldLicense,
IN DWORD dwNumLicProduct,
IN PLICENSEDPRODUCT pLicProduct,
IN BOOL bRequireTempLicense,
IN OUT PDWORD pcbEncodedCert,
OUT PBYTE* ppbEncodedCert
)
/*++
++*/
{
DWORD dwStatus = TLS_E_NO_LICENSE;
BOOL bAcceptTempLicense = FALSE;
DWORD index;
DWORD dwNumNewLicProduct;
TLSDBLICENSEDPRODUCT NewLicProduct;
PTLSDbWorkSpace pDbWkSpace=NULL;
PTLSDBLICENSEDPRODUCT pGenCertProduct=NULL;
FILETIME* pNotBefore=NULL;
FILETIME* pNotAfter=NULL;
DWORD dwNumChars;
DWORD dwLicGenStatus;
BOOL bDbHandleAcquired = FALSE;
BOOL fReissue = FALSE;
DWORD dwTried = NONE_TRIED;
//
// check to see if we can take temp. license
//
// The only case that we need to set temp. license's expiration date is
// latest licensed product is temporary and client is requesting for version
// greater than lastest license.
//
if(CompareTLSVersions(pRequest->dwProductVersion, pLicProduct->LicensedProduct.pProductInfo->dwVersion) > 0)
{
bAcceptTempLicense = TRUE;
if(pLicProduct->pLicensedVersion->dwFlags & LICENSED_VERSION_TEMPORARY)
{
//
// client holding 5.0 temp. and request 6.0 licenses.
// we need to issue 6.0 license but the license expiration
// date stay the same.
//
pNotBefore = &(pLicProduct->NotBefore);
pNotAfter = &(pLicProduct->NotAfter);
}
}
else if(CompareTLSVersions(pRequest->dwProductVersion, pLicProduct->LicensedProduct.pProductInfo->dwVersion) == 0)
{
if( IS_LICENSE_ISSUER_RTM(pLicProduct->pLicensedVersion->dwFlags) == FALSE &&
TLSIsBetaNTServer() == FALSE )
{
// issuer is beta/eval, we are a RTM, accept temp. license
bAcceptTempLicense = TRUE;
}
}
if(ALLOCATEDBHANDLE(pDbWorkSpace, g_EnumDbTimeout) == FALSE)
{
dwStatus = TLS_E_ALLOCATE_HANDLE;
goto cleanup;
}
CLEANUPSTMT;
BEGIN_TRANSACTION(pDbWorkSpace);
bDbHandleAcquired = TRUE;
if (!bRequireTempLicense)
{
//
// Check for reissuance first, if a) reissuance is supported, b)
// the license is permanent, c) the license is the current version,
// and d) the license is expired.
//
if ((*pdwSupportFlags & SUPPORT_PER_SEAT_REISSUANCE) &&
((_tcsnicmp((TCHAR *)pLicProduct->LicensedProduct.pProductInfo->pbProductID,
TERMSERV_PRODUCTID_SKU,
_tcslen(TERMSERV_PRODUCTID_SKU)) == 0) ||
(_tcsnicmp((TCHAR *)pLicProduct->LicensedProduct.pProductInfo->pbProductID,
TERMSERV_PRODUCTID_CONCURRENT_SKU,
_tcslen(TERMSERV_PRODUCTID_CONCURRENT_SKU)) == 0)) &&
(!(pLicProduct->pLicensedVersion->dwFlags &
LICENSED_VERSION_TEMPORARY)) &&
(CompareTLSVersions(pLicProduct->LicensedProduct.pProductInfo->dwVersion,
pRequest->dwProductVersion)) == 0)
{
DWORD t;
//
// Checking expiration with filetimes is a pain; convert.
//
FileTimeToLicenseDate(&(pLicProduct->NotAfter), &t);
if (t-g_dwReissueLeaseLeeway < time(NULL))
{
// do reissue
fReissue = TRUE;
if (CanIssuePermLicense())
{
dwStatus = TLSDBReissuePermanentLicense(
USEHANDLE(pDbWkSpace),
pLicProduct,
&NewLicProduct
);
if (dwStatus == ERROR_SUCCESS)
{
dwTried = PERMANENT_REISSUE_TRIED;
// skip past the next stuff if all goes well
goto licenseReissued;
}
}
else
{
dwStatus = TLS_E_RECORD_NOTFOUND;
}
if ((dwStatus == TLS_E_RECORD_NOTFOUND)
&& bForwardRequest
&& (_tcsicmp(pLicProduct->szIssuerId,
(LPTSTR)g_pszServerPid) != 0))
{
// couldn't find the license, forward the request to issuer
DWORD dwSupportFlagsTemp = *pdwSupportFlags;
DWORD dwErrCode;
dwStatus = ForwardUpgradeLicenseRequest(
pLicProduct->szIssuerId,
&dwSupportFlagsTemp,
pForward->m_pRequest,
pForward->m_ChallengeContext,
pForward->m_cbChallengeResponse,
pForward->m_pbChallengeResponse,
pForward->m_cbOldLicense,
pForward->m_pbOldLicense,
pcbEncodedCert,
ppbEncodedCert,
&dwErrCode
);
if (ERROR_SUCCESS == dwStatus
&& LSERVER_S_SUCCESS == dwErrCode)
{
*pdwSupportFlags = dwSupportFlagsTemp;
goto licenseReissued;
}
}
// other failure cases just follow the existing codepath
dwStatus = ERROR_SUCCESS;
}
}
if(CanIssuePermLicense())
{
DWORD dwQuantity = 1;
//
// Try to issue a new license from local
// if this server is registered
//
dwStatus = TLSDBIssueNewLicenseFromLocal(
USEHANDLE(pDbWkSpace),
pRequest,
TRUE, // bFindLostLicense
FALSE, // bRequireTempLicense
FALSE, // bAcceptFewerLicenses
&dwQuantity,
&NewLicProduct,
*pdwSupportFlags
);
if (TLS_I_FOUND_TEMPORARY_LICENSE == dwStatus)
{
// Found a temporary license; not what we want
dwStatus = TLS_E_RECORD_NOTFOUND;
}
else
{
dwTried = PERMANENT_ISSUE_TRIED;
}
}
else
{
dwStatus = TLS_E_NO_CERTIFICATE;
}
if(dwStatus != ERROR_SUCCESS && bForwardRequest == FALSE)
{
//
// If remote server can't handle upgrade, we don't do anything but
// return the license back to client, don't try to issue a temp.
// license for this client if we are not the original contact
// of client
//
goto cleanup;
}
if((dwStatus == TLS_E_PRODUCT_NOTINSTALL ||
dwStatus == TLS_E_NO_CERTIFICATE ||
dwStatus == TLS_E_NO_LICENSE ||
dwStatus == TLS_E_RECORD_NOTFOUND) && bForwardRequest)
{
//
// release our DB handle and forward request to other server
//
ROLLBACK_TRANSACTION(pDbWorkSpace);
FREEDBHANDLE(pDbWorkSpace);
bDbHandleAcquired = FALSE;
DWORD dwForwardStatus;
DWORD dwSupportFlagsTemp = *pdwSupportFlags;
dwForwardStatus = TLSForwardUpgradeRequest(
pForward,
&dwSupportFlagsTemp,
pRequest,
pcbEncodedCert,
ppbEncodedCert
);
if(dwForwardStatus == TLS_I_SERVICE_STOP || dwForwardStatus == ERROR_SUCCESS)
{
if (dwForwardStatus == ERROR_SUCCESS)
{
*pdwSupportFlags = dwSupportFlagsTemp;
}
dwStatus = dwForwardStatus;
goto cleanup;
}
}
if(bDbHandleAcquired == FALSE)
{
if(ALLOCATEDBHANDLE(pDbWorkSpace, g_GeneralDbTimeout) == FALSE)
{
dwStatus = TLS_E_ALLOCATE_HANDLE;
goto cleanup;
}
CLEANUPSTMT;
BEGIN_TRANSACTION(pDbWorkSpace);
bDbHandleAcquired = TRUE;
}
}
//
// if can't get license from remote, try temporary
//
// always issue a temporary license
if((dwStatus == TLS_E_PRODUCT_NOTINSTALL ||
dwStatus == TLS_E_NO_CERTIFICATE ||
dwStatus == TLS_E_NO_LICENSE ||
dwStatus == TLS_E_RECORD_NOTFOUND) && bAcceptTempLicense)
{
// Issue a temporary license if can't allocate a permenent license
if( TLSDBIssueTemporaryLicense(
USEHANDLE(pDbWkSpace),
pRequest,
pNotBefore,
pNotAfter,
&NewLicProduct
) == ERROR_SUCCESS )
{
dwStatus = TLS_W_TEMPORARY_LICENSE_ISSUED;
dwTried = TEMPORARY_ISSUE_TRIED;
}
}
//
// If we can find a server to upgrade or we can't issue temp
// license, get out.
//
if(TLS_ERROR(dwStatus) == TRUE)
{
goto cleanup;
}
licenseReissued:
//
// Determine which licensed product should be in the license blob
//
pGenCertProduct = (PTLSDBLICENSEDPRODUCT)AllocateMemory(
sizeof(TLSDBLICENSEDPRODUCT)*(dwNumLicProduct+1)
);
if(pGenCertProduct == NULL)
{
dwStatus = TLS_E_ALLOCATE_MEMORY;
goto cleanup;
}
dwNumNewLicProduct = 0;
//
// Copy all licensed product with version greated than requested
//
for( index = 0;
index < dwNumLicProduct && CompareTLSVersions((pLicProduct+index)->LicensedProduct.pProductInfo->dwVersion, NewLicProduct.dwProductVersion) > 0;
index++, dwNumNewLicProduct++)
{
LicensedProductToDbLicensedProduct( pLicProduct+index, pGenCertProduct+dwNumNewLicProduct );
}
//
// Append new license
//
*(pGenCertProduct+index) = NewLicProduct;
dwNumNewLicProduct++;
//
// Append licensed product older than request
//
for(;index < dwNumLicProduct;index++)
{
BOOL bTemp;
BOOL bDifferentProduct;
BOOL bNotNewerVersion = (CompareTLSVersions(NewLicProduct.dwProductVersion, (pLicProduct+index)->LicensedProduct.pProductInfo->dwVersion) <= 0);
bTemp = (((pLicProduct+index)->pLicensedVersion->dwFlags & LICENSED_VERSION_TEMPORARY) != 0);
// if we are running on RTM server, treat license issued from beta server as temporary license
if(bTemp == FALSE && TLSIsBetaNTServer() == FALSE)
{
bTemp = (IS_LICENSE_ISSUER_RTM((pLicProduct+index)->pLicensedVersion->dwFlags) == FALSE);
}
bDifferentProduct = (_tcscmp(NewLicProduct.szLicensedProductId, (LPTSTR)(pLicProduct+index)->LicensedProduct.pProductInfo->pbProductID) != 0);
if (bNotNewerVersion && !bDifferentProduct && !(bTemp || fReissue))
{
//
// we can't issue same version for the same product unless the old
// one was a temp or it is being re-issued
//
SetLastError(dwStatus = TLS_E_INTERNAL);
goto cleanup;
}
if(NewLicProduct.bTemp == FALSE || bTemp == TRUE)
{
if( IS_LICENSE_ISSUER_RTM((pLicProduct+index)->pLicensedVersion->dwFlags) == FALSE &&
TLSIsBetaNTServer() == FALSE )
{
// we wipe out beta database so ignore return.
continue;
}
if(_tcsicmp(pLicProduct->szIssuerId, (LPTSTR)g_pszServerPid) == 0)
{
//
// Convert LicensedProduct to TLSLicenseToBeReturn
// TODO - have its own version.
//
TLSLicenseToBeReturn tobeReturn;
tobeReturn.dwQuantity = (pLicProduct+index)->dwQuantity;
tobeReturn.dwKeyPackId = (pLicProduct+index)->ulSerialNumber.HighPart;
tobeReturn.dwLicenseId = (pLicProduct+index)->ulSerialNumber.LowPart;
tobeReturn.dwPlatformID = (pLicProduct+index)->LicensedProduct.dwPlatformID;
tobeReturn.cbEncryptedHwid = (pLicProduct+index)->LicensedProduct.cbEncryptedHwid;
tobeReturn.pbEncryptedHwid = (pLicProduct+index)->LicensedProduct.pbEncryptedHwid;
tobeReturn.dwProductVersion = MAKELONG(
(pLicProduct+index)->pLicensedVersion->wMinorVersion,
(pLicProduct+index)->pLicensedVersion->wMajorVersion
);
tobeReturn.pszOrgProductId = (LPTSTR)(pLicProduct+index)->pbOrgProductID;
tobeReturn.pszCompanyName = (LPTSTR) (pLicProduct+index)->LicensedProduct.pProductInfo->pbCompanyName;
tobeReturn.pszProductId = (LPTSTR) (pLicProduct+index)->LicensedProduct.pProductInfo->pbProductID;
tobeReturn.pszUserName = (LPTSTR) (pLicProduct+index)->szLicensedUser;
tobeReturn.pszMachineName = (pLicProduct+index)->szLicensedClient;
dwStatus = TLSReturnClientLicensedProduct(
USEHANDLE(pDbWkSpace),
pRequest->hClient,
pRequest->pPolicy,
&tobeReturn
);
}
else
{
dwStatus = TLSPostReturnClientLicenseJob( pLicProduct+index );
}
//
// Ignore can't find the record in database
//
dwStatus = ERROR_SUCCESS;
}
else
{
LicensedProductToDbLicensedProduct( pLicProduct + index, pGenCertProduct + dwNumNewLicProduct);
dwNumNewLicProduct++;
}
}
dwLicGenStatus = TLSGenerateClientCertificate(
g_hCryptProv,
dwNumNewLicProduct,
pGenCertProduct,
pRequest->wLicenseDetail,
ppbEncodedCert,
pcbEncodedCert
);
if(dwLicGenStatus != ERROR_SUCCESS)
{
dwStatus = dwLicGenStatus;
}
cleanup:
if(bDbHandleAcquired == TRUE)
{
if(TLS_ERROR(dwStatus))
{
ROLLBACK_TRANSACTION(pDbWorkSpace);
}
else
{
COMMIT_TRANSACTION(pDbWorkSpace);
switch (dwTried)
{
case PERMANENT_ISSUE_TRIED:
InterlockedIncrement(&g_lPermanentLicensesIssued);
break;
case TEMPORARY_ISSUE_TRIED:
InterlockedIncrement(&g_lTemporaryLicensesIssued);
break;
case PERMANENT_REISSUE_TRIED:
InterlockedIncrement(&g_lPermanentLicensesReissued);
break;
}
}
FREEDBHANDLE(pDbWorkSpace);
}
if(TLS_ERROR(dwStatus) == FALSE)
{
if(NewLicProduct.dwNumLicenseLeft == 0 && NewLicProduct.bTemp == FALSE)
{
// ignore error if we can't get it out to
// other server
TLSAnnounceLKPToAllRemoteServer(NewLicProduct.dwKeyPackId, 0);
}
}
FreeMemory(pGenCertProduct);
return dwStatus;
}
//----------------------------------------------------------
DWORD
TLSNewLicenseRequest(
IN BOOL bForwardRequest,
IN OUT DWORD *pdwSupportFlags,
IN PTLSForwardNewLicenseRequest pForward,
IN PTLSDBLICENSEREQUEST pRequest,
IN BOOL bAcceptTempLicense,
IN BOOL bRequireTempLicense,
IN BOOL bFindLostLicense,
IN BOOL bAcceptFewerLicenses,
IN OUT DWORD *pdwQuantity,
OUT PDWORD pcbEncodedCert,
OUT PBYTE* ppbEncodedCert
)
/*++
Abstract:
Parameter:
Returns:
++*/
{
DWORD dwStatus = TLS_E_NO_LICENSE;
TLSDBLICENSEDPRODUCT LicensedProduct;
PTLSDbWorkSpace pDbWorkSpace=NULL;
BOOL bDbHandleAcquired = FALSE;
DWORD dwSupportFlagsTemp = *pdwSupportFlags;
DWORD dwTried = NONE_TRIED;
if(ALLOCATEDBHANDLE(pDbWorkSpace, g_GeneralDbTimeout) == FALSE)
{
dwStatus = TLS_E_ALLOCATE_HANDLE;
goto cleanup;
}
CLEANUPSTMT;
BEGIN_TRANSACTION(pDbWorkSpace);
bDbHandleAcquired = TRUE;
try {
dwStatus = TLSDBIssueNewLicenseFromLocal(
USEHANDLE(pDbWorkSpace),
pRequest,
bFindLostLicense,
bRequireTempLicense,
bAcceptFewerLicenses,
pdwQuantity,
&LicensedProduct,
*pdwSupportFlags
);
dwTried = PERMANENT_ISSUE_TRIED;
}
catch( SE_Exception e ) {
dwStatus = e.getSeNumber();
}
catch(...) {
SetLastError(dwStatus = TLS_E_INTERNAL);
}
if (!bRequireTempLicense)
{
if( (dwStatus == TLS_E_PRODUCT_NOTINSTALL || dwStatus == TLS_I_FOUND_TEMPORARY_LICENSE ||
dwStatus == TLS_E_NO_LICENSE || dwStatus == TLS_E_NO_CERTIFICATE ||
dwStatus == TLS_E_RECORD_NOTFOUND) && bForwardRequest == TRUE )
{
//
// release our DB handle so others can proceed
//
ROLLBACK_TRANSACTION(pDbWorkSpace);
FREEDBHANDLE(pDbWorkSpace);
bDbHandleAcquired = FALSE;
DWORD dwForwardStatus;
DWORD dwQuantityTemp = *pdwQuantity;
//
// forward call here
//
dwForwardStatus = TLSForwardLicenseRequest(
pForward,
&dwSupportFlagsTemp,
pRequest,
bAcceptFewerLicenses,
&dwQuantityTemp,
pcbEncodedCert,
ppbEncodedCert
);
if(dwForwardStatus == TLS_I_SERVICE_STOP)
{
dwStatus = dwForwardStatus;
goto cleanup;
}
if(dwForwardStatus == ERROR_SUCCESS)
{
//
// remote server is able to issue perm. license,
// delete the license we are holding
//
*pdwSupportFlags = dwSupportFlagsTemp;
*pdwQuantity = dwQuantityTemp;
if(dwStatus == TLS_E_LICENSE_EXPIRED || dwStatus == TLS_I_FOUND_TEMPORARY_LICENSE)
{
//
// re-acquire DB handle only if we going to issue
// a temporary license
//
if(ALLOCATEDBHANDLE(pDbWorkSpace, g_GeneralDbTimeout) == FALSE)
{
dwStatus = TLS_E_ALLOCATE_HANDLE;
goto cleanup;
}
CLEANUPSTMT;
BEGIN_TRANSACTION(pDbWorkSpace);
bDbHandleAcquired = TRUE;
//
// need to mark this license has been upgraded
//
dwStatus = TLSDBMarkClientLicenseUpgraded(
USEHANDLE(pDbWorkSpace),
pRequest,
&LicensedProduct
);
if(TLS_ERROR(dwStatus))
{
ROLLBACK_TRANSACTION(pDbWorkSpace);
}
else
{
COMMIT_TRANSACTION(pDbWorkSpace);
}
bDbHandleAcquired = FALSE;
FREEDBHANDLE(pDbWorkSpace);
}
dwStatus = ERROR_SUCCESS;
// exit right here so we don't re-generate
// certificate
goto cleanup;
}
}
}
//
// if can't get license from remote, try temporary
//
// always issue a temporary license
if((dwStatus == TLS_E_PRODUCT_NOTINSTALL ||
dwStatus == TLS_E_NO_CERTIFICATE ||
dwStatus == TLS_E_NO_LICENSE ||
dwStatus == TLS_E_RECORD_NOTFOUND) && bAcceptTempLicense)
{
if(bDbHandleAcquired == FALSE)
{
//
// re-acquire DB handle only if we going to issue
// a temporary license
//
if(ALLOCATEDBHANDLE(pDbWorkSpace, g_GeneralDbTimeout) == FALSE)
{
dwStatus = TLS_E_ALLOCATE_HANDLE;
goto cleanup;
}
CLEANUPSTMT;
BEGIN_TRANSACTION(pDbWorkSpace);
bDbHandleAcquired = TRUE;
}
try {
// Issue a temporary license if can't allocate a permenent license
dwStatus=TLSDBIssueTemporaryLicense(
USEHANDLE(pDbWorkSpace),
pRequest,
NULL,
NULL,
&LicensedProduct
);
if(dwStatus == ERROR_SUCCESS)
{
dwTried = TEMPORARY_ISSUE_TRIED;
dwStatus = TLS_W_TEMPORARY_LICENSE_ISSUED;
}
}
catch( SE_Exception e ) {
dwStatus = e.getSeNumber();
}
catch(...) {
SetLastError(dwStatus = TLS_E_INTERNAL);
}
}
if(bDbHandleAcquired == TRUE)
{
if(TLS_ERROR(dwStatus))
{
ROLLBACK_TRANSACTION(pDbWorkSpace);
}
else
{
COMMIT_TRANSACTION(pDbWorkSpace);
switch (dwTried)
{
case PERMANENT_ISSUE_TRIED:
InterlockedExchangeAdd(&g_lPermanentLicensesIssued,
*pdwQuantity);
break;
case TEMPORARY_ISSUE_TRIED:
InterlockedIncrement(&g_lTemporaryLicensesIssued);
break;
}
}
FREEDBHANDLE(pDbWorkSpace);
}
//
// actually generate client certificate.
//
if(TLS_ERROR(dwStatus) == FALSE)
{
DWORD dwLicGenStatus;
//
// Post ssync job to inform other machine to delete this
// entry
//
if(LicensedProduct.dwNumLicenseLeft == 0 && LicensedProduct.bTemp == FALSE)
{
// ignore error if we can't get it out to
// other server
TLSAnnounceLKPToAllRemoteServer(LicensedProduct.dwKeyPackId, 0);
}
dwLicGenStatus = TLSGenerateClientCertificate(
g_hCryptProv,
1, // dwNumLicensedProduct
&LicensedProduct,
pRequest->wLicenseDetail,
ppbEncodedCert,
pcbEncodedCert
);
if(dwLicGenStatus != ERROR_SUCCESS)
{
dwStatus = dwLicGenStatus;
}
};
cleanup:
return dwStatus;
}
//----------------------------------------------------------
DWORD
TLSCheckLicenseMarkRequest(
IN BOOL bForwardRequest,
IN PLICENSEDPRODUCT pLicProduct,
IN DWORD cbLicense,
IN PBYTE pLicense,
OUT PUCHAR pucMarkFlags
)
{
DWORD dwStatus = TLS_E_RECORD_NOTFOUND;
DWORD dwErrCode = ERROR_SUCCESS;
LICENSEDCLIENT licClient;
// NB: licenses are in descending order, so use the first one
if ((bForwardRequest) &&
(_tcsicmp(pLicProduct->szIssuerId, (LPTSTR)g_pszServerPid) != 0))
{
// Check remote license server
TCHAR szServer[LSERVER_MAX_STRING_SIZE+2];
TCHAR *pszServer = szServer;
TLS_HANDLE hHandle;
dwStatus = TLSResolveServerIdToServer(pLicProduct->szIssuerId,
szServer);
if (dwStatus != ERROR_SUCCESS)
{
// id not registered; use name
pszServer = pLicProduct->szIssuer;
}
hHandle = TLSConnectAndEstablishTrust(pszServer, NULL);
if(hHandle == NULL)
{
dwStatus = GetLastError();
}
// RPC to remote license server
dwStatus = TLSCheckLicenseMark(
hHandle,
cbLicense,
pLicense,
pucMarkFlags,
&dwErrCode
);
TLSDisconnectFromServer(hHandle);
if ((dwStatus == ERROR_SUCCESS) && (dwErrCode == LSERVER_S_SUCCESS))
{
goto cleanup;
}
}
// we're issuing server, or issuing server not found; try looking up HWID
dwStatus = TLSFindLicense(pLicProduct,&licClient);
if (ERROR_SUCCESS == dwStatus)
{
// this field is being reused for marking (e.g. user is authenticated)
*pucMarkFlags = licClient.ucEntryStatus;
}
cleanup:
return dwStatus;
}
//----------------------------------------------------------
DWORD
TLSMarkLicenseRequest(
IN BOOL bForwardRequest,
IN UCHAR ucMarkFlags,
IN PLICENSEDPRODUCT pLicProduct,
IN DWORD cbLicense,
IN PBYTE pLicense
)
{
DWORD dwStatus = TLS_E_RECORD_NOTFOUND;
DWORD dwErrCode = ERROR_SUCCESS;
PTLSDbWorkSpace pDbWkSpace=NULL;
LICENSEDCLIENT license;
// NB: licenses are in descending order, so use the first one
if ((bForwardRequest) &&
(_tcsicmp(pLicProduct->szIssuerId, (LPTSTR)g_pszServerPid) != 0))
{
// Check remote license server
TCHAR szServer[LSERVER_MAX_STRING_SIZE+2];
TCHAR *pszServer = szServer;
TLS_HANDLE hHandle;
dwStatus = TLSResolveServerIdToServer(pLicProduct->szIssuerId,
szServer);
if (dwStatus != ERROR_SUCCESS)
{
// id not registered; use name
pszServer = pLicProduct->szIssuer;
}
hHandle = TLSConnectAndEstablishTrust(pszServer, NULL);
if(hHandle == NULL)
{
dwStatus = GetLastError();
}
// RPC to remote license server
dwStatus = TLSMarkLicense(
hHandle,
ucMarkFlags,
cbLicense,
pLicense,
&dwErrCode
);
TLSDisconnectFromServer(hHandle);
if ((dwStatus == ERROR_SUCCESS) && (dwErrCode == LSERVER_S_SUCCESS))
{
goto cleanup;
}
}
// we're issuing server, or issuing server not found; try looking up HWID
dwStatus = TLSFindLicense(pLicProduct,&license);
if((ERROR_SUCCESS == dwStatus) &&
(ALLOCATEDBHANDLE(pDbWkSpace, g_GeneralDbTimeout)))
{
CLEANUPSTMT;
BEGIN_TRANSACTION(pDbWkSpace);
TLSDBLockLicenseTable();
try {
license.ucEntryStatus |= ucMarkFlags;
dwStatus=TLSDBLicenseUpdateEntry(
USEHANDLE(pDbWkSpace),
LSLICENSE_SEARCH_MARK_FLAGS,
&license,
FALSE
);
}
catch(...) {
dwStatus = TLS_E_INTERNAL;
}
TLSDBUnlockLicenseTable();
if(TLS_ERROR(dwStatus))
{
ROLLBACK_TRANSACTION(pDbWkSpace);
}
else
{
COMMIT_TRANSACTION(pDbWkSpace);
InterlockedIncrement(&g_lLicensesMarked);
}
FREEDBHANDLE(pDbWkSpace);
}
else
{
dwStatus=TLS_E_ALLOCATE_HANDLE;
}
cleanup:
return dwStatus;
}