about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlexander Barton <alex@barton.de>2024-01-02 21:10:17 +0100
committerAlexander Barton <alex@barton.de>2024-03-23 20:19:01 +0100
commit679505aab9fea21b27a3d4bbf99cf2a16cf3d3d5 (patch)
tree215a0a85e6b2397daacf27b7d66fda486713b2e2
parent08647ab1e7cf0d034f2d8987a3cac3201af84e02 (diff)
downloadngircd-679505aab9fea21b27a3d4bbf99cf2a16cf3d3d5.tar.gz
ngircd-679505aab9fea21b27a3d4bbf99cf2a16cf3d3d5.zip
S2S-TLS/OpenSSL: Fix handling of certificate information for incoming connections
Show proper certificate information for incoming connections, too, and
not "peer did not present a certificate", regardless if the client sent
a certificate or not.

And free the client certificate structure "peer_cert" on incoming
connections as well!
-rw-r--r--src/ngircd/conn-ssl.c46
1 files changed, 30 insertions, 16 deletions
diff --git a/src/ngircd/conn-ssl.c b/src/ngircd/conn-ssl.c
index a51f46b2..d89c11fe 100644
--- a/src/ngircd/conn-ssl.c
+++ b/src/ngircd/conn-ssl.c
@@ -935,22 +935,36 @@ ConnSSL_LogCertInfo( CONNECTION * c, bool connect)
 	Log(LOG_INFO, "Connection %d: initialized %s using cipher %s, %s.",
 	    c->sock, SSL_get_version(ssl), SSL_get_cipher(ssl), comp_alg);
 	peer_cert = SSL_get_peer_certificate(ssl);
-	if (peer_cert && connect) {
+	if (peer_cert) {
 		cert_seen = true;
-		/* Client: Check server certificate */
-		int err = SSL_get_verify_result(ssl);
-		if (err == X509_V_OK) {
-			const char *peername = SSL_get0_peername(ssl);
-			if (peername != NULL)
-				cert_ok = true;
-			LogDebug("X509_V_OK, peername = '%s'", peername);
-		} else
-			Log(LOG_ERR, "Certificate validation failed: %s",
-			    X509_verify_cert_error_string(err));
-		snprintf(msg, sizeof(msg), "%svalid peer certificate",
-			 cert_ok ? "" : "in");
-		LogOpenSSL_CertInfo(cert_ok ? LOG_DEBUG : LOG_ERR, peer_cert,
-				    msg);
+
+		if (connect) {
+			/* Outgoing connection. Verify the remote server! */
+			int err = SSL_get_verify_result(ssl);
+			if (err == X509_V_OK) {
+				const char *peername = SSL_get0_peername(ssl);
+				if (peername != NULL)
+					cert_ok = true;
+				LogDebug("X509_V_OK, peername = '%s'", peername);
+			} else
+				Log(LOG_WARNING, "Certificate validation failed: %s!",
+				    X509_verify_cert_error_string(err));
+
+			snprintf(msg, sizeof(msg), "Got %svalid server certificate",
+				 cert_ok ? "" : "in");
+			LogOpenSSL_CertInfo(LOG_INFO, peer_cert, msg);
+		} else {
+			/* Incoming connection.
+			 * Accept all certificates, don't depend on their
+			 * validity: for example, we don't know the hostname
+			 * to check, because we not yet even know if this is a
+			 * server connection at all and if so, which one, so we
+			 * don't know a host name to look for. On the other
+			 * hand we want client certificates, for example for
+			 * "CertFP" authentication with services ... */
+			LogOpenSSL_CertInfo(LOG_INFO, peer_cert,
+					    "Got unchecked client certificate");
+		}
 
 		X509_free(peer_cert);
 	}
@@ -1038,7 +1052,7 @@ done_cn_validation:
 	if (cert_ok)
 		Conn_OPTION_ADD(c, CONN_SSL_PEERCERT_OK);
 	if (!cert_seen)
-		Log(LOG_INFO, "Peer did not present a certificate");
+		Log(LOG_INFO, "Peer did not present a certificate.");
 }