From: Alberto Leiva Popper Date: Mon, 29 Apr 2024 20:56:22 +0000 (-0600) Subject: Add CRLs and their extensions to --mode=print X-Git-Tag: 1.6.2~34 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7a0b2efc6bb334db60a9b23d6da16ba4aa4ab4ee;p=thirdparty%2FFORT-validator.git Add CRLs and their extensions to --mode=print Progress for #122. --- diff --git a/src/asn1/asn1c/CRL.c b/src/asn1/asn1c/CRL.c new file mode 100644 index 00000000..5c3b2408 --- /dev/null +++ b/src/asn1/asn1c/CRL.c @@ -0,0 +1,125 @@ +#include "asn1/asn1c/CRL.h" + +#include +#include +#include "extension.h" +#include "libcrypto_util.h" + +static json_t * +revokedCerts2json(X509_CRL *crl) +{ + STACK_OF(X509_REVOKED) *revokeds = X509_CRL_get_REVOKED(crl); + json_t *root, *child; + X509_REVOKED *rv; + int r; + + root = json_array(); + if (root == NULL) + return NULL; + + for (r = 0; r < sk_X509_REVOKED_num(revokeds); r++) { + rv = sk_X509_REVOKED_value(revokeds, 0); + if (json_array_append_new(root, child = json_object()) < 0) + goto fail; + if (json_object_set_new(child, "userCertificate", asn1int2json(X509_REVOKED_get0_serialNumber(rv))) < 0) + goto fail; + if (json_object_set_new(child, "revocationDate", asn1time2json(X509_REVOKED_get0_revocationDate(rv))) < 0) + goto fail; + if (json_object_set_new(child, "crlEntryExtensions", exts2json(X509_REVOKED_get0_extensions(rv))) < 0) + goto fail; + } + + return root; + +fail: json_decref(root); + return NULL; +} + +static json_t * +tbsCertList2json(X509_CRL *crl) +{ + json_t *root; + + root = json_object(); + if (root == NULL) + return NULL; + + if (json_object_set_new(root, "version", json_integer(X509_CRL_get_version(crl))) < 0) + goto fail; + if (json_object_set_new(root, "signature", json_string(OBJ_nid2sn(X509_CRL_get_signature_nid(crl)))) < 0) + goto fail; + if (json_object_set_new(root, "issuer", name2json(X509_CRL_get_issuer(crl))) < 0) + goto fail; + if (json_object_set_new(root, "thisUpdate", asn1time2json(X509_CRL_get0_lastUpdate(crl))) < 0) + goto fail; + if (json_object_set_new(root, "nextUpdate", asn1time2json(X509_CRL_get0_nextUpdate(crl))) < 0) + goto fail; + if (json_object_set_new(root, "revokedCertificates", revokedCerts2json(crl)) < 0) + goto fail; + if (json_object_set_new(root, "crlExtensions", exts2json(X509_CRL_get0_extensions(crl))) < 0) + goto fail; + + return root; + +fail: json_decref(root); + return NULL; +} + +static json_t * +sigAlgorithm2json(X509_CRL *crl) +{ + const X509_ALGOR *palg; + const ASN1_OBJECT *paobj; + + X509_CRL_get0_signature(crl, NULL, &palg); + X509_ALGOR_get0(&paobj, NULL, NULL, palg); + + return oid2json(paobj); +} + +static json_t * +sigValue2json(X509_CRL *crl) +{ + const ASN1_BIT_STRING *signature; + X509_CRL_get0_signature(crl, &signature, NULL); + return asn1str2json(signature); +} + +static json_t * +crl2json(X509_CRL *crl) +{ + json_t *root; + + root = json_object(); + if (root == NULL) + return NULL; + + if (json_object_set_new(root, "tbsCertList", tbsCertList2json(crl)) < 0) + goto fail; + if (json_object_set_new(root, "signatureAlgorithm", sigAlgorithm2json(crl)) < 0) + goto fail; + if (json_object_set_new(root, "signatureValue", sigValue2json(crl)) < 0) + goto fail; + + return root; + +fail: json_decref(root); + return NULL; +} + +json_t * +CRL_encode_json(ANY_t *ber) +{ + const unsigned char *tmp = (const unsigned char *) ber->buf; + X509_CRL *crl; + json_t *root; + + crl = d2i_X509_CRL(NULL, &tmp, ber->size); + if (crl == NULL) + return NULL; + + root = crl2json(crl); + + X509_CRL_free(crl); + return root; +} diff --git a/src/asn1/asn1c/CRL.h b/src/asn1/asn1c/CRL.h new file mode 100644 index 00000000..3c09eb87 --- /dev/null +++ b/src/asn1/asn1c/CRL.h @@ -0,0 +1,9 @@ +#ifndef SRC_ASN1_ASN1C_CRL_H_ +#define SRC_ASN1_ASN1C_CRL_H_ + +#include +#include "asn1/asn1c/ANY.h" + +json_t *CRL_encode_json(ANY_t *ber); + +#endif /* SRC_ASN1_ASN1C_CRL_H_ */ diff --git a/src/asn1/asn1c/Certificate.c b/src/asn1/asn1c/Certificate.c index 8b4fbbe4..5bfcfdfd 100644 --- a/src/asn1/asn1c/Certificate.c +++ b/src/asn1/asn1c/Certificate.c @@ -2,7 +2,6 @@ #include #include -#include "alloc.h" #include "extension.h" #include "libcrypto_util.h" @@ -87,111 +86,6 @@ suid2json(X509 const *x) return asn1str2json(suid); } -static json_t * -ext2json_known(struct extension_metadata const *meta, X509_EXTENSION *ext) -{ - void *decoded; - json_t *json; - - decoded = X509V3_EXT_d2i(ext); - if (decoded == NULL) - return NULL; - - json = meta->to_json(decoded); - - meta->destructor(decoded); - return json; -} - -static json_t * -ext2json_unknown(X509_EXTENSION *ext) -{ - BIO *bio = BIO_new(BIO_s_mem()); - if (bio == NULL) - return NULL; - - /* TODO Those flags are kinda interesting */ - if (!X509V3_EXT_print(bio, ext, 0, 0)) { - BIO_free_all(bio); - return NULL; - } - - return bio2json(bio); -} - -static json_t * -ext2json(X509_EXTENSION *ext) -{ - struct extension_metadata const **array, *meta; - int nid; - - array = ext_metadatas(); - nid = OBJ_obj2nid(X509_EXTENSION_get_object(ext)); - - for (meta = *array; meta != NULL; array++, meta = *array) { - if (meta->nid == nid) { - if (meta->to_json != NULL) - return ext2json_known(meta, ext); - else - break; - } - } - - return ext2json_unknown(ext); -} - -static json_t * -exts2json(const STACK_OF(X509_EXTENSION) *exts) -{ - json_t *root; - BIO *bio; - int i; - - if (sk_X509_EXTENSION_num(exts) <= 0) - return json_null(); - - root = json_object(); - if (root == NULL) - return NULL; - - for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { - json_t *node; - X509_EXTENSION *ex; - - ex = sk_X509_EXTENSION_value(exts, i); - - /* Get the extension name */ - bio = BIO_new(BIO_s_mem()); - if (bio == NULL) - goto fail; - if (i2a_ASN1_OBJECT(bio, X509_EXTENSION_get_object(ex)) <= 0) { - BIO_free_all(bio); - goto fail; - } - - /* Create node, add to parent */ - node = json_object(); - if (node == NULL) { - BIO_free_all(bio); - goto fail; - } - if (json_object_set_new(root, bio2str(bio), node) < 0) - goto fail; - - /* Child 1: Critical */ - if (json_object_set_new(node, "critical", X509_EXTENSION_get_critical(ex) ? json_true() : json_false()) < 0) - goto fail; - /* Child 2: Value */ - if (json_object_set_new(node, "value", ext2json(ex))) - goto fail; - } - - return root; - -fail: json_decref(root); - return NULL; -} - static json_t * tbsCert2json(X509 *x) { @@ -224,8 +118,7 @@ tbsCert2json(X509 *x) return tbsCert; -fail: - json_decref(tbsCert); +fail: json_decref(tbsCert); return NULL; } @@ -267,8 +160,7 @@ x509_to_json(X509 *x) return root; -fail: - json_decref(root); +fail: json_decref(root); return NULL; } @@ -292,13 +184,7 @@ Certificate_encode_json(ANY_t *ber) return NULL; root = x509_to_json(cert); - if (root == NULL) - goto fail; X509_free(cert); return root; - -fail: json_decref(root); - X509_free(cert); - return NULL; } diff --git a/src/asn1/asn1c/Makefile.include b/src/asn1/asn1c/Makefile.include index 245ec2e2..5fafde39 100644 --- a/src/asn1/asn1c/Makefile.include +++ b/src/asn1/asn1c/Makefile.include @@ -49,6 +49,7 @@ ASN_MODULE_SRCS= \ asn1/asn1c/OtherRevocationInfoFormat.c \ asn1/asn1c/Certificate.c \ asn1/asn1c/CertificateSet.c \ + asn1/asn1c/CRL.c \ asn1/asn1c/IssuerAndSerialNumber.c \ asn1/asn1c/CMSVersion.c \ asn1/asn1c/MessageDigest.c \ @@ -113,6 +114,7 @@ ASN_MODULE_HDRS= \ asn1/asn1c/OtherRevocationInfoFormat.h \ asn1/asn1c/Certificate.h \ asn1/asn1c/CertificateSet.h \ + asn1/asn1c/CRL.h \ asn1/asn1c/IssuerAndSerialNumber.h \ asn1/asn1c/CMSVersion.h \ asn1/asn1c/MessageDigest.h \ diff --git a/src/extension.c b/src/extension.c index b0657abd..fb2b5378 100644 --- a/src/extension.c +++ b/src/extension.c @@ -660,16 +660,59 @@ static struct extension_metadata AR2 = { ir_destroy, }; +static json_t * +cn2json(void const *ext) +{ + return asn1int2json(ext); +} + +static void +cn_destroy(void *cn) +{ + ASN1_INTEGER_free(cn); +} + static const struct extension_metadata CN = { "CRL Number", NID_crl_number, false, + cn2json, + cn_destroy, }; +static json_t * +eku2json(void const *ext) +{ + EXTENDED_KEY_USAGE const *eku = ext; + json_t *root; + int i; + + root = json_array(); + if (root == NULL) + return root; + + for (i = 0; i < sk_ASN1_OBJECT_num(eku); i++) + if (json_array_append_new(root, oid2json(sk_ASN1_OBJECT_value(eku, i))) < 0) + goto fail; + + return root; + +fail: json_decref(root); + return NULL; +} + +static void +eku_destroy(void *eku) +{ + EXTENDED_KEY_USAGE_free(eku); +} + static const struct extension_metadata EKU = { "Extended Key Usage", NID_ext_key_usage, false, + eku2json, + eku_destroy, }; int extension_init(void) diff --git a/src/libcrypto_util.c b/src/libcrypto_util.c index c5d93e33..462e79f3 100644 --- a/src/libcrypto_util.c +++ b/src/libcrypto_util.c @@ -4,6 +4,7 @@ #include #include "alloc.h" +#include "extension.h" /* Swallows @bio. */ char * @@ -179,3 +180,108 @@ gns2json(GENERAL_NAMES const *gns) fail: json_decref(root); return NULL; } + +static json_t * +ext2json_known(struct extension_metadata const *meta, X509_EXTENSION *ext) +{ + void *decoded; + json_t *json; + + decoded = X509V3_EXT_d2i(ext); + if (decoded == NULL) + return NULL; + + json = meta->to_json(decoded); + + meta->destructor(decoded); + return json; +} + +static json_t * +ext2json_unknown(X509_EXTENSION *ext) +{ + BIO *bio = BIO_new(BIO_s_mem()); + if (bio == NULL) + return NULL; + + /* TODO Those flags are kinda interesting */ + if (!X509V3_EXT_print(bio, ext, 0, 0)) { + BIO_free_all(bio); + return NULL; + } + + return bio2json(bio); +} + +static json_t * +ext2json(X509_EXTENSION *ext) +{ + struct extension_metadata const **array, *meta; + int nid; + + array = ext_metadatas(); + nid = OBJ_obj2nid(X509_EXTENSION_get_object(ext)); + + for (meta = *array; meta != NULL; array++, meta = *array) { + if (meta->nid == nid) { + if (meta->to_json != NULL) + return ext2json_known(meta, ext); + else + break; + } + } + + return ext2json_unknown(ext); +} + +json_t * +exts2json(const STACK_OF(X509_EXTENSION) *exts) +{ + json_t *root; + BIO *bio; + int i; + + if (sk_X509_EXTENSION_num(exts) <= 0) + return json_null(); + + root = json_object(); + if (root == NULL) + return NULL; + + for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { + json_t *node; + X509_EXTENSION *ex; + + ex = sk_X509_EXTENSION_value(exts, i); + + /* Get the extension name */ + bio = BIO_new(BIO_s_mem()); + if (bio == NULL) + goto fail; + if (i2a_ASN1_OBJECT(bio, X509_EXTENSION_get_object(ex)) <= 0) { + BIO_free_all(bio); + goto fail; + } + + /* Create node, add to parent */ + node = json_object(); + if (node == NULL) { + BIO_free_all(bio); + goto fail; + } + if (json_object_set_new(root, bio2str(bio), node) < 0) + goto fail; + + /* Child 1: Critical */ + if (json_object_set_new(node, "critical", X509_EXTENSION_get_critical(ex) ? json_true() : json_false()) < 0) + goto fail; + /* Child 2: Value */ + if (json_object_set_new(node, "value", ext2json(ex))) + goto fail; + } + + return root; + +fail: json_decref(root); + return NULL; +} diff --git a/src/libcrypto_util.h b/src/libcrypto_util.h index e1da52f0..53c9ba52 100644 --- a/src/libcrypto_util.h +++ b/src/libcrypto_util.h @@ -15,5 +15,6 @@ json_t *asn1time2json(ASN1_TIME const *); json_t *name2json(X509_NAME const *); json_t *gn2json(GENERAL_NAME const *); json_t *gns2json(GENERAL_NAMES const *); +json_t *exts2json(const STACK_OF(X509_EXTENSION) *); #endif /* SRC_LIBCRYPTO_UTIL_H_ */ diff --git a/src/print_file.c b/src/print_file.c index 7344fc01..830156f4 100644 --- a/src/print_file.c +++ b/src/print_file.c @@ -7,6 +7,29 @@ #include "log.h" #include "asn1/content_info.h" #include "asn1/asn1c/Certificate.h" +#include "asn1/asn1c/CRL.h" + +static json_t * +libcrypto2json(char const *filename, json_t *(*encoder)(ANY_t *)) +{ + struct file_contents fc; + ANY_t any; + json_t *json; + int error; + + error = file_load(filename, &fc); + if (error) + return NULL; + + memset(&any, 0, sizeof(any)); + any.buf = fc.buffer; + any.size = fc.buffer_size; + + json = encoder(&any); + + file_free(&fc); + return json; +} int print_file(void) @@ -18,20 +41,9 @@ print_file(void) filename = config_get_payload(); if (str_ends_with(filename, ".cer")) { - struct file_contents fc; - ANY_t any; - - error = file_load(filename, &fc); - if (error) - return error; - - memset(&any, 0, sizeof(any)); - any.buf = fc.buffer; - any.size = fc.buffer_size; - - json = Certificate_encode_json(&any); - - file_free(&fc); + json = libcrypto2json(filename, Certificate_encode_json); + } else if (str_ends_with(filename, ".crl")) { + json = libcrypto2json(filename, CRL_encode_json); } else { error = content_info_load(filename, &ci);