common.c (2561B)
- // 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
 - #ifndef MIN
 - #define MIN(a, b) (((a) < (b)) ? (a) : (b))
 - #endif
 - // Needs to be constant-time so the hash can't be guessed via using a rainbow-table
 - bool
 - hash_match(const char *a, const 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 = MIN(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(const char *hash, const 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: error: crypt");
 - return false;
 - }
 - bool match = hash_match(hash, chk_hash);
 - // cleanup
 - chk_hash = crypt("", 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: error: open(\"/dev/tty\")");
 - return got;
 - }
 - int tty_fd = fileno(tty);
 - if(tty_fd < 0)
 - {
 - perror("skeud_getpass: error: fileno(tty)");
 - goto getpass_end;
 - }
 - if(tcgetattr(tty_fd, &t) < 0)
 - {
 - perror("skeud_getpass: error: tcgetattr");
 - goto getpass_end;
 - }
 - const char *prompt = "Password: ";
 - write(tty_fd, prompt, strlen(prompt));
 - t.c_lflag &= ~ECHO;
 - if(tcsetattr(tty_fd, TCSANOW, &t) < 0)
 - {
 - perror("skeud_getpass: error: tcsetattr(~ECHO)");
 - goto getpass_end;
 - }
 - errno = 0;
 - got = getline(password, &len, tty);
 - if(got < 0)
 - {
 - if(errno != 0) perror("skeud_getpass: error: getline");
 - goto getpass_clean;
 - }
 - fputs("\n", tty);
 - (*password)[got] = 0;
 - (*password)[got - 1] = 0;
 - got--;
 - getpass_clean:
 - t.c_lflag ^= ECHO;
 - if(tcsetattr(tty_fd, TCSANOW, &t) < 0)
 - {
 - perror("skeud_getpass: error: tcsetattr(ECHO)");
 - explicit_bzero(password, got);
 - got = -1;
 - goto getpass_end;
 - }
 - getpass_end:
 - fclose(tty);
 - return got;
 - }