From 7281ae7db4d9bc9eb2b59134e1dea1231013f1af Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Fri, 23 Jun 2023 19:15:49 +0200 Subject: Use libar2simplified instead of crypt as crypt has a verily limited imput size, and add -h to key2root-addkey, and add key2root-crypt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- .gitignore | 3 +- Makefile | 23 +++++++---- README | 4 +- config.mk | 7 ++-- crypt.c | 61 ++++++++++++++++++++++++++++ crypt.h | 13 ++++++ key2root-addkey.8 | 21 ++++++++-- key2root-addkey.c | 116 +++++++++++++++++++++++------------------------------- key2root-crypt.8 | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++ key2root-crypt.c | 78 ++++++++++++++++++++++++++++++++++++ key2root-lskeys.8 | 3 +- key2root-rmkey.8 | 3 +- key2root.8 | 1 + key2root.c | 12 ++---- 14 files changed, 360 insertions(+), 94 deletions(-) create mode 100644 crypt.c create mode 100644 crypt.h create mode 100644 key2root-crypt.8 create mode 100644 key2root-crypt.c diff --git a/.gitignore b/.gitignore index d941ef3..354feb0 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ *.gcno *.gcda /key2root -/key2root-lskeys /key2root-addkey +/key2root-crypt +/key2root-lskeys /key2root-rmkey diff --git a/Makefile b/Makefile index ceafda7..86af4e2 100644 --- a/Makefile +++ b/Makefile @@ -3,12 +3,12 @@ CONFIGFILE = config.mk include $(CONFIGFILE) -BIN = key2root key2root-lskeys key2root-addkey key2root-rmkey +BIN = key2root key2root-lskeys key2root-addkey key2root-rmkey key2root-crypt -HDR = arg.h +HDR = arg.h crypt.h MAN8 = $(BIN:=.8) -OBJ = $(BIN:=.o) +OBJ = $(BIN:=.o) crypt.o all: $(BIN) $(OBJ): $(HDR) @@ -16,11 +16,20 @@ $(OBJ): $(HDR) .c.o: $(CC) -c -o $@ $< $(CFLAGS) $(CPPFLAGS) -.o: - $(CC) -o $@ $< $(LDFLAGS) +key2root: key2root.o crypt.o + $(CC) -o $@ $@.o crypt.o $(LDFLAGS_CRYPT) -.c: - $(CC) -o $@ $< $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) +key2root-lskeys: key2root-lskeys.o + $(CC) -o $@ $@.o $(LDFLAGS) + +key2root-addkey: key2root-addkey.o crypt.o + $(CC) -o $@ $@.o crypt.o $(LDFLAGS_CRYPT) + +key2root-rmkey: key2root-rmkey.o + $(CC) -o $@ $@.o $(LDFLAGS) + +key2root-crypt: key2root-crypt.o crypt.o + $(CC) -o $@ $@.o crypt.o $(LDFLAGS_CRYPT) install: $(BIN) mkdir -p -- "$(DESTDIR)$(PREFIX)/bin" diff --git a/README b/README index a77dc65..35fa5ab 100644 --- a/README +++ b/README @@ -45,5 +45,5 @@ RATIONALE authenticated himself rather also requiring his password. SEE ALSO - key2root-addkey(8), key2root-lskeys(8), key2root-rmkey(8), asroot(8), - sudo(8), doas(1), su(1) + key2root-addkey(8), key2root-crypt(8), key2root-lskeys(8), + key2root-rmkey(8), asroot(8), sudo(8), doas(1), su(1) diff --git a/config.mk b/config.mk index 38b5163..f9d2bf8 100644 --- a/config.mk +++ b/config.mk @@ -5,6 +5,7 @@ KEYPATH = /etc/key2root CC = cc -CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_GNU_SOURCE -D'KEYPATH="$(KEYPATH)"' -CFLAGS = -std=c99 -Wall -O2 -LDFLAGS = -lcrypt +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_GNU_SOURCE -D'KEYPATH="$(KEYPATH)"' +CFLAGS = -std=c99 -Wall -O2 +LDFLAGS = +LDFLAGS_CRYPT = $(LDFLAGS) -lar2simplified -lar2 -lblake -pthread diff --git a/crypt.c b/crypt.c new file mode 100644 index 0000000..ca3626d --- /dev/null +++ b/crypt.c @@ -0,0 +1,61 @@ +/* See LICENSE file for copyright and license details. */ +#include "crypt.h" +#include +#include +#include +#include +#include +#include + +extern char *argv0; + + +char * +key2root_crypt(char *msg, size_t msglen, const char *paramstr, int autoerase) +{ + struct libar2_argon2_parameters *params = NULL; + char *end, *ret = NULL, *hash = NULL; + size_t size; + struct libar2_context ctx; + + libar2simplified_init_context(&ctx); + ctx.autoerase_message = (unsigned char)autoerase; + + if (!paramstr) + paramstr = libar2simplified_recommendation(0); + + params = libar2simplified_decode_r(paramstr, NULL, &end, NULL, NULL); + if (!params) { + fprintf(stderr, "%s: libar2simplified_decode_r %s: %s\n", argv0, paramstr, strerror(errno)); + return NULL; + } + if (*end) { + fprintf(stderr, "%s: libar2simplified_decode_r %s: excess data at end parameter string: %s\n", argv0, paramstr, end); + goto out; + } + + size = libar2_hash_buf_size(params); + if (!size) + abort(); + if (!size || !(hash = malloc(size))) { + fprintf(stderr, "%s: malloc %zu: %s\n", argv0, size, strerror(errno)); + goto out; + } + + if (libar2_hash(hash, msg, msglen, params, &ctx)) { + if (autoerase) + libar2_erase(msg, msglen); + fprintf(stderr, "%s: libar2simplified_hash %s: %s\n", argv0, paramstr, strerror(errno)); + goto out; + } + + ret = libar2simplified_encode(params, hash); + +out: + if (params) { + libar2_erase(params->salt, params->saltlen); + free(params); + } + free(hash); + return ret; +} diff --git a/crypt.h b/crypt.h new file mode 100644 index 0000000..60621c5 --- /dev/null +++ b/crypt.h @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include + +char *key2root_crypt(char *msg, size_t msglen, const char *paramstr, int autoerase); + + +#define explicit_bzero key2root_erase +static inline void +key2root_erase(void *msg, size_t msglen) +{ + libar2_erase(msg, msglen); +} diff --git a/key2root-addkey.8 b/key2root-addkey.8 index 9faf335..1594d7f 100644 --- a/key2root-addkey.8 +++ b/key2root-addkey.8 @@ -6,9 +6,13 @@ key2root-addkey - add a keyfile for privilege escalation with key2root .SH SYNOPSIS .B key2root-addkey [-r] -.I user +.RI (user .I key-name .RI [ crypt-parameters ] +| -h +.I user +.I key-name +.IR key-hash ) .SH DESCRIPTION The @@ -45,19 +49,27 @@ The name the keyfile shall be given. May not include whitespace characters. .TP .I crypt-parameters -crypt(3) parameters that the keyfile shall be hashed with. +.BR libar2simplified_crypt (3) +parameters that the keyfile shall be hashed with. +.TP +.I key-hash +.BR key2root-crypt (8) +hash of the keyfile. .SH STDIN The .B key2root-addkey utility reads the keyfile to add from standard input, -which must not be a TTY. +which must not be a TTY. However if the +.B -h +option is used, the standard input is not used and +may be a TTY. .SH INPUT FILES None. .SH ENVIRONMENT VARIABLES -No following environment variable affects the execution of +No environment variables affect the execution of .BR key2root-addkey . .SH ASYNCHRONOUS EVENTS @@ -111,6 +123,7 @@ None. .SH SEE ALSO .BR key2root (8), +.BR key2root-crypt (8), .BR key2root-lskeys (8), .BR key2root-rmkey (8) diff --git a/key2root-addkey.c b/key2root-addkey.c index 989aa8f..cbb1d0e 100644 --- a/key2root-addkey.c +++ b/key2root-addkey.c @@ -1,6 +1,4 @@ /* See LICENSE file for copyright and license details. */ -#include -#include #include #include #include @@ -11,6 +9,7 @@ #include #include "arg.h" +#include "crypt.h" char *argv0; @@ -19,7 +18,7 @@ char *argv0; static void usage(void) { - fprintf(stderr, "usage: %s [-r] user key-name [crypt-parameters]\n", argv0); + fprintf(stderr, "usage: %s [-r] (user key-name [crypt-parameters] | -h user key-name key-hash)\n", argv0); exit(1); } @@ -119,27 +118,6 @@ loadandlocate(size_t *beginning_out, size_t *end_out, int fd, char **datap, size } -static char * -mksalt(char *p) -{ - uintptr_t rdata_addr; - char *rdata; - size_t i; - - rdata_addr = (uintptr_t)getauxval(AT_RANDOM); /* address to 16 random bytes */ - rdata = (void *)rdata_addr; - if (!rdata) { - fprintf(stderr, "%s: getauxval AT_RANDOM: %s\n", argv0, strerror(errno)); - exit(1); - } - - for (i = 0; i < 16; i++) - *p++ = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789./"[*rdata++ & 63]; - - return p; -} - - int main(int argc, char *argv[]) { @@ -153,6 +131,7 @@ main(int argc, char *argv[]) size_t beginning = 0; size_t end = 0; int allow_replace = 0; + int add_hash = 0; int failed = 0; int fd; char *key = NULL, *new; @@ -161,12 +140,13 @@ main(int argc, char *argv[]) char *hash; size_t gap_size; size_t gap_increase; -#define HASH_PREFIX "$6$" - char generated_parameters[sizeof(HASH_PREFIX"$") + 16]; ssize_t r; size_t i; ARGBEGIN { + case 'h': + add_hash = 1; + break; case 'r': allow_replace = 1; break; @@ -189,60 +169,64 @@ main(int argc, char *argv[]) fprintf(stderr, "%s: bad key name specified: %s, includes whitespace\n", argv0, keyname); failed = 1; } - if (isatty(STDIN_FILENO)) { + if (!add_hash && isatty(STDIN_FILENO)) { fprintf(stderr, "%s: standard input must not be a TTY.\n", argv0); failed = 1; } if (failed) return 1; - if (mlockall(MCL_CURRENT | MCL_FUTURE)) - fprintf(stderr, "%s: mlockall MCL_CURRENT|MCL_FUTURE: %s\n", argv0, strerror(errno)); - - if (!parameters) { - stpcpy(mksalt(stpcpy(generated_parameters, HASH_PREFIX)), "$"); - parameters = generated_parameters; - } - - for (;;) { - if (key_len == key_size) { - new = malloc(1 + (key_size += 1024)); - if (!new) { + if (add_hash) { + for (i = 0; parameters[i]; i++) { + if (parameters[i] <= ' ' || parameters[i] >= 127) { + fprintf(stderr, "%s: key-hash may only contain printable ASCII characters\n", argv0); + exit(1); + } + } + key_size = key_len = strlen(keyname) + strlen(parameters) + 2; + key = malloc(key_len + 1); + if (!key) { + fprintf(stderr, "%s: malloc: %s\n", argv0, strerror(errno)); + exit(1); + } + stpcpy(stpcpy(stpcpy(stpcpy(key, keyname), " "), parameters), "\n"); + } else { + for (;;) { + if (key_len == key_size) { + new = malloc(1 + (key_size += 1024)); + if (!new) { + explicit_bzero(key, key_len); + fprintf(stderr, "%s: read : %s\n", argv0, strerror(errno)); + exit(1); + } + memcpy(new, key, key_len); + explicit_bzero(key, key_len); + free(key); + key = new; + } + r = read(STDIN_FILENO, &key[key_len], key_size - key_len); + if (r <= 0) { + if (!r) + break; explicit_bzero(key, key_len); fprintf(stderr, "%s: read : %s\n", argv0, strerror(errno)); exit(1); } - memcpy(new, key, key_len); - explicit_bzero(key, key_len); - free(key); - key = new; + key_len += (size_t)r; } - r = read(STDIN_FILENO, &key[key_len], key_size - key_len); - if (r <= 0) { - if (!r) - break; - explicit_bzero(key, key_len); - fprintf(stderr, "%s: read : %s\n", argv0, strerror(errno)); + hash = key2root_crypt(key, key_len, parameters, 1); + if (!hash) + exit(1); + free(key); + key_size = key_len = strlen(keyname) + strlen(hash) + 2; + key = malloc(key_len + 1); + if (!key) { + fprintf(stderr, "%s: malloc: %s\n", argv0, strerror(errno)); exit(1); } - key_len += (size_t)r; - } - for (i = 0; i < key_len; i++) - if (!key[i]) - key[i] = (char)255; - key[key_len] = '\0'; - hash = crypt(key, parameters); - if (!hash) - fprintf(stderr, "%s: crypt %s: %s\n", argv0, parameters, strerror(errno)); - explicit_bzero(key, key_len); - free(key); - key_size = key_len = strlen(keyname) + strlen(hash) + 2; - key = malloc(key_len + 1); - if (!key) { - fprintf(stderr, "%s: malloc: %s\n", argv0, strerror(errno)); - exit(1); + stpcpy(stpcpy(stpcpy(stpcpy(key, keyname), " "), hash), "\n"); + free(hash); } - stpcpy(stpcpy(stpcpy(stpcpy(key, keyname), " "), hash), "\n"); path = malloc(sizeof(KEYPATH"/") + strlen(user)); if (!path) { diff --git a/key2root-crypt.8 b/key2root-crypt.8 new file mode 100644 index 0000000..7e0bf33 --- /dev/null +++ b/key2root-crypt.8 @@ -0,0 +1,109 @@ +.TH KEY2ROOT 8 key2root-crypt + +.SH NAME +key2root-crypt - generate key hash for key2root + +.SH SYNOPSIS +.B key2root-crypt +.RI [ crypt-parameters ] + +.SH DESCRIPTION +The +.B key2root-crypt +utility takes a keyfile from the standard input and computes +its cryptographic as stored by the +.BR key2root-addkey (8) +utility. + +.SH OPTIONS +The +.B key2root-crypt +utility conforms to the Base Definitions volume of POSIX.1-2017, +.IR "Section 12.2" , +.IR "Utility Syntax Guidelines" . +.PP +No options are supported. + +.SH OPERANDS +The following operands are supported: +.TP +.I crypt-parameters +.BR libar2simplified_crypt (3) +parameters that the keyfile shall be hashed with. + +.SH STDIN +The +.B key2root-crypt +utility reads the keyfile to add from standard input. + +.SH INPUT FILES +None. + +.SH ENVIRONMENT VARIABLES +No environment variable affect the execution of +.BR key2root-crypt . + +.SH ASYNCHRONOUS EVENTS +Default. + +.SH STDOUT +The +.B key2root-crypt +utility prints the hash of the key files to the standard output, in the following format: +.RS +.nf + +\fB\(dq%s\en\(dq, \fP<\fIkey-hash\fP> +.fi +.RE + +.SH STDERR +The standard error is used for diagnostic messages. + +.SH OUTPUT FILES +None. + +.SH EXTENDED DESCRIPTION +None. + +.SH EXIT STATUS +If the +.B key2root-crypt +utility fails it will exit with one of the following statuses: +.TP +0 +Successful completion. +.TP +1 +A error occurred. + +.SH CONSEQUENCES OF ERRORS +Default. + +.SH APPLICATION USAGE +None. + +.SH EXAMPLES +None. + +.SH RATIONALE +None. + +.SH NOTES +None. + +.SH BUGS +None. + +.SH FUTURE DIRECTIONS +None. + +.SH SEE ALSO +.BR key2root (8), +.BR key2root-addkey (8), +.BR key2root-lskeys (8), +.BR key2root-rmkey (8) + +.SH AUTHORS +Mattias Andrée +.RI < maandree@kth.se > diff --git a/key2root-crypt.c b/key2root-crypt.c new file mode 100644 index 0000000..961e00c --- /dev/null +++ b/key2root-crypt.c @@ -0,0 +1,78 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include + +#include "arg.h" +#include "crypt.h" + + +char *argv0; + + +static void +usage(void) +{ + fprintf(stderr, "usage: %s [crypt-parameters]\n", argv0); + exit(1); +} + + +int +main(int argc, char *argv[]) +{ + const char *parameters; + char *key = NULL, *new; + size_t key_len = 0; + size_t key_size = 0; + char *hash; + ssize_t r; + + ARGBEGIN { + default: + usage(); + } ARGEND; + + if (argc > 1) + usage(); + + parameters = argv[0]; + + for (;;) { + if (key_len == key_size) { + new = malloc(1 + (key_size += 1024)); + if (!new) { + explicit_bzero(key, key_len); + fprintf(stderr, "%s: read : %s\n", argv0, strerror(errno)); + exit(1); + } + memcpy(new, key, key_len); + explicit_bzero(key, key_len); + free(key); + key = new; + } + r = read(STDIN_FILENO, &key[key_len], key_size - key_len); + if (r <= 0) { + if (!r) + break; + explicit_bzero(key, key_len); + fprintf(stderr, "%s: read : %s\n", argv0, strerror(errno)); + exit(1); + } + key_len += (size_t)r; + } + hash = key2root_crypt(key, key_len, parameters, 1); + if (!hash) + exit(1); + free(key); + printf("%s\n", hash); + free(hash); + + if (fflush(stdout) || ferror(stdout) || fclose(stdout)) { + fprintf(stderr, "%s: printf: %s\n", argv0, strerror(errno)); + exit(1); + } + return 0; +} diff --git a/key2root-lskeys.8 b/key2root-lskeys.8 index f6f58cf..1df2713 100644 --- a/key2root-lskeys.8 +++ b/key2root-lskeys.8 @@ -45,7 +45,7 @@ utility does not use the standard input. None. .SH ENVIRONMENT VARIABLES -No following environment variable affects the execution of +No environment variables affect the execution of .BR key2root-lskeys . .SH ASYNCHRONOUS EVENTS @@ -111,6 +111,7 @@ None. .SH SEE ALSO .BR key2root (8), .BR key2root-addkey (8), +.BR key2root-crypt (8), .BR key2root-rmkey (8) .SH AUTHORS diff --git a/key2root-rmkey.8 b/key2root-rmkey.8 index d79544c..ce93754 100644 --- a/key2root-rmkey.8 +++ b/key2root-rmkey.8 @@ -47,7 +47,7 @@ utility does not use the standard input. None. .SH ENVIRONMENT VARIABLES -No following environment variable affects the execution of +No environment variables affect the execution of .BR key2root-rmkey . .SH ASYNCHRONOUS EVENTS @@ -112,6 +112,7 @@ None. .SH SEE ALSO .BR key2root (8), .BR key2root-addkey (8), +.BR key2root-crypt (8), .BR key2root-lskeys (8) .SH AUTHORS diff --git a/key2root.8 b/key2root.8 index 3747254..ebba529 100644 --- a/key2root.8 +++ b/key2root.8 @@ -151,6 +151,7 @@ None. .SH SEE ALSO .BR key2root-addkey (8), +.BR key2root-crypt (8), .BR key2root-lskeys (8), .BR key2root-rmkey (8), .BR asroot (8), diff --git a/key2root.c b/key2root.c index 450ca00..49febd2 100644 --- a/key2root.c +++ b/key2root.c @@ -12,6 +12,7 @@ #include #include "arg.h" +#include "crypt.h" #define EXIT_AUTH 124 @@ -276,8 +277,9 @@ checkauth(char *data, size_t whead, size_t *rheadp, size_t *rhead2p, size_t *lin *rheadp += keyname_len + 1; *key_foundp = 1; data[(*rhead2p)++] = '\0'; - hash = crypt(key, &data[*rheadp]); + hash = key2root_crypt(key, key_len, &data[*rheadp], 0); match = hash && hashequal(hash, &data[*rheadp]); + free(hash); *rheadp = *rhead2p; return match; } @@ -360,7 +362,6 @@ main(int argc, char *argv[]) char path_user_id[sizeof(KEYPATH"/") + 3 * sizeof(uintmax_t)]; char *path_user_name; struct passwd *pwd; - size_t i; ARGBEGIN { case 'e': @@ -378,9 +379,6 @@ main(int argc, char *argv[]) if (!argc) usage(); - if (mlockall(MCL_CURRENT | MCL_FUTURE)) - fprintf(stderr, "%s: mlockall MCL_CURRENT|MCL_FUTURE: %s\n", argv0, strerror(errno)); - sprintf(path_user_id, "%s/%ju", KEYPATH, (uintmax_t)getuid()); errno = 0; pwd = getpwuid(getuid()); @@ -421,10 +419,6 @@ main(int argc, char *argv[]) } key_len += (size_t)r; } - for (i = 0; i < key_len; i++) - if (!key[i]) - key[i] = (char)255; - key[key_len] = '\0'; key_found = 0; if (!authenticate(path_user_id, key_name, key, key_len, &key_found) && -- cgit v1.2.3-70-g09d2