From 1d192a13b91092ed9f0db12b803bb4d2648606f7 Mon Sep 17 00:00:00 2001
From: degroens <degroens@yahoo.com>
Date: Wed, 1 Jan 2020 18:42:08 -0500
Subject: [PATCH] Adds support for generating RFC2253 DNs using configuration
 variables by invoking OpenSSL library features.

---
 src/ssl_sock.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 134 insertions(+)

diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index e4dd913..cbefc8f 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -7696,6 +7696,136 @@ out:
 	return ret;
 }
 
+/*
+* string, returns a string of a formatted full dn in rfc 2253 format of certificate's issuer
+* The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
+        * should be use.
+*/
+static int
+smp_fetch_ssl_x_i_dn_rfc2253(const struct arg *args, struct sample *smp, const char *kw, void *private)
+{
+    int cert_peer = (kw[4] == 'c') ? 1 : 0;
+    X509 *crt = NULL;
+    X509_NAME *name;
+    BIO *bio = NULL;
+    int ret = 0;
+    struct connection *conn;
+    struct ssl_sock_ctx *ctx;
+    struct buffer *smp_trash;
+
+    conn = objt_conn(smp->sess->origin);
+    if (!conn || conn->xprt != &ssl_sock)
+        return 0;
+    ctx = conn->xprt_ctx;
+
+    if (!(conn->flags & CO_FL_CONNECTED)) {
+        smp->flags |= SMP_F_MAY_CHANGE;
+        return 0;
+    }
+
+    if (cert_peer)
+        crt = SSL_get_peer_certificate(ctx->ssl);
+    else
+        crt = SSL_get_certificate(ctx->ssl);
+    if (!crt)
+        goto out;
+
+    name = X509_get_issuer_name(crt);
+    if (!name)
+        goto out;
+
+    bio = BIO_new(BIO_s_mem());
+    if (bio == NULL)
+        goto out;
+
+    if (X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253) < 0)
+        goto out;
+
+    smp_trash = get_trash_chunk();
+
+    if (BIO_read(bio, smp_trash->area, smp_trash->size) < 0)
+        goto out;
+
+    smp->data.type = SMP_T_STR;
+    smp_trash->data = strlen(smp_trash->area);
+    smp->data.u.str = *smp_trash;
+
+    ret = 1;
+
+    out:
+    /* SSL_get_peer_certificate, it increase X509 * ref count */
+    if (cert_peer && crt)
+        X509_free(crt);
+    if (bio)
+        BIO_free(bio);
+    return ret;
+}
+
+/*
+* string, returns a string of a formatted full dn in rfc 2253 format of certificate's subject
+* The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
+        * should be use.
+*/
+static int
+smp_fetch_ssl_x_s_dn_rfc2253(const struct arg *args, struct sample *smp, const char *kw, void *private)
+{
+    int cert_peer = (kw[4] == 'c') ? 1 : 0;
+    X509 *crt = NULL;
+    X509_NAME *name;
+    BIO *bio = NULL;
+    int ret = 0;
+    struct connection *conn;
+    struct ssl_sock_ctx *ctx;
+    struct buffer *smp_trash;
+
+    conn = objt_conn(smp->sess->origin);
+    if (!conn || conn->xprt != &ssl_sock)
+        return 0;
+    ctx = conn->xprt_ctx;
+
+    if (!(conn->flags & CO_FL_CONNECTED)) {
+        smp->flags |= SMP_F_MAY_CHANGE;
+        return 0;
+    }
+
+    if (cert_peer)
+        crt = SSL_get_peer_certificate(ctx->ssl);
+    else
+        crt = SSL_get_certificate(ctx->ssl);
+    if (!crt)
+        goto out;
+
+    name = X509_get_subject_name(crt);
+    if (!name)
+        goto out;
+
+    bio = BIO_new(BIO_s_mem());
+    if (bio == NULL)
+        goto out;
+
+    if (X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253) < 0)
+        goto out;
+
+    smp_trash = get_trash_chunk();
+
+    if (BIO_read(bio, smp_trash->area, smp_trash->size) < 0 )
+        goto out;
+
+    smp->data.type = SMP_T_STR;
+    smp_trash->data = strlen(smp_trash->area);
+    smp->data.u.str = *smp_trash;
+
+    ret = 1;
+
+    out:
+    /* SSL_get_peer_certificate, it increase X509 * ref count */
+    if (cert_peer && crt)
+        X509_free(crt);
+    if (bio)
+        BIO_free(bio);
+    return ret;
+}
+
 /* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
  * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
  * should be use.
@@ -11155,11 +11285,13 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
 	{ "ssl_c_der",              smp_fetch_ssl_x_der,          0,                   NULL,    SMP_T_BIN,  SMP_USE_L5CLI },
 	{ "ssl_c_err",              smp_fetch_ssl_c_err,          0,                   NULL,    SMP_T_SINT, SMP_USE_L5CLI },
 	{ "ssl_c_i_dn",             smp_fetch_ssl_x_i_dn,         ARG2(0,STR,SINT),    NULL,    SMP_T_STR,  SMP_USE_L5CLI },
+    { "ssl_c_i_dn_rfc2253",     smp_fetch_ssl_x_i_dn_rfc2253, 0,                   NULL,    SMP_T_STR,  SMP_USE_L5CLI },
 	{ "ssl_c_key_alg",          smp_fetch_ssl_x_key_alg,      0,                   NULL,    SMP_T_STR,  SMP_USE_L5CLI },
 	{ "ssl_c_notafter",         smp_fetch_ssl_x_notafter,     0,                   NULL,    SMP_T_STR,  SMP_USE_L5CLI },
 	{ "ssl_c_notbefore",        smp_fetch_ssl_x_notbefore,    0,                   NULL,    SMP_T_STR,  SMP_USE_L5CLI },
 	{ "ssl_c_sig_alg",          smp_fetch_ssl_x_sig_alg,      0,                   NULL,    SMP_T_STR,  SMP_USE_L5CLI },
 	{ "ssl_c_s_dn",             smp_fetch_ssl_x_s_dn,         ARG2(0,STR,SINT),    NULL,    SMP_T_STR,  SMP_USE_L5CLI },
+    { "ssl_c_s_dn_rfc2253",     smp_fetch_ssl_x_s_dn_rfc2253, 0,                   NULL,    SMP_T_STR,  SMP_USE_L5CLI },
 	{ "ssl_c_serial",           smp_fetch_ssl_x_serial,       0,                   NULL,    SMP_T_BIN,  SMP_USE_L5CLI },
 	{ "ssl_c_sha1",             smp_fetch_ssl_x_sha1,         0,                   NULL,    SMP_T_BIN,  SMP_USE_L5CLI },
 	{ "ssl_c_used",             smp_fetch_ssl_c_used,         0,                   NULL,    SMP_T_BOOL, SMP_USE_L5CLI },
@@ -11167,11 +11299,13 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
 	{ "ssl_c_version",          smp_fetch_ssl_x_version,      0,                   NULL,    SMP_T_SINT, SMP_USE_L5CLI },
 	{ "ssl_f_der",              smp_fetch_ssl_x_der,          0,                   NULL,    SMP_T_BIN,  SMP_USE_L5CLI },
 	{ "ssl_f_i_dn",             smp_fetch_ssl_x_i_dn,         ARG2(0,STR,SINT),    NULL,    SMP_T_STR,  SMP_USE_L5CLI },
+    { "ssl_f_i_dn_rfc2253",     smp_fetch_ssl_x_i_dn_rfc2253, 0,                   NULL,    SMP_T_STR,  SMP_USE_L5CLI },
 	{ "ssl_f_key_alg",          smp_fetch_ssl_x_key_alg,      0,                   NULL,    SMP_T_STR,  SMP_USE_L5CLI },
 	{ "ssl_f_notafter",         smp_fetch_ssl_x_notafter,     0,                   NULL,    SMP_T_STR,  SMP_USE_L5CLI },
 	{ "ssl_f_notbefore",        smp_fetch_ssl_x_notbefore,    0,                   NULL,    SMP_T_STR,  SMP_USE_L5CLI },
 	{ "ssl_f_sig_alg",          smp_fetch_ssl_x_sig_alg,      0,                   NULL,    SMP_T_STR,  SMP_USE_L5CLI },
 	{ "ssl_f_s_dn",             smp_fetch_ssl_x_s_dn,         ARG2(0,STR,SINT),    NULL,    SMP_T_STR,  SMP_USE_L5CLI },
+    { "ssl_f_s_dn_rfc2253",     smp_fetch_ssl_x_s_dn_rfc2253, 0,                   NULL,    SMP_T_STR,  SMP_USE_L5CLI },
 	{ "ssl_f_serial",           smp_fetch_ssl_x_serial,       0,                   NULL,    SMP_T_BIN,  SMP_USE_L5CLI },
 	{ "ssl_f_sha1",             smp_fetch_ssl_x_sha1,         0,                   NULL,    SMP_T_BIN,  SMP_USE_L5CLI },
 	{ "ssl_f_version",          smp_fetch_ssl_x_version,      0,                   NULL,    SMP_T_SINT, SMP_USE_L5CLI },
-- 
1.8.3.1

