Win32API セキュリティ属性を指定してファイルを作成する

セキュリティ属性(ACL:アクセス制御リスト)を指定してファイルを作成するには、PSECURITY_ATTRIBUTESオブジェクトを正しく設定して、CreateFile関数の第4引数に渡して呼び出す必要がある。そのためのステップは以下のようになる。

1InitializeSecurityDescriptor関数で、セキュリティ記述子を初期化する
2LookupAccountName関数で、指定したユーザーアカウントに対するSIDを取得する
3InitializeAcl関数でDACL(随意アクセス制御リスト)を初期化する
4AddAccessAllowedAce関数で、ACE(アクセス制御エントリ)をDACLに追加する
5SetSecurityDescriptorDacl関数で、セキュリティ記述子にDACLの情報を設定する
6SECURITY_ATTRIBUTES(セキュリティ属性)オブジェクトの各メンバ(オブジェクトのサイズ、ハンドル継承の有無、セキュリティ記述子)に値をセットする
7CreateFile関数の第4引数に、SECURITY_ATTRIBUTES型オブジェクトへのポインタを渡し、CreateFile関数を呼び出す


  • 例: guestアカウントに読み取り専用を設定したファイルを作成する
  • #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アカウントに対して、読み取り許可が与えられていることがわかる