1 --- src/smtpd/smtpd.h.org Wed Feb 9 03:00:14 2005
2 +++ src/smtpd/smtpd.h Mon Feb 7 20:06:58 2005
4 int sender_rcptmap_checked; /* sender validated against maps */
5 int recipient_rcptmap_checked; /* recipient validated against maps */
6 int warn_if_reject; /* force reject into warning */
7 + int header_if_reject; /* add header instead of rejecting */
8 SMTPD_DEFER defer_if_reject; /* force reject into deferral */
9 SMTPD_DEFER defer_if_permit; /* force permit into deferral */
10 int defer_if_permit_client; /* force permit into warning */
11 --- src/global/mail_params.h.org Wed Feb 9 03:01:31 2005
12 +++ src/global/mail_params.h Wed Feb 9 02:01:01 2005
14 #define CHECK_RECIP_NS_ACL "check_recipient_ns_access"
16 #define WARN_IF_REJECT "warn_if_reject"
17 +#define HEADER_IF_REJECT "header_if_reject"
19 #define REJECT_RBL "reject_rbl" /* LaMont compatibility */
20 #define REJECT_RBL_CLIENT "reject_rbl_client"
21 --- src/smtpd/smtpd_check.c.org Sat Dec 27 03:54:03 2003
22 +++ src/smtpd/smtpd_check.c Wed Feb 9 06:04:25 2005
24 * permit-style restriction fails. Otherwise, we could reject legitimate
27 -static void PRINTFLIKE(3, 4) defer_if(SMTPD_DEFER *, int, const char *,...);
28 +static void PRINTFLIKE(4, 5) defer_if(SMTPD_STATE *, SMTPD_DEFER *, int, const char *,...);
30 #define DEFER_IF_REJECT2(state, class, fmt, a1, a2) \
31 - defer_if(&(state)->defer_if_reject, (class), (fmt), (a1), (a2))
32 + defer_if((state), &(state)->defer_if_reject, (class), (fmt), (a1), (a2))
33 #define DEFER_IF_REJECT3(state, class, fmt, a1, a2, a3) \
34 - defer_if(&(state)->defer_if_reject, (class), (fmt), (a1), (a2), (a3))
35 + defer_if((state), &(state)->defer_if_reject, (class), (fmt), (a1), (a2), (a3))
36 #define DEFER_IF_REJECT4(state, class, fmt, a1, a2, a3, a4) \
37 defer_if(&(state)->defer_if_reject, (class), (fmt), (a1), (a2), (a3), (a4))
38 #define DEFER_IF_PERMIT2(state, class, fmt, a1, a2) do { \
39 if ((state)->warn_if_reject == 0) \
40 - defer_if(&(state)->defer_if_permit, (class), (fmt), (a1), (a2)); \
41 + defer_if((state), &(state)->defer_if_permit, (class), (fmt), (a1), (a2)); \
43 (void) smtpd_check_reject((state), (class), (fmt), (a1), (a2)); \
45 #define DEFER_IF_PERMIT3(state, class, fmt, a1, a2, a3) do { \
46 if ((state)->warn_if_reject == 0) \
47 - defer_if(&(state)->defer_if_permit, (class), (fmt), (a1), (a2), (a3)); \
48 + defer_if((state), &(state)->defer_if_permit, (class), (fmt), (a1), (a2), (a3)); \
50 (void) smtpd_check_reject((state), (class), (fmt), (a1), (a2), (a3)); \
52 #define DEFER_IF_PERMIT4(state, class, fmt, a1, a2, a3, a4) do { \
53 if ((state)->warn_if_reject == 0) \
54 - defer_if(&(state)->defer_if_permit, (class), (fmt), (a1), (a2), (a3), (a4)); \
55 + defer_if((state), &(state)->defer_if_permit, (class), (fmt), (a1), (a2), (a3), (a4)); \
57 (void) smtpd_check_reject((state), (class), (fmt), (a1), (a2), (a3), (a4)); \
64 + va_start(ap, format);
65 + vstring_vsprintf(error_text, format, ap);
68 + return(xsmtpd_check_reject(state, error_class, error_text));
70 +static int xsmtpd_check_reject(SMTPD_STATE *state, int error_class,
71 + VSTRING *error_text)
74 + int header_if_reject;
82 + if (state->header_if_reject && error_class != MAIL_ERROR_SOFTWARE) {
83 + header_if_reject = 1;
84 + whatsup = "header_warning";
86 + header_if_reject = 0;
90 * Update the error class mask, and format the response. XXX What about
91 * multi-line responses? For now we cheat and send whitespace.
93 state->error_mask |= error_class;
94 - va_start(ap, format);
95 - vstring_vsprintf(error_text, format, ap);
99 * Ensure RFC compliance. We could do this inside smtpd_chat_reply() and
100 @@ -796,15 +810,58 @@
102 log_whatsup(state, whatsup, STR(error_text));
104 - return (warn_if_reject ? 0 : SMTPD_CHECK_REJECT);
105 + if (state->header_if_reject) {
106 + VSTRING *hbuf = vstring_alloc(100);
107 + int elen = strlen(STR(error_text));
109 + if (state->prepend == 0)
110 + state->prepend = argv_alloc(1);
111 + printable(STR(error_text), '?');
113 +#define PRETTY_HEADER
114 +#ifdef PRETTY_HEADER
119 + vstring_sprintf(hbuf, "%s", "X-Reject: ");
120 + while (len < elen-65 && (p = strchr(STR(error_text)+len+64, ' '))) {
122 + n = p-(STR(error_text)+len);
123 + vstring_sprintf_append(hbuf, "%.*s\n", n, STR(error_text)+len);
126 + vstring_sprintf_append(hbuf, "%s", STR(error_text)+len);
129 + vstring_sprintf(hbuf, "X-Reject: %s", STR(error_text));
132 + vstring_sprintf(hbuf, "X-Reject: %.*s", 999, STR(error_text));
134 + argv_add(state->prepend, STR(hbuf), ARGV_END);
135 + vstring_free(hbuf);
138 + return (warn_if_reject || header_if_reject ? 0 : SMTPD_CHECK_REJECT);
141 /* defer_if - prepare to change our mind */
143 -static void defer_if(SMTPD_DEFER *defer, int error_class, const char *fmt,...)
144 +static void defer_if(SMTPD_STATE *state, SMTPD_DEFER *defer, int error_class, const char *fmt,...)
148 + if (state->header_if_reject) {
150 + vstring_vsprintf(error_text, fmt, ap);
152 + if (STR(error_text)[0] == '5') {
153 + xsmtpd_check_reject(state, error_class, error_text);
159 * Keep the first reason for this type of deferral, to minimize
161 @@ -3147,6 +3204,11 @@
162 state->warn_if_reject = state->recursion;
165 + if (strcasecmp(name, HEADER_IF_REJECT) == 0) {
166 + if (state->header_if_reject == 0)
167 + state->header_if_reject = state->recursion;
172 * Spoof the is_map_command() routine, so that we do not have to make
173 @@ -3500,6 +3562,8 @@
175 if (state->warn_if_reject >= state->recursion)
176 state->warn_if_reject = 0;
177 + if (state->header_if_reject >= state->recursion)
178 + state->header_if_reject = 0;
182 @@ -3554,6 +3618,7 @@
183 #define SMTPD_CHECK_RESET() { \
184 state->recursion = 0; \
185 state->warn_if_reject = 0; \
186 + state->header_if_reject = 0; \
187 state->defer_if_reject.active = 0; \