common.c (2444B)
- // SPDX-FileCopyrightText: 2022 Haelwenn (lanodan) Monnier <contact+skeud@hacktivis.me>
- // SPDX-License-Identifier: MPL-2.0
- #define _POSIX_C_SOURCE 200809L
- // for explicit_bzero and termios
- #define _DEFAULT_SOURCE
- #include "common.h"
- #include <errno.h> // errno
- #include <stdio.h> // fclose, fopen, fprintf, perror, getline, fileno
- #include <string.h> // explicit_bzero
- #include <termios.h> // tcgetattr, tcsetattr
- #include <unistd.h> // crypt
- size_t
- smin(size_t a, size_t b)
- {
- return a < b ? a : b;
- }
- // Needs to be constant-time so the hash can't be guessed via using a rainbow-table
- bool
- hash_match(char *a, char *b)
- {
- /* flawfinder: ignore CWE-126 */
- size_t len_a = strlen(a);
- /* flawfinder: ignore CWE-126 */
- size_t len_b = strlen(b);
- size_t n = smin(len_a, len_b);
- bool ret = true;
- for(size_t i = 0; i < n; i++)
- if(a[i] != b[i]) ret = false;
- if(len_a != len_b)
- return false;
- else
- return ret;
- }
- bool
- skeud_crypt_check(char *hash, char *password)
- {
- if(!hash) return false;
- if(strcmp(hash, "") == 0) return false;
- /* flawfinder: ignore CWE-327, crypt is the only relevant function */
- char *chk_hash = crypt(password, hash);
- if(chk_hash == NULL)
- {
- perror("skeud_crypt_check: crypt");
- return false;
- }
- bool match = hash_match(hash, chk_hash);
- explicit_bzero(chk_hash, sizeof(chk_hash));
- return match;
- }
- ssize_t
- skeud_getpass(char **password)
- {
- struct termios t;
- size_t len = 0;
- ssize_t got = -1;
- /* flawfinder: ignore CWE-362 */
- FILE *tty = fopen("/dev/tty", "rb+");
- if(tty == NULL)
- {
- perror("skeud_getpass: open(\"/dev/tty\")");
- return got;
- }
- int tty_fd = fileno(tty);
- if(tty_fd < 0)
- {
- perror("skeud_getpass: fileno(tty)");
- goto getpass_end;
- }
- if(tcgetattr(tty_fd, &t) < 0)
- {
- perror("skeud_getpass: tcgetattr");
- goto getpass_end;
- }
- fprintf(tty, "Password: ");
- t.c_lflag &= ~ECHO;
- if(tcsetattr(tty_fd, TCSANOW, &t) < 0)
- {
- perror("skeud_getpass: tcsetattr(~ECHO)");
- goto getpass_end;
- }
- errno = 0;
- got = getline(password, &len, tty);
- fprintf(tty, "\n");
- if(got < 0)
- {
- if(errno != 0) perror("skeud_getpass: getline");
- goto getpass_clean;
- }
- (*password)[got] = 0;
- (*password)[got - 1] = 0;
- got--;
- getpass_clean:
- t.c_lflag ^= ECHO;
- if(tcsetattr(tty_fd, TCSANOW, &t) < 0)
- {
- perror("skeud_getpass: tcsetattr(ECHO)");
- explicit_bzero(password, got);
- got = -1;
- goto getpass_end;
- }
- getpass_end:
- fclose(tty);
- return got;
- }