]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Add CRLs and their extensions to --mode=print
authorAlberto Leiva Popper <ydahhrk@gmail.com>
Mon, 29 Apr 2024 20:56:22 +0000 (14:56 -0600)
committerAlberto Leiva Popper <ydahhrk@gmail.com>
Mon, 29 Apr 2024 21:52:03 +0000 (15:52 -0600)
Progress for #122.

src/asn1/asn1c/CRL.c [new file with mode: 0644]
src/asn1/asn1c/CRL.h [new file with mode: 0644]
src/asn1/asn1c/Certificate.c
src/asn1/asn1c/Makefile.include
src/extension.c
src/libcrypto_util.c
src/libcrypto_util.h
src/print_file.c

diff --git a/src/asn1/asn1c/CRL.c b/src/asn1/asn1c/CRL.c
new file mode 100644 (file)
index 0000000..5c3b240
--- /dev/null
@@ -0,0 +1,125 @@
+#include "asn1/asn1c/CRL.h"
+
+#include <openssl/x509v3.h>
+#include <openssl/pem.h>
+#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 (file)
index 0000000..3c09eb8
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef SRC_ASN1_ASN1C_CRL_H_
+#define SRC_ASN1_ASN1C_CRL_H_
+
+#include <jansson.h>
+#include "asn1/asn1c/ANY.h"
+
+json_t *CRL_encode_json(ANY_t *ber);
+
+#endif /* SRC_ASN1_ASN1C_CRL_H_ */
index 8b4fbbe46de3467c4a4223e4d16b5b0f8f165848..5bfcfdfdfa924f87e51d1045b73be2c63ad4e86f 100644 (file)
@@ -2,7 +2,6 @@
 
 #include <openssl/x509v3.h>
 #include <openssl/pem.h>
-#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;
 }
index 245ec2e2400a28e3547d4b5d2debc3b76fd99339..5fafde390a4d33ad690c5b47bd55f50eefe13363 100644 (file)
@@ -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      \
index b0657abd4ee27e41ecad7deb22665c390bae00eb..fb2b53783809b4935702b382f2783720e113e056 100644 (file)
@@ -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)
index c5d93e33b1d0f6faa0fdffd954bf405d9d2229a3..462e79f35c5092bc00aca22ad49d3deb19dd8094 100644 (file)
@@ -4,6 +4,7 @@
 #include <openssl/asn1.h>
 
 #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;
+}
index e1da52f01dcb700d27824156284a6491f0802506..53c9ba529c1651b0c97bc228d2c8025c1cbb6ac6 100644 (file)
@@ -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_ */
index 7344fc01b0fbc4b13fed4d4a36babd9e004f0b66..830156f459ddc495c57c17dc29530bb4d2738d7c 100644 (file)
@@ -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);