diff options
Diffstat (limited to 'src/lib/libssl/ssl_sess.c')
-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 | } |