📄 s3_pkt.c
字号:
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); if ((unsigned int)len > rr->length) n = rr->length; else n = (unsigned int)len; memcpy(buf,&(rr->data[rr->off]),n); if (!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)) { 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)) { al=SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_HELLO_REQUEST); goto f_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) && !s->s3->renegotiate) { 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)) { 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); } } } } /* 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) { int alert_level = s->s3->alert_fragment[0]; int alert_descr = s->s3->alert_fragment[1]; s->s3->alert_fragment_len = 0; 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 */ { 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 */ { 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)) { al=SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC); goto f_err; } /* Check we have a cipher to change to */ if (s->s3->tmp.new_cipher == NULL) { al=SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_CCS_RECEIVED_EARLY); goto f_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 (!ssl3_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) { 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 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 */ 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) ) )) { 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); }int ssl3_do_change_cipher_spec(SSL *s) { int i; const char *sender; int slen; if (s->state & SSL_ST_ACCEPT) i=SSL3_CHANGE_CIPHER_SERVER_READ; else i=SSL3_CHANGE_CIPHER_CLIENT_READ; if (s->s3->tmp.key_block == NULL) { s->session->cipher=s->s3->tmp.new_cipher; if (!s->method->ssl3_enc->setup_key_block(s)) return(0); } if (!s->method->ssl3_enc->change_cipher_state(s,i)) return(0); /* we have to record the message digest at * this point so we can get it before we read * the finished message */ if (s->state & SSL_ST_CONNECT) { sender=s->method->ssl3_enc->server_finished_label; slen=s->method->ssl3_enc->server_finished_label_len; } else { sender=s->method->ssl3_enc->client_finished_label; slen=s->method->ssl3_enc->client_finished_label_len; } s->s3->tmp.peer_finish_md_len = s->method->ssl3_enc->final_finish_mac(s, &(s->s3->finish_dgst1), &(s->s3->finish_dgst2), sender,slen,s->s3->tmp.peer_finish_md); return(1); }void ssl3_send_alert(SSL *s, int level, int desc) { /* Map tls/ssl alert value to correct one */ desc=s->method->ssl3_enc->alert_value(desc); if (s->version == SSL3_VERSION && desc == SSL_AD_PROTOCOL_VERSION) desc = SSL_AD_HANDSHAKE_FAILURE; /* SSL 3.0 does not have protocol_version alerts */ if (desc < 0) return; /* If a fatal one, remove from cache */ if ((level == 2) && (s->session != NULL)) SSL_CTX_remove_session(s->ctx,s->session); s->s3->alert_dispatch=1; s->s3->send_alert[0]=level; s->s3->send_alert[1]=desc; if (s->s3->wbuf.left == 0) /* data still being written out? */ s->method->ssl_dispatch_alert(s); /* else data is still being written out, we will get written * some time in the future */ }int ssl3_dispatch_alert(SSL *s) { int i,j; void (*cb)(const SSL *ssl,int type,int val)=NULL; s->s3->alert_dispatch=0; i = do_ssl3_write(s, SSL3_RT_ALERT, &s->s3->send_alert[0], 2, 0); if (i <= 0) { s->s3->alert_dispatch=1; } else { /* Alert sent to BIO. If it is important, flush it now. * If the message does not get sent due to non-blocking IO, * we will not worry too much. */ if (s->s3->send_alert[0] == SSL3_AL_FATAL) (void)BIO_flush(s->wbio); if (s->msg_callback) s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert, 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=(s->s3->send_alert[0]<<8)|s->s3->send_alert[1]; cb(s,SSL_CB_WRITE_ALERT,j); } } return(i); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -