3 * Copyright (C) Igor Sysoev
7 #include <ngx_config.h>
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_init_conf(ngx_cycle_t *cycle, void *conf);
41 static void ngx_openssl_exit(ngx_cycle_t *cycle);
44 static char *ngx_openssl_noengine(ngx_conf_t *cf, ngx_command_t *cmd,
49 static ngx_command_t ngx_openssl_commands[] = {
51 { ngx_string("ssl_engine"),
52 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
54 ngx_conf_set_str_slot,
59 offsetof(ngx_openssl_conf_t, engine),
66 static ngx_core_module_t ngx_openssl_module_ctx = {
67 ngx_string("openssl"),
68 ngx_openssl_create_conf,
73 ngx_module_t ngx_openssl_module = {
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 */
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,
94 SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3,
101 int ngx_ssl_connection_index;
102 int ngx_ssl_server_conf_index;
103 int ngx_ssl_session_cache_index;
107 ngx_ssl_init(ngx_log_t *log)
109 #if OPENSSL_VERSION_NUMBER >= 0x00907000
110 OPENSSL_config(NULL);
114 SSL_load_error_strings();
117 ENGINE_load_builtin_engines();
120 ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
122 if (ngx_ssl_connection_index == -1) {
123 ngx_ssl_error(NGX_LOG_ALERT, log, 0, "SSL_get_ex_new_index() failed");
127 ngx_ssl_server_conf_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, 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");
135 ngx_ssl_session_cache_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, 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");
148 ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data)
150 ssl->ctx = SSL_CTX_new(SSLv23_method());
152 if (ssl->ctx == NULL) {
153 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_new() failed");
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");
163 /* client side options */
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);
169 /* server side options */
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);
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);
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);
181 #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
182 SSL_CTX_set_options(ssl->ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
185 SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_DH_USE);
187 if (ngx_ssl_protocols[protocols >> 1] != 0) {
188 SSL_CTX_set_options(ssl->ctx, ngx_ssl_protocols[protocols >> 1]);
191 SSL_CTX_set_read_ahead(ssl->ctx, 1);
198 ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
201 if (ngx_conf_full_name(cf->cycle, cert, 1) == NGX_ERROR) {
205 if (SSL_CTX_use_certificate_chain_file(ssl->ctx, (char *) cert->data)
208 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
209 "SSL_CTX_use_certificate_chain_file(\"%s\") failed",
214 if (ngx_conf_full_name(cf->cycle, key, 1) == NGX_ERROR) {
218 if (SSL_CTX_use_PrivateKey_file(ssl->ctx, (char *) key->data,
222 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
223 "SSL_CTX_use_PrivateKey_file(\"%s\") failed", key->data);
232 ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
235 STACK_OF(X509_NAME) *list;
237 SSL_CTX_set_verify(ssl->ctx, SSL_VERIFY_PEER, ngx_http_ssl_verify_callback);
239 SSL_CTX_set_verify_depth(ssl->ctx, depth);
241 if (cert->len == 0) {
245 if (ngx_conf_full_name(cf->cycle, cert, 1) == NGX_ERROR) {
249 if (SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL)
252 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
253 "SSL_CTX_load_verify_locations(\"%s\") failed",
258 list = SSL_load_client_CA_file((char *) cert->data);
261 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
262 "SSL_load_client_CA_file(\"%s\") failed", cert->data);
267 * before 0.9.7h and 0.9.8 SSL_load_client_CA_file()
268 * always leaved an error in the error queue
273 SSL_CTX_set_client_CA_list(ssl->ctx, list);
280 ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store)
283 char *subject, *issuer;
286 X509_NAME *sname, *iname;
288 ngx_ssl_conn_t *ssl_conn;
290 ssl_conn = X509_STORE_CTX_get_ex_data(x509_store,
291 SSL_get_ex_data_X509_STORE_CTX_idx());
293 c = ngx_ssl_get_connection(ssl_conn);
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);
299 sname = X509_get_subject_name(cert);
300 subject = sname ? X509_NAME_oneline(sname, NULL, 0) : "(none)";
302 iname = X509_get_issuer_name(cert);
303 issuer = iname ? X509_NAME_oneline(iname, NULL, 0) : "(none)";
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);
311 OPENSSL_free(subject);
315 OPENSSL_free(issuer);
324 ngx_ssl_generate_rsa512_key(ngx_ssl_t *ssl)
328 if (SSL_CTX_need_tmp_RSA(ssl->ctx) == 0) {
332 key = RSA_generate_key(512, RSA_F4, NULL, NULL);
335 SSL_CTX_set_tmp_rsa(ssl->ctx, key);
342 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "RSA_generate_key(512) failed");
349 ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file)
355 * -----BEGIN DH PARAMETERS-----
356 * MIGHAoGBALu8LcrYRnSQfEP89YDpz9vZWKP1aLQtSwju1OsPs1BMbAMCducQgAxc
357 * y7qokiYUxb7spWWl/fHSh6K8BJvmd4Bg6RqSp1fjBI9osHb302zI8pul34HcLKcl
358 * 7OZicMyaUDXYzs7vnqAnSmOrHlj6/UmI0PZdFGdX2gcd8EXP4WubAgEC
359 * -----END DH PARAMETERS-----
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
376 static unsigned char dh1024_g[] = { 0x02 };
379 if (file->len == 0) {
383 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "DH_new() failed");
387 dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
388 dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
390 if (dh->p == NULL || dh->g == NULL) {
391 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "BN_bin2bn() failed");
396 SSL_CTX_set_tmp_dh(ssl->ctx, dh);
403 if (ngx_conf_full_name(cf->cycle, file, 1) == NGX_ERROR) {
407 bio = BIO_new_file((char *) file->data, "r");
409 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
410 "BIO_new_file(\"%s\") failed", file->data);
414 dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
416 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
417 "PEM_read_bio_DHparams(\"%s\") failed", file->data);
422 SSL_CTX_set_tmp_dh(ssl->ctx, dh);
432 ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags)
434 ngx_ssl_connection_t *sc;
436 sc = ngx_pcalloc(c->pool, sizeof(ngx_ssl_connection_t));
441 sc->buffer = ((flags & NGX_SSL_BUFFER) != 0);
443 sc->connection = SSL_new(ssl->ctx);
445 if (sc->connection == NULL) {
446 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_new() failed");
450 if (SSL_set_fd(sc->connection, c->fd) == 0) {
451 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_fd() failed");
455 if (flags & NGX_SSL_CLIENT) {
456 SSL_set_connect_state(sc->connection);
459 SSL_set_accept_state(sc->connection);
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");
474 ngx_ssl_set_session(ngx_connection_t *c, ngx_ssl_session_t *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");
488 ngx_ssl_handshake(ngx_connection_t *c)
493 ngx_ssl_clear_error(c->log);
495 n = SSL_do_handshake(c->ssl->connection);
497 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n);
501 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
505 if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
511 char buf[129], *s, *d;
514 cipher = SSL_get_current_cipher(c->ssl->connection);
517 SSL_CIPHER_description(cipher, &buf[1], 128);
519 for (s = &buf[1], d = buf; *s; s++) {
520 if (*s == ' ' && *d == ' ') {
524 if (*s == LF || *s == CR) {
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]);
541 if (SSL_session_reused(c->ssl->connection)) {
542 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
543 "SSL reused session");
547 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
548 "SSL no shared ciphers");
553 c->ssl->handshaked = 1;
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;
563 sslerr = SSL_get_error(c->ssl->connection, n);
565 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
567 if (sslerr == SSL_ERROR_WANT_READ) {
569 c->read->handler = ngx_ssl_handshake_handler;
570 c->write->handler = ngx_ssl_handshake_handler;
572 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
579 if (sslerr == SSL_ERROR_WANT_WRITE) {
581 c->read->handler = ngx_ssl_handshake_handler;
582 c->write->handler = ngx_ssl_handshake_handler;
584 if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
591 err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
593 c->ssl->no_wait_shutdown = 1;
594 c->ssl->no_send_shutdown = 1;
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");
606 ngx_ssl_connection_error(c, sslerr, err, "SSL_do_handshake() failed");
613 ngx_ssl_handshake_handler(ngx_event_t *ev)
619 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
620 "SSL handshake handler: %d", ev->write);
627 if (ngx_ssl_handshake(c) == NGX_AGAIN) {
636 ngx_ssl_recv_chain(ngx_connection_t *c, ngx_chain_t *cl)
649 n = ngx_ssl_recv(c, last, b->end - last);
655 if (last == b->end) {
671 if (n == 0 || n == NGX_ERROR) {
684 ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size)
688 if (c->ssl->last == NGX_ERROR) {
693 if (c->ssl->last == NGX_DONE) {
701 ngx_ssl_clear_error(c->log);
704 * SSL_read() may return data in parts, so try to read
705 * until SSL_read() would return no data
710 n = SSL_read(c->ssl->connection, buf, size);
712 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_read: %d", n);
718 c->ssl->last = ngx_ssl_handle_recv(c, n);
720 if (c->ssl->last == NGX_OK) {
737 switch (c->ssl->last) {
757 ngx_ssl_handle_recv(ngx_connection_t *c, int n)
764 if (c->ssl->saved_write_handler) {
766 c->write->handler = c->ssl->saved_write_handler;
767 c->ssl->saved_write_handler = NULL;
770 if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
774 ngx_post_event(c->write, &ngx_posted_events);
780 sslerr = SSL_get_error(c->ssl->connection, n);
782 err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
784 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
786 if (sslerr == SSL_ERROR_WANT_READ) {
791 if (sslerr == SSL_ERROR_WANT_WRITE) {
793 ngx_log_error(NGX_LOG_INFO, c->log, 0,
794 "peer started SSL renegotiation");
798 if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
803 * we do not set the timer because there is already the read event timer
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;
814 c->ssl->no_wait_shutdown = 1;
815 c->ssl->no_send_shutdown = 1;
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");
823 ngx_ssl_connection_error(c, sslerr, err, "SSL_read() failed");
830 ngx_ssl_write_handler(ngx_event_t *wev)
836 c->read->handler(c->read);
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.
844 * Besides for protocols such as HTTP it is possible to always buffer
845 * the output to decrease a SSL overhead some more.
849 ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
856 if (!c->ssl->buffer) {
859 if (ngx_buf_special(in->buf)) {
864 n = ngx_ssl_write(c, in->buf->pos, in->buf->last - in->buf->pos);
866 if (n == NGX_ERROR) {
867 return NGX_CHAIN_ERROR;
870 if (n == NGX_AGAIN) {
871 c->buffered |= NGX_SSL_BUFFERED;
877 if (in->buf->pos == in->buf->last) {
886 /* the maximum limit size is the maximum uint32_t value - the page size */
888 if (limit == 0 || limit > (off_t) (NGX_MAX_UINT32_VALUE - ngx_pagesize)) {
889 limit = NGX_MAX_UINT32_VALUE - ngx_pagesize;
895 buf = ngx_create_temp_buf(c->pool, NGX_SSL_BUFSIZE);
897 return NGX_CHAIN_ERROR;
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;
909 buf->pos = buf->start;
910 buf->last = buf->start;
911 buf->end = buf->start + NGX_SSL_BUFSIZE;
915 flush = (in == NULL) ? 1 : 0;
919 while (in && buf->last < buf->end) {
920 if (in->buf->last_buf || in->buf->flush) {
924 if (ngx_buf_special(in->buf)) {
929 size = in->buf->last - in->buf->pos;
931 if (size > buf->end - buf->last) {
932 size = buf->end - buf->last;
935 if (send + size > limit) {
936 size = (ssize_t) (limit - send);
940 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
941 "SSL buf copy: %d", size);
943 ngx_memcpy(buf->last, in->buf->pos, size);
947 in->buf->pos += size;
949 if (in->buf->pos == in->buf->last) {
954 size = buf->last - buf->pos;
956 if (!flush && buf->last < buf->end && c->ssl->buffer) {
960 n = ngx_ssl_write(c, buf->pos, size);
962 if (n == NGX_ERROR) {
963 return NGX_CHAIN_ERROR;
966 if (n == NGX_AGAIN) {
967 c->buffered |= NGX_SSL_BUFFERED;
979 if (buf->pos == buf->last) {
980 buf->pos = buf->start;
981 buf->last = buf->start;
984 if (in == NULL || send == limit) {
989 if (buf->pos < buf->last) {
990 c->buffered |= NGX_SSL_BUFFERED;
993 c->buffered &= ~NGX_SSL_BUFFERED;
1001 ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size)
1006 ngx_ssl_clear_error(c->log);
1008 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL to write: %d", size);
1010 n = SSL_write(c->ssl->connection, data, size);
1012 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_write: %d", n);
1016 if (c->ssl->saved_read_handler) {
1018 c->read->handler = c->ssl->saved_read_handler;
1019 c->ssl->saved_read_handler = NULL;
1022 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1026 ngx_post_event(c->read, &ngx_posted_events);
1032 sslerr = SSL_get_error(c->ssl->connection, n);
1034 err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
1036 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
1038 if (sslerr == SSL_ERROR_WANT_WRITE) {
1039 c->write->ready = 0;
1043 if (sslerr == SSL_ERROR_WANT_READ) {
1045 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1046 "peer started SSL renegotiation");
1050 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1055 * we do not set the timer because there is already
1056 * the write event timer
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;
1067 c->ssl->no_wait_shutdown = 1;
1068 c->ssl->no_send_shutdown = 1;
1069 c->write->error = 1;
1071 ngx_ssl_connection_error(c, sslerr, err, "SSL_write() failed");
1078 ngx_ssl_read_handler(ngx_event_t *rev)
1080 ngx_connection_t *c;
1084 c->write->handler(c->write);
1089 ngx_ssl_free_buffer(ngx_connection_t *c)
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;
1100 ngx_ssl_shutdown(ngx_connection_t *c)
1102 int n, sslerr, mode;
1106 mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN;
1109 mode = SSL_get_shutdown(c->ssl->connection);
1111 if (c->ssl->no_wait_shutdown) {
1112 mode |= SSL_RECEIVED_SHUTDOWN;
1115 if (c->ssl->no_send_shutdown) {
1116 mode |= SSL_SENT_SHUTDOWN;
1120 SSL_set_shutdown(c->ssl->connection, mode);
1122 ngx_ssl_clear_error(c->log);
1124 n = SSL_shutdown(c->ssl->connection);
1126 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n);
1130 /* SSL_shutdown() never returns -1, on error it returns 0 */
1132 if (n != 1 && ERR_peek_error()) {
1133 sslerr = SSL_get_error(c->ssl->connection, n);
1135 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1136 "SSL_get_error: %d", sslerr);
1139 if (n == 1 || sslerr == 0 || sslerr == SSL_ERROR_ZERO_RETURN) {
1140 SSL_free(c->ssl->connection);
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;
1150 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1154 if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
1158 if (sslerr == SSL_ERROR_WANT_READ) {
1159 ngx_add_timer(c->read, 30000);
1165 err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
1167 ngx_ssl_connection_error(c, sslerr, err, "SSL_shutdown() failed");
1169 SSL_free(c->ssl->connection);
1177 ngx_ssl_shutdown_handler(ngx_event_t *ev)
1179 ngx_connection_t *c;
1180 ngx_connection_handler_pt handler;
1183 handler = c->ssl->handler;
1189 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "SSL shutdown handler");
1191 if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
1200 ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
1206 level = NGX_LOG_CRIT;
1208 if (sslerr == SSL_ERROR_SYSCALL) {
1210 if (err == NGX_ECONNRESET
1212 || err == NGX_ENOTCONN
1213 #if !(NGX_CRIT_ETIMEDOUT)
1214 || err == NGX_ETIMEDOUT
1216 || err == NGX_ECONNREFUSED
1217 || err == NGX_ENETDOWN
1218 || err == NGX_ENETUNREACH
1219 || err == NGX_EHOSTDOWN
1220 || err == NGX_EHOSTUNREACH)
1222 switch (c->log_error) {
1224 case NGX_ERROR_IGNORE_ECONNRESET:
1225 case NGX_ERROR_INFO:
1226 level = NGX_LOG_INFO;
1230 level = NGX_LOG_ERR;
1238 } else if (sslerr == SSL_ERROR_SSL) {
1240 n = ERR_GET_REASON(ERR_peek_error());
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 */
1275 switch (c->log_error) {
1277 case NGX_ERROR_IGNORE_ECONNRESET:
1278 case NGX_ERROR_INFO:
1279 level = NGX_LOG_INFO;
1283 level = NGX_LOG_ERR;
1292 ngx_ssl_error(level, c->log, err, text);
1297 ngx_ssl_clear_error(ngx_log_t *log)
1299 while (ERR_peek_error()) {
1300 ngx_ssl_error(NGX_LOG_ALERT, log, 0, "ignoring stale global SSL error");
1308 ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...)
1313 u_char errstr[NGX_MAX_CONF_ERRSTR];
1315 last = errstr + NGX_MAX_CONF_ERRSTR;
1317 va_start(args, fmt);
1318 p = ngx_vsnprintf(errstr, sizeof(errstr) - 1, fmt, args);
1321 p = ngx_cpystrn(p, (u_char *) " (SSL:", last - p);
1325 n = ERR_get_error();
1337 ERR_error_string_n(n, (char *) p, last - p);
1339 while (p < last && *p) {
1344 ngx_log_error(level, log, err, "%s)", errstr);
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)
1354 if (builtin_session_cache == NGX_SSL_NO_SCACHE) {
1355 SSL_CTX_set_session_cache_mode(ssl->ctx, SSL_SESS_CACHE_OFF);
1359 if (builtin_session_cache == NGX_SSL_NONE_SCACHE) {
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.
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);
1377 SSL_CTX_sess_set_cache_size(ssl->ctx, 1);
1382 cache_mode = SSL_SESS_CACHE_SERVER;
1384 if (shm_zone && builtin_session_cache == NGX_SSL_NO_BUILTIN_SCACHE) {
1385 cache_mode |= SSL_SESS_CACHE_NO_INTERNAL;
1388 SSL_CTX_set_session_cache_mode(ssl->ctx, cache_mode);
1390 SSL_CTX_set_session_id_context(ssl->ctx, sess_ctx->data, sess_ctx->len);
1392 if (builtin_session_cache != NGX_SSL_NO_BUILTIN_SCACHE) {
1394 if (builtin_session_cache != NGX_SSL_DFLT_BUILTIN_SCACHE) {
1395 SSL_CTX_sess_set_cache_size(ssl->ctx, builtin_session_cache);
1399 SSL_CTX_set_timeout(ssl->ctx, timeout);
1402 shm_zone->init = ngx_ssl_session_cache_init;
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);
1408 if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_session_cache_index, shm_zone)
1411 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
1412 "SSL_CTX_set_ex_data() failed");
1422 ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data)
1424 ngx_slab_pool_t *shpool;
1425 ngx_ssl_session_cache_t *cache;
1428 shm_zone->data = data;
1432 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
1434 cache = ngx_slab_alloc(shpool, sizeof(ngx_ssl_session_cache_t));
1435 if (cache == NULL) {
1439 ngx_rbtree_init(&cache->session_rbtree, &cache->sentinel,
1440 ngx_ssl_session_rbtree_insert_value);
1442 ngx_queue_init(&cache->expire_queue);
1444 shm_zone->data = cache;
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.
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.
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.
1463 * OpenSSL's i2d_SSL_SESSION() and d2i_SSL_SESSION are slow,
1464 * so they are outside the code locked by shared pool mutex
1468 ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
1471 u_char *p, *id, *cached_sess;
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];
1481 len = i2d_SSL_SESSION(sess, NULL);
1483 /* do not cache too big session */
1485 if (len > (int) NGX_SSL_MAX_SESSION_SIZE) {
1490 i2d_SSL_SESSION(sess, &p);
1492 c = ngx_ssl_get_connection(ssl_conn);
1494 ssl_ctx = SSL_get_SSL_CTX(ssl_conn);
1495 shm_zone = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_session_cache_index);
1497 cache = shm_zone->data;
1498 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
1500 ngx_shmtx_lock(&shpool->mutex);
1502 /* drop one or two expired sessions */
1503 ngx_ssl_expire_sessions(cache, shpool, 1);
1505 cached_sess = ngx_slab_alloc_locked(shpool, len);
1507 if (cached_sess == NULL) {
1509 /* drop the oldest non-expired session and try once more */
1511 ngx_ssl_expire_sessions(cache, shpool, 0);
1513 cached_sess = ngx_slab_alloc_locked(shpool, len);
1515 if (cached_sess == NULL) {
1521 sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t));
1522 if (sess_id == NULL) {
1526 #if (NGX_PTR_SIZE == 8)
1528 id = sess_id->sess_id;
1532 id = ngx_slab_alloc_locked(shpool, sess->session_id_length);
1539 ngx_memcpy(cached_sess, buf, len);
1541 ngx_memcpy(id, sess->session_id, sess->session_id_length);
1543 hash = ngx_crc32_short(sess->session_id, sess->session_id_length);
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);
1549 sess_id->node.key = hash;
1550 sess_id->node.data = (u_char) sess->session_id_length;
1553 sess_id->session = cached_sess;
1555 sess_id->expire = ngx_time() + SSL_CTX_get_timeout(ssl_ctx);
1557 ngx_queue_insert_head(&cache->expire_queue, &sess_id->queue);
1559 ngx_rbtree_insert(&cache->session_rbtree, &sess_id->node);
1561 ngx_shmtx_unlock(&shpool->mutex);
1568 ngx_slab_free_locked(shpool, cached_sess);
1572 ngx_slab_free_locked(shpool, sess_id);
1575 ngx_shmtx_unlock(&shpool->mutex);
1577 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
1578 "could not add new SSL session to the session cache");
1584 static ngx_ssl_session_t *
1585 ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, u_char *id, int len,
1588 #if OPENSSL_VERSION_NUMBER >= 0x0090707fL
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];
1603 c = ngx_ssl_get_connection(ssl_conn);
1605 hash = ngx_crc32_short(id, (size_t) len);
1608 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
1609 "http ssl get session: %08XD:%d", hash, len);
1611 shm_zone = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ssl_conn),
1612 ngx_ssl_session_cache_index);
1614 cache = shm_zone->data;
1618 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
1620 ngx_shmtx_lock(&shpool->mutex);
1622 node = cache->session_rbtree.root;
1623 sentinel = cache->session_rbtree.sentinel;
1625 while (node != sentinel) {
1627 if (hash < node->key) {
1632 if (hash > node->key) {
1637 /* hash == node->key */
1640 sess_id = (ngx_ssl_sess_id_t *) node;
1642 rc = ngx_memn2cmp(id, sess_id->id,
1643 (size_t) len, (size_t) node->data);
1646 if (sess_id->expire > ngx_time()) {
1647 ngx_memcpy(buf, sess_id->session, sess_id->len);
1649 ngx_shmtx_unlock(&shpool->mutex);
1652 sess = d2i_SSL_SESSION(NULL, &p, sess_id->len);
1657 ngx_queue_remove(&sess_id->queue);
1659 ngx_rbtree_delete(&cache->session_rbtree, node);
1661 ngx_slab_free_locked(shpool, sess_id->session);
1662 #if (NGX_PTR_SIZE == 4)
1663 ngx_slab_free_locked(shpool, sess_id->id);
1665 ngx_slab_free_locked(shpool, sess_id);
1672 node = (rc < 0) ? node->left : node->right;
1674 } while (node != sentinel && hash == node->key);
1681 ngx_shmtx_unlock(&shpool->mutex);
1688 ngx_ssl_remove_cached_session(SSL_CTX *ssl, ngx_ssl_session_t *sess)
1690 SSL_CTX_remove_session(ssl, sess);
1692 ngx_ssl_remove_session(ssl, sess);
1697 ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess)
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;
1709 shm_zone = SSL_CTX_get_ex_data(ssl, ngx_ssl_session_cache_index);
1711 if (shm_zone == NULL) {
1715 cache = shm_zone->data;
1717 id = sess->session_id;
1718 len = (size_t) sess->session_id_length;
1720 hash = ngx_crc32_short(id, len);
1722 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
1723 "http ssl remove session: %08XD:%uz", hash, len);
1725 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
1727 ngx_shmtx_lock(&shpool->mutex);
1729 node = cache->session_rbtree.root;
1730 sentinel = cache->session_rbtree.sentinel;
1732 while (node != sentinel) {
1734 if (hash < node->key) {
1739 if (hash > node->key) {
1744 /* hash == node->key */
1747 sess_id = (ngx_ssl_sess_id_t *) node;
1749 rc = ngx_memn2cmp(id, sess_id->id, len, (size_t) node->data);
1753 ngx_queue_remove(&sess_id->queue);
1755 ngx_rbtree_delete(&cache->session_rbtree, node);
1757 ngx_slab_free_locked(shpool, sess_id->session);
1758 #if (NGX_PTR_SIZE == 4)
1759 ngx_slab_free_locked(shpool, sess_id->id);
1761 ngx_slab_free_locked(shpool, sess_id);
1766 node = (rc < 0) ? node->left : node->right;
1768 } while (node != sentinel && hash == node->key);
1775 ngx_shmtx_unlock(&shpool->mutex);
1780 ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache,
1781 ngx_slab_pool_t *shpool, ngx_uint_t n)
1785 ngx_ssl_sess_id_t *sess_id;
1791 if (ngx_queue_empty(&cache->expire_queue)) {
1795 q = ngx_queue_last(&cache->expire_queue);
1797 sess_id = ngx_queue_data(q, ngx_ssl_sess_id_t, queue);
1799 if (n++ != 0 && sess_id->expire > now) {
1803 ngx_queue_remove(q);
1805 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
1806 "expire session: %08Xi", sess_id->node.key);
1808 ngx_rbtree_delete(&cache->session_rbtree, &sess_id->node);
1810 ngx_slab_free_locked(shpool, sess_id->session);
1811 #if (NGX_PTR_SIZE == 4)
1812 ngx_slab_free_locked(shpool, sess_id->id);
1814 ngx_slab_free_locked(shpool, sess_id);
1820 ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp,
1821 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
1823 ngx_rbtree_node_t **p;
1824 ngx_ssl_sess_id_t *sess_id, *sess_id_temp;
1828 if (node->key < temp->key) {
1832 } else if (node->key > temp->key) {
1836 } else { /* node->key == temp->key */
1838 sess_id = (ngx_ssl_sess_id_t *) node;
1839 sess_id_temp = (ngx_ssl_sess_id_t *) temp;
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;
1846 if (*p == sentinel) {
1854 node->parent = temp;
1855 node->left = sentinel;
1856 node->right = sentinel;
1862 ngx_ssl_cleanup_ctx(void *data)
1864 ngx_ssl_t *ssl = data;
1866 SSL_CTX_free(ssl->ctx);
1871 ngx_ssl_get_protocol(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
1873 s->data = (u_char *) SSL_get_version(c->ssl->connection);
1879 ngx_ssl_get_cipher_name(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
1881 s->data = (u_char *) SSL_get_cipher_name(c->ssl->connection);
1887 ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
1895 cert = SSL_get_peer_certificate(c->ssl->connection);
1900 bio = BIO_new(BIO_s_mem());
1902 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed");
1907 if (PEM_write_bio_X509(bio, cert) == 0) {
1908 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "PEM_write_bio_X509() failed");
1912 len = BIO_pending(bio);
1915 s->data = ngx_pnalloc(pool, len);
1916 if (s->data == NULL) {
1920 BIO_read(bio, s->data, len);
1937 ngx_ssl_get_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
1944 if (ngx_ssl_get_raw_certificate(c, pool, &cert) != NGX_OK) {
1948 if (cert.len == 0) {
1955 for (i = 0; i < cert.len - 1; i++) {
1956 if (cert.data[i] == LF) {
1962 s->data = ngx_pnalloc(pool, len);
1963 if (s->data == NULL) {
1969 for (i = 0; i < len; i++) {
1970 *p++ = cert.data[i];
1971 if (cert.data[i] == LF) {
1981 ngx_ssl_get_subject_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
1990 cert = SSL_get_peer_certificate(c->ssl->connection);
1995 name = X509_get_subject_name(cert);
2001 p = X509_NAME_oneline(name, NULL, 0);
2003 for (len = 0; p[len]; len++) { /* void */ }
2006 s->data = ngx_pnalloc(pool, len);
2007 if (s->data == NULL) {
2013 ngx_memcpy(s->data, p, len);
2023 ngx_ssl_get_issuer_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
2032 cert = SSL_get_peer_certificate(c->ssl->connection);
2037 name = X509_get_issuer_name(cert);
2043 p = X509_NAME_oneline(name, NULL, 0);
2045 for (len = 0; p[len]; len++) { /* void */ }
2048 s->data = ngx_pnalloc(pool, len);
2049 if (s->data == NULL) {
2055 ngx_memcpy(s->data, p, len);
2065 ngx_ssl_get_serial_number(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
2073 cert = SSL_get_peer_certificate(c->ssl->connection);
2078 bio = BIO_new(BIO_s_mem());
2084 i2a_ASN1_INTEGER(bio, X509_get_serialNumber(cert));
2085 len = BIO_pending(bio);
2088 s->data = ngx_pnalloc(pool, len);
2089 if (s->data == NULL) {
2095 BIO_read(bio, s->data, len);
2104 ngx_openssl_create_conf(ngx_cycle_t *cycle)
2106 ngx_openssl_conf_t *oscf;
2108 oscf = ngx_pcalloc(cycle->pool, sizeof(ngx_openssl_conf_t));
2110 return NGX_CONF_ERROR;
2114 * set by ngx_pcalloc():
2116 * oscf->engine.len = 0;
2117 * oscf->engine.data = NULL;
2125 ngx_openssl_init_conf(ngx_cycle_t *cycle, void *conf)
2127 #if (NGX_SSL_ENGINE)
2128 ngx_openssl_conf_t *oscf = conf;
2132 if (oscf->engine.len == 0) {
2136 engine = ENGINE_by_id((const char *) oscf->engine.data);
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;
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",
2148 return NGX_CONF_ERROR;
2151 ENGINE_free(engine);
2159 #if !(NGX_SSL_ENGINE)
2162 ngx_openssl_noengine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
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,");
2168 return NGX_CONF_ERROR;
2175 ngx_openssl_exit(ngx_cycle_t *cycle)
2177 #if (NGX_SSL_ENGINE)