~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Nginx/mail/ngx_mail_ssl_module.c

Version: ~ [ nginx-0.6.26 ] ~ [ nginx-0.5.35 ] ~ [ nginx-0.5.20 ] ~ [ nginx-0.5.19 ] ~

  1 
  2 /*
  3  * Copyright (C) Igor Sysoev
  4  */
  5 
  6 
  7 #include <ngx_config.h>
  8 #include <ngx_core.h>
  9 #include <ngx_mail.h>
 10 
 11 
 12 #define NGX_DEFLAUT_CERTIFICATE      "cert.pem"
 13 #define NGX_DEFLAUT_CERTIFICATE_KEY  "cert.pem"
 14 #define NGX_DEFLAUT_CIPHERS  "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP"
 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 static char *ngx_mail_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
 20     void *conf);
 21 
 22 #if !defined (SSL_OP_CIPHER_SERVER_PREFERENCE)
 23 
 24 static char *ngx_mail_ssl_nosupported(ngx_conf_t *cf, ngx_command_t *cmd,
 25     void *conf);
 26 
 27 static char  ngx_mail_ssl_openssl097[] = "OpenSSL 0.9.7 and higher";
 28 
 29 #endif
 30 
 31 
 32 static ngx_conf_enum_t  ngx_http_starttls_state[] = {
 33     { ngx_string("off"), NGX_MAIL_STARTTLS_OFF },
 34     { ngx_string("on"), NGX_MAIL_STARTTLS_ON },
 35     { ngx_string("only"), NGX_MAIL_STARTTLS_ONLY },
 36     { ngx_null_string, 0 }
 37 };
 38 
 39 
 40 
 41 static ngx_conf_bitmask_t  ngx_mail_ssl_protocols[] = {
 42     { ngx_string("SSLv2"), NGX_SSL_SSLv2 },
 43     { ngx_string("SSLv3"), NGX_SSL_SSLv3 },
 44     { ngx_string("TLSv1"), NGX_SSL_TLSv1 },
 45     { ngx_null_string, 0 }
 46 };
 47 
 48 
 49 static ngx_command_t  ngx_mail_ssl_commands[] = {
 50 
 51     { ngx_string("ssl"),
 52       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG,
 53       ngx_conf_set_flag_slot,
 54       NGX_MAIL_SRV_CONF_OFFSET,
 55       offsetof(ngx_mail_ssl_conf_t, enable),
 56       NULL },
 57 
 58     { ngx_string("starttls"),
 59       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
 60       ngx_conf_set_enum_slot,
 61       NGX_MAIL_SRV_CONF_OFFSET,
 62       offsetof(ngx_mail_ssl_conf_t, starttls),
 63       ngx_http_starttls_state },
 64 
 65     { ngx_string("ssl_certificate"),
 66       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
 67       ngx_conf_set_str_slot,
 68       NGX_MAIL_SRV_CONF_OFFSET,
 69       offsetof(ngx_mail_ssl_conf_t, certificate),
 70       NULL },
 71 
 72     { ngx_string("ssl_certificate_key"),
 73       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
 74       ngx_conf_set_str_slot,
 75       NGX_MAIL_SRV_CONF_OFFSET,
 76       offsetof(ngx_mail_ssl_conf_t, certificate_key),
 77       NULL },
 78 
 79     { ngx_string("ssl_protocols"),
 80       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE,
 81       ngx_conf_set_bitmask_slot,
 82       NGX_MAIL_SRV_CONF_OFFSET,
 83       offsetof(ngx_mail_ssl_conf_t, protocols),
 84       &ngx_mail_ssl_protocols },
 85 
 86     { ngx_string("ssl_ciphers"),
 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, ciphers),
 91       NULL },
 92 
 93     { ngx_string("ssl_prefer_server_ciphers"),
 94       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG,
 95 #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
 96       ngx_conf_set_flag_slot,
 97       NGX_MAIL_SRV_CONF_OFFSET,
 98       offsetof(ngx_mail_ssl_conf_t, prefer_server_ciphers),
 99       NULL },
100 #else
101       ngx_mail_ssl_nosupported, 0, 0, ngx_mail_ssl_openssl097 },
102 #endif
103 
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 
111     { ngx_string("ssl_session_timeout"),
112       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
113       ngx_conf_set_sec_slot,
114       NGX_MAIL_SRV_CONF_OFFSET,
115       offsetof(ngx_mail_ssl_conf_t, session_timeout),
116       NULL },
117 
118       ngx_null_command
119 };
120 
121 
122 static ngx_mail_module_t  ngx_mail_ssl_module_ctx = {
123     NULL,                                  /* protocol */
124 
125     NULL,                                  /* create main configuration */
126     NULL,                                  /* init main configuration */
127 
128     ngx_mail_ssl_create_conf,              /* create server configuration */
129     ngx_mail_ssl_merge_conf                /* merge server configuration */
130 };
131 
132 
133 ngx_module_t  ngx_mail_ssl_module = {
134     NGX_MODULE_V1,
135     &ngx_mail_ssl_module_ctx,              /* module context */
136     ngx_mail_ssl_commands,                 /* module directives */
137     NGX_MAIL_MODULE,                       /* module type */
138     NULL,                                  /* init master */
139     NULL,                                  /* init module */
140     NULL,                                  /* init process */
141     NULL,                                  /* init thread */
142     NULL,                                  /* exit thread */
143     NULL,                                  /* exit process */
144     NULL,                                  /* exit master */
145     NGX_MODULE_V1_PADDING
146 };
147 
148 
149 static ngx_str_t ngx_mail_ssl_sess_id_ctx = ngx_string("MAIL");
150 
151 
152 static void *
153 ngx_mail_ssl_create_conf(ngx_conf_t *cf)
154 {
155     ngx_mail_ssl_conf_t  *scf;
156 
157     scf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_ssl_conf_t));
158     if (scf == NULL) {
159         return NGX_CONF_ERROR;
160     }
161 
162     /*
163      * set by ngx_pcalloc():
164      *
165      *     scf->protocols = 0;
166      *     scf->certificate.len = 0;
167      *     scf->certificate.data = NULL;
168      *     scf->certificate_key.len = 0;
169      *     scf->certificate_key.data = NULL;
170      *     scf->ciphers.len = 0;
171      *     scf->ciphers.data = NULL;
172      *     scf->shm_zone = NULL;
173      */
174 
175     scf->enable = NGX_CONF_UNSET;
176     scf->starttls = NGX_CONF_UNSET;
177     scf->prefer_server_ciphers = NGX_CONF_UNSET;
178     scf->builtin_session_cache = NGX_CONF_UNSET;
179     scf->session_timeout = NGX_CONF_UNSET;
180 
181     return scf;
182 }
183 
184 
185 static char *
186 ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
187 {
188     ngx_mail_ssl_conf_t *prev = parent;
189     ngx_mail_ssl_conf_t *conf = child;
190 
191     ngx_pool_cleanup_t  *cln;
192 
193     ngx_conf_merge_value(conf->enable, prev->enable, 0);
194     ngx_conf_merge_value(conf->starttls, prev->starttls, NGX_MAIL_STARTTLS_OFF);
195 
196     if (conf->enable == 0 && conf->starttls == NGX_MAIL_STARTTLS_OFF) {
197         return NGX_CONF_OK;
198     }
199 
200     ngx_conf_merge_value(conf->session_timeout,
201                          prev->session_timeout, 300);
202 
203     ngx_conf_merge_value(conf->prefer_server_ciphers,
204                          prev->prefer_server_ciphers, 0);
205 
206     ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
207                          (NGX_CONF_BITMASK_SET
208                           |NGX_SSL_SSLv2|NGX_SSL_SSLv3|NGX_SSL_TLSv1));
209 
210     ngx_conf_merge_str_value(conf->certificate, prev->certificate,
211                          NGX_DEFLAUT_CERTIFICATE);
212 
213     ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key,
214                          NGX_DEFLAUT_CERTIFICATE_KEY);
215 
216     ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFLAUT_CIPHERS);
217 
218 
219     conf->ssl.log = cf->log;
220 
221     if (ngx_ssl_create(&conf->ssl, conf->protocols, NULL) != NGX_OK) {
222         return NGX_CONF_ERROR;
223     }
224 
225     cln = ngx_pool_cleanup_add(cf->pool, 0);
226     if (cln == NULL) {
227         return NGX_CONF_ERROR;
228     }
229 
230     cln->handler = ngx_ssl_cleanup_ctx;
231     cln->data = &conf->ssl;
232 
233     if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate,
234                             &conf->certificate_key)
235         != NGX_OK)
236     {
237         return NGX_CONF_ERROR;
238     }
239 
240     if (conf->ciphers.len) {
241         if (SSL_CTX_set_cipher_list(conf->ssl.ctx,
242                                    (const char *) conf->ciphers.data)
243             == 0)
244         {
245             ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
246                           "SSL_CTX_set_cipher_list(\"%V\") failed",
247                           &conf->ciphers);
248         }
249     }
250 
251 #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
252 
253     if (conf->prefer_server_ciphers) {
254         SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
255     }
256 
257 #endif
258 
259     if (ngx_ssl_generate_rsa512_key(&conf->ssl) != NGX_OK) {
260         return NGX_CONF_ERROR;
261     }
262 
263     ngx_conf_merge_value(conf->builtin_session_cache,
264                          prev->builtin_session_cache, NGX_SSL_NO_SCACHE);
265 
266     if (conf->shm_zone == NULL) {
267         conf->shm_zone = prev->shm_zone;
268     }
269 
270     if (ngx_ssl_session_cache(&conf->ssl, &ngx_mail_ssl_sess_id_ctx,
271                               conf->builtin_session_cache,
272                               conf->shm_zone, conf->session_timeout)
273         != NGX_OK)
274     {
275         return NGX_CONF_ERROR;
276     }
277 
278     return NGX_CONF_OK;
279 }
280 
281 
282 static char *
283 ngx_mail_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
284 {
285     ngx_mail_ssl_conf_t  *scf = conf;
286 
287     size_t       len;
288     ngx_str_t   *value, name, size;
289     ngx_int_t    n;
290     ngx_uint_t   i, j;
291 
292     value = cf->args->elts;
293 
294     for (i = 1; i < cf->args->nelts; i++) {
295 
296         if (ngx_strcmp(value[i].data, "off") == 0) {
297             scf->builtin_session_cache = NGX_SSL_NO_SCACHE;
298             continue;
299         }
300 
301         if (ngx_strcmp(value[i].data, "builtin") == 0) {
302             scf->builtin_session_cache = NGX_SSL_DFLT_BUILTIN_SCACHE;
303             continue;
304         }
305 
306         if (value[i].len > sizeof("builtin:") - 1
307             && ngx_strncmp(value[i].data, "builtin:", sizeof("builtin:") - 1)
308                == 0)
309         {
310             n = ngx_atoi(value[i].data + sizeof("builtin:") - 1,
311                          value[i].len - (sizeof("builtin:") - 1));
312 
313             if (n == NGX_ERROR) {
314                 goto invalid;
315             }
316 
317             scf->builtin_session_cache = n;
318 
319             continue;
320         }
321 
322         if (value[i].len > sizeof("shared:") - 1
323             && ngx_strncmp(value[i].data, "shared:", sizeof("shared:") - 1)
324                == 0)
325         {
326             len = 0;
327 
328             for (j = sizeof("shared:") - 1; j < value[i].len; j++) {
329                 if (value[i].data[j] == ':') {
330                     break;
331                 }
332 
333                 len++;
334             }
335 
336             if (len == 0) {
337                 goto invalid;
338             }
339 
340             name.len = len;
341             name.data = value[i].data + sizeof("shared:") - 1;
342 
343             size.len = value[i].len - j - 1;
344             size.data = name.data + len + 1;
345 
346             n = ngx_parse_size(&size);
347 
348             if (n == NGX_ERROR) {
349                 goto invalid;
350             }
351 
352             if (n < (ngx_int_t) (8 * ngx_pagesize)) {
353                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
354                                    "session cache \"%V\" is too small",
355                                    &value[i]);
356 
357                 return NGX_CONF_ERROR;
358             }
359 
360             scf->shm_zone = ngx_shared_memory_add(cf, &name, n,
361                                                    &ngx_mail_ssl_module);
362             if (scf->shm_zone == NULL) {
363                 return NGX_CONF_ERROR;
364             }
365 
366             continue;
367         }
368 
369         goto invalid;
370     }
371 
372     if (scf->shm_zone && scf->builtin_session_cache == NGX_CONF_UNSET) {
373         scf->builtin_session_cache = NGX_SSL_NO_BUILTIN_SCACHE;
374     }
375 
376     return NGX_CONF_OK;
377 
378 invalid:
379 
380     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
381                        "invalid session cache \"%V\"", &value[i]);
382 
383     return NGX_CONF_ERROR;
384 }
385 
386 
387 #if !defined (SSL_OP_CIPHER_SERVER_PREFERENCE)
388 
389 static char *
390 ngx_mail_ssl_nosupported(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
391 {
392     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
393                        "\"%V\" directive is available only in %s,",
394                        &cmd->name, cmd->post);
395 
396     return NGX_CONF_ERROR;
397 }
398 
399 #endif
400 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.