C++를 사용하여 인증 설정
WMI용 IWbemLocator::ConnectServer의 주요 작업 중 하나는 IWbemServices 프록시에 대한 포인터를 반환하는 것입니다. IWbemServices 프록시를 통해 WMI 인프라의 기능에 액세스할 수 있습니다. 그러나 IWbemServices 프록시에 대한 포인터에는 IWbemServices 프로세스의 ID가 아니라 클라이언트 애플리케이션 프로세스의 ID가 있습니다. 따라서 포인터를 사용하여 IWbemServices에 액세스하려고 하면 E_ACCESSDENIED 같은 액세스 거부 코드를 받을 수 있습니다. 액세스 거부 오류를 방지하려면 CoSetProxyBlanket 인터페이스를 호출하여 새 포인터의 ID를 설정해야 합니다.
공급자는 네임스페이스에 대한 연결에서 패킷 개인 정보(PktPrivacy)를 사용하지 않는 한 데이터가 반환되지 않도록 네임스페이스에 대한 보안을 설정할 수 있습니다. 이렇게 하면 네트워크를 지날 때 데이터가 암호화됩니다. 더 낮은 인증 수준을 설정하려고 하면 액세스 거부 메시지가 표시됩니다. 자세한 내용은 네임스페이스 보안 설명자 설정을 참조하세요.
스크립팅에서 인증을 설정하는 방법에 관한 자세한 내용은 VBScript를 사용하여 기본 프로세스 보안 수준 설정을 참조하세요.
원격 IUnknown 인터페이스에서 보안 설정
경우에 따라서는 프록시에 대한 포인터보다 서버에 더 많이 액세스해야 합니다. 때때로 프록시의 IUnknown 인터페이스에 대한 보안 연결을 얻어야 할 수 있습니다. IUnknown을 사용하여 원격 시스템에서 인터페이스 및 그 외 필요한 기술을 쿼리할 수 있습니다.
프록시가 원격 컴퓨터에 있는 경우, 서버는 프록시의 IUnknown 인터페이스에 대한 모든 호출을 IUnknown 인터페이스에 위임합니다. 예를 들어 프록시에서 QueryInterface를 호출하고 요청된 인터페이스가 프록시의 일부가 아닌 경우 프록시는 원격 서버에 호출을 보냅니다. 따라서 원격 서버는 적절한 인터페이스 지원을 확인합니다. 서버에서 인터페이스를 지원하는 경우, COM은 애플리케이션이 새 인터페이스를 사용할 수 있도록 새 프록시를 클라이언트로 다시 마샬링합니다.
원격 서버에 대한 액세스 권한이 없는 클라이언트가 이 서버에 대해 액세스 권한이 있는 사용자의 자격 증명을 사용하는 경우 문제가 발생합니다. 이 경우 원격 서버에서 QueryInterface에 액세스하려는 시도가 실패합니다. 현재 사용자가 원격 서버에 액세스할 수 없기 때문에 프록시의 최종 릴리스도 실패합니다. 이 현상은 클라이언트 애플리케이션이 최종 프록시 릴리스에 실패하기 전 1~2초간 지연으로 나타납니다. COM이 현재 사용자의 기본 보안 설정을 사용하여 원격 서버에 액세스하려고 시도했기 때문에 오류가 발생합니다. 여기에는 처음에 서버에 대한 액세스를 허용한 수정된 자격 증명이 포함되어 있지 않습니다. 자세한 내용은 IWbemServices 및 기타 프록시에서 보안 설정을 참조하세요.
연결 실패를 방지하려면 CoSetProxyBlanket을 사용하여 IUnknown에서 반환된 포인터에서 보안 인증을 명시적으로 설정합니다. CoSetProxyBlanket을 사용하여 원격 서버가 올바른 인증 ID를 수신하는지 확인할 수 있습니다.
다음 코드 예제에서는 CoSetProxyBlanket을 사용하여 원격 IUnknown 인터페이스에 액세스하는 방법을 보여줍니다.
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;
참고
프록시의 IUnknown 인터페이스에서 보안을 설정하면 COM은 CoUninitialize를 호출할 때까지 릴리스할 수 없는 프록시의 복사본을 만듭니다.
관련 항목