Revert "tls: proper ifdef on libssl version for tls_init_locks()"
[kamailio] / src / modules / tls / tls_locking.c
1 /*
2  * TLS module
3  *
4  * Copyright (C) 2007 iptelorg GmbH
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18
19 /*!
20  * \file
21  * \brief Kamailio TLS support :: Locking
22  * \ingroup tls
23  * Module: \ref tls
24  */
25
26
27 #include <stdlib.h> /* abort() */
28 #include <openssl/crypto.h>
29 #include "../../core/dprint.h"
30 #include "../../core/locking.h"
31
32 static int n_static_locks=0;
33 static gen_lock_set_t* static_locks=0;
34
35 /* OpenSSL is thread-safe since 1.1.0 */
36 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
37
38 /* "dynamic" locks */
39
40 struct CRYPTO_dynlock_value{
41         gen_lock_t lock;
42 };
43
44
45 static struct CRYPTO_dynlock_value* dyn_create_f(const char* file, int line)
46 {
47         struct CRYPTO_dynlock_value* l;
48
49         l=shm_malloc(sizeof(struct CRYPTO_dynlock_value));
50         if (l==0){
51                 LM_CRIT("dyn create locking callback out of shm."
52                                 " memory (called from %s:%d)\n", file, line);
53                 goto error;
54         }
55         if (lock_init(&l->lock)==0){
56                 LM_CRIT("dyn create locking callback: lock "
57                                 "initialization failed (called from %s:%d)\n", file, line);
58                 shm_free(l);
59                 goto error;
60         }
61         return l;
62 error:
63         return 0;
64 }
65
66
67 static void dyn_lock_f(int mode, struct CRYPTO_dynlock_value* l,
68                                                 const char* file, int line)
69 {
70         if (l==0){
71                 LM_CRIT("dyn lock locking callback: null lock"
72                                 " (called from %s:%d)\n", file, line);
73                 /* try to continue */
74                 return;
75         }
76         if (mode & CRYPTO_LOCK){
77                 lock_get(&l->lock);
78         }else{
79                 lock_release(&l->lock);
80         }
81 }
82
83
84
85 static void dyn_destroy_f(struct CRYPTO_dynlock_value *l,
86                                                         const char* file, int line)
87 {
88         if (l==0){
89                 LM_CRIT("dyn destroy locking callback: null lock"
90                                 " (called from %s:%d)\n", file, line);
91                 return;
92         }
93         lock_destroy(&l->lock);
94         shm_free(l);
95 }
96
97
98
99 /* normal locking callback */
100 static void locking_f(int mode, int n, const char* file, int line)
101 {
102         if (n<0 || n>=n_static_locks){
103                 LM_CRIT("locking (callback): invalid lock number: "
104                                 " %d (range 0 - %d), called from %s:%d\n",
105                                 n, n_static_locks, file, line);
106                 abort(); /* quick crash :-) */
107         }
108         if (mode & CRYPTO_LOCK){
109 #ifdef EXTRA_DEBUG
110                 LM_DBG("lock get (%d): %d (%s:%d)\n", mode, n, file, line);
111 #endif
112                 lock_set_get(static_locks, n);
113         }else{
114                 lock_set_release(static_locks, n);
115 #ifdef EXTRA_DEBUG
116                 LM_DBG("lock release (%d): %d (%s:%d)\n", mode, n, file, line);
117 #endif
118         }
119 }
120
121 #endif /* openssl < 0x10100000L (1.1.0) or LibreSSL */
122
123
124 void tls_destroy_locks()
125 {
126         if (static_locks){
127                 lock_set_destroy(static_locks);
128                 lock_set_dealloc(static_locks);
129                 static_locks=0;
130                 n_static_locks=0;
131         }
132 }
133
134
135 unsigned long sr_ssl_id_f()
136 {
137         return my_pid();
138 }
139
140 /* returns -1 on error, 0 on success */
141 int tls_init_locks()
142 {
143 /* OpenSSL is thread-safe since 1.1.0 */
144 #if OPENSSL_VERSION_NUMBER < 0x10100000L
145         /* init "static" tls locks */
146         n_static_locks=CRYPTO_num_locks();
147         if (n_static_locks<0){
148                 LM_CRIT("bad CRYPTO_num_locks %d\n", n_static_locks);
149                 n_static_locks=0;
150         }
151         if (n_static_locks){
152                 if (CRYPTO_get_locking_callback()!=NULL) {
153                         LM_CRIT("ssl locking callback already set\n");
154                         return -1;
155                 }
156                 static_locks=lock_set_alloc(n_static_locks);
157                 if (static_locks==0){
158                         LM_CRIT("could not allocate lockset with %d locks\n",
159                                         n_static_locks);
160                         goto error;
161                 }
162                 if (lock_set_init(static_locks)==0){
163                         LM_CRIT("lock set init failed (%d locks)\n", n_static_locks);
164                         lock_set_dealloc(static_locks);
165                         static_locks=0;
166                         n_static_locks=0;
167                         goto error;
168                 }
169                 CRYPTO_set_locking_callback(locking_f);
170         }
171
172         /* set "dynamic" locks callbacks */
173         CRYPTO_set_dynlock_create_callback(dyn_create_f);
174         CRYPTO_set_dynlock_lock_callback(dyn_lock_f);
175         CRYPTO_set_dynlock_destroy_callback(dyn_destroy_f);
176
177         /* starting with v1.0.0 openssl does not use anymore getpid(), but address
178          * of errno which can point to same virtual address in a multi-process
179          * application
180          * - for refrence http://www.openssl.org/docs/crypto/threads.html
181          */
182         CRYPTO_set_id_callback(sr_ssl_id_f);
183
184         /* atomic add -- since for now we don't have atomic_add
185          *  (only atomic_inc), fallback to the default use-locks mode
186          * CRYPTO_set_add_lock_callback(atomic_add_f);
187          */
188 #endif
189
190         return 0;
191 error:
192         tls_destroy_locks();
193         return -1;
194 }