28
28
#include "cachedb_redis_utils.h"
29
29
#include "../../mem/mem.h"
30
30
#include "../../ut.h"
31
+ #include "../../pt.h"
31
32
#include "../../cachedb/cachedb.h"
32
33
33
34
#include <string.h>
38
39
int redis_query_tout = CACHEDB_REDIS_DEFAULT_TIMEOUT ;
39
40
int redis_connnection_tout = CACHEDB_REDIS_DEFAULT_TIMEOUT ;
40
41
int shutdown_on_error = 0 ;
42
+ int use_tls = 0 ;
43
+
44
+ struct tls_mgm_binds tls_api ;
41
45
42
46
redisContext * redis_get_ctx (char * ip , int port )
43
47
{
@@ -71,6 +75,64 @@ redisContext *redis_get_ctx(char *ip, int port)
71
75
return ctx ;
72
76
}
73
77
78
+ #ifdef HAVE_REDIS_SSL
79
+ static void tls_print_errstack (void )
80
+ {
81
+ int code ;
82
+
83
+ while ((code = ERR_get_error ())) {
84
+ LM_ERR ("TLS errstack: %s\n" , ERR_error_string (code , 0 ));
85
+ }
86
+ }
87
+
88
+ static int redis_init_ssl (char * url_extra_opts , redisContext * ctx ,
89
+ struct tls_domain * * tls_dom )
90
+ {
91
+ str tls_dom_name ;
92
+ SSL * ssl ;
93
+
94
+ if (* tls_dom == NULL ) {
95
+ if (strncmp (url_extra_opts , CACHEDB_TLS_DOM_PARAM ,
96
+ CACHEDB_TLS_DOM_PARAM_LEN )) {
97
+ LM_ERR ("Invalid Redis URL parameter: %s\n" , url_extra_opts );
98
+ return -1 ;
99
+ }
100
+
101
+ tls_dom_name .s = url_extra_opts + CACHEDB_TLS_DOM_PARAM_LEN ;
102
+ tls_dom_name .len = strlen (tls_dom_name .s );
103
+ if (!tls_dom_name .len ) {
104
+ LM_ERR ("Empty TLS domain name in Redis URL\n" );
105
+ return -1 ;
106
+ }
107
+
108
+ * tls_dom = tls_api .find_client_domain_name (& tls_dom_name );
109
+ if (* tls_dom == NULL ) {
110
+ LM_ERR ("TLS domain: %.*s not found\n" ,
111
+ tls_dom_name .len , tls_dom_name .s );
112
+ return -1 ;
113
+ }
114
+ }
115
+
116
+ ssl = SSL_new ((* tls_dom )-> ctx [process_no ]);
117
+ if (!ssl ) {
118
+ LM_ERR ("failed to create SSL structure (%d:%s)\n" , errno , strerror (errno ));
119
+ tls_print_errstack ();
120
+ tls_api .release_domain (* tls_dom );
121
+ return -1 ;
122
+ }
123
+
124
+ if (redisInitiateSSL (ctx , ssl ) != REDIS_OK ) {
125
+ printf ("Failed to init Redis SSL: %s\n" , ctx -> errstr );
126
+ tls_api .release_domain (* tls_dom );
127
+ return -1 ;
128
+ }
129
+
130
+ LM_DBG ("TLS enabled for this connection\n" );
131
+
132
+ return 0 ;
133
+ }
134
+ #endif
135
+
74
136
int redis_connect_node (redis_con * con ,cluster_node * node )
75
137
{
76
138
redisReply * rpl ;
@@ -79,14 +141,22 @@ int redis_connect_node(redis_con *con,cluster_node *node)
79
141
if (!node -> context )
80
142
return -1 ;
81
143
144
+ #ifdef HAVE_REDIS_SSL
145
+ if (use_tls && con -> id -> extra_options &&
146
+ redis_init_ssl (con -> id -> extra_options , node -> context ,
147
+ & node -> tls_dom ) < 0 ) {
148
+ redisFree (node -> context );
149
+ return -1 ;
150
+ }
151
+ #endif
152
+
82
153
if (con -> id -> password ) {
83
154
rpl = redisCommand (node -> context ,"AUTH %s" ,con -> id -> password );
84
155
if (rpl == NULL || rpl -> type == REDIS_REPLY_ERROR ) {
85
156
LM_ERR ("failed to auth to redis - %.*s\n" ,
86
157
rpl ?(unsigned )rpl -> len :7 ,rpl ?rpl -> str :"FAILURE" );
87
158
freeReplyObject (rpl );
88
- redisFree (node -> context );
89
- return -1 ;
159
+ goto error ;
90
160
}
91
161
LM_DBG ("AUTH [password] - %.*s\n" ,(unsigned )rpl -> len ,rpl -> str );
92
162
freeReplyObject (rpl );
@@ -98,15 +168,22 @@ int redis_connect_node(redis_con *con,cluster_node *node)
98
168
LM_ERR ("failed to select database %s - %.*s\n" ,con -> id -> database ,
99
169
rpl ?(unsigned )rpl -> len :7 ,rpl ?rpl -> str :"FAILURE" );
100
170
freeReplyObject (rpl );
101
- redisFree (node -> context );
102
- return -1 ;
171
+ goto error ;
103
172
}
104
173
105
174
LM_DBG ("SELECT [%s] - %.*s\n" ,con -> id -> database ,(unsigned )rpl -> len ,rpl -> str );
106
175
freeReplyObject (rpl );
107
176
}
108
177
109
178
return 0 ;
179
+
180
+ error :
181
+ redisFree (node -> context );
182
+ if (use_tls && node -> tls_dom ) {
183
+ tls_api .release_domain (node -> tls_dom );
184
+ node -> tls_dom = NULL ;
185
+ }
186
+ return -1 ;
110
187
}
111
188
112
189
int redis_reconnect_node (redis_con * con ,cluster_node * node )
@@ -120,19 +197,27 @@ int redis_reconnect_node(redis_con *con,cluster_node *node)
120
197
return redis_connect_node (con ,node );
121
198
}
122
199
123
-
124
200
int redis_connect (redis_con * con )
125
201
{
126
202
redisContext * ctx ;
127
203
redisReply * rpl ;
128
204
cluster_node * it ;
129
205
int len ;
206
+ struct tls_domain * tls_dom = NULL ;
130
207
131
208
/* connect to redis DB */
132
209
ctx = redis_get_ctx (con -> id -> host ,con -> id -> port );
133
210
if (!ctx )
134
211
return -1 ;
135
212
213
+ #ifdef HAVE_REDIS_SSL
214
+ if (use_tls && con -> id -> extra_options &&
215
+ redis_init_ssl (con -> id -> extra_options , ctx , & tls_dom ) < 0 ) {
216
+ redisFree (ctx );
217
+ return -1 ;
218
+ }
219
+ #endif
220
+
136
221
/* auth using password, if any */
137
222
if (con -> id -> password ) {
138
223
rpl = redisCommand (ctx ,"AUTH %s" ,con -> id -> password );
@@ -141,8 +226,7 @@ int redis_connect(redis_con *con)
141
226
rpl ?(unsigned )rpl -> len :7 ,rpl ?rpl -> str :"FAILURE" );
142
227
if (rpl != NULL )
143
228
freeReplyObject (rpl );
144
- redisFree (ctx );
145
- return -1 ;
229
+ goto error ;
146
230
}
147
231
LM_DBG ("AUTH [password] - %.*s\n" ,(unsigned )rpl -> len ,rpl -> str );
148
232
freeReplyObject (rpl );
@@ -158,8 +242,7 @@ int redis_connect(redis_con *con)
158
242
LM_ERR ("no more pkg\n" );
159
243
if (rpl != NULL )
160
244
freeReplyObject (rpl );
161
- redisFree (ctx );
162
- return -1 ;
245
+ goto error ;
163
246
}
164
247
con -> nodes -> ip = (char * )(con -> nodes + 1 );
165
248
@@ -178,15 +261,17 @@ int redis_connect(redis_con *con)
178
261
if (build_cluster_nodes (con ,rpl -> str ,rpl -> len ) < 0 ) {
179
262
LM_ERR ("failed to parse Redis cluster info\n" );
180
263
freeReplyObject (rpl );
181
- redisFree (ctx );
182
- return -1 ;
264
+ goto error ;
183
265
}
184
266
}
185
267
186
268
if (rpl != NULL )
187
269
freeReplyObject (rpl );
188
270
redisFree (ctx );
189
271
272
+ if (use_tls && tls_dom )
273
+ tls_api .release_domain (tls_dom );
274
+
190
275
con -> flags |= REDIS_INIT_NODES ;
191
276
192
277
for (it = con -> nodes ;it ;it = it -> next ) {
@@ -201,6 +286,12 @@ int redis_connect(redis_con *con)
201
286
}
202
287
203
288
return 0 ;
289
+
290
+ error :
291
+ redisFree (ctx );
292
+ if (use_tls && tls_dom )
293
+ tls_api .release_domain (tls_dom );
294
+ return -1 ;
204
295
}
205
296
206
297
redis_con * redis_new_connection (struct cachedb_id * id )
0 commit comments