3 * Copyright (C) Igor Sysoev
7 #include <ngx_config.h>
13 ngx_uint_t engine; /* unsigned engine:1; */
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);
27 static ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone,
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);
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);
44 static ngx_command_t ngx_openssl_commands[] = {
46 { ngx_string("ssl_engine"),
47 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
57 static ngx_core_module_t ngx_openssl_module_ctx = {
58 ngx_string("openssl"),
59 ngx_openssl_create_conf,
64 ngx_module_t ngx_openssl_module = {
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 */
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,
85 SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3,
92 int ngx_ssl_connection_index;
93 int ngx_ssl_server_conf_index;
94 int ngx_ssl_session_cache_index;
98 ngx_ssl_init(ngx_log_t *log)
100 #if OPENSSL_VERSION_NUMBER >= 0x00907000
101 OPENSSL_config(NULL);
105 SSL_load_error_strings();
108 ENGINE_load_builtin_engines();
111 ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
113 if (ngx_ssl_connection_index == -1) {
114 ngx_ssl_error(NGX_LOG_ALERT, log, 0, "SSL_get_ex_new_index() failed");
118 ngx_ssl_server_conf_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
120 if (ngx_ssl_server_conf_index == -1) {
121 ngx_ssl_error(NGX_LOG_ALERT, log, 0,
122 "SSL_CTX_get_ex_new_index() failed");
126 ngx_ssl_session_cache_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
128 if (ngx_ssl_session_cache_index == -1) {
129 ngx_ssl_error(NGX_LOG_ALERT, log, 0,
130 "SSL_CTX_get_ex_new_index() failed");
139 ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data)
141 ssl->ctx = SSL_CTX_new(SSLv23_method());
143 if (ssl->ctx == NULL) {
144 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_new() failed");
148 if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_server_conf_index, data) == 0) {
149 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
150 "SSL_CTX_set_ex_data() failed");
154 /* client side options */
156 SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_SESS_ID_BUG);
157 SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_CHALLENGE_BUG);
158 SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG);
160 /* server side options */
162 SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG);
163 SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER);
165 /* this option allow a potential SSL 2.0 rollback (CAN-2005-2969) */
166 SSL_CTX_set_options(ssl->ctx, SSL_OP_MSIE_SSLV2_RSA_PADDING);
168 SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLEAY_080_CLIENT_DH_BUG);
169 SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_D5_BUG);
170 SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_BLOCK_PADDING_BUG);
172 #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
173 SSL_CTX_set_options(ssl->ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
176 SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_DH_USE);
178 if (ngx_ssl_protocols[protocols >> 1] != 0) {
179 SSL_CTX_set_options(ssl->ctx, ngx_ssl_protocols[protocols >> 1]);
182 SSL_CTX_set_read_ahead(ssl->ctx, 1);
189 ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
192 if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
196 if (SSL_CTX_use_certificate_chain_file(ssl->ctx, (char *) cert->data)
199 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
200 "SSL_CTX_use_certificate_chain_file(\"%s\") failed",
205 if (ngx_conf_full_name(cf->cycle, key, 1) != NGX_OK) {
209 if (SSL_CTX_use_PrivateKey_file(ssl->ctx, (char *) key->data,
213 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
214 "SSL_CTX_use_PrivateKey_file(\"%s\") failed", key->data);
223 ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
226 STACK_OF(X509_NAME) *list;
228 SSL_CTX_set_verify(ssl->ctx, SSL_VERIFY_PEER, ngx_http_ssl_verify_callback);
230 SSL_CTX_set_verify_depth(ssl->ctx, depth);
232 if (cert->len == 0) {
236 if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
240 if (SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL)
243 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
244 "SSL_CTX_load_verify_locations(\"%s\") failed",
249 list = SSL_load_client_CA_file((char *) cert->data);
252 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
253 "SSL_load_client_CA_file(\"%s\") failed", cert->data);
258 * before 0.9.7h and 0.9.8 SSL_load_client_CA_file()
259 * always leaved an error in the error queue
264 SSL_CTX_set_client_CA_list(ssl->ctx, list);
271 ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store)
274 char *subject, *issuer;
277 X509_NAME *sname, *iname;
279 ngx_ssl_conn_t *ssl_conn;
281 ssl_conn = X509_STORE_CTX_get_ex_data(x509_store,
282 SSL_get_ex_data_X509_STORE_CTX_idx());
284 c = ngx_ssl_get_connection(ssl_conn);
286 cert = X509_STORE_CTX_get_current_cert(x509_store);
287 err = X509_STORE_CTX_get_error(x509_store);
288 depth = X509_STORE_CTX_get_error_depth(x509_store);
290 sname = X509_get_subject_name(cert);
291 subject = sname ? X509_NAME_oneline(sname, NULL, 0) : "(none)";
293 iname = X509_get_issuer_name(cert);
294 issuer = iname ? X509_NAME_oneline(iname, NULL, 0) : "(none)";
296 ngx_log_debug5(NGX_LOG_DEBUG_EVENT, c->log, 0,
297 "verify:%d, error:%d, depth:%d, "
298 "subject:\"%s\",issuer: \"%s\"",
299 ok, err, depth, subject, issuer);
302 OPENSSL_free(subject);
306 OPENSSL_free(issuer);
315 ngx_ssl_generate_rsa512_key(ngx_ssl_t *ssl)
319 if (SSL_CTX_need_tmp_RSA(ssl->ctx) == 0) {
323 key = RSA_generate_key(512, RSA_F4, NULL, NULL);
326 SSL_CTX_set_tmp_rsa(ssl->ctx, key);
333 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "RSA_generate_key(512) failed");
340 ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file)
346 * -----BEGIN DH PARAMETERS-----
347 * MIGHAoGBALu8LcrYRnSQfEP89YDpz9vZWKP1aLQtSwju1OsPs1BMbAMCducQgAxc
348 * y7qokiYUxb7spWWl/fHSh6K8BJvmd4Bg6RqSp1fjBI9osHb302zI8pul34HcLKcl
349 * 7OZicMyaUDXYzs7vnqAnSmOrHlj6/UmI0PZdFGdX2gcd8EXP4WubAgEC
350 * -----END DH PARAMETERS-----
353 static unsigned char dh1024_p[] = {
354 0xBB, 0xBC, 0x2D, 0xCA, 0xD8, 0x46, 0x74, 0x90, 0x7C, 0x43, 0xFC, 0xF5,
355 0x80, 0xE9, 0xCF, 0xDB, 0xD9, 0x58, 0xA3, 0xF5, 0x68, 0xB4, 0x2D, 0x4B,
356 0x08, 0xEE, 0xD4, 0xEB, 0x0F, 0xB3, 0x50, 0x4C, 0x6C, 0x03, 0x02, 0x76,
357 0xE7, 0x10, 0x80, 0x0C, 0x5C, 0xCB, 0xBA, 0xA8, 0x92, 0x26, 0x14, 0xC5,
358 0xBE, 0xEC, 0xA5, 0x65, 0xA5, 0xFD, 0xF1, 0xD2, 0x87, 0xA2, 0xBC, 0x04,
359 0x9B, 0xE6, 0x77, 0x80, 0x60, 0xE9, 0x1A, 0x92, 0xA7, 0x57, 0xE3, 0x04,
360 0x8F, 0x68, 0xB0, 0x76, 0xF7, 0xD3, 0x6C, 0xC8, 0xF2, 0x9B, 0xA5, 0xDF,
361 0x81, 0xDC, 0x2C, 0xA7, 0x25, 0xEC, 0xE6, 0x62, 0x70, 0xCC, 0x9A, 0x50,
362 0x35, 0xD8, 0xCE, 0xCE, 0xEF, 0x9E, 0xA0, 0x27, 0x4A, 0x63, 0xAB, 0x1E,
363 0x58, 0xFA, 0xFD, 0x49, 0x88, 0xD0, 0xF6, 0x5D, 0x14, 0x67, 0x57, 0xDA,
364 0x07, 0x1D, 0xF0, 0x45, 0xCF, 0xE1, 0x6B, 0x9B
367 static unsigned char dh1024_g[] = { 0x02 };
370 if (file->len == 0) {
374 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "DH_new() failed");
378 dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
379 dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
381 if (dh->p == NULL || dh->g == NULL) {
382 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "BN_bin2bn() failed");
387 SSL_CTX_set_tmp_dh(ssl->ctx, dh);
394 if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) {
398 bio = BIO_new_file((char *) file->data, "r");
400 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
401 "BIO_new_file(\"%s\") failed", file->data);
405 dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
407 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
408 "PEM_read_bio_DHparams(\"%s\") failed", file->data);
413 SSL_CTX_set_tmp_dh(ssl->ctx, dh);
423 ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags)
425 ngx_ssl_connection_t *sc;
427 sc = ngx_pcalloc(c->pool, sizeof(ngx_ssl_connection_t));
432 sc->buffer = ((flags & NGX_SSL_BUFFER) != 0);
434 sc->connection = SSL_new(ssl->ctx);
436 if (sc->connection == NULL) {
437 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_new() failed");
441 if (SSL_set_fd(sc->connection, c->fd) == 0) {
442 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_fd() failed");
446 if (flags & NGX_SSL_CLIENT) {
447 SSL_set_connect_state(sc->connection);
450 SSL_set_accept_state(sc->connection);
453 if (SSL_set_ex_data(sc->connection, ngx_ssl_connection_index, c) == 0) {
454 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_ex_data() failed");
465 ngx_ssl_set_session(ngx_connection_t *c, ngx_ssl_session_t *session)
468 if (SSL_set_session(c->ssl->connection, session) == 0) {
469 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_session() failed");
479 ngx_ssl_handshake(ngx_connection_t *c)
484 ngx_ssl_clear_error(c->log);
486 n = SSL_do_handshake(c->ssl->connection);
488 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n);
492 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
496 if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
502 char buf[129], *s, *d;
505 cipher = SSL_get_current_cipher(c->ssl->connection);
508 SSL_CIPHER_description(cipher, &buf[1], 128);
510 for (s = &buf[1], d = buf; *s; s++) {
511 if (*s == ' ' && *d == ' ') {
515 if (*s == LF || *s == CR) {
528 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
529 "SSL: %s, cipher: \"%s\"",
530 SSL_get_version(c->ssl->connection), &buf[1]);
532 if (SSL_session_reused(c->ssl->connection)) {
533 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
534 "SSL reused session");
538 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
539 "SSL no shared ciphers");
544 c->ssl->handshaked = 1;
546 c->recv = ngx_ssl_recv;
547 c->send = ngx_ssl_write;
548 c->recv_chain = ngx_ssl_recv_chain;
549 c->send_chain = ngx_ssl_send_chain;
554 sslerr = SSL_get_error(c->ssl->connection, n);
556 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
558 if (sslerr == SSL_ERROR_WANT_READ) {
560 c->read->handler = ngx_ssl_handshake_handler;
561 c->write->handler = ngx_ssl_handshake_handler;
563 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
570 if (sslerr == SSL_ERROR_WANT_WRITE) {
572 c->read->handler = ngx_ssl_handshake_handler;
573 c->write->handler = ngx_ssl_handshake_handler;
575 if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
582 err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
584 c->ssl->no_wait_shutdown = 1;
585 c->ssl->no_send_shutdown = 1;
588 if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
589 ngx_log_error(NGX_LOG_INFO, c->log, err,
590 "peer closed connection in SSL handshake");
597 ngx_ssl_connection_error(c, sslerr, err, "SSL_do_handshake() failed");
604 ngx_ssl_handshake_handler(ngx_event_t *ev)
610 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
611 "SSL handshake handler: %d", ev->write);
618 if (ngx_ssl_handshake(c) == NGX_AGAIN) {
627 ngx_ssl_recv_chain(ngx_connection_t *c, ngx_chain_t *cl)
640 n = ngx_ssl_recv(c, last, b->end - last);
646 if (last == b->end) {
662 if (n == 0 || n == NGX_ERROR) {
675 ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size)
679 if (c->ssl->last == NGX_ERROR) {
684 if (c->ssl->last == NGX_DONE) {
692 ngx_ssl_clear_error(c->log);
695 * SSL_read() may return data in parts, so try to read
696 * until SSL_read() would return no data
701 n = SSL_read(c->ssl->connection, buf, size);
703 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_read: %d", n);
709 c->ssl->last = ngx_ssl_handle_recv(c, n);
711 if (c->ssl->last == NGX_OK) {
728 switch (c->ssl->last) {
748 ngx_ssl_handle_recv(ngx_connection_t *c, int n)
755 if (c->ssl->saved_write_handler) {
757 c->write->handler = c->ssl->saved_write_handler;
758 c->ssl->saved_write_handler = NULL;
761 if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
765 ngx_post_event(c->write, &ngx_posted_events);
771 sslerr = SSL_get_error(c->ssl->connection, n);
773 err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
775 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
777 if (sslerr == SSL_ERROR_WANT_READ) {
782 if (sslerr == SSL_ERROR_WANT_WRITE) {
784 ngx_log_error(NGX_LOG_INFO, c->log, 0,
785 "peer started SSL renegotiation");
789 if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
794 * we do not set the timer because there is already the read event timer
797 if (c->ssl->saved_write_handler == NULL) {
798 c->ssl->saved_write_handler = c->write->handler;
799 c->write->handler = ngx_ssl_write_handler;
805 c->ssl->no_wait_shutdown = 1;
806 c->ssl->no_send_shutdown = 1;
808 if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
809 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
810 "peer shutdown SSL cleanly");
814 ngx_ssl_connection_error(c, sslerr, err, "SSL_read() failed");
821 ngx_ssl_write_handler(ngx_event_t *wev)
827 c->read->handler(c->read);
832 * OpenSSL has no SSL_writev() so we copy several bufs into our 16K buffer
833 * before the SSL_write() call to decrease a SSL overhead.
835 * Besides for protocols such as HTTP it is possible to always buffer
836 * the output to decrease a SSL overhead some more.
840 ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
847 if (!c->ssl->buffer) {
850 if (ngx_buf_special(in->buf)) {
855 n = ngx_ssl_write(c, in->buf->pos, in->buf->last - in->buf->pos);
857 if (n == NGX_ERROR) {
858 return NGX_CHAIN_ERROR;
861 if (n == NGX_AGAIN) {
862 c->buffered |= NGX_SSL_BUFFERED;
868 if (in->buf->pos == in->buf->last) {
877 /* the maximum limit size is the maximum uint32_t value - the page size */
879 if (limit == 0 || limit > (off_t) (NGX_MAX_UINT32_VALUE - ngx_pagesize)) {
880 limit = NGX_MAX_UINT32_VALUE - ngx_pagesize;
886 buf = ngx_create_temp_buf(c->pool, NGX_SSL_BUFSIZE);
888 return NGX_CHAIN_ERROR;
894 if (buf->start == NULL) {
895 buf->start = ngx_palloc(c->pool, NGX_SSL_BUFSIZE);
896 if (buf->start == NULL) {
897 return NGX_CHAIN_ERROR;
900 buf->pos = buf->start;
901 buf->last = buf->start;
902 buf->end = buf->start + NGX_SSL_BUFSIZE;
906 flush = (in == NULL) ? 1 : 0;
910 while (in && buf->last < buf->end) {
911 if (in->buf->last_buf || in->buf->flush) {
915 if (ngx_buf_special(in->buf)) {
920 size = in->buf->last - in->buf->pos;
922 if (size > buf->end - buf->last) {
923 size = buf->end - buf->last;
926 if (send + size > limit) {
927 size = (ssize_t) (limit - send);
931 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
932 "SSL buf copy: %d", size);
934 ngx_memcpy(buf->last, in->buf->pos, size);
938 in->buf->pos += size;
940 if (in->buf->pos == in->buf->last) {
945 size = buf->last - buf->pos;
947 if (!flush && buf->last < buf->end && c->ssl->buffer) {
951 n = ngx_ssl_write(c, buf->pos, size);
953 if (n == NGX_ERROR) {
954 return NGX_CHAIN_ERROR;
957 if (n == NGX_AGAIN) {
958 c->buffered |= NGX_SSL_BUFFERED;
970 if (buf->pos == buf->last) {
971 buf->pos = buf->start;
972 buf->last = buf->start;
975 if (in == NULL || send == limit) {
980 if (buf->pos < buf->last) {
981 c->buffered |= NGX_SSL_BUFFERED;
984 c->buffered &= ~NGX_SSL_BUFFERED;
992 ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size)
997 ngx_ssl_clear_error(c->log);
999 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL to write: %d", size);
1001 n = SSL_write(c->ssl->connection, data, size);
1003 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_write: %d", n);
1007 if (c->ssl->saved_read_handler) {
1009 c->read->handler = c->ssl->saved_read_handler;
1010 c->ssl->saved_read_handler = NULL;
1013 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1017 ngx_post_event(c->read, &ngx_posted_events);
1023 sslerr = SSL_get_error(c->ssl->connection, n);
1025 err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
1027 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
1029 if (sslerr == SSL_ERROR_WANT_WRITE) {
1030 c->write->ready = 0;
1034 if (sslerr == SSL_ERROR_WANT_READ) {
1036 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1037 "peer started SSL renegotiation");
1041 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1046 * we do not set the timer because there is already
1047 * the write event timer
1050 if (c->ssl->saved_read_handler == NULL) {
1051 c->ssl->saved_read_handler = c->read->handler;
1052 c->read->handler = ngx_ssl_read_handler;
1058 c->ssl->no_wait_shutdown = 1;
1059 c->ssl->no_send_shutdown = 1;
1060 c->write->error = 1;
1062 ngx_ssl_connection_error(c, sslerr, err, "SSL_write() failed");
1069 ngx_ssl_read_handler(ngx_event_t *rev)
1071 ngx_connection_t *c;
1075 c->write->handler(c->write);
1080 ngx_ssl_free_buffer(ngx_connection_t *c)
1082 if (c->ssl->buf && c->ssl->buf->start) {
1083 if (ngx_pfree(c->pool, c->ssl->buf->start) == NGX_OK) {
1084 c->ssl->buf->start = NULL;
1091 ngx_ssl_shutdown(ngx_connection_t *c)
1093 int n, sslerr, mode;
1097 mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN;
1100 mode = SSL_get_shutdown(c->ssl->connection);
1102 if (c->ssl->no_wait_shutdown) {
1103 mode |= SSL_RECEIVED_SHUTDOWN;
1106 if (c->ssl->no_send_shutdown) {
1107 mode |= SSL_SENT_SHUTDOWN;
1111 SSL_set_shutdown(c->ssl->connection, mode);
1113 ngx_ssl_clear_error(c->log);
1115 n = SSL_shutdown(c->ssl->connection);
1117 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n);
1121 /* SSL_shutdown() never returns -1, on error it returns 0 */
1123 if (n != 1 && ERR_peek_error()) {
1124 sslerr = SSL_get_error(c->ssl->connection, n);
1126 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1127 "SSL_get_error: %d", sslerr);
1130 if (n == 1 || sslerr == 0 || sslerr == SSL_ERROR_ZERO_RETURN) {
1131 SSL_free(c->ssl->connection);
1137 if (sslerr == SSL_ERROR_WANT_READ || sslerr == SSL_ERROR_WANT_WRITE) {
1138 c->read->handler = ngx_ssl_shutdown_handler;
1139 c->write->handler = ngx_ssl_shutdown_handler;
1141 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1145 if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
1149 if (sslerr == SSL_ERROR_WANT_READ) {
1150 ngx_add_timer(c->read, 30000);
1156 err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
1158 ngx_ssl_connection_error(c, sslerr, err, "SSL_shutdown() failed");
1160 SSL_free(c->ssl->connection);
1168 ngx_ssl_shutdown_handler(ngx_event_t *ev)
1170 ngx_connection_t *c;
1171 ngx_connection_handler_pt handler;
1174 handler = c->ssl->handler;
1180 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "SSL shutdown handler");
1182 if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
1191 ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
1197 level = NGX_LOG_CRIT;
1199 if (sslerr == SSL_ERROR_SYSCALL) {
1201 if (err == NGX_ECONNRESET
1203 || err == NGX_ENOTCONN
1204 #if !(NGX_CRIT_ETIMEDOUT)
1205 || err == NGX_ETIMEDOUT
1207 || err == NGX_ECONNREFUSED
1208 || err == NGX_ENETDOWN
1209 || err == NGX_ENETUNREACH
1210 || err == NGX_EHOSTDOWN
1211 || err == NGX_EHOSTUNREACH)
1213 switch (c->log_error) {
1215 case NGX_ERROR_IGNORE_ECONNRESET:
1216 case NGX_ERROR_INFO:
1217 level = NGX_LOG_INFO;
1221 level = NGX_LOG_ERR;
1229 } else if (sslerr == SSL_ERROR_SSL) {
1231 n = ERR_GET_REASON(ERR_peek_error());
1233 /* handshake failures */
1234 if (n == SSL_R_DIGEST_CHECK_FAILED /* 149 */
1235 || n == SSL_R_NO_CIPHERS_PASSED /* 182 */
1236 || n == SSL_R_NO_SHARED_CIPHER /* 193 */
1237 || n == SSL_R_UNEXPECTED_MESSAGE /* 244 */
1238 || n == SSL_R_UNEXPECTED_RECORD /* 245 */
1239 || n == SSL_R_WRONG_VERSION_NUMBER /* 267 */
1240 || n == SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC /* 281 */
1241 || n == 1000 /* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */
1242 || n == SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE /* 1010 */
1243 || n == SSL_R_SSLV3_ALERT_BAD_RECORD_MAC /* 1020 */
1244 || n == SSL_R_TLSV1_ALERT_DECRYPTION_FAILED /* 1021 */
1245 || n == SSL_R_TLSV1_ALERT_RECORD_OVERFLOW /* 1022 */
1246 || n == SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE /* 1030 */
1247 || n == SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE /* 1040 */
1248 || n == SSL_R_SSLV3_ALERT_NO_CERTIFICATE /* 1041 */
1249 || n == SSL_R_SSLV3_ALERT_BAD_CERTIFICATE /* 1042 */
1250 || n == SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE /* 1043 */
1251 || n == SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED /* 1044 */
1252 || n == SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED /* 1045 */
1253 || n == SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN /* 1046 */
1254 || n == SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER /* 1047 */
1255 || n == SSL_R_TLSV1_ALERT_UNKNOWN_CA /* 1048 */
1256 || n == SSL_R_TLSV1_ALERT_ACCESS_DENIED /* 1049 */
1257 || n == SSL_R_TLSV1_ALERT_DECODE_ERROR /* 1050 */
1258 || n == SSL_R_TLSV1_ALERT_DECRYPT_ERROR /* 1051 */
1259 || n == SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION /* 1060 */
1260 || n == SSL_R_TLSV1_ALERT_PROTOCOL_VERSION /* 1070 */
1261 || n == SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY /* 1071 */
1262 || n == SSL_R_TLSV1_ALERT_INTERNAL_ERROR /* 1080 */
1263 || n == SSL_R_TLSV1_ALERT_USER_CANCELLED /* 1090 */
1264 || n == SSL_R_TLSV1_ALERT_NO_RENEGOTIATION) /* 1100 */
1266 switch (c->log_error) {
1268 case NGX_ERROR_IGNORE_ECONNRESET:
1269 case NGX_ERROR_INFO:
1270 level = NGX_LOG_INFO;
1274 level = NGX_LOG_ERR;
1283 ngx_ssl_error(level, c->log, err, text);
1288 ngx_ssl_clear_error(ngx_log_t *log)
1290 while (ERR_peek_error()) {
1291 ngx_ssl_error(NGX_LOG_ALERT, log, 0, "ignoring stale global SSL error");
1299 ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...)
1304 u_char errstr[NGX_MAX_CONF_ERRSTR];
1306 last = errstr + NGX_MAX_CONF_ERRSTR;
1308 va_start(args, fmt);
1309 p = ngx_vsnprintf(errstr, sizeof(errstr) - 1, fmt, args);
1312 p = ngx_cpystrn(p, (u_char *) " (SSL:", last - p);
1316 n = ERR_get_error();
1328 ERR_error_string_n(n, (char *) p, last - p);
1330 while (p < last && *p) {
1335 ngx_log_error(level, log, err, "%s)", errstr);
1340 ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx,
1341 ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout)
1345 if (builtin_session_cache == NGX_SSL_NO_SCACHE) {
1346 SSL_CTX_set_session_cache_mode(ssl->ctx, SSL_SESS_CACHE_OFF);
1350 if (builtin_session_cache == NGX_SSL_NONE_SCACHE) {
1353 * If the server explicitly says that it does not support
1354 * session reuse (see SSL_SESS_CACHE_OFF above), then
1355 * Outlook Express fails to upload a sent email to
1356 * the Sent Items folder on the IMAP server via a separate IMAP
1357 * connection in the background. Therefore we have a special
1358 * mode (SSL_SESS_CACHE_SERVER|SSL_SESS_CACHE_NO_INTERNAL_STORE)
1359 * where the server pretends that it supports session reuse,
1360 * but it does not actually store any session.
1363 SSL_CTX_set_session_cache_mode(ssl->ctx,
1364 SSL_SESS_CACHE_SERVER
1365 |SSL_SESS_CACHE_NO_AUTO_CLEAR
1366 |SSL_SESS_CACHE_NO_INTERNAL_STORE);
1368 SSL_CTX_sess_set_cache_size(ssl->ctx, 1);
1373 cache_mode = SSL_SESS_CACHE_SERVER;
1375 if (shm_zone && builtin_session_cache == NGX_SSL_NO_BUILTIN_SCACHE) {
1376 cache_mode |= SSL_SESS_CACHE_NO_INTERNAL;
1379 SSL_CTX_set_session_cache_mode(ssl->ctx, cache_mode);
1381 SSL_CTX_set_session_id_context(ssl->ctx, sess_ctx->data, sess_ctx->len);
1383 if (builtin_session_cache != NGX_SSL_NO_BUILTIN_SCACHE) {
1385 if (builtin_session_cache != NGX_SSL_DFLT_BUILTIN_SCACHE) {
1386 SSL_CTX_sess_set_cache_size(ssl->ctx, builtin_session_cache);
1390 SSL_CTX_set_timeout(ssl->ctx, timeout);
1393 shm_zone->init = ngx_ssl_session_cache_init;
1395 SSL_CTX_sess_set_new_cb(ssl->ctx, ngx_ssl_new_session);
1396 SSL_CTX_sess_set_get_cb(ssl->ctx, ngx_ssl_get_cached_session);
1397 SSL_CTX_sess_set_remove_cb(ssl->ctx, ngx_ssl_remove_session);
1399 if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_session_cache_index, shm_zone)
1402 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
1403 "SSL_CTX_set_ex_data() failed");
1413 ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data)
1415 ngx_slab_pool_t *shpool;
1416 ngx_ssl_session_cache_t *cache;
1419 shm_zone->data = data;
1423 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
1425 cache = ngx_slab_alloc(shpool, sizeof(ngx_ssl_session_cache_t));
1426 if (cache == NULL) {
1430 ngx_rbtree_init(&cache->session_rbtree, &cache->sentinel,
1431 ngx_ssl_session_rbtree_insert_value);
1433 ngx_queue_init(&cache->expire_queue);
1435 shm_zone->data = cache;
1442 * The length of the session id is 16 bytes for SSLv2 sessions and
1443 * between 1 and 32 bytes for SSLv3/TLSv1, typically 32 bytes.
1444 * It seems that the typical length of the external ASN1 representation
1445 * of a session is 118 or 119 bytes for SSLv3/TSLv1.
1447 * Thus on 32-bit platforms we allocate separately an rbtree node,
1448 * a session id, and an ASN1 representation, they take accordingly
1449 * 64, 32, and 128 bytes.
1451 * On 64-bit platforms we allocate separately an rbtree node + session_id,
1452 * and an ASN1 representation, they take accordingly 128 and 128 bytes.
1454 * OpenSSL's i2d_SSL_SESSION() and d2i_SSL_SESSION are slow,
1455 * so they are outside the code locked by shared pool mutex
1459 ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
1462 u_char *p, *id, *cached_sess;
1465 ngx_shm_zone_t *shm_zone;
1466 ngx_connection_t *c;
1467 ngx_slab_pool_t *shpool;
1468 ngx_ssl_sess_id_t *sess_id;
1469 ngx_ssl_session_cache_t *cache;
1470 u_char buf[NGX_SSL_MAX_SESSION_SIZE];
1472 len = i2d_SSL_SESSION(sess, NULL);
1474 /* do not cache too big session */
1476 if (len > (int) NGX_SSL_MAX_SESSION_SIZE) {
1481 i2d_SSL_SESSION(sess, &p);
1483 c = ngx_ssl_get_connection(ssl_conn);
1485 ssl_ctx = SSL_get_SSL_CTX(ssl_conn);
1486 shm_zone = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_session_cache_index);
1488 cache = shm_zone->data;
1489 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
1491 ngx_shmtx_lock(&shpool->mutex);
1493 /* drop one or two expired sessions */
1494 ngx_ssl_expire_sessions(cache, shpool, 1);
1496 cached_sess = ngx_slab_alloc_locked(shpool, len);
1498 if (cached_sess == NULL) {
1500 /* drop the oldest non-expired session and try once more */
1502 ngx_ssl_expire_sessions(cache, shpool, 0);
1504 cached_sess = ngx_slab_alloc_locked(shpool, len);
1506 if (cached_sess == NULL) {
1512 sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t));
1513 if (sess_id == NULL) {
1517 #if (NGX_PTR_SIZE == 8)
1519 id = sess_id->sess_id;
1523 id = ngx_slab_alloc_locked(shpool, sess->session_id_length);
1530 ngx_memcpy(cached_sess, buf, len);
1532 ngx_memcpy(id, sess->session_id, sess->session_id_length);
1534 hash = ngx_crc32_short(sess->session_id, sess->session_id_length);
1536 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
1537 "http ssl new session: %08XD:%d:%d",
1538 hash, sess->session_id_length, len);
1540 sess_id->node.key = hash;
1541 sess_id->node.data = (u_char) sess->session_id_length;
1544 sess_id->session = cached_sess;
1546 sess_id->expire = ngx_time() + SSL_CTX_get_timeout(ssl_ctx);
1548 ngx_queue_insert_head(&cache->expire_queue, &sess_id->queue);
1550 ngx_rbtree_insert(&cache->session_rbtree, &sess_id->node);
1552 ngx_shmtx_unlock(&shpool->mutex);
1559 ngx_slab_free_locked(shpool, cached_sess);
1563 ngx_slab_free_locked(shpool, sess_id);
1566 ngx_shmtx_unlock(&shpool->mutex);
1568 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
1569 "could not add new SSL session to the session cache");
1575 static ngx_ssl_session_t *
1576 ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, u_char *id, int len,
1579 #if OPENSSL_VERSION_NUMBER >= 0x0090707fL
1585 ngx_shm_zone_t *shm_zone;
1586 ngx_slab_pool_t *shpool;
1587 ngx_connection_t *c;
1588 ngx_rbtree_node_t *node, *sentinel;
1589 ngx_ssl_session_t *sess;
1590 ngx_ssl_sess_id_t *sess_id;
1591 ngx_ssl_session_cache_t *cache;
1592 u_char buf[NGX_SSL_MAX_SESSION_SIZE];
1594 c = ngx_ssl_get_connection(ssl_conn);
1596 hash = ngx_crc32_short(id, (size_t) len);
1599 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
1600 "http ssl get session: %08XD:%d", hash, len);
1602 shm_zone = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ssl_conn),
1603 ngx_ssl_session_cache_index);
1605 cache = shm_zone->data;
1609 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
1611 ngx_shmtx_lock(&shpool->mutex);
1613 node = cache->session_rbtree.root;
1614 sentinel = cache->session_rbtree.sentinel;
1616 while (node != sentinel) {
1618 if (hash < node->key) {
1623 if (hash > node->key) {
1628 /* hash == node->key */
1631 sess_id = (ngx_ssl_sess_id_t *) node;
1633 rc = ngx_memn2cmp(id, sess_id->id,
1634 (size_t) len, (size_t) node->data);
1637 if (sess_id->expire > ngx_time()) {
1638 ngx_memcpy(buf, sess_id->session, sess_id->len);
1640 ngx_shmtx_unlock(&shpool->mutex);
1643 sess = d2i_SSL_SESSION(NULL, &p, sess_id->len);
1648 ngx_queue_remove(&sess_id->queue);
1650 ngx_rbtree_delete(&cache->session_rbtree, node);
1652 ngx_slab_free_locked(shpool, sess_id->session);
1653 #if (NGX_PTR_SIZE == 4)
1654 ngx_slab_free_locked(shpool, sess_id->id);
1656 ngx_slab_free_locked(shpool, sess_id);
1663 node = (rc < 0) ? node->left : node->right;
1665 } while (node != sentinel && hash == node->key);
1672 ngx_shmtx_unlock(&shpool->mutex);
1679 ngx_ssl_remove_cached_session(SSL_CTX *ssl, ngx_ssl_session_t *sess)
1681 SSL_CTX_remove_session(ssl, sess);
1683 ngx_ssl_remove_session(ssl, sess);
1688 ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess)
1694 ngx_shm_zone_t *shm_zone;
1695 ngx_slab_pool_t *shpool;
1696 ngx_rbtree_node_t *node, *sentinel;
1697 ngx_ssl_sess_id_t *sess_id;
1698 ngx_ssl_session_cache_t *cache;
1700 shm_zone = SSL_CTX_get_ex_data(ssl, ngx_ssl_session_cache_index);
1702 if (shm_zone == NULL) {
1706 cache = shm_zone->data;
1708 id = sess->session_id;
1709 len = (size_t) sess->session_id_length;
1711 hash = ngx_crc32_short(id, len);
1713 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
1714 "http ssl remove session: %08XD:%uz", hash, len);
1716 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
1718 ngx_shmtx_lock(&shpool->mutex);
1720 node = cache->session_rbtree.root;
1721 sentinel = cache->session_rbtree.sentinel;
1723 while (node != sentinel) {
1725 if (hash < node->key) {
1730 if (hash > node->key) {
1735 /* hash == node->key */
1738 sess_id = (ngx_ssl_sess_id_t *) node;
1740 rc = ngx_memn2cmp(id, sess_id->id, len, (size_t) node->data);
1744 ngx_queue_remove(&sess_id->queue);
1746 ngx_rbtree_delete(&cache->session_rbtree, node);
1748 ngx_slab_free_locked(shpool, sess_id->session);
1749 #if (NGX_PTR_SIZE == 4)
1750 ngx_slab_free_locked(shpool, sess_id->id);
1752 ngx_slab_free_locked(shpool, sess_id);
1757 node = (rc < 0) ? node->left : node->right;
1759 } while (node != sentinel && hash == node->key);
1766 ngx_shmtx_unlock(&shpool->mutex);
1771 ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache,
1772 ngx_slab_pool_t *shpool, ngx_uint_t n)
1776 ngx_ssl_sess_id_t *sess_id;
1782 if (ngx_queue_empty(&cache->expire_queue)) {
1786 q = ngx_queue_last(&cache->expire_queue);
1788 sess_id = ngx_queue_data(q, ngx_ssl_sess_id_t, queue);
1790 if (n++ != 0 && sess_id->expire > now) {
1794 ngx_queue_remove(q);
1796 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
1797 "expire session: %08Xi", sess_id->node.key);
1799 ngx_rbtree_delete(&cache->session_rbtree, &sess_id->node);
1801 ngx_slab_free_locked(shpool, sess_id->session);
1802 #if (NGX_PTR_SIZE == 4)
1803 ngx_slab_free_locked(shpool, sess_id->id);
1805 ngx_slab_free_locked(shpool, sess_id);
1811 ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp,
1812 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
1814 ngx_rbtree_node_t **p;
1815 ngx_ssl_sess_id_t *sess_id, *sess_id_temp;
1819 if (node->key < temp->key) {
1823 } else if (node->key > temp->key) {
1827 } else { /* node->key == temp->key */
1829 sess_id = (ngx_ssl_sess_id_t *) node;
1830 sess_id_temp = (ngx_ssl_sess_id_t *) temp;
1832 p = (ngx_memn2cmp(sess_id->id, sess_id_temp->id,
1833 (size_t) node->data, (size_t) temp->data)
1834 < 0) ? &temp->left : &temp->right;
1837 if (*p == sentinel) {
1845 node->parent = temp;
1846 node->left = sentinel;
1847 node->right = sentinel;
1853 ngx_ssl_cleanup_ctx(void *data)
1855 ngx_ssl_t *ssl = data;
1857 SSL_CTX_free(ssl->ctx);
1862 ngx_ssl_get_protocol(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
1864 s->data = (u_char *) SSL_get_version(c->ssl->connection);
1870 ngx_ssl_get_cipher_name(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
1872 s->data = (u_char *) SSL_get_cipher_name(c->ssl->connection);
1878 ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
1886 cert = SSL_get_peer_certificate(c->ssl->connection);
1891 bio = BIO_new(BIO_s_mem());
1893 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed");
1898 if (PEM_write_bio_X509(bio, cert) == 0) {
1899 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "PEM_write_bio_X509() failed");
1903 len = BIO_pending(bio);
1906 s->data = ngx_pnalloc(pool, len);
1907 if (s->data == NULL) {
1911 BIO_read(bio, s->data, len);
1928 ngx_ssl_get_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
1935 if (ngx_ssl_get_raw_certificate(c, pool, &cert) != NGX_OK) {
1939 if (cert.len == 0) {
1946 for (i = 0; i < cert.len - 1; i++) {
1947 if (cert.data[i] == LF) {
1953 s->data = ngx_pnalloc(pool, len);
1954 if (s->data == NULL) {
1960 for (i = 0; i < len; i++) {
1961 *p++ = cert.data[i];
1962 if (cert.data[i] == LF) {
1972 ngx_ssl_get_subject_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
1981 cert = SSL_get_peer_certificate(c->ssl->connection);
1986 name = X509_get_subject_name(cert);
1992 p = X509_NAME_oneline(name, NULL, 0);
1994 for (len = 0; p[len]; len++) { /* void */ }
1997 s->data = ngx_pnalloc(pool, len);
1998 if (s->data == NULL) {
2004 ngx_memcpy(s->data, p, len);
2014 ngx_ssl_get_issuer_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
2023 cert = SSL_get_peer_certificate(c->ssl->connection);
2028 name = X509_get_issuer_name(cert);
2034 p = X509_NAME_oneline(name, NULL, 0);
2036 for (len = 0; p[len]; len++) { /* void */ }
2039 s->data = ngx_pnalloc(pool, len);
2040 if (s->data == NULL) {
2046 ngx_memcpy(s->data, p, len);
2056 ngx_ssl_get_serial_number(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
2064 cert = SSL_get_peer_certificate(c->ssl->connection);
2069 bio = BIO_new(BIO_s_mem());
2075 i2a_ASN1_INTEGER(bio, X509_get_serialNumber(cert));
2076 len = BIO_pending(bio);
2079 s->data = ngx_pnalloc(pool, len);
2080 if (s->data == NULL) {
2086 BIO_read(bio, s->data, len);
2095 ngx_openssl_create_conf(ngx_cycle_t *cycle)
2097 ngx_openssl_conf_t *oscf;
2099 oscf = ngx_pcalloc(cycle->pool, sizeof(ngx_openssl_conf_t));
2101 return NGX_CONF_ERROR;
2105 * set by ngx_pcalloc():
2115 ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2117 #if (NGX_SSL_ENGINE)
2118 ngx_openssl_conf_t *oscf = conf;
2124 return "is duplicate";
2129 value = cf->args->elts;
2131 engine = ENGINE_by_id((const char *) value[1].data);
2133 if (engine == NULL) {
2134 ngx_ssl_error(NGX_LOG_WARN, cf->log, 0,
2135 "ENGINE_by_id(\"%V\") failed", &value[1]);
2136 return NGX_CONF_ERROR;
2139 if (ENGINE_set_default(engine, ENGINE_METHOD_ALL) == 0) {
2140 ngx_ssl_error(NGX_LOG_WARN, cf->log, 0,
2141 "ENGINE_set_default(\"%V\", ENGINE_METHOD_ALL) failed",
2144 ENGINE_free(engine);
2146 return NGX_CONF_ERROR;
2149 ENGINE_free(engine);
2155 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2156 "\"ssl_engine\" directive is available only in "
2157 "OpenSSL 0.9.7 and higher,");
2159 return NGX_CONF_ERROR;
2166 ngx_openssl_exit(ngx_cycle_t *cycle)
2168 #if (NGX_SSL_ENGINE)