diff options
| author | Sam Varshavchik | 2019-10-08 19:20:23 -0400 |
|---|---|---|
| committer | Sam Varshavchik | 2019-10-08 19:34:57 -0400 |
| commit | c8115514b4830a668ce726b2fcb8ab4a3d438ec9 (patch) | |
| tree | 488a88aa93d9310cbe8236ae7519ce5fc8432cde /tcpd | |
| parent | 4be1002d33838edbc78d508ef60cea198c94eb02 (diff) | |
| download | courier-libs-c8115514b4830a668ce726b2fcb8ab4a3d438ec9.tar.bz2 | |
Use OpenSSL to verify hostnames.
Diffstat (limited to 'tcpd')
| -rw-r--r-- | tcpd/libcouriertls.c | 203 |
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) { |
