| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682 |
- From 315125a8bcf6d80c969a3310c43b486b0e422e5b Mon Sep 17 00:00:00 2001
- From: Christoph Biedl <ngircd.anoy@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 <fw@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 );
- @@ -1774,6 +1783,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");
- }
- @@ -1904,7 +1923,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>
- @@ -74,6 +78,7 @@
- static gnutls_dh_params_t dh_params;
- static gnutls_priority_t priorities_cache = NULL;
- static bool ConnSSL_LoadServerKey_gnutls PARAMS(( void ));
- +static bool ConnSSL_SetVerifyProperties_gnutls PARAMS((void));
- #endif
-
- #define SHA256_STRING_LEN (32 * 2 + 1)
- @@ -131,10 +136,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();
- @@ -176,9 +209,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
-
- @@ -354,7 +394,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);
- @@ -394,6 +439,9 @@
- goto out;
- }
-
- + if (!ConnSSL_SetVerifyProperties_gnutls())
- + goto out;
- +
- Log(LOG_INFO, "GnuTLS %s initialized.", gnutls_check_version(NULL));
- initialized = true;
- return true;
- @@ -406,6 +454,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;
- @@ -531,6 +610,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)
- @@ -602,7 +731,7 @@
-
-
- bool
- -ConnSSL_PrepareConnect(CONNECTION *c, UNUSED CONF_SERVER *s)
- +ConnSSL_PrepareConnect(CONNECTION * c, CONF_SERVER * s)
- {
- bool ret;
- #ifdef HAVE_LIBGNUTLS
- @@ -613,7 +742,7 @@
- Log(LOG_ERR, "Failed to initialize new SSL session: %s",
- gnutls_strerror(err));
- return false;
- - }
- + }
- #endif
- ret = ConnSSL_Init_SSL(c);
- if (!ret)
- @@ -621,7 +750,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;
- }
- @@ -720,18 +865,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
- -ConnSSL_LogCertInfo( CONNECTION *c )
- +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, 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);
-
- @@ -740,7 +969,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");
- }
-
-
- @@ -879,7 +1182,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
- @@ -2546,6 +2546,7 @@
- cb_connserver_login_ssl(int sock, short unused)
- {
- CONN_ID idx = Socket2Index(sock);
- + int serveridx;
-
- (void) unused;
-
- @@ -2564,10 +2565,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;
-
|