From 199a7e162dc304b56c33cc55ec2d01490d544973 Mon Sep 17 00:00:00 2001 From: Bram Matthys Date: Fri, 1 Sep 2017 17:28:49 +0200 Subject: [PATCH] Make new functions more generic and use it from crash reporter so people with older OpenSSL libraries (and LibreSSL) benefit from the hostname validation code there as well. --- include/h.h | 4 ++-- src/crashreport.c | 18 +++++++++++++++++- src/modules/m_server.c | 3 +-- src/ssl.c | 19 +++++++++---------- 4 files changed, 29 insertions(+), 15 deletions(-) diff --git a/include/h.h b/include/h.h index 316a93cff..c8fdf6105 100644 --- a/include/h.h +++ b/include/h.h @@ -791,5 +791,5 @@ extern SSLOptions *FindSSLOptionsForUser(aClient *acptr); extern int IsWebsocket(aClient *acptr); extern PlaintextPolicy plaintextpolicy_strtoval(char *s); extern char *plaintextpolicy_valtostr(PlaintextPolicy policy); -extern int verify_certificate(aClient *acptr, char *hostname, char **errstr); -extern char *certificate_name(aClient *acptr); +extern int verify_certificate(SSL *ssl, char *hostname, char **errstr); +extern char *certificate_name(SSL *ssl); diff --git a/src/crashreport.c b/src/crashreport.c index 65bd14f4d..a8d64ef9d 100644 --- a/src/crashreport.c +++ b/src/crashreport.c @@ -489,8 +489,10 @@ int crashreport_send(char *fname) int n; FILE *fd; SSL_CTX *ctx_client; + SSL *ssl = NULL; BIO *socket = NULL; int xfr = 0; + char *errstr; filesize = getfilesize(fname); if (filesize < 0) @@ -534,7 +536,21 @@ int crashreport_send(char *fname) printf("ERROR: Could not connect to %s (SSL handshake failed)\n", CRASH_REPORT_HOST); return 0; } - + + BIO_get_ssl(socket, &ssl); + if (!ssl) + { + printf("ERROR: Could not get SSL connection from BIO\n"); + return 0; + } + + if (!verify_certificate(ssl, REPORT_HOST, &errstr)) + { + printf("Certificate problem with crash.unrealircd.org: %s\n", errstr); + printf("Fatal error. See above.\n"); + return 0; + } + snprintf(buf, sizeof(buf), "POST /crash.php HTTP/1.1\r\n" "User-Agent: UnrealIRCd %s\r\n" "Host: %s\r\n" diff --git a/src/modules/m_server.c b/src/modules/m_server.c index 8bf7c00ed..46750dff3 100644 --- a/src/modules/m_server.c +++ b/src/modules/m_server.c @@ -335,7 +335,6 @@ skip_host_check: if (!IsSSL(cptr)) { - /* Rare, but better we handle it here or the (other) error will be confusing */ sendto_one(cptr, "ERROR :Link '%s' denied (Not using SSL/TLS) %s", servername, inpath); @@ -344,7 +343,7 @@ skip_host_check: return exit_client(cptr, sptr, &me, "Link denied (Not using SSL/TLS)"); } - if (!verify_certificate(cptr, link->servername, &errstr)) + if (!verify_certificate(cptr->local->ssl, link->servername, &errstr)) { sendto_one(cptr, "ERROR :Link '%s' denied (Certificate verification failed) %s", diff --git a/src/ssl.c b/src/ssl.c index 6ed714699..39619d5fb 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -869,9 +869,8 @@ SSLOptions *FindSSLOptionsForUser(aClient *acptr) return sslopt; } -/** Verify certificate of client 'acptr' and make sure the certificate - * is valid for 'hostname'. */ -int verify_certificate(aClient *acptr, char *hostname, char **errstr) +/** Verify certificate and make sure the certificate is valid for 'hostname'. */ +int verify_certificate(SSL *ssl, char *hostname, char **errstr) { static char buf[512]; X509 *cert; @@ -882,7 +881,7 @@ int verify_certificate(aClient *acptr, char *hostname, char **errstr) if (*errstr) *errstr = NULL; /* default */ - if (!IsSecure(acptr)) + if (!ssl) { strlcpy(buf, "Not using SSL/TLS", sizeof(buf)); if (errstr) @@ -890,7 +889,7 @@ int verify_certificate(aClient *acptr, char *hostname, char **errstr) return 0; /* Cannot verify a non-SSL connection */ } - if (SSL_get_verify_result(acptr->local->ssl) != X509_V_OK) + if (SSL_get_verify_result(ssl) != X509_V_OK) { strlcpy(buf, "Certificate is not issued by a trusted Certificate Authority", sizeof(buf)); if (errstr) @@ -899,7 +898,7 @@ int verify_certificate(aClient *acptr, char *hostname, char **errstr) } /* Now verify if the name of the certificate matches hostname */ - cert = SSL_get_peer_certificate(acptr->local->ssl); + cert = SSL_get_peer_certificate(ssl); if (!cert) { @@ -927,22 +926,22 @@ int verify_certificate(aClient *acptr, char *hostname, char **errstr) /* Certificate is verified but is issued for a different hostname */ snprintf(buf, sizeof(buf), "Certificate '%s' is not valid for hostname '%s'", - certificate_name(acptr), hostname); + certificate_name(ssl), hostname); *errstr = buf; return 0; } /** Grab the certificate name */ -char *certificate_name(aClient *acptr) +char *certificate_name(SSL *ssl) { static char buf[384]; X509 *cert; X509_NAME *n; - if (!IsSecure(acptr)) + if (!ssl) return NULL; - cert = SSL_get_peer_certificate(acptr->local->ssl); + cert = SSL_get_peer_certificate(ssl); if (!cert) return NULL;