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