]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
REORG: shctx: move ssl functions to ssl_sock.c
authorWilliam Lallemand <wlallemand@haproxy.com>
Mon, 30 Oct 2017 18:36:36 +0000 (19:36 +0100)
committerWilly Tarreau <w@1wt.eu>
Tue, 31 Oct 2017 02:48:39 +0000 (03:48 +0100)
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.

include/proto/shctx.h
include/proto/ssl_sock.h
src/shctx.c
src/ssl_sock.c

index d56320c44ccc058c71c84f298b73893520290799..dfa0c57363d7c79bc284ce243ff2263671142c38 100644 (file)
@@ -49,6 +49,14 @@ int shared_context_init(struct shared_context **orig_shctx, int size, int shared
  * 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 @@ static inline void _shared_context_unlock(struct shared_context *shctx)
 
 #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 */
 
index 86ad137a9fe8dce61d9d491fa7317c0d82e5fb26..9f974dd6920acb5d9f92c26d9fd2ded9e8135e09 100644 (file)
@@ -76,6 +76,19 @@ SSL_CTX *ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_co
 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 */
 
 /*
index 8f900cc315f2c803828c32bc5319c7318792e1f8..853b522ee51fefaf6b31cbfa806f4986b974336f 100644 (file)
 #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 @@ static int shsess_free(struct shared_context *shctx, struct shared_session *shse
  * 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 @@ static struct shared_session *shsess_get_next(struct shared_context *shctx, int
  * 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;
 
@@ -200,168 +170,6 @@ static int shsess_store(struct shared_context *shctx, unsigned char *s_id, unsig
 }
 
 
-/* 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 @@ err:
        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);
-}
index 24e4f21ad744c6572808068d4d9d98556dd1faed..71bcbe3dc9e78b8605604391e6d4903121624611 100644 (file)
@@ -3718,6 +3718,191 @@ ssl_sock_initial_ctx(struct bind_conf *bind_conf)
        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;