From 4271e42b50eeddbc26f841d5b2bfca2d227af6fb Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Sat, 23 Mar 2019 13:59:20 +0000 Subject: [PATCH] [fido] download an LZMA compressed version of the script * Since we have compression available through Bled we might as well use it * Also validate that the download URL comes from https://github.com/pbatard/Fido * Also prevent the check for update from running while we are downloading ISOs --- src/bled/bled.c | 62 ++++++++++++++++++++++++++++++++++++++++++++---- src/bled/bled.h | 3 +++ src/bled/libbb.h | 13 +++++++++- src/net.c | 33 +++++++++++++++++++++----- src/rufus.h | 2 +- src/rufus.rc | 10 ++++---- src/stdlg.c | 9 +++++-- 7 files changed, 112 insertions(+), 20 deletions(-) diff --git a/src/bled/bled.c b/src/bled/bled.c index 8b3d47c0..3d4be7c4 100644 --- a/src/bled/bled.c +++ b/src/bled/bled.c @@ -25,6 +25,9 @@ progress_t bled_progress = NULL; unsigned long* bled_cancel_request; static bool bled_initialized = 0; jmp_buf bb_error_jmp; +char* bb_virtual_buf = NULL; +size_t bb_virtual_len = 0, bb_virtual_pos = 0; +int bb_virtual_fd = -1; static long long int unpack_none(transformer_state_t *xstate) { @@ -49,8 +52,10 @@ int64_t bled_uncompress(const char* src, const char* dst, int type) transformer_state_t xstate; int64_t ret; - if (!bled_initialized) + if (!bled_initialized) { + bb_error_msg("The library has not been initialized"); return -1; + } bb_total_rb = 0; init_transformer_state(&xstate); @@ -95,8 +100,10 @@ int64_t bled_uncompress_with_handles(HANDLE hSrc, HANDLE hDst, int type) { transformer_state_t xstate; - if (!bled_initialized) + if (!bled_initialized) { + bb_error_msg("The library has not been initialized"); return -1; + } bb_total_rb = 0; init_transformer_state(&xstate); @@ -132,8 +139,15 @@ int64_t bled_uncompress_to_buffer(const char* src, char* buf, size_t size, int t transformer_state_t xstate; int64_t ret; - if (!bled_initialized) + if (!bled_initialized) { + bb_error_msg("The library has not been initialized"); return -1; + } + + if ((src == NULL) || (buf == NULL)) { + bb_error_msg("Invalid parameter"); + return -1; + } bb_total_rb = 0; init_transformer_state(&xstate); @@ -141,7 +155,11 @@ int64_t bled_uncompress_to_buffer(const char* src, char* buf, size_t size, int t xstate.dst_fd = -1; xstate.check_signature = 1; - xstate.src_fd = _openU(src, _O_RDONLY | _O_BINARY, 0); + if (src[0] == 0) { + xstate.src_fd = bb_virtual_fd; + } else { + xstate.src_fd = _openU(src, _O_RDONLY | _O_BINARY, 0); + } if (xstate.src_fd < 0) { bb_error_msg("Could not open '%s' (errno: %d)", src, errno); goto err; @@ -159,7 +177,8 @@ int64_t bled_uncompress_to_buffer(const char* src, char* buf, size_t size, int t if (setjmp(bb_error_jmp)) goto err; ret = unpacker[type](&xstate); - _close(xstate.src_fd); + if (src[0] != 0) + _close(xstate.src_fd); return ret; err: @@ -168,6 +187,39 @@ err: return -1; } +int64_t bled_uncompress_from_buffer_to_buffer(const char* src, const size_t src_len, char* dst, size_t dst_len, int type) +{ + int64_t ret; + + if (!bled_initialized) { + bb_error_msg("The library has not been initialized"); + return -1; + } + + if ((src == NULL) || (dst == NULL)) { + bb_error_msg("Invalid parameter"); + return -1; + } + + if (bb_virtual_buf != NULL) { + bb_error_msg("Can not decompress more than one buffer at once"); + return -1; + } + + bb_virtual_buf = (char*)src; + bb_virtual_len = src_len; + bb_virtual_pos = 0; + bb_virtual_fd = 0; + + ret = bled_uncompress_to_buffer("", dst, dst_len, type); + + bb_virtual_buf = NULL; + bb_virtual_len = 0; + bb_virtual_fd = -1; + + return ret; +} + /* Initialize the library. * When the parameters are not NULL you can: * - specify the printf-like function you want to use to output message diff --git a/src/bled/bled.h b/src/bled/bled.h index fec3b4a8..6ec51ec0 100644 --- a/src/bled/bled.h +++ b/src/bled/bled.h @@ -39,6 +39,9 @@ int64_t bled_uncompress_with_handles(HANDLE hSrc, HANDLE hDst, int type); /* Uncompress file 'src', compressed using 'type', to buffer 'buf' of size 'size' */ int64_t bled_uncompress_to_buffer(const char* src, char* buf, size_t size, int type); +/* Uncompress buffer 'src' of length 'src_len' to buffer 'dst' of size 'dst_len' */ +int64_t bled_uncompress_from_buffer_to_buffer(const char* src, const size_t src_len, char* dst, size_t dst_len, int type); + /* Initialize the library. * When the parameters are not NULL you can: * - specify the printf-like function you want to use to output message diff --git a/src/bled/libbb.h b/src/bled/libbb.h index d6132ab5..faf71b9d 100644 --- a/src/bled/libbb.h +++ b/src/bled/libbb.h @@ -98,6 +98,9 @@ typedef unsigned int uid_t; extern smallint bb_got_signal; extern uint32_t *global_crc32_table; extern jmp_buf bb_error_jmp; +extern char* bb_virtual_buf; +extern size_t bb_virtual_len, bb_virtual_pos; +extern int bb_virtual_fd; uint32_t* crc32_filltable(uint32_t *crc_table, int endian); uint32_t crc32_le(uint32_t crc, unsigned char const *p, size_t len, uint32_t *crc32table_le); @@ -174,7 +177,15 @@ static inline int full_read(int fd, void *buf, size_t count) { return -1; } - rb = _read(fd, buf, (int)count); + if (fd == bb_virtual_fd) { + if (bb_virtual_pos + count > bb_virtual_len) + count = bb_virtual_len - bb_virtual_pos; + memcpy(buf, &bb_virtual_buf[bb_virtual_pos], count); + bb_virtual_pos += count; + rb = (int)count; + } else { + rb = _read(fd, buf, (int)count); + } if (rb > 0) { bb_total_rb += rb; if (bled_progress != NULL) diff --git a/src/net.c b/src/net.c index beda9ee5..923b08ce 100644 --- a/src/net.c +++ b/src/net.c @@ -36,6 +36,7 @@ #include "resource.h" #include "msapi_utf8.h" #include "localization.h" +#include "bled/bled.h" #include "settings.h" @@ -878,11 +879,14 @@ static DWORD WINAPI DownloadISOThread(LPVOID param) char locale_str[1024], cmdline[sizeof(locale_str) + 512], pipe[MAX_GUID_STRING_LENGTH + 16] = "\\\\.\\pipe\\"; char powershell_path[MAX_PATH], icon_path[MAX_PATH] = "", script_path[MAX_PATH] = ""; char *url = NULL, sig_url[128]; - BYTE *sig = NULL; + uint64_t uncompressed_size; + int64_t size = -1; + BYTE *compressed = NULL, *sig = NULL; HANDLE hFile, hPipe; - DWORD dwExitCode = 99, dwSize, dwAvail, dwPipeSize = 4096; + DWORD dwExitCode = 99, dwCompressedSize, dwSize, dwAvail, dwPipeSize = 4096; GUID guid; + dialog_showing++; IGNORE_RETVAL(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)); // Use a GUID as random unique string, else ill-intentioned security "researchers" @@ -903,22 +907,38 @@ static DWORD WINAPI DownloadISOThread(LPVOID param) #else // If we don't have the script, download it if (fido_script == NULL) { - fido_len = (DWORD)DownloadToFileOrBuffer(fido_url, NULL, &fido_script, hMainDialog, FALSE); - if (fido_len == 0) + dwCompressedSize = (DWORD)DownloadToFileOrBuffer(fido_url, NULL, &compressed, hMainDialog, FALSE); + if (dwCompressedSize == 0) goto out; static_sprintf(sig_url, "%s.sig", fido_url); dwSize = (DWORD)DownloadToFileOrBuffer(sig_url, NULL, &sig, NULL, FALSE); - if ((dwSize != RSA_SIGNATURE_SIZE) || (!ValidateOpensslSignature(fido_script, fido_len, sig, dwSize))) { + if ((dwSize != RSA_SIGNATURE_SIZE) || (!ValidateOpensslSignature(compressed, dwCompressedSize, sig, dwSize))) { uprintf("FATAL: Signature is invalid ✗"); FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_BAD_SIGNATURE); SendMessage(hProgress, PBM_SETSTATE, (WPARAM)PBST_ERROR, 0); SetTaskbarProgressState(TASKBAR_ERROR); - safe_free(fido_script); + safe_free(compressed); free(sig); goto out; } free(sig); uprintf("Signature is valid ✓"); + uncompressed_size = *((uint64_t*)&compressed[5]); + if ((uncompressed_size < 1 * MB) && (bled_init(_uprintf, NULL, &FormatStatus) >= 0)) { + fido_script = malloc((size_t)uncompressed_size); + size = bled_uncompress_from_buffer_to_buffer(compressed, dwCompressedSize, fido_script, (size_t)uncompressed_size, BLED_COMPRESSION_LZMA); + bled_exit(); + } + safe_free(compressed); + if (size != uncompressed_size) { + uprintf("FATAL: Could not uncompressed download script"); + safe_free(fido_script); + FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_INVALID_DATA; + SendMessage(hProgress, PBM_SETSTATE, (WPARAM)PBST_ERROR, 0); + SetTaskbarProgressState(TASKBAR_ERROR); + goto out; + } + fido_len = (DWORD)size; SendMessage(hProgress, PBM_SETSTATE, (WPARAM)PBST_NORMAL, 0); SetTaskbarProgressState(TASKBAR_NORMAL); SetTaskbarProgressValue(0, MAX_PROGRESS); @@ -1012,6 +1032,7 @@ out: #endif free(url); SendMessage(hMainDialog, UM_ENABLE_CONTROLS, 0, 0); + dialog_showing--; ExitThread(dwExitCode); } diff --git a/src/rufus.h b/src/rufus.h index b1a3ca88..ac644f38 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -104,7 +104,7 @@ #endif #define DOWNLOAD_URL RUFUS_URL "/downloads" #define FILES_URL RUFUS_URL "/files" -#define FIDO_VERSION "v1" +#define FIDO_VERSION "z1" #define SECURE_BOOT_MORE_INFO_URL "https://github.com/pbatard/rufus/wiki/FAQ#Why_do_I_need_to_disable_Secure_Boot_to_use_UEFINTFS" #define WPPRECORDER_MORE_INFO_URL "https://github.com/pbatard/rufus/wiki/FAQ#BSODs_with_Windows_To_Go_drives_created_from_Windows_10_1809_ISOs" #define SEVENZIP_URL "https://www.7-zip.org" diff --git a/src/rufus.rc b/src/rufus.rc index 19a8029d..a1d2ae0f 100644 --- a/src/rufus.rc +++ b/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 3.5.1487" +CAPTION "Rufus 3.5.1488" FONT 9, "Segoe UI Symbol", 400, 0, 0x0 BEGIN LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP @@ -394,8 +394,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 3,5,1487,0 - PRODUCTVERSION 3,5,1487,0 + FILEVERSION 3,5,1488,0 + PRODUCTVERSION 3,5,1488,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -413,13 +413,13 @@ BEGIN VALUE "Comments", "https://akeo.ie" VALUE "CompanyName", "Akeo Consulting" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "3.5.1487" + VALUE "FileVersion", "3.5.1488" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2019 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "https://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus-3.5.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "3.5.1487" + VALUE "ProductVersion", "3.5.1488" END END BLOCK "VarFileInfo" diff --git a/src/stdlg.c b/src/stdlg.c index 44dff99f..ec16db5b 100644 --- a/src/stdlg.c +++ b/src/stdlg.c @@ -1558,8 +1558,13 @@ BOOL SetUpdateCheck(void) if ((loc_len != 0) && (loc_len < 4 * KB)) { loc_len++; // DownloadToFileOrBuffer allocated an extra NUL character if needed fido_url = get_token_data_buffer(FIDO_VERSION, 1, loc, (size_t)loc_len); - uprintf("Fido URL is %s", fido_url); - enable_fido = IsDownloadable(fido_url); + if (safe_strncmp(fido_url, "https://github.com/pbatard/Fido", 31) != 0) { + ubprintf("WARNING: Download script URL %s is invalid ✗", fido_url); + safe_free(fido_url); + } else { + uprintf("Fido URL is %s", fido_url); + enable_fido = IsDownloadable(fido_url); + } } safe_free(loc); }