From b7e32f5f0aa84f751385fabd0eecc2cadf7a3699 Mon Sep 17 00:00:00 2001 From: LoRd_MuldeR Date: Sun, 18 Apr 2021 22:19:17 +0200 Subject: [PATCH] Refactored passphrase generator into a separate file. --- frontend/SlunkCrypt.vcxproj | 2 + frontend/SlunkCrypt.vcxproj.filters | 6 ++ frontend/src/main.c | 133 ++---------------------- frontend/src/pwgen.c | 151 ++++++++++++++++++++++++++++ frontend/src/pwgen.h | 16 +++ 5 files changed, 181 insertions(+), 127 deletions(-) create mode 100644 frontend/src/pwgen.c create mode 100644 frontend/src/pwgen.h diff --git a/frontend/SlunkCrypt.vcxproj b/frontend/SlunkCrypt.vcxproj index 93caa27..7cd9f70 100644 --- a/frontend/SlunkCrypt.vcxproj +++ b/frontend/SlunkCrypt.vcxproj @@ -45,6 +45,7 @@ + @@ -54,6 +55,7 @@ + diff --git a/frontend/SlunkCrypt.vcxproj.filters b/frontend/SlunkCrypt.vcxproj.filters index ad001d8..02be60d 100644 --- a/frontend/SlunkCrypt.vcxproj.filters +++ b/frontend/SlunkCrypt.vcxproj.filters @@ -33,6 +33,9 @@ Source Files + + Source Files + @@ -53,6 +56,9 @@ Header Files + + Header Files + diff --git a/frontend/src/main.c b/frontend/src/main.c index ed4e603..59be775 100644 --- a/frontend/src/main.c +++ b/frontend/src/main.c @@ -13,6 +13,7 @@ #include #include "utils.h" #include "crypt.h" +#include "pwgen.h" #include "selftest.h" /* CRT */ @@ -33,7 +34,8 @@ #define MODE_PASS 4 #define MODE_TEST 5 -#define PW_FROM_ENV (!(argc > 4)) +static const size_t RCMD_PWDLEN_LENGTH = 12U; +static const size_t DFLT_PWDLEN_LENGTH = 20U; static const CHR* const ENV_PASSWORD = T("SLUNK_PASSPHRASE"); static const CHR* const ENV_KEEPFILE = T("SLUNK_KEEP_INCOMPLETE"); @@ -41,23 +43,12 @@ static const CHR* const ENV_KEEPFILE = T("SLUNK_KEEP_INCOMPLETE"); static const CHR* const PREFIX_PASS = T("pass:"); static const CHR* const PREFIX_FILE = T("file:"); -static const char PASSWD_SYMBOLS[] = -{ - '!', '#', '$', '%', '&', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', - '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', - 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', ']', '^', '_', - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~' -}; - -static const size_t RCMD_PWDLEN_LENGTH = 12U; -static const size_t DFLT_PWDLEN_LENGTH = 20U; - // ========================================================================== // Auxiliary functions // ========================================================================== +#define PW_FROM_ENV (!(argc > 4)) + static int parse_slunk_mode(const CHR* const command) { if ((!STRICMP(command, T("-h"))) || (!STRICMP(command, T("/?"))) || (!STRICMP(command, T("--help")))) @@ -120,118 +111,6 @@ static char *copy_passphrase(const CHR *const passphrase) return buffer; } -static char *read_passphrase(const CHR *const file_name) -{ - if ((!file_name) || (!file_name[0U])) - { - FPUTS(T("Error: The passphrase input file name must not be empty!\n\n"), stderr); - return NULL; - } - - const size_t max_len = SLUNKCRYPT_PWDLEN_MAX + 2U; - char *const buffer = (char*) malloc(max_len * sizeof(char)); - if (!buffer) - { - FPUTS(T("Error: Failed to allocate the passphrase buffer!\n\n"), stderr); - return NULL; - } - - const int use_stdin = (!file_name) || (!STRICMP(file_name, T("-"))); - FILE *const file_in = use_stdin ? stdin : FOPEN(file_name, T("rb")); - if (!file_in) - { - FPRINTF(stderr, T("Error: Failed to open input file \"%") T(PRISTR) T("\" for reading!\n\n"), file_name); - free(buffer); - return NULL; - } - - do - { - if (!fgets(buffer, (int)max_len, file_in)) - { - buffer[0U] = '\0'; - goto finish; - } - size_t length = strlen(buffer); - while ((length > 0U) && ((buffer[length - 1U] == '\r') || (buffer[length - 1U] == '\n'))) - { - buffer[--length] = '\0'; - } - } - while (!buffer[0U]); - -finish: - - if ((!use_stdin) && file_in) - { - fclose(file_in); - } - - return buffer; -} - -static int weak_passphrase(const char *str) -{ - int flags[4U] = { 0, 0, 0, 0 }; - while (*str) - { - const int 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 generate_passphrase(const size_t length) -{ - int result = EXIT_FAILURE; - const size_t passwd_len = BOUND(SLUNKCRYPT_PWDLEN_MIN, length, SLUNKCRYPT_PWDLEN_MAX); - - char *const buffer = (char*) malloc((passwd_len + 1U) * sizeof(char)); - if (!buffer) - { - FPUTS(T("Error: Failed to allocate memory buffer!\n\n"), stderr); - return EXIT_FAILURE; - } - - do - { - for (size_t i = 0U; i < passwd_len; ++i) - { - uint64_t value; - if (slunkcrypt_generate_nonce(&value) != SLUNKCRYPT_SUCCESS) - { - FPUTS(T("Error: Failed to generate next random number!\n\n"), stderr); - goto clean_up; - } - buffer[i] = PASSWD_SYMBOLS[value % ARRAY_SIZE(PASSWD_SYMBOLS)]; - } - buffer[passwd_len] = '\0'; - } - while ((!isalpha((int)buffer[0U])) || (!isalnum((int)buffer[passwd_len - 1U])) || weak_passphrase(buffer)); - - FPRINTF(stdout, T("%") T(PRIstr) T("\n\n"), buffer); - fflush(stdout); - result = EXIT_SUCCESS; - -clean_up: - - if (buffer) - { - slunkcrypt_bzero(buffer, passwd_len * sizeof(char)); - free(buffer); - } - - return result; -} - static int keep_incomplete_files(void) { const CHR *const keep_files = GETENV(ENV_KEEPFILE); @@ -372,7 +251,7 @@ int MAIN(const int argc, CHR *const argv[]) } 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); + FPUTS(T("Warning: Using a *weak* passphrase; a mix of upper-case letters, lower-case letters, digits and other characters is recommended!\n\n"), stderr); } fflush(stderr); diff --git a/frontend/src/pwgen.c b/frontend/src/pwgen.c new file mode 100644 index 0000000..97968c7 --- /dev/null +++ b/frontend/src/pwgen.c @@ -0,0 +1,151 @@ +/******************************************************************************/ +/* SlunkCrypt, by LoRd_MuldeR */ +/* This work has been released under the CC0 1.0 Universal license! */ +/******************************************************************************/ + +#ifdef _WIN32 +# define _CRT_SECURE_NO_WARNINGS 1 +#else +# define _GNU_SOURCE 1 +#endif + +/* Internal */ +#include "pwgen.h" +#include +#include "utils.h" + +/* CRT */ +#include + +// ========================================================================== +// Constants +// ========================================================================== + +static const char PASSWD_SYMBOLS[] = +{ + '!', '#', '$', '%', '&', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', + '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', ']', '^', '_', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~' +}; + +// ========================================================================== +// Read passphrase from file +// ========================================================================== + +char *read_passphrase(const CHR *const file_name) +{ + if ((!file_name) || (!file_name[0U])) + { + FPUTS(T("Error: The passphrase input file name must not be empty!\n\n"), stderr); + return NULL; + } + + const size_t max_len = SLUNKCRYPT_PWDLEN_MAX + 2U; + char *const buffer = (char*) malloc(max_len * sizeof(char)); + if (!buffer) + { + FPUTS(T("Error: Failed to allocate the passphrase buffer!\n\n"), stderr); + return NULL; + } + + const int use_stdin = (!file_name) || (!STRICMP(file_name, T("-"))); + FILE *const file_in = use_stdin ? stdin : FOPEN(file_name, T("rb")); + if (!file_in) + { + FPRINTF(stderr, T("Error: Failed to open input file \"%") T(PRISTR) T("\" for reading!\n\n"), file_name); + free(buffer); + return NULL; + } + + do + { + if (!fgets(buffer, (int)max_len, file_in)) + { + buffer[0U] = '\0'; + goto finish; + } + size_t length = strlen(buffer); + while ((length > 0U) && ((buffer[length - 1U] == '\r') || (buffer[length - 1U] == '\n'))) + { + buffer[--length] = '\0'; + } + } + while (!buffer[0U]); + +finish: + + if ((!use_stdin) && file_in) + { + fclose(file_in); + } + + return buffer; +} + +// ========================================================================== +// Passphrase generator +// ========================================================================== + +int weak_passphrase(const char *str) +{ + unsigned int flags = 0U; + while ((*str) && (flags != 0xF)) + { + const int c = *str++; + if (isalpha(c)) + { + flags |= isupper(c) ? 0x1 : 0x2; + } + else + { + flags |= isdigit(c) ? 0x4 : 0x8; + } + } + return (flags != 0xF); +} + +int generate_passphrase(const size_t length) +{ + int result = EXIT_FAILURE; + const size_t passwd_len = BOUND(SLUNKCRYPT_PWDLEN_MIN, length, SLUNKCRYPT_PWDLEN_MAX); + + char *const buffer = (char*) malloc((passwd_len + 1U) * sizeof(char)); + if (!buffer) + { + FPUTS(T("Error: Failed to allocate memory buffer!\n\n"), stderr); + return EXIT_FAILURE; + } + + do + { + for (size_t i = 0U; i < passwd_len; ++i) + { + uint64_t value; + if (slunkcrypt_generate_nonce(&value) != SLUNKCRYPT_SUCCESS) + { + FPUTS(T("Error: Failed to generate next random number!\n\n"), stderr); + goto clean_up; + } + buffer[i] = PASSWD_SYMBOLS[value % ARRAY_SIZE(PASSWD_SYMBOLS)]; + } + buffer[passwd_len] = '\0'; + } + while ((!isalnum((int)buffer[0U])) || (!isalnum((int)buffer[passwd_len - 1U])) || weak_passphrase(buffer)); + + FPRINTF(stdout, T("%") T(PRIstr) T("\n\n"), buffer); + fflush(stdout); + result = EXIT_SUCCESS; + +clean_up: + + if (buffer) + { + slunkcrypt_bzero(buffer, passwd_len * sizeof(char)); + free(buffer); + } + + return result; +} diff --git a/frontend/src/pwgen.h b/frontend/src/pwgen.h new file mode 100644 index 0000000..5684faa --- /dev/null +++ b/frontend/src/pwgen.h @@ -0,0 +1,16 @@ +/******************************************************************************/ +/* SlunkCrypt, by LoRd_MuldeR */ +/* This work has been released under the CC0 1.0 Universal license! */ +/******************************************************************************/ + +#ifndef INC_SLUNKAPP_PWGEN_H +#define INC_SLUNKAPP_PWGEN_H + +#include "platform.h" +#include + +char *read_passphrase(const CHR *const file_name); +int weak_passphrase(const char *str); +int generate_passphrase(const size_t length); + +#endif