diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2016-02-11 16:10:31 +0100 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2016-02-16 09:59:59 +0100 |
commit | 87de44f70d9d848b91f4a6b86fb12b7b8a8633ac (patch) | |
tree | dafd59b16d07650c15ca1dad4bd60623cd06b38a | |
parent | b0f739c644b4182742bbb5f1485897aabeda6169 (diff) | |
download | gnutls-87de44f70d9d848b91f4a6b86fb12b7b8a8633ac.tar.gz |
Ensure that session resumption does not occur when ext master secret status changes
That is we make sure the server doesn't resume when:
1. Original session had extended master secret but not advertised in resumed
2. Original session did not have extended master secret but is advertised in resumed
Relates #69
-rw-r--r-- | lib/db.c | 15 | ||||
-rw-r--r-- | lib/db.h | 2 | ||||
-rw-r--r-- | lib/ext/session_ticket.c | 9 | ||||
-rw-r--r-- | lib/handshake.c | 99 |
4 files changed, 61 insertions, 64 deletions
@@ -251,6 +251,15 @@ int _gnutls_server_register_current_session(gnutls_session_t session) return ret; } +int _gnutls_check_resumed_params(gnutls_session_t session) +{ + if (session->internals.resumed_security_parameters.ext_master_secret != + session->security_parameters.ext_master_secret) + return gnutls_assert_val(GNUTLS_E_INVALID_SESSION); + + return 0; +} + int _gnutls_server_restore_session(gnutls_session_t session, uint8_t * session_id, int session_id_size) @@ -301,9 +310,9 @@ _gnutls_server_restore_session(gnutls_session_t session, return ret; } - /* Force the state of ext_master_secret based on the resumed parameters */ - if (session->internals.resumed_security_parameters.ext_master_secret != 0) - session->security_parameters.ext_master_secret = 1; + ret = _gnutls_check_resumed_params(session); + if (ret < 0) + return gnutls_assert_val(ret); return 0; } @@ -25,4 +25,6 @@ int _gnutls_server_restore_session(gnutls_session_t session, uint8_t * session_id, int session_id_size); +int _gnutls_check_resumed_params(gnutls_session_t session); + #define PACKED_SESSION_MAGIC ((0xfadebadd)+(GNUTLS_VERSION_NUMBER)) diff --git a/lib/ext/session_ticket.c b/lib/ext/session_ticket.c index 58f1bbacab..edbbf81564 100644 --- a/lib/ext/session_ticket.c +++ b/lib/ext/session_ticket.c @@ -34,6 +34,7 @@ #include <extensions.h> #include <constate.h> #include <dtls.h> +#include "db.h" #ifdef ENABLE_SESSION_TICKETS @@ -57,7 +58,7 @@ static void session_ticket_deinit_data(extension_priv_data_t priv); const extension_entry_st ext_mod_session_ticket = { .name = "SESSION TICKET", .type = GNUTLS_EXTENSION_SESSION_TICKET, - .parse_type = GNUTLS_EXT_MANDATORY, + .parse_type = GNUTLS_EXT_TLS, .recv_func = session_ticket_recv_params, .send_func = session_ticket_send_params, @@ -144,6 +145,12 @@ decrypt_ticket(gnutls_session_t session, session_ticket_ext_st * priv, goto cleanup; } + ret = _gnutls_check_resumed_params(session); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + session->internals.resumed = RESUME_TRUE; ret = 0; diff --git a/lib/handshake.c b/lib/handshake.c index 3d7a153493..8fa0b24a11 100644 --- a/lib/handshake.c +++ b/lib/handshake.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2000-2014 Free Software Foundation, Inc. + * Copyright (C) 2000-2016 Free Software Foundation, Inc. + * Copyright (C) 2015-2016 Red Hat, Inc. * * Author: Nikos Mavrogiannopoulos * @@ -475,15 +476,14 @@ read_client_hello(gnutls_session_t session, uint8_t * data, { uint8_t session_id_len; int pos = 0, ret; - uint16_t suite_size, comp_size; + uint16_t suite_size, comp_size, ext_size; gnutls_protocol_t adv_version; int neg_version, sret = 0; int len = datalen; uint8_t major, minor; - uint8_t *suite_ptr, *comp_ptr, *session_id; + uint8_t *suite_ptr, *comp_ptr, *session_id, *ext_ptr; DECR_LEN(len, 2); - _gnutls_handshake_log("HSK[%p]: Client's version: %d.%d\n", session, data[pos], data[pos + 1]); @@ -541,6 +541,38 @@ read_client_hello(gnutls_session_t session, uint8_t * data, pos += cookie_size; } + /* move forward to extensions and store other vals */ + DECR_LEN(len, 2); + suite_size = _gnutls_read_uint16(&data[pos]); + pos += 2; + + suite_ptr = &data[pos]; + DECR_LEN(len, suite_size); + pos += suite_size; + + DECR_LEN(len, 1); + comp_size = data[pos++]; /* the number of compression methods */ + + comp_ptr = &data[pos]; + DECR_LEN(len, comp_size); + pos += comp_size; + + ext_ptr = &data[pos]; + ext_size = len; + + /* Parse only the mandatory to read extensions for resumption. + * We don't want to parse any other extensions since + * we don't want new extension values to override the + * resumed ones. + */ + ret = + _gnutls_parse_extensions(session, GNUTLS_EXT_MANDATORY, + ext_ptr, ext_size); + if (ret < 0) { + gnutls_assert(); + return ret; + } + ret = _gnutls_server_restore_session(session, session_id, session_id_len); @@ -549,33 +581,6 @@ read_client_hello(gnutls_session_t session, uint8_t * data, session->internals.resumption_requested = 1; if (ret == 0) { /* resumed using default TLS resumption! */ - /* Parse only the safe renegotiation extension - * We don't want to parse any other extensions since - * we don't want new extension values to overwrite the - * resumed ones. - */ - - /* move forward to extensions */ - DECR_LEN(len, 2); - suite_size = _gnutls_read_uint16(&data[pos]); - pos += 2; - - DECR_LEN(len, suite_size); - pos += suite_size; - - DECR_LEN(len, 1); - comp_size = data[pos++]; /* z is the number of compression methods */ - DECR_LEN(len, comp_size); - pos += comp_size; - - ret = - _gnutls_parse_extensions(session, GNUTLS_EXT_MANDATORY, - &data[pos], len); - if (ret < 0) { - gnutls_assert(); - return ret; - } - ret = resume_copy_required_values(session); if (ret < 0) return gnutls_assert_val(ret); @@ -592,32 +597,13 @@ read_client_hello(gnutls_session_t session, uint8_t * data, session->internals.resumed = RESUME_FALSE; } - /* Remember ciphersuites for later - */ - DECR_LEN(len, 2); - suite_size = _gnutls_read_uint16(&data[pos]); - pos += 2; - - DECR_LEN(len, suite_size); - suite_ptr = &data[pos]; - pos += suite_size; - - /* Point to the compression methods - */ - DECR_LEN(len, 1); - comp_size = data[pos++]; /* z is the number of compression methods */ - - DECR_LEN(len, comp_size); - comp_ptr = &data[pos]; - pos += comp_size; - /* Parse the extensions (if any) * * Unconditionally try to parse extensions; safe renegotiation uses them in * sslv3 and higher, even though sslv3 doesn't officially support them. */ ret = _gnutls_parse_extensions(session, GNUTLS_EXT_APPLICATION, - &data[pos], len); + ext_ptr, ext_size); /* len is the rest of the parsed length */ if (ret < 0) { gnutls_assert(); @@ -631,16 +617,9 @@ read_client_hello(gnutls_session_t session, uint8_t * data, return sret; } - ret = _gnutls_parse_extensions(session, GNUTLS_EXT_MANDATORY, - &data[pos], len); - if (ret < 0) { - gnutls_assert(); - return ret; - } - + /* Session tickets are parsed in this point */ ret = - _gnutls_parse_extensions(session, GNUTLS_EXT_TLS, &data[pos], - len); + _gnutls_parse_extensions(session, GNUTLS_EXT_TLS, ext_ptr, ext_size); if (ret < 0) { gnutls_assert(); return ret; |