#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <lmcons.h>
#include <winnt.h>
#include <dapi.h>
#include <dapimsg.h> // error codes
//Defining the rights.
#define RIGHT_DS_ADD_CHILD 0x00000001L
#define RIGHT_DS_MODIFY_USER_ATT 0x00000002L
#define RIGHT_DS_MODIFY_ADMIN_ATT 0x00000004L
#define RIGHT_DS_DELETE DELETE
#define RIGHT_MAIL_SEND_AS 0x00000008L
#define RIGHT_MAIL_RECEIVE_AS 0x00000010L
#define RIGHT_MAIL_ADMIN_AS 0x00000020L
#define RIGHT_DS_REPLICATION 0x00000040L
#define RIGHT_DS_MODIFY_SEC_ATT 0x00000080L
#define GENERIC_READ_MAPPING 0x00000000L
// Generic execute.
#define GENERIC_EXECUTE_MAPPING
((RIGHT_MAIL_SEND_AS)|(RIGHT_MAIL_RECEIVE_AS))
// Generic right.
#define GENERIC_WRITE_MAPPING
((RIGHT_DS_ADD_CHILD)|(RIGHT_DS_MODIFY_USER_ATT)|
(RIGHT_DS_MODIFY_ADMIN_ATT)|(RIGHT_DS_DELETE))
// Generic all.
#define GENERIC_ALL_MAPPING
((GENERIC_READ_MAPPING)|(GENERIC_EXECUTE_MAPPING)|
(RIGHT_DS_MODIFY_SEC_ATT)|(GENERIC_WRITE_MAPPING))
// Standard DS generic access rights mapping.//
#define DS_GENERIC_MAPPING
{GENERIC_READ_MAPPING,GENERIC_WRITE_MAPPING,
GENERIC_EXECUTE_MAPPING,GENERIC_ALL_MAPPING}
#define NORMAL_USER_RIGHTS
((RIGHT_DS_MODIFY_USER_ATT)|(GENERIC_EXECUTE_MAPPING))
#define NORMAL_ADMIN_RIGHTS (GENERIC_WRITE_MAPPING)
#define NORMAL_SEC_ADMIN_RIGHTS
(NORMAL_ADMIN_RIGHTS | RIGHT_DS_MODIFY_SEC_ATT)
DWORD MakeSDAbsolute (
PSECURITY_DESCRIPTOR OldSD,
PSECURITY_DESCRIPTOR *NewSD );
BOOL CreateMySecurityDescriptor(
PSECURITY_DESCRIPTOR pSecurityDescriptor,
char *Owner );
void ReadMBAttr(
DAPI_HANDLE hDAPISession, char * szHomeServer,
char * szCN, char * szCN2 );
void ReportDAPIEvent(
DAPI_EVENT* pDAPIEvent );
char *MyUser;
FILE *ef;
void main(int argc, char* argv[])
{
DAPI_HANDLE hDAPISession;
DAPI_EVENT* pDAPIEvent = NULL;
DAPI_PARMS DAPIParms = {0};
// Command line syntax:
// DAPIRead ExchangeServerName Organization Site DomainName\UserName
if (4 > argc) {
printf("\nDAPIRead ExchangeServerName Organization Site"
printf(" Domain_User");
printf("\n\nExample:");
printf("\nDAPIRead MyServer /O=org SiteName Administrator ");
return;
}
// Create a log file.
ef = fopen("DAPIREAD.LOG", "a+");
printf("\nExchange Server: %s", argv[1]);
fprintf(ef,"\nExchange Server: %s",argv[1]);
printf("\nBasePoint Container DN: %s", argv[2]);
fprintf(ef,"\nBasePoint Container DN: %s", argv[2]);
printf("\nUser: %s", argv[4]);
fprintf(ef,"\nUser: %s", argv[4]);
// Start DAPI for this session.
// Initialize the DAPI Parms structure and the
// DAPI operation session.
DAPIParms.dwDAPISignature = DAPI_SIGNATURE;
DAPIParms.dwFlags = DAPI_EVENT_ALL |
DAPI_MODIFY_REPLACE_PROPERTIES | DAPI_RAW_MODE ;
DAPIParms.pszDSAName = argv[1];
DAPIParms.pszBasePoint = argv[2];
DAPIParms.pszContainer = NULL;
DAPIParms.pszNTDomain = NULL;
DAPIParms.pszCreateTemplate = NULL;
DAPIParms.pAttributes = NULL;
MyUser= argv[4];
pDAPIEvent = DAPIStart(&hDAPISession, &DAPIParms);
if(pDAPIEvent)
{
printf("\nDAPIStart() returned %08x - check app eventlog",
pDAPIEvent->dwDAPIError);
fprintf(ef,"\nDAPIStart() returned %08x - check app eventlog",
pDAPIEvent->dwDAPIError);
ReportDAPIEvent(pDAPIEvent);
// Note: dwDAPIError < 0 does NOT necessarily mean
// DAPIStart failed.
if (0==hDAPISession || INVALID_HANDLE_VALUE == hDAPISession)
return;
}
else
{
printf("\nDAPIStart() was successful");
fprintf(ef,"\nDAPIStart() was successful");
}
ReadMBAttr(hDAPISession, argv[1],argv[2], argv[3]);
DAPIEnd(&hDAPISession);
printf("\nEND PROGRAM");
fprintf(ef,"\nEND PROGRAM\n");
fclose(ef);
}
void ReadMBAttr(DAPI_HANDLE hDAPISession, char * szHomeServer,
char * szCN, char * szCN2)
{
DAPI_EVENT* pDAPIEvent = NULL;
DAPI_ENTRY Attributes;
DAPI_ENTRY Values;
ATT_VALUE AttName[5];
ATT_VALUE AttValue[5];
PDAPI_ENTRY ppValues = NULL;
PDAPI_ENTRY ppAttribs = NULL;
BOOL bToken = TRUE;
SECURITY_DESCRIPTOR *pRelativeSD = NULL;
SECURITY_DESCRIPTOR *pAbsoluteSecurityDescriptor = NULL;
DWORD dwAbs;
ULONG ulAbsSecLength = 0;
BOOL present;
BOOL systemDefault;
PACL dacl;
printf("\nIN ReadMBAttr()");
fprintf(ef,"\nIN ReadMBAttr()");
// Add Permissions to the Organization.
AttName[0].DapiType = DAPI_STRING8;
AttName[0].Value.pszValue = "Obj-Class";
AttName[0].size = strlen(AttName[0].Value.pszValue);
AttName[0].pNextValue = NULL;
AttName[1].DapiType = DAPI_STRING8;
AttName[1].Value.pszValue = "NT-Security-Descriptor";
AttName[1].size = strlen(AttName[1].Value.pszValue);
AttName[1].pNextValue = NULL;
AttName[2].DapiType = DAPI_STRING8;
AttName[2].Value.pszValue = "Organization-Name";
AttName[2].size = strlen(AttName[2].Value.pszValue);
AttName[2].pNextValue = NULL;
Attributes.unAttributes = 3; //# of attributes
Attributes.ulEvalTag = TEXT_VALUE_ARRAY; // Value Type.
Attributes.rgEntryValues = (ATT_VALUE*)&AttName;
AttValue[0].DapiType = DAPI_STRING8;
AttValue[0].Value.pszValue = "Organization";
AttValue[0].size = strlen(AttValue[0].Value.pszValue);
AttValue[0].pNextValue = NULL;
AttValue[1].DapiType = DAPI_STRING8;
AttValue[1].Value.pszValue = "Exch_admin";
AttValue[1].size = strlen(AttValue[1].Value.pszValue);
AttValue[1].pNextValue = NULL;
AttValue[2].DapiType = DAPI_STRING8;
AttValue[2].Value.pszValue = szCN;
AttValue[2].size = strlen(AttValue[2].Value.pszValue);
AttValue[2].pNextValue = NULL;
Values.unAttributes = 3; //# of attributes
Values.ulEvalTag = TEXT_VALUE_ARRAY; // Value Type.
Values.rgEntryValues = (ATT_VALUE*)&AttValue;
pDAPIEvent = DAPIRead(hDAPISession,
0, //DAPI_READ_DEFINED_ATTRIBUTES,
szCN, &Attributes, &ppAttribs, &ppValues);
if(pDAPIEvent) {
// Read FAILED
printf("\nDAPIRead ERROR %08x check app eventlog",
pDAPIEvent->dwDAPIError);
fprintf(ef,"\nDAPIRead ERROR %08x check app eventlog",
pDAPIEvent->dwDAPIError);
ReportDAPIEvent(pDAPIEvent);
} else printf("\nDAPIRead() was successful");
pRelativeSD = (SECURITY_DESCRIPTOR *)malloc(2048);
pAbsoluteSecurityDescriptor = (SECURITY_DESCRIPTOR *)malloc(2048);
pRelativeSD = (SECURITY_DESCRIPTOR *)
(*(ppAttribs)).rgEntryValues[1].Value.lpBinary;
// Change the security descriptor to Absolute.
dwAbs = MakeSDAbsolute(
(PSECURITY_DESCRIPTOR)pRelativeSD,
(PSECURITY_DESCRIPTOR *) &pAbsoluteSecurityDescriptor);
// AddNameToSD()
// **TO DO: Change the domain\user to the user you want as the admin.
if (CreateMySecurityDescriptor(pAbsoluteSecurityDescriptor,MyUser))
{
printf("\nCreateMySecurityDescriptor was successful");
fprintf(ef,"\nCreateMySecurityDescriptor was successful");
}
else
{
printf("\nCreateMySecurityDescriptor Failed for Organization");
fprintf(ef,"\nCreateMySecurityDescriptor Failed for Organization");
}
// Change the security descriptor to SelfRelative.
ulAbsSecLength = GetSecurityDescriptorLength(
pAbsoluteSecurityDescriptor);
pRelativeSD = (SECURITY_DESCRIPTOR *) malloc(ulAbsSecLength);
if (MakeSelfRelativeSD(pAbsoluteSecurityDescriptor,
pRelativeSD,&ulAbsSecLength))
{
printf("\nMakeSelfRelativeSD was successful");
fprintf(ef,"\nMakeSelfRelativeSD was successful");
}
else
{
printf("\nMakeSelfRelativeSD Failed for Organization");
fprintf(ef,"\nMakeSelfRelativeSD Failed for Organization");
}
if (IsValidSecurityDescriptor(pRelativeSD))
{
printf("\nValid SD");
fprintf(ef,"\nValid SD");
}
else
{
printf("\nInvalid SD for Organization");
fprintf(ef,"\nInvalid SD for Organization");
}
GetSecurityDescriptorDacl(pRelativeSD,&present,
&dacl, &systemDefault);
if (IsValidAcl(dacl))
printf("\nValid ACL");
fprintf(ef,"\nValid ACL");
AttValue[1].DapiType = DAPI_BINARY;
AttValue[1].Value.lpBinary = (unsigned char *)pRelativeSD;
AttValue[1].size = GetSecurityDescriptorLength(pRelativeSD);
AttValue[1].pNextValue = NULL;
// Write Security Descriptor Back to Exchange.
pDAPIEvent = DAPIWrite(hDAPISession, DAPI_WRITE_UPDATE,
&Attributes, & Values, NULL, NULL, NULL);
if(pDAPIEvent)
{
// create FAILED.
printf("\nDAPIWrite ERROR %08x check app eventlog",
pDAPIEvent->dwDAPIError);
fprintf(ef,"\nDAPIWrite ERROR %08x check app eventlog", \
pDAPIEvent->dwDAPIError);
ReportDAPIEvent(pDAPIEvent);
// DAPIFreeMemory(pDAPIEvent);
}
else
printf("\nDAPIWrite() for Organization was successful");
fprintf(ef,"\nDAPIWrite() for Organization was successful");
}
void ReportDAPIEvent(DAPI_EVENT* pDAPIEvent)
{
HANDLE hDAPIEventSource = RegisterEventSource(NULL,
TEXT("MSExchangeDSImp"));
ReportEvent( hDAPIEventSource, (WORD)EVENTLOG_ERROR_TYPE,
0xFFFF, pDAPIEvent->dwDAPIError, NULL,
(WORD)pDAPIEvent->unSubst, 0,
(const char**) pDAPIEvent->rgpszSubst, NULL);
DAPIFreeMemory(pDAPIEvent);
DeregisterEventSource(hDAPIEventSource);
}
BOOL CreateMySecurityDescriptor(
PSECURITY_DESCRIPTOR pSecurityDescriptor,
char *Owner )
{
GENERIC_MAPPING GenericMapping = DS_GENERIC_MAPPING;
PSID pOwnerSid;
PACL pAcl;
BOOL Ret=FALSE;
BOOL present;
BOOL systemDefault;
DWORD cbNewAcl;
ACCESS_ALLOWED_ACE * pAce;
ACCESS_MASK AccessMask = NORMAL_ADMIN_RIGHTS |
RIGHT_MAIL_ADMIN_AS | RIGHT_DS_MODIFY_SEC_ATT;
DWORD dwAce;
PACL pNewAcl;
//
// Initialize the Security Descriptor struct.
//
{
//
// Get the SID for the account/Group.
//
DWORD lSD = GetSecurityDescriptorLength(pSecurityDescriptor);
DWORD len1=1024,len2=1024;
char RefDomain[1024];
SID_NAME_USE snu=SidTypeUser; //don't care
if ((pOwnerSid=(PSID)calloc(len1,1))==NULL)
return FALSE;
Ret = LookupAccountName( NULL, Owner, pOwnerSid, &len1,
RefDomain, &len2, &snu );
if (!Ret)
{
free(pOwnerSid);
return FALSE;
}
}
{
//
// Create the access control list with access for
// the preceding SID.
//
MapGenericMask(&AccessMask, &GenericMapping);
if (!GetSecurityDescriptorDacl(
(SECURITY_DESCRIPTOR *)pSecurityDescriptor,
&present, &pAcl, &systemDefault))
return GetLastError();
ACL_SIZE_INFORMATION asiAcl;
if (GetAclInformation(pAcl,&asiAcl,
sizeof(asiAcl),AclSizeInformation))
{
printf("\nAcl Information Succeeded");
fprintf(ef,"\nAcl Information Succeeded");
}
else
return FALSE;
cbNewAcl = asiAcl.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE) +
GetLengthSid (pOwnerSid);
pNewAcl = (PACL) malloc(cbNewAcl);
if (!InitializeAcl (pNewAcl, cbNewAcl, ACL_REVISION2))
{
printf("\nInitializeAcl failed");
fprintf(ef,"\nInitializeAcl failed");
return FALSE;
}
else
printf("\nInitializeAcl succeeded");
fprintf(ef,"\nInitializeAcl succeeded");
// pAcl = pNewAcl;
// Move each ACE from the present ACL into the new one.
for (dwAce = 0 ; dwAce < asiAcl.AceCount ; dwAce++)
{
// Get the ACE out of the ACL
if (!GetAce (pAcl, dwAce, (void **)&pAce))
{
printf("\nGetAce failed");
fprintf(ef,"\nGetAce failed");
}
// Place the ACE into the new ACL.
if (!AddAce (pNewAcl, ACL_REVISION2, dwAce, pAce,
((ACE_HEADER *) pAce)->AceSize))
{
printf("\nAddAce failed");
fprintf(ef,"\nAddAce failed");
}
}
Ret = AddAccessAllowedAce( pNewAcl, ACL_REVISION,
AccessMask, pOwnerSid );
if (!Ret)
{
long err = GetLastError();
free(pOwnerSid);
free(pAcl);
return FALSE;
}
}
if (IsValidAcl(pNewAcl))
printf("\nValid ACL");
fprintf(ef,"\nValid ACL");
//
// Add the created ACL to the discreationary control list.
//
Ret = SetSecurityDescriptorDacl(pSecurityDescriptor,
TRUE,pNewAcl,FALSE);
if (!Ret)
{
free(pOwnerSid);
free(pAcl);
return FALSE;
}
if (IsValidSecurityDescriptor(pSecurityDescriptor))
printf("\nValid SD");
fprintf(ef,"\nValid SD");
DWORD lSD = GetSecurityDescriptorLength(pSecurityDescriptor);
return TRUE;
}
DWORD MakeSDAbsolute (
PSECURITY_DESCRIPTOR OldSD,
PSECURITY_DESCRIPTOR *NewSD )
{
PSECURITY_DESCRIPTOR sd = NULL;
DWORD descriptorSize;
DWORD daclSize;
DWORD saclSize;
DWORD ownerSIDSize;
DWORD groupSIDSize;
PACL dacl;
PACL sacl;
PSID ownerSID;
PSID groupSID;
BOOL present;
BOOL systemDefault;
ULONG pAce = NULL;
BOOL bToken = FALSE;
//
// Get SACL
//
if (!GetSecurityDescriptorSacl (OldSD, &present, &sacl,
&systemDefault))
return GetLastError();
if (sacl && present)
{
saclSize = sacl->AclSize;
} else saclSize = 0;
//
// Get DACL
//
if (!GetSecurityDescriptorDacl (OldSD, &present, &dacl,
&systemDefault))
return GetLastError();
if (dacl && present)
{
daclSize = dacl->AclSize;
} else daclSize = 0;
//
// Get Owner.
//
if (!GetSecurityDescriptorOwner (OldSD, &ownerSID, &systemDefault))
return GetLastError();
ownerSIDSize = GetLengthSid (ownerSID);
//
// Get Group.
//
if (!GetSecurityDescriptorGroup (OldSD, &groupSID, &systemDefault))
return GetLastError();
groupSIDSize = GetLengthSid (groupSID);
//
// Do the conversion.
//
descriptorSize = 0;
bToken = MakeAbsoluteSD (OldSD, sd, &descriptorSize, dacl,
&daclSize, sacl, &saclSize, ownerSID,
&ownerSIDSize, groupSID, &groupSIDSize);
sd = (PSECURITY_DESCRIPTOR)
new BYTE [SECURITY_DESCRIPTOR_MIN_LENGTH];
if (!InitializeSecurityDescriptor (sd,
SECURITY_DESCRIPTOR_REVISION))
return GetLastError();
if (!MakeAbsoluteSD (OldSD, sd, &descriptorSize, dacl, &daclSize,
sacl, &saclSize, ownerSID, &ownerSIDSize,
groupSID, &groupSIDSize))
return GetLastError();
*NewSD = sd;
return ERROR_SUCCESS;