(2) Last-minute typo fix in spec.
(3) Trailing space removal ready for the release.
-. $Cambridge: exim/doc/doc-src/spec.src,v 1.7 2005/02/16 16:09:00 ph10 Exp $
+. $Cambridge: exim/doc/doc-src/spec.src,v 1.8 2005/02/17 11:58:25 ph10 Exp $
.
.set version "4.50"
.set previousversion "4.40"
.section Mailing lists
.index mailing lists||for Exim users
-The following are the two main Exim mailing lists:
+.em
+The following are the three main Exim mailing lists:
.display rm
.tabs 28
$it{exim-users@@exim.org} $t general discussion list
+$it{exim-dev@@exim.org} $t discussion of bugs, enhancements, etc.
$it{exim-announce@@exim.org} $t moderated, low volume announcements list
.endd
+.nem
You can subscribe to these lists, change your existing subscriptions, and view
or search the archives via the
.if ~~html
.index virus scanners||command line interface
\cmdline\: This is the keyword for the generic command line scanner interface.
It can be used to attach virus scanners that are invoked from the shell. This
-scanner type takes 3 mantadory options:
+scanner type takes 3 mandatory options:
.numberpars
The full path and name of the scanner binary, with all command line options,
and a placeholder (%s) for the directory to scan.
-$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.83 2005/02/17 10:04:40 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.84 2005/02/17 11:58:25 ph10 Exp $
Change log file for Exim from version 4.21
-------------------------------------------
84. Some minor changes to the Linux configuration files to help with other
OS variants using glibc.
+85. One more patch for Sieve to update vacation handling to latest spec.
+
----------------------------------------------------
See the note above about the 4.44 and 4.50 releases.
-# $Cambridge: exim/src/OS/Makefile-Base,v 1.2 2004/12/16 15:11:47 tom Exp $
+# $Cambridge: exim/src/OS/Makefile-Base,v 1.3 2005/02/17 11:58:25 ph10 Exp $
# This file is the basis of the main makefile for Exim and friends. The
# makefile at the top level arranges to build the main makefile by calling
route.o search.o sieve.o smtp_in.o smtp_out.o spool_in.o spool_out.o \
store.o string.o tls.o tod.o transport.o tree.o verify.o \
local_scan.o $(EXIM_PERL) $(OBJ_WITH_CONTENT_SCAN) \
- $(OBJ_WITH_OLD_DEMIME) $(OBJ_EXPERIMENTAL)
+ $(OBJ_WITH_OLD_DEMIME) $(OBJ_EXPERIMENTAL)
exim: pcre/libpcre.a lookups/lookups.a auths/auths.a \
routers/routers.a transports/transports.a \
-# $Cambridge: exim/src/src/EDITME,v 1.7 2005/01/25 14:16:33 ph10 Exp $
+# $Cambridge: exim/src/src/EDITME,v 1.8 2005/02/17 11:58:25 ph10 Exp $
##################################################
# The Exim mail transport agent #
# CONFIGURE_OWNER=
# If the configuration file is group-writeable, Exim insists by default that it
-# is owned by root or the Exim user. You can specify one additional permitted
+# is owned by root or the Exim user. You can specify one additional permitted
# group owner here.
# CONFIGURE_GROUP=
-/* $Cambridge: exim/src/src/acl.c,v 1.18 2005/01/27 10:26:14 ph10 Exp $ */
+/* $Cambridge: exim/src/src/acl.c,v 1.19 2005/02/17 11:58:25 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
ACLC_DELAY,
#ifdef WITH_OLD_DEMIME
ACLC_DEMIME,
-#endif
+#endif
ACLC_DNSLISTS, ACLC_DOMAINS, ACLC_ENCRYPTED, ACLC_ENDPASS,
ACLC_HOSTS, ACLC_LOCAL_PARTS, ACLC_LOG_MESSAGE, ACLC_LOGWRITE,
#ifdef WITH_CONTENT_SCAN
#endif
ACLC_SENDER_DOMAINS, ACLC_SENDERS, ACLC_SET,
#ifdef WITH_CONTENT_SCAN
- ACLC_SPAM,
+ ACLC_SPAM,
#endif
#ifdef EXPERIMENTAL_SPF
ACLC_SPF,
US"bmi_optin",
#endif
US"condition",
- US"control",
+ US"control",
#ifdef WITH_CONTENT_SCAN
US"decode",
#endif
US"spf",
#endif
US"verify" };
-
+
/* ACL control names */
static uschar *controls[] = { US"error", US"caseful_local_part",
US"caselower_local_part", US"enforce_sync", US"no_enforce_sync", US"freeze",
- US"queue_only", US"submission", US"no_multiline"};
+ US"queue_only", US"submission", US"no_multiline"};
/* Flags to indicate for which conditions /modifiers a string expansion is done
at the outer level. In the other cases, expansion already occurs in the
FALSE, /* authenticated */
#ifdef EXPERIMENTAL_BRIGHTMAIL
TRUE, /* bmi_optin */
-#endif
+#endif
TRUE, /* condition */
TRUE, /* control */
#ifdef WITH_CONTENT_SCAN
FALSE, /* authenticated */
#ifdef EXPERIMENTAL_BRIGHTMAIL
TRUE, /* bmi_optin */
-#endif
+#endif
FALSE, /* condition */
TRUE, /* control */
#ifdef WITH_CONTENT_SCAN
static unsigned int cond_forbids[] = {
0, /* acl */
-
+
(1<<ACL_WHERE_NOTSMTP)|(1<<ACL_WHERE_CONNECT)| /* authenticated */
(1<<ACL_WHERE_HELO),
-
+
#ifdef EXPERIMENTAL_BRIGHTMAIL
(1<<ACL_WHERE_AUTH)| /* bmi_optin */
(1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
(1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_MIME)|
- (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
+ (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
(1<<ACL_WHERE_MAILAUTH)|
(1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
(1<<ACL_WHERE_VRFY)|(1<<ACL_WHERE_PREDATA),
#endif
-
+
0, /* condition */
-
+
/* Certain types of control are always allowed, so we let it through
always and check in the control processing itself */
-
+
0, /* control */
-
+
#ifdef WITH_CONTENT_SCAN
(1<<ACL_WHERE_AUTH)| /* decode */
(1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
#endif
0, /* delay */
-
+
#ifdef WITH_OLD_DEMIME
(1<<ACL_WHERE_AUTH)| /* demime */
(1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
(1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
(1<<ACL_WHERE_VRFY)|(1<<ACL_WHERE_MIME),
#endif
-
+
(1<<ACL_WHERE_NOTSMTP), /* dnslists */
(1<<ACL_WHERE_NOTSMTP)|(1<<ACL_WHERE_AUTH)| /* domains */
(1<<ACL_WHERE_NOTSMTP)|(1<<ACL_WHERE_CONNECT)| /* encrypted */
(1<<ACL_WHERE_HELO),
-
+
0, /* endpass */
-
+
(1<<ACL_WHERE_NOTSMTP), /* hosts */
(1<<ACL_WHERE_NOTSMTP)|(1<<ACL_WHERE_AUTH)| /* local_parts */
(1<<ACL_WHERE_VRFY),
0, /* log_message */
-
+
0, /* logwrite */
-
+
#ifdef WITH_CONTENT_SCAN
(1<<ACL_WHERE_AUTH)| /* malware */
(1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
/* Return values from decode_control() */
-enum {
+enum {
#ifdef EXPERIMENTAL_BRIGHTMAIL
CONTROL_BMI_RUN,
-#endif
+#endif
CONTROL_ERROR, CONTROL_CASEFUL_LOCAL_PART, CONTROL_CASELOWER_LOCAL_PART,
CONTROL_ENFORCE_SYNC, CONTROL_NO_ENFORCE_SYNC, CONTROL_FREEZE,
CONTROL_QUEUE_ONLY, CONTROL_SUBMISSION,
#ifdef WITH_CONTENT_SCAN
- CONTROL_NO_MBOX_UNSPOOL,
+ CONTROL_NO_MBOX_UNSPOOL,
#endif
CONTROL_FAKEREJECT, CONTROL_NO_MULTILINE };
#endif
0, /* error */
-
- (unsigned int)
+
+ (unsigned int)
~(1<<ACL_WHERE_RCPT), /* caseful_local_part */
-
- (unsigned int)
+
+ (unsigned int)
~(1<<ACL_WHERE_RCPT), /* caselower_local_part */
-
+
(1<<ACL_WHERE_NOTSMTP), /* enforce_sync */
-
+
(1<<ACL_WHERE_NOTSMTP), /* no_enforce_sync */
-
- (unsigned int)
+
+ (unsigned int)
~((1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_RCPT)| /* freeze */
(1<<ACL_WHERE_PREDATA)|(1<<ACL_WHERE_DATA)|
(1<<ACL_WHERE_NOTSMTP)),
-
- (unsigned int)
+
+ (unsigned int)
~((1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_RCPT)| /* queue_only */
(1<<ACL_WHERE_PREDATA)|(1<<ACL_WHERE_DATA)|
(1<<ACL_WHERE_NOTSMTP)),
-
- (unsigned int)
+
+ (unsigned int)
~((1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_RCPT)| /* submission */
- (1<<ACL_WHERE_PREDATA)),
+ (1<<ACL_WHERE_PREDATA)),
#ifdef WITH_CONTENT_SCAN
- (unsigned int)
+ (unsigned int)
~((1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_RCPT)| /* no_mbox_unspool */
(1<<ACL_WHERE_PREDATA)|(1<<ACL_WHERE_DATA)),
#endif
- (unsigned int)
+ (unsigned int)
~((1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_RCPT)| /* fakereject */
(1<<ACL_WHERE_PREDATA)|(1<<ACL_WHERE_DATA)),
{
newtype = htype_add_rfc;
p += 14;
- }
+ }
else if (strncmpic(p, US":at_start:", 10) == 0)
{
newtype = htype_add_top;
uschar *opt;
uschar buffer[256];
while (isspace(*ss)) ss++;
-
- /* This callout option handling code has become a mess as new options
- have been added in an ad hoc manner. It should be tidied up into some
+
+ /* This callout option handling code has become a mess as new options
+ have been added in an ad hoc manner. It should be tidied up into some
kind of table-driven thing. */
-
+
while ((opt = string_nextinlist(&ss, &optsep, buffer, sizeof(buffer)))
!= NULL)
{
if (verify_header_sender)
{
- int verrno;
+ int verrno;
rc = verify_check_header_address(user_msgptr, log_msgptr, callout,
callout_overall, callout_connect, se_mailfrom, pm_mailfrom, verify_options,
&verrno);
if (rc != OK)
- {
+ {
*basic_errno = verrno;
if (smtp_return_error_details)
{
*user_msgptr = string_sprintf("Rejected after DATA: %s", *log_msgptr);
if (rc == DEFER) acl_temp_details = TRUE;
}
- }
+ }
}
/* Handle a sender address. The default is to verify *the* sender address, but
{
BOOL routed = TRUE;
uschar *save_address_data = deliver_address_data;
-
+
sender_vaddr = deliver_make_addr(verify_sender_address, TRUE);
if (no_details) setflag(sender_vaddr, af_sverify_told);
if (verify_sender_address[0] != 0)
sender_vaddr->special_action = rc;
sender_vaddr->next = sender_verified_list;
sender_verified_list = sender_vaddr;
-
- /* Restore the recipient address data, which might have been clobbered by
+
+ /* Restore the recipient address data, which might have been clobbered by
the sender verification. */
-
+
deliver_address_data = save_address_data;
}
-
+
/* Put the sender address_data value into $sender_address_data */
- sender_address_data = sender_vaddr->p.address_data;
+ sender_address_data = sender_vaddr->p.address_data;
}
/* A recipient address just gets a straightforward verify; again we must handle
rc = verify_address(&addr2, NULL, verify_options|vopt_is_recipient, callout,
callout_overall, callout_connect, se_mailfrom, pm_mailfrom, NULL);
HDEBUG(D_acl) debug_printf("----------- end verify ------------\n");
-
+
*log_msgptr = addr2.message;
- *user_msgptr = (addr2.user_message != NULL)?
+ *user_msgptr = (addr2.user_message != NULL)?
addr2.user_message : addr2.message;
*basic_errno = addr2.basic_errno;
for (; cb != NULL; cb = cb->next)
{
uschar *arg;
- int control_type;
+ int control_type;
/* The message and log_message items set up messages to be used in
case of rejection. They are expanded later. */
*log_msgptr = string_sprintf("cannot use \"control=%s\" in %s ACL",
controls[control_type], acl_wherenames[where]);
return ERROR;
- }
+ }
switch(control_type)
{
bmi_run = 1;
break;
#endif
-
+
case CONTROL_ERROR:
return ERROR;
case CONTROL_FAKEREJECT:
fake_reject = TRUE;
if (*p == '/')
- {
+ {
uschar *pp = p + 1;
- while (*pp != 0) pp++;
+ while (*pp != 0) pp++;
fake_reject_text = expand_string(string_copyn(p+1, pp-p));
p = pp;
}
case CONTROL_SUBMISSION:
submission_mode = TRUE;
while (*p == '/')
- {
+ {
if (Ustrncmp(p, "/sender_retain", 14) == 0)
{
p += 14;
active_local_sender_retain = TRUE;
- active_local_from_check = FALSE;
- }
+ active_local_from_check = FALSE;
+ }
else if (Ustrncmp(p, "/domain=", 8) == 0)
{
uschar *pp = p + 8;
- while (*pp != 0 && *pp != '/') pp++;
+ while (*pp != 0 && *pp != '/') pp++;
submission_domain = string_copyn(p+8, pp-p);
- p = pp;
+ p = pp;
}
- else break;
- }
+ else break;
+ }
if (*p != 0)
{
*log_msgptr = string_sprintf("syntax error in \"control=%s\"", arg);
HDEBUG(D_acl)
debug_printf("delay skipped in -bh checking mode\n");
}
- else
+ else
{
while (delay > 0) delay = sleep(delay);
- }
+ }
}
}
break;
log_write(0, logbits, "%s", string_printing(s));
}
break;
-
+
#ifdef WITH_CONTENT_SCAN
case ACLC_MALWARE:
{
-$Cambridge: exim/src/src/auths/README,v 1.2 2004/12/20 14:57:05 ph10 Exp $
+$Cambridge: exim/src/src/auths/README,v 1.3 2005/02/17 11:58:27 ph10 Exp $
AUTHS
DEFER couldn't complete the check
FAIL authentication failed
CANCELLED authentication forced to fail by "*" response to challenge,
- or by a forced string expansion failure
+ or by a forced string expansion failure
BAD64 bad base64 data received
UNEXPECTED unexpected data received
-/* $Cambridge: exim/src/src/auths/auth-spa.h,v 1.2 2004/12/29 10:55:58 ph10 Exp $ */
+/* $Cambridge: exim/src/src/auths/auth-spa.h,v 1.3 2005/02/17 11:58:27 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
* All the code used here was torn by Marc Prud'hommeaux out of the
* Samba project (by Andrew Tridgell, Jeremy Allison, and others).
*/
-
-/* December 2004: The spa_base64_to_bits() function has no length checking in
-it. I have added a check. PH */
+
+/* December 2004: The spa_base64_to_bits() function has no length checking in
+it. I have added a check. PH */
/* It seems that some systems have existing but different definitions of some
of the following types. I received a complaint about "int16" causing
-/* $Cambridge: exim/src/src/bmi_spam.c,v 1.2 2004/12/16 15:11:47 tom Exp $ */
+/* $Cambridge: exim/src/src/bmi_spam.c,v 1.3 2005/02/17 11:58:25 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
-
+
/* Code for calling Brightmail AntiSpam.
Copyright (c) Tom Kistner <tom@duncanthrax.net> 2004
License: GPL */
uschar *host_address;
uschar *verdicts = NULL;
int i,j;
-
+
err = bmiInitSystem(BMI_VERSION, (char *)bmi_config_file, &system);
if (bmiErrorIsFatal(err) == BMI_TRUE) {
err_loc = bmiErrorGetLocation(err);
for(i=0;i<recipients_count;i++) {
recipient_item *r = recipients_list + i;
BmiOptin *optin = NULL;
-
+
/* create optin object if optin string is given */
if ((r->bmi_optin != NULL) && (Ustrlen(r->bmi_optin) > 1)) {
debug_printf("passing bmiOptin string: %s\n", r->bmi_optin);
optin = NULL;
};
};
-
+
err = bmiAccumulateTO((char *)r->address, optin, message);
-
+
if (optin != NULL)
bmiOptinFree(optin);
-
+
if (bmiErrorIsFatal(err) == BMI_TRUE) {
err_loc = bmiErrorGetLocation(err);
err_type = bmiErrorGetType(err);
bmiFreeSystem(system);
return NULL;
};
-
+
/* Send message headers */
while (header_list != NULL) {
/* skip deleted headers */
bmiFreeSystem(system);
return NULL;
};
-
+
/* Send body */
data_file = fdopen(data_fd,"r");
do {
bmiFreeSystem(system);
return NULL;
};
-
-
+
+
/* End message */
err = bmiEndMessage(message);
if (bmiErrorIsFatal(err) == BMI_TRUE) {
bmiFreeSystem(system);
return NULL;
};
-
+
/* get store for the verdict string */
verdicts = store_get(1);
*verdicts = '\0';
-
+
for ( err = bmiAccessFirstVerdict(message, &verdict);
verdict != NULL;
err = bmiAccessNextVerdict(message, verdict, &verdict) ) {
BmiErrorType err_type;
BmiVerdict *verdict = NULL;
int rc = 1; /* deliver by default */
-
+
/* always deliver when there is no verdict */
if (base64_verdict == NULL)
return 1;
}
else if (bmiVerdictDestinationIsDefault(verdict) == BMI_TRUE) {
/* deliver normally */
- rc = 1;
+ rc = 1;
}
else if (bmiVerdictAccessDestination(verdict) == NULL) {
/* do not deliver */
/* deliver to alternate location */
rc = 1;
};
-
+
bmiFreeVerdict(verdict);
return rc;
}
BmiErrorType err_type;
BmiVerdict *verdict = NULL;
uschar *rc = NULL;
-
+
/* always deliver when there is no verdict */
if (base64_verdict == NULL)
return NULL;
"bmi error [loc %d type %d]: bmiCreateVerdictFromStr() failed. [%s]", (int)err_loc, (int)err_type, base64_verdict);
return NULL;
};
-
+
err = bmiVerdictError(verdict);
if (bmiErrorIsFatal(err) == BMI_TRUE) {
/* deliver normally due to error */
}
else if (bmiVerdictDestinationIsDefault(verdict) == BMI_TRUE) {
/* deliver normally */
- rc = NULL;
+ rc = NULL;
}
else if (bmiVerdictAccessDestination(verdict) == NULL) {
/* do not deliver */
Ustrcpy(rc, bmiVerdictAccessDestination(verdict));
rc[strlen(bmiVerdictAccessDestination(verdict))] = '\0';
};
-
+
bmiFreeVerdict(verdict);
return rc;
}
uschar *verdict_ptr;
uschar *verdict_buffer = NULL;
int sep = 0;
-
+
/* return nothing if there are no verdicts available */
if (bmi_verdicts == NULL)
return NULL;
-
+
/* allocate room for the b64 verdict string */
verdict_buffer = store_get(Ustrlen(bmi_verdicts)+1);
-
+
/* loop through verdicts */
verdict_ptr = bmi_verdicts;
while ((verdict_str = (const char *)string_nextinlist(&verdict_ptr, &sep,
verdict_buffer,
Ustrlen(bmi_verdicts)+1)) != NULL) {
-
+
/* create verdict from base64 string */
err = bmiCreateVerdictFromStr(verdict_str, &verdict);
if (bmiErrorIsFatal(err) == BMI_TRUE) {
"bmi error [loc %d type %d]: bmiCreateVerdictFromStr() failed. [%s]", (int)err_loc, (int)err_type, verdict_str);
return NULL;
};
-
+
/* loop through rcpts for this verdict */
for ( recipient = bmiVerdictAccessFirstRecipient(verdict);
recipient != NULL;
recipient = bmiVerdictAccessNextRecipient(verdict, recipient)) {
uschar *rcpt_local_part;
uschar *rcpt_domain;
-
+
/* compare address against our subject */
rcpt_local_part = (unsigned char *)bmiRecipientAccessAddress(recipient);
rcpt_domain = Ustrchr(rcpt_local_part,'@');
/* found verdict */
bmiFreeVerdict(verdict);
return (uschar *)verdict_str;
- };
+ };
};
-
+
bmiFreeVerdict(verdict);
};
-
+
return NULL;
}
BmiErrorType err_type;
BmiVerdict *verdict = NULL;
uschar *rc = NULL;
-
+
/* always deliver when there is no verdict */
if (base64_verdict == NULL)
return NULL;
"bmi error [loc %d type %d]: bmiCreateVerdictFromStr() failed. [%s]", (int)err_loc, (int)err_type, base64_verdict);
return NULL;
};
-
+
/* create old tracker string from verdict */
err = bmiCreateOldStrFromVerdict(verdict, &rc);
if (bmiErrorIsFatal(err) == BMI_TRUE) {
"bmi error [loc %d type %d]: bmiCreateOldStrFromVerdict() failed. [%s]", (int)err_loc, (int)err_type, base64_verdict);
return NULL;
};
-
+
bmiFreeVerdict(verdict);
return rc;
}
uschar *rule_ptr;
uschar rule_buffer[32];
int sep = 0;
-
-
+
+
/* no verdict -> no rule fired */
if (base64_verdict == NULL)
return 0;
-
+
/* create verdict from base64 string */
err = bmiCreateVerdictFromStr(CS base64_verdict, &verdict);
if (bmiErrorIsFatal(err) == BMI_TRUE) {
"bmi error [loc %d type %d]: bmiCreateVerdictFromStr() failed. [%s]", (int)err_loc, (int)err_type, base64_verdict);
return 0;
};
-
+
err = bmiVerdictError(verdict);
if (bmiErrorIsFatal(err) == BMI_TRUE) {
/* error -> no rule fired */
bmiFreeVerdict(verdict);
return 0;
}
-
+
/* loop through numbers */
rule_ptr = option_list;
while ((rule_num = string_nextinlist(&rule_ptr, &sep,
rule_buffer, 32)) != NULL) {
int rule_int = -1;
-
+
/* try to translate to int */
sscanf(rule_num, "%d", &rule_int);
if (rule_int > 0) {
-/* $Cambridge: exim/src/src/bmi_spam.h,v 1.2 2004/12/16 15:11:47 tom Exp $ */
+/* $Cambridge: exim/src/src/bmi_spam.h,v 1.3 2005/02/17 11:58:25 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
-
+
/* Code for calling Brightmail AntiSpam.
Copyright (c) Tom Kistner <tom@duncanthrax.net> 2004
License: GPL */
-/* $Cambridge: exim/src/src/buildconfig.c,v 1.5 2005/01/04 10:00:42 ph10 Exp $ */
+/* $Cambridge: exim/src/src/buildconfig.c,v 1.6 2005/02/17 11:58:25 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
if (strcmp(name, "CONFIGURE_OWNER") == 0 ||
strcmp(name, "CONFIGURE_GROUP") == 0)
{
- int isgroup = name[10] == 'G';
+ int isgroup = name[10] == 'G';
uid_t uid = 0;
- gid_t gid = 0;
+ gid_t gid = 0;
char *s;
char *username = NULL;
char *user = getenv(name);
{
if (isgroup)
gid = (gid_t)atoi(user);
- else
+ else
uid = (uid_t)atoi(user);
}
{
if (isgroup)
fprintf(new, "#define CONFIGURE_GROUPNAME \"%s\"\n", username);
- else
+ else
fprintf(new, "#define CONFIGURE_OWNERNAME \"%s\"\n", username);
}
-
+
if (isgroup)
fprintf(new, "#define CONFIGURE_GROUP %d\n", (int)gid);
- else
+ else
fprintf(new, "#define CONFIGURE_OWNER %d\n", (int)uid);
continue;
}
for (i = 1, j = 0; i <= count; list++, i++)
{
char name[64];
-
+
p = list;
while (*list != 0 && *list != ':') list++;
strncpy(name, p, list-p);
name[list-p] = 0;
-
+
if (name[0] == 0)
{
- continue;
- }
+ continue;
+ }
else if (name[strspn(name, "0123456789")] == 0)
{
vector[j++] = (uid_t)atoi(name);
continue;
}
- /* WITH_CONTENT_SCAN is another special case: it must be set if either it or
- WITH_OLD_DEMIME is set. */
+ /* WITH_CONTENT_SCAN is another special case: it must be set if either it or
+ WITH_OLD_DEMIME is set. */
if (strcmp(name, "WITH_CONTENT_SCAN") == 0)
{
fprintf(new, "#define WITH_CONTENT_SCAN yes\n");
else fprintf(new, "/* WITH_CONTENT_SCAN not set */\n");
continue;
- }
+ }
/* Otherwise, check whether a value exists in the environment. Remember if
it is an AUTH setting or SUPPORT_CRYPTEQ. */
-/* $Cambridge: exim/src/src/child.c,v 1.3 2005/01/04 10:00:42 ph10 Exp $ */
+/* $Cambridge: exim/src/src/child.c,v 1.4 2005/02/17 11:58:25 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
process is placed
wd if not NULL, a path to be handed to chdir() in the new process
make_leader if TRUE, make the new process a process group leader
-
+
Returns: the pid of the created process or -1 if anything has gone wrong
*/
-/* $Cambridge: exim/src/src/daemon.c,v 1.8 2005/02/16 15:24:21 ph10 Exp $ */
+/* $Cambridge: exim/src/src/daemon.c,v 1.9 2005/02/17 11:58:25 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
int i;
int queue_only_reason = 0;
int old_pool = store_pool;
- int save_debug_selector = debug_selector;
+ int save_debug_selector = debug_selector;
BOOL local_queue_only;
#ifdef SA_NOCLDWAIT
struct sigaction act;
/* Attempt to get an id from the sending machine via the RFC 1413
protocol. We do this in the sub-process in order not to hold up the
main process if there is any delay. Then set up the fullhost information
- in case there is no HELO/EHLO.
-
- If debugging is enabled only for the daemon, we must turn if off while
- finding the id, but turn it on again afterwards so that information about the
+ in case there is no HELO/EHLO.
+
+ If debugging is enabled only for the daemon, we must turn if off while
+ finding the id, but turn it on again afterwards so that information about the
incoming connection is output. */
-
+
if (debug_daemon) debug_selector = 0;
verify_get_ident(IDENT_PORT);
host_build_sender_fullhost();
- debug_selector = save_debug_selector;
+ debug_selector = save_debug_selector;
DEBUG(D_any)
debug_printf("Process %d is handling incoming connection from %s\n",
DEBUG(D_any) debug_printf("child %d ended: status=0x%x\n", (int)pid,
status);
- /* If it's a listening daemon for which we are keeping track of individual
+ /* If it's a listening daemon for which we are keeping track of individual
subprocesses, deal with an accepting process that has terminated. */
if (smtp_slots != NULL)
#ifdef LOAD_AVG_NEEDS_ROOT
if (queue_only_load >= 0 || smtp_load_reserve >= 0 ||
- (deliver_queue_load_max >= 0 && deliver_drop_privilege))
+ (deliver_queue_load_max >= 0 && deliver_drop_privilege))
(void)os_getloadavg();
#endif
close(0); /* Get rid of stdin/stdout/stderr */
close(1);
close(2);
- exim_nullstd(); /* Connect stdin/stdout/stderr to /dev/null */
+ exim_nullstd(); /* Connect stdin/stdout/stderr to /dev/null */
log_stderr = NULL; /* So no attempt to copy paniclog output */
/* If the parent process of this one has pid == 1, we are re-initializing the
- daemon as the result of a SIGHUP. In this case, there is no need to do
+ daemon as the result of a SIGHUP. In this case, there is no need to do
anything, because the controlling terminal has long gone. Otherwise, fork, in
case current process is a process group leader (see 'man setsid' for an
explanation) before calling setsid(). */
if ((pid = fork()) == 0)
{
int sk;
-
+
DEBUG(D_any) debug_printf("Starting queue-runner: pid %d\n",
(int)getpid());
/* Disable debugging if it's required only for the daemon process. We
- leave the above message, because it ties up with the "child ended"
+ leave the above message, because it ties up with the "child ended"
debugging messages. */
if (debug_daemon) debug_selector = 0;
-
+
/* Close any open listening sockets in the child */
for (sk = 0; sk < listen_socket_count; sk++) close(listen_sockets[sk]);
}
DEBUG(D_any) debug_printf("Listening...\n");
-
- /* In rare cases we may have had a SIGCHLD signal in the time between
- setting the handler (below) and getting back here. If so, pretend that the
+
+ /* In rare cases we may have had a SIGCHLD signal in the time between
+ setting the handler (below) and getting back here. If so, pretend that the
select() was interrupted so that we reap the child. This might still leave
- a small window when a SIGCHLD could get lost. However, since we use SIGCHLD
+ a small window when a SIGCHLD could get lost. However, since we use SIGCHLD
only to do the reaping more quickly, it shouldn't result in anything other
than a delay until something else causes a wake-up. */
if (sigchld_seen)
{
lcount = -1;
- errno = EINTR;
+ errno = EINTR;
}
else
- {
+ {
lcount = select(max_socket + 1, (SELECT_ARG2_TYPE *)&select_listen,
NULL, NULL, NULL);
- }
+ }
if (lcount < 0)
{
select_failed = TRUE;
lcount = 1;
}
-
- /* Clean up any subprocesses that may have terminated. We need to do this
- here so that smtp_accept_max_per_host works when a connection to that host
- has completed, and we are about to accept a new one. When this code was
- later in the sequence, a new connection could be rejected, even though an
- old one had just finished. Preserve the errno from any select() failure for
+
+ /* Clean up any subprocesses that may have terminated. We need to do this
+ here so that smtp_accept_max_per_host works when a connection to that host
+ has completed, and we are about to accept a new one. When this code was
+ later in the sequence, a new connection could be rejected, even though an
+ old one had just finished. Preserve the errno from any select() failure for
the use of the common select/accept error processing below. */
-
+
select_errno = errno;
handle_ending_processes();
- errno = select_errno;
-
+ errno = select_errno;
+
/* Loop for all the sockets that are currently ready to go. If select
actually failed, we have set the count to 1 and select_failed=TRUE, so as
to use the common error code for select/accept below. */
tv.tv_sec = queue_interval;
tv.tv_usec = 0;
select(0, NULL, NULL, NULL, &tv);
- handle_ending_processes();
+ handle_ending_processes();
}
/* Re-enable the SIGCHLD handler if it has been run. It can't do it
-/* $Cambridge: exim/src/src/deliver.c,v 1.6 2005/01/04 10:00:42 ph10 Exp $ */
+/* $Cambridge: exim/src/src/deliver.c,v 1.7 2005/02/17 11:58:25 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
Each separate item is written to the pipe in a single write(), and as they are
all short items, the writes will all be atomic and we should never find
-ourselves in the position of having read an incomplete item. "Short" in this
-case can mean up to about 1K in the case when there is a long error message
+ourselves in the position of having read an incomplete item. "Short" in this
+case can mean up to about 1K in the case when there is a long error message
associated with an address. */
DEBUG(D_deliver) debug_printf("reading pipe for subprocess %d (%s)\n",
}
/* Remove the two message files. */
-
+
sprintf(CS spoolname, "%s/input/%s/%s-D", spool_directory, message_subdir, id);
if (Uunlink(spoolname) < 0)
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to unlink %s", spoolname);
/* Log the end of this message, with queue time if requested. */
if ((log_extra_selector & LX_queue_time_overall) != 0)
- log_write(0, LOG_MAIN, "Completed QT=%s",
+ log_write(0, LOG_MAIN, "Completed QT=%s",
readconf_printtime(time(NULL) - received_time));
else
log_write(0, LOG_MAIN, "Completed");
-/* $Cambridge: exim/src/src/demime.c,v 1.3 2004/12/29 16:24:03 ph10 Exp $ */
+/* $Cambridge: exim/src/src/demime.c,v 1.4 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
FILE *mbox_file;
uschar defer_error_buffer[1024];
int demime_rc = 0;
-
+
/* reset found_extension variable */
found_extension = NULL;
-
+
/* try to find 1st option */
if ((option = string_nextinlist(&list, &sep,
option_buffer,
sizeof(option_buffer))) != NULL) {
-
+
/* parse 1st option */
if ( (Ustrcmp(option,"false") == 0) || (Ustrcmp(option,"0") == 0) ) {
/* explicitly no demimeing */
/* no options -> no demimeing */
return FAIL;
};
-
+
/* make sure the eml mbox file is spooled up */
mbox_file = spool_mbox(&mbox_size);
-
+
if (mbox_file == NULL) {
/* error while spooling */
log_write(0, LOG_MAIN|LOG_PANIC,
"demime acl condition: error while creating mbox spool file");
- return DEFER;
+ return DEFER;
};
-
+
/* call demimer if not already done earlier */
if (!demime_ok)
demime_rc = mime_demux(mbox_file, defer_error_buffer);
-
+
fclose(mbox_file);
-
+
if (demime_rc == DEFER) {
/* temporary failure (DEFER => DEFER) */
log_write(0, LOG_MAIN,
"demime acl condition: %s", defer_error_buffer);
return DEFER;
};
-
+
/* set demime_ok to avoid unpacking again */
demime_ok = 1;
-
+
/* check for file extensions, if there */
while (option != NULL) {
struct file_extension *this_extension = file_extensions;
-
+
/* Look for the wildcard. If it is found, we always return true.
The user must then use a custom condition to evaluate demime_errorlevel */
if (Ustrcmp(option,"*") == 0) {
};
/* loop thru extension list */
- while (this_extension != NULL) {
+ while (this_extension != NULL) {
if (strcmpic(option, this_extension->file_extension_string) == 0) {
/* found one */
found_extension = this_extension->file_extension_string;
};
this_extension = this_extension->next;
};
-
+
/* grab next extension from option list */
option = string_nextinlist(&list, &sep,
option_buffer,
sizeof(option_buffer));
};
-
+
/* nothing found */
return FAIL;
}
unsigned int mime_hstr_i(uschar *cptr) {
unsigned int i, j = 0;
-
+
while (cptr && *cptr && isxdigit(*cptr)) {
i = *cptr++ - '0';
if (9 < i) i -= 7;
j <<= 4;
j |= (i & 0x0f);
}
-
+
return(j);
}
uschar hex[] = {0,0,0};
int nan = 0;
uschar *initial_pos = qp_p;
-
+
/* advance one char */
qp_p++;
-
+
REPEAT_FIRST:
if ( (*qp_p == '\t') || (*qp_p == ' ') || (*qp_p == '\r') ) {
/* tab or whitespace may follow
qp_p++;
};
}
- else if (*qp_p == '\n') {
+ else if (*qp_p == '\n') {
/* hit soft line break already, continue */
*c = -1;
return qp_p;
*c = -2;
return initial_pos;
};
-
+
if ( (('0' <= *qp_p) && (*qp_p <= '9')) || (('A' <= *qp_p) && (*qp_p <= 'F')) || (('a' <= *qp_p) && (*qp_p <= 'f')) ) {
if (hex[0] > 0) {
hex[1] = *qp_p;
else {
/* huh ? */
*c = -2;
- return initial_pos;
+ return initial_pos;
};
}
else {
/* illegal char */
*c = -2;
- return initial_pos;
+ return initial_pos;
};
-
+
}
unsigned int file_nr;
uschar default_extension[] = ".com";
uschar *p;
-
+
if (extension == NULL)
extension = default_extension;
-
+
/* scan the proposed extension.
if it is longer than 4 chars, or
contains exotic chars, use the default extension */
-
+
/* if (Ustrlen(extension) > 4) {
extension = default_extension;
};
-*/
-
+*/
+
p = extension+1;
-
+
while (*p != 0) {
*p = (uschar)tolower((uschar)*p);
if ( (*p < 97) || (*p > 122) ) {
extension = default_extension;
- break;
+ break;
};
p++;
};
-
+
/* find a new file to write to */
file_nr = 0;
do {
struct stat mystat;
-
+
snprintf(CS file_name,1024,"%s/scan/%s/%s-%05u%s",spool_directory,message_id,message_id,file_nr,extension);
file_nr++;
if (file_nr >= MIME_SANITY_MAX_DUMP_FILES) {
result = stat(CS file_name,&mystat);
}
while(result != -1);
-
+
*f = fopen(CS file_name,"w+");
if (*f == NULL) {
/* cannot open new dump file, disk full ? -> soft error */
snprintf(CS info, 1024,"unable to open dump file");
return -2;
};
-
+
return file_nr;
}
/* Find a string in a mime header, and optionally fill in
the value associated with it into *value
-
+
returns: 0 - nothing found
1 - found param
2 - found param + value
int mime_header_find(uschar *header, uschar *param, uschar **value) {
uschar *needle;
-
+
needle = strstric(header,param,FALSE);
if (needle != NULL) {
if (value != NULL) {
if (*needle == '=') {
uschar *value_start;
uschar *value_end;
-
+
value_start = needle + 1;
value_end = strstric(value_start,US";",FALSE);
if (value_end != NULL) {
*value = (uschar *)malloc((value_end - value_start)+1);
if (*value == NULL)
return 0;
-
+
Ustrncpy(*value,value_start,(value_end - value_start));
(*value)[(value_end - value_start)] = '\0';
return 2;
int done = 0;
int header_value_mode = 0;
int header_open_brackets = 0;
-
+
*num_copied = 0;
-
+
while(!done) {
-
+
c = fgetc(f);
if (c == EOF) break;
-
+
/* --------- header mode -------------- */
if (mime_demux_mode == MIME_DEMUX_MODE_MIME_HEADERS) {
-
+
/* always skip CRs */
if (c == '\r') continue;
-
+
if (c == '\n') {
if ((*num_copied) > 0) {
/* look if next char is '\t' or ' ' */
c = ';';
done = 1;
};
-
+
/* skip control characters */
if (c < 32) continue;
-
+
/* skip whitespace + tabs */
if ( (c == ' ') || (c == '\t') )
continue;
/* --------- value mode ----------- */
/* skip quotes */
if (c == '"') continue;
-
+
/* leave value mode on ';' */
if (c == ';') {
header_value_mode = 0;
}
else if ( (c == '=') && !header_open_brackets ) {
/* enter value mode */
- header_value_mode = 1;
+ header_value_mode = 1;
};
-
+
/* skip chars while we are in a comment */
if (header_open_brackets > 0)
continue;
done = 1;
/* ------------------------------------ */
};
-
+
/* copy the char to the buffer */
buffer[*num_copied] = (uschar)c;
/* raise counter */
(*num_copied)++;
-
+
/* break if buffer is full */
if (*num_copied > MIME_SANITY_MAX_LINE_LENGTH-1) {
done = 1;
};
}
-
+
/* 0-terminate */
buffer[*num_copied] = '\0';
-
+
if (*num_copied > MIME_SANITY_MAX_LINE_LENGTH-1)
return MIME_READ_LINE_OVERFLOW;
else
struct boundary *thisboundary = boundaries;
uschar workbuf[MIME_SANITY_MAX_LINE_LENGTH+1];
unsigned int i,j=0;
-
+
/* check for '--' first */
if (Ustrncmp(line,"--",2) == 0) {
-
+
/* strip tab and space */
for (i = 2; i < Ustrlen(line); i++) {
if ((line[i] != ' ') && (line[i] != '\t')) {
if (Ustrncmp(&workbuf[Ustrlen(thisboundary->boundary_string)],"--",2) == 0) {
/* final boundary found */
return 2;
- };
+ };
return 1;
};
thisboundary = thisboundary->next;
};
};
-
- return 0;
+
+ return 0;
}
*/
int mime_check_uu_start(uschar *line, uschar *uu_file_extension, int *has_tnef) {
-
+
if ( (strncmpic(line,US"begin ",6) == 0)) {
uschar *uu_filename = &line[6];
-
+
/* skip perms, if present */
Ustrtoul(&line[6],&uu_filename,10);
-
+
/* advance one char */
uu_filename++;
-
+
/* This should be the filename.
Check if winmail.dat is present,
which indicates TNEF. */
if (strncmpic(uu_filename,US"winmail.dat",11) == 0) {
- *has_tnef = 1;
+ *has_tnef = 1;
};
-
+
/* reverse to dot if present,
copy up to 4 chars for the extension */
if (Ustrrchr(uu_filename,'.') != NULL)
uu_filename = Ustrrchr(uu_filename,'.');
-
+
return sscanf(CS uu_filename, "%4[.0-9A-Za-z]",CS uu_file_extension);
}
else {
uschar tmp_c;
uschar *work;
int uu_decoded_line_len, uu_encoded_line_len;
-
+
/* allocate memory for data and work buffer */
*data = (uschar *)malloc(line_len);
if (*data == NULL) {
snprintf(CS info, 1024,"unable to allocate %lu bytes",line_len);
return -2;
};
-
+
memcpy(work,line,line_len);
-
+
/* First char is line length
This is microsofts way of getting it. Scary. */
if (work[0] < 32) {
else {
uu_decoded_line_len = uudec[work[0]];
};
-
+
p = &work[1];
while (*p > 32) {
uu_encoded_line_len = (p - &work[1]);
p = &work[1];
-
+
/* check that resulting line length is a multiple of 4 */
if ( ( uu_encoded_line_len % 4 ) != 0) {
if (!warned_about_uudec_line_sanity_1) {
};
while ( ((p - &work[1]) < uu_encoded_line_len) && (num_decoded < uu_decoded_line_len)) {
-
+
/* byte 0 ---------------------- */
if ((p - &work[1] + 1) >= uu_encoded_line_len) {
return 0;
}
-
+
(*data)[num_decoded] = *p;
(*data)[num_decoded] <<= 2;
-
+
tmp_c = *(p+1);
tmp_c >>= 4;
(*data)[num_decoded] |= tmp_c;
-
+
num_decoded++;
p++;
-
+
/* byte 1 ---------------------- */
if ((p - &work[1] + 1) >= uu_encoded_line_len) {
return 0;
}
-
+
(*data)[num_decoded] = *p;
(*data)[num_decoded] <<= 4;
-
+
tmp_c = *(p+1);
tmp_c >>= 2;
(*data)[num_decoded] |= tmp_c;
-
+
num_decoded++;
p++;
-
+
/* byte 2 ---------------------- */
if ((p - &work[1] + 1) >= uu_encoded_line_len) {
return 0;
}
-
+
(*data)[num_decoded] = *p;
(*data)[num_decoded] <<= 6;
-
+
(*data)[num_decoded] |= *(p+1);
-
+
num_decoded++;
p+=2;
-
+
};
-
+
return uu_decoded_line_len;
}
long num_decoded = 0;
int offset = 0;
uschar tmp_c;
-
+
/* allocate memory for data */
*data = (uschar *)malloc(max_data_len);
if (*data == NULL) {
snprintf(CS info, 1024,"unable to allocate %lu bytes",max_data_len);
return -2;
};
-
+
if (mime_demux_mode == MIME_DEMUX_MODE_BASE64) {
/* ---------------------------------------------- */
-
+
/* NULL out trailing '\r' and '\n' chars */
while (Ustrrchr(line,'\r') != NULL) {
*(Ustrrchr(line,'\r')) = '\0';
while (Ustrrchr(line,'\n') != NULL) {
*(Ustrrchr(line,'\n')) = '\0';
};
-
+
/* check maximum base 64 line length */
if (Ustrlen(line) > MIME_SANITY_MAX_B64_LINE_LENGTH ) {
if (!warned_about_b64_line_length) {
};
};
*p = 255;
-
+
/* check that resulting line length is a multiple of 4 */
if ( ( (p - &line[0]) % 4 ) != 0) {
if (!warned_about_b64_line_sanity) {
warned_about_b64_line_sanity = 1;
};
};
-
+
/* line is translated, start bit shifting */
p = line;
num_decoded = 0;
-
+
while(*p != 255) {
-
+
/* byte 0 ---------------------- */
if (*(p+1) == 255) {
break;
}
-
+
(*data)[num_decoded] = *p;
(*data)[num_decoded] <<= 2;
-
+
tmp_c = *(p+1);
tmp_c >>= 4;
(*data)[num_decoded] |= tmp_c;
-
+
num_decoded++;
p++;
-
+
/* byte 1 ---------------------- */
if (*(p+1) == 255) {
break;
}
-
+
(*data)[num_decoded] = *p;
(*data)[num_decoded] <<= 4;
-
+
tmp_c = *(p+1);
tmp_c >>= 2;
(*data)[num_decoded] |= tmp_c;
-
+
num_decoded++;
p++;
-
+
/* byte 2 ---------------------- */
if (*(p+1) == 255) {
break;
}
-
+
(*data)[num_decoded] = *p;
(*data)[num_decoded] <<= 6;
-
+
(*data)[num_decoded] |= *(p+1);
-
+
num_decoded++;
p+=2;
-
+
};
- return num_decoded;
+ return num_decoded;
/* ---------------------------------------------- */
}
else if (mime_demux_mode == MIME_DEMUX_MODE_QP) {
/* ---------------------------------------------- */
p = line;
-
+
while (*p != 0) {
if (*p == '=') {
int decode_qp_result;
-
+
p = mime_decode_qp(p,&decode_qp_result);
-
+
if (decode_qp_result == -2) {
/* Error from decoder. p is unchanged. */
if (!warned_about_qp_line_sanity) {
p++;
}
else if (decode_qp_result == -1) {
- /* End of the line with soft line break.
+ /* End of the line with soft line break.
Bail out. */
goto QP_RETURN;
}
return num_decoded;
/* ---------------------------------------------- */
};
-
+
return 0;
}
struct mime_part mime_part_p;
int has_tnef = 0;
int has_rfc822 = 0;
-
+
/* allocate room for our linebuffer */
line = (uschar *)malloc(MIME_SANITY_MAX_LINE_LENGTH);
if (line == NULL) {
snprintf(CS info, 1024,"unable to allocate %u bytes",MIME_SANITY_MAX_LINE_LENGTH);
return DEFER;
};
-
+
/* clear MIME header structure */
memset(&mime_part_p,0,sizeof(mime_part));
-
+
/* ----------------------- start demux loop --------------------- */
while (mime_read_line_status == MIME_READ_LINE_OK) {
-
+
/* read a line of input. Depending on the mode we are in,
the returned format will differ. */
mime_read_line_status = mime_read_line(f,mime_demux_mode,line,&line_len);
-
+
if (mime_read_line_status == MIME_READ_LINE_OVERFLOW) {
mime_trigger_error(MIME_ERRORLEVEL_LONG_LINE);
/* despite the error, continue .. */
if (mime_demux_mode == MIME_DEMUX_MODE_MIME_HEADERS) {
/* -------------- header mode --------------------- */
-
+
/* Check for an empty line, which is the end of the headers.
In HEADER mode, the line is returned "cooked", with the
final '\n' replaced by a ';' */
if (line_len == 1) {
int tmp;
-
+
/* We have reached the end of the headers. Start decoding
with the collected settings. */
if (mime_part_p.seen_content_transfer_encoding > 1) {
/* default to plain mode if no specific encoding type found */
mime_demux_mode = MIME_DEMUX_MODE_PLAIN;
};
-
+
/* open new dump file */
tmp = mime_get_dump_file(mime_part_p.extension, &mime_dump_file, info);
if (tmp < 0) {
if (strncmpic(US"content-type:",line,Ustrlen("content-type:")) == 0) {
/* ---------------------------- Content-Type header ------------------------------- */
uschar *value = line;
-
+
/* check for message/partial MIME type and reject it */
if (mime_header_find(line,US"message/partial",NULL) > 0)
mime_trigger_error(MIME_ERRORLEVEL_MESSAGE_PARTIAL);
/* check for TNEF content type, remember to unpack TNEF later. */
if (mime_header_find(line,US"application/ms-tnef",NULL) > 0)
has_tnef = 1;
-
+
/* check for message/rfcxxx attachments */
if (mime_header_find(line,US"message/rfc822",NULL) > 0)
has_rfc822 = 1;
-
+
/* find the file extension, but do not fill it in
it is already set, since content-disposition has
precedence. */
if (mime_header_find(line,US"name",&value) == 2) {
if (Ustrlen(value) > MIME_SANITY_MAX_FILENAME)
mime_trigger_error(MIME_ERRORLEVEL_FILENAME_LENGTH);
- mime_part_p.extension = value;
+ mime_part_p.extension = value;
mime_part_p.extension = Ustrrchr(value,'.');
if (mime_part_p.extension == NULL) {
/* file without extension, setting
else {
struct file_extension *this_extension =
(struct file_extension *)malloc(sizeof(file_extension));
-
- this_extension->file_extension_string =
+
+ this_extension->file_extension_string =
(uschar *)malloc(Ustrlen(mime_part_p.extension)+1);
Ustrcpy(this_extension->file_extension_string,
mime_part_p.extension+1);
};
};
};
-
+
/* find a boundary and add it to the list, if present */
value = line;
if (mime_header_find(line,US"boundary",&value) == 2) {
struct boundary *thisboundary;
if (Ustrlen(value) > MIME_SANITY_MAX_BOUNDARY_LENGTH) {
- mime_trigger_error(MIME_ERRORLEVEL_BOUNDARY_LENGTH);
+ mime_trigger_error(MIME_ERRORLEVEL_BOUNDARY_LENGTH);
}
else {
thisboundary = (struct boundary*)malloc(sizeof(boundary));
boundaries = thisboundary;
};
};
-
+
if (mime_part_p.seen_content_type == 0) {
mime_part_p.seen_content_type = 1;
}
}
else if (strncmpic(US"content-transfer-encoding:",line,Ustrlen("content-transfer-encoding:")) == 0) {
/* ---------------------------- Content-Transfer-Encoding header -------------- */
-
+
if (mime_part_p.seen_content_transfer_encoding == 0) {
if (mime_header_find(line,US"base64",NULL) > 0) {
mime_part_p.seen_content_transfer_encoding = MIME_DEMUX_MODE_BASE64;
else if (strncmpic(US"content-disposition:",line,Ustrlen("content-disposition:")) == 0) {
/* ---------------------------- Content-Disposition header -------------------- */
uschar *value = line;
-
+
if (mime_part_p.seen_content_disposition == 0) {
mime_part_p.seen_content_disposition = 1;
-
+
if (mime_header_find(line,US"filename",&value) == 2) {
if (Ustrlen(value) > MIME_SANITY_MAX_FILENAME)
mime_trigger_error(MIME_ERRORLEVEL_FILENAME_LENGTH);
else {
struct file_extension *this_extension =
(struct file_extension *)malloc(sizeof(file_extension));
-
- this_extension->file_extension_string =
+
+ this_extension->file_extension_string =
(uschar *)malloc(Ustrlen(mime_part_p.extension)+1);
Ustrcpy(this_extension->file_extension_string,
mime_part_p.extension+1);
if (uu_mode == MIME_UU_MODE_UNCONFIRMED) {
/* We are in unconfirmed UUENCODE mode. */
-
+
data_len = uu_decode_line(line,&data,line_len,info);
-
+
if (data_len == -2) {
/* temp error, turn off uudecode mode */
if (uu_dump_file != NULL) {
};
};
};
-
+
/* write data to dump file, if available */
if (data_len > 0) {
if (fwrite(data,1,data_len,uu_dump_file) < data_len) {
/* short write */
snprintf(CS info, 1024,"short write on uudecode dump file");
free(line);
- return DEFER;
+ return DEFER;
};
};
};
-
+
if (mime_demux_mode != MIME_DEMUX_MODE_SCANNING) {
/* Non-scanning and Non-header mode. That means
we are currently decoding data to the dump
rewind(mime_dump_file);
mime_demux(mime_dump_file,info);
};
-
+
fclose(mime_dump_file); mime_dump_file = NULL;
};
}
rewind(mime_dump_file);
mime_demux(mime_dump_file,info);
};
-
+
fclose(mime_dump_file); mime_dump_file = NULL;
};
}
else {
uschar *data;
long data_len = 0;
-
+
/* decode the line with the appropriate method */
if (mime_demux_mode == MIME_DEMUX_MODE_PLAIN) {
/* in plain mode, just dump the line */
data_len = 0;
};
};
-
+
/* write data to dump file */
if (data_len > 0) {
if (fwrite(data,1,data_len,mime_dump_file) < data_len) {
/* short write */
snprintf(CS info, 1024,"short write on dump file");
free(line);
- return DEFER;
+ return DEFER;
};
};
-
+
};
}
else {
if (mime_check_boundary(line,boundaries) == 1) {
mime_demux_mode = MIME_DEMUX_MODE_MIME_HEADERS;
};
-
+
};
/* ------------------------------------------------ */
};
};
/* ----------------------- end demux loop ----------------------- */
-
+
/* close files, they could still be open */
if (mime_dump_file != NULL)
fclose(mime_dump_file);
if (uu_dump_file != NULL)
fclose(uu_dump_file);
-
+
/* release line buffer */
free(line);
-
+
/* FIXME: release boundary buffers.
Not too much of a problem since
this instance of exim is not resident. */
-
+
if (has_tnef) {
uschar file_name[1024];
/* at least one file could be TNEF encoded.
attempt to send all decoded files thru the TNEF decoder */
-
+
snprintf(CS file_name,1024,"%s/scan/%s",spool_directory,message_id);
/* Removed FTTB. We need to decide on TNEF inclusion */
/* mime_unpack_tnef(file_name); */
-/* $Cambridge: exim/src/src/demime.h,v 1.2 2004/12/16 15:11:47 tom Exp $ */
+/* $Cambridge: exim/src/src/demime.h,v 1.3 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
/* BASE64 decoder matrix */
static unsigned char b64[256]={
/* 0 */ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
-/* 16 */ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+/* 16 */ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
/* 32 */ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
/* 48 */ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 255, 128, 128,
/* 64 */ 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128
};
/* Microsoft-Style uudecode matrix */
static unsigned char uudec[256]={
-/* 0 */ 0, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+/* 0 */ 0, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
/* 16 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
/* 32 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
/* 48 */ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
/* 192 */ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
/* 208 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
/* 224 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
-/* 240 */ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
+/* 240 */ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
};
#endif
-/* $Cambridge: exim/src/src/dns.c,v 1.4 2005/01/04 10:00:42 ph10 Exp $ */
+/* $Cambridge: exim/src/src/dns.c,v 1.5 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
case T_PTR: return US"PTR";
case T_SRV: return US"SRV";
case T_NS: return US"NS";
- case T_CNAME: return US"CNAME";
+ case T_CNAME: return US"CNAME";
default: return US"?";
}
}
* Do a DNS lookup and handle virtual types *
************************************************/
-/* This function handles some invented "lookup types" that synthesize feature
-not available in the basic types. The special types all have negative values.
+/* This function handles some invented "lookup types" that synthesize feature
+not available in the basic types. The special types all have negative values.
Positive type values are passed straight on to dns_lookup().
Arguments:
*/
int
-dns_special_lookup(dns_answer *dnsa, uschar *name, int type,
+dns_special_lookup(dns_answer *dnsa, uschar *name, int type,
uschar **fully_qualified_name)
{
if (type >= 0) return dns_lookup(dnsa, name, type, fully_qualified_name);
if (type == T_MXH) return dns_lookup(dnsa, name, T_MX, fully_qualified_name);
-/* Find nameservers for the domain or the nearest enclosing zone, excluding the
+/* Find nameservers for the domain or the nearest enclosing zone, excluding the
root servers. */
if (type == T_ZNS)
int rc = dns_lookup(dnsa, d, T_NS, fully_qualified_name);
if (rc != DNS_NOMATCH && rc != DNS_NODATA) return rc;
while (*d != 0 && *d != '.') d++;
- if (*d++ == 0) break;
+ if (*d++ == 0) break;
}
- return DNS_NOMATCH;
- }
+ return DNS_NOMATCH;
+ }
/* Control should never reach here */
#! /bin/sh
-# $Cambridge: exim/src/src/exicyclog.src,v 1.2 2004/12/21 16:26:31 ph10 Exp $
+# $Cambridge: exim/src/src/exicyclog.src,v 1.3 2005/02/17 11:58:26 ph10 Exp $
# Copyright (c) 2004 University of Cambridge.
# See the file NOTICE for conditions of use and distribution.
# This is a shell script for cycling exim main and reject log files. Each time
# it is run, the files get "shuffled down" by one, the current one (e.g.
# mainlog) becoming mainlog.01, the previous mainlog.01 becoming mainlog.02,
-# and so on, up to the limit configured here. When the number to keep is
-# greater than 99 (not common, but some people do it), three digits are used
-# (e.g. mainlog.001). The same shuffling happens to the reject logs. All
+# and so on, up to the limit configured here. When the number to keep is
+# greater than 99 (not common, but some people do it), three digits are used
+# (e.g. mainlog.001). The same shuffling happens to the reject logs. All
# renamed files with numbers greater than 1 are compressed.
# This script should be called regularly (e.g. daily) by a root crontab
while [ $count -gt 1 ]; do
old=`expr $count - 1`
if [ $keep -gt 99 ]; then
- if [ $old -lt 10 ]; then oldt=00$old
+ if [ $old -lt 10 ]; then oldt=00$old
elif [ $old -lt 100 ]; then oldt=0$old
else oldt=$old
- fi
- else
+ fi
+ else
if [ $old -lt 10 ]; then oldt=0$old; else oldt=$old; fi;
- fi
+ fi
if [ -f $mainlog.$oldt ]; then
$mv $mainlog.$oldt $mainlog.$countt
elif [ -f $mainlog.$oldt.$suffix ]; then
if [ $count -lt 10 ]; then countt=00$count
elif [ $count -lt 100 ]; then countt=0$count
else countt=$count
- fi
- else
+ fi
+ else
if [ $count -lt 10 ]; then countt=0$count; else countt=$count; fi
- fi
+ fi
if [ -f $mainlog.$countt ]; then $compress $mainlog.$countt; fi
if [ -f $mainlog.$countt.$suffix ]; then
$chown $user:$group $mainlog.$countt.$suffix
-/* $Cambridge: exim/src/src/exim.c,v 1.13 2005/01/11 15:51:02 ph10 Exp $ */
+/* $Cambridge: exim/src/src/exim.c,v 1.14 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
check_port(uschar *address)
{
int port = host_extract_port(address);
-if (string_is_ip_address(address, NULL) == 0)
+if (string_is_ip_address(address, NULL) == 0)
{
fprintf(stderr, "exim abandoned: \"%s\" is not an IP address\n", address);
exit(EXIT_FAILURE);
break;
/* -d: Set debug level (see also -v below) or set the drop_cr option.
- The latter is now a no-op, retained for compatibility only. If -dd is used,
+ The latter is now a no-op, retained for compatibility only. If -dd is used,
debugging subprocesses of the daemon is disabled. */
case 'd':
if (host_checking)
{
- int x[4];
+ int x[4];
int size;
-
+
sender_ident = NULL;
if (running_in_test_harness && sender_host_port != 0 &&
interface_address != NULL && interface_port != 0)
verify_get_ident(1413);
-
+
/* In case the given address is a non-canonical IPv6 address, canonicize
it. The code works for both IPv4 and IPv6, as it happens. */
-
+
size = host_aton(sender_host_address, x);
sender_host_address = store_get(48); /* large enough for full IPv6 */
(void)host_nmtoa(size, x, -1, sender_host_address, ':');
if (ftest_suffix != NULL) printf("Suffix = %s\n", ftest_suffix);
chdir("/"); /* Get away from wherever the user is running this from */
-
- /* Now we run either a system filter test, or a user filter test, or both.
- In the latter case, headers added by the system filter will persist and be
- available to the user filter. We need to copy the filter variables
+
+ /* Now we run either a system filter test, or a user filter test, or both.
+ In the latter case, headers added by the system filter will persist and be
+ available to the user filter. We need to copy the filter variables
explicitly. */
-
+
if ((filter_test & FTEST_SYSTEM) != 0)
{
if (!filter_runtest(filter_sfd, filter_test_sfile, TRUE, more))
exim_exit(EXIT_FAILURE);
- }
-
+ }
+
memcpy(filter_sn, filter_n, sizeof(filter_sn));
-
+
if ((filter_test & FTEST_USER) != 0)
{
if (!filter_runtest(filter_ufd, filter_test_ufile, FALSE, more))
exim_exit(EXIT_FAILURE);
- }
-
+ }
+
exim_exit(EXIT_SUCCESS);
}
#!PERL_COMMAND -w
-# $Cambridge: exim/src/src/eximstats.src,v 1.5 2005/02/16 15:49:36 steve Exp $
+# $Cambridge: exim/src/src/eximstats.src,v 1.6 2005/02/17 11:58:26 ph10 Exp $
# Copyright (c) 2001 University of Cambridge.
# See the file NOTICE for conditions of use and distribution.
# Added warnings if required GD::Graph modules are not available or
# insufficient -chart* options are specified.
#
-# 2004-02-20 V1.31 Andrea Balzi
+# 2004-02-20 V1.31 Andrea Balzi
# Only show the Local Sender/Destination links if the tables exist.
#
# 2004-07-05 V1.32 Steve Campbell
#######################################################################
# un_round();
-#
+#
# un_round($rounded_volume,\$bytes,\$gigabytes);
-#
+#
# Given a volume in KB, MB or GB, as generated by volume_rounded(),
# do the reverse transformation and convert it back into Bytes and Gigabytes.
# These are added to the $bytes and $gigabytes parameters.
-#
+#
# Given a data size in bytes, round it to KB, MB, or GB
# as appropriate.
-#
+#
# EG: 500 => (500,0), 14GB => (0,14), etc.
#######################################################################
sub un_round {
#######################################################################
# add_volume();
-#
+#
# add_volume(\$bytes,\$gigs,$size);
-#
+#
# Add $size to $bytes/$gigs where this is a number split into
# bytes ($bytes) and gigabytes ($gigs). This is significantly
# faster than using Math::BigInt.
#######################################################################
# format_time();
-#
+#
# $formatted_time = format_time($seconds);
-#
+#
# Given a time in seconds, break it down into
# weeks, days, hours, minutes, and seconds.
-#
+#
# Eg 12005 => 3h20m5s
#######################################################################
sub format_time {
#######################################################################
# unformat_time();
-#
+#
# $seconds = unformat_time($formatted_time);
-#
+#
# Given a time in weeks, days, hours, minutes, or seconds, convert it to seconds.
-#
+#
# Eg 3h20m5s => 12005
#######################################################################
sub unformat_time {
#######################################################################
# seconds();
-#
+#
# $time = seconds($timestamp);
-#
+#
# Given a time-of-day timestamp, convert it into a time() value using
# POSIX::mktime. We expect the timestamp to be of the form
# "$year-$mon-$day $hour:$min:$sec", with month going from 1 to 12,
# (with the -utc option), then we adjust the time by the current local
# time offset so that it can be compared with the time recorded in message
# IDs, which is UTC.
-#
+#
# To improve performance, we only use mktime on the date ($year-$mon-$day),
# and only calculate it if the date is different to the previous time we
# came here. We then add on seconds for the '$hour:$min:$sec'.
-#
+#
# We also store the results of the last conversion done, and only
# recalculate if the date is different.
-#
+#
# We used to have the '-cache' flag which would store the results of the
# mktime() call. However, the current way of just using mktime() on the
# date obsoletes this.
#######################################################################
# id_seconds();
-#
+#
# $time = id_seconds($message_id);
-#
+#
# Given a message ID, convert it into a time() value.
#######################################################################
sub id_seconds {
#######################################################################
# calculate_localtime_offset();
-#
+#
# $localtime_offset = calculate_localtime_offset();
-#
+#
# Calculate the the localtime offset from gmtime in seconds.
-#
+#
# $localtime = time() + $localtime_offset.
-#
+#
# These are the same semantics as ISO 8601 and RFC 2822 timezone offsets.
# (West is negative, East is positive.)
#######################################################################
#######################################################################
# print_queue_times();
-#
+#
# $time = print_queue_times($message_type,\@queue_times,$queue_more_than);
-#
+#
# Given the type of messages being output, the array of message queue times,
# and the number of messages which exceeded the queue times, print out
# a table.
#######################################################################
# print_histogram();
-#
+#
# print_histogram('Deliverieds|Messages received',@interval_count);
-#
+#
# Print a histogram of the messages delivered/received per time slot
# (hour by default).
#######################################################################
#######################################################################
# print_league_table();
-#
+#
# print_league_table($league_table_type,\%message_count,\%message_data,\%message_data_gigs);
-#
+#
# Given hashes of message count and message data, which are keyed by
# the table type (eg by the sending host), print a league table
# showing the top $topcount (defaults to 50).
$htmlkey = $key;
$htmlkey =~ s/>/\>\;/g;
$htmlkey =~ s/</\<\;/g;
-
+
# When displaying the average figures, we calculate the average of
# the rounded data, as the user would calculate it. This reduces
# the accuracy slightly, but we have to do it this way otherwise
foreach $key (top_n_sort($topcount,$m_data_gigs,$m_data,$m_count)) {
# The largest volume will be the first (top of the list).
# If it has at least 1 gig, then just use gigabytes to avoid
- # risking an integer overflow when generating the pie charts.
+ # risking an integer overflow when generating the pie charts.
if ($$m_data_gigs{$key}) {
$use_gig = 1;
}
#######################################################################
# top_n_sort();
-#
+#
# @sorted_keys = top_n_sort($n,$href1,$href2,$href3);
-#
+#
# Given a hash which has numerical values, return the sorted $n keys which
# point to the top values. The second and third hashes are used as
# tiebreakers. They all must have the same keys.
-#
+#
# The idea behind this routine is that when you only want to see the
# top n members of a set, rather than sorting the entire set and then
# plucking off the top n, sort through the stack as you go, discarding
# any member which is lower than your current n'th highest member.
-#
+#
# This proves to be an order of magnitude faster for large hashes.
# On 200,000 lines of mainlog it benchmarked 9 times faster.
# On 700,000 lines of mainlog it benchmarked 13.8 times faster.
-#
+#
# We assume the values are > 0.
#######################################################################
sub top_n_sort {
my $n_minus_1 = $n - 1;
my $n_minus_2 = $n - 2;
- # Pick out the top $n keys.
+ # Pick out the top $n keys.
my($key,$value1,$value2,$value3,$i,$comparison,$insert_position);
while (($key,$value1) = each %$href1) {
#print STDERR "key $key ($value1,",$href2->{$key},",",$href3->{$key},") <=> ($minimum_value1,$minimum_value2,$minimum_value3)\n";
-
+
# Check to see that the new value is bigger than the lowest of the
# top n keys that we're keeping.
- $comparison = $value1 <=> $minimum_value1 ||
+ $comparison = $value1 <=> $minimum_value1 ||
$href2->{$key} <=> $minimum_value2 ||
$href3->{$key} <=> $minimum_value3 ||
$top_n_key cmp $key;
for ($i = 0; $i < $n_minus_1; $i++) {
$top_n_key = $top_n_keys[$i];
if ( ($top_n_key eq '_') ||
- ( ($value1 <=> $href1->{$top_n_key} ||
+ ( ($value1 <=> $href1->{$top_n_key} ||
$value2 <=> $href2->{$top_n_key} ||
$value3 <=> $href3->{$top_n_key} ||
$top_n_key cmp $key) == 1
#######################################################################
# html_header();
-#
+#
# $header = html_header($title);
-#
+#
# Print our HTML header and start the <body> block.
#######################################################################
sub html_header {
#######################################################################
# help();
-#
+#
# help();
-#
+#
# Display usage instructions and exit.
#######################################################################
sub help {
#######################################################################
# generate_parser();
-#
+#
# $parser = generate_parser();
-#
+#
# This subroutine generates the parsing routine which will be
# used to parse the mainlog. We take the base operation, and remove bits not in use.
# This improves performance depending on what bits you take out or add.
-#
+#
# I've tested using study(), but this does not improve performance.
-#
+#
# We store our parsing routing in a variable, and process it looking for #IFDEF (Expression)
# or #IFNDEF (Expression) statements and corresponding #ENDIF (Expression) statements. If
# the expression evaluates to true, then it is included/excluded accordingly.
#######################################################################
# parse();
-#
+#
# parse($parser,\*FILEHANDLE);
-#
+#
# This subroutine accepts a parser and a filehandle from main and parses each
# line. We store the results into global variables.
#######################################################################
#######################################################################
# print_header();
-#
+#
# print_header();
-#
+#
# Print our headers and contents.
#######################################################################
sub print_header {
#######################################################################
# print_grandtotals();
-#
+#
# print_grandtotals();
-#
+#
# Print the grand totals.
#######################################################################
sub print_grandtotals {
#######################################################################
# print_user_patterns()
-#
+#
# print_user_patterns();
-#
+#
# Print the counts of user specified patterns.
#######################################################################
sub print_user_patterns {
#######################################################################
# print_transport();
-#
+#
# print_transport();
-#
+#
# Print totals by transport.
#######################################################################
sub print_transport {
#######################################################################
# print_relay();
-#
+#
# print_relay();
-#
+#
# Print our totals by relay.
#######################################################################
sub print_relay {
#######################################################################
# print_errors();
-#
+#
# print_errors();
-#
+#
# Print our errors. In HTML, we display them as a list rather than a table -
# Netscape doesn't like large tables!
#######################################################################
$text =~ s/\s\s+/ /g; #Convert multiple spaces to a single space.
$total_errors += $errors_count{$key};
if ($html) {
-
+
#Translate HTML tag characters. Sergey Sholokh.
$text =~ s/\</\<\;/g;
$text =~ s/\>/\>\;/g;
#######################################################################
# parse_old_eximstat_reports();
-#
+#
# parse_old_eximstat_reports($fh);
-#
+#
# Parse old eximstat output so we can merge daily stats to weekly stats and weekly to monthly etc.
-#
+#
# To test that the merging still works after changes, do something like the following.
# All the diffs should produce no output.
-#
+#
# options='-bydomain -byemail -byhost -byedomain'
# options="$options -pattern 'Completed Messages' /Completed/"
# options="$options -pattern 'Received Messages' /<=/"
-#
+#
# ./eximstats $options mainlog > mainlog.txt
# ./eximstats $options -merge mainlog.txt > mainlog.2.txt
# diff mainlog.txt mainlog.2.txt
-#
+#
# ./eximstats $options -html mainlog > mainlog.html
# ./eximstats $options -merge -html mainlog.txt > mainlog.2.html
# diff mainlog.html mainlog.2.html
-#
+#
# ./eximstats $options -merge mainlog.html > mainlog.3.txt
# diff mainlog.txt mainlog.3.txt
-#
+#
# ./eximstats $options -merge -html mainlog.html > mainlog.3.html
# diff mainlog.html mainlog.3.html
-#
+#
# ./eximstats $options -nvr mainlog > mainlog.nvr.txt
# ./eximstats $options -merge mainlog.nvr.txt > mainlog.4.txt
# diff mainlog.txt mainlog.4.txt
-#
+#
# # double_mainlog.txt should have twice the values that mainlog.txt has.
# ./eximstats $options mainlog mainlog > double_mainlog.txt
#######################################################################
#######################################################################
# update_relayed();
-#
+#
# update_relayed($count,$sender,$recipient);
-#
+#
# Adds an entry into the %relayed hash. Currently only used when
# merging reports.
#######################################################################
#######################################################################
# add_to_totals();
-#
+#
# add_to_totals(\%totals,\@keys,$values);
-#
+#
# Given a line of space seperated values, add them into the provided hash using @keys
# as the hash keys.
-#
+#
# If the value contains a '%', then the value is set rather than added. Otherwise, we
# convert the value to bytes and gigs. The gigs get added to I<Key>-gigs.
#######################################################################
#######################################################################
# get_report_total();
-#
+#
# $total = get_report_total(\%hash,$key);
-#
+#
# If %hash contains values split into Units and Gigs, we calculate and return
-#
+#
# $hash{$key} + 1024*1024*1024 * $hash{"${key}-gigs"}
#######################################################################
sub get_report_total {
#######################################################################
# html2txt();
-#
+#
# $text_line = html2txt($html_line);
-#
+#
# Convert a line from html to text. Currently we just convert HTML tags to spaces
# and convert >, <, and tags back.
#######################################################################
#######################################################################
# get_next_arg();
-#
+#
# $arg = get_next_arg();
-#
+#
# Because eximstats arguments are often passed as variables,
# we can't rely on shell parsing to deal with quotes. This
# subroutine returns $ARGV[1] and does a shift. If $ARGV[1]
# starts with a quote (' or "), and doesn't end in one, then
# we append the next argument to it and shift again. We repeat
# until we've got all of the argument.
-#
+#
# This isn't perfect as all white space gets reduced to one space,
# but it's as good as we can get! If it's esential that spacing
# be preserved precisely, then you get that by not using shell
#!PERL_COMMAND
-# $Cambridge: exim/src/src/exipick.src,v 1.2 2004/11/12 12:01:52 ph10 Exp $
+# $Cambridge: exim/src/src/exipick.src,v 1.3 2005/02/17 11:58:26 ph10 Exp $
# This variable should be set by the building process to Exim's spool directory.
my $spool = 'SPOOL_DIRECTORY';
sub parse_message {
my $self = shift;
-
+
$self->_reset();
$self->{_message} = shift || return(0);
return(0) if (!$self->{_spool_dir});
}
}
- # when we drop out of the while loop, we have the first line of the
+ # when we drop out of the while loop, we have the first line of the
# delivered tree in $_
do {
if ($_ eq 'XX') {
}
return(1);
-}
+}
# mimic exim's host_extract_port function - receive a ref to a scalar,
# strip it of port, return port
print $fh $self->{_message}, "\n";
return;
}
-
+
if ($self->{_output_long} || $self->{_output_flatq}) {
my $i = int($self->{_vars}{message_age} / 60);
if ($i > 90) {
if ($self->{_output_long}) {
print $fh " ($self->{_vars}{originator_login})"
if ($self->{_vars}{sender_set_untrusted});
-
+
# XXX exim contains code here to print spool format errors
print $fh " *** frozen ***" if ($self->{_vars}{deliver_freeze});
print $fh "\n";
foreach my $v (keys(%{$self->{_show_vars}})) {
printf $fh " %25s = '%s'\n", $v, $self->get_var($v);
}
-
+
foreach my $r (keys %{$self->{_recips}}) {
next if ($self->{_del_tree}{$r} && $self->{_undelivered_only});
printf $fh " %s %s\n", $self->{_del_tree}{$r} ? "D" : " ", $r;
-/* $Cambridge: exim/src/src/expand.c,v 1.12 2005/01/25 14:16:33 ph10 Exp $ */
+/* $Cambridge: exim/src/src/expand.c,v 1.13 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
vtype_host_lookup, /* value not used; get host name */
vtype_load_avg, /* value not used; result is int from os_getloadavg */
vtype_pspace, /* partition space; value is T/F for spool/log */
- vtype_pinodes /* partition inodes; value is T/F for spool/log */
+ vtype_pinodes /* partition inodes; value is T/F for spool/log */
};
/* This table must be kept in alphabetical order. */
{ "exim_uid", vtype_uid, &exim_uid },
#ifdef WITH_OLD_DEMIME
{ "found_extension", vtype_stringptr, &found_extension },
-#endif
+#endif
{ "home", vtype_stringptr, &deliver_home },
{ "host", vtype_stringptr, &deliver_host },
{ "host_address", vtype_stringptr, &deliver_host_address },
{ "local_user_uid", vtype_uid, &local_user_uid },
{ "localhost_number", vtype_int, &host_number },
{ "log_inodes", vtype_pinodes, (void *)FALSE },
- { "log_space", vtype_pspace, (void *)FALSE },
+ { "log_space", vtype_pspace, (void *)FALSE },
{ "mailstore_basename", vtype_stringptr, &mailstore_basename },
#ifdef WITH_CONTENT_SCAN
{ "malware_name", vtype_stringptr, &malware_name },
{ "received_for", vtype_stringptr, &received_for },
{ "received_protocol", vtype_stringptr, &received_protocol },
{ "recipient_data", vtype_stringptr, &recipient_data },
- { "recipient_verify_failure",vtype_stringptr,&recipient_verify_failure },
+ { "recipient_verify_failure",vtype_stringptr,&recipient_verify_failure },
{ "recipients", vtype_recipients, NULL },
{ "recipients_count", vtype_int, &recipients_count },
#ifdef WITH_CONTENT_SCAN
{ "sender_host_port", vtype_int, &sender_host_port },
{ "sender_ident", vtype_stringptr, &sender_ident },
{ "sender_rcvhost", vtype_stringptr, &sender_rcvhost },
- { "sender_verify_failure",vtype_stringptr, &sender_verify_failure },
- { "smtp_active_hostname", vtype_stringptr, &smtp_active_hostname },
+ { "sender_verify_failure",vtype_stringptr, &sender_verify_failure },
+ { "smtp_active_hostname", vtype_stringptr, &smtp_active_hostname },
{ "smtp_command_argument", vtype_stringptr, &smtp_command_argument },
{ "sn0", vtype_filter_int, &filter_sn[0] },
{ "sn1", vtype_filter_int, &filter_sn[1] },
#endif
{ "spool_directory", vtype_stringptr, &spool_directory },
{ "spool_inodes", vtype_pinodes, (void *)TRUE },
- { "spool_space", vtype_pspace, (void *)TRUE },
+ { "spool_space", vtype_pspace, (void *)TRUE },
#ifdef EXPERIMENTAL_SRS
{ "srs_db_address", vtype_stringptr, &srs_db_address },
{ "srs_db_key", vtype_stringptr, &srs_db_key },
s[ptr] = 0; /* string_cat() leaves room */
}
return s;
-
+
case vtype_pspace:
{
int inodes;
- sprintf(CS var_buffer, "%d",
- receive_statvfs(var_table[middle].value == (void *)TRUE, &inodes));
+ sprintf(CS var_buffer, "%d",
+ receive_statvfs(var_table[middle].value == (void *)TRUE, &inodes));
}
return var_buffer;
-
+
case vtype_pinodes:
{
int inodes;
- (void) receive_statvfs(var_table[middle].value == (void *)TRUE, &inodes);
+ (void) receive_statvfs(var_table[middle].value == (void *)TRUE, &inodes);
sprintf(CS var_buffer, "%d", inodes);
}
return var_buffer;
/* If there are no following strings, we substitute the contents of $value for
lookups and for extractions in the success case. For the ${if item, the string
-"true" is substituted. In the fail case, nothing is substituted for all three
+"true" is substituted. In the fail case, nothing is substituted for all three
items. */
while (isspace(*s)) s++;
{
if (type[0] == 'i')
{
- if (yes) *yieldptr = string_cat(*yieldptr, sizeptr, ptrptr, US"true", 4);
+ if (yes) *yieldptr = string_cat(*yieldptr, sizeptr, ptrptr, US"true", 4);
}
else
- {
+ {
if (yes && lookup_value != NULL)
*yieldptr = string_cat(*yieldptr, sizeptr, ptrptr, lookup_value,
Ustrlen(lookup_value));
-/* $Cambridge: exim/src/src/filtertest.c,v 1.3 2005/01/04 10:00:42 ph10 Exp $ */
+/* $Cambridge: exim/src/src/filtertest.c,v 1.4 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
somewhat more tedious. Pile it all into a circular buffer and sort out at the
end.
-Arguments:
+Arguments:
dot_ended TRUE if message already terminated by '.'
Returns: nothing
*/
-
+
static void
read_message_body(dot_ended)
-{
+{
register int ch;
int body_len, body_end_len, header_size;
uschar *s;
Argument:
fd an fd containing the filter file
- filename the name of the filter file
+ filename the name of the filter file
is_system TRUE if testing is to be as a system filter
dot_ended TRUE if message already terminated by '.'
return TRUE;
}
-/* For a filter, set up the message_body variables and the message size if this
+/* For a filter, set up the message_body variables and the message size if this
is the first time this function has been called. */
if (message_body == NULL) read_message_body(dot_ended);
-/* $Cambridge: exim/src/src/functions.h,v 1.10 2005/01/27 10:26:14 ph10 Exp $ */
+/* $Cambridge: exim/src/src/functions.h,v 1.11 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
extern BOOL receive_check_fs(int);
extern BOOL receive_check_set_sender(uschar *);
extern BOOL receive_msg(BOOL);
-extern int receive_statvfs(BOOL, int *);
+extern int receive_statvfs(BOOL, int *);
extern void receive_swallow_smtp(void);
#ifdef WITH_CONTENT_SCAN
extern int regex(uschar **);
-/* $Cambridge: exim/src/src/globals.c,v 1.16 2005/02/16 16:28:36 ph10 Exp $ */
+/* $Cambridge: exim/src/src/globals.c,v 1.17 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
550, /* PREDATA */
#ifdef WITH_CONTENT_SCAN
550, /* MIME */
-#endif
+#endif
550, /* DATA */
0, /* not SMTP; not relevant */
503, /* AUTH */
550, /* STARTTLS */
252 /* VRFY */
};
-
+
BOOL active_local_from_check = FALSE;
BOOL active_local_sender_retain = FALSE;
BOOL accept_8bitmime = FALSE;
NULL, /* address_data */
#ifdef EXPERIMENTAL_BRIGHTMAIL
NULL, /* bmi_rule */
-#endif
+#endif
NULL, /* cannot_route_message */
NULL, /* condition */
NULL, /* current_directory */
uschar *srs_orig_sender = NULL;
uschar *srs_recipient = NULL;
uschar *srs_status = NULL;
-#endif
+#endif
int string_datestamp_offset= -1;
BOOL strip_excess_angle_brackets = FALSE;
BOOL strip_trailing_dot = FALSE;
-/* $Cambridge: exim/src/src/host.c,v 1.8 2005/01/25 14:16:33 ph10 Exp $ */
+/* $Cambridge: exim/src/src/host.c,v 1.9 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
Arguments:
host -> the first host item
last -> the last host item
-
+
Returns: nothing
-*/
+*/
static void
sort_addresses(host_item *host, host_item *last)
int x[4];
int v4offset = 0;
-/* Handle IPv6 address, which may end with an IPv4 address. It may also end
+/* Handle IPv6 address, which may end with an IPv4 address. It may also end
with a "scope", introduced by a percent sign. This code is NOT enclosed in #if
HAVE_IPV6 in order that IPv6 addresses are recognized even if IPv6 is not
supported. */
/* If the address starts with a colon, it will start with two colons.
Just lose the first one, which will leave a null first component. */
-
+
if (*p == ':') p++;
- /* Split the address into components separated by colons. The input address
- is supposed to be checked for syntax. There was a case where this was
- overlooked; to guard against that happening again, check here and crash if
+ /* Split the address into components separated by colons. The input address
+ is supposed to be checked for syntax. There was a case where this was
+ overlooked; to guard against that happening again, check here and crash if
there are too many components. */
while (*p != 0 && *p != '%')
{
int len = Ustrcspn(p, ":%");
if (len == 0) nulloffset = ci;
- if (ci > 7) log_write(0, LOG_MAIN|LOG_PANIC_DIE,
+ if (ci > 7) log_write(0, LOG_MAIN|LOG_PANIC_DIE,
"Internal error: invalid IPv6 address \"%s\" passed to host_aton()",
- address);
+ address);
component[ci++] = p;
p += len;
if (*p == ':') p++;
host byte order. Also, we really want IPv6 addresses to be in a canonical
format, so we output them with no abbreviation. In a number of cases we can't
use the normal colon separator in them because it terminates keys in lsearch
-files, so we want to use dot instead. There's an argument that specifies what
+files, so we want to use dot instead. There's an argument that specifies what
to use for IPv6 addresses.
Arguments:
binary points to the ints
mask mask value; if < 0 don't add to result
buffer big enough to hold the result
- sep component separator character for IPv6 addresses
+ sep component separator character for IPv6 addresses
Returns: the number of characters placed in buffer, not counting
the final nul.
The variable host_lookup_msg is set to an empty string on sucess, or to a
reason for the failure otherwise, in a form suitable for tagging onto an error
-message, and also host_lookup_failed is set TRUE if the lookup failed. If there
+message, and also host_lookup_failed is set TRUE if the lookup failed. If there
was a defer, host_lookup_deferred is set TRUE.
Any dynamically constructed string for host_lookup_msg must be in permanent
{
HDEBUG(D_host_lookup)
debug_printf("Test harness: host name lookup returns DEFER\n");
- host_lookup_deferred = TRUE;
+ host_lookup_deferred = TRUE;
return DEFER;
}
{
HDEBUG(D_host_lookup)
debug_printf("IP address PTR lookup gave temporary error\n");
- host_lookup_deferred = TRUE;
+ host_lookup_deferred = TRUE;
return DEFER;
}
}
HDEBUG(D_host_lookup)
debug_printf("IP address lookup using gethostbyaddr()\n");
rc = host_name_lookup_byaddr();
- if (rc == DEFER)
+ if (rc == DEFER)
{
- host_lookup_deferred = TRUE;
+ host_lookup_deferred = TRUE;
return rc; /* Can't carry on */
- }
+ }
if (rc == OK) break; /* Found a name */
}
} /* Loop for bydns/byaddr scanning */
else if (rc == HOST_FIND_AGAIN)
{
HDEBUG(D_host_lookup) debug_printf("temporary error for host name lookup\n");
- host_lookup_deferred = TRUE;
+ host_lookup_deferred = TRUE;
return DEFER;
}
else
uschar *endname = host->name + Ustrlen(host->name);
if (Ustrcmp(endname - 14, "test.again.dns") == 0)
return HOST_FIND_AGAIN;
- }
+ }
/* In an IPv6 world, we need to scan for both kinds of address, so go round the
loop twice. Note that we have ensured that AF_INET6 is defined even in an IPv4
fails or times out, but not if another one succeeds. (In the early
IPv6 days there are name servers that always fail on AAAA, but are happy
to give out an A record. We want to proceed with that A record.) */
-
+
if (rc != DNS_SUCCEED)
{
if (i == 0) /* Just tried for an A record, i.e. end of loop */
/* When running in the test harness, sort into the order of addresses so as
to get repeatability. */
-
+
if (running_in_test_harness) sort_addresses(host, last);
DEBUG(D_host_lookup)
-/* $Cambridge: exim/src/src/lookups/dnsdb.c,v 1.9 2005/01/11 15:51:03 ph10 Exp $ */
+/* $Cambridge: exim/src/src/lookups/dnsdb.c,v 1.10 2005/02/17 11:58:27 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
"ptr",
"srv",
"txt",
- "zns"
+ "zns"
};
static int type_values[] = {
/* See local README for interface description. The query in the "keystring" may
consist of a number of parts.
-(a) If the first significant character is '>' then the next character is the
-separator character that is used when multiple records are found. The default
+(a) If the first significant character is '>' then the next character is the
+separator character that is used when multiple records are found. The default
separator is newline.
(b) If the next sequence of characters is 'defer_FOO' followed by a comma,
whole lookup to defer only if none of the DNS queries succeeds; and 'never',
where all defers are as if the lookup failed. The default is 'lax'.
-(c) If the next sequence of characters is a sequence of letters and digits
-followed by '=', it is interpreted as the name of the DNS record type. The
+(c) If the next sequence of characters is a sequence of letters and digits
+followed by '=', it is interpreted as the name of the DNS record type. The
default is "TXT".
-(d) Then there follows list of domain names. This is a generalized Exim list,
-which may start with '<' in order to set a specific separator. The default
+(d) Then there follows list of domain names. This is a generalized Exim list,
+which may start with '<' in order to set a specific separator. The default
separator, as always, is colon. */
int
if (*keystring == '>')
{
outsep = keystring + 1;
- keystring += 2;
+ keystring += 2;
while (isspace(*keystring)) keystring++;
- }
+ }
/* Check for a defer behaviour keyword. */
{
int i, len;
uschar *tend = equals;
-
- while (tend > keystring && isspace(tend[-1])) tend--;
- len = tend - keystring;
-
+
+ while (tend > keystring && isspace(tend[-1])) tend--;
+ len = tend - keystring;
+
for (i = 0; i < sizeof(type_names)/sizeof(uschar *); i++)
{
if (len == Ustrlen(type_names[i]) &&
break;
}
}
-
+
if (i >= sizeof(type_names)/sizeof(uschar *))
{
*errmsg = US"unsupported DNS record type";
return DEFER;
}
-
+
keystring = equals + 1;
while (isspace(*keystring)) keystring++;
}
-
+
/* Initialize the resolver in case this is the first time it has been used. */
dns_init(FALSE, FALSE);
-/* The remainder of the string must be a list of domains. As long as the lookup
-for at least one of them succeeds, we return success. Failure means that none
-of them were found.
+/* The remainder of the string must be a list of domains. As long as the lookup
+for at least one of them succeeds, we return success. Failure means that none
+of them were found.
-The original implementation did not support a list of domains. Adding the list
-feature is compatible, except in one case: when PTR records are being looked up
-for a single IPv6 address. Fortunately, we can hack in a compatibility feature
-here: If the type is PTR and no list separator is specified, and the entire
-remaining string is valid as an IP address, set an impossible separator so that
+The original implementation did not support a list of domains. Adding the list
+feature is compatible, except in one case: when PTR records are being looked up
+for a single IPv6 address. Fortunately, we can hack in a compatibility feature
+here: If the type is PTR and no list separator is specified, and the entire
+remaining string is valid as an IP address, set an impossible separator so that
it is treated as one item. */
if (type == T_PTR && keystring[0] != '<' &&
- string_is_ip_address(keystring, NULL) > 0)
+ string_is_ip_address(keystring, NULL) > 0)
sep = -1;
/* Now scan the list and do a lookup for each item */
-while ((domain = string_nextinlist(&keystring, &sep, buffer, sizeof(buffer)))
+while ((domain = string_nextinlist(&keystring, &sep, buffer, sizeof(buffer)))
!= NULL)
- {
+ {
uschar rbuffer[256];
int searchtype = (type == T_ZNS)? T_NS : /* record type we want */
- (type == T_MXH)? T_MX : type;
+ (type == T_MXH)? T_MX : type;
/* If the type is PTR, we have to construct the relevant magic lookup key if
the original is an IP address (some experimental protocols are using PTR
records for different purposes where the key string is a host name). This
code for doing the reversal is now in a separate function. */
-
- if (type == T_PTR && string_is_ip_address(domain, NULL) > 0)
+
+ if (type == T_PTR && string_is_ip_address(domain, NULL) > 0)
{
dns_build_reverse(domain, rbuffer);
domain = rbuffer;
}
-
+
DEBUG(D_lookup) debug_printf("dnsdb key: %s\n", domain);
-
- /* Do the lookup and sort out the result. There are two special types that
- are handled specially: T_ZNS and T_MXH. The former is handled in a special
+
+ /* Do the lookup and sort out the result. There are two special types that
+ are handled specially: T_ZNS and T_MXH. The former is handled in a special
lookup function so that the facility could be used from other parts of the
Exim code. The latter affects only what happens later on in this function,
but for tidiness it is handled in a similar way. If the lookup fails,
- continue with the next domain. In the case of DEFER, adjust the final
+ continue with the next domain. In the case of DEFER, adjust the final
"nothing found" result, but carry on to the next domain. */
-
+
rc = dns_special_lookup(&dnsa, domain, type, NULL);
-
+
if (rc == DNS_NOMATCH || rc == DNS_NODATA) continue;
if (rc != DNS_SUCCEED)
{
else if (defer_mode == PASS) failrc = DEFER; /* defer only if all do */
continue; /* treat defer as fail */
}
-
+
/* Search the returned records */
for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS);
rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT))
{
if (rr->type != searchtype) continue;
-
- /* There may be several addresses from an A6 record. Put the configured
- separator between them, just as for between several records. However, A6
+
+ /* There may be several addresses from an A6 record. Put the configured
+ separator between them, just as for between several records. However, A6
support is not normally configured these days. */
-
+
if (type == T_A ||
#ifdef SUPPORT_A6
type == T_A6 ||
for (da = dns_address_from_rr(&dnsa, rr); da != NULL; da = da->next)
{
if (ptr != 0) yield = string_cat(yield, &size, &ptr, outsep, 1);
- yield = string_cat(yield, &size, &ptr, da->address,
+ yield = string_cat(yield, &size, &ptr, da->address,
Ustrlen(da->address));
}
continue;
}
-
- /* Other kinds of record just have one piece of data each, but there may be
+
+ /* Other kinds of record just have one piece of data each, but there may be
several of them, of course. */
-
+
if (ptr != 0) yield = string_cat(yield, &size, &ptr, outsep, 1);
-
+
if (type == T_TXT)
{
yield = string_cat(yield, &size, &ptr, (uschar *)(rr->data+1),
}
else /* T_CNAME, T_MX, T_MXH, T_NS, T_SRV, T_PTR */
{
- int num;
+ int num;
uschar s[264];
uschar *p = (uschar *)(rr->data);
-
+
if (type == T_MXH)
{
/* mxh ignores the priority number and includes only the hostnames */
sprintf(CS s, "%d %d %d ", num, weight, port);
yield = string_cat(yield, &size, &ptr, s, Ustrlen(s));
}
-
+
rc = dn_expand(dnsa.answer, dnsa.answer + dnsa.answerlen, p,
(DN_EXPAND_ARG4_TYPE)(s), sizeof(s));
-
+
/* If an overlong response was received, the data will have been
truncated and dn_expand may fail. */
-
+
if (rc < 0)
{
log_write(0, LOG_MAIN, "host name alias list truncated: type=%s "
store_reset(yield + ptr + 1);
-/* If ptr == 0 we have not found anything. Otherwise, insert the terminating
+/* If ptr == 0 we have not found anything. Otherwise, insert the terminating
zero and return the result. */
if (ptr == 0) return failrc;
-/* $Cambridge: exim/src/src/lookups/ldap.c,v 1.8 2005/01/13 11:12:12 ph10 Exp $ */
+/* $Cambridge: exim/src/src/lookups/ldap.c,v 1.9 2005/02/17 11:58:27 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
#ifdef LDAP_OPT_NETWORK_TIMEOUT
if (tcplimit > 0)
ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, (void *)timeoutptr);
- #endif
+ #endif
/* I could not get TLS to work until I set the version to 3. That version
seems to be the default nowadays. The RFC is dated 1997, so I would hope
if ((rc = ldap_result( lcp->ld, msgid, 1, timeoutptr, &result )) <= 0)
{
*errmsg = string_sprintf("failed to bind the LDAP connection to server "
- "%s%s - LDAP error: %s", host, porttext,
+ "%s%s - LDAP error: %s", host, porttext,
rc == -1 ? "result retrieval failed" : "timeout" );
result = NULL;
goto RETURN_ERROR;
#if defined LDAP_LIB_SOLARIS || defined LDAP_LIB_OPENLDAP2
int err;
ldap_get_option(lcp->ld, LDAP_OPT_ERROR_NUMBER, &err);
- *errmsg = string_sprintf("ldap_search failed: %d, %s", err,
+ *errmsg = string_sprintf("ldap_search failed: %d, %s", err,
ldap_err2string(err));
-
- #else
+
+ #else
*errmsg = string_sprintf("ldap_search failed");
#endif
-
+
goto RETURN_ERROR;
}
}
/* A return code that isn't -1 doesn't necessarily mean there were no problems
-with the search. The message must be an LDAP_RES_SEARCH_RESULT or
-LDAP_RES_SEARCH_REFERENCE or else it's something we can't handle. Some versions
-of LDAP do not define LDAP_RES_SEARCH_REFERENCE (LDAP v1 is one, it seems). So
+with the search. The message must be an LDAP_RES_SEARCH_RESULT or
+LDAP_RES_SEARCH_REFERENCE or else it's something we can't handle. Some versions
+of LDAP do not define LDAP_RES_SEARCH_REFERENCE (LDAP v1 is one, it seems). So
we don't provide that functionality when we can't. :-) */
-if (rc != LDAP_RES_SEARCH_RESULT
+if (rc != LDAP_RES_SEARCH_RESULT
#ifdef LDAP_RES_SEARCH_REFERENCE
&& rc != LDAP_RES_SEARCH_REFERENCE
-#endif
+#endif
)
{
*errmsg = string_sprintf("ldap_result returned unexpected code %d", rc);
#if defined LDAP_LIB_SOLARIS || defined LDAP_LIB_OPENLDAP2
ldap_rc = rc;
- ldap_parse_rc = ldap_parse_result(lcp->ld, result, &rc, CSS &matched,
+ ldap_parse_rc = ldap_parse_result(lcp->ld, result, &rc, CSS &matched,
CSS &error2, NULL, NULL, 0);
DEBUG(D_lookup) debug_printf("ldap_parse_result: %d\n", ldap_parse_rc);
- if (ldap_parse_rc < 0 &&
+ if (ldap_parse_rc < 0 &&
(ldap_parse_rc != LDAP_NO_RESULTS_RETURNED
- #ifdef LDAP_RES_SEARCH_REFERENCE
+ #ifdef LDAP_RES_SEARCH_REFERENCE
|| ldap_rc != LDAP_RES_SEARCH_REFERENCE
- #endif
+ #endif
))
{
*errmsg = string_sprintf("ldap_parse_result failed %d", ldap_parse_rc);
-/* $Cambridge: exim/src/src/macros.h,v 1.8 2005/01/12 12:51:55 ph10 Exp $ */
+/* $Cambridge: exim/src/src/macros.h,v 1.9 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
#define FTEST_NONE 0 /* Not filter testing */
#define FTEST_USER 1 /* Testing user filter */
-#define FTEST_SYSTEM 2 /* Testing system filter */
+#define FTEST_SYSTEM 2 /* Testing system filter */
/* Returns from the routing, transport and authentication functions (not all
apply to all of them). Some other functions also use these convenient values,
-/* $Cambridge: exim/src/src/malware.c,v 1.6 2005/01/13 10:09:36 ph10 Exp $ */
+/* $Cambridge: exim/src/src/malware.c,v 1.7 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
#define DERR_TIMEOUT (1<<9) /* scan timeout has run out */
#define DERR_BAD_CALL (1<<15) /* wrong command */
-/* Routine to check whether a system is big- or litte-endian.
+/* Routine to check whether a system is big- or litte-endian.
Ripped from http://www.faqs.org/faqs/graphics/fileformats-faq/part4/section-7.html
Needed for proper kavdaemon implementation. Sigh. */
#define BIG_MY_ENDIAN 0
int roffset;
const pcre *re;
const uschar *rerror;
-
+
/* make sure the eml mbox file is spooled up */
mbox_file = spool_mbox(&mbox_size);
if (mbox_file == NULL) {
/* error while spooling */
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: error while creating mbox spool file");
- return DEFER;
+ return DEFER;
};
/* none of our current scanners need the mbox
file as a stream, so we can close it right away */
fclose(mbox_file);
-
+
/* extract the malware regex to match against from the option list */
if ((malware_regex = string_nextinlist(&list, &sep,
malware_regex_buffer,
sizeof(malware_regex_buffer))) != NULL) {
-
+
/* parse 1st option */
- if ( (strcmpic(malware_regex,US"false") == 0) ||
+ if ( (strcmpic(malware_regex,US"false") == 0) ||
(Ustrcmp(malware_regex,"0") == 0) ) {
/* explicitly no matching */
return FAIL;
};
-
+
/* special cases (match anything except empty) */
- if ( (strcmpic(malware_regex,US"true") == 0) ||
- (Ustrcmp(malware_regex,"*") == 0) ||
+ if ( (strcmpic(malware_regex,US"true") == 0) ||
+ (Ustrcmp(malware_regex,"*") == 0) ||
(Ustrcmp(malware_regex,"1") == 0) ) {
malware_regex = malware_regex_default;
};
"malware acl condition: av_scanner configuration variable is empty");
return DEFER;
};
-
+
/* "drweb" scanner type ----------------------------------------------- */
/* v0.1 - added support for tcp sockets */
/* v0.0 - initial release -- support for unix sockets */
struct hostent *he;
struct in_addr in;
pcre *drweb_re;
-
+
if ((drweb_options = string_nextinlist(&av_scanner_work, &sep,
drweb_options_buffer, sizeof(drweb_options_buffer))) == NULL) {
/* no options supplied, use default options */
drweb_options = drweb_options_default;
};
-
+
if (*drweb_options != '/') {
-
+
/* extract host and port part */
if( sscanf(CS drweb_options, "%s %u", hostname, &port) != 2 ) {
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: drweb: invalid socket '%s'", drweb_options);
return DEFER;
}
-
+
/* Lookup the host */
if((he = gethostbyname(CS hostname)) == 0) {
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: drweb: failed to lookup host '%s'", hostname);
return DEFER;
}
-
+
in = *(struct in_addr *) he->h_addr_list[0];
-
+
/* Open the drwebd TCP socket */
if ( (sock = ip_socket(SOCK_STREAM, AF_INET)) < 0) {
log_write(0, LOG_MAIN|LOG_PANIC,
strerror(errno));
return DEFER;
}
-
+
if (ip_connect(sock, AF_INET, (uschar*)inet_ntoa(in), port, 5) < 0) {
- close(sock);
+ close(sock);
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: drweb: connection to %s, port %u failed (%s)",
inet_ntoa(in), port, strerror(errno));
return DEFER;
}
-
+
/* prepare variables */
drweb_cmd = htonl(DRWEBD_SCAN_CMD);
drweb_flags = htonl(DRWEBD_RETURN_VIRUSES | DRWEBD_IS_MAIL);
- snprintf(CS scanrequest, 1024,CS"%s/scan/%s/%s.eml",
+ snprintf(CS scanrequest, 1024,CS"%s/scan/%s/%s.eml",
spool_directory, message_id, message_id);
-
+
/* calc file size */
drweb_fd = open(CS scanrequest, O_RDONLY);
if (drweb_fd == -1) {
close(sock);
log_write(0, LOG_MAIN|LOG_PANIC,
- "malware acl condition: drweb: can't open spool file %s: %s",
+ "malware acl condition: drweb: can't open spool file %s: %s",
scanrequest, strerror(errno));
- return DEFER;
+ return DEFER;
}
fsize = lseek(drweb_fd, 0, SEEK_END);
if (fsize == -1) {
close(sock);
close(drweb_fd);
log_write(0, LOG_MAIN|LOG_PANIC,
- "malware acl condition: drweb: can't seek spool file %s: %s",
+ "malware acl condition: drweb: can't seek spool file %s: %s",
scanrequest, strerror(errno));
- return DEFER;
+ return DEFER;
}
drweb_slen = htonl(fsize);
lseek(drweb_fd, 0, SEEK_SET);
-
+
/* send scan request */
- if ((send(sock, &drweb_cmd, sizeof(drweb_cmd), 0) < 0) ||
+ if ((send(sock, &drweb_cmd, sizeof(drweb_cmd), 0) < 0) ||
(send(sock, &drweb_flags, sizeof(drweb_flags), 0) < 0) ||
(send(sock, &drweb_fin, sizeof(drweb_fin), 0) < 0) ||
(send(sock, &drweb_slen, sizeof(drweb_slen), 0) < 0)) {
- close(sock);
+ close(sock);
close(drweb_fd);
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: drweb: unable to send commands to socket (%s)", drweb_options);
return DEFER;
}
-
+
drweb_fbuf = (uschar *) malloc (fsize);
if (!drweb_fbuf) {
close(sock);
close(drweb_fd);
log_write(0, LOG_MAIN|LOG_PANIC,
- "malware acl condition: drweb: unable to allocate memory %u for file (%s)",
+ "malware acl condition: drweb: unable to allocate memory %u for file (%s)",
fsize, scanrequest);
return DEFER;
}
-
+
result = read (drweb_fd, drweb_fbuf, fsize);
if (result == -1) {
close(sock);
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: drweb: can't read spool file %s: %s",
scanrequest, strerror(errno));
- return DEFER;
+ return DEFER;
}
close(drweb_fd);
-
+
/* send file body to socket */
if (send(sock, drweb_fbuf, fsize, 0) < 0) {
close(sock);
if (sock < 0) {
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: drweb: can't open UNIX socket");
- return DEFER;
+ return DEFER;
}
server.sun_family = AF_UNIX;
Ustrcpy(server.sun_path, drweb_options);
"malware acl condition: drweb: unable to connect to socket (%s). errno=%d", drweb_options, errno);
return DEFER;
}
-
+
/* prepare variables */
drweb_cmd = htonl(DRWEBD_SCAN_CMD);
drweb_flags = htonl(DRWEBD_RETURN_VIRUSES | DRWEBD_IS_MAIL);
snprintf(CS scanrequest, 1024,CS"%s/scan/%s/%s.eml", spool_directory, message_id, message_id);
drweb_slen = htonl(Ustrlen(scanrequest));
-
+
/* send scan request */
- if ((send(sock, &drweb_cmd, sizeof(drweb_cmd), 0) < 0) ||
+ if ((send(sock, &drweb_cmd, sizeof(drweb_cmd), 0) < 0) ||
(send(sock, &drweb_flags, sizeof(drweb_flags), 0) < 0) ||
(send(sock, &drweb_slen, sizeof(drweb_slen), 0) < 0) ||
(send(sock, scanrequest, Ustrlen(scanrequest), 0) < 0) ||
return DEFER;
}
}
-
+
/* wait for result */
if ((bread = recv(sock, &drweb_rc, sizeof(drweb_rc), 0) != sizeof(drweb_rc))) {
close(sock);
return DEFER;
}
drweb_rc = ntohl(drweb_rc);
-
+
if ((bread = recv(sock, &drweb_vnum, sizeof(drweb_vnum), 0) != sizeof(drweb_vnum))) {
close(sock);
log_write(0, LOG_MAIN|LOG_PANIC,
return DEFER;
}
drweb_vnum = ntohl(drweb_vnum);
-
+
/* "virus(es) found" if virus number is > 0 */
if (drweb_vnum)
{
int i;
uschar pre_malware_nb[256];
-
+
malware_name = malware_name_buffer;
-
+
/* setup default virus name */
Ustrcpy(malware_name_buffer,"unknown");
-
+
/* read and concatenate virus names into one string */
for (i=0;i<drweb_vnum;i++)
{
return DEFER;
};
drweb_slen = ntohl(drweb_slen);
-
+
/* read report body */
if ((bread = recv(sock, tmpbuf, drweb_slen, 0)) != drweb_slen) {
close(sock);
return DEFER;
};
tmpbuf[drweb_slen] = '\0';
-
+
/* set up match regex, depends on retcode */
Ustrcpy(drweb_match_string, "infected\\swith\\s*(.+?)$");
-
+
drweb_re = pcre_compile( CS drweb_match_string,
PCRE_COPT,
(const char **)&rerror,
&roffset,
NULL );
-
+
/* try matcher on the line, grab substring */
result = pcre_exec(drweb_re, NULL, CS tmpbuf, Ustrlen(tmpbuf), 0, 0, ovector, 30);
if (result >= 2) {
uschar buf[32768];
struct sockaddr_un server;
int sock;
-
+
if ((kav_options = string_nextinlist(&av_scanner_work, &sep,
kav_options_buffer,
sizeof(kav_options_buffer))) == NULL) {
/* no options supplied, use default options */
kav_options = kav_options_default;
};
-
+
/* open the aveserver socket */
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: can't open UNIX socket.");
- return DEFER;
+ return DEFER;
}
server.sun_family = AF_UNIX;
Ustrcpy(server.sun_path, kav_options);
"malware acl condition: unable to connect to aveserver UNIX socket (%s). errno=%d", kav_options, errno);
return DEFER;
}
-
+
/* read aveserver's greeting and see if it is ready (2xx greeting) */
recv_line(sock, buf, 32768);
"malware acl condition: aveserver is unavailable (Responded: %s).", ((buf[0] != 0) ? buf : (uschar *)"nothing") );
return DEFER;
};
-
+
/* prepare our command */
snprintf(CS buf, 32768, "SCAN bPQRSTUW %s/scan/%s/%s.eml\r\n", spool_directory, message_id, message_id);
-
+
/* and send it */
if (send(sock, buf, Ustrlen(buf), 0) < 0) {
close(sock);
"malware acl condition: unable to write to aveserver UNIX socket (%s)", kav_options);
return DEFER;
}
-
+
malware_name = NULL;
/* read response lines, find malware name and final response */
while (recv_line(sock, buf, 32768) > 0) {
US"CONFIGURE\tTIMEOUT\t0\n",
US"CONFIGURE\tMAXARCH\t5\n",
US"CONFIGURE\tMIME\t1\n" };
-
+
malware_name = NULL;
if ((fsecure_options = string_nextinlist(&av_scanner_work, &sep,
fsecure_options_buffer,
- sizeof(fsecure_options_buffer))) == NULL) {
+ sizeof(fsecure_options_buffer))) == NULL) {
/* no options supplied, use default options */
fsecure_options = fsecure_options_default;
};
-
+
/* open the fsecure socket */
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
fsecure_options, strerror(errno));
return DEFER;
}
-
+
/* pass options */
memset(av_buffer, 0, sizeof(av_buffer));
for (i=0; i != 4; i++) {
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: unable to write fsecure option %d to %s (%s)",
i, fsecure_options, strerror(errno));
- return DEFER;
+ return DEFER;
};
-
+
bread = read(sock, av_buffer, sizeof(av_buffer));
if (bread >0) av_buffer[bread]='\0';
if (bread < 0) {
/* debug_printf("read answer %d read=%d \"%s\"\n", i, bread, av_buffer ); */
/* while (Ustrstr(av_buffer, "OK\tServer configured.@") == NULL); */
};
-
+
/* pass the mailfile to fsecure */
snprintf(CS file_name,1024,"SCAN\t%s/scan/%s/%s.eml\n", spool_directory, message_id, message_id);
/* debug_printf("send scan %s",file_name); */
fsecure_options, strerror(errno));
return DEFER;
};
-
+
/* set up match */
/* todo also SUSPICION\t */
fs_inf = pcre_compile("\\S{0,5}INFECTED\\t[^\\t]*\\t([^\\t]+)\\t\\S*$", PCRE_COPT, (const char **)&rerror, &roffset, NULL);
-
+
/* read report, linewise */
do {
int ovector[30];
while ((i < sizeof(av_buffer)-1 ) && (av_buffer[i-1] != '\n'));
av_buffer[i-1] = '\0';
/* debug_printf("got line \"%s\"\n",av_buffer); */
-
+
/* Really search for virus again? */
if (malware_name == NULL) {
/* try matcher on the line, grab substring */
};
}
while (Ustrstr(av_buffer, "OK\tScan ok.") == NULL);
- close(sock);
+ close(sock);
}
/* ----------------------------------------------------------------------- */
int kav_rc;
unsigned long kav_reportlen, bread;
pcre *kav_re;
-
+
if ((kav_options = string_nextinlist(&av_scanner_work, &sep,
kav_options_buffer,
sizeof(kav_options_buffer))) == NULL) {
/* no options supplied, use default options */
kav_options = kav_options_default;
};
-
+
/* open the kavdaemon socket */
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: can't open UNIX socket.");
- return DEFER;
+ return DEFER;
}
server.sun_family = AF_UNIX;
Ustrcpy(server.sun_path, kav_options);
"malware acl condition: unable to connect to kavdaemon UNIX socket (%s). errno=%d", kav_options, errno);
return DEFER;
}
-
+
/* get current date and time, build scan request */
time(&t);
strftime(CS tmpbuf, sizeof(tmpbuf), "<0>%d %b %H:%M:%S:%%s/scan/%%s", localtime(&t));
snprintf(CS scanrequest, 1024,CS tmpbuf, spool_directory, message_id);
-
+
/* send scan request */
if (send(sock, scanrequest, Ustrlen(scanrequest)+1, 0) < 0) {
close(sock);
"malware acl condition: unable to write to kavdaemon UNIX socket (%s)", kav_options);
return DEFER;
}
-
+
/* wait for result */
if ((bread = recv(sock, tmpbuf, 2, 0) != 2)) {
close(sock);
"malware acl condition: unable to read 2 bytes from kavdaemon socket.");
return DEFER;
}
-
+
/* get errorcode from one nibble */
if (test_byte_order() == LITTLE_MY_ENDIAN) {
kav_rc = tmpbuf[0] & 0x0F;
else {
kav_rc = tmpbuf[1] & 0x0F;
};
-
+
/* improper kavdaemon configuration */
if ( (kav_rc == 5) || (kav_rc == 6) ) {
close(sock);
"malware acl condition: please reconfigure kavdaemon to NOT disinfect or remove infected files.");
return DEFER;
};
-
+
if (kav_rc == 1) {
close(sock);
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: kavdaemon reported 'scanning not completed' (code 1).");
return DEFER;
};
-
+
if (kav_rc == 7) {
close(sock);
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: kavdaemon reported 'kavdaemon damaged' (code 7).");
return DEFER;
};
-
+
/* code 8 is not handled, since it is ambigous. It appears mostly on
bounces where part of a file has been cut off */
-
+
/* "virus found" return codes (2-4) */
if ((kav_rc > 1) && (kav_rc < 5)) {
int report_flag = 0;
-
+
/* setup default virus name */
Ustrcpy(malware_name_buffer,"unknown");
malware_name = malware_name_buffer;
-
+
if (test_byte_order() == LITTLE_MY_ENDIAN) {
report_flag = tmpbuf[1];
}
else {
report_flag = tmpbuf[0];
};
-
+
/* read the report, if available */
if( report_flag == 1 ) {
/* read report size */
"malware acl condition: cannot read report size from kavdaemon");
return DEFER;
};
-
+
/* it's possible that avp returns av_buffer[1] == 1 but the
reportsize is 0 (!?) */
if (kav_reportlen > 0) {
Ustrcpy(kav_match_string, "suspicion:\\s*(.+?)\\s*$");
else
Ustrcpy(kav_match_string, "infected:\\s*(.+?)\\s*$");
-
+
kav_re = pcre_compile( CS kav_match_string,
PCRE_COPT,
(const char **)&rerror,
&roffset,
NULL );
-
- /* read report, linewise */
+
+ /* read report, linewise */
while (kav_reportlen > 0) {
int result = 0;
int ovector[30];
-
+
bread = 0;
while ( recv(sock, &tmpbuf[bread], 1, 0) == 1 ) {
kav_reportlen--;
};
bread++;
tmpbuf[bread] = '\0';
-
+
/* try matcher on the line, grab substring */
result = pcre_exec(kav_re, NULL, CS tmpbuf, Ustrlen(tmpbuf), 0, 0, ovector, 30);
if (result >= 2) {
/* no virus found */
malware_name = NULL;
};
-
+
close(sock);
}
/* ----------------------------------------------------------------------- */
-
-
+
+
/* "cmdline" scanner type ------------------------------------------------ */
else if (strcmpic(scanner_name,US"cmdline") == 0) {
uschar *cmdline_scanner;
int trigger = 0;
int result;
int ovector[30];
-
+
/* find scanner command line */
if ((cmdline_scanner = string_nextinlist(&av_scanner_work, &sep,
cmdline_scanner_buffer,
/* no command line supplied */
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: missing commandline specification for cmdline scanner type.");
- return DEFER;
+ return DEFER;
};
-
+
/* find scanner output trigger */
if ((cmdline_trigger = string_nextinlist(&av_scanner_work, &sep,
cmdline_trigger_buffer,
/* no trigger regex supplied */
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: missing trigger specification for cmdline scanner type.");
- return DEFER;
+ return DEFER;
};
-
+
/* precompile trigger regex */
cmdline_trigger_re = pcre_compile(CS cmdline_trigger, PCRE_COPT, (const char **)&rerror, &roffset, NULL);
if (cmdline_trigger_re == NULL) {
"malware acl condition: regular expression error in '%s': %s at offset %d", cmdline_trigger_re, rerror, roffset);
return DEFER;
};
-
+
/* find scanner name regex */
if ((cmdline_regex = string_nextinlist(&av_scanner_work, &sep,
cmdline_regex_buffer,
/* no name regex supplied */
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: missing virus name regex specification for cmdline scanner type.");
- return DEFER;
+ return DEFER;
};
-
+
/* precompile name regex */
cmdline_regex_re = pcre_compile(CS cmdline_regex, PCRE_COPT, (const char **)&rerror, &roffset, NULL);
if (cmdline_regex_re == NULL) {
"malware acl condition: regular expression error in '%s': %s at offset %d", cmdline_regex_re, rerror, roffset);
return DEFER;
};
-
+
/* prepare scanner call */
snprintf(CS file_name,1024,"%s/scan/%s", spool_directory, message_id);
snprintf(CS commandline,1024, CS cmdline_scanner,file_name);
/* redirect STDERR too */
Ustrcat(commandline," 2>&1");
-
+
/* store exims signal handlers */
eximsigchld = signal(SIGCHLD,SIG_DFL);
eximsigpipe = signal(SIGPIPE,SIG_DFL);
-
+
scanner_out = popen(CS commandline,"r");
if (scanner_out == NULL) {
log_write(0, LOG_MAIN|LOG_PANIC,
signal(SIGPIPE,eximsigpipe);
return DEFER;
};
-
+
snprintf(CS file_name,1024,"%s/scan/%s/%s_scanner_output", spool_directory, message_id, message_id);
scanner_record = fopen(CS file_name,"w");
-
+
if (scanner_record == NULL) {
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: opening scanner output file (%s) failed: %s.", file_name, strerror(errno));
signal(SIGPIPE,eximsigpipe);
return DEFER;
};
-
+
/* look for trigger while recording output */
while(fgets(CS linebuffer,32767,scanner_out) != NULL) {
if ( Ustrlen(linebuffer) > fwrite(linebuffer, 1, Ustrlen(linebuffer), scanner_record) ) {
if (!trigger && regex_match_and_setup(cmdline_trigger_re, linebuffer, 0, -1))
trigger = 1;
};
-
+
fclose(scanner_record);
pclose(scanner_out);
signal(SIGCHLD,eximsigchld);
signal(SIGPIPE,eximsigpipe);
-
+
if (trigger) {
/* setup default virus name */
Ustrcpy(malware_name_buffer,"unknown");
malware_name = malware_name_buffer;
-
+
/* re-open the scanner output file, look for name match */
scanner_record = fopen(CS file_name,"r");
while(fgets(CS linebuffer,32767,scanner_record) != NULL) {
};
}
/* ----------------------------------------------------------------------- */
-
-
+
+
/* "sophie" scanner type ------------------------------------------------- */
else if (strcmpic(scanner_name,US"sophie") == 0) {
uschar *sophie_options;
int sock;
uschar file_name[1024];
uschar av_buffer[1024];
-
+
if ((sophie_options = string_nextinlist(&av_scanner_work, &sep,
sophie_options_buffer,
sizeof(sophie_options_buffer))) == NULL) {
/* no options supplied, use default options */
sophie_options = sophie_options_default;
};
-
+
/* open the sophie socket */
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: can't open UNIX socket.");
- return DEFER;
+ return DEFER;
}
server.sun_family = AF_UNIX;
Ustrcpy(server.sun_path, sophie_options);
"malware acl condition: unable to connect to sophie UNIX socket (%s). errno=%d", sophie_options, errno);
return DEFER;
}
-
+
/* pass the scan directory to sophie */
snprintf(CS file_name,1024,"%s/scan/%s", spool_directory, message_id);
if (write(sock, file_name, Ustrlen(file_name)) < 0) {
close(sock);
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: unable to write to sophie UNIX socket (%s)", sophie_options);
- return DEFER;
+ return DEFER;
};
-
+
write(sock, "\n", 1);
-
+
/* wait for result */
memset(av_buffer, 0, sizeof(av_buffer));
if ((!(bread = read(sock, av_buffer, sizeof(av_buffer))) > 0)) {
"malware acl condition: unable to read from sophie UNIX socket (%s)", sophie_options);
return DEFER;
};
-
+
close(sock);
-
+
/* infected ? */
if (av_buffer[0] == '1') {
if (Ustrchr(av_buffer, '\n')) *Ustrchr(av_buffer, '\n') = '\0';
};
}
/* ----------------------------------------------------------------------- */
-
+
/* "clamd" scanner type ------------------------------------------------- */
/* This code was contributed by David Saez */
uschar *p,*vname;
struct sockaddr_un server;
int sock,bread=0;
- unsigned int port;
+ unsigned int port;
uschar file_name[1024];
uschar av_buffer[1024];
uschar hostname[256];
sizeof(clamd_options2_buffer))) == NULL) {
clamd_options2 = clamd_options2_default;
}
-
+
/* socket does not start with '/' -> network socket */
if (*clamd_options != '/') {
-
+
/* extract host and port part */
if( sscanf(CS clamd_options, "%s %u", hostname, &port) != 2 ) {
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: clamd: invalid socket '%s'", clamd_options);
return DEFER;
};
-
+
/* Lookup the host */
if((he = gethostbyname(CS hostname)) == 0) {
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: clamd: failed to lookup host '%s'", hostname);
return DEFER;
}
-
+
in = *(struct in_addr *) he->h_addr_list[0];
-
+
/* Open the ClamAV Socket */
if ( (sock = ip_socket(SOCK_STREAM, AF_INET)) < 0) {
log_write(0, LOG_MAIN|LOG_PANIC,
strerror(errno));
return DEFER;
}
-
+
if (ip_connect(sock, AF_INET, (uschar*)inet_ntoa(in), port, 5) < 0) {
- close(sock);
+ close(sock);
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: clamd: connection to %s, port %u failed (%s)",
inet_ntoa(in), port, strerror(errno));
if (strcmpic(clamd_options2,US"local") == 0) {
/* Pass the string to ClamAV (7 = "SCAN \n" + \0) */
-
+
snprintf(CS file_name,1024,"SCAN %s/scan/%s\n", spool_directory, message_id);
-
+
if (send(sock, file_name, Ustrlen(file_name), 0) < 0) {
close(sock);
log_write(0, LOG_MAIN|LOG_PANIC,"malware acl condition: clamd: unable to write to socket (%s)",
strerror(errno));
return DEFER;
}
-
+
if (bread == sizeof(av_buffer)) {
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: clamd: buffer too small");
return DEFER;
}
-
+
if (!(*av_buffer2)) {
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: clamd: ClamAV returned null");
return DEFER;
}
-
+
av_buffer2[bread] = '\0';
if( sscanf(CS av_buffer2, "PORT %u\n", &port) != 1 ) {
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: clamd: Expected port information from clamd, got '%s'", av_buffer2);
return DEFER;
};
-
+
if ( (sockData = ip_socket(SOCK_STREAM, AF_INET)) < 0) {
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: clamd: unable to acquire socket (%s)",
strerror(errno));
return DEFER;
}
-
+
if (ip_connect(sockData, AF_INET, (uschar*)inet_ntoa(in), port, 5) < 0) {
close(sockData);
log_write(0, LOG_MAIN|LOG_PANIC,
snprintf(CS scanrequest, 1024,CS"%s/scan/%s/%s.eml",
spool_directory, message_id, message_id);
-
+
/* calc file size */
clam_fd = open(CS scanrequest, O_RDONLY);
if (clam_fd == -1) {
log_write(0, LOG_MAIN|LOG_PANIC,
- "malware acl condition: clamd: can't open spool file %s: %s",
+ "malware acl condition: clamd: can't open spool file %s: %s",
scanrequest, strerror(errno));
- return DEFER;
+ return DEFER;
}
fsize = lseek(clam_fd, 0, SEEK_END);
if (fsize == -1) {
log_write(0, LOG_MAIN|LOG_PANIC,
- "malware acl condition: clamd: can't seek spool file %s: %s",
+ "malware acl condition: clamd: can't seek spool file %s: %s",
scanrequest, strerror(errno));
- return DEFER;
+ return DEFER;
}
lseek(clam_fd, 0, SEEK_SET);
-
+
clamav_fbuf = (uschar *) malloc (fsize);
if (!clamav_fbuf) {
close(sockData);
close(clam_fd);
log_write(0, LOG_MAIN|LOG_PANIC,
- "malware acl condition: clamd: unable to allocate memory %u for file (%s)",
+ "malware acl condition: clamd: unable to allocate memory %u for file (%s)",
fsize, scanrequest);
return DEFER;
}
-
+
result = read (clam_fd, clamav_fbuf, fsize);
if (result == -1) {
close(sockData);
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: clamd: can't read spool file %s: %s",
scanrequest, strerror(errno));
- return DEFER;
+ return DEFER;
}
close(clam_fd);
strerror(errno));
return DEFER;
}
-
+
server.sun_family = AF_UNIX;
Ustrcpy(server.sun_path, clamd_options);
-
+
if (connect(sock, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) < 0) {
close(sock);
log_write(0, LOG_MAIN|LOG_PANIC,
return DEFER;
}
}
-
+
/* Pass the string to ClamAV (7 = "SCAN \n" + \0) */
-
+
snprintf(CS file_name,1024,"SCAN %s/scan/%s\n", spool_directory, message_id);
-
+
if (send(sock, file_name, Ustrlen(file_name), 0) < 0) {
close(sock);
log_write(0, LOG_MAIN|LOG_PANIC,"malware acl condition: clamd: unable to write to socket (%s)",
strerror(errno));
return DEFER;
}
-
- /*
+
+ /*
We're done sending, close socket for writing.
-
+
One user reported that clamd 0.70 does not like this any more ...
-
+
*/
-
+
/* shutdown(sock, SHUT_WR); */
-
+
/* Read the result */
memset(av_buffer, 0, sizeof(av_buffer));
bread = read(sock, av_buffer, sizeof(av_buffer));
strerror(errno));
return DEFER;
}
-
+
if (bread == sizeof(av_buffer)) {
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: clamd: buffer too small");
return DEFER;
}
-
+
/* Check the result. ClamAV Returns
infected: -> "<filename>: <virusname> FOUND"
not-infected: -> "<filename>: OK"
error: -> "<filename>: <errcode> ERROR */
-
+
if (!(*av_buffer)) {
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: clamd: ClamAV returned null");
return DEFER;
}
-
+
/* colon in returned output? */
if((p = Ustrrchr(av_buffer,':')) == NULL) {
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: clamd: ClamAV returned malformed result: %s",
- av_buffer);
+ av_buffer);
return DEFER;
}
-
+
/* strip filename strip CR at the end */
++p;
while (*p == ' ') ++p;
}
}
/* ----------------------------------------------------------------------- */
-
-
+
+
/* "mksd" scanner type --------------------------------------------------- */
else if (strcmpic(scanner_name,US"mksd") == 0) {
uschar *mksd_options;
struct sockaddr_un server;
int sock;
int retval;
-
+
if ((mksd_options = string_nextinlist(&av_scanner_work, &sep,
mksd_options_buffer,
sizeof(mksd_options_buffer))) != NULL) {
return DEFER;
}
}
-
+
/* open the mksd socket */
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
log_write(0, LOG_MAIN|LOG_PANIC,
"malware acl condition: can't open UNIX socket.");
- return DEFER;
+ return DEFER;
}
server.sun_family = AF_UNIX;
Ustrcpy(server.sun_path, "/var/run/mksd/socket");
"malware acl condition: unable to connect to mksd UNIX socket (/var/run/mksd/socket). errno=%d", errno);
return DEFER;
}
-
+
malware_name = NULL;
-
+
retval = mksd_scan_packed(sock);
-
+
if (retval != OK)
return retval;
}
return DEFER;
};
/* ----------------------------------------------------------------------- */
-
+
/* set "been here, done that" marker */
malware_ok = 1;
};
int mksd_writev (int sock, struct iovec *iov, int iovcnt)
{
int i;
-
+
for (;;) {
do
i = writev (sock, iov, iovcnt);
"malware acl condition: unable to write to mksd UNIX socket (/var/run/mksd/socket)");
return -1;
}
-
+
for (;;)
if (i >= iov->iov_len) {
if (--iovcnt == 0)
{
int offset = 0;
int i;
-
+
do {
if ((i = recv (sock, av_buffer+offset, av_buffer_size-offset, 0)) <= 0) {
close (sock);
"malware acl condition: unable to read from mksd UNIX socket (/var/run/mksd/socket)");
return -1;
}
-
+
offset += i;
/* offset == av_buffer_size -> buffer full */
if (offset == av_buffer_size) {
return -1;
}
} while (av_buffer[offset-1] != '\n');
-
+
av_buffer[offset] = '\0';
return offset;
}
int mksd_parse_line (char *line)
{
char *p;
-
+
switch (*line) {
case 'O':
/* OK */
struct iovec iov[7];
char *cmd = "MSQ/scan/.eml\n";
uschar av_buffer[1024];
-
+
iov[0].iov_base = cmd;
iov[0].iov_len = 3;
iov[1].iov_base = CS spool_directory;
iov[4].iov_len = 1;
iov[6].iov_base = cmd + 9;
iov[6].iov_len = 5;
-
+
if (mksd_writev (sock, iov, 7) < 0)
return DEFER;
-
+
if (mksd_read_lines (sock, av_buffer, sizeof (av_buffer)) < 0)
return DEFER;
-
+
close (sock);
-
+
return mksd_parse_line (CS av_buffer);
}
-/* $Cambridge: exim/src/src/match.c,v 1.4 2005/01/04 13:31:41 ph10 Exp $ */
+/* $Cambridge: exim/src/src/match.c,v 1.5 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
DEBUG(D_lists) debug_printf("address match: subject=%s pattern=%s\n",
subject, pattern);
-/* Handle a regular expression, which must match the entire incoming address.
+/* Handle a regular expression, which must match the entire incoming address.
This may be the empty address. */
if (*pattern == '^')
if (*s == '*') s++;
if (*s == '@') s++;
-/* If it is a straight lookup, do a lookup for the whole address. This may be
+/* If it is a straight lookup, do a lookup for the whole address. This may be
the empty address. Partial matching doesn't make sense here, so we ignore it,
but write a panic log entry. However, *@ matching will be honoured. */
valueptr);
}
-/* For the remaining cases, an empty subject matches only an empty pattern,
-because other patterns expect to have a local part and a domain to match
+/* For the remaining cases, an empty subject matches only an empty pattern,
+because other patterns expect to have a local part and a domain to match
against. */
if (*subject == 0) return (*pattern == 0)? OK : FAIL;
-/* $Cambridge: exim/src/src/mime.c,v 1.3 2004/12/17 14:52:44 ph10 Exp $ */
+/* $Cambridge: exim/src/src/mime.c,v 1.4 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
uschar hex[] = {0,0,0};
int nan = 0;
uschar *initial_pos = qp_p;
-
+
/* advance one char */
qp_p++;
-
+
REPEAT_FIRST:
if ( (*qp_p == '\t') || (*qp_p == ' ') || (*qp_p == '\r') ) {
/* tab or whitespace may follow
qp_p++;
};
}
- else if (*qp_p == '\n') {
+ else if (*qp_p == '\n') {
/* hit soft line break already, continue */
*c = -1;
return qp_p;
*c = -2;
return initial_pos;
};
-
+
if ( (('0' <= *qp_p) && (*qp_p <= '9')) || (('A' <= *qp_p) && (*qp_p <= 'F')) || (('a' <= *qp_p) && (*qp_p <= 'f')) ) {
if (hex[0] > 0) {
hex[1] = *qp_p;
else {
/* huh ? */
*c = -2;
- return initial_pos;
+ return initial_pos;
};
}
else {
/* illegal char */
*c = -2;
- return initial_pos;
+ return initial_pos;
};
}
else if (Ustrcmp(encoding,"base64") == 0) {
uschar *p = buffer;
int offset = 0;
-
+
/* ----- BASE64 ---------------------------------------------------- */
/* NULL out '\r' and '\n' chars */
while (Ustrrchr(p,'\r') != NULL) {
};
};
*p = 255;
-
+
/* line is translated, start bit shifting */
p = buffer;
- *num_decoded = 0;
+ *num_decoded = 0;
while(*p != 255) {
uschar tmp_c;
-
+
/* byte 0 ---------------------- */
if (*(p+1) == 255) {
mime_set_anomaly(MIME_ANOMALY_BROKEN_BASE64);
}
data[(*num_decoded)] = *p;
data[(*num_decoded)] <<= 6;
- data[(*num_decoded)] |= *(p+1);
+ data[(*num_decoded)] |= *(p+1);
(*num_decoded)++;
p+=2;
-
+
};
return data;
/* ----------------------------------------------------------------- */
while (*p != 0) {
if (*p == '=') {
int decode_qp_result;
-
+
p = mime_decode_qp_char(p,&decode_qp_result);
-
+
if (decode_qp_result == -2) {
/* Error from decoder. p is unchanged. */
mime_set_anomaly(MIME_ANOMALY_BROKEN_QP);
FILE *mime_get_decode_file(uschar *pname, uschar *fname) {
FILE *f = NULL;
uschar *filename;
-
+
filename = (uschar *)malloc(2048);
-
+
if ((pname != NULL) && (fname != NULL)) {
snprintf(CS filename, 2048, "%s/%s", pname, fname);
f = fopen(CS filename,"w+");
while(result != -1);
f = fopen(CS filename,"w+");
};
-
+
/* set expansion variable */
mime_decoded_filename = filename;
-
+
return f;
}
if (mime_stream == NULL)
return FAIL;
-
+
f_pos = ftell(mime_stream);
-
+
/* build default decode path (will exist since MBOX must be spooled up) */
snprintf(CS decode_path,1024,"%s/scan/%s",spool_directory,message_id);
-
+
/* reserve a line buffer to work in */
buffer = (uschar *)malloc(MIME_MAX_LINE_LENGTH+1);
if (buffer == NULL) {
"decode ACL condition: can't allocate %d bytes of memory.", MIME_MAX_LINE_LENGTH+1);
return DEFER;
};
-
+
/* try to find 1st option */
if ((option = string_nextinlist(&list, &sep,
option_buffer,
sizeof(option_buffer))) != NULL) {
-
+
/* parse 1st option */
if ( (Ustrcmp(option,"false") == 0) || (Ustrcmp(option,"0") == 0) ) {
/* explicitly no decoding */
return FAIL;
};
-
+
if (Ustrcmp(option,"default") == 0) {
/* explicit default path + file names */
goto DEFAULT_PATH;
};
-
+
if (option[0] == '/') {
struct stat statbuf;
memset(&statbuf,0,sizeof(statbuf));
-
+
/* assume either path or path+file name */
if ( (stat(CS option, &statbuf) == 0) && S_ISDIR(statbuf.st_mode) )
/* is directory, use it as decode_path */
else
/* no option? patch default path */
DEFAULT_PATH: decode_file = mime_get_decode_file(decode_path, NULL);
-
+
if (decode_file == NULL)
return DEFER;
-
+
/* read data linewise and dump it to the file,
while looking for the current boundary */
while(fgets(CS buffer, MIME_MAX_LINE_LENGTH, mime_stream) != NULL) {
uschar *decoded_line = NULL;
int decoded_line_length = 0;
-
+
if (mime_current_boundary != NULL) {
/* boundary line must start with 2 dashes */
if (Ustrncmp(buffer,"--",2) == 0) {
break;
};
};
-
+
decoded_line = mime_parse_line(buffer, mime_content_transfer_encoding, &decoded_line_length);
/* write line to decode file */
if (fwrite(decoded_line, 1, decoded_line_length, decode_file) < decoded_line_length) {
return DEFER;
};
size_counter += decoded_line_length;
-
- if (size_counter > 1023) {
+
+ if (size_counter > 1023) {
if ((mime_content_size + (size_counter / 1024)) < 65535)
mime_content_size += (size_counter / 1024);
- else
+ else
mime_content_size = 65535;
size_counter = (size_counter % 1024);
};
-
+
free(decoded_line);
}
-
+
fclose(decode_file);
-
+
clearerr(mime_stream);
fseek(mime_stream,f_pos,SEEK_SET);
-
+
/* round up remaining size bytes to one k */
if (size_counter) {
mime_content_size++;
};
-
+
return OK;
}
int header_value_mode = 0;
int header_open_brackets = 0;
int num_copied = 0;
-
+
while(!done) {
-
+
c = fgetc(f);
if (c == EOF) break;
-
+
/* always skip CRs */
if (c == '\r') continue;
-
+
if (c == '\n') {
if (num_copied > 0) {
/* look if next char is '\t' or ' ' */
c = ';';
done = 1;
};
-
+
/* skip control characters */
if (c < 32) continue;
/* skip leading whitespace */
if ( ((c == '\t') || (c == ' ')) && (header_value_mode == 1) )
continue;
-
+
/* we have hit a non-whitespace char, start copying value data */
header_value_mode = 2;
-
+
/* skip quotes */
if (c == '"') continue;
-
+
/* leave value mode on ';' */
if (c == ';') {
header_value_mode = 0;
/* enter value mode */
header_value_mode = 1;
};
-
+
/* skip chars while we are in a comment */
if (header_open_brackets > 0)
continue;
/* -------------------------------- */
};
-
+
/* copy the char to the buffer */
header[num_copied] = (uschar)c;
/* raise counter */
num_copied++;
-
+
/* break if header buffer is full */
if (num_copied > MIME_MAX_HEADER_SIZE-1) {
done = 1;
/* 0-terminate */
header[num_copied] = '\0';
-
+
/* return 0 for EOF or empty line */
if ((c == EOF) || (num_copied == 1))
return 0;
}
-int mime_acl_check(FILE *f, struct mime_boundary_context *context, uschar
+int mime_acl_check(FILE *f, struct mime_boundary_context *context, uschar
**user_msgptr, uschar **log_msgptr) {
int rc = OK;
uschar *header = NULL;
/* loop through parts */
while(1) {
-
+
/* reset all per-part mime variables */
mime_anomaly_level = 0;
mime_anomaly_text = NULL;
mime_content_type = NULL;
mime_is_multipart = 0;
mime_content_size = 0;
-
+
/*
If boundary is null, we assume that *f is positioned on the start of headers (for example,
at the very beginning of a message.
If a boundary is given, we must first advance to it to reach the start of the next header
block.
*/
-
+
/* NOTE -- there's an error here -- RFC2046 specifically says to
* check for outer boundaries. This code doesn't do that, and
* I haven't fixed this.
*
- * (I have moved partway towards adding support, however, by adding
+ * (I have moved partway towards adding support, however, by adding
* a "parent" field to my new boundary-context structure.)
*/
if (context != NULL) {
debug_printf("Hit EOF ...\n");
return rc;
};
-
+
DECODE_HEADERS:
/* parse headers, set up expansion variables */
while(mime_get_header(f,header)) {
for (i = 0; i < mime_header_list_size; i++) {
uschar *header_value = NULL;
int header_value_len = 0;
-
+
/* found an interesting header? */
if (strncmpic(mime_header_list[i].name,header,mime_header_list[i].namelen) == 0) {
uschar *p = header + mime_header_list[i].namelen;
Ustrncpy(header_value, p, header_value_len);
debug_printf("Found %s MIME header, value is '%s'\n", mime_header_list[i].name, header_value);
*((uschar **)(mime_header_list[i].value)) = header_value;
-
+
/* make p point to the next character after the closing ';' */
p += (header_value_len+1);
-
+
/* grab all param=value tags on the remaining line, check if they are interesting */
NEXT_PARAM_SEARCH: while (*p != 0) {
int j;
for (j = 0; j < mime_parameter_list_size; j++) {
uschar *param_value = NULL;
int param_value_len = 0;
-
+
/* found an interesting parameter? */
if (strncmpic(mime_parameter_list[j].name,p,mime_parameter_list[j].namelen) == 0) {
uschar *q = p + mime_parameter_list[j].namelen;
};
};
};
-
+
/* set additional flag variables (easier access) */
if ( (mime_content_type != NULL) &&
(Ustrncmp(mime_content_type,"multipart",9) == 0) )
mime_is_multipart = 1;
-
+
/* Make a copy of the boundary pointer.
Required since mime_boundary is global
and can be overwritten further down in recursion */
nested_context.boundary = mime_boundary;
-
+
/* raise global counter */
mime_part_count++;
-
+
/* copy current file handle to global variable */
mime_stream = f;
mime_current_boundary = context ? context->boundary : 0;
/* Note the context */
mime_is_coverletter = !(context && context->context == MBC_ATTACHMENT);
-
+
/* call ACL handling function */
rc = acl_check(ACL_WHERE_MIME, NULL, acl_smtp_mime, user_msgptr, log_msgptr);
-
+
mime_stream = NULL;
mime_current_boundary = NULL;
-
+
if (rc != OK) break;
-
+
/* If we have a multipart entity and a boundary, go recursive */
if ( (mime_content_type != NULL) &&
(nested_context.boundary != NULL) &&
uschar filename[2048];
int file_nr = 0;
int result = 0;
-
+
/* must find first free sequential filename */
do {
struct stat mystat;
result = stat(CS filename,&mystat);
}
while(result != -1);
-
+
rfc822name = filename;
-
+
/* decode RFC822 attachment */
mime_decoded_filename = NULL;
mime_stream = f;
};
mime_decoded_filename = NULL;
};
-
+
NO_RFC822:
/* If the boundary of this instance is NULL, we are finished here */
if (context == NULL) break;
if (context->context == MBC_COVERLETTER_ONESHOT)
context->context = MBC_ATTACHMENT;
-
+
};
return rc;
-/* $Cambridge: exim/src/src/mime.h,v 1.2 2004/12/16 15:11:47 tom Exp $ */
+/* $Cambridge: exim/src/src/mime.h,v 1.3 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
/* BASE64 decoder matrix */
static unsigned char mime_b64[256]={
/* 0 */ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
-/* 16 */ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+/* 16 */ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
/* 32 */ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
/* 48 */ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 255, 128, 128,
/* 64 */ 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
/* 192 */ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
/* 208 */ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
/* 224 */ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
-/* 240 */ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128
+/* 240 */ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128
};
#endif
-/* $Cambridge: exim/src/src/parse.c,v 1.3 2005/01/04 10:00:42 ph10 Exp $ */
+/* $Cambridge: exim/src/src/parse.c,v 1.4 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
original string, unmodified. If a quoted string is too long for the buffer, it
is truncated. (This shouldn't happen: this is normally handling short strings.)
-Hmmph. As always, things get perverted for other uses. This function was
-originally for the "phrase" part of addresses. Now it is being used for much
-longer texts in ACLs and via the ${rfc2047: expansion item. This means we have
+Hmmph. As always, things get perverted for other uses. This function was
+originally for the "phrase" part of addresses. Now it is being used for much
+longer texts in ACLs and via the ${rfc2047: expansion item. This means we have
to check for overlong "encoded-word"s and split them. November 2004.
Arguments:
{
int ch = *s++;
if (t > buffer + buffer_size - hlen - 8) break;
-
+
if (t - p > 70)
{
*t++ = '?';
p = t;
Ustrncpy(p, buffer, hlen);
t += hlen;
- }
-
+ }
+
if (ch < 33 || ch > 126 ||
Ustrchr("?=()<>@,;:\\\".[]_", ch) != NULL)
{
}
else *t++ = ch;
}
-
+
*t++ = '?';
-*t++ = '=';
+*t++ = '=';
*t = 0;
-
+
return coded? buffer : string;
}
-/* $Cambridge: exim/src/src/perl.c,v 1.3 2005/01/27 15:00:39 ph10 Exp $ */
+/* $Cambridge: exim/src/src/perl.c,v 1.4 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
/*********************************************************************/
/* These lines by PH added to make "warn" output go to the Exim log; I
hope this doesn't break anything. */
-
+
sv = newSVpv(
"$SIG{__WARN__} = sub { my($s) = $_[0];"
- "$s =~ s/\\n$//;"
+ "$s =~ s/\\n$//;"
"Exim::log_write($s) };", 0);
PUSHMARK(SP);
perl_eval_sv(sv, G_SCALAR|G_DISCARD|G_KEEPERR);
SvREFCNT_dec(sv);
if (SvTRUE(ERRSV)) return US SvPV(ERRSV, len);
/*********************************************************************/
-
+
sv = newSVpv(CS startup_code, 0);
PUSHMARK(SP);
perl_eval_sv(sv, G_SCALAR|G_DISCARD|G_KEEPERR);
yield = string_cat(yield, sizep, ptrp, str, (int)len);
FREETMPS;
LEAVE;
-
+
setlocale(LC_ALL, "C"); /* In case it got changed */
return yield;
}
-/* $Cambridge: exim/src/src/queue.c,v 1.4 2005/01/04 10:00:42 ph10 Exp $ */
+/* $Cambridge: exim/src/src/queue.c,v 1.5 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
if (deliver_datafile >= 0) printf("has been removed\n");
else printf("has been removed or did not exist\n");
- if (removed)
+ if (removed)
{
log_write(0, LOG_MAIN, "removed by %s", username);
- log_write(0, LOG_MAIN, "Completed");
- }
+ log_write(0, LOG_MAIN, "Completed");
+ }
break;
-/* $Cambridge: exim/src/src/rda.c,v 1.3 2005/01/04 10:00:42 ph10 Exp $ */
+/* $Cambridge: exim/src/src/rda.c,v 1.4 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
(*filtertype == FILTER_EXIM)? "an Exim" : "a Sieve");
/* RDO_FILTER is an "allow" bit */
-
+
if ((options & RDO_FILTER) == 0)
{
*error = US"filtering not enabled";
expand_forbid =
(expand_forbid & ~RDO_FILTER_EXPANSIONS) |
(options & RDO_FILTER_EXPANSIONS);
-
+
/* RDO_{EXIM,SIEVE}_FILTER are forbid bits */
-
+
if (*filtertype == FILTER_EXIM)
{
if ((options & RDO_EXIM_FILTER) != 0)
{
*error = US"Exim filtering not enabled";
return FF_ERROR;
- }
+ }
frc = filter_interpret(data, options, generated, error);
- }
+ }
else
{
if ((options & RDO_SIEVE_FILTER) != 0)
*error = US"Sieve filtering not enabled";
return FF_ERROR;
}
- frc = sieve_interpret(data, options, sieve_vacation_directory, generated,
+ frc = sieve_interpret(data, options, sieve_vacation_directory, generated,
error);
- }
+ }
expand_forbid = old_expand_forbid;
return frc;
-/* $Cambridge: exim/src/src/readconf.c,v 1.4 2005/01/04 10:00:42 ph10 Exp $ */
+/* $Cambridge: exim/src/src/readconf.c,v 1.5 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
(statbuf.st_gid != exim_gid /* group not exim & */
#ifdef CONFIGURE_GROUP
&& statbuf.st_gid != config_gid /* group not the special one */
- #endif
+ #endif
&& (statbuf.st_mode & 020) != 0) || /* group writeable */
/* or */
((statbuf.st_mode & 2) != 0)) /* world writeable */
-/* $Cambridge: exim/src/src/receive.c,v 1.10 2005/01/27 15:57:51 ph10 Exp $ */
+/* $Cambridge: exim/src/src/receive.c,v 1.11 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
* Read space info for a partition *
*************************************************/
-/* This function is called by receive_check_fs() below, and also by string
-expansion for variables such as $spool_space. The field names for the statvfs
+/* This function is called by receive_check_fs() below, and also by string
+expansion for variables such as $spool_space. The field names for the statvfs
structure are macros, because not all OS have F_FAVAIL and it seems tidier to
have macros for F_BAVAIL and F_FILES as well. Some kinds of file system do not
have inodes, and they return -1 for the number available.
Later: It turns out that some file systems that do not have the concept of
inodes return 0 rather than -1. Such systems should also return 0 for the total
-number of inodes, so we require that to be greater than zero before returning
+number of inodes, so we require that to be greater than zero before returning
an inode count.
Arguments:
isspool TRUE for spool partition, FALSE for log partition
inodeptr address of int to receive inode count; -1 if there isn't one
-
+
Returns: available on-root space, in kilobytes
- -1 for log partition if there isn't one
-
-All values are -1 if the STATFS functions are not available.
+ -1 for log partition if there isn't one
+
+All values are -1 if the STATFS functions are not available.
*/
-int
+int
receive_statvfs(BOOL isspool, int *inodeptr)
{
#ifdef HAVE_STATFS
if (isspool)
{
- path = spool_directory;
- name = US"spool";
- }
-
+ path = spool_directory;
+ name = US"spool";
+ }
+
/* Need to cut down the log file path to the directory, and to ignore any
appearance of "syslog" in it. */
{
int sep = ':'; /* Not variable - outside scripts use */
uschar *p = log_file_path;
- name = US"log";
+ name = US"log";
/* An empty log_file_path means "use the default". This is the same as an
empty item in a list. */
if (path == NULL) /* No log files */
{
- *inodeptr = -1;
- return -1;
- }
+ *inodeptr = -1;
+ return -1;
+ }
- /* An empty string means use the default, which is in the spool directory.
- But don't just use the spool directory, as it is possible that the log
+ /* An empty string means use the default, which is in the spool directory.
+ But don't just use the spool directory, as it is possible that the log
subdirectory has been symbolically linked elsewhere. */
- if (path[0] == 0)
+ if (path[0] == 0)
{
sprintf(CS buffer, CS"%s/log", CS spool_directory);
path = buffer;
- }
- else
+ }
+ else
{
- uschar *cp;
+ uschar *cp;
if ((cp = Ustrrchr(path, '/')) != NULL) *cp = 0;
- }
+ }
}
-
+
/* We now have the patch; do the business */
memset(&statbuf, 0, sizeof(statbuf));
smtp_closedown(US"spool or log directory problem");
exim_exit(EXIT_FAILURE);
}
-
+
*inodeptr = (statbuf.F_FILES > 0)? statbuf.F_FAVAIL : -1;
/* Disks are getting huge. Take care with computing the size in kilobytes. */
-
+
return (int)(((double)statbuf.F_BAVAIL * (double)statbuf.F_FRSIZE)/1024.0);
/* Unable to find partition sizes in this environment. */
if (check_spool_space > 0 || msg_size > 0 || check_spool_inodes > 0)
{
- space = receive_statvfs(TRUE, &inodes);
-
+ space = receive_statvfs(TRUE, &inodes);
+
DEBUG(D_receive)
debug_printf("spool directory space = %dK inodes = %d "
"check_space = %dK inodes = %d msg_size = %d\n",
space, inodes, check_spool_space, check_spool_inodes, msg_size);
-
- if ((space >= 0 && space < check_spool_space) ||
+
+ if ((space >= 0 && space < check_spool_space) ||
(inodes >= 0 && inodes < check_spool_inodes))
- {
+ {
log_write(0, LOG_MAIN, "spool directory space check failed: space=%d "
"inodes=%d", space, inodes);
return FALSE;
if (check_log_space > 0 || check_log_inodes > 0)
{
- space = receive_statvfs(FALSE, &inodes);
-
+ space = receive_statvfs(FALSE, &inodes);
+
DEBUG(D_receive)
debug_printf("log directory space = %dK inodes = %d "
"check_space = %dK inodes = %d\n",
space, inodes, check_log_space, check_log_inodes);
-
- if ((space >= 0 && space < check_log_space) ||
+
+ if ((space >= 0 && space < check_log_space) ||
(inodes >= 0 && inodes < check_log_inodes))
- {
+ {
log_write(0, LOG_MAIN, "log directory space check failed: space=%d "
"inodes=%d", space, inodes);
return FALSE;
}
- }
-
+ }
+
return TRUE;
}
of all headers. Our current header must follow it. */
h->next = last_received->next;
last_received->next = h;
- DEBUG(D_receive|D_acl) debug_printf(" (before any non-Received: or Resent-*: header)");
+ DEBUG(D_receive|D_acl) debug_printf(" (before any non-Received: or Resent-*: header)");
break;
default:
header_line *my_headerlist;
uschar *user_msg, *log_msg;
int mime_part_count_buffer = -1;
-
+
memset(CS rfc822_file_path,0,2048);
-
+
/* check if it is a MIME message */
my_headerlist = header_list;
while (my_headerlist != NULL) {
};
my_headerlist = my_headerlist->next;
};
-
+
DEBUG(D_receive) debug_printf("No Content-Type: header - presumably not a MIME message.\n");
goto NO_MIME_ACL;
-
+
DO_MIME_ACL:
/* make sure the eml mbox file is spooled up */
mbox_file = spool_mbox(&mbox_size);
log_write(0, LOG_MAIN|LOG_PANIC,
"acl_smtp_mime: error while creating mbox spool file, message temporarily rejected.");
Uunlink(spool_name);
- unspool_mbox();
+ unspool_mbox();
smtp_respond(451, TRUE, US"temporary local problem");
message_id[0] = 0; /* Indicate no message accepted */
smtp_reply = US""; /* Indicate reply already sent */
goto TIDYUP; /* Skip to end of function */
};
-
+
mime_is_rfc822 = 0;
MIME_ACL_CHECK:
mime_part_count = -1;
rc = mime_acl_check(mbox_file, NULL, &user_msg, &log_msg);
fclose(mbox_file);
-
+
if (Ustrlen(rfc822_file_path) > 0) {
mime_part_count = mime_part_count_buffer;
-
+
if (unlink(CS rfc822_file_path) == -1) {
log_write(0, LOG_PANIC,
"acl_smtp_mime: can't unlink RFC822 spool file, skipping.");
goto END_MIME_ACL;
};
};
-
+
/* check if we must check any message/rfc822 attachments */
if (rc == OK) {
uschar temp_path[1024];
int n;
struct dirent *entry;
DIR *tempdir;
-
+
snprintf(CS temp_path, 1024, "%s/scan/%s", spool_directory, message_id);
tempdir = opendir(CS temp_path);
snprintf(CS rfc822_file_path, 2048,"%s/scan/%s/%s", spool_directory, message_id, entry->d_name);
debug_printf("RFC822 attachment detected: running MIME ACL for '%s'\n", rfc822_file_path);
break;
- };
+ };
} while (1);
closedir(tempdir);
-
+
if (entry != NULL) {
mbox_file = Ufopen(rfc822_file_path,"r");
if (mbox_file == NULL) {
goto MIME_ACL_CHECK;
};
};
-
+
END_MIME_ACL:
add_acl_headers(US"MIME");
- if (rc == DISCARD)
+ if (rc == DISCARD)
{
recipients_count = 0;
blackholed_by = US"MIME ACL";
smtp_reply = US""; /* Indicate reply already sent */
message_id[0] = 0; /* Indicate no message accepted */
goto TIDYUP; /* Skip to end of function */
- };
+ };
}
-
- NO_MIME_ACL:
+
+ NO_MIME_ACL:
#endif /* WITH_CONTENT_SCAN */
{
recipients_count = 0;
blackholed_by = US"DATA ACL";
- if (log_msg != NULL)
- blackhole_log_msg = string_sprintf(": %s", log_msg);
+ if (log_msg != NULL)
+ blackhole_log_msg = string_sprintf(": %s", log_msg);
}
else if (rc != OK)
{
{
recipients_count = 0;
blackholed_by = US"non-SMTP ACL";
- if (log_msg != NULL) blackhole_log_msg = string_sprintf(": %s", log_msg);
+ if (log_msg != NULL) blackhole_log_msg = string_sprintf(": %s", log_msg);
}
else if (rc != OK)
{
Uunlink(spool_name);
log_write(0, LOG_MAIN|LOG_REJECT, "F=<%s> rejected by non-SMTP ACL: %s",
sender_address, log_msg);
- if (user_msg == NULL) user_msg = US"local configuration problem";
+ if (user_msg == NULL) user_msg = US"local configuration problem";
if (smtp_batched_input)
{
moan_smtp_batch(NULL, "%d %s", 550, user_msg);
{
if (fake_reject)
smtp_respond(550,TRUE,fake_reject_text);
- else
- smtp_printf("250 OK id=%s\r\n", message_id);
+ else
+ smtp_printf("250 OK id=%s\r\n", message_id);
if (host_checking)
fprintf(stdout,
"\n**** SMTP testing: that is not a real message id!\n\n");
{
if (fake_reject && (smtp_reply[0] == '2'))
smtp_respond(550,TRUE,fake_reject_text);
- else
+ else
smtp_printf("%.1024s\r\n", smtp_reply);
}
}
-/* $Cambridge: exim/src/src/regex.c,v 1.3 2004/12/17 14:52:44 ph10 Exp $ */
+/* $Cambridge: exim/src/src/regex.c,v 1.4 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
int pcre_erroffset;
uschar *linebuffer;
long f_pos = 0;
-
+
/* reset expansion variable */
regex_match_string = NULL;
-
+
if (mime_stream == NULL) {
/* We are in the DATA ACL */
mbox_file = spool_mbox(&mbox_size);
f_pos = ftell(mime_stream);
mbox_file = mime_stream;
};
-
+
/* precompile our regexes */
while ((regex_string = string_nextinlist(&list, &sep,
regex_string_buffer,
sizeof(regex_string_buffer))) != NULL) {
-
+
/* parse option */
- if ( (strcmpic(regex_string,US"false") == 0) ||
+ if ( (strcmpic(regex_string,US"false") == 0) ||
(Ustrcmp(regex_string,"0") == 0) ) {
/* explicitly no matching */
continue;
};
-
+
/* compile our regular expression */
re = pcre_compile( CS regex_string,
0,
re_list_head = re_list_item;
};
};
-
+
/* no regexes -> nothing to do */
if (re_list_head == NULL) {
return FAIL;
};
-
+
/* match each line against all regexes */
linebuffer = store_get(32767);
- while (fgets(CS linebuffer, 32767, mbox_file) != NULL) {
+ while (fgets(CS linebuffer, 32767, mbox_file) != NULL) {
if ( (mime_stream != NULL) && (mime_current_boundary != NULL) ) {
/* check boundary */
if (Ustrncmp(linebuffer,"--",2) == 0) {
re_list_item = re_list_item->next;
} while (re_list_item != NULL);
};
-
+
if (mime_stream == NULL)
fclose(mbox_file);
else {
clearerr(mime_stream);
fseek(mime_stream,f_pos,SEEK_SET);
};
-
+
/* no matches ... */
return FAIL;
}
while ((regex_string = string_nextinlist(&list, &sep,
regex_string_buffer,
sizeof(regex_string_buffer))) != NULL) {
-
+
/* parse option */
- if ( (strcmpic(regex_string,US"false") == 0) ||
+ if ( (strcmpic(regex_string,US"false") == 0) ||
(Ustrcmp(regex_string,"0") == 0) ) {
/* explicitly no matching */
continue;
};
-
+
/* compile our regular expression */
re = pcre_compile( CS regex_string,
0,
re_list_head = re_list_item;
};
};
-
+
/* no regexes -> nothing to do */
if (re_list_head == NULL) {
return FAIL;
};
-
+
/* check if the file is already decoded */
if (mime_decoded_filename == NULL) {
uschar *empty = US"";
"mime_regex acl condition warning - can't open '%s' for reading.", mime_decoded_filename);
return DEFER;
};
-
+
/* get 32k memory */
mime_subject = (uschar *)store_get(32767);
-
+
/* read max 32k chars from file */
mime_subject_len = fread(mime_subject, 1, 32766, f);
-
+
re_list_item = re_list_head;
do {
/* try matcher on the mmapped file */
} while (re_list_item != NULL);
fclose(f);
-
+
/* no matches ... */
return FAIL;
}
-/* $Cambridge: exim/src/src/routers/redirect.c,v 1.4 2005/01/04 10:00:44 ph10 Exp $ */
+/* $Cambridge: exim/src/src/routers/redirect.c,v 1.5 2005/02/17 11:58:27 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
if(ob->srs != NULL)
{
BOOL usesrs = TRUE;
-
+
if(ob->srs_condition != NULL)
usesrs = expand_check_condition(ob->srs_condition, "srs_condition expansion failed", NULL);
-
+
if(usesrs)
if(Ustrcmp(ob->srs, "reverse") == 0 || Ustrcmp(ob->srs, "reverseandforward") == 0)
{
uschar *res;
int n_srs;
-
+
srs_orig_recipient = addr->address;
eximsrs_init();
if(ob->srs_db)
if(ob->srs != NULL)
{
BOOL usesrs = TRUE;
-
+
if(ob->srs_condition != NULL)
usesrs = expand_check_condition(ob->srs_condition, "srs_condition expansion failed", NULL);
-
+
if(usesrs)
if((Ustrcmp(ob->srs, "forward") == 0 || Ustrcmp(ob->srs, "reverseandforward") == 0) && !verify)
{
uschar *res;
uschar *usedomain;
int n_srs;
-
+
srs_orig_sender = sender_address;
eximsrs_init();
if(ob->srs_db)
if(ob->srs_alias != NULL ? (usedomain = expand_string(ob->srs_alias)) == NULL : 1)
usedomain = deliver_domain;
-
+
if((n_srs = eximsrs_forward(&res, sender_address, usedomain)) != OK)
return n_srs;
sender_address = res;
-/* $Cambridge: exim/src/src/sieve.c,v 1.6 2005/02/17 09:49:08 ph10 Exp $ */
+/* $Cambridge: exim/src/src/sieve.c,v 1.7 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
}
else
{
- filter->errmsg=CUS "expecting command or closing brace";
+ filter->errmsg=CUS "expecting command or closing brace";
return -1;
}
}
int m;
unsigned long days;
- struct String *addresses=(struct String*)0;
+ struct String *addresses;
struct String subject;
int reason_is_mime;
string_item *aliases;
filter->vacation_ran=1;
}
days=VACATION_MIN_DAYS>7 ? VACATION_MIN_DAYS : 7;
+ addresses=(struct String*)0;
subject.character=(uschar*)0;
subject.length=-1;
aliases=NULL;
uschar *buffer;
int buffer_capacity;
struct String key;
+ struct String *a;
md5 base;
uschar digest[16];
uschar hexdigest[33];
if (subject.length!=-1) key.character=string_cat(key.character,&capacity,&key.length,subject.character,subject.length);
key.character=string_cat(key.character,&capacity,&key.length,reason_is_mime?US"1":US"0",1);
key.character=string_cat(key.character,&capacity,&key.length,reason.character,reason.length);
+ if (addresses!=(struct String*)0) for (a=addresses; a->length!=-1; ++a)
+ {
+ key.character=string_cat(key.character,&capacity,&key.length,US":",1);
+ key.character=string_cat(key.character,&capacity,&key.length,a->character,a->length);
+ }
md5_start(&base);
md5_end(&base, key.character, key.length, digest);
for (i = 0; i < 16; i++) sprintf(CS (hexdigest+2*i), "%02X", digest[i]);
addr->reply = store_get(sizeof(reply_item));
memset(addr->reply,0,sizeof(reply_item)); /* XXX */
addr->reply->to = string_copy(sender_address);
- addr->reply->from = expand_string(US"$local_part@$domain");
+ addr->reply->from = expand_string(US"$local_part@$domain");
/* Allocation is larger than neccessary, but enough even for split MIME words */
buffer_capacity=16+4*subject.length;
buffer=store_get(buffer_capacity);
-/* $Cambridge: exim/src/src/smtp_in.c,v 1.10 2005/01/13 16:22:42 ph10 Exp $ */
+/* $Cambridge: exim/src/src/smtp_in.c,v 1.11 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
#ifdef EXPERIMENTAL_SPF
spf_header_comment = NULL;
spf_received = NULL;
-spf_result = NULL;
+spf_result = NULL;
spf_smtp_comment = NULL;
#endif
body_linecount = body_zerocount = 0;
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
+/* 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 &&
+if (running_in_test_harness &&
sender_host_address != NULL &&
Ustrcmp(sender_host_address, "127.0.0.2") == 0)
sleep(1);
{
int rc = read(fileno(smtp_in), smtp_inbuffer, in_buffer_size);
if (rc > 150) rc = 150;
- smtp_inbuffer[rc] = 0;
+ smtp_inbuffer[rc] = 0;
log_write(0, LOG_MAIN|LOG_REJECT, "SMTP protocol violation: "
"synchronization error (input sent without waiting for greeting): "
"rejected connection from %s input=\"%s\"", host_and_ident(TRUE),
uschar *what = (where == ACL_WHERE_PREDATA)? US"DATA" :
#ifdef WITH_CONTENT_SCAN
(where == ACL_WHERE_MIME)? US"during MIME ACL checks" :
-#endif
+#endif
(where == ACL_WHERE_DATA)? US"after DATA" :
string_sprintf("%s %s", acl_wherenames[where], smtp_data);
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;
}
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,
+ 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 */
-/* $Cambridge: exim/src/src/smtp_out.c,v 1.3 2005/01/04 10:00:42 ph10 Exp $ */
+/* $Cambridge: exim/src/src/smtp_out.c,v 1.4 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
if (save_errno != 0)
{
- HDEBUG(D_transport|D_acl|D_v)
+ HDEBUG(D_transport|D_acl|D_v)
{
debug_printf("failed: %s", CUstrerror(save_errno));
- if (save_errno == ETIMEDOUT)
+ if (save_errno == ETIMEDOUT)
debug_printf(" (timeout=%s)", readconf_printtime(timeout));
- debug_printf("\n");
- }
+ debug_printf("\n");
+ }
close(sock);
errno = save_errno;
return -1;
-/* $Cambridge: exim/src/src/spam.c,v 1.3 2004/12/17 14:52:44 ph10 Exp $ */
+/* $Cambridge: exim/src/src/spam.c,v 1.4 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
override = 1;
};
- /* if we scanned for this username last time, just return */
+ /* if we scanned for this username last time, just return */
if ( spam_ok && ( Ustrcmp(prev_user_name, user_name) == 0 ) ) {
if (override)
return OK;
else
return spam_rc;
};
-
+
/* make sure the eml mbox file is spooled up */
mbox_file = spool_mbox(&mbox_size);
-
+
if (mbox_file == NULL) {
/* error while spooling */
log_write(0, LOG_MAIN|LOG_PANIC,
while ((address = string_nextinlist(&spamd_address_list_ptr, &sep,
address_buffer,
sizeof(address_buffer))) != NULL) {
-
+
spamd_address_container *this_spamd =
(spamd_address_container *)store_get(sizeof(spamd_address_container));
-
+
/* grok spamd address and port */
if( sscanf(CS address, "%s %u", this_spamd->tcp_addr, &(this_spamd->tcp_port)) != 2 ) {
log_write(0, LOG_MAIN,
"spam acl condition: warning - invalid spamd address: '%s'", address);
continue;
};
-
+
spamd_address_vector[num_servers] = this_spamd;
num_servers++;
if (num_servers > 31)
break;
};
-
+
/* check if we have at least one server */
if (!num_servers) {
log_write(0, LOG_MAIN|LOG_PANIC,
current_server = start_server = (int)now % num_servers;
while (1) {
-
+
debug_printf("trying server %s, port %u\n",
spamd_address_vector[current_server]->tcp_addr,
spamd_address_vector[current_server]->tcp_port);
-
+
/* contact a spamd */
if ( (spamd_sock = ip_socket(SOCK_STREAM, AF_INET)) < 0) {
log_write(0, LOG_MAIN|LOG_PANIC,
"spam acl condition: error creating IP socket for spamd");
fclose(mbox_file);
- return DEFER;
+ return DEFER;
};
-
+
if (ip_connect( spamd_sock,
AF_INET,
spamd_address_vector[current_server]->tcp_addr,
/* connection OK */
break;
};
-
+
log_write(0, LOG_MAIN|LOG_PANIC,
"spam acl condition: warning - spamd connection to %s, port %u failed: %s",
spamd_address_vector[current_server]->tcp_addr,
/* we're done sending, close socket for writing */
shutdown(spamd_sock,SHUT_WR);
-
+
/* read spamd response */
memset(spamd_buffer, 0, sizeof(spamd_buffer));
offset = 0;
/* dig in the spamd output and put the report in a multiline header, if requested */
if( sscanf(CS spamd_buffer,"SPAMD/%s 0 EX_OK\r\nContent-length: %*u\r\n\r\n%lf/%lf\r\n%n",
spamd_version,&spamd_score,&spamd_threshold,&spamd_report_offset) != 3 ) {
-
+
/* try to fall back to pre-2.50 spamd output */
if( sscanf(CS spamd_buffer,"SPAMD/%s 0 EX_OK\r\nSpam: %*s ; %lf / %lf\r\n\r\n%n",
spamd_version,&spamd_score,&spamd_threshold,&spamd_report_offset) != 3 ) {
/* not spam */
spam_rc = FAIL;
};
-
+
/* remember user name and "been here" for it */
Ustrcpy(prev_user_name, user_name);
spam_ok = 1;
-
+
if (override) {
/* always return OK, no matter what the score */
return OK;
-/* $Cambridge: exim/src/src/spf.c,v 1.2 2004/12/16 15:11:47 tom Exp $ */
+/* $Cambridge: exim/src/src/spf.c,v 1.3 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
-
+
/* Experimental SPF support.
Copyright (c) Tom Kistner <tom@duncanthrax.net> 2004
License: GPL */
-
+
/* Code for calling spf checks via libspf-alt. Called from acl.c. */
#include "exim.h"
/* spf_init sets up a context that can be re-used for several
messages on the same SMTP connection (that come from the
same host with the same HELO string) */
-
+
int spf_init(uschar *spf_helo_domain, uschar *spf_remote_addr) {
uschar *p;
-
+
/* paranoia */
spfcid = NULL;
spfdcid_resolv = NULL;
spfdcid = NULL;
-
+
spfcid = SPF_create_config();
if ( spfcid == NULL ) {
debug_printf("spf: SPF_create_config() failed.\n");
spfdcid_resolv = NULL;
return 0;
}
-
+
return 1;
}
uschar spf_result_id_buffer[128];
SPF_output_t spf_output;
int rc = SPF_RESULT_ERROR;
-
+
if (!(spfcid && spfdcid)) {
/* no global context, assume temp error and skip to evaluation */
rc = SPF_RESULT_ERROR;
/* Invalid sender address. This should be a real rare occurence */
rc = SPF_RESULT_ERROR;
goto SPF_EVALUATE;
- }
+ }
/* get SPF result */
spf_output = SPF_result(spfcid, spfdcid);
-/* $Cambridge: exim/src/src/spf.h,v 1.2 2004/12/16 15:11:47 tom Exp $ */
+/* $Cambridge: exim/src/src/spf.h,v 1.3 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
-
+
/* Experimental SPF support.
Copyright (c) Tom Kistner <tom@duncanthrax.net> 2004
License: GPL */
-/* $Cambridge: exim/src/src/spool_in.c,v 1.7 2005/02/16 16:28:36 ph10 Exp $ */
+/* $Cambridge: exim/src/src/spool_in.c,v 1.8 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
uid = Uatoi(p);
if (p <= big_buffer || *(--p) != ' ') goto SPOOL_FORMAT_ERROR;
*p = 0;
-
+
originator_login = string_copy(big_buffer);
originator_uid = (uid_t)uid;
originator_gid = (gid_t)gid;
local_error_message = TRUE;
else if (Ustrncmp(big_buffer, "-local_scan ", 12) == 0)
local_scan_data = string_copy(big_buffer + 12);
-#ifdef WITH_CONTENT_SCAN
+#ifdef WITH_CONTENT_SCAN
else if (Ustrncmp(big_buffer, "-spam_score_int ", 16) == 0)
- spam_score_int = string_copy(big_buffer + 16);
+ spam_score_int = string_copy(big_buffer + 16);
#endif
#ifdef EXPERIMENTAL_BRIGHTMAIL
else if (Ustrncmp(big_buffer, "-bmi_verdicts ", 14) == 0)
}
else if (Ustrncmp(big_buffer, "-active_hostname", 16) == 0)
- smtp_active_hostname = string_copy(big_buffer + 17);
+ smtp_active_hostname = string_copy(big_buffer + 17);
else if (Ustrncmp(big_buffer, "-host_auth", 10) == 0)
sender_host_authenticated = string_copy(big_buffer + 11);
else if (Ustrncmp(big_buffer, "-host_name", 10) == 0)
-/* $Cambridge: exim/src/src/spool_mbox.c,v 1.3 2004/12/17 14:52:44 ph10 Exp $ */
+/* $Cambridge: exim/src/src/spool_mbox.c,v 1.4 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
header_line *my_headerlist;
struct stat statbuf;
int i,j;
-
+
if (!spool_mbox_ok) {
/* create scan directory, if not present */
if (!directory_make(spool_directory, US "scan", 0750, FALSE)) {
debug_printf("unable to create directory: %s/scan\n", spool_directory);
return NULL;
};
-
+
/* create temp directory inside scan dir */
snprintf(CS mbox_path, 1024, "%s/scan/%s", spool_directory, message_id);
if (!directory_make(NULL, mbox_path, 0750, FALSE)) {
debug_printf("unable to create directory: %s/scan/%s\n", spool_directory, message_id);
return NULL;
};
-
+
/* open [message_id].eml file for writing */
snprintf(CS mbox_path, 1024, "%s/scan/%s/%s.eml", spool_directory, message_id, message_id);
mbox_file = Ufopen(mbox_path,"w");
-
+
if (mbox_file == NULL) {
debug_printf("unable to open file for writing: %s\n", mbox_path);
return NULL;
};
-
+
/* write all header lines to mbox file */
my_headerlist = header_list;
while (my_headerlist != NULL) {
-
+
/* skip deleted headers */
if (my_headerlist->type == '*') {
my_headerlist = my_headerlist->next;
continue;
};
-
+
i = fwrite(my_headerlist->text, 1, my_headerlist->slen, mbox_file);
if (i != my_headerlist->slen) {
debug_printf("error/short write on writing in: %s", mbox_path);
fclose(mbox_file);
return NULL;
};
-
+
my_headerlist = my_headerlist->next;
};
-
+
/* copy body file */
message_subdir[1] = '\0';
for (i = 0; i < 2; i++) {
};
fread(data_buffer, 1, 18, data_file);
-
+
do {
j = fread(data_buffer, 1, sizeof(data_buffer), data_file);
if (j > 0) {
};
};
} while (j > 0);
-
+
fclose(data_file);
fclose(mbox_file);
Ustrcpy(spooled_message_id, message_id);
/* open [message_id].eml file for reading */
mbox_file = Ufopen(mbox_path,"r");
-
+
return mbox_file;
}
demime_reason = NULL;
file_extensions = NULL;
#endif
-
+
spam_ok = 0;
malware_ok = 0;
-
+
if (spool_mbox_ok) {
spool_mbox_ok = 0;
-
+
if (!no_mbox_unspool) {
uschar mbox_path[1024];
uschar file_path[1024];
int n;
struct dirent *entry;
DIR *tempdir;
-
+
snprintf(CS mbox_path, 1024, "%s/scan/%s", spool_directory, spooled_message_id);
-
+
tempdir = opendir(CS mbox_path);
/* loop thru dir & delete entries */
n = 0;
if ( (Ustrcmp(entry->d_name,"..") != 0) && (Ustrcmp(entry->d_name,".") != 0) ) {
debug_printf("unspool_mbox(): unlinking '%s'\n", file_path);
n = unlink(CS file_path);
- };
+ };
} while (n > -1);
-
+
closedir(tempdir);
-
+
/* remove directory */
n = rmdir(CS mbox_path);
};
-/* $Cambridge: exim/src/src/spool_out.c,v 1.5 2005/01/25 14:16:33 ph10 Exp $ */
+/* $Cambridge: exim/src/src/spool_out.c,v 1.6 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
if (interface_address != NULL)
fprintf(f, "-interface_address %s.%d\n", interface_address, interface_port);
-
+
if (smtp_active_hostname != primary_hostname)
- fprintf(f, "-active_hostname %s\n", smtp_active_hostname);
+ fprintf(f, "-active_hostname %s\n", smtp_active_hostname);
/* Likewise for any ident information; for local messages this is
likely to be the same as originator_login, but will be different if
-/* $Cambridge: exim/src/src/srs.c,v 1.3 2004/12/17 14:52:44 ph10 Exp $ */
+/* $Cambridge: exim/src/src/srs.c,v 1.4 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
/* srs_init just initialises libsrs and creates (if necessary)
an srs object to use for all srs calls in this instance */
-
+
int eximsrs_init()
{
int co;
char *sbufp;
int hashlen, maxage;
-
+
if(!srs)
{
/* Check config */
"SRS Configuration Error");
return DEFER;
}
-
+
/* Get config */
co = 0;
if((secret = string_nextinlist(&list, &co, secret_buf,
"SRS Configuration Error: No secret specified");
return DEFER;
}
-
+
if((sbufp = string_nextinlist(&list, &co, sbuf, sizeof(sbuf))) == NULL)
maxage = 31;
else
"SRS Configuration Error: Invalid hash length");
return DEFER;
}
-
-
+
+
if((srs = srs_open(secret, strnlen(secret, SRS_MAX_SECRET_LENGTH),
maxage, hashlen, hashlen)) == NULL)
{
if((sbufp = string_nextinlist(&list, &co, sbuf, sizeof(sbuf))) != NULL)
srs_set_option(srs, SRS_OPTION_USETIMESTAMP, atoi(sbuf));
-
+
if((sbufp = string_nextinlist(&list, &co, sbuf, sizeof(sbuf))) != NULL)
srs_set_option(srs, SRS_OPTION_USEHASH, atoi(sbuf));
{
if(srs)
srs_close(srs);
-
+
srs = NULL;
return OK;
srs_db_reverse = string_copy(srs_db);
else
srs_db_forward = string_copy(srs_db);
-
+
if(srs_set_db_functions(srs, eximsrs_db_insert, eximsrs_db_lookup) * SRS_RESULT_FAIL)
return DEFER;
-
+
return OK;
}
srs_db_address = string_copyn(data, data_len);
if(srs_generate_unique_id(srs, srs_db_address, buf, 64) & SRS_RESULT_FAIL)
return DEFER;
-
+
srs_db_key = string_copyn(buf, 16);
-
+
if((res = expand_string(srs_db_forward)) == NULL)
return SRS_RESULT_DBERROR;
-
+
if(result_len < 17)
return SRS_RESULT_DBERROR;
-
+
strncpy(result, srs_db_key, result_len);
return SRS_RESULT_OK;
srs_db_key = string_copyn(data, data_len);
if((res = expand_string(srs_db_reverse)) == NULL)
return SRS_RESULT_DBERROR;
-
+
if(Ustrlen(res) >= result_len)
return SRS_RESULT_ADDRESSTOOLONG;
-
+
strncpy(result, res, result_len);
return SRS_RESULT_OK;
-/* $Cambridge: exim/src/src/structs.h,v 1.3 2005/01/04 10:00:42 ph10 Exp $ */
+/* $Cambridge: exim/src/src/structs.h,v 1.4 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
uschar *address_data; /* Arbitrary data */
#ifdef EXPERIMENTAL_BRIGHTMAIL
uschar *bmi_rule; /* Brightmail AntiSpam rule checking */
-#endif
+#endif
uschar *cannot_route_message; /* Used when routing fails */
uschar *condition; /* General condition */
uschar *current_directory; /* For use during delivery */
-/* $Cambridge: exim/src/src/tls-gnu.c,v 1.4 2005/01/04 10:00:42 ph10 Exp $ */
+/* $Cambridge: exim/src/src/tls-gnu.c,v 1.5 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
cert_expanded, key_expanded);
rc = gnutls_certificate_set_x509_key_file(x509_cred, CS cert_expanded,
CS key_expanded, GNUTLS_X509_FMT_PEM);
- if (rc < 0)
+ if (rc < 0)
{
uschar *msg = string_sprintf("cert/key setup: cert=%s key=%s",
- cert_expanded, key_expanded);
+ cert_expanded, key_expanded);
return tls_error(msg, host, rc);
- }
+ }
}
/* A certificate is mandatory in a server, but not in a client */
-/* $Cambridge: exim/src/src/transport.c,v 1.3 2005/01/04 10:00:42 ph10 Exp $ */
+/* $Cambridge: exim/src/src/transport.c,v 1.4 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
}
/* Wait for the writing process to complete. If it ends successfully,
-read the results from its pipe, provided we haven't already had a filter
+read the results from its pipe, provided we haven't already had a filter
process failure. */
DEBUG(D_transport) debug_printf("waiting for writing process\n");
rc = child_close(write_pid, 30);
if (yield)
{
- if (rc == 0)
+ if (rc == 0)
{
BOOL ok;
read(pfd[pipe_read], (void *)&ok, sizeof(BOOL));
addr->more_errno = rc;
DEBUG(D_transport) debug_printf("writing process returned %d\n", rc);
}
- }
+ }
}
close(pfd[pipe_read]);
-/* $Cambridge: exim/src/src/transports/appendfile.c,v 1.4 2005/01/04 10:00:45 ph10 Exp $ */
+/* $Cambridge: exim/src/src/transports/appendfile.c,v 1.5 2005/02/17 11:58:27 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
from child_close() is in more_errno. */
else if (errno == ERRNO_FILTER_FAIL)
- {
+ {
yield = PANIC;
addr->message = string_sprintf("transport filter process failed (%d) "
"while writing to %s%s", addr->more_errno, dataname,
(addr->more_errno == EX_EXECFAILED)? ": unable to execute command" : "");
- }
+ }
/* Handle failure to expand header changes */
-/* $Cambridge: exim/src/src/transports/lmtp.c,v 1.3 2005/01/04 10:00:45 ph10 Exp $ */
+/* $Cambridge: exim/src/src/transports/lmtp.c,v 1.4 2005/02/17 11:58:27 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
if (*errno_value == ERRNO_FILTER_FAIL)
{
- *message = string_sprintf("transport filter process failed (%d)%s",
- more_errno,
+ *message = string_sprintf("transport filter process failed (%d)%s",
+ more_errno,
(more_errno == EX_EXECFAILED)? ": unable to execute command" : "");
return FALSE;
}
-/* $Cambridge: exim/src/src/transports/pipe.c,v 1.3 2005/01/04 10:00:45 ph10 Exp $ */
+/* $Cambridge: exim/src/src/transports/pipe.c,v 1.4 2005/02/17 11:58:27 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
}
else
{
- addr->transport_return = PANIC;
+ addr->transport_return = PANIC;
addr->basic_errno = errno;
if (errno == ERRNO_CHHEADER_FAIL)
addr->message =
-/* $Cambridge: exim/src/src/transports/smtp.c,v 1.5 2005/01/11 15:51:03 ph10 Exp $ */
+/* $Cambridge: exim/src/src/transports/smtp.c,v 1.6 2005/02/17 11:58:27 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
10*60, /* final timeout */
1024, /* size_addition */
5, /* hosts_max_try */
- 50, /* hosts_max_try_hardlimit */
+ 50, /* hosts_max_try_hardlimit */
FALSE, /* allow_localhost */
FALSE, /* gethostbyname */
TRUE, /* dns_qualify_single */
if (*errno_value == ERRNO_FILTER_FAIL)
{
*message = US string_sprintf("transport filter process failed (%d)%s",
- more_errno,
+ more_errno,
(more_errno == EX_EXECFAILED)? ": unable to execute command" : "");
return FALSE;
}
int hosts_retry = 0;
int hosts_serial = 0;
int hosts_total = 0;
-int total_hosts_tried = 0;
+int total_hosts_tried = 0;
address_item *addr;
BOOL expired = TRUE;
BOOL continuing = continue_hostname != NULL;
. If there are any addresses whose status is still DEFER, carry on to the
next host/IPaddress, unless we have tried the number of hosts given
by hosts_max_try or hosts_max_try_hardlimit; otherwise return. Note that
- there is some fancy logic for hosts_max_try that means its limit can be
- overstepped in some circumstances.
+ there is some fancy logic for hosts_max_try that means its limit can be
+ overstepped in some circumstances.
If we get to the end of the list, all hosts have deferred at least one address,
or not reached their retry times. If delay_after_cutoff is unset, it requests a
int unexpired_hosts_tried = 0;
for (host = hostlist;
- host != NULL &&
+ host != NULL &&
unexpired_hosts_tried < ob->hosts_max_try &&
total_hosts_tried < ob->hosts_max_try_hardlimit;
host = nexthost)
/* This is for real. If the host is expired, we don't count it for
hosts_max_retry. This ensures that all hosts must expire before an address
- is timed out, unless hosts_max_try_hardlimit (which protects against
+ is timed out, unless hosts_max_try_hardlimit (which protects against
lunatic DNS configurations) is reached.
-
+
If the host is not expired and we are about to hit the hosts_max_retry
limit, check to see if there is a subsequent hosts with a different MX
value. If so, make that the next host, and don't count this one. This is a
because of hosts_max_try or hosts_max_try_hardlimit. In the former case, this
means we need to behave as if some hosts were skipped because their retry
time had not come. Specifically, this prevents the address from timing out.
- However, if we have hit hosts_max_try_hardlimit, we want to behave as if all
+ However, if we have hit hosts_max_try_hardlimit, we want to behave as if all
hosts were tried. */
if (host != NULL)
"hosts were tried\n");
}
else
- {
+ {
DEBUG(D_transport)
debug_printf("hosts_max_try limit caused some hosts to be skipped\n");
setflag(addr, af_retry_skipped);
- }
+ }
}
if (queue_smtp) /* no deliveries attempted */
-/* $Cambridge: exim/src/src/transports/smtp.h,v 1.3 2005/01/04 16:36:28 ph10 Exp $ */
+/* $Cambridge: exim/src/src/transports/smtp.h,v 1.4 2005/02/17 11:58:27 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
int final_timeout;
int size_addition;
int hosts_max_try;
- int hosts_max_try_hardlimit;
+ int hosts_max_try_hardlimit;
BOOL allow_localhost;
BOOL gethostbyname;
BOOL dns_qualify_single;
-/* $Cambridge: exim/src/src/transports/tf_maildir.c,v 1.3 2005/01/04 10:00:45 ph10 Exp $ */
+/* $Cambridge: exim/src/src/transports/tf_maildir.c,v 1.4 2005/02/17 11:58:27 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
if (*endptr == 0)
{
- if (size < 0 || filecount < 0)
+ if (size < 0 || filecount < 0)
{
DEBUG(D_transport) debug_printf("negative value in maildirsize "
- "(size=%d count=%d): recalculating\n", size, filecount);
- goto RECALCULATE;
- }
-
+ "(size=%d count=%d): recalculating\n", size, filecount);
+ goto RECALCULATE;
+ }
+
if (ob->quota_value > 0 &&
(size + (ob->quota_is_inclusive? message_size : 0) > ob->quota_value ||
(ob->quota_filecount_value > 0 &&
-/* $Cambridge: exim/src/src/verify.c,v 1.14 2005/01/27 10:26:14 ph10 Exp $ */
+/* $Cambridge: exim/src/src/verify.c,v 1.15 2005/02/17 11:58:26 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
static int
do_callout(address_item *addr, host_item *host_list, transport_feedback *tf,
- int callout, int callout_overall, int callout_connect, int options,
+ int callout, int callout_overall, int callout_connect, int options,
uschar *se_mailfrom, uschar *pm_mailfrom)
{
BOOL is_recipient = (options & vopt_is_recipient) != 0;
uschar *address_key;
uschar *from_address;
uschar *random_local_part = NULL;
-uschar **failure_ptr = is_recipient?
+uschar **failure_ptr = is_recipient?
&recipient_verify_failure : &sender_verify_failure;
open_db dbblock;
open_db *dbm_file = NULL;
setflag(addr, af_verify_nsfail);
addr->user_message = US"(result of an earlier callout reused).";
yield = FAIL;
- *failure_ptr = US"mail";
+ *failure_ptr = US"mail";
goto END_CALLOUT;
}
debug_printf("callout cache: domain does not accept "
"RCPT TO:<postmaster@domain>\n");
yield = FAIL;
- *failure_ptr = US"postmaster";
+ *failure_ptr = US"postmaster";
setflag(addr, af_verify_pmfail);
addr->user_message = US"(result of earlier verification reused).";
goto END_CALLOUT;
HDEBUG(D_verify)
debug_printf("callout cache: address record is negative\n");
addr->user_message = US"Previous (cached) callout verification failure";
- *failure_ptr = US"recipient";
+ *failure_ptr = US"recipient";
yield = FAIL;
}
goto END_CALLOUT;
smtp_outblock outblock;
int host_af;
int port = 25;
- BOOL send_quit = TRUE;
+ BOOL send_quit = TRUE;
uschar *helo = US"HELO";
uschar *interface = NULL; /* Outgoing interface to use; NULL => any */
uschar inbuffer[4096];
if (!done)
{
- *failure_ptr = US"mail";
+ *failure_ptr = US"mail";
if (errno == 0 && responsebuffer[0] == '5')
{
setflag(addr, af_verify_nsfail);
new_address_record.result = ccache_accept;
else if (errno == 0 && responsebuffer[0] == '5')
{
- *failure_ptr = US"recipient";
+ *failure_ptr = US"recipient";
new_address_record.result = ccache_reject;
- }
+ }
/* Do postmaster check if requested */
new_domain_record.postmaster_result = ccache_accept;
else if (errno == 0 && responsebuffer[0] == '5')
{
- *failure_ptr = US"postmaster";
+ *failure_ptr = US"postmaster";
setflag(addr, af_verify_pmfail);
new_domain_record.postmaster_result = ccache_reject;
}
if (errno == ETIMEDOUT)
{
HDEBUG(D_verify) debug_printf("SMTP timeout\n");
- send_quit = FALSE;
+ send_quit = FALSE;
}
else if (errno == 0)
{
for individual commands
callout_overall if > 0, gives overall timeout for the callout function;
if < 0, a default is used (see do_callout())
- callout_connect the connection timeout for callouts
+ callout_connect the connection timeout for callouts
se_mailfrom when callout is requested to verify a sender, use this
in MAIL FROM; NULL => ""
pm_mailfrom when callout is requested, if non-NULL, do the postmaster
int
verify_address(address_item *vaddr, FILE *f, int options, int callout,
- int callout_overall, int callout_connect, uschar *se_mailfrom,
+ int callout_overall, int callout_connect, uschar *se_mailfrom,
uschar *pm_mailfrom, BOOL *routed)
{
BOOL allok = TRUE;
address_item *addr_remote = NULL;
address_item *addr_local = NULL;
address_item *addr_succeed = NULL;
-uschar **failure_ptr = is_recipient?
+uschar **failure_ptr = is_recipient?
&recipient_verify_failure : &sender_verify_failure;
uschar *ko_prefix, *cr;
uschar *address = vaddr->address;
if (f != NULL)
fprintf(f, "%sA domain is required for \"%s\"%s\n", ko_prefix, address,
cr);
- *failure_ptr = US"qualify";
+ *failure_ptr = US"qualify";
return FAIL;
}
address = rewrite_address_qualify(address, is_recipient);
host_build_hostlist(&host_list, s, tf.hosts_randomize);
/* Just ignore failures to find a host address. If we don't manage
- to find any addresses, the callout will defer. Note that more than
- one address may be found for a single host, which will result in
- additional host items being inserted into the chain. Hence we must
+ to find any addresses, the callout will defer. Note that more than
+ one address may be found for a single host, which will result in
+ additional host items being inserted into the chain. Hence we must
save the next host first. */
for (host = host_list; host != NULL; host = nexthost)
{
nexthost = host->next;
- if (tf.gethostbyname ||
+ if (tf.gethostbyname ||
string_is_ip_address(host->name, NULL) > 0)
(void)host_find_byname(host, NULL, &canonical_name, TRUE);
else
}
}
- /* Can only do a callout if we have at least one host! If the callout
+ /* Can only do a callout if we have at least one host! If the callout
fails, it will have set ${sender,recipient}_verify_failure. */
if (host_list != NULL)
}
}
}
-
+
/* Otherwise, any failure is a routing failure */
-
- else *failure_ptr = US"route";
+
+ else *failure_ptr = US"route";
/* A router may return REROUTED if it has set up a child address as a result
of a change of domain name (typically from widening). In this case we always
want to continue to verify the new child. */
if (rc == REROUTED) continue;
-
+
/* Handle hard failures */
if (rc == FAIL)
}
}
-/* Will be DEFER or FAIL if any one address has, only for full_info (which is
+/* Will be DEFER or FAIL if any one address has, only for full_info (which is
the -bv or -bt case). */
-return yield;
+return yield;
}
log_msgptr points to where to put a log error message
callout timeout for callout check (passed to verify_address())
callout_overall overall callout timeout (ditto)
- callout_connect connect callout timeout (ditto)
+ callout_connect connect callout timeout (ditto)
se_mailfrom mailfrom for verify; NULL => ""
pm_mailfrom sender for pm callout check (passed to verify_address())
options callout options (passed to verify_address())
- verrno where to put the address basic_errno
+ verrno where to put the address basic_errno
If log_msgptr is set to something without setting user_msgptr, the caller
normally uses log_msgptr for both things.
int
verify_check_header_address(uschar **user_msgptr, uschar **log_msgptr,
- int callout, int callout_overall, int callout_connect, uschar *se_mailfrom,
+ int callout, int callout_overall, int callout_connect, uschar *se_mailfrom,
uschar *pm_mailfrom, int options, int *verrno)
{
static int header_types[] = { htype_sender, htype_reply_to, htype_from };
{
vaddr = deliver_make_addr(address, FALSE);
new_ok = verify_address(vaddr, NULL, options | vopt_fake_sender,
- callout, callout_overall, callout_connect, se_mailfrom,
+ callout, callout_overall, callout_connect, se_mailfrom,
pm_mailfrom, NULL);
}
}
if (new_ok != OK)
{
- *verrno = vaddr->basic_errno;
+ *verrno = vaddr->basic_errno;
if (smtp_return_error_details)
{
*user_msgptr = string_sprintf("Rejected after DATA: "
"could not verify \"%.*s\" header address\n%s: %s",
endname - h->text, h->text, vaddr->address, vaddr->message);
}
- }
+ }
/* Success or defer */
/* Adjust parameters for the type of lookup. For a query-style
lookup, there is no file name, and the "key" is just the query. For
a single-key lookup, the key is the current IP address, masked
- appropriately, and reconverted to text form, with the mask appended.
+ appropriately, and reconverted to text form, with the mask appended.
For IPv6 addresses, specify dot separators instead of colons. */
if (mac_islookup(search_type, lookup_querystyle))
cb.host_ipv4 = (Ustrncmp(host_address, "::ffff:", 7) == 0)?
host_address + 7 : host_address;
-/* During the running of the check, put the IP address into $host_address. In
-the case of calls from the smtp transport, it will already be there. However,
-in other calls (e.g. when testing ignore_target_hosts), it won't. Just to be on
+/* During the running of the check, put the IP address into $host_address. In
+the case of calls from the smtp transport, it will already be there. However,
+in other calls (e.g. when testing ignore_target_hosts), it won't. Just to be on
the safe side, any existing setting is preserved, though as I write this
(November 2004) I can't see any cases where it is actually needed. */
check_host, /* function for testing */
&cb, /* argument for function */
MCL_HOST, /* type of check */
- (host_address == sender_host_address)?
+ (host_address == sender_host_address)?
US"host" : host_address, /* text for debugging */
valueptr); /* where to pass back data */
deliver_host_address = save_host_address;
-return rc;
+return rc;
}
Arguments:
domain the outer dnsbl domain (for debug message)
- keydomain the current keydomain (for debug message)
+ keydomain the current keydomain (for debug message)
query the domain to be looked up
- iplist the list of matching IP addresses
- bitmask true if bitmask matching is wanted
- invert_result true if result to be inverted
- defer_return what to return for a defer
+ iplist the list of matching IP addresses
+ bitmask true if bitmask matching is wanted
+ invert_result true if result to be inverted
+ defer_return what to return for a defer
Returns: OK if lookup succeeded
FAIL if not
*/
static int
-one_check_dnsbl(uschar *domain, uschar *keydomain, uschar *query,
+one_check_dnsbl(uschar *domain, uschar *keydomain, uschar *query,
uschar *iplist, BOOL bitmask, BOOL invert_result, int defer_return)
-{
+{
dns_answer dnsa;
dns_scan dnss;
tree_node *t;
debug_printf("=> there was %s match for %c%s\n",
invert_result? "an exclude":"no", bitmask? '&' : '=', iplist);
}
- return FAIL;
+ return FAIL;
}
}
}
}
- /* If there is no key string, construct the query by adding the domain name
+ /* If there is no key string, construct the query by adding the domain name
onto the inverted host address, and perform a single DNS lookup. */
-
+
if (key == NULL)
{
if (sender_host_address == NULL) return FAIL; /* can never match */
if (revadd[0] == 0) invert_address(revadd, sender_host_address);
frc = string_format(query, sizeof(query), "%s%s", revadd, domain);
-
+
if (!frc)
{
log_write(0, LOG_MAIN|LOG_PANIC, "dnslist query is too long "
"(ignored): %s...", query);
continue;
}
-
- rc = one_check_dnsbl(domain, sender_host_address, query, iplist, bitmask,
+
+ rc = one_check_dnsbl(domain, sender_host_address, query, iplist, bitmask,
invert_result, defer_return);
-
+
if (rc == OK)
{
dnslist_domain = string_copy(domain);
- HDEBUG(D_dnsbl) debug_printf("=> that means %s is listed at %s\n",
+ HDEBUG(D_dnsbl) debug_printf("=> that means %s is listed at %s\n",
sender_host_address, domain);
}
-
+
if (rc != FAIL) return rc; /* OK or DEFER */
}
-
- /* If there is a key string, it can be a list of domains or IP addresses to
+
+ /* If there is a key string, it can be a list of domains or IP addresses to
be concatenated with the main domain. */
-
+
else
{
int keysep = 0;
- BOOL defer = FALSE;
- uschar *keydomain;
+ BOOL defer = FALSE;
+ uschar *keydomain;
uschar keybuffer[256];
-
- while ((keydomain = string_nextinlist(&key, &keysep, keybuffer,
+
+ while ((keydomain = string_nextinlist(&key, &keysep, keybuffer,
sizeof(keybuffer))) != NULL)
- {
+ {
if (string_is_ip_address(keydomain, NULL) > 0)
{
uschar keyrevadd[128];
invert_address(keyrevadd, keydomain);
- frc = string_format(query, sizeof(query), "%s%s", keyrevadd, domain);
+ frc = string_format(query, sizeof(query), "%s%s", keyrevadd, domain);
}
else
- {
+ {
frc = string_format(query, sizeof(query), "%s.%s", keydomain, domain);
}
"(ignored): %s...", query);
continue;
}
-
- rc = one_check_dnsbl(domain, keydomain, query, iplist, bitmask,
+
+ rc = one_check_dnsbl(domain, keydomain, query, iplist, bitmask,
invert_result, defer_return);
-
+
if (rc == OK)
{
dnslist_domain = string_copy(domain);
- HDEBUG(D_dnsbl) debug_printf("=> that means %s is listed at %s\n",
+ HDEBUG(D_dnsbl) debug_printf("=> that means %s is listed at %s\n",
keydomain, domain);
- return OK;
+ return OK;
}
-
+
/* If the lookup deferred, remember this fact. We keep trying the rest
of the list to see if we get a useful result, and if we don't, we return
DEFER at the end. */
} /* continue with next keystring domain/address */
if (defer) return DEFER;
- }
+ }
} /* continue with next dnsdb outer domain */
return FAIL;