C++ – Alternatives to LogonUser for network impersonation (C++)

cimpersonationSecuritysspiwinapi

Are there any alternatives to LogonUser and for impersonating given account in order to access network resources? I'm looking for the method of impersonation which would let me connect to machine in foreign domains (or, workgroup machines for the same matter).

For initial data I have: machine name, username (or domain\username), cleartext password.

I know there's a way to establish connection using WNetAddConnection to a \\machinename\ipc$, then most network functions will run in a context of that account, however win2008 added another twist and some functions still use the account, that thread is running under.

I'm also aware, that there's some way to get an impersonation token using SSPI. Have anyone experimented with those tokens, are they good for accessing shares, SCM, remote registry and stuff? Is is what WNetAddConnection is using?

EDIT: To clarify, the reason I cannot use LogonUser is because I need to impersonate user in a non-trusted domain or workgroup

EDIT2: Another clarification: the item I'm trying to implement is similar to psexec, e.g.:

  • program should not modify host or active directory configuration (e.g.: create temporary local users, etc). Moreover assumption cannot be made that it is running on DC or not
  • there can be no assumptions made about which software is pre-installed on the remote host, only condition given is that windows file sharing is enabled on target
  • Account/password is known to be working on target, but target machine may be in local domain, foreign domain, not in domain at all.

EDIT3: I would really love to hear more about SSPI InitializeSecurityContext / AcquireCredentialsHandle option. Is there anybody who has been working with this API extensively? Is it possible to use the tokens returned with impersonation, so that a thread can access network shares and copy files, etc? Can someone post a working code snippet?

EDIT4: Thanks to Marsh Ray, problem got resolved. If anyone is looking to see the proof-of-concept code, it is here

Best Answer

If you're wanting to "access network resources" outside of your forest, do that with WNetAddConnection2/3 as you mentioned, or use the standard RPC APIs with RPC_ C__ AUTHN__ GSS__ NEGOTIATE and and explicit credentials structure.

Normally, "impersonation" is something that happens on the server side. The server side will be able to impersonate the connection as the account you're connecting as.

But the key is this: impersonation only makes sense for impersonating an account the server can access in his local SAM/domain/forest directory. If the client and server are in different forests, they clearly can't agree on the SID of an account for an impersonation token (except for the case of well-known SIDs like Administrator which serve mainly to confuse this kind of thing), and that seems necessary to check against DACLs etc.

Perhaps what you want is to call LogonUserEx with the LOGON32__ LOGON__ NEW__ CREDENTIALS flag. This should succeed (even in a different forest - it doesn't actually authenticate the credentials you give it) giving you a token with the username/password you specified. You may have to use DuplicateToken to turn this into an impersonation token. Then you can use SetThreadToken to replace the token on your thread.

IMHO this isn't really "impersonation", you're just using the credentials outright, but it allows you to access network resources transparently as the arbitrary username/password you supply.

Edit: Oh yeah, be aware that there is no protection against man-in-the-middle on this type of connection. The client especially cannot strongly authenticate the server (short of heroics like IPSEC), so in theory you can't trust anything the server tells you.

Related Topic