mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
[md5sum] Add md5sum.txt creation and runtime UEFI validation
* This allows *runtime* validation of UEFI bootable media, such as Windows or Linux installers, which, considering the unreliability of USB flash drives, we assert is a a much better proposal than write-time validation that utilities like balenaEcther (and to a lesser extent MCT) provide. * Based on uefi-md5sum (https://github.com/pbatard/uefi-md5sum). * Unconditionally activated on ISO extraction for GPT targets for now. This will be changed to a user selectable option later.
This commit is contained in:
parent
b7568ab30a
commit
52ca79816f
7 changed files with 272 additions and 126 deletions
10
src/format.c
10
src/format.c
|
@ -71,6 +71,7 @@ static float format_percent = 0.0f;
|
|||
static int task_number = 0, actual_fs_type;
|
||||
static unsigned int sec_buf_pos = 0;
|
||||
extern const int nb_steps[FS_MAX];
|
||||
extern const char* md5sum_name[2];
|
||||
extern uint32_t dur_mins, dur_secs;
|
||||
extern uint32_t wim_nb_files, wim_proc_files, wim_extra_files;
|
||||
extern BOOL force_large_fat32, enable_ntfs_compression, lock_drive, zero_drive, fast_zeroing, enable_file_indexing;
|
||||
|
@ -1035,11 +1036,11 @@ BOOL WritePBR(HANDLE hLogicalVolume)
|
|||
uprintf(using_msg, bt_to_name(), "FAT32");
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (!is_fat_32_fs(fp)) {
|
||||
uprintf("New volume does not have a %s FAT32 boot sector - aborting", i?"secondary":"primary");
|
||||
uprintf("New volume does not have a %s FAT32 boot sector - aborting", i ? "secondary" : "primary");
|
||||
break;
|
||||
}
|
||||
uprintf("Confirmed new volume has a %s FAT32 boot sector", i?"secondary":"primary");
|
||||
uprintf("Setting %s FAT32 boot sector for boot...", i?"secondary":"primary");
|
||||
uprintf("Confirmed new volume has a %s FAT32 boot sector", i ? "secondary" : "primary");
|
||||
uprintf("Setting %s FAT32 boot sector for boot...", i ? "secondary" : "primary");
|
||||
if (boot_type == BT_FREEDOS) {
|
||||
if (!write_fat_32_fd_br(fp, 0)) break;
|
||||
} else if (boot_type == BT_REACTOS) {
|
||||
|
@ -1964,8 +1965,11 @@ DWORD WINAPI FormatThread(void* param)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
UpdateProgress(OP_FINALIZE, -1.0f);
|
||||
PrintInfoDebug(0, MSG_233);
|
||||
if ((boot_type == BT_IMAGE) && (image_path != NULL) && (img_report.is_iso) && (!windows_to_go))
|
||||
UpdateMD5Sum(drive_name, md5sum_name[img_report.has_md5sum ? img_report.has_md5sum - 1 : 0]);
|
||||
if (IsChecked(IDC_EXTENDED_LABEL))
|
||||
SetAutorun(drive_name);
|
||||
// Issue another complete remount before we exit, to ensure we're clean
|
||||
|
|
144
src/hash.c
144
src/hash.c
|
@ -60,6 +60,7 @@
|
|||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
@ -103,14 +104,18 @@
|
|||
|
||||
/* Globals */
|
||||
char hash_str[HASH_MAX][150];
|
||||
uint32_t proc_bufnum, hash_count[HASH_MAX] = { MD5_HASHSIZE, SHA1_HASHSIZE, SHA256_HASHSIZE, SHA512_HASHSIZE };
|
||||
HANDLE data_ready[HASH_MAX] = { 0 }, thread_ready[HASH_MAX] = { 0 };
|
||||
DWORD read_size[NUM_BUFFERS];
|
||||
BOOL enable_extra_hashes = FALSE;
|
||||
BOOL enable_extra_hashes = FALSE, validate_md5sum = FALSE;
|
||||
uint8_t ALIGNED(64) buffer[NUM_BUFFERS][BUFFER_SIZE];
|
||||
extern int default_thread_priority;
|
||||
uint32_t pe256ssp_size = 0;
|
||||
uint8_t* pe256ssp = NULL;
|
||||
uint32_t proc_bufnum, hash_count[HASH_MAX] = { MD5_HASHSIZE, SHA1_HASHSIZE, SHA256_HASHSIZE, SHA512_HASHSIZE };
|
||||
uint32_t pe256ssp_size = 0;
|
||||
uint64_t md5sum_totalbytes;
|
||||
StrArray modified_files = { 0 };
|
||||
|
||||
extern int default_thread_priority;
|
||||
extern const char* efi_bootname[ARCH_MAX];
|
||||
|
||||
/*
|
||||
* Rotate 32 or 64 bit integers by n bytes.
|
||||
|
@ -2122,6 +2127,137 @@ void PrintRevokedBootloaderInfo(void)
|
|||
uprintf("WARNING: Could not parse this system's SkuSiPolicy.p7b for additional revoked UEFI bootloaders");
|
||||
}
|
||||
|
||||
/*
|
||||
* Updates the MD5SUMS/md5sum.txt file that some distros (Ubuntu, Mint...)
|
||||
* use to validate the media. Because we may alter some of the validated files
|
||||
* to add persistence and whatnot, we need to alter the MD5 list as a result.
|
||||
* The format of the file is expected to always be "<MD5SUM> <FILE_PATH>" on
|
||||
* individual lines.
|
||||
* This function is also used to finalize the md5sum.txt we create for use with
|
||||
* our uefi-md5sum bootloaders.
|
||||
*/
|
||||
void UpdateMD5Sum(const char* dest_dir, const char* md5sum_name)
|
||||
{
|
||||
BOOL display_header = TRUE;
|
||||
BYTE* res_data;
|
||||
DWORD res_size;
|
||||
HANDLE hFile;
|
||||
intptr_t pos;
|
||||
uint32_t i, j, size, md5_size, new_size;
|
||||
uint8_t sum[MD5_HASHSIZE];
|
||||
char md5_path[64], path1[64], path2[64], *md5_data = NULL, *new_data = NULL, *str_pos;
|
||||
char *d, *s, *p;
|
||||
|
||||
if (!img_report.has_md5sum && !validate_md5sum)
|
||||
goto out;
|
||||
|
||||
static_sprintf(md5_path, "%s\\%s", dest_dir, md5sum_name);
|
||||
md5_size = read_file(md5_path, (uint8_t**)&md5_data);
|
||||
if (md5_size == 0)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < modified_files.Index; i++) {
|
||||
for (j = 0; j < (uint32_t)strlen(modified_files.String[i]); j++)
|
||||
if (modified_files.String[i][j] == '\\')
|
||||
modified_files.String[i][j] = '/';
|
||||
str_pos = strstr(md5_data, &modified_files.String[i][2]);
|
||||
if (str_pos == NULL)
|
||||
// File is not listed in md5 sums
|
||||
continue;
|
||||
if (display_header) {
|
||||
uprintf("Updating %s:", md5_path);
|
||||
display_header = FALSE;
|
||||
}
|
||||
uprintf("● %s", &modified_files.String[i][2]);
|
||||
pos = str_pos - md5_data;
|
||||
HashFile(HASH_MD5, modified_files.String[i], sum);
|
||||
while ((pos > 0) && (md5_data[pos - 1] != '\n'))
|
||||
pos--;
|
||||
assert(IS_HEXASCII(md5_data[pos]));
|
||||
for (j = 0; j < 16; j++) {
|
||||
md5_data[pos + 2 * j] = ((sum[j] >> 4) < 10) ? ('0' + (sum[j] >> 4)) : ('a' - 0xa + (sum[j] >> 4));
|
||||
md5_data[pos + 2 * j + 1] = ((sum[j] & 15) < 10) ? ('0' + (sum[j] & 15)) : ('a' - 0xa + (sum[j] & 15));
|
||||
}
|
||||
}
|
||||
|
||||
// If we validate md5sum we need to update the original bootloader names and add md5sum_totalbytes
|
||||
if (validate_md5sum) {
|
||||
new_size = md5_size;
|
||||
new_data = malloc(md5_size + 1024);
|
||||
assert(new_data != NULL);
|
||||
if (new_data == NULL)
|
||||
goto out;
|
||||
// Will be nonzero if we created the file, otherwise zero
|
||||
if (md5sum_totalbytes != 0) {
|
||||
snprintf(new_data, md5_size + 1024, "# md5sum_totalbytes = 0x%llx\n", md5sum_totalbytes);
|
||||
new_size += (uint32_t)strlen(new_data);
|
||||
d = &new_data[strlen(new_data)];
|
||||
} else {
|
||||
d = new_data;
|
||||
}
|
||||
s = md5_data;
|
||||
for (p = md5_data; (p = StrStrIA(p, " ./efi/boot/boot")) != NULL; ) {
|
||||
for (i = 1; i < ARRAYSIZE(efi_bootname); i++) {
|
||||
if (p[12 + strlen(efi_bootname[i])] != 0x0a)
|
||||
continue;
|
||||
p[12 + strlen(efi_bootname[i])] = 0;
|
||||
if (lstrcmpiA(&p[12], efi_bootname[i]) == 0) {
|
||||
res_data = (BYTE*)GetResource(hMainInstance, MAKEINTRESOURCEA(IDR_MD5_BOOT + i),
|
||||
_RT_RCDATA, efi_bootname[i], &res_size, FALSE);
|
||||
static_sprintf(path1, "%s\\%s", dest_dir, &p[3]);
|
||||
for (j = 0; j < strlen(path1); j++)
|
||||
if (path1[j] == '/') path1[j] = '\\';
|
||||
static_strcpy(path2, path1);
|
||||
path2[strlen(path2) - 4] = 0;
|
||||
static_strcat(path2, "_original.efi");
|
||||
if (res_data != NULL && MoveFileU(path1, path2)) {
|
||||
uprintf("Renamed: %s → %s", path1, path2);
|
||||
hFile = CreateFileA(path1, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL,
|
||||
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if ((hFile == NULL) || (hFile == INVALID_HANDLE_VALUE)) {
|
||||
uprintf("Could not create '%s': %s.", path1, WindowsErrorString());
|
||||
MoveFileU(path2, path1);
|
||||
continue;
|
||||
}
|
||||
if (!WriteFileWithRetry(hFile, res_data, res_size, NULL, WRITE_RETRIES)) {
|
||||
uprintf("Could not write '%s': %s.", path1, WindowsErrorString());
|
||||
safe_closehandle(hFile);
|
||||
MoveFileU(path2, path1);
|
||||
continue;
|
||||
}
|
||||
safe_closehandle(hFile);
|
||||
uprintf("Created: %s (%s)", path1, SizeToHumanReadable(res_size, FALSE, FALSE));
|
||||
size = (uint32_t)(p - s) + 12 + (uint32_t)strlen(efi_bootname[i]) - 4;
|
||||
memcpy(d, s, size);
|
||||
d = &d[size];
|
||||
strcpy(d, "_original.efi\n");
|
||||
new_size += 9;
|
||||
d = &d[14];
|
||||
s = &p[12 + strlen(efi_bootname[i]) + 1];
|
||||
// TODO: Update sources/boot.wim if we modified it
|
||||
// Also, we'll need to keep a copy of the size of boot.wim BEFORE we alter it
|
||||
// so we can adjust md5sum_totalbytes
|
||||
}
|
||||
}
|
||||
p[12 + strlen(efi_bootname[i])] = 0x0a;
|
||||
}
|
||||
p = &p[12];
|
||||
}
|
||||
p = &md5_data[md5_size];
|
||||
memcpy(d, s, p - s);
|
||||
free(md5_data);
|
||||
md5_data = new_data;
|
||||
md5_size = new_size;
|
||||
}
|
||||
|
||||
write_file(md5_path, md5_data, md5_size);
|
||||
free(md5_data);
|
||||
|
||||
out:
|
||||
// We no longer need the string array at this stage
|
||||
StrArrayDestroy(&modified_files);
|
||||
}
|
||||
|
||||
#if defined(_DEBUG) || defined(TEST) || defined(ALPHA)
|
||||
/* Convert a lowercase hex string to binary. Returned value must be freed */
|
||||
uint8_t* to_bin(const char* str)
|
||||
|
|
157
src/iso.c
157
src/iso.c
|
@ -82,8 +82,10 @@ typedef struct {
|
|||
|
||||
RUFUS_IMG_REPORT img_report;
|
||||
int64_t iso_blocking_status = -1;
|
||||
extern BOOL preserve_timestamps, enable_ntfs_compression;
|
||||
extern uint64_t md5sum_totalbytes;
|
||||
extern BOOL preserve_timestamps, enable_ntfs_compression, validate_md5sum;
|
||||
extern HANDLE format_thread;
|
||||
extern StrArray modified_files;
|
||||
BOOL enable_iso = TRUE, enable_joliet = TRUE, enable_rockridge = TRUE, has_ldlinux_c32;
|
||||
#define ISO_BLOCKING(x) do {x; iso_blocking_status++; } while(0)
|
||||
static const char* psz_extract_dir;
|
||||
|
@ -92,7 +94,7 @@ const char* bootmgr_efi_name = "bootmgr.efi";
|
|||
static const char* grldr_name = "grldr";
|
||||
static const char* ldlinux_name = "ldlinux.sys";
|
||||
static const char* ldlinux_c32 = "ldlinux.c32";
|
||||
static const char* md5sum_name[] = { "MD5SUMS", "md5sum.txt" };
|
||||
const char* md5sum_name[2] = { "md5sum.txt", "MD5SUMS" };
|
||||
static const char* casper_dirname = "/casper";
|
||||
static const char* proxmox_dirname = "/proxmox";
|
||||
const char* efi_dirname = "/efi/boot";
|
||||
|
@ -124,7 +126,8 @@ static const int64_t old_c32_threshold[NB_OLD_C32] = OLD_C32_THRESHOLD;
|
|||
static uint8_t joliet_level = 0;
|
||||
static uint64_t total_blocks, extra_blocks, nb_blocks, last_nb_blocks;
|
||||
static BOOL scan_only = FALSE;
|
||||
static StrArray config_path, isolinux_path, modified_path;
|
||||
static FILE* fd_md5sum = NULL;
|
||||
static StrArray config_path, isolinux_path;
|
||||
static char symlinked_syslinux[MAX_PATH];
|
||||
|
||||
// Ensure filenames do not contain invalid FAT32 or NTFS characters
|
||||
|
@ -475,66 +478,11 @@ static void fix_config(const char* psz_fullpath, const char* psz_path, const cha
|
|||
}
|
||||
|
||||
if (modified)
|
||||
StrArrayAdd(&modified_path, psz_fullpath, TRUE);
|
||||
StrArrayAdd(&modified_files, psz_fullpath, TRUE);
|
||||
|
||||
free(src);
|
||||
}
|
||||
|
||||
// This updates the MD5SUMS/md5sum.txt file that some distros (Ubuntu, Mint...)
|
||||
// use to validate the media. Because we may alter some of the validated files
|
||||
// to add persistence and whatnot, we need to alter the MD5 list as a result.
|
||||
// The format of the file is expected to always be "<MD5SUM> <FILE_PATH>" on
|
||||
// individual lines.
|
||||
static void update_md5sum(void)
|
||||
{
|
||||
BOOL display_header = TRUE;
|
||||
intptr_t pos;
|
||||
uint32_t i, j, size, md5_size;
|
||||
uint8_t* buf = NULL, sum[16];
|
||||
char md5_path[64], * md5_data = NULL, * str_pos;
|
||||
|
||||
if (!img_report.has_md5sum)
|
||||
goto out;
|
||||
|
||||
assert(img_report.has_md5sum <= ARRAYSIZE(md5sum_name));
|
||||
if (img_report.has_md5sum > ARRAYSIZE(md5sum_name))
|
||||
goto out;
|
||||
|
||||
static_sprintf(md5_path, "%s\\%s", psz_extract_dir, md5sum_name[img_report.has_md5sum - 1]);
|
||||
md5_size = read_file(md5_path, (uint8_t**)&md5_data);
|
||||
if (md5_size == 0)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < modified_path.Index; i++) {
|
||||
str_pos = strstr(md5_data, &modified_path.String[i][2]);
|
||||
if (str_pos == NULL)
|
||||
// File is not listed in md5 sums
|
||||
continue;
|
||||
if (display_header) {
|
||||
uprintf("Updating %s:", md5_path);
|
||||
display_header = FALSE;
|
||||
}
|
||||
uprintf("● %s", &modified_path.String[i][2]);
|
||||
pos = str_pos - md5_data;
|
||||
size = read_file(modified_path.String[i], &buf);
|
||||
if (size == 0)
|
||||
continue;
|
||||
HashBuffer(HASH_MD5, buf, size, sum);
|
||||
free(buf);
|
||||
while ((pos > 0) && (md5_data[pos - 1] != '\n'))
|
||||
pos--;
|
||||
for (j = 0; j < 16; j++) {
|
||||
md5_data[pos + 2 * j] = ((sum[j] >> 4) < 10) ? ('0' + (sum[j] >> 4)) : ('a' - 0xa + (sum[j] >> 4));
|
||||
md5_data[pos + 2 * j + 1] = ((sum[j] & 15) < 10) ? ('0' + (sum[j] & 15)) : ('a' - 0xa + (sum[j] & 15));
|
||||
}
|
||||
}
|
||||
|
||||
write_file(md5_path, md5_data, md5_size);
|
||||
free(md5_data);
|
||||
|
||||
out:
|
||||
StrArrayDestroy(&modified_path);
|
||||
}
|
||||
|
||||
static void print_extracted_file(char* psz_fullpath, uint64_t file_length)
|
||||
{
|
||||
|
@ -586,9 +534,10 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha
|
|||
HANDLE file_handle = NULL;
|
||||
DWORD buf_size, wr_size, err;
|
||||
EXTRACT_PROPS props;
|
||||
HASH_CONTEXT ctx;
|
||||
BOOL r, is_identical;
|
||||
int length;
|
||||
size_t i, nb;
|
||||
size_t i, j, nb;
|
||||
char tmp[128], *psz_fullpath = NULL, *psz_sanpath = NULL;
|
||||
const char* psz_basename;
|
||||
udf_dirent_t *p_udf_dirent2;
|
||||
|
@ -669,16 +618,22 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha
|
|||
else
|
||||
goto out;
|
||||
} else {
|
||||
if (fd_md5sum != NULL)
|
||||
hash_init[HASH_MD5](&ctx);
|
||||
while (file_length > 0) {
|
||||
if (FormatStatus)
|
||||
goto out;
|
||||
nb = MIN(ISO_BUFFER_SIZE / UDF_BLOCKSIZE, (file_length + UDF_BLOCKSIZE - 1) / UDF_BLOCKSIZE);
|
||||
nb = (size_t)MIN(ISO_BUFFER_SIZE / UDF_BLOCKSIZE, (file_length + UDF_BLOCKSIZE - 1) / UDF_BLOCKSIZE);
|
||||
read = udf_read_block(p_udf_dirent, buf, nb);
|
||||
if (read < 0) {
|
||||
uprintf(" Error reading UDF file %s", &psz_fullpath[strlen(psz_extract_dir)]);
|
||||
goto out;
|
||||
}
|
||||
buf_size = (DWORD)MIN(file_length, read);
|
||||
if (fd_md5sum != NULL) {
|
||||
md5sum_totalbytes += buf_size;
|
||||
hash_write[HASH_MD5](&ctx, buf, buf_size);
|
||||
}
|
||||
ISO_BLOCKING(r = WriteFileWithRetry(file_handle, buf, buf_size, &wr_size, WRITE_RETRIES));
|
||||
if (!r || (wr_size != buf_size)) {
|
||||
uprintf(" Error writing file: %s", r ? "Short write detected" : WindowsErrorString());
|
||||
|
@ -691,6 +646,12 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha
|
|||
last_nb_blocks = nb_blocks;
|
||||
}
|
||||
}
|
||||
if (fd_md5sum != NULL) {
|
||||
hash_final[HASH_MD5](&ctx);
|
||||
for (j = 0; j < MD5_HASHSIZE; j++)
|
||||
fprintf(fd_md5sum, "%02x", ctx.buf[j]);
|
||||
fprintf(fd_md5sum, " ./%s\n", &psz_fullpath[3]);
|
||||
}
|
||||
}
|
||||
if ((preserve_timestamps) && (!SetFileTime(file_handle, to_filetime(udf_get_attribute_time(p_udf_dirent)),
|
||||
to_filetime(udf_get_access_time(p_udf_dirent)), to_filetime(udf_get_modification_time(p_udf_dirent)))))
|
||||
|
@ -726,6 +687,7 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
|
|||
HANDLE file_handle = NULL;
|
||||
DWORD buf_size, wr_size, err;
|
||||
EXTRACT_PROPS props;
|
||||
HASH_CONTEXT ctx;
|
||||
BOOL is_symlink, is_identical, create_file, free_p_statbuf = FALSE;
|
||||
int length, r = 1;
|
||||
char psz_fullpath[MAX_PATH], *psz_basename = NULL, *psz_sanpath = NULL;
|
||||
|
@ -737,7 +699,7 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
|
|||
CdioListNode_t* p_entnode;
|
||||
iso9660_stat_t *p_statbuf;
|
||||
CdioISO9660FileList_t* p_entlist = NULL;
|
||||
size_t i, nb;
|
||||
size_t i, j, nb;
|
||||
lsn_t lsn;
|
||||
int64_t file_length;
|
||||
|
||||
|
@ -921,28 +883,42 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
|
|||
uprintf(" Error writing file: %s", WindowsErrorString());
|
||||
goto out;
|
||||
}
|
||||
} else for (i = 0; file_length > 0; i += nb) {
|
||||
if (FormatStatus)
|
||||
goto out;
|
||||
lsn = p_statbuf->lsn + (lsn_t)i;
|
||||
nb = MIN(ISO_BUFFER_SIZE / ISO_BLOCKSIZE, (file_length + ISO_BLOCKSIZE - 1) / ISO_BLOCKSIZE);
|
||||
if (iso9660_iso_seek_read(p_iso, buf, lsn, (long)nb) != (nb * ISO_BLOCKSIZE)) {
|
||||
uprintf(" Error reading ISO9660 file %s at LSN %lu",
|
||||
psz_iso_name, (long unsigned int)lsn);
|
||||
goto out;
|
||||
} else {
|
||||
if (fd_md5sum != NULL)
|
||||
hash_init[HASH_MD5](&ctx);
|
||||
for (i = 0; file_length > 0; i += nb) {
|
||||
if (FormatStatus)
|
||||
goto out;
|
||||
lsn = p_statbuf->lsn + (lsn_t)i;
|
||||
nb = (size_t)MIN(ISO_BUFFER_SIZE / ISO_BLOCKSIZE, (file_length + ISO_BLOCKSIZE - 1) / ISO_BLOCKSIZE);
|
||||
if (iso9660_iso_seek_read(p_iso, buf, lsn, (long)nb) != (nb * ISO_BLOCKSIZE)) {
|
||||
uprintf(" Error reading ISO9660 file %s at LSN %lu",
|
||||
psz_iso_name, (long unsigned int)lsn);
|
||||
goto out;
|
||||
}
|
||||
buf_size = (DWORD)MIN(file_length, ISO_BUFFER_SIZE);
|
||||
if (fd_md5sum != NULL) {
|
||||
md5sum_totalbytes += buf_size;
|
||||
hash_write[HASH_MD5](&ctx, buf, buf_size);
|
||||
}
|
||||
ISO_BLOCKING(r = WriteFileWithRetry(file_handle, buf, buf_size, &wr_size, WRITE_RETRIES));
|
||||
if (!r || wr_size != buf_size) {
|
||||
uprintf(" Error writing file: %s", r ? "Short write detected" : WindowsErrorString());
|
||||
goto out;
|
||||
}
|
||||
file_length -= wr_size;
|
||||
nb_blocks += nb;
|
||||
if (nb_blocks - last_nb_blocks >= PROGRESS_THRESHOLD) {
|
||||
UpdateProgressWithInfo(OP_FILE_COPY, MSG_231, nb_blocks, total_blocks +
|
||||
((fs_type != FS_NTFS) ? extra_blocks : 0));
|
||||
last_nb_blocks = nb_blocks;
|
||||
}
|
||||
}
|
||||
buf_size = (DWORD)MIN(file_length, ISO_BUFFER_SIZE);
|
||||
ISO_BLOCKING(r = WriteFileWithRetry(file_handle, buf, buf_size, &wr_size, WRITE_RETRIES));
|
||||
if (!r || wr_size != buf_size) {
|
||||
uprintf(" Error writing file: %s", r ? "Short write detected" : WindowsErrorString());
|
||||
goto out;
|
||||
}
|
||||
file_length -= wr_size;
|
||||
nb_blocks += nb;
|
||||
if (nb_blocks - last_nb_blocks >= PROGRESS_THRESHOLD) {
|
||||
UpdateProgressWithInfo(OP_FILE_COPY, MSG_231, nb_blocks, total_blocks +
|
||||
((fs_type != FS_NTFS) ? extra_blocks : 0));
|
||||
last_nb_blocks = nb_blocks;
|
||||
if (fd_md5sum != NULL) {
|
||||
hash_final[HASH_MD5](&ctx);
|
||||
for (j = 0; j < MD5_HASHSIZE; j++)
|
||||
fprintf(fd_md5sum, "%02x", ctx.buf[j]);
|
||||
fprintf(fd_md5sum, " ./%s\n", &psz_fullpath[3]);
|
||||
}
|
||||
}
|
||||
if (preserve_timestamps) {
|
||||
|
@ -1098,7 +1074,17 @@ BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan)
|
|||
last_nb_blocks = 0;
|
||||
iso_blocking_status = 0;
|
||||
symlinked_syslinux[0] = 0;
|
||||
StrArrayCreate(&modified_path, 8);
|
||||
StrArrayCreate(&modified_files, 8);
|
||||
if (validate_md5sum) {
|
||||
md5sum_totalbytes = 0;
|
||||
// If there isn't an already existing md5sum.txt create one
|
||||
if (img_report.has_md5sum != 1) {
|
||||
static_sprintf(path, "%s\\%s", dest_dir, md5sum_name[0]);
|
||||
fd_md5sum = fopenU(path, "wb");
|
||||
if (fd_md5sum == NULL)
|
||||
uprintf("WARNING: Could not create '%s'", md5sum_name[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// First try to open as UDF - fallback to ISO if it failed
|
||||
|
@ -1397,7 +1383,8 @@ out:
|
|||
uprintf("Could not move %s → %s", path, dst_path, WindowsErrorString());
|
||||
}
|
||||
}
|
||||
update_md5sum();
|
||||
if (fd_md5sum != NULL)
|
||||
fclose(fd_md5sum);
|
||||
}
|
||||
iso9660_close(p_iso);
|
||||
udf_close(p_udf);
|
||||
|
|
|
@ -94,6 +94,7 @@ static char uppercase_select[2][64], uppercase_start[64], uppercase_close[64], u
|
|||
|
||||
extern HANDLE update_check_thread, wim_thread;
|
||||
extern BOOL enable_iso, enable_joliet, enable_rockridge, enable_extra_hashes, is_bootloader_revoked;
|
||||
extern BOOL validate_md5sum;
|
||||
extern BYTE* fido_script;
|
||||
extern HWND hFidoDlg;
|
||||
extern uint8_t* grub2_buf;
|
||||
|
@ -1441,6 +1442,7 @@ static DWORD WINAPI BootCheckThread(LPVOID param)
|
|||
|
||||
syslinux_ldlinux_len[0] = 0; syslinux_ldlinux_len[1] = 0;
|
||||
is_bootloader_revoked = FALSE;
|
||||
validate_md5sum = FALSE;
|
||||
safe_free(grub2_buf);
|
||||
|
||||
if (ComboBox_GetCurSel(hDeviceList) == CB_ERR)
|
||||
|
@ -1567,6 +1569,9 @@ static DWORD WINAPI BootCheckThread(LPVOID param)
|
|||
ShellExecuteA(hMainDialog, "open", SEVENZIP_URL, NULL, NULL, SW_SHOWNORMAL);
|
||||
goto out;
|
||||
}
|
||||
// TODO: Move this option to a user selection
|
||||
validate_md5sum = TRUE;
|
||||
uprintf("Will add runtime UEFI media validation through 'md5sum.txt'");
|
||||
} else if ( ((fs_type == FS_NTFS) && !HAS_WINDOWS(img_report) && !HAS_GRUB(img_report) &&
|
||||
(!HAS_SYSLINUX(img_report) || (SL_MAJOR(img_report.sl_version) <= 5)))
|
||||
|| ((IS_FAT(fs_type)) && (!HAS_SYSLINUX(img_report)) && (!allow_dual_uefi_bios) && !IS_EFI_BOOTABLE(img_report) &&
|
||||
|
|
59
src/rufus.h
59
src/rufus.h
|
@ -625,6 +625,35 @@ typedef struct {
|
|||
#define UNATTEND_OFFLINE_SERVICING_MASK (UNATTEND_OFFLINE_INTERNAL_DRIVES | UNATTEND_FORCE_S_MODE)
|
||||
#define UNATTEND_DEFAULT_SELECTION_MASK (UNATTEND_SECUREBOOT_TPM_MINRAM | UNATTEND_NO_ONLINE_ACCOUNT | UNATTEND_OFFLINE_INTERNAL_DRIVES)
|
||||
|
||||
/* Hash tables */
|
||||
typedef struct htab_entry {
|
||||
uint32_t used;
|
||||
char* str;
|
||||
void* data;
|
||||
} htab_entry;
|
||||
typedef struct htab_table {
|
||||
htab_entry* table;
|
||||
uint32_t size;
|
||||
uint32_t filled;
|
||||
} htab_table;
|
||||
#define HTAB_EMPTY {NULL, 0, 0}
|
||||
extern BOOL htab_create(uint32_t nel, htab_table* htab);
|
||||
extern void htab_destroy(htab_table* htab);
|
||||
extern uint32_t htab_hash(char* str, htab_table* htab);
|
||||
|
||||
/* Basic String Array */
|
||||
typedef struct {
|
||||
char** String;
|
||||
uint32_t Index; // Current array size
|
||||
uint32_t Max; // Maximum array size
|
||||
} StrArray;
|
||||
extern void StrArrayCreate(StrArray* arr, uint32_t initial_size);
|
||||
extern int32_t StrArrayAdd(StrArray* arr, const char* str, BOOL);
|
||||
extern int32_t StrArrayFind(StrArray* arr, const char* str);
|
||||
extern void StrArrayClear(StrArray* arr);
|
||||
extern void StrArrayDestroy(StrArray* arr);
|
||||
#define IsStrArrayEmpty(arr) (arr.Index == 0)
|
||||
|
||||
/*
|
||||
* Globals
|
||||
*/
|
||||
|
@ -758,6 +787,7 @@ extern HANDLE CreateFileWithTimeout(LPCSTR lpFileName, DWORD dwDesiredAccess, DW
|
|||
extern BOOL SetThreadAffinity(DWORD_PTR* thread_affinity, size_t num_threads);
|
||||
extern BOOL HashFile(const unsigned type, const char* path, uint8_t* sum);
|
||||
extern BOOL PE256File(const char* path, uint8_t* hash);
|
||||
extern void UpdateMD5Sum(const char* dest_dir, const char* md5sum_name);
|
||||
extern BOOL HashBuffer(const unsigned type, const uint8_t* buf, const size_t len, uint8_t* sum);
|
||||
extern BOOL IsFileInDB(const char* path);
|
||||
extern int IsBootloaderRevoked(const char* path);
|
||||
|
@ -787,35 +817,6 @@ extern uint32_t ResolveDllAddress(dll_resolver_t* resolver);
|
|||
|
||||
DWORD WINAPI HashThread(void* param);
|
||||
|
||||
/* Hash tables */
|
||||
typedef struct htab_entry {
|
||||
uint32_t used;
|
||||
char* str;
|
||||
void* data;
|
||||
} htab_entry;
|
||||
typedef struct htab_table {
|
||||
htab_entry *table;
|
||||
uint32_t size;
|
||||
uint32_t filled;
|
||||
} htab_table;
|
||||
#define HTAB_EMPTY {NULL, 0, 0}
|
||||
extern BOOL htab_create(uint32_t nel, htab_table* htab);
|
||||
extern void htab_destroy(htab_table* htab);
|
||||
extern uint32_t htab_hash(char* str, htab_table* htab);
|
||||
|
||||
/* Basic String Array */
|
||||
typedef struct {
|
||||
char** String;
|
||||
uint32_t Index; // Current array size
|
||||
uint32_t Max; // Maximum array size
|
||||
} StrArray;
|
||||
extern void StrArrayCreate(StrArray* arr, uint32_t initial_size);
|
||||
extern int32_t StrArrayAdd(StrArray* arr, const char* str, BOOL );
|
||||
extern int32_t StrArrayFind(StrArray* arr, const char* str);
|
||||
extern void StrArrayClear(StrArray* arr);
|
||||
extern void StrArrayDestroy(StrArray* arr);
|
||||
#define IsStrArrayEmpty(arr) (arr.Index == 0)
|
||||
|
||||
/*
|
||||
* typedefs for the function prototypes. Use the something like:
|
||||
* PF_DECL(FormatEx);
|
||||
|
|
10
src/rufus.rc
10
src/rufus.rc
|
@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
|||
IDD_DIALOG DIALOGEX 12, 12, 232, 326
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
EXSTYLE WS_EX_ACCEPTFILES
|
||||
CAPTION "Rufus 4.5.2119"
|
||||
CAPTION "Rufus 4.5.2120"
|
||||
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
|
||||
BEGIN
|
||||
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
|
||||
|
@ -397,8 +397,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 4,5,2119,0
|
||||
PRODUCTVERSION 4,5,2119,0
|
||||
FILEVERSION 4,5,2120,0
|
||||
PRODUCTVERSION 4,5,2120,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -416,13 +416,13 @@ BEGIN
|
|||
VALUE "Comments", "https://rufus.ie"
|
||||
VALUE "CompanyName", "Akeo Consulting"
|
||||
VALUE "FileDescription", "Rufus"
|
||||
VALUE "FileVersion", "4.5.2119"
|
||||
VALUE "FileVersion", "4.5.2120"
|
||||
VALUE "InternalName", "Rufus"
|
||||
VALUE "LegalCopyright", "<22> 2011-2024 Pete Batard (GPL v3)"
|
||||
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
|
||||
VALUE "OriginalFilename", "rufus-4.5.exe"
|
||||
VALUE "ProductName", "Rufus"
|
||||
VALUE "ProductVersion", "4.5.2119"
|
||||
VALUE "ProductVersion", "4.5.2120"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
13
src/wue.c
13
src/wue.c
|
@ -47,6 +47,9 @@ char *unattend_xml_path = NULL, unattend_username[MAX_USERNAME_LENGTH];
|
|||
BOOL is_bootloader_revoked = FALSE;
|
||||
|
||||
extern uint32_t wim_nb_files, wim_proc_files, wim_extra_files;
|
||||
extern BOOL validate_md5sum;
|
||||
extern uint64_t md5sum_totalbytes;
|
||||
extern StrArray modified_files;
|
||||
|
||||
/// <summary>
|
||||
/// Create an installation answer file containing the sections specified by the flags.
|
||||
|
@ -808,6 +811,10 @@ BOOL ApplyWindowsCustomization(char drive_letter, int flags)
|
|||
CloseHandle(CreateFileU(appraiserres_dll_src, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ,
|
||||
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL));
|
||||
uprintf("Created '%s' placeholder", appraiserres_dll_src);
|
||||
if (validate_md5sum) {
|
||||
md5sum_totalbytes -= _filesizeU(appraiserres_dll_dst);
|
||||
StrArrayAdd(&modified_files, appraiserres_dll_src, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -815,6 +822,8 @@ BOOL ApplyWindowsCustomization(char drive_letter, int flags)
|
|||
// We only need to mount boot.wim if we have windowsPE data to deal with. If
|
||||
// not, we can just copy our unattend.xml in \sources\$OEM$\$$\Panther\.
|
||||
if (flags & UNATTEND_WINPE_SETUP_MASK) {
|
||||
if (validate_md5sum)
|
||||
md5sum_totalbytes -= _filesizeU(boot_wim_path);
|
||||
uprintf("Mounting '%s[%d]'...", boot_wim_path, wim_index);
|
||||
// Some "unofficial" ISOs have a modified boot.wim that doesn't have Windows Setup at index 2...
|
||||
if (!WimIsValidIndex(boot_wim_path, wim_index)) {
|
||||
|
@ -929,6 +938,10 @@ out:
|
|||
if (mount_path) {
|
||||
uprintf("Unmounting '%s[%d]'...", boot_wim_path, wim_index);
|
||||
WimUnmountImage(boot_wim_path, wim_index, TRUE);
|
||||
if (validate_md5sum) {
|
||||
md5sum_totalbytes += _filesizeU(boot_wim_path);
|
||||
StrArrayAdd(&modified_files, boot_wim_path, TRUE);
|
||||
}
|
||||
UpdateProgressWithInfo(OP_PATCH, MSG_325, PATCH_PROGRESS_TOTAL, PATCH_PROGRESS_TOTAL);
|
||||
}
|
||||
free(mount_path);
|
||||
|
|
Loading…
Reference in a new issue