diff -Nru xchat-gnome-0.30.0~git20131003.d20b8d+really20110821/debian/changelog xchat-gnome-0.30.0~git20131003.d20b8d+really20110821/debian/changelog --- xchat-gnome-0.30.0~git20131003.d20b8d+really20110821/debian/changelog 2014-10-20 14:30:31.000000000 +0000 +++ xchat-gnome-0.30.0~git20131003.d20b8d+really20110821/debian/changelog 2016-04-01 17:43:49.000000000 +0000 @@ -1,3 +1,16 @@ +xchat-gnome (1:0.30.0~git20131003.d20b8d+really20110821-0.2ubuntu12.2) trusty-security; urgency=medium + + * SECURITY UPDATE: no ssl hostname verification (LP: #1565000) + - debian/patches/validate_ssl_hostnames.patch: properly validate + hostnames in src/common/server.c, src/common/ssl.c, src/common/ssl.h. + - CVE number pending + * SECURITY UPDATE: missing ssl certificate handled incorrectly + - debian/patches/handle_missing_ssl_cert.patch: fail connection if + certificate isn't found in src/common/server.c. + - No CVE number + + -- Marc Deslauriers Fri, 01 Apr 2016 13:43:49 -0400 + xchat-gnome (1:0.30.0~git20131003.d20b8d+really20110821-0.2ubuntu12.1) trusty; urgency=medium * Don't force the use of SSLv3 (LP: #1381484) diff -Nru xchat-gnome-0.30.0~git20131003.d20b8d+really20110821/debian/patches/handle_missing_ssl_cert.patch xchat-gnome-0.30.0~git20131003.d20b8d+really20110821/debian/patches/handle_missing_ssl_cert.patch --- xchat-gnome-0.30.0~git20131003.d20b8d+really20110821/debian/patches/handle_missing_ssl_cert.patch 1970-01-01 00:00:00.000000000 +0000 +++ xchat-gnome-0.30.0~git20131003.d20b8d+really20110821/debian/patches/handle_missing_ssl_cert.patch 2016-04-01 17:43:30.000000000 +0000 @@ -0,0 +1,20 @@ +Description: properly handle missing ssl certificate +Origin: other, https://github.com/hexchat/hexchat/commit/50463ca8321c39f3966c278ab25ca158404d72f1 +Bug: https://github.com/hexchat/hexchat/pull/1549 + +Index: xchat-gnome-0.30.0~git20141005.816798/src/common/server.c +=================================================================== +--- xchat-gnome-0.30.0~git20141005.816798.orig/src/common/server.c 2016-04-01 12:50:01.197172847 -0400 ++++ xchat-gnome-0.30.0~git20141005.816798/src/common/server.c 2016-04-01 12:50:52.897480775 -0400 +@@ -695,9 +695,8 @@ + NULL, 0); + } else + { +- snprintf (buf, sizeof (buf), " * No Certificate"); +- EMIT_SIGNAL (XP_TE_SERVTEXT, serv->server_session, buf, NULL, NULL, +- NULL, 0); ++ snprintf (buf, sizeof (buf), "No Certificate"); ++ goto conn_fail; + } + + chiper_info = _SSL_get_cipher_info (serv->ssl); /* static buffer */ diff -Nru xchat-gnome-0.30.0~git20131003.d20b8d+really20110821/debian/patches/series xchat-gnome-0.30.0~git20131003.d20b8d+really20110821/debian/patches/series --- xchat-gnome-0.30.0~git20131003.d20b8d+really20110821/debian/patches/series 2014-10-20 14:30:16.000000000 +0000 +++ xchat-gnome-0.30.0~git20131003.d20b8d+really20110821/debian/patches/series 2016-04-01 17:43:30.000000000 +0000 @@ -25,3 +25,5 @@ link.diff define_functions_fix_build.patch dont_force_sslv3.patch +validate_ssl_hostnames.patch +handle_missing_ssl_cert.patch diff -Nru xchat-gnome-0.30.0~git20131003.d20b8d+really20110821/debian/patches/validate_ssl_hostnames.patch xchat-gnome-0.30.0~git20131003.d20b8d+really20110821/debian/patches/validate_ssl_hostnames.patch --- xchat-gnome-0.30.0~git20131003.d20b8d+really20110821/debian/patches/validate_ssl_hostnames.patch 1970-01-01 00:00:00.000000000 +0000 +++ xchat-gnome-0.30.0~git20131003.d20b8d+really20110821/debian/patches/validate_ssl_hostnames.patch 2016-04-01 17:43:08.000000000 +0000 @@ -0,0 +1,280 @@ +Description: implement ssl hostname verification +Origin: other, https://github.com/hexchat/hexchat/commit/c9b63f7f9be01692b03fa15275135a4910a7e02d +Bug: https://github.com/hexchat/hexchat/issues/524 +Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=1081839 +Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/xchat-gnome/+bug/1565000 + +Index: xchat-gnome-0.30.0~git20141005.816798/src/common/server.c +=================================================================== +--- xchat-gnome-0.30.0~git20141005.816798.orig/src/common/server.c 2016-04-01 13:00:44.222610757 -0400 ++++ xchat-gnome-0.30.0~git20141005.816798/src/common/server.c 2016-04-01 13:01:30.607065618 -0400 +@@ -714,6 +714,20 @@ + switch (verify_error) + { + case X509_V_OK: ++ { ++ X509 *cert = SSL_get_peer_certificate (serv->ssl); ++ int hostname_err; ++ if ((hostname_err = _SSL_check_hostname(cert, serv->hostname)) != 0) ++ { ++ snprintf (buf, sizeof (buf), "* Verify E: Failed to validate hostname? (%d)%s", ++ hostname_err, serv->accept_invalid_cert ? " -- Ignored" : ""); ++ if (serv->accept_invalid_cert) ++ EMIT_SIGNAL (XP_TE_SERVTEXT, serv->server_session, buf, NULL, NULL, NULL, 0); ++ else ++ goto conn_fail; ++ } ++ break; ++ } + /* snprintf (buf, sizeof (buf), "* Verify OK (?)"); */ + /* EMIT_SIGNAL (XP_TE_SERVTEXT, serv->server_session, buf, NULL, NULL, NULL, 0); */ + break; +@@ -735,6 +749,7 @@ + snprintf (buf, sizeof (buf), "%s.? (%d)", + X509_verify_cert_error_string (verify_error), + verify_error); ++conn_fail: + EMIT_SIGNAL (XP_TE_CONNFAIL, serv->server_session, buf, NULL, NULL, + NULL, 0); + +Index: xchat-gnome-0.30.0~git20141005.816798/src/common/ssl.c +=================================================================== +--- xchat-gnome-0.30.0~git20141005.816798.orig/src/common/ssl.c 2016-04-01 13:00:44.222610757 -0400 ++++ xchat-gnome-0.30.0~git20141005.816798/src/common/ssl.c 2016-04-01 13:00:44.222610757 -0400 +@@ -19,6 +19,7 @@ + + #include /* SSL_() */ + #include /* ERR_() */ ++#include + #include /* asctime() */ + #include /* strncpy() */ + #include "ssl.h" /* struct cert_info */ +@@ -29,6 +30,10 @@ + #define snprintf g_snprintf + #endif + ++#include ++#include ++#include ++ + /* globals */ + static struct chiper_info chiper_info; /* static buffer for _SSL_get_cipher_info() */ + static char err_buf[256]; /* generic error buffer */ +@@ -321,3 +326,204 @@ + SSL_free (ssl); + ERR_remove_state (0); /* free state buffer */ + } ++ ++/* Hostname validation code based on OpenBSD's libtls. */ ++ ++static int ++_SSL_match_hostname (const char *cert_hostname, const char *hostname) ++{ ++ const char *cert_domain, *domain, *next_dot; ++ ++ if (g_ascii_strcasecmp (cert_hostname, hostname) == 0) ++ return 0; ++ ++ /* Wildcard match? */ ++ if (cert_hostname[0] == '*') ++ { ++ /* ++ * Valid wildcards: ++ * - "*.domain.tld" ++ * - "*.sub.domain.tld" ++ * - etc. ++ * Reject "*.tld". ++ * No attempt to prevent the use of eg. "*.co.uk". ++ */ ++ cert_domain = &cert_hostname[1]; ++ /* Disallow "*" */ ++ if (cert_domain[0] == '\0') ++ return -1; ++ /* Disallow "*foo" */ ++ if (cert_domain[0] != '.') ++ return -1; ++ /* Disallow "*.." */ ++ if (cert_domain[1] == '.') ++ return -1; ++ next_dot = strchr (&cert_domain[1], '.'); ++ /* Disallow "*.bar" */ ++ if (next_dot == NULL) ++ return -1; ++ /* Disallow "*.bar.." */ ++ if (next_dot[1] == '.') ++ return -1; ++ ++ domain = strchr (hostname, '.'); ++ ++ /* No wildcard match against a hostname with no domain part. */ ++ if (domain == NULL || strlen(domain) == 1) ++ return -1; ++ ++ if (g_ascii_strcasecmp (cert_domain, domain) == 0) ++ return 0; ++ } ++ ++ return -1; ++} ++ ++static int ++_SSL_check_subject_altname (X509 *cert, const char *host) ++{ ++ STACK_OF(GENERAL_NAME) *altname_stack = NULL; ++ GInetAddress *addr; ++ GSocketFamily family; ++ int type = GEN_DNS; ++ int count, i; ++ int rv = -1; ++ ++ altname_stack = X509_get_ext_d2i (cert, NID_subject_alt_name, NULL, NULL); ++ if (altname_stack == NULL) ++ return -1; ++ ++ addr = g_inet_address_new_from_string (host); ++ if (addr != NULL) ++ { ++ family = g_inet_address_get_family (addr); ++ if (family == G_SOCKET_FAMILY_IPV4 || family == G_SOCKET_FAMILY_IPV6) ++ type = GEN_IPADD; ++ } ++ ++ count = sk_GENERAL_NAME_num(altname_stack); ++ for (i = 0; i < count; i++) ++ { ++ GENERAL_NAME *altname; ++ ++ altname = sk_GENERAL_NAME_value (altname_stack, i); ++ ++ if (altname->type != type) ++ continue; ++ ++ if (type == GEN_DNS) ++ { ++ unsigned char *data; ++ int format; ++ ++ format = ASN1_STRING_type (altname->d.dNSName); ++ if (format == V_ASN1_IA5STRING) ++ { ++ data = ASN1_STRING_data (altname->d.dNSName); ++ ++ if (ASN1_STRING_length (altname->d.dNSName) != (int)strlen(data)) ++ { ++ g_warning("NUL byte in subjectAltName, probably a malicious certificate.\n"); ++ rv = -2; ++ break; ++ } ++ ++ if (_SSL_match_hostname (data, host) == 0) ++ { ++ rv = 0; ++ break; ++ } ++ } ++ else ++ g_warning ("unhandled subjectAltName dNSName encoding (%d)\n", format); ++ ++ } ++ else if (type == GEN_IPADD) ++ { ++ unsigned char *data; ++ const guint8 *addr_bytes; ++ int datalen, addr_len; ++ ++ datalen = ASN1_STRING_length (altname->d.iPAddress); ++ data = ASN1_STRING_data (altname->d.iPAddress); ++ ++ addr_bytes = g_inet_address_to_bytes (addr); ++ addr_len = (int)g_inet_address_get_native_size (addr); ++ ++ if (datalen == addr_len && memcmp (data, addr_bytes, addr_len) == 0) ++ { ++ rv = 0; ++ break; ++ } ++ } ++ } ++ ++ if (addr != NULL) ++ g_object_unref (addr); ++ sk_GENERAL_NAME_free (altname_stack); ++ return rv; ++} ++ ++static int ++_SSL_check_common_name (X509 *cert, const char *host) ++{ ++ X509_NAME *name; ++ char *common_name = NULL; ++ int common_name_len; ++ int rv = -1; ++ GInetAddress *addr; ++ ++ name = X509_get_subject_name (cert); ++ if (name == NULL) ++ return -1; ++ ++ common_name_len = X509_NAME_get_text_by_NID (name, NID_commonName, NULL, 0); ++ if (common_name_len < 0) ++ return -1; ++ ++ common_name = calloc (common_name_len + 1, 1); ++ if (common_name == NULL) ++ return -1; ++ ++ X509_NAME_get_text_by_NID (name, NID_commonName, common_name, common_name_len + 1); ++ ++ /* NUL bytes in CN? */ ++ if (common_name_len != (int)strlen(common_name)) ++ { ++ g_warning ("NUL byte in Common Name field, probably a malicious certificate.\n"); ++ rv = -2; ++ goto out; ++ } ++ ++ if ((addr = g_inet_address_new_from_string (host)) != NULL) ++ { ++ /* ++ * We don't want to attempt wildcard matching against IP ++ * addresses, so perform a simple comparison here. ++ */ ++ if (g_strcmp0 (common_name, host) == 0) ++ rv = 0; ++ else ++ rv = -1; ++ ++ g_object_unref (addr); ++ } ++ else if (_SSL_match_hostname (common_name, host) == 0) ++ rv = 0; ++ ++out: ++ free(common_name); ++ return rv; ++} ++ ++int ++_SSL_check_hostname (X509 *cert, const char *host) ++{ ++ int rv; ++ ++ rv = _SSL_check_subject_altname (cert, host); ++ if (rv == 0 || rv == -2) ++ return rv; ++ ++ return _SSL_check_common_name (cert, host); ++} +Index: xchat-gnome-0.30.0~git20141005.816798/src/common/ssl.h +=================================================================== +--- xchat-gnome-0.30.0~git20141005.816798.orig/src/common/ssl.h 2016-04-01 13:00:44.222610757 -0400 ++++ xchat-gnome-0.30.0~git20141005.816798/src/common/ssl.h 2016-04-01 13:00:44.222610757 -0400 +@@ -34,7 +34,7 @@ + int SSL_get_fd(SSL *); + */ + void _SSL_close (SSL * ssl); +- ++int _SSL_check_hostname(X509 *cert, const char *host); + int _SSL_get_cert_info (struct cert_info *cert_info, SSL * ssl); + struct chiper_info *_SSL_get_cipher_info (SSL * ssl); +