Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_mail_smtp_module.c
Go to the documentation of this file.
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) Nginx, Inc.
5  */
6 
7 
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_event.h>
11 #include <ngx_mail.h>
12 #include <ngx_mail_smtp_module.h>
13 
14 
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,
17  void *child);
18 
19 
20 static ngx_conf_bitmask_t ngx_mail_smtp_auth_methods[] = {
25  { ngx_null_string, 0 }
26 };
27 
28 
29 static ngx_str_t ngx_mail_smtp_auth_methods_names[] = {
30  ngx_string("PLAIN"),
31  ngx_string("LOGIN"),
32  ngx_null_string, /* APOP */
33  ngx_string("CRAM-MD5"),
34  ngx_null_string /* NONE */
35 };
36 
37 
38 static ngx_mail_protocol_t ngx_mail_smtp_protocol = {
39  ngx_string("smtp"),
40  { 25, 465, 587, 0 },
42 
47 
48  ngx_string("451 4.3.2 Internal server error" CRLF)
49 };
50 
51 
52 static ngx_command_t ngx_mail_smtp_commands[] = {
53 
54  { ngx_string("smtp_client_buffer"),
58  offsetof(ngx_mail_smtp_srv_conf_t, client_buffer_size),
59  NULL },
60 
61  { ngx_string("smtp_greeting_delay"),
65  offsetof(ngx_mail_smtp_srv_conf_t, greeting_delay),
66  NULL },
67 
68  { ngx_string("smtp_capabilities"),
72  offsetof(ngx_mail_smtp_srv_conf_t, capabilities),
73  NULL },
74 
75  { ngx_string("smtp_auth"),
79  offsetof(ngx_mail_smtp_srv_conf_t, auth_methods),
80  &ngx_mail_smtp_auth_methods },
81 
83 };
84 
85 
86 static ngx_mail_module_t ngx_mail_smtp_module_ctx = {
87  &ngx_mail_smtp_protocol, /* protocol */
88 
89  NULL, /* create main configuration */
90  NULL, /* init main configuration */
91 
92  ngx_mail_smtp_create_srv_conf, /* create server configuration */
93  ngx_mail_smtp_merge_srv_conf /* merge server configuration */
94 };
95 
96 
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 */
110 };
111 
112 
113 static void *
114 ngx_mail_smtp_create_srv_conf(ngx_conf_t *cf)
115 {
117 
118  sscf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_smtp_srv_conf_t));
119  if (sscf == NULL) {
120  return NULL;
121  }
122 
125 
126  if (ngx_array_init(&sscf->capabilities, cf->pool, 4, sizeof(ngx_str_t))
127  != NGX_OK)
128  {
129  return NULL;
130  }
131 
132  return sscf;
133 }
134 
135 
136 static char *
137 ngx_mail_smtp_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
138 {
139  ngx_mail_smtp_srv_conf_t *prev = parent;
140  ngx_mail_smtp_srv_conf_t *conf = child;
141 
142  u_char *p, *auth, *last;
143  size_t size;
144  ngx_str_t *c;
145  ngx_uint_t i, m, auth_enabled;
147 
149  prev->client_buffer_size,
150  (size_t) ngx_pagesize);
151 
153  prev->greeting_delay, 0);
154 
156  prev->auth_methods,
160 
161 
163 
164  size = sizeof("220 ESMTP ready" CRLF) - 1 + cscf->server_name.len;
165 
166  p = ngx_pnalloc(cf->pool, size);
167  if (p == NULL) {
168  return NGX_CONF_ERROR;
169  }
170 
171  conf->greeting.len = size;
172  conf->greeting.data = p;
173 
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);
177 
178 
179  size = sizeof("250 " CRLF) - 1 + cscf->server_name.len;
180 
181  p = ngx_pnalloc(cf->pool, size);
182  if (p == NULL) {
183  return NGX_CONF_ERROR;
184  }
185 
186  conf->server_name.len = size;
187  conf->server_name.data = p;
188 
189  *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = ' ';
190  p = ngx_cpymem(p, cscf->server_name.data, cscf->server_name.len);
191  *p++ = CR; *p = LF;
192 
193 
194  if (conf->capabilities.nelts == 0) {
195  conf->capabilities = prev->capabilities;
196  }
197 
198  size = sizeof("250-") - 1 + cscf->server_name.len + sizeof(CRLF) - 1;
199 
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;
203  }
204 
205  auth_enabled = 0;
206 
207  for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0;
209  m <<= 1, i++)
210  {
211  if (m & conf->auth_methods) {
212  size += 1 + ngx_mail_smtp_auth_methods_names[i].len;
213  auth_enabled = 1;
214  }
215  }
216 
217  if (auth_enabled) {
218  size += sizeof("250 AUTH") - 1 + sizeof(CRLF) - 1;
219  }
220 
221  p = ngx_pnalloc(cf->pool, size);
222  if (p == NULL) {
223  return NGX_CONF_ERROR;
224  }
225 
226  conf->capability.len = size;
227  conf->capability.data = p;
228 
229  last = p;
230 
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;
234 
235  for (i = 0; i < conf->capabilities.nelts; i++) {
236  last = p;
237  *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = '-';
238  p = ngx_cpymem(p, c[i].data, c[i].len);
239  *p++ = CR; *p++ = LF;
240  }
241 
242  auth = p;
243 
244  if (auth_enabled) {
245  last = p;
246 
247  *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = ' ';
248  *p++ = 'A'; *p++ = 'U'; *p++ = 'T'; *p++ = 'H';
249 
250  for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0;
252  m <<= 1, i++)
253  {
254  if (m & conf->auth_methods) {
255  *p++ = ' ';
256  p = ngx_cpymem(p, ngx_mail_smtp_auth_methods_names[i].data,
257  ngx_mail_smtp_auth_methods_names[i].len);
258  }
259  }
260 
261  *p++ = CR; *p = LF;
262 
263  } else {
264  last[3] = ' ';
265  }
266 
267  size += sizeof("250 STARTTLS" CRLF) - 1;
268 
269  p = ngx_pnalloc(cf->pool, size);
270  if (p == NULL) {
271  return NGX_CONF_ERROR;
272  }
273 
274  conf->starttls_capability.len = size;
275  conf->starttls_capability.data = p;
276 
277  p = ngx_cpymem(p, conf->capability.data, conf->capability.len);
278 
279  p = ngx_cpymem(p, "250 STARTTLS" CRLF, sizeof("250 STARTTLS" CRLF) - 1);
280  *p++ = CR; *p = LF;
281 
282  p = conf->starttls_capability.data
283  + (last - conf->capability.data) + 3;
284  *p = '-';
285 
286  size = (auth - conf->capability.data)
287  + sizeof("250 STARTTLS" CRLF) - 1;
288 
289  p = ngx_pnalloc(cf->pool, size);
290  if (p == NULL) {
291  return NGX_CONF_ERROR;
292  }
293 
294  conf->starttls_only_capability.len = size;
295  conf->starttls_only_capability.data = p;
296 
297  p = ngx_cpymem(p, conf->capability.data, auth - conf->capability.data);
298 
299  ngx_memcpy(p, "250 STARTTLS" CRLF, sizeof("250 STARTTLS" CRLF) - 1);
300 
301  if (last < auth) {
303  + (last - conf->capability.data) + 3;
304  *p = '-';
305  }
306 
307  return NGX_CONF_OK;
308 }