]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
added max_record_size extension
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Tue, 6 Nov 2001 12:57:56 +0000 (12:57 +0000)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Tue, 6 Nov 2001 12:57:56 +0000 (12:57 +0000)
16 files changed:
NEWS
configure.in
lib/Makefile.am
lib/ext_dnsname.c
lib/ext_max_record.c [new file with mode: 0644]
lib/ext_max_record.h [new file with mode: 0644]
lib/ext_srp.c
lib/gnutls.h.in
lib/gnutls_constate.c
lib/gnutls_errors.c
lib/gnutls_errors_int.h
lib/gnutls_extensions.c
lib/gnutls_handshake.c
lib/gnutls_int.h
lib/gnutls_record.c
src/cli.c

diff --git a/NEWS b/NEWS
index 73307d64c8264187c4d9e1e003547986385bea85..f8baf05d435a5399d04635e3b3eb567253414710 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,8 @@ Version 0.2.11
    an alert to the peer.
 - Made receive buffer dynamic. Normaly if no large chunks are receive
   it occupies less space.
+- Added max_record_size extension
+- Bugfixes session handling
 
 Version 0.2.10 (5/11/2001)
 - Corrected bugs and improved non blocking IO
index 8aae057b4572874154dc9d987dc6beb5bf4792d8..682ef32ad1c439de592a3c4539ba6583be9c97e9 100644 (file)
@@ -11,7 +11,7 @@ AC_DEFINE_UNQUOTED(T_OS, "$target_os")
 
 GNUTLS_MAJOR_VERSION=0
 GNUTLS_MINOR_VERSION=2
-GNUTLS_MICRO_VERSION=10
+GNUTLS_MICRO_VERSION=11
 GNUTLS_VERSION=$GNUTLS_MAJOR_VERSION.$GNUTLS_MINOR_VERSION.$GNUTLS_MICRO_VERSION
 
 AC_DEFINE_UNQUOTED(GNUTLS_VERSION, "$GNUTLS_VERSION")
index 4271b123f3a1e95d9a7f908a35b58df8b4801e0c..5bfbd22eaff8ad1264f6cd964b7abc7c2eaac823 100644 (file)
@@ -17,7 +17,7 @@ EXTRA_DIST = debug.h gnutls_compress.h defines.h pkcs1.asn pkix.asn \
        ext_dnsname.h gnutls_pk.h gnutls_record.h gnutls_cert.h \
        gnutls_privkey.h gnutls_constate.h gnutls_global.h x509_verify.h \
        gnutls_sig.h gnutls_mem.h x509_extensions.h gnutls_ui.h \
-       gnutls-api.tex io_debug.h
+       gnutls-api.tex io_debug.h ext_max_record.h
 
 lib_LTLIBRARIES = libgnutls.la
 
@@ -35,7 +35,7 @@ COBJECTS = gnutls_record.c gnutls_compress.c debug.c \
        gnutls_global.c gnutls_privkey.c gnutls_constate.c gnutls_anon_cred.c \
        x509_sig_check.c pkix_asn1_tab.c pkcs1_asn1_tab.c gnutls_mem.c \
        x509_extensions.c auth_x509.c gnutls_ui.c gnutls_sig.c auth_dhe_rsa.c \
-       gnutls_dh_primes.c
+       gnutls_dh_primes.c ext_max_record.c
 
 libgnutls_la_SOURCES = $(COBJECTS)
 
index 3760fe29a4074c1fc6690a72e911dffc1e2b25fc..f20f16779ec5bb766168223c6da26a49fa8f6cb4 100644 (file)
@@ -74,6 +74,7 @@ int _gnutls_name_ind_send_params( GNUTLS_STATE state, opaque** data) {
                        case GNUTLS_DNSNAME:
                                if ( (len = strlen(state->security_parameters.extensions.name.dnsname)) > 0) { /* send dnsname */
                                        (*data) = gnutls_malloc(len+3); /* hold the size and the type also */
+                                       if (*data==NULL) return GNUTLS_E_MEMORY_ERROR;
                                        
                                        WRITEuint16( len+1, *data);
                                        (*data)[2] = 0;
diff --git a/lib/ext_max_record.c b/lib/ext_max_record.c
new file mode 100644 (file)
index 0000000..09f269d
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ *      Copyright (C) 2001 Nikos Mavroyanopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * GNUTLS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GNUTLS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "gnutls_int.h"
+#include "gnutls_errors.h"
+#include "gnutls_num.h"
+#include "ext_max_record.h"
+
+/* 
+ * In case of a server: if a MAX_RECORD_SIZE extension type is received then it stores
+ * into the state the new value. The server may use gnutls_get_max_record_size(),
+ * in order to access it.
+ *
+ * In case of a client: If a different max record size (than the default) has
+ * been specified then it sends the extension.
+ *
+ */
+
+int _gnutls_max_record_recv_params( GNUTLS_STATE state, const opaque* data, int data_size) {
+       size_t new_size;
+       
+       if (state->security_parameters.entity == GNUTLS_SERVER) {
+               if (data_size > 0) {
+                       
+                       if ( data_size != 1) {
+                               gnutls_assert();
+                               return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+                       }
+                       
+                       new_size = _gnutls_mre_num2record(data[0]);
+
+                       if (new_size < 0) {
+                               gnutls_assert();
+                               return new_size;
+                       }
+
+                       state->security_parameters.max_record_size = new_size;
+               }
+       } else { /* CLIENT SIDE - we must check if the sent record size is the right one 
+                 */
+               if (data_size > 0) {
+
+                       if ( data_size != 1) {
+                               gnutls_assert();
+                               return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+                       }
+                       
+                       new_size = _gnutls_mre_num2record(data[0]);
+
+fprintf(stderr, "RECEIVING IT %d\n", new_size);
+
+                       if (new_size < 0 || new_size != state->security_parameters.max_record_size) {
+                               gnutls_assert();
+                               return GNUTLS_E_ILLEGAL_PARAMETER;
+                       }
+
+               }
+       
+       
+       }
+       
+       return 0;
+}
+
+/* returns data_size or a negative number on failure
+ * data is allocated localy
+ */
+int _gnutls_max_record_send_params( GNUTLS_STATE state, opaque** data) {
+       uint16 len;
+       /* this function sends the client extension data (dnsname) */
+       if (state->security_parameters.entity == GNUTLS_CLIENT) {
+
+               if (state->security_parameters.max_record_size != DEFAULT_MAX_RECORD_SIZE) {
+                       len = 1;
+                       (*data) = gnutls_malloc(len); /* hold the size and the type also */
+                       if (*data==NULL) return GNUTLS_E_MEMORY_ERROR;
+                       
+                       (*data)[0] = _gnutls_mre_record2num( state->security_parameters.max_record_size);
+                       return len;
+               }
+
+       } else { /* server side */
+
+               if (state->security_parameters.max_record_size != DEFAULT_MAX_RECORD_SIZE) {
+                       len = 1;
+                       (*data) = gnutls_malloc(len+2); /* hold the size and the type also */
+                       if (*data==NULL) return GNUTLS_E_MEMORY_ERROR;
+                       
+                       (*data)[0] = _gnutls_mre_record2num( state->security_parameters.max_record_size);
+                       return len;
+               }       
+       
+       
+       }
+
+       *data = NULL;
+       return 0;
+}
+
+/* Maps record size to numbers according to the
+ * extensions draft.
+ */
+int _gnutls_mre_num2record( int num) {
+       switch( num) {
+       case 1:
+               return 512;
+       case 2:
+               return 1024;
+       case 3:
+               return 2048;
+       case 4:
+               return 4096;
+       default:
+               return GNUTLS_E_ILLEGAL_PARAMETER;
+       }
+}
+
+int _gnutls_mre_record2num( int record_size) {
+       switch(record_size) {
+       case 512:
+               return 1;
+       case 1024:
+               return 2;
+       case 2048:
+               return 3;
+       case 4096:
+               return 4;
+       default:
+               return GNUTLS_E_ILLEGAL_PARAMETER;
+       }
+
+}
diff --git a/lib/ext_max_record.h b/lib/ext_max_record.h
new file mode 100644 (file)
index 0000000..47f7248
--- /dev/null
@@ -0,0 +1,7 @@
+/* Maps record size to numbers according to the
+ * extensions draft.
+ */
+int _gnutls_mre_num2record( int num);
+int _gnutls_mre_record2num( int record_size);
+int _gnutls_max_record_recv_params( GNUTLS_STATE state, const opaque* data, int data_size);
+int _gnutls_max_record_send_params( GNUTLS_STATE state, opaque** data);
index eb373415f173efbaf91d19c17c0897f72b134416..8fe9d6e771990cef0a7ff43541754800e1310dd0 100644 (file)
@@ -74,6 +74,8 @@ int _gnutls_srp_send_params( GNUTLS_STATE state, opaque** data) {
                if (cred->username!=NULL) { /* send username */
                        len = strlen(cred->username);
                        (*data) = gnutls_malloc(len+1); /* hold the size also */
+                       if (*data==NULL) return GNUTLS_E_MEMORY_ERROR;
+                       
                        (*data)[0] = len;
                        memcpy( &(*data)[1], cred->username, len);
                        return len + 1;
index 4f074425618c27f792e96e2b15eb8fc07a7f0d1d..4516f0a22bb4b402e3dbdaa7157db228ac768fcf 100644 (file)
@@ -237,5 +237,6 @@ typedef void (*LOG_FUNC)( const char*);
 void gnutls_set_push_func( GNUTLS_STATE, PUSH_FUNC push_func);
 void gnutls_set_pull_func( GNUTLS_STATE, PULL_FUNC pull_func);
 
-
+size_t gnutls_get_max_record_size( GNUTLS_STATE state);
+size_t gnutls_set_max_record_size( GNUTLS_STATE state, size_t size);
 
index a2784e759bfe96ce2716c3f809a44568caeabb30..ef56c131323ced039765bb6c382818f06c054130 100644 (file)
@@ -151,6 +151,7 @@ int _gnutls_set_write_keys(GNUTLS_STATE state)
        memcpy( dst->session_id, src->session_id, TLS_MAX_SESSION_ID_SIZE); \
        dst->session_id_size = src->session_id_size; \
        dst->timestamp = src->timestamp; \
+       dst->max_record_size = src->max_record_size; \
        memcpy( &dst->extensions, &src->extensions, sizeof(TLSExtensions));
        
 static void _gnutls_cpy_read_security_parameters( SecurityParameters * dst, SecurityParameters* src) {
index ef0710825f95356d6ed82d50b539eca42d995af2..f8c80e266b480d9b28fa2011276b08241d6ef88c 100644 (file)
@@ -89,6 +89,7 @@ static gnutls_error_entry error_algorithms[] = {
        GNUTLS_ERROR_ENTRY( GNUTLS_E_DB_ERROR, 1),
        GNUTLS_ERROR_ENTRY( GNUTLS_E_INVALID_PARAMETERS, 1),
        GNUTLS_ERROR_ENTRY( GNUTLS_E_INVALID_REQUEST, 1),
+       GNUTLS_ERROR_ENTRY( GNUTLS_E_ILLEGAL_PARAMETER, 1),
        {0}
 };
 
index 77cebf04a533791252cbd580276a654916068848..4426100b5c4d771d978074334c2235b0a32ad0a5 100644 (file)
@@ -55,5 +55,6 @@
 #define GNUTLS_E_INTERRUPTED -52
 #define GNUTLS_E_PUSH_ERROR -53
 #define GNUTLS_E_PULL_ERROR -54
+#define GNUTLS_E_ILLEGAL_PARAMETER -55
 
 #define GNUTLS_E_UNIMPLEMENTED_FEATURE -250
index 636fbb8f0c0dd1b70bfcc0cac8de374b50d69af2..9f2f6f81f37265fc0106fe323683f736b7a2e69a 100644 (file)
@@ -23,6 +23,7 @@
 #include "gnutls_errors.h"
 #include "ext_srp.h"
 #include "ext_dnsname.h"
+#include "ext_max_record.h"
 #include "gnutls_num.h"
 
 /* Key Exchange Section */
@@ -40,6 +41,7 @@ typedef struct {
 static gnutls_extension_entry extensions[] = {
        GNUTLS_EXTENSION_ENTRY( GNUTLS_EXTENSION_SRP, _gnutls_srp_recv_params, _gnutls_srp_send_params),
        GNUTLS_EXTENSION_ENTRY( GNUTLS_EXTENSION_DNSNAME, _gnutls_name_ind_recv_params, _gnutls_name_ind_send_params),
+       GNUTLS_EXTENSION_ENTRY( GNUTLS_EXTENSION_MAX_RECORD_SIZE, _gnutls_max_record_recv_params, _gnutls_max_record_send_params),
        {0}
 };
 
index 2b367bc67fe73dac74fb27aa79f4b7ebacaf0aa0..9dbc9c6c5e4dc3478ad0429fa0678e4aa62b08a9 100644 (file)
@@ -1270,6 +1270,24 @@ int ret;
        return ret;
 }
 
+/* Sends the appropriate alert, depending
+ * on the error message.
+ */
+static int _gnutls_handshake_send_appropriate_alert( SOCKET cd, GNUTLS_STATE state, int err) {
+int ret;
+       switch (err) { /* send appropriate alert */
+               case GNUTLS_E_ILLEGAL_PARAMETER:
+                       ret = gnutls_send_alert(cd, state, GNUTLS_FATAL, GNUTLS_ILLEGAL_PARAMETER);
+                       break;
+               default:
+                       ret = gnutls_send_alert(cd, state, GNUTLS_FATAL, GNUTLS_HANDSHAKE_FAILURE);
+                       break;
+       }
+
+       return ret;
+}
+
+
 /* RECEIVE A HELLO MESSAGE. This should be called from gnutls_recv_handshake_int only if a
  * hello message is expected. It uses the security_parameters.current_cipher_suite
  * and gnutls_internals.compression_method.
@@ -1282,7 +1300,7 @@ int _gnutls_recv_hello(SOCKET cd, GNUTLS_STATE state, char *data,
        if (state->security_parameters.entity == GNUTLS_CLIENT) {
                ret = _gnutls_read_server_hello(state, data, datalen);
                if (ret < 0) {
-                       gnutls_send_alert(cd, state, GNUTLS_FATAL, GNUTLS_HANDSHAKE_FAILURE);   /* send handshake failure */
+                       _gnutls_handshake_send_appropriate_alert( cd, state, ret);
                        gnutls_assert();
                        return ret;
                }
@@ -1290,7 +1308,7 @@ int _gnutls_recv_hello(SOCKET cd, GNUTLS_STATE state, char *data,
 
                ret = _gnutls_read_client_hello(state, data, datalen);
                if (ret < 0) {
-                       gnutls_send_alert(cd, state, GNUTLS_FATAL, GNUTLS_HANDSHAKE_FAILURE);   /* send handshake failure */
+                       _gnutls_handshake_send_appropriate_alert( cd, state, ret);
                        gnutls_assert();
                        return ret;
                }
@@ -1405,6 +1423,7 @@ int gnutls_handshake(SOCKET cd, GNUTLS_STATE state)
                if (gnutls_is_fatal_error(ret)==0) return ret; \
                gnutls_assert(); \
                ERR( str, ret); \
+               _gnutls_handshake_send_appropriate_alert( cd, state, ret); \
                gnutls_clear_handshake_buffer(state); \
                return ret; \
        }
@@ -1786,28 +1805,9 @@ int _gnutls_generate_session_id(char *session_id, uint8 * len)
        return 0;
 }
 
-#define RENEGOTIATE
 int _gnutls_recv_hello_request(SOCKET cd, GNUTLS_STATE state, void *data,
                               uint32 data_size)
 {
-#ifndef RENEGOTIATE
-       int ret;
-
-       /* only client should receive that */
-       if (state->security_parameters.entity == GNUTLS_SERVER)
-               return GNUTLS_E_UNEXPECTED_PACKET;
-
-       /* just return an alert that we don't like that */
-       ret =
-           gnutls_send_alert(cd, state, GNUTLS_WARNING,
-                             GNUTLS_NO_RENEGOTIATION);
-       if (ret < 0) {
-               gnutls_assert();
-               return ret;
-       }
-       return 0;
-
-#else  /* this does seem to work - now */
        uint8 type;
 
        if (state->security_parameters.entity == GNUTLS_SERVER) {
@@ -1825,7 +1825,6 @@ int _gnutls_recv_hello_request(SOCKET cd, GNUTLS_STATE state, void *data,
                gnutls_assert();
                return GNUTLS_E_UNEXPECTED_PACKET;
        }
-#endif
 }
 
 /* This function will remove algorithms that are not supported by
index 8e47874fed41250b97c04dbd209b75a6e18d8a8f..ac51a5dec6da81626deb0d58c3ef4b5d26c61cea 100644 (file)
 
 #define MAX_DNSNAME_SIZE 256
 
+/* The initial size of the receive
+ * buffer size. This will grow if larger
+ * packets are received.
+ */
+#define INITIAL_RECV_BUFFER_SIZE 256
+
 /* the default for TCP */
 #define DEFAULT_LOWAT 1
 
@@ -70,7 +76,8 @@
 #define DEFAULT_EXPIRE_TIME 3600
 
 /* the maximum size of encrypted packets */
-#define MAX_ENC_LEN 16384
+#define DEFAULT_MAX_RECORD_SIZE 16384
+#define MAX_ENC_LEN state->security_parameters.max_record_size
 #define RECORD_HEADER_SIZE 5
 #define MAX_RECV_SIZE 18432+RECORD_HEADER_SIZE         /* 2^14+2048+RECORD_HEADER_SIZE */
 
@@ -133,7 +140,7 @@ typedef struct {
 /* STATE */
 typedef enum ConnectionEnd { GNUTLS_SERVER=1, GNUTLS_CLIENT } ConnectionEnd;
 typedef enum BulkCipherAlgorithm { GNUTLS_NULL_CIPHER=1, GNUTLS_ARCFOUR, GNUTLS_3DES_CBC, GNUTLS_RIJNDAEL_CBC, GNUTLS_TWOFISH_CBC, GNUTLS_RIJNDAEL256_CBC } BulkCipherAlgorithm;
-typedef enum Extensions { GNUTLS_EXTENSION_DNSNAME=0, GNUTLS_EXTENSION_SRP=6 } Extensions;
+typedef enum Extensions { GNUTLS_EXTENSION_DNSNAME=0, GNUTLS_EXTENSION_MAX_RECORD_SIZE=1, GNUTLS_EXTENSION_SRP=6 } Extensions;
 typedef enum KXAlgorithm { GNUTLS_KX_RSA=1, GNUTLS_KX_DHE_DSS, GNUTLS_KX_DHE_RSA, GNUTLS_KX_DH_DSS, GNUTLS_KX_DH_RSA, GNUTLS_KX_DH_ANON, GNUTLS_KX_SRP } KXAlgorithm;
 typedef enum CredType { GNUTLS_X509PKI=1, GNUTLS_ANON, GNUTLS_SRP } CredType;
 typedef enum CipherType { CIPHER_STREAM, CIPHER_BLOCK } CipherType;
@@ -280,6 +287,7 @@ typedef struct {
        uint8                   session_id_size;
        time_t                  timestamp;
        TLSExtensions           extensions;
+       uint16                  max_record_size;
 } SecurityParameters;
 
 /* This structure holds the generated keys
index 31e42f707bced4d1cd9f588216a4fd71b7e82ccb..a95eb8f21c34939df047bee8a6286b7bcc2b9443 100644 (file)
@@ -34,6 +34,7 @@
 #include "gnutls_num.h"
 #include "gnutls_record.h"
 #include "gnutls_datum.h"
+#include "ext_max_record.h"
 
 GNUTLS_Version gnutls_get_current_version(GNUTLS_STATE state) {
 GNUTLS_Version ver;
@@ -114,7 +115,11 @@ int gnutls_init(GNUTLS_STATE * state, ConnectionEnd con_end)
         * This is allocated in order to avoid small messages, makeing
         * the receive procedure slow.
         */
-       (*state)->gnutls_internals.recv_buffer.data = gnutls_malloc(256);
+       (*state)->gnutls_internals.recv_buffer.data = gnutls_malloc(INITIAL_RECV_BUFFER_SIZE);
+       
+       /* set the default maximum record size for TLS
+        */
+       (*state)->security_parameters.max_record_size = DEFAULT_MAX_RECORD_SIZE;
 
        /* everything else not initialized here is initialized
         * as NULL or 0. This is why calloc is used.
@@ -1090,3 +1095,48 @@ ssize_t gnutls_write(SOCKET cd, GNUTLS_STATE state, const void *data, size_t siz
 ssize_t gnutls_read(SOCKET cd, GNUTLS_STATE state, void *data, size_t sizeofdata) {
        return gnutls_recv_int( cd, state, GNUTLS_APPLICATION_DATA, -1, data, sizeofdata);
 }
+
+/**
+  * gnutls_get_max_record_size - returns the maximum record size
+  * @state: is a &GNUTLS_STATE structure.
+  *
+  * This function returns the maximum record size in this connection.
+  * The maximum record size is negotiated by the client after the
+  * first handshake message.
+  *
+  **/
+size_t gnutls_get_max_record_size( GNUTLS_STATE state) {
+       return state->security_parameters.max_record_size;
+}
+
+
+/**
+  * gnutls_set_max_record_size - sets the maximum record size
+  * @state: is a &GNUTLS_STATE structure.
+  * @size: is the new size
+  *
+  * This function sets the maximum record size in this connection.
+  * This property can only be set to clients. The server may
+  * choose not to accept the requested size.
+  *
+  * Acceptable values are 2^9, 2^10, 2^11 and 2^12.
+  * Returns the new record size.
+  *
+  **/
+size_t gnutls_set_max_record_size( GNUTLS_STATE state, size_t size) {
+size_t new_size;
+
+       if (state->security_parameters.entity==GNUTLS_SERVER)
+               return GNUTLS_E_INVALID_REQUEST;
+
+       new_size = _gnutls_mre_record2num( size);
+
+       if (new_size < 0) {
+               gnutls_assert();
+               return new_size;
+       }
+       
+       state->security_parameters.max_record_size = size;
+
+       return state->security_parameters.max_record_size;
+}
index 1e94b599a1dac8d525ab46ce0f0db45d22ca6754..886cd61cdb695b991e27b198fc98e4a0536d9b55 100644 (file)
--- a/src/cli.c
+++ b/src/cli.c
@@ -30,6 +30,8 @@
 #include "../lib/gnutls.h"
 #include <sys/time.h>
 
+#include <dmalloc.h>
+
 #ifndef SHUT_WR
 # define SHUT_WR 1
 #endif