From a3fd6360e1284b54a4c2de69d6b1114fdd728f97 Mon Sep 17 00:00:00 2001 From: LoRd_MuldeR Date: Wed, 14 Oct 2020 16:36:17 +0200 Subject: [PATCH] Make it possible to read the passphrase from a file. --- frontend/src/main.c | 134 +++++++++++++++++++++++++++------------- frontend/src/platform.h | 10 +-- frontend/src/utils.c | 27 +++++--- frontend/src/utils.h | 3 +- 4 files changed, 115 insertions(+), 59 deletions(-) diff --git a/frontend/src/main.c b/frontend/src/main.c index 6fb8eb7..efec490 100644 --- a/frontend/src/main.c +++ b/frontend/src/main.c @@ -12,15 +12,59 @@ #include #include #include +#include -static void print_string(const char *const text, const size_t length) +static volatile int g_interrupted = 0; + +static char* read_passphrase(const CHR* const file_name) { - fputc('"', stderr); - for (size_t i = 0; i < length; ++i) + const size_t buff_size = 1024U; + char *const buffer = (char*) malloc(buff_size * sizeof(char)); + if (!buffer) { - fputc((text[i] >= 0x20) ? text[i] : '?', stderr); + return NULL; } - fputs("\"\n\n", stderr); + FILE *const fin = FOPEN(file_name, T("rb")); + if (!fin) + { + return NULL; + } + do + { + if (!fgets(buffer, (int)buff_size, fin)) + { + fclose(fin); + free(buffer); + return NULL; + } + size_t length = strlen(buffer); + while ((length > 0U) && ((buffer[length - 1U] == '\r') || (buffer[length - 1U] == '\n'))) + { + buffer[--length] = '\0'; + } + } + while (!buffer[0U]); + fclose(fin); + return buffer; +} + +static int weak_passphrase(const char *str) +{ + int flags[4U] = { 0, 0, 0, 0 }; + while (*str) + { + const CHR c = *str++; + if (isalpha(c)) + { + flags[isupper(c) ? 0U : 1U] = 1; + } + else + { + flags[isdigit(c) ? 2U : 3U] = 1; + } + } + const int strong = flags[0U] && flags[1U] && flags[2U] && flags[3U]; + return !strong; } static int open_files(FILE** const fin, FILE** const fout, const CHR* const input, const CHR* const output) @@ -43,21 +87,6 @@ static int open_files(FILE** const fin, FILE** const fout, const CHR* const inpu return 0; } -static int weak_passphrase(const CHR *str) -{ - int flags[4U] = { 0, 0, 0, 0 }; - while (*str) - { - const CHR c = *str++; - if (ISUPPER(c)) flags[0U] = 1; - else if (ISLOWER(c)) flags[1U] = 1; - else if (ISDIGIT(c)) flags[2U] = 1; - else if (ISGRAPH(c)) flags[3U] = 1; - } - const int strong = flags[0U] && flags[1U] && flags[2U] && flags[3U]; - return !strong; -} - static int encrypt(const char* const passphrase, const CHR* const input, const CHR* const output) { mcrypt_t ctx = MCRYPT_NULL; @@ -136,6 +165,11 @@ static int encrypt(const char* const passphrase, const CHR* const input, const C fflush(stderr); clk_update = clk_now; } + if (g_interrupted) + { + FPUTS(T("\n\nProcess interrupted!\n\n"), stderr); + goto clean_up; + } } crc_actual = crc64_finish(crc_actual); @@ -254,6 +288,11 @@ static int decrypt(const char* const passphrase, const CHR* const input, const C fflush(stderr); clk_update = clk_now; } + if (g_interrupted) + { + FPUTS(T("\n\nProcess interrupted!\n\n"), stderr); + goto clean_up; + } } crc_actual = crc64_finish(crc_actual); @@ -392,9 +431,16 @@ clean_up: return result; } +static void sigint_handler(const int sig) +{ + g_interrupted = 1; + signal(SIGINT, sigint_handler); +} + int MAIN(int argc, CHR* argv[]) { init_terminal(); + signal(SIGINT, sigint_handler); FPRINTF(stderr, T("MCrypt Utility (%") T(PRIstr) T("-%") T(PRIstr) T("), by LoRd_MuldeR \n"), OS_TYPE, CPU_ARCH); FPRINTF(stderr, T("Using libMCrypt v%") T(PRIstr) T(" [%") T(PRIstr) T("]\n\n"), LIBMCRYPT_VERSION, LIBMCRYPT_BUILDNO); @@ -407,6 +453,7 @@ int MAIN(int argc, CHR* argv[]) const int help_requested = (argc > 1) && ((!STRICMP(argv[1U], T("/?"))) || (!STRICMP(argv[1U], T("--help"))) || (!STRICMP(argv[1U], T("--version")))); if ((argc < 5) || help_requested) { + const CHR* const program = get_file_name(argv[0U]); FPUTS(T("--------------------------------------------------------------------\n"), stderr); FPUTS(T("This software has been released under the CC0 1.0 Universal license:\n"), stderr); FPUTS(T("https://creativecommons.org/publicdomain/zero/1.0/legalcode\n"), stderr); @@ -416,28 +463,20 @@ int MAIN(int argc, CHR* argv[]) FPUTS(T("Error: Required argument is missing!\n\n"), stderr); } FPUTS(T("Usage:\n"), stderr); - FPRINTF(stderr, T(" %") T(PRISTR) T(" --encrypt \n"), argv[0U]); - FPRINTF(stderr, T(" %") T(PRISTR) T(" --decrypt \n\n"), argv[0U]); + FPRINTF(stderr, T(" %") T(PRISTR) T(" --encrypt [@] \n"), program); + FPRINTF(stderr, T(" %") T(PRISTR) T(" --decrypt [@] \n\n"), program); + FPUTS(T("Note: If starts with an '@' symbol, the remainder specifies the\n"), stderr); + FPUTS(T("file to read the passphrase from. Only the *first* line in the file is used!\n"), stderr); return help_requested ? 0 : 1; } const CHR *const command = argv[1U], *const passphrase = argv[2U], *const input_file = argv[3U], *const output_file = argv[4U]; - if (!passphrase[0U]) + + if ((!passphrase[0U]) || ((passphrase[0U] == T('@')) && (!passphrase[1U]))) { - FPUTS(T("Error: The passphrase must not be empty!\n\n"), stderr); + FPUTS(T("Error: The passphrase or passphrase file must not be empty!\n\n"), stderr); return 1; } - else - { - if (STRLEN(passphrase) < 12U) - { - FPUTS(T("Warning: Using a *short* passphrase; a length of 12 characters or more is recommended!\n\n"), stderr); - } - if (weak_passphrase(passphrase)) - { - FPUTS(T("Warning: Using a *weak* passphrase; a mix of upper-case letters, lower-case letters, digits and 'special' characters is recommended!\n\n"), stderr); - } - } if ((!input_file[0U]) || (!output_file[0U])) { @@ -445,23 +484,32 @@ int MAIN(int argc, CHR* argv[]) return 1; } - char* const passphrase_utf8 = CHR_to_utf8(passphrase); - if (!passphrase_utf8) + char *const passphrase_buffer = (passphrase[0U] == T('@')) ? read_passphrase(passphrase + 1U) : CHR_to_utf8(passphrase); + if (!passphrase_buffer) { - FPUTS(T("Error: Failed to convert passphrase to the UTF-8 format!\n\n"), stderr); + FPUTS(T("Error: Failed to read the passphrase file!\n\n"), stderr); return 1; } + if (strlen(passphrase_buffer) < 12U) + { + FPUTS(T("Warning: Using a *short* passphrase; a length of 12 characters or more is recommended!\n\n"), stderr); + } + else if (weak_passphrase(passphrase_buffer)) + { + FPUTS(T("Warning: Using a *weak* passphrase; a mix of upper-case letters, lower-case letters, digits and 'special' characters is recommended!\n\n"), stderr); + } + const clock_t clk_start = clock(); int result = -1; if (!STRICMP(command, T("--encrypt"))) { - result = encrypt(passphrase_utf8, input_file, output_file); + result = encrypt(passphrase_buffer, input_file, output_file); } else if (!STRICMP(command, T("--decrypt"))) { - result = decrypt(passphrase_utf8, input_file, output_file); + result = decrypt(passphrase_buffer, input_file, output_file); } else { @@ -477,10 +525,10 @@ int MAIN(int argc, CHR* argv[]) exiting: - if (passphrase_utf8) + if (passphrase_buffer) { - mcrypt_bzero(passphrase_utf8, strlen(passphrase_utf8)); - free(passphrase_utf8); + mcrypt_bzero(passphrase_buffer, strlen(passphrase_buffer)); + free(passphrase_buffer); } mcrypt_bzero((CHR*)passphrase, STRLEN(passphrase) * sizeof(CHR)); diff --git a/frontend/src/platform.h b/frontend/src/platform.h index 0ce1508..f122442 100644 --- a/frontend/src/platform.h +++ b/frontend/src/platform.h @@ -55,16 +55,13 @@ #define _T(X) L##X #define STRLEN(X) wcslen((X)) #define STRICMP(X,Y) _wcsicmp((X),(Y)) +#define STRRCHR(X,Y) wcsrchr((X),(Y)) #define FPUTS(X,Y) fputws((X),(Y)) #define FPRINTF(X,Y,...) fwprintf((X),(Y),__VA_ARGS__) #define FOPEN(X,Y) _wfsopen((X),(Y),_SH_SECURE) #define FILENO(X) _fileno((X)) #define FSTAT64(X,Y) _fstati64((X),(Y)) #define STAT64_T struct _stati64 -#define ISUPPER(X) iswupper((X)) -#define ISLOWER(X) iswlower((X)) -#define ISDIGIT(X) iswdigit((X)) -#define ISGRAPH(X) iswgraph((X)) #ifdef __MINGW32__ #define PRISTR "ls" #define PRIstr "hs" @@ -80,16 +77,13 @@ #define _T(X) X #define STRLEN(X) strlen((X)) #define STRICMP(X,Y) strcasecmp((X),(Y)) +#define STRRCHR(X,Y) strrchr((X),(Y)) #define FPUTS(X,Y) fputs((X),(Y)) #define FPRINTF(X,Y,...) fprintf((X),(Y),__VA_ARGS__) #define FOPEN(X,Y) fopen((X),(Y)) #define FILENO(X) fileno((X)) #define FSTAT64(X,Y) fstat64((X),(Y)) #define STAT64_T struct stat64 -#define ISUPPER(X) isupper((X)) -#define ISLOWER(X) islower((X)) -#define ISDIGIT(X) isdigit((X)) -#define ISGRAPH(X) isgraph((X)) #define PRISTR "s" #define PRIstr "s" #define PRIwcs "ls" diff --git a/frontend/src/utils.c b/frontend/src/utils.c index 3602102..9237b12 100644 --- a/frontend/src/utils.c +++ b/frontend/src/utils.c @@ -11,7 +11,6 @@ #endif #include "utils.h" -#include #include #include @@ -24,6 +23,14 @@ #define S_IFIFO _S_IFIFO #endif +void init_terminal(void) +{ +#ifdef _WIN32 + SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); + _setmode(_fileno(stderr), _O_U8TEXT); +#endif +} + char* CHR_to_utf8(const CHR*const input) { #ifdef _WIN32 @@ -55,7 +62,7 @@ char* CHR_to_utf8(const CHR*const input) #endif } -uint64_t get_file_size(FILE *const file) +uint64_t get_file_size(FILE* const file) { STAT64_T stat; if (FSTAT64(FILENO(file), &stat) != 0) @@ -70,10 +77,16 @@ uint64_t get_file_size(FILE *const file) return 0U; } -void init_terminal(void) +const CHR* get_file_name(const CHR* path) { -#ifdef _WIN32 - SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); - _setmode(_fileno(stderr), _O_U8TEXT); -#endif + const CHR* ptr; + while (ptr = STRRCHR(path, T('/'))) + { + path = ptr + 1U; + } + while (ptr = STRRCHR(path, T('\\'))) + { + path = ptr + 1U; + } + return path; } diff --git a/frontend/src/utils.h b/frontend/src/utils.h index 1d3b764..d7523c1 100644 --- a/frontend/src/utils.h +++ b/frontend/src/utils.h @@ -9,8 +9,9 @@ #include "platform.h" #include +void init_terminal(void); char* CHR_to_utf8(const CHR *const input); uint64_t get_file_size(FILE* const file); -void init_terminal(void); +const CHR *get_file_name(const CHR *path); #endif