* [including the GNU Public Licence.]
*/
/* ====================================================================
- * Copyright (c) 1998-1999 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1998-2000 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
* Application data protocol
* none of our business
*/
-int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len)
+int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
{
- int al,i,j,n,ret;
+ int al,i,j,ret;
+ unsigned int n;
SSL3_RECORD *rr;
void (*cb)()=NULL;
- BIO *bio;
if (s->s3->rbuf.buf == NULL) /* Not initialized yet */
if (!ssl3_setup_buffers(s))
return(-1);
- if ((type != SSL3_RT_APPLICATION_DATA) && (type != SSL3_RT_HANDSHAKE) && type)
+ if ((type && (type != SSL3_RT_APPLICATION_DATA) && (type != SSL3_RT_HANDSHAKE) && type) ||
+ (peek && (type != SSL3_RT_APPLICATION_DATA)))
{
SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_INTERNAL_ERROR);
return -1;
{
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))
{
n++;
}
/* move any remaining fragment bytes: */
- for (i = 0; i < s->s3->handshake_fragment_len; i++)
- s->s3->handshake_fragment[i] = *src++;
+ for (k = 0; k < s->s3->handshake_fragment_len; k++)
+ s->s3->handshake_fragment[k] = *src++;
return n;
}
* s->s3->rrec.length, - number of bytes. */
rr = &(s->s3->rrec);
- /* get new packet */
+ /* get new packet if necessary */
if ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY))
{
ret=ssl3_get_record(s);
goto err;
}
- /* If the other end has shutdown, throw anything we read away */
+ /* 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;
if (len <= 0) return(len);
if ((unsigned int)len > rr->length)
- n=rr->length;
+ n = rr->length;
else
- n=len;
+ n = (unsigned int)len;
- memcpy(buf,&(rr->data[rr->off]),(unsigned int)n);
- rr->length-=n;
- rr->off+=n;
- if (rr->length == 0)
+ memcpy(buf,&(rr->data[rr->off]),n);
+ if (!peek)
{
- s->rstate=SSL_ST_READ_HEADER;
- rr->off=0;
+ rr->length-=n;
+ rr->off+=n;
+ if (rr->length == 0)
+ {
+ s->rstate=SSL_ST_READ_HEADER;
+ rr->off=0;
+ }
}
return(n);
}
* fill that so that we can process the data at a fixed place.
*/
{
- int dest_maxlen = 0;
- unsigned char *dest;
- int *dest_len;
+ unsigned int dest_maxlen = 0;
+ unsigned char *dest = NULL;
+ unsigned int *dest_len = NULL;
if (rr->type == SSL3_RT_HANDSHAKE)
{
ssl3_renegotiate(s);
if (ssl3_renegotiate_check(s))
{
- n=s->handshake_func(s);
- if (n < 0) return(n);
- if (n == 0)
+ 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);
}
+
+ 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);
+ }
+ }
}
}
/* we either finished a handshake or ignored the request,
if (s->s3->alert_fragment_len >= 2)
{
- i = s->s3->alert_fragment[0];
- n = s->s3->alert_fragment[1];
+ int alert_level = s->s3->alert_fragment[0];
+ int alert_descr = s->s3->alert_fragment[1];
s->s3->alert_fragment_len = 0;
if (cb != NULL)
{
- j=(i<<8)|n;
- cb(s,SSL_CB_READ_ALERT,j);
+ j = (alert_level << 8) | alert_descr;
+ cb(s, SSL_CB_READ_ALERT, j);
}
- if (i == 1) /* warning */
+ if (alert_level == 1) /* warning */
{
- s->s3->warn_alert=n;
- if (n == SSL_AD_CLOSE_NOTIFY)
+ s->s3->warn_alert = alert_descr;
+ if (alert_descr == SSL_AD_CLOSE_NOTIFY)
{
- s->shutdown|=SSL_RECEIVED_SHUTDOWN;
+ s->shutdown |= SSL_RECEIVED_SHUTDOWN;
return(0);
}
}
- else if (i == 2) /* fatal */
+ else if (alert_level == 2) /* fatal */
{
char tmp[16];
s->rwstate=SSL_NOTHING;
- s->s3->fatal_alert=n;
- SSLerr(SSL_F_SSL3_READ_BYTES,
- SSL_AD_REASON_OFFSET+n);
- sprintf(tmp,"%d",n);
+ s->s3->fatal_alert = alert_descr;
+ SSLerr(SSL_F_SSL3_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);
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;
}
- n=s->handshake_func(s);
- if (n < 0) return(n);
- if (n == 0)
+ 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);
}
- /* In the case where we try to read application data
- * the first time, but we trigger an SSL handshake, we
- * return -1 with the retry option set. I do this
- * otherwise renegotiation can cause nasty problems
- * in the non-blocking world */
-
- s->rwstate=SSL_READING;
- bio=SSL_get_rbio(s);
- BIO_clear_retry_flags(bio);
- BIO_set_retry_read(bio);
- 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)
* 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 renegotation not yet started),
+ * at this point (session renegotiation not yet started),
* we will indulge it.
*/
if (s->s3->in_read_app_data &&
return(1);
}
-/* send s->init_buf in records of type 'type' */
-int ssl3_do_write(SSL *s, int type)
- {
- int ret;
-
- ret=ssl3_write_bytes(s,type,&s->init_buf->data[s->init_off],
- s->init_num);
- if (ret < 0) return(-1);
- if (type == SSL3_RT_HANDSHAKE)
- /* should not be done for 'Hello Request's, but in that case
- * we'll ignore the result anyway */
- ssl3_finish_mac(s,&s->init_buf->data[s->init_off],ret);
-
- if (ret == s->init_num)
- return(1);
- s->init_off+=ret;
- s->init_num-=ret;
- return(0);
- }
-
void ssl3_send_alert(SSL *s, int level, int desc)
{
/* Map tls/ssl alert value to correct one */