Setting Authentication Using C++

One of the main tasks of IWbemLocator::ConnectServer for WMI is returning a pointer to an IWbemServices proxy. Through the IWbemServices proxy, you can access the capabilities of the WMI infrastructure. However, the pointer to the IWbemServices proxy has the identity of the client application process and not the identity of the IWbemServices process. Therefore, if you attempt to access IWbemServices with the pointer, you can receive an access-denied code such as E_ACCESSDENIED. To avoid the access-denied error, you must set the identity of the new pointer with a call to the CoSetProxyBlanket interface.

A provider can set the security on a namespace so that no data is returned unless you use packet privacy (PktPrivacy) in your connection to that namespace. This ensures that data is encrypted as it crosses the network. If you try to set a lower authentication level, you will get an access denied message. For more information, see Setting Namepace Security Descriptors.

For more information about setting authentication in scripting, see Setting the Default Process Security Level Using VBScript.

Setting Security on a Remote IUnknown Interface

In some situations, more access to a server than just a pointer to a proxy is required. At times, you may need to gain a secure connection to the IUnknown interface of the proxy. Using IUnknown, you can query the remote system for interfaces and other necessary techniques.

When a proxy is located on a remote computer, the server delegates all calls to the IUnknown interface of the proxy to the IUnknown interface. For example, if you call QueryInterface on a proxy and the requested interface was not part of the proxy, the proxy sends the call to the remote server. In turn, the remote server checks for the appropriate interface support. If the server does support the interface, COM marshals a new proxy back to the client so that the application can use the new interface.

Problems arise if the client does not have access permissions to the remote server, yet is using the credentials of a user that does. In this situation, any attempt to access QueryInterface on the remote server fails. The final release on the proxy fails as well, because the current user does not have access to the remote server. A symptom of this is a one or two second lag before the client application fails the final proxy release. The failure occurs because COM attempted to access the remote server using the default security settings of the current user, which do not include the modified credentials that allowed access to the server in the first place. For more information, see Setting the Security on IWbemServices and Other Proxies.

To avoid the failed connection, use CoSetProxyBlanket to explicitly set the security authentication on the pointer returned from IUnknown. Using CoSetProxyBlanket, you can ensure that the remote server receives the correct authentication identity.

The following code example shows how to use CoSetProxyBlanket to access a remote IUnknown interface.

SEC_WINNT_AUTH_IDENTITY_W* pAuthIdentity = 
   new SEC_WINNT_AUTH_IDENTITY_W;
ZeroMemory(pAuthIdentity, sizeof(SEC_WINNT_AUTH_IDENTITY_W));

pAuthIdentity->User = new WCHAR[32];
StringCbCopyW(pAuthIdentity->User,sizeof(L"MyUser"),L"MyUser");
pAuthIdentity->UserLength = wcslen(pAuthIdentity->User);

pAuthIdentity->Domain = new WCHAR[32];
StringCbCopyW(pAuthIdentity->Domain,sizeof(L"MyDomain"),L"MyDomain");
pAuthIdentity->DomainLength = wcslen(pAuthIdentity->Domain);

pAuthIdentity->Password = new WCHAR[32];
pAuthIdentity->Password[0] = NULL;
pAuthIdentity->PasswordLength = wcslen( pAuthIdentity->Password);

pAuthIdentity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;

IWbemServices* pWbemServices = 0;

// Set proxy security
hr = CoSetProxyBlanket(pWbemServices, 
                       RPC_C_AUTHN_DEFAULT, 
                       RPC_C_AUTHZ_NONE, 
                       COLE_DEFAULT_PRINCIPAL, 
                       RPC_C_AUTHN_LEVEL_DEFAULT, 
                       RPC_C_IMP_LEVEL_IMPERSONATE, 
                       pAuthIdentity, 
                       EOAC_NONE 
);
if (FAILED(hr))
{
   cout << "Count not set proxy blanket. Error code = 0x"
        << hex << hr << endl;
   pWbemServices->Release();
   return 1;
}

// Set IUnknown security
IUnknown*    pUnk = NULL;
pWbemServices->QueryInterface(IID_IUnknown, (void**) &pUnk);

hr = CoSetProxyBlanket(pUnk, 
                       RPC_C_AUTHN_DEFAULT, 
                       RPC_C_AUTHZ_NONE, 
                       COLE_DEFAULT_PRINCIPAL, 
                       RPC_C_AUTHN_LEVEL_DEFAULT, 
                       RPC_C_IMP_LEVEL_IMPERSONATE, 
                       pAuthIdentity, 
                       EOAC_NONE 
);
if (FAILED(hr))
{
   cout << "Count not set proxy blanket. Error code = 0x"
        << hex << hr << endl;
   pUnk->Release();
   pWbemServices->Release();
   delete [] pAuthIdentity->User;
   delete [] pAuthIdentity->Domain;
   delete [] pAuthIdentity->Password;
   delete pAuthIdentity;   
   return 1;
}

// cleanup IUnknown
pUnk->Release();

//
// Perform a bunch of operations
//

// Cleanup
pWbemServices->Release();

delete [] pAuthIdentity->User;
delete [] pAuthIdentity->Domain;
delete [] pAuthIdentity->Password;

delete pAuthIdentity;

Note

When you set security on the IUnknown interface of a proxy, COM creates a copy of the proxy that cannot be released until you call CoUninitialize.

 

Setting Authentication in WMI