Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_event_openssl.c
Go to the documentation of this file.
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_event.h>
11 
12 
13 typedef struct {
14  ngx_uint_t engine; /* unsigned engine:1; */
16 
17 
18 static int ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store);
19 static void ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where,
20  int ret);
21 static void ngx_ssl_handshake_handler(ngx_event_t *ev);
22 static ngx_int_t ngx_ssl_handle_recv(ngx_connection_t *c, int n);
23 static void ngx_ssl_write_handler(ngx_event_t *wev);
24 static void ngx_ssl_read_handler(ngx_event_t *rev);
25 static void ngx_ssl_shutdown_handler(ngx_event_t *ev);
26 static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr,
27  ngx_err_t err, char *text);
28 static void ngx_ssl_clear_error(ngx_log_t *log);
29 
31 static int ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn,
32  ngx_ssl_session_t *sess);
33 static ngx_ssl_session_t *ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn,
34  u_char *id, int len, int *copy);
35 static void ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess);
36 static void ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache,
37  ngx_slab_pool_t *shpool, ngx_uint_t n);
38 static void ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp,
40 
41 static void *ngx_openssl_create_conf(ngx_cycle_t *cycle);
42 static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
43 static void ngx_openssl_exit(ngx_cycle_t *cycle);
44 
45 
46 static ngx_command_t ngx_openssl_commands[] = {
47 
48  { ngx_string("ssl_engine"),
50  ngx_openssl_engine,
51  0,
52  0,
53  NULL },
54 
56 };
57 
58 
59 static ngx_core_module_t ngx_openssl_module_ctx = {
60  ngx_string("openssl"),
61  ngx_openssl_create_conf,
62  NULL
63 };
64 
65 
68  &ngx_openssl_module_ctx, /* module context */
69  ngx_openssl_commands, /* module directives */
70  NGX_CORE_MODULE, /* module type */
71  NULL, /* init master */
72  NULL, /* init module */
73  NULL, /* init process */
74  NULL, /* init thread */
75  NULL, /* exit thread */
76  NULL, /* exit process */
77  ngx_openssl_exit, /* exit master */
79 };
80 
81 
87 
88 
91 {
92  OPENSSL_config(NULL);
93 
94  SSL_library_init();
95  SSL_load_error_strings();
96 
97  OpenSSL_add_all_algorithms();
98 
99 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
100 #ifndef SSL_OP_NO_COMPRESSION
101  {
102  /*
103  * Disable gzip compression in OpenSSL prior to 1.0.0 version,
104  * this saves about 522K per connection.
105  */
106  int n;
107  STACK_OF(SSL_COMP) *ssl_comp_methods;
108 
109  ssl_comp_methods = SSL_COMP_get_compression_methods();
110  n = sk_SSL_COMP_num(ssl_comp_methods);
111 
112  while (n--) {
113  (void) sk_SSL_COMP_pop(ssl_comp_methods);
114  }
115  }
116 #endif
117 #endif
118 
119  ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
120 
121  if (ngx_ssl_connection_index == -1) {
122  ngx_ssl_error(NGX_LOG_ALERT, log, 0, "SSL_get_ex_new_index() failed");
123  return NGX_ERROR;
124  }
125 
126  ngx_ssl_server_conf_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
127  NULL);
128  if (ngx_ssl_server_conf_index == -1) {
130  "SSL_CTX_get_ex_new_index() failed");
131  return NGX_ERROR;
132  }
133 
134  ngx_ssl_session_cache_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
135  NULL);
136  if (ngx_ssl_session_cache_index == -1) {
138  "SSL_CTX_get_ex_new_index() failed");
139  return NGX_ERROR;
140  }
141 
142  ngx_ssl_certificate_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
143  NULL);
144  if (ngx_ssl_certificate_index == -1) {
146  "SSL_CTX_get_ex_new_index() failed");
147  return NGX_ERROR;
148  }
149 
150  ngx_ssl_stapling_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
151  NULL);
152  if (ngx_ssl_stapling_index == -1) {
154  "SSL_CTX_get_ex_new_index() failed");
155  return NGX_ERROR;
156  }
157 
158  return NGX_OK;
159 }
160 
161 
162 ngx_int_t
163 ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data)
164 {
165  ssl->ctx = SSL_CTX_new(SSLv23_method());
166 
167  if (ssl->ctx == NULL) {
168  ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_new() failed");
169  return NGX_ERROR;
170  }
171 
172  if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_server_conf_index, data) == 0) {
174  "SSL_CTX_set_ex_data() failed");
175  return NGX_ERROR;
176  }
177 
178  /* client side options */
179 
180  SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_SESS_ID_BUG);
181  SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_CHALLENGE_BUG);
182 
183  /* server side options */
184 
185  SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG);
186  SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER);
187 
188  /* this option allow a potential SSL 2.0 rollback (CAN-2005-2969) */
189  SSL_CTX_set_options(ssl->ctx, SSL_OP_MSIE_SSLV2_RSA_PADDING);
190 
191  SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLEAY_080_CLIENT_DH_BUG);
192  SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_D5_BUG);
193  SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_BLOCK_PADDING_BUG);
194 
195  SSL_CTX_set_options(ssl->ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
196 
197  SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_DH_USE);
198 
199  if (!(protocols & NGX_SSL_SSLv2)) {
200  SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_SSLv2);
201  }
202  if (!(protocols & NGX_SSL_SSLv3)) {
203  SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_SSLv3);
204  }
205  if (!(protocols & NGX_SSL_TLSv1)) {
206  SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1);
207  }
208 #ifdef SSL_OP_NO_TLSv1_1
209  if (!(protocols & NGX_SSL_TLSv1_1)) {
210  SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1_1);
211  }
212 #endif
213 #ifdef SSL_OP_NO_TLSv1_2
214  if (!(protocols & NGX_SSL_TLSv1_2)) {
215  SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1_2);
216  }
217 #endif
218 
219 #ifdef SSL_OP_NO_COMPRESSION
220  SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_COMPRESSION);
221 #endif
222 
223 #ifdef SSL_MODE_RELEASE_BUFFERS
224  SSL_CTX_set_mode(ssl->ctx, SSL_MODE_RELEASE_BUFFERS);
225 #endif
226 
227  SSL_CTX_set_read_ahead(ssl->ctx, 1);
228 
229  SSL_CTX_set_info_callback(ssl->ctx, ngx_ssl_info_callback);
230 
231  return NGX_OK;
232 }
233 
234 
235 ngx_int_t
237  ngx_str_t *key)
238 {
239  BIO *bio;
240  X509 *x509;
241  u_long n;
242 
243  if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
244  return NGX_ERROR;
245  }
246 
247  /*
248  * we can't use SSL_CTX_use_certificate_chain_file() as it doesn't
249  * allow to access certificate later from SSL_CTX, so we reimplement
250  * it here
251  */
252 
253  bio = BIO_new_file((char *) cert->data, "r");
254  if (bio == NULL) {
256  "BIO_new_file(\"%s\") failed", cert->data);
257  return NGX_ERROR;
258  }
259 
260  x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL);
261  if (x509 == NULL) {
263  "PEM_read_bio_X509_AUX(\"%s\") failed", cert->data);
264  BIO_free(bio);
265  return NGX_ERROR;
266  }
267 
268  if (SSL_CTX_use_certificate(ssl->ctx, x509) == 0) {
270  "SSL_CTX_use_certificate(\"%s\") failed", cert->data);
271  X509_free(x509);
272  BIO_free(bio);
273  return NGX_ERROR;
274  }
275 
276  if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, x509)
277  == 0)
278  {
280  "SSL_CTX_set_ex_data() failed");
281  return NGX_ERROR;
282  }
283 
284  X509_free(x509);
285 
286  /* read rest of the chain */
287 
288  for ( ;; ) {
289 
290  x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
291  if (x509 == NULL) {
292  n = ERR_peek_last_error();
293 
294  if (ERR_GET_LIB(n) == ERR_LIB_PEM
295  && ERR_GET_REASON(n) == PEM_R_NO_START_LINE)
296  {
297  /* end of file */
298  ERR_clear_error();
299  break;
300  }
301 
302  /* some real error */
303 
305  "PEM_read_bio_X509(\"%s\") failed", cert->data);
306  BIO_free(bio);
307  return NGX_ERROR;
308  }
309 
310  if (SSL_CTX_add_extra_chain_cert(ssl->ctx, x509) == 0) {
312  "SSL_CTX_add_extra_chain_cert(\"%s\") failed",
313  cert->data);
314  X509_free(x509);
315  BIO_free(bio);
316  return NGX_ERROR;
317  }
318  }
319 
320  BIO_free(bio);
321 
322  if (ngx_conf_full_name(cf->cycle, key, 1) != NGX_OK) {
323  return NGX_ERROR;
324  }
325 
326  if (SSL_CTX_use_PrivateKey_file(ssl->ctx, (char *) key->data,
327  SSL_FILETYPE_PEM)
328  == 0)
329  {
331  "SSL_CTX_use_PrivateKey_file(\"%s\") failed", key->data);
332  return NGX_ERROR;
333  }
334 
335  return NGX_OK;
336 }
337 
338 
339 ngx_int_t
341  ngx_int_t depth)
342 {
343  STACK_OF(X509_NAME) *list;
344 
345  SSL_CTX_set_verify(ssl->ctx, SSL_VERIFY_PEER, ngx_http_ssl_verify_callback);
346 
347  SSL_CTX_set_verify_depth(ssl->ctx, depth);
348 
349  if (cert->len == 0) {
350  return NGX_OK;
351  }
352 
353  if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
354  return NGX_ERROR;
355  }
356 
357  if (SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL)
358  == 0)
359  {
361  "SSL_CTX_load_verify_locations(\"%s\") failed",
362  cert->data);
363  return NGX_ERROR;
364  }
365 
366  list = SSL_load_client_CA_file((char *) cert->data);
367 
368  if (list == NULL) {
370  "SSL_load_client_CA_file(\"%s\") failed", cert->data);
371  return NGX_ERROR;
372  }
373 
374  /*
375  * before 0.9.7h and 0.9.8 SSL_load_client_CA_file()
376  * always leaved an error in the error queue
377  */
378 
379  ERR_clear_error();
380 
381  SSL_CTX_set_client_CA_list(ssl->ctx, list);
382 
383  return NGX_OK;
384 }
385 
386 
387 ngx_int_t
389  ngx_int_t depth)
390 {
391  SSL_CTX_set_verify_depth(ssl->ctx, depth);
392 
393  if (cert->len == 0) {
394  return NGX_OK;
395  }
396 
397  if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
398  return NGX_ERROR;
399  }
400 
401  if (SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL)
402  == 0)
403  {
405  "SSL_CTX_load_verify_locations(\"%s\") failed",
406  cert->data);
407  return NGX_ERROR;
408  }
409 
410  return NGX_OK;
411 }
412 
413 
414 ngx_int_t
416 {
417  X509_STORE *store;
418  X509_LOOKUP *lookup;
419 
420  if (crl->len == 0) {
421  return NGX_OK;
422  }
423 
424  if (ngx_conf_full_name(cf->cycle, crl, 1) != NGX_OK) {
425  return NGX_ERROR;
426  }
427 
428  store = SSL_CTX_get_cert_store(ssl->ctx);
429 
430  if (store == NULL) {
432  "SSL_CTX_get_cert_store() failed");
433  return NGX_ERROR;
434  }
435 
436  lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
437 
438  if (lookup == NULL) {
440  "X509_STORE_add_lookup() failed");
441  return NGX_ERROR;
442  }
443 
444  if (X509_LOOKUP_load_file(lookup, (char *) crl->data, X509_FILETYPE_PEM)
445  == 0)
446  {
448  "X509_LOOKUP_load_file(\"%s\") failed", crl->data);
449  return NGX_ERROR;
450  }
451 
452  X509_STORE_set_flags(store,
453  X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
454 
455  return NGX_OK;
456 }
457 
458 
459 static int
460 ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store)
461 {
462 #if (NGX_DEBUG)
463  char *subject, *issuer;
464  int err, depth;
465  X509 *cert;
466  X509_NAME *sname, *iname;
467  ngx_connection_t *c;
468  ngx_ssl_conn_t *ssl_conn;
469 
470  ssl_conn = X509_STORE_CTX_get_ex_data(x509_store,
471  SSL_get_ex_data_X509_STORE_CTX_idx());
472 
473  c = ngx_ssl_get_connection(ssl_conn);
474 
475  cert = X509_STORE_CTX_get_current_cert(x509_store);
476  err = X509_STORE_CTX_get_error(x509_store);
477  depth = X509_STORE_CTX_get_error_depth(x509_store);
478 
479  sname = X509_get_subject_name(cert);
480  subject = sname ? X509_NAME_oneline(sname, NULL, 0) : "(none)";
481 
482  iname = X509_get_issuer_name(cert);
483  issuer = iname ? X509_NAME_oneline(iname, NULL, 0) : "(none)";
484 
486  "verify:%d, error:%d, depth:%d, "
487  "subject:\"%s\",issuer: \"%s\"",
488  ok, err, depth, subject, issuer);
489 
490  if (sname) {
491  OPENSSL_free(subject);
492  }
493 
494  if (iname) {
495  OPENSSL_free(issuer);
496  }
497 #endif
498 
499  return 1;
500 }
501 
502 
503 static void
504 ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, int ret)
505 {
506  ngx_connection_t *c;
507 
508  if (where & SSL_CB_HANDSHAKE_START) {
509  c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
510 
511  if (c->ssl->handshaked) {
512  c->ssl->renegotiation = 1;
513  ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL renegotiation");
514  }
515  }
516 }
517 
518 
519 RSA *
520 ngx_ssl_rsa512_key_callback(SSL *ssl, int is_export, int key_length)
521 {
522  static RSA *key;
523 
524  if (key_length == 512) {
525  if (key == NULL) {
526  key = RSA_generate_key(512, RSA_F4, NULL, NULL);
527  }
528  }
529 
530  return key;
531 }
532 
533 
534 ngx_int_t
536 {
537  DH *dh;
538  BIO *bio;
539 
540  /*
541  * -----BEGIN DH PARAMETERS-----
542  * MIGHAoGBALu8LcrYRnSQfEP89YDpz9vZWKP1aLQtSwju1OsPs1BMbAMCducQgAxc
543  * y7qokiYUxb7spWWl/fHSh6K8BJvmd4Bg6RqSp1fjBI9osHb302zI8pul34HcLKcl
544  * 7OZicMyaUDXYzs7vnqAnSmOrHlj6/UmI0PZdFGdX2gcd8EXP4WubAgEC
545  * -----END DH PARAMETERS-----
546  */
547 
548  static unsigned char dh1024_p[] = {
549  0xBB, 0xBC, 0x2D, 0xCA, 0xD8, 0x46, 0x74, 0x90, 0x7C, 0x43, 0xFC, 0xF5,
550  0x80, 0xE9, 0xCF, 0xDB, 0xD9, 0x58, 0xA3, 0xF5, 0x68, 0xB4, 0x2D, 0x4B,
551  0x08, 0xEE, 0xD4, 0xEB, 0x0F, 0xB3, 0x50, 0x4C, 0x6C, 0x03, 0x02, 0x76,
552  0xE7, 0x10, 0x80, 0x0C, 0x5C, 0xCB, 0xBA, 0xA8, 0x92, 0x26, 0x14, 0xC5,
553  0xBE, 0xEC, 0xA5, 0x65, 0xA5, 0xFD, 0xF1, 0xD2, 0x87, 0xA2, 0xBC, 0x04,
554  0x9B, 0xE6, 0x77, 0x80, 0x60, 0xE9, 0x1A, 0x92, 0xA7, 0x57, 0xE3, 0x04,
555  0x8F, 0x68, 0xB0, 0x76, 0xF7, 0xD3, 0x6C, 0xC8, 0xF2, 0x9B, 0xA5, 0xDF,
556  0x81, 0xDC, 0x2C, 0xA7, 0x25, 0xEC, 0xE6, 0x62, 0x70, 0xCC, 0x9A, 0x50,
557  0x35, 0xD8, 0xCE, 0xCE, 0xEF, 0x9E, 0xA0, 0x27, 0x4A, 0x63, 0xAB, 0x1E,
558  0x58, 0xFA, 0xFD, 0x49, 0x88, 0xD0, 0xF6, 0x5D, 0x14, 0x67, 0x57, 0xDA,
559  0x07, 0x1D, 0xF0, 0x45, 0xCF, 0xE1, 0x6B, 0x9B
560  };
561 
562  static unsigned char dh1024_g[] = { 0x02 };
563 
564 
565  if (file->len == 0) {
566 
567  dh = DH_new();
568  if (dh == NULL) {
569  ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "DH_new() failed");
570  return NGX_ERROR;
571  }
572 
573  dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
574  dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
575 
576  if (dh->p == NULL || dh->g == NULL) {
577  ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "BN_bin2bn() failed");
578  DH_free(dh);
579  return NGX_ERROR;
580  }
581 
582  SSL_CTX_set_tmp_dh(ssl->ctx, dh);
583 
584  DH_free(dh);
585 
586  return NGX_OK;
587  }
588 
589  if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) {
590  return NGX_ERROR;
591  }
592 
593  bio = BIO_new_file((char *) file->data, "r");
594  if (bio == NULL) {
596  "BIO_new_file(\"%s\") failed", file->data);
597  return NGX_ERROR;
598  }
599 
600  dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
601  if (dh == NULL) {
603  "PEM_read_bio_DHparams(\"%s\") failed", file->data);
604  BIO_free(bio);
605  return NGX_ERROR;
606  }
607 
608  SSL_CTX_set_tmp_dh(ssl->ctx, dh);
609 
610  DH_free(dh);
611  BIO_free(bio);
612 
613  return NGX_OK;
614 }
615 
616 
617 ngx_int_t
619 {
620 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
621 #ifndef OPENSSL_NO_ECDH
622  int nid;
623  EC_KEY *ecdh;
624 
625  /*
626  * Elliptic-Curve Diffie-Hellman parameters are either "named curves"
627  * from RFC 4492 section 5.1.1, or explicitly described curves over
628  * binary fields. OpenSSL only supports the "named curves", which provide
629  * maximum interoperability.
630  */
631 
632  nid = OBJ_sn2nid((const char *) name->data);
633  if (nid == 0) {
635  "Unknown curve name \"%s\"", name->data);
636  return NGX_ERROR;
637  }
638 
639  ecdh = EC_KEY_new_by_curve_name(nid);
640  if (ecdh == NULL) {
642  "Unable to create curve \"%s\"", name->data);
643  return NGX_ERROR;
644  }
645 
646  SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_ECDH_USE);
647 
648  SSL_CTX_set_tmp_ecdh(ssl->ctx, ecdh);
649 
650  EC_KEY_free(ecdh);
651 #endif
652 #endif
653 
654  return NGX_OK;
655 }
656 
657 
658 ngx_int_t
660 {
662 
663  sc = ngx_pcalloc(c->pool, sizeof(ngx_ssl_connection_t));
664  if (sc == NULL) {
665  return NGX_ERROR;
666  }
667 
668  sc->buffer = ((flags & NGX_SSL_BUFFER) != 0);
669 
670  sc->connection = SSL_new(ssl->ctx);
671 
672  if (sc->connection == NULL) {
673  ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_new() failed");
674  return NGX_ERROR;
675  }
676 
677  if (SSL_set_fd(sc->connection, c->fd) == 0) {
678  ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_fd() failed");
679  return NGX_ERROR;
680  }
681 
682  if (flags & NGX_SSL_CLIENT) {
683  SSL_set_connect_state(sc->connection);
684 
685  } else {
686  SSL_set_accept_state(sc->connection);
687  }
688 
689  if (SSL_set_ex_data(sc->connection, ngx_ssl_connection_index, c) == 0) {
690  ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_ex_data() failed");
691  return NGX_ERROR;
692  }
693 
694  c->ssl = sc;
695 
696  return NGX_OK;
697 }
698 
699 
700 ngx_int_t
702 {
703  if (session) {
704  if (SSL_set_session(c->ssl->connection, session) == 0) {
705  ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_session() failed");
706  return NGX_ERROR;
707  }
708  }
709 
710  return NGX_OK;
711 }
712 
713 
714 ngx_int_t
716 {
717  int n, sslerr;
718  ngx_err_t err;
719 
720  ngx_ssl_clear_error(c->log);
721 
722  n = SSL_do_handshake(c->ssl->connection);
723 
724  ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n);
725 
726  if (n == 1) {
727 
728  if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
729  return NGX_ERROR;
730  }
731 
732  if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
733  return NGX_ERROR;
734  }
735 
736 #if (NGX_DEBUG)
737  {
738  char buf[129], *s, *d;
739 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
740  const
741 #endif
742  SSL_CIPHER *cipher;
743 
744  cipher = SSL_get_current_cipher(c->ssl->connection);
745 
746  if (cipher) {
747  SSL_CIPHER_description(cipher, &buf[1], 128);
748 
749  for (s = &buf[1], d = buf; *s; s++) {
750  if (*s == ' ' && *d == ' ') {
751  continue;
752  }
753 
754  if (*s == LF || *s == CR) {
755  continue;
756  }
757 
758  *++d = *s;
759  }
760 
761  if (*d != ' ') {
762  d++;
763  }
764 
765  *d = '\0';
766 
768  "SSL: %s, cipher: \"%s\"",
769  SSL_get_version(c->ssl->connection), &buf[1]);
770 
771  if (SSL_session_reused(c->ssl->connection)) {
773  "SSL reused session");
774  }
775 
776  } else {
778  "SSL no shared ciphers");
779  }
780  }
781 #endif
782 
783  c->ssl->handshaked = 1;
784 
785  c->recv = ngx_ssl_recv;
786  c->send = ngx_ssl_write;
789 
790  /* initial handshake done, disable renegotiation (CVE-2009-3555) */
791  if (c->ssl->connection->s3) {
792  c->ssl->connection->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
793  }
794 
795  return NGX_OK;
796  }
797 
798  sslerr = SSL_get_error(c->ssl->connection, n);
799 
800  ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
801 
802  if (sslerr == SSL_ERROR_WANT_READ) {
803  c->read->ready = 0;
804  c->read->handler = ngx_ssl_handshake_handler;
805  c->write->handler = ngx_ssl_handshake_handler;
806 
807  if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
808  return NGX_ERROR;
809  }
810 
811  if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
812  return NGX_ERROR;
813  }
814 
815  return NGX_AGAIN;
816  }
817 
818  if (sslerr == SSL_ERROR_WANT_WRITE) {
819  c->write->ready = 0;
820  c->read->handler = ngx_ssl_handshake_handler;
821  c->write->handler = ngx_ssl_handshake_handler;
822 
823  if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
824  return NGX_ERROR;
825  }
826 
827  if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
828  return NGX_ERROR;
829  }
830 
831  return NGX_AGAIN;
832  }
833 
834  err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
835 
836  c->ssl->no_wait_shutdown = 1;
837  c->ssl->no_send_shutdown = 1;
838  c->read->eof = 1;
839 
840  if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
841  ngx_log_error(NGX_LOG_INFO, c->log, err,
842  "peer closed connection in SSL handshake");
843 
844  return NGX_ERROR;
845  }
846 
847  c->read->error = 1;
848 
849  ngx_ssl_connection_error(c, sslerr, err, "SSL_do_handshake() failed");
850 
851  return NGX_ERROR;
852 }
853 
854 
855 static void
856 ngx_ssl_handshake_handler(ngx_event_t *ev)
857 {
858  ngx_connection_t *c;
859 
860  c = ev->data;
861 
863  "SSL handshake handler: %d", ev->write);
864 
865  if (ev->timedout) {
866  c->ssl->handler(c);
867  return;
868  }
869 
870  if (ngx_ssl_handshake(c) == NGX_AGAIN) {
871  return;
872  }
873 
874  c->ssl->handler(c);
875 }
876 
877 
878 ssize_t
880 {
881  u_char *last;
882  ssize_t n, bytes;
883  ngx_buf_t *b;
884 
885  bytes = 0;
886 
887  b = cl->buf;
888  last = b->last;
889 
890  for ( ;; ) {
891 
892  n = ngx_ssl_recv(c, last, b->end - last);
893 
894  if (n > 0) {
895  last += n;
896  bytes += n;
897 
898  if (last == b->end) {
899  cl = cl->next;
900 
901  if (cl == NULL) {
902  return bytes;
903  }
904 
905  b = cl->buf;
906  last = b->last;
907  }
908 
909  continue;
910  }
911 
912  if (bytes) {
913 
914  if (n == 0 || n == NGX_ERROR) {
915  c->read->ready = 1;
916  }
917 
918  return bytes;
919  }
920 
921  return n;
922  }
923 }
924 
925 
926 ssize_t
927 ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size)
928 {
929  int n, bytes;
930 
931  if (c->ssl->last == NGX_ERROR) {
932  c->read->error = 1;
933  return NGX_ERROR;
934  }
935 
936  if (c->ssl->last == NGX_DONE) {
937  c->read->ready = 0;
938  c->read->eof = 1;
939  return 0;
940  }
941 
942  bytes = 0;
943 
944  ngx_ssl_clear_error(c->log);
945 
946  /*
947  * SSL_read() may return data in parts, so try to read
948  * until SSL_read() would return no data
949  */
950 
951  for ( ;; ) {
952 
953  n = SSL_read(c->ssl->connection, buf, size);
954 
955  ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_read: %d", n);
956 
957  if (n > 0) {
958  bytes += n;
959  }
960 
961  c->ssl->last = ngx_ssl_handle_recv(c, n);
962 
963  if (c->ssl->last == NGX_OK) {
964 
965  size -= n;
966 
967  if (size == 0) {
968  return bytes;
969  }
970 
971  buf += n;
972 
973  continue;
974  }
975 
976  if (bytes) {
977  return bytes;
978  }
979 
980  switch (c->ssl->last) {
981 
982  case NGX_DONE:
983  c->read->ready = 0;
984  c->read->eof = 1;
985  return 0;
986 
987  case NGX_ERROR:
988  c->read->error = 1;
989 
990  /* fall through */
991 
992  case NGX_AGAIN:
993  return c->ssl->last;
994  }
995  }
996 }
997 
998 
999 static ngx_int_t
1000 ngx_ssl_handle_recv(ngx_connection_t *c, int n)
1001 {
1002  int sslerr;
1003  ngx_err_t err;
1004 
1005  if (c->ssl->renegotiation) {
1006  /*
1007  * disable renegotiation (CVE-2009-3555):
1008  * OpenSSL (at least up to 0.9.8l) does not handle disabled
1009  * renegotiation gracefully, so drop connection here
1010  */
1011 
1012  ngx_log_error(NGX_LOG_NOTICE, c->log, 0, "SSL renegotiation disabled");
1013 
1014  while (ERR_peek_error()) {
1016  "ignoring stale global SSL error");
1017  }
1018 
1019  ERR_clear_error();
1020 
1021  c->ssl->no_wait_shutdown = 1;
1022  c->ssl->no_send_shutdown = 1;
1023 
1024  return NGX_ERROR;
1025  }
1026 
1027  if (n > 0) {
1028 
1029  if (c->ssl->saved_write_handler) {
1030 
1031  c->write->handler = c->ssl->saved_write_handler;
1032  c->ssl->saved_write_handler = NULL;
1033  c->write->ready = 1;
1034 
1035  if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
1036  return NGX_ERROR;
1037  }
1038 
1040  }
1041 
1042  return NGX_OK;
1043  }
1044 
1045  sslerr = SSL_get_error(c->ssl->connection, n);
1046 
1047  err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
1048 
1049  ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
1050 
1051  if (sslerr == SSL_ERROR_WANT_READ) {
1052  c->read->ready = 0;
1053  return NGX_AGAIN;
1054  }
1055 
1056  if (sslerr == SSL_ERROR_WANT_WRITE) {
1057 
1059  "peer started SSL renegotiation");
1060 
1061  c->write->ready = 0;
1062 
1063  if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
1064  return NGX_ERROR;
1065  }
1066 
1067  /*
1068  * we do not set the timer because there is already the read event timer
1069  */
1070 
1071  if (c->ssl->saved_write_handler == NULL) {
1072  c->ssl->saved_write_handler = c->write->handler;
1073  c->write->handler = ngx_ssl_write_handler;
1074  }
1075 
1076  return NGX_AGAIN;
1077  }
1078 
1079  c->ssl->no_wait_shutdown = 1;
1080  c->ssl->no_send_shutdown = 1;
1081 
1082  if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
1084  "peer shutdown SSL cleanly");
1085  return NGX_DONE;
1086  }
1087 
1088  ngx_ssl_connection_error(c, sslerr, err, "SSL_read() failed");
1089 
1090  return NGX_ERROR;
1091 }
1092 
1093 
1094 static void
1095 ngx_ssl_write_handler(ngx_event_t *wev)
1096 {
1097  ngx_connection_t *c;
1098 
1099  c = wev->data;
1100 
1101  c->read->handler(c->read);
1102 }
1103 
1104 
1105 /*
1106  * OpenSSL has no SSL_writev() so we copy several bufs into our 16K buffer
1107  * before the SSL_write() call to decrease a SSL overhead.
1108  *
1109  * Besides for protocols such as HTTP it is possible to always buffer
1110  * the output to decrease a SSL overhead some more.
1111  */
1112 
1113 ngx_chain_t *
1115 {
1116  int n;
1117  ngx_uint_t flush;
1118  ssize_t send, size;
1119  ngx_buf_t *buf;
1120 
1121  if (!c->ssl->buffer) {
1122 
1123  while (in) {
1124  if (ngx_buf_special(in->buf)) {
1125  in = in->next;
1126  continue;
1127  }
1128 
1129  n = ngx_ssl_write(c, in->buf->pos, in->buf->last - in->buf->pos);
1130 
1131  if (n == NGX_ERROR) {
1132  return NGX_CHAIN_ERROR;
1133  }
1134 
1135  if (n == NGX_AGAIN) {
1136  return in;
1137  }
1138 
1139  in->buf->pos += n;
1140  c->sent += n;
1141 
1142  if (in->buf->pos == in->buf->last) {
1143  in = in->next;
1144  }
1145  }
1146 
1147  return in;
1148  }
1149 
1150 
1151  /* the maximum limit size is the maximum int32_t value - the page size */
1152 
1153  if (limit == 0 || limit > (off_t) (NGX_MAX_INT32_VALUE - ngx_pagesize)) {
1155  }
1156 
1157  buf = c->ssl->buf;
1158 
1159  if (buf == NULL) {
1161  if (buf == NULL) {
1162  return NGX_CHAIN_ERROR;
1163  }
1164 
1165  c->ssl->buf = buf;
1166  }
1167 
1168  if (buf->start == NULL) {
1169  buf->start = ngx_palloc(c->pool, NGX_SSL_BUFSIZE);
1170  if (buf->start == NULL) {
1171  return NGX_CHAIN_ERROR;
1172  }
1173 
1174  buf->pos = buf->start;
1175  buf->last = buf->start;
1176  buf->end = buf->start + NGX_SSL_BUFSIZE;
1177  }
1178 
1179  send = buf->last - buf->pos;
1180  flush = (in == NULL) ? 1 : buf->flush;
1181 
1182  for ( ;; ) {
1183 
1184  while (in && buf->last < buf->end && send < limit) {
1185  if (in->buf->last_buf || in->buf->flush) {
1186  flush = 1;
1187  }
1188 
1189  if (ngx_buf_special(in->buf)) {
1190  in = in->next;
1191  continue;
1192  }
1193 
1194  size = in->buf->last - in->buf->pos;
1195 
1196  if (size > buf->end - buf->last) {
1197  size = buf->end - buf->last;
1198  }
1199 
1200  if (send + size > limit) {
1201  size = (ssize_t) (limit - send);
1202  }
1203 
1205  "SSL buf copy: %d", size);
1206 
1207  ngx_memcpy(buf->last, in->buf->pos, size);
1208 
1209  buf->last += size;
1210  in->buf->pos += size;
1211  send += size;
1212 
1213  if (in->buf->pos == in->buf->last) {
1214  in = in->next;
1215  }
1216  }
1217 
1218  if (!flush && send < limit && buf->last < buf->end) {
1219  break;
1220  }
1221 
1222  size = buf->last - buf->pos;
1223 
1224  if (size == 0) {
1225  buf->flush = 0;
1226  c->buffered &= ~NGX_SSL_BUFFERED;
1227  return in;
1228  }
1229 
1230  n = ngx_ssl_write(c, buf->pos, size);
1231 
1232  if (n == NGX_ERROR) {
1233  return NGX_CHAIN_ERROR;
1234  }
1235 
1236  if (n == NGX_AGAIN) {
1237  break;
1238  }
1239 
1240  buf->pos += n;
1241  c->sent += n;
1242 
1243  if (n < size) {
1244  break;
1245  }
1246 
1247  flush = 0;
1248 
1249  buf->pos = buf->start;
1250  buf->last = buf->start;
1251 
1252  if (in == NULL || send == limit) {
1253  break;
1254  }
1255  }
1256 
1257  buf->flush = flush;
1258 
1259  if (buf->pos < buf->last) {
1260  c->buffered |= NGX_SSL_BUFFERED;
1261 
1262  } else {
1263  c->buffered &= ~NGX_SSL_BUFFERED;
1264  }
1265 
1266  return in;
1267 }
1268 
1269 
1270 ssize_t
1271 ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size)
1272 {
1273  int n, sslerr;
1274  ngx_err_t err;
1275 
1276  ngx_ssl_clear_error(c->log);
1277 
1278  ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL to write: %d", size);
1279 
1280  n = SSL_write(c->ssl->connection, data, size);
1281 
1282  ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_write: %d", n);
1283 
1284  if (n > 0) {
1285 
1286  if (c->ssl->saved_read_handler) {
1287 
1288  c->read->handler = c->ssl->saved_read_handler;
1289  c->ssl->saved_read_handler = NULL;
1290  c->read->ready = 1;
1291 
1292  if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1293  return NGX_ERROR;
1294  }
1295 
1297  }
1298 
1299  return n;
1300  }
1301 
1302  sslerr = SSL_get_error(c->ssl->connection, n);
1303 
1304  err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
1305 
1306  ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
1307 
1308  if (sslerr == SSL_ERROR_WANT_WRITE) {
1309  c->write->ready = 0;
1310  return NGX_AGAIN;
1311  }
1312 
1313  if (sslerr == SSL_ERROR_WANT_READ) {
1314 
1316  "peer started SSL renegotiation");
1317 
1318  c->read->ready = 0;
1319 
1320  if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1321  return NGX_ERROR;
1322  }
1323 
1324  /*
1325  * we do not set the timer because there is already
1326  * the write event timer
1327  */
1328 
1329  if (c->ssl->saved_read_handler == NULL) {
1330  c->ssl->saved_read_handler = c->read->handler;
1331  c->read->handler = ngx_ssl_read_handler;
1332  }
1333 
1334  return NGX_AGAIN;
1335  }
1336 
1337  c->ssl->no_wait_shutdown = 1;
1338  c->ssl->no_send_shutdown = 1;
1339  c->write->error = 1;
1340 
1341  ngx_ssl_connection_error(c, sslerr, err, "SSL_write() failed");
1342 
1343  return NGX_ERROR;
1344 }
1345 
1346 
1347 static void
1348 ngx_ssl_read_handler(ngx_event_t *rev)
1349 {
1350  ngx_connection_t *c;
1351 
1352  c = rev->data;
1353 
1354  c->write->handler(c->write);
1355 }
1356 
1357 
1358 void
1360 {
1361  if (c->ssl->buf && c->ssl->buf->start) {
1362  if (ngx_pfree(c->pool, c->ssl->buf->start) == NGX_OK) {
1363  c->ssl->buf->start = NULL;
1364  }
1365  }
1366 }
1367 
1368 
1369 ngx_int_t
1371 {
1372  int n, sslerr, mode;
1373  ngx_err_t err;
1374 
1375  if (c->timedout) {
1376  mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN;
1377  SSL_set_quiet_shutdown(c->ssl->connection, 1);
1378 
1379  } else {
1380  mode = SSL_get_shutdown(c->ssl->connection);
1381 
1382  if (c->ssl->no_wait_shutdown) {
1383  mode |= SSL_RECEIVED_SHUTDOWN;
1384  }
1385 
1386  if (c->ssl->no_send_shutdown) {
1387  mode |= SSL_SENT_SHUTDOWN;
1388  }
1389 
1390  if (c->ssl->no_wait_shutdown && c->ssl->no_send_shutdown) {
1391  SSL_set_quiet_shutdown(c->ssl->connection, 1);
1392  }
1393  }
1394 
1395  SSL_set_shutdown(c->ssl->connection, mode);
1396 
1397  ngx_ssl_clear_error(c->log);
1398 
1399  n = SSL_shutdown(c->ssl->connection);
1400 
1401  ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n);
1402 
1403  sslerr = 0;
1404 
1405  /* SSL_shutdown() never returns -1, on error it returns 0 */
1406 
1407  if (n != 1 && ERR_peek_error()) {
1408  sslerr = SSL_get_error(c->ssl->connection, n);
1409 
1411  "SSL_get_error: %d", sslerr);
1412  }
1413 
1414  if (n == 1 || sslerr == 0 || sslerr == SSL_ERROR_ZERO_RETURN) {
1415  SSL_free(c->ssl->connection);
1416  c->ssl = NULL;
1417 
1418  return NGX_OK;
1419  }
1420 
1421  if (sslerr == SSL_ERROR_WANT_READ || sslerr == SSL_ERROR_WANT_WRITE) {
1422  c->read->handler = ngx_ssl_shutdown_handler;
1423  c->write->handler = ngx_ssl_shutdown_handler;
1424 
1425  if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1426  return NGX_ERROR;
1427  }
1428 
1429  if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
1430  return NGX_ERROR;
1431  }
1432 
1433  if (sslerr == SSL_ERROR_WANT_READ) {
1434  ngx_add_timer(c->read, 30000);
1435  }
1436 
1437  return NGX_AGAIN;
1438  }
1439 
1440  err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
1441 
1442  ngx_ssl_connection_error(c, sslerr, err, "SSL_shutdown() failed");
1443 
1444  SSL_free(c->ssl->connection);
1445  c->ssl = NULL;
1446 
1447  return NGX_ERROR;
1448 }
1449 
1450 
1451 static void
1452 ngx_ssl_shutdown_handler(ngx_event_t *ev)
1453 {
1454  ngx_connection_t *c;
1455  ngx_connection_handler_pt handler;
1456 
1457  c = ev->data;
1458  handler = c->ssl->handler;
1459 
1460  if (ev->timedout) {
1461  c->timedout = 1;
1462  }
1463 
1464  ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "SSL shutdown handler");
1465 
1466  if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
1467  return;
1468  }
1469 
1470  handler(c);
1471 }
1472 
1473 
1474 static void
1475 ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
1476  char *text)
1477 {
1478  int n;
1479  ngx_uint_t level;
1480 
1481  level = NGX_LOG_CRIT;
1482 
1483  if (sslerr == SSL_ERROR_SYSCALL) {
1484 
1485  if (err == NGX_ECONNRESET
1486  || err == NGX_EPIPE
1487  || err == NGX_ENOTCONN
1488  || err == NGX_ETIMEDOUT
1489  || err == NGX_ECONNREFUSED
1490  || err == NGX_ENETDOWN
1491  || err == NGX_ENETUNREACH
1492  || err == NGX_EHOSTDOWN
1493  || err == NGX_EHOSTUNREACH)
1494  {
1495  switch (c->log_error) {
1496 
1498  case NGX_ERROR_INFO:
1499  level = NGX_LOG_INFO;
1500  break;
1501 
1502  case NGX_ERROR_ERR:
1503  level = NGX_LOG_ERR;
1504  break;
1505 
1506  default:
1507  break;
1508  }
1509  }
1510 
1511  } else if (sslerr == SSL_ERROR_SSL) {
1512 
1513  n = ERR_GET_REASON(ERR_peek_error());
1514 
1515  /* handshake failures */
1516  if (n == SSL_R_BAD_CHANGE_CIPHER_SPEC /* 103 */
1517  || n == SSL_R_BLOCK_CIPHER_PAD_IS_WRONG /* 129 */
1518  || n == SSL_R_DIGEST_CHECK_FAILED /* 149 */
1519  || n == SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST /* 151 */
1520  || n == SSL_R_EXCESSIVE_MESSAGE_SIZE /* 152 */
1521  || n == SSL_R_LENGTH_MISMATCH /* 159 */
1522  || n == SSL_R_NO_CIPHERS_PASSED /* 182 */
1523  || n == SSL_R_NO_CIPHERS_SPECIFIED /* 183 */
1524  || n == SSL_R_NO_COMPRESSION_SPECIFIED /* 187 */
1525  || n == SSL_R_NO_SHARED_CIPHER /* 193 */
1526  || n == SSL_R_RECORD_LENGTH_MISMATCH /* 213 */
1527 #ifdef SSL_R_PARSE_TLSEXT
1528  || n == SSL_R_PARSE_TLSEXT /* 227 */
1529 #endif
1530  || n == SSL_R_UNEXPECTED_MESSAGE /* 244 */
1531  || n == SSL_R_UNEXPECTED_RECORD /* 245 */
1532  || n == SSL_R_UNKNOWN_ALERT_TYPE /* 246 */
1533  || n == SSL_R_UNKNOWN_PROTOCOL /* 252 */
1534  || n == SSL_R_WRONG_VERSION_NUMBER /* 267 */
1535  || n == SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC /* 281 */
1536 #ifdef SSL_R_RENEGOTIATE_EXT_TOO_LONG
1537  || n == SSL_R_RENEGOTIATE_EXT_TOO_LONG /* 335 */
1538  || n == SSL_R_RENEGOTIATION_ENCODING_ERR /* 336 */
1539  || n == SSL_R_RENEGOTIATION_MISMATCH /* 337 */
1540 #endif
1541 #ifdef SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED
1542  || n == SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED /* 338 */
1543 #endif
1544 #ifdef SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING
1545  || n == SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING /* 345 */
1546 #endif
1547  || n == 1000 /* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */
1548  || n == SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE /* 1010 */
1549  || n == SSL_R_SSLV3_ALERT_BAD_RECORD_MAC /* 1020 */
1550  || n == SSL_R_TLSV1_ALERT_DECRYPTION_FAILED /* 1021 */
1551  || n == SSL_R_TLSV1_ALERT_RECORD_OVERFLOW /* 1022 */
1552  || n == SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE /* 1030 */
1553  || n == SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE /* 1040 */
1554  || n == SSL_R_SSLV3_ALERT_NO_CERTIFICATE /* 1041 */
1555  || n == SSL_R_SSLV3_ALERT_BAD_CERTIFICATE /* 1042 */
1556  || n == SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE /* 1043 */
1557  || n == SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED /* 1044 */
1558  || n == SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED /* 1045 */
1559  || n == SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN /* 1046 */
1560  || n == SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER /* 1047 */
1561  || n == SSL_R_TLSV1_ALERT_UNKNOWN_CA /* 1048 */
1562  || n == SSL_R_TLSV1_ALERT_ACCESS_DENIED /* 1049 */
1563  || n == SSL_R_TLSV1_ALERT_DECODE_ERROR /* 1050 */
1564  || n == SSL_R_TLSV1_ALERT_DECRYPT_ERROR /* 1051 */
1565  || n == SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION /* 1060 */
1566  || n == SSL_R_TLSV1_ALERT_PROTOCOL_VERSION /* 1070 */
1567  || n == SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY /* 1071 */
1568  || n == SSL_R_TLSV1_ALERT_INTERNAL_ERROR /* 1080 */
1569  || n == SSL_R_TLSV1_ALERT_USER_CANCELLED /* 1090 */
1570  || n == SSL_R_TLSV1_ALERT_NO_RENEGOTIATION) /* 1100 */
1571  {
1572  switch (c->log_error) {
1573 
1575  case NGX_ERROR_INFO:
1576  level = NGX_LOG_INFO;
1577  break;
1578 
1579  case NGX_ERROR_ERR:
1580  level = NGX_LOG_ERR;
1581  break;
1582 
1583  default:
1584  break;
1585  }
1586  }
1587  }
1588 
1589  ngx_ssl_error(level, c->log, err, text);
1590 }
1591 
1592 
1593 static void
1594 ngx_ssl_clear_error(ngx_log_t *log)
1595 {
1596  while (ERR_peek_error()) {
1597  ngx_ssl_error(NGX_LOG_ALERT, log, 0, "ignoring stale global SSL error");
1598  }
1599 
1600  ERR_clear_error();
1601 }
1602 
1603 
1604 void ngx_cdecl
1605 ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...)
1606 {
1607  int flags;
1608  u_long n;
1609  va_list args;
1610  u_char *p, *last;
1611  u_char errstr[NGX_MAX_CONF_ERRSTR];
1612  const char *data;
1613 
1614  last = errstr + NGX_MAX_CONF_ERRSTR;
1615 
1616  va_start(args, fmt);
1617  p = ngx_vslprintf(errstr, last - 1, fmt, args);
1618  va_end(args);
1619 
1620  p = ngx_cpystrn(p, (u_char *) " (SSL:", last - p);
1621 
1622  for ( ;; ) {
1623 
1624  n = ERR_peek_error_line_data(NULL, NULL, &data, &flags);
1625 
1626  if (n == 0) {
1627  break;
1628  }
1629 
1630  if (p >= last) {
1631  goto next;
1632  }
1633 
1634  *p++ = ' ';
1635 
1636  ERR_error_string_n(n, (char *) p, last - p);
1637 
1638  while (p < last && *p) {
1639  p++;
1640  }
1641 
1642  if (p < last && *data && (flags & ERR_TXT_STRING)) {
1643  *p++ = ':';
1644  p = ngx_cpystrn(p, (u_char *) data, last - p);
1645  }
1646 
1647  next:
1648 
1649  (void) ERR_get_error();
1650  }
1651 
1652  ngx_log_error(level, log, err, "%s)", errstr);
1653 }
1654 
1655 
1656 ngx_int_t
1658  ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout)
1659 {
1660  long cache_mode;
1661 
1662  if (builtin_session_cache == NGX_SSL_NO_SCACHE) {
1663  SSL_CTX_set_session_cache_mode(ssl->ctx, SSL_SESS_CACHE_OFF);
1664  return NGX_OK;
1665  }
1666 
1667  SSL_CTX_set_session_id_context(ssl->ctx, sess_ctx->data, sess_ctx->len);
1668 
1669  if (builtin_session_cache == NGX_SSL_NONE_SCACHE) {
1670 
1671  /*
1672  * If the server explicitly says that it does not support
1673  * session reuse (see SSL_SESS_CACHE_OFF above), then
1674  * Outlook Express fails to upload a sent email to
1675  * the Sent Items folder on the IMAP server via a separate IMAP
1676  * connection in the background. Therefore we have a special
1677  * mode (SSL_SESS_CACHE_SERVER|SSL_SESS_CACHE_NO_INTERNAL_STORE)
1678  * where the server pretends that it supports session reuse,
1679  * but it does not actually store any session.
1680  */
1681 
1682  SSL_CTX_set_session_cache_mode(ssl->ctx,
1683  SSL_SESS_CACHE_SERVER
1684  |SSL_SESS_CACHE_NO_AUTO_CLEAR
1685  |SSL_SESS_CACHE_NO_INTERNAL_STORE);
1686 
1687  SSL_CTX_sess_set_cache_size(ssl->ctx, 1);
1688 
1689  return NGX_OK;
1690  }
1691 
1692  cache_mode = SSL_SESS_CACHE_SERVER;
1693 
1694  if (shm_zone && builtin_session_cache == NGX_SSL_NO_BUILTIN_SCACHE) {
1695  cache_mode |= SSL_SESS_CACHE_NO_INTERNAL;
1696  }
1697 
1698  SSL_CTX_set_session_cache_mode(ssl->ctx, cache_mode);
1699 
1700  if (builtin_session_cache != NGX_SSL_NO_BUILTIN_SCACHE) {
1701 
1702  if (builtin_session_cache != NGX_SSL_DFLT_BUILTIN_SCACHE) {
1703  SSL_CTX_sess_set_cache_size(ssl->ctx, builtin_session_cache);
1704  }
1705  }
1706 
1707  SSL_CTX_set_timeout(ssl->ctx, (long) timeout);
1708 
1709  if (shm_zone) {
1710  SSL_CTX_sess_set_new_cb(ssl->ctx, ngx_ssl_new_session);
1711  SSL_CTX_sess_set_get_cb(ssl->ctx, ngx_ssl_get_cached_session);
1712  SSL_CTX_sess_set_remove_cb(ssl->ctx, ngx_ssl_remove_session);
1713 
1714  if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_session_cache_index, shm_zone)
1715  == 0)
1716  {
1717  ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
1718  "SSL_CTX_set_ex_data() failed");
1719  return NGX_ERROR;
1720  }
1721  }
1722 
1723  return NGX_OK;
1724 }
1725 
1726 
1727 ngx_int_t
1729 {
1730  size_t len;
1731  ngx_slab_pool_t *shpool;
1732  ngx_ssl_session_cache_t *cache;
1733 
1734  if (data) {
1735  shm_zone->data = data;
1736  return NGX_OK;
1737  }
1738 
1739  if (shm_zone->shm.exists) {
1740  shm_zone->data = data;
1741  return NGX_OK;
1742  }
1743 
1744  shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
1745 
1746  cache = ngx_slab_alloc(shpool, sizeof(ngx_ssl_session_cache_t));
1747  if (cache == NULL) {
1748  return NGX_ERROR;
1749  }
1750 
1751  shpool->data = cache;
1752  shm_zone->data = cache;
1753 
1754  ngx_rbtree_init(&cache->session_rbtree, &cache->sentinel,
1755  ngx_ssl_session_rbtree_insert_value);
1756 
1757  ngx_queue_init(&cache->expire_queue);
1758 
1759  len = sizeof(" in SSL session shared cache \"\"") + shm_zone->shm.name.len;
1760 
1761  shpool->log_ctx = ngx_slab_alloc(shpool, len);
1762  if (shpool->log_ctx == NULL) {
1763  return NGX_ERROR;
1764  }
1765 
1766  ngx_sprintf(shpool->log_ctx, " in SSL session shared cache \"%V\"%Z",
1767  &shm_zone->shm.name);
1768 
1769  return NGX_OK;
1770 }
1771 
1772 
1773 /*
1774  * The length of the session id is 16 bytes for SSLv2 sessions and
1775  * between 1 and 32 bytes for SSLv3/TLSv1, typically 32 bytes.
1776  * It seems that the typical length of the external ASN1 representation
1777  * of a session is 118 or 119 bytes for SSLv3/TSLv1.
1778  *
1779  * Thus on 32-bit platforms we allocate separately an rbtree node,
1780  * a session id, and an ASN1 representation, they take accordingly
1781  * 64, 32, and 128 bytes.
1782  *
1783  * On 64-bit platforms we allocate separately an rbtree node + session_id,
1784  * and an ASN1 representation, they take accordingly 128 and 128 bytes.
1785  *
1786  * OpenSSL's i2d_SSL_SESSION() and d2i_SSL_SESSION are slow,
1787  * so they are outside the code locked by shared pool mutex
1788  */
1789 
1790 static int
1791 ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
1792 {
1793  int len;
1794  u_char *p, *id, *cached_sess;
1795  uint32_t hash;
1796  SSL_CTX *ssl_ctx;
1797  ngx_shm_zone_t *shm_zone;
1798  ngx_connection_t *c;
1799  ngx_slab_pool_t *shpool;
1800  ngx_ssl_sess_id_t *sess_id;
1801  ngx_ssl_session_cache_t *cache;
1802  u_char buf[NGX_SSL_MAX_SESSION_SIZE];
1803 
1804  len = i2d_SSL_SESSION(sess, NULL);
1805 
1806  /* do not cache too big session */
1807 
1808  if (len > (int) NGX_SSL_MAX_SESSION_SIZE) {
1809  return 0;
1810  }
1811 
1812  p = buf;
1813  i2d_SSL_SESSION(sess, &p);
1814 
1815  c = ngx_ssl_get_connection(ssl_conn);
1816 
1817  ssl_ctx = SSL_get_SSL_CTX(ssl_conn);
1818  shm_zone = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_session_cache_index);
1819 
1820  cache = shm_zone->data;
1821  shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
1822 
1823  ngx_shmtx_lock(&shpool->mutex);
1824 
1825  /* drop one or two expired sessions */
1826  ngx_ssl_expire_sessions(cache, shpool, 1);
1827 
1828  cached_sess = ngx_slab_alloc_locked(shpool, len);
1829 
1830  if (cached_sess == NULL) {
1831 
1832  /* drop the oldest non-expired session and try once more */
1833 
1834  ngx_ssl_expire_sessions(cache, shpool, 0);
1835 
1836  cached_sess = ngx_slab_alloc_locked(shpool, len);
1837 
1838  if (cached_sess == NULL) {
1839  sess_id = NULL;
1840  goto failed;
1841  }
1842  }
1843 
1844  sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t));
1845 
1846  if (sess_id == NULL) {
1847 
1848  /* drop the oldest non-expired session and try once more */
1849 
1850  ngx_ssl_expire_sessions(cache, shpool, 0);
1851 
1852  sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t));
1853 
1854  if (sess_id == NULL) {
1855  goto failed;
1856  }
1857  }
1858 
1859 #if (NGX_PTR_SIZE == 8)
1860 
1861  id = sess_id->sess_id;
1862 
1863 #else
1864 
1865  id = ngx_slab_alloc_locked(shpool, sess->session_id_length);
1866 
1867  if (id == NULL) {
1868 
1869  /* drop the oldest non-expired session and try once more */
1870 
1871  ngx_ssl_expire_sessions(cache, shpool, 0);
1872 
1873  id = ngx_slab_alloc_locked(shpool, sess->session_id_length);
1874 
1875  if (id == NULL) {
1876  goto failed;
1877  }
1878  }
1879 
1880 #endif
1881 
1882  ngx_memcpy(cached_sess, buf, len);
1883 
1884  ngx_memcpy(id, sess->session_id, sess->session_id_length);
1885 
1886  hash = ngx_crc32_short(sess->session_id, sess->session_id_length);
1887 
1889  "ssl new session: %08XD:%d:%d",
1890  hash, sess->session_id_length, len);
1891 
1892  sess_id->node.key = hash;
1893  sess_id->node.data = (u_char) sess->session_id_length;
1894  sess_id->id = id;
1895  sess_id->len = len;
1896  sess_id->session = cached_sess;
1897 
1898  sess_id->expire = ngx_time() + SSL_CTX_get_timeout(ssl_ctx);
1899 
1900  ngx_queue_insert_head(&cache->expire_queue, &sess_id->queue);
1901 
1902  ngx_rbtree_insert(&cache->session_rbtree, &sess_id->node);
1903 
1904  ngx_shmtx_unlock(&shpool->mutex);
1905 
1906  return 0;
1907 
1908 failed:
1909 
1910  if (cached_sess) {
1911  ngx_slab_free_locked(shpool, cached_sess);
1912  }
1913 
1914  if (sess_id) {
1915  ngx_slab_free_locked(shpool, sess_id);
1916  }
1917 
1918  ngx_shmtx_unlock(&shpool->mutex);
1919 
1921  "could not add new SSL session to the session cache");
1922 
1923  return 0;
1924 }
1925 
1926 
1927 static ngx_ssl_session_t *
1928 ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, u_char *id, int len,
1929  int *copy)
1930 {
1931 #if OPENSSL_VERSION_NUMBER >= 0x0090707fL
1932  const
1933 #endif
1934  u_char *p;
1935  uint32_t hash;
1936  ngx_int_t rc;
1937  ngx_shm_zone_t *shm_zone;
1938  ngx_slab_pool_t *shpool;
1939  ngx_rbtree_node_t *node, *sentinel;
1940  ngx_ssl_session_t *sess;
1941  ngx_ssl_sess_id_t *sess_id;
1942  ngx_ssl_session_cache_t *cache;
1943  u_char buf[NGX_SSL_MAX_SESSION_SIZE];
1944 #if (NGX_DEBUG)
1945  ngx_connection_t *c;
1946 #endif
1947 
1948  hash = ngx_crc32_short(id, (size_t) len);
1949  *copy = 0;
1950 
1951 #if (NGX_DEBUG)
1952  c = ngx_ssl_get_connection(ssl_conn);
1953 
1955  "ssl get session: %08XD:%d", hash, len);
1956 #endif
1957 
1958  shm_zone = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ssl_conn),
1960 
1961  cache = shm_zone->data;
1962 
1963  sess = NULL;
1964 
1965  shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
1966 
1967  ngx_shmtx_lock(&shpool->mutex);
1968 
1969  node = cache->session_rbtree.root;
1970  sentinel = cache->session_rbtree.sentinel;
1971 
1972  while (node != sentinel) {
1973 
1974  if (hash < node->key) {
1975  node = node->left;
1976  continue;
1977  }
1978 
1979  if (hash > node->key) {
1980  node = node->right;
1981  continue;
1982  }
1983 
1984  /* hash == node->key */
1985 
1986  sess_id = (ngx_ssl_sess_id_t *) node;
1987 
1988  rc = ngx_memn2cmp(id, sess_id->id, (size_t) len, (size_t) node->data);
1989 
1990  if (rc == 0) {
1991 
1992  if (sess_id->expire > ngx_time()) {
1993  ngx_memcpy(buf, sess_id->session, sess_id->len);
1994 
1995  ngx_shmtx_unlock(&shpool->mutex);
1996 
1997  p = buf;
1998  sess = d2i_SSL_SESSION(NULL, &p, sess_id->len);
1999 
2000  return sess;
2001  }
2002 
2003  ngx_queue_remove(&sess_id->queue);
2004 
2005  ngx_rbtree_delete(&cache->session_rbtree, node);
2006 
2007  ngx_slab_free_locked(shpool, sess_id->session);
2008 #if (NGX_PTR_SIZE == 4)
2009  ngx_slab_free_locked(shpool, sess_id->id);
2010 #endif
2011  ngx_slab_free_locked(shpool, sess_id);
2012 
2013  sess = NULL;
2014 
2015  goto done;
2016  }
2017 
2018  node = (rc < 0) ? node->left : node->right;
2019  }
2020 
2021 done:
2022 
2023  ngx_shmtx_unlock(&shpool->mutex);
2024 
2025  return sess;
2026 }
2027 
2028 
2029 void
2031 {
2032  SSL_CTX_remove_session(ssl, sess);
2033 
2034  ngx_ssl_remove_session(ssl, sess);
2035 }
2036 
2037 
2038 static void
2039 ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess)
2040 {
2041  size_t len;
2042  u_char *id;
2043  uint32_t hash;
2044  ngx_int_t rc;
2045  ngx_shm_zone_t *shm_zone;
2046  ngx_slab_pool_t *shpool;
2047  ngx_rbtree_node_t *node, *sentinel;
2048  ngx_ssl_sess_id_t *sess_id;
2049  ngx_ssl_session_cache_t *cache;
2050 
2051  shm_zone = SSL_CTX_get_ex_data(ssl, ngx_ssl_session_cache_index);
2052 
2053  if (shm_zone == NULL) {
2054  return;
2055  }
2056 
2057  cache = shm_zone->data;
2058 
2059  id = sess->session_id;
2060  len = (size_t) sess->session_id_length;
2061 
2062  hash = ngx_crc32_short(id, len);
2063 
2065  "ssl remove session: %08XD:%uz", hash, len);
2066 
2067  shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
2068 
2069  ngx_shmtx_lock(&shpool->mutex);
2070 
2071  node = cache->session_rbtree.root;
2072  sentinel = cache->session_rbtree.sentinel;
2073 
2074  while (node != sentinel) {
2075 
2076  if (hash < node->key) {
2077  node = node->left;
2078  continue;
2079  }
2080 
2081  if (hash > node->key) {
2082  node = node->right;
2083  continue;
2084  }
2085 
2086  /* hash == node->key */
2087 
2088  sess_id = (ngx_ssl_sess_id_t *) node;
2089 
2090  rc = ngx_memn2cmp(id, sess_id->id, len, (size_t) node->data);
2091 
2092  if (rc == 0) {
2093 
2094  ngx_queue_remove(&sess_id->queue);
2095 
2096  ngx_rbtree_delete(&cache->session_rbtree, node);
2097 
2098  ngx_slab_free_locked(shpool, sess_id->session);
2099 #if (NGX_PTR_SIZE == 4)
2100  ngx_slab_free_locked(shpool, sess_id->id);
2101 #endif
2102  ngx_slab_free_locked(shpool, sess_id);
2103 
2104  goto done;
2105  }
2106 
2107  node = (rc < 0) ? node->left : node->right;
2108  }
2109 
2110 done:
2111 
2112  ngx_shmtx_unlock(&shpool->mutex);
2113 }
2114 
2115 
2116 static void
2117 ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache,
2118  ngx_slab_pool_t *shpool, ngx_uint_t n)
2119 {
2120  time_t now;
2121  ngx_queue_t *q;
2122  ngx_ssl_sess_id_t *sess_id;
2123 
2124  now = ngx_time();
2125 
2126  while (n < 3) {
2127 
2128  if (ngx_queue_empty(&cache->expire_queue)) {
2129  return;
2130  }
2131 
2132  q = ngx_queue_last(&cache->expire_queue);
2133 
2134  sess_id = ngx_queue_data(q, ngx_ssl_sess_id_t, queue);
2135 
2136  if (n++ != 0 && sess_id->expire > now) {
2137  return;
2138  }
2139 
2140  ngx_queue_remove(q);
2141 
2143  "expire session: %08Xi", sess_id->node.key);
2144 
2145  ngx_rbtree_delete(&cache->session_rbtree, &sess_id->node);
2146 
2147  ngx_slab_free_locked(shpool, sess_id->session);
2148 #if (NGX_PTR_SIZE == 4)
2149  ngx_slab_free_locked(shpool, sess_id->id);
2150 #endif
2151  ngx_slab_free_locked(shpool, sess_id);
2152  }
2153 }
2154 
2155 
2156 static void
2157 ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp,
2158  ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
2159 {
2160  ngx_rbtree_node_t **p;
2161  ngx_ssl_sess_id_t *sess_id, *sess_id_temp;
2162 
2163  for ( ;; ) {
2164 
2165  if (node->key < temp->key) {
2166 
2167  p = &temp->left;
2168 
2169  } else if (node->key > temp->key) {
2170 
2171  p = &temp->right;
2172 
2173  } else { /* node->key == temp->key */
2174 
2175  sess_id = (ngx_ssl_sess_id_t *) node;
2176  sess_id_temp = (ngx_ssl_sess_id_t *) temp;
2177 
2178  p = (ngx_memn2cmp(sess_id->id, sess_id_temp->id,
2179  (size_t) node->data, (size_t) temp->data)
2180  < 0) ? &temp->left : &temp->right;
2181  }
2182 
2183  if (*p == sentinel) {
2184  break;
2185  }
2186 
2187  temp = *p;
2188  }
2189 
2190  *p = node;
2191  node->parent = temp;
2192  node->left = sentinel;
2193  node->right = sentinel;
2194  ngx_rbt_red(node);
2195 }
2196 
2197 
2198 void
2200 {
2201  ngx_ssl_t *ssl = data;
2202 
2203  SSL_CTX_free(ssl->ctx);
2204 }
2205 
2206 
2207 ngx_int_t
2209 {
2210  s->data = (u_char *) SSL_get_version(c->ssl->connection);
2211  return NGX_OK;
2212 }
2213 
2214 
2215 ngx_int_t
2217 {
2218  s->data = (u_char *) SSL_get_cipher_name(c->ssl->connection);
2219  return NGX_OK;
2220 }
2221 
2222 
2223 ngx_int_t
2225 {
2226  int len;
2227  u_char *p, *buf;
2228  SSL_SESSION *sess;
2229 
2230  sess = SSL_get0_session(c->ssl->connection);
2231 
2232  len = i2d_SSL_SESSION(sess, NULL);
2233 
2234  buf = ngx_alloc(len, c->log);
2235  if (buf == NULL) {
2236  return NGX_ERROR;
2237  }
2238 
2239  s->len = 2 * len;
2240  s->data = ngx_pnalloc(pool, 2 * len);
2241  if (s->data == NULL) {
2242  ngx_free(buf);
2243  return NGX_ERROR;
2244  }
2245 
2246  p = buf;
2247  i2d_SSL_SESSION(sess, &p);
2248 
2249  ngx_hex_dump(s->data, buf, len);
2250 
2251  ngx_free(buf);
2252 
2253  return NGX_OK;
2254 }
2255 
2256 
2257 ngx_int_t
2259 {
2260  size_t len;
2261  BIO *bio;
2262  X509 *cert;
2263 
2264  s->len = 0;
2265 
2266  cert = SSL_get_peer_certificate(c->ssl->connection);
2267  if (cert == NULL) {
2268  return NGX_OK;
2269  }
2270 
2271  bio = BIO_new(BIO_s_mem());
2272  if (bio == NULL) {
2273  ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed");
2274  X509_free(cert);
2275  return NGX_ERROR;
2276  }
2277 
2278  if (PEM_write_bio_X509(bio, cert) == 0) {
2279  ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "PEM_write_bio_X509() failed");
2280  goto failed;
2281  }
2282 
2283  len = BIO_pending(bio);
2284  s->len = len;
2285 
2286  s->data = ngx_pnalloc(pool, len);
2287  if (s->data == NULL) {
2288  goto failed;
2289  }
2290 
2291  BIO_read(bio, s->data, len);
2292 
2293  BIO_free(bio);
2294  X509_free(cert);
2295 
2296  return NGX_OK;
2297 
2298 failed:
2299 
2300  BIO_free(bio);
2301  X509_free(cert);
2302 
2303  return NGX_ERROR;
2304 }
2305 
2306 
2307 ngx_int_t
2309 {
2310  u_char *p;
2311  size_t len;
2312  ngx_uint_t i;
2313  ngx_str_t cert;
2314 
2315  if (ngx_ssl_get_raw_certificate(c, pool, &cert) != NGX_OK) {
2316  return NGX_ERROR;
2317  }
2318 
2319  if (cert.len == 0) {
2320  s->len = 0;
2321  return NGX_OK;
2322  }
2323 
2324  len = cert.len - 1;
2325 
2326  for (i = 0; i < cert.len - 1; i++) {
2327  if (cert.data[i] == LF) {
2328  len++;
2329  }
2330  }
2331 
2332  s->len = len;
2333  s->data = ngx_pnalloc(pool, len);
2334  if (s->data == NULL) {
2335  return NGX_ERROR;
2336  }
2337 
2338  p = s->data;
2339 
2340  for (i = 0; i < cert.len - 1; i++) {
2341  *p++ = cert.data[i];
2342  if (cert.data[i] == LF) {
2343  *p++ = '\t';
2344  }
2345  }
2346 
2347  return NGX_OK;
2348 }
2349 
2350 
2351 ngx_int_t
2353 {
2354  char *p;
2355  size_t len;
2356  X509 *cert;
2357  X509_NAME *name;
2358 
2359  s->len = 0;
2360 
2361  cert = SSL_get_peer_certificate(c->ssl->connection);
2362  if (cert == NULL) {
2363  return NGX_OK;
2364  }
2365 
2366  name = X509_get_subject_name(cert);
2367  if (name == NULL) {
2368  X509_free(cert);
2369  return NGX_ERROR;
2370  }
2371 
2372  p = X509_NAME_oneline(name, NULL, 0);
2373 
2374  for (len = 0; p[len]; len++) { /* void */ }
2375 
2376  s->len = len;
2377  s->data = ngx_pnalloc(pool, len);
2378  if (s->data == NULL) {
2379  OPENSSL_free(p);
2380  X509_free(cert);
2381  return NGX_ERROR;
2382  }
2383 
2384  ngx_memcpy(s->data, p, len);
2385 
2386  OPENSSL_free(p);
2387  X509_free(cert);
2388 
2389  return NGX_OK;
2390 }
2391 
2392 
2393 ngx_int_t
2395 {
2396  char *p;
2397  size_t len;
2398  X509 *cert;
2399  X509_NAME *name;
2400 
2401  s->len = 0;
2402 
2403  cert = SSL_get_peer_certificate(c->ssl->connection);
2404  if (cert == NULL) {
2405  return NGX_OK;
2406  }
2407 
2408  name = X509_get_issuer_name(cert);
2409  if (name == NULL) {
2410  X509_free(cert);
2411  return NGX_ERROR;
2412  }
2413 
2414  p = X509_NAME_oneline(name, NULL, 0);
2415 
2416  for (len = 0; p[len]; len++) { /* void */ }
2417 
2418  s->len = len;
2419  s->data = ngx_pnalloc(pool, len);
2420  if (s->data == NULL) {
2421  OPENSSL_free(p);
2422  X509_free(cert);
2423  return NGX_ERROR;
2424  }
2425 
2426  ngx_memcpy(s->data, p, len);
2427 
2428  OPENSSL_free(p);
2429  X509_free(cert);
2430 
2431  return NGX_OK;
2432 }
2433 
2434 
2435 ngx_int_t
2437 {
2438  size_t len;
2439  X509 *cert;
2440  BIO *bio;
2441 
2442  s->len = 0;
2443 
2444  cert = SSL_get_peer_certificate(c->ssl->connection);
2445  if (cert == NULL) {
2446  return NGX_OK;
2447  }
2448 
2449  bio = BIO_new(BIO_s_mem());
2450  if (bio == NULL) {
2451  X509_free(cert);
2452  return NGX_ERROR;
2453  }
2454 
2455  i2a_ASN1_INTEGER(bio, X509_get_serialNumber(cert));
2456  len = BIO_pending(bio);
2457 
2458  s->len = len;
2459  s->data = ngx_pnalloc(pool, len);
2460  if (s->data == NULL) {
2461  BIO_free(bio);
2462  X509_free(cert);
2463  return NGX_ERROR;
2464  }
2465 
2466  BIO_read(bio, s->data, len);
2467  BIO_free(bio);
2468  X509_free(cert);
2469 
2470  return NGX_OK;
2471 }
2472 
2473 
2474 ngx_int_t
2476 {
2477  X509 *cert;
2478 
2479  if (SSL_get_verify_result(c->ssl->connection) != X509_V_OK) {
2480  ngx_str_set(s, "FAILED");
2481  return NGX_OK;
2482  }
2483 
2484  cert = SSL_get_peer_certificate(c->ssl->connection);
2485 
2486  if (cert) {
2487  ngx_str_set(s, "SUCCESS");
2488 
2489  } else {
2490  ngx_str_set(s, "NONE");
2491  }
2492 
2493  X509_free(cert);
2494 
2495  return NGX_OK;
2496 }
2497 
2498 
2499 static void *
2500 ngx_openssl_create_conf(ngx_cycle_t *cycle)
2501 {
2502  ngx_openssl_conf_t *oscf;
2503 
2504  oscf = ngx_pcalloc(cycle->pool, sizeof(ngx_openssl_conf_t));
2505  if (oscf == NULL) {
2506  return NULL;
2507  }
2508 
2509  /*
2510  * set by ngx_pcalloc():
2511  *
2512  * oscf->engine = 0;
2513  */
2514 
2515  return oscf;
2516 }
2517 
2518 
2519 static char *
2520 ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2521 {
2522  ngx_openssl_conf_t *oscf = conf;
2523 
2524  ENGINE *engine;
2525  ngx_str_t *value;
2526 
2527  if (oscf->engine) {
2528  return "is duplicate";
2529  }
2530 
2531  oscf->engine = 1;
2532 
2533  value = cf->args->elts;
2534 
2535  engine = ENGINE_by_id((const char *) value[1].data);
2536 
2537  if (engine == NULL) {
2538  ngx_ssl_error(NGX_LOG_WARN, cf->log, 0,
2539  "ENGINE_by_id(\"%V\") failed", &value[1]);
2540  return NGX_CONF_ERROR;
2541  }
2542 
2543  if (ENGINE_set_default(engine, ENGINE_METHOD_ALL) == 0) {
2544  ngx_ssl_error(NGX_LOG_WARN, cf->log, 0,
2545  "ENGINE_set_default(\"%V\", ENGINE_METHOD_ALL) failed",
2546  &value[1]);
2547 
2548  ENGINE_free(engine);
2549 
2550  return NGX_CONF_ERROR;
2551  }
2552 
2553  ENGINE_free(engine);
2554 
2555  return NGX_CONF_OK;
2556 }
2557 
2558 
2559 static void
2560 ngx_openssl_exit(ngx_cycle_t *cycle)
2561 {
2562  EVP_cleanup();
2563  ENGINE_cleanup();
2564 }