diff options
| -rw-r--r-- | imap/ChangeLog | 4 | ||||
| -rw-r--r-- | imap/configure.ac | 2 | ||||
| -rw-r--r-- | rfc1035/rfc1035qa.c | 31 | ||||
| -rw-r--r-- | tcpd/libcouriergnutls.c | 89 |
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)); |
