diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2017-09-29 15:16:04 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2018-01-27 16:09:53 +0100 |
commit | 33d3510aff0cb1216c7ade754296484b686f6665 (patch) | |
tree | 867c5ac5c2ae55bdbc1fd6c2b111b5d3d0748d88 | |
parent | 6a15658d607b414ddfd0ae842f96b2ecaa6280bb (diff) | |
download | gnutls-33d3510aff0cb1216c7ade754296484b686f6665.tar.gz |
handshake: added support for reading and sending cookie extension
That introduces an internal API to associate data to an extension.
Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
-rw-r--r-- | lib/Makefile.am | 3 | ||||
-rw-r--r-- | lib/ext/Makefile.am | 3 | ||||
-rw-r--r-- | lib/ext/cookie.c | 117 | ||||
-rw-r--r-- | lib/ext/cookie.h | 30 | ||||
-rw-r--r-- | lib/gnutls_int.h | 3 | ||||
-rw-r--r-- | lib/hello_ext.c | 8 | ||||
-rw-r--r-- | lib/hello_ext_lib.c | 80 | ||||
-rw-r--r-- | lib/hello_ext_lib.h | 38 |
8 files changed, 276 insertions, 6 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index 1a8c82b89c..a0ac3b4c11 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -79,7 +79,8 @@ COBJECTS = range.c record.c compress.c debug.c cipher.c handshake-tls13.c \ safe-memfuncs.c system/inet_pton.c atfork.c atfork.h randomart.c \ system-keys.h urls.c urls.h prf.c auto-verify.c dh-session.c \ cert-session.c handshake-checks.c dtls-sw.c dh-primes.c openpgp_compat.c \ - crypto-selftests.c crypto-selftests-pk.c secrets.c extv.c extv.h + crypto-selftests.c crypto-selftests-pk.c secrets.c extv.c extv.h \ + hello_ext_lib.c hello_ext_lib.h if WINDOWS COBJECTS += system/keys-win.c diff --git a/lib/ext/Makefile.am b/lib/ext/Makefile.am index 211694778d..63d94760bb 100644 --- a/lib/ext/Makefile.am +++ b/lib/ext/Makefile.am @@ -42,7 +42,8 @@ libgnutls_ext_la_SOURCES = max_record.c \ status_request.h status_request.c dumbfw.c dumbfw.h \ ext_master_secret.c ext_master_secret.h etm.h etm.c \ supported_versions.c supported_versions.h \ - post_handshake.c post_handshake.h key_share.c key_share.h + post_handshake.c post_handshake.h key_share.c key_share.h \ + cookie.c cookie.h if ENABLE_ALPN libgnutls_ext_la_SOURCES += alpn.c alpn.h diff --git a/lib/ext/cookie.c b/lib/ext/cookie.c new file mode 100644 index 0000000000..c21e5c1c9d --- /dev/null +++ b/lib/ext/cookie.c @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2017 Red Hat, Inc. + * + * Author: Nikos Mavrogiannopoulos + * + * This file is part of GnuTLS. + * + * The GnuTLS is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +/* This file contains the code for the Max Record Size TLS extension. + */ + +#include "gnutls_int.h" +#include "errors.h" +#include "num.h" +#include "hello_ext_lib.h" +#include <ext/cookie.h> + +static int cookie_recv_params(gnutls_session_t session, + const uint8_t * data, + size_t data_size); +static int cookie_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata); + +const hello_ext_entry_st ext_mod_cookie = { + .name = "Cookie", + .tls_id = 44, + .gid = GNUTLS_EXTENSION_COOKIE, + .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_HRR, + .parse_type = GNUTLS_EXT_MANDATORY, /* force parsing prior to EXT_TLS extensions */ + + .recv_func = cookie_recv_params, + .send_func = cookie_send_params, + .pack_func = NULL, + .unpack_func = NULL, + .deinit_func = _gnutls_hello_ext_default_deinit, + .cannot_be_overriden = 0 +}; + +/* Only client sends this extension. */ +static int +cookie_recv_params(gnutls_session_t session, + const uint8_t * data, size_t _data_size) +{ + ssize_t data_size = _data_size; + ssize_t csize; + int ret; + gnutls_datum_t tmp; + + if (session->security_parameters.entity == GNUTLS_SERVER) { + /* we don't support it */ + return 0; + } else { /* client */ + if (_gnutls_ext_get_msg(session) == GNUTLS_EXT_FLAG_HRR) { + DECR_LEN(data_size, 2); + + csize = _gnutls_read_uint16(data); + data += 2; + + DECR_LEN(data_size, csize); + + if (data_size != 0) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + tmp.data = (void*)data; + tmp.size = csize; + + ret = _gnutls_hello_ext_set_datum(session, GNUTLS_EXTENSION_COOKIE, &tmp); + if (ret < 0) + return gnutls_assert_val(ret); + + return 0; + } + + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION); + } + + return 0; +} + +/* returns data_size or a negative number on failure + */ +static int +cookie_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata) +{ + gnutls_datum_t tmp; + int ret; + + /* this function sends the client extension data (dnsname) */ + if (session->security_parameters.entity == GNUTLS_CLIENT) { + ret = _gnutls_hello_ext_get_datum(session, GNUTLS_EXTENSION_COOKIE, &tmp); + if (ret < 0) + return 0; + + ret = _gnutls_buffer_append_data_prefix(extdata, 16, tmp.data, tmp.size); + if (ret < 0) + return gnutls_assert_val(ret); + + return 0; + } + + return 0; +} diff --git a/lib/ext/cookie.h b/lib/ext/cookie.h new file mode 100644 index 0000000000..d7c4048865 --- /dev/null +++ b/lib/ext/cookie.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2017 Red Hat, Inc. + * + * Author: Nikos Mavrogiannopoulos + * + * This file is part of GnuTLS. + * + * The GnuTLS is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +#ifndef EXT_COOKIE_H +#define EXT_COOKIE_H + +#include <hello_ext.h> + +extern const hello_ext_entry_st ext_mod_cookie; + +#endif diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index c86f303bdb..e110631d89 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -299,7 +299,8 @@ typedef enum extensions_t { GNUTLS_EXTENSION_POST_HANDSHAKE, GNUTLS_EXTENSION_SAFE_RENEGOTIATION, GNUTLS_EXTENSION_SERVER_NAME, - GNUTLS_EXTENSION_MAX = GNUTLS_EXTENSION_SERVER_NAME + GNUTLS_EXTENSION_COOKIE, + GNUTLS_EXTENSION_MAX = GNUTLS_EXTENSION_COOKIE } extensions_t; #define GNUTLS_EXTENSION_MAX_VALUE 31 diff --git a/lib/hello_ext.c b/lib/hello_ext.c index e22f72fca8..6d1927bcc5 100644 --- a/lib/hello_ext.c +++ b/lib/hello_ext.c @@ -47,6 +47,7 @@ #include <ext/dumbfw.h> #include <ext/key_share.h> #include <ext/etm.h> +#include <ext/cookie.h> #include "extv.h" #include <num.h> @@ -80,6 +81,7 @@ static hello_ext_entry_st const *extfunc[MAX_EXT_TYPES+1] = { &ext_mod_supported_ecc_pf, &ext_mod_sig, &ext_mod_key_share, + &ext_mod_cookie, #ifdef ENABLE_DTLS_SRTP &ext_mod_srtp, #endif @@ -622,7 +624,7 @@ _gnutls_hello_ext_set_sdata(gnutls_session_t session, extensions_t id, int _gnutls_hello_ext_get_sdata(gnutls_session_t session, - extensions_t id, gnutls_ext_priv_data_t * data) + extensions_t id, gnutls_ext_priv_data_t * data) { int i; @@ -640,8 +642,8 @@ _gnutls_hello_ext_get_sdata(gnutls_session_t session, int _gnutls_hello_ext_get_resumed_sdata(gnutls_session_t session, - extensions_t id, - gnutls_ext_priv_data_t * data) + extensions_t id, + gnutls_ext_priv_data_t * data) { int i; diff --git a/lib/hello_ext_lib.c b/lib/hello_ext_lib.c new file mode 100644 index 0000000000..a9ae28caed --- /dev/null +++ b/lib/hello_ext_lib.c @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2017 Red Hat, Inc. + * + * Author: Nikos Mavrogiannopoulos + * + * This file is part of GnuTLS. + * + * The GnuTLS is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +/* Internal API functions to be used by extension handlers. + */ + +#include "gnutls_int.h" +#include "hello_ext.h" +#include "hello_ext_lib.h" + +void _gnutls_hello_ext_default_deinit(gnutls_ext_priv_data_t priv) +{ + gnutls_free(priv); +} + +/* When this is used, the deinitialization function must be set to default: + * _gnutls_hello_ext_default_deinit. + * + * This also prevents and errors on duplicate entries. + */ +int +_gnutls_hello_ext_set_datum(gnutls_session_t session, + extensions_t id, const gnutls_datum_t *data) +{ + gnutls_ext_priv_data_t epriv; + + if (_gnutls_hello_ext_get_sdata(session, id, &epriv) >= 0) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + if (data->size >= UINT16_MAX) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + epriv = gnutls_malloc(data->size+2); + if (epriv == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + _gnutls_write_uint16(data->size, epriv); + memcpy(((uint8_t*)epriv)+2, data->data, data->size); + + _gnutls_hello_ext_set_sdata(session, id, epriv); + + return 0; +} + +int +_gnutls_hello_ext_get_datum(gnutls_session_t session, + extensions_t id, gnutls_datum_t *data /* constant contents */) +{ + gnutls_ext_priv_data_t epriv; + int ret; + + ret = _gnutls_hello_ext_get_sdata(session, id, &epriv); + if (ret < 0 || epriv == NULL) + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + + data->size = _gnutls_read_uint16(epriv); + data->data = ((uint8_t*)epriv)+2; + + return 0; +} + diff --git a/lib/hello_ext_lib.h b/lib/hello_ext_lib.h new file mode 100644 index 0000000000..6f1a5c21aa --- /dev/null +++ b/lib/hello_ext_lib.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2017 Red Hat, Inc. + * + * Author: Nikos Mavrogiannopoulos + * + * This file is part of GnuTLS. + * + * The GnuTLS is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +#ifndef GNUTLS_EXT_LIB_H +#define GNUTLS_EXT_LIB_H + +#include <gnutls/gnutls.h> +#include "hello_ext.h" + +void _gnutls_hello_ext_default_deinit(gnutls_ext_priv_data_t priv); + +int +_gnutls_hello_ext_set_datum(gnutls_session_t session, + extensions_t id, const gnutls_datum_t *data); +int +_gnutls_hello_ext_get_datum(gnutls_session_t session, + extensions_t id, gnutls_datum_t *data /* constant contents */); + +#endif |