diff options
| author | manuel <manuel@mausz.at> | 2015-07-24 14:16:16 +0200 |
|---|---|---|
| committer | manuel <manuel@mausz.at> | 2015-07-24 14:16:16 +0200 |
| commit | 6fc0d9657d169aea8e05874c7f953f47c82deb33 (patch) | |
| tree | a2edfb998a96bb9d87c909d2ce61f0f8cc258489 | |
| parent | 0afd1f46d4c35cc17cb412e94a1ffbcf8bd2991c (diff) | |
| download | qmail-6fc0d9657d169aea8e05874c7f953f47c82deb33.tar.gz qmail-6fc0d9657d169aea8e05874c7f953f47c82deb33.tar.bz2 qmail-6fc0d9657d169aea8e05874c7f953f47c82deb33.zip | |
update DANE support to libval 2.1 (+fixes)
| -rw-r--r-- | qmail-remote.c | 55 |
1 files changed, 35 insertions, 20 deletions
diff --git a/qmail-remote.c b/qmail-remote.c index ece335d..4119228 100644 --- a/qmail-remote.c +++ b/qmail-remote.c | |||
| @@ -74,6 +74,7 @@ char **myargv; | |||
| 74 | val_context_t *dane_context = NULL; | 74 | val_context_t *dane_context = NULL; |
| 75 | int dane_context_failed = 0; | 75 | int dane_context_failed = 0; |
| 76 | struct val_danestatus *dane_status = NULL; | 76 | struct val_danestatus *dane_status = NULL; |
| 77 | struct val_ssl_data *dane_ssl_data = NULL; | ||
| 77 | #endif | 78 | #endif |
| 78 | 79 | ||
| 79 | void out(s) char *s; { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); } | 80 | void out(s) char *s; { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); } |
| @@ -301,7 +302,7 @@ void smtp_quit() | |||
| 301 | /* waiting for remote side is just too ridiculous */ | 302 | /* waiting for remote side is just too ridiculous */ |
| 302 | } | 303 | } |
| 303 | 304 | ||
| 304 | void quit2(char *prepend, char *append, int flagdie) | 305 | void quit2(const char *prepend, const char *append, int flagdie) |
| 305 | { | 306 | { |
| 306 | smtp_quit(); | 307 | smtp_quit(); |
| 307 | out(prepend); | 308 | out(prepend); |
| @@ -430,25 +431,26 @@ int tls_init() | |||
| 430 | int tls_required = (smtps || servercert != NULL); | 431 | int tls_required = (smtps || servercert != NULL); |
| 431 | 432 | ||
| 432 | if (partner_fqdn && !servercert && !dane_context_failed) { | 433 | if (partner_fqdn && !servercert && !dane_context_failed) { |
| 433 | if (val_create_context(NULL, &dane_context) == VAL_NO_ERROR) { | 434 | if (dane_context == NULL && val_create_context(NULL, &dane_context) |
| 435 | != VAL_NO_ERROR) { | ||
| 436 | dane_context_failed = 1; | ||
| 437 | out("lUnable to initialize libval context\n"); | ||
| 438 | zeroflush(); | ||
| 439 | } | ||
| 440 | |||
| 441 | if (dane_context) { | ||
| 442 | val_free_dane(dane_status); | ||
| 443 | val_free_dane_ssl(dane_ssl_data); | ||
| 444 | |||
| 434 | /* DANE: lookup TLSA records */ | 445 | /* DANE: lookup TLSA records */ |
| 435 | struct val_daneparams dane_params = { | 446 | struct val_daneparams dane_params = { |
| 436 | .port = smtp_port, | 447 | .port = smtp_port, |
| 437 | .proto = DANE_PARAM_PROTO_TCP | 448 | .proto = DANE_PARAM_PROTO_TCP |
| 438 | }; | 449 | }; |
| 439 | if (dane_status != NULL) | ||
| 440 | val_free_dane(dane_status); | ||
| 441 | dane_retval = val_getdaneinfo(dane_context, partner_fqdn, &dane_params, &dane_status); | 450 | dane_retval = val_getdaneinfo(dane_context, partner_fqdn, &dane_params, &dane_status); |
| 442 | if (dane_status == NULL) // insecure domain without TLSA RR will return VAL_DANE_NOERROR | 451 | if (dane_retval == VAL_DANE_NOERROR) |
| 443 | dane_retval = VAL_DANE_CHECK_FAILED; | ||
| 444 | else if (dane_retval == VAL_DANE_NOERROR) | ||
| 445 | tls_required = 1; | 452 | tls_required = 1; |
| 446 | } | 453 | } |
| 447 | else { | ||
| 448 | dane_context_failed = 1; | ||
| 449 | out("lUnable to initialize libval context\n"); | ||
| 450 | zeroflush(); | ||
| 451 | } | ||
| 452 | } | 454 | } |
| 453 | 455 | ||
| 454 | if (!smtps) { | 456 | if (!smtps) { |
| @@ -480,6 +482,19 @@ int tls_init() | |||
| 480 | /* set the callback here; SSL_set_verify didn't work before 0.9.6c */ | 482 | /* set the callback here; SSL_set_verify didn't work before 0.9.6c */ |
| 481 | SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_cb); | 483 | SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_cb); |
| 482 | } | 484 | } |
| 485 | else if (dane_retval == VAL_DANE_NOERROR) { | ||
| 486 | /* DANE: treat PKIX-EE as it were DANE-EE */ | ||
| 487 | struct val_danestatus *dane_cur; | ||
| 488 | for (dane_cur = dane_status; dane_cur; dane_cur = dane_cur->next) { | ||
| 489 | if (dane_cur->usage == DANE_USE_SVC_CONSTRAINT) | ||
| 490 | dane_cur->usage = DANE_USE_DOMAIN_ISSUED; | ||
| 491 | } | ||
| 492 | /* DANE: set verify callback */ | ||
| 493 | int err = val_enable_dane_ssl(dane_context, ctx, partner_fqdn, dane_status, | ||
| 494 | &dane_ssl_data); | ||
| 495 | if (err != VAL_NO_ERROR) | ||
| 496 | tls_quit("ZCould not enable dane verification", p_val_error(err)); | ||
| 497 | } | ||
| 483 | 498 | ||
| 484 | /* let the other side complain if it needs a cert and we don't have one */ | 499 | /* let the other side complain if it needs a cert and we don't have one */ |
| 485 | if (SSL_CTX_use_certificate_chain_file(ctx, CLIENTCERT)) | 500 | if (SSL_CTX_use_certificate_chain_file(ctx, CLIENTCERT)) |
| @@ -532,10 +547,12 @@ int tls_init() | |||
| 532 | if (tls_required) | 547 | if (tls_required) |
| 533 | tls_quit("ZTLS connect failed", ssl_error_str()); | 548 | tls_quit("ZTLS connect failed", ssl_error_str()); |
| 534 | else { | 549 | else { |
| 535 | smtp_quit(); | 550 | out("lTLS connect failed"); |
| 536 | 551 | const char *err = ssl_error_str(); | |
| 537 | out("lTLS connect failed: "); | 552 | if (err) { |
| 538 | out(ssl_error_str()); | 553 | out(": "); |
| 554 | out(err); | ||
| 555 | } | ||
| 539 | out("; retrying without TLS\n"); | 556 | out("; retrying without TLS\n"); |
| 540 | zeroflush(); | 557 | zeroflush(); |
| 541 | 558 | ||
| @@ -597,11 +614,9 @@ int tls_init() | |||
| 597 | 614 | ||
| 598 | X509_free(peercert); | 615 | X509_free(peercert); |
| 599 | } | 616 | } |
| 600 | /* DANE: verify tls connection */ | 617 | /* DANE: verify result */ |
| 601 | else if (dane_retval == VAL_DANE_NOERROR) { | 618 | else if (dane_retval == VAL_DANE_NOERROR) { |
| 602 | int do_certcheck = 0; // ignored. DANE SMTP doesn't do any PKIX checks | 619 | if (!SSL_get_peer_certificate(ssl) || SSL_get_verify_result(ssl) != X509_V_OK) { |
| 603 | dane_retval = val_dane_check(dane_context, ssl, dane_status, &do_certcheck); | ||
| 604 | if (dane_retval != VAL_DANE_NOERROR) { | ||
| 605 | out("lNo TLSA record matched: "); | 620 | out("lNo TLSA record matched: "); |
| 606 | out(partner_fqdn); | 621 | out(partner_fqdn); |
| 607 | quit2("/", NULL, 0); | 622 | quit2("/", NULL, 0); |
