ngx_event_openssl.c
来自「Nginx是一个高性能的HTTP和反向代理服务器」· C语言 代码 · 共 1,975 行 · 第 1/4 页
C
1,975 行
/* * Copyright (C) Igor Sysoev */#include <ngx_config.h>#include <ngx_core.h>#include <ngx_event.h>typedef struct { ngx_str_t engine;} ngx_openssl_conf_t;static int ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store);static void ngx_ssl_handshake_handler(ngx_event_t *ev);static ngx_int_t ngx_ssl_handle_recv(ngx_connection_t *c, int n);static void ngx_ssl_write_handler(ngx_event_t *wev);static void ngx_ssl_read_handler(ngx_event_t *rev);static void ngx_ssl_shutdown_handler(ngx_event_t *ev);static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err, char *text);static void ngx_ssl_clear_error(ngx_log_t *log);static ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data);static int ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess);static ngx_ssl_session_t *ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, u_char *id, int len, int *copy);static void ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess);static void ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache, ngx_slab_pool_t *shpool, ngx_uint_t n);static void ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);static void *ngx_openssl_create_conf(ngx_cycle_t *cycle);static char *ngx_openssl_init_conf(ngx_cycle_t *cycle, void *conf);static void ngx_openssl_exit(ngx_cycle_t *cycle);#if !(NGX_SSL_ENGINE)static char *ngx_openssl_noengine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);#endifstatic ngx_command_t ngx_openssl_commands[] = { { ngx_string("ssl_engine"), NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,#if (NGX_SSL_ENGINE) ngx_conf_set_str_slot,#else ngx_openssl_noengine,#endif 0, offsetof(ngx_openssl_conf_t, engine), NULL }, ngx_null_command};static ngx_core_module_t ngx_openssl_module_ctx = { ngx_string("openssl"), ngx_openssl_create_conf, ngx_openssl_init_conf};ngx_module_t ngx_openssl_module = { NGX_MODULE_V1, &ngx_openssl_module_ctx, /* module context */ ngx_openssl_commands, /* module directives */ NGX_CORE_MODULE, /* module type */ NULL, /* init master */ NULL, /* init module */ NULL, /* init process */ NULL, /* init thread */ NULL, /* exit thread */ NULL, /* exit process */ ngx_openssl_exit, /* exit master */ NGX_MODULE_V1_PADDING};static long ngx_ssl_protocols[] = { SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1, SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1, SSL_OP_NO_SSLv2|SSL_OP_NO_TLSv1, SSL_OP_NO_TLSv1, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3, SSL_OP_NO_SSLv3, SSL_OP_NO_SSLv2, 0,};int ngx_ssl_connection_index;int ngx_ssl_server_conf_index;int ngx_ssl_session_cache_index;ngx_int_tngx_ssl_init(ngx_log_t *log){#if OPENSSL_VERSION_NUMBER >= 0x00907000 OPENSSL_config(NULL);#endif SSL_library_init(); SSL_load_error_strings();#if (NGX_SSL_ENGINE) ENGINE_load_builtin_engines();#endif ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); if (ngx_ssl_connection_index == -1) { ngx_ssl_error(NGX_LOG_ALERT, log, 0, "SSL_get_ex_new_index() failed"); return NGX_ERROR; } ngx_ssl_server_conf_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL); if (ngx_ssl_server_conf_index == -1) { ngx_ssl_error(NGX_LOG_ALERT, log, 0, "SSL_CTX_get_ex_new_index() failed"); return NGX_ERROR; } ngx_ssl_session_cache_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL); if (ngx_ssl_session_cache_index == -1) { ngx_ssl_error(NGX_LOG_ALERT, log, 0, "SSL_CTX_get_ex_new_index() failed"); return NGX_ERROR; } return NGX_OK;}ngx_int_tngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data){ ssl->ctx = SSL_CTX_new(SSLv23_method()); if (ssl->ctx == NULL) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_new() failed"); return NGX_ERROR; } if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_server_conf_index, data) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_set_ex_data() failed"); return NGX_ERROR; } /* client side options */ SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_SESS_ID_BUG); SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_CHALLENGE_BUG); SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG); /* server side options */ SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG); SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER); /* this option allow a potential SSL 2.0 rollback (CAN-2005-2969) */ SSL_CTX_set_options(ssl->ctx, SSL_OP_MSIE_SSLV2_RSA_PADDING); SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLEAY_080_CLIENT_DH_BUG); SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_D5_BUG); SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_BLOCK_PADDING_BUG);#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS SSL_CTX_set_options(ssl->ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);#endif if (ngx_ssl_protocols[protocols >> 1] != 0) { SSL_CTX_set_options(ssl->ctx, ngx_ssl_protocols[protocols >> 1]); } /* * we need this option because in ngx_ssl_send_chain() * we may switch to a buffered write and may copy leftover part of * previously unbuffered data to our internal buffer */ SSL_CTX_set_mode(ssl->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); SSL_CTX_set_read_ahead(ssl->ctx, 1); return NGX_OK;}ngx_int_tngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, ngx_str_t *key){ if (ngx_conf_full_name(cf->cycle, cert, 1) == NGX_ERROR) { return NGX_ERROR; } if (SSL_CTX_use_certificate_chain_file(ssl->ctx, (char *) cert->data) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_use_certificate_chain_file(\"%s\") failed", cert->data); return NGX_ERROR; } if (ngx_conf_full_name(cf->cycle, key, 1) == NGX_ERROR) { return NGX_ERROR; } if (SSL_CTX_use_PrivateKey_file(ssl->ctx, (char *) key->data, SSL_FILETYPE_PEM) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_use_PrivateKey_file(\"%s\") failed", key->data); return NGX_ERROR; } return NGX_OK;}ngx_int_tngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, ngx_int_t depth){ STACK_OF(X509_NAME) *list; SSL_CTX_set_verify(ssl->ctx, SSL_VERIFY_PEER, ngx_http_ssl_verify_callback); SSL_CTX_set_verify_depth(ssl->ctx, depth); if (cert->len == 0) { return NGX_OK; } if (ngx_conf_full_name(cf->cycle, cert, 1) == NGX_ERROR) { return NGX_ERROR; } if (SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_load_verify_locations(\"%s\") failed", cert->data); return NGX_ERROR; } list = SSL_load_client_CA_file((char *) cert->data); if (list == NULL) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_load_client_CA_file(\"%s\") failed", cert->data); return NGX_ERROR; } /* * before 0.9.7h and 0.9.8 SSL_load_client_CA_file() * always leaved an error in the error queue */ ERR_clear_error(); SSL_CTX_set_client_CA_list(ssl->ctx, list); return NGX_OK;}static intngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store){#if (NGX_DEBUG) char *subject, *issuer; int err, depth; X509 *cert; X509_NAME *sname, *iname; ngx_connection_t *c; ngx_ssl_conn_t *ssl_conn; ssl_conn = X509_STORE_CTX_get_ex_data(x509_store, SSL_get_ex_data_X509_STORE_CTX_idx()); c = ngx_ssl_get_connection(ssl_conn); cert = X509_STORE_CTX_get_current_cert(x509_store); err = X509_STORE_CTX_get_error(x509_store); depth = X509_STORE_CTX_get_error_depth(x509_store); sname = X509_get_subject_name(cert); subject = sname ? X509_NAME_oneline(sname, NULL, 0) : "(none)"; iname = X509_get_issuer_name(cert); issuer = iname ? X509_NAME_oneline(iname, NULL, 0) : "(none)"; ngx_log_debug5(NGX_LOG_DEBUG_EVENT, c->log, 0, "verify:%d, error:%d, depth:%d, " "subject:\"%s\",issuer: \"%s\"", ok, err, depth, subject, issuer); if (sname) { OPENSSL_free(subject); } if (iname) { OPENSSL_free(issuer); }#endif return 1;}ngx_int_tngx_ssl_generate_rsa512_key(ngx_ssl_t *ssl){ RSA *key; if (SSL_CTX_need_tmp_RSA(ssl->ctx) == 0) { return NGX_OK; } key = RSA_generate_key(512, RSA_F4, NULL, NULL); if (key) { SSL_CTX_set_tmp_rsa(ssl->ctx, key); RSA_free(key); return NGX_OK; } ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "RSA_generate_key(512) failed"); return NGX_ERROR;}ngx_int_tngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags){ ngx_ssl_connection_t *sc; sc = ngx_pcalloc(c->pool, sizeof(ngx_ssl_connection_t)); if (sc == NULL) { return NGX_ERROR; } sc->buffer = ((flags & NGX_SSL_BUFFER) != 0); sc->connection = SSL_new(ssl->ctx); if (sc->connection == NULL) { ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_new() failed"); return NGX_ERROR; } if (SSL_set_fd(sc->connection, c->fd) == 0) { ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_fd() failed"); return NGX_ERROR; } if (flags & NGX_SSL_CLIENT) { SSL_set_connect_state(sc->connection); } else { SSL_set_accept_state(sc->connection); } if (SSL_set_ex_data(sc->connection, ngx_ssl_connection_index, c) == 0) { ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_ex_data() failed"); return NGX_ERROR; } c->ssl = sc; return NGX_OK;}ngx_int_tngx_ssl_set_session(ngx_connection_t *c, ngx_ssl_session_t *session){ if (session) { if (SSL_set_session(c->ssl->connection, session) == 0) { ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_session() failed"); return NGX_ERROR; } } return NGX_OK;}ngx_int_tngx_ssl_handshake(ngx_connection_t *c){ int n, sslerr; ngx_err_t err; ngx_ssl_clear_error(c->log); n = SSL_do_handshake(c->ssl->connection); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n); if (n == 1) { if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) { return NGX_ERROR; } if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) { return NGX_ERROR; }#if (NGX_DEBUG) { char buf[129], *s, *d; SSL_CIPHER *cipher; cipher = SSL_get_current_cipher(c->ssl->connection); if (cipher) { SSL_CIPHER_description(cipher, &buf[1], 128); for (s = &buf[1], d = buf; *s; s++) { if (*s == ' ' && *d == ' ') { continue; } if (*s == LF || *s == CR) { continue; } *++d = *s; } if (*d != ' ') { d++; } *d = '\0'; ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL: %s, cipher: \"%s\"", SSL_get_version(c->ssl->connection), &buf[1]); if (SSL_session_reused(c->ssl->connection)) { ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL reused session"); } } else { ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL no shared ciphers"); } }#endif c->ssl->handshaked = 1; c->recv = ngx_ssl_recv; c->send = ngx_ssl_write; c->recv_chain = ngx_ssl_recv_chain; c->send_chain = ngx_ssl_send_chain; return NGX_OK; } sslerr = SSL_get_error(c->ssl->connection, n); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr); if (sslerr == SSL_ERROR_WANT_READ) { c->read->ready = 0; c->read->handler = ngx_ssl_handshake_handler; c->write->handler = ngx_ssl_handshake_handler;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?