]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Increase the limit of TLS PSK usernames from 128 to 65535 characters
authorZoltan Fridrich <zfridric@redhat.com>
Tue, 10 May 2022 13:20:45 +0000 (15:20 +0200)
committerZoltan Fridrich <zfridric@redhat.com>
Fri, 8 Jul 2022 08:12:01 +0000 (10:12 +0200)
Co-authored-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Zoltan Fridrich <zfridric@redhat.com>
15 files changed:
NEWS
lib/auth.c
lib/auth/dhe_psk.c
lib/auth/psk.c
lib/auth/psk.h
lib/auth/rsa_psk.c
lib/auth/srp_kx.c
lib/auth/srp_kx.h
lib/ext/pre_shared_key.c
lib/ext/srp.c
lib/gnutls_int.h
lib/handshake-checks.c
lib/psk.c
lib/session_pack.c
lib/state.c

diff --git a/NEWS b/NEWS
index 034b9ced84c6e444daa1c14eb20e5993e4b598df..0c0835e4f67ed317fd1248827438fff723358049 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,9 @@ See the end for copying conditions.
 ** libgnutls: gnutls_hkdf_expand now only accepts LENGTH argument less than or
    equal to 255 times hash digest size, to comply with RFC 5869 2.3.
 
+** libgnutls: Length limit for TLS PSK usernames has been increased
+   from 128 to 65535 characters (#1323).
+
 ** API and ABI modifications:
 gnutls_fips140_run_self_tests: New function
 
index 1a341c78f68a4ee3263b44681185f9a1f7da0c3d..7c58bd83ecc6999a8acf317d2b638967ae769461 100644 (file)
@@ -28,6 +28,7 @@
 #include "algorithms.h"
 #include <auth/cert.h>
 #include <auth/psk.h>
+#include <auth/srp_kx.h>
 #include <auth/anon.h>
 #include <datum.h>
 
@@ -327,6 +328,16 @@ void _gnutls_free_auth_info(gnutls_session_t session)
 
        switch (session->key.auth_info_type) {
        case GNUTLS_CRD_SRP:
+               {
+                       srp_server_auth_info_t info =
+                           _gnutls_get_auth_info(session, GNUTLS_CRD_SRP);
+
+                       if (info == NULL)
+                               break;
+
+                       gnutls_free(info->username);
+                       info->username = NULL;
+               }
                break;
 #ifdef ENABLE_ANON
        case GNUTLS_CRD_ANON:
@@ -350,6 +361,14 @@ void _gnutls_free_auth_info(gnutls_session_t session)
                        if (info == NULL)
                                break;
 
+                       gnutls_free(info->username);
+                       info->username = NULL;
+                       info->username_len = 0;
+
+                       gnutls_free(info->hint);
+                       info->hint = NULL;
+                       info->hint_len = 0;
+
 #ifdef ENABLE_DHE
                        dh_info = &info->dh;
                        _gnutls_free_dh_info(dh_info);
index a98ef9c9ef4fa4cc26f27451ab2ee2e5b1428696..81e0e1a6270e4789d94012631b73a2e6fe6a0d8a 100644 (file)
@@ -316,7 +316,9 @@ proc_dhe_psk_client_kx(gnutls_session_t session, uint8_t * data,
                return GNUTLS_E_ILLEGAL_SRP_USERNAME;
        }
 
-       _gnutls_copy_psk_username(info, &username);
+       ret = _gnutls_copy_psk_username(info, username);
+       if (ret < 0)
+               return gnutls_assert_val(ret);
 
        /* Adjust the data */
        data += username.size + 2;
@@ -382,7 +384,9 @@ proc_ecdhe_psk_client_kx(gnutls_session_t session, uint8_t * data,
                return GNUTLS_E_ILLEGAL_SRP_USERNAME;
        }
 
-       _gnutls_copy_psk_username(info, &username);
+       ret = _gnutls_copy_psk_username(info, username);
+       if (ret < 0)
+               return gnutls_assert_val(ret);
 
        /* Adjust the data */
        data += username.size + 2;
@@ -403,29 +407,6 @@ proc_ecdhe_psk_client_kx(gnutls_session_t session, uint8_t * data,
        return ret;
 }
 
-static int copy_hint(gnutls_session_t session, gnutls_datum_t *hint)
-{
-       psk_auth_info_t info;
-
-       /* copy the hint to the auth info structures
-        */
-       info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
-       if (info == NULL) {
-               gnutls_assert();
-               return GNUTLS_E_INTERNAL_ERROR;
-       }
-
-       if (hint->size > MAX_USERNAME_SIZE) {
-               gnutls_assert();
-               return GNUTLS_E_ILLEGAL_SRP_USERNAME;
-       }
-
-       memcpy(info->hint, hint->data, hint->size);
-       info->hint[hint->size] = 0;
-
-       return 0;
-}
-
 static int
 proc_dhe_psk_server_kx(gnutls_session_t session, uint8_t * data,
                       size_t _data_size)
@@ -433,6 +414,7 @@ proc_dhe_psk_server_kx(gnutls_session_t session, uint8_t * data,
 
        int ret;
        ssize_t data_size = _data_size;
+       psk_auth_info_t info;
        gnutls_datum_t hint;
 
        /* set auth_info */
@@ -457,7 +439,14 @@ proc_dhe_psk_server_kx(gnutls_session_t session, uint8_t * data,
                return ret;
        }
 
-       ret = copy_hint(session, &hint);
+       info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
+       if (info == NULL)
+               return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+
+       if (hint.size > MAX_USERNAME_SIZE)
+               return gnutls_assert_val(GNUTLS_E_ILLEGAL_SRP_USERNAME);
+
+       ret = _gnutls_copy_psk_hint(info, hint);
        if (ret < 0) {
                gnutls_assert();
                return ret;
@@ -473,6 +462,7 @@ proc_ecdhe_psk_server_kx(gnutls_session_t session, uint8_t * data,
 
        int ret;
        ssize_t data_size = _data_size;
+       psk_auth_info_t info;
        gnutls_datum_t hint;
 
        /* set auth_info */
@@ -497,7 +487,14 @@ proc_ecdhe_psk_server_kx(gnutls_session_t session, uint8_t * data,
                return ret;
        }
 
-       ret = copy_hint(session, &hint);
+       info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
+       if (info == NULL)
+               return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+
+       if (hint.size > MAX_USERNAME_SIZE)
+               return gnutls_assert_val(GNUTLS_E_ILLEGAL_SRP_USERNAME);
+
+       ret = _gnutls_copy_psk_hint(info, hint);
        if (ret < 0) {
                gnutls_assert();
                return ret;
index 6f220b63823c723e94a68ee689aa55eceee6d695..cdb1f1b2d06c1a40f8609aa387992596c4426986 100644 (file)
@@ -162,15 +162,18 @@ _gnutls_gen_psk_client_kx(gnutls_session_t session,
                gnutls_assert();
        }
 
-       if (username.size > sizeof(info->username)-1) {
+       if (username.size > MAX_USERNAME_SIZE) {
                gnutls_assert();
                ret = GNUTLS_E_ILLEGAL_SRP_USERNAME;
                goto cleanup;
        }
 
        assert(username.data != NULL);
-       _gnutls_copy_psk_username(info, &username);
-
+       ret = _gnutls_copy_psk_username(info, username);
+       if (ret < 0) {
+               gnutls_assert();
+               goto cleanup;
+       }
 
       cleanup:
        if (free) {
@@ -230,7 +233,9 @@ _gnutls_proc_psk_client_kx(gnutls_session_t session, uint8_t * data,
                return GNUTLS_E_ILLEGAL_SRP_USERNAME;
        }
 
-       _gnutls_copy_psk_username(info, &username);
+       ret = _gnutls_copy_psk_username(info, username);
+       if (ret < 0)
+               return gnutls_assert_val(ret);
 
        ret =
            _gnutls_psk_pwd_find_entry(session, info->username, info->username_len, &psk_key);
@@ -291,59 +296,38 @@ _gnutls_gen_psk_server_kx(gnutls_session_t session,
                                                 hint.size);
 }
 
-
-/* just read the hint from the server key exchange.
- */
+/* Read the hint from the server key exchange */
 static int
-_gnutls_proc_psk_server_kx(gnutls_session_t session, uint8_t * data,
-                          size_t _data_size)
+_gnutls_proc_psk_server_kx(gnutls_session_t session, uint8_t * data, size_t _data_size)
 {
-       ssize_t data_size = _data_size;
        int ret;
-       gnutls_datum_t hint;
+       ssize_t data_size = _data_size;
        gnutls_psk_client_credentials_t cred;
        psk_auth_info_t info;
+       gnutls_datum_t hint;
 
-       cred = (gnutls_psk_client_credentials_t)
-           _gnutls_get_cred(session, GNUTLS_CRD_PSK);
+       cred = (gnutls_psk_client_credentials_t) _gnutls_get_cred(session, GNUTLS_CRD_PSK);
+       if (cred == NULL)
+               return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
 
-       if (cred == NULL) {
-               gnutls_assert();
-               return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
-       }
-
-       if ((ret =
-            _gnutls_auth_info_init(session, GNUTLS_CRD_PSK,
-                                  sizeof(psk_auth_info_st), 1)) < 0) {
-               gnutls_assert();
-               return ret;
-       }
+       ret = _gnutls_auth_info_init(session, GNUTLS_CRD_PSK, sizeof(psk_auth_info_st), 1);
+       if (ret < 0)
+               return gnutls_assert_val(ret);
 
        DECR_LENGTH_RET(data_size, 2, 0);
        hint.size = _gnutls_read_uint16(&data[0]);
 
        DECR_LEN(data_size, hint.size);
-
        hint.data = &data[2];
 
-       /* copy the hint to the auth info structures
-        */
        info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
-       if (info == NULL) {
-               gnutls_assert();
-               return GNUTLS_E_INTERNAL_ERROR;
-       }
-
-       if (hint.size > sizeof(info->hint)-1) {
-               gnutls_assert();
-               return GNUTLS_E_ILLEGAL_SRP_USERNAME;
-       }
+       if (info == NULL)
+               return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
 
-       memcpy(info->hint, hint.data, hint.size);
-       info->hint[hint.size] = 0;
-
-       ret = 0;
+       if (hint.size > MAX_USERNAME_SIZE)
+               return gnutls_assert_val(GNUTLS_E_ILLEGAL_SRP_USERNAME);
 
+        ret = _gnutls_copy_psk_hint(info, hint);
        return ret;
 }
 
index b0e511f7fef263efc85612002e243709ed8c37d3..202ee05f99142aafb5d4582435ac08c662d91841 100644 (file)
 #include <auth.h>
 #include <auth/dh_common.h>
 
+#define _gnutls_copy_psk_username(info, datum) \
+       _gnutls_copy_psk_string(&(info)->username, &(info)->username_len, (datum))
+
+#define _gnutls_copy_psk_hint(info, datum) \
+       _gnutls_copy_psk_string(&(info)->hint, &(info)->hint_len, (datum))
+
 typedef struct gnutls_psk_client_credentials_st {
        gnutls_datum_t username;
        gnutls_datum_t key;
@@ -58,23 +64,34 @@ typedef struct gnutls_psk_server_credentials_st {
        const mac_entry_st *binder_algo;
 } psk_server_cred_st;
 
-/* these structures should not use allocated data */
 typedef struct psk_auth_info_st {
-       char username[MAX_USERNAME_SIZE + 1];
+       char *username;
        uint16_t username_len;
        dh_info_st dh;
-       char hint[MAX_USERNAME_SIZE + 1];
+       char *hint;
+       uint16_t hint_len;
 } *psk_auth_info_t;
 
 typedef struct psk_auth_info_st psk_auth_info_st;
 
-inline static
-void _gnutls_copy_psk_username(psk_auth_info_t info, const gnutls_datum_t *username)
+inline static int
+_gnutls_copy_psk_string(char **dest, uint16_t *dest_len, const gnutls_datum_t str)
 {
-       assert(sizeof(info->username) > username->size);
-       memcpy(info->username, username->data, username->size);
-       info->username[username->size] = 0;
-       info->username_len = username->size;
+       char *_tmp;
+
+       assert(MAX_USERNAME_SIZE >= str.size);
+       
+       _tmp = gnutls_malloc(str.size + 1);
+       if (_tmp == NULL)
+               return GNUTLS_E_MEMORY_ERROR;
+       memcpy(_tmp, str.data, str.size);
+       _tmp[str.size] = '\0';
+       
+       gnutls_free(*dest);
+       *dest = _tmp;
+       *dest_len = str.size;
+       
+       return GNUTLS_E_SUCCESS;
 }
 
 #ifdef ENABLE_PSK
index 1a9dab56128c48c7c9831f3c412fa4e10500778b..39092957e2b8b58b37a8a80ad1d5cd641bb3e901 100644 (file)
@@ -310,7 +310,9 @@ _gnutls_proc_rsa_psk_client_kx(gnutls_session_t session, uint8_t * data,
                return GNUTLS_E_ILLEGAL_SRP_USERNAME;
        }
 
-       _gnutls_copy_psk_username(info, &username);
+       ret = _gnutls_copy_psk_username(info, username);
+       if (ret < 0)
+               gnutls_assert_val(ret);
 
        /* Adjust data so it points to EncryptedPreMasterSecret */
        data += username.size + 2;
index 27a5046ef6e403867b6617969ccec93cc72efc24..e6ecf24623a893ec53086df2938b67218f53bbd4 100644 (file)
@@ -119,10 +119,9 @@ _gnutls_gen_srp_server_kx(gnutls_session_t session,
                          gnutls_buffer_st * data)
 {
        int ret;
-       char *username;
        SRP_PWD_ENTRY *pwd_entry;
        srp_server_auth_info_t info;
-       size_t tmp_size;
+       size_t tmp_size, username_length;
        gnutls_ext_priv_data_t epriv;
        srp_ext_st *priv;
        unsigned init_pos;
@@ -148,12 +147,16 @@ _gnutls_gen_srp_server_kx(gnutls_session_t session,
        if (info == NULL)
                return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
 
-       username = info->username;
+       username_length = strlen(priv->username);
+       if (username_length > MAX_USERNAME_SIZE)
+               return gnutls_assert_val(GNUTLS_E_ILLEGAL_SRP_USERNAME);
 
-       _gnutls_str_cpy(username, MAX_USERNAME_SIZE, priv->username);
-
-       ret = _gnutls_srp_pwd_read_entry(session, username, &pwd_entry);
+       gnutls_free(info->username);
+       info->username = gnutls_strdup(priv->username);
+       if (info->username == NULL)
+               return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
 
+       ret = _gnutls_srp_pwd_read_entry(session, priv->username, &pwd_entry);
        if (ret < 0) {
                gnutls_assert();
                return ret;
index ebe1477e026f3cdc723adc6b1f7cd449ee5c2bdd..3cf525205a85f4470c9d07b5a8b018d5c5e261d9 100644 (file)
@@ -46,9 +46,8 @@ typedef struct gnutls_srp_server_credentials_st {
        unsigned int fake_salt_length;
 } srp_server_cred_st;
 
-/* these structures should not use allocated data */
 typedef struct srp_server_auth_info_st {
-       char username[MAX_USERNAME_SIZE + 1];
+       char *username;
 } *srp_server_auth_info_t;
 
 #ifdef ENABLE_SRP
index 1b49a0305416b53384e31ae718059d88045bb64d..8dff2b495ff1feae6bb37fc8b09dff3b07abc544 100644 (file)
@@ -392,7 +392,12 @@ client_send_params(gnutls_session_t session,
                info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
                assert(info != NULL);
 
-               _gnutls_copy_psk_username(info, &username);
+               ret = _gnutls_copy_psk_username(info, username);
+               if (ret < 0) {
+                       gnutls_assert();
+                       goto cleanup;
+               }
+
 
                if ((ret = _gnutls_buffer_append_data_prefix(extdata, 16,
                                                             username.data,
@@ -674,7 +679,7 @@ static int server_recv_params(gnutls_session_t session,
        /* save the username in psk_auth_info to make it available
         * using gnutls_psk_server_get_username() */
        if (!resuming) {
-               assert(psk.identity.size < sizeof(info->username));
+               assert(psk.identity.size <= MAX_USERNAME_SIZE);
 
                ret = _gnutls_auth_info_init(session, GNUTLS_CRD_PSK, sizeof(psk_auth_info_st), 1);
                if (ret < 0) {
@@ -685,7 +690,12 @@ static int server_recv_params(gnutls_session_t session,
                info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
                assert(info != NULL);
 
-               _gnutls_copy_psk_username(info, &psk.identity);
+               ret = _gnutls_copy_psk_username(info, psk.identity);
+               if (ret < 0) {
+                       gnutls_assert();
+                       goto fail;
+               }
+
                _gnutls_handshake_log("EXT[%p]: selected PSK identity: %s (%d)\n", session, info->username, psk_index);
 
                /* We currently only support early data in resuming connection,
index 26fa56e3aac0022d2fc06295b406c8bddee35da4..f236c6443e210330fd4d19066d30e95e7bef5e56 100644 (file)
@@ -73,11 +73,6 @@ _gnutls_srp_recv_params(gnutls_session_t session, const uint8_t * data,
                        len = data[0];
                        DECR_LEN(data_size, len);
 
-                       if (MAX_USERNAME_SIZE < len) {
-                               gnutls_assert();
-                               return GNUTLS_E_ILLEGAL_SRP_USERNAME;
-                       }
-
                        priv = gnutls_calloc(1, sizeof(*priv));
                        if (priv == NULL) {
                                gnutls_assert();
index 8c7bdaa1dbde1a2f867479878a00a43d099f417d..8daad771c47fb38d0c3e9ae234ee56e4d4b3863f 100644 (file)
@@ -108,7 +108,10 @@ typedef int ssize_t;
 
 #define MAX_CIPHER_IV_SIZE 16
 
-#define MAX_USERNAME_SIZE 128
+/* Maximum size of 2^16-1 has been chosen so that usernames can hold
+ * PSK identities as defined in RFC 4279 section 2 and RFC 8446 section 4.2.11
+ */
+#define MAX_USERNAME_SIZE 65535
 #define MAX_SERVER_NAME_SIZE 256
 
 #define AEAD_EXPLICIT_DATA_SIZE 8
@@ -1446,7 +1449,10 @@ typedef struct {
        bool cert_hash_set;
 
        /* The saved username from PSK or SRP auth */
-       char saved_username[MAX_USERNAME_SIZE+1];
+       char *saved_username;
+       /* Length of the saved username without the NULL terminating byte.
+        * Must be set to -1 when saved username is NULL
+        */
        int saved_username_size;
 
        /* Needed for TCP Fast Open (TFO), set by gnutls_transport_set_fastopen() */
index b07b9680cb8aea8234aeb258ee7be58d6149b081..f5a3a4d3d22d14563706efb51f1b8bda1210abb2 100644 (file)
@@ -75,17 +75,27 @@ int _gnutls_check_id_for_change(gnutls_session_t session)
                if (username == NULL)
                        return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
 
-               if (session->internals.saved_username_size != -1) {
+               if (session->internals.saved_username &&
+                   session->internals.saved_username_size != -1) {
                        if (session->internals.saved_username_size == username_length &&
-                           strncmp(session->internals.saved_username, username, username_length) != 0) {
+                           strncmp(session->internals.saved_username, username, username_length)) {
                                _gnutls_debug_log("Session's PSK username changed during rehandshake; aborting!\n");
                                return gnutls_assert_val(GNUTLS_E_SESSION_USER_ID_CHANGED);
                        }
-               } else {
-                       memcpy(session->internals.saved_username, username, username_length);
-                       session->internals.saved_username[username_length] = 0;
+               } else if (session->internals.saved_username == NULL &&
+                          session->internals.saved_username_size == -1) {
+                       if (username_length > MAX_USERNAME_SIZE)
+                               return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+                       char *tmp = gnutls_malloc(username_length + 1);
+                       if (tmp == NULL)
+                               return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+                       memcpy(tmp, username, username_length);
+                       tmp[username_length] = '\0';
+                       session->internals.saved_username = tmp;
                        session->internals.saved_username_size = username_length;
-               }
+               } else
+                       return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+
        }
 
        return 0;
index e5f2b05311ad3ed946ec37db112c3ee1a39c89d6..49fe91c9950a22d4ea0572ec04bda8c34c035e5e 100644 (file)
--- a/lib/psk.c
+++ b/lib/psk.c
@@ -544,13 +544,7 @@ const char *gnutls_psk_client_get_hint(gnutls_session_t session)
        CHECK_AUTH_TYPE(GNUTLS_CRD_PSK, NULL);
 
        info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
-       if (info == NULL)
-               return NULL;
-
-       if (info->hint[0] != 0)
-               return info->hint;
-
-       return NULL;
+       return info ? info->hint : NULL;
 }
 
 /**
index 1f3bc4740c57cbea657a406530cea207aeab8879..fa9a0fcc62de2a9040bcb40bff0b2ccc3a287cd0 100644 (file)
@@ -600,8 +600,13 @@ pack_srp_auth_info(gnutls_session_t session, gnutls_buffer_st * ps)
        const char *username = NULL;
 
        if (info) {
-               username = info->username;
-               len = strlen(info->username) + 1;       /* include the terminating null */
+               if (info->username) {
+                       username = info->username;
+                       len = strlen(info->username) + 1; /* include the terminating null */
+               } else {
+                       username = "\0";
+                       len = 1;
+               }
        } else
                len = 0;
 
@@ -627,26 +632,27 @@ unpack_srp_auth_info(gnutls_session_t session, gnutls_buffer_st * ps)
        srp_server_auth_info_t info;
 
        BUFFER_POP_NUM(ps, username_size);
-       if (username_size > sizeof(info->username)) {
-               gnutls_assert();
-               return GNUTLS_E_INTERNAL_ERROR;
-       }
+       if (username_size > MAX_USERNAME_SIZE + 1)
+               return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
 
-       ret =
-           _gnutls_auth_info_init(session, GNUTLS_CRD_SRP,
-                                 sizeof(srp_server_auth_info_st), 1);
-       if (ret < 0) {
-               gnutls_assert();
-               return ret;
-       }
+       ret = _gnutls_auth_info_init(session, GNUTLS_CRD_SRP,
+                                    sizeof(srp_server_auth_info_st), 1);
+       if (ret < 0)
+               return gnutls_assert_val(ret);
 
        info = _gnutls_get_auth_info(session, GNUTLS_CRD_SRP);
        if (info == NULL)
                return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
 
+       gnutls_free(info->username);
+       if (username_size == 0) {
+               info->username = NULL;
+       } else {
+               info->username = gnutls_malloc(username_size);
+               if (info->username == NULL)
+                       return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+       }
        BUFFER_POP(ps, info->username, username_size);
-       if (username_size == 0)
-               info->username[0] = 0;
 
        ret = 0;
 
@@ -777,14 +783,14 @@ pack_psk_auth_info(gnutls_session_t session, gnutls_buffer_st * ps)
                return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
 
        username_len = info->username_len;
-       hint_len = strlen(info->hint) + 1;      /* include the terminating null */
+       hint_len = info->hint_len + 1; /* include the terminating null */
 
        size_offset = ps->length;
        BUFFER_APPEND_NUM(ps, 0);
        cur_size = ps->length;
 
        BUFFER_APPEND_PFX4(ps, info->username, username_len);
-       BUFFER_APPEND_PFX4(ps, info->hint, hint_len);
+       BUFFER_APPEND_PFX4(ps, info->hint ? info->hint : "\0", hint_len);
 
        BUFFER_APPEND_NUM(ps, info->dh.secret_bits);
        BUFFER_APPEND_PFX4(ps, info->dh.prime.data, info->dh.prime.size);
@@ -824,27 +830,28 @@ unpack_psk_auth_info(gnutls_session_t session, gnutls_buffer_st * ps)
                return GNUTLS_E_INVALID_REQUEST;
 
        BUFFER_POP_NUM(ps, username_size);
-       if (username_size > (sizeof(info->username) - 1)) {
-               gnutls_assert();
-               return GNUTLS_E_INTERNAL_ERROR;
-       }
+       if (username_size > MAX_USERNAME_SIZE)
+               return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
 
+       gnutls_free(info->username);
+       info->username = gnutls_malloc(username_size + 1);
+       if (info->username == NULL)
+               return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
        BUFFER_POP(ps, info->username, username_size);
-       if (username_size == 0)
-               info->username[0] = 0;
-
-       /* append a null terminator and set length */
        info->username[username_size] = 0;
        info->username_len = username_size;
 
+       /* hint_size includes the terminating null */
        BUFFER_POP_NUM(ps, hint_size);
-       if (hint_size > sizeof(info->hint)) {
-               gnutls_assert();
-               return GNUTLS_E_INTERNAL_ERROR;
-       }
+       if (hint_size > MAX_USERNAME_SIZE + 1)
+               return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+
+       gnutls_free(info->hint);
+       info->hint = gnutls_malloc(hint_size);
+       if (info->hint == NULL)
+               return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
        BUFFER_POP(ps, info->hint, hint_size);
-       if (hint_size == 0)
-               info->hint[0] = 0;
+       info->hint_len = hint_size - 1;
 
        BUFFER_POP_NUM(ps, info->dh.secret_bits);
 
index f7a379fde26e1aef7c4a82082a5449f212531d2e..ee72646128bdb23423a40daeac1a46f150059d31 100644 (file)
@@ -691,6 +691,7 @@ int gnutls_init(gnutls_session_t * session, unsigned int flags)
        (*session)->internals.pull_func = system_read;
        (*session)->internals.errno_func = system_errno;
 
+       (*session)->internals.saved_username = NULL;
        (*session)->internals.saved_username_size = -1;
 
        /* heartbeat timeouts */
@@ -782,6 +783,7 @@ void gnutls_deinit(gnutls_session_t session)
        gnutls_free(session->internals.rexts);
        gnutls_free(session->internals.post_handshake_cr_context.data);
 
+       gnutls_free(session->internals.saved_username);
        gnutls_free(session->internals.rsup);
 
        gnutls_credentials_clear(session);