On 13.07.22 01:06, Jacob Champion wrote:
I had to read up on this "ex_data" API.  Interesting.  But I'm wondering
a bit about how the life cycle of these objects is managed.  What
happens if the allocated error string is deallocated before its
containing object?  Or vice versa?

Yeah, I'm currently leaning heavily on the lack of any memory context
switches here. And I end up leaking out a pointer to the stale stack
of be_tls_open_server(), which is gross -- it works since there are no
other clients, but that could probably come back to bite us.

The ex_data API exposes optional callbacks for new/dup/free (I'm
currently setting those to NULL), so we can run custom code whenever
the SSL* is destroyed. If you'd rather the data have the same lifetime
of the SSL* object, we can switch to malloc/strdup/free (or even
OPENSSL_strdup() in later versions). But since we don't have any use
for the ex_data outside of this function, maybe we should just clear
it before we return, rather than carrying it around.

Concretely, I was thinking like the attached top-up patch.

The other way can surely be made to work somehow, but this seems much simpler and with fewer questions about the details.
From 662bc1d19101865f91c6ed4a98c0f13f3757e1c7 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Thu, 14 Jul 2022 22:08:53 +0200
Subject: [PATCH v5 2/2] squash! Log details for client certificate failures

---
 src/backend/libpq/be-secure-openssl.c | 29 +++++----------------------
 1 file changed, 5 insertions(+), 24 deletions(-)

diff --git a/src/backend/libpq/be-secure-openssl.c 
b/src/backend/libpq/be-secure-openssl.c
index 8d5eee0d16..2147524ffc 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -81,13 +81,7 @@ static bool ssl_is_server_start;
 static int     ssl_protocol_version_to_openssl(int v);
 static const char *ssl_protocol_version_to_string(int v);
 
-/* Helpers for storing application data in the SSL handle */
-struct pg_ex_data
-{
-       /* to bubble errors out of callbacks */
-       char       *errdetail;
-};
-static int     ssl_ex_index;
+static const char *cert_errdetail;
 
 /* ------------------------------------------------------------ */
 /*                                              Public interface               
                                */
@@ -110,7 +104,6 @@ be_tls_init(bool isServerStart)
                SSL_library_init();
                SSL_load_error_strings();
 #endif
-               ssl_ex_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
                SSL_initialized = true;
        }
 
@@ -422,7 +415,6 @@ be_tls_open_server(Port *port)
        int                     err;
        int                     waitfor;
        unsigned long ecode;
-       struct pg_ex_data exdata = {0};
        bool            give_proto_hint;
 
        Assert(!port->ssl);
@@ -455,14 +447,6 @@ be_tls_open_server(Port *port)
                                                
SSLerrmessage(ERR_get_error()))));
                return -1;
        }
-       if (!SSL_set_ex_data(port->ssl, ssl_ex_index, &exdata))
-       {
-               ereport(COMMERROR,
-                               (errcode(ERRCODE_PROTOCOL_VIOLATION),
-                                errmsg("could not attach application data to 
SSL handle: %s",
-                                               
SSLerrmessage(ERR_get_error()))));
-               return -1;
-       }
 
        port->ssl_in_use = true;
 
@@ -561,7 +545,7 @@ be_tls_open_server(Port *port)
                                                
(errcode(ERRCODE_PROTOCOL_VIOLATION),
                                                 errmsg("could not accept SSL 
connection: %s",
                                                                
SSLerrmessage(ecode)),
-                                                exdata.errdetail ? 
errdetail_internal("%s", exdata.errdetail) : 0,
+                                                cert_errdetail ? 
errdetail_internal("%s", cert_errdetail) : 0,
                                                 give_proto_hint ?
                                                 errhint("This may indicate 
that the client does not support any SSL protocol version between %s and %s.",
                                                                 
ssl_min_protocol_version ?
@@ -570,6 +554,7 @@ be_tls_open_server(Port *port)
                                                                 
ssl_max_protocol_version ?
                                                                 
ssl_protocol_version_to_string(ssl_max_protocol_version) :
                                                                 
MAX_OPENSSL_TLS_VERSION) : 0));
+                               cert_errdetail = NULL;
                                break;
                        case SSL_ERROR_ZERO_RETURN:
                                ereport(COMMERROR,
@@ -1145,12 +1130,10 @@ truncate_cert_name(char *name)
 static int
 verify_cb(int ok, X509_STORE_CTX *ctx)
 {
-       SSL                *ssl;
        int                     depth;
        int                     errcode;
        const char *errstring;
        StringInfoData str;
-       struct pg_ex_data *exdata;
        X509       *cert;
 
        if (ok)
@@ -1160,7 +1143,6 @@ verify_cb(int ok, X509_STORE_CTX *ctx)
        }
 
        /* Pull all the information we have on the verification failure. */
-       ssl = X509_STORE_CTX_get_ex_data(ctx, 
SSL_get_ex_data_X509_STORE_CTX_idx());
        depth = X509_STORE_CTX_get_error_depth(ctx);
        errcode = X509_STORE_CTX_get_error(ctx);
        errstring = X509_verify_cert_error_string(errcode);
@@ -1212,9 +1194,8 @@ verify_cb(int ok, X509_STORE_CTX *ctx)
                pfree(subject);
        }
 
-       /* Store our detail message in SSL application data, to be logged 
later. */
-       exdata = SSL_get_ex_data(ssl, ssl_ex_index);
-       exdata->errdetail = str.data;
+       /* Store our detail message to be logged later. */
+       cert_errdetail = str.data;
 
        return ok;
 }
-- 
2.37.0

Reply via email to