ngx_mail_ssl_module.c revision e18a033b
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
17static void *ngx_mail_ssl_create_conf(ngx_conf_t *cf);
18static char *ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child);
19
20static char *ngx_mail_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd,
21    void *conf);
22static char *ngx_mail_ssl_starttls(ngx_conf_t *cf, ngx_command_t *cmd,
23    void *conf);
24static char *ngx_mail_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
25    void *conf);
26static char *ngx_mail_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
27    void *conf);
28
29
30static 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
39static 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
49static 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
58static 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
197static 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
208ngx_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
224static ngx_str_t ngx_mail_ssl_sess_id_ctx = ngx_string("MAIL");
225
226
227static void *
228ngx_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
267static char *
268ngx_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
477static char *
478ngx_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
503static char *
504ngx_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
529static char *
530ngx_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
552static char *
553ngx_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
655invalid:
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}
662