2011-11-29 68 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

相關問題