X-Git-Url: https://git.exim.org/users/jgh/exim.git/blobdiff_plain/7a2fa0bc49edcd925d51605836f0132a130e0167..80fea873648ca2ab2e592999a336c59cf054ab55:/src/src/smtp_in.c diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c index 86b0d21cf..86d566dc9 100644 --- a/src/src/smtp_in.c +++ b/src/src/smtp_in.c @@ -2,7 +2,7 @@ * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2015 */ +/* Copyright (c) University of Cambridge 1995 - 2016 */ /* See the file NOTICE for conditions of use and distribution. */ /* Functions for handling an incoming SMTP call. */ @@ -135,7 +135,7 @@ static BOOL rcpt_smtp_response_same; static BOOL rcpt_in_progress; static int nonmail_command_count; static BOOL smtp_exit_function_called = 0; -#ifdef EXPERIMENTAL_INTERNATIONAL +#ifdef SUPPORT_I18N static BOOL smtputf8_advertised; #endif static int synprot_error_count; @@ -239,7 +239,7 @@ enum { ENV_MAIL_OPT_PRDR, #endif ENV_MAIL_OPT_RET, ENV_MAIL_OPT_ENVID, -#ifdef EXPERIMENTAL_INTERNATIONAL +#ifdef SUPPORT_I18N ENV_MAIL_OPT_UTF8, #endif }; @@ -258,7 +258,7 @@ static env_mail_type_t env_mail_type_list[] = { #endif { US"RET", ENV_MAIL_OPT_RET, TRUE }, { US"ENVID", ENV_MAIL_OPT_ENVID, TRUE }, -#ifdef EXPERIMENTAL_INTERNATIONAL +#ifdef SUPPORT_I18N { US"SMTPUTF8",ENV_MAIL_OPT_UTF8, FALSE }, /* rfc6531 */ #endif /* keep this the last entry */ @@ -1544,7 +1544,7 @@ spf_received = NULL; spf_result = NULL; spf_smtp_comment = NULL; #endif -#ifdef EXPERIMENTAL_INTERNATIONAL +#ifdef SUPPORT_I18N message_smtputf8 = FALSE; #endif body_linecount = body_zerocount = 0; @@ -1866,8 +1866,6 @@ pipelining_enable = TRUE; sync_cmd_limit = NON_SYNC_CMD_NON_PIPELINING; smtp_exit_function_called = FALSE; /* For avoiding loop in not-quit exit */ -memset(sender_host_cache, 0, sizeof(sender_host_cache)); - /* If receiving by -bs from a trusted user, or testing with -bh, we allow authentication settings from -oMaa to remain in force. */ @@ -1882,7 +1880,7 @@ tls_in.ocsp = OCSP_NOT_REQ; tls_advertised = FALSE; #endif dsn_advertised = FALSE; -#ifdef EXPERIMENTAL_INTERNATIONAL +#ifdef SUPPORT_I18N smtputf8_advertised = FALSE; #endif @@ -2355,10 +2353,9 @@ code = US"220"; /* Default status code */ esc = US""; /* Default extended status code */ esclen = 0; /* Length of esc */ -if (user_msg == NULL) +if (!user_msg) { - s = expand_string(smtp_banner); - if (s == NULL) + if (!(s = expand_string(smtp_banner))) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Expansion of \"%s\" (smtp_banner) " "failed: %s", smtp_banner, expand_string_message); } @@ -2366,7 +2363,7 @@ else { int codelen = 3; s = user_msg; - smtp_message_code(&code, &codelen, &s, NULL); + smtp_message_code(&code, &codelen, &s, NULL, TRUE); if (codelen > 4) { esc = code + 4; @@ -2628,23 +2625,24 @@ Arguments: codelen length of smtp code; if > 4 there's an ESC msg message text log_msg optional log message, to be adjusted with the new SMTP code + check_valid if true, verify the response code Returns: nothing */ void -smtp_message_code(uschar **code, int *codelen, uschar **msg, uschar **log_msg) +smtp_message_code(uschar **code, int *codelen, uschar **msg, uschar **log_msg, + BOOL check_valid) { int n; int ovector[3]; -if (msg == NULL || *msg == NULL) return; +if (!msg || !*msg) return; -n = pcre_exec(regex_smtp_code, NULL, CS *msg, Ustrlen(*msg), 0, - PCRE_EOPT, ovector, sizeof(ovector)/sizeof(int)); -if (n < 0) return; +if ((n = pcre_exec(regex_smtp_code, NULL, CS *msg, Ustrlen(*msg), 0, + PCRE_EOPT, ovector, sizeof(ovector)/sizeof(int))) < 0) return; -if ((*msg)[0] != (*code)[0]) +if (check_valid && (*msg)[0] != (*code)[0]) { log_write(0, LOG_MAIN|LOG_PANIC, "configured error code starts with " "incorrect digit (expected %c) in \"%s\"", (*code)[0], *msg); @@ -2679,18 +2677,19 @@ defaults disabled in Exim. However, discussion in connection with RFC 821bis (aka RFC 2821) has concluded that the response should be 252 in the disabled state, because there are broken clients that try VRFY before RCPT. A 5xx response should be given only when the address is positively known to be -undeliverable. Sigh. Also, for ETRN, 458 is given on refusal, and for AUTH, -503. +undeliverable. Sigh. We return 252 if there is no VRFY ACL or it provides +no explicit code, but if there is one we let it know best. +Also, for ETRN, 458 is given on refusal, and for AUTH, 503. From Exim 4.63, it is possible to override the response code details by providing a suitable response code string at the start of the message provided in user_msg. The code's first digit is checked for validity. Arguments: - where where the ACL was called from - rc the failure code - user_msg a message that can be included in an SMTP response - log_msg a message for logging + where where the ACL was called from + rc the failure code + user_msg a message that can be included in an SMTP response + log_msg a message for logging Returns: 0 in most cases 2 if the failure code was FAIL_DROP, in which case the @@ -2723,8 +2722,9 @@ if (drop) rc = FAIL; /* Set the default SMTP code, and allow a user message to change it. */ -smtp_code = (rc != FAIL)? US"451" : acl_wherecodes[where]; -smtp_message_code(&smtp_code, &codelen, &user_msg, &log_msg); +smtp_code = rc == FAIL ? acl_wherecodes[where] : US"451"; +smtp_message_code(&smtp_code, &codelen, &user_msg, &log_msg, + where != ACL_WHERE_VRFY); /* We used to have sender_address here; however, there was a bug that was not updating sender_address after a rewrite during a verify. When this bug was @@ -3098,7 +3098,7 @@ static void smtp_user_msg(uschar *code, uschar *user_msg) { int len = 3; -smtp_message_code(&code, &len, &user_msg, NULL); +smtp_message_code(&code, &len, &user_msg, NULL, TRUE); smtp_respond(code, len, TRUE, user_msg); } @@ -3307,14 +3307,13 @@ while (done <= 0) ) { cmd_list[CMD_LIST_TLS_AUTH].is_mail_cmd = FALSE; - if (acl_smtp_auth) + if ( acl_smtp_auth + && (rc = acl_check(ACL_WHERE_AUTH, NULL, acl_smtp_auth, + &user_msg, &log_msg)) != OK + ) { - 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); - continue; - } + done = smtp_handle_acl_fail(ACL_WHERE_AUTH, rc, user_msg, log_msg); + continue; } for (au = auths; au; au = au->next) @@ -3323,9 +3322,9 @@ while (done <= 0) smtp_cmd_data = NULL; if (smtp_in_auth(au, &s, &ss) == OK) - DEBUG(D_auth) debug_printf("tls auth succeeded\n"); + { DEBUG(D_auth) debug_printf("tls auth succeeded\n"); } else - DEBUG(D_auth) debug_printf("tls auth not succeeded\n"); + { DEBUG(D_auth) debug_printf("tls auth not succeeded\n"); } break; } } @@ -3373,14 +3372,13 @@ while (done <= 0) /* Check the ACL */ - if (acl_smtp_auth) + if ( acl_smtp_auth + && (rc = acl_check(ACL_WHERE_AUTH, NULL, acl_smtp_auth, + &user_msg, &log_msg)) != OK + ) { - 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); - break; - } + done = smtp_handle_acl_fail(ACL_WHERE_AUTH, rc, user_msg, log_msg); + break; } /* Find the name of the requested authentication mechanism. */ @@ -3552,10 +3550,9 @@ while (done <= 0) /* Apply an ACL check if one is defined; afterwards, recheck synchronization in case the client started sending in a delay. */ - if (acl_smtp_helo != NULL) - { - rc = acl_check(ACL_WHERE_HELO, NULL, acl_smtp_helo, &user_msg, &log_msg); - if (rc != OK) + if (acl_smtp_helo) + if ((rc = acl_check(ACL_WHERE_HELO, NULL, acl_smtp_helo, + &user_msg, &log_msg)) != OK) { done = smtp_handle_acl_fail(ACL_WHERE_HELO, rc, user_msg, log_msg); sender_helo_name = NULL; @@ -3563,7 +3560,6 @@ while (done <= 0) break; } else if (!check_sync()) goto SYNC_FAILURE; - } /* Generate an OK reply. The default string includes the ident if present, and also the IP address if present. Reflecting back the ident is intended @@ -3577,7 +3573,7 @@ while (done <= 0) tls_advertised = FALSE; #endif dsn_advertised = FALSE; -#ifdef EXPERIMENTAL_INTERNATIONAL +#ifdef SUPPORT_I18N smtputf8_advertised = FALSE; #endif @@ -3611,7 +3607,7 @@ while (done <= 0) { char *ss; int codelen = 4; - smtp_message_code(&smtp_code, &codelen, &user_msg, NULL); + smtp_message_code(&smtp_code, &codelen, &user_msg, NULL, TRUE); s = string_sprintf("%.*s%s", codelen, smtp_code, user_msg); if ((ss = strpbrk(CS s, "\r\n")) != NULL) { @@ -3771,7 +3767,7 @@ while (done <= 0) } #endif -#ifdef EXPERIMENTAL_INTERNATIONAL +#ifdef SUPPORT_I18N if ( accept_8bitmime && verify_check_host(&smtputf8_advertise_hosts) != FAIL) { @@ -4054,7 +4050,7 @@ while (done <= 0) break; #endif -#ifdef EXPERIMENTAL_INTERNATIONAL +#ifdef SUPPORT_I18N case ENV_MAIL_OPT_UTF8: if (smtputf8_advertised) { @@ -4583,51 +4579,49 @@ while (done <= 0) case VRFY_CMD: - HAD(SCH_VRFY); - 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 { - uschar *address; - uschar *s = NULL; + uschar * address; + + HAD(SCH_VRFY); - /* rfc821_domains = TRUE; << no longer needed */ - address = parse_extract_address(smtp_cmd_data, &errmess, &start, &end, - &recipient_domain, FALSE); - /* rfc821_domains = FALSE; << no longer needed */ + if(!(address = parse_extract_address(smtp_cmd_data, &errmess, &start, &end, + &recipient_domain, FALSE))) + smtp_printf("501 %s\r\n", errmess); - if (address == NULL) - s = string_sprintf("501 %s", errmess); + else if ((rc = acl_check(ACL_WHERE_VRFY, address, acl_smtp_vrfy, + &user_msg, &log_msg)) != OK) + done = smtp_handle_acl_fail(ACL_WHERE_VRFY, rc, user_msg, log_msg); else - { - address_item *addr = deliver_make_addr(address, FALSE); - switch(verify_address(addr, NULL, vopt_is_recipient | vopt_qualify, -1, - -1, -1, NULL, NULL, NULL)) - { - case OK: - s = string_sprintf("250 <%s> is deliverable", address); - break; + { + uschar *s = NULL; - case DEFER: - s = (addr->user_message != NULL)? - string_sprintf("451 <%s> %s", address, addr->user_message) : - string_sprintf("451 Cannot resolve <%s> at this time", address); - break; + address_item *addr = deliver_make_addr(address, FALSE); + switch(verify_address(addr, NULL, vopt_is_recipient | vopt_qualify, -1, + -1, -1, NULL, NULL, NULL)) + { + case OK: + s = string_sprintf("250 <%s> is deliverable", address); + break; - case FAIL: - s = (addr->user_message != NULL)? - string_sprintf("550 <%s> %s", address, addr->user_message) : - string_sprintf("550 <%s> is not deliverable", address); - log_write(0, LOG_MAIN, "VRFY failed for %s %s", - smtp_cmd_argument, host_and_ident(TRUE)); - break; - } - } + case DEFER: + s = (addr->user_message != NULL)? + string_sprintf("451 <%s> %s", address, addr->user_message) : + string_sprintf("451 Cannot resolve <%s> at this time", address); + break; - smtp_printf("%s\r\n", s); + case FAIL: + s = (addr->user_message != NULL)? + string_sprintf("550 <%s> %s", address, addr->user_message) : + string_sprintf("550 <%s> is not deliverable", address); + log_write(0, LOG_MAIN, "VRFY failed for %s %s", + smtp_cmd_argument, host_and_ident(TRUE)); + break; + } + + smtp_printf("%s\r\n", s); + } + break; } - break; case EXPN_CMD: @@ -4661,15 +4655,13 @@ while (done <= 0) /* Apply an ACL check if one is defined */ - if (acl_smtp_starttls != NULL) + if ( acl_smtp_starttls + && (rc = acl_check(ACL_WHERE_STARTTLS, NULL, acl_smtp_starttls, + &user_msg, &log_msg)) != OK + ) { - rc = acl_check(ACL_WHERE_STARTTLS, NULL, acl_smtp_starttls, &user_msg, - &log_msg); - if (rc != OK) - { - done = smtp_handle_acl_fail(ACL_WHERE_STARTTLS, rc, user_msg, log_msg); - break; - } + done = smtp_handle_acl_fail(ACL_WHERE_STARTTLS, rc, user_msg, log_msg); + break; } /* RFC 2487 is not clear on when this command may be sent, though it @@ -4912,8 +4904,8 @@ while (done <= 0) log_write(L_etrn, LOG_MAIN, "ETRN %s received from %s", smtp_cmd_argument, host_and_ident(FALSE)); - rc = acl_check(ACL_WHERE_ETRN, NULL, acl_smtp_etrn, &user_msg, &log_msg); - if (rc != OK) + if ((rc = acl_check(ACL_WHERE_ETRN, NULL, acl_smtp_etrn, + &user_msg, &log_msg)) != OK) { done = smtp_handle_acl_fail(ACL_WHERE_ETRN, rc, user_msg, log_msg); break;