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