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