Retrieving Security Descriptors from Directory Objects
It is convenient to have code that retrieves Windows NT security
descriptors from Microsoft Exchange directory objects. You can use DAPI or MAPI
to extract them. The sample below (DapiDumpSecApp) uses DAPIRead function to
read this information. Let's take a look at the code:
(*
* Algorithm:
* 1. Do DAPIStart.
* 2. Do DAPIRead to request security descriptor.
* 3. Do DAPIEnd.
*)
procedure TfrmMain.btStartClick(Sender: TObject);
function DumpSecurAttributes(pSD:PSID):TStrings;
var
...
begin
if GetSecurityDescriptorDacl(pSD,pbDaclPresent,pDacl, lpbDaclDefaulted) then
begin
wAceCount := pdacl.AceCount;
pAce := nil;
for W := 0 to wAceCount-1 do
begin
b := GetAce(pdacl^, w, pAce);
dwMask := PACCESS_ALLOWED_ACE(pAce).Mask;
Result.Add('Mask '+IntToStr(W)+': '+#0+IntToHex(dwMask,8))
end;
end;
end;
var
ObjectToRead:Array [0..255] of Char;
TempStr:String;
userprop:TStrings;
iSizeNeeded,
CountAtt,i:Integer;
p:PCHAR;
ppSD:PSID;
begin
ppSD:=nil;
if Assigned(SiteInfo) then SiteInfo.Free;
SiteInfo:=TSiteInfo.Create(Trim(ebESName.Text));
if SiteInfo.GetInfo then
begin
ZeroMemory(@ObjectToRead,256);
TempStr:=Trim(ebMailbox.Text);
if TempStr<>EmptyStr then
TempStr:='/cn=Recipients/cn='+TempStr
else
TempStr:='/cn=Recipients';
TempStr:=SiteInfo.SiteDNString+TempStr;
StrPCopy(@ObjectToRead,TempStr);
// Check for started DAPI Session
if DSession=DAPI_INVALID_HANDLE then
begin
DAPIParms.dwDAPISignature:=DAPI_SIGNATURE;
DAPIParms.dwFlags := DAPI_EVENT_ALL;
DAPIParms.pszDSAName:=PChar(SiteInfo.SrvName);
(*
The DAPIStart function initializes a directory operation session.
*)
pDAPIEvent:=DAPIStart(@DSession,@DAPIParms);
if Assigned(pDAPIEvent) then
begin
RaiseDAPIError(pDAPIEvent);
DAPIFreeMemory(pDAPIEvent);
end
else
begin
if Assigned(pValues) then
begin
DapiFreeMemory(pValues);
pValues:=nil;
end;
if Assigned(pAttributes) then
begin
DapiFreeMemory(pAttributes);
pAttributes:=nil;
end;
CountAtt:=2;
deAttributes:=DAPIAllocBuffer(SizeOf(DAPI_ENTRY), nil);
ZeroMemory(deAttributes, SizeOf(DAPI_ENTRY));
deAttributes.unAttributes := 1;
deAttributes.ulEvalTag := TEXT_LINE;
deAttributes.rgEntryValues:=DAPIAllocBuffer(SizeOf(ATT_VALUE), deAttributes);
ZeroMemory(deAttributes.rgEntryValues, SizeOf(ATT_VALUE));
PATT_VALUE(deAttributes.rgEntryValues).DapiType := DAPI_TEXT;
PATT_VALUE(deAttributes.rgEntryValues).Value.pszValue:='Object-Class,NT-Security-Descriptor';
PATT_VALUE(deAttributes.rgEntryValues).size := strlen(PATT_VALUE(deAttributes.rgEntryValues).Value.pszValue);
pDAPIEvent:=DAPIRead(
DSession,
0,
@ObjectToRead,
deAttributes,
@pValues,
nil);
if Assigned(pDAPIEvent) then
RaiseDAPIError(pDAPIEvent)
else
begin
iSizeNeeded:=PATT_VALUE(ULONG(pValues.rgEntryValues) + ( sizeof(ATT_VALUE))).size;
ppSD:=nil;
ListViewProp.Items.Clear;
If iSizeNeeded>0 then
begin
ppSD:=AllocMem(iSizeNeeded);
CopyMemory(ppSD,
PATT_VALUE(ULONG(pValues.rgEntryValues) + ( sizeof(ATT_VALUE))).Value.lpBinary,
iSizeNeeded);
userprop:=DumpSecurAttributes(ppSD);
if Assigned(ppSD) then
FreeMem(ppSD);
ListViewProp.Items.BeginUpdate;
ListViewProp.Items.Clear;
for i := 0 to userprop.count - 1 do
with ListViewProp.Items.Add do
begin
p := @userprop [i] [1];
Caption := p;
inc(p,StrLen(P)+1);
SubItems.Add(p);
end;
ListViewProp.Items.EndUpdate;
userprop.Free;
end;
// Deallocate memory
if Assigned(avAttrName) then
begin
DapiFreeMemory(avAttrName);
avAttrName:=nil;
end;
if Assigned(deAttributes) then
begin
DapiFreeMemory(deAttributes);
deAttributes:=nil;
end;
if Assigned(pValues) then
begin
DapiFreeMemory(pValues);
pValues:=nil;
end;
if Assigned(pAttributes) then
begin
DapiFreeMemory(pAttributes);
pAttributes:=nil;
end;
end;
end;
end;
end;
if DSession<>DAPI_INVALID_HANDLE then
// Terminate DAPI session
DAPIEnd(@DSession);
end;
Compiled DELPHI 5 example
|