question

onein528-6030 avatar image
0 Votes"
onein528-6030 asked onein528-6030 commented

[Win32API] How to change file owner.

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

windows-api
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

XiaopoYang-MSFT avatar image
0 Votes"
XiaopoYang-MSFT answered onein528-6030 commented

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`.


· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Thank you for your answer.

But, I was able to do it without getting privileges.

As Follow:

 BOOL SetFileOwner(LPWSTR filename, LPWSTR owner) {
    
     PSID pSid = GetSid(owner);
    
     if (!pSid) return FAILURE;
    
     // Change owner
     SECURITY_INFORMATION SecInfo  = OWNER_SECURITY_INFORMATION;
    
     // Start protected statement
     __try {
    
         // Set new owner/group in the object's security descriptor
         if (!SetNamedSecurityInfoW(filename, SE_FILE_OBJECT, SecInfo, pSid, NULL, NULL, NULL))
             __leave;
     }
     __finally {
    
         // Cleanup
         if (pSid) LocalFree(pSid);
         return SUCCESS;
     }
    
 }

0 Votes 0 ·