-# $Cambridge: exim/src/OS/Makefile-Base,v 1.1.2.3 2004/12/02 16:33:30 tom Exp $
+# $Cambridge: exim/src/OS/Makefile-Base,v 1.1.2.4 2004/12/10 09:24:38 tom 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
@echo ">>> convert4r4 script built"; echo ""
+# These are objects of optional features. They are always compiled, but
+# if the corresponding #defines are not set, they wind up empty and
+# are thrown away by the linker.
+
+OBJ_WITH_CONTENT_SCAN = malware.o mime.o regex.o spam.o spool_mbox.o
+OBJ_WITH_OLD_DEMIME = demime.o
+OBJ_EXPERIMENTAL = bmi_spam.o spf.o srs.o
+
# Targets for final binaries; the main one has a build number which is
# updated each time. We don't bother with that for the auxiliaries.
-OBJ_WITH_CONTENT_SCAN = demime.o malware.o mime.o regex.o spam.o spool_mbox.o
-
OBJ_EXIM = acl.o child.o crypt16.o daemon.o dbfn.o debug.o deliver.o \
directory.o dns.o drtables.o enq.o exim.o expand.o filter.o \
filtertest.o globals.o \
rda.o readconf.o receive.o retry.o rewrite.o rfc2047.o \
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)
+ local_scan.o $(EXIM_PERL) $(OBJ_WITH_CONTENT_SCAN) \
+ $(OBJ_WITH_OLD_DEMIME) $(OBJ_EXPERIMENTAL)
exim: pcre/libpcre.a lookups/lookups.a auths/auths.a \
routers/routers.a transports/transports.a \
# Dependencies for WITH_CONTENT_SCAN modules
-demime.o: $(HDRS) demime.c
malware.o: $(HDRS) malware.c
mime.o: $(HDRS) mime.c
regex.o: $(HDRS) regex.c
spool_mbox.o: $(HDRS) spool_mbox.c
+# Dependencies for WITH_OLD_DEMIME modules
+
+demime.o: $(HDRS) demime.c
+
+
+# Dependencies for EXPERIMENTAL_* modules
+
+bmi_spam.o: $(HDRS) bmi_spam.c
+spf.o: $(HDRS) spf.c
+srs.o: $(HDRS) srs.c
+
+
# The module containing tables of available lookups, routers, auths, and
# transports must be rebuilt if any of them are. However, because the makefiles
# for the drivers are always run, we don't actually put the dependencies here,
#!/bin/sh
-# $Cambridge: exim/src/scripts/MakeLinks,v 1.1.2.3 2004/12/02 16:33:30 tom Exp $
+# $Cambridge: exim/src/scripts/MakeLinks,v 1.1.2.4 2004/12/10 09:24:38 tom Exp $
# Script to build links for all the exim source files from the system-
# specific build directory. It should be run from within that directory.
# but local_scan.c does not, because its location is taken from the build-time
# configuration. Likewise for the os.c file, which gets build dynamically.
-# NB: Files marked as "WITH_CONTENT_SCAN" contain only functions relating
-# to content scanning. They are always linked, but their contents compile
-# to nothing if WITH_CONTENT_SCAN is not set.
-
ln -s ../src/dbfunctions.h dbfunctions.h
ln -s ../src/dbstuff.h dbstuff.h
-# WITH_OLD_DEMIME
-ln -s ../src/demime.h demime.h
-#
ln -s ../src/exim.h exim.h
ln -s ../src/functions.h functions.h
ln -s ../src/globals.h globals.h
ln -s ../src/local_scan.h local_scan.h
ln -s ../src/macros.h macros.h
-# WITH_CONTENT_SCAN
-ln -s ../src/mime.h mime.h
-#
ln -s ../src/mytypes.h mytypes.h
ln -s ../src/osfunctions.h osfunctions.h
-# WITH_CONTENT_SCAN
-ln -s ../src/spam.h spam.h
-#
ln -s ../src/store.h store.h
ln -s ../src/structs.h structs.h
ln -s ../src/dbfn.c dbfn.c
ln -s ../src/debug.c debug.c
ln -s ../src/deliver.c deliver.c
-# WITH_OLD_DEMIME
-ln -s ../src/demime.c demime.c
-#
ln -s ../src/directory.c directory.c
ln -s ../src/dns.c dns.c
ln -s ../src/drtables.c drtables.c
ln -s ../src/ip.c ip.c
ln -s ../src/log.c log.c
ln -s ../src/lss.c lss.c
-# WITH_CONTENT_SCAN
-ln -s ../src/malware.c malware.c
-#
ln -s ../src/match.c match.c
-# WITH_CONTENT_SCAN
-ln -s ../src/mime.c mime.c
-#
ln -s ../src/moan.c moan.c
ln -s ../src/parse.c parse.c
ln -s ../src/perl.c perl.c
ln -s ../src/rda.c rda.c
ln -s ../src/readconf.c readconf.c
ln -s ../src/receive.c receive.c
-# WITH_CONTENT_SCAN
-ln -s ../src/regex.c regex.c
-#
ln -s ../src/retry.c retry.c
ln -s ../src/rewrite.c rewrite.c
ln -s ../src/rfc2047.c rfc2047.c
ln -s ../src/sieve.c sieve.c
ln -s ../src/smtp_in.c smtp_in.c
ln -s ../src/smtp_out.c smtp_out.c
-# WITH_CONTENT_SCAN
-ln -s ../src/spam.c spam.c
-#
ln -s ../src/spool_in.c spool_in.c
-# WITH_CONTENT_SCAN
-ln -s ../src/spool_mbox.c spool_mbox.c
-#
ln -s ../src/spool_out.c spool_out.c
ln -s ../src/store.c store.c
ln -s ../src/string.c string.c
ln -s ../src/verify.c verify.c
ln -s ../src/version.c version.c
+# WITH_CONTENT_SCAN
+ln -s ../src/spam.c spam.c
+ln -s ../src/spam.h spam.h
+ln -s ../src/spool_mbox.c spool_mbox.c
+ln -s ../src/regex.c regex.c
+ln -s ../src/mime.c mime.c
+ln -s ../src/mime.h mime.h
+ln -s ../src/malware.c malware.c
+
+# WITH_OLD_DEMIME
+ln -s ../src/demime.c demime.c
+ln -s ../src/demime.h demime.h
+
+# EXPERIMENTAL_*
+ln -s ../src/bmi_spam.c bmi_spam.c
+ln -s ../src/bmi_spam.h bmi_spam.h
+ln -s ../src/spf.c spf.c
+ln -s ../src/spf.h spf.h
+ln -s ../src/srs.c srs.c
+ln -s ../src/srs.h srs.h
+
# End of MakeLinks
-/* $Cambridge: exim/src/src/acl.c,v 1.5.2.3 2004/12/02 16:33:30 tom Exp $ */
+/* $Cambridge: exim/src/src/acl.c,v 1.5.2.4 2004/12/10 09:24:38 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
#ifdef WITH_CONTENT_SCAN
case CONTROL_FAKEREJECT:
fake_reject = TRUE;
+ if (*p == '/')
+ {
+ uschar *pp = p + 1;
+ while (*pp != 0) pp++;
+ fake_reject_text = expand_string(string_copyn(p+1, pp-p));
+ p = pp;
+ }
+ else
+ {
+ /* Explicitly reset to default string */
+ fake_reject_text = US"Your message has been rejected but is being kept for evaluation.\nIf it was a legit message, it may still be delivered to the target recipient(s).";
+ }
break;
#endif
--- /dev/null
+/* $Cambridge: exim/src/src/bmi_spam.c,v 1.1.2.1 2004/12/10 09:24:38 tom Exp $ */
+
+/*************************************************
+* Exim - an Internet mail transport agent *
+*************************************************/
+
+/* Code for calling Brightmail AntiSpam.
+ Copyright (c) Tom Kistner <tom@duncanthrax.net> 2004
+ License: GPL */
+
+#include "exim.h"
+#ifdef EXPERIMENTAL_BRIGHTMAIL
+
+#include "bmi_spam.h"
+
+uschar *bmi_current_optin = NULL;
+
+uschar *bmi_process_message(header_line *header_list, int data_fd) {
+ BmiSystem *system = NULL;
+ BmiMessage *message = NULL;
+ BmiError err;
+ BmiErrorLocation err_loc;
+ BmiErrorType err_type;
+ const BmiVerdict *verdict = NULL;
+ FILE *data_file;
+ uschar data_buffer[4096];
+ uschar localhost[] = "127.0.0.1";
+ 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);
+ err_type = bmiErrorGetType(err);
+ log_write(0, LOG_PANIC,
+ "bmi error [loc %d type %d]: could not initialize Brightmail system.", (int)err_loc, (int)err_type);
+ return NULL;
+ }
+
+ err = bmiInitMessage(system, &message);
+ if (bmiErrorIsFatal(err) == BMI_TRUE) {
+ err_loc = bmiErrorGetLocation(err);
+ err_type = bmiErrorGetType(err);
+ log_write(0, LOG_PANIC,
+ "bmi error [loc %d type %d]: could not initialize Brightmail message.", (int)err_loc, (int)err_type);
+ bmiFreeSystem(system);
+ return NULL;
+ }
+
+ /* Send IP address of sending host */
+ if (sender_host_address == NULL)
+ host_address = localhost;
+ else
+ host_address = sender_host_address;
+ err = bmiProcessConnection((char *)host_address, message);
+ if (bmiErrorIsFatal(err) == BMI_TRUE) {
+ err_loc = bmiErrorGetLocation(err);
+ err_type = bmiErrorGetType(err);
+ log_write(0, LOG_PANIC,
+ "bmi error [loc %d type %d]: bmiProcessConnection() failed (IP %s).", (int)err_loc, (int)err_type, (char *)host_address);
+ bmiFreeMessage(message);
+ bmiFreeSystem(system);
+ return NULL;
+ };
+
+ /* Send envelope sender address */
+ err = bmiProcessFROM((char *)sender_address, message);
+ if (bmiErrorIsFatal(err) == BMI_TRUE) {
+ err_loc = bmiErrorGetLocation(err);
+ err_type = bmiErrorGetType(err);
+ log_write(0, LOG_PANIC,
+ "bmi error [loc %d type %d]: bmiProcessFROM() failed (address %s).", (int)err_loc, (int)err_type, (char *)sender_address);
+ bmiFreeMessage(message);
+ bmiFreeSystem(system);
+ return NULL;
+ };
+
+ /* Send envelope recipients */
+ 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);
+ bmiOptinInit(&optin);
+ err = bmiOptinMset(optin, r->bmi_optin, ':');
+ if (bmiErrorIsFatal(err) == BMI_TRUE) {
+ log_write(0, LOG_PANIC|LOG_MAIN,
+ "bmi warning: [loc %d type %d]: bmiOptinMSet() failed (address '%s', string '%s').", (int)err_loc, (int)err_type, (char *)r->address, (char *)r->bmi_optin);
+ if (optin != NULL)
+ bmiOptinFree(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);
+ log_write(0, LOG_PANIC,
+ "bmi error [loc %d type %d]: bmiAccumulateTO() failed (address %s).", (int)err_loc, (int)err_type, (char *)r->address);
+ bmiFreeMessage(message);
+ bmiFreeSystem(system);
+ return NULL;
+ };
+ };
+ err = bmiEndTO(message);
+ if (bmiErrorIsFatal(err) == BMI_TRUE) {
+ err_loc = bmiErrorGetLocation(err);
+ err_type = bmiErrorGetType(err);
+ log_write(0, LOG_PANIC,
+ "bmi error [loc %d type %d]: bmiEndTO() failed.", (int)err_loc, (int)err_type);
+ bmiFreeMessage(message);
+ bmiFreeSystem(system);
+ return NULL;
+ };
+
+ /* Send message headers */
+ while (header_list != NULL) {
+ /* skip deleted headers */
+ if (header_list->type == '*') {
+ header_list = header_list->next;
+ continue;
+ };
+ err = bmiAccumulateHeaders((const char *)header_list->text, header_list->slen, message);
+ if (bmiErrorIsFatal(err) == BMI_TRUE) {
+ err_loc = bmiErrorGetLocation(err);
+ err_type = bmiErrorGetType(err);
+ log_write(0, LOG_PANIC,
+ "bmi error [loc %d type %d]: bmiAccumulateHeaders() failed.", (int)err_loc, (int)err_type);
+ bmiFreeMessage(message);
+ bmiFreeSystem(system);
+ return NULL;
+ };
+ header_list = header_list->next;
+ };
+ err = bmiEndHeaders(message);
+ if (bmiErrorIsFatal(err) == BMI_TRUE) {
+ err_loc = bmiErrorGetLocation(err);
+ err_type = bmiErrorGetType(err);
+ log_write(0, LOG_PANIC,
+ "bmi error [loc %d type %d]: bmiEndHeaders() failed.", (int)err_loc, (int)err_type);
+ bmiFreeMessage(message);
+ bmiFreeSystem(system);
+ return NULL;
+ };
+
+ /* Send body */
+ data_file = fdopen(data_fd,"r");
+ do {
+ j = fread(data_buffer, 1, sizeof(data_buffer), data_file);
+ if (j > 0) {
+ err = bmiAccumulateBody((const char *)data_buffer, j, message);
+ if (bmiErrorIsFatal(err) == BMI_TRUE) {
+ err_loc = bmiErrorGetLocation(err);
+ err_type = bmiErrorGetType(err);
+ log_write(0, LOG_PANIC,
+ "bmi error [loc %d type %d]: bmiAccumulateBody() failed.", (int)err_loc, (int)err_type);
+ bmiFreeMessage(message);
+ bmiFreeSystem(system);
+ return NULL;
+ };
+ };
+ } while (j > 0);
+ err = bmiEndBody(message);
+ if (bmiErrorIsFatal(err) == BMI_TRUE) {
+ err_loc = bmiErrorGetLocation(err);
+ err_type = bmiErrorGetType(err);
+ log_write(0, LOG_PANIC,
+ "bmi error [loc %d type %d]: bmiEndBody() failed.", (int)err_loc, (int)err_type);
+ bmiFreeMessage(message);
+ bmiFreeSystem(system);
+ return NULL;
+ };
+
+
+ /* End message */
+ err = bmiEndMessage(message);
+ if (bmiErrorIsFatal(err) == BMI_TRUE) {
+ err_loc = bmiErrorGetLocation(err);
+ err_type = bmiErrorGetType(err);
+ log_write(0, LOG_PANIC,
+ "bmi error [loc %d type %d]: bmiEndMessage() failed.", (int)err_loc, (int)err_type);
+ bmiFreeMessage(message);
+ 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) ) {
+ char *verdict_str;
+
+ err = bmiCreateStrFromVerdict(verdict,&verdict_str);
+ if (!store_extend(verdicts, Ustrlen(verdicts)+1, Ustrlen(verdicts)+1+strlen(verdict_str)+1)) {
+ /* can't allocate more store */
+ return NULL;
+ };
+ if (*verdicts != '\0')
+ Ustrcat(verdicts, US ":");
+ Ustrcat(verdicts, US verdict_str);
+ bmiFreeStr(verdict_str);
+ };
+
+ DEBUG(D_receive) debug_printf("bmi verdicts: %s\n", verdicts);
+
+ if (Ustrlen(verdicts) == 0)
+ return NULL;
+ else
+ return verdicts;
+}
+
+
+int bmi_get_delivery_status(uschar *base64_verdict) {
+ BmiError err;
+ BmiErrorLocation err_loc;
+ 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;
+
+ /* create verdict from base64 string */
+ err = bmiCreateVerdictFromStr(CS base64_verdict, &verdict);
+ if (bmiErrorIsFatal(err) == BMI_TRUE) {
+ err_loc = bmiErrorGetLocation(err);
+ err_type = bmiErrorGetType(err);
+ log_write(0, LOG_PANIC,
+ "bmi error [loc %d type %d]: bmiCreateVerdictFromStr() failed. [%s]", (int)err_loc, (int)err_type, base64_verdict);
+ return 1;
+ };
+
+ err = bmiVerdictError(verdict);
+ if (bmiErrorIsFatal(err) == BMI_TRUE) {
+ /* deliver normally due to error */
+ rc = 1;
+ }
+ else if (bmiVerdictDestinationIsDefault(verdict) == BMI_TRUE) {
+ /* deliver normally */
+ rc = 1;
+ }
+ else if (bmiVerdictAccessDestination(verdict) == NULL) {
+ /* do not deliver */
+ rc = 0;
+ }
+ else {
+ /* deliver to alternate location */
+ rc = 1;
+ };
+
+ bmiFreeVerdict(verdict);
+ return rc;
+}
+
+
+uschar *bmi_get_alt_location(uschar *base64_verdict) {
+ BmiError err;
+ BmiErrorLocation err_loc;
+ BmiErrorType err_type;
+ BmiVerdict *verdict = NULL;
+ uschar *rc = NULL;
+
+ /* always deliver when there is no verdict */
+ if (base64_verdict == NULL)
+ return NULL;
+
+ /* create verdict from base64 string */
+ err = bmiCreateVerdictFromStr(CS base64_verdict, &verdict);
+ if (bmiErrorIsFatal(err) == BMI_TRUE) {
+ err_loc = bmiErrorGetLocation(err);
+ err_type = bmiErrorGetType(err);
+ log_write(0, LOG_PANIC,
+ "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 */
+ rc = NULL;
+ }
+ else if (bmiVerdictDestinationIsDefault(verdict) == BMI_TRUE) {
+ /* deliver normally */
+ rc = NULL;
+ }
+ else if (bmiVerdictAccessDestination(verdict) == NULL) {
+ /* do not deliver */
+ rc = NULL;
+ }
+ else {
+ /* deliver to alternate location */
+ rc = store_get(strlen(bmiVerdictAccessDestination(verdict))+1);
+ Ustrcpy(rc, bmiVerdictAccessDestination(verdict));
+ rc[strlen(bmiVerdictAccessDestination(verdict))] = '\0';
+ };
+
+ bmiFreeVerdict(verdict);
+ return rc;
+}
+
+uschar *bmi_get_base64_verdict(uschar *bmi_local_part, uschar *bmi_domain) {
+ BmiError err;
+ BmiErrorLocation err_loc;
+ BmiErrorType err_type;
+ BmiVerdict *verdict = NULL;
+ const BmiRecipient *recipient = NULL;
+ const char *verdict_str = NULL;
+ 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) {
+ err_loc = bmiErrorGetLocation(err);
+ err_type = bmiErrorGetType(err);
+ log_write(0, LOG_PANIC,
+ "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,'@');
+ if (rcpt_domain == NULL) {
+ rcpt_domain = US"";
+ }
+ else {
+ *rcpt_domain = '\0';
+ rcpt_domain++;
+ };
+
+ if ( (strcmpic(rcpt_local_part, bmi_local_part) == 0) &&
+ (strcmpic(rcpt_domain, bmi_domain) == 0) ) {
+ /* found verdict */
+ bmiFreeVerdict(verdict);
+ return (uschar *)verdict_str;
+ };
+ };
+
+ bmiFreeVerdict(verdict);
+ };
+
+ return NULL;
+}
+
+
+uschar *bmi_get_base64_tracker_verdict(uschar *base64_verdict) {
+ BmiError err;
+ BmiErrorLocation err_loc;
+ BmiErrorType err_type;
+ BmiVerdict *verdict = NULL;
+ uschar *rc = NULL;
+
+ /* always deliver when there is no verdict */
+ if (base64_verdict == NULL)
+ return NULL;
+
+ /* create verdict from base64 string */
+ err = bmiCreateVerdictFromStr(CS base64_verdict, &verdict);
+ if (bmiErrorIsFatal(err) == BMI_TRUE) {
+ err_loc = bmiErrorGetLocation(err);
+ err_type = bmiErrorGetType(err);
+ log_write(0, LOG_PANIC,
+ "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) {
+ err_loc = bmiErrorGetLocation(err);
+ err_type = bmiErrorGetType(err);
+ log_write(0, LOG_PANIC,
+ "bmi error [loc %d type %d]: bmiCreateOldStrFromVerdict() failed. [%s]", (int)err_loc, (int)err_type, base64_verdict);
+ return NULL;
+ };
+
+ bmiFreeVerdict(verdict);
+ return rc;
+}
+
+
+int bmi_check_rule(uschar *base64_verdict, uschar *option_list) {
+ BmiError err;
+ BmiErrorLocation err_loc;
+ BmiErrorType err_type;
+ BmiVerdict *verdict = NULL;
+ int rc = 0;
+ uschar *rule_num;
+ 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) {
+ err_loc = bmiErrorGetLocation(err);
+ err_type = bmiErrorGetType(err);
+ log_write(0, LOG_PANIC,
+ "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) {
+ debug_printf("checking rule #%d\n", rule_int);
+ /* check if rule fired on the message */
+ if (bmiVerdictRuleFired(verdict, rule_int) == BMI_TRUE) {
+ debug_printf("rule #%d fired\n", rule_int);
+ rc = 1;
+ break;
+ };
+ };
+ };
+
+ bmiFreeVerdict(verdict);
+ return rc;
+};
+
+#endif
--- /dev/null
+/* $Cambridge: exim/src/src/bmi_spam.h,v 1.1.2.1 2004/12/10 09:24:38 tom Exp $ */
+
+/*************************************************
+* Exim - an Internet mail transport agent *
+*************************************************/
+
+/* Code for calling Brightmail AntiSpam.
+ Copyright (c) Tom Kistner <tom@duncanthrax.net> 2004
+ License: GPL */
+
+#ifdef EXPERIMENTAL_BRIGHTMAIL
+
+#include <bmi_api.h>
+
+extern uschar *bmi_process_message(header_line *, int);
+extern uschar *bmi_get_base64_verdict(uschar *, uschar *);
+extern uschar *bmi_get_base64_tracker_verdict(uschar *);
+extern int bmi_get_delivery_status(uschar *);
+extern uschar *bmi_get_alt_location(uschar *);
+extern int bmi_check_rule(uschar *,uschar *);
+
+extern uschar *bmi_current_optin;
+
+#endif
-/* $Cambridge: exim/src/src/globals.c,v 1.6.2.3 2004/12/02 09:15:11 tom Exp $ */
+/* $Cambridge: exim/src/src/globals.c,v 1.6.2.4 2004/12/10 09:24:38 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
#ifdef WITH_CONTENT_SCAN
BOOL fake_reject = FALSE;
+uschar *fake_reject_text = US"Your message has been rejected but is being kept for evaluation.\nIf it was a legit message, it may still be delivered to the target recipient(s).";
#endif
int filter_n[FILTER_VARIABLE_COUNT];
BOOL filter_running = FALSE;
-/* $Cambridge: exim/src/src/globals.h,v 1.6.2.2 2004/12/02 09:15:11 tom Exp $ */
+/* $Cambridge: exim/src/src/globals.h,v 1.6.2.3 2004/12/10 09:24:38 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
#ifdef WITH_CONTENT_SCAN
extern BOOL fake_reject; /* TRUE if fake reject is to be given */
+extern uschar *fake_reject_text; /* Option for the fakereject control statement: can contain user defined message. Default is in globals.c. */
#endif
extern int filter_n[FILTER_VARIABLE_COUNT]; /* filter variables */
extern BOOL filter_running; /* TRUE while running a filter */
-/* $Cambridge: exim/src/src/receive.c,v 1.4.2.2 2004/12/02 16:33:30 tom Exp $ */
+/* $Cambridge: exim/src/src/receive.c,v 1.4.2.3 2004/12/10 09:24:38 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
smtp_printf("250 OK id=%s\r\n", message_id);
#else
if (fake_reject)
- {
- smtp_printf("550-FAKE_REJECT id=%s\r\n", message_id);
- smtp_printf("550-Your message has been rejected but is being kept for evaluation.\r\n");
- smtp_printf("550 If it was a legit message, it may still be delivered to the target recipient(s).\r\n");
- }
+ smtp_respond(550,TRUE,fake_reject_text);
else
smtp_printf("250 OK id=%s\r\n", message_id);
#endif
else if (smtp_reply[0] != 0)
{
if (fake_reject && (smtp_reply[0] == '2'))
- {
- smtp_printf("550-FAKE_REJECT id=%s\r\n", message_id);
- smtp_printf("550-Your message has been rejected but is being kept for evaluation.\r\n");
- smtp_printf("550 If it was a legit message, it may still be delivered to the target recipient(s).\r\n");
- }
+ smtp_respond(550,TRUE,fake_reject_text);
else
smtp_printf("%.1024s\r\n", smtp_reply);
};
--- /dev/null
+/* $Cambridge: exim/src/src/spf.c,v 1.1.2.1 2004/12/10 09:24:38 tom 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"
+#ifdef EXPERIMENTAL_SPF
+
+#include "spf.h"
+
+SPF_config_t spfcid = NULL;
+SPF_dns_config_t spfdcid_resolv = NULL;
+SPF_dns_config_t spfdcid = NULL;
+
+
+/* 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");
+ return 0;
+ }
+
+ /* set up resolver */
+ spfdcid_resolv = SPF_dns_create_config_resolv(NULL, 0);
+ spfdcid = SPF_dns_create_config_cache(spfdcid_resolv, 8, 0);
+
+ if (spfdcid == NULL) {
+ debug_printf("spf: SPF_dns_create_config_cache() failed.\n");
+ spfcid = NULL;
+ spfdcid_resolv = NULL;
+ return 0;
+ }
+
+ if (SPF_set_ip_str(spfcid, spf_remote_addr)) {
+ debug_printf("spf: SPF_set_ip_str() failed.\n");
+ spfcid = NULL;
+ spfdcid_resolv = NULL;
+ return 0;
+ }
+
+ if (SPF_set_helo_dom(spfcid, spf_helo_domain)) {
+ debug_printf("spf: SPF_set_helo_dom() failed.\n");
+ spfcid = NULL;
+ spfdcid_resolv = NULL;
+ return 0;
+ }
+
+ return 1;
+}
+
+
+/* spf_process adds the envelope sender address to the existing
+ context (if any), retrieves the result, sets up expansion
+ strings and evaluates the condition outcome. */
+
+int spf_process(uschar **listptr, uschar *spf_envelope_sender) {
+ int sep = 0;
+ uschar *list = *listptr;
+ uschar *spf_result_id;
+ 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;
+ goto SPF_EVALUATE;
+ };
+
+ if (SPF_set_env_from(spfcid, spf_envelope_sender)) {
+ /* 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);
+
+ /* set up expansion items */
+ spf_header_comment = spf_output.header_comment ? (uschar *)spf_output.header_comment : NULL;
+ spf_received = spf_output.received_spf ? (uschar *)spf_output.received_spf : NULL;
+ spf_result = (uschar *)SPF_strresult(spf_output.result);
+ spf_smtp_comment = spf_output.smtp_comment ? (uschar *)spf_output.smtp_comment : NULL;
+
+ rc = spf_output.result;
+
+ /* We got a result. Now see if we should return OK or FAIL for it */
+ SPF_EVALUATE:
+ debug_printf("SPF result is %s (%d)\n", SPF_strresult(rc), rc);
+ while ((spf_result_id = string_nextinlist(&list, &sep,
+ spf_result_id_buffer,
+ sizeof(spf_result_id_buffer))) != NULL) {
+ int negate = 0;
+ int result = 0;
+
+ /* Check for negation */
+ if (spf_result_id[0] == '!') {
+ negate = 1;
+ spf_result_id++;
+ };
+
+ /* Check the result identifier */
+ result = Ustrcmp(spf_result_id, spf_result_id_list[rc].name);
+ if (!negate && result==0) return OK;
+ if (negate && result!=0) return OK;
+ };
+
+ /* no match */
+ return FAIL;
+}
+
+#endif
+
--- /dev/null
+/* $Cambridge: exim/src/src/spf.h,v 1.1.2.1 2004/12/10 09:24:38 tom Exp $ */
+
+/*************************************************
+* Exim - an Internet mail transport agent *
+*************************************************/
+
+/* Experimental SPF support.
+ Copyright (c) Tom Kistner <tom@duncanthrax.net> 2004
+ License: GPL */
+
+#ifdef EXPERIMENTAL_SPF
+
+#include <spf2/spf.h>
+#include <spf2/spf_dns_resolv.h>
+#include <spf2/spf_dns_cache.h>
+
+typedef struct spf_result_id {
+ uschar *name;
+ int value;
+} spf_result_id;
+
+/* must be kept in numeric order */
+static spf_result_id spf_result_id_list[] = {
+ { US"pass", 0 },
+ { US"fail", 1 },
+ { US"softfail", 2 },
+ { US"neutral", 3 },
+ { US"err_perm", 4 },
+ { US"err_temp", 5 },
+ { US"none", 6 }
+};
+
+static int spf_result_id_list_size = sizeof(spf_result_id_list)/sizeof(spf_result_id);
+
+/* prototypes */
+int spf_init(uschar *,uschar *);
+int spf_process(uschar **, uschar *);
+
+#endif
--- /dev/null
+/* $Cambridge: exim/src/src/srs.c,v 1.1.2.1 2004/12/10 09:24:38 tom Exp $ */
+
+/*************************************************
+* Exim - an Internet mail transport agent *
+*************************************************/
+
+/* SRS - Sender rewriting scheme support
+ ©2004 Miles Wilton <miles@mirtol.com>
+ License: GPL */
+
+#include "exim.h"
+#ifdef EXPERIMENTAL_SRS
+
+#include <srs_alt.h>
+#include "srs.h"
+
+srs_t *srs = NULL;
+uschar *srs_db_forward = NULL;
+uschar *srs_db_reverse = NULL;
+
+
+/* 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;
+ uschar *list = srs_config;
+ char secret_buf[SRS_MAX_SECRET_LENGTH];
+ char *secret;
+ char sbuf[4];
+ char *sbufp;
+ int hashlen, maxage;
+
+
+ if(!srs)
+ {
+ // Check config
+ if(!srs_config)
+ {
+ log_write(0, LOG_MAIN | LOG_PANIC,
+ "SRS Configuration Error");
+ return DEFER;
+ }
+
+ // Get config
+ co = 0;
+ if((secret = string_nextinlist(&list, &co, secret_buf,
+ SRS_MAX_SECRET_LENGTH)) == NULL)
+ {
+ log_write(0, LOG_MAIN | LOG_PANIC,
+ "SRS Configuration Error: No secret specified");
+ return DEFER;
+ }
+
+ if((sbufp = string_nextinlist(&list, &co, sbuf, sizeof(sbuf))) == NULL)
+ maxage = 31;
+ else
+ maxage = atoi(sbuf);
+ if(maxage < 0 || maxage > 365)
+ {
+ log_write(0, LOG_MAIN | LOG_PANIC,
+ "SRS Configuration Error: Invalid maximum timestamp age");
+ return DEFER;
+ }
+
+ if((sbufp = string_nextinlist(&list, &co, sbuf, sizeof(sbuf))) == NULL)
+ hashlen = 6;
+ else
+ hashlen = atoi(sbuf);
+ if(hashlen < 1 || hashlen > 20)
+ {
+ log_write(0, LOG_MAIN | LOG_PANIC,
+ "SRS Configuration Error: Invalid hash length");
+ return DEFER;
+ }
+
+
+ if((srs = srs_open(secret, strnlen(secret, SRS_MAX_SECRET_LENGTH),
+ maxage, hashlen, hashlen)) == NULL)
+ {
+ log_write(0, LOG_MAIN | LOG_PANIC,
+ "Failed to allocate SRS memory");
+ return DEFER;
+ }
+
+
+ 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));
+
+ DEBUG(D_any)
+ debug_printf("SRS initialized\n");
+ }
+
+ return OK;
+}
+
+
+int eximsrs_done()
+{
+ if(srs)
+ srs_close(srs);
+
+ srs = NULL;
+
+ return OK;
+}
+
+
+int eximsrs_forward(uschar **result, uschar *orig_sender, uschar *domain)
+{
+ char res[512];
+ int n;
+
+ if((n = srs_forward(srs, orig_sender, domain, res, sizeof(res))) & SRS_RESULT_FAIL)
+ {
+ DEBUG(D_any)
+ debug_printf("srs_forward failed (%s, %s): %s\n", orig_sender, domain, srs_geterrormsg(n));
+ return DEFER;
+ }
+
+ *result = string_copy(res);
+ return OK;
+}
+
+
+int eximsrs_reverse(uschar **result, uschar *address)
+{
+ char res[512];
+ int n;
+
+ if((n = srs_reverse(srs, address, res, sizeof(res))) & SRS_RESULT_FAIL)
+ {
+ DEBUG(D_any)
+ debug_printf("srs_reverse failed (%s): %s\n", address, srs_geterrormsg(n));
+ if(n == SRS_RESULT_NOTSRS || n == SRS_RESULT_BADSRS)
+ return DECLINE;
+ if(n == SRS_RESULT_BADHASH || n == SRS_RESULT_BADTIMESTAMP || n == SRS_RESULT_TIMESTAMPEXPIRED)
+ return FAIL;
+ return DEFER;
+ }
+
+ *result = string_copy(res);
+ return OK;
+}
+
+
+int eximsrs_db_set(BOOL reverse, uschar *srs_db)
+{
+ if(reverse)
+ 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_result eximsrs_db_insert(srs_t *srs, char *data, uint data_len, char *result, uint result_len)
+{
+ uschar *res;
+ char buf[64];
+
+ 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_result eximsrs_db_lookup(srs_t *srs, char *data, uint data_len, char *result, uint result_len)
+{
+ uschar *res;
+
+ 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;
+}
+
+
+#endif
+
--- /dev/null
+/* $Cambridge: exim/src/src/srs.h,v 1.1.2.1 2004/12/10 09:24:38 tom Exp $ */
+
+/*************************************************
+* Exim - an Internet mail transport agent *
+*************************************************/
+
+/* SRS - Sender rewriting scheme support
+ ©2004 Miles Wilton <miles@mirtol.com>
+ License: GPL */
+
+#ifndef __SRS_H__
+
+#define __SRS_H__ 1
+
+#ifdef EXPERIMENTAL_SRS
+
+#include "mytypes.h"
+#include <srs_alt.h>
+
+int eximsrs_init();
+int eximsrs_done();
+int eximsrs_forward(uschar **result, uschar *orig_sender, uschar *domain);
+int eximsrs_reverse(uschar **result, uschar *address);
+int eximsrs_db(BOOL reverse, uschar *srs_db);
+
+srs_result eximsrs_db_insert(srs_t *srs, char *data, uint data_len, char *result, uint result_len);
+srs_result eximsrs_db_lookup(srs_t *srs, char *data, uint data_len, char *result, uint result_len);
+
+#endif
+
+#endif