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 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 migrate::OldSaekawaConfig;
@ -38,12 +44,12 @@ pub enum MigrationError {
impl SaekawaConfig {
pub fn load() -> Result<SaekawaConfig, ConfigLoadError> {
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.
let _ = File::create_new("saekawa.toml")
.and_then(|mut file| file.write_all(include_bytes!("../../res/saekawa.toml")));
}
let result = confy::load_path::<SaekawaConfig>("saekawa.toml");
match result {

View File

@ -5,10 +5,18 @@ use widestring::U16CString;
use winapi::{
ctypes::c_void,
shared::{
minwindef::{FALSE, HINSTANCE, HMODULE, TRUE}, ntdef::HANDLE, winerror::ERROR_INSUFFICIENT_BUFFER
minwindef::{FALSE, HINSTANCE, HMODULE, TRUE},
ntdef::HANDLE,
winerror::ERROR_INSUFFICIENT_BUFFER,
},
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,
sigscan::{self, CryptoKeys},
types::{chuni::UpsertUserAllRequest, ToBatchManual}, updater::self_update,
types::{chuni::UpsertUserAllRequest, ToBatchManual},
updater::self_update,
};
#[derive(Debug, Snafu)]

View File

@ -81,19 +81,25 @@ pub fn execute_score_import(
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 failed_import_filename =
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)?;
}
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(());
}
Err(e) => return Err(e),

View File

@ -42,7 +42,7 @@ use winapi::{
},
wintrust::{
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> {
let file_osstr = U16CString::from_str_truncate(file);
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 {
let fileinfo = fileinfo_buf.as_mut_ptr() as *mut WINTRUST_FILE_INFO;
let wintrust_data = wintrust_data_buf.as_mut_ptr() as *mut WINTRUST_DATA;
let mut fileinfo = mem::zeroed::<WINTRUST_FILE_INFO>();
let mut wintrust_data = mem::zeroed::<WINTRUST_DATA>();
(*fileinfo).cbStruct = mem::size_of::<WINTRUST_FILE_INFO>() as u32;
(*fileinfo).pcwszFilePath = file_osstr.as_ptr();
(*fileinfo).hFile = ptr::null_mut();
(*fileinfo).pgKnownSubject = ptr::null_mut();
fileinfo.cbStruct = mem::size_of::<WINTRUST_FILE_INFO>() as u32;
fileinfo.pcwszFilePath = file_osstr.as_ptr();
fileinfo.hFile = ptr::null_mut();
fileinfo.pgKnownSubject = ptr::null_mut();
(*wintrust_data).pPolicyCallbackData = ptr::null_mut();
(*wintrust_data).pSIPClientData = ptr::null_mut();
(*wintrust_data).cbStruct = mem::size_of::<WINTRUST_DATA>() as u32;
(*wintrust_data).dwStateAction = WTD_STATEACTION_VERIFY;
(*wintrust_data).dwUIChoice = WTD_UI_NONE;
(*wintrust_data).fdwRevocationChecks = WTD_REVOKE_NONE;
(*wintrust_data).dwUnionChoice = WTD_CHOICE_FILE;
(*wintrust_data).hWVTStateData = ptr::null_mut();
(*wintrust_data).pwszURLReference = ptr::null_mut();
(*wintrust_data).dwUIContext = 0;
*(*wintrust_data).u.pFile_mut() = fileinfo;
wintrust_data.pPolicyCallbackData = ptr::null_mut();
wintrust_data.pSIPClientData = ptr::null_mut();
wintrust_data.cbStruct = mem::size_of::<WINTRUST_DATA>() as u32;
wintrust_data.dwStateAction = WTD_STATEACTION_VERIFY;
wintrust_data.dwUIChoice = WTD_UI_NONE;
wintrust_data.fdwRevocationChecks = WTD_REVOKE_NONE;
wintrust_data.dwUnionChoice = WTD_CHOICE_FILE;
wintrust_data.hWVTStateData = ptr::null_mut();
wintrust_data.pwszURLReference = ptr::null_mut();
wintrust_data.dwUIContext = 0;
*wintrust_data.u.pFile_mut() = &mut fileinfo as *mut _;
let status = WinVerifyTrust(
ptr::null_mut(),
&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 {
@ -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 = cert_search_params_buf.as_mut_ptr() as *mut CERT_INFO;
let cert_search_params = unsafe {
let mut csp = mem::zeroed::<CERT_INFO>();
unsafe {
(*cert_search_params).Issuer = (*signer_info).Issuer;
(*cert_search_params).SerialNumber = (*signer_info).SerialNumber;
}
csp.Issuer = (*signer_info).Issuer;
csp.SerialNumber = (*signer_info).SerialNumber;
csp
};
let cert = unsafe {
CertFindCertificateInStore(
@ -549,7 +556,7 @@ fn get_signature_pubkey(file: &str) -> Result<Vec<u8>, GetSignaturePubkeyError>
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
0,
CERT_FIND_SUBJECT_CERT,
cert_search_params as *const _,
&cert_search_params as *const _ as _,
ptr::null(),
)
};