Compartir objetos del kernel entre procesos (SECURITY_DESCRIPTOR)

En el siguiente ejemplo demuestro como crear un descriptor de seguridad (security descriptor) para permitir el acceso a un objeto del kernel a todos los usuarios, de esta manera puede ser compartido por procesos pertenecientes a diferentes cuentas de usuario. Esto puede resultar útil, por ejemplo, cuando un servicio tiene que compartir un objeto con una aplicación que se esta ejecutando bajo una cuenta de usuario diferente.

La siguiente función inicializa la variable del tipo SECURITY_DESCRIPTOR, que se le pasa como parámetro, con una DACL que permite a todos los usuarios identificados los accesos GERERIC_READ, GENERIC_WRITE y GENERIC_EXECUTE. La función devuelve nil si falla o un puntero si termina con éxito. Este puntero debe ser liberado, una vez lo hemos utilizado para crear el nuevo objeto, llamando a la función FreeRestridtedSD.

const
  SECURITY_NT_AUTHORITY: TSIDIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 5));
  SECURITY_AUTHENTICATED_USER_RID = 11;
  ACL_REVISION  = 2;
 
type
  ACE_HEADER = record
    AceType,
    AceFlags: BYTE;
    AceSize: WORD;
  end;
 
  PACE_HEADER = ^ACE_HEADER;
 
  ACCESS_ALLOWED_ACE = record
    Header: ACE_HEADER;
    Mask: ACCESS_MASK;
    SidStart: DWORD;
  end;
 
function BuildRestrictedSD(pSD: PSECURITY_DESCRIPTOR): Pointer;
var
  dwAclLength: DWORD;
  pAuthenticatedUsersSID: PSID;
  pDACL: PACL;
  bResult: BOOL;
  siaNT: SID_IDENTIFIER_AUTHORITY;
begin
  pAuthenticatedUsersSID:= nil;
  pDACL:= nil;
  bResult:= FALSE;
  siaNT:= SECURITY_NT_AUTHORITY;
  if InitializeSecurityDescriptor(pSD,SECURITY_DESCRIPTOR_REVISION) then
    if AllocateAndInitializeSid(siaNT, 1, SECURITY_AUTHENTICATED_USER_RID,
      0, 0, 0, 0, 0, 0, 0,pAuthenticatedUsersSID) then
    begin
      dwAclLength:= Sizeof(ACL)
            + Sizeof(ACCESS_ALLOWED_ACE) - Sizeof(DWORD)
            + GetLengthSid(pAuthenticatedUsersSID);
      GetMem(pDACL,dwAclLength);
      if InitializeAcl(pDACL^, dwAclLength, ACL_REVISION) then
        if AddAccessAllowedAce(pDACL^, ACL_REVISION,
          GENERIC_READ or GENERIC_WRITE or GENERIC_EXECUTE,
          pAuthenticatedUsersSID) then
          if SetSecurityDescriptorDacl(pSD, TRUE, pDACL, FALSE) then
            bResult:= TRUE;
      if pAuthenticatedUsersSID <> nil then
        FreeSid(pAuthenticatedUsersSID);
      if not bResult then
        if pDACL <> nil then
        begin
          FreeMem(pDACL);
          pDACL:= nil;
        end;
    end;
  Result:= pDACL;
end;

Ahora vamos a demostrar como, utilizando la función anterior, podemos crear un mutex que puede ser compartido entre distintos usuarios:

function CrearMutex(Nombre: String): THandle;
var
  sa: SECURITY_ATTRIBUTES;
  sd: SECURITY_DESCRIPTOR;
  ptr: Pointer;
begin
  Result:= 0;
  ptr:= BuildRestrictedSD(@sd);
  if ptr <> nil then
  try
    sa.nLength:= Sizeof(sa);
    sa.lpSecurityDescriptor:= @sd;
    sa.bInheritHandle:= FALSE;
    Result:= CreateMutex(@sa, TRUE, PChar(Nombre));
    if Result <> 0 then
      ReleaseMutex(Result);
  finally
    FreeMem(ptr);
  end;
end;

Comentarios

Muy interesante este código!!!, lo probaré.

saludos seoane