Package: fdm Version: 1.6+cvs20111013-2 Severity: wishlist Tags: patch upstream
fdm rejects the SSL certificate for one of the pop3s servers listed in my configuration, because the hostname does not match the CN in the X509 structure. However, the hostname does match one of the DNS names listed in the X509v3 Subject Alternative Name extension, and should be considered valid. In fact, other pop3s clients (notably mutt and icedove) do accept the certificate, while fdm requires a "no-verify" option to proceed to my inbox. The attached patch implements the logic to check SANs in case the CN does not match. Best regards, g -- System Information: Debian Release: 7.2 APT prefers stable-updates APT policy: (500, 'stable-updates'), (500, 'stable') Architecture: i386 (i686) Kernel: Linux 3.2.0-4-686-pae (SMP w/2 CPU cores) Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968) Shell: /bin/sh linked to /bin/dash Versions of packages fdm depends on: ii adduser 3.113+nmu3 ii libc6 2.13-38 ii libpcre3 1:8.30-5 ii libssl1.0.0 1.0.1e-2 ii libtdb1 1.2.10-2 ii zlib1g 1:1.2.7.dfsg-13 fdm recommends no packages. fdm suggests no packages. -- no debconf information
--- connect.c.orig 2013-11-20 09:41:34.632235841 +0100 +++ connect.c 2013-11-20 12:13:25.294174792 +0100 @@ -33,6 +33,7 @@ #include <openssl/ssl.h> #include <openssl/err.h> +#include <openssl/x509v3.h> #include "fdm.h" @@ -83,6 +84,39 @@ return (cause); } +static +char * +ssl_check_alt_names(char *host, char *fqdn, X509 *x509) +{ + int n; + const int fn_flags = FNM_NOESCAPE | FNM_CASEFOLD; + char *ptr = NULL; + const GENERAL_NAMES *ans = + X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL); + + if (!ans) + return ptr; + + n = sk_GENERAL_NAME_num(ans); + + while (n-- > 0 && ptr == NULL) { + char *buf = NULL; + const GENERAL_NAME *p = sk_GENERAL_NAME_value(ans, n); + if (!p || p->type != GEN_DNS) + continue; + ASN1_STRING_to_UTF8((unsigned char **) &buf, p->d.dNSName); + if (buf == NULL) + continue; + if (fnmatch(buf, host, fn_flags) == 0 || + (fqdn && fnmatch(buf, fqdn, fn_flags) == 0)) + ptr = buf; + OPENSSL_free(buf); + } + + sk_GENERAL_NAME_free(ans); + return ptr; +} + int sslverify(struct server *srv, SSL *ssl, char **cause) { @@ -130,6 +164,11 @@ if (ptr2 != NULL) *ptr2 = '/'; } while ((ptr = strstr(ptr, "/CN=")) != NULL); + + /* No valid CN found. Try alternative names */ + if (ptr == NULL) + ptr = ssl_check_alt_names(srv->host, fqdn, x509); + if (fqdn != NULL) xfree(fqdn);