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