2011-11-29 99 views
0

如果Windows服务需要监视/访问一组文件夹,并在这些文件夹之间移动文件时遇到问题。API调用要求用户具有文件夹权限时

过去已经使用了一些样板代码,它将检查给定文件夹中给定用户的特定粒度权限。奇怪的是,我通过测试发现,如果手动拒绝该服务运行所在的帐户对该文件夹的所有权限,然后运行代码,则会报告一切正常,并且用户实际上拥有这些权限,即使它很明显(并且可证明)他没有。

起初我以为这可能是因为该服务在本地系统帐户下运行,但如果与NetworkService以及本地用户帐户一起运行,则会出现同样的问题。这在Windows 7/2008 R2上。

样板方法:

public static void ValidateFolderPermissions(WindowsIdentity userId, string folder, FileSystemRights[] requiredAccessRights) 
    { 
     SecurityIdentifier secId; 
     StringBuilder sb = new StringBuilder(); 
     bool permissionsAreSufficient = false; 
     bool notAuthorized = false; 
     String errorMsg = String.Empty; 

     IdentityReferenceCollection irc = userId.Groups; 

     foreach (IdentityReference ir in irc) 
     { 
      secId = ir.Translate(typeof(SecurityIdentifier)) as SecurityIdentifier; 

      try 
      { 
       DirectoryInfo dInfo = new DirectoryInfo(folder); 
       DirectorySecurity dSecurity = dInfo.GetAccessControl(); 
       AuthorizationRuleCollection rules = dSecurity.GetAccessRules(true, true, typeof(SecurityIdentifier)); 
       foreach (FileSystemAccessRule ar in rules) 
       { 
        if (secId.CompareTo(ar.IdentityReference as SecurityIdentifier) == 0) 
        { 
         sb.AppendLine(ar.FileSystemRights.ToString()); 

         foreach (FileSystemRights right in requiredAccessRights) 
         { 
          if (right == ar.FileSystemRights) 
          { 
           permissionsAreSufficient = true; 
           break; 
          } 
         } 
        } 
       } 
      } 
      catch (UnauthorizedAccessException) 
      { 
       notAuthorized = true; 
       errorMsg = "user not authorized"; 
      } 
      catch (SecurityException) 
      { 
       // If we failed authorization do not update error 
       if (!notAuthorized) 
        errorMsg = "security error"; 
      } 
      catch (Exception) 
      { 
       // If we failed authorization do not update error 
       if (!notAuthorized) 
        errorMsg = "invalid folder or folder not accessible"; 
      } 
     } 

     if (!permissionsAreSufficient) 
     { 
      if (!String.IsNullOrEmpty(errorMsg)) 
       throw new Exception(String.Format("User {0} does not have required access to folder {1}. The error is {2}.", userId.Name, folder, errorMsg)); 
      else 
       throw new Exception(String.Format("User {0} does not have required access rights to folder {1}.", userId.Name, folder)); 
     } 
    } 

和主叫片段:

FileSystemRights[] requireAccessRights = 
     { 
      FileSystemRights.Delete, 
      FileSystemRights.Read, 
      FileSystemRights.FullControl 
     }; 

     try 
     { 
      FolderPermissionValidator.ValidateFolderPermissions(WindowsIdentity.GetCurrent(), inputFolder, requireAccessRights); 
      Log.Debug("In ServiceConfigurationValidator: {0}, {1}", WindowsIdentity.GetCurrent().Name, inputFolder); 
     } 
     catch (Exception ex) 
     { 
      Log.Debug("Throwing exception {0}", ex.Message); 
     } 

回答

1

此代码枚举ACL中的条目为FileSystemAccessRule对象,但不打扰检查AccessControlType是允许还是拒绝。

我还注意到,逻辑返回true如果任何ACE 恰好匹配的requiredAccessRights阵列的元件的任何;我怀疑预期的行为是,如果所有指定的权利都存在,它将返回true。如果只有一些请求的权限存在,这可能会导致误报,但是由于它只查找完全匹配,所以也可能导致错误否定,例如,如果ACE实际上给出的权限比请求的多。 (虽然在给出的示例中没有这样的问题,但是,因为您要求完全控制。)

另一个缺陷是它只检查与用户所属的组匹配的访问条目;用户帐户本身的访问条目将被忽略。 (我不确定WindowsIdentity.Groups的行为对于像SYSTEM和NetworkService这样的非真实用户帐户的安全原语是什么,尽管听起来像那个部分是按照需要工作的。)

请注意,因为它是很难正确处理所有可能的情况(例如,考虑每个人的访问控制条目或服务),允许管理员覆盖检查是否明智地报告该账户是否有错误报告必要的访问。

+0

这些是有益的建议,谢谢。我发现的一件事是,对于标准用户,这个函数的权限被正确报告,但即使我们拒绝该用户访问,管理用户也被报告具有访问权限。不知道这是否是因为管理员用户理论上可以控制文件或文件夹,而不管用户的实际权限与否。 – bleggett

+0

如果您的意思是您明确拒绝管理员用户访问(使用拒绝条目),那只是因为该功能将拒绝条目视为允许条目。 –

+0

这是与一个允许/拒绝检查,足够奇怪。 – bleggett

2

我没有看到任何ValidateFolderPermissions检查允许权限之前检查否认。如果拒绝条目阻止访问,则没有任何允许条目可以覆盖它。

+0

在ValidateFolderPermissions调用之前有一个通用的“Directory Exists”检查,我没有包含在代码片段中,这是我的错误。 – bleggett

相关问题