Setting a password on an AD account...

G

Guest

OK, I have code that I used in a standard windows app
that would create an account and then set the password.

I have taken that code and am using it in a Web App.

Here's the code:

user.CommitChanges();
user.Properties["userAccountControl"].Value = 0x200; //Normal user
user.Invoke("SetPassword", new object[] {szPassword});
//szPassword is a randomly generated complex password.
user.CommitChanges();

The code errors out on the user.Invoke line with an error of "The network
path was not found". Since I just created the account in AD and have
verified
that the account is there, I don't get why I am getting that error.

If anyone has any thoughts they would be appreciated.
 
W

Willy Denoyette [MVP]

Joe said:
OK, I have code that I used in a standard windows app
that would create an account and then set the password.

I have taken that code and am using it in a Web App.

Here's the code:

user.CommitChanges();
user.Properties["userAccountControl"].Value = 0x200; //Normal user
user.Invoke("SetPassword", new object[] {szPassword});
//szPassword is a randomly generated complex password.
user.CommitChanges();

The code errors out on the user.Invoke line with an error of "The network
path was not found". Since I just created the account in AD and have
verified
that the account is there, I don't get why I am getting that error.

If anyone has any thoughts they would be appreciated.


Make sure you are binding securely to the directory object using
"AuthenticationTypes.Secure".

Willy.
 
G

Guest

Will,

Thanks. I am definitely connecting with AuthenticationTypes.Secure.

Could it be the level of .NET?
Joe said:
OK, I have code that I used in a standard windows app
that would create an account and then set the password.

I have taken that code and am using it in a Web App.

Here's the code:

user.CommitChanges();
user.Properties["userAccountControl"].Value = 0x200; //Normal user
user.Invoke("SetPassword", new object[] {szPassword});
//szPassword is a randomly generated complex password.
user.CommitChanges();

The code errors out on the user.Invoke line with an error of "The network
path was not found". Since I just created the account in AD and have
verified
that the account is there, I don't get why I am getting that error.

If anyone has any thoughts they would be appreciated.


Make sure you are binding securely to the directory object using
"AuthenticationTypes.Secure".

Willy.
 
W

Willy Denoyette [MVP]

Joe said:
Will,

Thanks. I am definitely connecting with AuthenticationTypes.Secure.

Could it be the level of .NET?


Guess not.
How does your objectpath looks like (LDAP://....), please specy whether the server name is a
domain name or a DC name.
Is the client (machine) a member of the AD domain you are binding to?
What's the exact callers context, is this called from a console or a Windows application or
something else?
What's the exact Exception message and if possible post a stack trace.
What happens when you don't set the password, are the objects created?

Willy.
 
G

Guest

Willy,

This is a Web App as I stated initially. The user does get created but is
disabled. No problems there.

DirectoryEntry parent = new DirectoryEntry(
"LDAP://dc.mydomain.local/OU=MyOU,DC=mydomain,DC=local",
szUsername,
szPassword,
AuthenticationTypes.Secure);

DirectoryEntry user = parent.Children.Add("CN=" + szFName + " " + szLName,
"user");

using(user)
{
....Set properties...
user.CommitChanges();
AdsUserFlags newValue = AdsUserFlags.NormalAccount;
user.Properties["userAccountControl"].Value = newValue;
user.Invoke("SetPassword", new object[]{szPassword});
user.CommitChanges();
user.Dispose();
parent.Dispose();
}

The client is NOT a member of the domain. This code did work when it
was a Windows App.

Here are the errors:
ex.Message: Reason: Exception has been thrown by the target of an invocation.
ex.InnerException.Message: The network path was not found.

Thanks for the help.
 
G

Guest

Willy,

I forgot to include the stack trace.

" at System.RuntimeType.InvokeDispMethod(String name,
BindingFlags invokeAttr, Object target, Object[] args,
Boolean[] byrefModifiers, Int32 culture,
String[] namedParameters)\r\n

at System.RuntimeType.InvokeMember(String name,
BindingFlags invokeAttr, Binder binder, Object target,
Object[] args, ParameterModifier[] modifiers,
CultureInfo culture, String[] namedParameters)\r\n

at System.Type.InvokeMember(String name, BindingFlags
invokeAttr, Binder binder, Object target,
Object[] args)\r\n

at System.DirectoryServices.DirectoryEntry.Invoke
(String methodName, Object[] args)\r\n

at Project.FormName.btnCreateUser_ServerClick
(Object sender, EventArgs e) in
h:\\inetpub\\wwwroot\\Project\\secure\\FormName.aspx.cs:line 166"

Line 166 is the line where the password is set.

I hope that this helps.

Joe said:
Willy,

This is a Web App as I stated initially. The user does get created but is
disabled. No problems there.

DirectoryEntry parent = new DirectoryEntry(
"LDAP://dc.mydomain.local/OU=MyOU,DC=mydomain,DC=local",
szUsername,
szPassword,
AuthenticationTypes.Secure);

DirectoryEntry user = parent.Children.Add("CN=" + szFName + " " + szLName,
"user");

using(user)
{
...Set properties...
user.CommitChanges();
AdsUserFlags newValue = AdsUserFlags.NormalAccount;
user.Properties["userAccountControl"].Value = newValue;
user.Invoke("SetPassword", new object[]{szPassword});
user.CommitChanges();
user.Dispose();
parent.Dispose();
}

The client is NOT a member of the domain. This code did work when it
was a Windows App.

Here are the errors:
ex.Message: Reason: Exception has been thrown by the target of an invocation.
ex.InnerException.Message: The network path was not found.

Thanks for the help.
Guess not.
How does your objectpath looks like (LDAP://....), please specy whether the server name is a
domain name or a DC name.
Is the client (machine) a member of the AD domain you are binding to?
What's the exact callers context, is this called from a console or a Windows application or
something else?
What's the exact Exception message and if possible post a stack trace.
What happens when you don't set the password, are the objects created?

Willy.
 
W

Willy Denoyette [MVP]

See inline...

Willy.

Joe said:
Willy,

This is a Web App as I stated initially. The user does get created but is
disabled. No problems there.
Right, but this doesn't tell me about the "security context" of the web application.
Anyhow, I assume it's running in a restricted account (network service or aspnet) right?
You don't use SSL to bind, and as this runs from a server which is not a domain member (a
BAD thing if you ask me), Kerberos cannot be used to pass the password in a secured way
either.
That means that "SetPassword" will try Win32 API "NetUserSetInfo" to change the users
password. Now, this one fails when the current user is not an administrator on the DC. So I
guess it works from a windows application started from a session which runs with
administrative privileges on the DC.

One solution is to use SSL with server certificates, or delegate the AD access stuff to a
COM+ server style application which runs as a Domain administrator, note that the latter
will need to be a "shadow account" as you are running this on a non-domain member.


DirectoryEntry parent = new DirectoryEntry(
"LDAP://dc.mydomain.local/OU=MyOU,DC=mydomain,DC=local",
szUsername,
szPassword,
AuthenticationTypes.Secure);

DirectoryEntry user = parent.Children.Add("CN=" + szFName + " " + szLName,
"user");

using(user)
{
...Set properties...
user.CommitChanges();
AdsUserFlags newValue = AdsUserFlags.NormalAccount;
user.Properties["userAccountControl"].Value = newValue;
user.Invoke("SetPassword", new object[]{szPassword});
user.CommitChanges();
user.Dispose();
parent.Dispose();
}

The client is NOT a member of the domain. This code did work when it
was a Windows App.

Here are the errors:
ex.Message: Reason: Exception has been thrown by the target of an invocation.
ex.InnerException.Message: The network path was not found.
Weird thing, this InnerException....

Willy.
 
G

Guest

Willy,

I misunderstood the question. The development box is not a part of the
domain,
but when I run it on the webserver within the domain the error is: Access is
denied.

The account has full admin access.

I just want to verify that the code I am using does not have an error in it
that I am
not seeing.

Thanks.
See inline...

Willy.

Joe said:
Willy,

This is a Web App as I stated initially. The user does get created but is
disabled. No problems there.
Right, but this doesn't tell me about the "security context" of the web application.
Anyhow, I assume it's running in a restricted account (network service or aspnet) right?
You don't use SSL to bind, and as this runs from a server which is not a domain member (a
BAD thing if you ask me), Kerberos cannot be used to pass the password in a secured way
either.
That means that "SetPassword" will try Win32 API "NetUserSetInfo" to change the users
password. Now, this one fails when the current user is not an administrator on the DC. So I
guess it works from a windows application started from a session which runs with
administrative privileges on the DC.

One solution is to use SSL with server certificates, or delegate the AD access stuff to a
COM+ server style application which runs as a Domain administrator, note that the latter
will need to be a "shadow account" as you are running this on a non-domain member.


DirectoryEntry parent = new DirectoryEntry(
"LDAP://dc.mydomain.local/OU=MyOU,DC=mydomain,DC=local",
szUsername,
szPassword,
AuthenticationTypes.Secure);

DirectoryEntry user = parent.Children.Add("CN=" + szFName + " " + szLName,
"user");

using(user)
{
...Set properties...
user.CommitChanges();
AdsUserFlags newValue = AdsUserFlags.NormalAccount;
user.Properties["userAccountControl"].Value = newValue;
user.Invoke("SetPassword", new object[]{szPassword});
user.CommitChanges();
user.Dispose();
parent.Dispose();
}

The client is NOT a member of the domain. This code did work when it
was a Windows App.

Here are the errors:
ex.Message: Reason: Exception has been thrown by the target of an invocation.
ex.InnerException.Message: The network path was not found.
Weird thing, this InnerException....

Willy.
 
W

Willy Denoyette [MVP]

Joe said:
Willy,

I misunderstood the question. The development box is not a part of the
domain,
but when I run it on the webserver within the domain the error is: Access is
denied.

The account has full admin access.

I just want to verify that the code I am using does not have an error in it
that I am
not seeing.

No there is no error in it.
When you run this from a member server you need to make sure that the account specified when
binding has appropriate rights to "Set/Change" the users password.

Following code, will reset the users password ...

private static void SetPassword(string userPath)
{
using (DirectoryEntry userEntry = new DirectoryEntry(userPath, bindUser, bindPwd
,AuthenticationTypes.Secure | AuthenticationTypes.ServerBind
))

try

{

entry.Invoke("SetPassword", new object[]

{"xxxkhljhghg"});

}

catch (TargetInvocationException ex)

{

throw ex.InnerException;

}

}



given a userPath that points to a user object, and that bindUser and bindPwd refers to a
domain admin.





Willy.
 
G

Guest

Willy,

I think I found the error. I haven't corrected it yet, but at least it
gives me a
place to look.

I am seeing this error whenever I try to set the password.

"Windows cannot query for the list of Group Policy objects. Check the event
log for possible messages previously logged by the policy engine that
describes the reason for this."
Joe said:
Willy,

I misunderstood the question. The development box is not a part of the
domain,
but when I run it on the webserver within the domain the error is: Access is
denied.

The account has full admin access.

I just want to verify that the code I am using does not have an error in it
that I am
not seeing.

No there is no error in it.
When you run this from a member server you need to make sure that the account specified when
binding has appropriate rights to "Set/Change" the users password.

Following code, will reset the users password ...

private static void SetPassword(string userPath)
{
using (DirectoryEntry userEntry = new DirectoryEntry(userPath, bindUser, bindPwd
,AuthenticationTypes.Secure | AuthenticationTypes.ServerBind
))

try

{

entry.Invoke("SetPassword", new object[]

{"xxxkhljhghg"});

}

catch (TargetInvocationException ex)

{

throw ex.InnerException;

}

}



given a userPath that points to a user object, and that bindUser and bindPwd refers to a
domain admin.





Willy.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top