📄 s3_pkt.c
字号:
{ 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 */ if (rr->length == 0) goto again; return(1);f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al);err: return(ret); }int ssl3_do_uncompress(SSL *ssl) {#ifndef OPENSSL_NO_COMP int i; SSL3_RECORD *rr; rr= &(ssl->s3->rrec); i=COMP_expand_block(ssl->expand,rr->comp, SSL3_RT_MAX_PLAIN_LENGTH,rr->data,(int)rr->length); if (i < 0) return(0); else rr->length=i; rr->data=rr->comp;#endif return(1); }int ssl3_do_compress(SSL *ssl) {#ifndef OPENSSL_NO_COMP int i; SSL3_RECORD *wr; wr= &(ssl->s3->wrec); i=COMP_compress_block(ssl->compress,wr->data, SSL3_RT_MAX_COMPRESSED_LENGTH, wr->input,(int)wr->length); if (i < 0) return(0); else wr->length=i; wr->input=wr->data;#endif return(1); }/* 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 ssl3_write_bytes(SSL *s, int type, const void *buf_, int len) { const unsigned char *buf=buf_; unsigned int tot,n,nw; int i; s->rwstate=SSL_NOTHING; tot=s->s3->wnum; s->s3->wnum=0; if (SSL_in_init(s) && !s->in_handshake) { i=s->handshake_func(s); if (i < 0) return(i); if (i == 0) { SSLerr(SSL_F_SSL3_WRITE_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE); return -1; } } n=(len-tot); for (;;) { if (n > SSL3_RT_MAX_PLAIN_LENGTH) nw=SSL3_RT_MAX_PLAIN_LENGTH; else nw=n; i=do_ssl3_write(s, type, &(buf[tot]), nw, 0); if (i <= 0) { s->s3->wnum=tot; 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; } n-=i; tot+=i; } }static int do_ssl3_write(SSL *s, int type, const unsigned char *buf, unsigned int len, int create_empty_fragment) { unsigned char *p,*plen; int i,mac_size,clear=0; int prefix_len = 0; SSL3_RECORD *wr; SSL3_BUFFER *wb; SSL_SESSION *sess; /* 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) 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); /* 'create_empty_fragment' is true only when this function calls itself */ if (!clear && !create_empty_fragment && !s->s3->empty_fragment_done) { /* 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 = do_ssl3_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_SSL3_WRITE, ERR_R_INTERNAL_ERROR); goto err; } } s->s3->empty_fragment_done = 1; } p = wb->buf + prefix_len; /* write the header */ *(p++)=type&0xff; wr->type=type; *(p++)=(s->version>>8); *(p++)=s->version&0xff; /* field where we are to write out packet length */ plen=p; p+=2; /* lets setup the record stuff. */ wr->data=p; wr->length=(int)len; wr->input=(unsigned char *)buf; /* we now 'read' from wr->input, wr->length bytes into * wr->data */ /* first we compress */ if (s->compress != NULL) { if (!ssl3_do_compress(s)) { SSLerr(SSL_F_DO_SSL3_WRITE,SSL_R_COMPRESSION_FAILURE); goto err; } } else { memcpy(wr->data,wr->input,wr->length); wr->input=wr->data; } /* we should still have the output to wr->data and the input * from wr->input. Length should be wr->length. * wr->data still points in the wb->buf */ if (mac_size != 0) { s->method->ssl3_enc->mac(s,&(p[wr->length]),1); wr->length+=mac_size; wr->input=p; wr->data=p; } /* ssl3_enc can only have an error on read */ s->method->ssl3_enc->enc(s,1); /* record length after mac and block padding */ s2n(wr->length,plen); /* we should now have * wr->data pointing to the encrypted data, which is * wr->length long */ wr->type=type; /* not needed but helps for debugging */ wr->length+=SSL3_RT_HEADER_LENGTH; if (create_empty_fragment) { /* we are in a recursive call; * just return the length, don't write out anything here */ return wr->length; } /* now let's set up wb */ wb->left = prefix_len + wr->length; wb->offset = 0; /* memorize arguments so that ssl3_write_pending can detect bad write retries later */ s->s3->wpend_tot=len; s->s3->wpend_buf=buf; s->s3->wpend_type=type; s->s3->wpend_ret=len; /* we now just need to write the buffer */ return ssl3_write_pending(s,type,buf,len);err: return -1; }/* if s->s3->wbuf.left != 0, we need to call this */int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, unsigned int len) { int i;/* XXXX */ if ((s->s3->wpend_tot > (int)len) || ((s->s3->wpend_buf != buf) && !(s->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)) || (s->s3->wpend_type != type)) { SSLerr(SSL_F_SSL3_WRITE_PENDING,SSL_R_BAD_WRITE_RETRY); return(-1); } for (;;) { clear_sys_error(); if (s->wbio != NULL) { s->rwstate=SSL_WRITING; i=BIO_write(s->wbio, (char *)&(s->s3->wbuf.buf[s->s3->wbuf.offset]), (unsigned int)s->s3->wbuf.left); } else { SSLerr(SSL_F_SSL3_WRITE_PENDING,SSL_R_BIO_NOT_SET); i= -1; } if (i == s->s3->wbuf.left) { s->s3->wbuf.left=0; s->rwstate=SSL_NOTHING; return(s->s3->wpend_ret); } else if (i <= 0) return(i); s->s3->wbuf.offset+=i; s->s3->wbuf.left-=i; } }/* Return up to 'len' payload bytes received in 'type' records. * 'type' is one of the following: * * - SSL3_RT_HANDSHAKE (when ssl3_get_message calls us) * - SSL3_RT_APPLICATION_DATA (when ssl3_read calls us) * - 0 (during a shutdown, no data has to be returned) * * If we don't have stored data to work from, read a SSL/TLS record first * (possibly multiple records if we still don't have anything to return). * * This function must handle any surprises the peer may have for us, such as * Alert records (e.g. close_notify), ChangeCipherSpec records (not really * a surprise, but handled as if it were), or renegotiation requests. * Also if record payloads contain fragments too small to process, we store * them until there is enough for the respective protocol (the record protocol * may use arbitrary fragmentation and even interleaving): * Change cipher spec protocol * just 1 byte needed, no need for keeping anything stored * Alert protocol * 2 bytes needed (AlertLevel, AlertDescription) * Handshake protocol * 4 bytes needed (HandshakeType, uint24 length) -- we just have * to detect unexpected Client Hello and Hello Request messages * here, anything else is handled by higher layers * Application data protocol * none of our business */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); 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)) { /* 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: 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)) { 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 f_err; } /* If the other end has shut down, throw anything we read away * (even in 'peek' mode) */ if (s->shutdown & SSL_RECEIVED_SHUTDOWN) { rr->length=0; s->rwstate=SSL_NOTHING;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -