Win32API セキュリティ属性を指定してファイルを作成する
セキュリティ属性(ACL:アクセス制御リスト)を指定してファイルを作成するには、PSECURITY_ATTRIBUTESオブジェクトを正しく設定して、CreateFile関数の第4引数に渡して呼び出す必要がある。そのためのステップは以下のようになる。
1 | InitializeSecurityDescriptor関数で、セキュリティ記述子を初期化する |
2 | LookupAccountName関数で、指定したユーザーアカウントに対するSIDを取得する |
3 | InitializeAcl関数でDACL(随意アクセス制御リスト)を初期化する |
4 | AddAccessAllowedAce関数で、ACE(アクセス制御エントリ)をDACLに追加する |
5 | SetSecurityDescriptorDacl関数で、セキュリティ記述子にDACLの情報を設定する |
6 | SECURITY_ATTRIBUTES(セキュリティ属性)オブジェクトの各メンバ(オブジェクトのサイズ、ハンドル継承の有無、セキュリティ記述子)に値をセットする |
7 | CreateFile関数の第4引数に、SECURITY_ATTRIBUTES型オブジェクトへのポインタを渡し、CreateFile関数を呼び出す |
#include <windows.h> #include <stdio.h> BOOL GetSidByAccountName(const char *lpAccountName, PSID *ppSid, char *lpszDomainName, DWORD dwDomainName) { DWORD dwSidSize = 0; SID_NAME_USE snu; BOOL bRet; //SIDを格納するために、dwSidSizeに必要なバッファサイズを取得する bRet = LookupAccountNameA(0, lpAccountName, NULL, &dwSidSize, lpszDomainName, &dwDomainName, &snu); if (!bRet && GetLastError() != ERROR_INSUFFICIENT_BUFFER) { return FALSE; } *ppSid = (PSID)HeapAlloc(GetProcessHeap(), 0, dwSidSize); if (*ppSid == NULL) { return FALSE; } bRet = LookupAccountNameA(0, lpAccountName, *ppSid, &dwSidSize, lpszDomainName, &dwDomainName, &snu); return bRet; } int main() { SECURITY_ATTRIBUTES sa; SECURITY_DESCRIPTOR sd; PACL pDacl; PSID pSid; char szDomainName[256] = {'\0'}; DWORD dwDomainNameSize = sizeof(szDomainName)/sizeof(szDomainName[0]); HANDLE hFile; DWORD dwAclSize = 1024; //1.セキュリティ記述子を初期化する InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); //2.LookupAccountName関数で、指定したユーザーアカウントに対するSIDを取得する GetSidByAccountName("guest", &pSid, szDomainName, dwDomainNameSize); pDacl = (PACL)HeapAlloc(GetProcessHeap(), 0, dwAclSize); if (pDacl == NULL) { return 1; } //3.DACL(随意アクセス制御リスト)を初期化する InitializeAcl(pDacl, dwAclSize, ACL_REVISION); //4.ACE(アクセス制御エントリ)をDACLに追加する AddAccessAllowedAce(pDacl, ACL_REVISION, GENERIC_READ, pSid); //5.セキュリティ記述子にDACLの情報を設定する SetSecurityDescriptorDacl(&sd, TRUE, pDacl, FALSE); //6.SECURITY_ATTRIBUTES(セキュリティ属性)オブジェクトの各メンバ(オブジェクトのサイズ、 //ハンドル継承の有無、セキュリティ記述子)に値をセットする sa.nLength = sizeof(sa); sa.bInheritHandle = FALSE; sa.lpSecurityDescriptor = &sd; //7.reateFile関数の第4引数に、SECURITY_ATTRIBUTES型オブジェクトへのポインタを渡し、 //CreateFile関数を呼び出す hFile = CreateFile(TEXT("test"), GENERIC_READ|GENERIC_WRITE, 0, &sa, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); } HeapFree(GetProcessHeap(), 0, pSid); HeapFree(GetProcessHeap(), 0, pDacl); return 0; }
guestアカウントに対して、読み取り許可が与えられていることがわかる