nginx openssl 的集成代码流程
2014-06-11 17:43
2231 查看
本文转载自:http://blog.chinaunix.net/uid-26335251-id-3508765.html
说明:
一、这里个人测试完全和nginx处理流程和返回的数据完全一致
二、这里做了只是做了简要抽取,如果作为服务器,能实现这些步骤整体ssl处理应该没有任何问题。
三、这里包含三个文件:NGXSSL.c 为主文件,source.h为头文件,source.c为部分代码文件。
source.h
source.c
NGXSSL.c
说明:
一、这里个人测试完全和nginx处理流程和返回的数据完全一致
二、这里做了只是做了简要抽取,如果作为服务器,能实现这些步骤整体ssl处理应该没有任何问题。
三、这里包含三个文件:NGXSSL.c 为主文件,source.h为头文件,source.c为部分代码文件。
source.h
/* * source.h * * Created on: 2013-3-3 * Author: root */ #ifndef SOURCE_H_ #define SOURCE_H_ #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <unistd.h> #include <sys/types.h> #include <sys/epoll.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/ioctl.h> #include <openssl/ssl.h> #include <openssl/err.h> #include <openssl/conf.h> #include <openssl/engine.h> #include <openssl/evp.h> //错误码的定义 #define NGX_OK 0 #define NGX_ERROR -1 #define NGX_AGAIN -2 #define NGX_BUSY -3 #define NGX_DONE -4 #define NGX_DECLINED -5 #define NGX_ABORT -6 #if (NGX_HAVE_ACCEPT4) static ngx_uint_t use_accept4 = 1; #endif typedef int ngx_socket_t; int ngx_ssl_connection_index; int ngx_ssl_server_conf_index; int ngx_ssl_session_cache_index; #define NGX_SSL_SSLv2 0x0002 #define NGX_SSL_SSLv3 0x0004 #define NGX_SSL_TLSv1 0x0008 #define NGX_SSL_TLSv1_1 0x0010 #define NGX_SSL_TLSv1_2 0x0020 #define ngx_ssl_get_connection(ssl_conn) SSL_get_ex_data(ssl_conn, ngx_ssl_connection_index) #define ngx_ssl_conn_t SSL #define ngx_close_socket close #define ngx_socket socket //错误吗的定义 #define NGX_OK 0 #define NGX_ERROR -1 #define NGX_AGAIN -2 #define NGX_BUSY -3 #define NGX_DONE -4 #define NGX_DECLINED -5 #define NGX_ABORT -6 typedef intptr_t ngx_int_t; //long int 定义 typedef uintptr_t ngx_uint_t; //unsigned long int定义 typedef intptr_t ngx_flag_t; typedef struct { SSL_CTX *ctx; } ngx_ssl_t; RSA * ngx_ssl_rsa512_key_callback(SSL *ssl, int is_export, int key_length); int ngx_nonblocking(ngx_socket_t s); void ngx_http_ssl_handshake(int fd,ngx_ssl_conn_t *connection); ngx_int_t ngx_ssl_handshake(ngx_ssl_conn_t *connection); ngx_int_t ngx_ssl_shutdown(ngx_ssl_conn_t *connection); void ngx_ssl_clear_error(); #endif /* SOURCE_H_ */
source.c
/* * source.c * * Created on: 2013-3-3 * Author: root */ #include "source.h" //设置一个临时的RSA,在出口算法中,有规定需要这么做的 RSA * ngx_ssl_rsa512_key_callback(SSL *ssl, int is_export, int key_length) { static RSA *key; if (key_length == 512) { if (key == NULL) { key = RSA_generate_key(512, RSA_F4, NULL, NULL); } } return key; } // int ngx_nonblocking(ngx_socket_t s) { int nb; nb = 1; return ioctl(s, FIONBIO, &nb); } void ngx_http_ssl_handshake(int fd,ngx_ssl_conn_t *connection) { u_char buf[1]; ssize_t n; ngx_int_t rc; //如果在recv的时候,flag字段设置了MSG_PEEK,则读取数据包的时候,不会把该数据包从缓存队列中删除;下次读取时还是这个数据包 n = recv(fd, (char *) buf, 1, MSG_PEEK); if (n == 1) { if (buf[0] & 0x80 /* SSLv2 */|| buf[0] == 0x16 /* SSLv3/TLSv1 */) { //对不同加密协议进行判断 rc = ngx_ssl_handshake(connection); //处理握手和单向认证 if (rc == NGX_AGAIN) { return; } return; }else { //http 平台的请求,如果是http平台的请求,就走一般流程返回错我信息 return; } } return; } ngx_int_t ngx_ssl_handshake(ngx_ssl_conn_t *connection) { int n, sslerr; n = SSL_do_handshake(connection); //这里会试着握手,由于上次recv之后,会有数据正在写入,返回-1 if (n == 1) { /* initial handshake done, disable renegotiation (CVE-2009-3555) */ if (connection->s3) { connection->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS; } return NGX_OK; } sslerr = SSL_get_error(connection, n); //这里应该再重新接收一次和NGINX一样,等待下一次循环(epoll)再进行,同时设置读写句柄,以便下次读取的时候直接进行握手 if (sslerr == SSL_ERROR_WANT_READ) { n = SSL_do_handshake(connection); if (n == 1) { /* initial handshake done, disable renegotiation (CVE-2009-3555) */ if (connection->s3) { connection->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS; } return NGX_OK;//握手成功,就可以读取了 } } return NGX_AGAIN; } //ret->quiet_shutdown=1;默认的是ret->quiet_shutdown=0;他相当于SSL_set_shutdown函数将参数设置为SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN // 当设置为1时,假如关闭后,不通知对方,这样不适合TLS标准 ngx_int_t ngx_ssl_shutdown(ngx_ssl_conn_t *connection) { //这里是对认证正确的处理方式简要地关闭处理 int n, sslerr, mode; // ngx_err_t err; // if (c->timedout) { //超时,可能是读取或写入超时导致 if(0){ mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN; SSL_set_quiet_shutdown(connection, 1); //设置为1时,假如关闭后,不通知对方 } else { mode = SSL_get_shutdown(connection); // if (c->ssl->no_wait_shutdown) { mode |= SSL_RECEIVED_SHUTDOWN; // } // if (c->ssl->no_send_shutdown) { mode |= SSL_SENT_SHUTDOWN; // } // if (c->ssl->no_wait_shutdown && c->ssl->no_send_shutdown) { SSL_set_quiet_shutdown(connection, 1); // } } SSL_set_shutdown(connection, mode); ngx_ssl_clear_error(); n = SSL_shutdown(connection);//关闭SSL套接字 sslerr = 0; // /* SSL_shutdown() never returns -1, on error it returns 0 */ // if (n == 1 || sslerr == 0 || sslerr == SSL_ERROR_ZERO_RETURN) { SSL_free(connection); //释放SSL套接字 // c->ssl = NULL; return NGX_OK; //到这里结束了 // } // // return NGX_OK; } void ngx_ssl_clear_error() { //对错误信息的清理工作 while (ERR_peek_error()) { } ERR_clear_error(); } // //ngx_int_t ngx_ssl_init(void) { // OPENSSL_config(NULL); // // SSL_library_init(); // SSL_load_error_strings(); // // OpenSSL_add_all_algorithms(); // // ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); // // if (ngx_ssl_connection_index == -1) { // printf("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) { // printf("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) { // printf("SSL_CTX_get_ex_new_index() failed"); // return NGX_ERROR; // } // // return NGX_OK; //} // ////static void * ////ngx_openssl_create_conf(ngx_cycle_t *cycle) ////{ //// ngx_openssl_conf_t *oscf; //// //// oscf = ngx_pcalloc(cycle->pool, sizeof(ngx_openssl_conf_t)); //// if (oscf == NULL) { //// return NULL; //// } //// //// /* //// * set by ngx_pcalloc(): //// * //// * oscf->engine = 0; //// */ //// //// return oscf; ////} //// ////static void * ////ngx_http_ssl_create_srv_conf(ngx_conf_t *cf) ////{ //// ngx_http_ssl_srv_conf_t *sscf; //// //// sscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssl_srv_conf_t)); //// if (sscf == NULL) { //// return NULL; //// } //// //// /* //// * set by ngx_pcalloc(): //// * //// * sscf->protocols = 0; //// * sscf->certificate = { 0, NULL }; //// * sscf->certificate_key = { 0, NULL }; //// * sscf->dhparam = { 0, NULL }; //// * sscf->ecdh_curve = { 0, NULL }; //// * sscf->client_certificate = { 0, NULL }; //// * sscf->crl = { 0, NULL }; //// * sscf->ciphers = { 0, NULL }; //// * sscf->shm_zone = NULL; //// */ //// //// sscf->enable = NGX_CONF_UNSET; //// sscf->prefer_server_ciphers = NGX_CONF_UNSET; //// sscf->verify = NGX_CONF_UNSET_UINT; //// sscf->verify_depth = NGX_CONF_UNSET_UINT; //// sscf->builtin_session_cache = NGX_CONF_UNSET; //// sscf->session_timeout = NGX_CONF_UNSET; //// //// return sscf; ////} //// ////static ngx_int_t ////ngx_http_ssl_add_variables(ngx_conf_t *cf) ////{ //// ngx_http_variable_t *var, *v; //// //// for (v = ngx_http_ssl_vars; v->name.len; v++) { //// var = ngx_http_add_variable(cf, &v->name, v->flags); //// if (var == NULL) { //// return NGX_ERROR; //// } //// //// var->get_handler = v->get_handler; //// var->data = v->data; //// } //// //// return NGX_OK; ////} //// ////static void * ////ngx_http_ssl_create_srv_conf(ngx_conf_t *cf) ////{ //// ngx_http_ssl_srv_conf_t *sscf; //// //// sscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssl_srv_conf_t)); //// if (sscf == NULL) { //// return NULL; //// } //// //// /* //// * set by ngx_pcalloc(): //// * //// * sscf->protocols = 0; //// * sscf->certificate = { 0, NULL }; //// * sscf->certificate_key = { 0, NULL }; //// * sscf->dhparam = { 0, NULL }; //// * sscf->ecdh_curve = { 0, NULL }; //// * sscf->client_certificate = { 0, NULL }; //// * sscf->crl = { 0, NULL }; //// * sscf->ciphers = { 0, NULL }; //// * sscf->shm_zone = NULL; //// */ //// //// sscf->enable = NGX_CONF_UNSET; //// sscf->prefer_server_ciphers = NGX_CONF_UNSET; //// sscf->verify = NGX_CONF_UNSET_UINT; //// sscf->verify_depth = NGX_CONF_UNSET_UINT; //// sscf->builtin_session_cache = NGX_CONF_UNSET; //// sscf->session_timeout = NGX_CONF_UNSET; //// //// return sscf; ////} //// //// //ngx_int_t ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data) { // ssl->ctx = SSL_CTX_new(SSLv23_method()); // // if (ssl->ctx == NULL) { // printf("SSL_CTX_new() failed"); // return NGX_ERROR; // } // // if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_server_conf_index, data) == 0) { // printf("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); // // /* 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); // // SSL_CTX_set_options(ssl->ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); // // SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_DH_USE); // // if (!(protocols & NGX_SSL_SSLv2)) { // SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_SSLv2); // } // if (!(protocols & NGX_SSL_SSLv3)) { // SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_SSLv3); // } // if (!(protocols & NGX_SSL_TLSv1)) { // SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1); // } // //#ifdef SSL_OP_NO_COMPRESSION // SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_COMPRESSION); //#endif // //#ifdef SSL_MODE_RELEASE_BUFFERS // SSL_CTX_set_mode(ssl->ctx, SSL_MODE_RELEASE_BUFFERS); //#endif // // SSL_CTX_set_read_ahead(ssl->ctx, 1); // // SSL_CTX_set_info_callback(ssl->ctx, ngx_ssl_info_callback); // // return NGX_OK; //} // //void ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, int ret) { // // void *c; // // // // if (where & SSL_CB_HANDSHAKE_START) { // // c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn); // // // // if (c) { // // printf("SSL renegotiation"); // // } // // } // // printf("SSL renegotiation"); //} // //int ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) { // const char *servername; // // servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name); // // if (servername == NULL) { // return SSL_TLSEXT_ERR_NOACK; // } // // c = ngx_ssl_get_connection(ssl_conn); // // printf("SSL server name: "%s"", servername); // // return SSL_TLSEXT_ERR_OK; //} // //ngx_int_t ngx_ssl_certificate(ngx_ssl_t *ssl, const char *cert, const char *key) { // if (SSL_CTX_use_certificate_chain_file(ssl->ctx, (char *) cert) == 0) { // printf("SSL_CTX_use_certificate_chain_file("%s") failed", cert); // return NGX_ERROR; // } // // if (SSL_CTX_use_PrivateKey_file(ssl->ctx, (char *) key, SSL_FILETYPE_PEM) // == 0) { // printf("SSL_CTX_use_PrivateKey_file("%s") failed", key); // return NGX_ERROR; // } // // return NGX_OK; //} // // //ngx_ssl_conn_t * ngx_ssl_create_connection(ngx_ssl_t *ssl, int socketid) { // c = malloc(1024); // ngx_ssl_conn_t *connection; // // connection = SSL_new(ssl->ctx); // // if (connection == NULL) { // return NULL; // } // // if (SSL_set_fd(connection, socketid) == 0) { // return NULL; // } // SSL_set_accept_state(connection); // if (SSL_set_ex_data(connection, ngx_ssl_connection_index, c) == 0) { // return NULL; // } // // return connection; //} // // //ngx_int_t ngx_ssl_dhparam(ngx_ssl_t *ssl, const char *file) { // DH *dh; // BIO *bio; // // /* // * -----BEGIN DH PARAMETERS----- // * MIGHAoGBALu8LcrYRnSQfEP89YDpz9vZWKP1aLQtSwju1OsPs1BMbAMCducQgAxc // * y7qokiYUxb7spWWl/fHSh6K8BJvmd4Bg6RqSp1fjBI9osHb302zI8pul34HcLKcl // * 7OZicMyaUDXYzs7vnqAnSmOrHlj6/UmI0PZdFGdX2gcd8EXP4WubAgEC // * -----END DH PARAMETERS----- // */ // // static unsigned char dh1024_p[] = { 0xBB, 0xBC, 0x2D, 0xCA, 0xD8, 0x46, // 0x74, 0x90, 0x7C, 0x43, 0xFC, 0xF5, 0x80, 0xE9, 0xCF, 0xDB, 0xD9, // 0x58, 0xA3, 0xF5, 0x68, 0xB4, 0x2D, 0x4B, 0x08, 0xEE, 0xD4, 0xEB, // 0x0F, 0xB3, 0x50, 0x4C, 0x6C, 0x03, 0x02, 0x76, 0xE7, 0x10, 0x80, // 0x0C, 0x5C, 0xCB, 0xBA, 0xA8, 0x92, 0x26, 0x14, 0xC5, 0xBE, 0xEC, // 0xA5, 0x65, 0xA5, 0xFD, 0xF1, 0xD2, 0x87, 0xA2, 0xBC, 0x04, 0x9B, // 0xE6, 0x77, 0x80, 0x60, 0xE9, 0x1A, 0x92, 0xA7, 0x57, 0xE3, 0x04, // 0x8F, 0x68, 0xB0, 0x76, 0xF7, 0xD3, 0x6C, 0xC8, 0xF2, 0x9B, 0xA5, // 0xDF, 0x81, 0xDC, 0x2C, 0xA7, 0x25, 0xEC, 0xE6, 0x62, 0x70, 0xCC, // 0x9A, 0x50, 0x35, 0xD8, 0xCE, 0xCE, 0xEF, 0x9E, 0xA0, 0x27, 0x4A, // 0x63, 0xAB, 0x1E, 0x58, 0xFA, 0xFD, 0x49, 0x88, 0xD0, 0xF6, 0x5D, // 0x14, 0x67, 0x57, 0xDA, 0x07, 0x1D, 0xF0, 0x45, 0xCF, 0xE1, 0x6B, // 0x9B }; // // static unsigned char dh1024_g[] = { 0x02 }; // // if (!file) { // // dh = DH_new(); // if (dh == NULL) { // return NGX_ERROR; // } // // dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL); // dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL); // // if (dh->p == NULL || dh->g == NULL) { // DH_free(dh); // return NGX_ERROR; // } // // SSL_CTX_set_tmp_dh(ssl->ctx, dh); // // DH_free(dh); // // return NGX_OK; // } // // bio = BIO_new_file((char *) file, "r"); // if (bio == NULL) { // return NGX_ERROR; // } // // dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); // if (dh == NULL) { // BIO_free(bio); // return NGX_ERROR; // } // // SSL_CTX_set_tmp_dh(ssl->ctx, dh); // // DH_free(dh); // BIO_free(bio); // // return NGX_OK; //} // //ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, const char *sess_ctx, // ssize_t builtin_session_cache, time_t timeout) { // SSL_CTX_set_session_id_context(ssl->ctx, (const unsigned char *) sess_ctx,strlen(sess_ctx)); // // SSL_CTX_set_session_cache_mode(ssl->ctx, // SSL_SESS_CACHE_SERVER // |SSL_SESS_CACHE_NO_AUTO_CLEAR // |SSL_SESS_CACHE_NO_INTERNAL_STORE); // // SSL_CTX_sess_set_cache_size(ssl->ctx, 1); // // return NGX_OK; // //} //// //////打开监听到接口,只绑定了一个 ////ngx_socket_t ngx_open_listening_sockets() { //// int reuseaddr; //// ngx_socket_t s; //// reuseaddr = 1; //重用地址 //// struct sockaddr_in addr; //// //// s = ngx_socket(AF_INET, SOCK_STREAM, 0); //创建套接口 //// if (s == -1) { //// return NGX_ERROR; //// } //// //// /* 填写sockaddr_in结构*/ //// bzero(&addr, sizeof(addr)); //// addr.sin_family = AF_INET; //// addr.sin_port = htons(443); //// addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //// //// if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuseaddr, //// sizeof(int)) == -1) { //// if (ngx_close_socket(s) == -1) { //出错就把它关闭 //// } //// return NGX_ERROR; //// } //// //// if (ngx_nonblocking(s) == -1) { //堵塞失败调用 //// if (ngx_close_socket(s) == -1) { //关闭套接字 //// } //// return NGX_ERROR; //// } //// //// if (bind(s, (struct sockaddr*) &addr, sizeof(addr)) == -1) { //绑定 //// return NGX_ERROR; //// } //// //// if (listen(s, 5) == -1) { //监听套接口 //// if (ngx_close_socket(s) == -1) { //// } //// return NGX_ERROR; //// } //// //// return s; ////}
NGXSSL.c
/* ============================================================================ Name : NGXSSL.c Author : xiangrongcheng Version : Copyright : Your copyright notice Description : Ansi-style ============================================================================ */ #include <stdio.h> #include <stdlib.h> #include "source.h" int epfd; int main(void) { // void *data = NULL; //认证和密钥目录 const char * certificate = "/usr/local/nginx/conf/api.bz.crt"; const char * certificate_key = "/usr/local/nginx/conf/api.bz_nopass.key"; //这里模拟nginx初始化 // ngx_ssl_init(); //初始化ssl OPENSSL_config(NULL); //加载openssl的配置信息,不知道对否 SSL_library_init(); //加载ssl库函数 SSL_load_error_strings(); //格式化错误日志信息 OpenSSL_add_all_algorithms(); //load所有的SSL算法 // //这里没有必要,是做为缓存,会话和连接池处理的 // ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); // if (ngx_ssl_connection_index == -1) { // printf("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) { // printf("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) { // printf("SSL_CTX_get_ex_new_index() failed"); // return NGX_ERROR; // } //创建ssl ngx_ssl_t ssl; ngx_uint_t protocols = 61; // ngx_ssl_create(ssl, protocols, data); ssl.ctx = SSL_CTX_new(SSLv23_method()); //通过SSL所用方法新建SSL_CTX上下文信息 if (ssl.ctx == NULL) { printf("SSL_CTX_new() failed"); return NGX_ERROR; } // //设置上下文信息的数据,保存扩展数据(应该不是很需要) // if (SSL_CTX_set_ex_data(ssl.ctx, ngx_ssl_server_conf_index, data) == 0) { // printf("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); /* 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); SSL_CTX_set_options(ssl.ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); SSL_CTX_set_options(ssl.ctx, SSL_OP_SINGLE_DH_USE); if (!(protocols & NGX_SSL_SSLv2)) { SSL_CTX_set_options(ssl.ctx, SSL_OP_NO_SSLv2); } if (!(protocols & NGX_SSL_SSLv3)) { SSL_CTX_set_options(ssl.ctx, SSL_OP_NO_SSLv3); } if (!(protocols & NGX_SSL_TLSv1)) { SSL_CTX_set_options(ssl.ctx, SSL_OP_NO_TLSv1); } #ifdef SSL_OP_NO_COMPRESSION SSL_CTX_set_options(ssl.ctx, SSL_OP_NO_COMPRESSION); #endif #ifdef SSL_MODE_RELEASE_BUFFERS SSL_CTX_set_mode(ssl.ctx, SSL_MODE_RELEASE_BUFFERS); #endif //这里一定需要,设置读取头一个字节,作为判断协议,如果不设定那么将使得n = SSL_read(connection, buffer, 512);少读前一个字节,因为读取第一个字节作为判断字节 SSL_CTX_set_read_ahead(ssl.ctx, 1); //下面也不是必要的 // SSL_CTX_set_info_callback(ssl.ctx, ngx_ssl_info_callback); // SSL_CTX_set_tlsext_servername_callback(ssl.ctx,ngx_http_ssl_servername); // ngx_ssl_certificate(ssl, certificate, certificate_key); // SSL_CTX_load_verify_locations用于加载受信任的CA证书,CAfile如果不为NULL,则他指向的文件包含PEM编码格式的一个或多个证书,可以用e.g.来简要介绍证书内容 // CApath如果不为NULL,则它指向一个包含PEM格式的CA证书的目录,目录中每个文件包含一份CA证书,文件名是证书中CA名的HASH值 // 可以用c-rehash来建立该目录,如cd /some/where/certs(包含了很多可信任的CA证书) c_rehash .。返回一成功,0 失败。SSL_CTX_set_default_verify_paths找寻默认的验证路径,在这里肯定找不到的。 // 这里主要set cert_store // char *CAfile=NULL,*CApath=NULL; // SSL_CTX_load_verify_locations(ctx,CAfile,CApath); // 当需要客户端验证的时候,服务器把CAfile里面的可信任CA证书发往客户端。 // if(CAfile !=NULL )SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfile)); // 设置最大的验证用户证书的上级数。 // SSL_CTX_set_verify_depth(ctx,10); //设置加载服务器的证书和私钥 if (SSL_CTX_use_certificate_chain_file(ssl.ctx, (char *) certificate) == 0) { printf("SSL_CTX_use_certificate_chain_file("%s") failed", certificate); } if (SSL_CTX_use_PrivateKey_file(ssl.ctx, (char *) certificate_key, SSL_FILETYPE_PEM)== 0) { //类型测试好像无所谓,应该是SSL_FILETYPE_ASN1? printf("SSL_CTX_use_PrivateKey_file("%s") failed", certificate_key); } SSL_CTX_set_cipher_list(ssl.ctx, "HIGH:!aNULL:!MD5"); //设置密码链表,具体看密码 ciphers(1)指令吧 SSL_CTX_set_tmp_rsa_callback(ssl.ctx, ngx_ssl_rsa512_key_callback); //设置键改变时调用,握手时的处理 //如果是双向认证还得做下面这几件事情 // SSL_CTX_set_verify(ssl->ctx, SSL_VERIFY_PEER, ngx_http_ssl_verify_callback); // SSL_CTX_set_verify_depth(ssl->ctx, depth); // SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL); // SSL_load_client_CA_file((char *) cert->data); // ERR_clear_error(); // SSL_CTX_set_client_CA_list(ssl->ctx, list); // SSL_CTX_get_cert_store(ssl->ctx); // X509_STORE_add_lookup(store, X509_LOOKUP_file(); // X509_LOOKUP_load_file(lookup, (char *) crl->data, X509_FILETYPE_PEM); // X509_STORE_set_flags(store,X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); //ngx_ssl_dhparam(ssl, ""); // 当使用RSA算法鉴别的时候,会有一个临时的DH密钥磋商发生。这样会话数据将用这个临时的密钥加密,而证书中的密钥中做为签名。 // 所以这样增强了安全性,临时密钥是在会话结束消失的,所以就是获取了全部信息也无法把通信内容给解密出来。 // 实现 openssl 提供的默认的 DH_METHOD,实现了根据密钥参数生成 DH 公私钥,以及根据 DH 公钥(一方)以及 DH 私钥(另一方)来生成一个共享密钥,用于密钥交换。 //DH密钥磋商设置 DH *dh; static unsigned char dh1024_p[] = { 0xBB, 0xBC, 0x2D, 0xCA, 0xD8, 0x46, 0x74, 0x90, 0x7C, 0x43, 0xFC, 0xF5, 0x80, 0xE9, 0xCF, 0xDB, 0xD9, 0x58, 0xA3, 0xF5, 0x68, 0xB4, 0x2D, 0x4B, 0x08, 0xEE, 0xD4, 0xEB, 0x0F, 0xB3, 0x50, 0x4C, 0x6C, 0x03, 0x02, 0x76, 0xE7, 0x10, 0x80, 0x0C, 0x5C, 0xCB, 0xBA, 0xA8, 0x92, 0x26, 0x14, 0xC5, 0xBE, 0xEC, 0xA5, 0x65, 0xA5, 0xFD, 0xF1, 0xD2, 0x87, 0xA2, 0xBC, 0x04, 0x9B, 0xE6, 0x77, 0x80, 0x60, 0xE9, 0x1A, 0x92, 0xA7, 0x57, 0xE3, 0x04, 0x8F, 0x68, 0xB0, 0x76, 0xF7, 0xD3, 0x6C, 0xC8, 0xF2, 0x9B, 0xA5, 0xDF, 0x81, 0xDC, 0x2C, 0xA7, 0x25, 0xEC, 0xE6, 0x62, 0x70, 0xCC, 0x9A, 0x50, 0x35, 0xD8, 0xCE, 0xCE, 0xEF, 0x9E, 0xA0, 0x27, 0x4A, 0x63, 0xAB, 0x1E, 0x58, 0xFA, 0xFD, 0x49, 0x88, 0xD0, 0xF6, 0x5D, 0x14, 0x67, 0x57, 0xDA, 0x07, 0x1D, 0xF0, 0x45, 0xCF, 0xE1, 0x6B, 0x9B }; static unsigned char dh1024_g[] = { 0x02 }; dh = DH_new(); if (dh == NULL) { } dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL); dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL); if (dh->p == NULL || dh->g == NULL) { DH_free(dh); } SSL_CTX_set_tmp_dh(ssl.ctx, dh); DH_free(dh); // ngx_ssl_session_cache(ssl, "HTTP", 0, 0); //下面只是会话的设置 SSL_CTX_set_session_id_context(ssl.ctx, (const unsigned char *) "HTTP",strlen("HTTP")); SSL_CTX_set_session_cache_mode(ssl.ctx, SSL_SESS_CACHE_SERVER |SSL_SESS_CACHE_NO_AUTO_CLEAR |SSL_SESS_CACHE_NO_INTERNAL_STORE); // 设置cache的大小,默认的为1024*20=20000,这个也就是可以存多少个session_id,一般都不需要更改的。假如为0的话将是无限 SSL_CTX_sess_set_cache_size(ssl.ctx, 1); //下面是网络模块 socklen_t sin_len = sizeof(struct sockaddr_in); int fd, opt = 1; struct epoll_event ev; struct sockaddr_in sin, cin; epfd = epoll_create(1024); if ((fd = socket(AF_INET, SOCK_STREAM, 0)) <= 0) { fprintf(stderr, "socket failed/n"); return -1; } setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*) &opt, sizeof(opt)); memset(&sin, 0, sizeof(struct sockaddr_in)); sin.sin_family = AF_INET; sin.sin_port = htons((short) (443)); sin.sin_addr.s_addr = INADDR_ANY; if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) != 0) { fprintf(stderr, "bind failed/n"); return -1; } if (listen(fd, 32) != 0) { fprintf(stderr, "listen failed/n"); return -1; } int i, cfd, n, nfds; struct epoll_event events[1024]; char buffer[512]; ev.data.fd = fd; ev.events = EPOLLIN | EPOLLET; //设置要处理的事件类型 epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev); while (1) { nfds = epoll_wait(epfd, events, 1024, -1); printf("nfds ........... %d/n", nfds); for (i = 0; i < nfds; i++) { if (events[i].data.fd == fd) { cfd = accept(fd, (struct sockaddr *) &cin, &sin_len); ngx_nonblocking(cfd); //把客户端的socket设置为非阻塞方式 ev.data.fd = cfd; ev.events = EPOLLIN | EPOLLET; epoll_ctl(epfd, EPOLL_CTL_ADD, cfd, &ev); } else { if (events[i].events & EPOLLIN) { cfd = events[i].data.fd; //这里模拟nginx接收 // ngx_ssl_create_connection(ssl, cfd); ngx_ssl_conn_t *connection = SSL_new(ssl.ctx); //根据上下文,建立ssl套接口或链接 if (connection == NULL) { } if (SSL_set_fd(connection, cfd) == 0) { //设置处理的id进入上下文里面 } SSL_set_accept_state(connection); //设置接收状态 // if (SSL_set_ex_data(connection, ngx_ssl_connection_index, c) == 0) { // } //进行握手处理 ngx_http_ssl_handshake(cfd,connection); //正确处理 for (;;) { n = SSL_read(connection, buffer, 512); //会读取好几次把之前读取的第一个字节也读取回来 if (n > 0) { } else { break; } continue; } //这里是,对请求的相关处理,省略掉了 //ngx_http_process_request_headers(rev); //给客户端发送数据 const char *data = "HTTP/1.1 200 OKrnServer: nginx/1.0.12rnDate: Sun, 03 Mar 2013 12:38:48 GMTrnContent- ..."; n = SSL_write(connection, data, sizeof(data)); //关闭请求链接;如果验证通过是不会走这里的(而等到超时的时候才处理);对于验证不通过或http请求则直接调用关闭链接。 ngx_ssl_shutdown(connection); SSL_CTX_free(ssl.ctx);//释放SSL环境 close(fd); // ret = recv(cfd, buffer, sizeof(buffer), 0); // printf("read ret..........= %d/n", ret); // // ev.data.fd = cfd; // ev.events = EPOLLOUT | EPOLLET; // epoll_ctl(epfd, EPOLL_CTL_MOD, cfd, &ev); } else if (events[i].events & EPOLLOUT) { cfd = events[i].data.fd; ev.data.fd = cfd; epoll_ctl(epfd, EPOLL_CTL_DEL, cfd, &ev); close(cfd); } } } } if (fd > 0) close(fd); return 0; }
相关文章推荐
- 2017最新在swift3.0下集成iOS内购全流程(附代码)
- nginx openssl 的集成代码流程
- 集成腾讯随心播1.8.4代码流程分析
- SourceInsight与PC-LINT集成进行代码静态分析
- Peercast核心代码执行流程
- Beginning C# Objects从概念到代码——1.11 循环和其他控制结构流程(一)
- Eboot代码流程
- (3)jBPM websale代码学习: home.jsp(启动流程)
- Eboot代码流程
- jBPM websale代码学习: home.jsp(启动流程)
- 系统集成项目操作流程
- mapxtreme3.0模板代码的执行流程
- 以流程设计为向导的现实代码(引以为戒!)
- 基于流程的企业业务集成方案
- DotNetNuke的Skin.vb代码流程分析
- Beginning C# Objects从概念到代码——1.11 循环和其他控制结构流程(二)
- 关于在xslt中集成HTML代码的问题
- 在VS集成代码检测工具
- Visual Studio Orcas Web设计器集成进VS主体代码
- dm9000驱动代码流程分析