zoukankan      html  css  js  c++  java
  • SSL连接建立过程分析(5)

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

    本文档的Copyleft归yfydz所有,使用GPL发布,可以自由拷贝,转载,转载时请保持文档的完整性,严禁用于任何商业用途。
    msn: yfydz_no1@hotmail.com
    来源:http://yfydz.cublog.cn/

    2.14 SSL_read

    SSL结构(struct ssl_st)中的s2,s3指针分别指向SSL2和SSL3的状态结构,这些状态结构中都有用于读的rbuf,其中保存SSL会话接收到的原始数据,另外还有保存记录的rrec,用来保存解码后的数据。在SSL结构中有个指针packet是指向原始数据的。

    SSL_read()实现从SSL通道中读取数据,送到应用程序的数据是已经经过SSL解封装的了。

    /* ssl/ssl_lib.c */
    int SSL_read(SSL *s,void *buf,int num)
     {
     if (s->handshake_func == 0)
      {
      SSLerr(SSL_F_SSL_READ, SSL_R_UNINITIALIZED);
      return -1;
      }
    // 发现接收shutdown标志,接收结束
     if (s->shutdown & SSL_RECEIVED_SHUTDOWN)
      {
      s->rwstate=SSL_NOTHING;
      return(0);
      }
    // 调用具体方法的接收函数, 如ssl3_read(), ssl2_read()等
     return(s->method->ssl_read(s,buf,num));
     }

    下面以ssl3_read()函数进行详细说明,ssl3_read()函数本质是调用ssl3_read_internal()
    /* ssl/s3_lib.c */
    int ssl3_read(SSL *s, void *buf, int len)
     {
    // 最后一个参数为0,表示是实实在在的读数据,不是偷看(peek)
    // peek的意思是读数据,但不会把已读数据从缓冲区中去掉,因此下一次读还会读到
     return ssl3_read_internal(s, buf, len, 0);
     }

    static int ssl3_read_internal(SSL *s, void *buf, int len, int peek)
     {
     int ret;
    // 清除错误信息 
     clear_sys_error();
    // 检查协商是否成功
     if (s->s3->renegotiate) ssl3_renegotiate_check(s);
    // 标志现在在读应用层数据
     s->s3->in_read_app_data=1;
    // ssl3读取数据, 类型是SSL3_RT_APPLICATION_DATA,应用数据
     ret=ssl3_read_bytes(s,SSL3_RT_APPLICATION_DATA,buf,len,peek);
     if ((ret == -1) && (s->s3->in_read_app_data == 2))
      {
    // s->s3->in_read_app_data == 2表示要读协商数据
      /* ssl3_read_bytes decided to call s->handshake_func, which
       * called ssl3_read_bytes to read handshake data.
       * However, ssl3_read_bytes actually found application data
       * and thinks that application data makes sense here; so disable
       * handshake processing and try to read application data again. */
      s->in_handshake++;
    // 重新读数据
      ret=ssl3_read_bytes(s,SSL3_RT_APPLICATION_DATA,buf,len,peek);
      s->in_handshake--;
      }
     else
      s->s3->in_read_app_data=0;
     return(ret);
     }

    读取数据的主要函数实际为ssl3_read_bytes():
    /* ssl/ssl3_pkt.c */
    int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
     {
     int al,i,j,ret;
     unsigned int n;
     SSL3_RECORD *rr;
     void (*cb)(const SSL *ssl,int type2,int val)=NULL;
    // 检查是否分配了接收缓冲区
     if (s->s3->rbuf.buf == NULL) /* Not initialized yet */
      if (!ssl3_setup_buffers(s))
       return(-1);
    // 只处理两种数据,或是应用层数据或者是SSL握手协商数据,
    // peek只处理应用层数据,其他则出错
     if ((type && (type != SSL3_RT_APPLICATION_DATA) &&
         (type != SSL3_RT_HANDSHAKE) && type) ||
         (peek && (type != SSL3_RT_APPLICATION_DATA)))
      {
      SSLerr(SSL_F_SSL3_READ_BYTES, ERR_R_INTERNAL_ERROR);
      return -1;
      }
     if ((type == SSL3_RT_HANDSHAKE) && (s->s3->handshake_fragment_len > 0))
      /* (partially) satisfy request from storage */
      {
    // 握手数据碎片, 处理完直到不再是碎片
      unsigned char *src = s->s3->handshake_fragment;
      unsigned char *dst = buf;
      unsigned int k;
      /* peek == 0 */
      n = 0;
      while ((len > 0) && (s->s3->handshake_fragment_len > 0))
       {
       *dst++ = *src++;
       len--; s->s3->handshake_fragment_len--;
       n++;
       }
      /* move any remaining fragment bytes: */
      for (k = 0; k < s->s3->handshake_fragment_len; k++)
       s->s3->handshake_fragment[k] = *src++;
      return n;
     }
     /* Now s->s3->handshake_fragment_len == 0 if type == SSL3_RT_HANDSHAKE. */
     if (!s->in_handshake && SSL_in_init(s))
      {
    // 没进握手阶段但属于SSL初始化阶段, 调用SSL握手处理
      /* type == SSL3_RT_APPLICATION_DATA */
      i=s->handshake_func(s);
      if (i < 0) return(i);
      if (i == 0)
       {
       SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
       return(-1);
       }
      }
    start:
    // 正常的接收数据开始, 开始读写状态为NOTHING
     s->rwstate=SSL_NOTHING;
     /* s->s3->rrec.type     - is the type of record
      * s->s3->rrec.data,    - data
      * s->s3->rrec.off,     - offset into 'data' for next read
      * s->s3->rrec.length,  - number of bytes. */
    // 记录类型指针
     rr = &(s->s3->rrec);
     /* get new packet if necessary */
     if ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY))
      {
    // 当前没记录,获取新的记录信息, 该函数获取SSL记录数据
      ret=ssl3_get_record(s);
      if (ret <= 0) return(ret);
      }
     /* we now have a packet which can be read and processed */
     if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec,
                                    * reset by ssl3_get_finished */
      && (rr->type != SSL3_RT_HANDSHAKE))
      {
    // 只允许在握手状态下修改当前的算法信息,否则出错
      al=SSL_AD_UNEXPECTED_MESSAGE;
      SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_DATA_BETWEEN_CCS_AND_FINISHED);
      goto err;
      }
     /* If the other end has shut down, throw anything we read away
      * (even in 'peek' mode) */
     if (s->shutdown & SSL_RECEIVED_SHUTDOWN)
      {
    // 接收到对方的FIN信息, 接收结束
      rr->length=0;
      s->rwstate=SSL_NOTHING;
      return(0);
      }

     if (type == rr->type) /* SSL3_RT_APPLICATION_DATA or SSL3_RT_HANDSHAKE */
      {
    // 读到是数据类型和期待读到的数据类型一致
    // 这是正常大多数的情况
      /* make sure that we are not getting application data when we
       * are doing a handshake for the first time */
      if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) &&
       (s->enc_read_ctx == NULL))
       {
    // 在初始阶段只应该读握手信息而不该读应用信息
       al=SSL_AD_UNEXPECTED_MESSAGE;
       SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_APP_DATA_IN_HANDSHAKE);
       goto f_err;
       }
      if (len <= 0) return(len);
    // 在期待读取的数据长度len和已经读到的数据记录长度rr->length取小值作为返回的数据长度
      if ((unsigned int)len > rr->length)
       n = rr->length;
      else
       n = (unsigned int)len;
      memcpy(buf,&(rr->data[rr->off]),n);
      if (!peek)
       {
    // 如果不是peek,移动记录缓冲的数据偏移指针,长度减
       rr->length-=n;
       rr->off+=n;
       if (rr->length == 0)
        {
        s->rstate=SSL_ST_READ_HEADER;
        rr->off=0;
        }
       }
    // 正常返回
      return(n);
      }

     /* If we get here, then type != rr->type; if we have a handshake
      * message, then it was unexpected (Hello Request or Client Hello). */
     /* In case of record types for which we have 'fragment' storage,
      * fill that so that we can process the data at a fixed place.
      */
    // 现在情况是读取的数据类型和期待读取的数据类型不一致
    // 已经读到的数据不丢弃,而是作为碎片存储起来以后备用
      {
      unsigned int dest_maxlen = 0;
      unsigned char *dest = NULL;
      unsigned int *dest_len = NULL;
      if (rr->type == SSL3_RT_HANDSHAKE)
       {
    // 握手类型数据存到握手碎片区
       dest_maxlen = sizeof s->s3->handshake_fragment;
       dest = s->s3->handshake_fragment;
       dest_len = &s->s3->handshake_fragment_len;
       }
      else if (rr->type == SSL3_RT_ALERT)
       {
    // 告警信息存到告警碎片区
       dest_maxlen = sizeof s->s3->alert_fragment;
       dest = s->s3->alert_fragment;
       dest_len = &s->s3->alert_fragment_len;
       }
      if (dest_maxlen > 0)
       {
    // 有缓冲区, 计算可用的最大缓冲区
       n = dest_maxlen - *dest_len; /* available space in 'dest' */
    // 如果要写入的长度小于可用空间大小,可全部写入
       if (rr->length < n)
        n = rr->length; /* available bytes */
    // 写入缓冲区
       /* now move 'n' bytes: */
       while (n-- > 0)
        {
        dest[(*dest_len)++] = rr->data[rr->off++];
        rr->length--;
        }
       if (*dest_len < dest_maxlen)
        goto start; /* fragment was too small */
       }
      }
     /* s->s3->handshake_fragment_len == 4  iff  rr->type == SSL3_RT_HANDSHAKE;
      * s->s3->alert_fragment_len == 2      iff  rr->type == SSL3_RT_ALERT.
      * (Possibly rr is 'empty' now, i.e. rr->length may be 0.) */
     /* If we are a client, check for an incoming 'Hello Request': */
     if ((!s->server) &&
      (s->s3->handshake_fragment_len >= 4) &&
      (s->s3->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) &&
      (s->session != NULL) && (s->session->cipher != NULL))
      {
    // 本地是客户端
    // 握手碎片长度至少是4字节, 类型是HELLO的握手信息时进行处理
      s->s3->handshake_fragment_len = 0;
      if ((s->s3->handshake_fragment[1] != 0) ||
       (s->s3->handshake_fragment[2] != 0) ||
       (s->s3->handshake_fragment[3] != 0))
       {
    // SSL3_MT_HELLO_REQUEST类型后三个字节都要是0
       al=SSL_AD_DECODE_ERROR;
       SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_HELLO_REQUEST);
       goto err;
       }
      if (s->msg_callback)
       s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->s3->handshake_fragment, 4, s, s->msg_callback_arg);
      if (SSL_is_init_finished(s) &&
    // 协商结束但没设置不需重协商算法标志
       !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) &&
    // 没设置该ssl3会话的重协商标志
       !s->s3->renegotiate)
       {
    // 进行ssl3重协商,实际是将s->s3->renegotiate置1
       ssl3_renegotiate(s);
       if (ssl3_renegotiate_check(s))
        {
    // 进行重协商
        i=s->handshake_func(s);
        if (i < 0) return(i);
        if (i == 0)
         {
         SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
         return(-1);
         }
        if (!(s->mode & SSL_MODE_AUTO_RETRY))
    // 该SSL会话不是自动重试模式
         {
         if (s->s3->rbuf.left == 0) /* no read-ahead left? */
          {
          BIO *bio;
      /* In the case where we try to read application data,
       * but we trigger an SSL handshake, we return -1 with
       * the retry option set.  Otherwise renegotiation may
       * cause nasty problems in the blocking world */
          s->rwstate=SSL_READING;
          bio=SSL_get_rbio(s);
    // 清除读BIO重试标志
          BIO_clear_retry_flags(bio);
    // 设置读BIO重试标志
          BIO_set_retry_read(bio);
          return(-1);
          }
         }
        }
       }
     /* we either finished a handshake or ignored the request,
      * now try again to obtain the (application) data we were asked for */
    // 重新读数据
      goto start;
      }
     if (s->s3->alert_fragment_len >= 2)
      {
    // 处理告警碎片信息, 长度大于等于2字节时就处理
      int alert_level = s->s3->alert_fragment[0];
      int alert_descr = s->s3->alert_fragment[1];
      s->s3->alert_fragment_len = 0;
    // 分别处理msg和info的回调
      if (s->msg_callback)
       s->msg_callback(0, s->version, SSL3_RT_ALERT, s->s3->alert_fragment, 2, s, s->msg_callback_arg);
      if (s->info_callback != NULL)
       cb=s->info_callback;
      else if (s->ctx->info_callback != NULL)
       cb=s->ctx->info_callback;
      if (cb != NULL)
       {
       j = (alert_level << 8) | alert_descr;
       cb(s, SSL_CB_READ_ALERT, j);
       }
      if (alert_level == 1) /* warning */
       {
    // 普通报警信息
       s->s3->warn_alert = alert_descr;
       if (alert_descr == SSL_AD_CLOSE_NOTIFY)
        {
        s->shutdown |= SSL_RECEIVED_SHUTDOWN;
        return(0);
        }
       }
      else if (alert_level == 2) /* fatal */
       {
    // 严重错误信息, 断开SSL会话
       char tmp[16];
       s->rwstate=SSL_NOTHING;
       s->s3->fatal_alert = alert_descr;
       SSLerr(SSL_F_SSL3_READ_BYTES, SSL_AD_REASON_OFFSET + alert_descr);
       BIO_snprintf(tmp,sizeof tmp,"%d",alert_descr);
       ERR_add_error_data(2,"SSL alert number ",tmp);
       s->shutdown|=SSL_RECEIVED_SHUTDOWN;
       SSL_CTX_remove_session(s->ctx,s->session);
       return(0);
       }
      else
       {
       al=SSL_AD_ILLEGAL_PARAMETER;
       SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNKNOWN_ALERT_TYPE);
       goto f_err;
       }
      goto start;
      }
     if (s->shutdown & SSL_SENT_SHUTDOWN) /* but we have not received a shutdown */
      {
    // SSL会话设置发送SHUTDOWN, 表示不再发送数据
      s->rwstate=SSL_NOTHING;
      rr->length=0;
      return(0);
      }
     if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC)
      {
    // 数据记录类型是更改算法参数
      /* 'Change Cipher Spec' is just a single byte, so we know
       * exactly what the record payload has to look like */
      if ( (rr->length != 1) || (rr->off != 0) ||
       (rr->data[0] != SSL3_MT_CCS))
       {
    // 错误检查
       i=SSL_AD_ILLEGAL_PARAMETER;
       SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC);
       goto err;
       }
      rr->length=0;
      if (s->msg_callback)
       s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, rr->data, 1, s, s->msg_callback_arg);
    // 加密算法更改处理,成功时转到重新接收数据
      s->s3->change_cipher_spec=1;
      if (!do_change_cipher_spec(s))
       goto err;
      else
       goto start;
      }
     /* Unexpected handshake message (Client Hello, or protocol violation) */
     if ((s->s3->handshake_fragment_len >= 4) && !s->in_handshake)
      {
    // 异常的握手信息
    // SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS标志表示不需要重新协商加密算法
      if (((s->state&SSL_ST_MASK) == SSL_ST_OK) &&
       !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS))
       {
    #if 0 /* worked only because C operator preferences are not as expected (and
           * because this is not really needed for clients except for detecting
           * protocol violations): */
       s->state=SSL_ST_BEFORE|(s->server)
        ?SSL_ST_ACCEPT
        :SSL_ST_CONNECT;
    #else
    // 如果是服务器端,SSL状态转为接受;如果是客户端, 转为连接
       s->state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT;
    #endif
    // 重新进行新会话
       s->new_session=1;
       }
    // 重新握手协商
      i=s->handshake_func(s);
      if (i < 0) return(i);
      if (i == 0)
       {
       SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
       return(-1);
       }
      if (!(s->mode & SSL_MODE_AUTO_RETRY))
       {
       if (s->s3->rbuf.left == 0) /* no read-ahead left? */
        {
        BIO *bio;
        /* In the case where we try to read application data,
         * but we trigger an SSL handshake, we return -1 with
         * the retry option set.  Otherwise renegotiation may
         * cause nasty problems in the blocking world */
        s->rwstate=SSL_READING;
        bio=SSL_get_rbio(s);
        BIO_clear_retry_flags(bio);
        BIO_set_retry_read(bio);
        return(-1);
        }
       }
      goto start;
      }
    // 最后再根据记录类型进行处理
     switch (rr->type)
      {
     default:
    #ifndef OPENSSL_NO_TLS
      /* TLS just ignores unknown message types */
    // 如果会话是TLS1版本转为重新接收数据
    // 其他版本则认为出错
      if (s->version == TLS1_VERSION)
       {
       rr->length = 0;
       goto start;
       }
    #endif
      al=SSL_AD_UNEXPECTED_MESSAGE;
      SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
      goto f_err;
     case SSL3_RT_CHANGE_CIPHER_SPEC:
     case SSL3_RT_ALERT:
     case SSL3_RT_HANDSHAKE:
    // 这几种类型前面已经处理过了, 到这还有的话是哪出错了
      /* we already handled all of these, with the possible exception
       * of SSL3_RT_HANDSHAKE when s->in_handshake is set, but that
       * should not happen when type != rr->type */
      al=SSL_AD_UNEXPECTED_MESSAGE;
      SSLerr(SSL_F_SSL3_READ_BYTES,ERR_R_INTERNAL_ERROR);
      goto f_err;
      case SSL3_RT_APPLICATION_DATA:
    // 这时情况是收到的是应用数据,而期望接收的是握手数据
      /* At this point, we were expecting handshake data,
       * but have application data.  If the library was
       * running inside ssl3_read() (i.e. in_read_app_data
       * is set) and it makes sense to read application data
       * at this point (session renegotiation not yet started),
       * we will indulge it.
       */
    // 要接收应用数据
      if (s->s3->in_read_app_data &&
    // 需要重协商
       (s->s3->total_renegotiations != 0) &&
       ((
        (s->state & SSL_ST_CONNECT) &&
        (s->state >= SSL3_ST_CW_CLNT_HELLO_A) &&
        (s->state <= SSL3_ST_CR_SRVR_HELLO_A)
        ) || (
         (s->state & SSL_ST_ACCEPT) &&
         (s->state <= SSL3_ST_SW_HELLO_REQ_A) &&
         (s->state >= SSL3_ST_SR_CLNT_HELLO_A)
         )
        ))
       {
    // in_read_app_data设置为2,会重新执行ssl3_read_bytes()
       s->s3->in_read_app_data=2;
       return(-1);
       }
      else
       {
       al=SSL_AD_UNEXPECTED_MESSAGE;
       SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
       goto f_err;
       }
      }
     /* not reached */
    f_err:
    // 错误时发送告警信息
     ssl3_send_alert(s,SSL3_AL_FATAL,al);
    err:
     return(-1);
     }

    可以看出接收数据的重点函数是ssl3_get_record():
    /* ssl/s3_pkt.c */
    static int ssl3_get_record(SSL *s)
     {
     int ssl_major,ssl_minor,al;
     int enc_err,n,i,ret= -1;
     SSL3_RECORD *rr;
     SSL_SESSION *sess;
     unsigned char *p;
     unsigned char md[EVP_MAX_MD_SIZE];
     short version;
     unsigned int mac_size;
     int clear=0;
     size_t extra;
     int decryption_failed_or_bad_record_mac = 0;
     unsigned char *mac = NULL;
    // 所读数据的记录指针
     rr= &(s->s3->rrec);
     sess=s->session;
     if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)
    // MS的SSL实现可附带较大数据
      extra=SSL3_RT_MAX_EXTRA;
     else
      extra=0;
     if (extra != s->s3->rbuf.len - SSL3_RT_MAX_PACKET_SIZE)
    // 普通情况下读缓冲大小就是SSL3_RT_MAX_PACKET_SIZE
      {
    /* actually likely an application error: SLS_OP_MICROSOFT_BIG_SSLV3_BUFFER
     * set after ssl3_setup_buffers() was done */
      SSLerr(SSL_F_SSL3_GET_RECORD, ERR_R_INTERNAL_ERROR);
      return -1;
      }
    again:
     /* check if we have the header */
     if ( (s->rstate != SSL_ST_READ_BODY) ||
    // 接收的数据长度还不够记录长度
      (s->packet_length < SSL3_RT_HEADER_LENGTH))
      {
    // 读至少SSL3_RT_HEADER_LENGTH长度,最大s->s3->rbuf.len
      n=ssl3_read_n(s, SSL3_RT_HEADER_LENGTH, s->s3->rbuf.len, 0);
      if (n <= 0) return(n); /* error or non-blocking */
      s->rstate=SSL_ST_READ_BODY;
    // p现在是SSL收到的原始数据头
      p=s->packet;
      /* Pull apart the header into the SSL3_RECORD */
    // SSL记录类型
      rr->type= *(p++);
    // 版本信息
      ssl_major= *(p++);
      ssl_minor= *(p++);
      version=(ssl_major<<8)|ssl_minor;
    // 数据长度
      n2s(p,rr->length);
      /* Lets check version */
      if (s->first_packet)
       {
       s->first_packet=0;
       }
      else
       {
    // 已经不是第一个包了
    // 检查版本是否等于SSL会话版本,这时应该协商好应该是相同的了
    // 如果不同就是错的
       if (version != s->version)
        {
        SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER);
        /* Send back error using their
         * version number :-) */
        s->version=version;
        al=SSL_AD_PROTOCOL_VERSION;
        goto f_err;
        }
       }
    // 检查版本是否是SSL3
      if ((version>>8) != SSL3_VERSION_MAJOR)
       {
       SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER);
       goto err;
       }
    // 接收数据过长出错
      if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH+extra)
       {
       al=SSL_AD_RECORD_OVERFLOW;
       SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_PACKET_LENGTH_TOO_LONG);
       goto f_err;
       }
      /* now s->rstate == SSL_ST_READ_BODY */
      }
     /* s->rstate == SSL_ST_READ_BODY, get and decode the data */
    // SSL3_RT_HEADER_LENGTH = 5
     if (rr->length > s->packet_length-SSL3_RT_HEADER_LENGTH)
      {
    // 已收到的数据还不够记录长度, 继续读够记录长度
      /* now s->packet_length == SSL3_RT_HEADER_LENGTH */
      i=rr->length;
      n=ssl3_read_n(s,i,i,1);
      if (n <= 0) return(n); /* error or non-blocking io */
      /* now n == rr->length,
       * and s->packet_length == SSL3_RT_HEADER_LENGTH + rr->length */
      }
    //
    // 状态转为已经接收到SSL头信息
     s->rstate=SSL_ST_READ_HEADER; /* set state for later operations */
     /* At this point, s->packet_length == SSL3_RT_HEADER_LNGTH + rr->length,
      * and we have that many bytes in s->packet
      */
    // input指向SSL原始数据头后的数据
     rr->input= &(s->packet[SSL3_RT_HEADER_LENGTH]);
     /* ok, we can now read from 's->packet' data into 'rr'
      * rr->input points at rr->length bytes, which
      * need to be copied into rr->data by either
      * the decryption or by the decompression
      * When the data is 'copied' into the rr->data buffer,
      * rr->input will be pointed at the new buffer */
     /* We now have - encrypted [ MAC [ compressed [ plain ] ] ]
      * rr->length bytes of encrypted compressed stuff. */
     /* check is not needed I believe */
     if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH+extra)
      {
    // 数据又读多了
      al=SSL_AD_RECORD_OVERFLOW;
      SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
      goto f_err;
      }
     /* decrypt in place in 'rr->input' */
    // 记录数据
     rr->data=rr->input;
    // 对数据进行解密
     enc_err = s->method->ssl3_enc->enc(s,0);
     if (enc_err <= 0)
      {
      if (enc_err == 0)
       /* SSLerr() and ssl3_send_alert() have been called */
       goto err;
      /* Otherwise enc_err == -1, which indicates bad padding
       * (rec->length has not been changed in this case).
       * To minimize information leaked via timing, we will perform
       * the MAC computation anyway. */
    // 注意 enc_err<0 时并不立即转到错误处理,只是作个标志
      decryption_failed_or_bad_record_mac = 1;
      }

     /* r->length is now the compressed data plus mac */
     if ( (sess == NULL) ||
      (s->enc_read_ctx == NULL) ||
      (s->read_hash == NULL))
    // 会话,加密上下文,读认证码操作都为空的情况,设置标志clear
      clear=1;
     if (!clear)
      {
    // HASH算法的认证码长度
      mac_size=EVP_MD_size(s->read_hash);
      if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra+mac_size)
       {
    #if 0 /* OK only for stream ciphers (then rr->length is visible from ciphertext anyway) */
       al=SSL_AD_RECORD_OVERFLOW;
       SSLerr(SSL_F_SSL3_GET_RECORD,
        SSL_R_PRE_MAC_LENGTH_TOO_LONG);
       goto f_err;
    #else
    // 长度过长, 设置出错标志
       decryption_failed_or_bad_record_mac = 1;
    #endif   
       }
      /* check the MAC for rr->input (it's in mac_size bytes at the tail) */
      if (rr->length >= mac_size)
       {
    // 记录长度中减去认证码长度
       rr->length -= mac_size;
    // 认证码数据指针
       mac = &rr->data[rr->length];
       }
      else
       {
       /* record (minus padding) is too short to contain a MAC */
    #if 0 /* OK only for stream ciphers */
       al=SSL_AD_DECODE_ERROR;
       SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_LENGTH_TOO_SHORT);
       goto f_err;
    #else
    // 记录长度还没认证码长度长, 设置出错标志
       decryption_failed_or_bad_record_mac = 1;
       rr->length = 0;
    #endif
       }
    // 用认证码对数据进行认证
      i=s->method->ssl3_enc->mac(s,md,0);
      if (mac == NULL || memcmp(md, mac, mac_size) != 0)
       {
       decryption_failed_or_bad_record_mac = 1;
       }
      }
     if (decryption_failed_or_bad_record_mac)
      {
    // 解密错误, 跳出
      /* A separate 'decryption_failed' alert was introduced with TLS 1.0,
       * SSL 3.0 only has 'bad_record_mac'.  But unless a decryption
       * failure is directly visible from the ciphertext anyway,
       * we should not reveal which kind of error occured -- this
       * might become visible to an attacker (e.g. via a logfile) */
      al=SSL_AD_BAD_RECORD_MAC;
      SSLerr(SSL_F_SSL3_GET_RECORD,
       SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
      goto f_err;
      }
     /* r->length is now just compressed */
     if (s->expand != NULL)
    // 现在数据是经过压缩处理的
      {
      if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra)
       {
    // 压缩数据长度又太长了
       al=SSL_AD_RECORD_OVERFLOW;
       SSLerr(SSL_F_SSL3_GET_RECORD,
        SSL_R_COMPRESSED_LENGTH_TOO_LONG);
       goto f_err;
       }
    // 对数据解压
      if (!do_uncompress(s))
       {
    // 解压失败, 跳出
       al=SSL_AD_DECOMPRESSION_FAILURE;
       SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BAD_DECOMPRESSION);
       goto f_err;
       }
      }
     if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH+extra)
      {
    // 解压缩后的明文数据长度过长, 跳出
      al=SSL_AD_RECORD_OVERFLOW;
      SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_DATA_LENGTH_TOO_LONG);
      goto f_err;
      }
     rr->off=0;
     /* So at this point the following is true
      * ssl->s3->rrec.type  is the type of record
      * ssl->s3->rrec.length == number of bytes in record
      * ssl->s3->rrec.off == offset to first valid byte
      * ssl->s3->rrec.data == where to take bytes from, increment
      *      after use :-).
      */
     /* we have pulled in a full packet so zero things */
     s->packet_length=0;
     /* just read a 0 length packet */
    // 如果记录长度为0, 转到继续接收数据
     if (rr->length == 0) goto again;
     return(1);
    f_err:
    // 错误发送告警信息
     ssl3_send_alert(s,SSL3_AL_FATAL,al);
    err:
     return(ret);
     }

    最后看一下ssl3_read_n()函数,接收SSL原始数据, 该函数只被ssl3_get_record()函数调用,是static的:
    /* ssl/s3_pkt.c */
    static int ssl3_read_n(SSL *s, int n, int max, int extend)
     {
    // extend为0时表示要读全新数据,非0表示可以用现在缓冲中的数据
     /* If extend == 0, obtain new n-byte packet; if extend == 1, increase
      * packet by another n bytes.
      * The packet will be in the sub-array of s->s3->rbuf.buf specified
      * by s->packet and s->packet_length.
      * (If s->read_ahead is set, 'max' bytes may be stored in rbuf
      * [plus s->packet_length bytes if extend == 1].)
      */
     int i,off,newb;
     if (!extend)
      {
      /* start with empty packet ... */
    // 确定包缓冲地址, 置当前的包长为0
      if (s->s3->rbuf.left == 0)
       s->s3->rbuf.offset = 0;
      s->packet = s->s3->rbuf.buf + s->s3->rbuf.offset;
      s->packet_length = 0;
      /* ... now we can act as if 'extend' was set */
      }
     /* if there is enough in the buffer from a previous read, take some */
     if (s->s3->rbuf.left >= (int)n)
      {
    // 如果已读缓冲区中剩余数据超过要读的数据,直接移动指针即可
      s->packet_length+=n;
      s->s3->rbuf.left-=n;
      s->s3->rbuf.offset+=n;
      return(n);
      }
     /* else we need to read more data */
    // 预读数据长度为0
     if (!s->read_ahead)
      max=n;
     {
      /* avoid buffer overflow */
    // 当前缓冲区最大空闲值
      int max_max = s->s3->rbuf.len - s->packet_length;
      if (max > max_max)
       max = max_max;
     }
     if (n > max) /* does not happen */
      {
    // 要读的数据量超过了缓冲区量,出错
      SSLerr(SSL_F_SSL3_READ_N,ERR_R_INTERNAL_ERROR);
      return -1;
      }
     off = s->packet_length;
    // newb为读缓冲区中剩下的有效数据长度
     newb = s->s3->rbuf.left;
     /* Move any available bytes to front of buffer:
      * 'off' bytes already pointed to by 'packet',
      * 'newb' extra ones at the end */
     if (s->packet != s->s3->rbuf.buf)
      {
      /*  off > 0 */
      memmove(s->s3->rbuf.buf, s->packet, off+newb);
      s->packet = s->s3->rbuf.buf;
      }
     while (newb < n)
      {
     /* Now we have off+newb bytes at the front of s->s3->rbuf.buf and need
      * to read in more until we have off+n (up to off+max if possible) */
      clear_sys_error();
      if (s->rbio != NULL)
       {
       s->rwstate=SSL_READING;
    // 通过SSL的读BIO读取数据
       i=BIO_read(s->rbio, &(s->s3->rbuf.buf[off+newb]), max-newb);
       }
      else
       {
       SSLerr(SSL_F_SSL3_READ_N,SSL_R_READ_BIO_NOT_SET);
       i = -1;
       }
      if (i <= 0)
       {
    // 读完或出错, newb为缓冲区剩余有效数据长度
       s->s3->rbuf.left = newb;
       return(i);
       }
      newb+=i;
      }
     /* done reading, now the book-keeping */
    // 读数据完成, 修改偏移量和剩余数据长度
     s->s3->rbuf.offset = off + n;
     s->s3->rbuf.left = newb - n;
     s->packet_length += n;
     s->rwstate=SSL_NOTHING;
     return(n);
     }

    ...... 待续 ......
  • 相关阅读:
    easyui datagride 两种查询方式
    SharePoint常用目录介绍
    sharepoint 2013 入门1_ 建立一个网页程序
    Windows2012 显示我的电脑
    你知道 react-color 的实现原理吗
    如何实现 Promise 池
    如何使 pdf 文件在浏览器里面直接下载而不是打开
    macOS 安装 oh-my-zsh 之后 node 失效的问题
    剑指offer[47]——求1+2+3+...+n
    剑指offer[46]——孩子们的游戏(圆圈中最后剩下的数)
  • 原文地址:https://www.cnblogs.com/adylee/p/1541093.html
Copyright © 2011-2022 走看看