Created
March 7, 2019 10:43
-
-
Save MysteryDash/f26f4abb2915557720e8ef3535634e9d to your computer and use it in GitHub Desktop.
Install root certificates for the current user without confirmation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// This file is licensed under the terms of the Simple Non Code License (SNCL) 2.3.0. | |
// The full license text can be found in the file named License.txt. | |
// Written originally by Alexandre Quoniou in 2019. | |
// | |
using System; | |
using System.Diagnostics; | |
using System.Linq; | |
using System.Runtime.InteropServices; | |
using System.Security.Cryptography.X509Certificates; | |
using System.Threading; | |
using System.Threading.Tasks; | |
namespace Dash.Win32 | |
{ | |
public static class CertificateStore | |
{ | |
// ReSharper disable once InconsistentNaming | |
private const int BM_CLICK = 0x00F5; | |
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] | |
private static extern bool PostMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); | |
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] | |
private static extern IntPtr FindWindowEx(IntPtr hWndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); | |
/// <summary> | |
/// Installs a certificate (in CurrentUser's Root store) and bypasses the confirmation window. | |
/// </summary> | |
/// <param name="certificate"></param> | |
/// <param name="token"></param> | |
/// <returns></returns> | |
public static Task<bool> InstallAsync(X509Certificate2 certificate, CancellationToken token = default) | |
{ | |
var installationTask = Task.Run(() => | |
{ | |
using (var store = new X509Store(StoreName.Root, StoreLocation.CurrentUser)) | |
{ | |
store.Open(OpenFlags.ReadWrite); | |
store.Add(certificate); | |
} | |
}, token); | |
var validationTask = Task.Run(async () => | |
{ | |
var success = ConfirmSecurityWindow(installationTask, token); | |
await installationTask; | |
return success; | |
}, token); | |
return validationTask; | |
} | |
/// <summary> | |
/// Removes a certificate (in CurrentUser's Root store) and bypasses the confirmation window. | |
/// </summary> | |
/// <param name="certificate"></param> | |
/// <param name="token"></param> | |
/// <returns></returns> | |
public static Task<bool> UninstallAsync(X509Certificate2 certificate, CancellationToken token = default) | |
{ | |
var deletionTask = Task.Run(() => | |
{ | |
using (var store = new X509Store(StoreName.Root, StoreLocation.CurrentUser)) | |
{ | |
store.Open(OpenFlags.ReadWrite); | |
store.Remove(certificate); | |
} | |
}, token); | |
var validationTask = Task.Run(async () => | |
{ | |
var success = ConfirmSecurityWindow(deletionTask, token); | |
await deletionTask; | |
return success; | |
}, token); | |
return validationTask; | |
} | |
private static bool ConfirmSecurityWindow(Task securityWindowTask, CancellationToken token = default) | |
{ | |
while (!securityWindowTask.IsFaulted && | |
!securityWindowTask.IsCanceled && | |
!securityWindowTask.IsCompleted) | |
{ | |
token.ThrowIfCancellationRequested(); | |
foreach (var process in Process.GetProcessesByName("csrss").Where(p => p.MainWindowHandle != IntPtr.Zero)) | |
{ | |
var windowHandle = process.MainWindowHandle; | |
var buttonHandle = FindWindowEx(windowHandle, IntPtr.Zero, "Button", null); | |
return PostMessage(buttonHandle, BM_CLICK, IntPtr.Zero, IntPtr.Zero); | |
} | |
} | |
return false; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Simple Non Code License (SNCL)
Version 2.3.0
Copyright © 2016-2019 Alexandre Quoniou
The original creator(s) of the data or text under this license is thereby called the licensor.
The physical or juridical person obtaining a copy of the data or text under this license is thereby called the licensee.
The data, source code or text under this license is therefore called the object.
The licensee's rights and obligations
1.1. The licensee has the right to obtain a free copy of the object.
1.2. It is the right of the licensee to redistribute unaltered copies of the object although commercial use is utterly forbidden (except with the original licensor's express written consent).
1.3. The licensee is given the right to adapt or modify the object to suit their needs and to redistribute the modified version subject to the following conditions:
Liability of the licensor and of the licensee
2.1. The licensor offers the object as-is and as-available, and makes no representations or warranties of any kind concerning the object. Thus, the licensor is not liable for any use made of the object.
2.2. The licensee only is liable for any juridical issue related to the use of the object, edited by third parties or not.
Termination
3.1. All of the clauses stated in section 1 are void if the licensee fails to accomplish their obligations established in section 1.
3.2. If the clause 3.1 becomes true the licensee must pay for any costs the licensor may have with juridical actions against him.
Other terms and conditions
4.1. The licensor shall not be bound by any additional or different terms or conditions communicated by the licensee unless expressly agreed.
4.2. The licensor has the right to edit at any time the content of this license, however, its effects will not be retroactive.
4.3. Any modification made by the licensor shall not affect the already published versions of the object, only the future ones.