373 lines
14 KiB
ObjectPascal
373 lines
14 KiB
ObjectPascal
{*******************************************************}
|
|
{ MiTeC Common Routines }
|
|
{ Access Control API }
|
|
{ }
|
|
{ Copyright (c) 2009-2013 Michal Mutl }
|
|
{ }
|
|
{*******************************************************}
|
|
|
|
{$INCLUDE Compilers.inc}
|
|
|
|
unit MiTeC_AclApi;
|
|
|
|
interface
|
|
|
|
uses{$IFDEF RAD9PLUS}
|
|
WinAPI.Windows, System.SysUtils;
|
|
{$ELSE}
|
|
Windows, SysUtils;
|
|
{$ENDIF}
|
|
|
|
type
|
|
_SE_OBJECT_TYPE = (
|
|
SE_UNKNOWN_OBJECT_TYPE,
|
|
SE_FILE_OBJECT,
|
|
SE_SERVICE,
|
|
SE_PRINTER,
|
|
SE_REGISTRY_KEY,
|
|
SE_LMSHARE,
|
|
SE_KERNEL_OBJECT,
|
|
SE_WINDOW_OBJECT,
|
|
SE_DS_OBJECT,
|
|
SE_DS_OBJECT_ALL,
|
|
SE_PROVIDER_DEFINED_OBJECT,
|
|
SE_WMIGUID_OBJECT,
|
|
SE_REGISTRY_WOW64_32KEY);
|
|
SE_OBJECT_TYPE = _SE_OBJECT_TYPE;
|
|
TSeObjectType = SE_OBJECT_TYPE;
|
|
|
|
PPSID = ^PSID;
|
|
|
|
{PACL = ^ACL;
|
|
_ACL = record
|
|
AclRevision: Byte;
|
|
Sbz1: Byte;
|
|
AclSize: Word;
|
|
AceCount: Word;
|
|
Sbz2: Word;
|
|
end;
|
|
ACL = _ACL;
|
|
TAcl = ACL;}
|
|
|
|
PPACL = ^PAcl;
|
|
|
|
//
|
|
// Definition: TRUSTEE_TYPE
|
|
// This enumerated type specifies the type of trustee account for the trustee
|
|
// returned by the API described in this document.
|
|
// TRUSTEE_IS_UNKNOWN - The trustee is an unknown, but not necessarily invalid
|
|
// type. This field is not validated on input to the APIs
|
|
// that take Trustees.
|
|
// TRUSTEE_IS_USER The trustee account is a user account.
|
|
// TRUSTEE_IS_GROUP The trustee account is a group account.
|
|
//
|
|
|
|
_TRUSTEE_TYPE = (
|
|
TRUSTEE_IS_UNKNOWN,
|
|
TRUSTEE_IS_USER,
|
|
TRUSTEE_IS_GROUP,
|
|
TRUSTEE_IS_DOMAIN,
|
|
TRUSTEE_IS_ALIAS,
|
|
TRUSTEE_IS_WELL_KNOWN_GROUP,
|
|
TRUSTEE_IS_DELETED,
|
|
TRUSTEE_IS_INVALID,
|
|
TRUSTEE_IS_COMPUTER);
|
|
TRUSTEE_TYPE = _TRUSTEE_TYPE;
|
|
TTrusteeType = TRUSTEE_TYPE;
|
|
|
|
//
|
|
// Definition: TRUSTEE_FORM
|
|
// This enumerated type specifies the form the trustee identifier is in for a
|
|
// particular trustee.
|
|
// TRUSTEE_IS_SID The trustee is identified with a SID rather than with a name.
|
|
// TRUSTEE_IS_NAME The trustee is identified with a name.
|
|
//
|
|
|
|
_TRUSTEE_FORM = (
|
|
TRUSTEE_IS_SID,
|
|
TRUSTEE_IS_NAME,
|
|
TRUSTEE_BAD_FORM,
|
|
TRUSTEE_IS_OBJECTS_AND_SID,
|
|
TRUSTEE_IS_OBJECTS_AND_NAME);
|
|
TRUSTEE_FORM = _TRUSTEE_FORM;
|
|
TTrusteeForm = TRUSTEE_FORM;
|
|
|
|
//
|
|
// Definition: MULTIPLE_TRUSTEE_OPERATION
|
|
// If the trustee is a multiple trustee, this enumerated type specifies the type.
|
|
// TRUSTEE_IS_IMPERSONATE The trustee is an impersonate trustee and the multiple
|
|
// trustee field in the trustee points to another trustee
|
|
// that is a trustee for the server that will be doing the
|
|
// impersonation.
|
|
//
|
|
|
|
_MULTIPLE_TRUSTEE_OPERATION = (NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_IMPERSONATE);
|
|
MULTIPLE_TRUSTEE_OPERATION = _MULTIPLE_TRUSTEE_OPERATION;
|
|
TMultipleTrusteeOperation = MULTIPLE_TRUSTEE_OPERATION;
|
|
|
|
PTRUSTEE_A = ^TRUSTEE_A;
|
|
_TRUSTEE_A = packed record
|
|
pMultipleTrustee: PTRUSTEE_A;
|
|
MultipleTrusteeOperation: MULTIPLE_TRUSTEE_OPERATION;
|
|
TrusteeForm: TRUSTEE_FORM;
|
|
TrusteeType: TRUSTEE_TYPE;
|
|
ptstrName: LPSTR;
|
|
end;
|
|
TRUSTEE_A = _TRUSTEE_A;
|
|
TRUSTEEA = TRUSTEE_A;
|
|
PPTRUSTEE_A = ^PTRUSTEE_A;
|
|
TTrusteeA = TRUSTEE_A;
|
|
PTrusteeA = PTRUSTEE_A;
|
|
|
|
PTRUSTEE_W = ^TRUSTEE_W;
|
|
_TRUSTEE_W = packed record
|
|
pMultipleTrustee: PTRUSTEE_W;
|
|
MultipleTrusteeOperation: MULTIPLE_TRUSTEE_OPERATION;
|
|
TrusteeForm: TRUSTEE_FORM;
|
|
TrusteeType: TRUSTEE_TYPE;
|
|
ptstrName: LPWSTR;
|
|
end;
|
|
TRUSTEE_W = _TRUSTEE_W;
|
|
TRUSTEEW = TRUSTEE_W;
|
|
PPTRUSTEE_W = ^PTRUSTEE_W;
|
|
TTrusteeW = TRUSTEE_W;
|
|
PTrusteeW = PTRUSTEE_W;
|
|
|
|
{$IFDEF UNICODE}
|
|
TRUSTEE_ = TRUSTEE_W;
|
|
PTRUSTEE_ = PTRUSTEE_W;
|
|
TRUSTEE = TRUSTEEW;
|
|
PPTRUSTEE = ^PPTRUSTEE_W;
|
|
TTrustee = TTrusteeW;
|
|
PTrustee = PTrusteeW;
|
|
{$ELSE}
|
|
TRUSTEE_ = TRUSTEE_A;
|
|
PTRUSTEE_ = PTRUSTEE_A;
|
|
TRUSTEE = TRUSTEEA;
|
|
PPTRUSTEE = ^PPTRUSTEE_A;
|
|
TTrustee = TTrusteeA;
|
|
PTrustee = PTrusteeA;
|
|
{$ENDIF}
|
|
|
|
//
|
|
// Definition: ACCESS_MODE
|
|
// This enumerated type specifies how permissions are (requested)/to be applied
|
|
// for the trustee by the access control entry. On input this field can by any
|
|
// of the values, although it is not meaningful to mix access control and audit
|
|
// control entries. On output this field will be either SET_ACCESS, DENY_ACCESS,
|
|
// SET_AUDIT_SUCCESS, SET_AUDIT_FAILURE.
|
|
// The following descriptions define how this type effects an explicit access
|
|
// request to apply access permissions to an object.
|
|
// GRANT_ACCESS - The trustee will have at least the requested permissions upon
|
|
// successful completion of the command. (If the trustee has
|
|
// additional permissions they will not be removed).
|
|
// SET_ACCESS - The trustee will have exactly the requested permissions upon
|
|
// successful completion of the command.
|
|
// DENY_ACCESS - The trustee will be denied the specified permissions.
|
|
// REVOKE_ACCESS - Any explicit access rights the trustee has will be revoked.
|
|
// SET_AUDIT_SUCCESS - The trustee will be audited for successful opens of the
|
|
// object using the requested permissions.
|
|
// SET_AUDIT_FAILURE - The trustee will be audited for failed opens of the object
|
|
// using the requested permissions.
|
|
//
|
|
|
|
_ACCESS_MODE = (
|
|
NOT_USED_ACCESS,
|
|
GRANT_ACCESS,
|
|
SET_ACCESS,
|
|
DENY_ACCESS,
|
|
REVOKE_ACCESS,
|
|
SET_AUDIT_SUCCESS,
|
|
SET_AUDIT_FAILURE);
|
|
ACCESS_MODE = _ACCESS_MODE;
|
|
TAccessMode = _ACCESS_MODE;
|
|
|
|
//
|
|
// Definition: Inheritance flags
|
|
// These bit masks are provided to allow simple application of inheritance in
|
|
// explicit access requests on containers.
|
|
// NO_INHERITANCE The specific access permissions will only be applied to
|
|
// the container, and will not be inherited by objects created
|
|
// within the container.
|
|
// SUB_CONTAINERS_ONLY_INHERIT The specific access permissions will be inherited
|
|
// and applied to sub containers created within the
|
|
// container, and will be applied to the container
|
|
// itself.
|
|
// SUB_OBJECTS_ONLY_INHERIT The specific access permissions will only be inherited
|
|
// by objects created within the specific container.
|
|
// The access permissions will not be applied to the
|
|
// container itself.
|
|
// SUB_CONTAINERS_AND_OBJECTS_INHERIT The specific access permissions will be
|
|
// inherited by containers created within the
|
|
// specific container, will be applied to
|
|
// objects created within the container, but
|
|
// will not be applied to the container itself.
|
|
//
|
|
|
|
const
|
|
NO_INHERITANCE = $0;
|
|
SUB_OBJECTS_ONLY_INHERIT = $1;
|
|
SUB_CONTAINERS_ONLY_INHERIT = $2;
|
|
SUB_CONTAINERS_AND_OBJECTS_INHERIT = $3;
|
|
INHERIT_NO_PROPAGATE = $4;
|
|
INHERIT_ONLY = $8;
|
|
|
|
type
|
|
PEXPLICIT_ACCESS_A = ^EXPLICIT_ACCESS_A;
|
|
_EXPLICIT_ACCESS_A = packed record
|
|
grfAccessPermissions: DWORD;
|
|
grfAccessMode: ACCESS_MODE;
|
|
grfInheritance: DWORD;
|
|
Trustee: TRUSTEE_A;
|
|
end;
|
|
EXPLICIT_ACCESS_A = _EXPLICIT_ACCESS_A;
|
|
EXPLICIT_ACCESSA = EXPLICIT_ACCESS_A;
|
|
PEXPLICIT_ACCESSA = PEXPLICIT_ACCESS_A;
|
|
TExplicitAccessA = EXPLICIT_ACCESS_A;
|
|
PExplicitAccessA = PEXPLICIT_ACCESS_A;
|
|
|
|
PEXPLICIT_ACCESS_W = ^EXPLICIT_ACCESS_W;
|
|
_EXPLICIT_ACCESS_W = packed record
|
|
grfAccessPermissions: DWORD;
|
|
grfAccessMode: ACCESS_MODE;
|
|
grfInheritance: DWORD;
|
|
Trustee: TRUSTEE_W;
|
|
end;
|
|
EXPLICIT_ACCESS_W = _EXPLICIT_ACCESS_W;
|
|
EXPLICIT_ACCESSW = EXPLICIT_ACCESS_W;
|
|
PEXPLICIT_ACCESSW = PEXPLICIT_ACCESS_W;
|
|
TExplicitAccessW = EXPLICIT_ACCESS_W;
|
|
PExplicitAccessW = PEXPLICIT_ACCESS_W;
|
|
|
|
{$IFDEF UNICODE}
|
|
EXPLICIT_ACCESS_ = EXPLICIT_ACCESS_W;
|
|
PEXPLICIT_ACCESS_ = PEXPLICIT_ACCESS_W;
|
|
EXPLICIT_ACCESS = EXPLICIT_ACCESSW;
|
|
PEXPLICIT_ACCESS = PEXPLICIT_ACCESSW;
|
|
TExplicitAccess = TExplicitAccessW;
|
|
PExplicitAccess = PExplicitAccessW;
|
|
{$ELSE}
|
|
EXPLICIT_ACCESS_ = EXPLICIT_ACCESS_A;
|
|
PEXPLICIT_ACCESS_ = PEXPLICIT_ACCESS_A;
|
|
EXPLICIT_ACCESS = EXPLICIT_ACCESSA;
|
|
PEXPLICIT_ACCESS = PEXPLICIT_ACCESSA;
|
|
TExplicitAccess = TExplicitAccessA;
|
|
PExplicitAccess = PExplicitAccessA;
|
|
{$ENDIF}
|
|
|
|
TGetNamedSecurityInfoA = function (pObjectName: LPSTR; ObjectType: SE_OBJECT_TYPE;
|
|
SecurityInfo: SECURITY_INFORMATION; ppsidOwner, ppsidGroup: PPSID; ppDacl,
|
|
ppSacl: PPACL; var ppSecurityDescriptor: PSECURITY_DESCRIPTOR): DWORD; stdcall;
|
|
|
|
TGetNamedSecurityInfoW = function (pObjectName: LPWSTR; ObjectType: SE_OBJECT_TYPE;
|
|
SecurityInfo: SECURITY_INFORMATION; ppsidOwner, ppsidGroup: PPSID; ppDacl,
|
|
ppSacl: PPACL; var ppSecurityDescriptor: PSECURITY_DESCRIPTOR): DWORD; stdcall;
|
|
|
|
TGetNamedSecurityInfo = function (pObjectName: LPTSTR; ObjectType: SE_OBJECT_TYPE;
|
|
SecurityInfo: SECURITY_INFORMATION; ppsidOwner, ppsidGroup: PPSID; ppDacl,
|
|
ppSacl: PPACL; var ppSecurityDescriptor: PSECURITY_DESCRIPTOR): DWORD; stdcall;
|
|
|
|
TGetSecurityInfo = function(handle: THANDLE; ObjectType: SE_OBJECT_TYPE;
|
|
SecurityInfo: SECURITY_INFORMATION; ppsidOwner: PPSID; ppsidGroup: PPSID;
|
|
ppDacl, ppSacl: PPACL; var ppSecurityDescriptor: PSECURITY_DESCRIPTOR): DWORD; stdcall;
|
|
|
|
TBuildExplicitAccessWithNameA = procedure (pExplicitAccess: PEXPLICIT_ACCESS_A;
|
|
pTrusteeName: LPSTR; AccessPermissions: DWORD; AccessMode: ACCESS_MODE;
|
|
Inheritance: DWORD); stdcall;
|
|
|
|
TBuildExplicitAccessWithNameW = procedure (pExplicitAccess: PEXPLICIT_ACCESS_W;
|
|
pTrusteeName: LPWSTR; AccessPermissions: DWORD; AccessMode: ACCESS_MODE;
|
|
Inheritance: DWORD); stdcall;
|
|
|
|
TBuildExplicitAccessWithName = procedure (pExplicitAccess: PEXPLICIT_ACCESS;
|
|
pTrusteeName: LPTSTR; AccessPermissions: DWORD; AccessMode: ACCESS_MODE;
|
|
Inheritance: DWORD); stdcall;
|
|
|
|
TSetEntriesInAclA = function (cCountOfExplicitEntries: ULONG;
|
|
pListOfExplicitEntries: PEXPLICIT_ACCESS_A; OldAcl: PACL;
|
|
var NewAcl: PACL): DWORD; stdcall;
|
|
|
|
TSetEntriesInAclW = function (cCountOfExplicitEntries: ULONG;
|
|
pListOfExplicitEntries: PEXPLICIT_ACCESS_W; OldAcl: PACL;
|
|
var NewAcl: PACL): DWORD; stdcall;
|
|
|
|
TSetEntriesInAcl = function (cCountOfExplicitEntries: ULONG;
|
|
pListOfExplicitEntries: PEXPLICIT_ACCESS; OldAcl: PACL;
|
|
var NewAcl: PACL): DWORD; stdcall;
|
|
|
|
TSetNamedSecurityInfoA = function (pObjectName: LPSTR; ObjectType: SE_OBJECT_TYPE;
|
|
SecurityInfo: SECURITY_INFORMATION; psidOwner, psidGroup: PSID;
|
|
pDacl, pSacl: PACL): DWORD; stdcall;
|
|
|
|
TSetNamedSecurityInfoW = function (pObjectName: LPWSTR; ObjectType: SE_OBJECT_TYPE;
|
|
SecurityInfo: SECURITY_INFORMATION; psidOwner, psidGroup: PSID;
|
|
pDacl, pSacl: PACL): DWORD; stdcall;
|
|
|
|
TSetNamedSecurityInfo = function (pObjectName: LPTSTR; ObjectType: SE_OBJECT_TYPE;
|
|
SecurityInfo: SECURITY_INFORMATION; psidOwner, psidGroup: PSID;
|
|
pDacl, pSacl: PACL): DWORD; stdcall;
|
|
|
|
var
|
|
GetNamedSecurityInfoA: TGetNamedSecurityInfoA;
|
|
GetNamedSecurityInfoW: TGetNamedSecurityInfoW;
|
|
GetNamedSecurityInfo: TGetNamedSecurityInfo;
|
|
GetSecurityInfo: TGetSecurityInfo;
|
|
BuildExplicitAccessWithNameA: TBuildExplicitAccessWithNameA = nil;
|
|
BuildExplicitAccessWithNameW: TBuildExplicitAccessWithNameW = nil;
|
|
BuildExplicitAccessWithName: TBuildExplicitAccessWithName = nil;
|
|
SetEntriesInAclA: TSetEntriesInAclA = nil;
|
|
SetEntriesInAclW: TSetEntriesInAclW = nil;
|
|
SetEntriesInAcl: TSetEntriesInAcl = nil;
|
|
SetNamedSecurityInfoW: TSetNamedSecurityInfoW;
|
|
SetNamedSecurityInfoA: TSetNamedSecurityInfoA;
|
|
SetNamedSecurityInfo: TSetNamedSecurityInfo = nil;
|
|
|
|
implementation
|
|
|
|
const
|
|
AclAPI_DLL = 'advapi32.dll';
|
|
|
|
var
|
|
AclAPIHandle: THandle;
|
|
UnloadAclAPI: Boolean;
|
|
|
|
function InitAclAPI: Boolean;
|
|
begin
|
|
AclAPIHandle:=GetModuleHandle(AclAPI_DLL);
|
|
UnloadAclAPI:=AclAPIHandle=0;
|
|
if AclAPIHandle=0 then
|
|
AclAPIHandle:=loadlibrary(AclAPI_DLL);
|
|
if AclAPIHandle<>0 then begin
|
|
@GetNamedSecurityInfoA:=GetProcAddress(AclAPIHandle,PChar('GetNamedSecurityInfoA'));
|
|
@GetNamedSecurityInfoW:=GetProcAddress(AclAPIHandle,PChar('GetNamedSecurityInfoW'));
|
|
GetNamedSecurityInfo:={$IFDEF UNICODE}GetNamedSecurityInfoW{$ELSE}GetNamedSecurityInfoA{$ENDIF};
|
|
@GetSecurityInfo:=GetProcAddress(AclAPIHandle,PChar('GetSecurityInfo'));
|
|
@BuildExplicitAccessWithNameA:=GetProcAddress(AclAPIHandle,PChar('BuildExplicitAccessWithNameA'));
|
|
@BuildExplicitAccessWithNameW:=GetProcAddress(AclAPIHandle,PChar('BuildExplicitAccessWithNameW'));
|
|
BuildExplicitAccessWithName:={$IFDEF UNICODE}BuildExplicitAccessWithNameW{$ELSE}BuildExplicitAccessWithNameA{$ENDIF};
|
|
@SetEntriesInAclA:=GetProcAddress(AclAPIHandle,PChar('SetEntriesInAclA'));
|
|
@SetEntriesInAclW:=GetProcAddress(AclAPIHandle,PChar('SetEntriesInAclW'));
|
|
SetEntriesInAcl:={$IFDEF UNICODE}SetEntriesInAclW{$ELSE}SetEntriesInAclA{$ENDIF};
|
|
@SetNamedSecurityInfoA:=GetProcAddress(AclAPIHandle,PChar('SetNamedSecurityInfoA'));
|
|
@SetNamedSecurityInfoW:=GetProcAddress(AclAPIHandle,PChar('SetNamedSecurityInfoW'));
|
|
SetNamedSecurityInfo:={$IFDEF UNICODE}SetNamedSecurityInfoW{$ELSE}SetNamedSecurityInfoA{$ENDIF};
|
|
end;
|
|
result:=(AclAPIHandle<>0) and Assigned(GetNamedSecurityInfo);
|
|
end;
|
|
|
|
procedure FreeAclAPI;
|
|
begin
|
|
if (AclAPIHandle<>0) and UnloadAclAPI then begin
|
|
if not FreeLibrary(AclAPIHandle) then
|
|
raise Exception.Create(Format('Unload Error: %s - 0x%x',[AclAPI_DLL,GetModuleHandle(AclAPI_DLL)]))
|
|
else
|
|
AclAPIHandle:=0;
|
|
end;
|
|
end;
|
|
|
|
initialization
|
|
InitACLAPI;
|
|
end.
|
|
|
|
|