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