For RRDP support the repository code needs to be cleaned up and adjusted.
Instead of working with host/module store the URI (repo->repo) and the
local path (repo->local). This simplifies the communication between
rpki-client main process and the rsync process a fair bit.
Also introduce mkpath() stolen and adjusted from bin/mkdir to create
all directories in a path. In a second step the repository layout will
probably change so that rsync and rrdp can coexist. This is why some code
is currently maybe a bit extra complex.
--
:wq Claudio
Index: Makefile
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/Makefile,v
retrieving revision 1.16
diff -u -p -r1.16 Makefile
--- Makefile 8 Jan 2021 08:09:07 -0000 1.16
+++ Makefile 2 Feb 2021 17:24:34 -0000
@@ -1,8 +1,8 @@
# $OpenBSD: Makefile,v 1.16 2021/01/08 08:09:07 claudio Exp $
PROG= rpki-client
-SRCS= as.c cert.c cms.c crl.c gbr.c io.c ip.c log.c main.c mft.c output.c \
- output-bgpd.c output-bird.c output-csv.c output-json.c \
+SRCS= as.c cert.c cms.c crl.c gbr.c io.c ip.c log.c main.c mft.c mkdir.c \
+ output.c output-bgpd.c output-bird.c output-csv.c output-json.c \
roa.c rsync.c tal.c validate.c x509.c
MAN= rpki-client.8
Index: extern.h
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
retrieving revision 1.38
diff -u -p -r1.38 extern.h
--- extern.h 29 Jan 2021 10:13:16 -0000 1.38
+++ extern.h 2 Feb 2021 17:25:27 -0000
@@ -422,6 +422,8 @@ int output_json(FILE *, struct vrp_tre
void logx(const char *fmt, ...)
__attribute__((format(printf, 1, 2)));
+int mkpath(const char *);
+
#define RPKI_PATH_OUT_DIR "/var/db/rpki-client"
#define RPKI_PATH_BASE_DIR "/var/cache/rpki-client"
Index: main.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/main.c,v
retrieving revision 1.91
diff -u -p -r1.91 main.c
--- main.c 29 Jan 2021 10:13:16 -0000 1.91
+++ main.c 2 Feb 2021 17:57:51 -0000
@@ -83,10 +83,11 @@
* An rsync repository.
*/
struct repo {
- char *host; /* hostname */
- char *module; /* module name */
- int loaded; /* whether loaded or not */
- size_t id; /* identifier (array index) */
+ char *repo; /* repository rsync URI */
+ char *local; /* local path name */
+ char *notify; /* RRDB notify URI if available */
+ size_t id; /* identifier (array index) */
+ int loaded; /* whether loaded or not */
};
size_t entity_queue;
@@ -288,6 +289,7 @@ repo_lookup(struct msgbuf *msgq, const c
{
const char *host, *mod;
size_t hostsz, modsz, i;
+ char *local;
struct repo *rp;
struct ibuf *b;
@@ -295,17 +297,16 @@ repo_lookup(struct msgbuf *msgq, const c
&mod, &modsz, NULL, NULL, NULL, uri))
errx(1, "%s: malformed", uri);
+ if (asprintf(&local, "%.*s/%.*s", (int)hostsz, host,
+ (int)modsz, mod) == -1)
+ err(1, "asprintf");
+
/* Look up in repository table. */
for (i = 0; i < rt.reposz; i++) {
- if (strlen(rt.repos[i].host) != hostsz)
- continue;
- if (strlen(rt.repos[i].module) != modsz)
- continue;
- if (strncasecmp(rt.repos[i].host, host, hostsz))
- continue;
- if (strncasecmp(rt.repos[i].module, mod, modsz))
+ if (strcmp(rt.repos[i].local, local))
continue;
+ free(local);
return &rt.repos[i];
}
@@ -317,25 +318,25 @@ repo_lookup(struct msgbuf *msgq, const c
rp = &rt.repos[rt.reposz++];
memset(rp, 0, sizeof(struct repo));
rp->id = rt.reposz - 1;
+ rp->local = local;
- if ((rp->host = strndup(host, hostsz)) == NULL ||
- (rp->module = strndup(mod, modsz)) == NULL)
- err(1, "strndup");
-
- i = rt.reposz - 1;
+ if ((rp->repo = strndup(uri, mod + modsz - uri)) == NULL)
+ err(1, "strdup");
if (!noop) {
- logx("%s/%s: pulling from network", rp->host, rp->module);
- if ((b = ibuf_dynamic(128, UINT_MAX)) == NULL)
+ if (asprintf(&local, "%s", rp->local) == -1)
+ err(1, "asprintf");
+ logx("%s: pulling from network", local);
+ if ((b = ibuf_dynamic(256, UINT_MAX)) == NULL)
err(1, NULL);
- io_simple_buffer(b, &i, sizeof(i));
- io_str_buffer(b, rp->host);
- io_str_buffer(b, rp->module);
-
+ io_simple_buffer(b, &rp->id, sizeof(rp->id));
+ io_str_buffer(b, local);
+ io_str_buffer(b, rp->repo);
ibuf_close(msgq, b);
+ free(local);
} else {
rp->loaded = 1;
- logx("%s/%s: using cache", rp->host, rp->module);
+ logx("%s: using cache", rp->local);
stats.repos++;
/* there is nothing in the queue so no need to flush */
}
@@ -350,9 +351,8 @@ repo_filename(const struct repo *repo, c
{
char *nfile;
- uri += 8 + strlen(repo->host) + 1 + strlen(repo->module) + 1;
-
- if (asprintf(&nfile, "%s/%s/%s", repo->host, repo->module, uri) == -1)
+ uri += strlen(repo->repo) + 1;
+ if (asprintf(&nfile, "%s/%s", repo->local, uri) == -1)
err(1, "asprintf");
return nfile;
}
@@ -411,8 +411,6 @@ queue_add_from_mft(struct msgbuf *msgq,
char *cp, *nfile;
/* Construct local path from filename. */
- /* We know this is host/module/... */
-
cp = strrchr(mft, '/');
assert(cp != NULL);
assert(cp - mft < INT_MAX);
@@ -555,17 +553,13 @@ queue_add_from_tal(struct msgbuf *procq,
*/
static void
queue_add_from_cert(struct msgbuf *procq, struct msgbuf *rsyncq,
- struct entityq *q, const char *rsyncuri, const char *rrdpuri)
+ struct entityq *q, const struct cert *cert)
{
- char *nfile;
const struct repo *repo;
+ char *nfile;
- if (rsyncuri == NULL)
- return;
-
- /* Look up the repository. */
- repo = repo_lookup(rsyncq, rsyncuri);
- nfile = repo_filename(repo, rsyncuri);
+ repo = repo_lookup(rsyncq, cert->mft);
+ nfile = repo_filename(repo, cert->mft);
entityq_add(procq, q, nfile, RTYPE_MFT, repo, NULL, 0, NULL);
}
@@ -1206,7 +1200,7 @@ entity_process(int proc, struct msgbuf *
* process the MFT.
*/
queue_add_from_cert(procq, rsyncq,
- q, cert->mft, cert->notify);
+ q, cert);
} else
st->certs_invalid++;
cert_free(cert);
@@ -1311,8 +1305,7 @@ repo_cleanup(const char *cachedir)
err(1, "%s: chdir", cachedir);
for (i = 0; i < rt.reposz; i++) {
- if (asprintf(&argv[0], "%s/%s", rt.repos[i].host,
- rt.repos[i].module) == -1)
+ if (asprintf(&argv[0], "%s", rt.repos[i].local) == -1)
err(1, NULL);
argv[1] = NULL;
if ((fts = fts_open(argv, FTS_PHYSICAL | FTS_NOSTAT,
@@ -1603,8 +1596,11 @@ main(int argc, char *argv[])
if (c == 0) {
for (i = j = 0; i < rt.reposz; i++)
- if (!rt.repos[i].loaded)
+ if (!rt.repos[i].loaded) {
+ logx("pending repo %s",
+ rt.repos[i].local);
j++;
+ }
logx("period stats: %zu pending repos", j);
logx("period stats: %zu pending entries", entity_queue);
continue;
@@ -1646,15 +1642,15 @@ main(int argc, char *argv[])
io_simple_read(rsync, &i, sizeof(size_t));
io_simple_read(rsync, &ok, sizeof(ok));
assert(i < rt.reposz);
+
assert(!rt.repos[i].loaded);
rt.repos[i].loaded = 1;
if (ok)
- logx("%s/%s: loaded from network",
- rt.repos[i].host, rt.repos[i].module);
+ logx("%s: loaded from network",
+ rt.repos[i].local);
else
- logx("%s/%s: load from network failed, "
- "fallback to cache",
- rt.repos[i].host, rt.repos[i].module);
+ logx("%s: load from network failed, "
+ "fallback to cache", rt.repos[i].local);
stats.repos++;
entityq_flush(&procq, &q, &rt.repos[i]);
}
@@ -1733,8 +1729,8 @@ main(int argc, char *argv[])
/* Memory cleanup. */
for (i = 0; i < rt.reposz; i++) {
- free(rt.repos[i].host);
- free(rt.repos[i].module);
+ free(rt.repos[i].local);
+ free(rt.repos[i].repo);
}
free(rt.repos);
Index: mkdir.c
===================================================================
RCS file: mkdir.c
diff -N mkdir.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ mkdir.c 2 Feb 2021 16:56:35 -0000
@@ -0,0 +1,75 @@
+/* $OpenBSD: mkdir.c,v 1.31 2019/06/28 13:34:59 deraadt Exp $ */
+
+/*
+ * Copyright (c) 1983, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <string.h>
+
+#include "extern.h"
+
+/*
+ * mkpath -- create directories.
+ * path - path
+ * mode - file mode of terminal directory
+ * dir_mode - file mode of intermediate directories
+ */
+int
+mkpath(const char *dir)
+{
+ char *path, *slash;
+ int done;
+
+ if ((path = strdup(dir)) == NULL)
+ return -1;
+
+ slash = path;
+ for (;;) {
+ slash += strspn(slash, "/");
+ slash += strcspn(slash, "/");
+
+ done = (*slash == '\0');
+ *slash = '\0';
+
+ if (mkdir(path, 0700) == -1 && errno != EEXIST) {
+ free(path);
+ return (-1);
+ }
+
+ if (done)
+ break;
+
+ *slash = '/';
+ }
+
+ free(path);
+ return (0);
+}
Index: rsync.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/rsync.c,v
retrieving revision 1.14
diff -u -p -r1.14 rsync.c
--- rsync.c 12 Jan 2021 09:22:11 -0000 1.14
+++ rsync.c 2 Feb 2021 17:37:35 -0000
@@ -173,8 +173,7 @@ proc_rsync(char *prog, char *bind_addr,
{
size_t id, i, idsz = 0;
ssize_t ssz;
- char *host = NULL, *mod = NULL, *uri = NULL,
- *dst = NULL, *path, *save, *cmd;
+ char *uri = NULL, *dst = NULL, *path, *save, *cmd;
const char *pp;
pid_t pid;
char *args[32];
@@ -228,6 +227,9 @@ proc_rsync(char *prog, char *bind_addr,
if (unveil(NULL, NULL) == -1)
err(1, "unveil");
+ if (pledge("stdio cpath proc exec", NULL) == -1)
+ err(1, "pledge");
+
/* Initialise retriever for children exiting. */
if (sigemptyset(&mask) == -1)
@@ -314,10 +316,10 @@ proc_rsync(char *prog, char *bind_addr,
/* Read host and module. */
- io_str_read(fd, &host);
- io_str_read(fd, &mod);
- assert(host);
- assert(mod);
+ io_str_read(fd, &dst);
+ io_str_read(fd, &uri);
+ assert(dst);
+ assert(uri);
/*
* Create source and destination locations.
@@ -325,17 +327,9 @@ proc_rsync(char *prog, char *bind_addr,
* will not build the destination for us.
*/
- if (mkdir(host, 0700) == -1 && EEXIST != errno)
- err(1, "%s", host);
-
- if (asprintf(&dst, "%s/%s", host, mod) == -1)
- err(1, NULL);
- if (mkdir(dst, 0700) == -1 && EEXIST != errno)
+ if (mkpath(dst))
err(1, "%s", dst);
- if (asprintf(&uri, "rsync://%s/%s", host, mod) == -1)
- err(1, NULL);
-
/* Run process itself, wait for exit, check error. */
if ((pid = fork()) == -1)
@@ -378,9 +372,7 @@ proc_rsync(char *prog, char *bind_addr,
/* Clean up temporary values. */
- free(mod);
free(dst);
- free(host);
}
/* No need for these to be hanging around. */