From: Nikos Mavrogiannopoulos Date: Wed, 20 Sep 2017 08:05:53 +0000 (+0200) Subject: extensions: use the low-level extension parsing code for hello parsing X-Git-Tag: gnutls_3_6_3~401 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=377410a805eb078eefd43def58c01fbf564ff667;p=thirdparty%2Fgnutls.git extensions: use the low-level extension parsing code for hello parsing That's a step towards unification of TLS-type extension handling for TLS 1.3. Signed-off-by: Nikos Mavrogiannopoulos --- diff --git a/lib/ext/alpn.c b/lib/ext/alpn.c index 8c554da51c..59ec3a3b22 100644 --- a/lib/ext/alpn.c +++ b/lib/ext/alpn.c @@ -34,7 +34,7 @@ static int _gnutls_alpn_send_params(gnutls_session_t session, static void _gnutls_alpn_deinit_data(gnutls_ext_priv_data_t priv); -const extension_entry_st ext_mod_alpn = { +const hello_ext_entry_st ext_mod_alpn = { .name = "ALPN", .tls_id = 16, .gid = GNUTLS_EXTENSION_ALPN, diff --git a/lib/ext/alpn.h b/lib/ext/alpn.h index 60d5266ef6..b04eabd1b2 100644 --- a/lib/ext/alpn.h +++ b/lib/ext/alpn.h @@ -34,6 +34,6 @@ typedef struct { unsigned flags; } alpn_ext_st; -extern const extension_entry_st ext_mod_alpn; +extern const hello_ext_entry_st ext_mod_alpn; #endif diff --git a/lib/ext/dumbfw.c b/lib/ext/dumbfw.c index 2c25ea5522..3ffeeca560 100644 --- a/lib/ext/dumbfw.c +++ b/lib/ext/dumbfw.c @@ -35,7 +35,7 @@ static int _gnutls_dumbfw_send_params(gnutls_session_t session, gnutls_buffer_st * extdata); -const extension_entry_st ext_mod_dumbfw = { +const hello_ext_entry_st ext_mod_dumbfw = { .name = "ClientHello Padding", .tls_id = 21, .gid = GNUTLS_EXTENSION_DUMBFW, diff --git a/lib/ext/dumbfw.h b/lib/ext/dumbfw.h index a3bd756eb8..6ee30e9f6b 100644 --- a/lib/ext/dumbfw.h +++ b/lib/ext/dumbfw.h @@ -22,6 +22,6 @@ #include -extern const extension_entry_st ext_mod_dumbfw; +extern const hello_ext_entry_st ext_mod_dumbfw; #endif diff --git a/lib/ext/ecc.c b/lib/ext/ecc.c index 1679eda59f..797046bb2f 100644 --- a/lib/ext/ecc.c +++ b/lib/ext/ecc.c @@ -49,7 +49,7 @@ static int _gnutls_supported_ecc_pf_send_params(gnutls_session_t session, gnutls_buffer_st * extdata); -const extension_entry_st ext_mod_supported_ecc = { +const hello_ext_entry_st ext_mod_supported_ecc = { .name = "Negotiated Groups", .tls_id = 10, .gid = GNUTLS_EXTENSION_SUPPORTED_ECC, @@ -64,7 +64,7 @@ const extension_entry_st ext_mod_supported_ecc = { .cannot_be_overriden = 1 }; -const extension_entry_st ext_mod_supported_ecc_pf = { +const hello_ext_entry_st ext_mod_supported_ecc_pf = { .name = "Supported ECC Point Formats", .tls_id = 11, .gid = GNUTLS_EXTENSION_SUPPORTED_ECC_PF, diff --git a/lib/ext/ecc.h b/lib/ext/ecc.h index a3b4311f64..50074843ef 100644 --- a/lib/ext/ecc.h +++ b/lib/ext/ecc.h @@ -24,8 +24,8 @@ #include -extern const extension_entry_st ext_mod_supported_ecc; -extern const extension_entry_st ext_mod_supported_ecc_pf; +extern const hello_ext_entry_st ext_mod_supported_ecc; +extern const hello_ext_entry_st ext_mod_supported_ecc_pf; int _gnutls_session_supports_group(gnutls_session_t session, diff --git a/lib/ext/etm.c b/lib/ext/etm.c index 0fa9805ea4..eda7f457ee 100644 --- a/lib/ext/etm.c +++ b/lib/ext/etm.c @@ -35,7 +35,7 @@ static int _gnutls_ext_etm_recv_params(gnutls_session_t session, static int _gnutls_ext_etm_send_params(gnutls_session_t session, gnutls_buffer_st * extdata); -const extension_entry_st ext_mod_etm = { +const hello_ext_entry_st ext_mod_etm = { .name = "Encrypt-then-MAC", .tls_id = 22, .gid = GNUTLS_EXTENSION_ETM, diff --git a/lib/ext/etm.h b/lib/ext/etm.h index 5ceeb618d2..3a14c662c7 100644 --- a/lib/ext/etm.h +++ b/lib/ext/etm.h @@ -25,6 +25,6 @@ #include -extern const extension_entry_st ext_mod_etm; +extern const hello_ext_entry_st ext_mod_etm; #endif diff --git a/lib/ext/ext_master_secret.c b/lib/ext/ext_master_secret.c index edbc7f6cd6..4c3c937426 100644 --- a/lib/ext/ext_master_secret.c +++ b/lib/ext/ext_master_secret.c @@ -35,7 +35,7 @@ static int _gnutls_ext_master_secret_recv_params(gnutls_session_t session, static int _gnutls_ext_master_secret_send_params(gnutls_session_t session, gnutls_buffer_st * extdata); -const extension_entry_st ext_mod_ext_master_secret = { +const hello_ext_entry_st ext_mod_ext_master_secret = { .name = "Extended Master Secret", .tls_id = 23, .gid = GNUTLS_EXTENSION_EXT_MASTER_SECRET, diff --git a/lib/ext/ext_master_secret.h b/lib/ext/ext_master_secret.h index 04d20ab3fb..cfe4d26ff2 100644 --- a/lib/ext/ext_master_secret.h +++ b/lib/ext/ext_master_secret.h @@ -25,6 +25,6 @@ #include -extern const extension_entry_st ext_mod_ext_master_secret; +extern const hello_ext_entry_st ext_mod_ext_master_secret; #endif diff --git a/lib/ext/heartbeat.c b/lib/ext/heartbeat.c index 1df9fedd08..32a3c29c43 100644 --- a/lib/ext/heartbeat.c +++ b/lib/ext/heartbeat.c @@ -522,7 +522,7 @@ _gnutls_heartbeat_unpack(gnutls_buffer_st * ps, return ret; } -const extension_entry_st ext_mod_heartbeat = { +const hello_ext_entry_st ext_mod_heartbeat = { .name = "Heartbeat", .tls_id = 15, .gid = GNUTLS_EXTENSION_HEARTBEAT, diff --git a/lib/ext/heartbeat.h b/lib/ext/heartbeat.h index c304e93a36..f319b87b02 100644 --- a/lib/ext/heartbeat.h +++ b/lib/ext/heartbeat.h @@ -36,7 +36,7 @@ #define HEARTBEAT_DEFAULT_POLICY PEER_NOT_ALLOWED_TO_SEND -extern const extension_entry_st ext_mod_heartbeat; +extern const hello_ext_entry_st ext_mod_heartbeat; int _gnutls_heartbeat_handle(gnutls_session_t session, mbuffer_st * bufel); int _gnutls_heartbeat_enabled(gnutls_session_t session, int local); diff --git a/lib/ext/key_share.c b/lib/ext/key_share.c index 5354cdec55..ed95a29765 100644 --- a/lib/ext/key_share.c +++ b/lib/ext/key_share.c @@ -43,7 +43,7 @@ static int key_share_recv_params(gnutls_session_t session, static int key_share_send_params(gnutls_session_t session, gnutls_buffer_st * extdata); -const extension_entry_st ext_mod_key_share = { +const hello_ext_entry_st ext_mod_key_share = { .name = "Key Share", .tls_id = 40, .gid = GNUTLS_EXTENSION_KEY_SHARE, diff --git a/lib/ext/key_share.h b/lib/ext/key_share.h index 11d6345d00..7e8fd327a6 100644 --- a/lib/ext/key_share.h +++ b/lib/ext/key_share.h @@ -25,6 +25,6 @@ #include -extern const extension_entry_st ext_mod_key_share; +extern const hello_ext_entry_st ext_mod_key_share; #endif diff --git a/lib/ext/max_record.c b/lib/ext/max_record.c index 4f34651476..5b70aba5f2 100644 --- a/lib/ext/max_record.c +++ b/lib/ext/max_record.c @@ -47,7 +47,7 @@ static int _gnutls_mre_num2record(int num); static int _gnutls_mre_record2num(uint16_t record_size); -const extension_entry_st ext_mod_max_record_size = { +const hello_ext_entry_st ext_mod_max_record_size = { .name = "Maximum Record Size", .tls_id = 1, .gid = GNUTLS_EXTENSION_MAX_RECORD_SIZE, diff --git a/lib/ext/max_record.h b/lib/ext/max_record.h index 27e621e930..cdbe6094d3 100644 --- a/lib/ext/max_record.h +++ b/lib/ext/max_record.h @@ -25,6 +25,6 @@ #include -extern const extension_entry_st ext_mod_max_record_size; +extern const hello_ext_entry_st ext_mod_max_record_size; #endif diff --git a/lib/ext/post_handshake.c b/lib/ext/post_handshake.c index bb6cc31c09..d4bf312397 100644 --- a/lib/ext/post_handshake.c +++ b/lib/ext/post_handshake.c @@ -36,7 +36,7 @@ static int _gnutls_post_handshake_recv_params(gnutls_session_t session, static int _gnutls_post_handshake_send_params(gnutls_session_t session, gnutls_buffer_st * extdata); -const extension_entry_st ext_mod_post_handshake = { +const hello_ext_entry_st ext_mod_post_handshake = { .name = "Post Handshake Auth", .tls_id = 49, .gid = GNUTLS_EXTENSION_POST_HANDSHAKE, diff --git a/lib/ext/post_handshake.h b/lib/ext/post_handshake.h index 4f48930521..eb4872ccf4 100644 --- a/lib/ext/post_handshake.h +++ b/lib/ext/post_handshake.h @@ -25,6 +25,6 @@ #include -extern const extension_entry_st ext_mod_post_handshake; +extern const hello_ext_entry_st ext_mod_post_handshake; #endif diff --git a/lib/ext/safe_renegotiation.c b/lib/ext/safe_renegotiation.c index ec2791588f..6870cf0bd9 100644 --- a/lib/ext/safe_renegotiation.c +++ b/lib/ext/safe_renegotiation.c @@ -31,7 +31,7 @@ static int _gnutls_sr_send_params(gnutls_session_t state, gnutls_buffer_st *); static void _gnutls_sr_deinit_data(gnutls_ext_priv_data_t priv); -const extension_entry_st ext_mod_sr = { +const hello_ext_entry_st ext_mod_sr = { .name = "Safe Renegotiation", .tls_id = 65281, .gid = GNUTLS_EXTENSION_SAFE_RENEGOTIATION, diff --git a/lib/ext/safe_renegotiation.h b/lib/ext/safe_renegotiation.h index 1838d5a08e..e3f0a81d04 100644 --- a/lib/ext/safe_renegotiation.h +++ b/lib/ext/safe_renegotiation.h @@ -38,7 +38,7 @@ typedef struct { unsigned int connection_using_safe_renegotiation:1; } sr_ext_st; -extern const extension_entry_st ext_mod_sr; +extern const hello_ext_entry_st ext_mod_sr; int _gnutls_ext_sr_finished(gnutls_session_t session, void *vdata, size_t vdata_size, int dir); diff --git a/lib/ext/server_name.c b/lib/ext/server_name.c index ffec574e04..649e4d7d02 100644 --- a/lib/ext/server_name.c +++ b/lib/ext/server_name.c @@ -45,7 +45,7 @@ _gnutls_server_name_set_raw(gnutls_session_t session, gnutls_server_name_type_t type, const void *name, size_t name_length); -const extension_entry_st ext_mod_server_name = { +const hello_ext_entry_st ext_mod_server_name = { .name = "Server Name Indication", .tls_id = 0, .gid = GNUTLS_EXTENSION_SERVER_NAME, diff --git a/lib/ext/server_name.h b/lib/ext/server_name.h index 95caa33deb..9b6085a23d 100644 --- a/lib/ext/server_name.h +++ b/lib/ext/server_name.h @@ -31,7 +31,7 @@ typedef struct { gnutls_server_name_type_t type; } server_name_ext_st; -extern const extension_entry_st ext_mod_server_name; +extern const hello_ext_entry_st ext_mod_server_name; unsigned _gnutls_server_name_matches_resumed(gnutls_session_t); diff --git a/lib/ext/session_ticket.c b/lib/ext/session_ticket.c index 3564db1445..459f39bcdb 100644 --- a/lib/ext/session_ticket.c +++ b/lib/ext/session_ticket.c @@ -59,7 +59,7 @@ static int session_ticket_pack(gnutls_ext_priv_data_t _priv, gnutls_buffer_st * ps); static void session_ticket_deinit_data(gnutls_ext_priv_data_t priv); -const extension_entry_st ext_mod_session_ticket = { +const hello_ext_entry_st ext_mod_session_ticket = { .name = "Session Ticket", .tls_id = 35, .gid = GNUTLS_EXTENSION_SESSION_TICKET, diff --git a/lib/ext/session_ticket.h b/lib/ext/session_ticket.h index 5c862d28d0..f82565b073 100644 --- a/lib/ext/session_ticket.h +++ b/lib/ext/session_ticket.h @@ -25,7 +25,7 @@ #include -extern const extension_entry_st ext_mod_session_ticket; +extern const hello_ext_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); diff --git a/lib/ext/signature.c b/lib/ext/signature.c index f41c91e46b..1301d821d9 100644 --- a/lib/ext/signature.c +++ b/lib/ext/signature.c @@ -49,7 +49,7 @@ static int signature_algorithms_pack(gnutls_ext_priv_data_t epriv, static int signature_algorithms_unpack(gnutls_buffer_st * ps, gnutls_ext_priv_data_t * _priv); -const extension_entry_st ext_mod_sig = { +const hello_ext_entry_st ext_mod_sig = { .name = "Signature Algorithms", .tls_id = 13, .gid = GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, diff --git a/lib/ext/signature.h b/lib/ext/signature.h index 5e8f710c13..373af2fa86 100644 --- a/lib/ext/signature.h +++ b/lib/ext/signature.h @@ -27,7 +27,7 @@ #include -extern const extension_entry_st ext_mod_sig; +extern const hello_ext_entry_st ext_mod_sig; gnutls_sign_algorithm_t _gnutls_session_get_sign_algo(gnutls_session_t session, diff --git a/lib/ext/srp.c b/lib/ext/srp.c index 1980e169da..d6f87b5d4c 100644 --- a/lib/ext/srp.c +++ b/lib/ext/srp.c @@ -42,7 +42,7 @@ static int _gnutls_srp_recv_params(gnutls_session_t state, static int _gnutls_srp_send_params(gnutls_session_t state, gnutls_buffer_st * extdata); -const extension_entry_st ext_mod_srp = { +const hello_ext_entry_st ext_mod_srp = { .name = "SRP", .tls_id = 12, .gid = GNUTLS_EXTENSION_SRP, diff --git a/lib/ext/srp.h b/lib/ext/srp.h index 00b8e2ba0e..a18efc9780 100644 --- a/lib/ext/srp.h +++ b/lib/ext/srp.h @@ -30,7 +30,7 @@ #define IS_SRP_KX(kx) ((kx == GNUTLS_KX_SRP || (kx == GNUTLS_KX_SRP_RSA) || \ kx == GNUTLS_KX_SRP_DSS)?1:0) -extern const extension_entry_st ext_mod_srp; +extern const hello_ext_entry_st ext_mod_srp; typedef struct { char *username; diff --git a/lib/ext/srtp.c b/lib/ext/srtp.c index a513feabd6..1931327d65 100644 --- a/lib/ext/srtp.c +++ b/lib/ext/srtp.c @@ -39,7 +39,7 @@ static int _gnutls_srtp_pack(gnutls_ext_priv_data_t _priv, static void _gnutls_srtp_deinit_data(gnutls_ext_priv_data_t priv); -const extension_entry_st ext_mod_srtp = { +const hello_ext_entry_st ext_mod_srtp = { .name = "SRTP", .tls_id = 14, .gid = GNUTLS_EXTENSION_SRTP, diff --git a/lib/ext/srtp.h b/lib/ext/srtp.h index 7846fa2942..82482e577f 100644 --- a/lib/ext/srtp.h +++ b/lib/ext/srtp.h @@ -35,6 +35,6 @@ typedef struct { unsigned int mki_received; } srtp_ext_st; -extern const extension_entry_st ext_mod_srtp; +extern const hello_ext_entry_st ext_mod_srtp; #endif diff --git a/lib/ext/status_request.c b/lib/ext/status_request.c index ae5b6b7298..8a3515d199 100644 --- a/lib/ext/status_request.c +++ b/lib/ext/status_request.c @@ -529,7 +529,7 @@ _gnutls_status_request_unpack(gnutls_buffer_st * ps, return ret; } -const extension_entry_st ext_mod_status_request = { +const hello_ext_entry_st ext_mod_status_request = { .name = "OCSP Status Request", .tls_id = 5, .gid = GNUTLS_EXTENSION_STATUS_REQUEST, diff --git a/lib/ext/status_request.h b/lib/ext/status_request.h index 81809b1f65..f01d54724f 100644 --- a/lib/ext/status_request.h +++ b/lib/ext/status_request.h @@ -25,7 +25,7 @@ #include -extern const extension_entry_st ext_mod_status_request; +extern const hello_ext_entry_st ext_mod_status_request; int _gnutls_send_server_certificate_status(gnutls_session_t session, diff --git a/lib/ext/supported_versions.c b/lib/ext/supported_versions.c index 26d652b037..5ffb9bb4ba 100644 --- a/lib/ext/supported_versions.c +++ b/lib/ext/supported_versions.c @@ -36,7 +36,7 @@ static int supported_versions_recv_params(gnutls_session_t session, static int supported_versions_send_params(gnutls_session_t session, gnutls_buffer_st * extdata); -const extension_entry_st ext_mod_supported_versions = { +const hello_ext_entry_st ext_mod_supported_versions = { .name = "Supported Versions", .tls_id = 43, .gid = GNUTLS_EXTENSION_SUPPORTED_VERSIONS, diff --git a/lib/ext/supported_versions.h b/lib/ext/supported_versions.h index 288851c5db..7eb0abfbf2 100644 --- a/lib/ext/supported_versions.h +++ b/lib/ext/supported_versions.h @@ -25,6 +25,6 @@ #include -extern const extension_entry_st ext_mod_supported_versions; +extern const hello_ext_entry_st ext_mod_supported_versions; #endif diff --git a/lib/extensions.c b/lib/extensions.c index 8ebf4ab378..c338f6fc0c 100644 --- a/lib/extensions.c +++ b/lib/extensions.c @@ -47,15 +47,16 @@ #include #include #include +#include "extv.h" #include static void -unset_ext_data(gnutls_session_t session, const struct extension_entry_st *, unsigned idx); +unset_ext_data(gnutls_session_t session, const struct hello_ext_entry_st *, unsigned idx); -static int ext_register(extension_entry_st * mod); -static void unset_resumed_ext_data(gnutls_session_t session, const struct extension_entry_st *, unsigned idx); +static int ext_register(hello_ext_entry_st * mod); +static void unset_resumed_ext_data(gnutls_session_t session, const struct hello_ext_entry_st *, unsigned idx); -static extension_entry_st const *extfunc[MAX_EXT_TYPES+1] = { +static hello_ext_entry_st const *extfunc[MAX_EXT_TYPES+1] = { &ext_mod_max_record_size, &ext_mod_ext_master_secret, &ext_mod_supported_versions, @@ -91,11 +92,11 @@ static extension_entry_st const *extfunc[MAX_EXT_TYPES+1] = { NULL }; -static const extension_entry_st * +static const hello_ext_entry_st * _gnutls_ext_ptr(gnutls_session_t session, extensions_t id, gnutls_ext_parse_type_t parse_type) { unsigned i; - const extension_entry_st *e; + const hello_ext_entry_st *e; for (i=0;iinternals.rexts_size;i++) { if (session->internals.rexts[i].gid == id) { @@ -163,127 +164,113 @@ void _gnutls_extension_list_add_sr(gnutls_session_t session) _gnutls_extension_list_add(session, &ext_mod_sr, 1); } -int -_gnutls_parse_extensions(gnutls_session_t session, - gnutls_ext_flags_t msg, - gnutls_ext_parse_type_t parse_type, - const uint8_t * data, int data_size) -{ - int next, ret; - int pos = 0; - uint16_t tls_id; - extensions_t id; - const uint8_t *sdata; - const extension_entry_st *ext; - uint16_t size; - - if (data_size == 0) - return 0; +typedef struct hello_ext_ctx_st { + gnutls_session_t session; + gnutls_ext_flags_t msg; + gnutls_ext_parse_type_t parse_type; + const hello_ext_entry_st *ext; /* used during send */ +} hello_ext_ctx_st; - DECR_LENGTH_RET(data_size, 2, GNUTLS_E_UNEXPECTED_EXTENSIONS_LENGTH); - next = _gnutls_read_uint16(data); - pos += 2; - - DECR_LENGTH_RET(data_size, next, GNUTLS_E_UNEXPECTED_EXTENSIONS_LENGTH); +static +int hello_ext_parse(void *_ctx, uint16_t tls_id, const uint8_t *data, int data_size) +{ + hello_ext_ctx_st *ctx = _ctx; + gnutls_session_t session = ctx->session; + const hello_ext_entry_st *ext; + unsigned id; + int ret; - if (next == 0 && data_size == 0) /* field is present, but has zero length? Ignore it. */ + id = tls_id_to_gid(session, tls_id); + if (id == 0) { /* skip */ return 0; - else if (data_size > 0) /* forbid unaccounted data */ - return gnutls_assert_val(GNUTLS_E_UNEXPECTED_EXTENSIONS_LENGTH); - - do { - DECR_LENGTH_RET(next, 2, GNUTLS_E_UNEXPECTED_EXTENSIONS_LENGTH); - tls_id = _gnutls_read_uint16(&data[pos]); - pos += 2; - - id = tls_id_to_gid(session, tls_id); - if (id == 0) { - goto skip; - } + } - if (session->security_parameters.entity == GNUTLS_CLIENT) { - if ((ret = - _gnutls_extension_list_check(session, id)) < 0) { - _gnutls_debug_log("EXT[%p]: Received unexpected extension '%s/%d'\n", session, - gnutls_ext_get_name(tls_id), (int)tls_id); - gnutls_assert(); - return ret; - } + if (session->security_parameters.entity == GNUTLS_CLIENT) { + if ((ret = + _gnutls_extension_list_check(session, id)) < 0) { + _gnutls_debug_log("EXT[%p]: Received unexpected extension '%s/%d'\n", session, + gnutls_ext_get_name(tls_id), (int)tls_id); + gnutls_assert(); + return ret; } + } - skip: - DECR_LENGTH_RET(next, 2, GNUTLS_E_UNEXPECTED_EXTENSIONS_LENGTH); - size = _gnutls_read_uint16(&data[pos]); - pos += 2; - - DECR_LENGTH_RET(next, size, GNUTLS_E_UNEXPECTED_EXTENSIONS_LENGTH); - sdata = &data[pos]; - pos += size; - - ext = _gnutls_ext_ptr(session, id, parse_type); - if (ext == NULL || ext->recv_func == NULL) { - _gnutls_handshake_log - ("EXT[%p]: Ignoring extension '%s/%d'\n", session, - gnutls_ext_get_name(tls_id), tls_id); + ext = _gnutls_ext_ptr(session, id, ctx->parse_type); + if (ext == NULL || ext->recv_func == NULL) { + _gnutls_handshake_log + ("EXT[%p]: Ignoring extension '%s/%d'\n", session, + gnutls_ext_get_name(tls_id), tls_id); + return 0; + } - continue; - } + if ((ext->validity & ctx->msg) == 0) { + _gnutls_debug_log("EXT[%p]: Received unexpected extension (%s/%d) for '%s'\n", session, + gnutls_ext_get_name(tls_id), (int)tls_id, + ext_msg_validity_to_str(ctx->msg)); + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION); + } + if (session->security_parameters.entity == GNUTLS_SERVER) { + ret = _gnutls_extension_list_add(session, ext, 1); + if (ret == 0) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION); + } - if ((ext->validity & msg) == 0) { + _gnutls_handshake_log + ("EXT[%p]: Parsing extension '%s/%d' (%d bytes)\n", + session, gnutls_ext_get_name(tls_id), tls_id, + data_size); - _gnutls_debug_log("EXT[%p]: Received unexpected extension (%s/%d) for '%s'\n", session, - gnutls_ext_get_name(tls_id), (int)tls_id, - ext_msg_validity_to_str(msg)); - return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION); - } + if ((ret = ext->recv_func(session, data, data_size)) < 0) { + gnutls_assert(); + return ret; + } - if (session->security_parameters.entity == GNUTLS_SERVER) { - ret = _gnutls_extension_list_add(session, ext, 1); - if (ret == 0) - return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION); - } + return 0; +} - _gnutls_handshake_log - ("EXT[%p]: Parsing extension '%s/%d' (%d bytes)\n", - session, gnutls_ext_get_name(tls_id), tls_id, - size); +int +_gnutls_parse_extensions(gnutls_session_t session, + gnutls_ext_flags_t msg, + gnutls_ext_parse_type_t parse_type, + const uint8_t * data, int data_size) +{ + int ret; + hello_ext_ctx_st ctx; - if ((ret = ext->recv_func(session, sdata, size)) < 0) { - gnutls_assert(); - return ret; - } - } - while (next > 2); + ctx.session = session; + ctx.msg = msg; + ctx.parse_type = parse_type; - /* forbid leftovers */ - if (next > 0) - return gnutls_assert_val(GNUTLS_E_UNEXPECTED_EXTENSIONS_LENGTH); + ret = _gnutls_extv_parse(&ctx, hello_ext_parse, data, data_size); + if (ret < 0) + return gnutls_assert_val(ret); return 0; - } static -int send_extension(gnutls_session_t session, const extension_entry_st *p, - gnutls_buffer_st *extdata, - gnutls_ext_flags_t msg, - gnutls_ext_parse_type_t parse_type) +int hello_ext_send(void *_ctx, gnutls_buffer_st *buf) { - int size_pos, appended, ret; + hello_ext_ctx_st *ctx = _ctx; + int ret; + const hello_ext_entry_st *p = ctx->ext; + gnutls_session_t session = ctx->session; + int appended; size_t size_prev; - if (p->send_func == NULL) + if (unlikely(p->send_func == NULL)) return 0; - if (parse_type != GNUTLS_EXT_ANY - && p->parse_type != parse_type) + if (ctx->parse_type != GNUTLS_EXT_ANY + && p->parse_type != ctx->parse_type) { return 0; + } - if ((msg & p->validity) == 0) { + if ((ctx->msg & p->validity) == 0) { _gnutls_handshake_log("EXT[%p]: Not sending extension (%s/%d) for '%s'\n", session, - gnutls_ext_get_name(p->tls_id), (int)p->tls_id, - ext_msg_validity_to_str(msg)); + p->name, (int)p->tls_id, + ext_msg_validity_to_str(ctx->msg)); return 0; } @@ -292,97 +279,90 @@ int send_extension(gnutls_session_t session, const extension_entry_st *p, ret = _gnutls_extension_list_check(session, p->gid); if (session->security_parameters.entity == GNUTLS_SERVER) { - if (ret < 0) /* not advertized */ + if (ret < 0) {/* not advertized */ return 0; + } } else { - if (ret == 0) /* already sent */ + if (ret == 0) {/* already sent */ return 0; + } } - ret = _gnutls_buffer_append_prefix(extdata, 16, p->tls_id); - if (ret < 0) - return gnutls_assert_val(ret); - size_pos = extdata->length; - ret = _gnutls_buffer_append_prefix(extdata, 16, 0); - if (ret < 0) - return gnutls_assert_val(ret); + size_prev = buf->length; - size_prev = extdata->length; - ret = p->send_func(session, extdata); + ret = p->send_func(session, buf); if (ret < 0 && ret != GNUTLS_E_INT_RET_0) { return gnutls_assert_val(ret); } - /* returning GNUTLS_E_INT_RET_0 means to send an empty - * extension of this type. - */ - appended = extdata->length - size_prev; - - if (appended > 0 || ret == GNUTLS_E_INT_RET_0) { - if (ret == GNUTLS_E_INT_RET_0) - appended = 0; + appended = buf->length - size_prev; - /* write the real size */ - _gnutls_write_uint16(appended, - &extdata->data[size_pos]); - - /* add this extension to the extension list - */ - if (session->security_parameters.entity == GNUTLS_CLIENT) - _gnutls_extension_list_add(session, p, 0); + /* add this extension to the extension list, to know which extensions + * to expect. + */ + if ((appended > 0 || ret == GNUTLS_E_INT_RET_0) && + session->security_parameters.entity == GNUTLS_CLIENT) { - _gnutls_handshake_log - ("EXT[%p]: Sending extension %s/%d (%d bytes)\n", - session, p->name, (int)p->tls_id, appended); - } else if (appended == 0) - extdata->length -= 4; /* reset type and size */ + _gnutls_extension_list_add(session, p, 0); + } - return 0; + return ret; } int _gnutls_gen_extensions(gnutls_session_t session, - gnutls_buffer_st * extdata, + gnutls_buffer_st * buf, gnutls_ext_flags_t msg, gnutls_ext_parse_type_t parse_type) { - int size; int pos, ret; - size_t i, init_size = extdata->length; + size_t i; + hello_ext_ctx_st ctx; - pos = extdata->length; /* we will store length later on */ + ctx.session = session; + ctx.msg = msg; + ctx.parse_type = parse_type; - ret = _gnutls_buffer_append_prefix(extdata, 16, 0); + ret = _gnutls_extv_append_init(buf); if (ret < 0) return gnutls_assert_val(ret); + pos = ret; + for (i=0; i < session->internals.rexts_size; i++) { - ret = send_extension(session, &session->internals.rexts[i], extdata, msg, parse_type); + ctx.ext = &session->internals.rexts[i]; + ret = _gnutls_extv_append(buf, session->internals.rexts[i].tls_id, + &ctx, hello_ext_send); if (ret < 0) return gnutls_assert_val(ret); + + if (ret > 0) + _gnutls_handshake_log + ("EXT[%p]: Sending extension %s/%d (%d bytes)\n", + session, ctx.ext->name, (int)ctx.ext->tls_id, ret-4); } /* send_extension() ensures we don't send duplicates, in case * of overriden extensions */ for (i = 0; extfunc[i] != NULL; i++) { - ret = send_extension(session, extfunc[i], extdata, msg, parse_type); + ctx.ext = extfunc[i]; + ret = _gnutls_extv_append(buf, extfunc[i]->tls_id, + &ctx, hello_ext_send); if (ret < 0) return gnutls_assert_val(ret); - } - - /* remove any initial data, and the size of the header */ - size = extdata->length - init_size - 2; - if (size > UINT16_MAX) /* sent too many extensions */ - return gnutls_assert_val(GNUTLS_E_HANDSHAKE_TOO_LARGE); + if (ret > 0) + _gnutls_handshake_log + ("EXT[%p]: Sending extension %s/%d (%d bytes)\n", + session, ctx.ext->name, (int)ctx.ext->tls_id, ret-4); + } - if (size > 0) - _gnutls_write_uint16(size, &extdata->data[pos]); - else if (size == 0) - extdata->length -= 2; /* the length bytes */ + ret = _gnutls_extv_append_final(buf, pos); + if (ret < 0) + return gnutls_assert_val(ret); - return size; + return 0; } /* Global deinit and init of global extensions */ @@ -404,7 +384,7 @@ void _gnutls_ext_deinit(void) } static -int ext_register(extension_entry_st * mod) +int ext_register(hello_ext_entry_st * mod) { unsigned i = 0; @@ -422,7 +402,7 @@ int ext_register(extension_entry_st * mod) } /* Packing of extension data (for use in resumption) */ -static int pack_extension(gnutls_session_t session, const extension_entry_st *extp, +static int pack_extension(gnutls_session_t session, const hello_ext_entry_st *extp, gnutls_buffer_st *packed) { int ret; @@ -463,7 +443,7 @@ int _gnutls_ext_pack(gnutls_session_t session, gnutls_buffer_st *packed) int ret; int total_exts_pos; int n_exts = 0; - const struct extension_entry_st *ext; + const struct hello_ext_entry_st *ext; total_exts_pos = packed->length; BUFFER_APPEND_NUM(packed, 0); @@ -495,7 +475,7 @@ _gnutls_ext_set_resumed_session_data(gnutls_session_t session, gnutls_ext_priv_data_t data) { int i; - const struct extension_entry_st *ext; + const struct hello_ext_entry_st *ext; ext = _gnutls_ext_ptr(session, id, GNUTLS_EXT_ANY); @@ -521,7 +501,7 @@ int _gnutls_ext_unpack(gnutls_session_t session, gnutls_buffer_st * packed) int max_exts = 0; extensions_t id; int size_for_id, cur_pos; - const struct extension_entry_st *ext; + const struct hello_ext_entry_st *ext; BUFFER_POP_NUM(packed, max_exts); for (i = 0; i < max_exts; i++) { @@ -559,7 +539,7 @@ int _gnutls_ext_unpack(gnutls_session_t session, gnutls_buffer_st * packed) } static void -unset_ext_data(gnutls_session_t session, const struct extension_entry_st *ext, unsigned idx) +unset_ext_data(gnutls_session_t session, const struct hello_ext_entry_st *ext, unsigned idx) { if (session->internals.ext_data[idx].set == 0) return; @@ -574,7 +554,7 @@ _gnutls_ext_unset_session_data(gnutls_session_t session, extensions_t id) { int i; - const struct extension_entry_st *ext; + const struct hello_ext_entry_st *ext; ext = _gnutls_ext_ptr(session, id, GNUTLS_EXT_ANY); @@ -586,7 +566,7 @@ _gnutls_ext_unset_session_data(gnutls_session_t session, } } -static void unset_resumed_ext_data(gnutls_session_t session, const struct extension_entry_st *ext, unsigned idx) +static void unset_resumed_ext_data(gnutls_session_t session, const struct hello_ext_entry_st *ext, unsigned idx) { if (session->internals.ext_data[idx].resumed_set == 0) return; @@ -602,7 +582,7 @@ static void unset_resumed_ext_data(gnutls_session_t session, const struct extens void _gnutls_ext_free_session_data(gnutls_session_t session) { unsigned int i; - const struct extension_entry_st *ext; + const struct hello_ext_entry_st *ext; for (i = 0; i < MAX_EXT_TYPES; i++) { if (!session->internals.ext_data[i].set && !session->internals.ext_data[i].resumed_set) @@ -624,7 +604,7 @@ _gnutls_ext_set_session_data(gnutls_session_t session, extensions_t id, gnutls_ext_priv_data_t data) { unsigned int i; - const struct extension_entry_st *ext; + const struct hello_ext_entry_st *ext; ext = _gnutls_ext_ptr(session, id, GNUTLS_EXT_ANY); @@ -713,7 +693,7 @@ gnutls_ext_register(const char *name, int id, gnutls_ext_parse_type_t parse_type gnutls_ext_deinit_data_func deinit_func, gnutls_ext_pack_func pack_func, gnutls_ext_unpack_func unpack_func) { - extension_entry_st *tmp_mod; + hello_ext_entry_st *tmp_mod; int ret; unsigned i; unsigned gid = GNUTLS_EXTENSION_MAX+1; @@ -799,8 +779,8 @@ gnutls_session_ext_register(gnutls_session_t session, gnutls_ext_deinit_data_func deinit_func, gnutls_ext_pack_func pack_func, gnutls_ext_unpack_func unpack_func, unsigned flags) { - extension_entry_st tmp_mod; - extension_entry_st *exts; + hello_ext_entry_st tmp_mod; + hello_ext_entry_st *exts; unsigned i; unsigned gid = GNUTLS_EXTENSION_MAX+1; @@ -832,7 +812,7 @@ gnutls_session_ext_register(gnutls_session_t session, if (gid > GNUTLS_EXTENSION_MAX_VALUE) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); - memset(&tmp_mod, 0, sizeof(extension_entry_st)); + memset(&tmp_mod, 0, sizeof(hello_ext_entry_st)); tmp_mod.free_struct = 1; tmp_mod.tls_id = id; tmp_mod.gid = gid; @@ -855,7 +835,7 @@ gnutls_session_ext_register(gnutls_session_t session, session->internals.rexts = exts; - memcpy(&session->internals.rexts[session->internals.rexts_size], &tmp_mod, sizeof(extension_entry_st)); + memcpy(&session->internals.rexts[session->internals.rexts_size], &tmp_mod, sizeof(hello_ext_entry_st)); session->internals.rexts_size++; return 0; diff --git a/lib/extensions.h b/lib/extensions.h index b1a47ecf36..364ec3b349 100644 --- a/lib/extensions.h +++ b/lib/extensions.h @@ -79,7 +79,7 @@ inline static const char *ext_msg_validity_to_str(gnutls_ext_flags_t msg) } } -typedef struct extension_entry_st { +typedef struct hello_ext_entry_st { const char *name; /* const overriden when free_struct is set */ unsigned free_struct; @@ -113,9 +113,9 @@ typedef struct extension_entry_st { * gnutls_init(), or modify the TLS protocol in a way that the application * cannot control. */ unsigned cannot_be_overriden; -} extension_entry_st; +} hello_ext_entry_st; -int _gnutls_ext_register(extension_entry_st *); +int _gnutls_ext_register(hello_ext_entry_st *); void _gnutls_extension_list_add_sr(gnutls_session_t session); @@ -143,7 +143,7 @@ _gnutls_extension_list_check(gnutls_session_t session, extensions_t id) */ inline static unsigned _gnutls_extension_list_add(gnutls_session_t session, - const struct extension_entry_st *e, + const struct hello_ext_entry_st *e, unsigned check_dup) { if (check_dup && _gnutls_extension_list_check(session, e->gid) == 0) { diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 50ffc14ecb..a010400a52 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -1138,7 +1138,7 @@ typedef struct { struct gnutls_supplemental_entry_st *rsup; unsigned rsup_size; - struct extension_entry_st *rexts; + struct hello_ext_entry_st *rexts; unsigned rexts_size; struct {