summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZoltan Fridrich <zfridric@redhat.com>2022-05-10 15:20:45 +0200
committerZoltan Fridrich <zfridric@redhat.com>2022-07-08 10:12:01 +0200
commitf032324af70b8420f7b550f3277efd4a9cd2b2dd (patch)
tree1ab9b3f09c3cc6934fb302d56452259614c01557
parent41c6b26cf099803fc2515ca800e0439f152d5a0f (diff)
downloadgnutls-f032324af70b8420f7b550f3277efd4a9cd2b2dd.tar.gz
Increase the limit of TLS PSK usernames from 128 to 65535 characters
Co-authored-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Zoltan Fridrich <zfridric@redhat.com>
-rw-r--r--NEWS3
-rw-r--r--lib/auth.c19
-rw-r--r--lib/auth/dhe_psk.c51
-rw-r--r--lib/auth/psk.c64
-rw-r--r--lib/auth/psk.h35
-rw-r--r--lib/auth/rsa_psk.c4
-rw-r--r--lib/auth/srp_kx.c15
-rw-r--r--lib/auth/srp_kx.h3
-rw-r--r--lib/ext/pre_shared_key.c16
-rw-r--r--lib/ext/srp.c5
-rw-r--r--lib/gnutls_int.h10
-rw-r--r--lib/handshake-checks.c22
-rw-r--r--lib/psk.c8
-rw-r--r--lib/session_pack.c69
-rw-r--r--lib/state.c2
15 files changed, 187 insertions, 139 deletions
diff --git a/NEWS b/NEWS
index 034b9ced84..0c0835e4f6 100644
--- 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
diff --git a/lib/auth.c b/lib/auth.c
index 1a341c78f6..7c58bd83ec 100644
--- a/lib/auth.c
+++ b/lib/auth.c
@@ -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);
diff --git a/lib/auth/dhe_psk.c b/lib/auth/dhe_psk.c
index a98ef9c9ef..81e0e1a627 100644
--- a/lib/auth/dhe_psk.c
+++ b/lib/auth/dhe_psk.c
@@ -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;
diff --git a/lib/auth/psk.c b/lib/auth/psk.c
index 6f220b6382..cdb1f1b2d0 100644
--- a/lib/auth/psk.c
+++ b/lib/auth/psk.c
@@ -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;
}
diff --git a/lib/auth/psk.h b/lib/auth/psk.h
index b0e511f7fe..202ee05f99 100644
--- a/lib/auth/psk.h
+++ b/lib/auth/psk.h
@@ -26,6 +26,12 @@
#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
diff --git a/lib/auth/rsa_psk.c b/lib/auth/rsa_psk.c
index 1a9dab5612..39092957e2 100644
--- a/lib/auth/rsa_psk.c
+++ b/lib/auth/rsa_psk.c
@@ -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;
diff --git a/lib/auth/srp_kx.c b/lib/auth/srp_kx.c
index 27a5046ef6..e6ecf24623 100644
--- a/lib/auth/srp_kx.c
+++ b/lib/auth/srp_kx.c
@@ -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;
diff --git a/lib/auth/srp_kx.h b/lib/auth/srp_kx.h
index ebe1477e02..3cf525205a 100644
--- a/lib/auth/srp_kx.h
+++ b/lib/auth/srp_kx.h
@@ -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
diff --git a/lib/ext/pre_shared_key.c b/lib/ext/pre_shared_key.c
index 1b49a03054..8dff2b495f 100644
--- a/lib/ext/pre_shared_key.c
+++ b/lib/ext/pre_shared_key.c
@@ -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,
diff --git a/lib/ext/srp.c b/lib/ext/srp.c
index 26fa56e3aa..f236c6443e 100644
--- a/lib/ext/srp.c
+++ b/lib/ext/srp.c
@@ -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();
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 8c7bdaa1db..8daad771c4 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -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() */
diff --git a/lib/handshake-checks.c b/lib/handshake-checks.c
index b07b9680cb..f5a3a4d3d2 100644
--- a/lib/handshake-checks.c
+++ b/lib/handshake-checks.c
@@ -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;
diff --git a/lib/psk.c b/lib/psk.c
index e5f2b05311..49fe91c995 100644
--- 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;
}
/**
diff --git a/lib/session_pack.c b/lib/session_pack.c
index 1f3bc4740c..fa9a0fcc62 100644
--- a/lib/session_pack.c
+++ b/lib/session_pack.c
@@ -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);
diff --git a/lib/state.c b/lib/state.c
index f7a379fde2..ee72646128 100644
--- a/lib/state.c
+++ b/lib/state.c
@@ -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);