REORG: shctx: move ssl functions to ssl_sock.c
Move the ssl callback functions of the ssl shared session cache to
ssl_sock.c. The shctx functions still needs to be separated of the ssl
tree and data.
diff --git a/include/proto/shctx.h b/include/proto/shctx.h
index d56320c..dfa0c57 100644
--- a/include/proto/shctx.h
+++ b/include/proto/shctx.h
@@ -49,6 +49,14 @@
* Shared context MUST be firstly initialized */
void shared_context_set_cache(SSL_CTX *ctx);
+
+int shsess_free(struct shared_context *shctx, struct shared_session *shsess);
+
+struct shared_session *shsess_get_next(struct shared_context *shctx, int data_len);
+
+int shsess_store(struct shared_context *shctx, unsigned char *s_id, unsigned char *data, int data_len);
+
+
/* Lock functions */
#if defined (USE_PRIVATE_CACHE)
@@ -186,6 +194,30 @@
#endif
+/* List Macros */
+
+#define shblock_unset(s) (s)->n->p = (s)->p; \
+ (s)->p->n = (s)->n;
+
+static inline void shblock_set_free(struct shared_context *shctx,
+ struct shared_block *s)
+{
+ shblock_unset(s);
+ (s)->n = &shctx->free;
+ (s)->p = shctx->free.p;
+ shctx->free.p->n = s;
+ shctx->free.p = s;
+}
+
+static inline void shblock_set_active(struct shared_context *shctx,
+ struct shared_block *s)
+{
+ shblock_unset(s)
+ (s)->n = &shctx->active;
+ (s)->p = shctx->active.p;
+ shctx->active.p->n = s;
+ shctx->active.p = s;
+}
#endif /* SHCTX_H */
diff --git a/include/proto/ssl_sock.h b/include/proto/ssl_sock.h
index 86ad137..9f974dd 100644
--- a/include/proto/ssl_sock.h
+++ b/include/proto/ssl_sock.h
@@ -76,6 +76,19 @@
int ssl_sock_set_generated_cert(SSL_CTX *ctx, unsigned int key, struct bind_conf *bind_conf);
unsigned int ssl_sock_generated_cert_key(const void *data, size_t len);
+
+/* ssl shctx macro */
+
+#define shsess_tree_delete(s) ebmb_delete(&(s)->key);
+
+#define shsess_tree_insert(shctx, s) (struct shared_session *)ebmb_insert(&shctx->active.data.session.key.node.branches, \
+ &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
+
+#define shsess_tree_lookup(shctx, k) (struct shared_session *)ebmb_lookup(&shctx->active.data.session.key.node.branches, \
+ (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
+
+
+
#endif /* _PROTO_SSL_SOCK_H */
/*
diff --git a/src/shctx.c b/src/shctx.c
index 8f900cc..853b522 100644
--- a/src/shctx.c
+++ b/src/shctx.c
@@ -15,55 +15,25 @@
#include <arpa/inet.h>
#include <ebmbtree.h>
+#include <proto/connection.h>
#include <proto/shctx.h>
+#include <proto/ssl_sock.h>
#include <proto/openssl-compat.h>
#include <types/global.h>
#include <types/shctx.h>
+
#if !defined (USE_PRIVATE_CACHE)
int use_shared_mem = 0;
#endif
-/* List Macros */
-
-#define shblock_unset(s) (s)->n->p = (s)->p; \
- (s)->p->n = (s)->n;
-
-static inline void shblock_set_free(struct shared_context *shctx,
- struct shared_block *s)
-{
- shblock_unset(s);
- (s)->n = &shctx->free;
- (s)->p = shctx->free.p;
- shctx->free.p->n = s;
- shctx->free.p = s;
-}
-
-static inline void shblock_set_active(struct shared_context *shctx,
- struct shared_block *s)
-{
- shblock_unset(s)
- (s)->n = &shctx->active;
- (s)->p = shctx->active.p;
- shctx->active.p->n = s;
- shctx->active.p = s;
-}
-
/* Tree Macros */
-#define shsess_tree_delete(s) ebmb_delete(&(s)->key);
-
-#define shsess_tree_insert(shctx, s) (struct shared_session *)ebmb_insert(&shctx->active.data.session.key.node.branches, \
- &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
-
-#define shsess_tree_lookup(shctx, k) (struct shared_session *)ebmb_lookup(&shctx->active.data.session.key.node.branches, \
- (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
-
/* shared session functions */
/* Free session blocks, returns number of freed blocks */
-static int shsess_free(struct shared_context *shctx, struct shared_session *shsess)
+int shsess_free(struct shared_context *shctx, struct shared_session *shsess)
{
struct shared_block *block;
int ret = 1;
@@ -95,7 +65,7 @@
* Returns a ptr on a free block if it succeeds, or NULL if there are not
* enough blocks to store that session.
*/
-static struct shared_session *shsess_get_next(struct shared_context *shctx, int data_len)
+struct shared_session *shsess_get_next(struct shared_context *shctx, int data_len)
{
int head = 0;
struct shared_block *b;
@@ -135,7 +105,7 @@
* data_len: asn1 encoded session length
* Returns 1 id session was stored (else 0)
*/
-static int shsess_store(struct shared_context *shctx, unsigned char *s_id, unsigned char *data, int data_len)
+int shsess_store(struct shared_context *shctx, unsigned char *s_id, unsigned char *data, int data_len)
{
struct shared_session *shsess, *oldshsess;
@@ -199,169 +169,7 @@
return 1;
}
-
-/* SSL context callbacks */
-
-/* SSL callback used on new session creation */
-int shctx_new_cb(SSL *ssl, SSL_SESSION *sess)
-{
- unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
- unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
- unsigned char *p;
- int data_len;
- unsigned int sid_length, sid_ctx_length;
- const unsigned char *sid_data;
- const unsigned char *sid_ctx_data;
-
- /* Session id is already stored in to key and session id is known
- * so we dont store it to keep size.
- */
-
- sid_data = SSL_SESSION_get_id(sess, &sid_length);
- sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
- SSL_SESSION_set1_id(sess, sid_data, 0);
- SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
-
- /* check if buffer is large enough for the ASN1 encoded session */
- data_len = i2d_SSL_SESSION(sess, NULL);
- if (data_len > SHSESS_MAX_DATA_LEN)
- goto err;
-
- p = encsess;
-
- /* process ASN1 session encoding before the lock */
- i2d_SSL_SESSION(sess, &p);
-
- memcpy(encid, sid_data, sid_length);
- if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
- memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
-
- shared_context_lock(ssl_shctx);
-
- /* store to cache */
- shsess_store(ssl_shctx, encid, encsess, data_len);
-
- shared_context_unlock(ssl_shctx);
-
-err:
- /* reset original length values */
- SSL_SESSION_set1_id(sess, sid_data, sid_length);
- SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
-
- return 0; /* do not increment session reference count */
-}
-
-/* SSL callback used on lookup an existing session cause none found in internal cache */
-SSL_SESSION *shctx_get_cb(SSL *ssl, __OPENSSL_110_CONST__ unsigned char *key, int key_len, int *do_copy)
-{
- struct shared_session *shsess;
- unsigned char data[SHSESS_MAX_DATA_LEN], *p;
- unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
- int data_len;
- SSL_SESSION *sess;
-
- global.shctx_lookups++;
-
- /* allow the session to be freed automatically by openssl */
- *do_copy = 0;
-
- /* tree key is zeros padded sessionid */
- if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
- memcpy(tmpkey, key, key_len);
- memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
- key = tmpkey;
- }
-
- /* lock cache */
- shared_context_lock(ssl_shctx);
-
- /* lookup for session */
- shsess = shsess_tree_lookup(ssl_shctx, key);
- if (!shsess) {
- /* no session found: unlock cache and exit */
- shared_context_unlock(ssl_shctx);
- global.shctx_misses++;
- return NULL;
- }
-
- data_len = ((struct shared_block *)shsess)->data_len;
- if (data_len <= sizeof(shsess->data)) {
- /* Session stored on single block */
- memcpy(data, shsess->data, data_len);
- shblock_set_active(ssl_shctx, (struct shared_block *)shsess);
- }
- else {
- /* Session stored on multiple blocks */
- struct shared_block *block;
-
- memcpy(data, shsess->data, sizeof(shsess->data));
- p = data + sizeof(shsess->data);
- block = ((struct shared_block *)shsess)->n;
- shblock_set_active(ssl_shctx, (struct shared_block *)shsess);
- while (1) {
- /* Retrieve data from next block */
- struct shared_block *next;
-
- if (block->data_len <= sizeof(block->data.data)) {
- /* This is the last block */
- memcpy(p, block->data.data, block->data_len);
- p += block->data_len;
- shblock_set_active(ssl_shctx, block);
- break;
- }
- /* Intermediate block */
- memcpy(p, block->data.data, sizeof(block->data.data));
- p += sizeof(block->data.data);
- next = block->n;
- shblock_set_active(ssl_shctx, block);
- block = next;
- }
- }
-
- shared_context_unlock(ssl_shctx);
-
- /* decode ASN1 session */
- p = data;
- sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, data_len);
- /* Reset session id and session id contenxt */
- if (sess) {
- SSL_SESSION_set1_id(sess, key, key_len);
- SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
- }
-
- return sess;
-}
-
-/* SSL callback used to signal session is no more used in internal cache */
-void shctx_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
-{
- struct shared_session *shsess;
- unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
- unsigned int sid_length;
- const unsigned char *sid_data;
- (void)ctx;
-
- sid_data = SSL_SESSION_get_id(sess, &sid_length);
- /* tree key is zeros padded sessionid */
- if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
- memcpy(tmpkey, sid_data, sid_length);
- memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
- sid_data = tmpkey;
- }
-
- shared_context_lock(ssl_shctx);
-
- /* lookup for session */
- shsess = shsess_tree_lookup(ssl_shctx, sid_data);
- if (shsess) {
- /* free session */
- shsess_tree_delete(shsess);
- shsess_free(ssl_shctx, shsess);
- }
- /* unlock cache */
- shared_context_unlock(ssl_shctx);
-}
/* Allocate shared memory context.
* <size> is maximum cached sessions.
@@ -461,25 +269,3 @@
return ret;
}
-
-/* Set session cache mode to server and disable openssl internal cache.
- * Set shared cache callbacks on an ssl context.
- * Shared context MUST be firstly initialized */
-void shared_context_set_cache(SSL_CTX *ctx)
-{
- SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
-
- if (!ssl_shctx) {
- SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
- return;
- }
-
- SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
- SSL_SESS_CACHE_NO_INTERNAL |
- SSL_SESS_CACHE_NO_AUTO_CLEAR);
-
- /* Set callbacks */
- SSL_CTX_sess_set_new_cb(ctx, shctx_new_cb);
- SSL_CTX_sess_set_get_cb(ctx, shctx_get_cb);
- SSL_CTX_sess_set_remove_cb(ctx, shctx_remove_cb);
-}
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index 24e4f21..71bcbe3 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -3718,6 +3718,191 @@
return cfgerr;
}
+/* SSL context callbacks */
+
+/* SSL callback used on new session creation */
+int shctx_new_cb(SSL *ssl, SSL_SESSION *sess)
+{
+ unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
+ unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
+ unsigned char *p;
+ int data_len;
+ unsigned int sid_length, sid_ctx_length;
+ const unsigned char *sid_data;
+ const unsigned char *sid_ctx_data;
+
+ /* Session id is already stored in to key and session id is known
+ * so we dont store it to keep size.
+ */
+
+ sid_data = SSL_SESSION_get_id(sess, &sid_length);
+ sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
+ SSL_SESSION_set1_id(sess, sid_data, 0);
+ SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
+
+ /* check if buffer is large enough for the ASN1 encoded session */
+ data_len = i2d_SSL_SESSION(sess, NULL);
+ if (data_len > SHSESS_MAX_DATA_LEN)
+ goto err;
+
+ p = encsess;
+
+ /* process ASN1 session encoding before the lock */
+ i2d_SSL_SESSION(sess, &p);
+
+ memcpy(encid, sid_data, sid_length);
+ if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
+ memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
+
+ shared_context_lock(ssl_shctx);
+
+ /* store to cache */
+ shsess_store(ssl_shctx, encid, encsess, data_len);
+
+ shared_context_unlock(ssl_shctx);
+
+err:
+ /* reset original length values */
+ SSL_SESSION_set1_id(sess, sid_data, sid_length);
+ SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
+
+ return 0; /* do not increment session reference count */
+}
+
+/* SSL callback used on lookup an existing session cause none found in internal cache */
+SSL_SESSION *shctx_get_cb(SSL *ssl, __OPENSSL_110_CONST__ unsigned char *key, int key_len, int *do_copy)
+{
+ struct shared_session *shsess;
+ unsigned char data[SHSESS_MAX_DATA_LEN], *p;
+ unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
+ int data_len;
+ SSL_SESSION *sess;
+
+ global.shctx_lookups++;
+
+ /* allow the session to be freed automatically by openssl */
+ *do_copy = 0;
+
+ /* tree key is zeros padded sessionid */
+ if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
+ memcpy(tmpkey, key, key_len);
+ memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
+ key = tmpkey;
+ }
+
+ /* lock cache */
+ shared_context_lock(ssl_shctx);
+
+ /* lookup for session */
+ shsess = shsess_tree_lookup(ssl_shctx, key);
+ if (!shsess) {
+ /* no session found: unlock cache and exit */
+ shared_context_unlock(ssl_shctx);
+ global.shctx_misses++;
+ return NULL;
+ }
+
+ data_len = ((struct shared_block *)shsess)->data_len;
+ if (data_len <= sizeof(shsess->data)) {
+ /* Session stored on single block */
+ memcpy(data, shsess->data, data_len);
+ shblock_set_active(ssl_shctx, (struct shared_block *)shsess);
+ }
+ else {
+ /* Session stored on multiple blocks */
+ struct shared_block *block;
+
+ memcpy(data, shsess->data, sizeof(shsess->data));
+ p = data + sizeof(shsess->data);
+ block = ((struct shared_block *)shsess)->n;
+ shblock_set_active(ssl_shctx, (struct shared_block *)shsess);
+ while (1) {
+ /* Retrieve data from next block */
+ struct shared_block *next;
+
+ if (block->data_len <= sizeof(block->data.data)) {
+ /* This is the last block */
+ memcpy(p, block->data.data, block->data_len);
+ p += block->data_len;
+ shblock_set_active(ssl_shctx, block);
+ break;
+ }
+ /* Intermediate block */
+ memcpy(p, block->data.data, sizeof(block->data.data));
+ p += sizeof(block->data.data);
+ next = block->n;
+ shblock_set_active(ssl_shctx, block);
+ block = next;
+ }
+ }
+
+ shared_context_unlock(ssl_shctx);
+
+ /* decode ASN1 session */
+ p = data;
+ sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, data_len);
+ /* Reset session id and session id contenxt */
+ if (sess) {
+ SSL_SESSION_set1_id(sess, key, key_len);
+ SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
+ }
+
+ return sess;
+}
+
+/* SSL callback used to signal session is no more used in internal cache */
+void shctx_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
+{
+ struct shared_session *shsess;
+ unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
+ unsigned int sid_length;
+ const unsigned char *sid_data;
+ (void)ctx;
+
+ sid_data = SSL_SESSION_get_id(sess, &sid_length);
+ /* tree key is zeros padded sessionid */
+ if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
+ memcpy(tmpkey, sid_data, sid_length);
+ memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
+ sid_data = tmpkey;
+ }
+
+ shared_context_lock(ssl_shctx);
+
+ /* lookup for session */
+ shsess = shsess_tree_lookup(ssl_shctx, sid_data);
+ if (shsess) {
+ /* free session */
+ shsess_tree_delete(shsess);
+ shsess_free(ssl_shctx, shsess);
+ }
+
+ /* unlock cache */
+ shared_context_unlock(ssl_shctx);
+}
+
+/* Set session cache mode to server and disable openssl internal cache.
+ * Set shared cache callbacks on an ssl context.
+ * Shared context MUST be firstly initialized */
+void shared_context_set_cache(SSL_CTX *ctx)
+{
+ SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
+
+ if (!ssl_shctx) {
+ SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
+ return;
+ }
+
+ SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
+ SSL_SESS_CACHE_NO_INTERNAL |
+ SSL_SESS_CACHE_NO_AUTO_CLEAR);
+
+ /* Set callbacks */
+ SSL_CTX_sess_set_new_cb(ctx, shctx_new_cb);
+ SSL_CTX_sess_set_get_cb(ctx, shctx_get_cb);
+ SSL_CTX_sess_set_remove_cb(ctx, shctx_remove_cb);
+}
+
int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
{
struct proxy *curproxy = bind_conf->frontend;