Tuesday, April 28, 2009

Creating Win32 security descriptor with Delphi

Sometimes it is necessary to specify a non-default security options for a system object. In Windows API, this can be done specifying SecurityAttributes parameter in CreateFile, CreateSemaphore, CreateFileMapping etc. functions. However, filling the security attributes is not a very simple task, especially in Delphi. So I want to share my Delphi code that creates security attributes that allow full access for built-in Everyone account.

var
EveryoneSecurityDescriptor:TSecurityDescriptor;
pEveryoneACL:PACL;
EveryoneSID:PSID;
EveryoneSecurityAttributes:TSecurityAttributes;

procedure InitializeEveryoneSecurityDescriptor;
const
SECURITY_WORLD_SID_AUTHORITY : _SID_IDENTIFIER_AUTHORITY =
(Value : (0, 0, 0, 0, 0, 1));
SECURITY_WORLD_RID = $00000000;
ACL_REVISION = 2;
var cbAcl:Integer;
SIDAuthWorld:TSIDIdentifierAuthority;
begin
// create empty security descriptor
InitializeSecurityDescriptor(@EveryoneSecurityDescriptor,
SECURITY_DESCRIPTOR_REVISION);

// create SID for 'Everyone' account ('S-1-1-0')
SIDAuthWorld := SECURITY_WORLD_SID_AUTHORITY;
AllocateAndInitializeSID(SIDAuthWorld, 1,
SECURITY_WORLD_RID,
0, 0, 0, 0, 0, 0, 0, EveryoneSID);

// initialize ACL (Access Control List)
// size for an ACL with a single ACE
cbAcl := SizeOf(TACL) + 12 {SizeOf(ACCESS_ALLOWED_ACE)} +
GetLengthSid(EveryoneSID) - sizeof(DWORD);
GetMem(pEveryoneACL, cbAcl);
InitializeAcl(pEveryoneACL^, cbAcl, ACL_REVISION);

// add entry (ACE, Access Control Entry) for 'Everyone'
// to the ACL
AddAccessAllowedAce(pEveryoneACL^, ACL_REVISION,
GENERIC_ALL or GENERIC_READ or GENERIC_WRITE or
SPECIFIC_RIGHTS_ALL or STANDARD_RIGHTS_ALL,
EveryoneSID);

// set reference to the ACL for our security descriptor
SetSecurityDescriptorDacl(@EveryoneSecurityDescriptor,
True, pEveryoneACL, False);

// now fill in SECURITY_ATTRIBUTES structure. It can be
// passed to most WinAPI 'create' functions.
EveryoneSecurityAttributes.nLength:=
SizeOf(EveryoneSecurityAttributes);
EveryoneSecurityAttributes.lpSecurityDescriptor:=
@EveryoneSecurityDescriptor;
// change this if you need your handle to be inherited
EveryoneSecurityAttributes.bInheritHandle:=False;
end;

procedure FinalizeEveryoneSecurityDescriptor;
begin
if Assigned(EveryoneSID) then FreeSID(EveryoneSID);
if Assigned(pEveryoneACL) then FreeMem(pEveryoneACL);
end;

After calling InitializeEveryoneSecurityDescriptor, you can pass @EveryoneSecurityAttributes to any Create... function.

No comments:

Post a Comment