




已阅读5页,还剩19页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
转 SSL连接建立过程分析 42.13 SSL_connect SSL_connect()这个函数完成SSL协商的客户端操作:/* ssl/ssl_lib.c */int SSL_connect(SSL *s)if (s-handshake_func = 0)/* Not properly initialized yet */SSL_set_connect_state(s);return(s-method-ssl_connect(s);其中SSL_set_connect_state(s)函数初始化SSL协商处理:void SSL_set_connect_state(SSL *s)/ 客户端s-server=0;s-shutdown=0;/ 初始化客户端状态值s-state=SSL_ST_CONNECT|SSL_ST_BEFORE;/ 握手函数即是ssl_connect函数s-handshake_func=s-method-ssl_connect;/* clear the current cipher */ 清除SSL读写加密算法上下文ssl_clear_cipher_ctx(s);因此最重要的就是ssl_connect()这两个成员函数,是前面SSLv23_client_method()函数中定义的,如对于SSLv23方法,处理函数分别为ssl23_connect()函数,其它SSLv2和SSLv3方法分别对应ssl2_connect()和ssl3_connect(),后两者就没有协商过程了,ssl23_connect()实际在协商确定协议版本后也是调用ssl23_connect()。掌握了服务器端的accept过程,理解客户端的connect过程就简单了。/* ssl/s23_clnt.c */int ssl23_connect(SSL *s)BUF_MEM *buf=NULL;unsigned long Time=time(NULL);void (*cb)(const SSL *ssl,int type,int val)=NULL;int ret= -1;int new_state,state;/ 和服务器端一样进行基本的初始化RAND_add(&Time,sizeof(Time),0);ERR_clear_error();clear_sys_error();if (s-info_callback != NULL)cb=s-info_callback;else if (s-ctx-info_callback != NULL)cb=s-ctx-info_callback;s-in_handshake+;if (!SSL_in_init(s) | SSL_in_before(s) SSL_clear(s); for (;)state=s-state;/ 在SSL_set_connect_state中s-state被初始化为SSL_ST_CONNECT|SSL_ST_BEFOREswitch(s-state)case SSL_ST_BEFORE:case SSL_ST_CONNECT:case SSL_ST_BEFORE|SSL_ST_CONNECT:case SSL_ST_OK|SSL_ST_CONNECT:/ 进行基本初始化,分配缓冲区if (s-session != NULL)SSLerr(SSL_F_SSL23_CONNECT,SSL_R_SSL23_DOING_SESSION_ID_REUSE);ret= -1;goto end;s-server=0;if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);/* s-version=TLS1_VERSION; */s-type=SSL_ST_CONNECT;if (s-init_buf = NULL)if (buf=BUF_MEM_new() = NULL)ret= -1;goto end;if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH)ret= -1;goto end;s-init_buf=buf;buf=NULL;if (!ssl3_setup_buffers(s) ret= -1; goto end; ssl3_init_finished_mac(s);/ SSL客户端状态转为准备发送HELLO信息s-state=SSL23_ST_CW_CLNT_HELLO_A;s-ctx-stats.sess_connect+;s-init_num=0;break;case SSL23_ST_CW_CLNT_HELLO_A:case SSL23_ST_CW_CLNT_HELLO_B:/ 发送客户端的HELLO信息s-shutdown=0;ret=ssl23_client_hello(s);if (ret state=SSL23_ST_CR_SRVR_HELLO_A;s-init_num=0;break;case SSL23_ST_CR_SRVR_HELLO_A:case SSL23_ST_CR_SRVR_HELLO_B:/ 读取服务器端的HELLO信息,完成SSL握手协商ret=ssl23_get_server_hello(s);if (ret = 0) cb=NULL;goto end;/* break; */default:SSLerr(SSL_F_SSL23_CONNECT,SSL_R_UNKNOWN_STATE);ret= -1;goto end;/* break; */if (s-debug) (void)BIO_flush(s-wbio); if (cb != NULL) & (s-state != state)new_state=s-state;s-state=state;cb(s,SSL_CB_CONNECT_LOOP,1);s-state=new_state;end:s-in_handshake-;if (buf != NULL)BUF_MEM_free(buf);if (cb != NULL)cb(s,SSL_CB_CONNECT_EXIT,ret);return(ret);ssl23_client_hello()函数发送客户端的HELLO信息:/* ssl/s23_clnt.c */static int ssl23_client_hello(SSL *s)unsigned char *buf;unsigned char *p,*d;int i,ch_len;int ret;buf=(unsigned char *)s-init_buf-data;if (s-state = SSL23_ST_CW_CLNT_HELLO_A)/ 准备发送HELLO, 构造发送缓冲区的数据,数据格式见SSL_accept一节中的说明p=s-s3-client_random;RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE);/* Do the message type and length last */d= &(buf2);/ p指向SSL握手记录头(11字节长)后的第一字节处p=d+9;/ 消息类型*(d+)=SSL2_MT_CLIENT_HELLO;/ 填写客户端版本号if (!(s-options & SSL_OP_NO_TLSv1)*(d+)=TLS1_VERSION_MAJOR;*(d+)=TLS1_VERSION_MINOR;s-client_version=TLS1_VERSION;else if (!(s-options & SSL_OP_NO_SSLv3)*(d+)=SSL3_VERSION_MAJOR;*(d+)=SSL3_VERSION_MINOR;s-client_version=SSL3_VERSION;else if (!(s-options & SSL_OP_NO_SSLv2)*(d+)=SSL2_VERSION_MAJOR;*(d+)=SSL2_VERSION_MINOR;s-client_version=SSL2_VERSION;elseSSLerr(SSL_F_SSL23_CLIENT_HELLO,SSL_R_NO_PROTOCOLS_AVAILABLE);return(-1);/ 填写cipher_specs信息/* Ciphers supported */i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),p);if (i = 0)/* no ciphers */SSLerr(SSL_F_SSL23_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE);return(-1);s2n(i,d);p+=i;/ 填写会话ID/* put in the session-id, zero since there is no * reuse. */s2n(0,d);if (s-options & SSL_OP_NETSCAPE_CHALLENGE_BUG)ch_len=SSL2_CHALLENGE_LENGTH;elsech_len=SSL2_MAX_CHALLENGE_LENGTH;/ 填写挑战信息/* write out sslv2 challenge */if (SSL3_RANDOM_SIZE s3-client_random0),0,SSL3_RANDOM_SIZE);RAND_pseudo_bytes(&(s-s3-client_randomSSL3_RANDOM_SIZE-i),i);memcpy(p,&(s-s3-client_randomSSL3_RANDOM_SIZE-i),i);p+=i;/ 数据长度i= p- &(buf2);buf0=(i8)&0xff)|0x80;buf1=(i&0xff);/ 数据完成,状态转为HELLO B准备发送s-state=SSL23_ST_CW_CLNT_HELLO_B;/* number of bytes to write */s-init_num=i+2;s-init_off=0;ssl3_finish_mac(s,&(buf2),i);/* SSL3_ST_CW_CLNT_HELLO_B */ 发送HELLO数据ret = ssl23_write_bytes(s);if (ret = 2)if (s-msg_callback)s-msg_callback(1, SSL2_VERSION, 0, s-init_buf-data+2, ret-2, s, s-msg_callback_arg); /* CLIENT-HELLO */return ret;ssl23_get_server_hello()接收服务器端的回应,识别服务器的SSL版本,最后再相应调用ssl2_connect()或ssl3_connect()函数。/* ssl/s23_clnt.c */static int ssl23_get_server_hello(SSL *s)char buf8;unsigned char *p;int i;int n;/ 读7字节的服务器端数据n=ssl23_read_bytes(s,7);if (n != 7) return(n);p=s-packet;memcpy(buf,p,n);if (p0 & 0x80) & (p2 = SSL2_MT_SERVER_HELLO) &(p5 = 0x00) & (p6 = 0x02)/ 服务器是SSL2版本#ifdef OPENSSL_NO_SSL2SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_PROTOCOL);goto err;#else/* we are talking sslv2 */* we need to clean up the SSLv3 setup and put in the * sslv2 stuff. */int ch_len;if (s-options & SSL_OP_NO_SSLv2)SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_PROTOCOL);goto err;/ 初始化SSL结构中的SSL2支持,ssl_connect将为ssl2_connectif (s-s2 = NULL)if (!ssl2_new(s)goto err;elsessl2_clear(s);if (s-options & SSL_OP_NETSCAPE_CHALLENGE_BUG)ch_len=SSL2_CHALLENGE_LENGTH;elsech_len=SSL2_MAX_CHALLENGE_LENGTH;/* write out sslv2 challenge */i=(SSL3_RANDOM_SIZE s2-challenge_length=i;memcpy(s-s2-challenge,&(s-s3-client_randomSSL3_RANDOM_SIZE-i),i);if (s-s3 != NULL) ssl3_free(s);if (!BUF_MEM_grow_clean(s-init_buf,SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,ERR_R_BUF_LIB);goto err;s-state=SSL2_ST_GET_SERVER_HELLO_A;if (!(s-client_version = SSL2_VERSION)/* use special padding (SSL 3.0 draft/RFC 2246, App. E.2) */s-s2-ssl2_rollback=1;/* setup the 5 bytes we have read so we get them from * the sslv2 buffer */s-rstate=SSL_ST_READ_HEADER;s-packet_length=n;s-packet= &(s-s2-rbuf0);memcpy(s-packet,buf,n);s-s2-rbuf_left=n;s-s2-rbuf_offs=0;/* we have already written one */s-s2-write_sequence=1;s-method=SSLv2_client_method();s-handshake_func=s-method-ssl_connect;#endifelse if (p0 = SSL3_RT_HANDSHAKE) & (p1 = SSL3_VERSION_MAJOR) & (p2 = SSL3_VERSION_MINOR) | (p2 = TLS1_VERSION_MINOR) & (p5 = SSL3_MT_SERVER_HELLO)/ 服务器版本为SSL3或TLS1,ssl_connect将为ssl3_connect/* we have sslv3 or tls1 */if (!ssl_init_wbio_buffer(s,1) goto err;/* we are in this state */s-state=SSL3_ST_CR_SRVR_HELLO_A;/* put the 5 bytes we have read into the input buffer * for SSLv3 */s-rstate=SSL_ST_READ_HEADER;s-packet_length=n;s-packet= &(s-s3-rbuf.buf0);memcpy(s-packet,buf,n);s-s3-rbuf.left=n;s-s3-rbuf.offset=0;if (p2 = SSL3_VERSION_MINOR) &!(s-options & SSL_OP_NO_SSLv3)s-version=SSL3_VERSION;s-method=SSLv3_client_method();else if (p2 = TLS1_VERSION_MINOR) &!(s-options & SSL_OP_NO_TLSv1)s-version=TLS1_VERSION;s-method=TLSv1_client_method();elseSSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_PROTOCOL);goto err;s-handshake_func=s-method-ssl_connect;else if (p0 = SSL3_RT_ALERT) & (p1 = SSL3_VERSION_MAJOR) & (p2 = SSL3_VERSION_MINOR) | (p2 = TLS1_VERSION_MINOR) & (p3 = 0) & (p4 = 2)/ SSL告警信息void (*cb)(const SSL *ssl,int type,int val)=NULL;int j;/* An alert */if (s-info_callback != NULL)cb=s-info_callback;else if (s-ctx-info_callback != NULL)cb=s-ctx-info_callback;i=p5;if (cb != NULL)j=(irwstate=SSL_NOTHING;SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_AD_REASON_OFFSET+p6);goto err;elseSSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNKNOWN_PROTOCOL);goto err;s-init_num=0;/* Since, if we are sending a ssl23 client hello, we are not * reusing a session-id */if (!ssl_get_new_session(s,0)goto err;s-first_packet=1;/ 递归调用SSL_connect,实际将执行ssl2_connect()或ssl3_connect()return(SSL_connect(s);err:return(-1);举例ssl3_conect()函数定义如下,ssl2_connect()就不分析了:/* ssl/s3_clnt.c */int ssl3_connect(SSL *s)BUF_MEM *buf=NULL;unsigned long Time=time(NULL),l;long num1;void (*cb)(const SSL *ssl,int type,int val)=NULL;int ret= -1;int new_state,state,skip=0;/ 对SSL3连接的初始化RAND_add(&Time,sizeof(Time),0);ERR_clear_error();clear_sys_error();if (s-info_callback != NULL)cb=s-info_callback;else if (s-ctx-info_callback != NULL)cb=s-ctx-info_callback;s-in_handshake+;if (!SSL_in_init(s) | SSL_in_before(s) SSL_clear(s); for (;)state=s-state;switch(s-state)case SSL_ST_RENEGOTIATE:/ 重协商的话从头开始, 注意break是注释掉的s-new_session=1;s-state=SSL_ST_CONNECT;s-ctx-stats.sess_connect_renegotiate+;/* break */ 初始状态应该是SSL_ST_BEFORE|SSL_ST_CONNECTcase SSL_ST_BEFORE:case SSL_ST_CONNECT:case SSL_ST_BEFORE|SSL_ST_CONNECT:case SSL_ST_OK|SSL_ST_CONNECT:/ server=0表示是客户端s-server=0;if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);/ 如果本地版本不是SSL3则出错if (s-version & 0xff00 ) != 0x0300)SSLerr(SSL_F_SSL3_CONNECT, ERR_R_INTERNAL_ERROR);ret = -1;goto end;/* s-version=SSL3_VERSION; */s-type=SSL_ST_CONNECT;/ 初始化连接缓冲区if (s-init_buf = NULL)if (buf=BUF_MEM_new() = NULL)ret= -1;goto end;if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH)ret= -1;goto end;s-init_buf=buf;buf=NULL;if (!ssl3_setup_buffers(s) ret= -1; goto end; /* setup buffing BIO */if (!ssl_init_wbio_buffer(s,0) ret= -1; goto end; /* dont push the buffering BIO quite yet */ssl3_init_finished_mac(s);/ 准备发送HELLO信息s-state=SSL3_ST_CW_CLNT_HELLO_A;s-ctx-stats.sess_connect+;s-init_num=0;break;case SSL3_ST_CW_CLNT_HELLO_A:case SSL3_ST_CW_CLNT_HELLO_B:/ 该状态发送客户端SSL3信息s-shutdown=0;ret=ssl3_client_hello(s);if (ret state=SSL3_ST_CR_SRVR_HELLO_A;s-init_num=0;/* turn on buffering for the next lot of output */if (s-bbio != s-wbio)s-wbio=BIO_push(s-bbio,s-wbio);break;case SSL3_ST_CR_SRVR_HELLO_A:case SSL3_ST_CR_SRVR_HELLO_B:/ 该状态下接收服务器发送的HELLO信息ret=ssl3_get_server_hello(s);if (ret hit)/ 如果是reuse的连接,状态转为接收结束s-state=SSL3_ST_CR_FINISHED_A;else/ 否则状态转为准备接收服务器的证书s-state=SSL3_ST_CR_CERT_A;s-init_num=0;break;case SSL3_ST_CR_CERT_A:case SSL3_ST_CR_CERT_B:/ 该状态下接收服务器发送的证书/* Check if it is anon DH */if (!(s-s3-tmp.new_cipher-algorithms & SSL_aNULL)ret=ssl3_get_server_certificate(s);if (ret state=SSL3_ST_CR_KEY_EXCH_A;s-init_num=0;break;case SSL3_ST_CR_KEY_EXCH_A:case SSL3_ST_CR_KEY_EXCH_B:/ 该状态下接收密钥交换信息ret=ssl3_get_key_exchange(s);if (ret state=SSL3_ST_CR_CERT_REQ_A;s-init_num=0;/* at this point we check that we have the * required stuff from the server */if (!ssl3_check_cert_and_algorithm(s)ret= -1;goto end;break;case SSL3_ST_CR_CERT_REQ_A:case SSL3_ST_CR_CERT_REQ_B:/ 该状态下接收服务器的证书请求ret=ssl3_get_certificate_request(s);if (ret state=SSL3_ST_CR_SRVR_DONE_A;s-init_num=0;break;case SSL3_ST_CR_SRVR_DONE_A:case SSL3_ST_CR_SRVR_DONE_B:/ 该状态下接收服务器信息结束ret=ssl3_get_server_done(s);if (ret s3-tmp.cert_req)/ 发送客户端证书s-state=SSL3_ST_CW_CERT_A;else/ 发送密钥交换信息s-state=SSL3_ST_CW_KEY_EXCH_A;s-init_num=0;break;case SSL3_ST_CW_CERT_A:case SSL3_ST_CW_CERT_B:case SSL3_ST_CW_CERT_C:case SSL3_ST_CW_CERT_D:/ 该状态下发送客户端证书ret=ssl3_send_client_certificate(s);if (ret state=SSL3_ST_CW_KEY_EXCH_A;s-init_num=0;break;case SSL3_ST_CW_KEY_EXCH_A:case SSL3_ST_CW_KEY_EXCH_B:/ 该状态下发送密钥交换信息ret=ssl3_send_client_key_exchange(s);if (ret s3-tmp.new_cipher-algorithms;/* EAY EAY EAY need to check for DH fix cert * sent back */* For TLS, cert_req is set to 2, so a cert chain * of nothing is sent, but no verify packet is sent */if (s-s3-tmp.cert_req = 1)/ 发送证书验证s-state=SSL3_ST_CW_CERT_VRFY_A;else/ TLS, 不用发送证书认证信息,直接转为修改算法状态s-state=SSL3_ST_CW_CHANGE_A;s-s3-change_cipher_spec=0;s-init_num=0;break;case SSL3_ST_CW_CERT_VRFY_A:case SSL3_ST_CW_CERT_VRFY_B:/ 该状态发送证书验证信息ret=ssl3_send_client_verify(s);if (ret state=SSL3_ST_CW_CHANGE_A;s-init_num=0;s-s3-change_cipher_spec=0;break;case SSL3_ST_CW_CHANGE_A:case SSL3_ST_CW_CHANGE_B:/ 该状态下发送修改算法信息ret=ssl3_send_change_cipher_spec(s,SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B);if (ret state=SSL3_ST_CW_FINISHED_A;s-init_num=0;/ 设置会话加密算法s-session-cipher=s-s3-tmp.new_cipher;if (s-s3-tmp.new_compression = NULL)s-session-compress_meth=0;elses-session-compress_meth=s-s3-tmp.new_compression-id;if (!s-method-ssl3_enc-setup_key_block(s)ret= -1;goto end;if (!s-method-ssl3_enc-change_cipher_state(s,SSL3_CHANGE_CIPHER_CLIENT_WRITE)ret= -1;goto end;break;case SSL3_ST_CW_FINISHED_A:case SSL3_ST_CW_FINISHED_B:/ 该状态下发送协商结束信息ret=ssl3_send_finished(s,SSL3_ST_CW_FINISHED_A,SSL3_ST_CW_FINISHED_B,s-method-ssl3_enc-client_finished_label,s-method-ssl3_enc-client_finished_label_len);if (ret state=SSL3_ST_CW_FLUSH;/* clear flags */s-s3-flags&= SSL3_FLAGS_POP_BUFFER;if (s-hit)/ 如果是reuse的会话, FLUSH后的下一个状态转为协商成功s-s3-tmp.next_state=SSL_ST_OK;if (s-s3-flags & SSL3_FLAGS_DELAY_CLIENT_FINISHED)s-state=SSL_ST_OK;s-s3-flags|=SSL3_FLAGS_POP_BUFFER;s-s3-delay_buf_pop_ret=0;else/ 否则状态转为准备接收服务器的协商结束信息s-s3-tmp.next_state=SSL3_ST_CR_FINISHED_A;s-init_num=0;break;case SSL3_ST_CR_FINISHED_A:case SSL3_ST_CR_FINISHED_B:/ 该状态接收服务器发送的协商结束信息ret=ssl3_get_finished(s,SSL3_ST_CR_FINIS
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025园林绿化设计合同范本
- 2025劳动合同协议书范本模板
- 2025企业合同终止的情形分析:合规解除劳动合同的途径与条件
- 江苏省镇江市2024-2025学年高一上学期期中检测生物试卷 含解析
- 腰椎疼痛康复护理
- 脊柱外科术后护理
- 静脉留置消毒护理
- 心脏支架术后护理规范
- 【方案】2024咪咕全域营销媒体手册6928mb
- 三晋卓越联盟·2024-2025学年高三5月质量检测卷(25-X-635C)生物(B)
- DL∕T 1901-2018 水电站大坝运行安全应急预案编制导则
- 实验室可靠性测试计划表
- 大型活动交通保障方案
- 2024年济南先投人才发展集团招聘笔试冲刺题(带答案解析)
- 居间费用协议合同范本
- 云南省昆明市2023-2024学年高二下学期期末质量检测化学试题
- CJ343-2010 污水排入城市下水道水质标准
- 铁路盖板涵、框架涵施工方案培训资料
- 中医健康管理技术规范
- 医院深入开展2024年度“三合理一规范”活动实施方案
- 公园设施维修投标方案
评论
0/150
提交评论