Copy File Owner

delphi package - easy access to security apis
Post Reply
pcoenen
Posts: 19
Joined: Wed Mar 07, 2018 4:41 pm
Contact:

Copy File Owner

Post by pcoenen »

Hi,

After a copy of a file I would like to change the owner of the copied file to the owner of the original file. I've tried many (many) things but I'm getting "access denied" as LastErrorStr.
When I start my application As Administrator then I get "This security ID may not be assigned as the owner of this object."

Any idea what is wrong with my Function.

Code: Select all

Function CopyFileOwner(Const Source: String; Const Destination: String; Var ErrorStr: String): Boolean;
Var
  SourceSO: ISecurityObject;
  DestSO: ISecurityObject;
  tmpSource: String;
  tmpDestination: String;
  tmpSrcExists: Boolean;
  tmpDstExists: Boolean;
Begin
  // Init Var
  Result := False;
  ErrorStr := '';
  // Check Source
  tmpSource := Trim(Source);
  tmpDestination := Trim(Destination);
  tmpSrcExists := FileExists(tmpSource);
  tmpDstExists := FileExists(tmpDestination);
  // Check Exists
  If tmpSrcExists And tmpDstExists Then
  Begin
    Try
      SourceSO := FileSecurity(tmpSource);
      DestSO := FileSecurity(tmpDestination);
      DestSO.Owner := SourceSO.Owner;
      // Set Result
      ErrorStr := DestSO.LastErrorStr;
      Result := ErrorStr = '';
    Except
      On e: exception Do
        ErrorStr := Trim(e.Message);
    End;
  End
  Else
  Begin
    If (Not tmpSrcExists) Or (Not tmpDstExists) Then
      ErrorStr := 'Error File Does Not Exist ';
    If Not(tmpSrcExists) Then
      ErrorStr := ErrorStr + '[' + tmpSource + ']';
    If Not(tmpDstExists) Then
      ErrorStr := ErrorStr + '[' + tmpDestination + ']';
  End;
End;
Regards,
Pascal
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: Copy File Owner

Post by madshi »

Looks ok to me. Not sure what's going on there. You could debug madSecurity.pas by copying it (and mad.inc) into your project folder. Basically madSecurity is just a wrapper around the win32 API. So in the end either the wrapper must do something wrong, or the underlying win32 APIs doesn't play ball.
pcoenen
Posts: 19
Joined: Wed Mar 07, 2018 4:41 pm
Contact:

Re: Copy File Owner

Post by pcoenen »

ok good ideae. Let me try this ..
pcoenen
Posts: 19
Joined: Wed Mar 07, 2018 4:41 pm
Contact:

Re: Copy File Owner

Post by pcoenen »

In Function

Code: Select all

function TISecurityObject.SetSecurityInfo
The result of c1 = 5
(FYI: sidGroup, dacl, sacl are all Nil)

Code: Select all


c1 := SetNamedSecurityInfoW(PWideChar(name), type_, c1, sidOwner, sidGroup, dacl, sacl)[/b]

madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: Copy File Owner

Post by madshi »

5 = ERROR_ACCESS_DENIED
pcoenen
Posts: 19
Joined: Wed Mar 07, 2018 4:41 pm
Contact:

Re: Copy File Owner

Post by pcoenen »

Ok I found

https://docs.microsoft.com/en-us/window ... urityinfow
The SecurityInfo parameter must include the OWNER_SECURITY_INFORMATION flag. To set the owner, the caller must have WRITE_OWNER access to the object or have the SE_TAKE_OWNERSHIP_NAME privilege enabled.
Maybe stupid question but how do I enable SE_TAKE_OWNERSHIP_NAME flag
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: Copy File Owner

Post by madshi »

Here's how to enable *all* privileges. You should probably not do this:

Code: Select all

procedure EnableAllPrivileges;
type TTokenPrivileges = record
       PrivilegeCount : dword;
       Privileges     : array [0..maxInt shr 4 - 1] of TLUIDAndAttributes;
     end;
var token : THandle;
    c2    : dword;
    i1    : integer;
    ptp   : ^TTokenPrivileges;
    backup, restore, owner : int64;
begin
  if OpenProcessToken(windows.GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, token) then
    try
      c2 := 0;
      GetTokenInformation(token, TokenPrivileges, nil, 0, c2);
      if c2 <> 0 then begin
        ptp := pointer(LocalAlloc(LPTR, c2 * 2));
        if GetTokenInformation(token, TokenPrivileges, ptp, c2 * 2, c2) then begin
          for i1 := 0 to integer(ptp^.PrivilegeCount) - 1 do
            if (ptp^.Privileges[i1].Luid <> backup ) and
               (ptp^.Privileges[i1].Luid <> restore) and
               (ptp^.Privileges[i1].Luid <> owner  ) then
              ptp^.Privileges[i1].Attributes := ptp^.Privileges[i1].Attributes or SE_PRIVILEGE_ENABLED;
          AdjustTokenPrivileges(token, false, PTokenPrivileges(ptp)^, c2, PTokenPrivileges(nil)^, dword(pointer(nil)^));
        end;
        LocalFree(HLOCAL(ptp));
      end;
    finally CloseHandle(token) end;
end;
And of course you can only enable privileges that you already have but which are just not enabled yet. If your user account doesn't have a specific privilege *at all* (not even in disabled state), then the user simply can't do this. In that case you need to use a different user.
pcoenen
Posts: 19
Joined: Wed Mar 07, 2018 4:41 pm
Contact:

Re: Copy File Owner

Post by pcoenen »

Ok thank you. I did a test with the procedure EnableAllPrivileges

When I start my application as Adminstrator then it works. Enough for today:-)
I'll do some more testwork tomorrow (I need to limit this somehow), thanks for helping.

Regards,
Pascal
pcoenen
Posts: 19
Joined: Wed Mar 07, 2018 4:41 pm
Contact:

Re: Copy File Owner

Post by pcoenen »

Ok added a function called 'SetPrivilege'. I call this function before changing the owner. Application must be started as Administrator'.

SetPrivilege('SeRestorePrivilege'); // SE_RESTORE_NAME

Code: Select all

  Function SetPrivilege(Const PrivilegeName: String): Boolean;
  Var
    TokenPrivileges, RequestedPrivileges: TTokenPrivileges;
    Token: THandle;
    ReturnLength: DWord;
  Begin
    // http://delphi.cjcsoft.net/viewthread.php?tid=46650
    // https://docs.microsoft.com/nl-be/windows/desktop/SecAuthZ/privilege-constants
    Result := False;
    If OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY, Token) Then
    Begin
      RequestedPrivileges.PrivilegeCount := 1;
      If LookupPrivilegeValue(Nil, PWideChar(PrivilegeName), RequestedPrivileges.Privileges[0].LUID) Then
      Begin
        RequestedPrivileges.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
        ReturnLength := 0;
        Result := AdjustTokenPrivileges(Token, False, RequestedPrivileges, SizeOf(TokenPrivileges), TokenPrivileges, ReturnLength);
      End;
      CloseHandle(Token)
    End;
  End;
pcoenen
Posts: 19
Joined: Wed Mar 07, 2018 4:41 pm
Contact:

Re: Copy File Owner

Post by pcoenen »

FYI

My tool can be used as application or as service. With the service version I don't have to add any Administrator tricks. Even the default Logon As user of the service (= Local System Account) is allowed to change the owner of the copied file. Strange ..
Post Reply