Mercurial > hg > nginx-mail
comparison src/mail/ngx_mail_core_module.c @ 400:f1e2fab7a46c
Mail: smtp proxy without authentication.
Activated by auth method "unauth" in smtp_auth directive.
Waits for MAIL FROM and first RCPT TO from client, asks auth_http for
backend with additional headers Auth-SMTP-Helo, Auth-SMTP-From,
Auth-SMTP-To, and establishes connection to backend.
Auth-SMTP-From/To currently contain full command (e.g. "mail from: <>"),
this may change in future.
The functionality was designed to take off load from real smtp servers.
Additionally it may be used to implement pop-before-smtp authentication
(but dont do it unless you really need it - use real auth instead).
Current bug-features:
- If only "unauth" method activated in config, other methods (e.g. plain,
login) not advertised but accepted. Make sure your auth server handles
this gracefully.
- If backend server returns error on MAIL FROM / RCPT TO command while
proxy tunnel setup, nginx will close connection to client with 4xx
error. One may use proxy_pass_error_message directive to pass original
error message to client.
- Syntax of MAIL FROM / RCPT TO commands from client isn't checked.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Sun, 22 Jul 2007 23:55:12 +0000 |
parents | f9e6413396d4 |
children | d4cac61d8e95 |
comparison
equal
deleted
inserted
replaced
399:137505db4246 | 400:f1e2fab7a46c |
---|---|
64 | 64 |
65 static ngx_conf_bitmask_t ngx_smtp_auth_methods[] = { | 65 static ngx_conf_bitmask_t ngx_smtp_auth_methods[] = { |
66 { ngx_string("plain"), NGX_MAIL_AUTH_PLAIN_ENABLED }, | 66 { ngx_string("plain"), NGX_MAIL_AUTH_PLAIN_ENABLED }, |
67 { ngx_string("login"), NGX_MAIL_AUTH_LOGIN_ENABLED }, | 67 { ngx_string("login"), NGX_MAIL_AUTH_LOGIN_ENABLED }, |
68 { ngx_string("cram-md5"), NGX_MAIL_AUTH_CRAM_MD5_ENABLED }, | 68 { ngx_string("cram-md5"), NGX_MAIL_AUTH_CRAM_MD5_ENABLED }, |
69 { ngx_string("unauth"), NGX_MAIL_AUTH_UNAUTH_ENABLED }, | |
69 { ngx_null_string, 0 } | 70 { ngx_null_string, 0 } |
70 }; | 71 }; |
71 | 72 |
72 | 73 |
73 static ngx_str_t ngx_imap_auth_methods_names[] = { | 74 static ngx_str_t ngx_imap_auth_methods_names[] = { |
74 ngx_string("AUTH=PLAIN"), | 75 ngx_string("AUTH=PLAIN"), |
75 ngx_string("AUTH=LOGIN"), | 76 ngx_string("AUTH=LOGIN"), |
76 ngx_null_string, /* APOP */ | 77 ngx_null_string, /* APOP */ |
77 ngx_string("AUTH=CRAM-MD5") | 78 ngx_string("AUTH=CRAM-MD5"), |
79 ngx_null_string /* UNAUTH */ | |
78 }; | 80 }; |
79 | 81 |
80 | 82 |
81 static ngx_str_t ngx_smtp_auth_methods_names[] = { | 83 static ngx_str_t ngx_smtp_auth_methods_names[] = { |
82 ngx_string("PLAIN"), | 84 ngx_string("PLAIN"), |
83 ngx_string("LOGIN"), | 85 ngx_string("LOGIN"), |
84 ngx_null_string, /* APOP */ | 86 ngx_null_string, /* APOP */ |
85 ngx_string("CRAM-MD5") | 87 ngx_string("CRAM-MD5"), |
88 ngx_null_string /* UNAUTH */ | |
86 }; | 89 }; |
87 | 90 |
88 | 91 |
89 static ngx_str_t ngx_pop3_auth_plain_capability = | 92 static ngx_str_t ngx_pop3_auth_plain_capability = |
90 ngx_string("+OK methods supported:" CRLF | 93 ngx_string("+OK methods supported:" CRLF |
299 ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) | 302 ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) |
300 { | 303 { |
301 ngx_mail_core_srv_conf_t *prev = parent; | 304 ngx_mail_core_srv_conf_t *prev = parent; |
302 ngx_mail_core_srv_conf_t *conf = child; | 305 ngx_mail_core_srv_conf_t *conf = child; |
303 | 306 |
304 u_char *p, *auth_p; | 307 u_char *p, *auth_p, *last_p; |
305 size_t size, stls_only_size; | 308 size_t size, stls_only_size; |
306 ngx_str_t *c, *d; | 309 ngx_str_t *c, *d; |
307 ngx_uint_t i, m; | 310 ngx_uint_t i, m, smtp_auth_enabled; |
308 | 311 |
309 ngx_conf_merge_size_value(conf->imap_client_buffer_size, | 312 ngx_conf_merge_size_value(conf->imap_client_buffer_size, |
310 prev->imap_client_buffer_size, | 313 prev->imap_client_buffer_size, |
311 (size_t) ngx_pagesize); | 314 (size_t) ngx_pagesize); |
312 ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000); | 315 ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000); |
597 | 600 |
598 if (conf->smtp_capabilities.nelts == 0) { | 601 if (conf->smtp_capabilities.nelts == 0) { |
599 conf->smtp_capabilities = prev->smtp_capabilities; | 602 conf->smtp_capabilities = prev->smtp_capabilities; |
600 } | 603 } |
601 | 604 |
602 size = sizeof("250-") - 1 + conf->server_name.len + sizeof(CRLF) - 1 | 605 size = sizeof("250-") - 1 + conf->server_name.len + sizeof(CRLF) - 1; |
603 + sizeof("250 AUTH") - 1 + sizeof(CRLF) - 1; | |
604 | 606 |
605 c = conf->smtp_capabilities.elts; | 607 c = conf->smtp_capabilities.elts; |
606 for (i = 0; i < conf->smtp_capabilities.nelts; i++) { | 608 for (i = 0; i < conf->smtp_capabilities.nelts; i++) { |
607 size += sizeof("250 ") - 1 + c[i].len + sizeof(CRLF) - 1; | 609 size += sizeof("250 ") - 1 + c[i].len + sizeof(CRLF) - 1; |
608 } | 610 } |
609 | 611 |
612 smtp_auth_enabled = 0; | |
610 for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0; | 613 for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0; |
611 m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED; | 614 m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED; |
612 m <<= 1, i++) | 615 m <<= 1, i++) |
613 { | 616 { |
614 if (m & conf->smtp_auth_methods) { | 617 if (m & conf->smtp_auth_methods) { |
615 size += 1 + ngx_smtp_auth_methods_names[i].len; | 618 size += 1 + ngx_smtp_auth_methods_names[i].len; |
616 } | 619 smtp_auth_enabled = 1; |
620 } | |
621 } | |
622 | |
623 if (smtp_auth_enabled) { | |
624 size += sizeof("250 AUTH") - 1 + sizeof(CRLF) - 1; | |
617 } | 625 } |
618 | 626 |
619 p = ngx_palloc(cf->pool, size); | 627 p = ngx_palloc(cf->pool, size); |
620 if (p == NULL) { | 628 if (p == NULL) { |
621 return NGX_CONF_ERROR; | 629 return NGX_CONF_ERROR; |
622 } | 630 } |
623 | 631 |
624 conf->smtp_capability.len = size; | 632 conf->smtp_capability.len = size; |
625 conf->smtp_capability.data = p; | 633 conf->smtp_capability.data = p; |
626 | 634 |
635 last_p = p; | |
627 *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = '-'; | 636 *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = '-'; |
628 p = ngx_cpymem(p, conf->server_name.data, conf->server_name.len); | 637 p = ngx_cpymem(p, conf->server_name.data, conf->server_name.len); |
629 *p++ = CR; *p++ = LF; | 638 *p++ = CR; *p++ = LF; |
630 | 639 |
631 for (i = 0; i < conf->smtp_capabilities.nelts; i++) { | 640 for (i = 0; i < conf->smtp_capabilities.nelts; i++) { |
641 last_p = p; | |
632 *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = '-'; | 642 *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = '-'; |
633 p = ngx_cpymem(p, c[i].data, c[i].len); | 643 p = ngx_cpymem(p, c[i].data, c[i].len); |
634 *p++ = CR; *p++ = LF; | 644 *p++ = CR; *p++ = LF; |
635 } | 645 } |
636 | 646 |
637 auth_p = p; | 647 auth_p = p; |
638 | 648 |
639 *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = ' '; | 649 if (smtp_auth_enabled) { |
640 *p++ = 'A'; *p++ = 'U'; *p++ = 'T'; *p++ = 'H'; | 650 last_p = p; |
641 | 651 |
642 for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0; | 652 *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = ' '; |
643 m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED; | 653 *p++ = 'A'; *p++ = 'U'; *p++ = 'T'; *p++ = 'H'; |
644 m <<= 1, i++) | 654 |
645 { | 655 for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0; |
646 if (m & conf->smtp_auth_methods) { | 656 m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED; |
647 *p++ = ' '; | 657 m <<= 1, i++) |
648 p = ngx_cpymem(p, ngx_smtp_auth_methods_names[i].data, | 658 { |
649 ngx_smtp_auth_methods_names[i].len); | 659 if (m & conf->smtp_auth_methods) { |
650 } | 660 *p++ = ' '; |
651 } | 661 p = ngx_cpymem(p, ngx_smtp_auth_methods_names[i].data, |
652 | 662 ngx_smtp_auth_methods_names[i].len); |
653 *p++ = CR; *p = LF; | 663 } |
664 } | |
665 | |
666 *p++ = CR; *p = LF; | |
667 | |
668 } else { | |
669 last_p[3] = ' '; | |
670 } | |
654 | 671 |
655 size += sizeof("250 STARTTLS" CRLF) - 1; | 672 size += sizeof("250 STARTTLS" CRLF) - 1; |
656 | 673 |
657 p = ngx_palloc(cf->pool, size); | 674 p = ngx_palloc(cf->pool, size); |
658 if (p == NULL) { | 675 if (p == NULL) { |
667 | 684 |
668 p = ngx_cpymem(p, "250 STARTTLS" CRLF, sizeof("250 STARTTLS" CRLF) - 1); | 685 p = ngx_cpymem(p, "250 STARTTLS" CRLF, sizeof("250 STARTTLS" CRLF) - 1); |
669 *p++ = CR; *p = LF; | 686 *p++ = CR; *p = LF; |
670 | 687 |
671 p = conf->smtp_starttls_capability.data | 688 p = conf->smtp_starttls_capability.data |
672 + (auth_p - conf->smtp_capability.data) + 3; | 689 + (last_p - conf->smtp_capability.data) + 3; |
673 *p = '-'; | 690 *p = '-'; |
674 | 691 |
675 size = (auth_p - conf->smtp_capability.data) | 692 size = (auth_p - conf->smtp_capability.data) |
676 + sizeof("250 STARTTLS" CRLF) - 1; | 693 + sizeof("250 STARTTLS" CRLF) - 1; |
677 | 694 |
685 | 702 |
686 p = ngx_cpymem(p, conf->smtp_capability.data, | 703 p = ngx_cpymem(p, conf->smtp_capability.data, |
687 auth_p - conf->smtp_capability.data); | 704 auth_p - conf->smtp_capability.data); |
688 | 705 |
689 p = ngx_cpymem(p, "250 STARTTLS" CRLF, sizeof("250 STARTTLS" CRLF) - 1); | 706 p = ngx_cpymem(p, "250 STARTTLS" CRLF, sizeof("250 STARTTLS" CRLF) - 1); |
707 | |
708 if (last_p < auth_p) { | |
709 p = conf->smtp_starttls_only_capability.data | |
710 + (last_p - conf->smtp_capability.data) + 3; | |
711 *p = '-'; | |
712 } | |
690 | 713 |
691 return NGX_CONF_OK; | 714 return NGX_CONF_OK; |
692 } | 715 } |
693 | 716 |
694 | 717 |