src/mail/ngx_mail_ssl_module.c - nginx-1.31.3 nginx/ @ 42f8df65b

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_certificate_compression"),
  75.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG,
  76.       ngx_conf_set_flag_slot,
  77.       NGX_MAIL_SRV_CONF_OFFSET,
  78.       offsetof(ngx_mail_ssl_conf_t, certificate_compression),
  79.       NULL },

  80.     { ngx_string("ssl_dhparam"),
  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, dhparam),
  85.       NULL },

  86.     { ngx_string("ssl_ecdh_curve"),
  87.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
  88.       ngx_conf_set_str_slot,
  89.       NGX_MAIL_SRV_CONF_OFFSET,
  90.       offsetof(ngx_mail_ssl_conf_t, ecdh_curve),
  91.       NULL },

  92.     { ngx_string("ssl_protocols"),
  93.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE,
  94.       ngx_conf_set_bitmask_slot,
  95.       NGX_MAIL_SRV_CONF_OFFSET,
  96.       offsetof(ngx_mail_ssl_conf_t, protocols),
  97.       &ngx_mail_ssl_protocols },

  98.     { ngx_string("ssl_ciphers"),
  99.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
  100.       ngx_conf_set_str_slot,
  101.       NGX_MAIL_SRV_CONF_OFFSET,
  102.       offsetof(ngx_mail_ssl_conf_t, ciphers),
  103.       NULL },

  104.     { ngx_string("ssl_prefer_server_ciphers"),
  105.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG,
  106.       ngx_conf_set_flag_slot,
  107.       NGX_MAIL_SRV_CONF_OFFSET,
  108.       offsetof(ngx_mail_ssl_conf_t, prefer_server_ciphers),
  109.       NULL },

  110.     { ngx_string("ssl_session_cache"),
  111.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE12,
  112.       ngx_mail_ssl_session_cache,
  113.       NGX_MAIL_SRV_CONF_OFFSET,
  114.       0,
  115.       NULL },

  116.     { ngx_string("ssl_session_tickets"),
  117.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG,
  118.       ngx_conf_set_flag_slot,
  119.       NGX_MAIL_SRV_CONF_OFFSET,
  120.       offsetof(ngx_mail_ssl_conf_t, session_tickets),
  121.       NULL },

  122.     { ngx_string("ssl_session_ticket_key"),
  123.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
  124.       ngx_conf_set_str_array_slot,
  125.       NGX_MAIL_SRV_CONF_OFFSET,
  126.       offsetof(ngx_mail_ssl_conf_t, session_ticket_keys),
  127.       NULL },

  128.     { ngx_string("ssl_session_timeout"),
  129.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
  130.       ngx_conf_set_sec_slot,
  131.       NGX_MAIL_SRV_CONF_OFFSET,
  132.       offsetof(ngx_mail_ssl_conf_t, session_timeout),
  133.       NULL },

  134.     { ngx_string("ssl_verify_client"),
  135.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
  136.       ngx_conf_set_enum_slot,
  137.       NGX_MAIL_SRV_CONF_OFFSET,
  138.       offsetof(ngx_mail_ssl_conf_t, verify),
  139.       &ngx_mail_ssl_verify },

  140.     { ngx_string("ssl_verify_depth"),
  141.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
  142.       ngx_conf_set_num_slot,
  143.       NGX_MAIL_SRV_CONF_OFFSET,
  144.       offsetof(ngx_mail_ssl_conf_t, verify_depth),
  145.       NULL },

  146.     { ngx_string("ssl_client_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, client_certificate),
  151.       NULL },

  152.     { ngx_string("ssl_trusted_certificate"),
  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, trusted_certificate),
  157.       NULL },

  158.     { ngx_string("ssl_crl"),
  159.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
  160.       ngx_conf_set_str_slot,
  161.       NGX_MAIL_SRV_CONF_OFFSET,
  162.       offsetof(ngx_mail_ssl_conf_t, crl),
  163.       NULL },

  164.     { ngx_string("ssl_conf_command"),
  165.       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE2,
  166.       ngx_conf_set_keyval_slot,
  167.       NGX_MAIL_SRV_CONF_OFFSET,
  168.       offsetof(ngx_mail_ssl_conf_t, conf_commands),
  169.       &ngx_mail_ssl_conf_command_post },

  170.       ngx_null_command
  171. };


  172. static ngx_mail_module_t  ngx_mail_ssl_module_ctx = {
  173.     NULL,                                  /* protocol */

  174.     NULL,                                  /* create main configuration */
  175.     NULL,                                  /* init main configuration */

  176.     ngx_mail_ssl_create_conf,              /* create server configuration */
  177.     ngx_mail_ssl_merge_conf                /* merge server configuration */
  178. };


  179. ngx_module_t  ngx_mail_ssl_module = {
  180.     NGX_MODULE_V1,
  181.     &ngx_mail_ssl_module_ctx,              /* module context */
  182.     ngx_mail_ssl_commands,                 /* module directives */
  183.     NGX_MAIL_MODULE,                       /* module type */
  184.     NULL,                                  /* init master */
  185.     NULL,                                  /* init module */
  186.     NULL,                                  /* init process */
  187.     NULL,                                  /* init thread */
  188.     NULL,                                  /* exit thread */
  189.     NULL,                                  /* exit process */
  190.     NULL,                                  /* exit master */
  191.     NGX_MODULE_V1_PADDING
  192. };


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


  194. #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation

  195. static int
  196. ngx_mail_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out,
  197.     unsigned char *outlen, const unsigned char *in, unsigned int inlen,
  198.     void *arg)
  199. {
  200.     unsigned int               srvlen;
  201.     unsigned char             *srv;
  202.     ngx_connection_t          *c;
  203.     ngx_mail_session_t        *s;
  204.     ngx_mail_core_srv_conf_t  *cscf;
  205. #if (NGX_DEBUG)
  206.     unsigned int               i;
  207. #endif

  208.     c = ngx_ssl_get_connection(ssl_conn);
  209.     s = c->data;

  210. #if (NGX_DEBUG)
  211.     for (i = 0; i < inlen; i += in[i] + 1) {
  212.         ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0,
  213.                        "SSL ALPN supported by client: %*s",
  214.                        (size_t) in[i], &in[i + 1]);
  215.     }
  216. #endif

  217.     cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);

  218.     srv = cscf->protocol->alpn.data;
  219.     srvlen = cscf->protocol->alpn.len;

  220.     if (SSL_select_next_proto((unsigned char **) out, outlen, srv, srvlen,
  221.                               in, inlen)
  222.         != OPENSSL_NPN_NEGOTIATED)
  223.     {
  224.         return SSL_TLSEXT_ERR_ALERT_FATAL;
  225.     }

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

  228.     return SSL_TLSEXT_ERR_OK;
  229. }

  230. #endif


  231. static void *
  232. ngx_mail_ssl_create_conf(ngx_conf_t *cf)
  233. {
  234.     ngx_mail_ssl_conf_t  *scf;

  235.     scf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_ssl_conf_t));
  236.     if (scf == NULL) {
  237.         return NULL;
  238.     }

  239.     /*
  240.      * set by ngx_pcalloc():
  241.      *
  242.      *     scf->listen = 0;
  243.      *     scf->protocols = 0;
  244.      *     scf->dhparam = { 0, NULL };
  245.      *     scf->ecdh_curve = { 0, NULL };
  246.      *     scf->client_certificate = { 0, NULL };
  247.      *     scf->trusted_certificate = { 0, NULL };
  248.      *     scf->crl = { 0, NULL };
  249.      *     scf->ciphers = { 0, NULL };
  250.      *     scf->shm_zone = NULL;
  251.      */

  252.     scf->starttls = NGX_CONF_UNSET_UINT;
  253.     scf->certificates = NGX_CONF_UNSET_PTR;
  254.     scf->certificate_keys = NGX_CONF_UNSET_PTR;
  255.     scf->passwords = NGX_CONF_UNSET_PTR;
  256.     scf->conf_commands = NGX_CONF_UNSET_PTR;
  257.     scf->prefer_server_ciphers = NGX_CONF_UNSET;
  258.     scf->certificate_compression = NGX_CONF_UNSET;
  259.     scf->verify = NGX_CONF_UNSET_UINT;
  260.     scf->verify_depth = NGX_CONF_UNSET_UINT;
  261.     scf->builtin_session_cache = NGX_CONF_UNSET;
  262.     scf->session_timeout = NGX_CONF_UNSET;
  263.     scf->session_tickets = NGX_CONF_UNSET;
  264.     scf->session_ticket_keys = NGX_CONF_UNSET_PTR;

  265.     return scf;
  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.     char                *mode;
  273.     ngx_pool_cleanup_t  *cln;

  274.     ngx_conf_merge_uint_value(conf->starttls, prev->starttls,
  275.                          NGX_MAIL_STARTTLS_OFF);

  276.     ngx_conf_merge_value(conf->session_timeout,
  277.                          prev->session_timeout, 300);

  278.     ngx_conf_merge_value(conf->prefer_server_ciphers,
  279.                          prev->prefer_server_ciphers, 0);

  280.     ngx_conf_merge_value(conf->certificate_compression,
  281.                          prev->certificate_compression, 0);

  282.     ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
  283.                          (NGX_CONF_BITMASK_SET|NGX_SSL_DEFAULT_PROTOCOLS));

  284.     ngx_conf_merge_uint_value(conf->verify, prev->verify, 0);
  285.     ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1);

  286.     ngx_conf_merge_ptr_value(conf->certificates, prev->certificates, NULL);
  287.     ngx_conf_merge_ptr_value(conf->certificate_keys, prev->certificate_keys,
  288.                          NULL);

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

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

  291.     ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve,
  292.                          NGX_DEFAULT_ECDH_CURVE);

  293.     ngx_conf_merge_str_value(conf->client_certificate,
  294.                          prev->client_certificate, "");
  295.     ngx_conf_merge_str_value(conf->trusted_certificate,
  296.                          prev->trusted_certificate, "");
  297.     ngx_conf_merge_str_value(conf->crl, prev->crl, "");

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

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


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

  301.     if (conf->listen) {
  302.         mode = "listen ... ssl";

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

  305.     } else {
  306.         return NGX_CONF_OK;
  307.     }

  308.     if (conf->file == NULL) {
  309.         conf->file = prev->file;
  310.         conf->line = prev->line;
  311.     }

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

  319.     if (conf->certificate_keys == NULL) {
  320.         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
  321.                       "no \"ssl_certificate_key\" is defined for "
  322.                       "the \"%s\" directive in %s:%ui",
  323.                       mode, conf->file, conf->line);
  324.         return NGX_CONF_ERROR;
  325.     }

  326.     if (conf->certificate_keys->nelts < conf->certificates->nelts) {
  327.         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
  328.                       "no \"ssl_certificate_key\" is defined "
  329.                       "for certificate \"%V\" and "
  330.                       "the \"%s\" directive in %s:%ui",
  331.                       ((ngx_str_t *) conf->certificates->elts)
  332.                       + conf->certificates->nelts - 1,
  333.                       mode, conf->file, conf->line);
  334.         return NGX_CONF_ERROR;
  335.     }

  336.     if (ngx_ssl_create(&conf->ssl, conf->protocols, NULL) != NGX_OK) {
  337.         return NGX_CONF_ERROR;
  338.     }

  339.     cln = ngx_pool_cleanup_add(cf->pool, 0);
  340.     if (cln == NULL) {
  341.         ngx_ssl_cleanup_ctx(&conf->ssl);
  342.         return NGX_CONF_ERROR;
  343.     }

  344.     cln->handler = ngx_ssl_cleanup_ctx;
  345.     cln->data = &conf->ssl;

  346. #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
  347.     SSL_CTX_set_alpn_select_cb(conf->ssl.ctx, ngx_mail_ssl_alpn_select, NULL);
  348. #endif

  349.     if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers,
  350.                         conf->prefer_server_ciphers)
  351.         != NGX_OK)
  352.     {
  353.         return NGX_CONF_ERROR;
  354.     }

  355.     if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates,
  356.                              conf->certificate_keys, conf->passwords)
  357.         != NGX_OK)
  358.     {
  359.         return NGX_CONF_ERROR;
  360.     }

  361.     if (ngx_ssl_certificate_compression(cf, &conf->ssl,
  362.                                         conf->certificate_compression)
  363.         != NGX_OK)
  364.     {
  365.         return NGX_CONF_ERROR;
  366.     }

  367.     if (conf->verify) {

  368.         if (conf->verify != 3
  369.             && conf->client_certificate.len == 0
  370.             && conf->trusted_certificate.len == 0)
  371.         {
  372.             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
  373.                           "no ssl_client_certificate or "
  374.                           "ssl_trusted_certificate for ssl_verify_client");
  375.             return NGX_CONF_ERROR;
  376.         }

  377.         if (ngx_ssl_client_certificate(cf, &conf->ssl,
  378.                                        &conf->client_certificate,
  379.                                        conf->verify_depth)
  380.             != NGX_OK)
  381.         {
  382.             return NGX_CONF_ERROR;
  383.         }

  384.         if (ngx_ssl_trusted_certificate(cf, &conf->ssl,
  385.                                         &conf->trusted_certificate,
  386.                                         conf->verify_depth)
  387.             != NGX_OK)
  388.         {
  389.             return NGX_CONF_ERROR;
  390.         }

  391.         if (ngx_ssl_crl(cf, &conf->ssl, &conf->crl) != NGX_OK) {
  392.             return NGX_CONF_ERROR;
  393.         }
  394.     }

  395.     if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) {
  396.         return NGX_CONF_ERROR;
  397.     }

  398.     if (ngx_ssl_ecdh_curve(cf, &conf->ssl, &conf->ecdh_curve) != NGX_OK) {
  399.         return NGX_CONF_ERROR;
  400.     }

  401.     ngx_conf_merge_value(conf->builtin_session_cache,
  402.                          prev->builtin_session_cache, NGX_SSL_NONE_SCACHE);

  403.     if (conf->shm_zone == NULL) {
  404.         conf->shm_zone = prev->shm_zone;
  405.     }

  406.     if (ngx_ssl_session_cache(&conf->ssl, &ngx_mail_ssl_sess_id_ctx,
  407.                               conf->certificates, conf->builtin_session_cache,
  408.                               conf->shm_zone, conf->session_timeout)
  409.         != NGX_OK)
  410.     {
  411.         return NGX_CONF_ERROR;
  412.     }

  413.     ngx_conf_merge_value(conf->session_tickets,
  414.                          prev->session_tickets, 1);

  415. #ifdef SSL_OP_NO_TICKET
  416.     if (!conf->session_tickets) {
  417.         SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_NO_TICKET);
  418.     }
  419. #endif

  420.     ngx_conf_merge_ptr_value(conf->session_ticket_keys,
  421.                          prev->session_ticket_keys, NULL);

  422.     if (ngx_ssl_session_ticket_keys(cf, &conf->ssl, conf->session_ticket_keys)
  423.         != NGX_OK)
  424.     {
  425.         return NGX_CONF_ERROR;
  426.     }

  427.     if (ngx_ssl_conf_commands(cf, &conf->ssl, conf->conf_commands) != NGX_OK) {
  428.         return NGX_CONF_ERROR;
  429.     }

  430.     return NGX_CONF_OK;
  431. }


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

  436.     char  *rv;

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

  438.     if (rv != NGX_CONF_OK) {
  439.         return rv;
  440.     }

  441.     if (!scf->listen) {
  442.         scf->file = cf->conf_file->file.name.data;
  443.         scf->line = cf->conf_file->line;
  444.     }

  445.     return NGX_CONF_OK;
  446. }


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

  451.     ngx_str_t  *value;

  452.     if (scf->passwords != NGX_CONF_UNSET_PTR) {
  453.         return "is duplicate";
  454.     }

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

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

  457.     if (scf->passwords == NULL) {
  458.         return NGX_CONF_ERROR;
  459.     }

  460.     return NGX_CONF_OK;
  461. }


  462. static char *
  463. ngx_mail_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  464. {
  465.     ngx_mail_ssl_conf_t  *scf = conf;

  466.     size_t       len;
  467.     ngx_str_t   *value, name, size;
  468.     ngx_int_t    n;
  469.     ngx_uint_t   i, j;

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

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

  472.         if (ngx_strcmp(value[i].data, "off") == 0) {
  473.             scf->builtin_session_cache = NGX_SSL_NO_SCACHE;
  474.             continue;
  475.         }

  476.         if (ngx_strcmp(value[i].data, "none") == 0) {
  477.             scf->builtin_session_cache = NGX_SSL_NONE_SCACHE;
  478.             continue;
  479.         }

  480.         if (ngx_strcmp(value[i].data, "builtin") == 0) {
  481.             scf->builtin_session_cache = NGX_SSL_DFLT_BUILTIN_SCACHE;
  482.             continue;
  483.         }

  484.         if (value[i].len > sizeof("builtin:") - 1
  485.             && ngx_strncmp(value[i].data, "builtin:", sizeof("builtin:") - 1)
  486.                == 0)
  487.         {
  488.             n = ngx_atoi(value[i].data + sizeof("builtin:") - 1,
  489.                          value[i].len - (sizeof("builtin:") - 1));

  490.             if (n == NGX_ERROR) {
  491.                 goto invalid;
  492.             }

  493.             scf->builtin_session_cache = n;

  494.             continue;
  495.         }

  496.         if (value[i].len > sizeof("shared:") - 1
  497.             && ngx_strncmp(value[i].data, "shared:", sizeof("shared:") - 1)
  498.                == 0)
  499.         {
  500.             len = 0;

  501.             for (j = sizeof("shared:") - 1; j < value[i].len; j++) {
  502.                 if (value[i].data[j] == ':') {
  503.                     break;
  504.                 }

  505.                 len++;
  506.             }

  507.             if (len == 0 || j == value[i].len) {
  508.                 goto invalid;
  509.             }

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

  512.             size.len = value[i].len - j - 1;
  513.             size.data = name.data + len + 1;

  514.             n = ngx_parse_size(&size);

  515.             if (n == NGX_ERROR) {
  516.                 goto invalid;
  517.             }

  518.             if (n < (ngx_int_t) (8 * ngx_pagesize)) {
  519.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  520.                                    "session cache \"%V\" is too small",
  521.                                    &value[i]);

  522.                 return NGX_CONF_ERROR;
  523.             }

  524.             scf->shm_zone = ngx_shared_memory_add(cf, &name, n,
  525.                                                    &ngx_mail_ssl_module);
  526.             if (scf->shm_zone == NULL) {
  527.                 return NGX_CONF_ERROR;
  528.             }

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

  530.             continue;
  531.         }

  532.         goto invalid;
  533.     }

  534.     if (scf->shm_zone && scf->builtin_session_cache == NGX_CONF_UNSET) {
  535.         scf->builtin_session_cache = NGX_SSL_NO_BUILTIN_SCACHE;
  536.     }

  537.     return NGX_CONF_OK;

  538. invalid:

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

  541.     return NGX_CONF_ERROR;
  542. }


  543. static char *
  544. ngx_mail_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
  545. {
  546. #ifndef SSL_CONF_FLAG_FILE
  547.     return "is not supported on this platform";
  548. #else
  549.     return NGX_CONF_OK;
  550. #endif
  551. }