Refactored passphrase generator into a separate file.

This commit is contained in:
LoRd_MuldeR 2021-04-18 22:19:17 +02:00
parent 46dc28f3ca
commit b7e32f5f0a
Signed by: mulder
GPG Key ID: 2B5913365F57E03F
5 changed files with 181 additions and 127 deletions

View File

@ -45,6 +45,7 @@
<ItemGroup>
<ClCompile Include="src\blake2.c" />
<ClCompile Include="src\crypt.c" />
<ClCompile Include="src\pwgen.c" />
<ClCompile Include="src\selftest.c" />
<ClCompile Include="src\test_data.c" />
<ClCompile Include="src\main.c" />
@ -54,6 +55,7 @@
<ClInclude Include="src\blake2.h" />
<ClInclude Include="src\crypt.h" />
<ClInclude Include="src\platform.h" />
<ClInclude Include="src\pwgen.h" />
<ClInclude Include="src\selftest.h" />
<ClInclude Include="src\test_data.h" />
<ClInclude Include="src\utils.h" />

View File

@ -33,6 +33,9 @@
<ClCompile Include="src\selftest.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\pwgen.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\utils.h">
@ -53,6 +56,9 @@
<ClInclude Include="src\selftest.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\pwgen.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Manifest Include="res\compatibility.manifest">

View File

@ -13,6 +13,7 @@
#include <slunkcrypt.h>
#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);

151
frontend/src/pwgen.c Normal file
View File

@ -0,0 +1,151 @@
/******************************************************************************/
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
/* 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 <slunkcrypt.h>
#include "utils.h"
/* CRT */
#include <ctype.h>
// ==========================================================================
// 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;
}

16
frontend/src/pwgen.h Normal file
View File

@ -0,0 +1,16 @@
/******************************************************************************/
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
/* 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 <stdint.h>
char *read_passphrase(const CHR *const file_name);
int weak_passphrase(const char *str);
int generate_passphrase(const size_t length);
#endif