src/mail/ngx_mail_ssl_module.c - nginx source code

Global variables defined

Functions defined

Macros defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_mail.h>


  8. #define NGX_DEFAULT_CIPHERS     "HIGH:!aNULL:!MD5"
  9. #define NGX_DEFAULT_ECDH_CURVE  "auto"


  10. #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
  11. static int ngx_mail_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn,
  12.     const unsigned char **out, unsigned char *outlen,
  13.     const unsigned char *in, unsigned int inlen, void *arg);
  14. #endif

  15. static void *ngx_mail_ssl_create_conf(ngx_conf_t *cf);
  16. static char *ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child);

  17. static char *ngx_mail_ssl_starttls(ngx_conf_t *cf, ngx_command_t *cmd,
  18.     void *conf);
  19. static char *ngx_mail_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
  20.     void *conf);
  21. static char *ngx_mail_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
  22.     void *conf);

  23. static char *ngx_mail_ssl_conf_command_check(ngx_conf_t *cf, void *post,
  24.     void *data);


  25. static ngx_conf_enum_t  ngx_mail_starttls_state[] = {
  26.     { ngx_string("off"), NGX_MAIL_STARTTLS_OFF },
  27.     { ngx_string("on"), NGX_MAIL_STARTTLS_ON },
  28.     { ngx_string("only"), NGX_MAIL_STARTTLS_ONLY },
  29.     { ngx_null_string, 0 }
  30. };



  31. static ngx_conf_bitmask_t  ngx_mail_ssl_protocols[] = {
  32.     { ngx_string("SSLv2"), NGX_SSL_SSLv2 },
  33.     { ngx_string("SSLv3"), NGX_SSL_SSLv3 },
  34.     { ngx_string("TLSv1"), NGX_SSL_TLSv1 },
  35.     { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 },
  36.     { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
  37.     { ngx_string("TLSv1.3"), NGX_SSL_TLSv1_3 },
  38.     { ngx_null_string, 0 }
  39. };


  40. static ngx_conf_enum_t  ngx_mail_ssl_verify[] = {
  41.     { ngx_string("off"), 0 },
  42.     { ngx_string("on"), 1 },
  43.     { ngx_string("optional"), 2 },
  44.     { ngx_string("optional_no_ca"), 3 },
  45.     { ngx_null_string, 0 }
  46. };


  47. static ngx_conf_post_t  ngx_mail_ssl_conf_command_post =
  48.     { ngx_mail_ssl_conf_command_check };


  49. static ngx_command_t  ngx_mail_ssl_commands[] = {

  50.     { ngx_string("starttls"),
  51.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
  52.       ngx_mail_ssl_starttls,
  53.       NGX_MAIL_SRV_CONF_OFFSET,
  54.       offsetof(ngx_mail_ssl_conf_t, starttls),
  55.       ngx_mail_starttls_state },

  56.     { ngx_string("ssl_certificate"),
  57.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
  58.       ngx_conf_set_str_array_slot,
  59.       NGX_MAIL_SRV_CONF_OFFSET,
  60.       offsetof(ngx_mail_ssl_conf_t, certificates),
  61.       NULL },

  62.     { ngx_string("ssl_certificate_key"),
  63.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
  64.       ngx_conf_set_str_array_slot,
  65.       NGX_MAIL_SRV_CONF_OFFSET,
  66.       offsetof(ngx_mail_ssl_conf_t, certificate_keys),
  67.       NULL },

  68.     { ngx_string("ssl_password_file"),
  69.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
  70.       ngx_mail_ssl_password_file,
  71.       NGX_MAIL_SRV_CONF_OFFSET,
  72.       0,
  73.       NULL },

  74.     { ngx_string("ssl_dhparam"),
  75.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
  76.       ngx_conf_set_str_slot,
  77.       NGX_MAIL_SRV_CONF_OFFSET,
  78.       offsetof(ngx_mail_ssl_conf_t, dhparam),
  79.       NULL },

  80.     { ngx_string("ssl_ecdh_curve"),
  81.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
  82.       ngx_conf_set_str_slot,
  83.       NGX_MAIL_SRV_CONF_OFFSET,
  84.       offsetof(ngx_mail_ssl_conf_t, ecdh_curve),
  85.       NULL },

  86.     { ngx_string("ssl_protocols"),
  87.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE,
  88.       ngx_conf_set_bitmask_slot,
  89.       NGX_MAIL_SRV_CONF_OFFSET,
  90.       offsetof(ngx_mail_ssl_conf_t, protocols),
  91.       &ngx_mail_ssl_protocols },

  92.     { ngx_string("ssl_ciphers"),
  93.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
  94.       ngx_conf_set_str_slot,
  95.       NGX_MAIL_SRV_CONF_OFFSET,
  96.       offsetof(ngx_mail_ssl_conf_t, ciphers),
  97.       NULL },

  98.     { ngx_string("ssl_prefer_server_ciphers"),
  99.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG,
  100.       ngx_conf_set_flag_slot,
  101.       NGX_MAIL_SRV_CONF_OFFSET,
  102.       offsetof(ngx_mail_ssl_conf_t, prefer_server_ciphers),
  103.       NULL },

  104.     { ngx_string("ssl_session_cache"),
  105.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE12,
  106.       ngx_mail_ssl_session_cache,
  107.       NGX_MAIL_SRV_CONF_OFFSET,
  108.       0,
  109.       NULL },

  110.     { ngx_string("ssl_session_tickets"),
  111.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG,
  112.       ngx_conf_set_flag_slot,
  113.       NGX_MAIL_SRV_CONF_OFFSET,
  114.       offsetof(ngx_mail_ssl_conf_t, session_tickets),
  115.       NULL },

  116.     { ngx_string("ssl_session_ticket_key"),
  117.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
  118.       ngx_conf_set_str_array_slot,
  119.       NGX_MAIL_SRV_CONF_OFFSET,
  120.       offsetof(ngx_mail_ssl_conf_t, session_ticket_keys),
  121.       NULL },

  122.     { ngx_string("ssl_session_timeout"),
  123.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
  124.       ngx_conf_set_sec_slot,
  125.       NGX_MAIL_SRV_CONF_OFFSET,
  126.       offsetof(ngx_mail_ssl_conf_t, session_timeout),
  127.       NULL },

  128.     { ngx_string("ssl_verify_client"),
  129.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
  130.       ngx_conf_set_enum_slot,
  131.       NGX_MAIL_SRV_CONF_OFFSET,
  132.       offsetof(ngx_mail_ssl_conf_t, verify),
  133.       &ngx_mail_ssl_verify },

  134.     { ngx_string("ssl_verify_depth"),
  135.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
  136.       ngx_conf_set_num_slot,
  137.       NGX_MAIL_SRV_CONF_OFFSET,
  138.       offsetof(ngx_mail_ssl_conf_t, verify_depth),
  139.       NULL },

  140.     { ngx_string("ssl_client_certificate"),
  141.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
  142.       ngx_conf_set_str_slot,
  143.       NGX_MAIL_SRV_CONF_OFFSET,
  144.       offsetof(ngx_mail_ssl_conf_t, client_certificate),
  145.       NULL },

  146.     { ngx_string("ssl_trusted_certificate"),
  147.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
  148.       ngx_conf_set_str_slot,
  149.       NGX_MAIL_SRV_CONF_OFFSET,
  150.       offsetof(ngx_mail_ssl_conf_t, trusted_certificate),
  151.       NULL },

  152.     { ngx_string("ssl_crl"),
  153.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
  154.       ngx_conf_set_str_slot,
  155.       NGX_MAIL_SRV_CONF_OFFSET,
  156.       offsetof(ngx_mail_ssl_conf_t, crl),
  157.       NULL },

  158.     { ngx_string("ssl_conf_command"),
  159.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE2,
  160.       ngx_conf_set_keyval_slot,
  161.       NGX_MAIL_SRV_CONF_OFFSET,
  162.       offsetof(ngx_mail_ssl_conf_t, conf_commands),
  163.       &ngx_mail_ssl_conf_command_post },

  164.       ngx_null_command
  165. };


  166. static ngx_mail_module_t  ngx_mail_ssl_module_ctx = {
  167.     NULL,                                  /* protocol */

  168.     NULL,                                  /* create main configuration */
  169.     NULL,                                  /* init main configuration */

  170.     ngx_mail_ssl_create_conf,              /* create server configuration */
  171.     ngx_mail_ssl_merge_conf                /* merge server configuration */
  172. };


  173. ngx_module_t  ngx_mail_ssl_module = {
  174.     NGX_MODULE_V1,
  175.     &ngx_mail_ssl_module_ctx,              /* module context */
  176.     ngx_mail_ssl_commands,                 /* module directives */
  177.     NGX_MAIL_MODULE,                       /* module type */
  178.     NULL,                                  /* init master */
  179.     NULL,                                  /* init module */
  180.     NULL,                                  /* init process */
  181.     NULL,                                  /* init thread */
  182.     NULL,                                  /* exit thread */
  183.     NULL,                                  /* exit process */
  184.     NULL,                                  /* exit master */
  185.     NGX_MODULE_V1_PADDING
  186. };


  187. static ngx_str_t ngx_mail_ssl_sess_id_ctx = ngx_string("MAIL");


  188. #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation

  189. static int
  190. ngx_mail_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out,
  191.     unsigned char *outlen, const unsigned char *in, unsigned int inlen,
  192.     void *arg)
  193. {
  194.     unsigned int               srvlen;
  195.     unsigned char             *srv;
  196.     ngx_connection_t          *c;
  197.     ngx_mail_session_t        *s;
  198.     ngx_mail_core_srv_conf_t  *cscf;
  199. #if (NGX_DEBUG)
  200.     unsigned int               i;
  201. #endif

  202.     c = ngx_ssl_get_connection(ssl_conn);
  203.     s = c->data;

  204. #if (NGX_DEBUG)
  205.     for (i = 0; i < inlen; i += in[i] + 1) {
  206.         ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0,
  207.                        "SSL ALPN supported by client: %*s",
  208.                        (size_t) in[i], &in[i + 1]);
  209.     }
  210. #endif

  211.     cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);

  212.     srv = cscf->protocol->alpn.data;
  213.     srvlen = cscf->protocol->alpn.len;

  214.     if (SSL_select_next_proto((unsigned char **) out, outlen, srv, srvlen,
  215.                               in, inlen)
  216.         != OPENSSL_NPN_NEGOTIATED)
  217.     {
  218.         return SSL_TLSEXT_ERR_ALERT_FATAL;
  219.     }

  220.     ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0,
  221.                    "SSL ALPN selected: %*s", (size_t) *outlen, *out);

  222.     return SSL_TLSEXT_ERR_OK;
  223. }

  224. #endif


  225. static void *
  226. ngx_mail_ssl_create_conf(ngx_conf_t *cf)
  227. {
  228.     ngx_mail_ssl_conf_t  *scf;

  229.     scf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_ssl_conf_t));
  230.     if (scf == NULL) {
  231.         return NULL;
  232.     }

  233.     /*
  234.      * set by ngx_pcalloc():
  235.      *
  236.      *     scf->listen = 0;
  237.      *     scf->protocols = 0;
  238.      *     scf->dhparam = { 0, NULL };
  239.      *     scf->ecdh_curve = { 0, NULL };
  240.      *     scf->client_certificate = { 0, NULL };
  241.      *     scf->trusted_certificate = { 0, NULL };
  242.      *     scf->crl = { 0, NULL };
  243.      *     scf->ciphers = { 0, NULL };
  244.      *     scf->shm_zone = NULL;
  245.      */

  246.     scf->starttls = NGX_CONF_UNSET_UINT;
  247.     scf->certificates = NGX_CONF_UNSET_PTR;
  248.     scf->certificate_keys = NGX_CONF_UNSET_PTR;
  249.     scf->passwords = NGX_CONF_UNSET_PTR;
  250.     scf->conf_commands = NGX_CONF_UNSET_PTR;
  251.     scf->prefer_server_ciphers = NGX_CONF_UNSET;
  252.     scf->verify = NGX_CONF_UNSET_UINT;
  253.     scf->verify_depth = NGX_CONF_UNSET_UINT;
  254.     scf->builtin_session_cache = NGX_CONF_UNSET;
  255.     scf->session_timeout = NGX_CONF_UNSET;
  256.     scf->session_tickets = NGX_CONF_UNSET;
  257.     scf->session_ticket_keys = NGX_CONF_UNSET_PTR;

  258.     return scf;
  259. }


  260. static char *
  261. ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
  262. {
  263.     ngx_mail_ssl_conf_t *prev = parent;
  264.     ngx_mail_ssl_conf_t *conf = child;

  265.     char                *mode;
  266.     ngx_pool_cleanup_t  *cln;

  267.     ngx_conf_merge_uint_value(conf->starttls, prev->starttls,
  268.                          NGX_MAIL_STARTTLS_OFF);

  269.     ngx_conf_merge_value(conf->session_timeout,
  270.                          prev->session_timeout, 300);

  271.     ngx_conf_merge_value(conf->prefer_server_ciphers,
  272.                          prev->prefer_server_ciphers, 0);

  273.     ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
  274.                          (NGX_CONF_BITMASK_SET|NGX_SSL_DEFAULT_PROTOCOLS));

  275.     ngx_conf_merge_uint_value(conf->verify, prev->verify, 0);
  276.     ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1);

  277.     ngx_conf_merge_ptr_value(conf->certificates, prev->certificates, NULL);
  278.     ngx_conf_merge_ptr_value(conf->certificate_keys, prev->certificate_keys,
  279.                          NULL);

  280.     ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL);

  281.     ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, "");

  282.     ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve,
  283.                          NGX_DEFAULT_ECDH_CURVE);

  284.     ngx_conf_merge_str_value(conf->client_certificate,
  285.                          prev->client_certificate, "");
  286.     ngx_conf_merge_str_value(conf->trusted_certificate,
  287.                          prev->trusted_certificate, "");
  288.     ngx_conf_merge_str_value(conf->crl, prev->crl, "");

  289.     ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS);

  290.     ngx_conf_merge_ptr_value(conf->conf_commands, prev->conf_commands, NULL);


  291.     conf->ssl.log = cf->log;

  292.     if (conf->listen) {
  293.         mode = "listen ... ssl";

  294.     } else if (conf->starttls != NGX_MAIL_STARTTLS_OFF) {
  295.         mode = "starttls";

  296.     } else {
  297.         return NGX_CONF_OK;
  298.     }

  299.     if (conf->file == NULL) {
  300.         conf->file = prev->file;
  301.         conf->line = prev->line;
  302.     }

  303.     if (conf->certificates == NULL) {
  304.         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
  305.                       "no \"ssl_certificate\" is defined for "
  306.                       "the \"%s\" directive in %s:%ui",
  307.                       mode, conf->file, conf->line);
  308.         return NGX_CONF_ERROR;
  309.     }

  310.     if (conf->certificate_keys == NULL) {
  311.         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
  312.                       "no \"ssl_certificate_key\" is defined for "
  313.                       "the \"%s\" directive in %s:%ui",
  314.                       mode, conf->file, conf->line);
  315.         return NGX_CONF_ERROR;
  316.     }

  317.     if (conf->certificate_keys->nelts < conf->certificates->nelts) {
  318.         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
  319.                       "no \"ssl_certificate_key\" is defined "
  320.                       "for certificate \"%V\" and "
  321.                       "the \"%s\" directive in %s:%ui",
  322.                       ((ngx_str_t *) conf->certificates->elts)
  323.                       + conf->certificates->nelts - 1,
  324.                       mode, conf->file, conf->line);
  325.         return NGX_CONF_ERROR;
  326.     }

  327.     if (ngx_ssl_create(&conf->ssl, conf->protocols, NULL) != NGX_OK) {
  328.         return NGX_CONF_ERROR;
  329.     }

  330.     cln = ngx_pool_cleanup_add(cf->pool, 0);
  331.     if (cln == NULL) {
  332.         ngx_ssl_cleanup_ctx(&conf->ssl);
  333.         return NGX_CONF_ERROR;
  334.     }

  335.     cln->handler = ngx_ssl_cleanup_ctx;
  336.     cln->data = &conf->ssl;

  337. #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
  338.     SSL_CTX_set_alpn_select_cb(conf->ssl.ctx, ngx_mail_ssl_alpn_select, NULL);
  339. #endif

  340.     if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers,
  341.                         conf->prefer_server_ciphers)
  342.         != NGX_OK)
  343.     {
  344.         return NGX_CONF_ERROR;
  345.     }

  346.     if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates,
  347.                              conf->certificate_keys, conf->passwords)
  348.         != NGX_OK)
  349.     {
  350.         return NGX_CONF_ERROR;
  351.     }

  352.     if (conf->verify) {

  353.         if (conf->verify != 3
  354.             && conf->client_certificate.len == 0
  355.             && conf->trusted_certificate.len == 0)
  356.         {
  357.             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
  358.                           "no ssl_client_certificate or "
  359.                           "ssl_trusted_certificate for ssl_verify_client");
  360.             return NGX_CONF_ERROR;
  361.         }

  362.         if (ngx_ssl_client_certificate(cf, &conf->ssl,
  363.                                        &conf->client_certificate,
  364.                                        conf->verify_depth)
  365.             != NGX_OK)
  366.         {
  367.             return NGX_CONF_ERROR;
  368.         }

  369.         if (ngx_ssl_trusted_certificate(cf, &conf->ssl,
  370.                                         &conf->trusted_certificate,
  371.                                         conf->verify_depth)
  372.             != NGX_OK)
  373.         {
  374.             return NGX_CONF_ERROR;
  375.         }

  376.         if (ngx_ssl_crl(cf, &conf->ssl, &conf->crl) != NGX_OK) {
  377.             return NGX_CONF_ERROR;
  378.         }
  379.     }

  380.     if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) {
  381.         return NGX_CONF_ERROR;
  382.     }

  383.     if (ngx_ssl_ecdh_curve(cf, &conf->ssl, &conf->ecdh_curve) != NGX_OK) {
  384.         return NGX_CONF_ERROR;
  385.     }

  386.     ngx_conf_merge_value(conf->builtin_session_cache,
  387.                          prev->builtin_session_cache, NGX_SSL_NONE_SCACHE);

  388.     if (conf->shm_zone == NULL) {
  389.         conf->shm_zone = prev->shm_zone;
  390.     }

  391.     if (ngx_ssl_session_cache(&conf->ssl, &ngx_mail_ssl_sess_id_ctx,
  392.                               conf->certificates, conf->builtin_session_cache,
  393.                               conf->shm_zone, conf->session_timeout)
  394.         != NGX_OK)
  395.     {
  396.         return NGX_CONF_ERROR;
  397.     }

  398.     ngx_conf_merge_value(conf->session_tickets,
  399.                          prev->session_tickets, 1);

  400. #ifdef SSL_OP_NO_TICKET
  401.     if (!conf->session_tickets) {
  402.         SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_NO_TICKET);
  403.     }
  404. #endif

  405.     ngx_conf_merge_ptr_value(conf->session_ticket_keys,
  406.                          prev->session_ticket_keys, NULL);

  407.     if (ngx_ssl_session_ticket_keys(cf, &conf->ssl, conf->session_ticket_keys)
  408.         != NGX_OK)
  409.     {
  410.         return NGX_CONF_ERROR;
  411.     }

  412.     if (ngx_ssl_conf_commands(cf, &conf->ssl, conf->conf_commands) != NGX_OK) {
  413.         return NGX_CONF_ERROR;
  414.     }

  415.     return NGX_CONF_OK;
  416. }


  417. static char *
  418. ngx_mail_ssl_starttls(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  419. {
  420.     ngx_mail_ssl_conf_t  *scf = conf;

  421.     char  *rv;

  422.     rv = ngx_conf_set_enum_slot(cf, cmd, conf);

  423.     if (rv != NGX_CONF_OK) {
  424.         return rv;
  425.     }

  426.     if (!scf->listen) {
  427.         scf->file = cf->conf_file->file.name.data;
  428.         scf->line = cf->conf_file->line;
  429.     }

  430.     return NGX_CONF_OK;
  431. }


  432. static char *
  433. ngx_mail_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  434. {
  435.     ngx_mail_ssl_conf_t  *scf = conf;

  436.     ngx_str_t  *value;

  437.     if (scf->passwords != NGX_CONF_UNSET_PTR) {
  438.         return "is duplicate";
  439.     }

  440.     value = cf->args->elts;

  441.     scf->passwords = ngx_ssl_read_password_file(cf, &value[1]);

  442.     if (scf->passwords == NULL) {
  443.         return NGX_CONF_ERROR;
  444.     }

  445.     return NGX_CONF_OK;
  446. }


  447. static char *
  448. ngx_mail_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  449. {
  450.     ngx_mail_ssl_conf_t  *scf = conf;

  451.     size_t       len;
  452.     ngx_str_t   *value, name, size;
  453.     ngx_int_t    n;
  454.     ngx_uint_t   i, j;

  455.     value = cf->args->elts;

  456.     for (i = 1; i < cf->args->nelts; i++) {

  457.         if (ngx_strcmp(value[i].data, "off") == 0) {
  458.             scf->builtin_session_cache = NGX_SSL_NO_SCACHE;
  459.             continue;
  460.         }

  461.         if (ngx_strcmp(value[i].data, "none") == 0) {
  462.             scf->builtin_session_cache = NGX_SSL_NONE_SCACHE;
  463.             continue;
  464.         }

  465.         if (ngx_strcmp(value[i].data, "builtin") == 0) {
  466.             scf->builtin_session_cache = NGX_SSL_DFLT_BUILTIN_SCACHE;
  467.             continue;
  468.         }

  469.         if (value[i].len > sizeof("builtin:") - 1
  470.             && ngx_strncmp(value[i].data, "builtin:", sizeof("builtin:") - 1)
  471.                == 0)
  472.         {
  473.             n = ngx_atoi(value[i].data + sizeof("builtin:") - 1,
  474.                          value[i].len - (sizeof("builtin:") - 1));

  475.             if (n == NGX_ERROR) {
  476.                 goto invalid;
  477.             }

  478.             scf->builtin_session_cache = n;

  479.             continue;
  480.         }

  481.         if (value[i].len > sizeof("shared:") - 1
  482.             && ngx_strncmp(value[i].data, "shared:", sizeof("shared:") - 1)
  483.                == 0)
  484.         {
  485.             len = 0;

  486.             for (j = sizeof("shared:") - 1; j < value[i].len; j++) {
  487.                 if (value[i].data[j] == ':') {
  488.                     break;
  489.                 }

  490.                 len++;
  491.             }

  492.             if (len == 0 || j == value[i].len) {
  493.                 goto invalid;
  494.             }

  495.             name.len = len;
  496.             name.data = value[i].data + sizeof("shared:") - 1;

  497.             size.len = value[i].len - j - 1;
  498.             size.data = name.data + len + 1;

  499.             n = ngx_parse_size(&size);

  500.             if (n == NGX_ERROR) {
  501.                 goto invalid;
  502.             }

  503.             if (n < (ngx_int_t) (8 * ngx_pagesize)) {
  504.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  505.                                    "session cache \"%V\" is too small",
  506.                                    &value[i]);

  507.                 return NGX_CONF_ERROR;
  508.             }

  509.             scf->shm_zone = ngx_shared_memory_add(cf, &name, n,
  510.                                                    &ngx_mail_ssl_module);
  511.             if (scf->shm_zone == NULL) {
  512.                 return NGX_CONF_ERROR;
  513.             }

  514.             scf->shm_zone->init = ngx_ssl_session_cache_init;

  515.             continue;
  516.         }

  517.         goto invalid;
  518.     }

  519.     if (scf->shm_zone && scf->builtin_session_cache == NGX_CONF_UNSET) {
  520.         scf->builtin_session_cache = NGX_SSL_NO_BUILTIN_SCACHE;
  521.     }

  522.     return NGX_CONF_OK;

  523. invalid:

  524.     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  525.                        "invalid session cache \"%V\"", &value[i]);

  526.     return NGX_CONF_ERROR;
  527. }


  528. static char *
  529. ngx_mail_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
  530. {
  531. #ifndef SSL_CONF_FLAG_FILE
  532.     return "is not supported on this platform";
  533. #else
  534.     return NGX_CONF_OK;
  535. #endif
  536. }