diff options
author | markus <> | 2002-09-05 12:51:50 +0000 |
---|---|---|
committer | markus <> | 2002-09-05 12:51:50 +0000 |
commit | 15b5d84f9da2ce4bfae8580e56e34a859f74ad71 (patch) | |
tree | bf939e82d7fd73cc8a01cf6959002209972091bc /src/lib/libssl/ssl_sess.c | |
parent | 027351f729b9e837200dae6e1520cda6577ab930 (diff) | |
download | openbsd-15b5d84f9da2ce4bfae8580e56e34a859f74ad71.tar.gz openbsd-15b5d84f9da2ce4bfae8580e56e34a859f74ad71.tar.bz2 openbsd-15b5d84f9da2ce4bfae8580e56e34a859f74ad71.zip |
import openssl-0.9.7-beta1
Diffstat (limited to 'src/lib/libssl/ssl_sess.c')
-rw-r--r-- | src/lib/libssl/ssl_sess.c | 431 |
1 files changed, 297 insertions, 134 deletions
diff --git a/src/lib/libssl/ssl_sess.c b/src/lib/libssl/ssl_sess.c index 8212600e40..6424f775e2 100644 --- a/src/lib/libssl/ssl_sess.c +++ b/src/lib/libssl/ssl_sess.c | |||
@@ -57,60 +57,57 @@ | |||
57 | */ | 57 | */ |
58 | 58 | ||
59 | #include <stdio.h> | 59 | #include <stdio.h> |
60 | #include "lhash.h" | 60 | #include <openssl/lhash.h> |
61 | #include "rand.h" | 61 | #include <openssl/rand.h> |
62 | #include "ssl_locl.h" | 62 | #include "ssl_locl.h" |
63 | 63 | ||
64 | #ifndef NOPROTO | ||
65 | 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); |
66 | 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); |
67 | #else | 66 | static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck); |
68 | static void SSL_SESSION_list_remove(); | ||
69 | static void SSL_SESSION_list_add(); | ||
70 | #endif | ||
71 | |||
72 | static ssl_session_num=0; | ||
73 | static STACK *ssl_session_meth=NULL; | ||
74 | 67 | ||
75 | SSL_SESSION *SSL_get_session(ssl) | 68 | SSL_SESSION *SSL_get_session(SSL *ssl) |
76 | SSL *ssl; | 69 | /* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */ |
77 | { | 70 | { |
78 | return(ssl->session); | 71 | return(ssl->session); |
79 | } | 72 | } |
80 | 73 | ||
81 | int SSL_SESSION_get_ex_new_index(argl,argp,new_func,dup_func,free_func) | 74 | SSL_SESSION *SSL_get1_session(SSL *ssl) |
82 | long argl; | 75 | /* variant of SSL_get_session: caller really gets something */ |
83 | char *argp; | 76 | { |
84 | int (*new_func)(); | 77 | SSL_SESSION *sess; |
85 | int (*dup_func)(); | 78 | /* Need to lock this all up rather than just use CRYPTO_add so that |
86 | void (*free_func)(); | 79 | * somebody doesn't free ssl->session between when we check it's |
87 | { | 80 | * non-null and when we up the reference count. */ |
88 | ssl_session_num++; | 81 | CRYPTO_r_lock(CRYPTO_LOCK_SSL_SESSION); |
89 | return(CRYPTO_get_ex_new_index(ssl_session_num-1, | 82 | sess = ssl->session; |
90 | &ssl_session_meth, | 83 | if(sess) |
91 | argl,argp,new_func,dup_func,free_func)); | 84 | sess->references++; |
92 | } | 85 | CRYPTO_r_unlock(CRYPTO_LOCK_SSL_SESSION); |
93 | 86 | return(sess); | |
94 | int SSL_SESSION_set_ex_data(s,idx,arg) | 87 | } |
95 | SSL_SESSION *s; | 88 | |
96 | int idx; | 89 | int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, |
97 | char *arg; | 90 | CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) |
91 | { | ||
92 | return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, argl, argp, | ||
93 | new_func, dup_func, free_func); | ||
94 | } | ||
95 | |||
96 | int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg) | ||
98 | { | 97 | { |
99 | return(CRYPTO_set_ex_data(&s->ex_data,idx,arg)); | 98 | return(CRYPTO_set_ex_data(&s->ex_data,idx,arg)); |
100 | } | 99 | } |
101 | 100 | ||
102 | char *SSL_SESSION_get_ex_data(s,idx) | 101 | void *SSL_SESSION_get_ex_data(SSL_SESSION *s, int idx) |
103 | SSL_SESSION *s; | ||
104 | int idx; | ||
105 | { | 102 | { |
106 | return(CRYPTO_get_ex_data(&s->ex_data,idx)); | 103 | return(CRYPTO_get_ex_data(&s->ex_data,idx)); |
107 | } | 104 | } |
108 | 105 | ||
109 | SSL_SESSION *SSL_SESSION_new() | 106 | SSL_SESSION *SSL_SESSION_new(void) |
110 | { | 107 | { |
111 | SSL_SESSION *ss; | 108 | SSL_SESSION *ss; |
112 | 109 | ||
113 | ss=(SSL_SESSION *)Malloc(sizeof(SSL_SESSION)); | 110 | ss=(SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION)); |
114 | if (ss == NULL) | 111 | if (ss == NULL) |
115 | { | 112 | { |
116 | SSLerr(SSL_F_SSL_SESSION_NEW,ERR_R_MALLOC_FAILURE); | 113 | SSLerr(SSL_F_SSL_SESSION_NEW,ERR_R_MALLOC_FAILURE); |
@@ -118,26 +115,64 @@ SSL_SESSION *SSL_SESSION_new() | |||
118 | } | 115 | } |
119 | memset(ss,0,sizeof(SSL_SESSION)); | 116 | memset(ss,0,sizeof(SSL_SESSION)); |
120 | 117 | ||
118 | ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */ | ||
121 | ss->references=1; | 119 | ss->references=1; |
122 | ss->timeout=60*5+4; /* 5 minute timeout by default */ | 120 | ss->timeout=60*5+4; /* 5 minute timeout by default */ |
123 | ss->time=time(NULL); | 121 | ss->time=time(NULL); |
124 | ss->prev=NULL; | 122 | ss->prev=NULL; |
125 | ss->next=NULL; | 123 | ss->next=NULL; |
126 | CRYPTO_new_ex_data(ssl_session_meth,(char *)ss,&ss->ex_data); | 124 | ss->compress_meth=0; |
125 | CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); | ||
127 | return(ss); | 126 | return(ss); |
128 | } | 127 | } |
129 | 128 | ||
130 | int ssl_get_new_session(s, session) | 129 | /* Even with SSLv2, we have 16 bytes (128 bits) of session ID space. SSLv3/TLSv1 |
131 | SSL *s; | 130 | * has 32 bytes (256 bits). As such, filling the ID with random gunk repeatedly |
132 | int session; | 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 | |||
161 | int ssl_get_new_session(SSL *s, int session) | ||
133 | { | 162 | { |
163 | /* This gets used by clients and servers. */ | ||
164 | |||
165 | unsigned int tmp; | ||
134 | SSL_SESSION *ss=NULL; | 166 | SSL_SESSION *ss=NULL; |
167 | GEN_SESSION_CB cb = def_generate_session_id; | ||
135 | 168 | ||
136 | if ((ss=SSL_SESSION_new()) == NULL) return(0); | 169 | if ((ss=SSL_SESSION_new()) == NULL) return(0); |
137 | 170 | ||
138 | /* If the context has a default timeout, use it */ | 171 | /* If the context has a default timeout, use it */ |
139 | if (s->ctx->session_timeout != 0) | 172 | if (s->ctx->session_timeout == 0) |
140 | ss->timeout=SSL_get_default_timeout(s); | 173 | ss->timeout=SSL_get_default_timeout(s); |
174 | else | ||
175 | ss->timeout=s->ctx->session_timeout; | ||
141 | 176 | ||
142 | if (s->session != NULL) | 177 | if (s->session != NULL) |
143 | { | 178 | { |
@@ -147,7 +182,7 @@ int session; | |||
147 | 182 | ||
148 | if (session) | 183 | if (session) |
149 | { | 184 | { |
150 | if (s->version == SSL2_CLIENT_VERSION) | 185 | if (s->version == SSL2_VERSION) |
151 | { | 186 | { |
152 | ss->ssl_version=SSL2_VERSION; | 187 | ss->ssl_version=SSL2_VERSION; |
153 | ss->session_id_length=SSL2_SSL_SESSION_ID_LENGTH; | 188 | ss->session_id_length=SSL2_SSL_SESSION_ID_LENGTH; |
@@ -168,18 +203,46 @@ int session; | |||
168 | SSL_SESSION_free(ss); | 203 | SSL_SESSION_free(ss); |
169 | return(0); | 204 | return(0); |
170 | } | 205 | } |
171 | 206 | /* Choose which callback will set the session ID */ | |
172 | 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)) | ||
216 | { | ||
217 | /* The callback failed */ | ||
218 | SSLerr(SSL_F_SSL_GET_NEW_SESSION, | ||
219 | SSL_R_SSL_SESSION_ID_CALLBACK_FAILED); | ||
220 | SSL_SESSION_free(ss); | ||
221 | return(0); | ||
222 | } | ||
223 | /* Don't allow the callback to set the session length to zero. | ||
224 | * nor set it higher than it was. */ | ||
225 | if(!tmp || (tmp > ss->session_id_length)) | ||
226 | { | ||
227 | /* The callback set an illegal length */ | ||
228 | SSLerr(SSL_F_SSL_GET_NEW_SESSION, | ||
229 | SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH); | ||
230 | SSL_SESSION_free(ss); | ||
231 | return(0); | ||
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)) | ||
173 | { | 241 | { |
174 | SSL_SESSION *r; | 242 | SSLerr(SSL_F_SSL_GET_NEW_SESSION, |
175 | 243 | SSL_R_SSL_SESSION_ID_CONFLICT); | |
176 | RAND_bytes(ss->session_id,ss->session_id_length); | 244 | SSL_SESSION_free(ss); |
177 | CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); | 245 | return(0); |
178 | r=(SSL_SESSION *)lh_retrieve(s->ctx->sessions, | ||
179 | (char *)ss); | ||
180 | CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); | ||
181 | if (r == NULL) break; | ||
182 | /* else - woops a session_id match */ | ||
183 | } | 246 | } |
184 | } | 247 | } |
185 | else | 248 | else |
@@ -187,58 +250,100 @@ int session; | |||
187 | ss->session_id_length=0; | 250 | ss->session_id_length=0; |
188 | } | 251 | } |
189 | 252 | ||
253 | memcpy(ss->sid_ctx,s->sid_ctx,s->sid_ctx_length); | ||
254 | ss->sid_ctx_length=s->sid_ctx_length; | ||
190 | s->session=ss; | 255 | s->session=ss; |
191 | ss->ssl_version=s->version; | 256 | ss->ssl_version=s->version; |
257 | ss->verify_result = X509_V_OK; | ||
192 | 258 | ||
193 | return(1); | 259 | return(1); |
194 | } | 260 | } |
195 | 261 | ||
196 | int ssl_get_prev_session(s,session_id,len) | 262 | int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len) |
197 | SSL *s; | ||
198 | unsigned char *session_id; | ||
199 | int len; | ||
200 | { | 263 | { |
264 | /* This is used only by servers. */ | ||
265 | |||
201 | SSL_SESSION *ret=NULL,data; | 266 | SSL_SESSION *ret=NULL,data; |
267 | int fatal = 0; | ||
202 | 268 | ||
203 | /* conn_init();*/ | ||
204 | data.ssl_version=s->version; | 269 | data.ssl_version=s->version; |
205 | data.session_id_length=len; | 270 | data.session_id_length=len; |
206 | if (len > SSL_MAX_SSL_SESSION_ID_LENGTH) | 271 | if (len > SSL_MAX_SSL_SESSION_ID_LENGTH) |
207 | return(0); | 272 | goto err; |
208 | memcpy(data.session_id,session_id,len);; | 273 | memcpy(data.session_id,session_id,len); |
209 | 274 | ||
210 | if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) | 275 | if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) |
211 | { | 276 | { |
212 | CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); | 277 | CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); |
213 | ret=(SSL_SESSION *)lh_retrieve(s->ctx->sessions,(char *)&data); | 278 | ret=(SSL_SESSION *)lh_retrieve(s->ctx->sessions,&data); |
279 | if (ret != NULL) | ||
280 | /* don't allow other threads to steal it: */ | ||
281 | CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION); | ||
214 | CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); | 282 | CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); |
215 | } | 283 | } |
216 | 284 | ||
217 | if (ret == NULL) | 285 | if (ret == NULL) |
218 | { | 286 | { |
219 | int copy=1; | 287 | int copy=1; |
220 | 288 | ||
221 | s->ctx->sess_miss++; | 289 | s->ctx->stats.sess_miss++; |
222 | ret=NULL; | 290 | ret=NULL; |
223 | if ((s->ctx->get_session_cb != NULL) && | 291 | if (s->ctx->get_session_cb != NULL |
224 | ((ret=s->ctx->get_session_cb(s,session_id,len,©)) | 292 | && (ret=s->ctx->get_session_cb(s,session_id,len,©)) |
225 | != NULL)) | 293 | != NULL) |
226 | { | 294 | { |
227 | s->ctx->sess_cb_hit++; | 295 | s->ctx->stats.sess_cb_hit++; |
296 | |||
297 | /* Increment reference count now if the session callback | ||
298 | * asks us to do so (note that if the session structures | ||
299 | * returned by the callback are shared between threads, | ||
300 | * it must handle the reference count itself [i.e. copy == 0], | ||
301 | * or things won't be thread-safe). */ | ||
302 | if (copy) | ||
303 | CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION); | ||
228 | 304 | ||
229 | /* The following should not return 1, otherwise, | 305 | /* The following should not return 1, otherwise, |
230 | * things are very strange */ | 306 | * things are very strange */ |
231 | SSL_CTX_add_session(s->ctx,ret); | 307 | SSL_CTX_add_session(s->ctx,ret); |
232 | /* auto free it */ | ||
233 | if (!copy) | ||
234 | SSL_SESSION_free(ret); | ||
235 | } | 308 | } |
236 | if (ret == NULL) return(0); | 309 | if (ret == NULL) |
310 | goto err; | ||
311 | } | ||
312 | |||
313 | /* Now ret is non-NULL, and we own one of its reference counts. */ | ||
314 | |||
315 | if((s->verify_mode&SSL_VERIFY_PEER) | ||
316 | && (!s->sid_ctx_length || ret->sid_ctx_length != s->sid_ctx_length | ||
317 | || memcmp(ret->sid_ctx,s->sid_ctx,ret->sid_ctx_length))) | ||
318 | { | ||
319 | /* We've found the session named by the client, but we don't | ||
320 | * want to use it in this context. */ | ||
321 | |||
322 | if (s->sid_ctx_length == 0) | ||
323 | { | ||
324 | /* application should have used SSL[_CTX]_set_session_id_context | ||
325 | * -- we could tolerate this and just pretend we never heard | ||
326 | * of this session, but then applications could effectively | ||
327 | * disable the session cache by accident without anyone noticing */ | ||
328 | |||
329 | SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED); | ||
330 | fatal = 1; | ||
331 | goto err; | ||
332 | } | ||
333 | else | ||
334 | { | ||
335 | #if 0 /* The client cannot always know when a session is not appropriate, | ||
336 | * so we shouldn't generate an error message. */ | ||
337 | |||
338 | SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT); | ||
339 | #endif | ||
340 | goto err; /* treat like cache miss */ | ||
341 | } | ||
237 | } | 342 | } |
238 | 343 | ||
239 | if (ret->cipher == NULL) | 344 | if (ret->cipher == NULL) |
240 | { | 345 | { |
241 | char buf[5],*p; | 346 | unsigned char buf[5],*p; |
242 | unsigned long l; | 347 | unsigned long l; |
243 | 348 | ||
244 | p=buf; | 349 | p=buf; |
@@ -249,25 +354,28 @@ int len; | |||
249 | else | 354 | else |
250 | ret->cipher=ssl_get_cipher_by_char(s,&(buf[1])); | 355 | ret->cipher=ssl_get_cipher_by_char(s,&(buf[1])); |
251 | if (ret->cipher == NULL) | 356 | if (ret->cipher == NULL) |
252 | return(0); | 357 | goto err; |
253 | } | 358 | } |
254 | 359 | ||
360 | |||
361 | #if 0 /* This is way too late. */ | ||
362 | |||
255 | /* If a thread got the session, then 'swaped', and another got | 363 | /* If a thread got the session, then 'swaped', and another got |
256 | * it and then due to a time-out decided to 'Free' it we could | 364 | * it and then due to a time-out decided to 'OPENSSL_free' it we could |
257 | * be in trouble. So I'll increment it now, then double decrement | 365 | * be in trouble. So I'll increment it now, then double decrement |
258 | * later - am I speaking rubbish?. */ | 366 | * later - am I speaking rubbish?. */ |
259 | CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION); | 367 | CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION); |
368 | #endif | ||
260 | 369 | ||
261 | if ((long)(ret->time+ret->timeout) < (long)time(NULL)) /* timeout */ | 370 | if ((long)(ret->time+ret->timeout) < (long)time(NULL)) /* timeout */ |
262 | { | 371 | { |
263 | s->ctx->sess_timeout++; | 372 | s->ctx->stats.sess_timeout++; |
264 | /* remove it from the cache */ | 373 | /* remove it from the cache */ |
265 | SSL_CTX_remove_session(s->ctx,ret); | 374 | SSL_CTX_remove_session(s->ctx,ret); |
266 | SSL_SESSION_free(ret); /* again to actually Free it */ | 375 | goto err; |
267 | return(0); | ||
268 | } | 376 | } |
269 | 377 | ||
270 | s->ctx->sess_hit++; | 378 | s->ctx->stats.sess_hit++; |
271 | 379 | ||
272 | /* ret->time=time(NULL); */ /* rezero timeout? */ | 380 | /* ret->time=time(NULL); */ /* rezero timeout? */ |
273 | /* again, just leave the session | 381 | /* again, just leave the session |
@@ -276,37 +384,64 @@ int len; | |||
276 | if (s->session != NULL) | 384 | if (s->session != NULL) |
277 | SSL_SESSION_free(s->session); | 385 | SSL_SESSION_free(s->session); |
278 | s->session=ret; | 386 | s->session=ret; |
387 | s->verify_result = s->session->verify_result; | ||
279 | return(1); | 388 | return(1); |
389 | |||
390 | err: | ||
391 | if (ret != NULL) | ||
392 | SSL_SESSION_free(ret); | ||
393 | if (fatal) | ||
394 | return -1; | ||
395 | else | ||
396 | return 0; | ||
280 | } | 397 | } |
281 | 398 | ||
282 | int SSL_CTX_add_session(ctx,c) | 399 | int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) |
283 | SSL_CTX *ctx; | ||
284 | SSL_SESSION *c; | ||
285 | { | 400 | { |
286 | int ret=0; | 401 | int ret=0; |
287 | SSL_SESSION *s; | 402 | SSL_SESSION *s; |
288 | 403 | ||
289 | /* conn_init(); */ | 404 | /* add just 1 reference count for the SSL_CTX's session cache |
405 | * even though it has two ways of access: each session is in a | ||
406 | * doubly linked list and an lhash */ | ||
290 | CRYPTO_add(&c->references,1,CRYPTO_LOCK_SSL_SESSION); | 407 | CRYPTO_add(&c->references,1,CRYPTO_LOCK_SSL_SESSION); |
408 | /* if session c is in already in cache, we take back the increment later */ | ||
291 | 409 | ||
292 | CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); | 410 | CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); |
293 | s=(SSL_SESSION *)lh_insert(ctx->sessions,(char *)c); | 411 | s=(SSL_SESSION *)lh_insert(ctx->sessions,c); |
294 | 412 | ||
295 | /* Put on the end of the queue unless it is already in the cache */ | 413 | /* s != NULL iff we already had a session with the given PID. |
414 | * In this case, s == c should hold (then we did not really modify | ||
415 | * ctx->sessions), or we're in trouble. */ | ||
416 | if (s != NULL && s != c) | ||
417 | { | ||
418 | /* We *are* in trouble ... */ | ||
419 | SSL_SESSION_list_remove(ctx,s); | ||
420 | SSL_SESSION_free(s); | ||
421 | /* ... so pretend the other session did not exist in cache | ||
422 | * (we cannot handle two SSL_SESSION structures with identical | ||
423 | * session ID in the same cache, which could happen e.g. when | ||
424 | * two threads concurrently obtain the same session from an external | ||
425 | * cache) */ | ||
426 | s = NULL; | ||
427 | } | ||
428 | |||
429 | /* Put at the head of the queue unless it is already in the cache */ | ||
296 | if (s == NULL) | 430 | if (s == NULL) |
297 | SSL_SESSION_list_add(ctx,c); | 431 | SSL_SESSION_list_add(ctx,c); |
298 | 432 | ||
299 | /* If the same session if is being 're-added', Free the old | ||
300 | * one when the last person stops using it. | ||
301 | * This will also work if it is alread in the cache. | ||
302 | * The references will go up and then down :-) */ | ||
303 | if (s != NULL) | 433 | if (s != NULL) |
304 | { | 434 | { |
305 | SSL_SESSION_free(s); | 435 | /* existing cache entry -- decrement previously incremented reference |
436 | * count because it already takes into account the cache */ | ||
437 | |||
438 | SSL_SESSION_free(s); /* s == c */ | ||
306 | ret=0; | 439 | ret=0; |
307 | } | 440 | } |
308 | else | 441 | else |
309 | { | 442 | { |
443 | /* new cache entry -- remove old ones if cache has become too large */ | ||
444 | |||
310 | ret=1; | 445 | ret=1; |
311 | 446 | ||
312 | if (SSL_CTX_sess_get_cache_size(ctx) > 0) | 447 | if (SSL_CTX_sess_get_cache_size(ctx) > 0) |
@@ -314,11 +449,11 @@ SSL_SESSION *c; | |||
314 | while (SSL_CTX_sess_number(ctx) > | 449 | while (SSL_CTX_sess_number(ctx) > |
315 | SSL_CTX_sess_get_cache_size(ctx)) | 450 | SSL_CTX_sess_get_cache_size(ctx)) |
316 | { | 451 | { |
317 | if (!SSL_CTX_remove_session(ctx, | 452 | if (!remove_session_lock(ctx, |
318 | ctx->session_cache_tail)) | 453 | ctx->session_cache_tail, 0)) |
319 | break; | 454 | break; |
320 | else | 455 | else |
321 | ctx->sess_cache_full++; | 456 | ctx->stats.sess_cache_full++; |
322 | } | 457 | } |
323 | } | 458 | } |
324 | } | 459 | } |
@@ -326,24 +461,27 @@ SSL_SESSION *c; | |||
326 | return(ret); | 461 | return(ret); |
327 | } | 462 | } |
328 | 463 | ||
329 | int SSL_CTX_remove_session(ctx,c) | 464 | int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c) |
330 | SSL_CTX *ctx; | 465 | { |
331 | SSL_SESSION *c; | 466 | return remove_session_lock(ctx, c, 1); |
467 | } | ||
468 | |||
469 | static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck) | ||
332 | { | 470 | { |
333 | SSL_SESSION *r; | 471 | SSL_SESSION *r; |
334 | int ret=0; | 472 | int ret=0; |
335 | 473 | ||
336 | if ((c != NULL) && (c->session_id_length != 0)) | 474 | if ((c != NULL) && (c->session_id_length != 0)) |
337 | { | 475 | { |
338 | CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); | 476 | if(lck) CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); |
339 | r=(SSL_SESSION *)lh_delete(ctx->sessions,(char *)c); | 477 | if ((r = (SSL_SESSION *)lh_retrieve(ctx->sessions,c)) == c) |
340 | if (r != NULL) | ||
341 | { | 478 | { |
342 | ret=1; | 479 | ret=1; |
480 | r=(SSL_SESSION *)lh_delete(ctx->sessions,c); | ||
343 | SSL_SESSION_list_remove(ctx,c); | 481 | SSL_SESSION_list_remove(ctx,c); |
344 | } | 482 | } |
345 | 483 | ||
346 | CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); | 484 | if(lck) CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); |
347 | 485 | ||
348 | if (ret) | 486 | if (ret) |
349 | { | 487 | { |
@@ -358,11 +496,13 @@ SSL_SESSION *c; | |||
358 | return(ret); | 496 | return(ret); |
359 | } | 497 | } |
360 | 498 | ||
361 | void SSL_SESSION_free(ss) | 499 | void SSL_SESSION_free(SSL_SESSION *ss) |
362 | SSL_SESSION *ss; | ||
363 | { | 500 | { |
364 | int i; | 501 | int i; |
365 | 502 | ||
503 | if(ss == NULL) | ||
504 | return; | ||
505 | |||
366 | i=CRYPTO_add(&ss->references,-1,CRYPTO_LOCK_SSL_SESSION); | 506 | i=CRYPTO_add(&ss->references,-1,CRYPTO_LOCK_SSL_SESSION); |
367 | #ifdef REF_PRINT | 507 | #ifdef REF_PRINT |
368 | REF_PRINT("SSL_SESSION",ss); | 508 | REF_PRINT("SSL_SESSION",ss); |
@@ -376,21 +516,19 @@ SSL_SESSION *ss; | |||
376 | } | 516 | } |
377 | #endif | 517 | #endif |
378 | 518 | ||
379 | CRYPTO_free_ex_data(ssl_session_meth,(char *)ss,&ss->ex_data); | 519 | CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); |
380 | 520 | ||
381 | memset(ss->key_arg,0,SSL_MAX_KEY_ARG_LENGTH); | 521 | memset(ss->key_arg,0,SSL_MAX_KEY_ARG_LENGTH); |
382 | memset(ss->master_key,0,SSL_MAX_MASTER_KEY_LENGTH); | 522 | memset(ss->master_key,0,SSL_MAX_MASTER_KEY_LENGTH); |
383 | memset(ss->session_id,0,SSL_MAX_SSL_SESSION_ID_LENGTH); | 523 | memset(ss->session_id,0,SSL_MAX_SSL_SESSION_ID_LENGTH); |
384 | if (ss->cert != NULL) ssl_cert_free(ss->cert); | 524 | if (ss->sess_cert != NULL) ssl_sess_cert_free(ss->sess_cert); |
385 | if (ss->peer != NULL) X509_free(ss->peer); | 525 | if (ss->peer != NULL) X509_free(ss->peer); |
386 | if (ss->ciphers != NULL) sk_free(ss->ciphers); | 526 | if (ss->ciphers != NULL) sk_SSL_CIPHER_free(ss->ciphers); |
387 | memset(ss,0,sizeof(*ss)); | 527 | memset(ss,0,sizeof(*ss)); |
388 | Free(ss); | 528 | OPENSSL_free(ss); |
389 | } | 529 | } |
390 | 530 | ||
391 | int SSL_set_session(s, session) | 531 | int SSL_set_session(SSL *s, SSL_SESSION *session) |
392 | SSL *s; | ||
393 | SSL_SESSION *session; | ||
394 | { | 532 | { |
395 | int ret=0; | 533 | int ret=0; |
396 | SSL_METHOD *meth; | 534 | SSL_METHOD *meth; |
@@ -410,14 +548,29 @@ SSL_SESSION *session; | |||
410 | { | 548 | { |
411 | if (!SSL_set_ssl_method(s,meth)) | 549 | if (!SSL_set_ssl_method(s,meth)) |
412 | return(0); | 550 | return(0); |
413 | session->timeout=SSL_get_default_timeout(s); | 551 | if (s->ctx->session_timeout == 0) |
552 | session->timeout=SSL_get_default_timeout(s); | ||
553 | else | ||
554 | session->timeout=s->ctx->session_timeout; | ||
414 | } | 555 | } |
415 | 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 | |||
416 | /* CRYPTO_w_lock(CRYPTO_LOCK_SSL);*/ | 568 | /* CRYPTO_w_lock(CRYPTO_LOCK_SSL);*/ |
417 | CRYPTO_add(&session->references,1,CRYPTO_LOCK_SSL_SESSION); | 569 | CRYPTO_add(&session->references,1,CRYPTO_LOCK_SSL_SESSION); |
418 | if (s->session != NULL) | 570 | if (s->session != NULL) |
419 | SSL_SESSION_free(s->session); | 571 | SSL_SESSION_free(s->session); |
420 | s->session=session; | 572 | s->session=session; |
573 | s->verify_result = s->session->verify_result; | ||
421 | /* CRYPTO_w_unlock(CRYPTO_LOCK_SSL);*/ | 574 | /* CRYPTO_w_unlock(CRYPTO_LOCK_SSL);*/ |
422 | ret=1; | 575 | ret=1; |
423 | } | 576 | } |
@@ -428,42 +581,59 @@ SSL_SESSION *session; | |||
428 | SSL_SESSION_free(s->session); | 581 | SSL_SESSION_free(s->session); |
429 | s->session=NULL; | 582 | s->session=NULL; |
430 | } | 583 | } |
584 | |||
585 | meth=s->ctx->method; | ||
586 | if (meth != s->method) | ||
587 | { | ||
588 | if (!SSL_set_ssl_method(s,meth)) | ||
589 | return(0); | ||
590 | } | ||
591 | ret=1; | ||
431 | } | 592 | } |
432 | return(ret); | 593 | return(ret); |
433 | } | 594 | } |
434 | 595 | ||
435 | long SSL_SESSION_set_timeout(s,t) | 596 | long SSL_SESSION_set_timeout(SSL_SESSION *s, long t) |
436 | SSL_SESSION *s; | ||
437 | long t; | ||
438 | { | 597 | { |
439 | if (s == NULL) return(0); | 598 | if (s == NULL) return(0); |
440 | s->timeout=t; | 599 | s->timeout=t; |
441 | return(1); | 600 | return(1); |
442 | } | 601 | } |
443 | 602 | ||
444 | long SSL_SESSION_get_timeout(s) | 603 | long SSL_SESSION_get_timeout(SSL_SESSION *s) |
445 | SSL_SESSION *s; | ||
446 | { | 604 | { |
447 | if (s == NULL) return(0); | 605 | if (s == NULL) return(0); |
448 | return(s->timeout); | 606 | return(s->timeout); |
449 | } | 607 | } |
450 | 608 | ||
451 | long SSL_SESSION_get_time(s) | 609 | long SSL_SESSION_get_time(SSL_SESSION *s) |
452 | SSL_SESSION *s; | ||
453 | { | 610 | { |
454 | if (s == NULL) return(0); | 611 | if (s == NULL) return(0); |
455 | return(s->time); | 612 | return(s->time); |
456 | } | 613 | } |
457 | 614 | ||
458 | long SSL_SESSION_set_time(s,t) | 615 | long SSL_SESSION_set_time(SSL_SESSION *s, long t) |
459 | SSL_SESSION *s; | ||
460 | long t; | ||
461 | { | 616 | { |
462 | if (s == NULL) return(0); | 617 | if (s == NULL) return(0); |
463 | s->time=t; | 618 | s->time=t; |
464 | return(t); | 619 | return(t); |
465 | } | 620 | } |
466 | 621 | ||
622 | long SSL_CTX_set_timeout(SSL_CTX *s, long t) | ||
623 | { | ||
624 | long l; | ||
625 | if (s == NULL) return(0); | ||
626 | l=s->session_timeout; | ||
627 | s->session_timeout=t; | ||
628 | return(l); | ||
629 | } | ||
630 | |||
631 | long SSL_CTX_get_timeout(SSL_CTX *s) | ||
632 | { | ||
633 | if (s == NULL) return(0); | ||
634 | return(s->session_timeout); | ||
635 | } | ||
636 | |||
467 | typedef struct timeout_param_st | 637 | typedef struct timeout_param_st |
468 | { | 638 | { |
469 | SSL_CTX *ctx; | 639 | SSL_CTX *ctx; |
@@ -471,15 +641,13 @@ typedef struct timeout_param_st | |||
471 | LHASH *cache; | 641 | LHASH *cache; |
472 | } TIMEOUT_PARAM; | 642 | } TIMEOUT_PARAM; |
473 | 643 | ||
474 | static void timeout(s,p) | 644 | static void timeout(SSL_SESSION *s, TIMEOUT_PARAM *p) |
475 | SSL_SESSION *s; | ||
476 | TIMEOUT_PARAM *p; | ||
477 | { | 645 | { |
478 | if ((p->time == 0) || (p->time > (s->time+s->timeout))) /* timeout */ | 646 | if ((p->time == 0) || (p->time > (s->time+s->timeout))) /* timeout */ |
479 | { | 647 | { |
480 | /* The reason we don't call SSL_CTX_remove_session() is to | 648 | /* The reason we don't call SSL_CTX_remove_session() is to |
481 | * save on locking overhead */ | 649 | * save on locking overhead */ |
482 | lh_delete(p->cache,(char *)s); | 650 | lh_delete(p->cache,s); |
483 | SSL_SESSION_list_remove(p->ctx,s); | 651 | SSL_SESSION_list_remove(p->ctx,s); |
484 | s->not_resumable=1; | 652 | s->not_resumable=1; |
485 | if (p->ctx->remove_session_cb != NULL) | 653 | if (p->ctx->remove_session_cb != NULL) |
@@ -488,27 +656,26 @@ TIMEOUT_PARAM *p; | |||
488 | } | 656 | } |
489 | } | 657 | } |
490 | 658 | ||
491 | void SSL_CTX_flush_sessions(s,t) | 659 | static IMPLEMENT_LHASH_DOALL_ARG_FN(timeout, SSL_SESSION *, TIMEOUT_PARAM *) |
492 | SSL_CTX *s; | 660 | |
493 | long t; | 661 | void SSL_CTX_flush_sessions(SSL_CTX *s, long t) |
494 | { | 662 | { |
495 | unsigned long i; | 663 | unsigned long i; |
496 | TIMEOUT_PARAM tp; | 664 | TIMEOUT_PARAM tp; |
497 | 665 | ||
498 | tp.ctx=s; | 666 | tp.ctx=s; |
499 | tp.cache=SSL_CTX_sessions(s); | 667 | tp.cache=s->sessions; |
500 | if (tp.cache == NULL) return; | 668 | if (tp.cache == NULL) return; |
501 | tp.time=t; | 669 | tp.time=t; |
502 | CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); | 670 | CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); |
503 | i=tp.cache->down_load; | 671 | i=tp.cache->down_load; |
504 | tp.cache->down_load=0; | 672 | tp.cache->down_load=0; |
505 | lh_doall_arg(tp.cache,(void (*)())timeout,(char *)&tp); | 673 | lh_doall_arg(tp.cache, LHASH_DOALL_ARG_FN(timeout), &tp); |
506 | tp.cache->down_load=i; | 674 | tp.cache->down_load=i; |
507 | CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); | 675 | CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); |
508 | } | 676 | } |
509 | 677 | ||
510 | int ssl_clear_bad_session(s) | 678 | int ssl_clear_bad_session(SSL *s) |
511 | SSL *s; | ||
512 | { | 679 | { |
513 | if ( (s->session != NULL) && | 680 | if ( (s->session != NULL) && |
514 | !(s->shutdown & SSL_SENT_SHUTDOWN) && | 681 | !(s->shutdown & SSL_SENT_SHUTDOWN) && |
@@ -522,9 +689,7 @@ SSL *s; | |||
522 | } | 689 | } |
523 | 690 | ||
524 | /* locked by SSL_CTX in the calling function */ | 691 | /* locked by SSL_CTX in the calling function */ |
525 | static void SSL_SESSION_list_remove(ctx,s) | 692 | static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s) |
526 | SSL_CTX *ctx; | ||
527 | SSL_SESSION *s; | ||
528 | { | 693 | { |
529 | if ((s->next == NULL) || (s->prev == NULL)) return; | 694 | if ((s->next == NULL) || (s->prev == NULL)) return; |
530 | 695 | ||
@@ -557,9 +722,7 @@ SSL_SESSION *s; | |||
557 | s->prev=s->next=NULL; | 722 | s->prev=s->next=NULL; |
558 | } | 723 | } |
559 | 724 | ||
560 | static void SSL_SESSION_list_add(ctx,s) | 725 | static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s) |
561 | SSL_CTX *ctx; | ||
562 | SSL_SESSION *s; | ||
563 | { | 726 | { |
564 | if ((s->next != NULL) && (s->prev != NULL)) | 727 | if ((s->next != NULL) && (s->prev != NULL)) |
565 | SSL_SESSION_list_remove(ctx,s); | 728 | SSL_SESSION_list_remove(ctx,s); |