summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--imap/ChangeLog4
-rw-r--r--imap/configure.ac2
-rw-r--r--rfc1035/rfc1035qa.c31
-rw-r--r--tcpd/libcouriergnutls.c89
4 files changed, 103 insertions, 23 deletions
diff --git a/imap/ChangeLog b/imap/ChangeLog
index f02a57e..8cd6989 100644
--- a/imap/ChangeLog
+++ b/imap/ChangeLog
@@ -1,3 +1,7 @@
+2019-12-05 Sam Varshavchik <mrsam@courier-mta.com>
+
+ * Fix virtual IP and hostname handling when using GnuTLS for SSL.
+
2019-09-05 Sam Varshavchik <mrsam@courier-mta.com>
* imap, pop3: include remote port TCP port number together with the
diff --git a/imap/configure.ac b/imap/configure.ac
index c21a80e..92726bc 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, [courier-users@lists.sourceforge.net])
+AC_INIT(courier-imap, 5.0.8.20191205, [courier-users@lists.sourceforge.net])
>confdefs.h # Kill PACKAGE_ macros
diff --git a/rfc1035/rfc1035qa.c b/rfc1035/rfc1035qa.c
index 46fc204..ffed34f 100644
--- a/rfc1035/rfc1035qa.c
+++ b/rfc1035/rfc1035qa.c
@@ -1,5 +1,5 @@
/*
-** Copyright 1998 - 2011 Double Precision, Inc.
+** Copyright 1998 - 2019 Double Precision, Inc.
** See COPYING for distribution information.
*/
@@ -8,6 +8,7 @@
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
+#include <idna.h>
/* Convenient function to do forward IP lookup */
@@ -16,8 +17,9 @@
static int rfc1035_a_ipv4(struct rfc1035_res *res,
const char *name, struct in_addr **iaptr, unsigned *iasize)
#else
-int rfc1035_a(struct rfc1035_res *res,
- const char *name, RFC1035_ADDR **iaptr, unsigned *iasize)
+static int rfc1035_unicode(struct rfc1035_res *res,
+ const char *name,
+ RFC1035_ADDR **iaptr, unsigned *iasize)
#endif
{
struct rfc1035_reply *reply;
@@ -111,8 +113,9 @@ unsigned i;
return (0);
}
-int rfc1035_a(struct rfc1035_res *res,
- const char *name, struct in6_addr **iaptr, unsigned *iasize)
+static int rfc1035_unicode(struct rfc1035_res *res,
+ const char *name, struct in6_addr **iaptr,
+ unsigned *iasize)
{
struct rfc1035_reply *reply;
int n, o;
@@ -236,3 +239,21 @@ unsigned k;
return (0);
}
#endif
+
+int rfc1035_a(struct rfc1035_res *res,
+ const char *name,
+ RFC1035_ADDR **iaptr, unsigned *iasize)
+{
+ char *p;
+ int r;
+
+ /* Convert requested hostname to UTF-8, with fallback */
+
+ if (idna_to_unicode_8z8z(name, &p, 0) != IDNA_SUCCESS)
+ return rfc1035_unicode(res, name, iaptr, iasize);
+
+ r=rfc1035_unicode(res, p, iaptr, iasize);
+
+ free(p);
+ return r;
+}
diff --git a/tcpd/libcouriergnutls.c b/tcpd/libcouriergnutls.c
index 65c34cb..7a48ae3 100644
--- a/tcpd/libcouriergnutls.c
+++ b/tcpd/libcouriergnutls.c
@@ -1,5 +1,5 @@
/*
-** Copyright 2007-2018 Double Precision, Inc.
+** Copyright 2007-2019 Double Precision, Inc.
** See COPYING for distribution information.
*/
#include "config.h"
@@ -567,10 +567,21 @@ static int name_check(ssl_handle ssl,
p=idn_domain ? idn_domain:ssl->info_cpy.peer_verify_domain;
+ printf("Check %s\n", p);
rc=gnutls_x509_crt_check_hostname(cert, p);
if (idn_domain)
+ {
free(idn_domain);
+
+ /* Now try the ACE-encoded hostname for a filename. */
+
+ if (rc == 0)
+ {
+ p=ssl->info_cpy.peer_verify_domain;
+ rc=gnutls_x509_crt_check_hostname(cert, p);
+ }
+ }
return rc;
}
@@ -736,10 +747,10 @@ static int dohandshake(ssl_handle ssl, int fd, fd_set *r, fd_set *w)
return rc;
}
-static char *check_cert(const char *filename,
- gnutls_certificate_type_t cert_type,
- const char *req_dn,
- int isvirtual)
+static char *check_cert_unicode(const char *filename,
+ gnutls_certificate_type_t cert_type,
+ const char *req_dn,
+ int isvirtual)
{
if (!filename || !*filename)
return NULL;
@@ -766,6 +777,12 @@ static char *check_cert(const char *filename,
++req_dn;
}
+ /*
+ ** We're called with a hostname first. Don't check the defualt
+ ** filename, we'll be called again with an IP address
+ */
+
+ if (!isvirtual)
{
char *p=malloc(strlen(filename)+10);
@@ -782,6 +799,33 @@ static char *check_cert(const char *filename,
return NULL;
}
+static char *check_cert(const char *filename,
+ gnutls_certificate_type_t cert_type,
+ const char *req_dn,
+ int isvirtual)
+{
+ if (isvirtual)
+ {
+ char *p;
+ char *retfile;
+
+ if (idna_to_ascii_8z(req_dn, &p, 0) != IDNA_SUCCESS)
+ p=0;
+
+ if (p)
+ {
+ retfile=check_cert_unicode(filename, cert_type, p,
+ isvirtual);
+ free(p);
+
+ if (retfile)
+ return retfile;
+ }
+ }
+
+ return check_cert_unicode(filename, cert_type, req_dn, isvirtual);
+}
+
static char *check_key(const char *filename,
gnutls_certificate_type_t cert_type,
const char *req_dn,
@@ -952,39 +996,51 @@ static int get_server_cert(gnutls_session_t session,
++vhost_idx)
{
char *p;
+ char *utf8;
+ char *namebuf;
+
+ /* Convert to UTF8 */
+ if (idna_to_unicode_8z8z(vhost_buf, &utf8, 0)
+ != IDNA_SUCCESS)
+ utf8=0;
- for (p=vhost_buf; *p; p++)
+ namebuf=utf8 ? utf8:vhost_buf;
+
+ for (p=namebuf; *p; p++)
if (*p == '/')
*p='.'; /* Script kiddie check */
if (ssl->ctx->certfile)
certfilename=check_cert(ssl->ctx->certfile,
st->cert_type,
- vhost_buf, 1);
+ namebuf, 1);
if (ssl->ctx->keyfile)
keyfilename=check_key(ssl->ctx->keyfile,
st->cert_type,
- vhost_buf, 1);
+ namebuf, 1);
+ if (utf8)
+ free(utf8);
if (certfilename)
break;
}
if (!certfilename)
{
+ const char *ip=
+ safe_getenv(ssl->ctx,
+ "TCPLOCALIP", "");
+
+ if (strncmp(ip, "::ffff:", 7) == 0 && strchr(ip, '.'))
+ ip += 7;
+
if (ssl->ctx->certfile)
certfilename=check_cert(ssl->ctx->certfile,
- st->cert_type,
- safe_getenv(ssl->ctx,
- "TCPLOCALIP", ""),
- 0);
+ st->cert_type, ip, 0);
if (ssl->ctx->keyfile)
keyfilename=check_key(ssl->ctx->keyfile,
- st->cert_type,
- safe_getenv(ssl->ctx,
- "TCPLOCALIP", ""),
- 0);
+ st->cert_type, ip, 0);
}
if (!certfilename)
@@ -1324,7 +1380,6 @@ static int name_set(ssl_handle ssl, ssl_context ctx)
p=idn_domain ? idn_domain:ctx->info_cpy.peer_verify_domain;
-
rc=gnutls_server_name_set(ssl->session, GNUTLS_NAME_DNS,
p, strlen(p));