Как скопировать разрешения NTFS - PullRequest
0 голосов
/ 25 июня 2010

Я нашел способ скопировать информацию о разрешениях ntfs из одной существующей папки во вновь созданную - я не уверен, выполняет ли он ту работу, которую должен делать.Может быть, можно взглянуть на метод и дать некоторые комментарии:

private static void CopySecurityInformation(String source, String dest)
{
    FileSecurity fileSecurity = File.GetAccessControl(
        source,
        AccessControlSections.All);
    FileAttributes fileAttributes = File.GetAttributes(source);
    File.SetAccessControl(dest, fileSecurity);
    File.SetAttributes(dest, fileAttributes);
}

Спасибо за вашу помощь, Даниэль

Ответы [ 2 ]

2 голосов
/ 26 сентября 2014

Я попытался следовать предложенному OP шаблону для копирования ACL и атрибутов файла и обнаружил несколько проблем в нашем приложении. Надеюсь, эта информация поможет другим.

Согласно MSDN, использование метода File.SetAccessControl(), как показано выше, не будет работать.

Метод SetAccessControl сохраняет только объекты FileSecurity, которые были изменены после создания объекта. Если объект FileSecurity не был изменен, он не будет сохранен в файл. Следовательно, невозможно получить объект FileSecurity из одного файла и повторно применить тот же объект к другому файлу .

Необходимо создать новый объект FileSecurity для файла назначения и назначить ему копию исходного FileSecurity объекта.

Вот пример шаблона, который работает из нашего приложения.

    public static void CopyFile(string source, string destination)
    {
        // Copy the file
        File.Copy(source, destination, true);

        // Get the source file's ACLs
        FileSecurity fileSecuritySource = File.GetAccessControl(source, AccessControlSections.All);
        string sddlSource = fileSecuritySource.GetSecurityDescriptorSddlForm(AccessControlSections.All);

        // Create the destination file's ACLs
        FileSecurity fileSecurityDestination = new FileSecurity();
        fileSecurityDestination.SetSecurityDescriptorSddlForm(sddlSource);

        // Set the destination file's ACLs
        File.SetAccessControl(destination, fileSecurityDestination);

        // copy the file attributes now
        FileAttributes fileAttributes = File.GetAttributes(source);
        File.SetAttributes(destination, fileAttributes);
    }

После исправления первой проблемы мы обнаружили, что атрибут владельца не копируется. Вместо этого целевой файл в нашем случае принадлежал Администратору. Чтобы обойти это, процесс должен включить привилегию SE_RESTORE_NAME. Проверьте AdjustTokenPrivileges на pinvoke.net для полного класса привилегий, который облегчает настройку привилегий.

Последнее, с чем нам пришлось иметь дело, это UAC. Нам нужно было перезапустить наше приложение с правами администратора, если пользователь работает под управлением UAC. Вот еще один пример из нашего приложения, которое касается перезапуска приложения с повышенными привилегиями.

    private static void RelaunchWithAdministratorRights(string[] args)
    {
        // Launch as administrator
        ProcessStartInfo processStartInfo = new ProcessStartInfo();
        processStartInfo.UseShellExecute = true;
        processStartInfo.WorkingDirectory = Environment.CurrentDirectory;
        string executablePath = System.Reflection.Assembly.GetExecutingAssembly().Location;
        processStartInfo.FileName = executablePath;
        processStartInfo.Verb = "runas";

        if (args != null && args.Count() > 0)
        {
            string arguments = args[0];
            for (int i = 1; i < args.Count(); i++)
                arguments += " " + args[i];
            processStartInfo.Arguments = arguments;
        }

        try
        {
            using (Process exeProcess = Process.Start(processStartInfo))
            {
                exeProcess.WaitForExit();
            }
        }
        catch
        {
            // The user refused to allow privileges elevation. Do nothing and return directly ...
        }

        Environment.Exit(0);
    }

Наше приложение было консольным, поэтому нам нужно передать параметр args из метода Main в RelaunchWithAdministratorRights(args). Неконсольские приложения могут вместо этого принимать значение NULL. Мы вызываем RelaunchWithAdministratorRights из catch блоков, как в:

        try
        {
            ...
        }
        catch (SecurityException)
        {
            RelaunchWithAdministratorRights(args);
            return;
        }

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

Наслаждайтесь!

1 голос
/ 25 июня 2010

Это немного больше, чем просто копирование разрешений NTFS. Он также копирует атрибуты файла. Я не совсем уверен, копирует ли он унаследованные разрешения, но запустите его один раз, и вы сможете узнать.

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

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