Mercurial > hg > nginx-mail
annotate src/mail/ngx_mail_core_module.c @ 405:05c02cbce7be PATCH_NGINX_MAIL_0_4
Mail: reduce diffs.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Tue, 24 Jul 2007 00:28:22 +0000 |
parents | 481e8f936572 |
children | 52b28d322d76 |
rev | line source |
---|---|
290 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 */ | |
5 | |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 #include <ngx_event.h> | |
10 #include <ngx_mail.h> | |
11 | |
12 | |
13 static void *ngx_mail_core_create_main_conf(ngx_conf_t *cf); | |
14 static void *ngx_mail_core_create_srv_conf(ngx_conf_t *cf); | |
15 static char *ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent, | |
16 void *child); | |
17 static char *ngx_mail_core_server(ngx_conf_t *cf, ngx_command_t *cmd, | |
18 void *conf); | |
19 static char *ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, | |
20 void *conf); | |
21 static char *ngx_mail_core_capability(ngx_conf_t *cf, ngx_command_t *cmd, | |
22 void *conf); | |
23 | |
24 | |
25 static ngx_conf_enum_t ngx_mail_core_procotol[] = { | |
26 { ngx_string("pop3"), NGX_MAIL_POP3_PROTOCOL }, | |
27 { ngx_string("imap"), NGX_MAIL_IMAP_PROTOCOL }, | |
28 { ngx_string("smtp"), NGX_MAIL_SMTP_PROTOCOL }, | |
29 { ngx_null_string, 0 } | |
30 }; | |
31 | |
32 | |
33 static ngx_str_t ngx_pop3_default_capabilities[] = { | |
34 ngx_string("TOP"), | |
35 ngx_string("USER"), | |
36 ngx_string("UIDL"), | |
37 ngx_null_string | |
38 }; | |
39 | |
40 | |
41 static ngx_str_t ngx_imap_default_capabilities[] = { | |
42 ngx_string("IMAP4"), | |
43 ngx_string("IMAP4rev1"), | |
44 ngx_string("UIDPLUS"), | |
45 ngx_null_string | |
46 }; | |
47 | |
48 | |
49 static ngx_conf_bitmask_t ngx_pop3_auth_methods[] = { | |
50 { ngx_string("plain"), NGX_MAIL_AUTH_PLAIN_ENABLED }, | |
51 { ngx_string("apop"), NGX_MAIL_AUTH_APOP_ENABLED }, | |
52 { ngx_string("cram-md5"), NGX_MAIL_AUTH_CRAM_MD5_ENABLED }, | |
53 { ngx_null_string, 0 } | |
54 }; | |
55 | |
56 | |
322 | 57 static ngx_conf_bitmask_t ngx_imap_auth_methods[] = { |
58 { ngx_string("plain"), NGX_MAIL_AUTH_PLAIN_ENABLED }, | |
59 { ngx_string("login"), NGX_MAIL_AUTH_LOGIN_ENABLED }, | |
60 { ngx_string("cram-md5"), NGX_MAIL_AUTH_CRAM_MD5_ENABLED }, | |
61 { ngx_null_string, 0 } | |
62 }; | |
63 | |
64 | |
290 | 65 static ngx_conf_bitmask_t ngx_smtp_auth_methods[] = { |
66 { ngx_string("plain"), NGX_MAIL_AUTH_PLAIN_ENABLED }, | |
67 { ngx_string("login"), NGX_MAIL_AUTH_LOGIN_ENABLED }, | |
68 { ngx_string("cram-md5"), NGX_MAIL_AUTH_CRAM_MD5_ENABLED }, | |
404
481e8f936572
Mail: rename "unauth" to "none".
Maxim Dounin <mdounin@mdounin.ru>
parents:
403
diff
changeset
|
69 { ngx_string("none"), NGX_MAIL_AUTH_NONE_ENABLED }, |
290 | 70 { ngx_null_string, 0 } |
71 }; | |
72 | |
73 | |
322 | 74 static ngx_str_t ngx_imap_auth_methods_names[] = { |
75 ngx_string("AUTH=PLAIN"), | |
76 ngx_string("AUTH=LOGIN"), | |
77 ngx_null_string, /* APOP */ | |
400
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
78 ngx_string("AUTH=CRAM-MD5"), |
404
481e8f936572
Mail: rename "unauth" to "none".
Maxim Dounin <mdounin@mdounin.ru>
parents:
403
diff
changeset
|
79 ngx_null_string /* NONE */ |
322 | 80 }; |
81 | |
82 | |
290 | 83 static ngx_str_t ngx_smtp_auth_methods_names[] = { |
296 | 84 ngx_string("PLAIN"), |
290 | 85 ngx_string("LOGIN"), |
86 ngx_null_string, /* APOP */ | |
400
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
87 ngx_string("CRAM-MD5"), |
404
481e8f936572
Mail: rename "unauth" to "none".
Maxim Dounin <mdounin@mdounin.ru>
parents:
403
diff
changeset
|
88 ngx_null_string /* NONE */ |
290 | 89 }; |
90 | |
91 | |
92 static ngx_str_t ngx_pop3_auth_plain_capability = | |
93 ngx_string("+OK methods supported:" CRLF | |
94 "LOGIN" CRLF | |
95 "PLAIN" CRLF | |
96 "." CRLF); | |
97 | |
98 | |
99 static ngx_str_t ngx_pop3_auth_cram_md5_capability = | |
100 ngx_string("+OK methods supported:" CRLF | |
101 "LOGIN" CRLF | |
102 "PLAIN" CRLF | |
103 "CRAM-MD5" CRLF | |
104 "." CRLF); | |
105 | |
106 | |
107 | |
108 static ngx_command_t ngx_mail_core_commands[] = { | |
109 | |
110 { ngx_string("server"), | |
111 NGX_MAIL_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, | |
112 ngx_mail_core_server, | |
113 0, | |
114 0, | |
115 NULL }, | |
116 | |
117 { ngx_string("listen"), | |
118 NGX_MAIL_SRV_CONF|NGX_CONF_TAKE12, | |
119 ngx_mail_core_listen, | |
120 0, | |
121 0, | |
122 NULL }, | |
123 | |
124 { ngx_string("protocol"), | |
125 NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, | |
126 ngx_conf_set_enum_slot, | |
127 NGX_MAIL_SRV_CONF_OFFSET, | |
128 offsetof(ngx_mail_core_srv_conf_t, protocol), | |
129 &ngx_mail_core_procotol }, | |
130 | |
131 { ngx_string("imap_client_buffer"), | |
132 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, | |
133 ngx_conf_set_size_slot, | |
134 NGX_MAIL_SRV_CONF_OFFSET, | |
135 offsetof(ngx_mail_core_srv_conf_t, imap_client_buffer_size), | |
136 NULL }, | |
137 | |
138 { ngx_string("so_keepalive"), | |
139 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, | |
140 ngx_conf_set_flag_slot, | |
141 NGX_MAIL_SRV_CONF_OFFSET, | |
142 offsetof(ngx_mail_core_srv_conf_t, so_keepalive), | |
143 NULL }, | |
144 | |
145 { ngx_string("timeout"), | |
146 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, | |
147 ngx_conf_set_msec_slot, | |
148 NGX_MAIL_SRV_CONF_OFFSET, | |
149 offsetof(ngx_mail_core_srv_conf_t, timeout), | |
150 NULL }, | |
151 | |
152 { ngx_string("pop3_capabilities"), | |
153 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, | |
154 ngx_mail_core_capability, | |
155 NGX_MAIL_SRV_CONF_OFFSET, | |
156 offsetof(ngx_mail_core_srv_conf_t, pop3_capabilities), | |
157 NULL }, | |
158 | |
159 { ngx_string("imap_capabilities"), | |
160 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, | |
161 ngx_mail_core_capability, | |
162 NGX_MAIL_SRV_CONF_OFFSET, | |
163 offsetof(ngx_mail_core_srv_conf_t, imap_capabilities), | |
164 NULL }, | |
165 | |
166 { ngx_string("smtp_capabilities"), | |
167 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, | |
168 ngx_mail_core_capability, | |
169 NGX_MAIL_SRV_CONF_OFFSET, | |
170 offsetof(ngx_mail_core_srv_conf_t, smtp_capabilities), | |
171 NULL }, | |
172 | |
173 { ngx_string("server_name"), | |
174 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, | |
175 ngx_conf_set_str_slot, | |
176 NGX_MAIL_SRV_CONF_OFFSET, | |
177 offsetof(ngx_mail_core_srv_conf_t, server_name), | |
178 NULL }, | |
179 | |
180 { ngx_string("auth"), | |
181 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, | |
182 ngx_conf_set_bitmask_slot, | |
183 NGX_MAIL_SRV_CONF_OFFSET, | |
184 offsetof(ngx_mail_core_srv_conf_t, pop3_auth_methods), | |
185 &ngx_pop3_auth_methods }, | |
186 | |
187 { ngx_string("pop3_auth"), | |
188 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, | |
189 ngx_conf_set_bitmask_slot, | |
190 NGX_MAIL_SRV_CONF_OFFSET, | |
191 offsetof(ngx_mail_core_srv_conf_t, pop3_auth_methods), | |
192 &ngx_pop3_auth_methods }, | |
193 | |
322 | 194 { ngx_string("imap_auth"), |
195 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, | |
196 ngx_conf_set_bitmask_slot, | |
197 NGX_MAIL_SRV_CONF_OFFSET, | |
198 offsetof(ngx_mail_core_srv_conf_t, imap_auth_methods), | |
199 &ngx_imap_auth_methods }, | |
200 | |
290 | 201 { ngx_string("smtp_auth"), |
202 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, | |
203 ngx_conf_set_bitmask_slot, | |
204 NGX_MAIL_SRV_CONF_OFFSET, | |
205 offsetof(ngx_mail_core_srv_conf_t, smtp_auth_methods), | |
206 &ngx_smtp_auth_methods }, | |
207 | |
208 ngx_null_command | |
209 }; | |
210 | |
211 | |
212 static ngx_mail_module_t ngx_mail_core_module_ctx = { | |
213 ngx_mail_core_create_main_conf, /* create main configuration */ | |
214 NULL, /* init main configuration */ | |
215 | |
216 ngx_mail_core_create_srv_conf, /* create server configuration */ | |
217 ngx_mail_core_merge_srv_conf /* merge server configuration */ | |
218 }; | |
219 | |
220 | |
221 ngx_module_t ngx_mail_core_module = { | |
222 NGX_MODULE_V1, | |
223 &ngx_mail_core_module_ctx, /* module context */ | |
224 ngx_mail_core_commands, /* module directives */ | |
225 NGX_MAIL_MODULE, /* module type */ | |
226 NULL, /* init master */ | |
227 NULL, /* init module */ | |
228 NULL, /* init process */ | |
229 NULL, /* init thread */ | |
230 NULL, /* exit thread */ | |
231 NULL, /* exit process */ | |
232 NULL, /* exit master */ | |
233 NGX_MODULE_V1_PADDING | |
234 }; | |
235 | |
236 | |
237 static void * | |
238 ngx_mail_core_create_main_conf(ngx_conf_t *cf) | |
239 { | |
240 ngx_mail_core_main_conf_t *cmcf; | |
241 | |
242 cmcf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_core_main_conf_t)); | |
243 if (cmcf == NULL) { | |
244 return NGX_CONF_ERROR; | |
245 } | |
246 | |
247 if (ngx_array_init(&cmcf->servers, cf->pool, 4, | |
248 sizeof(ngx_mail_core_srv_conf_t *)) | |
249 != NGX_OK) | |
250 { | |
251 return NGX_CONF_ERROR; | |
252 } | |
253 | |
254 if (ngx_array_init(&cmcf->listen, cf->pool, 4, sizeof(ngx_mail_listen_t)) | |
255 != NGX_OK) | |
256 { | |
257 return NGX_CONF_ERROR; | |
258 } | |
259 | |
260 return cmcf; | |
261 } | |
262 | |
263 | |
264 static void * | |
265 ngx_mail_core_create_srv_conf(ngx_conf_t *cf) | |
266 { | |
267 ngx_mail_core_srv_conf_t *cscf; | |
268 | |
269 cscf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_core_srv_conf_t)); | |
270 if (cscf == NULL) { | |
271 return NULL; | |
272 } | |
273 | |
274 cscf->imap_client_buffer_size = NGX_CONF_UNSET_SIZE; | |
275 cscf->protocol = NGX_CONF_UNSET_UINT; | |
276 cscf->timeout = NGX_CONF_UNSET_MSEC; | |
277 cscf->so_keepalive = NGX_CONF_UNSET; | |
278 | |
279 if (ngx_array_init(&cscf->pop3_capabilities, cf->pool, 4, sizeof(ngx_str_t)) | |
280 != NGX_OK) | |
281 { | |
282 return NULL; | |
283 } | |
284 | |
285 if (ngx_array_init(&cscf->imap_capabilities, cf->pool, 4, sizeof(ngx_str_t)) | |
286 != NGX_OK) | |
287 { | |
288 return NULL; | |
289 } | |
290 | |
291 if (ngx_array_init(&cscf->smtp_capabilities, cf->pool, 4, sizeof(ngx_str_t)) | |
292 != NGX_OK) | |
293 { | |
294 return NULL; | |
295 } | |
296 | |
297 return cscf; | |
298 } | |
299 | |
300 | |
301 static char * | |
302 ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) | |
303 { | |
304 ngx_mail_core_srv_conf_t *prev = parent; | |
305 ngx_mail_core_srv_conf_t *conf = child; | |
306 | |
403 | 307 u_char *p, *auth, *last; |
290 | 308 size_t size, stls_only_size; |
309 ngx_str_t *c, *d; | |
400
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
310 ngx_uint_t i, m, smtp_auth_enabled; |
290 | 311 |
312 ngx_conf_merge_size_value(conf->imap_client_buffer_size, | |
313 prev->imap_client_buffer_size, | |
314 (size_t) ngx_pagesize); | |
315 ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000); | |
316 ngx_conf_merge_uint_value(conf->protocol, prev->protocol, | |
317 NGX_MAIL_IMAP_PROTOCOL); | |
318 ngx_conf_merge_value(conf->so_keepalive, prev->so_keepalive, 0); | |
319 | |
320 | |
321 ngx_conf_merge_bitmask_value(conf->pop3_auth_methods, | |
322 prev->pop3_auth_methods, | |
323 (NGX_CONF_BITMASK_SET | |
324 |NGX_MAIL_AUTH_PLAIN_ENABLED)); | |
325 | |
322 | 326 ngx_conf_merge_bitmask_value(conf->imap_auth_methods, |
327 prev->imap_auth_methods, | |
328 (NGX_CONF_BITMASK_SET | |
329 |NGX_MAIL_AUTH_PLAIN_ENABLED)); | |
330 | |
290 | 331 ngx_conf_merge_bitmask_value(conf->smtp_auth_methods, |
332 prev->smtp_auth_methods, | |
333 (NGX_CONF_BITMASK_SET | |
334 |NGX_MAIL_AUTH_PLAIN_ENABLED | |
335 |NGX_MAIL_AUTH_LOGIN_ENABLED)); | |
336 | |
337 | |
338 ngx_conf_merge_str_value(conf->server_name, prev->server_name, ""); | |
339 | |
340 if (conf->server_name.len == 0) { | |
341 conf->server_name.data = ngx_palloc(cf->pool, NGX_MAXHOSTNAMELEN); | |
342 if (conf->server_name.data == NULL) { | |
343 return NGX_CONF_ERROR; | |
344 } | |
345 | |
346 if (gethostname((char *) conf->server_name.data, NGX_MAXHOSTNAMELEN) | |
347 == -1) | |
348 { | |
349 ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, | |
350 "gethostname() failed"); | |
351 return NGX_CONF_ERROR; | |
352 } | |
353 | |
354 conf->server_name.len = ngx_strlen(conf->server_name.data); | |
355 } | |
356 | |
357 | |
358 if (conf->pop3_capabilities.nelts == 0) { | |
359 conf->pop3_capabilities = prev->pop3_capabilities; | |
360 } | |
361 | |
362 if (conf->pop3_capabilities.nelts == 0) { | |
363 | |
364 for (d = ngx_pop3_default_capabilities; d->len; d++) { | |
365 c = ngx_array_push(&conf->pop3_capabilities); | |
366 if (c == NULL) { | |
367 return NGX_CONF_ERROR; | |
368 } | |
369 | |
370 *c = *d; | |
371 } | |
372 } | |
373 | |
374 size = sizeof("+OK Capability list follows" CRLF) - 1 | |
375 + sizeof("." CRLF) - 1; | |
376 | |
377 stls_only_size = size + sizeof("STLS" CRLF) - 1; | |
378 | |
379 c = conf->pop3_capabilities.elts; | |
380 for (i = 0; i < conf->pop3_capabilities.nelts; i++) { | |
381 size += c[i].len + sizeof(CRLF) - 1; | |
382 | |
383 if (ngx_strcasecmp(c[i].data, (u_char *) "USER") == 0) { | |
384 continue; | |
385 } | |
386 | |
387 stls_only_size += c[i].len + sizeof(CRLF) - 1; | |
388 } | |
389 | |
390 if (conf->pop3_auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED) { | |
391 size += sizeof("SASL LOGIN PLAIN CRAM-MD5" CRLF) - 1; | |
392 | |
393 } else { | |
394 size += sizeof("SASL LOGIN PLAIN" CRLF) - 1; | |
395 } | |
396 | |
397 p = ngx_palloc(cf->pool, size); | |
398 if (p == NULL) { | |
399 return NGX_CONF_ERROR; | |
400 } | |
401 | |
402 conf->pop3_capability.len = size; | |
403 conf->pop3_capability.data = p; | |
404 | |
405 p = ngx_cpymem(p, "+OK Capability list follows" CRLF, | |
406 sizeof("+OK Capability list follows" CRLF) - 1); | |
407 | |
408 for (i = 0; i < conf->pop3_capabilities.nelts; i++) { | |
409 p = ngx_cpymem(p, c[i].data, c[i].len); | |
410 *p++ = CR; *p++ = LF; | |
411 } | |
412 | |
413 if (conf->pop3_auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED) { | |
414 p = ngx_cpymem(p, "SASL LOGIN PLAIN CRAM-MD5" CRLF, | |
415 sizeof("SASL LOGIN PLAIN CRAM-MD5" CRLF) - 1); | |
416 | |
417 } else { | |
418 p = ngx_cpymem(p, "SASL LOGIN PLAIN" CRLF, | |
419 sizeof("SASL LOGIN PLAIN" CRLF) - 1); | |
420 } | |
421 | |
422 *p++ = '.'; *p++ = CR; *p = LF; | |
423 | |
424 | |
425 size += sizeof("STLS" CRLF) - 1; | |
426 | |
427 p = ngx_palloc(cf->pool, size); | |
428 if (p == NULL) { | |
429 return NGX_CONF_ERROR; | |
430 } | |
431 | |
432 conf->pop3_starttls_capability.len = size; | |
433 conf->pop3_starttls_capability.data = p; | |
434 | |
435 p = ngx_cpymem(p, conf->pop3_capability.data, | |
436 conf->pop3_capability.len - (sizeof("." CRLF) - 1)); | |
437 | |
438 p = ngx_cpymem(p, "STLS" CRLF, sizeof("STLS" CRLF) - 1); | |
439 *p++ = '.'; *p++ = CR; *p = LF; | |
440 | |
441 | |
442 if (conf->pop3_auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED) { | |
443 conf->pop3_auth_capability = ngx_pop3_auth_cram_md5_capability; | |
444 | |
445 } else { | |
446 conf->pop3_auth_capability = ngx_pop3_auth_plain_capability; | |
447 } | |
448 | |
449 | |
450 p = ngx_palloc(cf->pool, stls_only_size); | |
451 if (p == NULL) { | |
452 return NGX_CONF_ERROR; | |
453 } | |
454 | |
455 conf->pop3_starttls_only_capability.len = stls_only_size; | |
456 conf->pop3_starttls_only_capability.data = p; | |
457 | |
458 p = ngx_cpymem(p, "+OK Capability list follows" CRLF, | |
459 sizeof("+OK Capability list follows" CRLF) - 1); | |
460 | |
461 for (i = 0; i < conf->pop3_capabilities.nelts; i++) { | |
462 if (ngx_strcasecmp(c[i].data, (u_char *) "USER") == 0) { | |
463 continue; | |
464 } | |
465 | |
466 p = ngx_cpymem(p, c[i].data, c[i].len); | |
467 *p++ = CR; *p++ = LF; | |
468 } | |
469 | |
470 p = ngx_cpymem(p, "STLS" CRLF, sizeof("STLS" CRLF) - 1); | |
471 *p++ = '.'; *p++ = CR; *p = LF; | |
472 | |
473 | |
474 if (conf->imap_capabilities.nelts == 0) { | |
475 conf->imap_capabilities = prev->imap_capabilities; | |
476 } | |
477 | |
478 if (conf->imap_capabilities.nelts == 0) { | |
479 | |
480 for (d = ngx_imap_default_capabilities; d->len; d++) { | |
481 c = ngx_array_push(&conf->imap_capabilities); | |
482 if (c == NULL) { | |
483 return NGX_CONF_ERROR; | |
484 } | |
485 | |
486 *c = *d; | |
487 } | |
488 } | |
489 | |
490 size = sizeof("* CAPABILITY" CRLF) - 1; | |
491 | |
492 c = conf->imap_capabilities.elts; | |
493 for (i = 0; i < conf->imap_capabilities.nelts; i++) { | |
494 size += 1 + c[i].len; | |
495 } | |
496 | |
322 | 497 for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0; |
498 m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED; | |
499 m <<= 1, i++) | |
500 { | |
501 if (m & conf->imap_auth_methods) { | |
502 size += 1 + ngx_imap_auth_methods_names[i].len; | |
503 } | |
504 } | |
505 | |
290 | 506 p = ngx_palloc(cf->pool, size); |
507 if (p == NULL) { | |
508 return NGX_CONF_ERROR; | |
509 } | |
510 | |
511 conf->imap_capability.len = size; | |
512 conf->imap_capability.data = p; | |
513 | |
514 p = ngx_cpymem(p, "* CAPABILITY", sizeof("* CAPABILITY") - 1); | |
515 | |
516 for (i = 0; i < conf->imap_capabilities.nelts; i++) { | |
517 *p++ = ' '; | |
518 p = ngx_cpymem(p, c[i].data, c[i].len); | |
519 } | |
520 | |
322 | 521 auth = p; |
522 | |
523 for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0; | |
524 m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED; | |
525 m <<= 1, i++) | |
526 { | |
527 if (m & conf->imap_auth_methods) { | |
528 *p++ = ' '; | |
529 p = ngx_cpymem(p, ngx_imap_auth_methods_names[i].data, | |
530 ngx_imap_auth_methods_names[i].len); | |
531 } | |
532 } | |
533 | |
290 | 534 *p++ = CR; *p = LF; |
535 | |
536 | |
537 size += sizeof(" STARTTLS") - 1; | |
538 | |
539 p = ngx_palloc(cf->pool, size); | |
540 if (p == NULL) { | |
541 return NGX_CONF_ERROR; | |
542 } | |
543 | |
544 conf->imap_starttls_capability.len = size; | |
545 conf->imap_starttls_capability.data = p; | |
546 | |
547 p = ngx_cpymem(p, conf->imap_capability.data, | |
548 conf->imap_capability.len - (sizeof(CRLF) - 1)); | |
549 p = ngx_cpymem(p, " STARTTLS", sizeof(" STARTTLS") - 1); | |
550 *p++ = CR; *p = LF; | |
551 | |
552 | |
322 | 553 size = (auth - conf->imap_capability.data) + sizeof(CRLF) - 1 |
554 + sizeof(" STARTTLS LOGINDISABLED") - 1; | |
290 | 555 |
556 p = ngx_palloc(cf->pool, size); | |
557 if (p == NULL) { | |
558 return NGX_CONF_ERROR; | |
559 } | |
560 | |
561 conf->imap_starttls_only_capability.len = size; | |
562 conf->imap_starttls_only_capability.data = p; | |
563 | |
322 | 564 p = ngx_cpymem(p, conf->imap_capability.data, |
565 auth - conf->imap_capability.data); | |
566 p = ngx_cpymem(p, " STARTTLS LOGINDISABLED", | |
567 sizeof(" STARTTLS LOGINDISABLED") - 1); | |
290 | 568 *p++ = CR; *p = LF; |
569 | |
570 | |
571 size = sizeof("220 ESMTP ready" CRLF) - 1 + conf->server_name.len; | |
572 | |
573 p = ngx_palloc(cf->pool, size); | |
574 if (p == NULL) { | |
575 return NGX_CONF_ERROR; | |
576 } | |
577 | |
578 conf->smtp_greeting.len = size; | |
579 conf->smtp_greeting.data = p; | |
580 | |
581 *p++ = '2'; *p++ = '2'; *p++ = '0'; *p++ = ' '; | |
582 p = ngx_cpymem(p, conf->server_name.data, conf->server_name.len); | |
583 ngx_memcpy(p, " ESMTP ready" CRLF, sizeof(" ESMTP ready" CRLF) - 1); | |
584 | |
585 | |
586 size = sizeof("250 " CRLF) - 1 + conf->server_name.len; | |
587 | |
588 p = ngx_palloc(cf->pool, size); | |
589 if (p == NULL) { | |
590 return NGX_CONF_ERROR; | |
591 } | |
592 | |
593 conf->smtp_server_name.len = size; | |
594 conf->smtp_server_name.data = p; | |
595 | |
596 *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = ' '; | |
597 p = ngx_cpymem(p, conf->server_name.data, conf->server_name.len); | |
598 *p++ = CR; *p = LF; | |
599 | |
600 | |
601 if (conf->smtp_capabilities.nelts == 0) { | |
602 conf->smtp_capabilities = prev->smtp_capabilities; | |
603 } | |
604 | |
400
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
605 size = sizeof("250-") - 1 + conf->server_name.len + sizeof(CRLF) - 1; |
290 | 606 |
607 c = conf->smtp_capabilities.elts; | |
608 for (i = 0; i < conf->smtp_capabilities.nelts; i++) { | |
609 size += sizeof("250 ") - 1 + c[i].len + sizeof(CRLF) - 1; | |
610 } | |
611 | |
400
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
612 smtp_auth_enabled = 0; |
290 | 613 for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0; |
614 m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED; | |
615 m <<= 1, i++) | |
616 { | |
617 if (m & conf->smtp_auth_methods) { | |
618 size += 1 + ngx_smtp_auth_methods_names[i].len; | |
400
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
619 smtp_auth_enabled = 1; |
290 | 620 } |
621 } | |
622 | |
400
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
623 if (smtp_auth_enabled) { |
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
624 size += sizeof("250 AUTH") - 1 + sizeof(CRLF) - 1; |
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
625 } |
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
626 |
290 | 627 p = ngx_palloc(cf->pool, size); |
628 if (p == NULL) { | |
629 return NGX_CONF_ERROR; | |
630 } | |
631 | |
632 conf->smtp_capability.len = size; | |
633 conf->smtp_capability.data = p; | |
634 | |
403 | 635 last = p; |
290 | 636 *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = '-'; |
637 p = ngx_cpymem(p, conf->server_name.data, conf->server_name.len); | |
638 *p++ = CR; *p++ = LF; | |
639 | |
640 for (i = 0; i < conf->smtp_capabilities.nelts; i++) { | |
403 | 641 last = p; |
290 | 642 *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = '-'; |
643 p = ngx_cpymem(p, c[i].data, c[i].len); | |
644 *p++ = CR; *p++ = LF; | |
645 } | |
646 | |
322 | 647 auth = p; |
648 | |
400
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
649 if (smtp_auth_enabled) { |
403 | 650 last = p; |
400
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
651 |
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
652 *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = ' '; |
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
653 *p++ = 'A'; *p++ = 'U'; *p++ = 'T'; *p++ = 'H'; |
290 | 654 |
400
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
655 for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0; |
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
656 m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED; |
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
657 m <<= 1, i++) |
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
658 { |
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
659 if (m & conf->smtp_auth_methods) { |
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
660 *p++ = ' '; |
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
661 p = ngx_cpymem(p, ngx_smtp_auth_methods_names[i].data, |
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
662 ngx_smtp_auth_methods_names[i].len); |
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
663 } |
290 | 664 } |
400
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
665 |
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
666 *p++ = CR; *p = LF; |
290 | 667 |
400
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
668 } else { |
403 | 669 last[3] = ' '; |
400
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
670 } |
290 | 671 |
322 | 672 size += sizeof("250 STARTTLS" CRLF) - 1; |
673 | |
674 p = ngx_palloc(cf->pool, size); | |
675 if (p == NULL) { | |
676 return NGX_CONF_ERROR; | |
677 } | |
678 | |
679 conf->smtp_starttls_capability.len = size; | |
680 conf->smtp_starttls_capability.data = p; | |
681 | |
682 p = ngx_cpymem(p, conf->smtp_capability.data, | |
683 conf->smtp_capability.len); | |
684 | |
685 p = ngx_cpymem(p, "250 STARTTLS" CRLF, sizeof("250 STARTTLS" CRLF) - 1); | |
686 *p++ = CR; *p = LF; | |
687 | |
688 p = conf->smtp_starttls_capability.data | |
403 | 689 + (last - conf->smtp_capability.data) + 3; |
322 | 690 *p = '-'; |
691 | |
692 size = (auth - conf->smtp_capability.data) | |
405 | 693 + sizeof("250 STARTTLS" CRLF) - 1; |
322 | 694 |
695 p = ngx_palloc(cf->pool, size); | |
696 if (p == NULL) { | |
697 return NGX_CONF_ERROR; | |
698 } | |
699 | |
700 conf->smtp_starttls_only_capability.len = size; | |
701 conf->smtp_starttls_only_capability.data = p; | |
702 | |
703 p = ngx_cpymem(p, conf->smtp_capability.data, | |
704 auth - conf->smtp_capability.data); | |
705 | |
405 | 706 ngx_memcpy(p, "250 STARTTLS" CRLF, sizeof("250 STARTTLS" CRLF) - 1); |
396
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
296
diff
changeset
|
707 |
403 | 708 if (last < auth) { |
400
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
709 p = conf->smtp_starttls_only_capability.data |
403 | 710 + (last - conf->smtp_capability.data) + 3; |
400
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
711 *p = '-'; |
f1e2fab7a46c
Mail: smtp proxy without authentication.
Maxim Dounin <mdounin@mdounin.ru>
parents:
398
diff
changeset
|
712 } |
322 | 713 |
290 | 714 return NGX_CONF_OK; |
715 } | |
716 | |
717 | |
718 static char * | |
719 ngx_mail_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
720 { | |
721 char *rv; | |
722 void *mconf; | |
723 ngx_uint_t m; | |
724 ngx_conf_t pcf; | |
725 ngx_mail_module_t *module; | |
726 ngx_mail_conf_ctx_t *ctx, *mail_ctx; | |
727 ngx_mail_core_srv_conf_t *cscf, **cscfp; | |
728 ngx_mail_core_main_conf_t *cmcf; | |
729 | |
730 | |
731 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_mail_conf_ctx_t)); | |
732 if (ctx == NULL) { | |
733 return NGX_CONF_ERROR; | |
734 } | |
735 | |
736 mail_ctx = cf->ctx; | |
737 ctx->main_conf = mail_ctx->main_conf; | |
738 | |
739 /* the server{}'s srv_conf */ | |
740 | |
741 ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_mail_max_module); | |
742 if (ctx->srv_conf == NULL) { | |
743 return NGX_CONF_ERROR; | |
744 } | |
745 | |
746 for (m = 0; ngx_modules[m]; m++) { | |
747 if (ngx_modules[m]->type != NGX_MAIL_MODULE) { | |
748 continue; | |
749 } | |
750 | |
751 module = ngx_modules[m]->ctx; | |
752 | |
753 if (module->create_srv_conf) { | |
754 mconf = module->create_srv_conf(cf); | |
755 if (mconf == NULL) { | |
756 return NGX_CONF_ERROR; | |
757 } | |
758 | |
759 ctx->srv_conf[ngx_modules[m]->ctx_index] = mconf; | |
760 } | |
761 } | |
762 | |
763 /* the server configuration context */ | |
764 | |
765 cscf = ctx->srv_conf[ngx_mail_core_module.ctx_index]; | |
766 cscf->ctx = ctx; | |
767 | |
768 cmcf = ctx->main_conf[ngx_mail_core_module.ctx_index]; | |
769 | |
770 cscfp = ngx_array_push(&cmcf->servers); | |
771 if (cscfp == NULL) { | |
772 return NGX_CONF_ERROR; | |
773 } | |
774 | |
775 *cscfp = cscf; | |
776 | |
777 | |
778 /* parse inside server{} */ | |
779 | |
780 pcf = *cf; | |
781 cf->ctx = ctx; | |
782 cf->cmd_type = NGX_MAIL_SRV_CONF; | |
783 | |
784 rv = ngx_conf_parse(cf, NULL); | |
785 | |
786 *cf = pcf; | |
787 | |
788 return rv; | |
789 } | |
790 | |
791 | |
792 /* AF_INET only */ | |
793 | |
794 static char * | |
795 ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
796 { | |
797 ngx_str_t *value; | |
798 ngx_url_t u; | |
799 ngx_uint_t i; | |
800 ngx_mail_listen_t *imls; | |
801 ngx_mail_core_main_conf_t *cmcf; | |
802 | |
803 value = cf->args->elts; | |
804 | |
805 ngx_memzero(&u, sizeof(ngx_url_t)); | |
806 | |
807 u.url = value[1]; | |
808 u.listen = 1; | |
809 | |
810 if (ngx_parse_url(cf, &u) != NGX_OK) { | |
811 if (u.err) { | |
812 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
813 "%s in \"%V\" of the \"listen\" directive", | |
814 u.err, &u.url); | |
815 } | |
816 | |
817 return NGX_CONF_ERROR; | |
818 } | |
819 | |
820 cmcf = ngx_mail_conf_get_module_main_conf(cf, ngx_mail_core_module); | |
821 | |
822 imls = cmcf->listen.elts; | |
823 | |
824 for (i = 0; i < cmcf->listen.nelts; i++) { | |
825 | |
826 if (imls[i].addr != u.addr.in_addr || imls[i].port != u.port) { | |
827 continue; | |
828 } | |
829 | |
830 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
831 "duplicate \"%V\" address and port pair", &u.url); | |
832 return NGX_CONF_ERROR; | |
833 } | |
834 | |
835 imls = ngx_array_push(&cmcf->listen); | |
836 if (imls == NULL) { | |
837 return NGX_CONF_ERROR; | |
838 } | |
839 | |
840 ngx_memzero(imls, sizeof(ngx_mail_listen_t)); | |
841 | |
842 imls->addr = u.addr.in_addr; | |
843 imls->port = u.port; | |
844 imls->family = AF_INET; | |
845 imls->ctx = cf->ctx; | |
846 | |
847 if (cf->args->nelts == 2) { | |
848 return NGX_CONF_OK; | |
849 } | |
850 | |
851 if (ngx_strcmp(value[2].data, "bind") == 0) { | |
852 imls->bind = 1; | |
853 return NGX_CONF_OK; | |
854 } | |
855 | |
856 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
857 "the invalid \"%V\" parameter", &value[2]); | |
858 return NGX_CONF_ERROR; | |
859 } | |
860 | |
861 | |
862 static char * | |
863 ngx_mail_core_capability(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
864 { | |
865 char *p = conf; | |
866 | |
867 ngx_str_t *c, *value; | |
868 ngx_uint_t i; | |
869 ngx_array_t *a; | |
870 | |
871 a = (ngx_array_t *) (p + cmd->offset); | |
872 | |
873 value = cf->args->elts; | |
874 | |
875 for (i = 1; i < cf->args->nelts; i++) { | |
876 c = ngx_array_push(a); | |
877 if (c == NULL) { | |
878 return NGX_CONF_ERROR; | |
879 } | |
880 | |
881 *c = value[i]; | |
882 } | |
883 | |
884 return NGX_CONF_OK; | |
885 } |