Mercurial > hg > nginx
comparison src/mail/ngx_mail_core_module.c @ 1136:68f30ab68bb7
Many changes:
*) rename imap to mail, sort pop3/imap functions
*) smtp auth support
*) pop3 starttls only
*) fix segfault if cram-md5 was used without apop
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 19 Mar 2007 13:36:56 +0000 |
parents | src/imap/ngx_imap_core_module.c@a0310ac2814f |
children | 6be5ee17d80b |
comparison
equal
deleted
inserted
replaced
1135:03f1133f24e8 | 1136:68f30ab68bb7 |
---|---|
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 | |
57 static ngx_conf_bitmask_t ngx_smtp_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 | |
65 static ngx_str_t ngx_smtp_auth_methods_names[] = { | |
66 ngx_string("PLAIN"), | |
67 ngx_string("LOGIN"), | |
68 ngx_null_string, /* APOP */ | |
69 ngx_string("CRAM-MD5") | |
70 }; | |
71 | |
72 | |
73 static ngx_str_t ngx_pop3_auth_plain_capability = | |
74 ngx_string("+OK methods supported:" CRLF | |
75 "LOGIN" CRLF | |
76 "PLAIN" CRLF | |
77 "." CRLF); | |
78 | |
79 | |
80 static ngx_str_t ngx_pop3_auth_cram_md5_capability = | |
81 ngx_string("+OK methods supported:" CRLF | |
82 "LOGIN" CRLF | |
83 "PLAIN" CRLF | |
84 "CRAM-MD5" CRLF | |
85 "." CRLF); | |
86 | |
87 | |
88 | |
89 static ngx_command_t ngx_mail_core_commands[] = { | |
90 | |
91 { ngx_string("server"), | |
92 NGX_MAIL_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, | |
93 ngx_mail_core_server, | |
94 0, | |
95 0, | |
96 NULL }, | |
97 | |
98 { ngx_string("listen"), | |
99 NGX_MAIL_SRV_CONF|NGX_CONF_TAKE12, | |
100 ngx_mail_core_listen, | |
101 0, | |
102 0, | |
103 NULL }, | |
104 | |
105 { ngx_string("protocol"), | |
106 NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, | |
107 ngx_conf_set_enum_slot, | |
108 NGX_MAIL_SRV_CONF_OFFSET, | |
109 offsetof(ngx_mail_core_srv_conf_t, protocol), | |
110 &ngx_mail_core_procotol }, | |
111 | |
112 { ngx_string("imap_client_buffer"), | |
113 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, | |
114 ngx_conf_set_size_slot, | |
115 NGX_MAIL_SRV_CONF_OFFSET, | |
116 offsetof(ngx_mail_core_srv_conf_t, imap_client_buffer_size), | |
117 NULL }, | |
118 | |
119 { ngx_string("so_keepalive"), | |
120 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, | |
121 ngx_conf_set_flag_slot, | |
122 NGX_MAIL_SRV_CONF_OFFSET, | |
123 offsetof(ngx_mail_core_srv_conf_t, so_keepalive), | |
124 NULL }, | |
125 | |
126 { ngx_string("timeout"), | |
127 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, | |
128 ngx_conf_set_msec_slot, | |
129 NGX_MAIL_SRV_CONF_OFFSET, | |
130 offsetof(ngx_mail_core_srv_conf_t, timeout), | |
131 NULL }, | |
132 | |
133 { ngx_string("pop3_capabilities"), | |
134 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, | |
135 ngx_mail_core_capability, | |
136 NGX_MAIL_SRV_CONF_OFFSET, | |
137 offsetof(ngx_mail_core_srv_conf_t, pop3_capabilities), | |
138 NULL }, | |
139 | |
140 { ngx_string("imap_capabilities"), | |
141 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, | |
142 ngx_mail_core_capability, | |
143 NGX_MAIL_SRV_CONF_OFFSET, | |
144 offsetof(ngx_mail_core_srv_conf_t, imap_capabilities), | |
145 NULL }, | |
146 | |
147 { ngx_string("smtp_capabilities"), | |
148 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, | |
149 ngx_mail_core_capability, | |
150 NGX_MAIL_SRV_CONF_OFFSET, | |
151 offsetof(ngx_mail_core_srv_conf_t, smtp_capabilities), | |
152 NULL }, | |
153 | |
154 { ngx_string("server_name"), | |
155 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, | |
156 ngx_conf_set_str_slot, | |
157 NGX_MAIL_SRV_CONF_OFFSET, | |
158 offsetof(ngx_mail_core_srv_conf_t, server_name), | |
159 NULL }, | |
160 | |
161 { ngx_string("auth"), | |
162 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, | |
163 ngx_conf_set_bitmask_slot, | |
164 NGX_MAIL_SRV_CONF_OFFSET, | |
165 offsetof(ngx_mail_core_srv_conf_t, pop3_auth_methods), | |
166 &ngx_pop3_auth_methods }, | |
167 | |
168 { ngx_string("pop3_auth"), | |
169 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, | |
170 ngx_conf_set_bitmask_slot, | |
171 NGX_MAIL_SRV_CONF_OFFSET, | |
172 offsetof(ngx_mail_core_srv_conf_t, pop3_auth_methods), | |
173 &ngx_pop3_auth_methods }, | |
174 | |
175 { ngx_string("smtp_auth"), | |
176 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, | |
177 ngx_conf_set_bitmask_slot, | |
178 NGX_MAIL_SRV_CONF_OFFSET, | |
179 offsetof(ngx_mail_core_srv_conf_t, smtp_auth_methods), | |
180 &ngx_smtp_auth_methods }, | |
181 | |
182 ngx_null_command | |
183 }; | |
184 | |
185 | |
186 static ngx_mail_module_t ngx_mail_core_module_ctx = { | |
187 ngx_mail_core_create_main_conf, /* create main configuration */ | |
188 NULL, /* init main configuration */ | |
189 | |
190 ngx_mail_core_create_srv_conf, /* create server configuration */ | |
191 ngx_mail_core_merge_srv_conf /* merge server configuration */ | |
192 }; | |
193 | |
194 | |
195 ngx_module_t ngx_mail_core_module = { | |
196 NGX_MODULE_V1, | |
197 &ngx_mail_core_module_ctx, /* module context */ | |
198 ngx_mail_core_commands, /* module directives */ | |
199 NGX_MAIL_MODULE, /* module type */ | |
200 NULL, /* init master */ | |
201 NULL, /* init module */ | |
202 NULL, /* init process */ | |
203 NULL, /* init thread */ | |
204 NULL, /* exit thread */ | |
205 NULL, /* exit process */ | |
206 NULL, /* exit master */ | |
207 NGX_MODULE_V1_PADDING | |
208 }; | |
209 | |
210 | |
211 static void * | |
212 ngx_mail_core_create_main_conf(ngx_conf_t *cf) | |
213 { | |
214 ngx_mail_core_main_conf_t *cmcf; | |
215 | |
216 cmcf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_core_main_conf_t)); | |
217 if (cmcf == NULL) { | |
218 return NGX_CONF_ERROR; | |
219 } | |
220 | |
221 if (ngx_array_init(&cmcf->servers, cf->pool, 4, | |
222 sizeof(ngx_mail_core_srv_conf_t *)) | |
223 != NGX_OK) | |
224 { | |
225 return NGX_CONF_ERROR; | |
226 } | |
227 | |
228 if (ngx_array_init(&cmcf->listen, cf->pool, 4, sizeof(ngx_mail_listen_t)) | |
229 != NGX_OK) | |
230 { | |
231 return NGX_CONF_ERROR; | |
232 } | |
233 | |
234 return cmcf; | |
235 } | |
236 | |
237 | |
238 static void * | |
239 ngx_mail_core_create_srv_conf(ngx_conf_t *cf) | |
240 { | |
241 ngx_mail_core_srv_conf_t *cscf; | |
242 | |
243 cscf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_core_srv_conf_t)); | |
244 if (cscf == NULL) { | |
245 return NULL; | |
246 } | |
247 | |
248 cscf->imap_client_buffer_size = NGX_CONF_UNSET_SIZE; | |
249 cscf->protocol = NGX_CONF_UNSET_UINT; | |
250 cscf->timeout = NGX_CONF_UNSET_MSEC; | |
251 cscf->so_keepalive = NGX_CONF_UNSET; | |
252 | |
253 if (ngx_array_init(&cscf->pop3_capabilities, cf->pool, 4, sizeof(ngx_str_t)) | |
254 != NGX_OK) | |
255 { | |
256 return NULL; | |
257 } | |
258 | |
259 if (ngx_array_init(&cscf->imap_capabilities, cf->pool, 4, sizeof(ngx_str_t)) | |
260 != NGX_OK) | |
261 { | |
262 return NULL; | |
263 } | |
264 | |
265 if (ngx_array_init(&cscf->smtp_capabilities, cf->pool, 4, sizeof(ngx_str_t)) | |
266 != NGX_OK) | |
267 { | |
268 return NULL; | |
269 } | |
270 | |
271 return cscf; | |
272 } | |
273 | |
274 | |
275 static char * | |
276 ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) | |
277 { | |
278 ngx_mail_core_srv_conf_t *prev = parent; | |
279 ngx_mail_core_srv_conf_t *conf = child; | |
280 | |
281 u_char *p; | |
282 size_t size, stls_only_size; | |
283 ngx_str_t *c, *d; | |
284 ngx_uint_t i, m; | |
285 | |
286 ngx_conf_merge_size_value(conf->imap_client_buffer_size, | |
287 prev->imap_client_buffer_size, | |
288 (size_t) ngx_pagesize); | |
289 ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000); | |
290 ngx_conf_merge_uint_value(conf->protocol, prev->protocol, | |
291 NGX_MAIL_IMAP_PROTOCOL); | |
292 ngx_conf_merge_value(conf->so_keepalive, prev->so_keepalive, 0); | |
293 | |
294 | |
295 ngx_conf_merge_bitmask_value(conf->pop3_auth_methods, | |
296 prev->pop3_auth_methods, | |
297 (NGX_CONF_BITMASK_SET | |
298 |NGX_MAIL_AUTH_PLAIN_ENABLED)); | |
299 | |
300 ngx_conf_merge_bitmask_value(conf->smtp_auth_methods, | |
301 prev->smtp_auth_methods, | |
302 (NGX_CONF_BITMASK_SET | |
303 |NGX_MAIL_AUTH_PLAIN_ENABLED | |
304 |NGX_MAIL_AUTH_LOGIN_ENABLED)); | |
305 | |
306 | |
307 ngx_conf_merge_str_value(conf->server_name, prev->server_name, ""); | |
308 | |
309 if (conf->server_name.len == 0) { | |
310 conf->server_name.data = ngx_palloc(cf->pool, NGX_MAXHOSTNAMELEN); | |
311 if (conf->server_name.data == NULL) { | |
312 return NGX_CONF_ERROR; | |
313 } | |
314 | |
315 if (gethostname((char *) conf->server_name.data, NGX_MAXHOSTNAMELEN) | |
316 == -1) | |
317 { | |
318 ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, | |
319 "gethostname() failed"); | |
320 return NGX_CONF_ERROR; | |
321 } | |
322 | |
323 conf->server_name.len = ngx_strlen(conf->server_name.data); | |
324 } | |
325 | |
326 | |
327 if (conf->pop3_capabilities.nelts == 0) { | |
328 conf->pop3_capabilities = prev->pop3_capabilities; | |
329 } | |
330 | |
331 if (conf->pop3_capabilities.nelts == 0) { | |
332 | |
333 for (d = ngx_pop3_default_capabilities; d->len; d++) { | |
334 c = ngx_array_push(&conf->pop3_capabilities); | |
335 if (c == NULL) { | |
336 return NGX_CONF_ERROR; | |
337 } | |
338 | |
339 *c = *d; | |
340 } | |
341 } | |
342 | |
343 size = sizeof("+OK Capability list follows" CRLF) - 1 | |
344 + sizeof("." CRLF) - 1; | |
345 | |
346 stls_only_size = size + sizeof("STLS" CRLF) - 1; | |
347 | |
348 c = conf->pop3_capabilities.elts; | |
349 for (i = 0; i < conf->pop3_capabilities.nelts; i++) { | |
350 size += c[i].len + sizeof(CRLF) - 1; | |
351 | |
352 if (ngx_strcasecmp(c[i].data, (u_char *) "USER") == 0) { | |
353 continue; | |
354 } | |
355 | |
356 stls_only_size += c[i].len + sizeof(CRLF) - 1; | |
357 } | |
358 | |
359 if (conf->pop3_auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED) { | |
360 size += sizeof("SASL LOGIN PLAIN CRAM-MD5" CRLF) - 1; | |
361 | |
362 } else { | |
363 size += sizeof("SASL LOGIN PLAIN" CRLF) - 1; | |
364 } | |
365 | |
366 p = ngx_palloc(cf->pool, size); | |
367 if (p == NULL) { | |
368 return NGX_CONF_ERROR; | |
369 } | |
370 | |
371 conf->pop3_capability.len = size; | |
372 conf->pop3_capability.data = p; | |
373 | |
374 p = ngx_cpymem(p, "+OK Capability list follows" CRLF, | |
375 sizeof("+OK Capability list follows" CRLF) - 1); | |
376 | |
377 for (i = 0; i < conf->pop3_capabilities.nelts; i++) { | |
378 p = ngx_cpymem(p, c[i].data, c[i].len); | |
379 *p++ = CR; *p++ = LF; | |
380 } | |
381 | |
382 if (conf->pop3_auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED) { | |
383 p = ngx_cpymem(p, "SASL LOGIN PLAIN CRAM-MD5" CRLF, | |
384 sizeof("SASL LOGIN PLAIN CRAM-MD5" CRLF) - 1); | |
385 | |
386 } else { | |
387 p = ngx_cpymem(p, "SASL LOGIN PLAIN" CRLF, | |
388 sizeof("SASL LOGIN PLAIN" CRLF) - 1); | |
389 } | |
390 | |
391 *p++ = '.'; *p++ = CR; *p = LF; | |
392 | |
393 | |
394 size += sizeof("STLS" CRLF) - 1; | |
395 | |
396 p = ngx_palloc(cf->pool, size); | |
397 if (p == NULL) { | |
398 return NGX_CONF_ERROR; | |
399 } | |
400 | |
401 conf->pop3_starttls_capability.len = size; | |
402 conf->pop3_starttls_capability.data = p; | |
403 | |
404 p = ngx_cpymem(p, conf->pop3_capability.data, | |
405 conf->pop3_capability.len - (sizeof("." CRLF) - 1)); | |
406 | |
407 p = ngx_cpymem(p, "STLS" CRLF, sizeof("STLS" CRLF) - 1); | |
408 *p++ = '.'; *p++ = CR; *p = LF; | |
409 | |
410 | |
411 if (conf->pop3_auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED) { | |
412 conf->pop3_auth_capability = ngx_pop3_auth_cram_md5_capability; | |
413 | |
414 } else { | |
415 conf->pop3_auth_capability = ngx_pop3_auth_plain_capability; | |
416 } | |
417 | |
418 | |
419 p = ngx_palloc(cf->pool, stls_only_size); | |
420 if (p == NULL) { | |
421 return NGX_CONF_ERROR; | |
422 } | |
423 | |
424 conf->pop3_starttls_only_capability.len = stls_only_size; | |
425 conf->pop3_starttls_only_capability.data = p; | |
426 | |
427 p = ngx_cpymem(p, "+OK Capability list follows" CRLF, | |
428 sizeof("+OK Capability list follows" CRLF) - 1); | |
429 | |
430 for (i = 0; i < conf->pop3_capabilities.nelts; i++) { | |
431 if (ngx_strcasecmp(c[i].data, (u_char *) "USER") == 0) { | |
432 continue; | |
433 } | |
434 | |
435 p = ngx_cpymem(p, c[i].data, c[i].len); | |
436 *p++ = CR; *p++ = LF; | |
437 } | |
438 | |
439 p = ngx_cpymem(p, "STLS" CRLF, sizeof("STLS" CRLF) - 1); | |
440 *p++ = '.'; *p++ = CR; *p = LF; | |
441 | |
442 | |
443 if (conf->imap_capabilities.nelts == 0) { | |
444 conf->imap_capabilities = prev->imap_capabilities; | |
445 } | |
446 | |
447 if (conf->imap_capabilities.nelts == 0) { | |
448 | |
449 for (d = ngx_imap_default_capabilities; d->len; d++) { | |
450 c = ngx_array_push(&conf->imap_capabilities); | |
451 if (c == NULL) { | |
452 return NGX_CONF_ERROR; | |
453 } | |
454 | |
455 *c = *d; | |
456 } | |
457 } | |
458 | |
459 size = sizeof("* CAPABILITY" CRLF) - 1; | |
460 | |
461 c = conf->imap_capabilities.elts; | |
462 for (i = 0; i < conf->imap_capabilities.nelts; i++) { | |
463 size += 1 + c[i].len; | |
464 } | |
465 | |
466 p = ngx_palloc(cf->pool, size); | |
467 if (p == NULL) { | |
468 return NGX_CONF_ERROR; | |
469 } | |
470 | |
471 conf->imap_capability.len = size; | |
472 conf->imap_capability.data = p; | |
473 | |
474 p = ngx_cpymem(p, "* CAPABILITY", sizeof("* CAPABILITY") - 1); | |
475 | |
476 for (i = 0; i < conf->imap_capabilities.nelts; i++) { | |
477 *p++ = ' '; | |
478 p = ngx_cpymem(p, c[i].data, c[i].len); | |
479 } | |
480 | |
481 *p++ = CR; *p = LF; | |
482 | |
483 | |
484 size += sizeof(" STARTTLS") - 1; | |
485 | |
486 p = ngx_palloc(cf->pool, size); | |
487 if (p == NULL) { | |
488 return NGX_CONF_ERROR; | |
489 } | |
490 | |
491 conf->imap_starttls_capability.len = size; | |
492 conf->imap_starttls_capability.data = p; | |
493 | |
494 p = ngx_cpymem(p, conf->imap_capability.data, | |
495 conf->imap_capability.len - (sizeof(CRLF) - 1)); | |
496 p = ngx_cpymem(p, " STARTTLS", sizeof(" STARTTLS") - 1); | |
497 *p++ = CR; *p = LF; | |
498 | |
499 | |
500 size += sizeof(" LOGINDISABLED") - 1; | |
501 | |
502 p = ngx_palloc(cf->pool, size); | |
503 if (p == NULL) { | |
504 return NGX_CONF_ERROR; | |
505 } | |
506 | |
507 conf->imap_starttls_only_capability.len = size; | |
508 conf->imap_starttls_only_capability.data = p; | |
509 | |
510 p = ngx_cpymem(p, conf->imap_starttls_capability.data, | |
511 conf->imap_starttls_capability.len - (sizeof(CRLF) - 1)); | |
512 p = ngx_cpymem(p, " LOGINDISABLED", sizeof(" LOGINDISABLED") - 1); | |
513 *p++ = CR; *p = LF; | |
514 | |
515 | |
516 size = sizeof("220 ESMTP ready" CRLF) - 1 + conf->server_name.len; | |
517 | |
518 p = ngx_palloc(cf->pool, size); | |
519 if (p == NULL) { | |
520 return NGX_CONF_ERROR; | |
521 } | |
522 | |
523 conf->smtp_greeting.len = size; | |
524 conf->smtp_greeting.data = p; | |
525 | |
526 *p++ = '2'; *p++ = '2'; *p++ = '0'; *p++ = ' '; | |
527 p = ngx_cpymem(p, conf->server_name.data, conf->server_name.len); | |
528 ngx_memcpy(p, " ESMTP ready" CRLF, sizeof(" ESMTP ready" CRLF) - 1); | |
529 | |
530 | |
531 size = sizeof("250 " CRLF) - 1 + conf->server_name.len; | |
532 | |
533 p = ngx_palloc(cf->pool, size); | |
534 if (p == NULL) { | |
535 return NGX_CONF_ERROR; | |
536 } | |
537 | |
538 conf->smtp_server_name.len = size; | |
539 conf->smtp_server_name.data = p; | |
540 | |
541 *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = ' '; | |
542 p = ngx_cpymem(p, conf->server_name.data, conf->server_name.len); | |
543 *p++ = CR; *p = LF; | |
544 | |
545 | |
546 if (conf->smtp_capabilities.nelts == 0) { | |
547 conf->smtp_capabilities = prev->smtp_capabilities; | |
548 } | |
549 | |
550 size = sizeof("250-") - 1 + conf->server_name.len + sizeof(CRLF) - 1 | |
551 + sizeof("250 AUTH") - 1 + sizeof(CRLF) - 1; | |
552 | |
553 c = conf->smtp_capabilities.elts; | |
554 for (i = 0; i < conf->smtp_capabilities.nelts; i++) { | |
555 size += sizeof("250 ") - 1 + c[i].len + sizeof(CRLF) - 1; | |
556 } | |
557 | |
558 for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0; | |
559 m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED; | |
560 m <<= 1, i++) | |
561 { | |
562 if (m & conf->smtp_auth_methods) { | |
563 size += 1 + ngx_smtp_auth_methods_names[i].len; | |
564 } | |
565 } | |
566 | |
567 p = ngx_palloc(cf->pool, size); | |
568 if (p == NULL) { | |
569 return NGX_CONF_ERROR; | |
570 } | |
571 | |
572 conf->smtp_capability.len = size; | |
573 conf->smtp_capability.data = p; | |
574 | |
575 *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = '-'; | |
576 p = ngx_cpymem(p, conf->server_name.data, conf->server_name.len); | |
577 *p++ = CR; *p++ = LF; | |
578 | |
579 for (i = 0; i < conf->smtp_capabilities.nelts; i++) { | |
580 *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = '-'; | |
581 p = ngx_cpymem(p, c[i].data, c[i].len); | |
582 *p++ = CR; *p++ = LF; | |
583 } | |
584 | |
585 *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = ' '; | |
586 *p++ = 'A'; *p++ = 'U'; *p++ = 'T'; *p++ = 'H'; | |
587 | |
588 for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0; | |
589 m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED; | |
590 m <<= 1, i++) | |
591 { | |
592 if (m & conf->smtp_auth_methods) { | |
593 *p++ = ' '; | |
594 p = ngx_cpymem(p, ngx_smtp_auth_methods_names[i].data, | |
595 ngx_smtp_auth_methods_names[i].len); | |
596 } | |
597 } | |
598 | |
599 *p++ = CR; *p = LF; | |
600 | |
601 return NGX_CONF_OK; | |
602 } | |
603 | |
604 | |
605 static char * | |
606 ngx_mail_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
607 { | |
608 char *rv; | |
609 void *mconf; | |
610 ngx_uint_t m; | |
611 ngx_conf_t pcf; | |
612 ngx_mail_module_t *module; | |
613 ngx_mail_conf_ctx_t *ctx, *mail_ctx; | |
614 ngx_mail_core_srv_conf_t *cscf, **cscfp; | |
615 ngx_mail_core_main_conf_t *cmcf; | |
616 | |
617 | |
618 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_mail_conf_ctx_t)); | |
619 if (ctx == NULL) { | |
620 return NGX_CONF_ERROR; | |
621 } | |
622 | |
623 mail_ctx = cf->ctx; | |
624 ctx->main_conf = mail_ctx->main_conf; | |
625 | |
626 /* the server{}'s srv_conf */ | |
627 | |
628 ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_mail_max_module); | |
629 if (ctx->srv_conf == NULL) { | |
630 return NGX_CONF_ERROR; | |
631 } | |
632 | |
633 for (m = 0; ngx_modules[m]; m++) { | |
634 if (ngx_modules[m]->type != NGX_MAIL_MODULE) { | |
635 continue; | |
636 } | |
637 | |
638 module = ngx_modules[m]->ctx; | |
639 | |
640 if (module->create_srv_conf) { | |
641 mconf = module->create_srv_conf(cf); | |
642 if (mconf == NULL) { | |
643 return NGX_CONF_ERROR; | |
644 } | |
645 | |
646 ctx->srv_conf[ngx_modules[m]->ctx_index] = mconf; | |
647 } | |
648 } | |
649 | |
650 /* the server configuration context */ | |
651 | |
652 cscf = ctx->srv_conf[ngx_mail_core_module.ctx_index]; | |
653 cscf->ctx = ctx; | |
654 | |
655 cmcf = ctx->main_conf[ngx_mail_core_module.ctx_index]; | |
656 | |
657 cscfp = ngx_array_push(&cmcf->servers); | |
658 if (cscfp == NULL) { | |
659 return NGX_CONF_ERROR; | |
660 } | |
661 | |
662 *cscfp = cscf; | |
663 | |
664 | |
665 /* parse inside server{} */ | |
666 | |
667 pcf = *cf; | |
668 cf->ctx = ctx; | |
669 cf->cmd_type = NGX_MAIL_SRV_CONF; | |
670 | |
671 rv = ngx_conf_parse(cf, NULL); | |
672 | |
673 *cf = pcf; | |
674 | |
675 return rv; | |
676 } | |
677 | |
678 | |
679 /* AF_INET only */ | |
680 | |
681 static char * | |
682 ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
683 { | |
684 ngx_str_t *value; | |
685 ngx_url_t u; | |
686 ngx_uint_t i; | |
687 ngx_mail_listen_t *imls; | |
688 ngx_mail_core_main_conf_t *cmcf; | |
689 | |
690 value = cf->args->elts; | |
691 | |
692 ngx_memzero(&u, sizeof(ngx_url_t)); | |
693 | |
694 u.url = value[1]; | |
695 u.listen = 1; | |
696 | |
697 if (ngx_parse_url(cf, &u) != NGX_OK) { | |
698 if (u.err) { | |
699 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
700 "%s in \"%V\" of the \"listen\" directive", | |
701 u.err, &u.url); | |
702 } | |
703 | |
704 return NGX_CONF_ERROR; | |
705 } | |
706 | |
707 cmcf = ngx_mail_conf_get_module_main_conf(cf, ngx_mail_core_module); | |
708 | |
709 imls = cmcf->listen.elts; | |
710 | |
711 for (i = 0; i < cmcf->listen.nelts; i++) { | |
712 | |
713 if (imls[i].addr != u.addr.in_addr || imls[i].port != u.port) { | |
714 continue; | |
715 } | |
716 | |
717 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
718 "duplicate \"%V\" address and port pair", &u.url); | |
719 return NGX_CONF_ERROR; | |
720 } | |
721 | |
722 imls = ngx_array_push(&cmcf->listen); | |
723 if (imls == NULL) { | |
724 return NGX_CONF_ERROR; | |
725 } | |
726 | |
727 ngx_memzero(imls, sizeof(ngx_mail_listen_t)); | |
728 | |
729 imls->addr = u.addr.in_addr; | |
730 imls->port = u.port; | |
731 imls->family = AF_INET; | |
732 imls->ctx = cf->ctx; | |
733 | |
734 if (cf->args->nelts == 2) { | |
735 return NGX_CONF_OK; | |
736 } | |
737 | |
738 if (ngx_strcmp(value[2].data, "bind") == 0) { | |
739 imls->bind = 1; | |
740 return NGX_CONF_OK; | |
741 } | |
742 | |
743 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
744 "the invalid \"%V\" parameter", &value[2]); | |
745 return NGX_CONF_ERROR; | |
746 } | |
747 | |
748 | |
749 static char * | |
750 ngx_mail_core_capability(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
751 { | |
752 char *p = conf; | |
753 | |
754 ngx_str_t *c, *value; | |
755 ngx_uint_t i; | |
756 ngx_array_t *a; | |
757 | |
758 a = (ngx_array_t *) (p + cmd->offset); | |
759 | |
760 value = cf->args->elts; | |
761 | |
762 for (i = 1; i < cf->args->nelts; i++) { | |
763 c = ngx_array_push(a); | |
764 if (c == NULL) { | |
765 return NGX_CONF_ERROR; | |
766 } | |
767 | |
768 *c = value[i]; | |
769 } | |
770 | |
771 return NGX_CONF_OK; | |
772 } |