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