summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2001-11-15 12:37:08 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2001-11-15 12:37:08 +0000
commit80bc85066bd8406464f2d2d36574dfe1b6bfdc6b (patch)
tree8c5446d81cc1c283e8ed1edd610d9c55473e0ef9
parentabc3977c66a2b00c5e76a5a8a03d5d3a74215c28 (diff)
downloadgnutls-80bc85066bd8406464f2d2d36574dfe1b6bfdc6b.tar.gz
corrected some obscure bugs in the handshake and record send buffering code.
-rw-r--r--configure.in1
-rw-r--r--lib/auth_dhe_rsa.c2
-rw-r--r--lib/auth_srp.c3
-rw-r--r--lib/auth_x509.c7
-rw-r--r--lib/gnutls_buffers.c156
-rw-r--r--lib/gnutls_buffers.h2
-rw-r--r--lib/gnutls_errors.c1
-rw-r--r--lib/gnutls_errors_int.h1
-rw-r--r--lib/gnutls_record.c2
-rw-r--r--src/serv.c2
10 files changed, 116 insertions, 61 deletions
diff --git a/configure.in b/configure.in
index ca975efa4f..19cc3ef489 100644
--- a/configure.in
+++ b/configure.in
@@ -176,6 +176,7 @@ dnl **** CROSS COMPILING
AC_MSG_RESULT(none)
)
+
AC_MSG_CHECKING([whether to check for external libraries])
dnl if used --with-ext-libraries then we will not check
diff --git a/lib/auth_dhe_rsa.c b/lib/auth_dhe_rsa.c
index 519a80cdf9..bec7454fcc 100644
--- a/lib/auth_dhe_rsa.c
+++ b/lib/auth_dhe_rsa.c
@@ -309,7 +309,7 @@ static int proc_dhe_rsa_server_kx(GNUTLS_STATE state, opaque * data,
sigsize = READuint16( &data[vparams.size]);
signature.data = &data[vparams.size+2];
- signature.size = GMIN(data_size-vparams.size-2, sigsize);
+ signature.size = GMIN(data_size-vparams.size-2, sigsize);
ret = _gnutls_verify_sig_params( state, &state->gnutls_internals.peer_cert, &vparams, &signature);
if (ret<0) {
diff --git a/lib/auth_srp.c b/lib/auth_srp.c
index dad9eb68bc..7d36b4344d 100644
--- a/lib/auth_srp.c
+++ b/lib/auth_srp.c
@@ -88,7 +88,6 @@ int gen_srp_server_hello(GNUTLS_STATE state, opaque ** data)
username = ((SRP_SERVER_AUTH_INFO)state->gnutls_key->auth_info)->username;
strcpy( username, state->security_parameters.extensions.srp_username);
-#warning GET_PWD_ENTRY_USERNAME
pwd_entry = _gnutls_srp_pwd_read_entry( state->gnutls_key, username, &err);
if (pwd_entry == NULL) {
@@ -249,7 +248,6 @@ int gen_srp_client_kx0(GNUTLS_STATE state, opaque ** data)
return GNUTLS_E_INSUFICIENT_CRED;
}
-#warning GET_USERNAME_PASSWORD
username = cred->username;
password = cred->password;
@@ -310,7 +308,6 @@ int proc_srp_server_hello(GNUTLS_STATE state, const opaque * data, int data_size
return GNUTLS_E_INSUFICIENT_CRED;
}
-#warning GET_USERNAME_PASSWORD
username = cred->username;
password = cred->password;
diff --git a/lib/auth_x509.c b/lib/auth_x509.c
index 668466872d..41b739531a 100644
--- a/lib/auth_x509.c
+++ b/lib/auth_x509.c
@@ -414,7 +414,6 @@ int _gnutls_gen_x509_client_certificate(GNUTLS_STATE state, opaque ** data)
gnutls_private_key *apr_pkey;
int apr_cert_list_length;
-#warning GET_CLIENT_CERTIFICATE
/* find the appropriate certificate */
if ((ret=_gnutls_find_apr_cert( state, &apr_cert_list, &apr_cert_list_length, &apr_pkey))<0) {
gnutls_assert();
@@ -475,7 +474,6 @@ int _gnutls_gen_x509_server_certificate(GNUTLS_STATE state, opaque ** data)
gnutls_private_key *apr_pkey;
int apr_cert_list_length;
-#warning GET_SERVER_CERTIFICATE
if ((ret=_gnutls_find_apr_cert( state, &apr_cert_list, &apr_cert_list_length, &apr_pkey))<0) {
gnutls_assert();
return ret;
@@ -533,7 +531,6 @@ int _gnutls_proc_x509_server_certificate(GNUTLS_STATE state, opaque * data, int
gnutls_datum tmp;
CertificateStatus verify;
-#warning PUT_SERVER_CERTIFICATE
cred = _gnutls_get_cred(state->gnutls_key, GNUTLS_X509PKI, NULL);
if (cred == NULL) {
gnutls_assert();
@@ -626,7 +623,6 @@ int _gnutls_proc_x509_server_certificate(GNUTLS_STATE state, opaque * data, int
j++;
}
-#warning GET_SERVER_CERTIFICATE_PARAMS
/* store the required parameters for the handshake
*/
if ((ret =
@@ -759,7 +755,6 @@ int _gnutls_gen_x509_client_cert_vrfy(GNUTLS_STATE state, opaque ** data)
*data = NULL;
-#warning GENERATE_SIGNATURE_FROM_DATA
/* find the appropriate certificate */
if ((ret=_gnutls_find_apr_cert( state, &apr_cert_list, &apr_cert_list_length, &apr_pkey))<0) {
gnutls_assert();
@@ -802,7 +797,6 @@ gnutls_datum sig;
size = READuint16( pdata);
pdata += 2;
-#warning VERIFY_SIGNATURE_FROM_DATA
if ( size < data_size - 2) {
gnutls_assert();
return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
@@ -861,7 +855,6 @@ int _gnutls_gen_x509_server_cert_req(GNUTLS_STATE state, opaque ** data)
pdata += 2;
size += 2;
-#warning GET_TRUSTED_CAS_DN
for (i = 0; i < cred->ncas; i++) {
if ( (ret=_gnutls_find_dn( &dn, &cred->ca_list[i])) < 0) {
gnutls_free( (*data));
diff --git a/lib/gnutls_buffers.c b/lib/gnutls_buffers.c
index 64a9ee9775..e5c712a8ef 100644
--- a/lib/gnutls_buffers.c
+++ b/lib/gnutls_buffers.c
@@ -1,4 +1,3 @@
-#define IO_DEBUG 5
/*
* Copyright (C) 2000,2001 Nikos Mavroyanopoulos
*
@@ -38,6 +37,12 @@
# define EAGAIN EWOULDBLOCK
#endif
+inline
+static int RET( int err) {
+ if (err==EAGAIN) return GNUTLS_E_AGAIN;
+ return GNUTLS_E_INTERRUPTED;
+}
+
#ifdef IO_DEBUG
# include <io_debug.h>
#endif
@@ -206,8 +211,8 @@ static ssize_t _gnutls_read( SOCKET fd, GNUTLS_STATE state, void *iptr, size_t s
goto finish;
}
gnutls_assert();
- if (errno==EAGAIN) return GNUTLS_E_AGAIN;
- else return GNUTLS_E_INTERRUPTED;
+
+ return RET(errno);
} else {
gnutls_assert();
return GNUTLS_E_PULL_ERROR;
@@ -440,6 +445,58 @@ ssize_t _gnutls_read_buffered( int fd, GNUTLS_STATE state, opaque **iptr, size_t
}
}
+
+/* These two functions are used to insert data to the send buffer of the handshake or
+ * record protocol. The send buffer is kept if a send is interrupted and we need to keep
+ * the data left to sent, in order to send them later.
+ */
+
+#define MEMSUB(x,y) (x-y)
+
+inline
+static int _gnutls_buffer_insert( gnutls_datum * buffer, const opaque* _data, int data_size) {
+
+ if ( ( MEMSUB(_data, buffer->data) >= 0) && (MEMSUB(_data, buffer->data) < buffer->size) ) {
+ /* the given _data is part of the buffer.
+ */
+ if (data_size > buffer->size) {
+ gnutls_assert();
+ /* this shouldn't have happened */
+ return GNUTLS_E_UNKNOWN_ERROR;
+ }
+
+ if (_data==buffer->data) { /* then don't even memmove */
+ buffer->size = data_size;
+ return 0;
+ }
+
+ memmove( buffer->data, _data, data_size);
+ buffer->size = data_size;
+
+ return 0;
+ }
+
+ buffer->data = gnutls_realloc_fast( buffer->data, data_size);
+ buffer->size = data_size;
+
+ if (buffer->data == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ memcpy( buffer->data, _data, data_size);
+
+ return 0;
+}
+
+inline
+static int _gnutls_buffer_get( gnutls_datum * buffer, const opaque ** ptr, size_t *ptr_size) {
+ *ptr_size = buffer->size;
+ *ptr = buffer->data;
+
+ return 0;
+}
+
/* This function is like write. But it does not return -1 on error.
* It does return gnutls_errno instead.
*
@@ -459,8 +516,8 @@ ssize_t _gnutls_write_buffered(SOCKET fd, GNUTLS_STATE state, const void *iptr,
#endif
ssize_t retval, i;
const opaque * ptr;
- int ptrcopy; /* indicates whether to copy from the ptr */
-
+ int ret;
+
ptr = iptr;
/* In case the previous write was interrupted, check if the
@@ -474,12 +531,13 @@ ssize_t _gnutls_write_buffered(SOCKET fd, GNUTLS_STATE state, const void *iptr,
/* If data in the buffer exist
*/
- ptrcopy = 1;
if (iptr == NULL) {
/* checking is handled above */
- ptr = state->gnutls_internals.send_buffer.data;
- n = state->gnutls_internals.send_buffer.size;
- ptrcopy = 0;
+ ret = _gnutls_buffer_get( &state->gnutls_internals.send_buffer, &ptr, &n);
+ if (ret < 0) {
+ gnutls_assert();
+ return retval;
+ }
#ifdef WRITE_DEBUG
_gnutls_log( "WRITE: Restoring old write. (%d bytes to send)\n", n);
#endif
@@ -502,25 +560,16 @@ ssize_t _gnutls_write_buffered(SOCKET fd, GNUTLS_STATE state, const void *iptr,
if (errno == EAGAIN || errno == EINTR) {
state->gnutls_internals.send_buffer_prev_size += n - left;
- state->gnutls_internals.send_buffer.data = gnutls_realloc_fast(
- state->gnutls_internals.send_buffer.data, left);
-
- if (state->gnutls_internals.send_buffer.data == NULL) {
+ retval = _gnutls_buffer_insert( &state->gnutls_internals.send_buffer, &ptr[n-left], left);
+ if (retval < 0) {
gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
+ return retval;
}
- state->gnutls_internals.send_buffer.size = left;
-
- if (ptrcopy != 0)
- memcpy( state->gnutls_internals.send_buffer.data, &ptr[n-left], left);
- else
- memmove( state->gnutls_internals.send_buffer.data, &state->gnutls_internals.send_buffer.data[n-left], left);
-
+
#ifdef WRITE_DEBUG
_gnutls_log( "WRITE: Interrupted. Stored %d bytes to buffer. Already sent %d bytes.\n", left, n-left);
#endif
- if (errno==EAGAIN) retval = GNUTLS_E_AGAIN;
- else retval = GNUTLS_E_INTERRUPTED;
+ retval = RET(errno);
return retval;
} else {
@@ -584,7 +633,6 @@ ssize_t _gnutls_write_flush(SOCKET fd, GNUTLS_STATE state)
ssize_t _gnutls_handshake_write_flush(SOCKET fd, GNUTLS_STATE state)
{
ssize_t ret;
-
ret = _gnutls_handshake_send_int(fd, state, 0, 0, NULL, 0);
if (ret < 0) {
gnutls_assert();
@@ -609,41 +657,63 @@ ssize_t _gnutls_handshake_write_flush(SOCKET fd, GNUTLS_STATE state)
/* This is a send function for the gnutls handshake
* protocol. Just makes sure that all data have been sent.
*/
-ssize_t _gnutls_handshake_send_int( SOCKET fd, GNUTLS_STATE state, ContentType type, HandshakeType htype, void *iptr, size_t n)
+ssize_t _gnutls_handshake_send_int( SOCKET fd, GNUTLS_STATE state, ContentType type, HandshakeType htype, const void *iptr, size_t n)
{
size_t left;
ssize_t i = 0, ret=0;
- opaque *ptr;
- int ptrcopy;
+ const opaque *ptr;
ssize_t retval = 0;
+
+ ptr = iptr;
- ptrcopy = 1;
- if (state->gnutls_internals.handshake_send_buffer.size > 0 && iptr==NULL && n == 0) {
+ if (state->gnutls_internals.handshake_send_buffer.size > 0 && ptr==NULL && n == 0) {
/* resuming previously interrupted write
*/
gnutls_assert();
- n = state->gnutls_internals.handshake_send_buffer.size;
- iptr = state->gnutls_internals.handshake_send_buffer.data;
+ ret = _gnutls_buffer_get( &state->gnutls_internals.handshake_send_buffer, &ptr, &n);
+ if (ret < 0) {
+ gnutls_assert();
+ return retval;
+ }
type = state->gnutls_internals.handshake_send_buffer_type;
htype = state->gnutls_internals.handshake_send_buffer_htype;
- ptrcopy = 0;
} else if (state->gnutls_internals.handshake_send_buffer.size > 0) {
gnutls_assert();
return GNUTLS_E_UNKNOWN_ERROR;
+ } else {
+#ifdef WRITE_DEBUG
+ size_t sum=0, x, j;
+
+ _gnutls_log( "HWRITE: will write %d bytes to %d.\n", n, fd);
+ for (x=0;x<((n)/16)+1;x++) {
+ if (sum>n)
+ break;
+
+ _gnutls_log( "%.4x - ",x);
+ for (j=0;j<16;j++) {
+ if (sum<n) {
+ _gnutls_log( "%.2x ", ((unsigned char*)ptr)[sum++]);
+ } else break;
+ }
+ _gnutls_log( "\n");
+ }
+ _gnutls_log( "\n");
+#endif
+
+
}
if (n==0) { /* if we have no data to send */
gnutls_assert();
return 0;
- } else if (iptr==NULL) {
+ } else if (ptr==NULL) {
gnutls_assert();
return GNUTLS_E_UNKNOWN_ERROR;
}
- ptr = iptr;
left = n;
while (left > 0) {
ret = gnutls_send_int(fd, state, type, htype, &ptr[n-left], left);
@@ -657,22 +727,12 @@ ssize_t _gnutls_handshake_send_int( SOCKET fd, GNUTLS_STATE state, ContentType t
if ( left > 0 && (ret==GNUTLS_E_INTERRUPTED || ret==GNUTLS_E_AGAIN)) {
gnutls_assert();
- state->gnutls_internals.handshake_send_buffer.data = gnutls_realloc_fast(
- state->gnutls_internals.handshake_send_buffer.data, left);
-
- if (state->gnutls_internals.handshake_send_buffer.data==NULL) {
+ retval = _gnutls_buffer_insert( &state->gnutls_internals.handshake_send_buffer, &ptr[n-left], left);
+ if (retval < 0) {
gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
+ return retval;
}
-
- if (ptrcopy!=0)
- memcpy( state->gnutls_internals.handshake_send_buffer.data, &ptr[n-left], left);
- else
- if (n-left > 0)
- memmove( state->gnutls_internals.handshake_send_buffer.data,
- &state->gnutls_internals.handshake_send_buffer.data[n-left], left);
-
- state->gnutls_internals.handshake_send_buffer.size = left;
+
state->gnutls_internals.handshake_send_buffer_prev_size += n-left;
state->gnutls_internals.handshake_send_buffer_type = type;
diff --git a/lib/gnutls_buffers.h b/lib/gnutls_buffers.h
index 63b17e0ef5..28f54a595d 100644
--- a/lib/gnutls_buffers.h
+++ b/lib/gnutls_buffers.h
@@ -35,6 +35,6 @@ int gnutls_insert_to_handshake_buffer( GNUTLS_STATE state, char *data, int lengt
int gnutls_clear_handshake_buffer( GNUTLS_STATE state);
ssize_t _gnutls_handshake_recv_int(SOCKET fd, GNUTLS_STATE, ContentType, HandshakeType, void *, size_t);
-ssize_t _gnutls_handshake_send_int(SOCKET fd, GNUTLS_STATE, ContentType, HandshakeType, void *, size_t);
+ssize_t _gnutls_handshake_send_int(SOCKET fd, GNUTLS_STATE, ContentType, HandshakeType, const void *, size_t);
ssize_t _gnutls_write_flush(SOCKET fd, GNUTLS_STATE state);
ssize_t _gnutls_handshake_write_flush(SOCKET fd, GNUTLS_STATE state);
diff --git a/lib/gnutls_errors.c b/lib/gnutls_errors.c
index f8c80e266b..499d0c5033 100644
--- a/lib/gnutls_errors.c
+++ b/lib/gnutls_errors.c
@@ -84,6 +84,7 @@ static gnutls_error_entry error_algorithms[] = {
GNUTLS_ERROR_ENTRY( GNUTLS_E_X509_KEY_USAGE_VIOLATION, 1),
GNUTLS_ERROR_ENTRY( GNUTLS_E_AGAIN, 0),
GNUTLS_ERROR_ENTRY( GNUTLS_E_INTERRUPTED, 0),
+ GNUTLS_ERROR_ENTRY( GNUTLS_E_TIMEOUT, 0),
GNUTLS_ERROR_ENTRY( GNUTLS_E_REHANDSHAKE, 0),
GNUTLS_ERROR_ENTRY( GNUTLS_E_GOT_APPLICATION_DATA, 0),
GNUTLS_ERROR_ENTRY( GNUTLS_E_DB_ERROR, 1),
diff --git a/lib/gnutls_errors_int.h b/lib/gnutls_errors_int.h
index 4426100b5c..ea2ff4ca6a 100644
--- a/lib/gnutls_errors_int.h
+++ b/lib/gnutls_errors_int.h
@@ -56,5 +56,6 @@
#define GNUTLS_E_PUSH_ERROR -53
#define GNUTLS_E_PULL_ERROR -54
#define GNUTLS_E_ILLEGAL_PARAMETER -55
+#define GNUTLS_E_TIMEOUT -56
#define GNUTLS_E_UNIMPLEMENTED_FEATURE -250
diff --git a/lib/gnutls_record.c b/lib/gnutls_record.c
index 6c316635af..9628c64892 100644
--- a/lib/gnutls_record.c
+++ b/lib/gnutls_record.c
@@ -543,6 +543,8 @@ ssize_t gnutls_send_int(SOCKET cd, GNUTLS_STATE state, ContentType type, Handsha
if (state->gnutls_internals.send_buffer.size > 0) {
ret = _gnutls_write_flush(cd, state);
if (ret > 0) cipher_size = ret;
+ else cipher_size = 0;
+
cipher = NULL;
retval = state->gnutls_internals.send_buffer_user_size;
diff --git a/src/serv.c b/src/serv.c
index 7aa3da7868..c6efeb4c59 100644
--- a/src/serv.c
+++ b/src/serv.c
@@ -63,7 +63,7 @@ static char http_buffer[16*1024];
#define HTTP_END "</BODY></HTML>\n\n"
-//#define RENEGOTIATE
+#define RENEGOTIATE
/* These are global */
SRP_SERVER_CREDENTIALS srp_cred;