IT点滴

我不去想是否能够成功 既然选择了远方 便只顾风雨兼程
  博客园  :: 首页  :: 联系 :: 订阅 订阅  :: 管理

SSL连接建立过程分析(4)

Posted on 2009-08-07 12:28  Ady Lee  阅读(1208)  评论(0编辑  收藏  举报
SSL连接建立过程分析(4)
 
本文档的Copyleft归yfydz所有,使用GPL发布,可以自由拷贝,转载,转载时请保持文档的完整性,严禁用于任何商业用途。
msn: yfydz_no1@hotmail.com
来源:http://yfydz.cublog.cn/

2.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()这两个成员函数,是前面SSLv[2][3]_client_method()函数中定义的,如对于SSLv23方法,处理函数分别为ssl23_connect()函数,其它SSLv2和SSLv3方法分别对应ssl2_connect()和ssl3_connect(),后两者就没有协商过程了,ssl23_connect()实际在协商确定协议版本后也是调用ssl2[3]_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_BEFORE
  switch(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 <= 0) goto end;
// 转为准备接收服务器端的HELLO状态
   s->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= &(buf[2]);
// 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;
   }
  else
   {
   SSLerr(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;
  else
   ch_len=SSL2_MAX_CHALLENGE_LENGTH;
// 填写挑战信息
  /* write out sslv2 challenge */
  if (SSL3_RANDOM_SIZE < ch_len)
   i=SSL3_RANDOM_SIZE;
  else
   i=ch_len;
  s2n(i,d);
  memset(&(s->s3->client_random[0]),0,SSL3_RANDOM_SIZE);
  RAND_pseudo_bytes(&(s->s3->client_random[SSL3_RANDOM_SIZE-i]),i);
  memcpy(p,&(s->s3->client_random[SSL3_RANDOM_SIZE-i]),i);
  p+=i;
// 数据长度
  i= p- &(buf[2]);
  buf[0]=((i>>8)&0xff)|0x80;
  buf[1]=(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,&(buf[2]),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 buf[8];
 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 ((p[0] & 0x80) && (p[2] == SSL2_MT_SERVER_HELLO) &&
  (p[5] == 0x00) && (p[6] == 0x02))
  {
// 服务器是SSL2版本
#ifdef OPENSSL_NO_SSL2
  SSLerr(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_connect
  if (s->s2 == NULL)
   {
   if (!ssl2_new(s))
    goto err;
   }
  else
   ssl2_clear(s);
  if (s->options & SSL_OP_NETSCAPE_CHALLENGE_BUG)
   ch_len=SSL2_CHALLENGE_LENGTH;
  else
   ch_len=SSL2_MAX_CHALLENGE_LENGTH;
  /* write out sslv2 challenge */
  i=(SSL3_RANDOM_SIZE < ch_len)
   ?SSL3_RANDOM_SIZE:ch_len;
  s->s2->challenge_length=i;
  memcpy(s->s2->challenge,
   &(s->s3->client_random[SSL3_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->rbuf[0]);
  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;
#endif
  }
 else if ((p[0] == SSL3_RT_HANDSHAKE) &&
   (p[1] == SSL3_VERSION_MAJOR) &&
   ((p[2] == SSL3_VERSION_MINOR) ||
    (p[2] == TLS1_VERSION_MINOR)) &&
   (p[5] == 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.buf[0]);
  memcpy(s->packet,buf,n);
  s->s3->rbuf.left=n;
  s->s3->rbuf.offset=0;
  if ((p[2] == SSL3_VERSION_MINOR) &&
   !(s->options & SSL_OP_NO_SSLv3))
   {
   s->version=SSL3_VERSION;
   s->method=SSLv3_client_method();
   }
  else if ((p[2] == TLS1_VERSION_MINOR) &&
   !(s->options & SSL_OP_NO_TLSv1))
   {
   s->version=TLS1_VERSION;
   s->method=TLSv1_client_method();
   }
  else
   {
   SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_PROTOCOL);
   goto err;
   }
   
  s->handshake_func=s->method->ssl_connect;
  }
 else if ((p[0] == SSL3_RT_ALERT) &&
   (p[1] == SSL3_VERSION_MAJOR) &&
   ((p[2] == SSL3_VERSION_MINOR) ||
    (p[2] == TLS1_VERSION_MINOR)) &&
   (p[3] == 0) &&
   (p[4] == 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=p[5];
  if (cb != NULL)
   {
   j=(i<<8)|p[6];
   cb(s,SSL_CB_READ_ALERT,j);
   }
  s->rwstate=SSL_NOTHING;
  SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_AD_REASON_OFFSET+p[6]);
  goto err;
  }
 else
  {
  SSLerr(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_CONNECT
  case 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; }
   /* don't 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 <= 0) goto end;
// 发送成功,状态转为准备接收服务器的HELLO回应
   s->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 <= 0) goto end;
   if (s->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 <= 0) goto end;
    }
   else
    skip=1;
// 状态转为接收密钥交换信息
   s->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 <= 0) goto end;
// 状态转为接收证书请求
   s->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 <= 0) goto end;
   s->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 <= 0) goto end;
   if (s->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 <= 0) goto end;
// 状态转为发送密钥交换信息
   s->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 <= 0) goto end;
// 加密算法
   l=s->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 <= 0) goto end;
// 状态转为发送修改算法信息
   s->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 <= 0) goto end;
// 状态转为发送结束
   s->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;
   else
    s->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 <= 0) goto end;
// 转为刷新写缓冲状态
   s->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_FINISHED_A,
    SSL3_ST_CR_FINISHED_B);
   if (ret <= 0) goto end;
   if (s->hit)
// 如果会话是reuse的,状态转为发送算法
    s->state=SSL3_ST_CW_CHANGE_A;
   else
// 否则协商成功
    s->state=SSL_ST_OK;
   s->init_num=0;
   break;
  case SSL3_ST_CW_FLUSH:
// 该状态下刷新写缓冲区
   /* number of bytes to be flushed */
   num1=BIO_ctrl(s->wbio,BIO_CTRL_INFO,0,NULL);
   if (num1 > 0)
    {
    s->rwstate=SSL_WRITING;
    num1=BIO_flush(s->wbio);
    if (num1 <= 0) { ret= -1; goto end; }
    s->rwstate=SSL_NOTHING;
    }
   s->state=s->s3->tmp.next_state;
   break;
  case SSL_ST_OK:
// 该状态下协商成功结束
// 释放协商时分配的资源
   /* clean a few things up */
   ssl3_cleanup_key_block(s);
   if (s->init_buf != NULL)
    {
    BUF_MEM_free(s->init_buf);
    s->init_buf=NULL;
    }
   /* If we are not 'joining' the last two packets,
    * remove the buffering now */
   if (!(s->s3->flags & SSL3_FLAGS_POP_BUFFER))
    ssl_free_wbio_buffer(s);
   /* else do it later in ssl3_write */
   s->init_num=0;
   s->new_session=0;
   ssl_update_cache(s,SSL_SESS_CACHE_CLIENT);
   if (s->hit) s->ctx->stats.sess_hit++;
   ret=1;
   /* s->server=0; */
   s->handshake_func=ssl3_connect;
   s->ctx->stats.sess_connect_good++;
   if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);
   goto end;
   /* break; */
   
  default:
   SSLerr(SSL_F_SSL3_CONNECT,SSL_R_UNKNOWN_STATE);
   ret= -1;
   goto end;
   /* break; */
   }
  /* did we do anything */
  if (!s->s3->tmp.reuse_message && !skip)
   {
   if (s->debug)
    {
    if ((ret=BIO_flush(s->wbio)) <= 0)
     goto end;
    }
   if ((cb != NULL) && (s->state != state))
    {
    new_state=s->state;
    s->state=state;
    cb(s,SSL_CB_CONNECT_LOOP,1);
    s->state=new_state;
    }
   }
  skip=0;
  }
end:
 s->in_handshake--;
 if (buf != NULL)
  BUF_MEM_free(buf);
 if (cb != NULL)
  cb(s,SSL_CB_CONNECT_EXIT,ret);
 return(ret);
 }

...... 待续 ......