fix: free WinVerifyTrust state data

working with Win32 APIs is actually miserable as shit
This commit is contained in:
beerpiss 2024-06-27 01:55:44 +07:00
parent e5dda7def3
commit 47bb748b3b
5 changed files with 67 additions and 39 deletions

View File

@ -1,7 +1,13 @@
mod defaults; mod defaults;
mod migrate; mod migrate;
use std::{collections::HashMap, fs::File, io::Write, path::{Path, PathBuf}, str::FromStr}; use std::{
collections::HashMap,
fs::File,
io::Write,
path::{Path, PathBuf},
str::FromStr,
};
use log::{info, warn}; use log::{info, warn};
use migrate::OldSaekawaConfig; use migrate::OldSaekawaConfig;
@ -38,12 +44,12 @@ pub enum MigrationError {
impl SaekawaConfig { impl SaekawaConfig {
pub fn load() -> Result<SaekawaConfig, ConfigLoadError> { pub fn load() -> Result<SaekawaConfig, ConfigLoadError> {
if !Path::new("saekawa.toml").exists() { if !Path::new("saekawa.toml").exists() {
// We don't really care about the error here, since Confy will autogenerate a // We don't really care about the error here, since Confy will autogenerate a
// default configuration file anyways. That one just doesn't have comments. // default configuration file anyways. That one just doesn't have comments.
let _ = File::create_new("saekawa.toml") let _ = File::create_new("saekawa.toml")
.and_then(|mut file| file.write_all(include_bytes!("../../res/saekawa.toml"))); .and_then(|mut file| file.write_all(include_bytes!("../../res/saekawa.toml")));
} }
let result = confy::load_path::<SaekawaConfig>("saekawa.toml"); let result = confy::load_path::<SaekawaConfig>("saekawa.toml");
match result { match result {

View File

@ -5,10 +5,18 @@ use widestring::U16CString;
use winapi::{ use winapi::{
ctypes::c_void, ctypes::c_void,
shared::{ shared::{
minwindef::{FALSE, HINSTANCE, HMODULE, TRUE}, ntdef::HANDLE, winerror::ERROR_INSUFFICIENT_BUFFER minwindef::{FALSE, HINSTANCE, HMODULE, TRUE},
ntdef::HANDLE,
winerror::ERROR_INSUFFICIENT_BUFFER,
}, },
um::{ um::{
errhandlingapi::GetLastError, handleapi::{CloseHandle, DuplicateHandle}, libloaderapi::{FreeLibraryAndExitThread, GetModuleFileNameW}, processthreadsapi::{GetCurrentProcess, GetCurrentThread}, synchapi::WaitForSingleObject, winhttp::{WinHttpQueryOption, HINTERNET}, winnt::SYNCHRONIZE errhandlingapi::GetLastError,
handleapi::{CloseHandle, DuplicateHandle},
libloaderapi::{FreeLibraryAndExitThread, GetModuleFileNameW},
processthreadsapi::{GetCurrentProcess, GetCurrentThread},
synchapi::WaitForSingleObject,
winhttp::{WinHttpQueryOption, HINTERNET},
winnt::SYNCHRONIZE,
}, },
}; };

View File

@ -29,7 +29,8 @@ use crate::{
}, },
score_import::execute_score_import, score_import::execute_score_import,
sigscan::{self, CryptoKeys}, sigscan::{self, CryptoKeys},
types::{chuni::UpsertUserAllRequest, ToBatchManual}, updater::self_update, types::{chuni::UpsertUserAllRequest, ToBatchManual},
updater::self_update,
}; };
#[derive(Debug, Snafu)] #[derive(Debug, Snafu)]

View File

@ -81,19 +81,25 @@ pub fn execute_score_import(
return Err(ScoreImportError::MaxRetriesExhausted { max_retries }); return Err(ScoreImportError::MaxRetriesExhausted { max_retries });
}; };
info!("Saving batch manual JSON to configured failed import directory for later import."); info!(
"Saving batch manual JSON to configured failed import directory for later import."
);
let current_time = chrono::Local::now().format("%Y-%m-%d_%H-%M-%S"); let current_time = chrono::Local::now().format("%Y-%m-%d_%H-%M-%S");
let failed_import_filename = let failed_import_filename =
d.join(format!("saekawa_{}_{}.json", access_code, current_time)); d.join(format!("saekawa_{}_{}.json", access_code, current_time));
{ {
let file = File::create(&failed_import_filename).context(FailedCreatingBackupSnafu)?; let file =
File::create(&failed_import_filename).context(FailedCreatingBackupSnafu)?;
serde_json::to_writer_pretty(file, &import).context(FailedWritingBackupSnafu)?; serde_json::to_writer_pretty(file, &import).context(FailedWritingBackupSnafu)?;
} }
info!("Saved batch manual JSON to {}", failed_import_filename.to_string_lossy()); info!(
"Saved batch manual JSON to {}",
failed_import_filename.to_string_lossy()
);
return Ok(()); return Ok(());
} }
Err(e) => return Err(e), Err(e) => return Err(e),

View File

@ -42,7 +42,7 @@ use winapi::{
}, },
wintrust::{ wintrust::{
WinVerifyTrust, WINTRUST_DATA, WINTRUST_FILE_INFO, WTD_CHOICE_FILE, WTD_REVOKE_NONE, WinVerifyTrust, WINTRUST_DATA, WINTRUST_FILE_INFO, WTD_CHOICE_FILE, WTD_REVOKE_NONE,
WTD_STATEACTION_VERIFY, WTD_UI_NONE, WTD_STATEACTION_CLOSE, WTD_STATEACTION_VERIFY, WTD_UI_NONE,
}, },
}, },
}; };
@ -425,34 +425,40 @@ fn validate_sha256(data: &[u8], expected: &str) -> Result<(), SelfUpdateError> {
fn verify_signature(file: &str) -> Result<(), VerifySignatureError> { fn verify_signature(file: &str) -> Result<(), VerifySignatureError> {
let file_osstr = U16CString::from_str_truncate(file); let file_osstr = U16CString::from_str_truncate(file);
let mut verification_type = WINTRUST_ACTION_GENERIC_VERIFY_V2; let mut verification_type = WINTRUST_ACTION_GENERIC_VERIFY_V2;
let mut wintrust_data_buf = vec![0u8; mem::size_of::<WINTRUST_DATA>()];
let mut fileinfo_buf = vec![0u8; mem::size_of::<WINTRUST_FILE_INFO>()];
unsafe { unsafe {
let fileinfo = fileinfo_buf.as_mut_ptr() as *mut WINTRUST_FILE_INFO; let mut fileinfo = mem::zeroed::<WINTRUST_FILE_INFO>();
let wintrust_data = wintrust_data_buf.as_mut_ptr() as *mut WINTRUST_DATA; let mut wintrust_data = mem::zeroed::<WINTRUST_DATA>();
(*fileinfo).cbStruct = mem::size_of::<WINTRUST_FILE_INFO>() as u32; fileinfo.cbStruct = mem::size_of::<WINTRUST_FILE_INFO>() as u32;
(*fileinfo).pcwszFilePath = file_osstr.as_ptr(); fileinfo.pcwszFilePath = file_osstr.as_ptr();
(*fileinfo).hFile = ptr::null_mut(); fileinfo.hFile = ptr::null_mut();
(*fileinfo).pgKnownSubject = ptr::null_mut(); fileinfo.pgKnownSubject = ptr::null_mut();
(*wintrust_data).pPolicyCallbackData = ptr::null_mut(); wintrust_data.pPolicyCallbackData = ptr::null_mut();
(*wintrust_data).pSIPClientData = ptr::null_mut(); wintrust_data.pSIPClientData = ptr::null_mut();
(*wintrust_data).cbStruct = mem::size_of::<WINTRUST_DATA>() as u32; wintrust_data.cbStruct = mem::size_of::<WINTRUST_DATA>() as u32;
(*wintrust_data).dwStateAction = WTD_STATEACTION_VERIFY; wintrust_data.dwStateAction = WTD_STATEACTION_VERIFY;
(*wintrust_data).dwUIChoice = WTD_UI_NONE; wintrust_data.dwUIChoice = WTD_UI_NONE;
(*wintrust_data).fdwRevocationChecks = WTD_REVOKE_NONE; wintrust_data.fdwRevocationChecks = WTD_REVOKE_NONE;
(*wintrust_data).dwUnionChoice = WTD_CHOICE_FILE; wintrust_data.dwUnionChoice = WTD_CHOICE_FILE;
(*wintrust_data).hWVTStateData = ptr::null_mut(); wintrust_data.hWVTStateData = ptr::null_mut();
(*wintrust_data).pwszURLReference = ptr::null_mut(); wintrust_data.pwszURLReference = ptr::null_mut();
(*wintrust_data).dwUIContext = 0; wintrust_data.dwUIContext = 0;
*(*wintrust_data).u.pFile_mut() = fileinfo; *wintrust_data.u.pFile_mut() = &mut fileinfo as *mut _;
let status = WinVerifyTrust( let status = WinVerifyTrust(
ptr::null_mut(), ptr::null_mut(),
&mut verification_type, &mut verification_type,
wintrust_data as *mut _, &mut wintrust_data as *mut _ as _,
);
wintrust_data.dwStateAction = WTD_STATEACTION_CLOSE;
WinVerifyTrust(
ptr::null_mut(),
&mut verification_type,
&mut wintrust_data as *mut _ as _,
); );
match status { match status {
@ -535,13 +541,14 @@ fn get_signature_pubkey(file: &str) -> Result<Vec<u8>, GetSignaturePubkeyError>
}); });
} }
let mut cert_search_params_buf = vec![0u8; mem::size_of::<CERT_INFO>()]; let cert_search_params = unsafe {
let cert_search_params = cert_search_params_buf.as_mut_ptr() as *mut CERT_INFO; let mut csp = mem::zeroed::<CERT_INFO>();
unsafe { csp.Issuer = (*signer_info).Issuer;
(*cert_search_params).Issuer = (*signer_info).Issuer; csp.SerialNumber = (*signer_info).SerialNumber;
(*cert_search_params).SerialNumber = (*signer_info).SerialNumber;
} csp
};
let cert = unsafe { let cert = unsafe {
CertFindCertificateInStore( CertFindCertificateInStore(
@ -549,7 +556,7 @@ fn get_signature_pubkey(file: &str) -> Result<Vec<u8>, GetSignaturePubkeyError>
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
0, 0,
CERT_FIND_SUBJECT_CERT, CERT_FIND_SUBJECT_CERT,
cert_search_params as *const _, &cert_search_params as *const _ as _,
ptr::null(), ptr::null(),
) )
}; };