ProtectedData.Unprotect() after Impersonate()
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 says
"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 w开发者_JAVA百科ant to impersonate, before calling the method."
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
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.
精彩评论