Getting the password from WindowsIdentity/WindowsPrincipal??

M

Michael Howes

In our application the user needs to log on and to do so they need a
local windows account.
I do this calling LogonUser. I use the token to create a
WindowsIdentity and also use WindowsPrincipal to check if the user is a
Power User.

I keep this WindowsIdentity around in the application.

There is an area of the application that does some user management but
the user needs to be a administrator. Most of the work is done using
DirectoryEntry and the initial call to the machine needs name and
password of an administrator.
Is there any way to get the password from the WindowsIdentity and pass
in the name/password from the WindowsIdentity to the DirectoryEntry
constructor?

I can use WindowsPrincipal to check if the user is an administrator
and if they are I shouldn't prompt the user to logon again if they try
and go into the user manager area.

Or do I need to keep the password around after they logon?

thanks
mike
 
P

Peter Bradley

Ysgrifennodd Michael Howes:
In our application the user needs to log on and to do so they need a
local windows account.
I do this calling LogonUser. I use the token to create a
WindowsIdentity and also use WindowsPrincipal to check if the user is a
Power User.

I keep this WindowsIdentity around in the application.

There is an area of the application that does some user management but
the user needs to be a administrator. Most of the work is done using
DirectoryEntry and the initial call to the machine needs name and
password of an administrator.
Is there any way to get the password from the WindowsIdentity and pass
in the name/password from the WindowsIdentity to the DirectoryEntry
constructor?

I can use WindowsPrincipal to check if the user is an administrator and
if they are I shouldn't prompt the user to logon again if they try and
go into the user manager area.

Or do I need to keep the password around after they logon?

thanks
mike

Hmm. You don't really want to be keeping passwords lying around.

We do lots of this stuff. The way we arrange it (in a nutshell) is to
perform all the AD stuff using a Service hosted remote Server Activated
Object. We use roles to protect sensitive areas of our programs, and
don't let non-admins access those areas. This means that we can be
confident that calls reaching the remote object are from admins, so we
give the remote object the necessary rights on AD (via the effective uid
of the service process).

It's not foolproof, but it satisfies our threat model.

HTH


Peter
 
J

Joe Kaplan

No, you can't get the password from the WindowsIdentity. You may need to
keep the password around if you prompted for it.

However, you can just impersonate the WindowsIdentity for the local user via
WindowsImpersonationContext and supply null credentials in your
DirectoryEntry constructor. That will accomplish the same goal without
needing to keep the password (as long as you keep the WindowsIdentity).
Note that you need to be careful if your DirectoryEntry calls will access
resources off box, but you said this was for modification of local accounts,
so I assume this is a non-issue.

Joe K.
 
G

Guest

The WindowsIdentity class has only the following properties:
AuthenticationType- Gets the type of authentication used to identify the
user.
IsAnonymous- Gets a value indicating whether the user account is identified
as an anonymous account by the system.
IsAuthenticated- Gets a value indicating whether the user has been
authenticated by Windows.
IsGuest- Gets a value indicating whether the user account is identified as a
Guest account by the system.
IsSystem- Gets a value indicating whether the user account is identified as
a System account by the system.
Name- Gets the user's Windows logon name.
Token- Gets the Windows account token for the user.

if you can identify the "role" or group of a user by name (even by using a
simple lookup), you can do your initial call with the same valid account
credentials every time and it should not be necessary to know the user's
password.

Peter
 
M

Michael Howes

However, you can just impersonate the WindowsIdentity for the local user via
WindowsImpersonationContext and supply null credentials in your
DirectoryEntry constructor. That will accomplish the same goal without
needing to keep the password (as long as you keep the WindowsIdentity).
Note that you need to be careful if your DirectoryEntry calls will access
resources off box, but you said this was for modification of local accounts,
so I assume this is a non-issue.

I got this to somewhat work with 3 lines of code which is nice.
Since I already keep the WindowsIdentity around I just called
Impersonate() and then created a DirectoryEntry without credentials.

I was able to get a list of local users in a specific group.

But after it was all done and I'm about to show my user manager dialog
I get an exception "Safe handle has been closed"??

I assume this is in reference to the tokenHandle I get from calling
LogonUser and use to create my WindowsIdentity??

the stack trace shows
ImpersonateLoggedOnUser
SafeImpersonate
Impersonate

all the way through the details of what calling Impersonate must do

any ideas what might be going on here?

mike
 
J

Joe Kaplan

It is hard to tell what you might be doing wrong here without seeing the
code, but is it possible that you failed to call Undo on your
WindowsImpersonationContext in the appropriate finally block or something?
It sounds like your WindowsIdentity got finalized before you were done using
it.

Joe K.
 
M

Michael Howes

It is hard to tell what you might be doing wrong here without seeing the
code, but is it possible that you failed to call Undo on your
WindowsImpersonationContext in the appropriate finally block or something?
It sounds like your WindowsIdentity got finalized before you were done using
it.

Undo?

I did the follow to impersonate

using (m_CurrentUser)
{
m_CurrentUser.Impersonate();
m_LocalMachine = new DirectoryEntry("WinNT://" +
Environment.MachineName + ",Computer");

}

Once I have the local connection I keep it around in the class I have to
do all the user management. Most actions, disabling a user, adding a
user, changing passwords all use m_LocalMachine.

Right after this call I make calls to get the users in the Power Users
group and I do get all the users. I loop through them adding them to a
listview on a form and right before the form shows (this all happens in
the constructor of the form) the exception is thrown.

m_CurrentUser is a WindowsIdentity that is passed in from the main
application.

thanks
mike
 
J

Joe Kaplan

Normally, you might do something like this:

using (m_CurrentUser)
{

WindowsImpersonationContext wic = m_CurrentUser.Impersonate();
try
{
m_LocalMachine = new DirectoryEntry("WinNT://" +
Environment.MachineName + ",Computer");
}
finally
{
wic.Undo();
}

}

I'm not sure if this is going to totally work for you though. Having the
DirectoryEntry is good, but it isn't bound to the directory yet. You need
to access a property or method on it that forces the bind. You need to do
that while you are still impersonating. Additionally, you may need to keep
impersonating while you are accessing other properties and methods. The
ADSI WinNT provider is basically a wrapper around a lot of the NetUserXXX
RPC methods and such, so I'm not totally sure if they will maintain the same
security context after the initial bind. If you were doing LDAP it would
since LDAP is connection-based and once the connection is made and
authenticated, it stays that way but I'm just not sure with WinNT. Be
careful.

Joe K.
 
M

Michael Howes

I'm not sure if this is going to totally work for you though. Having the
DirectoryEntry is good, but it isn't bound to the directory yet. You need
to access a property or method on it that forces the bind. You need to do
that while you are still impersonating. Additionally, you may need to keep
impersonating while you are accessing other properties and methods. The
ADSI WinNT provider is basically a wrapper around a lot of the NetUserXXX
RPC methods and such, so I'm not totally sure if they will maintain the same
security context after the initial bind. If you were doing LDAP it would
since LDAP is connection-based and once the connection is made and
authenticated, it stays that way but I'm just not sure with WinNT. Be
careful.

yeah, same error.

Will it work if I impersonate during every DirectoryEntry call?

that's going to make the code a mess

In the end it looks like keeping the original password around is the
cleanest way to do this.

mike
 
J

Joe Kaplan

That may be the way you need to do it. Without getting a lot more details
as to what's going on with your implementation, I'm not sure if I can solve
this problem for you. Impersonating with each call wouldn't hurt and might
fix the problem, but it looks more like something else is wrong with the
impersonation itself.

Joe K.
 

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