summaryrefslogtreecommitdiffstats
path: root/qmail-remote.c
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2026-04-28 12:20:56 +0200
committermanuel <manuel@mausz.at>2026-04-28 12:20:56 +0200
commit2a7f632316cda04ddaf6672c64d61a1ca1d2a6e6 (patch)
tree18369c0024f661ab3757fdc602ff491c8941d97d /qmail-remote.c
parent0552b77cfb593891abe8cc7726f66fba53218149 (diff)
downloadqmail-2a7f632316cda04ddaf6672c64d61a1ca1d2a6e6.tar.gz
qmail-2a7f632316cda04ddaf6672c64d61a1ca1d2a6e6.tar.bz2
qmail-2a7f632316cda04ddaf6672c64d61a1ca1d2a6e6.zip
qmail-remote: let openssl verify the certificate
this is veeery old code. openssl already handles this for us
Diffstat (limited to 'qmail-remote.c')
-rw-r--r--qmail-remote.c59
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); }
82void zero() { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); } 82void zero() { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); }
83void zeroflush() { zero(); substdio_flush(subfdoutsmall); } 83void zeroflush() { zero(); substdio_flush(subfdoutsmall); }
84void zerodie() { zeroflush(); _exit(0); } 84void zerodie() { zeroflush(); _exit(0); }
85void outsafe(sa) stralloc *sa; { int i; unsigned char ch; 85void outsafe(const stralloc *sa) {
86for (i = 0;i < sa->len;++i) { 86 int i; unsigned char ch;
87ch = sa->s[i]; if (ch < 33) ch = '?'; if (ch > 126 && ch <= 127) ch = '?'; 87 for (i = 0;i < sa->len;++i) {
88if (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
90void temp_nomem() { out("ZOut of memory. (#4.3.0)\n"); zerodie(); } 95void temp_nomem() { out("ZOut of memory. (#4.3.0)\n"); zerodie(); }
91void temp_oserr() { out("Z\ 96void 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) {