473,387 Members | 1,291 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Taking Ownership

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();
}


Nov 17 '05 #1
7 1805
"Stephen Engle" <en***********@aoins.com> wrote in message
news:eM*************@TK2MSFTNGP15.phx.gbl...
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?


AdjustTokenPrivileges() does not grant privileges. If it did, there would be
no security at all as any thread could grant any old privilege. Rather it
enables privleges.

To review, privilges have three states:

1) not granted
2) granted and not enabled
3) granted and enabled

AdjustTokenPrivileges() can transition from state 2 to 3 or 3 to 2 in my
list above.

Because you say the code works as a domain administrator you will have to
run the code in a more privileged security context.

You have a few options:

1) Run under a proper user context.

2) Use the credentials of a suitably privileged user and LogonUser(),
ImpersonateLoggedOnUser() and RevertToSelf() so that you have the necessary
credentials at the time you need them

3) make some inter-process request of a service installed with the proper
credentials to do your bidding. Of course, then you need a way for the
service to verify that the request comes from a party it trusts.

I'd post again in a more appropriate group. If security was my _thing_ I'd
point you, but it ain't so I can't. :-)

Regards,
Will
Nov 17 '05 #2
The thing I can't figure out here, is why Active Directory Users and
Computers can take ownership, yet my program cannot (obviously something is
missing). I tried using ADSI objects as well but got the same result. Is
ADU&C doing something behind the scenes with the servers to facilitate this,
or is it some API calls that I'm not doing?

"William DePalo [MVP VC++]" <wi***********@mvps.org> wrote in message
news:ul**************@TK2MSFTNGP14.phx.gbl...
"Stephen Engle" <en***********@aoins.com> wrote in message
news:eM*************@TK2MSFTNGP15.phx.gbl...
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?
AdjustTokenPrivileges() does not grant privileges. If it did, there would

be no security at all as any thread could grant any old privilege. Rather it
enables privleges.

To review, privilges have three states:

1) not granted
2) granted and not enabled
3) granted and enabled

AdjustTokenPrivileges() can transition from state 2 to 3 or 3 to 2 in my
list above.

Because you say the code works as a domain administrator you will have to
run the code in a more privileged security context.

You have a few options:

1) Run under a proper user context.

2) Use the credentials of a suitably privileged user and LogonUser(),
ImpersonateLoggedOnUser() and RevertToSelf() so that you have the necessary credentials at the time you need them

3) make some inter-process request of a service installed with the proper
credentials to do your bidding. Of course, then you need a way for the
service to verify that the request comes from a party it trusts.

I'd post again in a more appropriate group. If security was my _thing_ I'd
point you, but it ain't so I can't. :-)

Regards,
Will

Nov 17 '05 #3
"Stephen Engle" <en***********@aoins.com> wrote in message
news:um**************@TK2MSFTNGP09.phx.gbl...
The thing I can't figure out here, is why Active Directory Users and
Computers can take ownership, yet my program cannot (obviously something
is
missing).
It is a good question for which I don't have an answer. I _think_ though
that you could find an answer by looking at that group and its privileges.
Assuming that the code is proper, the issue is a privilege granted to a user
in the group and which is lacking in the user under whose context your
application runs.

Do you have the credentials of one of the users in this group? If so, and if
you run on XP you could try this experiment:

LogonUser(); // use credentials of user in AD Users group
ImpersonateLoggedOnUser();

// do what you need to do

RevertToSelf();

I tried using ADSI objects as well but got the same result. Is
ADU&C doing something behind the scenes with the servers to facilitate
this,
or is it some API calls that I'm not doing?


Sorry, but I am not well versed in AD. You may want to search for a more
appropriate group in which to post your question.

Regards,
Will
Nov 17 '05 #4
Sorry - I should have been more plain about the user. I log on as the user
(a test id) in question to test my app (and also to test that user's rights
using Active Directory Users & Computers). Unfortunately, the only thing I
have been able to determine is that the user id has the appropriate rights
(because ADU&C can make the change) but my app still won't work, unless I'm
logged in as myself. I am a Domain Admin and therefore have so many rights
that I don't know for sure what the difference really is. But since ADU&C
can work for the test id, I would think there must be some way to do this
with my app.

Do you have any ideas as to what group might be more appropriate to post
this question to. I have looked at the huge list of Microsoft groups and
have only found this and potentially the microsoft.public.win2000.security
group that seemed to touch on this.
Thanks again.
"William DePalo [MVP VC++]" <wi***********@mvps.org> wrote in message
news:#Y*************@TK2MSFTNGP09.phx.gbl...
"Stephen Engle" <en***********@aoins.com> wrote in message
news:um**************@TK2MSFTNGP09.phx.gbl...
The thing I can't figure out here, is why Active Directory Users and
Computers can take ownership, yet my program cannot (obviously something
is
missing).
It is a good question for which I don't have an answer. I _think_ though
that you could find an answer by looking at that group and its privileges.
Assuming that the code is proper, the issue is a privilege granted to a

user in the group and which is lacking in the user under whose context your
application runs.

Do you have the credentials of one of the users in this group? If so, and if you run on XP you could try this experiment:

LogonUser(); // use credentials of user in AD Users group
ImpersonateLoggedOnUser();

// do what you need to do

RevertToSelf();

I tried using ADSI objects as well but got the same result. Is
ADU&C doing something behind the scenes with the servers to facilitate
this,
or is it some API calls that I'm not doing?


Sorry, but I am not well versed in AD. You may want to search for a more
appropriate group in which to post your question.

Regards,
Will

Nov 17 '05 #5
"Stephen Engle" <en***********@aoins.com> wrote in message
news:uK**************@tk2msftngp13.phx.gbl...
Sorry - I should have been more plain about the user. I log on as the
user
(a test id) in question to test my app (and also to test that user's
rights
using Active Directory Users & Computers). Unfortunately, the only thing
I
have been able to determine is that the user id has the appropriate rights
(because ADU&C can make the change) but my app still won't work, unless
I'm
logged in as myself. I am a Domain Admin and therefore have so many
rights
that I don't know for sure what the difference really is. But since ADU&C
can work for the test id, I would think there must be some way to do this
with my app. Do you have any ideas as to what group might be more appropriate to post
this question to. I have looked at the huge list of Microsoft groups and
have only found this and potentially the microsoft.public.win2000.security
group that seemed to touch on this.
The two languages groups (this and m.p.vc.language) field lots of questions
on things people do with the language even though the groups' focus is
ostensibly on the language itself.

The kernel group (m.p.win32.programmer.kernel) has a similar mix of skills
among the regulars and more than a few who grok security.

Apart from the kernel group, I'd plug

activedirectory

or

adsi

into the newsgroup search edit box to find a more appropriate one. If I read
any of these groups I'd suggest one, but as I said, I don't so I can't. :-(

At the risk of stating the obvious ... are you checking the return codes
from the functions that you call? It is a really really rare event for a
function in the Win32 API to fail silently. One thing you can do is type

err

in the watch window in the debugger. This pseudo-variable is an alias for
the calling thread's last error code. When a function fails (and only if it
fails so you need to check return codes or look at the EAX register if you
forgot to capture the return) this is the place to look for the underlying
cause of the failure.
Thanks again.


You are welcome.

Regards,
Will
Nov 17 '05 #6
I have indeed been checking my return codes. The only one that fails is the
call to apply the changes back to the AD group (E_ACCESSDENIED). But thanks
for all of your help and suggestions. I will look for another place to post
and check on this.

"William DePalo [MVP VC++]" <wi***********@mvps.org> wrote in message
news:eF**************@TK2MSFTNGP15.phx.gbl...
"Stephen Engle" <en***********@aoins.com> wrote in message
news:uK**************@tk2msftngp13.phx.gbl...
Sorry - I should have been more plain about the user. I log on as the
user
(a test id) in question to test my app (and also to test that user's
rights
using Active Directory Users & Computers). Unfortunately, the only thing I
have been able to determine is that the user id has the appropriate rights (because ADU&C can make the change) but my app still won't work, unless
I'm
logged in as myself. I am a Domain Admin and therefore have so many
rights
that I don't know for sure what the difference really is. But since ADU&C can work for the test id, I would think there must be some way to do this with my app.
Do you have any ideas as to what group might be more appropriate to post
this question to. I have looked at the huge list of Microsoft groups and have only found this and potentially the microsoft.public.win2000.security group that seemed to touch on this.


The two languages groups (this and m.p.vc.language) field lots of

questions on things people do with the language even though the groups' focus is
ostensibly on the language itself.

The kernel group (m.p.win32.programmer.kernel) has a similar mix of skills
among the regulars and more than a few who grok security.

Apart from the kernel group, I'd plug

activedirectory

or

adsi

into the newsgroup search edit box to find a more appropriate one. If I read any of these groups I'd suggest one, but as I said, I don't so I can't. :-(
At the risk of stating the obvious ... are you checking the return codes
from the functions that you call? It is a really really rare event for a
function in the Win32 API to fail silently. One thing you can do is type

err

in the watch window in the debugger. This pseudo-variable is an alias for
the calling thread's last error code. When a function fails (and only if it fails so you need to check return codes or look at the EAX register if you
forgot to capture the return) this is the place to look for the underlying
cause of the failure.
Thanks again.


You are welcome.

Regards,
Will

Nov 17 '05 #7
"Stephen Engle" <en***********@aoins.com> wrote in message
news:e2**************@TK2MSFTNGP10.phx.gbl...
I have indeed been checking my return codes. The only one that fails is
the
call to apply the changes back to the AD group (E_ACCESSDENIED).
Does the function that fails not detail what it requires? Is there any
possibility that it is a wild pointer problem? It it is something in wide
use, someone in the kernel group may spot the problem.
But thanks for all of your help and suggestions.


You are welcome.

Regards.
Will
Nov 17 '05 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Ryan | last post by:
We have a DTS package developed on our development PC's (SQL 7). It runs fine. When we schedule it on the server (SQL 7), it fails. We have been able to find that this is a known issue down to the...
4
by: tarmat | last post by:
I've been using code such as the following, whereby I call the constructor of a class with an object allocated on the heap. The class is responsible for tidying up the memory. class Base{};...
11
by: Jacob | last post by:
I am trying to find the best way of documenting (in code and comments) ownership of secondary contained objects. This is my current status, and I would appreciate feedback on it: Case 1: ...
14
by: Howard | last post by:
Hi, I recently had a problem where I decided to store objects in a vector. (Previously, I had always stored pointers in vectors). Well, naturally, when storing an object in a vector, using...
2
by: Benden Ziyade | last post by:
Hello; I want to write a C program that check file ownership in /bin directory(ls, mkdir...). But I don't know how I start. I'm happy with your helping.
9
by: Andrew | last post by:
Apologies for the double-post.. I'm new, just getting used to this.. and should have posted this way in the first place.. How does one go about taking ownership of a registry key using C# & .NET...
1
by: ShaiH | last post by:
When I create a file from a simple command line application written in C# the file ownership given to the newly created file is of administrators group although I am running this application in my...
0
by: YellowFin Announcements | last post by:
(Association Press) - Get ready for the next wave of business intelligence, which will once and for all take BI mainstream, with query, reporting, and analysis dashboards on every desktop. ...
0
by: digz | last post by:
In the code below , a simplified version I need to pass a smart pointer to function f which I control .I cannot use std::auto_ptr as a parameter to f because it releases ownership on copy...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.