Mercurial > hg > nginx
annotate src/mail/ngx_mail_parse.c @ 7841:ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Previously, s->backslash was set if any of the arguments was a quoted
string with a backslash character. After successful command parsing
this resulted in all arguments being filtered to remove backslashes.
This is, however, incorrect, as backslashes should not be removed from
IMAP literals. For example:
S: * OK IMAP4 ready
C: a01 login {9}
S: + OK
C: user\name "pass\"word"
S: * BAD internal server error
resulted in "Auth-User: username" instead of "Auth-User: user\name"
as it should.
Fix is to apply backslash filtering on per-argument basis during parsing.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Wed, 19 May 2021 03:13:23 +0300 |
parents | 379d461eccf4 |
children | 4b15f1b92100 |
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 break; | |
128 case LF: | |
129 goto done; | |
130 default: | |
131 if (s->args.nelts <= 2) { | |
132 state = sw_argument; | |
133 s->arg_start = p; | |
134 break; | |
135 } | |
136 goto invalid; | |
137 } | |
138 break; | |
139 | |
140 case sw_argument: | |
141 switch (ch) { | |
142 | |
143 case ' ': | |
144 | |
145 /* | |
146 * the space should be considered as part of the at username | |
147 * or password, but not of argument in other commands | |
148 */ | |
149 | |
150 if (s->command == NGX_POP3_USER | |
151 || s->command == NGX_POP3_PASS) | |
152 { | |
153 break; | |
154 } | |
155 | |
156 /* fall through */ | |
157 | |
158 case CR: | |
159 case LF: | |
160 arg = ngx_array_push(&s->args); | |
161 if (arg == NULL) { | |
162 return NGX_ERROR; | |
163 } | |
164 arg->len = p - s->arg_start; | |
165 arg->data = s->arg_start; | |
166 s->arg_start = NULL; | |
167 | |
168 switch (ch) { | |
169 case ' ': | |
170 state = sw_spaces_before_argument; | |
171 break; | |
172 case CR: | |
173 state = sw_almost_done; | |
174 break; | |
175 case LF: | |
176 goto done; | |
177 } | |
178 break; | |
179 | |
180 default: | |
181 break; | |
182 } | |
183 break; | |
184 | |
185 case sw_almost_done: | |
186 switch (ch) { | |
187 case LF: | |
188 goto done; | |
189 default: | |
190 goto invalid; | |
191 } | |
192 } | |
193 } | |
194 | |
195 s->buffer->pos = p; | |
196 s->state = state; | |
197 | |
198 return NGX_AGAIN; | |
199 | |
200 done: | |
201 | |
202 s->buffer->pos = p + 1; | |
203 s->state = (s->command != NGX_POP3_AUTH) ? sw_start : sw_argument; | |
204 | |
205 return NGX_OK; | |
206 | |
207 invalid: | |
208 | |
7838
815c63581be4
Mail: POP3 pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7837
diff
changeset
|
209 s->state = sw_invalid; |
1136 | 210 |
7838
815c63581be4
Mail: POP3 pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7837
diff
changeset
|
211 /* skip invalid command till LF */ |
815c63581be4
Mail: POP3 pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7837
diff
changeset
|
212 |
815c63581be4
Mail: POP3 pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7837
diff
changeset
|
213 for ( /* void */ ; p < s->buffer->last; p++) { |
815c63581be4
Mail: POP3 pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7837
diff
changeset
|
214 if (*p == LF) { |
815c63581be4
Mail: POP3 pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7837
diff
changeset
|
215 s->state = sw_start; |
815c63581be4
Mail: POP3 pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7837
diff
changeset
|
216 s->buffer->pos = p + 1; |
815c63581be4
Mail: POP3 pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7837
diff
changeset
|
217 return NGX_MAIL_PARSE_INVALID_COMMAND; |
815c63581be4
Mail: POP3 pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7837
diff
changeset
|
218 } |
815c63581be4
Mail: POP3 pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7837
diff
changeset
|
219 } |
815c63581be4
Mail: POP3 pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7837
diff
changeset
|
220 |
815c63581be4
Mail: POP3 pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7837
diff
changeset
|
221 s->buffer->pos = p; |
815c63581be4
Mail: POP3 pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7837
diff
changeset
|
222 |
815c63581be4
Mail: POP3 pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7837
diff
changeset
|
223 return NGX_AGAIN; |
1136 | 224 } |
225 | |
226 | |
1477 | 227 ngx_int_t |
228 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
|
229 { |
7841
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
230 u_char ch, *p, *c, *dst, *src, *end; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
231 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
|
232 enum { |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
233 sw_start = 0, |
527 | 234 sw_spaces_before_command, |
235 sw_command, | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
236 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
|
237 sw_argument, |
543 | 238 sw_backslash, |
527 | 239 sw_literal, |
543 | 240 sw_no_sync_literal_argument, |
527 | 241 sw_start_literal_argument, |
242 sw_literal_argument, | |
243 sw_end_literal_argument, | |
244 sw_almost_done | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
245 } state; |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
246 |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
247 state = s->state; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
248 |
527 | 249 for (p = s->buffer->pos; p < s->buffer->last; p++) { |
250 ch = *p; | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
251 |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
252 switch (state) { |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
253 |
527 | 254 /* IMAP tag */ |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
255 case sw_start: |
527 | 256 switch (ch) { |
257 case ' ': | |
258 s->tag.len = p - s->buffer->start + 1; | |
259 s->tag.data = s->buffer->start; | |
260 state = sw_spaces_before_command; | |
261 break; | |
262 case CR: | |
263 s->state = sw_start; | |
1136 | 264 return NGX_MAIL_PARSE_INVALID_COMMAND; |
527 | 265 case LF: |
266 s->state = sw_start; | |
1136 | 267 return NGX_MAIL_PARSE_INVALID_COMMAND; |
527 | 268 } |
269 break; | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
270 |
527 | 271 case sw_spaces_before_command: |
272 switch (ch) { | |
273 case ' ': | |
274 break; | |
275 case CR: | |
276 s->state = sw_start; | |
1136 | 277 return NGX_MAIL_PARSE_INVALID_COMMAND; |
527 | 278 case LF: |
279 s->state = sw_start; | |
1136 | 280 return NGX_MAIL_PARSE_INVALID_COMMAND; |
527 | 281 default: |
282 s->cmd_start = p; | |
283 state = sw_command; | |
284 break; | |
285 } | |
286 break; | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
287 |
527 | 288 case sw_command: |
289 if (ch == ' ' || ch == CR || ch == LF) { | |
290 | |
291 c = s->cmd_start; | |
292 | |
293 switch (p - c) { | |
294 | |
295 case 4: | |
296 if ((c[0] == 'N' || c[0] == 'n') | |
297 && (c[1] == 'O'|| c[1] == 'o') | |
298 && (c[2] == 'O'|| c[2] == 'o') | |
299 && (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
|
300 { |
527 | 301 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
|
302 |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
303 } else { |
527 | 304 goto invalid; |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
305 } |
527 | 306 break; |
307 | |
308 case 5: | |
309 if ((c[0] == 'L'|| c[0] == 'l') | |
310 && (c[1] == 'O'|| c[1] == 'o') | |
311 && (c[2] == 'G'|| c[2] == 'g') | |
312 && (c[3] == 'I'|| c[3] == 'i') | |
313 && (c[4] == 'N'|| c[4] == 'n')) | |
314 { | |
315 s->command = NGX_IMAP_LOGIN; | |
316 | |
317 } else { | |
318 goto invalid; | |
319 } | |
320 break; | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
321 |
527 | 322 case 6: |
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] == 'O'|| c[3] == 'o') | |
327 && (c[4] == 'U'|| c[4] == 'u') | |
328 && (c[5] == 'T'|| c[5] == 't')) | |
329 { | |
330 s->command = NGX_IMAP_LOGOUT; | |
331 | |
332 } else { | |
333 goto invalid; | |
334 } | |
335 break; | |
336 | |
1136 | 337 #if (NGX_MAIL_SSL) |
583 | 338 case 8: |
339 if ((c[0] == 'S'|| c[0] == 's') | |
340 && (c[1] == 'T'|| c[1] == 't') | |
341 && (c[2] == 'A'|| c[2] == 'a') | |
342 && (c[3] == 'R'|| c[3] == 'r') | |
343 && (c[4] == 'T'|| c[4] == 't') | |
344 && (c[5] == 'T'|| c[5] == 't') | |
345 && (c[6] == 'L'|| c[6] == 'l') | |
346 && (c[7] == 'S'|| c[7] == 's')) | |
347 { | |
348 s->command = NGX_IMAP_STARTTLS; | |
349 | |
350 } else { | |
351 goto invalid; | |
352 } | |
353 break; | |
354 #endif | |
355 | |
527 | 356 case 10: |
357 if ((c[0] == 'C'|| c[0] == 'c') | |
358 && (c[1] == 'A'|| c[1] == 'a') | |
359 && (c[2] == 'P'|| c[2] == 'p') | |
360 && (c[3] == 'A'|| c[3] == 'a') | |
361 && (c[4] == 'B'|| c[4] == 'b') | |
362 && (c[5] == 'I'|| c[5] == 'i') | |
363 && (c[6] == 'L'|| c[6] == 'l') | |
364 && (c[7] == 'I'|| c[7] == 'i') | |
365 && (c[8] == 'T'|| c[8] == 't') | |
366 && (c[9] == 'Y'|| c[9] == 'y')) | |
367 { | |
368 s->command = NGX_IMAP_CAPABILITY; | |
369 | |
370 } else { | |
371 goto invalid; | |
372 } | |
373 break; | |
374 | |
1323 | 375 case 12: |
376 if ((c[0] == 'A'|| c[0] == 'a') | |
377 && (c[1] == 'U'|| c[1] == 'u') | |
378 && (c[2] == 'T'|| c[2] == 't') | |
379 && (c[3] == 'H'|| c[3] == 'h') | |
380 && (c[4] == 'E'|| c[4] == 'e') | |
381 && (c[5] == 'N'|| c[5] == 'n') | |
382 && (c[6] == 'T'|| c[6] == 't') | |
383 && (c[7] == 'I'|| c[7] == 'i') | |
384 && (c[8] == 'C'|| c[8] == 'c') | |
385 && (c[9] == 'A'|| c[9] == 'a') | |
386 && (c[10] == 'T'|| c[10] == 't') | |
387 && (c[11] == 'E'|| c[11] == 'e')) | |
388 { | |
389 s->command = NGX_IMAP_AUTHENTICATE; | |
390 | |
391 } else { | |
392 goto invalid; | |
393 } | |
394 break; | |
395 | |
527 | 396 default: |
397 goto invalid; | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
398 } |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
399 |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
400 switch (ch) { |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
401 case ' ': |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
402 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
|
403 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
404 case CR: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
405 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
|
406 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
407 case LF: |
527 | 408 goto done; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
409 } |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
410 break; |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
411 } |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
412 |
527 | 413 if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) { |
414 goto invalid; | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
415 } |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
416 |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
417 break; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
418 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
419 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
|
420 switch (ch) { |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
421 case ' ': |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
422 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
423 case CR: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
424 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
|
425 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
426 case LF: |
527 | 427 goto done; |
428 case '"': | |
429 if (s->args.nelts <= 2) { | |
430 s->quoted = 1; | |
431 s->arg_start = p + 1; | |
432 state = sw_argument; | |
433 break; | |
434 } | |
435 goto invalid; | |
436 case '{': | |
437 if (s->args.nelts <= 2) { | |
438 state = sw_literal; | |
439 break; | |
440 } | |
441 goto invalid; | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
442 default: |
527 | 443 if (s->args.nelts <= 2) { |
444 s->arg_start = p; | |
445 state = sw_argument; | |
446 break; | |
447 } | |
448 goto invalid; | |
449 } | |
450 break; | |
451 | |
452 case sw_argument: | |
1405
fdd064faf26a
escape " ", "%", and %00-%1F in login and password
Igor Sysoev <igor@sysoev.ru>
parents:
1323
diff
changeset
|
453 if (ch == ' ' && s->quoted) { |
fdd064faf26a
escape " ", "%", and %00-%1F in login and password
Igor Sysoev <igor@sysoev.ru>
parents:
1323
diff
changeset
|
454 break; |
fdd064faf26a
escape " ", "%", and %00-%1F in login and password
Igor Sysoev <igor@sysoev.ru>
parents:
1323
diff
changeset
|
455 } |
fdd064faf26a
escape " ", "%", and %00-%1F in login and password
Igor Sysoev <igor@sysoev.ru>
parents:
1323
diff
changeset
|
456 |
527 | 457 switch (ch) { |
458 case '"': | |
459 if (!s->quoted) { | |
460 break; | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
461 } |
527 | 462 s->quoted = 0; |
463 /* fall through */ | |
464 case ' ': | |
465 case CR: | |
466 case LF: | |
467 arg = ngx_array_push(&s->args); | |
468 if (arg == NULL) { | |
469 return NGX_ERROR; | |
470 } | |
471 arg->len = p - s->arg_start; | |
472 arg->data = s->arg_start; | |
7841
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
473 |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
474 if (s->backslash) { |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
475 dst = s->arg_start; |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
476 end = p; |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
477 |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
478 for (src = dst; src < end; dst++) { |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
479 *dst = *src; |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
480 if (*src++ == '\\') { |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
481 *dst = *src++; |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
482 } |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
483 } |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
484 |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
485 arg->len = dst - s->arg_start; |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
486 s->backslash = 0; |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
487 } |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
488 |
527 | 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; | |
1323 | 617 s->state = (s->command != NGX_IMAP_AUTHENTICATE) ? sw_start : sw_argument; |
527 | 618 |
619 return NGX_OK; | |
620 | |
621 invalid: | |
622 | |
623 s->state = sw_start; | |
624 s->quoted = 0; | |
7839
3974f4e56a4e
Mail: fixed s->arg_start clearing on invalid IMAP commands.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7838
diff
changeset
|
625 s->backslash = 0; |
543 | 626 s->no_sync_literal = 0; |
527 | 627 s->literal_len = 0; |
628 | |
1136 | 629 return NGX_MAIL_PARSE_INVALID_COMMAND; |
527 | 630 } |
631 | |
632 | |
1477 | 633 ngx_int_t |
634 ngx_mail_smtp_parse_command(ngx_mail_session_t *s) | |
527 | 635 { |
636 u_char ch, *p, *c, c0, c1, c2, c3; | |
637 ngx_str_t *arg; | |
638 enum { | |
639 sw_start = 0, | |
5398
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
640 sw_command, |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
641 sw_invalid, |
527 | 642 sw_spaces_before_argument, |
643 sw_argument, | |
644 sw_almost_done | |
645 } state; | |
646 | |
647 state = s->state; | |
648 | |
649 for (p = s->buffer->pos; p < s->buffer->last; p++) { | |
650 ch = *p; | |
651 | |
652 switch (state) { | |
653 | |
1136 | 654 /* SMTP command */ |
527 | 655 case sw_start: |
5398
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
656 s->cmd_start = p; |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
657 state = sw_command; |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
658 |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
659 /* fall through */ |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
660 |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
661 case sw_command: |
527 | 662 if (ch == ' ' || ch == CR || ch == LF) { |
5398
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
663 c = s->cmd_start; |
527 | 664 |
665 if (p - c == 4) { | |
666 | |
667 c0 = ngx_toupper(c[0]); | |
668 c1 = ngx_toupper(c[1]); | |
669 c2 = ngx_toupper(c[2]); | |
670 c3 = ngx_toupper(c[3]); | |
671 | |
1136 | 672 if (c0 == 'H' && c1 == 'E' && c2 == 'L' && c3 == 'O') |
527 | 673 { |
1136 | 674 s->command = NGX_SMTP_HELO; |
527 | 675 |
1136 | 676 } else if (c0 == 'E' && c1 == 'H' && c2 == 'L' && c3 == 'O') |
800 | 677 { |
1136 | 678 s->command = NGX_SMTP_EHLO; |
800 | 679 |
527 | 680 } else if (c0 == 'Q' && c1 == 'U' && c2 == 'I' && c3 == 'T') |
681 { | |
1136 | 682 s->command = NGX_SMTP_QUIT; |
527 | 683 |
809 | 684 } else if (c0 == 'A' && c1 == 'U' && c2 == 'T' && c3 == 'H') |
685 { | |
1136 | 686 s->command = NGX_SMTP_AUTH; |
809 | 687 |
527 | 688 } else if (c0 == 'N' && c1 == 'O' && c2 == 'O' && c3 == 'P') |
689 { | |
1136 | 690 s->command = NGX_SMTP_NOOP; |
691 | |
692 } else if (c0 == 'M' && c1 == 'A' && c2 == 'I' && c3 == 'L') | |
583 | 693 { |
1136 | 694 s->command = NGX_SMTP_MAIL; |
695 | |
696 } else if (c0 == 'R' && c1 == 'S' && c2 == 'E' && c3 == 'T') | |
697 { | |
698 s->command = NGX_SMTP_RSET; | |
699 | |
1322 | 700 } else if (c0 == 'R' && c1 == 'C' && c2 == 'P' && c3 == 'T') |
701 { | |
702 s->command = NGX_SMTP_RCPT; | |
703 | |
704 } else if (c0 == 'V' && c1 == 'R' && c2 == 'F' && c3 == 'Y') | |
705 { | |
706 s->command = NGX_SMTP_VRFY; | |
707 | |
708 } else if (c0 == 'E' && c1 == 'X' && c2 == 'P' && c3 == 'N') | |
709 { | |
710 s->command = NGX_SMTP_EXPN; | |
711 | |
712 } else if (c0 == 'H' && c1 == 'E' && c2 == 'L' && c3 == 'P') | |
713 { | |
714 s->command = NGX_SMTP_HELP; | |
715 | |
527 | 716 } else { |
717 goto invalid; | |
718 } | |
1322 | 719 #if (NGX_MAIL_SSL) |
720 } else if (p - c == 8) { | |
527 | 721 |
1322 | 722 if ((c[0] == 'S'|| c[0] == 's') |
723 && (c[1] == 'T'|| c[1] == 't') | |
724 && (c[2] == 'A'|| c[2] == 'a') | |
725 && (c[3] == 'R'|| c[3] == 'r') | |
726 && (c[4] == 'T'|| c[4] == 't') | |
727 && (c[5] == 'T'|| c[5] == 't') | |
728 && (c[6] == 'L'|| c[6] == 'l') | |
729 && (c[7] == 'S'|| c[7] == 's')) | |
730 { | |
731 s->command = NGX_SMTP_STARTTLS; | |
732 | |
733 } else { | |
734 goto invalid; | |
735 } | |
736 #endif | |
527 | 737 } else { |
738 goto invalid; | |
739 } | |
740 | |
5398
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
741 s->cmd.data = s->cmd_start; |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
742 s->cmd.len = p - s->cmd_start; |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
743 |
527 | 744 switch (ch) { |
745 case ' ': | |
746 state = sw_spaces_before_argument; | |
747 break; | |
748 case CR: | |
749 state = sw_almost_done; | |
750 break; | |
751 case LF: | |
752 goto done; | |
753 } | |
754 break; | |
755 } | |
756 | |
757 if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) { | |
758 goto invalid; | |
759 } | |
760 | |
761 break; | |
762 | |
5398
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
763 case sw_invalid: |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
764 goto invalid; |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
765 |
527 | 766 case sw_spaces_before_argument: |
767 switch (ch) { | |
768 case ' ': | |
769 break; | |
770 case CR: | |
771 state = sw_almost_done; | |
772 break; | |
773 case LF: | |
774 goto done; | |
775 default: | |
2309 | 776 if (s->args.nelts <= 10) { |
527 | 777 state = sw_argument; |
778 s->arg_start = p; | |
779 break; | |
780 } | |
781 goto invalid; | |
782 } | |
783 break; | |
784 | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
785 case sw_argument: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
786 switch (ch) { |
800 | 787 case ' ': |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
788 case CR: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
789 case LF: |
501 | 790 arg = ngx_array_push(&s->args); |
791 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
|
792 return NGX_ERROR; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
793 } |
527 | 794 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
|
795 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
|
796 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
|
797 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
798 switch (ch) { |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
799 case ' ': |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
800 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
|
801 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
802 case CR: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
803 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
|
804 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
805 case LF: |
527 | 806 goto done; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
807 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
808 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
809 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
810 default: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
811 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
812 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
813 break; |
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 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
|
816 switch (ch) { |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
817 case LF: |
527 | 818 goto done; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
819 default: |
527 | 820 goto invalid; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
821 } |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
822 } |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
823 } |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
824 |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
825 s->buffer->pos = p; |
527 | 826 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
|
827 |
527 | 828 return NGX_AGAIN; |
829 | |
830 done: | |
831 | |
832 s->buffer->pos = p + 1; | |
1136 | 833 s->state = (s->command != NGX_SMTP_AUTH) ? sw_start : sw_argument; |
834 | |
527 | 835 return NGX_OK; |
836 | |
837 invalid: | |
838 | |
5398
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
839 s->state = sw_invalid; |
527 | 840 |
5398
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
841 /* skip invalid command till LF */ |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
842 |
7837
ba8a8299b904
Mail: optimized discarding invalid SMTP commands.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7836
diff
changeset
|
843 for ( /* void */ ; p < s->buffer->last; p++) { |
5398
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
844 if (*p == LF) { |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
845 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
|
846 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
|
847 return NGX_MAIL_PARSE_INVALID_COMMAND; |
5398
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
848 } |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
849 } |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
850 |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
851 s->buffer->pos = p; |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
852 |
7836
6a81d96d3733
Mail: fixed handling of invalid SMTP commands split between reads.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6774
diff
changeset
|
853 return NGX_AGAIN; |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
854 } |
1479 | 855 |
856 | |
857 ngx_int_t | |
858 ngx_mail_auth_parse(ngx_mail_session_t *s, ngx_connection_t *c) | |
859 { | |
860 ngx_str_t *arg; | |
861 | |
862 #if (NGX_MAIL_SSL) | |
863 if (ngx_mail_starttls_only(s, c)) { | |
864 return NGX_MAIL_PARSE_INVALID_COMMAND; | |
865 } | |
866 #endif | |
867 | |
5246
b6562f98bfd8
Mail: fixed possible uninitialized memory access.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4759
diff
changeset
|
868 if (s->args.nelts == 0) { |
b6562f98bfd8
Mail: fixed possible uninitialized memory access.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4759
diff
changeset
|
869 return NGX_MAIL_PARSE_INVALID_COMMAND; |
b6562f98bfd8
Mail: fixed possible uninitialized memory access.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4759
diff
changeset
|
870 } |
b6562f98bfd8
Mail: fixed possible uninitialized memory access.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4759
diff
changeset
|
871 |
1479 | 872 arg = s->args.elts; |
873 | |
874 if (arg[0].len == 5) { | |
875 | |
876 if (ngx_strncasecmp(arg[0].data, (u_char *) "LOGIN", 5) == 0) { | |
877 | |
878 if (s->args.nelts == 1) { | |
879 return NGX_MAIL_AUTH_LOGIN; | |
880 } | |
881 | |
2495
a59b26eee816
compatibility with Microsoft's
Igor Sysoev <igor@sysoev.ru>
parents:
2309
diff
changeset
|
882 if (s->args.nelts == 2) { |
a59b26eee816
compatibility with Microsoft's
Igor Sysoev <igor@sysoev.ru>
parents:
2309
diff
changeset
|
883 return NGX_MAIL_AUTH_LOGIN_USERNAME; |
a59b26eee816
compatibility with Microsoft's
Igor Sysoev <igor@sysoev.ru>
parents:
2309
diff
changeset
|
884 } |
a59b26eee816
compatibility with Microsoft's
Igor Sysoev <igor@sysoev.ru>
parents:
2309
diff
changeset
|
885 |
1479 | 886 return NGX_MAIL_PARSE_INVALID_COMMAND; |
887 } | |
888 | |
889 if (ngx_strncasecmp(arg[0].data, (u_char *) "PLAIN", 5) == 0) { | |
890 | |
891 if (s->args.nelts == 1) { | |
892 return NGX_MAIL_AUTH_PLAIN; | |
893 } | |
894 | |
895 if (s->args.nelts == 2) { | |
896 return ngx_mail_auth_plain(s, c, 1); | |
897 } | |
898 } | |
899 | |
900 return NGX_MAIL_PARSE_INVALID_COMMAND; | |
901 } | |
902 | |
903 if (arg[0].len == 8) { | |
904 | |
6774
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
905 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
|
906 |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
907 if (s->args.nelts != 1) { |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
908 return NGX_MAIL_PARSE_INVALID_COMMAND; |
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 |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
911 return NGX_MAIL_AUTH_CRAM_MD5; |
1479 | 912 } |
913 | |
6774
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
914 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
|
915 |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
916 if (s->args.nelts == 1) { |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
917 return NGX_MAIL_AUTH_EXTERNAL; |
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 |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
920 if (s->args.nelts == 2) { |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
921 return ngx_mail_auth_external(s, c, 1); |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
922 } |
1479 | 923 } |
6774
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
924 |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
925 return NGX_MAIL_PARSE_INVALID_COMMAND; |
1479 | 926 } |
927 | |
928 return NGX_MAIL_PARSE_INVALID_COMMAND; | |
929 } |