summaryrefslogtreecommitdiff
path: root/thirdparty/openssl/ssl/s2_pkt.c
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/openssl/ssl/s2_pkt.c')
-rw-r--r--thirdparty/openssl/ssl/s2_pkt.c725
1 files changed, 725 insertions, 0 deletions
diff --git a/thirdparty/openssl/ssl/s2_pkt.c b/thirdparty/openssl/ssl/s2_pkt.c
new file mode 100644
index 0000000000..7a61888134
--- /dev/null
+++ b/thirdparty/openssl/ssl/s2_pkt.c
@@ -0,0 +1,725 @@
+/* ssl/s2_pkt.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * 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:
+ * 1. Redistributions of source code must retain the copyright
+ * 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 the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * 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
+ * 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
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * 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
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT 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.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "ssl_locl.h"
+#ifndef OPENSSL_NO_SSL2
+# 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 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.
+ */
+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;
+
+ 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);
+ }
+}
+
+int ssl2_read(SSL *s, void *buf, int len)
+{
+ 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);
+}
+
+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);
+}
+
+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;
+ }
+}
+
+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;
+ }
+}
+
+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]);
+
+ /*
+ * It would be clearer to write this as follows:
+ * if (mac_size + len + p > SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER)
+ * However |len| is user input that could in theory be very large. We
+ * know |mac_size| and |p| are small, so to avoid any possibility of
+ * overflow we write it like this.
+ *
+ * In theory this should never fail because the logic above should have
+ * modified |len| if it is too big. But we are being cautious.
+ */
+ if (len > (SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER - (mac_size + p))) {
+ return -1;
+ }
+ /* 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);
+ }
+}
+
+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);
+}
+
+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 */
+
+# if PEDANTIC
+static void *dummy = &dummy;
+# endif
+
+#endif