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