-/* $Cambridge: exim/src/src/receive.c,v 1.37 2007/04/16 10:31:58 ph10 Exp $ */
+/* $Cambridge: exim/src/src/receive.c,v 1.44 2008/01/22 19:23:46 fanf2 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
#include "exim.h"
+#if (defined EXPERIMENTAL_DOMAINKEYS) && (defined EXPERIMENTAL_DKIM)
+
+#warning Chaining Domainkeys via DKIM receive functions
+#define RECEIVE_GETC dkim_receive_getc
+#define RECEIVE_UNGETC dkim_receive_ungetc
+
+#else
+
+#if (defined EXPERIMENTAL_DOMAINKEYS) || (defined EXPERIMENTAL_DKIM)
+
#ifdef EXPERIMENTAL_DOMAINKEYS
+#warning Using Domainkeys receive functions
#define RECEIVE_GETC dk_receive_getc
#define RECEIVE_UNGETC dk_receive_ungetc
+#endif
+#ifdef EXPERIMENTAL_DKIM
+#warning Using DKIM receive functions
+#define RECEIVE_GETC dkim_receive_getc
+#define RECEIVE_UNGETC dkim_receive_ungetc
+#endif
+
#else
+
+/* Normal operation */
#define RECEIVE_GETC receive_getc
#define RECEIVE_UNGETC receive_ungetc
+
+#endif
+
+#endif
+
+
+#ifdef EXPERIMENTAL_DCC
+extern int dcc_ok;
#endif
/*************************************************
}
}
-/* We now have the patch; do the business */
+/* We now have the path; do the business */
memset(&statbuf, 0, sizeof(statbuf));
function if there is an ultimate disaster. That is why it is globally
accessible.
-Arguments: SMTP response to give if in an SMTP session
+Arguments:
+ reason text reason to pass to the not-quit ACL
+ msg default SMTP response to give if in an SMTP session
Returns: it doesn't
*/
void
-receive_bomb_out(uschar *msg)
+receive_bomb_out(uschar *reason, uschar *msg)
{
/* If spool_name is set, it contains the name of the data file that is being
written. Unlink it before closing so that it cannot be picked up by a delivery
if (data_file != NULL) (void)fclose(data_file);
else if (data_fd >= 0) (void)close(data_fd);
-/* Attempt to close down an SMTP connection tidily. */
+/* Attempt to close down an SMTP connection tidily. For non-batched SMTP, call
+smtp_notquit_exit(), which runs the NOTQUIT ACL, if present, and handles the
+SMTP response. */
if (smtp_input)
{
- if (!smtp_batched_input)
- {
- smtp_printf("421 %s %s - closing connection.\r\n", smtp_active_hostname,
- msg);
- mac_smtp_fflush();
- }
-
- /* Control does not return from moan_smtp_batch(). */
-
- else moan_smtp_batch(NULL, "421 %s - message abandoned", msg);
+ if (smtp_batched_input)
+ moan_smtp_batch(NULL, "421 %s - message abandoned", msg); /* No return */
+ smtp_notquit_exit(reason, US"421", US"%s %s - closing connection.",
+ smtp_active_hostname, msg);
}
/* Exit from the program (non-BSMTP cases) */
LOG_MAIN, "timed out while reading local message");
}
-receive_bomb_out(msg); /* Does not return */
+receive_bomb_out(US"data-timeout", msg); /* Does not return */
}
sig = sig; /* Keep picky compilers happy */
log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() function timed out - "
"message temporarily rejected (size %d)", message_size);
-receive_bomb_out(US"local verification problem"); /* Does not return */
+/* Does not return */
+receive_bomb_out(US"local-scan-timeout", US"local verification problem");
}
{
log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() function crashed with "
"signal %d - message temporarily rejected (size %d)", sig, message_size);
-receive_bomb_out(US"local verification problem"); /* Does not return */
+/* Does not return */
+receive_bomb_out(US"local-scan-error", US"local verification problem");
}
}
}
-receive_bomb_out(msg); /* Does not return */
+receive_bomb_out(US"signal-exit", msg); /* Does not return */
}
{
int ch_state;
register int ch;
+register int linelength = 0;
/* Handle the case when only EOF terminates the message */
if (ch == 0) body_zerocount++;
if (last_ch == '\r' && ch != '\n')
{
+ if (linelength > max_received_linelength)
+ max_received_linelength = linelength;
+ linelength = 0;
if (fputc('\n', fout) == EOF) return END_WERROR;
message_size++;
body_linecount++;
if (ch == '\r') continue;
if (fputc(ch, fout) == EOF) return END_WERROR;
- if (ch == '\n') body_linecount++;
+ if (ch == '\n')
+ {
+ if (linelength > max_received_linelength)
+ max_received_linelength = linelength;
+ linelength = 0;
+ body_linecount++;
+ }
+ else linelength++;
if (++message_size > thismessage_size_limit) return END_SIZE;
}
if (last_ch != '\n')
{
+ if (linelength > max_received_linelength)
+ max_received_linelength = linelength;
if (fputc('\n', fout) == EOF) return END_WERROR;
message_size++;
body_linecount++;
{
case 0: /* Normal state (previous char written) */
if (ch == '\n')
- { body_linecount++; ch_state = 1; }
+ {
+ body_linecount++;
+ if (linelength > max_received_linelength)
+ max_received_linelength = linelength;
+ linelength = -1;
+ ch_state = 1;
+ }
else if (ch == '\r')
{ ch_state = 2; continue; }
break;
case 1: /* After written "\n" */
if (ch == '.') { ch_state = 3; continue; }
- if (ch != '\n') ch_state = 0;
+ if (ch != '\n') ch_state = 0; else linelength = -1;
break;
case 2:
body_linecount++; /* After unwritten "\r" */
+ if (linelength > max_received_linelength)
+ max_received_linelength = linelength;
if (ch == '\n')
- { ch_state = 1; }
+ {
+ ch_state = 1;
+ linelength = -1;
+ }
else
{
if (message_size++, fputc('\n', fout) == EOF) return END_WERROR;
if (ch == '\r') continue;
ch_state = 0;
+ linelength = 0;
}
break;
if (ch == '\n') return END_DOT;
if (ch == '\r') { ch_state = 4; continue; }
message_size++;
+ linelength++;
if (fputc('.', fout) == EOF) return END_WERROR;
ch_state = 0;
break;
break;
}
+ linelength++;
if (fputc(ch, fout) == EOF) return END_WERROR;
if (++message_size > thismessage_size_limit) return END_SIZE;
}
{
int ch_state = 0;
register int ch;
+register int linelength = 0;
while ((ch = (RECEIVE_GETC)()) != EOF)
{
{
ch_state = 0;
body_linecount++;
+ if (linelength > max_received_linelength)
+ max_received_linelength = linelength;
+ linelength = -1;
}
else if (ch == '\r')
{
case 2: /* After (unwritten) CR */
body_linecount++;
+ if (linelength > max_received_linelength)
+ max_received_linelength = linelength;
+ linelength = -1;
if (ch == '\n')
{
ch_state = 0;
next. */
message_size++;
+ linelength++;
if (fout != NULL)
{
if (fputc(ch, fout) == EOF) return END_WERROR;
int start, end, domain, size, sptr;
int id_resolution;
int had_zero = 0;
+int prevlines_length = 0;
register int ptr = 0;
spool_name[0] = 0;
message_size = 0;
warning_count = 0;
-received_count = 1; /* For the one we will add */
+received_count = 1; /* For the one we will add */
if (thismessage_size_limit <= 0) thismessage_size_limit = INT_MAX;
/* While reading the message, the following counts are computed. */
-message_linecount = body_linecount = body_zerocount = 0;
+message_linecount = body_linecount = body_zerocount =
+ max_received_linelength = 0;
#ifdef EXPERIMENTAL_DOMAINKEYS
/* Call into DK to set up the context. Check if DK is to be run are carried out
inside dk_exim_verify_init(). */
dk_exim_verify_init();
#endif
+#ifdef EXPERIMENTAL_DKIM
+/* Call into DKIM to set up the context. Check if DKIM is to be run are carried out
+ inside dk_exim_verify_init(). */
+dkim_exim_verify_init();
+#endif
+
/* Remember the time of reception. Exim uses time+pid for uniqueness of message
ids, and fractions of a second are required. See the comments that precede the
receive_linecount++;
message_linecount++;
+ /* Keep track of maximum line length */
+
+ if (ptr - prevlines_length > max_received_linelength)
+ max_received_linelength = ptr - prevlines_length;
+ prevlines_length = ptr + 1;
+
/* Now put in the terminating newline. There is always space for
at least two more characters. */
next->text = store_get(header_size);
ptr = 0;
had_zero = 0;
+ prevlines_length = 0;
} /* Continue, starting to read the next header */
/* At this point, we have read all the headers into a data structure in main
if (sender_address_unrewritten == NULL)
sender_address_unrewritten = sender_address;
sender_address = generated_sender_address;
- log_write(L_address_rewrite, LOG_MAIN,
- "\"%s\" from env-from rewritten as \"%s\" by submission mode",
- sender_address_unrewritten, generated_sender_address);
+ if (Ustrcmp(sender_address_unrewritten, generated_sender_address) != 0)
+ log_write(L_address_rewrite, LOG_MAIN,
+ "\"%s\" from env-from rewritten as \"%s\" by submission mode",
+ sender_address_unrewritten, generated_sender_address);
}
}
#ifdef EXPERIMENTAL_DOMAINKEYS
dk_exim_verify_finish();
#endif
+#ifdef EXPERIMENTAL_DKIM
+ dkim_exim_verify_finish();
+#endif
#ifdef WITH_CONTENT_SCAN
if (acl_smtp_mime != NULL &&
unspool_mbox();
#endif
+#ifdef EXPERIMENTAL_DCC
+dcc_ok = 0;
+#endif
+
+
/* The final check on the message is to run the scan_local() function. The
version supplied with Exim always accepts, but this is a hook for sysadmins to
supply their own checking code. The local_scan() function is run even when all
s = string_append(s, &size, &sptr, 2, US" CV=",
tls_certificate_verified? "yes":"no");
if ((log_extra_selector & LX_tls_peerdn) != 0 && tls_peerdn != NULL)
- s = string_append(s, &size, &sptr, 3, US" DN=\"", tls_peerdn, US"\"");
+ s = string_append(s, &size, &sptr, 3, US" DN=\"",
+ string_printing(tls_peerdn), US"\"");
#endif
if (sender_host_authenticated != NULL)