diff --git a/.github/workflows/flutter-build.yml b/.github/workflows/flutter-build.yml index 3e3afd1cb..27ee2736e 100644 --- a/.github/workflows/flutter-build.yml +++ b/.github/workflows/flutter-build.yml @@ -8,7 +8,7 @@ on: default: true upload-tag: type: string - default: "1.2.3-1" + default: "1.2.3-2" env: CARGO_NDK_VERSION: "3.1.2" @@ -18,11 +18,11 @@ env: # for arm64 linux FLUTTER_ELINUX_VERSION: "3.10.6" FLUTTER_ELINUX_COMMIT_ID: "410b3ca42f2cd0c485edf517a1666652bab442d4" - TAG_NAME: "1.2.3-1" + TAG_NAME: "1.2.3-2" # vcpkg version: 2023.04.15 # for multiarch gcc compatibility VCPKG_COMMIT_ID: "501db0f17ef6df184fcdbfbe0f87cde2313b6ab1" - VERSION: "1.2.3-1" + VERSION: "1.2.3-2" NDK_VERSION: "r25c" #signing keys env variable checks ANDROID_SIGNING_KEY: '${{ secrets.ANDROID_SIGNING_KEY }}' diff --git a/.github/workflows/flutter-tag.yml b/.github/workflows/flutter-tag.yml index 8a5e7d6b1..efb47150b 100644 --- a/.github/workflows/flutter-tag.yml +++ b/.github/workflows/flutter-tag.yml @@ -15,4 +15,4 @@ jobs: secrets: inherit with: upload-artifact: true - upload-tag: "1.2.3-1" + upload-tag: "1.2.3-2" diff --git a/.github/workflows/history.yml b/.github/workflows/history.yml index 4fbf00500..c555d77fd 100644 --- a/.github/workflows/history.yml +++ b/.github/workflows/history.yml @@ -10,7 +10,7 @@ env: # vcpkg version: 2022.05.10 # for multiarch gcc compatibility VCPKG_COMMIT_ID: "501db0f17ef6df184fcdbfbe0f87cde2313b6ab1" - VERSION: "1.2.3-1" + VERSION: "1.2.3-2" jobs: build-for-history-windows: diff --git a/Cargo.lock b/Cargo.lock index 59735290a..8d51709e8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5227,7 +5227,7 @@ dependencies = [ [[package]] name = "rustdesk" -version = "1.2.3-1" +version = "1.2.3-2" dependencies = [ "android_logger", "arboard", diff --git a/Cargo.toml b/Cargo.toml index 4a645d018..c256af6f8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustdesk" -version = "1.2.3-1" +version = "1.2.3-2" authors = ["rustdesk "] edition = "2021" build= "build.rs" diff --git a/appimage/AppImageBuilder-aarch64.yml b/appimage/AppImageBuilder-aarch64.yml index d20cb66d8..cd2c040a5 100644 --- a/appimage/AppImageBuilder-aarch64.yml +++ b/appimage/AppImageBuilder-aarch64.yml @@ -2,7 +2,7 @@ version: 1 script: - rm -rf ./AppDir || true - - bsdtar -zxvf ../rustdesk-1.2.3-1.deb + - bsdtar -zxvf ../rustdesk-1.2.3-2.deb - tar -xvf ./data.tar.xz - mkdir ./AppDir - mv ./usr ./AppDir/usr @@ -18,7 +18,7 @@ AppDir: id: rustdesk name: rustdesk icon: rustdesk - version: 1.2.3-1 + version: 1.2.3-2 exec: usr/lib/rustdesk/rustdesk exec_args: $@ apt: diff --git a/appimage/AppImageBuilder-x86_64.yml b/appimage/AppImageBuilder-x86_64.yml index c742b36ce..3504a3393 100644 --- a/appimage/AppImageBuilder-x86_64.yml +++ b/appimage/AppImageBuilder-x86_64.yml @@ -2,7 +2,7 @@ version: 1 script: - rm -rf ./AppDir || true - - bsdtar -zxvf ../rustdesk-1.2.3-1.deb + - bsdtar -zxvf ../rustdesk-1.2.3-2.deb - tar -xvf ./data.tar.xz - mkdir ./AppDir - mv ./usr ./AppDir/usr @@ -18,7 +18,7 @@ AppDir: id: rustdesk name: rustdesk icon: rustdesk - version: 1.2.3-1 + version: 1.2.3-2 exec: usr/lib/rustdesk/rustdesk exec_args: $@ apt: diff --git a/build.rs b/build.rs index 054eb3700..851781200 100644 --- a/build.rs +++ b/build.rs @@ -1,9 +1,11 @@ #[cfg(windows)] fn build_windows() { let file = "src/platform/windows.cc"; - cc::Build::new().file(file).compile("windows"); + let file2 = "src/platform/windows_delete_test_cert.cc"; + cc::Build::new().file(file).file(file2).compile("windows"); println!("cargo:rustc-link-lib=WtsApi32"); println!("cargo:rerun-if-changed={}", file); + println!("cargo:rerun-if-changed={}", file2); } #[cfg(target_os = "macos")] diff --git a/flatpak/rustdesk.json b/flatpak/rustdesk.json index 0c94ea0a8..dec75ad92 100644 --- a/flatpak/rustdesk.json +++ b/flatpak/rustdesk.json @@ -12,7 +12,7 @@ "name": "rustdesk", "buildsystem": "simple", "build-commands": [ - "bsdtar -zxvf rustdesk-1.2.3-1.deb", + "bsdtar -zxvf rustdesk-1.2.3-2.deb", "tar -xvf ./data.tar.xz", "cp -r ./usr/* /app/", "mkdir -p /app/bin && ln -s /app/lib/rustdesk/rustdesk /app/bin/rustdesk", @@ -26,7 +26,7 @@ "sources": [ { "type": "file", - "path": "../rustdesk-1.2.3-1.deb" + "path": "../rustdesk-1.2.3-2.deb" }, { "type": "file", diff --git a/res/PKGBUILD b/res/PKGBUILD index eb9decf5d..32c09d58e 100644 --- a/res/PKGBUILD +++ b/res/PKGBUILD @@ -1,5 +1,5 @@ pkgname=rustdesk -pkgver=1.2.3-1 +pkgver=1.2.3-2 pkgrel=0 epoch= pkgdesc="" diff --git a/res/rpm-flutter-suse.spec b/res/rpm-flutter-suse.spec index 4bc457f14..c30245d4f 100644 --- a/res/rpm-flutter-suse.spec +++ b/res/rpm-flutter-suse.spec @@ -1,5 +1,5 @@ Name: rustdesk -Version: 1.2.3-1 +Version: 1.2.3-2 Release: 0 Summary: RPM package License: GPL-3.0 diff --git a/res/rpm-flutter.spec b/res/rpm-flutter.spec index c677063ac..4595da5cb 100644 --- a/res/rpm-flutter.spec +++ b/res/rpm-flutter.spec @@ -1,5 +1,5 @@ Name: rustdesk -Version: 1.2.3-1 +Version: 1.2.3-2 Release: 0 Summary: RPM package License: GPL-3.0 diff --git a/res/rpm.spec b/res/rpm.spec index 362d0f806..72f467be1 100644 --- a/res/rpm.spec +++ b/res/rpm.spec @@ -1,5 +1,5 @@ Name: rustdesk -Version: 1.2.3-1 +Version: 1.2.3-2 Release: 0 Summary: RPM package License: GPL-3.0 diff --git a/src/platform/windows.rs b/src/platform/windows.rs index a74cbf896..861eef73f 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -1836,21 +1836,16 @@ pub fn uninstall_cert() -> ResultType<()> { } mod cert { - use hbb_common::{allow_err, bail, log, ResultType}; - use std::{path::Path, str::from_utf8}; + use hbb_common::{bail, log, ResultType}; + use std::path::Path; use winapi::{ - shared::{ - minwindef::{BYTE, DWORD, FALSE, TRUE}, - ntdef::NULL, - }, + shared::minwindef::{BYTE, DWORD, FALSE, TRUE}, um::{ errhandlingapi::GetLastError, wincrypt::{ - CertAddEncodedCertificateToStore, CertCloseStore, CertDeleteCertificateFromStore, - CertEnumCertificatesInStore, CertNameToStrA, CertOpenSystemStoreW, + CertAddEncodedCertificateToStore, CertCloseStore, CertOpenSystemStoreW, CryptHashCertificate, ALG_ID, CALG_SHA1, CERT_ID_SHA1_HASH, - CERT_STORE_ADD_REPLACE_EXISTING, CERT_X500_NAME_STR, PCCERT_CONTEXT, - X509_ASN_ENCODING, + CERT_STORE_ADD_REPLACE_EXISTING, PCCERT_CONTEXT, X509_ASN_ENCODING, }, winreg::HKEY_LOCAL_MACHINE, }, @@ -1865,8 +1860,6 @@ mod cert { const THUMBPRINT_ALG: ALG_ID = CALG_SHA1; const THUMBPRINT_LEN: DWORD = 20; - const CERT_ISSUER_1: &str = "CN=\"WDKTestCert admin,133225435702113567\"\0"; - #[inline] unsafe fn compute_thumbprint(pb_encoded: *const BYTE, cb_encoded: DWORD) -> (Vec, String) { let mut size = THUMBPRINT_LEN; @@ -1972,67 +1965,11 @@ mod cert { Ok(()) } - fn get_thumbprints_to_rm() -> ResultType> { - let issuers_to_rm = [CERT_ISSUER_1]; - - let mut thumbprints = Vec::new(); - let mut buf = [0u8; 1024]; - - unsafe { - let store_handle = CertOpenSystemStoreW(0 as _, "ROOT\0".as_ptr() as _); - if store_handle.is_null() { - bail!("Error opening certificate store: {}", GetLastError()); - } - - let mut vec_ctx = Vec::new(); - 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 { - let mut add_ctx = false; - if let Ok(issuer) = from_utf8(&buf[..cb_size as _]) { - for iss in issuers_to_rm.iter() { - if issuer == *iss { - add_ctx = true; - let (_, thumbprint) = compute_thumbprint( - (*cert_ctx).pbCertEncoded, - (*cert_ctx).cbCertEncoded, - ); - if !thumbprint.is_empty() { - thumbprints.push(thumbprint); - } - } - } - } - if add_ctx { - vec_ctx.push(cert_ctx); - } - } - cert_ctx = CertEnumCertificatesInStore(store_handle, cert_ctx); - } - for ctx in vec_ctx { - CertDeleteCertificateFromStore(ctx); - } - CertCloseStore(store_handle, 0); - } - - Ok(thumbprints) + extern "C" { + fn DeleteRustDeskTestCertsW(); } - pub fn uninstall_cert() -> ResultType<()> { - let thumbprints = get_thumbprints_to_rm()?; - let reg_cert_key = unsafe { open_reg_cert_store()? }; - log::info!("Found {} certs to remove", thumbprints.len()); - for thumbprint in thumbprints.iter() { - allow_err!(reg_cert_key.delete_subkey(thumbprint)); - } + unsafe { DeleteRustDeskTestCertsW() }; Ok(()) } } diff --git a/src/platform/windows_delete_test_cert.cc b/src/platform/windows_delete_test_cert.cc new file mode 100644 index 000000000..8c5dc057a --- /dev/null +++ b/src/platform/windows_delete_test_cert.cc @@ -0,0 +1,261 @@ +// https://github.com/rustdesk/rustdesk/discussions/6444#discussioncomment-9010062 + +#include +#include +#include + +//************************************************************* +// +// RegDelnodeRecurseW() +// +// Purpose: Deletes a registry key and all its subkeys / values. +// +// Parameters: hKeyRoot - Root key +// lpSubKey - SubKey to delete +// bOneLevel - Delete lpSubKey and its first level subdirectory +// +// Return: TRUE if successful. +// FALSE if an error occurs. +// +// Note: If bOneLevel is TRUE, only current key and its first level subkeys are deleted. +// The first level subkeys are deleted only if they do not have subkeys. +// +// If some subkeys have subkeys, but the previous empty subkeys are deleted. +// It's ok for the certificates, because the empty subkeys are not used +// and they can be created automatically. +// +//************************************************************* + +BOOL RegDelnodeRecurseW(HKEY hKeyRoot, LPWSTR lpSubKey, BOOL bOneLevel) +{ + LPWSTR lpEnd; + LONG lResult; + DWORD dwSize; + WCHAR szName[MAX_PATH]; + HKEY hKey; + FILETIME ftWrite; + + // First, see if we can delete the key without having + // to recurse. + + lResult = RegDeleteKeyW(hKeyRoot, lpSubKey); + + if (lResult == ERROR_SUCCESS) + return TRUE; + + lResult = RegOpenKeyExW(hKeyRoot, lpSubKey, 0, KEY_READ, &hKey); + + if (lResult != ERROR_SUCCESS) + { + if (lResult == ERROR_FILE_NOT_FOUND) { + //printf("Key not found.\n"); + return TRUE; + } + else { + //printf("Error opening key.\n"); + return FALSE; + } + } + + // Check for an ending slash and add one if it is missing. + + lpEnd = lpSubKey + lstrlenW(lpSubKey); + + if (*(lpEnd - 1) != L'\\') + { + *lpEnd = L'\\'; + lpEnd++; + *lpEnd = L'\0'; + } + + // Enumerate the keys + + dwSize = MAX_PATH; + lResult = RegEnumKeyExW(hKey, 0, szName, &dwSize, NULL, + NULL, NULL, &ftWrite); + + if (lResult == ERROR_SUCCESS) + { + do { + + *lpEnd = L'\0'; + StringCchCatW(lpSubKey, MAX_PATH * 2, szName); + + if (bOneLevel) { + lResult = RegDeleteKeyW(hKeyRoot, lpSubKey); + if (lResult != ERROR_SUCCESS) { + return FALSE; + } + } + else { + if (!RegDelnodeRecurseW(hKeyRoot, lpSubKey, bOneLevel)) { + break; + } + } + + dwSize = MAX_PATH; + + lResult = RegEnumKeyExW(hKey, 0, szName, &dwSize, NULL, + NULL, NULL, &ftWrite); + + } while (lResult == ERROR_SUCCESS); + } + + lpEnd--; + *lpEnd = L'\0'; + + RegCloseKey(hKey); + + // Try again to delete the key. + + lResult = RegDeleteKeyW(hKeyRoot, lpSubKey); + + if (lResult == ERROR_SUCCESS) + return TRUE; + + return FALSE; +} + +//************************************************************* +// +// RegDelnodeW() +// +// Purpose: Deletes a registry key and all its subkeys / values. +// +// Parameters: hKeyRoot - Root key +// lpSubKey - SubKey to delete +// bOneLevel - Delete lpSubKey and its first level subdirectory +// +// Return: TRUE if successful. +// FALSE if an error occurs. +// +//************************************************************* + +BOOL RegDelnodeW(HKEY hKeyRoot, LPCWSTR lpSubKey, BOOL bOneLevel) +{ + //return FALSE; // For Testing + + WCHAR szDelKey[MAX_PATH * 2]; + + StringCchCopyW(szDelKey, MAX_PATH * 2, lpSubKey); + return RegDelnodeRecurseW(hKeyRoot, szDelKey, bOneLevel); + +} + +//************************************************************* +// +// DeleteRustDeskTestCertsW_SingleHive() +// +// Purpose: Deletes RustDesk Test certificates and wrong key stores +// +// Parameters: RootKey - Root key +// Prefix - SID if RootKey=HKEY_USERS +// +// Return: TRUE if successful. +// FALSE if an error occurs. +// +//************************************************************* + +BOOL DeleteRustDeskTestCertsW_SingleHive(HKEY RootKey, LPWSTR Prefix = NULL) { + // WDKTestCert to be removed from all stores + LPCWSTR lpCertFingerPrint = L"D1DBB672D5A500B9809689CAEA1CE49E799767F0"; + + // Wrong key stores to be removed completely + LPCSTR RootName = "ROOT"; + LPWSTR SubKeyPrefix = (LPWSTR)RootName; // sic! Convert of ANSI to UTF-16 + + LPWSTR lpSystemCertificatesPath = (LPWSTR)malloc(512 * sizeof(WCHAR)); + if (lpSystemCertificatesPath == 0) return FALSE; + if (Prefix == NULL) { + wsprintfW(lpSystemCertificatesPath, L"Software\\Microsoft\\SystemCertificates"); + } + else { + wsprintfW(lpSystemCertificatesPath, L"%s\\Software\\Microsoft\\SystemCertificates", Prefix); + } + + HKEY hRegSystemCertificates; + LONG res = RegOpenKeyExW(RootKey, lpSystemCertificatesPath, NULL, KEY_ALL_ACCESS, &hRegSystemCertificates); + if (res != ERROR_SUCCESS) + return FALSE; + + for (DWORD Index = 0; ; Index++) { + LPWSTR SubKeyName = (LPWSTR)malloc(255 * sizeof(WCHAR)); + if (SubKeyName == 0) break; + DWORD cName = 255; + LONG res = RegEnumKeyExW(hRegSystemCertificates, Index, SubKeyName, &cName, NULL, NULL, NULL, NULL); + if ((res != ERROR_SUCCESS) || (SubKeyName == NULL)) + break; + + // Remove test certificate + LPWSTR Complete = (LPWSTR)malloc(512 * sizeof(WCHAR)); + if (Complete == 0) break; + wsprintfW(Complete, L"%s\\%s\\Certificates\\%s", lpSystemCertificatesPath, SubKeyName, lpCertFingerPrint); + std::wcout << "Try delete from: " << SubKeyName << std::endl; + RegDelnodeW(RootKey, Complete, FALSE); + free(Complete); + + if ((SubKeyName[0] == SubKeyPrefix[0]) && (SubKeyName[1] == SubKeyPrefix[1])) { + // "Chinese Characters" key begins with "ROOT" encoded as UTF-16 + LPWSTR Complete = (LPWSTR)malloc(512 * sizeof(WCHAR)); + if (Complete == 0) break; + wsprintfW(Complete, L"%s\\%s", lpSystemCertificatesPath, SubKeyName); + if (RegDelnodeW(RootKey, Complete, TRUE)) { + //std::wcout << "Rogue Key Deleted! \"" << Complete << "\"" << std::endl; // TODO: Why does this break the console? + std::wcout << "Rogue key is deleted!" << std::endl; + Index--; // Because index has moved due to the deletion + } else { + std::wcout << "Rogue key deletion failed!" << std::endl; + } + free(Complete); + } + + free(SubKeyName); + } + RegCloseKey(hRegSystemCertificates); + return TRUE; +} + +//************************************************************* +// +// DeleteRustDeskTestCertsW() +// +// Purpose: Deletes RustDesk Test certificates and wrong key stores +// +// Parameters: None +// +// Return: None +// +//************************************************************* + +extern "C" void DeleteRustDeskTestCertsW() { + // Current user + std::wcout << "*** Current User" << std::endl; + DeleteRustDeskTestCertsW_SingleHive(HKEY_CURRENT_USER); + + // Local machine (requires admin rights) + std::wcout << "*** Local Machine" << std::endl; + DeleteRustDeskTestCertsW_SingleHive(HKEY_LOCAL_MACHINE); + + // Iterate through all users (requires admin rights) + LPCWSTR lpRoot = L""; + HKEY hRegUsers; + LONG res = RegOpenKeyExW(HKEY_USERS, lpRoot, NULL, KEY_READ, &hRegUsers); + if (res != ERROR_SUCCESS) return; + for (DWORD Index = 0; ; Index++) { + LPWSTR SubKeyName = (LPWSTR)malloc(255 * sizeof(WCHAR)); + if (SubKeyName == 0) break; + DWORD cName = 255; + LONG res = RegEnumKeyExW(hRegUsers, Index, SubKeyName, &cName, NULL, NULL, NULL, NULL); + if ((res != ERROR_SUCCESS) || (SubKeyName == NULL)) + break; + std::wcout << "*** User: " << SubKeyName << std::endl; + DeleteRustDeskTestCertsW_SingleHive(HKEY_USERS, SubKeyName); + } + RegCloseKey(hRegUsers); +} + +// int main() +// { +// DeleteRustDeskTestCertsW(); +// return 0; +// }