views:

170

answers:

2

The following code doesn't work:

IntPtr token = Win32Dll.LogonUser(“user1”, “mydomain”, “password1”);
WindowsIdentity id = new WindowsIdentity(token);
WindowsImpersonationContext ic = id.Impersonate();
byte[] unprotectedBytes = ProtectedData.Unprotect(passwordBytes, null, DataProtectionScope.CurrentUser);
password = Encoding.Unicode.GetString(unprotectedBytes);
ic.Undo();

The password is not decrypted.

MSDN said "If you use this method during impersonation, you may receive the following error: "Key not valid for use in specified state." This error can be prevented by loading the profile of the user you want to impersonate, before calling the method."

I would be very grateful for the help!

A: 

Haven't tried this myself, but you could try to use the LoadUserProfile unmanaged API call. For more info, check here.

There are some related SO questions.

Ronald Wildenberg
Thanks for you reply.But I tried to call LoadUserProfile() after "... id.Impersonate();" and code still didn't work.Also I don't know what to do with result of function LoadUserProfile() (its return IntPtr token).Do I just call LoadUserProfile()?Do I to do something with the token?
Andrey
I'm afraid I don't know what to do with the result from LoadUserProfile. I tried reproducing your problem but I never get the exception you describe. I tested both with local and domain accounts but ProtectedData.Protect always succeeds. Good luck, I'd be interested to hear if you found a solution...
Ronald Wildenberg
@rwwilden: Unprotect, not Protect.
GregS
@GregS: Sorry, I meant Unprotect. I tried both.
Ronald Wildenberg
Thanks all for discussion.On one computer unprotect() work.But I have following problem.Try testing the following:1) Protect string by User1 on Computer1 2) Unprotect string by User2 on Computer2 with User1-impersonation.I have been an exception in 2 step.
Andrey
I'm afraid I do not have everything available to perform this test..
Ronald Wildenberg
A: 

Here's what's going on: for DPAPI to work it needs the user's keying material which is derived in part from the user's logon credentials. This data is stored with the user's profile. That's why a process not running as the user must load the user's profile.

You must call UnloadUserProfile() using the data returned from LoadUserProfile()

here's what you need to do:

LogonUser()
Impersonate()
LoadUserProfile()
Encrypt()
UnloadUserProfile()
RevertImpersonation() (Undo() in .NET)

You must check errors, using GetLastError(), every step of the way.

Note that for you to all this stuff basically requires the process be an admin account. You need the backup and restore privileges to load a user's profile. If when calling LoadUserProfile you get a privilege not held error, then you need to:

a) make sure the application account has backup and restore privs
b) the privs are enabled, by default they are not.

You can enabled privs using AdjustTokenPrivileges() http://msdn.microsoft.com/en-us/library/aa375202(VS.85).aspx

Michael Howard-MSFT