OK job@
On Tue, Oct 26, 2021 at 05:43:32PM +0200, Claudio Jeker wrote:
> This is part 3 of the BIO removal. Switch tal_parse to pass a file buffer
> like all other callers. The parent process can now just use load_file()
> and pass that buffer to the parser. From there on the magic just happens.
>
> --
> :wq Claudio
>
> Index: encoding.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/encoding.c,v
> retrieving revision 1.4
> diff -u -p -r1.4 encoding.c
> --- encoding.c 11 Oct 2021 16:06:36 -0000 1.4
> +++ encoding.c 26 Oct 2021 14:40:47 -0000
> @@ -29,11 +29,11 @@
> * Returns 0 on success or -1 for any errors.
> */
> int
> -base64_decode(const unsigned char *in, unsigned char **out, size_t *outlen)
> +base64_decode(const unsigned char *in, size_t inlen,
> + unsigned char **out, size_t *outlen)
> {
> static EVP_ENCODE_CTX *ctx;
> unsigned char *to;
> - size_t inlen;
> int tolen;
>
> if (ctx == NULL && (ctx = EVP_ENCODE_CTX_new()) == NULL)
> @@ -42,7 +42,6 @@ base64_decode(const unsigned char *in, u
> *out = NULL;
> *outlen = 0;
>
> - inlen = strlen(in);
> if (inlen >= INT_MAX - 3)
> return -1;
> tolen = ((inlen + 3) / 4) * 3 + 1;
> Index: extern.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
> retrieving revision 1.79
> diff -u -p -r1.79 extern.h
> --- extern.h 26 Oct 2021 13:31:05 -0000 1.79
> +++ extern.h 26 Oct 2021 14:40:37 -0000
> @@ -337,12 +337,12 @@ enum publish_type {
> * and parsed.
> */
> struct entity {
> - enum rtype type; /* type of entity (not RTYPE_EOF) */
> - char *file; /* local path to file */
> - int has_pkey; /* whether pkey/sz is specified */
> - unsigned char *pkey; /* public key (optional) */
> - size_t pkeysz; /* public key length (optional) */
> - char *descr; /* tal description */
> + enum rtype type; /* type of entity (not RTYPE_EOF) */
> + char *file; /* local path to file */
> + int has_data; /* whether data blob is specified */
> + unsigned char *data; /* optional data blob */
> + size_t datasz; /* length of optional data blob */
> + char *descr; /* tal description */
> TAILQ_ENTRY(entity) entries;
> };
> TAILQ_HEAD(entityq, entity);
> @@ -397,8 +397,7 @@ extern int verbose;
>
> void tal_buffer(struct ibuf *, const struct tal *);
> void tal_free(struct tal *);
> -struct tal *tal_parse(const char *, char *);
> -char *tal_read_file(const char *);
> +struct tal *tal_parse(const char *, char *, size_t);
> struct tal *tal_read(struct ibuf *);
>
> void cert_buffer(struct ibuf *, const struct cert *);
> @@ -534,8 +533,8 @@ void cryptoerrx(const char *, ...)
>
> /* Encoding functions for hex and base64. */
>
> -int base64_decode(const unsigned char *, unsigned char **,
> - size_t *);
> +int base64_decode(const unsigned char *, size_t,
> + unsigned char **, size_t *);
> int base64_encode(const unsigned char *, size_t, char **);
> char *hex_encode(const unsigned char *, size_t);
>
> @@ -595,8 +594,9 @@ int output_csv(FILE *, struct vrp_tree
> int output_json(FILE *, struct vrp_tree *, struct brk_tree *,
> struct stats *);
>
> -void logx(const char *fmt, ...)
> +void logx(const char *fmt, ...)
> __attribute__((format(printf, 1, 2)));
> +unsigned char *load_file(const char *, size_t *);
>
> int mkpath(const char *);
>
> Index: main.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/main.c,v
> retrieving revision 1.154
> diff -u -p -r1.154 main.c
> --- main.c 24 Oct 2021 21:24:19 -0000 1.154
> +++ main.c 26 Oct 2021 14:38:40 -0000
> @@ -20,6 +20,7 @@
> #include <sys/queue.h>
> #include <sys/socket.h>
> #include <sys/resource.h>
> +#include <sys/stat.h>
> #include <sys/statvfs.h>
> #include <sys/tree.h>
> #include <sys/wait.h>
> @@ -82,13 +83,46 @@ logx(const char *fmt, ...)
> }
> }
>
> +unsigned char *
> +load_file(const char *name, size_t *len)
> +{
> + unsigned char *buf = NULL;
> + struct stat st;
> + ssize_t n;
> + size_t size;
> + int fd;
> +
> + *len = 0;
> +
> + if ((fd = open(name, O_RDONLY)) == -1)
> + return NULL;
> + if (fstat(fd, &st) != 0)
> + goto err;
> + if (st.st_size < 0)
> + goto err;
> + size = (size_t)st.st_size;
> + if ((buf = malloc(size)) == NULL)
> + goto err;
> + n = read(fd, buf, size);
> + if (n < 0 || (size_t)n != size)
> + goto err;
> + close(fd);
> + *len = size;
> + return buf;
> +
> +err:
> + close(fd);
> + free(buf);
> + return NULL;
> +}
> +
> void
> entity_free(struct entity *ent)
> {
> if (ent == NULL)
> return;
>
> - free(ent->pkey);
> + free(ent->data);
> free(ent->file);
> free(ent->descr);
> free(ent);
> @@ -104,10 +138,10 @@ entity_read_req(struct ibuf *b, struct e
> {
> io_read_buf(b, &ent->type, sizeof(ent->type));
> io_read_str(b, &ent->file);
> - io_read_buf(b, &ent->has_pkey, sizeof(ent->has_pkey));
> - if (ent->has_pkey)
> - io_read_buf_alloc(b, (void **)&ent->pkey, &ent->pkeysz);
> io_read_str(b, &ent->descr);
> + io_read_buf(b, &ent->has_data, sizeof(ent->has_data));
> + if (ent->has_data)
> + io_read_buf_alloc(b, (void **)&ent->data, &ent->datasz);
> }
>
> /*
> @@ -128,10 +162,10 @@ entity_write_req(const struct entity *en
> b = io_new_buffer();
> io_simple_buffer(b, &ent->type, sizeof(ent->type));
> io_str_buffer(b, ent->file);
> - io_simple_buffer(b, &ent->has_pkey, sizeof(int));
> - if (ent->has_pkey)
> - io_buf_buffer(b, ent->pkey, ent->pkeysz);
> io_str_buffer(b, ent->descr);
> + io_simple_buffer(b, &ent->has_data, sizeof(int));
> + if (ent->has_data)
> + io_buf_buffer(b, ent->data, ent->datasz);
> io_close_buffer(&procq, b);
> }
>
> @@ -169,7 +203,7 @@ entityq_flush(struct entityq *q, struct
> */
> static void
> entityq_add(char *file, enum rtype type, struct repo *rp,
> - const unsigned char *pkey, size_t pkeysz, char *descr)
> + unsigned char *data, size_t datasz, char *descr)
> {
> struct entity *p;
>
> @@ -178,12 +212,10 @@ entityq_add(char *file, enum rtype type,
>
> p->type = type;
> p->file = file;
> - p->has_pkey = pkey != NULL;
> - if (p->has_pkey) {
> - p->pkeysz = pkeysz;
> - if ((p->pkey = malloc(pkeysz)) == NULL)
> - err(1, NULL);
> - memcpy(p->pkey, pkey, pkeysz);
> + p->has_data = data != NULL;
> + if (p->has_data) {
> + p->data = data;
> + p->datasz = datasz;
> }
> if (descr != NULL)
> if ((p->descr = strdup(descr)) == NULL)
> @@ -388,11 +420,13 @@ queue_add_from_mft_set(const struct mft
> static void
> queue_add_tal(const char *file)
> {
> - char *nfile, *buf;
> + unsigned char *buf;
> + char *nfile;
> + size_t len;
>
> if ((nfile = strdup(file)) == NULL)
> err(1, NULL);
> - buf = tal_read_file(file);
> + buf = load_file(file, &len);
>
> /* Record tal for later reporting */
> if (stats.talnames == NULL) {
> @@ -408,9 +442,7 @@ queue_add_tal(const char *file)
> }
>
> /* Not in a repository, so directly add to queue. */
> - entityq_add(nfile, RTYPE_TAL, NULL, NULL, 0, buf);
> - /* entityq_add makes a copy of buf */
> - free(buf);
> + entityq_add(nfile, RTYPE_TAL, NULL, buf, len, buf);
> }
>
> /*
> @@ -420,13 +452,17 @@ static void
> queue_add_from_tal(struct tal *tal)
> {
> struct repo *repo;
> + unsigned char *data;
>
> assert(tal->urisz);
>
> /* Look up the repository. */
> repo = ta_lookup(tal);
>
> - entityq_add(NULL, RTYPE_CER, repo, tal->pkey,
> + /* steal the pkey from the tal structure */
> + data = tal->pkey;
> + tal->pkey = NULL;
> + entityq_add(NULL, RTYPE_CER, repo, data,
> tal->pkeysz, tal->descr);
> }
>
> @@ -683,6 +719,7 @@ main(int argc, char *argv[])
> char *bind_addr = NULL;
> const char *cachedir = NULL, *outputdir = NULL;
> const char *tals[TALSZ_MAX], *errs, *name;
> + const char *file = NULL;
> struct vrp_tree vrps = RB_INITIALIZER(&vrps);
> struct brk_tree brks = RB_INITIALIZER(&brks);
> struct rusage ru;
> @@ -709,7 +746,7 @@ main(int argc, char *argv[])
> "proc exec unveil", NULL) == -1)
> err(1, "pledge");
>
> - while ((c = getopt(argc, argv, "b:Bcd:e:jnorRs:t:T:vV")) != -1)
> + while ((c = getopt(argc, argv, "b:Bcd:e:f:jnorRs:t:T:vV")) != -1)
> switch (c) {
> case 'b':
> bind_addr = optarg;
> @@ -725,6 +762,10 @@ main(int argc, char *argv[])
> break;
> case 'e':
> rsync_prog = optarg;
> + break;
> + case 'f':
> + file = optarg;
> + noop = 1;
> break;
> case 'j':
> outformats |= FORMAT_JSON;
> Index: parser.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/parser.c,v
> retrieving revision 1.19
> diff -u -p -r1.19 parser.c
> --- parser.c 26 Oct 2021 13:31:05 -0000 1.19
> +++ parser.c 26 Oct 2021 14:24:53 -0000
> @@ -17,13 +17,11 @@
> */
>
> #include <sys/queue.h>
> -#include <sys/stat.h>
> #include <sys/tree.h>
> #include <sys/types.h>
>
> #include <assert.h>
> #include <err.h>
> -#include <fcntl.h>
> #include <poll.h>
> #include <stdio.h>
> #include <stdlib.h>
> @@ -201,7 +199,7 @@ proc_parser_cert(const struct entity *en
> STACK_OF(X509) *chain;
> STACK_OF(X509_CRL) *crls;
>
> - assert(!entp->has_pkey);
> + assert(!entp->has_data);
>
> /* Extract certificate data and X509. */
>
> @@ -294,11 +292,11 @@ proc_parser_root_cert(const struct entit
> struct auth *na;
> char *tal;
>
> - assert(entp->has_pkey);
> + assert(entp->has_data);
>
> /* Extract certificate data and X509. */
>
> - cert = ta_parse(&x509, entp->file, der, len, entp->pkey, entp->pkeysz);
> + cert = ta_parse(&x509, entp->file, der, len, entp->data, entp->datasz);
> if (cert == NULL)
> return NULL;
>
> @@ -510,39 +508,6 @@ build_crls(const struct crl *crl, STACK_
> err(1, "sk_X509_CRL_push");
> }
>
> -static unsigned char *
> -load_file(const char *name, size_t *len)
> -{
> - unsigned char *buf = NULL;
> - struct stat st;
> - ssize_t n;
> - size_t size;
> - int fd;
> -
> - *len = 0;
> -
> - if ((fd = open(name, O_RDONLY)) == -1)
> - return NULL;
> - if (fstat(fd, &st) != 0)
> - goto err;
> - if (st.st_size < 0)
> - goto err;
> - size = (size_t)st.st_size;
> - if ((buf = malloc(size)) == NULL)
> - goto err;
> - n = read(fd, buf, size);
> - if (n < 0 || (size_t)n != size)
> - goto err;
> - close(fd);
> - *len = size;
> - return buf;
> -
> -err:
> - close(fd);
> - free(buf);
> - return NULL;
> -}
> -
> static void
> parse_entity(struct entityq *q, struct msgbuf *msgq)
> {
> @@ -571,14 +536,15 @@ parse_entity(struct entityq *q, struct m
>
> switch (entp->type) {
> case RTYPE_TAL:
> - if ((tal = tal_parse(entp->file, entp->descr)) == NULL)
> + if ((tal = tal_parse(entp->file, entp->data,
> + entp->datasz)) == NULL)
> errx(1, "%s: could not parse tal file",
> entp->file);
> tal_buffer(b, tal);
> tal_free(tal);
> break;
> case RTYPE_CER:
> - if (entp->has_pkey)
> + if (entp->has_data)
> cert = proc_parser_root_cert(entp, f, flen);
> else
> cert = proc_parser_cert(entp, f, flen);
> Index: rrdp.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/rrdp.c,v
> retrieving revision 1.14
> diff -u -p -r1.14 rrdp.c
> --- rrdp.c 23 Oct 2021 20:01:16 -0000 1.14
> +++ rrdp.c 26 Oct 2021 14:42:12 -0000
> @@ -661,7 +661,8 @@ publish_done(struct rrdp *s, struct publ
> size_t datasz = 0;
>
> if (pxml->data_length > 0)
> - if ((base64_decode(pxml->data, &data, &datasz)) == -1)
> + if ((base64_decode(pxml->data, pxml->data_length,
> + &data, &datasz)) == -1)
> return -1;
>
> /* only send files if the fetch did not fail already */
> Index: tal.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/tal.c,v
> retrieving revision 1.31
> diff -u -p -r1.31 tal.c
> --- tal.c 23 Oct 2021 16:06:04 -0000 1.31
> +++ tal.c 26 Oct 2021 14:39:52 -0000
> @@ -41,7 +41,7 @@ tal_cmp(const void *a, const void *b)
> * The pointer must be freed with tal_free().
> */
> static struct tal *
> -tal_parse_buffer(const char *fn, char *buf)
> +tal_parse_buffer(const char *fn, char *buf, size_t len)
> {
> char *nl, *line, *f, *file = NULL;
> unsigned char *der;
> @@ -49,18 +49,31 @@ tal_parse_buffer(const char *fn, char *b
> int rc = 0;
> struct tal *tal = NULL;
> EVP_PKEY *pkey = NULL;
> + int optcomment = 1;
>
> if ((tal = calloc(1, sizeof(struct tal))) == NULL)
> err(1, NULL);
>
> /* Begin with the URI section, comment section already removed. */
> - while ((nl = strchr(buf, '\n')) != NULL) {
> + while ((nl = memchr(buf, '\n', len)) != NULL) {
> line = buf;
> +
> + /* replace LF and optional CR with NUL */
> *nl = '\0';
> + if (nl > line && nl[-1] == '\r')
> + nl[-1] = '\0';
>
> /* advance buffer to next line */
> + len -= nl + 1 - buf;
> buf = nl + 1;
>
> + if (optcomment) {
> + /* if this is a comment, just eat the line */
> + if (line[0] == '#')
> + continue;
> + optcomment = 0;
> + }
> +
> /* Zero-length line is end of section. */
> if (*line == '\0')
> break;
> @@ -112,7 +125,7 @@ tal_parse_buffer(const char *fn, char *b
> qsort(tal->uri, tal->urisz, sizeof(tal->uri[0]), tal_cmp);
>
> /* Now the Base64-encoded public key. */
> - if ((base64_decode(buf, &der, &dersz)) == -1) {
> + if ((base64_decode(buf, len, &der, &dersz)) == -1) {
> warnx("%s: RFC 7730 section 2.1: subjectPublicKeyInfo: "
> "bad public key", fn);
> goto out;
> @@ -144,13 +157,13 @@ out:
> * Returns the encoded data or NULL on syntax failure.
> */
> struct tal *
> -tal_parse(const char *fn, char *buf)
> +tal_parse(const char *fn, char *buf, size_t len)
> {
> struct tal *p;
> const char *d;
> size_t dlen;
>
> - p = tal_parse_buffer(fn, buf);
> + p = tal_parse_buffer(fn, buf, len);
> if (p == NULL)
> return NULL;
>
> @@ -167,76 +180,6 @@ tal_parse(const char *fn, char *buf)
> err(1, NULL);
>
> return p;
> -}
> -
> -/*
> - * Read the file named "file" into a returned, NUL-terminated buffer.
> - * This replaces CRLF terminators with plain LF, if found, and also
> - * elides document-leading comment lines starting with "#".
> - * Files may not exceeds 4096 bytes.
> - * This function exits on failure, so it always returns a buffer with
> - * TAL data.
> - */
> -char *
> -tal_read_file(const char *file)
> -{
> - char *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(1, "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((unsigned char)line[i]) &&
> - !isspace((unsigned char)line[i]))
> - errx(1, "getline: %s: "
> - "invalid content", file);
> -
> - /* concat line to buf */
> - if ((nbuf = realloc(buf, bsz + n + 1)) == NULL)
> - err(1, NULL);
> - if (buf == NULL)
> - nbuf[0] = '\0'; /* initialize buffer */
> - buf = nbuf;
> - bsz += n + 1;
> - if (strlcat(buf, line, bsz) >= bsz)
> - errx(1, "strlcat overflow");
> - /* limit the buffer size */
> - if (bsz > 4096)
> - errx(1, "%s: file too big", file);
> - }
> -
> - free(line);
> - if (ferror(in))
> - err(1, "getline: %s", file);
> - fclose(in);
> - if (buf == NULL)
> - errx(1, "%s: no data", file);
> - return buf;
> }
>
> /*
>