📄 d1_pkt.c
字号:
int alert_level = s->d1->alert_fragment[0]; int alert_descr = s->d1->alert_fragment[1]; s->d1->alert_fragment_len = 0; if (s->msg_callback) s->msg_callback(0, s->version, SSL3_RT_ALERT, s->d1->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); }#if 0 /* XXX: this is a possible improvement in the future */ /* now check if it's a missing record */ if (alert_descr == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE) { unsigned short seq; unsigned int frag_off; unsigned char *p = &(s->d1->alert_fragment[2]); n2s(p, seq); n2l3(p, frag_off); dtls1_retransmit_message(s, seq, frag_off, &found); if ( ! found && SSL_in_init(s)) { /* fprintf( stderr,"in init = %d\n", SSL_in_init(s)); */ /* requested a message not yet sent, send an alert ourselves */ ssl3_send_alert(s,SSL3_AL_WARNING, DTLS1_AD_MISSING_HANDSHAKE_MESSAGE); } }#endif } else if (alert_level == 2) /* fatal */ { char tmp[16]; s->rwstate=SSL_NOTHING; s->s3->fatal_alert = alert_descr; SSLerr(SSL_F_DTLS1_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_DTLS1_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) { struct ccs_header_st ccs_hdr; dtls1_get_ccs_header(rr->data, &ccs_hdr); if ( ccs_hdr.seq == s->d1->handshake_read_seq) { /* 'Change Cipher Spec' is just a single byte, so we know * exactly what the record payload has to look like */ /* XDTLS: check that epoch is consistent */ if ( (rr->length != DTLS1_CCS_HEADER_LENGTH) || (rr->off != 0) || (rr->data[0] != SSL3_MT_CCS)) { i=SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_DTLS1_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 (!ssl3_do_change_cipher_spec(s)) goto err; /* do this whenever CCS is processed */ dtls1_reset_seq_numbers(s, SSL3_CC_READ); /* handshake read seq is reset upon handshake completion */ s->d1->handshake_read_seq++; goto start; } else { rr->length = 0; goto start; } } /* Unexpected handshake message (Client Hello, or protocol violation) */ if ((s->d1->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) && !s->in_handshake) { struct hm_header_st msg_hdr; /* this may just be a stale retransmit */ dtls1_get_message_header(rr->data, &msg_hdr); if( rr->epoch != s->d1->r_epoch) { rr->length = 0; goto start; } 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_DTLS1_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_DTLS1_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_DTLS1_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_DTLS1_READ_BYTES,SSL_R_UNEXPECTED_RECORD); goto f_err; } } /* not reached */f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al);err: return(-1); }intdtls1_write_app_data_bytes(SSL *s, int type, const void *buf_, int len) { unsigned int n,tot; int i; if (SSL_in_init(s) && !s->in_handshake) { i=s->handshake_func(s); if (i < 0) return(i); if (i == 0) { SSLerr(SSL_F_DTLS1_WRITE_APP_DATA_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE); return -1; } } tot = s->s3->wnum; n = len - tot; while( n) { /* dtls1_write_bytes sends one record at a time, sized according to * the currently known MTU */ i = dtls1_write_bytes(s, type, buf_, len); if (i <= 0) return i; if ((i == (int)n) || (type == SSL3_RT_APPLICATION_DATA && (s->mode & SSL_MODE_ENABLE_PARTIAL_WRITE))) { /* next chunk of data should get another prepended empty fragment * in ciphersuites with known-IV weakness: */ s->s3->empty_fragment_done = 0; return tot+i; } tot += i; n-=i; } return tot; } /* this only happens when a client hello is received and a handshake * is started. */static inthave_handshake_fragment(SSL *s, int type, unsigned char *buf, int len, int peek) { if ((type == SSL3_RT_HANDSHAKE) && (s->d1->handshake_fragment_len > 0)) /* (partially) satisfy request from storage */ { unsigned char *src = s->d1->handshake_fragment; unsigned char *dst = buf; unsigned int k,n; /* peek == 0 */ n = 0; while ((len > 0) && (s->d1->handshake_fragment_len > 0)) { *dst++ = *src++; len--; s->d1->handshake_fragment_len--; n++; } /* move any remaining fragment bytes: */ for (k = 0; k < s->d1->handshake_fragment_len; k++) s->d1->handshake_fragment[k] = *src++; return n; } return 0; }/* Call this to write data in records of type 'type' * It will return <= 0 if not all data has been sent or non-blocking IO. */int dtls1_write_bytes(SSL *s, int type, const void *buf_, int len) { const unsigned char *buf=buf_; unsigned int tot,n,nw; int i; unsigned int mtu; s->rwstate=SSL_NOTHING; tot=s->s3->wnum; n=(len-tot); /* handshake layer figures out MTU for itself, but data records * are also sent through this interface, so need to figure out MTU */#if 0 mtu = BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_GET_MTU, 0, NULL); mtu += DTLS1_HM_HEADER_LENGTH; /* HM already inserted */#endif mtu = s->d1->mtu; if (mtu > SSL3_RT_MAX_PLAIN_LENGTH) mtu = SSL3_RT_MAX_PLAIN_LENGTH; if (n > mtu) nw=mtu; else nw=n; i=do_dtls1_write(s, type, &(buf[tot]), nw, 0); if (i <= 0) { s->s3->wnum=tot; return i; } if ( (int)s->s3->wnum + i == len) s->s3->wnum = 0; else s->s3->wnum += i; return tot + i; }int do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len, int create_empty_fragment) { unsigned char *p,*pseq; int i,mac_size,clear=0; int prefix_len = 0; SSL3_RECORD *wr; SSL3_BUFFER *wb; SSL_SESSION *sess; int bs; /* first check if there is a SSL3_BUFFER still being written * out. This will happen with non blocking IO */ if (s->s3->wbuf.left != 0) { OPENSSL_assert(0); /* XDTLS: want to see if we ever get here */ return(ssl3_write_pending(s,type,buf,len)); } /* If we have an alert to send, lets send it */ if (s->s3->alert_dispatch) { i=s->method->ssl_dispatch_alert(s); if (i <= 0) return(i); /* if it went, fall through and send more stuff */ } if (len == 0 && !create_empty_fragment) return 0; wr= &(s->s3->wrec); wb= &(s->s3->wbuf); sess=s->session; if ( (sess == NULL) || (s->enc_write_ctx == NULL) || (s->write_hash == NULL)) clear=1; if (clear) mac_size=0; else mac_size=EVP_MD_size(s->write_hash); /* DTLS implements explicit IV, so no need for empty fragments */#if 0 /* 'create_empty_fragment' is true only when this function calls itself */ if (!clear && !create_empty_fragment && !s->s3->empty_fragment_done && SSL_version(s) != DTLS1_VERSION) { /* countermeasure against known-IV weakness in CBC ciphersuites * (see http://www.openssl.org/~bodo/tls-cbc.txt) */ if (s->s3->need_empty_fragments && type == SSL3_RT_APPLICATION_DATA) { /* recursive function call with 'create_empty_fragment' set; * this prepares and buffers the data for an empty fragment * (these 'prefix_len' bytes are sent out later * together with the actual payload) */ prefix_len = s->method->do_ssl_write(s, type, buf, 0, 1); if (prefix_len <= 0) goto err; if (s->s3->wbuf.len < (size_t)prefix_len + SSL3_RT_MAX_PACKET_SIZE) { /* insufficient space */ SSLerr(SSL_F_DO_DTLS1_WRITE, ERR_R_INTERNAL_ERROR); goto err; } } s->s3->empty_fragment_done = 1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -