summaryrefslogtreecommitdiffstats
path: root/tcpd
diff options
context:
space:
mode:
authorSam Varshavchik2019-10-08 19:20:23 -0400
committerSam Varshavchik2019-10-08 19:34:57 -0400
commitc8115514b4830a668ce726b2fcb8ab4a3d438ec9 (patch)
tree488a88aa93d9310cbe8236ae7519ce5fc8432cde /tcpd
parent4be1002d33838edbc78d508ef60cea198c94eb02 (diff)
downloadcourier-libs-c8115514b4830a668ce726b2fcb8ab4a3d438ec9.tar.bz2
Use OpenSSL to verify hostnames.
Diffstat (limited to 'tcpd')
-rw-r--r--tcpd/libcouriertls.c203
1 files changed, 19 insertions, 184 deletions
diff --git a/tcpd/libcouriertls.c b/tcpd/libcouriertls.c
index 1915ee0..d4d1643 100644
--- a/tcpd/libcouriertls.c
+++ b/tcpd/libcouriertls.c
@@ -142,195 +142,12 @@ static int ssl_verify_callback(int goodcert, X509_STORE_CTX *x509)
return (1);
}
-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);
+ return SSL_get_verify_result(ssl) == X509_V_OK;
}
static void nonsslerror(const struct tls_info *info, const char *pfix)
@@ -1274,6 +1091,24 @@ SSL *tls_connect(SSL_CTX *ctx, int fd)
SSL_set_tlsext_host_name(ssl, info->peer_verify_domain);
}
#endif
+ 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);
+ }
if ((rc=SSL_connect(ssl)) > 0)
{