Locking issues.
[openssl.git] / ssl / s2_pkt.c
1 /* ssl/s2_pkt.c */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  * 
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  * 
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  * 
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from 
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  * 
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * 
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58 /* ====================================================================
59  * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
60  *
61  * Redistribution and use in source and binary forms, with or without
62  * modification, are permitted provided that the following conditions
63  * are met:
64  *
65  * 1. Redistributions of source code must retain the above copyright
66  *    notice, this list of conditions and the following disclaimer. 
67  *
68  * 2. Redistributions in binary form must reproduce the above copyright
69  *    notice, this list of conditions and the following disclaimer in
70  *    the documentation and/or other materials provided with the
71  *    distribution.
72  *
73  * 3. All advertising materials mentioning features or use of this
74  *    software must display the following acknowledgment:
75  *    "This product includes software developed by the OpenSSL Project
76  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
77  *
78  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
79  *    endorse or promote products derived from this software without
80  *    prior written permission. For written permission, please contact
81  *    openssl-core@openssl.org.
82  *
83  * 5. Products derived from this software may not be called "OpenSSL"
84  *    nor may "OpenSSL" appear in their names without prior written
85  *    permission of the OpenSSL Project.
86  *
87  * 6. Redistributions of any form whatsoever must retain the following
88  *    acknowledgment:
89  *    "This product includes software developed by the OpenSSL Project
90  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
91  *
92  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
93  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
95  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
96  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
97  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
98  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
99  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
101  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
102  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
103  * OF THE POSSIBILITY OF SUCH DAMAGE.
104  * ====================================================================
105  *
106  * This product includes cryptographic software written by Eric Young
107  * (eay@cryptsoft.com).  This product includes software written by Tim
108  * Hudson (tjh@cryptsoft.com).
109  *
110  */
111
112 #include "ssl_locl.h"
113 #ifndef NO_SSL2
114 #include <stdio.h>
115 #include <errno.h>
116 #define USE_SOCKETS
117
118 static int read_n(SSL *s,unsigned int n,unsigned int max,unsigned int extend);
119 static int do_ssl_write(SSL *s, const unsigned char *buf, unsigned int len);
120 static int write_pending(SSL *s, const unsigned char *buf, unsigned int len);
121 static int ssl_mt_error(int n);
122
123
124 /* SSL 2.0 imlementation for SSL_read/SSL_peek -
125  * This routine will return 0 to len bytes, decrypted etc if required.
126  */
127 static int ssl2_read_internal(SSL *s, void *buf, int len, int peek)
128         {
129         int n;
130         unsigned char mac[MAX_MAC_SIZE];
131         unsigned char *p;
132         int i;
133         unsigned int mac_size=0;
134
135         if (peek)
136                 {
137                 SSLerr(SSL_F_SSL2_READ_INTERNAL, SSL_R_FIXME); /* proper implementation not yet completed */
138                 return -1;
139                 }
140
141 ssl2_read_again:
142         if (SSL_in_init(s) && !s->in_handshake)
143                 {
144                 n=s->handshake_func(s);
145                 if (n < 0) return(n);
146                 if (n == 0)
147                         {
148                         SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_SSL_HANDSHAKE_FAILURE);
149                         return(-1);
150                         }
151                 }
152
153         clear_sys_error();
154         s->rwstate=SSL_NOTHING;
155         if (len <= 0) return(len);
156
157         if (s->s2->ract_data_length != 0) /* read from buffer */
158                 {
159                 if (len > s->s2->ract_data_length)
160                         n=s->s2->ract_data_length;
161                 else
162                         n=len;
163
164                 memcpy(buf,s->s2->ract_data,(unsigned int)n);
165                 s->s2->ract_data_length-=n;
166                 s->s2->ract_data+=n;
167                 if (s->s2->ract_data_length == 0)
168                         s->rstate=SSL_ST_READ_HEADER;
169                 return(n);
170                 }
171
172         if (s->rstate == SSL_ST_READ_HEADER)
173                 {
174                 if (s->first_packet)
175                         {
176                         n=read_n(s,5,SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2,0);
177                         if (n <= 0) return(n); /* error or non-blocking */
178                         s->first_packet=0;
179                         p=s->packet;
180                         if (!((p[0] & 0x80) && (
181                                 (p[2] == SSL2_MT_CLIENT_HELLO) ||
182                                 (p[2] == SSL2_MT_SERVER_HELLO))))
183                                 {
184                                 SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_NON_SSLV2_INITIAL_PACKET);
185                                 return(-1);
186                                 }
187                         }
188                 else
189                         {
190                         n=read_n(s,2,SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2,0);
191                         if (n <= 0) return(n); /* error or non-blocking */
192                         }
193                 /* part read stuff */
194
195                 s->rstate=SSL_ST_READ_BODY;
196                 p=s->packet;
197                 /* Do header */
198                 /*s->s2->padding=0;*/
199                 s->s2->escape=0;
200                 s->s2->rlength=(((unsigned int)p[0])<<8)|((unsigned int)p[1]);
201                 if ((p[0] & TWO_BYTE_BIT))              /* Two byte header? */
202                         {
203                         s->s2->three_byte_header=0;
204                         s->s2->rlength&=TWO_BYTE_MASK;  
205                         }
206                 else
207                         {
208                         s->s2->three_byte_header=1;
209                         s->s2->rlength&=THREE_BYTE_MASK;
210
211                         /* security >s2->escape */
212                         s->s2->escape=((p[0] & SEC_ESC_BIT))?1:0;
213                         }
214                 }
215
216         if (s->rstate == SSL_ST_READ_BODY)
217                 {
218                 n=s->s2->rlength+2+s->s2->three_byte_header;
219                 if (n > (int)s->packet_length)
220                         {
221                         n-=s->packet_length;
222                         i=read_n(s,(unsigned int)n,(unsigned int)n,1);
223                         if (i <= 0) return(i); /* ERROR */
224                         }
225
226                 p= &(s->packet[2]);
227                 s->rstate=SSL_ST_READ_HEADER;
228                 if (s->s2->three_byte_header)
229                         s->s2->padding= *(p++);
230                 else    s->s2->padding=0;
231
232                 /* Data portion */
233                 if (s->s2->clear_text)
234                         {
235                         s->s2->mac_data=p;
236                         s->s2->ract_data=p;
237                         s->s2->pad_data=NULL;
238                         }
239                 else
240                         {
241                         mac_size=EVP_MD_size(s->read_hash);
242                         s->s2->mac_data=p;
243                         s->s2->ract_data= &p[mac_size];
244                         s->s2->pad_data= &p[mac_size+
245                                 s->s2->rlength-s->s2->padding];
246                         }
247
248                 s->s2->ract_data_length=s->s2->rlength;
249                 /* added a check for length > max_size in case
250                  * encryption was not turned on yet due to an error */
251                 if ((!s->s2->clear_text) &&
252                         (s->s2->rlength >= mac_size))
253                         {
254                         ssl2_enc(s,0);
255                         s->s2->ract_data_length-=mac_size;
256                         ssl2_mac(s,mac,0);
257                         s->s2->ract_data_length-=s->s2->padding;
258                         if (    (memcmp(mac,s->s2->mac_data,
259                                 (unsigned int)mac_size) != 0) ||
260                                 (s->s2->rlength%EVP_CIPHER_CTX_block_size(s->enc_read_ctx) != 0))
261                                 {
262                                 SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_BAD_MAC_DECODE);
263                                 return(-1);
264                                 }
265                         }
266                 INC32(s->s2->read_sequence); /* expect next number */
267                 /* s->s2->ract_data is now available for processing */
268
269 #if 1
270                 /* How should we react when a packet containing 0
271                  * bytes is received?  (Note that SSLeay/OpenSSL itself
272                  * never sends such packets; see ssl2_write.)
273                  * Returning 0 would be interpreted by the caller as
274                  * indicating EOF, so it's not a good idea.
275                  * Instead, we just continue reading.  Note that using
276                  * select() for blocking sockets *never* guarantees
277                  * that the next SSL_read will not block -- the available
278                  * data may contain incomplete packets, and except for SSL 2
279                  * renegotiation can confuse things even more. */
280
281                 goto ssl2_read_again; /* This should really be
282                                        * "return ssl2_read(s,buf,len)",
283                                        * but that would allow for
284                                        * denial-of-service attacks if a
285                                        * C compiler is used that does not
286                                        * recognize end-recursion. */
287 #else
288                 /* If a 0 byte packet was sent, return 0, otherwise
289                  * we play havoc with people using select with
290                  * blocking sockets.  Let them handle a packet at a time,
291                  * they should really be using non-blocking sockets. */
292                 if (s->s2->ract_data_length == 0)
293                         return(0);
294                 return(ssl2_read(s,buf,len));
295 #endif
296                 }
297         else
298                 {
299                 SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_BAD_STATE);
300                         return(-1);
301                 }
302         }
303
304 int ssl2_read(SSL *s, void *buf, int len)
305         {
306         return ssl2_read_internal(s, buf, len, 0);
307         }
308
309 int ssl2_peek(SSL *s, char *buf, int len)
310         {
311         return ssl2_read_internal(s, buf, len, 1);
312         }
313
314 static int read_n(SSL *s, unsigned int n, unsigned int max,
315              unsigned int extend)
316         {
317         int i,off,newb;
318
319         /* if there is stuff still in the buffer from a previous read,
320          * and there is more than we want, take some. */
321         if (s->s2->rbuf_left >= (int)n)
322                 {
323                 if (extend)
324                         s->packet_length+=n;
325                 else
326                         {
327                         s->packet= &(s->s2->rbuf[s->s2->rbuf_offs]);
328                         s->packet_length=n;
329                         }
330                 s->s2->rbuf_left-=n;
331                 s->s2->rbuf_offs+=n;
332                 return(n);
333                 }
334
335         if (!s->read_ahead) max=n;
336         if (max > (unsigned int)(SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2))
337                 max=SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2;
338         
339
340         /* Else we want more than we have.
341          * First, if there is some left or we want to extend */
342         off=0;
343         if ((s->s2->rbuf_left != 0) || ((s->packet_length != 0) && extend))
344                 {
345                 newb=s->s2->rbuf_left;
346                 if (extend)
347                         {
348                         off=s->packet_length;
349                         if (s->packet != s->s2->rbuf)
350                                 memcpy(s->s2->rbuf,s->packet,
351                                         (unsigned int)newb+off);
352                         }
353                 else if (s->s2->rbuf_offs != 0)
354                         {
355                         memcpy(s->s2->rbuf,&(s->s2->rbuf[s->s2->rbuf_offs]),
356                                 (unsigned int)newb);
357                         s->s2->rbuf_offs=0;
358                         }
359                 s->s2->rbuf_left=0;
360                 }
361         else
362                 newb=0;
363
364         /* off is the offset to start writing too.
365          * r->s2->rbuf_offs is the 'unread data', now 0. 
366          * newb is the number of new bytes so far
367          */
368         s->packet=s->s2->rbuf;
369         while (newb < (int)n)
370                 {
371                 clear_sys_error();
372                 if (s->rbio != NULL)
373                         {
374                         s->rwstate=SSL_READING;
375                         i=BIO_read(s->rbio,(char *)&(s->s2->rbuf[off+newb]),
376                                 max-newb);
377                         }
378                 else
379                         {
380                         SSLerr(SSL_F_READ_N,SSL_R_READ_BIO_NOT_SET);
381                         i= -1;
382                         }
383 #ifdef PKT_DEBUG
384                 if (s->debug & 0x01) sleep(1);
385 #endif
386                 if (i <= 0)
387                         {
388                         s->s2->rbuf_left+=newb;
389                         return(i);
390                         }
391                 newb+=i;
392                 }
393
394         /* record unread data */
395         if (newb > (int)n)
396                 {
397                 s->s2->rbuf_offs=n+off;
398                 s->s2->rbuf_left=newb-n;
399                 }
400         else
401                 {
402                 s->s2->rbuf_offs=0;
403                 s->s2->rbuf_left=0;
404                 }
405         if (extend)
406                 s->packet_length+=n;
407         else
408                 s->packet_length=n;
409         s->rwstate=SSL_NOTHING;
410         return(n);
411         }
412
413 int ssl2_write(SSL *s, const void *_buf, int len)
414         {
415         const unsigned char *buf=_buf;
416         unsigned int n,tot;
417         int i;
418
419         if (SSL_in_init(s) && !s->in_handshake)
420                 {
421                 i=s->handshake_func(s);
422                 if (i < 0) return(i);
423                 if (i == 0)
424                         {
425                         SSLerr(SSL_F_SSL2_WRITE,SSL_R_SSL_HANDSHAKE_FAILURE);
426                         return(-1);
427                         }
428                 }
429
430         if (s->error)
431                 {
432                 ssl2_write_error(s);
433                 if (s->error)
434                         return(-1);
435                 }
436
437         clear_sys_error();
438         s->rwstate=SSL_NOTHING;
439         if (len <= 0) return(len);
440
441         tot=s->s2->wnum;
442         s->s2->wnum=0;
443
444         n=(len-tot);
445         for (;;)
446                 {
447                 i=do_ssl_write(s,&(buf[tot]),n);
448                 if (i <= 0)
449                         {
450                         s->s2->wnum=tot;
451                         return(i);
452                         }
453                 if ((i == (int)n) ||
454                         (s->mode & SSL_MODE_ENABLE_PARTIAL_WRITE))
455                         {
456                         return(tot+i);
457                         }
458                 
459                 n-=i;
460                 tot+=i;
461                 }
462         }
463
464 static int write_pending(SSL *s, const unsigned char *buf, unsigned int len)
465         {
466         int i;
467
468         /* s->s2->wpend_len != 0 MUST be true. */
469
470         /* check that they have given us the same buffer to
471          * write */
472         if ((s->s2->wpend_tot > (int)len) ||
473                 ((s->s2->wpend_buf != buf) &&
474                  !(s->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)))
475                 {
476                 SSLerr(SSL_F_WRITE_PENDING,SSL_R_BAD_WRITE_RETRY);
477                 return(-1);
478                 }
479
480         for (;;)
481                 {
482                 clear_sys_error();
483                 if (s->wbio != NULL)
484                         {
485                         s->rwstate=SSL_WRITING;
486                         i=BIO_write(s->wbio,
487                                 (char *)&(s->s2->write_ptr[s->s2->wpend_off]),
488                                 (unsigned int)s->s2->wpend_len);
489                         }
490                 else
491                         {
492                         SSLerr(SSL_F_WRITE_PENDING,SSL_R_WRITE_BIO_NOT_SET);
493                         i= -1;
494                         }
495 #ifdef PKT_DEBUG
496                 if (s->debug & 0x01) sleep(1);
497 #endif
498                 if (i == s->s2->wpend_len)
499                         {
500                         s->s2->wpend_len=0;
501                         s->rwstate=SSL_NOTHING;
502                         return(s->s2->wpend_ret);
503                         }
504                 else if (i <= 0)
505                         return(i);
506                 s->s2->wpend_off+=i;
507                 s->s2->wpend_len-=i;
508                 }
509         }
510
511 static int do_ssl_write(SSL *s, const unsigned char *buf, unsigned int len)
512         {
513         unsigned int j,k,olen,p,mac_size,bs;
514         register unsigned char *pp;
515
516         olen=len;
517
518         /* first check if there is data from an encryption waiting to
519          * be sent - it must be sent because the other end is waiting.
520          * This will happen with non-blocking IO.  We print it and then
521          * return.
522          */
523         if (s->s2->wpend_len != 0) return(write_pending(s,buf,len));
524
525         /* set mac_size to mac size */
526         if (s->s2->clear_text)
527                 mac_size=0;
528         else
529                 mac_size=EVP_MD_size(s->write_hash);
530
531         /* lets set the pad p */
532         if (s->s2->clear_text)
533                 {
534                 if (len > SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER)
535                         len=SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER;
536                 p=0;
537                 s->s2->three_byte_header=0;
538                 /* len=len; */
539                 }
540         else
541                 {
542                 bs=EVP_CIPHER_CTX_block_size(s->enc_read_ctx);
543                 j=len+mac_size;
544                 if ((j > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER) &&
545                         (!s->s2->escape))
546                         {
547                         if (j > SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER)
548                                 j=SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER;
549                         /* set k to the max number of bytes with 2
550                          * byte header */
551                         k=j-(j%bs);
552                         /* how many data bytes? */
553                         len=k-mac_size; 
554                         s->s2->three_byte_header=0;
555                         p=0;
556                         }
557                 else if ((bs <= 1) && (!s->s2->escape))
558                         {
559                         /* len=len; */
560                         s->s2->three_byte_header=0;
561                         p=0;
562                         }
563                 else /* 3 byte header */
564                         {
565                         /*len=len; */
566                         p=(j%bs);
567                         p=(p == 0)?0:(bs-p);
568                         if (s->s2->escape)
569                                 s->s2->three_byte_header=1;
570                         else
571                                 s->s2->three_byte_header=(p == 0)?0:1;
572                         }
573                 }
574         /* mac_size is the number of MAC bytes
575          * len is the number of data bytes we are going to send
576          * p is the number of padding bytes
577          * if p == 0, it is a 2 byte header */
578
579         s->s2->wlength=len;
580         s->s2->padding=p;
581         s->s2->mac_data= &(s->s2->wbuf[3]);
582         s->s2->wact_data= &(s->s2->wbuf[3+mac_size]);
583         /* we copy the data into s->s2->wbuf */
584         memcpy(s->s2->wact_data,buf,len);
585 #ifdef PURIFY
586         if (p)
587                 memset(&(s->s2->wact_data[len]),0,p);
588 #endif
589
590         if (!s->s2->clear_text)
591                 {
592                 s->s2->wact_data_length=len+p;
593                 ssl2_mac(s,s->s2->mac_data,1);
594                 s->s2->wlength+=p+mac_size;
595                 ssl2_enc(s,1);
596                 }
597
598         /* package up the header */
599         s->s2->wpend_len=s->s2->wlength;
600         if (s->s2->three_byte_header) /* 3 byte header */
601                 {
602                 pp=s->s2->mac_data;
603                 pp-=3;
604                 pp[0]=(s->s2->wlength>>8)&(THREE_BYTE_MASK>>8);
605                 if (s->s2->escape) pp[0]|=SEC_ESC_BIT;
606                 pp[1]=s->s2->wlength&0xff;
607                 pp[2]=s->s2->padding;
608                 s->s2->wpend_len+=3;
609                 }
610         else
611                 {
612                 pp=s->s2->mac_data;
613                 pp-=2;
614                 pp[0]=((s->s2->wlength>>8)&(TWO_BYTE_MASK>>8))|TWO_BYTE_BIT;
615                 pp[1]=s->s2->wlength&0xff;
616                 s->s2->wpend_len+=2;
617                 }
618         s->s2->write_ptr=pp;
619         
620         INC32(s->s2->write_sequence); /* expect next number */
621
622         /* lets try to actually write the data */
623         s->s2->wpend_tot=olen;
624         s->s2->wpend_buf=buf;
625
626         s->s2->wpend_ret=len;
627
628         s->s2->wpend_off=0;
629         return(write_pending(s,buf,olen));
630         }
631
632 int ssl2_part_read(SSL *s, unsigned long f, int i)
633         {
634         unsigned char *p;
635         int j;
636
637         /* check for error */
638         if ((s->init_num == 0) && (i >= 3))
639                 {
640                 p=(unsigned char *)s->init_buf->data;
641                 if (p[0] == SSL2_MT_ERROR)
642                         {
643                         j=(p[1]<<8)|p[2];
644                         SSLerr((int)f,ssl_mt_error(j));
645                         }
646                 }
647
648         if (i < 0)
649                 {
650                 /* ssl2_return_error(s); */
651                 /* for non-blocking io,
652                  * this is not fatal */
653                 return(i);
654                 }
655         else
656                 {
657                 s->init_num+=i;
658                 return(0);
659                 }
660         }
661
662 int ssl2_do_write(SSL *s)
663         {
664         int ret;
665
666         ret=ssl2_write(s,&s->init_buf->data[s->init_off],s->init_num);
667         if (ret == s->init_num)
668                 return(1);
669         if (ret < 0)
670                 return(-1);
671         s->init_off+=ret;
672         s->init_num-=ret;
673         return(0);
674         }
675
676 static int ssl_mt_error(int n)
677         {
678         int ret;
679
680         switch (n)
681                 {
682         case SSL2_PE_NO_CIPHER:
683                 ret=SSL_R_PEER_ERROR_NO_CIPHER;
684                 break;
685         case SSL2_PE_NO_CERTIFICATE:
686                 ret=SSL_R_PEER_ERROR_NO_CERTIFICATE;
687                 break;
688         case SSL2_PE_BAD_CERTIFICATE:
689                 ret=SSL_R_PEER_ERROR_CERTIFICATE;
690                 break;
691         case SSL2_PE_UNSUPPORTED_CERTIFICATE_TYPE:
692                 ret=SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE;
693                 break;
694         default:
695                 ret=SSL_R_UNKNOWN_REMOTE_ERROR_TYPE;
696                 break;
697                 }
698         return(ret);
699         }
700 #else /* !NO_SSL2 */
701
702 # if PEDANTIC
703 static void *dummy=&dummy;
704 # endif
705
706 #endif