From: Nikos Mavrogiannopoulos Date: Fri, 11 Jun 2010 18:17:33 +0000 (+0200) Subject: Simplified and made more safe the packing of data for session storage. Extensions use X-Git-Tag: gnutls_2_11_3~184 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a9b55a42fa65e37fbd00c7359f56b11eaea11e3e;p=thirdparty%2Fgnutls.git Simplified and made more safe the packing of data for session storage. Extensions use the internal API to store/retrieve during resumption. Removed OPRFI since it was never standardized and was never actually included in gnutls since it was in inactive ifdef. This was instead of rewriting it to use the new API. --- diff --git a/NEWS b/NEWS index 3d947da787..5213f18e18 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,10 @@ See the end for copying conditions. * Version 2.11.0 (unreleased) +** libgnutls: Internal API for extensions augmented to allow +safe storing and loading of data on resumption. OPRFI extension +was removed. + ** libgnutls: Added support for DSA-SHA256 and DSA-SHA224 ** libgnutls: Added PKCS #11 support and an API to access objects in diff --git a/doc/cha-gtls-app.texi b/doc/cha-gtls-app.texi index 13651a442f..a29a0924a5 100644 --- a/doc/cha-gtls-app.texi +++ b/doc/cha-gtls-app.texi @@ -10,7 +10,6 @@ * Server examples:: * Miscellaneous examples:: * Compatibility with the OpenSSL library:: -* Opaque PRF Input TLS Extension:: * Keying Material Exporters:: @end menu @@ -454,20 +453,6 @@ Current limitations imposed by the compatibility layer include: @end itemize -@node Opaque PRF Input TLS Extension -@section Opaque PRF Input TLS Extension -@cindex Opaque PRF Input - -GnuTLS supports the Opaque PRF Input TLS extension -(@code{draft-rescorla-tls-opaque-prf-input-00.txt}). The API consists -of one API for use in the client, @ref{gnutls_oprfi_enable_client}, -and one API for use in the server, @ref{gnutls_oprfi_enable_server}. -You must invoke both functions before calling @ref{gnutls_handshake}. -The server utilizes a callback function into the application. The -callback can look at the random string provided by the client, and -also set the server string. The string lengths must be equal -according to the protocol. - @node Keying Material Exporters @section Keying Material Exporters @cindex Keying Material Exporters diff --git a/lib/auth_srp.c b/lib/auth_srp.c index 8ab237c21a..43e463b2aa 100644 --- a/lib/auth_srp.c +++ b/lib/auth_srp.c @@ -36,6 +36,7 @@ #include "auth_srp.h" #include #include +#include const mod_auth_st srp_auth_struct = { "SRP", @@ -142,6 +143,16 @@ _gnutls_gen_srp_server_kx (gnutls_session_t session, opaque ** data) size_t n_b, tmp_size; char buf[64]; uint8_t *data_b; + extension_priv_data_t epriv; + srp_ext_st * priv; + + ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SRP, &epriv); + if (ret < 0) /* peer didn't send a username */ + { + gnutls_assert(); + return GNUTLS_E_UNKNOWN_SRP_USERNAME; + } + priv = epriv.ptr; if ((ret = _gnutls_auth_info_set (session, GNUTLS_CRD_SRP, @@ -154,8 +165,7 @@ _gnutls_gen_srp_server_kx (gnutls_session_t session, opaque ** data) info = _gnutls_get_auth_info (session); username = info->username; - _gnutls_str_cpy (username, MAX_SRP_USERNAME, - session->security_parameters.extensions.srp_username); + _gnutls_str_cpy (username, MAX_SRP_USERNAME, priv->username); ret = _gnutls_srp_pwd_read_entry (session, username, &pwd_entry); @@ -264,7 +274,16 @@ _gnutls_gen_srp_client_kx (gnutls_session_t session, opaque ** data) char *username, *password; char buf[64]; gnutls_srp_client_credentials_t cred; + extension_priv_data_t epriv; + srp_ext_st * priv; + ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SRP, &epriv); + if (ret < 0) /* peer didn't send a username */ + { + gnutls_assert(); + return GNUTLS_E_UNKNOWN_SRP_USERNAME; + } + priv = epriv.ptr; cred = (gnutls_srp_client_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_SRP, NULL); @@ -275,15 +294,16 @@ _gnutls_gen_srp_client_kx (gnutls_session_t session, opaque ** data) return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } - if (session->internals.srp_username == NULL) + if (priv->username == NULL) { username = cred->username; password = cred->password; } else { - username = session->internals.srp_username; - password = session->internals.srp_password; + + username = priv->username; + password = priv->password; } if (username == NULL || password == NULL) @@ -716,6 +736,16 @@ _gnutls_proc_srp_server_kx (gnutls_session_t session, opaque * data, char *username, *password; ssize_t data_size = _data_size; gnutls_srp_client_credentials_t cred; + extension_priv_data_t epriv; + srp_ext_st * priv; + + ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SRP, &epriv); + if (ret < 0) + { + gnutls_assert(); + return GNUTLS_E_UNKNOWN_SRP_USERNAME; + } + priv = epriv.ptr; cred = (gnutls_srp_client_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_SRP, NULL); @@ -726,15 +756,15 @@ _gnutls_proc_srp_server_kx (gnutls_session_t session, opaque * data, return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } - if (session->internals.srp_username == NULL) + if (priv->username == NULL) { username = cred->username; password = cred->password; } else { - username = session->internals.srp_username; - password = session->internals.srp_password; + username = priv->username; + password = priv->password; } if (username == NULL || password == NULL) diff --git a/lib/ext_cert_type.c b/lib/ext_cert_type.c index 1351092acd..ea98511704 100644 --- a/lib/ext_cert_type.c +++ b/lib/ext_cert_type.c @@ -34,8 +34,27 @@ #include #include +/* Maps record size to numbers according to the + * extensions draft. + */ inline static int _gnutls_num2cert_type (int num); inline static int _gnutls_cert_type2num (int record_size); +static int _gnutls_cert_type_recv_params (gnutls_session_t session, + const opaque * data, size_t data_size); +static int _gnutls_cert_type_send_params (gnutls_session_t session, opaque * data, + size_t); + +extension_entry_st ext_mod_cert_type = { + .name = "CERT TYPE", + .type = GNUTLS_EXTENSION_CERT_TYPE, + .parse_type = GNUTLS_EXT_TLS, + + .recv_func = _gnutls_cert_type_recv_params, + .send_func = _gnutls_cert_type_send_params, + .pack_func = NULL, + .unpack_func = NULL, + .deinit_func = NULL +}; /* * In case of a server: if a CERT_TYPE extension type is received then it stores @@ -46,7 +65,7 @@ inline static int _gnutls_cert_type2num (int record_size); * */ -int +static int _gnutls_cert_type_recv_params (gnutls_session_t session, const opaque * data, size_t _data_size) { @@ -142,7 +161,7 @@ _gnutls_cert_type_recv_params (gnutls_session_t session, /* returns data_size or a negative number on failure */ -int +static int _gnutls_cert_type_send_params (gnutls_session_t session, opaque * data, size_t data_size) { diff --git a/lib/ext_cert_type.h b/lib/ext_cert_type.h index 3ab9f2a073..dc3b421c4a 100644 --- a/lib/ext_cert_type.h +++ b/lib/ext_cert_type.h @@ -23,10 +23,11 @@ * */ -/* Maps record size to numbers according to the - * extensions draft. - */ -int _gnutls_cert_type_recv_params (gnutls_session_t session, - const opaque * data, size_t data_size); -int _gnutls_cert_type_send_params (gnutls_session_t session, opaque * data, - size_t); +#ifndef EXT_CERT_TYPE_H +#define EXT_CERT_TYPE_H + +#include + +extern extension_entry_st ext_mod_cert_type; + +#endif diff --git a/lib/ext_max_record.c b/lib/ext_max_record.c index 32bc918dba..98326686b2 100644 --- a/lib/ext_max_record.c +++ b/lib/ext_max_record.c @@ -28,8 +28,36 @@ #include "gnutls_int.h" #include "gnutls_errors.h" #include "gnutls_num.h" +#include #include +static int _gnutls_max_record_recv_params (gnutls_session_t session, + const opaque * data, size_t data_size); +static int _gnutls_max_record_send_params (gnutls_session_t session, opaque * data, + size_t); + +static int _gnutls_max_record_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv); +static int _gnutls_max_record_pack(extension_priv_data_t _priv, gnutls_buffer_st* ps); + +/* Maps record size to numbers according to the + * extensions draft. + */ +static int _gnutls_mre_num2record (int num); +static int _gnutls_mre_record2num (uint16_t record_size); + + +extension_entry_st ext_mod_max_record_size = { + .name = "MAX RECORD SIZE", + .type = GNUTLS_EXTENSION_MAX_RECORD_SIZE, + .parse_type = GNUTLS_EXT_TLS, + + .recv_func = _gnutls_max_record_recv_params, + .send_func = _gnutls_max_record_send_params, + .pack_func = _gnutls_max_record_pack, + .unpack_func = _gnutls_max_record_unpack, + .deinit_func = NULL +}; + /* * In case of a server: if a MAX_RECORD_SIZE extension type is received then it stores * into the session the new value. The server may use gnutls_get_max_record_size(), @@ -40,12 +68,14 @@ * */ -int +static int _gnutls_max_record_recv_params (gnutls_session_t session, const opaque * data, size_t _data_size) { ssize_t new_size; ssize_t data_size = _data_size; + extension_priv_data_t epriv; + int ret; if (session->security_parameters.entity == GNUTLS_SERVER) { @@ -66,10 +96,17 @@ _gnutls_max_record_recv_params (gnutls_session_t session, } } else - { /* CLIENT SIDE - we must check if the sent record size is the right one - */ + { /* CLIENT SIDE - we must check if the sent record size is the right one + */ if (data_size > 0) { + ret = _gnutls_ext_get_session_data( session, + GNUTLS_EXTENSION_MAX_RECORD_SIZE, &epriv); + if (ret < 0) + { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } if (data_size != 1) { @@ -79,8 +116,7 @@ _gnutls_max_record_recv_params (gnutls_session_t session, new_size = _gnutls_mre_num2record (data[0]); - if (new_size < 0 - || new_size != session->internals.proposed_record_size) + if (new_size < 0 || new_size != epriv.num) { gnutls_assert (); return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; @@ -88,7 +124,7 @@ _gnutls_max_record_recv_params (gnutls_session_t session, else { session->security_parameters.max_record_recv_size = - session->internals.proposed_record_size; + epriv.num; } } @@ -101,16 +137,26 @@ _gnutls_max_record_recv_params (gnutls_session_t session, /* returns data_size or a negative number on failure */ -int +static int _gnutls_max_record_send_params (gnutls_session_t session, opaque * data, size_t data_size) { uint16_t len; + int ret; + /* this function sends the client extension data (dnsname) */ if (session->security_parameters.entity == GNUTLS_CLIENT) { + extension_priv_data_t epriv; + + ret = _gnutls_ext_get_session_data( session, + GNUTLS_EXTENSION_MAX_RECORD_SIZE, &epriv); + if (ret < 0) /* it is ok not to have it */ + { + return 0; + } - if (session->internals.proposed_record_size != DEFAULT_MAX_RECORD_SIZE) + if (epriv.num != DEFAULT_MAX_RECORD_SIZE) { len = 1; if (data_size < len) @@ -120,8 +166,7 @@ _gnutls_max_record_send_params (gnutls_session_t session, opaque * data, } data[0] = - (uint8_t) _gnutls_mre_record2num (session-> - internals.proposed_record_size); + (uint8_t) _gnutls_mre_record2num (epriv.num); return len; } @@ -152,10 +197,36 @@ _gnutls_max_record_send_params (gnutls_session_t session, opaque * data, return 0; } + +static int _gnutls_max_record_pack(extension_priv_data_t epriv, gnutls_buffer_st* ps) +{ +int ret; + + BUFFER_APPEND_NUM(ps, epriv.num); + + return 0; + +} + +static int _gnutls_max_record_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv) +{ +extension_priv_data_t epriv; +int ret; + + BUFFER_POP_NUM(ps, epriv.num); + + *_priv = epriv; + + ret = 0; +error: + return ret; +} + + /* Maps numbers to record sizes according to the * extensions draft. */ -int +static int _gnutls_mre_num2record (int num) { switch (num) @@ -176,7 +247,7 @@ _gnutls_mre_num2record (int num) /* Maps record size to numbers according to the * extensions draft. */ -int +static int _gnutls_mre_record2num (uint16_t record_size) { switch (record_size) @@ -194,3 +265,67 @@ _gnutls_mre_record2num (uint16_t record_size) } } + +/** + * gnutls_record_get_max_size: + * @session: is a #gnutls_session_t structure. + * + * Get the record size. The maximum record size is negotiated by the + * client after the first handshake message. + * + * Returns: The maximum record packet size in this connection. + **/ +size_t +gnutls_record_get_max_size (gnutls_session_t session) +{ + /* Recv will hold the negotiated max record size + * always. + */ + return session->security_parameters.max_record_recv_size; +} + + +/** + * gnutls_record_set_max_size: + * @session: is a #gnutls_session_t structure. + * @size: is the new size + * + * This function sets the maximum record packet size in this + * connection. This property can only be set to clients. The server + * may choose not to accept the requested size. + * + * Acceptable values are 512(=2^9), 1024(=2^10), 2048(=2^11) and + * 4096(=2^12). The requested record size does get in effect + * immediately only while sending data. The receive part will take + * effect after a successful handshake. + * + * This function uses a TLS extension called 'max record size'. Not + * all TLS implementations use or even understand this extension. + * + * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned, + * otherwise an error code is returned. + **/ +ssize_t +gnutls_record_set_max_size (gnutls_session_t session, size_t size) +{ + ssize_t new_size; + extension_priv_data_t epriv; + + if (session->security_parameters.entity == GNUTLS_SERVER) + return GNUTLS_E_INVALID_REQUEST; + + new_size = _gnutls_mre_record2num (size); + + if (new_size < 0) + { + gnutls_assert (); + return new_size; + } + + session->security_parameters.max_record_send_size = size; + epriv.num = size; + + _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_MAX_RECORD_SIZE, epriv); + + return 0; +} diff --git a/lib/ext_max_record.h b/lib/ext_max_record.h index bfc465fa36..d159b27815 100644 --- a/lib/ext_max_record.h +++ b/lib/ext_max_record.h @@ -23,12 +23,11 @@ * */ -/* Maps record size to numbers according to the - * extensions draft. - */ -int _gnutls_mre_num2record (int num); -int _gnutls_mre_record2num (uint16_t record_size); -int _gnutls_max_record_recv_params (gnutls_session_t session, - const opaque * data, size_t data_size); -int _gnutls_max_record_send_params (gnutls_session_t session, opaque * data, - size_t); +#ifndef EXT_MAX_RECORD_H +#define EXT_MAX_RECORD_H + +#include + +extern extension_entry_st ext_mod_max_record_size; + +#endif diff --git a/lib/ext_oprfi.c b/lib/ext_oprfi.c deleted file mode 100644 index 1fad66018b..0000000000 --- a/lib/ext_oprfi.c +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (C) 2007, 2010 Free Software Foundation, Inc. - * - * Author: Simon Josefsson - * - * 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 library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA - * - */ - -/* Implementation of Opaque PRF Input: - * http://tools.ietf.org/id/draft-rescorla-tls-opaque-prf-input-00.txt - * - */ - -#include - -#include -#include - -int -oprfi_recv_server (gnutls_session_t session, - const opaque * data, size_t _data_size) -{ - ssize_t data_size = _data_size; - uint16_t len; - int ret; - - if (!session->internals.oprfi_cb) - { - gnutls_assert (); - return 0; - } - - DECR_LEN (data_size, 2); - len = _gnutls_read_uint16 (data); - data += 2; - - if (len != data_size) - { - gnutls_assert (); - return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; - } - - /* Store incoming data. */ - session->security_parameters.extensions.oprfi_client_len = len; - session->security_parameters.extensions.oprfi_client = gnutls_malloc (len); - if (!session->security_parameters.extensions.oprfi_client) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - memcpy (session->security_parameters.extensions.oprfi_client, data, len); - - return 0; -} - -int -oprfi_recv_client (gnutls_session_t session, - const opaque * data, size_t _data_size) -{ - ssize_t data_size = _data_size; - uint16_t len; - int ret; - - if (session->security_parameters.extensions.oprfi_client == NULL) - { - gnutls_assert (); - return 0; - } - - DECR_LEN (data_size, 2); - len = _gnutls_read_uint16 (data); - data += 2; - - if (len != data_size) - { - gnutls_assert (); - return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; - } - - if (len != session->security_parameters.extensions.oprfi_client_len) - { - gnutls_assert (); - return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; - } - - /* Store incoming data. */ - session->security_parameters.extensions.oprfi_server_len = len; - session->security_parameters.extensions.oprfi_server = gnutls_malloc (len); - if (!session->security_parameters.extensions.oprfi_server) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - memcpy (session->security_parameters.extensions.oprfi_server, data, len); - - return 0; -} - -int -_gnutls_oprfi_recv_params (gnutls_session_t session, - const opaque * data, size_t data_size) -{ - if (session->security_parameters.entity == GNUTLS_CLIENT) - return oprfi_recv_client (session, data, data_size); - else - return oprfi_recv_server (session, data, data_size); -} - -int -oprfi_send_client (gnutls_session_t session, opaque * data, size_t _data_size) -{ - opaque *p = data; - ssize_t data_size = _data_size; - int oprf_size = session->security_parameters.extensions.oprfi_client_len; - - if (oprf_size == 0) - return 0; - - DECR_LENGTH_RET (data_size, 2, GNUTLS_E_SHORT_MEMORY_BUFFER); - _gnutls_write_uint16 (oprf_size, p); - p += 2; - - DECR_LENGTH_RET (data_size, oprf_size, GNUTLS_E_SHORT_MEMORY_BUFFER); - - memcpy (p, session->security_parameters.extensions.oprfi_client, oprf_size); - - return 2 + oprf_size; -} - -int -oprfi_send_server (gnutls_session_t session, opaque * data, size_t _data_size) -{ - opaque *p = data; - int ret; - ssize_t data_size = _data_size; - size_t len; - - if (!session->security_parameters.extensions.oprfi_client || - !session->internals.oprfi_cb) - return 0; - - /* Allocate buffer for outgoing data. */ - session->security_parameters.extensions.oprfi_server_len = - session->security_parameters.extensions.oprfi_client_len; - session->security_parameters.extensions.oprfi_server = - gnutls_malloc (session->security_parameters.extensions.oprfi_server_len); - if (!session->security_parameters.extensions.oprfi_server) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - - /* Get outgoing data. */ - ret = session->internals.oprfi_cb - (session, session->internals.oprfi_userdata, - session->security_parameters.extensions.oprfi_client_len, - session->security_parameters.extensions.oprfi_client, - session->security_parameters.extensions.oprfi_server); - if (ret < 0) - { - gnutls_assert (); - gnutls_free (session->security_parameters.extensions.oprfi_server); - return ret; - } - - DECR_LENGTH_RET (data_size, 2, GNUTLS_E_SHORT_MEMORY_BUFFER); - _gnutls_write_uint16 (session->security_parameters.extensions. - oprfi_server_len, p); - p += 2; - - DECR_LENGTH_RET (data_size, - session->security_parameters.extensions.oprfi_server_len, - GNUTLS_E_SHORT_MEMORY_BUFFER); - - memcpy (p, session->security_parameters.extensions.oprfi_server, - session->security_parameters.extensions.oprfi_server_len); - - return 2 + session->security_parameters.extensions.oprfi_server_len; -} - -int -_gnutls_oprfi_send_params (gnutls_session_t session, - opaque * data, size_t data_size) -{ - if (session->security_parameters.entity == GNUTLS_CLIENT) - return oprfi_send_client (session, data, data_size); - else - return oprfi_send_server (session, data, data_size); -} - -/** - * gnutls_oprfi_enable_client: - * @session: is a #gnutls_session_t structure. - * @len: length of Opaque PRF data to use in client. - * @data: Opaque PRF data to use in client. - * - * Request that the client should attempt to negotiate the Opaque PRF - * Input TLS extension, using the given data as the client's Opaque - * PRF input. - * - * The data is copied into the session context after this call, so you - * may de-allocate it immediately after calling this function. - **/ -void -gnutls_oprfi_enable_client (gnutls_session_t session, - size_t len, unsigned char *data) -{ - session->security_parameters.extensions.oprfi_client_len = len; - session->security_parameters.extensions.oprfi_client = data; -} - -/** - * gnutls_oprfi_enable_server: - * @session: is a #gnutls_session_t structure. - * @cb: function pointer to Opaque PRF extension server callback. - * @userdata: hook passed to callback function for passing application state. - * - * Request that the server should attempt to accept the Opaque PRF - * Input TLS extension. If the client requests the extension, the - * provided callback @cb will be invoked. The callback must have the - * following prototype: - * - * int callback (gnutls_session_t session, void *userdata, - * size_t oprfi_len, const unsigned char *in_oprfi, - * unsigned char *out_oprfi); - * - * The callback can inspect the client-provided data in the input - * parameters, and specify its own opaque prf input data in the output - * variable. The function must return 0 on success, otherwise the - * handshake will be aborted. - **/ -void -gnutls_oprfi_enable_server (gnutls_session_t session, - gnutls_oprfi_callback_func cb, void *userdata) -{ - session->internals.oprfi_cb = cb; - session->internals.oprfi_userdata = userdata; -} diff --git a/lib/ext_oprfi.h b/lib/ext_oprfi.h deleted file mode 100644 index 3df9d129a5..0000000000 --- a/lib/ext_oprfi.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2007, 2010 Free Software Foundation, Inc. - * - * Author: Simon Josefsson - * - * 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 library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA - * - */ - -#include - -int _gnutls_oprfi_recv_params (gnutls_session_t state, - const opaque * data, size_t data_size); - -int _gnutls_oprfi_send_params (gnutls_session_t state, - opaque * data, size_t data_size); diff --git a/lib/ext_safe_renegotiation.c b/lib/ext_safe_renegotiation.c index 14392b34ab..1e67f3831a 100644 --- a/lib/ext_safe_renegotiation.c +++ b/lib/ext_safe_renegotiation.c @@ -26,14 +26,229 @@ #include #include -int -_gnutls_safe_renegotiation_recv_params (gnutls_session_t session, + +static int _gnutls_sr_recv_params (gnutls_session_t state, + const opaque * data, + size_t data_size); +static int _gnutls_sr_send_params (gnutls_session_t state, + opaque * data, size_t); +static int _gnutls_sr_pack(extension_priv_data_t epriv, gnutls_buffer_st* ps); +static int _gnutls_sr_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv); +static void _gnutls_sr_deinit_data(extension_priv_data_t priv); + +extension_entry_st ext_mod_sr = { + .name = "SAFE RENEGOTIATION", + .type = GNUTLS_EXTENSION_SAFE_RENEGOTIATION, + .parse_type = GNUTLS_EXT_MANDATORY, + + .recv_func = _gnutls_sr_recv_params, + .send_func = _gnutls_sr_send_params, + .pack_func = NULL, + .unpack_func = NULL, + .deinit_func = _gnutls_sr_deinit_data, +}; + +int _gnutls_ext_sr_finished( gnutls_session_t session, void* vdata, size_t vdata_size, int dir) +{ +int ret; +sr_ext_st* priv; +extension_priv_data_t epriv; + + if (session->internals.priorities.sr == SR_DISABLED) + { + return 0; + } + + ret = _gnutls_ext_get_session_data( session, + GNUTLS_EXTENSION_SAFE_RENEGOTIATION, &epriv); + if (ret < 0) + { + gnutls_assert(); + return ret; + } + priv = epriv.ptr; + + /* Save data for safe renegotiation. + */ + if (vdata_size > MAX_VERIFY_DATA_SIZE) + { + gnutls_assert (); + return GNUTLS_E_INTERNAL_ERROR; + } + + if ((session->security_parameters.entity == GNUTLS_CLIENT && dir == 0) || + (session->security_parameters.entity == GNUTLS_SERVER && dir == 1)) + { + priv->client_verify_data_len = vdata_size; + memcpy (priv->client_verify_data, vdata, vdata_size); + } + else + { + priv->server_verify_data_len = vdata_size; + memcpy (priv->server_verify_data, vdata, vdata_size); + } + + return 0; +} + +int _gnutls_ext_sr_verify(gnutls_session_t session) +{ +int ret; +sr_ext_st* priv = NULL; +extension_priv_data_t epriv; + + if (session->internals.priorities.sr == SR_DISABLED) + { + gnutls_assert (); + return 0; + } + + ret = _gnutls_ext_get_session_data( session, + GNUTLS_EXTENSION_SAFE_RENEGOTIATION, &epriv); + if (ret >= 0) + priv = epriv.ptr; + + /* Safe renegotiation */ + + if (priv && priv->safe_renegotiation_received) + { + if ((priv->ri_extension_data_len < priv->client_verify_data_len) || + (memcmp (priv->ri_extension_data, + priv->client_verify_data, priv->client_verify_data_len))) + { + gnutls_assert (); + _gnutls_handshake_log ("HSK[%p]: Safe renegotiation failed [1]\n", + session); + return GNUTLS_E_SAFE_RENEGOTIATION_FAILED; + } + + if (session->security_parameters.entity == GNUTLS_CLIENT) + { + if ((priv->ri_extension_data_len != + priv->client_verify_data_len + priv->server_verify_data_len) || + memcmp (priv->ri_extension_data + priv->client_verify_data_len, + priv->server_verify_data, + priv->server_verify_data_len) != 0) + { + gnutls_assert (); + _gnutls_handshake_log + ("HSK[%p]: Safe renegotiation failed [2]\n", session); + return GNUTLS_E_SAFE_RENEGOTIATION_FAILED; + } + } + else /* Make sure there are 0 extra bytes */ + { + if (priv->ri_extension_data_len != priv->client_verify_data_len) + { + gnutls_assert (); + _gnutls_handshake_log + ("HSK[%p]: Safe renegotiation failed [3]\n", session); + return GNUTLS_E_SAFE_RENEGOTIATION_FAILED; + } + } + + _gnutls_handshake_log ("HSK[%p]: Safe renegotiation succeeded\n", + session); + } + else /* safe renegotiation not received... */ + { + if (priv && priv->connection_using_safe_renegotiation) + { + gnutls_assert (); + _gnutls_handshake_log + ("HSK[%p]: Peer previously asked for safe renegotiation\n", + session); + return GNUTLS_E_SAFE_RENEGOTIATION_FAILED; + } + + /* Clients can't tell if it's an initial negotiation */ + if (session->internals.initial_negotiation_completed) + { + if (session->internals.priorities.sr < SR_PARTIAL) + { + _gnutls_handshake_log + ("HSK[%p]: Allowing unsafe (re)negotiation\n", session); + } + else + { + gnutls_assert (); + _gnutls_handshake_log + ("HSK[%p]: Denying unsafe (re)negotiation\n", session); + return GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED; + } + } + else + { + if (session->internals.priorities.sr < SR_SAFE) + { + _gnutls_handshake_log + ("HSK[%p]: Allowing unsafe initial negotiation\n", session); + } + else + { + gnutls_assert (); + _gnutls_handshake_log + ("HSK[%p]: Denying unsafe initial negotiation\n", session); + return GNUTLS_E_SAFE_RENEGOTIATION_FAILED; + } + } + } + + return 0; +} + +/* if a server received the special ciphersuite. + */ +int _gnutls_ext_sr_recv_cs(gnutls_session_t session) +{ + int ret, set = 0; + sr_ext_st* priv; + extension_priv_data_t epriv; + + ret = _gnutls_ext_get_session_data( session, + GNUTLS_EXTENSION_SAFE_RENEGOTIATION, &epriv); + if (ret < 0) + { + set = 1; + } + else if (ret < 0) + { + gnutls_assert(); + return ret; + } + + if (set != 0) + { + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) + { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + epriv.ptr = priv; + } + else + priv = epriv.ptr; + + priv->safe_renegotiation_received = 1; + priv->connection_using_safe_renegotiation = 1; + + if (set != 0) + _gnutls_ext_set_session_data( session, GNUTLS_EXTENSION_SAFE_RENEGOTIATION, epriv); + + return 0; +} + +static int +_gnutls_sr_recv_params (gnutls_session_t session, const opaque * data, size_t _data_size) { - tls_ext_st *ext = &session->security_parameters.extensions; int len = data[0]; ssize_t data_size = _data_size; + sr_ext_st* priv; + extension_priv_data_t epriv; + int set = 0, ret; DECR_LEN (data_size, len + 1 /* count the first byte and payload */ ); @@ -43,38 +258,65 @@ _gnutls_safe_renegotiation_recv_params (gnutls_session_t session, return 0; } + ret = _gnutls_ext_get_session_data( session, + GNUTLS_EXTENSION_SAFE_RENEGOTIATION, &epriv); + if (ret < 0 && session->security_parameters.entity == GNUTLS_SERVER) + { + set = 1; + } + else if (ret < 0) + { + gnutls_assert(); + return ret; + } + + if (set != 0) + { + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) + { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + epriv.ptr = priv; + } + else + priv = epriv.ptr; + /* It is not legal to receive this extension on a renegotiation and * not receive it on the initial negotiation. */ if (session->internals.initial_negotiation_completed != 0 && - session->internals.connection_using_safe_renegotiation == 0) + priv->connection_using_safe_renegotiation == 0) { gnutls_assert (); return GNUTLS_E_SAFE_RENEGOTIATION_FAILED; } - if (len > sizeof (ext->ri_extension_data)) + if (len > sizeof (priv->ri_extension_data)) { gnutls_assert (); return GNUTLS_E_SAFE_RENEGOTIATION_FAILED; } if (len > 0) - memcpy (ext->ri_extension_data, &data[1], len); - ext->ri_extension_data_len = len; + memcpy (priv->ri_extension_data, &data[1], len); + priv->ri_extension_data_len = len; /* "safe renegotiation received" means on *this* handshake; "connection using * safe renegotiation" means that the initial hello received on the connection * indicated safe renegotiation. */ - session->internals.safe_renegotiation_received = 1; - session->internals.connection_using_safe_renegotiation = 1; + priv->safe_renegotiation_received = 1; + priv->connection_using_safe_renegotiation = 1; + if (set != 0) + _gnutls_ext_set_session_data( session, GNUTLS_EXTENSION_SAFE_RENEGOTIATION, epriv); return 0; } -int -_gnutls_safe_renegotiation_send_params (gnutls_session_t session, +static int +_gnutls_sr_send_params (gnutls_session_t session, opaque * data, size_t _data_size) { /* The format of this extension is a one-byte length of verify data followed @@ -83,7 +325,9 @@ _gnutls_safe_renegotiation_send_params (gnutls_session_t session, * the minimum extension is one byte: 0x00. */ ssize_t data_size = _data_size; - tls_ext_st *ext = &session->security_parameters.extensions; + sr_ext_st* priv; + int ret, set = 0; + extension_priv_data_t epriv; if (session->internals.priorities.sr == SR_DISABLED) { @@ -91,31 +335,52 @@ _gnutls_safe_renegotiation_send_params (gnutls_session_t session, return 0; } + ret = _gnutls_ext_get_session_data( session, + GNUTLS_EXTENSION_SAFE_RENEGOTIATION, &epriv); + if (ret < 0) + { + set = 1; + } + + if (set != 0) + { + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) + { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + epriv.ptr = priv; + + _gnutls_ext_set_session_data( session, GNUTLS_EXTENSION_SAFE_RENEGOTIATION, epriv); + } + else + priv = epriv.ptr; + data[0] = 0; /* Always offer the extension if we're a client */ - if (session->internals.connection_using_safe_renegotiation || + if (priv->connection_using_safe_renegotiation || session->security_parameters.entity == GNUTLS_CLIENT) { DECR_LEN (data_size, 1); - data[0] = ext->client_verify_data_len; + data[0] = priv->client_verify_data_len; - DECR_LEN (data_size, ext->client_verify_data_len); + DECR_LEN (data_size, priv->client_verify_data_len); - if (ext->client_verify_data_len > 0) - memcpy (&data[1], ext->client_verify_data, - ext->client_verify_data_len); + if (priv->client_verify_data_len > 0) + memcpy (&data[1], priv->client_verify_data, priv->client_verify_data_len); if (session->security_parameters.entity == GNUTLS_SERVER) - { - data[0] += ext->server_verify_data_len; + { + data[0] += priv->server_verify_data_len; - DECR_LEN (data_size, ext->server_verify_data_len); + DECR_LEN (data_size, priv->server_verify_data_len); - if (ext->server_verify_data_len > 0) - memcpy (&data[1 + ext->client_verify_data_len], - ext->server_verify_data, ext->server_verify_data_len); - } + if (priv->server_verify_data_len > 0) + memcpy (&data[1 + priv->client_verify_data_len], + priv->server_verify_data, priv->server_verify_data_len); + } } else return 0; @@ -123,6 +388,58 @@ _gnutls_safe_renegotiation_send_params (gnutls_session_t session, return 1 + data[0]; /* don't forget the length byte */ } +static void _gnutls_sr_deinit_data(extension_priv_data_t priv) +{ + gnutls_free(priv.ptr); +} + +#if 0 + +static int _gnutls_sr_pack(extension_priv_data_t epriv, gnutls_buffer_st* ps) +{ +sr_ext_st* priv = epriv.ptr; +int ret; + + BUFFER_APPEND_PFX(ps, priv->client_verify_data, priv->client_verify_data_len); + BUFFER_APPEND_PFX(ps, priv->server_verify_data, priv->server_verify_data_len); + BUFFER_APPEND_PFX(ps, priv->ri_extension_data, priv->ri_extension_data_len); + + return 0; +} + +static int _gnutls_sr_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv) +{ +sr_ext_st* priv; +int ret; +extension_priv_data_t epriv; + + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) + { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + BUFFER_POP_NUM(ps, priv->client_verify_data_len); + BUFFER_POP(ps, priv->client_verify_data, priv->client_verify_data_len); + + BUFFER_POP_NUM(ps, priv->server_verify_data_len); + BUFFER_POP(ps, priv->server_verify_data, priv->server_verify_data_len); + + BUFFER_POP_NUM(ps, priv->ri_extension_data_len); + BUFFER_POP(ps, priv->ri_extension_data, priv->ri_extension_data_len); + + epriv.ptr = priv; + *_priv = epriv; + + ret = 0; + +error: + return ret; +} + +#endif + /** * gnutls_safe_renegotiation_status: * @session: is a #gnutls_session_t structure. @@ -138,5 +455,19 @@ _gnutls_safe_renegotiation_send_params (gnutls_session_t session, int gnutls_safe_renegotiation_status (gnutls_session_t session) { - return session->internals.connection_using_safe_renegotiation; +int ret; +sr_ext_st* priv; +extension_priv_data_t epriv; + + ret = _gnutls_ext_get_session_data( session, + GNUTLS_EXTENSION_SAFE_RENEGOTIATION, &epriv); + if (ret < 0) + { + gnutls_assert(); + return 0; + } + priv = epriv.ptr; + + return priv->connection_using_safe_renegotiation; } + diff --git a/lib/ext_safe_renegotiation.h b/lib/ext_safe_renegotiation.h index ca4fb7a92c..f79cca3db5 100644 --- a/lib/ext_safe_renegotiation.h +++ b/lib/ext_safe_renegotiation.h @@ -25,10 +25,26 @@ #ifndef EXT_SAFE_RENEGOTIATION_H # define EXT_SAFE_RENEGOTIATION_H -int _gnutls_safe_renegotiation_recv_params (gnutls_session_t state, - const opaque * data, - size_t data_size); -int _gnutls_safe_renegotiation_send_params (gnutls_session_t state, - opaque * data, size_t); +#include + +typedef struct { + uint8_t client_verify_data[MAX_VERIFY_DATA_SIZE]; + size_t client_verify_data_len; + uint8_t server_verify_data[MAX_VERIFY_DATA_SIZE]; + size_t server_verify_data_len; + uint8_t ri_extension_data[MAX_VERIFY_DATA_SIZE * 2]; /* max signal is 72 bytes in s->c sslv3 */ + size_t ri_extension_data_len; + + int safe_renegotiation_received:1; + int initial_negotiation_completed:1; + int connection_using_safe_renegotiation:1; +} sr_ext_st; + +extern extension_entry_st ext_mod_sr; + +int _gnutls_ext_sr_finished( gnutls_session_t session, void* vdata, + size_t vdata_size, int dir); +int _gnutls_ext_sr_recv_cs(gnutls_session_t session); +int _gnutls_ext_sr_verify(gnutls_session_t session); #endif /* EXT_SAFE_RENEGOTIATION_H */ diff --git a/lib/ext_server_name.c b/lib/ext_server_name.c index 85ff9107bd..7b2face4bb 100644 --- a/lib/ext_server_name.c +++ b/lib/ext_server_name.c @@ -29,6 +29,28 @@ #include "gnutls_num.h" #include +static int _gnutls_server_name_recv_params (gnutls_session_t session, + const opaque * data, size_t data_size); +static int _gnutls_server_name_send_params (gnutls_session_t session, + opaque * data, size_t); + +static int _gnutls_server_name_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv); +static int _gnutls_server_name_pack(extension_priv_data_t _priv, gnutls_buffer_st* ps); +static void _gnutls_server_name_deinit_data(extension_priv_data_t priv); + + +extension_entry_st ext_mod_server_name = { + .name = "SERVER NAME", + .type = GNUTLS_EXTENSION_SERVER_NAME, + .parse_type = GNUTLS_EXT_APPLICATION, + + .recv_func = _gnutls_server_name_recv_params, + .send_func = _gnutls_server_name_send_params, + .pack_func = _gnutls_server_name_pack, + .unpack_func = _gnutls_server_name_unpack, + .deinit_func = _gnutls_server_name_deinit_data, +}; + /* * In case of a server: if a NAME_DNS extension type is received then * it stores into the session the value of NAME_DNS. The server may @@ -38,9 +60,7 @@ * in the session then it sends the extension to the peer. * */ - -int -_gnutls_server_name_recv_params (gnutls_session_t session, +static int _gnutls_server_name_recv_params (gnutls_session_t session, const opaque * data, size_t _data_size) { int i; @@ -48,7 +68,9 @@ _gnutls_server_name_recv_params (gnutls_session_t session, uint16_t len, type; ssize_t data_size = _data_size; int server_names = 0; - + server_name_ext_st* priv; + extension_priv_data_t epriv; + if (session->security_parameters.entity == GNUTLS_SERVER) { DECR_LENGTH_RET (data_size, 2, 0); @@ -98,11 +120,17 @@ _gnutls_server_name_recv_params (gnutls_session_t session, server_names = MAX_SERVER_NAME_EXTENSIONS; } - session->security_parameters.extensions.server_names_size = - server_names; if (server_names == 0) return 0; /* no names found */ + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) + { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + priv->server_names_size = server_names; p = data + 2; for (i = 0; i < server_names; i++) @@ -115,15 +143,12 @@ _gnutls_server_name_recv_params (gnutls_session_t session, switch (type) { - case 0: /* NAME_DNS */ + case 0: /* NAME_DNS */ if (len <= MAX_SERVER_NAME_SIZE) { - memcpy (session->security_parameters. - extensions.server_names[i].name, p, len); - session->security_parameters.extensions.server_names[i]. - name_length = len; - session->security_parameters.extensions.server_names[i]. - type = GNUTLS_NAME_DNS; + memcpy (priv->server_names[i].name, p, len); + priv->server_names[i].name_length = len; + priv->server_names[i].type = GNUTLS_NAME_DNS; break; } } @@ -131,13 +156,18 @@ _gnutls_server_name_recv_params (gnutls_session_t session, /* move to next record */ p += len; } + + epriv.ptr = priv; + _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_SERVER_NAME, epriv); + } + return 0; } /* returns data_size or a negative number on failure */ -int +static int _gnutls_server_name_send_params (gnutls_session_t session, opaque * data, size_t _data_size) { @@ -145,27 +175,33 @@ _gnutls_server_name_send_params (gnutls_session_t session, opaque *p; unsigned i; ssize_t data_size = _data_size; - int total_size = 0; + int total_size = 0, ret; + server_name_ext_st* priv; + extension_priv_data_t epriv; + + ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SERVER_NAME, &epriv); + if (ret < 0) + return 0; + /* this function sends the client extension data (dnsname) */ if (session->security_parameters.entity == GNUTLS_CLIENT) { + priv = epriv.ptr; - if (session->security_parameters.extensions.server_names_size == 0) + if (priv->server_names_size == 0) return 0; /* uint16_t */ total_size = 2; for (i = 0; - i < session->security_parameters.extensions.server_names_size; i++) + i < priv->server_names_size; i++) { /* count the total size */ - len = - session->security_parameters.extensions. - server_names[i].name_length; + len = priv->server_names[i].name_length; /* uint8_t + uint16_t + size */ @@ -179,19 +215,14 @@ _gnutls_server_name_send_params (gnutls_session_t session, DECR_LENGTH_RET (data_size, 2, GNUTLS_E_SHORT_MEMORY_BUFFER); _gnutls_write_uint16 (total_size - 2, p); p += 2; - for (i = 0; - i < session->security_parameters.extensions.server_names_size; i++) + i < priv->server_names_size; i++) { - switch (session->security_parameters.extensions.server_names[i]. - type) + switch (priv->server_names[i].type) { case GNUTLS_NAME_DNS: - - len = - session->security_parameters.extensions.server_names[i]. - name_length; + len = priv->server_names[i].name_length; if (len == 0) break; @@ -208,9 +239,7 @@ _gnutls_server_name_send_params (gnutls_session_t session, _gnutls_write_uint16 (len, p); p += 2; - memcpy (p, - session->security_parameters.extensions.server_names[i]. - name, len); + memcpy (p, priv->server_names[i].name, len); p += len; break; default: @@ -257,28 +286,37 @@ gnutls_server_name_get (gnutls_session_t session, void *data, unsigned int *type, unsigned int indx) { char *_data = data; + server_name_ext_st* priv; + int ret; + extension_priv_data_t epriv; if (session->security_parameters.entity == GNUTLS_CLIENT) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } + + ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SERVER_NAME, &epriv); + if (ret < 0) + { + gnutls_assert(); + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + } + + priv = epriv.ptr; - if (indx + 1 > session->security_parameters.extensions.server_names_size) + if (indx + 1 > priv->server_names_size) { return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } - *type = session->security_parameters.extensions.server_names[indx].type; + *type = priv->server_names[indx].type; - if (*data_length > /* greater since we need one extra byte for the null */ - session->security_parameters.extensions.server_names[indx].name_length) + if (*data_length > /* greater since we need one extra byte for the null */ + priv->server_names[indx].name_length) { - *data_length = - session->security_parameters.extensions. - server_names[indx].name_length; - memcpy (data, - session->security_parameters.extensions.server_names[indx].name, + *data_length = priv->server_names[indx].name_length; + memcpy (data, priv->server_names[indx].name, *data_length); if (*type == GNUTLS_NAME_DNS) /* null terminate */ @@ -287,9 +325,7 @@ gnutls_server_name_get (gnutls_session_t session, void *data, } else { - *data_length = - session->security_parameters.extensions. - server_names[indx].name_length; + *data_length = priv->server_names[indx].name_length; return GNUTLS_E_SHORT_MEMORY_BUFFER; } @@ -321,7 +357,10 @@ gnutls_server_name_set (gnutls_session_t session, gnutls_server_name_type_t type, const void *name, size_t name_length) { - int server_names; + int server_names, ret; + server_name_ext_st* priv; + extension_priv_data_t epriv; + int set = 0; if (session->security_parameters.entity == GNUTLS_SERVER) { @@ -332,21 +371,95 @@ gnutls_server_name_set (gnutls_session_t session, if (name_length > MAX_SERVER_NAME_SIZE) return GNUTLS_E_SHORT_MEMORY_BUFFER; - server_names = - session->security_parameters.extensions.server_names_size + 1; + ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SERVER_NAME, &epriv); + if (ret < 0) + { + set = 1; + } + + if (set != 0) + { + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) + { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + epriv.ptr = priv; + } + else + priv = epriv.ptr; + + server_names = priv->server_names_size + 1; if (server_names > MAX_SERVER_NAME_EXTENSIONS) server_names = MAX_SERVER_NAME_EXTENSIONS; - session->security_parameters.extensions.server_names - [server_names - 1].type = type; - memcpy (session->security_parameters. - extensions.server_names[server_names - 1].name, name, name_length); - session->security_parameters.extensions.server_names[server_names - - 1].name_length = - name_length; + priv->server_names[server_names - 1].type = type; + memcpy (priv->server_names[server_names - 1].name, name, name_length); + priv->server_names[server_names - 1].name_length = name_length; + + priv->server_names_size++; + + if (set != 0) + _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_SERVER_NAME, epriv); + + return 0; +} + +static void _gnutls_server_name_deinit_data(extension_priv_data_t priv) +{ + gnutls_free(priv.ptr); +} + +static int _gnutls_server_name_pack(extension_priv_data_t epriv, gnutls_buffer_st* ps) +{ +server_name_ext_st* priv = epriv.ptr; +int i, ret; + + BUFFER_APPEND_NUM(ps, priv->server_names_size); + for (i = 0; i < priv->server_names_size;i++) + { + BUFFER_APPEND_NUM(ps, priv->server_names[i].type); + BUFFER_APPEND_PFX(ps, priv->server_names[i].name, + priv->server_names[i].name_length); + } + return 0; +} + +static int _gnutls_server_name_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv) +{ +server_name_ext_st* priv; +int i, ret; +extension_priv_data_t epriv; - session->security_parameters.extensions.server_names_size++; + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) + { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + BUFFER_POP_NUM(ps, priv->server_names_size); + for (i = 0; i < priv->server_names_size;i++) + { + BUFFER_POP_NUM(ps, priv->server_names[i].type); + BUFFER_POP_NUM(ps, priv->server_names[i].name_length); + if (priv->server_names[i].name_length > sizeof(priv->server_names[i].name)) + { + gnutls_assert(); + return GNUTLS_E_PARSING_ERROR; + } + BUFFER_POP(ps, priv->server_names[i].name, priv->server_names[i].name_length); + } + + epriv.ptr = priv; + *_priv = epriv; + return 0; + +error: + gnutls_free(priv); + return ret; } + diff --git a/lib/ext_server_name.h b/lib/ext_server_name.h index a598e1c5f0..af36ce849f 100644 --- a/lib/ext_server_name.h +++ b/lib/ext_server_name.h @@ -22,8 +22,26 @@ * USA * */ +#ifndef EXT_SERVER_NAME_H +#define EXT_SERVER_NAME_H -int _gnutls_server_name_recv_params (gnutls_session_t session, - const opaque * data, size_t data_size); -int _gnutls_server_name_send_params (gnutls_session_t session, - opaque * data, size_t); +#include + +typedef struct +{ + opaque name[MAX_SERVER_NAME_SIZE]; + unsigned name_length; + gnutls_server_name_type_t type; +} server_name_st; + +#define MAX_SERVER_NAME_EXTENSIONS 3 + +typedef struct { + server_name_st server_names[MAX_SERVER_NAME_EXTENSIONS]; + /* limit server_name extensions */ + unsigned server_names_size; +} server_name_ext_st; + +extern extension_entry_st ext_mod_server_name; + +#endif diff --git a/lib/ext_session_ticket.c b/lib/ext_session_ticket.c index 2f000fe63c..fafb1747b2 100644 --- a/lib/ext_session_ticket.c +++ b/lib/ext_session_ticket.c @@ -33,6 +33,7 @@ #include #include #include +#include #ifdef ENABLE_SESSION_TICKET @@ -43,6 +44,45 @@ #define MAC_SIZE 32 +static int session_ticket_recv_params (gnutls_session_t session, + const opaque * data, + size_t data_size); +static int session_ticket_send_params (gnutls_session_t session, + opaque * data, size_t data_size); +static int session_ticket_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv); +static int session_ticket_pack(extension_priv_data_t _priv, gnutls_buffer_st* ps); +static void session_ticket_deinit_data(extension_priv_data_t priv); + +extension_entry_st ext_mod_session_ticket = { + .name = "SESSION TICKET", + .type = GNUTLS_EXTENSION_SESSION_TICKET, + .parse_type = GNUTLS_EXT_TLS, + + .recv_func = session_ticket_recv_params, + .send_func = session_ticket_send_params, + .pack_func = session_ticket_pack, + .unpack_func = session_ticket_unpack, + .deinit_func = session_ticket_deinit_data, +}; + +struct gnutls_session_ticket_key_st +{ + opaque key_name[SESSION_TICKET_KEY_NAME_SIZE]; + opaque key[SESSION_TICKET_KEY_SIZE]; + opaque mac_secret[SESSION_TICKET_MAC_SECRET_SIZE]; +}; + +typedef struct { + int session_ticket_enable; + int session_ticket_renew; + opaque session_ticket_IV[SESSION_TICKET_IV_SIZE]; + + opaque* session_ticket; + int session_ticket_len; + + struct gnutls_session_ticket_key_st key; +} session_ticket_ext_st; + struct ticket { opaque key_name[KEY_NAME_SIZE]; @@ -79,17 +119,16 @@ digest_ticket (const gnutls_datum_t * key, struct ticket *ticket, } static int -decrypt_ticket (gnutls_session_t session, struct ticket *ticket) +decrypt_ticket (gnutls_session_t session, session_ticket_ext_st* priv, struct ticket *ticket) { cipher_hd_st cipher_hd; gnutls_datum_t key, IV, mac_secret, state; - opaque final[32]; + opaque final[MAC_SECRET_SIZE]; time_t timestamp = time (0); int ret; /* Check the integrity of ticket using HMAC-SHA-256. */ - mac_secret.data = (void *) - session->internals.session_ticket_key->mac_secret; + mac_secret.data = (void *) priv->key.mac_secret; mac_secret.size = MAC_SECRET_SIZE; ret = digest_ticket (&mac_secret, ticket, final); if (ret < 0) @@ -105,7 +144,7 @@ decrypt_ticket (gnutls_session_t session, struct ticket *ticket) } /* Decrypt encrypted_state using 128-bit AES in CBC mode. */ - key.data = (void *) session->internals.session_ticket_key->key; + key.data = (void *) priv->key.key; key.size = KEY_SIZE; IV.data = ticket->IV; IV.size = IV_SIZE; @@ -149,7 +188,7 @@ decrypt_ticket (gnutls_session_t session, struct ticket *ticket) } static int -encrypt_ticket (gnutls_session_t session, struct ticket *ticket) +encrypt_ticket (gnutls_session_t session, session_ticket_ext_st* priv, struct ticket *ticket) { cipher_hd_st cipher_hd; gnutls_datum_t key, IV, mac_secret, state, encrypted_state; @@ -164,6 +203,7 @@ encrypt_ticket (gnutls_session_t session, struct ticket *ticket) return ret; } blocksize = gnutls_cipher_get_block_size (GNUTLS_CIPHER_AES_128_CBC); + encrypted_state.size = ((state.size + blocksize - 1) / blocksize) * blocksize; encrypted_state.data = gnutls_malloc (encrypted_state.size); @@ -178,9 +218,9 @@ encrypt_ticket (gnutls_session_t session, struct ticket *ticket) _gnutls_free_datum (&state); /* Encrypt state using 128-bit AES in CBC mode. */ - key.data = (void *) session->internals.session_ticket_key->key; + key.data = (void *) priv->key.key; key.size = KEY_SIZE; - IV.data = session->internals.session_ticket_IV; + IV.data = priv->session_ticket_IV; IV.size = IV_SIZE; ret = _gnutls_cipher_init (&cipher_hd, GNUTLS_CIPHER_AES_128_CBC, &key, &IV); @@ -202,14 +242,12 @@ encrypt_ticket (gnutls_session_t session, struct ticket *ticket) } /* Fill the ticket structure to compute MAC. */ - memcpy (ticket->key_name, - session->internals.session_ticket_key->key_name, KEY_NAME_SIZE); + memcpy (ticket->key_name, priv->key.key_name, KEY_NAME_SIZE); memcpy (ticket->IV, IV.data, IV.size); ticket->encrypted_state_len = encrypted_state.size; ticket->encrypted_state = encrypted_state.data; - mac_secret.data = - (void *) session->internals.session_ticket_key->mac_secret; + mac_secret.data = priv->key.mac_secret; mac_secret.size = MAC_SECRET_SIZE; ret = digest_ticket (&mac_secret, ticket, ticket->mac); if (ret < 0) @@ -222,13 +260,24 @@ encrypt_ticket (gnutls_session_t session, struct ticket *ticket) return 0; } -int -_gnutls_session_ticket_recv_params (gnutls_session_t session, +static int +session_ticket_recv_params (gnutls_session_t session, const opaque * data, size_t _data_size) { ssize_t data_size = _data_size; + session_ticket_ext_st* priv=NULL; + extension_priv_data_t epriv; + int ret; - if (!session->internals.session_ticket_enable) + ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SESSION_TICKET, &epriv); + if (ret < 0) + { + gnutls_assert(); + return ret; + } + priv = epriv.ptr; + + if (!priv->session_ticket_enable) return 0; if (session->security_parameters.entity == GNUTLS_SERVER) @@ -240,7 +289,7 @@ _gnutls_session_ticket_recv_params (gnutls_session_t session, /* The client requested a new session ticket. */ if (data_size == 0) { - session->internals.session_ticket_renew = 1; + priv->session_ticket_renew = 1; return 0; } @@ -250,11 +299,9 @@ _gnutls_session_ticket_recv_params (gnutls_session_t session, /* If the key name of the ticket does not match the one that we hold, issue a new ticket. */ - if (memcmp (ticket.key_name, - session->internals.session_ticket_key->key_name, - KEY_NAME_SIZE)) + if (memcmp (ticket.key_name, priv->key.key_name, KEY_NAME_SIZE)) { - session->internals.session_ticket_renew = 1; + priv->session_ticket_renew = 1; return 0; } @@ -283,19 +330,19 @@ _gnutls_session_ticket_recv_params (gnutls_session_t session, memcpy (ticket.encrypted_state, encrypted_state, ticket.encrypted_state_len); - ret = decrypt_ticket (session, &ticket); + ret = decrypt_ticket (session, priv, &ticket); gnutls_free (ticket.encrypted_state); if (ret < 0) { - session->internals.session_ticket_renew = 1; + priv->session_ticket_renew = 1; return 0; } } - else + else /* Client */ { if (data_size == 0) { - session->internals.session_ticket_renew = 1; + priv->session_ticket_renew = 1; return 0; } } @@ -306,39 +353,44 @@ _gnutls_session_ticket_recv_params (gnutls_session_t session, /* returns a positive number if we send the extension data, zero if we do not want to send it, and a negative number on failure. */ -int -_gnutls_session_ticket_send_params (gnutls_session_t session, +static int +session_ticket_send_params (gnutls_session_t session, opaque * data, size_t _data_size) { ssize_t data_size = _data_size; + session_ticket_ext_st* priv=NULL; + extension_priv_data_t epriv; + int ret; - if (!session->internals.session_ticket_enable) + ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SESSION_TICKET, &epriv); + if (ret >= 0) + priv = epriv.ptr; + + if (priv == NULL || !priv->session_ticket_enable) return 0; if (session->security_parameters.entity == GNUTLS_SERVER) { - if (session->internals.session_ticket_renew) + if (priv && priv->session_ticket_renew) { return GNUTLS_E_INT_RET_0; } } else { - if (session->internals.resumed_security_parameters. - extensions.session_ticket_len > 0) + ret = _gnutls_ext_get_resumed_session_data( session, GNUTLS_EXTENSION_SESSION_TICKET, &epriv); + if (ret >= 0) + priv = epriv.ptr; + + if (ret < 0 || !priv->session_ticket_enable) + return 0; + + if (priv->session_ticket_len > 0) { - DECR_LENGTH_RET (data_size, - session->internals. - resumed_security_parameters.extensions. - session_ticket_len, GNUTLS_E_SHORT_MEMORY_BUFFER); - memcpy (data, - session->internals.resumed_security_parameters. - extensions.session_ticket, - session->internals.resumed_security_parameters. - extensions.session_ticket_len); - - return session->internals.resumed_security_parameters.extensions. - session_ticket_len; + DECR_LENGTH_RET (data_size, priv->session_ticket_len, GNUTLS_E_SHORT_MEMORY_BUFFER); + memcpy (data, priv->session_ticket, priv->session_ticket_len); + + return priv->session_ticket_len; } else { @@ -348,6 +400,55 @@ _gnutls_session_ticket_send_params (gnutls_session_t session, return 0; } + +static void session_ticket_deinit_data(extension_priv_data_t epriv) +{ +session_ticket_ext_st* priv = epriv.ptr; + + gnutls_free(priv->session_ticket); + gnutls_free(priv); +} + +static int session_ticket_pack(extension_priv_data_t epriv, gnutls_buffer_st* ps) +{ +session_ticket_ext_st* priv = epriv.ptr; +int ret; + + BUFFER_APPEND_PFX(ps, priv->session_ticket, priv->session_ticket_len); + + return 0; +} + +static int session_ticket_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv) +{ +session_ticket_ext_st* priv=NULL; +int ret; +extension_priv_data_t epriv; +gnutls_datum ticket; + + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) + { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + BUFFER_POP_DATUM(ps, &ticket); + priv->session_ticket = ticket.data; + priv->session_ticket_len = ticket.size; + + epriv.ptr = priv; + *_priv = epriv; + + ret = 0; + +error: + gnutls_free(priv); + return ret; +} + + + /** * gnutls_session_ticket_key_generate: * @key: is a pointer to a #gnutls_datum_t which will contain a newly @@ -400,13 +501,27 @@ gnutls_session_ticket_key_generate (gnutls_datum_t * key) int gnutls_session_ticket_enable_client (gnutls_session_t session) { + session_ticket_ext_st* priv=NULL; + extension_priv_data_t epriv; + if (!session) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } - session->internals.session_ticket_enable = 1; + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) + { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + priv->session_ticket_enable = 1; + epriv.ptr = priv; + + _gnutls_ext_set_session_data(session, + GNUTLS_EXTENSION_SESSION_TICKET, epriv); + return 0; } @@ -429,6 +544,8 @@ gnutls_session_ticket_enable_server (gnutls_session_t session, const gnutls_datum_t * key) { int ret; + session_ticket_ext_st* priv=NULL; + extension_priv_data_t epriv; if (!session || !key || key->size != sizeof (struct gnutls_session_ticket_key_st)) @@ -437,33 +554,31 @@ gnutls_session_ticket_enable_server (gnutls_session_t session, return GNUTLS_E_INVALID_REQUEST; } + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) + { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + epriv.ptr = priv; + ret = _gnutls_rnd (GNUTLS_RND_RANDOM, - session->internals.session_ticket_IV, IV_SIZE); + priv->session_ticket_IV, IV_SIZE); if (ret < 0) { gnutls_assert (); return ret; } - session->internals.session_ticket_key = - (struct gnutls_session_ticket_key_st *) key->data; - session->internals.session_ticket_enable = 1; + memcpy(&priv->key, key->data, key->size); + priv->session_ticket_enable = 1; + + _gnutls_ext_set_session_data(session, + GNUTLS_EXTENSION_SESSION_TICKET, epriv); + return 0; } -int -_gnutls_send_new_session_ticket (gnutls_session_t session, int again) -{ - mbuffer_st *bufel = NULL; - uint8_t *data = NULL, *p; - int data_size = 0; - int ret; - struct ticket ticket; - uint16_t ticket_len; - gnutls_cipher_algorithm_t write_bulk_cipher_algorithm; - gnutls_mac_algorithm_t write_mac_algorithm; - gnutls_compression_method_t write_compression_algorithm; - #define SAVE_WRITE_SECURITY_PARAMETERS \ do \ { \ @@ -488,8 +603,31 @@ _gnutls_send_new_session_ticket (gnutls_session_t session, int again) } \ while (0) +int +_gnutls_send_new_session_ticket (gnutls_session_t session, int again) +{ + mbuffer_st *bufel = NULL; + uint8_t *data = NULL, *p; + int data_size = 0; + int ret; + struct ticket ticket; + uint16_t ticket_len; + gnutls_cipher_algorithm_t write_bulk_cipher_algorithm; + gnutls_mac_algorithm_t write_mac_algorithm; + gnutls_compression_method_t write_compression_algorithm; + session_ticket_ext_st* priv=NULL; + extension_priv_data_t epriv; + if (again == 0) { + ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SESSION_TICKET, &epriv); + if (ret < 0) + return 0; + priv = epriv.ptr; + + if (!priv->session_ticket_renew) + return 0; + /* XXX: Temporarily set write algorithms to be used. _gnutls_write_connection_state_init() does this job, but it also triggers encryption, while NewSessionTicket should not be @@ -514,7 +652,7 @@ _gnutls_send_new_session_ticket (gnutls_session_t session, int again) if (ret < 0) return ret; - ret = encrypt_ticket (session, &ticket); + ret = encrypt_ticket (session, priv, &ticket); RESTORE_WRITE_SECURITY_PARAMETERS; if (ret < 0) { @@ -535,9 +673,8 @@ _gnutls_send_new_session_ticket (gnutls_session_t session, int again) data = _mbuffer_get_udata_ptr(bufel); p = data; - /* FIXME: ticket lifetime is fixed to 10 days, which should be - customizable. */ - _gnutls_write_uint32 (864000, p); + + _gnutls_write_uint32 ( session->internals.expire_time, p); p += 4; _gnutls_write_uint16 (ticket_len, p); @@ -576,6 +713,19 @@ _gnutls_recv_new_session_ticket (gnutls_session_t session) uint32_t lifetime_hint; uint16_t ticket_len; int ret; + session_ticket_ext_st* priv=NULL; + extension_priv_data_t epriv; + + ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SESSION_TICKET, &epriv); + if (ret < 0) + { + gnutls_assert(); + return 0; + } + priv = epriv.ptr; + + if (!priv->session_ticket_renew) + return 0; ret = _gnutls_recv_handshake (session, &data, &data_size, GNUTLS_HANDSHAKE_NEW_SESSION_TICKET, @@ -596,29 +746,26 @@ _gnutls_recv_new_session_ticket (gnutls_session_t session) p += 2; DECR_LENGTH_COM (data_size, ticket_len, goto error); - session->security_parameters.extensions.session_ticket = - gnutls_realloc (session->security_parameters.extensions.session_ticket, - ticket_len); - if (!session->security_parameters.extensions.session_ticket) + priv->session_ticket = gnutls_realloc (priv->session_ticket, ticket_len); + if (!priv->session_ticket) { gnutls_assert (); gnutls_free (data); return GNUTLS_E_MEMORY_ERROR; } - memcpy (session->security_parameters.extensions.session_ticket, - p, ticket_len); + memcpy (priv->session_ticket, p, ticket_len); gnutls_free (data); - session->security_parameters.extensions.session_ticket_len = ticket_len; + priv->session_ticket_len = ticket_len; /* Discard the current session ID. (RFC5077 3.4) */ ret = _gnutls_generate_session_id (session->security_parameters.session_id, - &session-> - security_parameters.session_id_size); + &session->security_parameters.session_id_size); if (ret < 0) { gnutls_assert (); gnutls_free (data); - gnutls_free (session->security_parameters.extensions.session_ticket); + gnutls_free (priv->session_ticket); + priv->session_ticket = NULL; return GNUTLS_E_INTERNAL_ERROR; } return 0; diff --git a/lib/ext_session_ticket.h b/lib/ext_session_ticket.h index 85a518044b..e8a531b909 100644 --- a/lib/ext_session_ticket.h +++ b/lib/ext_session_ticket.h @@ -22,15 +22,17 @@ * */ -#ifdef ENABLE_SESSION_TICKET +#ifndef EXT_SESSION_TICKET_H +# define EXT_SESSION_TICKET_H -int _gnutls_session_ticket_recv_params (gnutls_session_t session, - const opaque * data, - size_t data_size); -int _gnutls_session_ticket_send_params (gnutls_session_t session, - opaque * data, size_t data_size); +# ifdef ENABLE_SESSION_TICKET + +#include + +extern extension_entry_st ext_mod_session_ticket; int _gnutls_send_new_session_ticket (gnutls_session_t session, int again); int _gnutls_recv_new_session_ticket (gnutls_session_t session); +# endif #endif diff --git a/lib/ext_signature.c b/lib/ext_signature.c index e41e785dda..6936ff0975 100644 --- a/lib/ext_signature.c +++ b/lib/ext_signature.c @@ -35,6 +35,33 @@ #include #include +static int _gnutls_signature_algorithm_recv_params (gnutls_session_t session, + const opaque * data, + size_t data_size); +static int _gnutls_signature_algorithm_send_params (gnutls_session_t session, + opaque * data, size_t); +static void signature_algorithms_deinit_data(extension_priv_data_t priv); +static int signature_algorithms_pack(extension_priv_data_t epriv, gnutls_buffer_st* ps); +static int signature_algorithms_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv); + +extension_entry_st ext_mod_sig = { + .name = "SIGNATURE ALGORITHMS", + .type = GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, + .parse_type = GNUTLS_EXT_TLS, + + .recv_func = _gnutls_signature_algorithm_recv_params, + .send_func = _gnutls_signature_algorithm_send_params, + .pack_func = signature_algorithms_pack, + .unpack_func = signature_algorithms_unpack, + .deinit_func = signature_algorithms_deinit_data, +}; + +typedef struct { + /* TLS 1.2 signature algorithms */ + gnutls_sign_algorithm_t sign_algorithms[MAX_SIGNATURE_ALGORITHMS]; + uint16_t sign_algorithms_size; +} sig_ext_st; + /* generates a SignatureAndHashAlgorithm structure with length as prefix * by using the setup priorities. */ @@ -70,6 +97,7 @@ _gnutls_sign_algorithm_write_params (gnutls_session_t session, opaque * data, return len + 2; } + /* Parses the Signature Algorithm structure and stores data into * session->security_parameters.extensions. */ @@ -78,8 +106,15 @@ _gnutls_sign_algorithm_parse_data (gnutls_session_t session, const opaque * data, size_t data_size) { int sig, i; + sig_ext_st * priv; + extension_priv_data_t epriv; - session->security_parameters.extensions.sign_algorithms_size = 0; + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) + { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } for (i = 0; i < data_size; i += 2) { @@ -91,16 +126,16 @@ _gnutls_sign_algorithm_parse_data (gnutls_session_t session, sig = _gnutls_tls_aid_to_sign (&aid); if (sig != GNUTLS_SIGN_UNKNOWN) { - session->security_parameters.extensions.sign_algorithms[session-> - security_parameters. - extensions.sign_algorithms_size++] + priv->sign_algorithms[priv->sign_algorithms_size++] = sig; - if (session->security_parameters.extensions.sign_algorithms_size == - MAX_SIGNATURE_ALGORITHMS) + if (priv->sign_algorithms_size == MAX_SIGNATURE_ALGORITHMS) break; } } + epriv.ptr = priv; + _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, epriv); + return 0; } @@ -113,7 +148,7 @@ _gnutls_sign_algorithm_parse_data (gnutls_session_t session, * then it is an error; */ -int +static int _gnutls_signature_algorithm_recv_params (gnutls_session_t session, const opaque * data, size_t _data_size) @@ -139,7 +174,6 @@ _gnutls_signature_algorithm_recv_params (gnutls_session_t session, { uint16_t len; - DECR_LEN (data_size, 2); len = _gnutls_read_uint16 (data); DECR_LEN (data_size, len); @@ -158,7 +192,7 @@ _gnutls_signature_algorithm_recv_params (gnutls_session_t session, /* returns data_size or a negative number on failure */ -int +static int _gnutls_signature_algorithm_send_params (gnutls_session_t session, opaque * data, size_t data_size) { @@ -196,11 +230,22 @@ _gnutls_session_get_sign_algo (gnutls_session_t session, gnutls_digest_algorithm_t * hash) { unsigned i; + int ret; gnutls_protocol_t ver = gnutls_protocol_get_version (session); + sig_ext_st * priv; + extension_priv_data_t epriv; + ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, + &epriv); + if (ret < 0) + { + gnutls_assert(); + return ret; + } + priv = epriv.ptr; if (!_gnutls_version_has_selectable_sighash (ver) - || session->security_parameters.extensions.sign_algorithms_size == 0) + || priv->sign_algorithms_size == 0) /* none set, allow all */ { *hash = GNUTLS_DIG_SHA1; @@ -208,15 +253,14 @@ _gnutls_session_get_sign_algo (gnutls_session_t session, } for (i = 0; - i < session->security_parameters.extensions.sign_algorithms_size; i++) + i < priv->sign_algorithms_size; i++) { if (_gnutls_sign_get_pk_algorithm - (session->security_parameters.extensions.sign_algorithms[i]) == pk) + (priv->sign_algorithms[i]) == pk) { *hash = - _gnutls_sign_get_hash_algorithm (session->security_parameters. - extensions.sign_algorithms[i]); - return session->security_parameters.extensions.sign_algorithms[i]; + _gnutls_sign_get_hash_algorithm (priv->sign_algorithms[i]); + return priv->sign_algorithms[i]; } } @@ -233,19 +277,31 @@ _gnutls_session_sign_algo_requested (gnutls_session_t session, gnutls_sign_algorithm_t sig) { unsigned i; + int ret; gnutls_protocol_t ver = gnutls_protocol_get_version (session); + sig_ext_st * priv; + extension_priv_data_t epriv; + + ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, + &epriv); + if (ret < 0) + { + gnutls_assert(); + return ret; + } + priv = epriv.ptr; if (!_gnutls_version_has_selectable_sighash (ver) - || session->security_parameters.extensions.sign_algorithms_size == 0) + || priv->sign_algorithms_size == 0) /* none set, allow all */ { return 0; } for (i = 0; - i < session->security_parameters.extensions.sign_algorithms_size; i++) + i < priv->sign_algorithms_size; i++) { - if (session->security_parameters.extensions.sign_algorithms[i] == sig) + if (priv->sign_algorithms[i] == sig) { return 0; /* ok */ } @@ -263,10 +319,22 @@ _gnutls_session_sign_algo_enabled (gnutls_session_t session, gnutls_sign_algorithm_t sig) { unsigned i; + int ret; gnutls_protocol_t ver = gnutls_protocol_get_version (session); + sig_ext_st * priv; + extension_priv_data_t epriv; + + ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, + &epriv); + if (ret < 0) + { + gnutls_assert(); + return 0; + } + priv = epriv.ptr; if (!_gnutls_version_has_selectable_sighash (ver) - || session->security_parameters.extensions.sign_algorithms_size == 0) + || priv->sign_algorithms_size == 0) /* none set, allow all */ { return 0; @@ -283,6 +351,55 @@ _gnutls_session_sign_algo_enabled (gnutls_session_t session, return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM; } +static void signature_algorithms_deinit_data(extension_priv_data_t priv) +{ + gnutls_free(priv.ptr); +} + +static int signature_algorithms_pack(extension_priv_data_t epriv, gnutls_buffer_st* ps) +{ +sig_ext_st* priv = epriv.ptr; +int ret, i; + + BUFFER_APPEND_NUM(ps, priv->sign_algorithms_size); + for (i = 0; i < priv->sign_algorithms_size;i++) + { + BUFFER_APPEND_NUM(ps, priv->sign_algorithms[i]); + } + return 0; +} + +static int signature_algorithms_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv) +{ +sig_ext_st* priv; +int i, ret; +extension_priv_data_t epriv; + + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) + { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + BUFFER_POP_NUM(ps, priv->sign_algorithms_size); + for (i = 0; i < priv->sign_algorithms_size;i++) + { + BUFFER_POP_NUM(ps, priv->sign_algorithms[i]); + } + + epriv.ptr = priv; + *_priv = epriv; + + return 0; + +error: + gnutls_free(priv); + return ret; +} + + + /** * gnutls_sign_algorithm_get_requested: * @session: is a #gnutls_session_t structure. @@ -310,16 +427,28 @@ gnutls_sign_algorithm_get_requested (gnutls_session_t session, gnutls_sign_algorithm_t * algo) { gnutls_protocol_t ver = gnutls_protocol_get_version (session); + sig_ext_st * priv; + extension_priv_data_t epriv; + int ret; + + ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, + &epriv); + if (ret < 0) + { + gnutls_assert(); + return ret; + } + priv = epriv.ptr; if (!_gnutls_version_has_selectable_sighash (ver) - || session->security_parameters.extensions.sign_algorithms_size == 0) + || priv->sign_algorithms_size == 0) { return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } - if (indx < session->security_parameters.extensions.sign_algorithms_size) + if (indx < priv->sign_algorithms_size) { - *algo = session->security_parameters.extensions.sign_algorithms[indx]; + *algo = priv->sign_algorithms[indx]; return 0; } else diff --git a/lib/ext_signature.h b/lib/ext_signature.h index 69a05b741d..2e41b60268 100644 --- a/lib/ext_signature.h +++ b/lib/ext_signature.h @@ -25,11 +25,13 @@ /* signature algorithms extension */ -int _gnutls_signature_algorithm_recv_params (gnutls_session_t session, - const opaque * data, - size_t data_size); -int _gnutls_signature_algorithm_send_params (gnutls_session_t session, - opaque * data, size_t); +#ifndef EXT_SIGNATURE_H +# define EXT_SIGNATURE_H + +#include + +extern extension_entry_st ext_mod_sig; + int _gnutls_session_sign_algo_requested (gnutls_session_t session, gnutls_sign_algorithm_t sig); gnutls_sign_algorithm_t _gnutls_session_get_sign_algo (gnutls_session_t @@ -44,3 +46,5 @@ int _gnutls_sign_algorithm_write_params (gnutls_session_t session, opaque * data, size_t max_data_size); int _gnutls_session_sign_algo_enabled (gnutls_session_t session, gnutls_sign_algorithm_t sig); + +#endif diff --git a/lib/ext_srp.c b/lib/ext_srp.c index 650e27e758..7c36de0ffe 100644 --- a/lib/ext_srp.c +++ b/lib/ext_srp.c @@ -33,14 +33,37 @@ #include "gnutls_errors.h" #include "gnutls_algorithms.h" #include +#include -int +static int _gnutls_srp_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv); +static int _gnutls_srp_pack(extension_priv_data_t epriv, gnutls_buffer_st* ps); +static void _gnutls_srp_deinit_data(extension_priv_data_t epriv); +static int _gnutls_srp_recv_params (gnutls_session_t state, const opaque * data, + size_t data_size); +static int _gnutls_srp_send_params (gnutls_session_t state, opaque * data, size_t); + +extension_entry_st ext_mod_srp = { + .name = "SRP", + .type = GNUTLS_EXTENSION_SRP, + .parse_type = GNUTLS_EXT_TLS, + + .recv_func = _gnutls_srp_recv_params, + .send_func = _gnutls_srp_send_params, + .pack_func = _gnutls_srp_pack, + .unpack_func = _gnutls_srp_unpack, + .deinit_func = _gnutls_srp_deinit_data +}; + + +static int _gnutls_srp_recv_params (gnutls_session_t session, const opaque * data, size_t _data_size) { uint8_t len; ssize_t data_size = _data_size; - + extension_priv_data_t epriv; + srp_ext_st * priv; + if (session->security_parameters.entity == GNUTLS_SERVER) { if (data_size > 0) @@ -53,10 +76,24 @@ _gnutls_srp_recv_params (gnutls_session_t session, const opaque * data, gnutls_assert (); return GNUTLS_E_ILLEGAL_SRP_USERNAME; } - memcpy (session->security_parameters.extensions.srp_username, - &data[1], len); - /* null terminated */ - session->security_parameters.extensions.srp_username[len] = 0; + + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) + { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + priv->username = gnutls_malloc(len+1); + if (priv->username) + { + memcpy (priv->username, &data[1], len); + /* null terminated */ + priv->username[len] = 0; + } + + epriv.ptr = priv; + _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_SRP, epriv); } } return 0; @@ -65,11 +102,13 @@ _gnutls_srp_recv_params (gnutls_session_t session, const opaque * data, /* returns data_size or a negative number on failure * data is allocated locally */ -int +static int _gnutls_srp_send_params (gnutls_session_t session, opaque * data, size_t data_size) { unsigned len; + extension_priv_data_t epriv; + srp_ext_st * priv; if (_gnutls_kx_priority (session, GNUTLS_KX_SRP) < 0 && _gnutls_kx_priority (session, GNUTLS_KX_SRP_DSS) < 0 && @@ -126,8 +165,18 @@ _gnutls_srp_send_params (gnutls_session_t session, opaque * data, return GNUTLS_E_SHORT_MEMORY_BUFFER; } - session->internals.srp_username = username; - session->internals.srp_password = password; + priv = gnutls_malloc(sizeof(*priv)); + if (priv == NULL) + { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + priv->username = username; + priv->password = password; + + epriv.ptr = priv; + _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_SRP, epriv); data[0] = (uint8_t) len; memcpy (&data[1], username, len); @@ -137,4 +186,63 @@ _gnutls_srp_send_params (gnutls_session_t session, opaque * data, return 0; } +static void _gnutls_srp_deinit_data(extension_priv_data_t epriv) +{ + srp_ext_st * priv = epriv.ptr; + + gnutls_free(priv->username); + gnutls_free(priv->password); + gnutls_free(priv); +} + +static int _gnutls_srp_pack(extension_priv_data_t epriv, gnutls_buffer_st* ps) +{ +srp_ext_st* priv = epriv.ptr; +int ret; +int password_len = 0, username_len = 0; + + if (priv->username) + username_len = strlen(priv->username); + + if (priv->password) + password_len = strlen(priv->password); + + BUFFER_APPEND_PFX(ps, priv->username, username_len); + BUFFER_APPEND_PFX(ps, priv->password, password_len); + + return 0; +} + +static int _gnutls_srp_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv) +{ +srp_ext_st* priv; +int ret; +extension_priv_data_t epriv; +gnutls_datum username = { NULL, 0 }, password = {NULL, 0}; + + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) + { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + BUFFER_POP_DATUM(ps, &username); + BUFFER_POP_DATUM(ps, &password); + + priv->username = username.data; + priv->password = password.data; + + epriv.ptr = priv; + *_priv = epriv; + + return 0; + +error: + _gnutls_free_datum(&username); + _gnutls_free_datum(&password); + return ret; +} + + #endif /* ENABLE_SRP */ diff --git a/lib/ext_srp.h b/lib/ext_srp.h index 4491823026..a1146b024a 100644 --- a/lib/ext_srp.h +++ b/lib/ext_srp.h @@ -23,13 +23,23 @@ * */ -#ifdef ENABLE_SRP +#ifndef EXT_SRP_H +#define EXT_SRP_H -#define IS_SRP_KX(kx) ((kx == GNUTLS_KX_SRP || (kx == GNUTLS_KX_SRP_RSA) || \ +#include + +# ifdef ENABLE_SRP + +# define IS_SRP_KX(kx) ((kx == GNUTLS_KX_SRP || (kx == GNUTLS_KX_SRP_RSA) || \ kx == GNUTLS_KX_SRP_DSS)?1:0) -int _gnutls_srp_recv_params (gnutls_session_t state, const opaque * data, - size_t data_size); -int _gnutls_srp_send_params (gnutls_session_t state, opaque * data, size_t); +extern extension_entry_st ext_mod_srp; + +typedef struct { + char* username; + char* password; +} srp_ext_st; + +# endif #endif diff --git a/lib/gnutls_buffers.c b/lib/gnutls_buffers.c index 0b6b88bbcd..78aa8b76ee 100644 --- a/lib/gnutls_buffers.c +++ b/lib/gnutls_buffers.c @@ -218,14 +218,14 @@ _gnutls_record_buffer_get (content_type_t type, switch (type) { case GNUTLS_APPLICATION_DATA: - _gnutls_buffer_get_data (&session->internals.application_data_buffer, + _gnutls_buffer_pop_data (&session->internals.application_data_buffer, data, &length); _gnutls_buffers_log ("BUFFER[REC][AD]: Read %d bytes of Data(%d)\n", (int) length, (int) type); break; case GNUTLS_HANDSHAKE: - _gnutls_buffer_get_data (&session->internals.handshake_data_buffer, + _gnutls_buffer_pop_data (&session->internals.handshake_data_buffer, data, &length); _gnutls_buffers_log ("BUF[REC][HD]: Read %d bytes of Data(%d)\n", (int) length, (int) type); @@ -233,7 +233,7 @@ _gnutls_record_buffer_get (content_type_t type, case GNUTLS_INNER_APPLICATION: - _gnutls_buffer_get_data (&session->internals.ia_data_buffer, data, + _gnutls_buffer_pop_data (&session->internals.ia_data_buffer, data, &length); _gnutls_buffers_log ("BUF[REC][IA]: Read %d bytes of Data(%d)\n", (int) length, (int) type); @@ -839,14 +839,14 @@ _gnutls_handshake_io_recv_int (gnutls_session_t session, gnutls_assert (); tmp = sizeOfPtr; - _gnutls_buffer_get_data (&session->internals.handshake_recv_buffer, + _gnutls_buffer_pop_data (&session->internals.handshake_recv_buffer, iptr, &tmp); return tmp; } gnutls_assert (); tmp = sizeOfPtr; - _gnutls_buffer_get_data (&session->internals.handshake_recv_buffer, + _gnutls_buffer_pop_data (&session->internals.handshake_recv_buffer, iptr, &tmp); left -= tmp; diff --git a/lib/gnutls_constate.c b/lib/gnutls_constate.c index f6d58cc430..b91abc4657 100644 --- a/lib/gnutls_constate.c +++ b/lib/gnutls_constate.c @@ -35,6 +35,7 @@ #include #include #include +#include static const char keyexp[] = "key expansion"; static const int keyexp_length = sizeof (keyexp) - 1; @@ -381,13 +382,6 @@ _gnutls_set_write_keys (gnutls_session_t session) export_flag); } -#define CPY_EXTENSIONS \ - gnutls_free(dst->extensions.session_ticket); \ - gnutls_free(dst->extensions.oprfi_client); \ - gnutls_free(dst->extensions.oprfi_server); \ - memcpy(&dst->extensions.server_names, &src->extensions, sizeof(src->extensions)); \ - memset(&src->extensions, 0, sizeof(src->extensions)) /* avoid duplicate free's */ - #define CPY_COMMON dst->entity = src->entity; \ dst->kx_algorithm = src->kx_algorithm; \ memcpy( &dst->current_cipher_suite, &src->current_cipher_suite, sizeof(cipher_suite_st)); \ @@ -400,8 +394,7 @@ _gnutls_set_write_keys (gnutls_session_t session) dst->timestamp = src->timestamp; \ dst->max_record_recv_size = src->max_record_recv_size; \ dst->max_record_send_size = src->max_record_send_size; \ - dst->version = src->version; \ - memcpy( &dst->inner_secret, &src->inner_secret, GNUTLS_MASTER_SIZE) + dst->version = src->version static void _gnutls_cpy_read_security_parameters (security_parameters_st * @@ -419,7 +412,6 @@ _gnutls_cpy_write_security_parameters (security_parameters_st * dst, security_parameters_st * src) { CPY_COMMON; - CPY_EXTENSIONS; /* only do once */ dst->write_bulk_cipher_algorithm = src->write_bulk_cipher_algorithm; dst->write_mac_algorithm = src->write_mac_algorithm; @@ -493,7 +485,7 @@ _gnutls_read_connection_state_init (gnutls_session_t session) return rc; } else - { /* RESUME_TRUE */ + { /* RESUME_TRUE */ _gnutls_cpy_read_security_parameters (&session->security_parameters, &session-> internals.resumed_security_parameters); @@ -681,6 +673,7 @@ _gnutls_write_connection_state_init (gnutls_session_t session) _gnutls_cpy_write_security_parameters (&session->security_parameters, &session-> internals.resumed_security_parameters); + _gnutls_ext_restore_resumed_session(session); } rc = _gnutls_set_write_keys (session); diff --git a/lib/gnutls_extensions.c b/lib/gnutls_extensions.c index 9a1b8f9a25..f316d5c7ce 100644 --- a/lib/gnutls_extensions.c +++ b/lib/gnutls_extensions.c @@ -34,7 +34,6 @@ #include "ext_max_record.h" #include #include -#include #include #include #include @@ -42,28 +41,26 @@ #include #include -typedef struct -{ - const char *name; - uint16_t type; - gnutls_ext_parse_type_t parse_type; - /* this function must return 0 when Not Applicable - * size of extension data if ok - * < 0 on other error. - */ - gnutls_ext_recv_func recv_func; +static void _gnutls_ext_unset_resumed_session_data(gnutls_session_t session, uint16_t type); - /* this function must return 0 when Not Applicable - * size of extension data if ok - * GNUTLS_E_INT_RET_0 if extension data size is zero - * < 0 on other error. - */ - gnutls_ext_send_func send_func; -} gnutls_extension_entry; static size_t extfunc_size = 0; -static gnutls_extension_entry *extfunc = NULL; +static extension_entry_st *extfunc = NULL; + +static gnutls_ext_parse_type_t +_gnutls_ext_parse_type (uint16_t type) +{ + size_t i; + + for (i = 0; i < extfunc_size; i++) + { + if (extfunc[i].type == type) + return extfunc[i].parse_type; + } + + return GNUTLS_EXT_NONE; +} static gnutls_ext_recv_func _gnutls_ext_func_recv (uint16_t type, gnutls_ext_parse_type_t parse_type) @@ -78,6 +75,31 @@ _gnutls_ext_func_recv (uint16_t type, gnutls_ext_parse_type_t parse_type) return NULL; } +static gnutls_ext_deinit_data_func +_gnutls_ext_func_deinit (uint16_t type) +{ + size_t i; + + for (i = 0; i < extfunc_size; i++) + if (extfunc[i].type == type) + return extfunc[i].deinit_func; + + return NULL; +} + +static gnutls_ext_unpack_func +_gnutls_ext_func_unpack (uint16_t type) +{ + size_t i; + + for (i = 0; i < extfunc_size; i++) + if (extfunc[i].type == type) + return extfunc[i].unpack_func; + + return NULL; +} + + static const char * _gnutls_extension_get_name (uint16_t type) { @@ -236,7 +258,7 @@ _gnutls_gen_extensions (gnutls_session_t session, opaque * data, pos += 2; for (i = 0; i < extfunc_size; i++) { - gnutls_extension_entry *p = &extfunc[i]; + extension_entry_st *p = &extfunc[i]; if (p->send_func == NULL) continue; @@ -272,8 +294,8 @@ _gnutls_gen_extensions (gnutls_session_t session, opaque * data, */ _gnutls_extension_list_add (session, p->type); - _gnutls_debug_log ("EXT[%p]: Sending extension %s\n", - session, p->name); + _gnutls_debug_log ("EXT[%p]: Sending extension %s (%d bytes)\n", + session, p->name, size); } else if (size < 0) { @@ -303,73 +325,37 @@ _gnutls_ext_init (void) { int ret; - ret = gnutls_ext_register (GNUTLS_EXTENSION_MAX_RECORD_SIZE, - "MAX_RECORD_SIZE", - GNUTLS_EXT_TLS, - _gnutls_max_record_recv_params, - _gnutls_max_record_send_params); + ret = _gnutls_ext_register (&ext_mod_max_record_size); if (ret != GNUTLS_E_SUCCESS) return ret; - ret = gnutls_ext_register (GNUTLS_EXTENSION_CERT_TYPE, - "CERT_TYPE", - GNUTLS_EXT_TLS, - _gnutls_cert_type_recv_params, - _gnutls_cert_type_send_params); + ret = _gnutls_ext_register (&ext_mod_cert_type); if (ret != GNUTLS_E_SUCCESS) return ret; - ret = gnutls_ext_register (GNUTLS_EXTENSION_SERVER_NAME, - "SERVER_NAME", - GNUTLS_EXT_APPLICATION, - _gnutls_server_name_recv_params, - _gnutls_server_name_send_params); - if (ret != GNUTLS_E_SUCCESS) - return ret; - ret = gnutls_ext_register (GNUTLS_EXTENSION_SAFE_RENEGOTIATION, - "SAFE_RENEGOTIATION", - GNUTLS_EXT_MANDATORY, - _gnutls_safe_renegotiation_recv_params, - _gnutls_safe_renegotiation_send_params); + ret = _gnutls_ext_register (&ext_mod_server_name); if (ret != GNUTLS_E_SUCCESS) return ret; -#ifdef ENABLE_OPRFI - ret = gnutls_ext_register (GNUTLS_EXTENSION_OPAQUE_PRF_INPUT, - "OPAQUE_PRF_INPUT", - GNUTLS_EXT_TLS, - _gnutls_oprfi_recv_params, - _gnutls_oprfi_send_params); + ret = _gnutls_ext_register (&ext_mod_sr); if (ret != GNUTLS_E_SUCCESS) return ret; -#endif #ifdef ENABLE_SRP - ret = gnutls_ext_register (GNUTLS_EXTENSION_SRP, - "SRP", - GNUTLS_EXT_TLS, - _gnutls_srp_recv_params, - _gnutls_srp_send_params); + ret = _gnutls_ext_register (&ext_mod_srp); if (ret != GNUTLS_E_SUCCESS) return ret; #endif + #ifdef ENABLE_SESSION_TICKET - ret = gnutls_ext_register (GNUTLS_EXTENSION_SESSION_TICKET, - "SESSION_TICKET", - GNUTLS_EXT_TLS, - _gnutls_session_ticket_recv_params, - _gnutls_session_ticket_send_params); + ret = _gnutls_ext_register (&ext_mod_session_ticket); if (ret != GNUTLS_E_SUCCESS) return ret; #endif - ret = gnutls_ext_register (GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, - "SIGNATURE_ALGORITHMS", - GNUTLS_EXT_TLS, - _gnutls_signature_algorithm_recv_params, - _gnutls_signature_algorithm_send_params); + ret = _gnutls_ext_register (&ext_mod_sig); if (ret != GNUTLS_E_SUCCESS) return ret; @@ -384,6 +370,27 @@ _gnutls_ext_deinit (void) extfunc_size = 0; } +int +_gnutls_ext_register (extension_entry_st* mod) +{ + extension_entry_st *p; + + p = gnutls_realloc (extfunc, sizeof (*extfunc) * (extfunc_size + 1)); + if (!p) + { + gnutls_assert (); + return GNUTLS_E_MEMORY_ERROR; + } + + extfunc = p; + + memcpy(&extfunc[extfunc_size], mod, sizeof(*mod)); + + extfunc_size++; + + return GNUTLS_E_SUCCESS; +} + /** * gnutls_ext_register: * @type: the 16-bit integer referring to the extension type @@ -405,23 +412,288 @@ gnutls_ext_register (int type, gnutls_ext_recv_func recv_func, gnutls_ext_send_func send_func) { - gnutls_extension_entry *p; +extension_entry_st ee; + + memset(&ee, 0, sizeof(ee)); + + ee.type = type; + ee.name = name; + ee.parse_type = parse_type; + ee.recv_func = recv_func; + ee.send_func = send_func; + /* FIXME: Why is this exported? Should it be removed? */ + return _gnutls_ext_register (&ee); +} - p = gnutls_realloc (extfunc, sizeof (*extfunc) * (extfunc_size + 1)); - if (!p) +int _gnutls_ext_pack(gnutls_session_t session, gnutls_buffer_st* packed) +{ +int i, ret; +extension_priv_data_t data; +int cur_size; +void* size_pos; +void* total_exts_pos; +int exts = 0; + + total_exts_pos = packed->data + packed->length; + + BUFFER_APPEND_NUM(packed, 0); + + for (i = 0; i < extfunc_size; i++) { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; + ret = _gnutls_ext_get_session_data(session, extfunc[i].type, &data); + if (ret >= 0 && extfunc[i].pack_func != NULL) + { + BUFFER_APPEND_NUM(packed, extfunc[i].type); + + size_pos = packed->data + packed->length; + + BUFFER_APPEND_NUM(packed, 0); + + cur_size = packed->length; + + ret = extfunc[i].pack_func(data, packed); + if (ret < 0) + { + gnutls_assert(); + return ret; + } + + exts++; + /* write the actual size */ + _gnutls_write_uint32(packed->length-cur_size, size_pos); + } } - extfunc = p; - extfunc[extfunc_size].type = type; - extfunc[extfunc_size].name = name; - extfunc[extfunc_size].parse_type = parse_type; - extfunc[extfunc_size].recv_func = recv_func; - extfunc[extfunc_size].send_func = send_func; + _gnutls_write_uint32(exts, total_exts_pos); - extfunc_size++; + return 0; + +} - return GNUTLS_E_SUCCESS; +void _gnutls_ext_restore_resumed_session(gnutls_session_t session) +{ +int i; + + + /* clear everything except MANDATORY extensions */ + for (i=0;iinternals.extension_int_data[i].set != 0 && + _gnutls_ext_parse_type(session->internals.extension_int_data[i].type) != GNUTLS_EXT_MANDATORY) + { + _gnutls_ext_unset_session_data(session, session->internals.extension_int_data[i].type); + } + } + + /* copy resumed to main */ + for (i=0;iinternals.resumed_extension_int_data[i].set != 0 && + _gnutls_ext_parse_type(session->internals.resumed_extension_int_data[i].type) != GNUTLS_EXT_MANDATORY) + { + _gnutls_ext_set_session_data(session, session->internals.resumed_extension_int_data[i].type, + session->internals.resumed_extension_int_data[i].priv); + session->internals.resumed_extension_int_data[i].set = 0; + } + } + +} + + +static void _gnutls_ext_set_resumed_session_data(gnutls_session_t session, uint16_t type, + extension_priv_data_t data) +{ +int i; + + for (i=0;iinternals.resumed_extension_int_data[i].type == type) + { + + if (session->internals.resumed_extension_int_data[i].set != 0) + _gnutls_ext_unset_resumed_session_data(session, type); + + session->internals.resumed_extension_int_data[i].type = type; + session->internals.resumed_extension_int_data[i].priv = data; + session->internals.resumed_extension_int_data[i].set = 1; + return; + } + } +} + +int _gnutls_ext_unpack(gnutls_session_t session, gnutls_buffer_st* packed) +{ +int i, ret; +extension_priv_data_t data; +gnutls_ext_unpack_func unpack; +int max_exts = 0; +uint16_t type; +int size_for_type, cur_pos; + + BUFFER_POP_NUM(packed, max_exts); + for (i = 0; i < max_exts; i++) + { + BUFFER_POP_NUM(packed, type); + BUFFER_POP_NUM(packed, size_for_type); + + cur_pos = packed->length; + + unpack = _gnutls_ext_func_unpack(type); + if (unpack == NULL) + { + gnutls_assert(); + return GNUTLS_E_PARSING_ERROR; + } + + ret = unpack(packed, &data); + if (ret < 0) + { + gnutls_assert(); + return ret; + } + + /* verify that unpack read the correct bytes */ + cur_pos = cur_pos - packed->length; + if (cur_pos /* read length */ != size_for_type) + { + gnutls_assert(); + return GNUTLS_E_PARSING_ERROR; + } + _gnutls_ext_set_resumed_session_data(session, type, data); + } + + return 0; + +error: + return ret; +} + +void _gnutls_ext_unset_session_data(gnutls_session_t session, uint16_t type) +{ +gnutls_ext_deinit_data_func deinit; +extension_priv_data_t data; +int ret, i; + + deinit = _gnutls_ext_func_deinit (type); + ret = _gnutls_ext_get_session_data(session, type, &data); + + if (ret >= 0 && deinit != NULL) + { + deinit(data); + } + + for (i=0;iinternals.extension_int_data[i].type == type) + { + session->internals.extension_int_data[i].set = 0; + return; + } + } + +} + +static void _gnutls_ext_unset_resumed_session_data(gnutls_session_t session, uint16_t type) +{ +gnutls_ext_deinit_data_func deinit; +extension_priv_data_t data; +int ret, i; + + deinit = _gnutls_ext_func_deinit (type); + ret = _gnutls_ext_get_resumed_session_data(session, type, &data); + + if (ret >= 0 && deinit != NULL) + { + deinit(data); + } + + for (i=0;iinternals.resumed_extension_int_data[i].type == type) + { + session->internals.resumed_extension_int_data[i].set = 0; + return; + } + } + +} + +/* Deinitializes all data that are associated with TLS extensions. + */ +void _gnutls_ext_free_session_data(gnutls_session_t session) +{ +int i; + + for (i = 0; i < extfunc_size; i++) + { + _gnutls_ext_unset_session_data(session, extfunc[i].type); + } + + for (i = 0; i < extfunc_size; i++) + { + _gnutls_ext_unset_resumed_session_data(session, extfunc[i].type); + } + +} + +/* This function allows and extension to store data in the current session + * and retrieve them later on. We use functions instead of a pointer to a + * private pointer, to allow API additions by individual extensions. + */ +void _gnutls_ext_set_session_data(gnutls_session_t session, uint16_t type, + extension_priv_data_t data) +{ +int i; +gnutls_ext_deinit_data_func deinit; + + deinit = _gnutls_ext_func_deinit (type); + + for (i=0;iinternals.extension_int_data[i].type == type || session->internals.extension_int_data[i].set == 0) + { + if (session->internals.extension_int_data[i].set != 0) + { + if (deinit) deinit(session->internals.extension_int_data[i].priv); + } + session->internals.extension_int_data[i].type = type; + session->internals.extension_int_data[i].priv = data; + session->internals.extension_int_data[i].set = 1; + return; + } + } +} + +int _gnutls_ext_get_session_data(gnutls_session_t session, + uint16_t type, extension_priv_data_t* data) +{ +int i; + + for (i=0;iinternals.extension_int_data[i].set != 0 && + session->internals.extension_int_data[i].type == type) + { + *data = session->internals.extension_int_data[i].priv; + return 0; + } + } + return GNUTLS_E_INVALID_REQUEST; +} + +int _gnutls_ext_get_resumed_session_data(gnutls_session_t session, + uint16_t type, extension_priv_data_t* data) +{ +int i; + + for (i=0;iinternals.resumed_extension_int_data[i].set != 0 && + session->internals.resumed_extension_int_data[i].type == type) + { + *data = session->internals.resumed_extension_int_data[i].priv; + return 0; + } + } + return GNUTLS_E_INVALID_REQUEST; } diff --git a/lib/gnutls_extensions.h b/lib/gnutls_extensions.h index 6c6f891793..3c450e8993 100644 --- a/lib/gnutls_extensions.h +++ b/lib/gnutls_extensions.h @@ -23,6 +23,9 @@ * */ +#ifndef GNUTLS_EXTENSIONS_H +#define GNUTLS_EXTENSIONS_H + int _gnutls_parse_extensions (gnutls_session_t session, gnutls_ext_parse_type_t parse_type, const opaque * data, int data_size); @@ -32,3 +35,56 @@ int _gnutls_ext_init (void); void _gnutls_ext_deinit (void); void _gnutls_extension_list_add (gnutls_session_t session, uint16_t type); + +typedef void (*gnutls_ext_deinit_data_func) (extension_priv_data_t data); +typedef int (*gnutls_ext_pack_func) (extension_priv_data_t data, gnutls_buffer_st* packed_data); +typedef int (*gnutls_ext_unpack_func) (gnutls_buffer_st* packed_data, extension_priv_data_t* data); + +void _gnutls_ext_free_session_data(gnutls_session_t session); + +/* functions to be used by extensions internally + */ +void _gnutls_ext_unset_session_data(gnutls_session_t session, uint16_t type); +void _gnutls_ext_set_session_data(gnutls_session_t session, uint16_t type, + extension_priv_data_t); +int _gnutls_ext_get_session_data(gnutls_session_t session, + uint16_t type, extension_priv_data_t*); +int _gnutls_ext_get_resumed_session_data(gnutls_session_t session, + uint16_t type, extension_priv_data_t* data); + +void _gnutls_ext_restore_resumed_session(gnutls_session_t session); + +/* for session packing */ +int _gnutls_ext_pack(gnutls_session_t session, gnutls_buffer_st* packed); +int _gnutls_ext_unpack(gnutls_session_t session, gnutls_buffer_st* packed); + +typedef struct +{ + const char *name; + uint16_t type; + gnutls_ext_parse_type_t parse_type; + + /* this function must return 0 when Not Applicable + * size of extension data if ok + * < 0 on other error. + */ + gnutls_ext_recv_func recv_func; + + /* this function must return 0 when Not Applicable + * size of extension data if ok + * GNUTLS_E_INT_RET_0 if extension data size is zero + * < 0 on other error. + */ + gnutls_ext_send_func send_func; + + gnutls_ext_deinit_data_func deinit_func; /* this will be called to deinitialize + * internal data + */ + gnutls_ext_pack_func pack_func; /* packs internal data to machine independent format */ + gnutls_ext_unpack_func unpack_func; /* unpacks internal data */ + +} extension_entry_st; + +int _gnutls_ext_register (extension_entry_st*); + +#endif diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c index 95bbb3ddcd..278c7c6a8c 100644 --- a/lib/gnutls_handshake.c +++ b/lib/gnutls_handshake.c @@ -697,27 +697,12 @@ _gnutls_send_finished (gnutls_session_t session, int again) if (session->internals.finished_func) session->internals.finished_func (session, data, vdata_size); - /* Save data for safe renegotiation. - */ - if (vdata_size > MAX_VERIFY_DATA_SIZE) - { - gnutls_assert (); - return GNUTLS_E_INTERNAL_ERROR; - } - - if (session->security_parameters.entity == GNUTLS_CLIENT) - { - session->security_parameters.extensions.client_verify_data_len = - vdata_size; - - memcpy (session->security_parameters.extensions.client_verify_data, data, vdata_size); - } - else - { - session->security_parameters.extensions.server_verify_data_len = vdata_size; - memcpy (session->security_parameters.extensions.server_verify_data, - data, vdata_size); - } + ret = _gnutls_ext_sr_finished( session, data, vdata_size, 0); + if (ret < 0) + { + gnutls_assert(); + return ret; + } ret = _gnutls_send_handshake (session, bufel, GNUTLS_HANDSHAKE_FINISHED); } @@ -739,7 +724,6 @@ _gnutls_recv_finished (gnutls_session_t session) int data_size; int ret; int vrfysize; - tls_ext_st *ext; ret = _gnutls_recv_handshake (session, &vrfy, &vrfysize, @@ -797,24 +781,11 @@ _gnutls_recv_finished (gnutls_session_t session) } gnutls_free (vrfy); - /* Save peer's verify data for safe renegotiation */ - if (data_size > MAX_VERIFY_DATA_SIZE) - { - gnutls_assert (); - return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; - } - - ext = &session->security_parameters.extensions; - - if (session->security_parameters.entity == GNUTLS_CLIENT) - { - memcpy (ext->server_verify_data, data, data_size); - ext->server_verify_data_len = data_size; - } - else + ret = _gnutls_ext_sr_finished( session, data, data_size, 1); + if (ret < 0) { - memcpy (ext->client_verify_data, data, data_size); - ext->client_verify_data_len = data_size; + gnutls_assert(); + return ret; } session->internals.initial_negotiation_completed = 1; @@ -886,8 +857,12 @@ _gnutls_server_select_suite (gnutls_session_t session, opaque * data, { _gnutls_handshake_log ("HSK[%p]: Received safe renegotiation CS\n", session); - session->internals.safe_renegotiation_received = 1; - session->internals.connection_using_safe_renegotiation = 1; + retval = _gnutls_ext_sr_recv_cs(session); + if (retval < 0) + { + gnutls_assert(); + return retval; + } break; } } @@ -1938,7 +1913,7 @@ _gnutls_copy_comp_methods (gnutls_session_t session, /* This should be sufficient by now. It should hold all the extensions * plus the headers in a hello message. */ -#define MAX_EXT_DATA_LENGTH 1024 +#define MAX_EXT_DATA_LENGTH 4096 /* This function sends the client hello handshake message. */ @@ -1976,10 +1951,7 @@ _gnutls_send_client_hello (gnutls_session_t session, int again) return GNUTLS_E_MEMORY_ERROR; } data = _mbuffer_get_udata_ptr(bufel); - extdatalen = MAX_EXT_DATA_LENGTH - + - session->internals.resumed_security_parameters. - extensions.session_ticket_len; + extdatalen = MAX_EXT_DATA_LENGTH; extdata = gnutls_malloc (extdatalen); if (extdata == NULL) @@ -2079,7 +2051,7 @@ _gnutls_send_client_hello (gnutls_session_t session, int again) if (ret > 0) { - bufel = _mbuffer_append_data (bufel, extdata, ret); + bufel = _mbuffer_push_data (bufel, extdata, ret); if (bufel == NULL) { gnutls_assert (); @@ -2103,7 +2075,7 @@ _gnutls_send_client_hello (gnutls_session_t session, int again) ret = _gnutls_copy_comp_methods (session, extdata, extdatalen); if (ret > 0) { - bufel = _mbuffer_append_data (bufel, extdata, ret); + bufel = _mbuffer_push_data (bufel, extdata, ret); if (bufel == NULL) { gnutls_assert (); @@ -2137,7 +2109,7 @@ _gnutls_send_client_hello (gnutls_session_t session, int again) if (ret > 0) { - bufel = _mbuffer_append_data (bufel, extdata, ret); + bufel = _mbuffer_push_data (bufel, extdata, ret); if (bufel == NULL) { gnutls_assert (); @@ -2176,28 +2148,6 @@ _gnutls_send_server_hello (gnutls_session_t session, int again) datalen = 0; -#ifdef ENABLE_SRP - if (IS_SRP_KX - (_gnutls_cipher_suite_get_kx_algo - (&session->security_parameters.current_cipher_suite))) - { - /* While resuming we cannot check the username extension since it is - * not available at this point. It will be copied on connection - * state activation. - */ - if (session->internals.resumed == RESUME_FALSE && - session->security_parameters.extensions.srp_username[0] == 0) - { - /* The peer didn't send a valid SRP extension with the - * SRP username. The draft requires that we send a fatal - * alert and abort. - */ - gnutls_assert (); - return GNUTLS_E_UNKNOWN_SRP_USERNAME; - } - } -#endif - if (again == 0) { datalen = 2 + session_id_len + 1 + GNUTLS_RANDOM_SIZE + 3; @@ -2269,8 +2219,6 @@ _gnutls_send_hello (gnutls_session_t session, int again) { int ret; - session->internals.safe_renegotiation_received = 0; - if (session->security_parameters.entity == GNUTLS_CLIENT) { ret = _gnutls_send_client_hello (session, again); @@ -2292,7 +2240,6 @@ int _gnutls_recv_hello (gnutls_session_t session, opaque * data, int datalen) { int ret; - tls_ext_st *ext; if (session->security_parameters.entity == GNUTLS_CLIENT) { @@ -2314,101 +2261,14 @@ _gnutls_recv_hello (gnutls_session_t session, opaque * data, int datalen) } } - if (session->internals.priorities.sr == SR_DISABLED) - { - gnutls_assert (); - return ret; - } - - /* Safe renegotiation */ - ext = &session->security_parameters.extensions; - - if (session->internals.safe_renegotiation_received) - { - if ((ext->ri_extension_data_len < ext->client_verify_data_len) || - (memcmp (ext->ri_extension_data, - ext->client_verify_data, ext->client_verify_data_len))) - { - gnutls_assert (); - _gnutls_handshake_log ("HSK[%p]: Safe renegotiation failed [1]\n", - session); - return GNUTLS_E_SAFE_RENEGOTIATION_FAILED; - } - - if (session->security_parameters.entity == GNUTLS_CLIENT) - { - if ((ext->ri_extension_data_len != - ext->client_verify_data_len + ext->server_verify_data_len) || - memcmp (ext->ri_extension_data + ext->client_verify_data_len, - ext->server_verify_data, - ext->server_verify_data_len) != 0) - { - gnutls_assert (); - _gnutls_handshake_log - ("HSK[%p]: Safe renegotiation failed [2]\n", session); - return GNUTLS_E_SAFE_RENEGOTIATION_FAILED; - } - } - else /* Make sure there are 0 extra bytes */ - { - if (ext->ri_extension_data_len != ext->client_verify_data_len) - { - gnutls_assert (); - _gnutls_handshake_log - ("HSK[%p]: Safe renegotiation failed [3]\n", session); - return GNUTLS_E_SAFE_RENEGOTIATION_FAILED; - } - } - - _gnutls_handshake_log ("HSK[%p]: Safe renegotiation succeeded\n", - session); - } - else /* safe renegotiation not received... */ + ret = _gnutls_ext_sr_verify(session); + if (ret < 0) { - if (session->internals.connection_using_safe_renegotiation) - { - gnutls_assert (); - _gnutls_handshake_log - ("HSK[%p]: Peer previously asked for safe renegotiation\n", - session); - return GNUTLS_E_SAFE_RENEGOTIATION_FAILED; - } - - /* Clients can't tell if it's an initial negotiation */ - if (session->internals.initial_negotiation_completed) - { - - if (session->internals.priorities.sr < SR_PARTIAL) - { - _gnutls_handshake_log - ("HSK[%p]: Allowing unsafe (re)negotiation\n", session); - } - else - { - gnutls_assert (); - _gnutls_handshake_log - ("HSK[%p]: Denying unsafe (re)negotiation\n", session); - return GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED; - } - } - else - { - if (session->internals.priorities.sr < SR_SAFE) - { - _gnutls_handshake_log - ("HSK[%p]: Allowing unsafe initial negotiation\n", session); - } - else - { - gnutls_assert (); - _gnutls_handshake_log - ("HSK[%p]: Denying unsafe initial negotiation\n", session); - return GNUTLS_E_SAFE_RENEGOTIATION_FAILED; - } - } + gnutls_assert(); + return ret; } - return ret; + return 0; } /* The packets in gnutls_handshake (it's more broad than original TLS handshake) @@ -2767,7 +2627,7 @@ _gnutls_handshake_client (gnutls_session_t session) IMED_RET ("recv hello", ret, 1); case STATE70: - if (session->security_parameters.extensions.do_recv_supplemental) + if (session->security_parameters.do_recv_supplemental) { ret = _gnutls_recv_supplemental (session); STATE = STATE70; @@ -2808,7 +2668,7 @@ _gnutls_handshake_client (gnutls_session_t session) IMED_RET ("recv server hello done", ret, 1); case STATE71: - if (session->security_parameters.extensions.do_send_supplemental) + if (session->security_parameters.do_send_supplemental) { ret = _gnutls_send_supplemental (session, AGAIN (STATE71)); STATE = STATE71; @@ -2867,7 +2727,6 @@ _gnutls_send_handshake_final (gnutls_session_t session, int init) gnutls_assert (); return ret; } - /* Initialize the connection session (start encryption) - in case of client */ if (init == TRUE) @@ -2991,7 +2850,7 @@ _gnutls_handshake_server (gnutls_session_t session) IMED_RET ("send hello", ret, 0); case STATE70: - if (session->security_parameters.extensions.do_send_supplemental) + if (session->security_parameters.do_send_supplemental) { ret = _gnutls_send_supplemental (session, AGAIN (STATE70)); STATE = STATE70; @@ -3033,7 +2892,7 @@ _gnutls_handshake_server (gnutls_session_t session) IMED_RET ("send server hello done", ret, 0); case STATE71: - if (session->security_parameters.extensions.do_recv_supplemental) + if (session->security_parameters.do_recv_supplemental) { ret = _gnutls_recv_supplemental (session); STATE = STATE71; @@ -3091,13 +2950,9 @@ _gnutls_handshake_common (gnutls_session_t session) { case STATE0: case STATE40: - if (session->internals.session_ticket_renew) - { - ret = - _gnutls_send_new_session_ticket (session, AGAIN (STATE40)); - STATE = STATE40; - IMED_RET ("send handshake new session ticket", ret, 0); - } + ret = _gnutls_send_new_session_ticket (session, AGAIN (STATE40)); + STATE = STATE40; + IMED_RET ("send handshake new session ticket", ret, 0); STATE = STATE0; default: break; @@ -3125,12 +2980,9 @@ _gnutls_handshake_common (gnutls_session_t session) { case STATE0: case STATE41: - if (session->internals.session_ticket_renew) - { - ret = _gnutls_recv_new_session_ticket (session); - STATE = STATE41; - IMED_RET ("recv handshake new session ticket", ret, 1); - } + ret = _gnutls_recv_new_session_ticket (session); + STATE = STATE41; + IMED_RET ("recv handshake new session ticket", ret, 1); STATE = STATE0; default: break; diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index aa727c16bf..b099f111c0 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -95,7 +95,7 @@ typedef struct /* we can receive up to MAX_EXT_TYPES extensions. */ -#define MAX_EXT_TYPES 64 +#define MAX_EXT_TYPES 32 /* The initial size of the receive * buffer size. This will grow if larger @@ -172,9 +172,6 @@ typedef enum extensions_t { GNUTLS_EXTENSION_SERVER_NAME = 0, GNUTLS_EXTENSION_MAX_RECORD_SIZE = 1, GNUTLS_EXTENSION_CERT_TYPE = 9, -#ifdef ENABLE_OPRFI - GNUTLS_EXTENSION_OPAQUE_PRF_INPUT = ENABLE_OPRFI, -#endif GNUTLS_EXTENSION_SRP = 12, GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS = 13, GNUTLS_EXTENSION_SESSION_TICKET = 35, @@ -185,12 +182,8 @@ typedef enum extensions_t typedef enum { CIPHER_STREAM, CIPHER_BLOCK } cipher_type_t; -typedef enum valid_session_t -{ VALID_TRUE, VALID_FALSE } valid_session_t; -typedef enum resumable_session_t -{ RESUME_TRUE, - RESUME_FALSE -} resumable_session_t; +#define RESUME_TRUE 0 +#define RESUME_FALSE -1 /* Record Protocol */ typedef enum content_type_t @@ -315,69 +308,10 @@ typedef struct * structures also - see SRP). */ -typedef struct -{ - opaque name[MAX_SERVER_NAME_SIZE]; - unsigned name_length; - gnutls_server_name_type_t type; -} server_name_st; - -#define MAX_SERVER_NAME_EXTENSIONS 3 #define MAX_SIGNATURE_ALGORITHMS 16 -struct gnutls_session_ticket_key_st -{ - opaque key_name[SESSION_TICKET_KEY_NAME_SIZE]; - opaque key[SESSION_TICKET_KEY_SIZE]; - opaque mac_secret[SESSION_TICKET_MAC_SECRET_SIZE]; -}; - #define MAX_VERIFY_DATA_SIZE 36 /* in SSL 3.0, 12 in TLS 1.0 */ -/* If you want the extension data to be kept across resuming sessions - * then modify CPY_EXTENSIONS in gnutls_constate.c - */ -typedef struct -{ - server_name_st server_names[MAX_SERVER_NAME_EXTENSIONS]; - /* limit server_name extensions */ - unsigned server_names_size; - - opaque srp_username[MAX_SRP_USERNAME + 1]; - - /* TLS 1.2 signature algorithms */ - gnutls_sign_algorithm_t sign_algorithms[MAX_SIGNATURE_ALGORITHMS]; - uint16_t sign_algorithms_size; - - /* TLS/IA data. */ - int gnutls_ia_enable, gnutls_ia_peer_enable; - int gnutls_ia_allowskip, gnutls_ia_peer_allowskip; - - /* Used by extensions that enable supplemental data. */ - int do_recv_supplemental, do_send_supplemental; - - opaque *session_ticket; - uint16_t session_ticket_len; - - /*** Those below do not get copied when resuming session - ***/ - - /* Opaque PRF input. */ - opaque *oprfi_client; - uint16_t oprfi_client_len; - opaque *oprfi_server; - uint16_t oprfi_server_len; - - /* Safe renegotiation. */ - uint8_t client_verify_data[MAX_VERIFY_DATA_SIZE]; - size_t client_verify_data_len; - uint8_t server_verify_data[MAX_VERIFY_DATA_SIZE]; - size_t server_verify_data_len; - uint8_t ri_extension_data[MAX_VERIFY_DATA_SIZE * 2]; /* max signal is 72 bytes in s->c sslv3 */ - size_t ri_extension_data_len; - -} tls_ext_st; - /* auth_info_t structures now MAY contain malloced * elements. */ @@ -424,7 +358,6 @@ typedef struct opaque session_id[TLS_MAX_SESSION_ID_SIZE]; uint8_t session_id_size; time_t timestamp; - tls_ext_st extensions; /* The send size is the one requested by the programmer. * The recv size is the one negotiated with the peer. @@ -435,8 +368,14 @@ typedef struct gnutls_certificate_type_t cert_type; gnutls_protocol_t version; /* moved here */ - /* For TLS/IA. XXX: Move to IA credential? */ - opaque inner_secret[GNUTLS_MASTER_SIZE]; + /* FIXME: The following are not saved in the session storage + * for session resumption. + */ + + /* Used by extensions that enable supplemental data: Which ones + * do that? Do they belong in security parameters? + */ + int do_recv_supplemental, do_send_supplemental; } security_parameters_st; /* This structure holds the generated keys @@ -529,6 +468,11 @@ typedef struct gnutls_handshake_description_t recv_type; } handshake_header_buffer_st; +typedef union +{ + void* ptr; + uint32_t num; +} extension_priv_data_t; typedef struct { @@ -552,7 +496,7 @@ typedef struct gnutls_buffer_st handshake_data_buffer; /* this is a buffer that holds the current handshake message */ gnutls_buffer_st ia_data_buffer; /* holds inner application data (TLS/IA) */ - resumable_session_t resumable; /* TRUE or FALSE - if we can resume that session */ + int resumable:1; /* TRUE or FALSE - if we can resume that session */ handshake_state_t handshake_state; /* holds * a number which indicates where * the handshake procedure has been @@ -560,12 +504,12 @@ typedef struct * no interruption has happened. */ - valid_session_t valid_connection; /* true or FALSE - if this session is valid */ + int invalid_connection:1; /* true or FALSE - if this session is valid */ - int may_not_read; /* if it's 0 then we can read/write, otherwise it's forbiden to read/write + int may_not_read:1; /* if it's 0 then we can read/write, otherwise it's forbiden to read/write */ - int may_not_write; - int read_eof; /* non-zero if we have received a closure alert. */ + int may_not_write:1; + int read_eof:1; /* non-zero if we have received a closure alert. */ int last_alert; /* last alert received */ @@ -581,7 +525,7 @@ typedef struct struct gnutls_priority_st priorities; /* resumed session */ - resumable_session_t resumed; /* RESUME_TRUE or FALSE - if we are resuming a session */ + int resumed:1; /* RESUME_TRUE or FALSE - if we are resuming a session */ security_parameters_st resumed_security_parameters; /* sockets internals */ @@ -607,7 +551,7 @@ typedef struct /* 0 if no peeked data was kept, 1 otherwise. */ - int have_peeked_data; + int have_peeked_data:1; int expire_time; /* after expire_time seconds this session will expire */ struct mod_auth_st_int *auth_struct; /* used in handshake packets and KX algorithms */ @@ -662,11 +606,6 @@ typedef struct */ gnutls_handshake_post_client_hello_func user_hello_func; - /* Holds the record size requested by the - * user. - */ - uint16_t proposed_record_size; - /* holds the selected certificate and key. * use _gnutls_selected_certs_deinit() and _gnutls_selected_certs_set() * to change them. @@ -674,7 +613,7 @@ typedef struct gnutls_cert *selected_cert_list; int selected_cert_list_length; struct gnutls_privkey_st *selected_key; - int selected_need_free; + int selected_need_free:1; /* holds the extensions we sent to the peer * (in case of a client) @@ -691,8 +630,6 @@ typedef struct * record packet will have. */ opaque default_record_version[2]; - int cbc_protection_hack; - void *user_ptr; int enable_private; /* non zero to @@ -721,9 +658,6 @@ typedef struct */ opaque rsa_pms_version[2]; - char *srp_username; - char *srp_password; - /* Here we cache the DH or RSA parameters got from the * credentials structure, or from a callback. That is to * minimize external calls. @@ -759,19 +693,19 @@ typedef struct */ uint16_t srp_prime_bits; - int session_ticket_enable, session_ticket_renew; - - int safe_renegotiation_received:1; int initial_negotiation_completed:1; - int connection_using_safe_renegotiation:1; - - /* Oprfi */ - gnutls_oprfi_callback_func oprfi_cb; - const void *oprfi_userdata; - /* Session Ticket */ - struct gnutls_session_ticket_key_st *session_ticket_key; - opaque session_ticket_IV[SESSION_TICKET_IV_SIZE]; + struct { + uint16_t type; + extension_priv_data_t priv; + int set:1; + } extension_int_data[MAX_EXT_TYPES]; + + struct { + uint16_t type; + extension_priv_data_t priv; + int set:1; + } resumed_extension_int_data[MAX_EXT_TYPES]; /* If you add anything here, check _gnutls_handshake_internal_state_clear(). */ diff --git a/lib/gnutls_kx.c b/lib/gnutls_kx.c index 9d3cae9616..9f1f5a7927 100644 --- a/lib/gnutls_kx.c +++ b/lib/gnutls_kx.c @@ -39,6 +39,7 @@ #include #include #include +#include "../libextra/ext_inner_application.h" /* isn't this too much? */ /* This is a temporary function to be used before the generate_* internal API is changed to use mbuffers. For now we don't avoid the @@ -123,64 +124,6 @@ generate_normal_master (gnutls_session_t session, int keep_premaster) security_parameters.master_secret); } - else if (session->security_parameters.extensions.oprfi_client_len > 0 && - session->security_parameters.extensions.oprfi_server_len > 0) - { - opaque *rnd; - size_t rndlen = 2 * GNUTLS_RANDOM_SIZE; - - rndlen += session->security_parameters.extensions.oprfi_client_len; - rndlen += session->security_parameters.extensions.oprfi_server_len; - - rnd = gnutls_malloc (rndlen + 1); - if (!rnd) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - - _gnutls_hard_log ("INT: CLIENT OPRFI[%d]: %s\n", - session->security_parameters.extensions. - oprfi_server_len, - _gnutls_bin2hex (session-> - security_parameters.extensions. - oprfi_client, - session-> - security_parameters.extensions. - oprfi_client_len, buf, - sizeof (buf), NULL)); - _gnutls_hard_log ("INT: SERVER OPRFI[%d]: %s\n", - session->security_parameters.extensions. - oprfi_server_len, - _gnutls_bin2hex (session-> - security_parameters.extensions. - oprfi_server, - session-> - security_parameters.extensions. - oprfi_server_len, buf, - sizeof (buf), NULL)); - - memcpy (rnd, session->security_parameters.client_random, - GNUTLS_RANDOM_SIZE); - memcpy (rnd + GNUTLS_RANDOM_SIZE, - session->security_parameters.extensions.oprfi_client, - session->security_parameters.extensions.oprfi_client_len); - memcpy (rnd + GNUTLS_RANDOM_SIZE + - session->security_parameters.extensions.oprfi_client_len, - session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); - memcpy (rnd + GNUTLS_RANDOM_SIZE + - session->security_parameters.extensions.oprfi_client_len + - GNUTLS_RANDOM_SIZE, - session->security_parameters.extensions.oprfi_server, - session->security_parameters.extensions.oprfi_server_len); - - ret = _gnutls_PRF (session, PREMASTER.data, PREMASTER.size, - MASTER_SECRET, strlen (MASTER_SECRET), - rnd, rndlen, GNUTLS_MASTER_SIZE, - session->security_parameters.master_secret); - - gnutls_free (rnd); - } else { opaque rnd[2 * GNUTLS_RANDOM_SIZE + 1]; @@ -198,8 +141,7 @@ generate_normal_master (gnutls_session_t session, int keep_premaster) } /* TLS/IA inner secret is derived from the master secret. */ - memcpy (session->security_parameters.inner_secret, - session->security_parameters.master_secret, GNUTLS_MASTER_SIZE); + _gnutls_ia_derive_inner_secret(session); if (!keep_premaster) _gnutls_free_datum (&PREMASTER); diff --git a/lib/gnutls_mbuffers.c b/lib/gnutls_mbuffers.c index 2c9e9d8135..db9763bc4b 100644 --- a/lib/gnutls_mbuffers.c +++ b/lib/gnutls_mbuffers.c @@ -152,7 +152,7 @@ _mbuffer_alloc (size_t payload_size) } mbuffer_st* -_mbuffer_append_data (mbuffer_st *bufel, void* newdata, size_t newdata_size) +_mbuffer_push_data (mbuffer_st *bufel, void* newdata, size_t newdata_size) { bufel = gnutls_realloc_fast (bufel, bufel->msg.size+newdata_size+sizeof (mbuffer_st)); if (bufel == NULL) diff --git a/lib/gnutls_mbuffers.h b/lib/gnutls_mbuffers.h index a1a6065328..3580a420e2 100644 --- a/lib/gnutls_mbuffers.h +++ b/lib/gnutls_mbuffers.h @@ -37,7 +37,7 @@ mbuffer_st* _mbuffer_alloc (size_t payload_size); /* This is dangerous since it will replace bufel with a new * one. */ -mbuffer_st* _mbuffer_append_data (mbuffer_st *bufel, void* newdata, size_t newdata_size); +mbuffer_st* _mbuffer_push_data (mbuffer_st *bufel, void* newdata, size_t newdata_size); /* For "user" use. One can have buffer data and header. diff --git a/lib/gnutls_record.c b/lib/gnutls_record.c index a3a0409e71..c2c3a9b30a 100644 --- a/lib/gnutls_record.c +++ b/lib/gnutls_record.c @@ -273,7 +273,7 @@ gnutls_bye (gnutls_session_t session, gnutls_close_request_t how) inline static void session_invalidate (gnutls_session_t session) { - session->internals.valid_connection = VALID_FALSE; + session->internals.invalid_connection = 1; } @@ -288,7 +288,7 @@ session_unresumable (gnutls_session_t session) inline static int session_is_valid (gnutls_session_t session) { - if (session->internals.valid_connection == VALID_FALSE) + if (session->internals.invalid_connection != 0) return GNUTLS_E_INVALID_SESSION; return 0; @@ -1173,64 +1173,3 @@ gnutls_record_recv (gnutls_session_t session, void *data, size_t sizeofdata) sizeofdata); } -/** - * gnutls_record_get_max_size: - * @session: is a #gnutls_session_t structure. - * - * Get the record size. The maximum record size is negotiated by the - * client after the first handshake message. - * - * Returns: The maximum record packet size in this connection. - **/ -size_t -gnutls_record_get_max_size (gnutls_session_t session) -{ - /* Recv will hold the negotiated max record size - * always. - */ - return session->security_parameters.max_record_recv_size; -} - - -/** - * gnutls_record_set_max_size: - * @session: is a #gnutls_session_t structure. - * @size: is the new size - * - * This function sets the maximum record packet size in this - * connection. This property can only be set to clients. The server - * may choose not to accept the requested size. - * - * Acceptable values are 512(=2^9), 1024(=2^10), 2048(=2^11) and - * 4096(=2^12). The requested record size does get in effect - * immediately only while sending data. The receive part will take - * effect after a successful handshake. - * - * This function uses a TLS extension called 'max record size'. Not - * all TLS implementations use or even understand this extension. - * - * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned, - * otherwise an error code is returned. - **/ -ssize_t -gnutls_record_set_max_size (gnutls_session_t session, size_t size) -{ - ssize_t new_size; - - if (session->security_parameters.entity == GNUTLS_SERVER) - return GNUTLS_E_INVALID_REQUEST; - - new_size = _gnutls_mre_record2num (size); - - if (new_size < 0) - { - gnutls_assert (); - return new_size; - } - - session->security_parameters.max_record_send_size = size; - - session->internals.proposed_record_size = size; - - return 0; -} diff --git a/lib/gnutls_session_pack.c b/lib/gnutls_session_pack.c index 0ca3b0c29f..03e7909cd2 100644 --- a/lib/gnutls_session_pack.c +++ b/lib/gnutls_session_pack.c @@ -41,34 +41,33 @@ #include #include #include +#include -#define PACK_HEADER_SIZE 1 -#define MAX_SEC_PARAMS 7+MAX_SRP_USERNAME+MAX_SERVER_NAME_EXTENSIONS*(3+MAX_SERVER_NAME_SIZE)+165 static int pack_certificate_auth_info (gnutls_session_t, - gnutls_datum_t * packed_session); + gnutls_buffer_st * packed_session); static int unpack_certificate_auth_info (gnutls_session_t, - const gnutls_datum_t * + gnutls_buffer_st * packed_session); static int unpack_srp_auth_info (gnutls_session_t session, - const gnutls_datum_t * packed_session); + gnutls_buffer_st * packed_session); static int pack_srp_auth_info (gnutls_session_t session, - gnutls_datum_t * packed_session); + gnutls_buffer_st * packed_session); static int unpack_psk_auth_info (gnutls_session_t session, - const gnutls_datum_t * packed_session); + gnutls_buffer_st * packed_session); static int pack_psk_auth_info (gnutls_session_t session, - gnutls_datum_t * packed_session); + gnutls_buffer_st * packed_session); static int unpack_anon_auth_info (gnutls_session_t session, - const gnutls_datum_t * packed_session); + gnutls_buffer_st * packed_session); static int pack_anon_auth_info (gnutls_session_t session, - gnutls_datum_t * packed_session); + gnutls_buffer_st * packed_session); static int unpack_security_parameters (gnutls_session_t session, - const gnutls_datum_t * packed_session); + gnutls_buffer_st * packed_session); static int pack_security_parameters (gnutls_session_t session, - gnutls_datum_t * packed_session); + gnutls_buffer_st * packed_session); /* Since auth_info structures contain malloced data, this function @@ -84,6 +83,8 @@ _gnutls_session_pack (gnutls_session_t session, gnutls_datum_t * packed_session) { int ret; + gnutls_buffer_st sb; + opaque id; if (packed_session == NULL) { @@ -91,12 +92,16 @@ _gnutls_session_pack (gnutls_session_t session, return GNUTLS_E_INTERNAL_ERROR; } + _gnutls_buffer_init(&sb); - switch (gnutls_auth_get_type (session)) + id = gnutls_auth_get_type (session); + BUFFER_APPEND(&sb, &id, 1); + + switch (id) { #ifdef ENABLE_SRP case GNUTLS_CRD_SRP: - ret = pack_srp_auth_info (session, packed_session); + ret = pack_srp_auth_info (session, &sb); if (ret < 0) { gnutls_assert (); @@ -106,7 +111,7 @@ _gnutls_session_pack (gnutls_session_t session, #endif #ifdef ENABLE_PSK case GNUTLS_CRD_PSK: - ret = pack_psk_auth_info (session, packed_session); + ret = pack_psk_auth_info (session, &sb); if (ret < 0) { gnutls_assert (); @@ -116,7 +121,7 @@ _gnutls_session_pack (gnutls_session_t session, #endif #ifdef ENABLE_ANON case GNUTLS_CRD_ANON: - ret = pack_anon_auth_info (session, packed_session); + ret = pack_anon_auth_info (session, &sb); if (ret < 0) { gnutls_assert (); @@ -125,7 +130,7 @@ _gnutls_session_pack (gnutls_session_t session, break; #endif case GNUTLS_CRD_CERTIFICATE: - ret = pack_certificate_auth_info (session, packed_session); + ret = pack_certificate_auth_info (session, &sb); if (ret < 0) { gnutls_assert (); @@ -140,15 +145,25 @@ _gnutls_session_pack (gnutls_session_t session, /* Auth_info structures copied. Now copy security_parameters_st. * packed_session must have allocated space for the security parameters. */ - ret = pack_security_parameters (session, packed_session); + ret = pack_security_parameters (session, &sb); if (ret < 0) { gnutls_assert (); - _gnutls_free_datum (packed_session); + _gnutls_buffer_clear(&sb); return ret; } - - return 0; + + ret = _gnutls_ext_pack(session, &sb); + if (ret < 0) + { + gnutls_assert (); + _gnutls_buffer_clear(&sb); + return ret; + } + + ret = _gnutls_buffer_to_datum(&sb, packed_session); + + return ret; } @@ -159,6 +174,10 @@ _gnutls_session_unpack (gnutls_session_t session, const gnutls_datum_t * packed_session) { int ret; + gnutls_buffer_st sb; + opaque id; + + _gnutls_buffer_init(&sb); if (packed_session == NULL || packed_session->size == 0) { @@ -166,36 +185,45 @@ _gnutls_session_unpack (gnutls_session_t session, return GNUTLS_E_INTERNAL_ERROR; } + ret = _gnutls_buffer_append_data(&sb, packed_session->data, packed_session->size); + if (ret < 0) + { + gnutls_assert(); + return ret; + } + if (_gnutls_get_auth_info (session) != NULL) { _gnutls_free_auth_info (session); } - switch (packed_session->data[0]) + BUFFER_POP(&sb, &id, 1); + + switch (id) { #ifdef ENABLE_SRP case GNUTLS_CRD_SRP: - ret = unpack_srp_auth_info (session, packed_session); + ret = unpack_srp_auth_info (session, &sb); if (ret < 0) { gnutls_assert (); - return ret; + goto error; } break; #endif #ifdef ENABLE_PSK case GNUTLS_CRD_PSK: - ret = unpack_psk_auth_info (session, packed_session); + ret = unpack_psk_auth_info (session, &sb); if (ret < 0) { gnutls_assert (); - return ret; + goto error; } break; #endif #ifdef ENABLE_ANON case GNUTLS_CRD_ANON: - ret = unpack_anon_auth_info (session, packed_session); + ret = unpack_anon_auth_info (session, &sb); if (ret < 0) { gnutls_assert (); @@ -204,33 +232,47 @@ _gnutls_session_unpack (gnutls_session_t session, break; #endif case GNUTLS_CRD_CERTIFICATE: - ret = unpack_certificate_auth_info (session, packed_session); + ret = unpack_certificate_auth_info (session, &sb); if (ret < 0) { gnutls_assert (); - return ret; + goto error; } break; default: gnutls_assert (); - return GNUTLS_E_INTERNAL_ERROR; + ret = GNUTLS_E_INTERNAL_ERROR; + goto error; } /* Auth_info structures copied. Now copy security_parameters_st. * packed_session must have allocated space for the security parameters. */ - ret = unpack_security_parameters (session, packed_session); + ret = unpack_security_parameters (session, &sb); if (ret < 0) { gnutls_assert (); - return ret; + goto error; + } + + ret = _gnutls_ext_unpack(session, &sb); + if (ret < 0) + { + gnutls_assert (); + goto error; } - return 0; + ret = 0; + +error: + _gnutls_buffer_clear(&sb); + + return ret; } + /* Format: * 1 byte the credentials type * 4 bytes the size of the whole structure @@ -255,78 +297,37 @@ _gnutls_session_unpack (gnutls_session_t session, */ static int pack_certificate_auth_info (gnutls_session_t session, - gnutls_datum_t * packed_session) + gnutls_buffer_st * ps) { - unsigned int pos = 0, i; - int cert_size, pack_size; + unsigned int i; + int cur_size, ret; cert_auth_info_t info = _gnutls_get_auth_info (session); + void* size_pos; - if (info) - { - cert_size = 4; + size_pos = ps->data + ps->length; - for (i = 0; i < info->ncerts; i++) - cert_size += 4 + info->raw_certificate_list[i].size; - - pack_size = 2 + 4 + info->dh.prime.size + - 4 + info->dh.generator.size + 4 + info->dh.public_key.size + - 4 + info->rsa_export.modulus.size + - 4 + info->rsa_export.exponent.size + cert_size; - } - else - pack_size = 0; - - packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof (uint32_t); - - /* calculate the size and allocate the data. - */ - packed_session->data = - gnutls_malloc (packed_session->size + MAX_SEC_PARAMS + 2 + - session->security_parameters.extensions. - session_ticket_len); + BUFFER_APPEND_NUM(ps, 0); + cur_size = ps->length; - if (packed_session->data == NULL) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - - packed_session->data[0] = GNUTLS_CRD_CERTIFICATE; - _gnutls_write_uint32 (pack_size, &packed_session->data[PACK_HEADER_SIZE]); - pos += 4 + PACK_HEADER_SIZE; - - - if (pack_size > 0) + if (info) { - _gnutls_write_uint16 (info->dh.secret_bits, &packed_session->data[pos]); - pos += 2; - - _gnutls_write_datum32 (&packed_session->data[pos], info->dh.prime); - pos += 4 + info->dh.prime.size; - _gnutls_write_datum32 (&packed_session->data[pos], info->dh.generator); - pos += 4 + info->dh.generator.size; - _gnutls_write_datum32 (&packed_session->data[pos], info->dh.public_key); - pos += 4 + info->dh.public_key.size; + BUFFER_APPEND_NUM( ps, info->dh.secret_bits); + BUFFER_APPEND_PFX( ps, info->dh.prime.data, info->dh.prime.size); + BUFFER_APPEND_PFX( ps, info->dh.generator.data, info->dh.generator.size); + BUFFER_APPEND_PFX( ps, info->dh.public_key.data, info->dh.public_key.size); + BUFFER_APPEND_PFX( ps, info->rsa_export.modulus.data, info->rsa_export.modulus.size); + BUFFER_APPEND_PFX( ps, info->rsa_export.exponent.data, info->rsa_export.exponent.size); - _gnutls_write_datum32 (&packed_session->data[pos], - info->rsa_export.modulus); - pos += 4 + info->rsa_export.modulus.size; - _gnutls_write_datum32 (&packed_session->data[pos], - info->rsa_export.exponent); - pos += 4 + info->rsa_export.exponent.size; - - _gnutls_write_uint32 (info->ncerts, &packed_session->data[pos]); - pos += 4; + BUFFER_APPEND_NUM( ps, info->ncerts); for (i = 0; i < info->ncerts; i++) - { - _gnutls_write_datum32 (&packed_session->data[pos], - info->raw_certificate_list[i]); - pos += sizeof (uint32_t) + info->raw_certificate_list[i].size; - } + BUFFER_APPEND_PFX( ps, info->raw_certificate_list[i].data, info->raw_certificate_list[i].size); } + /* write the real size */ + _gnutls_write_uint32(ps->length-cur_size, size_pos); + return 0; } @@ -335,32 +336,18 @@ pack_certificate_auth_info (gnutls_session_t session, */ static int unpack_certificate_auth_info (gnutls_session_t session, - const gnutls_datum_t * packed_session) + gnutls_buffer_st * ps) { - int pos = 0, size, ret; - unsigned int i = 0, j; + int ret; + unsigned int i = 0, j = 0; size_t pack_size; - cert_auth_info_t info; - - if (packed_session->data[0] != GNUTLS_CRD_CERTIFICATE) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } + cert_auth_info_t info = NULL; - pack_size = _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]); - pos += PACK_HEADER_SIZE + 4; + BUFFER_POP_NUM(ps, pack_size); if (pack_size == 0) return 0; /* nothing to be done */ - /* a simple check for integrity */ - if (pack_size + PACK_HEADER_SIZE + 4 > packed_session->size) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - /* client and server have the same auth_info here */ ret = @@ -379,113 +366,49 @@ unpack_certificate_auth_info (gnutls_session_t session, return GNUTLS_E_INTERNAL_ERROR; } - info->dh.secret_bits = _gnutls_read_uint16 (&packed_session->data[pos]); - pos += 2; - - size = _gnutls_read_uint32 (&packed_session->data[pos]); - pos += 4; - ret = _gnutls_set_datum (&info->dh.prime, &packed_session->data[pos], size); - if (ret < 0) - { - gnutls_assert (); - goto error; - } - pos += size; - - size = _gnutls_read_uint32 (&packed_session->data[pos]); - pos += 4; - ret = - _gnutls_set_datum (&info->dh.generator, &packed_session->data[pos], size); - if (ret < 0) - { - gnutls_assert (); - goto error; - } - pos += size; - - size = _gnutls_read_uint32 (&packed_session->data[pos]); - pos += 4; - ret = - _gnutls_set_datum (&info->dh.public_key, &packed_session->data[pos], - size); - if (ret < 0) - { - gnutls_assert (); - goto error; - } - pos += size; - - size = _gnutls_read_uint32 (&packed_session->data[pos]); - pos += 4; - ret = - _gnutls_set_datum (&info->rsa_export.modulus, - &packed_session->data[pos], size); - if (ret < 0) - { - gnutls_assert (); - goto error; - } - pos += size; + BUFFER_POP_NUM(ps, info->dh.secret_bits); - size = _gnutls_read_uint32 (&packed_session->data[pos]); - pos += 4; - ret = - _gnutls_set_datum (&info->rsa_export.exponent, - &packed_session->data[pos], size); - if (ret < 0) - { - gnutls_assert (); - goto error; - } - pos += size; + BUFFER_POP_DATUM(ps, &info->dh.prime); + BUFFER_POP_DATUM(ps, &info->dh.generator); + BUFFER_POP_DATUM(ps, &info->dh.public_key); + BUFFER_POP_DATUM(ps, &info->rsa_export.modulus); + BUFFER_POP_DATUM(ps, &info->rsa_export.exponent); - info->ncerts = _gnutls_read_uint32 (&packed_session->data[pos]); - pos += 4; + BUFFER_POP_NUM(ps, info->ncerts); if (info->ncerts > 0) { - info->raw_certificate_list = - gnutls_calloc (info->ncerts, sizeof (gnutls_datum_t)); + info->raw_certificate_list = gnutls_calloc (info->ncerts, sizeof (gnutls_datum_t)); if (info->raw_certificate_list == NULL) - { - gnutls_assert (); - ret = GNUTLS_E_MEMORY_ERROR; - goto error; - } + { + gnutls_assert (); + ret = GNUTLS_E_MEMORY_ERROR; + goto error; + } } for (i = 0; i < info->ncerts; i++) { - size = _gnutls_read_uint32 (&packed_session->data[pos]); - pos += sizeof (uint32_t); - - ret = - _gnutls_set_datum (&info->raw_certificate_list[i], - &packed_session->data[pos], size); - pos += size; - - if (ret < 0) - { - gnutls_assert (); - goto error; - } + BUFFER_POP_DATUM(ps, &info->raw_certificate_list[i]); } - return 0; error: - _gnutls_free_datum (&info->dh.prime); - _gnutls_free_datum (&info->dh.generator); - _gnutls_free_datum (&info->dh.public_key); + if (info) + { + _gnutls_free_datum (&info->dh.prime); + _gnutls_free_datum (&info->dh.generator); + _gnutls_free_datum (&info->dh.public_key); - _gnutls_free_datum (&info->rsa_export.modulus); - _gnutls_free_datum (&info->rsa_export.exponent); + _gnutls_free_datum (&info->rsa_export.modulus); + _gnutls_free_datum (&info->rsa_export.exponent); - for (j = 0; j < i; j++) - _gnutls_free_datum (&info->raw_certificate_list[j]); + for (j = 0; j < i; j++) + _gnutls_free_datum (&info->raw_certificate_list[j]); - gnutls_free (info->raw_certificate_list); + gnutls_free (info->raw_certificate_list); + } return ret; @@ -501,37 +424,27 @@ error: * x bytes the SRP username */ static int -pack_srp_auth_info (gnutls_session_t session, gnutls_datum_t * packed_session) +pack_srp_auth_info (gnutls_session_t session, gnutls_buffer_st * ps) { srp_server_auth_info_t info = _gnutls_get_auth_info (session); - int pack_size; + int len, ret; + void* size_pos; + size_t cur_size; if (info && info->username) - pack_size = strlen (info->username) + 1; /* include the terminating null */ + len = strlen (info->username) + 1; /* include the terminating null */ else - pack_size = 0; + len = 0; - packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof (uint32_t); + size_pos = ps->data + ps->length; - /* calculate the size and allocate the data. - */ - packed_session->data = - gnutls_malloc (packed_session->size + MAX_SEC_PARAMS + 2 + - session->security_parameters.extensions. - session_ticket_len); + BUFFER_APPEND_NUM(ps, 0); + cur_size = ps->length; - if (packed_session->data == NULL) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - - packed_session->data[0] = GNUTLS_CRD_SRP; - _gnutls_write_uint32 (pack_size, &packed_session->data[PACK_HEADER_SIZE]); + BUFFER_APPEND_PFX(ps, info->username, len); - if (pack_size > 0) - memcpy (&packed_session->data[PACK_HEADER_SIZE + sizeof (uint32_t)], - info->username, pack_size + 1); + /* write the real size */ + _gnutls_write_uint32(ps->length-cur_size, size_pos); return 0; } @@ -539,30 +452,19 @@ pack_srp_auth_info (gnutls_session_t session, gnutls_datum_t * packed_session) static int unpack_srp_auth_info (gnutls_session_t session, - const gnutls_datum_t * packed_session) + gnutls_buffer_st * ps) { size_t username_size; int ret; srp_server_auth_info_t info; - if (packed_session->data[0] != GNUTLS_CRD_SRP) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - username_size = - _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]); - - if (username_size == 0) - return 0; /* nothing to be done */ - - /* a simple check for integrity */ - if (username_size + 4 + PACK_HEADER_SIZE > packed_session->size) + BUFFER_POP_NUM(ps, username_size); + if (username_size > sizeof(info->username)) { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; } + ret = _gnutls_auth_info_set (session, GNUTLS_CRD_SRP, @@ -580,11 +482,12 @@ unpack_srp_auth_info (gnutls_session_t session, return GNUTLS_E_INTERNAL_ERROR; } - memcpy (info->username, - &packed_session->data[PACK_HEADER_SIZE + sizeof (uint32_t)], - username_size); + BUFFER_POP(ps, info->username, username_size); - return 0; + ret = 0; + +error: + return ret; } #endif @@ -606,50 +509,27 @@ unpack_srp_auth_info (gnutls_session_t session, */ static int pack_anon_auth_info (gnutls_session_t session, - gnutls_datum_t * packed_session) + gnutls_buffer_st * ps) { + int cur_size, ret; anon_auth_info_t info = _gnutls_get_auth_info (session); - int pos = 0; - size_t pack_size; - - if (info) - pack_size = 2 + 4 * 3 + info->dh.prime.size + - info->dh.generator.size + info->dh.public_key.size; - else - pack_size = 0; + void* size_pos; - packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof (uint32_t); + size_pos = ps->data + ps->length; - /* calculate the size and allocate the data. - */ - packed_session->data = - gnutls_malloc (packed_session->size + MAX_SEC_PARAMS + 2 + - session->security_parameters.extensions. - session_ticket_len); + BUFFER_APPEND_NUM(ps, 0); + cur_size = ps->length; - if (packed_session->data == NULL) + if (info) { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; + BUFFER_APPEND_NUM( ps, info->dh.secret_bits); + BUFFER_APPEND_PFX( ps, info->dh.prime.data, info->dh.prime.size); + BUFFER_APPEND_PFX( ps, info->dh.generator.data, info->dh.generator.size); + BUFFER_APPEND_PFX( ps, info->dh.public_key.data, info->dh.public_key.size); } - packed_session->data[0] = GNUTLS_CRD_ANON; - _gnutls_write_uint32 (pack_size, &packed_session->data[PACK_HEADER_SIZE]); - pos += 4 + PACK_HEADER_SIZE; - - if (pack_size > 0) - { - _gnutls_write_uint16 (info->dh.secret_bits, &packed_session->data[pos]); - pos += 2; - - _gnutls_write_datum32 (&packed_session->data[pos], info->dh.prime); - pos += 4 + info->dh.prime.size; - _gnutls_write_datum32 (&packed_session->data[pos], info->dh.generator); - pos += 4 + info->dh.generator.size; - _gnutls_write_datum32 (&packed_session->data[pos], info->dh.public_key); - pos += 4 + info->dh.public_key.size; - - } + /* write the real size */ + _gnutls_write_uint32(ps->length-cur_size, size_pos); return 0; } @@ -657,33 +537,18 @@ pack_anon_auth_info (gnutls_session_t session, static int unpack_anon_auth_info (gnutls_session_t session, - const gnutls_datum_t * packed_session) + gnutls_buffer_st * ps) { + int ret; size_t pack_size; - int pos = 0, size, ret; - anon_auth_info_t info; - - if (packed_session->data[0] != GNUTLS_CRD_ANON) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - pack_size = _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]); - pos += PACK_HEADER_SIZE + 4; + anon_auth_info_t info = NULL; + BUFFER_POP_NUM(ps, pack_size); if (pack_size == 0) - return 0; /* nothing to be done */ + return 0; /* nothing to be done */ - /* a simple check for integrity */ - if (pack_size + PACK_HEADER_SIZE + 4 > packed_session->size) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - /* client and serer have the same auth_info here + /* client and server have the same auth_info here */ ret = _gnutls_auth_info_set (session, GNUTLS_CRD_ANON, @@ -701,48 +566,22 @@ unpack_anon_auth_info (gnutls_session_t session, return GNUTLS_E_INTERNAL_ERROR; } - info->dh.secret_bits = _gnutls_read_uint16 (&packed_session->data[pos]); - pos += 2; + BUFFER_POP_NUM(ps, info->dh.secret_bits); - size = _gnutls_read_uint32 (&packed_session->data[pos]); - pos += 4; - ret = _gnutls_set_datum (&info->dh.prime, &packed_session->data[pos], size); - if (ret < 0) - { - gnutls_assert (); - goto error; - } - pos += size; + BUFFER_POP_DATUM(ps, &info->dh.prime); + BUFFER_POP_DATUM(ps, &info->dh.generator); + BUFFER_POP_DATUM(ps, &info->dh.public_key); - size = _gnutls_read_uint32 (&packed_session->data[pos]); - pos += 4; - ret = - _gnutls_set_datum (&info->dh.generator, &packed_session->data[pos], size); - if (ret < 0) - { - gnutls_assert (); - goto error; - } - pos += size; + return 0; - size = _gnutls_read_uint32 (&packed_session->data[pos]); - pos += 4; - ret = - _gnutls_set_datum (&info->dh.public_key, &packed_session->data[pos], - size); - if (ret < 0) +error: + if (info) { - gnutls_assert (); - goto error; + _gnutls_free_datum (&info->dh.prime); + _gnutls_free_datum (&info->dh.generator); + _gnutls_free_datum (&info->dh.public_key); } - pos += size; - - return 0; -error: - _gnutls_free_datum (&info->dh.prime); - _gnutls_free_datum (&info->dh.generator); - _gnutls_free_datum (&info->dh.public_key); return ret; } #endif /* ANON */ @@ -766,108 +605,53 @@ error: * x bytes the public key */ static int -pack_psk_auth_info (gnutls_session_t session, gnutls_datum_t * packed_session) +pack_psk_auth_info (gnutls_session_t session, gnutls_buffer_st * ps) { psk_auth_info_t info; - int pack_size, username_size = 0, hint_size = 0, pos; + int username_len; + int hint_len, ret; + void* size_pos; + size_t cur_size; info = _gnutls_get_auth_info (session); - if (info) - { - username_size = strlen (info->username) + 1; /* include the terminating null */ - hint_size = strlen (info->hint) + 1; /* include the terminating null */ - - pack_size = 1 + 4 + 4 + username_size + 4 + hint_size + - +2 + 4 + info->dh.prime.size + 4 + info->dh.generator.size + - 4 + info->dh.public_key.size; - } + if (info && info->username) + username_len = strlen (info->username) + 1; /* include the terminating null */ else - pack_size = 0; + username_len = 0; - packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof (uint32_t); - - /* calculate the size and allocate the data. - */ - packed_session->data = - gnutls_malloc (packed_session->size + MAX_SEC_PARAMS + 2 + - session->security_parameters.extensions. - session_ticket_len); - - if (packed_session->data == NULL) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - - pos = 0; - - packed_session->data[pos] = GNUTLS_CRD_PSK; - pos++; - - _gnutls_write_uint32 (pack_size, &packed_session->data[pos]); - pos += 4; - - if (pack_size > 0) - { - _gnutls_write_uint32 (username_size, &packed_session->data[pos]); - pos += 4; - - memcpy (&packed_session->data[pos], info->username, username_size); - pos += username_size; + if (info && info->hint) + hint_len = strlen (info->hint) + 1; /* include the terminating null */ + else + hint_len = 0; - _gnutls_write_uint32 (hint_size, &packed_session->data[pos]); - pos += 4; + size_pos = ps->data + ps->length; - memcpy (&packed_session->data[pos], info->hint, hint_size); - pos += hint_size; + BUFFER_APPEND_NUM(ps, 0); + cur_size = ps->length; - _gnutls_write_uint16 (info->dh.secret_bits, &packed_session->data[pos]); - pos += 2; + BUFFER_APPEND_PFX(ps, info->username, username_len); + BUFFER_APPEND_PFX(ps, info->hint, hint_len); - _gnutls_write_datum32 (&packed_session->data[pos], info->dh.prime); - pos += 4 + info->dh.prime.size; - _gnutls_write_datum32 (&packed_session->data[pos], info->dh.generator); - pos += 4 + info->dh.generator.size; - _gnutls_write_datum32 (&packed_session->data[pos], info->dh.public_key); - pos += 4 + info->dh.public_key.size; - } + BUFFER_APPEND_NUM( ps, info->dh.secret_bits); + BUFFER_APPEND_PFX( ps, info->dh.prime.data, info->dh.prime.size); + BUFFER_APPEND_PFX( ps, info->dh.generator.data, info->dh.generator.size); + BUFFER_APPEND_PFX( ps, info->dh.public_key.data, info->dh.public_key.size); + /* write the real size */ + _gnutls_write_uint32(ps->length-cur_size, size_pos); return 0; } static int unpack_psk_auth_info (gnutls_session_t session, - const gnutls_datum_t * packed_session) + gnutls_buffer_st * ps) { size_t username_size, hint_size; - size_t pack_size; - int pos = 0, size, ret; + int ret; psk_auth_info_t info; - if (packed_session->data[0] != GNUTLS_CRD_PSK) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - pack_size = _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]); - pos += PACK_HEADER_SIZE + 4; - - - if (pack_size == 0) - return 0; /* nothing to be done */ - - /* a simple check for integrity */ - if (pack_size + PACK_HEADER_SIZE + 4 > packed_session->size) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - /* client and serer have the same auth_info here - */ ret = _gnutls_auth_info_set (session, GNUTLS_CRD_PSK, sizeof (psk_auth_info_st), 1); @@ -884,60 +668,36 @@ unpack_psk_auth_info (gnutls_session_t session, return GNUTLS_E_INTERNAL_ERROR; } - username_size = _gnutls_read_uint32 (&packed_session->data[pos]); - pos += 4; - - memcpy (info->username, &packed_session->data[pos], username_size); - pos += username_size; - - hint_size = _gnutls_read_uint32 (&packed_session->data[pos]); - pos += 4; - - memcpy (info->hint, &packed_session->data[pos], hint_size); - pos += hint_size; - - info->dh.secret_bits = _gnutls_read_uint16 (&packed_session->data[pos]); - pos += 2; - - size = _gnutls_read_uint32 (&packed_session->data[pos]); - pos += 4; - ret = _gnutls_set_datum (&info->dh.prime, &packed_session->data[pos], size); - if (ret < 0) + BUFFER_POP_NUM(ps, username_size); + if (username_size > sizeof(info->username)) { - gnutls_assert (); - goto error; + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; } - pos += size; - size = _gnutls_read_uint32 (&packed_session->data[pos]); - pos += 4; - ret = - _gnutls_set_datum (&info->dh.generator, &packed_session->data[pos], size); - if (ret < 0) - { - gnutls_assert (); - goto error; - } - pos += size; + BUFFER_POP(ps, info->username, username_size); - size = _gnutls_read_uint32 (&packed_session->data[pos]); - pos += 4; - ret = - _gnutls_set_datum (&info->dh.public_key, &packed_session->data[pos], - size); - if (ret < 0) + BUFFER_POP_NUM(ps, hint_size); + if (hint_size > sizeof(info->hint)) { - gnutls_assert (); - goto error; + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; } - pos += size; + BUFFER_POP(ps, info->hint, hint_size); - return 0; + BUFFER_POP_NUM(ps, info->dh.secret_bits); + + BUFFER_POP_DATUM(ps, &info->dh.prime); + BUFFER_POP_DATUM(ps, &info->dh.generator); + BUFFER_POP_DATUM(ps, &info->dh.public_key); + ret = 0; + error: _gnutls_free_datum (&info->dh.prime); _gnutls_free_datum (&info->dh.generator); _gnutls_free_datum (&info->dh.public_key); + return ret; } #endif @@ -975,217 +735,97 @@ error: * ------------------- * MAX: 165 bytes * - * EXTENSIONS: - * 2 bytes the record send size - * 2 bytes the record recv size - * - * 1 byte the SRP username size - * x bytes the SRP username (MAX_SRP_USERNAME) - * - * 2 bytes the number of server name extensions (up to MAX_SERVER_NAME_EXTENSIONS) - * 1 byte the first name type - * 2 bytes the size of the first name - * x bytes the first name (MAX_SERVER_NAME_SIZE) - * and so on... - * 2 bytes the session ticket size - * x bytes the session ticket (MAX_SESSION_TICKET_SIZE) - * - * -------------------- - * MAX: 7+MAX_SRP_USERNAME+MAX_SERVER_NAME_EXTENSIONS*(3+MAX_SERVER_NAME_SIZE)+MAX_SESSION_TICKET_SIZE */ static int pack_security_parameters (gnutls_session_t session, - gnutls_datum_t * packed_session) + gnutls_buffer_st * ps) { - int pos = 0; - size_t len, init, i; + + int ret; + void* size_pos; + size_t cur_size; /* move after the auth info stuff. */ - init = - _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]) + 4 + - PACK_HEADER_SIZE; - - pos = init + 4; /* make some space to write later the size */ - - packed_session->data[pos++] = session->security_parameters.entity; - packed_session->data[pos++] = session->security_parameters.kx_algorithm; - packed_session->data[pos++] = - session->security_parameters.read_bulk_cipher_algorithm; - packed_session->data[pos++] = - session->security_parameters.read_mac_algorithm; - packed_session->data[pos++] = - session->security_parameters.read_compression_algorithm; - packed_session->data[pos++] = - session->security_parameters.write_bulk_cipher_algorithm; - packed_session->data[pos++] = - session->security_parameters.write_mac_algorithm; - packed_session->data[pos++] = - session->security_parameters.write_compression_algorithm; - packed_session->data[pos++] = - session->security_parameters.current_cipher_suite.suite[0]; - packed_session->data[pos++] = - session->security_parameters.current_cipher_suite.suite[1]; - - packed_session->data[pos++] = session->security_parameters.cert_type; - packed_session->data[pos++] = session->security_parameters.version; - - memcpy (&packed_session->data[pos], - session->security_parameters.master_secret, GNUTLS_MASTER_SIZE); - pos += GNUTLS_MASTER_SIZE; - - memcpy (&packed_session->data[pos], - session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); - pos += GNUTLS_RANDOM_SIZE; - memcpy (&packed_session->data[pos], - session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); - pos += GNUTLS_RANDOM_SIZE; - - packed_session->data[pos++] = session->security_parameters.session_id_size; - memcpy (&packed_session->data[pos], session->security_parameters.session_id, - session->security_parameters.session_id_size); - pos += session->security_parameters.session_id_size; - - _gnutls_write_uint32 (session->security_parameters.timestamp, - &packed_session->data[pos]); - pos += 4; - - /* Extensions */ - _gnutls_write_uint16 (session->security_parameters.max_record_send_size, - &packed_session->data[pos]); - pos += 2; - - _gnutls_write_uint16 (session->security_parameters.max_record_recv_size, - &packed_session->data[pos]); - pos += 2; - - /* SRP */ - len = - strlen ((char *) session->security_parameters.extensions.srp_username); - packed_session->data[pos++] = len; - memcpy (&packed_session->data[pos], - session->security_parameters.extensions.srp_username, len); - pos += len; - - _gnutls_write_uint16 (session->security_parameters. - extensions.server_names_size, - &packed_session->data[pos]); - pos += 2; - - for (i = 0; i < session->security_parameters.extensions.server_names_size; - i++) - { - packed_session->data[pos++] = - session->security_parameters.extensions.server_names[i].type; - _gnutls_write_uint16 (session->security_parameters. - extensions.server_names[i].name_length, - &packed_session->data[pos]); - pos += 2; - - memcpy (&packed_session->data[pos], - session->security_parameters.extensions.server_names[i].name, - session->security_parameters.extensions. - server_names[i].name_length); - pos += - session->security_parameters.extensions.server_names[i].name_length; - } + size_pos = ps->data + ps->length; + + BUFFER_APPEND_NUM(ps, 0); + cur_size = ps->length; + - _gnutls_write_uint16 (session->security_parameters. - extensions.session_ticket_len, - &packed_session->data[pos]); - pos += 2; - memcpy (&packed_session->data[pos], - session->security_parameters.extensions.session_ticket, - session->security_parameters.extensions.session_ticket_len); - pos += session->security_parameters.extensions.session_ticket_len; + BUFFER_APPEND(ps, &session->security_parameters.entity, 1); + BUFFER_APPEND(ps, &session->security_parameters.kx_algorithm, 1); + BUFFER_APPEND(ps, &session->security_parameters.read_bulk_cipher_algorithm, 1); + BUFFER_APPEND(ps, &session->security_parameters.read_mac_algorithm, 1); + BUFFER_APPEND(ps, &session->security_parameters.read_compression_algorithm, 1); + BUFFER_APPEND(ps, &session->security_parameters.write_bulk_cipher_algorithm, 1); + BUFFER_APPEND(ps, &session->security_parameters.write_mac_algorithm, 1); + BUFFER_APPEND(ps, &session->security_parameters.write_compression_algorithm, 1); + BUFFER_APPEND(ps, &session->security_parameters.current_cipher_suite.suite[0], 1); + BUFFER_APPEND(ps, &session->security_parameters.current_cipher_suite.suite[1], 1); + BUFFER_APPEND(ps, &session->security_parameters.cert_type, 1); + BUFFER_APPEND(ps, &session->security_parameters.version, 1); - /* write the total size */ - _gnutls_write_uint32 (pos - init - 4, &packed_session->data[init]); - packed_session->size += pos - init; + BUFFER_APPEND(ps, session->security_parameters.master_secret, GNUTLS_MASTER_SIZE); + BUFFER_APPEND(ps, session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); + BUFFER_APPEND(ps, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); + BUFFER_APPEND_NUM(ps, session->security_parameters.session_id_size); + BUFFER_APPEND_NUM(ps, session->security_parameters.max_record_send_size); + BUFFER_APPEND_NUM(ps, session->security_parameters.max_record_recv_size); + BUFFER_APPEND(ps, session->security_parameters.session_id, session->security_parameters.session_id_size); + + BUFFER_APPEND_NUM(ps, session->security_parameters.timestamp); + + _gnutls_write_uint32(ps->length-cur_size, size_pos); return 0; } - static int unpack_security_parameters (gnutls_session_t session, - const gnutls_datum_t * packed_session) + gnutls_buffer_st * ps) { - size_t pack_size, init, i; - int pos = 0, len; + size_t pack_size; + int ret; time_t timestamp = time (0); - - /* skip the auth info stuff */ - init = - _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]) + 4 + - PACK_HEADER_SIZE; - - pos = init; - - pack_size = _gnutls_read_uint32 (&packed_session->data[pos]); - pos += 4; - + BUFFER_POP_NUM(ps, pack_size); if (pack_size == 0) return GNUTLS_E_INVALID_REQUEST; - /* a simple check for integrity */ - if (pack_size > MAX_SEC_PARAMS + 2 + MAX_SESSION_TICKET_SIZE) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - memset (&session->internals.resumed_security_parameters, 0, sizeof (session->internals.resumed_security_parameters)); - session->internals.resumed_security_parameters.entity = - packed_session->data[pos++]; - session->internals.resumed_security_parameters.kx_algorithm = - packed_session->data[pos++]; - session->internals.resumed_security_parameters.read_bulk_cipher_algorithm = - packed_session->data[pos++]; - session->internals.resumed_security_parameters.read_mac_algorithm = - packed_session->data[pos++]; - session->internals.resumed_security_parameters.read_compression_algorithm = - packed_session->data[pos++]; - session->internals.resumed_security_parameters.write_bulk_cipher_algorithm = - packed_session->data[pos++]; - session->internals.resumed_security_parameters.write_mac_algorithm = - packed_session->data[pos++]; - session->internals.resumed_security_parameters.write_compression_algorithm = - packed_session->data[pos++]; - session->internals.resumed_security_parameters. - current_cipher_suite.suite[0] = packed_session->data[pos++]; - session->internals.resumed_security_parameters. - current_cipher_suite.suite[1] = packed_session->data[pos++]; - - session->internals.resumed_security_parameters.cert_type = - packed_session->data[pos++]; - session->internals.resumed_security_parameters.version = - packed_session->data[pos++]; - - memcpy (session->internals.resumed_security_parameters.master_secret, - &packed_session->data[pos], GNUTLS_MASTER_SIZE); - pos += GNUTLS_MASTER_SIZE; - - memcpy (session->internals.resumed_security_parameters.client_random, - &packed_session->data[pos], GNUTLS_RANDOM_SIZE); - pos += GNUTLS_RANDOM_SIZE; - memcpy (session->internals.resumed_security_parameters.server_random, - &packed_session->data[pos], GNUTLS_RANDOM_SIZE); - pos += GNUTLS_RANDOM_SIZE; - - session->internals.resumed_security_parameters.session_id_size = - packed_session->data[pos++]; - memcpy (session->internals.resumed_security_parameters.session_id, - &packed_session->data[pos], + + BUFFER_POP(ps, &session->internals.resumed_security_parameters.entity, 1); + BUFFER_POP(ps, &session->internals.resumed_security_parameters.kx_algorithm, 1); + BUFFER_POP(ps, &session->internals.resumed_security_parameters.read_bulk_cipher_algorithm, 1); + BUFFER_POP(ps, &session->internals.resumed_security_parameters.read_mac_algorithm, 1); + BUFFER_POP(ps, &session->internals.resumed_security_parameters.read_compression_algorithm, 1); + BUFFER_POP(ps, &session->internals.resumed_security_parameters.write_bulk_cipher_algorithm, 1); + BUFFER_POP(ps, &session->internals.resumed_security_parameters.write_mac_algorithm, 1); + BUFFER_POP(ps, &session->internals.resumed_security_parameters.write_compression_algorithm, 1); + BUFFER_POP(ps, &session->internals.resumed_security_parameters.current_cipher_suite.suite[0], 1); + BUFFER_POP(ps, &session->internals.resumed_security_parameters. + current_cipher_suite.suite[1], 1); + BUFFER_POP(ps, &session->internals.resumed_security_parameters.cert_type, 1); + BUFFER_POP(ps, &session->internals.resumed_security_parameters.version, 1); + + BUFFER_POP(ps, &session->internals.resumed_security_parameters.master_secret, + GNUTLS_MASTER_SIZE); + + BUFFER_POP(ps, &session->internals.resumed_security_parameters.client_random, + GNUTLS_RANDOM_SIZE); + BUFFER_POP(ps, &session->internals.resumed_security_parameters.server_random, + GNUTLS_RANDOM_SIZE); + BUFFER_POP_NUM(ps, session->internals.resumed_security_parameters.session_id_size); + + BUFFER_POP(ps, &session->internals.resumed_security_parameters.session_id, session->internals.resumed_security_parameters.session_id_size); - pos += session->internals.resumed_security_parameters.session_id_size; - session->internals.resumed_security_parameters.timestamp = - _gnutls_read_uint32 (&packed_session->data[pos]); - pos += 4; + BUFFER_POP_NUM(ps, session->internals.resumed_security_parameters.timestamp); + BUFFER_POP_NUM(ps, session->internals.resumed_security_parameters.max_record_send_size); + BUFFER_POP_NUM(ps, session->internals.resumed_security_parameters.max_record_recv_size); if (timestamp - session->internals.resumed_security_parameters.timestamp > session->internals.expire_time @@ -1195,60 +835,8 @@ unpack_security_parameters (gnutls_session_t session, return GNUTLS_E_EXPIRED; } - /* Extensions */ - session->internals.resumed_security_parameters.max_record_send_size = - _gnutls_read_uint16 (&packed_session->data[pos]); - pos += 2; - - session->internals.resumed_security_parameters.max_record_recv_size = - _gnutls_read_uint16 (&packed_session->data[pos]); - pos += 2; - - - /* SRP */ - len = packed_session->data[pos++]; /* srp username length */ - memcpy (session->internals.resumed_security_parameters. - extensions.srp_username, &packed_session->data[pos], len); - session->internals.resumed_security_parameters. - extensions.srp_username[len] = 0; - pos += len; - - session->internals.resumed_security_parameters. - extensions.server_names_size = - _gnutls_read_uint16 (&packed_session->data[pos]); - pos += 2; - for (i = 0; - i < - session->internals.resumed_security_parameters. - extensions.server_names_size; i++) - { - session->internals.resumed_security_parameters. - extensions.server_names[i].type = packed_session->data[pos++]; - session->internals.resumed_security_parameters. - extensions.server_names[i].name_length = - _gnutls_read_uint16 (&packed_session->data[pos]); - pos += 2; - - memcpy (session->internals.resumed_security_parameters. - extensions.server_names[i].name, &packed_session->data[pos], - session->internals.resumed_security_parameters. - extensions.server_names[i].name_length); - pos += - session->internals.resumed_security_parameters. - extensions.server_names[i].name_length; - } - - session->internals.resumed_security_parameters. - extensions.session_ticket_len = - _gnutls_read_uint16 (&packed_session->data[pos]); - pos += 2; - session->internals.resumed_security_parameters.extensions.session_ticket = - gnutls_malloc (session->internals.resumed_security_parameters. - extensions.session_ticket_len); - memcpy (session->internals.resumed_security_parameters. - extensions.session_ticket, &packed_session->data[pos], - session->internals.resumed_security_parameters. - extensions.session_ticket_len); + ret = 0; - return 0; +error: + return ret; } diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c index eca8a644a4..b5769de176 100644 --- a/lib/gnutls_state.c +++ b/lib/gnutls_state.c @@ -45,6 +45,7 @@ #include #include #include +#include /* These should really be static, but src/tests.c calls them. Make them public functions? */ @@ -216,7 +217,6 @@ _gnutls_handshake_internal_state_init (gnutls_session_t session) session->internals.extensions_sent_size = 0; /* by default no selected certificate */ - session->internals.proposed_record_size = DEFAULT_MAX_RECORD_SIZE; session->internals.adv_version_major = 0; session->internals.adv_version_minor = 0; session->internals.v2_hello = 0; @@ -225,7 +225,6 @@ _gnutls_handshake_internal_state_init (gnutls_session_t session) session->internals.adv_version_minor = 0; session->internals.adv_version_minor = 0; session->internals.direction = 0; - session->internals.safe_renegotiation_received = 0; /* use out of band data for the last * handshake messages received. @@ -385,6 +384,7 @@ gnutls_deinit (gnutls_session_t session) _gnutls_handshake_internal_state_clear (session); _gnutls_handshake_io_buffer_clear (session); + _gnutls_ext_free_session_data (session); _gnutls_free_datum (&session->connection_state.read_mac_secret); _gnutls_free_datum (&session->connection_state.write_mac_secret); @@ -439,19 +439,6 @@ gnutls_deinit (gnutls_session_t session) session->key = NULL; } - gnutls_free (session->internals.srp_username); - - if (session->internals.srp_password) - { - memset (session->internals.srp_password, 0, - strlen (session->internals.srp_password)); - gnutls_free (session->internals.srp_password); - } - - gnutls_free (session->security_parameters.extensions.session_ticket); - gnutls_free (session->internals.resumed_security_parameters. - extensions.session_ticket); - memset (session, 0, sizeof (struct gnutls_session_int)); gnutls_free (session); } diff --git a/lib/gnutls_str.c b/lib/gnutls_str.c index 0667886449..4975ddee03 100644 --- a/lib/gnutls_str.c +++ b/lib/gnutls_str.c @@ -112,7 +112,7 @@ _gnutls_buffer_clear (gnutls_buffer_st * str) str->length = 0; } -#define MIN_CHUNK 256 +#define MIN_CHUNK 1024 int _gnutls_buffer_append_data (gnutls_buffer_st * dest, const void *data, @@ -211,7 +211,7 @@ _gnutls_buffer_append_str (gnutls_buffer_st * dest, const char *src) * data are appended in the buffer. */ void -_gnutls_buffer_get_datum (gnutls_buffer_st * str, gnutls_datum_t * data, +_gnutls_buffer_pop_datum (gnutls_buffer_st * str, gnutls_datum_t * data, size_t req_size) { @@ -240,14 +240,48 @@ _gnutls_buffer_get_datum (gnutls_buffer_st * str, gnutls_datum_t * data, return; } +/* converts the buffer to a datum if possible. After this call the buffer + * is at an usable state and might not be used or deinitialized */ +int +_gnutls_buffer_to_datum (gnutls_buffer_st * str, gnutls_datum_t * data) +{ + + if (str->length == 0) + { + data->data = NULL; + data->size = 0; + return 0; + } + + if (str->allocd != str->data) + { + data->data = gnutls_malloc(str->length); + if (data->data == NULL) + { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + memcpy(data->data, str->data, str->length); + data->size = str->length; + _gnutls_buffer_clear(str); + } + else + { + data->data = str->data; + data->size = str->length; + } + + return 0; +} + /* returns data from a string in a constant buffer. */ void -_gnutls_buffer_get_data (gnutls_buffer_st * str, void *data, size_t * req_size) +_gnutls_buffer_pop_data (gnutls_buffer_st * str, void *data, size_t * req_size) { gnutls_datum_t tdata; - _gnutls_buffer_get_datum (str, &tdata, *req_size); + _gnutls_buffer_pop_datum (str, &tdata, *req_size); *req_size = tdata.size; memcpy (data, tdata.data, tdata.size); @@ -509,3 +543,90 @@ _gnutls_hostname_compare (const char *certname, return 0; } + +int _gnutls_buffer_append_prefix (gnutls_buffer_st * buf, size_t data_size) +{ + opaque ss[4]; + _gnutls_write_uint32(data_size, ss); + return _gnutls_buffer_append_data(buf, ss, 4); +} + +/* Reads an uint32 number from the buffer. If check is non zero it will also check whether + * the number read, is less than the data in the buffer + */ +int _gnutls_buffer_pop_prefix (gnutls_buffer_st * buf, size_t *data_size, int check) +{ + size_t size; + + if (buf->length < 4) { + gnutls_assert(); + return GNUTLS_E_PARSING_ERROR; + } + + size = _gnutls_read_uint32(buf->data); + if (check && size > buf->length-4) { + gnutls_assert(); + return GNUTLS_E_PARSING_ERROR; + } + + buf->data+=4; + buf->length-=4; + + *data_size = size; + + return 0; +} + +int _gnutls_buffer_pop_datum_prefix (gnutls_buffer_st * buf, gnutls_datum_t* data) +{ + size_t size; + int ret; + + ret = _gnutls_buffer_pop_prefix(buf, &size, 1); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + if (size > 0) { + size_t osize = size; + _gnutls_buffer_pop_datum(buf, data, size); + if (osize != data->size) { + gnutls_assert(); + return GNUTLS_E_PARSING_ERROR; + } + } else { + data->size = 0; + data->data = NULL; + } + + return 0; +} + +int _gnutls_buffer_append_data_prefix (gnutls_buffer_st * buf, const void *data, + size_t data_size) +{ + _gnutls_buffer_append_prefix(buf, data_size); + if (data_size > 0) + return _gnutls_buffer_append_data(buf, data, data_size); + + return 0; +} + +int _gnutls_buffer_pop_data_prefix (gnutls_buffer_st * buf, void * data, size_t * data_size) +{ + size_t size; + int ret; + + ret = _gnutls_buffer_pop_prefix(buf, &size, 1); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + if (size > 0) + _gnutls_buffer_pop_data(buf, data, data_size); + + return 0; +} + diff --git a/lib/gnutls_str.h b/lib/gnutls_str.h index 63b8761a87..7d7df473ba 100644 --- a/lib/gnutls_str.h +++ b/lib/gnutls_str.h @@ -27,6 +27,7 @@ # define GNUTLS_STR_H #include +#include void _gnutls_str_cpy (char *dest, size_t dest_tot_size, const char *src); void _gnutls_mem_cpy (char *dest, size_t dest_tot_size, const char *src, @@ -49,10 +50,23 @@ int _gnutls_buffer_append_str (gnutls_buffer_st *, const char *str); int _gnutls_buffer_append_data (gnutls_buffer_st *, const void *data, size_t data_size); -void _gnutls_buffer_get_data (gnutls_buffer_st *, void *, size_t * size); -void _gnutls_buffer_get_datum (gnutls_buffer_st *, gnutls_datum_t *, +#include + +int _gnutls_buffer_append_prefix (gnutls_buffer_st * buf, size_t data_size); + +int _gnutls_buffer_append_data_prefix (gnutls_buffer_st * buf, + const void *data, size_t data_size); +void _gnutls_buffer_pop_data (gnutls_buffer_st *, void *, size_t * size); +void _gnutls_buffer_pop_datum (gnutls_buffer_st *, gnutls_datum_t *, size_t max_size); +int _gnutls_buffer_pop_prefix (gnutls_buffer_st * buf, size_t *data_size, int check); + +int _gnutls_buffer_pop_data_prefix (gnutls_buffer_st * buf, void * data, size_t * data_size); + +int _gnutls_buffer_pop_datum_prefix (gnutls_buffer_st * buf, gnutls_datum_t* data); +int _gnutls_buffer_to_datum (gnutls_buffer_st * str, gnutls_datum_t * data); + int _gnutls_buffer_escape(gnutls_buffer_st * dest, const char *const invalid_chars); int _gnutls_buffer_unescape(gnutls_buffer_st * dest); @@ -75,4 +89,60 @@ int _gnutls_hostname_compare (const char *certname, size_t certnamesize, const char *hostname); #define MAX_CN 256 +#define BUFFER_APPEND(b, x, s) { \ + ret = _gnutls_buffer_append_data(b, x, s); \ + if (ret < 0) { \ + gnutls_assert(); \ + return ret; \ + } \ + } + +#define BUFFER_APPEND_PFX(b, x, s) { \ + ret = _gnutls_buffer_append_data_prefix(b, x, s); \ + if (ret < 0) { \ + gnutls_assert(); \ + return ret; \ + } \ + } + +#define BUFFER_APPEND_NUM(b, s) { \ + ret = _gnutls_buffer_append_prefix(b, s); \ + if (ret < 0) { \ + gnutls_assert(); \ + return ret; \ + } \ + } + + +#define BUFFER_POP(b, x, s) { \ + size_t is = s; \ + _gnutls_buffer_pop_data(b, x, &is); \ + if (is != s) { \ + ret = GNUTLS_E_PARSING_ERROR; \ + gnutls_assert(); \ + goto error; \ + } \ + } + +#define BUFFER_POP_DATUM(b, o) { \ + gnutls_datum_t d; \ + ret = _gnutls_buffer_pop_datum_prefix(b, &d); \ + if (ret >= 0) \ + ret = _gnutls_set_datum (o, d.data, d.size); \ + if (ret < 0) { \ + gnutls_assert(); \ + goto error; \ + } \ + } + +#define BUFFER_POP_NUM(b, o) { \ + size_t s; \ + ret = _gnutls_buffer_pop_prefix(b, &s, 0); \ + if (ret < 0) { \ + gnutls_assert(); \ + goto error; \ + } \ + o = s; \ + } + #endif diff --git a/lib/includes/gnutls/compat.h b/lib/includes/gnutls/compat.h index 5cae317ee8..566f8c599f 100644 --- a/lib/includes/gnutls/compat.h +++ b/lib/includes/gnutls/compat.h @@ -165,4 +165,10 @@ void gnutls_certificate_server_set_retrieve_function gnutls_sign_func gnutls_sign_callback_get (gnutls_session_t session, void **userdata); + int gnutls_ext_register (int type, + const char *name, + gnutls_ext_parse_type_t parse_type, + gnutls_ext_recv_func recv_func, + gnutls_ext_send_func send_func) _GNUTLS_GCC_ATTR_DEPRECATED; + #endif /* _GNUTLS_COMPAT_H */ diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index 441b42850c..7ea6ea3616 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -817,11 +817,6 @@ extern "C" GNUTLS_EXT_NONE = 4, } gnutls_ext_parse_type_t; - int gnutls_ext_register (int type, - const char *name, - gnutls_ext_parse_type_t parse_type, - gnutls_ext_recv_func recv_func, - gnutls_ext_send_func send_func); /** * gnutls_server_name_type_t: diff --git a/lib/libgnutls.map b/lib/libgnutls.map index 527c618912..cc93d6cd1f 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -706,6 +706,13 @@ GNUTLS_PRIVATE { _gnutls_hash_init; _gnutls_hash_deinit; _gnutls_hash; + _gnutls_ext_get_session_data; + _gnutls_ext_set_session_data; + _gnutls_ext_register; + _gnutls_buffer_append_prefix; + _gnutls_buffer_append_data_prefix; + _gnutls_buffer_pop_data; + _gnutls_buffer_pop_prefix; # Internal symbols needed by psktool: diff --git a/lib/pkcs11.c b/lib/pkcs11.c index ecd2033081..f2b3708d3a 100644 --- a/lib/pkcs11.c +++ b/lib/pkcs11.c @@ -375,7 +375,7 @@ static int unescape_string (char* output, const char* input, size_t* size, char return ret; } - _gnutls_buffer_get_data(&str, output, size); + _gnutls_buffer_pop_data(&str, output, size); _gnutls_buffer_clear(&str); diff --git a/lib/x509/dn.c b/lib/x509/dn.c index d8f2791d3d..4288470081 100644 --- a/lib/x509/dn.c +++ b/lib/x509/dn.c @@ -309,7 +309,7 @@ _gnutls_x509_parse_dn (ASN1_TYPE asn1_struct, if (buf) { - _gnutls_buffer_get_data (&out_str, buf, sizeof_buf); + _gnutls_buffer_pop_data (&out_str, buf, sizeof_buf); buf[*sizeof_buf] = 0; } else diff --git a/libextra/ext_inner_application.c b/libextra/ext_inner_application.c index 0dcc9aca9e..bad812e4a9 100644 --- a/libextra/ext_inner_application.c +++ b/libextra/ext_inner_application.c @@ -31,11 +31,34 @@ #define NO 0 #define YES 1 -int +static int _gnutls_inner_application_recv_params (gnutls_session_t session, + const opaque * data, + size_t data_size); +static int _gnutls_inner_application_send_params (gnutls_session_t session, + opaque * data, size_t); +static int ia_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv); +static int ia_pack(extension_priv_data_t _priv, gnutls_buffer_st* ps); +static void ia_deinit_data(extension_priv_data_t priv); + +extension_entry_st ext_mod_ia = { + .name = "INNER APPLICATION", + .type = GNUTLS_EXTENSION_INNER_APPLICATION, + .parse_type = GNUTLS_EXT_TLS, + + .recv_func = _gnutls_inner_application_recv_params, + .send_func = _gnutls_inner_application_send_params, + .pack_func = ia_pack, + .unpack_func = ia_unpack, + .deinit_func = ia_deinit_data, +}; + +static int _gnutls_inner_application_recv_params (gnutls_session_t session, const opaque * data, size_t data_size) { - tls_ext_st *ext = &session->security_parameters.extensions; + extension_priv_data_t epriv; + ia_ext_st *priv; + int ret; if (data_size != 1) { @@ -43,13 +66,29 @@ _gnutls_inner_application_recv_params (gnutls_session_t session, return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } - ext->gnutls_ia_peer_enable = 1; - ext->gnutls_ia_peer_allowskip = 0; + ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_INNER_APPLICATION, &epriv); + if (ret < 0) + { + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) + { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + epriv.ptr = priv; + _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_INNER_APPLICATION, epriv); + } + else + priv = epriv.ptr; + + priv->flags |= IA_PEER_ENABLE; + priv->flags &= ~IA_PEER_ALLOW_SKIP; switch ((unsigned char) *data) { - case NO: /* Peer's ia_on_resume == no */ - ext->gnutls_ia_peer_allowskip = 1; + case NO: /* Peer's ia_on_resume == no */ + priv->flags |= IA_PEER_ALLOW_SKIP; break; case YES: @@ -59,17 +98,36 @@ _gnutls_inner_application_recv_params (gnutls_session_t session, gnutls_assert (); } + return 0; } /* returns data_size or a negative number on failure */ -int +static int _gnutls_inner_application_send_params (gnutls_session_t session, opaque * data, size_t data_size) { - tls_ext_st *ext = &session->security_parameters.extensions; + extension_priv_data_t epriv; + ia_ext_st * priv = NULL; + int ret; + + ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_INNER_APPLICATION, &epriv); + if (ret < 0) + { + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) + { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + epriv.ptr = priv; + _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_INNER_APPLICATION, epriv); + } + else + priv = epriv.ptr; /* Set ext->gnutls_ia_enable depending on whether we have a TLS/IA credential in the session. */ @@ -77,29 +135,31 @@ _gnutls_inner_application_send_params (gnutls_session_t session, if (session->security_parameters.entity == GNUTLS_CLIENT) { gnutls_ia_client_credentials_t cred = (gnutls_ia_client_credentials_t) - _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL); + _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL); if (cred) - ext->gnutls_ia_enable = 1; + priv->flags |= IA_ENABLE; } - else + else /* SERVER */ { - gnutls_ia_server_credentials_t cred = (gnutls_ia_server_credentials_t) - _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL); + gnutls_ia_server_credentials_t cred; + + cred = (gnutls_ia_server_credentials_t) + _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL); if (cred) - ext->gnutls_ia_enable = 1; + priv->flags |= IA_PEER_ENABLE; } /* If we don't want gnutls_ia locally, or we are a server and the * client doesn't want it, don't advertise TLS/IA support at all, as * required. */ - if (!ext->gnutls_ia_enable) + if (!(priv->flags & IA_ENABLE)) return 0; if (session->security_parameters.entity == GNUTLS_SERVER && - !ext->gnutls_ia_peer_enable) + !(priv->flags & IA_PEER_ENABLE)) return 0; /* We'll advertise. Check if there's room in the hello buffer. */ @@ -119,8 +179,8 @@ _gnutls_inner_application_send_params (gnutls_session_t session, /* Client: value follows local setting */ - if (ext->gnutls_ia_allowskip) - *data = NO; + if (priv->flags & IA_ALLOW_SKIP) + *data = NO; } else { @@ -137,11 +197,60 @@ _gnutls_inner_application_send_params (gnutls_session_t session, * always skip IA on resumption, because recv_ext isn't even called * to record the peer's support for IA at all. Simon? */ - if (ext->gnutls_ia_allowskip && - ext->gnutls_ia_peer_allowskip && - session->internals.resumed == RESUME_TRUE) - *data = NO; + if ((priv->flags & IA_ALLOW_SKIP) && + (priv->flags & IA_PEER_ALLOW_SKIP) && + session->internals.resumed == RESUME_TRUE) + *data = NO; } return 1; } + +static void ia_deinit_data(extension_priv_data_t priv) +{ + gnutls_free(priv.ptr); +} + +static int ia_pack(extension_priv_data_t epriv, gnutls_buffer_st* ps) +{ +ia_ext_st* priv = epriv.ptr; +int ret; + + BUFFER_APPEND_NUM(ps, priv->flags); + BUFFER_APPEND_PFX(ps, priv->inner_secret, GNUTLS_MASTER_SIZE); + + return 0; +} + +static int ia_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv) +{ +ia_ext_st* priv; +int size, ret; +extension_priv_data_t epriv; + + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) + { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + BUFFER_POP_NUM(ps, priv->flags); + BUFFER_POP_NUM(ps, size); + if (size != GNUTLS_MASTER_SIZE) + { + gnutls_assert(); + return GNUTLS_E_PARSING_ERROR; + } + BUFFER_POP(ps, priv->inner_secret, GNUTLS_MASTER_SIZE); + + epriv.ptr = priv; + *_priv = epriv; + + return 0; + +error: + gnutls_free(priv); + return ret; +} + diff --git a/libextra/ext_inner_application.h b/libextra/ext_inner_application.h index a75ee604f9..3a037cde46 100644 --- a/libextra/ext_inner_application.h +++ b/libextra/ext_inner_application.h @@ -21,8 +21,40 @@ * */ -int _gnutls_inner_application_recv_params (gnutls_session_t session, - const opaque * data, - size_t data_size); -int _gnutls_inner_application_send_params (gnutls_session_t session, - opaque * data, size_t); +#ifndef EXT_IA_H +#define EXT_IA_H + +#include + +#define IA_PEER_ENABLE (1 << 1) +#define IA_PEER_ALLOW_SKIP (1 << 2) +#define IA_ENABLE (1 << 3) +#define IA_ALLOW_SKIP (1 << 4) + +extension_entry_st ext_mod_ia; + +typedef struct { + unsigned int flags; + /* For TLS/IA. XXX: Move to IA credential? */ + opaque inner_secret[GNUTLS_MASTER_SIZE]; +} ia_ext_st; + +inline static void _gnutls_ia_derive_inner_secret(gnutls_session_t session) +{ +extension_priv_data_t epriv; +ia_ext_st *priv; +int ret; + + ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_INNER_APPLICATION, &epriv); + if (ret < 0) + { + return ; + } + priv = epriv.ptr; + + memcpy (priv->inner_secret, + session->security_parameters.master_secret, GNUTLS_MASTER_SIZE); + +} + +#endif diff --git a/libextra/gnutls_extra.c b/libextra/gnutls_extra.c index f8866cfc07..490f0c5ab7 100644 --- a/libextra/gnutls_extra.c +++ b/libextra/gnutls_extra.c @@ -126,11 +126,7 @@ gnutls_global_init_extra (void) if (_gnutls_init_extra != 1) return 0; - ret = gnutls_ext_register (GNUTLS_EXTENSION_INNER_APPLICATION, - "INNER_APPLICATION", - GNUTLS_EXT_TLS, - _gnutls_inner_application_recv_params, - _gnutls_inner_application_send_params); + ret = _gnutls_ext_register (&ext_mod_ia); if (ret != GNUTLS_E_SUCCESS) return ret; diff --git a/libextra/gnutls_ia.c b/libextra/gnutls_ia.c index 804ed3f4f1..f3f1e4a9a7 100644 --- a/libextra/gnutls_ia.c +++ b/libextra/gnutls_ia.c @@ -26,6 +26,7 @@ #include "gnutls_num.h" #include "gnutls_state.h" #include +#include #define CHECKSUM_SIZE 12 @@ -171,6 +172,16 @@ _gnutls_ia_prf (gnutls_session_t session, int ret; opaque *seed; size_t seedsize = 2 * GNUTLS_RANDOM_SIZE + extra_size; + extension_priv_data_t epriv; + ia_ext_st *priv; + + ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_INNER_APPLICATION, &epriv); + if (ret < 0) + { + gnutls_assert(); + return ret; + } + priv = epriv.ptr; seed = gnutls_malloc (seedsize); if (!seed) @@ -185,7 +196,7 @@ _gnutls_ia_prf (gnutls_session_t session, session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); memcpy (seed + 2 * GNUTLS_RANDOM_SIZE, extra, extra_size); - ret = _gnutls_PRF (session, session->security_parameters.inner_secret, + ret = _gnutls_PRF (session, priv->inner_secret, GNUTLS_MASTER_SIZE, label, label_size, seed, seedsize, outsize, out); @@ -213,13 +224,25 @@ gnutls_ia_permute_inner_secret (gnutls_session_t session, size_t session_keys_size, const char *session_keys) { + extension_priv_data_t epriv; + ia_ext_st *priv; + int ret; + + ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_INNER_APPLICATION, &epriv); + if (ret < 0) + { + gnutls_assert(); + return ret; + } + priv = epriv.ptr; + return _gnutls_ia_prf (session, sizeof (inner_permutation_label) - 1, inner_permutation_label, session_keys_size, session_keys, GNUTLS_RANDOM_SIZE, - session->security_parameters.inner_secret); + priv->inner_secret); } /** @@ -261,8 +284,19 @@ gnutls_ia_generate_challenge (gnutls_session_t session, void gnutls_ia_extract_inner_secret (gnutls_session_t session, char *buffer) { - memcpy (buffer, session->security_parameters.inner_secret, - GNUTLS_MASTER_SIZE); + extension_priv_data_t epriv; + ia_ext_st *priv; + int ret; + + ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_INNER_APPLICATION, &epriv); + if (ret < 0) + { + gnutls_assert(); + return; + } + priv = epriv.ptr; + + memcpy (buffer, priv->inner_secret, GNUTLS_MASTER_SIZE); } /** @@ -290,8 +324,18 @@ gnutls_ia_endphase_send (gnutls_session_t session, int final_p) sizeof (server_finished_label); ssize_t len; int ret; + extension_priv_data_t epriv; + ia_ext_st *priv; + + ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_INNER_APPLICATION, &epriv); + if (ret < 0) + { + gnutls_assert(); + return ret; + } + priv = epriv.ptr; - ret = _gnutls_PRF (session, session->security_parameters.inner_secret, + ret = _gnutls_PRF (session, priv->inner_secret, GNUTLS_MASTER_SIZE, label, size_of_label - 1, /* XXX specification unclear on seed. */ "", 0, CHECKSUM_SIZE, local_checksum); @@ -343,8 +387,18 @@ gnutls_ia_verify_endphase (gnutls_session_t session, const char *checksum) int size_of_label = client ? sizeof (server_finished_label) : sizeof (client_finished_label); int ret; + extension_priv_data_t epriv; + ia_ext_st *priv; - ret = _gnutls_PRF (session, session->security_parameters.inner_secret, + ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_INNER_APPLICATION, &epriv); + if (ret < 0) + { + gnutls_assert(); + return ret; + } + priv = epriv.ptr; + + ret = _gnutls_PRF (session, priv->inner_secret, GNUTLS_MASTER_SIZE, label, size_of_label - 1, "", 0, CHECKSUM_SIZE, local_checksum); @@ -610,22 +664,32 @@ _gnutls_ia_server_handshake (gnutls_session_t session) int gnutls_ia_handshake_p (gnutls_session_t session) { - tls_ext_st *ext = &session->security_parameters.extensions; + extension_priv_data_t epriv; + ia_ext_st * priv; + int ret; + + ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SERVER_NAME, &epriv); + if (ret < 0) + { + gnutls_assert(); + return ret; + } + priv = epriv.ptr; /* Either local side or peer doesn't do TLS/IA: don't do IA */ - if (!ext->gnutls_ia_enable || !ext->gnutls_ia_peer_enable) + if (!(priv->flags & IA_ENABLE) || !(priv->flags & IA_PEER_ENABLE)) return 0; /* Not resuming or we don't allow skipping on resumption locally: do IA */ - if (!ext->gnutls_ia_allowskip || !gnutls_session_is_resumed (session)) + if (!(priv->flags & IA_ALLOW_SKIP) || !gnutls_session_is_resumed (session)) return 1; /* If we're resuming and we and the peer both allow skipping on resumption: * don't do IA */ - return !ext->gnutls_ia_peer_allowskip; + return !(priv->flags & IA_PEER_ALLOW_SKIP); } @@ -902,10 +966,24 @@ gnutls_ia_get_server_avp_ptr (gnutls_ia_server_credentials_t cred) * calling gnutls_ia_handshake() or one of the lower level gnutls_ia_* * functions. **/ -void -gnutls_ia_enable (gnutls_session_t session, int allow_skip_on_resume) +void gnutls_ia_enable (gnutls_session_t session, int allow_skip_on_resume) { - session->security_parameters.extensions.gnutls_ia_enable = 1; - session->security_parameters.extensions.gnutls_ia_allowskip = - allow_skip_on_resume; + extension_priv_data_t epriv; + ia_ext_st * priv; + + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) + { + gnutls_assert(); + return; + } + + epriv.ptr = priv; + + priv->flags |= IA_ENABLE; + if (allow_skip_on_resume) + priv->flags |= IA_ALLOW_SKIP; + + _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_INNER_APPLICATION, epriv); + } diff --git a/src/cli.c b/src/cli.c index 4d90b43191..f0eba23a7c 100644 --- a/src/cli.c +++ b/src/cli.c @@ -601,14 +601,8 @@ init_tls_session (const char *hostname) } } -#ifdef ENABLE_OPRFI - if (info.opaque_prf_input) - gnutls_oprfi_enable_client (session, strlen (info.opaque_prf_input), - info.opaque_prf_input); -#endif - #ifdef ENABLE_SESSION_TICKET - if (!info.noticket) + if (disable_extensions ==0 && !info.noticket) gnutls_session_ticket_enable_client (session); #endif @@ -774,6 +768,7 @@ main (int argc, char **argv) &session_data_size); gnutls_session_get_id (hd.session, NULL, &session_id_size); + session_id = malloc (session_id_size); gnutls_session_get_id (hd.session, session_id, &session_id_size); diff --git a/src/serv.c b/src/serv.c index a2457ea781..eb7b892ab7 100644 --- a/src/serv.c +++ b/src/serv.c @@ -333,29 +333,6 @@ static int comp_priority[PRI_MAX]; static int mac_priority[PRI_MAX]; static int cert_type_priority[PRI_MAX]; -#if ENABLE_OPRFI -int -oprfi_callback (gnutls_session_t session, - void *userdata, - size_t oprfi_len, - const unsigned char *in_oprfi, unsigned char *out_oprfi) -{ - size_t ourlen = strlen (info.opaque_prf_input); - size_t i; - - printf ("- Received Opaque PRF data of %d bytes\n", oprfi_len); - printf (" data: "); - for (i = 0; i < oprfi_len; i++) - printf ("%02x", in_oprfi[i]); - printf ("\n"); - - memset (out_oprfi, 0, oprfi_len); - strncpy (out_oprfi, info.opaque_prf_input, oprfi_len); - - return 0; -} -#endif - static gnutls_session_t initialize_session (void) { @@ -420,11 +397,6 @@ initialize_session (void) gnutls_certificate_server_set_request (session, GNUTLS_CERT_REQUEST); } -#ifdef ENABLE_OPRFI - if (info.opaque_prf_input) - gnutls_oprfi_enable_server (session, oprfi_callback, NULL); -#endif - return session; } diff --git a/tests/Makefile.am b/tests/Makefile.am index 165370a3c6..a6dcb33a02 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -83,10 +83,6 @@ endif tlsia_LDADD = ../libextra/libgnutls-extra.la $(LDADD) $(LTLIBREADLINE) endif -if ENABLE_OPRFI -ctests += oprfi -endif - check_PROGRAMS = $(ctests) dist_check_SCRIPTS = rfc2253-escape-test diff --git a/tests/oprfi.c b/tests/oprfi.c deleted file mode 100644 index ea6b8e4673..0000000000 --- a/tests/oprfi.c +++ /dev/null @@ -1,413 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software - * Foundation, Inc. - * - * Author: Simon Josefsson - * - * This file is part of GnuTLS. - * - * GnuTLS is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * GnuTLS 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GnuTLS; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -/* Parts copied from GnuTLS example programs. */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "utils.h" - -static void -tls_log_func (int level, const char *str) -{ - fprintf (stderr, "|<%d>| %s", level, str); -} - -/* A very basic TLS client, with anonymous authentication. - */ - -#define MAX_BUF 1024 -#define MSG "Hello TLS" - -/* Connects to the peer and returns a socket - * descriptor. - */ -int -tcp_connect (void) -{ - const char *PORT = "5556"; - const char *SERVER = "127.0.0.1"; - int err, sd; - struct sockaddr_in sa; - - /* connects to server - */ - sd = socket (AF_INET, SOCK_STREAM, 0); - - memset (&sa, '\0', sizeof (sa)); - sa.sin_family = AF_INET; - sa.sin_port = htons (atoi (PORT)); - inet_pton (AF_INET, SERVER, &sa.sin_addr); - - err = connect (sd, (struct sockaddr *) &sa, sizeof (sa)); - if (err < 0) - { - fprintf (stderr, "Connect error\n"); - exit (1); - } - - return sd; -} - -/* closes the given socket descriptor. - */ -void -tcp_close (int sd) -{ - shutdown (sd, SHUT_RDWR); /* no more receptions */ - close (sd); -} - -void -client (void) -{ - int ret, sd, ii; - gnutls_session_t session; - char buffer[MAX_BUF + 1]; - gnutls_anon_client_credentials_t anoncred; - /* Need to enable anonymous KX specifically. */ - const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 }; - - gnutls_global_init (); - - gnutls_global_set_log_function (tls_log_func); - if (debug) - gnutls_global_set_log_level (4711); - - gnutls_anon_allocate_client_credentials (&anoncred); - - /* Initialize TLS session - */ - gnutls_init (&session, GNUTLS_CLIENT); - - /* Use default priorities */ - gnutls_set_default_priority (session); - gnutls_kx_set_priority (session, kx_prio); - - /* put the anonymous credentials to the current session - */ - gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred); - - gnutls_oprfi_enable_client (session, 3, "foo"); - - /* connect to the peer - */ - sd = tcp_connect (); - - gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd); - - /* Perform the TLS handshake - */ - ret = gnutls_handshake (session); - - if (ret < 0) - { - fail ("client: Handshake failed\n"); - gnutls_perror (ret); - goto end; - } - else - { - success ("client: Handshake was completed\n"); - } - - success ("client: TLS version is: %s\n", - gnutls_protocol_get_name (gnutls_protocol_get_version (session))); - - gnutls_record_send (session, MSG, strlen (MSG)); - - ret = gnutls_record_recv (session, buffer, MAX_BUF); - if (ret == 0) - { - success ("client: Peer has closed the TLS connection\n"); - goto end; - } - else if (ret < 0) - { - fail ("client: Error: %s\n", gnutls_strerror (ret)); - goto end; - } - - printf ("- Received %d bytes: ", ret); - for (ii = 0; ii < ret; ii++) - { - fputc (buffer[ii], stdout); - } - fputs ("\n", stdout); - - gnutls_bye (session, GNUTLS_SHUT_RDWR); - -end: - - tcp_close (sd); - - gnutls_deinit (session); - - gnutls_anon_free_client_credentials (anoncred); - - gnutls_global_deinit (); -} - -/* This is a sample TLS 1.0 echo server, for anonymous authentication only. - */ - -#define SA struct sockaddr -#define MAX_BUF 1024 -#define PORT 5556 /* listen to 5556 port */ -#define DH_BITS 1024 - -/* These are global */ -gnutls_anon_server_credentials_t anoncred; - -int -oprfi_callback (gnutls_session_t session, - void *userdata, - size_t oprfi_len, - const unsigned char *in_oprfi, unsigned char *out_oprfi) -{ - size_t i; - - puts ("cb"); - - for (i = 0; i < oprfi_len; i++) - printf ("OPRF[%d]: %02x %03d %c\n", i, in_oprfi[i], - in_oprfi[i], in_oprfi[i]); - - memset (out_oprfi, 42, oprfi_len); - - return 0; -} - -gnutls_session_t -initialize_tls_session (void) -{ - gnutls_session_t session; - const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 }; - - gnutls_init (&session, GNUTLS_SERVER); - - /* avoid calling all the priority functions, since the defaults - * are adequate. - */ - gnutls_set_default_priority (session); - gnutls_kx_set_priority (session, kx_prio); - - gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred); - - gnutls_dh_set_prime_bits (session, DH_BITS); - - gnutls_oprfi_enable_server (session, oprfi_callback, NULL); - - return session; -} - -static gnutls_dh_params_t dh_params; - -static int -generate_dh_params (void) -{ - const gnutls_datum_t p3 = { pkcs3, strlen (pkcs3) }; - /* Generate Diffie-Hellman parameters - for use with DHE - * kx algorithms. These should be discarded and regenerated - * once a day, once a week or once a month. Depending on the - * security requirements. - */ - gnutls_dh_params_init (&dh_params); - return gnutls_dh_params_import_pkcs3 (dh_params, &p3, GNUTLS_X509_FMT_PEM); -} - -int err, listen_sd, i; -int sd, ret; -struct sockaddr_in sa_serv; -struct sockaddr_in sa_cli; -int client_len; -char topbuf[512]; -gnutls_session_t session; -char buffer[MAX_BUF + 1]; -int optval = 1; - -void -server_start (void) -{ - /* this must be called once in the program - */ - gnutls_global_init (); - - gnutls_global_set_log_function (tls_log_func); - if (debug) - gnutls_global_set_log_level (4711); - - gnutls_anon_allocate_server_credentials (&anoncred); - - success ("Launched, generating DH parameters...\n"); - - generate_dh_params (); - - gnutls_anon_set_server_dh_params (anoncred, dh_params); - - /* Socket operations - */ - listen_sd = socket (AF_INET, SOCK_STREAM, 0); - if (err == -1) - { - perror ("socket"); - fail ("server: socket failed\n"); - return; - } - - memset (&sa_serv, '\0', sizeof (sa_serv)); - sa_serv.sin_family = AF_INET; - sa_serv.sin_addr.s_addr = INADDR_ANY; - sa_serv.sin_port = htons (PORT); /* Server Port number */ - - setsockopt (listen_sd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval, - sizeof (int)); - - err = bind (listen_sd, (SA *) & sa_serv, sizeof (sa_serv)); - if (err == -1) - { - perror ("bind"); - fail ("server: bind failed\n"); - return; - } - - err = listen (listen_sd, 1024); - if (err == -1) - { - perror ("listen"); - fail ("server: listen failed\n"); - return; - } - - success ("server: ready. Listening to port '%d'.\n", PORT); -} - -void -server (void) -{ - client_len = sizeof (sa_cli); - - session = initialize_tls_session (); - - sd = accept (listen_sd, (SA *) & sa_cli, &client_len); - - success ("server: connection from %s, port %d\n", - inet_ntop (AF_INET, &sa_cli.sin_addr, topbuf, - sizeof (topbuf)), ntohs (sa_cli.sin_port)); - - gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd); - ret = gnutls_handshake (session); - if (ret < 0) - { - close (sd); - gnutls_deinit (session); - fail ("server: Handshake has failed (%s)\n\n", gnutls_strerror (ret)); - return; - } - success ("server: Handshake was completed\n"); - - success ("server: TLS version is: %s\n", - gnutls_protocol_get_name (gnutls_protocol_get_version (session))); - - /* see the Getting peer's information example */ - /* print_info(session); */ - - i = 0; - for (;;) - { - memset (buffer, 0, MAX_BUF + 1); - ret = gnutls_record_recv (session, buffer, MAX_BUF); - - if (ret == 0) - { - success ("server: Peer has closed the GnuTLS connection\n"); - break; - } - else if (ret < 0) - { - fail ("server: Received corrupted data(%d). Closing...\n", ret); - break; - } - else if (ret > 0) - { - /* echo data back to the client - */ - gnutls_record_send (session, buffer, strlen (buffer)); - } - } - /* do not wait for the peer to close the connection. - */ - gnutls_bye (session, GNUTLS_SHUT_WR); - - close (sd); - gnutls_deinit (session); - - close (listen_sd); - - gnutls_anon_free_server_credentials (anoncred); - - gnutls_global_deinit (); - - success ("server: finished\n"); -} - -void -doit (void) -{ - pid_t child; - - server_start (); - if (error_count) - return; - - child = fork (); - if (child < 0) - { - perror ("fork"); - fail ("fork"); - return; - } - - if (child) - { - int status; - /* parent */ - server (); - wait (&status); - } - else - client (); -} diff --git a/tests/tlsia.c b/tests/tlsia.c index dd42892af9..c97ce9517f 100644 --- a/tests/tlsia.c +++ b/tests/tlsia.c @@ -51,6 +51,12 @@ #define MAX_BUF 1024 #define MSG "Hello TLS" +static void +tls_log_func (int level, const char *str) +{ + fprintf (stderr, "<%d>| %s", level, str); +} + static int client_avp (gnutls_session_t session, void *ptr, const char *last, size_t lastlen, char **new, size_t * newlen) @@ -117,6 +123,10 @@ client (void) const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 }; ret = gnutls_global_init (); + gnutls_global_set_log_function (tls_log_func); + if (debug) + gnutls_global_set_log_level (2); + if (ret) fail ("global_init: %d\n", ret); ret = gnutls_global_init_extra (); @@ -425,6 +435,10 @@ server (void) if (ret) fail ("global_init_extra: %d\n", ret); + gnutls_global_set_log_function (tls_log_func); + if (debug) + gnutls_global_set_log_level (2); + gnutls_anon_allocate_server_credentials (&anoncred); gnutls_ia_allocate_server_credentials (&iacred);