X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fssl_sess.c;h=69e6d7fea52e3b57cd06cc6b4204d48d8541d81a;hp=22d2e661b90039cceefdcbea76f74b6c5645742e;hb=05f0fb9f6acc34c82a082d7668572828925694e7;hpb=69f682374868ba2b19a8aeada496bf03dbb037cf diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c index 22d2e661b9..69e6d7fea5 100644 --- a/ssl/ssl_sess.c +++ b/ssl/ssl_sess.c @@ -193,12 +193,12 @@ SSL_SESSION *SSL_SESSION_new(void) { SSL_SESSION *ss; - ss = (SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION)); + ss = OPENSSL_malloc(sizeof(*ss)); if (ss == NULL) { SSLerr(SSL_F_SSL_SESSION_NEW, ERR_R_MALLOC_FAILURE); return (0); } - memset(ss, 0, sizeof(SSL_SESSION)); + memset(ss, 0, sizeof(*ss)); ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */ ss->references = 1; @@ -207,14 +207,12 @@ SSL_SESSION *SSL_SESSION_new(void) ss->prev = NULL; ss->next = NULL; ss->compress_meth = 0; -#ifndef OPENSSL_NO_TLSEXT ss->tlsext_hostname = NULL; -# ifndef OPENSSL_NO_EC +#ifndef OPENSSL_NO_EC ss->tlsext_ecpointformatlist_length = 0; ss->tlsext_ecpointformatlist = NULL; ss->tlsext_ellipticcurvelist_length = 0; ss->tlsext_ellipticcurvelist = NULL; -# endif #endif CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); #ifndef OPENSSL_NO_PSK @@ -227,6 +225,129 @@ SSL_SESSION *SSL_SESSION_new(void) return (ss); } +/* + * Create a new SSL_SESSION and duplicate the contents of |src| into it. If + * ticket == 0 then no ticket information is duplicated, otherwise it is. + */ +SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket) +{ + SSL_SESSION *dest; + + dest = OPENSSL_malloc(sizeof(*src)); + if (dest == NULL) { + goto err; + } + memcpy(dest, src, sizeof(*dest)); + + /* + * Set the various pointers to NULL so that we can call SSL_SESSION_free in + * the case of an error whilst halfway through constructing dest + */ +#ifndef OPENSSL_NO_PSK + dest->psk_identity_hint = NULL; + dest->psk_identity = NULL; +#endif + dest->ciphers = NULL; + dest->tlsext_hostname = NULL; +#ifndef OPENSSL_NO_EC + dest->tlsext_ecpointformatlist = NULL; + dest->tlsext_ellipticcurvelist = NULL; +#endif + dest->tlsext_tick = NULL; +#ifndef OPENSSL_NO_SRP + dest->srp_username = NULL; +#endif + memset(&dest->ex_data, 0, sizeof(dest->ex_data)); + + /* We deliberately don't copy the prev and next pointers */ + dest->prev = NULL; + dest->next = NULL; + + dest->references = 1; + + if (src->peer != NULL) + X509_up_ref(src->peer); + + if (src->peer_chain != NULL) { + dest->peer_chain = X509_chain_up_ref(src->peer_chain); + if (dest->peer_chain == NULL) + goto err; + } + +#ifndef OPENSSL_NO_PSK + if (src->psk_identity_hint) { + dest->psk_identity_hint = BUF_strdup(src->psk_identity_hint); + if (dest->psk_identity_hint == NULL) { + goto err; + } + } + if (src->psk_identity) { + dest->psk_identity = BUF_strdup(src->psk_identity); + if (dest->psk_identity == NULL) { + goto err; + } + } +#endif + + if(src->ciphers != NULL) { + dest->ciphers = sk_SSL_CIPHER_dup(src->ciphers); + if (dest->ciphers == NULL) + goto err; + } + + if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, + &dest->ex_data, &src->ex_data)) { + goto err; + } + + if (src->tlsext_hostname) { + dest->tlsext_hostname = BUF_strdup(src->tlsext_hostname); + if (dest->tlsext_hostname == NULL) { + goto err; + } + } +#ifndef OPENSSL_NO_EC + if (src->tlsext_ecpointformatlist) { + dest->tlsext_ecpointformatlist = + BUF_memdup(src->tlsext_ecpointformatlist, + src->tlsext_ecpointformatlist_length); + if (dest->tlsext_ecpointformatlist == NULL) + goto err; + } + if (src->tlsext_ellipticcurvelist) { + dest->tlsext_ellipticcurvelist = + BUF_memdup(src->tlsext_ellipticcurvelist, + src->tlsext_ellipticcurvelist_length); + if (dest->tlsext_ellipticcurvelist == NULL) + goto err; + } +#endif + + if (ticket != 0) { + dest->tlsext_tick = BUF_memdup(src->tlsext_tick, src->tlsext_ticklen); + if(dest->tlsext_tick == NULL) + goto err; + } else { + dest->tlsext_tick_lifetime_hint = 0; + dest->tlsext_ticklen = 0; + } + +#ifndef OPENSSL_NO_SRP + if (src->srp_username) { + dest->srp_username = BUF_strdup(src->srp_username); + if (dest->srp_username == NULL) { + goto err; + } + } +#endif + + return dest; +err: + SSLerr(SSL_F_SSL_SESSION_DUP, ERR_R_MALLOC_FAILURE); + SSL_SESSION_free(dest); + return NULL; +} + const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len) { @@ -257,7 +378,7 @@ static int def_generate_session_id(const SSL *ssl, unsigned char *id, { unsigned int retry = 0; do - if (RAND_pseudo_bytes(id, *id_len) <= 0) + if (RAND_bytes(id, *id_len) <= 0) return 0; while (SSL_has_matching_session_id(ssl, id, *id_len) && (++retry < MAX_SESS_ID_ATTEMPTS)) ; @@ -292,10 +413,8 @@ int ssl_get_new_session(SSL *s, int session) else ss->timeout = s->session_ctx->session_timeout; - if (s->session != NULL) { - SSL_SESSION_free(s->session); - s->session = NULL; - } + SSL_SESSION_free(s->session); + s->session = NULL; if (session) { if (s->version == SSL3_VERSION) { @@ -324,7 +443,7 @@ int ssl_get_new_session(SSL *s, int session) SSL_SESSION_free(ss); return (0); } -#ifndef OPENSSL_NO_TLSEXT + /*- * If RFC5077 ticket, use empty session ID (as server). * Note that: @@ -344,7 +463,7 @@ int ssl_get_new_session(SSL *s, int session) ss->session_id_length = 0; goto sess_id_done; } -#endif + /* Choose which callback will set the session ID */ CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); if (s->generate_session_id) @@ -380,7 +499,7 @@ int ssl_get_new_session(SSL *s, int session) SSL_SESSION_free(ss); return (0); } -#ifndef OPENSSL_NO_TLSEXT + sess_id_done: if (s->tlsext_hostname) { ss->tlsext_hostname = BUF_strdup(s->tlsext_hostname); @@ -390,7 +509,6 @@ int ssl_get_new_session(SSL *s, int session) return 0; } } -#endif } else { ss->session_id_length = 0; } @@ -429,27 +547,24 @@ int ssl_get_new_session(SSL *s, int session) * - Both for new and resumed sessions, s->tlsext_ticket_expected is set to 1 * if the server should issue a new session ticket (to 0 otherwise). */ -int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len, - const unsigned char *limit) +int ssl_get_prev_session(SSL *s, PACKET *pkt, unsigned char *session_id, + int len) { /* This is used only by servers. */ SSL_SESSION *ret = NULL; int fatal = 0; int try_session_cache = 1; -#ifndef OPENSSL_NO_TLSEXT int r; -#endif - if (len > SSL_MAX_SSL_SESSION_ID_LENGTH) + if (len < 0 || len > SSL_MAX_SSL_SESSION_ID_LENGTH) goto err; if (len == 0) try_session_cache = 0; -#ifndef OPENSSL_NO_TLSEXT /* sets s->tlsext_ticket_expected */ - r = tls1_process_ticket(s, session_id, len, limit, &ret); + r = tls1_process_ticket(s, pkt, session_id, len, &ret); switch (r) { case -1: /* Error during processing */ fatal = 1; @@ -464,7 +579,6 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len, default: abort(); } -#endif if (try_session_cache && ret == NULL && @@ -515,7 +629,7 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len, * The following should not return 1, otherwise, things are * very strange */ - if(SSL_CTX_add_session(s->session_ctx, ret)) + if (SSL_CTX_add_session(s->session_ctx, ret)) goto err; } } @@ -578,8 +692,7 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len, s->session_ctx->stats.sess_hit++; - if (s->session != NULL) - SSL_SESSION_free(s->session); + SSL_SESSION_free(s->session); s->session = ret; s->verify_result = s->session->verify_result; return 1; @@ -587,7 +700,7 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len, err: if (ret != NULL) { SSL_SESSION_free(ret); -#ifndef OPENSSL_NO_TLSEXT + if (!try_session_cache) { /* * The session was from a ticket, so we should issue a ticket for @@ -595,7 +708,6 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len, */ s->tlsext_ticket_expected = 1; } -#endif } if (fatal) return -1; @@ -729,38 +841,25 @@ void SSL_SESSION_free(SSL_SESSION *ss) OPENSSL_cleanse(ss->master_key, sizeof ss->master_key); OPENSSL_cleanse(ss->session_id, sizeof ss->session_id); - if (ss->sess_cert != NULL) - ssl_sess_cert_free(ss->sess_cert); - if (ss->peer != NULL) - X509_free(ss->peer); - if (ss->ciphers != NULL) - sk_SSL_CIPHER_free(ss->ciphers); -#ifndef OPENSSL_NO_TLSEXT - if (ss->tlsext_hostname != NULL) - OPENSSL_free(ss->tlsext_hostname); - if (ss->tlsext_tick != NULL) - OPENSSL_free(ss->tlsext_tick); -# ifndef OPENSSL_NO_EC + X509_free(ss->peer); + sk_X509_pop_free(ss->peer_chain, X509_free); + sk_SSL_CIPHER_free(ss->ciphers); + OPENSSL_free(ss->tlsext_hostname); + OPENSSL_free(ss->tlsext_tick); +#ifndef OPENSSL_NO_EC ss->tlsext_ecpointformatlist_length = 0; - if (ss->tlsext_ecpointformatlist != NULL) - OPENSSL_free(ss->tlsext_ecpointformatlist); + OPENSSL_free(ss->tlsext_ecpointformatlist); ss->tlsext_ellipticcurvelist_length = 0; - if (ss->tlsext_ellipticcurvelist != NULL) - OPENSSL_free(ss->tlsext_ellipticcurvelist); -# endif /* OPENSSL_NO_EC */ -#endif + OPENSSL_free(ss->tlsext_ellipticcurvelist); +#endif /* OPENSSL_NO_EC */ #ifndef OPENSSL_NO_PSK - if (ss->psk_identity_hint != NULL) - OPENSSL_free(ss->psk_identity_hint); - if (ss->psk_identity != NULL) - OPENSSL_free(ss->psk_identity); + OPENSSL_free(ss->psk_identity_hint); + OPENSSL_free(ss->psk_identity); #endif #ifndef OPENSSL_NO_SRP - if (ss->srp_username != NULL) - OPENSSL_free(ss->srp_username); + OPENSSL_free(ss->srp_username); #endif - OPENSSL_cleanse(ss, sizeof(*ss)); - OPENSSL_free(ss); + OPENSSL_clear_free(ss, sizeof(*ss)); } int SSL_set_session(SSL *s, SSL_SESSION *session) @@ -781,35 +880,17 @@ int SSL_set_session(SSL *s, SSL_SESSION *session) if (!SSL_set_ssl_method(s, meth)) return (0); } -#ifndef OPENSSL_NO_KRB5 - if (s->kssl_ctx && !s->kssl_ctx->client_princ && - session->krb5_client_princ_len > 0) { - s->kssl_ctx->client_princ = - (char *)OPENSSL_malloc(session->krb5_client_princ_len + 1); - if (s->kssl_ctx->client_princ == NULL) { - SSLerr(SSL_F_SSL_SET_SESSION, ERR_R_MALLOC_FAILURE); - return (0); - } - memcpy(s->kssl_ctx->client_princ, session->krb5_client_princ, - session->krb5_client_princ_len); - s->kssl_ctx->client_princ[session->krb5_client_princ_len] = '\0'; - } -#endif /* OPENSSL_NO_KRB5 */ /* CRYPTO_w_lock(CRYPTO_LOCK_SSL); */ CRYPTO_add(&session->references, 1, CRYPTO_LOCK_SSL_SESSION); - if (s->session != NULL) - SSL_SESSION_free(s->session); + SSL_SESSION_free(s->session); s->session = session; s->verify_result = s->session->verify_result; /* CRYPTO_w_unlock(CRYPTO_LOCK_SSL); */ ret = 1; } else { - if (s->session != NULL) { - SSL_SESSION_free(s->session); - s->session = NULL; - } - + SSL_SESSION_free(s->session); + s->session = NULL; meth = s->ctx->method; if (meth != s->method) { if (!SSL_set_ssl_method(s, meth)) @@ -864,7 +945,7 @@ void SSL_SESSION_get0_ticket(const SSL_SESSION *s, unsigned char **tick, size_t *len) { *len = s->tlsext_ticklen; - if(tick != NULL) + if (tick != NULL) *tick = s->tlsext_tick; } @@ -904,7 +985,6 @@ long SSL_CTX_get_timeout(const SSL_CTX *s) return (s->session_timeout); } -#ifndef OPENSSL_NO_TLSEXT int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb) (SSL *s, void *secret, @@ -936,11 +1016,8 @@ int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb, int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len) { if (s->version >= TLS1_VERSION) { - if (s->tlsext_session_ticket) { - OPENSSL_free(s->tlsext_session_ticket); - s->tlsext_session_ticket = NULL; - } - + OPENSSL_free(s->tlsext_session_ticket); + s->tlsext_session_ticket = NULL; s->tlsext_session_ticket = OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len); if (!s->tlsext_session_ticket) { @@ -962,7 +1039,6 @@ int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len) return 0; } -#endif /* OPENSSL_NO_TLSEXT */ typedef struct timeout_param_st { SSL_CTX *ctx;