//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 2000. // // File: U H C O M M O N . C P P // // Contents: Common UPnP Device Host code // // Notes: // // Author: mbend 21 Sep 2000 // //---------------------------------------------------------------------------- #include "pch.h" #pragma hdrstop #include "ncbase.h" #include "uhcommon.h" static PSID g_pNetworkSid; HRESULT HrUDNStringToGUID(const wchar_t * szUUID, UUID & uuid) { HRESULT hr = S_OK; // Size of uuid:UUID const long nUDNStringLength = 41; // Size of uuid: prefix const long nUDNPrefix = 5; if(nUDNStringLength != lstrlen(szUUID)) { TraceTag(ttidError, "GUIDFromString: Invalid GUID string"); hr = E_INVALIDARG; } if(SUCCEEDED(hr)) { // Skip past "uuid:" RPC_STATUS status; status = UuidFromString((unsigned short *)(const_cast(&szUUID[nUDNPrefix])), &uuid); if(RPC_S_INVALID_STRING_UUID == status) { TraceTag(ttidError, "GUIDFromString: Invalid GUID string"); hr = E_INVALIDARG; } } TraceHr(ttidError, FAL, hr, FALSE, "HrUDNStringToGUID"); return hr; } HRESULT HrContentURLToGUID(const wchar_t * szURL, GUID & guid) { HRESULT hr = S_OK; const wchar_t * sz = szURL; while (*sz && *sz != '=') { sz++; } if (*sz == '=') { sz++; hr = HrUDNStringToGUID(sz, guid); } TraceHr(ttidError, FAL, hr, FALSE, "HrContentURLToGUID"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrSysAllocString // // Purpose: Simple HR wrapper for HrSysAllocString // // Arguments: // pszSource [in] Source string (WCHAR) // pbstrDest [out] Output param -- pointer to BSTR // // Returns: S_OK on success, E_OUTOFMEMORY if the alloc failed. // // Author: jeffspr 16 Sep 1999 // // Notes: // HRESULT HrSysAllocString(LPCWSTR pszSource, BSTR *pbstrDest) { HRESULT hr = S_OK; Assert(pszSource); Assert(pbstrDest); *pbstrDest = SysAllocString(pszSource); if (!*pbstrDest) { TraceTag(ttidError, "HrSysAllocString failed on %S", pszSource); hr = E_OUTOFMEMORY; } TraceHr(ttidError, FAL, hr, FALSE, "HrSysAllocString"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrIsAllowedCOMCallLocality // // Purpose: Used to check whether the caller of a method on a COM interface // should be allowed to call that method, based on whether it's // a call from the local machine or across the network // // Arguments: // clAllowedCallLocality - bitmask of allowed COM call localities // // Returns : // E_ACCESSDENIED if access is denied, S_OK if access is granted, error HRESULT otherwise. // // Author: AMallet 15 Mar 2002 // HRESULT HrIsAllowedCOMCallLocality( IN CALL_LOCALITY clAllowedCallLocality ) { HRESULT hr = S_OK; CALL_LOCALITY clCurrentCallLocality; // // Retrieve the current call locality // if ( FAILED( hr = HrGetCurrentCallLocality( &clCurrentCallLocality ) )) { TraceHr(ttidRegistrar,FAL, hr, FALSE,"HrGetCurrentCallLocality"); } else { // // If current call locality isn't one of the allowed ones, deny access // if ( ( clCurrentCallLocality & clAllowedCallLocality ) == 0 ) { TraceTag(ttidRegistrar, "Caller locality %d, granted locality %d, access denied.", clCurrentCallLocality, clAllowedCallLocality); hr = E_ACCESSDENIED; } } return hr; } //+--------------------------------------------------------------------------- // // Function: HrGetCurrentCallLocality // // Purpose: Checks locality (in-proc, on same machine, on different machine) of // caller of a COM method // // Arguments: // pclCurrentCallLocality [out] - set to // // Author: radus 7 Mar 2002 // // Notes: Currently implemented by checking the existence of the NETWORK // SID in the impersonation token of the calling thread HRESULT HrGetCurrentCallLocality( OUT CALL_LOCALITY *pclCurrentCallLocality ) { HRESULT hr = S_OK; HANDLE hToken = NULL; BOOL fImpersonated = FALSE; if ( !pclCurrentCallLocality || !g_pNetworkSid ) { return E_INVALIDARG; } // // Impersonate client // hr = CoImpersonateClient(); if(SUCCEEDED(hr)) { fImpersonated = TRUE; // // open impersonation token // if( OpenThreadToken( GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken)) { // // Check whether the token has the NETWORK SID in it; if it does, // assume the caller is on a different machine. Else, the caller // is on the local machine. // // Note : This isn't entirely foolproof in that it's possible for a local // user's token to also have the NETWORK SID eg if they called LsaLogonUser // with the Network LogonType, but it's the best we can do for XP SP1. // COM may have a way to get more accurate information for .NET Server. // BOOL fIsMember; if( CheckTokenMembership( hToken, g_pNetworkSid, &fIsMember)) { if ( fIsMember ) { *pclCurrentCallLocality = CALL_LOCALITY_DIFFERENTMACHINE; } else { *pclCurrentCallLocality = (CALL_LOCALITY) ( CALL_LOCALITY_LOCAL | CALL_LOCALITY_INPROC ); } } else { hr = HrFromLastWin32Error(); TraceHr(ttidRegistrar, FAL, hr, FALSE, "CheckTokenMembership"); } } else { hr = HrFromLastWin32Error(); TraceHr(ttidRegistrar, FAL, hr, FALSE, "OpenThreadToken"); } } else { // // If the COM call is a direct in-proc v-tbl call, with no proxy, the call to // CoImpersonateClient will return RPC_E_CALL_COMPLETE; in this case, // we know the caller is in-proc to us // if ( hr == RPC_E_CALL_COMPLETE ) { *pclCurrentCallLocality = CALL_LOCALITY_INPROC; hr = S_OK; } else { TraceHr(ttidRegistrar,FAL, hr, FALSE, "CoImpersonateClient"); } } if ( hToken ) { CloseHandle( hToken ); } if ( fImpersonated ) { CoRevertToSelf(); } TraceHr(ttidRegistrar, FAL, hr, FALSE, "HrCheckAccessRights"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrCreateNetworkSID // // Purpose: Allocates and initializes a SID structure with the NETWORK SID // // Arguments: // None // // Author: AMallet 16 Mar 2002 // HRESULT HrCreateNetworkSID() { HRESULT hr = S_OK; SID_IDENTIFIER_AUTHORITY id = SECURITY_NT_AUTHORITY; // // Allocate the NETWORK SID // if( !AllocateAndInitializeSid( &id, 1, SECURITY_NETWORK_RID, 0,0,0,0,0,0,0, &g_pNetworkSid ) ) // S-1-5-2 { hr = HrFromLastWin32Error(); TraceHr(ttidError, FAL, hr, FALSE, "AllocateAndInitializeSid"); } return hr; } //+--------------------------------------------------------------------------- // // Function: CleanupNetworkSID // // Purpose: Cleans up the NETWORK SID allocated via call to HrCreateNetworkSID // // Arguments: // None // // Author: AMallet 16 Mar 2002 // VOID CleanupNetworkSID() { if ( g_pNetworkSid ) { FreeSid( g_pNetworkSid ); } }