blob: 8f900cc315f2c803828c32bc5319c7318792e1f8 [file] [log] [blame]
Emeric Brun3e541d12012-09-03 11:14:36 +02001/*
2 * shctx.c - shared context management functions for SSL
3 *
4 * Copyright (C) 2011-2012 EXCELIANCE
5 *
6 * Author: Emeric Brun - emeric@exceliance.fr
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 */
13
14#include <sys/mman.h>
Emeric Brunaf9619d2012-11-28 18:47:52 +010015#include <arpa/inet.h>
Willy Tarreauce3f9132014-05-28 16:47:01 +020016#include <ebmbtree.h>
Emeric Bruncd1a5262014-05-07 23:11:42 +020017
William Lallemand24a7a752017-10-09 14:17:39 +020018#include <proto/shctx.h>
19#include <proto/openssl-compat.h>
Emeric Brun3e541d12012-09-03 11:14:36 +020020
William Lallemand24a7a752017-10-09 14:17:39 +020021#include <types/global.h>
22#include <types/shctx.h>
Emeric Brun4b3091e2012-09-24 15:48:52 +020023
William Lallemand24a7a752017-10-09 14:17:39 +020024#if !defined (USE_PRIVATE_CACHE)
25int use_shared_mem = 0;
Emeric Brun9faf0712012-09-25 11:11:16 +020026#endif
Emeric Brun3e541d12012-09-03 11:14:36 +020027
28/* List Macros */
29
William Lallemand3f85c9a2017-10-09 16:30:50 +020030#define shblock_unset(s) (s)->n->p = (s)->p; \
31 (s)->p->n = (s)->n;
Emeric Brun3e541d12012-09-03 11:14:36 +020032
William Lallemand3f85c9a2017-10-09 16:30:50 +020033static inline void shblock_set_free(struct shared_context *shctx,
34 struct shared_block *s)
35{
36 shblock_unset(s);
37 (s)->n = &shctx->free;
38 (s)->p = shctx->free.p;
39 shctx->free.p->n = s;
40 shctx->free.p = s;
41}
Emeric Brun3e541d12012-09-03 11:14:36 +020042
William Lallemand3f85c9a2017-10-09 16:30:50 +020043static inline void shblock_set_active(struct shared_context *shctx,
44 struct shared_block *s)
45{
46 shblock_unset(s)
47 (s)->n = &shctx->active;
48 (s)->p = shctx->active.p;
49 shctx->active.p->n = s;
50 shctx->active.p = s;
51}
Emeric Brun3e541d12012-09-03 11:14:36 +020052
Emeric Brun3e541d12012-09-03 11:14:36 +020053/* Tree Macros */
54
55#define shsess_tree_delete(s) ebmb_delete(&(s)->key);
56
William Lallemand3f85c9a2017-10-09 16:30:50 +020057#define shsess_tree_insert(shctx, s) (struct shared_session *)ebmb_insert(&shctx->active.data.session.key.node.branches, \
Emeric Brun3e541d12012-09-03 11:14:36 +020058 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
59
William Lallemand3f85c9a2017-10-09 16:30:50 +020060#define shsess_tree_lookup(shctx, k) (struct shared_session *)ebmb_lookup(&shctx->active.data.session.key.node.branches, \
Emeric Brun3e541d12012-09-03 11:14:36 +020061 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
62
Emeric Brunaf9619d2012-11-28 18:47:52 +010063/* shared session functions */
Emeric Brun3e541d12012-09-03 11:14:36 +020064
Emeric Brunaf9619d2012-11-28 18:47:52 +010065/* Free session blocks, returns number of freed blocks */
William Lallemand3f85c9a2017-10-09 16:30:50 +020066static int shsess_free(struct shared_context *shctx, struct shared_session *shsess)
Emeric Brunaf9619d2012-11-28 18:47:52 +010067{
68 struct shared_block *block;
69 int ret = 1;
Emeric Brun3e541d12012-09-03 11:14:36 +020070
Emeric Brunaf9619d2012-11-28 18:47:52 +010071 if (((struct shared_block *)shsess)->data_len <= sizeof(shsess->data)) {
William Lallemand3f85c9a2017-10-09 16:30:50 +020072 shblock_set_free(shctx, (struct shared_block *)shsess);
Emeric Brunaf9619d2012-11-28 18:47:52 +010073 return ret;
74 }
75 block = ((struct shared_block *)shsess)->n;
William Lallemand3f85c9a2017-10-09 16:30:50 +020076 shblock_set_free(shctx, (struct shared_block *)shsess);
Emeric Brunaf9619d2012-11-28 18:47:52 +010077 while (1) {
78 struct shared_block *next;
Emeric Brun3e541d12012-09-03 11:14:36 +020079
Emeric Brunaf9619d2012-11-28 18:47:52 +010080 if (block->data_len <= sizeof(block->data)) {
81 /* last block */
William Lallemand3f85c9a2017-10-09 16:30:50 +020082 shblock_set_free(shctx, block);
Emeric Brunaf9619d2012-11-28 18:47:52 +010083 ret++;
84 break;
85 }
86 next = block->n;
William Lallemand3f85c9a2017-10-09 16:30:50 +020087 shblock_set_free(shctx, block);
Emeric Brunaf9619d2012-11-28 18:47:52 +010088 ret++;
89 block = next;
90 }
91 return ret;
92}
Emeric Brun3e541d12012-09-03 11:14:36 +020093
Emeric Brunaf9619d2012-11-28 18:47:52 +010094/* This function frees enough blocks to store a new session of data_len.
95 * Returns a ptr on a free block if it succeeds, or NULL if there are not
96 * enough blocks to store that session.
97 */
William Lallemand3f85c9a2017-10-09 16:30:50 +020098static struct shared_session *shsess_get_next(struct shared_context *shctx, int data_len)
Emeric Brun3e541d12012-09-03 11:14:36 +020099{
Emeric Brunaf9619d2012-11-28 18:47:52 +0100100 int head = 0;
101 struct shared_block *b;
102
103 b = shctx->free.n;
104 while (b != &shctx->free) {
105 if (!head) {
106 data_len -= sizeof(b->data.session.data);
107 head = 1;
108 }
109 else
110 data_len -= sizeof(b->data.data);
111 if (data_len <= 0)
112 return &shctx->free.n->data.session;
113 b = b->n;
114 }
115 b = shctx->active.n;
116 while (b != &shctx->active) {
117 int freed;
118
119 shsess_tree_delete(&b->data.session);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200120 freed = shsess_free(shctx, &b->data.session);
Emeric Brunaf9619d2012-11-28 18:47:52 +0100121 if (!head)
122 data_len -= sizeof(b->data.session.data) + (freed-1)*sizeof(b->data.data);
123 else
124 data_len -= freed*sizeof(b->data.data);
125 if (data_len <= 0)
126 return &shctx->free.n->data.session;
127 b = shctx->active.n;
128 }
129 return NULL;
130}
Emeric Brun3e541d12012-09-03 11:14:36 +0200131
Emeric Brunaf9619d2012-11-28 18:47:52 +0100132/* store a session into the cache
133 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
134 * data: asn1 encoded session
135 * data_len: asn1 encoded session length
136 * Returns 1 id session was stored (else 0)
137 */
William Lallemand3f85c9a2017-10-09 16:30:50 +0200138static int shsess_store(struct shared_context *shctx, unsigned char *s_id, unsigned char *data, int data_len)
Emeric Brunaf9619d2012-11-28 18:47:52 +0100139{
140 struct shared_session *shsess, *oldshsess;
141
William Lallemand3f85c9a2017-10-09 16:30:50 +0200142 shsess = shsess_get_next(shctx, data_len);
Emeric Brunaf9619d2012-11-28 18:47:52 +0100143 if (!shsess) {
144 /* Could not retrieve enough free blocks to store that session */
Emeric Brun3e541d12012-09-03 11:14:36 +0200145 return 0;
Emeric Brunaf9619d2012-11-28 18:47:52 +0100146 }
Emeric Brun3e541d12012-09-03 11:14:36 +0200147
Emeric Brunaf9619d2012-11-28 18:47:52 +0100148 /* prepare key */
149 memcpy(shsess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
Emeric Brun3e541d12012-09-03 11:14:36 +0200150
Emeric Brunaf9619d2012-11-28 18:47:52 +0100151 /* it returns the already existing node
152 or current node if none, never returns null */
William Lallemand3f85c9a2017-10-09 16:30:50 +0200153 oldshsess = shsess_tree_insert(shctx, shsess);
Emeric Brunaf9619d2012-11-28 18:47:52 +0100154 if (oldshsess != shsess) {
155 /* free all blocks used by old node */
William Lallemand3f85c9a2017-10-09 16:30:50 +0200156 shsess_free(shctx, oldshsess);
Emeric Brunaf9619d2012-11-28 18:47:52 +0100157 shsess = oldshsess;
158 }
Emeric Brun3e541d12012-09-03 11:14:36 +0200159
Emeric Brunaf9619d2012-11-28 18:47:52 +0100160 ((struct shared_block *)shsess)->data_len = data_len;
161 if (data_len <= sizeof(shsess->data)) {
162 /* Store on a single block */
163 memcpy(shsess->data, data, data_len);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200164 shblock_set_active(shctx, (struct shared_block *)shsess);
Emeric Brunaf9619d2012-11-28 18:47:52 +0100165 }
166 else {
167 unsigned char *p;
168 /* Store on multiple blocks */
169 int cur_len;
Emeric Brun3e541d12012-09-03 11:14:36 +0200170
Emeric Brunaf9619d2012-11-28 18:47:52 +0100171 memcpy(shsess->data, data, sizeof(shsess->data));
172 p = data + sizeof(shsess->data);
173 cur_len = data_len - sizeof(shsess->data);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200174 shblock_set_active(shctx, (struct shared_block *)shsess);
Emeric Brunaf9619d2012-11-28 18:47:52 +0100175 while (1) {
176 /* Store next data on free block.
177 * shsess_get_next guarantees that there are enough
178 * free blocks in queue.
179 */
180 struct shared_block *block;
Emeric Brun3e541d12012-09-03 11:14:36 +0200181
Emeric Brunaf9619d2012-11-28 18:47:52 +0100182 block = shctx->free.n;
183 if (cur_len <= sizeof(block->data)) {
184 /* This is the last block */
185 block->data_len = cur_len;
186 memcpy(block->data.data, p, cur_len);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200187 shblock_set_active(shctx, block);
Emeric Brunaf9619d2012-11-28 18:47:52 +0100188 break;
189 }
190 /* Intermediate block */
191 block->data_len = cur_len;
192 memcpy(block->data.data, p, sizeof(block->data));
193 p += sizeof(block->data.data);
194 cur_len -= sizeof(block->data.data);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200195 shblock_set_active(shctx, block);
Emeric Brunaf9619d2012-11-28 18:47:52 +0100196 }
197 }
Emeric Brun3e541d12012-09-03 11:14:36 +0200198
Emeric Brunaf9619d2012-11-28 18:47:52 +0100199 return 1;
200}
Emeric Brun3e541d12012-09-03 11:14:36 +0200201
Emeric Brun3e541d12012-09-03 11:14:36 +0200202
Emeric Brunaf9619d2012-11-28 18:47:52 +0100203/* SSL context callbacks */
Emeric Brun3e541d12012-09-03 11:14:36 +0200204
Emeric Brunaf9619d2012-11-28 18:47:52 +0100205/* SSL callback used on new session creation */
206int shctx_new_cb(SSL *ssl, SSL_SESSION *sess)
207{
William Lallemand2a979662017-09-18 17:37:07 +0200208 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
209 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
Emeric Brunaf9619d2012-11-28 18:47:52 +0100210 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200211 int data_len;
212 unsigned int sid_length, sid_ctx_length;
213 const unsigned char *sid_data;
214 const unsigned char *sid_ctx_data;
Emeric Brun3e541d12012-09-03 11:14:36 +0200215
Emeric Brunaf9619d2012-11-28 18:47:52 +0100216 /* Session id is already stored in to key and session id is known
217 * so we dont store it to keep size.
218 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200219
220 sid_data = SSL_SESSION_get_id(sess, &sid_length);
221 sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
222 SSL_SESSION_set1_id(sess, sid_data, 0);
223 SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
Emeric Brun3e541d12012-09-03 11:14:36 +0200224
Emeric Brunaf9619d2012-11-28 18:47:52 +0100225 /* check if buffer is large enough for the ASN1 encoded session */
226 data_len = i2d_SSL_SESSION(sess, NULL);
227 if (data_len > SHSESS_MAX_DATA_LEN)
228 goto err;
229
William Lallemand2a979662017-09-18 17:37:07 +0200230 p = encsess;
231
Emeric Brunaf9619d2012-11-28 18:47:52 +0100232 /* process ASN1 session encoding before the lock */
Emeric Brunaf9619d2012-11-28 18:47:52 +0100233 i2d_SSL_SESSION(sess, &p);
234
William Lallemand2a979662017-09-18 17:37:07 +0200235 memcpy(encid, sid_data, sid_length);
Emeric Brunaf9619d2012-11-28 18:47:52 +0100236 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
William Lallemand2a979662017-09-18 17:37:07 +0200237 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
Emeric Brunaf9619d2012-11-28 18:47:52 +0100238
William Lallemand3f85c9a2017-10-09 16:30:50 +0200239 shared_context_lock(ssl_shctx);
Emeric Brunaf9619d2012-11-28 18:47:52 +0100240
241 /* store to cache */
William Lallemand3f85c9a2017-10-09 16:30:50 +0200242 shsess_store(ssl_shctx, encid, encsess, data_len);
Emeric Brunaf9619d2012-11-28 18:47:52 +0100243
William Lallemand3f85c9a2017-10-09 16:30:50 +0200244 shared_context_unlock(ssl_shctx);
Emeric Brunaf9619d2012-11-28 18:47:52 +0100245
246err:
247 /* reset original length values */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200248 SSL_SESSION_set1_id(sess, sid_data, sid_length);
249 SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
Emeric Brun3e541d12012-09-03 11:14:36 +0200250
251 return 0; /* do not increment session reference count */
252}
253
254/* SSL callback used on lookup an existing session cause none found in internal cache */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200255SSL_SESSION *shctx_get_cb(SSL *ssl, __OPENSSL_110_CONST__ unsigned char *key, int key_len, int *do_copy)
Emeric Brun3e541d12012-09-03 11:14:36 +0200256{
257 struct shared_session *shsess;
258 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
259 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
Emeric Brunaf9619d2012-11-28 18:47:52 +0100260 int data_len;
Emeric Brun3e541d12012-09-03 11:14:36 +0200261 SSL_SESSION *sess;
Emeric Brun3e541d12012-09-03 11:14:36 +0200262
Willy Tarreauce3f9132014-05-28 16:47:01 +0200263 global.shctx_lookups++;
264
Emeric Brun3e541d12012-09-03 11:14:36 +0200265 /* allow the session to be freed automatically by openssl */
266 *do_copy = 0;
267
268 /* tree key is zeros padded sessionid */
269 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
270 memcpy(tmpkey, key, key_len);
271 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
272 key = tmpkey;
273 }
274
275 /* lock cache */
William Lallemand3f85c9a2017-10-09 16:30:50 +0200276 shared_context_lock(ssl_shctx);
Emeric Brun3e541d12012-09-03 11:14:36 +0200277
278 /* lookup for session */
William Lallemand3f85c9a2017-10-09 16:30:50 +0200279 shsess = shsess_tree_lookup(ssl_shctx, key);
Emeric Brun3e541d12012-09-03 11:14:36 +0200280 if (!shsess) {
281 /* no session found: unlock cache and exit */
William Lallemand3f85c9a2017-10-09 16:30:50 +0200282 shared_context_unlock(ssl_shctx);
Willy Tarreauce3f9132014-05-28 16:47:01 +0200283 global.shctx_misses++;
Emeric Brun3e541d12012-09-03 11:14:36 +0200284 return NULL;
285 }
286
Emeric Brunaf9619d2012-11-28 18:47:52 +0100287 data_len = ((struct shared_block *)shsess)->data_len;
288 if (data_len <= sizeof(shsess->data)) {
289 /* Session stored on single block */
290 memcpy(data, shsess->data, data_len);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200291 shblock_set_active(ssl_shctx, (struct shared_block *)shsess);
Emeric Brunaf9619d2012-11-28 18:47:52 +0100292 }
293 else {
294 /* Session stored on multiple blocks */
295 struct shared_block *block;
Emeric Brun3e541d12012-09-03 11:14:36 +0200296
Emeric Brunaf9619d2012-11-28 18:47:52 +0100297 memcpy(data, shsess->data, sizeof(shsess->data));
298 p = data + sizeof(shsess->data);
299 block = ((struct shared_block *)shsess)->n;
William Lallemand3f85c9a2017-10-09 16:30:50 +0200300 shblock_set_active(ssl_shctx, (struct shared_block *)shsess);
Emeric Brunaf9619d2012-11-28 18:47:52 +0100301 while (1) {
302 /* Retrieve data from next block */
303 struct shared_block *next;
Emeric Brun3e541d12012-09-03 11:14:36 +0200304
Emeric Brunaf9619d2012-11-28 18:47:52 +0100305 if (block->data_len <= sizeof(block->data.data)) {
306 /* This is the last block */
307 memcpy(p, block->data.data, block->data_len);
308 p += block->data_len;
William Lallemand3f85c9a2017-10-09 16:30:50 +0200309 shblock_set_active(ssl_shctx, block);
Emeric Brunaf9619d2012-11-28 18:47:52 +0100310 break;
311 }
312 /* Intermediate block */
313 memcpy(p, block->data.data, sizeof(block->data.data));
314 p += sizeof(block->data.data);
315 next = block->n;
William Lallemand3f85c9a2017-10-09 16:30:50 +0200316 shblock_set_active(ssl_shctx, block);
Emeric Brunaf9619d2012-11-28 18:47:52 +0100317 block = next;
318 }
319 }
Emeric Brun3e541d12012-09-03 11:14:36 +0200320
William Lallemand3f85c9a2017-10-09 16:30:50 +0200321 shared_context_unlock(ssl_shctx);
Emeric Brun3e541d12012-09-03 11:14:36 +0200322
323 /* decode ASN1 session */
324 p = data;
325 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, data_len);
Emeric Brunaf9619d2012-11-28 18:47:52 +0100326 /* Reset session id and session id contenxt */
327 if (sess) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200328 SSL_SESSION_set1_id(sess, key, key_len);
329 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
Emeric Brunaf9619d2012-11-28 18:47:52 +0100330 }
Emeric Brun3e541d12012-09-03 11:14:36 +0200331
332 return sess;
333}
334
335/* SSL callback used to signal session is no more used in internal cache */
336void shctx_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
337{
338 struct shared_session *shsess;
339 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200340 unsigned int sid_length;
341 const unsigned char *sid_data;
Emeric Brun3e541d12012-09-03 11:14:36 +0200342 (void)ctx;
343
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200344 sid_data = SSL_SESSION_get_id(sess, &sid_length);
Emeric Brun3e541d12012-09-03 11:14:36 +0200345 /* tree key is zeros padded sessionid */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200346 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
347 memcpy(tmpkey, sid_data, sid_length);
348 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
349 sid_data = tmpkey;
Emeric Brun3e541d12012-09-03 11:14:36 +0200350 }
351
William Lallemand3f85c9a2017-10-09 16:30:50 +0200352 shared_context_lock(ssl_shctx);
Emeric Brun3e541d12012-09-03 11:14:36 +0200353
354 /* lookup for session */
William Lallemand3f85c9a2017-10-09 16:30:50 +0200355 shsess = shsess_tree_lookup(ssl_shctx, sid_data);
Emeric Brun3e541d12012-09-03 11:14:36 +0200356 if (shsess) {
Emeric Brunaf9619d2012-11-28 18:47:52 +0100357 /* free session */
358 shsess_tree_delete(shsess);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200359 shsess_free(ssl_shctx, shsess);
Emeric Brun3e541d12012-09-03 11:14:36 +0200360 }
361
362 /* unlock cache */
William Lallemand3f85c9a2017-10-09 16:30:50 +0200363 shared_context_unlock(ssl_shctx);
Emeric Brun3e541d12012-09-03 11:14:36 +0200364}
365
Emeric Brun3e541d12012-09-03 11:14:36 +0200366/* Allocate shared memory context.
Emeric Brunaf9619d2012-11-28 18:47:52 +0100367 * <size> is maximum cached sessions.
Emeric Brun22890a12012-12-28 14:41:32 +0100368 * If <size> is set to less or equal to 0, ssl cache is disabled.
Emeric Brunaf9619d2012-11-28 18:47:52 +0100369 * Returns: -1 on alloc failure, <size> if it performs context alloc,
370 * and 0 if cache is already allocated.
371 */
William Lallemand3f85c9a2017-10-09 16:30:50 +0200372int shared_context_init(struct shared_context **orig_shctx, int size, int shared)
Emeric Brun3e541d12012-09-03 11:14:36 +0200373{
374 int i;
William Lallemand3f85c9a2017-10-09 16:30:50 +0200375 struct shared_context *shctx;
376 int ret;
Emeric Brun9faf0712012-09-25 11:11:16 +0200377#ifndef USE_PRIVATE_CACHE
Emeric Bruncd1a5262014-05-07 23:11:42 +0200378#ifdef USE_PTHREAD_PSHARED
Emeric Brun3e541d12012-09-03 11:14:36 +0200379 pthread_mutexattr_t attr;
Emeric Bruncd1a5262014-05-07 23:11:42 +0200380#endif
Emeric Brun9faf0712012-09-25 11:11:16 +0200381#endif
Emeric Brunaf9619d2012-11-28 18:47:52 +0100382 struct shared_block *prev,*cur;
Emeric Brun4b3091e2012-09-24 15:48:52 +0200383 int maptype = MAP_PRIVATE;
Emeric Brun3e541d12012-09-03 11:14:36 +0200384
William Lallemand3f85c9a2017-10-09 16:30:50 +0200385 if (orig_shctx && *orig_shctx)
Emeric Brun3e541d12012-09-03 11:14:36 +0200386 return 0;
387
388 if (size<=0)
Emeric Brun22890a12012-12-28 14:41:32 +0100389 return 0;
Emeric Brun3e541d12012-09-03 11:14:36 +0200390
Emeric Brunaf9619d2012-11-28 18:47:52 +0100391 /* Increate size by one to reserve one node for lookup */
392 size++;
Emeric Brun9faf0712012-09-25 11:11:16 +0200393#ifndef USE_PRIVATE_CACHE
Emeric Brun4b3091e2012-09-24 15:48:52 +0200394 if (shared)
395 maptype = MAP_SHARED;
Emeric Brun9faf0712012-09-25 11:11:16 +0200396#endif
Emeric Brun4b3091e2012-09-24 15:48:52 +0200397
Emeric Brunaf9619d2012-11-28 18:47:52 +0100398 shctx = (struct shared_context *)mmap(NULL, sizeof(struct shared_context)+(size*sizeof(struct shared_block)),
Emeric Brun4b3091e2012-09-24 15:48:52 +0200399 PROT_READ | PROT_WRITE, maptype | MAP_ANON, -1, 0);
Emeric Brun3e541d12012-09-03 11:14:36 +0200400 if (!shctx || shctx == MAP_FAILED) {
401 shctx = NULL;
William Lallemand3f85c9a2017-10-09 16:30:50 +0200402 ret = SHCTX_E_ALLOC_CACHE;
403 goto err;
Emeric Brun3e541d12012-09-03 11:14:36 +0200404 }
405
Emeric Brun9faf0712012-09-25 11:11:16 +0200406#ifndef USE_PRIVATE_CACHE
Emeric Bruncaa19cc2014-05-07 16:10:18 +0200407 if (maptype == MAP_SHARED) {
Emeric Bruncd1a5262014-05-07 23:11:42 +0200408#ifdef USE_PTHREAD_PSHARED
Emeric Bruncaa19cc2014-05-07 16:10:18 +0200409 if (pthread_mutexattr_init(&attr)) {
410 munmap(shctx, sizeof(struct shared_context)+(size*sizeof(struct shared_block)));
411 shctx = NULL;
William Lallemand3f85c9a2017-10-09 16:30:50 +0200412 ret = SHCTX_E_INIT_LOCK;
413 goto err;
Emeric Bruncaa19cc2014-05-07 16:10:18 +0200414 }
415
416 if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
417 pthread_mutexattr_destroy(&attr);
418 munmap(shctx, sizeof(struct shared_context)+(size*sizeof(struct shared_block)));
419 shctx = NULL;
William Lallemand3f85c9a2017-10-09 16:30:50 +0200420 ret = SHCTX_E_INIT_LOCK;
421 goto err;
Emeric Bruncaa19cc2014-05-07 16:10:18 +0200422 }
423
424 if (pthread_mutex_init(&shctx->mutex, &attr)) {
425 pthread_mutexattr_destroy(&attr);
426 munmap(shctx, sizeof(struct shared_context)+(size*sizeof(struct shared_block)));
427 shctx = NULL;
William Lallemand3f85c9a2017-10-09 16:30:50 +0200428 ret = SHCTX_E_INIT_LOCK;
429 goto err;
Emeric Bruncaa19cc2014-05-07 16:10:18 +0200430 }
Emeric Bruncd1a5262014-05-07 23:11:42 +0200431#else
432 shctx->waiters = 0;
Emeric Brun3e541d12012-09-03 11:14:36 +0200433#endif
Emeric Brun4b3091e2012-09-24 15:48:52 +0200434 use_shared_mem = 1;
Emeric Bruncaa19cc2014-05-07 16:10:18 +0200435 }
Emeric Brun9faf0712012-09-25 11:11:16 +0200436#endif
Emeric Brun4b3091e2012-09-24 15:48:52 +0200437
Emeric Brunaf9619d2012-11-28 18:47:52 +0100438 memset(&shctx->active.data.session.key, 0, sizeof(struct ebmb_node));
439 memset(&shctx->free.data.session.key, 0, sizeof(struct ebmb_node));
Emeric Brun3e541d12012-09-03 11:14:36 +0200440
441 /* No duplicate authorized in tree: */
Emeric Brunaf9619d2012-11-28 18:47:52 +0100442 shctx->active.data.session.key.node.branches = EB_ROOT_UNIQUE;
443
Emeric Brun3e541d12012-09-03 11:14:36 +0200444 cur = &shctx->active;
445 cur->n = cur->p = cur;
446
447 cur = &shctx->free;
448 for (i = 0 ; i < size ; i++) {
449 prev = cur;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200450 cur++;
Emeric Brun3e541d12012-09-03 11:14:36 +0200451 prev->n = cur;
452 cur->p = prev;
453 }
454 cur->n = &shctx->free;
455 shctx->free.p = cur;
456
William Lallemand3f85c9a2017-10-09 16:30:50 +0200457 ret = size;
458
459err:
460 *orig_shctx = shctx;
461 return ret;
Emeric Brun3e541d12012-09-03 11:14:36 +0200462}
463
464
465/* Set session cache mode to server and disable openssl internal cache.
466 * Set shared cache callbacks on an ssl context.
467 * Shared context MUST be firstly initialized */
468void shared_context_set_cache(SSL_CTX *ctx)
469{
Emeric Brun786991e2012-11-26 18:37:12 +0100470 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
471
William Lallemand3f85c9a2017-10-09 16:30:50 +0200472 if (!ssl_shctx) {
Emeric Brun22890a12012-12-28 14:41:32 +0100473 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
Emeric Brun3e541d12012-09-03 11:14:36 +0200474 return;
Emeric Brun22890a12012-12-28 14:41:32 +0100475 }
476
477 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
478 SSL_SESS_CACHE_NO_INTERNAL |
479 SSL_SESS_CACHE_NO_AUTO_CLEAR);
Emeric Brun3e541d12012-09-03 11:14:36 +0200480
481 /* Set callbacks */
482 SSL_CTX_sess_set_new_cb(ctx, shctx_new_cb);
483 SSL_CTX_sess_set_get_cb(ctx, shctx_get_cb);
484 SSL_CTX_sess_set_remove_cb(ctx, shctx_remove_cb);
485}