Package: ngircd
Version: 25-2
Severity: important
Tags: patch
X-Debbugs-Cc: debian.a...@manchmal.in-ulm.de
Control: fixed 26.1-1+deb11u1
Control: fixed 26.1-1+deb12u1
Control: fixed 27~rc1-1

A long-standing issue was fixed in a recent version of ngircd, a
lightweight Internet Relay Chat server:

In a TLS-based server-server connection, the server certificate is
not validated.

github issue: https://github.com/ngircd/ngircd/issues/120

For reasons both upstream and I fail to understand, no CVE number was
assigned by MITRE.

For Debian unstable and testing, this has been fixed in 27~rc1-1,
uploaded April 13th.

For Debian 12 (stable, bookworm) and 11 (oldstable, bullseye), this will
be fixed in the upcoming stable point release on June 29th.

See https://bugs.debian.org/1074018 for details.

For Debian 10 (oldoldstable, buster), downstream distributions based on
it might want to peruse the attached debdiff. It fixes two other issues,
just the way it was done for the two newer stable releases:

1. In a server-server connection, a connection may still use
plain text despite the connection ought to be TLS-based.

2. Some IRC services might send an empty string for the hostname to
implement the "uncloak host" functionality, leading to a protocol
violation in subsequent "WHOIS" or other commands against the ngircd
server.

    Christoph
diff -Nru ngircd-25/debian/changelog ngircd-25/debian/changelog
--- ngircd-25/debian/changelog  2019-01-28 18:47:07.000000000 +0100
+++ ngircd-25/debian/changelog  2024-05-01 10:00:00.000000000 +0200
@@ -1,3 +1,13 @@
+ngircd (25-2+deb10u1) buster; urgency=high
+
+  * Cherry-pick "Respect "SSLConnect" option for incoming
+    connections". Closes: #1067237
+  * Cherry-pick "Support for server certificate validation on server
+    links [S2S-TLS]"
+  * Cherry-pick "METADATA: Fix unsetting "cloakhost""
+
+ -- Christoph Biedl <debian.a...@manchmal.in-ulm.de>  Wed, 01 May 2024 
10:00:00 +0200
+
 ngircd (25-2) unstable; urgency=medium
 
   * Re-enable compression support
diff -Nru ngircd-25/debian/ngircd.conf ngircd-25/debian/ngircd.conf
--- ngircd-25/debian/ngircd.conf        2015-12-10 23:48:06.000000000 +0100
+++ ngircd-25/debian/ngircd.conf        2024-05-01 10:00:00.000000000 +0200
@@ -254,6 +254,15 @@
 [SSL]
        # SSL-related configuration options.
 
+       # SSL Trusted CA Certificates File for verifying peer certificates.
+       # (Default: not set; so no certificates are trusted)
+       ;CAFile = /etc/ssl/certs/ca-certificates.crt
+
+
+       # Certificate Revocation File (for marking otherwise valid
+       # certficates as invalid)
+       ;CRLFile = /etc/ssl/CA/crl.pem
+
        # SSL Server Key Certificate
        ;CertFile = /etc/ssl/certs/server.crt
 
@@ -347,6 +356,10 @@
        # Connect to the remote server using TLS/SSL (Default: false)
        ;SSLConnect = yes
 
+       # Verify the TLS certificate presented by the remote server
+       # (Default: yes)
+       ;SSLVerify = yes
+
        # Define a (case insensitive) list of masks matching nicknames that
        # should be treated as IRC services when introduced via this remote
        # server, separated by commas (",").
diff -Nru ngircd-25/debian/ngircd.NEWS ngircd-25/debian/ngircd.NEWS
--- ngircd-25/debian/ngircd.NEWS        1970-01-01 01:00:00.000000000 +0100
+++ ngircd-25/debian/ngircd.NEWS        2024-05-01 10:00:00.000000000 +0200
@@ -0,0 +1,8 @@
+ngircd (25-2+deb10u1) buster; urgency=high
+
+  * This version introduces x509 certificate validation on TLS-based
+    server-server links. Existing configurations will likely break, for
+    details see </usr/share/doc/ngircd/README.Debian>, starting at
+    "TLS-based server-server links".
+
+ -- Christoph Biedl <debian.a...@manchmal.in-ulm.de>  Wed, 01 May 2024 
10:00:00 +0200
diff -Nru ngircd-25/debian/ngircd.README.Debian 
ngircd-25/debian/ngircd.README.Debian
--- ngircd-25/debian/ngircd.README.Debian       2014-10-15 19:44:02.000000000 
+0200
+++ ngircd-25/debian/ngircd.README.Debian       2024-05-01 10:00:00.000000000 
+0200
@@ -43,6 +43,25 @@
   Repeat the last step for all users that run a daemon providing TLS.
 
 
+TLS-based server-server links
+-----------------------------
+When linking two ngircd servers, the connection should be TLS-based for
+obvious reasons. To do so, edit ngircd.conf:
+
+* Enable SSLConnect in each [Server] stanza.
+* Define CAFile in the [SSL] stanza. Note that by default *no*
+  certificate is trusted.
+  If the peers's certificate was signed by one of the well-known
+  certificate authorities: Use the suggested value
+  "/etc/ssl/certs/ca-certificates.crt" and install the ca-certificate
+  package.
+  Else set the value to the respective CA's certificate file.
+
+Verfication can be disabled entirely on a per-link base by setting
+SSLVerify to false. This is strongly discouraged as you will lose all
+security by that.
+
+
 DH parameters file
 ------------------
 It is suggested to create a DH params file. If missing, ngIRCd will
diff -Nru 
ngircd-25/debian/patches/0001-Respect-SSLConnect-option-for-incoming-connections.patch
 
ngircd-25/debian/patches/0001-Respect-SSLConnect-option-for-incoming-connections.patch
--- 
ngircd-25/debian/patches/0001-Respect-SSLConnect-option-for-incoming-connections.patch
      1970-01-01 01:00:00.000000000 +0100
+++ 
ngircd-25/debian/patches/0001-Respect-SSLConnect-option-for-incoming-connections.patch
      2024-04-02 21:15:49.000000000 +0200
@@ -0,0 +1,42 @@
+From 65a304dab3329625b409efa161f2c31a7221ad7c Mon Sep 17 00:00:00 2001
+From: Alexander Barton <a...@barton.de>
+Date: Mon, 1 Jan 2024 18:20:26 +0100
+Subject: [PATCH 01/20] Respect "SSLConnect" option for incoming connections
+
+Don't accept incoming plain-text ("non SSL") server connections for
+servers configured with "SSLConnect" enabled.
+
+If "SSLConnect" is not set for an incoming connection the server still
+accepts both plain-text and encrypted connections.
+
+This change prevents an authenticated client-server being able to force
+the server-server to send its password on a plain-text connection when
+SSL/TLS was intended.
+
+(cherry picked from commit 21c1751b045b0be49e584a4ba191a330e0c381bb)
+---
+ src/ngircd/irc-server.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+--- a/src/ngircd/irc-server.c
++++ b/src/ngircd/irc-server.c
+@@ -87,6 +87,19 @@
+                       return DISCONNECTED;
+               }
+ 
++#ifdef SSL_SUPPORT
++              /* Does this server require an SSL connection? */
++              if (Conf_Server[i].SSLConnect &&
++                  !(Conn_Options(Client_Conn(Client)) & CONN_SSL)) {
++                      Log(LOG_ERR,
++                          "Connection %d: Server \"%s\" requires a secure 
connection!",
++                          Client_Conn(Client), Req->argv[0]);
++                      Conn_Close(Client_Conn(Client), NULL,
++                                 "Secure connection required", true);
++                      return DISCONNECTED;
++              }
++#endif
++
+               /* Check server password */
+               if (strcmp(Conn_Password(Client_Conn(Client)),
+                   Conf_Server[i].pwd_in) != 0) {
diff -Nru 
ngircd-25/debian/patches/0001-S2S-SSL-GnuTLS-Enable-CRL-verification_26.1.patch 
ngircd-25/debian/patches/0001-S2S-SSL-GnuTLS-Enable-CRL-verification_26.1.patch
--- 
ngircd-25/debian/patches/0001-S2S-SSL-GnuTLS-Enable-CRL-verification_26.1.patch 
    1970-01-01 01:00:00.000000000 +0100
+++ 
ngircd-25/debian/patches/0001-S2S-SSL-GnuTLS-Enable-CRL-verification_26.1.patch 
    2024-04-15 14:14:32.000000000 +0200
@@ -0,0 +1,21 @@
+From edb8fce8719efb0d887c72495e540d60a3bf4ed7 Mon Sep 17 00:00:00 2001
+From: Christoph Biedl <ngircd.a...@manchmal.in-ulm.de>
+Date: Sun, 31 Mar 2024 00:36:53 +0100
+Subject: [PATCH] S2S-SSL/GnuTLS: Enable CRL verification
+
+(cherry picked from commit b2c9049af20b12f2fde08f4af0a35968404effdb)
+---
+ src/ngircd/conn-ssl.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/src/ngircd/conn-ssl.c
++++ b/src/ngircd/conn-ssl.c
+@@ -486,6 +486,8 @@
+               return false;
+ 
+       gnutls_certificate_set_dh_params(x509_cred, dh_params);
++      gnutls_certificate_set_flags(x509_cred, GNUTLS_CERTIFICATE_VERIFY_CRLS);
++
+       err = gnutls_certificate_set_x509_key_file(x509_cred, cert_file, 
Conf_SSLOptions.KeyFile, GNUTLS_X509_FMT_PEM);
+       if (err < 0) {
+               Log(LOG_ERR,
diff -Nru 
ngircd-25/debian/patches/0002-Support-for-server-certificate-validation-on-server-.patch
 
ngircd-25/debian/patches/0002-Support-for-server-certificate-validation-on-server-.patch
--- 
ngircd-25/debian/patches/0002-Support-for-server-certificate-validation-on-server-.patch
    1970-01-01 01:00:00.000000000 +0100
+++ 
ngircd-25/debian/patches/0002-Support-for-server-certificate-validation-on-server-.patch
    2024-04-15 14:14:26.000000000 +0200
@@ -0,0 +1,682 @@
+From 0707d8a5c23744eb117621b12c12b1f8dbf6973b Mon Sep 17 00:00:00 2001
+From: Christoph Biedl <ngircd.a...@manchmal.in-ulm.de>
+Date: Sun, 2 Nov 2014 14:48:34 +0100
+Subject: [PATCH 02/20] Support for server certificate validation on server
+ links [S2S-TLS]
+
+This patch provides code to validate the server certificate in
+server links, defeating nasty man-in-the-middle attacks on server
+links.
+
+Features:
+
+- Check whether the certificate is signed by a trusted certificate
+  authority (CA).
+- Check the host name, including wildcard certificates and Subject
+  Alternative Names.
+- Optionally check against a certificate revocation list (CRL).
+- Implementation for both OpenSSL and GnuTLS linkage.
+
+Left for another day:
+
+- Parameterize the TLS parameter of an outbound connection. Currently,
+  it's hardcoded to disable all versions before TLSv1.1.
+- Using certificate as CA-certificate. They work for GnuTLS only but
+  perhaps this should rather raise an error there, too.
+- Optional OCSP checking.
+- Checking client certificates. Code is there but this first needs some
+  consideration about the use cases. This could replace all other
+  authentication methods, for both client-server and server-server
+  connections.
+
+This patch is based on a patch by Florian Westphal from 2009, which
+implemented this for OpenSSL only:
+
+  From: Florian Westphal <f...@strlen.de>
+  Date: Mon, 18 May 2009 00:29:02 +0200
+  Subject: SSL/TLS: Add initial certificate support to OpenSSL backend
+
+Commit message modified by Alex Barton.
+
+Closes #120, "Server links using TLS/SSL need certificate validation".
+Supersedes PR #8, "Options for verifying and requiring SSL client
+certificates", which had (incomplete?) code for OpenSSL, no GnuTLS.
+
+(cherry picked from commit 817937b218c4b57515f54216ebc936cd69df0aae)
+---
+ doc/sample-ngircd.conf.tmpl |  11 ++
+ man/ngircd.conf.5.tmpl      |  10 ++
+ src/ngircd/conf.c           |  27 ++-
+ src/ngircd/conf.h           |   3 +
+ src/ngircd/conn-ssl.c       | 323 ++++++++++++++++++++++++++++++++++--
+ src/ngircd/conn.c           |  21 +++
+ src/ngircd/conn.h           |   3 +-
+ 7 files changed, 385 insertions(+), 13 deletions(-)
+
+--- a/doc/sample-ngircd.conf.tmpl
++++ b/doc/sample-ngircd.conf.tmpl
+@@ -266,6 +266,13 @@
+       # is only available when ngIRCd is compiled with support for SSL!
+       # So don't forget to remove the ";" above if this is the case ...
+ 
++      # SSL Trusted CA Certificates File (for verifying peer certificates)
++      ;CAFile = /etc/ssl/CA/cacert.pem
++
++      # Certificate Revocation File (for marking otherwise valid
++      # certficates as invalid)
++      ;CRLFile = /etc/ssl/CA/crl.pem
++
+       # SSL Server Key Certificate
+       ;CertFile = :ETCDIR:/ssl/server-cert.pem
+ 
+@@ -357,6 +364,10 @@
+       # Connect to the remote server using TLS/SSL (Default: false)
+       ;SSLConnect = yes
+ 
++      # Verify the TLS certificate presented by the remote server
++      # (Default: yes)
++      ;SSLVerify = yes
++
+       # Define a (case insensitive) list of masks matching nicknames that
+       # should be treated as IRC services when introduced via this remote
+       # server, separated by commas (",").
+--- a/man/ngircd.conf.5.tmpl
++++ b/man/ngircd.conf.5.tmpl
+@@ -385,6 +385,13 @@
+ section. Please note that this whole section is only recognized by ngIRCd
+ when it is compiled with support for SSL using OpenSSL or GnuTLS!
+ .TP
++\fBCAFile (string)\fR
++Filename pointing to the Trusted CA Certificates. This is required for
++verifying peer certificates.
++.TP
++\fBCRLFile (string)\fR
++Filename of Certificate Revocation List.
++.TP
+ \fBCertFile\fR (string)
+ SSL Certificate file of the private server key.
+ .TP
+@@ -479,6 +486,9 @@
+ \fBSSLConnect\fR (boolean)
+ Connect to the remote server using TLS/SSL. Default: false.
+ .TP
++\fBSSLVerify\fR (boolean)
++Verify the TLS certificate presented by the remote server. Default: yes.
++.TP
+ \fBServiceMask\fR (string)
+ Define a (case insensitive) list of masks matching nicknames that should be
+ treated as IRC services when introduced via this remote server, separated
+--- a/src/ngircd/conf.c
++++ b/src/ngircd/conf.c
+@@ -112,6 +112,12 @@
+       free(Conf_SSLOptions.CertFile);
+       Conf_SSLOptions.CertFile = NULL;
+ 
++      free(Conf_SSLOptions.CAFile);
++      Conf_SSLOptions.CAFile = NULL;
++
++      free(Conf_SSLOptions.CRLFile);
++      Conf_SSLOptions.CRLFile = NULL;
++
+       free(Conf_SSLOptions.DHFile);
+       Conf_SSLOptions.DHFile = NULL;
+       array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
+@@ -464,7 +470,10 @@
+               printf( "  Host = %s\n", Conf_Server[i].host );
+               printf( "  Port = %u\n", (unsigned int)Conf_Server[i].port );
+ #ifdef SSL_SUPPORT
+-              printf( "  SSLConnect = %s\n", 
Conf_Server[i].SSLConnect?"yes":"no");
++              printf("  SSLConnect = %s\n",
++                     yesno_to_str(Conf_Server[i].SSLConnect));
++              printf("  SSLVerify = %s\n",
++                     yesno_to_str(Conf_Server[i].SSLVerify));
+ #endif
+               printf( "  MyPassword = %s\n", Conf_Server[i].pwd_in );
+               printf( "  PeerPassword = %s\n", Conf_Server[i].pwd_out );
+@@ -1940,6 +1949,16 @@
+               Conf_SSLOptions.CipherList = strdup_warn(Arg);
+               return;
+       }
++      if (strcasecmp(Var, "CAFile") == 0) {
++              assert(Conf_SSLOptions.CAFile == NULL);
++              Conf_SSLOptions.CAFile = strdup_warn(Arg);
++              return;
++      }
++      if (strcasecmp(Var, "CRLFile") == 0) {
++              assert(Conf_SSLOptions.CRLFile == NULL);
++              Conf_SSLOptions.CRLFile = strdup_warn(Arg);
++              return;
++      }
+ 
+       Config_Error_Section(File, Line, Var, "SSL");
+ }
+@@ -2070,7 +2089,11 @@
+       if( strcasecmp( Var, "SSLConnect" ) == 0 ) {
+               New_Server.SSLConnect = Check_ArgIsTrue(Arg);
+               return;
+-        }
++      }
++      if (strcasecmp(Var, "SSLVerify") == 0) {
++              New_Server.SSLVerify = Check_ArgIsTrue(Arg);
++              return;
++      }
+ #endif
+       if( strcasecmp( Var, "Group" ) == 0 ) {
+               /* Server group */
+--- a/src/ngircd/conf.h
++++ b/src/ngircd/conf.h
+@@ -61,6 +61,7 @@
+       ng_ipaddr_t dst_addr[2];        /**< List of addresses to connect to */
+ #ifdef SSL_SUPPORT
+       bool SSLConnect;                /**< Establish connection using SSL? */
++      bool SSLVerify;                 /**< Verify server certificate using 
CA? */
+ #endif
+       char svs_mask[CLIENT_ID_LEN];   /**< Mask of nicknames that should be
+                                            treated and counted as services */
+@@ -76,6 +77,8 @@
+       array ListenPorts;              /**< Array of listening SSL ports */
+       array KeyFilePassword;          /**< Key file password */
+       char *CipherList;               /**< Set SSL cipher list to use */
++      char *CAFile;                   /**< Trusted CA certificates file */
++      char *CRLFile;                  /**< Certificate revocation file */
+ };
+ #endif
+ 
+--- a/src/ngircd/conn-ssl.c
++++ b/src/ngircd/conn-ssl.c
+@@ -43,13 +43,17 @@
+ #include <openssl/err.h>
+ #include <openssl/rand.h>
+ #include <openssl/dh.h>
++#include <openssl/x509v3.h>
+ 
+ static SSL_CTX * ssl_ctx;
+ static DH *dh_params;
+ 
+ static bool ConnSSL_LoadServerKey_openssl PARAMS(( SSL_CTX *c ));
++static bool ConnSSL_SetVerifyProperties_openssl PARAMS((SSL_CTX * c));
+ #endif
+ 
++#define MAX_CERT_CHAIN_LENGTH 10      /* XXX: do not hardcode */
++
+ #ifdef HAVE_LIBGNUTLS
+ #include <sys/types.h>
+ #include <sys/stat.h>
+@@ -66,6 +70,7 @@
+ static gnutls_dh_params_t dh_params;
+ static gnutls_priority_t priorities_cache;
+ static bool ConnSSL_LoadServerKey_gnutls PARAMS(( void ));
++static bool ConnSSL_SetVerifyProperties_gnutls PARAMS((void));
+ #endif
+ 
+ #define SHA256_STRING_LEN     (32 * 2 + 1)
+@@ -123,10 +128,38 @@
+ /**
+  * Log OpenSSL error message.
+  *
++ * @param level The log level
+  * @param msg The error message.
+  * @param info Additional information text or NULL.
+  */
+ static void
++LogOpenSSL_CertInfo(int level, X509 * cert, const char *msg)
++{
++      BIO *mem;
++      char *memptr;
++      long len;
++
++      assert(cert);
++      assert(msg);
++
++      if (!cert)
++              return;
++      mem = BIO_new(BIO_s_mem());
++      if (!mem)
++              return;
++      X509_NAME_print_ex(mem, X509_get_subject_name(cert), 4,
++                         XN_FLAG_ONELINE);
++      X509_NAME_print_ex(mem, X509_get_issuer_name(cert), 4, XN_FLAG_ONELINE);
++      if (BIO_write(mem, "", 1) == 1) {
++              len = BIO_get_mem_data(mem, &memptr);
++              if (memptr && len > 0)
++                      Log(level, "%s: \"%s\"", msg, memptr);
++      }
++      (void)BIO_set_close(mem, BIO_CLOSE);
++      BIO_free(mem);
++}
++
++static void
+ LogOpenSSLError(const char *error, const char *info)
+ {
+       unsigned long err = ERR_get_error();
+@@ -168,9 +201,16 @@
+ 
+ 
+ static int
+-Verify_openssl(UNUSED int preverify_ok, UNUSED X509_STORE_CTX *x509_ctx)
++Verify_openssl(int preverify_ok, X509_STORE_CTX * ctx)
+ {
+-      return 1;
++      int err;
++
++      if (!preverify_ok) {
++              err = X509_STORE_CTX_get_error(ctx);
++              Log(LOG_ERR, "Certificate validation failed: %s",
++                  X509_verify_cert_error_string(err));
++      }
++      return preverify_ok;
+ }
+ #endif
+ 
+@@ -321,7 +361,12 @@
+       }
+ 
+       SSL_CTX_set_session_id_context(newctx, (unsigned char *)"ngircd", 6);
+-      SSL_CTX_set_options(newctx, SSL_OP_SINGLE_DH_USE|SSL_OP_NO_SSLv2);
++      if (!ConnSSL_SetVerifyProperties_openssl(newctx))
++              goto out;
++      SSL_CTX_set_options(newctx,
++                          SSL_OP_SINGLE_DH_USE | SSL_OP_NO_SSLv2 |
++                          SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | 
SSL_OP_NO_TLSv1_1 |
++                          SSL_OP_NO_COMPRESSION);
+       SSL_CTX_set_mode(newctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
+       SSL_CTX_set_verify(newctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
+                          Verify_openssl);
+@@ -362,6 +407,9 @@
+               goto out;
+       }
+ 
++      if (!ConnSSL_SetVerifyProperties_gnutls())
++              goto out;
++
+       Log(LOG_INFO, "GnuTLS %s initialized.", gnutls_check_version(NULL));
+       initialized = true;
+       return true;
+@@ -374,6 +422,37 @@
+ 
+ #ifdef HAVE_LIBGNUTLS
+ static bool
++ConnSSL_SetVerifyProperties_gnutls(void)
++{
++      int err;
++
++      if (!Conf_SSLOptions.CAFile)
++              return true;
++
++      err = gnutls_certificate_set_x509_trust_file(x509_cred,
++                                                   Conf_SSLOptions.CAFile,
++                                                   GNUTLS_X509_FMT_PEM);
++      if (err < 0) {
++              Log(LOG_ERR, "Failed to load x509 trust file %s: %s",
++                  Conf_SSLOptions.CAFile, gnutls_strerror(err));
++              return false;
++      }
++      if (Conf_SSLOptions.CRLFile) {
++              err =
++                  gnutls_certificate_set_x509_crl_file(x509_cred,
++                                                       
Conf_SSLOptions.CRLFile,
++                                                       GNUTLS_X509_FMT_PEM);
++              if (err < 0) {
++                      Log(LOG_ERR, "Failed to load x509 crl file %s: %s",
++                          Conf_SSLOptions.CRLFile, gnutls_strerror(err));
++                      return false;
++              }
++      }
++      return true;
++}
++
++
++static bool
+ ConnSSL_LoadServerKey_gnutls(void)
+ {
+       int err;
+@@ -459,6 +538,56 @@
+ }
+ 
+ 
++static bool
++ConnSSL_SetVerifyProperties_openssl(SSL_CTX * ctx)
++{
++      X509_STORE *store = NULL;
++      X509_LOOKUP *lookup;
++      int verify_flags = SSL_VERIFY_PEER;
++      bool ret = false;
++
++      if (!Conf_SSLOptions.CAFile)
++              return true;
++
++      if (SSL_CTX_load_verify_locations(ctx, Conf_SSLOptions.CAFile, NULL) !=
++          1) {
++              LogOpenSSLError("SSL_CTX_load_verify_locations", NULL);
++              goto out;
++      }
++
++      if (Conf_SSLOptions.CRLFile) {
++              X509_VERIFY_PARAM *param = X509_VERIFY_PARAM_new();
++              X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
++              SSL_CTX_set1_param(ctx, param);
++
++              store = SSL_CTX_get_cert_store(ctx);
++              assert(store);
++              lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
++              if (!lookup) {
++                      LogOpenSSLError("X509_STORE_add_lookup",
++                                      Conf_SSLOptions.CRLFile);
++                      goto out;
++              }
++
++              if (X509_load_crl_file
++                  (lookup, Conf_SSLOptions.CRLFile, X509_FILETYPE_PEM) != 1) {
++                      LogOpenSSLError("X509_load_crl_file",
++                                      Conf_SSLOptions.CRLFile);
++                      goto out;
++              }
++      }
++
++      SSL_CTX_set_verify(ctx, verify_flags, Verify_openssl);
++      SSL_CTX_set_verify_depth(ctx, MAX_CERT_CHAIN_LENGTH);
++      ret = true;
++out:
++      if (Conf_SSLOptions.CRLFile)
++              free(Conf_SSLOptions.CRLFile);
++      Conf_SSLOptions.CRLFile = NULL;
++      return ret;
++}
++
++
+ #endif
+ static bool
+ ConnSSL_Init_SSL(CONNECTION *c)
+@@ -525,7 +654,7 @@
+ 
+ 
+ bool
+-ConnSSL_PrepareConnect(CONNECTION *c, UNUSED CONF_SERVER *s)
++ConnSSL_PrepareConnect(CONNECTION * c, CONF_SERVER * s)
+ {
+       bool ret;
+ #ifdef HAVE_LIBGNUTLS
+@@ -536,7 +665,7 @@
+               Log(LOG_ERR, "Failed to initialize new SSL session: %s",
+                   gnutls_strerror(err));
+               return false;
+-        }
++      }
+ #endif
+       ret = ConnSSL_Init_SSL(c);
+       if (!ret)
+@@ -544,7 +673,23 @@
+       Conn_OPTION_ADD(c, CONN_SSL_CONNECT);
+ #ifdef HAVE_LIBSSL
+       assert(c->ssl_state.ssl);
+-      SSL_set_verify(c->ssl_state.ssl, SSL_VERIFY_NONE, NULL);
++      if (s->SSLVerify) {
++              X509_VERIFY_PARAM *param = NULL;
++              param = SSL_get0_param(c->ssl_state.ssl);
++              X509_VERIFY_PARAM_set_hostflags(param,
++                                              
X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
++Log(LOG_ERR, "DEBUG: Setting up hostname verification for '%s'", s->host);
++              int err = X509_VERIFY_PARAM_set1_host(param, s->host, 0);
++              if (err != 1) {
++                      Log(LOG_ERR,
++                          "Cannot set up hostname verification for '%s': %u",
++                          s->host, err);
++                      return false;
++              }
++              SSL_set_verify(c->ssl_state.ssl, SSL_VERIFY_PEER,
++                             Verify_openssl);
++      } else
++              SSL_set_verify(c->ssl_state.ssl, SSL_VERIFY_NONE, NULL);
+ #endif
+       return true;
+ }
+@@ -643,18 +788,102 @@
+ }
+ 
+ 
++#ifdef HAVE_LIBGNUTLS
++static void *
++LogMalloc(size_t s)
++{
++      void *mem = malloc(s);
++      if (!mem)
++              Log(LOG_ERR, "Out of memory: Could not allocate %lu byte",
++                  (unsigned long)s);
++      return mem;
++}
++
++
++static void
++LogGnuTLS_CertInfo(int level, gnutls_x509_crt_t cert, const char *msg)
++{
++      char *dn, *issuer_dn;
++      size_t size = 0;
++      int err = gnutls_x509_crt_get_dn(cert, NULL, &size);
++      if (size == 0) {
++              Log(LOG_ERR, "gnutls_x509_crt_get_dn: size == 0");
++              return;
++      }
++      if (err && err != GNUTLS_E_SHORT_MEMORY_BUFFER)
++              goto err_crt_get;
++      dn = LogMalloc(size);
++      if (!dn)
++              return;
++      err = gnutls_x509_crt_get_dn(cert, dn, &size);
++      if (err)
++              goto err_crt_get;
++      gnutls_x509_crt_get_issuer_dn(cert, NULL, &size);
++      assert(size);
++      issuer_dn = LogMalloc(size);
++      if (!issuer_dn) {
++              Log(level, "%s: Distinguished Name: %s", msg, dn);
++              free(dn);
++              return;
++      }
++      gnutls_x509_crt_get_issuer_dn(cert, issuer_dn, &size);
++      Log(level, "%s: Distinguished Name: \"%s\", Issuer \"%s\"", msg, dn,
++          issuer_dn);
++      free(dn);
++      free(issuer_dn);
++      return;
++
++      err_crt_get:
++      Log(LOG_ERR, "gnutls_x509_crt_get_dn: %s", gnutls_strerror(err));
++      return;
++}
++#endif
++
++
+ static void
+-ConnSSL_LogCertInfo( CONNECTION *c )
++ConnSSL_LogCertInfo( CONNECTION * c, bool connect)
+ {
++      bool cert_seen = false, cert_ok = false;
++      char msg[128];
+ #ifdef HAVE_LIBSSL
++      const char *comp_alg = "no compression";
++      const void *comp;
++      X509 *peer_cert = NULL;
+       SSL *ssl = c->ssl_state.ssl;
+ 
+       assert(ssl);
+ 
+-      Log(LOG_INFO, "Connection %d: initialized %s using cipher %s.",
+-              c->sock, SSL_get_version(ssl), SSL_get_cipher(ssl));
++      comp = SSL_get_current_compression(ssl);
++      if (comp)
++              comp_alg = SSL_COMP_get_name(comp);
++      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) {
++              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;
++
++                      Log(LOG_ERR, "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);
++
++              X509_free(peer_cert);
++      }
+ #endif
+ #ifdef HAVE_LIBGNUTLS
++      unsigned int status;
++      gnutls_credentials_type_t cred;
+       gnutls_session_t sess = c->ssl_state.gnutls_session;
+       gnutls_cipher_algorithm_t cipher = gnutls_cipher_get(sess);
+ 
+@@ -663,7 +892,81 @@
+           gnutls_protocol_get_name(gnutls_protocol_get_version(sess)),
+           gnutls_cipher_get_name(cipher),
+           gnutls_mac_get_name(gnutls_mac_get(sess)));
++      cred = gnutls_auth_get_type(c->ssl_state.gnutls_session);
++      if (cred == GNUTLS_CRD_CERTIFICATE && connect) {
++              cert_seen = true;
++              int verify =
++                  gnutls_certificate_verify_peers2(c->
++                                                   ssl_state.gnutls_session,
++                                                   &status);
++Log(LOG_ERR, "DEBUG: verify = %d", verify);
++              if (verify < 0) {
++                      Log(LOG_ERR,
++                          "gnutls_certificate_verify_peers2 failed: %s",
++                          gnutls_strerror(verify));
++                      goto done_cn_validation;
++              } else if (status) {
++                      gnutls_datum_t out;
++
++                      if (gnutls_certificate_verification_status_print
++                          (status, gnutls_certificate_type_get(sess), &out,
++                           0) == GNUTLS_E_SUCCESS) {
++                              Log(LOG_ERR,
++                                  "Certificate validation failed: %s",
++                                  out.data);
++                              gnutls_free(out.data);
++                      }
++              }
++Log(LOG_ERR, "DEBUG: status = %d", status);
++
++              gnutls_x509_crt_t cert;
++              unsigned cert_list_size;
++              const gnutls_datum_t *cert_list =
++                  gnutls_certificate_get_peers(sess, &cert_list_size);
++              if (!cert_list || cert_list_size == 0) {
++                      Log(LOG_ERR, "No certificates found");
++                      goto done_cn_validation;
++              }
++              int err = gnutls_x509_crt_init(&cert);
++              if (err < 0) {
++                      Log(LOG_ERR,
++                          "Failed to initialize x509 certificate: %s",
++                          gnutls_strerror(err));
++                      goto done_cn_validation;
++              }
++              err = gnutls_x509_crt_import(cert, cert_list,
++                                         GNUTLS_X509_FMT_DER);
++              if (err < 0) {
++                      Log(LOG_ERR, "Failed to parse the certificate: %s",
++                          gnutls_strerror(err));
++                      goto done_cn_validation;
++              }
++              err = gnutls_x509_crt_check_hostname(cert, c->host);
++              if (err == 0)
++                      Log(LOG_ERR,
++                          "Failed to verify the hostname, expected \"%s\"",
++                          c->host);
++              else
++                      cert_ok = verify == 0 && status == 0;
++
++              snprintf(msg, sizeof(msg), "%svalid peer certificate",
++                      cert_ok ? "" : "in");
++              LogGnuTLS_CertInfo(cert_ok ? LOG_DEBUG : LOG_ERR, cert, msg);
++
++              gnutls_x509_crt_deinit(cert);
++done_cn_validation:
++              ;
++      }
+ #endif
++      /*
++       * can be used later to check if connection was authenticated, e.g.
++       * if inbound connection tries to register itself as server.
++       * Could also restrict /OPER to authenticated connections, etc.
++       */
++      if (cert_ok)
++              Conn_OPTION_ADD(c, CONN_SSL_PEERCERT_OK);
++      if (!cert_seen)
++              Log(LOG_INFO, "Peer did not present a certificate");
+ }
+ 
+ 
+@@ -802,7 +1105,7 @@
+       (void)ConnSSL_InitCertFp(c);
+ 
+       Conn_OPTION_DEL(c, 
(CONN_SSL_WANT_WRITE|CONN_SSL_WANT_READ|CONN_SSL_CONNECT));
+-      ConnSSL_LogCertInfo(c);
++      ConnSSL_LogCertInfo(c, connect);
+ 
+       Conn_StartLogin(CONNECTION2ID(c));
+       return 1;
+--- a/src/ngircd/conn.c
++++ b/src/ngircd/conn.c
+@@ -2506,6 +2506,7 @@
+ cb_connserver_login_ssl(int sock, short unused)
+ {
+       CONN_ID idx = Socket2Index(sock);
++      int serveridx;
+ 
+       (void) unused;
+ 
+@@ -2524,10 +2525,30 @@
+                       return;
+       }
+ 
++      serveridx = Conf_GetServer(idx);
++      assert(serveridx >= 0);
++      if (serveridx < 0)
++              goto err;
++
+       Log( LOG_INFO, "SSL connection %d with \"%s:%d\" established.", idx,
+           My_Connections[idx].host, Conf_Server[Conf_GetServer( idx )].port );
+ 
++      if (!Conn_OPTION_ISSET(&My_Connections[idx], CONN_SSL_PEERCERT_OK)) {
++              if (Conf_Server[serveridx].SSLVerify) {
++                      Log(LOG_ERR,
++                              "SSLVerify enabled for %d, but peer certificate 
check failed",
++                              idx);
++                      goto err;
++              }
++              Log(LOG_WARNING,
++                      "Peer certificate check failed for %d, but SSLVerify is 
disabled, continuing",
++                      idx);
++      }
+       server_login(idx);
++      return;
++      err:
++      Log(LOG_ERR, "SSL connection on socket %d failed!", sock);
++      Conn_Close(idx, "Can't connect!", NULL, false);
+ }
+ 
+ 
+--- a/src/ngircd/conn.h
++++ b/src/ngircd/conn.h
+@@ -40,7 +40,8 @@
+ #define CONN_SSL              32      /* this connection is SSL encrypted */
+ #define CONN_SSL_WANT_WRITE   64      /* SSL/TLS library needs to write 
protocol data */
+ #define CONN_SSL_WANT_READ    128     /* SSL/TLS library needs to read 
protocol data */
+-#define CONN_SSL_FLAGS_ALL    
(CONN_SSL_CONNECT|CONN_SSL|CONN_SSL_WANT_WRITE|CONN_SSL_WANT_READ)
++#define CONN_SSL_PEERCERT_OK  256     /* peer presented a valid certificate 
(used to check inbound server auth */
++#define CONN_SSL_FLAGS_ALL    
(CONN_SSL_CONNECT|CONN_SSL|CONN_SSL_WANT_WRITE|CONN_SSL_WANT_READ|CONN_SSL_PEERCERT_OK)
+ #endif
+ typedef int CONN_ID;
+ 
diff -Nru 
ngircd-25/debian/patches/0003-S2S-TLS-Add-missing-CAFile-and-CRLFile-options-to-co.patch
 
ngircd-25/debian/patches/0003-S2S-TLS-Add-missing-CAFile-and-CRLFile-options-to-co.patch
--- 
ngircd-25/debian/patches/0003-S2S-TLS-Add-missing-CAFile-and-CRLFile-options-to-co.patch
    1970-01-01 01:00:00.000000000 +0100
+++ 
ngircd-25/debian/patches/0003-S2S-TLS-Add-missing-CAFile-and-CRLFile-options-to-co.patch
    2024-04-15 14:14:26.000000000 +0200
@@ -0,0 +1,28 @@
+From b50be568a0d4d67532b3539eb00908473ff6d956 Mon Sep 17 00:00:00 2001
+From: Alexander Barton <a...@barton.de>
+Date: Sat, 16 Dec 2023 16:29:05 +0100
+Subject: [PATCH 03/20] S2S-TLS: Add missing CAFile and CRLFile options to
+ "configtest" output
+
+(cherry picked from commit 5ca567a18caf699f93495ba2bc3749fb5f65383b)
+---
+ src/ngircd/conf.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/src/ngircd/conf.c
++++ b/src/ngircd/conf.c
+@@ -441,10 +441,14 @@
+ 
+ #ifdef SSL_SUPPORT
+       puts("[SSL]");
++      printf("  CAFile = %s\n", Conf_SSLOptions.CAFile
++                                      ? Conf_SSLOptions.CAFile : "");
+       printf("  CertFile = %s\n", Conf_SSLOptions.CertFile
+                                       ? Conf_SSLOptions.CertFile : "");
+       printf("  CipherList = %s\n", Conf_SSLOptions.CipherList ?
+              Conf_SSLOptions.CipherList : DEFAULT_CIPHERS);
++      printf("  CRLFile = %s\n", Conf_SSLOptions.CRLFile
++                                      ? Conf_SSLOptions.CRLFile : "");
+       printf("  DHFile = %s\n", Conf_SSLOptions.DHFile
+                                       ? Conf_SSLOptions.DHFile : "");
+       printf("  KeyFile = %s\n", Conf_SSLOptions.KeyFile
diff -Nru 
ngircd-25/debian/patches/0004-S2S-TLS-Remove-leftover-debug-messages.patch 
ngircd-25/debian/patches/0004-S2S-TLS-Remove-leftover-debug-messages.patch
--- ngircd-25/debian/patches/0004-S2S-TLS-Remove-leftover-debug-messages.patch  
1970-01-01 01:00:00.000000000 +0100
+++ ngircd-25/debian/patches/0004-S2S-TLS-Remove-leftover-debug-messages.patch  
2024-04-15 14:14:26.000000000 +0200
@@ -0,0 +1,47 @@
+From 43fdbf79dc245dba629103513ebb7db0ac4374ab Mon Sep 17 00:00:00 2001
+From: Alexander Barton <a...@barton.de>
+Date: Sat, 16 Dec 2023 16:30:06 +0100
+Subject: [PATCH 04/20] S2S-TLS: Remove leftover debug messages
+
+(cherry picked from commit 8f8bef9faee96a6033e8719fd38167017299847a)
+---
+ src/ngircd/conn-ssl.c | 7 +------
+ 1 file changed, 1 insertion(+), 6 deletions(-)
+
+--- a/src/ngircd/conn-ssl.c
++++ b/src/ngircd/conn-ssl.c
+@@ -678,7 +678,6 @@
+               param = SSL_get0_param(c->ssl_state.ssl);
+               X509_VERIFY_PARAM_set_hostflags(param,
+                                               
X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
+-Log(LOG_ERR, "DEBUG: Setting up hostname verification for '%s'", s->host);
+               int err = X509_VERIFY_PARAM_set1_host(param, s->host, 0);
+               if (err != 1) {
+                       Log(LOG_ERR,
+@@ -867,9 +866,7 @@
+                       const char *peername = SSL_get0_peername(ssl);
+                       if (peername != NULL)
+                               cert_ok = true;
+-
+-                      Log(LOG_ERR, "X509_V_OK, peername = '%s'", peername);
+-
++                      LogDebug("X509_V_OK, peername = '%s'", peername);
+               } else
+                       Log(LOG_ERR, "Certificate validation failed: %s",
+                           X509_verify_cert_error_string(err));
+@@ -899,7 +896,6 @@
+                   gnutls_certificate_verify_peers2(c->
+                                                    ssl_state.gnutls_session,
+                                                    &status);
+-Log(LOG_ERR, "DEBUG: verify = %d", verify);
+               if (verify < 0) {
+                       Log(LOG_ERR,
+                           "gnutls_certificate_verify_peers2 failed: %s",
+@@ -917,7 +913,6 @@
+                               gnutls_free(out.data);
+                       }
+               }
+-Log(LOG_ERR, "DEBUG: status = %d", status);
+ 
+               gnutls_x509_crt_t cert;
+               unsigned cert_list_size;
diff -Nru 
ngircd-25/debian/patches/0005-S2S-TLS-OpenSSL-Always-setup-host-name-verification.patch
 
ngircd-25/debian/patches/0005-S2S-TLS-OpenSSL-Always-setup-host-name-verification.patch
--- 
ngircd-25/debian/patches/0005-S2S-TLS-OpenSSL-Always-setup-host-name-verification.patch
     1970-01-01 01:00:00.000000000 +0100
+++ 
ngircd-25/debian/patches/0005-S2S-TLS-OpenSSL-Always-setup-host-name-verification.patch
     2024-04-15 14:14:26.000000000 +0200
@@ -0,0 +1,58 @@
+From 3ec63bec484149255268e691f29d4784177bc0ce Mon Sep 17 00:00:00 2001
+From: Alexander Barton <a...@barton.de>
+Date: Mon, 1 Jan 2024 19:58:35 +0100
+Subject: [PATCH 05/20] S2S-TLS/OpenSSL: Always setup host name verification
+
+Setup host name verification even when the "SSLVerify" option is
+disabled, because even then the peer can present a valid certificate and
+validation would always(!) fail because of the missing host name
+verification setup.
+
+(cherry picked from commit 84b019b11f761b71c8239d60e7f8db0b82a55df3)
+---
+ src/ngircd/conn-ssl.c | 28 +++++++++++++++-------------
+ 1 file changed, 15 insertions(+), 13 deletions(-)
+
+--- a/src/ngircd/conn-ssl.c
++++ b/src/ngircd/conn-ssl.c
+@@ -671,25 +671,27 @@
+       if (!ret)
+               return false;
+       Conn_OPTION_ADD(c, CONN_SSL_CONNECT);
++
+ #ifdef HAVE_LIBSSL
+       assert(c->ssl_state.ssl);
+-      if (s->SSLVerify) {
+-              X509_VERIFY_PARAM *param = NULL;
+-              param = SSL_get0_param(c->ssl_state.ssl);
+-              X509_VERIFY_PARAM_set_hostflags(param,
+-                                              
X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
+-              int err = X509_VERIFY_PARAM_set1_host(param, s->host, 0);
+-              if (err != 1) {
+-                      Log(LOG_ERR,
+-                          "Cannot set up hostname verification for '%s': %u",
+-                          s->host, err);
+-                      return false;
+-              }
++
++      X509_VERIFY_PARAM *param = SSL_get0_param(c->ssl_state.ssl);
++      X509_VERIFY_PARAM_set_hostflags(param, 
X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
++      int err = X509_VERIFY_PARAM_set1_host(param, s->host, 0);
++      if (err != 1) {
++              Log(LOG_ERR,
++                  "Cannot set up hostname verification for '%s': %u",
++                  s->host, err);
++              return false;
++      }
++
++      if (s->SSLVerify)
+               SSL_set_verify(c->ssl_state.ssl, SSL_VERIFY_PEER,
+                              Verify_openssl);
+-      } else
++      else
+               SSL_set_verify(c->ssl_state.ssl, SSL_VERIFY_NONE, NULL);
+ #endif
++
+       return true;
+ }
+ 
diff -Nru 
ngircd-25/debian/patches/0006-S2S-TLS-OpenSSL-Set-the-verification-flags-only-once.patch
 
ngircd-25/debian/patches/0006-S2S-TLS-OpenSSL-Set-the-verification-flags-only-once.patch
--- 
ngircd-25/debian/patches/0006-S2S-TLS-OpenSSL-Set-the-verification-flags-only-once.patch
    1970-01-01 01:00:00.000000000 +0100
+++ 
ngircd-25/debian/patches/0006-S2S-TLS-OpenSSL-Set-the-verification-flags-only-once.patch
    2024-04-15 14:14:26.000000000 +0200
@@ -0,0 +1,45 @@
+From 23c62de3fdce2833428437b2ea60b6b9ab70063c Mon Sep 17 00:00:00 2001
+From: Alexander Barton <a...@barton.de>
+Date: Tue, 2 Jan 2024 20:55:15 +0100
+Subject: [PATCH 06/20] S2S-TLS/OpenSSL: Set the verification flags only once
+
+Set the verification flags in the ConnSSL_SetVerifyProperties_openssl
+function only, don't override them in ConnSSL_InitLibrary() afterwards.
+
+No functional changes, now ConnSSL_SetVerifyProperties_openssl() sets
+exactly the parameters which ConnSSL_InitLibrary() always overwrote ...
+
+(cherry picked from commit 08647ab1e7cf0d034f2d8987a3cac3201af84e02)
+---
+ src/ngircd/conn-ssl.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+--- a/src/ngircd/conn-ssl.c
++++ b/src/ngircd/conn-ssl.c
+@@ -368,8 +368,6 @@
+                           SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | 
SSL_OP_NO_TLSv1_1 |
+                           SSL_OP_NO_COMPRESSION);
+       SSL_CTX_set_mode(newctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
+-      SSL_CTX_set_verify(newctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
+-                         Verify_openssl);
+       SSL_CTX_free(ssl_ctx);
+       ssl_ctx = newctx;
+       Log(LOG_INFO, "%s initialized.", OpenSSL_version(OPENSSL_VERSION));
+@@ -543,7 +541,6 @@
+ {
+       X509_STORE *store = NULL;
+       X509_LOOKUP *lookup;
+-      int verify_flags = SSL_VERIFY_PEER;
+       bool ret = false;
+ 
+       if (!Conf_SSLOptions.CAFile)
+@@ -577,7 +574,8 @@
+               }
+       }
+ 
+-      SSL_CTX_set_verify(ctx, verify_flags, Verify_openssl);
++      SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
++                         Verify_openssl);
+       SSL_CTX_set_verify_depth(ctx, MAX_CERT_CHAIN_LENGTH);
+       ret = true;
+ out:
diff -Nru 
ngircd-25/debian/patches/0007-S2S-TLS-OpenSSL-Fix-handling-of-certificate-informat.patch
 
ngircd-25/debian/patches/0007-S2S-TLS-OpenSSL-Fix-handling-of-certificate-informat.patch
--- 
ngircd-25/debian/patches/0007-S2S-TLS-OpenSSL-Fix-handling-of-certificate-informat.patch
    1970-01-01 01:00:00.000000000 +0100
+++ 
ngircd-25/debian/patches/0007-S2S-TLS-OpenSSL-Fix-handling-of-certificate-informat.patch
    2024-04-15 14:14:26.000000000 +0200
@@ -0,0 +1,81 @@
+From 85e0fc8580e989cb7418369f41cdae4ad240aab3 Mon Sep 17 00:00:00 2001
+From: Alexander Barton <a...@barton.de>
+Date: Tue, 2 Jan 2024 21:10:17 +0100
+Subject: [PATCH 07/20] 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!
+
+(cherry picked from commit 679505aab9fea21b27a3d4bbf99cf2a16cf3d3d5)
+---
+ src/ngircd/conn-ssl.c | 46 ++++++++++++++++++++++++++++---------------
+ 1 file changed, 30 insertions(+), 16 deletions(-)
+
+--- a/src/ngircd/conn-ssl.c
++++ b/src/ngircd/conn-ssl.c
+@@ -858,22 +858,36 @@
+       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);
+       }
+@@ -961,7 +975,7 @@
+       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.");
+ }
+ 
+ 
diff -Nru 
ngircd-25/debian/patches/0008-S2S-TLS-OpenSSL-Postpone-verification-of-TLS-session.patch
 
ngircd-25/debian/patches/0008-S2S-TLS-OpenSSL-Postpone-verification-of-TLS-session.patch
--- 
ngircd-25/debian/patches/0008-S2S-TLS-OpenSSL-Postpone-verification-of-TLS-session.patch
    1970-01-01 01:00:00.000000000 +0100
+++ 
ngircd-25/debian/patches/0008-S2S-TLS-OpenSSL-Postpone-verification-of-TLS-session.patch
    2024-04-15 14:14:26.000000000 +0200
@@ -0,0 +1,72 @@
+From dc75413ffbb588e9caf25f9978fbaf624491e2ba Mon Sep 17 00:00:00 2001
+From: Alexander Barton <a...@barton.de>
+Date: Tue, 2 Jan 2024 22:02:46 +0100
+Subject: [PATCH 08/20] S2S-TLS/OpenSSL: Postpone verification of TLS session
+ right before server handshake
+
+The verify callback in OpenSSL is called pretty early, and at that time
+it is not possible yet to check which connection it belongs to, and some
+connections may have relaxed requirements.
+
+So always return success in the Verify_openssl() callback, and postpone
+validation of the TLS session until starting the server handshake in
+cb_connserver_login_ssl(), when we know which server this connection
+belongs to and which options (like "SSLVerify") are in effect.
+
+The code doing this was already present in cb_connserver_login_ssl(),
+but this patch adds a more prominent comment to the function.
+
+(cherry picked from commit 3db3b47fc7172a69b7d99d66eddb07a323dc6e74)
+---
+ src/ngircd/conn-ssl.c | 21 +++++++++++++++------
+ src/ngircd/conn.c     |  7 +++++++
+ 2 files changed, 22 insertions(+), 6 deletions(-)
+
+--- a/src/ngircd/conn-ssl.c
++++ b/src/ngircd/conn-ssl.c
+@@ -203,14 +203,23 @@
+ static int
+ Verify_openssl(int preverify_ok, X509_STORE_CTX * ctx)
+ {
+-      int err;
+-
++#ifdef DEBUG
+       if (!preverify_ok) {
+-              err = X509_STORE_CTX_get_error(ctx);
+-              Log(LOG_ERR, "Certificate validation failed: %s",
+-                  X509_verify_cert_error_string(err));
++              int err = X509_STORE_CTX_get_error(ctx);
++              LogDebug("Certificate validation failed: %s",
++                       X509_verify_cert_error_string(err));
+       }
+-      return preverify_ok;
++#else
++      (void)preverify_ok;
++      (void)ctx;
++#endif
++
++      /* Always(!) return success as we have to deal with invalid
++       * (self-signed, expired, ...) client certificates and with invalid
++       * server certificates when "SSLVerify" is disabled, which we don't
++       * know at this stage. Therefore we postpone this check, it will be
++       * (and has to be!) handled in cb_connserver_login_ssl(). */
++      return 1;
+ }
+ #endif
+ 
+--- a/src/ngircd/conn.c
++++ b/src/ngircd/conn.c
+@@ -2499,6 +2499,13 @@
+ /**
+  * IO callback for new outgoing SSL-enabled server connections.
+  *
++ * IMPORTANT: The SSL session has been validated before, but all errors have
++ * been ignored so far! The reason for this is that the generic SSL code has 
no
++ * idea if the new session actually belongs to a server, as this only becomes
++ * clear when the remote peer sends its PASS command (and we have to handle
++ * invalid client certificates!). Therefore, it is important to check the
++ * status of the SSL session first before continuing the server handshake 
here!
++ *
+  * @param sock                Socket descriptor.
+  * @param unused      (ignored IO specification)
+  */
diff -Nru 
ngircd-25/debian/patches/0009-S2S-TLS-OpenSSL-Streamline-logging.patch 
ngircd-25/debian/patches/0009-S2S-TLS-OpenSSL-Streamline-logging.patch
--- ngircd-25/debian/patches/0009-S2S-TLS-OpenSSL-Streamline-logging.patch      
1970-01-01 01:00:00.000000000 +0100
+++ ngircd-25/debian/patches/0009-S2S-TLS-OpenSSL-Streamline-logging.patch      
2024-04-15 14:14:26.000000000 +0200
@@ -0,0 +1,93 @@
+From 36ba9c20f4962b207531238ea2a0935ee9122547 Mon Sep 17 00:00:00 2001
+From: Alexander Barton <a...@barton.de>
+Date: Tue, 2 Jan 2024 22:13:42 +0100
+Subject: [PATCH 09/20] S2S-TLS/OpenSSL: Streamline logging
+
+This includes simplifying cb_connserver_login_ssl() a bit, we do not
+have to code for invalid state which was ruled out by an assert() and
+therefore can get rid of the goto altogether (and don't log the same
+error twice with different messages).
+
+(cherry picked from commit 02bb99b0242ade8af78f957aa1657561374ef1d6)
+---
+ src/ngircd/conn-ssl.c | 15 +++++++++------
+ src/ngircd/conn.c     | 25 +++++++++++--------------
+ 2 files changed, 20 insertions(+), 20 deletions(-)
+
+--- a/src/ngircd/conn-ssl.c
++++ b/src/ngircd/conn-ssl.c
+@@ -147,13 +147,13 @@
+       mem = BIO_new(BIO_s_mem());
+       if (!mem)
+               return;
+-      X509_NAME_print_ex(mem, X509_get_subject_name(cert), 4,
++      X509_NAME_print_ex(mem, X509_get_subject_name(cert), 0,
+                          XN_FLAG_ONELINE);
+-      X509_NAME_print_ex(mem, X509_get_issuer_name(cert), 4, XN_FLAG_ONELINE);
++      X509_NAME_print_ex(mem, X509_get_issuer_name(cert), 2, XN_FLAG_ONELINE);
+       if (BIO_write(mem, "", 1) == 1) {
+               len = BIO_get_mem_data(mem, &memptr);
+               if (memptr && len > 0)
+-                      Log(level, "%s: \"%s\"", msg, memptr);
++                      Log(level, "%s: \"%s\".", msg, memptr);
+       }
+       (void)BIO_set_close(mem, BIO_CLOSE);
+       BIO_free(mem);
+@@ -755,9 +755,12 @@
+                                   "SSL error, client disconnected [in %s()]!",
+                                   fname);
+                               break;
+-                      case -1:        /* low level socket I/O error, check 
errno */
+-                              Log(LOG_ERR, "SSL error: %s [in %s()]!",
+-                                  strerror(real_errno), fname);
++                      case -1:
++                              /* Low level socket I/O error, check errno. But
++                               * we don't need to log this here, the generic
++                               * connection layer will take care of it. */
++                              LogDebug("SSL error: %s [in %s()]!",
++                                       strerror(real_errno), fname);
+                       }
+               }
+               break;
+--- a/src/ngircd/conn.c
++++ b/src/ngircd/conn.c
+@@ -2534,28 +2534,25 @@
+ 
+       serveridx = Conf_GetServer(idx);
+       assert(serveridx >= 0);
+-      if (serveridx < 0)
+-              goto err;
+-
+-      Log( LOG_INFO, "SSL connection %d with \"%s:%d\" established.", idx,
+-          My_Connections[idx].host, Conf_Server[Conf_GetServer( idx )].port );
+ 
++      /* The SSL handshake is done, but validation results were ignored so
++       * far, so let's see where we are: */
++      LogDebug("SSL handshake on socket %d done.", idx);
+       if (!Conn_OPTION_ISSET(&My_Connections[idx], CONN_SSL_PEERCERT_OK)) {
+               if (Conf_Server[serveridx].SSLVerify) {
+                       Log(LOG_ERR,
+-                              "SSLVerify enabled for %d, but peer certificate 
check failed",
+-                              idx);
+-                      goto err;
++                              "Peer certificate check failed for \"%s\" on 
connection %d!",
++                              My_Connections[idx].host, idx);
++                      Conn_Close(idx, "Valid certificate required",
++                                 NULL, false);
++                      return;
+               }
+               Log(LOG_WARNING,
+-                      "Peer certificate check failed for %d, but SSLVerify is 
disabled, continuing",
+-                      idx);
++                      "Peer certificate check failed for \"%s\" on connection 
%d, but \"SSLVerify\" is disabled. Continuing ...",
++                      My_Connections[idx].host, idx);
+       }
++      LogDebug("Server certificate accepted, continuing server login ...");
+       server_login(idx);
+-      return;
+-      err:
+-      Log(LOG_ERR, "SSL connection on socket %d failed!", sock);
+-      Conn_Close(idx, "Can't connect!", NULL, false);
+ }
+ 
+ 
diff -Nru 
ngircd-25/debian/patches/0010-S2S-TLS-Fix-formatting-and-sort-new-SSL-options-in-n.patch
 
ngircd-25/debian/patches/0010-S2S-TLS-Fix-formatting-and-sort-new-SSL-options-in-n.patch
--- 
ngircd-25/debian/patches/0010-S2S-TLS-Fix-formatting-and-sort-new-SSL-options-in-n.patch
    1970-01-01 01:00:00.000000000 +0100
+++ 
ngircd-25/debian/patches/0010-S2S-TLS-Fix-formatting-and-sort-new-SSL-options-in-n.patch
    2024-04-15 14:14:26.000000000 +0200
@@ -0,0 +1,38 @@
+From 42e78c79e7bf8eda20bf06f4ca8aa98087d7f778 Mon Sep 17 00:00:00 2001
+From: Alexander Barton <a...@barton.de>
+Date: Wed, 3 Jan 2024 15:40:58 +0100
+Subject: [PATCH 10/20] S2S-TLS: Fix formatting and sort new SSL options in
+ ngircd.conf manual page
+
+(cherry picked from commit 58ee4df2ae2e4e59ae8909b69670825229158da8)
+---
+ man/ngircd.conf.5.tmpl | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/man/ngircd.conf.5.tmpl
++++ b/man/ngircd.conf.5.tmpl
+@@ -385,13 +385,10 @@
+ section. Please note that this whole section is only recognized by ngIRCd
+ when it is compiled with support for SSL using OpenSSL or GnuTLS!
+ .TP
+-\fBCAFile (string)\fR
++\fBCAFile\fR (string)
+ Filename pointing to the Trusted CA Certificates. This is required for
+ verifying peer certificates.
+ .TP
+-\fBCRLFile (string)\fR
+-Filename of Certificate Revocation List.
+-.TP
+ \fBCertFile\fR (string)
+ SSL Certificate file of the private server key.
+ .TP
+@@ -401,6 +398,9 @@
+ Please see 'man 1ssl ciphers' (OpenSSL) and 'man 3 gnutls_priority_init'
+ (GnuTLS) for details.
+ .TP
++\fBCRLFile\fR (string)
++Filename of Certificate Revocation List.
++.TP
+ \fBDHFile\fR (string)
+ Name of the Diffie-Hellman Parameter file. Can be created with GnuTLS
+ "certtool \-\-generate-dh-params" or "openssl dhparam". If this file is not
diff -Nru 
ngircd-25/debian/patches/0011-S2S-TLS-MAX_CERT_CHAIN_LENGTH-is-only-used-by-OpenSS.patch
 
ngircd-25/debian/patches/0011-S2S-TLS-MAX_CERT_CHAIN_LENGTH-is-only-used-by-OpenSS.patch
--- 
ngircd-25/debian/patches/0011-S2S-TLS-MAX_CERT_CHAIN_LENGTH-is-only-used-by-OpenSS.patch
    1970-01-01 01:00:00.000000000 +0100
+++ 
ngircd-25/debian/patches/0011-S2S-TLS-MAX_CERT_CHAIN_LENGTH-is-only-used-by-OpenSS.patch
    2024-04-15 14:14:26.000000000 +0200
@@ -0,0 +1,30 @@
+From 6bfa7f43074d9167993d2e3312161a2c71cb2061 Mon Sep 17 00:00:00 2001
+From: Alexander Barton <a...@barton.de>
+Date: Fri, 5 Jan 2024 22:17:12 +0100
+Subject: [PATCH 11/20] S2S-TLS: MAX_CERT_CHAIN_LENGTH is only used by OpenSSL
+
+(cherry picked from commit c8589e9890742c377c78595131ef1cdc8d784c66)
+---
+ src/ngircd/conn-ssl.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/src/ngircd/conn-ssl.c
++++ b/src/ngircd/conn-ssl.c
+@@ -45,6 +45,8 @@
+ #include <openssl/dh.h>
+ #include <openssl/x509v3.h>
+ 
++#define MAX_CERT_CHAIN_LENGTH 10      /* XXX: do not hardcode */
++
+ static SSL_CTX * ssl_ctx;
+ static DH *dh_params;
+ 
+@@ -52,8 +54,6 @@
+ static bool ConnSSL_SetVerifyProperties_openssl PARAMS((SSL_CTX * c));
+ #endif
+ 
+-#define MAX_CERT_CHAIN_LENGTH 10      /* XXX: do not hardcode */
+-
+ #ifdef HAVE_LIBGNUTLS
+ #include <sys/types.h>
+ #include <sys/stat.h>
diff -Nru 
ngircd-25/debian/patches/0013-S2S-TLS-GnuTLS-Fix-handling-of-certificate-informati.patch
 
ngircd-25/debian/patches/0013-S2S-TLS-GnuTLS-Fix-handling-of-certificate-informati.patch
--- 
ngircd-25/debian/patches/0013-S2S-TLS-GnuTLS-Fix-handling-of-certificate-informati.patch
    1970-01-01 01:00:00.000000000 +0100
+++ 
ngircd-25/debian/patches/0013-S2S-TLS-GnuTLS-Fix-handling-of-certificate-informati.patch
    2024-04-15 14:14:26.000000000 +0200
@@ -0,0 +1,118 @@
+From 4384e600b9d709551deb8e2c93754f5af1a24161 Mon Sep 17 00:00:00 2001
+From: Alexander Barton <a...@barton.de>
+Date: Fri, 5 Jan 2024 22:29:40 +0100
+Subject: [PATCH 13/20] S2S-TLS/GnuTLS: 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.
+
+This change is for GnuTLS and similar to what was implemented in commit
+for OpenSSL in "S2S-TLS/OpenSSL: Fix handling of certificate information
+for incoming connections".
+
+(cherry picked from commit 509ff6032686662328f4ecb0c5c287a34e929c53)
+---
+ src/ngircd/conn-ssl.c | 75 ++++++++++++++++++++++++-------------------
+ 1 file changed, 42 insertions(+), 33 deletions(-)
+
+--- a/src/ngircd/conn-ssl.c
++++ b/src/ngircd/conn-ssl.c
+@@ -667,6 +667,7 @@
+ #ifdef HAVE_LIBGNUTLS
+       int err;
+ 
++      (void)s;
+       err = gnutls_init(&c->ssl_state.gnutls_session, GNUTLS_CLIENT);
+       if (err) {
+               Log(LOG_ERR, "Failed to initialize new SSL session: %s",
+@@ -916,29 +917,8 @@
+           gnutls_cipher_get_name(cipher),
+           gnutls_mac_get_name(gnutls_mac_get(sess)));
+       cred = gnutls_auth_get_type(c->ssl_state.gnutls_session);
+-      if (cred == GNUTLS_CRD_CERTIFICATE && connect) {
++      if (cred == GNUTLS_CRD_CERTIFICATE) {
+               cert_seen = true;
+-              int verify =
+-                  gnutls_certificate_verify_peers2(c->
+-                                                   ssl_state.gnutls_session,
+-                                                   &status);
+-              if (verify < 0) {
+-                      Log(LOG_ERR,
+-                          "gnutls_certificate_verify_peers2 failed: %s",
+-                          gnutls_strerror(verify));
+-                      goto done_cn_validation;
+-              } else if (status) {
+-                      gnutls_datum_t out;
+-
+-                      if (gnutls_certificate_verification_status_print
+-                          (status, gnutls_certificate_type_get(sess), &out,
+-                           0) == GNUTLS_E_SUCCESS) {
+-                              Log(LOG_ERR,
+-                                  "Certificate validation failed: %s",
+-                                  out.data);
+-                              gnutls_free(out.data);
+-                      }
+-              }
+ 
+               gnutls_x509_crt_t cert;
+               unsigned cert_list_size;
+@@ -962,17 +942,46 @@
+                           gnutls_strerror(err));
+                       goto done_cn_validation;
+               }
+-              err = gnutls_x509_crt_check_hostname(cert, c->host);
+-              if (err == 0)
+-                      Log(LOG_ERR,
+-                          "Failed to verify the hostname, expected \"%s\"",
+-                          c->host);
+-              else
+-                      cert_ok = verify == 0 && status == 0;
+-
+-              snprintf(msg, sizeof(msg), "%svalid peer certificate",
+-                      cert_ok ? "" : "in");
+-              LogGnuTLS_CertInfo(cert_ok ? LOG_DEBUG : LOG_ERR, cert, msg);
++
++              if (connect) {
++                      int verify =
++                          gnutls_certificate_verify_peers2(c->
++                                                           
ssl_state.gnutls_session,
++                                                           &status);
++                      if (verify < 0) {
++                              Log(LOG_ERR,
++                                  "gnutls_certificate_verify_peers2 failed: 
%s",
++                                  gnutls_strerror(verify));
++                              goto done_cn_validation;
++                      } else if (status) {
++                              gnutls_datum_t out;
++
++                              if (gnutls_certificate_verification_status_print
++                                  (status, gnutls_certificate_type_get(sess), 
&out,
++                                   0) == GNUTLS_E_SUCCESS) {
++                                      Log(LOG_ERR,
++                                          "Certificate validation failed: %s",
++                                          out.data);
++                                      gnutls_free(out.data);
++                              }
++                      }
++
++                      err = gnutls_x509_crt_check_hostname(cert, c->host);
++                      if (err == 0)
++                              Log(LOG_ERR,
++                                  "Failed to verify the hostname, expected 
\"%s\"",
++                                  c->host);
++                      else
++                              cert_ok = verify == 0 && status == 0;
++
++                      snprintf(msg, sizeof(msg), "Got %svalid server 
certificate",
++                              cert_ok ? "" : "in");
++                      LogGnuTLS_CertInfo(LOG_INFO, cert, msg);
++              } else {
++                      /* Incoming connection. Please see comments for 
OpenSSL! */
++                      LogGnuTLS_CertInfo(LOG_INFO, cert,
++                                          "Got unchecked peer certificate");
++              }
+ 
+               gnutls_x509_crt_deinit(cert);
+ done_cn_validation:
diff -Nru ngircd-25/debian/patches/0014-S2S-TLS-GnuTLS-Streamline-logging.patch 
ngircd-25/debian/patches/0014-S2S-TLS-GnuTLS-Streamline-logging.patch
--- ngircd-25/debian/patches/0014-S2S-TLS-GnuTLS-Streamline-logging.patch       
1970-01-01 01:00:00.000000000 +0100
+++ ngircd-25/debian/patches/0014-S2S-TLS-GnuTLS-Streamline-logging.patch       
2024-04-15 14:14:26.000000000 +0200
@@ -0,0 +1,49 @@
+From 8a4ee38cb2c70b25aa5866eee5749807fd2b79b8 Mon Sep 17 00:00:00 2001
+From: Alexander Barton <a...@barton.de>
+Date: Fri, 5 Jan 2024 22:31:32 +0100
+Subject: [PATCH 14/20] S2S-TLS/GnuTLS: Streamline logging
+
+(cherry picked from commit 663972c88d3ae3e3226fe6f95ca1113694ce0618)
+---
+ src/ngircd/conn-ssl.c | 12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+--- a/src/ngircd/conn-ssl.c
++++ b/src/ngircd/conn-ssl.c
+@@ -789,8 +789,10 @@
+       default:
+               assert(code < 0);
+               if (gnutls_error_is_fatal(code)) {
+-                      Log(LOG_ERR, "SSL error: %s [%s].",
+-                          gnutls_strerror(code), fname);
++                      /* We don't need to log this here, the generic
++                       * connection layer will take care of it. */
++                      LogDebug("SSL error: %s [%s].",
++                               gnutls_strerror(code), fname);
+                       ConnSSL_Free(c);
+                       return -1;
+               }
+@@ -834,12 +836,12 @@
+       assert(size);
+       issuer_dn = LogMalloc(size);
+       if (!issuer_dn) {
+-              Log(level, "%s: Distinguished Name: %s", msg, dn);
++              Log(level, "%s: Distinguished Name \"%s\".", msg, dn);
+               free(dn);
+               return;
+       }
+       gnutls_x509_crt_get_issuer_dn(cert, issuer_dn, &size);
+-      Log(level, "%s: Distinguished Name: \"%s\", Issuer \"%s\"", msg, dn,
++      Log(level, "%s: Distinguished Name \"%s\", Issuer \"%s\".", msg, dn,
+           issuer_dn);
+       free(dn);
+       free(issuer_dn);
+@@ -899,7 +901,7 @@
+                        * hand we want client certificates, for example for
+                        * "CertFP" authentication with services ... */
+                       LogOpenSSL_CertInfo(LOG_INFO, peer_cert,
+-                                          "Got unchecked client certificate");
++                                          "Got unchecked peer certificate");
+               }
+ 
+               X509_free(peer_cert);
diff -Nru 
ngircd-25/debian/patches/0015-S2S-TLS-Verify-the-TLS-certificates-by-default.patch
 
ngircd-25/debian/patches/0015-S2S-TLS-Verify-the-TLS-certificates-by-default.patch
--- 
ngircd-25/debian/patches/0015-S2S-TLS-Verify-the-TLS-certificates-by-default.patch
  1970-01-01 01:00:00.000000000 +0100
+++ 
ngircd-25/debian/patches/0015-S2S-TLS-Verify-the-TLS-certificates-by-default.patch
  2024-04-15 14:14:26.000000000 +0200
@@ -0,0 +1,27 @@
+From e622ae80a336ab1be294c7cc65cf538e50e4d1c8 Mon Sep 17 00:00:00 2001
+From: Alexander Barton <a...@barton.de>
+Date: Sat, 6 Jan 2024 15:55:54 +0100
+Subject: [PATCH 15/20] S2S-TLS: Verify the TLS certificates by default
+
+This is already mentioned as the default in the manual page and the
+sample configuration file, but was actually not enabled in the code!
+
+(cherry picked from commit 180e2ec1359378172135472148c99a2d14e873cc)
+---
+ src/ngircd/conf.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/src/ngircd/conf.c
++++ b/src/ngircd/conf.c
+@@ -2467,6 +2467,11 @@
+       Proc_InitStruct(&Server->res_stat);
+       Server->conn_id = NONE;
+       memset(&Server->bind_addr, 0, sizeof(Server->bind_addr));
++
++#ifdef SSL_SUPPORT
++      /* Verify SSL connections by default! */
++      Server->SSLVerify = true;
++#endif
+ }
+ 
+ /* -eof- */
diff -Nru 
ngircd-25/debian/patches/0016-S2S-TLS-GnuTLS-Fix-handling-of-connections-without-p.patch
 
ngircd-25/debian/patches/0016-S2S-TLS-GnuTLS-Fix-handling-of-connections-without-p.patch
--- 
ngircd-25/debian/patches/0016-S2S-TLS-GnuTLS-Fix-handling-of-connections-without-p.patch
    1970-01-01 01:00:00.000000000 +0100
+++ 
ngircd-25/debian/patches/0016-S2S-TLS-GnuTLS-Fix-handling-of-connections-without-p.patch
    2024-04-15 14:14:26.000000000 +0200
@@ -0,0 +1,34 @@
+From 4c7c73c93825aa2e3550e675dffd9b921df9b634 Mon Sep 17 00:00:00 2001
+From: Alexander Barton <a...@barton.de>
+Date: Sat, 6 Jan 2024 19:57:50 +0100
+Subject: [PATCH 16/20] S2S-TLS/GnuTLS: Fix handling of connections without
+ peer certificates
+
+(cherry picked from commit 8cef3ce42cd645a3ffb0e1eded52b8b77bb8caff)
+---
+ src/ngircd/conn-ssl.c | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+--- a/src/ngircd/conn-ssl.c
++++ b/src/ngircd/conn-ssl.c
+@@ -920,16 +920,15 @@
+           gnutls_mac_get_name(gnutls_mac_get(sess)));
+       cred = gnutls_auth_get_type(c->ssl_state.gnutls_session);
+       if (cred == GNUTLS_CRD_CERTIFICATE) {
+-              cert_seen = true;
+-
+               gnutls_x509_crt_t cert;
+               unsigned cert_list_size;
+               const gnutls_datum_t *cert_list =
+                   gnutls_certificate_get_peers(sess, &cert_list_size);
+-              if (!cert_list || cert_list_size == 0) {
+-                      Log(LOG_ERR, "No certificates found");
++
++              if (!cert_list || cert_list_size == 0)
+                       goto done_cn_validation;
+-              }
++
++              cert_seen = true;
+               int err = gnutls_x509_crt_init(&cert);
+               if (err < 0) {
+                       Log(LOG_ERR,
diff -Nru 
ngircd-25/debian/patches/0017-S2S-TLS-Convert-SSL.txt-to-Markdown-and-update-infor.patch
 
ngircd-25/debian/patches/0017-S2S-TLS-Convert-SSL.txt-to-Markdown-and-update-infor.patch
--- 
ngircd-25/debian/patches/0017-S2S-TLS-Convert-SSL.txt-to-Markdown-and-update-infor.patch
    1970-01-01 01:00:00.000000000 +0100
+++ 
ngircd-25/debian/patches/0017-S2S-TLS-Convert-SSL.txt-to-Markdown-and-update-infor.patch
    2024-04-15 14:14:26.000000000 +0200
@@ -0,0 +1,234 @@
+From 3b510a15e0a8d1c8596ce278aeab74edf52cb4e5 Mon Sep 17 00:00:00 2001
+From: Alexander Barton <a...@barton.de>
+Date: Mon, 8 Jan 2024 18:31:30 +0100
+Subject: [PATCH 17/20] S2S-TLS: Convert SSL.txt to Markdown and update
+ information given
+
+No longer describe creating self-signed certificates or using "stunnel",
+as both is not recommended.
+
+(cherry picked from commit b826fad15871f73435328b1d77fd364838389adb)
+---
+ doc/Makefile.am |   2 +-
+ doc/SSL.md      |  80 +++++++++++++++++++++++++++++++++++
+ doc/SSL.txt     | 108 ------------------------------------------------
+ 3 files changed, 81 insertions(+), 109 deletions(-)
+ create mode 100644 doc/SSL.md
+ delete mode 100644 doc/SSL.txt
+
+--- a/doc/Makefile.am
++++ b/doc/Makefile.am
+@@ -33,7 +33,7 @@
+       README-Interix.txt \
+       RFC.txt \
+       Services.txt \
+-      SSL.txt
++      SSL.md
+ 
+ doc_templates = sample-ngircd.conf.tmpl
+ 
+--- /dev/null
++++ b/doc/SSL.md
+@@ -0,0 +1,80 @@
++# [ngIRCd](https://ngircd.barton.de) - SSL/TLS Encrypted Connections
++
++ngIRCd supports SSL/TLS encrypted connections using the *OpenSSL* or *GnuTLS*
++libraries. Both encrypted server-server links as well as client-server links
++are supported.
++
++SSL is a compile-time option which is disabled by default. Use one of these
++options of the ./configure script to enable it:
++
++- `--with-openssl`: enable SSL support using OpenSSL.
++- `--with-gnutls`: enable SSL support using GnuTLS.
++
++You can check the output of `ngircd --version` to validate if your executable
++includes support for SSL or not: "+SSL" must be listed in the feature flags.
++
++You also need a SSL key and certificate, for example using Let's Encrypt, 
which
++is out of the scope of this document.
++
++From a feature point of view, ngIRCds support for both libraries is
++comparable. The only major difference (at this time) is that ngIRCd with 
GnuTLS
++does not support password protected private keys.
++
++## Configuration
++
++SSL-encrypted connections and plain-text connects can't run on the same 
network
++port (which is a limitation of the IRC protocol); therefore you have to define
++separate port(s) in your `[SSL]` block in the configuration file.
++
++A minimal configuration for *accepting* SSL-encrypted client & server
++connections looks like this:
++
++``` ini
++[SSL]
++CertFile = /etc/ssl/certs/my-fullchain.pem
++KeyFile = /etc/ssl/certs/my-privkey.pem
++Ports = 6697, 6698
++```
++
++In this case, the server only deals with *incoming* connections and never has 
to
++validate SSL certificates itself, and therefore no "Certificate Authorities" 
are
++needed.
++
++If you want to use *outgoing* SSL-connections to other servers, you need to 
add:
++
++``` ini
++[SSL]
++...
++CAFile = /etc/ssl/certs/ca-certificates.crt
++DHFile = /etc/ngircd/dhparams.pem
++
++[SERVER]
++...
++SSLConnect = yes
++```
++
++The `CAFile` option configures a file listing all the certificates of the
++trusted Certificate Authorities.
++
++The Diffie-Hellman parameters file `dhparams.pem` can be created like this:
++
++- OpenSSL: `openssl dhparam -2 -out /etc/ngircd/dhparams.pem 4096`
++- GnuTLS: `certtool --generate-dh-params --bits 4096 --outfile 
/etc/ngircd/dhparams.pem`
++
++Note that enabling `SSLConnect` not only enforces SSL-encrypted links for
++*outgoing* connections to other servers, but for *incoming* connections as 
well:
++If a server configured with `SSLConnect = yes` tries to connect on a 
plain-text
++connection, it won't be accepted to prevent data leakage! Therefore you should
++set this for *all* servers you expect to use SSL-encrypted connections!
++
++## Accepting untrusted Remote Certificates
++
++If you are using self-signed certificates or otherwise invalid certificates,
++which ngIRCd would reject by default, you can force ngIRCd to skip certificate
++validation on a per-server basis and continue establishing outgoing 
connections
++to the respective peer by setting `SSLVerify = no` in the `[SERVER]` block of
++this remote server in your configuration.
++
++But please think twice before doing so: the established connection is still
++encrypted but the remote site is *not verified at all* and man-in-the-middle
++attacks are possible!
+--- a/doc/SSL.txt
++++ /dev/null
+@@ -1,108 +0,0 @@
+-
+-                     ngIRCd - Next Generation IRC Server
+-
+-                        (c)2001-2008 Alexander Barton,
+-                    a...@barton.de, http://www.barton.de/
+-
+-               ngIRCd is free software and published under the
+-                   terms of the GNU General Public License.
+-
+-                                 -- SSL.txt --
+-
+-
+-ngIRCd supports SSL/TLSv1 encrypted connections using the OpenSSL or GnuTLS
+-libraries. Both encrypted server-server links as well as client-server links
+-are supported.
+-
+-SSL is a compile-time option which is disabled by default. Use one of these
+-options of the ./configure script to enable it:
+-
+-  --with-openssl     enable SSL support using OpenSSL
+-  --with-gnutls      enable SSL support using GnuTLS
+-
+-You also need a key/certificate, see below for how to create a self-signed 
one.
+-
+-From a feature point of view, ngIRCds support for both libraries is
+-comparable. The only major difference (at this time) is that ngircd with 
gnutls
+-does not support password protected private keys.
+-
+-Configuration
+-~~~~~~~~~~~~~
+-
+-To enable SSL connections a separate port must be configured: it is NOT
+-possible to handle unencrypted and encrypted connections on the same port!
+-This is a limitation of the IRC protocol ...
+-
+-You have to set (at least) the following configuration variables in the
+-[SSL] section of ngircd.conf(5): Ports, KeyFile, and CertFile.
+-
+-Now IRC clients are able to connect using SSL on the configured port(s).
+-(Using port 6697 for encrypted connections is common.)
+-
+-To enable encrypted server-server links, you have to additionally set
+-SSLConnect to "yes" in the corresponding [SERVER] section.
+-
+-
+-Creating a self-signed certificate
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-
+-OpenSSL:
+-
+-Creating a self-signed certificate and key:
+- $ openssl req -newkey rsa:2048 -x509 -keyout server-key.pem -out 
server-cert.pem -days 1461
+-Create DH parameters (optional):
+- $ openssl dhparam -2 -out dhparams.pem 4096
+-
+-GnuTLS:
+-
+-Creating a self-signed certificate and key:
+- $ certtool --generate-privkey --bits 2048 --outfile server-key.pem
+- $ certtool --generate-self-signed --load-privkey server-key.pem --outfile 
server-cert.pem
+-Create DH parameters (optional):
+- $ certtool  --generate-dh-params --bits 4096 --outfile dhparams.pem
+-
+-
+-Alternate approach using stunnel(1)
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-
+-Alternatively (or if you are using ngIRCd compiled without support
+-for GnuTLS/OpenSSL), you can use external programs/tools like stunnel(1) to
+-get SSL encrypted connections:
+-
+-  <http://stunnel.mirt.net/>
+-  <http://www.stunnel.org/>
+-
+-Stefan Sperling (stefan at binarchy dot net) mailed the following text as a
+-short "how-to", thanks Stefan!
+-
+-=== snip ===
+-    ! This guide applies to stunnel 4.x !
+-
+-    Put this in your stunnel.conf:
+-
+-        [ircs]
+-        accept = 6667
+-        connect = 6668
+-
+-    This makes stunnel listen for incoming connections
+-    on port 6667 and forward decrypted data to port 6668.
+-    We call the connection 'ircs'. Stunnel will use this
+-    name when logging connection attempts via syslog.
+-    You can also use the name in /etc/hosts.{allow,deny}
+-    if you run tcp-wrappers.
+-
+-    To make sure ngircd is listening on the port where
+-    the decrypted data arrives, set
+-
+-        Ports = 6668
+-
+-    in your ngircd.conf.
+-
+-    Start stunnel and restart ngircd.
+-
+-    That's it.
+-    Don't forget to activate ssl support in your irc client ;)
+-    The main drawback of this approach compared to using builtin ssl
+-    is that from ngIRCds point of view, all ssl-enabled client connections 
will
+-    originate from the host running stunnel.
+-=== snip ===
+--- a/doc/Makefile.in
++++ b/doc/Makefile.in
+@@ -243,7 +243,7 @@
+       README-Interix.txt \
+       RFC.txt \
+       Services.txt \
+-      SSL.txt
++      SSL.md
+ 
+ doc_templates = sample-ngircd.conf.tmpl
+ generated_docs = sample-ngircd.conf
diff -Nru ngircd-25/debian/patches/0018-S2S-TLS-Add-notice-to-INSTALL.patch 
ngircd-25/debian/patches/0018-S2S-TLS-Add-notice-to-INSTALL.patch
--- ngircd-25/debian/patches/0018-S2S-TLS-Add-notice-to-INSTALL.patch   
1970-01-01 01:00:00.000000000 +0100
+++ ngircd-25/debian/patches/0018-S2S-TLS-Add-notice-to-INSTALL.patch   
2024-04-15 14:14:26.000000000 +0200
@@ -0,0 +1,30 @@
+From 37dcb74898f4ff7e211088cf831996ea5e2471f1 Mon Sep 17 00:00:00 2001
+From: Alexander Barton <a...@barton.de>
+Date: Thu, 11 Jan 2024 14:24:22 +0100
+Subject: [PATCH 18/20] S2S-TLS: Add notice to INSTALL
+
+(cherry picked from commit 6b27eabf5bdbc6bf6f71d7b1e7d059dfeab6849b)
+---
+ INSTALL | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/INSTALL
++++ b/INSTALL
+@@ -12,6 +12,17 @@
+ I. Upgrade Information
+ ~~~~~~~~~~~~~~~~~~~~~~
+ 
++- **Attention**:
++  Starting with release 27, ngIRCd validates SSL/TLS certificates on outgoing
++  server-server links by default and drops(!) connections when the remote
++  certificate is invalid (for example self-signed, expired, not matching the
++  host name, ...). Therefore you have to make sure that all relevant
++  *certificates are valid* (or to disable certificate validation on this
++  connection using the new `SSLVerify = false` setting in the affected
++  `[Server]` block, where the remote certificate is not valid and you can not
++  fix this issue).
++  And this change was backported to this ngIRCd release!
++
+ Differences to version 22.x
+ 
+ - The "NoticeAuth" ngircd.conf configuration variable has been renamed to
diff -Nru 
ngircd-25/debian/patches/0019-S2S-TLS-Fix-make-check-in-separate-build-directory.patch
 
ngircd-25/debian/patches/0019-S2S-TLS-Fix-make-check-in-separate-build-directory.patch
--- 
ngircd-25/debian/patches/0019-S2S-TLS-Fix-make-check-in-separate-build-directory.patch
      1970-01-01 01:00:00.000000000 +0100
+++ 
ngircd-25/debian/patches/0019-S2S-TLS-Fix-make-check-in-separate-build-directory.patch
      2024-04-15 14:14:26.000000000 +0200
@@ -0,0 +1,28 @@
+From 05c0c9364a586011304beba33e2f15ffa1b86580 Mon Sep 17 00:00:00 2001
+From: Alexander Barton <a...@barton.de>
+Date: Sat, 10 Feb 2024 00:14:33 +0100
+Subject: [PATCH 19/20] S2S-TLS: Fix "make check" in separate build directory
+
+(cherry picked from commit b9d6a2f49c4b3607c69b298cc770c0c945f627f6)
+---
+ src/testsuite/prep-server3   | 5 +++++
+ src/testsuite/switch-server3 | 4 ++++
+ 2 files changed, 9 insertions(+)
+ create mode 100755 src/testsuite/prep-server3
+ create mode 100755 src/testsuite/switch-server3
+
+--- /dev/null
++++ b/src/testsuite/prep-server3
+@@ -0,0 +1,5 @@
++#!/bin/sh -e
++mkdir -p ssl
++cp "${srcdir}"/ssl/cert-my-first-domain-tld.pem ssl/cert.pem
++cp "${srcdir}"/ssl/key-my-first-domain-tld.pem ssl/key.pem
++cp "${srcdir}"/ssl/dhparams-my-first-domain-tld.pem ssl/dhparams.pem
+--- /dev/null
++++ b/src/testsuite/switch-server3
+@@ -0,0 +1,4 @@
++#!/bin/sh -e
++cp "${srcdir}"/ssl/cert-my-second-domain-tld.pem ssl/cert.pem
++cp "${srcdir}"/ssl/key-my-second-domain-tld.pem ssl/key.pem
++cp "${srcdir}"/ssl/dhparams-my-second-domain-tld.pem ssl/dhparams.pem
diff -Nru ngircd-25/debian/patches/0020-METADATA-Fix-unsetting-cloakhost.patch 
ngircd-25/debian/patches/0020-METADATA-Fix-unsetting-cloakhost.patch
--- ngircd-25/debian/patches/0020-METADATA-Fix-unsetting-cloakhost.patch        
1970-01-01 01:00:00.000000000 +0100
+++ ngircd-25/debian/patches/0020-METADATA-Fix-unsetting-cloakhost.patch        
2024-04-15 14:14:32.000000000 +0200
@@ -0,0 +1,28 @@
+From f9959d90deb34ddb0b86f91b51dee5ff50997de2 Mon Sep 17 00:00:00 2001
+From: Alexander Barton <a...@barton.de>
+Date: Sun, 17 Mar 2024 15:55:39 +0100
+Subject: [PATCH 20/20] METADATA: Fix unsetting "cloakhost"
+
+Correctly re-generate the "cloaked hostname" when removing the
+"cloakhost" using an empty string by passing down NULL instead of the
+empty string, which results in protocol violations (for example on
+WHOIS).
+
+(cherry picked from commit 1118b0e77ca961a7b082f90cb124210eca8fb6bd)
+---
+ src/ngircd/irc-metadata.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/src/ngircd/irc-metadata.c
++++ b/src/ngircd/irc-metadata.c
+@@ -72,7 +72,9 @@
+       }
+ 
+       if (strcasecmp(Req->argv[1], "cloakhost") == 0) {
+-              Client_UpdateCloakedHostname(target, prefix, Req->argv[2]);
++              /* Set or remove a "cloaked hostname". */
++              Client_UpdateCloakedHostname(target, prefix,
++                                           *Req->argv[2] ? Req->argv[2] : 
NULL);
+               if (Client_Conn(target) > NONE && Client_HasMode(target, 'x'))
+                       IRC_WriteStrClientPrefix(target, prefix,
+                                       RPL_HOSTHIDDEN_MSG, Client_ID(target),
diff -Nru 
ngircd-25/debian/patches/1713563399.rel-27-rc1-6-g3e3f6cbe.clarify-that-cafile-is-not-set-by-default.patch
 
ngircd-25/debian/patches/1713563399.rel-27-rc1-6-g3e3f6cbe.clarify-that-cafile-is-not-set-by-default.patch
--- 
ngircd-25/debian/patches/1713563399.rel-27-rc1-6-g3e3f6cbe.clarify-that-cafile-is-not-set-by-default.patch
  1970-01-01 01:00:00.000000000 +0100
+++ 
ngircd-25/debian/patches/1713563399.rel-27-rc1-6-g3e3f6cbe.clarify-that-cafile-is-not-set-by-default.patch
  2024-05-01 10:00:00.000000000 +0200
@@ -0,0 +1,28 @@
+Subject: Clarify that "CAFile" is not set by default
+Origin: rel-27-rc1-6-g3e3f6cbe
+Upstream-Author: Alexander Barton <a...@barton.de>
+Date: Fri Apr 19 23:49:59 2024 +0200
+
+--- a/doc/sample-ngircd.conf.tmpl
++++ b/doc/sample-ngircd.conf.tmpl
+@@ -266,7 +266,8 @@
+       # is only available when ngIRCd is compiled with support for SSL!
+       # So don't forget to remove the ";" above if this is the case ...
+ 
+-      # SSL Trusted CA Certificates File (for verifying peer certificates)
++      # SSL Trusted CA Certificates File for verifying peer certificates.
++      # (Default: not set; so no certificates are trusted)
+       ;CAFile = /etc/ssl/CA/cacert.pem
+ 
+       # Certificate Revocation File (for marking otherwise valid
+--- a/man/ngircd.conf.5.tmpl
++++ b/man/ngircd.conf.5.tmpl
+@@ -387,7 +387,7 @@
+ .TP
+ \fBCAFile\fR (string)
+ Filename pointing to the Trusted CA Certificates. This is required for
+-verifying peer certificates.
++verifying peer certificates. Default: not set, so no certificates are trusted.
+ .TP
+ \fBCertFile\fR (string)
+ SSL Certificate file of the private server key.
diff -Nru ngircd-25/debian/patches/series ngircd-25/debian/patches/series
--- ngircd-25/debian/patches/series     2019-01-28 18:04:59.000000000 +0100
+++ ngircd-25/debian/patches/series     2024-05-01 10:00:00.000000000 +0200
@@ -1 +1,24 @@
+# cherry-picked from upstream
+0001-Respect-SSLConnect-option-for-incoming-connections.patch
+0002-Support-for-server-certificate-validation-on-server-.patch
+0003-S2S-TLS-Add-missing-CAFile-and-CRLFile-options-to-co.patch
+0004-S2S-TLS-Remove-leftover-debug-messages.patch
+0005-S2S-TLS-OpenSSL-Always-setup-host-name-verification.patch
+0006-S2S-TLS-OpenSSL-Set-the-verification-flags-only-once.patch
+0007-S2S-TLS-OpenSSL-Fix-handling-of-certificate-informat.patch
+0008-S2S-TLS-OpenSSL-Postpone-verification-of-TLS-session.patch
+0009-S2S-TLS-OpenSSL-Streamline-logging.patch
+0010-S2S-TLS-Fix-formatting-and-sort-new-SSL-options-in-n.patch
+0011-S2S-TLS-MAX_CERT_CHAIN_LENGTH-is-only-used-by-OpenSS.patch
+0013-S2S-TLS-GnuTLS-Fix-handling-of-certificate-informati.patch
+0014-S2S-TLS-GnuTLS-Streamline-logging.patch
+0015-S2S-TLS-Verify-the-TLS-certificates-by-default.patch
+0016-S2S-TLS-GnuTLS-Fix-handling-of-connections-without-p.patch
+0017-S2S-TLS-Convert-SSL.txt-to-Markdown-and-update-infor.patch
+0018-S2S-TLS-Add-notice-to-INSTALL.patch
+0019-S2S-TLS-Fix-make-check-in-separate-build-directory.patch
+0020-METADATA-Fix-unsetting-cloakhost.patch
+0001-S2S-SSL-GnuTLS-Enable-CRL-verification_26.1.patch
+1713563399.rel-27-rc1-6-g3e3f6cbe.clarify-that-cafile-is-not-set-by-default.patch
+
 fix-typos.patch

Attachment: signature.asc
Description: PGP signature

Reply via email to