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

Linux Cross Reference
Nginx/http/modules/ngx_http_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_http.h>
 10 
 11 
 12 typedef ngx_int_t (*ngx_ssl_variable_handler_pt)(ngx_connection_t *c,
 13     ngx_pool_t *pool, ngx_str_t *s);
 14 
 15 
 16 #define NGX_DEFLAUT_CERTIFICATE      "cert.pem"
 17 #define NGX_DEFLAUT_CERTIFICATE_KEY  "cert.pem"
 18 #define NGX_DEFLAUT_CIPHERS  "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP"
 19 
 20 
 21 static ngx_int_t ngx_http_ssl_static_variable(ngx_http_request_t *r,
 22     ngx_http_variable_value_t *v, uintptr_t data);
 23 static ngx_int_t ngx_http_ssl_variable(ngx_http_request_t *r,
 24     ngx_http_variable_value_t *v, uintptr_t data);
 25 
 26 static ngx_int_t ngx_http_ssl_add_variables(ngx_conf_t *cf);
 27 static void *ngx_http_ssl_create_srv_conf(ngx_conf_t *cf);
 28 static char *ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf,
 29     void *parent, void *child);
 30 
 31 static char *ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
 32     void *conf);
 33 
 34 #if !defined (SSL_OP_CIPHER_SERVER_PREFERENCE)
 35 
 36 static char *ngx_http_ssl_nosupported(ngx_conf_t *cf, ngx_command_t *cmd,
 37     void *conf);
 38 
 39 static char  ngx_http_ssl_openssl097[] = "OpenSSL 0.9.7 and higher";
 40 
 41 #endif
 42 
 43 
 44 static ngx_conf_bitmask_t  ngx_http_ssl_protocols[] = {
 45     { ngx_string("SSLv2"), NGX_SSL_SSLv2 },
 46     { ngx_string("SSLv3"), NGX_SSL_SSLv3 },
 47     { ngx_string("TLSv1"), NGX_SSL_TLSv1 },
 48     { ngx_null_string, 0 }
 49 };
 50 
 51 
 52 static ngx_command_t  ngx_http_ssl_commands[] = {
 53 
 54     { ngx_string("ssl"),
 55       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
 56       ngx_conf_set_flag_slot,
 57       NGX_HTTP_SRV_CONF_OFFSET,
 58       offsetof(ngx_http_ssl_srv_conf_t, enable),
 59       NULL },
 60 
 61     { ngx_string("ssl_certificate"),
 62       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
 63       ngx_conf_set_str_slot,
 64       NGX_HTTP_SRV_CONF_OFFSET,
 65       offsetof(ngx_http_ssl_srv_conf_t, certificate),
 66       NULL },
 67 
 68     { ngx_string("ssl_certificate_key"),
 69       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
 70       ngx_conf_set_str_slot,
 71       NGX_HTTP_SRV_CONF_OFFSET,
 72       offsetof(ngx_http_ssl_srv_conf_t, certificate_key),
 73       NULL },
 74 
 75     { ngx_string("ssl_protocols"),
 76       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
 77       ngx_conf_set_bitmask_slot,
 78       NGX_HTTP_SRV_CONF_OFFSET,
 79       offsetof(ngx_http_ssl_srv_conf_t, protocols),
 80       &ngx_http_ssl_protocols },
 81 
 82     { ngx_string("ssl_ciphers"),
 83       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
 84       ngx_conf_set_str_slot,
 85       NGX_HTTP_SRV_CONF_OFFSET,
 86       offsetof(ngx_http_ssl_srv_conf_t, ciphers),
 87       NULL },
 88 
 89     { ngx_string("ssl_verify_client"),
 90       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
 91       ngx_conf_set_flag_slot,
 92       NGX_HTTP_SRV_CONF_OFFSET,
 93       offsetof(ngx_http_ssl_srv_conf_t, verify),
 94       NULL },
 95 
 96     { ngx_string("ssl_verify_depth"),
 97       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
 98       ngx_conf_set_num_slot,
 99       NGX_HTTP_SRV_CONF_OFFSET,
100       offsetof(ngx_http_ssl_srv_conf_t, verify_depth),
101       NULL },
102 
103     { ngx_string("ssl_client_certificate"),
104       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
105       ngx_conf_set_str_slot,
106       NGX_HTTP_SRV_CONF_OFFSET,
107       offsetof(ngx_http_ssl_srv_conf_t, client_certificate),
108       NULL },
109 
110     { ngx_string("ssl_prefer_server_ciphers"),
111       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
112 #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
113       ngx_conf_set_flag_slot,
114       NGX_HTTP_SRV_CONF_OFFSET,
115       offsetof(ngx_http_ssl_srv_conf_t, prefer_server_ciphers),
116       NULL },
117 #else
118       ngx_http_ssl_nosupported, 0, 0, ngx_http_ssl_openssl097 },
119 #endif
120 
121     { ngx_string("ssl_session_cache"),
122       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE12,
123       ngx_http_ssl_session_cache,
124       NGX_HTTP_SRV_CONF_OFFSET,
125       0,
126       NULL },
127 
128     { ngx_string("ssl_session_timeout"),
129       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
130       ngx_conf_set_sec_slot,
131       NGX_HTTP_SRV_CONF_OFFSET,
132       offsetof(ngx_http_ssl_srv_conf_t, session_timeout),
133       NULL },
134 
135       ngx_null_command
136 };
137 
138 
139 static ngx_http_module_t  ngx_http_ssl_module_ctx = {
140     ngx_http_ssl_add_variables,            /* preconfiguration */
141     NULL,                                  /* postconfiguration */
142 
143     NULL,                                  /* create main configuration */
144     NULL,                                  /* init main configuration */
145 
146     ngx_http_ssl_create_srv_conf,          /* create server configuration */
147     ngx_http_ssl_merge_srv_conf,           /* merge server configuration */
148 
149     NULL,                                  /* create location configuration */
150     NULL                                   /* merge location configuration */
151 };
152 
153 
154 ngx_module_t  ngx_http_ssl_module = {
155     NGX_MODULE_V1,
156     &ngx_http_ssl_module_ctx,              /* module context */
157     ngx_http_ssl_commands,                 /* module directives */
158     NGX_HTTP_MODULE,                       /* module type */
159     NULL,                                  /* init master */
160     NULL,                                  /* init module */
161     NULL,                                  /* init process */
162     NULL,                                  /* init thread */
163     NULL,                                  /* exit thread */
164     NULL,                                  /* exit process */
165     NULL,                                  /* exit master */
166     NGX_MODULE_V1_PADDING
167 };
168 
169 
170 static ngx_http_variable_t  ngx_http_ssl_vars[] = {
171 
172     { ngx_string("ssl_protocol"), NULL, ngx_http_ssl_static_variable,
173       (uintptr_t) ngx_ssl_get_protocol, NGX_HTTP_VAR_CHANGEABLE, 0 },
174 
175     { ngx_string("ssl_cipher"), NULL, ngx_http_ssl_static_variable,
176       (uintptr_t) ngx_ssl_get_cipher_name, NGX_HTTP_VAR_CHANGEABLE, 0 },
177 
178     { ngx_string("ssl_client_s_dn"), NULL, ngx_http_ssl_variable,
179       (uintptr_t) ngx_ssl_get_subject_dn, NGX_HTTP_VAR_CHANGEABLE, 0 },
180 
181     { ngx_string("ssl_client_i_dn"), NULL, ngx_http_ssl_variable,
182       (uintptr_t) ngx_ssl_get_issuer_dn, NGX_HTTP_VAR_CHANGEABLE, 0 },
183 
184     { ngx_string("ssl_client_serial"), NULL, ngx_http_ssl_variable,
185       (uintptr_t) ngx_ssl_get_serial_number, NGX_HTTP_VAR_CHANGEABLE, 0 },
186 
187     { ngx_null_string, NULL, NULL, 0, 0, 0 }
188 };
189 
190 
191 static ngx_str_t ngx_http_ssl_sess_id_ctx = ngx_string("HTTP");
192 
193 
194 static ngx_int_t
195 ngx_http_ssl_static_variable(ngx_http_request_t *r,
196     ngx_http_variable_value_t *v, uintptr_t data)
197 {
198     ngx_ssl_variable_handler_pt  handler = (ngx_ssl_variable_handler_pt) data;
199 
200     size_t     len;
201     ngx_str_t  s;
202 
203     if (r->connection->ssl) {
204 
205         (void) handler(r->connection, NULL, &s);
206 
207         v->data = s.data;
208 
209         for (len = 0; v->data[len]; len++) { /* void */ }
210 
211         v->len = len;
212         v->valid = 1;
213         v->no_cacheable = 0;
214         v->not_found = 0;
215 
216         return NGX_OK;
217     }
218 
219     v->not_found = 1;
220 
221     return NGX_OK;
222 }
223 
224 
225 static ngx_int_t
226 ngx_http_ssl_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
227     uintptr_t data)
228 {
229     ngx_ssl_variable_handler_pt  handler = (ngx_ssl_variable_handler_pt) data;
230 
231     ngx_str_t  s;
232 
233     if (r->connection->ssl) {
234 
235         if (handler(r->connection, r->pool, &s) != NGX_OK) {
236             return NGX_ERROR;
237         }
238 
239         v->len = s.len;
240         v->data = s.data;
241 
242         if (v->len) {
243             v->valid = 1;
244             v->no_cacheable = 0;
245             v->not_found = 0;
246 
247             return NGX_OK;
248         }
249     }
250 
251     v->not_found = 1;
252 
253     return NGX_OK;
254 }
255 
256 
257 static ngx_int_t
258 ngx_http_ssl_add_variables(ngx_conf_t *cf)
259 {
260     ngx_http_variable_t  *var, *v;
261 
262     for (v = ngx_http_ssl_vars; v->name.len; v++) {
263         var = ngx_http_add_variable(cf, &v->name, v->flags);
264         if (var == NULL) {
265             return NGX_ERROR;
266         }
267 
268         var->get_handler = v->get_handler;
269         var->data = v->data;
270     }
271 
272     return NGX_OK;
273 }
274 
275 
276 static void *
277 ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
278 {
279     ngx_http_ssl_srv_conf_t  *sscf;
280 
281     sscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssl_srv_conf_t));
282     if (sscf == NULL) {
283         return NGX_CONF_ERROR;
284     }
285 
286     /*
287      * set by ngx_pcalloc():
288      *
289      *     sscf->protocols = 0;
290      *     sscf->certificate.len = 0;
291      *     sscf->certificate.data = NULL;
292      *     sscf->certificate_key.len = 0;
293      *     sscf->certificate_key.data = NULL;
294      *     sscf->client_certificate.len = 0;
295      *     sscf->client_certificate.data = NULL;
296      *     sscf->ciphers.len = 0;
297      *     sscf->ciphers.data = NULL;
298      *     sscf->shm_zone = NULL;
299      */
300 
301     sscf->enable = NGX_CONF_UNSET;
302     sscf->verify = NGX_CONF_UNSET;
303     sscf->verify_depth = NGX_CONF_UNSET;
304     sscf->prefer_server_ciphers = NGX_CONF_UNSET;
305     sscf->builtin_session_cache = NGX_CONF_UNSET;
306     sscf->session_timeout = NGX_CONF_UNSET;
307 
308     return sscf;
309 }
310 
311 
312 static char *
313 ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
314 {
315     ngx_http_ssl_srv_conf_t *prev = parent;
316     ngx_http_ssl_srv_conf_t *conf = child;
317 
318     ngx_pool_cleanup_t  *cln;
319 
320     ngx_conf_merge_value(conf->enable, prev->enable, 0);
321 
322     if (conf->enable == 0) {
323         return NGX_CONF_OK;
324     }
325 
326     ngx_conf_merge_value(conf->session_timeout,
327                          prev->session_timeout, 300);
328 
329     ngx_conf_merge_value(conf->prefer_server_ciphers,
330                          prev->prefer_server_ciphers, 0);
331 
332     ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
333                          (NGX_CONF_BITMASK_SET
334                           |NGX_SSL_SSLv2|NGX_SSL_SSLv3|NGX_SSL_TLSv1));
335 
336     ngx_conf_merge_value(conf->verify, prev->verify, 0);
337     ngx_conf_merge_value(conf->verify_depth, prev->verify_depth, 1);
338 
339     ngx_conf_merge_str_value(conf->certificate, prev->certificate,
340                          NGX_DEFLAUT_CERTIFICATE);
341 
342     ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key,
343                          NGX_DEFLAUT_CERTIFICATE_KEY);
344 
345     ngx_conf_merge_str_value(conf->client_certificate, prev->client_certificate,
346                          "");
347 
348     ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFLAUT_CIPHERS);
349 
350 
351     conf->ssl.log = cf->log;
352 
353     if (ngx_ssl_create(&conf->ssl, conf->protocols, conf) != NGX_OK) {
354         return NGX_CONF_ERROR;
355     }
356 
357 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
358 
359     if (SSL_CTX_set_tlsext_servername_callback(conf->ssl.ctx,
360                                                ngx_http_ssl_servername)
361         == 0)
362     {
363         ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
364                       "SSL_CTX_set_tlsext_servername_callback() failed");
365         return NGX_CONF_ERROR;
366     }
367 
368 #endif
369 
370     cln = ngx_pool_cleanup_add(cf->pool, 0);
371     if (cln == NULL) {
372         return NGX_CONF_ERROR;
373     }
374 
375     cln->handler = ngx_ssl_cleanup_ctx;
376     cln->data = &conf->ssl;
377 
378     if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate,
379                             &conf->certificate_key)
380         != NGX_OK)
381     {
382         return NGX_CONF_ERROR;
383     }
384 
385     if (SSL_CTX_set_cipher_list(conf->ssl.ctx,
386                                 (const char *) conf->ciphers.data)
387         == 0)
388     {
389         ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
390                       "SSL_CTX_set_cipher_list(\"%V\") failed",
391                       &conf->ciphers);
392     }
393 
394     if (conf->verify) {
395         if (ngx_ssl_client_certificate(cf, &conf->ssl,
396                                        &conf->client_certificate,
397                                        conf->verify_depth)
398             != NGX_OK)
399         {
400             return NGX_CONF_ERROR;
401         }
402     }
403 
404 #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
405 
406     if (conf->prefer_server_ciphers) {
407         SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
408     }
409 
410 #endif
411 
412     /* a temporary 512-bit RSA key is required for export versions of MSIE */
413     if (ngx_ssl_generate_rsa512_key(&conf->ssl) != NGX_OK) {
414         return NGX_CONF_ERROR;
415     }
416 
417     ngx_conf_merge_value(conf->builtin_session_cache,
418                          prev->builtin_session_cache, NGX_SSL_NO_SCACHE);
419 
420     if (conf->shm_zone == NULL) {
421         conf->shm_zone = prev->shm_zone;
422     }
423 
424     if (ngx_ssl_session_cache(&conf->ssl, &ngx_http_ssl_sess_id_ctx,
425                               conf->builtin_session_cache,
426                               conf->shm_zone, conf->session_timeout)
427         != NGX_OK)
428     {
429         return NGX_CONF_ERROR;
430     }
431 
432     return NGX_CONF_OK;
433 }
434 
435 
436 static char *
437 ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
438 {
439     ngx_http_ssl_srv_conf_t *sscf = conf;
440 
441     size_t       len;
442     ngx_str_t   *value, name, size;
443     ngx_int_t    n;
444     ngx_uint_t   i, j;
445 
446     value = cf->args->elts;
447 
448     for (i = 1; i < cf->args->nelts; i++) {
449 
450         if (ngx_strcmp(value[i].data, "off") == 0) {
451             sscf->builtin_session_cache = NGX_SSL_NO_SCACHE;
452             continue;
453         }
454 
455         if (ngx_strcmp(value[i].data, "builtin") == 0) {
456             sscf->builtin_session_cache = NGX_SSL_DFLT_BUILTIN_SCACHE;
457             continue;
458         }
459 
460         if (value[i].len > sizeof("builtin:") - 1
461             && ngx_strncmp(value[i].data, "builtin:", sizeof("builtin:") - 1)
462                == 0)
463         {
464             n = ngx_atoi(value[i].data + sizeof("builtin:") - 1,
465                          value[i].len - (sizeof("builtin:") - 1));
466 
467             if (n == NGX_ERROR) {
468                 goto invalid;
469             }
470 
471             sscf->builtin_session_cache = n;
472 
473             continue;
474         }
475 
476         if (value[i].len > sizeof("shared:") - 1
477             && ngx_strncmp(value[i].data, "shared:", sizeof("shared:") - 1)
478                == 0)
479         {
480             len = 0;
481 
482             for (j = sizeof("shared:") - 1; j < value[i].len; j++) {
483                 if (value[i].data[j] == ':') {
484                     break;
485                 }
486 
487                 len++;
488             }
489 
490             if (len == 0) {
491                 goto invalid;
492             }
493 
494             name.len = len;
495             name.data = value[i].data + sizeof("shared:") - 1;
496 
497             size.len = value[i].len - j - 1;
498             size.data = name.data + len + 1;
499 
500             n = ngx_parse_size(&size);
501 
502             if (n == NGX_ERROR) {
503                 goto invalid;
504             }
505 
506             if (n < (ngx_int_t) (8 * ngx_pagesize)) {
507                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
508                                    "session cache \"%V\" is too small",
509                                    &value[i]);
510 
511                 return NGX_CONF_ERROR;
512             }
513 
514             sscf->shm_zone = ngx_shared_memory_add(cf, &name, n,
515                                                    &ngx_http_ssl_module);
516             if (sscf->shm_zone == NULL) {
517                 return NGX_CONF_ERROR;
518             }
519 
520             continue;
521         }
522 
523         goto invalid;
524     }
525 
526     if (sscf->shm_zone && sscf->builtin_session_cache == NGX_CONF_UNSET) {
527         sscf->builtin_session_cache = NGX_SSL_NO_BUILTIN_SCACHE;
528     }
529 
530     return NGX_CONF_OK;
531 
532 invalid:
533 
534     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
535                        "invalid session cache \"%V\"", &value[i]);
536 
537     return NGX_CONF_ERROR;
538 }
539 
540 
541 #if !defined (SSL_OP_CIPHER_SERVER_PREFERENCE)
542 
543 static char *
544 ngx_http_ssl_nosupported(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
545 {
546     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
547                        "\"%V\" directive is available only in %s,",
548                        &cmd->name, cmd->post);
549 
550     return NGX_CONF_ERROR;
551 }
552 
553 #endif
554 

~ [ 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.