summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Varshavchik2019-12-10 20:36:35 -0500
committerSam Varshavchik2019-12-10 20:39:04 -0500
commit296d760c2db224567fd3b9ba15280a43fe48a6ba (patch)
tree48c3cb784c350f04329b5bd60b8f3f12c8ac4449
parenteaa4c8f12c295b03d5034fc3d4ec1e45c86984af (diff)
downloadcourier-libs-296d760c2db224567fd3b9ba15280a43fe48a6ba.tar.bz2
Restore OpenSSL 1.1, and earlier support.
Restores code that c8115514b4830a668ce726b2fcb8ab4a3d438ec9 removed, but make it conditionally compiled. Have configure.ac autodetect the openssl version. Correctly UTF8-ize SSL_set_tlsext_host_name()'s parameter.
-rw-r--r--imap/configure.ac2
-rw-r--r--tcpd/configure.ac2
-rw-r--r--tcpd/libcouriertls.c219
3 files changed, 211 insertions, 12 deletions
diff --git a/imap/configure.ac b/imap/configure.ac
index 9bf0201..6ac8577 100644
--- a/imap/configure.ac
+++ b/imap/configure.ac
@@ -4,7 +4,7 @@ dnl
dnl Copyright 1998 - 2019 Double Precision, Inc. See COPYING for
dnl distribution information.
-AC_INIT(courier-imap, 5.0.8.20191205, [courier-users@lists.sourceforge.net])
+AC_INIT(courier-imap, 5.0.8.20191210, [courier-users@lists.sourceforge.net])
>confdefs.h # Kill PACKAGE_ macros
diff --git a/tcpd/configure.ac b/tcpd/configure.ac
index 872a0ad..08ba7d0 100644
--- a/tcpd/configure.ac
+++ b/tcpd/configure.ac
@@ -552,7 +552,7 @@ RAND_bytes(dummy, 1);
]
)
LIBS="-lssl $LIBS"
- AC_CHECK_FUNCS(TLSv1_1_method TLSv1_2_method)
+ AC_CHECK_FUNCS(TLSv1_1_method TLSv1_2_method X509_VERIFY_PARAM_set1_host)
LIBS="$save_LIBS"
AC_TRY_COMPILE( [
diff --git a/tcpd/libcouriertls.c b/tcpd/libcouriertls.c
index d4d1643..ac05caf 100644
--- a/tcpd/libcouriertls.c
+++ b/tcpd/libcouriertls.c
@@ -142,6 +142,7 @@ static int ssl_verify_callback(int goodcert, X509_STORE_CTX *x509)
return (1);
}
+#if HAVE_X509_VERIFY_PARAM_SET1_HOST
static int verifypeer(const struct tls_info *info, SSL *ssl)
{
if (!info->peer_verify_domain)
@@ -149,6 +150,199 @@ static int verifypeer(const struct tls_info *info, SSL *ssl)
return SSL_get_verify_result(ssl) == X509_V_OK;
}
+#else
+
+static int hostmatch_utf8(const char *a, const char *b)
+{
+ while (*a || *b)
+ {
+ char ca=*a;
+ char cb=*b;
+
+ if (ca >= 'A' && ca <= 'Z')
+ ca += 'a'-'A';
+ if (cb >= 'A' && cb <= 'Z')
+ cb += 'a'-'A';
+ if (ca != cb)
+ return 0;
+
+ ++a;
+ ++b;
+ }
+ return 1;
+}
+
+static int hostmatch(const struct tls_info *info, const char *domain)
+{
+ const char *p=domain;
+ const char *verify_domain=info->peer_verify_domain;
+ char *idn_domain1;
+ char *idn_domain2;
+ int rc;
+
+ if (*p == '*')
+ {
+ ++p;
+
+ if (*p != '.')
+ return 0;
+
+ while (*verify_domain)
+ {
+ if (*verify_domain++ == '.')
+ break;
+ }
+ }
+
+ if (idna_to_unicode_8z8z(info->peer_verify_domain, &idn_domain1, 0)
+ != IDNA_SUCCESS)
+ idn_domain1=0;
+
+ if (idna_to_unicode_8z8z(p, &idn_domain2, 0)
+ != IDNA_SUCCESS)
+ idn_domain2=0;
+
+ rc=hostmatch_utf8(idn_domain1 ? idn_domain1:info->peer_verify_domain,
+ idn_domain2 ? idn_domain2:p);
+
+ if (idn_domain1)
+ free(idn_domain1);
+ if (idn_domain2)
+ free(idn_domain2);
+ return rc;
+}
+
+static int verifypeer1(const struct tls_info *info, X509 *x,
+ STACK_OF(GENERAL_NAME) *subject_alt_names);
+
+static int verifypeer(const struct tls_info *info, SSL *ssl)
+{
+ X509 *x=NULL;
+ int rc;
+ STACK_OF(GENERAL_NAME) *subject_alt_names;
+
+ if (!info->peer_verify_domain)
+ return (1);
+
+ if (SSL_get_verify_result(ssl) != X509_V_OK)
+ return (1);
+
+ x=SSL_get_peer_certificate(ssl);
+
+ if (!x)
+ return (0);
+
+ subject_alt_names=
+ X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
+
+ rc=verifypeer1(info, x, subject_alt_names);
+
+ if (subject_alt_names)
+ GENERAL_NAMES_free(subject_alt_names);
+
+ X509_free(x);
+
+ return rc;
+}
+
+static int verifypeer1(const struct tls_info *info, X509 *x,
+ STACK_OF(GENERAL_NAME) *subject_alt_names)
+{
+ X509_NAME *subj=NULL;
+ int nentries, j;
+ char domain[256];
+ char errmsg[1000];
+
+ if(subject_alt_names)
+ {
+ int n=sk_GENERAL_NAME_num(subject_alt_names);
+ int i;
+
+ for (i=0; i<n; i++)
+ {
+ const GENERAL_NAME *gn=
+ sk_GENERAL_NAME_value(subject_alt_names, i);
+ const char *str;
+ int l;
+
+ if (gn->type != GEN_DNS)
+ continue;
+
+#ifdef HAVE_OPENSSL110
+ str = (const char *)ASN1_STRING_get0_data(gn->d.ia5);
+#else
+ str = (const char *)ASN1_STRING_data(gn->d.ia5);
+#endif
+ l=ASN1_STRING_length(gn->d.ia5);
+
+ if (l >= sizeof(domain)-1)
+ l=sizeof(domain)-1;
+
+ memcpy(domain, str, l);
+ domain[l]=0;
+
+ if (hostmatch(info, domain))
+ return 1;
+ }
+ }
+
+ subj=X509_get_subject_name(x);
+
+ nentries=0;
+ if (subj)
+ nentries=X509_NAME_entry_count(subj);
+
+ domain[0]=0;
+ for (j=0; j<nentries; j++)
+ {
+ const char *obj_name;
+ X509_NAME_ENTRY *e;
+ ASN1_OBJECT *o;
+ ASN1_STRING *d;
+
+ int dlen;
+ const unsigned char *ddata;
+
+ e=X509_NAME_get_entry(subj, j);
+ if (!e)
+ continue;
+
+ o=X509_NAME_ENTRY_get_object(e);
+ d=X509_NAME_ENTRY_get_data(e);
+
+ if (!o || !d)
+ continue;
+
+ obj_name=OBJ_nid2sn(OBJ_obj2nid(o));
+
+ dlen=ASN1_STRING_length(d);
+#ifdef HAVE_OPENSSL110
+ ddata=ASN1_STRING_get0_data(d);
+#else
+ ddata=ASN1_STRING_data(d);
+#endif
+ if (strcasecmp(obj_name, "CN") == 0)
+ {
+ if (dlen >= sizeof(domain)-1)
+ dlen=sizeof(domain)-1;
+
+ memcpy(domain, ddata, dlen);
+ domain[dlen]=0;
+ }
+ }
+
+ if (domain[0] && hostmatch(info, domain))
+ return 1;
+
+ strcpy(errmsg, "couriertls: Mismatched SSL certificate: CN=");
+ strcat(errmsg, domain);
+ strcat(errmsg, " (expected ");
+ strncat(errmsg, info->peer_verify_domain, 256);
+ strcat(errmsg, ")");
+ (*info->tls_err_msg)(errmsg, info->app_data);
+ return (0);
+}
+#endif
static void nonsslerror(const struct tls_info *info, const char *pfix)
{
@@ -1083,32 +1277,37 @@ SSL *tls_connect(SSL_CTX *ctx, int fd)
}
else
{
+ char *idn_domain1;
+
+ if (idna_to_unicode_8z8z(info->peer_verify_domain,
+ &idn_domain1, 0)
+ != IDNA_SUCCESS)
+ idn_domain1=0;
+
SSL_set_connect_state(ssl);
#ifdef HAVE_OPENSSL_SNI
if (info->peer_verify_domain)
{
- SSL_set_tlsext_host_name(ssl, info->peer_verify_domain);
+ SSL_set_tlsext_host_name(ssl,
+ idn_domain1 ? idn_domain1
+ : (char *)
+ info->peer_verify_domain);
}
#endif
+#if HAVE_X509_VERIFY_PARAM_SET1_HOST
if (info->peer_verify_domain)
{
- char *idn_domain1;
-
- if (idna_to_unicode_8z8z(info->peer_verify_domain,
- &idn_domain1, 0)
- != IDNA_SUCCESS)
- idn_domain1=0;
-
X509_VERIFY_PARAM *param = SSL_get0_param(ssl);
X509_VERIFY_PARAM_set1_host(param,
idn_domain1 ?
idn_domain1 :
info->peer_verify_domain,
0);
- if (idn_domain1)
- free(idn_domain1);
}
+#endif
+ if (idn_domain1)
+ free(idn_domain1);
if ((rc=SSL_connect(ssl)) > 0)
{