Mercurial > hg > nginx
annotate src/mail/ngx_mail_parse.c @ 7842:4b15f1b92100
Mail: stricter checking of IMAP tags.
Only "A-Za-z0-9-._" characters now allowed (which is stricter than what
RFC 3501 requires, but expected to be enough for all known clients),
and tags shouldn't be longer than 32 characters.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Wed, 19 May 2021 03:13:26 +0300 |
parents | ccdf83bee8c1 |
children | b38728495e1a |
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; |
7842
4b15f1b92100
Mail: stricter checking of IMAP tags.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7841
diff
changeset
|
268 default: |
4b15f1b92100
Mail: stricter checking of IMAP tags.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7841
diff
changeset
|
269 if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z') |
4b15f1b92100
Mail: stricter checking of IMAP tags.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7841
diff
changeset
|
270 && (ch < '0' || ch > '9') && ch != '-' && ch != '.' |
4b15f1b92100
Mail: stricter checking of IMAP tags.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7841
diff
changeset
|
271 && ch != '_') |
4b15f1b92100
Mail: stricter checking of IMAP tags.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7841
diff
changeset
|
272 { |
4b15f1b92100
Mail: stricter checking of IMAP tags.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7841
diff
changeset
|
273 goto invalid; |
4b15f1b92100
Mail: stricter checking of IMAP tags.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7841
diff
changeset
|
274 } |
4b15f1b92100
Mail: stricter checking of IMAP tags.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7841
diff
changeset
|
275 if (p - s->buffer->start > 31) { |
4b15f1b92100
Mail: stricter checking of IMAP tags.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7841
diff
changeset
|
276 goto invalid; |
4b15f1b92100
Mail: stricter checking of IMAP tags.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7841
diff
changeset
|
277 } |
4b15f1b92100
Mail: stricter checking of IMAP tags.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7841
diff
changeset
|
278 break; |
527 | 279 } |
280 break; | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
281 |
527 | 282 case sw_spaces_before_command: |
283 switch (ch) { | |
284 case ' ': | |
285 break; | |
286 case CR: | |
287 s->state = sw_start; | |
1136 | 288 return NGX_MAIL_PARSE_INVALID_COMMAND; |
527 | 289 case LF: |
290 s->state = sw_start; | |
1136 | 291 return NGX_MAIL_PARSE_INVALID_COMMAND; |
527 | 292 default: |
293 s->cmd_start = p; | |
294 state = sw_command; | |
295 break; | |
296 } | |
297 break; | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
298 |
527 | 299 case sw_command: |
300 if (ch == ' ' || ch == CR || ch == LF) { | |
301 | |
302 c = s->cmd_start; | |
303 | |
304 switch (p - c) { | |
305 | |
306 case 4: | |
307 if ((c[0] == 'N' || c[0] == 'n') | |
308 && (c[1] == 'O'|| c[1] == 'o') | |
309 && (c[2] == 'O'|| c[2] == 'o') | |
310 && (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
|
311 { |
527 | 312 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
|
313 |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
314 } else { |
527 | 315 goto invalid; |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
316 } |
527 | 317 break; |
318 | |
319 case 5: | |
320 if ((c[0] == 'L'|| c[0] == 'l') | |
321 && (c[1] == 'O'|| c[1] == 'o') | |
322 && (c[2] == 'G'|| c[2] == 'g') | |
323 && (c[3] == 'I'|| c[3] == 'i') | |
324 && (c[4] == 'N'|| c[4] == 'n')) | |
325 { | |
326 s->command = NGX_IMAP_LOGIN; | |
327 | |
328 } else { | |
329 goto invalid; | |
330 } | |
331 break; | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
332 |
527 | 333 case 6: |
334 if ((c[0] == 'L'|| c[0] == 'l') | |
335 && (c[1] == 'O'|| c[1] == 'o') | |
336 && (c[2] == 'G'|| c[2] == 'g') | |
337 && (c[3] == 'O'|| c[3] == 'o') | |
338 && (c[4] == 'U'|| c[4] == 'u') | |
339 && (c[5] == 'T'|| c[5] == 't')) | |
340 { | |
341 s->command = NGX_IMAP_LOGOUT; | |
342 | |
343 } else { | |
344 goto invalid; | |
345 } | |
346 break; | |
347 | |
1136 | 348 #if (NGX_MAIL_SSL) |
583 | 349 case 8: |
350 if ((c[0] == 'S'|| c[0] == 's') | |
351 && (c[1] == 'T'|| c[1] == 't') | |
352 && (c[2] == 'A'|| c[2] == 'a') | |
353 && (c[3] == 'R'|| c[3] == 'r') | |
354 && (c[4] == 'T'|| c[4] == 't') | |
355 && (c[5] == 'T'|| c[5] == 't') | |
356 && (c[6] == 'L'|| c[6] == 'l') | |
357 && (c[7] == 'S'|| c[7] == 's')) | |
358 { | |
359 s->command = NGX_IMAP_STARTTLS; | |
360 | |
361 } else { | |
362 goto invalid; | |
363 } | |
364 break; | |
365 #endif | |
366 | |
527 | 367 case 10: |
368 if ((c[0] == 'C'|| c[0] == 'c') | |
369 && (c[1] == 'A'|| c[1] == 'a') | |
370 && (c[2] == 'P'|| c[2] == 'p') | |
371 && (c[3] == 'A'|| c[3] == 'a') | |
372 && (c[4] == 'B'|| c[4] == 'b') | |
373 && (c[5] == 'I'|| c[5] == 'i') | |
374 && (c[6] == 'L'|| c[6] == 'l') | |
375 && (c[7] == 'I'|| c[7] == 'i') | |
376 && (c[8] == 'T'|| c[8] == 't') | |
377 && (c[9] == 'Y'|| c[9] == 'y')) | |
378 { | |
379 s->command = NGX_IMAP_CAPABILITY; | |
380 | |
381 } else { | |
382 goto invalid; | |
383 } | |
384 break; | |
385 | |
1323 | 386 case 12: |
387 if ((c[0] == 'A'|| c[0] == 'a') | |
388 && (c[1] == 'U'|| c[1] == 'u') | |
389 && (c[2] == 'T'|| c[2] == 't') | |
390 && (c[3] == 'H'|| c[3] == 'h') | |
391 && (c[4] == 'E'|| c[4] == 'e') | |
392 && (c[5] == 'N'|| c[5] == 'n') | |
393 && (c[6] == 'T'|| c[6] == 't') | |
394 && (c[7] == 'I'|| c[7] == 'i') | |
395 && (c[8] == 'C'|| c[8] == 'c') | |
396 && (c[9] == 'A'|| c[9] == 'a') | |
397 && (c[10] == 'T'|| c[10] == 't') | |
398 && (c[11] == 'E'|| c[11] == 'e')) | |
399 { | |
400 s->command = NGX_IMAP_AUTHENTICATE; | |
401 | |
402 } else { | |
403 goto invalid; | |
404 } | |
405 break; | |
406 | |
527 | 407 default: |
408 goto invalid; | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
409 } |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
410 |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
411 switch (ch) { |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
412 case ' ': |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
413 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
|
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 CR: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
416 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
|
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 LF: |
527 | 419 goto done; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
420 } |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
421 break; |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
422 } |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
423 |
527 | 424 if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) { |
425 goto invalid; | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
426 } |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
427 |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
428 break; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
429 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
430 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
|
431 switch (ch) { |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
432 case ' ': |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
433 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
434 case CR: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
435 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
|
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 LF: |
527 | 438 goto done; |
439 case '"': | |
440 if (s->args.nelts <= 2) { | |
441 s->quoted = 1; | |
442 s->arg_start = p + 1; | |
443 state = sw_argument; | |
444 break; | |
445 } | |
446 goto invalid; | |
447 case '{': | |
448 if (s->args.nelts <= 2) { | |
449 state = sw_literal; | |
450 break; | |
451 } | |
452 goto invalid; | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
453 default: |
527 | 454 if (s->args.nelts <= 2) { |
455 s->arg_start = p; | |
456 state = sw_argument; | |
457 break; | |
458 } | |
459 goto invalid; | |
460 } | |
461 break; | |
462 | |
463 case sw_argument: | |
1405
fdd064faf26a
escape " ", "%", and %00-%1F in login and password
Igor Sysoev <igor@sysoev.ru>
parents:
1323
diff
changeset
|
464 if (ch == ' ' && s->quoted) { |
fdd064faf26a
escape " ", "%", and %00-%1F in login and password
Igor Sysoev <igor@sysoev.ru>
parents:
1323
diff
changeset
|
465 break; |
fdd064faf26a
escape " ", "%", and %00-%1F in login and password
Igor Sysoev <igor@sysoev.ru>
parents:
1323
diff
changeset
|
466 } |
fdd064faf26a
escape " ", "%", and %00-%1F in login and password
Igor Sysoev <igor@sysoev.ru>
parents:
1323
diff
changeset
|
467 |
527 | 468 switch (ch) { |
469 case '"': | |
470 if (!s->quoted) { | |
471 break; | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
472 } |
527 | 473 s->quoted = 0; |
474 /* fall through */ | |
475 case ' ': | |
476 case CR: | |
477 case LF: | |
478 arg = ngx_array_push(&s->args); | |
479 if (arg == NULL) { | |
480 return NGX_ERROR; | |
481 } | |
482 arg->len = p - s->arg_start; | |
483 arg->data = s->arg_start; | |
7841
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 if (s->backslash) { |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
486 dst = s->arg_start; |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
487 end = p; |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
488 |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
489 for (src = dst; src < end; dst++) { |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
490 *dst = *src; |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
491 if (*src++ == '\\') { |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
492 *dst = *src++; |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
493 } |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
494 } |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
495 |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
496 arg->len = dst - s->arg_start; |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
497 s->backslash = 0; |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
498 } |
ccdf83bee8c1
Mail: fixed backslash handling in IMAP literals.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7840
diff
changeset
|
499 |
527 | 500 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
|
501 |
527 | 502 switch (ch) { |
503 case '"': | |
504 case ' ': | |
505 state = sw_spaces_before_argument; | |
506 break; | |
507 case CR: | |
508 state = sw_almost_done; | |
509 break; | |
510 case LF: | |
511 goto done; | |
512 } | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
513 break; |
543 | 514 case '\\': |
515 if (s->quoted) { | |
516 s->backslash = 1; | |
517 state = sw_backslash; | |
518 } | |
519 break; | |
520 } | |
521 break; | |
522 | |
523 case sw_backslash: | |
524 switch (ch) { | |
525 case CR: | |
526 case LF: | |
527 goto invalid; | |
528 default: | |
529 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
|
530 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
531 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
532 |
527 | 533 case sw_literal: |
534 if (ch >= '0' && ch <= '9') { | |
535 s->literal_len = s->literal_len * 10 + (ch - '0'); | |
536 break; | |
537 } | |
538 if (ch == '}') { | |
539 state = sw_start_literal_argument; | |
540 break; | |
541 } | |
543 | 542 if (ch == '+') { |
543 state = sw_no_sync_literal_argument; | |
544 break; | |
545 } | |
546 goto invalid; | |
547 | |
548 case sw_no_sync_literal_argument: | |
549 if (ch == '}') { | |
550 s->no_sync_literal = 1; | |
551 state = sw_start_literal_argument; | |
552 break; | |
553 } | |
527 | 554 goto invalid; |
555 | |
556 case sw_start_literal_argument: | |
557 switch (ch) { | |
558 case CR: | |
559 break; | |
560 case LF: | |
561 s->buffer->pos = p + 1; | |
562 s->arg_start = p + 1; | |
543 | 563 if (s->no_sync_literal == 0) { |
564 s->state = sw_literal_argument; | |
565 return NGX_IMAP_NEXT; | |
566 } | |
567 state = sw_literal_argument; | |
568 s->no_sync_literal = 0; | |
569 break; | |
570 default: | |
571 goto invalid; | |
527 | 572 } |
543 | 573 break; |
527 | 574 |
575 case sw_literal_argument: | |
529 | 576 if (s->literal_len && --s->literal_len) { |
527 | 577 break; |
578 } | |
579 | |
580 arg = ngx_array_push(&s->args); | |
581 if (arg == NULL) { | |
582 return NGX_ERROR; | |
583 } | |
584 arg->len = p + 1 - s->arg_start; | |
585 arg->data = s->arg_start; | |
586 s->arg_start = NULL; | |
587 state = sw_end_literal_argument; | |
588 | |
589 break; | |
590 | |
591 case sw_end_literal_argument: | |
592 switch (ch) { | |
593 case '{': | |
594 if (s->args.nelts <= 2) { | |
595 state = sw_literal; | |
596 break; | |
597 } | |
598 goto invalid; | |
599 case CR: | |
600 state = sw_almost_done; | |
601 break; | |
602 case LF: | |
603 goto done; | |
604 default: | |
529 | 605 state = sw_spaces_before_argument; |
606 break; | |
527 | 607 } |
608 break; | |
609 | |
610 case sw_almost_done: | |
611 switch (ch) { | |
612 case LF: | |
613 goto done; | |
614 default: | |
615 goto invalid; | |
616 } | |
617 } | |
618 } | |
619 | |
620 s->buffer->pos = p; | |
621 s->state = state; | |
622 | |
623 return NGX_AGAIN; | |
624 | |
625 done: | |
626 | |
627 s->buffer->pos = p + 1; | |
1323 | 628 s->state = (s->command != NGX_IMAP_AUTHENTICATE) ? sw_start : sw_argument; |
527 | 629 |
630 return NGX_OK; | |
631 | |
632 invalid: | |
633 | |
634 s->state = sw_start; | |
635 s->quoted = 0; | |
7839
3974f4e56a4e
Mail: fixed s->arg_start clearing on invalid IMAP commands.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7838
diff
changeset
|
636 s->backslash = 0; |
543 | 637 s->no_sync_literal = 0; |
527 | 638 s->literal_len = 0; |
639 | |
1136 | 640 return NGX_MAIL_PARSE_INVALID_COMMAND; |
527 | 641 } |
642 | |
643 | |
1477 | 644 ngx_int_t |
645 ngx_mail_smtp_parse_command(ngx_mail_session_t *s) | |
527 | 646 { |
647 u_char ch, *p, *c, c0, c1, c2, c3; | |
648 ngx_str_t *arg; | |
649 enum { | |
650 sw_start = 0, | |
5398
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
651 sw_command, |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
652 sw_invalid, |
527 | 653 sw_spaces_before_argument, |
654 sw_argument, | |
655 sw_almost_done | |
656 } state; | |
657 | |
658 state = s->state; | |
659 | |
660 for (p = s->buffer->pos; p < s->buffer->last; p++) { | |
661 ch = *p; | |
662 | |
663 switch (state) { | |
664 | |
1136 | 665 /* SMTP command */ |
527 | 666 case sw_start: |
5398
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
667 s->cmd_start = p; |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
668 state = sw_command; |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
669 |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
670 /* fall through */ |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
671 |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
672 case sw_command: |
527 | 673 if (ch == ' ' || ch == CR || ch == LF) { |
5398
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
674 c = s->cmd_start; |
527 | 675 |
676 if (p - c == 4) { | |
677 | |
678 c0 = ngx_toupper(c[0]); | |
679 c1 = ngx_toupper(c[1]); | |
680 c2 = ngx_toupper(c[2]); | |
681 c3 = ngx_toupper(c[3]); | |
682 | |
1136 | 683 if (c0 == 'H' && c1 == 'E' && c2 == 'L' && c3 == 'O') |
527 | 684 { |
1136 | 685 s->command = NGX_SMTP_HELO; |
527 | 686 |
1136 | 687 } else if (c0 == 'E' && c1 == 'H' && c2 == 'L' && c3 == 'O') |
800 | 688 { |
1136 | 689 s->command = NGX_SMTP_EHLO; |
800 | 690 |
527 | 691 } else if (c0 == 'Q' && c1 == 'U' && c2 == 'I' && c3 == 'T') |
692 { | |
1136 | 693 s->command = NGX_SMTP_QUIT; |
527 | 694 |
809 | 695 } else if (c0 == 'A' && c1 == 'U' && c2 == 'T' && c3 == 'H') |
696 { | |
1136 | 697 s->command = NGX_SMTP_AUTH; |
809 | 698 |
527 | 699 } else if (c0 == 'N' && c1 == 'O' && c2 == 'O' && c3 == 'P') |
700 { | |
1136 | 701 s->command = NGX_SMTP_NOOP; |
702 | |
703 } else if (c0 == 'M' && c1 == 'A' && c2 == 'I' && c3 == 'L') | |
583 | 704 { |
1136 | 705 s->command = NGX_SMTP_MAIL; |
706 | |
707 } else if (c0 == 'R' && c1 == 'S' && c2 == 'E' && c3 == 'T') | |
708 { | |
709 s->command = NGX_SMTP_RSET; | |
710 | |
1322 | 711 } else if (c0 == 'R' && c1 == 'C' && c2 == 'P' && c3 == 'T') |
712 { | |
713 s->command = NGX_SMTP_RCPT; | |
714 | |
715 } else if (c0 == 'V' && c1 == 'R' && c2 == 'F' && c3 == 'Y') | |
716 { | |
717 s->command = NGX_SMTP_VRFY; | |
718 | |
719 } else if (c0 == 'E' && c1 == 'X' && c2 == 'P' && c3 == 'N') | |
720 { | |
721 s->command = NGX_SMTP_EXPN; | |
722 | |
723 } else if (c0 == 'H' && c1 == 'E' && c2 == 'L' && c3 == 'P') | |
724 { | |
725 s->command = NGX_SMTP_HELP; | |
726 | |
527 | 727 } else { |
728 goto invalid; | |
729 } | |
1322 | 730 #if (NGX_MAIL_SSL) |
731 } else if (p - c == 8) { | |
527 | 732 |
1322 | 733 if ((c[0] == 'S'|| c[0] == 's') |
734 && (c[1] == 'T'|| c[1] == 't') | |
735 && (c[2] == 'A'|| c[2] == 'a') | |
736 && (c[3] == 'R'|| c[3] == 'r') | |
737 && (c[4] == 'T'|| c[4] == 't') | |
738 && (c[5] == 'T'|| c[5] == 't') | |
739 && (c[6] == 'L'|| c[6] == 'l') | |
740 && (c[7] == 'S'|| c[7] == 's')) | |
741 { | |
742 s->command = NGX_SMTP_STARTTLS; | |
743 | |
744 } else { | |
745 goto invalid; | |
746 } | |
747 #endif | |
527 | 748 } else { |
749 goto invalid; | |
750 } | |
751 | |
5398
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
752 s->cmd.data = s->cmd_start; |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
753 s->cmd.len = p - s->cmd_start; |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
754 |
527 | 755 switch (ch) { |
756 case ' ': | |
757 state = sw_spaces_before_argument; | |
758 break; | |
759 case CR: | |
760 state = sw_almost_done; | |
761 break; | |
762 case LF: | |
763 goto done; | |
764 } | |
765 break; | |
766 } | |
767 | |
768 if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) { | |
769 goto invalid; | |
770 } | |
771 | |
772 break; | |
773 | |
5398
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
774 case sw_invalid: |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
775 goto invalid; |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
776 |
527 | 777 case sw_spaces_before_argument: |
778 switch (ch) { | |
779 case ' ': | |
780 break; | |
781 case CR: | |
782 state = sw_almost_done; | |
783 break; | |
784 case LF: | |
785 goto done; | |
786 default: | |
2309 | 787 if (s->args.nelts <= 10) { |
527 | 788 state = sw_argument; |
789 s->arg_start = p; | |
790 break; | |
791 } | |
792 goto invalid; | |
793 } | |
794 break; | |
795 | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
796 case sw_argument: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
797 switch (ch) { |
800 | 798 case ' ': |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
799 case CR: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
800 case LF: |
501 | 801 arg = ngx_array_push(&s->args); |
802 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
|
803 return NGX_ERROR; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
804 } |
527 | 805 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
|
806 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
|
807 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
|
808 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
809 switch (ch) { |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
810 case ' ': |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
811 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
|
812 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
813 case CR: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
814 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
|
815 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
816 case LF: |
527 | 817 goto done; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
818 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
819 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
820 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
821 default: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
822 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
823 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
824 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
825 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
826 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
|
827 switch (ch) { |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
828 case LF: |
527 | 829 goto done; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
830 default: |
527 | 831 goto invalid; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
832 } |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
833 } |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
834 } |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
835 |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
836 s->buffer->pos = p; |
527 | 837 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
|
838 |
527 | 839 return NGX_AGAIN; |
840 | |
841 done: | |
842 | |
843 s->buffer->pos = p + 1; | |
1136 | 844 s->state = (s->command != NGX_SMTP_AUTH) ? sw_start : sw_argument; |
845 | |
527 | 846 return NGX_OK; |
847 | |
848 invalid: | |
849 | |
5398
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
850 s->state = sw_invalid; |
527 | 851 |
5398
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
852 /* skip invalid command till LF */ |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
853 |
7837
ba8a8299b904
Mail: optimized discarding invalid SMTP commands.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7836
diff
changeset
|
854 for ( /* void */ ; p < s->buffer->last; p++) { |
5398
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
855 if (*p == LF) { |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
856 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
|
857 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
|
858 return NGX_MAIL_PARSE_INVALID_COMMAND; |
5398
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
859 } |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
860 } |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
861 |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
862 s->buffer->pos = p; |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5246
diff
changeset
|
863 |
7836
6a81d96d3733
Mail: fixed handling of invalid SMTP commands split between reads.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6774
diff
changeset
|
864 return NGX_AGAIN; |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
865 } |
1479 | 866 |
867 | |
868 ngx_int_t | |
869 ngx_mail_auth_parse(ngx_mail_session_t *s, ngx_connection_t *c) | |
870 { | |
871 ngx_str_t *arg; | |
872 | |
873 #if (NGX_MAIL_SSL) | |
874 if (ngx_mail_starttls_only(s, c)) { | |
875 return NGX_MAIL_PARSE_INVALID_COMMAND; | |
876 } | |
877 #endif | |
878 | |
5246
b6562f98bfd8
Mail: fixed possible uninitialized memory access.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4759
diff
changeset
|
879 if (s->args.nelts == 0) { |
b6562f98bfd8
Mail: fixed possible uninitialized memory access.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4759
diff
changeset
|
880 return NGX_MAIL_PARSE_INVALID_COMMAND; |
b6562f98bfd8
Mail: fixed possible uninitialized memory access.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4759
diff
changeset
|
881 } |
b6562f98bfd8
Mail: fixed possible uninitialized memory access.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4759
diff
changeset
|
882 |
1479 | 883 arg = s->args.elts; |
884 | |
885 if (arg[0].len == 5) { | |
886 | |
887 if (ngx_strncasecmp(arg[0].data, (u_char *) "LOGIN", 5) == 0) { | |
888 | |
889 if (s->args.nelts == 1) { | |
890 return NGX_MAIL_AUTH_LOGIN; | |
891 } | |
892 | |
2495
a59b26eee816
compatibility with Microsoft's
Igor Sysoev <igor@sysoev.ru>
parents:
2309
diff
changeset
|
893 if (s->args.nelts == 2) { |
a59b26eee816
compatibility with Microsoft's
Igor Sysoev <igor@sysoev.ru>
parents:
2309
diff
changeset
|
894 return NGX_MAIL_AUTH_LOGIN_USERNAME; |
a59b26eee816
compatibility with Microsoft's
Igor Sysoev <igor@sysoev.ru>
parents:
2309
diff
changeset
|
895 } |
a59b26eee816
compatibility with Microsoft's
Igor Sysoev <igor@sysoev.ru>
parents:
2309
diff
changeset
|
896 |
1479 | 897 return NGX_MAIL_PARSE_INVALID_COMMAND; |
898 } | |
899 | |
900 if (ngx_strncasecmp(arg[0].data, (u_char *) "PLAIN", 5) == 0) { | |
901 | |
902 if (s->args.nelts == 1) { | |
903 return NGX_MAIL_AUTH_PLAIN; | |
904 } | |
905 | |
906 if (s->args.nelts == 2) { | |
907 return ngx_mail_auth_plain(s, c, 1); | |
908 } | |
909 } | |
910 | |
911 return NGX_MAIL_PARSE_INVALID_COMMAND; | |
912 } | |
913 | |
914 if (arg[0].len == 8) { | |
915 | |
6774
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
916 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
|
917 |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
918 if (s->args.nelts != 1) { |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
919 return NGX_MAIL_PARSE_INVALID_COMMAND; |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
920 } |
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 return NGX_MAIL_AUTH_CRAM_MD5; |
1479 | 923 } |
924 | |
6774
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
925 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
|
926 |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
927 if (s->args.nelts == 1) { |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
928 return NGX_MAIL_AUTH_EXTERNAL; |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
929 } |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
930 |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
931 if (s->args.nelts == 2) { |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
932 return ngx_mail_auth_external(s, c, 1); |
bcb107bb89cd
Mail: support SASL EXTERNAL (RFC 4422).
Rob N ★ <robn@fastmail.com>
parents:
5398
diff
changeset
|
933 } |
1479 | 934 } |
6774
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 return NGX_MAIL_PARSE_INVALID_COMMAND; |
1479 | 937 } |
938 | |
939 return NGX_MAIL_PARSE_INVALID_COMMAND; | |
940 } |