diff options
| -rw-r--r-- | qmail-remote.c | 59 |
1 files changed, 14 insertions, 45 deletions
diff --git a/qmail-remote.c b/qmail-remote.c index dbeef95..7eb2714 100644 --- a/qmail-remote.c +++ b/qmail-remote.c | |||
| @@ -82,10 +82,15 @@ void out(s) char *s; { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); } | |||
| 82 | void zero() { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); } | 82 | void zero() { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); } |
| 83 | void zeroflush() { zero(); substdio_flush(subfdoutsmall); } | 83 | void zeroflush() { zero(); substdio_flush(subfdoutsmall); } |
| 84 | void zerodie() { zeroflush(); _exit(0); } | 84 | void zerodie() { zeroflush(); _exit(0); } |
| 85 | void outsafe(sa) stralloc *sa; { int i; unsigned char ch; | 85 | void outsafe(const stralloc *sa) { |
| 86 | for (i = 0;i < sa->len;++i) { | 86 | int i; unsigned char ch; |
| 87 | ch = sa->s[i]; if (ch < 33) ch = '?'; if (ch > 126 && ch <= 127) ch = '?'; | 87 | for (i = 0;i < sa->len;++i) { |
| 88 | if (substdio_put(subfdoutsmall,&ch,1) == -1) _exit(0); } } | 88 | ch = sa->s[i]; |
| 89 | if (ch < 33) ch = '?'; | ||
| 90 | if (ch > 126 && ch <= 127) ch = '?'; | ||
| 91 | if (substdio_put(subfdoutsmall,&ch,1) == -1) _exit(0); | ||
| 92 | } | ||
| 93 | } | ||
| 89 | 94 | ||
| 90 | void temp_nomem() { out("ZOut of memory. (#4.3.0)\n"); zerodie(); } | 95 | void temp_nomem() { out("ZOut of memory. (#4.3.0)\n"); zerodie(); } |
| 91 | void temp_oserr() { out("Z\ | 96 | void temp_oserr() { out("Z\ |
| @@ -511,6 +516,11 @@ static int tls_init(unsigned long code, struct ip_mx *current_mx) | |||
| 511 | } | 516 | } |
| 512 | /* set the callback here; SSL_set_verify didn't work before 0.9.6c */ | 517 | /* set the callback here; SSL_set_verify didn't work before 0.9.6c */ |
| 513 | SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_cb); | 518 | SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_cb); |
| 519 | |||
| 520 | X509_VERIFY_PARAM *param = X509_VERIFY_PARAM_new(); | ||
| 521 | X509_VERIFY_PARAM_set1_host(param, mx_host, 0); | ||
| 522 | SSL_CTX_set1_param(ctx, param); | ||
| 523 | X509_VERIFY_PARAM_free(param); | ||
| 514 | } | 524 | } |
| 515 | 525 | ||
| 516 | /* let the other side complain if it needs a cert and we don't have one */ | 526 | /* let the other side complain if it needs a cert and we don't have one */ |
| @@ -681,47 +691,6 @@ static int tls_init(unsigned long code, struct ip_mx *current_mx) | |||
| 681 | tls_quit(servercert, X509_verify_cert_error_string(r)); | 691 | tls_quit(servercert, X509_verify_cert_error_string(r)); |
| 682 | } | 692 | } |
| 683 | alloc_free(servercert); | 693 | alloc_free(servercert); |
| 684 | |||
| 685 | peercert = SSL_get_peer_certificate(myssl); | ||
| 686 | if (!peercert) { | ||
| 687 | out("ZTLS unable to verify server "); | ||
| 688 | tls_quit(mx_host, "no certificate provided"); | ||
| 689 | } | ||
| 690 | |||
| 691 | /* RFC 2595 section 2.4: find a matching name | ||
| 692 | * first find a match among alternative names */ | ||
| 693 | gens = X509_get_ext_d2i(peercert, NID_subject_alt_name, 0, 0); | ||
| 694 | if (gens) { | ||
| 695 | for (i = 0, r = sk_GENERAL_NAME_num(gens); i < r; ++i) | ||
| 696 | { | ||
| 697 | const GENERAL_NAME *gn = sk_GENERAL_NAME_value(gens, i); | ||
| 698 | if (gn->type == GEN_DNS) | ||
| 699 | if (match_mx_host(mx_host, ASN1_STRING_get0_data(gn->d.dNSName), ASN1_STRING_length(gn->d.dNSName))) break; | ||
| 700 | } | ||
| 701 | sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); | ||
| 702 | } | ||
| 703 | |||
| 704 | /* no alternative name matched, look up commonName */ | ||
| 705 | if (!gens || i >= r) { | ||
| 706 | stralloc peer = {0}; | ||
| 707 | X509_NAME *subj = X509_get_subject_name(peercert); | ||
| 708 | i = X509_NAME_get_index_by_NID(subj, NID_commonName, -1); | ||
| 709 | if (i >= 0) { | ||
| 710 | X509_NAME_ENTRY *entry = X509_NAME_get_entry(subj, i); | ||
| 711 | ASN1_STRING *s = X509_NAME_ENTRY_get_data(entry); | ||
| 712 | if (s) { peer.len = ASN1_STRING_length(s); peer.s = (char *)ASN1_STRING_get0_data(s); } | ||
| 713 | } | ||
| 714 | if (peer.len <= 0) { | ||
| 715 | out("ZTLS unable to verify server "); | ||
| 716 | tls_quit(mx_host, "certificate contains no valid commonName"); | ||
| 717 | } | ||
| 718 | if (!match_mx_host(mx_host, peer.s, peer.len)) { | ||
| 719 | out("ZTLS unable to verify server "); out(mx_host); | ||
| 720 | out(": received certificate for "); outsafe(&peer); TLS_QUIT; | ||
| 721 | } | ||
| 722 | } | ||
| 723 | |||
| 724 | X509_free(peercert); | ||
| 725 | } | 694 | } |
| 726 | /* DANE: verify result */ | 695 | /* DANE: verify result */ |
| 727 | else if (tlsa_rr.len) { | 696 | else if (tlsa_rr.len) { |
