aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--Makefile23
-rw-r--r--README4
-rw-r--r--config.mk7
-rw-r--r--crypt.c61
-rw-r--r--crypt.h13
-rw-r--r--key2root-addkey.821
-rw-r--r--key2root-addkey.c116
-rw-r--r--key2root-crypt.8109
-rw-r--r--key2root-crypt.c78
-rw-r--r--key2root-lskeys.83
-rw-r--r--key2root-rmkey.83
-rw-r--r--key2root.81
-rw-r--r--key2root.c12
14 files changed, 360 insertions, 94 deletions
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 <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <libar2simplified.h>
+#include <libar2.h>
+
+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 <stddef.h>
+#include <libar2.h>
+
+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 <sys/auxv.h>
-#include <sys/mman.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
@@ -11,6 +9,7 @@
#include <unistd.h>
#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 <stdin>: %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 <stdin>: %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 <stdin>: %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 <key> %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 <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#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 <stdin>: %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 <stdin>: %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 <unistd.h>
#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) &&