mattjohnsonpint/SimpleImpersonation

User name contains the special character throw error

Sabin-Pradhan opened this issue · 7 comments

When pass the username that contains special character then when instantiate the UserCredentials throw the error of:
System.ArgumentException: 'Username cannot contain \ or @ characters when domain is provided separately. (Parameter 'username')'

UserCredentials credentials = new UserCredentials("ABC-COOLS.NCC.LOCAL", ABC\Test.test, "test@12");

My understanding is that is a limitation of Windows usernames. Is it not?

In your example, how can "ABC\" be part of the username? It would be interpreted as the domain being "ABC", which would then conflict with the domain you gave in the first parameter.

Oh Sorry that was just an example and it is a typo. Below is corrected one:
UserCredentials credentials = new UserCredentials("ABC-COOLS.NCC.LOCAL", "NCC\Test.test", "test@12");
When I remote desktop to the above remote server using the username: "NCC\Test.test" and password: "test@12". It is working fine and is able to connect to the server.

So, in that example, the domain is "NCC". You'll get the same effect with new UserCredentials("NCC", "Test.test", "test@12"). The first parameter is not supposed to be the machine name.

Keep in mind that all this library is is a managed wrapper for the Windows LogonUser API. If you don't actually have a domain established but are just trying to connect to a remote computer that is domainless, then this library isn't going to help you because LogonUser isn't designed for that.

From the LogonUser docs:

The LogonUser function attempts to log a user on to the local computer. The local computer is the computer from which LogonUser was called. You cannot use LogonUser to log on to a remote computer. ...

On a domain managed computer, the local computer participates in the domain. So you can connect to another computer in the same domain, or any domain that has an existing relationship established with that domain, and you can use any user from that domain.

But if there is no domain, or the domain that the local computer is in doesn't know anything about the domain the remote computer is in, there's no way to impersonate such a user.

Keep in mind that this is very different then something like a Remote Desktop connection to a domainless machine. In that case, the RDP protocol itself is helping to relay credentials to the remote machine.

I added a note about the above to the project readme to help clarify for future users.

The server has a domain name and that is what I am passing it to UserCredentials. So you are saying the error of System.ArgumentException: 'Username cannot contain \ or @ characters when domain is provided separately. is it because the domain main is missing? I am confused now.

A Windows username cannot contain any of these characters: " / \ [ ] : ; | = , + * ? < >

  • In particular the \ character is used in the "down-level logon name format" to separate a Windows NetBIOS domain name from the user name. The combined down-level format is DOMAIN\username
  • It also cannot contain an @ character because that is used in the combined "user principal name" (UPN) format. The combined UPN format is username@domain

See:

With regard to SimpleImpersonation.UserCredentials

  • The constructor that takes two parameters expects the first parameter to be either a username on the local computer, or a combined domain and username in either the down-level or UPN format. (The second parameter is the password.)
  • The constructor that takes three parameters allows you to specify the domain and username separately. The first parameter is the domain, the second is the username, and the third is the password.
    • It makes no sense to provide a value in the username field that contains a domain name also, as that's what the first parameter is for. It also would create conflicts when the two domain names differ, as they do in your example.
    • Interpreting a \ or @ in any manner other than to separate the domain and username when they are combined in the same string makes no sense. That would be invalid input, and thus you get an exception.

In your example, you are basically saying new UserCredentials("domain1", "DOMAIN2\username", password). There can't be two different domains provided.

I think perhaps you might be confused about the term "domain" here. It's domain as in Windows Active Directory Domain Services (AD DS) domain. These have been part of Windows networking since the earliest days of Windows NT.

That is a related but different concept than the Internet Domain Name System (DNS) name.

In your example of new UserCredentials("ABC-COOLS.NCC.LOCAL", "NCC\Test.test", "test@12"), it looks like you are providing an AD DS domain name of "NCC" in the second parameter, but the first parameter "ABC-COOLS.NCC.LOCAL" appears to be an Internet DNS name.