Retrieving Security Descriptors from Directory Objects
| Nik Okuntseff |
MS Exchange Server Programming |
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 (Security/Retrieve) uses DAPIRead function
to read this information. Let's take a look at the code:
#include <afxwin.h>
#include <dapi.h>
#include <edk.h>
int GetDirObjectSD(char * pszServer, char * pszDN, void ** ppSD)
{
/*
* Algorithm:
* 1. Do DAPIStart.
* 2. Do DAPIRead to request security
descriptor.
* 3. Do DAPIEnd.
*/
DAPI_PARMS parms = {0};
parms.dwDAPISignature = DAPI_SIGNATURE;
parms.pszDSAName = pszServer;
PDAPI_EVENT pDAPIEvent = NULL;
DAPI_HANDLE hDAPISession = NULL;
// Initialize DAPI
pDAPIEvent = ::DAPIStart(&hDAPISession, &parms);
if (pDAPIEvent)
{
DAPIFreeMemory(pDAPIEvent);
return -1;
}
// We have DAPI session. Use it now for read.
DAPI_ENTRY * pdeValues = NULL;
DAPI_ENTRY * pdeAttributes = NULL;
ATT_VALUE avAttrName[3];
avAttrName[0].DapiType = DAPI_STRING8;
avAttrName[0].Value.pszA = "Obj-Class";
avAttrName[0].size = 9;
avAttrName[0].pNextValue = NULL;
avAttrName[1].DapiType = DAPI_STRING8;
avAttrName[1].Value.pszA = "NT-Security-Descriptor";
avAttrName[1].size = 22;
avAttrName[1].pNextValue = NULL;
// This terminates our attribute name array
ZeroMemory( &avAttrName[2], sizeof(ATT_VALUE)
);
DAPI_ENTRY deAttributes;
deAttributes.unAttributes = 2;
deAttributes.ulEvalTag = TEXT_VALUE_ARRAY;
deAttributes.rgEntryValues = &avAttrName[0];
// Now read the security descriptor
pDAPIEvent = DAPIRead(hDAPISession,
0,
pszDN,
&deAttributes,
&pdeValues,
&pdeAttributes);
if (pDAPIEvent)
{
DAPIFreeMemory(pDAPIEvent);
return -1;
}
// Allocate new security descriptor
int iSizeNeeded = pdeValues->rgEntryValues[1].size;
*ppSD = malloc(iSizeNeeded);
// Copy data into it
memcpy(*ppSD, pdeValues->rgEntryValues[1].Value.lpBinary,
iSizeNeeded);
// Deallocate memory
if (pdeValues)
DAPIFreeMemory(pdeValues);
if (pdeAttributes)
DAPIFreeMemory(pdeAttributes);
// Terminate DAPI session
DAPIEnd(&hDAPISession);
return 0;
}
int main( void )
{
char * pszServer = "MIG"; // Change
this
// Get the organization name.
LPSTR pszOrganizations;
HRESULT hr = HrEnumOrganizations("", pszServer,
&pszOrganizations);
if (FAILED(hr)) throw -1;
// Get the first available site.
LPSTR pszSites;
hr = HrEnumSites(pszServer, pszOrganizations, &pszSites);
if (FAILED(hr)) throw -1;
char * pszSite = pszSites;
// Note. In case of multiple sites one string is
allocated.
// A single zero separates individual entries, a
double zero
// terminates the list.
char pszDN[MAX_PATH];
ZeroMemory(pszDN, MAX_PATH);
memcpy(pszDN, pszSite, strlen(pszSite));
// Let's do it for the Recipients container
// Append "/cn=Recipients" to get DN
memcpy(pszDN + strlen(pszSite), "/cn=Recipients",
15);
void * pSD = NULL;
int i = GetDirObjectSD(pszServer, pszDN, &pSD);
assert(S_OK == i);
// We have the security descriptor here.
// Dump DACL masks
int DaclOffset = (int)((PISECURITY_DESCRIPTOR) pSD)->Dacl;
PACL dacl = (PACL)((BYTE *) pSD + DaclOffset);
WORD wAceCount = dacl->AceCount;
void * pAce = NULL;
for (WORD w = 0; w < wAceCount; w++)
{
BOOL b = GetAce(dacl, w,
&pAce);
assert(b);
DWORD dwMask = ((ACCESS_ALLOWED_ACE
*) pAce)->Mask;
printf("\nMask %d: 0x%08X",
w, dwMask);
}
if (pSD)
free(pSD);
return 0;
}
The function named GetDirObjectSD gets security descriptor for us. It
does this by utilizing Directory API (DAPI) functions. We need to provide
the object Distinguished Name (DN) and deallocate security descriptor after
use.
The main function illustrates a few other things. First, it obtains
the Exchange organization name via the HrEnumOrganizations call, then it
gets the name for the first available Exchange site in it. If you have
just one site - this is all you need to get DN for the site. In case of
multiple sites you may need to scan through the list. Notice the comment
in the code about the format of the string. Then I append something to
the site DN to get the distinguished name for the Recipients container
in the site. You may wish to navigate further below to individual mailboxes.
In this case you need to append "/cn=MailboxAlias" to the string. Then
I call the GetDirObjectSD and dump access masks from the resulting security
descriptor.
[ Contents |
Home
]
Send comments and suggestions to niko@wrconsulting.com
Copyright © 1997-1998 by Nik Okuntseff
|