Вызовы API заявляют, что у пользователя есть права доступа к папке, когда они этого не делают.

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

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

Сначала я подумал, что это может быть связано с тем, что служба работает под локальной учетной записью System, но та же проблема возникает, если она запускается с 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);
        }

person bleggett    schedule 29.11.2011    source источник


Ответы (2)


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

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

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

Обратите внимание, что, поскольку очень сложно правильно справиться со всеми возможными ситуациями (рассмотрите, например, запись управления доступом для всех или для СЛУЖБЫ), было бы разумно позволить администратору отменить проверку, если он ошибочно сообщает, что учетная запись не имеет необходимого доступа.

person Harry Johnston    schedule 30.11.2011
comment
Это полезные предложения, спасибо. Одна вещь, которую я обнаружил, заключается в том, что эта функция правильно сообщает о разрешениях для обычного пользователя, но сообщается, что администраторы имеют доступ, даже если мы отказываем этому пользователю в доступе. Не уверен, что это связано с тем, что пользователи-администраторы теоретически могут получить контроль над файлом или папкой независимо от фактических разрешений пользователя или нет. - person bleggett; 02.12.2011
comment
Если вы имеете в виду, что вы явно запрещаете доступ пользователя-администратора (используя запрещающие записи), то это просто потому, что функция обрабатывает запрещающие записи, как если бы они были разрешенными записями. - person Harry Johnston; 03.12.2011
comment
Как ни странно, это с включенной проверкой Разрешить/Запретить. - person bleggett; 06.12.2011
comment
Вы не забыли перестать искать, если найдете запрещенную запись? Обычно будет и запись о запрете, и запись о разрешении, причем та, которая появляется первой (которая всегда должна быть запрещающей), имеет приоритет. - person Harry Johnston; 06.12.2011

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

person Windows programmer    schedule 30.11.2011
comment
Существует общая проверка существования каталога перед вызовом ValidateFolderPermissions, которую я не включил во фрагмент, моя ошибка. - person bleggett; 01.12.2011