Refactor the tal parsing code to use the same load_file() and buffer
authorclaudio <claudio@openbsd.org>
Tue, 26 Oct 2021 16:12:54 +0000 (16:12 +0000)
committerclaudio <claudio@openbsd.org>
Tue, 26 Oct 2021 16:12:54 +0000 (16:12 +0000)
passing as done for the other parsers.
OK job@ tb@

usr.sbin/rpki-client/encoding.c
usr.sbin/rpki-client/extern.h
usr.sbin/rpki-client/main.c
usr.sbin/rpki-client/parser.c
usr.sbin/rpki-client/rrdp.c
usr.sbin/rpki-client/tal.c

index ff6d873..5208598 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: encoding.c,v 1.4 2021/10/11 16:06:36 claudio Exp $  */
+/*     $OpenBSD: encoding.c,v 1.5 2021/10/26 16:12:54 claudio Exp $  */
 /*
  * Copyright (c) 2020 Claudio Jeker <claudio@openbsd.org>
  *
  * 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, unsigned char **out, size_t *outlen)
        *out = NULL;
        *outlen = 0;
 
-       inlen = strlen(in);
        if (inlen >= INT_MAX - 3)
                return -1;
        tolen = ((inlen + 3) / 4) * 3 + 1;
index 7c3cb3e..8e77b68 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: extern.h,v 1.79 2021/10/26 13:31:05 claudio Exp $ */
+/*     $OpenBSD: extern.h,v 1.80 2021/10/26 16:12:54 claudio Exp $ */
 /*
  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -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 *, struct brk_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 f83a4ba..775b321 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: main.c,v 1.154 2021/10/24 21:24:19 deraadt Exp $ */
+/*     $OpenBSD: main.c,v 1.155 2021/10/26 16:12:54 claudio Exp $ */
 /*
  * Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -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 entity *ent)
 {
        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 *ent)
        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 repo *rp)
  */
 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, struct repo *rp,
 
        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 *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;
@@ -726,6 +763,10 @@ main(int argc, char *argv[])
                case 'e':
                        rsync_prog = optarg;
                        break;
+               case 'f':
+                       file = optarg;
+                       noop = 1;
+                       break;
                case 'j':
                        outformats |= FORMAT_JSON;
                        break;
index cc2f151..acafeb2 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: parser.c,v 1.19 2021/10/26 13:31:05 claudio Exp $ */
+/*     $OpenBSD: parser.c,v 1.20 2021/10/26 16:12:54 claudio Exp $ */
 /*
  * Copyright (c) 2019 Claudio Jeker <claudio@openbsd.org>
  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
  */
 
 #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 *entp, const unsigned char *der,
        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 entity *entp, const unsigned char *der,
        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_OF(X509_CRL) **crls)
                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 msgbuf *msgq)
 
                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 579353f..9271881 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: rrdp.c,v 1.14 2021/10/23 20:01:16 claudio Exp $ */
+/*     $OpenBSD: rrdp.c,v 1.15 2021/10/26 16:12:54 claudio Exp $ */
 /*
  * Copyright (c) 2020 Nils Fisher <nils_fisher@hotmail.com>
  * Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
@@ -661,7 +661,8 @@ publish_done(struct rrdp *s, struct publish_xml *pxml)
        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 b6a0890..8875d28 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: tal.c,v 1.31 2021/10/23 16:06:04 claudio Exp $ */
+/*     $OpenBSD: tal.c,v 1.32 2021/10/26 16:12:54 claudio Exp $ */
 /*
  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -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 *buf)
        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 *buf)
        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;
 
@@ -169,76 +182,6 @@ tal_parse(const char *fn, char *buf)
        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;
-}
-
 /*
  * Free a TAL pointer.
  * Safe to call with NULL.