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_mail.h>
11 
12 
13 #define NGX_DEFAULT_CIPHERS     "HIGH:!aNULL:!MD5"
14 #define NGX_DEFAULT_ECDH_CURVE  "auto"
15 
16 
17 static void *ngx_mail_ssl_create_conf(ngx_conf_t *cf);
18 static char *ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child);
19 
20 static char *ngx_mail_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd,
21     void *conf);
22 static char *ngx_mail_ssl_starttls(ngx_conf_t *cf, ngx_command_t *cmd,
23     void *conf);
24 static char *ngx_mail_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
25     void *conf);
26 static char *ngx_mail_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
27     void *conf);
28 
29 static char *ngx_mail_ssl_conf_command_check(ngx_conf_t *cf, void *post,
30     void *data);
31 
32 
33 static ngx_conf_enum_t  ngx_mail_starttls_state[] = {
34     { ngx_string("off"), NGX_MAIL_STARTTLS_OFF },
35     { ngx_string("on"), NGX_MAIL_STARTTLS_ON },
36     { ngx_string("only"), NGX_MAIL_STARTTLS_ONLY },
37     { ngx_null_string, 0 }
38 };
39 
40 
41 
42 static ngx_conf_bitmask_t  ngx_mail_ssl_protocols[] = {
43     { ngx_string("SSLv2"), NGX_SSL_SSLv2 },
44     { ngx_string("SSLv3"), NGX_SSL_SSLv3 },
45     { ngx_string("TLSv1"), NGX_SSL_TLSv1 },
46     { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 },
47     { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
48     { ngx_string("TLSv1.3"), NGX_SSL_TLSv1_3 },
49     { ngx_null_string, 0 }
50 };
51 
52 
53 static ngx_conf_enum_t  ngx_mail_ssl_verify[] = {
54     { ngx_string("off"), 0 },
55     { ngx_string("on"), 1 },
56     { ngx_string("optional"), 2 },
57     { ngx_string("optional_no_ca"), 3 },
58     { ngx_null_string, 0 }
59 };
60 
61 
62 static ngx_conf_deprecated_t  ngx_mail_ssl_deprecated = {
63     ngx_conf_deprecated, "ssl", "listen ... ssl"
64 };
65 
66 
67 static ngx_conf_post_t  ngx_mail_ssl_conf_command_post =
68     { ngx_mail_ssl_conf_command_check };
69 
70 
71 static ngx_command_t  ngx_mail_ssl_commands[] = {
72 
73     { ngx_string("ssl"),
74       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG,
75       ngx_mail_ssl_enable,
76       NGX_MAIL_SRV_CONF_OFFSET,
77       offsetof(ngx_mail_ssl_conf_t, enable),
78       &ngx_mail_ssl_deprecated },
79 
80     { ngx_string("starttls"),
81       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
82       ngx_mail_ssl_starttls,
83       NGX_MAIL_SRV_CONF_OFFSET,
84       offsetof(ngx_mail_ssl_conf_t, starttls),
85       ngx_mail_starttls_state },
86 
87     { ngx_string("ssl_certificate"),
88       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
89       ngx_conf_set_str_array_slot,
90       NGX_MAIL_SRV_CONF_OFFSET,
91       offsetof(ngx_mail_ssl_conf_t, certificates),
92       NULL },
93 
94     { ngx_string("ssl_certificate_key"),
95       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
96       ngx_conf_set_str_array_slot,
97       NGX_MAIL_SRV_CONF_OFFSET,
98       offsetof(ngx_mail_ssl_conf_t, certificate_keys),
99       NULL },
100 
101     { ngx_string("ssl_password_file"),
102       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
103       ngx_mail_ssl_password_file,
104       NGX_MAIL_SRV_CONF_OFFSET,
105       0,
106       NULL },
107 
108     { ngx_string("ssl_dhparam"),
109       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
110       ngx_conf_set_str_slot,
111       NGX_MAIL_SRV_CONF_OFFSET,
112       offsetof(ngx_mail_ssl_conf_t, dhparam),
113       NULL },
114 
115     { ngx_string("ssl_ecdh_curve"),
116       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
117       ngx_conf_set_str_slot,
118       NGX_MAIL_SRV_CONF_OFFSET,
119       offsetof(ngx_mail_ssl_conf_t, ecdh_curve),
120       NULL },
121 
122     { ngx_string("ssl_protocols"),
123       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE,
124       ngx_conf_set_bitmask_slot,
125       NGX_MAIL_SRV_CONF_OFFSET,
126       offsetof(ngx_mail_ssl_conf_t, protocols),
127       &ngx_mail_ssl_protocols },
128 
129     { ngx_string("ssl_ciphers"),
130       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
131       ngx_conf_set_str_slot,
132       NGX_MAIL_SRV_CONF_OFFSET,
133       offsetof(ngx_mail_ssl_conf_t, ciphers),
134       NULL },
135 
136     { ngx_string("ssl_prefer_server_ciphers"),
137       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG,
138       ngx_conf_set_flag_slot,
139       NGX_MAIL_SRV_CONF_OFFSET,
140       offsetof(ngx_mail_ssl_conf_t, prefer_server_ciphers),
141       NULL },
142 
143     { ngx_string("ssl_session_cache"),
144       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE12,
145       ngx_mail_ssl_session_cache,
146       NGX_MAIL_SRV_CONF_OFFSET,
147       0,
148       NULL },
149 
150     { ngx_string("ssl_session_tickets"),
151       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG,
152       ngx_conf_set_flag_slot,
153       NGX_MAIL_SRV_CONF_OFFSET,
154       offsetof(ngx_mail_ssl_conf_t, session_tickets),
155       NULL },
156 
157     { ngx_string("ssl_session_ticket_key"),
158       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
159       ngx_conf_set_str_array_slot,
160       NGX_MAIL_SRV_CONF_OFFSET,
161       offsetof(ngx_mail_ssl_conf_t, session_ticket_keys),
162       NULL },
163 
164     { ngx_string("ssl_session_timeout"),
165       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
166       ngx_conf_set_sec_slot,
167       NGX_MAIL_SRV_CONF_OFFSET,
168       offsetof(ngx_mail_ssl_conf_t, session_timeout),
169       NULL },
170 
171     { ngx_string("ssl_verify_client"),
172       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
173       ngx_conf_set_enum_slot,
174       NGX_MAIL_SRV_CONF_OFFSET,
175       offsetof(ngx_mail_ssl_conf_t, verify),
176       &ngx_mail_ssl_verify },
177 
178     { ngx_string("ssl_verify_depth"),
179       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
180       ngx_conf_set_num_slot,
181       NGX_MAIL_SRV_CONF_OFFSET,
182       offsetof(ngx_mail_ssl_conf_t, verify_depth),
183       NULL },
184 
185     { ngx_string("ssl_client_certificate"),
186       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
187       ngx_conf_set_str_slot,
188       NGX_MAIL_SRV_CONF_OFFSET,
189       offsetof(ngx_mail_ssl_conf_t, client_certificate),
190       NULL },
191 
192     { ngx_string("ssl_trusted_certificate"),
193       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
194       ngx_conf_set_str_slot,
195       NGX_MAIL_SRV_CONF_OFFSET,
196       offsetof(ngx_mail_ssl_conf_t, trusted_certificate),
197       NULL },
198 
199     { ngx_string("ssl_crl"),
200       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
201       ngx_conf_set_str_slot,
202       NGX_MAIL_SRV_CONF_OFFSET,
203       offsetof(ngx_mail_ssl_conf_t, crl),
204       NULL },
205 
206     { ngx_string("ssl_conf_command"),
207       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE2,
208       ngx_conf_set_keyval_slot,
209       NGX_MAIL_SRV_CONF_OFFSET,
210       offsetof(ngx_mail_ssl_conf_t, conf_commands),
211       &ngx_mail_ssl_conf_command_post },
212 
213       ngx_null_command
214 };
215 
216 
217 static ngx_mail_module_t  ngx_mail_ssl_module_ctx = {
218     NULL,                                  /* protocol */
219 
220     NULL,                                  /* create main configuration */
221     NULL,                                  /* init main configuration */
222 
223     ngx_mail_ssl_create_conf,              /* create server configuration */
224     ngx_mail_ssl_merge_conf                /* merge server configuration */
225 };
226 
227 
228 ngx_module_t  ngx_mail_ssl_module = {
229     NGX_MODULE_V1,
230     &ngx_mail_ssl_module_ctx,              /* module context */
231     ngx_mail_ssl_commands,                 /* module directives */
232     NGX_MAIL_MODULE,                       /* module type */
233     NULL,                                  /* init master */
234     NULL,                                  /* init module */
235     NULL,                                  /* init process */
236     NULL,                                  /* init thread */
237     NULL,                                  /* exit thread */
238     NULL,                                  /* exit process */
239     NULL,                                  /* exit master */
240     NGX_MODULE_V1_PADDING
241 };
242 
243 
244 static ngx_str_t ngx_mail_ssl_sess_id_ctx = ngx_string("MAIL");
245 
246 
247 static void *
ngx_mail_ssl_create_conf(ngx_conf_t * cf)248 ngx_mail_ssl_create_conf(ngx_conf_t *cf)
249 {
250     ngx_mail_ssl_conf_t  *scf;
251 
252     scf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_ssl_conf_t));
253     if (scf == NULL) {
254         return NULL;
255     }
256 
257     /*
258      * set by ngx_pcalloc():
259      *
260      *     scf->listen = 0;
261      *     scf->protocols = 0;
262      *     scf->dhparam = { 0, NULL };
263      *     scf->ecdh_curve = { 0, NULL };
264      *     scf->client_certificate = { 0, NULL };
265      *     scf->trusted_certificate = { 0, NULL };
266      *     scf->crl = { 0, NULL };
267      *     scf->ciphers = { 0, NULL };
268      *     scf->shm_zone = NULL;
269      */
270 
271     scf->enable = NGX_CONF_UNSET;
272     scf->starttls = NGX_CONF_UNSET_UINT;
273     scf->certificates = NGX_CONF_UNSET_PTR;
274     scf->certificate_keys = NGX_CONF_UNSET_PTR;
275     scf->passwords = NGX_CONF_UNSET_PTR;
276     scf->conf_commands = NGX_CONF_UNSET_PTR;
277     scf->prefer_server_ciphers = NGX_CONF_UNSET;
278     scf->verify = NGX_CONF_UNSET_UINT;
279     scf->verify_depth = NGX_CONF_UNSET_UINT;
280     scf->builtin_session_cache = NGX_CONF_UNSET;
281     scf->session_timeout = NGX_CONF_UNSET;
282     scf->session_tickets = NGX_CONF_UNSET;
283     scf->session_ticket_keys = NGX_CONF_UNSET_PTR;
284 
285     return scf;
286 }
287 
288 
289 static char *
ngx_mail_ssl_merge_conf(ngx_conf_t * cf,void * parent,void * child)290 ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
291 {
292     ngx_mail_ssl_conf_t *prev = parent;
293     ngx_mail_ssl_conf_t *conf = child;
294 
295     char                *mode;
296     ngx_pool_cleanup_t  *cln;
297 
298     ngx_conf_merge_value(conf->enable, prev->enable, 0);
299     ngx_conf_merge_uint_value(conf->starttls, prev->starttls,
300                          NGX_MAIL_STARTTLS_OFF);
301 
302     ngx_conf_merge_value(conf->session_timeout,
303                          prev->session_timeout, 300);
304 
305     ngx_conf_merge_value(conf->prefer_server_ciphers,
306                          prev->prefer_server_ciphers, 0);
307 
308     ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
309                          (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1
310                           |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));
311 
312     ngx_conf_merge_uint_value(conf->verify, prev->verify, 0);
313     ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1);
314 
315     ngx_conf_merge_ptr_value(conf->certificates, prev->certificates, NULL);
316     ngx_conf_merge_ptr_value(conf->certificate_keys, prev->certificate_keys,
317                          NULL);
318 
319     ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL);
320 
321     ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, "");
322 
323     ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve,
324                          NGX_DEFAULT_ECDH_CURVE);
325 
326     ngx_conf_merge_str_value(conf->client_certificate,
327                          prev->client_certificate, "");
328     ngx_conf_merge_str_value(conf->trusted_certificate,
329                          prev->trusted_certificate, "");
330     ngx_conf_merge_str_value(conf->crl, prev->crl, "");
331 
332     ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS);
333 
334     ngx_conf_merge_ptr_value(conf->conf_commands, prev->conf_commands, NULL);
335 
336 
337     conf->ssl.log = cf->log;
338 
339     if (conf->listen) {
340         mode = "listen ... ssl";
341 
342     } else if (conf->enable) {
343         mode = "ssl";
344 
345     } else if (conf->starttls != NGX_MAIL_STARTTLS_OFF) {
346         mode = "starttls";
347 
348     } else {
349         return NGX_CONF_OK;
350     }
351 
352     if (conf->file == NULL) {
353         conf->file = prev->file;
354         conf->line = prev->line;
355     }
356 
357     if (conf->certificates == NULL) {
358         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
359                       "no \"ssl_certificate\" is defined for "
360                       "the \"%s\" directive in %s:%ui",
361                       mode, conf->file, conf->line);
362         return NGX_CONF_ERROR;
363     }
364 
365     if (conf->certificate_keys == NULL) {
366         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
367                       "no \"ssl_certificate_key\" is defined for "
368                       "the \"%s\" directive in %s:%ui",
369                       mode, conf->file, conf->line);
370         return NGX_CONF_ERROR;
371     }
372 
373     if (conf->certificate_keys->nelts < conf->certificates->nelts) {
374         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
375                       "no \"ssl_certificate_key\" is defined "
376                       "for certificate \"%V\" and "
377                       "the \"%s\" directive in %s:%ui",
378                       ((ngx_str_t *) conf->certificates->elts)
379                       + conf->certificates->nelts - 1,
380                       mode, conf->file, conf->line);
381         return NGX_CONF_ERROR;
382     }
383 
384     if (ngx_ssl_create(&conf->ssl, conf->protocols, NULL) != NGX_OK) {
385         return NGX_CONF_ERROR;
386     }
387 
388     cln = ngx_pool_cleanup_add(cf->pool, 0);
389     if (cln == NULL) {
390         ngx_ssl_cleanup_ctx(&conf->ssl);
391         return NGX_CONF_ERROR;
392     }
393 
394     cln->handler = ngx_ssl_cleanup_ctx;
395     cln->data = &conf->ssl;
396 
397     if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates,
398                              conf->certificate_keys, conf->passwords)
399         != NGX_OK)
400     {
401         return NGX_CONF_ERROR;
402     }
403 
404     if (conf->verify) {
405 
406         if (conf->client_certificate.len == 0 && conf->verify != 3) {
407             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
408                           "no ssl_client_certificate for ssl_verify_client");
409             return NGX_CONF_ERROR;
410         }
411 
412         if (ngx_ssl_client_certificate(cf, &conf->ssl,
413                                        &conf->client_certificate,
414                                        conf->verify_depth)
415             != NGX_OK)
416         {
417             return NGX_CONF_ERROR;
418         }
419 
420         if (ngx_ssl_trusted_certificate(cf, &conf->ssl,
421                                         &conf->trusted_certificate,
422                                         conf->verify_depth)
423             != NGX_OK)
424         {
425             return NGX_CONF_ERROR;
426         }
427 
428         if (ngx_ssl_crl(cf, &conf->ssl, &conf->crl) != NGX_OK) {
429             return NGX_CONF_ERROR;
430         }
431     }
432 
433     if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers,
434                         conf->prefer_server_ciphers)
435         != NGX_OK)
436     {
437         return NGX_CONF_ERROR;
438     }
439 
440     if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) {
441         return NGX_CONF_ERROR;
442     }
443 
444     if (ngx_ssl_ecdh_curve(cf, &conf->ssl, &conf->ecdh_curve) != NGX_OK) {
445         return NGX_CONF_ERROR;
446     }
447 
448     ngx_conf_merge_value(conf->builtin_session_cache,
449                          prev->builtin_session_cache, NGX_SSL_NONE_SCACHE);
450 
451     if (conf->shm_zone == NULL) {
452         conf->shm_zone = prev->shm_zone;
453     }
454 
455     if (ngx_ssl_session_cache(&conf->ssl, &ngx_mail_ssl_sess_id_ctx,
456                               conf->certificates, conf->builtin_session_cache,
457                               conf->shm_zone, conf->session_timeout)
458         != NGX_OK)
459     {
460         return NGX_CONF_ERROR;
461     }
462 
463     ngx_conf_merge_value(conf->session_tickets,
464                          prev->session_tickets, 1);
465 
466 #ifdef SSL_OP_NO_TICKET
467     if (!conf->session_tickets) {
468         SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_NO_TICKET);
469     }
470 #endif
471 
472     ngx_conf_merge_ptr_value(conf->session_ticket_keys,
473                          prev->session_ticket_keys, NULL);
474 
475     if (ngx_ssl_session_ticket_keys(cf, &conf->ssl, conf->session_ticket_keys)
476         != NGX_OK)
477     {
478         return NGX_CONF_ERROR;
479     }
480 
481     if (ngx_ssl_conf_commands(cf, &conf->ssl, conf->conf_commands) != NGX_OK) {
482         return NGX_CONF_ERROR;
483     }
484 
485     return NGX_CONF_OK;
486 }
487 
488 
489 static char *
ngx_mail_ssl_enable(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)490 ngx_mail_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
491 {
492     ngx_mail_ssl_conf_t  *scf = conf;
493 
494     char  *rv;
495 
496     rv = ngx_conf_set_flag_slot(cf, cmd, conf);
497 
498     if (rv != NGX_CONF_OK) {
499         return rv;
500     }
501 
502     if (scf->enable && (ngx_int_t) scf->starttls > NGX_MAIL_STARTTLS_OFF) {
503         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
504                            "\"starttls\" directive conflicts with \"ssl on\"");
505         return NGX_CONF_ERROR;
506     }
507 
508     if (!scf->listen) {
509         scf->file = cf->conf_file->file.name.data;
510         scf->line = cf->conf_file->line;
511     }
512 
513     return NGX_CONF_OK;
514 }
515 
516 
517 static char *
ngx_mail_ssl_starttls(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)518 ngx_mail_ssl_starttls(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
519 {
520     ngx_mail_ssl_conf_t  *scf = conf;
521 
522     char  *rv;
523 
524     rv = ngx_conf_set_enum_slot(cf, cmd, conf);
525 
526     if (rv != NGX_CONF_OK) {
527         return rv;
528     }
529 
530     if (scf->enable == 1 && (ngx_int_t) scf->starttls > NGX_MAIL_STARTTLS_OFF) {
531         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
532                            "\"ssl\" directive conflicts with \"starttls\"");
533         return NGX_CONF_ERROR;
534     }
535 
536     if (!scf->listen) {
537         scf->file = cf->conf_file->file.name.data;
538         scf->line = cf->conf_file->line;
539     }
540 
541     return NGX_CONF_OK;
542 }
543 
544 
545 static char *
ngx_mail_ssl_password_file(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)546 ngx_mail_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
547 {
548     ngx_mail_ssl_conf_t  *scf = conf;
549 
550     ngx_str_t  *value;
551 
552     if (scf->passwords != NGX_CONF_UNSET_PTR) {
553         return "is duplicate";
554     }
555 
556     value = cf->args->elts;
557 
558     scf->passwords = ngx_ssl_read_password_file(cf, &value[1]);
559 
560     if (scf->passwords == NULL) {
561         return NGX_CONF_ERROR;
562     }
563 
564     return NGX_CONF_OK;
565 }
566 
567 
568 static char *
ngx_mail_ssl_session_cache(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)569 ngx_mail_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
570 {
571     ngx_mail_ssl_conf_t  *scf = conf;
572 
573     size_t       len;
574     ngx_str_t   *value, name, size;
575     ngx_int_t    n;
576     ngx_uint_t   i, j;
577 
578     value = cf->args->elts;
579 
580     for (i = 1; i < cf->args->nelts; i++) {
581 
582         if (ngx_strcmp(value[i].data, "off") == 0) {
583             scf->builtin_session_cache = NGX_SSL_NO_SCACHE;
584             continue;
585         }
586 
587         if (ngx_strcmp(value[i].data, "none") == 0) {
588             scf->builtin_session_cache = NGX_SSL_NONE_SCACHE;
589             continue;
590         }
591 
592         if (ngx_strcmp(value[i].data, "builtin") == 0) {
593             scf->builtin_session_cache = NGX_SSL_DFLT_BUILTIN_SCACHE;
594             continue;
595         }
596 
597         if (value[i].len > sizeof("builtin:") - 1
598             && ngx_strncmp(value[i].data, "builtin:", sizeof("builtin:") - 1)
599                == 0)
600         {
601             n = ngx_atoi(value[i].data + sizeof("builtin:") - 1,
602                          value[i].len - (sizeof("builtin:") - 1));
603 
604             if (n == NGX_ERROR) {
605                 goto invalid;
606             }
607 
608             scf->builtin_session_cache = n;
609 
610             continue;
611         }
612 
613         if (value[i].len > sizeof("shared:") - 1
614             && ngx_strncmp(value[i].data, "shared:", sizeof("shared:") - 1)
615                == 0)
616         {
617             len = 0;
618 
619             for (j = sizeof("shared:") - 1; j < value[i].len; j++) {
620                 if (value[i].data[j] == ':') {
621                     break;
622                 }
623 
624                 len++;
625             }
626 
627             if (len == 0) {
628                 goto invalid;
629             }
630 
631             name.len = len;
632             name.data = value[i].data + sizeof("shared:") - 1;
633 
634             size.len = value[i].len - j - 1;
635             size.data = name.data + len + 1;
636 
637             n = ngx_parse_size(&size);
638 
639             if (n == NGX_ERROR) {
640                 goto invalid;
641             }
642 
643             if (n < (ngx_int_t) (8 * ngx_pagesize)) {
644                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
645                                    "session cache \"%V\" is too small",
646                                    &value[i]);
647 
648                 return NGX_CONF_ERROR;
649             }
650 
651             scf->shm_zone = ngx_shared_memory_add(cf, &name, n,
652                                                    &ngx_mail_ssl_module);
653             if (scf->shm_zone == NULL) {
654                 return NGX_CONF_ERROR;
655             }
656 
657             scf->shm_zone->init = ngx_ssl_session_cache_init;
658 
659             continue;
660         }
661 
662         goto invalid;
663     }
664 
665     if (scf->shm_zone && scf->builtin_session_cache == NGX_CONF_UNSET) {
666         scf->builtin_session_cache = NGX_SSL_NO_BUILTIN_SCACHE;
667     }
668 
669     return NGX_CONF_OK;
670 
671 invalid:
672 
673     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
674                        "invalid session cache \"%V\"", &value[i]);
675 
676     return NGX_CONF_ERROR;
677 }
678 
679 
680 static char *
ngx_mail_ssl_conf_command_check(ngx_conf_t * cf,void * post,void * data)681 ngx_mail_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
682 {
683 #ifndef SSL_CONF_FLAG_FILE
684     return "is not supported on this platform";
685 #else
686     return NGX_CONF_OK;
687 #endif
688 }
689