Add simple external session cache to s_server. This serialises sessions
just like a "real" server making it easier to trace any problems. (manually applied from commit 35b0ea4efe24dee3194964588655d1a3187c6e63)
This commit is contained in:
parent
0cca92cdd3
commit
506e70a216
114
apps/s_server.c
114
apps/s_server.c
@ -213,6 +213,8 @@ static int init_ssl_connection(SSL *s);
|
|||||||
static void print_stats(BIO *bp,SSL_CTX *ctx);
|
static void print_stats(BIO *bp,SSL_CTX *ctx);
|
||||||
static int generate_session_id(const SSL *ssl, unsigned char *id,
|
static int generate_session_id(const SSL *ssl, unsigned char *id,
|
||||||
unsigned int *id_len);
|
unsigned int *id_len);
|
||||||
|
static void init_session_cache_ctx(SSL_CTX *sctx);
|
||||||
|
static void free_sessions(void);
|
||||||
#ifndef OPENSSL_NO_DH
|
#ifndef OPENSSL_NO_DH
|
||||||
static DH *load_dh_param(const char *dhfile);
|
static DH *load_dh_param(const char *dhfile);
|
||||||
static DH *get_dh512(void);
|
static DH *get_dh512(void);
|
||||||
@ -969,7 +971,7 @@ int MAIN(int argc, char *argv[])
|
|||||||
X509 *s_cert = NULL, *s_dcert = NULL;
|
X509 *s_cert = NULL, *s_dcert = NULL;
|
||||||
STACK_OF(X509) *s_chain = NULL, *s_dchain = NULL;
|
STACK_OF(X509) *s_chain = NULL, *s_dchain = NULL;
|
||||||
EVP_PKEY *s_key = NULL, *s_dkey = NULL;
|
EVP_PKEY *s_key = NULL, *s_dkey = NULL;
|
||||||
int no_cache = 0;
|
int no_cache = 0, ext_cache = 0;
|
||||||
int rev = 0;
|
int rev = 0;
|
||||||
#ifndef OPENSSL_NO_TLSEXT
|
#ifndef OPENSSL_NO_TLSEXT
|
||||||
EVP_PKEY *s_key2 = NULL;
|
EVP_PKEY *s_key2 = NULL;
|
||||||
@ -1164,6 +1166,8 @@ int MAIN(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
else if (strcmp(*argv,"-no_cache") == 0)
|
else if (strcmp(*argv,"-no_cache") == 0)
|
||||||
no_cache = 1;
|
no_cache = 1;
|
||||||
|
else if (strcmp(*argv,"-ext_cache") == 0)
|
||||||
|
ext_cache = 1;
|
||||||
else if (strcmp(*argv,"-CRLform") == 0)
|
else if (strcmp(*argv,"-CRLform") == 0)
|
||||||
{
|
{
|
||||||
if (--argc < 1) goto bad;
|
if (--argc < 1) goto bad;
|
||||||
@ -1668,6 +1672,8 @@ bad:
|
|||||||
if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback);
|
if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback);
|
||||||
if (no_cache)
|
if (no_cache)
|
||||||
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
|
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
|
||||||
|
else if (ext_cache)
|
||||||
|
init_session_cache_ctx(ctx);
|
||||||
else
|
else
|
||||||
SSL_CTX_sess_set_cache_size(ctx,128);
|
SSL_CTX_sess_set_cache_size(ctx,128);
|
||||||
|
|
||||||
@ -1752,6 +1758,8 @@ bad:
|
|||||||
|
|
||||||
if (no_cache)
|
if (no_cache)
|
||||||
SSL_CTX_set_session_cache_mode(ctx2,SSL_SESS_CACHE_OFF);
|
SSL_CTX_set_session_cache_mode(ctx2,SSL_SESS_CACHE_OFF);
|
||||||
|
else if (ext_cache)
|
||||||
|
init_session_cache_ctx(ctx2);
|
||||||
else
|
else
|
||||||
SSL_CTX_sess_set_cache_size(ctx2,128);
|
SSL_CTX_sess_set_cache_size(ctx2,128);
|
||||||
|
|
||||||
@ -1983,6 +1991,7 @@ end:
|
|||||||
OPENSSL_free(dpass);
|
OPENSSL_free(dpass);
|
||||||
if (vpm)
|
if (vpm)
|
||||||
X509_VERIFY_PARAM_free(vpm);
|
X509_VERIFY_PARAM_free(vpm);
|
||||||
|
free_sessions();
|
||||||
#ifndef OPENSSL_NO_TLSEXT
|
#ifndef OPENSSL_NO_TLSEXT
|
||||||
if (tlscstatp.host)
|
if (tlscstatp.host)
|
||||||
OPENSSL_free(tlscstatp.host);
|
OPENSSL_free(tlscstatp.host);
|
||||||
@ -3268,3 +3277,106 @@ static int generate_session_id(const SSL *ssl, unsigned char *id,
|
|||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* By default s_server uses an in-memory cache which caches SSL_SESSION
|
||||||
|
* structures without any serialisation. This hides some bugs which only
|
||||||
|
* become apparent in deployed servers. By implementing a basic external
|
||||||
|
* session cache some issues can be debugged using s_server.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct simple_ssl_session_st
|
||||||
|
{
|
||||||
|
unsigned char *id;
|
||||||
|
unsigned int idlen;
|
||||||
|
unsigned char *der;
|
||||||
|
int derlen;
|
||||||
|
struct simple_ssl_session_st *next;
|
||||||
|
} simple_ssl_session;
|
||||||
|
|
||||||
|
static simple_ssl_session *first = NULL;
|
||||||
|
|
||||||
|
static int add_session(SSL *ssl, SSL_SESSION *session)
|
||||||
|
{
|
||||||
|
simple_ssl_session *sess;
|
||||||
|
unsigned char *p;
|
||||||
|
|
||||||
|
sess = OPENSSL_malloc(sizeof(simple_ssl_session));
|
||||||
|
|
||||||
|
SSL_SESSION_get_id(session, &sess->idlen);
|
||||||
|
sess->derlen = i2d_SSL_SESSION(session, NULL);
|
||||||
|
|
||||||
|
sess->id = BUF_memdup(SSL_SESSION_get_id(session, NULL), sess->idlen);
|
||||||
|
|
||||||
|
sess->der = OPENSSL_malloc(sess->derlen);
|
||||||
|
p = sess->der;
|
||||||
|
i2d_SSL_SESSION(session, &p);
|
||||||
|
|
||||||
|
sess->next = first;
|
||||||
|
first = sess;
|
||||||
|
BIO_printf(bio_err, "New session added to external cache\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SSL_SESSION *get_session(SSL *ssl, unsigned char *id, int idlen,
|
||||||
|
int *do_copy)
|
||||||
|
{
|
||||||
|
simple_ssl_session *sess;
|
||||||
|
*do_copy = 0;
|
||||||
|
for (sess = first; sess; sess = sess->next)
|
||||||
|
{
|
||||||
|
if (idlen == (int)sess->idlen && !memcmp(sess->id, id, idlen))
|
||||||
|
{
|
||||||
|
const unsigned char *p = sess->der;
|
||||||
|
BIO_printf(bio_err, "Lookup session: cache hit\n");
|
||||||
|
return d2i_SSL_SESSION(NULL, &p, sess->derlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BIO_printf(bio_err, "Lookup session: cache miss\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void del_session(SSL_CTX *sctx, SSL_SESSION *session)
|
||||||
|
{
|
||||||
|
simple_ssl_session *sess, *prev = NULL;
|
||||||
|
const unsigned char *id;
|
||||||
|
unsigned int idlen;
|
||||||
|
id = SSL_SESSION_get_id(session, &idlen);
|
||||||
|
for (sess = first; sess; sess = sess->next)
|
||||||
|
{
|
||||||
|
if (idlen == sess->idlen && !memcmp(sess->id, id, idlen))
|
||||||
|
{
|
||||||
|
if(prev)
|
||||||
|
prev->next = sess->next;
|
||||||
|
else
|
||||||
|
first = sess->next;
|
||||||
|
OPENSSL_free(sess->id);
|
||||||
|
OPENSSL_free(sess->der);
|
||||||
|
OPENSSL_free(sess);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
prev = sess;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init_session_cache_ctx(SSL_CTX *sctx)
|
||||||
|
{
|
||||||
|
SSL_CTX_set_session_cache_mode(sctx,
|
||||||
|
SSL_SESS_CACHE_NO_INTERNAL|SSL_SESS_CACHE_SERVER);
|
||||||
|
SSL_CTX_sess_set_new_cb(sctx, add_session);
|
||||||
|
SSL_CTX_sess_set_get_cb(sctx, get_session);
|
||||||
|
SSL_CTX_sess_set_remove_cb(sctx, del_session);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free_sessions(void)
|
||||||
|
{
|
||||||
|
simple_ssl_session *sess, *tsess;
|
||||||
|
for (sess = first; sess;)
|
||||||
|
{
|
||||||
|
OPENSSL_free(sess->id);
|
||||||
|
OPENSSL_free(sess->der);
|
||||||
|
tsess = sess;
|
||||||
|
sess = sess->next;
|
||||||
|
OPENSSL_free(tsess);
|
||||||
|
}
|
||||||
|
first = NULL;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user