WIn32API Windowsサービスのセキュリティ情報を取得する QueryServiceObjectSecurity
Windowsサービスは、プロセスやファイルなどと同様にセキュリティ記述子を持っている。そして、このセキュリティ記述子は、QueryServiceObjectSecurity関数で取得することが可能である。
QueryServiceObjectSecurity関数のプロトタイプは、以下のとおり。
BOOL QueryServiceObjectSecurity( SC_HANDLE hService, // サービスのハンドル SECURITY_INFORMATION dwSecurityInformation, // 取得するセキュリティ情報のタイプ PSECURITY_DESCRIPTOR lpSecurityDescriptor, // セキュリティ記述子のアドレス DWORD cbBufSize, // セキュリティ記述子を保持するバッファのサイズ LPDWORD pcbBytesNeeded // 必要なバイト数を受け取る変数のアドレス );
以下のプログラムは、DHCPサービスのセキュリティ情報を取得して表示している。
まず、OpenSCManager関数、OpenService関数でサービスのハンドルを取得し、そのサービスのハンドルを第1引数に指定してQueryServiceObjectSecurity関数を呼び出すことで、サービスのセキュリティ記述子を取得している。
その後は、GetSecurityDescriptorDacl関数でDACL(随意アクセス制御リスト)を取得し、GetAce関数でDACLからACE(アクセス制御エントリ)を取得し、各ACEのアカウント名、ドメイン名、アクセスマスクを取得し表示している。ACEのアカウント名、ドメイン名はLookupAccountSid関数で取得している。
#include <windows.h> #include <stdio.h> #include <locale.h> int main() { SC_HANDLE hSCM = NULL; SC_HANDLE hService = NULL; PSECURITY_DESCRIPTOR pSD = NULL; DWORD dwBytesNeeded; BOOL bDaclPresent; BOOL bDaclDefaulted; PACL pDacl; ACL_SIZE_INFORMATION aclSize; ACCESS_ALLOWED_ACE *pAce; TCHAR szAccountName[256]; TCHAR szDomainName[256]; DWORD dwAccountNameSize; DWORD dwDomainNameSize; SID_NAME_USE snu; DWORD i; LPCTSTR lpszServiceName = TEXT("Dhcp"); setlocale(LC_ALL, setlocale(LC_CTYPE, ""));//コンソールに日本語を表示させるため //サービス制御マネージャーのハンドルを取得 hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); if (hSCM == NULL) { printf("OpenSCManager error: %d\n", GetLastError()); goto EXIT_FUNC; } //サービスのハンドルを取得 hService = OpenService(hSCM, lpszServiceName, READ_CONTROL); if (hService == NULL) { printf("OpenService error: %d\n", GetLastError()); goto EXIT_FUNC; } //サービスのセキュリティ記述子を格納するのに必要なメモリサイズをdwBytesNeededに取得する QueryServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, NULL, 0, &dwBytesNeeded); pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, dwBytesNeeded); if (pSD == NULL) { goto EXIT_FUNC; } //サービスのセキュリティ記述子をpSDに取得する QueryServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, pSD, dwBytesNeeded, &dwBytesNeeded); //サービスのセキュリティ記述子からpDaclにDACL(随意アクセス制御リスト)を取得する GetSecurityDescriptorDacl(pSD, &bDaclPresent, &pDacl, &bDaclDefaulted); if (!bDaclPresent) { puts("No Dacl"); } else { GetAclInformation(pDacl, &aclSize, sizeof(aclSize), AclSizeInformation); for (i = 0; i < aclSize.AceCount; i++) { //DACLからACEを取得する GetAce(pDacl, i, (LPVOID *)&pAce); dwAccountNameSize = sizeof(szAccountName)/sizeof(szAccountName[0]); dwDomainNameSize = sizeof(szDomainName)/sizeof(szDomainName[0]); //SIDからACEのアカウント、ドメイン名を取得する LookupAccountSid(NULL, &pAce->SidStart, szAccountName, &dwAccountNameSize, szDomainName, &dwDomainNameSize, &snu); puts("======================================================================"); _tprintf(TEXT("AccountName: %s\n"), szAccountName); _tprintf(TEXT("DomainName: %s\n"), szDomainName); puts("\n========== AccessMask =========="); if ( (pAce->Mask & SERVICE_QUERY_CONFIG) == SERVICE_QUERY_CONFIG ) puts("SERVICE_QUERY_CONFIG"); if ( (pAce->Mask & SERVICE_CHANGE_CONFIG) == SERVICE_CHANGE_CONFIG ) puts("SERVICE_CHANGE_CONFIG"); if ( (pAce->Mask & SERVICE_QUERY_STATUS) == SERVICE_QUERY_STATUS ) puts("SERVICE_QUERY_STATUS"); if ( (pAce->Mask & SERVICE_START) == SERVICE_START ) puts("SERVICE_START"); if ( (pAce->Mask & SERVICE_STOP) == SERVICE_STOP ) puts("SERVICE_STOP"); if ( (pAce->Mask & SERVICE_PAUSE_CONTINUE) == SERVICE_PAUSE_CONTINUE ) puts("SERVICE_PAUSE_CONTINUE"); if ( (pAce->Mask & SERVICE_INTERROGATE) == SERVICE_INTERROGATE ) puts("SERVICE_INTERROGATE"); if ( (pAce->Mask & SERVICE_USER_DEFINED_CONTROL) == SERVICE_USER_DEFINED_CONTROL ) puts("SERVICE_USER_DEFINED_CONTROL"); puts("\n"); } } EXIT_FUNC: LocalFree(pSD); CloseServiceHandle(hSCM); CloseServiceHandle(hService); return 0; }
====================================================================== AccountName: Authenticated Users DomainName: NT AUTHORITY ========== AccessMask ========== SERVICE_QUERY_CONFIG SERVICE_QUERY_STATUS SERVICE_INTERROGATE SERVICE_USER_DEFINED_CONTROL ====================================================================== AccountName: Authenticated Users DomainName: NT AUTHORITY ========== AccessMask ========== SERVICE_QUERY_CONFIG SERVICE_QUERY_STATUS SERVICE_START SERVICE_STOP SERVICE_PAUSE_CONTINUE SERVICE_INTERROGATE SERVICE_USER_DEFINED_CONTROL ====================================================================== AccountName: Administrators DomainName: BUILTIN ========== AccessMask ========== SERVICE_QUERY_CONFIG SERVICE_CHANGE_CONFIG SERVICE_QUERY_STATUS SERVICE_START SERVICE_STOP SERVICE_PAUSE_CONTINUE SERVICE_INTERROGATE SERVICE_USER_DEFINED_CONTROL ====================================================================== AccountName: コンソール ログオン DomainName: ========== AccessMask ========== SERVICE_QUERY_CONFIG SERVICE_QUERY_STATUS SERVICE_START SERVICE_INTERROGATE SERVICE_USER_DEFINED_CONTROL ====================================================================== AccountName: SYSTEM DomainName: NT AUTHORITY ========== AccessMask ========== SERVICE_QUERY_CONFIG SERVICE_QUERY_STATUS SERVICE_START SERVICE_STOP SERVICE_PAUSE_CONTINUE SERVICE_INTERROGATE SERVICE_USER_DEFINED_CONTROL
http://msdn.microsoft.com/ja-jp/library/cc447525.aspx