diff options
Diffstat (limited to 'qmail-remote.c')
| -rw-r--r-- | qmail-remote.c | 197 |
1 files changed, 107 insertions, 90 deletions
diff --git a/qmail-remote.c b/qmail-remote.c index 0e2377e..1a09df9 100644 --- a/qmail-remote.c +++ b/qmail-remote.c | |||
| @@ -63,8 +63,6 @@ struct ip_address partner; | |||
| 63 | # include "tls.h" | 63 | # include "tls.h" |
| 64 | # include "ssl_timeoutio.h" | 64 | # include "ssl_timeoutio.h" |
| 65 | # include <openssl/x509v3.h> | 65 | # include <openssl/x509v3.h> |
| 66 | # include <validator/validator.h> | ||
| 67 | # include <validator/val_dane.h> | ||
| 68 | 66 | ||
| 69 | # define EHLO 1 | 67 | # define EHLO 1 |
| 70 | # define CLIENTCERT "control/clientcert.pem" | 68 | # define CLIENTCERT "control/clientcert.pem" |
| @@ -72,10 +70,6 @@ struct ip_address partner; | |||
| 72 | int tls_init(); | 70 | int tls_init(); |
| 73 | const char *ssl_err_str = 0; | 71 | const char *ssl_err_str = 0; |
| 74 | char **myargv; | 72 | char **myargv; |
| 75 | val_context_t *dane_context = NULL; | ||
| 76 | int dane_context_failed = 0; | ||
| 77 | struct val_danestatus *dane_status = NULL; | ||
| 78 | struct val_ssl_data *dane_ssl_data = NULL; | ||
| 79 | #endif | 73 | #endif |
| 80 | 74 | ||
| 81 | #ifdef SMTPUTF8 | 75 | #ifdef SMTPUTF8 |
| @@ -241,10 +235,6 @@ unsigned long ehlo() | |||
| 241 | if (ehlokw.len > maxehlokwlen) maxehlokwlen = ehlokw.len; | 235 | if (ehlokw.len > maxehlokwlen) maxehlokwlen = ehlokw.len; |
| 242 | ehlokw.len = 0; | 236 | ehlokw.len = 0; |
| 243 | 237 | ||
| 244 | # ifdef MXPS | ||
| 245 | if (type == 's') return 0; | ||
| 246 | # endif | ||
| 247 | |||
| 248 | substdio_puts(&smtpto, "EHLO "); | 238 | substdio_puts(&smtpto, "EHLO "); |
| 249 | substdio_put(&smtpto, helohost.s, helohost.len); | 239 | substdio_put(&smtpto, helohost.s, helohost.len); |
| 250 | substdio_puts(&smtpto, "\r\n"); | 240 | substdio_puts(&smtpto, "\r\n"); |
| @@ -437,34 +427,28 @@ int tls_init() | |||
| 437 | } | 427 | } |
| 438 | } | 428 | } |
| 439 | 429 | ||
| 440 | /* DANE: starts here */ | 430 | /* DANE: lookup TLSA records */ |
| 441 | int dane_retval = VAL_DANE_INTERNAL_ERROR; | ||
| 442 | int tls_required = (smtps || servercert != NULL); | 431 | int tls_required = (smtps || servercert != NULL); |
| 443 | 432 | stralloc tlsa_rr = { 0 }; | |
| 444 | if (partner_fqdn && !servercert && !dane_context_failed) { | 433 | |
| 445 | if (dane_context == NULL && val_create_context(NULL, &dane_context) | 434 | if (partner_fqdn && !servercert) { |
| 446 | != VAL_NO_ERROR) { | 435 | stralloc tlsa_label = { 0 }; |
| 447 | dane_context_failed = 1; | 436 | char port[FMT_ULONG]; |
| 448 | out("lUnable to initialize libval context\n"); | 437 | |
| 449 | zeroflush(); | 438 | if (!stralloc_copyb(&tlsa_label, "_", 1)) temp_nomem(); |
| 439 | port[fmt_ulong(port, smtp_port)] = 0; | ||
| 440 | if (!stralloc_cats(&tlsa_label, port)) temp_nomem(); | ||
| 441 | if (!stralloc_cats(&tlsa_label, "._tcp.")) temp_nomem(); | ||
| 442 | if (!stralloc_cats(&tlsa_label, partner_fqdn)) temp_nomem(); | ||
| 443 | |||
| 444 | switch (dns_tlsa(&tlsa_rr, &tlsa_label)) { | ||
| 445 | case DNS_MEM: temp_nomem(); | ||
| 446 | case DNS_SOFT: temp_dns(); | ||
| 447 | case DNS_HARD: tlsa_rr.len = 0; // no record found | ||
| 450 | } | 448 | } |
| 451 | 449 | ||
| 452 | if (dane_context) { | 450 | if (tlsa_rr.len) |
| 453 | val_free_dane(dane_status); | 451 | tls_required = 1; |
| 454 | val_free_dane_ssl(dane_ssl_data); | ||
| 455 | |||
| 456 | /* DANE: lookup TLSA records */ | ||
| 457 | struct val_daneparams dane_params = { | ||
| 458 | .port = smtp_port, | ||
| 459 | .proto = DANE_PARAM_PROTO_TCP | ||
| 460 | }; | ||
| 461 | dane_retval = val_getdaneinfo(dane_context, partner_fqdn, &dane_params, &dane_status); | ||
| 462 | /* work around a bug if no error but no also no records */ | ||
| 463 | if (dane_retval == VAL_DANE_NOERROR && dane_status == NULL) | ||
| 464 | dane_retval = VAL_DANE_IGNORE_TLSA; | ||
| 465 | if (dane_retval == VAL_DANE_NOERROR) | ||
| 466 | tls_required = 1; | ||
| 467 | } | ||
| 468 | } | 452 | } |
| 469 | 453 | ||
| 470 | if (!smtps) { | 454 | if (!smtps) { |
| @@ -480,13 +464,20 @@ int tls_init() | |||
| 480 | } | 464 | } |
| 481 | 465 | ||
| 482 | SSL_library_init(); | 466 | SSL_library_init(); |
| 483 | ctx = SSL_CTX_new(SSLv23_client_method()); | 467 | ctx = SSL_CTX_new(TLS_client_method()); |
| 484 | if (!ctx) { | 468 | if (!ctx) { |
| 485 | if (!tls_required) return 0; | ||
| 486 | smtptext.len = 0; | 469 | smtptext.len = 0; |
| 487 | tls_quit_error("ZTLS error initializing ctx"); | 470 | tls_quit_error("ZTLS error initializing ctx"); |
| 488 | } | 471 | } |
| 489 | SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3); | 472 | SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION); |
| 473 | |||
| 474 | /* we verify ourself below. see SSL_get_verify_result */ | ||
| 475 | SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); | ||
| 476 | |||
| 477 | if (SSL_CTX_dane_enable(ctx) <= 0) { | ||
| 478 | smtptext.len = 0; | ||
| 479 | tls_quit_error("ZTLS error initializing dane ctx"); | ||
| 480 | } | ||
| 490 | 481 | ||
| 491 | if (servercert) { | 482 | if (servercert) { |
| 492 | if (!SSL_CTX_load_verify_locations(ctx, servercert, NULL)) { | 483 | if (!SSL_CTX_load_verify_locations(ctx, servercert, NULL)) { |
| @@ -497,19 +488,6 @@ int tls_init() | |||
| 497 | /* set the callback here; SSL_set_verify didn't work before 0.9.6c */ | 488 | /* set the callback here; SSL_set_verify didn't work before 0.9.6c */ |
| 498 | SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_cb); | 489 | SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_cb); |
| 499 | } | 490 | } |
| 500 | else if (dane_retval == VAL_DANE_NOERROR) { | ||
| 501 | /* DANE: treat PKIX-EE as it were DANE-EE */ | ||
| 502 | struct val_danestatus *dane_cur; | ||
| 503 | for (dane_cur = dane_status; dane_cur; dane_cur = dane_cur->next) { | ||
| 504 | if (dane_cur->usage == DANE_USE_SVC_CONSTRAINT) | ||
| 505 | dane_cur->usage = DANE_USE_DOMAIN_ISSUED; | ||
| 506 | } | ||
| 507 | /* DANE: set verify callback */ | ||
| 508 | int err = val_enable_dane_ssl(dane_context, ctx, partner_fqdn, dane_status, | ||
| 509 | &dane_ssl_data); | ||
| 510 | if (err != VAL_NO_ERROR) | ||
| 511 | tls_quit("ZCould not enable dane verification", p_val_error(err)); | ||
| 512 | } | ||
| 513 | 491 | ||
| 514 | /* let the other side complain if it needs a cert and we don't have one */ | 492 | /* let the other side complain if it needs a cert and we don't have one */ |
| 515 | if (SSL_CTX_use_certificate_chain_file(ctx, CLIENTCERT)) | 493 | if (SSL_CTX_use_certificate_chain_file(ctx, CLIENTCERT)) |
| @@ -518,14 +496,10 @@ int tls_init() | |||
| 518 | myssl = SSL_new(ctx); | 496 | myssl = SSL_new(ctx); |
| 519 | SSL_CTX_free(ctx); | 497 | SSL_CTX_free(ctx); |
| 520 | if (!myssl) { | 498 | if (!myssl) { |
| 521 | if (!tls_required) return 0; | ||
| 522 | smtptext.len = 0; | 499 | smtptext.len = 0; |
| 523 | tls_quit_error("ZTLS error initializing ssl"); | 500 | tls_quit_error("ZTLS error initializing ssl"); |
| 524 | } | 501 | } |
| 525 | 502 | ||
| 526 | if (!smtps) | ||
| 527 | substdio_putsflush(&smtpto, "STARTTLS\r\n"); | ||
| 528 | |||
| 529 | /* while the server is preparing a responce, do something else */ | 503 | /* while the server is preparing a responce, do something else */ |
| 530 | if (control_readfile(&saciphers, "control/tlsclientciphers", 0) == -1) | 504 | if (control_readfile(&saciphers, "control/tlsclientciphers", 0) == -1) |
| 531 | { SSL_free(myssl); temp_control(); } | 505 | { SSL_free(myssl); temp_control(); } |
| @@ -539,14 +513,15 @@ int tls_init() | |||
| 539 | SSL_set_cipher_list(myssl, ciphers); | 513 | SSL_set_cipher_list(myssl, ciphers); |
| 540 | alloc_free(saciphers.s); | 514 | alloc_free(saciphers.s); |
| 541 | 515 | ||
| 542 | #if OPENSSL_VERSION_NUMBER >= 0x10100005L | ||
| 543 | stralloc opensslconf = {0}; | 516 | stralloc opensslconf = {0}; |
| 544 | if (control_readfile(&opensslconf, "control/opensslconf", 0) == -1) | 517 | if (control_readfile(&opensslconf, "control/opensslconf", 0) == -1) |
| 545 | { SSL_free(myssl); temp_control(); } | 518 | { SSL_free(myssl); temp_control(); } |
| 546 | if (opensslconf.len) { | 519 | if (opensslconf.len) { |
| 547 | SSL_CONF_CTX *cctx = SSL_CONF_CTX_new(); | 520 | SSL_CONF_CTX *cctx = SSL_CONF_CTX_new(); |
| 548 | SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE); | 521 | SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE); |
| 522 | /* client + server so we can share one single file */ | ||
| 549 | SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CLIENT); | 523 | SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CLIENT); |
| 524 | SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER); | ||
| 550 | SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CERTIFICATE); | 525 | SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CERTIFICATE); |
| 551 | SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SHOW_ERRORS); | 526 | SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SHOW_ERRORS); |
| 552 | SSL_CONF_CTX_set_ssl(cctx, myssl); | 527 | SSL_CONF_CTX_set_ssl(cctx, myssl); |
| @@ -572,13 +547,68 @@ int tls_init() | |||
| 572 | 547 | ||
| 573 | (void)SSL_CONF_CTX_finish(cctx); | 548 | (void)SSL_CONF_CTX_finish(cctx); |
| 574 | } | 549 | } |
| 575 | #endif | ||
| 576 | 550 | ||
| 577 | /* set SNI hostname */ | 551 | /* set SNI hostname */ |
| 578 | if (partner_fqdn) | 552 | if (partner_fqdn) |
| 579 | SSL_set_tlsext_host_name(myssl, partner_fqdn); | 553 | SSL_set_tlsext_host_name(myssl, partner_fqdn); |
| 580 | 554 | ||
| 581 | /* SSL_set_options(myssl, SSL_OP_NO_TLSv1); */ | 555 | /* DANE: enable + add records */ |
| 556 | if (tlsa_rr.len) { | ||
| 557 | if (SSL_dane_enable(myssl, partner_fqdn) <= 0) { | ||
| 558 | smtptext.len = 0; | ||
| 559 | tls_quit_error("ZTLS error enabling dane"); | ||
| 560 | } | ||
| 561 | SSL_dane_set_flags(myssl, DANE_FLAG_NO_DANE_EE_NAMECHECKS); | ||
| 562 | |||
| 563 | // loop through TLSA rr | ||
| 564 | int pos = 0, num_usable = 0; | ||
| 565 | unsigned char *rr_data = (unsigned char *)tlsa_rr.s; | ||
| 566 | while (pos < tlsa_rr.len && tlsa_rr.len - pos > 2 + 4) // sizeof(rrlen) + min(rrdata) | ||
| 567 | { | ||
| 568 | unsigned short rrlen = (rr_data[pos] << 8) + rr_data[pos + 1]; | ||
| 569 | pos += 2; | ||
| 570 | uint8_t usage = rr_data[pos]; | ||
| 571 | uint8_t selector = rr_data[pos + 1]; | ||
| 572 | uint8_t mtype = rr_data[pos + 2]; | ||
| 573 | |||
| 574 | /* | ||
| 575 | * Opportunistic DANE TLS clients support only DANE-TA(2) or DANE-EE(3). | ||
| 576 | * They treat all other certificate usages, and in particular PKIX-TA(0) | ||
| 577 | * and PKIX-EE(1), as unusable. | ||
| 578 | */ | ||
| 579 | switch (usage) { | ||
| 580 | default: | ||
| 581 | case 0: /* PKIX-TA(0) */ | ||
| 582 | case 1: /* PKIX-EE(1) */ | ||
| 583 | pos += rrlen; | ||
| 584 | continue; | ||
| 585 | case 2: /* DANE-TA(2) */ | ||
| 586 | case 3: /* DANE-EE(3) */ | ||
| 587 | break; | ||
| 588 | } | ||
| 589 | |||
| 590 | // rrlen includes usage+selector+mtype (3) byte. remove | ||
| 591 | unsigned const char *cdata = rr_data + pos + 3; | ||
| 592 | size_t cdlen = rrlen - 3; | ||
| 593 | int tlsa_added = SSL_dane_tlsa_add(myssl, usage, selector, mtype, cdata, cdlen); | ||
| 594 | if (tlsa_added < 0) { | ||
| 595 | smtptext.len = 0; | ||
| 596 | tls_quit_error("ZTLS error adding DANE TLSA record"); | ||
| 597 | } | ||
| 598 | else if (tlsa_added > 0) | ||
| 599 | ++num_usable; | ||
| 600 | |||
| 601 | pos += rrlen; | ||
| 602 | } | ||
| 603 | |||
| 604 | // no records usable. fallback to unauthenticated TLS | ||
| 605 | if (num_usable == 0) | ||
| 606 | tlsa_rr.len = 0; | ||
| 607 | } | ||
| 608 | |||
| 609 | if (!smtps) | ||
| 610 | substdio_putsflush(&smtpto, "STARTTLS\r\n"); | ||
| 611 | |||
| 582 | SSL_set_fd(myssl, smtpfd); | 612 | SSL_set_fd(myssl, smtpfd); |
| 583 | 613 | ||
| 584 | /* read the responce to STARTTLS */ | 614 | /* read the responce to STARTTLS */ |
| @@ -593,7 +623,7 @@ int tls_init() | |||
| 593 | } | 623 | } |
| 594 | 624 | ||
| 595 | ssl = myssl; | 625 | ssl = myssl; |
| 596 | if (ssl_timeoutconn(timeout, smtpfd, smtpfd, ssl) <= 0) { | 626 | if (ssl_timeoutconn(timeout, smtpfd, smtpfd, myssl) <= 0) { |
| 597 | if (tls_required) | 627 | if (tls_required) |
| 598 | tls_quit("ZTLS connect failed", ssl_error_str()); | 628 | tls_quit("ZTLS connect failed", ssl_error_str()); |
| 599 | else { | 629 | else { |
| @@ -617,14 +647,14 @@ int tls_init() | |||
| 617 | X509 *peercert; | 647 | X509 *peercert; |
| 618 | STACK_OF(GENERAL_NAME) *gens; | 648 | STACK_OF(GENERAL_NAME) *gens; |
| 619 | 649 | ||
| 620 | int r = SSL_get_verify_result(ssl); | 650 | int r = SSL_get_verify_result(myssl); |
| 621 | if (r != X509_V_OK) { | 651 | if (r != X509_V_OK) { |
| 622 | out("ZTLS unable to verify server with "); | 652 | out("ZTLS unable to verify server with "); |
| 623 | tls_quit(servercert, X509_verify_cert_error_string(r)); | 653 | tls_quit(servercert, X509_verify_cert_error_string(r)); |
| 624 | } | 654 | } |
| 625 | alloc_free(servercert); | 655 | alloc_free(servercert); |
| 626 | 656 | ||
| 627 | peercert = SSL_get_peer_certificate(ssl); | 657 | peercert = SSL_get_peer_certificate(myssl); |
| 628 | if (!peercert) { | 658 | if (!peercert) { |
| 629 | out("ZTLS unable to verify server "); | 659 | out("ZTLS unable to verify server "); |
| 630 | tls_quit(partner_fqdn, "no certificate provided"); | 660 | tls_quit(partner_fqdn, "no certificate provided"); |
| @@ -651,10 +681,7 @@ int tls_init() | |||
| 651 | if (i >= 0) { | 681 | if (i >= 0) { |
| 652 | X509_NAME_ENTRY *entry = X509_NAME_get_entry(subj, i); | 682 | X509_NAME_ENTRY *entry = X509_NAME_get_entry(subj, i); |
| 653 | ASN1_STRING *s = X509_NAME_ENTRY_get_data(entry); | 683 | ASN1_STRING *s = X509_NAME_ENTRY_get_data(entry); |
| 654 | #if OPENSSL_VERSION_NUMBER < 0x10100005L | 684 | if (s) { peer.len = ASN1_STRING_length(s); peer.s = (char *)ASN1_STRING_get0_data(s); } |
| 655 | #define ASN1_STRING_get0_data ASN1_STRING_data | ||
| 656 | #endif | ||
| 657 | if (s) { peer.len = ASN1_STRING_length(s); peer.s = (unsigned char *)ASN1_STRING_get0_data(s); } | ||
| 658 | } | 685 | } |
| 659 | if (peer.len <= 0) { | 686 | if (peer.len <= 0) { |
| 660 | out("ZTLS unable to verify server "); | 687 | out("ZTLS unable to verify server "); |
| @@ -669,8 +696,8 @@ int tls_init() | |||
| 669 | X509_free(peercert); | 696 | X509_free(peercert); |
| 670 | } | 697 | } |
| 671 | /* DANE: verify result */ | 698 | /* DANE: verify result */ |
| 672 | else if (dane_retval == VAL_DANE_NOERROR) { | 699 | else if (tlsa_rr.len) { |
| 673 | if (!SSL_get_peer_certificate(ssl) || SSL_get_verify_result(ssl) != X509_V_OK) { | 700 | if (!SSL_get_peer_certificate(myssl) || SSL_get_verify_result(myssl) != X509_V_OK) { |
| 674 | out("lNo TLSA record matched: "); | 701 | out("lNo TLSA record matched: "); |
| 675 | out(partner_fqdn); | 702 | out(partner_fqdn); |
| 676 | quit2("/", NULL, 0); | 703 | quit2("/", NULL, 0); |
| @@ -746,33 +773,22 @@ void mail_without_auth() | |||
| 746 | 773 | ||
| 747 | void smtp() | 774 | void smtp() |
| 748 | { | 775 | { |
| 749 | unsigned long code; | 776 | unsigned long code = 0; |
| 750 | int flagbother; | 777 | int flagbother; |
| 751 | int i, j; | ||
| 752 | |||
| 753 | #ifndef PORT_SMTP | ||
| 754 | /* the qmtpc patch uses smtp_port and undefines PORT_SMTP */ | ||
| 755 | # define port smtp_port | ||
| 756 | #endif | ||
| 757 | 778 | ||
| 758 | #ifdef TLS | 779 | #ifdef TLS |
| 759 | # ifdef MXPS | 780 | if (smtp_port == 465) smtps = 1; |
| 760 | if (type == 'S') smtps = 1; | 781 | if (!smtps) { |
| 761 | else if (type != 's') | ||
| 762 | # endif | ||
| 763 | if (port == 465) smtps = 1; | ||
| 764 | if (!smtps) | ||
| 765 | #endif | 782 | #endif |
| 766 | |||
| 767 | code = smtpcode(); | 783 | code = smtpcode(); |
| 768 | if (code >= 500 && code < 600) quit("DConnected to "," but greeting failed"); | 784 | if (code >= 500 && code < 600) quit("DConnected to "," but greeting failed"); |
| 769 | if (code >= 400 && code < 500) return; /* try next MX, see RFC-2821 */ | 785 | if (code >= 400 && code < 500) return; /* try next MX, see RFC-2821 */ |
| 770 | if (code != 220) quit("ZConnected to "," but greeting failed"); | 786 | if (code != 220) quit("ZConnected to "," but greeting failed"); |
| 771 | 787 | ||
| 788 | code = ehlo(); | ||
| 772 | #ifdef TLS | 789 | #ifdef TLS |
| 773 | if (!smtps) | 790 | } |
| 774 | #endif | 791 | #endif |
| 775 | code = ehlo(); | ||
| 776 | 792 | ||
| 777 | #ifdef TLS | 793 | #ifdef TLS |
| 778 | int tls = tls_init(); | 794 | int tls = tls_init(); |
| @@ -782,7 +798,7 @@ void smtp() | |||
| 782 | ssl = NULL; | 798 | ssl = NULL; |
| 783 | return; /* try next MX */ | 799 | return; /* try next MX */ |
| 784 | } | 800 | } |
| 785 | else if (tls) | 801 | else if (tls > 0) |
| 786 | /* RFC2487 says we should issue EHLO (even if we might not need | 802 | /* RFC2487 says we should issue EHLO (even if we might not need |
| 787 | * extensions); at the same time, it does not prohibit a server | 803 | * extensions); at the same time, it does not prohibit a server |
| 788 | * to reject the EHLO and make us fallback to HELO */ | 804 | * to reject the EHLO and make us fallback to HELO */ |
| @@ -803,7 +819,7 @@ void smtp() | |||
| 803 | if (code != 250) quit("ZConnected to "," but my name was rejected"); | 819 | if (code != 250) quit("ZConnected to "," but my name was rejected"); |
| 804 | } | 820 | } |
| 805 | 821 | ||
| 806 | i = 0; | 822 | int i = 0; |
| 807 | if (auth_smtp_user.len && auth_smtp_pass.len) { | 823 | if (auth_smtp_user.len && auth_smtp_pass.len) { |
| 808 | while((i += str_chr(smtptext.s+i,'\n') + 1) && | 824 | while((i += str_chr(smtptext.s+i,'\n') + 1) && |
| 809 | (i+8 < smtptext.len) && | 825 | (i+8 < smtptext.len) && |
| @@ -854,7 +870,7 @@ void smtp() | |||
| 854 | if (code >= 400) quit("ZConnected to "," but sender was rejected"); | 870 | if (code >= 400) quit("ZConnected to "," but sender was rejected"); |
| 855 | 871 | ||
| 856 | flagbother = 0; | 872 | flagbother = 0; |
| 857 | for (i = 0;i < reciplist.len;++i) { | 873 | for (int i = 0;i < reciplist.len;++i) { |
| 858 | substdio_puts(&smtpto,"RCPT TO:<"); | 874 | substdio_puts(&smtpto,"RCPT TO:<"); |
| 859 | substdio_put(&smtpto,reciplist.sa[i].s,reciplist.sa[i].len); | 875 | substdio_put(&smtpto,reciplist.sa[i].s,reciplist.sa[i].len); |
| 860 | substdio_puts(&smtpto,">\r\n"); | 876 | substdio_puts(&smtpto,">\r\n"); |
| @@ -907,7 +923,6 @@ void qmtp() | |||
| 907 | { | 923 | { |
| 908 | struct stat st; | 924 | struct stat st; |
| 909 | unsigned long len; | 925 | unsigned long len; |
| 910 | int len2; | ||
| 911 | char *x; | 926 | char *x; |
| 912 | int i; | 927 | int i; |
| 913 | int n; | 928 | int n; |
| @@ -1039,9 +1054,11 @@ void getcontrols() | |||
| 1039 | case -1: | 1054 | case -1: |
| 1040 | temp_control(); | 1055 | temp_control(); |
| 1041 | case 0: | 1056 | case 0: |
| 1042 | if (!constmap_init(&maproutes,"",0,1)) temp_nomem(); break; | 1057 | if (!constmap_init(&maproutes,"",0,1)) temp_nomem(); |
| 1058 | break; | ||
| 1043 | case 1: | 1059 | case 1: |
| 1044 | if (!constmap_init(&maproutes,routes.s,routes.len,1)) temp_nomem(); break; | 1060 | if (!constmap_init(&maproutes,routes.s,routes.len,1)) temp_nomem(); |
| 1061 | break; | ||
| 1045 | } | 1062 | } |
| 1046 | } | 1063 | } |
| 1047 | 1064 | ||
| @@ -1074,7 +1091,7 @@ char **argv; | |||
| 1074 | relayhost = 0; | 1091 | relayhost = 0; |
| 1075 | for (i = 0;i <= host.len;++i) | 1092 | for (i = 0;i <= host.len;++i) |
| 1076 | if ((i == 0) || (i == host.len) || (host.s[i] == '.')) | 1093 | if ((i == 0) || (i == host.len) || (host.s[i] == '.')) |
| 1077 | if (relayhost = constmap(&maproutes,host.s + i,host.len - i)) | 1094 | if ((relayhost = constmap(&maproutes,host.s + i,host.len - i))) |
| 1078 | break; | 1095 | break; |
| 1079 | if (relayhost && !*relayhost) relayhost = 0; | 1096 | if (relayhost && !*relayhost) relayhost = 0; |
| 1080 | 1097 | ||
