Typo.
[openssl.git] / ssl / ssl_sess.c
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 #include "ssl_locl.h"
63
64 static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s);
65 static void SSL_SESSION_list_add(SSL_CTX *ctx,SSL_SESSION *s);
66 static int ssl_session_num=0;
67 static STACK *ssl_session_meth=NULL;
68
69 SSL_SESSION *SSL_get_session(SSL *ssl)
70         {
71         return(ssl->session);
72         }
73
74 int SSL_SESSION_get_ex_new_index(long argl, char *argp, int (*new_func)(),
75              int (*dup_func)(), void (*free_func)())
76         {
77         ssl_session_num++;
78         return(CRYPTO_get_ex_new_index(ssl_session_num-1,
79                 &ssl_session_meth,
80                 argl,argp,new_func,dup_func,free_func));
81         }
82
83 int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg)
84         {
85         return(CRYPTO_set_ex_data(&s->ex_data,idx,arg));
86         }
87
88 void *SSL_SESSION_get_ex_data(SSL_SESSION *s, int idx)
89         {
90         return(CRYPTO_get_ex_data(&s->ex_data,idx));
91         }
92
93 SSL_SESSION *SSL_SESSION_new(void)
94         {
95         SSL_SESSION *ss;
96
97         ss=(SSL_SESSION *)Malloc(sizeof(SSL_SESSION));
98         if (ss == NULL)
99                 {
100                 SSLerr(SSL_F_SSL_SESSION_NEW,ERR_R_MALLOC_FAILURE);
101                 return(0);
102                 }
103         memset(ss,0,sizeof(SSL_SESSION));
104
105         ss->references=1;
106         ss->timeout=60*5+4; /* 5 minute timeout by default */
107         ss->time=time(NULL);
108         ss->prev=NULL;
109         ss->next=NULL;
110         ss->compress_meth=0;
111         CRYPTO_new_ex_data(ssl_session_meth,(char *)ss,&ss->ex_data);
112         return(ss);
113         }
114
115 int ssl_get_new_session(SSL *s, int session)
116         {
117         SSL_SESSION *ss=NULL;
118
119         if ((ss=SSL_SESSION_new()) == NULL) return(0);
120
121         /* If the context has a default timeout, use it */
122         if (s->ctx->session_timeout == 0)
123                 ss->timeout=SSL_get_default_timeout(s);
124         else
125                 ss->timeout=s->ctx->session_timeout;
126
127         if (s->session != NULL)
128                 {
129                 SSL_SESSION_free(s->session);
130                 s->session=NULL;
131                 }
132
133         if (session)
134                 {
135                 if (s->version == SSL2_VERSION)
136                         {
137                         ss->ssl_version=SSL2_VERSION;
138                         ss->session_id_length=SSL2_SSL_SESSION_ID_LENGTH;
139                         }
140                 else if (s->version == SSL3_VERSION)
141                         {
142                         ss->ssl_version=SSL3_VERSION;
143                         ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
144                         }
145                 else if (s->version == TLS1_VERSION)
146                         {
147                         ss->ssl_version=TLS1_VERSION;
148                         ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
149                         }
150                 else
151                         {
152                         SSLerr(SSL_F_SSL_GET_NEW_SESSION,SSL_R_UNSUPPORTED_SSL_VERSION);
153                         SSL_SESSION_free(ss);
154                         return(0);
155                         }
156
157                 for (;;)
158                         {
159                         SSL_SESSION *r;
160
161                         RAND_bytes(ss->session_id,ss->session_id_length);
162                         CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
163                         r=(SSL_SESSION *)lh_retrieve(s->ctx->sessions,
164                                 (char *)ss);
165                         CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
166                         if (r == NULL) break;
167                         /* else - woops a session_id match */
168                         }
169                 }
170         else
171                 {
172                 ss->session_id_length=0;
173                 }
174
175         memcpy(ss->sid_ctx,s->sid_ctx,s->sid_ctx_length);
176         ss->sid_ctx_length=s->sid_ctx_length;
177         s->session=ss;
178         ss->ssl_version=s->version;
179
180         return(1);
181         }
182
183 int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len)
184         {
185         SSL_SESSION *ret=NULL,data;
186         int copy=1;
187
188         /* conn_init();*/
189         data.ssl_version=s->version;
190         data.session_id_length=len;
191         if (len > SSL_MAX_SSL_SESSION_ID_LENGTH)
192                 return(0);
193         memcpy(data.session_id,session_id,len);
194
195         if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
196                 {
197                 CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
198                 ret=(SSL_SESSION *)lh_retrieve(s->ctx->sessions,(char *)&data);
199                 CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
200                 }
201
202         if (ret == NULL)
203                 {
204                 s->ctx->stats.sess_miss++;
205                 ret=NULL;
206                 if (s->ctx->get_session_cb != NULL
207                     && (ret=s->ctx->get_session_cb(s,session_id,len,&copy))
208                        != NULL)
209                         {
210                         s->ctx->stats.sess_cb_hit++;
211
212                         /* The following should not return 1, otherwise,
213                          * things are very strange */
214                         SSL_CTX_add_session(s->ctx,ret);
215                         }
216                 if (ret == NULL) return(0);
217                 }
218
219         if((s->verify_mode&SSL_VERIFY_PEER)
220            && (!s->sid_ctx_length || ret->sid_ctx_length != s->sid_ctx_length
221                || memcmp(ret->sid_ctx,s->sid_ctx,ret->sid_ctx_length)))
222             {
223             SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
224             return 0;
225             }
226
227         /* auto free it */
228         if (!copy)
229             SSL_SESSION_free(ret);
230
231         if (ret->cipher == NULL)
232                 {
233                 unsigned char buf[5],*p;
234                 unsigned long l;
235
236                 p=buf;
237                 l=ret->cipher_id;
238                 l2n(l,p);
239                 if ((ret->ssl_version>>8) == SSL3_VERSION_MAJOR)
240                         ret->cipher=ssl_get_cipher_by_char(s,&(buf[2]));
241                 else 
242                         ret->cipher=ssl_get_cipher_by_char(s,&(buf[1]));
243                 if (ret->cipher == NULL)
244                         return(0);
245                 }
246
247         /* If a thread got the session, then 'swaped', and another got
248          * it and then due to a time-out decided to 'Free' it we could
249          * be in trouble.  So I'll increment it now, then double decrement
250          * later - am I speaking rubbish?. */
251         CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION);
252
253         if ((long)(ret->time+ret->timeout) < (long)time(NULL)) /* timeout */
254                 {
255                 s->ctx->stats.sess_timeout++;
256                 /* remove it from the cache */
257                 SSL_CTX_remove_session(s->ctx,ret);
258                 SSL_SESSION_free(ret);          /* again to actually Free it */
259                 return(0);
260                 }
261
262         s->ctx->stats.sess_hit++;
263
264         /* ret->time=time(NULL); */ /* rezero timeout? */
265         /* again, just leave the session 
266          * if it is the same session, we have just incremented and
267          * then decremented the reference count :-) */
268         if (s->session != NULL)
269                 SSL_SESSION_free(s->session);
270         s->session=ret;
271         return(1);
272         }
273
274 int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c)
275         {
276         int ret=0;
277         SSL_SESSION *s;
278
279         /* conn_init(); */
280         CRYPTO_add(&c->references,1,CRYPTO_LOCK_SSL_SESSION);
281
282         CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
283         s=(SSL_SESSION *)lh_insert(ctx->sessions,(char *)c);
284         
285         /* Put on the end of the queue unless it is already in the cache */
286         if (s == NULL)
287                 SSL_SESSION_list_add(ctx,c);
288
289         /* If the same session if is being 're-added', Free the old
290          * one when the last person stops using it.
291          * This will also work if it is alread in the cache.
292          * The references will go up and then down :-) */
293         if (s != NULL)
294                 {
295                 SSL_SESSION_free(s);
296                 ret=0;
297                 }
298         else
299                 {
300                 ret=1;
301
302                 if (SSL_CTX_sess_get_cache_size(ctx) > 0)
303                         {
304                         while (SSL_CTX_sess_number(ctx) >
305                                 SSL_CTX_sess_get_cache_size(ctx))
306                                 {
307                                 if (!SSL_CTX_remove_session(ctx,
308                                         ctx->session_cache_tail))
309                                         break;
310                                 else
311                                         ctx->stats.sess_cache_full++;
312                                 }
313                         }
314                 }
315         CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
316         return(ret);
317         }
318
319 int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c)
320         {
321         SSL_SESSION *r;
322         int ret=0;
323
324         if ((c != NULL) && (c->session_id_length != 0))
325                 {
326                 CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
327                 r=(SSL_SESSION *)lh_delete(ctx->sessions,(char *)c);
328                 if (r != NULL)
329                         {
330                         ret=1;
331                         SSL_SESSION_list_remove(ctx,c);
332                         }
333
334                 CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
335
336                 if (ret)
337                         {
338                         r->not_resumable=1;
339                         if (ctx->remove_session_cb != NULL)
340                                 ctx->remove_session_cb(ctx,r);
341                         SSL_SESSION_free(r);
342                         }
343                 }
344         else
345                 ret=0;
346         return(ret);
347         }
348
349 void SSL_SESSION_free(SSL_SESSION *ss)
350         {
351         int i;
352
353         if(ss == NULL)
354             return;
355
356         i=CRYPTO_add(&ss->references,-1,CRYPTO_LOCK_SSL_SESSION);
357 #ifdef REF_PRINT
358         REF_PRINT("SSL_SESSION",ss);
359 #endif
360         if (i > 0) return;
361 #ifdef REF_CHECK
362         if (i < 0)
363                 {
364                 fprintf(stderr,"SSL_SESSION_free, bad reference count\n");
365                 abort(); /* ok */
366                 }
367 #endif
368
369         CRYPTO_free_ex_data(ssl_session_meth,(char *)ss,&ss->ex_data);
370
371         memset(ss->key_arg,0,SSL_MAX_KEY_ARG_LENGTH);
372         memset(ss->master_key,0,SSL_MAX_MASTER_KEY_LENGTH);
373         memset(ss->session_id,0,SSL_MAX_SSL_SESSION_ID_LENGTH);
374         if (ss->cert != NULL) ssl_cert_free(ss->cert);
375         if (ss->peer != NULL) X509_free(ss->peer);
376         if (ss->ciphers != NULL) sk_SSL_CIPHER_free(ss->ciphers);
377         memset(ss,0,sizeof(*ss));
378         Free(ss);
379         }
380
381 int SSL_set_session(SSL *s, SSL_SESSION *session)
382         {
383         int ret=0;
384         SSL_METHOD *meth;
385
386         if (session != NULL)
387                 {
388                 meth=s->ctx->method->get_ssl_method(session->ssl_version);
389                 if (meth == NULL)
390                         meth=s->method->get_ssl_method(session->ssl_version);
391                 if (meth == NULL)
392                         {
393                         SSLerr(SSL_F_SSL_SET_SESSION,SSL_R_UNABLE_TO_FIND_SSL_METHOD);
394                         return(0);
395                         }
396
397                 if (meth != s->method)
398                         {
399                         if (!SSL_set_ssl_method(s,meth))
400                                 return(0);
401                         if (s->ctx->session_timeout == 0)
402                                 session->timeout=SSL_get_default_timeout(s);
403                         else
404                                 session->timeout=s->ctx->session_timeout;
405                         }
406
407                 /* CRYPTO_w_lock(CRYPTO_LOCK_SSL);*/
408                 CRYPTO_add(&session->references,1,CRYPTO_LOCK_SSL_SESSION);
409                 if (s->session != NULL)
410                         SSL_SESSION_free(s->session);
411                 s->session=session;
412                 /* CRYPTO_w_unlock(CRYPTO_LOCK_SSL);*/
413                 ret=1;
414                 }
415         else
416                 {
417                 if (s->session != NULL)
418                         {
419                         SSL_SESSION_free(s->session);
420                         s->session=NULL;
421                         }
422
423                 meth=s->ctx->method;
424                 if (meth != s->method)
425                         {
426                         if (!SSL_set_ssl_method(s,meth))
427                                 return(0);
428                         }
429                 ret=1;
430                 }
431         return(ret);
432         }
433
434 long SSL_SESSION_set_timeout(SSL_SESSION *s, long t)
435         {
436         if (s == NULL) return(0);
437         s->timeout=t;
438         return(1);
439         }
440
441 long SSL_SESSION_get_timeout(SSL_SESSION *s)
442         {
443         if (s == NULL) return(0);
444         return(s->timeout);
445         }
446
447 long SSL_SESSION_get_time(SSL_SESSION *s)
448         {
449         if (s == NULL) return(0);
450         return(s->time);
451         }
452
453 long SSL_SESSION_set_time(SSL_SESSION *s, long t)
454         {
455         if (s == NULL) return(0);
456         s->time=t;
457         return(t);
458         }
459
460 long SSL_CTX_set_timeout(SSL_CTX *s, long t)
461         {
462         long l;
463         if (s == NULL) return(0);
464         l=s->session_timeout;
465         s->session_timeout=t;
466         return(l);
467         }
468
469 long SSL_CTX_get_timeout(SSL_CTX *s)
470         {
471         if (s == NULL) return(0);
472         return(s->session_timeout);
473         }
474
475 typedef struct timeout_param_st
476         {
477         SSL_CTX *ctx;
478         long time;
479         LHASH *cache;
480         } TIMEOUT_PARAM;
481
482 static void timeout(SSL_SESSION *s, TIMEOUT_PARAM *p)
483         {
484         if ((p->time == 0) || (p->time > (s->time+s->timeout))) /* timeout */
485                 {
486                 /* The reason we don't call SSL_CTX_remove_session() is to
487                  * save on locking overhead */
488                 lh_delete(p->cache,(char *)s);
489                 SSL_SESSION_list_remove(p->ctx,s);
490                 s->not_resumable=1;
491                 if (p->ctx->remove_session_cb != NULL)
492                         p->ctx->remove_session_cb(p->ctx,s);
493                 SSL_SESSION_free(s);
494                 }
495         }
496
497 void SSL_CTX_flush_sessions(SSL_CTX *s, long t)
498         {
499         unsigned long i;
500         TIMEOUT_PARAM tp;
501
502         tp.ctx=s;
503         tp.cache=s->sessions;
504         if (tp.cache == NULL) return;
505         tp.time=t;
506         CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
507         i=tp.cache->down_load;
508         tp.cache->down_load=0;
509         lh_doall_arg(tp.cache,(void (*)())timeout,(char *)&tp);
510         tp.cache->down_load=i;
511         CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
512         }
513
514 int ssl_clear_bad_session(SSL *s)
515         {
516         if (    (s->session != NULL) &&
517                 !(s->shutdown & SSL_SENT_SHUTDOWN) &&
518                 !(SSL_in_init(s) || SSL_in_before(s)))
519                 {
520                 SSL_CTX_remove_session(s->ctx,s->session);
521                 return(1);
522                 }
523         else
524                 return(0);
525         }
526
527 /* locked by SSL_CTX in the calling function */
528 static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s)
529         {
530         if ((s->next == NULL) || (s->prev == NULL)) return;
531
532         if (s->next == (SSL_SESSION *)&(ctx->session_cache_tail))
533                 { /* last element in list */
534                 if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head))
535                         { /* only one element in list */
536                         ctx->session_cache_head=NULL;
537                         ctx->session_cache_tail=NULL;
538                         }
539                 else
540                         {
541                         ctx->session_cache_tail=s->prev;
542                         s->prev->next=(SSL_SESSION *)&(ctx->session_cache_tail);
543                         }
544                 }
545         else
546                 {
547                 if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head))
548                         { /* first element in list */
549                         ctx->session_cache_head=s->next;
550                         s->next->prev=(SSL_SESSION *)&(ctx->session_cache_head);
551                         }
552                 else
553                         { /* middle of list */
554                         s->next->prev=s->prev;
555                         s->prev->next=s->next;
556                         }
557                 }
558         s->prev=s->next=NULL;
559         }
560
561 static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s)
562         {
563         if ((s->next != NULL) && (s->prev != NULL))
564                 SSL_SESSION_list_remove(ctx,s);
565
566         if (ctx->session_cache_head == NULL)
567                 {
568                 ctx->session_cache_head=s;
569                 ctx->session_cache_tail=s;
570                 s->prev=(SSL_SESSION *)&(ctx->session_cache_head);
571                 s->next=(SSL_SESSION *)&(ctx->session_cache_tail);
572                 }
573         else
574                 {
575                 s->next=ctx->session_cache_head;
576                 s->next->prev=s;
577                 s->prev=(SSL_SESSION *)&(ctx->session_cache_head);
578                 ctx->session_cache_head=s;
579                 }
580         }
581