323 lines
8.1 KiB
C++
323 lines
8.1 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// 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<wchar_t*>(&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 );
|
|
}
|
|
}
|