blob: 2c5dfe695794cb10524fb59dd4e8d5129d08280b [file] [log] [blame]
Adam Langley95c29f32014-06-20 12:00:00 -07001/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2 * All rights reserved.
3 *
4 * This package is an SSL implementation written
5 * by Eric Young (eay@cryptsoft.com).
6 * The implementation was written so as to conform with Netscapes SSL.
7 *
8 * This library is free for commercial and non-commercial use as long as
9 * the following conditions are aheared to. The following conditions
10 * apply to all code found in this distribution, be it the RC4, RSA,
11 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
12 * included with this distribution is covered by the same copyright terms
13 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14 *
15 * Copyright remains Eric Young's, and as such any Copyright notices in
16 * the code are not to be removed.
17 * If this package is used in a product, Eric Young should be given attribution
18 * as the author of the parts of the library used.
19 * This can be in the form of a textual message at program startup or
20 * in documentation (online or textual) provided with the package.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
24 * are met:
25 * 1. Redistributions of source code must retain the copyright
26 * notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following disclaimer in the
29 * documentation and/or other materials provided with the distribution.
30 * 3. All advertising materials mentioning features or use of this software
31 * must display the following acknowledgement:
32 * "This product includes cryptographic software written by
33 * Eric Young (eay@cryptsoft.com)"
34 * The word 'cryptographic' can be left out if the rouines from the library
35 * being used are not cryptographic related :-).
36 * 4. If you include any Windows specific code (or a derivative thereof) from
37 * the apps directory (application code) you must include an acknowledgement:
38 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 * SUCH DAMAGE.
51 *
52 * The licence and distribution terms for any publically available version or
53 * derivative of this code cannot be changed. i.e. this code cannot simply be
54 * copied and put under another distribution licence
55 * [including the GNU Public Licence.]
56 */
57/* ====================================================================
58 * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved.
59 *
60 * Redistribution and use in source and binary forms, with or without
61 * modification, are permitted provided that the following conditions
62 * are met:
63 *
64 * 1. Redistributions of source code must retain the above copyright
65 * notice, this list of conditions and the following disclaimer.
66 *
67 * 2. Redistributions in binary form must reproduce the above copyright
68 * notice, this list of conditions and the following disclaimer in
69 * the documentation and/or other materials provided with the
70 * distribution.
71 *
72 * 3. All advertising materials mentioning features or use of this
73 * software must display the following acknowledgment:
74 * "This product includes software developed by the OpenSSL Project
75 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
76 *
77 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
78 * endorse or promote products derived from this software without
79 * prior written permission. For written permission, please contact
80 * openssl-core@openssl.org.
81 *
82 * 5. Products derived from this software may not be called "OpenSSL"
83 * nor may "OpenSSL" appear in their names without prior written
84 * permission of the OpenSSL Project.
85 *
86 * 6. Redistributions of any form whatsoever must retain the following
87 * acknowledgment:
88 * "This product includes software developed by the OpenSSL Project
89 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
90 *
91 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
92 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
93 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
94 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
95 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
96 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
97 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
98 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
99 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
100 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
101 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
102 * OF THE POSSIBILITY OF SUCH DAMAGE.
103 * ====================================================================
104 *
105 * This product includes cryptographic software written by Eric Young
106 * (eay@cryptsoft.com). This product includes software written by Tim
107 * Hudson (tjh@cryptsoft.com).
108 *
109 */
110/* ====================================================================
111 * Copyright 2005 Nokia. All rights reserved.
112 *
113 * The portions of the attached software ("Contribution") is developed by
114 * Nokia Corporation and is licensed pursuant to the OpenSSL open source
115 * license.
116 *
117 * The Contribution, originally written by Mika Kousa and Pasi Eronen of
118 * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
119 * support (see RFC 4279) to OpenSSL.
120 *
121 * No patent licenses or other rights except those expressly stated in
122 * the OpenSSL open source license shall be deemed granted or received
123 * expressly, by implication, estoppel, or otherwise.
124 *
125 * No assurances are provided by Nokia that the Contribution does not
126 * infringe the patent or other intellectual property rights of any third
127 * party or that the license provides you with all the necessary rights
128 * to make use of the Contribution.
129 *
130 * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
131 * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
132 * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
133 * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
134 * OTHERWISE. */
135
David Benjamine3aa1d92015-06-16 15:34:50 -0400136#include <assert.h>
Adam Langley95c29f32014-06-20 12:00:00 -0700137#include <stdio.h>
David Benjaminf0ae1702015-04-07 23:05:04 -0400138#include <string.h>
Adam Langley95c29f32014-06-20 12:00:00 -0700139
Adam Langley95c29f32014-06-20 12:00:00 -0700140#include <openssl/err.h>
141#include <openssl/lhash.h>
142#include <openssl/mem.h>
143#include <openssl/rand.h>
144
David Benjamin2ee94aa2015-04-07 22:38:30 -0400145#include "internal.h"
David Benjamin546f1a52015-04-15 16:46:09 -0400146#include "../crypto/internal.h"
147
Adam Langley95c29f32014-06-20 12:00:00 -0700148
Adam Langleyb2ce0582014-06-20 12:00:00 -0700149/* The address of this is a magic value, a pointer to which is returned by
150 * SSL_magic_pending_session_ptr(). It allows a session callback to indicate
151 * that it needs to asynchronously fetch session information. */
Brian Smithefed2212015-01-28 16:20:02 -0800152static const char g_pending_session_magic = 0;
Adam Langleyb2ce0582014-06-20 12:00:00 -0700153
David Benjaminaa585132015-06-29 23:36:17 -0400154static CRYPTO_EX_DATA_CLASS g_ex_data_class =
155 CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA;
David Benjamin9f33fc62015-04-15 17:29:53 -0400156
Adam Langley95c29f32014-06-20 12:00:00 -0700157static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s);
David Benjaminb18f0242015-03-10 18:30:08 -0400158static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s);
Adam Langley95c29f32014-06-20 12:00:00 -0700159static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck);
160
Adam Langleyfcf25832014-12-18 17:42:32 -0800161SSL_SESSION *SSL_magic_pending_session_ptr(void) {
162 return (SSL_SESSION *)&g_pending_session_magic;
Adam Langley95c29f32014-06-20 12:00:00 -0700163}
164
Adam Langleyfcf25832014-12-18 17:42:32 -0800165SSL_SESSION *SSL_get_session(const SSL *ssl)
166{
167 /* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */
168 return ssl->session;
169}
Adam Langley95c29f32014-06-20 12:00:00 -0700170
Adam Langleyfcf25832014-12-18 17:42:32 -0800171SSL_SESSION *SSL_get1_session(SSL *ssl) {
172 /* variant of SSL_get_session: caller really gets something */
David Benjamin23a8ca12015-02-09 03:35:43 -0500173 return SSL_SESSION_up_ref(ssl->session);
Adam Langleyfcf25832014-12-18 17:42:32 -0800174}
Adam Langley8eaaa862014-08-11 17:18:25 -0700175
Adam Langleyfcf25832014-12-18 17:42:32 -0800176int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
177 CRYPTO_EX_dup *dup_func,
178 CRYPTO_EX_free *free_func) {
David Benjamin9f33fc62015-04-15 17:29:53 -0400179 int index;
180 if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, new_func,
181 dup_func, free_func)) {
182 return -1;
183 }
184 return index;
Adam Langleyfcf25832014-12-18 17:42:32 -0800185}
Adam Langley95c29f32014-06-20 12:00:00 -0700186
Adam Langleyfcf25832014-12-18 17:42:32 -0800187int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg) {
188 return CRYPTO_set_ex_data(&s->ex_data, idx, arg);
189}
Adam Langley95c29f32014-06-20 12:00:00 -0700190
Adam Langleyfcf25832014-12-18 17:42:32 -0800191void *SSL_SESSION_get_ex_data(const SSL_SESSION *s, int idx) {
192 return CRYPTO_get_ex_data(&s->ex_data, idx);
193}
Adam Langley95c29f32014-06-20 12:00:00 -0700194
Adam Langleyfcf25832014-12-18 17:42:32 -0800195SSL_SESSION *SSL_SESSION_new(void) {
196 SSL_SESSION *ss;
Adam Langley95c29f32014-06-20 12:00:00 -0700197
Adam Langleyfcf25832014-12-18 17:42:32 -0800198 ss = (SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION));
199 if (ss == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400200 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
Adam Langleyfcf25832014-12-18 17:42:32 -0800201 return 0;
202 }
203 memset(ss, 0, sizeof(SSL_SESSION));
Adam Langley95c29f32014-06-20 12:00:00 -0700204
Adam Langleyfcf25832014-12-18 17:42:32 -0800205 ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */
206 ss->references = 1;
207 ss->timeout = SSL_DEFAULT_SESSION_TIMEOUT;
208 ss->time = (unsigned long)time(NULL);
David Benjamin9f33fc62015-04-15 17:29:53 -0400209 CRYPTO_new_ex_data(&g_ex_data_class, ss, &ss->ex_data);
Adam Langleyfcf25832014-12-18 17:42:32 -0800210 return ss;
211}
212
213const uint8_t *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len) {
214 if (len) {
215 *len = s->session_id_length;
216 }
217 return s->session_id;
218}
219
220/* Even with SSLv2, we have 16 bytes (128 bits) of session ID space.
221 * SSLv3/TLSv1 has 32 bytes (256 bits). As such, filling the ID with random
222 * gunk repeatedly until we have no conflict is going to complete in one
223 * iteration pretty much "most" of the time (btw: understatement). So, if it
224 * takes us 10 iterations and we still can't avoid a conflict - well that's a
225 * reasonable point to call it quits. Either the RAND code is broken or someone
226 * is trying to open roughly very close to 2^128 (or 2^256) SSL sessions to our
227 * server. How you might store that many sessions is perhaps a more interesting
228 * question ... */
229static int def_generate_session_id(const SSL *ssl, uint8_t *id,
230 unsigned int *id_len) {
231 static const unsigned kMaxAttempts = 10;
232 unsigned int retry = 0;
233 do {
234 if (!RAND_bytes(id, *id_len)) {
235 return 0;
236 }
237 } while (SSL_has_matching_session_id(ssl, id, *id_len) &&
238 (++retry < kMaxAttempts));
239
240 if (retry < kMaxAttempts) {
241 return 1;
242 }
243
244 /* else - woops a session_id match */
245 /* XXX We should also check the external cache -- but the probability of a
246 * collision is negligible, and we could not prevent the concurrent creation
247 * of sessions with identical IDs since we currently don't have means to
248 * atomically check whether a session ID already exists and make a
249 * reservation for it if it does not (this problem applies to the internal
250 * cache as well). */
251 return 0;
252}
253
254int ssl_get_new_session(SSL *s, int session) {
255 /* This gets used by clients and servers. */
256
257 unsigned int tmp;
258 SSL_SESSION *ss = NULL;
259 GEN_SESSION_CB cb = def_generate_session_id;
260
261 if (s->mode & SSL_MODE_NO_SESSION_CREATION) {
David Benjamin3570d732015-06-29 00:28:17 -0400262 OPENSSL_PUT_ERROR(SSL, SSL_R_SESSION_MAY_NOT_BE_CREATED);
Adam Langleyfcf25832014-12-18 17:42:32 -0800263 return 0;
264 }
265
266 ss = SSL_SESSION_new();
267 if (ss == NULL) {
268 return 0;
269 }
270
271 /* If the context has a default timeout, use it over the default. */
272 if (s->initial_ctx->session_timeout != 0) {
273 ss->timeout = s->initial_ctx->session_timeout;
274 }
275
David Benjamin2755a3e2015-04-22 16:17:58 -0400276 SSL_SESSION_free(s->session);
277 s->session = NULL;
Adam Langleyfcf25832014-12-18 17:42:32 -0800278
279 if (session) {
280 if (s->version == SSL3_VERSION || s->version == TLS1_VERSION ||
281 s->version == TLS1_1_VERSION || s->version == TLS1_2_VERSION ||
282 s->version == DTLS1_VERSION || s->version == DTLS1_2_VERSION) {
283 ss->ssl_version = s->version;
284 ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
285 } else {
David Benjamin3570d732015-06-29 00:28:17 -0400286 OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_SSL_VERSION);
Adam Langleyfcf25832014-12-18 17:42:32 -0800287 SSL_SESSION_free(ss);
288 return 0;
289 }
290
291 /* If RFC4507 ticket use empty session ID */
292 if (s->tlsext_ticket_expected) {
293 ss->session_id_length = 0;
294 goto sess_id_done;
295 }
296
297 /* Choose which callback will set the session ID */
Adam Langleyfcf25832014-12-18 17:42:32 -0800298 if (s->generate_session_id) {
299 cb = s->generate_session_id;
300 } else if (s->initial_ctx->generate_session_id) {
301 cb = s->initial_ctx->generate_session_id;
302 }
Adam Langleyfcf25832014-12-18 17:42:32 -0800303
304 /* Choose a session ID */
305 tmp = ss->session_id_length;
306 if (!cb(s, ss->session_id, &tmp)) {
307 /* The callback failed */
David Benjamin3570d732015-06-29 00:28:17 -0400308 OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_SESSION_ID_CALLBACK_FAILED);
Adam Langleyfcf25832014-12-18 17:42:32 -0800309 SSL_SESSION_free(ss);
310 return 0;
311 }
312
313 /* Don't allow the callback to set the session length to zero. nor set it
314 * higher than it was. */
315 if (!tmp || tmp > ss->session_id_length) {
316 /* The callback set an illegal length */
David Benjamin3570d732015-06-29 00:28:17 -0400317 OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH);
Adam Langleyfcf25832014-12-18 17:42:32 -0800318 SSL_SESSION_free(ss);
319 return 0;
320 }
321
322 ss->session_id_length = tmp;
323 /* Finally, check for a conflict */
324 if (SSL_has_matching_session_id(s, ss->session_id, ss->session_id_length)) {
David Benjamin3570d732015-06-29 00:28:17 -0400325 OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_SESSION_ID_CONFLICT);
Adam Langleyfcf25832014-12-18 17:42:32 -0800326 SSL_SESSION_free(ss);
327 return 0;
328 }
329
330 sess_id_done:
331 if (s->tlsext_hostname) {
332 ss->tlsext_hostname = BUF_strdup(s->tlsext_hostname);
333 if (ss->tlsext_hostname == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400334 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
Adam Langleyfcf25832014-12-18 17:42:32 -0800335 SSL_SESSION_free(ss);
336 return 0;
337 }
338 }
339 } else {
340 ss->session_id_length = 0;
341 }
342
343 if (s->sid_ctx_length > sizeof(ss->sid_ctx)) {
David Benjamin3570d732015-06-29 00:28:17 -0400344 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
Adam Langleyfcf25832014-12-18 17:42:32 -0800345 SSL_SESSION_free(ss);
346 return 0;
347 }
348
349 memcpy(ss->sid_ctx, s->sid_ctx, s->sid_ctx_length);
350 ss->sid_ctx_length = s->sid_ctx_length;
351 s->session = ss;
352 ss->ssl_version = s->version;
353 ss->verify_result = X509_V_OK;
354
355 return 1;
356}
Adam Langley95c29f32014-06-20 12:00:00 -0700357
David Benjamine3aa1d92015-06-16 15:34:50 -0400358/* ssl_lookup_session looks up |session_id| in the session cache and sets
359 * |*out_session| to an |SSL_SESSION| object if found. The caller takes
360 * ownership of the result. */
361static enum ssl_session_result_t ssl_lookup_session(
362 SSL *ssl, SSL_SESSION **out_session, const uint8_t *session_id,
363 size_t session_id_len) {
364 *out_session = NULL;
Adam Langley95c29f32014-06-20 12:00:00 -0700365
David Benjamine3aa1d92015-06-16 15:34:50 -0400366 if (session_id_len == 0 || session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) {
367 return ssl_session_success;
Adam Langleyfcf25832014-12-18 17:42:32 -0800368 }
Adam Langley95c29f32014-06-20 12:00:00 -0700369
David Benjamine3aa1d92015-06-16 15:34:50 -0400370 SSL_SESSION *session;
371 /* Try the internal cache, if it exists. */
372 if (!(ssl->initial_ctx->session_cache_mode &
Adam Langleyfcf25832014-12-18 17:42:32 -0800373 SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) {
374 SSL_SESSION data;
David Benjamine3aa1d92015-06-16 15:34:50 -0400375 data.ssl_version = ssl->version;
376 data.session_id_length = session_id_len;
377 memcpy(data.session_id, session_id, session_id_len);
378
379 CRYPTO_MUTEX_lock_read(&ssl->initial_ctx->lock);
380 session = lh_SSL_SESSION_retrieve(ssl->initial_ctx->sessions, &data);
381 if (session != NULL) {
382 SSL_SESSION_up_ref(session);
Adam Langleyfcf25832014-12-18 17:42:32 -0800383 }
David Benjamine3aa1d92015-06-16 15:34:50 -0400384 CRYPTO_MUTEX_unlock(&ssl->initial_ctx->lock);
Adam Langley4bdb6e42015-05-15 15:29:21 -0700385
David Benjamine3aa1d92015-06-16 15:34:50 -0400386 if (session != NULL) {
387 *out_session = session;
388 return ssl_session_success;
Adam Langleyfcf25832014-12-18 17:42:32 -0800389 }
390 }
Adam Langley95c29f32014-06-20 12:00:00 -0700391
David Benjamine3aa1d92015-06-16 15:34:50 -0400392 /* Fall back to the external cache, if it exists. */
393 if (ssl->initial_ctx->get_session_cb == NULL) {
394 return ssl_session_success;
395 }
396 int copy = 1;
397 session = ssl->initial_ctx->get_session_cb(ssl, (uint8_t *)session_id,
398 session_id_len, &copy);
399 if (session == NULL) {
400 return ssl_session_success;
401 }
402 if (session == SSL_magic_pending_session_ptr()) {
403 return ssl_session_retry;
Adam Langleyfcf25832014-12-18 17:42:32 -0800404 }
Adam Langley95c29f32014-06-20 12:00:00 -0700405
David Benjamine3aa1d92015-06-16 15:34:50 -0400406 /* Increment reference count now if the session callback asks us to do so
407 * (note that if the session structures returned by the callback are shared
408 * between threads, it must handle the reference count itself [i.e. copy ==
409 * 0], or things won't be thread-safe). */
410 if (copy) {
411 SSL_SESSION_up_ref(session);
Adam Langleyfcf25832014-12-18 17:42:32 -0800412 }
Adam Langley95c29f32014-06-20 12:00:00 -0700413
David Benjamine3aa1d92015-06-16 15:34:50 -0400414 /* Add the externally cached session to the internal cache if necessary. */
415 if (!(ssl->initial_ctx->session_cache_mode &
416 SSL_SESS_CACHE_NO_INTERNAL_STORE)) {
417 SSL_CTX_add_session(ssl->initial_ctx, session);
418 }
419
420 *out_session = session;
421 return ssl_session_success;
422}
423
424enum ssl_session_result_t ssl_get_prev_session(
425 SSL *ssl, SSL_SESSION **out_session, int *out_send_ticket,
426 const struct ssl_early_callback_ctx *ctx) {
427 /* This is used only by servers. */
428 assert(ssl->server);
429 SSL_SESSION *session = NULL;
430 int send_ticket = 0;
431
432 /* If tickets are disabled, always behave as if no tickets are present. */
David Benjamin3e536332015-07-01 18:45:03 -0400433 const uint8_t *ticket = NULL;
434 size_t ticket_len = 0;
David Benjamine3aa1d92015-06-16 15:34:50 -0400435 const int tickets_supported =
436 !(SSL_get_options(ssl) & SSL_OP_NO_TICKET) &&
437 (ssl->version > SSL3_VERSION || ctx->extensions != NULL) &&
438 SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_session_ticket,
439 &ticket, &ticket_len);
440 if (tickets_supported) {
441 if (!tls_process_ticket(ssl, &session, &send_ticket, ticket, ticket_len,
442 ctx->session_id, ctx->session_id_len)) {
443 return ssl_session_error;
444 }
445 } else {
446 /* The client does not support session tickets, so the session ID should be
447 * used instead. */
448 enum ssl_session_result_t lookup_ret = ssl_lookup_session(
449 ssl, &session, ctx->session_id, ctx->session_id_len);
450 if (lookup_ret != ssl_session_success) {
451 return lookup_ret;
452 }
453 }
454
455 if (session == NULL ||
456 session->sid_ctx_length != ssl->sid_ctx_length ||
457 memcmp(session->sid_ctx, ssl->sid_ctx, ssl->sid_ctx_length) != 0) {
458 goto no_session;
459 }
460
461 if ((ssl->verify_mode & SSL_VERIFY_PEER) && ssl->sid_ctx_length == 0) {
Adam Langleyfcf25832014-12-18 17:42:32 -0800462 /* We can't be sure if this session is being used out of context, which is
463 * especially important for SSL_VERIFY_PEER. The application should have
464 * used SSL[_CTX]_set_session_id_context.
465 *
466 * For this error case, we generate an error instead of treating the event
467 * like a cache miss (otherwise it would be easy for applications to
468 * effectively disable the session cache by accident without anyone
469 * noticing). */
David Benjamin3570d732015-06-29 00:28:17 -0400470 OPENSSL_PUT_ERROR(SSL, SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED);
David Benjamine3aa1d92015-06-16 15:34:50 -0400471 goto fatal_error;
Adam Langleyfcf25832014-12-18 17:42:32 -0800472 }
Adam Langley95c29f32014-06-20 12:00:00 -0700473
David Benjamine3aa1d92015-06-16 15:34:50 -0400474 if (session->timeout < (long)(time(NULL) - session->time)) {
475 if (!tickets_supported) {
476 /* The session was from the cache, so remove it. */
477 SSL_CTX_remove_session(ssl->initial_ctx, session);
Adam Langleyfcf25832014-12-18 17:42:32 -0800478 }
David Benjamine3aa1d92015-06-16 15:34:50 -0400479 goto no_session;
Adam Langleyfcf25832014-12-18 17:42:32 -0800480 }
Adam Langley95c29f32014-06-20 12:00:00 -0700481
David Benjamine3aa1d92015-06-16 15:34:50 -0400482 *out_session = session;
483 *out_send_ticket = send_ticket;
484 return ssl_session_success;
Adam Langley95c29f32014-06-20 12:00:00 -0700485
David Benjamine3aa1d92015-06-16 15:34:50 -0400486fatal_error:
487 SSL_SESSION_free(session);
488 return ssl_session_error;
489
490no_session:
491 *out_session = NULL;
492 *out_send_ticket = tickets_supported;
493 SSL_SESSION_free(session);
494 return ssl_session_success;
Adam Langley95c29f32014-06-20 12:00:00 -0700495}
496
Adam Langleyfcf25832014-12-18 17:42:32 -0800497int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) {
498 int ret = 0;
499 SSL_SESSION *s;
Adam Langley95c29f32014-06-20 12:00:00 -0700500
Adam Langleyfcf25832014-12-18 17:42:32 -0800501 /* add just 1 reference count for the SSL_CTX's session cache even though it
502 * has two ways of access: each session is in a doubly linked list and an
503 * lhash */
David Benjamin33639842015-02-09 03:34:47 -0500504 SSL_SESSION_up_ref(c);
Adam Langleyfcf25832014-12-18 17:42:32 -0800505 /* if session c is in already in cache, we take back the increment later */
Adam Langley95c29f32014-06-20 12:00:00 -0700506
Adam Langley4bdb6e42015-05-15 15:29:21 -0700507 CRYPTO_MUTEX_lock_write(&ctx->lock);
Adam Langleyfcf25832014-12-18 17:42:32 -0800508 if (!lh_SSL_SESSION_insert(ctx->sessions, &s, c)) {
Adam Langley4bdb6e42015-05-15 15:29:21 -0700509 CRYPTO_MUTEX_unlock(&ctx->lock);
David Benjamine3aa1d92015-06-16 15:34:50 -0400510 SSL_SESSION_free(c);
Adam Langleyfcf25832014-12-18 17:42:32 -0800511 return 0;
512 }
Adam Langley95c29f32014-06-20 12:00:00 -0700513
David Benjamine3aa1d92015-06-16 15:34:50 -0400514 /* s != NULL iff we already had a session with the given session ID. In this
515 * case, s == c should hold (then we did not really modify ctx->sessions), or
516 * we're in trouble. */
Adam Langleyfcf25832014-12-18 17:42:32 -0800517 if (s != NULL && s != c) {
518 /* We *are* in trouble ... */
519 SSL_SESSION_list_remove(ctx, s);
520 SSL_SESSION_free(s);
521 /* ... so pretend the other session did not exist in cache (we cannot
522 * handle two SSL_SESSION structures with identical session ID in the same
523 * cache, which could happen e.g. when two threads concurrently obtain the
524 * same session from an external cache) */
525 s = NULL;
526 }
Adam Langley95c29f32014-06-20 12:00:00 -0700527
Adam Langleyfcf25832014-12-18 17:42:32 -0800528 /* Put at the head of the queue unless it is already in the cache */
529 if (s == NULL) {
530 SSL_SESSION_list_add(ctx, c);
531 }
Adam Langley95c29f32014-06-20 12:00:00 -0700532
Adam Langleyfcf25832014-12-18 17:42:32 -0800533 if (s != NULL) {
534 /* existing cache entry -- decrement previously incremented reference count
535 * because it already takes into account the cache */
536 SSL_SESSION_free(s); /* s == c */
537 ret = 0;
538 } else {
539 /* new cache entry -- remove old ones if cache has become too large */
540 ret = 1;
Adam Langley95c29f32014-06-20 12:00:00 -0700541
Adam Langleyfcf25832014-12-18 17:42:32 -0800542 if (SSL_CTX_sess_get_cache_size(ctx) > 0) {
543 while (SSL_CTX_sess_number(ctx) > SSL_CTX_sess_get_cache_size(ctx)) {
544 if (!remove_session_lock(ctx, ctx->session_cache_tail, 0)) {
545 break;
546 }
Adam Langleyfcf25832014-12-18 17:42:32 -0800547 }
548 }
549 }
Adam Langley95c29f32014-06-20 12:00:00 -0700550
Adam Langley4bdb6e42015-05-15 15:29:21 -0700551 CRYPTO_MUTEX_unlock(&ctx->lock);
Adam Langleyfcf25832014-12-18 17:42:32 -0800552 return ret;
553}
Adam Langley95c29f32014-06-20 12:00:00 -0700554
Adam Langleyfcf25832014-12-18 17:42:32 -0800555int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c) {
556 return remove_session_lock(ctx, c, 1);
557}
Adam Langley95c29f32014-06-20 12:00:00 -0700558
Adam Langleyfcf25832014-12-18 17:42:32 -0800559static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lock) {
560 SSL_SESSION *r;
561 int ret = 0;
Adam Langley95c29f32014-06-20 12:00:00 -0700562
Adam Langleyfcf25832014-12-18 17:42:32 -0800563 if (c != NULL && c->session_id_length != 0) {
564 if (lock) {
Adam Langley4bdb6e42015-05-15 15:29:21 -0700565 CRYPTO_MUTEX_lock_write(&ctx->lock);
Adam Langleyfcf25832014-12-18 17:42:32 -0800566 }
567 r = lh_SSL_SESSION_retrieve(ctx->sessions, c);
568 if (r == c) {
569 ret = 1;
570 r = lh_SSL_SESSION_delete(ctx->sessions, c);
571 SSL_SESSION_list_remove(ctx, c);
572 }
Adam Langley95c29f32014-06-20 12:00:00 -0700573
Adam Langleyfcf25832014-12-18 17:42:32 -0800574 if (lock) {
Adam Langley4bdb6e42015-05-15 15:29:21 -0700575 CRYPTO_MUTEX_unlock(&ctx->lock);
Adam Langleyfcf25832014-12-18 17:42:32 -0800576 }
Adam Langley95c29f32014-06-20 12:00:00 -0700577
Adam Langleyfcf25832014-12-18 17:42:32 -0800578 if (ret) {
579 r->not_resumable = 1;
580 if (ctx->remove_session_cb != NULL) {
581 ctx->remove_session_cb(ctx, r);
582 }
583 SSL_SESSION_free(r);
584 }
585 }
Adam Langley95c29f32014-06-20 12:00:00 -0700586
Adam Langleyfcf25832014-12-18 17:42:32 -0800587 return ret;
588}
Adam Langley95c29f32014-06-20 12:00:00 -0700589
David Benjamin33639842015-02-09 03:34:47 -0500590SSL_SESSION *SSL_SESSION_up_ref(SSL_SESSION *session) {
591 if (session) {
Adam Langley0b5e3902015-05-15 13:08:38 -0700592 CRYPTO_refcount_inc(&session->references);
David Benjamin33639842015-02-09 03:34:47 -0500593 }
594 return session;
595}
596
David Benjamin4fcc2e22015-04-22 12:58:16 -0400597void SSL_SESSION_free(SSL_SESSION *session) {
598 if (session == NULL ||
Adam Langley0b5e3902015-05-15 13:08:38 -0700599 !CRYPTO_refcount_dec_and_test_zero(&session->references)) {
Adam Langleyfcf25832014-12-18 17:42:32 -0800600 return;
601 }
Adam Langley95c29f32014-06-20 12:00:00 -0700602
David Benjamin4fcc2e22015-04-22 12:58:16 -0400603 CRYPTO_free_ex_data(&g_ex_data_class, session, &session->ex_data);
Adam Langley95c29f32014-06-20 12:00:00 -0700604
David Benjamin4fcc2e22015-04-22 12:58:16 -0400605 OPENSSL_cleanse(session->master_key, sizeof(session->master_key));
606 OPENSSL_cleanse(session->session_id, sizeof(session->session_id));
David Benjamin2755a3e2015-04-22 16:17:58 -0400607 ssl_sess_cert_free(session->sess_cert);
608 X509_free(session->peer);
609 OPENSSL_free(session->tlsext_hostname);
610 OPENSSL_free(session->tlsext_tick);
611 OPENSSL_free(session->tlsext_signed_cert_timestamp_list);
612 OPENSSL_free(session->ocsp_response);
613 OPENSSL_free(session->psk_identity);
David Benjamin4fcc2e22015-04-22 12:58:16 -0400614 OPENSSL_cleanse(session, sizeof(*session));
615 OPENSSL_free(session);
Adam Langleyfcf25832014-12-18 17:42:32 -0800616}
Adam Langley95c29f32014-06-20 12:00:00 -0700617
Adam Langleyfcf25832014-12-18 17:42:32 -0800618int SSL_set_session(SSL *s, SSL_SESSION *session) {
619 if (s->session == session) {
620 return 1;
621 }
Adam Langley95c29f32014-06-20 12:00:00 -0700622
David Benjamin2755a3e2015-04-22 16:17:58 -0400623 SSL_SESSION_free(s->session);
Adam Langleyfcf25832014-12-18 17:42:32 -0800624 s->session = session;
625 if (session != NULL) {
David Benjamin33639842015-02-09 03:34:47 -0500626 SSL_SESSION_up_ref(session);
Adam Langleyfcf25832014-12-18 17:42:32 -0800627 s->verify_result = session->verify_result;
628 }
Adam Langley95c29f32014-06-20 12:00:00 -0700629
Adam Langleyfcf25832014-12-18 17:42:32 -0800630 return 1;
631}
Adam Langley95c29f32014-06-20 12:00:00 -0700632
Adam Langleyfcf25832014-12-18 17:42:32 -0800633long SSL_SESSION_set_timeout(SSL_SESSION *s, long t) {
634 if (s == NULL) {
635 return 0;
636 }
Adam Langley95c29f32014-06-20 12:00:00 -0700637
Adam Langleyfcf25832014-12-18 17:42:32 -0800638 s->timeout = t;
639 return 1;
640}
Adam Langley95c29f32014-06-20 12:00:00 -0700641
Adam Langleyfcf25832014-12-18 17:42:32 -0800642long SSL_SESSION_get_timeout(const SSL_SESSION *s) {
643 if (s == NULL) {
644 return 0;
645 }
Adam Langley95c29f32014-06-20 12:00:00 -0700646
Adam Langleyfcf25832014-12-18 17:42:32 -0800647 return s->timeout;
648}
649
650long SSL_SESSION_get_time(const SSL_SESSION *s) {
651 if (s == NULL) {
652 return 0;
653 }
654
655 return s->time;
656}
657
658long SSL_SESSION_set_time(SSL_SESSION *s, long t) {
659 if (s == NULL) {
660 return 0;
661 }
662
663 s->time = t;
664 return t;
665}
666
667X509 *SSL_SESSION_get0_peer(SSL_SESSION *s) { return s->peer; }
668
669int SSL_SESSION_set1_id_context(SSL_SESSION *s, const uint8_t *sid_ctx,
670 unsigned int sid_ctx_len) {
671 if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) {
David Benjamin3570d732015-06-29 00:28:17 -0400672 OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
Adam Langleyfcf25832014-12-18 17:42:32 -0800673 return 0;
674 }
675
676 s->sid_ctx_length = sid_ctx_len;
677 memcpy(s->sid_ctx, sid_ctx, sid_ctx_len);
678
679 return 1;
680}
681
682long SSL_CTX_set_timeout(SSL_CTX *s, long t) {
683 long l;
684 if (s == NULL) {
685 return 0;
686 }
687
688 l = s->session_timeout;
689 s->session_timeout = t;
690 return l;
691}
692
693long SSL_CTX_get_timeout(const SSL_CTX *s) {
694 if (s == NULL) {
695 return 0;
696 }
697
698 return s->session_timeout;
699}
700
701typedef struct timeout_param_st {
702 SSL_CTX *ctx;
703 long time;
David Benjamin60da0cd2015-05-03 15:21:28 -0400704 LHASH_OF(SSL_SESSION) *cache;
Adam Langleyfcf25832014-12-18 17:42:32 -0800705} TIMEOUT_PARAM;
706
707static void timeout_doall_arg(SSL_SESSION *sess, void *void_param) {
708 TIMEOUT_PARAM *param = void_param;
709
710 if (param->time == 0 ||
711 param->time > (sess->time + sess->timeout)) {
712 /* timeout */
713 /* The reason we don't call SSL_CTX_remove_session() is to
714 * save on locking overhead */
Adam Langleya307dfd2015-01-09 15:42:58 -0800715 (void) lh_SSL_SESSION_delete(param->cache, sess);
Adam Langleyfcf25832014-12-18 17:42:32 -0800716 SSL_SESSION_list_remove(param->ctx, sess);
717 sess->not_resumable = 1;
718 if (param->ctx->remove_session_cb != NULL) {
719 param->ctx->remove_session_cb(param->ctx, sess);
720 }
721 SSL_SESSION_free(sess);
722 }
723}
724
Adam Langley4bdb6e42015-05-15 15:29:21 -0700725void SSL_CTX_flush_sessions(SSL_CTX *ctx, long t) {
Adam Langleyfcf25832014-12-18 17:42:32 -0800726 TIMEOUT_PARAM tp;
727
Adam Langley4bdb6e42015-05-15 15:29:21 -0700728 tp.ctx = ctx;
729 tp.cache = ctx->sessions;
Adam Langleyfcf25832014-12-18 17:42:32 -0800730 if (tp.cache == NULL) {
731 return;
732 }
733 tp.time = t;
Adam Langley4bdb6e42015-05-15 15:29:21 -0700734 CRYPTO_MUTEX_lock_write(&ctx->lock);
Adam Langleyfcf25832014-12-18 17:42:32 -0800735 lh_SSL_SESSION_doall_arg(tp.cache, timeout_doall_arg, &tp);
Adam Langley4bdb6e42015-05-15 15:29:21 -0700736 CRYPTO_MUTEX_unlock(&ctx->lock);
Adam Langleyfcf25832014-12-18 17:42:32 -0800737}
738
739int ssl_clear_bad_session(SSL *s) {
740 if (s->session != NULL && !(s->shutdown & SSL_SENT_SHUTDOWN) &&
741 !SSL_in_init(s)) {
742 SSL_CTX_remove_session(s->ctx, s->session);
743 return 1;
744 }
745
746 return 0;
747}
Adam Langley95c29f32014-06-20 12:00:00 -0700748
749/* locked by SSL_CTX in the calling function */
Adam Langleyfcf25832014-12-18 17:42:32 -0800750static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s) {
751 if (s->next == NULL || s->prev == NULL) {
752 return;
753 }
Adam Langley95c29f32014-06-20 12:00:00 -0700754
Adam Langleyfcf25832014-12-18 17:42:32 -0800755 if (s->next == (SSL_SESSION *)&ctx->session_cache_tail) {
756 /* last element in list */
757 if (s->prev == (SSL_SESSION *)&ctx->session_cache_head) {
758 /* only one element in list */
759 ctx->session_cache_head = NULL;
760 ctx->session_cache_tail = NULL;
761 } else {
762 ctx->session_cache_tail = s->prev;
763 s->prev->next = (SSL_SESSION *)&(ctx->session_cache_tail);
764 }
765 } else {
766 if (s->prev == (SSL_SESSION *)&ctx->session_cache_head) {
767 /* first element in list */
768 ctx->session_cache_head = s->next;
769 s->next->prev = (SSL_SESSION *)&(ctx->session_cache_head);
770 } else { /* middle of list */
771 s->next->prev = s->prev;
772 s->prev->next = s->next;
773 }
774 }
775 s->prev = s->next = NULL;
776}
Adam Langley95c29f32014-06-20 12:00:00 -0700777
Adam Langleyfcf25832014-12-18 17:42:32 -0800778static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s) {
779 if (s->next != NULL && s->prev != NULL) {
780 SSL_SESSION_list_remove(ctx, s);
781 }
Adam Langley95c29f32014-06-20 12:00:00 -0700782
Adam Langleyfcf25832014-12-18 17:42:32 -0800783 if (ctx->session_cache_head == NULL) {
784 ctx->session_cache_head = s;
785 ctx->session_cache_tail = s;
786 s->prev = (SSL_SESSION *)&(ctx->session_cache_head);
787 s->next = (SSL_SESSION *)&(ctx->session_cache_tail);
788 } else {
789 s->next = ctx->session_cache_head;
790 s->next->prev = s;
791 s->prev = (SSL_SESSION *)&(ctx->session_cache_head);
792 ctx->session_cache_head = s;
793 }
794}
Adam Langley95c29f32014-06-20 12:00:00 -0700795
796void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx,
Adam Langleyfcf25832014-12-18 17:42:32 -0800797 int (*cb)(struct ssl_st *ssl, SSL_SESSION *sess)) {
798 ctx->new_session_cb = cb;
799}
Adam Langley95c29f32014-06-20 12:00:00 -0700800
Adam Langleyfcf25832014-12-18 17:42:32 -0800801int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(SSL *ssl, SSL_SESSION *sess) {
802 return ctx->new_session_cb;
803}
Adam Langley95c29f32014-06-20 12:00:00 -0700804
805void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx,
Adam Langleyfcf25832014-12-18 17:42:32 -0800806 void (*cb)(SSL_CTX *ctx, SSL_SESSION *sess)) {
807 ctx->remove_session_cb = cb;
808}
Adam Langley95c29f32014-06-20 12:00:00 -0700809
Adam Langleyfcf25832014-12-18 17:42:32 -0800810void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(SSL_CTX *ctx,
811 SSL_SESSION *sess) {
812 return ctx->remove_session_cb;
813}
Adam Langley95c29f32014-06-20 12:00:00 -0700814
815void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx,
Adam Langleyfcf25832014-12-18 17:42:32 -0800816 SSL_SESSION *(*cb)(struct ssl_st *ssl,
817 uint8_t *data, int len,
818 int *copy)) {
819 ctx->get_session_cb = cb;
820}
Adam Langley95c29f32014-06-20 12:00:00 -0700821
Adam Langleyfcf25832014-12-18 17:42:32 -0800822SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(SSL *ssl, uint8_t *data,
823 int len, int *copy) {
824 return ctx->get_session_cb;
825}
Adam Langley95c29f32014-06-20 12:00:00 -0700826
Adam Langleyfcf25832014-12-18 17:42:32 -0800827void SSL_CTX_set_info_callback(SSL_CTX *ctx,
828 void (*cb)(const SSL *ssl, int type, int val)) {
829 ctx->info_callback = cb;
830}
Adam Langley95c29f32014-06-20 12:00:00 -0700831
Adam Langleyfcf25832014-12-18 17:42:32 -0800832void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl, int type,
833 int val) {
834 return ctx->info_callback;
835}
Adam Langley95c29f32014-06-20 12:00:00 -0700836
Adam Langleyfcf25832014-12-18 17:42:32 -0800837void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, int (*cb)(SSL *ssl, X509 **x509,
838 EVP_PKEY **pkey)) {
839 ctx->client_cert_cb = cb;
840}
Adam Langley95c29f32014-06-20 12:00:00 -0700841
Adam Langleyfcf25832014-12-18 17:42:32 -0800842int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL *ssl, X509 **x509,
843 EVP_PKEY **pkey) {
844 return ctx->client_cert_cb;
845}
Adam Langley95c29f32014-06-20 12:00:00 -0700846
Adam Langley1258b6a2014-06-20 12:00:00 -0700847void SSL_CTX_set_channel_id_cb(SSL_CTX *ctx,
Adam Langleyfcf25832014-12-18 17:42:32 -0800848 void (*cb)(SSL *ssl, EVP_PKEY **pkey)) {
849 ctx->channel_id_cb = cb;
850}
Adam Langley1258b6a2014-06-20 12:00:00 -0700851
Adam Langleyfcf25832014-12-18 17:42:32 -0800852void (*SSL_CTX_get_channel_id_cb(SSL_CTX *ctx))(SSL *ssl, EVP_PKEY **pkey) {
853 return ctx->channel_id_cb;
854}
Adam Langley1258b6a2014-06-20 12:00:00 -0700855
Adam Langley95c29f32014-06-20 12:00:00 -0700856IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION)