win, install cert

Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
fufesou 2023-03-07 19:10:37 +08:00
parent 2689688da5
commit e00eaee4b5
4 changed files with 185 additions and 1 deletions

1
Cargo.lock generated
View File

@ -4943,6 +4943,7 @@ dependencies = [
"flutter_rust_bridge_codegen",
"fruitbasket",
"hbb_common",
"hex",
"hound",
"image 0.24.5",
"impersonate_system",

View File

@ -64,6 +64,7 @@ errno = "0.2.8"
rdev = { git = "https://github.com/fufesou/rdev" }
url = { version = "2.1", features = ["serde"] }
dlopen = "0.1"
hex = "0.4.3"
reqwest = { version = "0.11", features = ["blocking", "json", "rustls-tls"], default-features=false }
chrono = "0.4.23"
@ -87,7 +88,7 @@ system_shutdown = "3.0.0"
[target.'cfg(target_os = "windows")'.dependencies]
trayicon = { git = "https://github.com/open-trade/trayicon-rs", features = ["winit"] }
winit = "0.26"
winapi = { version = "0.3", features = ["winuser"] }
winapi = { version = "0.3", features = ["winuser", "wincrypt"] }
winreg = "0.10"
windows-service = "0.4"
virtual_display = { path = "libs/virtual_display" }

View File

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hbb/common.dart';
@ -63,6 +65,7 @@ class _InstallPageBodyState extends State<_InstallPageBody>
late final TextEditingController controller;
final RxBool startmenu = true.obs;
final RxBool desktopicon = true.obs;
final RxBool driverCert = false.obs;
final RxBool showProgress = false.obs;
final RxBool btnEnabled = true.obs;
@ -165,6 +168,20 @@ class _InstallPageBodyState extends State<_InstallPageBody>
Text(translate('Create desktop icon'))
],
),
Offstage(
offstage: !Platform.isWindows,
child: Row(
children: [
Obx(() => Checkbox(
value: driverCert.value,
onChanged: (b) {
if (b != null) driverCert.value = b;
})),
Text(
'${translate('Install driver cert')} ${translate('Virtual display requirement')}')
],
),
),
GestureDetector(
onTap: () => launchUrlString('http://rustdesk.com/privacy'),
child: Row(
@ -230,6 +247,7 @@ class _InstallPageBodyState extends State<_InstallPageBody>
String args = '';
if (startmenu.value) args += ' startmenu';
if (desktopicon.value) args += ' desktopicon';
if (driverCert.value) args += ' driverCert';
bind.installInstallMe(options: args, path: controller.text);
}

View File

@ -1084,6 +1084,9 @@ copy /Y \"{tmp_path}\\Uninstall {app_name}.lnk\" \"{start_menu}\\\"
app_name = crate::get_app_name(),
);
}
if options.contains("driverCert") {
allow_err!(cert::install_cert("IddSampleDriver.cer"));
}
let meta = std::fs::symlink_metadata(std::env::current_exe()?)?;
let size = meta.len() / 1024;
@ -1236,6 +1239,7 @@ fn get_uninstall(kill_self: bool) -> String {
}
pub fn uninstall_me(kill_self: bool) -> ResultType<()> {
allow_err!(cert::uninstall_certs());
run_cmds(get_uninstall(kill_self), true, "uninstall")
}
@ -1902,3 +1906,163 @@ pub fn user_accessible_folder() -> ResultType<PathBuf> {
}
Ok(dir)
}
mod cert {
use hbb_common::{bail, log, ResultType};
use std::{path::Path, str::from_utf8};
use winapi::shared::{
minwindef::{BYTE, DWORD, TRUE},
ntdef::NULL,
};
use winapi::um::{
errhandlingapi::GetLastError,
wincrypt::{
CertCloseStore, CertEnumCertificatesInStore, CertNameToStrA, CertOpenSystemStoreA,
CryptHashCertificate, ALG_ID, CALG_SHA1, CERT_ID_SHA1_HASH, CERT_X500_NAME_STR,
PCCERT_CONTEXT,
},
winreg::HKEY_LOCAL_MACHINE,
};
use winreg::{
enums::{KEY_WRITE, REG_BINARY},
RegKey,
};
const ROOT_CERT_STORE_PATH: &str = "SOFTWARE\\Microsoft\\SystemCertificates\\ROOT\\Certificates\\";
const THUMBPRINT_ALG: ALG_ID = CALG_SHA1;
const THUMBPRINT_LEN: DWORD = 20;
#[inline]
unsafe fn compute_thumbprint(pb_encoded: *const BYTE, cb_encoded: DWORD) -> (Vec<u8>, String) {
let mut size = THUMBPRINT_LEN;
let mut thumbprint = [0u8; THUMBPRINT_LEN as usize];
if CryptHashCertificate(
0,
THUMBPRINT_ALG,
0,
pb_encoded,
cb_encoded,
thumbprint.as_mut_ptr(),
&mut size,
) == TRUE
{
(thumbprint.to_vec(), hex::encode(thumbprint))
} else {
(thumbprint.to_vec(), "".to_owned())
}
}
#[inline]
unsafe fn open_reg_cert_store() -> ResultType<RegKey> {
let hklm = winreg::RegKey::predef(HKEY_LOCAL_MACHINE);
Ok(hklm.open_subkey_with_flags(ROOT_CERT_STORE_PATH, KEY_WRITE)?)
}
// https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-gpef/6a9e35fa-2ac7-4c10-81e1-eabe8d2472f1
fn create_cert_blob(thumbprint: Vec<u8>, encoded: Vec<u8>) -> Vec<u8> {
let mut blob = Vec::new();
let mut property_id = (CERT_ID_SHA1_HASH as u32).to_le_bytes().to_vec();
let mut pro_reserved = [0x01, 0x00, 0x00, 0x00].to_vec();
let mut pro_length = (THUMBPRINT_LEN as u32).to_le_bytes().to_vec();
let mut pro_val = thumbprint;
blob.append(&mut property_id);
blob.append(&mut pro_reserved);
blob.append(&mut pro_length);
blob.append(&mut pro_val);
let mut blob_reserved = [0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00].to_vec();
let mut blob_length = (encoded.len() as u32).to_le_bytes().to_vec();
let mut blob_val = encoded;
blob.append(&mut blob_reserved);
blob.append(&mut blob_length);
blob.append(&mut blob_val);
blob
}
pub fn install_cert<P: AsRef<Path>>(path: P) -> ResultType<()> {
let mut cert_bytes = std::fs::read(path)?;
unsafe {
let thumbprint = compute_thumbprint(cert_bytes.as_mut_ptr(), cert_bytes.len() as _);
log::debug!("Thumbprint of cert {}", &thumbprint.1);
let reg_cert_key = open_reg_cert_store()?;
let (cert_key, _) = reg_cert_key.create_subkey(&thumbprint.1.to_ascii_uppercase())?;
let data = winreg::RegValue {
vtype: REG_BINARY,
bytes: create_cert_blob(thumbprint.0, cert_bytes),
};
cert_key.set_raw_value("Blob", &data)?;
}
Ok(())
}
fn get_thumbprints_to_rm() -> ResultType<Vec<String>> {
let issuers_to_rm = ["CN=\"WDKTestCert admin,133225435702113567\""];
let mut thumbprints = Vec::new();
let mut buf = [0u8; 1024];
unsafe {
let store_handle = CertOpenSystemStoreA(0 as _, "ROOT\0".as_ptr() as _);
if store_handle.is_null() {
bail!("Error opening certificate store: {}", GetLastError());
}
let mut cert_ctx: PCCERT_CONTEXT = CertEnumCertificatesInStore(store_handle, NULL as _);
while !cert_ctx.is_null() {
// https://stackoverflow.com/a/66432736
let cb_size = CertNameToStrA(
(*cert_ctx).dwCertEncodingType,
&mut ((*(*cert_ctx).pCertInfo).Issuer) as _,
CERT_X500_NAME_STR,
buf.as_mut_ptr() as _,
buf.len() as _,
);
if cb_size != 1 {
if let Ok(issuer) = from_utf8(&buf) {
for iss in issuers_to_rm.iter() {
if issuer.contains(iss) {
let (_, thumbprint) = compute_thumbprint(
(*cert_ctx).pbCertEncoded,
(*cert_ctx).cbCertEncoded,
);
if !thumbprint.is_empty() {
thumbprints.push(thumbprint);
}
}
}
}
}
cert_ctx = CertEnumCertificatesInStore(store_handle, cert_ctx);
}
CertCloseStore(store_handle, 0);
}
Ok(thumbprints)
}
pub fn uninstall_certs() -> ResultType<()> {
let thumbprints = get_thumbprints_to_rm()?;
let reg_cert_key = unsafe { open_reg_cert_store()? };
for thumbprint in thumbprints.iter() {
reg_cert_key.delete_subkey(&hex::encode(thumbprint)).ok();
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_install_cert() {
println!("install driver cert: {:?}", cert::install_cert("RustDeskIddDriver.cer"));
}
#[test]
fn test_uninstall_cert() {
println!("uninstall driver certs: {:?}", cert::uninstall_certs());
}
}