C++ を使用した既定のプロセス セキュリティ レベルの設定

クライアント アプリケーションが Windows Management Instrumentation (WMI) に初めてログオンするときは、CoInitializeSecurity の呼び出しで既定のプロセス セキュリティ レベルを設定する必要があります。 COM は、呼び出し内の情報を使用して、他のプロセスがクライアント アプリケーション プロセスにアクセスするためにどれだけのセキュリティを必要とするかを調べます。

このトピックでは次のセクションを扱います。

ほとんどのクライアント アプリケーションでは、次の例に示す引数で 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;
}

コードは、正しくコンパイルするために次の参照と #include ステートメントが必要です。

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

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

認証レベルを RPC_C_AUTHN_LEVEL_DEFAULT に設定すると、DCOM はターゲット コンピューターのセキュリティ需要に合わせて認証レベルをネゴシエートできます。 詳細については、「C++ を使用した既定の認証資格情報の変更」と「C++ を使用した既定の偽装設定の変更」を参照してください。

C++ を使用した既定の認証資格情報の変更

既定の認証資格情報はほとんどの状況で機能しますが、さまざまな状況で異なる認証資格情報を使用したくなる場合もあるでしょう。 たとえば、認証手順に暗号化を追加するのもよいかもしれません。

次の表に、さまざまな認証レベルの一覧と説明を示します。

認証レベル 説明
RPC_C_AUTHN_LEVEL_DEFAULT 既定のセキュリティ認証。
RPC_C_AUTHN_LEVEL_NONE 認証なし。
RPC_C_AUTHN_LEVEL_CONNECT クライアントがサーバーとのリレーションシップを作成するときに限った認証。
RPC_C_AUTHN_LEVEL_CALL サーバーが RPC を受け取るたびに行われる認証。
RPC_C_AUTHN_LEVEL_PKT サーバーがクライアントからデータを受け取るたびに行われる認証。
RPC_C_AUTHN_LEVEL_PKT_INTEGRITY パケットからのデータが変更されていないことの認証。
RPC_C_AUTHN_LEVEL_PKT_PRIVACY 以前のすべての認証レベルが含まれており、各 RPC 呼び出しの値が暗号化されます。

 

CoInitializeSecuritypAuthList パラメーターで SOLE_AUTHENTICATION_LIST 構造を使用することで、複数のユーザーの既定の認証資格情報を指定できます。

次のコード例は、認証資格情報を変更する方法を示しています。

// 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);

C++ を使用した既定の偽装レベルの変更

COM から、システム レジストリから読み取られた既定のセキュリティ レベルが提供されます。 ただし、特に変更されない限り、レジストリ設定により設定される偽装レベルは、WMI が機能するには低すぎます。 通常、既定の偽装レベルは RPC_C_IMP_LEVEL_IDENTIFY ですが、WMI はほとんどのプロバイダーで機能するためには RPC_C_IMP_LEVEL_IMPERSONATE 以上を必要とし、もっと高いレベルの偽装の設定が必要になる場合もあるかもしれません。 詳細については、「リモート コンピューター上の WMI への接続」を参照してください。 次の表に、偽装のさまざまなレベルを示します。

Level 説明
RPC_C_IMP_LEVEL_DEFAULT オペレーティング システムが偽装のレベルを選択します。
RPC_C_IMP_LEVEL_ANONYMOUS サーバーはクライアントを偽装できますが、偽装トークンは何のためにも使用することができません。
RPC_C_IMP_LEVEL_IDENTIFY サーバーは、クライアントの ID を取得し、クライアントを偽装して ACL チェックを行うことができます。
RPC_C_IMP_LEVEL_IMPERSONATE サーバーは、1 つのコンピューター境界を越えてクライアントを偽装できます。
RPC_C_IMP_LEVEL_DELEGATE サーバーは、複数の境界にわたってクライアントを偽装でき、クライアントの代わりに呼び出しを行うことができます。