S
Stephen Engle
I am trying to allow for user account to take ownership of an Active
Directory object. I have assigned the Modify Owner permission to the user
on the AD object - a distribution list in this case. Using Active Directory
Users and Computers, the user can take ownership of the object. But I have
not been able to get the program I am working on to do so. Whenever I try
to write the Security Descriptor back to the object, I get the
E_ACCESSDENIED error. The program code works fine if ran as a domain
administrator. So I am thinking that I do not have a privilege activated
that I need. But I have tried using AdjustTokenPrivilege to grant the
SE_RESTORE_NAME and SE_TAKE_OWNERSHIP_NAME privileges. That does not seem
to have any effect.
Does anyone have an idea about what I am missing?
Thanks.
The test code is as follows:
void CADOwnDlg::OnBnClickedTakeownership()
{
ACL * abdacl;
DWORD abdacllen;
SID * abowner;
DWORD abownerlen;
SID * abpg;
DWORD abpglen;
ACL * absacl;
DWORD absacllen;
SECURITY_DESCRIPTOR * absd;
DWORD absdlen;
IDirectoryObject * adobject;
ADSVALUE adsvalue;
ADS_ATTR_INFO attrinfo;
LPWSTR attrstr;
DWORD buflen;
HRESULT hr;
LUID luid;
DWORD numobjattr;
ADS_ATTR_INFO * objattr;
WCHAR objectpath[256];
HANDLE prochandle;
SECURITY_DESCRIPTOR * sd;
SECURITY_DESCRIPTOR * sdsr;
unsigned char sid[256];
SID * sidnewowner;
HANDLE tokenhandle;
TOKEN_PRIVILEGES tp;
abdacl=NULL;
abdacllen=0;
abowner=NULL;
abownerlen=0;
abpg=NULL;
abpglen=0;
absacl=NULL;
absacllen=0;
absd=NULL;
absdlen=0;
adobject=NULL;
attrstr=L"nTSecurityDescriptor";
buflen=0;
DWORD numattr;
objattr=NULL;
sdsr=NULL;
memset(sid, 0, sizeof(sid));
memcpy(sid, SidVal, SidValSize);
sidnewowner=(SID *)sid;
wcscpy(objectpath, L"LDAP://CN=Test.One,OU=Client Distribution
Lists,OU=Public Distribution Lists,DC=aoins,DC=com");
hr=CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
hr=ADsOpenObject(objectpath, NULL, NULL, ADS_SECURE_AUTHENTICATION,
IID_IDirectoryObject, (void **)&adobject);
hr=adobject->GetObjectAttributes(&attrstr, 1, &objattr, &numobjattr);
sd=(SECURITY_DESCRIPTOR *)objattr->pADsValues->SecurityDescriptor.lpValue;
MakeAbsoluteSD(sd, absd, &absdlen, abdacl, &abdacllen, absacl, &absacllen,
abowner, &abownerlen, abpg, &abpglen);
absd=(SECURITY_DESCRIPTOR *)malloc(absdlen);
abdacl=(ACL *)malloc(abdacllen);
absacl=(ACL *)malloc(absacllen);
abowner=(SID *)malloc(abownerlen);
abpg=(SID *)malloc(abpglen);
MakeAbsoluteSD(sd, absd, &absdlen, abdacl, &abdacllen, absacl,
&absacllen, abowner, &abownerlen, abpg, &abpglen);
SetSecurityDescriptorOwner(absd, sidnewowner, FALSE);
MakeSelfRelativeSD(absd, sdsr, &buflen);
sdsr=(SECURITY_DESCRIPTOR *)malloc(buflen);
MakeSelfRelativeSD(absd, sdsr, &buflen);
prochandle=GetCurrentProcess();
OpenProcessToken(prochandle, TOKEN_ADJUST_PRIVILEGES, &tokenhandle);
LookupPrivilegeValue("DCH1", SE_RESTORE_NAME, &luid);
tp.PrivilegeCount=1;
tp.Privileges[0].Luid=luid;
tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(tokenhandle, FALSE, &tp, 0, NULL, NULL);
LookupPrivilegeValue("DCH1", SE_TAKE_OWNERSHIP_NAME, &luid);
tp.PrivilegeCount=1;
tp.Privileges[0].Luid=luid;
tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(tokenhandle, FALSE, &tp, 0, NULL, NULL);
attrinfo.dwADsType=objattr->dwADsType;
attrinfo.dwControlCode=ADS_ATTR_UPDATE;
attrinfo.dwNumValues=1;
attrinfo.pADsValues=&adsvalue;
adsvalue.dwType=objattr->dwADsType;
adsvalue.SecurityDescriptor.lpValue=(LPBYTE)sdsr;
adsvalue.SecurityDescriptor.dwLength=buflen;
attrinfo.pszAttrName=attrstr;
hr=adobject->SetObjectAttributes(&attrinfo, 1, &numattr);
FreeADsMem(objattr);
adobject->Release();
if(abdacl!=NULL) free(abdacl);
if(abowner!=NULL) free(abowner);
if(abpg!=NULL) free(abpg);
if(absacl!=NULL) free(absacl);
if(absd!=NULL) free(absd);
if(sdsr!=NULL) free(sdsr);
CoUninitialize();
}
Directory object. I have assigned the Modify Owner permission to the user
on the AD object - a distribution list in this case. Using Active Directory
Users and Computers, the user can take ownership of the object. But I have
not been able to get the program I am working on to do so. Whenever I try
to write the Security Descriptor back to the object, I get the
E_ACCESSDENIED error. The program code works fine if ran as a domain
administrator. So I am thinking that I do not have a privilege activated
that I need. But I have tried using AdjustTokenPrivilege to grant the
SE_RESTORE_NAME and SE_TAKE_OWNERSHIP_NAME privileges. That does not seem
to have any effect.
Does anyone have an idea about what I am missing?
Thanks.
The test code is as follows:
void CADOwnDlg::OnBnClickedTakeownership()
{
ACL * abdacl;
DWORD abdacllen;
SID * abowner;
DWORD abownerlen;
SID * abpg;
DWORD abpglen;
ACL * absacl;
DWORD absacllen;
SECURITY_DESCRIPTOR * absd;
DWORD absdlen;
IDirectoryObject * adobject;
ADSVALUE adsvalue;
ADS_ATTR_INFO attrinfo;
LPWSTR attrstr;
DWORD buflen;
HRESULT hr;
LUID luid;
DWORD numobjattr;
ADS_ATTR_INFO * objattr;
WCHAR objectpath[256];
HANDLE prochandle;
SECURITY_DESCRIPTOR * sd;
SECURITY_DESCRIPTOR * sdsr;
unsigned char sid[256];
SID * sidnewowner;
HANDLE tokenhandle;
TOKEN_PRIVILEGES tp;
abdacl=NULL;
abdacllen=0;
abowner=NULL;
abownerlen=0;
abpg=NULL;
abpglen=0;
absacl=NULL;
absacllen=0;
absd=NULL;
absdlen=0;
adobject=NULL;
attrstr=L"nTSecurityDescriptor";
buflen=0;
DWORD numattr;
objattr=NULL;
sdsr=NULL;
memset(sid, 0, sizeof(sid));
memcpy(sid, SidVal, SidValSize);
sidnewowner=(SID *)sid;
wcscpy(objectpath, L"LDAP://CN=Test.One,OU=Client Distribution
Lists,OU=Public Distribution Lists,DC=aoins,DC=com");
hr=CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
hr=ADsOpenObject(objectpath, NULL, NULL, ADS_SECURE_AUTHENTICATION,
IID_IDirectoryObject, (void **)&adobject);
hr=adobject->GetObjectAttributes(&attrstr, 1, &objattr, &numobjattr);
sd=(SECURITY_DESCRIPTOR *)objattr->pADsValues->SecurityDescriptor.lpValue;
MakeAbsoluteSD(sd, absd, &absdlen, abdacl, &abdacllen, absacl, &absacllen,
abowner, &abownerlen, abpg, &abpglen);
absd=(SECURITY_DESCRIPTOR *)malloc(absdlen);
abdacl=(ACL *)malloc(abdacllen);
absacl=(ACL *)malloc(absacllen);
abowner=(SID *)malloc(abownerlen);
abpg=(SID *)malloc(abpglen);
MakeAbsoluteSD(sd, absd, &absdlen, abdacl, &abdacllen, absacl,
&absacllen, abowner, &abownerlen, abpg, &abpglen);
SetSecurityDescriptorOwner(absd, sidnewowner, FALSE);
MakeSelfRelativeSD(absd, sdsr, &buflen);
sdsr=(SECURITY_DESCRIPTOR *)malloc(buflen);
MakeSelfRelativeSD(absd, sdsr, &buflen);
prochandle=GetCurrentProcess();
OpenProcessToken(prochandle, TOKEN_ADJUST_PRIVILEGES, &tokenhandle);
LookupPrivilegeValue("DCH1", SE_RESTORE_NAME, &luid);
tp.PrivilegeCount=1;
tp.Privileges[0].Luid=luid;
tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(tokenhandle, FALSE, &tp, 0, NULL, NULL);
LookupPrivilegeValue("DCH1", SE_TAKE_OWNERSHIP_NAME, &luid);
tp.PrivilegeCount=1;
tp.Privileges[0].Luid=luid;
tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(tokenhandle, FALSE, &tp, 0, NULL, NULL);
attrinfo.dwADsType=objattr->dwADsType;
attrinfo.dwControlCode=ADS_ATTR_UPDATE;
attrinfo.dwNumValues=1;
attrinfo.pADsValues=&adsvalue;
adsvalue.dwType=objattr->dwADsType;
adsvalue.SecurityDescriptor.lpValue=(LPBYTE)sdsr;
adsvalue.SecurityDescriptor.dwLength=buflen;
attrinfo.pszAttrName=attrstr;
hr=adobject->SetObjectAttributes(&attrinfo, 1, &numattr);
FreeADsMem(objattr);
adobject->Release();
if(abdacl!=NULL) free(abdacl);
if(abowner!=NULL) free(abowner);
if(abpg!=NULL) free(abpg);
if(absacl!=NULL) free(absacl);
if(absd!=NULL) free(absd);
if(sdsr!=NULL) free(sdsr);
CoUninitialize();
}