Hi all,

Scratching an itch: When debugging RPKI things, I've grown tired of
typing stuff like the below 2 commands to get to the CMS encapsulated
DER encoded EE certificate in RPKI Signed Objects.

    $ openssl cms -verify -noverify -inform DER -signer signer.pem \
        -in OOFPkv3HzPv8GCNhUjrifWl-lS8.mft > /dev/zero
    $ openssl x509 -in signer.pem -text

Life is too short to type that many letters - instead, I'd rather:

    $ rpki-client -p OOFPkv3HzPv8GCNhUjrifWl-lS8.mft

For completeness' sake, also print all other (not-CMS encapsulated)
file types such as CA certs, BGPsec Router Keys, and CRLs.

OK?

Kind regards,

Job

Index: extern.h
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
retrieving revision 1.150
diff -u -p -r1.150 extern.h
--- extern.h    19 Aug 2022 12:45:53 -0000      1.150
+++ extern.h    24 Aug 2022 23:33:24 -0000
@@ -664,6 +664,7 @@ void                 mft_print(const X509 *, const str
 void            roa_print(const X509 *, const struct roa *);
 void            gbr_print(const X509 *, const struct gbr *);
 void            rsc_print(const X509 *, const struct rsc *);
+int             print_pem(char *);
 
 /* Output! */
 
Index: main.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/main.c,v
retrieving revision 1.209
diff -u -p -r1.209 main.c
--- main.c      4 Aug 2022 13:44:07 -0000       1.209
+++ main.c      24 Aug 2022 23:33:25 -0000
@@ -64,6 +64,7 @@ const char    *bird_tablename = "ROAS";
 int    verbose;
 int    noop;
 int    filemode;
+int    pemmode;
 int    rrdpon = 1;
 int    repo_timeout;
 
@@ -819,7 +820,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:fjnoprRs:S:t:T:vV")) != -1)
                switch (c) {
                case 'b':
                        bind_addr = optarg;
@@ -849,6 +850,9 @@ main(int argc, char *argv[])
                case 'o':
                        outformats |= FORMAT_OPENBGPD;
                        break;
+               case 'p':
+                       pemmode = 1;
+                       break;
                case 'R':
                        rrdpon = 0;
                        break;
@@ -888,6 +892,17 @@ main(int argc, char *argv[])
        argv += optind;
        argc -= optind;
 
+       if (pemmode) {
+               if (pledge("stdio rpath", NULL) == -1)
+                       err(1, "pledge");
+
+               if (argc > 1)
+                       goto usage;
+
+               rc = print_pem(argv[0]);
+               return rc;
+       }
+
        if (!filemode) {
                if (argc == 1)
                        outputdir = argv[0];
@@ -1278,6 +1293,7 @@ usage:
            " [-e rsync_prog]\n"
            "                   [-S skiplist] [-s timeout] [-T table] [-t tal]"
            " [outputdir]\n"
-           "       rpki-client [-Vv] [-d cachedir] [-t tal] -f file ...\n");
+           "       rpki-client [-Vv] [-d cachedir] [-t tal] -f file ...\n"
+           "       rpki-client -p file\n");
        return 1;
 }
Index: print.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/print.c,v
retrieving revision 1.14
diff -u -p -r1.14 print.c
--- print.c     14 Jul 2022 13:24:56 -0000      1.14
+++ print.c     24 Aug 2022 23:33:25 -0000
@@ -1,5 +1,6 @@
 /*     $OpenBSD: print.c,v 1.14 2022/07/14 13:24:56 job Exp $ */
 /*
+ * Copyright (c) 2022 Job Snijders <[email protected]>
  * Copyright (c) 2021 Claudio Jeker <[email protected]>
  * Copyright (c) 2019 Kristaps Dzonsons <[email protected]>
  *
@@ -26,6 +27,8 @@
 #include <time.h>
 
 #include <openssl/evp.h>
+#include <openssl/pem.h>
+#include <openssl/x509.h>
 
 #include "extern.h"
 
@@ -567,4 +570,100 @@ rsc_print(const X509 *x, const struct rs
 
        if (outformats & FORMAT_JSON)
                printf("\t],\n");
+}
+
+/*
+ * Read a file, extract the encapsulated X509 cert and print in PEM format.
+ * Return zero on success, non-zero on failure.
+ */
+int
+print_pem(char *fn)
+{
+       BIO *bio_out = NULL;
+       X509 *x = NULL;
+       X509_CRL *c = NULL;
+       struct gbr *gbr = NULL;
+       struct mft *mft = NULL;
+       struct roa *roa = NULL;
+       struct rsc *rsc = NULL;
+       unsigned char *buf;
+       size_t len;
+       enum rtype type;
+       int rc = 1;
+
+       x509_init_oid();
+
+       type = rtype_from_file_extension(fn);
+       if (type == RTYPE_INVALID) {
+               buf = NULL;
+               warnx("%s: unsupported file type", fn);
+               goto out;
+       }
+
+       if ((buf = load_file(fn, &len)) == NULL) {
+               warnx("load_file failed");
+               goto out;
+       }
+
+       if ((bio_out = BIO_new_fp(stdout, BIO_NOCLOSE)) == NULL)
+               errx(1, "BIO_new_fp");
+
+       switch (type) {
+       case RTYPE_CER:
+               if ((x = d2i_X509(NULL, (const unsigned char **)&buf, len))
+                   == NULL) {
+                       warnx("d2i_X509 failed");
+                       goto out;
+               }
+               break;
+       case RTYPE_CRL:
+               if ((c = d2i_X509_CRL(NULL, (const unsigned char **)&buf, len))
+                   == NULL) {
+                       warnx("d2i_X509_CRL failed");
+                       goto out;
+               }
+               if (!X509_CRL_print(bio_out, c))
+                       errx(1, "X509_CRL_print");
+               if (!PEM_write_bio_X509_CRL(bio_out, c))
+                       errx(1, "PEM_write_bio_X509_CRL");
+               rc = 0;
+               goto out;
+       case RTYPE_GBR:
+               if ((gbr = gbr_parse(&x, fn, buf, len)) == NULL)
+                       goto out;
+               break;
+       case RTYPE_MFT:
+               if ((mft = mft_parse(&x, fn, buf, len)) == NULL)
+                       goto out;
+               break;
+       case RTYPE_ROA:
+               if ((roa = roa_parse(&x, fn, buf, len)) == NULL)
+                       goto out;
+               break;
+       case RTYPE_RSC:
+               if ((rsc = rsc_parse(&x, fn, buf, len)) == NULL)
+                       goto out;
+               break;
+       default:
+               errx(1, "%s: unhandled", fn);
+       }
+
+       if (!X509_print(bio_out, x))
+               errx(1, "X509_print");
+
+       if (!PEM_write_bio_X509(bio_out, x))
+               errx(1, "PEM_write_bio_X509");
+
+       rc = 0;
+ out:
+       BIO_free(bio_out);
+       if (type != RTYPE_CER && type != RTYPE_CRL)
+               free(buf);
+       X509_free(x);
+       X509_CRL_free(c);
+       gbr_free(gbr);
+       mft_free(mft);
+       roa_free(roa);
+       rsc_free(rsc);
+       return rc;
 }
Index: rpki-client.8
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/rpki-client.8,v
retrieving revision 1.68
diff -u -p -r1.68 rpki-client.8
--- rpki-client.8       30 Jun 2022 10:27:52 -0000      1.68
+++ rpki-client.8       24 Aug 2022 23:33:25 -0000
@@ -37,6 +37,8 @@
 .Op Fl t Ar tal
 .Fl f
 .Ar
+.Nm
+.Fl p Ar file
 .Sh DESCRIPTION
 The
 .Nm
@@ -144,6 +146,12 @@ If the
 and
 .Fl j
 options are not specified this is the default.
+.It Fl p Ar file
+Print the encapsulated DER encoded X.509 certificate or CRL in
+.Ar file
+in both human-readable and
+.Em PEM
+format.
 .It Fl R
 Synchronize via RSYNC only.
 .It Fl r

Reply via email to