Re: SetPassword access denied
- From: "Isaac Oben [MCITP:EA, MCSE]" <isaac.oben@xxxxxxxxxxxxxxxx>
- Date: Sat, 14 Mar 2009 10:01:54 -0500
Hello Systinte5
Glad to know you got it working and thanks for sharing your solution as well
Isaac
"systinte5" <systinte5@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
news:57ABE691-C612-4FA0-AFAA-53593D7E4A32@xxxxxxxxxxxxxxxx
Sorry, it has been a while. We figured out why SetPassword threw an access
denied exception and SDS.P threw array out of bounds exception as well.
After
trying out various approaches, we finally found there were GPOs at the
client
site that necessitated a specific sequence of attributes be set before
attempting SetPassword. I always thought sAMAccountName was the single
mandatory property to be set for a successful account creation. We can
then
safely invoke SetPassword etc..... But this specific customer / site
required
that in addition to sAMAccountName, we have to set givenName, sn,
userPrincipalName, displayName and only then invoke SetPassword() method.
Just thought other developers may like to know that there are GPO
interference to keep an eye out for....
"Joe Kaplan" wrote:
Glad you have the book. Sorry it did not magically solve this problem
for
you. We tried. :) We rewrote ch 8 3 times before we shipped and I
still
think we could have explained some of this stuff a little better. It is
a
difficult topic to nail perfectly.
That said, I think one thing worth pointing out is that in both cases
here,
your code is supplying credentials to the DirectoryEntry constructor. In
that case, the identity of the current thread (established either via
impersonation or using the process token without impersonation) is NOT
the
account that is used for performing remote activities in the directory.
Basically, you should either impersonate and use default credentials OR
not
impersonate and supply credentials directly to the DirectoryEntry. I
don't
quite get why you need to supply fixed credentials for just the pwd set
either. It really should work consistently.
I'm also a big fan of using the SDS.P-based LDAP password changer from ch
10
and using SSPI auth with signing and sealing enabled as the default
mechanism for doing pwd changes. Using this approach avoids all the
confusion that can come from calling SetPassword and also allows you to
bypass the need for SSL. You can still use SSL if you want and it is
available, but you don't have to. This will work cleanly with
impersonation
as well.
Of course, this requires some recode, but I think it is overall more
sustainable. For high scale situations, you can also pool LDAP
connections
on a "per OU admin" basis if needed.
If you set any other auth flags and don't set "Secure", you WILL be doing
simple bind. That is usually a bad idea. I recommend always doing
secure
bind to AD, even if you are also using SSL.
If you are using a fixed DC, ServerBind gives you a little perf increase.
As per the book, I'd suggest not using the IP address as that breaks Kerb
auth. If impersonation is possible, DNS resolution ought to be working
too.
:) I can understand having to use a fixed DC if your system can't
tolerate
the possibility of "jumping" to another DC (dirsync, logical
inconsistency
due to replication lag, etc.).
I hope that gives you some ideas. I still can't quite tell what is wrong
though.
--
Joe Kaplan-MS MVP Directory Services Programming
Co-author of "The .NET Developer's Guide to Directory Services
Programming"
http://www.directoryprogramming.net
"systinte5" <systinte5@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
news:8BC21C53-B173-4278-8B35-595A33E1204B@xxxxxxxxxxxxxxxx
Hi Joe,
Sorry that I did not post the code snippet. Can you critique on the way
we
create the DirectoryEntry object in the non-secure ldap (port 389)? Per
your
book, you recommend on page 91 (Recommendations for
AuthenticationTypes),
it
is better to use both SECURE and SERVERBIND (because we specify full IP
address of DC in the LDAP path). We are not doing that when going to
port
389. Also we use the OUAdmin credential both to impersonate (because we
do
a
lot of other stuff after setting password that requires that we be
running
as
the OUAdmin) and in the ActiveDirectory constructor. All of this works
in
a
number of locations. We are having the access denied error just in this
client location, so we are not entirely sure if it is the code or some
other
permissions.
try
{
using (new Impersonator(userSA, domainSA, passwordSA))
{
message = "Before DirectoryEntry For " + info;
if (port == "636")
newUser = new DirectoryEntry(path, domainSA + @"\" + userSA,
passwordSA, AuthenticationTypes.SecureSocketsLayer);
else
newUser = new DirectoryEntry(path, domainSA + @"\" + userSA,
passwordSA);// no authenticationtype used)
//Ensure that the password is set
message = "Before pwdLastSet For " + info;
newUser.Properties["pwdLastSet"].Value = 0; // this does not
crash - newUser is not null
message = "Before SetPassword For " + info;
newUser.Invoke("SetPassword", new object[] {
userPassword });
//
this crashes - the catch block sends back the message string to caller
and
it
shows Before SetPassword For ..... and inner exception is
E_ACCESSDENIED
with
0x80070005
Thanks.
--------
"systinte5" wrote:
Thanks Joe. I am a proud owner of your (and Ryan Dunn) book "The .NET
Developer's Guide to Directory Services Programming". The reason, we
impersonate is because depending on the OU, there may be a different
OU
administrator who is delegated admin rights on that OU. This made it
flexible. The service itself is a .NET remoting server and runs with
minimal
rights.
Thanks again.
------
"Joe Kaplan" wrote:
It really should work the same way if the same credentials are being
used to
contact the directory.
One thing you could do in your code for debug purposes would be to
call
WindowsIdentity.GetCurrent() and dump out the identity groups info
somewhere
right before the SetPassword method is called. This will help
ensure
that
you are really running with the identity and thus the permissions
you
think
you are.
I still can't think of a reason why the permissions would be lower
though if
the same account logged in interactively on the same box can execute
the
same steps.
SetPassword under the hood attempts to reset the password either by
LDAP,
Kerberos or NetUserSetInfo, depending on what options are available.
The
authorization policy is always applied by the DC based on the
identity
of
the user who executed the LDAP bind. Note that if you did the bind
before
you started impersonation, that could potentially cause weird things
to
happen. Maybe showing a snip of code would be possible?
I also wonder why you impersonate in code rather than having the
service
execute as the privileged user directly? Either should be possible
but
impersonation causes you to have to store the plaintext credentials
of
the
privileged user somewhere instead of just letting the service
control
manager take care of that.
--
Joe Kaplan-MS MVP Directory Services Programming
Co-author of "The .NET Developer's Guide to Directory Services
Programming"
http://www.directoryprogramming.net
"systinte5" <systinte5@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
news:01BA1584-7663-4D85-99F8-D3461FFCF3EF@xxxxxxxxxxxxxxxx
.NET 2.0 c# code running as a service (no, it does not use the
system
account). The service impersonates an OUAdmin account in order to
create a
user account in that OU. We are able to create an account through
the
software. However when SetPassword() is invoked, it encounters
0x80070005
E_ACCESSDENIED. The impersonated account is just a domain user
account
that
has been delegated administrative control of the OU. The account
is
also a
member of the local machine built-in Administrators group. The
funny
thing
is, if we manually login using the impersonated account, we are
able
to
create new accounts n that OU and set the initial password and set
the
change
password at next logon. The access denied only occurs when doen in
software,
that too only at certain client locations. Most places we have
tested
the
code, it works fine. How can we diagnose the problem? I keep
thinking, it
is
not the code, rather COM permissions issue (because 0x80070005 is
a
COM
error)? When manually creating the account and setting the
password,
I am
sure Microsoft is not doing this using the same interfaces we
developers
are
using?
Thanks for any assistance.
.
- References:
- Re: SetPassword access denied
- From: systinte5
- Re: SetPassword access denied
- Prev by Date: Re: Preparing AD for first Server 2008 PC
- Next by Date: Re: search by owner
- Previous by thread: Re: SetPassword access denied
- Next by thread: Schema transfer error
- Index(es):
Relevant Pages
|