2.13 SSL_connect
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;
// 清除SSL读写加密算法上下文
ssl_clear_cipher_ctx(s);
}
因此最重要的就是ssl_connect()这两个成员函数,是前面SSLv[2][3]_client_method()函数中定义的,如对于SSLv23方法,处理函数分别为ssl23_connect()函数,其它SSLv2和SSLv3方法分别对应ssl2_connect()和ssl3_connect(),后两者就没有协商过程了,ssl23_connect()实际在协商确定协议版本后也是调用ssl2[3]_connect()。掌握了服务器端的accept过程,理解客户端的connect过程就简单了。
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_BEFORE
switch(s->state)
{
case SSL_ST_BEFORE:
case SSL_ST_CONNECT:
caseSSL_ST_BEFORE|SSL_ST_CONNECT:
caseSSL_ST_OK|SSL_ST_CONNECT:
// 进行基本初始化,分配缓冲区
if(s->session != NULL)
{
SSLerr(SSL_F_SSL23_CONNECT,SSL_R_SSL23_DOING_SESSION_ID_REUSE);
ret=-1;
gotoend;
}
s->server=0;
if (cb !=NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
s->type=SSL_ST_CONNECT;
if(s->init_buf == NULL)
{
if((buf=BUF_MEM_new()) == NULL)
{
ret=-1;
gotoend;
}
if(!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH))
{
ret=-1;
gotoend;
}
s->init_buf=buf;
buf=NULL;
}
if(!ssl3_setup_buffers(s)) { ret= -1; goto end; }
ssl3_init_finished_mac(s);
caseSSL23_ST_CW_CLNT_HELLO_A:
caseSSL23_ST_CW_CLNT_HELLO_B:
// 发送客户端的HELLO信息
s->shutdown=0;
ret=ssl23_client_hello(s);
if (ret <=0) goto end;
// 转为准备接收服务器端的HELLO状态
s->state=SSL23_ST_CR_SRVR_HELLO_A;
s->init_num=0;
break;
caseSSL23_ST_CR_SRVR_HELLO_A:
caseSSL23_ST_CR_SRVR_HELLO_B:
// 读取服务器端的HELLO信息,完成SSL握手协商
ret=ssl23_get_server_hello(s);
if (ret >=0) cb=NULL;
gotoend;
default:
SSLerr(SSL_F_SSL23_CONNECT,SSL_R_UNKNOWN_STATE);
ret=-1;
gotoend;
}
if (s->debug) {(void)BIO_flush(s->wbio); }
if ((cb != NULL) &&(s->state != state))
{
new_state=s->state;
s->state=state;
SSL_connect()这个函数完成SSL协商的客户端操作:
int SSL_connect(SSL *s)
{
if (s->handshake_func == 0)
SSL_set_connect_state(s);
其中SSL_set_connect_state(s)函数初始化SSL协商处理:
void SSL_set_connect_state(SSL *s)
// 客户端
// 初始化客户端状态值
// 握手函数即是ssl_connect函数
// 清除SSL读写加密算法上下文
因此最重要的就是ssl_connect()这两个成员函数,是前面SSLv[2][3]_client_method()函数中定义的,如对于SSLv23方法,处理函数分别为ssl23_connect()函数,其它SSLv2和SSLv3方法分别对应ssl2_connect()和ssl3_connect(),后两者就没有协商过程了,ssl23_connect()实际在协商确定协议版本后也是调用ssl2[3]_connect()。掌握了服务器端的accept过程,理解客户端的connect过程就简单了。
int ssl23_connect(SSL *s)
{
BUF_MEM *buf=NULL;
unsigned long Time=time(NULL);
void (*cb)(const SSL *ssl,int type,intval)=NULL;
int ret= -1;
int new_state,state;
// 和服务器端一样进行基本的初始化
RAND_add(&Time,sizeof(Time),0);
ERR_clear_error();
clear_sys_error();
//在SSL_set_connect_state中s->state被初始化为SSL_ST_CONNECT|SSL_ST_BEFORE
// 进行基本初始化,分配缓冲区
// SSL客户端状态转为准备发送HELLO信息
s->state=SSL23_ST_CW_CLNT_HELLO_A;
s->ctx->stats.sess_connect++;
s->init_num=0;
break;
// 发送客户端的HELLO信息
// 转为准备接收服务器端的HELLO状态
// 读取服务器端的HELLO信息,完成SSL握手协商