]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
better support for buffered read and several cleanups
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 19 Aug 2001 14:25:44 +0000 (14:25 +0000)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 19 Aug 2001 14:25:44 +0000 (14:25 +0000)
NEWS
configure.in
lib/auth_srp.c
lib/ext_srp.c
lib/gnutls_buffers.c
lib/gnutls_buffers.h
lib/gnutls_errors.c
lib/gnutls_errors_int.h
lib/gnutls_int.h
lib/gnutls_record.c
src/cli.c

diff --git a/NEWS b/NEWS
index 47c02ebe8ead961f487529ba2040716628a69640..281ebf5c20b66565cc027d736cc7451f07e49cca 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,6 @@
+Version 0.2.1 (07/08/2001)
+- SRP fixes
+
 Version 0.2.0 (07/08/2001)
 - Partial support for X509v3 Certificate extensions.
 - Added Internal memory handlers
index f2c75f796946b03206e37eca0a359187d9580998..f81784eccf40dfcb6aa145bfa09cf88011241500 100644 (file)
@@ -11,7 +11,7 @@ AC_DEFINE_UNQUOTED(T_OS, "$target_os")
 
 GNUTLS_MAJOR_VERSION=0
 GNUTLS_MINOR_VERSION=2
-GNUTLS_MICRO_VERSION=0
+GNUTLS_MICRO_VERSION=2
 GNUTLS_VERSION=$GNUTLS_MAJOR_VERSION.$GNUTLS_MINOR_VERSION.$GNUTLS_MICRO_VERSION
 
 AC_DEFINE_UNQUOTED(GNUTLS_VERSION, "$GNUTLS_VERSION")
index 11cd3cef9543fa3a537bf6690b1acf22d8d1a4e8..8a4977f1fa21729f88fec9046cc36131d6683f71 100644 (file)
@@ -86,7 +86,7 @@ int gen_srp_server_hello(GNUTLS_STATE state, opaque ** data)
        state->gnutls_key->auth_info_size = sizeof(SRP_SERVER_AUTH_INFO_INT);
        
        username = ((SRP_SERVER_AUTH_INFO)state->gnutls_key->auth_info)->username;
-       strcpy( username, state->gnutls_internals.srp_username);
+       strcpy( username, state->security_parameters.extensions.srp_username);
 
        pwd_entry = _gnutls_srp_pwd_read_entry( state->gnutls_key, username, &err);
 
index b2d716e3ec94164c1f6545900f5578051e4bf4ee..d174c74f7c7473c7a3024cc26a7b9d1dc09ee8de 100644 (file)
@@ -41,12 +41,12 @@ int _gnutls_srp_recv_params( GNUTLS_STATE state, const opaque* data, int data_si
                                gnutls_assert();
                                return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
                        }
-                       if ( sizeof( state->gnutls_internals.srp_username) <= len) {
+                       if ( sizeof( state->security_parameters.extensions.srp_username) <= len) {
                                gnutls_assert();
                                return GNUTLS_E_MEMORY_ERROR;
                        }
-                       memcpy( state->gnutls_internals.srp_username, &data[1], len);
-                       state->gnutls_internals.srp_username[len]=0; /* null terminated */
+                       memcpy( state->security_parameters.extensions.srp_username, &data[1], len);
+                       state->security_parameters.extensions.srp_username[len]=0; /* null terminated */
                }
        } else { /* client side reading server hello extensions */
                if (state->gnutls_internals.resumed==RESUME_FALSE)
index 20701b64588cae99105bd12b3b90872f06b129c1..731c1ef83c7a7b6e63692002d42b47b438ed59fc 100644 (file)
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  */
 
-#include "gnutls_int.h"
-#include "gnutls_errors.h"
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <gnutls_num.h>
+
 #ifdef HAVE_ERRNO_H
- # include <errno.h>
+# include <errno.h>
+#endif
+
+#ifndef EAGAIN
+# define EAGAIN EWOULDBLOCK
 #endif
 
 extern ssize_t (*_gnutls_recv_func)( SOCKET, void*, size_t, int);
@@ -132,8 +138,9 @@ int gnutls_getDataFromBuffer(ContentType type, GNUTLS_STATE state, char *data, i
        return length;
 }
 
+
 /* This function is like read. But it does not return -1 on error.
- * It does return -errno instead.
+ * It does return gnutls_errno instead.
  */
 ssize_t _gnutls_Read(int fd, void *iptr, size_t sizeOfPtr, int flag)
 {
@@ -149,7 +156,10 @@ ssize_t _gnutls_Read(int fd, void *iptr, size_t sizeOfPtr, int flag)
        while (left > 0) {
                i = _gnutls_recv_func(fd, &ptr[i], left, flag);
                if (i < 0) {
-                       return (0-errno);
+                       if (errno == EAGAIN)
+                               return GNUTLS_E_AGAIN;
+                       else 
+                               return GNUTLS_E_UNKNOWN_ERROR;
                } else {
                        if (i == 0)
                                break;  /* EOF */
@@ -178,10 +188,105 @@ ssize_t _gnutls_Read(int fd, void *iptr, size_t sizeOfPtr, int flag)
 }
 
 
+#define RCVLOWAT state->gnutls_internals.lowat 
+
+int _gnutls_clear_peeked_data( SOCKET cd, GNUTLS_STATE state) {
+char peekdata1;
+char *peekdata2;
+
+       if (state->gnutls_internals.have_peeked_data==0)
+               return 0;
+               
+       if (RCVLOWAT != 1) {
+               if (RCVLOWAT == 0)
+                       return 0;
+                       
+               peekdata2 = gnutls_malloc( RCVLOWAT);
+       
+               /* this was already read by using MSG_PEEK - so it shouldn't fail */
+               _gnutls_Read( cd, peekdata2, RCVLOWAT, 0); 
+        
+               gnutls_free(peekdata2);
+        } else {
+               _gnutls_Read( cd, &peekdata1, RCVLOWAT, 0); 
+        }
+       state->gnutls_internals.have_peeked_data=0;
+
+               return 0;
+}
+
+
+void _gnutls_read_clear_buffer( GNUTLS_STATE state) {
+       state->gnutls_internals.recv_buffer_data_size = 0;
+}
+                       
+/* This function is like read. But it does not return -1 on error.
+ * It does return gnutls_errno instead.
+ */
+ssize_t _gnutls_read_buffered( int fd, GNUTLS_STATE state, void *iptr, size_t sizeOfPtr, int flag, ContentType recv_type)
+{
+       ssize_t ret=0, ret2=0;
+       int min;
+       char *ptr = iptr;
+       int recvlowat = RCVLOWAT;
+
+       /* leave peeked data to the kernel space only if application data
+        * is received.
+        */
+       if (recv_type != GNUTLS_APPLICATION_DATA)
+               recvlowat = 0;
+
+       /* copy peeked data to given buffer
+        */
+       min = GMIN( state->gnutls_internals.recv_buffer_data_size, sizeOfPtr);
+       if ( min > 0) {
+               memcpy( iptr, state->gnutls_internals.recv_buffer_data, min);   
+               if ( min == sizeOfPtr)
+                       return min;
+       }
+
+       /* since we are going to read data, we must clear any peeked.
+        */
+       _gnutls_clear_peeked_data( fd, state);
+       
+       /* read fresh data - but leave RCVLOWAT bytes in the kernel buffer.
+        */
+       if ( sizeOfPtr - min - recvlowat > 0)
+               ret = _gnutls_Read( fd, &ptr[min], sizeOfPtr - min - recvlowat, flag);
+               if (ret >= 0 && recvlowat > 0) {
+                       ret2 = _gnutls_Read( fd, &ptr[min+ret], recvlowat, MSG_PEEK|flag);
+                       state->gnutls_internals.have_peeked_data = 1;
+               }
+
+       if (ret < 0 || ret2 < 0)
+               return GMIN(ret, ret2);
+
+
+       ret += ret2;
+
+       if (ret < recvlowat) {
+               gnutls_assert();
+               return GNUTLS_E_AGAIN;
+       }
+
+       
+       /* copy fresh data to our buffer.
+        */
+       if ( ret+state->gnutls_internals.recv_buffer_data_size > sizeof( state->gnutls_internals.recv_buffer_data)) {
+               gnutls_assert();
+               return GNUTLS_E_MEMORY_ERROR;
+       }
+       memcpy( &state->gnutls_internals.recv_buffer_data[state->gnutls_internals.recv_buffer_data_size], &ptr[min], ret);
+       state->gnutls_internals.recv_buffer_data_size += ret;
+
+       return ret+min;
+}
+
+
 /* This function is like write. But it does not return -1 on error.
  * It does return -errno instead.
  */
-ssize_t _gnutls_Write(int fd, const void *iptr, size_t n, int flags)
+ssize_t _gnutls_write(int fd, const void *iptr, size_t n, int flags)
 {
        size_t left;
 #ifdef WRITE_DEBUG
index 7ecbfe88f96d6b56ad9d183836c792357d3cd18a..afb2a302240707b91384472a44ef30b0f62c019c 100644 (file)
 int gnutls_insertDataBuffer(ContentType type, GNUTLS_STATE state, char *data, int length);
 int gnutls_getDataBufferSize(ContentType type, GNUTLS_STATE state);
 int gnutls_getDataFromBuffer(ContentType type, GNUTLS_STATE state, char *data, int length);
-ssize_t _gnutls_Read(int fd, void *iptr, size_t n, int);
-ssize_t _gnutls_Write(int fd, const void *iptr, size_t n, int );
+ssize_t _gnutls_read_buffered(int fd, GNUTLS_STATE, void *iptr, size_t n, int, ContentType);
+void _gnutls_read_clear_buffer( GNUTLS_STATE);
+int _gnutls_clear_peeked_data( SOCKET cd, GNUTLS_STATE state);
+
+ssize_t _gnutls_write(int fd, const void *iptr, size_t n, int );
 
 /* used in SSL3 */
 int gnutls_getHashDataFromBuffer( GNUTLS_STATE state, char *data, int length);
index 3e8dafa7050452d01a93e3effc06886a53372dbc..4fce48b09bc6a9facdde1cb016a33c22832ce57f 100644 (file)
@@ -82,7 +82,7 @@ static gnutls_error_entry error_algorithms[] = {
        GNUTLS_ERROR_ENTRY( GNUTLS_E_X509_UNSUPPORTED_CRITICAL_EXTENSION, 1),
        GNUTLS_ERROR_ENTRY( GNUTLS_E_X509_KEY_USAGE_VIOLATION, 1),
        GNUTLS_ERROR_ENTRY( GNUTLS_E_AGAIN, 0),
-       GNUTLS_ERROR_ENTRY( GNUTLS_E_GOT_HELLO_REQUEST, 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),
        {0}
index 5eaeaf2ad3d0f08395b7bf985af20b847e12c18f..e66bfaf0ba25fb3a57cdde1e3366abb6cf656a9f 100644 (file)
@@ -37,7 +37,7 @@
 #define GNUTLS_E_PARSING_ERROR -34
 #define        GNUTLS_E_MPI_PRINT_FAILED -35
 #define GNUTLS_E_AUTH_FAILED -36
-#define GNUTLS_E_GOT_HELLO_REQUEST -37
+#define GNUTLS_E_REHANDSHAKE -37
 #define GNUTLS_E_GOT_APPLICATION_DATA -38
 #define GNUTLS_E_RECORD_LIMIT_REACHED -39
 #define GNUTLS_E_ENCRYPTION_FAILED -40
index 4937f8fc45a7310ba7681d91c3f325f45929069c..ec7a0977f35fc8e391fed356d4473e25d40ccef8 100644 (file)
@@ -204,6 +204,7 @@ typedef struct {
  */
 typedef struct {
        opaque dnsname[MAX_DNSNAME_SIZE];
+       opaque srp_username[MAX_SRP_USERNAME];
 } TLSExtensions;
 
 /* AUTH_INFO structures MUST NOT contain malloced 
@@ -322,6 +323,16 @@ typedef struct {
        /* sockets internals */
        int                             lowat;
 
+                                       /* this buffer holds a record packet -mostly used for
+                                        * non blocking IO.
+                                        */
+       opaque                          recv_buffer_data[MAX_RECV_SIZE];
+       int                             recv_buffer_data_size;
+
+                                       /* 0 if no peeked data was kept, 1 otherwise.
+                                        */
+       int                             have_peeked_data;
+
        /* gdbm */
        char*                           db_name;
        int                             expire_time;
@@ -352,7 +363,6 @@ typedef struct {
        int                             peer_pk_algorithm;
        /* holds the username got in the srp tls extension
         */
-       opaque                          srp_username[MAX_SRP_USERNAME];
 } GNUTLS_INTERNALS;
 
 struct GNUTLS_STATE_INT {
index b0bb5a646dbad46b67ca578780812768c406ca5e..22bdf2bd7d6911a76a47fa7869f8471bd309203c 100644 (file)
 #include "gnutls_record.h"
 #include "gnutls_datum.h"
 
-#ifdef HAVE_ERRNO_H
-# include <errno.h>
-#endif
-
-#ifndef EAGAIN
-# define EAGAIN EWOULDBLOCK
-#endif
 
 GNUTLS_Version gnutls_get_current_version(GNUTLS_STATE state) {
 GNUTLS_Version ver;
@@ -61,7 +54,9 @@ void _gnutls_set_current_version(GNUTLS_STATE state, GNUTLS_Version version) {
   * Used to set the lowat value in order for select to check
   * if there are pending data to socket buffer. Used only   
   * if you have changed the default low water value (default is 1).
-  * Normally you will not need that function.
+  * Normally you will not need that function. 
+  * If you plan to use non standard recv() function you should set
+  * this to zero.
   **/
 int gnutls_set_lowat(GNUTLS_STATE state, int num) {
        state->gnutls_internals.lowat = num;
@@ -449,7 +444,7 @@ ssize_t gnutls_send_int(SOCKET cd, GNUTLS_STATE state, ContentType type, Handsha
                WRITEuint16( cipher_size-RECORD_HEADER_SIZE, &headers[3]);
                memcpy( cipher, headers, RECORD_HEADER_SIZE);
 
-               if (_gnutls_Write(cd, cipher, cipher_size, flags) != cipher_size) {
+               if (_gnutls_write(cd, cipher, cipher_size, flags) != cipher_size) {
                        state->gnutls_internals.valid_connection = VALID_FALSE;
                        state->gnutls_internals.resumable = RESUME_FALSE;
                        gnutls_assert();
@@ -476,12 +471,10 @@ ssize_t gnutls_send_int(SOCKET cd, GNUTLS_STATE state, ContentType type, Handsha
                cipher_size = _gnutls_encrypt( state, &data[i*Size], Size, &cipher, type);
                if (cipher_size<=0) return cipher_size;
 
-               WRITEuint16( cipher_size, &headers[3]);
-
+               WRITEuint16( cipher_size-RECORD_HEADER_SIZE, &headers[3]);
                memcpy( cipher, headers, RECORD_HEADER_SIZE);
 
-               cipher_size += RECORD_HEADER_SIZE;
-               if (_gnutls_Write(cd, cipher, cipher_size, flags) != cipher_size) {
+               if (_gnutls_write(cd, cipher, cipher_size, flags) != cipher_size) {
                        state->gnutls_internals.valid_connection = VALID_FALSE;
                        state->gnutls_internals.resumable = RESUME_FALSE;
                        gnutls_assert();
@@ -519,17 +512,6 @@ ssize_t _gnutls_send_change_cipher_spec(SOCKET cd, GNUTLS_STATE state)
 
 }
 
-#define RCVLOWAT state->gnutls_internals.lowat /* this is the default for TCP - just don't change that! */
-
-static int _gnutls_clear_peeked_data( SOCKET cd, GNUTLS_STATE state) {
-char peekdata;
-
-       /* this was already read by using MSG_PEEK - so it shouldn't fail */
-       _gnutls_Read( cd, &peekdata, RCVLOWAT, 0); 
-
-       return 0;
-}
-
 #define CHECK_RECORD_VERSION
 
 /* This function behave exactly like read(). The only difference is 
@@ -537,7 +519,7 @@ char peekdata;
  * send (if called by the user the Content is Userdata only)
  * It is intended to receive data, under the current state.
  * flags is the sockets flags to use. Currently only MSG_DONTWAIT is
- * supported.
+ * supported, and should be used together with MSG_WAITALL.
  */
 ssize_t gnutls_recv_int(SOCKET cd, GNUTLS_STATE state, ContentType type, HandshakeType htype, char *data, size_t sizeofdata, int flags)
 {
@@ -548,20 +530,23 @@ ssize_t gnutls_recv_int(SOCKET cd, GNUTLS_STATE state, ContentType type, Handsha
        ContentType recv_type;
        uint16 length;
        uint8 *ciphertext;
+       uint8 *recv_data;
        int ret = 0;
        int header_size = RECORD_HEADER_SIZE;
+
+
+
        /* If we have enough data in the cache do not bother receiving
         * a new packet. (in order to flush the cache)
         */
        if ( (type == GNUTLS_APPLICATION_DATA || type == GNUTLS_HANDSHAKE) && gnutls_getDataBufferSize(type, state) > 0) {
                ret = gnutls_getDataFromBuffer(type, state, data, sizeofdata);
 
-               if (type==GNUTLS_APPLICATION_DATA) {
-                       /* if the buffer just got empty */
-                       if (gnutls_getDataBufferSize(type, state)==0) {
-                               _gnutls_clear_peeked_data( cd, state);
-                       }
+               /* if the buffer just got empty */
+               if (gnutls_getDataBufferSize(type, state)==0) {
+                       _gnutls_clear_peeked_data( cd, state);
                }
+
                return ret;
        }
 
@@ -572,8 +557,8 @@ ssize_t gnutls_recv_int(SOCKET cd, GNUTLS_STATE state, ContentType type, Handsha
        /* in order for GNUTLS_E_AGAIN to be returned the socket
         * must be set to non blocking mode
         */
-       if ( (ret = _gnutls_Read(cd, headers, RECORD_HEADER_SIZE, MSG_PEEK|flags)) != RECORD_HEADER_SIZE) {
-               if (ret==(0-EAGAIN)) return GNUTLS_E_AGAIN;
+       if ( (ret = _gnutls_read_buffered(cd, state, headers, RECORD_HEADER_SIZE, flags, -1)) != RECORD_HEADER_SIZE) {
+               if (ret==GNUTLS_E_AGAIN) return ret;
 
                state->gnutls_internals.valid_connection = VALID_FALSE;
                if (type==GNUTLS_ALERT) return 0; /* we were expecting close notify */
@@ -648,15 +633,14 @@ ssize_t gnutls_recv_int(SOCKET cd, GNUTLS_STATE state, ContentType type, Handsha
                return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
        }
 
-       ciphertext = gnutls_malloc(length+header_size);
+       recv_data = gnutls_malloc(length+header_size);
+
+       /* check if we have that data into buffer. 
+        */
+       if ( (ret = _gnutls_read_buffered(cd, state, recv_data, header_size+length, flags, recv_type)) != length+header_size) {
+               gnutls_free(recv_data);
+               if (ret==GNUTLS_E_AGAIN) return ret;
 
-/* check if we have that data into buffer. This seems to be
- * expensive - but this is the only way to handle Non Blocking IO.
- */
-       if ( (ret = _gnutls_Read(cd, ciphertext, header_size+length, MSG_PEEK|flags)) != length+header_size) {
-               gnutls_free(ciphertext);
-               
-               if (ret==(0-EAGAIN)) return GNUTLS_E_AGAIN;
                state->gnutls_internals.valid_connection = VALID_FALSE;
                state->gnutls_internals.resumable = RESUME_FALSE;
                gnutls_assert();
@@ -666,42 +650,8 @@ ssize_t gnutls_recv_int(SOCKET cd, GNUTLS_STATE state, ContentType type, Handsha
 /* ok now we are sure that we can read all the data - so
  * move on !
  */
-       if (_gnutls_Read(cd, headers, header_size, 0)!=header_size) {  /* read and clear the headers - again! */
-               gnutls_free(ciphertext);
-               state->gnutls_internals.valid_connection = VALID_FALSE;
-               state->gnutls_internals.resumable = RESUME_FALSE;
-               gnutls_assert();
-               return GNUTLS_E_UNKNOWN_ERROR;
-       }
-
-/* Read the whole packet - again? 
- * Here we keep RCVLOWAT bytes in the TCP buffers, only for
- * APPLICATION_DATA data.
- */    
-       if ( type==GNUTLS_APPLICATION_DATA && type==recv_type) {
-               /* get the data - but do not free the buffer in the kernel */
-               ret = _gnutls_Read(cd, ciphertext, length-RCVLOWAT, 0);
-               if (ret>=0)
-                       ret += _gnutls_Read(cd, &ciphertext[length-RCVLOWAT], RCVLOWAT, MSG_PEEK);
-
-       } else { /* our - internal data */
-               ret = _gnutls_Read(cd, ciphertext, length, 0);
-       }
-
-       /* Oooops... very rare case since we know that the system HAD 
-        * received that data.
-        */
-       if (ret != length) {
-#ifdef RECORD_DEBUG
-               _gnutls_log( "Record: Received packet with length: %d\nExpected %d\n", ret, length);
-#endif
-               gnutls_free(ciphertext);
-               state->gnutls_internals.valid_connection = VALID_FALSE;
-               state->gnutls_internals.resumable = RESUME_FALSE;
-               gnutls_assert();
-               return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
-       }
-
+       _gnutls_read_clear_buffer( state);
+       ciphertext = &recv_data[header_size];
        
        /* decrypt the data we got
         */
@@ -721,7 +671,7 @@ ssize_t gnutls_recv_int(SOCKET cd, GNUTLS_STATE state, ContentType type, Handsha
                state->gnutls_internals.valid_connection = VALID_FALSE;
                state->gnutls_internals.resumable = RESUME_FALSE;
                gnutls_assert();
-               gnutls_free(ciphertext);
+               gnutls_free(recv_data);
                return tmplen;
        }
 
@@ -732,7 +682,7 @@ ssize_t gnutls_recv_int(SOCKET cd, GNUTLS_STATE state, ContentType type, Handsha
                _gnutls_log( "Record: ChangeCipherSpec Packet was received\n");
 #endif
 
-               gnutls_free(ciphertext);
+               gnutls_free(recv_data);
 
                if (tmplen!=sizeofdata) { /* sizeofdata should be 1 */
                        gnutls_assert();
@@ -758,7 +708,7 @@ ssize_t gnutls_recv_int(SOCKET cd, GNUTLS_STATE state, ContentType type, Handsha
                return GNUTLS_E_RECORD_LIMIT_REACHED;
        }
 
-       gnutls_free(ciphertext);
+       gnutls_free(recv_data);
 
        if ( (recv_type == type) && (type == GNUTLS_APPLICATION_DATA || type == GNUTLS_HANDSHAKE)) {
                gnutls_insertDataBuffer(type, state, (void *) tmpdata, tmplen);
@@ -782,9 +732,8 @@ ssize_t gnutls_recv_int(SOCKET cd, GNUTLS_STATE state, ContentType type, Handsha
                                        gnutls_bye(cd, state, 1);
                                
                                gnutls_free(tmpdata);
-                               
+
                                return 0; /* EOF */
-/*                             return GNUTLS_E_CLOSURE_ALERT_RECEIVED; */
                        } else {
                        
                                /* if the alert is FATAL or WARNING
@@ -810,7 +759,7 @@ ssize_t gnutls_recv_int(SOCKET cd, GNUTLS_STATE state, ContentType type, Handsha
                        gnutls_assert();
        
                        gnutls_free(tmpdata);
-                       
+
                        return GNUTLS_E_UNEXPECTED_PACKET;
                case GNUTLS_APPLICATION_DATA:
 #if 0                  
@@ -830,7 +779,12 @@ ssize_t gnutls_recv_int(SOCKET cd, GNUTLS_STATE state, ContentType type, Handsha
 
                        break;
                case GNUTLS_HANDSHAKE:
-                       /* This is only legal if HELLO_REQUEST is received */
+                       /* This is only legal if HELLO_REQUEST is received - and we are a client */
+                       if (htype!=GNUTLS_HELLO_REQUEST && state->security_parameters.entity==GNUTLS_SERVER) {
+                               gnutls_assert();
+                               gnutls_free( tmpdata);
+                               return GNUTLS_E_UNEXPECTED_PACKET;
+                       }
 
                        break;
                default:
@@ -846,13 +800,12 @@ ssize_t gnutls_recv_int(SOCKET cd, GNUTLS_STATE state, ContentType type, Handsha
        /* Get Application data from buffer */
        if ((type == GNUTLS_APPLICATION_DATA || type == GNUTLS_HANDSHAKE) && (recv_type == type)) {
                ret = gnutls_getDataFromBuffer(type, state, data, sizeofdata);
-               if (type==GNUTLS_APPLICATION_DATA) {
-                       /* if the buffer just got empty */
-                       if (gnutls_getDataBufferSize(type, state)==0) {
-                               _gnutls_clear_peeked_data( cd, state);
-                       }
 
+               /* if the buffer just got empty */
+               if (gnutls_getDataBufferSize(type, state)==0) {
+                       _gnutls_clear_peeked_data( cd, state);
                }
+
                gnutls_free(tmpdata);
        } else {
                if (recv_type == GNUTLS_HANDSHAKE) {
@@ -861,7 +814,7 @@ ssize_t gnutls_recv_int(SOCKET cd, GNUTLS_STATE state, ContentType type, Handsha
                        if (ret < 0) {
                                gnutls_assert();
                        } else /* inform the caller */
-                               ret = GNUTLS_E_GOT_HELLO_REQUEST;
+                               ret = GNUTLS_E_REHANDSHAKE;
                } else {
                        gnutls_assert();
                        ret = GNUTLS_E_UNEXPECTED_PACKET; 
index d3377609de27483b41b77c44fedbf8a96acc58aa..5c219d8362e87dcd52fb297f8dd5ea8d21a2afb2 100644 (file)
--- a/src/cli.c
+++ b/src/cli.c
@@ -288,8 +288,8 @@ int main(int argc, char** argv)
 
                if (FD_ISSET(sd, &rset)) {
                        bzero(buffer, MAX_BUF+1);
-
                        ret = gnutls_read(sd, state, buffer, MAX_BUF);
+
                        /* remove new line */
 
                        if (gnutls_is_fatal_error(ret) == 1 || ret==0) {
@@ -304,8 +304,8 @@ int main(int argc, char** argv)
                        } else {
                                if (ret==GNUTLS_E_WARNING_ALERT_RECEIVED || ret==GNUTLS_E_FATAL_ALERT_RECEIVED)
                                        printf("* Received alert [%d]\n", gnutls_get_last_alert(state));
-                               if (ret==GNUTLS_E_GOT_HELLO_REQUEST)
-                                       printf("* Received HelloRequest message (server asked to rehandshake)\n");
+                               if (ret==GNUTLS_E_REHANDSHAKE)
+                                       printf("* Rehandshake was performed\n");
 
                                if (ret > 0) {
                                        printf("- Received[%d]: ", ret);