From d77d4c27f76238f21d1bd0dd579a4f48ca72f158 Mon Sep 17 00:00:00 2001 From: Todd Lyons Date: Sat, 17 Mar 2012 07:24:30 -0700 Subject: [PATCH] PRDR Server support * Basic ACL variable, global enable variable, HELO content * Detect incoming PRDR request * Respond with affirmative when PRDR requested * Adjust DATA response if PRDR was requested. --- src/src/globals.c | 7 ++++++ src/src/globals.h | 2 ++ src/src/readconf.c | 1 + src/src/smtp_in.c | 59 +++++++++++++++++++++++++++++++++------------- 4 files changed, 53 insertions(+), 16 deletions(-) diff --git a/src/src/globals.c b/src/src/globals.c index bcbe12d82..91a888d7b 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -143,6 +143,10 @@ uschar *tls_verify_certificates= NULL; uschar *tls_verify_hosts = NULL; #endif +/* Per Recipient Data Response variables */ +BOOL prdr_enable = TRUE; +BOOL prdr_requested = FALSE; +recipient_item *prdr_recipients_list = NULL; /* 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 @@ -200,6 +204,7 @@ uschar *acl_removed_headers = NULL; uschar *acl_smtp_auth = NULL; uschar *acl_smtp_connect = NULL; uschar *acl_smtp_data = NULL; +uschar *acl_smtp_data_prdr = NULL; #ifndef DISABLE_DKIM uschar *acl_smtp_dkim = NULL; #endif @@ -246,6 +251,7 @@ uschar *acl_wherenames[] = { US"RCPT", US"STARTTLS", US"VRFY", US"expansion" + US"PRDR" }; uschar *acl_wherecodes[] = { US"550", /* RCPT */ @@ -267,6 +273,7 @@ uschar *acl_wherecodes[] = { US"550", /* RCPT */ US"550", /* STARTTLS */ US"252", /* VRFY */ US"0" /* unknown; not relevant */ + US"550", /* RCPT PRDR */ }; BOOL active_local_from_check = FALSE; diff --git a/src/src/globals.h b/src/src/globals.h index 16caa41e9..643cf5663 100644 --- a/src/src/globals.h +++ b/src/src/globals.h @@ -556,6 +556,8 @@ 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 */ +extern BOOL prdr_enable; /* As it says */ +extern BOOL prdr_requested; /* Connecting mail server wants PRDR */ 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/readconf.c b/src/src/readconf.c index ddd81d1d3..1d66ef870 100644 --- a/src/src/readconf.c +++ b/src/src/readconf.c @@ -316,6 +316,7 @@ static optionlist optionlist_config[] = { #endif { "pid_file_path", opt_stringptr, &pid_file_path }, { "pipelining_advertise_hosts", opt_stringptr, &pipelining_advertise_hosts }, + { "prdr_enable", opt_bool, &prdr_enable }, { "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/smtp_in.c b/src/src/smtp_in.c index b1fea9daf..41c64bdc5 100644 --- a/src/src/smtp_in.c +++ b/src/src/smtp_in.c @@ -222,7 +222,8 @@ 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 }, - { US"NULL", ENV_MAIL_OPT_NULL, FALSE } /* Placeholder for ending */ + { US"PRDR", ENV_MAIL_OPT_PRDR, FALSE }, + { US"NULL", ENV_MAIL_OPT_NULL, FALSE } }; /* When reading SMTP from a remote host, we have to use our own versions of the @@ -998,19 +999,23 @@ uschar *n; uschar *v = smtp_cmd_data + Ustrlen(smtp_cmd_data) - 1; while (isspace(*v)) v--; v[1] = 0; - while (v > smtp_cmd_data && *v != '=' && !isspace(*v)) v--; -if (*v != '=') return FALSE; n = v; -while(isalpha(n[-1])) n--; - -/* RFC says SP, but TAB seen in wild and other major MTAs accept it */ -if (!isspace(n[-1])) return FALSE; - -n[-1] = 0; -*name = n; +if (*v == '=') +{ + while(isalpha(n[-1])) n--; + /* RFC says SP, but TAB seen in wild and other major MTAs accept it */ + if (!isspace(n[-1])) return FALSE; + n[-1] = 0; +} +else +{ + n++; + if (v == smtp_cmd_data) return FALSE; +} *v++ = 0; +*name = n; *value = v; return TRUE; } @@ -3119,6 +3124,7 @@ while (done <= 0) pipelining_advertised = TRUE; } + /* If any server authentication mechanisms are configured, advertise them if the current host is in auth_advertise_hosts. The problem with advertising always is that some clients then require users to @@ -3177,6 +3183,12 @@ while (done <= 0) } #endif + /* 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); + } + /* Finish off the multiline reply with one that is always available. */ s = string_cat(s, &size, &ptr, smtp_code, 3); @@ -3395,12 +3407,17 @@ while (done <= 0) } } break; - + + case ENV_MAIL_OPT_PRDR: + if ( prdr_enable ) + prdr_requested = TRUE; + break; + /* Unknown option. Stick back the terminator characters and break the loop. An error for a malformed address will occur. */ default: - /* BAD_MAIL_ARGS: */ +BAD_MAIL_ARGS: name[-1] = ' '; value[-1] = '='; break; @@ -3524,8 +3541,16 @@ while (done <= 0) if (rc == OK || rc == DISCARD) { - if (user_msg == NULL) smtp_printf("250 OK\r\n"); - else smtp_user_msg(US"250", user_msg); + if (user_msg == NULL) + smtp_printf("%s%s%s", US"250 OK", + prdr_requested == TRUE ? US", PRDR Requested" : 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); + } smtp_delay_rcpt = smtp_rlr_base; recipients_discarded = (rc == DISCARD); was_rej_mail = FALSE; @@ -3789,9 +3814,11 @@ while (done <= 0) if (rc == OK) { + uschar * code; + code = prdr_requested ? "353" : "354"; if (user_msg == NULL) - smtp_printf("354 Enter message, ending with \".\" on a line by itself\r\n"); - else smtp_user_msg(US"354", user_msg); + smtp_printf("%i 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