summaryrefslogtreecommitdiff
path: root/usr.sbin/rpki-client
diff options
context:
space:
mode:
authorJob Snijders <job@cvs.openbsd.org>2022-04-20 10:46:21 +0000
committerJob Snijders <job@cvs.openbsd.org>2022-04-20 10:46:21 +0000
commitcefc080d6ef5721457172b1641d1e2d7a38b1e7e (patch)
tree3ee2f52055fb7dbd880d967525c2ffcb810b09fc /usr.sbin/rpki-client
parent9e3b82aa8c97a55b041bccb95813e3a7ce63eeef (diff)
Add Concatenated JSON output in filemode (rpki-client -j -f *)
The schema is still work in progress. OK claudio@
Diffstat (limited to 'usr.sbin/rpki-client')
-rw-r--r--usr.sbin/rpki-client/extern.h11
-rw-r--r--usr.sbin/rpki-client/mft.c4
-rw-r--r--usr.sbin/rpki-client/parser.c57
-rw-r--r--usr.sbin/rpki-client/print.c350
-rw-r--r--usr.sbin/rpki-client/rpki-client.810
5 files changed, 331 insertions, 101 deletions
diff --git a/usr.sbin/rpki-client/extern.h b/usr.sbin/rpki-client/extern.h
index 129e9b9f91f..fea4bdfe99f 100644
--- a/usr.sbin/rpki-client/extern.h
+++ b/usr.sbin/rpki-client/extern.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: extern.h,v 1.128 2022/04/19 13:52:24 claudio Exp $ */
+/* $OpenBSD: extern.h,v 1.129 2022/04/20 10:46:20 job Exp $ */
/*
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -196,7 +196,7 @@ struct mft {
char *ski; /* SKI */
char *crl; /* CRL file name */
unsigned char crlhash[SHA256_DIGEST_LENGTH];
- time_t valid_from;
+ time_t valid_since;
time_t valid_until;
size_t filesz; /* number of filenames */
unsigned int repoid;
@@ -598,12 +598,13 @@ int x509_location(const char *, const char *, const char *,
/* printers */
char *time2str(time_t);
+void x509_print(const X509 *);
void tal_print(const struct tal *);
void cert_print(const struct cert *);
void crl_print(const struct crl *);
-void mft_print(const struct mft *);
-void roa_print(const struct roa *);
-void gbr_print(const struct gbr *);
+void mft_print(const X509 *, const struct mft *);
+void roa_print(const X509 *, const struct roa *);
+void gbr_print(const X509 *, const struct gbr *);
/* Output! */
diff --git a/usr.sbin/rpki-client/mft.c b/usr.sbin/rpki-client/mft.c
index 4d8caf2ac73..565a441b0bb 100644
--- a/usr.sbin/rpki-client/mft.c
+++ b/usr.sbin/rpki-client/mft.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mft.c,v 1.59 2022/04/19 18:52:36 tb Exp $ */
+/* $OpenBSD: mft.c,v 1.60 2022/04/20 10:46:20 job Exp $ */
/*
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -86,7 +86,7 @@ mft_parse_time(const ASN1_GENERALIZEDTIME *from,
return 0;
}
- if ((p->res->valid_from = timegm(&tm_from)) == -1 ||
+ if ((p->res->valid_since = timegm(&tm_from)) == -1 ||
(p->res->valid_until = timegm(&tm_until)) == -1)
errx(1, "%s: timegm failed", p->fn);
diff --git a/usr.sbin/rpki-client/parser.c b/usr.sbin/rpki-client/parser.c
index abaa54c12cd..7751bc1a3a9 100644
--- a/usr.sbin/rpki-client/parser.c
+++ b/usr.sbin/rpki-client/parser.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: parser.c,v 1.69 2022/04/19 13:25:08 claudio Exp $ */
+/* $OpenBSD: parser.c,v 1.70 2022/04/20 10:46:20 job Exp $ */
/*
* Copyright (c) 2019 Claudio Jeker <claudio@openbsd.org>
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -428,9 +428,9 @@ proc_parser_mft_post(char *file, struct mft *mft, const char *path)
}
/* check that now is not before from */
- if (now < mft->valid_from) {
+ if (now < mft->valid_since) {
warnx("%s: mft not yet valid %s", file,
- time2str(mft->valid_from));
+ time2str(mft->valid_since));
mft->stale = 1;
}
/* check that now is not after until */
@@ -1038,8 +1038,12 @@ proc_parser_file(char *file, unsigned char *buf, size_t len)
enum rtype type;
int is_ta = 0;
- if (num++ > 0)
- printf("--\n");
+ if (num++ > 0) {
+ if (outformats & FORMAT_JSON)
+ printf("\n");
+ else
+ printf("--\n");
+ }
if (strncmp(file, "rsync://", strlen("rsync://")) == 0) {
file += strlen("rsync://");
@@ -1050,7 +1054,10 @@ proc_parser_file(char *file, unsigned char *buf, size_t len)
}
}
- printf("File: %s\n", file);
+ if (outformats & FORMAT_JSON)
+ printf("{\n\t\"file\": \"%s\",\n", file);
+ else
+ printf("File: %s\n", file);
type = rtype_from_file_extension(file);
@@ -1081,7 +1088,7 @@ proc_parser_file(char *file, unsigned char *buf, size_t len)
mft = mft_parse(&x509, file, buf, len);
if (mft == NULL)
break;
- mft_print(mft);
+ mft_print(x509, mft);
aia = mft->aia;
aki = mft->aki;
break;
@@ -1089,7 +1096,7 @@ proc_parser_file(char *file, unsigned char *buf, size_t len)
roa = roa_parse(&x509, file, buf, len);
if (roa == NULL)
break;
- roa_print(roa);
+ roa_print(x509, roa);
aia = roa->aia;
aki = roa->aki;
break;
@@ -1097,7 +1104,7 @@ proc_parser_file(char *file, unsigned char *buf, size_t len)
gbr = gbr_parse(&x509, file, buf, len);
if (gbr == NULL)
break;
- gbr_print(gbr);
+ gbr_print(x509, gbr);
aia = gbr->aia;
aki = gbr->aki;
break;
@@ -1112,6 +1119,11 @@ proc_parser_file(char *file, unsigned char *buf, size_t len)
break;
}
+ if (outformats & FORMAT_JSON)
+ printf("\t\"validation\": \"");
+ else
+ printf("Validation: ");
+
if (aia != NULL) {
struct auth *a;
struct crl *c;
@@ -1126,25 +1138,34 @@ proc_parser_file(char *file, unsigned char *buf, size_t len)
c = get_crl(a);
if (valid_x509(file, x509, a, c, 0))
- printf("Validation: OK\n");
+ printf("OK");
else
- printf("Validation: Failed\n");
+ printf("Failed");
} else if (is_ta) {
if ((tal = find_tal(cert)) != NULL) {
cert = ta_parse(file, cert, tal->pkey, tal->pkeysz);
- printf("TAL: %s\n", tal->descr);
- tal = NULL;
+ if (cert != NULL)
+ printf("OK");
} else {
cert_free(cert);
cert = NULL;
- printf("TAL: not found\n");
+ printf("Failed");
}
- if (cert != NULL)
- printf("Validation: OK\n");
- else
- printf("Validation: Failed\n");
}
+ if (is_ta) {
+ if (outformats & FORMAT_JSON) {
+ printf("\",\n\t\"tal\": \"%s\"\n", tal->descr);
+ printf("}");
+ } else {
+ printf("\nTAL: %s\n", tal->descr);
+ }
+ tal = NULL;
+ } else if (outformats & FORMAT_JSON)
+ printf("\"\n}");
+ else
+ printf("\n");
+
X509_free(x509);
cert_free(cert);
crl_free(crl);
diff --git a/usr.sbin/rpki-client/print.c b/usr.sbin/rpki-client/print.c
index d1a54f4d524..89bb4bbc9ea 100644
--- a/usr.sbin/rpki-client/print.c
+++ b/usr.sbin/rpki-client/print.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: print.c,v 1.7 2022/04/12 11:05:50 job Exp $ */
+/* $OpenBSD: print.c,v 1.8 2022/04/20 10:46:20 job Exp $ */
/*
* Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -73,7 +73,6 @@ tal_print(const struct tal *p)
int rder_len;
size_t i;
- printf("Trust anchor name: %s\n", p->descr);
der = p->pkey;
pk = d2i_PUBKEY(NULL, &der, p->pkeysz);
@@ -90,76 +89,177 @@ tal_print(const struct tal *p)
errx(1, "EVP_Digest failed in %s", __func__);
ski = hex_encode(md, SHA_DIGEST_LENGTH);
- printf("Subject key identifier: %s\n", pretty_key_id(ski));
-
- printf("Trust anchor locations:\n");
- for (i = 0; i < p->urisz; i++)
- printf("%5zu: %s\n", i + 1, p->uri[i]);
+ if (outformats & FORMAT_JSON) {
+ printf("\t\"type\": \"tal\",\n");
+ printf("\t\"name\": %s\n", p->descr);
+ printf("\t\"ski\": %s\n", pretty_key_id(ski));
+ printf("\t\"trust_anchor_locations\": [");
+ for (i = 0; i < p->urisz; i++) {
+ printf("\"%s\"", p->uri[i]);
+ if (i + 1 < p->urisz)
+ printf(", ");
+ }
+ printf("]\n");
+
+ } else {
+ printf("Trust anchor name: %s\n", p->descr);
+ printf("Subject key identifier: %s\n", pretty_key_id(ski));
+ printf("Trust anchor locations:\n");
+ for (i = 0; i < p->urisz; i++)
+ printf("%5zu: %s\n", i + 1, p->uri[i]);
+ }
+
EVP_PKEY_free(pk);
free(rder);
free(ski);
}
void
+x509_print(const X509 *x)
+{
+ const ASN1_INTEGER *xserial;
+ char *serial = NULL;
+
+ xserial = X509_get0_serialNumber(x);
+ if (xserial == NULL) {
+ warnx("X509_get0_serialNumber failed in %s", __func__);
+ goto out;
+ }
+
+ serial = x509_convert_seqnum(__func__, xserial);
+ if (serial == NULL) {
+ warnx("x509_convert_seqnum failed in %s", __func__);
+ goto out;
+ }
+
+ if (outformats & FORMAT_JSON) {
+ printf("\t\"cert_serial\": \"%s\",\n", serial);
+ } else {
+ printf("Certificate serial: %s\n", serial);
+ }
+
+ out:
+ free(serial);
+}
+
+void
cert_print(const struct cert *p)
{
- size_t i;
- char buf1[64], buf2[64];
- int sockt;
- char tbuf[21];
+ size_t i, j;
+ char buf1[64], buf2[64];
+ int sockt;
+ char tbuf[21];
- printf("Subject key identifier: %s\n", pretty_key_id(p->ski));
- if (p->aki != NULL)
- printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
- if (p->aia != NULL)
- printf("Authority info access: %s\n", p->aia);
- if (p->mft != NULL)
- printf("Manifest: %s\n", p->mft);
- if (p->repo != NULL)
- printf("caRepository: %s\n", p->repo);
- if (p->notify != NULL)
- printf("Notify URL: %s\n", p->notify);
- if (p->pubkey != NULL)
- printf("BGPsec P-256 ECDSA public key: %s\n", p->pubkey);
strftime(tbuf, sizeof(tbuf), "%FT%TZ", gmtime(&p->expires));
- printf("Valid until: %s\n", tbuf);
- printf("Subordinate Resources:\n");
+ if (outformats & FORMAT_JSON) {
+ if (p->pubkey != NULL)
+ printf("\t\"type\": \"router_key\",\n");
+ else
+ printf("\t\"type\": \"ca_cert\",\n");
+ printf("\t\"ski\": \"%s\",\n", pretty_key_id(p->ski));
+ if (p->aki != NULL)
+ printf("\t\"aki\": \"%s\",\n", pretty_key_id(p->aki));
+ x509_print(p->x509);
+ if (p->aia != NULL)
+ printf("\t\"aia\": \"%s\",\n", p->aia);
+ if (p->mft != NULL)
+ printf("\t\"manifest\": \"%s\",\n", p->mft);
+ if (p->repo != NULL)
+ printf("\t\"carepository\": \"%s\",\n", p->repo);
+ if (p->notify != NULL)
+ printf("\t\"notify_url\": \"%s\",\n", p->notify);
+ if (p->pubkey != NULL)
+ printf("\t\"router_key\": \"%s\",\n", p->pubkey);
+ printf("\t\"valid_until\": %lld,\n", (long long)p->expires);
+ printf("\t\"subordinate_resources\": [\n");
+ } else {
+ printf("Subject key identifier: %s\n", pretty_key_id(p->ski));
+ if (p->aki != NULL)
+ printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
+ x509_print(p->x509);
+ if (p->aia != NULL)
+ printf("Authority info access: %s\n", p->aia);
+ if (p->mft != NULL)
+ printf("Manifest: %s\n", p->mft);
+ if (p->repo != NULL)
+ printf("caRepository: %s\n", p->repo);
+ if (p->notify != NULL)
+ printf("Notify URL: %s\n", p->notify);
+ if (p->pubkey != NULL)
+ printf("BGPsec P-256 ECDSA public key: %s\n", p->pubkey);
+ printf("Valid until: %s\n", tbuf);
+ printf("Subordinate Resources:\n");
+ }
- for (i = 0; i < p->asz; i++)
+ for (i = 0; i < p->asz; i++) {
switch (p->as[i].type) {
case CERT_AS_ID:
- printf("%5zu: AS: %u\n", i + 1, p->as[i].id);
+ if (outformats & FORMAT_JSON)
+ printf("\t\t{ \"asid\": %u }", p->as[i].id);
+ else
+ printf("%5zu: AS: %u", i + 1, p->as[i].id);
break;
case CERT_AS_INHERIT:
- printf("%5zu: AS: inherit\n", i + 1);
+ if (outformats & FORMAT_JSON)
+ printf("\t\t{ \"asid_inherit\": \"true\" }");
+ else
+ printf("%5zu: AS: inherit", i + 1);
break;
case CERT_AS_RANGE:
- printf("%5zu: AS: %u -- %u\n", i + 1,
- p->as[i].range.min, p->as[i].range.max);
+ if (outformats & FORMAT_JSON)
+ printf("\t\t{ \"asrange\": { \"min\": %u, "
+ "\"max\": %u }}", p->as[i].range.min,
+ p->as[i].range.max);
+ else
+ printf("%5zu: AS: %u -- %u", i + 1,
+ p->as[i].range.min, p->as[i].range.max);
break;
}
+ if (outformats & FORMAT_JSON && i + 1 < p->asz + p->ipsz)
+ printf(",\n");
+ else
+ printf("\n");
+ }
- for (i = 0; i < p->ipsz; i++)
- switch (p->ips[i].type) {
+ for (j = 0; j < p->ipsz; j++) {
+ switch (p->ips[j].type) {
case CERT_IP_INHERIT:
- printf("%5zu: IP: inherit\n", i + 1);
+ if (outformats & FORMAT_JSON)
+ printf("\t\t{ \"ip_inherit\": \"true\" }");
+ else
+ printf("%5zu: IP: inherit", i + j + 1);
break;
case CERT_IP_ADDR:
- ip_addr_print(&p->ips[i].ip,
- p->ips[i].afi, buf1, sizeof(buf1));
- printf("%5zu: IP: %s\n", i + 1, buf1);
+ ip_addr_print(&p->ips[j].ip,
+ p->ips[j].afi, buf1, sizeof(buf1));
+ if (outformats & FORMAT_JSON)
+ printf("\t\t{ \"ip_prefix\": \"%s\" }", buf1);
+ else
+ printf("%5zu: IP: %s", i + j + 1, buf1);
break;
case CERT_IP_RANGE:
- sockt = (p->ips[i].afi == AFI_IPV4) ?
+ sockt = (p->ips[j].afi == AFI_IPV4) ?
AF_INET : AF_INET6;
- inet_ntop(sockt, p->ips[i].min, buf1, sizeof(buf1));
- inet_ntop(sockt, p->ips[i].max, buf2, sizeof(buf2));
- printf("%5zu: IP: %s -- %s\n", i + 1, buf1, buf2);
+ inet_ntop(sockt, p->ips[j].min, buf1, sizeof(buf1));
+ inet_ntop(sockt, p->ips[j].max, buf2, sizeof(buf2));
+ if (outformats & FORMAT_JSON)
+ printf("\t\t{ \"ip_range\": { \"min\": \"%s\""
+ ", \"max\": \"%s\" }}", buf1, buf2);
+ else
+ printf("%5zu: IP: %s -- %s", i + j + 1, buf1,
+ buf2);
break;
}
+ if (outformats & FORMAT_JSON && i + j + 1 < p->asz + p->ipsz)
+ printf(",\n");
+ else
+ printf("\n");
+ }
+ if (outformats & FORMAT_JSON)
+ printf("\t],\n");
}
void
@@ -172,81 +272,185 @@ crl_print(const struct crl *p)
char *serial;
time_t t;
- printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
+ if (outformats & FORMAT_JSON) {
+ printf("\t\"type\": \"crl\",\n");
+ printf("\t\"aki\": \"%s\",\n", pretty_key_id(p->aki));
+ } else
+ printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
crlnum = X509_CRL_get_ext_d2i(p->x509_crl, NID_crl_number, NULL, NULL);
serial = x509_convert_seqnum(__func__, crlnum);
- if (serial != NULL)
- printf("CRL Serial Number: %s\n", serial);
+ if (serial != NULL) {
+ if (outformats & FORMAT_JSON)
+ printf("\t\"crl_serial\": \"%s\",\n", serial);
+ else
+ printf("CRL Serial Number: %s\n", serial);
+ }
free(serial);
ASN1_INTEGER_free(crlnum);
- printf("CRL valid since: %s\n", time2str(p->issued));
- printf("CRL valid until: %s\n", time2str(p->expires));
+ if (outformats & FORMAT_JSON) {
+ printf("\t\"valid_since\": %lld,\n", (long long)p->issued);
+ printf("\t\"valid_until\": %lld,\n", (long long)p->expires);
+ printf("\t\"revoked_certs\": [\n");
+ } else {
+ printf("CRL valid since: %s\n", time2str(p->issued));
+ printf("CRL valid until: %s\n", time2str(p->expires));
+ printf("Revoked Certificates:\n");
+ }
revlist = X509_CRL_get_REVOKED(p->x509_crl);
for (i = 0; i < sk_X509_REVOKED_num(revlist); i++) {
- if (i == 0)
- printf("Revoked Certificates:\n");
rev = sk_X509_REVOKED_value(revlist, i);
-
serial = x509_convert_seqnum(__func__,
X509_REVOKED_get0_serialNumber(rev));
x509_get_time(X509_REVOKED_get0_revocationDate(rev), &t);
- if (serial != NULL)
- printf(" Serial: %8s Revocation Date: %s\n",
- serial, time2str(t));
+ if (serial != NULL) {
+ if (outformats & FORMAT_JSON) {
+ printf("\t\t{ \"serial\": \"%s\"", serial);
+ printf(", \"date\": \"%s\" }", time2str(t));
+ if (i + 1 < sk_X509_REVOKED_num(revlist))
+ printf(",");
+ printf("\n");
+ } else
+ printf(" Serial: %8s Revocation Date: %s"
+ "\n", serial, time2str(t));
+ }
free(serial);
}
- if (i == 0)
+
+ if (outformats & FORMAT_JSON)
+ printf("\t],\n");
+ else if (i == 0)
printf("No Revoked Certificates\n");
}
void
-mft_print(const struct mft *p)
+mft_print(const X509 *x, const struct mft *p)
{
size_t i;
char *hash;
- printf("Subject key identifier: %s\n", pretty_key_id(p->ski));
- printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
- printf("Authority info access: %s\n", p->aia);
- printf("Manifest Number: %s\n", p->seqnum);
+ if (outformats & FORMAT_JSON) {
+ printf("\t\"type\": \"manifest\",\n");
+ printf("\t\"ski\": \"%s\",\n", pretty_key_id(p->ski));
+ x509_print(x);
+ printf("\t\"aki\": \"%s\",\n", pretty_key_id(p->aki));
+ printf("\t\"aia\": \"%s\",\n", p->aia);
+ printf("\t\"manifest_number\": \"%s\",\n", p->seqnum);
+ printf("\t\"valid_since\": %lld,\n", (long long)p->valid_since);
+ printf("\t\"valid_until\": %lld,\n", (long long)p->valid_until);
+ } else {
+ printf("Subject key identifier: %s\n", pretty_key_id(p->ski));
+ printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
+ x509_print(x);
+ printf("Authority info access: %s\n", p->aia);
+ printf("Manifest Number: %s\n", p->seqnum);
+ printf("Manifest valid since: %s\n", time2str(p->valid_since));
+ printf("Manifest valid until: %s\n", time2str(p->valid_until));
+ }
+
for (i = 0; i < p->filesz; i++) {
+ if (i == 0 && outformats & FORMAT_JSON)
+ printf("\t\"filesandhashes\": [\n");
+
if (base64_encode(p->files[i].hash, sizeof(p->files[i].hash),
&hash) == -1)
errx(1, "base64_encode failure");
- printf("%5zu: %s\n", i + 1, p->files[i].file);
- printf("\thash %s\n", hash);
+
+ if (outformats & FORMAT_JSON) {
+ printf("\t\t{ \"filename\": \"%s\",", p->files[i].file);
+ printf(" \"hash\": \"%s\" }", hash);
+ if (i + 1 < p->filesz)
+ printf(",");
+ printf("\n");
+ } else {
+ printf("%5zu: %s\n", i + 1, p->files[i].file);
+ printf("\thash %s\n", hash);
+ }
+
free(hash);
}
+
+ if (outformats & FORMAT_JSON)
+ printf("\t],\n");
+
+
}
void
-roa_print(const struct roa *p)
+roa_print(const X509 *x, const struct roa *p)
{
char buf[128];
size_t i;
- printf("Subject key identifier: %s\n", pretty_key_id(p->ski));
- printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
- printf("Authority info access: %s\n", p->aia);
- printf("ROA valid until: %s\n", time2str(p->expires));
+ if (outformats & FORMAT_JSON) {
+ printf("\t\"type\": \"roa\",\n");
+ printf("\t\"ski\": \"%s\",\n", pretty_key_id(p->ski));
+ x509_print(x);
+ printf("\t\"aki\": \"%s\",\n", pretty_key_id(p->aki));
+ printf("\t\"aia\": \"%s\",\n", p->aia);
+ printf("\t\"valid_until\": %lld,\n", (long long)p->expires);
+ } else {
+ printf("Subject key identifier: %s\n", pretty_key_id(p->ski));
+ x509_print(x);
+ printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
+ printf("Authority info access: %s\n", p->aia);
+ printf("ROA valid until: %s\n", time2str(p->expires));
+ printf("asID: %u\n", p->asid);
+ }
- printf("asID: %u\n", p->asid);
for (i = 0; i < p->ipsz; i++) {
+ if (i == 0 && outformats & FORMAT_JSON)
+ printf("\t\"vrps\": [\n");
+
ip_addr_print(&p->ips[i].addr,
p->ips[i].afi, buf, sizeof(buf));
- printf("%5zu: %s maxlen: %hhu\n", i + 1,
- buf, p->ips[i].maxlength);
+
+ if (outformats & FORMAT_JSON) {
+ printf("\t\t{ \"prefix\": \"%s\",", buf);
+ printf(" \"asid\": %u,", p->asid);
+ printf(" \"maxlen\": %hhu }", p->ips[i].maxlength);
+ if (i + 1 < p->ipsz)
+ printf(",");
+ printf("\n");
+ } else
+ printf("%5zu: %s maxlen: %hhu\n", i + 1, buf,
+ p->ips[i].maxlength);
}
+
+ if (outformats & FORMAT_JSON)
+ printf("\t],\n");
}
void
-gbr_print(const struct gbr *p)
+gbr_print(const X509 *x, const struct gbr *p)
{
- printf("Subject key identifier: %s\n", pretty_key_id(p->ski));
- printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
- printf("Authority info access: %s\n", p->aia);
- printf("vcard:\n%s", p->vcard);
+ size_t i;
+
+ if (outformats & FORMAT_JSON) {
+ printf("\t\"type\": \"gbr\",\n");
+ printf("\t\"ski\": \"%s\",\n", pretty_key_id(p->ski));
+ x509_print(x);
+ printf("\t\"aki\": \"%s\",\n", pretty_key_id(p->aki));
+ printf("\t\"aia\": \"%s\",\n", p->aia);
+ printf("\t\"vcard\": \"");
+ for (i = 0; i < strlen(p->vcard); i++) {
+ if (p->vcard[i] == '"')
+ printf("\\\"");
+ if (p->vcard[i] == '\r')
+ continue;
+ if (p->vcard[i] == '\n')
+ printf("\\r\\n");
+ else
+ putchar(p->vcard[i]);
+ }
+ printf("\",\n");
+ } else {
+ printf("Subject key identifier: %s\n", pretty_key_id(p->ski));
+ x509_print(x);
+ printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
+ printf("Authority info access: %s\n", p->aia);
+ printf("vcard:\n%s", p->vcard);
+ }
}
diff --git a/usr.sbin/rpki-client/rpki-client.8 b/usr.sbin/rpki-client/rpki-client.8
index 4ff77286441..b03188a28d2 100644
--- a/usr.sbin/rpki-client/rpki-client.8
+++ b/usr.sbin/rpki-client/rpki-client.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: rpki-client.8,v 1.59 2022/04/12 12:54:09 jmc Exp $
+.\" $OpenBSD: rpki-client.8,v 1.60 2022/04/20 10:46:20 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: April 12 2022 $
+.Dd $Mdocdate: April 20 2022 $
.Dt RPKI-CLIENT 8
.Os
.Sh NAME
@@ -112,7 +112,11 @@ If
.Ar file
is an rsync:// URI, the corresponding file from the cache will be used.
This option implies
-.Fl n .
+.Fl n ,
+and can be combined with
+.Fl j
+to emit a stream of
+.Em Concatenated JSON .
.It Fl j
Create output in the file
.Pa json