Вызовы API утверждают, что у пользователя есть разрешения на доступ к папкам - PullRequest
0 голосов
/ 30 ноября 2011

Возникла проблема со службой Windows, которая должна отслеживать / иметь доступ к набору папок и перемещать файлы между этими папками.

Существует немного стандартного кода, который использовался в прошлом, который проверит заданную папку для конкретных гранулярных разрешений для данного пользователя.Странно то, что в ходе тестирования я обнаружил, что если я вручную отрицаю все разрешения в этой папке для учетной записи, под которой работает служба, а затем запускаю код, он сообщает, что все в порядке, и у пользователя действительно есть эти разрешения,хотя очевидно (и это очевидно), что он этого не делает.

Сначала я подумал, что это может быть связано с тем, что служба работала под локальной системной учетной записью, но та же проблема возникает, если она запускается с NetworkService.а также с локальной учетной записью пользователя.Это на Windows 7/2008 R2.

Метод Boilerplate:

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);
        }

Ответы [ 2 ]

2 голосов
/ 30 ноября 2011

Я не вижу ничего в ValidateFolderPermissions, чтобы проверить наличие отказов перед проверкой разрешенных разрешений. Если запрещенная запись запрещает доступ, то никакое количество разрешенных записей не может переопределить ее.

1 голос
/ 30 ноября 2011

Этот код перечисляет записи в ACL как объекты FileSystemAccessRule, но не заботится о том, чтобы разрешить или запретить AccessControlType.

Я также отмечаю, что логика возвращает true, если любой ACE точно соответствует любому элементов массива requiredAccessRights;Я подозреваю, что предполагаемое поведение состоит в том, что он возвращает true, если all указанных прав присутствуют.Это может привести к ложным срабатываниям, если присутствуют только некоторые из запрошенных прав, но поскольку он ищет только точные совпадения, это также может привести к ложному отрицанию, например, если ACE фактически дает больше прав, чем запрашивается,(Однако в данном примере это не такая проблема, потому что вы запрашиваете полный доступ.)

Еще один недостаток состоит в том, что он проверяет только те записи доступа, которые соответствуют группам, к которым принадлежит пользователь;записи доступа для самой учетной записи пользователя будут игнорироваться.(Я не уверен, каково поведение WindowsIdentity.Groups для примитивов безопасности, таких как SYSTEM и NetworkService, которые не являются действительными учетными записями пользователей, хотя кажется, что эта часть работала должным образом.)

Обратите внимание, что, посколькуочень трудно правильно справиться со всеми возможными ситуациями (например, для элемента управления доступом для каждого пользователя или для SERVICE) было бы целесообразно разрешить администратору отменять проверку, если он ошибочно сообщает, что учетная запись не 'не иметь необходимого доступа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...