Mercurial
diff auth/hash_password.c @ 264:04fee26ecce0
add authenticated JRPG conversation platform
Add reusable auth/session storage, owned conversation recovery, guest quotas, admin workflows, URL-routed conversation UI, mobile frame support, and parallel browser acceptance.
Co-authored-by: Copilot <[email protected]>
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Fri, 07 Aug 2026 07:34:12 -0700 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/auth/hash_password.c Fri Aug 07 07:34:12 2026 -0700 @@ -0,0 +1,111 @@ +#include "auth/auth_crypto.h" + +#include <openssl/crypto.h> + +#include <stdio.h> +#include <string.h> +#include <termios.h> +#include <unistd.h> + +#define PW_MAX AUTH_CRYPTO_PASSWORD_MAX_BYTES + +static int read_password(int fd, char *buf, size_t capacity) +{ + size_t len = 0; + int too_long = 0; + for (;;) + { + unsigned char c; + int r = (int)read(fd, &c, 1); + if (r < 0) + return -1; + if (r == 0) + break; + if (c == '\n' || c == '\r') + break; + if (len + 1 >= capacity) + { + too_long = 1; + continue; + } + buf[len++] = (char)c; + } + buf[len] = '\0'; + return too_long ? -2 : (int)len; +} + +int main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + int fd = STDIN_FILENO; + int is_tty = isatty(fd); + struct termios old_term; + struct termios new_term; + int restored = 0; + + if (is_tty) + { + if (tcgetattr(fd, &old_term) != 0) + { + fprintf(stderr, "hash_password: failed to get terminal attributes\n"); + return 1; + } + new_term = old_term; + new_term.c_lflag &= (tcflag_t)~(ECHO | ECHOE | ECHOK | ECHONL); + new_term.c_lflag |= ICANON; + if (tcsetattr(fd, TCSAFLUSH, &new_term) != 0) + { + fprintf(stderr, "hash_password: failed to disable echo\n"); + return 1; + } + restored = 1; + fprintf(stderr, "Password: "); + fflush(stderr); + } + + char pw[PW_MAX + 1]; + memset(pw, 0, sizeof(pw)); + int n = read_password(fd, pw, sizeof(pw)); + + if (restored) + { + tcsetattr(fd, TCSAFLUSH, &old_term); + fprintf(stderr, "\n"); + } + + if (n == -2) + { + fprintf(stderr, "hash_password: %s\n", + Auth_Crypto_Result_String(AUTH_CRYPTO_PASSWORD_TOO_LONG)); + OPENSSL_cleanse(pw, sizeof(pw)); + return 1; + } + if (n < 0) + { + fprintf(stderr, "hash_password: read error\n"); + OPENSSL_cleanse(pw, sizeof(pw)); + return 1; + } + if (n == 0) + { + fprintf(stderr, "hash_password: empty password\n"); + OPENSSL_cleanse(pw, sizeof(pw)); + return 1; + } + + char encoded_hash[AUTH_CRYPTO_PASSWORD_HASH_ENCODED_SIZE]; + Auth_Crypto_Result result = + Auth_Crypto_Password_Hash(pw, encoded_hash, sizeof(encoded_hash)); + OPENSSL_cleanse(pw, sizeof(pw)); + + if (result != AUTH_CRYPTO_OK) + { + fprintf(stderr, "hash_password: %s\n", Auth_Crypto_Result_String(result)); + return 1; + } + + puts(encoded_hash); + return 0; +}