3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
8 #include <ngx_config.h>
10 #include <ngx_event.h>
12 #include <ngx_mail_smtp_module.h>
15 static void *ngx_mail_smtp_create_srv_conf(ngx_conf_t
*cf
);
16 static char *ngx_mail_smtp_merge_srv_conf(ngx_conf_t
*cf
, void *parent
,
20 static ngx_conf_bitmask_t ngx_mail_smtp_auth_methods
[] = {
21 { ngx_string("plain"), NGX_MAIL_AUTH_PLAIN_ENABLED
},
22 { ngx_string("login"), NGX_MAIL_AUTH_LOGIN_ENABLED
},
23 { ngx_string("cram-md5"), NGX_MAIL_AUTH_CRAM_MD5_ENABLED
},
24 { ngx_string("none"), NGX_MAIL_AUTH_NONE_ENABLED
},
25 { ngx_null_string
, 0 }
29 static ngx_str_t ngx_mail_smtp_auth_methods_names
[] = {
32 ngx_null_string
, /* APOP */
33 ngx_string("CRAM-MD5"),
34 ngx_null_string
/* NONE */
38 static ngx_mail_protocol_t ngx_mail_smtp_protocol
= {
41 NGX_MAIL_SMTP_PROTOCOL
,
43 ngx_mail_smtp_init_session
,
44 ngx_mail_smtp_init_protocol
,
45 ngx_mail_smtp_parse_command
,
46 ngx_mail_smtp_auth_state
,
48 ngx_string("451 4.3.2 Internal server error" CRLF
)
52 static ngx_command_t ngx_mail_smtp_commands
[] = {
54 { ngx_string("smtp_client_buffer"),
55 NGX_MAIL_MAIN_CONF
|NGX_MAIL_SRV_CONF
|NGX_CONF_TAKE1
,
56 ngx_conf_set_size_slot
,
57 NGX_MAIL_SRV_CONF_OFFSET
,
58 offsetof(ngx_mail_smtp_srv_conf_t
, client_buffer_size
),
61 { ngx_string("smtp_greeting_delay"),
62 NGX_MAIL_MAIN_CONF
|NGX_MAIL_SRV_CONF
|NGX_CONF_TAKE1
,
63 ngx_conf_set_msec_slot
,
64 NGX_MAIL_SRV_CONF_OFFSET
,
65 offsetof(ngx_mail_smtp_srv_conf_t
, greeting_delay
),
68 { ngx_string("smtp_capabilities"),
69 NGX_MAIL_MAIN_CONF
|NGX_MAIL_SRV_CONF
|NGX_CONF_1MORE
,
70 ngx_mail_capabilities
,
71 NGX_MAIL_SRV_CONF_OFFSET
,
72 offsetof(ngx_mail_smtp_srv_conf_t
, capabilities
),
75 { ngx_string("smtp_auth"),
76 NGX_MAIL_MAIN_CONF
|NGX_MAIL_SRV_CONF
|NGX_CONF_1MORE
,
77 ngx_conf_set_bitmask_slot
,
78 NGX_MAIL_SRV_CONF_OFFSET
,
79 offsetof(ngx_mail_smtp_srv_conf_t
, auth_methods
),
80 &ngx_mail_smtp_auth_methods
},
86 static ngx_mail_module_t ngx_mail_smtp_module_ctx
= {
87 &ngx_mail_smtp_protocol
, /* protocol */
89 NULL
, /* create main configuration */
90 NULL
, /* init main configuration */
92 ngx_mail_smtp_create_srv_conf
, /* create server configuration */
93 ngx_mail_smtp_merge_srv_conf
/* merge server configuration */
97 ngx_module_t ngx_mail_smtp_module
= {
99 &ngx_mail_smtp_module_ctx
, /* module context */
100 ngx_mail_smtp_commands
, /* module directives */
101 NGX_MAIL_MODULE
, /* module type */
102 NULL
, /* init master */
103 NULL
, /* init module */
104 NULL
, /* init process */
105 NULL
, /* init thread */
106 NULL
, /* exit thread */
107 NULL
, /* exit process */
108 NULL
, /* exit master */
109 NGX_MODULE_V1_PADDING
114 ngx_mail_smtp_create_srv_conf(ngx_conf_t
*cf
)
116 ngx_mail_smtp_srv_conf_t
*sscf
;
118 sscf
= ngx_pcalloc(cf
->pool
, sizeof(ngx_mail_smtp_srv_conf_t
));
123 sscf
->client_buffer_size
= NGX_CONF_UNSET_SIZE
;
124 sscf
->greeting_delay
= NGX_CONF_UNSET_MSEC
;
126 if (ngx_array_init(&sscf
->capabilities
, cf
->pool
, 4, sizeof(ngx_str_t
))
137 ngx_mail_smtp_merge_srv_conf(ngx_conf_t
*cf
, void *parent
, void *child
)
139 ngx_mail_smtp_srv_conf_t
*prev
= parent
;
140 ngx_mail_smtp_srv_conf_t
*conf
= child
;
142 u_char
*p
, *auth
, *last
;
145 ngx_uint_t i
, m
, auth_enabled
;
146 ngx_mail_core_srv_conf_t
*cscf
;
148 ngx_conf_merge_size_value(conf
->client_buffer_size
,
149 prev
->client_buffer_size
,
150 (size_t) ngx_pagesize
);
152 ngx_conf_merge_msec_value(conf
->greeting_delay
,
153 prev
->greeting_delay
, 0);
155 ngx_conf_merge_bitmask_value(conf
->auth_methods
,
157 (NGX_CONF_BITMASK_SET
158 |NGX_MAIL_AUTH_PLAIN_ENABLED
159 |NGX_MAIL_AUTH_LOGIN_ENABLED
));
162 cscf
= ngx_mail_conf_get_module_srv_conf(cf
, ngx_mail_core_module
);
164 size
= sizeof("220 ESMTP ready" CRLF
) - 1 + cscf
->server_name
.len
;
166 p
= ngx_pnalloc(cf
->pool
, size
);
168 return NGX_CONF_ERROR
;
171 conf
->greeting
.len
= size
;
172 conf
->greeting
.data
= p
;
174 *p
++ = '2'; *p
++ = '2'; *p
++ = '0'; *p
++ = ' ';
175 p
= ngx_cpymem(p
, cscf
->server_name
.data
, cscf
->server_name
.len
);
176 ngx_memcpy(p
, " ESMTP ready" CRLF
, sizeof(" ESMTP ready" CRLF
) - 1);
179 size
= sizeof("250 " CRLF
) - 1 + cscf
->server_name
.len
;
181 p
= ngx_pnalloc(cf
->pool
, size
);
183 return NGX_CONF_ERROR
;
186 conf
->server_name
.len
= size
;
187 conf
->server_name
.data
= p
;
189 *p
++ = '2'; *p
++ = '5'; *p
++ = '0'; *p
++ = ' ';
190 p
= ngx_cpymem(p
, cscf
->server_name
.data
, cscf
->server_name
.len
);
194 if (conf
->capabilities
.nelts
== 0) {
195 conf
->capabilities
= prev
->capabilities
;
198 size
= sizeof("250-") - 1 + cscf
->server_name
.len
+ sizeof(CRLF
) - 1;
200 c
= conf
->capabilities
.elts
;
201 for (i
= 0; i
< conf
->capabilities
.nelts
; i
++) {
202 size
+= sizeof("250 ") - 1 + c
[i
].len
+ sizeof(CRLF
) - 1;
207 for (m
= NGX_MAIL_AUTH_PLAIN_ENABLED
, i
= 0;
208 m
<= NGX_MAIL_AUTH_CRAM_MD5_ENABLED
;
211 if (m
& conf
->auth_methods
) {
212 size
+= 1 + ngx_mail_smtp_auth_methods_names
[i
].len
;
218 size
+= sizeof("250 AUTH") - 1 + sizeof(CRLF
) - 1;
221 p
= ngx_pnalloc(cf
->pool
, size
);
223 return NGX_CONF_ERROR
;
226 conf
->capability
.len
= size
;
227 conf
->capability
.data
= p
;
231 *p
++ = '2'; *p
++ = '5'; *p
++ = '0'; *p
++ = '-';
232 p
= ngx_cpymem(p
, cscf
->server_name
.data
, cscf
->server_name
.len
);
233 *p
++ = CR
; *p
++ = LF
;
235 for (i
= 0; i
< conf
->capabilities
.nelts
; i
++) {
237 *p
++ = '2'; *p
++ = '5'; *p
++ = '0'; *p
++ = '-';
238 p
= ngx_cpymem(p
, c
[i
].data
, c
[i
].len
);
239 *p
++ = CR
; *p
++ = LF
;
247 *p
++ = '2'; *p
++ = '5'; *p
++ = '0'; *p
++ = ' ';
248 *p
++ = 'A'; *p
++ = 'U'; *p
++ = 'T'; *p
++ = 'H';
250 for (m
= NGX_MAIL_AUTH_PLAIN_ENABLED
, i
= 0;
251 m
<= NGX_MAIL_AUTH_CRAM_MD5_ENABLED
;
254 if (m
& conf
->auth_methods
) {
256 p
= ngx_cpymem(p
, ngx_mail_smtp_auth_methods_names
[i
].data
,
257 ngx_mail_smtp_auth_methods_names
[i
].len
);
267 size
+= sizeof("250 STARTTLS" CRLF
) - 1;
269 p
= ngx_pnalloc(cf
->pool
, size
);
271 return NGX_CONF_ERROR
;
274 conf
->starttls_capability
.len
= size
;
275 conf
->starttls_capability
.data
= p
;
277 p
= ngx_cpymem(p
, conf
->capability
.data
, conf
->capability
.len
);
279 p
= ngx_cpymem(p
, "250 STARTTLS" CRLF
, sizeof("250 STARTTLS" CRLF
) - 1);
282 p
= conf
->starttls_capability
.data
283 + (last
- conf
->capability
.data
) + 3;
286 size
= (auth
- conf
->capability
.data
)
287 + sizeof("250 STARTTLS" CRLF
) - 1;
289 p
= ngx_pnalloc(cf
->pool
, size
);
291 return NGX_CONF_ERROR
;
294 conf
->starttls_only_capability
.len
= size
;
295 conf
->starttls_only_capability
.data
= p
;
297 p
= ngx_cpymem(p
, conf
->capability
.data
, auth
- conf
->capability
.data
);
299 ngx_memcpy(p
, "250 STARTTLS" CRLF
, sizeof("250 STARTTLS" CRLF
) - 1);
302 p
= conf
->starttls_only_capability
.data
303 + (last
- conf
->capability
.data
) + 3;