-/* $Cambridge: exim/src/src/smtp_in.c,v 1.26 2005/09/13 11:13:27 ph10 Exp $ */
+/* $Cambridge: exim/src/src/smtp_in.c,v 1.36 2006/03/08 10:49:18 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2005 */
+/* Copyright (c) University of Cambridge 1995 - 2006 */
/* See the file NOTICE for conditions of use and distribution. */
/* Functions for handling an incoming SMTP call. */
DEBUG(D_receive)
{
+ uschar *cr, *end;
va_start(ap, format);
(void) string_vformat(big_buffer, big_buffer_size, format, ap);
+ va_end(ap);
+ end = big_buffer + Ustrlen(big_buffer);
+ while ((cr = Ustrchr(big_buffer, '\r')) != NULL) /* lose CRs */
+ memmove(cr, cr + 1, (end--) - cr);
debug_printf("SMTP>> %s", big_buffer);
}
/* This function is called when logging information about an SMTP connection.
It sets up appropriate source information, depending on the type of connection.
+If sender_fullhost is NULL, we are at a very early stage of the connection;
+just use the IP address.
Argument: none
Returns: a string describing the connection
uschar *
smtp_get_connection_info(void)
{
+uschar *hostname = (sender_fullhost == NULL)?
+ sender_host_address : sender_fullhost;
+
if (host_checking)
- return string_sprintf("SMTP connection from %s", sender_fullhost);
+ return string_sprintf("SMTP connection from %s", hostname);
if (sender_host_unknown || sender_host_notsocket)
return string_sprintf("SMTP connection from %s", sender_ident);
if (is_inetd)
- return string_sprintf("SMTP connection from %s (via inetd)", sender_fullhost);
+ return string_sprintf("SMTP connection from %s (via inetd)", hostname);
if ((log_extra_selector & LX_incoming_interface) != 0 &&
interface_address != NULL)
- return string_sprintf("SMTP connection from %s I=[%s]:%d", sender_fullhost,
+ return string_sprintf("SMTP connection from %s I=[%s]:%d", hostname,
interface_address, interface_port);
-return string_sprintf("SMTP connection from %s", sender_fullhost);
+return string_sprintf("SMTP connection from %s", hostname);
}
raw_recipients_count = recipients_count = recipients_list_max = 0;
message_linecount = 0;
message_size = -1;
-acl_warn_headers = NULL;
+acl_added_headers = NULL;
queue_only_policy = FALSE;
deliver_freeze = FALSE; /* Can be set by ACL */
+freeze_tell = freeze_tell_config; /* 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 */
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 variables follow the connection variables. */
+
+for (i = 0; i < ACL_MVARS; i++) acl_var[ACL_CVARS + i] = NULL;
/* The message body variables use malloc store. They may be set if this is
not the first message in an SMTP session and the previous message caused them
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;
/* Reset ACL connection variables */
-for (i = 0; i < ACL_C_MAX; i++) acl_var[i] = NULL;
+for (i = 0; i < ACL_CVARS; i++) acl_var[i] = NULL;
/* Allow for trailing 0 in the command buffer. */
/* If there's been a sender verification failure with a specific message, and
we have not sent a response about it yet, do so now, as a preliminary line for
-failures, but not defers. However, log it in both cases. */
+failures, but not defers. However, always log it for defer, and log it for fail
+unless the sender_verify_fail log selector has been turned off. */
if (sender_verified_failed != NULL &&
!testflag(sender_verified_failed, af_sverify_told))
{
setflag(sender_verified_failed, af_sverify_told);
- log_write(0, LOG_MAIN|LOG_REJECT, "%s sender verify %s for <%s>%s",
- host_and_ident(TRUE),
- ((sender_verified_failed->special_action & 255) == DEFER)? "defer" : "fail",
- sender_verified_failed->address,
- (sender_verified_failed->message == NULL)? US"" :
- string_sprintf(": %s", sender_verified_failed->message));
+ if (rc != FAIL || (log_extra_selector & LX_sender_verify_fail) != 0)
+ log_write(0, LOG_MAIN|LOG_REJECT, "%s sender verify %s for <%s>%s",
+ host_and_ident(TRUE),
+ ((sender_verified_failed->special_action & 255) == DEFER)? "defer":"fail",
+ sender_verified_failed->address,
+ (sender_verified_failed->message == NULL)? US"" :
+ string_sprintf(": %s", sender_verified_failed->message));
if (rc == FAIL && sender_verified_failed->user_message != NULL)
smtp_respond(code, FALSE, string_sprintf(
pid_t pid;
int start, end, sender_domain, recipient_domain;
int ptr, size, rc;
- int c;
+ int c, i;
auth_instance *au;
switch(smtp_read_command(TRUE))
{
/* The AUTH command is not permitted to occur inside a transaction, and may
- occur successfully only once per connection, and then only when we've
- advertised it. Actually, that isn't quite true. When TLS is started, all
- previous information about a connection must be discarded, so a new AUTH is
- permitted at that time.
+ occur successfully only once per connection. Actually, that isn't quite
+ true. When TLS is started, all previous information about a connection must
+ be discarded, so a new AUTH is permitted at that time.
+
+ AUTH may only be used when it has been advertised. However, it seems that
+ there are clients that send AUTH when it hasn't been advertised, some of
+ them even doing this after HELO. And there are MTAs that accept this. Sigh.
+ So there's a get-out that allows this to happen.
AUTH is initially labelled as a "nonmail command" so that one occurrence
doesn't get counted. We change the label here so that multiple failing
authentication_failed = TRUE;
cmd_list[CMD_LIST_AUTH].is_mail_cmd = FALSE;
- if (!auth_advertised)
+ if (!auth_advertised && !allow_auth_unadvertised)
{
done = synprot_error(L_smtp_protocol_error, 503, NULL,
US"AUTH command used when not advertised");
}
/* Search for an authentication mechanism which is configured for use
- as a server and which has been advertised. */
+ as a server and which has been advertised (unless, sigh, allow_auth_
+ unadvertised is set). */
for (au = auths; au != NULL; au = au->next)
{
if (strcmpic(s, au->public_name) == 0 && au->server &&
- au->advertised) break;
+ (au->advertised || allow_auth_unadvertised)) break;
}
if (au == NULL)
break;
}
- /* Run the checking code, passing the remainder of the command
- line as data. Initialize $0 empty. The authenticator may set up
- other numeric variables. Afterwards, have a go at expanding the set_id
- string, even if authentication failed - for bad passwords it can be useful
- to log the userid. On success, require set_id to expand and exist, and
- put it in authenticated_id. Save this in permanent store, as the working
- store gets reset at HELO, RSET, etc. */
+ /* Run the checking code, passing the remainder of the command line as
+ data. Initials the $auth<n> variables as empty. Initialize $0 empty and set
+ it as the only set numerical variable. The authenticator may set $auth<n>
+ and also set other numeric variables. The $auth<n> variables are preferred
+ nowadays; the numerical variables remain for backwards compatibility.
+
+ Afterwards, have a go at expanding the set_id string, even if
+ authentication failed - for bad passwords it can be useful to log the
+ userid. On success, require set_id to expand and exist, and put it in
+ authenticated_id. Save this in permanent store, as the working store gets
+ reset at HELO, RSET, etc. */
+ for (i = 0; i < AUTH_VARS; i++) auth_vars[i] = NULL;
expand_nmax = 0;
expand_nlength[0] = 0; /* $0 contains nothing */
c = (au->info->servercode)(au, smtp_cmd_argument);
if (au->set_id != NULL) set_id = expand_string(au->set_id);
expand_nmax = -1; /* Reset numeric variables */
+ for (i = 0; i < AUTH_VARS; i++) auth_vars[i] = NULL; /* Reset $auth<n> */
/* 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
#endif
(void)fwrite(s, 1, ptr, smtp_out);
- DEBUG(D_receive) debug_printf("SMTP>> %s", s);
+ DEBUG(D_receive)
+ {
+ uschar *cr;
+ while ((cr = Ustrchr(s, '\r')) != NULL) /* lose CRs */
+ memmove(cr, cr + 1, (ptr--) - (cr - s));
+ debug_printf("SMTP>> %s", s);
+ }
helo_seen = TRUE;
break; /* HELO/EHLO */