X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/981756dbc52b48a213522a9b0fcae82dfcf59352..8800895ae8a1e9c49c739839a6623292d7a473d0:/src/src/smtp_in.c diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c index 9b25c2333..c08d17972 100644 --- a/src/src/smtp_in.c +++ b/src/src/smtp_in.c @@ -1,10 +1,10 @@ -/* $Cambridge: exim/src/src/smtp_in.c,v 1.5 2004/11/10 15:21:16 ph10 Exp $ */ +/* $Cambridge: exim/src/src/smtp_in.c,v 1.25 2005/09/12 10:08:54 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2004 */ +/* Copyright (c) University of Cambridge 1995 - 2005 */ /* See the file NOTICE for conditions of use and distribution. */ /* Functions for handling an incoming SMTP call. */ @@ -34,9 +34,12 @@ int deny_severity = LOG_NOTICE; #endif -/* Size of buffer for reading SMTP commands */ +/* Size of buffer for reading SMTP commands. We used to use 512, as defined +by RFC 821. However, RFC 1869 specifies that this must be increased for SMTP +commands that accept arguments, and this in particular applies to AUTH, where +the data can be quite long. */ -#define cmd_buffer_size 512 /* Ref. RFC 821 */ +#define cmd_buffer_size 2048 /* Size of buffer for reading SMTP incoming packets */ @@ -116,8 +119,6 @@ static int unknown_command_count; static int sync_cmd_limit; static int smtp_write_error = 0; -static uschar *smtp_data; - static uschar *cmd_buffer; /* We need to know the position of RSET, HELO, EHLO, AUTH, and STARTTLS. Their @@ -532,7 +533,7 @@ for (p = cmd_list; p < cmd_list_end; p++) the following test, so that if it fails, the command name can easily be logged. */ - smtp_data = cmd_buffer + p->len; + smtp_command_argument = cmd_buffer + p->len; /* Count non-mail commands from those hosts that are controlled in this way. The default is all hosts. We don't waste effort checking the list @@ -550,11 +551,11 @@ for (p = cmd_list; p < cmd_list_end; p++) return TOO_MANY_NONMAIL_CMD; } - /* Get the data pointer over leading spaces and return; if there is no data - for a command that expects it, we give the error centrally here. */ + /* Get the data pointer over leading spaces and return; if there is data + for a command that does not expect it, give the error centrally here. */ - while (isspace(*smtp_data)) smtp_data++; - return (p->has_arg || *smtp_data == 0)? p->cmd : BADARG_CMD; + while (isspace(*smtp_command_argument)) smtp_command_argument++; + return (p->has_arg || *smtp_command_argument == 0)? p->cmd : BADARG_CMD; } } @@ -742,7 +743,7 @@ return yield; * Extract SMTP command option * *************************************************/ -/* This function picks the next option setting off the end of smtp_data. It +/* This function picks the next option setting off the end of smtp_command_argument. It is called for MAIL FROM and RCPT TO commands, to pick off the optional ESMTP things that can appear there. @@ -757,11 +758,11 @@ static BOOL extract_option(uschar **name, uschar **value) { uschar *n; -uschar *v = smtp_data + Ustrlen(smtp_data) -1; +uschar *v = smtp_command_argument + Ustrlen(smtp_command_argument) -1; while (isspace(*v)) v--; v[1] = 0; -while (v > smtp_data && *v != '=' && !isspace(*v)) v--; +while (v > smtp_command_argument && *v != '=' && !isspace(*v)) v--; if (*v != '=') return FALSE; n = v; @@ -801,22 +802,46 @@ store_reset(reset_point); recipients_list = NULL; rcpt_count = rcpt_defer_count = rcpt_fail_count = raw_recipients_count = recipients_count = recipients_list_max = 0; +message_linecount = 0; message_size = -1; acl_warn_headers = NULL; queue_only_policy = FALSE; deliver_freeze = FALSE; /* Can be set by ACL */ +fake_response = OK; /* Can be set by ACL */ +#ifdef WITH_CONTENT_SCAN +no_mbox_unspool = FALSE; /* Can be set by ACL */ +#endif submission_mode = FALSE; /* Can be set by ACL */ +suppress_local_fixups = FALSE; /* Can be set by ACL */ active_local_from_check = local_from_check; /* Can be set by ACL */ active_local_sender_retain = local_sender_retain; /* Can be set by ACL */ sender_address = NULL; +submission_name = NULL; /* Can be set by ACL */ raw_sender = NULL; /* After SMTP rewrite, before qualifying */ sender_address_unrewritten = NULL; /* Set only after verify rewrite */ sender_verified_list = NULL; /* No senders verified */ memset(sender_address_cache, 0, sizeof(sender_address_cache)); memset(sender_domain_cache, 0, sizeof(sender_domain_cache)); authenticated_sender = NULL; +#ifdef EXPERIMENTAL_BRIGHTMAIL +bmi_run = 0; +bmi_verdicts = NULL; +#endif +#ifdef EXPERIMENTAL_DOMAINKEYS +dk_do_verify = 0; +#endif +#ifdef EXPERIMENTAL_SPF +spf_header_comment = NULL; +spf_received = NULL; +spf_result = NULL; +spf_smtp_comment = NULL; +#endif body_linecount = body_zerocount = 0; +sender_rate = sender_rate_limit = sender_rate_period = NULL; +ratelimiters_mail = NULL; /* Updated by ratelimit ACL condition */ + /* Note that ratelimiters_conn persists across resets. */ + for (i = 0; i < ACL_M_MAX; i++) acl_var[ACL_C_MAX + i] = NULL; /* The message body variables use malloc store. They may be set if this is @@ -901,7 +926,7 @@ while (done <= 0) case HELO_CMD: case EHLO_CMD: - check_helo(smtp_data); + check_helo(smtp_command_argument); /* Fall through */ case RSET_CMD: @@ -921,7 +946,7 @@ while (done <= 0) /* The function moan_smtp_batch() does not return. */ moan_smtp_batch(cmd_buffer, "503 Sender already given"); - if (smtp_data[0] == 0) + if (smtp_command_argument[0] == 0) /* The function moan_smtp_batch() does not return. */ moan_smtp_batch(cmd_buffer, "501 MAIL FROM must have an address operand"); @@ -932,8 +957,8 @@ while (done <= 0) /* Apply SMTP rewrite */ raw_sender = ((rewrite_existflags & rewrite_smtp) != 0)? - rewrite_one(smtp_data, rewrite_smtp|rewrite_smtp_sender, NULL, FALSE, - US"", global_rewrite_rules) : smtp_data; + rewrite_one(smtp_command_argument, rewrite_smtp|rewrite_smtp_sender, NULL, FALSE, + US"", global_rewrite_rules) : smtp_command_argument; /* Extract the address; the TRUE flag allows <> as valid */ @@ -976,7 +1001,7 @@ while (done <= 0) /* The function moan_smtp_batch() does not return. */ moan_smtp_batch(cmd_buffer, "503 No sender yet given"); - if (smtp_data[0] == 0) + if (smtp_command_argument[0] == 0) /* The function moan_smtp_batch() does not return. */ moan_smtp_batch(cmd_buffer, "501 RCPT TO must have an address operand"); @@ -991,8 +1016,8 @@ while (done <= 0) recipient address */ recipient = ((rewrite_existflags & rewrite_smtp) != 0)? - rewrite_one(smtp_data, rewrite_smtp, NULL, FALSE, US"", - global_rewrite_rules) : smtp_data; + rewrite_one(smtp_command_argument, rewrite_smtp, NULL, FALSE, US"", + global_rewrite_rules) : smtp_command_argument; /* rfc821_domains = TRUE; << no longer needed */ recipient = parse_extract_address(recipient, &errmess, &start, &end, @@ -1107,6 +1132,17 @@ int size = 256; int i, ptr; uschar *p, *s, *ss; +/* If we are running in the test harness, and the incoming call is from +127.0.0.2 (sic), have a short delay. This makes it possible to test handling of +input sent too soon (before the banner is output). */ + +if (running_in_test_harness && + sender_host_address != NULL && + Ustrcmp(sender_host_address, "127.0.0.2") == 0) + sleep(1); + +/* Default values for certain variables */ + helo_seen = esmtp = helo_accept_junk = FALSE; count_nonmail = TRUE_UNSET; synprot_error_count = unknown_command_count = nonmail_command_count = 0; @@ -1234,16 +1270,16 @@ if (!sender_host_unknown) if (!host_checking && !sender_host_notsocket) { #if OPTSTYLE == 1 - SOCKLEN_T optlen = sizeof(struct ip_options) + MAX_IPOPTLEN; + EXIM_SOCKLEN_T optlen = sizeof(struct ip_options) + MAX_IPOPTLEN; struct ip_options *ipopt = store_get(optlen); #elif OPTSTYLE == 2 struct ip_opts ipoptblock; struct ip_opts *ipopt = &ipoptblock; - SOCKLEN_T optlen = sizeof(ipoptblock); + EXIM_SOCKLEN_T optlen = sizeof(ipoptblock); #else struct ipoption ipoptblock; struct ipoption *ipopt = &ipoptblock; - SOCKLEN_T optlen = sizeof(ipoptblock); + EXIM_SOCKLEN_T optlen = sizeof(ipoptblock); #endif /* Occasional genuine failures of getsockopt() have been seen - for @@ -1510,8 +1546,7 @@ if (acl_smtp_connect != NULL) { int rc; uschar *user_msg, *log_msg; - smtp_data = US"in \"connect\" ACL"; /* For logged failure message */ - rc = acl_check(ACL_WHERE_CONNECT, US"", acl_smtp_connect, &user_msg, + rc = acl_check(ACL_WHERE_CONNECT, NULL, acl_smtp_connect, &user_msg, &log_msg); if (rc != OK) { @@ -1584,11 +1619,18 @@ if (smtp_enforce_sync && sender_host_address != NULL && !sender_host_notsocket) if (select(fileno(smtp_in) + 1, (SELECT_ARG2_TYPE *)&fds, NULL, NULL, &tzero) > 0) { - log_write(0, LOG_MAIN|LOG_REJECT, "SMTP protocol violation: " - "synchronization error (input sent without waiting for greeting): " - "rejected connection from %s", host_and_ident(TRUE)); - smtp_printf("554 SMTP synchronization error\r\n"); - return FALSE; + int rc = read(fileno(smtp_in), smtp_inbuffer, in_buffer_size); + if (rc > 0) + { + if (rc > 150) rc = 150; + smtp_inbuffer[rc] = 0; + log_write(0, LOG_MAIN|LOG_REJECT, "SMTP protocol " + "synchronization error (input sent without waiting for greeting): " + "rejected connection from %s input=\"%s\"", host_and_ident(TRUE), + string_printing(smtp_inbuffer)); + smtp_printf("554 SMTP synchronization error\r\n"); + return FALSE; + } } } @@ -1773,9 +1815,15 @@ int code = acl_wherecodes[where]; BOOL drop = rc == FAIL_DROP; uschar *lognl; uschar *sender_info = US""; -uschar *what = (where == ACL_WHERE_PREDATA)? US"DATA" : - (where == ACL_WHERE_DATA)? US"after DATA" : - string_sprintf("%s %s", acl_wherenames[where], smtp_data); +uschar *what = +#ifdef WITH_CONTENT_SCAN + (where == ACL_WHERE_MIME)? US"during MIME ACL checks" : +#endif + (where == ACL_WHERE_PREDATA)? US"DATA" : + (where == ACL_WHERE_DATA)? US"after DATA" : + (smtp_command_argument == NULL)? + string_sprintf("%s in \"connect\" ACL", acl_wherenames[where]) : + string_sprintf("%s %s", acl_wherenames[where], smtp_command_argument); if (drop) rc = FAIL; @@ -1785,7 +1833,11 @@ fixed, sender_address at this point became the rewritten address. I'm not sure this is what should be logged, so I've changed to logging the unrewritten address to retain backward compatibility. */ +#ifndef WITH_CONTENT_SCAN if (where == ACL_WHERE_RCPT || where == ACL_WHERE_DATA) +#else +if (where == ACL_WHERE_RCPT || where == ACL_WHERE_DATA || where == ACL_WHERE_MIME) +#endif { sender_info = string_sprintf("F=<%s> ", (sender_address_unrewritten != NULL)? sender_address_unrewritten : sender_address); @@ -1882,6 +1934,130 @@ return 2; +/************************************************* +* Verify HELO argument * +*************************************************/ + +/* This function is called if helo_verify_hosts or helo_try_verify_hosts is +matched. It is also called from ACL processing if verify = helo is used and +verification was not previously tried (i.e. helo_try_verify_hosts was not +matched). The result of its processing is to set helo_verified and +helo_verify_failed. These variables should both be FALSE for this function to +be called. + +Note that EHLO/HELO is legitimately allowed to quote an address literal. Allow +for IPv6 ::ffff: literals. + +Argument: none +Returns: TRUE if testing was completed; + FALSE on a temporary failure +*/ + +BOOL +smtp_verify_helo(void) +{ +BOOL yield = TRUE; + +HDEBUG(D_receive) debug_printf("verifying EHLO/HELO argument \"%s\"\n", + sender_helo_name); + +if (sender_helo_name == NULL) + { + HDEBUG(D_receive) debug_printf("no EHLO/HELO command was issued\n"); + } + +else if (sender_helo_name[0] == '[') + { + helo_verified = Ustrncmp(sender_helo_name+1, sender_host_address, + Ustrlen(sender_host_address)) == 0; + + #if HAVE_IPV6 + if (!helo_verified) + { + if (strncmpic(sender_host_address, US"::ffff:", 7) == 0) + helo_verified = Ustrncmp(sender_helo_name + 1, + sender_host_address + 7, Ustrlen(sender_host_address) - 7) == 0; + } + #endif + + HDEBUG(D_receive) + { if (helo_verified) debug_printf("matched host address\n"); } + } + +/* Do a reverse lookup if one hasn't already given a positive or negative +response. If that fails, or the name doesn't match, try checking with a forward +lookup. */ + +else + { + if (sender_host_name == NULL && !host_lookup_failed) + yield = host_name_lookup() != DEFER; + + /* If a host name is known, check it and all its aliases. */ + + if (sender_host_name != NULL) + { + helo_verified = strcmpic(sender_host_name, sender_helo_name) == 0; + + if (helo_verified) + { + HDEBUG(D_receive) debug_printf("matched host name\n"); + } + else + { + uschar **aliases = sender_host_aliases; + while (*aliases != NULL) + { + helo_verified = strcmpic(*aliases++, sender_helo_name) == 0; + if (helo_verified) break; + } + HDEBUG(D_receive) + { + if (helo_verified) + debug_printf("matched alias %s\n", *(--aliases)); + } + } + } + + /* Final attempt: try a forward lookup of the helo name */ + + if (!helo_verified) + { + int rc; + host_item h; + h.name = sender_helo_name; + h.address = NULL; + h.mx = MX_NONE; + h.next = NULL; + HDEBUG(D_receive) debug_printf("getting IP address for %s\n", + sender_helo_name); + rc = host_find_byname(&h, NULL, NULL, TRUE); + if (rc == HOST_FOUND || rc == HOST_FOUND_LOCAL) + { + host_item *hh = &h; + while (hh != NULL) + { + if (Ustrcmp(hh->address, sender_host_address) == 0) + { + helo_verified = TRUE; + HDEBUG(D_receive) + debug_printf("IP address for %s matches calling address\n", + sender_helo_name); + break; + } + hh = hh->next; + } + } + } + } + +if (!helo_verified) helo_verify_failed = FALSE; /* We've tried ... */ +return yield; +} + + + + /************************************************* * Initialize for SMTP incoming message * *************************************************/ @@ -2005,8 +2181,7 @@ while (done <= 0) if (acl_smtp_auth != NULL) { - rc = acl_check(ACL_WHERE_AUTH, smtp_data, acl_smtp_auth, &user_msg, - &log_msg); + rc = acl_check(ACL_WHERE_AUTH, NULL, acl_smtp_auth, &user_msg, &log_msg); if (rc != OK) { done = smtp_handle_acl_fail(ACL_WHERE_AUTH, rc, user_msg, log_msg); @@ -2016,8 +2191,8 @@ while (done <= 0) /* Find the name of the requested authentication mechanism. */ - s = smtp_data; - while ((c = *smtp_data) != 0 && !isspace(c)) + s = smtp_command_argument; + while ((c = *smtp_command_argument) != 0 && !isspace(c)) { if (!isalnum(c) && c != '-' && c != '_') { @@ -2025,16 +2200,16 @@ while (done <= 0) US"invalid character in authentication mechanism name"); goto COMMAND_LOOP; } - smtp_data++; + smtp_command_argument++; } /* If not at the end of the line, we must be at white space. Terminate the name and move the pointer on to any data that may be present. */ - if (*smtp_data != 0) + if (*smtp_command_argument != 0) { - *smtp_data++ = 0; - while (isspace(*smtp_data)) smtp_data++; + *smtp_command_argument++ = 0; + while (isspace(*smtp_command_argument)) smtp_command_argument++; } /* Search for an authentication mechanism which is configured for use @@ -2064,10 +2239,18 @@ while (done <= 0) expand_nmax = 0; expand_nlength[0] = 0; /* $0 contains nothing */ - c = (au->info->servercode)(au, smtp_data); + c = (au->info->servercode)(au, smtp_command_argument); if (au->set_id != NULL) set_id = expand_string(au->set_id); expand_nmax = -1; /* Reset numeric variables */ + /* The value of authenticated_id is stored in the spool file and printed in + log lines. It must not contain binary zeros or newline characters. In + normal use, it never will, but when playing around or testing, this error + can (did) happen. To guard against this, ensure that the id contains only + printing characters. */ + + if (set_id != NULL) set_id = string_printing(set_id); + /* For the non-OK cases, set up additional logging data if set_id is not empty. */ @@ -2172,14 +2355,14 @@ while (done <= 0) /* Reject the HELO if its argument was invalid or non-existent. A successful check causes the argument to be saved in malloc store. */ - if (!check_helo(smtp_data)) + if (!check_helo(smtp_command_argument)) { smtp_printf("501 Syntactically invalid %s argument(s)\r\n", hello); log_write(0, LOG_MAIN|LOG_REJECT, "rejected %s from %s: syntactically " "invalid argument(s): %s", hello, host_and_ident(FALSE), - (*smtp_data == 0)? US"(no argument given)" : - string_printing(smtp_data)); + (*smtp_command_argument == 0)? US"(no argument given)" : + string_printing(smtp_command_argument)); if (++synprot_error_count > smtp_max_synprot_errors) { @@ -2202,7 +2385,7 @@ while (done <= 0) if (!sender_host_unknown) { BOOL old_helo_verified = helo_verified; - uschar *p = smtp_data; + uschar *p = smtp_command_argument; while (*p != 0 && !isspace(*p)) { *p = tolower(*p); p++; } *p = 0; @@ -2224,104 +2407,16 @@ while (done <= 0) (tls_active >= 0)? " TLS" : "", host_and_ident(FALSE)); /* Verify if configured. This doesn't give much security, but it does - make some people happy to be able to do it. Note that HELO is legitimately - allowed to quote an address literal. Allow for IPv6 ::ffff: literals. */ + make some people happy to be able to do it. If helo_required is set, + (host matches helo_verify_hosts) failure forces rejection. If helo_verify + is set (host matches helo_try_verify_hosts), it does not. This is perhaps + now obsolescent, since the verification can now be requested selectively + at ACL time. */ - helo_verified = FALSE; + helo_verified = helo_verify_failed = FALSE; if (helo_required || helo_verify) { - BOOL tempfail = FALSE; - - HDEBUG(D_receive) debug_printf("verifying %s %s\n", hello, - sender_helo_name); - if (sender_helo_name[0] == '[') - { - helo_verified = Ustrncmp(sender_helo_name+1, sender_host_address, - Ustrlen(sender_host_address)) == 0; - - #if HAVE_IPV6 - if (!helo_verified) - { - if (strncmpic(sender_host_address, US"::ffff:", 7) == 0) - helo_verified = Ustrncmp(sender_helo_name + 1, - sender_host_address + 7, Ustrlen(sender_host_address) - 7) == 0; - } - #endif - - HDEBUG(D_receive) - { if (helo_verified) debug_printf("matched host address\n"); } - } - - /* Do a reverse lookup if one hasn't already given a positive or - negative response. If that fails, or the name doesn't match, try - checking with a forward lookup. */ - - else - { - if (sender_host_name == NULL && !host_lookup_failed) - tempfail = host_name_lookup() == DEFER; - - /* If a host name is known, check it and all its aliases. */ - - if (sender_host_name != NULL) - { - helo_verified = strcmpic(sender_host_name, sender_helo_name) == 0; - - if (helo_verified) - { - HDEBUG(D_receive) debug_printf("matched host name\n"); - } - else - { - uschar **aliases = sender_host_aliases; - while (*aliases != NULL) - { - helo_verified = strcmpic(*aliases++, sender_helo_name) == 0; - if (helo_verified) break; - } - HDEBUG(D_receive) - { - if (helo_verified) - debug_printf("matched alias %s\n", *(--aliases)); - } - } - } - - /* Final attempt: try a forward lookup of the helo name */ - - if (!helo_verified) - { - int rc; - host_item h; - h.name = sender_helo_name; - h.address = NULL; - h.mx = MX_NONE; - h.next = NULL; - HDEBUG(D_receive) debug_printf("getting IP address for %s\n", - sender_helo_name); - rc = host_find_byname(&h, NULL, NULL, TRUE); - if (rc == HOST_FOUND || rc == HOST_FOUND_LOCAL) - { - host_item *hh = &h; - while (hh != NULL) - { - if (Ustrcmp(hh->address, sender_host_address) == 0) - { - helo_verified = TRUE; - HDEBUG(D_receive) - debug_printf("IP address for %s matches calling address\n", - sender_helo_name); - break; - } - hh = hh->next; - } - } - } - } - - /* Verification failed. A temporary lookup failure gives a temporary - error. */ - + BOOL tempfail = !smtp_verify_helo(); if (!helo_verified) { if (helo_required) @@ -2340,12 +2435,16 @@ while (done <= 0) } } +#ifdef EXPERIMENTAL_SPF + /* set up SPF context */ + spf_init(sender_helo_name, sender_host_address); +#endif + /* Apply an ACL check if one is defined */ if (acl_smtp_helo != NULL) { - rc = acl_check(ACL_WHERE_HELO, smtp_data, acl_smtp_helo, &user_msg, - &log_msg); + rc = acl_check(ACL_WHERE_HELO, NULL, acl_smtp_helo, &user_msg, &log_msg); if (rc != OK) { done = smtp_handle_acl_fail(ACL_WHERE_HELO, rc, user_msg, log_msg); @@ -2530,7 +2629,7 @@ while (done <= 0) if (tls_active >= 0) (void)tls_write(s, ptr); else #endif - fwrite(s, 1, ptr, smtp_out); + (void)fwrite(s, 1, ptr, smtp_out); DEBUG(D_receive) debug_printf("SMTP>> %s", s); helo_seen = TRUE; break; /* HELO/EHLO */ @@ -2561,7 +2660,7 @@ while (done <= 0) break; } - if (smtp_data[0] == 0) + if (smtp_command_argument[0] == 0) { done = synprot_error(L_smtp_protocol_error, 501, NULL, US"MAIL must have an address operand"); @@ -2720,8 +2819,8 @@ while (done <= 0) TRUE flag allows "<>" as a sender address. */ raw_sender = ((rewrite_existflags & rewrite_smtp) != 0)? - rewrite_one(smtp_data, rewrite_smtp, NULL, FALSE, US"", - global_rewrite_rules) : smtp_data; + rewrite_one(smtp_command_argument, rewrite_smtp, NULL, FALSE, US"", + global_rewrite_rules) : smtp_command_argument; /* rfc821_domains = TRUE; << no longer needed */ raw_sender = @@ -2731,7 +2830,7 @@ while (done <= 0) if (raw_sender == NULL) { - done = synprot_error(L_smtp_syntax_error, 501, smtp_data, errmess); + done = synprot_error(L_smtp_syntax_error, 501, smtp_command_argument, errmess); break; } @@ -2791,7 +2890,7 @@ while (done <= 0) else { smtp_printf("501 %s: sender address must contain a domain\r\n", - smtp_data); + smtp_command_argument); log_write(L_smtp_syntax_error, LOG_MAIN|LOG_REJECT, "unqualified sender rejected: <%s> %s%s", @@ -2859,7 +2958,7 @@ while (done <= 0) /* Check for an operand */ - if (smtp_data[0] == 0) + if (smtp_command_argument[0] == 0) { done = synprot_error(L_smtp_syntax_error, 501, NULL, US"RCPT must have an address operand"); @@ -2871,8 +2970,8 @@ while (done <= 0) as a recipient address */ recipient = ((rewrite_existflags & rewrite_smtp) != 0)? - rewrite_one(smtp_data, rewrite_smtp, NULL, FALSE, US"", - global_rewrite_rules) : smtp_data; + rewrite_one(smtp_command_argument, rewrite_smtp, NULL, FALSE, US"", + global_rewrite_rules) : smtp_command_argument; /* rfc821_domains = TRUE; << no longer needed */ recipient = parse_extract_address(recipient, &errmess, &start, &end, @@ -2881,7 +2980,7 @@ while (done <= 0) if (recipient == NULL) { - done = synprot_error(L_smtp_syntax_error, 501, smtp_data, errmess); + done = synprot_error(L_smtp_syntax_error, 501, smtp_command_argument, errmess); rcpt_fail_count++; break; } @@ -2911,7 +3010,7 @@ while (done <= 0) { rcpt_fail_count++; smtp_printf("501 %s: recipient address must contain a domain\r\n", - smtp_data); + smtp_command_argument); log_write(L_smtp_syntax_error, LOG_MAIN|LOG_REJECT, "unqualified recipient rejected: " "<%s> %s%s", recipient, host_and_ident(TRUE), @@ -2985,7 +3084,7 @@ while (done <= 0) "discarded by %s ACL%s%s", host_and_ident(TRUE), (sender_address_unrewritten != NULL)? sender_address_unrewritten : sender_address, - smtp_data, recipients_discarded? "MAIL" : "RCPT", + smtp_command_argument, recipients_discarded? "MAIL" : "RCPT", (log_msg == NULL)? US"" : US": ", (log_msg == NULL)? US"" : log_msg); } @@ -3034,11 +3133,11 @@ while (done <= 0) smtp_printf("554 Too many recipients\r\n"); break; } - + if (acl_smtp_predata == NULL) rc = OK; else - { + { enable_dollar_recipients = TRUE; - rc = acl_check(ACL_WHERE_PREDATA, NULL, acl_smtp_predata, &user_msg, + rc = acl_check(ACL_WHERE_PREDATA, NULL, acl_smtp_predata, &user_msg, &log_msg); enable_dollar_recipients = FALSE; } @@ -3059,8 +3158,7 @@ while (done <= 0) case VRFY_CMD: - rc = acl_check(ACL_WHERE_VRFY, smtp_data, acl_smtp_vrfy, &user_msg, - &log_msg); + rc = acl_check(ACL_WHERE_VRFY, NULL, acl_smtp_vrfy, &user_msg, &log_msg); if (rc != OK) done = smtp_handle_acl_fail(ACL_WHERE_VRFY, rc, user_msg, log_msg); else @@ -3069,7 +3167,7 @@ while (done <= 0) uschar *s = NULL; /* rfc821_domains = TRUE; << no longer needed */ - address = parse_extract_address(smtp_data, &errmess, &start, &end, + address = parse_extract_address(smtp_command_argument, &errmess, &start, &end, &recipient_domain, FALSE); /* rfc821_domains = FALSE; << no longer needed */ @@ -3096,7 +3194,7 @@ while (done <= 0) string_sprintf("550 <%s> %s", address, addr->message) : string_sprintf("550 <%s> is not deliverable", address); log_write(0, LOG_MAIN, "VRFY failed for %s %s", - smtp_data, host_and_ident(TRUE)); + smtp_command_argument, host_and_ident(TRUE)); break; } } @@ -3107,17 +3205,16 @@ while (done <= 0) case EXPN_CMD: - rc = acl_check(ACL_WHERE_EXPN, smtp_data, acl_smtp_expn, &user_msg, - &log_msg); + rc = acl_check(ACL_WHERE_EXPN, NULL, acl_smtp_expn, &user_msg, &log_msg); if (rc != OK) done = smtp_handle_acl_fail(ACL_WHERE_EXPN, rc, user_msg, log_msg); else { BOOL save_log_testing_mode = log_testing_mode; address_test_mode = log_testing_mode = TRUE; - (void) verify_address(deliver_make_addr(smtp_data, FALSE), smtp_out, - vopt_is_recipient | vopt_qualify | vopt_expn, -1, -1, -1, NULL, NULL, - NULL); + (void) verify_address(deliver_make_addr(smtp_command_argument, FALSE), + smtp_out, vopt_is_recipient | vopt_qualify | vopt_expn, -1, -1, -1, + NULL, NULL, NULL); address_test_mode = FALSE; log_testing_mode = save_log_testing_mode; /* true for -bh */ } @@ -3244,7 +3341,7 @@ while (done <= 0) if (acl_smtp_quit != NULL) { - rc = acl_check(ACL_WHERE_QUIT, US"", acl_smtp_quit,&user_msg,&log_msg); + rc = acl_check(ACL_WHERE_QUIT, NULL, acl_smtp_quit,&user_msg,&log_msg); if (rc == ERROR) log_write(0, LOG_MAIN|LOG_PANIC, "ACL for QUIT returned ERROR: %s", log_msg); @@ -3333,11 +3430,10 @@ while (done <= 0) break; } - log_write(L_etrn, LOG_MAIN, "ETRN %s received from %s", smtp_data, + log_write(L_etrn, LOG_MAIN, "ETRN %s received from %s", smtp_command_argument, host_and_ident(FALSE)); - rc = acl_check(ACL_WHERE_ETRN, smtp_data, acl_smtp_etrn, &user_msg, - &log_msg); + rc = acl_check(ACL_WHERE_ETRN, NULL, acl_smtp_etrn, &user_msg, &log_msg); if (rc != OK) { done = smtp_handle_acl_fail(ACL_WHERE_ETRN, rc, user_msg, log_msg); @@ -3346,7 +3442,7 @@ while (done <= 0) /* Compute the serialization key for this command. */ - etrn_serialize_key = string_sprintf("etrn-%s\n", smtp_data); + etrn_serialize_key = string_sprintf("etrn-%s\n", smtp_command_argument); /* If a command has been specified for running as a result of ETRN, we permit any argument to ETRN. If not, only the # standard form is permitted, @@ -3358,7 +3454,7 @@ while (done <= 0) uschar *error; BOOL rc; etrn_command = smtp_etrn_command; - deliver_domain = smtp_data; + deliver_domain = smtp_command_argument; rc = transport_set_up_command(&argv, smtp_etrn_command, TRUE, 0, NULL, US"ETRN processing", &error); deliver_domain = NULL; @@ -3375,7 +3471,7 @@ while (done <= 0) else { - if (*smtp_data++ != '#') + if (*smtp_command_argument++ != '#') { done = synprot_error(L_smtp_syntax_error, 501, NULL, US"argument must begin with #"); @@ -3383,7 +3479,7 @@ while (done <= 0) } etrn_command = US"exim -R"; argv = child_exec_exim(CEE_RETURN_ARGV, TRUE, NULL, TRUE, 2, US"-R", - smtp_data); + smtp_command_argument); } /* If we are host-testing, don't actually do anything. */ @@ -3405,7 +3501,7 @@ while (done <= 0) if (smtp_etrn_serialize && !enq_start(etrn_serialize_key)) { - smtp_printf("458 Already processing %s\r\n", smtp_data); + smtp_printf("458 Already processing %s\r\n", smtp_command_argument); break; } @@ -3420,9 +3516,9 @@ while (done <= 0) if ((pid = fork()) == 0) { - smtp_input = FALSE; /* This process is not associated with the */ - fclose(smtp_in); /* SMTP call any more. */ - fclose(smtp_out); + smtp_input = FALSE; /* This process is not associated with the */ + (void)fclose(smtp_in); /* SMTP call any more. */ + (void)fclose(smtp_out); signal(SIGCHLD, SIG_DFL); /* Want to catch child */ @@ -3499,8 +3595,7 @@ while (done <= 0) if (c > 150) c = 150; smtp_inptr[c] = 0; incomplete_transaction_log(US"sync failure"); - log_write(0, LOG_MAIN|LOG_REJECT, "SMTP protocol violation: " - "synchronization error " + log_write(0, LOG_MAIN|LOG_REJECT, "SMTP protocol synchronization error " "(next input sent too soon: pipelining was%s advertised): " "rejected \"%s\" %s next input=\"%s\"", pipelining_advertised? "" : " not", @@ -3515,7 +3610,7 @@ while (done <= 0) incomplete_transaction_log(US"too many non-mail commands"); log_write(0, LOG_MAIN|LOG_REJECT, "SMTP call from %s dropped: too many " "nonmail commands (last was \"%.*s\")", host_and_ident(FALSE), - smtp_data - cmd_buffer, cmd_buffer); + smtp_command_argument - cmd_buffer, cmd_buffer); smtp_printf("554 Too many nonmail commands\r\n"); done = 1; /* Pretend eof - drops connection */ break;