2015-10-21 17 views
5

共有ディレクトリのアクセス許可をチェックするコードを作成したいが、複数の解決策をチェックするが、ローカルディレクトリのアクセス権を取得しようとするとうまくいくが、失敗する。 SOF: checking-for-directory-and-file-write-permissions-in-net共有ディレクトリのアクセス許可を確認する - C#

をそれだけでローカルディレクトリで動作します:

私はこの質問の例をしようとしています。

例えば、私はこのクラスを使用:

public class CurrentUserSecurity 
{ 
    WindowsIdentity _currentUser; 
    WindowsPrincipal _currentPrincipal; 

    public CurrentUserSecurity() 
    { 
     _currentUser = WindowsIdentity.GetCurrent(); 
     _currentPrincipal = new WindowsPrincipal(WindowsIdentity.GetCurrent()); 
    } 

    public bool HasAccess(DirectoryInfo directory, FileSystemRights right) 
    { 
     // Get the collection of authorization rules that apply to the directory. 
     AuthorizationRuleCollection acl = directory.GetAccessControl() 
      .GetAccessRules(true, true, typeof(SecurityIdentifier)); 
     return HasFileOrDirectoryAccess(right, acl); 
    } 

    public bool HasAccess(FileInfo file, FileSystemRights right) 
    { 
     // Get the collection of authorization rules that apply to the file. 
     AuthorizationRuleCollection acl = file.GetAccessControl() 
      .GetAccessRules(true, true, typeof(SecurityIdentifier)); 
     return HasFileOrDirectoryAccess(right, acl); 
    } 

    private bool HasFileOrDirectoryAccess(FileSystemRights right, 
              AuthorizationRuleCollection acl) 
    { 
     bool allow = false; 
     bool inheritedAllow = false; 
     bool inheritedDeny = false; 

     for (int i = 0; i < acl.Count; i++) 
     { 
      FileSystemAccessRule currentRule = (FileSystemAccessRule)acl[i]; 
      // If the current rule applies to the current user. 
      if (_currentUser.User.Equals(currentRule.IdentityReference) || 
       _currentPrincipal.IsInRole(
           (SecurityIdentifier)currentRule.IdentityReference)) 
      { 

       if (currentRule.AccessControlType.Equals(AccessControlType.Deny)) 
       { 
        if ((currentRule.FileSystemRights & right) == right) 
        { 
         if (currentRule.IsInherited) 
         { 
          inheritedDeny = true; 
         } 
         else 
         { // Non inherited "deny" takes overall precedence. 
          return false; 
         } 
        } 
       } 
       else if (currentRule.AccessControlType 
               .Equals(AccessControlType.Allow)) 
       { 
        if ((currentRule.FileSystemRights & right) == right) 
        { 
         if (currentRule.IsInherited) 
         { 
          inheritedAllow = true; 
         } 
         else 
         { 
          allow = true; 
         } 
        } 
       } 
      } 
     } 

     if (allow) 
     { // Non inherited "allow" takes precedence over inherited rules. 
      return true; 
     } 
     return inheritedAllow && !inheritedDeny; 
    } 
} 

それは、ディレクトリやファイルの現在の偽装の許可を確認してください。 ローカルディレクトリをチェックするとすべてのテストケースが正しく渡されますが、そのうちのいくつかは共有ディレクトリで失敗します。これは解決したい問題です。そのための解決策はありますか?

ディレクトリに書き込み権限を持っていなかったが、以下のテストケースは失敗します。

 [TestMethod] 
    public void HasAccess_NotHaveAccess_ReturnsFalse() 
    { 
     CurrentUserSecurity cus = new CurrentUserSecurity(); 
     bool result = cus.HasAccess(new DirectoryInfo(@"\\sharedpc\readonly"), System.Security.AccessControl.FileSystemRights.Write); 
     Assert.AreEqual(result, false); 
    } 
+1

こんにちはdeserthero、私はあなたのコードを試して、すべてここでうまく動作します。あなたは "\\ sharedpc \ readonly"フォルダ内の現在のユーザの権限を適切に設定してもよろしいですか? –

+1

こんにちは、私は以下の答えを入れましたが、これは環境の問題か、ちょっとした混乱だと思います。私はあなたのTestMethodがTrueを返すことを理解しています*ユーザーが*権限を持っていますが、それは*間違っています*? 1.あなたの質問を編集し、フォルダのアクセス許可のスクリーンショットを提供できます。2.コード 'WindowsIdentity.GetCurrent'を実行しているユーザーアカウント名を指定します。 3.自分の横の別のWindowIdentityでテストしたことを確認してください。これは最も簡単な方法です。http://stackoverflow.com/questions/125341/how-do-you-do-impersonation-in-net/7250145#7250145 。 –

+1

これを試しましたか?https://msdn.microsoft.com/en-us/library/system.security.accesscontrol.filesystemsecurity.accessrulefactory(v=vs.110).aspx? Getメソッドはおそらくネストされたルールやグループに適用されたルールなどの従属ルールを解決しないでしょう。このメソッドは実際のアクセスルールを検証するかもしれません。 –

答えて

3

あなたのコードWOMM。標準の.NET クラスがWin32 APIを直接使用して(自分の環境で)BCLが潜んでいる潜在的な問題を発見できない理由を理解することをお勧めします。

この下位レベルの方法を試しても指が交差すると、エラーが発生し、BCLクラスで問題が何かを知ることができます。回避策としてを使用してください。

using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Runtime.InteropServices; 

class MainConsole 
{ 
    [DllImport("Netapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
    static extern int NetShareGetInfo(
     [MarshalAs(UnmanagedType.LPWStr)] string serverName, 
     [MarshalAs(UnmanagedType.LPWStr)] string netName, 
     Int32 level, 
     out IntPtr bufPtr); 

    [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    static extern bool GetSecurityDescriptorDacl(
     IntPtr pSecurityDescriptor, 
     [MarshalAs(UnmanagedType.Bool)] out bool bDaclPresent, 
     ref IntPtr pDacl, 
     [MarshalAs(UnmanagedType.Bool)] out bool bDaclDefaulted 
     ); 

    [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    static extern bool GetAclInformation(
     IntPtr pAcl, 
     ref ACL_SIZE_INFORMATION pAclInformation, 
     uint nAclInformationLength, 
     ACL_INFORMATION_CLASS dwAclInformationClass 
    ); 

    [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
    static extern int GetAce(
     IntPtr aclPtr, 
     int aceIndex, 
     out IntPtr acePtr 
    ); 

    [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
    static extern int GetLengthSid(
     IntPtr pSID 
    ); 

    [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    static extern bool ConvertSidToStringSid(
     [MarshalAs(UnmanagedType.LPArray)] byte[] pSID, 
     out IntPtr ptrSid 
    ); 

    [DllImport("netapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
    static extern int NetApiBufferFree(
     IntPtr buffer 
    ); 

    enum SID_NAME_USE 
    { 
     SidTypeUser = 1, 
     SidTypeGroup, 
     SidTypeDomain, 
     SidTypeAlias, 
     SidTypeWellKnownGroup, 
     SidTypeDeletedAccount, 
     SidTypeInvalid, 
     SidTypeUnknown, 
     SidTypeComputer 
    } 

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    static extern bool LookupAccountSid(
     string lpSystemName, 
     [MarshalAs(UnmanagedType.LPArray)] byte[] Sid, 
     System.Text.StringBuilder lpName, 
     ref uint cchName, 
     System.Text.StringBuilder ReferencedDomainName, 
     ref uint cchReferencedDomainName, 
     out SID_NAME_USE peUse); 

    [StructLayout(LayoutKind.Sequential)] 
    struct SHARE_INFO_502 
    { 
     [MarshalAs(UnmanagedType.LPWStr)] 
     public string shi502_netname; 
     public uint shi502_type; 
     [MarshalAs(UnmanagedType.LPWStr)] 
     public string shi502_remark; 
     public Int32 shi502_permissions; 
     public Int32 shi502_max_uses; 
     public Int32 shi502_current_uses; 
     [MarshalAs(UnmanagedType.LPWStr)] 
     public string shi502_path; 
     public IntPtr shi502_passwd; 
     public Int32 shi502_reserved; 
     public IntPtr shi502_security_descriptor; 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    struct ACL_SIZE_INFORMATION 
    { 
     public uint AceCount; 
     public uint AclBytesInUse; 
     public uint AclBytesFree; 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    public struct ACE_HEADER 
    { 
     public byte AceType; 
     public byte AceFlags; 
     public short AceSize; 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    struct ACCESS_ALLOWED_ACE 
    { 
     public ACE_HEADER Header; 
     public int Mask; 
     public int SidStart; 
    } 

    enum ACL_INFORMATION_CLASS 
    { 
     AclRevisionInformation = 1, 
     AclSizeInformation 
    } 



    static void Main(string[] args) 
    { 
     IntPtr bufptr = IntPtr.Zero; 
     int err = NetShareGetInfo("ServerName", "ShareName", 502, out bufptr); 
     if (0 == err) 
     { 
      SHARE_INFO_502 shareInfo = (SHARE_INFO_502)Marshal.PtrToStructure(bufptr, typeof(SHARE_INFO_502)); 

      bool bDaclPresent; 
      bool bDaclDefaulted; 
      IntPtr pAcl = IntPtr.Zero; 
      GetSecurityDescriptorDacl(shareInfo.shi502_security_descriptor, out bDaclPresent, ref pAcl, out bDaclDefaulted); 
      if (bDaclPresent) 
      { 
       ACL_SIZE_INFORMATION AclSize = new ACL_SIZE_INFORMATION(); 
       GetAclInformation(pAcl, ref AclSize, (uint)Marshal.SizeOf(typeof(ACL_SIZE_INFORMATION)), ACL_INFORMATION_CLASS.AclSizeInformation); 
       for (int i = 0; i < AclSize.AceCount; i++) 
       { 
        IntPtr pAce; 
        err = GetAce(pAcl, i, out pAce); 
        ACCESS_ALLOWED_ACE ace = (ACCESS_ALLOWED_ACE)Marshal.PtrToStructure(pAce, typeof(ACCESS_ALLOWED_ACE)); 

        IntPtr iter = (IntPtr)((long)pAce + (long)Marshal.OffsetOf(typeof(ACCESS_ALLOWED_ACE), "SidStart")); 
        byte[] bSID = null; 
        int size = (int)GetLengthSid(iter); 
        bSID = new byte[size]; 
        Marshal.Copy(iter, bSID, 0, size); 
        IntPtr ptrSid; 
        ConvertSidToStringSid(bSID, out ptrSid); 
        string strSID = Marshal.PtrToStringAuto(ptrSid); 

        Console.WriteLine("The details of ACE number {0} are: ", i+1); 

        StringBuilder name = new StringBuilder(); 
        uint cchName = (uint)name.Capacity; 
        StringBuilder referencedDomainName = new StringBuilder(); 
        uint cchReferencedDomainName = (uint)referencedDomainName.Capacity; 
        SID_NAME_USE sidUse; 

        LookupAccountSid(null, bSID, name, ref cchName, referencedDomainName, ref cchReferencedDomainName, out sidUse); 

        Console.WriteLine("Trustee Name: " + name); 
        Console.WriteLine("Domain Name: " + referencedDomainName); 

        if ((ace.Mask & 0x1F01FF) == 0x1F01FF) 
        { 
         Console.WriteLine("Permission: Full Control"); 
        } 
        else if ((ace.Mask & 0x1301BF) == 0x1301BF) 
        { 
         Console.WriteLine("Permission: READ and CHANGE"); 
        } 
        else if ((ace.Mask & 0x1200A9) == 0x1200A9) 
        { 
         Console.WriteLine("Permission: READ only"); 
        } 
        Console.WriteLine("SID: {0} \nHeader AceType: {1} \nAccess Mask: {2} \nHeader AceFlag: {3}", strSID, ace.Header.AceType.ToString(), ace.Mask.ToString(), ace.Header.AceFlags.ToString()); 
        Console.WriteLine("\n"); 
       } 
      } 
      err = NetApiBufferFree(bufptr); 
     } 
    } 
} 

REF:またhttp://blogs.msdn.com/b/dsadsi/archive/2012/03/30/to-read-shared-permissions-of-a-server-resource-in-c-using-netsharegetinfo.aspx

私はそのいくつかの環境問題を考えているので、あなたが、別のネットワーク上のコードと、このコードを試してみてくださいすることができます。

関連する問題