msn: [email protected]
来源: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); } ...... 待续 ......