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