X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=src%2Fsrc%2Fsmtp_in.c;h=f7549bb7c8580c3bb01825838945e3a9d4d75dbc;hb=cf39cf5741111de26125a55c311223b5b6b6a36b;hp=ff08cbd5653cd980f4e30c540d0504c3e7baa1d5;hpb=69358f0206debf14a18c7e798e23133d304232b6;p=exim.git diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c index ff08cbd56..f7549bb7c 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.2 2004/10/19 11:04:26 ph10 Exp $ */ +/* $Cambridge: exim/src/src/smtp_in.c,v 1.21 2005/08/02 08:25:45 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 */ @@ -167,17 +170,18 @@ static smtp_cmd_list *cmd_list_end = #define CMD_LIST_STARTTLS 4 static uschar *protocols[] = { - US"local-smtp", - US"local-esmtp", - US"local-esmtpa", - US"local-esmtps", - US"local-esmtpsa" + US"local-smtp", /* HELO */ + US"local-smtps", /* The rare case EHLO->STARTTLS->HELO */ + US"local-esmtp", /* EHLO */ + US"local-esmtps", /* EHLO->STARTTLS->EHLO */ + US"local-esmtpa", /* EHLO->AUTH */ + US"local-esmtpsa" /* EHLO->STARTTLS->EHLO->AUTH */ }; #define pnormal 0 -#define pextend 1 -#define pauthed 1 /* added to pextend */ -#define pcrpted 2 /* added to pextend */ +#define pextend 2 +#define pcrpted 1 /* added to pextend or pnormal */ +#define pauthed 2 /* added to pextend */ #define pnlocal 6 /* offset to remove "local" */ /* When reading SMTP from a remote host, we have to use our own versions of the @@ -800,10 +804,15 @@ 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 */ active_local_from_check = local_from_check; /* Can be set by ACL */ active_local_sender_retain = local_sender_retain; /* Can be set by ACL */ @@ -814,8 +823,25 @@ 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 @@ -1106,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; @@ -1233,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 @@ -1583,11 +1620,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,6 +1817,9 @@ BOOL drop = rc == FAIL_DROP; uschar *lognl; uschar *sender_info = US""; uschar *what = (where == ACL_WHERE_PREDATA)? US"DATA" : +#ifdef WITH_CONTENT_SCAN + (where == ACL_WHERE_MIME)? US"during MIME ACL checks" : +#endif (where == ACL_WHERE_DATA)? US"after DATA" : string_sprintf("%s %s", acl_wherenames[where], smtp_data); @@ -1784,7 +1831,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); @@ -2067,6 +2118,14 @@ while (done <= 0) 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. */ @@ -2339,6 +2398,11 @@ 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) @@ -2362,7 +2426,7 @@ while (done <= 0) ((sender_host_authenticated != NULL)? pauthed : 0) + ((tls_active >= 0)? pcrpted : 0)] : - protocols[pnormal]) + protocols[pnormal + ((tls_active >= 0)? pcrpted : 0)]) + ((sender_host_address != NULL)? pnlocal : 0); @@ -2529,7 +2593,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 */ @@ -3034,8 +3098,13 @@ while (done <= 0) break; } - rc = (acl_smtp_predata == NULL)? OK : - acl_check(ACL_WHERE_PREDATA, NULL, acl_smtp_predata, &user_msg, &log_msg); + if (acl_smtp_predata == NULL) rc = OK; else + { + enable_dollar_recipients = TRUE; + rc = acl_check(ACL_WHERE_PREDATA, NULL, acl_smtp_predata, &user_msg, + &log_msg); + enable_dollar_recipients = FALSE; + } if (rc == OK) { @@ -3073,7 +3142,7 @@ while (done <= 0) { address_item *addr = deliver_make_addr(address, FALSE); switch(verify_address(addr, NULL, vopt_is_recipient | vopt_qualify, -1, - -1, NULL, NULL, NULL)) + -1, -1, NULL, NULL, NULL)) { case OK: s = string_sprintf("250 <%s> is deliverable", address); @@ -3110,7 +3179,8 @@ while (done <= 0) 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, NULL, NULL, NULL); + 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 */ } @@ -3176,7 +3246,7 @@ while (done <= 0) protocols[pextend + pcrpted + ((sender_host_authenticated != NULL)? pauthed : 0)] : - protocols[pnormal]) + protocols[pnormal + pcrpted]) + ((sender_host_address != NULL)? pnlocal : 0); @@ -3413,9 +3483,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 */ @@ -3492,8 +3562,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",