Don't require environment variable to start with "pass:" prefix + some code clean-up.

This commit is contained in:
LoRd_MuldeR 2021-03-26 01:21:29 +01:00
parent c8cd0fc699
commit bdab06cd80
Signed by: mulder
GPG Key ID: 2B5913365F57E03F

View File

@ -25,22 +25,25 @@
#include <signal.h> #include <signal.h>
#include <assert.h> #include <assert.h>
/* Const */ // ==========================================================================
// Constants
// ==========================================================================
#define BUFFER_SIZE 4096U #define BUFFER_SIZE 4096U
/* Op-mode */ #define MODE_HELP 0
#define SLUNK_MODE_HELP 0 #define MODE_VERS 1
#define SLUNK_MODE_VERS 1 #define MODE_ENCR 2
#define SLUNK_MODE_ENCR 2 #define MODE_DECR 3
#define SLUNK_MODE_DECR 3 #define MODE_PASS 4
#define SLUNK_MODE_PASS 4 #define MODE_TEST 5
#define SLUNK_MODE_TEST 5
#define PW_FROM_ENV (!(argc > 4))
static const CHR* const ENV_PASSWRD = T("SLUNK_PASSPHRASE");
static const CHR* const PREFIX_PASS = T("pass:"); static const CHR* const PREFIX_PASS = T("pass:");
static const CHR* const PREFIX_FILE = T("file:"); static const CHR* const PREFIX_FILE = T("file:");
static const CHR* const ENV_PASSWD_NAME = T("SLUNK_PASSPHRASE");
static const char PASSWD_SYMBOLS[] = static const char PASSWD_SYMBOLS[] =
{ {
'!', '#', '$', '%', '&', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '!', '#', '$', '%', '&', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1',
@ -51,42 +54,44 @@ static const char PASSWD_SYMBOLS[] =
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~' '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;
static const uint64_t MAGIC_NUMBER = 0x243F6A8885A308D3ull; static const uint64_t MAGIC_NUMBER = 0x243F6A8885A308D3ull;
// ========================================================================== // ==========================================================================
// Auxiliary functions // Auxiliary functions
// ========================================================================== // ==========================================================================
static int parse_mode(const CHR* const command) static int parse_slunk_mode(const CHR* const command)
{ {
if ((!STRICMP(command, T("-h"))) || (!STRICMP(command, T("/?"))) || (!STRICMP(command, T("--help")))) if ((!STRICMP(command, T("-h"))) || (!STRICMP(command, T("/?"))) || (!STRICMP(command, T("--help"))))
{ {
return SLUNK_MODE_HELP; return MODE_HELP;
} }
else if ((!STRICMP(command, T("-v"))) || (!STRICMP(command, T("--version")))) else if ((!STRICMP(command, T("-v"))) || (!STRICMP(command, T("--version"))))
{ {
return SLUNK_MODE_VERS; return MODE_VERS;
} }
else if ((!STRICMP(command, T("-e"))) || (!STRICMP(command, T("--encrypt")))) else if ((!STRICMP(command, T("-e"))) || (!STRICMP(command, T("--encrypt"))))
{ {
return SLUNK_MODE_ENCR; return MODE_ENCR;
} }
else if ((!STRICMP(command, T("-d"))) || (!STRICMP(command, T("--decrypt")))) else if ((!STRICMP(command, T("-d"))) || (!STRICMP(command, T("--decrypt"))))
{ {
return SLUNK_MODE_DECR; return MODE_DECR;
} }
else if ((!STRICMP(command, T("-p"))) || (!STRICMP(command, T("--make-pw")))) else if ((!STRICMP(command, T("-p"))) || (!STRICMP(command, T("--make-pw"))))
{ {
return SLUNK_MODE_PASS; return MODE_PASS;
} }
else if ((!STRICMP(command, T("-t"))) || (!STRICMP(command, T("--self-test")))) else if ((!STRICMP(command, T("-t"))) || (!STRICMP(command, T("--self-test"))))
{ {
return SLUNK_MODE_TEST; return MODE_TEST;
} }
else else
{ {
FPRINTF(stderr, T("Error: The specified command \"%") T(PRISTR) T("\" is unknown!\n\n"), command); return -1; /*invalid command*/
exit(EXIT_FAILURE);
} }
} }
@ -100,22 +105,29 @@ static void print_manpage(const CHR *const program)
FPRINTF(stderr, T(" %") T(PRISTR) T(" --encrypt [pass:<pass>|file:<file>] <input.txt> <output.enc>\n"), program); FPRINTF(stderr, T(" %") T(PRISTR) T(" --encrypt [pass:<pass>|file:<file>] <input.txt> <output.enc>\n"), program);
FPRINTF(stderr, T(" %") T(PRISTR) T(" --decrypt [pass:<pass>|file:<file>] <input.enc> <output.txt>\n"), program); FPRINTF(stderr, T(" %") T(PRISTR) T(" --decrypt [pass:<pass>|file:<file>] <input.enc> <output.txt>\n"), program);
FPRINTF(stderr, T(" %") T(PRISTR) T(" --make-pw [<length>]\n\n"), program); FPRINTF(stderr, T(" %") T(PRISTR) T(" --make-pw [<length>]\n\n"), program);
FPRINTF(stderr, T("Optionally, reads passphrase from the %") T(PRISTR) T(" environment variable.\n\n"), ENV_PASSWD_NAME); FPRINTF(stderr, T("Optionally, reads passphrase from the %") T(PRISTR) T(" environment variable.\n\n"), ENV_PASSWRD);
} }
static char *duplicate_string(const CHR *const passphrase) static char *copy_passphrase(const CHR *const passphrase)
{ {
if ((!passphrase) || (!passphrase[0U]))
{
FPUTS(T("Error: The passphrase input string must not be empty!\n\n"), stderr);
return NULL;
}
char *const buffer = CHR_to_utf8(passphrase); char *const buffer = CHR_to_utf8(passphrase);
if (!buffer) if (!buffer)
{ {
FPUTS(T("Error: Failed to allocate the string buffer!\n\n"), stderr); FPUTS(T("Error: Failed to allocate the string buffer!\n\n"), stderr);
} }
return buffer; return buffer;
} }
static char *read_passphrase(const CHR* const file_name) static char *read_passphrase(const CHR *const file_name)
{ {
if (file_name && (!file_name[0U])) if ((!file_name) || (!file_name[0U]))
{ {
FPUTS(T("Error: The passphrase input file name must not be empty!\n\n"), stderr); FPUTS(T("Error: The passphrase input file name must not be empty!\n\n"), stderr);
return NULL; return NULL;
@ -133,7 +145,7 @@ static char *read_passphrase(const CHR* const file_name)
FILE *const file_in = use_stdin ? stdin : FOPEN(file_name, T("rb")); FILE *const file_in = use_stdin ? stdin : FOPEN(file_name, T("rb"));
if (!file_in) if (!file_in)
{ {
FPRINTF(stderr, T("Error: Failed to open file \"%") T(PRISTR) T("\" for reading!\n\n"), file_name); FPRINTF(stderr, T("Error: Failed to open input file \"%") T(PRISTR) T("\" for reading!\n\n"), file_name);
free(buffer); free(buffer);
return NULL; return NULL;
} }
@ -225,20 +237,20 @@ clean_up:
return result; return result;
} }
static int open_files(FILE **const file_in, FILE **const file_out, const CHR* const input_path, const CHR* const output_path) static int open_files(FILE **const file_in, FILE **const file_out, const CHR *const input_path, const CHR *const output_path)
{ {
*file_in = FOPEN(input_path, T("rb")); if (!(*file_in = FOPEN(input_path, T("rb"))))
if (!(*file_in))
{ {
FPRINTF(stderr, T("Error: Failed to open file \"%") T(PRISTR) T("\" for reading!\n\n"), input_path); FPRINTF(stderr, T("Error: Failed to open input file \"%") T(PRISTR) T("\" for reading!\n\n"), input_path);
*file_out = NULL;
return EXIT_FAILURE; return EXIT_FAILURE;
} }
*file_out = FOPEN(output_path, T("wb")); if (!(*file_out = FOPEN(output_path, T("wb"))))
if (!(*file_out))
{ {
FPRINTF(stderr, T("Error: Failed to open file \"%") T(PRISTR) T("\" for writing!\n\n"), output_path); FPRINTF(stderr, T("Error: Failed to open output file \"%") T(PRISTR) T("\" for writing!\n\n"), output_path);
fclose(*file_in); fclose(*file_in);
*file_in = NULL;
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -763,20 +775,26 @@ int MAIN(const int argc, CHR *const argv[])
goto clean_up; goto clean_up;
} }
const int mode = parse_mode(argv[1U]); const int slunk_mode = parse_slunk_mode(argv[1U]);
switch (mode) switch (slunk_mode)
{ {
case SLUNK_MODE_HELP: case MODE_HELP:
print_manpage(get_file_name(argv[0U])); print_manpage(get_file_name(argv[0U]));
case SLUNK_MODE_VERS: case MODE_VERS:
result = EXIT_SUCCESS; result = EXIT_SUCCESS;
goto clean_up; goto clean_up;
case SLUNK_MODE_PASS: case MODE_ENCR:
result = generate_passphrase((argc > 2) ? STRTOUL(argv[2U]) : 24U); case MODE_DECR:
break; /*fallthrough*/
case MODE_PASS:
result = generate_passphrase((argc > 2) ? STRTOUL(argv[2U]) : DFLT_PWDLEN_LENGTH);
goto clean_up; goto clean_up;
case SLUNK_MODE_TEST: case MODE_TEST:
result = run_self_test(); result = run_self_test();
goto clean_up; goto clean_up;
default:
FPRINTF(stderr, T("Error: The specified command \"%") T(PRISTR) T("\" is unknown!\n\n"), argv[1U]);
goto clean_up;
} }
if (argc < 4) if (argc < 4)
@ -785,8 +803,8 @@ int MAIN(const int argc, CHR *const argv[])
goto clean_up; goto clean_up;
} }
const CHR *const passphrase = (argc > 4) ? argv[2U] : GETENV(ENV_PASSWD_NAME); const CHR *const passphrase = PW_FROM_ENV ? GETENV(ENV_PASSWRD) : argv[2U];
const CHR *const input_file = argv[(argc > 4) ? 3U : 2U], *const output_file = argv[(argc > 4) ? 4U : 3U]; const CHR *const input_file = argv[PW_FROM_ENV ? 2U : 3U], *const output_file = argv[PW_FROM_ENV ? 3U : 4U];
if ((!passphrase) || (!passphrase[0U])) if ((!passphrase) || (!passphrase[0U]))
{ {
@ -794,10 +812,13 @@ int MAIN(const int argc, CHR *const argv[])
goto clean_up; goto clean_up;
} }
if (STRICMP(passphrase, T("-")) && (!STARTS_WITH(passphrase, PREFIX_PASS)) && (!STARTS_WITH(passphrase, PREFIX_FILE))) if ((!PW_FROM_ENV) && STRICMP(passphrase, T("-")))
{ {
FPRINTF(stderr, T("Error: The passphrase must start with a '%") T(PRISTR) T("' or '%") T(PRISTR) T("' prefix!\n\n"), PREFIX_PASS, PREFIX_FILE); if ((!STARTS_WITH(passphrase, PREFIX_PASS)) && (!STARTS_WITH(passphrase, PREFIX_FILE)))
goto clean_up; {
FPRINTF(stderr, T("Error: The passphrase must start with a '%") T(PRISTR) T("' or '%") T(PRISTR) T("' prefix!\n\n"), PREFIX_PASS, PREFIX_FILE);
goto clean_up;
}
} }
if ((!input_file[0U]) || (!output_file[0U])) if ((!input_file[0U]) || (!output_file[0U]))
@ -810,9 +831,9 @@ int MAIN(const int argc, CHR *const argv[])
/* Initialize passphrase */ /* Initialize passphrase */
/* ----------------------------------------------------- */ /* ----------------------------------------------------- */
passphrase_buffer = STARTS_WITH(passphrase, PREFIX_PASS) ? duplicate_string(passphrase + STRLEN(PREFIX_PASS)) : if (!(passphrase_buffer = PW_FROM_ENV ? copy_passphrase(passphrase) :
(STARTS_WITH(passphrase, PREFIX_FILE) ? read_passphrase(passphrase + STRLEN(PREFIX_FILE)) : read_passphrase(NULL)); (STARTS_WITH(passphrase, PREFIX_PASS) ? copy_passphrase(passphrase + STRLEN(PREFIX_PASS)) :
if (!passphrase_buffer) (STARTS_WITH(passphrase, PREFIX_FILE) ? read_passphrase(passphrase + STRLEN(PREFIX_FILE)) : read_passphrase(T("-"))))))
{ {
goto clean_up; goto clean_up;
} }
@ -822,18 +843,18 @@ int MAIN(const int argc, CHR *const argv[])
const size_t passphrase_len = strlen(passphrase_buffer); const size_t passphrase_len = strlen(passphrase_buffer);
if (passphrase_len < SLUNKCRYPT_PWDLEN_MIN) if (passphrase_len < SLUNKCRYPT_PWDLEN_MIN)
{ {
FPRINTF(stderr, T("Error: Passphrase must be at least %") T(PRIu64) T(" characters in length!\n\n"), (uint64_t)SLUNKCRYPT_PWDLEN_MIN); FPRINTF(stderr, T("Error: Passphrase must be at least %u characters in length!\n\n"), (unsigned)SLUNKCRYPT_PWDLEN_MIN);
goto clean_up; goto clean_up;
} }
else if (passphrase_len > SLUNKCRYPT_PWDLEN_MAX) else if (passphrase_len > SLUNKCRYPT_PWDLEN_MAX)
{ {
FPRINTF(stderr, T("Error: Passphrase must be at most %") T(PRIu64) T(" characters in length!\n\n"), (uint64_t)SLUNKCRYPT_PWDLEN_MAX); FPRINTF(stderr, T("Error: Passphrase must be at most %u characters in length!\n\n"), (unsigned)SLUNKCRYPT_PWDLEN_MAX);
goto clean_up; goto clean_up;
} }
if (passphrase_len < 12U) if (passphrase_len < RCMD_PWDLEN_LENGTH)
{ {
FPUTS(T("Warning: Using a *short* passphrase; a length of 12 characters or more is recommended!\n\n"), stderr); FPRINTF(stderr, T("Warning: Using a *short* passphrase; a length of %u characters or more is recommended!\n\n"), (unsigned)RCMD_PWDLEN_LENGTH);
} }
else if (weak_passphrase(passphrase_buffer)) else if (weak_passphrase(passphrase_buffer))
{ {
@ -846,12 +867,12 @@ int MAIN(const int argc, CHR *const argv[])
const clock_t clk_start = clock(); const clock_t clk_start = clock();
switch (mode) switch (slunk_mode)
{ {
case SLUNK_MODE_ENCR: case MODE_ENCR:
result = encrypt(passphrase_buffer, input_file, output_file); result = encrypt(passphrase_buffer, input_file, output_file);
break; break;
case SLUNK_MODE_DECR: case MODE_DECR:
result = decrypt(passphrase_buffer, input_file, output_file); result = decrypt(passphrase_buffer, input_file, output_file);
break; break;
default: default: