From 552aa7f8cfcae4c91b65c6e34dd16920a71642f3 Mon Sep 17 00:00:00 2001
From: Noriko Hosoi <nhosoi@redhat.com>
Date: Thu, 6 Nov 2014 15:32:48 -0800
Subject: [PATCH] Ticket #47945 - Add SSL/TLS version info to the access log

Description: Added the currently used SSL library version info per
connection to the access log.
Sample output:
  SSL
  [..] conn=3 fd=64 slot=64 SSL connection from ::1 to ::1
  [..] conn=3 TLS1.2 128-bit AES-GCM

  startTLS
  [..] conn=4 op=0 EXT oid="1.3.6.1.4.1.1466.20037" name="startTLS"
  [..] conn=4 op=0 RESULT err=0 tag=120 nentries=0 etime=0
  [..] conn=4 TLS1.2 128-bit AES-GCM
---
 ldap/servers/slapd/auth.c | 104 ++++++++++++++++++++++++++++++++--------------
 1 file changed, 73 insertions(+), 31 deletions(-)

diff --git a/ldap/servers/slapd/auth.c b/ldap/servers/slapd/auth.c
index 5b7dc31..907ee52 100644
--- a/ldap/servers/slapd/auth.c
+++ b/ldap/servers/slapd/auth.c
@@ -50,6 +50,7 @@
 #endif
 #include "slap.h" /* slapi_ch_malloc */
 #include "fe.h"
+#include <sslproto.h> /* For the SSL version ID */
 
 char* client_auth_config_file = NULL;
 
@@ -412,6 +413,37 @@ handle_bad_certificate (void* clientData, PRFileDesc *prfd)
     return -1; /* non-zero means reject this certificate */
 }
 
+typedef struct {
+    int ssl_vid;
+    char *ssl_vname;
+} ssl_version_table;
+static ssl_version_table _ssl_version_table[] = {
+    {SSL_LIBRARY_VERSION_2,       "SSL2"},
+    {SSL_LIBRARY_VERSION_3_0,     "SSL3"},
+    {SSL_LIBRARY_VERSION_TLS_1_0, "TLS1.0"},
+    {SSL_LIBRARY_VERSION_TLS_1_1, "TLS1.1"},
+    {SSL_LIBRARY_VERSION_TLS_1_2, "TLS1.2"},
+    {SSL_LIBRARY_VERSION_TLS_1_3, "TLS1.3"},
+    {0, "UNKNOWN SSL VERSION"}
+};
+#define SSL_LIBRARY_VERSION_MAX SSL_LIBRARY_VERSION_TLS_1_3
+#define SSL_LIBRARY_VERSION_MAX_STR " >TLS1.3"
+
+static char *
+get_ssl_version_str(int vid)
+{
+    ssl_version_table *svtp = NULL;
+
+    for (svtp = _ssl_version_table; svtp && svtp->ssl_vid; svtp++) {
+        if (vid == svtp->ssl_vid) {
+            return svtp->ssl_vname;
+        }
+    }
+    if (vid > SSL_LIBRARY_VERSION_MAX) {
+        return SSL_LIBRARY_VERSION_MAX_STR;
+    }
+    return svtp->ssl_vname;
+}
 
 /*
  * Get an identity from the client's certificate (if any was sent).
@@ -460,38 +492,46 @@ handle_handshake_done (PRFileDesc *prfd, void* clientData)
      * to be enough, close the SSL connection. */
     if ( conn->c_flags & CONN_FLAG_START_TLS ) {
         if ( cipherInfo.symKeyBits == 0 ) {
-	        start_tls_graceful_closure( conn, NULL, 1 );
-		goto done;
-	}
+            start_tls_graceful_closure( conn, NULL, 1 );
+            goto done;
+        }
     }
 
     if (config_get_SSLclientAuth() == SLAPD_SSLCLIENTAUTH_OFF ) {
-		slapi_log_access (LDAP_DEBUG_STATS, "conn=%" NSPRIu64 " SSL %i-bit %s\n",
-				(long long unsigned int)conn->c_connid, keySize, cipher ? cipher : "NULL" );
-		goto done;
-    } 
+        slapi_log_access (LDAP_DEBUG_STATS, "conn=%" NSPRIu64 " %s %i-bit %s\n",
+                (long long unsigned int)conn->c_connid, 
+                get_ssl_version_str(channelInfo.protocolVersion),
+                keySize, cipher ? cipher : "NULL" );
+        goto done;
+    }
     if (clientCert == NULL) {
-	slapi_log_access (LDAP_DEBUG_STATS, "conn=%" NSPRIu64 " SSL %i-bit %s\n",
-			(long long unsigned int)conn->c_connid, keySize, cipher ? cipher : "NULL" );
+        slapi_log_access (LDAP_DEBUG_STATS, "conn=%" NSPRIu64 " %s %i-bit %s\n",
+                (long long unsigned int)conn->c_connid, 
+                get_ssl_version_str(channelInfo.protocolVersion),
+                keySize, cipher ? cipher : "NULL" );
     } else {
-	subject = subject_of (clientCert);
-	if (!subject) {
-		slapi_log_access( LDAP_DEBUG_STATS,
-		       "conn=%" NSPRIu64 " SSL %i-bit %s; missing subject\n",
-		       (long long unsigned int)conn->c_connid, keySize, cipher ? cipher : "NULL");
-		goto done;
-	}
-	{
-	    char* issuer  = issuer_of (clientCert);
-	    char sbuf[ BUFSIZ ], ibuf[ BUFSIZ ];
-	    slapi_log_access( LDAP_DEBUG_STATS,
-		       "conn=%" NSPRIu64 " SSL %i-bit %s; client %s; issuer %s\n",
-		       (long long unsigned int)conn->c_connid, keySize, cipher ? cipher : "NULL",
-		       subject ? escape_string( subject, sbuf ) : "NULL",
-		       issuer  ? escape_string( issuer,  ibuf ) : "NULL");
-	    if (issuer) free (issuer);
-	}
-	slapi_dn_normalize (subject);
+        subject = subject_of (clientCert);
+        if (!subject) {
+            slapi_log_access( LDAP_DEBUG_STATS,
+                       "conn=%" NSPRIu64 " %s %i-bit %s; missing subject\n",
+                       (long long unsigned int)conn->c_connid, 
+                       get_ssl_version_str(channelInfo.protocolVersion),
+                       keySize, cipher ? cipher : "NULL");
+            goto done;
+        }
+        {
+            char* issuer  = issuer_of (clientCert);
+            char sbuf[ BUFSIZ ], ibuf[ BUFSIZ ];
+            slapi_log_access( LDAP_DEBUG_STATS,
+                        "conn=%" NSPRIu64 " %s %i-bit %s; client %s; issuer %s\n",
+                        (long long unsigned int)conn->c_connid,
+                        get_ssl_version_str(channelInfo.protocolVersion),
+                        keySize, cipher ? cipher : "NULL",
+                        subject ? escape_string( subject, sbuf ) : "NULL",
+                        issuer  ? escape_string( issuer,  ibuf ) : "NULL");
+            if (issuer) free (issuer);
+        }
+        slapi_dn_normalize (subject);
 	{
 	    LDAPMessage* chain = NULL;
 		char *basedn = config_get_basedn();
@@ -526,13 +566,15 @@ handle_handshake_done (PRFileDesc *prfd, void* clientData)
         clientDN = slapi_ch_strdup(slapi_sdn_get_dn(sdn));
         slapi_sdn_free(&sdn);
         slapi_log_access (LDAP_DEBUG_STATS, 
-                          "conn=%" NSPRIu64 " SSL client bound as %s\n",
-                          (long long unsigned int)conn->c_connid, clientDN);
+                          "conn=%" NSPRIu64 " %s client bound as %s\n",
+                          (long long unsigned int)conn->c_connid,
+                          get_ssl_version_str(channelInfo.protocolVersion), clientDN);
     } else if (clientCert != NULL) {
         slapi_log_access (LDAP_DEBUG_STATS,
-                          "conn=%" NSPRIu64 " SSL failed to map client "
+                          "conn=%" NSPRIu64 " %s failed to map client "
                           "certificate to LDAP DN (%s)\n",
-                          (long long unsigned int)conn->c_connid, extraErrorMsg );
+                          (long long unsigned int)conn->c_connid,
+                          get_ssl_version_str(channelInfo.protocolVersion), extraErrorMsg);
     }
 
 	/*
-- 
1.9.3

