none
ファイルのアクセス権について追加設定したプリンシパルのアクセス権が反映されない場合があるか? RRS feed

  • 質問

  • ファイルのアクセス権を変更する処理を開発していますが、以下のように作成したファイル(B.)のアクセス権で、Authenticated Usersに所属するログインユーザーでのファイルへの追加書込みでエラーが発生しました。

    このため、一旦B.ファイルのアクセス権を削除して上位フォルダのアクセス権を継承しなおした(D.ファイル)ところ、正常に追加書込みできるようになりました。

    そこで、質問ですが、

    (1) 「継承元なし」になっているプリンシパル(この場合Authenticated User)について、実際のアクセス権が得られない条件等はありますか?

    (2) 上位フォルダから正しく継承させるためのアクセス権設定順序はありますか?(先に上位フォルダを設定してからファイルを設定するなど)

    (3) 上記、(2)で順序に決まりがある場合、順序通り設定しなかった場合、ファイルアクセス時に何か問題がおきますか?

    (4) また、B.ファイルの状態で、追加書込みには失敗しましたが、ファイルの削除や新規作成は可能でした。なぜ書込みのみ失敗するのでしょうか?

    以上、4点について、わかる方はいらっしゃいますでしょうか?

    ファイルのアクセス権設定は、WindowsAPIAddAccessAllowedAceExSetSecurityDescriptorDaclSetSecurityDescriptorControl関数を使って設定しました。

    作成順序

    ・まず、A.のアクセス権が設定されている上位フォルダにファイルを作成し、B.のアクセス権を設定しました。

    ・その後、上位フォルダをC.のように設定しました。

    ・この時点でB.ファイルの書き込みでエラーが起きたので、D.のようにファイルのアクセス権を設定しなおしたところ、正常になりました。

    A.上位フォルダ(初期のアクセス権)

     プリンシパル        | アクセス         | 継承元 | 適用先

     Everyone            | フルコントロール | なし   | このフォルダー、サブフォルダーおよびファイル

     Administrators      | フルコントロール | あり   | このフォルダー、サブフォルダーおよびファイル

     SYSTEM              | フルコントロール | あり   | このフォルダー、サブフォルダーおよびファイル

     Users               | 読み取りと実行   | あり   | このフォルダー、サブフォルダーおよびファイル

     Users               | 書き込み         | あり   | このフォルダーとサブフォルダー

    B.不具合が起きたファイル(上位フォルダ内に作成されています)

     プリンシパル        | アクセス         | 継承元

     Authenticated Users | フルコントロール | なし

     Administrators      | フルコントロール | 上位フォルダ

     SYSTEM              | フルコントロール | 上位フォルダ

     Users               | 読み取りと実行   | 上位フォルダ

    C.上位フォルダ(更新後のアクセス権)

     プリンシパル        | アクセス         | 継承元 | 適用先

     Authenticated Users | フルコントロール | なし   | このフォルダー、サブフォルダーおよびファイル

     Administrators      | フルコントロール | あり   | このフォルダー、サブフォルダーおよびファイル

     SYSTEM              | フルコントロール | あり   | このフォルダー、サブフォルダーおよびファイル

     Users               | 読み取りと実行   | あり   | このフォルダー、サブフォルダーおよびファイル

     Users               | 書き込み         | あり   | このフォルダーとサブフォルダー

    D.上位フォルダのアクセス権設定後にアクセス権を再設定したファイル(上位フォルダ内に作成されています)

     プリンシパル        | アクセス         | 継承元

     Authenticated Users | フルコントロール | 上位フォルダ

     Administrators      | フルコントロール | 上位フォルダ

     SYSTEM              | フルコントロール | 上位フォルダ

     Users               | 読み取りと実行   | 上位フォルダ

    2020年5月1日 6:38

すべての返信

  • itom0717さん、こんにちは。フォーラムオペレーターのクモです。
    MSDNフォーラムにご投稿くださいましてありがとうございます。

    この問題の再現を試みた最小限のサンプルと手順をご提供いただけませんか?

    どうぞよろしくお願いいたします。

    MSDN/ TechNet Community Support Kumo ~参考になった投稿には「回答としてマーク」をご設定ください。なかった場合は「回答としてマークされていない」も設定できます。同じ問題で後から参照した方が、情報を見つけやすくなりますので、 ご協力くださいますようお願いいたします。また、MSDNサポートに賛辞や苦情がある場合は、MSDNFSF@microsoft.comまでお気軽にお問い合わせください。~

    2020年5月7日 5:26
    モデレータ
  • 返信ありがとうございます。
    最小限のサンプルと手順ですが、準備するのに時間が掛かりそうです。
    準備できましたら、改めて投稿します。

    2020年5月7日 8:48
  • サンプル手順を投稿します。

    何かわかればよろしくお願いいたします。

    --------------------------

    以下のサンプル関数のようにAFileNameにアクセス権を更新するファイル名、APareintDirに該当ファイルの上位フォルダを指定して実行し、

    Authenticated Usersのアクセス権をフルコントールで追加し、その後上位フォルダのアクセス権を継承するようになっています。

    関数自体はエラーもなく最後まで処理されてSetFileSecurity関数でアクセス権の更新が成功しております。

    実行手順は、上位フォルダを「A.上位フォルダ(初期のアクセス権)」の状態にして本関数を呼び出すか、

    C.上位フォルダ(更新後のアクセス権)」の状態にして本関数を呼び出すか(関数自体の呼び出し方は同じ)です。

    BOOL SetFileAccessACL(LPCWSTR AFileName, LPCWSTR APareintDir) {

     BOOL bResult = false;

     DWORD cbFileSD;

     if (!GetFileSecurity(AFileName, DACL_SECURITY_INFORMATION, NULL, 0, &cbFileSD)) {

      if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return bResult;

     };

     PSECURITY_DESCRIPTOR lpFileSD;

     DWORD cbFileSize = cbFileSD;

     if (cbFileSize > 0) {

      lpFileSD = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbFileSize);

     } else {

      return bResult;

     };

     if (!GetFileSecurity(AFileName, DACL_SECURITY_INFORMATION, lpFileSD, cbFileSize, &cbFileSD)) {

      if (lpFileSD != NULL) HeapFree(GetProcessHeap(), 0, lpFileSD);

      return bResult;

     };

     __try {

      if (!GetFileSecurity(APareintDir, DACL_SECURITY_INFORMATION, NULL, 0, &cbFileSD)) {

       if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return bResult;

      };

      PSECURITY_DESCRIPTOR lpParentSD;

      cbFileSize = cbFileSD;

      if (cbFileSize > 0) {

       lpParentSD = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbFileSize);

      } else {

       throw;

      };

      if (!GetFileSecurity(APareintDir, DACL_SECURITY_INFORMATION, lpParentSD, cbFileSize, &cbFileSD)) {

       if (lpParentSD != NULL) HeapFree(GetProcessHeap(), 0, lpParentSD);

       throw;

      };

      __try {

       BOOL fDaclPresent;

       PACL lpParentACL;

       BOOL fDaclDefaulted;

       if (!GetSecurityDescriptorDacl(lpParentSD, &fDaclPresent, &lpParentACL, &fDaclDefaulted)) throw;

       if (lpParentACL == NULL) fDaclPresent = false;

       if (!fDaclPresent) throw;

       ACL_SIZE_INFORMATION rcParentAclInfo;

       rcParentAclInfo.AceCount = 0;

       rcParentAclInfo.AclBytesFree = 0;

       rcParentAclInfo.AclBytesInUse = sizeof(ACL);

       if (!GetAclInformation(lpParentACL, &rcParentAclInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) throw;

       PSID lpAddSID;

       if (!ConvertStringSidToSidW(SSID_AUTHENTICATEDUSERS, &lpAddSID)) throw;

       DWORD cbAddSIDSize = GetLengthSid(lpAddSID);

       PSECURITY_DESCRIPTOR lpNewSD = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SECURITY_DESCRIPTOR));

       if (lpNewSD == NULL) throw;

       __try {

        if (!InitializeSecurityDescriptor(lpNewSD, SECURITY_DESCRIPTOR_REVISION)) throw;

        DWORD cbNewACL = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + rcParentAclInfo.AclBytesInUse + cbAddSIDSize;

        PACL lpNewACL = (PACL)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbNewACL);

        if (lpNewACL == NULL) throw;

        __try {

         if (!InitializeAcl(lpNewACL, cbNewACL, ACL_REVISION2)) throw;

         PACCESS_ALLOWED_ACE lpParentAce = NULL;

         BYTE nTmpFlags;

         BYTE nAceFlags = ACEFLAGS_FILEONLY;

         for (DWORD ni = 0; rcParentAclInfo.AceCount > ni; ni++) {

          if (!GetAce(lpParentACL, ni, (LPVOID*)&lpParentAce)) continue;

          if (lpParentAce->Header.AceType != ACCESS_ALLOWED_ACE_TYPE) continue;

          nTmpFlags = lpParentAce->Header.AceFlags;

          if (!ToInheritedAceFlags(&nTmpFlags)) continue;

          if (!EqualSid(&lpParentAce->SidStart, lpAddSID)) continue;

          nAceFlags = INHERITED_ACE;

          break;

         };

         if (!AddAccessAllowedAceEx(lpNewACL, ACL_REVISION2, nAceFlags, FILE_MASK_FULLCONTROL, lpAddSID)) throw;

         int nErrCount = 0;

         for (DWORD ni = 0; rcParentAclInfo.AceCount > ni; ni++) {

          if (!GetAce(lpParentACL, ni, (LPVOID*)&lpParentAce)) continue;

          if (lpParentAce->Header.AceType != ACCESS_ALLOWED_ACE_TYPE) continue;

          if (!ToInheritedAceFlags(&lpParentAce->Header.AceFlags)) continue;

          if (EqualSid(&lpParentAce->SidStart, lpAddSID)) continue;

          if (!AddAccessAllowedAceEx(lpNewACL, ACL_REVISION2, lpParentAce->Header.AceFlags, lpParentAce->Mask, &lpParentAce->SidStart)) nErrCount++;

         };

         if (nErrCount > 0) throw;

         if (!SetSecurityDescriptorDacl(lpNewSD, true, lpNewACL, false)) throw;

         bResult = SetFileSecurity(AFileName, DACL_SECURITY_INFORMATION, lpNewSD);

        } __finally {

         if (lpNewACL != NULL) HeapFree(GetProcessHeap(), 0, lpNewACL);

        };

       } __finally {

        if (lpNewSD != NULL) HeapFree(GetProcessHeap(), 0, lpNewSD);

       };

      } __finally {

       if (lpParentSD != NULL) HeapFree(GetProcessHeap(), 0, lpParentSD);

      };

     } __finally {

      if (lpFileSD != NULL) HeapFree(GetProcessHeap(), 0, lpFileSD);

     };

     return bResult;

    };



    • 編集済み itom0717 2020年5月25日 9:21
    2020年5月25日 9:20
  • itom0717さん、こんにちは。フォーラムオペレーターのクモです。
    ご返信いただきありがとうございます。

    私側でこの問題を再現することができません。
    コードはコンパイルできません。
    「SSID_AUTHENTICATEDUSERS」(代わりにSDDL_AUTHENTICATED_USERSを使用)、「ACEFLAGS_FILEONLY」(代わりにゼロを使用)、「ToInheritedAceFlags()」(コメントを追加)など、定義されていないものがあります。

    「Path \ C」というフォルダを作成し、「Path \ C \ A.txt」と「Path \ C \ B.txt」の2つのファイルを作成しました。
    次のような関数を呼び出す:SetFileAccessACL(L "Path \\ C \\ B.txt"、L "Path \\ C");
    認証ユーザー-フルコントロール-なしがファイルセキュリティに追加されました。
    しかし、エラーなくB.txtファイルに書き込むことができます。

    どうぞよろしくお願いいたします。

    MSDN/ TechNet Community Support Kumo ~参考になった投稿には「回答としてマーク」をご設定ください。なかった場合は「回答としてマークされていない」も設定できます。同じ問題で後から参照した方が、情報を見つけやすくなりますので、 ご協力くださいますようお願いいたします。また、MSDNサポートに賛辞や苦情がある場合は、MSDNFSF@microsoft.comまでお気軽にお問い合わせください。~

    2020年5月26日 6:29
    モデレータ
  • 確認ありがとうございます。

    再度確認してみます。

    2020年5月28日 1:19