/src/unbound/util/net_help.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * util/net_help.c - implementation of the network helper code |
3 | | * |
4 | | * Copyright (c) 2007, NLnet Labs. All rights reserved. |
5 | | * |
6 | | * This software is open source. |
7 | | * |
8 | | * Redistribution and use in source and binary forms, with or without |
9 | | * modification, are permitted provided that the following conditions |
10 | | * are met: |
11 | | * |
12 | | * Redistributions of source code must retain the above copyright notice, |
13 | | * this list of conditions and the following disclaimer. |
14 | | * |
15 | | * Redistributions in binary form must reproduce the above copyright notice, |
16 | | * this list of conditions and the following disclaimer in the documentation |
17 | | * and/or other materials provided with the distribution. |
18 | | * |
19 | | * Neither the name of the NLNET LABS nor the names of its contributors may |
20 | | * be used to endorse or promote products derived from this software without |
21 | | * specific prior written permission. |
22 | | * |
23 | | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
24 | | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
25 | | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
26 | | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
27 | | * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
28 | | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED |
29 | | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
30 | | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
31 | | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
32 | | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
33 | | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
34 | | */ |
35 | | /** |
36 | | * \file |
37 | | * Implementation of net_help.h. |
38 | | */ |
39 | | |
40 | | #include "config.h" |
41 | | #ifdef HAVE_SYS_TYPES_H |
42 | | # include <sys/types.h> |
43 | | #endif |
44 | | #ifdef HAVE_NET_IF_H |
45 | | #include <net/if.h> |
46 | | #endif |
47 | | #ifdef HAVE_NETIOAPI_H |
48 | | #include <netioapi.h> |
49 | | #endif |
50 | | #include "util/net_help.h" |
51 | | #include "util/log.h" |
52 | | #include "util/data/dname.h" |
53 | | #include "util/module.h" |
54 | | #include "util/regional.h" |
55 | | #include "util/config_file.h" |
56 | | #include "sldns/parseutil.h" |
57 | | #include "sldns/wire2str.h" |
58 | | #include "sldns/str2wire.h" |
59 | | #include <fcntl.h> |
60 | | #ifdef HAVE_OPENSSL_SSL_H |
61 | | #include <openssl/ssl.h> |
62 | | #include <openssl/evp.h> |
63 | | #include <openssl/rand.h> |
64 | | #endif |
65 | | #ifdef HAVE_OPENSSL_ERR_H |
66 | | #include <openssl/err.h> |
67 | | #endif |
68 | | #ifdef HAVE_OPENSSL_CORE_NAMES_H |
69 | | #include <openssl/core_names.h> |
70 | | #endif |
71 | | #ifdef USE_WINSOCK |
72 | | #include <wincrypt.h> |
73 | | #endif |
74 | | #ifdef HAVE_NGHTTP2_NGHTTP2_H |
75 | | #include <nghttp2/nghttp2.h> |
76 | | #endif |
77 | | |
78 | | /** max length of an IP address (the address portion) that we allow */ |
79 | 0 | #define MAX_ADDR_STRLEN 128 /* characters */ |
80 | | /** default value for EDNS ADVERTISED size */ |
81 | | uint16_t EDNS_ADVERTISED_SIZE = 4096; |
82 | | |
83 | | /** minimal responses when positive answer: default is no */ |
84 | | int MINIMAL_RESPONSES = 0; |
85 | | |
86 | | /** rrset order roundrobin: default is yes */ |
87 | | int RRSET_ROUNDROBIN = 1; |
88 | | |
89 | | /** log tag queries with name instead of 'info' for filtering */ |
90 | | int LOG_TAG_QUERYREPLY = 0; |
91 | | |
92 | | static struct tls_session_ticket_key { |
93 | | unsigned char *key_name; |
94 | | unsigned char *aes_key; |
95 | | unsigned char *hmac_key; |
96 | | } *ticket_keys; |
97 | | |
98 | | #ifdef HAVE_SSL |
99 | | /** |
100 | | * callback TLS session ticket encrypt and decrypt |
101 | | * For use with SSL_CTX_set_tlsext_ticket_key_cb or |
102 | | * SSL_CTX_set_tlsext_ticket_key_evp_cb |
103 | | * @param s: the SSL_CTX to use (from connect_sslctx_create()) |
104 | | * @param key_name: secret name, 16 bytes |
105 | | * @param iv: up to EVP_MAX_IV_LENGTH. |
106 | | * @param evp_ctx: the evp cipher context, function sets this. |
107 | | * @param hmac_ctx: the hmac context, function sets this. |
108 | | * with ..key_cb it is of type HMAC_CTX* |
109 | | * with ..key_evp_cb it is of type EVP_MAC_CTX* |
110 | | * @param enc: 1 is encrypt, 0 is decrypt |
111 | | * @return 0 on no ticket, 1 for okay, and 2 for okay but renew the ticket |
112 | | * (the ticket is decrypt only). and <0 for failures. |
113 | | */ |
114 | | int tls_session_ticket_key_cb(SSL *s, unsigned char* key_name, |
115 | | unsigned char* iv, EVP_CIPHER_CTX *evp_ctx, |
116 | | #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB |
117 | | EVP_MAC_CTX *hmac_ctx, |
118 | | #else |
119 | | HMAC_CTX* hmac_ctx, |
120 | | #endif |
121 | | int enc); |
122 | | #endif /* HAVE_SSL */ |
123 | | |
124 | | /* returns true is string addr is an ip6 specced address */ |
125 | | int |
126 | | str_is_ip6(const char* str) |
127 | 0 | { |
128 | 0 | if(strchr(str, ':')) |
129 | 0 | return 1; |
130 | 0 | else return 0; |
131 | 0 | } |
132 | | |
133 | | int |
134 | | fd_set_nonblock(int s) |
135 | 0 | { |
136 | 0 | #ifdef HAVE_FCNTL |
137 | 0 | int flag; |
138 | 0 | if((flag = fcntl(s, F_GETFL)) == -1) { |
139 | 0 | log_err("can't fcntl F_GETFL: %s", strerror(errno)); |
140 | 0 | flag = 0; |
141 | 0 | } |
142 | 0 | flag |= O_NONBLOCK; |
143 | 0 | if(fcntl(s, F_SETFL, flag) == -1) { |
144 | 0 | log_err("can't fcntl F_SETFL: %s", strerror(errno)); |
145 | 0 | return 0; |
146 | 0 | } |
147 | | #elif defined(HAVE_IOCTLSOCKET) |
148 | | unsigned long on = 1; |
149 | | if(ioctlsocket(s, FIONBIO, &on) != 0) { |
150 | | log_err("can't ioctlsocket FIONBIO on: %s", |
151 | | wsa_strerror(WSAGetLastError())); |
152 | | } |
153 | | #endif |
154 | 0 | return 1; |
155 | 0 | } |
156 | | |
157 | | int |
158 | | fd_set_block(int s) |
159 | 0 | { |
160 | 0 | #ifdef HAVE_FCNTL |
161 | 0 | int flag; |
162 | 0 | if((flag = fcntl(s, F_GETFL)) == -1) { |
163 | 0 | log_err("cannot fcntl F_GETFL: %s", strerror(errno)); |
164 | 0 | flag = 0; |
165 | 0 | } |
166 | 0 | flag &= ~O_NONBLOCK; |
167 | 0 | if(fcntl(s, F_SETFL, flag) == -1) { |
168 | 0 | log_err("cannot fcntl F_SETFL: %s", strerror(errno)); |
169 | 0 | return 0; |
170 | 0 | } |
171 | | #elif defined(HAVE_IOCTLSOCKET) |
172 | | unsigned long off = 0; |
173 | | if(ioctlsocket(s, FIONBIO, &off) != 0) { |
174 | | if(WSAGetLastError() != WSAEINVAL || verbosity >= 4) |
175 | | log_err("can't ioctlsocket FIONBIO off: %s", |
176 | | wsa_strerror(WSAGetLastError())); |
177 | | } |
178 | | #endif |
179 | 0 | return 1; |
180 | 0 | } |
181 | | |
182 | | int |
183 | | is_pow2(size_t num) |
184 | 0 | { |
185 | 0 | if(num == 0) return 1; |
186 | 0 | return (num & (num-1)) == 0; |
187 | 0 | } |
188 | | |
189 | | void* |
190 | | memdup(void* data, size_t len) |
191 | 0 | { |
192 | 0 | void* d; |
193 | 0 | if(!data) return NULL; |
194 | 0 | if(len == 0) return NULL; |
195 | 0 | d = malloc(len); |
196 | 0 | if(!d) return NULL; |
197 | 0 | memcpy(d, data, len); |
198 | 0 | return d; |
199 | 0 | } |
200 | | |
201 | | void |
202 | | log_addr(enum verbosity_value v, const char* str, |
203 | | struct sockaddr_storage* addr, socklen_t addrlen) |
204 | 0 | { |
205 | 0 | uint16_t port; |
206 | 0 | const char* family = "unknown"; |
207 | 0 | char dest[100]; |
208 | 0 | int af = (int)((struct sockaddr_in*)addr)->sin_family; |
209 | 0 | void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; |
210 | 0 | if(verbosity < v) |
211 | 0 | return; |
212 | 0 | switch(af) { |
213 | 0 | case AF_INET: family="ip4"; break; |
214 | 0 | case AF_INET6: family="ip6"; |
215 | 0 | sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; |
216 | 0 | break; |
217 | 0 | case AF_LOCAL: |
218 | 0 | dest[0]=0; |
219 | 0 | (void)inet_ntop(af, sinaddr, dest, |
220 | 0 | (socklen_t)sizeof(dest)); |
221 | 0 | verbose(v, "%s local %s", str, dest); |
222 | 0 | return; /* do not continue and try to get port */ |
223 | 0 | default: break; |
224 | 0 | } |
225 | 0 | if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { |
226 | 0 | (void)strlcpy(dest, "(inet_ntop error)", sizeof(dest)); |
227 | 0 | } |
228 | 0 | dest[sizeof(dest)-1] = 0; |
229 | 0 | port = ntohs(((struct sockaddr_in*)addr)->sin_port); |
230 | 0 | if(verbosity >= 4) |
231 | 0 | verbose(v, "%s %s %s port %d (len %d)", str, family, dest, |
232 | 0 | (int)port, (int)addrlen); |
233 | 0 | else verbose(v, "%s %s port %d", str, dest, (int)port); |
234 | 0 | } |
235 | | |
236 | | int |
237 | | extstrtoaddr(const char* str, struct sockaddr_storage* addr, |
238 | | socklen_t* addrlen, int port) |
239 | 0 | { |
240 | 0 | char* s; |
241 | 0 | if((s=strchr(str, '@'))) { |
242 | 0 | char buf[MAX_ADDR_STRLEN]; |
243 | 0 | if(s-str >= MAX_ADDR_STRLEN) { |
244 | 0 | return 0; |
245 | 0 | } |
246 | 0 | (void)strlcpy(buf, str, sizeof(buf)); |
247 | 0 | buf[s-str] = 0; |
248 | 0 | port = atoi(s+1); |
249 | 0 | if(port == 0 && strcmp(s+1,"0")!=0) { |
250 | 0 | return 0; |
251 | 0 | } |
252 | 0 | return ipstrtoaddr(buf, port, addr, addrlen); |
253 | 0 | } |
254 | 0 | return ipstrtoaddr(str, port, addr, addrlen); |
255 | 0 | } |
256 | | |
257 | | int |
258 | | ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr, |
259 | | socklen_t* addrlen) |
260 | 0 | { |
261 | 0 | uint16_t p; |
262 | 0 | if(!ip) return 0; |
263 | 0 | p = (uint16_t) port; |
264 | 0 | if(str_is_ip6(ip)) { |
265 | 0 | char buf[MAX_ADDR_STRLEN]; |
266 | 0 | char* s; |
267 | 0 | struct sockaddr_in6* sa = (struct sockaddr_in6*)addr; |
268 | 0 | *addrlen = (socklen_t)sizeof(struct sockaddr_in6); |
269 | 0 | memset(sa, 0, *addrlen); |
270 | 0 | sa->sin6_family = AF_INET6; |
271 | 0 | sa->sin6_port = (in_port_t)htons(p); |
272 | 0 | if((s=strchr(ip, '%'))) { /* ip6%interface, rfc 4007 */ |
273 | 0 | if(s-ip >= MAX_ADDR_STRLEN) |
274 | 0 | return 0; |
275 | 0 | (void)strlcpy(buf, ip, sizeof(buf)); |
276 | 0 | buf[s-ip]=0; |
277 | 0 | #ifdef HAVE_IF_NAMETOINDEX |
278 | 0 | if (!(sa->sin6_scope_id = if_nametoindex(s+1))) |
279 | 0 | #endif /* HAVE_IF_NAMETOINDEX */ |
280 | 0 | sa->sin6_scope_id = (uint32_t)atoi(s+1); |
281 | 0 | ip = buf; |
282 | 0 | } |
283 | 0 | if(inet_pton((int)sa->sin6_family, ip, &sa->sin6_addr) <= 0) { |
284 | 0 | return 0; |
285 | 0 | } |
286 | 0 | } else { /* ip4 */ |
287 | 0 | struct sockaddr_in* sa = (struct sockaddr_in*)addr; |
288 | 0 | *addrlen = (socklen_t)sizeof(struct sockaddr_in); |
289 | 0 | memset(sa, 0, *addrlen); |
290 | 0 | sa->sin_family = AF_INET; |
291 | 0 | sa->sin_port = (in_port_t)htons(p); |
292 | 0 | if(inet_pton((int)sa->sin_family, ip, &sa->sin_addr) <= 0) { |
293 | 0 | return 0; |
294 | 0 | } |
295 | 0 | } |
296 | 0 | return 1; |
297 | 0 | } |
298 | | |
299 | | int netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr, |
300 | | socklen_t* addrlen, int* net) |
301 | 0 | { |
302 | 0 | char buf[64]; |
303 | 0 | char* s; |
304 | 0 | *net = (str_is_ip6(str)?128:32); |
305 | 0 | if((s=strchr(str, '/'))) { |
306 | 0 | if(atoi(s+1) > *net) { |
307 | 0 | log_err("netblock too large: %s", str); |
308 | 0 | return 0; |
309 | 0 | } |
310 | 0 | *net = atoi(s+1); |
311 | 0 | if(*net == 0 && strcmp(s+1, "0") != 0) { |
312 | 0 | log_err("cannot parse netblock: '%s'", str); |
313 | 0 | return 0; |
314 | 0 | } |
315 | 0 | strlcpy(buf, str, sizeof(buf)); |
316 | 0 | s = strchr(buf, '/'); |
317 | 0 | if(s) *s = 0; |
318 | 0 | s = buf; |
319 | 0 | } |
320 | 0 | if(!ipstrtoaddr(s?s:str, port, addr, addrlen)) { |
321 | 0 | log_err("cannot parse ip address: '%s'", str); |
322 | 0 | return 0; |
323 | 0 | } |
324 | 0 | if(s) { |
325 | 0 | addr_mask(addr, *addrlen, *net); |
326 | 0 | } |
327 | 0 | return 1; |
328 | 0 | } |
329 | | |
330 | | /* RPZ format address dname to network byte order address */ |
331 | | static int ipdnametoaddr(uint8_t* dname, size_t dnamelen, |
332 | | struct sockaddr_storage* addr, socklen_t* addrlen, int* af) |
333 | 0 | { |
334 | 0 | uint8_t* ia; |
335 | 0 | int dnamelabs = dname_count_labels(dname); |
336 | 0 | uint8_t lablen; |
337 | 0 | char* e = NULL; |
338 | 0 | int z = 0; |
339 | 0 | size_t len = 0; |
340 | 0 | int i; |
341 | 0 | *af = AF_INET; |
342 | | |
343 | | /* need 1 byte for label length */ |
344 | 0 | if(dnamelen < 1) |
345 | 0 | return 0; |
346 | | |
347 | 0 | if(dnamelabs > 6 || |
348 | 0 | dname_has_label(dname, dnamelen, (uint8_t*)"\002zz")) { |
349 | 0 | *af = AF_INET6; |
350 | 0 | } |
351 | 0 | len = *dname; |
352 | 0 | lablen = *dname++; |
353 | 0 | i = (*af == AF_INET) ? 3 : 15; |
354 | 0 | if(*af == AF_INET6) { |
355 | 0 | struct sockaddr_in6* sa = (struct sockaddr_in6*)addr; |
356 | 0 | *addrlen = (socklen_t)sizeof(struct sockaddr_in6); |
357 | 0 | memset(sa, 0, *addrlen); |
358 | 0 | sa->sin6_family = AF_INET6; |
359 | 0 | ia = (uint8_t*)&sa->sin6_addr; |
360 | 0 | } else { /* ip4 */ |
361 | 0 | struct sockaddr_in* sa = (struct sockaddr_in*)addr; |
362 | 0 | *addrlen = (socklen_t)sizeof(struct sockaddr_in); |
363 | 0 | memset(sa, 0, *addrlen); |
364 | 0 | sa->sin_family = AF_INET; |
365 | 0 | ia = (uint8_t*)&sa->sin_addr; |
366 | 0 | } |
367 | 0 | while(lablen && i >= 0 && len <= dnamelen) { |
368 | 0 | char buff[LDNS_MAX_LABELLEN+1]; |
369 | 0 | uint16_t chunk; /* big enough to not overflow on IPv6 hextet */ |
370 | 0 | if((*af == AF_INET && (lablen > 3 || dnamelabs > 6)) || |
371 | 0 | (*af == AF_INET6 && (lablen > 4 || dnamelabs > 10))) { |
372 | 0 | return 0; |
373 | 0 | } |
374 | 0 | if(memcmp(dname, "zz", 2) == 0 && *af == AF_INET6) { |
375 | | /* Add one or more 0 labels. Address is initialised at |
376 | | * 0, so just skip the zero part. */ |
377 | 0 | int zl = 11 - dnamelabs; |
378 | 0 | if(z || zl < 0) |
379 | 0 | return 0; |
380 | 0 | z = 1; |
381 | 0 | i -= (zl*2); |
382 | 0 | } else { |
383 | 0 | memcpy(buff, dname, lablen); |
384 | 0 | buff[lablen] = '\0'; |
385 | 0 | chunk = strtol(buff, &e, (*af == AF_INET) ? 10 : 16); |
386 | 0 | if(!e || *e != '\0' || (*af == AF_INET && chunk > 255)) |
387 | 0 | return 0; |
388 | 0 | if(*af == AF_INET) { |
389 | 0 | log_assert(i < 4 && i >= 0); |
390 | 0 | ia[i] = (uint8_t)chunk; |
391 | 0 | i--; |
392 | 0 | } else { |
393 | 0 | log_assert(i < 16 && i >= 1); |
394 | | /* ia in network byte order */ |
395 | 0 | ia[i-1] = (uint8_t)(chunk >> 8); |
396 | 0 | ia[i] = (uint8_t)(chunk & 0x00FF); |
397 | 0 | i -= 2; |
398 | 0 | } |
399 | 0 | } |
400 | 0 | dname += lablen; |
401 | 0 | lablen = *dname++; |
402 | 0 | len += lablen; |
403 | 0 | } |
404 | 0 | if(i != -1) |
405 | | /* input too short */ |
406 | 0 | return 0; |
407 | 0 | return 1; |
408 | 0 | } |
409 | | |
410 | | int netblockdnametoaddr(uint8_t* dname, size_t dnamelen, |
411 | | struct sockaddr_storage* addr, socklen_t* addrlen, int* net, int* af) |
412 | 0 | { |
413 | 0 | char buff[3 /* 3 digit netblock */ + 1]; |
414 | 0 | size_t nlablen; |
415 | 0 | if(dnamelen < 1 || *dname > 3) |
416 | | /* netblock invalid */ |
417 | 0 | return 0; |
418 | 0 | nlablen = *dname; |
419 | |
|
420 | 0 | if(dnamelen < 1 + nlablen) |
421 | 0 | return 0; |
422 | | |
423 | 0 | memcpy(buff, dname+1, nlablen); |
424 | 0 | buff[nlablen] = '\0'; |
425 | 0 | *net = atoi(buff); |
426 | 0 | if(*net == 0 && strcmp(buff, "0") != 0) |
427 | 0 | return 0; |
428 | 0 | dname += nlablen; |
429 | 0 | dname++; |
430 | 0 | if(!ipdnametoaddr(dname, dnamelen-1-nlablen, addr, addrlen, af)) |
431 | 0 | return 0; |
432 | 0 | if((*af == AF_INET6 && *net > 128) || (*af == AF_INET && *net > 32)) |
433 | 0 | return 0; |
434 | 0 | return 1; |
435 | 0 | } |
436 | | |
437 | | int authextstrtoaddr(char* str, struct sockaddr_storage* addr, |
438 | | socklen_t* addrlen, char** auth_name) |
439 | 0 | { |
440 | 0 | char* s; |
441 | 0 | int port = UNBOUND_DNS_PORT; |
442 | 0 | if((s=strchr(str, '@'))) { |
443 | 0 | char buf[MAX_ADDR_STRLEN]; |
444 | 0 | size_t len = (size_t)(s-str); |
445 | 0 | char* hash = strchr(s+1, '#'); |
446 | 0 | if(hash) { |
447 | 0 | *auth_name = hash+1; |
448 | 0 | } else { |
449 | 0 | *auth_name = NULL; |
450 | 0 | } |
451 | 0 | if(len >= MAX_ADDR_STRLEN) { |
452 | 0 | return 0; |
453 | 0 | } |
454 | 0 | (void)strlcpy(buf, str, sizeof(buf)); |
455 | 0 | buf[len] = 0; |
456 | 0 | port = atoi(s+1); |
457 | 0 | if(port == 0) { |
458 | 0 | if(!hash && strcmp(s+1,"0")!=0) |
459 | 0 | return 0; |
460 | 0 | if(hash && strncmp(s+1,"0#",2)!=0) |
461 | 0 | return 0; |
462 | 0 | } |
463 | 0 | return ipstrtoaddr(buf, port, addr, addrlen); |
464 | 0 | } |
465 | 0 | if((s=strchr(str, '#'))) { |
466 | 0 | char buf[MAX_ADDR_STRLEN]; |
467 | 0 | size_t len = (size_t)(s-str); |
468 | 0 | if(len >= MAX_ADDR_STRLEN) { |
469 | 0 | return 0; |
470 | 0 | } |
471 | 0 | (void)strlcpy(buf, str, sizeof(buf)); |
472 | 0 | buf[len] = 0; |
473 | 0 | port = UNBOUND_DNS_OVER_TLS_PORT; |
474 | 0 | *auth_name = s+1; |
475 | 0 | return ipstrtoaddr(buf, port, addr, addrlen); |
476 | 0 | } |
477 | 0 | *auth_name = NULL; |
478 | 0 | return ipstrtoaddr(str, port, addr, addrlen); |
479 | 0 | } |
480 | | |
481 | | uint8_t* authextstrtodname(char* str, int* port, char** auth_name) |
482 | 0 | { |
483 | 0 | char* s; |
484 | 0 | uint8_t* dname; |
485 | 0 | size_t dname_len; |
486 | 0 | *port = UNBOUND_DNS_PORT; |
487 | 0 | *auth_name = NULL; |
488 | 0 | if((s=strchr(str, '@'))) { |
489 | 0 | char* hash = strchr(s+1, '#'); |
490 | 0 | if(hash) { |
491 | 0 | *auth_name = hash+1; |
492 | 0 | } else { |
493 | 0 | *auth_name = NULL; |
494 | 0 | } |
495 | 0 | *port = atoi(s+1); |
496 | 0 | if(*port == 0) { |
497 | 0 | if(!hash && strcmp(s+1,"0")!=0) |
498 | 0 | return 0; |
499 | 0 | if(hash && strncmp(s+1,"0#",2)!=0) |
500 | 0 | return 0; |
501 | 0 | } |
502 | 0 | *s = 0; |
503 | 0 | dname = sldns_str2wire_dname(str, &dname_len); |
504 | 0 | *s = '@'; |
505 | 0 | } else if((s=strchr(str, '#'))) { |
506 | 0 | *port = UNBOUND_DNS_OVER_TLS_PORT; |
507 | 0 | *auth_name = s+1; |
508 | 0 | *s = 0; |
509 | 0 | dname = sldns_str2wire_dname(str, &dname_len); |
510 | 0 | *s = '#'; |
511 | 0 | } else { |
512 | 0 | dname = sldns_str2wire_dname(str, &dname_len); |
513 | 0 | } |
514 | 0 | return dname; |
515 | 0 | } |
516 | | |
517 | | /** store port number into sockaddr structure */ |
518 | | void |
519 | | sockaddr_store_port(struct sockaddr_storage* addr, socklen_t addrlen, int port) |
520 | 0 | { |
521 | 0 | if(addr_is_ip6(addr, addrlen)) { |
522 | 0 | struct sockaddr_in6* sa = (struct sockaddr_in6*)addr; |
523 | 0 | sa->sin6_port = (in_port_t)htons((uint16_t)port); |
524 | 0 | } else { |
525 | 0 | struct sockaddr_in* sa = (struct sockaddr_in*)addr; |
526 | 0 | sa->sin_port = (in_port_t)htons((uint16_t)port); |
527 | 0 | } |
528 | 0 | } |
529 | | |
530 | | void |
531 | | log_nametypeclass(enum verbosity_value v, const char* str, uint8_t* name, |
532 | | uint16_t type, uint16_t dclass) |
533 | 0 | { |
534 | 0 | char buf[LDNS_MAX_DOMAINLEN+1]; |
535 | 0 | char t[12], c[12]; |
536 | 0 | const char *ts, *cs; |
537 | 0 | if(verbosity < v) |
538 | 0 | return; |
539 | 0 | dname_str(name, buf); |
540 | 0 | if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG"; |
541 | 0 | else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR"; |
542 | 0 | else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR"; |
543 | 0 | else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB"; |
544 | 0 | else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA"; |
545 | 0 | else if(type == LDNS_RR_TYPE_ANY) ts = "ANY"; |
546 | 0 | else if(sldns_rr_descript(type) && sldns_rr_descript(type)->_name) |
547 | 0 | ts = sldns_rr_descript(type)->_name; |
548 | 0 | else { |
549 | 0 | snprintf(t, sizeof(t), "TYPE%d", (int)type); |
550 | 0 | ts = t; |
551 | 0 | } |
552 | 0 | if(sldns_lookup_by_id(sldns_rr_classes, (int)dclass) && |
553 | 0 | sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name) |
554 | 0 | cs = sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name; |
555 | 0 | else { |
556 | 0 | snprintf(c, sizeof(c), "CLASS%d", (int)dclass); |
557 | 0 | cs = c; |
558 | 0 | } |
559 | 0 | log_info("%s %s %s %s", str, buf, ts, cs); |
560 | 0 | } |
561 | | |
562 | | void |
563 | | log_query_in(const char* str, uint8_t* name, uint16_t type, uint16_t dclass) |
564 | 0 | { |
565 | 0 | char buf[LDNS_MAX_DOMAINLEN+1]; |
566 | 0 | char t[12], c[12]; |
567 | 0 | const char *ts, *cs; |
568 | 0 | dname_str(name, buf); |
569 | 0 | if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG"; |
570 | 0 | else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR"; |
571 | 0 | else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR"; |
572 | 0 | else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB"; |
573 | 0 | else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA"; |
574 | 0 | else if(type == LDNS_RR_TYPE_ANY) ts = "ANY"; |
575 | 0 | else if(sldns_rr_descript(type) && sldns_rr_descript(type)->_name) |
576 | 0 | ts = sldns_rr_descript(type)->_name; |
577 | 0 | else { |
578 | 0 | snprintf(t, sizeof(t), "TYPE%d", (int)type); |
579 | 0 | ts = t; |
580 | 0 | } |
581 | 0 | if(sldns_lookup_by_id(sldns_rr_classes, (int)dclass) && |
582 | 0 | sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name) |
583 | 0 | cs = sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name; |
584 | 0 | else { |
585 | 0 | snprintf(c, sizeof(c), "CLASS%d", (int)dclass); |
586 | 0 | cs = c; |
587 | 0 | } |
588 | 0 | if(LOG_TAG_QUERYREPLY) |
589 | 0 | log_query("%s %s %s %s", str, buf, ts, cs); |
590 | 0 | else log_info("%s %s %s %s", str, buf, ts, cs); |
591 | 0 | } |
592 | | |
593 | | void log_name_addr(enum verbosity_value v, const char* str, uint8_t* zone, |
594 | | struct sockaddr_storage* addr, socklen_t addrlen) |
595 | 0 | { |
596 | 0 | uint16_t port; |
597 | 0 | const char* family = "unknown_family "; |
598 | 0 | char namebuf[LDNS_MAX_DOMAINLEN+1]; |
599 | 0 | char dest[100]; |
600 | 0 | int af = (int)((struct sockaddr_in*)addr)->sin_family; |
601 | 0 | void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; |
602 | 0 | if(verbosity < v) |
603 | 0 | return; |
604 | 0 | switch(af) { |
605 | 0 | case AF_INET: family=""; break; |
606 | 0 | case AF_INET6: family=""; |
607 | 0 | sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; |
608 | 0 | break; |
609 | 0 | case AF_LOCAL: family="local "; break; |
610 | 0 | default: break; |
611 | 0 | } |
612 | 0 | if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { |
613 | 0 | (void)strlcpy(dest, "(inet_ntop error)", sizeof(dest)); |
614 | 0 | } |
615 | 0 | dest[sizeof(dest)-1] = 0; |
616 | 0 | port = ntohs(((struct sockaddr_in*)addr)->sin_port); |
617 | 0 | dname_str(zone, namebuf); |
618 | 0 | if(af != AF_INET && af != AF_INET6) |
619 | 0 | verbose(v, "%s <%s> %s%s#%d (addrlen %d)", |
620 | 0 | str, namebuf, family, dest, (int)port, (int)addrlen); |
621 | 0 | else verbose(v, "%s <%s> %s%s#%d", |
622 | 0 | str, namebuf, family, dest, (int)port); |
623 | 0 | } |
624 | | |
625 | | void log_err_addr(const char* str, const char* err, |
626 | | struct sockaddr_storage* addr, socklen_t addrlen) |
627 | 0 | { |
628 | 0 | uint16_t port; |
629 | 0 | char dest[100]; |
630 | 0 | int af = (int)((struct sockaddr_in*)addr)->sin_family; |
631 | 0 | void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; |
632 | 0 | if(af == AF_INET6) |
633 | 0 | sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; |
634 | 0 | if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { |
635 | 0 | (void)strlcpy(dest, "(inet_ntop error)", sizeof(dest)); |
636 | 0 | } |
637 | 0 | dest[sizeof(dest)-1] = 0; |
638 | 0 | port = ntohs(((struct sockaddr_in*)addr)->sin_port); |
639 | 0 | if(verbosity >= 4) |
640 | 0 | log_err("%s: %s for %s port %d (len %d)", str, err, dest, |
641 | 0 | (int)port, (int)addrlen); |
642 | 0 | else log_err("%s: %s for %s port %d", str, err, dest, (int)port); |
643 | 0 | } |
644 | | |
645 | | int |
646 | | sockaddr_cmp(struct sockaddr_storage* addr1, socklen_t len1, |
647 | | struct sockaddr_storage* addr2, socklen_t len2) |
648 | 0 | { |
649 | 0 | struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1; |
650 | 0 | struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2; |
651 | 0 | struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1; |
652 | 0 | struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2; |
653 | 0 | if(len1 < len2) |
654 | 0 | return -1; |
655 | 0 | if(len1 > len2) |
656 | 0 | return 1; |
657 | 0 | log_assert(len1 == len2); |
658 | 0 | if( p1_in->sin_family < p2_in->sin_family) |
659 | 0 | return -1; |
660 | 0 | if( p1_in->sin_family > p2_in->sin_family) |
661 | 0 | return 1; |
662 | 0 | log_assert( p1_in->sin_family == p2_in->sin_family ); |
663 | | /* compare ip4 */ |
664 | 0 | if( p1_in->sin_family == AF_INET ) { |
665 | | /* just order it, ntohs not required */ |
666 | 0 | if(p1_in->sin_port < p2_in->sin_port) |
667 | 0 | return -1; |
668 | 0 | if(p1_in->sin_port > p2_in->sin_port) |
669 | 0 | return 1; |
670 | 0 | log_assert(p1_in->sin_port == p2_in->sin_port); |
671 | 0 | return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE); |
672 | 0 | } else if (p1_in6->sin6_family == AF_INET6) { |
673 | | /* just order it, ntohs not required */ |
674 | 0 | if(p1_in6->sin6_port < p2_in6->sin6_port) |
675 | 0 | return -1; |
676 | 0 | if(p1_in6->sin6_port > p2_in6->sin6_port) |
677 | 0 | return 1; |
678 | 0 | log_assert(p1_in6->sin6_port == p2_in6->sin6_port); |
679 | 0 | return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr, |
680 | 0 | INET6_SIZE); |
681 | 0 | } else { |
682 | | /* eek unknown type, perform this comparison for sanity. */ |
683 | 0 | return memcmp(addr1, addr2, len1); |
684 | 0 | } |
685 | 0 | } |
686 | | |
687 | | int |
688 | | sockaddr_cmp_addr(struct sockaddr_storage* addr1, socklen_t len1, |
689 | | struct sockaddr_storage* addr2, socklen_t len2) |
690 | 0 | { |
691 | 0 | struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1; |
692 | 0 | struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2; |
693 | 0 | struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1; |
694 | 0 | struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2; |
695 | 0 | if(len1 < len2) |
696 | 0 | return -1; |
697 | 0 | if(len1 > len2) |
698 | 0 | return 1; |
699 | 0 | log_assert(len1 == len2); |
700 | 0 | if( p1_in->sin_family < p2_in->sin_family) |
701 | 0 | return -1; |
702 | 0 | if( p1_in->sin_family > p2_in->sin_family) |
703 | 0 | return 1; |
704 | 0 | log_assert( p1_in->sin_family == p2_in->sin_family ); |
705 | | /* compare ip4 */ |
706 | 0 | if( p1_in->sin_family == AF_INET ) { |
707 | 0 | return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE); |
708 | 0 | } else if (p1_in6->sin6_family == AF_INET6) { |
709 | 0 | return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr, |
710 | 0 | INET6_SIZE); |
711 | 0 | } else { |
712 | | /* eek unknown type, perform this comparison for sanity. */ |
713 | 0 | return memcmp(addr1, addr2, len1); |
714 | 0 | } |
715 | 0 | } |
716 | | |
717 | | int |
718 | | addr_is_ip6(struct sockaddr_storage* addr, socklen_t len) |
719 | 0 | { |
720 | 0 | if(len == (socklen_t)sizeof(struct sockaddr_in6) && |
721 | 0 | ((struct sockaddr_in6*)addr)->sin6_family == AF_INET6) |
722 | 0 | return 1; |
723 | 0 | else return 0; |
724 | 0 | } |
725 | | |
726 | | void |
727 | | addr_mask(struct sockaddr_storage* addr, socklen_t len, int net) |
728 | 0 | { |
729 | 0 | uint8_t mask[8] = {0x0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe}; |
730 | 0 | int i, max; |
731 | 0 | uint8_t* s; |
732 | 0 | if(addr_is_ip6(addr, len)) { |
733 | 0 | s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr; |
734 | 0 | max = 128; |
735 | 0 | } else { |
736 | 0 | s = (uint8_t*)&((struct sockaddr_in*)addr)->sin_addr; |
737 | 0 | max = 32; |
738 | 0 | } |
739 | 0 | if(net >= max) |
740 | 0 | return; |
741 | 0 | for(i=net/8+1; i<max/8; i++) { |
742 | 0 | s[i] = 0; |
743 | 0 | } |
744 | 0 | s[net/8] &= mask[net&0x7]; |
745 | 0 | } |
746 | | |
747 | | int |
748 | | addr_in_common(struct sockaddr_storage* addr1, int net1, |
749 | | struct sockaddr_storage* addr2, int net2, socklen_t addrlen) |
750 | 0 | { |
751 | 0 | int min = (net1<net2)?net1:net2; |
752 | 0 | int i, to; |
753 | 0 | int match = 0; |
754 | 0 | uint8_t* s1, *s2; |
755 | 0 | if(addr_is_ip6(addr1, addrlen)) { |
756 | 0 | s1 = (uint8_t*)&((struct sockaddr_in6*)addr1)->sin6_addr; |
757 | 0 | s2 = (uint8_t*)&((struct sockaddr_in6*)addr2)->sin6_addr; |
758 | 0 | to = 16; |
759 | 0 | } else { |
760 | 0 | s1 = (uint8_t*)&((struct sockaddr_in*)addr1)->sin_addr; |
761 | 0 | s2 = (uint8_t*)&((struct sockaddr_in*)addr2)->sin_addr; |
762 | 0 | to = 4; |
763 | 0 | } |
764 | | /* match = bits_in_common(s1, s2, to); */ |
765 | 0 | for(i=0; i<to; i++) { |
766 | 0 | if(s1[i] == s2[i]) { |
767 | 0 | match += 8; |
768 | 0 | } else { |
769 | 0 | uint8_t z = s1[i]^s2[i]; |
770 | 0 | log_assert(z); |
771 | 0 | while(!(z&0x80)) { |
772 | 0 | match++; |
773 | 0 | z<<=1; |
774 | 0 | } |
775 | 0 | break; |
776 | 0 | } |
777 | 0 | } |
778 | 0 | if(match > min) match = min; |
779 | 0 | return match; |
780 | 0 | } |
781 | | |
782 | | void |
783 | | addr_to_str(struct sockaddr_storage* addr, socklen_t addrlen, |
784 | | char* buf, size_t len) |
785 | 0 | { |
786 | 0 | int af = (int)((struct sockaddr_in*)addr)->sin_family; |
787 | 0 | void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; |
788 | 0 | if(addr_is_ip6(addr, addrlen)) |
789 | 0 | sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; |
790 | 0 | if(inet_ntop(af, sinaddr, buf, (socklen_t)len) == 0) { |
791 | 0 | snprintf(buf, len, "(inet_ntop_error)"); |
792 | 0 | } |
793 | 0 | } |
794 | | |
795 | | int |
796 | | prefixnet_is_nat64(int prefixnet) |
797 | 0 | { |
798 | 0 | return (prefixnet == 32 || prefixnet == 40 || |
799 | 0 | prefixnet == 48 || prefixnet == 56 || |
800 | 0 | prefixnet == 64 || prefixnet == 96); |
801 | 0 | } |
802 | | |
803 | | void |
804 | | addr_to_nat64(const struct sockaddr_storage* addr, |
805 | | const struct sockaddr_storage* nat64_prefix, |
806 | | socklen_t nat64_prefixlen, int nat64_prefixnet, |
807 | | struct sockaddr_storage* nat64_addr, socklen_t* nat64_addrlen) |
808 | 0 | { |
809 | 0 | struct sockaddr_in *sin = (struct sockaddr_in *)addr; |
810 | 0 | struct sockaddr_in6 *sin6; |
811 | 0 | uint8_t *v4_byte; |
812 | | |
813 | | /* This needs to be checked by the caller */ |
814 | 0 | log_assert(addr->ss_family == AF_INET); |
815 | | /* Current usage is only from config values; prefix lengths enforced |
816 | | * during config validation */ |
817 | 0 | log_assert(prefixnet_is_nat64(nat64_prefixnet)); |
818 | |
|
819 | 0 | *nat64_addr = *nat64_prefix; |
820 | 0 | *nat64_addrlen = nat64_prefixlen; |
821 | |
|
822 | 0 | sin6 = (struct sockaddr_in6 *)nat64_addr; |
823 | 0 | sin6->sin6_flowinfo = 0; |
824 | 0 | sin6->sin6_port = sin->sin_port; |
825 | |
|
826 | 0 | nat64_prefixnet = nat64_prefixnet / 8; |
827 | |
|
828 | 0 | v4_byte = (uint8_t *)&sin->sin_addr.s_addr; |
829 | 0 | for(int i = 0; i < 4; i++) { |
830 | 0 | if(nat64_prefixnet == 8) { |
831 | | /* bits 64...71 are MBZ */ |
832 | 0 | sin6->sin6_addr.s6_addr[nat64_prefixnet++] = 0; |
833 | 0 | } |
834 | 0 | sin6->sin6_addr.s6_addr[nat64_prefixnet++] = *v4_byte++; |
835 | 0 | } |
836 | 0 | } |
837 | | |
838 | | int |
839 | | addr_is_ip4mapped(struct sockaddr_storage* addr, socklen_t addrlen) |
840 | 0 | { |
841 | | /* prefix for ipv4 into ipv6 mapping is ::ffff:x.x.x.x */ |
842 | 0 | const uint8_t map_prefix[16] = |
843 | 0 | {0,0,0,0, 0,0,0,0, 0,0,0xff,0xff, 0,0,0,0}; |
844 | 0 | uint8_t* s; |
845 | 0 | if(!addr_is_ip6(addr, addrlen)) |
846 | 0 | return 0; |
847 | | /* s is 16 octet ipv6 address string */ |
848 | 0 | s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr; |
849 | 0 | return (memcmp(s, map_prefix, 12) == 0); |
850 | 0 | } |
851 | | |
852 | | int addr_is_broadcast(struct sockaddr_storage* addr, socklen_t addrlen) |
853 | 0 | { |
854 | 0 | int af = (int)((struct sockaddr_in*)addr)->sin_family; |
855 | 0 | void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; |
856 | 0 | return af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in) |
857 | 0 | && memcmp(sinaddr, "\377\377\377\377", 4) == 0; |
858 | 0 | } |
859 | | |
860 | | int addr_is_any(struct sockaddr_storage* addr, socklen_t addrlen) |
861 | 0 | { |
862 | 0 | int af = (int)((struct sockaddr_in*)addr)->sin_family; |
863 | 0 | void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; |
864 | 0 | void* sin6addr = &((struct sockaddr_in6*)addr)->sin6_addr; |
865 | 0 | if(af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in) |
866 | 0 | && memcmp(sinaddr, "\000\000\000\000", 4) == 0) |
867 | 0 | return 1; |
868 | 0 | else if(af==AF_INET6 && addrlen>=(socklen_t)sizeof(struct sockaddr_in6) |
869 | 0 | && memcmp(sin6addr, "\000\000\000\000\000\000\000\000" |
870 | 0 | "\000\000\000\000\000\000\000\000", 16) == 0) |
871 | 0 | return 1; |
872 | 0 | return 0; |
873 | 0 | } |
874 | | |
875 | | void sock_list_insert(struct sock_list** list, struct sockaddr_storage* addr, |
876 | | socklen_t len, struct regional* region) |
877 | 0 | { |
878 | 0 | struct sock_list* add = (struct sock_list*)regional_alloc(region, |
879 | 0 | sizeof(*add) - sizeof(add->addr) + (size_t)len); |
880 | 0 | if(!add) { |
881 | 0 | log_err("out of memory in socketlist insert"); |
882 | 0 | return; |
883 | 0 | } |
884 | 0 | log_assert(list); |
885 | 0 | add->next = *list; |
886 | 0 | add->len = len; |
887 | 0 | *list = add; |
888 | 0 | if(len) memmove(&add->addr, addr, len); |
889 | 0 | } |
890 | | |
891 | | void sock_list_prepend(struct sock_list** list, struct sock_list* add) |
892 | 0 | { |
893 | 0 | struct sock_list* last = add; |
894 | 0 | if(!last) |
895 | 0 | return; |
896 | 0 | while(last->next) |
897 | 0 | last = last->next; |
898 | 0 | last->next = *list; |
899 | 0 | *list = add; |
900 | 0 | } |
901 | | |
902 | | int sock_list_find(struct sock_list* list, struct sockaddr_storage* addr, |
903 | | socklen_t len) |
904 | 0 | { |
905 | 0 | while(list) { |
906 | 0 | if(len == list->len) { |
907 | 0 | if(len == 0 || sockaddr_cmp_addr(addr, len, |
908 | 0 | &list->addr, list->len) == 0) |
909 | 0 | return 1; |
910 | 0 | } |
911 | 0 | list = list->next; |
912 | 0 | } |
913 | 0 | return 0; |
914 | 0 | } |
915 | | |
916 | | void sock_list_merge(struct sock_list** list, struct regional* region, |
917 | | struct sock_list* add) |
918 | 0 | { |
919 | 0 | struct sock_list* p; |
920 | 0 | for(p=add; p; p=p->next) { |
921 | 0 | if(!sock_list_find(*list, &p->addr, p->len)) |
922 | 0 | sock_list_insert(list, &p->addr, p->len, region); |
923 | 0 | } |
924 | 0 | } |
925 | | |
926 | | void |
927 | | log_crypto_err(const char* str) |
928 | 0 | { |
929 | 0 | #ifdef HAVE_SSL |
930 | 0 | log_crypto_err_code(str, ERR_get_error()); |
931 | | #else |
932 | | (void)str; |
933 | | #endif /* HAVE_SSL */ |
934 | 0 | } |
935 | | |
936 | | void log_crypto_err_code(const char* str, unsigned long err) |
937 | 0 | { |
938 | 0 | #ifdef HAVE_SSL |
939 | | /* error:[error code]:[library name]:[function name]:[reason string] */ |
940 | 0 | char buf[128]; |
941 | 0 | unsigned long e; |
942 | 0 | ERR_error_string_n(err, buf, sizeof(buf)); |
943 | 0 | log_err("%s crypto %s", str, buf); |
944 | 0 | while( (e=ERR_get_error()) ) { |
945 | 0 | ERR_error_string_n(e, buf, sizeof(buf)); |
946 | 0 | log_err("and additionally crypto %s", buf); |
947 | 0 | } |
948 | | #else |
949 | | (void)str; |
950 | | (void)err; |
951 | | #endif /* HAVE_SSL */ |
952 | 0 | } |
953 | | |
954 | | #ifdef HAVE_SSL |
955 | | /** log certificate details */ |
956 | | void |
957 | | log_cert(unsigned level, const char* str, void* cert) |
958 | 0 | { |
959 | 0 | BIO* bio; |
960 | 0 | char nul = 0; |
961 | 0 | char* pp = NULL; |
962 | 0 | long len; |
963 | 0 | if(verbosity < level) return; |
964 | 0 | bio = BIO_new(BIO_s_mem()); |
965 | 0 | if(!bio) return; |
966 | 0 | X509_print_ex(bio, (X509*)cert, 0, (unsigned long)-1 |
967 | 0 | ^(X509_FLAG_NO_SUBJECT |
968 | 0 | |X509_FLAG_NO_ISSUER|X509_FLAG_NO_VALIDITY |
969 | 0 | |X509_FLAG_NO_EXTENSIONS|X509_FLAG_NO_AUX |
970 | 0 | |X509_FLAG_NO_ATTRIBUTES)); |
971 | 0 | BIO_write(bio, &nul, (int)sizeof(nul)); |
972 | 0 | len = BIO_get_mem_data(bio, &pp); |
973 | 0 | if(len != 0 && pp) { |
974 | | /* reduce size of cert printout */ |
975 | 0 | char* s; |
976 | 0 | while((s=strstr(pp, " "))!=NULL) |
977 | 0 | memmove(s, s+1, strlen(s+1)+1); |
978 | 0 | while((s=strstr(pp, "\t\t"))!=NULL) |
979 | 0 | memmove(s, s+1, strlen(s+1)+1); |
980 | 0 | verbose(level, "%s: \n%s", str, pp); |
981 | 0 | } |
982 | 0 | BIO_free(bio); |
983 | 0 | } |
984 | | #endif /* HAVE_SSL */ |
985 | | |
986 | | #if defined(HAVE_SSL) && defined(HAVE_NGHTTP2) && defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB) |
987 | | static int alpn_select_cb(SSL* ATTR_UNUSED(ssl), const unsigned char** out, |
988 | | unsigned char* outlen, const unsigned char* in, unsigned int inlen, |
989 | | void* ATTR_UNUSED(arg)) |
990 | | { |
991 | | int rv = nghttp2_select_next_protocol((unsigned char **)out, outlen, in, |
992 | | inlen); |
993 | | if(rv == -1) { |
994 | | return SSL_TLSEXT_ERR_NOACK; |
995 | | } |
996 | | /* either http/1.1 or h2 selected */ |
997 | | return SSL_TLSEXT_ERR_OK; |
998 | | } |
999 | | #endif |
1000 | | |
1001 | | int |
1002 | | listen_sslctx_setup(void* ctxt) |
1003 | 0 | { |
1004 | 0 | #ifdef HAVE_SSL |
1005 | 0 | SSL_CTX* ctx = (SSL_CTX*)ctxt; |
1006 | | /* no SSLv2, SSLv3 because has defects */ |
1007 | | #if SSL_OP_NO_SSLv2 != 0 |
1008 | | if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2) |
1009 | | != SSL_OP_NO_SSLv2){ |
1010 | | log_crypto_err("could not set SSL_OP_NO_SSLv2"); |
1011 | | return 0; |
1012 | | } |
1013 | | #endif |
1014 | 0 | if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3) |
1015 | 0 | != SSL_OP_NO_SSLv3){ |
1016 | 0 | log_crypto_err("could not set SSL_OP_NO_SSLv3"); |
1017 | 0 | return 0; |
1018 | 0 | } |
1019 | 0 | #if defined(SSL_OP_NO_TLSv1) && defined(SSL_OP_NO_TLSv1_1) |
1020 | | /* if we have tls 1.1 disable 1.0 */ |
1021 | 0 | if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1) & SSL_OP_NO_TLSv1) |
1022 | 0 | != SSL_OP_NO_TLSv1){ |
1023 | 0 | log_crypto_err("could not set SSL_OP_NO_TLSv1"); |
1024 | 0 | return 0; |
1025 | 0 | } |
1026 | 0 | #endif |
1027 | 0 | #if defined(SSL_OP_NO_TLSv1_1) && defined(SSL_OP_NO_TLSv1_2) |
1028 | | /* if we have tls 1.2 disable 1.1 */ |
1029 | 0 | if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_1) & SSL_OP_NO_TLSv1_1) |
1030 | 0 | != SSL_OP_NO_TLSv1_1){ |
1031 | 0 | log_crypto_err("could not set SSL_OP_NO_TLSv1_1"); |
1032 | 0 | return 0; |
1033 | 0 | } |
1034 | 0 | #endif |
1035 | 0 | #if defined(SSL_OP_NO_RENEGOTIATION) |
1036 | | /* disable client renegotiation */ |
1037 | 0 | if((SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION) & |
1038 | 0 | SSL_OP_NO_RENEGOTIATION) != SSL_OP_NO_RENEGOTIATION) { |
1039 | 0 | log_crypto_err("could not set SSL_OP_NO_RENEGOTIATION"); |
1040 | 0 | return 0; |
1041 | 0 | } |
1042 | 0 | #endif |
1043 | 0 | #if defined(SHA256_DIGEST_LENGTH) && defined(USE_ECDSA) |
1044 | | /* if we detect system-wide crypto policies, use those */ |
1045 | 0 | if (access( "/etc/crypto-policies/config", F_OK ) != 0 ) { |
1046 | | /* if we have sha256, set the cipher list to have no known vulns */ |
1047 | 0 | if(!SSL_CTX_set_cipher_list(ctx, "TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256")) |
1048 | 0 | log_crypto_err("could not set cipher list with SSL_CTX_set_cipher_list"); |
1049 | 0 | } |
1050 | 0 | #endif |
1051 | | #if defined(SSL_OP_IGNORE_UNEXPECTED_EOF) |
1052 | | /* ignore errors when peers do not send the mandatory close_notify |
1053 | | * alert on shutdown. |
1054 | | * Relevant for openssl >= 3 */ |
1055 | | if((SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF) & |
1056 | | SSL_OP_IGNORE_UNEXPECTED_EOF) != SSL_OP_IGNORE_UNEXPECTED_EOF) { |
1057 | | log_crypto_err("could not set SSL_OP_IGNORE_UNEXPECTED_EOF"); |
1058 | | return 0; |
1059 | | } |
1060 | | #endif |
1061 | |
|
1062 | 0 | if((SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE) & |
1063 | 0 | SSL_OP_CIPHER_SERVER_PREFERENCE) != |
1064 | 0 | SSL_OP_CIPHER_SERVER_PREFERENCE) { |
1065 | 0 | log_crypto_err("could not set SSL_OP_CIPHER_SERVER_PREFERENCE"); |
1066 | 0 | return 0; |
1067 | 0 | } |
1068 | | |
1069 | 0 | #ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL |
1070 | 0 | SSL_CTX_set_security_level(ctx, 0); |
1071 | 0 | #endif |
1072 | | #if defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB) && defined(HAVE_NGHTTP2) |
1073 | | SSL_CTX_set_alpn_select_cb(ctx, alpn_select_cb, NULL); |
1074 | | #endif |
1075 | | #else |
1076 | | (void)ctxt; |
1077 | | #endif /* HAVE_SSL */ |
1078 | 0 | return 1; |
1079 | 0 | } |
1080 | | |
1081 | | void |
1082 | | listen_sslctx_setup_2(void* ctxt) |
1083 | 0 | { |
1084 | 0 | #ifdef HAVE_SSL |
1085 | 0 | SSL_CTX* ctx = (SSL_CTX*)ctxt; |
1086 | 0 | (void)ctx; |
1087 | 0 | #if HAVE_DECL_SSL_CTX_SET_ECDH_AUTO |
1088 | 0 | if(!SSL_CTX_set_ecdh_auto(ctx,1)) { |
1089 | 0 | log_crypto_err("Error in SSL_CTX_ecdh_auto, not enabling ECDHE"); |
1090 | 0 | } |
1091 | | #elif defined(USE_ECDSA) |
1092 | | if(1) { |
1093 | | EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1); |
1094 | | if (!ecdh) { |
1095 | | log_crypto_err("could not find p256, not enabling ECDHE"); |
1096 | | } else { |
1097 | | if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh)) { |
1098 | | log_crypto_err("Error in SSL_CTX_set_tmp_ecdh, not enabling ECDHE"); |
1099 | | } |
1100 | | EC_KEY_free (ecdh); |
1101 | | } |
1102 | | } |
1103 | | #endif |
1104 | | #else |
1105 | | (void)ctxt; |
1106 | | #endif /* HAVE_SSL */ |
1107 | 0 | } |
1108 | | |
1109 | | void* listen_sslctx_create(char* key, char* pem, char* verifypem) |
1110 | 0 | { |
1111 | 0 | #ifdef HAVE_SSL |
1112 | 0 | SSL_CTX* ctx = SSL_CTX_new(SSLv23_server_method()); |
1113 | 0 | if(!ctx) { |
1114 | 0 | log_crypto_err("could not SSL_CTX_new"); |
1115 | 0 | return NULL; |
1116 | 0 | } |
1117 | 0 | if(!key || key[0] == 0) { |
1118 | 0 | log_err("error: no tls-service-key file specified"); |
1119 | 0 | SSL_CTX_free(ctx); |
1120 | 0 | return NULL; |
1121 | 0 | } |
1122 | 0 | if(!pem || pem[0] == 0) { |
1123 | 0 | log_err("error: no tls-service-pem file specified"); |
1124 | 0 | SSL_CTX_free(ctx); |
1125 | 0 | return NULL; |
1126 | 0 | } |
1127 | 0 | if(!listen_sslctx_setup(ctx)) { |
1128 | 0 | SSL_CTX_free(ctx); |
1129 | 0 | return NULL; |
1130 | 0 | } |
1131 | 0 | if(!SSL_CTX_use_certificate_chain_file(ctx, pem)) { |
1132 | 0 | log_err("error for cert file: %s", pem); |
1133 | 0 | log_crypto_err("error in SSL_CTX use_certificate_chain_file"); |
1134 | 0 | SSL_CTX_free(ctx); |
1135 | 0 | return NULL; |
1136 | 0 | } |
1137 | 0 | if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) { |
1138 | 0 | log_err("error for private key file: %s", key); |
1139 | 0 | log_crypto_err("Error in SSL_CTX use_PrivateKey_file"); |
1140 | 0 | SSL_CTX_free(ctx); |
1141 | 0 | return NULL; |
1142 | 0 | } |
1143 | 0 | if(!SSL_CTX_check_private_key(ctx)) { |
1144 | 0 | log_err("error for key file: %s", key); |
1145 | 0 | log_crypto_err("Error in SSL_CTX check_private_key"); |
1146 | 0 | SSL_CTX_free(ctx); |
1147 | 0 | return NULL; |
1148 | 0 | } |
1149 | 0 | listen_sslctx_setup_2(ctx); |
1150 | 0 | if(verifypem && verifypem[0]) { |
1151 | 0 | if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) { |
1152 | 0 | log_crypto_err("Error in SSL_CTX verify locations"); |
1153 | 0 | SSL_CTX_free(ctx); |
1154 | 0 | return NULL; |
1155 | 0 | } |
1156 | 0 | SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file( |
1157 | 0 | verifypem)); |
1158 | 0 | SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); |
1159 | 0 | } |
1160 | 0 | return ctx; |
1161 | | #else |
1162 | | (void)key; (void)pem; (void)verifypem; |
1163 | | return NULL; |
1164 | | #endif |
1165 | 0 | } |
1166 | | |
1167 | | #ifdef USE_WINSOCK |
1168 | | /* For windows, the CA trust store is not read by openssl. |
1169 | | Add code to open the trust store using wincrypt API and add |
1170 | | the root certs into openssl trust store */ |
1171 | | static int |
1172 | | add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx) |
1173 | | { |
1174 | | HCERTSTORE hSystemStore; |
1175 | | PCCERT_CONTEXT pTargetCert = NULL; |
1176 | | X509_STORE* store; |
1177 | | |
1178 | | verbose(VERB_ALGO, "Adding Windows certificates from system root store to CA store"); |
1179 | | |
1180 | | /* load just once per context lifetime for this version |
1181 | | TODO: dynamically update CA trust changes as they are available */ |
1182 | | if (!tls_ctx) |
1183 | | return 0; |
1184 | | |
1185 | | /* Call wincrypt's CertOpenStore to open the CA root store. */ |
1186 | | |
1187 | | if ((hSystemStore = CertOpenStore( |
1188 | | CERT_STORE_PROV_SYSTEM, |
1189 | | 0, |
1190 | | 0, |
1191 | | /* NOTE: mingw does not have this const: replace with 1 << 16 from code |
1192 | | CERT_SYSTEM_STORE_CURRENT_USER, */ |
1193 | | 1 << 16, |
1194 | | L"root")) == 0) |
1195 | | { |
1196 | | return 0; |
1197 | | } |
1198 | | |
1199 | | store = SSL_CTX_get_cert_store(tls_ctx); |
1200 | | if (!store) |
1201 | | return 0; |
1202 | | |
1203 | | /* failure if the CA store is empty or the call fails */ |
1204 | | if ((pTargetCert = CertEnumCertificatesInStore( |
1205 | | hSystemStore, pTargetCert)) == 0) { |
1206 | | verbose(VERB_ALGO, "CA certificate store for Windows is empty."); |
1207 | | return 0; |
1208 | | } |
1209 | | /* iterate over the windows cert store and add to openssl store */ |
1210 | | do |
1211 | | { |
1212 | | X509 *cert1 = d2i_X509(NULL, |
1213 | | (const unsigned char **)&pTargetCert->pbCertEncoded, |
1214 | | pTargetCert->cbCertEncoded); |
1215 | | if (!cert1) { |
1216 | | unsigned long error = ERR_get_error(); |
1217 | | /* return error if a cert fails */ |
1218 | | verbose(VERB_ALGO, "%s %d:%s", |
1219 | | "Unable to parse certificate in memory", |
1220 | | (int)error, ERR_error_string(error, NULL)); |
1221 | | return 0; |
1222 | | } |
1223 | | else { |
1224 | | /* return error if a cert add to store fails */ |
1225 | | if (X509_STORE_add_cert(store, cert1) == 0) { |
1226 | | unsigned long error = ERR_peek_last_error(); |
1227 | | |
1228 | | /* Ignore error X509_R_CERT_ALREADY_IN_HASH_TABLE which means the |
1229 | | * certificate is already in the store. */ |
1230 | | if(ERR_GET_LIB(error) != ERR_LIB_X509 || |
1231 | | ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) { |
1232 | | error = ERR_get_error(); |
1233 | | verbose(VERB_ALGO, "%s %d:%s\n", |
1234 | | "Error adding certificate", (int)error, |
1235 | | ERR_error_string(error, NULL)); |
1236 | | X509_free(cert1); |
1237 | | return 0; |
1238 | | } |
1239 | | } |
1240 | | X509_free(cert1); |
1241 | | } |
1242 | | } while ((pTargetCert = CertEnumCertificatesInStore( |
1243 | | hSystemStore, pTargetCert)) != 0); |
1244 | | |
1245 | | /* Clean up memory and quit. */ |
1246 | | if (pTargetCert) |
1247 | | CertFreeCertificateContext(pTargetCert); |
1248 | | if (hSystemStore) |
1249 | | { |
1250 | | if (!CertCloseStore( |
1251 | | hSystemStore, 0)) |
1252 | | return 0; |
1253 | | } |
1254 | | verbose(VERB_ALGO, "Completed adding Windows certificates to CA store successfully"); |
1255 | | return 1; |
1256 | | } |
1257 | | #endif /* USE_WINSOCK */ |
1258 | | |
1259 | | void* connect_sslctx_create(char* key, char* pem, char* verifypem, int wincert) |
1260 | 0 | { |
1261 | 0 | #ifdef HAVE_SSL |
1262 | 0 | SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method()); |
1263 | 0 | if(!ctx) { |
1264 | 0 | log_crypto_err("could not allocate SSL_CTX pointer"); |
1265 | 0 | return NULL; |
1266 | 0 | } |
1267 | | #if SSL_OP_NO_SSLv2 != 0 |
1268 | | if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2) |
1269 | | != SSL_OP_NO_SSLv2) { |
1270 | | log_crypto_err("could not set SSL_OP_NO_SSLv2"); |
1271 | | SSL_CTX_free(ctx); |
1272 | | return NULL; |
1273 | | } |
1274 | | #endif |
1275 | 0 | if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3) |
1276 | 0 | != SSL_OP_NO_SSLv3) { |
1277 | 0 | log_crypto_err("could not set SSL_OP_NO_SSLv3"); |
1278 | 0 | SSL_CTX_free(ctx); |
1279 | 0 | return NULL; |
1280 | 0 | } |
1281 | 0 | #if defined(SSL_OP_NO_RENEGOTIATION) |
1282 | | /* disable client renegotiation */ |
1283 | 0 | if((SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION) & |
1284 | 0 | SSL_OP_NO_RENEGOTIATION) != SSL_OP_NO_RENEGOTIATION) { |
1285 | 0 | log_crypto_err("could not set SSL_OP_NO_RENEGOTIATION"); |
1286 | 0 | SSL_CTX_free(ctx); |
1287 | 0 | return 0; |
1288 | 0 | } |
1289 | 0 | #endif |
1290 | | #if defined(SSL_OP_IGNORE_UNEXPECTED_EOF) |
1291 | | /* ignore errors when peers do not send the mandatory close_notify |
1292 | | * alert on shutdown. |
1293 | | * Relevant for openssl >= 3 */ |
1294 | | if((SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF) & |
1295 | | SSL_OP_IGNORE_UNEXPECTED_EOF) != SSL_OP_IGNORE_UNEXPECTED_EOF) { |
1296 | | log_crypto_err("could not set SSL_OP_IGNORE_UNEXPECTED_EOF"); |
1297 | | SSL_CTX_free(ctx); |
1298 | | return 0; |
1299 | | } |
1300 | | #endif |
1301 | 0 | if(key && key[0]) { |
1302 | 0 | if(!SSL_CTX_use_certificate_chain_file(ctx, pem)) { |
1303 | 0 | log_err("error in client certificate %s", pem); |
1304 | 0 | log_crypto_err("error in certificate file"); |
1305 | 0 | SSL_CTX_free(ctx); |
1306 | 0 | return NULL; |
1307 | 0 | } |
1308 | 0 | if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) { |
1309 | 0 | log_err("error in client private key %s", key); |
1310 | 0 | log_crypto_err("error in key file"); |
1311 | 0 | SSL_CTX_free(ctx); |
1312 | 0 | return NULL; |
1313 | 0 | } |
1314 | 0 | if(!SSL_CTX_check_private_key(ctx)) { |
1315 | 0 | log_err("error in client key %s", key); |
1316 | 0 | log_crypto_err("error in SSL_CTX_check_private_key"); |
1317 | 0 | SSL_CTX_free(ctx); |
1318 | 0 | return NULL; |
1319 | 0 | } |
1320 | 0 | } |
1321 | 0 | if((verifypem && verifypem[0]) || wincert) { |
1322 | 0 | if(verifypem && verifypem[0]) { |
1323 | 0 | if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) { |
1324 | 0 | log_crypto_err("error in SSL_CTX verify"); |
1325 | 0 | SSL_CTX_free(ctx); |
1326 | 0 | return NULL; |
1327 | 0 | } |
1328 | 0 | } |
1329 | | #ifdef USE_WINSOCK |
1330 | | if(wincert) { |
1331 | | if(!add_WIN_cacerts_to_openssl_store(ctx)) { |
1332 | | log_crypto_err("error in add_WIN_cacerts_to_openssl_store"); |
1333 | | SSL_CTX_free(ctx); |
1334 | | return NULL; |
1335 | | } |
1336 | | } |
1337 | | #else |
1338 | 0 | if(wincert) { |
1339 | 0 | if(!SSL_CTX_set_default_verify_paths(ctx)) { |
1340 | 0 | log_crypto_err("error in default_verify_paths"); |
1341 | 0 | SSL_CTX_free(ctx); |
1342 | 0 | return NULL; |
1343 | 0 | } |
1344 | 0 | } |
1345 | 0 | #endif |
1346 | 0 | SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); |
1347 | 0 | } |
1348 | 0 | return ctx; |
1349 | | #else |
1350 | | (void)key; (void)pem; (void)verifypem; (void)wincert; |
1351 | | return NULL; |
1352 | | #endif |
1353 | 0 | } |
1354 | | |
1355 | | void* incoming_ssl_fd(void* sslctx, int fd) |
1356 | 0 | { |
1357 | 0 | #ifdef HAVE_SSL |
1358 | 0 | SSL* ssl = SSL_new((SSL_CTX*)sslctx); |
1359 | 0 | if(!ssl) { |
1360 | 0 | log_crypto_err("could not SSL_new"); |
1361 | 0 | return NULL; |
1362 | 0 | } |
1363 | 0 | SSL_set_accept_state(ssl); |
1364 | 0 | (void)SSL_set_mode(ssl, (long)SSL_MODE_AUTO_RETRY); |
1365 | 0 | if(!SSL_set_fd(ssl, fd)) { |
1366 | 0 | log_crypto_err("could not SSL_set_fd"); |
1367 | 0 | SSL_free(ssl); |
1368 | 0 | return NULL; |
1369 | 0 | } |
1370 | 0 | return ssl; |
1371 | | #else |
1372 | | (void)sslctx; (void)fd; |
1373 | | return NULL; |
1374 | | #endif |
1375 | 0 | } |
1376 | | |
1377 | | void* outgoing_ssl_fd(void* sslctx, int fd) |
1378 | 0 | { |
1379 | 0 | #ifdef HAVE_SSL |
1380 | 0 | SSL* ssl = SSL_new((SSL_CTX*)sslctx); |
1381 | 0 | if(!ssl) { |
1382 | 0 | log_crypto_err("could not SSL_new"); |
1383 | 0 | return NULL; |
1384 | 0 | } |
1385 | 0 | SSL_set_connect_state(ssl); |
1386 | 0 | (void)SSL_set_mode(ssl, (long)SSL_MODE_AUTO_RETRY); |
1387 | 0 | if(!SSL_set_fd(ssl, fd)) { |
1388 | 0 | log_crypto_err("could not SSL_set_fd"); |
1389 | 0 | SSL_free(ssl); |
1390 | 0 | return NULL; |
1391 | 0 | } |
1392 | 0 | return ssl; |
1393 | | #else |
1394 | | (void)sslctx; (void)fd; |
1395 | | return NULL; |
1396 | | #endif |
1397 | 0 | } |
1398 | | |
1399 | | int check_auth_name_for_ssl(char* auth_name) |
1400 | 0 | { |
1401 | 0 | if(!auth_name) return 1; |
1402 | | #if defined(HAVE_SSL) && !defined(HAVE_SSL_SET1_HOST) && !defined(HAVE_X509_VERIFY_PARAM_SET1_HOST) |
1403 | | log_err("the query has an auth_name %s, but libssl has no call to " |
1404 | | "perform TLS authentication. Remove that name from config " |
1405 | | "or upgrade the ssl crypto library.", auth_name); |
1406 | | return 0; |
1407 | | #else |
1408 | 0 | return 1; |
1409 | 0 | #endif |
1410 | 0 | } |
1411 | | |
1412 | | /** set the authname on an SSL structure, SSL* ssl */ |
1413 | | int set_auth_name_on_ssl(void* ssl, char* auth_name, int use_sni) |
1414 | 0 | { |
1415 | 0 | if(!auth_name) return 1; |
1416 | 0 | #ifdef HAVE_SSL |
1417 | 0 | if(use_sni) { |
1418 | 0 | (void)SSL_set_tlsext_host_name(ssl, auth_name); |
1419 | 0 | } |
1420 | | #else |
1421 | | (void)ssl; |
1422 | | (void)use_sni; |
1423 | | #endif |
1424 | 0 | #ifdef HAVE_SSL_SET1_HOST |
1425 | 0 | SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL); |
1426 | | /* setting the hostname makes openssl verify the |
1427 | | * host name in the x509 certificate in the |
1428 | | * SSL connection*/ |
1429 | 0 | if(!SSL_set1_host(ssl, auth_name)) { |
1430 | 0 | log_err("SSL_set1_host failed"); |
1431 | 0 | return 0; |
1432 | 0 | } |
1433 | | #elif defined(HAVE_X509_VERIFY_PARAM_SET1_HOST) |
1434 | | /* openssl 1.0.2 has this function that can be used for |
1435 | | * set1_host like verification */ |
1436 | | if(auth_name) { |
1437 | | X509_VERIFY_PARAM* param = SSL_get0_param(ssl); |
1438 | | # ifdef X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS |
1439 | | X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); |
1440 | | # endif |
1441 | | if(!X509_VERIFY_PARAM_set1_host(param, auth_name, strlen(auth_name))) { |
1442 | | log_err("X509_VERIFY_PARAM_set1_host failed"); |
1443 | | return 0; |
1444 | | } |
1445 | | SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL); |
1446 | | } |
1447 | | #else |
1448 | | verbose(VERB_ALGO, "the query has an auth_name, but libssl has no call to perform TLS authentication"); |
1449 | | #endif /* HAVE_SSL_SET1_HOST */ |
1450 | 0 | return 1; |
1451 | 0 | } |
1452 | | |
1453 | | #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L |
1454 | | /** global lock list for openssl locks */ |
1455 | | static lock_basic_type *ub_openssl_locks = NULL; |
1456 | | |
1457 | | /** callback that gets thread id for openssl */ |
1458 | | #ifdef HAVE_CRYPTO_THREADID_SET_CALLBACK |
1459 | | static void |
1460 | | ub_crypto_id_cb(CRYPTO_THREADID *id) |
1461 | | { |
1462 | | CRYPTO_THREADID_set_numeric(id, (unsigned long)log_thread_get()); |
1463 | | } |
1464 | | #else |
1465 | | static unsigned long |
1466 | | ub_crypto_id_cb(void) |
1467 | | { |
1468 | | return (unsigned long)log_thread_get(); |
1469 | | } |
1470 | | #endif |
1471 | | |
1472 | | static void |
1473 | | ub_crypto_lock_cb(int mode, int type, const char *ATTR_UNUSED(file), |
1474 | | int ATTR_UNUSED(line)) |
1475 | | { |
1476 | | if((mode&CRYPTO_LOCK)) { |
1477 | | lock_basic_lock(&ub_openssl_locks[type]); |
1478 | | } else { |
1479 | | lock_basic_unlock(&ub_openssl_locks[type]); |
1480 | | } |
1481 | | } |
1482 | | #endif /* OPENSSL_THREADS */ |
1483 | | |
1484 | | int ub_openssl_lock_init(void) |
1485 | 0 | { |
1486 | | #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L |
1487 | | int i; |
1488 | | ub_openssl_locks = (lock_basic_type*)reallocarray( |
1489 | | NULL, (size_t)CRYPTO_num_locks(), sizeof(lock_basic_type)); |
1490 | | if(!ub_openssl_locks) |
1491 | | return 0; |
1492 | | for(i=0; i<CRYPTO_num_locks(); i++) { |
1493 | | lock_basic_init(&ub_openssl_locks[i]); |
1494 | | } |
1495 | | # ifdef HAVE_CRYPTO_THREADID_SET_CALLBACK |
1496 | | CRYPTO_THREADID_set_callback(&ub_crypto_id_cb); |
1497 | | # else |
1498 | | CRYPTO_set_id_callback(&ub_crypto_id_cb); |
1499 | | # endif |
1500 | | CRYPTO_set_locking_callback(&ub_crypto_lock_cb); |
1501 | | #endif /* OPENSSL_THREADS */ |
1502 | 0 | return 1; |
1503 | 0 | } |
1504 | | |
1505 | | void ub_openssl_lock_delete(void) |
1506 | 0 | { |
1507 | | #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L |
1508 | | int i; |
1509 | | if(!ub_openssl_locks) |
1510 | | return; |
1511 | | # ifdef HAVE_CRYPTO_THREADID_SET_CALLBACK |
1512 | | CRYPTO_THREADID_set_callback(NULL); |
1513 | | # else |
1514 | | CRYPTO_set_id_callback(NULL); |
1515 | | # endif |
1516 | | CRYPTO_set_locking_callback(NULL); |
1517 | | for(i=0; i<CRYPTO_num_locks(); i++) { |
1518 | | lock_basic_destroy(&ub_openssl_locks[i]); |
1519 | | } |
1520 | | free(ub_openssl_locks); |
1521 | | #endif /* OPENSSL_THREADS */ |
1522 | 0 | } |
1523 | | |
1524 | 0 | int listen_sslctx_setup_ticket_keys(void* sslctx, struct config_strlist* tls_session_ticket_keys) { |
1525 | 0 | #ifdef HAVE_SSL |
1526 | 0 | size_t s = 1; |
1527 | 0 | struct config_strlist* p; |
1528 | 0 | struct tls_session_ticket_key *keys; |
1529 | 0 | for(p = tls_session_ticket_keys; p; p = p->next) { |
1530 | 0 | s++; |
1531 | 0 | } |
1532 | 0 | keys = calloc(s, sizeof(struct tls_session_ticket_key)); |
1533 | 0 | if(!keys) |
1534 | 0 | return 0; |
1535 | 0 | memset(keys, 0, s*sizeof(*keys)); |
1536 | 0 | ticket_keys = keys; |
1537 | |
|
1538 | 0 | for(p = tls_session_ticket_keys; p; p = p->next) { |
1539 | 0 | size_t n; |
1540 | 0 | unsigned char *data; |
1541 | 0 | FILE *f; |
1542 | |
|
1543 | 0 | data = (unsigned char *)malloc(80); |
1544 | 0 | if(!data) |
1545 | 0 | return 0; |
1546 | | |
1547 | 0 | f = fopen(p->str, "rb"); |
1548 | 0 | if(!f) { |
1549 | 0 | log_err("could not read tls-session-ticket-key %s: %s", p->str, strerror(errno)); |
1550 | 0 | free(data); |
1551 | 0 | return 0; |
1552 | 0 | } |
1553 | 0 | n = fread(data, 1, 80, f); |
1554 | 0 | fclose(f); |
1555 | |
|
1556 | 0 | if(n != 80) { |
1557 | 0 | log_err("tls-session-ticket-key %s is %d bytes, must be 80 bytes", p->str, (int)n); |
1558 | 0 | free(data); |
1559 | 0 | return 0; |
1560 | 0 | } |
1561 | 0 | verbose(VERB_OPS, "read tls-session-ticket-key: %s", p->str); |
1562 | |
|
1563 | 0 | keys->key_name = data; |
1564 | 0 | keys->aes_key = data + 16; |
1565 | 0 | keys->hmac_key = data + 48; |
1566 | 0 | keys++; |
1567 | 0 | } |
1568 | | /* terminate array with NULL key name entry */ |
1569 | 0 | keys->key_name = NULL; |
1570 | | # ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB |
1571 | | if(SSL_CTX_set_tlsext_ticket_key_evp_cb(sslctx, tls_session_ticket_key_cb) == 0) { |
1572 | | log_err("no support for TLS session ticket"); |
1573 | | return 0; |
1574 | | } |
1575 | | # else |
1576 | 0 | if(SSL_CTX_set_tlsext_ticket_key_cb(sslctx, tls_session_ticket_key_cb) == 0) { |
1577 | 0 | log_err("no support for TLS session ticket"); |
1578 | 0 | return 0; |
1579 | 0 | } |
1580 | 0 | # endif |
1581 | 0 | return 1; |
1582 | | #else |
1583 | | (void)sslctx; |
1584 | | (void)tls_session_ticket_keys; |
1585 | | return 0; |
1586 | | #endif |
1587 | |
|
1588 | 0 | } |
1589 | | |
1590 | | #ifdef HAVE_SSL |
1591 | | int tls_session_ticket_key_cb(SSL *ATTR_UNUSED(sslctx), unsigned char* key_name, |
1592 | | unsigned char* iv, EVP_CIPHER_CTX *evp_sctx, |
1593 | | #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB |
1594 | | EVP_MAC_CTX *hmac_ctx, |
1595 | | #else |
1596 | | HMAC_CTX* hmac_ctx, |
1597 | | #endif |
1598 | | int enc) |
1599 | 0 | { |
1600 | 0 | #ifdef HAVE_SSL |
1601 | | # ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB |
1602 | | OSSL_PARAM params[3]; |
1603 | | # else |
1604 | 0 | const EVP_MD *digest; |
1605 | 0 | # endif |
1606 | 0 | const EVP_CIPHER *cipher; |
1607 | 0 | int evp_cipher_length; |
1608 | 0 | # ifndef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB |
1609 | 0 | digest = EVP_sha256(); |
1610 | 0 | # endif |
1611 | 0 | cipher = EVP_aes_256_cbc(); |
1612 | 0 | evp_cipher_length = EVP_CIPHER_iv_length(cipher); |
1613 | 0 | if( enc == 1 ) { |
1614 | | /* encrypt */ |
1615 | 0 | verbose(VERB_CLIENT, "start session encrypt"); |
1616 | 0 | memcpy(key_name, ticket_keys->key_name, 16); |
1617 | 0 | if (RAND_bytes(iv, evp_cipher_length) != 1) { |
1618 | 0 | verbose(VERB_CLIENT, "RAND_bytes failed"); |
1619 | 0 | return -1; |
1620 | 0 | } |
1621 | 0 | if (EVP_EncryptInit_ex(evp_sctx, cipher, NULL, ticket_keys->aes_key, iv) != 1) { |
1622 | 0 | verbose(VERB_CLIENT, "EVP_EncryptInit_ex failed"); |
1623 | 0 | return -1; |
1624 | 0 | } |
1625 | | #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB |
1626 | | params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, |
1627 | | ticket_keys->hmac_key, 32); |
1628 | | params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, |
1629 | | "sha256", 0); |
1630 | | params[2] = OSSL_PARAM_construct_end(); |
1631 | | #ifdef HAVE_EVP_MAC_CTX_SET_PARAMS |
1632 | | EVP_MAC_CTX_set_params(hmac_ctx, params); |
1633 | | #else |
1634 | | EVP_MAC_set_ctx_params(hmac_ctx, params); |
1635 | | #endif |
1636 | | #elif !defined(HMAC_INIT_EX_RETURNS_VOID) |
1637 | 0 | if (HMAC_Init_ex(hmac_ctx, ticket_keys->hmac_key, 32, digest, NULL) != 1) { |
1638 | 0 | verbose(VERB_CLIENT, "HMAC_Init_ex failed"); |
1639 | 0 | return -1; |
1640 | 0 | } |
1641 | | #else |
1642 | | HMAC_Init_ex(hmac_ctx, ticket_keys->hmac_key, 32, digest, NULL); |
1643 | | #endif |
1644 | 0 | return 1; |
1645 | 0 | } else if (enc == 0) { |
1646 | | /* decrypt */ |
1647 | 0 | struct tls_session_ticket_key *key; |
1648 | 0 | verbose(VERB_CLIENT, "start session decrypt"); |
1649 | 0 | for(key = ticket_keys; key->key_name != NULL; key++) { |
1650 | 0 | if (!memcmp(key_name, key->key_name, 16)) { |
1651 | 0 | verbose(VERB_CLIENT, "Found session_key"); |
1652 | 0 | break; |
1653 | 0 | } |
1654 | 0 | } |
1655 | 0 | if(key->key_name == NULL) { |
1656 | 0 | verbose(VERB_CLIENT, "Not found session_key"); |
1657 | 0 | return 0; |
1658 | 0 | } |
1659 | | |
1660 | | #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB |
1661 | | params[0] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, |
1662 | | key->hmac_key, 32); |
1663 | | params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, |
1664 | | "sha256", 0); |
1665 | | params[2] = OSSL_PARAM_construct_end(); |
1666 | | #ifdef HAVE_EVP_MAC_CTX_SET_PARAMS |
1667 | | EVP_MAC_CTX_set_params(hmac_ctx, params); |
1668 | | #else |
1669 | | EVP_MAC_set_ctx_params(hmac_ctx, params); |
1670 | | #endif |
1671 | | #elif !defined(HMAC_INIT_EX_RETURNS_VOID) |
1672 | 0 | if (HMAC_Init_ex(hmac_ctx, key->hmac_key, 32, digest, NULL) != 1) { |
1673 | 0 | verbose(VERB_CLIENT, "HMAC_Init_ex failed"); |
1674 | 0 | return -1; |
1675 | 0 | } |
1676 | | #else |
1677 | | HMAC_Init_ex(hmac_ctx, key->hmac_key, 32, digest, NULL); |
1678 | | #endif |
1679 | 0 | if (EVP_DecryptInit_ex(evp_sctx, cipher, NULL, key->aes_key, iv) != 1) { |
1680 | 0 | log_err("EVP_DecryptInit_ex failed"); |
1681 | 0 | return -1; |
1682 | 0 | } |
1683 | | |
1684 | 0 | return (key == ticket_keys) ? 1 : 2; |
1685 | 0 | } |
1686 | 0 | return -1; |
1687 | | #else |
1688 | | (void)key_name; |
1689 | | (void)iv; |
1690 | | (void)evp_sctx; |
1691 | | (void)hmac_ctx; |
1692 | | (void)enc; |
1693 | | return 0; |
1694 | | #endif |
1695 | 0 | } |
1696 | | #endif /* HAVE_SSL */ |
1697 | | |
1698 | | void |
1699 | | listen_sslctx_delete_ticket_keys(void) |
1700 | 0 | { |
1701 | 0 | struct tls_session_ticket_key *key; |
1702 | 0 | if(!ticket_keys) return; |
1703 | 0 | for(key = ticket_keys; key->key_name != NULL; key++) { |
1704 | | /* wipe key data from memory*/ |
1705 | 0 | #ifdef HAVE_EXPLICIT_BZERO |
1706 | 0 | explicit_bzero(key->key_name, 80); |
1707 | | #else |
1708 | | memset(key->key_name, 0xdd, 80); |
1709 | | #endif |
1710 | 0 | free(key->key_name); |
1711 | 0 | } |
1712 | 0 | free(ticket_keys); |
1713 | 0 | ticket_keys = NULL; |
1714 | 0 | } |
1715 | | |
1716 | | # ifndef USE_WINSOCK |
1717 | | char* |
1718 | | sock_strerror(int errn) |
1719 | 0 | { |
1720 | 0 | return strerror(errn); |
1721 | 0 | } |
1722 | | |
1723 | | void |
1724 | | sock_close(int socket) |
1725 | 0 | { |
1726 | 0 | close(socket); |
1727 | 0 | } |
1728 | | |
1729 | | # else |
1730 | | char* |
1731 | | sock_strerror(int ATTR_UNUSED(errn)) |
1732 | | { |
1733 | | return wsa_strerror(WSAGetLastError()); |
1734 | | } |
1735 | | |
1736 | | void |
1737 | | sock_close(int socket) |
1738 | | { |
1739 | | closesocket(socket); |
1740 | | } |
1741 | | # endif /* USE_WINSOCK */ |