diff options
Diffstat (limited to 'src/lib/libssl/ssl_sess.c')
| -rw-r--r-- | src/lib/libssl/ssl_sess.c | 89 |
1 files changed, 66 insertions, 23 deletions
diff --git a/src/lib/libssl/ssl_sess.c b/src/lib/libssl/ssl_sess.c index 681499f08a..9e01f72753 100644 --- a/src/lib/libssl/ssl_sess.c +++ b/src/lib/libssl/ssl_sess.c | |||
| @@ -65,15 +65,31 @@ 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; | 67 | static int ssl_session_num=0; |
| 68 | static STACK *ssl_session_meth=NULL; | 68 | static STACK_OF(CRYPTO_EX_DATA_FUNCS) *ssl_session_meth=NULL; |
| 69 | 69 | ||
| 70 | SSL_SESSION *SSL_get_session(SSL *ssl) | 70 | SSL_SESSION *SSL_get_session(SSL *ssl) |
| 71 | /* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */ | ||
| 71 | { | 72 | { |
| 72 | return(ssl->session); | 73 | return(ssl->session); |
| 73 | } | 74 | } |
| 74 | 75 | ||
| 75 | int SSL_SESSION_get_ex_new_index(long argl, char *argp, int (*new_func)(), | 76 | SSL_SESSION *SSL_get1_session(SSL *ssl) |
| 76 | int (*dup_func)(), void (*free_func)()) | 77 | /* variant of SSL_get_session: caller really gets something */ |
| 78 | { | ||
| 79 | SSL_SESSION *sess; | ||
| 80 | /* Need to lock this all up rather than just use CRYPTO_add so that | ||
| 81 | * somebody doesn't free ssl->session between when we check it's | ||
| 82 | * non-null and when we up the reference count. */ | ||
| 83 | CRYPTO_r_lock(CRYPTO_LOCK_SSL_SESSION); | ||
| 84 | sess = ssl->session; | ||
| 85 | if(sess) | ||
| 86 | sess->references++; | ||
| 87 | CRYPTO_r_unlock(CRYPTO_LOCK_SSL_SESSION); | ||
| 88 | return(sess); | ||
| 89 | } | ||
| 90 | |||
| 91 | 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) | ||
| 77 | { | 93 | { |
| 78 | ssl_session_num++; | 94 | ssl_session_num++; |
| 79 | return(CRYPTO_get_ex_new_index(ssl_session_num-1, | 95 | return(CRYPTO_get_ex_new_index(ssl_session_num-1, |
| @@ -103,13 +119,14 @@ SSL_SESSION *SSL_SESSION_new(void) | |||
| 103 | } | 119 | } |
| 104 | memset(ss,0,sizeof(SSL_SESSION)); | 120 | memset(ss,0,sizeof(SSL_SESSION)); |
| 105 | 121 | ||
| 122 | ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */ | ||
| 106 | ss->references=1; | 123 | ss->references=1; |
| 107 | ss->timeout=60*5+4; /* 5 minute timeout by default */ | 124 | ss->timeout=60*5+4; /* 5 minute timeout by default */ |
| 108 | ss->time=time(NULL); | 125 | ss->time=time(NULL); |
| 109 | ss->prev=NULL; | 126 | ss->prev=NULL; |
| 110 | ss->next=NULL; | 127 | ss->next=NULL; |
| 111 | ss->compress_meth=0; | 128 | ss->compress_meth=0; |
| 112 | CRYPTO_new_ex_data(ssl_session_meth,(char *)ss,&ss->ex_data); | 129 | CRYPTO_new_ex_data(ssl_session_meth,ss,&ss->ex_data); |
| 113 | return(ss); | 130 | return(ss); |
| 114 | } | 131 | } |
| 115 | 132 | ||
| @@ -161,15 +178,20 @@ int ssl_get_new_session(SSL *s, int session) | |||
| 161 | { | 178 | { |
| 162 | SSL_SESSION *r; | 179 | SSL_SESSION *r; |
| 163 | 180 | ||
| 164 | RAND_bytes(ss->session_id,ss->session_id_length); | 181 | RAND_pseudo_bytes(ss->session_id,ss->session_id_length); |
| 165 | CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); | 182 | CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); |
| 166 | r=(SSL_SESSION *)lh_retrieve(s->ctx->sessions, | 183 | r=(SSL_SESSION *)lh_retrieve(s->ctx->sessions, ss); |
| 167 | (char *)ss); | ||
| 168 | CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); | 184 | CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); |
| 169 | if (r == NULL) break; | 185 | if (r == NULL) break; |
| 170 | /* else - woops a session_id match */ | 186 | /* else - woops a session_id match */ |
| 171 | /* XXX should also check external cache! | 187 | /* XXX We should also check the external cache -- |
| 172 | * (But the probability of a collision is negligible, anyway...) */ | 188 | * but the probability of a collision is negligible, and |
| 189 | * we could not prevent the concurrent creation of sessions | ||
| 190 | * with identical IDs since we currently don't have means | ||
| 191 | * to atomically check whether a session ID already exists | ||
| 192 | * and make a reservation for it if it does not | ||
| 193 | * (this problem applies to the internal cache as well). | ||
| 194 | */ | ||
| 173 | } | 195 | } |
| 174 | } | 196 | } |
| 175 | else | 197 | else |
| @@ -181,6 +203,7 @@ int ssl_get_new_session(SSL *s, int session) | |||
| 181 | ss->sid_ctx_length=s->sid_ctx_length; | 203 | ss->sid_ctx_length=s->sid_ctx_length; |
| 182 | s->session=ss; | 204 | s->session=ss; |
| 183 | ss->ssl_version=s->version; | 205 | ss->ssl_version=s->version; |
| 206 | ss->verify_result = X509_V_OK; | ||
| 184 | 207 | ||
| 185 | return(1); | 208 | return(1); |
| 186 | } | 209 | } |
| @@ -192,7 +215,6 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len) | |||
| 192 | SSL_SESSION *ret=NULL,data; | 215 | SSL_SESSION *ret=NULL,data; |
| 193 | int fatal = 0; | 216 | int fatal = 0; |
| 194 | 217 | ||
| 195 | /* conn_init();*/ | ||
| 196 | data.ssl_version=s->version; | 218 | data.ssl_version=s->version; |
| 197 | data.session_id_length=len; | 219 | data.session_id_length=len; |
| 198 | if (len > SSL_MAX_SSL_SESSION_ID_LENGTH) | 220 | if (len > SSL_MAX_SSL_SESSION_ID_LENGTH) |
| @@ -202,7 +224,7 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len) | |||
| 202 | if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) | 224 | if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) |
| 203 | { | 225 | { |
| 204 | CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); | 226 | CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); |
| 205 | ret=(SSL_SESSION *)lh_retrieve(s->ctx->sessions,(char *)&data); | 227 | ret=(SSL_SESSION *)lh_retrieve(s->ctx->sessions,&data); |
| 206 | if (ret != NULL) | 228 | if (ret != NULL) |
| 207 | /* don't allow other threads to steal it: */ | 229 | /* don't allow other threads to steal it: */ |
| 208 | CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION); | 230 | CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION); |
| @@ -311,6 +333,7 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len) | |||
| 311 | if (s->session != NULL) | 333 | if (s->session != NULL) |
| 312 | SSL_SESSION_free(s->session); | 334 | SSL_SESSION_free(s->session); |
| 313 | s->session=ret; | 335 | s->session=ret; |
| 336 | s->verify_result = s->session->verify_result; | ||
| 314 | return(1); | 337 | return(1); |
| 315 | 338 | ||
| 316 | err: | 339 | err: |
| @@ -327,27 +350,47 @@ int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) | |||
| 327 | int ret=0; | 350 | int ret=0; |
| 328 | SSL_SESSION *s; | 351 | SSL_SESSION *s; |
| 329 | 352 | ||
| 330 | /* conn_init(); */ | 353 | /* add just 1 reference count for the SSL_CTX's session cache |
| 354 | * even though it has two ways of access: each session is in a | ||
| 355 | * doubly linked list and an lhash */ | ||
| 331 | CRYPTO_add(&c->references,1,CRYPTO_LOCK_SSL_SESSION); | 356 | CRYPTO_add(&c->references,1,CRYPTO_LOCK_SSL_SESSION); |
| 357 | /* if session c is in already in cache, we take back the increment later */ | ||
| 332 | 358 | ||
| 333 | CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); | 359 | CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); |
| 334 | s=(SSL_SESSION *)lh_insert(ctx->sessions,(char *)c); | 360 | s=(SSL_SESSION *)lh_insert(ctx->sessions,c); |
| 335 | 361 | ||
| 336 | /* Put on the end of the queue unless it is already in the cache */ | 362 | /* s != NULL iff we already had a session with the given PID. |
| 363 | * In this case, s == c should hold (then we did not really modify | ||
| 364 | * ctx->sessions), or we're in trouble. */ | ||
| 365 | if (s != NULL && s != c) | ||
| 366 | { | ||
| 367 | /* We *are* in trouble ... */ | ||
| 368 | SSL_SESSION_list_remove(ctx,s); | ||
| 369 | SSL_SESSION_free(s); | ||
| 370 | /* ... so pretend the other session did not exist in cache | ||
| 371 | * (we cannot handle two SSL_SESSION structures with identical | ||
| 372 | * session ID in the same cache, which could happen e.g. when | ||
| 373 | * two threads concurrently obtain the same session from an external | ||
| 374 | * cache) */ | ||
| 375 | s = NULL; | ||
| 376 | } | ||
| 377 | |||
| 378 | /* Put at the head of the queue unless it is already in the cache */ | ||
| 337 | if (s == NULL) | 379 | if (s == NULL) |
| 338 | SSL_SESSION_list_add(ctx,c); | 380 | SSL_SESSION_list_add(ctx,c); |
| 339 | 381 | ||
| 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) | 382 | if (s != NULL) |
| 345 | { | 383 | { |
| 346 | SSL_SESSION_free(s); | 384 | /* existing cache entry -- decrement previously incremented reference |
| 385 | * count because it already takes into account the cache */ | ||
| 386 | |||
| 387 | SSL_SESSION_free(s); /* s == c */ | ||
| 347 | ret=0; | 388 | ret=0; |
| 348 | } | 389 | } |
| 349 | else | 390 | else |
| 350 | { | 391 | { |
| 392 | /* new cache entry -- remove old ones if cache has become too large */ | ||
| 393 | |||
| 351 | ret=1; | 394 | ret=1; |
| 352 | 395 | ||
| 353 | if (SSL_CTX_sess_get_cache_size(ctx) > 0) | 396 | if (SSL_CTX_sess_get_cache_size(ctx) > 0) |
| @@ -380,7 +423,7 @@ static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck) | |||
| 380 | if ((c != NULL) && (c->session_id_length != 0)) | 423 | if ((c != NULL) && (c->session_id_length != 0)) |
| 381 | { | 424 | { |
| 382 | if(lck) CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); | 425 | if(lck) CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); |
| 383 | r=(SSL_SESSION *)lh_delete(ctx->sessions,(char *)c); | 426 | r=(SSL_SESSION *)lh_delete(ctx->sessions,c); |
| 384 | if (r != NULL) | 427 | if (r != NULL) |
| 385 | { | 428 | { |
| 386 | ret=1; | 429 | ret=1; |
| @@ -422,7 +465,7 @@ void SSL_SESSION_free(SSL_SESSION *ss) | |||
| 422 | } | 465 | } |
| 423 | #endif | 466 | #endif |
| 424 | 467 | ||
| 425 | CRYPTO_free_ex_data(ssl_session_meth,(char *)ss,&ss->ex_data); | 468 | CRYPTO_free_ex_data(ssl_session_meth,ss,&ss->ex_data); |
| 426 | 469 | ||
| 427 | memset(ss->key_arg,0,SSL_MAX_KEY_ARG_LENGTH); | 470 | memset(ss->key_arg,0,SSL_MAX_KEY_ARG_LENGTH); |
| 428 | memset(ss->master_key,0,SSL_MAX_MASTER_KEY_LENGTH); | 471 | memset(ss->master_key,0,SSL_MAX_MASTER_KEY_LENGTH); |
| @@ -541,7 +584,7 @@ static void timeout(SSL_SESSION *s, TIMEOUT_PARAM *p) | |||
| 541 | { | 584 | { |
| 542 | /* The reason we don't call SSL_CTX_remove_session() is to | 585 | /* The reason we don't call SSL_CTX_remove_session() is to |
| 543 | * save on locking overhead */ | 586 | * save on locking overhead */ |
| 544 | lh_delete(p->cache,(char *)s); | 587 | lh_delete(p->cache,s); |
| 545 | SSL_SESSION_list_remove(p->ctx,s); | 588 | SSL_SESSION_list_remove(p->ctx,s); |
| 546 | s->not_resumable=1; | 589 | s->not_resumable=1; |
| 547 | if (p->ctx->remove_session_cb != NULL) | 590 | if (p->ctx->remove_session_cb != NULL) |
| @@ -562,7 +605,7 @@ void SSL_CTX_flush_sessions(SSL_CTX *s, long t) | |||
| 562 | CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); | 605 | CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); |
| 563 | i=tp.cache->down_load; | 606 | i=tp.cache->down_load; |
| 564 | tp.cache->down_load=0; | 607 | tp.cache->down_load=0; |
| 565 | lh_doall_arg(tp.cache,(void (*)())timeout,(char *)&tp); | 608 | lh_doall_arg(tp.cache,(void (*)())timeout,&tp); |
| 566 | tp.cache->down_load=i; | 609 | tp.cache->down_load=i; |
| 567 | CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); | 610 | CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); |
| 568 | } | 611 | } |
