According to MSDN:SE_RESTORE_NAME and this thread, It's necessary to enable SE_RESTORE_NAME privilege which enables you to set any valid user or group SID as the owner of a file.
Additionally, It is recommend to use SetNamedSecurityInfo.
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Hi I'm making icacls command(It is windows file security utility) with C and Win32API.
So, when I try to implement the owner change, it fails with SetFileSecurity and GetLastError returns 1307.
What's wrong with this following code:
#include "Icacls.h"
BOOL SetFileOwner(LPWSTR lpFileName, LPWSTR lpUserName) {
DWORD dwSecurityDescriptorSize = 0;
// Get file security information size needed
if (!GetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION, NULL, 0, &dwSecurityDescriptorSize)) {
// Buffer shortage
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
// Allocate memory
PSECURITY_DESCRIPTOR pSecDesc = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, dwSecurityDescriptorSize + 1000);
if (NULL == pSecDesc) {
wprintf(L"LocalAlloc (pSecDesc) error: %d\n", GetLastError());
return ERROR_NOT_ENOUGH_MEMORY;
}
// Start protected statement
__try {
// Get file security information with size needed
if (!GetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION, pSecDesc, dwSecurityDescriptorSize, &dwSecurityDescriptorSize)) {
wprintf(L"GetFileSecurityW error: %d\n", GetLastError());
__leave;
}
// Initialize security descriptor
if (!InitializeSecurityDescriptor(pSecDesc, SECURITY_DESCRIPTOR_REVISION)) {
wprintf(L"InitializeSecurityDescriptor error: %d\n", GetLastError());
__leave;
}
BOOL bOwnerDefaulted = FALSE; PSID pNewSid = NULL;
// Get account sid from username
if (!GetAccountSid(lpUserName, &pNewSid, NULL)) {
wprintf(L"InitializeSecurityDescriptor error: %d\n", GetLastError());
__leave;
}
wprintf(L"lpUserName: %s\nlpFileName: %s\n\n", lpUserName, lpFileName);
// Set file owner to local security descriptor
if (!SetSecurityDescriptorOwner(pSecDesc, pNewSid, bOwnerDefaulted)) {
wprintf(L"SetSecurityDescriptorOwner error: %d\n", GetLastError());
__leave;
}
HANDLE hToken;
GetTokenHandle(&hToken);
AssertTakeOwnership(hToken);
// Set security descriptor to file security
if (!SetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION, pSecDesc)) {
wprintf(L"SetFileSecurityW error: %d\n", GetLastError());
__leave;
}
}
// Cleanup
__finally {
if (pSecDesc) LocalFree(pSecDesc);
return GetLastError();
}
}
}
}
BOOL GetTokenHandle(PHANDLE TokenHandle) {
HANDLE ProcessHandle;
BOOL Result;
ProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
if (ProcessHandle == NULL) {
return(FALSE);
}
Result = OpenProcessToken(ProcessHandle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, TokenHandle);
if (!Result) {
CloseHandle(ProcessHandle);
return FALSE;
}
CloseHandle(ProcessHandle);
return(TRUE);
}
BOOL AssertTakeOwnership(HANDLE TokenHandle) {
LUID TakeOwnershipValue;
BOOL Result;
TOKEN_PRIVILEGES TokenPrivileges;
Result = LookupPrivilegeValueW(NULL, L"SeTakeOwnershipPrivilege", &TakeOwnershipValue);
if (!Result) {
return FALSE;
}
TokenPrivileges.PrivilegeCount = 1;
TokenPrivileges.Privileges[0].Luid = TakeOwnershipValue;
TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
(VOID)AdjustTokenPrivileges(TokenHandle, FALSE, &TokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
if (GetLastError() != NO_ERROR) {
return FALSE;
}
return(TRUE);
}
According to MSDN:SE_RESTORE_NAME and this thread, It's necessary to enable SE_RESTORE_NAME privilege which enables you to set any valid user or group SID as the owner of a file.
Additionally, It is recommend to use SetNamedSecurityInfo.