/*++ Copyright (c) 1994 Microsoft Corporation Module Name: rpcstub.c Abstract: License Logging Service client stubs. Author: Arthur Hanson (arth) 06-Dec-1994 Environment: User mode only. Revision History: --*/ #include #include #include #include #include #include #include #include #include "lsapi_c.h" #include // #define API_TRACE 1 BOOLEAN LLSUp = FALSE; //swi, code review, why we hard code the length here, where is 72 from? winnt.h has a define already, SECURITY_MAX_SID_SIZE #define MAX_EXPECTED_SID_LENGTH 72 LPTSTR pszStringBinding = NULL; RTL_CRITICAL_SECTION LPCInitLock; static HANDLE LpcPortHandle = NULL; ///////////////////////////////////////////////////////////////////////// NTSTATUS LLSReInitLPC( ) /*++ Routine Description: This service connects to the LLS server and initializes the LPC port. Arguments: Return Value: STATUS_SUCCESS - The call completed successfully. --*/ { RPC_STATUS Status = STATUS_SUCCESS; LPTSTR pszUuid = NULL; LPTSTR pszProtocolSequence = NULL; LPTSTR pszNetworkAddress = NULL; LPTSTR pszEndpoint = NULL; LPTSTR pszOptions = NULL; pszProtocolSequence = TEXT("ncalrpc"); pszEndpoint = TEXT(LLS_LPC_ENDPOINT); pszNetworkAddress = NULL; if (LLSUp) { LLSUp = FALSE; if (pszStringBinding != NULL) { Status = RpcStringFree(&pszStringBinding); pszStringBinding = NULL; } if (Status == STATUS_SUCCESS) { if (lsapirpc_handle != NULL) { Status = RpcBindingFree(&lsapirpc_handle); } lsapirpc_handle = NULL; } } try { // Compose a string binding Status = RpcStringBindingComposeW(pszUuid, pszProtocolSequence, pszNetworkAddress, pszEndpoint, pszOptions, &pszStringBinding); } except (TRUE) { Status = RpcExceptionCode(); } if(Status) { #if DBG dprintf(TEXT("NTLSAPI RpcStringBindingComposeW Failed: 0x%lX\n"), Status); #endif if (pszStringBinding != NULL) { RpcStringFree(&pszStringBinding); pszStringBinding = NULL; } return I_RpcMapWin32Status(Status); } // Bind using the created string binding... try { Status = RpcBindingFromStringBindingW(pszStringBinding, &lsapirpc_handle); } except (TRUE) { Status = RpcExceptionCode(); } if(Status) { #if DBG dprintf(TEXT("NTLSAPI RpcBindingFromStringBindingW Failed: 0x%lX\n"), Status); #endif // lsapirpc_handle = NULL; if (pszStringBinding != NULL) { RpcStringFree(&pszStringBinding); pszStringBinding = NULL; } return I_RpcMapWin32Status(Status); } LLSUp = TRUE; return I_RpcMapWin32Status(Status); } // LLSReInitLPC ///////////////////////////////////////////////////////////////////////// NTSTATUS LLSInitLPC( ) /*++ Routine Description: This service connects to the LLS server and initializes the LPC port. Arguments: Return Value: STATUS_SUCCESS - The call completed successfully. --*/ { NTSTATUS status; status = RtlInitializeCriticalSection(&LPCInitLock); lsapirpc_handle = NULL; return status; } // LLSInitLPC ///////////////////////////////////////////////////////////////////////// NTSTATUS LLSCloseLPC( ) /*++ Routine Description: This closes the LPC port connection to the service. Arguments: Return Value: STATUS_SUCCESS - The call completed successfully. --*/ { RPC_STATUS Status = STATUS_SUCCESS, Status2 = STATUS_SUCCESS; RtlEnterCriticalSection(&LPCInitLock); LLSUp = FALSE; if (pszStringBinding != NULL) { Status = RpcStringFree(&pszStringBinding); pszStringBinding = NULL; } if (lsapirpc_handle != NULL) { Status2 = RpcBindingFree(&lsapirpc_handle); } if (Status == STATUS_SUCCESS) Status = Status2; lsapirpc_handle = NULL; RtlLeaveCriticalSection(&LPCInitLock); return Status; } // LLSCloseLPC ///////////////////////////////////////////////////////////////////////// NTSTATUS LLSLicenseRequest2 ( IN LPWSTR ProductName, IN LPWSTR Version, IN ULONG DataType, IN BOOLEAN IsAdmin, IN PVOID Data, OUT PHANDLE LicenseHandle ) /*++ Arguments: ProductName - Version - DataType - IsAdmin - Data - LicenseHandle - Return Status: STATUS_SUCCESS - Indicates the service completed successfully. Routine Description: --*/ { WCHAR ProductID[MAX_PRODUCT_NAME_LENGTH + MAX_VERSION_LENGTH + 2]; NTSTATUS Status = STATUS_SUCCESS; BOOL Close = FALSE; ULONG VersionIndex; ULONG Size = 0; ULONG i; LICENSE_HANDLE RpcLicenseHandle; BOOL bActuallyConnect = TRUE; HRESULT hr; size_t cb; ZeroMemory(&RpcLicenseHandle, sizeof(RpcLicenseHandle)); // // Get this out of the way in-case anything goes wrong // *LicenseHandle = NULL; // // If LicenseService isn't running (no LPC port) then just return // dummy info - and let the user on. // RtlEnterCriticalSection(&LPCInitLock); if (!LLSUp) Status = LLSReInitLPC(); RtlLeaveCriticalSection(&LPCInitLock); if (!NT_SUCCESS(Status)) return STATUS_SUCCESS; if (((i = lstrlen(ProductName)) > MAX_PRODUCT_NAME_LENGTH) || (lstrlen(Version) > MAX_VERSION_LENGTH)) return STATUS_SUCCESS; // // Create productID - product name + version string. // cb = sizeof(ProductID); hr = StringCbCopy(ProductID, cb, ProductName); ASSERT(SUCCEEDED(hr)); hr = StringCbCat(ProductID, cb, TEXT(" ")); ASSERT(SUCCEEDED(hr)); hr = StringCbCat(ProductID, cb, Version); ASSERT(SUCCEEDED(hr)); VersionIndex = i; // // Based on DataType figure out if we are doing a name or a SID // and copy the data appropriatly // if (DataType == NT_LS_USER_NAME) { Size = lstrlen((LPWSTR) Data); //swi, code review, MAX_USER_NAME_LENGTH is defined in inc\llsconst.h as 37 where did 37 come from? if (Size > MAX_USER_NAME_LENGTH) return STATUS_SUCCESS; Size = (Size + 1) * sizeof(TCHAR); } if (DataType == NT_LS_USER_SID) { // // Friggin SID, so need to copy it manually. // WARNING: This makes it dependent on the structure of the // SID!!! // Size = RtlLengthSid( (PSID) Data); if (Size > MAX_EXPECTED_SID_LENGTH) return STATUS_SUCCESS; } //swi, code review, what happen if DataType is not NT_LS_USER_NAME or NT_LS_USER_SID? //- it at least pass the call with invalid data to rpc. we should block from here. //- check with the server side code, it doesn't validate DataType either and it actually goes through the loop to check it against all users in cached list. mostly performance hit. // // Call the Server. // try { Status = LlsrLicenseRequestW( &RpcLicenseHandle, ProductID, VersionIndex, IsAdmin, DataType, Size, (PBYTE) Data ); } except (TRUE) { #if DBG Status = I_RpcMapWin32Status(RpcExceptionCode()); if (Status != RPC_NT_SERVER_UNAVAILABLE) { dprintf(TEXT("ERROR NTLSAPI.DLL: RPC Exception: 0x%lX\n"), Status); // ASSERT(FALSE); } #endif *LicenseHandle = NULL; Status = STATUS_SUCCESS; bActuallyConnect = FALSE; } if (Close) LLSCloseLPC(); // This is really a ULONG, we just treated it as a PVOID so // RPC would treat is as a context handle if(bActuallyConnect == TRUE) *LicenseHandle = RpcLicenseHandle; return Status; } // LLSLicenseRequest ///////////////////////////////////////////////////////////////////////// NTSTATUS LLSLicenseRequest ( IN LPWSTR ProductName, IN LPWSTR Version, IN ULONG DataType, IN BOOLEAN IsAdmin, IN PVOID Data, OUT PULONG LicenseHandle ) /*++ Arguments: ProductName - Version - DataType - IsAdmin - Data - LicenseHandle - Return Status: STATUS_SUCCESS - Indicates the service completed successfully. Routine Description: --*/ { HANDLE RealLicenseHandle; NTSTATUS status; #pragma warning (push) #pragma warning (disable : 4127) //conditional expression is constant if (sizeof(ULONG) == sizeof(HANDLE)) #pragma warning (pop) { // Should still work on Win32 status = LLSLicenseRequest2(ProductName,Version,DataType,IsAdmin,Data,&RealLicenseHandle); if (NULL != LicenseHandle) *LicenseHandle = PtrToUlong(RealLicenseHandle); } else { status = STATUS_NOT_IMPLEMENTED; if (NULL != LicenseHandle) *LicenseHandle = (ULONG) 0xFFFFFFFF; } return status; } ///////////////////////////////////////////////////////////////////////// NTSTATUS LLSLicenseFree2 ( IN HANDLE LicenseHandle ) /*++ Arguments: LicenseHandle - Return Status: STATUS_SUCCESS - Indicates the service completed successfully. --*/ { BOOL Close = FALSE; NTSTATUS Status; LICENSE_HANDLE RpcLicenseHandle = (LICENSE_HANDLE) LicenseHandle; // // If LicenseService isn't running (no LPC port) then just return // dummy info - and let the user on. // if (!LLSUp) { return STATUS_SUCCESS; } // // Call the Server. // try { Status = LlsrLicenseFree( &RpcLicenseHandle ); } except (TRUE) { #if DBG Status = I_RpcMapWin32Status(RpcExceptionCode()); if (Status != RPC_NT_SERVER_UNAVAILABLE) { dprintf(TEXT("ERROR NTLSAPI.DLL: RPC Exception: 0x%lX\n"), Status); // ASSERT(FALSE); } #endif Status = STATUS_SUCCESS; } if (Close) LLSCloseLPC(); return Status; } // LLSLicenseFree ///////////////////////////////////////////////////////////////////////// NTSTATUS LLSLicenseFree ( IN ULONG LicenseHandle ) /*++ Arguments: LicenseHandle - Return Status: STATUS_SUCCESS - Indicates the service completed successfully. --*/ { #pragma warning (push) #pragma warning (disable : 4127) //conditional expression is constant if (sizeof(ULONG) == sizeof(HANDLE)) #pragma warning (pop) { // Should still work on Win32 return LLSLicenseFree2(ULongToPtr(LicenseHandle)); } else { return STATUS_NOT_IMPLEMENTED; } }