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);
 

Reply via email to