logo

skeud

Simple and portable utilities to deal with user accounts (su, login)git clone https://anongit.hacktivis.me/git/skeud.git/
commit: e016382605f6cdc93afc3bd63d8df6a53225b80c
parent 43250cd651ad96a1b50d06de1dccda647af69509
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Sun, 28 Sep 2025 13:51:15 +0200

argv0, no-strlen hash_match

Diffstat:

Mcommon.c25++++++++++---------------
Mcommon.h7+++++--
Mcommon_test.c40+++++++++++++---------------------------
Mlogin.c3++-
Msu.c3++-
5 files changed, 32 insertions(+), 46 deletions(-)

diff --git a/common.c b/common.c @@ -13,25 +13,20 @@ #include <termios.h> // tcgetattr, tcsetattr #include <unistd.h> // crypt -#ifndef MIN +#undef 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 +// Needs to be constant-time bool -hash_match(const char *a, const char *b) +hash_match(const char *a, size_t alen, const char *b, size_t blen) { - /* 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; + size_t n = MIN(alen, blen); + bool ret = true; for(size_t i = 0; i < n; i++) if(a[i] != b[i]) ret = false; - if(len_a != len_b) + if(alen != blen) return false; else return ret; @@ -40,18 +35,18 @@ hash_match(const char *a, const char *b) bool skeud_crypt_check(const char *hash, const char *password) { - if(!hash) return false; - if(strcmp(hash, "") == 0) return false; + size_t hashlen = strlen0(hash); + if(hashlen == 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"); + fprintf(stderr, "%s: error: Failed hashing password: %s\n", argv0, strerror(errno)); return false; } - bool match = hash_match(hash, chk_hash); + bool match = hash_match(hash, hashlen, chk_hash, strlen(chk_hash)); // cleanup chk_hash = crypt("", hash); diff --git a/common.h b/common.h @@ -4,7 +4,10 @@ #include <stdbool.h> // bool #include <sys/types.h> // ssize_t -size_t smin(size_t a, size_t b); -bool hash_match(const char *a, const char *b); +extern const char *argv0; + +#define strlen0(str) str ? strlen(str) : 0 + +bool hash_match(const char *a, size_t alen, const char *b, size_t blen); bool skeud_crypt_check(const char *hash, const char *password); ssize_t skeud_getpass(char **password); diff --git a/common_test.c b/common_test.c @@ -4,43 +4,26 @@ #include "common.h" #include <stdio.h> +#include <string.h> // strlen + +const char *argv0 = "common_test"; int counter = 0; int err = 0; static void -test_hash_match(int ret, const char *s1, const char *s2) -{ - int id = ++counter; - int got = hash_match(s1, s2); - - if(got == ret) - { - printf("ok %d - hash_match(\"%s\", \"%s\") == %d\n", id, s1, s2, ret); - return; - } - - err = 1; - - printf("not ok %d - hash_match(\"%s\", \"%s\") == %d\n", id, s1, s2, ret); - printf("# Got: %d\n", got); -} - -static void -test_crypt_check(int ret, const char *s1, const char *s2) +check_int(const char *name, int got, int exp) { - int id = ++counter; - int got = skeud_crypt_check(s1, s2); - - if(got == ret) + int id = ++counter; + if(got == exp) { - printf("ok %d - skeud_crypt_check(\"%s\", \"%s\") == %d\n", id, s1, s2, ret); + printf("ok %d - %s ==> %d\n", id, name, exp); return; } err = 1; - printf("not ok %d - skeud_crypt_check(\"%s\", \"%s\") == %d\n", id, s1, s2, ret); + printf("not ok %d - %s ==> %d\n", id, name, exp); printf("# Got: %d\n", got); } @@ -50,11 +33,14 @@ main(void) int plan = 12; printf("1..%d\n", plan); +#define CHECK_INT(func, exp) check_int(#func, func, exp) +#define test_hash_match(exp, s1, s2) CHECK_INT(hash_match(s1, strlen0(s1), s2, strlen0(s2)), exp) test_hash_match(1, "foo", "foo"); test_hash_match(0, "foo", "bar"); test_hash_match(0, "foo", "fooo"); test_hash_match(0, "fooo", "foo"); +#define test_crypt_check(exp, s1, s2) CHECK_INT(skeud_crypt_check(s1, s2), exp) test_crypt_check(0, NULL, "foobar"); test_crypt_check(0, "", "foobar"); test_crypt_check(0, "x", "foobar"); @@ -70,10 +56,10 @@ main(void) test_crypt_check(1, "$5$8VryLuwDTzZ8MSZX$2UIaWB5LcMlhXv7UQIBcFeq8/Dr6PswXZP/SJ09L01B", "foobar"); // SHA512: openssl passwd -6 -noverify - const char *hash = + const char *sha256_hash = "$6$QUEEGuX9dkGlNkTP$IJwcvb6tpm63hoOfm9QJjEgjte/OpcQS3S43zDN95G3diJ5Xc/OlhhbCkUyV/" "A0ARhgQj2D/4m/DWhwvvs3A91"; - test_crypt_check(1, hash, "foobar"); + test_crypt_check(1, sha256_hash, "foobar"); if(counter != plan) { diff --git a/login.c b/login.c @@ -27,7 +27,8 @@ #define TTY_PERMS 0600 extern char **environ; -char *envclear[] = {NULL}; +char *envclear[] = {NULL}; +const char *argv0 = "login"; static int process_pwent(struct passwd *pwent) diff --git a/su.c b/su.c @@ -23,7 +23,8 @@ #include <unistd.h> // getuid, getopt, opt*, chdir, setuid, setgid extern char **environ; -char *envclear[] = {NULL}; +char *envclear[] = {NULL}; +const char *argv0 = "su"; int main(int argc, char *argv[])