[rs-commit] r100 - in /redwax-tool/trunk: redwax_openssl.c redwax_util.c redwax_util.h

rs-commit at redwax.eu rs-commit at redwax.eu
Wed Dec 1 21:51:36 CET 2021


Author: minfrin at redwax.eu
Date: Wed Dec  1 21:51:35 2021
New Revision: 100

Log:
Add output for some X509v3Extensions.

Modified:
    redwax-tool/trunk/redwax_openssl.c
    redwax-tool/trunk/redwax_util.c
    redwax-tool/trunk/redwax_util.h

Modified: redwax-tool/trunk/redwax_openssl.c
==============================================================================
--- redwax-tool/trunk/redwax_openssl.c	(original)
+++ redwax-tool/trunk/redwax_openssl.c	Wed Dec  1 21:51:35 2021
@@ -2513,7 +2513,7 @@
             cn = X509_NAME_ENTRY_get_data(e);
 
             if ((lbio = BIO_new(BIO_s_mem())) == NULL) {
-                return 0;
+                return APR_ENOMEM;
             }
 
             ASN1_STRING_print_ex(lbio, cn, ASN1_STRFLGS_ESC_2253 |
@@ -2569,8 +2569,8 @@
 
     redwax_metadata_push_object(m, "SubjectPublicKeyInfo", 0);
 
-    if ((bio = BIO_new(BIO_s_mem())) == NULL) {
-        return 0;
+    if (!(bio = BIO_new(BIO_s_mem()))) {
+        return APR_ENOMEM;
     }
 
     i2a_ASN1_OBJECT(bio, xpoid);
@@ -2594,25 +2594,471 @@
     return APR_SUCCESS;
 }
 
-static apr_status_t redwax_openssl_extensions_metadata(redwax_tool_t *r,
-        redwax_metadata_t *m, const STACK_OF(X509_EXTENSION) *xe)
-{
-
-    return APR_ENOTIMPL;
-}
-
-static apr_status_t redwax_openssl_signature_metadata(redwax_tool_t *r,
-        redwax_metadata_t *m, const X509_ALGOR *sig_alg, const ASN1_BIT_STRING *sig)
-{
+static apr_status_t redwax_openssl_general_name_metadata(redwax_tool_t *r,
+        redwax_metadata_t *m, GENERAL_NAME *gen)
+{
+    BIO *bio;
+
+    const char *key = NULL;
+    const char *okey = NULL;
+
+    if (!(bio = BIO_new(BIO_s_mem()))) {
+        return APR_ENOMEM;
+    }
+
+    switch (gen->type) {
+    case GEN_OTHERNAME: {
+
+        int nid;
+
+        nid = OBJ_obj2nid(gen->d.otherName->type_id);
+
+        if ((nid == NID_SRVName
+             && gen->d.otherName->value->type != V_ASN1_IA5STRING)
+                || (nid != NID_SRVName
+                    && gen->d.otherName->value->type != V_ASN1_UTF8STRING)) {
+
+            redwax_print_error(r, "metadata-out: unsupported othername with nid %d, ignoring\n",
+                    nid);
+
+            break;
+        }
+
+        switch (nid) {
+        case NID_id_on_SmtpUTF8Mailbox:
+            key = "OtherName";
+            okey = "SmtpUTF8Mailbox";
+            BIO_printf(bio, "%s",
+                       gen->d.otherName->value->value.utf8string->data);
+            break;
+        case NID_XmppAddr:
+            key = "OtherName";
+            okey = "XmppAddr";
+            BIO_printf(bio, "%s",
+                       gen->d.otherName->value->value.utf8string->data);
+            break;
+        case NID_SRVName:
+            key = "OtherName";
+            okey = "SRVName";
+            BIO_printf(bio, "%s",
+                       gen->d.otherName->value->value.ia5string->data);
+            break;
+        case NID_ms_upn:
+            key = "OtherName";
+            okey = "UPN";
+            BIO_printf(bio, "%s",
+                       gen->d.otherName->value->value.utf8string->data);
+            break;
+        case NID_NAIRealm:
+            key = "OtherName";
+            okey = "NAIRealm";
+            BIO_printf(bio, "%s",
+                       gen->d.otherName->value->value.utf8string->data);
+            break;
+        default:
+
+            redwax_print_error(r, "metadata-out: unsupported othername with nid %d, ignoring\n",
+                    nid);
+
+            break;
+        }
+        break;
+    }
+    case GEN_X400: {
+
+        /* X400Name unsupported */
+        redwax_print_error(r, "metadata-out: unsupported X400Name, ignoring\n");
+
+        break;
+    }
+    case GEN_EDIPARTY: {
+
+        /* EdiPartyName unsupported */
+        /* Maybe fix this: it is supported now */
+        redwax_print_error(r, "metadata-out: unsupported EdiPartyName, ignoring\n");
+
+        break;
+    }
+    case GEN_EMAIL: {
+        key = "Email";
+        ASN1_STRING_print(bio, gen->d.ia5);
+        break;
+    }
+    case GEN_DNS: {
+        key = "DNS";
+        ASN1_STRING_print(bio, gen->d.ia5);
+        break;
+    }
+    case GEN_URI: {
+        key = "URI";
+        ASN1_STRING_print(bio, gen->d.ia5);
+        break;
+    }
+    case GEN_DIRNAME: {
+        key = "DirName";
+        X509_NAME_print_ex(bio, gen->d.dirn, 0, XN_FLAG_ONELINE);
+        break;
+    }
+    case GEN_IPADD: {
+
+        unsigned char *p;
+        int i;
+
+        p = gen->d.ip->data;
+        if (gen->d.ip->length == 4) {
+            key = "IPAddress";
+            BIO_printf(bio, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+        }
+        else if (gen->d.ip->length == 16) {
+            key = "IPAddress";
+            for (i = 0; i < 8; i++) {
+                if (i) {
+                    BIO_puts(bio, ":");
+                }
+                BIO_printf(bio, "%X", p[0] << 8 | p[1]);
+                p += 2;
+            }
+        }
+        break;
+    }
+    case GEN_RID: {
+        key = "RegisteredID";
+        i2a_ASN1_OBJECT(bio, gen->d.rid);
+        break;
+    }
+    }
+
+    if (key) {
+
+        char *buf = NULL;
+        int len = 0;
+
+        len = BIO_get_mem_data(bio, &buf);
+
+        if (okey) {
+            redwax_metadata_push_object(m, key, 0);
+            redwax_metadata_add_string(m, okey,
+                    apr_psprintf(m->pool, "%.*s", len, buf));
+            redwax_metadata_pop_object(m);
+        }
+        else {
+            redwax_metadata_add_string(m, key,
+                    apr_psprintf(m->pool, "%.*s", len, buf));
+        }
+    }
+
+    BIO_free(bio);
+
+    return APR_SUCCESS;
+}
+
+static BIT_STRING_BITNAME ns_cert_type_table[] = {
+    {0, "SSL Client", "client"},
+    {1, "SSL Server", "server"},
+    {2, "S/MIME", "email"},
+    {3, "Object Signing", "objsign"},
+    {4, "Unused", "reserved"},
+    {5, "SSL CA", "sslCA"},
+    {6, "S/MIME CA", "emailCA"},
+    {7, "Object Signing CA", "objCA"},
+    {-1, NULL, NULL}
+};
+
+static BIT_STRING_BITNAME key_usage_type_table[] = {
+    {0, "Digital Signature", "digitalSignature"},
+    {1, "Non Repudiation", "nonRepudiation"},
+    {2, "Key Encipherment", "keyEncipherment"},
+    {3, "Data Encipherment", "dataEncipherment"},
+    {4, "Key Agreement", "keyAgreement"},
+    {5, "Certificate Sign", "keyCertSign"},
+    {6, "CRL Sign", "cRLSign"},
+    {7, "Encipher Only", "encipherOnly"},
+    {8, "Decipher Only", "decipherOnly"},
+    {-1, NULL, NULL}
+};
+
+static apr_status_t redwax_openssl_extension_metadata(redwax_tool_t *r,
+        redwax_metadata_t *m, X509_EXTENSION *ex)
+{
+    ASN1_OBJECT *obj;
 
     BIO *bio;
     char *buf = NULL;
     int len = 0;
 
+    int crit, nid;
+
+    obj = X509_EXTENSION_get_object(ex);
+
+    if ((bio = BIO_new(BIO_s_mem())) == NULL) {
+        return APR_ENOMEM;
+    }
+
+    i2a_ASN1_OBJECT(bio, obj);
+
+    len = BIO_get_mem_data(bio, &buf);
+
+    redwax_metadata_push_object(m, apr_pstrip_whitespace(m->pool, buf, len), 0);
+
+    BIO_free(bio);
+
+    crit = X509_EXTENSION_get_critical(ex);
+    if (crit) {
+        redwax_metadata_add_boolean(m, "Critical", 1);
+    }
+
+    nid = OBJ_obj2nid(obj);
+    switch (nid) {
+    case NID_basic_constraints: {
+
+        BASIC_CONSTRAINTS *bs = X509V3_EXT_d2i(ex);
+
+        if (bs) {
+
+            redwax_metadata_add_boolean(m, "CA", bs->ca);
+
+            if (bs->pathlen) {
+                if ((bs->pathlen->type == V_ASN1_NEG_INTEGER) || !bs->ca) {
+                    redwax_metadata_add_boolean(m, "InvalidPathLength", 1);
+                } else {
+                    redwax_metadata_add_long(m, "PathLength",
+                            ASN1_INTEGER_get(bs->pathlen));
+                }
+            }
+
+            BASIC_CONSTRAINTS_free(bs);
+        }
+
+        break;
+    }
+    case NID_key_usage: {
+
+        ASN1_BIT_STRING *usage = X509V3_EXT_d2i(ex);
+        apr_uint32_t ex_kusage;
+
+        int i, usages = 0;
+
+        if (usage->length > 0) {
+            ex_kusage = usage->data[0];
+            if (usage->length > 1)
+                ex_kusage |= usage->data[1] << 8;
+        }
+        else {
+            ex_kusage = 0;
+        }
+
+        for (i = 0; key_usage_type_table[i].lname; i++) {
+            if ((ex_kusage >> i) & 1) {
+                usages++;
+            }
+        }
+
+        if (usages) {
+
+            redwax_metadata_push_array(m, "KeyUsages", 0);
+
+            for (i = 0; key_usage_type_table[i].sname; i++) {
+                if ((ex_kusage >> i) & 1) {
+                    redwax_metadata_add_string(m, "KeyUsage",
+                            key_usage_type_table[i].sname);
+                }
+            }
+
+            redwax_metadata_pop_array(m);
+        }
+
+        ASN1_BIT_STRING_free(usage);
+
+        break;
+    }
+    case NID_ext_key_usage: {
+
+        EXTENDED_KEY_USAGE *eku = X509V3_EXT_d2i(ex);
+
+        int i;
+
+        if (sk_ASN1_OBJECT_num(eku)) {
+
+            redwax_metadata_push_array(m, "ExtendedKeyUsages", 0);
+
+            for (i = 0; i < sk_ASN1_OBJECT_num(eku); i++) {
+
+                char obj_tmp[80];
+                ASN1_OBJECT *obj;
+
+                obj = sk_ASN1_OBJECT_value(eku, i);
+                i2t_ASN1_OBJECT(obj_tmp, sizeof(obj_tmp), obj);
+
+                redwax_metadata_add_string(m, "ExtendedKeyUsage",
+                        key_usage_type_table[i].sname);
+
+            }
+
+            redwax_metadata_pop_array(m);
+        }
+
+        sk_ASN1_OBJECT_pop_free(eku, ASN1_OBJECT_free);
+
+        break;
+    }
+    case NID_netscape_cert_type: {
+
+        ASN1_BIT_STRING *nscert = X509V3_EXT_d2i(ex);
+        apr_uint32_t ex_nscert;
+
+        int i, nscerts = 0;
+
+        if (nscert->length > 0) {
+            ex_nscert = nscert->data[0];
+            if (nscert->length > 1)
+                ex_nscert |= nscert->data[1] << 8;
+        }
+        else {
+            ex_nscert = 0;
+        }
+
+        for (i = 0; ns_cert_type_table[i].lname; i++) {
+            if ((ex_nscert >> i) & 1) {
+                nscerts++;
+            }
+        }
+
+        if (nscerts) {
+
+            redwax_metadata_push_array(m, "CertificateTypes", 0);
+
+            for (i = 0; ns_cert_type_table[i].sname; i++) {
+                if ((ex_nscert >> i) & 1) {
+                    redwax_metadata_add_string(m, "CertificateType",
+                            ns_cert_type_table[i].sname);
+                }
+            }
+
+            redwax_metadata_pop_array(m);
+        }
+
+        ASN1_BIT_STRING_free(nscert);
+
+        break;
+    }
+    case NID_info_access:
+    case NID_sinfo_access: {
+
+        AUTHORITY_INFO_ACCESS *ainfo = X509V3_EXT_d2i(ex);
+
+        int i;
+
+        if (sk_ACCESS_DESCRIPTION_num(ainfo)) {
+
+            redwax_metadata_push_array(m, "Accesses", 0);
+
+            for (i = 0; i < sk_ACCESS_DESCRIPTION_num(ainfo); i++) {
+
+                char objtmp[80];
+                ACCESS_DESCRIPTION *desc;
+
+                desc = sk_ACCESS_DESCRIPTION_value(ainfo, i);
+                i2t_ASN1_OBJECT(objtmp, sizeof(objtmp), desc->method);
+
+                redwax_metadata_push_object(m, "Access", 0);
+                redwax_metadata_push_object(m,
+                        apr_pstrip_whitespace(m->pool, objtmp, strlen(objtmp)),
+                        0);
+
+                redwax_openssl_general_name_metadata(r, m, desc->location);
+
+                redwax_metadata_pop_object(m);
+                redwax_metadata_pop_object(m);
+            }
+
+            redwax_metadata_pop_array(m);
+        }
+
+        AUTHORITY_INFO_ACCESS_free(ainfo);
+
+        break;
+    }
+    case NID_subject_alt_name:
+    case NID_issuer_alt_name:
+    case NID_certificate_issuer: {
+
+        GENERAL_NAMES *gens = X509V3_EXT_d2i(ex);
+
+        int i;
+
+        if (sk_GENERAL_NAME_num(gens)) {
+
+            redwax_metadata_push_array(m, "Names", 0);
+
+            for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
+
+                GENERAL_NAME *gen;
+
+                gen = sk_GENERAL_NAME_value(gens, i);
+
+                redwax_metadata_push_object(m, "Name", 0);
+                redwax_openssl_general_name_metadata(r, m, gen);
+                redwax_metadata_pop_object(m);
+            }
+
+            redwax_metadata_pop_array(m);
+        }
+
+        break;
+    }
+    default:
+
+        /*
+         * Unknown extensions - we print they exist, but print no contents.
+         *
+         * This allows us to fill in contents at a future date without
+         * changing the existing format.
+         */
+
+        break;
+    }
+
+    redwax_metadata_pop_object(m);
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t redwax_openssl_extensions_metadata(redwax_tool_t *r,
+        redwax_metadata_t *m, const STACK_OF(X509_EXTENSION) *exts)
+{
+    int i;
+
+    redwax_metadata_push_object(m, "X509v3Extensions", !sk_X509_EXTENSION_num(exts));
+
+    for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
+
+        X509_EXTENSION *ex;
+
+        ex = sk_X509_EXTENSION_value(exts, i);
+
+        if (ex) {
+            redwax_openssl_extension_metadata(r, m, ex);
+        }
+
+    }
+
+    redwax_metadata_pop_object(m);
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t redwax_openssl_signature_metadata(redwax_tool_t *r,
+        redwax_metadata_t *m, const X509_ALGOR *sig_alg, const ASN1_BIT_STRING *sig)
+{
+
+    BIO *bio;
+    char *buf = NULL;
+    int len = 0;
+
     if (sig_alg) {
 
         if ((bio = BIO_new(BIO_s_mem())) == NULL) {
-            return 0;
+            return APR_ENOMEM;
         }
 
         i2a_ASN1_OBJECT(bio, sig_alg->algorithm);
@@ -2720,7 +3166,7 @@
                 int len = 0;
 
                 if ((bio = BIO_new(BIO_s_mem())) == NULL) {
-                    return 0;
+                    return APR_ENOMEM;
                 }
 
                 ASN1_TIME_print(bio, tm);
@@ -2742,7 +3188,7 @@
                 int len = 0;
 
                 if ((bio = BIO_new(BIO_s_mem())) == NULL) {
-                    return 0;
+                    return APR_ENOMEM;
                 }
 
                 ASN1_TIME_print(bio, tm);

Modified: redwax-tool/trunk/redwax_util.c
==============================================================================
--- redwax-tool/trunk/redwax_util.c	(original)
+++ redwax-tool/trunk/redwax_util.c	Wed Dec  1 21:51:35 2021
@@ -824,6 +824,76 @@
     return NULL;
 }
 
+apr_status_t redwax_strip_whitespace(char *escaped, const char *str,
+        apr_size_t slen, apr_size_t *len)
+{
+    apr_size_t size = 1;
+    int found = 0;
+    const unsigned char *s = (const unsigned char *) str;
+    unsigned char *d = (unsigned char *) escaped;
+    unsigned c;
+
+    if (slen == REDWAX_ESCAPE_STRING) {
+        slen = strlen(str);
+    }
+
+    if (s) {
+        if (d) {
+            while ((c = *s) && slen) {
+                if (apr_isspace(c)) {
+                    found = 1;
+                }
+                else {
+                    *d++ = c;
+                    size++;
+                }
+                ++s;
+                slen--;
+            }
+            *d = '\0';
+        }
+        else {
+            while ((c = *s) && slen) {
+                if (apr_isspace(c)) {
+                    found = 1;
+                }
+                else {
+                    size++;
+                }
+                ++s;
+                slen--;
+            }
+        }
+    }
+
+    if (len) {
+        *len = size;
+    }
+    if (!found) {
+        return APR_NOTFOUND;
+    }
+
+    return APR_SUCCESS;
+}
+
+const char* apr_pstrip_whitespace(apr_pool_t *p, const char *str, apr_size_t slen)
+{
+    apr_size_t len;
+
+    switch (redwax_strip_whitespace(NULL, str, slen, &len)) {
+    case APR_SUCCESS: {
+        char *cmd = apr_palloc(p, len);
+        redwax_strip_whitespace(cmd, str, slen, NULL);
+        return cmd;
+    }
+    case APR_NOTFOUND: {
+        break;
+    }
+    }
+
+    return str;
+}
+
 #define XML_PREAMBLE "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
 
 static apr_status_t cleanup_metadata(void *dummy)
@@ -1647,3 +1717,126 @@
 
     return APR_SUCCESS;
 }
+
+apr_status_t redwax_metadata_add_number(redwax_metadata_t *m, const char *key,
+        void *v, apr_size_t vlen)
+{
+    redwax_metadata_level_t *ml = m->level;
+
+    apr_status_t status = APR_SUCCESS;
+
+    void *k = (void *)key;
+    int klen = k ? strlen(k) : 0;
+
+    int array = ml->array;
+    int object = ml->object;
+    int next = ml->next;
+
+    ml->next = 1;
+
+    redwax_metadata_prefix(m, 1);
+
+    switch (m->format) {
+    case REDWAX_FORMAT_TEXT:
+        break;
+    case REDWAX_FORMAT_XML: {
+
+        const struct iovec vec[] = {
+                {"\n", 1},
+                {m->object_prefix, m->prefix_len},
+                {"<", 1},
+                {k, klen},
+                {">", 1},
+                {v, vlen},
+                {"</", 2},
+                {k, klen},
+                {">", 1},
+        };
+
+        status = m->wv(m->ctx, vec, 9);
+
+        break;
+    }
+    case REDWAX_FORMAT_JSON: {
+
+        if (object) {
+
+            const struct iovec vec[] = {
+                    {next ? "," : "", next ? 1 : 0},
+                    {"\n", 1},
+                    {m->object_prefix, m->prefix_len},
+                    {"\"", 1},
+                    {k, klen},
+                    {"\": ", 3},
+                    {v, vlen}
+            };
+
+            status = m->wv(m->ctx, vec, 7);
+        }
+
+        else if (array) {
+
+            const struct iovec vec[] = {
+                    {next ? "," : "", next ? 1 : 0},
+                    {"\n", 1},
+                    {m->object_prefix, m->prefix_len},
+                    {v, vlen}
+            };
+
+            status = m->wv(m->ctx, vec, 4);
+        }
+
+        break;
+    }
+    case REDWAX_FORMAT_YAML: {
+
+        if (object) {
+
+            const struct iovec vec[] = {
+                    {"\n", 1},
+                    {m->object_prefix, m->prefix_len},
+                    {k, klen},
+                    {": ", 2},
+                    {v, vlen}
+            };
+
+            status = m->wv(m->ctx, vec, 5);
+        }
+
+        else if (array) {
+
+            const struct iovec vec[] = {
+                    {"\n", 1},
+                    {m->array_prefix, m->prefix_len},
+                    {v, vlen}
+            };
+
+            status = m->wv(m->ctx, vec, 3);
+        }
+
+        break;
+    }
+    default:
+        break;
+    }
+
+    redwax_metadata_prefix(m, -1);
+
+    return APR_SUCCESS;
+}
+
+apr_status_t redwax_metadata_add_long(redwax_metadata_t *m, const char *key, long val)
+{
+    void *v = apr_itoa(m->pool, val);
+    int vlen = v ? strlen(v) : 0;
+
+    return redwax_metadata_add_number(m, key, v, vlen);
+}
+
+apr_status_t redwax_metadata_add_boolean(redwax_metadata_t *m, const char *key, int val)
+{
+    void *v = val ? "true" : "false";
+    int vlen = v ? strlen(v) : 0;
+
+    return redwax_metadata_add_number(m, key, v, vlen);
+}

Modified: redwax-tool/trunk/redwax_util.h
==============================================================================
--- redwax-tool/trunk/redwax_util.h	(original)
+++ redwax-tool/trunk/redwax_util.h	Wed Dec  1 21:51:35 2021
@@ -63,6 +63,11 @@
 const char* redwax_pencode_base16_binary(apr_pool_t *p,
         const unsigned char *src, apr_ssize_t slen, int flags, apr_size_t *len);
 
+apr_status_t redwax_strip_whitespace(char *escaped, const char *str,
+        apr_size_t slen, apr_size_t *len);
+
+const char* apr_pstrip_whitespace(apr_pool_t *p, const char *str, apr_size_t slen);
+
 #define REDWAX_ESCAPE_STRING -1
 
 /**
@@ -125,4 +130,11 @@
 
 apr_status_t redwax_metadata_add_string(redwax_metadata_t *m, const char *k, const char *v);
 
+apr_status_t redwax_metadata_add_number(redwax_metadata_t *m, const char *key,
+        void *v, apr_size_t vlen);
+
+apr_status_t redwax_metadata_add_long(redwax_metadata_t *m, const char *key, long val);
+
+apr_status_t redwax_metadata_add_boolean(redwax_metadata_t *m, const char *key, int val);
+
 #endif



More information about the rs-commit mailing list