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