From 3f56889505bb30cc65768b9e270954423a4fb5f4 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Tue, 7 Aug 2018 14:45:07 +0200 Subject: ext/pre_shared_key: prevent crash if no server credentials are set Previously, if server is configured without PSK credentials and the client authenticated with PSK, the server crashed with: Program received signal SIGSEGV, Segmentation fault. 0x00007ffff7b190ba in server_recv_params (session=0x636fc0, data=0x634e6e "", len=46, pskcred=0x0) at pre_shared_key.c:523 523 prf = pskcred->binder_algo; Signed-off-by: Daiki Ueno --- lib/ext/pre_shared_key.c | 3 ++- tests/psk-file.c | 37 ++++++++++++++++++++++++++----------- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/lib/ext/pre_shared_key.c b/lib/ext/pre_shared_key.c index dc56d1dc49..b2f24bc3ba 100644 --- a/lib/ext/pre_shared_key.c +++ b/lib/ext/pre_shared_key.c @@ -515,7 +515,8 @@ static int server_recv_params(gnutls_session_t session, resuming = 1; break; - } else if (psk.ob_ticket_age == 0 && + } else if (pskcred && + psk.ob_ticket_age == 0 && psk.identity.size > 0 && psk.identity.size <= MAX_USERNAME_SIZE) { /* _gnutls_psk_pwd_find_entry() expects 0-terminated identities */ char identity_str[psk.identity.size + 1]; diff --git a/tests/psk-file.c b/tests/psk-file.c index 3defa28275..28d45560b1 100644 --- a/tests/psk-file.c +++ b/tests/psk-file.c @@ -27,6 +27,7 @@ #include #endif +#include #include #include @@ -171,7 +172,8 @@ static void client(int sd, const char *prio, const char *user, const gnutls_datu #define MAX_BUF 1024 -static void server(int sd, const char *prio, const char *user, int expect_fail, int exp_kx) +static void server(int sd, const char *prio, const char *user, bool no_cred, + int expect_fail, int exp_kx) { gnutls_psk_server_credentials_t server_pskcred; int ret, kx; @@ -206,7 +208,8 @@ static void server(int sd, const char *prio, const char *user, int expect_fail, assert(gnutls_priority_set_direct(session, prio, NULL)>=0); - gnutls_credentials_set(session, GNUTLS_CRD_PSK, server_pskcred); + if (!no_cred) + gnutls_credentials_set(session, GNUTLS_CRD_PSK, server_pskcred); gnutls_transport_set_int(session, sd); ret = gnutls_handshake(session); @@ -267,10 +270,12 @@ static void server(int sd, const char *prio, const char *user, int expect_fail, if (expect_fail) fail("server: expected failure but connection succeeded!\n"); - pskid = gnutls_psk_server_get_username(session); - if (pskid == NULL || strcmp(pskid, user) != 0) { - fail("server: username (%s), does not match expected (%s)\n", - pskid, user); + if (!no_cred) { + pskid = gnutls_psk_server_get_username(session); + if (pskid == NULL || strcmp(pskid, user) != 0) { + fail("server: username (%s), does not match expected (%s)\n", + pskid, user); + } } if (exp_kx && kx != exp_kx) { @@ -292,7 +297,7 @@ static void server(int sd, const char *prio, const char *user, int expect_fail, } static -void run_test2(const char *prio, const char *sprio, const char *user, const gnutls_datum_t *key, +void run_test3(const char *prio, const char *sprio, const char *user, const gnutls_datum_t *key, bool no_cred, unsigned expect_hint, int exp_kx, int expect_fail_cli, int expect_fail_serv) { pid_t child; @@ -323,7 +328,7 @@ void run_test2(const char *prio, const char *sprio, const char *user, const gnut close(sockets[1]); int status; /* parent */ - server(sockets[0], sprio?sprio:prio, user, expect_fail_serv, exp_kx); + server(sockets[0], sprio?sprio:prio, user, no_cred, expect_fail_serv, exp_kx); wait(&status); check_wait_status(status); } else { @@ -333,22 +338,29 @@ void run_test2(const char *prio, const char *sprio, const char *user, const gnut } } +static +void run_test2(const char *prio, const char *sprio, const char *user, const gnutls_datum_t *key, + unsigned expect_hint, int exp_kx, int expect_fail_cli, int expect_fail_serv) +{ + run_test3(prio, sprio, user, key, 0, expect_hint, exp_kx, expect_fail_cli, expect_fail_serv); +} + static void run_test_ok(const char *prio, const char *user, const gnutls_datum_t *key, unsigned expect_hint, int expect_fail) { - return run_test2(prio, NULL, user, key, expect_hint, GNUTLS_KX_PSK, expect_fail, expect_fail); + run_test2(prio, NULL, user, key, expect_hint, GNUTLS_KX_PSK, expect_fail, expect_fail); } static void run_ectest_ok(const char *prio, const char *user, const gnutls_datum_t *key, unsigned expect_hint, int expect_fail) { - return run_test2(prio, NULL, user, key, expect_hint, GNUTLS_KX_ECDHE_PSK, expect_fail, expect_fail); + run_test2(prio, NULL, user, key, expect_hint, GNUTLS_KX_ECDHE_PSK, expect_fail, expect_fail); } static void run_dhtest_ok(const char *prio, const char *user, const gnutls_datum_t *key, unsigned expect_hint, int expect_fail) { - return run_test2(prio, NULL, user, key, expect_hint, GNUTLS_KX_DHE_PSK, expect_fail, expect_fail); + run_test2(prio, NULL, user, key, expect_hint, GNUTLS_KX_DHE_PSK, expect_fail, expect_fail); } void doit(void) @@ -398,6 +410,9 @@ void doit(void) /* try with HelloRetryRequest and PSK */ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-ALL:+GROUP-FFDHE2048:+GROUP-FFDHE4096", "NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-ALL:+GROUP-FFDHE4096", "jas", &key, 0, GNUTLS_KX_DHE_PSK, 0, 0); + + /* try without server credentials */ + run_test3("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:+DHE-PSK", NULL, "jas", &key, 1, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_INSUFFICIENT_CREDENTIALS); } #endif /* _WIN32 */ -- cgit v1.2.1