////////////////////////////////////////////////////////
// excerpt from delegate.idl
//
[
uuid(9b8c32f3-249a-11d2-a7bb-006008d25ccf),
object,
local
]
interface IDelegatorFactory : IUnknown
{
typedef enum _DelegatorOptions
{
DO_MBV_INPROC = 0x00000001,
DO_MBV_LOCAL = 0x00000002,
DO_MBV_DIFFERENTMACHINE = 0x00000004,
DO_MBV_ALL = 0x00000007,
DO_MAINTAIN_IDENTITY = 0x00000008
} DelegatorOptions;
HRESULT CreateDelegator( [in] IUnknown* pUnkOuter,
[in] IUnknown* pUnkInner,
[in] CLSID* pclsidHook,
[in] IUnknown* pHook,
[in] DWORD grfOptions,
[in] REFIID iid,
[out, iid_is(iid)] void** ppv );
}
Figure 6 IAlternateCredentialDelegatorHook
////////////////////////////////////////////////////////
// excerpt from delegate.idl
//
[
uuid(9b8c32f8-249a-11d2-a7bb-006008d25ccf),
object,
local
]
interface IAlternateCredentialDelegatorHook : IUnknown
{
typedef enum _ACDH_OPTIONS
{
ACDH_AUTHNSVC = 0x00000001,
ACDH_AUTHZSVC = 0x00000002,
ACDH_SERVERPRINCIPAL = 0x00000004,
ACDH_AUTHNLEVEL = 0x00000008,
ACDH_IMPLEVEL = 0x00000010,
ACDH_CREDENTIALS = 0x00000020,
ACDH_CAPS = 0x00000040
} ACDH_OPTIONS;
HRESULT Init( [in] DWORD grfOptions,
[in] DWORD nAuthnSvc,
[in] DWORD nAuthzSvc,
[in] const OLECHAR* pszServerPrincipal,
[in] DWORD nAuthnLevel,
[in] DWORD nImpLevel,
[in] const OLECHAR* pszAuthority,
[in] const OLECHAR* pszPrincipal,
[in] const OLECHAR* pszPassword,
[in] DWORD grfCaps );
}
Figure 7 Using the Alternate Credentials Hook
////////////////////////////////////////////////////////
// acdh.cpp
//
// This example demonstrates the use of the alternate
// credentials hook, with a fictitious penguin object
//
#define _WIN32_WINNT 0x403
#include <windows.h>
#include "delegate.h"
#include "delegate_i.c"
// imaginary header files with penguin interface & GUID definitions
#include "penguin.h"
#include "penguin_i.c"
// This is a useful helper function that applies the delegator
// coupled with an initialized alternate credentials hook
HRESULT WrapWithAlternateCredentials(
IUnknown*& rpUnk,
const wchar_t* pszAuthority,
const wchar_t* pszPrincipal,
const wchar_t* pszPassword,
REFIID iid, void** ppv )
{
IAlternateCredentialDelegatorHook* phook = 0;
HRESULT hr = CoCreateInstance( CLSID_CoAlternateCredentialDelegatorHook,
0, CLSCTX_INPROC_SERVER,
IID_IAlternateCredentialDelegatorHook,
(void**)&phook );
if ( SUCCEEDED( hr ) )
{
hr = phook->Init( ACDH_CREDENTIALS, 0, 0, 0, 0, 0,
pszAuthority, pszPrincipal, pszPassword, 0 );
if ( SUCCEEDED( hr ) )
{
IDelegatorFactory* pfactory = 0;
hr = CoGetClassObject( CLSID_CoDelegator, CLSCTX_INPROC_SERVER, 0,
IID_IDelegatorFactory, (void**)&pfactory );
if ( SUCCEEDED( hr ) )
{
hr = pfactory->CreateDelegator( 0, rpUnk,
0, phook,
DO_MBV_INPROC,
iid, ppv );
pfactory->Release();
}
}
phook->Release();
}
// release the original interface pointer so the only pointers we'll see
// for this object will actually point to the delegator.
rpUnk->Release();
rpUnk = 0;
return hr;
}
// This code creates a penguin object on the requested
// machine, then makes calls through various interfaces
// using the supplied credentials.
HRESULT CreateAndUsePenguinAsUser( const wchar_t* pszMachine,
const wchar_t* pszAuthority,
const wchar_t* pszPrincipal,
const wchar_t* pszPassword )
{
// Standard client-side code required to activate an object
// using alternate credentials
COAUTHIDENTITY caid = { const_cast<wchar_t*>(pszPrincipal),
lstrlenW(pszPrincipal),
const_cast<wchar_t*>(pszAuthority),
lstrlenW(pszAuthority),
const_cast<wchar_t*>(pszPassword),
lstrlenW(pszPassword),
2 }; // Unicode
COAUTHINFO cai = { RPC_C_AUTHN_WINNT, 0, 0,
RPC_C_AUTHN_LEVEL_PKT,
RPC_C_IMP_LEVEL_IMPERSONATE,
&caid, 0 };
COSERVERINFO csi = { 0, const_cast<wchar_t*>(pszMachine), &cai, 0 };
MULTI_QI mqi = { &IID_IAnimal, 0, 0 };
HRESULT hr = CoCreateInstanceEx( CLSID_CoPenguin, 0,
CLSCTX_ALL, &csi,
1, &mqi );
if ( SUCCEEDED( hr ) )
{
// Here's where the UD gets involved to automatically apply
// the alternate credentials to each interface exposed from the object
IAnimal* pAnimal = 0;
hr = WrapWithAlternateCredentials( mqi.pItf,
pszAuthority,
pszPrincipal,
pszPassword,
IID_IAnimal, (void**)&pAnimal );
if ( SUCCEEDED( hr ) )
{
pAnimal->Eat(); // Eat goes out as Bill
pAnimal->Sleep(); // Sleep goes out as Bill
ISwimmer* pSwimmer = 0; // QI goes out as Bill
hr = pAnimal->QueryInterface( IID_ISwimmer, (void**)&pSwimmer );
if ( SUCCEEDED( hr ) )
{
pSwimmer->Dive(); // Dive goes out as Bill
pSwimmer->Swim(); // Swim goes out as Bill
pSwimmer->Release(); // This Release doesn't send packets
}
pAnimal->Release(); // Release goes out as Bill,
} // only if OS >= NT4SP4
}
return hr;
}
void main()
{
CreateAndUsePenguinAsUser( L"OvalOffice", // machine name
L"US", // authority
L"BillClinton", // principal
L"notacrook" ); // password
}
Figure 10 DO_MBV_XXX Summary
DO_MBV_XXX Options
|
MBV Boundary
|
INPROC
|
This Process
|
INPROC | LOCAL
|
This Machine
|
INPROC | LOCAL | DIFFERENTMACHINE
|
No Boundary
|