[rt-commit] r145 - in /redwax-tool/trunk: ChangeLog redwax-tool.c redwax-tool.h redwax_openssl.c

rt-commit at redwax.eu rt-commit at redwax.eu
Wed Jul 19 00:23:26 CEST 2023


Author: minfrin at redwax.eu
Date: Wed Jul 19 00:23:25 2023
New Revision: 145

Log:
Add --order-out parameter to control the order of
certificates, intermediates, roots and keys that are
written by the --pem-out option.

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

Modified: redwax-tool/trunk/ChangeLog
==============================================================================
--- redwax-tool/trunk/ChangeLog	(original)
+++ redwax-tool/trunk/ChangeLog	Wed Jul 19 00:23:25 2023
@@ -1,5 +1,9 @@
 
 Changes with v0.9.3
+
+ *) Add --order-out parameter to control the order of
+    certificates, intermediates, roots and keys that are
+    written by the --pem-out option. [Graham Leggett]
 
  *) Add --parameter-out and --no-parameter-out to include
     parameters with private keys. [Graham Leggett]

Modified: redwax-tool/trunk/redwax-tool.c
==============================================================================
--- redwax-tool/trunk/redwax-tool.c	(original)
+++ redwax-tool/trunk/redwax-tool.c	Wed Jul 19 00:23:25 2023
@@ -77,6 +77,8 @@
         APR_HOOK_LINK(complete_format_out);
         APR_HOOK_LINK(process_jwks_out);
         APR_HOOK_LINK(set_format_out);
+        APR_HOOK_LINK(complete_order_out);
+        APR_HOOK_LINK(set_order_out);
         APR_HOOK_LINK(search_chain);
         APR_HOOK_LINK(search_key);
         APR_HOOK_LINK(compare_certificate);
@@ -133,6 +135,10 @@
         (redwax_tool_t * r, const char *arg), (r, arg), DECLINED);
 APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, complete_format_out,
         (redwax_tool_t * r, apr_hash_t *formats), (r, formats), DECLINED);
+APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, set_order_out,
+        (redwax_tool_t * r, const char *arg), (r, arg), DECLINED);
+APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, complete_order_out,
+        (redwax_tool_t * r, apr_hash_t *orders), (r, orders), DECLINED);
 APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, process_jwks_out,
         (redwax_tool_t * r, const char *arg), (r, arg), DECLINED);
 APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, apr_status_t, search_chain,
@@ -208,6 +214,7 @@
 #define REDWAX_TOOL_USER_OUT 307
 #define REDWAX_TOOL_GROUP_IN 308
 #define REDWAX_TOOL_GROUP_OUT 309
+#define REDWAX_TOOL_ORDER_OUT 310
 
 #define REDWAX_EXIT_OK 0
 #define REDWAX_EXIT_INIT 1
@@ -298,7 +305,8 @@
     { "user-in", REDWAX_TOOL_USER_IN, 1, "  --user-in=user\t\tUse the privileges of this user when reading\n\t\t\t\tcertificates and keys." },
     { "user-out", REDWAX_TOOL_USER_OUT, 1, "  --user-out=user\t\tUse the privileges of this user when writing\n\t\t\t\tcertificates and keys." },
     { "group-in", REDWAX_TOOL_GROUP_IN, 1, "  --group-in=group\t\tUse the privileges of this group when reading\n\t\t\t\tcertificates and keys. If you have set a user\n\t\t\t\tbefore setting a group, you may no longer have\n\t\t\t\tpermission to set the group. It is recommended\n\t\t\t\tthat if user and group are set, the group is set\n\t\t\t\tfirst." },
-    { "group-out", REDWAX_TOOL_GROUP_OUT, 1, "  --group-out=group\t\tUse the privileges of this group when writing\n\t\t\t\tcertificates and keys. If you have set a user\n\t\t\t\tbefore setting a group, you may no longer have\n\t\t\t\tpermission to set the group. It is recommended\n\t\t\t\tthat if user and group are set, the group is set\n\t\t\t\tfirst." },
+    { "group-out", REDWAX_TOOL_GROUP_OUT, 1, "  --group-out=group\t\t\tUse the privileges of this group when writing\n\t\t\t\t\tcertificates and keys. If you have set a user\n\t\t\t\t\tbefore setting a group, you may no longer have\n\t\t\t\t\tpermission to set the group. It is recommended\n\t\t\t\t\tthat if user and group are set, the group is set\n\t\t\t\t\tfirst." },
+    { "order-out", REDWAX_TOOL_ORDER_OUT, 1, "  --order-out=[all|key-first|key-last]\tControls the order of keys and certificates in\n\t\t\t\t\tthe output. 'all' outputs all leaf certificates,\n\t\t\t\t\tfollowed by all intermediate certificates,\n\t\t\t\t\tfollowed by all root certificates, followed by\n\t\t\t\t\tall keys. 'key-first' outputs all certificates\n\t\t\t\t\twith a matching private key, with the private\n\t\t\t\t\tkey first, followed by the certificate, followed\n\t\t\t\t\tby intermediates and roots, followed by the\n\t\t\t\t\tprivate key of the next certificate and so on.\n\t\t\t\t\t'key-last' outputs all certificates with a\n\t\t\t\t\tmatching private key, with the certificate first,\n\t\t\t\t\tfollowed by intermediates and roots, followed by\n\t\t\t\t\tthe key of the certificate, finally followed by\n\t\t\t\t\tthe next certificate with a private key and so on." },
     { "ssh-public-out", REDWAX_TOOL_SSH_PUBLIC_OUT, 1, "  --ssh-public-out=file\t\tWrite an SSH public key to the given file." },
 #if 0
     { "jwks-out", REDWAX_TOOL_JWKS_OUT, 1, "  --jwks-out=file\t\tWrite keys to the given file as an RFC7517 JSON\n\t\t\t\tWeb Key Set." },
@@ -1769,6 +1777,31 @@
     return APR_SUCCESS;
 }
 
+static apr_status_t redwax_complete_order_out(redwax_tool_t *r, const char *arg,
+        redwax_token_quoted_e quoted)
+{
+    apr_hash_t *orders = apr_hash_make(r->pool);
+
+    apr_hash_index_t *hi;
+    void *val;
+    int arglen =  strlen(arg);
+
+    rt_run_complete_order_out(r, orders);
+
+    for (hi = apr_hash_first(r->pool, orders); hi; hi = apr_hash_next(hi)) {
+        apr_hash_this(hi, NULL, NULL, &val);
+
+        if (!strncmp(arg, (const char *)val, arglen)) {
+
+            apr_file_printf(r->out, "%s \n",
+                    redwax_pescape_echo_quoted(r->pool,
+                            (const char *)val, quoted, 1));
+        }
+    }
+
+    return APR_SUCCESS;
+}
+
 apr_status_t redwax_file_out(redwax_tool_t *r, const char *path,
         apr_status_t (out)(redwax_tool_t *r, const char *path, const char *secret))
 {
@@ -2284,6 +2317,14 @@
     return status;
 }
 
+static apr_status_t redwax_order_out(redwax_tool_t *r, const char *arg)
+{
+
+    apr_status_t status = rt_run_set_order_out(r, arg);
+
+    return status;
+}
+
 static apr_status_t redwax_jwks_out(redwax_tool_t *r, const char *arg)
 {
     arg = redwax_home(r, arg);
@@ -2599,6 +2640,12 @@
         }
         case REDWAX_TOOL_FORMAT_OUT: {
             redwax_format_out(r, optarg);
+            break;
+        }
+        case REDWAX_TOOL_ORDER_OUT: {
+            if (redwax_order_out(r, optarg)) {
+                return REDWAX_EXIT_OPTIONS;
+            }
             break;
         }
         case REDWAX_TOOL_JWKS_OUT: {
@@ -2808,6 +2855,10 @@
                 redwax_complete_group(r, optarg, state.isquoted);
                 break;
             }
+            case REDWAX_TOOL_ORDER_OUT: {
+                redwax_complete_order_out(r, optarg, state.isquoted);
+                break;
+            }
             }
 
         }
@@ -2998,6 +3049,10 @@
         }
         case REDWAX_TOOL_GROUP_OUT: {
             redwax_complete_group(r, "", state.isquoted);
+            break;
+        }
+        case REDWAX_TOOL_ORDER_OUT: {
+            redwax_complete_order_out(r, "", state.isquoted);
             break;
         }
         }

Modified: redwax-tool/trunk/redwax-tool.h
==============================================================================
--- redwax-tool/trunk/redwax-tool.h	(original)
+++ redwax-tool/trunk/redwax-tool.h	Wed Jul 19 00:23:25 2023
@@ -52,6 +52,12 @@
     REDWAX_FORMAT_JSON,
     REDWAX_FORMAT_YAML,
 } redwax_format_e;
+
+typedef enum redwax_order_e {
+	REDWAX_ORDER_ALL = 0,
+	REDWAX_ORDER_KEY_FIRST,
+	REDWAX_ORDER_KEY_LAST,
+} redwax_order_e;
 
 typedef struct redwax_tool_t {
     apr_pool_t *pool;
@@ -81,6 +87,7 @@
     apr_hash_t *ips_index;
     apr_hash_t *keys_index;
     apr_hash_t *duplicates_index;
+    apr_hash_t *cert_relationships;
     const char *verify_param;
     const char *secret_suffix_in;
     const char *secret_suffix_out;
@@ -97,6 +104,7 @@
     redwax_pkcs11_t pkcs11_out;
     apr_time_t *now;
     redwax_format_e format;
+    redwax_order_e order;
     int current;
     int cert_out;
     int chain_out;
@@ -554,6 +562,22 @@
         (redwax_tool_t *r, const char *arg));
 
 /**
+ * Hook to complete the output order.
+ *
+ * @param r The redwax-tool context.
+ */
+APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, complete_order_out,
+        (redwax_tool_t *r, apr_hash_t *orders));
+
+/**
+ * Hook to set the output order.
+ *
+ * @param r The redwax-tool context.
+ */
+APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, set_order_out,
+        (redwax_tool_t *r, const char *arg));
+
+/**
  * Hook to handle the output of JWK sets.
  *
  * @param r The redwax-tool context.

Modified: redwax-tool/trunk/redwax_openssl.c
==============================================================================
--- redwax-tool/trunk/redwax_openssl.c	(original)
+++ redwax-tool/trunk/redwax_openssl.c	Wed Jul 19 00:23:25 2023
@@ -50,6 +50,10 @@
 
 #define REDWAX_OPENSSL_SEARCH "search"
 #define REDWAX_OPENSSL_VERIFY "verify"
+
+#define REDWAX_ORDER_ALL_TEXT "all"
+#define REDWAX_ORDER_KEY_FIRST_TEXT "key-first"
+#define REDWAX_ORDER_KEY_LAST_TEXT "key-last"
 
 #define REDWAX_PKCS12_MIN 8
 #define REDWAX_PKCS12_MAX HUGE_STRING_LEN
@@ -2057,7 +2061,7 @@
     return APR_SUCCESS;
 }
 
-static apr_status_t redwax_openssl_process_pem_out(redwax_tool_t *r,
+static apr_status_t redwax_openssl_process_pem_out_all(redwax_tool_t *r,
         const char *file, const char *secret)
 {
 
@@ -2090,21 +2094,21 @@
 
             const unsigned char *der = cert->der;
 
-             X509 *x = d2i_X509(NULL, &der, cert->len);
-
-             if (x) {
-
-                 redwax_print_error(r, "pem-out: certificate: %s\n",
-                         redwax_openssl_name(r->pool, X509_get_subject_name(x)));
-
-                 if ((r->text && !X509_print_ex(bio, x, 0, 0)) ||
+            X509 *x = d2i_X509(NULL, &der, cert->len);
+
+            if (x) {
+
+                redwax_print_error(r, "pem-out: certificate: %s\n",
+                        redwax_openssl_name(r->pool, X509_get_subject_name(x)));
+
+                if ((r->text && !X509_print_ex(bio, x, 0, 0)) ||
                          !PEM_write_bio_X509(bio, x)) {
-                     redwax_openssl_print_errors(r);
-                     X509_free(x);
-                     return APR_ENOENT;
-                 }
-                 X509_free(x);
-             }
+                    redwax_openssl_print_errors(r);
+                    X509_free(x);
+                    return APR_ENOENT;
+                }
+                X509_free(x);
+            }
 
         }
     }
@@ -2249,6 +2253,269 @@
     }
 
     return APR_SUCCESS;
+}
+
+static apr_status_t process_pem_out_key(redwax_tool_t *r,
+        BIO *bio, const redwax_key_t *key)
+{
+    BIO *kbio;
+    PKCS8_PRIV_KEY_INFO *p8inf;
+    EVP_PKEY *pkey;
+
+    if (!key->der) {
+        redwax_print_error(r, "pem-out: non-extractable private key, skipping\n");
+        return APR_SUCCESS;
+    }
+
+    if ((kbio = BIO_new_mem_buf(key->der, key->len)) == NULL) {
+        return APR_ENOMEM;
+    }
+
+    apr_pool_cleanup_register(r->pool, kbio, cleanup_bio,
+            apr_pool_cleanup_null);
+
+    if (!(p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(kbio, NULL)) ||
+            !(pkey = EVP_PKCS82PKEY(p8inf))) {
+
+        redwax_openssl_print_errors(r);
+        return APR_ENOENT;
+    }
+
+#if HAVE_EVP_PKEY_GET0_DESCRIPTION
+    redwax_print_error(r, "pem-out: private key: %s\n",
+            EVP_PKEY_get0_description(pkey));
+#else
+    redwax_print_error(r, "pem-out: private key\n");
+#endif
+
+    if ((r->text && !EVP_PKEY_print_private(bio, pkey, 0, NULL)) ||
+        (r->param_out && !PEM_write_bio_Parameters(bio, pkey)) ||
+            !PEM_write_bio_PKCS8_PRIV_KEY_INFO(bio, p8inf)) {
+
+        redwax_openssl_print_errors(r);
+        return APR_ENOENT;
+    }
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t process_pem_out_chain(redwax_tool_t *r,
+        BIO *bio, const redwax_certificate_t *cert, const char *type)
+{
+    apr_status_t status;
+    int i;
+
+    const unsigned char *der;
+    X509 *x, *xi;
+
+    der = cert->der;
+
+    x = d2i_X509(NULL, &der, cert->len);
+
+    if (x) {
+
+        redwax_print_error(r, "pem-out: %s: %s\n", type,
+                redwax_openssl_name(r->pool, X509_get_subject_name(x)));
+
+        if ((r->text && !X509_print_ex(bio, x, 0, 0)) ||
+                 !PEM_write_bio_X509(bio, x)) {
+            redwax_openssl_print_errors(r);
+            X509_free(x);
+            return APR_ENOENT;
+        }
+
+        if (!X509_NAME_cmp(X509_get_issuer_name(x),
+                X509_get_subject_name(x))) {
+
+            /* self signed - end of chain */
+            return APR_SUCCESS;
+        }
+
+        if (r->chain_out) {
+            for (i = 0; i < r->intermediates_out->nelts; i++)
+            {
+                const redwax_certificate_t *intermediate = &APR_ARRAY_IDX(r->intermediates_out, i, const redwax_certificate_t);
+
+                const unsigned char *der = intermediate->der;
+
+                xi = d2i_X509(NULL, &der, intermediate->len);
+
+                if (xi) {
+
+                    if (X509_check_issued(xi, x) == X509_V_OK) {
+
+                        status = process_pem_out_chain(r, bio, intermediate, "intermediate");
+                        if (APR_SUCCESS != status) {
+                            return status;
+                        }
+
+                    }
+
+                    X509_free(xi);
+                }
+
+            }
+        }
+
+        if (r->root_out || r->trust_out) {
+            for (i = 0; i < r->trusted_out->nelts; i++)
+            {
+                const redwax_certificate_t *trusted = &APR_ARRAY_IDX(r->trusted_out, i, const redwax_certificate_t);
+
+                const unsigned char *der = trusted->der;
+
+                xi = d2i_X509_AUX(NULL, &der, cert->len);
+
+                if (xi) {
+
+                    if (X509_check_issued(xi, x) == X509_V_OK) {
+
+                        status = process_pem_out_chain(r, bio, trusted, "trusted");
+                        if (APR_SUCCESS != status) {
+                            return status;
+                        }
+
+                    }
+
+                    X509_free(xi);
+                }
+
+            }
+        }
+
+        // todo loop chain
+        X509_free(x);
+    }
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t process_pem_out_certificate(redwax_tool_t *r,
+        BIO *bio, const redwax_certificate_t *cert, const char *type, int last)
+{
+    apr_status_t status;
+
+    redwax_key_t *key = apr_hash_get(r->keys_index,
+            cert->common.subjectpublickeyinfo_der,
+            cert->common.subjectpublickeyinfo_len);
+
+    if (!key) {
+        /* ignore all certs without keys */
+        return APR_SUCCESS;
+    }
+
+    if (!last && r->key_out) {
+        status = process_pem_out_key(r, bio, key);
+        if (APR_SUCCESS != status) {
+            return status;
+        }
+    }
+
+    status = process_pem_out_chain(r, bio, cert, type);
+    if (APR_SUCCESS != status) {
+        return status;
+    }
+
+    if (last && r->key_out) {
+        status = process_pem_out_key(r, bio, key);
+        if (APR_SUCCESS != status) {
+            return status;
+        }
+    }
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t redwax_openssl_process_pem_out_key(redwax_tool_t *r,
+        const char *file, const char *secret, int last)
+{
+
+    BIO *bio;
+    apr_status_t status;
+    int i;
+
+    if (!strcmp(file, "-")) {
+        if ((bio = BIO_new_fp(stdout, BIO_NOCLOSE)) == NULL) {
+            redwax_openssl_print_errors(r);
+            return APR_ENOMEM;
+        }
+    }
+    else if ((bio = BIO_new(BIO_s_file())) == NULL) {
+        redwax_openssl_print_errors(r);
+        return APR_ENOMEM;
+    }
+    else if (BIO_write_filename(bio, (char *)file) <= 0) {
+        redwax_openssl_print_errors(r);
+        BIO_free(bio);
+        return APR_ENOENT;
+    }
+
+    apr_pool_cleanup_register(r->pool, bio, cleanup_bio,
+            apr_pool_cleanup_null);
+
+    if (r->cert_out) {
+        for (i = 0; i < r->certs_out->nelts; i++)
+        {
+            const redwax_certificate_t *cert = &APR_ARRAY_IDX(r->certs_out, i, const redwax_certificate_t);
+
+            status = process_pem_out_certificate(r, bio, cert, "certificate", last);
+            if (APR_SUCCESS != status) {
+                return status;
+            }
+
+        }
+    }
+
+    if (r->chain_out) {
+        for (i = 0; i < r->intermediates_out->nelts; i++)
+        {
+            const redwax_certificate_t *cert = &APR_ARRAY_IDX(r->intermediates_out, i, const redwax_certificate_t);
+
+            status = process_pem_out_certificate(r, bio, cert, "intermediate", last);
+            if (APR_SUCCESS != status) {
+                return status;
+            }
+
+        }
+    }
+
+    if (r->root_out || r->trust_out) {
+        for (i = 0; i < r->trusted_out->nelts; i++)
+        {
+            const redwax_certificate_t *cert = &APR_ARRAY_IDX(r->trusted_out, i, const redwax_certificate_t);
+
+            status = process_pem_out_certificate(r, bio, cert, "trusted", last);
+            if (APR_SUCCESS != status) {
+                return status;
+            }
+
+        }
+    }
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t redwax_openssl_process_pem_out(redwax_tool_t *r,
+        const char *file, const char *secret)
+{
+
+    switch (r->order) {
+    case REDWAX_ORDER_ALL:
+
+        return redwax_openssl_process_pem_out_all(r, file, secret);
+
+    case REDWAX_ORDER_KEY_FIRST:
+
+        return redwax_openssl_process_pem_out_key(r, file, secret, 0);
+
+    case REDWAX_ORDER_KEY_LAST:
+
+        return redwax_openssl_process_pem_out_key(r, file, secret, 1);
+
+    default:
+        return DECLINED;
+    }
+
 }
 
 static const char *read_secret(redwax_tool_t *r, const char *what, const char *file,
@@ -2999,30 +3266,30 @@
 }
 
 static void redwax_openssl_ssh_bignum(BIO *bio,
-		unsigned char *buf, apr_size_t len)
-{
-	apr_size_t padded_len = len;
-	unsigned char c;
-
-	if (buf[0] & 0x80) {
-		padded_len++;
-	}
-
-	c = padded_len >> 24;
-	BIO_write(bio, &c, 1);
-	c = padded_len >> 16;
-	BIO_write(bio, &c, 1);
-	c = padded_len >> 8;
-	BIO_write(bio, &c, 1);
-	c = padded_len;
-	BIO_write(bio, &c, 1);
-
-	if (buf[0] & 0x80) {
-		c = 0;
-		BIO_write(bio, &c, 1);
-	}
-
-	BIO_write(bio, buf, len);
+        unsigned char *buf, apr_size_t len)
+{
+    apr_size_t padded_len = len;
+    unsigned char c;
+
+    if (buf[0] & 0x80) {
+        padded_len++;
+    }
+
+    c = padded_len >> 24;
+    BIO_write(bio, &c, 1);
+    c = padded_len >> 16;
+    BIO_write(bio, &c, 1);
+    c = padded_len >> 8;
+    BIO_write(bio, &c, 1);
+    c = padded_len;
+    BIO_write(bio, &c, 1);
+
+    if (buf[0] & 0x80) {
+        c = 0;
+        BIO_write(bio, &c, 1);
+    }
+
+    BIO_write(bio, buf, len);
 }
 
 static apr_status_t redwax_openssl_process_ssh_public_out(redwax_tool_t *r,
@@ -3060,38 +3327,38 @@
             switch (key->common.type) {
             case REDWAX_KEY_RSA: {
 
-            	static unsigned char sshHeader[11] = { 0x00, 0x00, 0x00, 0x07, 's', 's', 'h', '-', 'r', 's', 'a'};
-
-            	if (!key->rsa) {
+                static unsigned char sshHeader[11] = { 0x00, 0x00, 0x00, 0x07, 's', 's', 'h', '-', 'r', 's', 'a'};
+
+                if (!key->rsa) {
                     redwax_print_error(r, "ssh-public-out: no rsa components, skipping\n");
                     break;
                 }
 
-            	b64 = BIO_new(BIO_f_base64());
-            	BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
-            	BIO_printf(bio, "ssh-rsa ");
-            	bio = BIO_push(b64, bio);
-
-            	BIO_write(bio, sshHeader, sizeof(sshHeader));
-
-            	redwax_openssl_ssh_bignum(bio, key->rsa->public_exponent, key->rsa->public_exponent_len);
-            	redwax_openssl_ssh_bignum(bio, key->rsa->modulus, key->rsa->modulus_len);
-
-            	BIO_flush(bio);
-            	bio = BIO_pop(b64);
-            	BIO_printf(bio, " %s\n", "label");
-            	BIO_flush(bio);
-            	BIO_free(b64);
+                b64 = BIO_new(BIO_f_base64());
+                BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
+                BIO_printf(bio, "ssh-rsa ");
+                bio = BIO_push(b64, bio);
+
+                BIO_write(bio, sshHeader, sizeof(sshHeader));
+
+                redwax_openssl_ssh_bignum(bio, key->rsa->public_exponent, key->rsa->public_exponent_len);
+                redwax_openssl_ssh_bignum(bio, key->rsa->modulus, key->rsa->modulus_len);
+
+                BIO_flush(bio);
+                bio = BIO_pop(b64);
+                BIO_printf(bio, " %s\n", "label");
+                BIO_flush(bio);
+                BIO_free(b64);
 
                 redwax_print_error(r, "ssh-public-out: private key\n");
 
-            	break;
+                break;
             }
             default: {
 
                 redwax_print_error(r, "ssh-public-out: unsupported key, skipping\n");
 
-            	break;
+                break;
             }
             }
 
@@ -4344,14 +4611,14 @@
 
         redwax_metadata_push_array(m, "Trusts", !r->trusted_out->nelts);
 
-    	for (i = 0; i < r->trusted_out->nelts; i++)
+        for (i = 0; i < r->trusted_out->nelts; i++)
         {
             const redwax_certificate_t *cert = &APR_ARRAY_IDX(r->trusted_out, i, const redwax_certificate_t);
 
             redwax_openssl_cert_metadata(r, m, cert);
         }
 
-    	redwax_metadata_pop_array(m);
+        redwax_metadata_pop_array(m);
     }
 
     if (r->key_out) {
@@ -4398,6 +4665,39 @@
 
     if (!strcmp(arg, "yaml")) {
         r->format = REDWAX_FORMAT_YAML;
+        return APR_SUCCESS;
+    }
+
+    return DECLINED;
+}
+
+apr_status_t redwax_openssl_complete_order_out(redwax_tool_t *r,
+        apr_hash_t *orders)
+{
+    apr_hash_set(orders, REDWAX_ORDER_ALL_TEXT,
+            strlen(REDWAX_ORDER_ALL_TEXT), REDWAX_ORDER_ALL_TEXT);
+    apr_hash_set(orders, REDWAX_ORDER_KEY_FIRST_TEXT,
+            strlen(REDWAX_ORDER_KEY_FIRST_TEXT), REDWAX_ORDER_KEY_FIRST_TEXT);
+    apr_hash_set(orders, REDWAX_ORDER_KEY_LAST_TEXT,
+            strlen(REDWAX_ORDER_KEY_LAST_TEXT), REDWAX_ORDER_KEY_LAST_TEXT);
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t redwax_openssl_set_order_out(redwax_tool_t *r, const char *arg)
+{
+    if (!strcmp(arg, REDWAX_ORDER_ALL_TEXT)) {
+        r->order = REDWAX_ORDER_ALL;
+        return APR_SUCCESS;
+    }
+
+    if (!strcmp(arg, REDWAX_ORDER_KEY_FIRST_TEXT)) {
+        r->order = REDWAX_ORDER_KEY_FIRST;
+        return APR_SUCCESS;
+    }
+
+    if (!strcmp(arg, REDWAX_ORDER_KEY_LAST_TEXT)) {
+        r->order = REDWAX_ORDER_KEY_LAST;
         return APR_SUCCESS;
     }
 
@@ -5289,6 +5589,8 @@
     rt_hook_process_metadata_out(redwax_openssl_process_metadata_out, NULL, NULL, APR_HOOK_MIDDLE);
     rt_hook_complete_format_out(redwax_openssl_complete_format_out, NULL, NULL, APR_HOOK_MIDDLE);
     rt_hook_set_format_out(redwax_openssl_set_format_out, NULL, NULL, APR_HOOK_MIDDLE);
+    rt_hook_complete_order_out(redwax_openssl_complete_order_out, NULL, NULL, APR_HOOK_MIDDLE);
+    rt_hook_set_order_out(redwax_openssl_set_order_out, NULL, NULL, APR_HOOK_MIDDLE);
     rt_hook_process_jwks_out(redwax_openssl_process_jwks_out, NULL, NULL, APR_HOOK_MIDDLE);
     rt_hook_search_chain(redwax_openssl_search_chain, NULL, NULL, APR_HOOK_MIDDLE);
     rt_hook_search_key(redwax_openssl_search_key, NULL, NULL, APR_HOOK_MIDDLE);



More information about the rt-commit mailing list