static void SSL_SESSION_list_add(SSL_CTX *ctx,SSL_SESSION *s);
static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck);
static int ssl_session_num=0;
-static STACK *ssl_session_meth=NULL;
+static STACK_OF(CRYPTO_EX_DATA_FUNCS) *ssl_session_meth=NULL;
-#if 1 /* traditional SSLeay behaviour */
SSL_SESSION *SSL_get_session(SSL *ssl)
+/* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */
{
return(ssl->session);
}
-#else /* suggested change: increase reference counter so that a session
- * can later be set in a new SSL object.
- * Objections:
- * -- the modified function should have a new name (or old
- * applications, including s_client, leak memory);
- * -- the locking seems unnecessary given that SSL structures
- * usually cannot be safely shared between threads anyway. */
-SSL_SESSION *SSL_get_session(SSL *ssl)
+
+SSL_SESSION *SSL_get1_session(SSL *ssl)
+/* variant of SSL_get_session: caller really gets something */
{
SSL_SESSION *sess;
/* Need to lock this all up rather than just use CRYPTO_add so that
CRYPTO_r_unlock(CRYPTO_LOCK_SSL_SESSION);
return(sess);
}
-#endif
-int SSL_SESSION_get_ex_new_index(long argl, char *argp, int (*new_func)(),
- int (*dup_func)(), void (*free_func)())
+int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
{
ssl_session_num++;
return(CRYPTO_get_ex_new_index(ssl_session_num-1,
{
SSL_SESSION *ss;
- ss=(SSL_SESSION *)Malloc(sizeof(SSL_SESSION));
+ ss=(SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION));
if (ss == NULL)
{
SSLerr(SSL_F_SSL_SESSION_NEW,ERR_R_MALLOC_FAILURE);
ss->prev=NULL;
ss->next=NULL;
ss->compress_meth=0;
- CRYPTO_new_ex_data(ssl_session_meth,(char *)ss,&ss->ex_data);
+ CRYPTO_new_ex_data(ssl_session_meth,ss,&ss->ex_data);
return(ss);
}
+/* Even with SSLv2, we have 16 bytes (128 bits) of session ID space. SSLv3/TLSv1
+ * has 32 bytes (256 bits). As such, filling the ID with random gunk repeatedly
+ * until we have no conflict is going to complete in one iteration pretty much
+ * "most" of the time (btw: understatement). So, if it takes us 10 iterations
+ * and we still can't avoid a conflict - well that's a reasonable point to call
+ * it quits. Either the RAND code is broken or someone is trying to open roughly
+ * very close to 2^128 (or 2^256) SSL sessions to our server. How you might
+ * store that many sessions is perhaps a more interesting question ... */
+
+#define MAX_SESS_ID_ATTEMPTS 10
+static int def_generate_session_id(const SSL *ssl, unsigned char *id,
+ unsigned int *id_len)
+{
+ unsigned int retry = 0;
+ do
+ RAND_pseudo_bytes(id, *id_len);
+ while(SSL_has_matching_session_id(ssl, id, *id_len) &&
+ (++retry < MAX_SESS_ID_ATTEMPTS));
+ if(retry < MAX_SESS_ID_ATTEMPTS)
+ return 1;
+ /* else - woops a session_id match */
+ /* XXX We should also check the external cache --
+ * but the probability of a collision is negligible, and
+ * we could not prevent the concurrent creation of sessions
+ * with identical IDs since we currently don't have means
+ * to atomically check whether a session ID already exists
+ * and make a reservation for it if it does not
+ * (this problem applies to the internal cache as well).
+ */
+ return 0;
+}
+
int ssl_get_new_session(SSL *s, int session)
{
/* This gets used by clients and servers. */
+ unsigned int tmp;
SSL_SESSION *ss=NULL;
+ GEN_SESSION_CB cb = def_generate_session_id;
if ((ss=SSL_SESSION_new()) == NULL) return(0);
SSL_SESSION_free(ss);
return(0);
}
-
- for (;;)
+ /* Choose which callback will set the session ID */
+ CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
+ if(s->generate_session_id)
+ cb = s->generate_session_id;
+ else if(s->ctx->generate_session_id)
+ cb = s->ctx->generate_session_id;
+ CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
+ /* Choose a session ID */
+ tmp = ss->session_id_length;
+ if(!cb(s, ss->session_id, &tmp))
{
- SSL_SESSION *r;
-
- RAND_bytes(ss->session_id,ss->session_id_length);
- CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
- r=(SSL_SESSION *)lh_retrieve(s->ctx->sessions,
- (char *)ss);
- CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
- if (r == NULL) break;
- /* else - woops a session_id match */
- /* XXX We should also check the external cache --
- * but the probability of a collision is negligible, and
- * we could not prevent the concurrent creation of sessions
- * with identical IDs since we currently don't have means
- * to atomically check whether a session ID already exists
- * and make a reservation for it if it does not
- * (this problem applies to the internal cache as well).
- */
+ /* The callback failed */
+ SSLerr(SSL_F_SSL_GET_NEW_SESSION,
+ SSL_R_SSL_SESSION_ID_CALLBACK_FAILED);
+ SSL_SESSION_free(ss);
+ return(0);
+ }
+ /* Don't allow the callback to set the session length to zero.
+ * nor set it higher than it was. */
+ if(!tmp || (tmp > ss->session_id_length))
+ {
+ /* The callback set an illegal length */
+ SSLerr(SSL_F_SSL_GET_NEW_SESSION,
+ SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH);
+ SSL_SESSION_free(ss);
+ return(0);
+ }
+ /* If the session length was shrunk and we're SSLv2, pad it */
+ if((tmp < ss->session_id_length) && (s->version == SSL2_VERSION))
+ memset(ss->session_id + tmp, 0, ss->session_id_length - tmp);
+ else
+ ss->session_id_length = tmp;
+ /* Finally, check for a conflict */
+ if(SSL_has_matching_session_id(s, ss->session_id,
+ ss->session_id_length))
+ {
+ SSLerr(SSL_F_SSL_GET_NEW_SESSION,
+ SSL_R_SSL_SESSION_ID_CONFLICT);
+ SSL_SESSION_free(ss);
+ return(0);
}
}
else
if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
{
CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
- ret=(SSL_SESSION *)lh_retrieve(s->ctx->sessions,(char *)&data);
+ ret=(SSL_SESSION *)lh_retrieve(s->ctx->sessions,&data);
if (ret != NULL)
/* don't allow other threads to steal it: */
CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION);
#if 0 /* This is way too late. */
/* If a thread got the session, then 'swaped', and another got
- * it and then due to a time-out decided to 'Free' it we could
+ * it and then due to a time-out decided to 'OPENSSL_free' it we could
* be in trouble. So I'll increment it now, then double decrement
* later - am I speaking rubbish?. */
CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION);
/* if session c is in already in cache, we take back the increment later */
CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
- s=(SSL_SESSION *)lh_insert(ctx->sessions,(char *)c);
+ s=(SSL_SESSION *)lh_insert(ctx->sessions,c);
/* s != NULL iff we already had a session with the given PID.
* In this case, s == c should hold (then we did not really modify
if ((c != NULL) && (c->session_id_length != 0))
{
if(lck) CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
- r=(SSL_SESSION *)lh_delete(ctx->sessions,(char *)c);
+ r=(SSL_SESSION *)lh_delete(ctx->sessions,c);
if (r != NULL)
{
ret=1;
}
#endif
- CRYPTO_free_ex_data(ssl_session_meth,(char *)ss,&ss->ex_data);
+ CRYPTO_free_ex_data(ssl_session_meth,ss,&ss->ex_data);
memset(ss->key_arg,0,SSL_MAX_KEY_ARG_LENGTH);
memset(ss->master_key,0,SSL_MAX_MASTER_KEY_LENGTH);
if (ss->peer != NULL) X509_free(ss->peer);
if (ss->ciphers != NULL) sk_SSL_CIPHER_free(ss->ciphers);
memset(ss,0,sizeof(*ss));
- Free(ss);
+ OPENSSL_free(ss);
}
int SSL_set_session(SSL *s, SSL_SESSION *session)
if (s->session != NULL)
SSL_SESSION_free(s->session);
s->session=session;
+ s->verify_result = s->session->verify_result;
/* CRYPTO_w_unlock(CRYPTO_LOCK_SSL);*/
ret=1;
}
{
/* The reason we don't call SSL_CTX_remove_session() is to
* save on locking overhead */
- lh_delete(p->cache,(char *)s);
+ lh_delete(p->cache,s);
SSL_SESSION_list_remove(p->ctx,s);
s->not_resumable=1;
if (p->ctx->remove_session_cb != NULL)
}
}
+static IMPLEMENT_LHASH_DOALL_ARG_FN(timeout, SSL_SESSION *, TIMEOUT_PARAM *)
+
void SSL_CTX_flush_sessions(SSL_CTX *s, long t)
{
unsigned long i;
CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
i=tp.cache->down_load;
tp.cache->down_load=0;
- lh_doall_arg(tp.cache,(void (*)())timeout,(char *)&tp);
+ lh_doall_arg(tp.cache, LHASH_DOALL_ARG_FN(timeout), &tp);
tp.cache->down_load=i;
CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
}