嵌入式 建立ssl连接过程分析四

原创 2013年12月02日 14:46:35
2.13 SSL_connect
 
SSL_connect()这个函数完成SSL协商的客户端操作:

int SSL_connect(SSL *s)
 {
 if (s->handshake_func == 0)
  
  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;
 
// 清除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过程就简单了。

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();
 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);
// SSL客户端状态转为准备发送HELLO信息
   s->state=SSL23_ST_CW_CLNT_HELLO_A;
   s->ctx->stats.sess_connect++;
   s->init_num=0;
   break;
  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;
   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信息:


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);
  
  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信息
  
  i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),p);
  if (i == 0)
   {
   
   SSLerr(SSL_F_SSL23_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE);
   return(-1);
   }
  s2n(i,d);
  p+=i;
// 填写会话ID
  
  s2n(0,d);
  if (s->options &SSL_OP_NETSCAPE_CHALLENGE_BUG)
   ch_len=SSL2_CHALLENGE_LENGTH;
  else
   ch_len=SSL2_MAX_CHALLENGE_LENGTH;
// 填写挑战信息
  
  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;
  
  s->init_num=i+2;
  s->init_off=0;
  ssl3_finish_mac(s,&(buf[2]),i);
  }
 
// 发送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);
 return ret;
 }

ssl23_get_server_hello()接收服务器端的回应,识别服务器的SSL版本,最后再相应调用ssl2_connect()或ssl3_connect()函数。


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
  
  
  int ch_len;
  if (s->options &SSL_OP_NO_SSLv2)
   {
   SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_PROTOCOL);
   gotoerr;
   }
// 初始化SSL结构中的SSL2支持,ssl_connect将为ssl2_connect
  if (s->s2 == NULL)
   {
   if(!ssl2_new(s))
    gotoerr;
   }
  else
   ssl2_clear(s);
  if (s->options &SSL_OP_NETSCAPE_CHALLENGE_BUG)
   ch_len=SSL2_CHALLENGE_LENGTH;
  else
   ch_len=SSL2_MAX_CHALLENGE_LENGTH;
  
  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);
   gotoerr;
   }
  s->state=SSL2_ST_GET_SERVER_HELLO_A;
  if (!(s->client_version ==SSL2_VERSION))
   
   s->s2->ssl2_rollback=1;
  
  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;
  
  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
  
  if (!ssl_init_wbio_buffer(s,1))goto err;
  
  s->state=SSL3_ST_CR_SRVR_HELLO_A;
  
  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);
   gotoerr;
   }
   
  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,inttype,int val)=NULL;
  int j;
  
  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;
 
 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()就不分析了:
int ssl3_connect(SSL *s)
 {
 BUF_MEM *buf=NULL;
 unsigned long Time=time(NULL),l;
 long num1;
 void (*cb)(const SSL *ssl,int type,intval)=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++;
   
// 初始状态应该是SSL_ST_BEFORE|SSL_ST_CONNECT
  case SSL_ST_BEFORE:
  case SSL_ST_CONNECT:
  caseSSL_ST_BEFORE|SSL_ST_CONNECT:
  caseSSL_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;
    gotoend;
    }
   
   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; }
   
   if(!ssl_init_wbio_buffer(s,0)) { ret= -1; goto end; }
   
   ssl3_init_finished_mac(s);
// 准备发送HELLO信息
   s->state=SSL3_ST_CW_CLNT_HELLO_A;
   s->ctx->stats.sess_connect++;
   s->init_num=0;
   break;
  caseSSL3_ST_CW_CLNT_HELLO_A:
  caseSSL3_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;
   
   if(s->bbio != s->wbio)
    s->wbio=BIO_push(s->bbio,s->wbio);
   break;
  caseSSL3_ST_CR_SRVR_HELLO_A:
  caseSSL3_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:
// 该状态下接收服务器发送的证书
   
   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;
  caseSSL3_ST_CR_KEY_EXCH_A:
  caseSSL3_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;
   
   if(!ssl3_check_cert_and_algorithm(s))
    {
    ret=-1;
    gotoend;
    }
   break;
  caseSSL3_ST_CR_CERT_REQ_A:
  caseSSL3_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;
  caseSSL3_ST_CR_SRVR_DONE_A:
  caseSSL3_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;
  caseSSL3_ST_CW_KEY_EXCH_A:
  caseSSL3_ST_CW_KEY_EXCH_B:
// 该状态下发送密钥交换信息
   ret=ssl3_send_client_key_exchange(s);
   if (ret <=0) goto end;
// 加密算法
   l=s->s3->tmp.new_cipher->algorithms;
   
   
   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;
  caseSSL3_ST_CW_CERT_VRFY_A:
  caseSSL3_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;
    gotoend;
    }
   if(!s->method->ssl3_enc->change_cipher_state(s,
    SSL3_CHANGE_CIPHER_CLIENT_WRITE))
    {
    ret=-1;
    gotoend;
    }
   break;
  caseSSL3_ST_CW_FINISHED_A:
  caseSSL3_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;
   
   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;
  caseSSL3_ST_CR_FINISHED_A:
  caseSSL3_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:
// 该状态下刷新写缓冲区
   
   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:
// 该状态下协商成功结束
// 释放协商时分配的资源
   
   ssl3_cleanup_key_block(s);
   if(s->init_buf != NULL)
    {
    BUF_MEM_free(s->init_buf);
    s->init_buf=NULL;
    }
   
   if(!(s->s3->flags & SSL3_FLAGS_POP_BUFFER))
    ssl_free_wbio_buffer(s);
   
   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->handshake_func=ssl3_connect;
   s->ctx->stats.sess_connect_good++;
   if (cb !=NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);
   gotoend;
   
   
  default:
   SSLerr(SSL_F_SSL3_CONNECT,SSL_R_UNKNOWN_STATE);
   ret=-1;
   gotoend;
   
   }
  
  if(!s->s3->tmp.reuse_message && !skip)
   {
   if(s->debug)
    {
    if((ret=BIO_flush(s->wbio)) <= 0)
     gotoend;
    }
   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);
 }

相关文章推荐

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

Https协议:SSL建立过程分析web访问的两种方式:http协议,我们一般情况下是通过它访问web,因为它不要求太多的安全机制,使用起来也简单,很多web站点也只支持这种方式下的访问.https协...
  • jinhill
  • jinhill
  • 2008年12月26日 16:43
  • 33348

SSL握手过程实例分析

为了更好理解SSL协议的握手过程,结合实例,使用Wireshark抓包分析SSL握手过程中客户端与服务器间的交互过程。本例中服务器为https://www.baidu.com/(180.97.33.1...

SSL连接建立过程分析

SSL连接建立过程分析 字体大小:大 中 小 博文 SSL连接建立过程分析(1) (2006-10-23 08:54) 分类: openssl SSL连接建立过程分析(1)...

嵌入式 建立ssl连接过程分析一

Https协议:SSL建立过程分析 web访问的两种方式: http协议,我们一般情况下是通过它访问web,因为它不要求太多的安全机制,使用起来也简单,很多web站点也只支持这种方式下的访问. ...
  • skdkjxy
  • skdkjxy
  • 2013年12月02日 14:46
  • 1205

SSL连接建立过程分析

 Https协议:SSL建立过程分析 web访问的两种方式: http协议,我们一般情况下是通过它访问web,因为它不要求太多的安全机制,使用起来也简单,很多web站点也只支持这种方式下的访...

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

Https协议:SSL建立过程分析 web访问的两种方式: http协议,我们一般情况下是通过它访问web,因为它不要求太多的安全机制,使用起来也简单,很多web站点也只支持这种方式下的访问. htt...

嵌入式 vlc从接收到数据流到播放视频的过程分析

Vlc流播放流程  vlc源码目录树: 目录名称 说明 bindings Java, CIL 和Python绑定 doc ...
  • cds9527
  • cds9527
  • 2016年12月07日 11:33
  • 1495

Https协议:SSL建立过程分析

web访问的两种方式: http协议,我们一般情况下是通过它访问web,因为它不要求太多的安全机制,使用起来也简单,很多web站点也只支持这种方式下的访问. https协议(Hyperte...
  • gao8658
  • gao8658
  • 2012年05月18日 11:56
  • 2750

Https 建立安全连接的过程(SSL原理)

文中首先解释了加密解密的一些基础知识和概念,然后通过一个加密通信过程的例子说明了加密算法的作用,以及数字证书的出现所起的作用。接着对数字证书做一个详细的解释,并讨论一下windows中数字证书的管理,...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:嵌入式 建立ssl连接过程分析四
举报原因:
原因补充:

(最多只允许输入30个字)