summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2017-06-26 10:02:22 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2017-07-10 07:40:17 +0000
commitfd9cc393ba5fba46c2d98c2cb8470863039e75e2 (patch)
tree9a4283e1ab1a565fb0530425fdaf363341ffe819
parent2ef812203971c17d374ccbb3464397683a2c9477 (diff)
downloadgnutls-fd9cc393ba5fba46c2d98c2cb8470863039e75e2.tar.gz
priorities: share priority structures across sessions
As the contents of the priority cache grows, it makes sense to shared these structures across many sessions (in server side) rather than copying them to a session. All overrides of the priority contents were moved to session->internals. On client side where gnutls_priority_set_direct() is more commonly used, ensure that the set priority is deinitialized. That also introduces gnutls_priority_set2() which does not copy the priority contents by default. Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
-rw-r--r--lib/algorithms/ciphersuites.c30
-rw-r--r--lib/algorithms/protocols.c12
-rw-r--r--lib/auth/cert.c2
-rw-r--r--lib/auth/rsa.c4
-rw-r--r--lib/auth/rsa_psk.c2
-rw-r--r--lib/dh-session.c2
-rw-r--r--lib/ext/dumbfw.c2
-rw-r--r--lib/ext/ecc.c14
-rw-r--r--lib/ext/etm.c6
-rw-r--r--lib/ext/ext_master_secret.c8
-rw-r--r--lib/ext/safe_renegotiation.c12
-rw-r--r--lib/ext/signature.c12
-rw-r--r--lib/ext/srp.c4
-rw-r--r--lib/gnutls_int.h48
-rw-r--r--lib/handshake.c19
-rw-r--r--lib/includes/gnutls/gnutls.h.in5
-rw-r--r--lib/libgnutls.map1
-rw-r--r--lib/priority.c73
-rw-r--r--lib/record.h4
-rw-r--r--lib/state.c11
-rw-r--r--lib/state.h6
-rw-r--r--lib/tls-sig.c4
22 files changed, 184 insertions, 97 deletions
diff --git a/lib/algorithms/ciphersuites.c b/lib/algorithms/ciphersuites.c
index 9ea7371dd8..6f5d34b022 100644
--- a/lib/algorithms/ciphersuites.c
+++ b/lib/algorithms/ciphersuites.c
@@ -1407,7 +1407,7 @@ _gnutls_figure_common_ciphersuite(gnutls_session_t session,
return NULL;
}
- if (session->internals.priorities.server_precedence == 0) {
+ if (session->internals.priorities->server_precedence == 0) {
for (i = 0; i < peer_clist->size; i++) {
_gnutls_debug_log("checking %.2x.%.2x (%s) for compatibility\n",
(unsigned)peer_clist->entry[i]->id[0],
@@ -1418,8 +1418,8 @@ _gnutls_figure_common_ciphersuite(gnutls_session_t session,
kx = peer_clist->entry[i]->kx_algorithm;
cred_type = _gnutls_map_kx_get_cred(kx, 1);
- for (j = 0; j < session->internals.priorities.cs.size; j++) {
- if (session->internals.priorities.cs.entry[j] == peer_clist->entry[i]) {
+ for (j = 0; j < session->internals.priorities->cs.size; j++) {
+ if (session->internals.priorities->cs.entry[j] == peer_clist->entry[i]) {
KX_CHECKS(kx, cred_type, continue);
if (cred_type == GNUTLS_CRD_CERTIFICATE) {
@@ -1435,8 +1435,8 @@ _gnutls_figure_common_ciphersuite(gnutls_session_t session,
}
}
} else {
- for (j = 0; j < session->internals.priorities.cs.size; j++) {
- VERSION_CHECK(session->internals.priorities.cs.entry[j]);
+ for (j = 0; j < session->internals.priorities->cs.size; j++) {
+ VERSION_CHECK(session->internals.priorities->cs.entry[j]);
for (i = 0; i < peer_clist->size; i++) {
_gnutls_debug_log("checking %.2x.%.2x (%s) for compatibility\n",
@@ -1444,7 +1444,7 @@ _gnutls_figure_common_ciphersuite(gnutls_session_t session,
(unsigned)peer_clist->entry[i]->id[1],
peer_clist->entry[i]->name);
- if (session->internals.priorities.cs.entry[j] == peer_clist->entry[i]) {
+ if (session->internals.priorities->cs.entry[j] == peer_clist->entry[i]) {
kx = peer_clist->entry[i]->kx_algorithm;
cred_type = _gnutls_map_kx_get_cred(kx, 1);
@@ -1495,10 +1495,10 @@ _gnutls_get_client_ciphersuites(gnutls_session_t session,
unsigned cipher_suites_size = 0;
size_t init_length = cdata->length;
- for (j = 0; j < session->internals.priorities.cs.size; j++) {
- CLIENT_VERSION_CHECK(vmin, vmax, session->internals.priorities.cs.entry[j]);
+ for (j = 0; j < session->internals.priorities->cs.size; j++) {
+ CLIENT_VERSION_CHECK(vmin, vmax, session->internals.priorities->cs.entry[j]);
- kx = session->internals.priorities.cs.entry[j]->kx_algorithm;
+ kx = session->internals.priorities->cs.entry[j]->kx_algorithm;
cred_type = _gnutls_map_kx_get_cred(kx, 0);
if (!session->internals.premaster_set && _gnutls_get_cred(session, cred_type) == NULL)
@@ -1507,11 +1507,11 @@ _gnutls_get_client_ciphersuites(gnutls_session_t session,
KX_SRP_CHECKS(kx, continue);
_gnutls_debug_log("Keeping ciphersuite %.2x.%.2x (%s)\n",
- (unsigned)session->internals.priorities.cs.entry[j]->id[0],
- (unsigned)session->internals.priorities.cs.entry[j]->id[1],
- session->internals.priorities.cs.entry[j]->name);
- cipher_suites[cipher_suites_size] = session->internals.priorities.cs.entry[j]->id[0];
- cipher_suites[cipher_suites_size + 1] = session->internals.priorities.cs.entry[j]->id[1];
+ (unsigned)session->internals.priorities->cs.entry[j]->id[0],
+ (unsigned)session->internals.priorities->cs.entry[j]->id[1],
+ session->internals.priorities->cs.entry[j]->name);
+ cipher_suites[cipher_suites_size] = session->internals.priorities->cs.entry[j]->id[0];
+ cipher_suites[cipher_suites_size + 1] = session->internals.priorities->cs.entry[j]->id[1];
cipher_suites_size += 2;
if (cipher_suites_size >= MAX_CIPHERSUITE_SIZE*2)
@@ -1531,7 +1531,7 @@ _gnutls_get_client_ciphersuites(gnutls_session_t session,
}
#endif
- if (session->internals.priorities.fallback) {
+ if (session->internals.priorities->fallback) {
cipher_suites[cipher_suites_size] = GNUTLS_FALLBACK_SCSV_MAJOR;
cipher_suites[cipher_suites_size + 1] = GNUTLS_FALLBACK_SCSV_MINOR;
cipher_suites_size += 2;
diff --git a/lib/algorithms/protocols.c b/lib/algorithms/protocols.c
index b2bd675f5f..14204f0803 100644
--- a/lib/algorithms/protocols.c
+++ b/lib/algorithms/protocols.c
@@ -158,9 +158,9 @@ _gnutls_version_priority(gnutls_session_t session,
{
unsigned int i;
- for (i = 0; i < session->internals.priorities.protocol.algorithms;
+ for (i = 0; i < session->internals.priorities->protocol.algorithms;
i++) {
- if (session->internals.priorities.protocol.priority[i] ==
+ if (session->internals.priorities->protocol.priority[i] ==
version)
return i;
}
@@ -176,9 +176,9 @@ const version_entry_st *_gnutls_version_lowest(gnutls_session_t session)
const version_entry_st *v, *min_v = NULL;
const version_entry_st *backup = NULL;
- for (i=0;i < session->internals.priorities.protocol.algorithms;i++) {
+ for (i=0;i < session->internals.priorities->protocol.algorithms;i++) {
cur_prot =
- session->internals.priorities.protocol.priority[i];
+ session->internals.priorities->protocol.priority[i];
v = version_to_entry(cur_prot);
if (v != NULL && version_is_valid_for_session(session, v)) {
@@ -216,10 +216,10 @@ gnutls_protocol_t _gnutls_version_max(gnutls_session_t session)
unsigned int i, max = 0x00;
gnutls_protocol_t cur_prot;
- for (i = 0; i < session->internals.priorities.protocol.algorithms;
+ for (i = 0; i < session->internals.priorities->protocol.algorithms;
i++) {
cur_prot =
- session->internals.priorities.protocol.priority[i];
+ session->internals.priorities->protocol.priority[i];
if (cur_prot > max
&& _gnutls_version_is_supported(session, cur_prot))
diff --git a/lib/auth/cert.c b/lib/auth/cert.c
index 87b64e68e8..0553e79461 100644
--- a/lib/auth/cert.c
+++ b/lib/auth/cert.c
@@ -1423,7 +1423,7 @@ unsigned pubkey_is_compat_with_cs(gnutls_session_t session,
return 0;
}
- if (unlikely(session->internals.priorities.allow_server_key_usage_violation)) {
+ if (unlikely(session->internals.priorities->allow_server_key_usage_violation)) {
key_usage = 0;
} else {
key_usage = pubkey->key_usage;
diff --git a/lib/auth/rsa.c b/lib/auth/rsa.c
index 6f75bb5327..a691c129e3 100644
--- a/lib/auth/rsa.c
+++ b/lib/auth/rsa.c
@@ -68,7 +68,7 @@ int check_key_usage_for_enc(gnutls_session_t session, unsigned key_usage)
if (key_usage != 0) {
if (!(key_usage & GNUTLS_KEY_KEY_ENCIPHERMENT) && !(key_usage & GNUTLS_KEY_KEY_AGREEMENT)) {
gnutls_assert();
- if (session->internals.priorities.allow_key_usage_violation == 0) {
+ if (session->internals.allow_key_usage_violation == 0) {
_gnutls_audit_log(session,
"Peer's certificate does not allow encryption. Key usage violation detected.\n");
return GNUTLS_E_KEY_USAGE_VIOLATION;
@@ -206,7 +206,7 @@ proc_rsa_client_kx(gnutls_session_t session, uint8_t * data,
*/
if (_gnutls_get_adv_version_major(session) !=
plaintext.data[0]
- || (session->internals.priorities.allow_wrong_pms == 0
+ || (session->internals.allow_wrong_pms == 0
&& _gnutls_get_adv_version_minor(session) !=
plaintext.data[1])) {
/* No error is returned here, if the version number check
diff --git a/lib/auth/rsa_psk.c b/lib/auth/rsa_psk.c
index 9d65529cdc..b118796552 100644
--- a/lib/auth/rsa_psk.c
+++ b/lib/auth/rsa_psk.c
@@ -343,7 +343,7 @@ _gnutls_proc_rsa_psk_client_kx(gnutls_session_t session, uint8_t * data,
*/
if (_gnutls_get_adv_version_major(session) !=
plaintext.data[0]
- || (session->internals.priorities.allow_wrong_pms == 0
+ || (session->internals.allow_wrong_pms == 0
&& _gnutls_get_adv_version_minor(session) !=
plaintext.data[1])) {
/* No error is returned here, if the version number check
diff --git a/lib/dh-session.c b/lib/dh-session.c
index 4d9f55cd3b..163aaa4cc5 100644
--- a/lib/dh-session.c
+++ b/lib/dh-session.c
@@ -72,7 +72,7 @@ void gnutls_dh_set_prime_bits(gnutls_session_t session, unsigned int bits)
_gnutls_audit_log(session,
"Note that the security level of the Diffie-Hellman key exchange has been lowered to %u bits and this may allow decryption of the session data\n",
bits);
- session->internals.priorities.dh_prime_bits = bits;
+ session->internals.dh_prime_bits = bits;
}
diff --git a/lib/ext/dumbfw.c b/lib/ext/dumbfw.c
index 5ccc180faa..e210f96242 100644
--- a/lib/ext/dumbfw.c
+++ b/lib/ext/dumbfw.c
@@ -57,7 +57,7 @@ _gnutls_dumbfw_send_params(gnutls_session_t session,
unsigned pad_size;
if (session->security_parameters.entity == GNUTLS_SERVER ||
- session->internals.priorities.dumbfw == 0 ||
+ session->internals.dumbfw == 0 ||
IS_DTLS(session) != 0 ||
(extdata->length < 256 || extdata->length >= 512)) {
return 0;
diff --git a/lib/ext/ecc.c b/lib/ext/ecc.c
index e827f4e7c1..e589fbc447 100644
--- a/lib/ext/ecc.c
+++ b/lib/ext/ecc.c
@@ -162,11 +162,11 @@ _gnutls_supported_ecc_send_params(gnutls_session_t session,
/* this extension is only being sent on client side */
if (session->security_parameters.entity == GNUTLS_CLIENT) {
- if (session->internals.priorities.supported_ecc.
+ if (session->internals.priorities->supported_ecc.
algorithms > 0) {
len =
- session->internals.priorities.supported_ecc.
+ session->internals.priorities->supported_ecc.
algorithms;
/* this is a vector!
@@ -180,7 +180,7 @@ _gnutls_supported_ecc_send_params(gnutls_session_t session,
for (i = 0; i < len; i++) {
p = _gnutls_ecc_curve_get_tls_id(session->
internals.
- priorities.supported_ecc.
+ priorities->supported_ecc.
priority
[i]);
ret =
@@ -264,7 +264,7 @@ _gnutls_supported_ecc_pf_send_params(gnutls_session_t session,
&& !_gnutls_session_is_ecc(session))
return 0;
- if (session->internals.priorities.supported_ecc.algorithms > 0) {
+ if (session->internals.priorities->supported_ecc.algorithms > 0) {
ret = _gnutls_buffer_append_data(extdata, p, 2);
if (ret < 0)
return gnutls_assert_val(ret);
@@ -284,12 +284,12 @@ _gnutls_session_supports_ecc_curve(gnutls_session_t session,
{
unsigned i;
- if (session->internals.priorities.supported_ecc.algorithms > 0) {
+ if (session->internals.priorities->supported_ecc.algorithms > 0) {
for (i = 0;
i <
- session->internals.priorities.supported_ecc.
+ session->internals.priorities->supported_ecc.
algorithms; i++) {
- if (session->internals.priorities.supported_ecc.
+ if (session->internals.priorities->supported_ecc.
priority[i] == ecc_type)
return 0;
}
diff --git a/lib/ext/etm.c b/lib/ext/etm.c
index 1abb120925..ca6a2f91ce 100644
--- a/lib/ext/etm.c
+++ b/lib/ext/etm.c
@@ -66,7 +66,7 @@ _gnutls_ext_etm_recv_params(gnutls_session_t session,
if (session->security_parameters.entity == GNUTLS_SERVER) {
gnutls_ext_priv_data_t epriv;
- if (session->internals.priorities.no_etm != 0)
+ if (session->internals.no_etm != 0)
return 0;
epriv = (void*)(intptr_t)1;
@@ -99,12 +99,12 @@ static int
_gnutls_ext_etm_send_params(gnutls_session_t session,
gnutls_buffer_st * extdata)
{
- if (session->internals.priorities.no_etm != 0)
+ if (session->internals.no_etm != 0)
return 0;
/* this function sends the client extension data */
if (session->security_parameters.entity == GNUTLS_CLIENT) {
- if (session->internals.priorities.have_cbc != 0)
+ if (session->internals.priorities->have_cbc != 0)
return GNUTLS_E_INT_RET_0;
else
return 0;
diff --git a/lib/ext/ext_master_secret.c b/lib/ext/ext_master_secret.c
index a7793f87e6..18de6cb1ac 100644
--- a/lib/ext/ext_master_secret.c
+++ b/lib/ext/ext_master_secret.c
@@ -51,8 +51,8 @@ const extension_entry_st ext_mod_ext_master_secret = {
#ifdef ENABLE_SSL3
static inline unsigned have_only_ssl3_enabled(gnutls_session_t session)
{
- if (session->internals.priorities.protocol.algorithms == 1 &&
- session->internals.priorities.protocol.priority[0] == GNUTLS_SSL3)
+ if (session->internals.priorities->protocol.algorithms == 1 &&
+ session->internals.priorities->protocol.priority[0] == GNUTLS_SSL3)
return 1;
return 0;
}
@@ -70,7 +70,7 @@ _gnutls_ext_master_secret_recv_params(gnutls_session_t session,
ssize_t data_size = _data_size;
if ((session->internals.flags & GNUTLS_NO_EXTENSIONS) ||
- session->internals.priorities.no_ext_master_secret != 0) {
+ session->internals.no_ext_master_secret != 0) {
return 0;
}
@@ -102,7 +102,7 @@ _gnutls_ext_master_secret_send_params(gnutls_session_t session,
gnutls_buffer_st * extdata)
{
if ((session->internals.flags & GNUTLS_NO_EXTENSIONS) ||
- session->internals.priorities.no_ext_master_secret != 0) {
+ session->internals.no_ext_master_secret != 0) {
session->security_parameters.ext_master_secret = 0;
return 0;
}
diff --git a/lib/ext/safe_renegotiation.c b/lib/ext/safe_renegotiation.c
index 1e0a3f80e7..764309380b 100644
--- a/lib/ext/safe_renegotiation.c
+++ b/lib/ext/safe_renegotiation.c
@@ -52,7 +52,7 @@ _gnutls_ext_sr_finished(gnutls_session_t session, void *vdata,
sr_ext_st *priv;
gnutls_ext_priv_data_t epriv;
- if (session->internals.priorities.sr == SR_DISABLED) {
+ if (session->internals.priorities->sr == SR_DISABLED) {
return 0;
}
@@ -96,7 +96,7 @@ int _gnutls_ext_sr_verify(gnutls_session_t session)
sr_ext_st *priv = NULL;
gnutls_ext_priv_data_t epriv;
- if (session->internals.priorities.sr == SR_DISABLED) {
+ if (session->internals.priorities->sr == SR_DISABLED) {
gnutls_assert();
return 0;
}
@@ -163,7 +163,7 @@ int _gnutls_ext_sr_verify(gnutls_session_t session)
/* Clients can't tell if it's an initial negotiation */
if (session->internals.initial_negotiation_completed) {
- if (session->internals.priorities.sr < SR_PARTIAL) {
+ if (session->internals.priorities->sr < SR_PARTIAL) {
_gnutls_handshake_log
("HSK[%p]: Allowing unsafe (re)negotiation\n",
session);
@@ -176,7 +176,7 @@ int _gnutls_ext_sr_verify(gnutls_session_t session)
GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED;
}
} else {
- if (session->internals.priorities.sr < SR_SAFE) {
+ if (session->internals.priorities->sr < SR_SAFE) {
_gnutls_handshake_log
("HSK[%p]: Allowing unsafe initial negotiation\n",
session);
@@ -277,7 +277,7 @@ _gnutls_sr_recv_params(gnutls_session_t session,
DECR_LEN(data_size,
len + 1 /* count the first byte and payload */ );
- if (session->internals.priorities.sr == SR_DISABLED) {
+ if (session->internals.priorities->sr == SR_DISABLED) {
gnutls_assert();
return 0;
}
@@ -350,7 +350,7 @@ _gnutls_sr_send_params(gnutls_session_t session,
gnutls_ext_priv_data_t epriv;
size_t init_length = extdata->length;
- if (session->internals.priorities.sr == SR_DISABLED) {
+ if (session->internals.priorities->sr == SR_DISABLED) {
gnutls_assert();
return 0;
}
diff --git a/lib/ext/signature.c b/lib/ext/signature.c
index 4d63642025..765a475b1a 100644
--- a/lib/ext/signature.c
+++ b/lib/ext/signature.c
@@ -83,8 +83,8 @@ _gnutls_sign_algorithm_write_params(gnutls_session_t session,
p = buffer;
len = 0;
- for (i=0;i<session->internals.priorities.sigalg.size;i++) {
- aid = &session->internals.priorities.sigalg.entry[i]->aid;
+ for (i=0;i<session->internals.priorities->sigalg.size;i++) {
+ aid = &session->internals.priorities->sigalg.entry[i]->aid;
if (HAVE_UNKNOWN_SIGAID(aid))
continue;
@@ -92,7 +92,7 @@ _gnutls_sign_algorithm_write_params(gnutls_session_t session,
_gnutls_handshake_log
("EXT[%p]: sent signature algo (%d.%d) %s\n", session,
(int)aid->id[0], (int)aid->id[1],
- session->internals.priorities.sigalg.entry[i]->name);
+ session->internals.priorities->sigalg.entry[i]->name);
len += 2;
if (unlikely(len >= sizeof(buffer))) {
@@ -231,7 +231,7 @@ _gnutls_signature_algorithm_send_params(gnutls_session_t session,
/* this function sends the client extension data */
if (session->security_parameters.entity == GNUTLS_CLIENT
&& _gnutls_version_has_selectable_sighash(ver)) {
- if (session->internals.priorities.sigalg.size > 0) {
+ if (session->internals.priorities->sigalg.size > 0) {
ret =
_gnutls_sign_algorithm_write_params(session, extdata);
if (ret < 0)
@@ -321,9 +321,9 @@ _gnutls_session_sign_algo_enabled(gnutls_session_t session,
return 0;
}
- for (i = 0; i < session->internals.priorities.sigalg.size;
+ for (i = 0; i < session->internals.priorities->sigalg.size;
i++) {
- if (session->internals.priorities.sigalg.entry[i]->id ==
+ if (session->internals.priorities->sigalg.entry[i]->id ==
sig) {
return 0; /* ok */
}
diff --git a/lib/ext/srp.c b/lib/ext/srp.c
index 46072e2a2d..113f5f234f 100644
--- a/lib/ext/srp.c
+++ b/lib/ext/srp.c
@@ -104,8 +104,8 @@ static unsigned have_srp_ciphersuites(gnutls_session_t session)
unsigned j;
unsigned kx;
- for (j = 0; j < session->internals.priorities.cs.size; j++) {
- kx = session->internals.priorities.cs.entry[j]->kx_algorithm;
+ for (j = 0; j < session->internals.priorities->cs.size; j++) {
+ kx = session->internals.priorities->cs.entry[j]->kx_algorithm;
if (kx == GNUTLS_KX_SRP || kx == GNUTLS_KX_SRP_RSA || kx == GNUTLS_KX_SRP_DSS)
return 1;
}
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 1050de7ce3..1c8b2c613b 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -674,29 +674,35 @@ struct gnutls_priority_st {
/* to disable record padding */
bool no_extensions;
- bool no_ext_master_secret;
- bool allow_large_records;
- unsigned int dumbfw;
+
+
safe_renegotiation_t sr;
bool min_record_version;
bool server_precedence;
- bool allow_key_usage_violation;
bool allow_server_key_usage_violation; /* for test suite purposes only */
- bool allow_wrong_pms;
bool no_tickets;
- bool no_etm;
bool have_cbc;
unsigned int additional_verify_flags;
+ /* TLS_FALLBACK_SCSV */
+ bool fallback;
+
/* The session's expected security level.
* Will be used to determine the minimum DH bits,
* (or the acceptable certificate security level).
*/
gnutls_sec_param_t level;
- unsigned int dh_prime_bits; /* old (deprecated) variable */
- /* TLS_FALLBACK_SCSV */
- bool fallback;
+ /* these should be accessed from
+ * session->internals.VAR names */
+ bool _allow_large_records;
+ bool _no_etm;
+ bool _no_ext_master_secret;
+ bool _allow_key_usage_violation;
+ bool _allow_wrong_pms;
+ bool _dumbfw;
+ unsigned int _dh_prime_bits; /* old (deprecated) variable */
+
};
/* Allow around 50KB of length-hiding padding
@@ -712,6 +718,14 @@ struct gnutls_priority_st {
(x)->allow_wrong_pms = 1; \
(x)->dumbfw = 1
+#define ENABLE_PRIO_COMPAT(x) \
+ (x)->_allow_large_records = 1; \
+ (x)->_no_etm = 1; \
+ (x)->_no_ext_master_secret = 1; \
+ (x)->_allow_key_usage_violation = 1; \
+ (x)->_allow_wrong_pms = 1; \
+ (x)->_dumbfw = 1
+
/* DH and RSA parameters types.
*/
typedef struct gnutls_dh_params_int {
@@ -808,7 +822,21 @@ typedef struct {
int last_handshake_out;
/* priorities */
- struct gnutls_priority_st priorities;
+ struct gnutls_priority_st *priorities;
+ /* non-zero if the priorities are assigned only to this session (and
+ * thus should be freed by it */
+ bool deinit_priorities;
+
+ /* variables directly set when setting the priorities above, or
+ * when overriding them */
+ bool allow_large_records;
+ bool no_etm;
+ bool no_ext_master_secret;
+ bool allow_key_usage_violation;
+ bool allow_wrong_pms;
+ bool dumbfw;
+ unsigned int dh_prime_bits; /* old (deprecated) variable */
+
/* resumed session */
bool resumed; /* RESUME_TRUE or FALSE - if we are resuming a session */
diff --git a/lib/handshake.c b/lib/handshake.c
index 4c48fd155f..15599eb935 100644
--- a/lib/handshake.c
+++ b/lib/handshake.c
@@ -842,7 +842,7 @@ _gnutls_server_select_suite(gnutls_session_t session, uint8_t * data,
for (i = 0; i < datalen; i += 2) {
#ifdef ENABLE_SSL3 /* No need to support certain SCSV's without SSL 3.0 */
/* TLS_RENEGO_PROTECTION_REQUEST = { 0x00, 0xff } */
- if (session->internals.priorities.sr != SR_DISABLED &&
+ if (session->internals.priorities->sr != SR_DISABLED &&
data[i] == GNUTLS_RENEGO_PROTECTION_REQUEST_MAJOR &&
data[i + 1] == GNUTLS_RENEGO_PROTECTION_REQUEST_MINOR) {
_gnutls_handshake_log
@@ -1341,10 +1341,10 @@ set_client_ciphersuite(gnutls_session_t session, uint8_t suite[2])
int ret;
const gnutls_cipher_suite_entry_st *selected = NULL;
- for (j = 0; j < session->internals.priorities.cs.size; j++) {
- if (suite[0] == session->internals.priorities.cs.entry[j]->id[0] &&
- suite[1] == session->internals.priorities.cs.entry[j]->id[1]) {
- selected = session->internals.priorities.cs.entry[j];
+ for (j = 0; j < session->internals.priorities->cs.size; j++) {
+ if (suite[0] == session->internals.priorities->cs.entry[j]->id[0] &&
+ suite[1] == session->internals.priorities->cs.entry[j]->id[1]) {
+ selected = session->internals.priorities->cs.entry[j];
break;
}
}
@@ -1661,7 +1661,7 @@ static int send_client_hello(gnutls_session_t session, int again)
if (_gnutls_set_current_version(session, hver->id) < 0)
return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
- if (session->internals.priorities.min_record_version != 0) {
+ if (session->internals.priorities->min_record_version != 0) {
/* Advertize the lowest supported (SSL 3.0) record packet
* version in record packets during the handshake.
* That is to avoid confusing implementations
@@ -1726,7 +1726,7 @@ static int send_client_hello(gnutls_session_t session, int again)
if (!session->internals.initial_negotiation_completed &&
session->security_parameters.entity == GNUTLS_CLIENT &&
(hver->id == GNUTLS_SSL3 &&
- session->internals.priorities.no_extensions != 0)) {
+ session->internals.priorities->no_extensions != 0)) {
add_sr_scsv = 1;
}
#endif
@@ -1746,7 +1746,7 @@ static int send_client_hello(gnutls_session_t session, int again)
/* Generate and copy TLS extensions.
*/
- if (session->internals.priorities.no_extensions == 0) {
+ if (session->internals.priorities->no_extensions == 0) {
if (_gnutls_version_has_extensions(hver)) {
type = GNUTLS_EXT_ANY;
} else {
@@ -2186,7 +2186,8 @@ int gnutls_handshake(gnutls_session_t session)
if (STATE == STATE0) {
/* first call */
- if (session->internals.priorities.protocol.algorithms == 0)
+ if (session->internals.priorities == NULL ||
+ session->internals.priorities->cs.size == 0)
return gnutls_assert_val(GNUTLS_E_NO_PRIORITIES_WERE_SET);
session->internals.used_exts_size = 0;
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index e2d25bcbf1..bc18a4a109 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -1355,6 +1355,11 @@ gnutls_priority_string_list(unsigned iter, unsigned int flags);
int gnutls_priority_set(gnutls_session_t session,
gnutls_priority_t priority);
+
+#define GNUTLS_PRIORITY_FLAG_COPY 1
+int gnutls_priority_set2(gnutls_session_t session,
+ gnutls_priority_t priority,
+ unsigned int flags);
int gnutls_priority_set_direct(gnutls_session_t session,
const char *priorities,
const char **err_pos);
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index 609410cf41..e1152059f7 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -1164,6 +1164,7 @@ GNUTLS_3_4
gnutls_sign_supports_pk_algorithm;
gnutls_privkey_sign_hash2;
gnutls_privkey_sign_data2;
+ gnutls_priority_set2;
local:
*;
};
diff --git a/lib/priority.c b/lib/priority.c
index a41944c9c7..8fca2f194c 100644
--- a/lib/priority.c
+++ b/lib/priority.c
@@ -533,25 +533,64 @@ static void prio_add(priority_st * priority_list, unsigned int algo)
* Sets the priorities to use on the ciphers, key exchange methods,
* and macs.
*
+ * This is identical to calling gnutls_priority_set2() with
+ * %GNUTLS_PRIORITY_FLAG_COPY.
+ *
* Returns: %GNUTLS_E_SUCCESS on success, or an error code.
**/
int
gnutls_priority_set(gnutls_session_t session, gnutls_priority_t priority)
{
+ return gnutls_priority_set2(session, priority, GNUTLS_PRIORITY_FLAG_COPY);
+}
+
+/**
+ * gnutls_priority_set2:
+ * @session: is a #gnutls_session_t type.
+ * @priority: is a #gnutls_priority_t type.
+ * @flags: zero or %GNUTLS_PRIORITY_FLAG_COPY
+ *
+ * Sets the priorities to use on the ciphers, key exchange methods,
+ * and macs.
+ *
+ * Unless %GNUTLS_PRIORITY_FLAG_COPY is specified, the @priority reference
+ * must remain valid for the lifetime of the session.
+ *
+ * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
+ **/
+int
+gnutls_priority_set2(gnutls_session_t session, gnutls_priority_t priority, unsigned int flags)
+{
if (priority == NULL) {
gnutls_assert();
return GNUTLS_E_NO_CIPHER_SUITES;
}
- memcpy(&session->internals.priorities, priority,
- sizeof(struct gnutls_priority_st));
+ if (session->internals.deinit_priorities &&
+ session->internals.priorities)
+ gnutls_priority_deinit(session->internals.priorities);
+
+ if (flags & GNUTLS_PRIORITY_FLAG_COPY) {
+ session->internals.priorities = gnutls_malloc(sizeof(*session->internals.priorities));
+ if (session->internals.priorities == NULL)
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+
+ /* it is fine to use memcpy() here since we are only storing
+ * values and pointers to constant static data. */
+ memcpy(session->internals.priorities, priority, sizeof(*priority));
+
+ session->internals.deinit_priorities = 1;
+ } else {
+ session->internals.priorities = priority;
+ session->internals.deinit_priorities = 0;
+ }
/* set the current version to the first in the chain.
* This will be overridden later.
*/
- if (session->internals.priorities.protocol.algorithms > 0) {
+ if (session->internals.priorities->protocol.algorithms > 0) {
if (_gnutls_set_current_version(session,
- session->internals.priorities.
+ session->internals.priorities->
protocol.priority[0]) < 0) {
return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
}
@@ -562,12 +601,23 @@ gnutls_priority_set(gnutls_session_t session, gnutls_priority_t priority)
_gnutls_ext_unset_session_data(session, GNUTLS_EXTENSION_SESSION_TICKET);
}
- if (session->internals.priorities.protocol.algorithms == 0 ||
- session->internals.priorities.cs.size == 0)
+ if (session->internals.priorities->protocol.algorithms == 0 ||
+ session->internals.priorities->cs.size == 0)
return gnutls_assert_val(GNUTLS_E_NO_PRIORITIES_WERE_SET);
ADD_PROFILE_VFLAGS(session, priority->additional_verify_flags);
+ /* mirror variables */
+#undef COPY_TO_INTERNALS
+#define COPY_TO_INTERNALS(xx) session->internals.xx = priority->_##xx
+ COPY_TO_INTERNALS(allow_large_records);
+ COPY_TO_INTERNALS(no_etm);
+ COPY_TO_INTERNALS(no_ext_master_secret);
+ COPY_TO_INTERNALS(allow_key_usage_violation);
+ COPY_TO_INTERNALS(allow_wrong_pms);
+ COPY_TO_INTERNALS(dumbfw);
+ COPY_TO_INTERNALS(dh_prime_bits);
+
return 0;
}
@@ -744,7 +794,7 @@ int check_level(const char *level, gnutls_priority_t priority_cache,
static void enable_compat(gnutls_priority_t c)
{
- ENABLE_COMPAT(c);
+ ENABLE_PRIO_COMPAT(c);
}
static void enable_server_key_usage_violations(gnutls_priority_t c)
{
@@ -752,7 +802,7 @@ static void enable_server_key_usage_violations(gnutls_priority_t c)
}
static void enable_dumbfw(gnutls_priority_t c)
{
- c->dumbfw = 1;
+ c->_dumbfw = 1;
}
static void enable_no_extensions(gnutls_priority_t c)
{
@@ -760,11 +810,11 @@ static void enable_no_extensions(gnutls_priority_t c)
}
static void enable_no_ext_master_secret(gnutls_priority_t c)
{
- c->no_ext_master_secret = 1;
+ c->_no_ext_master_secret = 1;
}
static void enable_no_etm(gnutls_priority_t c)
{
- c->no_etm = 1;
+ c->_no_etm = 1;
}
static void enable_no_tickets(gnutls_priority_t c)
{
@@ -1501,6 +1551,9 @@ gnutls_priority_set_direct(gnutls_session_t session,
return ret;
}
+ /* ensure this priority is deinitialized with the session */
+ session->internals.deinit_priorities = 1;
+
gnutls_priority_deinit(prio);
return 0;
diff --git a/lib/record.h b/lib/record.h
index f16df4769d..6478d4253c 100644
--- a/lib/record.h
+++ b/lib/record.h
@@ -54,7 +54,7 @@ inline static unsigned max_record_recv_size(gnutls_session_t session)
size = MAX_CIPHER_BLOCK_SIZE /*iv*/ + MAX_PAD_SIZE + MAX_HASH_SIZE/*MAC*/;
- if (gnutls_compression_get(session)!=GNUTLS_COMP_NULL || session->internals.priorities.allow_large_records != 0)
+ if (gnutls_compression_get(session)!=GNUTLS_COMP_NULL || session->internals.allow_large_records != 0)
size += EXTRA_COMP_SIZE;
size += session->security_parameters.max_record_recv_size + RECORD_HEADER_SIZE(session);
@@ -66,7 +66,7 @@ inline static unsigned max_decrypted_size(gnutls_session_t session)
{
unsigned size = 0;
- if (session->internals.priorities.allow_large_records != 0)
+ if (session->internals.allow_large_records != 0)
size += EXTRA_COMP_SIZE;
size += session->security_parameters.max_record_recv_size;
diff --git a/lib/state.c b/lib/state.c
index 5dfc2e2a36..15636b53cf 100644
--- a/lib/state.c
+++ b/lib/state.c
@@ -330,11 +330,6 @@ int gnutls_init(gnutls_session_t * session, unsigned int flags)
handshake_internal_state_clear1(*session);
- /* emulate old gnutls behavior for old applications that do not use the priority_*
- * functions.
- */
- (*session)->internals.priorities.sr = SR_PARTIAL;
-
#ifdef HAVE_WRITEV
#ifdef MSG_NOSIGNAL
if (flags & GNUTLS_NO_SIGNAL)
@@ -434,6 +429,10 @@ void gnutls_deinit(gnutls_session_t session)
gnutls_credentials_clear(session);
_gnutls_selected_certs_deinit(session);
+ if (session->internals.deinit_priorities &&
+ session->internals.priorities)
+ gnutls_priority_deinit(session->internals.priorities);
+
gnutls_free(session);
}
@@ -924,7 +923,7 @@ gnutls_handshake_set_post_client_hello_function(gnutls_session_t session,
**/
void gnutls_session_enable_compatibility_mode(gnutls_session_t session)
{
- ENABLE_COMPAT(&session->internals.priorities);
+ ENABLE_COMPAT(&session->internals);
}
/**
diff --git a/lib/state.h b/lib/state.h
index cefefad92c..154ce51259 100644
--- a/lib/state.h
+++ b/lib/state.h
@@ -64,12 +64,12 @@ int _gnutls_dh_set_group(gnutls_session_t session, bigint_t gen,
static inline int _gnutls_dh_get_min_prime_bits(gnutls_session_t session)
{
- if (session->internals.priorities.dh_prime_bits != 0)
- return session->internals.priorities.dh_prime_bits;
+ if (session->internals.dh_prime_bits != 0)
+ return session->internals.dh_prime_bits;
else
return gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH,
session->internals.
- priorities.level);
+ priorities->level);
}
void _gnutls_handshake_internal_state_clear(gnutls_session_t);
diff --git a/lib/tls-sig.c b/lib/tls-sig.c
index 87a4cf978d..5c1e53a21f 100644
--- a/lib/tls-sig.c
+++ b/lib/tls-sig.c
@@ -47,10 +47,10 @@ int check_key_usage_for_sig(gnutls_session_t session, unsigned key_usage, unsign
if (our_cert) {
lstr = "Local";
- allow_key_usage_violation = session->internals.priorities.allow_server_key_usage_violation;
+ allow_key_usage_violation = session->internals.priorities->allow_server_key_usage_violation;
} else {
lstr = "Peer's";
- allow_key_usage_violation = session->internals.priorities.allow_key_usage_violation;
+ allow_key_usage_violation = session->internals.allow_key_usage_violation;
}
if (key_usage != 0) {