Mercurial
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 263:ee04e4e69fed | 264:04fee26ecce0 |
|---|---|
| 1 #include "auth/auth_crypto.h" | |
| 2 | |
| 3 #include <openssl/crypto.h> | |
| 4 | |
| 5 #include <stdio.h> | |
| 6 #include <string.h> | |
| 7 #include <termios.h> | |
| 8 #include <unistd.h> | |
| 9 | |
| 10 #define PW_MAX AUTH_CRYPTO_PASSWORD_MAX_BYTES | |
| 11 | |
| 12 static int read_password(int fd, char *buf, size_t capacity) | |
| 13 { | |
| 14 size_t len = 0; | |
| 15 int too_long = 0; | |
| 16 for (;;) | |
| 17 { | |
| 18 unsigned char c; | |
| 19 int r = (int)read(fd, &c, 1); | |
| 20 if (r < 0) | |
| 21 return -1; | |
| 22 if (r == 0) | |
| 23 break; | |
| 24 if (c == '\n' || c == '\r') | |
| 25 break; | |
| 26 if (len + 1 >= capacity) | |
| 27 { | |
| 28 too_long = 1; | |
| 29 continue; | |
| 30 } | |
| 31 buf[len++] = (char)c; | |
| 32 } | |
| 33 buf[len] = '\0'; | |
| 34 return too_long ? -2 : (int)len; | |
| 35 } | |
| 36 | |
| 37 int main(int argc, char **argv) | |
| 38 { | |
| 39 (void)argc; | |
| 40 (void)argv; | |
| 41 | |
| 42 int fd = STDIN_FILENO; | |
| 43 int is_tty = isatty(fd); | |
| 44 struct termios old_term; | |
| 45 struct termios new_term; | |
| 46 int restored = 0; | |
| 47 | |
| 48 if (is_tty) | |
| 49 { | |
| 50 if (tcgetattr(fd, &old_term) != 0) | |
| 51 { | |
| 52 fprintf(stderr, "hash_password: failed to get terminal attributes\n"); | |
| 53 return 1; | |
| 54 } | |
| 55 new_term = old_term; | |
| 56 new_term.c_lflag &= (tcflag_t)~(ECHO | ECHOE | ECHOK | ECHONL); | |
| 57 new_term.c_lflag |= ICANON; | |
| 58 if (tcsetattr(fd, TCSAFLUSH, &new_term) != 0) | |
| 59 { | |
| 60 fprintf(stderr, "hash_password: failed to disable echo\n"); | |
| 61 return 1; | |
| 62 } | |
| 63 restored = 1; | |
| 64 fprintf(stderr, "Password: "); | |
| 65 fflush(stderr); | |
| 66 } | |
| 67 | |
| 68 char pw[PW_MAX + 1]; | |
| 69 memset(pw, 0, sizeof(pw)); | |
| 70 int n = read_password(fd, pw, sizeof(pw)); | |
| 71 | |
| 72 if (restored) | |
| 73 { | |
| 74 tcsetattr(fd, TCSAFLUSH, &old_term); | |
| 75 fprintf(stderr, "\n"); | |
| 76 } | |
| 77 | |
| 78 if (n == -2) | |
| 79 { | |
| 80 fprintf(stderr, "hash_password: %s\n", | |
| 81 Auth_Crypto_Result_String(AUTH_CRYPTO_PASSWORD_TOO_LONG)); | |
| 82 OPENSSL_cleanse(pw, sizeof(pw)); | |
| 83 return 1; | |
| 84 } | |
| 85 if (n < 0) | |
| 86 { | |
| 87 fprintf(stderr, "hash_password: read error\n"); | |
| 88 OPENSSL_cleanse(pw, sizeof(pw)); | |
| 89 return 1; | |
| 90 } | |
| 91 if (n == 0) | |
| 92 { | |
| 93 fprintf(stderr, "hash_password: empty password\n"); | |
| 94 OPENSSL_cleanse(pw, sizeof(pw)); | |
| 95 return 1; | |
| 96 } | |
| 97 | |
| 98 char encoded_hash[AUTH_CRYPTO_PASSWORD_HASH_ENCODED_SIZE]; | |
| 99 Auth_Crypto_Result result = | |
| 100 Auth_Crypto_Password_Hash(pw, encoded_hash, sizeof(encoded_hash)); | |
| 101 OPENSSL_cleanse(pw, sizeof(pw)); | |
| 102 | |
| 103 if (result != AUTH_CRYPTO_OK) | |
| 104 { | |
| 105 fprintf(stderr, "hash_password: %s\n", Auth_Crypto_Result_String(result)); | |
| 106 return 1; | |
| 107 } | |
| 108 | |
| 109 puts(encoded_hash); | |
| 110 return 0; | |
| 111 } |