ssl_sess.c revision 98d58bb80c64b02a33662f0ea80351d4a1535267
1/* ssl/ssl_sess.c */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved.
4 *
5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com).
7 * The implementation was written so as to conform with Netscapes SSL.
8 *
9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to.  The following conditions
11 * apply to all code found in this distribution, be it the RC4, RSA,
12 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13 * included with this distribution is covered by the same copyright terms
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 *
16 * Copyright remains Eric Young's, and as such any Copyright notices in
17 * the code are not to be removed.
18 * If this package is used in a product, Eric Young should be given attribution
19 * as the author of the parts of the library used.
20 * This can be in the form of a textual message at program startup or
21 * in documentation (online or textual) provided with the package.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the copyright
27 *    notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 *    notice, this list of conditions and the following disclaimer in the
30 *    documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 *    must display the following acknowledgement:
33 *    "This product includes cryptographic software written by
34 *     Eric Young (eay@cryptsoft.com)"
35 *    The word 'cryptographic' can be left out if the rouines from the library
36 *    being used are not cryptographic related :-).
37 * 4. If you include any Windows specific code (or a derivative thereof) from
38 *    the apps directory (application code) you must include an acknowledgement:
39 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 *
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
52 *
53 * The licence and distribution terms for any publically available version or
54 * derivative of this code cannot be changed.  i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
57 */
58
59#include <stdio.h>
60#include <openssl/lhash.h>
61#include <openssl/rand.h>
62#ifndef OPENSSL_NO_ENGINE
63#include <openssl/engine.h>
64#endif
65#include "ssl_locl.h"
66
67static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s);
68static void SSL_SESSION_list_add(SSL_CTX *ctx,SSL_SESSION *s);
69static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck);
70
71SSL_SESSION *SSL_get_session(const SSL *ssl)
72/* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */
73	{
74	return(ssl->session);
75	}
76
77SSL_SESSION *SSL_get1_session(SSL *ssl)
78/* variant of SSL_get_session: caller really gets something */
79	{
80	SSL_SESSION *sess;
81	/* Need to lock this all up rather than just use CRYPTO_add so that
82	 * somebody doesn't free ssl->session between when we check it's
83	 * non-null and when we up the reference count. */
84	CRYPTO_w_lock(CRYPTO_LOCK_SSL_SESSION);
85	sess = ssl->session;
86	if(sess)
87		sess->references++;
88	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_SESSION);
89	return(sess);
90	}
91
92int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
93	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
94	{
95	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, argl, argp,
96			new_func, dup_func, free_func);
97	}
98
99int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg)
100	{
101	return(CRYPTO_set_ex_data(&s->ex_data,idx,arg));
102	}
103
104void *SSL_SESSION_get_ex_data(const SSL_SESSION *s, int idx)
105	{
106	return(CRYPTO_get_ex_data(&s->ex_data,idx));
107	}
108
109SSL_SESSION *SSL_SESSION_new(void)
110	{
111	SSL_SESSION *ss;
112
113	ss=(SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION));
114	if (ss == NULL)
115		{
116		SSLerr(SSL_F_SSL_SESSION_NEW,ERR_R_MALLOC_FAILURE);
117		return(0);
118		}
119	memset(ss,0,sizeof(SSL_SESSION));
120
121	ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */
122	ss->references=1;
123	ss->timeout=60*5+4; /* 5 minute timeout by default */
124	ss->time=(unsigned long)time(NULL);
125	ss->prev=NULL;
126	ss->next=NULL;
127	ss->compress_meth=0;
128#ifndef OPENSSL_NO_TLSEXT
129	ss->tlsext_hostname = NULL;
130#endif
131	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
132	return(ss);
133	}
134
135const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len)
136	{
137	if(len)
138		*len = s->session_id_length;
139	return s->session_id;
140	}
141
142/* Even with SSLv2, we have 16 bytes (128 bits) of session ID space. SSLv3/TLSv1
143 * has 32 bytes (256 bits). As such, filling the ID with random gunk repeatedly
144 * until we have no conflict is going to complete in one iteration pretty much
145 * "most" of the time (btw: understatement). So, if it takes us 10 iterations
146 * and we still can't avoid a conflict - well that's a reasonable point to call
147 * it quits. Either the RAND code is broken or someone is trying to open roughly
148 * very close to 2^128 (or 2^256) SSL sessions to our server. How you might
149 * store that many sessions is perhaps a more interesting question ... */
150
151#define MAX_SESS_ID_ATTEMPTS 10
152static int def_generate_session_id(const SSL *ssl, unsigned char *id,
153				unsigned int *id_len)
154{
155	unsigned int retry = 0;
156	do
157		if (RAND_pseudo_bytes(id, *id_len) <= 0)
158			return 0;
159	while(SSL_has_matching_session_id(ssl, id, *id_len) &&
160		(++retry < MAX_SESS_ID_ATTEMPTS));
161	if(retry < MAX_SESS_ID_ATTEMPTS)
162		return 1;
163	/* else - woops a session_id match */
164	/* XXX We should also check the external cache --
165	 * but the probability of a collision is negligible, and
166	 * we could not prevent the concurrent creation of sessions
167	 * with identical IDs since we currently don't have means
168	 * to atomically check whether a session ID already exists
169	 * and make a reservation for it if it does not
170	 * (this problem applies to the internal cache as well).
171	 */
172	return 0;
173}
174
175int ssl_get_new_session(SSL *s, int session)
176	{
177	/* This gets used by clients and servers. */
178
179	unsigned int tmp;
180	SSL_SESSION *ss=NULL;
181	GEN_SESSION_CB cb = def_generate_session_id;
182
183	if ((ss=SSL_SESSION_new()) == NULL) return(0);
184
185	/* If the context has a default timeout, use it */
186	if (s->ctx->session_timeout == 0)
187		ss->timeout=SSL_get_default_timeout(s);
188	else
189		ss->timeout=s->ctx->session_timeout;
190
191	if (s->session != NULL)
192		{
193		SSL_SESSION_free(s->session);
194		s->session=NULL;
195		}
196
197	if (session)
198		{
199		if (s->version == SSL2_VERSION)
200			{
201			ss->ssl_version=SSL2_VERSION;
202			ss->session_id_length=SSL2_SSL_SESSION_ID_LENGTH;
203			}
204		else if (s->version == SSL3_VERSION)
205			{
206			ss->ssl_version=SSL3_VERSION;
207			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
208			}
209		else if (s->version == TLS1_VERSION)
210			{
211			ss->ssl_version=TLS1_VERSION;
212			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
213			}
214		else if (s->version == DTLS1_BAD_VER)
215			{
216			ss->ssl_version=DTLS1_BAD_VER;
217			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
218			}
219		else if (s->version == DTLS1_VERSION)
220			{
221			ss->ssl_version=DTLS1_VERSION;
222			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
223			}
224		else
225			{
226			SSLerr(SSL_F_SSL_GET_NEW_SESSION,SSL_R_UNSUPPORTED_SSL_VERSION);
227			SSL_SESSION_free(ss);
228			return(0);
229			}
230#ifndef OPENSSL_NO_TLSEXT
231		/* If RFC4507 ticket use empty session ID */
232		if (s->tlsext_ticket_expected)
233			{
234			ss->session_id_length = 0;
235			goto sess_id_done;
236			}
237#endif
238		/* Choose which callback will set the session ID */
239		CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
240		if(s->generate_session_id)
241			cb = s->generate_session_id;
242		else if(s->ctx->generate_session_id)
243			cb = s->ctx->generate_session_id;
244		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
245		/* Choose a session ID */
246		tmp = ss->session_id_length;
247		if(!cb(s, ss->session_id, &tmp))
248			{
249			/* The callback failed */
250			SSLerr(SSL_F_SSL_GET_NEW_SESSION,
251				SSL_R_SSL_SESSION_ID_CALLBACK_FAILED);
252			SSL_SESSION_free(ss);
253			return(0);
254			}
255		/* Don't allow the callback to set the session length to zero.
256		 * nor set it higher than it was. */
257		if(!tmp || (tmp > ss->session_id_length))
258			{
259			/* The callback set an illegal length */
260			SSLerr(SSL_F_SSL_GET_NEW_SESSION,
261				SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH);
262			SSL_SESSION_free(ss);
263			return(0);
264			}
265		/* If the session length was shrunk and we're SSLv2, pad it */
266		if((tmp < ss->session_id_length) && (s->version == SSL2_VERSION))
267			memset(ss->session_id + tmp, 0, ss->session_id_length - tmp);
268		else
269			ss->session_id_length = tmp;
270		/* Finally, check for a conflict */
271		if(SSL_has_matching_session_id(s, ss->session_id,
272						ss->session_id_length))
273			{
274			SSLerr(SSL_F_SSL_GET_NEW_SESSION,
275				SSL_R_SSL_SESSION_ID_CONFLICT);
276			SSL_SESSION_free(ss);
277			return(0);
278			}
279#ifndef OPENSSL_NO_TLSEXT
280		sess_id_done:
281		if (s->tlsext_hostname) {
282			ss->tlsext_hostname = BUF_strdup(s->tlsext_hostname);
283			if (ss->tlsext_hostname == NULL) {
284				SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_INTERNAL_ERROR);
285				SSL_SESSION_free(ss);
286				return 0;
287				}
288			}
289#endif
290		}
291	else
292		{
293		ss->session_id_length=0;
294		}
295
296	if (s->sid_ctx_length > sizeof ss->sid_ctx)
297		{
298		SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_INTERNAL_ERROR);
299		SSL_SESSION_free(ss);
300		return 0;
301		}
302	memcpy(ss->sid_ctx,s->sid_ctx,s->sid_ctx_length);
303	ss->sid_ctx_length=s->sid_ctx_length;
304	s->session=ss;
305	ss->ssl_version=s->version;
306	ss->verify_result = X509_V_OK;
307
308	return(1);
309	}
310
311int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
312			const unsigned char *limit)
313	{
314	/* This is used only by servers. */
315
316	SSL_SESSION *ret=NULL;
317	int fatal = 0;
318#ifndef OPENSSL_NO_TLSEXT
319	int r;
320#endif
321
322	if (len > SSL_MAX_SSL_SESSION_ID_LENGTH)
323		goto err;
324#ifndef OPENSSL_NO_TLSEXT
325 	r = tls1_process_ticket(s, session_id, len, limit, &ret);
326	if (r == -1)
327		{
328		fatal = 1;
329 		goto err;
330		}
331	else if (r == 0 || (!ret && !len))
332		goto err;
333	else if (!ret && !(s->session_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
334#else
335	if (len == 0)
336		goto err;
337	if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
338#endif
339		{
340		SSL_SESSION data;
341		data.ssl_version=s->version;
342		data.session_id_length=len;
343		if (len == 0)
344			return 0;
345 		memcpy(data.session_id,session_id,len);
346		CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
347		ret=(SSL_SESSION *)lh_retrieve(s->ctx->sessions,&data);
348		if (ret != NULL)
349		    /* don't allow other threads to steal it: */
350		    CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION);
351		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
352		}
353
354	if (ret == NULL)
355		{
356		int copy=1;
357
358		s->ctx->stats.sess_miss++;
359		ret=NULL;
360		if (s->ctx->get_session_cb != NULL
361		    && (ret=s->ctx->get_session_cb(s,session_id,len,&copy))
362		       != NULL)
363			{
364			s->ctx->stats.sess_cb_hit++;
365
366			/* Increment reference count now if the session callback
367			 * asks us to do so (note that if the session structures
368			 * returned by the callback are shared between threads,
369			 * it must handle the reference count itself [i.e. copy == 0],
370			 * or things won't be thread-safe). */
371			if (copy)
372				CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION);
373
374			/* Add the externally cached session to the internal
375			 * cache as well if and only if we are supposed to. */
376			if(!(s->ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_STORE))
377				/* The following should not return 1, otherwise,
378				 * things are very strange */
379				SSL_CTX_add_session(s->ctx,ret);
380			}
381		if (ret == NULL)
382			goto err;
383		}
384
385	/* Now ret is non-NULL, and we own one of its reference counts. */
386
387	if (ret->sid_ctx_length != s->sid_ctx_length
388	    || memcmp(ret->sid_ctx,s->sid_ctx,ret->sid_ctx_length))
389		{
390		/* We've found the session named by the client, but we don't
391		 * want to use it in this context. */
392
393#if 0 /* The client cannot always know when a session is not appropriate,
394       * so we shouldn't generate an error message. */
395
396		SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
397#endif
398		goto err; /* treat like cache miss */
399		}
400
401	if((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0)
402		{
403		/* We can't be sure if this session is being used out of
404		 * context, which is especially important for SSL_VERIFY_PEER.
405		 * The application should have used SSL[_CTX]_set_session_id_context.
406		 *
407		 * For this error case, we generate an error instead of treating
408		 * the event like a cache miss (otherwise it would be easy for
409		 * applications to effectively disable the session cache by
410		 * accident without anyone noticing).
411		 */
412
413		SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED);
414		fatal = 1;
415		goto err;
416		}
417
418	if (ret->cipher == NULL)
419		{
420		unsigned char buf[5],*p;
421		unsigned long l;
422
423		p=buf;
424		l=ret->cipher_id;
425		l2n(l,p);
426		if ((ret->ssl_version>>8) >= SSL3_VERSION_MAJOR)
427			ret->cipher=ssl_get_cipher_by_char(s,&(buf[2]));
428		else
429			ret->cipher=ssl_get_cipher_by_char(s,&(buf[1]));
430		if (ret->cipher == NULL)
431			goto err;
432		}
433
434
435#if 0 /* This is way too late. */
436
437	/* If a thread got the session, then 'swaped', and another got
438	 * it and then due to a time-out decided to 'OPENSSL_free' it we could
439	 * be in trouble.  So I'll increment it now, then double decrement
440	 * later - am I speaking rubbish?. */
441	CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION);
442#endif
443
444	if (ret->timeout < (long)(time(NULL) - ret->time)) /* timeout */
445		{
446		s->ctx->stats.sess_timeout++;
447		/* remove it from the cache */
448		SSL_CTX_remove_session(s->ctx,ret);
449		goto err;
450		}
451
452	s->ctx->stats.sess_hit++;
453
454	/* ret->time=time(NULL); */ /* rezero timeout? */
455	/* again, just leave the session
456	 * if it is the same session, we have just incremented and
457	 * then decremented the reference count :-) */
458	if (s->session != NULL)
459		SSL_SESSION_free(s->session);
460	s->session=ret;
461	s->verify_result = s->session->verify_result;
462	return(1);
463
464 err:
465	if (ret != NULL)
466		SSL_SESSION_free(ret);
467	if (fatal)
468		return -1;
469	else
470		return 0;
471	}
472
473int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c)
474	{
475	int ret=0;
476	SSL_SESSION *s;
477
478	/* add just 1 reference count for the SSL_CTX's session cache
479	 * even though it has two ways of access: each session is in a
480	 * doubly linked list and an lhash */
481	CRYPTO_add(&c->references,1,CRYPTO_LOCK_SSL_SESSION);
482	/* if session c is in already in cache, we take back the increment later */
483
484	CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
485	s=(SSL_SESSION *)lh_insert(ctx->sessions,c);
486
487	/* s != NULL iff we already had a session with the given PID.
488	 * In this case, s == c should hold (then we did not really modify
489	 * ctx->sessions), or we're in trouble. */
490	if (s != NULL && s != c)
491		{
492		/* We *are* in trouble ... */
493		SSL_SESSION_list_remove(ctx,s);
494		SSL_SESSION_free(s);
495		/* ... so pretend the other session did not exist in cache
496		 * (we cannot handle two SSL_SESSION structures with identical
497		 * session ID in the same cache, which could happen e.g. when
498		 * two threads concurrently obtain the same session from an external
499		 * cache) */
500		s = NULL;
501		}
502
503 	/* Put at the head of the queue unless it is already in the cache */
504	if (s == NULL)
505		SSL_SESSION_list_add(ctx,c);
506
507	if (s != NULL)
508		{
509		/* existing cache entry -- decrement previously incremented reference
510		 * count because it already takes into account the cache */
511
512		SSL_SESSION_free(s); /* s == c */
513		ret=0;
514		}
515	else
516		{
517		/* new cache entry -- remove old ones if cache has become too large */
518
519		ret=1;
520
521		if (SSL_CTX_sess_get_cache_size(ctx) > 0)
522			{
523			while (SSL_CTX_sess_number(ctx) >
524				SSL_CTX_sess_get_cache_size(ctx))
525				{
526				if (!remove_session_lock(ctx,
527					ctx->session_cache_tail, 0))
528					break;
529				else
530					ctx->stats.sess_cache_full++;
531				}
532			}
533		}
534	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
535	return(ret);
536	}
537
538int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c)
539{
540	return remove_session_lock(ctx, c, 1);
541}
542
543static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck)
544	{
545	SSL_SESSION *r;
546	int ret=0;
547
548	if ((c != NULL) && (c->session_id_length != 0))
549		{
550		if(lck) CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
551		if ((r = (SSL_SESSION *)lh_retrieve(ctx->sessions,c)) == c)
552			{
553			ret=1;
554			r=(SSL_SESSION *)lh_delete(ctx->sessions,c);
555			SSL_SESSION_list_remove(ctx,c);
556			}
557
558		if(lck) CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
559
560		if (ret)
561			{
562			r->not_resumable=1;
563			if (ctx->remove_session_cb != NULL)
564				ctx->remove_session_cb(ctx,r);
565			SSL_SESSION_free(r);
566			}
567		}
568	else
569		ret=0;
570	return(ret);
571	}
572
573void SSL_SESSION_free(SSL_SESSION *ss)
574	{
575	int i;
576
577	if(ss == NULL)
578	    return;
579
580	i=CRYPTO_add(&ss->references,-1,CRYPTO_LOCK_SSL_SESSION);
581#ifdef REF_PRINT
582	REF_PRINT("SSL_SESSION",ss);
583#endif
584	if (i > 0) return;
585#ifdef REF_CHECK
586	if (i < 0)
587		{
588		fprintf(stderr,"SSL_SESSION_free, bad reference count\n");
589		abort(); /* ok */
590		}
591#endif
592
593	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
594
595	OPENSSL_cleanse(ss->key_arg,sizeof ss->key_arg);
596	OPENSSL_cleanse(ss->master_key,sizeof ss->master_key);
597	OPENSSL_cleanse(ss->session_id,sizeof ss->session_id);
598	if (ss->sess_cert != NULL) ssl_sess_cert_free(ss->sess_cert);
599	if (ss->peer != NULL) X509_free(ss->peer);
600	if (ss->ciphers != NULL) sk_SSL_CIPHER_free(ss->ciphers);
601#ifndef OPENSSL_NO_TLSEXT
602	if (ss->tlsext_hostname != NULL) OPENSSL_free(ss->tlsext_hostname);
603	if (ss->tlsext_tick != NULL) OPENSSL_free(ss->tlsext_tick);
604#endif
605	OPENSSL_cleanse(ss,sizeof(*ss));
606	OPENSSL_free(ss);
607	}
608
609int SSL_set_session(SSL *s, SSL_SESSION *session)
610	{
611	int ret=0;
612	SSL_METHOD *meth;
613
614	if (session != NULL)
615		{
616		meth=s->ctx->method->get_ssl_method(session->ssl_version);
617		if (meth == NULL)
618			meth=s->method->get_ssl_method(session->ssl_version);
619		if (meth == NULL)
620			{
621			SSLerr(SSL_F_SSL_SET_SESSION,SSL_R_UNABLE_TO_FIND_SSL_METHOD);
622			return(0);
623			}
624
625		if (meth != s->method)
626			{
627			if (!SSL_set_ssl_method(s,meth))
628				return(0);
629			if (s->ctx->session_timeout == 0)
630				session->timeout=SSL_get_default_timeout(s);
631			else
632				session->timeout=s->ctx->session_timeout;
633			}
634
635#ifndef OPENSSL_NO_KRB5
636                if (s->kssl_ctx && !s->kssl_ctx->client_princ &&
637                    session->krb5_client_princ_len > 0)
638                {
639                    s->kssl_ctx->client_princ = (char *)OPENSSL_malloc(session->krb5_client_princ_len + 1);
640                    memcpy(s->kssl_ctx->client_princ,session->krb5_client_princ,
641                            session->krb5_client_princ_len);
642                    s->kssl_ctx->client_princ[session->krb5_client_princ_len] = '\0';
643                }
644#endif /* OPENSSL_NO_KRB5 */
645
646		/* CRYPTO_w_lock(CRYPTO_LOCK_SSL);*/
647		CRYPTO_add(&session->references,1,CRYPTO_LOCK_SSL_SESSION);
648		if (s->session != NULL)
649			SSL_SESSION_free(s->session);
650		s->session=session;
651		s->verify_result = s->session->verify_result;
652		/* CRYPTO_w_unlock(CRYPTO_LOCK_SSL);*/
653		ret=1;
654		}
655	else
656		{
657		if (s->session != NULL)
658			{
659			SSL_SESSION_free(s->session);
660			s->session=NULL;
661			}
662
663		meth=s->ctx->method;
664		if (meth != s->method)
665			{
666			if (!SSL_set_ssl_method(s,meth))
667				return(0);
668			}
669		ret=1;
670		}
671	return(ret);
672	}
673
674long SSL_SESSION_set_timeout(SSL_SESSION *s, long t)
675	{
676	if (s == NULL) return(0);
677	s->timeout=t;
678	return(1);
679	}
680
681long SSL_SESSION_get_timeout(const SSL_SESSION *s)
682	{
683	if (s == NULL) return(0);
684	return(s->timeout);
685	}
686
687long SSL_SESSION_get_time(const SSL_SESSION *s)
688	{
689	if (s == NULL) return(0);
690	return(s->time);
691	}
692
693long SSL_SESSION_set_time(SSL_SESSION *s, long t)
694	{
695	if (s == NULL) return(0);
696	s->time=t;
697	return(t);
698	}
699
700long SSL_CTX_set_timeout(SSL_CTX *s, long t)
701	{
702	long l;
703	if (s == NULL) return(0);
704	l=s->session_timeout;
705	s->session_timeout=t;
706	return(l);
707	}
708
709long SSL_CTX_get_timeout(const SSL_CTX *s)
710	{
711	if (s == NULL) return(0);
712	return(s->session_timeout);
713	}
714
715typedef struct timeout_param_st
716	{
717	SSL_CTX *ctx;
718	long time;
719	LHASH *cache;
720	} TIMEOUT_PARAM;
721
722static void timeout(SSL_SESSION *s, TIMEOUT_PARAM *p)
723	{
724	if ((p->time == 0) || (p->time > (s->time+s->timeout))) /* timeout */
725		{
726		/* The reason we don't call SSL_CTX_remove_session() is to
727		 * save on locking overhead */
728		lh_delete(p->cache,s);
729		SSL_SESSION_list_remove(p->ctx,s);
730		s->not_resumable=1;
731		if (p->ctx->remove_session_cb != NULL)
732			p->ctx->remove_session_cb(p->ctx,s);
733		SSL_SESSION_free(s);
734		}
735	}
736
737static IMPLEMENT_LHASH_DOALL_ARG_FN(timeout, SSL_SESSION *, TIMEOUT_PARAM *)
738
739void SSL_CTX_flush_sessions(SSL_CTX *s, long t)
740	{
741	unsigned long i;
742	TIMEOUT_PARAM tp;
743
744	tp.ctx=s;
745	tp.cache=s->sessions;
746	if (tp.cache == NULL) return;
747	tp.time=t;
748	CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
749	i=tp.cache->down_load;
750	tp.cache->down_load=0;
751	lh_doall_arg(tp.cache, LHASH_DOALL_ARG_FN(timeout), &tp);
752	tp.cache->down_load=i;
753	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
754	}
755
756int ssl_clear_bad_session(SSL *s)
757	{
758	if (	(s->session != NULL) &&
759		!(s->shutdown & SSL_SENT_SHUTDOWN) &&
760		!(SSL_in_init(s) || SSL_in_before(s)))
761		{
762		SSL_CTX_remove_session(s->ctx,s->session);
763		return(1);
764		}
765	else
766		return(0);
767	}
768
769/* locked by SSL_CTX in the calling function */
770static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s)
771	{
772	if ((s->next == NULL) || (s->prev == NULL)) return;
773
774	if (s->next == (SSL_SESSION *)&(ctx->session_cache_tail))
775		{ /* last element in list */
776		if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head))
777			{ /* only one element in list */
778			ctx->session_cache_head=NULL;
779			ctx->session_cache_tail=NULL;
780			}
781		else
782			{
783			ctx->session_cache_tail=s->prev;
784			s->prev->next=(SSL_SESSION *)&(ctx->session_cache_tail);
785			}
786		}
787	else
788		{
789		if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head))
790			{ /* first element in list */
791			ctx->session_cache_head=s->next;
792			s->next->prev=(SSL_SESSION *)&(ctx->session_cache_head);
793			}
794		else
795			{ /* middle of list */
796			s->next->prev=s->prev;
797			s->prev->next=s->next;
798			}
799		}
800	s->prev=s->next=NULL;
801	}
802
803static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s)
804	{
805	if ((s->next != NULL) && (s->prev != NULL))
806		SSL_SESSION_list_remove(ctx,s);
807
808	if (ctx->session_cache_head == NULL)
809		{
810		ctx->session_cache_head=s;
811		ctx->session_cache_tail=s;
812		s->prev=(SSL_SESSION *)&(ctx->session_cache_head);
813		s->next=(SSL_SESSION *)&(ctx->session_cache_tail);
814		}
815	else
816		{
817		s->next=ctx->session_cache_head;
818		s->next->prev=s;
819		s->prev=(SSL_SESSION *)&(ctx->session_cache_head);
820		ctx->session_cache_head=s;
821		}
822	}
823
824void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx,
825	int (*cb)(struct ssl_st *ssl,SSL_SESSION *sess))
826	{
827	ctx->new_session_cb=cb;
828	}
829
830int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(SSL *ssl, SSL_SESSION *sess)
831	{
832	return ctx->new_session_cb;
833	}
834
835void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx,
836	void (*cb)(SSL_CTX *ctx,SSL_SESSION *sess))
837	{
838	ctx->remove_session_cb=cb;
839	}
840
841void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(SSL_CTX * ctx,SSL_SESSION *sess)
842	{
843	return ctx->remove_session_cb;
844	}
845
846void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx,
847	SSL_SESSION *(*cb)(struct ssl_st *ssl,
848	         unsigned char *data,int len,int *copy))
849	{
850	ctx->get_session_cb=cb;
851	}
852
853SSL_SESSION * (*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(SSL *ssl,
854	         unsigned char *data,int len,int *copy)
855	{
856	return ctx->get_session_cb;
857	}
858
859void SSL_CTX_set_info_callback(SSL_CTX *ctx,
860	void (*cb)(const SSL *ssl,int type,int val))
861	{
862	ctx->info_callback=cb;
863	}
864
865void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl,int type,int val)
866	{
867	return ctx->info_callback;
868	}
869
870void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx,
871	int (*cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey))
872	{
873	ctx->client_cert_cb=cb;
874	}
875
876int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL * ssl, X509 ** x509 , EVP_PKEY **pkey)
877	{
878	return ctx->client_cert_cb;
879	}
880
881#ifndef OPENSSL_NO_ENGINE
882int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e)
883	{
884	if (!ENGINE_init(e))
885		{
886		SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, ERR_R_ENGINE_LIB);
887		return 0;
888		}
889	if(!ENGINE_get_ssl_client_cert_function(e))
890		{
891		SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, SSL_R_NO_CLIENT_CERT_METHOD);
892		ENGINE_finish(e);
893		return 0;
894		}
895	ctx->client_cert_engine = e;
896	return 1;
897	}
898#endif
899
900void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx,
901	int (*cb)(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len))
902	{
903	ctx->app_gen_cookie_cb=cb;
904	}
905
906void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx,
907	int (*cb)(SSL *ssl, unsigned char *cookie, unsigned int cookie_len))
908	{
909	ctx->app_verify_cookie_cb=cb;
910	}
911
912