다음을 통해 공유


액세스 검사 수행

액세스 검사는 보안 설명자가 액세스 토큰으로 식별된 클라이언트 또는 스레드에 대해 지정된 액세스 권한 집합을 부여하는지 여부를 결정합니다. 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 네임스페이스에 대한 액세스