Know if app is installed for "All users" - c#

How do detect if my app was installed for "All users" or just for one user.
Today I check for files put in either Environment.SpecialFolder.CommonApplicationData or Environment.SpecialFolder.ApplicationData by my installer.
Is there a better way?

To expand on Sachin Gaur's answer:
The S-1-5-18(*) folder is for Local System user - which is used when installing for All Users.
Intallation for the current user would have the product key in a folder named after that user's security identifier (S-something-else).
To get the current user's SID, use System.Security.Principal.WindowsIdentity.GetCurrent() to get a WindowsIdentity. Then, use the User property to get a SecurityIdentifier. Then use ToString() to get the string value.
See MSDN for the GetValue method used to access the registry.
(*) HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\

I hope this may be useful to you.
You can know whether application is installed for all user or not by reading the registry value. For this, you must know the product code of the application:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\
To read the registry entry in C#, you can use GetValue() method of Registry class in Microsoft.Win32.

Related

DPAPI ProtectData from different users

I'm using DPAPI ProtectData as follow:
var temp = new byte[32]
{
1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,3,
3,3,3,3,3,3,3,3,
4,4,4,4,4,4,4,4
};
ProtectedData.Protect(temp, null, DataProtectionScope.CurrentUser);
string userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
Lets assume that now temp look likes:
temp = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,....31 };
I want to execute this code from .exe file and also from my WebService (IIS).
The problem is that if I'm running the code from the exe the current user is MyDomain/Administrator and if i'm running the code from WebService the current user is IIS APPPOOL/MyApp.
How can i solve this issue?
I'm trying to run from the WebService the .exe file as follow:
Process.Start(#"C:\myexe.exe");
But Its not worked from some reason (i have full access to my iis application) and anyway i dont think this is the right solution for this case.
Note: From security reason i cant change from DataProtectionScope.LocalMachine to DataProtectionScope.CurrentUser
If you don't want to use DataProtectionScope.CurrentUser, you could install it as LocalMachine to begin with. Then, have the WebService decrypt it, then re-encrypt it using CurrentUser. Make sure to delete the old value and all its transient copies. In this way, you can take it from LocalMachine and lock it down once the appropriate user is running.
This still leaves the key exposed at LocalMachine level, but for a shorter window of time.
Another solution is to use LocalMachine and use the additional entropy feature with a secret shared between the two executables. This could be an obfuscated value known to the application (no "real" security), or a user-provided password. The user-provided password solution could be more secure but is also more of a pain and more programming overhead.
If the time window between installation and WebService running is small, the first solution may be a good fit.
The problem was solved.
I running the IIS application from local user.
You can find this by selecting the app pool and clicking Advance Settings... under the Actions pane menu. Select Identity and then click the button beside the current user listed. Select Custom account and click Set. Use the format domain\username for the username and enter the password for the user.

In Visual Studio: Trying to delete registry entry but "Requested registry access is not allowed"

I have searched for quite a while on a solution to this. At least I think I understand the problem, but I have yet to come to any solution.
What I need is either some sort of executable or a script that will delete some registry entries. The problem is that the registry entries in question only give read/write access to SYSTEM and no one else. The only way that I can delete them is by going into regedit, setting myself as the owner, and finally setting full control to everyone. Only then can the keys be deleted. I need this process to be in some sort of script though!
So in C#, I first make sure that the software has administrative rights. Then I try to execute the following.
RegistryKey reg_localmachine = RegistryKey.OpenRemoteBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, "");
RegistryKey key = reg_localmachine.OpenSubKey(#"SYSTEM\path to subkey", true);
On the second line, when I try to access the sub key with write access, I get the exception "Requested registry access is not allowed." In order for me to change owner or grant permissions, I need to execute SetAccessControl() on the RegistryKey. In order to set access control, I need write privileges for the key. So I am in this paradox.
Security is there for a reason.
You don't want any old program to be able to come in and start hacking around in the registry.
Each entry in the registry has it's own set of DACLS. There are only two solutions:-
Change the account under which your program is running to an account that has permission to delete the registry entry.
Change the DACLS on the registry entry to include the account your program is running under.

Must GnuPG to have installed keys for every username profile?

I'm running (on my local machine) the GPG (wingpg ) - command line version.
My login name at win7 - is RoyiN. ( so I have a profile for it)
When I logged in - I've installed the keys (using PKA.exe) both private and public.
All fine.
Then I wrote this code ( which is working )
Process proc = new Process();
proc.StartInfo.FileName = cfg.PGP_Program_FullPath;
proc.StartInfo.UserName = "Royin";
proc.StartInfo.Domain = ...;
proc.StartInfo.Password = ...
proc.StartInfo.Verb = "runas";
proc.Start();
...
However if I write in the UserName field - another user which is also Administrator on my local machine - it says :
gpg: decryption failed: No secret key
Then I swapped again to RoyiN and it did work
Are keys installed per user? is there a way to change that so it will be global ? ( so every user on the machine will be able to use these keys - without having to install the keys under each every profile) ?
It also implies that if i want to allow other's to connect to my computer - I must be logged on with RoiyN 24/7....
Is there any workaround for this ?
There are two different things happening here that are related to the "person" running gpg.
GPG searches for keys in the default keyring files, which are installed in your user profile directory (under a folder named .gnupg). This will be a set of files like pubring.gpg and secring.gpg. This part is easy to work around: pass --secret-keyring "path\to\file" as one of the parameters and it will add that keyring file to its search path. You may want to move it to a publically readable location, like %ALLUSERSPROFILE%, first.
Apart from that, GnuPG keys are generated for and tied to an identity, which is usually your email address. When receiving files, the data will specify the identify of the person who's key is needed to decrypt and/or verify the integrity. When encrypting or signing files, you have to tell GPG who's key to use. Your secret key is used when you sign things for others, or when you decrypt data sent to you. You need to make sure the appropriate keys are in whatever keyring file you use, regardless of where it is.
There's no need for you to actually stay logged in when you run gpg, if you give it an explicit location for the data. It's simply that gpg, by default, reads the current environment variables, set at login, to determine where those things are.
You'll probably need to specify a keyring file path, a secret keyring file path, and a configuration file path if you want to run GPG unattended. The entire list of options you can specify is on the GPG Configuration Options page.
(You may want to try starting with just the --homedir option, which I think will override the default paths for everything else in one go, but you'd need to test that to make sure.)
Yes, they are installed on per-user basis
Simple answer - just export the private/public key pair, and install it for the Administrator account as well.
Although, it'd be better to create a separate key for your automated system with own public key - whoever has your key with a high level of trust, will accept this one as well.

Problem when trying to use EventLog.SourceExists method in .NET

I am trying to use eventlogs in my application using C#, so I added the following code
if (!EventLog.SourceExists("SomeName"))
EventLog.CreateEventSource("SomeName", "Application");
The EventLog.SourceExists causes SecurityException that says
"The source was not found, but some or all event logs could not be searched. Inaccessible logs: Security."
I am running as administrator in Windows 7.
Any help would be appriciated.
This is a permissions problem - you should give the running user permission to read the following registry key:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog
Alternaitvely you can bypas the CreateEventSource removing the need to access this registry key.
Both solutions are explained in more detail in the following thread - How do I create an Event Log source under Vista?.
Yes, it's a permissions issue, but it's actually worse than indicated by the currently accepted answer. There are actually 2 parts.
Part 1
In order to use SourceExists(), the account that your code is running under must have "Read" permission for the HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog key and it must also have "Read" permissions on each of the descendant-keys. The problem is that some of the children of that key don't inherit permissions, and only allow a subset of accounts to read them. E.g. some that I know about:
Security
State
Virtual Server
So you have to also manually change those when they exist.
FYI, for those keys (e.g. "State") where even the Administrator account doesn't have "Full Access" permission, you'll have to use PsExec/PsExec64 to "fix" things. As indicated in this StackOverflow answer, download PsTools. Run this from an elevated command prompt: PsExec64 -i -s regedit.exe and you'll them be able to add the permissions you need to that key.
Part 2
In order to successfully use CreateEventSource(), the account that your code is running under must have "Full Control" permissions on HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog as well as have "Full Control" permissions on the log you're adding the new source to.
But wait, there's more...
It is also important to know that both CreateEventSource() and WriteEntry() call SourceExists() "under the hood". So ultimately, if you want to use the EventLog class in .Net, you have to change permissions in the registry. The account needs "Full Control" on the HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog key and "Read" for all children.
Commentary: And I believe all of this mess is because when Microsoft originally designed the EventLog, they decided it was critical that people would be able to log something by "Source" without needing to know what log that "Source" went with.
Short tip:
One event source is registered during Service instalation (if application is Windows Service), and can be used without Security Exception with low-profile process owner (not Administrator)
I perform service installation / run with C# code in typical way from SO/ MSDN
Important is property ServiceName in class System.ServiceProcess.ServiceBase .
Good afternoon,
The simplest is that you run vs2019 as an administrator, so when debugging or excute the service, it will run correctly without generating the exception.

Impersonation to get user HKEY_CURRENT_USER does not work?

I am attempting to Impersonate an administrator account from a LocalSystem Service in order to get data from administrators HKEY CURRENT USER registry - in order to impersonate I am using the codeproject code found at the following site written by Uwe Keim: Impersonator
My source code is as follows:
using (new Impersonator("user", ".", "pass"))
{
RegistryKey rk = Registry.CurrentUser.OpenSubKey("Software\\CompanyName");
string sValue = rk.GetValue("Value", "").ToString();
rk2.Close();
}
My expectation was that sValue would be from the user/pass account (as I am impersonating it) but oddly enough it is still the sValue from the LocalSystem account where my service is runnning ...
Any clues on what I am doing wrong? Any help would be much appreciated.
Thanks,
I know this is an old thread but I recently came across the same issue (albeit from a C++ Windows service) and thought I'd share my findings, because many forums have asked the same question and none have left a satisfactory answer.
Basically, I've found two ways to approach this, though this is an answer more for C applications rather than .NET (I haven't tested with pinvoke but it may work).
Solution 1:
Instead of using RegOpenKey, use RegOpenCurrentUser() to get the key handle. Apparently, the reason RegOpenKey doesn't get the impersonated user's key is because HKEY_CURRENT_USER is cached in the running thread.
Solution 2:
RegDisablePredefinedCache(). This disables the cache mentioned above and lets subsequent calls to HKEY_CURRENT_USER be of the actual impersonated user. This is the solution I went with.
Hope this helps.
Everything I've read on the subject seems to indicate that impersonation should get you access to the HKEY_CurrentUser for the impersonated account. However, it could be a quirk in the .NET Registry implementation.
This is just a hunch, and an untested one at that, but have you considered using Registry.Users instead of Registry.CurrentUser?
You'll need to find the SID for the Administrator account, but you should be able to deduce that using Regedit
By default the HKEY_CURRENT_USER handle is cached on a process wide basis. So when you impersonate a user and then access the current user hive you will be accessing the hive of the user that started the process not the user being impersonated. This is true for all Win32 processes not just .Net. If you wish to disable this caching so that all current user calls go to the correct user hive under HKEY_USERS then you must call RegDisablePredefinedCache via pInvoke.
Be warned that if the user being impersonated has not had their profile loaded then any CurrentUser requests will be forwarded to the .DEFAULT user. So you may also need to call LoadUserProfile.
Disabling the handle caching will also cause a slight slowdown in all CurrentUser requests.
I'm guessing you're going to find that you're out of luck. It can't be done.
If applications were able to impersonate an Administrator account and write values to the Registry in Windows, it would present a huge security hole. My guess is that the Registry.CurrentUser property will ALWAYS reference the user running your application...whether or not you try impersonation or not.
EDIT
Turns out that I didn't read the implementation details of the Impersonator code you were using. Your problem could be something completely different.
Does your code refer to the Registry static class prior to your impersonation code being run? If so, that would be the problem. If you look at the Registry.CurrentUser property in Reflector, you'll see that it is set by the static constructor of the Registry object. Static constructors get called when the static object is first referenced.
In your case, if you're referencing the Registry object (whether it involves CurrentUser or not) the static constructor is being called which is setting CurrentUser to your original user...not the Impersonated account.

Categories