Mercurial > hg > nginx-quic
annotate src/mail/ngx_mail_parse.c @ 8450:2851e4c7de03
Mail: fixed reading with fully filled buffer (ticket #2159).
With SMTP pipelining, ngx_mail_read_command() can be called with s->buffer
without any space available, to parse additional commands received to the
buffer on previous calls. Previously, this resulted in recv() being called
with zero length, resulting in zero being returned, which was interpreted
as a connection close by the client, so nginx silently closed connection.
Fix is to avoid calling c->recv() if there is no free space in the buffer,
but continue parsing of the already received commands.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Wed, 21 Apr 2021 23:24:59 +0300 |
parents | bcb107bb89cd |
children | 6a81d96d3733 |
rev | line source |
---|---|
441
da8c5707af39
nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
1 |
da8c5707af39
nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
2 /* |
444
42d11f017717
nginx-0.1.0-2004-09-29-20:00:49 import; remove years from copyright
Igor Sysoev <igor@sysoev.ru>
parents:
441
diff
changeset
|
3 * Copyright (C) Igor Sysoev |
4412 | 4 * Copyright (C) Nginx, Inc. |
441
da8c5707af39
nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
5 */ |
da8c5707af39
nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
6 |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
7 |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
8 #include <ngx_config.h> |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
9 #include <ngx_core.h> |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
10 #include <ngx_event.h> |
1136 | 11 #include <ngx_mail.h> |
4759
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4412
diff
changeset
|
12 #include <ngx_mail_pop3_module.h> |
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4412
diff
changeset
|
13 #include <ngx_mail_imap_module.h> |
4c36e15651f7
Fixed compilation with -Wmissing-prototypes.
Ruslan Ermilov <ru@nginx.com>
parents:
4412
diff
changeset
|
14 #include <ngx_mail_smtp_module.h> |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
15 |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
16 |
1477 | 17 ngx_int_t |
18 ngx_mail_pop3_parse_command(ngx_mail_session_t *s) | |
1136 | 19 { |
20 u_char ch, *p, *c, c0, c1, c2, c3; | |
21 ngx_str_t *arg; | |
22 enum { | |
23 sw_start = 0, | |
24 sw_spaces_before_argument, | |
25 sw_argument, | |
26 sw_almost_done | |
27 } state; | |
28 | |
29 state = s->state; | |
30 | |
31 for (p = s->buffer->pos; p < s->buffer->last; p++) { | |
32 ch = *p; | |
33 | |
34 switch (state) { | |
35 | |
36 /* POP3 command */ | |
37 case sw_start: | |
38 if (ch == ' ' || ch == CR || ch == LF) { | |
39 c = s->buffer->start; | |
40 | |
41 if (p - c == 4) { | |
42 | |
43 c0 = ngx_toupper(c[0]); | |
44 c1 = ngx_toupper(c[1]); | |
45 c2 = ngx_toupper(c[2]); | |
46 c3 = ngx_toupper(c[3]); | |
47 | |
48 if (c0 == 'U' && c1 == 'S' && c2 == 'E' && c3 == 'R') | |
49 { | |
50 s->command = NGX_POP3_USER; | |
51 | |
52 } else if (c0 == 'P' && c1 == 'A' && c2 == 'S' && c3 == 'S') | |
53 { | |
54 s->command = NGX_POP3_PASS; | |
55 | |
56 } else if (c0 == 'A' && c1 == 'P' && c2 == 'O' && c3 == 'P') | |
57 { | |
58 s->command = NGX_POP3_APOP; | |
59 | |
60 } else if (c0 == 'Q' && c1 == 'U' && c2 == 'I' && c3 == 'T') | |
61 { | |
62 s->command = NGX_POP3_QUIT; | |
63 | |
64 } else if (c0 == 'C' && c1 == 'A' && c2 == 'P' && c3 == 'A') | |
65 { | |
66 s->command = NGX_POP3_CAPA; | |
67 | |
68 } else if (c0 == 'A' && c1 == 'U' && c2 == 'T' && c3 == 'H') | |
69 { | |
70 s->command = NGX_POP3_AUTH; | |
71 | |
72 } else if (c0 == 'N' && c1 == 'O' && c2 == 'O' && c3 == 'P') | |
73 { | |
74 s->command = NGX_POP3_NOOP; | |
75 #if (NGX_MAIL_SSL) | |
76 } else if (c0 == 'S' && c1 == 'T' && c2 == 'L' && c3 == 'S') | |
77 { | |
78 s->command = NGX_POP3_STLS; | |
79 #endif | |
80 } else { | |
81 goto invalid; | |
82 } | |
83 | |
84 } else { | |
85 goto invalid; | |
86 } | |
87 | |
88 switch (ch) { | |
89 case ' ': | |
90 state = sw_spaces_before_argument; | |
91 break; | |
92 case CR: | |
93 state = sw_almost_done; | |
94 break; | |
95 case LF: | |
96 goto done; | |
97 } | |
98 break; | |
99 } | |
100 | |
101 if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) { | |
102 goto invalid; | |
103 } | |
104 | |
105 break; | |
106 | |
107 case sw_spaces_before_argument: | |
108 switch (ch) { | |
109 case ' ': | |
110 break; | |
111 case CR: | |
112 state = sw_almost_done; | |
113 s->arg_end = p; | |
114 break; | |
115 case LF: | |
116 s->arg_end = p; | |
117 goto done; | |
118 default: | |
119 if (s->args.nelts <= 2) { | |
120 state = sw_argument; | |
121 s->arg_start = p; | |
122 break; | |
123 } | |
124 goto invalid; | |
125 } | |
126 break; | |
127 | |
128 case sw_argument: | |
129 switch (ch) { | |
130 | |
131 case ' ': | |
132 | |
133 /* | |
134 * the space should be considered as part of the at username | |
135 * or password, but not of argument in other commands | |
136 */ | |
137 | |
138 if (s->command == NGX_POP3_USER | |
139 || s->command == NGX_POP3_PASS) | |
140 { | |
141 break; | |
142 } | |
143 | |
144 /* fall through */ | |
145 | |
146 case CR: | |
147 case LF: | |
148 arg = ngx_array_push(&s->args); | |
149 if (arg == NULL) { | |
150 return NGX_ERROR; | |
151 } | |
152 arg->len = p - s->arg_start; | |
153 arg->data = s->arg_start; | |
154 s->arg_start = NULL; | |
155 | |
156 switch (ch) { | |
157 case ' ': | |
158 state = sw_spaces_before_argument; | |
159 break; | |
160 case CR: | |
161 state = sw_almost_done; | |
162 break; | |
163 case LF: | |
164 goto done; | |
165 } | |
166 break; | |
167 | |
168 default: | |
169 break; | |
170 } | |
171 break; | |
172 | |
173 case sw_almost_done: | |
174 switch (ch) { | |
175 case LF: | |
176 goto done; | |
177 default: | |
178 goto invalid; | |
179 } | |
180 } | |
181 } | |
182 | |
183 s->buffer->pos = p; | |
184 s->state = state; | |
185 | |
186 return NGX_AGAIN; | |
187 | |
188 done: | |
189 | |
190 s->buffer->pos = p + 1; | |
191 | |
192 if (s->arg_start) { | |
193 arg = ngx_array_push(&s->args); | |
194 if (arg == NULL) { | |
195 return NGX_ERROR; | |
196 } | |
197 arg->len = s->arg_end - s->arg_start; | |
198 arg->data = s->arg_start; | |
199 s->arg_start = NULL; | |
200 } | |
201 | |
202 s->state = (s->command != NGX_POP3_AUTH) ? sw_start : sw_argument; | |
203 | |
204 return NGX_OK; | |
205 | |
206 invalid: | |
207 | |
208 s->state = sw_start; | |
209 s->arg_start = NULL; | |
210 | |
211 return NGX_MAIL_PARSE_INVALID_COMMAND; | |
212 } | |
213 | |
214 | |
1477 | 215 ngx_int_t |
216 ngx_mail_imap_parse_command(ngx_mail_session_t *s) | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
217 { |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
218 u_char ch, *p, *c; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
219 ngx_str_t *arg; |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
220 enum { |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
221 sw_start = 0, |
527 | 222 sw_spaces_before_command, |
223 sw_command, | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
224 sw_spaces_before_argument, |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
225 sw_argument, |
543 | 226 sw_backslash, |
527 | 227 sw_literal, |
543 | 228 sw_no_sync_literal_argument, |
527 | 229 sw_start_literal_argument, |
230 sw_literal_argument, | |
231 sw_end_literal_argument, | |
232 sw_almost_done | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
233 } state; |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
234 |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
235 state = s->state; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
236 |
527 | 237 for (p = s->buffer->pos; p < s->buffer->last; p++) { |
238 ch = *p; | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
239 |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
240 switch (state) { |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
241 |
527 | 242 /* IMAP tag */ |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
243 case sw_start: |
527 | 244 switch (ch) { |
245 case ' ': | |
246 s->tag.len = p - s->buffer->start + 1; | |
247 s->tag.data = s->buffer->start; | |
248 state = sw_spaces_before_command; | |
249 break; | |
250 case CR: | |
251 s->state = sw_start; | |
1136 | 252 return NGX_MAIL_PARSE_INVALID_COMMAND; |
527 | 253 case LF: |
254 s->state = sw_start; | |
1136 | 255 return NGX_MAIL_PARSE_INVALID_COMMAND; |
527 | 256 } |
257 break; | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
258 |
527 | 259 case sw_spaces_before_command: |
260 switch (ch) { | |
261 case ' ': | |
262 break; | |
263 case CR: | |
264 s->state = sw_start; | |
1136 | 265 return NGX_MAIL_PARSE_INVALID_COMMAND; |
527 | 266 case LF: |
267 s->state = sw_start; | |
1136 | 268 return NGX_MAIL_PARSE_INVALID_COMMAND; |
527 | 269 default: |
270 s->cmd_start = p; | |
271 state = sw_command; | |
272 break; | |
273 } | |
274 break; | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
275 |
527 | 276 case sw_command: |
277 if (ch == ' ' || ch == CR || ch == LF) { | |
278 | |
279 c = s->cmd_start; | |
280 | |
281 switch (p - c) { | |
282 | |
283 case 4: | |
284 if ((c[0] == 'N' || c[0] == 'n') | |
285 && (c[1] == 'O'|| c[1] == 'o') | |
286 && (c[2] == 'O'|| c[2] == 'o') | |
287 && (c[3] == 'P'|| c[3] == 'p')) | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
288 { |
527 | 289 s->command = NGX_IMAP_NOOP; |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
290 |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
291 } else { |
527 | 292 goto invalid; |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
293 } |
527 | 294 break; |
295 | |
296 case 5: | |
297 if ((c[0] == 'L'|| c[0] == 'l') | |
298 && (c[1] == 'O'|| c[1] == 'o') | |
299 && (c[2] == 'G'|| c[2] == 'g') | |
300 && (c[3] == 'I'|| c[3] == 'i') | |
301 && (c[4] == 'N'|| c[4] == 'n')) | |
302 { | |
303 s->command = NGX_IMAP_LOGIN; | |
304 | |
305 } else { | |
306 goto invalid; | |
307 } | |
308 break; | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
309 |
527 | 310 case 6: |
311 if ((c[0] == 'L'|| c[0] == 'l') | |
312 && (c[1] == 'O'|| c[1] == 'o') | |
313 && (c[2] == 'G'|| c[2] == 'g') | |
314 && (c[3] == 'O'|| c[3] == 'o') | |
315 && (c[4] == 'U'|| c[4] == 'u') | |
316 && (c[5] == 'T'|| c[5] == 't')) | |
317 { | |
318 s->command = NGX_IMAP_LOGOUT; | |
319 | |
320 } else { | |
321 goto invalid; | |
322 } | |
323 break; | |
324 | |
1136 | 325 #if (NGX_MAIL_SSL) |
583 | 326 case 8: |
327 if ((c[0] == 'S'|| c[0] == 's') | |
328 && (c[1] == 'T'|| c[1] == 't') | |
329 && (c[2] == 'A'|| c[2] == 'a') | |
330 && (c[3] == 'R'|| c[3] == 'r') | |
331 && (c[4] == 'T'|| c[4] == 't') | |
332 && (c[5] == 'T'|| c[5] == 't') | |
333 && (c[6] == 'L'|| c[6] == 'l') | |
334 && (c[7] == 'S'|| c[7] == 's')) | |
335 { | |
336 s->command = NGX_IMAP_STARTTLS; | |
337 | |
338 } else { | |
339 goto invalid; | |
340 } | |
341 break; | |
342 #endif | |
343 | |
527 | 344 case 10: |
345 if ((c[0] == 'C'|| c[0] == 'c') | |
346 && (c[1] == 'A'|| c[1] == 'a') | |
347 && (c[2] == 'P'|| c[2] == 'p') | |
348 && (c[3] == 'A'|| c[3] == 'a') | |
349 && (c[4] == 'B'|| c[4] == 'b') | |
350 && (c[5] == 'I'|| c[5] == 'i') | |
351 && (c[6] == 'L'|| c[6] == 'l') | |
352 && (c[7] == 'I'|| c[7] == 'i') | |
353 && (c[8] == 'T'|| c[8] == 't') | |
354 && (c[9] == 'Y'|| c[9] == 'y')) | |
355 { | |
356 s->command = NGX_IMAP_CAPABILITY; | |
357 | |
358 } else { | |
359 goto invalid; | |
360 } | |
361 break; | |
362 | |
1323 | 363 case 12: |
364 if ((c[0] == 'A'|| c[0] == 'a') | |
365 && (c[1] == 'U'|| c[1] == 'u') | |
366 && (c[2] == 'T'|| c[2] == 't') | |
367 && (c[3] == 'H'|| c[3] == 'h') | |
368 && (c[4] == 'E'|| c[4] == 'e') | |
369 && (c[5] == 'N'|| c[5] == 'n') | |
370 && (c[6] == 'T'|| c[6] == 't') | |
371 && (c[7] == 'I'|| c[7] == 'i') | |
372 && (c[8] == 'C'|| c[8] == 'c') | |
373 && (c[9] == 'A'|| c[9] == 'a') | |
374 && (c[10] == 'T'|| c[10] == 't') | |
375 && (c[11] == 'E'|| c[11] == 'e')) | |
376 { | |
377 s->command = NGX_IMAP_AUTHENTICATE; | |
378 | |
379 } else { | |
380 goto invalid; | |
381 } | |
382 break; | |
383 | |
527 | 384 default: |
385 goto invalid; | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
386 } |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
387 |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
388 switch (ch) { |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
389 case ' ': |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
390 state = sw_spaces_before_argument; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
391 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
392 case CR: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
393 state = sw_almost_done; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
394 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
395 case LF: |
527 | 396 goto done; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
397 } |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
398 break; |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
399 } |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
400 |
527 | 401 if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) { |
402 goto invalid; | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
403 } |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
404 |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
405 break; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
406 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
407 case sw_spaces_before_argument: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
408 switch (ch) { |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
409 case ' ': |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
410 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
411 case CR: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
412 state = sw_almost_done; |
527 | 413 s->arg_end = p; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
414 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
415 case LF: |
527 | 416 s->arg_end = p; |
417 goto done; | |
418 case '"': | |
419 if (s->args.nelts <= 2) { | |
420 s->quoted = 1; | |
421 s->arg_start = p + 1; | |
422 state = sw_argument; | |
423 break; | |
424 } | |
425 goto invalid; | |
426 case '{': | |
427 if (s->args.nelts <= 2) { | |
428 state = sw_literal; | |
429 break; | |
430 } | |
431 goto invalid; | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
432 default: |
527 | 433 if (s->args.nelts <= 2) { |
434 s->arg_start = p; | |
435 state = sw_argument; | |
436 break; | |
437 } | |
438 goto invalid; | |
439 } | |
440 break; | |
441 | |
442 case sw_argument: | |
1405
fdd064faf26a
escape " ", "%", and %00-%1F in login and password
Igor Sysoev <igor@sysoev.ru>
parents:
1323
diff
changeset
|
443 if (ch == ' ' && s->quoted) { |
fdd064faf26a
escape " ", "%", and %00-%1F in login and password
Igor Sysoev <igor@sysoev.ru>
parents:
1323
diff
changeset
|
444 break; |
fdd064faf26a
escape " ", "%", and %00-%1F in login and password
Igor Sysoev <igor@sysoev.ru>
parents:
1323
diff
changeset
|
445 } |
fdd064faf26a
escape " ", "%", and %00-%1F in login and password
Igor Sysoev <igor@sysoev.ru>
parents:
1323
diff
changeset
|
446 |
527 | 447 switch (ch) { |
448 case '"': | |
449 if (!s->quoted) { | |
450 break; | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
451 } |
527 | 452 s->quoted = 0; |
453 /* fall through */ | |
454 case ' ': | |
455 case CR: | |
456 case LF: | |
457 arg = ngx_array_push(&s->args); | |
458 if (arg == NULL) { | |
459 return NGX_ERROR; | |
460 } | |
461 arg->len = p - s->arg_start; | |
462 arg->data = s->arg_start; | |
463 s->arg_start = NULL; | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
464 |
527 | 465 switch (ch) { |
466 case '"': | |
467 case ' ': | |
468 state = sw_spaces_before_argument; | |
469 break; | |
470 case CR: | |
471 state = sw_almost_done; | |
472 break; | |
473 case LF: | |
474 goto done; | |
475 } | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
476 break; |
543 | 477 case '\\': |
478 if (s->quoted) { | |
479 s->backslash = 1; | |
480 state = sw_backslash; | |
481 } | |
482 break; | |
483 } | |
484 break; | |
485 | |
486 case sw_backslash: | |
487 switch (ch) { | |
488 case CR: | |
489 case LF: | |
490 goto invalid; | |
491 default: | |
492 state = sw_argument; | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
493 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
494 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
495 |
527 | 496 case sw_literal: |
497 if (ch >= '0' && ch <= '9') { | |
498 s->literal_len = s->literal_len * 10 + (ch - '0'); | |
499 break; | |
500 } | |
501 if (ch == '}') { | |
502 state = sw_start_literal_argument; | |
503 break; | |
504 } | |
543 | 505 if (ch == '+') { |
506 state = sw_no_sync_literal_argument; | |
507 break; | |
508 } | |
509 goto invalid; | |
510 | |
511 case sw_no_sync_literal_argument: | |
512 if (ch == '}') { | |
513 s->no_sync_literal = 1; | |
514 state = sw_start_literal_argument; | |
515 break; | |
516 } | |
527 | 517 goto invalid; |
518 | |
519 case sw_start_literal_argument: | |
520 switch (ch) { | |
521 case CR: | |
522 break; | |
523 case LF: | |
524 s->buffer->pos = p + 1; | |
525 s->arg_start = p + 1; | |
543 | 526 if (s->no_sync_literal == 0) { |
527 s->state = sw_literal_argument; | |
528 return NGX_IMAP_NEXT; | |
529 } | |
530 state = sw_literal_argument; | |
531 s->no_sync_literal = 0; | |
532 break; | |
533 default: | |
534 goto invalid; | |
527 | 535 } |
543 | 536 break; |
527 | 537 |
538 case sw_literal_argument: | |
529 | 539 if (s->literal_len && --s->literal_len) { |
527 | 540 break; |
541 } | |
542 | |
543 arg = ngx_array_push(&s->args); | |
544 if (arg == NULL) { | |
545 return NGX_ERROR; | |
546 } | |
547 arg->len = p + 1 - s->arg_start; | |
548 arg->data = s->arg_start; | |
549 s->arg_start = NULL; | |
550 state = sw_end_literal_argument; | |
551 | |
552 break; | |
553 | |
554 case sw_end_literal_argument: | |
555 switch (ch) { | |
556 case '{': | |
557 if (s->args.nelts <= 2) { | |
558 state = sw_literal; | |
559 break; | |
560 } | |
561 goto invalid; | |
562 case CR: | |
563 state = sw_almost_done; | |
564 break; | |
565 case LF: | |
566 goto done; | |
567 default: | |
529 | 568 state = sw_spaces_before_argument; |
569 break; | |
527 | 570 } |
571 break; | |
572 | |
573 case sw_almost_done: | |
574 switch (ch) { | |
575 case LF: | |
576 goto done; | |
577 default: | |
578 goto invalid; | |
579 } | |
580 } | |
581 } | |
582 | |
583 s->buffer->pos = p; | |
584 s->state = state; | |
585 | |
586 return NGX_AGAIN; | |
587 | |
588 done: | |
589 | |
590 s->buffer->pos = p + 1; | |
591 | |
592 if (s->arg_start) { | |
593 arg = ngx_array_push(&s->args); | |
594 if (arg == NULL) { | |
595 return NGX_ERROR; | |
596 } | |
597 arg->len = s->arg_end - s->arg_start; | |
598 arg->data = s->arg_start; | |
543 | 599 |
527 | 600 s->arg_start = NULL; |
601 s->cmd_start = NULL; | |
602 s->quoted = 0; | |
543 | 603 s->no_sync_literal = 0; |
527 | 604 s->literal_len = 0; |
605 } | |
606 | |
1323 | 607 s->state = (s->command != NGX_IMAP_AUTHENTICATE) ? sw_start : sw_argument; |
527 | 608 |
609 return NGX_OK; | |
610 | |
611 invalid: | |
612 | |
613 s->state = sw_start; | |
614 s->quoted = 0; | |
543 | 615 s->no_sync_literal = 0; |
527 | 616 s->literal_len = 0; |
617 | |
1136 | 618 return NGX_MAIL_PARSE_INVALID_COMMAND; |
527 | 619 } |
620 | |
621 | |
1477 | 622 ngx_int_t |
623 ngx_mail_smtp_parse_command(ngx_mail_session_t *s) | |
527 | 624 { |
625 u_char ch, *p, *c, c0, c1, c2, c3; | |
626 ngx_str_t *arg; | |
627 enum { | |
628 sw_start = 0, | |
5398
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
629 sw_command, |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
630 sw_invalid, |
527 | 631 sw_spaces_before_argument, |
632 sw_argument, | |
633 sw_almost_done | |
634 } state; | |
635 | |
636 state = s->state; | |
637 | |
638 for (p = s->buffer->pos; p < s->buffer->last; p++) { | |
639 ch = *p; | |
640 | |
641 switch (state) { | |
642 | |
1136 | 643 /* SMTP command */ |
527 | 644 case sw_start: |
5398
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
645 s->cmd_start = p; |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
646 state = sw_command; |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
647 |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
648 /* fall through */ |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
649 |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
650 case sw_command: |
527 | 651 if (ch == ' ' || ch == CR || ch == LF) { |
5398
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
652 c = s->cmd_start; |
527 | 653 |
654 if (p - c == 4) { | |
655 | |
656 c0 = ngx_toupper(c[0]); | |
657 c1 = ngx_toupper(c[1]); | |
658 c2 = ngx_toupper(c[2]); | |
659 c3 = ngx_toupper(c[3]); | |
660 | |
1136 | 661 if (c0 == 'H' && c1 == 'E' && c2 == 'L' && c3 == 'O') |
527 | 662 { |
1136 | 663 s->command = NGX_SMTP_HELO; |
527 | 664 |
1136 | 665 } else if (c0 == 'E' && c1 == 'H' && c2 == 'L' && c3 == 'O') |
800 | 666 { |
1136 | 667 s->command = NGX_SMTP_EHLO; |
800 | 668 |
527 | 669 } else if (c0 == 'Q' && c1 == 'U' && c2 == 'I' && c3 == 'T') |
670 { | |
1136 | 671 s->command = NGX_SMTP_QUIT; |
527 | 672 |
809 | 673 } else if (c0 == 'A' && c1 == 'U' && c2 == 'T' && c3 == 'H') |
674 { | |
1136 | 675 s->command = NGX_SMTP_AUTH; |
809 | 676 |
527 | 677 } else if (c0 == 'N' && c1 == 'O' && c2 == 'O' && c3 == 'P') |
678 { | |
1136 | 679 s->command = NGX_SMTP_NOOP; |
680 | |
681 } else if (c0 == 'M' && c1 == 'A' && c2 == 'I' && c3 == 'L') | |
583 | 682 { |
1136 | 683 s->command = NGX_SMTP_MAIL; |
684 | |
685 } else if (c0 == 'R' && c1 == 'S' && c2 == 'E' && c3 == 'T') | |
686 { | |
687 s->command = NGX_SMTP_RSET; | |
688 | |
1322 | 689 } else if (c0 == 'R' && c1 == 'C' && c2 == 'P' && c3 == 'T') |
690 { | |
691 s->command = NGX_SMTP_RCPT; | |
692 | |
693 } else if (c0 == 'V' && c1 == 'R' && c2 == 'F' && c3 == 'Y') | |
694 { | |
695 s->command = NGX_SMTP_VRFY; | |
696 | |
697 } else if (c0 == 'E' && c1 == 'X' && c2 == 'P' && c3 == 'N') | |
698 { | |
699 s->command = NGX_SMTP_EXPN; | |
700 | |
701 } else if (c0 == 'H' && c1 == 'E' && c2 == 'L' && c3 == 'P') | |
702 { | |
703 s->command = NGX_SMTP_HELP; | |
704 | |
527 | 705 } else { |
706 goto invalid; | |
707 } | |
1322 | 708 #if (NGX_MAIL_SSL) |
709 } else if (p - c == 8) { | |
527 | 710 |
1322 | 711 if ((c[0] == 'S'|| c[0] == 's') |
712 && (c[1] == 'T'|| c[1] == 't') | |
713 && (c[2] == 'A'|| c[2] == 'a') | |
714 && (c[3] == 'R'|| c[3] == 'r') | |
715 && (c[4] == 'T'|| c[4] == 't') | |
716 && (c[5] == 'T'|| c[5] == 't') | |
717 && (c[6] == 'L'|| c[6] == 'l') | |
718 && (c[7] == 'S'|| c[7] == 's')) | |
719 { | |
720 s->command = NGX_SMTP_STARTTLS; | |
721 | |
722 } else { | |
723 goto invalid; | |
724 } | |
725 #endif | |
527 | 726 } else { |
727 goto invalid; | |
728 } | |
729 | |
5398
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
730 s->cmd.data = s->cmd_start; |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
731 s->cmd.len = p - s->cmd_start; |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
732 |
527 | 733 switch (ch) { |
734 case ' ': | |
735 state = sw_spaces_before_argument; | |
736 break; | |
737 case CR: | |
738 state = sw_almost_done; | |
739 break; | |
740 case LF: | |
741 goto done; | |
742 } | |
743 break; | |
744 } | |
745 | |
746 if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) { | |
747 goto invalid; | |
748 } | |
749 | |
750 break; | |
751 | |
5398
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
752 case sw_invalid: |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
753 goto invalid; |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
754 |
527 | 755 case sw_spaces_before_argument: |
756 switch (ch) { | |
757 case ' ': | |
758 break; | |
759 case CR: | |
760 state = sw_almost_done; | |
761 s->arg_end = p; | |
762 break; | |
763 case LF: | |
764 s->arg_end = p; | |
765 goto done; | |
766 default: | |
2309 | 767 if (s->args.nelts <= 10) { |
527 | 768 state = sw_argument; |
769 s->arg_start = p; | |
770 break; | |
771 } | |
772 goto invalid; | |
773 } | |
774 break; | |
775 | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
776 case sw_argument: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
777 switch (ch) { |
800 | 778 case ' ': |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
779 case CR: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
780 case LF: |
501 | 781 arg = ngx_array_push(&s->args); |
782 if (arg == NULL) { | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
783 return NGX_ERROR; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
784 } |
527 | 785 arg->len = p - s->arg_start; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
786 arg->data = s->arg_start; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
787 s->arg_start = NULL; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
788 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
789 switch (ch) { |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
790 case ' ': |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
791 state = sw_spaces_before_argument; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
792 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
793 case CR: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
794 state = sw_almost_done; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
795 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
796 case LF: |
527 | 797 goto done; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
798 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
799 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
800 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
801 default: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
802 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
803 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
804 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
805 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
806 case sw_almost_done: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
807 switch (ch) { |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
808 case LF: |
527 | 809 goto done; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
810 default: |
527 | 811 goto invalid; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
812 } |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
813 } |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
814 } |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
815 |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
816 s->buffer->pos = p; |
527 | 817 s->state = state; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
818 |
527 | 819 return NGX_AGAIN; |
820 | |
821 done: | |
822 | |
823 s->buffer->pos = p + 1; | |
824 | |
825 if (s->arg_start) { | |
826 arg = ngx_array_push(&s->args); | |
827 if (arg == NULL) { | |
828 return NGX_ERROR; | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
829 } |
527 | 830 arg->len = s->arg_end - s->arg_start; |
831 arg->data = s->arg_start; | |
832 s->arg_start = NULL; | |
833 } | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
834 |
1136 | 835 s->state = (s->command != NGX_SMTP_AUTH) ? sw_start : sw_argument; |
836 | |
527 | 837 return NGX_OK; |
838 | |
839 invalid: | |
840 | |
5398
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
841 s->state = sw_invalid; |
810 | 842 s->arg_start = NULL; |
527 | 843 |
5398
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
844 /* skip invalid command till LF */ |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
845 |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
846 for (p = s->buffer->pos; p < s->buffer->last; p++) { |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
847 if (*p == LF) { |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
848 s->state = sw_start; |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
849 p++; |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
850 break; |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
851 } |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
852 } |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
853 |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
854 s->buffer->pos = p; |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
855 |
1136 | 856 return NGX_MAIL_PARSE_INVALID_COMMAND; |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
857 } |
1479 | 858 |
859 | |
860 ngx_int_t | |
861 ngx_mail_auth_parse(ngx_mail_session_t *s, ngx_connection_t *c) | |
862 { | |
863 ngx_str_t *arg; | |
864 | |
865 #if (NGX_MAIL_SSL) | |
866 if (ngx_mail_starttls_only(s, c)) { | |
867 return NGX_MAIL_PARSE_INVALID_COMMAND; | |
868 } | |
869 #endif | |
870 | |
5246
b6562f98bfd8
Mail: fixed possible uninitialized memory access.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4759
diff
changeset
|
871 if (s->args.nelts == 0) { |
b6562f98bfd8
Mail: fixed possible uninitialized memory access.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4759
diff
changeset
|
872 return NGX_MAIL_PARSE_INVALID_COMMAND; |
b6562f98bfd8
Mail: fixed possible uninitialized memory access.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4759
diff
changeset
|
873 } |
b6562f98bfd8
Mail: fixed possible uninitialized memory access.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4759
diff
changeset
|
874 |
1479 | 875 arg = s->args.elts; |
876 | |
877 if (arg[0].len == 5) { | |
878 | |
879 if (ngx_strncasecmp(arg[0].data, (u_char *) "LOGIN", 5) == 0) { | |
880 | |
881 if (s->args.nelts == 1) { | |
882 return NGX_MAIL_AUTH_LOGIN; | |
883 } | |
884 | |
2495
a59b26eee816
compatibility with Microsoft's
Igor Sysoev <igor@sysoev.ru>
parents:
2309
diff
changeset
|
885 if (s->args.nelts == 2) { |
a59b26eee816
compatibility with Microsoft's
Igor Sysoev <igor@sysoev.ru>
parents:
2309
diff
changeset
|
886 return NGX_MAIL_AUTH_LOGIN_USERNAME; |
a59b26eee816
compatibility with Microsoft's
Igor Sysoev <igor@sysoev.ru>
parents:
2309
diff
changeset
|
887 } |
a59b26eee816
compatibility with Microsoft's
Igor Sysoev <igor@sysoev.ru>
parents:
2309
diff
changeset
|
888 |
1479 | 889 return NGX_MAIL_PARSE_INVALID_COMMAND; |
890 } | |
891 | |
892 if (ngx_strncasecmp(arg[0].data, (u_char *) "PLAIN", 5) == 0) { | |
893 | |
894 if (s->args.nelts == 1) { | |
895 return NGX_MAIL_AUTH_PLAIN; | |
896 } | |
897 | |
898 if (s->args.nelts == 2) { | |
899 return ngx_mail_auth_plain(s, c, 1); | |
900 } | |
901 } | |
902 | |
903 return NGX_MAIL_PARSE_INVALID_COMMAND; | |
904 } | |
905 | |
906 if (arg[0].len == 8) { | |
907 | |
6774
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
908 if (ngx_strncasecmp(arg[0].data, (u_char *) "CRAM-MD5", 8) == 0) { |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
909 |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
910 if (s->args.nelts != 1) { |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
911 return NGX_MAIL_PARSE_INVALID_COMMAND; |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
912 } |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
913 |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
914 return NGX_MAIL_AUTH_CRAM_MD5; |
1479 | 915 } |
916 | |
6774
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
917 if (ngx_strncasecmp(arg[0].data, (u_char *) "EXTERNAL", 8) == 0) { |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
918 |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
919 if (s->args.nelts == 1) { |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
920 return NGX_MAIL_AUTH_EXTERNAL; |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
921 } |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
922 |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
923 if (s->args.nelts == 2) { |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
924 return ngx_mail_auth_external(s, c, 1); |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
925 } |
1479 | 926 } |
6774
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
927 |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
928 return NGX_MAIL_PARSE_INVALID_COMMAND; |
1479 | 929 } |
930 | |
931 return NGX_MAIL_PARSE_INVALID_COMMAND; | |
932 } |