diff options
Diffstat (limited to '')
| -rw-r--r-- | src/lib/libssl/ssl_sess.c | 122 |
1 files changed, 93 insertions, 29 deletions
diff --git a/src/lib/libssl/ssl_sess.c b/src/lib/libssl/ssl_sess.c index 7064262def..6424f775e2 100644 --- a/src/lib/libssl/ssl_sess.c +++ b/src/lib/libssl/ssl_sess.c | |||
| @@ -64,8 +64,6 @@ | |||
| 64 | static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s); | 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); | 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); | 66 | static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck); |
| 67 | static int ssl_session_num=0; | ||
| 68 | static STACK_OF(CRYPTO_EX_DATA_FUNCS) *ssl_session_meth=NULL; | ||
| 69 | 67 | ||
| 70 | SSL_SESSION *SSL_get_session(SSL *ssl) | 68 | SSL_SESSION *SSL_get_session(SSL *ssl) |
| 71 | /* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */ | 69 | /* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */ |
| @@ -91,10 +89,8 @@ SSL_SESSION *SSL_get1_session(SSL *ssl) | |||
| 91 | int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, | 89 | int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, |
| 92 | CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) | 90 | CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) |
| 93 | { | 91 | { |
| 94 | ssl_session_num++; | 92 | return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, argl, argp, |
| 95 | return(CRYPTO_get_ex_new_index(ssl_session_num-1, | 93 | new_func, dup_func, free_func); |
| 96 | &ssl_session_meth, | ||
| 97 | argl,argp,new_func,dup_func,free_func)); | ||
| 98 | } | 94 | } |
| 99 | 95 | ||
| 100 | int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg) | 96 | int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg) |
| @@ -126,15 +122,49 @@ SSL_SESSION *SSL_SESSION_new(void) | |||
| 126 | ss->prev=NULL; | 122 | ss->prev=NULL; |
| 127 | ss->next=NULL; | 123 | ss->next=NULL; |
| 128 | ss->compress_meth=0; | 124 | ss->compress_meth=0; |
| 129 | CRYPTO_new_ex_data(ssl_session_meth,ss,&ss->ex_data); | 125 | CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); |
| 130 | return(ss); | 126 | return(ss); |
| 131 | } | 127 | } |
| 132 | 128 | ||
| 129 | /* Even with SSLv2, we have 16 bytes (128 bits) of session ID space. SSLv3/TLSv1 | ||
| 130 | * has 32 bytes (256 bits). As such, filling the ID with random gunk repeatedly | ||
| 131 | * until we have no conflict is going to complete in one iteration pretty much | ||
| 132 | * "most" of the time (btw: understatement). So, if it takes us 10 iterations | ||
| 133 | * and we still can't avoid a conflict - well that's a reasonable point to call | ||
| 134 | * it quits. Either the RAND code is broken or someone is trying to open roughly | ||
| 135 | * very close to 2^128 (or 2^256) SSL sessions to our server. How you might | ||
| 136 | * store that many sessions is perhaps a more interesting question ... */ | ||
| 137 | |||
| 138 | #define MAX_SESS_ID_ATTEMPTS 10 | ||
| 139 | static int def_generate_session_id(const SSL *ssl, unsigned char *id, | ||
| 140 | unsigned int *id_len) | ||
| 141 | { | ||
| 142 | unsigned int retry = 0; | ||
| 143 | do | ||
| 144 | RAND_pseudo_bytes(id, *id_len); | ||
| 145 | while(SSL_has_matching_session_id(ssl, id, *id_len) && | ||
| 146 | (++retry < MAX_SESS_ID_ATTEMPTS)); | ||
| 147 | if(retry < MAX_SESS_ID_ATTEMPTS) | ||
| 148 | return 1; | ||
| 149 | /* else - woops a session_id match */ | ||
| 150 | /* XXX We should also check the external cache -- | ||
| 151 | * but the probability of a collision is negligible, and | ||
| 152 | * we could not prevent the concurrent creation of sessions | ||
| 153 | * with identical IDs since we currently don't have means | ||
| 154 | * to atomically check whether a session ID already exists | ||
| 155 | * and make a reservation for it if it does not | ||
| 156 | * (this problem applies to the internal cache as well). | ||
| 157 | */ | ||
| 158 | return 0; | ||
| 159 | } | ||
| 160 | |||
| 133 | int ssl_get_new_session(SSL *s, int session) | 161 | int ssl_get_new_session(SSL *s, int session) |
| 134 | { | 162 | { |
| 135 | /* This gets used by clients and servers. */ | 163 | /* This gets used by clients and servers. */ |
| 136 | 164 | ||
| 165 | unsigned int tmp; | ||
| 137 | SSL_SESSION *ss=NULL; | 166 | SSL_SESSION *ss=NULL; |
| 167 | GEN_SESSION_CB cb = def_generate_session_id; | ||
| 138 | 168 | ||
| 139 | if ((ss=SSL_SESSION_new()) == NULL) return(0); | 169 | if ((ss=SSL_SESSION_new()) == NULL) return(0); |
| 140 | 170 | ||
| @@ -173,25 +203,46 @@ int ssl_get_new_session(SSL *s, int session) | |||
| 173 | SSL_SESSION_free(ss); | 203 | SSL_SESSION_free(ss); |
| 174 | return(0); | 204 | return(0); |
| 175 | } | 205 | } |
| 176 | 206 | /* Choose which callback will set the session ID */ | |
| 177 | for (;;) | 207 | CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); |
| 208 | if(s->generate_session_id) | ||
| 209 | cb = s->generate_session_id; | ||
| 210 | else if(s->ctx->generate_session_id) | ||
| 211 | cb = s->ctx->generate_session_id; | ||
| 212 | CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); | ||
| 213 | /* Choose a session ID */ | ||
| 214 | tmp = ss->session_id_length; | ||
| 215 | if(!cb(s, ss->session_id, &tmp)) | ||
| 178 | { | 216 | { |
| 179 | SSL_SESSION *r; | 217 | /* The callback failed */ |
| 180 | 218 | SSLerr(SSL_F_SSL_GET_NEW_SESSION, | |
| 181 | RAND_pseudo_bytes(ss->session_id,ss->session_id_length); | 219 | SSL_R_SSL_SESSION_ID_CALLBACK_FAILED); |
| 182 | CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); | 220 | SSL_SESSION_free(ss); |
| 183 | r=(SSL_SESSION *)lh_retrieve(s->ctx->sessions, ss); | 221 | return(0); |
| 184 | CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); | 222 | } |
| 185 | if (r == NULL) break; | 223 | /* Don't allow the callback to set the session length to zero. |
| 186 | /* else - woops a session_id match */ | 224 | * nor set it higher than it was. */ |
| 187 | /* XXX We should also check the external cache -- | 225 | if(!tmp || (tmp > ss->session_id_length)) |
| 188 | * but the probability of a collision is negligible, and | 226 | { |
| 189 | * we could not prevent the concurrent creation of sessions | 227 | /* The callback set an illegal length */ |
| 190 | * with identical IDs since we currently don't have means | 228 | SSLerr(SSL_F_SSL_GET_NEW_SESSION, |
| 191 | * to atomically check whether a session ID already exists | 229 | SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH); |
| 192 | * and make a reservation for it if it does not | 230 | SSL_SESSION_free(ss); |
| 193 | * (this problem applies to the internal cache as well). | 231 | return(0); |
| 194 | */ | 232 | } |
| 233 | /* If the session length was shrunk and we're SSLv2, pad it */ | ||
| 234 | if((tmp < ss->session_id_length) && (s->version == SSL2_VERSION)) | ||
| 235 | memset(ss->session_id + tmp, 0, ss->session_id_length - tmp); | ||
| 236 | else | ||
| 237 | ss->session_id_length = tmp; | ||
| 238 | /* Finally, check for a conflict */ | ||
| 239 | if(SSL_has_matching_session_id(s, ss->session_id, | ||
| 240 | ss->session_id_length)) | ||
| 241 | { | ||
| 242 | SSLerr(SSL_F_SSL_GET_NEW_SESSION, | ||
| 243 | SSL_R_SSL_SESSION_ID_CONFLICT); | ||
| 244 | SSL_SESSION_free(ss); | ||
| 245 | return(0); | ||
| 195 | } | 246 | } |
| 196 | } | 247 | } |
| 197 | else | 248 | else |
| @@ -423,10 +474,10 @@ static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck) | |||
| 423 | if ((c != NULL) && (c->session_id_length != 0)) | 474 | if ((c != NULL) && (c->session_id_length != 0)) |
| 424 | { | 475 | { |
| 425 | if(lck) CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); | 476 | if(lck) CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); |
| 426 | r=(SSL_SESSION *)lh_delete(ctx->sessions,c); | 477 | if ((r = (SSL_SESSION *)lh_retrieve(ctx->sessions,c)) == c) |
| 427 | if (r != NULL) | ||
| 428 | { | 478 | { |
| 429 | ret=1; | 479 | ret=1; |
| 480 | r=(SSL_SESSION *)lh_delete(ctx->sessions,c); | ||
| 430 | SSL_SESSION_list_remove(ctx,c); | 481 | SSL_SESSION_list_remove(ctx,c); |
| 431 | } | 482 | } |
| 432 | 483 | ||
| @@ -465,7 +516,7 @@ void SSL_SESSION_free(SSL_SESSION *ss) | |||
| 465 | } | 516 | } |
| 466 | #endif | 517 | #endif |
| 467 | 518 | ||
| 468 | CRYPTO_free_ex_data(ssl_session_meth,ss,&ss->ex_data); | 519 | CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); |
| 469 | 520 | ||
| 470 | memset(ss->key_arg,0,SSL_MAX_KEY_ARG_LENGTH); | 521 | memset(ss->key_arg,0,SSL_MAX_KEY_ARG_LENGTH); |
| 471 | memset(ss->master_key,0,SSL_MAX_MASTER_KEY_LENGTH); | 522 | memset(ss->master_key,0,SSL_MAX_MASTER_KEY_LENGTH); |
| @@ -503,6 +554,17 @@ int SSL_set_session(SSL *s, SSL_SESSION *session) | |||
| 503 | session->timeout=s->ctx->session_timeout; | 554 | session->timeout=s->ctx->session_timeout; |
| 504 | } | 555 | } |
| 505 | 556 | ||
| 557 | #ifndef OPENSSL_NO_KRB5 | ||
| 558 | if (s->kssl_ctx && !s->kssl_ctx->client_princ && | ||
| 559 | session->krb5_client_princ_len > 0) | ||
| 560 | { | ||
| 561 | s->kssl_ctx->client_princ = (char *)malloc(session->krb5_client_princ_len + 1); | ||
| 562 | memcpy(s->kssl_ctx->client_princ,session->krb5_client_princ, | ||
| 563 | session->krb5_client_princ_len); | ||
| 564 | s->kssl_ctx->client_princ[session->krb5_client_princ_len] = '\0'; | ||
| 565 | } | ||
| 566 | #endif /* OPENSSL_NO_KRB5 */ | ||
| 567 | |||
| 506 | /* CRYPTO_w_lock(CRYPTO_LOCK_SSL);*/ | 568 | /* CRYPTO_w_lock(CRYPTO_LOCK_SSL);*/ |
| 507 | CRYPTO_add(&session->references,1,CRYPTO_LOCK_SSL_SESSION); | 569 | CRYPTO_add(&session->references,1,CRYPTO_LOCK_SSL_SESSION); |
| 508 | if (s->session != NULL) | 570 | if (s->session != NULL) |
| @@ -594,6 +656,8 @@ static void timeout(SSL_SESSION *s, TIMEOUT_PARAM *p) | |||
| 594 | } | 656 | } |
| 595 | } | 657 | } |
| 596 | 658 | ||
| 659 | static IMPLEMENT_LHASH_DOALL_ARG_FN(timeout, SSL_SESSION *, TIMEOUT_PARAM *) | ||
| 660 | |||
| 597 | void SSL_CTX_flush_sessions(SSL_CTX *s, long t) | 661 | void SSL_CTX_flush_sessions(SSL_CTX *s, long t) |
| 598 | { | 662 | { |
| 599 | unsigned long i; | 663 | unsigned long i; |
| @@ -606,7 +670,7 @@ void SSL_CTX_flush_sessions(SSL_CTX *s, long t) | |||
| 606 | CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); | 670 | CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); |
| 607 | i=tp.cache->down_load; | 671 | i=tp.cache->down_load; |
| 608 | tp.cache->down_load=0; | 672 | tp.cache->down_load=0; |
| 609 | lh_doall_arg(tp.cache,(void (*)())timeout,&tp); | 673 | lh_doall_arg(tp.cache, LHASH_DOALL_ARG_FN(timeout), &tp); |
| 610 | tp.cache->down_load=i; | 674 | tp.cache->down_load=i; |
| 611 | CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); | 675 | CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); |
| 612 | } | 676 | } |
