Setting the Default Process Security Level Using C++

When a client application logs on to Windows Management Instrumentation (WMI) for the first time, it must set the default process security level with a call to CoInitializeSecurity. COM uses the information in the call to determine how much security another process must have to access the client application process.

The following sections are discussed in this topic:

For most client applications the arguments shown in the following example set the default security for WMI.

HRESULT hr = NULL;
hr = CoInitializeSecurity(
        NULL,                       // security descriptor
       -1,                          // use this simple setting
       NULL,                        // use this simple setting
       NULL,                        // reserved
       RPC_C_AUTHN_LEVEL_DEFAULT,   // authentication level  
       RPC_C_IMP_LEVEL_IMPERSONATE, // impersonation level
       NULL,                        // use this simple setting
       EOAC_NONE,                   // no special capabilities
       NULL);                          // reserved

if (FAILED(hr))
{
  CoUninitialize();
  cout << "Failed to initialize security. Error code = 0x"
       << hex << hr << endl;
  return;
}

The code requires the following references and #include statements to compile correctly.

#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <Wbemidl.h>

#pragma comment(lib, "wbemuuid.lib")

Setting the authentication level to RPC_C_AUTHN_LEVEL_DEFAULT allows DCOM to negotiate the authentication level to match the security demands of the target computer. For more information, see Changing the Default Authentication Credentials Using C++ and Changing the Default Impersonation Settings Using C++.

Changing the Default Authentication Credentials Using C++

The default authentication credentials work for most situations, but you might need to use different authentication credentials in different situations. For example, you might want to add encryption to the authentication procedures.

The following table lists and describes the different levels of authentication.

Authentication level Description
RPC_C_AUTHN_LEVEL_DEFAULT Default security authentication.
RPC_C_AUTHN_LEVEL_NONE No authentication.
RPC_C_AUTHN_LEVEL_CONNECT Authentication only when the client creates a relationship with the server.
RPC_C_AUTHN_LEVEL_CALL Authentication each time the server receives an RPC.
RPC_C_AUTHN_LEVEL_PKT Authentication each time the server receives data from a client.
RPC_C_AUTHN_LEVEL_PKT_INTEGRITY Authentication that no data from the packet has been modified.
RPC_C_AUTHN_LEVEL_PKT_PRIVACY Includes all previous authentication levels, and encrypts the value of each RPC call.

 

You can specify the default authentication credentials for multiple users by using a SOLE_AUTHENTICATION_LIST structure in the pAuthList parameter of CoInitializeSecurity.

The following code example shows how to change the authentication credentials.

// Auth Identity structure
SEC_WINNT_AUTH_IDENTITY_W        authidentity;
SecureZeroMemory( &authidentity, sizeof(authidentity) );

authidentity.User = L"MyUser";
authidentity.UserLength = wcslen( authidentity.User );
authidentity.Domain = L"MyDomain ";
authidentity.DomainLength = wcslen( authidentity.Domain );
authidentity.Password = L"";
authidentity.PasswordLength = wcslen( authidentity.Password );
authidentity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;

SecureZeroMemory( authninfo, sizeof(SOLE_AUTHENTICATION_INFO)*2 );

// NTLM Settings
authninfo[0].dwAuthnSvc = RPC_C_AUTHN_WINNT;
authninfo[0].dwAuthzSvc = RPC_C_AUTHZ_NONE;
authninfo[0].pAuthInfo = &authidentity;

// Kerberos Settings
authninfo[1].dwAuthnSvc = RPC_C_AUTHN_GSS_KERBEROS ;
authninfo[1].dwAuthzSvc = RPC_C_AUTHZ_NONE;
authninfo[1].pAuthInfo = &authidentity;

SOLE_AUTHENTICATION_LIST    authentlist;

authentlist.cAuthInfo = 2;
authentlist.aAuthInfo = authninfo;

CoInitializeSecurity( 
  NULL, 
  -1, 
  NULL, 
  NULL, 
  RPC_C_AUTHN_LEVEL_CALL, 
  RPC_C_IMP_LEVEL_IMPERSONATE,
  &authentlist, 
  EOAC_NONE,
  NULL);

Changing the Default Impersonation Levels Using C++

COM provides default security levels read from the system registry. However, unless specifically modified, the registry settings set the impersonation level too low for WMI to function. Typically, the default impersonation level is RPC_C_IMP_LEVEL_IDENTIFY, but WMI needs at least RPC_C_IMP_LEVEL_IMPERSONATE to function with most providers, and you might encounter a situation where you need to set a higher level of impersonation. For more information, see Connecting to WMI on a Remote Computer. The following table lists the different levels of impersonation.

Level Description
RPC_C_IMP_LEVEL_DEFAULT The operating system chooses the level of impersonation.
RPC_C_IMP_LEVEL_ANONYMOUS The server can impersonate the client, but the impersonation token cannot be used for anything.
RPC_C_IMP_LEVEL_IDENTIFY The server can obtain the identity of the client and impersonate the client for ACL checking.
RPC_C_IMP_LEVEL_IMPERSONATE The server can impersonate the client across one computer boundary.
RPC_C_IMP_LEVEL_DELEGATE The server can impersonate the client across multiple boundaries, and can make calls on behalf of the client.