I write a method to install a certificate:
public void Install(StoreName storeName, StoreLocation storeLocation)
{
using var store = new X509Store(storeName, storeLocation);
store.Open(OpenFlags.ReadWrite);
store.Add(cert);
}
and invoke it by passing StoreName.Root, StoreLocation.CurrentUser
certificateManager.Install(StoreName.Root, StoreLocation.CurrentUser);
will result in:
Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Access is denied.
at Internal.Cryptography.Pal.StorePal.Add(ICertificatePal certificate)
at System.Security.Cryptography.X509Certificates.X509Store.Add(X509Certificate2 certificate)
at Pixeval.Persisting.WebApi.CertificateManager.Install(StoreName storeName, StoreLocation storeLocation) in C:\NotSystem\Coding\projects\visualstudio\csharp\Pixeval\Persisting\WebApi\CertificateManager.cs:line 99
at Pixeval.App.InstallFakeCaCertificate() in C:\NotSystem\Coding\projects\visualstudio\csharp\Pixeval\App.xaml.cs:line 129
at Pixeval.App.OnStartup(StartupEventArgs e) in C:\NotSystem\Coding\projects\visualstudio\csharp\Pixeval\App.xaml.cs:line 68
at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__139_0(Object state)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.DispatcherOperation.InvokeImpl()
at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state)
at System.Windows.Threading.DispatcherOperation.Invoke()
at System.Windows.Threading.Dispatcher.ProcessQueue()
at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
at System.Windows.Threading.Dispatcher.Run()
at System.Windows.Application.RunDispatcher(Object ignore)
at System.Windows.Application.RunInternal(Window window)
at System.Windows.Application.Run()
at Pixeval.App.Main()
after googling I found mostly relevant questions are asking for StoreLocation.LocalMachine, I didn't found any solution for install a certificate at StoreLocation.CurrentUser
Note: I cannot reproduce this issue because it's posted by one of the users of my application
There are two issues, one is associated with configuration and another with the code itself.
The exception is raised because CurrentUser.Root
store is readonly. It seems that your systems administrator configured GPO to restrict users from writing to this store:
Even if you fix this, the code may fail in a different way: it may hang/freeze. This is because when you install certificates to CurrentUser.Root
, a popup is invoked (you can't avoid this pop-up) to confirm the operation:
I haven't tested, but if the code is invoked in a background thread, then the code may fail, because UI thread is accessed from background thread.
If the application works as a service/batch/imersonated context (such as web app, for example), the pop-up will be shown in a separate session, not on main screen, thus no one will be able to press confirmation button.
Therefore, you SHALL NOT install certificates in CurrentUser.Root
outside of currently interactively logged user context and be sure there is anyone who can press confirmation buttons. And avoid this code execution from bckground tasks.