tom 2005/03/08 15:32:02 GMT
Modified files:
exim-src/OS Makefile-Base
exim-src/scripts MakeLinks
exim-src/src acl.c config.h.defaults exim.c exim.h
expand.c functions.h globals.c globals.h
mime.c receive.c smtp_in.c spool_in.c
transport.c
exim-src/src/transports smtp.c smtp.h
Added files:
exim-src/src dk.c dk.h
Log:
Added DomainKeys support. See doc/experimental-spec.txt for documentation.
Revision Changes Path
1.4 +3 -3 exim/exim-src/OS/Makefile-Base
1.3 +2 -0 exim/exim-src/scripts/MakeLinks
1.20 +183 -1 exim/exim-src/src/acl.c
1.5 +1 -0 exim/exim-src/src/config.h.defaults
1.1 +418 -0 exim/exim-src/src/dk.c (new)
1.1 +51 -0 exim/exim-src/src/dk.h (new)
1.15 +3 -0 exim/exim-src/src/exim.c
1.8 +3 -0 exim/exim-src/src/exim.h
1.14 +60 -0 exim/exim-src/src/expand.c
1.12 +5 -0 exim/exim-src/src/functions.h
1.19 +6 -0 exim/exim-src/src/globals.c
1.12 +6 -0 exim/exim-src/src/globals.h
1.5 +13 -8 exim/exim-src/src/mime.c
1.12 +29 -14 exim/exim-src/src/receive.c
1.12 +3 -0 exim/exim-src/src/smtp_in.c
1.9 +4 -0 exim/exim-src/src/spool_in.c
1.5 +158 -0 exim/exim-src/src/transport.c
1.7 +39 -0 exim/exim-src/src/transports/smtp.c
1.5 +8 -0 exim/exim-src/src/transports/smtp.h
Index: Makefile-Base
===================================================================
RCS file: /home/cvs/exim/exim-src/OS/Makefile-Base,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- Makefile-Base 17 Feb 2005 11:58:25 -0000 1.3
+++ Makefile-Base 8 Mar 2005 15:32:02 -0000 1.4
@@ -1,4 +1,4 @@
-# $Cambridge: exim/exim-src/OS/Makefile-Base,v 1.3 2005/02/17 11:58:25 ph10 Exp $
+# $Cambridge: exim/exim-src/OS/Makefile-Base,v 1.4 2005/03/08 15:32:02 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
@@ -290,7 +290,7 @@
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
+OBJ_EXPERIMENTAL = bmi_spam.o spf.o srs.o dk.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.
@@ -455,7 +455,7 @@
# Compile instructions for perl.o for when EXIM_PERL is set
perl.o: $(HDRS) perl.c
- $(PERL_CC) $(PERL_CCOPTS) $(INCLUDE) -c perl.c
+ $(PERL_CC) $(PERL_CCOPTS) $(CFLAGS) $(INCLUDE) -c perl.c
# Compile instructions for the database utility modules
@@ -575,7 +575,7 @@
bmi_spam.o: $(HDRS) bmi_spam.c
spf.o: $(HDRS) spf.c
srs.o: $(HDRS) srs.c
-
+dk.o: $(HDRS) dk.c
# The module containing tables of available lookups, routers, auths, and
# transports must be rebuilt if any of them are. However, because the makefiles
Index: MakeLinks
===================================================================
RCS file: /home/cvs/exim/exim-src/scripts/MakeLinks,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- MakeLinks 16 Dec 2004 15:11:47 -0000 1.2
+++ MakeLinks 8 Mar 2005 15:32:02 -0000 1.3
@@ -1,5 +1,5 @@
#!/bin/sh
-# $Cambridge: exim/exim-src/scripts/MakeLinks,v 1.2 2004/12/16 15:11:47 tom Exp $
+# $Cambridge: exim/exim-src/scripts/MakeLinks,v 1.3 2005/03/08 15:32:02 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.
@@ -261,5 +261,7 @@
ln -s ../src/spf.h spf.h
ln -s ../src/srs.c srs.c
ln -s ../src/srs.h srs.h
+ln -s ../src/dk.c dk.c
+ln -s ../src/dk.h dk.h
# End of MakeLinks
Index: dk.c
====================================================================
/* $Cambridge: exim/exim-src/src/dk.c,v 1.1 2005/03/08 15:32:02 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
/* Copyright (c) University of Cambridge 1995 - 2005 */
/* See the file NOTICE for conditions of use and distribution. */
/* Code for DomainKeys support. Other DK relevant code is in
receive.c, transport.c and transports/smtp.c */
#include "exim.h"
#ifdef EXPERIMENTAL_DOMAINKEYS
/* Globals related to the DK reference library. */
DK *dk_context = NULL;
DK_LIB *dk_lib = NULL;
DK_FLAGS dk_flags;
DK_STAT dk_internal_status;
/* Globals related to Exim DK implementation. */
dk_exim_verify_block *dk_verify_block = NULL;
/* Global char buffer for getc/ungetc functions. We need
to accumulate some chars to be able to match EOD and
doubled SMTP dots. Those must not be fed to the validation
engine. */
int dkbuff[6] = {256,256,256,256,256,256};
/* receive_getc() wrapper that feeds DK while Exim reads
the message. */
int dk_receive_getc(void) {
int i;
int c = receive_getc();
if (dk_context != NULL) {
/* Send oldest byte */
if ((dkbuff[0] < 256) && (dk_internal_status == DK_STAT_OK)) {
dk_internal_status = dk_message(dk_context, (char *)&dkbuff[0], 1);
if (dk_internal_status != DK_STAT_OK)
DEBUG(D_receive) debug_printf("DK: %s\n", DK_STAT_to_string(dk_internal_status));
}
/* rotate buffer */
for (i=0;i<5;i++) dkbuff[i]=dkbuff[i+1];
dkbuff[5]=c;
/* look for our candidate patterns */
if ( (dkbuff[1] == '\r') &&
(dkbuff[2] == '\n') &&
(dkbuff[3] == '.') &&
(dkbuff[4] == '\r') &&
(dkbuff[5] == '\n') ) {
/* End of DATA */
dkbuff[3] = 256;
dkbuff[4] = 256;
dkbuff[5] = 256;
}
if ( (dkbuff[2] == '\r') &&
(dkbuff[3] == '\n') &&
(dkbuff[4] == '.') &&
(dkbuff[5] == '.') ) {
/* doubled dot, skip this char */
dkbuff[5] = 256;
}
}
return c;
}
/* When exim puts a char back in the fd, we
must rotate our buffer back. */
int dk_receive_ungetc(int c) {
int i;
if (dk_context != NULL) {
/* rotate buffer back */
for (i=5;i>0;i--) dkbuff[i]=dkbuff[i-1];
dkbuff[0]=256;
}
return receive_ungetc(c);
}
void dk_exim_verify_init(void) {
int old_pool = store_pool;
store_pool = POOL_PERM;
/* Reset DK state in any case. */
dk_context = NULL;
dk_lib = NULL;
dk_verify_block = NULL;
/* Set up DK context if DK was requested and input is SMTP. */
if (smtp_input && !smtp_batched_input && dk_do_verify) {
/* initialize library */
dk_lib = dk_init(&dk_internal_status);
if (dk_internal_status != DK_STAT_OK)
debug_printf("DK: %s\n", DK_STAT_to_string(dk_internal_status));
else {
/* initialize verification context */
dk_context = dk_verify(dk_lib, &dk_internal_status);
if (dk_internal_status != DK_STAT_OK) {
debug_printf("DK: %s\n", DK_STAT_to_string(dk_internal_status));
dk_context = NULL;
}
else {
/* Reserve some space for the verify block. */
dk_verify_block = store_get(sizeof(dk_exim_verify_block));
if (dk_verify_block == NULL) {
debug_printf("DK: Can't allocate %d bytes.\n",sizeof(dk_exim_verify_block));
dk_context = NULL;
}
else {
memset(dk_verify_block, 0, sizeof(dk_exim_verify_block));
}
}
}
}
store_pool = old_pool;
}
void dk_exim_verify_finish(void) {
char *p,*q;
int i;
int old_pool = store_pool;
/* Bail out if context could not be set up earlier. */
if (dk_context == NULL)
return;
store_pool = POOL_PERM;
/* Send remaining bytes from input which are still in the buffer. */
for (i=0;i<6;i++)
if (dkbuff[i] < 256)
dk_internal_status = dk_message(dk_context, (char *)&dkbuff[i], 1);
/* Flag end-of-message. */
dk_internal_status = dk_end(dk_context, NULL);
/* Grab address/domain information. */
p = dk_address(dk_context);
if (p != NULL) {
switch(p[0]) {
case 'N':
dk_verify_block->address_source = DK_EXIM_ADDRESS_NONE;
break;
case 'S':
dk_verify_block->address_source = DK_EXIM_ADDRESS_FROM_SENDER;
break;
case 'F':
dk_verify_block->address_source = DK_EXIM_ADDRESS_FROM_FROM;
break;
}
p++;
if (*p != '\0') {
dk_verify_block->address = string_copy((uschar *)p);
q = strrchr(p,'@');
if ((q != NULL) && (*(q+1) != '\0')) {
dk_verify_block->domain = string_copy((uschar *)(q+1));
*q = '\0';
dk_verify_block->local_part = string_copy((uschar *)p);
}
}
}
dk_flags = dk_policy(dk_context);
/* Grab domain policy */
if (dk_flags & DK_FLAG_SET) {
if (dk_flags & DK_FLAG_TESTING)
dk_verify_block->testing = TRUE;
if (dk_flags & DK_FLAG_SIGNSALL)
dk_verify_block->signsall = TRUE;
}
/* Set up main result. */
switch(dk_internal_status)
{
case DK_STAT_NOSIG:
dk_verify_block->is_signed = FALSE;
dk_verify_block->result = DK_EXIM_RESULT_NO_SIGNATURE;
break;
case DK_STAT_OK:
dk_verify_block->is_signed = TRUE;
dk_verify_block->result = DK_EXIM_RESULT_GOOD;
break;
case DK_STAT_BADSIG:
dk_verify_block->is_signed = TRUE;
dk_verify_block->result = DK_EXIM_RESULT_BAD;
break;
case DK_STAT_REVOKED:
dk_verify_block->is_signed = TRUE;
dk_verify_block->result = DK_EXIM_RESULT_REVOKED;
break;
case DK_STAT_BADKEY:
case DK_STAT_SYNTAX:
dk_verify_block->is_signed = TRUE;
/* Syntax -> Bad format? */
dk_verify_block->result = DK_EXIM_RESULT_BAD_FORMAT;
break;
case DK_STAT_NOKEY:
dk_verify_block->is_signed = TRUE;
dk_verify_block->result = DK_EXIM_RESULT_NO_KEY;
break;
case DK_STAT_NORESOURCE:
case DK_STAT_INTERNAL:
case DK_STAT_ARGS:
case DK_STAT_CANTVRFY:
dk_verify_block->result = DK_EXIM_RESULT_ERR;
break;
/* This is missing DK_EXIM_RESULT_NON_PARTICIPANT. The lib does not
report such a status. */
}
/* Set up human readable result string. */
dk_verify_block->result_string = string_copy((uschar *)DK_STAT_to_string(dk_internal_status));
/* All done, reset dk_context. */
dk_free(dk_context);
dk_context = NULL;
store_pool = old_pool;
}
uschar *dk_exim_sign(int dk_fd,
uschar *dk_private_key,
uschar *dk_domain,
uschar *dk_selector,
uschar *dk_canon) {
uschar *rc = NULL;
int dk_canon_int = DK_CANON_SIMPLE;
char c;
int seen_lf = 0;
int seen_lfdot = 0;
uschar sig[1024];
int save_errno = 0;
int sread;
int old_pool = store_pool;
store_pool = POOL_PERM;
dk_lib = dk_init(&dk_internal_status);
if (dk_internal_status != DK_STAT_OK) {
debug_printf("DK: %s\n", DK_STAT_to_string(dk_internal_status));
rc = NULL;
goto CLEANUP;
}
/* Figure out what canonicalization to use. Unfortunately
we must do this BEFORE knowing which domain we sign for. */
if ((dk_canon != NULL) && (Ustrcmp(dk_canon, "nofws") == 0)) dk_canon_int = DK_CANON_NOFWS;
else dk_canon = "simple";
/* Initialize signing context. */
dk_context = dk_sign(dk_lib, &dk_internal_status, dk_canon_int);
if (dk_internal_status != DK_STAT_OK) {
debug_printf("DK: %s\n", DK_STAT_to_string(dk_internal_status));
dk_context = NULL;
goto CLEANUP;
}
while((sread = read(dk_fd,&c,1)) > 0) {
if ((c == '.') && seen_lfdot) {
/* escaped dot, write "\n.", continue */
dk_message(dk_context, "\n.", 2);
seen_lf = 0;
seen_lfdot = 0;
continue;
}
if (seen_lfdot) {
/* EOM, write "\n" and break */
dk_message(dk_context, "\n", 1);
break;
}
if ((c == '.') && seen_lf) {
seen_lfdot = 1;
continue;
}
if (seen_lf) {
/* normal lf, just send it */
dk_message(dk_context, "\n", 1);
seen_lf = 0;
}
if (c == '\n') {
seen_lf = 1;
continue;
}
/* write the char */
dk_message(dk_context, &c, 1);
}
/* Handle failed read above. */
if (sread == -1) {
debug_printf("DK: Error reading -K file.\n");
save_errno = errno;
rc = NULL;
goto CLEANUP;
}
/* Flag end-of-message. */
dk_internal_status = dk_end(dk_context, NULL);
/* TODO: check status */
/* Get domain to use, unless overridden. */
if (dk_domain == NULL) {
dk_domain = dk_address(dk_context);
switch(dk_domain[0]) {
case 'N': dk_domain = NULL; break;
case 'F':
case 'S':
dk_domain++;
dk_domain = strrchr(dk_domain,'@');
if (dk_domain != NULL) {
uschar *p;
dk_domain++;
p = dk_domain;
while (*p != 0) { *p = tolower(*p); p++; }
}
break;
}
if (dk_domain == NULL) {
debug_printf("DK: Could not determine domain to use for signing from message headers.\n");
/* In this case, we return "OK" by sending up an empty string as the
DomainKey-Signature header. If there is no domain to sign for, we
can send the message anyway since the recipient has no policy to
apply ... */
rc = "";
goto CLEANUP;
}
}
else {
dk_domain = expand_string(dk_domain);
if (dk_domain == NULL) {
/* expansion error, do not send message. */
debug_printf("DK: Error while expanding dk_domain option.\n");
rc = NULL;
goto CLEANUP;
}
}
/* Set up $dk_domain expansion variable. */
dk_signing_domain = dk_domain;
/* Get selector to use. */
dk_selector = expand_string(dk_selector);
if (dk_selector == NULL) {
log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand "
"dk_selector: %s", expand_string_message);
rc = NULL;
goto CLEANUP;
}
/* Set up $dk_selector expansion variable. */
dk_signing_selector = dk_selector;
/* Get private key to use. */
dk_private_key = expand_string(dk_private_key);
if (dk_private_key == NULL) {
log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand "
"dk_private_key: %s", expand_string_message);
rc = NULL;
goto CLEANUP;
}
if ( (Ustrlen(dk_private_key) == 0) ||
(Ustrcmp(dk_private_key,"0") == 0) ||
(Ustrcmp(dk_private_key,"false") == 0) ) {
/* don't sign, but no error */
rc = "";
goto CLEANUP;
}
if (dk_private_key[0] == '/') {
int privkey_fd = 0;
/* Looks like a filename, load the private key. */
memset(big_buffer,0,big_buffer_size);
privkey_fd = open(dk_private_key,O_RDONLY);
read(privkey_fd,big_buffer,16383);
close(privkey_fd);
dk_private_key = big_buffer;
}
/* Get the signature. */
dk_internal_status = dk_getsig(dk_context, dk_private_key, sig, 8192);
/* Check for unuseable key */
if (dk_internal_status != DK_STAT_OK) {
debug_printf("DK: %s\n", DK_STAT_to_string(dk_internal_status));
rc = NULL;
goto CLEANUP;
}
rc = store_get(1024);
/* Build DomainKey-Signature header to return. */
snprintf(rc, 1024, "DomainKey-Signature: a=rsa-sha1; q=dns; c=%s;\r\n"
"\ts=%s; d=%s;\r\n"
"\tb=%s;\r\n", dk_canon, dk_selector, dk_domain, sig);
log_write(0, LOG_MAIN, "DK: message signed using a=rsa-sha1; q=dns; c=%s; s=%s; d=%s;", dk_canon, dk_selector, dk_domain);
CLEANUP:
if (dk_context != NULL) {
dk_free(dk_context);
dk_context = NULL;
}
store_pool = old_pool;
errno = save_errno;
return rc;
}
#endif
Index: dk.h
====================================================================
/* $Cambridge: exim/exim-src/src/dk.h,v 1.1 2005/03/08 15:32:02 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
/* Copyright (c) University of Cambridge 1995 - 2005 */
/* See the file NOTICE for conditions of use and distribution. */
/* Code for DomainKeys support. Other DK relevant code is in
receive.c, transport.c and transports/smtp.c */
#ifdef EXPERIMENTAL_DOMAINKEYS
#include <domainkeys.h>
#define DK_EXIM_ADDRESS_NONE 0
#define DK_EXIM_ADDRESS_FROM_FROM 1
#define DK_EXIM_ADDRESS_FROM_SENDER 2
#define DK_EXIM_RESULT_ERR 0
#define DK_EXIM_RESULT_BAD_FORMAT 1
#define DK_EXIM_RESULT_NO_KEY 2
#define DK_EXIM_RESULT_NO_SIGNATURE 3
#define DK_EXIM_RESULT_REVOKED 4
#define DK_EXIM_RESULT_NON_PARTICIPANT 5
#define DK_EXIM_RESULT_GOOD 6
#define DK_EXIM_RESULT_BAD 7
typedef struct dk_exim_verify_block {
int result;
int address_source;
uschar *result_string;
uschar *address;
uschar *domain;
uschar *local_part;
BOOL is_signed;
BOOL signsall;
BOOL testing;
} dk_exim_verify_block;
int dk_receive_getc(void);
int dk_receive_ungetc(int);
void dk_exim_verify_init(void);
void dk_exim_verify_finish(void);
int dk_exim_verify_result(uschar **);
uschar *dk_exim_sign(int, uschar *, uschar *, uschar *, uschar *);
extern dk_exim_verify_block *dk_verify_block;
#endif
Index: acl.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/acl.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- acl.c 17 Feb 2005 11:58:25 -0000 1.19
+++ acl.c 8 Mar 2005 15:32:02 -0000 1.20
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/acl.c,v 1.19 2005/02/17 11:58:25 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/acl.c,v 1.20 2005/03/08 15:32:02 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -46,6 +46,14 @@
#ifdef WITH_OLD_DEMIME
ACLC_DEMIME,
#endif
+#ifdef EXPERIMENTAL_DOMAINKEYS
+ ACLC_DK_DOMAIN_SOURCE,
+ ACLC_DK_POLICY,
+ ACLC_DK_SENDER_DOMAINS,
+ ACLC_DK_SENDER_LOCAL_PARTS,
+ ACLC_DK_SENDERS,
+ ACLC_DK_STATUS,
+#endif
ACLC_DNSLISTS, ACLC_DOMAINS, ACLC_ENCRYPTED, ACLC_ENDPASS,
ACLC_HOSTS, ACLC_LOCAL_PARTS, ACLC_LOG_MESSAGE, ACLC_LOGWRITE,
#ifdef WITH_CONTENT_SCAN
@@ -85,6 +93,14 @@
#ifdef WITH_OLD_DEMIME
US"demime",
#endif
+#ifdef EXPERIMENTAL_DOMAINKEYS
+ US"dk_domain_source",
+ US"dk_policy",
+ US"dk_sender_domains",
+ US"dk_sender_local_parts",
+ US"dk_senders",
+ US"dk_status",
+#endif
US"dnslists", US"domains", US"encrypted",
US"endpass", US"hosts", US"local_parts", US"log_message", US"logwrite",
#ifdef WITH_CONTENT_SCAN
@@ -132,6 +148,14 @@
#ifdef WITH_OLD_DEMIME
TRUE, /* demime */
#endif
+#ifdef EXPERIMENTAL_DOMAINKEYS
+ TRUE,
+ TRUE,
+ TRUE,
+ TRUE,
+ TRUE,
+ TRUE,
+#endif
TRUE, /* dnslists */
FALSE, /* domains */
FALSE, /* encrypted */
@@ -180,6 +204,14 @@
#ifdef WITH_OLD_DEMIME
FALSE, /* demime */
#endif
+#ifdef EXPERIMENTAL_DOMAINKEYS
+ FALSE,
+ FALSE,
+ FALSE,
+ FALSE,
+ FALSE,
+ FALSE,
+#endif
FALSE, /* dnslists */
FALSE, /* domains */
FALSE, /* encrypted */
@@ -259,6 +291,56 @@
(1<<ACL_WHERE_VRFY)|(1<<ACL_WHERE_MIME),
#endif
+#ifdef EXPERIMENTAL_DOMAINKEYS
+ (1<<ACL_WHERE_AUTH)|
+ (1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
+ (1<<ACL_WHERE_RCPT)|(1<<ACL_WHERE_PREDATA)|
+ (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
+ (1<<ACL_WHERE_MAILAUTH)|(1<<ACL_WHERE_QUIT)|
+ (1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
+ (1<<ACL_WHERE_VRFY),
+
+ (1<<ACL_WHERE_AUTH)|
+ (1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
+ (1<<ACL_WHERE_RCPT)|(1<<ACL_WHERE_PREDATA)|
+ (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
+ (1<<ACL_WHERE_MAILAUTH)|(1<<ACL_WHERE_QUIT)|
+ (1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
+ (1<<ACL_WHERE_VRFY),
+
+ (1<<ACL_WHERE_AUTH)|
+ (1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
+ (1<<ACL_WHERE_RCPT)|(1<<ACL_WHERE_PREDATA)|
+ (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
+ (1<<ACL_WHERE_MAILAUTH)|(1<<ACL_WHERE_QUIT)|
+ (1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
+ (1<<ACL_WHERE_VRFY),
+
+ (1<<ACL_WHERE_AUTH)|
+ (1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
+ (1<<ACL_WHERE_RCPT)|(1<<ACL_WHERE_PREDATA)|
+ (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
+ (1<<ACL_WHERE_MAILAUTH)|(1<<ACL_WHERE_QUIT)|
+ (1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
+ (1<<ACL_WHERE_VRFY),
+
+ (1<<ACL_WHERE_AUTH)|
+ (1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
+ (1<<ACL_WHERE_RCPT)|(1<<ACL_WHERE_PREDATA)|
+ (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
+ (1<<ACL_WHERE_MAILAUTH)|(1<<ACL_WHERE_QUIT)|
+ (1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
+ (1<<ACL_WHERE_VRFY),
+
+ (1<<ACL_WHERE_AUTH)|
+ (1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
+ (1<<ACL_WHERE_RCPT)|(1<<ACL_WHERE_PREDATA)|
+ (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
+ (1<<ACL_WHERE_MAILAUTH)|(1<<ACL_WHERE_QUIT)|
+ (1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
+ (1<<ACL_WHERE_VRFY),
+#endif
+
(1<<ACL_WHERE_NOTSMTP), /* dnslists */
(1<<ACL_WHERE_NOTSMTP)|(1<<ACL_WHERE_AUTH)| /* domains */
@@ -373,6 +455,9 @@
#ifdef EXPERIMENTAL_BRIGHTMAIL
CONTROL_BMI_RUN,
#endif
+#ifdef EXPERIMENTAL_DOMAINKEYS
+ CONTROL_DK_VERIFY,
+#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,
@@ -389,6 +474,9 @@
#ifdef EXPERIMENTAL_BRIGHTMAIL
0, /* bmi_run */
#endif
+#ifdef EXPERIMENTAL_DOMAINKEYS
+ (1<<ACL_WHERE_PREDATA)|(1<<ACL_WHERE_DATA), /* dk_verify */
+#endif
0, /* error */
@@ -441,6 +529,9 @@
#ifdef EXPERIMENTAL_BRIGHTMAIL
{ US"bmi_run", CONTROL_BMI_RUN, FALSE},
#endif
+#ifdef EXPERIMENTAL_DOMAINKEYS
+ { US"dk_verify", CONTROL_DK_VERIFY, FALSE},
+#endif
{ US"caseful_local_part", CONTROL_CASEFUL_LOCAL_PART, FALSE},
{ US"caselower_local_part", CONTROL_CASELOWER_LOCAL_PART, FALSE},
{ US"enforce_sync", CONTROL_ENFORCE_SYNC, FALSE},
@@ -1648,7 +1739,11 @@
bmi_run = 1;
break;
#endif
-
+#ifdef EXPERIMENTAL_DOMAINKEYS
+ case CONTROL_DK_VERIFY:
+ dk_do_verify = 1;
+ break;
+#endif
case CONTROL_ERROR:
return ERROR;
@@ -1767,6 +1862,93 @@
case ACLC_DEMIME:
rc = demime(&arg);
break;
+#endif
+
+#ifdef EXPERIMENTAL_DOMAINKEYS
+ case ACLC_DK_DOMAIN_SOURCE:
+ if (dk_verify_block == NULL) { rc = FAIL; break; };
+ /* check header source of domain against given string */
+ switch (dk_verify_block->address_source) {
+ case DK_EXIM_ADDRESS_FROM_FROM:
+ rc = match_isinlist(US"from", &arg, 0, NULL,
+ NULL, MCL_STRING, TRUE, NULL);
+ break;
+ case DK_EXIM_ADDRESS_FROM_SENDER:
+ rc = match_isinlist(US"sender", &arg, 0, NULL,
+ NULL, MCL_STRING, TRUE, NULL);
+ break;
+ case DK_EXIM_ADDRESS_NONE:
+ rc = match_isinlist(US"none", &arg, 0, NULL,
+ NULL, MCL_STRING, TRUE, NULL);
+ break;
+ }
+ break;
+ case ACLC_DK_POLICY:
+ if (dk_verify_block == NULL) { rc = FAIL; break; };
+ /* check policy against given string, default FAIL */
+ rc = FAIL;
+ if (dk_verify_block->signsall)
+ rc = match_isinlist(US"signsall", &arg, 0, NULL,
+ NULL, MCL_STRING, TRUE, NULL);
+ if (dk_verify_block->testing)
+ rc = match_isinlist(US"testing", &arg, 0, NULL,
+ NULL, MCL_STRING, TRUE, NULL);
+ break;
+ case ACLC_DK_SENDER_DOMAINS:
+ if (dk_verify_block == NULL) { rc = FAIL; break; };
+ if (dk_verify_block->domain != NULL)
+ rc = match_isinlist(dk_verify_block->domain, &arg, 0, &domainlist_anchor,
+ NULL, MCL_DOMAIN, TRUE, NULL);
+ else rc = FAIL;
+ break;
+ case ACLC_DK_SENDER_LOCAL_PARTS:
+ if (dk_verify_block == NULL) { rc = FAIL; break; };
+ if (dk_verify_block->local_part != NULL)
+ rc = match_isinlist(dk_verify_block->local_part, &arg, 0, &localpartlist_anchor,
+ NULL, MCL_LOCALPART, TRUE, NULL);
+ else rc = FAIL;
+ break;
+ case ACLC_DK_SENDERS:
+ if (dk_verify_block == NULL) { rc = FAIL; break; };
+ if (dk_verify_block->address != NULL)
+ rc = match_address_list(dk_verify_block->address, TRUE, TRUE, &arg, NULL, -1, 0, NULL);
+ else rc = FAIL;
+ break;
+ case ACLC_DK_STATUS:
+ if (dk_verify_block == NULL) { rc = FAIL; break; };
+ if (dk_verify_block->result > 0) {
+ switch(dk_verify_block->result) {
+ case DK_EXIM_RESULT_BAD_FORMAT:
+ rc = match_isinlist(US"bad format", &arg, 0, NULL,
+ NULL, MCL_STRING, TRUE, NULL);
+ break;
+ case DK_EXIM_RESULT_NO_KEY:
+ rc = match_isinlist(US"no key", &arg, 0, NULL,
+ NULL, MCL_STRING, TRUE, NULL);
+ break;
+ case DK_EXIM_RESULT_NO_SIGNATURE:
+ rc = match_isinlist(US"no signature", &arg, 0, NULL,
+ NULL, MCL_STRING, TRUE, NULL);
+ break;
+ case DK_EXIM_RESULT_REVOKED:
+ rc = match_isinlist(US"revoked", &arg, 0, NULL,
+ NULL, MCL_STRING, TRUE, NULL);
+ break;
+ case DK_EXIM_RESULT_NON_PARTICIPANT:
+ rc = match_isinlist(US"non-participant", &arg, 0, NULL,
+ NULL, MCL_STRING, TRUE, NULL);
+ break;
+ case DK_EXIM_RESULT_GOOD:
+ rc = match_isinlist(US"good", &arg, 0, NULL,
+ NULL, MCL_STRING, TRUE, NULL);
+ break;
+ case DK_EXIM_RESULT_BAD:
+ rc = match_isinlist(US"bad", &arg, 0, NULL,
+ NULL, MCL_STRING, TRUE, NULL);
+ break;
+ }
+ }
+ break;
#endif
case ACLC_DNSLISTS:
Index: config.h.defaults
===================================================================
RCS file: /home/cvs/exim/exim-src/src/config.h.defaults,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- config.h.defaults 4 Jan 2005 10:00:42 -0000 1.4
+++ config.h.defaults 8 Mar 2005 15:32:02 -0000 1.5
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/config.h.defaults,v 1.4 2005/01/04 10:00:42 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/config.h.defaults,v 1.5 2005/03/08 15:32:02 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -144,6 +144,7 @@
/* EXPERIMENTAL features */
#define EXPERIMENTAL_SPF
#define EXPERIMENTAL_SRS
+#define EXPERIMENTAL_DOMAINKEYS
#define EXPERIMENTAL_BRIGHTMAIL
/* Things that are not routinely changed but are nevertheless configurable
Index: exim.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/exim.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- exim.c 17 Feb 2005 11:58:26 -0000 1.14
+++ exim.c 8 Mar 2005 15:32:02 -0000 1.15
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/exim.c,v 1.14 2005/02/17 11:58:26 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/exim.c,v 1.15 2005/03/08 15:32:02 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -853,6 +853,9 @@
#endif
#ifdef EXPERIMENTAL_BRIGHTMAIL
fprintf(f, " Experimental_Brightmail");
+#endif
+#ifdef EXPERIMENTAL_DOMAINKEYS
+ fprintf(f, " Experimental_DomainKeys");
#endif
fprintf(f, "\n");
Index: exim.h
===================================================================
RCS file: /home/cvs/exim/exim-src/src/exim.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- exim.h 4 Jan 2005 10:00:42 -0000 1.7
+++ exim.h 8 Mar 2005 15:32:02 -0000 1.8
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/exim.h,v 1.7 2005/01/04 10:00:42 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/exim.h,v 1.8 2005/03/08 15:32:02 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -401,6 +401,9 @@
#endif
#ifdef EXPERIMENTAL_SRS
#include "srs.h"
+#endif
+#ifdef EXPERIMENTAL_DOMAINKEYS
+#include "dk.h"
#endif
/* The following stuff must follow the inclusion of config.h because it
Index: expand.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/expand.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- expand.c 17 Feb 2005 11:58:26 -0000 1.13
+++ expand.c 8 Mar 2005 15:32:02 -0000 1.14
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/expand.c,v 1.13 2005/02/17 11:58:26 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/expand.c,v 1.14 2005/03/08 15:32:02 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -286,6 +286,9 @@
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 */
+#ifdef EXPERIMENTAL_DOMAINKEYS
+ ,vtype_dk_verify /* Serve request out of DomainKeys verification structure */
+#endif
};
/* This table must be kept in alphabetical order. */
@@ -336,6 +339,19 @@
{ "demime_errorlevel", vtype_int, &demime_errorlevel },
{ "demime_reason", vtype_stringptr, &demime_reason },
#endif
+#ifdef EXPERIMENTAL_DOMAINKEYS
+ { "dk_domain", vtype_stringptr, &dk_signing_domain },
+ { "dk_is_signed", vtype_dk_verify, NULL },
+ { "dk_result", vtype_dk_verify, NULL },
+ { "dk_selector", vtype_stringptr, &dk_signing_selector },
+ { "dk_sender", vtype_dk_verify, NULL },
+ { "dk_sender_domain", vtype_dk_verify, NULL },
+ { "dk_sender_local_part",vtype_dk_verify, NULL },
+ { "dk_sender_source", vtype_dk_verify, NULL },
+ { "dk_signsall", vtype_dk_verify, NULL },
+ { "dk_status", vtype_dk_verify, NULL },
+ { "dk_testing", vtype_dk_verify, NULL },
+#endif
{ "dnslist_domain", vtype_stringptr, &dnslist_domain },
{ "dnslist_text", vtype_stringptr, &dnslist_text },
{ "dnslist_value", vtype_stringptr, &dnslist_value },
@@ -1237,6 +1253,50 @@
case vtype_filter_int:
if (!filter_running) return NULL;
/* Fall through */
+
+#ifdef EXPERIMENTAL_DOMAINKEYS
+
+ case vtype_dk_verify:
+ s = NULL;
+ if (Ustrcmp(var_table[middle].name, "dk_result") == 0)
+ s = dk_verify_block->result_string;
+ if (Ustrcmp(var_table[middle].name, "dk_sender") == 0)
+ s = dk_verify_block->address;
+ if (Ustrcmp(var_table[middle].name, "dk_sender_domain") == 0)
+ s = dk_verify_block->domain;
+ if (Ustrcmp(var_table[middle].name, "dk_sender_local_part") == 0)
+ s = dk_verify_block->local_part;
+
+ if (Ustrcmp(var_table[middle].name, "dk_sender_source") == 0)
+ switch(dk_verify_block->address_source) {
+ case DK_EXIM_ADDRESS_NONE: s = "0"; break;
+ case DK_EXIM_ADDRESS_FROM_FROM: s = "from"; break;
+ case DK_EXIM_ADDRESS_FROM_SENDER: s = "sender"; break;
+ }
+
+ if (Ustrcmp(var_table[middle].name, "dk_status") == 0)
+ switch(dk_verify_block->result) {
+ case DK_EXIM_RESULT_ERR: s = "error"; break;
+ case DK_EXIM_RESULT_BAD_FORMAT: s = "bad format"; break;
+ case DK_EXIM_RESULT_NO_KEY: s = "no key"; break;
+ case DK_EXIM_RESULT_NO_SIGNATURE: s = "no signature"; break;
+ case DK_EXIM_RESULT_REVOKED: s = "revoked"; break;
+ case DK_EXIM_RESULT_NON_PARTICIPANT: s = "non-participant"; break;
+ case DK_EXIM_RESULT_GOOD: s = "good"; break;
+ case DK_EXIM_RESULT_BAD: s = "bad"; break;
+ }
+
+ if (Ustrcmp(var_table[middle].name, "dk_signsall") == 0)
+ s = (dk_verify_block->signsall)? "1" : "0";
+
+ if (Ustrcmp(var_table[middle].name, "dk_testing") == 0)
+ s = (dk_verify_block->testing)? "1" : "0";
+
+ if (Ustrcmp(var_table[middle].name, "dk_is_signed") == 0)
+ s = (dk_verify_block->is_signed)? "1" : "0";
+
+ return (s == NULL)? US"" : s;
+#endif
case vtype_int:
sprintf(CS var_buffer, "%d", *(int *)(var_table[middle].value)); /* Integer */
Index: functions.h
===================================================================
RCS file: /home/cvs/exim/exim-src/src/functions.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- functions.h 17 Feb 2005 11:58:26 -0000 1.11
+++ functions.h 8 Mar 2005 15:32:02 -0000 1.12
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/functions.h,v 1.11 2005/02/17 11:58:26 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/functions.h,v 1.12 2005/03/08 15:32:02 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -72,6 +72,11 @@
extern int demime(uschar **);
#endif
extern BOOL directory_make(uschar *, uschar *, int, BOOL);
+#ifdef EXPERIMENTAL_DOMAINKEYS
+extern BOOL dk_transport_write_message(address_item *, int, int,
+ int, uschar *, uschar *, uschar *, uschar *, rewrite_rule *,
+ int, uschar *, uschar *, uschar *, uschar *, uschar *, uschar *);
+#endif
extern dns_address *dns_address_from_rr(dns_answer *, dns_record *);
extern void dns_build_reverse(uschar *, uschar *);
extern void dns_init(BOOL, BOOL);
Index: globals.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/globals.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -r1.18 -r1.19
--- globals.c 1 Mar 2005 10:21:44 -0000 1.18
+++ globals.c 8 Mar 2005 15:32:02 -0000 1.19
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/globals.c,v 1.18 2005/03/01 10:21:44 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/globals.c,v 1.19 2005/03/08 15:32:02 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -462,6 +462,12 @@
uschar *demime_reason = NULL;
#endif
BOOL disable_logging = FALSE;
+
+#ifdef EXPERIMENTAL_DOMAINKEYS
+uschar *dk_signing_domain = NULL;
+uschar *dk_signing_selector = NULL;
+int dk_do_verify = 0;
+#endif
uschar *dns_again_means_nonexist = NULL;
uschar *dns_ipv4_lookup = NULL;
Index: globals.h
===================================================================
RCS file: /home/cvs/exim/exim-src/src/globals.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- globals.h 25 Jan 2005 14:16:33 -0000 1.11
+++ globals.h 8 Mar 2005 15:32:02 -0000 1.12
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/globals.h,v 1.11 2005/01/25 14:16:33 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/globals.h,v 1.12 2005/03/08 15:32:02 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -256,6 +256,12 @@
extern uschar *demime_reason; /* Reason for broken MIME container */
#endif
extern BOOL disable_logging; /* Disables log writing when TRUE */
+
+#ifdef EXPERIMENTAL_DOMAINKEYS
+extern uschar *dk_signing_domain; /* Domain used for signing a message. */
+extern uschar *dk_signing_selector; /* Selector used for signing a message. */
+extern int dk_do_verify; /* DK verification switch. Set with ACL control statement. */
+#endif
extern uschar *dns_again_means_nonexist; /* Domains that are badly set up */
extern uschar *dns_ipv4_lookup; /* For these domains, don't look for AAAA (or A6) */
Index: mime.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/mime.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- mime.c 17 Feb 2005 11:58:26 -0000 1.4
+++ mime.c 8 Mar 2005 15:32:02 -0000 1.5
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/mime.c,v 1.4 2005/02/17 11:58:26 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/mime.c,v 1.5 2005/03/08 15:32:02 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -115,11 +115,8 @@
}
-uschar *mime_parse_line(uschar *buffer, uschar *encoding, int *num_decoded) {
- uschar *data = NULL;
-
- data = (uschar *)malloc(Ustrlen(buffer)+2);
-
+uschar *mime_parse_line(uschar *buffer, uschar *data, uschar *encoding, int *num_decoded) {
+
if (encoding == NULL) {
/* no encoding type at all */
NO_DECODING:
@@ -285,6 +282,7 @@
uschar decode_path[1024];
FILE *decode_file = NULL;
uschar *buffer = NULL;
+ uschar *decode_buffer = NULL;
long f_pos = 0;
unsigned int size_counter = 0;
@@ -296,7 +294,7 @@
/* 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 */
+ /* reserve a line and decoder buffer to work in */
buffer = (uschar *)malloc(MIME_MAX_LINE_LENGTH+1);
if (buffer == NULL) {
log_write(0, LOG_PANIC,
@@ -304,6 +302,13 @@
return DEFER;
};
+ decode_buffer = (uschar *)malloc(MIME_MAX_LINE_LENGTH+1);
+ if (decode_buffer == NULL) {
+ log_write(0, LOG_PANIC,
+ "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,
@@ -358,7 +363,8 @@
};
};
- decoded_line = mime_parse_line(buffer, mime_content_transfer_encoding, &decoded_line_length);
+ decoded_line = mime_parse_line(buffer, decode_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) {
/* error/short write */
@@ -376,7 +382,6 @@
size_counter = (size_counter % 1024);
};
- free(decoded_line);
}
fclose(decode_file);
Index: receive.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/receive.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- receive.c 17 Feb 2005 11:58:26 -0000 1.11
+++ receive.c 8 Mar 2005 15:32:02 -0000 1.12
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/receive.c,v 1.11 2005/02/17 11:58:26 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/receive.c,v 1.12 2005/03/08 15:32:02 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -9,10 +9,15 @@
/* Code for receiving a message and setting up spool files. */
-
#include "exim.h"
-
+#ifdef EXPERIMENTAL_DOMAINKEYS
+#define RECEIVE_GETC dk_receive_getc
+#define RECEIVE_UNGETC dk_receive_ungetc
+#else
+#define RECEIVE_GETC receive_getc
+#define RECEIVE_UNGETC receive_ungetc
+#endif
/*************************************************
* Local static variables *
@@ -565,7 +570,7 @@
{
register int last_ch = '\n';
- for (; (ch = (receive_getc)()) != EOF; last_ch = ch)
+ for (; (ch = (RECEIVE_GETC)()) != EOF; last_ch = ch)
{
if (ch == 0) body_zerocount++;
if (last_ch == '\r' && ch != '\n')
@@ -595,7 +600,7 @@
ch_state = 1;
-while ((ch = (receive_getc)()) != EOF)
+while ((ch = (RECEIVE_GETC)()) != EOF)
{
if (ch == 0) body_zerocount++;
switch (ch_state)
@@ -696,7 +701,7 @@
int ch_state = 0;
register int ch;
-while ((ch = (receive_getc)()) != EOF)
+while ((ch = (RECEIVE_GETC)()) != EOF)
{
if (ch == 0) body_zerocount++;
switch (ch_state)
@@ -1197,6 +1202,12 @@
body_linecount = body_zerocount = 0;
+#ifdef EXPERIMENTAL_DOMAINKEYS
+/* Call into DK to set up the context. Check if DK is to be run are carried out
+ inside dk_exim_verify_init(). */
+dk_exim_verify_init();
+#endif
+
/* Remember the time of reception. Exim uses time+pid for uniqueness of message
ids, and fractions of a second are required. See the comments that precede the
message id creation below. */
@@ -1245,7 +1256,7 @@
for (;;)
{
- int ch = (receive_getc)();
+ int ch = (RECEIVE_GETC)();
/* If we hit EOF on a SMTP connection, it's an error, since incoming
SMTP must have a correct "." terminator. */
@@ -1309,7 +1320,7 @@
if (ch == '\n')
{
if (first_line_ended_crlf == TRUE_UNSET) first_line_ended_crlf = FALSE;
- else if (first_line_ended_crlf) receive_ungetc(' ');
+ else if (first_line_ended_crlf) RECEIVE_UNGETC(' ');
goto EOL;
}
@@ -1324,13 +1335,13 @@
if (ptr == 0 && ch == '.' && (smtp_input || dot_ends))
{
- ch = (receive_getc)();
+ ch = (RECEIVE_GETC)();
if (ch == '\r')
{
- ch = (receive_getc)();
+ ch = (RECEIVE_GETC)();
if (ch != '\n')
{
- receive_ungetc(ch);
+ RECEIVE_UNGETC(ch);
ch = '\r'; /* Revert to CR */
}
}
@@ -1358,7 +1369,7 @@
if (ch == '\r')
{
- ch = (receive_getc)();
+ ch = (RECEIVE_GETC)();
if (ch == '\n')
{
if (first_line_ended_crlf == TRUE_UNSET) first_line_ended_crlf = TRUE;
@@ -1368,7 +1379,7 @@
/* Otherwise, put back the character after CR, and turn the bare CR
into LF SP. */
- ch = (receive_ungetc)(ch);
+ ch = (RECEIVE_UNGETC)(ch);
next->text[ptr++] = '\n';
message_size++;
ch = ' ';
@@ -1443,14 +1454,14 @@
if (ch != EOF)
{
- int nextch = (receive_getc)();
+ int nextch = (RECEIVE_GETC)();
if (nextch == ' ' || nextch == '\t')
{
next->text[ptr++] = nextch;
message_size++;
continue; /* Iterate the loop */
}
- else if (nextch != EOF) (receive_ungetc)(nextch); /* For next time */
+ else if (nextch != EOF) (RECEIVE_UNGETC)(nextch); /* For next time */
else ch = EOF; /* Cause main loop to exit at end */
}
@@ -2737,6 +2748,10 @@
if (smtp_input && !smtp_batched_input)
{
+
+#ifdef EXPERIMENTAL_DOMAINKEYS
+ dk_exim_verify_finish();
+#endif
#ifdef WITH_CONTENT_SCAN
/* MIME ACL hook */
Index: smtp_in.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/smtp_in.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- smtp_in.c 17 Feb 2005 11:58:26 -0000 1.11
+++ smtp_in.c 8 Mar 2005 15:32:02 -0000 1.12
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/smtp_in.c,v 1.11 2005/02/17 11:58:26 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/smtp_in.c,v 1.12 2005/03/08 15:32:02 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -822,6 +822,9 @@
#ifdef EXPERIMENTAL_BRIGHTMAIL
bmi_run = 0;
bmi_verdicts = NULL;
+#endif
+#ifdef EXPERIMENTAL_DOMAINKEYS
+dk_do_verify = 0;
#endif
#ifdef EXPERIMENTAL_SPF
spf_header_comment = NULL;
Index: spool_in.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/spool_in.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- spool_in.c 17 Feb 2005 11:58:26 -0000 1.8
+++ spool_in.c 8 Mar 2005 15:32:02 -0000 1.9
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/spool_in.c,v 1.8 2005/02/17 11:58:26 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/spool_in.c,v 1.9 2005/03/08 15:32:02 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -276,6 +276,10 @@
#ifdef EXPERIMENTAL_BRIGHTMAIL
bmi_run = 0;
bmi_verdicts = NULL;
+#endif
+
+#ifdef EXPERIMENTAL_DOMAINKEYS
+dk_do_verify = 0;
#endif
#ifdef SUPPORT_TLS
Index: transport.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/transport.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- transport.c 17 Feb 2005 11:58:26 -0000 1.4
+++ transport.c 8 Mar 2005 15:32:02 -0000 1.5
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/transport.c,v 1.4 2005/02/17 11:58:26 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/transport.c,v 1.5 2005/03/08 15:32:02 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -903,6 +903,164 @@
}
+#ifdef EXPERIMENTAL_DOMAINKEYS
+
+/**********************************************************************************
+* External interface to write the message, while signing it with domainkeys *
+**********************************************************************************/
+
+/* This function is a wrapper around transport_write_message(). It is only called
+ from the smtp transport if
+ (1) Domainkeys support is compiled in.
+ (2) The dk_private_key option on the smtp transport is set.
+ The function sets up a replacement fd into a -K file, then calls the normal
+ function. This way, the exact bits that exim would have put "on the wire" will
+ end up in the file (except for TLS encapsulation, which is the very
+ very last thing). When we are done signing the file, send the
+ signed message down the original fd (or TLS fd).
+
+Arguments: as for internal_transport_write_message() above, with additional
+ arguments:
+ uschar *dk_private_key The private key to use (filename or plain data)
+ uschar *dk_domain Override domain (normally NULL)
+ uschar *dk_selector The selector to use.
+ uschar *dk_canon The canonalization scheme to use, "simple" or "nofws"
+ uschar *dk_headers Colon-separated header list to include in the signing
+ process.
+ uschar *dk_strict What to do if signing fails: 1/true => throw error
+ 0/false => send anyway
+
+Returns: TRUE on success; FALSE (with errno) for any failure
+*/
+
+BOOL
+dk_transport_write_message(address_item *addr, int fd, int options,
+ int size_limit, uschar *add_headers, uschar *remove_headers,
+ uschar *check_string, uschar *escape_string, rewrite_rule *rewrite_rules,
+ int rewrite_existflags, uschar *dk_private_key, uschar *dk_domain,
+ uschar *dk_selector, uschar *dk_canon, uschar *dk_headers, uschar *dk_strict)
+{
+ int dk_fd;
+ int save_errno = 0;
+ BOOL rc;
+ uschar dk_spool_name[256];
+ char sbuf[2048];
+ int sread = 0;
+ int wwritten = 0;
+ uschar *dk_signature = NULL;
+
+ snprintf(CS dk_spool_name, 256, "%s/input/%s/%s-K",
+ spool_directory, message_subdir, message_id);
+ dk_fd = Uopen(dk_spool_name, O_RDWR|O_CREAT|O_EXCL, SPOOL_MODE);
+ if (dk_fd < 0)
+ {
+ /* Can't create spool file. Ugh. */
+ rc = FALSE;
+ save_errno = errno;
+ goto CLEANUP;
+ }
+
+ /* Call original function */
+ rc = transport_write_message(addr, dk_fd, options,
+ size_limit, add_headers, remove_headers,
+ check_string, escape_string, rewrite_rules,
+ rewrite_existflags);
+
+ /* Save error state. We must clean up before returning. */
+ if (!rc)
+ {
+ save_errno = errno;
+ goto CLEANUP;
+ }
+
+ /* Rewind file and feed it to the goats^W DK lib */
+ lseek(dk_fd, 0, SEEK_SET);
+ dk_signature = dk_exim_sign(dk_fd,
+ dk_private_key,
+ dk_domain,
+ dk_selector,
+ dk_canon);
+
+ if (dk_signature != NULL)
+ {
+ /* Send the signature first */
+ int siglen = Ustrlen(dk_signature);
+ while(siglen > 0)
+ {
+ #ifdef SUPPORT_TLS
+ if (tls_active == fd) wwritten = tls_write(dk_signature, siglen); else
+ #endif
+ wwritten = write(fd,dk_signature,siglen);
+ if (wwritten == -1)
+ {
+ /* error, bail out */
+ save_errno = errno;
+ rc = FALSE;
+ goto CLEANUP;
+ }
+ siglen -= wwritten;
+ dk_signature += wwritten;
+ }
+ }
+ else if (dk_strict != NULL)
+ {
+ uschar *dk_strict_result = expand_string(dk_strict);
+ if (dk_strict_result != NULL)
+ {
+ if ( (strcmpic(dk_strict,"1") == 0) ||
+ (strcmpic(dk_strict,"true") == 0) )
+ {
+ save_errno = errno;
+ rc = FALSE;
+ goto CLEANUP;
+ }
+ }
+ }
+
+ /* Rewind file and send it down the original fd. */
+ lseek(dk_fd, 0, SEEK_SET);
+
+ while((sread = read(dk_fd,sbuf,2048)) > 0)
+ {
+ char *p = sbuf;
+ /* write the chunk */
+ DK_WRITE:
+ #ifdef SUPPORT_TLS
+ if (tls_active == fd) wwritten = tls_write(p, sread); else
+ #endif
+ wwritten = write(fd,p,sread);
+ if (wwritten == -1)
+ {
+ /* error, bail out */
+ save_errno = errno;
+ rc = FALSE;
+ goto CLEANUP;
+ }
+ if (wwritten < sread)
+ {
+ /* short write, try again */
+ p += wwritten;
+ sread -= wwritten;
+ goto DK_WRITE;
+ }
+ }
+
+ if (sread == -1)
+ {
+ save_errno = errno;
+ rc = FALSE;
+ goto CLEANUP;
+ }
+
+
+ CLEANUP:
+ /* unlink -K file */
+ close(dk_fd);
+ Uunlink(dk_spool_name);
+ errno = save_errno;
+ return rc;
+}
+#endif
/*************************************************
Index: smtp.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/transports/smtp.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- smtp.c 17 Feb 2005 11:58:27 -0000 1.6
+++ smtp.c 8 Mar 2005 15:32:02 -0000 1.7
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/transports/smtp.c,v 1.6 2005/02/17 11:58:27 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/transports/smtp.c,v 1.7 2005/03/08 15:32:02 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -35,6 +35,20 @@
(void *)offsetof(smtp_transport_options_block, data_timeout) },
{ "delay_after_cutoff", opt_bool,
(void *)offsetof(smtp_transport_options_block, delay_after_cutoff) },
+#ifdef EXPERIMENTAL_DOMAINKEYS
+ { "dk_canon", opt_stringptr,
+ (void *)offsetof(smtp_transport_options_block, dk_canon) },
+ { "dk_domain", opt_stringptr,
+ (void *)offsetof(smtp_transport_options_block, dk_domain) },
+ { "dk_headers", opt_stringptr,
+ (void *)offsetof(smtp_transport_options_block, dk_headers) },
+ { "dk_private_key", opt_stringptr,
+ (void *)offsetof(smtp_transport_options_block, dk_private_key) },
+ { "dk_selector", opt_stringptr,
+ (void *)offsetof(smtp_transport_options_block, dk_selector) },
+ { "dk_strict", opt_stringptr,
+ (void *)offsetof(smtp_transport_options_block, dk_strict) },
+#endif
{ "dns_qualify_single", opt_bool,
(void *)offsetof(smtp_transport_options_block, dns_qualify_single) },
{ "dns_search_parents", opt_bool,
@@ -158,6 +172,14 @@
NULL, /* tls_verify_certificates */
TRUE /* tls_tempfail_tryclear */
#endif
+ #ifdef EXPERIMENTAL_DOMAINKEYS
+ ,NULL, /* dk_canon */
+ NULL, /* dk_domain */
+ NULL, /* dk_headers */
+ NULL, /* dk_private_key */
+ NULL, /* dk_selector */
+ NULL /* dk_strict */
+ #endif
};
@@ -1394,6 +1416,23 @@
DEBUG(D_transport|D_v)
debug_printf(" SMTP>> writing message and terminating \".\"\n");
transport_count = 0;
+#ifdef EXPERIMENTAL_DOMAINKEYS
+ if ( (ob->dk_private_key != NULL) && (ob->dk_selector != NULL) )
+ ok = dk_transport_write_message(addrlist, inblock.sock,
+ topt_use_crlf | topt_end_dot | topt_escape_headers |
+ (tblock->body_only? topt_no_headers : 0) |
+ (tblock->headers_only? topt_no_body : 0) |
+ (tblock->return_path_add? topt_add_return_path : 0) |
+ (tblock->delivery_date_add? topt_add_delivery_date : 0) |
+ (tblock->envelope_to_add? topt_add_envelope_to : 0),
+ 0, /* No size limit */
+ tblock->add_headers, tblock->remove_headers,
+ US".", US"..", /* Escaping strings */
+ tblock->rewrite_rules, tblock->rewrite_existflags,
+ ob->dk_private_key, ob->dk_domain, ob->dk_selector,
+ ob->dk_canon, ob->dk_headers, ob->dk_strict);
+ else
+#endif
ok = transport_write_message(addrlist, inblock.sock,
topt_use_crlf | topt_end_dot | topt_escape_headers |
(tblock->body_only? topt_no_headers : 0) |
Index: smtp.h
===================================================================
RCS file: /home/cvs/exim/exim-src/src/transports/smtp.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- smtp.h 17 Feb 2005 11:58:27 -0000 1.4
+++ smtp.h 8 Mar 2005 15:32:02 -0000 1.5
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/transports/smtp.h,v 1.4 2005/02/17 11:58:27 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/transports/smtp.h,v 1.5 2005/03/08 15:32:02 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -49,6 +49,14 @@
uschar *tls_require_ciphers;
uschar *tls_verify_certificates;
BOOL tls_tempfail_tryclear;
+ #endif
+ #ifdef EXPERIMENTAL_DOMAINKEYS
+ uschar *dk_domain;
+ uschar *dk_private_key;
+ uschar *dk_selector;
+ uschar *dk_canon;
+ uschar *dk_headers;
+ uschar *dk_strict;
#endif
} smtp_transport_options_block;