aboutsummaryrefslogtreecommitdiffstats
path: root/ssl/s2_pkt.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssl/s2_pkt.c')
-rw-r--r--ssl/s2_pkt.c1183
1 files changed, 573 insertions, 610 deletions
diff --git a/ssl/s2_pkt.c b/ssl/s2_pkt.c
index acd61dc546af..614b9a35d2ea 100644
--- a/ssl/s2_pkt.c
+++ b/ssl/s2_pkt.c
@@ -5,21 +5,21 @@
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
- *
+ *
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
+ *
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -34,10 +34,10 @@
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
+ * 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
+ *
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -49,7 +49,7 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
+ *
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
@@ -63,7 +63,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
@@ -111,638 +111,601 @@
#include "ssl_locl.h"
#ifndef OPENSSL_NO_SSL2
-#include <stdio.h>
-#include <errno.h>
-#define USE_SOCKETS
+# include <stdio.h>
+# include <errno.h>
+# define USE_SOCKETS
-static int read_n(SSL *s,unsigned int n,unsigned int max,unsigned int extend);
+static int read_n(SSL *s, unsigned int n, unsigned int max,
+ unsigned int extend);
static int n_do_ssl_write(SSL *s, const unsigned char *buf, unsigned int len);
static int write_pending(SSL *s, const unsigned char *buf, unsigned int len);
static int ssl_mt_error(int n);
-
-/* SSL 2.0 imlementation for SSL_read/SSL_peek -
- * This routine will return 0 to len bytes, decrypted etc if required.
+/*
+ * SSL 2.0 imlementation for SSL_read/SSL_peek - This routine will return 0
+ * to len bytes, decrypted etc if required.
*/
static int ssl2_read_internal(SSL *s, void *buf, int len, int peek)
- {
- int n;
- unsigned char mac[MAX_MAC_SIZE];
- unsigned char *p;
- int i;
- int mac_size;
+{
+ int n;
+ unsigned char mac[MAX_MAC_SIZE];
+ unsigned char *p;
+ int i;
+ int mac_size;
ssl2_read_again:
- if (SSL_in_init(s) && !s->in_handshake)
- {
- n=s->handshake_func(s);
- if (n < 0) return(n);
- if (n == 0)
- {
- SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_SSL_HANDSHAKE_FAILURE);
- return(-1);
- }
- }
-
- clear_sys_error();
- s->rwstate=SSL_NOTHING;
- if (len <= 0) return(len);
-
- if (s->s2->ract_data_length != 0) /* read from buffer */
- {
- if (len > s->s2->ract_data_length)
- n=s->s2->ract_data_length;
- else
- n=len;
-
- memcpy(buf,s->s2->ract_data,(unsigned int)n);
- if (!peek)
- {
- s->s2->ract_data_length-=n;
- s->s2->ract_data+=n;
- if (s->s2->ract_data_length == 0)
- s->rstate=SSL_ST_READ_HEADER;
- }
-
- return(n);
- }
-
- /* s->s2->ract_data_length == 0
- *
- * Fill the buffer, then goto ssl2_read_again.
- */
-
- if (s->rstate == SSL_ST_READ_HEADER)
- {
- if (s->first_packet)
- {
- n=read_n(s,5,SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2,0);
- if (n <= 0) return(n); /* error or non-blocking */
- s->first_packet=0;
- p=s->packet;
- if (!((p[0] & 0x80) && (
- (p[2] == SSL2_MT_CLIENT_HELLO) ||
- (p[2] == SSL2_MT_SERVER_HELLO))))
- {
- SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_NON_SSLV2_INITIAL_PACKET);
- return(-1);
- }
- }
- else
- {
- n=read_n(s,2,SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2,0);
- if (n <= 0) return(n); /* error or non-blocking */
- }
- /* part read stuff */
-
- s->rstate=SSL_ST_READ_BODY;
- p=s->packet;
- /* Do header */
- /*s->s2->padding=0;*/
- s->s2->escape=0;
- s->s2->rlength=(((unsigned int)p[0])<<8)|((unsigned int)p[1]);
- if ((p[0] & TWO_BYTE_BIT)) /* Two byte header? */
- {
- s->s2->three_byte_header=0;
- s->s2->rlength&=TWO_BYTE_MASK;
- }
- else
- {
- s->s2->three_byte_header=1;
- s->s2->rlength&=THREE_BYTE_MASK;
-
- /* security >s2->escape */
- s->s2->escape=((p[0] & SEC_ESC_BIT))?1:0;
- }
- }
-
- if (s->rstate == SSL_ST_READ_BODY)
- {
- n=s->s2->rlength+2+s->s2->three_byte_header;
- if (n > (int)s->packet_length)
- {
- n-=s->packet_length;
- i=read_n(s,(unsigned int)n,(unsigned int)n,1);
- if (i <= 0) return(i); /* ERROR */
- }
-
- p= &(s->packet[2]);
- s->rstate=SSL_ST_READ_HEADER;
- if (s->s2->three_byte_header)
- s->s2->padding= *(p++);
- else s->s2->padding=0;
-
- /* Data portion */
- if (s->s2->clear_text)
- {
- mac_size = 0;
- s->s2->mac_data=p;
- s->s2->ract_data=p;
- if (s->s2->padding)
- {
- SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_ILLEGAL_PADDING);
- return(-1);
- }
- }
- else
- {
- mac_size=EVP_MD_CTX_size(s->read_hash);
- if (mac_size < 0)
- return -1;
- OPENSSL_assert(mac_size <= MAX_MAC_SIZE);
- s->s2->mac_data=p;
- s->s2->ract_data= &p[mac_size];
- if (s->s2->padding + mac_size > s->s2->rlength)
- {
- SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_ILLEGAL_PADDING);
- return(-1);
- }
- }
-
- s->s2->ract_data_length=s->s2->rlength;
- /* added a check for length > max_size in case
- * encryption was not turned on yet due to an error */
- if ((!s->s2->clear_text) &&
- (s->s2->rlength >= (unsigned int)mac_size))
- {
- if(!ssl2_enc(s,0))
- {
- SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_DECRYPTION_FAILED);
- return(-1);
- }
- s->s2->ract_data_length-=mac_size;
- ssl2_mac(s,mac,0);
- s->s2->ract_data_length-=s->s2->padding;
- if ( (CRYPTO_memcmp(mac,s->s2->mac_data,mac_size) != 0) ||
- (s->s2->rlength%EVP_CIPHER_CTX_block_size(s->enc_read_ctx) != 0))
- {
- SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_BAD_MAC_DECODE);
- return(-1);
- }
- }
- INC32(s->s2->read_sequence); /* expect next number */
- /* s->s2->ract_data is now available for processing */
-
- /* Possibly the packet that we just read had 0 actual data bytes.
- * (SSLeay/OpenSSL itself never sends such packets; see ssl2_write.)
- * In this case, returning 0 would be interpreted by the caller
- * as indicating EOF, so it's not a good idea. Instead, we just
- * continue reading; thus ssl2_read_internal may have to process
- * multiple packets before it can return.
- *
- * [Note that using select() for blocking sockets *never* guarantees
- * that the next SSL_read will not block -- the available
- * data may contain incomplete packets, and except for SSL 2,
- * renegotiation can confuse things even more.] */
-
- goto ssl2_read_again; /* This should really be
- * "return ssl2_read(s,buf,len)",
- * but that would allow for
- * denial-of-service attacks if a
- * C compiler is used that does not
- * recognize end-recursion. */
- }
- else
- {
- SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_BAD_STATE);
- return(-1);
- }
- }
+ if (SSL_in_init(s) && !s->in_handshake) {
+ n = s->handshake_func(s);
+ if (n < 0)
+ return (n);
+ if (n == 0) {
+ SSLerr(SSL_F_SSL2_READ_INTERNAL, SSL_R_SSL_HANDSHAKE_FAILURE);
+ return (-1);
+ }
+ }
+
+ clear_sys_error();
+ s->rwstate = SSL_NOTHING;
+ if (len <= 0)
+ return (len);
+
+ if (s->s2->ract_data_length != 0) { /* read from buffer */
+ if (len > s->s2->ract_data_length)
+ n = s->s2->ract_data_length;
+ else
+ n = len;
+
+ memcpy(buf, s->s2->ract_data, (unsigned int)n);
+ if (!peek) {
+ s->s2->ract_data_length -= n;
+ s->s2->ract_data += n;
+ if (s->s2->ract_data_length == 0)
+ s->rstate = SSL_ST_READ_HEADER;
+ }
+
+ return (n);
+ }
+
+ /*
+ * s->s2->ract_data_length == 0 Fill the buffer, then goto
+ * ssl2_read_again.
+ */
+
+ if (s->rstate == SSL_ST_READ_HEADER) {
+ if (s->first_packet) {
+ n = read_n(s, 5, SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER + 2, 0);
+ if (n <= 0)
+ return (n); /* error or non-blocking */
+ s->first_packet = 0;
+ p = s->packet;
+ if (!((p[0] & 0x80) && ((p[2] == SSL2_MT_CLIENT_HELLO) ||
+ (p[2] == SSL2_MT_SERVER_HELLO)))) {
+ SSLerr(SSL_F_SSL2_READ_INTERNAL,
+ SSL_R_NON_SSLV2_INITIAL_PACKET);
+ return (-1);
+ }
+ } else {
+ n = read_n(s, 2, SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER + 2, 0);
+ if (n <= 0)
+ return (n); /* error or non-blocking */
+ }
+ /* part read stuff */
+
+ s->rstate = SSL_ST_READ_BODY;
+ p = s->packet;
+ /* Do header */
+ /*
+ * s->s2->padding=0;
+ */
+ s->s2->escape = 0;
+ s->s2->rlength = (((unsigned int)p[0]) << 8) | ((unsigned int)p[1]);
+ if ((p[0] & TWO_BYTE_BIT)) { /* Two byte header? */
+ s->s2->three_byte_header = 0;
+ s->s2->rlength &= TWO_BYTE_MASK;
+ } else {
+ s->s2->three_byte_header = 1;
+ s->s2->rlength &= THREE_BYTE_MASK;
+
+ /* security >s2->escape */
+ s->s2->escape = ((p[0] & SEC_ESC_BIT)) ? 1 : 0;
+ }
+ }
+
+ if (s->rstate == SSL_ST_READ_BODY) {
+ n = s->s2->rlength + 2 + s->s2->three_byte_header;
+ if (n > (int)s->packet_length) {
+ n -= s->packet_length;
+ i = read_n(s, (unsigned int)n, (unsigned int)n, 1);
+ if (i <= 0)
+ return (i); /* ERROR */
+ }
+
+ p = &(s->packet[2]);
+ s->rstate = SSL_ST_READ_HEADER;
+ if (s->s2->three_byte_header)
+ s->s2->padding = *(p++);
+ else
+ s->s2->padding = 0;
+
+ /* Data portion */
+ if (s->s2->clear_text) {
+ mac_size = 0;
+ s->s2->mac_data = p;
+ s->s2->ract_data = p;
+ if (s->s2->padding) {
+ SSLerr(SSL_F_SSL2_READ_INTERNAL, SSL_R_ILLEGAL_PADDING);
+ return (-1);
+ }
+ } else {
+ mac_size = EVP_MD_CTX_size(s->read_hash);
+ if (mac_size < 0)
+ return -1;
+ OPENSSL_assert(mac_size <= MAX_MAC_SIZE);
+ s->s2->mac_data = p;
+ s->s2->ract_data = &p[mac_size];
+ if (s->s2->padding + mac_size > s->s2->rlength) {
+ SSLerr(SSL_F_SSL2_READ_INTERNAL, SSL_R_ILLEGAL_PADDING);
+ return (-1);
+ }
+ }
+
+ s->s2->ract_data_length = s->s2->rlength;
+ /*
+ * added a check for length > max_size in case encryption was not
+ * turned on yet due to an error
+ */
+ if ((!s->s2->clear_text) &&
+ (s->s2->rlength >= (unsigned int)mac_size)) {
+ if (!ssl2_enc(s, 0)) {
+ SSLerr(SSL_F_SSL2_READ_INTERNAL, SSL_R_DECRYPTION_FAILED);
+ return (-1);
+ }
+ s->s2->ract_data_length -= mac_size;
+ ssl2_mac(s, mac, 0);
+ s->s2->ract_data_length -= s->s2->padding;
+ if ((CRYPTO_memcmp(mac, s->s2->mac_data, mac_size) != 0) ||
+ (s->s2->rlength %
+ EVP_CIPHER_CTX_block_size(s->enc_read_ctx) != 0)) {
+ SSLerr(SSL_F_SSL2_READ_INTERNAL, SSL_R_BAD_MAC_DECODE);
+ return (-1);
+ }
+ }
+ INC32(s->s2->read_sequence); /* expect next number */
+ /* s->s2->ract_data is now available for processing */
+
+ /*
+ * Possibly the packet that we just read had 0 actual data bytes.
+ * (SSLeay/OpenSSL itself never sends such packets; see ssl2_write.)
+ * In this case, returning 0 would be interpreted by the caller as
+ * indicating EOF, so it's not a good idea. Instead, we just
+ * continue reading; thus ssl2_read_internal may have to process
+ * multiple packets before it can return. [Note that using select()
+ * for blocking sockets *never* guarantees that the next SSL_read
+ * will not block -- the available data may contain incomplete
+ * packets, and except for SSL 2, renegotiation can confuse things
+ * even more.]
+ */
+
+ goto ssl2_read_again; /* This should really be "return
+ * ssl2_read(s,buf,len)", but that would
+ * allow for denial-of-service attacks if a C
+ * compiler is used that does not recognize
+ * end-recursion. */
+ } else {
+ SSLerr(SSL_F_SSL2_READ_INTERNAL, SSL_R_BAD_STATE);
+ return (-1);
+ }
+}
int ssl2_read(SSL *s, void *buf, int len)
- {
- return ssl2_read_internal(s, buf, len, 0);
- }
+{
+ return ssl2_read_internal(s, buf, len, 0);
+}
int ssl2_peek(SSL *s, void *buf, int len)
- {
- return ssl2_read_internal(s, buf, len, 1);
- }
+{
+ return ssl2_read_internal(s, buf, len, 1);
+}
static int read_n(SSL *s, unsigned int n, unsigned int max,
- unsigned int extend)
- {
- int i,off,newb;
-
- /* if there is stuff still in the buffer from a previous read,
- * and there is more than we want, take some. */
- if (s->s2->rbuf_left >= (int)n)
- {
- if (extend)
- s->packet_length+=n;
- else
- {
- s->packet= &(s->s2->rbuf[s->s2->rbuf_offs]);
- s->packet_length=n;
- }
- s->s2->rbuf_left-=n;
- s->s2->rbuf_offs+=n;
- return(n);
- }
-
- if (!s->read_ahead) max=n;
- if (max > (unsigned int)(SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2))
- max=SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2;
-
-
- /* Else we want more than we have.
- * First, if there is some left or we want to extend */
- off=0;
- if ((s->s2->rbuf_left != 0) || ((s->packet_length != 0) && extend))
- {
- newb=s->s2->rbuf_left;
- if (extend)
- {
- off=s->packet_length;
- if (s->packet != s->s2->rbuf)
- memcpy(s->s2->rbuf,s->packet,
- (unsigned int)newb+off);
- }
- else if (s->s2->rbuf_offs != 0)
- {
- memcpy(s->s2->rbuf,&(s->s2->rbuf[s->s2->rbuf_offs]),
- (unsigned int)newb);
- s->s2->rbuf_offs=0;
- }
- s->s2->rbuf_left=0;
- }
- else
- newb=0;
-
- /* off is the offset to start writing too.
- * r->s2->rbuf_offs is the 'unread data', now 0.
- * newb is the number of new bytes so far
- */
- s->packet=s->s2->rbuf;
- while (newb < (int)n)
- {
- clear_sys_error();
- if (s->rbio != NULL)
- {
- s->rwstate=SSL_READING;
- i=BIO_read(s->rbio,(char *)&(s->s2->rbuf[off+newb]),
- max-newb);
- }
- else
- {
- SSLerr(SSL_F_READ_N,SSL_R_READ_BIO_NOT_SET);
- i= -1;
- }
-#ifdef PKT_DEBUG
- if (s->debug & 0x01) sleep(1);
-#endif
- if (i <= 0)
- {
- s->s2->rbuf_left+=newb;
- return(i);
- }
- newb+=i;
- }
-
- /* record unread data */
- if (newb > (int)n)
- {
- s->s2->rbuf_offs=n+off;
- s->s2->rbuf_left=newb-n;
- }
- else
- {
- s->s2->rbuf_offs=0;
- s->s2->rbuf_left=0;
- }
- if (extend)
- s->packet_length+=n;
- else
- s->packet_length=n;
- s->rwstate=SSL_NOTHING;
- return(n);
- }
+ unsigned int extend)
+{
+ int i, off, newb;
+
+ /*
+ * if there is stuff still in the buffer from a previous read, and there
+ * is more than we want, take some.
+ */
+ if (s->s2->rbuf_left >= (int)n) {
+ if (extend)
+ s->packet_length += n;
+ else {
+ s->packet = &(s->s2->rbuf[s->s2->rbuf_offs]);
+ s->packet_length = n;
+ }
+ s->s2->rbuf_left -= n;
+ s->s2->rbuf_offs += n;
+ return (n);
+ }
+
+ if (!s->read_ahead)
+ max = n;
+ if (max > (unsigned int)(SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER + 2))
+ max = SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER + 2;
+
+ /*
+ * Else we want more than we have. First, if there is some left or we
+ * want to extend
+ */
+ off = 0;
+ if ((s->s2->rbuf_left != 0) || ((s->packet_length != 0) && extend)) {
+ newb = s->s2->rbuf_left;
+ if (extend) {
+ off = s->packet_length;
+ if (s->packet != s->s2->rbuf)
+ memcpy(s->s2->rbuf, s->packet, (unsigned int)newb + off);
+ } else if (s->s2->rbuf_offs != 0) {
+ memcpy(s->s2->rbuf, &(s->s2->rbuf[s->s2->rbuf_offs]),
+ (unsigned int)newb);
+ s->s2->rbuf_offs = 0;
+ }
+ s->s2->rbuf_left = 0;
+ } else
+ newb = 0;
+
+ /*
+ * off is the offset to start writing too. r->s2->rbuf_offs is the
+ * 'unread data', now 0. newb is the number of new bytes so far
+ */
+ s->packet = s->s2->rbuf;
+ while (newb < (int)n) {
+ clear_sys_error();
+ if (s->rbio != NULL) {
+ s->rwstate = SSL_READING;
+ i = BIO_read(s->rbio, (char *)&(s->s2->rbuf[off + newb]),
+ max - newb);
+ } else {
+ SSLerr(SSL_F_READ_N, SSL_R_READ_BIO_NOT_SET);
+ i = -1;
+ }
+# ifdef PKT_DEBUG
+ if (s->debug & 0x01)
+ sleep(1);
+# endif
+ if (i <= 0) {
+ s->s2->rbuf_left += newb;
+ return (i);
+ }
+ newb += i;
+ }
+
+ /* record unread data */
+ if (newb > (int)n) {
+ s->s2->rbuf_offs = n + off;
+ s->s2->rbuf_left = newb - n;
+ } else {
+ s->s2->rbuf_offs = 0;
+ s->s2->rbuf_left = 0;
+ }
+ if (extend)
+ s->packet_length += n;
+ else
+ s->packet_length = n;
+ s->rwstate = SSL_NOTHING;
+ return (n);
+}
int ssl2_write(SSL *s, const void *_buf, int len)
- {
- const unsigned char *buf=_buf;
- 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_SSL2_WRITE,SSL_R_SSL_HANDSHAKE_FAILURE);
- return(-1);
- }
- }
-
- if (s->error)
- {
- ssl2_write_error(s);
- if (s->error)
- return(-1);
- }
-
- clear_sys_error();
- s->rwstate=SSL_NOTHING;
- if (len <= 0) return(len);
-
- tot=s->s2->wnum;
- s->s2->wnum=0;
-
- n=(len-tot);
- for (;;)
- {
- i=n_do_ssl_write(s,&(buf[tot]),n);
- if (i <= 0)
- {
- s->s2->wnum=tot;
- return(i);
- }
- if ((i == (int)n) ||
- (s->mode & SSL_MODE_ENABLE_PARTIAL_WRITE))
- {
- return(tot+i);
- }
-
- n-=i;
- tot+=i;
- }
- }
+{
+ const unsigned char *buf = _buf;
+ 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_SSL2_WRITE, SSL_R_SSL_HANDSHAKE_FAILURE);
+ return (-1);
+ }
+ }
+
+ if (s->error) {
+ ssl2_write_error(s);
+ if (s->error)
+ return (-1);
+ }
+
+ clear_sys_error();
+ s->rwstate = SSL_NOTHING;
+ if (len <= 0)
+ return (len);
+
+ tot = s->s2->wnum;
+ s->s2->wnum = 0;
+
+ n = (len - tot);
+ for (;;) {
+ i = n_do_ssl_write(s, &(buf[tot]), n);
+ if (i <= 0) {
+ s->s2->wnum = tot;
+ return (i);
+ }
+ if ((i == (int)n) || (s->mode & SSL_MODE_ENABLE_PARTIAL_WRITE)) {
+ return (tot + i);
+ }
+
+ n -= i;
+ tot += i;
+ }
+}
static int write_pending(SSL *s, const unsigned char *buf, unsigned int len)
- {
- int i;
-
- /* s->s2->wpend_len != 0 MUST be true. */
-
- /* check that they have given us the same buffer to
- * write */
- if ((s->s2->wpend_tot > (int)len) ||
- ((s->s2->wpend_buf != buf) &&
- !(s->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)))
- {
- SSLerr(SSL_F_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->s2->write_ptr[s->s2->wpend_off]),
- (unsigned int)s->s2->wpend_len);
- }
- else
- {
- SSLerr(SSL_F_WRITE_PENDING,SSL_R_WRITE_BIO_NOT_SET);
- i= -1;
- }
-#ifdef PKT_DEBUG
- if (s->debug & 0x01) sleep(1);
-#endif
- if (i == s->s2->wpend_len)
- {
- s->s2->wpend_len=0;
- s->rwstate=SSL_NOTHING;
- return(s->s2->wpend_ret);
- }
- else if (i <= 0)
- return(i);
- s->s2->wpend_off+=i;
- s->s2->wpend_len-=i;
- }
- }
+{
+ int i;
+
+ /* s->s2->wpend_len != 0 MUST be true. */
+
+ /*
+ * check that they have given us the same buffer to write
+ */
+ if ((s->s2->wpend_tot > (int)len) ||
+ ((s->s2->wpend_buf != buf) &&
+ !(s->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER))) {
+ SSLerr(SSL_F_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->s2->write_ptr[s->s2->wpend_off]),
+ (unsigned int)s->s2->wpend_len);
+ } else {
+ SSLerr(SSL_F_WRITE_PENDING, SSL_R_WRITE_BIO_NOT_SET);
+ i = -1;
+ }
+# ifdef PKT_DEBUG
+ if (s->debug & 0x01)
+ sleep(1);
+# endif
+ if (i == s->s2->wpend_len) {
+ s->s2->wpend_len = 0;
+ s->rwstate = SSL_NOTHING;
+ return (s->s2->wpend_ret);
+ } else if (i <= 0)
+ return (i);
+ s->s2->wpend_off += i;
+ s->s2->wpend_len -= i;
+ }
+}
static int n_do_ssl_write(SSL *s, const unsigned char *buf, unsigned int len)
- {
- unsigned int j,k,olen,p,bs;
- int mac_size;
- register unsigned char *pp;
-
- olen=len;
-
- /* first check if there is data from an encryption waiting to
- * be sent - it must be sent because the other end is waiting.
- * This will happen with non-blocking IO. We print it and then
- * return.
- */
- if (s->s2->wpend_len != 0) return(write_pending(s,buf,len));
-
- /* set mac_size to mac size */
- if (s->s2->clear_text)
- mac_size=0;
- else
- {
- mac_size=EVP_MD_CTX_size(s->write_hash);
- if (mac_size < 0)
- return -1;
- }
-
- /* lets set the pad p */
- if (s->s2->clear_text)
- {
- if (len > SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER)
- len=SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER;
- p=0;
- s->s2->three_byte_header=0;
- /* len=len; */
- }
- else
- {
- bs=EVP_CIPHER_CTX_block_size(s->enc_read_ctx);
- j=len+mac_size;
- /* Two-byte headers allow for a larger record length than
- * three-byte headers, but we can't use them if we need
- * padding or if we have to set the escape bit. */
- if ((j > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER) &&
- (!s->s2->escape))
- {
- if (j > SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER)
- j=SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER;
- /* set k to the max number of bytes with 2
- * byte header */
- k=j-(j%bs);
- /* how many data bytes? */
- len=k-mac_size;
- s->s2->three_byte_header=0;
- p=0;
- }
- else if ((bs <= 1) && (!s->s2->escape))
- {
- /* j <= SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER, thus
- * j < SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER */
- s->s2->three_byte_header=0;
- p=0;
- }
- else /* we may have to use a 3 byte header */
- {
- /* If s->s2->escape is not set, then
- * j <= SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER, and thus
- * j < SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER. */
- p=(j%bs);
- p=(p == 0)?0:(bs-p);
- if (s->s2->escape)
- {
- s->s2->three_byte_header=1;
- if (j > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)
- j=SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER;
- }
- else
- s->s2->three_byte_header=(p == 0)?0:1;
- }
- }
-
- /* Now
- * j <= SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER
- * holds, and if s->s2->three_byte_header is set, then even
- * j <= SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER.
- */
-
- /* mac_size is the number of MAC bytes
- * len is the number of data bytes we are going to send
- * p is the number of padding bytes
- * (if it is a two-byte header, then p == 0) */
-
- s->s2->wlength=len;
- s->s2->padding=p;
- s->s2->mac_data= &(s->s2->wbuf[3]);
- s->s2->wact_data= &(s->s2->wbuf[3+mac_size]);
- /* we copy the data into s->s2->wbuf */
- memcpy(s->s2->wact_data,buf,len);
- if (p)
- memset(&(s->s2->wact_data[len]),0,p); /* arbitrary padding */
-
- if (!s->s2->clear_text)
- {
- s->s2->wact_data_length=len+p;
- ssl2_mac(s,s->s2->mac_data,1);
- s->s2->wlength+=p+mac_size;
- if(ssl2_enc(s,1) < 1)
- return -1;
- }
-
- /* package up the header */
- s->s2->wpend_len=s->s2->wlength;
- if (s->s2->three_byte_header) /* 3 byte header */
- {
- pp=s->s2->mac_data;
- pp-=3;
- pp[0]=(s->s2->wlength>>8)&(THREE_BYTE_MASK>>8);
- if (s->s2->escape) pp[0]|=SEC_ESC_BIT;
- pp[1]=s->s2->wlength&0xff;
- pp[2]=s->s2->padding;
- s->s2->wpend_len+=3;
- }
- else
- {
- pp=s->s2->mac_data;
- pp-=2;
- pp[0]=((s->s2->wlength>>8)&(TWO_BYTE_MASK>>8))|TWO_BYTE_BIT;
- pp[1]=s->s2->wlength&0xff;
- s->s2->wpend_len+=2;
- }
- s->s2->write_ptr=pp;
-
- INC32(s->s2->write_sequence); /* expect next number */
-
- /* lets try to actually write the data */
- s->s2->wpend_tot=olen;
- s->s2->wpend_buf=buf;
-
- s->s2->wpend_ret=len;
-
- s->s2->wpend_off=0;
- return(write_pending(s,buf,olen));
- }
+{
+ unsigned int j, k, olen, p, bs;
+ int mac_size;
+ register unsigned char *pp;
+
+ olen = len;
+
+ /*
+ * first check if there is data from an encryption waiting to be sent -
+ * it must be sent because the other end is waiting. This will happen
+ * with non-blocking IO. We print it and then return.
+ */
+ if (s->s2->wpend_len != 0)
+ return (write_pending(s, buf, len));
+
+ /* set mac_size to mac size */
+ if (s->s2->clear_text)
+ mac_size = 0;
+ else {
+ mac_size = EVP_MD_CTX_size(s->write_hash);
+ if (mac_size < 0)
+ return -1;
+ }
+
+ /* lets set the pad p */
+ if (s->s2->clear_text) {
+ if (len > SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER)
+ len = SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER;
+ p = 0;
+ s->s2->three_byte_header = 0;
+ /* len=len; */
+ } else {
+ bs = EVP_CIPHER_CTX_block_size(s->enc_read_ctx);
+ j = len + mac_size;
+ /*
+ * Two-byte headers allow for a larger record length than three-byte
+ * headers, but we can't use them if we need padding or if we have to
+ * set the escape bit.
+ */
+ if ((j > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER) && (!s->s2->escape)) {
+ if (j > SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER)
+ j = SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER;
+ /*
+ * set k to the max number of bytes with 2 byte header
+ */
+ k = j - (j % bs);
+ /* how many data bytes? */
+ len = k - mac_size;
+ s->s2->three_byte_header = 0;
+ p = 0;
+ } else if ((bs <= 1) && (!s->s2->escape)) {
+ /*-
+ * j <= SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER, thus
+ * j < SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER
+ */
+ s->s2->three_byte_header = 0;
+ p = 0;
+ } else { /* we may have to use a 3 byte header */
+
+ /*-
+ * If s->s2->escape is not set, then
+ * j <= SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER, and thus
+ * j < SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER.
+ */
+ p = (j % bs);
+ p = (p == 0) ? 0 : (bs - p);
+ if (s->s2->escape) {
+ s->s2->three_byte_header = 1;
+ if (j > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)
+ j = SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER;
+ } else
+ s->s2->three_byte_header = (p == 0) ? 0 : 1;
+ }
+ }
+
+ /*-
+ * Now
+ * j <= SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER
+ * holds, and if s->s2->three_byte_header is set, then even
+ * j <= SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER.
+ */
+
+ /*
+ * mac_size is the number of MAC bytes len is the number of data bytes we
+ * are going to send p is the number of padding bytes (if it is a
+ * two-byte header, then p == 0)
+ */
+
+ s->s2->wlength = len;
+ s->s2->padding = p;
+ s->s2->mac_data = &(s->s2->wbuf[3]);
+ s->s2->wact_data = &(s->s2->wbuf[3 + mac_size]);
+ /* we copy the data into s->s2->wbuf */
+ memcpy(s->s2->wact_data, buf, len);
+ if (p)
+ memset(&(s->s2->wact_data[len]), 0, p); /* arbitrary padding */
+
+ if (!s->s2->clear_text) {
+ s->s2->wact_data_length = len + p;
+ ssl2_mac(s, s->s2->mac_data, 1);
+ s->s2->wlength += p + mac_size;
+ if (ssl2_enc(s, 1) < 1)
+ return -1;
+ }
+
+ /* package up the header */
+ s->s2->wpend_len = s->s2->wlength;
+ if (s->s2->three_byte_header) { /* 3 byte header */
+ pp = s->s2->mac_data;
+ pp -= 3;
+ pp[0] = (s->s2->wlength >> 8) & (THREE_BYTE_MASK >> 8);
+ if (s->s2->escape)
+ pp[0] |= SEC_ESC_BIT;
+ pp[1] = s->s2->wlength & 0xff;
+ pp[2] = s->s2->padding;
+ s->s2->wpend_len += 3;
+ } else {
+ pp = s->s2->mac_data;
+ pp -= 2;
+ pp[0] = ((s->s2->wlength >> 8) & (TWO_BYTE_MASK >> 8)) | TWO_BYTE_BIT;
+ pp[1] = s->s2->wlength & 0xff;
+ s->s2->wpend_len += 2;
+ }
+ s->s2->write_ptr = pp;
+
+ INC32(s->s2->write_sequence); /* expect next number */
+
+ /* lets try to actually write the data */
+ s->s2->wpend_tot = olen;
+ s->s2->wpend_buf = buf;
+
+ s->s2->wpend_ret = len;
+
+ s->s2->wpend_off = 0;
+ return (write_pending(s, buf, olen));
+}
int ssl2_part_read(SSL *s, unsigned long f, int i)
- {
- unsigned char *p;
- int j;
-
- if (i < 0)
- {
- /* ssl2_return_error(s); */
- /* for non-blocking io,
- * this is not necessarily fatal */
- return(i);
- }
- else
- {
- s->init_num+=i;
-
- /* Check for error. While there are recoverable errors,
- * this function is not called when those must be expected;
- * any error detected here is fatal. */
- if (s->init_num >= 3)
- {
- p=(unsigned char *)s->init_buf->data;
- if (p[0] == SSL2_MT_ERROR)
- {
- j=(p[1]<<8)|p[2];
- SSLerr((int)f,ssl_mt_error(j));
- s->init_num -= 3;
- if (s->init_num > 0)
- memmove(p, p+3, s->init_num);
- }
- }
-
- /* If it's not an error message, we have some error anyway --
- * the message was shorter than expected. This too is treated
- * as fatal (at least if SSL_get_error is asked for its opinion). */
- return(0);
- }
- }
+{
+ unsigned char *p;
+ int j;
+
+ if (i < 0) {
+ /* ssl2_return_error(s); */
+ /*
+ * for non-blocking io, this is not necessarily fatal
+ */
+ return (i);
+ } else {
+ s->init_num += i;
+
+ /*
+ * Check for error. While there are recoverable errors, this
+ * function is not called when those must be expected; any error
+ * detected here is fatal.
+ */
+ if (s->init_num >= 3) {
+ p = (unsigned char *)s->init_buf->data;
+ if (p[0] == SSL2_MT_ERROR) {
+ j = (p[1] << 8) | p[2];
+ SSLerr((int)f, ssl_mt_error(j));
+ s->init_num -= 3;
+ if (s->init_num > 0)
+ memmove(p, p + 3, s->init_num);
+ }
+ }
+
+ /*
+ * If it's not an error message, we have some error anyway -- the
+ * message was shorter than expected. This too is treated as fatal
+ * (at least if SSL_get_error is asked for its opinion).
+ */
+ return (0);
+ }
+}
int ssl2_do_write(SSL *s)
- {
- int ret;
-
- ret=ssl2_write(s,&s->init_buf->data[s->init_off],s->init_num);
- if (ret == s->init_num)
- {
- if (s->msg_callback)
- s->msg_callback(1, s->version, 0, s->init_buf->data, (size_t)(s->init_off + s->init_num), s, s->msg_callback_arg);
- return(1);
- }
- if (ret < 0)
- return(-1);
- s->init_off+=ret;
- s->init_num-=ret;
- return(0);
- }
+{
+ int ret;
+
+ ret = ssl2_write(s, &s->init_buf->data[s->init_off], s->init_num);
+ if (ret == s->init_num) {
+ if (s->msg_callback)
+ s->msg_callback(1, s->version, 0, s->init_buf->data,
+ (size_t)(s->init_off + s->init_num), s,
+ s->msg_callback_arg);
+ return (1);
+ }
+ if (ret < 0)
+ return (-1);
+ s->init_off += ret;
+ s->init_num -= ret;
+ return (0);
+}
static int ssl_mt_error(int n)
- {
- int ret;
-
- switch (n)
- {
- case SSL2_PE_NO_CIPHER:
- ret=SSL_R_PEER_ERROR_NO_CIPHER;
- break;
- case SSL2_PE_NO_CERTIFICATE:
- ret=SSL_R_PEER_ERROR_NO_CERTIFICATE;
- break;
- case SSL2_PE_BAD_CERTIFICATE:
- ret=SSL_R_PEER_ERROR_CERTIFICATE;
- break;
- case SSL2_PE_UNSUPPORTED_CERTIFICATE_TYPE:
- ret=SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE;
- break;
- default:
- ret=SSL_R_UNKNOWN_REMOTE_ERROR_TYPE;
- break;
- }
- return(ret);
- }
-#else /* !OPENSSL_NO_SSL2 */
+{
+ int ret;
+
+ switch (n) {
+ case SSL2_PE_NO_CIPHER:
+ ret = SSL_R_PEER_ERROR_NO_CIPHER;
+ break;
+ case SSL2_PE_NO_CERTIFICATE:
+ ret = SSL_R_PEER_ERROR_NO_CERTIFICATE;
+ break;
+ case SSL2_PE_BAD_CERTIFICATE:
+ ret = SSL_R_PEER_ERROR_CERTIFICATE;
+ break;
+ case SSL2_PE_UNSUPPORTED_CERTIFICATE_TYPE:
+ ret = SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE;
+ break;
+ default:
+ ret = SSL_R_UNKNOWN_REMOTE_ERROR_TYPE;
+ break;
+ }
+ return (ret);
+}
+#else /* !OPENSSL_NO_SSL2 */
# if PEDANTIC
-static void *dummy=&dummy;
+static void *dummy = &dummy;
# endif
#endif