Link Here
|
|
|
1 |
|
2 |
--- src/globals.c.orig 2007-12-10 18:59:58.297661332 +0300 |
3 |
+++ src/globals.c 2007-12-10 19:00:22.299029091 +0300 |
4 |
@@ -621,6 +621,7 @@ |
5 |
BOOL helo_verified = FALSE; |
6 |
BOOL helo_verify_failed = FALSE; |
7 |
uschar *helo_verify_hosts = NULL; |
8 |
+uschar *xclient_allow_hosts = NULL; |
9 |
uschar *hex_digits = US"0123456789abcdef"; |
10 |
uschar *hold_domains = NULL; |
11 |
BOOL host_checking = FALSE; |
12 |
--- src/globals.h.orig 2007-12-10 19:11:45.337953260 +0300 |
13 |
+++ src/globals.h 2007-12-10 19:12:42.341201691 +0300 |
14 |
@@ -367,6 +367,7 @@ |
15 |
extern BOOL helo_verified; /* True if HELO verified */ |
16 |
extern BOOL helo_verify_failed; /* True if attempt failed */ |
17 |
extern uschar *helo_verify_hosts; /* Hard check HELO argument for these */ |
18 |
+extern uschar *xclient_allow_hosts; /* Allow XCLIENT command for specified hosts */ |
19 |
extern uschar *hex_digits; /* Used in several places */ |
20 |
extern uschar *hold_domains; /* Hold up deliveries to these */ |
21 |
extern BOOL host_find_failed_syntax;/* DNS syntax check failure */ |
22 |
--- src/macros.h.orig 2007-08-30 18:31:06.000000000 +0400 |
23 |
+++ src/macros.h 2007-12-10 17:36:29.512226916 +0300 |
24 |
@@ -714,7 +714,7 @@ |
25 |
|
26 |
enum { SCH_NONE, SCH_AUTH, SCH_DATA, SCH_EHLO, SCH_ETRN, SCH_EXPN, SCH_HELO, |
27 |
SCH_HELP, SCH_MAIL, SCH_NOOP, SCH_QUIT, SCH_RCPT, SCH_RSET, SCH_STARTTLS, |
28 |
- SCH_VRFY }; |
29 |
+ SCH_VRFY, SCH_XCLIENT }; |
30 |
|
31 |
/* Returns from host_find_by{name,dns}() */ |
32 |
|
33 |
--- src/readconf.c.orig 2007-12-10 19:03:32.809885687 +0300 |
34 |
+++ src/readconf.c 2007-12-10 19:13:37.344336141 +0300 |
35 |
@@ -404,7 +404,8 @@ |
36 |
{ "uucp_from_pattern", opt_stringptr, &uucp_from_pattern }, |
37 |
{ "uucp_from_sender", opt_stringptr, &uucp_from_sender }, |
38 |
{ "warn_message_file", opt_stringptr, &warn_message_file }, |
39 |
- { "write_rejectlog", opt_bool, &write_rejectlog } |
40 |
+ { "write_rejectlog", opt_bool, &write_rejectlog }, |
41 |
+ { "xclient_allow_hosts", opt_stringptr, &xclient_allow_hosts }, |
42 |
}; |
43 |
|
44 |
static int optionlist_config_size = |
45 |
--- src/smtp_in.c.orig 2007-12-10 15:54:30.000000000 +0300 |
46 |
+++ src/smtp_in.c 2009-02-03 17:29:33.181798456 +0300 |
47 |
@@ -63,10 +63,10 @@ |
48 |
/* These commands are required to be synchronized, i.e. to be the last in a |
49 |
block of commands when pipelining. */ |
50 |
|
51 |
- HELO_CMD, EHLO_CMD, DATA_CMD, /* These are listed in the pipelining */ |
52 |
- VRFY_CMD, EXPN_CMD, NOOP_CMD, /* RFC as requiring synchronization */ |
53 |
- ETRN_CMD, /* This by analogy with TURN from the RFC */ |
54 |
- STARTTLS_CMD, /* Required by the STARTTLS RFC */ |
55 |
+ HELO_CMD, EHLO_CMD, XCLIENT_CMD, DATA_CMD, /* These are listed in the pipelining */ |
56 |
+ VRFY_CMD, EXPN_CMD, NOOP_CMD, /* RFC as requiring synchronization */ |
57 |
+ ETRN_CMD, /* This by analogy with TURN from the RFC */ |
58 |
+ STARTTLS_CMD, /* Required by the STARTTLS RFC */ |
59 |
|
60 |
/* This is a dummy to identify the non-sync commands when pipelining */ |
61 |
|
62 |
@@ -152,6 +152,7 @@ |
63 |
{ "rset", sizeof("rset")-1, RSET_CMD, FALSE, FALSE }, /* First */ |
64 |
{ "helo", sizeof("helo")-1, HELO_CMD, TRUE, FALSE }, |
65 |
{ "ehlo", sizeof("ehlo")-1, EHLO_CMD, TRUE, FALSE }, |
66 |
+ { "xclient", sizeof("xclient")-1, XCLIENT_CMD, TRUE, FALSE }, |
67 |
{ "auth", sizeof("auth")-1, AUTH_CMD, TRUE, TRUE }, |
68 |
#ifdef SUPPORT_TLS |
69 |
{ "starttls", sizeof("starttls")-1, STARTTLS_CMD, FALSE, FALSE }, |
70 |
@@ -184,7 +185,7 @@ |
71 |
|
72 |
static uschar *smtp_names[] = |
73 |
{ |
74 |
- US"NONE", US"AUTH", US"DATA", US"EHLO", US"ETRN", US"EXPN", US"HELO", |
75 |
+ US"NONE", US"AUTH", US"DATA", US"EHLO", US"ETRN", US"EXPN", US"HELO", US"XCLIENT", |
76 |
US"HELP", US"MAIL", US"NOOP", US"QUIT", US"RCPT", US"RSET", US"STARTTLS", |
77 |
US"VRFY" }; |
78 |
|
79 |
@@ -847,6 +848,205 @@ |
80 |
} |
81 |
|
82 |
|
83 |
+/************************************************* |
84 |
+* Check XCLIENT line and set sender_address * |
85 |
+*************************************************/ |
86 |
+ |
87 |
+/* Check the format of a XCLIENT line. |
88 |
+ * XCLIENT Command syntax |
89 |
+ * |
90 |
+ * An example client-server conversation is given at the end of this document. |
91 |
+ * |
92 |
+ * In SMTP server EHLO replies, the keyword associated with this extension is XCLIENT. It is followed by the names of the attributes that the XCLIENT implementation supports. |
93 |
+ * |
94 |
+ * The XCLIENT command may be sent at any time, except in the middle of a mail delivery transaction (i.e. between MAIL and DOT, or MAIL and RSET). |
95 |
+ * The XCLIENT command may be pipelined when the server supports ESMTP command pipelining. |
96 |
+ * To avoid triggering spamware detectors, the command should be sent at the end of a command group. |
97 |
+ * |
98 |
+ * The syntax of XCLIENT requests is described below. |
99 |
+ * Upper case and quoted strings specify terminals, lowercase strings specify meta terminals, and SP is whitespace. |
100 |
+ * Although command and attribute names are shown in upper case, they are in fact case insensitive. |
101 |
+ * |
102 |
+ * xclient-command = XCLIENT 1*( SP attribute-name"="attribute-value ) |
103 |
+ * |
104 |
+ * attribute-name = ( NAME | ADDR | PORT | HELO | PROTO | LOGIN) |
105 |
+ * |
106 |
+ * attribute-value = xtext |
107 |
+ * |
108 |
+ * Attribute values are xtext encoded as per RFC 1891. |
109 |
+ * The NAME attribute specifies an SMTP client hostname (not an SMTP client address), [UNAVAILABLE] when client hostname lookup failed due to a permanent error, or [TEMPUNAVAIL] when the lookup error condition was transient. |
110 |
+ * |
111 |
+ * The ADDR attribute specifies an SMTP client numerical IPv4 network address, an IPv6 address prefixed with IPV6:, or [UNAVAILABLE] when the address information is unavailable. Address information is not enclosed with []. |
112 |
+ * |
113 |
+ * The PORT attribute specifies the SMTP client TCP port number as a decimal number, or [UNAVAILABLE] when the information is unavailable. |
114 |
+ * The HELO attribute specifies an SMTP HELO parameter value, or the value [UNAVAILABLE] when the information is unavailable. |
115 |
+ * The PROTO attribute specifies either SMTP or ESMTP. |
116 |
+ * |
117 |
+ * Note 1: syntactically valid NAME and HELO attribute-value elements can be up to 255 characters long. |
118 |
+ * The client must not send XCLIENT commands that exceed the 512 character limit for SMTP commands. |
119 |
+ * To avoid exceeding the limit the client should send the information in multiple XCLIENT commands; for example, send NAME and ADDR first, then HELO and PROTO. |
120 |
+ * |
121 |
+ * Note 2: [UNAVAILABLE], [TEMPUNAVAIL] and IPV6: may be specified in upper case, lower case or mixed case. |
122 |
+Argument: |
123 |
+ s the data portion of the line (already past any white space) |
124 |
+ |
125 |
+Returns: TRUE |
126 |
+ FALSE |
127 |
+*/ |
128 |
+ |
129 |
+/* XCLIENT MACROS */ |
130 |
+#define XCLIENT_UNAVAIL US"[UNAVAILABLE]" |
131 |
+#define XCLIENT_TEMPUNAVAIL US"[TEMPUNAVAIL]" |
132 |
+ |
133 |
+static BOOL |
134 |
+smtp_handle_xclient(uschar *s) |
135 |
+{ |
136 |
+ uschar *p, *end, *arg; |
137 |
+ int len; |
138 |
+ p = s; |
139 |
+ end = s + Ustrlen(s); |
140 |
+ |
141 |
+ while (p <= end) { |
142 |
+ /* Addr */ |
143 |
+ if (strncmpic(p, US"ADDR=", 5) == 0) { |
144 |
+ p += 5; |
145 |
+ arg = p; |
146 |
+ while (*p++ != ' ' && p <= end ); |
147 |
+ len = p - arg; |
148 |
+ /* Strip whitespace */ |
149 |
+ if(*(p - 1) == ' ') { |
150 |
+ len --; |
151 |
+ } |
152 |
+ if (len > 0) { |
153 |
+ sender_host_address = string_copy_malloc(string_copyn(arg, len)); |
154 |
+ } |
155 |
+ else { |
156 |
+ return FALSE; |
157 |
+ } |
158 |
+ } |
159 |
+ /* Name */ |
160 |
+ else if (strncmpic(p, US"NAME=", 5) == 0) { |
161 |
+ p += 5; |
162 |
+ arg = p; |
163 |
+ while (*p++ != ' ' && p <= end ); |
164 |
+ len = p - arg; |
165 |
+ /* Strip whitespace */ |
166 |
+ if(*(p - 1) == ' ') { |
167 |
+ len --; |
168 |
+ } |
169 |
+ if (len > 0) { |
170 |
+ if ((len == sizeof(XCLIENT_UNAVAIL) - 1 && strncmpic(arg, XCLIENT_UNAVAIL, sizeof (XCLIENT_UNAVAIL) -1) == 0) || |
171 |
+ (len == sizeof(XCLIENT_TEMPUNAVAIL) - 1 && strncmpic(arg, XCLIENT_TEMPUNAVAIL, sizeof (XCLIENT_UNAVAIL) -1) == 0)) { |
172 |
+ sender_host_name = NULL; |
173 |
+ } |
174 |
+ else { |
175 |
+ sender_host_name = string_copy_malloc(string_copyn(arg, len)); |
176 |
+ } |
177 |
+ } |
178 |
+ else { |
179 |
+ return FALSE; |
180 |
+ } |
181 |
+ } |
182 |
+ /* Helo */ |
183 |
+ else if (strncmpic(p, US"HELO=", 5) == 0) { |
184 |
+ p += 5; |
185 |
+ arg = p; |
186 |
+ while (*p++ != ' ' && p <= end ); |
187 |
+ len = p - arg; |
188 |
+ /* Strip whitespace */ |
189 |
+ if(*(p - 1) == ' ') { |
190 |
+ len --; |
191 |
+ } |
192 |
+ |
193 |
+ if (len > 0) { |
194 |
+ if ((len == sizeof(XCLIENT_UNAVAIL) - 1 && strncmpic(arg, XCLIENT_UNAVAIL, sizeof (XCLIENT_UNAVAIL) -1) == 0) || |
195 |
+ (len == sizeof(XCLIENT_TEMPUNAVAIL) - 1 && strncmpic(arg, XCLIENT_TEMPUNAVAIL, sizeof (XCLIENT_UNAVAIL) -1) == 0)) { |
196 |
+ sender_helo_name = NULL; |
197 |
+ } |
198 |
+ else { |
199 |
+ sender_helo_name = string_copy_malloc(string_copyn(arg, len)); |
200 |
+ } |
201 |
+ } |
202 |
+ else { |
203 |
+ return FALSE; |
204 |
+ } |
205 |
+ } |
206 |
+ /* Port */ |
207 |
+ else if (strncmpic(p, US"PORT=", 5) == 0) { |
208 |
+ p += 5; |
209 |
+ arg = p; |
210 |
+ while (*p++ != ' ' && p <= end); |
211 |
+ len = p - arg; |
212 |
+ if(*(p - 1) == ' ') { |
213 |
+ len --; |
214 |
+ } |
215 |
+ if (len > 0) { |
216 |
+ if ((len == sizeof(XCLIENT_UNAVAIL) - 1 && strncmpic(arg, XCLIENT_UNAVAIL, sizeof (XCLIENT_UNAVAIL) -1) == 0) || |
217 |
+ (len == sizeof(XCLIENT_TEMPUNAVAIL) - 1 && strncmpic(arg, XCLIENT_TEMPUNAVAIL, sizeof (XCLIENT_UNAVAIL) -1) == 0)) { |
218 |
+ sender_host_port = 0; |
219 |
+ } |
220 |
+ else { |
221 |
+ sender_host_port = Uatoi(arg); |
222 |
+ } |
223 |
+ } |
224 |
+ else { |
225 |
+ return FALSE; |
226 |
+ } |
227 |
+ } |
228 |
+ /* Login */ |
229 |
+ else if (strncmpic(p, US"LOGIN=", 6) == 0) { |
230 |
+ p += 6; |
231 |
+ arg = p; |
232 |
+ while (*p++ != ' ' && p <= end); |
233 |
+ len = p - arg; |
234 |
+ if(*(p - 1) == ' ') { |
235 |
+ len --; |
236 |
+ } |
237 |
+ if (len > 0) { |
238 |
+ if ((len == sizeof(XCLIENT_UNAVAIL) - 1 && strncmpic(arg, XCLIENT_UNAVAIL, sizeof (XCLIENT_UNAVAIL) -1) == 0) || |
239 |
+ (len == sizeof(XCLIENT_TEMPUNAVAIL) - 1 && strncmpic(arg, XCLIENT_TEMPUNAVAIL, sizeof (XCLIENT_UNAVAIL) -1) == 0)) { |
240 |
+ authenticated_id = NULL; |
241 |
+ sender_host_authenticated = NULL; |
242 |
+ } |
243 |
+ else { |
244 |
+ authenticated_id = string_copy_malloc(string_copyn(arg, len)); |
245 |
+ sender_host_authenticated = "xclient"; |
246 |
+ authentication_failed = FALSE; |
247 |
+ } |
248 |
+ } |
249 |
+ else { |
250 |
+ return FALSE; |
251 |
+ } |
252 |
+ } |
253 |
+ /* Proto */ |
254 |
+ else if (strncmpic(p, US"PROTO=", 6) == 0) { |
255 |
+ p += 6; |
256 |
+ arg = p; |
257 |
+ while (*p++ != ' ' && p <= end); |
258 |
+ len = p - arg; |
259 |
+ if(*(p - 1) == ' ') { |
260 |
+ len --; |
261 |
+ } |
262 |
+ if (len > 0) { |
263 |
+ if (len == 4 && (strncmpic(arg, US"SMTP", 4) == 0)) { |
264 |
+ esmtp = FALSE; |
265 |
+ } |
266 |
+ else if (len == 5 && (strncmpic(arg, US"ESMTP", 5) == 0)) { |
267 |
+ esmtp = TRUE; |
268 |
+ } |
269 |
+ } |
270 |
+ } |
271 |
+ else { |
272 |
+ return FALSE; |
273 |
+ } |
274 |
+ } |
275 |
+ |
276 |
+ host_build_sender_fullhost(); |
277 |
+ return TRUE; |
278 |
+} |
279 |
+ |
280 |
+#undef XCLIENT_UNAVAIL |
281 |
+#undef XCLIENT_TEMPUNAVAIL |
282 |
|
283 |
/************************************************* |
284 |
* Check HELO line and set sender_helo_name * |
285 |
@@ -1131,6 +1331,11 @@ |
286 |
bsmtp_transaction_linecount = receive_linecount; |
287 |
break; |
288 |
|
289 |
+ /* Handle XCLIENT command */ |
290 |
+ case XCLIENT_CMD: |
291 |
+ smtp_handle_xclient(smtp_cmd_data); |
292 |
+ break; |
293 |
+ |
294 |
|
295 |
/* The MAIL FROM command requires an address as an operand. All we |
296 |
do here is to parse it for syntactic correctness. The form "<>" is |
297 |
@@ -3158,7 +3363,50 @@ |
298 |
toomany = FALSE; |
299 |
break; /* HELO/EHLO */ |
300 |
|
301 |
+ case XCLIENT_CMD: |
302 |
+ HAD(SCH_XCLIENT); |
303 |
+ smtp_mailcmd_count++; |
304 |
+ if (helo_required && !helo_seen) |
305 |
+ { |
306 |
+ smtp_printf("503 HELO or EHLO required\r\n"); |
307 |
+ log_write(0, LOG_MAIN|LOG_REJECT, "rejected XCLIENT from %s: no " |
308 |
+ "HELO/EHLO given", host_and_ident(FALSE)); |
309 |
+ break; |
310 |
+ } |
311 |
+ |
312 |
+ /* Check for an operand */ |
313 |
+ if (smtp_cmd_data[0] == 0) |
314 |
+ { |
315 |
+ done = synprot_error(L_smtp_syntax_error, 501, NULL, |
316 |
+ US"XCLIENT must have at least one operand"); |
317 |
+ break; |
318 |
+ } |
319 |
+ if(xclient_allow_hosts != NULL) |
320 |
+ { |
321 |
+ if (match_isinlist (sender_host_address, &xclient_allow_hosts, ':', NULL, NULL, MCL_NOEXPAND, FALSE, NULL) != OK) |
322 |
+ { |
323 |
+ done = synprot_error(L_smtp_syntax_error, 550, NULL, |
324 |
+ US"XCLIENT is not allowed"); |
325 |
+ break; |
326 |
+ } |
327 |
+ } |
328 |
+ else |
329 |
+ { |
330 |
+ done = synprot_error(L_smtp_syntax_error, 550, NULL, |
331 |
+ US"XCLIENT is not allowed"); |
332 |
+ break; |
333 |
+ } |
334 |
+ if(smtp_handle_xclient(smtp_cmd_data) == FALSE) |
335 |
+ { |
336 |
+ done = synprot_error(L_smtp_syntax_error, 501, NULL, |
337 |
+ US"bad command parameter syntax"); |
338 |
+ break; |
339 |
+ } |
340 |
+ smtp_code = US"220"; /* Default status code */ |
341 |
+ |
342 |
+ smtp_printf("%s XCLIENT success\r\n", smtp_code); |
343 |
|
344 |
+ break; /* XCLIENT */ |
345 |
/* The MAIL command requires an address as an operand. All we do |
346 |
here is to parse it for syntactic correctness. The form "<>" is |
347 |
a special case which converts into an empty string. The start/end |