Impersonating users to access hives - various methods, what are the practical issues? - c++

I am designing a Service to run under LocalSystem account on Win2000, XP and Vista. It will need access to users registry hives, sometimes for extended periods of time, both when the users are logged-in, and also, when they are not logged-in (IF the profile is local. If the profile is Roaming and not loaded, I will not attempt to load it.)
If the user is logged-on, I can get the Users access token by various means (E.g. from its Explorer process, or by receiving Logon events from the Service Control Manager) then use ImpersonateLoggedOnUser and RegOpenCurrentUser to access the User's hive. However, what are the implications if the User selects LogOff from the start menu while I am impersonating and have his hive open? Will the logoff be prevented? Will my impersonation be terminated?
If the user is not logged on, I can use RegLoadKey to directly open the hive NTUSER.DAT. (Impossible for a logged-on user). But what are the implications of this if the user decides to log-on (I suppose the hive will be locked and the logon either prevented, or may experience difficulty?)
I will be setting up some test projects to explore these ideas however, regardless of their apparent results, these questions are theoretical in terms of what type of problems might, or would, be caused by the user loggin in/out during these actions by the service.
Caveat: ImpersonateLoggedOnUser can ONLY be used either for a logged-on user (token obtained from process or SCM event) OR for a user for which I have the plaintext password to call WinLogon and obtain a token - TRUE / FALSE ? In other words although I have maximum permissions as LocalSystem and am able to change the user's password or even delete the user's account, if the user is not logged-on, it is totally impossible to create a new token to impersonate the user without having the the password?

Apparently, there is some risk of damaging a user's profile if it is already loaded by another process when the user logs in. In that case, the system will try to create a new subdirectory for the user.

Related

C++ read any windows user HKEY using username/SID or Alternate

I have created an application, which works for all the windows users (Local, AD, Azure etc). For every user, I'm storing some data inside HKEY_CurrentUer\TESTApp\ registry. Now in the custom credential provider (LOGINUI) once the user enters the credential Wants to read that user HKEY_{...}\TESTApp\ details to know more about the user.
I can successfully store user details in HKEY_CurrentUer\TESTApp\ registry and read details from HKEY_USERS\SID\TESTApp\ if he already login's in.
Now I have the following question,
Is it possible to do the same for not logged in or log out users using either username/SID?
Is there any other HKEY place where I can store the user details and can easily read using username/SID without admin permission? For now, I want to maintain the user details in the machine itself (no cloud).
At last, if the above two is not possible, can I create and read a file with key-pair values in my app workspace without any permission issue?
Since I'm new to windows app development, correct me if I'm doing wrong. THANKS in advance.
HKEY_USERS\SID will be created only after successfully logon on this machine and continue to reside after logout.
If you are talking about logon scenario for credential provider CPUS_LOGON means that your credential provider is working with highest privileges for application - as a SYSTEM user, and you can read and write practically everywhere.

Windows: How to get full users' accounts

Is there any way to get users' system account? I want to make authorisation in my prog with Windows account. Trying to use Active Directory, but it only helps with names and other information, but what about passwords? I understand that I can't get passwords in free access, and I don't need this. But is there any way just to compare input string with real user's windows password?
Or is there any other way to embed authorisation into my program with windows users' accounts?
You may start with NetUserEnum, and with NetQueryDisplayInformation.
There is no way to determine password of a user.
You may use LogonUser API to authenticate users based on password they'd give on your logon window. You should not keep the password after this API succeeds - that's a breach of safety.
Use CredUIPromptForCredentials for asking the user credentials.
The easiest way is to observe that you are in fact running in a login session for the current user, so he does know his password. From there on, Windows will handle all authorisations automatically.

Get user's default UI language using user token with C++

I know that GetUserDefaultUILanguage API can retrieve the UI language identifier for the current user, but I need to call it from a service and find out the UI of a specific user by its user token. Is such possible?
A service runs under some account, so even if you could successfully call functions like this, they'd tell you about the account the service is running under, not the account of a user that might need the service to carry out operations on its behalf.
As such, you probably need to have the user program register itself (e.g., PID and UI language) with the service. The service can then store those and use them as needed.
To use functions like GetUserDefaultUILanguage() inside a service, it needs to be running as that user. Either set the service in the SCM to run under that specific user account, or else have its code impersonate the user dynamically when needed.

On Non-Admin Account OpenSCManager() function returns null

Please help me soon.
I am writing a c++ code to run a service, it works fine on administrator account
but on Non-Admin user account, OpenSCManager() function return null.
Please tell me how to grant permission to non-admin user account to start and stop services.
Or do i need to do something else.
Please reply soon
Probably you're calling OpenSCManager specifying the SC_MANAGER_ALL_ACCESS flag, which actually requires a set of privileges that are given by default only to admins. To start/stop services here you just need to specify the SC_MANAGER_CONNECT flag, which is given by default to any authenticated user.
Now that you have a handle to the service manager, you have to use OpenService to get a handle to the service. To have rights to start/stop the service you should specify GENERIC_READ | GENERIC_EXECUTE as desired access (actually I think you can even narrow down the needed rights to just SERVICE_START and SERVICE_STOP and, if necessary, SERVICE_INTERROGATE).
Here is the problem: standard services DACL don't grant such rights to normal users, so you should change the DACL of the service you need to start to allow normal users to start/stop it; see here. For more info about access rights for services, see here.
If, instead of a single service, you want to allow a normal user to start/stop any service, I don't know if it is possible without changing all the DACLs, but in my opinion it's definitely a bad idea.
Note that even in the single service case, if the service is running under a privileged account (e.g. LocalSystem) or if it's a vital system service, letting unprivileged users mess with it it's still a bad idea. You should allow users to start/stop only services that aren't all that important for the system.
Out of curiosity, why do you need to let users start/stop services?

Problem using AddIPAddress when impersonating an Admin User

I am attempting to add a temporary IP address to a NIC using AddIPAddress when logged in as a non-admin user. The MSDN documentation for AddIPAddress states that ERROR_INVALID_HANDLE is returned as as error if the function is called by a non-admin user.
Given that I have preceeded the call to AddIPAddress with API calls to LogonUser() and ImpersonateLoggedOnUser(). Now my application thinks it's logged in as an Admin, but AddIPAddress still fails with ERROR_INVALID_HANDLE.
MSDN also states that..
"Note Group policies, enterprise policies, and other restrictions on the network may prevent these functions from completing successfully. Ensure that the application has the necessary network permissions before attempting to use these functions."
Is it possible to call AddIPAddress using impersonation? if so how? I'm guessing I need to change the permissions mentioned above but I am at a loss as to what to chnage in this area.
Any help would be appreciated!
Additonal: I've also drawn a blank while attempting to call out to netsh (again logged in as a normal user) using CreateProcessAsUser using a handle to an impersonated admin user to launch the process. Always returns errors indicating insufficent priviledges.
If you are using windows Vista you may need to elevate privileges.
In Vista by default UAC is enabled. This makes it so that even as an administrator you are using a limited user token unless you explicitly elevate. When you do this the user is presented with a dialog to allow or deny the request.
For more information on this see Windows Vista Application Development Requirements for User Account Control Compatibility.
You may want to try using CheckTokenMembership to verify you are properly elevated after you log on as admin. I would suspect you are getting the limited user token and thus failing requests for privileged resources.
Best of luck.