What patterns are possible in Windows for the login field - windows

Our Web Application has a login screen: User can login with their Windows Accounts (the admin can use local accounts).
The Web Application uses the UserPrincipal in .NET-Framework to match the login name and password. The entered login will be split by the '\' into Domain part and SamAccountName part. E.g.:
Calamitas\Simon
But for local accounts in Windows it is possible to use the computer name instead the domain name:
ComputerName\LocalUser
And instead for the computer name it is possible to use a dot:
.\LocalUser
Where can I get a list of all these login patterns?

If you are calling FindByIdentity then the formats supported are listed in the IdentityType enum. This seems to be a subset of the types GetUserNameEx can return.
You have most of the important patterns covered already except for name#example.com, name#domain and example.com/name? It might also accept just a name but that lookup is going to be slow in a large domain forest.
There are also distinguished names (CN=Jeff Smith,OU=Sales,DC=Fabrikam,DC=COM) but they are hard to parse/validate.
Users are probably not going to use a GUID or a SID to log in.
If you are trying to validate form input then I would suggest allowing ?*\?* and ?*#?* (DOS syntax). Add S-?-?* to support SIDs.

Related

How to get the SAM compatible domain name on a Hybrid domain computer?

EDIT:
Thank you #RbMm for your clarification questions!
I am implementing MFA in a credential provider (not a wrapper provider). One of the options I must support is to verify the same UPN is used for logging in to the computer and validating with the MFA provider. I use LsaLogonUser, ImpersonateLoggedOnUser and GetUserNameEx(UserNamePrincipal) to obtain this information. This works in most environments; however, on a computer connected to a hybrid Azure AD domain, LsaLogonUser fails. This lead to an investigation the results of which are elaborated below:
I have a computer belonging to an AzureAD hybrid domain, but I have no way of getting the SAM-compatible domain name from the AzureAD domain name.
For example,
I can log in with a user whose AzureAD upn is, for example's sake user#domain.com. The SAM-compatible name is localdomain\localuser.
GetUserNameEx(NameUserPrincipal) reutrns user#domain.com
GetUserNameEx(NameSamCompatible) returns localdomain\localuser
HOWEVER in the following code, TranslateName fails with GetLastError() returning ERROR_NO_SUCH_DOMAIN.
TCHAR validBuffer[MAX_PATH+1];
ULONG nValidSize = MAX_PATH;
TranslateName("user#domain.com", NameUserPrincipal, NameSamCompatible, validBuffer, &nValidSize);
I have also tried the following APIs without success, they all fail with different return values:
GetComputerObjectName fails with any value passed to NameFormat
GetCompterNameEx fails with ERROR_CANT_ACCESS_DOMAIN_INFO for any relevant value of NameType
NetWkstaGetInfo does not return any useful information in any field
Also, if you look at the computer's join information in This PC > Properties > Advanced System Properties, u see it as part of a workgroup, not a domain.
-if you run the dsregcmd /status command:
executed within the aforementioned user's logon session: the 'Diagnostic' part lists the localdomain in the output
executed from a command prompt running with the LocalSystem account, the output does not list the localdomain anywhere.
An important point (thanks #RbMm) - the code services a Windows Credential Provider, when using the 'Other User' tile. I am trying to pre-verify the entered credentials using LsaLogonUser, before serializing them successfully in my implementation of ICredentialProviderCredential2::GetSerialization. Using 'user#domain.com' fails, while using 'localdomain\user#domain.com' or 'localdomain\localuser' succeeds. When logging in with Windows' built in password provider, using 'user#domain.com' of course works. Maybe I should be using a different authentication package for LsaLogonUser?
I am STUMPED.
thanks for anyone's help..
Uriel

Is there anything I can use to mock an AD API for getting a list of users?

I don't need AD for anything more than getting a list of user names. My application uses it's own, custom auth, but it does checks based on the domain username of the logged on user, so the user names in my Users table should match those used by the logged on users.
E.g. For domain user johnblack to access features in my app, the app admin must create a user in my app called johnblack, but when creating this user, the username is a free text field. This allows the app admin to mistakenly create a user called jonblack. I want to make the user name field a dropdown, populated with users from the domain, when the admin adds a new user.
However, the epic saga involved in getting AD running on a VM on my Win 7 Home laptop is just too much overhead for now. Are their any mocks I could use, where my C# code needn't change to switch over to real AD?
Have a look at Active Directory Lightweight Directory Services (AD LDS) - formerly also know as AD/AM (AD Application Mode).
http://msdn.microsoft.com/en-us/library/windows/desktop/aa705886%28v=vs.85%29.aspx
It's a lightweight version of AD, which smells like AD, behaves like AD, but it's a NT service that you can start (and stop) at will, and it doesn't completely take over your machine/server - you can easily disable/uninstall it.

Stored User Names and Passwords

I'm writing an application which needs to store login data for multiple (XMPP) accounts on Windows.
Currently the application stores them in Windows' "Stored User Names and Passwords" using CredRead and CredWrite. And here is the problem: The login name for an XMPP account cannot be changed (it's the account's JID), but Windows only stores user name/password pairs under a given target name. I use something like "xmpp:account#server.tld" for the target name and don't use the user name at all during login. The user can't even set the user name from within the application (it will be set to "account#server.tld" automatically instead).
Now I would like to prevent the user name to be changed to something different by the user (using control panel or rundll32.exe keymgr.dll, KRShowKeyMgr) or an other application as this is currently possible and somehow confusing because the actual value is ignored anyway. If I open up the "Stored User Names and Passwords" dialog (using rundll32.exe keymgr.dll, KRShowKeyMgr), the entries which are created by my application are listed as "xmpp:account#server.tld (LegacyGeneric)" and can be edited using the "Edit..." button.
The list contains also an entry for Windows Live (listed as "live_account#hotmail.com (WindowsLive)"), whose user name cannot be changed (trying so will bring up a message box saying: "Windows cannot save the logon information. Make sure the information is correct and that all required fields are completed.".
And here is (finally) my question: Can I get this behavior for my application as well? How can I change the credential type to something different than "LegcyGeneric"? Or is there a better way to store only the password for a given login name (maybe using Windows Data Protection), while still using some "standard" Windows way of storing them?
Any hints and answers are appreciated.

CFPreferences for another (or all) users

I'm working on a background service which needs to ask several users' iTunes settings (the users will opt-in via a helper application which they run from their login). Is there an easy way to read the preferences for another user, than the current one, using CFPreferences ? The docs, for example for CFPreferencesCopyValue, explicitly state: 'Do not use arbitrary user and host names, instead pass the pre-defined domain qualifier constants.', when passing the 'userName' argument to the various functions.
The userName parameter in CFPreferencesCopyValue is somewhat misleading; the possible values are restricted to the following ones:
- kCFPreferencesAnyUser;
- kCFPreferencesCurrentUser;
It specifies the scope of the preferences you are accessing (either current user or all users). This also means that you cannot access preference of another user, even if you run as root.

What's wrong with GetUserName Win32 API?

I'm using GetUserName Win32 API to get the user name of my computer, but I found the user name is different (uppercase vs. lowercase only) when using my VPN connection into work when I was at home. I’m wondering if the VPN client or other software could be affecting the username?
The GetUserName API states:
Retrieves the name of the user
associated with the current thread.
Use the GetUserNameEx function to
retrieve the user name in a specified
format. Additional information is
provided by the IADsADSystemInfo
interface.
So it looks like that GetUserName uses IADsADSystemInfo to get it's information.
If you look at the IADsADSystemInfo interface you see it has the method:
get_UserName
Retrieves the Active
Directory distinguished name of the
current user, which is the logged-on
user or the user impersonated by the
calling thread.
So when your connected via VPN to a domain login you will most likely get Active Directory distinguished name of the current user and when you aren't, you most likely get the user name that you typed in (in whatever case you typed in) to log onto the computer with.
This API returns the name as typed by the user when logging on to the computer. So if my username is 'esac', but I type 'Esac', this API will return 'Esac'. Subsequently if I type 'ESAC' that is what it will return as well.
Not 100% sure, but I suspect that GetUserName will end up talking to the DC when you're connected to your domain network, whereas it will use the local answer otherwise

Resources