diff options
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/rpki-client/extern.h | 4 | ||||
-rw-r--r-- | usr.sbin/rpki-client/main.c | 105 | ||||
-rw-r--r-- | usr.sbin/rpki-client/rsync.c | 4 | ||||
-rw-r--r-- | usr.sbin/rpki-client/tal.c | 110 |
4 files changed, 104 insertions, 119 deletions
diff --git a/usr.sbin/rpki-client/extern.h b/usr.sbin/rpki-client/extern.h index 95bfdf43b0d..666b9955abd 100644 --- a/usr.sbin/rpki-client/extern.h +++ b/usr.sbin/rpki-client/extern.h @@ -1,4 +1,4 @@ -/* $OpenBSD: extern.h,v 1.9 2019/10/16 17:43:29 claudio Exp $ */ +/* $OpenBSD: extern.h,v 1.10 2019/10/31 08:36:43 claudio Exp $ */ /* * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -229,7 +229,7 @@ extern int verbose; void tal_buffer(char **, size_t *, size_t *, const struct tal *); void tal_free(struct tal *); -struct tal *tal_parse(const char *); +struct tal *tal_parse(const char *, char *); struct tal *tal_read(int); void cert_buffer(char **, size_t *, size_t *, const struct cert *); diff --git a/usr.sbin/rpki-client/main.c b/usr.sbin/rpki-client/main.c index 528a476ba6a..95b30b6b861 100644 --- a/usr.sbin/rpki-client/main.c +++ b/usr.sbin/rpki-client/main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.20 2019/10/16 21:43:41 jmc Exp $ */ +/* $OpenBSD: main.c,v 1.21 2019/10/31 08:36:43 claudio Exp $ */ /* * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -22,6 +22,7 @@ #include <sys/wait.h> #include <assert.h> +#include <ctype.h> #include <err.h> #include <dirent.h> #include <fcntl.h> @@ -462,14 +463,64 @@ queue_add_from_mft_set(int fd, struct entityq *q, const struct mft *mft, static void queue_add_tal(int fd, struct entityq *q, const char *file, size_t *eid) { - char *nfile; + char *nfile, *nbuf, *line = NULL, *buf = NULL; + FILE *in; + ssize_t n, i; + size_t sz = 0, bsz = 0; + int optcomment = 1; + + if ((in = fopen(file, "r")) == NULL) + err(EXIT_FAILURE, "fopen: %s", file); + + while ((n = getline(&line, &sz, in)) != -1) { + /* replace CRLF with just LF */ + if (n > 1 && line[n - 1] == '\n' && line[n - 2] == '\r') { + line[n - 2] = '\n'; + line[n - 1] = '\0'; + n--; + } + if (optcomment) { + /* if this is comment, just eat the line */ + if (line[0] == '#') + continue; + optcomment = 0; + /* + * Empty line is end of section and needs + * to be eaten as well. + */ + if (line[0] == '\n') + continue; + } + + /* make sure every line is valid ascii */ + for (i = 0; i < n; i++) + if (!isprint(line[i]) && !isspace(line[i])) + errx(EXIT_FAILURE, "getline: %s: " + "invalid content", file); + + /* concat line to buf */ + if ((nbuf = realloc(buf, bsz + n + 1)) == NULL) + err(EXIT_FAILURE, NULL); + buf = nbuf; + bsz += n + 1; + strlcat(buf, line, bsz); + /* limit the buffer size */ + if (bsz > 4096) + errx(EXIT_FAILURE, "%s: file too big", file); + } + + free(line); + if (ferror(in)) + err(EXIT_FAILURE, "getline: %s", file); + fclose(in); if ((nfile = strdup(file)) == NULL) err(EXIT_FAILURE, "strdup"); /* Not in a repository, so directly add to queue. */ - - entityq_add(fd, q, nfile, RTYPE_TAL, NULL, NULL, NULL, 0, NULL, eid); + entityq_add(fd, q, nfile, RTYPE_TAL, NULL, NULL, NULL, 0, buf, eid); + /* entityq_add makes a copy of buf */ + free(buf); } /* @@ -1020,7 +1071,6 @@ proc_parser(int fd, int force, int norev) X509_STORE *store; X509_STORE_CTX *ctx; struct auth *auths = NULL; - int first_tals = 1; ERR_load_crypto_strings(); OpenSSL_add_all_ciphers(); @@ -1102,31 +1152,12 @@ proc_parser(int fd, int force, int norev) entp = TAILQ_FIRST(&q); assert(entp != NULL); - /* - * Extra security. - * Our TAL files may be anywhere, but the repository - * resources may only be in BASE_DIR. - * When we've finished processing TAL files, make sure - * that we can only see what's under that. - */ - - if (entp->type != RTYPE_TAL && first_tals) { - if (unveil(BASE_DIR, "r") == -1) - err(EXIT_FAILURE, "%s: unveil", BASE_DIR); - if (unveil(NULL, NULL) == -1) - err(EXIT_FAILURE, "unveil"); - first_tals = 0; - } else if (entp->type != RTYPE_TAL) { - assert(!first_tals); - } else if (entp->type == RTYPE_TAL) - assert(first_tals); - entity_buffer_resp(&b, &bsz, &bmax, entp); switch (entp->type) { case RTYPE_TAL: assert(!entp->has_dgst); - if ((tal = tal_parse(entp->uri)) == NULL) + if ((tal = tal_parse(entp->uri, entp->descr)) == NULL) goto out; tal_buffer(&b, &bsz, &bmax, tal); tal_free(tal); @@ -1420,7 +1451,12 @@ main(int argc, char *argv[]) if (procpid == 0) { close(fd[1]); - if (pledge("stdio rpath unveil", NULL) == -1) + /* Only allow access to BASE_DIR. */ + if (unveil(BASE_DIR, "r") == -1) + err(EXIT_FAILURE, "%s: unveil", BASE_DIR); + if (unveil(NULL, NULL) == -1) + err(EXIT_FAILURE, "unveil"); + if (pledge("stdio rpath", NULL) == -1) err(EXIT_FAILURE, "pledge"); proc_parser(fd[0], force, norev); /* NOTREACHED */ @@ -1460,13 +1496,7 @@ main(int argc, char *argv[]) assert(rsync != proc); - /* - * The main process drives the top-down scan to leaf ROAs using - * data downloaded by the rsync process and parsed by the - * parsing process. - */ - - if (pledge("stdio", NULL) == -1) + if (pledge("stdio rpath", NULL) == -1) err(EXIT_FAILURE, "pledge"); /* @@ -1478,6 +1508,15 @@ main(int argc, char *argv[]) for (i = 0; i < talsz; i++) queue_add_tal(proc, &q, tals[i], &eid); + /* + * The main process drives the top-down scan to leaf ROAs using + * data downloaded by the rsync process and parsed by the + * parsing process. + */ + + if (pledge("stdio", NULL) == -1) + err(EXIT_FAILURE, "pledge"); + pfd[0].fd = rsync; pfd[1].fd = proc; pfd[0].events = pfd[1].events = POLLIN; diff --git a/usr.sbin/rpki-client/rsync.c b/usr.sbin/rpki-client/rsync.c index a503390577d..0e54680a8ff 100644 --- a/usr.sbin/rpki-client/rsync.c +++ b/usr.sbin/rpki-client/rsync.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rsync.c,v 1.6 2019/06/19 16:30:37 deraadt Exp $ */ +/* $OpenBSD: rsync.c,v 1.7 2019/10/31 08:36:43 claudio Exp $ */ /* * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -129,8 +129,6 @@ rsync_uri_parse(const char **hostp, size_t *hostsz, *rtypep = RTYPE_CER; else if (strcasecmp(path + sz - 4, ".crl") == 0) *rtypep = RTYPE_CRL; - else if (strcasecmp(path + sz - 4, ".tal") == 0) - *rtypep = RTYPE_TAL; } return 1; diff --git a/usr.sbin/rpki-client/tal.c b/usr.sbin/rpki-client/tal.c index d8d86f7dae9..f6f0742e7a7 100644 --- a/usr.sbin/rpki-client/tal.c +++ b/usr.sbin/rpki-client/tal.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tal.c,v 1.7 2019/10/08 10:04:36 claudio Exp $ */ +/* $OpenBSD: tal.c,v 1.8 2019/10/31 08:36:43 claudio Exp $ */ /* * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -29,18 +29,18 @@ #include "extern.h" /* - * Inner function for parsing RFC 7730 from a file stream. + * Inner function for parsing RFC 7730 from a buffer. * Returns a valid pointer on success, NULL otherwise. * The pointer must be freed with tal_free(). */ static struct tal * -tal_parse_stream(const char *fn, FILE *f) +tal_parse_buffer(const char *fn, char *buf) { - char *line = NULL; + char *nl, *line; unsigned char *b64 = NULL; - size_t sz, b64sz = 0, linesize = 0, lineno = 0; - ssize_t linelen, ssz; - int rc = 0; + size_t sz; + ssize_t linelen; + int rc = 0, b64sz; struct tal *tal = NULL; enum rtype rp; EVP_PKEY *pkey = NULL; @@ -48,27 +48,19 @@ tal_parse_stream(const char *fn, FILE *f) if ((tal = calloc(1, sizeof(struct tal))) == NULL) err(EXIT_FAILURE, NULL); - /* Begin with the URI section. */ + /* Begin with the URI section, comment section already removed. */ + while ((nl = strchr(buf, '\n')) != NULL) { + line = buf; + *nl = '\0'; - while ((linelen = getline(&line, &linesize, f)) != -1) { - lineno++; - assert(linelen); - if (line[linelen - 1] != '\n') { - warnx("%s: RFC 7730 section 2.1: " - "failed to parse URL", fn); - goto out; - } - line[--linelen] = '\0'; - if (linelen && line[linelen - 1] == '\r') - line[--linelen] = '\0'; + /* advance buffer to next line */ + buf = nl + 1; /* Zero-length line is end of section. */ - - if (linelen == 0) + if (*line == '\0') break; /* Append to list of URIs. */ - tal->uri = reallocarray(tal->uri, tal->urisz + 1, sizeof(char *)); if (tal->uri == NULL) @@ -77,85 +69,48 @@ tal_parse_stream(const char *fn, FILE *f) tal->uri[tal->urisz] = strdup(line); if (tal->uri[tal->urisz] == NULL) err(EXIT_FAILURE, NULL); - tal->urisz++; /* Make sure we're a proper rsync URI. */ - if (!rsync_uri_parse(NULL, NULL, NULL, NULL, NULL, NULL, &rp, line)) { warnx("%s: RFC 7730 section 2.1: " "failed to parse URL: %s", fn, line); goto out; - } else if (rp != RTYPE_CER) { + } + if (rp != RTYPE_CER) { warnx("%s: RFC 7730 section 2.1: " "not a certificate URL: %s", fn, line); goto out; } - } - if (ferror(f)) - err(EXIT_FAILURE, "%s: getline", fn); + } if (tal->urisz == 0) { warnx("%s: no URIs in manifest part", fn); goto out; - } else if (tal->urisz > 1) { + } else if (tal->urisz > 1) warnx("%s: multiple URIs: using the first", fn); - goto out; - } - - /* Now the BASE64-encoded public key. */ - - while ((linelen = getline(&line, &linesize, f)) != -1) { - lineno++; - assert(linelen); - if (line[linelen - 1] != '\n') { - warnx("%s: RFC 7730 section 2.1: " - "failed to parse public key", fn); - goto out; - } - line[--linelen] = '\0'; - if (linelen && line[linelen - 1] == '\r') - line[--linelen] = '\0'; - - /* Zero-length line can be ignored... ? */ - - if (linelen == 0) - continue; - - /* Do our base64 decoding in-band. */ - - sz = ((linelen + 2) / 3) * 4 + 1; - if ((b64 = realloc(b64, b64sz + sz)) == NULL) - err(EXIT_FAILURE, NULL); - if ((ssz = b64_pton(line, b64 + b64sz, sz)) < 0) - errx(EXIT_FAILURE, "b64_pton"); - - /* - * This might be different from our allocation size, but - * that doesn't matter: the slop here is minimal. - */ - b64sz += ssz; - } - - if (ferror(f)) - err(EXIT_FAILURE, "%s: getline", fn); - - if (b64sz == 0) { + sz = strlen(buf); + if (sz == 0) { warnx("%s: RFC 7730 section 2.1: subjectPublicKeyInfo: " "zero-length public key", fn); goto out; } + /* Now the BASE64-encoded public key. */ + sz = ((sz + 2) / 3) * 4 + 1; + if ((b64 = malloc(sz)) == NULL) + err(EXIT_FAILURE, NULL); + if ((b64sz = b64_pton(buf, b64, sz)) < 0) + errx(EXIT_FAILURE, "b64_pton"); + tal->pkey = b64; tal->pkeysz = b64sz; /* Make sure it's a valid public key. */ - pkey = d2i_PUBKEY(NULL, (const unsigned char **)&b64, b64sz); - b64 = NULL; if (pkey == NULL) { cryptowarnx("%s: RFC 7730 section 2.1: subjectPublicKeyInfo: " "failed public key parse", fn); @@ -163,8 +118,6 @@ tal_parse_stream(const char *fn, FILE *f) } rc = 1; out: - free(line); - free(b64); if (rc == 0) { tal_free(tal); tal = NULL; @@ -180,18 +133,13 @@ out: * memory, bad syntax, etc. */ struct tal * -tal_parse(const char *fn) +tal_parse(const char *fn, char *buf) { - FILE *f; struct tal *p; char *d; size_t dlen; - if ((f = fopen(fn, "r")) == NULL) - err(EXIT_FAILURE, "%s: open", fn); - - p = tal_parse_stream(fn, f); - fclose(f); + p = tal_parse_buffer(fn, buf); /* extract the TAL basename (without .tal suffix) */ d = basename(fn); |