From 139a79a1191d8987d7c172d4c55e2daf62f9b1ff Mon Sep 17 00:00:00 2001 From: Todd Lyons Date: Tue, 28 Aug 2012 07:48:20 -0700 Subject: [PATCH] Call PRDR acl after data phase, once for each rcpt Does not yet handle all conditions. Wrap all PRDR code in EXPERIMENTAL_PRDR #ifdef. --- src/src/acl.c | 70 ++++++++++++++++++++++++++++++++++----- src/src/config.h.defaults | 1 + src/src/exim.c | 3 ++ src/src/globals.c | 14 ++++++-- src/src/globals.h | 5 +++ src/src/local_scan.h | 3 ++ src/src/macros.h | 3 ++ src/src/readconf.c | 5 +++ src/src/receive.c | 32 ++++++++++++++++++ src/src/smtp_in.c | 40 ++++++++++++++++------ 10 files changed, 155 insertions(+), 21 deletions(-) diff --git a/src/src/acl.c b/src/src/acl.c index 3b23a915b..7d9422992 100644 --- a/src/src/acl.c +++ b/src/src/acl.c @@ -368,6 +368,9 @@ static unsigned int cond_forbids[] = { (unsigned int) ~((1< 1 ) cancel_cutthrough_connection("more than one recipient"); else if (rc == OK && cutthrough_delivery && cutthrough_fd < 0) diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults index ef83621b3..7fdab92da 100644 --- a/src/src/config.h.defaults +++ b/src/src/config.h.defaults @@ -166,6 +166,7 @@ it's a default value. */ #define EXPERIMENTAL_BRIGHTMAIL #define EXPERIMENTAL_DCC #define EXPERIMENTAL_OCSP +#define EXPERIMENTAL_PRDR #define EXPERIMENTAL_SPF #define EXPERIMENTAL_SRS diff --git a/src/src/exim.c b/src/src/exim.c index a59cfea9a..f55db7445 100644 --- a/src/src/exim.c +++ b/src/src/exim.c @@ -816,6 +816,9 @@ fprintf(f, "Support for:"); #ifdef EXPERIMENTAL_DCC fprintf(f, " Experimental_DCC"); #endif +#ifdef EXPERIMENTAL_PRDR + fprintf(f, " Experimental_PRDR"); +#endif fprintf(f, "\n"); fprintf(f, "Lookups (built-in):"); diff --git a/src/src/globals.c b/src/src/globals.c index 91a888d7b..4a68dd133 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -143,10 +143,12 @@ uschar *tls_verify_certificates= NULL; uschar *tls_verify_hosts = NULL; #endif +#ifdef EXPERIMENTAL_PRDR /* Per Recipient Data Response variables */ BOOL prdr_enable = TRUE; BOOL prdr_requested = FALSE; -recipient_item *prdr_recipients_list = NULL; +//recipient_item *prdr_recipients_list = NULL; +#endif /* Input-reading functions for messages, so we can use special ones for incoming TCP/IP. The defaults use stdin. We never need these for any @@ -204,7 +206,9 @@ uschar *acl_removed_headers = NULL; uschar *acl_smtp_auth = NULL; uschar *acl_smtp_connect = NULL; uschar *acl_smtp_data = NULL; +#ifdef EXPERIMENTAL_PRDR uschar *acl_smtp_data_prdr = NULL; +#endif #ifndef DISABLE_DKIM uschar *acl_smtp_dkim = NULL; #endif @@ -251,7 +255,9 @@ uschar *acl_wherenames[] = { US"RCPT", US"STARTTLS", US"VRFY", US"expansion" - US"PRDR" + #ifdef EXPERIMENTAL_PRDR + , US"PRDR" + #endif }; uschar *acl_wherecodes[] = { US"550", /* RCPT */ @@ -273,7 +279,9 @@ uschar *acl_wherecodes[] = { US"550", /* RCPT */ US"550", /* STARTTLS */ US"252", /* VRFY */ US"0" /* unknown; not relevant */ - US"550", /* RCPT PRDR */ + #ifdef EXPERIMENTAL_PRDR + ,US"550" /* RCPT PRDR */ + #endif }; BOOL active_local_from_check = FALSE; diff --git a/src/src/globals.h b/src/src/globals.h index 643cf5663..2e2cde281 100644 --- a/src/src/globals.h +++ b/src/src/globals.h @@ -146,6 +146,9 @@ extern uschar *acl_removed_headers; /* Headers deleted by an ACL */ extern uschar *acl_smtp_auth; /* ACL run for AUTH */ extern uschar *acl_smtp_connect; /* ACL run on SMTP connection */ extern uschar *acl_smtp_data; /* ACL run after DATA received */ +#ifdef EXPERIMENTAL_PRDR +extern uschar *acl_smtp_data_prdr; /* ACL run after DATA received if in PRDR mode*/ +#endif #ifndef DISABLE_DKIM extern uschar *acl_smtp_dkim; /* ACL run for DKIM signatures / domains */ #endif @@ -556,8 +559,10 @@ extern uschar *percent_hack_domains; /* Local domains for which '% operates */ extern uschar *pid_file_path; /* For writing daemon pids */ extern uschar *pipelining_advertise_hosts; /* As it says */ extern BOOL pipelining_enable; /* As it says */ +#ifdef EXPERIMENTAL_PRDR extern BOOL prdr_enable; /* As it says */ extern BOOL prdr_requested; /* Connecting mail server wants PRDR */ +#endif extern BOOL preserve_message_logs; /* Save msglog files */ extern uschar *primary_hostname; /* Primary name of this computer */ extern BOOL print_topbitchars; /* Topbit chars are printing chars */ diff --git a/src/src/local_scan.h b/src/src/local_scan.h index 057e4d428..2aa6df887 100644 --- a/src/src/local_scan.h +++ b/src/src/local_scan.h @@ -131,6 +131,9 @@ typedef struct recipient_item { #ifdef EXPERIMENTAL_BRIGHTMAIL uschar *bmi_optin; #endif +#ifdef EXPERIMENTAL_PRDR + int prdr_rc; /* ACL return code for this recipient */ +#endif } recipient_item; diff --git a/src/src/macros.h b/src/src/macros.h index cec4733f6..1f5d69b1c 100644 --- a/src/src/macros.h +++ b/src/src/macros.h @@ -811,6 +811,9 @@ enum { ACL_WHERE_RCPT, /* Some controls are for RCPT only */ ACL_WHERE_MIME, /* ) implemented by <= WHERE_NOTSMTP */ ACL_WHERE_DKIM, /* ) */ ACL_WHERE_DATA, /* ) */ +#ifdef EXPERIMENTAL_PRDR + ACL_WHERE_PRDR, /* ) */ +#endif ACL_WHERE_NOTSMTP, /* ) */ ACL_WHERE_AUTH, /* These remaining ones are not currently */ diff --git a/src/src/readconf.c b/src/src/readconf.c index 1d66ef870..9ab54e0d2 100644 --- a/src/src/readconf.c +++ b/src/src/readconf.c @@ -140,6 +140,9 @@ static optionlist optionlist_config[] = { { "acl_smtp_auth", opt_stringptr, &acl_smtp_auth }, { "acl_smtp_connect", opt_stringptr, &acl_smtp_connect }, { "acl_smtp_data", opt_stringptr, &acl_smtp_data }, +#ifdef EXPERIMENTAL_PRDR + { "acl_smtp_data_prdr", opt_stringptr, &acl_smtp_data_prdr }, +#endif #ifndef DISABLE_DKIM { "acl_smtp_dkim", opt_stringptr, &acl_smtp_dkim }, #endif @@ -316,7 +319,9 @@ static optionlist optionlist_config[] = { #endif { "pid_file_path", opt_stringptr, &pid_file_path }, { "pipelining_advertise_hosts", opt_stringptr, &pipelining_advertise_hosts }, +#ifdef EXPERIMENTAL_PRDR { "prdr_enable", opt_bool, &prdr_enable }, +#endif { "preserve_message_logs", opt_bool, &preserve_message_logs }, { "primary_hostname", opt_stringptr, &primary_hostname }, { "print_topbitchars", opt_bool, &print_topbitchars }, diff --git a/src/src/receive.c b/src/src/receive.c index 7b51805dc..33e1eb9f6 100644 --- a/src/src/receive.c +++ b/src/src/receive.c @@ -3195,6 +3195,38 @@ else goto TIDYUP; #endif /* WITH_CONTENT_SCAN */ +#ifdef EXPERIMENTAL_PRDR + unsigned int c; + if (prdr_requested && recipients_count > 0 && acl_smtp_data_prdr != NULL ) + { + // for loop through recipients. Must stay in order received because + // responses must be in same order. + + for (c = 0; recipients_count > c; c++) + { + DEBUG(D_receive) + debug_printf("PRDR processing recipient %s (%d of %d)\n", + recipients_list[c].address, c+1, recipients_count); + rc = acl_check(ACL_WHERE_PRDR, recipients_list[c].address, acl_smtp_data_prdr, &user_msg, &log_msg); + recipients_list[c].prdr_rc = rc; + //add_acl_headers(US"PRDR"); + //if (rc == DISCARD) + // { + // blackholed_by = US"PRDR ACL"; + // if (log_msg != NULL) + // blackhole_log_msg = string_sprintf(": %s", log_msg); + // if (smtp_handle_acl_fail(ACL_WHERE_PRDR, rc, user_msg, log_msg) != 0) + // smtp_yield = FALSE; + // smtp_reply = US""; + // message_id[0] = 0; + // } + } + DEBUG(D_receive) debug_printf("Finished acl_smtp_data_prdr\n"); + } + /* Kinda ugly, but turns the next if into an else-if */ + else +#endif /* EXPERIMENTAL_PRDR */ + /* Check the recipients count again, as the MIME ACL might have changed them. */ diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c index 41c64bdc5..01269d76a 100644 --- a/src/src/smtp_in.c +++ b/src/src/smtp_in.c @@ -210,7 +210,10 @@ static uschar *protocols[] = { /* Sanity check and validate optional args to MAIL FROM: envelope */ enum { ENV_MAIL_OPT_SIZE, ENV_MAIL_OPT_BODY, ENV_MAIL_OPT_AUTH, - ENV_MAIL_OPT_PRDR, ENV_MAIL_OPT_NULL +#ifdef EXPERIMENTAL_PRDR + ENV_MAIL_OPT_PRDR, +#endif + ENV_MAIL_OPT_NULL }; typedef struct { uschar * name; /* option requested during MAIL cmd */ @@ -222,7 +225,9 @@ static env_mail_type_t env_mail_type_list[] = { { US"SIZE", ENV_MAIL_OPT_SIZE, TRUE }, { US"BODY", ENV_MAIL_OPT_BODY, TRUE }, { US"AUTH", ENV_MAIL_OPT_AUTH, TRUE }, +#ifdef EXPERIMENTAL_PRDR { US"PRDR", ENV_MAIL_OPT_PRDR, FALSE }, +#endif { US"NULL", ENV_MAIL_OPT_NULL, FALSE } }; @@ -2206,6 +2211,9 @@ uschar *what = #endif (where == ACL_WHERE_PREDATA)? US"DATA" : (where == ACL_WHERE_DATA)? US"after DATA" : +#ifdef EXPERIMENTAL_PRDR + (where == ACL_WHERE_PRDR)? US"after DATA PRDR" : +#endif (smtp_cmd_data == NULL)? string_sprintf("%s in \"connect\" ACL", acl_wherenames[where]) : string_sprintf("%s %s", acl_wherenames[where], smtp_cmd_data); @@ -3183,11 +3191,13 @@ while (done <= 0) } #endif + #ifdef EXPERIMENTAL_PRDR /* Per Recipient Data Response, draft by Eric A. Hall extending RFC */ if (prdr_enable) { s = string_cat(s, &size, &ptr, smtp_code, 3); s = string_cat(s, &size, &ptr, US"-PRDR\r\n", 7); } + #endif /* Finish off the multiline reply with one that is always available. */ @@ -3408,10 +3418,12 @@ while (done <= 0) } break; +#ifdef EXPERIMENTAL_PRDR case ENV_MAIL_OPT_PRDR: if ( prdr_enable ) prdr_requested = TRUE; break; +#endif /* Unknown option. Stick back the terminator characters and break the loop. An error for a malformed address will occur. */ @@ -3543,14 +3555,19 @@ BAD_MAIL_ARGS: { if (user_msg == NULL) smtp_printf("%s%s%s", US"250 OK", - prdr_requested == TRUE ? US", PRDR Requested" : US"", + #ifdef EXPERIMENTAL_PRDR + prdr_requested == TRUE ? US", PRDR Requested" : + #endif + US"", US"\r\n"); - else - { - if ( prdr_requested == TRUE ) - user_msg = string_sprintf(US"%s%s", user_msg, US", PRDR Requested"); - smtp_user_msg(US"250",user_msg); - } + else + { + #ifdef EXPERIMENTAL_PRDR + if ( prdr_requested == TRUE ) + user_msg = string_sprintf(US"%s%s", user_msg, US", PRDR Requested"); + #endif + smtp_user_msg(US"250",user_msg); + } smtp_delay_rcpt = smtp_rlr_base; recipients_discarded = (rc == DISCARD); was_rej_mail = FALSE; @@ -3815,9 +3832,12 @@ BAD_MAIL_ARGS: if (rc == OK) { uschar * code; - code = prdr_requested ? "353" : "354"; + code = US"354"; + #ifdef EXPERIMENTAL_PRDR + code = prdr_requested ? US"353" : code; + #endif if (user_msg == NULL) - smtp_printf("%i Enter message, ending with \".\" on a line by itself\r\n", code); + smtp_printf("%s Enter message, ending with \".\" on a line by itself\r\n", code); else smtp_user_msg(code, user_msg); done = 3; message_ended = END_NOTENDED; /* Indicate in middle of data */ -- 2.25.1