diff options
Diffstat (limited to 'src/lib/libssl/ssl_sess.c')
| -rw-r--r-- | src/lib/libssl/ssl_sess.c | 160 |
1 files changed, 112 insertions, 48 deletions
diff --git a/src/lib/libssl/ssl_sess.c b/src/lib/libssl/ssl_sess.c index 8e5d8a0972..ad40fadd02 100644 --- a/src/lib/libssl/ssl_sess.c +++ b/src/lib/libssl/ssl_sess.c | |||
| @@ -218,6 +218,9 @@ SSL_SESSION *SSL_SESSION_new(void) | |||
| 218 | ss->psk_identity_hint=NULL; | 218 | ss->psk_identity_hint=NULL; |
| 219 | ss->psk_identity=NULL; | 219 | ss->psk_identity=NULL; |
| 220 | #endif | 220 | #endif |
| 221 | #ifndef OPENSSL_NO_SRP | ||
| 222 | ss->srp_username=NULL; | ||
| 223 | #endif | ||
| 221 | return(ss); | 224 | return(ss); |
| 222 | } | 225 | } |
| 223 | 226 | ||
| @@ -228,6 +231,11 @@ const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len) | |||
| 228 | return s->session_id; | 231 | return s->session_id; |
| 229 | } | 232 | } |
| 230 | 233 | ||
| 234 | unsigned int SSL_SESSION_get_compress_id(const SSL_SESSION *s) | ||
| 235 | { | ||
| 236 | return s->compress_meth; | ||
| 237 | } | ||
| 238 | |||
| 231 | /* Even with SSLv2, we have 16 bytes (128 bits) of session ID space. SSLv3/TLSv1 | 239 | /* Even with SSLv2, we have 16 bytes (128 bits) of session ID space. SSLv3/TLSv1 |
| 232 | * has 32 bytes (256 bits). As such, filling the ID with random gunk repeatedly | 240 | * has 32 bytes (256 bits). As such, filling the ID with random gunk repeatedly |
| 233 | * until we have no conflict is going to complete in one iteration pretty much | 241 | * until we have no conflict is going to complete in one iteration pretty much |
| @@ -300,6 +308,16 @@ int ssl_get_new_session(SSL *s, int session) | |||
| 300 | ss->ssl_version=TLS1_VERSION; | 308 | ss->ssl_version=TLS1_VERSION; |
| 301 | ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH; | 309 | ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH; |
| 302 | } | 310 | } |
| 311 | else if (s->version == TLS1_1_VERSION) | ||
| 312 | { | ||
| 313 | ss->ssl_version=TLS1_1_VERSION; | ||
| 314 | ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH; | ||
| 315 | } | ||
| 316 | else if (s->version == TLS1_2_VERSION) | ||
| 317 | { | ||
| 318 | ss->ssl_version=TLS1_2_VERSION; | ||
| 319 | ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH; | ||
| 320 | } | ||
| 303 | else if (s->version == DTLS1_BAD_VER) | 321 | else if (s->version == DTLS1_BAD_VER) |
| 304 | { | 322 | { |
| 305 | ss->ssl_version=DTLS1_BAD_VER; | 323 | ss->ssl_version=DTLS1_BAD_VER; |
| @@ -423,6 +441,25 @@ int ssl_get_new_session(SSL *s, int session) | |||
| 423 | return(1); | 441 | return(1); |
| 424 | } | 442 | } |
| 425 | 443 | ||
| 444 | /* ssl_get_prev attempts to find an SSL_SESSION to be used to resume this | ||
| 445 | * connection. It is only called by servers. | ||
| 446 | * | ||
| 447 | * session_id: points at the session ID in the ClientHello. This code will | ||
| 448 | * read past the end of this in order to parse out the session ticket | ||
| 449 | * extension, if any. | ||
| 450 | * len: the length of the session ID. | ||
| 451 | * limit: a pointer to the first byte after the ClientHello. | ||
| 452 | * | ||
| 453 | * Returns: | ||
| 454 | * -1: error | ||
| 455 | * 0: a session may have been found. | ||
| 456 | * | ||
| 457 | * Side effects: | ||
| 458 | * - If a session is found then s->session is pointed at it (after freeing an | ||
| 459 | * existing session if need be) and s->verify_result is set from the session. | ||
| 460 | * - Both for new and resumed sessions, s->tlsext_ticket_expected is set to 1 | ||
| 461 | * if the server should issue a new session ticket (to 0 otherwise). | ||
| 462 | */ | ||
| 426 | int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len, | 463 | int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len, |
| 427 | const unsigned char *limit) | 464 | const unsigned char *limit) |
| 428 | { | 465 | { |
| @@ -430,27 +467,39 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len, | |||
| 430 | 467 | ||
| 431 | SSL_SESSION *ret=NULL; | 468 | SSL_SESSION *ret=NULL; |
| 432 | int fatal = 0; | 469 | int fatal = 0; |
| 470 | int try_session_cache = 1; | ||
| 433 | #ifndef OPENSSL_NO_TLSEXT | 471 | #ifndef OPENSSL_NO_TLSEXT |
| 434 | int r; | 472 | int r; |
| 435 | #endif | 473 | #endif |
| 436 | 474 | ||
| 437 | if (len > SSL_MAX_SSL_SESSION_ID_LENGTH) | 475 | if (len > SSL_MAX_SSL_SESSION_ID_LENGTH) |
| 438 | goto err; | 476 | goto err; |
| 477 | |||
| 478 | if (len == 0) | ||
| 479 | try_session_cache = 0; | ||
| 480 | |||
| 439 | #ifndef OPENSSL_NO_TLSEXT | 481 | #ifndef OPENSSL_NO_TLSEXT |
| 440 | r = tls1_process_ticket(s, session_id, len, limit, &ret); | 482 | r = tls1_process_ticket(s, session_id, len, limit, &ret); /* sets s->tlsext_ticket_expected */ |
| 441 | if (r == -1) | 483 | switch (r) |
| 442 | { | 484 | { |
| 485 | case -1: /* Error during processing */ | ||
| 443 | fatal = 1; | 486 | fatal = 1; |
| 444 | goto err; | 487 | goto err; |
| 488 | case 0: /* No ticket found */ | ||
| 489 | case 1: /* Zero length ticket found */ | ||
| 490 | break; /* Ok to carry on processing session id. */ | ||
| 491 | case 2: /* Ticket found but not decrypted. */ | ||
| 492 | case 3: /* Ticket decrypted, *ret has been set. */ | ||
| 493 | try_session_cache = 0; | ||
| 494 | break; | ||
| 495 | default: | ||
| 496 | abort(); | ||
| 445 | } | 497 | } |
| 446 | else if (r == 0 || (!ret && !len)) | ||
| 447 | goto err; | ||
| 448 | else if (!ret && !(s->session_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) | ||
| 449 | #else | ||
| 450 | if (len == 0) | ||
| 451 | goto err; | ||
| 452 | if (!(s->session_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) | ||
| 453 | #endif | 498 | #endif |
| 499 | |||
| 500 | if (try_session_cache && | ||
| 501 | ret == NULL && | ||
| 502 | !(s->session_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) | ||
| 454 | { | 503 | { |
| 455 | SSL_SESSION data; | 504 | SSL_SESSION data; |
| 456 | data.ssl_version=s->version; | 505 | data.ssl_version=s->version; |
| @@ -461,20 +510,22 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len, | |||
| 461 | CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); | 510 | CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); |
| 462 | ret=lh_SSL_SESSION_retrieve(s->session_ctx->sessions,&data); | 511 | ret=lh_SSL_SESSION_retrieve(s->session_ctx->sessions,&data); |
| 463 | if (ret != NULL) | 512 | if (ret != NULL) |
| 464 | /* don't allow other threads to steal it: */ | 513 | { |
| 465 | CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION); | 514 | /* don't allow other threads to steal it: */ |
| 515 | CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION); | ||
| 516 | } | ||
| 466 | CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); | 517 | CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); |
| 518 | if (ret == NULL) | ||
| 519 | s->session_ctx->stats.sess_miss++; | ||
| 467 | } | 520 | } |
| 468 | 521 | ||
| 469 | if (ret == NULL) | 522 | if (try_session_cache && |
| 523 | ret == NULL && | ||
| 524 | s->session_ctx->get_session_cb != NULL) | ||
| 470 | { | 525 | { |
| 471 | int copy=1; | 526 | int copy=1; |
| 472 | 527 | ||
| 473 | s->session_ctx->stats.sess_miss++; | 528 | if ((ret=s->session_ctx->get_session_cb(s,session_id,len,©))) |
| 474 | ret=NULL; | ||
| 475 | if (s->session_ctx->get_session_cb != NULL | ||
| 476 | && (ret=s->session_ctx->get_session_cb(s,session_id,len,©)) | ||
| 477 | != NULL) | ||
| 478 | { | 529 | { |
| 479 | s->session_ctx->stats.sess_cb_hit++; | 530 | s->session_ctx->stats.sess_cb_hit++; |
| 480 | 531 | ||
| @@ -493,23 +544,18 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len, | |||
| 493 | * things are very strange */ | 544 | * things are very strange */ |
| 494 | SSL_CTX_add_session(s->session_ctx,ret); | 545 | SSL_CTX_add_session(s->session_ctx,ret); |
| 495 | } | 546 | } |
| 496 | if (ret == NULL) | ||
| 497 | goto err; | ||
| 498 | } | 547 | } |
| 499 | 548 | ||
| 500 | /* Now ret is non-NULL, and we own one of its reference counts. */ | 549 | if (ret == NULL) |
| 550 | goto err; | ||
| 551 | |||
| 552 | /* Now ret is non-NULL and we own one of its reference counts. */ | ||
| 501 | 553 | ||
| 502 | if (ret->sid_ctx_length != s->sid_ctx_length | 554 | if (ret->sid_ctx_length != s->sid_ctx_length |
| 503 | || memcmp(ret->sid_ctx,s->sid_ctx,ret->sid_ctx_length)) | 555 | || memcmp(ret->sid_ctx,s->sid_ctx,ret->sid_ctx_length)) |
| 504 | { | 556 | { |
| 505 | /* We've found the session named by the client, but we don't | 557 | /* We have the session requested by the client, but we don't |
| 506 | * want to use it in this context. */ | 558 | * want to use it in this context. */ |
| 507 | |||
| 508 | #if 0 /* The client cannot always know when a session is not appropriate, | ||
| 509 | * so we shouldn't generate an error message. */ | ||
| 510 | |||
| 511 | SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT); | ||
| 512 | #endif | ||
| 513 | goto err; /* treat like cache miss */ | 559 | goto err; /* treat like cache miss */ |
| 514 | } | 560 | } |
| 515 | 561 | ||
| @@ -546,39 +592,38 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len, | |||
| 546 | goto err; | 592 | goto err; |
| 547 | } | 593 | } |
| 548 | 594 | ||
| 549 | |||
| 550 | #if 0 /* This is way too late. */ | ||
| 551 | |||
| 552 | /* If a thread got the session, then 'swaped', and another got | ||
| 553 | * it and then due to a time-out decided to 'OPENSSL_free' it we could | ||
| 554 | * be in trouble. So I'll increment it now, then double decrement | ||
| 555 | * later - am I speaking rubbish?. */ | ||
| 556 | CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION); | ||
| 557 | #endif | ||
| 558 | |||
| 559 | if (ret->timeout < (long)(time(NULL) - ret->time)) /* timeout */ | 595 | if (ret->timeout < (long)(time(NULL) - ret->time)) /* timeout */ |
| 560 | { | 596 | { |
| 561 | s->session_ctx->stats.sess_timeout++; | 597 | s->session_ctx->stats.sess_timeout++; |
| 562 | /* remove it from the cache */ | 598 | if (try_session_cache) |
| 563 | SSL_CTX_remove_session(s->session_ctx,ret); | 599 | { |
| 600 | /* session was from the cache, so remove it */ | ||
| 601 | SSL_CTX_remove_session(s->session_ctx,ret); | ||
| 602 | } | ||
| 564 | goto err; | 603 | goto err; |
| 565 | } | 604 | } |
| 566 | 605 | ||
| 567 | s->session_ctx->stats.sess_hit++; | 606 | s->session_ctx->stats.sess_hit++; |
| 568 | 607 | ||
| 569 | /* ret->time=time(NULL); */ /* rezero timeout? */ | ||
| 570 | /* again, just leave the session | ||
| 571 | * if it is the same session, we have just incremented and | ||
| 572 | * then decremented the reference count :-) */ | ||
| 573 | if (s->session != NULL) | 608 | if (s->session != NULL) |
| 574 | SSL_SESSION_free(s->session); | 609 | SSL_SESSION_free(s->session); |
| 575 | s->session=ret; | 610 | s->session=ret; |
| 576 | s->verify_result = s->session->verify_result; | 611 | s->verify_result = s->session->verify_result; |
| 577 | return(1); | 612 | return 1; |
| 578 | 613 | ||
| 579 | err: | 614 | err: |
| 580 | if (ret != NULL) | 615 | if (ret != NULL) |
| 616 | { | ||
| 581 | SSL_SESSION_free(ret); | 617 | SSL_SESSION_free(ret); |
| 618 | #ifndef OPENSSL_NO_TLSEXT | ||
| 619 | if (!try_session_cache) | ||
| 620 | { | ||
| 621 | /* The session was from a ticket, so we should | ||
| 622 | * issue a ticket for the new session */ | ||
| 623 | s->tlsext_ticket_expected = 1; | ||
| 624 | } | ||
| 625 | #endif | ||
| 626 | } | ||
| 582 | if (fatal) | 627 | if (fatal) |
| 583 | return -1; | 628 | return -1; |
| 584 | else | 629 | else |
| @@ -729,6 +774,10 @@ void SSL_SESSION_free(SSL_SESSION *ss) | |||
| 729 | if (ss->psk_identity != NULL) | 774 | if (ss->psk_identity != NULL) |
| 730 | OPENSSL_free(ss->psk_identity); | 775 | OPENSSL_free(ss->psk_identity); |
| 731 | #endif | 776 | #endif |
| 777 | #ifndef OPENSSL_NO_SRP | ||
| 778 | if (ss->srp_username != NULL) | ||
| 779 | OPENSSL_free(ss->srp_username); | ||
| 780 | #endif | ||
| 732 | OPENSSL_cleanse(ss,sizeof(*ss)); | 781 | OPENSSL_cleanse(ss,sizeof(*ss)); |
| 733 | OPENSSL_free(ss); | 782 | OPENSSL_free(ss); |
| 734 | } | 783 | } |
| @@ -753,10 +802,6 @@ int SSL_set_session(SSL *s, SSL_SESSION *session) | |||
| 753 | { | 802 | { |
| 754 | if (!SSL_set_ssl_method(s,meth)) | 803 | if (!SSL_set_ssl_method(s,meth)) |
| 755 | return(0); | 804 | return(0); |
| 756 | if (s->ctx->session_timeout == 0) | ||
| 757 | session->timeout=SSL_get_default_timeout(s); | ||
| 758 | else | ||
| 759 | session->timeout=s->ctx->session_timeout; | ||
| 760 | } | 805 | } |
| 761 | 806 | ||
| 762 | #ifndef OPENSSL_NO_KRB5 | 807 | #ifndef OPENSSL_NO_KRB5 |
| @@ -824,6 +869,25 @@ long SSL_SESSION_set_time(SSL_SESSION *s, long t) | |||
| 824 | return(t); | 869 | return(t); |
| 825 | } | 870 | } |
| 826 | 871 | ||
| 872 | X509 *SSL_SESSION_get0_peer(SSL_SESSION *s) | ||
| 873 | { | ||
| 874 | return s->peer; | ||
| 875 | } | ||
| 876 | |||
| 877 | int SSL_SESSION_set1_id_context(SSL_SESSION *s,const unsigned char *sid_ctx, | ||
| 878 | unsigned int sid_ctx_len) | ||
| 879 | { | ||
| 880 | if(sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) | ||
| 881 | { | ||
| 882 | SSLerr(SSL_F_SSL_SESSION_SET1_ID_CONTEXT,SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); | ||
| 883 | return 0; | ||
| 884 | } | ||
| 885 | s->sid_ctx_length=sid_ctx_len; | ||
| 886 | memcpy(s->sid_ctx,sid_ctx,sid_ctx_len); | ||
| 887 | |||
| 888 | return 1; | ||
| 889 | } | ||
| 890 | |||
| 827 | long SSL_CTX_set_timeout(SSL_CTX *s, long t) | 891 | long SSL_CTX_set_timeout(SSL_CTX *s, long t) |
| 828 | { | 892 | { |
| 829 | long l; | 893 | long l; |
