File: tls_init.c

package info (click to toggle)
kamailio 4.2.0-2%2Bdeb8u3
  • links: PTS, VCS
  • area: main
  • in suites: jessie
  • size: 56,276 kB
  • sloc: ansic: 552,836; xml: 166,484; sh: 8,659; makefile: 7,676; sql: 6,235; perl: 3,487; yacc: 3,428; python: 1,457; cpp: 1,219; php: 1,047; java: 449; pascal: 194; cs: 40; awk: 27
file content (691 lines) | stat: -rw-r--r-- 20,015 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
/* 
 * TLS module
 *
 * Copyright (C) 2005,2006 iptelorg GmbH
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/*! \defgroup tls SIP-router TLS support
 *
 * This modules implements SIP over TCP with TLS encryption.
 * Make sure you read the README file that describes configuration
 * of TLS for single servers and servers hosting multiple domains,
 * and thus using multiple SSL/TLS certificates.
 *
 *
 */
/*!
 * \file
 * \brief SIP-router TLS support :: Initialization
 * \ingroup tls
 * Module: \ref tls
 */



#include <stdio.h>
#include <sys/types.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <string.h>
#include <openssl/ssl.h>
 
#include "../../dprint.h"
#include "../../mem/shm_mem.h"
#include "../../tcp_init.h"
#include "../../socket_info.h"
#include "../../pt.h"
#include "../../cfg/cfg.h"
#include "../../cfg/cfg_ctx.h"
#include "tls_verify.h"
#include "tls_domain.h"
#include "tls_util.h"
#include "tls_mod.h"
#include "tls_init.h"
#include "tls_locking.h"
#include "tls_ct_wrq.h"
#include "tls_cfg.h"

/* will be set to 1 when the TLS env is initialized to make destroy safe */
static int tls_mod_initialized = 0;

#if OPENSSL_VERSION_NUMBER < 0x00907000L
#    warning ""
#    warning "==============================================================="
#    warning " Your version of OpenSSL is < 0.9.7."
#    warning " Upgrade for better compatibility, features and security fixes!"
#    warning "==============================================================="
#    warning ""
#endif

/* replace openssl zlib compression with our version if necessary
 * (the openssl zlib compression uses the wrong malloc, see
 *  openssl #1468): 0.9.8-dev < version  <0.9.8e-beta1 */
#if OPENSSL_VERSION_NUMBER >= 0x00908000L  /* 0.9.8-dev */ && \
		OPENSSL_VERSION_NUMBER <  0x00908051L  /* 0.9.8.e-beta1 */
#    ifndef OPENSSL_NO_COMP
#        warning "openssl zlib compression bug workaround enabled"
#    endif
#    define TLS_FIX_ZLIB_COMPRESSION
#    include "fixed_c_zlib.h"
#endif

#ifdef TLS_KSSL_WORKARROUND
#if OPENSSL_VERSION_NUMBER < 0x00908050L
#	warning "openssl lib compiled with kerberos support which introduces a bug\
 (wrong malloc/free used in kssl.c) -- attempting workaround"
#	warning "NOTE: if you don't link libssl staticaly don't try running the \
compiled code on a system with a differently compiled openssl (it's safer \
to compile on the  _target_ system)"
#endif /* OPENSSL_VERSION_NUMBER */
#endif /* TLS_KSSL_WORKARROUND */

/* openssl < 1. 0 */
#if OPENSSL_VERSION_NUMBER < 0x01000000L
#	warning "openssl < 1.0: no TLS extensions or server name support"
#endif /* OPENSSL_VERION < 1.0 */



#ifndef OPENSSL_NO_COMP
#define TLS_COMP_SUPPORT
#else
#undef TLS_COMP_SUPPORT
#endif

#ifndef OPENSSL_NO_KRB5
#define TLS_KERBEROS_SUPPORT
#else
#undef TLS_KERBEROS_SUPPORT
#endif


#ifdef TLS_KSSL_WORKARROUND
int openssl_kssl_malloc_bug=0; /* is openssl bug #1467 present ? */
#endif

const SSL_METHOD* ssl_methods[TLS_METHOD_MAX];

#ifdef NO_TLS_MALLOC_DBG
#undef TLS_MALLOC_DBG /* extra malloc debug info from openssl */
#endif /* NO_TLS_MALLOC_DBG */

/*
 * Wrappers around SER shared memory functions
 * (which can be macros)
 */
#ifdef TLS_MALLOC_DBG
#warning "tls module compiled with malloc debugging info (extra overhead)"
#include <execinfo.h>

/*
#define RAND_NULL_MALLOC (1024)
#define NULL_GRACE_PERIOD 10U
*/

inline static char* buf_append(char* buf, char* end, char* str, int str_len)
{
	if ( (buf+str_len)<end){
		memcpy(buf, str, str_len);
		return buf+str_len;
	}
	return 0;
}


inline static int backtrace2str(char* buf, int size)
{
	void* bt[32];
	int bt_size, i;
	char** bt_strs;
	char* p;
	char* end;
	char* next;
	char* s;
	char* e;
	
	p=buf; end=buf+size;
	bt_size=backtrace(bt, sizeof(bt)/sizeof(bt[0]));
	bt_strs=backtrace_symbols(bt, bt_size);
	if (bt_strs){
		p=buf; end=buf+size;
		/*if (bt_size>16) bt_size=16;*/ /* go up only 12 entries */
		for (i=3; i< bt_size; i++){
			/* try to isolate only the function name*/
			s=strchr(bt_strs[i], '(');
			if (s && ((e=strchr(s, ')'))!=0)){
				s++;
			}else if ((s=strchr(bt_strs[i], '['))!=0){
				e=s+strlen(s);
			}else{
				s=bt_strs[i]; e=s+strlen(s); /* add thw whole string */
			}
			next=buf_append(p, end, s, (int)(long)(e-s));
			if (next==0) break;
			else p=next;
			if (p<end){
				*p=':'; /* separator */
				p++;
			}else break;
		}
		if (p==buf){
			*p=0;
			p++;
		}else
			*(p-1)=0;
		free(bt_strs);
	}
	return (int)(long)(p-buf);
}

static void* ser_malloc(size_t size, const char* file, int line)
{
	void  *p;
	char bt_buf[1024];
	int s;
#ifdef RAND_NULL_MALLOC
	static ticks_t st=0;

	/* start random null returns only after 
	 * NULL_GRACE_PERIOD from first call */
	if (st==0) st=get_ticks();
	if (((get_ticks()-st)<NULL_GRACE_PERIOD) || (random()%RAND_NULL_MALLOC)){
#endif
		s=backtrace2str(bt_buf, sizeof(bt_buf));
		/* ugly hack: keep the bt inside the alloc'ed fragment */
		p=_shm_malloc(size+s, file, "via ser_malloc", line);
		if (p==0){
			LOG(L_CRIT, "tsl: ser_malloc(%d)[%s:%d]==null, bt: %s\n", 
						size, file, line, bt_buf);
		}else{
			memcpy(p+size, bt_buf, s);
			((struct qm_frag*)((char*)p-sizeof(struct qm_frag)))->func=
				p+size;
		}
#ifdef RAND_NULL_MALLOC
	}else{
		p=0;
		backtrace2str(bt_buf, sizeof(bt_buf));
		LOG(L_CRIT, "tsl: random ser_malloc(%d)[%s:%d]"
				" returning null - bt: %s\n",
				size, file, line, bt_buf);
	}
#endif
	return p;
}


static void* ser_realloc(void *ptr, size_t size, const char* file, int line)
{
	void  *p;
	char bt_buf[1024];
	int s;
#ifdef RAND_NULL_MALLOC
	static ticks_t st=0;

	/* start random null returns only after 
	 * NULL_GRACE_PERIOD from first call */
	if (st==0) st=get_ticks();
	if (((get_ticks()-st)<NULL_GRACE_PERIOD) || (random()%RAND_NULL_MALLOC)){
#endif
		s=backtrace2str(bt_buf, sizeof(bt_buf));
		p=_shm_realloc(ptr, size+s, file, "via ser_realloc", line);
		if (p==0){
			LOG(L_CRIT, "tsl: ser_realloc(%p, %d)[%s:%d]==null, bt: %s\n",
					ptr, size, file, line, bt_buf);
		}else{
			memcpy(p+size, bt_buf, s);
			((struct qm_frag*)((char*)p-sizeof(struct qm_frag)))->func=
				p+size;
		}
#ifdef RAND_NULL_MALLOC
	}else{
		p=0;
		backtrace2str(bt_buf, sizeof(bt_buf));
		LOG(L_CRIT, "tsl: random ser_realloc(%p, %d)[%s:%d]"
					" returning null - bt: %s\n", ptr, size, file, line,
					bt_buf);
	}
#endif
	return p;
}

#else /*TLS_MALLOC_DBG */

static void* ser_malloc(size_t size)
{
	return shm_malloc(size);
}


static void* ser_realloc(void *ptr, size_t size)
{
		return shm_realloc(ptr, size);
}

#endif

static void ser_free(void *ptr)
{
	/* The memory functions provided to openssl needs to behave like standard
	 * memory functions, i.e. free(). Therefore, ser_free must accept NULL
	 * pointers, see: http://openssl.6102.n7.nabble.com/Custom-free-routine-is-invoked-with-NULL-argument-in-openssl-1-0-1-td25937.html
	 * As shm_free() aborts on null pointers, we have to check for null pointer
	 * here in the wrapper function.
	 */
	if (ptr) {
		shm_free(ptr);
	}
}


/*
 * Initialize TLS socket
 */
int tls_h_init_si(struct socket_info *si)
{
	int ret;
	     /*
	      * reuse tcp initialization 
	      */
	ret = tcp_init(si);
	if (ret != 0) {
		ERR("Error while initializing TCP part of TLS socket %.*s:%d\n",
		    si->address_str.len, si->address_str.s, si->port_no);
		goto error;
	}
	
	si->proto = PROTO_TLS;
	return 0;
	
 error:
	if (si->socket != -1) {
		close(si->socket);
		si->socket = -1;
	}
	return ret;
}



/*
 * initialize ssl methods 
 */
static void init_ssl_methods(void)
{
	memset(ssl_methods, 0, sizeof(ssl_methods));

#ifndef OPENSSL_NO_SSL2
	ssl_methods[TLS_USE_SSLv2_cli - 1] = SSLv2_client_method();
	ssl_methods[TLS_USE_SSLv2_srv - 1] = SSLv2_server_method();
	ssl_methods[TLS_USE_SSLv2 - 1] = SSLv2_method();
#endif

	ssl_methods[TLS_USE_SSLv3_cli - 1] = SSLv3_client_method();
	ssl_methods[TLS_USE_SSLv3_srv - 1] = SSLv3_server_method();
	ssl_methods[TLS_USE_SSLv3 - 1] = SSLv3_method();

	ssl_methods[TLS_USE_TLSv1_cli - 1] = TLSv1_client_method();
	ssl_methods[TLS_USE_TLSv1_srv - 1] = TLSv1_server_method();
	ssl_methods[TLS_USE_TLSv1 - 1] = TLSv1_method();

	ssl_methods[TLS_USE_SSLv23_cli - 1] = SSLv23_client_method();
	ssl_methods[TLS_USE_SSLv23_srv - 1] = SSLv23_server_method();
	ssl_methods[TLS_USE_SSLv23 - 1] = SSLv23_method();

#if OPENSSL_VERSION_NUMBER >= 0x1000100fL
	ssl_methods[TLS_USE_TLSv1_1_cli - 1] = TLSv1_1_client_method();
	ssl_methods[TLS_USE_TLSv1_1_srv - 1] = TLSv1_1_server_method();
	ssl_methods[TLS_USE_TLSv1_1 - 1] = TLSv1_1_method();
#endif

#if OPENSSL_VERSION_NUMBER >= 0x1000105fL
	ssl_methods[TLS_USE_TLSv1_2_cli - 1] = TLSv1_2_client_method();
	ssl_methods[TLS_USE_TLSv1_2_srv - 1] = TLSv1_2_server_method();
	ssl_methods[TLS_USE_TLSv1_2 - 1] = TLSv1_2_method();
#endif
}


/*
 * Fix openssl compression bugs if necessary
 */
static int init_tls_compression(void)
{
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
	int n, r;
	STACK_OF(SSL_COMP)* comp_methods;
	SSL_COMP* zlib_comp;
	long ssl_version;
	
	/* disabling compression */
#	ifndef SSL_COMP_ZLIB_IDX
#		define SSL_COMP_ZLIB_IDX 1 /* openssl/ssl/ssl_ciph.c:84 */
#	endif 
	comp_methods = SSL_COMP_get_compression_methods();
	if (comp_methods == 0) {
		LOG(L_INFO, "tls: init_tls: compression support disabled in the"
					" openssl lib\n");
		goto end; /* nothing to do, exit */
	} else if (cfg_get(tls, tls_cfg, disable_compression)){
		LOG(L_INFO, "tls: init_tls: disabling compression...\n");
		sk_SSL_COMP_zero(comp_methods);
	}else{
		ssl_version=SSLeay();
		/* replace openssl zlib compression with our version if necessary
		 * (the openssl zlib compression uses the wrong malloc, see
		 *  openssl #1468): 0.9.8-dev < version  <0.9.8e-beta1 */
		if ((ssl_version >= 0x00908000L) && (ssl_version < 0x00908051L)){
			/* the above SSL_COMP_get_compression_methods() call has the side
			 * effect of initializing the compression stack (if not already
			 * initialized) => after it zlib is initialized and in the stack */
			/* find zlib_comp (cannot use ssl3_comp_find, not exported) */
			n = sk_SSL_COMP_num(comp_methods);
			zlib_comp = 0;
			for (r = 0; r < n; r++) {
				zlib_comp = sk_SSL_COMP_value(comp_methods, r);
				DBG("tls: init_tls: found compression method %p id %d\n",
						zlib_comp, zlib_comp->id);
				if (zlib_comp->id == SSL_COMP_ZLIB_IDX) {
					DBG("tls: init_tls: found zlib compression (%d)\n", 
							SSL_COMP_ZLIB_IDX);
					break /* found */;
				} else {
					zlib_comp = 0;
				}
			}
			if (zlib_comp == 0) {
				LOG(L_INFO, "tls: init_tls: no openssl zlib compression "
							"found\n");
			}else{
				LOG(L_WARN, "tls: init_tls: detected openssl lib with "
							"known zlib compression bug: \"%s\" (0x%08lx)\n",
							SSLeay_version(SSLEAY_VERSION), ssl_version);
#	ifdef TLS_FIX_ZLIB_COMPRESSION
				LOG(L_WARN, "tls: init_tls: enabling openssl zlib compression "
							"bug workaround (replacing zlib COMP method with "
							"our own version)\n");
				/* hack: make sure that the CRYPTO_EX_INDEX_COMP class is empty
				 * and it does not contain any free_ex_data from the 
				 * built-in zlib. This can happen if the current openssl
				 * zlib malloc fix patch is used (CRYPTO_get_ex_new_index() in
				 * COMP_zlib()). Unfortunately the only way
				 * to do this it to cleanup all the ex_data stuff.
				 * It should be safe if this is executed before SSL_init()
				 * (only the COMP class is initialized before).
				 */
				CRYPTO_cleanup_all_ex_data();
				
				if (fixed_c_zlib_init() != 0) {
					LOG(L_CRIT, "tls: init_tls: BUG: failed to initialize zlib"
							" compression fix, disabling compression...\n");
					sk_SSL_COMP_zero(comp_methods); /* delete compression */
					goto end;
				}
				/* "fix" it */
				zlib_comp->method = &zlib_method;
#	else
				LOG(L_WARN, "tls: init_tls: disabling openssl zlib "
							"compression \n");
				zlib_comp=sk_SSL_COMP_delete(comp_methods, r);
				if (zlib_comp)
					OPENSSL_free(zlib_comp);
#	endif
			}
		}
	}
end:
#endif /* OPENSSL_VERSION_NUMBER >= 0.9.8 */
	return 0;
}


/**
 * tls pre-init function
 */
int tls_pre_init(void)
{
	     /*
	      * this has to be called before any function calling CRYPTO_malloc,
	      * CRYPTO_malloc will set allow_customize in openssl to 0
	      */
#ifdef TLS_MALLOC_DBG
	if (!CRYPTO_set_mem_ex_functions(ser_malloc, ser_realloc, ser_free)) {
#else
	if (!CRYPTO_set_mem_functions(ser_malloc, ser_realloc, ser_free)) {
#endif
		ERR("Unable to set the memory allocation functions\n");
		return -1;
	}

	if (tls_init_locks()<0)
		return -1;

	init_tls_compression();

	return 0;
}

/*
 * First step of TLS initialization
 */
int init_tls_h(void)
{
	/*struct socket_info* si;*/
	long ssl_version;
	int lib_kerberos;
	int lib_zlib;
	int kerberos_support;
	int comp_support;
	const char* lib_cflags;
	int low_mem_threshold1;
	int low_mem_threshold2;
	str tls_grp;
	str s;
	cfg_ctx_t* cfg_ctx;

#if OPENSSL_VERSION_NUMBER < 0x00907000L
	WARN("You are using an old version of OpenSSL (< 0.9.7). Upgrade!\n");
#endif
	ssl_version=SSLeay();
	/* check if version have the same major minor and fix level
	 * (e.g. 0.9.8a & 0.9.8c are ok, but 0.9.8 and 0.9.9x are not)
	 * - values is represented as 0xMMNNFFPPS: major minor fix patch status
	 *   0x00090705f == 0.9.7e release */
	if ((ssl_version>>12)!=(OPENSSL_VERSION_NUMBER>>12)){
		LOG(L_CRIT, "ERROR: tls: init_tls_h: installed openssl library "
				"version is too different from the library the ser tls module "
				"was compiled with: installed \"%s\" (0x%08lx), compiled "
				"\"%s\" (0x%08lx).\n"
				" Please make sure a compatible version is used"
				" (tls_force_run in ser.cfg will override this check)\n",
				SSLeay_version(SSLEAY_VERSION), ssl_version,
				OPENSSL_VERSION_TEXT, (long)OPENSSL_VERSION_NUMBER);
		if (cfg_get(tls, tls_cfg, force_run))
			LOG(L_WARN, "tls: init_tls_h: tls_force_run turned on, ignoring "
						" openssl version mismatch\n");
		else
			return -1; /* safer to exit */
	}
#ifdef TLS_KERBEROS_SUPPORT
	kerberos_support=1;
#else
	kerberos_support=0;
#endif
#ifdef TLS_COMP_SUPPORT
	comp_support=1;
#else
	comp_support=0;
#endif
	/* attempt to guess if the library was compiled with kerberos or
	 * compression support from the cflags */
	lib_cflags=SSLeay_version(SSLEAY_CFLAGS);
	lib_kerberos=0;
	lib_zlib=0;
	if ((lib_cflags==0) || strstr(lib_cflags, "not available")){ 
		lib_kerberos=-1;
		lib_zlib=-1;
	}else{
		if (strstr(lib_cflags, "-DZLIB"))
			lib_zlib=1;
		if (strstr(lib_cflags, "-DKRB5_"))
			lib_kerberos=1;
	}
	LOG(L_INFO, "tls: _init_tls_h:  compiled  with  openssl  version " 
				"\"%s\" (0x%08lx), kerberos support: %s, compression: %s\n",
				OPENSSL_VERSION_TEXT, (long)OPENSSL_VERSION_NUMBER,
				kerberos_support?"on":"off", comp_support?"on":"off");
	LOG(L_INFO, "tls: init_tls_h: installed openssl library version "
				"\"%s\" (0x%08lx), kerberos support: %s, "
				" zlib compression: %s"
				"\n %s\n",
				SSLeay_version(SSLEAY_VERSION), ssl_version,
				(lib_kerberos==1)?"on":(lib_kerberos==0)?"off":"unknown",
				(lib_zlib==1)?"on":(lib_zlib==0)?"off":"unknown",
				SSLeay_version(SSLEAY_CFLAGS));
	if (lib_kerberos!=kerberos_support){
		if (lib_kerberos!=-1){
			LOG(L_CRIT, "ERROR: tls: init_tls_h: openssl compile options"
						" mismatch: library has kerberos support"
						" %s and ser tls %s (unstable configuration)\n"
						" (tls_force_run in ser.cfg will override this"
						" check)\n",
						lib_kerberos?"enabled":"disabled",
						kerberos_support?"enabled":"disabled"
				);
			if (cfg_get(tls, tls_cfg, force_run))
				LOG(L_WARN, "tls: init_tls_h: tls_force_run turned on, "
						"ignoring kerberos support mismatch\n");
			else
				return -1; /* exit, is safer */
		}else{
			LOG(L_WARN, "WARNING: tls: init_tls_h: openssl  compile options"
						" missing -- cannot detect if kerberos support is"
						" enabled. Possible unstable configuration\n");
		}
	}

	#ifdef TLS_KSSL_WORKARROUND
	/* if openssl compiled with kerberos support, and openssl < 0.9.8e-dev
	 * or openssl between 0.9.9-dev and 0.9.9-beta1 apply workaround for
	 * openssl bug #1467 */
	if (ssl_version < 0x00908050L || 
			(ssl_version >= 0x00909000L && ssl_version < 0x00909001L)){
		openssl_kssl_malloc_bug=1;
		LOG(L_WARN, "tls: init_tls_h: openssl kerberos malloc bug detected, "
			" kerberos support will be disabled...\n");
	}
	#endif
	/* set free memory threshold for openssl bug #1491 workaround */
	low_mem_threshold1 = cfg_get(tls, tls_cfg, low_mem_threshold1);
	low_mem_threshold2 = cfg_get(tls, tls_cfg, low_mem_threshold2);
	if (low_mem_threshold1<0){
		/* default */
		low_mem_threshold1=512*1024*get_max_procs();
	}else
		low_mem_threshold1*=1024; /* KB */
	if (low_mem_threshold2<0){
		/* default */
		low_mem_threshold2=256*1024*get_max_procs();
	}else
		low_mem_threshold2*=1024; /* KB */
	if ((low_mem_threshold1==0) || (low_mem_threshold2==0))
		LOG(L_WARN, "tls: openssl bug #1491 (crash/mem leaks on low memory)"
					" workarround disabled\n");
	else
		LOG(L_WARN, "tls: openssl bug #1491 (crash/mem leaks on low memory)"
				" workaround enabled (on low memory tls operations will fail"
				" preemptively) with free memory thresholds %d and %d bytes\n",
				low_mem_threshold1, low_mem_threshold2);
	
	if (shm_available()==(unsigned long)(-1)){
		LOG(L_WARN, "tls: ser compiled without MALLOC_STATS support:"
				" the workaround for low mem. openssl bugs will _not_ "
				"work\n");
		low_mem_threshold1=0;
		low_mem_threshold2=0;
	}
	if ((low_mem_threshold1 != cfg_get(tls, tls_cfg, low_mem_threshold1)) ||
	    (low_mem_threshold2 != cfg_get(tls, tls_cfg, low_mem_threshold2))) {
		/* ugly hack to set the initial values for the mem tresholds */
		if (cfg_register_ctx(&cfg_ctx, 0)) {
			ERR("failed to register cfg context\n");
			return -1;
		}
		tls_grp.s = "tls";
		tls_grp.len = strlen(tls_grp.s);
		s.s = "low_mem_threshold1";
		s.len = strlen(s.s);
		if (low_mem_threshold1 != cfg_get(tls, tls_cfg, low_mem_threshold1) &&
				cfg_set_now_int(cfg_ctx, &tls_grp, NULL /* group id */, &s, low_mem_threshold1)) {
			ERR("failed to set tls.low_mem_threshold1 to %d\n",
					low_mem_threshold1);
			return -1;
		}
		s.s = "low_mem_threshold2";
		s.len = strlen(s.s);
		if (low_mem_threshold2 != cfg_get(tls, tls_cfg, low_mem_threshold2) &&
				cfg_set_now_int(cfg_ctx, &tls_grp, NULL /* group id */, &s, low_mem_threshold2)) {
			ERR("failed to set tls.low_mem_threshold1 to %d\n",
					low_mem_threshold2);
			return -1;
		}
	}
	
	SSL_library_init();
	SSL_load_error_strings();
	init_ssl_methods();
	tls_mod_initialized = 1;
	return 0;
}


/*
 * Make sure that all server domains in the configuration have corresponding
 * listening socket in SER
 */
int tls_check_sockets(tls_domains_cfg_t* cfg)
{
	tls_domain_t* d;

	if (!cfg) return 0;

	d = cfg->srv_list;
	while(d) {
		if (d->ip.len && !find_si(&d->ip, d->port, PROTO_TLS)) {
			ERR("%s: No listening socket found\n", tls_domain_str(d));
			return -1;
		}
		d = d->next;
	}
	return 0;
}


/*
 * TLS cleanup when SER exits
 */
void destroy_tls_h(void)
{
	DBG("tls module final tls destroy\n");
	if(tls_mod_initialized > 0)
		ERR_free_strings();
	/* TODO: free all the ctx'es */
	tls_destroy_cfg();
	tls_destroy_locks();
	tls_ct_wq_destroy();
}