使用 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;
}

此代码需要以下引用,并 # 包含对语句的正确编译。

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

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

将身份验证级别设置为 RPC _ C _ 身份验证 _ level _ 默认值 后,DCOM 可以协商身份验证级别以匹配目标计算机的安全要求。 有关详细信息,请参阅 使用 c + + 更改默认身份验证凭据使用 c + + 更改默认模拟设置

使用 c + + 更改默认身份验证凭据

默认身份验证凭据适用于大多数情况,但你可能需要在不同的情况下使用不同的身份验证凭据。 例如,你可能希望向身份验证过程中添加加密。

下表列出并描述了不同级别的身份验证。

身份验证级别 描述
RPC _ C _ 身份验证 _ 级别 _ 默认值 默认安全身份验证。
RPC _ C _ 身份验证 _ LEVEL _ NONE 无身份验证。
RPC _ C _ 身份验证 _ 级别 _ 连接 仅当客户端与服务器建立关系时进行身份验证。
RPC _ C _ 身份验证 _ 级别 _ 调用 每次服务器接收 RPC 时进行身份验证。
RPC _ C _ 身份验证 _ 级别 _ PKT 每次服务器从客户端接收数据时进行身份验证。
RPC _ C _ 身份验证 _ 级别 _ PKT _ 完整性 身份验证未修改来自包的数据。
RPC _ C _ 身份验证 _ 级别 _ PKT _ 隐私 包括以前的所有身份验证级别,并对每个 RPC 调用的值进行加密。

可以通过在 CoInitializeSecuritypAuthList 参数中使用 唯一 _ 身份验证 _ 列表 结构,为多个用户指定默认的身份验证凭据。

下面的代码示例演示如何更改身份验证凭据。

// 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 _ 标识,但 WMI 至少需要 RPC _ c _ IMP _ 级别 _ 模拟 ,才能与大多数提供程序一起工作,并且你可能会遇到需要设置更高级别的模拟的情况。 有关详细信息,请参阅 连接到远程计算机上的 WMI。 下表列出了不同的模拟级别。

Level 描述
RPC _ C _ IMP _ 级别 _ 默认值 操作系统选择模拟级别。
RPC _ C _ IMP _ 级别 _ ANONYMOUS 服务器可以模拟客户端,但模拟令牌不能用于任何其他操作。
RPC _ C _ IMP _ LEVEL _ 标识 服务器可以获取客户端的标识并模拟客户端进行 ACL 检查。
RPC _ C _ IMP _ 级别 _ 模拟 服务器可以在一台计算机边界上模拟客户端。
RPC _ C _ IMP _ 级别 _ 委托 服务器可以跨多个边界模拟客户端,并可以代表客户端进行调用。