Add shortlist functionality, a compagnion to the skiplist
authorjob <job@openbsd.org>
Thu, 17 Nov 2022 20:49:38 +0000 (20:49 +0000)
committerjob <job@openbsd.org>
Thu, 17 Nov 2022 20:49:38 +0000 (20:49 +0000)
If the operator specifies the '-H' option once (or more) followed by a FQDN,
the utility will *only* connect to those hosts and skip all others.

OK claudio@ tb@

usr.sbin/rpki-client/main.c
usr.sbin/rpki-client/rpki-client.8

index 51f4211..6cc37ca 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: main.c,v 1.220 2022/11/02 12:43:02 job Exp $ */
+/*     $OpenBSD: main.c,v 1.221 2022/11/17 20:49:38 job Exp $ */
 /*
  * Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -64,6 +64,7 @@ const char    *bird_tablename = "ROAS";
 int    verbose;
 int    noop;
 int    filemode;
+int    shortlistmode;
 int    rrdpon = 1;
 int    repo_timeout;
 time_t deadline;
@@ -72,6 +73,13 @@ struct skiplist skiplist = LIST_HEAD_INITIALIZER(skiplist);
 
 struct stats    stats;
 
+struct shortlistentry {
+       LIST_ENTRY(shortlistentry)       entry;
+       char                            *value; /* FQDN */
+};
+LIST_HEAD(shortlist, shortlistentry);
+struct shortlist shortlist = LIST_HEAD_INITIALIZER(shortlist);
+
 /*
  * Log a message to stderr if and only if "verbose" is non-zero.
  * This uses the err(3) functionality.
@@ -448,21 +456,35 @@ queue_add_from_cert(const struct cert *cert)
 {
        struct repo             *repo;
        struct skiplistentry    *sle;
+       struct shortlistentry   *she;
        char                    *nfile, *npath, *host;
        const char              *uri, *repouri, *file;
        size_t                   repourisz;
+       int                      shortlisted = 0;
 
-       LIST_FOREACH(sle, &skiplist, entry) {
-               if (strncmp(cert->repo, "rsync://", 8) != 0)
-                       errx(1, "unexpected protocol");
-               host = cert->repo + 8;
+       if (strncmp(cert->repo, "rsync://", 8) != 0)
+               errx(1, "unexpected protocol");
+       host = cert->repo + 8;
 
+       LIST_FOREACH(sle, &skiplist, entry) {
                if (strncasecmp(host, sle->value, strcspn(host, "/")) == 0) {
                        warnx("skipping %s (listed in skiplist)", cert->repo);
                        return;
                }
        }
 
+       LIST_FOREACH(she, &shortlist, entry) {
+               if (strncasecmp(host, she->value, strcspn(host, "/")) == 0) {
+                       shortlisted = 1;
+                       break;
+               }
+       }
+       if (shortlistmode && shortlisted == 0) {
+               if (verbose)
+                       warnx("skipping %s (not shortlisted)", cert->repo);
+               return;
+       }
+
        repo = repo_lookup(cert->talid, cert->repo,
            rrdpon ? cert->notify : NULL);
        if (repo == NULL)
@@ -760,6 +782,26 @@ load_skiplist(const char *slf)
        free(line);
 }
 
+/*
+ * Load shortlist entries.
+ */
+static void
+load_shortlist(const char *fqdn)
+{
+       struct shortlistentry   *she;
+
+       if (!valid_uri(fqdn, strlen(fqdn), NULL))
+               errx(1, "invalid fqdn passed to -q: %s", fqdn);
+
+       if ((she = malloc(sizeof(struct shortlistentry))) == NULL)
+               err(1, NULL);
+
+       if ((she->value = strdup(fqdn)) == NULL)
+               err(1, NULL);
+
+       LIST_INSERT_HEAD(&shortlist, she, entry);
+}
+
 static void
 check_fs_size(int fd, const char *cachedir)
 {
@@ -865,7 +907,7 @@ main(int argc, char *argv[])
            "proc exec unveil", NULL) == -1)
                err(1, "pledge");
 
-       while ((c = getopt(argc, argv, "b:Bcd:e:fjnorRs:S:t:T:vV")) != -1)
+       while ((c = getopt(argc, argv, "b:Bcd:e:fH:jnorRs:S:t:T:vV")) != -1)
                switch (c) {
                case 'b':
                        bind_addr = optarg;
@@ -886,6 +928,10 @@ main(int argc, char *argv[])
                        filemode = 1;
                        noop = 1;
                        break;
+               case 'H':
+                       shortlistmode = 1;
+                       load_shortlist(optarg);
+                       break;
                case 'j':
                        outformats |= FORMAT_JSON;
                        break;
@@ -1330,8 +1376,9 @@ usage:
        fprintf(stderr,
            "usage: rpki-client [-BcjnoRrVv] [-b sourceaddr] [-d cachedir]"
            " [-e rsync_prog]\n"
-           "                   [-S skiplist] [-s timeout] [-T table] [-t tal]"
-           " [outputdir]\n"
+           "                   [-H fqdn ] [-S skiplist] [-s timeout] [-T table]"
+           " [-t tal]\n"
+           "                   [outputdir]\n"
            "       rpki-client [-Vv] [-d cachedir] [-j] [-t tal] -f file ..."
            "\n");
        return 1;
index c5812ec..39a970d 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: rpki-client.8,v 1.79 2022/11/10 13:22:55 job Exp $
+.\"    $OpenBSD: rpki-client.8,v 1.80 2022/11/17 20:49:38 job Exp $
 .\"
 .\" Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
 .\"
@@ -14,7 +14,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: November 10 2022 $
+.Dd $Mdocdate: November 17 2022 $
 .Dt RPKI-CLIENT 8
 .Os
 .Sh NAME
@@ -26,6 +26,7 @@
 .Op Fl b Ar sourceaddr
 .Op Fl d Ar cachedir
 .Op Fl e Ar rsync_prog
+.Op Fl H Ar fqdn
 .Op Fl S Ar skiplist
 .Op Fl s Ar timeout
 .Op Fl T Ar table
@@ -120,6 +121,16 @@ and can be combined with
 .Fl j
 to emit a stream of
 .Em Concatenated JSON .
+.It Fl H Ar fqdn
+Create a shortlist and add
+.Ar fqdn
+to the shortlist.
+.Nm
+only connects to shortlisted hosts.
+The shortlist filter is enforced during processing of the
+.Em Subject Information Access Pq SIA
+extension in CA certificates, thus applies to both RSYNC and RRDP connections.
+This option can be used multiple times.
 .It Fl j
 Create output in the file
 .Pa json