]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
priorities: share priority structures across sessions
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Mon, 26 Jun 2017 08:02:22 +0000 (10:02 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Mon, 10 Jul 2017 07:40:17 +0000 (07:40 +0000)
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>
22 files changed:
lib/algorithms/ciphersuites.c
lib/algorithms/protocols.c
lib/auth/cert.c
lib/auth/rsa.c
lib/auth/rsa_psk.c
lib/dh-session.c
lib/ext/dumbfw.c
lib/ext/ecc.c
lib/ext/etm.c
lib/ext/ext_master_secret.c
lib/ext/safe_renegotiation.c
lib/ext/signature.c
lib/ext/srp.c
lib/gnutls_int.h
lib/handshake.c
lib/includes/gnutls/gnutls.h.in
lib/libgnutls.map
lib/priority.c
lib/record.h
lib/state.c
lib/state.h
lib/tls-sig.c

index 9ea7371dd8b930bfa5524780e42ea96c95a24998..6f5d34b0229be87a42060755fe3158116405c196 100644 (file)
@@ -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;
index b2bd675f5fd363766275964472e21effbc2fcd47..14204f0803b3a40b70049812374e28aea9729a54 100644 (file)
@@ -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))
index 87b64e68e8d3bf40ce85291ec8771dea7d7325cb..0553e794619d8b5dcaf7a0f2dc64878f8a897427 100644 (file)
@@ -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;
index 6f75bb5327b858cb4aa1e3c6d63d3b5adee3a164..a691c129e3fb73adc1cf9ab16151392845ee3153 100644 (file)
@@ -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
index 9d65529cdc7f429f0b99e1c8973c33cbe760b504..b11879655295304c11374d8bbbc269282292e9e8 100644 (file)
@@ -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
index 4d9f55cd3b6930339737e4ffddcdaaa3b3727fda..163aaa4cc58e798f0768fa9a2dafa3bdf059fef5 100644 (file)
@@ -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;
 }
 
 
index 5ccc180faa598230792f9a7d12011f7d6fbd2efb..e210f962426c05313cce2f588aa9393574ce81f6 100644 (file)
@@ -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;
index e827f4e7c12f0554394385809ed9e5ee614aaeb1..e589fbc447c5684d35128e50e08411402417a2a7 100644 (file)
@@ -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;
                }
index 1abb12092518107cef3e8f8080c974aea8da7f2d..ca6a2f91ce9d7aa61bfea2cf916645e8d6ff9519 100644 (file)
@@ -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;
index a7793f87e6a423fe0612b6e941d5d4ef061d1d1f..18de6cb1ac989df5d81588022cbeb26dd6f810b0 100644 (file)
@@ -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;
        }
index 1e0a3f80e778c740a003d91e40a01b6dafe93dcf..764309380bd24857a4360dea87811f4af43caf1a 100644 (file)
@@ -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;
        }
index 4d636420250e9098ead763dbbde2f9c7f081bcc5..765a475b1ab87db49ac2fb1890abf973d547c860 100644 (file)
@@ -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 */
                }
index 46072e2a2d31edfcc2930a9e878e76e70bbe0bb9..113f5f234fa1477017107ce2940391f5e4cfe05a 100644 (file)
@@ -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;
        }
index 1050de7ce3099622581ead65e5dcc13c201d8c21..1c8b2c613bc867341ef5f6e0df59e18a078ab9fb 100644 (file)
@@ -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 */
index 4c48fd155f604e053eabae418ca63b163049886c..15599eb93587175435de86080527479b731a9b98 100644 (file)
@@ -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;
index e2d25bcbf18ee89c9d442851946f86d34ec3968b..bc18a4a1095f9022dac4406cc854e4e1e307a64d 100644 (file)
@@ -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);
index 609410cf4141f600a68b326709505ac164a53d8f..e1152059f72192a4033c9d267d989f95696902e1 100644 (file)
@@ -1164,6 +1164,7 @@ GNUTLS_3_4
        gnutls_sign_supports_pk_algorithm;
        gnutls_privkey_sign_hash2;
        gnutls_privkey_sign_data2;
+       gnutls_priority_set2;
  local:
        *;
 };
index a41944c9c7190f3281ab35a420f75c05b3fe59dc..8fca2f194c3506f397cbb7be0e47c227e08c72ee 100644 (file)
@@ -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;
index f16df4769d24cd2eb11bb1195b34ac156b3ae1a4..6478d4253c2182545cc554b8840ef89a8c213f2f 100644 (file)
@@ -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;
index 5dfc2e2a36cc0cddbaf4f55d6ed33e267dc4e1df..15636b53cf790d48c8930b3b105b510cde0547d9 100644 (file)
@@ -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);
 }
 
 /**
index cefefad92c03899925bc4c49d452ab197b35a3b1..154ce51259eabdcc0bf8f650e8d71f578a57ba3a 100644 (file)
@@ -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);
index 87a4cf978dc63c8c0cf401bd1e761db003a6dfa8..5c1e53a21ffa0aeeddc2106169debbebb080aae3 100644 (file)
@@ -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) {