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; |