Page 1 of 1

WinApi : Set File Permission (32bits/64bits)

Posted: Mon Jun 19, 2023 10:11 am
by tatanas
Hi,

I'm trying to set permission on a file with WinApi. It works fine in 32 bits but not in 64 bits.
It seems the problem come from the EXPLICIT_ACCESS structure size (https://stackoverflow.com/questions/589 ... riesinacla).

Here is the code :

Code: Select all

; #include <Accctrl.h>
; #include <Aclapi.h>

#GRANT_ACCESS = 1
#NO_INHERITANCE = 0
#TRUSTEE_IS_SID = 0
#TRUSTEE_IS_WELL_KNOWN_GROUP = 5
#SECURITY_WORLD_SID_AUTHORITY = 1
#DACL_SECURITY_INFORMATION = 4

Structure NTAUTHORITY
	NtAuthority.b[6]
EndStructure

Structure TRUSTEE
	*pMultipleTrustee
	MultipleTrusteeOperation.l
	TrusteeForm.l
	TrusteeType.l
	*ptstrName
EndStructure

Structure EXPLICIT_ACCESS
	grfAccessPermissions.l
	grfAccessMode.l
	grfInheritance.l
	Trustee.TRUSTEE
EndStructure


Procedure SetFilePermission(FileName.s)
	Protected Security_Nt_Authority.NTAUTHORITY
	Security_Nt_Authority\NtAuthority[5] = #SECURITY_WORLD_SID_AUTHORITY
		
	; Create a well-known SID For the Everyone group.
	Protected *pEveryoneSID = #Null
	If Not AllocateAndInitializeSid_(@Security_Nt_Authority, 1, #SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, @*pEveryoneSID)
		Debug "erreur AllocateAndInitializeSid_ : " + GetLastError_()
	EndIf
	
	; Initialize an EXPLICIT_ACCESS Structure For an ACE.
	Protected Dim ea.EXPLICIT_ACCESS(0)
	ea(0)\grfAccessPermissions = $FFFFFFFF ; all access
	ea(0)\grfAccessMode = #GRANT_ACCESS
	ea(0)\grfInheritance= #NO_INHERITANCE
	ea(0)\Trustee\TrusteeForm = #TRUSTEE_IS_SID
	ea(0)\Trustee\TrusteeType = #TRUSTEE_IS_WELL_KNOWN_GROUP
	ea(0)\Trustee\MultipleTrusteeOperation = 0
	ea(0)\Trustee\ptstrName = *pEveryoneSID


   ; Create a new ACL that contains the new ACEs.
	Protected *pACL = #Null
   ret = SetEntriesInAcl_(1, @ea(), #Null, @*pACL)
	If ret <> #ERROR_SUCCESS
		Debug "erreur SetEntriesInAcl_ : " + ret ; 87 invalid parameter
		ProcedureReturn 0
	EndIf

   ; Initialize a security descriptor.  
	Protected *pSD.SECURITY_DESCRIPTOR = AllocateMemory(#SECURITY_DESCRIPTOR_MIN_LENGTH)
	If Not InitializeSecurityDescriptor_(*pSD, #SECURITY_DESCRIPTOR_REVISION)
		Debug "erreur InitializeSecurityDescriptor_ : " + GetLastError_()
		ProcedureReturn 0
	EndIf

   ; Add the ACL To the security descriptor. 
   If Not SetSecurityDescriptorDacl_(*pSD, 
            #True, ;    // bDaclPresent flag   
            *pACL, 
            #False) ;   // Not a Default DACL 
		Debug "erreur SetSecurityDescriptorDacl_ : " + GetLastError_()
		ProcedureReturn 0
	EndIf

   ; Change the security attributes
   If Not SetFileSecurity_(FileName, #DACL_SECURITY_INFORMATION, *pSD)
		Debug "erreur SetFileSecurity_ : " + GetLastError_()
		ProcedureReturn 0
	EndIf

   If *pEveryoneSID : FreeSid_(*pEveryoneSID) : EndIf
   If *pACL : LocalFree_(*pACL) : EndIf
   If *pSD : FreeMemory(*pSD) : EndIf
EndProcedure


If CreateFile(0, "c:\test.txt")
	CloseFile(0)

	SetFilePermission("c:\test.txt")
EndIf
Thanks for your time

Re: WinApi : Set File Permission (32bits/64bits)

Posted: Mon Jun 19, 2023 3:11 pm
by Axolotl
If your assumption is correct, then it is probably due to the size of the typedef enums. (i.e. ACCESS_MODE and TRUSTEE)
I would probably check the sizes of the enum based data with a c-compiler if i had one......
Unfortunately I can't help at this point.

Re: WinApi : Set File Permission (32bits/64bits)

Posted: Mon Jun 19, 2023 4:01 pm
by luis
Hi

Code: Select all

Structure TRUSTEE Align #PB_Structure_AlignC
	*pMultipleTrustee
	MultipleTrusteeOperation.l
	TrusteeForm.l
	TrusteeType.l
	*ptstrName
EndStructure

Structure EXPLICIT_ACCESS Align #PB_Structure_AlignC
	grfAccessPermissions.l
	grfAccessMode.l
	grfInheritance.l
	Trustee.TRUSTEE
EndStructure

Re: WinApi : Set File Permission (32bits/64bits)

Posted: Tue Jun 20, 2023 7:01 am
by tatanas
I tried your solution Luis. There is no error 87 from SetEntriesInAcl() like before, unfortunately the permission isn't apply.
The problem could come from grfAccessPermissions from EXPLICIT_ACCESS which can't accept $FFFFFFFF (all rights) if we keep it as LONG. But if we change it to INTEGER, the error comes back...

Re: WinApi : Set File Permission (32bits/64bits)

Posted: Tue Jun 20, 2023 7:53 am
by tatanas
I found a workaround. It's working fine in 64 bits :

Code: Select all

; https://binaryworld.net/Main/CodeDetail.aspx?CodeId=3659

#SE_FILE_OBJECT = 1

#GRANT_ACCESS = 1
#NO_INHERITANCE = 0
#TRUSTEE_IS_SID = 0
#TRUSTEE_IS_WELL_KNOWN_GROUP = 5
#SECURITY_WORLD_SID_AUTHORITY = 1
#DACL_SECURITY_INFORMATION = 4

#READ_CONTROL = $20000
#GENERIC_READ = $80000000
#GENERIC_WRITE = $40000000
#STANDARD_RIGHTS_ALL = $1F0000
#ALL_ACCESS = $FFFFFFFF


Structure TRUSTEE Align #PB_Structure_AlignC
	*pMultipleTrustee
	MultipleTrusteeOperation.l
	TrusteeForm.l
	TrusteeType.l
	*ptstrName
EndStructure

Structure EXPLICIT_ACCESS Align #PB_Structure_AlignC
	grfAccessPermissions.i
	grfAccessMode.l
	grfInheritance.l
	Trustee.TRUSTEE
EndStructure


Procedure SetFilePermission(FileName.s, TrusteeName.s, Permissions.i)

	Protected ea.EXPLICIT_ACCESS
	Protected pOldDACL.i
	Protected *pSecDesc = #Null
	Protected *pNewDACL = #Null
	Protected result.i
	
	result = GetNamedSecurityInfo_(FileName, #SE_FILE_OBJECT, #DACL_SECURITY_INFORMATION, #Null, #Null, @pOldDACL, #Null, @*pSecDesc)
	If result <> #ERROR_SUCCESS
		Debug "GetNamedSecurityInfo_ Error : " + result
		ProcedureReturn 0
	EndIf
	
   BuildExplicitAccessWithName_(@ea, TrusteeName, Permissions, #GRANT_ACCESS, #CONTAINER_INHERIT_ACE | #OBJECT_INHERIT_ACE)

	result = SetEntriesInAcl_(1, @ea, pOldDACL, @*pNewDACL)
	If result <> #ERROR_SUCCESS
		Debug "SetEntriesInAcl_ Error : " + result
		ProcedureReturn 0
	EndIf

   result = SetNamedSecurityInfo_(FileName, #SE_FILE_OBJECT, #DACL_SECURITY_INFORMATION, #Null, #Null, *pNewDACL, #Null)
   If result <> #ERROR_SUCCESS
		Debug "SetNamedSecurityInfo_ Error : " + result
		ProcedureReturn 0
	EndIf

	LocalFree_(*pNewDACL)
	LocalFree_(*pSecDesc)

	ProcedureReturn 1

EndProcedure


If CreateFile(0, "c:\test.txt")
	CloseFile(0)

	SetFilePermission("c:\test.txt", "Tout le monde", #GENERIC_WRITE | #GENERIC_READ)
EndIf

Re: WinApi : Set File Permission (32bits/64bits)

Posted: Tue Jun 20, 2023 11:07 am
by luis
tatanas wrote: Tue Jun 20, 2023 7:01 am I tried your solution Luis. There is no error 87 from SetEntriesInAcl() like before, unfortunately the permission isn't apply.
Are you sure ? I've just tried compiled to 64 bits and it creates the file with "everyone" as group and all permissions enabled.
Tried 32 bits and seems to do the same, so I thought it was OK.
Isn't that what it is supposed to do ?
I'm also using Win 10 x64. The only thing I've changed beyond the structure is putting the file under temp, else can't be created in my C: root.
tatanas wrote: Tue Jun 20, 2023 7:01 amThe problem could come from grfAccessPermissions from EXPLICIT_ACCESS which can't accept $FFFFFFFF (all rights) if we keep it as LONG.
Sure it can. It's 32 bit. PB interpret it as a signed long but it's not important to the API reading from it.
You can set all bits to 1 in it nevertheless. Just try it and print it using Hex().

Your last code instead doesn't work for me and I get this error:

SetEntriesInAcl_ Error : 1332

Re: WinApi : Set File Permission (32bits/64bits)

Posted: Tue Jun 20, 2023 11:35 am
by tatanas
Did you change the "Tout le monde" Windows group by your own language version ?
I replace the grfAccessPermissions.i by Long and you're right it works too.

Re: WinApi : Set File Permission (32bits/64bits)

Posted: Tue Jun 20, 2023 11:44 am
by luis
tatanas wrote: Tue Jun 20, 2023 11:35 am Did you change the "Tout le monde" Windows group by your own language version ?
Evidently no, I did but maybe I made a typo. I'm sorry. Works now. Or at least I don't get the error.
But your last code seems to just be adding "everyone" not to replace everything else.
And now that I notice... doesn't set all the permission to enabled like the original code, I have only read and write.

Still, the original one with just the alignment changed worked for me.
Was supposed to add the "everyone" group or to replace everything with the "everyone" group ?
Because both 32 and 64 seem to do the latter so I assumed that was what you wanted to do.
Anyway, both the 32 bits and the 64 bits were giving the same result on my PC.

Re: WinApi : Set File Permission (32bits/64bits)

Posted: Tue Jun 20, 2023 1:02 pm
by tatanas
It was supposed to add the "everyone" group. So it works as it should for both of us :).
Thanks for your help.