다음을 통해 공유


액세스 검사 수행

액세스 검사를 통해 보안 설명자가 액세스 토큰으로 식별된 클라이언트 또는 스레드에 지정된 액세스 권한 집합을 부여할지 여부를 결정합니다. C++ 또는 C#으로 작성된 WMI 클라이언트 애플리케이션 또는 공급자에서 보안 함수 AccessCheck를 호출할 수 있습니다. 스크립트 및 Visual Basic 애플리케이션은 여기서 설명하는 메서드를 사용하여 액세스 검사를 수행할 수 없습니다.

클라이언트 애플리케이션은 클라이언트 비동기 호출에서 제공하는 싱크로 결과를 반환할 때 콜백의 ID를 확인하기 위해 액세스 검사를 수행해야 합니다.

공급자가 데이터를 요청하는 클라이언트 애플리케이션 또는 스크립트를 가장할 수 없는 경우 다음과 같은 상황에 대한 액세스 검사를 수행해야 합니다.

  • ACL(액세스 제어 목록)으로 보호되지 않는 리소스에 액세스하는 경우
  • 클라이언트가 RPC_C_LEVEL_IDENTIFY 가장 수준에서 연결된 경우

참고

C++ 및 C# 애플리케이션은 별도의 프로세스에서 액세스 검사를 수행하는지 여부를 제어할 수 있습니다. 스크립트 및 Visual Basic 애플리케이션은 레지스트리 키를 읽거나 변경하여 WMI가 액세스 검사를 수행하도록 할 수 있습니다. 자세한 내용은 비동기 호출에서 보안 설정을 참조하세요.

 

이 항목의 코드 예제를 올바르게 컴파일하려면 다음 참조 및 #include 문이 필요합니다.

#include <lmcons.h>
#define _WIN32_DCOM
#define SECURITY_WIN32
#include <wbemidl.h>
#include <security.h>
#include <safestr.h>
#pragma comment(lib, "wbemuuid.lib")
#pragma comment(lib, "Secur32.lib")

다음 코드 예제는 클라이언트 애플리케이션 스레드의 보안 토큰에 지정된 보안 설명자에 적합한 권한이 포함되어 있는지 확인하는 방법을 보여줍니다. 함수는 문자열 "domain\user"를 사용하고 SID를 반환합니다. 호출에 실패하면 함수는 NULL을 반환하는데, 아닌 경우에는 호출자가 반환된 포인터를 해제해야 합니다.

BYTE * GetSid(LPWSTR pwcUserName)
{
    DWORD dwSidSize = 0, dwDomainSize = 0;
    SID_NAME_USE use;

    // first call is to get the size
    BOOL bRet = LookupAccountNameW(

      NULL,            // system name
      pwcUserName,     // account name
      NULL,            // security identifier
      &dwSidSize,      // size of security identifier
      NULL,            // domain name
      &dwDomainSize,   // size of domain name
      &use             // SID-type indicator
      );    

    if(bRet == FALSE && ERROR_INSUFFICIENT_BUFFER 
        != GetLastError())\
        return NULL;

    BYTE * buff = new BYTE[dwSidSize];

    if(buff == NULL)
        return NULL;

    WCHAR * pwcDomain = new WCHAR[dwDomainSize];

    if(pwcDomain == NULL)

    {
        delete [] buff;
        return FALSE;
    }

    // Call to LookupAccountNameW actually gets the SID
    bRet = LookupAccountNameW(

      NULL,           // system name
      pwcUserName,    // account name
      buff,           // security identifier
      &dwSidSize,     // size of security identifier
      pwcDomain,      // domain name
      &dwDomainSize,  // size of domain name
      &use            // SID-type indicator
      );    

    delete [] pwcDomain;

    if(bRet == FALSE)
    {
        delete [] buff;
        return NULL;
    }

    return buff;
}

// This returns true if the caller is coming 
//   from the expected computer in the expected domain.

BOOL IsAllowed(LPWSTR pwsExpectedDomain, 
   LPWSTR pwsExpectedMachine)
{

    WCHAR wCallerName[UNLEN + 1];
    DWORD nSize = UNLEN + 1;

// Impersonate the caller and get its name

    HRESULT hr = CoImpersonateClient();
    if(FAILED(hr))

        return FALSE;

    BOOL bRet = GetUserNameExW(NameSamCompatible, 
       wCallerName, &nSize);

    CoRevertToSelf();

    if(bRet == FALSE)

        return FALSE;


    // take the expected domain and lan manager 
    //   style name and create a SID.  In actual
    // production code, it would be more efficient 
    //   to do this only when necessary

    WCHAR wExpectedName[UNLEN + 1];

    HRESULT hrCopyCat;
    hrCopyCat = StringCchCopy(wExpectedName,
        sizeof(pwsExpectedDomain)*sizeof(WCHAR)+1, 
        pwsExpectedDomain);
    if (FAILED(hrCopyCat))
    {
        return FALSE;
    }
    hrCopyCat = 
        StringCchCat(wExpectedName,sizeof(wExpectedName)
        + 2*sizeof(WCHAR)+1, L"\\");
    if (FAILED(hrCopyCat))
    {
        return FALSE;
    }
    hrCopyCat = StringCchCat(wExpectedName,sizeof(wExpectedName)
        + sizeof(pwsExpectedMachine)*sizeof(WCHAR)+1, 
        pwsExpectedMachine);
    if (FAILED(hrCopyCat))
    {
        return FALSE;
    }
    hrCopyCat = StringCchCat(wExpectedName,sizeof(wExpectedName)
        + sizeof(WCHAR)+1, L"$");
    if (FAILED(hrCopyCat))
    {
        return FALSE;
    }
  

    // convert the two names to SIDs and compare.  
    // Note that SIDs are used since 
    //   the format of the names might vary.  

    BYTE * pCaller = GetSid(wCallerName);

    if(pCaller == NULL)

        return FALSE;

    BYTE * pExpected = GetSid(wExpectedName);

    if(pExpected == NULL)
    {
        delete [] pCaller;

        return FALSE;
    }

    bRet = EqualSid((PSID)pCaller, (PSID)pExpected);

    delete [] pCaller;
    delete [] pExpected;

    return bRet;
}

올바른 등록 선택

WMI 보안 유지 관리

공급자 보안

WMI 네임스페이스에 대한 액세스