diff options
Diffstat (limited to '')
-rw-r--r-- | key2root-addkey.c | 13 | ||||
-rw-r--r-- | key2root-lskeys.c | 6 | ||||
-rw-r--r-- | key2root-rmkey.8 | 5 | ||||
-rw-r--r-- | key2root-rmkey.c | 188 |
4 files changed, 205 insertions, 7 deletions
diff --git a/key2root-addkey.c b/key2root-addkey.c index d5ec701..c80ebbe 100644 --- a/key2root-addkey.c +++ b/key2root-addkey.c @@ -1,6 +1,10 @@ /* See LICENSE file for copyright and license details. */ +#include <sys/mman.h> +#include <errno.h> +#include <fcntl.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <unistd.h> #include "arg.h" @@ -56,7 +60,14 @@ main(int argc, char *argv[]) if (failed) return 1; - /* TODO */ + if (mlockall(MCL_CURRENT | MCL_FUTURE)) { + fprintf(stderr, "%s: mlockall MCL_CURRENT|MCL_FUTURE: %s\n", argv0, strerror(errno)); + exit(1); + } + + /* TODO hash input */ + /* TODO add or replace key */ + /* TODO save changes, mode shall be 0700 */ return 0; } diff --git a/key2root-lskeys.c b/key2root-lskeys.c index 7dee003..69e6319 100644 --- a/key2root-lskeys.c +++ b/key2root-lskeys.c @@ -91,7 +91,7 @@ listkeys(int dir, const char *user) } } r = read(fd, &data[whead], size - whead); - if (r <= 0) { + if (r < 0) { fprintf(stderr, "%s: read /etc/key2root/%s: %s\n", argv0, user, strerror(errno)); close(fd); return 1; @@ -102,8 +102,10 @@ listkeys(int dir, const char *user) failed |= outputkey(data, whead, &rhead, &rhead2, &lineno, user); } - if (rhead != whead) + if (rhead != whead) { fprintf(stderr, "%s: file truncated: /etc/key2root/%s\n", argv0, user); + failed = 1; + } close(fd); return failed; diff --git a/key2root-rmkey.8 b/key2root-rmkey.8 index fe01c93..d79544c 100644 --- a/key2root-rmkey.8 +++ b/key2root-rmkey.8 @@ -97,6 +97,11 @@ associated with the user name, and the user name must be specified when removing it. Likewise if a keyfile was added with a user ID specified, it is only associated with the user ID, and the user ID must be specified when removing it. +.PP +To completely remove a user, remove +.BI /etc/key2root/ user-id +and +.BR /etc/key2root/ \fIuser-name\fP. .SH BUGS None. diff --git a/key2root-rmkey.c b/key2root-rmkey.c index f2ab34d..d3dbc16 100644 --- a/key2root-rmkey.c +++ b/key2root-rmkey.c @@ -1,6 +1,10 @@ /* See LICENSE file for copyright and license details. */ +#include <errno.h> +#include <fcntl.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> +#include <unistd.h> #include "arg.h" @@ -16,11 +20,118 @@ usage(void) } +static int +writeall(int fd, const char *data, size_t len) +{ + size_t off = 0; + ssize_t r; + + for (;;) { + r = write(fd, &data[off], len - off); + if (r < 0) + return -1; + off += (size_t)r; + } + + return 0; +} + + +static void +removekeys(char *data, size_t *wheadp, size_t *rheadp, size_t *rhead2p, size_t *linenop, + const char *path, const char **keys, size_t *nkeysp) +{ + int failed = 0; + size_t len, klen; + size_t i; + + while (*rhead2p < *wheadp || data[*rhead2p] != '\n') + ++*rhead2p; + + if (data[*rhead2p] != '\n') + return; + + len = *rhead2p - *rheadp; + *linenop += 1; + + if (memchr(&data[*rheadp], '\0', len)) { + fprintf(stderr, "%s: NUL byte found in %s on line %zu\n", argv0, path, *linenop); + failed = 1; + } + if (!memchr(&data[*rheadp], ' ', len)) { + fprintf(stderr, "%s: no SP byte found in %s on line %zu\n", argv0, path, *linenop); + failed = 1; + } + + if (failed) { + goto no_match; + } else { + for (i = 0; i < *nkeysp; i++) { + klen = strlen(keys[i]); + if (klen >= len || data[*rheadp + klen] != ' ' || memcpy(&data[*rheadp], keys[i], klen)) + continue; + memmove(&keys[i], &keys[i + 1], (--*nkeysp - i) * sizeof(*keys)); + goto match; + } + no_match: + *rheadp = ++*rhead2p; + return; + match: + ++*rhead2p; + memmove(&data[*rheadp], &data[*rhead2p], *wheadp - *rhead2p); + *wheadp -= *rhead2p - *rheadp; + *rhead2p = *rheadp; + } +} + + +static void +loadandremove(int fd, char **datap, size_t *lenp, size_t *sizep, const char **keys, size_t *nkeysp, const char *path) +{ + char *new; + size_t lineno = 0; + ssize_t r = 1; + size_t rhead = 0; + size_t rhead2 = 0; + + while (r) { + if (*lenp == *sizep) { + new = realloc(*datap, *sizep += 4096); + if (!new) { + fprintf(stderr, "%s: realloc: %s\n", argv0, strerror(errno)); + exit(1); + } + *datap = new; + } + + r = read(fd, &(*datap)[*lenp], *sizep - *lenp); + if (r < 0) { + fprintf(stderr, "%s: read %s: %s\n", argv0, path, strerror(errno)); + exit(1); + } + *lenp += (size_t)r; + + while (rhead2 < *lenp) + removekeys(*datap, lenp, &rhead, &rhead2, &lineno, path, keys, nkeysp); + } + + if (rhead != *lenp) + fprintf(stderr, "%s: file truncated: %s\n", argv0, path); +} + + int main(int argc, char *argv[]) { + char *path, *path2; const char *user; - int i, failed = 0; + int failed = 0; + const char **keys; + size_t i, nkeys; + int fd; + char *data = NULL; + size_t data_len = 0; + size_t data_size = 0; ARGBEGIN { default: @@ -37,7 +148,7 @@ main(int argc, char *argv[]) fprintf(stderr, "%s: bad user name specified: %s\n", argv0, user); failed = 1; } - for (i = 0; i < argc; i++) { + for (i = 0; i < (size_t)argc; i++) { if (argv[i][strcspn(argv[i], " \t\f\n\r\v")]) { fprintf(stderr, "%s: bad key name specified: %s, includes whitespace\n", argv0, argv[i]); failed = 1; @@ -46,7 +157,76 @@ main(int argc, char *argv[]) if (failed) return 1; - /* TODO */ + nkeys = (size_t)argc; + keys = calloc(nkeys, sizeof(*keys)); + if (!keys) { + fprintf(stderr, "%s: calloc: %s\n", argv0, strerror(errno)); + exit(1); + } + for (i = 0; i < (size_t)argc; i++) + keys[i] = argv[i]; - return 0; + path = malloc(sizeof("/etc/key2root/") + strlen(user)); + if (!path) { + fprintf(stderr, "%s: malloc: %s\n", argv0, strerror(errno)); + exit(1); + } + path2 = malloc(sizeof("/etc/key2root/~") + strlen(user)); + if (!path) { + fprintf(stderr, "%s: malloc: %s\n", argv0, strerror(errno)); + exit(1); + } + stpcpy(stpcpy(path, "/etc/key2root/"), user); + stpcpy(stpcpy(path2, path), "~"); + + fd = open(path, O_RDONLY); + if (fd < 0) { + if (errno == ENOENT) + goto out; + fprintf(stderr, "%s: open %s O_RDONLY: %s\n", argv0, path, strerror(errno)); + exit(1); + } + loadandremove(fd, &data, &data_len, &data_size, keys, &nkeys, path); + if (close(fd)) { + fprintf(stderr, "%s: read %s: %s\n", argv0, path, strerror(errno)); + exit(1); + } + +out: + for (i = 0; i < nkeys; i++) + fprintf(stderr, "%s: key not found for %s: %s\n", argv0, user, keys[i]); + failed |= !nkeys; + + if (nkeys != (size_t)argc) { + if (!data_len) { + if (unlink(path)) { + fprintf(stderr, "%s: unlink %s: %s\n", argv0, path, strerror(errno)); + failed = 1; + } + } else { + fd = open(path2, O_WRONLY | O_CREAT | O_EXCL, 0600); + if (fd < 0) { + fprintf(stderr, "%s: open %s O_WRONLY|O_CREAT|O_EXCL 0600: %s\n", argv0, path2, strerror(errno)); + exit(1); + } + if (writeall(fd, data, data_len) || close(fd)) { + fprintf(stderr, "%s: write %s: %s\n", argv0, path2, strerror(errno)); + if (unlink(path2)) + fprintf(stderr, "%s: unlink %s: %s\n", argv0, path2, strerror(errno)); + exit(1); + } + if (rename(path2, path)) { + fprintf(stderr, "%s: rename %s %s: %s\n", argv0, path2, path, strerror(errno)); + if (unlink(path2)) + fprintf(stderr, "%s: unlink %s: %s\n", argv0, path2, strerror(errno)); + exit(1); + } + } + } + + free(keys); + free(path); + free(path2); + free(data); + return failed; } |