blob: 9d4bea4ba3e397163ac5c9dee92a137604a89194 [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 +020024struct shared_context *shctx = NULL;
Emeric Brun4b3091e2012-09-24 15:48:52 +020025
William Lallemand24a7a752017-10-09 14:17:39 +020026#if !defined (USE_PRIVATE_CACHE)
27int use_shared_mem = 0;
Emeric Brun9faf0712012-09-25 11:11:16 +020028#endif
Emeric Brun3e541d12012-09-03 11:14:36 +020029
30/* List Macros */
31
Emeric Brunaf9619d2012-11-28 18:47:52 +010032#define shblock_unset(s) (s)->n->p = (s)->p; \
Emeric Brun3e541d12012-09-03 11:14:36 +020033 (s)->p->n = (s)->n;
34
Emeric Brunaf9619d2012-11-28 18:47:52 +010035#define shblock_set_free(s) shblock_unset(s) \
36 (s)->n = &shctx->free; \
37 (s)->p = shctx->free.p; \
38 shctx->free.p->n = s; \
39 shctx->free.p = s;
Emeric Brun3e541d12012-09-03 11:14:36 +020040
41
Emeric Brunaf9619d2012-11-28 18:47:52 +010042#define shblock_set_active(s) shblock_unset(s) \
43 (s)->n = &shctx->active; \
44 (s)->p = shctx->active.p; \
45 shctx->active.p->n = s; \
46 shctx->active.p = s;
Emeric Brun3e541d12012-09-03 11:14:36 +020047
48
Emeric Brun3e541d12012-09-03 11:14:36 +020049/* Tree Macros */
50
51#define shsess_tree_delete(s) ebmb_delete(&(s)->key);
52
Emeric Brunaf9619d2012-11-28 18:47:52 +010053#define shsess_tree_insert(s) (struct shared_session *)ebmb_insert(&shctx->active.data.session.key.node.branches, \
Emeric Brun3e541d12012-09-03 11:14:36 +020054 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
55
Emeric Brunaf9619d2012-11-28 18:47:52 +010056#define shsess_tree_lookup(k) (struct shared_session *)ebmb_lookup(&shctx->active.data.session.key.node.branches, \
Emeric Brun3e541d12012-09-03 11:14:36 +020057 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
58
Emeric Brunaf9619d2012-11-28 18:47:52 +010059/* shared session functions */
Emeric Brun3e541d12012-09-03 11:14:36 +020060
Emeric Brunaf9619d2012-11-28 18:47:52 +010061/* Free session blocks, returns number of freed blocks */
62static int shsess_free(struct shared_session *shsess)
63{
64 struct shared_block *block;
65 int ret = 1;
Emeric Brun3e541d12012-09-03 11:14:36 +020066
Emeric Brunaf9619d2012-11-28 18:47:52 +010067 if (((struct shared_block *)shsess)->data_len <= sizeof(shsess->data)) {
68 shblock_set_free((struct shared_block *)shsess);
69 return ret;
70 }
71 block = ((struct shared_block *)shsess)->n;
72 shblock_set_free((struct shared_block *)shsess);
73 while (1) {
74 struct shared_block *next;
Emeric Brun3e541d12012-09-03 11:14:36 +020075
Emeric Brunaf9619d2012-11-28 18:47:52 +010076 if (block->data_len <= sizeof(block->data)) {
77 /* last block */
78 shblock_set_free(block);
79 ret++;
80 break;
81 }
82 next = block->n;
83 shblock_set_free(block);
84 ret++;
85 block = next;
86 }
87 return ret;
88}
Emeric Brun3e541d12012-09-03 11:14:36 +020089
Emeric Brunaf9619d2012-11-28 18:47:52 +010090/* This function frees enough blocks to store a new session of data_len.
91 * Returns a ptr on a free block if it succeeds, or NULL if there are not
92 * enough blocks to store that session.
93 */
94static struct shared_session *shsess_get_next(int data_len)
Emeric Brun3e541d12012-09-03 11:14:36 +020095{
Emeric Brunaf9619d2012-11-28 18:47:52 +010096 int head = 0;
97 struct shared_block *b;
98
99 b = shctx->free.n;
100 while (b != &shctx->free) {
101 if (!head) {
102 data_len -= sizeof(b->data.session.data);
103 head = 1;
104 }
105 else
106 data_len -= sizeof(b->data.data);
107 if (data_len <= 0)
108 return &shctx->free.n->data.session;
109 b = b->n;
110 }
111 b = shctx->active.n;
112 while (b != &shctx->active) {
113 int freed;
114
115 shsess_tree_delete(&b->data.session);
116 freed = shsess_free(&b->data.session);
117 if (!head)
118 data_len -= sizeof(b->data.session.data) + (freed-1)*sizeof(b->data.data);
119 else
120 data_len -= freed*sizeof(b->data.data);
121 if (data_len <= 0)
122 return &shctx->free.n->data.session;
123 b = shctx->active.n;
124 }
125 return NULL;
126}
Emeric Brun3e541d12012-09-03 11:14:36 +0200127
Emeric Brunaf9619d2012-11-28 18:47:52 +0100128/* store a session into the cache
129 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
130 * data: asn1 encoded session
131 * data_len: asn1 encoded session length
132 * Returns 1 id session was stored (else 0)
133 */
134static int shsess_store(unsigned char *s_id, unsigned char *data, int data_len)
135{
136 struct shared_session *shsess, *oldshsess;
137
138 shsess = shsess_get_next(data_len);
139 if (!shsess) {
140 /* Could not retrieve enough free blocks to store that session */
Emeric Brun3e541d12012-09-03 11:14:36 +0200141 return 0;
Emeric Brunaf9619d2012-11-28 18:47:52 +0100142 }
Emeric Brun3e541d12012-09-03 11:14:36 +0200143
Emeric Brunaf9619d2012-11-28 18:47:52 +0100144 /* prepare key */
145 memcpy(shsess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
Emeric Brun3e541d12012-09-03 11:14:36 +0200146
Emeric Brunaf9619d2012-11-28 18:47:52 +0100147 /* it returns the already existing node
148 or current node if none, never returns null */
149 oldshsess = shsess_tree_insert(shsess);
150 if (oldshsess != shsess) {
151 /* free all blocks used by old node */
152 shsess_free(oldshsess);
153 shsess = oldshsess;
154 }
Emeric Brun3e541d12012-09-03 11:14:36 +0200155
Emeric Brunaf9619d2012-11-28 18:47:52 +0100156 ((struct shared_block *)shsess)->data_len = data_len;
157 if (data_len <= sizeof(shsess->data)) {
158 /* Store on a single block */
159 memcpy(shsess->data, data, data_len);
160 shblock_set_active((struct shared_block *)shsess);
161 }
162 else {
163 unsigned char *p;
164 /* Store on multiple blocks */
165 int cur_len;
Emeric Brun3e541d12012-09-03 11:14:36 +0200166
Emeric Brunaf9619d2012-11-28 18:47:52 +0100167 memcpy(shsess->data, data, sizeof(shsess->data));
168 p = data + sizeof(shsess->data);
169 cur_len = data_len - sizeof(shsess->data);
170 shblock_set_active((struct shared_block *)shsess);
171 while (1) {
172 /* Store next data on free block.
173 * shsess_get_next guarantees that there are enough
174 * free blocks in queue.
175 */
176 struct shared_block *block;
Emeric Brun3e541d12012-09-03 11:14:36 +0200177
Emeric Brunaf9619d2012-11-28 18:47:52 +0100178 block = shctx->free.n;
179 if (cur_len <= sizeof(block->data)) {
180 /* This is the last block */
181 block->data_len = cur_len;
182 memcpy(block->data.data, p, cur_len);
183 shblock_set_active(block);
184 break;
185 }
186 /* Intermediate block */
187 block->data_len = cur_len;
188 memcpy(block->data.data, p, sizeof(block->data));
189 p += sizeof(block->data.data);
190 cur_len -= sizeof(block->data.data);
191 shblock_set_active(block);
192 }
193 }
Emeric Brun3e541d12012-09-03 11:14:36 +0200194
Emeric Brunaf9619d2012-11-28 18:47:52 +0100195 return 1;
196}
Emeric Brun3e541d12012-09-03 11:14:36 +0200197
Emeric Brun3e541d12012-09-03 11:14:36 +0200198
Emeric Brunaf9619d2012-11-28 18:47:52 +0100199/* SSL context callbacks */
Emeric Brun3e541d12012-09-03 11:14:36 +0200200
Emeric Brunaf9619d2012-11-28 18:47:52 +0100201/* SSL callback used on new session creation */
202int shctx_new_cb(SSL *ssl, SSL_SESSION *sess)
203{
William Lallemand2a979662017-09-18 17:37:07 +0200204 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
205 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
Emeric Brunaf9619d2012-11-28 18:47:52 +0100206 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200207 int data_len;
208 unsigned int sid_length, sid_ctx_length;
209 const unsigned char *sid_data;
210 const unsigned char *sid_ctx_data;
Emeric Brun3e541d12012-09-03 11:14:36 +0200211
Emeric Brunaf9619d2012-11-28 18:47:52 +0100212 /* Session id is already stored in to key and session id is known
213 * so we dont store it to keep size.
214 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200215
216 sid_data = SSL_SESSION_get_id(sess, &sid_length);
217 sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
218 SSL_SESSION_set1_id(sess, sid_data, 0);
219 SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
Emeric Brun3e541d12012-09-03 11:14:36 +0200220
Emeric Brunaf9619d2012-11-28 18:47:52 +0100221 /* check if buffer is large enough for the ASN1 encoded session */
222 data_len = i2d_SSL_SESSION(sess, NULL);
223 if (data_len > SHSESS_MAX_DATA_LEN)
224 goto err;
225
William Lallemand2a979662017-09-18 17:37:07 +0200226 p = encsess;
227
Emeric Brunaf9619d2012-11-28 18:47:52 +0100228 /* process ASN1 session encoding before the lock */
Emeric Brunaf9619d2012-11-28 18:47:52 +0100229 i2d_SSL_SESSION(sess, &p);
230
William Lallemand2a979662017-09-18 17:37:07 +0200231 memcpy(encid, sid_data, sid_length);
Emeric Brunaf9619d2012-11-28 18:47:52 +0100232 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
William Lallemand2a979662017-09-18 17:37:07 +0200233 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
Emeric Brunaf9619d2012-11-28 18:47:52 +0100234
235 shared_context_lock();
236
237 /* store to cache */
William Lallemand2a979662017-09-18 17:37:07 +0200238 shsess_store(encid, encsess, data_len);
Emeric Brunaf9619d2012-11-28 18:47:52 +0100239
240 shared_context_unlock();
241
242err:
243 /* reset original length values */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200244 SSL_SESSION_set1_id(sess, sid_data, sid_length);
245 SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
Emeric Brun3e541d12012-09-03 11:14:36 +0200246
247 return 0; /* do not increment session reference count */
248}
249
250/* SSL callback used on lookup an existing session cause none found in internal cache */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200251SSL_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 +0200252{
253 struct shared_session *shsess;
254 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
255 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
Emeric Brunaf9619d2012-11-28 18:47:52 +0100256 int data_len;
Emeric Brun3e541d12012-09-03 11:14:36 +0200257 SSL_SESSION *sess;
Emeric Brun3e541d12012-09-03 11:14:36 +0200258
Willy Tarreauce3f9132014-05-28 16:47:01 +0200259 global.shctx_lookups++;
260
Emeric Brun3e541d12012-09-03 11:14:36 +0200261 /* allow the session to be freed automatically by openssl */
262 *do_copy = 0;
263
264 /* tree key is zeros padded sessionid */
265 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
266 memcpy(tmpkey, key, key_len);
267 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
268 key = tmpkey;
269 }
270
271 /* lock cache */
272 shared_context_lock();
273
274 /* lookup for session */
275 shsess = shsess_tree_lookup(key);
276 if (!shsess) {
277 /* no session found: unlock cache and exit */
278 shared_context_unlock();
Willy Tarreauce3f9132014-05-28 16:47:01 +0200279 global.shctx_misses++;
Emeric Brun3e541d12012-09-03 11:14:36 +0200280 return NULL;
281 }
282
Emeric Brunaf9619d2012-11-28 18:47:52 +0100283 data_len = ((struct shared_block *)shsess)->data_len;
284 if (data_len <= sizeof(shsess->data)) {
285 /* Session stored on single block */
286 memcpy(data, shsess->data, data_len);
287 shblock_set_active((struct shared_block *)shsess);
288 }
289 else {
290 /* Session stored on multiple blocks */
291 struct shared_block *block;
Emeric Brun3e541d12012-09-03 11:14:36 +0200292
Emeric Brunaf9619d2012-11-28 18:47:52 +0100293 memcpy(data, shsess->data, sizeof(shsess->data));
294 p = data + sizeof(shsess->data);
295 block = ((struct shared_block *)shsess)->n;
296 shblock_set_active((struct shared_block *)shsess);
297 while (1) {
298 /* Retrieve data from next block */
299 struct shared_block *next;
Emeric Brun3e541d12012-09-03 11:14:36 +0200300
Emeric Brunaf9619d2012-11-28 18:47:52 +0100301 if (block->data_len <= sizeof(block->data.data)) {
302 /* This is the last block */
303 memcpy(p, block->data.data, block->data_len);
304 p += block->data_len;
305 shblock_set_active(block);
306 break;
307 }
308 /* Intermediate block */
309 memcpy(p, block->data.data, sizeof(block->data.data));
310 p += sizeof(block->data.data);
311 next = block->n;
312 shblock_set_active(block);
313 block = next;
314 }
315 }
Emeric Brun3e541d12012-09-03 11:14:36 +0200316
317 shared_context_unlock();
318
319 /* decode ASN1 session */
320 p = data;
321 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, data_len);
Emeric Brunaf9619d2012-11-28 18:47:52 +0100322 /* Reset session id and session id contenxt */
323 if (sess) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200324 SSL_SESSION_set1_id(sess, key, key_len);
325 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
Emeric Brunaf9619d2012-11-28 18:47:52 +0100326 }
Emeric Brun3e541d12012-09-03 11:14:36 +0200327
328 return sess;
329}
330
331/* SSL callback used to signal session is no more used in internal cache */
332void shctx_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
333{
334 struct shared_session *shsess;
335 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200336 unsigned int sid_length;
337 const unsigned char *sid_data;
Emeric Brun3e541d12012-09-03 11:14:36 +0200338 (void)ctx;
339
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200340 sid_data = SSL_SESSION_get_id(sess, &sid_length);
Emeric Brun3e541d12012-09-03 11:14:36 +0200341 /* tree key is zeros padded sessionid */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200342 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
343 memcpy(tmpkey, sid_data, sid_length);
344 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
345 sid_data = tmpkey;
Emeric Brun3e541d12012-09-03 11:14:36 +0200346 }
347
348 shared_context_lock();
349
350 /* lookup for session */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200351 shsess = shsess_tree_lookup(sid_data);
Emeric Brun3e541d12012-09-03 11:14:36 +0200352 if (shsess) {
Emeric Brunaf9619d2012-11-28 18:47:52 +0100353 /* free session */
354 shsess_tree_delete(shsess);
355 shsess_free(shsess);
Emeric Brun3e541d12012-09-03 11:14:36 +0200356 }
357
358 /* unlock cache */
359 shared_context_unlock();
360}
361
Emeric Brun3e541d12012-09-03 11:14:36 +0200362/* Allocate shared memory context.
Emeric Brunaf9619d2012-11-28 18:47:52 +0100363 * <size> is maximum cached sessions.
Emeric Brun22890a12012-12-28 14:41:32 +0100364 * If <size> is set to less or equal to 0, ssl cache is disabled.
Emeric Brunaf9619d2012-11-28 18:47:52 +0100365 * Returns: -1 on alloc failure, <size> if it performs context alloc,
366 * and 0 if cache is already allocated.
367 */
Emeric Brun4b3091e2012-09-24 15:48:52 +0200368int shared_context_init(int size, int shared)
Emeric Brun3e541d12012-09-03 11:14:36 +0200369{
370 int i;
Emeric Brun9faf0712012-09-25 11:11:16 +0200371#ifndef USE_PRIVATE_CACHE
Emeric Bruncd1a5262014-05-07 23:11:42 +0200372#ifdef USE_PTHREAD_PSHARED
Emeric Brun3e541d12012-09-03 11:14:36 +0200373 pthread_mutexattr_t attr;
Emeric Bruncd1a5262014-05-07 23:11:42 +0200374#endif
Emeric Brun9faf0712012-09-25 11:11:16 +0200375#endif
Emeric Brunaf9619d2012-11-28 18:47:52 +0100376 struct shared_block *prev,*cur;
Emeric Brun4b3091e2012-09-24 15:48:52 +0200377 int maptype = MAP_PRIVATE;
Emeric Brun3e541d12012-09-03 11:14:36 +0200378
379 if (shctx)
380 return 0;
381
382 if (size<=0)
Emeric Brun22890a12012-12-28 14:41:32 +0100383 return 0;
Emeric Brun3e541d12012-09-03 11:14:36 +0200384
Emeric Brunaf9619d2012-11-28 18:47:52 +0100385 /* Increate size by one to reserve one node for lookup */
386 size++;
Emeric Brun9faf0712012-09-25 11:11:16 +0200387#ifndef USE_PRIVATE_CACHE
Emeric Brun4b3091e2012-09-24 15:48:52 +0200388 if (shared)
389 maptype = MAP_SHARED;
Emeric Brun9faf0712012-09-25 11:11:16 +0200390#endif
Emeric Brun4b3091e2012-09-24 15:48:52 +0200391
Emeric Brunaf9619d2012-11-28 18:47:52 +0100392 shctx = (struct shared_context *)mmap(NULL, sizeof(struct shared_context)+(size*sizeof(struct shared_block)),
Emeric Brun4b3091e2012-09-24 15:48:52 +0200393 PROT_READ | PROT_WRITE, maptype | MAP_ANON, -1, 0);
Emeric Brun3e541d12012-09-03 11:14:36 +0200394 if (!shctx || shctx == MAP_FAILED) {
395 shctx = NULL;
Emeric Bruncaa19cc2014-05-07 16:10:18 +0200396 return SHCTX_E_ALLOC_CACHE;
Emeric Brun3e541d12012-09-03 11:14:36 +0200397 }
398
Emeric Brun9faf0712012-09-25 11:11:16 +0200399#ifndef USE_PRIVATE_CACHE
Emeric Bruncaa19cc2014-05-07 16:10:18 +0200400 if (maptype == MAP_SHARED) {
Emeric Bruncd1a5262014-05-07 23:11:42 +0200401#ifdef USE_PTHREAD_PSHARED
Emeric Bruncaa19cc2014-05-07 16:10:18 +0200402 if (pthread_mutexattr_init(&attr)) {
403 munmap(shctx, sizeof(struct shared_context)+(size*sizeof(struct shared_block)));
404 shctx = NULL;
405 return SHCTX_E_INIT_LOCK;
406 }
407
408 if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
409 pthread_mutexattr_destroy(&attr);
410 munmap(shctx, sizeof(struct shared_context)+(size*sizeof(struct shared_block)));
411 shctx = NULL;
412 return SHCTX_E_INIT_LOCK;
413 }
414
415 if (pthread_mutex_init(&shctx->mutex, &attr)) {
416 pthread_mutexattr_destroy(&attr);
417 munmap(shctx, sizeof(struct shared_context)+(size*sizeof(struct shared_block)));
418 shctx = NULL;
419 return SHCTX_E_INIT_LOCK;
420 }
Emeric Bruncd1a5262014-05-07 23:11:42 +0200421#else
422 shctx->waiters = 0;
Emeric Brun3e541d12012-09-03 11:14:36 +0200423#endif
Emeric Brun4b3091e2012-09-24 15:48:52 +0200424 use_shared_mem = 1;
Emeric Bruncaa19cc2014-05-07 16:10:18 +0200425 }
Emeric Brun9faf0712012-09-25 11:11:16 +0200426#endif
Emeric Brun4b3091e2012-09-24 15:48:52 +0200427
Emeric Brunaf9619d2012-11-28 18:47:52 +0100428 memset(&shctx->active.data.session.key, 0, sizeof(struct ebmb_node));
429 memset(&shctx->free.data.session.key, 0, sizeof(struct ebmb_node));
Emeric Brun3e541d12012-09-03 11:14:36 +0200430
431 /* No duplicate authorized in tree: */
Emeric Brunaf9619d2012-11-28 18:47:52 +0100432 shctx->active.data.session.key.node.branches = EB_ROOT_UNIQUE;
433
Emeric Brun3e541d12012-09-03 11:14:36 +0200434 cur = &shctx->active;
435 cur->n = cur->p = cur;
436
437 cur = &shctx->free;
438 for (i = 0 ; i < size ; i++) {
439 prev = cur;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200440 cur++;
Emeric Brun3e541d12012-09-03 11:14:36 +0200441 prev->n = cur;
442 cur->p = prev;
443 }
444 cur->n = &shctx->free;
445 shctx->free.p = cur;
446
447 return size;
448}
449
450
451/* Set session cache mode to server and disable openssl internal cache.
452 * Set shared cache callbacks on an ssl context.
453 * Shared context MUST be firstly initialized */
454void shared_context_set_cache(SSL_CTX *ctx)
455{
Emeric Brun786991e2012-11-26 18:37:12 +0100456 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
457
Emeric Brun22890a12012-12-28 14:41:32 +0100458 if (!shctx) {
459 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
Emeric Brun3e541d12012-09-03 11:14:36 +0200460 return;
Emeric Brun22890a12012-12-28 14:41:32 +0100461 }
462
463 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
464 SSL_SESS_CACHE_NO_INTERNAL |
465 SSL_SESS_CACHE_NO_AUTO_CLEAR);
Emeric Brun3e541d12012-09-03 11:14:36 +0200466
467 /* Set callbacks */
468 SSL_CTX_sess_set_new_cb(ctx, shctx_new_cb);
469 SSL_CTX_sess_set_get_cb(ctx, shctx_get_cb);
470 SSL_CTX_sess_set_remove_cb(ctx, shctx_remove_cb);
471}