tom 2007/09/28 13:21:57 BST
Modified files:
exim-src/OS Makefile-Base
exim-src/scripts MakeLinks
exim-src/src acl.c config.h.defaults drtables.c exim.c
exim.h functions.h globals.c globals.h
receive.c sieve.c smtp_in.c spool_in.c
transport.c
exim-src/src/lookups Makefile
exim-src/src/transports smtp.c smtp.h
Added files:
exim-src/src dkim-exim.c dkim-exim.h
exim-src/src/lookups dkim.c dkim.h
Log:
[Buzilla 376] Preliminary DKIM support
Revision Changes Path
1.11 +2 -1 exim/exim-src/OS/Makefile-Base
1.13 +4 -0 exim/exim-src/scripts/MakeLinks
1.80 +20 -0 exim/exim-src/src/acl.c
1.15 +1 -0 exim/exim-src/src/config.h.defaults
1.1 +507 -0 exim/exim-src/src/dkim-exim.c (new)
1.1 +35 -0 exim/exim-src/src/dkim-exim.h (new)
1.9 +22 -0 exim/exim-src/src/drtables.c
1.59 +3 -0 exim/exim-src/src/exim.c
1.23 +3 -0 exim/exim-src/src/exim.h
1.39 +5 -0 exim/exim-src/src/functions.h
1.79 +6 -0 exim/exim-src/src/globals.c
1.60 +6 -0 exim/exim-src/src/globals.h
1.7 +2 -1 exim/exim-src/src/lookups/Makefile
1.1 +52 -0 exim/exim-src/src/lookups/dkim.c (new)
1.1 +16 -0 exim/exim-src/src/lookups/dkim.h (new)
1.42 +33 -0 exim/exim-src/src/receive.c
1.31 +9 -9 exim/exim-src/src/sieve.c
1.62 +3 -0 exim/exim-src/src/smtp_in.c
1.21 +4 -0 exim/exim-src/src/spool_in.c
1.20 +187 -0 exim/exim-src/src/transport.c
1.38 +39 -0 exim/exim-src/src/transports/smtp.c
1.13 +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.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- Makefile-Base 7 Feb 2006 14:20:58 -0000 1.10
+++ Makefile-Base 28 Sep 2007 12:21:57 -0000 1.11
@@ -1,4 +1,4 @@
-# $Cambridge: exim/exim-src/OS/Makefile-Base,v 1.10 2006/02/07 14:20:58 ph10 Exp $
+# $Cambridge: exim/exim-src/OS/Makefile-Base,v 1.11 2007/09/28 12:21:57 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
@@ -298,7 +298,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 dk.o
+OBJ_EXPERIMENTAL = bmi_spam.o spf.o srs.o dk.o dkim-exim.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.
@@ -599,6 +599,7 @@
spf.o: $(HDRS) spf.h spf.c
srs.o: $(HDRS) srs.h srs.c
dk.o: $(HDRS) dk.h dk.c
+dkim-exim.o: $(HDRS) dkim-exim.h dkim-exim.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.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- MakeLinks 23 Aug 2007 10:16:51 -0000 1.12
+++ MakeLinks 28 Sep 2007 12:21:57 -0000 1.13
@@ -1,5 +1,5 @@
#!/bin/sh
-# $Cambridge: exim/exim-src/scripts/MakeLinks,v 1.12 2007/08/23 10:16:51 ph10 Exp $
+# $Cambridge: exim/exim-src/scripts/MakeLinks,v 1.13 2007/09/28 12:21:57 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.
@@ -61,6 +61,8 @@
ln -s ../../src/lookups/cdb.c cdb.c
ln -s ../../src/lookups/dbmdb.h dbmdb.h
ln -s ../../src/lookups/dbmdb.c dbmdb.c
+ln -s ../../src/lookups/dkim.h dkim.h
+ln -s ../../src/lookups/dkim.c dkim.c
ln -s ../../src/lookups/dnsdb.h dnsdb.h
ln -s ../../src/lookups/dnsdb.c dnsdb.c
ln -s ../../src/lookups/dsearch.h dsearch.h
@@ -280,5 +282,7 @@
ln -s ../src/srs.h srs.h
ln -s ../src/dk.c dk.c
ln -s ../src/dk.h dk.h
+ln -s ../src/dkim-exim.c dkim-exim.c
+ln -s ../src/dkim-exim.h dkim-exim.h
# End of MakeLinks
Index: dkim-exim.c
====================================================================
/* $Cambridge: exim/exim-src/src/dkim-exim.c,v 1.1 2007/09/28 12:21:57 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
/* Copyright (c) University of Cambridge 1995 - 2007 */
/* See the file NOTICE for conditions of use and distribution. */
/* Code for DKIM support. Other DKIM relevant code is in
receive.c, transport.c and transports/smtp.c */
#include "exim.h"
#ifdef EXPERIMENTAL_DKIM
/* Globals related to the DKIM reference library. */
DKIMContext *dkim_context = NULL;
DKIMSignOptions *dkim_sign_options = NULL;
DKIMVerifyOptions *dkim_verify_options = NULL;
int dkim_verify_result = DKIM_NEUTRAL;
int dkim_internal_status = DKIM_SUCCESS;
/* 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 dkimbuff[6] = {256,256,256,256,256,256};
/* receive_getc() wrapper that feeds DKIM while Exim reads
the message. */
int dkim_receive_getc(void) {
int i;
#ifdef EXPERIMENTAL_DOMAINKEYS
int c = dk_receive_getc();
#else
int c = receive_getc();
#endif
if ((dkim_context != NULL) &&
(dkim_internal_status == DKIM_SUCCESS)) {
/* Send oldest byte */
if (dkimbuff[0] < 256) {
DKIMVerifyProcess(dkim_context,(char *)&dkimbuff[0],1);
/* debug_printf("%c",(int)dkimbuff[0]); */
}
/* rotate buffer */
for (i=0;i<5;i++) dkimbuff[i]=dkimbuff[i+1];
dkimbuff[5]=c;
/* look for our candidate patterns */
if ( (dkimbuff[1] == '\r') &&
(dkimbuff[2] == '\n') &&
(dkimbuff[3] == '.') &&
(dkimbuff[4] == '\r') &&
(dkimbuff[5] == '\n') ) {
/* End of DATA */
dkimbuff[1] = 256;
dkimbuff[2] = 256;
dkimbuff[3] = 256;
dkimbuff[4] = 256;
dkimbuff[5] = 256;
}
if ( (dkimbuff[2] == '\r') &&
(dkimbuff[3] == '\n') &&
(dkimbuff[4] == '.') &&
(dkimbuff[5] == '.') ) {
/* doubled dot, skip this char */
dkimbuff[5] = 256;
}
}
return c;
}
/* When exim puts a char back in the fd, we
must rotate our buffer back. */
int dkim_receive_ungetc(int c) {
if ((dkim_context != NULL) &&
(dkim_internal_status == DKIM_SUCCESS)) {
int i;
/* rotate buffer back */
for (i=5;i>0;i--) dkimbuff[i]=dkimbuff[i-1];
dkimbuff[0]=256;
}
#ifdef EXPERIMENTAL_DOMAINKEYS
return dk_receive_ungetc(c);
#else
return receive_ungetc(c);
#endif
}
void dkim_exim_verify_init(void) {
int old_pool = store_pool;
/* Bail out unless we got perfect conditions */
if (!(smtp_input &&
!smtp_batched_input &&
dkim_do_verify)) {
return;
}
store_pool = POOL_PERM;
dkim_context = NULL;
dkim_verify_options = NULL;
dkim_context = store_get(sizeof(DKIMContext));
dkim_verify_options = store_get(sizeof(DKIMVerifyOptions));
if (!dkim_context ||
!dkim_verify_options) {
debug_printf("DKIM: Can't allocate memory for verifying.\n");
dkim_context = NULL;
}
memset(dkim_context,0,sizeof(DKIMContext));
memset(dkim_verify_options,0,sizeof(DKIMVerifyOptions));
dkim_verify_options->nHonorBodyLengthTag = 1; /* Honor the l= tag */
dkim_verify_options->nCheckPolicy = 1; /* Fetch sender's policy */
dkim_verify_options->nSubjectRequired = 1; /* Do not require Subject header inclusion */
dkim_verify_options->pfnSelectorCallback = NULL;
dkim_verify_options->pfnPolicyCallback = NULL;
dkim_status_wrap( DKIMVerifyInit(dkim_context, dkim_verify_options),
"error calling DKIMVerifyInit()" );
if (dkim_internal_status != DKIM_SUCCESS) {
/* Invalidate context */
dkim_context = NULL;
}
store_pool = old_pool;
}
void dkim_exim_verify_finish(void) {
int i;
int old_pool = store_pool;
if (!dkim_do_verify ||
(!(smtp_input && !smtp_batched_input)) ||
(dkim_context == NULL) ||
(dkim_internal_status != DKIM_SUCCESS)) return;
store_pool = POOL_PERM;
/* Flush eventual remaining input chars */
for (i=0;i<6;i++)
if (dkimbuff[i] < 256)
DKIMVerifyProcess(dkim_context,(char *)&dkimbuff[i],1);
/* Fetch global result. Can be one of:
DKIM_SUCCESS
DKIM_PARTIAL_SUCCESS
DKIM_NEUTRAL
DKIM_FAIL
*/
dkim_verify_result = DKIMVerifyResults(dkim_context);
store_pool = old_pool;
}
/* Lookup result for a given domain (or identity) */
int dkim_exim_verify_result(uschar *domain, uschar **result, uschar **error) {
int sig_count = 0;
int i,rc;
char policy[512];
DKIMVerifyDetails *dkim_verify_details = NULL;
if (!dkim_do_verify ||
(!(smtp_input && !smtp_batched_input)) ||
(dkim_context == NULL) ||
(dkim_internal_status != DKIM_SUCCESS)) {
rc = DKIM_EXIM_UNVERIFIED;
goto YIELD;
}
DKIMVerifyGetDetails(dkim_context,
&sig_count,
&dkim_verify_details,
policy);
rc = DKIM_EXIM_UNSIGNED;
debug_printf("DKIM: We have %d signature(s)\n",sig_count);
for (i=0;i<sig_count;i++) {
debug_printf( "DKIM: [%d] ", i + 1 );
if (!dkim_verify_details[i].Domain) {
debug_printf("parse error (no domain)\n");
continue;
}
if (dkim_verify_details[i].nResult >= 0) {
debug_printf( "GOOD d=%s i=%s\n",
dkim_verify_details[i].Domain,
dkim_verify_details[i].IdentityDomain );
}
else {
debug_printf( "FAIL d=%s i=%s c=%d\n",
dkim_verify_details[i].Domain,
dkim_verify_details[i].IdentityDomain,
dkim_verify_details[i].nResult
);
}
if ( (strcmpic(domain,dkim_verify_details[i].Domain) == 0) ||
(strcmpic(domain,dkim_verify_details[i].IdentityDomain) == 0) ) {
if (dkim_verify_details[i].nResult >= 0) {
rc = DKIM_EXIM_GOOD;
/* TODO: Add From: domain check */
}
else {
/* Return DEFER for temp. error types */
if (dkim_verify_details[i].nResult == DKIM_SELECTOR_DNS_TEMP_FAILURE) {
rc = DKIM_EXIM_DEFER;
}
else {
rc = DKIM_EXIM_FAIL;
}
}
}
}
YIELD:
switch (rc) {
case DKIM_EXIM_FAIL:
*result = "bad";
break;
case DKIM_EXIM_DEFER:
*result = "defer";
break;
case DKIM_EXIM_UNVERIFIED:
*result = "unverified";
break;
case DKIM_EXIM_UNSIGNED:
*result = "unsigned";
break;
case DKIM_EXIM_GOOD:
*result = "good";
break;
}
return rc;
}
uschar *dkim_exim_sign_headers = NULL;
int dkim_exim_header_callback(const char* header) {
int sep = 0;
uschar *hdr_ptr = dkim_exim_sign_headers;
uschar *hdr_itr = NULL;
uschar hdr_buf[512];
uschar *hdr_name = string_copy(US header);
char *colon_pos = strchr(hdr_name,':');
if (colon_pos == NULL) return 0;
*colon_pos = '\0';
debug_printf("DKIM: header '%s' ",hdr_name);
while ((hdr_itr = string_nextinlist(&hdr_ptr, &sep,
hdr_buf,
sizeof(hdr_buf))) != NULL) {
if (strcmpic((uschar *)hdr_name,hdr_itr) == 0) {
debug_printf("included in signature.\n");
return 1;
}
}
debug_printf("NOT included in signature.\n");
return 0;
}
uschar *dkim_exim_sign(int dkim_fd,
uschar *dkim_private_key,
uschar *dkim_domain,
uschar *dkim_selector,
uschar *dkim_canon,
uschar *dkim_sign_headers) {
uschar *rc = NULL;
char buf[4096];
int seen_lf = 0;
int seen_lfdot = 0;
int save_errno = 0;
int sread;
char *signature;
int old_pool = store_pool;
store_pool = POOL_PERM;
dkim_context = NULL;
dkim_sign_options = NULL;
dkim_context = store_get(sizeof(DKIMContext));
dkim_sign_options = store_get(sizeof(DKIMSignOptions));
dkim_sign_options->nIncludeBodyLengthTag = 0;
dkim_sign_options->nIncludeCopiedHeaders = 0;
dkim_sign_options->nHash = DKIM_HASH_SHA256;
dkim_sign_options->nIncludeTimeStamp = 0;
dkim_sign_options->nIncludeQueryMethod = 0;
dkim_sign_options->pfnHeaderCallback = dkim_exim_header_callback;
dkim_sign_options->nIncludeBodyHash = DKIM_BODYHASH_IETF_1;
dkim_domain = expand_string(dkim_domain);
if (dkim_domain == NULL) {
/* expansion error, do not send message. */
log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand "
"dkim_domain: %s", expand_string_message);
rc = NULL;
goto CLEANUP;
}
/* Set up $dkim_domain expansion variable. */
dkim_signing_domain = dkim_domain;
Ustrncpy((uschar *)dkim_sign_options->szDomain,dkim_domain,255);
/* Get selector to use. */
dkim_selector = expand_string(dkim_selector);
if (dkim_selector == NULL) {
log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand "
"dkim_selector: %s", expand_string_message);
rc = NULL;
goto CLEANUP;
}
/* Set up $dkim_selector expansion variable. */
dkim_signing_selector = dkim_selector;
Ustrncpy((uschar *)dkim_sign_options->szSelector,dkim_selector,79);
/* Expand provided options */
dkim_canon = expand_string(dkim_canon?dkim_canon:US"relaxed");
if (dkim_canon == NULL) {
/* expansion error, do not send message. */
log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand "
"dkim_canon: %s", expand_string_message);
rc = NULL;
goto CLEANUP;
}
if (Ustrcmp(dkim_canon, "relaxed") == 0)
dkim_sign_options->nCanon = DKIM_SIGN_RELAXED;
else if (Ustrcmp(dkim_canon, "simple") == 0)
dkim_sign_options->nCanon = DKIM_SIGN_SIMPLE;
else {
log_write(0, LOG_MAIN, "DKIM: unknown canonicalization method '%s', defaulting to 'relaxed'.\n",dkim_canon);
dkim_sign_options->nCanon = DKIM_SIGN_RELAXED;
}
/* Expand signing headers once */
if (dkim_sign_headers != NULL) {
dkim_sign_headers = expand_string(dkim_sign_headers);
if (dkim_sign_headers == NULL) {
log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand "
"dkim_sign_headers: %s", expand_string_message);
rc = NULL;
goto CLEANUP;
}
}
if (dkim_sign_headers == NULL) {
/* Use RFC defaults */
dkim_sign_headers = US"from:sender:reply-to:subject:date:"
"message-id:to:cc:mime-version:content-type:"
"content-transfer-encoding:content-id:"
"content-description:resent-date:resent-from:"
"resent-sender:resent-to:resent-cc:resent-message-id:"
"in-reply-to:references:"
"list-id:list-help:list-unsubscribe:"
"list-subscribe:list-post:list-owner:list-archive";
}
dkim_exim_sign_headers = dkim_sign_headers;
/* Get private key to use. */
dkim_private_key = expand_string(dkim_private_key);
if (dkim_private_key == NULL) {
log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand "
"dkim_private_key: %s", expand_string_message);
rc = NULL;
goto CLEANUP;
}
if ( (Ustrlen(dkim_private_key) == 0) ||
(Ustrcmp(dkim_private_key,"0") == 0) ||
(Ustrcmp(dkim_private_key,"false") == 0) ) {
/* don't sign, but no error */
rc = US"";
goto CLEANUP;
}
if (dkim_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(CS dkim_private_key,O_RDONLY);
(void)read(privkey_fd,big_buffer,16383);
(void)close(privkey_fd);
dkim_private_key = big_buffer;
}
/* Initialize signing context. */
dkim_status_wrap( DKIMSignInit(dkim_context, dkim_sign_options),
"error calling DKIMSignInit()" );
if (dkim_internal_status != DKIM_SUCCESS) {
/* Invalidate context */
dkim_context = NULL;
goto CLEANUP;
}
while((sread = read(dkim_fd,&buf,4096)) > 0) {
int pos = 0;
char c;
while (pos < sread) {
c = buf[pos++];
if ((c == '.') && seen_lfdot) {
/* escaped dot, write "\n.", continue */
dkim_internal_status = DKIMSignProcess(dkim_context,"\n.",2);
seen_lf = 0;
seen_lfdot = 0;
continue;
}
if (seen_lfdot) {
/* EOM, write "\n" and break */
dkim_internal_status = DKIMSignProcess(dkim_context,"\n",1);
break;
}
if ((c == '.') && seen_lf) {
seen_lfdot = 1;
continue;
}
if (seen_lf) {
/* normal lf, just send it */
dkim_internal_status = DKIMSignProcess(dkim_context,"\n",1);
seen_lf = 0;
}
if (c == '\n') {
seen_lf = 1;
continue;
}
/* write the char */
dkim_internal_status = DKIMSignProcess(dkim_context,&c,1);
}
}
/* Handle failed read above. */
if (sread == -1) {
debug_printf("DKIM: Error reading -K file.\n");
save_errno = errno;
rc = NULL;
goto CLEANUP;
}
if (!dkim_status_wrap(dkim_internal_status,
"error while processing message data")) {
rc = NULL;
goto CLEANUP;
}
if (!dkim_status_wrap( DKIMSignGetSig2( dkim_context, dkim_private_key, &signature ),
"error while signing message" ) ) {
rc = NULL;
goto CLEANUP;
}
log_write(0, LOG_MAIN, "Message signed with DKIM: %s\n",signature);
rc = store_get(strlen(signature)+3);
Ustrcpy(rc,US signature);
Ustrcat(rc,US"\r\n");
CLEANUP:
if (dkim_context != NULL) {
dkim_context = NULL;
}
store_pool = old_pool;
errno = save_errno;
return rc;
}
unsigned int dkim_status_wrap(int stat, uschar *text) {
char *p = DKIMGetErrorString(stat);
if (stat != DKIM_SUCCESS) {
debug_printf("DKIM: %s",text?text:US"");
if (p) debug_printf(" (%s)",p);
debug_printf("\n");
}
dkim_internal_status = stat;
return (dkim_internal_status==DKIM_SUCCESS)?1:0;
}
#endif
Index: dkim-exim.h
====================================================================
/* $Cambridge: exim/exim-src/src/dkim-exim.h,v 1.1 2007/09/28 12:21:57 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
/* Copyright (c) University of Cambridge 1995 - 2007 */
/* See the file NOTICE for conditions of use and distribution. */
/* Code for DKIM support. Other DKIM relevant code is in
receive.c, transport.c and transports/smtp.c */
/* Exim interface to DKIM results */
#define DKIM_EXIM_FAIL -2 /* Message has a bad signature from that domain or identity. */
#define DKIM_EXIM_DEFER -1 /* Message has an unverified signature from that domain */
#define DKIM_EXIM_UNVERIFIED 0 /* Message was not validated with the DK engine */
#define DKIM_EXIM_UNSIGNED 1 /* Message has no signature from that domain or identity */
#define DKIM_EXIM_GOOD 2 /* Message has good signature from that domain or identity */
#ifdef EXPERIMENTAL_DKIM
#include <dkim.h>
int dkim_exim_verify_result(uschar *,uschar **,uschar **);
/* Internal prototypes */
int dkim_receive_getc(void);
int dkim_receive_ungetc(int);
void dkim_exim_verify_init(void);
void dkim_exim_verify_finish(void);
uschar *dkim_exim_sign(int, uschar *, uschar *, uschar *, uschar *, uschar *);
unsigned int dkim_status_wrap(int, uschar *);
#endif
Index: acl.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/acl.c,v
retrieving revision 1.79
retrieving revision 1.80
diff -u -r1.79 -r1.80
--- acl.c 29 Aug 2007 13:58:25 -0000 1.79
+++ acl.c 28 Sep 2007 12:21:57 -0000 1.80
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/acl.c,v 1.79 2007/08/29 13:58:25 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/acl.c,v 1.80 2007/09/28 12:21:57 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -174,6 +174,9 @@
#ifdef EXPERIMENTAL_DOMAINKEYS
CONTROL_DK_VERIFY,
#endif
+ #ifdef EXPERIMENTAL_DKIM
+ CONTROL_DKIM_VERIFY,
+ #endif
CONTROL_ERROR,
CONTROL_CASEFUL_LOCAL_PART,
CONTROL_CASELOWER_LOCAL_PART,
@@ -207,6 +210,9 @@
#ifdef EXPERIMENTAL_DOMAINKEYS
US"dk_verify",
#endif
+ #ifdef EXPERIMENTAL_DKIM
+ US"dkim_verify",
+ #endif
US"error",
US"caseful_local_part",
US"caselower_local_part",
@@ -550,6 +556,11 @@
(1<<ACL_WHERE_NOTSMTP_START),
#endif
+ #ifdef EXPERIMENTAL_DKIM
+ (1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_NOTSMTP)| /* dkim_verify */
+ (1<<ACL_WHERE_NOTSMTP_START),
+ #endif
+
0, /* error */
(unsigned int)
@@ -629,6 +640,9 @@
#ifdef EXPERIMENTAL_DOMAINKEYS
{ US"dk_verify", CONTROL_DK_VERIFY, FALSE },
#endif
+#ifdef EXPERIMENTAL_DKIM
+ { US"dkim_verify", CONTROL_DKIM_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 },
@@ -2613,6 +2627,12 @@
break;
#endif
+ #ifdef EXPERIMENTAL_DKIM
+ case CONTROL_DKIM_VERIFY:
+ dkim_do_verify = 1;
+ break;
+ #endif
+
case CONTROL_ERROR:
return ERROR;
Index: config.h.defaults
===================================================================
RCS file: /home/cvs/exim/exim-src/src/config.h.defaults,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- config.h.defaults 22 Jan 2007 16:29:54 -0000 1.14
+++ config.h.defaults 28 Sep 2007 12:21:57 -0000 1.15
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/config.h.defaults,v 1.14 2007/01/22 16:29:54 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/config.h.defaults,v 1.15 2007/09/28 12:21:57 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -151,6 +151,7 @@
#define EXPERIMENTAL_SPF
#define EXPERIMENTAL_SRS
#define EXPERIMENTAL_DOMAINKEYS
+#define EXPERIMENTAL_DKIM
#define EXPERIMENTAL_BRIGHTMAIL
/* Things that are not routinely changed but are nevertheless configurable
Index: drtables.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/drtables.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- drtables.c 8 Jan 2007 10:50:18 -0000 1.8
+++ drtables.c 28 Sep 2007 12:21:57 -0000 1.9
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/drtables.c,v 1.8 2007/01/08 10:50:18 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/drtables.c,v 1.9 2007/09/28 12:21:57 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -105,6 +105,11 @@
#include "lookups/whoson.h"
#endif
+#ifdef EXPERIMENTAL_DKIM
+#include "lookups/dkim.h"
+#endif
+
+
/* The second field in each item below is a set of bit flags:
lookup_querystyle => this is a query-style lookup,
@@ -171,6 +176,23 @@
#endif
},
+/* DKIM lookups */
+
+ {
+ US"dkim", /* lookup name */
+ lookup_querystyle, /* query style */
+#ifdef EXPERIMENTAL_DKIM
+ dkim_open, /* open function */
+ NULL, /* check function */
+ dkim_find, /* find function */
+ NULL, /* no close function */
+ NULL, /* no tidy function */
+ NULL /* no quoting function */
+#else
+ NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
+#endif
+ },
+
/* Using DNS TXT records as a database */
{
Index: exim.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/exim.c,v
retrieving revision 1.58
retrieving revision 1.59
diff -u -r1.58 -r1.59
--- exim.c 4 Sep 2007 08:18:12 -0000 1.58
+++ exim.c 28 Sep 2007 12:21:57 -0000 1.59
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/exim.c,v 1.58 2007/09/04 08:18:12 nm4 Exp $ */
+/* $Cambridge: exim/exim-src/src/exim.c,v 1.59 2007/09/28 12:21:57 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -920,6 +920,9 @@
#ifdef EXPERIMENTAL_DOMAINKEYS
fprintf(f, " Experimental_DomainKeys");
#endif
+#ifdef EXPERIMENTAL_DKIM
+ fprintf(f, " Experimental_DKIM");
+#endif
fprintf(f, "\n");
fprintf(f, "Lookups:");
Index: exim.h
===================================================================
RCS file: /home/cvs/exim/exim-src/src/exim.h,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- exim.h 22 Jan 2007 16:29:54 -0000 1.22
+++ exim.h 28 Sep 2007 12:21:57 -0000 1.23
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/exim.h,v 1.22 2007/01/22 16:29:54 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/exim.h,v 1.23 2007/09/28 12:21:57 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -449,6 +449,9 @@
#ifdef EXPERIMENTAL_DOMAINKEYS
#include "dk.h"
#endif
+#ifdef EXPERIMENTAL_DKIM
+#include "dkim-exim.h"
+#endif
/* The following stuff must follow the inclusion of config.h because it
requires various things that are set therein. */
Index: functions.h
===================================================================
RCS file: /home/cvs/exim/exim-src/src/functions.h,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -r1.38 -r1.39
--- functions.h 22 Aug 2007 10:10:23 -0000 1.38
+++ functions.h 28 Sep 2007 12:21:57 -0000 1.39
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/functions.h,v 1.38 2007/08/22 10:10:23 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/functions.h,v 1.39 2007/09/28 12:21:57 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -83,6 +83,11 @@
int, uschar *, uschar *, uschar *, uschar *, rewrite_rule *,
int, uschar *, uschar *, uschar *, uschar *, uschar *, uschar *);
#endif
+#ifdef EXPERIMENTAL_DKIM
+extern BOOL dkim_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.78
retrieving revision 1.79
diff -u -r1.78 -r1.79
--- globals.c 23 Aug 2007 11:01:49 -0000 1.78
+++ globals.c 28 Sep 2007 12:21:57 -0000 1.79
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/globals.c,v 1.78 2007/08/23 11:01:49 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/globals.c,v 1.79 2007/09/28 12:21:57 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -523,6 +523,12 @@
int dk_do_verify = 0;
#endif
+#ifdef EXPERIMENTAL_DKIM
+uschar *dkim_signing_domain = NULL;
+uschar *dkim_signing_selector = NULL;
+int dkim_do_verify = 0;
+#endif
+
uschar *dns_again_means_nonexist = NULL;
int dns_csa_search_limit = 5;
BOOL dns_csa_use_reverse = TRUE;
Index: globals.h
===================================================================
RCS file: /home/cvs/exim/exim-src/src/globals.h,v
retrieving revision 1.59
retrieving revision 1.60
diff -u -r1.59 -r1.60
--- globals.h 23 Aug 2007 11:01:49 -0000 1.59
+++ globals.h 28 Sep 2007 12:21:57 -0000 1.60
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/globals.h,v 1.59 2007/08/23 11:01:49 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/globals.h,v 1.60 2007/09/28 12:21:57 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -292,6 +292,12 @@
extern int dk_do_verify; /* DK verification switch. Set with ACL control statement. */
#endif
+#ifdef EXPERIMENTAL_DKIM
+extern uschar *dkim_signing_domain; /* Domain used for signing a message. */
+extern uschar *dkim_signing_selector; /* Selector used for signing a message. */
+extern int dkim_do_verify; /* DKIM verification switch. Set with ACL control statement. */
+#endif
+
extern uschar *dns_again_means_nonexist; /* Domains that are badly set up */
extern int dns_csa_search_limit; /* How deep to search for CSA SRV records */
extern BOOL dns_csa_use_reverse; /* Check CSA in reverse DNS? (non-standard) */
Index: receive.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/receive.c,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -r1.41 -r1.42
--- receive.c 22 Aug 2007 14:20:28 -0000 1.41
+++ receive.c 28 Sep 2007 12:21:57 -0000 1.42
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/receive.c,v 1.41 2007/08/22 14:20:28 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/receive.c,v 1.42 2007/09/28 12:21:57 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -11,14 +11,38 @@
#include "exim.h"
+#if (defined EXPERIMENTAL_DOMAINKEYS) && (defined EXPERIMENTAL_DKIM)
+
+#warning Chaining Domainkeys via DKIM receive functions
+#define RECEIVE_GETC dkim_receive_getc
+#define RECEIVE_UNGETC dkim_receive_ungetc
+
+#else
+
+#if (defined EXPERIMENTAL_DOMAINKEYS) || (defined EXPERIMENTAL_DKIM)
+
#ifdef EXPERIMENTAL_DOMAINKEYS
+#warning Using Domainkeys receive functions
#define RECEIVE_GETC dk_receive_getc
#define RECEIVE_UNGETC dk_receive_ungetc
+#endif
+#ifdef EXPERIMENTAL_DKIM
+#warning Using DKIM receive functions
+#define RECEIVE_GETC dkim_receive_getc
+#define RECEIVE_UNGETC dkim_receive_ungetc
+#endif
+
#else
+
+/* Normal operation */
#define RECEIVE_GETC receive_getc
#define RECEIVE_UNGETC receive_ungetc
+
+#endif
+
#endif
+
/*************************************************
* Local static variables *
*************************************************/
@@ -1393,6 +1417,12 @@
inside dk_exim_verify_init(). */
dk_exim_verify_init();
#endif
+#ifdef EXPERIMENTAL_DKIM
+/* Call into DKIM to set up the context. Check if DKIM is to be run are carried out
+ inside dk_exim_verify_init(). */
+dkim_exim_verify_init();
+#endif
+
/* Remember the time of reception. Exim uses time+pid for uniqueness of message
ids, and fractions of a second are required. See the comments that precede the
@@ -2975,6 +3005,9 @@
#ifdef EXPERIMENTAL_DOMAINKEYS
dk_exim_verify_finish();
#endif
+#ifdef EXPERIMENTAL_DKIM
+ dkim_exim_verify_finish();
+#endif
#ifdef WITH_CONTENT_SCAN
if (acl_smtp_mime != NULL &&
Index: sieve.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/sieve.c,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -r1.30 -r1.31
--- sieve.c 24 Sep 2007 11:52:16 -0000 1.30
+++ sieve.c 28 Sep 2007 12:21:57 -0000 1.31
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/sieve.c,v 1.30 2007/09/24 11:52:16 michael Exp $ */
+/* $Cambridge: exim/exim-src/src/sieve.c,v 1.31 2007/09/28 12:21:57 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -1942,14 +1942,14 @@
-1 syntax or execution error
*/
-static int parse_testlist(struct Sieve *filter, int *n, int *true, int exec)
+static int parse_testlist(struct Sieve *filter, int *n, int *num_true, int exec)
{
if (parse_white(filter)==-1) return -1;
if (*filter->pc=='(')
{
++filter->pc;
*n=0;
- *true=0;
+ *num_true=0;
for (;;)
{
int cond;
@@ -1958,7 +1958,7 @@
{
case -1: return -1;
case 0: filter->errmsg=CUS "missing test"; return -1;
- default: ++*n; if (cond) ++*true; break;
+ default: ++*n; if (cond) ++*num_true; break;
}
if (parse_white(filter)==-1) return -1;
if (*filter->pc==',') ++filter->pc;
@@ -2146,13 +2146,13 @@
allof-test = "allof" <tests: test-list>
*/
- int n,true;
+ int n,num_true;
- switch (parse_testlist(filter,&n,&true,exec))
+ switch (parse_testlist(filter,&n,&num_true,exec))
{
case -1: return -1;
case 0: filter->errmsg=CUS "missing test list"; return -1;
- default: *cond=(n==true); return 1;
+ default: *cond=(n==num_true); return 1;
}
}
else if (parse_identifier(filter,CUS "anyof"))
@@ -2161,13 +2161,13 @@
anyof-test = "anyof" <tests: test-list>
*/
- int n,true;
+ int n,num_true;
- switch (parse_testlist(filter,&n,&true,exec))
+ switch (parse_testlist(filter,&n,&num_true,exec))
{
case -1: return -1;
case 0: filter->errmsg=CUS "missing test list"; return -1;
- default: *cond=(true>0); return 1;
+ default: *cond=(num_true>0); return 1;
}
}
else if (parse_identifier(filter,CUS "exists"))
Index: smtp_in.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/smtp_in.c,v
retrieving revision 1.61
retrieving revision 1.62
diff -u -r1.61 -r1.62
--- smtp_in.c 22 Aug 2007 14:20:28 -0000 1.61
+++ smtp_in.c 28 Sep 2007 12:21:57 -0000 1.62
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/smtp_in.c,v 1.61 2007/08/22 14:20:28 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/smtp_in.c,v 1.62 2007/09/28 12:21:57 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -1025,6 +1025,9 @@
#ifdef EXPERIMENTAL_DOMAINKEYS
dk_do_verify = 0;
#endif
+#ifdef EXPERIMENTAL_DKIM
+dkim_do_verify = 0;
+#endif
#ifdef EXPERIMENTAL_SPF
spf_header_comment = NULL;
spf_received = NULL;
Index: spool_in.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/spool_in.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -r1.20 -r1.21
--- spool_in.c 22 Jun 2007 14:38:58 -0000 1.20
+++ spool_in.c 28 Sep 2007 12:21:57 -0000 1.21
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/spool_in.c,v 1.20 2007/06/22 14:38:58 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/spool_in.c,v 1.21 2007/09/28 12:21:57 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -282,6 +282,10 @@
dk_do_verify = 0;
#endif
+#ifdef EXPERIMENTAL_DKIM
+dkim_do_verify = 0;
+#endif
+
#ifdef SUPPORT_TLS
tls_certificate_verified = FALSE;
tls_cipher = NULL;
Index: transport.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/transport.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- transport.c 8 Jan 2007 10:50:18 -0000 1.19
+++ transport.c 28 Sep 2007 12:21:57 -0000 1.20
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/transport.c,v 1.19 2007/01/08 10:50:18 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/transport.c,v 1.20 2007/09/28 12:21:57 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -1127,6 +1127,193 @@
#endif
+
+#ifdef EXPERIMENTAL_DKIM
+
+/**********************************************************************************
+* External interface to write the message, while signing it with DKIM *
+**********************************************************************************/
+
+/* This function is a wrapper around transport_write_message(). It is only called
+ from the smtp transport if
+ (1) DKIM support is compiled in.
+ (2) The dkim_private_key and dkim_domain 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 *dkim_private_key The private key to use (filename or plain data)
+ uschar *dkim_domain The domain to use
+ uschar *dkim_selector The selector to use.
+ uschar *dkim_canon The canonalization scheme to use, "simple" or "relaxed"
+ uschar *dkim_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
+dkim_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 *dkim_private_key, uschar *dkim_domain,
+ uschar *dkim_selector, uschar *dkim_canon, uschar *dkim_strict, uschar *dkim_sign_headers)
+{
+ int dkim_fd;
+ int save_errno = 0;
+ BOOL rc;
+ uschar dkim_spool_name[256];
+ char sbuf[2048];
+ int sread = 0;
+ int wwritten = 0;
+ uschar *dkim_signature = NULL;
+ off_t size = 0;
+
+ (void)string_format(dkim_spool_name, 256, "%s/input/%s/%s-%d-K",
+ spool_directory, message_subdir, message_id, (int)getpid());
+ dkim_fd = Uopen(dkim_spool_name, O_RDWR|O_CREAT|O_TRUNC, SPOOL_MODE);
+ if (dkim_fd < 0)
+ {
+ /* Can't create spool file. Ugh. */
+ rc = FALSE;
+ save_errno = errno;
+ goto CLEANUP;
+ }
+
+ /* Call original function */
+ rc = transport_write_message(addr, dkim_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 DKIM lib */
+ lseek(dkim_fd, 0, SEEK_SET);
+ dkim_signature = dkim_exim_sign(dkim_fd,
+ dkim_private_key,
+ dkim_domain,
+ dkim_selector,
+ dkim_canon,
+ dkim_sign_headers);
+
+ if (dkim_signature != NULL)
+ {
+ /* Send the signature first */
+ int siglen = Ustrlen(dkim_signature);
+ while(siglen > 0)
+ {
+ #ifdef SUPPORT_TLS
+ if (tls_active == fd) wwritten = tls_write(dkim_signature, siglen); else
+ #endif
+ wwritten = write(fd,dkim_signature,siglen);
+ if (wwritten == -1)
+ {
+ /* error, bail out */
+ save_errno = errno;
+ rc = FALSE;
+ goto CLEANUP;
+ }
+ siglen -= wwritten;
+ dkim_signature += wwritten;
+ }
+ }
+ else if (dkim_strict != NULL)
+ {
+ uschar *dkim_strict_result = expand_string(dkim_strict);
+ if (dkim_strict_result != NULL)
+ {
+ if ( (strcmpic(dkim_strict,US"1") == 0) ||
+ (strcmpic(dkim_strict,US"true") == 0) )
+ {
+ save_errno = errno;
+ rc = FALSE;
+ goto CLEANUP;
+ }
+ }
+ }
+
+ /* Fetch file positition (the size) */
+ size = lseek(dkim_fd,0,SEEK_CUR);
+
+ /* Rewind file */
+ lseek(dkim_fd, 0, SEEK_SET);
+
+#ifdef HAVE_LINUX_SENDFILE
+ /* We can use sendfile() to shove the file contents
+ to the socket. However only if we don't use TLS,
+ in which case theres another layer of indirection
+ before the data finally hits the socket. */
+ if (tls_active != fd)
+ {
+ ssize_t copied = 0;
+ off_t offset = 0;
+ while((copied >= 0) && (offset<size))
+ {
+ copied = sendfile(fd, dkim_fd, &offset, (size - offset));
+ }
+ if (copied < 0)
+ {
+ save_errno = errno;
+ rc = FALSE;
+ }
+ goto CLEANUP;
+ }
+#endif
+
+ /* Send file down the original fd */
+ while((sread = read(dkim_fd,sbuf,2048)) > 0)
+ {
+ char *p = sbuf;
+ /* write the chunk */
+ DKIM_WRITE:
+ #ifdef SUPPORT_TLS
+ if (tls_active == fd) wwritten = tls_write(US 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 DKIM_WRITE;
+ }
+ }
+
+ if (sread == -1)
+ {
+ save_errno = errno;
+ rc = FALSE;
+ goto CLEANUP;
+ }
+
+ CLEANUP:
+ /* unlink -K file */
+ (void)close(dkim_fd);
+ Uunlink(dkim_spool_name);
+ errno = save_errno;
+ return rc;
+}
+#endif
+
+
+
/*************************************************
* External interface to write the message *
*************************************************/
Index: dkim.c
====================================================================
/* $Cambridge: exim/exim-src/src/lookups/dkim.c,v 1.1 2007/09/28 12:21:57 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
/* Copyright (c) University of Cambridge 1995 - 2007 */
/* See the file NOTICE for conditions of use and distribution. */
#include "../exim.h"
#include "dkim.h"
/*************************************************
* Open entry point *
*************************************************/
/* See local README for interface description */
void *
dkim_open(uschar *filename, uschar **errmsg)
{
filename = filename; /* Keep picky compilers happy */
errmsg = errmsg;
return (void *)(-1); /* Just return something non-null */
}
/*************************************************
* Find entry point for passwd *
*************************************************/
/* See local README for interface description */
int
dkim_find(void *handle, uschar *filename, uschar *keystring, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
#ifdef EXPERIMENTAL_DKIM
dkim_exim_verify_result(keystring,result,errmsg);
return OK;
#else
*errmsg = US"DKIM support not compiled.";
*result = US"unverified";
return FAIL;
#endif
}
/* End of lookups/dkim.c */
Index: dkim.h
====================================================================
/* $Cambridge: exim/exim-src/src/lookups/dkim.h,v 1.1 2007/09/28 12:21:57 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
/* Copyright (c) University of Cambridge 1995 - 2007 */
/* See the file NOTICE for conditions of use and distribution. */
/* Header for the DKIM lookup */
extern void *dkim_open(uschar *, uschar **);
extern int dkim_find(void *, uschar *, uschar *, int, uschar **, uschar **,
BOOL *);
/* End of lookups/dkim.h */
Index: Makefile
===================================================================
RCS file: /home/cvs/exim/exim-src/src/lookups/Makefile,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- Makefile 23 Aug 2007 10:16:51 -0000 1.6
+++ Makefile 28 Sep 2007 12:21:57 -0000 1.7
@@ -1,11 +1,11 @@
-# $Cambridge: exim/exim-src/src/lookups/Makefile,v 1.6 2007/08/23 10:16:51 ph10 Exp $
+# $Cambridge: exim/exim-src/src/lookups/Makefile,v 1.7 2007/09/28 12:21:57 tom Exp $
# Make file for building a library containing all the available lookups and
# calling it lookups.a. This is called from the main make file, after cd'ing
# to the lookups subdirectory. When the relevant LOOKUP_ macros are not
# defined, dummy modules get compiled.
-OBJ = cdb.o dbmdb.o dnsdb.o dsearch.o ibase.o ldap.o lsearch.o mysql.o nis.o \
+OBJ = cdb.o dbmdb.o dkim.o dnsdb.o dsearch.o ibase.o ldap.o lsearch.o mysql.o nis.o \
nisplus.o oracle.o passwd.o pgsql.o spf.o sqlite.o testdb.o whoson.o \
lf_check_file.o lf_quote.o lf_sqlperform.o
@@ -26,6 +26,7 @@
cdb.o: $(HDRS) cdb.c cdb.h
dbmdb.o: $(HDRS) dbmdb.c dbmdb.h
+dkim.o: $(HDRS) dkim.c dkim.h
dnsdb.o: $(HDRS) dnsdb.c dnsdb.h
dsearch.o: $(HDRS) dsearch.c dsearch.h
ibase.o: $(HDRS) ibase.c ibase.h
Index: smtp.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/transports/smtp.c,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -r1.37 -r1.38
--- smtp.c 18 Jun 2007 13:57:50 -0000 1.37
+++ smtp.c 28 Sep 2007 12:21:57 -0000 1.38
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/transports/smtp.c,v 1.37 2007/06/18 13:57:50 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/transports/smtp.c,v 1.38 2007/09/28 12:21:57 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -53,6 +53,20 @@
{ "dk_strict", opt_stringptr,
(void *)offsetof(smtp_transport_options_block, dk_strict) },
#endif
+#ifdef EXPERIMENTAL_DKIM
+ { "dkim_canon", opt_stringptr,
+ (void *)offsetof(smtp_transport_options_block, dkim_canon) },
+ { "dkim_domain", opt_stringptr,
+ (void *)offsetof(smtp_transport_options_block, dkim_domain) },
+ { "dkim_private_key", opt_stringptr,
+ (void *)offsetof(smtp_transport_options_block, dkim_private_key) },
+ { "dkim_selector", opt_stringptr,
+ (void *)offsetof(smtp_transport_options_block, dkim_selector) },
+ { "dkim_sign_headers", opt_stringptr,
+ (void *)offsetof(smtp_transport_options_block, dkim_sign_headers) },
+ { "dkim_strict", opt_stringptr,
+ (void *)offsetof(smtp_transport_options_block, dkim_strict) },
+#endif
{ "dns_qualify_single", opt_bool,
(void *)offsetof(smtp_transport_options_block, dns_qualify_single) },
{ "dns_search_parents", opt_bool,
@@ -203,6 +217,14 @@
NULL, /* dk_selector */
NULL /* dk_strict */
#endif
+ #ifdef EXPERIMENTAL_DKIM
+ ,NULL, /* dkim_canon */
+ NULL, /* dkim_domain */
+ NULL, /* dkim_private_key */
+ NULL, /* dkim_selector */
+ NULL, /* dkim_sign_headers */
+ NULL /* dkim_strict */
+ #endif
};
@@ -1590,6 +1612,23 @@
ob->dk_canon, ob->dk_headers, ob->dk_strict);
else
#endif
+#ifdef EXPERIMENTAL_DKIM
+ if ( (ob->dkim_private_key != NULL) && (ob->dkim_domain != NULL) && (ob->dkim_selector != NULL) )
+ ok = dkim_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->dkim_private_key, ob->dkim_domain, ob->dkim_selector,
+ ob->dkim_canon, ob->dkim_strict, ob->dkim_sign_headers);
+ 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.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- smtp.h 6 Feb 2007 14:49:13 -0000 1.12
+++ smtp.h 28 Sep 2007 12:21:57 -0000 1.13
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/transports/smtp.h,v 1.12 2007/02/06 14:49:13 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/transports/smtp.h,v 1.13 2007/09/28 12:21:57 tom Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -65,6 +65,14 @@
uschar *dk_headers;
uschar *dk_strict;
#endif
+ #ifdef EXPERIMENTAL_DKIM
+ uschar *dkim_domain;
+ uschar *dkim_private_key;
+ uschar *dkim_selector;
+ uschar *dkim_canon;
+ uschar *dkim_sign_headers;
+ uschar *dkim_strict;
+ #endif
} smtp_transport_options_block;
/* Data for reading the private options. */