ERROR_ACCESS_DENIED установка владельца файла

Я пытаюсь установить владельца файла другому пользователю программно на С++.

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

Что еще может быть причиной этого сообщения об отказе в доступе? Что я не учел?

std::wstring fileSystemObject = L"C:\test.txt";
*status_code = SetNamedSecurityInfo((wchar_t*)fileSystemObject.c_str(), SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, pSID, NULL, NULL, NULL);
if (*status_code == ERROR_SUCCESS)
{
    Log(L"Successfully set owner for " + fileSystemObject);
    return true;
}
else
{
    Log(L"Failed to set owner for " + fileSystemObject + L". Error code: ", *status_code);
    return false;
}

Спасибо.

EDIT: Большое спасибо за вашу постоянную помощь. Это очень ценится.

Я использовал ваш код для всех следующих тестов. По сути, я также получаю сообщения об отказе в доступе из вашего кода, однако я немного отследил его.

Во-первых, "C:\test.txt" не был моим настоящим кодом, и, к сожалению, отсутствующая обратная косая черта не является причиной моей проблемы. Но спасибо за зоркий взгляд :)

Кроме того, я использую учетную запись администратора с отключенным UAC, и в моей программе в манифесте установлен параметр requireAdministrator.

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

1: я не являюсь владельцем, и для разрешений «Взять во владение» установлено значение «Запретить», например. Все.

2: я являюсь владельцем, и для разрешения «Взять на себя ответственность» установлено значение «Запретить», например. Все. Любопытно, что во втором случае, несмотря на код ошибки, смена владельца действительно происходит.

Я не понимаю, почему это происходит. Я и вы установили SE_RESTORE_NAME в маркере процесса. Мне должно быть разрешено произвольно устанавливать SID владельца. Но, кажется, я не могу.

Кажется, что любой отказ в DACL TakeOwnership переопределяет мою способность стать владельцем. Однако я не могу изменить разрешения, пока не стану владельцем! вздыхает.

Я мог бы попробовать установить SeTakeOwnershipPrivilege, как вы изначально рекомендовали, взять на себя ответственность, изменить разрешения, установить право собственности извне. Какая боль. И я даже не очень уверен, что это сработает.

Я также нашел это: http://us.generation-nt.com/setnamedsecurityinfo-failing-rc-1307-help-59729462.html

Кажется, он находится в похожей ситуации (я получаю 1307, если неправильно настрою токен процесса). Но CreatePrivateObjectSecurityEx требует гораздо больше настройки.

Хммм. Спасибо за ваше время.


person niemiro    schedule 09.09.2012    source источник
comment
SeTakeOwnershipPrivilege? stackoverflow.com/a/5454795/868014   -  person Roman R.    schedule 09.09.2012
comment
Спасибо за помощь. Мое понимание (которое может быть ошибочным - мой код не работает!) состоит в том, что SeTakeOwnershipPrivilege позволяет мне установить владельца для себя (а затем, я полагаю, для другого пользователя). Однако я подумал, что SeRestorePrivilege должен позволить мне установить его непосредственно для другого пользователя без этого дополнительного шага.   -  person niemiro    schedule 09.09.2012
comment
blogs.msdn.com/b/oldnewthing/archive/ 2005/08/18/453054.aspx   -  person niemiro    schedule 09.09.2012
comment
Я только что сделал быстрый тест и это сработало хорошо для меня. Интересно, в вашем реальном коде это C:\t, а не C:\\t? Я подумал, что у вас также может быть повышение привилегий, чтобы это удалось.   -  person Roman R.    schedule 09.09.2012
comment
Я обновил свой вопрос, потому что это было бы слишком долго для комментария.   -  person niemiro    schedule 09.09.2012
comment
Нашел кого-то еще с такой же проблемой: social.technet.microsoft.com/Forums/ta/winserverpowershell/ networksteve.com/forum/topic.php/ К сожалению, решения нет.   -  person niemiro    schedule 09.09.2012
comment
Что ж, отказ DACL во владении может быть проблемой. Однако даже в этом случае включение дополнительного SE_TAKE_OWNERSHIP_NAME кажется решением. Он подумал, что может потребоваться взять на себя ответственность, а затем временно удалить DACL, но нет, просто сработала дополнительная привилегия: обновленный код.   -  person Roman R.    schedule 09.09.2012
comment
Большое спасибо!!! Ваше исправление сработало отлично. Если вы создадите ответ на это, я с радостью отмечу его как таковой. Спасибо вам огромное,еще раз!!   -  person niemiro    schedule 09.09.2012
comment
Ах! Я говорил слишком рано. Теперь я продолжаю получать ERROR_INVALID_OWNER. Дайте мне немного времени на расследование. Я попробую много вещей и вернусь, если не смогу решить.   -  person niemiro    schedule 09.09.2012


Ответы (1)


Проблема здесь в том, что подсистема и модель безопасности защищают объект от необоснованной смены собственника, и даже наличие прав администратора необходимо для корректного преодоления препятствий.

Есть две привилегии, связанные с владением файлом: SE_TAKE_OWNERSHIP_NAME и SE_RESTORE_NAME. Первый позволяет взять чей-то объект, а второй позволяет установить владельца, который сам не является сеттером.

Может показаться, что SE_RESTORE_NAME — это более мощная привилегия и ее достаточно для выполнения задачи, однако оказывается, что это не так. Да, это позволяет установить чье-либо право собственности, как указано в MSDN:

Если у вызывающей стороны нет константы SeRestorePrivilege (см. Константы привилегий), этот SID должен содержаться в маркере вызывающей стороны, и для него должно быть включено разрешение SE_GROUP_OWNER. Параметр SecurityInfo должен включать флаг OWNER_SECURITY_INFORMATION. Чтобы установить владельца, у вызывающей стороны должен быть доступ WRITE_OWNER к объекту или должна быть включена привилегия SE_TAKE_OWNERSHIP_NAME.

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

Я копирую ссылку на исходный код C++/ATL из комментария выше: SetFileOwner.cpp. Когда разрешения/DACL имеют элемент «Запретить», возникает исключение, и включение второй привилегии решает проблему.

person Roman R.    schedule 09.09.2012
comment
Большое спасибо за вашу помощь, еще раз. Теперь все работает хорошо. Прошу прощения, что так долго не отвечал. Это было чрезвычайно беспокойно. Еще раз спасибо :) - person niemiro; 15.09.2012