#include <signal.h>
#include <assert.h>
-/* Const */
+// ==========================================================================
+// Constants
+// ==========================================================================
+
#define BUFFER_SIZE 4096U
-/* Op-mode */
-#define SLUNK_MODE_HELP 0
-#define SLUNK_MODE_VERS 1
-#define SLUNK_MODE_ENCR 2
-#define SLUNK_MODE_DECR 3
-#define SLUNK_MODE_PASS 4
-#define SLUNK_MODE_TEST 5
+#define MODE_HELP 0
+#define MODE_VERS 1
+#define MODE_ENCR 2
+#define MODE_DECR 3
+#define MODE_PASS 4
+#define 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_FILE = T("file:");
-static const CHR* const ENV_PASSWD_NAME = T("SLUNK_PASSPHRASE");
-
static const char PASSWD_SYMBOLS[] =
{
'!', '#', '$', '%', '&', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1',
'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;
// ==========================================================================
// 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"))))
{
- return SLUNK_MODE_HELP;
+ return MODE_HELP;
}
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"))))
{
- return SLUNK_MODE_ENCR;
+ return MODE_ENCR;
}
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"))))
{
- return SLUNK_MODE_PASS;
+ return MODE_PASS;
}
else if ((!STRICMP(command, T("-t"))) || (!STRICMP(command, T("--self-test"))))
{
- return SLUNK_MODE_TEST;
+ return MODE_TEST;
}
else
{
- FPRINTF(stderr, T("Error: The specified command \"%") T(PRISTR) T("\" is unknown!\n\n"), command);
- exit(EXIT_FAILURE);
+ return -1; /*invalid command*/
}
}
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(" --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);
if (!buffer)
{
FPUTS(T("Error: Failed to allocate the string buffer!\n\n"), stderr);
}
+
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);
return NULL;
FILE *const file_in = use_stdin ? stdin : FOPEN(file_name, T("rb"));
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);
return NULL;
}
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))
+ if (!(*file_in = FOPEN(input_path, T("rb"))))
{
- 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;
}
- *file_out = FOPEN(output_path, T("wb"));
- if (!(*file_out))
+ if (!(*file_out = FOPEN(output_path, T("wb"))))
{
- 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);
+ *file_in = NULL;
return EXIT_FAILURE;
}
goto clean_up;
}
- const int mode = parse_mode(argv[1U]);
- switch (mode)
+ const int slunk_mode = parse_slunk_mode(argv[1U]);
+ switch (slunk_mode)
{
- case SLUNK_MODE_HELP:
+ case MODE_HELP:
print_manpage(get_file_name(argv[0U]));
- case SLUNK_MODE_VERS:
+ case MODE_VERS:
result = EXIT_SUCCESS;
goto clean_up;
- case SLUNK_MODE_PASS:
- result = generate_passphrase((argc > 2) ? STRTOUL(argv[2U]) : 24U);
+ case MODE_ENCR:
+ case MODE_DECR:
+ break; /*fallthrough*/
+ case MODE_PASS:
+ result = generate_passphrase((argc > 2) ? STRTOUL(argv[2U]) : DFLT_PWDLEN_LENGTH);
goto clean_up;
- case SLUNK_MODE_TEST:
+ case MODE_TEST:
result = run_self_test();
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)
goto clean_up;
}
- const CHR *const passphrase = (argc > 4) ? argv[2U] : GETENV(ENV_PASSWD_NAME);
- const CHR *const input_file = argv[(argc > 4) ? 3U : 2U], *const output_file = argv[(argc > 4) ? 4U : 3U];
+ const CHR *const passphrase = PW_FROM_ENV ? GETENV(ENV_PASSWRD) : argv[2U];
+ const CHR *const input_file = argv[PW_FROM_ENV ? 2U : 3U], *const output_file = argv[PW_FROM_ENV ? 3U : 4U];
if ((!passphrase) || (!passphrase[0U]))
{
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);
- goto clean_up;
+ if ((!STARTS_WITH(passphrase, PREFIX_PASS)) && (!STARTS_WITH(passphrase, PREFIX_FILE)))
+ {
+ 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]))
/* Initialize passphrase */
/* ----------------------------------------------------- */
- passphrase_buffer = STARTS_WITH(passphrase, PREFIX_PASS) ? duplicate_string(passphrase + STRLEN(PREFIX_PASS)) :
- (STARTS_WITH(passphrase, PREFIX_FILE) ? read_passphrase(passphrase + STRLEN(PREFIX_FILE)) : read_passphrase(NULL));
- if (!passphrase_buffer)
+ if (!(passphrase_buffer = PW_FROM_ENV ? copy_passphrase(passphrase) :
+ (STARTS_WITH(passphrase, PREFIX_PASS) ? copy_passphrase(passphrase + STRLEN(PREFIX_PASS)) :
+ (STARTS_WITH(passphrase, PREFIX_FILE) ? read_passphrase(passphrase + STRLEN(PREFIX_FILE)) : read_passphrase(T("-"))))))
{
goto clean_up;
}
const size_t passphrase_len = strlen(passphrase_buffer);
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;
}
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;
}
- 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))
{
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);
break;
- case SLUNK_MODE_DECR:
+ case MODE_DECR:
result = decrypt(passphrase_buffer, input_file, output_file);
break;
default: