//+-------------------------------------------------------------------------- // // 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; }