xref: /openbsd-src/sbin/unwind/libunbound/util/net_help.c (revision 7037e34cdfd270b3989fb1829c7cd3439048bd3a)
1ae8c6e27Sflorian /*
2ae8c6e27Sflorian  * util/net_help.c - implementation of the network helper code
3ae8c6e27Sflorian  *
4ae8c6e27Sflorian  * Copyright (c) 2007, NLnet Labs. All rights reserved.
5ae8c6e27Sflorian  *
6ae8c6e27Sflorian  * This software is open source.
7ae8c6e27Sflorian  *
8ae8c6e27Sflorian  * Redistribution and use in source and binary forms, with or without
9ae8c6e27Sflorian  * modification, are permitted provided that the following conditions
10ae8c6e27Sflorian  * are met:
11ae8c6e27Sflorian  *
12ae8c6e27Sflorian  * Redistributions of source code must retain the above copyright notice,
13ae8c6e27Sflorian  * this list of conditions and the following disclaimer.
14ae8c6e27Sflorian  *
15ae8c6e27Sflorian  * Redistributions in binary form must reproduce the above copyright notice,
16ae8c6e27Sflorian  * this list of conditions and the following disclaimer in the documentation
17ae8c6e27Sflorian  * and/or other materials provided with the distribution.
18ae8c6e27Sflorian  *
19ae8c6e27Sflorian  * Neither the name of the NLNET LABS nor the names of its contributors may
20ae8c6e27Sflorian  * be used to endorse or promote products derived from this software without
21ae8c6e27Sflorian  * specific prior written permission.
22ae8c6e27Sflorian  *
23ae8c6e27Sflorian  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24ae8c6e27Sflorian  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25ae8c6e27Sflorian  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26ae8c6e27Sflorian  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27ae8c6e27Sflorian  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28ae8c6e27Sflorian  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29ae8c6e27Sflorian  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30ae8c6e27Sflorian  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31ae8c6e27Sflorian  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32ae8c6e27Sflorian  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33ae8c6e27Sflorian  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34ae8c6e27Sflorian  */
35ae8c6e27Sflorian /**
36ae8c6e27Sflorian  * \file
37ae8c6e27Sflorian  * Implementation of net_help.h.
38ae8c6e27Sflorian  */
39ae8c6e27Sflorian 
40ae8c6e27Sflorian #include "config.h"
41ebe14541Sflorian #ifdef HAVE_SYS_TYPES_H
42ebe14541Sflorian #  include <sys/types.h>
43ebe14541Sflorian #endif
44ebe14541Sflorian #ifdef HAVE_NET_IF_H
45ebe14541Sflorian #include <net/if.h>
46ebe14541Sflorian #endif
47a1a7ba80Sflorian #ifdef HAVE_NETIOAPI_H
48a1a7ba80Sflorian #include <netioapi.h>
49a1a7ba80Sflorian #endif
50*7037e34cSflorian #include <ctype.h>
51ae8c6e27Sflorian #include "util/net_help.h"
52ae8c6e27Sflorian #include "util/log.h"
53ae8c6e27Sflorian #include "util/data/dname.h"
54ae8c6e27Sflorian #include "util/module.h"
55ae8c6e27Sflorian #include "util/regional.h"
56e97c6e54Ssthen #include "util/config_file.h"
57ae8c6e27Sflorian #include "sldns/parseutil.h"
58ae8c6e27Sflorian #include "sldns/wire2str.h"
59a1a7ba80Sflorian #include "sldns/str2wire.h"
60ae8c6e27Sflorian #include <fcntl.h>
61ae8c6e27Sflorian #ifdef HAVE_OPENSSL_SSL_H
62ae8c6e27Sflorian #include <openssl/ssl.h>
63e97c6e54Ssthen #include <openssl/evp.h>
64e97c6e54Ssthen #include <openssl/rand.h>
65ae8c6e27Sflorian #endif
66ae8c6e27Sflorian #ifdef HAVE_OPENSSL_ERR_H
67ae8c6e27Sflorian #include <openssl/err.h>
68ae8c6e27Sflorian #endif
69e47fef9eSflorian #ifdef HAVE_OPENSSL_CORE_NAMES_H
70e47fef9eSflorian #include <openssl/core_names.h>
71e47fef9eSflorian #endif
72ae8c6e27Sflorian #ifdef USE_WINSOCK
73ae8c6e27Sflorian #include <wincrypt.h>
74ae8c6e27Sflorian #endif
75f4f0f0ceSflorian #ifdef HAVE_NGHTTP2_NGHTTP2_H
76f4f0f0ceSflorian #include <nghttp2/nghttp2.h>
77f4f0f0ceSflorian #endif
78ae8c6e27Sflorian 
79ae8c6e27Sflorian /** max length of an IP address (the address portion) that we allow */
80ae8c6e27Sflorian #define MAX_ADDR_STRLEN 128 /* characters */
81096314feSflorian /** max length of a hostname (with port and tls name) that we allow */
82096314feSflorian #define MAX_HOST_STRLEN (LDNS_MAX_DOMAINLEN * 3) /* characters */
83ae8c6e27Sflorian /** default value for EDNS ADVERTISED size */
84ae8c6e27Sflorian uint16_t EDNS_ADVERTISED_SIZE = 4096;
85ae8c6e27Sflorian 
86ae8c6e27Sflorian /** minimal responses when positive answer: default is no */
87ae8c6e27Sflorian int MINIMAL_RESPONSES = 0;
88ae8c6e27Sflorian 
89e47fef9eSflorian /** rrset order roundrobin: default is yes */
90e47fef9eSflorian int RRSET_ROUNDROBIN = 1;
91ae8c6e27Sflorian 
92e97c6e54Ssthen /** log tag queries with name instead of 'info' for filtering */
93e97c6e54Ssthen int LOG_TAG_QUERYREPLY = 0;
94e97c6e54Ssthen 
95e97c6e54Ssthen static struct tls_session_ticket_key {
96e97c6e54Ssthen 	unsigned char *key_name;
97e97c6e54Ssthen 	unsigned char *aes_key;
98e97c6e54Ssthen 	unsigned char *hmac_key;
99e97c6e54Ssthen } *ticket_keys;
100e97c6e54Ssthen 
101f4f0f0ceSflorian #ifdef HAVE_SSL
102e47fef9eSflorian /**
103e47fef9eSflorian  * callback TLS session ticket encrypt and decrypt
104e47fef9eSflorian  * For use with SSL_CTX_set_tlsext_ticket_key_cb or
105e47fef9eSflorian  * SSL_CTX_set_tlsext_ticket_key_evp_cb
106e47fef9eSflorian  * @param s: the SSL_CTX to use (from connect_sslctx_create())
107e47fef9eSflorian  * @param key_name: secret name, 16 bytes
108e47fef9eSflorian  * @param iv: up to EVP_MAX_IV_LENGTH.
109e47fef9eSflorian  * @param evp_ctx: the evp cipher context, function sets this.
110e47fef9eSflorian  * @param hmac_ctx: the hmac context, function sets this.
111e47fef9eSflorian  * 	with ..key_cb it is of type HMAC_CTX*
112e47fef9eSflorian  * 	with ..key_evp_cb it is of type EVP_MAC_CTX*
113e47fef9eSflorian  * @param enc: 1 is encrypt, 0 is decrypt
114e47fef9eSflorian  * @return 0 on no ticket, 1 for okay, and 2 for okay but renew the ticket
115e47fef9eSflorian  * 	(the ticket is decrypt only). and <0 for failures.
116e47fef9eSflorian  */
117e47fef9eSflorian int tls_session_ticket_key_cb(SSL *s, unsigned char* key_name,
118e47fef9eSflorian 	unsigned char* iv, EVP_CIPHER_CTX *evp_ctx,
119e47fef9eSflorian #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
120e47fef9eSflorian 	EVP_MAC_CTX *hmac_ctx,
121e47fef9eSflorian #else
122e47fef9eSflorian 	HMAC_CTX* hmac_ctx,
123e47fef9eSflorian #endif
124e47fef9eSflorian 	int enc);
125e47fef9eSflorian #endif /* HAVE_SSL */
126e47fef9eSflorian 
127ae8c6e27Sflorian /* returns true is string addr is an ip6 specced address */
128ae8c6e27Sflorian int
129ae8c6e27Sflorian str_is_ip6(const char* str)
130ae8c6e27Sflorian {
131ae8c6e27Sflorian 	if(strchr(str, ':'))
132ae8c6e27Sflorian 		return 1;
133ae8c6e27Sflorian 	else    return 0;
134ae8c6e27Sflorian }
135ae8c6e27Sflorian 
136ae8c6e27Sflorian int
137ae8c6e27Sflorian fd_set_nonblock(int s)
138ae8c6e27Sflorian {
139ae8c6e27Sflorian #ifdef HAVE_FCNTL
140ae8c6e27Sflorian 	int flag;
141ae8c6e27Sflorian 	if((flag = fcntl(s, F_GETFL)) == -1) {
142ae8c6e27Sflorian 		log_err("can't fcntl F_GETFL: %s", strerror(errno));
143ae8c6e27Sflorian 		flag = 0;
144ae8c6e27Sflorian 	}
145ae8c6e27Sflorian 	flag |= O_NONBLOCK;
146ae8c6e27Sflorian 	if(fcntl(s, F_SETFL, flag) == -1) {
147ae8c6e27Sflorian 		log_err("can't fcntl F_SETFL: %s", strerror(errno));
148ae8c6e27Sflorian 		return 0;
149ae8c6e27Sflorian 	}
150ae8c6e27Sflorian #elif defined(HAVE_IOCTLSOCKET)
151ae8c6e27Sflorian 	unsigned long on = 1;
152ae8c6e27Sflorian 	if(ioctlsocket(s, FIONBIO, &on) != 0) {
153ae8c6e27Sflorian 		log_err("can't ioctlsocket FIONBIO on: %s",
154ae8c6e27Sflorian 			wsa_strerror(WSAGetLastError()));
155ae8c6e27Sflorian 	}
156ae8c6e27Sflorian #endif
157ae8c6e27Sflorian 	return 1;
158ae8c6e27Sflorian }
159ae8c6e27Sflorian 
160ae8c6e27Sflorian int
161ae8c6e27Sflorian fd_set_block(int s)
162ae8c6e27Sflorian {
163ae8c6e27Sflorian #ifdef HAVE_FCNTL
164ae8c6e27Sflorian 	int flag;
165ae8c6e27Sflorian 	if((flag = fcntl(s, F_GETFL)) == -1) {
166ae8c6e27Sflorian 		log_err("cannot fcntl F_GETFL: %s", strerror(errno));
167ae8c6e27Sflorian 		flag = 0;
168ae8c6e27Sflorian 	}
169ae8c6e27Sflorian 	flag &= ~O_NONBLOCK;
170ae8c6e27Sflorian 	if(fcntl(s, F_SETFL, flag) == -1) {
171ae8c6e27Sflorian 		log_err("cannot fcntl F_SETFL: %s", strerror(errno));
172ae8c6e27Sflorian 		return 0;
173ae8c6e27Sflorian 	}
174ae8c6e27Sflorian #elif defined(HAVE_IOCTLSOCKET)
175ae8c6e27Sflorian 	unsigned long off = 0;
176ae8c6e27Sflorian 	if(ioctlsocket(s, FIONBIO, &off) != 0) {
177ae8c6e27Sflorian 		if(WSAGetLastError() != WSAEINVAL || verbosity >= 4)
178ae8c6e27Sflorian 			log_err("can't ioctlsocket FIONBIO off: %s",
179ae8c6e27Sflorian 				wsa_strerror(WSAGetLastError()));
180ae8c6e27Sflorian 	}
181ae8c6e27Sflorian #endif
182ae8c6e27Sflorian 	return 1;
183ae8c6e27Sflorian }
184ae8c6e27Sflorian 
185ae8c6e27Sflorian int
186ae8c6e27Sflorian is_pow2(size_t num)
187ae8c6e27Sflorian {
188ae8c6e27Sflorian 	if(num == 0) return 1;
189ae8c6e27Sflorian 	return (num & (num-1)) == 0;
190ae8c6e27Sflorian }
191ae8c6e27Sflorian 
192ae8c6e27Sflorian void*
193ae8c6e27Sflorian memdup(void* data, size_t len)
194ae8c6e27Sflorian {
195ae8c6e27Sflorian 	void* d;
196ae8c6e27Sflorian 	if(!data) return NULL;
197ae8c6e27Sflorian 	if(len == 0) return NULL;
198ae8c6e27Sflorian 	d = malloc(len);
199ae8c6e27Sflorian 	if(!d) return NULL;
200ae8c6e27Sflorian 	memcpy(d, data, len);
201ae8c6e27Sflorian 	return d;
202ae8c6e27Sflorian }
203ae8c6e27Sflorian 
204ae8c6e27Sflorian void
205ae8c6e27Sflorian log_addr(enum verbosity_value v, const char* str,
206ae8c6e27Sflorian 	struct sockaddr_storage* addr, socklen_t addrlen)
207ae8c6e27Sflorian {
208ae8c6e27Sflorian 	uint16_t port;
209ae8c6e27Sflorian 	const char* family = "unknown";
210ae8c6e27Sflorian 	char dest[100];
211ae8c6e27Sflorian 	int af = (int)((struct sockaddr_in*)addr)->sin_family;
212ae8c6e27Sflorian 	void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
213ae8c6e27Sflorian 	if(verbosity < v)
214ae8c6e27Sflorian 		return;
215ae8c6e27Sflorian 	switch(af) {
216ae8c6e27Sflorian 		case AF_INET: family="ip4"; break;
217ae8c6e27Sflorian 		case AF_INET6: family="ip6";
218ae8c6e27Sflorian 			sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
219ae8c6e27Sflorian 			break;
220ae8c6e27Sflorian 		case AF_LOCAL:
221ae8c6e27Sflorian 			dest[0]=0;
222ae8c6e27Sflorian 			(void)inet_ntop(af, sinaddr, dest,
223ae8c6e27Sflorian 				(socklen_t)sizeof(dest));
224ae8c6e27Sflorian 			verbose(v, "%s local %s", str, dest);
225ae8c6e27Sflorian 			return; /* do not continue and try to get port */
226ae8c6e27Sflorian 		default: break;
227ae8c6e27Sflorian 	}
228ae8c6e27Sflorian 	if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
229ae8c6e27Sflorian 		(void)strlcpy(dest, "(inet_ntop error)", sizeof(dest));
230ae8c6e27Sflorian 	}
231ae8c6e27Sflorian 	dest[sizeof(dest)-1] = 0;
232ae8c6e27Sflorian 	port = ntohs(((struct sockaddr_in*)addr)->sin_port);
233ae8c6e27Sflorian 	if(verbosity >= 4)
234ae8c6e27Sflorian 		verbose(v, "%s %s %s port %d (len %d)", str, family, dest,
235ae8c6e27Sflorian 			(int)port, (int)addrlen);
236ae8c6e27Sflorian 	else	verbose(v, "%s %s port %d", str, dest, (int)port);
237ae8c6e27Sflorian }
238ae8c6e27Sflorian 
239ae8c6e27Sflorian int
240ae8c6e27Sflorian extstrtoaddr(const char* str, struct sockaddr_storage* addr,
2415c45b740Sflorian 	socklen_t* addrlen, int port)
242ae8c6e27Sflorian {
243ae8c6e27Sflorian 	char* s;
244ae8c6e27Sflorian 	if((s=strchr(str, '@'))) {
245ae8c6e27Sflorian 		char buf[MAX_ADDR_STRLEN];
246ae8c6e27Sflorian 		if(s-str >= MAX_ADDR_STRLEN) {
247ae8c6e27Sflorian 			return 0;
248ae8c6e27Sflorian 		}
249ae8c6e27Sflorian 		(void)strlcpy(buf, str, sizeof(buf));
250ae8c6e27Sflorian 		buf[s-str] = 0;
251ae8c6e27Sflorian 		port = atoi(s+1);
252ae8c6e27Sflorian 		if(port == 0 && strcmp(s+1,"0")!=0) {
253ae8c6e27Sflorian 			return 0;
254ae8c6e27Sflorian 		}
255ae8c6e27Sflorian 		return ipstrtoaddr(buf, port, addr, addrlen);
256ae8c6e27Sflorian 	}
257ae8c6e27Sflorian 	return ipstrtoaddr(str, port, addr, addrlen);
258ae8c6e27Sflorian }
259ae8c6e27Sflorian 
260ae8c6e27Sflorian int
261ae8c6e27Sflorian ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr,
262ae8c6e27Sflorian 	socklen_t* addrlen)
263ae8c6e27Sflorian {
264ae8c6e27Sflorian 	uint16_t p;
265ae8c6e27Sflorian 	if(!ip) return 0;
266ae8c6e27Sflorian 	p = (uint16_t) port;
267ae8c6e27Sflorian 	if(str_is_ip6(ip)) {
268ae8c6e27Sflorian 		char buf[MAX_ADDR_STRLEN];
269ae8c6e27Sflorian 		char* s;
270ae8c6e27Sflorian 		struct sockaddr_in6* sa = (struct sockaddr_in6*)addr;
271ae8c6e27Sflorian 		*addrlen = (socklen_t)sizeof(struct sockaddr_in6);
272ae8c6e27Sflorian 		memset(sa, 0, *addrlen);
273ae8c6e27Sflorian 		sa->sin6_family = AF_INET6;
274ae8c6e27Sflorian 		sa->sin6_port = (in_port_t)htons(p);
275ae8c6e27Sflorian 		if((s=strchr(ip, '%'))) { /* ip6%interface, rfc 4007 */
276ae8c6e27Sflorian 			if(s-ip >= MAX_ADDR_STRLEN)
277ae8c6e27Sflorian 				return 0;
278ae8c6e27Sflorian 			(void)strlcpy(buf, ip, sizeof(buf));
279ae8c6e27Sflorian 			buf[s-ip]=0;
280ebe14541Sflorian #ifdef HAVE_IF_NAMETOINDEX
281ebe14541Sflorian 			if (!(sa->sin6_scope_id = if_nametoindex(s+1)))
282ebe14541Sflorian #endif /* HAVE_IF_NAMETOINDEX */
283ae8c6e27Sflorian 				sa->sin6_scope_id = (uint32_t)atoi(s+1);
284ae8c6e27Sflorian 			ip = buf;
285ae8c6e27Sflorian 		}
286ae8c6e27Sflorian 		if(inet_pton((int)sa->sin6_family, ip, &sa->sin6_addr) <= 0) {
287ae8c6e27Sflorian 			return 0;
288ae8c6e27Sflorian 		}
289ae8c6e27Sflorian 	} else { /* ip4 */
290ae8c6e27Sflorian 		struct sockaddr_in* sa = (struct sockaddr_in*)addr;
291ae8c6e27Sflorian 		*addrlen = (socklen_t)sizeof(struct sockaddr_in);
292ae8c6e27Sflorian 		memset(sa, 0, *addrlen);
293ae8c6e27Sflorian 		sa->sin_family = AF_INET;
294ae8c6e27Sflorian 		sa->sin_port = (in_port_t)htons(p);
295ae8c6e27Sflorian 		if(inet_pton((int)sa->sin_family, ip, &sa->sin_addr) <= 0) {
296ae8c6e27Sflorian 			return 0;
297ae8c6e27Sflorian 		}
298ae8c6e27Sflorian 	}
299ae8c6e27Sflorian 	return 1;
300ae8c6e27Sflorian }
301ae8c6e27Sflorian 
302ae8c6e27Sflorian int netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr,
303ae8c6e27Sflorian         socklen_t* addrlen, int* net)
304ae8c6e27Sflorian {
305ae8c6e27Sflorian 	char buf[64];
306ae8c6e27Sflorian 	char* s;
307ae8c6e27Sflorian 	*net = (str_is_ip6(str)?128:32);
308ae8c6e27Sflorian 	if((s=strchr(str, '/'))) {
309ae8c6e27Sflorian 		if(atoi(s+1) > *net) {
310ae8c6e27Sflorian 			log_err("netblock too large: %s", str);
311ae8c6e27Sflorian 			return 0;
312ae8c6e27Sflorian 		}
313ae8c6e27Sflorian 		*net = atoi(s+1);
314ae8c6e27Sflorian 		if(*net == 0 && strcmp(s+1, "0") != 0) {
315ae8c6e27Sflorian 			log_err("cannot parse netblock: '%s'", str);
316ae8c6e27Sflorian 			return 0;
317ae8c6e27Sflorian 		}
318ae8c6e27Sflorian 		strlcpy(buf, str, sizeof(buf));
319ae8c6e27Sflorian 		s = strchr(buf, '/');
320ae8c6e27Sflorian 		if(s) *s = 0;
321ae8c6e27Sflorian 		s = buf;
322ae8c6e27Sflorian 	}
323ae8c6e27Sflorian 	if(!ipstrtoaddr(s?s:str, port, addr, addrlen)) {
324ae8c6e27Sflorian 		log_err("cannot parse ip address: '%s'", str);
325ae8c6e27Sflorian 		return 0;
326ae8c6e27Sflorian 	}
327ae8c6e27Sflorian 	if(s) {
328ae8c6e27Sflorian 		addr_mask(addr, *addrlen, *net);
329ae8c6e27Sflorian 	}
330ae8c6e27Sflorian 	return 1;
331ae8c6e27Sflorian }
332ae8c6e27Sflorian 
333d32eb43cSflorian /* RPZ format address dname to network byte order address */
334d32eb43cSflorian static int ipdnametoaddr(uint8_t* dname, size_t dnamelen,
335d32eb43cSflorian 	struct sockaddr_storage* addr, socklen_t* addrlen, int* af)
336d32eb43cSflorian {
337d32eb43cSflorian 	uint8_t* ia;
338a8eaceedSflorian 	int dnamelabs = dname_count_labels(dname);
339d32eb43cSflorian 	uint8_t lablen;
340d32eb43cSflorian 	char* e = NULL;
341d32eb43cSflorian 	int z = 0;
342d32eb43cSflorian 	size_t len = 0;
343d32eb43cSflorian 	int i;
344d32eb43cSflorian 	*af = AF_INET;
345d32eb43cSflorian 
346d32eb43cSflorian 	/* need 1 byte for label length */
347d32eb43cSflorian 	if(dnamelen < 1)
348d32eb43cSflorian 		return 0;
349d32eb43cSflorian 
350d32eb43cSflorian 	if(dnamelabs > 6 ||
351d32eb43cSflorian 		dname_has_label(dname, dnamelen, (uint8_t*)"\002zz")) {
352d32eb43cSflorian 		*af = AF_INET6;
353d32eb43cSflorian 	}
354d32eb43cSflorian 	len = *dname;
355d32eb43cSflorian 	lablen = *dname++;
356d32eb43cSflorian 	i = (*af == AF_INET) ? 3 : 15;
357d32eb43cSflorian 	if(*af == AF_INET6) {
358d32eb43cSflorian 		struct sockaddr_in6* sa = (struct sockaddr_in6*)addr;
359d32eb43cSflorian 		*addrlen = (socklen_t)sizeof(struct sockaddr_in6);
360d32eb43cSflorian 		memset(sa, 0, *addrlen);
361d32eb43cSflorian 		sa->sin6_family = AF_INET6;
362d32eb43cSflorian 		ia = (uint8_t*)&sa->sin6_addr;
363d32eb43cSflorian 	} else { /* ip4 */
364d32eb43cSflorian 		struct sockaddr_in* sa = (struct sockaddr_in*)addr;
365d32eb43cSflorian 		*addrlen = (socklen_t)sizeof(struct sockaddr_in);
366d32eb43cSflorian 		memset(sa, 0, *addrlen);
367d32eb43cSflorian 		sa->sin_family = AF_INET;
368d32eb43cSflorian 		ia = (uint8_t*)&sa->sin_addr;
369d32eb43cSflorian 	}
370d32eb43cSflorian 	while(lablen && i >= 0 && len <= dnamelen) {
371d32eb43cSflorian 		char buff[LDNS_MAX_LABELLEN+1];
372d32eb43cSflorian 		uint16_t chunk; /* big enough to not overflow on IPv6 hextet */
373d32eb43cSflorian 		if((*af == AF_INET && (lablen > 3 || dnamelabs > 6)) ||
374d32eb43cSflorian 			(*af == AF_INET6 && (lablen > 4 || dnamelabs > 10))) {
375d32eb43cSflorian 			return 0;
376d32eb43cSflorian 		}
377d32eb43cSflorian 		if(memcmp(dname, "zz", 2) == 0 && *af == AF_INET6) {
378d32eb43cSflorian 			/* Add one or more 0 labels. Address is initialised at
379d32eb43cSflorian 			 * 0, so just skip the zero part. */
380d32eb43cSflorian 			int zl = 11 - dnamelabs;
381d32eb43cSflorian 			if(z || zl < 0)
382d32eb43cSflorian 				return 0;
383d32eb43cSflorian 			z = 1;
384d32eb43cSflorian 			i -= (zl*2);
385d32eb43cSflorian 		} else {
386d32eb43cSflorian 			memcpy(buff, dname, lablen);
387d32eb43cSflorian 			buff[lablen] = '\0';
388d32eb43cSflorian 			chunk = strtol(buff, &e, (*af == AF_INET) ? 10 : 16);
389d32eb43cSflorian 			if(!e || *e != '\0' || (*af == AF_INET && chunk > 255))
390d32eb43cSflorian 				return 0;
391d32eb43cSflorian 			if(*af == AF_INET) {
392d32eb43cSflorian 				log_assert(i < 4 && i >= 0);
393d32eb43cSflorian 				ia[i] = (uint8_t)chunk;
394d32eb43cSflorian 				i--;
395d32eb43cSflorian 			} else {
396d32eb43cSflorian 				log_assert(i < 16 && i >= 1);
397d32eb43cSflorian 				/* ia in network byte order */
398d32eb43cSflorian 				ia[i-1] = (uint8_t)(chunk >> 8);
399d32eb43cSflorian 				ia[i] = (uint8_t)(chunk & 0x00FF);
400d32eb43cSflorian 				i -= 2;
401d32eb43cSflorian 			}
402d32eb43cSflorian 		}
403d32eb43cSflorian 		dname += lablen;
404d32eb43cSflorian 		lablen = *dname++;
405d32eb43cSflorian 		len += lablen;
406d32eb43cSflorian 	}
407d32eb43cSflorian 	if(i != -1)
408d32eb43cSflorian 		/* input too short */
409d32eb43cSflorian 		return 0;
410d32eb43cSflorian 	return 1;
411d32eb43cSflorian }
412d32eb43cSflorian 
413d32eb43cSflorian int netblockdnametoaddr(uint8_t* dname, size_t dnamelen,
414d32eb43cSflorian 	struct sockaddr_storage* addr, socklen_t* addrlen, int* net, int* af)
415d32eb43cSflorian {
416d32eb43cSflorian 	char buff[3 /* 3 digit netblock */ + 1];
417d32eb43cSflorian 	size_t nlablen;
418d32eb43cSflorian 	if(dnamelen < 1 || *dname > 3)
419d32eb43cSflorian 		/* netblock invalid */
420d32eb43cSflorian 		return 0;
421d32eb43cSflorian 	nlablen = *dname;
422d32eb43cSflorian 
423d32eb43cSflorian 	if(dnamelen < 1 + nlablen)
424d32eb43cSflorian 		return 0;
425d32eb43cSflorian 
426d32eb43cSflorian 	memcpy(buff, dname+1, nlablen);
427d32eb43cSflorian 	buff[nlablen] = '\0';
428d32eb43cSflorian 	*net = atoi(buff);
429d32eb43cSflorian 	if(*net == 0 && strcmp(buff, "0") != 0)
430d32eb43cSflorian 		return 0;
431d32eb43cSflorian 	dname += nlablen;
432d32eb43cSflorian 	dname++;
433d32eb43cSflorian 	if(!ipdnametoaddr(dname, dnamelen-1-nlablen, addr, addrlen, af))
434d32eb43cSflorian 		return 0;
435d32eb43cSflorian 	if((*af == AF_INET6 && *net > 128) || (*af == AF_INET && *net > 32))
436d32eb43cSflorian 		return 0;
437d32eb43cSflorian 	return 1;
438d32eb43cSflorian }
439d32eb43cSflorian 
440ae8c6e27Sflorian int authextstrtoaddr(char* str, struct sockaddr_storage* addr,
441ae8c6e27Sflorian 	socklen_t* addrlen, char** auth_name)
442ae8c6e27Sflorian {
443ae8c6e27Sflorian 	char* s;
444ae8c6e27Sflorian 	int port = UNBOUND_DNS_PORT;
445ae8c6e27Sflorian 	if((s=strchr(str, '@'))) {
446ae8c6e27Sflorian 		char buf[MAX_ADDR_STRLEN];
447ae8c6e27Sflorian 		size_t len = (size_t)(s-str);
448ae8c6e27Sflorian 		char* hash = strchr(s+1, '#');
449ae8c6e27Sflorian 		if(hash) {
450ae8c6e27Sflorian 			*auth_name = hash+1;
451ae8c6e27Sflorian 		} else {
452ae8c6e27Sflorian 			*auth_name = NULL;
453ae8c6e27Sflorian 		}
454ae8c6e27Sflorian 		if(len >= MAX_ADDR_STRLEN) {
455ae8c6e27Sflorian 			return 0;
456ae8c6e27Sflorian 		}
457ae8c6e27Sflorian 		(void)strlcpy(buf, str, sizeof(buf));
458ae8c6e27Sflorian 		buf[len] = 0;
459ae8c6e27Sflorian 		port = atoi(s+1);
460ae8c6e27Sflorian 		if(port == 0) {
461ae8c6e27Sflorian 			if(!hash && strcmp(s+1,"0")!=0)
462ae8c6e27Sflorian 				return 0;
463ae8c6e27Sflorian 			if(hash && strncmp(s+1,"0#",2)!=0)
464ae8c6e27Sflorian 				return 0;
465ae8c6e27Sflorian 		}
466ae8c6e27Sflorian 		return ipstrtoaddr(buf, port, addr, addrlen);
467ae8c6e27Sflorian 	}
468ae8c6e27Sflorian 	if((s=strchr(str, '#'))) {
469ae8c6e27Sflorian 		char buf[MAX_ADDR_STRLEN];
470ae8c6e27Sflorian 		size_t len = (size_t)(s-str);
471ae8c6e27Sflorian 		if(len >= MAX_ADDR_STRLEN) {
472ae8c6e27Sflorian 			return 0;
473ae8c6e27Sflorian 		}
474ae8c6e27Sflorian 		(void)strlcpy(buf, str, sizeof(buf));
475ae8c6e27Sflorian 		buf[len] = 0;
476ae8c6e27Sflorian 		port = UNBOUND_DNS_OVER_TLS_PORT;
477ae8c6e27Sflorian 		*auth_name = s+1;
478ae8c6e27Sflorian 		return ipstrtoaddr(buf, port, addr, addrlen);
479ae8c6e27Sflorian 	}
480ae8c6e27Sflorian 	*auth_name = NULL;
481ae8c6e27Sflorian 	return ipstrtoaddr(str, port, addr, addrlen);
482ae8c6e27Sflorian }
483ae8c6e27Sflorian 
484a1a7ba80Sflorian uint8_t* authextstrtodname(char* str, int* port, char** auth_name)
485a1a7ba80Sflorian {
486a1a7ba80Sflorian 	char* s;
487a1a7ba80Sflorian 	uint8_t* dname;
488a1a7ba80Sflorian 	size_t dname_len;
489a1a7ba80Sflorian 	*port = UNBOUND_DNS_PORT;
490a1a7ba80Sflorian 	*auth_name = NULL;
491a1a7ba80Sflorian 	if((s=strchr(str, '@'))) {
492096314feSflorian 		char buf[MAX_HOST_STRLEN];
493096314feSflorian 		size_t len = (size_t)(s-str);
494a1a7ba80Sflorian 		char* hash = strchr(s+1, '#');
495a1a7ba80Sflorian 		if(hash) {
496a1a7ba80Sflorian 			*auth_name = hash+1;
497a1a7ba80Sflorian 		} else {
498a1a7ba80Sflorian 			*auth_name = NULL;
499a1a7ba80Sflorian 		}
500096314feSflorian 		if(len >= MAX_HOST_STRLEN) {
501096314feSflorian 			return NULL;
502096314feSflorian 		}
503096314feSflorian 		(void)strlcpy(buf, str, sizeof(buf));
504096314feSflorian 		buf[len] = 0;
505a1a7ba80Sflorian 		*port = atoi(s+1);
506a1a7ba80Sflorian 		if(*port == 0) {
507a1a7ba80Sflorian 			if(!hash && strcmp(s+1,"0")!=0)
508096314feSflorian 				return NULL;
509a1a7ba80Sflorian 			if(hash && strncmp(s+1,"0#",2)!=0)
510096314feSflorian 				return NULL;
511a1a7ba80Sflorian 		}
512096314feSflorian 		dname = sldns_str2wire_dname(buf, &dname_len);
513a1a7ba80Sflorian 	} else if((s=strchr(str, '#'))) {
514096314feSflorian 		char buf[MAX_HOST_STRLEN];
515096314feSflorian 		size_t len = (size_t)(s-str);
516096314feSflorian 		if(len >= MAX_HOST_STRLEN) {
517096314feSflorian 			return NULL;
518096314feSflorian 		}
519096314feSflorian 		(void)strlcpy(buf, str, sizeof(buf));
520096314feSflorian 		buf[len] = 0;
521a1a7ba80Sflorian 		*port = UNBOUND_DNS_OVER_TLS_PORT;
522a1a7ba80Sflorian 		*auth_name = s+1;
523096314feSflorian 		dname = sldns_str2wire_dname(buf, &dname_len);
524a1a7ba80Sflorian 	} else {
525a1a7ba80Sflorian 		dname = sldns_str2wire_dname(str, &dname_len);
526a1a7ba80Sflorian 	}
527a1a7ba80Sflorian 	return dname;
528a1a7ba80Sflorian }
529a1a7ba80Sflorian 
530ae8c6e27Sflorian /** store port number into sockaddr structure */
531ae8c6e27Sflorian void
532ae8c6e27Sflorian sockaddr_store_port(struct sockaddr_storage* addr, socklen_t addrlen, int port)
533ae8c6e27Sflorian {
534ae8c6e27Sflorian 	if(addr_is_ip6(addr, addrlen)) {
535ae8c6e27Sflorian 		struct sockaddr_in6* sa = (struct sockaddr_in6*)addr;
536ae8c6e27Sflorian 		sa->sin6_port = (in_port_t)htons((uint16_t)port);
537ae8c6e27Sflorian 	} else {
538ae8c6e27Sflorian 		struct sockaddr_in* sa = (struct sockaddr_in*)addr;
539ae8c6e27Sflorian 		sa->sin_port = (in_port_t)htons((uint16_t)port);
540ae8c6e27Sflorian 	}
541ae8c6e27Sflorian }
542ae8c6e27Sflorian 
543ae8c6e27Sflorian void
544ae8c6e27Sflorian log_nametypeclass(enum verbosity_value v, const char* str, uint8_t* name,
545ae8c6e27Sflorian 	uint16_t type, uint16_t dclass)
546ae8c6e27Sflorian {
547ae8c6e27Sflorian 	char buf[LDNS_MAX_DOMAINLEN+1];
548ae8c6e27Sflorian 	char t[12], c[12];
549ae8c6e27Sflorian 	const char *ts, *cs;
550ae8c6e27Sflorian 	if(verbosity < v)
551ae8c6e27Sflorian 		return;
552ae8c6e27Sflorian 	dname_str(name, buf);
553ae8c6e27Sflorian 	if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG";
554ae8c6e27Sflorian 	else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR";
555ae8c6e27Sflorian 	else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR";
556ae8c6e27Sflorian 	else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB";
557ae8c6e27Sflorian 	else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA";
558ae8c6e27Sflorian 	else if(type == LDNS_RR_TYPE_ANY) ts = "ANY";
559ae8c6e27Sflorian 	else if(sldns_rr_descript(type) && sldns_rr_descript(type)->_name)
560ae8c6e27Sflorian 		ts = sldns_rr_descript(type)->_name;
561ae8c6e27Sflorian 	else {
562ae8c6e27Sflorian 		snprintf(t, sizeof(t), "TYPE%d", (int)type);
563ae8c6e27Sflorian 		ts = t;
564ae8c6e27Sflorian 	}
565ae8c6e27Sflorian 	if(sldns_lookup_by_id(sldns_rr_classes, (int)dclass) &&
566ae8c6e27Sflorian 		sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name)
567ae8c6e27Sflorian 		cs = sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name;
568ae8c6e27Sflorian 	else {
569ae8c6e27Sflorian 		snprintf(c, sizeof(c), "CLASS%d", (int)dclass);
570ae8c6e27Sflorian 		cs = c;
571ae8c6e27Sflorian 	}
572ae8c6e27Sflorian 	log_info("%s %s %s %s", str, buf, ts, cs);
573ae8c6e27Sflorian }
574ae8c6e27Sflorian 
575e97c6e54Ssthen void
576e97c6e54Ssthen log_query_in(const char* str, uint8_t* name, uint16_t type, uint16_t dclass)
577e97c6e54Ssthen {
578e97c6e54Ssthen 	char buf[LDNS_MAX_DOMAINLEN+1];
579e97c6e54Ssthen 	char t[12], c[12];
580e97c6e54Ssthen 	const char *ts, *cs;
581e97c6e54Ssthen 	dname_str(name, buf);
582e97c6e54Ssthen 	if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG";
583e97c6e54Ssthen 	else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR";
584e97c6e54Ssthen 	else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR";
585e97c6e54Ssthen 	else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB";
586e97c6e54Ssthen 	else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA";
587e97c6e54Ssthen 	else if(type == LDNS_RR_TYPE_ANY) ts = "ANY";
588e97c6e54Ssthen 	else if(sldns_rr_descript(type) && sldns_rr_descript(type)->_name)
589e97c6e54Ssthen 		ts = sldns_rr_descript(type)->_name;
590e97c6e54Ssthen 	else {
591e97c6e54Ssthen 		snprintf(t, sizeof(t), "TYPE%d", (int)type);
592e97c6e54Ssthen 		ts = t;
593e97c6e54Ssthen 	}
594e97c6e54Ssthen 	if(sldns_lookup_by_id(sldns_rr_classes, (int)dclass) &&
595e97c6e54Ssthen 		sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name)
596e97c6e54Ssthen 		cs = sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name;
597e97c6e54Ssthen 	else {
598e97c6e54Ssthen 		snprintf(c, sizeof(c), "CLASS%d", (int)dclass);
599e97c6e54Ssthen 		cs = c;
600e97c6e54Ssthen 	}
601e97c6e54Ssthen 	if(LOG_TAG_QUERYREPLY)
602e97c6e54Ssthen 		log_query("%s %s %s %s", str, buf, ts, cs);
603e97c6e54Ssthen 	else	log_info("%s %s %s %s", str, buf, ts, cs);
604e97c6e54Ssthen }
605e97c6e54Ssthen 
606ae8c6e27Sflorian void log_name_addr(enum verbosity_value v, const char* str, uint8_t* zone,
607ae8c6e27Sflorian 	struct sockaddr_storage* addr, socklen_t addrlen)
608ae8c6e27Sflorian {
609ae8c6e27Sflorian 	uint16_t port;
610ae8c6e27Sflorian 	const char* family = "unknown_family ";
611ae8c6e27Sflorian 	char namebuf[LDNS_MAX_DOMAINLEN+1];
612ae8c6e27Sflorian 	char dest[100];
613ae8c6e27Sflorian 	int af = (int)((struct sockaddr_in*)addr)->sin_family;
614ae8c6e27Sflorian 	void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
615ae8c6e27Sflorian 	if(verbosity < v)
616ae8c6e27Sflorian 		return;
617ae8c6e27Sflorian 	switch(af) {
618ae8c6e27Sflorian 		case AF_INET: family=""; break;
619ae8c6e27Sflorian 		case AF_INET6: family="";
620ae8c6e27Sflorian 			sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
621ae8c6e27Sflorian 			break;
622ae8c6e27Sflorian 		case AF_LOCAL: family="local "; break;
623ae8c6e27Sflorian 		default: break;
624ae8c6e27Sflorian 	}
625ae8c6e27Sflorian 	if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
626ae8c6e27Sflorian 		(void)strlcpy(dest, "(inet_ntop error)", sizeof(dest));
627ae8c6e27Sflorian 	}
628ae8c6e27Sflorian 	dest[sizeof(dest)-1] = 0;
629ae8c6e27Sflorian 	port = ntohs(((struct sockaddr_in*)addr)->sin_port);
630ae8c6e27Sflorian 	dname_str(zone, namebuf);
631ae8c6e27Sflorian 	if(af != AF_INET && af != AF_INET6)
632ae8c6e27Sflorian 		verbose(v, "%s <%s> %s%s#%d (addrlen %d)",
633ae8c6e27Sflorian 			str, namebuf, family, dest, (int)port, (int)addrlen);
634ae8c6e27Sflorian 	else	verbose(v, "%s <%s> %s%s#%d",
635ae8c6e27Sflorian 			str, namebuf, family, dest, (int)port);
636ae8c6e27Sflorian }
637ae8c6e27Sflorian 
638ae8c6e27Sflorian void log_err_addr(const char* str, const char* err,
639ae8c6e27Sflorian 	struct sockaddr_storage* addr, socklen_t addrlen)
640ae8c6e27Sflorian {
641ae8c6e27Sflorian 	uint16_t port;
642ae8c6e27Sflorian 	char dest[100];
643ae8c6e27Sflorian 	int af = (int)((struct sockaddr_in*)addr)->sin_family;
644ae8c6e27Sflorian 	void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
645ae8c6e27Sflorian 	if(af == AF_INET6)
646ae8c6e27Sflorian 		sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
647ae8c6e27Sflorian 	if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
648ae8c6e27Sflorian 		(void)strlcpy(dest, "(inet_ntop error)", sizeof(dest));
649ae8c6e27Sflorian 	}
650ae8c6e27Sflorian 	dest[sizeof(dest)-1] = 0;
651ae8c6e27Sflorian 	port = ntohs(((struct sockaddr_in*)addr)->sin_port);
652ae8c6e27Sflorian 	if(verbosity >= 4)
653ae8c6e27Sflorian 		log_err("%s: %s for %s port %d (len %d)", str, err, dest,
654ae8c6e27Sflorian 			(int)port, (int)addrlen);
655ae8c6e27Sflorian 	else	log_err("%s: %s for %s port %d", str, err, dest, (int)port);
656ae8c6e27Sflorian }
657ae8c6e27Sflorian 
658ae8c6e27Sflorian int
659ae8c6e27Sflorian sockaddr_cmp(struct sockaddr_storage* addr1, socklen_t len1,
660ae8c6e27Sflorian 	struct sockaddr_storage* addr2, socklen_t len2)
661ae8c6e27Sflorian {
662ae8c6e27Sflorian 	struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1;
663ae8c6e27Sflorian 	struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2;
664ae8c6e27Sflorian 	struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1;
665ae8c6e27Sflorian 	struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2;
666ae8c6e27Sflorian 	if(len1 < len2)
667ae8c6e27Sflorian 		return -1;
668ae8c6e27Sflorian 	if(len1 > len2)
669ae8c6e27Sflorian 		return 1;
670ae8c6e27Sflorian 	log_assert(len1 == len2);
671ae8c6e27Sflorian 	if( p1_in->sin_family < p2_in->sin_family)
672ae8c6e27Sflorian 		return -1;
673ae8c6e27Sflorian 	if( p1_in->sin_family > p2_in->sin_family)
674ae8c6e27Sflorian 		return 1;
675ae8c6e27Sflorian 	log_assert( p1_in->sin_family == p2_in->sin_family );
676ae8c6e27Sflorian 	/* compare ip4 */
677ae8c6e27Sflorian 	if( p1_in->sin_family == AF_INET ) {
678ae8c6e27Sflorian 		/* just order it, ntohs not required */
679ae8c6e27Sflorian 		if(p1_in->sin_port < p2_in->sin_port)
680ae8c6e27Sflorian 			return -1;
681ae8c6e27Sflorian 		if(p1_in->sin_port > p2_in->sin_port)
682ae8c6e27Sflorian 			return 1;
683ae8c6e27Sflorian 		log_assert(p1_in->sin_port == p2_in->sin_port);
684ae8c6e27Sflorian 		return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE);
685ae8c6e27Sflorian 	} else if (p1_in6->sin6_family == AF_INET6) {
686ae8c6e27Sflorian 		/* just order it, ntohs not required */
687ae8c6e27Sflorian 		if(p1_in6->sin6_port < p2_in6->sin6_port)
688ae8c6e27Sflorian 			return -1;
689ae8c6e27Sflorian 		if(p1_in6->sin6_port > p2_in6->sin6_port)
690ae8c6e27Sflorian 			return 1;
691ae8c6e27Sflorian 		log_assert(p1_in6->sin6_port == p2_in6->sin6_port);
692ae8c6e27Sflorian 		return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr,
693ae8c6e27Sflorian 			INET6_SIZE);
694ae8c6e27Sflorian 	} else {
695ae8c6e27Sflorian 		/* eek unknown type, perform this comparison for sanity. */
696ae8c6e27Sflorian 		return memcmp(addr1, addr2, len1);
697ae8c6e27Sflorian 	}
698ae8c6e27Sflorian }
699ae8c6e27Sflorian 
700ae8c6e27Sflorian int
701ae8c6e27Sflorian sockaddr_cmp_addr(struct sockaddr_storage* addr1, socklen_t len1,
702ae8c6e27Sflorian 	struct sockaddr_storage* addr2, socklen_t len2)
703ae8c6e27Sflorian {
704ae8c6e27Sflorian 	struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1;
705ae8c6e27Sflorian 	struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2;
706ae8c6e27Sflorian 	struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1;
707ae8c6e27Sflorian 	struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2;
708ae8c6e27Sflorian 	if(len1 < len2)
709ae8c6e27Sflorian 		return -1;
710ae8c6e27Sflorian 	if(len1 > len2)
711ae8c6e27Sflorian 		return 1;
712ae8c6e27Sflorian 	log_assert(len1 == len2);
713ae8c6e27Sflorian 	if( p1_in->sin_family < p2_in->sin_family)
714ae8c6e27Sflorian 		return -1;
715ae8c6e27Sflorian 	if( p1_in->sin_family > p2_in->sin_family)
716ae8c6e27Sflorian 		return 1;
717ae8c6e27Sflorian 	log_assert( p1_in->sin_family == p2_in->sin_family );
718ae8c6e27Sflorian 	/* compare ip4 */
719ae8c6e27Sflorian 	if( p1_in->sin_family == AF_INET ) {
720ae8c6e27Sflorian 		return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE);
721ae8c6e27Sflorian 	} else if (p1_in6->sin6_family == AF_INET6) {
722ae8c6e27Sflorian 		return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr,
723ae8c6e27Sflorian 			INET6_SIZE);
724ae8c6e27Sflorian 	} else {
725ae8c6e27Sflorian 		/* eek unknown type, perform this comparison for sanity. */
726ae8c6e27Sflorian 		return memcmp(addr1, addr2, len1);
727ae8c6e27Sflorian 	}
728ae8c6e27Sflorian }
729ae8c6e27Sflorian 
730ae8c6e27Sflorian int
731ae8c6e27Sflorian addr_is_ip6(struct sockaddr_storage* addr, socklen_t len)
732ae8c6e27Sflorian {
733ae8c6e27Sflorian 	if(len == (socklen_t)sizeof(struct sockaddr_in6) &&
734ae8c6e27Sflorian 		((struct sockaddr_in6*)addr)->sin6_family == AF_INET6)
735ae8c6e27Sflorian 		return 1;
736ae8c6e27Sflorian 	else    return 0;
737ae8c6e27Sflorian }
738ae8c6e27Sflorian 
739ae8c6e27Sflorian void
740ae8c6e27Sflorian addr_mask(struct sockaddr_storage* addr, socklen_t len, int net)
741ae8c6e27Sflorian {
742ae8c6e27Sflorian 	uint8_t mask[8] = {0x0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe};
743ae8c6e27Sflorian 	int i, max;
744ae8c6e27Sflorian 	uint8_t* s;
745ae8c6e27Sflorian 	if(addr_is_ip6(addr, len)) {
746ae8c6e27Sflorian 		s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr;
747ae8c6e27Sflorian 		max = 128;
748ae8c6e27Sflorian 	} else {
749ae8c6e27Sflorian 		s = (uint8_t*)&((struct sockaddr_in*)addr)->sin_addr;
750ae8c6e27Sflorian 		max = 32;
751ae8c6e27Sflorian 	}
752ae8c6e27Sflorian 	if(net >= max)
753ae8c6e27Sflorian 		return;
754ae8c6e27Sflorian 	for(i=net/8+1; i<max/8; i++) {
755ae8c6e27Sflorian 		s[i] = 0;
756ae8c6e27Sflorian 	}
757ae8c6e27Sflorian 	s[net/8] &= mask[net&0x7];
758ae8c6e27Sflorian }
759ae8c6e27Sflorian 
760ae8c6e27Sflorian int
761ae8c6e27Sflorian addr_in_common(struct sockaddr_storage* addr1, int net1,
762ae8c6e27Sflorian 	struct sockaddr_storage* addr2, int net2, socklen_t addrlen)
763ae8c6e27Sflorian {
764ae8c6e27Sflorian 	int min = (net1<net2)?net1:net2;
765ae8c6e27Sflorian 	int i, to;
766ae8c6e27Sflorian 	int match = 0;
767ae8c6e27Sflorian 	uint8_t* s1, *s2;
768ae8c6e27Sflorian 	if(addr_is_ip6(addr1, addrlen)) {
769ae8c6e27Sflorian 		s1 = (uint8_t*)&((struct sockaddr_in6*)addr1)->sin6_addr;
770ae8c6e27Sflorian 		s2 = (uint8_t*)&((struct sockaddr_in6*)addr2)->sin6_addr;
771ae8c6e27Sflorian 		to = 16;
772ae8c6e27Sflorian 	} else {
773ae8c6e27Sflorian 		s1 = (uint8_t*)&((struct sockaddr_in*)addr1)->sin_addr;
774ae8c6e27Sflorian 		s2 = (uint8_t*)&((struct sockaddr_in*)addr2)->sin_addr;
775ae8c6e27Sflorian 		to = 4;
776ae8c6e27Sflorian 	}
777ae8c6e27Sflorian 	/* match = bits_in_common(s1, s2, to); */
778ae8c6e27Sflorian 	for(i=0; i<to; i++) {
779ae8c6e27Sflorian 		if(s1[i] == s2[i]) {
780ae8c6e27Sflorian 			match += 8;
781ae8c6e27Sflorian 		} else {
782ae8c6e27Sflorian 			uint8_t z = s1[i]^s2[i];
783ae8c6e27Sflorian 			log_assert(z);
784ae8c6e27Sflorian 			while(!(z&0x80)) {
785ae8c6e27Sflorian 				match++;
786ae8c6e27Sflorian 				z<<=1;
787ae8c6e27Sflorian 			}
788ae8c6e27Sflorian 			break;
789ae8c6e27Sflorian 		}
790ae8c6e27Sflorian 	}
791ae8c6e27Sflorian 	if(match > min) match = min;
792ae8c6e27Sflorian 	return match;
793ae8c6e27Sflorian }
794ae8c6e27Sflorian 
795ae8c6e27Sflorian void
796ae8c6e27Sflorian addr_to_str(struct sockaddr_storage* addr, socklen_t addrlen,
797ae8c6e27Sflorian 	char* buf, size_t len)
798ae8c6e27Sflorian {
799ae8c6e27Sflorian 	int af = (int)((struct sockaddr_in*)addr)->sin_family;
800ae8c6e27Sflorian 	void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
801ae8c6e27Sflorian 	if(addr_is_ip6(addr, addrlen))
802ae8c6e27Sflorian 		sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
803ae8c6e27Sflorian 	if(inet_ntop(af, sinaddr, buf, (socklen_t)len) == 0) {
804ae8c6e27Sflorian 		snprintf(buf, len, "(inet_ntop_error)");
805ae8c6e27Sflorian 	}
806ae8c6e27Sflorian }
807ae8c6e27Sflorian 
808ae8c6e27Sflorian int
809d500c338Sflorian prefixnet_is_nat64(int prefixnet)
810d500c338Sflorian {
811d500c338Sflorian 	return (prefixnet == 32 || prefixnet == 40 ||
812d500c338Sflorian 		prefixnet == 48 || prefixnet == 56 ||
813d500c338Sflorian 		prefixnet == 64 || prefixnet == 96);
814d500c338Sflorian }
815d500c338Sflorian 
816d500c338Sflorian void
817d500c338Sflorian addr_to_nat64(const struct sockaddr_storage* addr,
818d500c338Sflorian 	const struct sockaddr_storage* nat64_prefix,
819d500c338Sflorian 	socklen_t nat64_prefixlen, int nat64_prefixnet,
820d500c338Sflorian 	struct sockaddr_storage* nat64_addr, socklen_t* nat64_addrlen)
821d500c338Sflorian {
822d500c338Sflorian 	struct sockaddr_in *sin = (struct sockaddr_in *)addr;
823d500c338Sflorian 	struct sockaddr_in6 *sin6;
824d500c338Sflorian 	uint8_t *v4_byte;
825fc357d0dSderaadt 	int i;
826d500c338Sflorian 
827d500c338Sflorian 	/* This needs to be checked by the caller */
828d500c338Sflorian 	log_assert(addr->ss_family == AF_INET);
829d500c338Sflorian 	/* Current usage is only from config values; prefix lengths enforced
830d500c338Sflorian 	 * during config validation */
831d500c338Sflorian 	log_assert(prefixnet_is_nat64(nat64_prefixnet));
832d500c338Sflorian 
833d500c338Sflorian 	*nat64_addr = *nat64_prefix;
834d500c338Sflorian 	*nat64_addrlen = nat64_prefixlen;
835d500c338Sflorian 
836d500c338Sflorian 	sin6 = (struct sockaddr_in6 *)nat64_addr;
837d500c338Sflorian 	sin6->sin6_flowinfo = 0;
838d500c338Sflorian 	sin6->sin6_port = sin->sin_port;
839d500c338Sflorian 
840d500c338Sflorian 	nat64_prefixnet = nat64_prefixnet / 8;
841d500c338Sflorian 
842d500c338Sflorian 	v4_byte = (uint8_t *)&sin->sin_addr.s_addr;
843fc357d0dSderaadt 	for(i = 0; i < 4; i++) {
844d500c338Sflorian 		if(nat64_prefixnet == 8) {
845d500c338Sflorian 			/* bits 64...71 are MBZ */
846d500c338Sflorian 			sin6->sin6_addr.s6_addr[nat64_prefixnet++] = 0;
847d500c338Sflorian 		}
848d500c338Sflorian 		sin6->sin6_addr.s6_addr[nat64_prefixnet++] = *v4_byte++;
849d500c338Sflorian 	}
850d500c338Sflorian }
851d500c338Sflorian 
852d500c338Sflorian int
853ae8c6e27Sflorian addr_is_ip4mapped(struct sockaddr_storage* addr, socklen_t addrlen)
854ae8c6e27Sflorian {
855ae8c6e27Sflorian 	/* prefix for ipv4 into ipv6 mapping is ::ffff:x.x.x.x */
856ae8c6e27Sflorian 	const uint8_t map_prefix[16] =
857ae8c6e27Sflorian 		{0,0,0,0,  0,0,0,0, 0,0,0xff,0xff, 0,0,0,0};
858ae8c6e27Sflorian 	uint8_t* s;
859ae8c6e27Sflorian 	if(!addr_is_ip6(addr, addrlen))
860ae8c6e27Sflorian 		return 0;
861ae8c6e27Sflorian 	/* s is 16 octet ipv6 address string */
862ae8c6e27Sflorian 	s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr;
863ae8c6e27Sflorian 	return (memcmp(s, map_prefix, 12) == 0);
864ae8c6e27Sflorian }
865ae8c6e27Sflorian 
866*7037e34cSflorian int addr_is_ip6linklocal(struct sockaddr_storage* addr, socklen_t addrlen)
867*7037e34cSflorian {
868*7037e34cSflorian 	const uint8_t prefix[2] = {0xfe, 0x80};
869*7037e34cSflorian 	int af = (int)((struct sockaddr_in6*)addr)->sin6_family;
870*7037e34cSflorian 	void* sin6addr = &((struct sockaddr_in6*)addr)->sin6_addr;
871*7037e34cSflorian 	uint8_t start[2];
872*7037e34cSflorian 	if(af != AF_INET6 || addrlen<(socklen_t)sizeof(struct sockaddr_in6))
873*7037e34cSflorian 		return 0;
874*7037e34cSflorian 	/* Put the first 10 bits of sin6addr in start, match fe80::/10. */
875*7037e34cSflorian 	memmove(start, sin6addr, 2);
876*7037e34cSflorian 	start[1] &= 0xc0;
877*7037e34cSflorian 	return memcmp(start, prefix, 2) == 0;
878*7037e34cSflorian }
879*7037e34cSflorian 
880ae8c6e27Sflorian int addr_is_broadcast(struct sockaddr_storage* addr, socklen_t addrlen)
881ae8c6e27Sflorian {
882ae8c6e27Sflorian 	int af = (int)((struct sockaddr_in*)addr)->sin_family;
883ae8c6e27Sflorian 	void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
884ae8c6e27Sflorian 	return af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in)
885ae8c6e27Sflorian 		&& memcmp(sinaddr, "\377\377\377\377", 4) == 0;
886ae8c6e27Sflorian }
887ae8c6e27Sflorian 
888ae8c6e27Sflorian int addr_is_any(struct sockaddr_storage* addr, socklen_t addrlen)
889ae8c6e27Sflorian {
890ae8c6e27Sflorian 	int af = (int)((struct sockaddr_in*)addr)->sin_family;
891ae8c6e27Sflorian 	void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
892ae8c6e27Sflorian 	void* sin6addr = &((struct sockaddr_in6*)addr)->sin6_addr;
893ae8c6e27Sflorian 	if(af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in)
894ae8c6e27Sflorian 		&& memcmp(sinaddr, "\000\000\000\000", 4) == 0)
895ae8c6e27Sflorian 		return 1;
896ae8c6e27Sflorian 	else if(af==AF_INET6 && addrlen>=(socklen_t)sizeof(struct sockaddr_in6)
897ae8c6e27Sflorian 		&& memcmp(sin6addr, "\000\000\000\000\000\000\000\000"
898ae8c6e27Sflorian 		"\000\000\000\000\000\000\000\000", 16) == 0)
899ae8c6e27Sflorian 		return 1;
900ae8c6e27Sflorian 	return 0;
901ae8c6e27Sflorian }
902ae8c6e27Sflorian 
903ae8c6e27Sflorian void sock_list_insert(struct sock_list** list, struct sockaddr_storage* addr,
904ae8c6e27Sflorian 	socklen_t len, struct regional* region)
905ae8c6e27Sflorian {
906ae8c6e27Sflorian 	struct sock_list* add = (struct sock_list*)regional_alloc(region,
907ae8c6e27Sflorian 		sizeof(*add) - sizeof(add->addr) + (size_t)len);
908ae8c6e27Sflorian 	if(!add) {
909ae8c6e27Sflorian 		log_err("out of memory in socketlist insert");
910ae8c6e27Sflorian 		return;
911ae8c6e27Sflorian 	}
912ae8c6e27Sflorian 	log_assert(list);
913ae8c6e27Sflorian 	add->next = *list;
914ae8c6e27Sflorian 	add->len = len;
915ae8c6e27Sflorian 	*list = add;
916ae8c6e27Sflorian 	if(len) memmove(&add->addr, addr, len);
917ae8c6e27Sflorian }
918ae8c6e27Sflorian 
919ae8c6e27Sflorian void sock_list_prepend(struct sock_list** list, struct sock_list* add)
920ae8c6e27Sflorian {
921ae8c6e27Sflorian 	struct sock_list* last = add;
922ae8c6e27Sflorian 	if(!last)
923ae8c6e27Sflorian 		return;
924ae8c6e27Sflorian 	while(last->next)
925ae8c6e27Sflorian 		last = last->next;
926ae8c6e27Sflorian 	last->next = *list;
927ae8c6e27Sflorian 	*list = add;
928ae8c6e27Sflorian }
929ae8c6e27Sflorian 
930ae8c6e27Sflorian int sock_list_find(struct sock_list* list, struct sockaddr_storage* addr,
931ae8c6e27Sflorian         socklen_t len)
932ae8c6e27Sflorian {
933ae8c6e27Sflorian 	while(list) {
934ae8c6e27Sflorian 		if(len == list->len) {
935ae8c6e27Sflorian 			if(len == 0 || sockaddr_cmp_addr(addr, len,
936ae8c6e27Sflorian 				&list->addr, list->len) == 0)
937ae8c6e27Sflorian 				return 1;
938ae8c6e27Sflorian 		}
939ae8c6e27Sflorian 		list = list->next;
940ae8c6e27Sflorian 	}
941ae8c6e27Sflorian 	return 0;
942ae8c6e27Sflorian }
943ae8c6e27Sflorian 
944ae8c6e27Sflorian void sock_list_merge(struct sock_list** list, struct regional* region,
945ae8c6e27Sflorian 	struct sock_list* add)
946ae8c6e27Sflorian {
947ae8c6e27Sflorian 	struct sock_list* p;
948ae8c6e27Sflorian 	for(p=add; p; p=p->next) {
949ae8c6e27Sflorian 		if(!sock_list_find(*list, &p->addr, p->len))
950ae8c6e27Sflorian 			sock_list_insert(list, &p->addr, p->len, region);
951ae8c6e27Sflorian 	}
952ae8c6e27Sflorian }
953ae8c6e27Sflorian 
954ae8c6e27Sflorian void
955ae8c6e27Sflorian log_crypto_err(const char* str)
956ae8c6e27Sflorian {
957ae8c6e27Sflorian #ifdef HAVE_SSL
95857403691Sflorian 	log_crypto_err_code(str, ERR_get_error());
95957403691Sflorian #else
96057403691Sflorian 	(void)str;
96157403691Sflorian #endif /* HAVE_SSL */
96257403691Sflorian }
96357403691Sflorian 
96457403691Sflorian void log_crypto_err_code(const char* str, unsigned long err)
96557403691Sflorian {
96657403691Sflorian #ifdef HAVE_SSL
967ae8c6e27Sflorian 	/* error:[error code]:[library name]:[function name]:[reason string] */
968ae8c6e27Sflorian 	char buf[128];
969ae8c6e27Sflorian 	unsigned long e;
97057403691Sflorian 	ERR_error_string_n(err, buf, sizeof(buf));
971ae8c6e27Sflorian 	log_err("%s crypto %s", str, buf);
972ae8c6e27Sflorian 	while( (e=ERR_get_error()) ) {
973ae8c6e27Sflorian 		ERR_error_string_n(e, buf, sizeof(buf));
974ae8c6e27Sflorian 		log_err("and additionally crypto %s", buf);
975ae8c6e27Sflorian 	}
976ae8c6e27Sflorian #else
977ae8c6e27Sflorian 	(void)str;
97857403691Sflorian 	(void)err;
979ae8c6e27Sflorian #endif /* HAVE_SSL */
980ae8c6e27Sflorian }
981ae8c6e27Sflorian 
982e47fef9eSflorian #ifdef HAVE_SSL
98354cc57acSflorian /** Print crypt erro with SSL_get_error want code and err_get_error code */
98454cc57acSflorian static void log_crypto_err_io_code_arg(const char* str, int r,
98554cc57acSflorian 	unsigned long err, int err_present)
98654cc57acSflorian {
98754cc57acSflorian 	int print_errno = 0, print_crypto_err = 0;
98854cc57acSflorian 	const char* inf = NULL;
98954cc57acSflorian 
99054cc57acSflorian 	switch(r) {
99154cc57acSflorian 	case SSL_ERROR_NONE:
99254cc57acSflorian 		inf = "no error";
99354cc57acSflorian 		break;
99454cc57acSflorian 	case SSL_ERROR_ZERO_RETURN:
99554cc57acSflorian 		inf = "channel closed";
99654cc57acSflorian 		break;
99754cc57acSflorian 	case SSL_ERROR_WANT_READ:
99854cc57acSflorian 		inf = "want read";
99954cc57acSflorian 		break;
100054cc57acSflorian 	case SSL_ERROR_WANT_WRITE:
100154cc57acSflorian 		inf = "want write";
100254cc57acSflorian 		break;
100354cc57acSflorian 	case SSL_ERROR_WANT_CONNECT:
100454cc57acSflorian 		inf = "want connect";
100554cc57acSflorian 		break;
100654cc57acSflorian 	case SSL_ERROR_WANT_ACCEPT:
100754cc57acSflorian 		inf = "want accept";
100854cc57acSflorian 		break;
100954cc57acSflorian 	case SSL_ERROR_WANT_X509_LOOKUP:
101054cc57acSflorian 		inf = "want X509 lookup";
101154cc57acSflorian 		break;
101254cc57acSflorian #ifdef SSL_ERROR_WANT_ASYNC
101354cc57acSflorian 	case SSL_ERROR_WANT_ASYNC:
101454cc57acSflorian 		inf = "want async";
101554cc57acSflorian 		break;
101654cc57acSflorian #endif
101754cc57acSflorian #ifdef SSL_ERROR_WANT_ASYNC_JOB
101854cc57acSflorian 	case SSL_ERROR_WANT_ASYNC_JOB:
101954cc57acSflorian 		inf = "want async job";
102054cc57acSflorian 		break;
102154cc57acSflorian #endif
102254cc57acSflorian #ifdef SSL_ERROR_WANT_CLIENT_HELLO_CB
102354cc57acSflorian 	case SSL_ERROR_WANT_CLIENT_HELLO_CB:
102454cc57acSflorian 		inf = "want client hello cb";
102554cc57acSflorian 		break;
102654cc57acSflorian #endif
102754cc57acSflorian 	case SSL_ERROR_SYSCALL:
102854cc57acSflorian 		print_errno = 1;
102954cc57acSflorian 		inf = "syscall";
103054cc57acSflorian 		break;
103154cc57acSflorian 	case SSL_ERROR_SSL:
103254cc57acSflorian 		print_crypto_err = 1;
103354cc57acSflorian 		inf = "SSL, usually protocol, error";
103454cc57acSflorian 		break;
103554cc57acSflorian 	default:
103654cc57acSflorian 		inf = "unknown SSL_get_error result code";
103754cc57acSflorian 		print_errno = 1;
103854cc57acSflorian 		print_crypto_err = 1;
103954cc57acSflorian 	}
104054cc57acSflorian 	if(print_crypto_err) {
104154cc57acSflorian 		if(print_errno) {
104254cc57acSflorian 			char buf[1024];
104354cc57acSflorian 			snprintf(buf, sizeof(buf), "%s with errno %s",
104454cc57acSflorian 				str, strerror(errno));
104554cc57acSflorian 			if(err_present)
104654cc57acSflorian 				log_crypto_err_code(buf, err);
104754cc57acSflorian 			else	log_crypto_err(buf);
104854cc57acSflorian 		} else {
104954cc57acSflorian 			if(err_present)
105054cc57acSflorian 				log_crypto_err_code(str, err);
105154cc57acSflorian 			else	log_crypto_err(str);
105254cc57acSflorian 		}
105354cc57acSflorian 	} else {
105454cc57acSflorian 		if(print_errno) {
105554cc57acSflorian 			if(errno == 0)
1056096314feSflorian 				log_err("%s: syscall error with errno %s",
1057096314feSflorian 					str, strerror(errno));
1058096314feSflorian 			else log_err("%s: %s", str, strerror(errno));
105954cc57acSflorian 		} else {
1060096314feSflorian 			log_err("%s: %s", str, inf);
106154cc57acSflorian 		}
106254cc57acSflorian 	}
106354cc57acSflorian }
106454cc57acSflorian #endif /* HAVE_SSL */
106554cc57acSflorian 
106654cc57acSflorian void log_crypto_err_io(const char* str, int r)
106754cc57acSflorian {
106854cc57acSflorian #ifdef HAVE_SSL
106954cc57acSflorian 	log_crypto_err_io_code_arg(str, r, 0, 0);
107054cc57acSflorian #else
107154cc57acSflorian 	(void)str;
107254cc57acSflorian 	(void)r;
107354cc57acSflorian #endif /* HAVE_SSL */
107454cc57acSflorian }
107554cc57acSflorian 
107654cc57acSflorian void log_crypto_err_io_code(const char* str, int r, unsigned long err)
107754cc57acSflorian {
107854cc57acSflorian #ifdef HAVE_SSL
107954cc57acSflorian 	log_crypto_err_io_code_arg(str, r, err, 1);
108054cc57acSflorian #else
108154cc57acSflorian 	(void)str;
108254cc57acSflorian 	(void)r;
108354cc57acSflorian 	(void)err;
108454cc57acSflorian #endif /* HAVE_SSL */
108554cc57acSflorian }
108654cc57acSflorian 
108754cc57acSflorian #ifdef HAVE_SSL
1088e47fef9eSflorian /** log certificate details */
1089e47fef9eSflorian void
1090e47fef9eSflorian log_cert(unsigned level, const char* str, void* cert)
1091e47fef9eSflorian {
1092e47fef9eSflorian 	BIO* bio;
1093e47fef9eSflorian 	char nul = 0;
1094e47fef9eSflorian 	char* pp = NULL;
1095e47fef9eSflorian 	long len;
1096e47fef9eSflorian 	if(verbosity < level) return;
1097e47fef9eSflorian 	bio = BIO_new(BIO_s_mem());
1098e47fef9eSflorian 	if(!bio) return;
1099e47fef9eSflorian 	X509_print_ex(bio, (X509*)cert, 0, (unsigned long)-1
1100e47fef9eSflorian 		^(X509_FLAG_NO_SUBJECT
1101e47fef9eSflorian                         |X509_FLAG_NO_ISSUER|X509_FLAG_NO_VALIDITY
1102e47fef9eSflorian 			|X509_FLAG_NO_EXTENSIONS|X509_FLAG_NO_AUX
1103e47fef9eSflorian 			|X509_FLAG_NO_ATTRIBUTES));
1104e47fef9eSflorian 	BIO_write(bio, &nul, (int)sizeof(nul));
1105e47fef9eSflorian 	len = BIO_get_mem_data(bio, &pp);
1106e47fef9eSflorian 	if(len != 0 && pp) {
1107a1a7ba80Sflorian 		/* reduce size of cert printout */
1108a1a7ba80Sflorian 		char* s;
1109a1a7ba80Sflorian 		while((s=strstr(pp, "  "))!=NULL)
1110a1a7ba80Sflorian 			memmove(s, s+1, strlen(s+1)+1);
1111a1a7ba80Sflorian 		while((s=strstr(pp, "\t\t"))!=NULL)
1112a1a7ba80Sflorian 			memmove(s, s+1, strlen(s+1)+1);
1113e47fef9eSflorian 		verbose(level, "%s: \n%s", str, pp);
1114e47fef9eSflorian 	}
1115e47fef9eSflorian 	BIO_free(bio);
1116e47fef9eSflorian }
1117e47fef9eSflorian #endif /* HAVE_SSL */
1118e47fef9eSflorian 
1119411c5950Sflorian #if defined(HAVE_SSL) && defined(HAVE_NGHTTP2) && defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB)
1120f4f0f0ceSflorian static int alpn_select_cb(SSL* ATTR_UNUSED(ssl), const unsigned char** out,
1121f4f0f0ceSflorian 	unsigned char* outlen, const unsigned char* in, unsigned int inlen,
1122f4f0f0ceSflorian 	void* ATTR_UNUSED(arg))
1123f4f0f0ceSflorian {
1124f4f0f0ceSflorian 	int rv = nghttp2_select_next_protocol((unsigned char **)out, outlen, in,
1125f4f0f0ceSflorian 		inlen);
1126f4f0f0ceSflorian 	if(rv == -1) {
1127f4f0f0ceSflorian 		return SSL_TLSEXT_ERR_NOACK;
1128f4f0f0ceSflorian 	}
1129f4f0f0ceSflorian 	/* either http/1.1 or h2 selected */
1130f4f0f0ceSflorian 	return SSL_TLSEXT_ERR_OK;
1131f4f0f0ceSflorian }
1132f4f0f0ceSflorian #endif
1133f4f0f0ceSflorian 
1134ae8c6e27Sflorian int
1135ae8c6e27Sflorian listen_sslctx_setup(void* ctxt)
1136ae8c6e27Sflorian {
1137ae8c6e27Sflorian #ifdef HAVE_SSL
1138ae8c6e27Sflorian 	SSL_CTX* ctx = (SSL_CTX*)ctxt;
1139ae8c6e27Sflorian 	/* no SSLv2, SSLv3 because has defects */
1140d32eb43cSflorian #if SSL_OP_NO_SSLv2 != 0
1141ae8c6e27Sflorian 	if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
1142ae8c6e27Sflorian 		!= SSL_OP_NO_SSLv2){
1143ae8c6e27Sflorian 		log_crypto_err("could not set SSL_OP_NO_SSLv2");
1144ae8c6e27Sflorian 		return 0;
1145ae8c6e27Sflorian 	}
1146d32eb43cSflorian #endif
1147ae8c6e27Sflorian 	if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
1148ae8c6e27Sflorian 		!= SSL_OP_NO_SSLv3){
1149ae8c6e27Sflorian 		log_crypto_err("could not set SSL_OP_NO_SSLv3");
1150ae8c6e27Sflorian 		return 0;
1151ae8c6e27Sflorian 	}
1152ae8c6e27Sflorian #if defined(SSL_OP_NO_TLSv1) && defined(SSL_OP_NO_TLSv1_1)
1153ae8c6e27Sflorian 	/* if we have tls 1.1 disable 1.0 */
1154ae8c6e27Sflorian 	if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1) & SSL_OP_NO_TLSv1)
1155ae8c6e27Sflorian 		!= SSL_OP_NO_TLSv1){
1156ae8c6e27Sflorian 		log_crypto_err("could not set SSL_OP_NO_TLSv1");
1157ae8c6e27Sflorian 		return 0;
1158ae8c6e27Sflorian 	}
1159ae8c6e27Sflorian #endif
1160ae8c6e27Sflorian #if defined(SSL_OP_NO_TLSv1_1) && defined(SSL_OP_NO_TLSv1_2)
1161ae8c6e27Sflorian 	/* if we have tls 1.2 disable 1.1 */
1162ae8c6e27Sflorian 	if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_1) & SSL_OP_NO_TLSv1_1)
1163ae8c6e27Sflorian 		!= SSL_OP_NO_TLSv1_1){
1164ae8c6e27Sflorian 		log_crypto_err("could not set SSL_OP_NO_TLSv1_1");
1165ae8c6e27Sflorian 		return 0;
1166ae8c6e27Sflorian 	}
1167ae8c6e27Sflorian #endif
1168da8c8390Sflorian #if defined(SSL_OP_NO_RENEGOTIATION)
1169da8c8390Sflorian 	/* disable client renegotiation */
1170da8c8390Sflorian 	if((SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION) &
1171da8c8390Sflorian 		SSL_OP_NO_RENEGOTIATION) != SSL_OP_NO_RENEGOTIATION) {
1172da8c8390Sflorian 		log_crypto_err("could not set SSL_OP_NO_RENEGOTIATION");
1173da8c8390Sflorian 		return 0;
1174da8c8390Sflorian 	}
1175da8c8390Sflorian #endif
1176ae8c6e27Sflorian #if defined(SHA256_DIGEST_LENGTH) && defined(USE_ECDSA)
1177a1a7ba80Sflorian 	/* if we detect system-wide crypto policies, use those */
1178a1a7ba80Sflorian 	if (access( "/etc/crypto-policies/config", F_OK ) != 0 ) {
1179ae8c6e27Sflorian 	/* if we have sha256, set the cipher list to have no known vulns */
1180ae8c6e27Sflorian 		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"))
1181ae8c6e27Sflorian 			log_crypto_err("could not set cipher list with SSL_CTX_set_cipher_list");
1182a1a7ba80Sflorian 	}
1183ae8c6e27Sflorian #endif
1184d500c338Sflorian #if defined(SSL_OP_IGNORE_UNEXPECTED_EOF)
1185d500c338Sflorian 	/* ignore errors when peers do not send the mandatory close_notify
1186d500c338Sflorian 	 * alert on shutdown.
1187d500c338Sflorian 	 * Relevant for openssl >= 3 */
1188d500c338Sflorian 	if((SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF) &
1189d500c338Sflorian 		SSL_OP_IGNORE_UNEXPECTED_EOF) != SSL_OP_IGNORE_UNEXPECTED_EOF) {
1190d500c338Sflorian 		log_crypto_err("could not set SSL_OP_IGNORE_UNEXPECTED_EOF");
1191d500c338Sflorian 		return 0;
1192d500c338Sflorian 	}
1193d500c338Sflorian #endif
1194ae8c6e27Sflorian 
1195ae8c6e27Sflorian 	if((SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE) &
1196ae8c6e27Sflorian 		SSL_OP_CIPHER_SERVER_PREFERENCE) !=
1197ae8c6e27Sflorian 		SSL_OP_CIPHER_SERVER_PREFERENCE) {
1198ae8c6e27Sflorian 		log_crypto_err("could not set SSL_OP_CIPHER_SERVER_PREFERENCE");
1199ae8c6e27Sflorian 		return 0;
1200ae8c6e27Sflorian 	}
1201ae8c6e27Sflorian 
1202ae8c6e27Sflorian #ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL
1203ae8c6e27Sflorian 	SSL_CTX_set_security_level(ctx, 0);
1204ae8c6e27Sflorian #endif
1205f4f0f0ceSflorian #if defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB) && defined(HAVE_NGHTTP2)
1206f4f0f0ceSflorian 	SSL_CTX_set_alpn_select_cb(ctx, alpn_select_cb, NULL);
1207f4f0f0ceSflorian #endif
1208ae8c6e27Sflorian #else
1209ae8c6e27Sflorian 	(void)ctxt;
1210ae8c6e27Sflorian #endif /* HAVE_SSL */
1211ae8c6e27Sflorian 	return 1;
1212ae8c6e27Sflorian }
1213ae8c6e27Sflorian 
1214ae8c6e27Sflorian void
1215ae8c6e27Sflorian listen_sslctx_setup_2(void* ctxt)
1216ae8c6e27Sflorian {
1217ae8c6e27Sflorian #ifdef HAVE_SSL
1218ae8c6e27Sflorian 	SSL_CTX* ctx = (SSL_CTX*)ctxt;
1219ae8c6e27Sflorian 	(void)ctx;
1220ae8c6e27Sflorian #if HAVE_DECL_SSL_CTX_SET_ECDH_AUTO
1221ae8c6e27Sflorian 	if(!SSL_CTX_set_ecdh_auto(ctx,1)) {
1222ae8c6e27Sflorian 		log_crypto_err("Error in SSL_CTX_ecdh_auto, not enabling ECDHE");
1223ae8c6e27Sflorian 	}
1224*7037e34cSflorian #elif defined(USE_ECDSA) && defined(HAVE_SSL_CTX_SET_TMP_ECDH)
1225ae8c6e27Sflorian 	if(1) {
1226ae8c6e27Sflorian 		EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1);
1227ae8c6e27Sflorian 		if (!ecdh) {
1228ae8c6e27Sflorian 			log_crypto_err("could not find p256, not enabling ECDHE");
1229ae8c6e27Sflorian 		} else {
1230ae8c6e27Sflorian 			if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh)) {
1231ae8c6e27Sflorian 				log_crypto_err("Error in SSL_CTX_set_tmp_ecdh, not enabling ECDHE");
1232ae8c6e27Sflorian 			}
1233ae8c6e27Sflorian 			EC_KEY_free (ecdh);
1234ae8c6e27Sflorian 		}
1235ae8c6e27Sflorian 	}
1236ae8c6e27Sflorian #endif
1237ae8c6e27Sflorian #else
1238ae8c6e27Sflorian 	(void)ctxt;
1239ae8c6e27Sflorian #endif /* HAVE_SSL */
1240ae8c6e27Sflorian }
1241ae8c6e27Sflorian 
1242ae8c6e27Sflorian void* listen_sslctx_create(char* key, char* pem, char* verifypem)
1243ae8c6e27Sflorian {
1244ae8c6e27Sflorian #ifdef HAVE_SSL
1245ae8c6e27Sflorian 	SSL_CTX* ctx = SSL_CTX_new(SSLv23_server_method());
1246ae8c6e27Sflorian 	if(!ctx) {
1247ae8c6e27Sflorian 		log_crypto_err("could not SSL_CTX_new");
1248ae8c6e27Sflorian 		return NULL;
1249ae8c6e27Sflorian 	}
12509b465e50Sflorian 	if(!key || key[0] == 0) {
12519b465e50Sflorian 		log_err("error: no tls-service-key file specified");
12529b465e50Sflorian 		SSL_CTX_free(ctx);
12539b465e50Sflorian 		return NULL;
12549b465e50Sflorian 	}
12559b465e50Sflorian 	if(!pem || pem[0] == 0) {
12569b465e50Sflorian 		log_err("error: no tls-service-pem file specified");
12579b465e50Sflorian 		SSL_CTX_free(ctx);
12589b465e50Sflorian 		return NULL;
12599b465e50Sflorian 	}
1260ae8c6e27Sflorian 	if(!listen_sslctx_setup(ctx)) {
1261ae8c6e27Sflorian 		SSL_CTX_free(ctx);
1262ae8c6e27Sflorian 		return NULL;
1263ae8c6e27Sflorian 	}
1264ae8c6e27Sflorian 	if(!SSL_CTX_use_certificate_chain_file(ctx, pem)) {
1265ae8c6e27Sflorian 		log_err("error for cert file: %s", pem);
1266ae8c6e27Sflorian 		log_crypto_err("error in SSL_CTX use_certificate_chain_file");
1267ae8c6e27Sflorian 		SSL_CTX_free(ctx);
1268ae8c6e27Sflorian 		return NULL;
1269ae8c6e27Sflorian 	}
1270ae8c6e27Sflorian 	if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) {
1271ae8c6e27Sflorian 		log_err("error for private key file: %s", key);
1272ae8c6e27Sflorian 		log_crypto_err("Error in SSL_CTX use_PrivateKey_file");
1273ae8c6e27Sflorian 		SSL_CTX_free(ctx);
1274ae8c6e27Sflorian 		return NULL;
1275ae8c6e27Sflorian 	}
1276ae8c6e27Sflorian 	if(!SSL_CTX_check_private_key(ctx)) {
1277ae8c6e27Sflorian 		log_err("error for key file: %s", key);
1278ae8c6e27Sflorian 		log_crypto_err("Error in SSL_CTX check_private_key");
1279ae8c6e27Sflorian 		SSL_CTX_free(ctx);
1280ae8c6e27Sflorian 		return NULL;
1281ae8c6e27Sflorian 	}
1282ae8c6e27Sflorian 	listen_sslctx_setup_2(ctx);
1283ae8c6e27Sflorian 	if(verifypem && verifypem[0]) {
1284ae8c6e27Sflorian 		if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) {
1285ae8c6e27Sflorian 			log_crypto_err("Error in SSL_CTX verify locations");
1286ae8c6e27Sflorian 			SSL_CTX_free(ctx);
1287ae8c6e27Sflorian 			return NULL;
1288ae8c6e27Sflorian 		}
1289ae8c6e27Sflorian 		SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(
1290ae8c6e27Sflorian 			verifypem));
1291e47fef9eSflorian 		SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
1292ae8c6e27Sflorian 	}
1293ae8c6e27Sflorian 	return ctx;
1294ae8c6e27Sflorian #else
1295ae8c6e27Sflorian 	(void)key; (void)pem; (void)verifypem;
1296ae8c6e27Sflorian 	return NULL;
1297ae8c6e27Sflorian #endif
1298ae8c6e27Sflorian }
1299ae8c6e27Sflorian 
1300ae8c6e27Sflorian #ifdef USE_WINSOCK
1301ae8c6e27Sflorian /* For windows, the CA trust store is not read by openssl.
1302ae8c6e27Sflorian    Add code to open the trust store using wincrypt API and add
1303ae8c6e27Sflorian    the root certs into openssl trust store */
1304ae8c6e27Sflorian static int
1305ae8c6e27Sflorian add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx)
1306ae8c6e27Sflorian {
1307ae8c6e27Sflorian 	HCERTSTORE      hSystemStore;
1308ae8c6e27Sflorian 	PCCERT_CONTEXT  pTargetCert = NULL;
1309ae8c6e27Sflorian 	X509_STORE*	store;
1310ae8c6e27Sflorian 
1311ae8c6e27Sflorian 	verbose(VERB_ALGO, "Adding Windows certificates from system root store to CA store");
1312ae8c6e27Sflorian 
1313ae8c6e27Sflorian 	/* load just once per context lifetime for this version
1314ae8c6e27Sflorian 	   TODO: dynamically update CA trust changes as they are available */
1315ae8c6e27Sflorian 	if (!tls_ctx)
1316ae8c6e27Sflorian 		return 0;
1317ae8c6e27Sflorian 
1318ae8c6e27Sflorian 	/* Call wincrypt's CertOpenStore to open the CA root store. */
1319ae8c6e27Sflorian 
1320ae8c6e27Sflorian 	if ((hSystemStore = CertOpenStore(
1321ae8c6e27Sflorian 		CERT_STORE_PROV_SYSTEM,
1322ae8c6e27Sflorian 		0,
1323ae8c6e27Sflorian 		0,
1324ae8c6e27Sflorian 		/* NOTE: mingw does not have this const: replace with 1 << 16 from code
1325ae8c6e27Sflorian 		   CERT_SYSTEM_STORE_CURRENT_USER, */
1326ae8c6e27Sflorian 		1 << 16,
1327ae8c6e27Sflorian 		L"root")) == 0)
1328ae8c6e27Sflorian 	{
1329ae8c6e27Sflorian 		return 0;
1330ae8c6e27Sflorian 	}
1331ae8c6e27Sflorian 
1332ae8c6e27Sflorian 	store = SSL_CTX_get_cert_store(tls_ctx);
1333ae8c6e27Sflorian 	if (!store)
1334ae8c6e27Sflorian 		return 0;
1335ae8c6e27Sflorian 
1336ae8c6e27Sflorian 	/* failure if the CA store is empty or the call fails */
1337ae8c6e27Sflorian 	if ((pTargetCert = CertEnumCertificatesInStore(
1338ae8c6e27Sflorian 		hSystemStore, pTargetCert)) == 0) {
1339ae8c6e27Sflorian 		verbose(VERB_ALGO, "CA certificate store for Windows is empty.");
1340ae8c6e27Sflorian 		return 0;
1341ae8c6e27Sflorian 	}
1342ae8c6e27Sflorian 	/* iterate over the windows cert store and add to openssl store */
1343ae8c6e27Sflorian 	do
1344ae8c6e27Sflorian 	{
1345ae8c6e27Sflorian 		X509 *cert1 = d2i_X509(NULL,
1346ae8c6e27Sflorian 			(const unsigned char **)&pTargetCert->pbCertEncoded,
1347ae8c6e27Sflorian 			pTargetCert->cbCertEncoded);
1348ae8c6e27Sflorian 		if (!cert1) {
13496d08cb1bSflorian 			unsigned long error = ERR_get_error();
1350ae8c6e27Sflorian 			/* return error if a cert fails */
1351ae8c6e27Sflorian 			verbose(VERB_ALGO, "%s %d:%s",
1352ae8c6e27Sflorian 				"Unable to parse certificate in memory",
13536d08cb1bSflorian 				(int)error, ERR_error_string(error, NULL));
1354ae8c6e27Sflorian 			return 0;
1355ae8c6e27Sflorian 		}
1356ae8c6e27Sflorian 		else {
1357ae8c6e27Sflorian 			/* return error if a cert add to store fails */
1358ae8c6e27Sflorian 			if (X509_STORE_add_cert(store, cert1) == 0) {
1359ae8c6e27Sflorian 				unsigned long error = ERR_peek_last_error();
1360ae8c6e27Sflorian 
1361ae8c6e27Sflorian 				/* Ignore error X509_R_CERT_ALREADY_IN_HASH_TABLE which means the
1362ae8c6e27Sflorian 				* certificate is already in the store.  */
1363ae8c6e27Sflorian 				if(ERR_GET_LIB(error) != ERR_LIB_X509 ||
1364ae8c6e27Sflorian 					ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
13656d08cb1bSflorian 					error = ERR_get_error();
1366ae8c6e27Sflorian 					verbose(VERB_ALGO, "%s %d:%s\n",
13676d08cb1bSflorian 					    "Error adding certificate", (int)error,
13686d08cb1bSflorian 					     ERR_error_string(error, NULL));
1369ae8c6e27Sflorian 					X509_free(cert1);
1370ae8c6e27Sflorian 					return 0;
1371ae8c6e27Sflorian 				}
1372ae8c6e27Sflorian 			}
1373ae8c6e27Sflorian 			X509_free(cert1);
1374ae8c6e27Sflorian 		}
1375ae8c6e27Sflorian 	} while ((pTargetCert = CertEnumCertificatesInStore(
1376ae8c6e27Sflorian 		hSystemStore, pTargetCert)) != 0);
1377ae8c6e27Sflorian 
1378ae8c6e27Sflorian 	/* Clean up memory and quit. */
1379ae8c6e27Sflorian 	if (pTargetCert)
1380ae8c6e27Sflorian 		CertFreeCertificateContext(pTargetCert);
1381ae8c6e27Sflorian 	if (hSystemStore)
1382ae8c6e27Sflorian 	{
1383ae8c6e27Sflorian 		if (!CertCloseStore(
1384ae8c6e27Sflorian 			hSystemStore, 0))
1385ae8c6e27Sflorian 			return 0;
1386ae8c6e27Sflorian 	}
1387ae8c6e27Sflorian 	verbose(VERB_ALGO, "Completed adding Windows certificates to CA store successfully");
1388ae8c6e27Sflorian 	return 1;
1389ae8c6e27Sflorian }
1390ae8c6e27Sflorian #endif /* USE_WINSOCK */
1391ae8c6e27Sflorian 
1392ae8c6e27Sflorian void* connect_sslctx_create(char* key, char* pem, char* verifypem, int wincert)
1393ae8c6e27Sflorian {
1394ae8c6e27Sflorian #ifdef HAVE_SSL
1395ae8c6e27Sflorian 	SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method());
1396ae8c6e27Sflorian 	if(!ctx) {
1397ae8c6e27Sflorian 		log_crypto_err("could not allocate SSL_CTX pointer");
1398ae8c6e27Sflorian 		return NULL;
1399ae8c6e27Sflorian 	}
1400d32eb43cSflorian #if SSL_OP_NO_SSLv2 != 0
1401ae8c6e27Sflorian 	if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
1402ae8c6e27Sflorian 		!= SSL_OP_NO_SSLv2) {
1403ae8c6e27Sflorian 		log_crypto_err("could not set SSL_OP_NO_SSLv2");
1404ae8c6e27Sflorian 		SSL_CTX_free(ctx);
1405ae8c6e27Sflorian 		return NULL;
1406ae8c6e27Sflorian 	}
1407d32eb43cSflorian #endif
1408ae8c6e27Sflorian 	if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
1409ae8c6e27Sflorian 		!= SSL_OP_NO_SSLv3) {
1410ae8c6e27Sflorian 		log_crypto_err("could not set SSL_OP_NO_SSLv3");
1411ae8c6e27Sflorian 		SSL_CTX_free(ctx);
1412ae8c6e27Sflorian 		return NULL;
1413ae8c6e27Sflorian 	}
1414da8c8390Sflorian #if defined(SSL_OP_NO_RENEGOTIATION)
1415da8c8390Sflorian 	/* disable client renegotiation */
1416da8c8390Sflorian 	if((SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION) &
1417da8c8390Sflorian 		SSL_OP_NO_RENEGOTIATION) != SSL_OP_NO_RENEGOTIATION) {
1418da8c8390Sflorian 		log_crypto_err("could not set SSL_OP_NO_RENEGOTIATION");
1419a1a7ba80Sflorian 		SSL_CTX_free(ctx);
1420da8c8390Sflorian 		return 0;
1421da8c8390Sflorian 	}
1422da8c8390Sflorian #endif
1423d500c338Sflorian #if defined(SSL_OP_IGNORE_UNEXPECTED_EOF)
1424d500c338Sflorian 	/* ignore errors when peers do not send the mandatory close_notify
1425d500c338Sflorian 	 * alert on shutdown.
1426d500c338Sflorian 	 * Relevant for openssl >= 3 */
1427d500c338Sflorian 	if((SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF) &
1428d500c338Sflorian 		SSL_OP_IGNORE_UNEXPECTED_EOF) != SSL_OP_IGNORE_UNEXPECTED_EOF) {
1429d500c338Sflorian 		log_crypto_err("could not set SSL_OP_IGNORE_UNEXPECTED_EOF");
1430d500c338Sflorian 		SSL_CTX_free(ctx);
1431d500c338Sflorian 		return 0;
1432d500c338Sflorian 	}
1433d500c338Sflorian #endif
1434ae8c6e27Sflorian 	if(key && key[0]) {
1435ae8c6e27Sflorian 		if(!SSL_CTX_use_certificate_chain_file(ctx, pem)) {
1436ae8c6e27Sflorian 			log_err("error in client certificate %s", pem);
1437ae8c6e27Sflorian 			log_crypto_err("error in certificate file");
1438ae8c6e27Sflorian 			SSL_CTX_free(ctx);
1439ae8c6e27Sflorian 			return NULL;
1440ae8c6e27Sflorian 		}
1441ae8c6e27Sflorian 		if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) {
1442ae8c6e27Sflorian 			log_err("error in client private key %s", key);
1443ae8c6e27Sflorian 			log_crypto_err("error in key file");
1444ae8c6e27Sflorian 			SSL_CTX_free(ctx);
1445ae8c6e27Sflorian 			return NULL;
1446ae8c6e27Sflorian 		}
1447ae8c6e27Sflorian 		if(!SSL_CTX_check_private_key(ctx)) {
1448ae8c6e27Sflorian 			log_err("error in client key %s", key);
1449ae8c6e27Sflorian 			log_crypto_err("error in SSL_CTX_check_private_key");
1450ae8c6e27Sflorian 			SSL_CTX_free(ctx);
1451ae8c6e27Sflorian 			return NULL;
1452ae8c6e27Sflorian 		}
1453ae8c6e27Sflorian 	}
1454ae8c6e27Sflorian 	if((verifypem && verifypem[0]) || wincert) {
1455ae8c6e27Sflorian 		if(verifypem && verifypem[0]) {
1456ae8c6e27Sflorian 			if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) {
1457ae8c6e27Sflorian 				log_crypto_err("error in SSL_CTX verify");
1458ae8c6e27Sflorian 				SSL_CTX_free(ctx);
1459ae8c6e27Sflorian 				return NULL;
1460ae8c6e27Sflorian 			}
1461ae8c6e27Sflorian 		}
1462ae8c6e27Sflorian #ifdef USE_WINSOCK
1463ae8c6e27Sflorian 		if(wincert) {
1464ae8c6e27Sflorian 			if(!add_WIN_cacerts_to_openssl_store(ctx)) {
1465ae8c6e27Sflorian 				log_crypto_err("error in add_WIN_cacerts_to_openssl_store");
1466ae8c6e27Sflorian 				SSL_CTX_free(ctx);
1467ae8c6e27Sflorian 				return NULL;
1468ae8c6e27Sflorian 			}
1469ae8c6e27Sflorian 		}
1470ae8c6e27Sflorian #else
14717a05b9dfSflorian 		if(wincert) {
14727a05b9dfSflorian 			if(!SSL_CTX_set_default_verify_paths(ctx)) {
14737a05b9dfSflorian 				log_crypto_err("error in default_verify_paths");
14747a05b9dfSflorian 				SSL_CTX_free(ctx);
14757a05b9dfSflorian 				return NULL;
14767a05b9dfSflorian 			}
14777a05b9dfSflorian 		}
1478ae8c6e27Sflorian #endif
1479ae8c6e27Sflorian 		SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
1480ae8c6e27Sflorian 	}
1481ae8c6e27Sflorian 	return ctx;
1482ae8c6e27Sflorian #else
1483ae8c6e27Sflorian 	(void)key; (void)pem; (void)verifypem; (void)wincert;
1484ae8c6e27Sflorian 	return NULL;
1485ae8c6e27Sflorian #endif
1486ae8c6e27Sflorian }
1487ae8c6e27Sflorian 
1488ae8c6e27Sflorian void* incoming_ssl_fd(void* sslctx, int fd)
1489ae8c6e27Sflorian {
1490ae8c6e27Sflorian #ifdef HAVE_SSL
1491ae8c6e27Sflorian 	SSL* ssl = SSL_new((SSL_CTX*)sslctx);
1492ae8c6e27Sflorian 	if(!ssl) {
1493ae8c6e27Sflorian 		log_crypto_err("could not SSL_new");
1494ae8c6e27Sflorian 		return NULL;
1495ae8c6e27Sflorian 	}
1496ae8c6e27Sflorian 	SSL_set_accept_state(ssl);
149757403691Sflorian 	(void)SSL_set_mode(ssl, (long)SSL_MODE_AUTO_RETRY);
1498ae8c6e27Sflorian 	if(!SSL_set_fd(ssl, fd)) {
1499ae8c6e27Sflorian 		log_crypto_err("could not SSL_set_fd");
1500ae8c6e27Sflorian 		SSL_free(ssl);
1501ae8c6e27Sflorian 		return NULL;
1502ae8c6e27Sflorian 	}
1503ae8c6e27Sflorian 	return ssl;
1504ae8c6e27Sflorian #else
1505ae8c6e27Sflorian 	(void)sslctx; (void)fd;
1506ae8c6e27Sflorian 	return NULL;
1507ae8c6e27Sflorian #endif
1508ae8c6e27Sflorian }
1509ae8c6e27Sflorian 
1510ae8c6e27Sflorian void* outgoing_ssl_fd(void* sslctx, int fd)
1511ae8c6e27Sflorian {
1512ae8c6e27Sflorian #ifdef HAVE_SSL
1513ae8c6e27Sflorian 	SSL* ssl = SSL_new((SSL_CTX*)sslctx);
1514ae8c6e27Sflorian 	if(!ssl) {
1515ae8c6e27Sflorian 		log_crypto_err("could not SSL_new");
1516ae8c6e27Sflorian 		return NULL;
1517ae8c6e27Sflorian 	}
1518ae8c6e27Sflorian 	SSL_set_connect_state(ssl);
151957403691Sflorian 	(void)SSL_set_mode(ssl, (long)SSL_MODE_AUTO_RETRY);
1520ae8c6e27Sflorian 	if(!SSL_set_fd(ssl, fd)) {
1521ae8c6e27Sflorian 		log_crypto_err("could not SSL_set_fd");
1522ae8c6e27Sflorian 		SSL_free(ssl);
1523ae8c6e27Sflorian 		return NULL;
1524ae8c6e27Sflorian 	}
1525ae8c6e27Sflorian 	return ssl;
1526ae8c6e27Sflorian #else
1527ae8c6e27Sflorian 	(void)sslctx; (void)fd;
1528ae8c6e27Sflorian 	return NULL;
1529ae8c6e27Sflorian #endif
1530ae8c6e27Sflorian }
1531ae8c6e27Sflorian 
1532e47fef9eSflorian int check_auth_name_for_ssl(char* auth_name)
1533e47fef9eSflorian {
1534e47fef9eSflorian 	if(!auth_name) return 1;
1535e47fef9eSflorian #if defined(HAVE_SSL) && !defined(HAVE_SSL_SET1_HOST) && !defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
1536e47fef9eSflorian 	log_err("the query has an auth_name %s, but libssl has no call to "
1537e47fef9eSflorian 		"perform TLS authentication.  Remove that name from config "
1538e47fef9eSflorian 		"or upgrade the ssl crypto library.", auth_name);
1539e47fef9eSflorian 	return 0;
1540e47fef9eSflorian #else
1541e47fef9eSflorian 	return 1;
1542e47fef9eSflorian #endif
1543e47fef9eSflorian }
1544e47fef9eSflorian 
1545e47fef9eSflorian /** set the authname on an SSL structure, SSL* ssl */
1546e47fef9eSflorian int set_auth_name_on_ssl(void* ssl, char* auth_name, int use_sni)
1547e47fef9eSflorian {
1548e47fef9eSflorian 	if(!auth_name) return 1;
1549e47fef9eSflorian #ifdef HAVE_SSL
1550e47fef9eSflorian 	if(use_sni) {
1551e47fef9eSflorian 		(void)SSL_set_tlsext_host_name(ssl, auth_name);
1552e47fef9eSflorian 	}
1553e47fef9eSflorian #else
1554e47fef9eSflorian 	(void)ssl;
1555e47fef9eSflorian 	(void)use_sni;
1556e47fef9eSflorian #endif
1557e47fef9eSflorian #ifdef HAVE_SSL_SET1_HOST
1558e47fef9eSflorian 	SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL);
1559e47fef9eSflorian 	/* setting the hostname makes openssl verify the
1560e47fef9eSflorian 	 * host name in the x509 certificate in the
1561e47fef9eSflorian 	 * SSL connection*/
1562e47fef9eSflorian 	if(!SSL_set1_host(ssl, auth_name)) {
1563e47fef9eSflorian 		log_err("SSL_set1_host failed");
1564e47fef9eSflorian 		return 0;
1565e47fef9eSflorian 	}
1566e47fef9eSflorian #elif defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
1567e47fef9eSflorian 	/* openssl 1.0.2 has this function that can be used for
1568e47fef9eSflorian 	 * set1_host like verification */
1569e47fef9eSflorian 	if(auth_name) {
1570e47fef9eSflorian 		X509_VERIFY_PARAM* param = SSL_get0_param(ssl);
1571e47fef9eSflorian #  ifdef X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS
1572e47fef9eSflorian 		X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
1573e47fef9eSflorian #  endif
1574e47fef9eSflorian 		if(!X509_VERIFY_PARAM_set1_host(param, auth_name, strlen(auth_name))) {
1575e47fef9eSflorian 			log_err("X509_VERIFY_PARAM_set1_host failed");
1576e47fef9eSflorian 			return 0;
1577e47fef9eSflorian 		}
1578e47fef9eSflorian 		SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL);
1579e47fef9eSflorian 	}
1580e47fef9eSflorian #else
1581e47fef9eSflorian 	verbose(VERB_ALGO, "the query has an auth_name, but libssl has no call to perform TLS authentication");
1582e47fef9eSflorian #endif /* HAVE_SSL_SET1_HOST */
1583e47fef9eSflorian 	return 1;
1584e47fef9eSflorian }
1585e47fef9eSflorian 
1586ae8c6e27Sflorian #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L
1587ae8c6e27Sflorian /** global lock list for openssl locks */
1588ae8c6e27Sflorian static lock_basic_type *ub_openssl_locks = NULL;
1589ae8c6e27Sflorian 
1590ae8c6e27Sflorian /** callback that gets thread id for openssl */
1591988ebc2dSflorian #ifdef HAVE_CRYPTO_THREADID_SET_CALLBACK
1592988ebc2dSflorian static void
1593988ebc2dSflorian ub_crypto_id_cb(CRYPTO_THREADID *id)
1594988ebc2dSflorian {
1595988ebc2dSflorian 	CRYPTO_THREADID_set_numeric(id, (unsigned long)log_thread_get());
1596988ebc2dSflorian }
1597988ebc2dSflorian #else
1598ae8c6e27Sflorian static unsigned long
1599ae8c6e27Sflorian ub_crypto_id_cb(void)
1600ae8c6e27Sflorian {
1601ae8c6e27Sflorian 	return (unsigned long)log_thread_get();
1602ae8c6e27Sflorian }
1603988ebc2dSflorian #endif
1604ae8c6e27Sflorian 
1605ae8c6e27Sflorian static void
1606ae8c6e27Sflorian ub_crypto_lock_cb(int mode, int type, const char *ATTR_UNUSED(file),
1607ae8c6e27Sflorian 	int ATTR_UNUSED(line))
1608ae8c6e27Sflorian {
1609ae8c6e27Sflorian 	if((mode&CRYPTO_LOCK)) {
1610ae8c6e27Sflorian 		lock_basic_lock(&ub_openssl_locks[type]);
1611ae8c6e27Sflorian 	} else {
1612ae8c6e27Sflorian 		lock_basic_unlock(&ub_openssl_locks[type]);
1613ae8c6e27Sflorian 	}
1614ae8c6e27Sflorian }
1615ae8c6e27Sflorian #endif /* OPENSSL_THREADS */
1616ae8c6e27Sflorian 
1617ae8c6e27Sflorian int ub_openssl_lock_init(void)
1618ae8c6e27Sflorian {
1619ae8c6e27Sflorian #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L
1620ae8c6e27Sflorian 	int i;
1621ae8c6e27Sflorian 	ub_openssl_locks = (lock_basic_type*)reallocarray(
1622ae8c6e27Sflorian 		NULL, (size_t)CRYPTO_num_locks(), sizeof(lock_basic_type));
1623ae8c6e27Sflorian 	if(!ub_openssl_locks)
1624ae8c6e27Sflorian 		return 0;
1625ae8c6e27Sflorian 	for(i=0; i<CRYPTO_num_locks(); i++) {
1626ae8c6e27Sflorian 		lock_basic_init(&ub_openssl_locks[i]);
1627ae8c6e27Sflorian 	}
1628988ebc2dSflorian #  ifdef HAVE_CRYPTO_THREADID_SET_CALLBACK
1629988ebc2dSflorian 	CRYPTO_THREADID_set_callback(&ub_crypto_id_cb);
1630988ebc2dSflorian #  else
1631ae8c6e27Sflorian 	CRYPTO_set_id_callback(&ub_crypto_id_cb);
1632988ebc2dSflorian #  endif
1633ae8c6e27Sflorian 	CRYPTO_set_locking_callback(&ub_crypto_lock_cb);
1634ae8c6e27Sflorian #endif /* OPENSSL_THREADS */
1635ae8c6e27Sflorian 	return 1;
1636ae8c6e27Sflorian }
1637ae8c6e27Sflorian 
1638ae8c6e27Sflorian void ub_openssl_lock_delete(void)
1639ae8c6e27Sflorian {
1640ae8c6e27Sflorian #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L
1641ae8c6e27Sflorian 	int i;
1642ae8c6e27Sflorian 	if(!ub_openssl_locks)
1643ae8c6e27Sflorian 		return;
1644988ebc2dSflorian #  ifdef HAVE_CRYPTO_THREADID_SET_CALLBACK
1645988ebc2dSflorian 	CRYPTO_THREADID_set_callback(NULL);
1646988ebc2dSflorian #  else
1647ae8c6e27Sflorian 	CRYPTO_set_id_callback(NULL);
1648988ebc2dSflorian #  endif
1649ae8c6e27Sflorian 	CRYPTO_set_locking_callback(NULL);
1650ae8c6e27Sflorian 	for(i=0; i<CRYPTO_num_locks(); i++) {
1651ae8c6e27Sflorian 		lock_basic_destroy(&ub_openssl_locks[i]);
1652ae8c6e27Sflorian 	}
1653ae8c6e27Sflorian 	free(ub_openssl_locks);
1654ae8c6e27Sflorian #endif /* OPENSSL_THREADS */
1655ae8c6e27Sflorian }
1656ae8c6e27Sflorian 
1657e97c6e54Ssthen int listen_sslctx_setup_ticket_keys(void* sslctx, struct config_strlist* tls_session_ticket_keys) {
1658e97c6e54Ssthen #ifdef HAVE_SSL
1659e97c6e54Ssthen 	size_t s = 1;
1660e97c6e54Ssthen 	struct config_strlist* p;
1661e97c6e54Ssthen 	struct tls_session_ticket_key *keys;
1662e97c6e54Ssthen 	for(p = tls_session_ticket_keys; p; p = p->next) {
1663e97c6e54Ssthen 		s++;
1664e97c6e54Ssthen 	}
1665e97c6e54Ssthen 	keys = calloc(s, sizeof(struct tls_session_ticket_key));
1666d32eb43cSflorian 	if(!keys)
1667d32eb43cSflorian 		return 0;
1668e97c6e54Ssthen 	memset(keys, 0, s*sizeof(*keys));
1669e97c6e54Ssthen 	ticket_keys = keys;
1670e97c6e54Ssthen 
1671e97c6e54Ssthen 	for(p = tls_session_ticket_keys; p; p = p->next) {
1672e97c6e54Ssthen 		size_t n;
1673d32eb43cSflorian 		unsigned char *data;
1674d32eb43cSflorian 		FILE *f;
1675d32eb43cSflorian 
1676d32eb43cSflorian 		data = (unsigned char *)malloc(80);
1677d32eb43cSflorian 		if(!data)
1678d32eb43cSflorian 			return 0;
1679d32eb43cSflorian 
1680e47fef9eSflorian 		f = fopen(p->str, "rb");
1681e97c6e54Ssthen 		if(!f) {
1682e97c6e54Ssthen 			log_err("could not read tls-session-ticket-key %s: %s", p->str, strerror(errno));
1683e97c6e54Ssthen 			free(data);
1684e97c6e54Ssthen 			return 0;
1685e97c6e54Ssthen 		}
1686e97c6e54Ssthen 		n = fread(data, 1, 80, f);
1687e97c6e54Ssthen 		fclose(f);
1688e97c6e54Ssthen 
1689e97c6e54Ssthen 		if(n != 80) {
1690e97c6e54Ssthen 			log_err("tls-session-ticket-key %s is %d bytes, must be 80 bytes", p->str, (int)n);
1691e97c6e54Ssthen 			free(data);
1692e97c6e54Ssthen 			return 0;
1693e97c6e54Ssthen 		}
1694e97c6e54Ssthen 		verbose(VERB_OPS, "read tls-session-ticket-key: %s", p->str);
1695e97c6e54Ssthen 
1696e97c6e54Ssthen 		keys->key_name = data;
1697e97c6e54Ssthen 		keys->aes_key = data + 16;
1698e97c6e54Ssthen 		keys->hmac_key = data + 48;
1699e97c6e54Ssthen 		keys++;
1700e97c6e54Ssthen 	}
1701e97c6e54Ssthen 	/* terminate array with NULL key name entry */
1702e97c6e54Ssthen 	keys->key_name = NULL;
1703e47fef9eSflorian #  ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
1704e47fef9eSflorian 	if(SSL_CTX_set_tlsext_ticket_key_evp_cb(sslctx, tls_session_ticket_key_cb) == 0) {
1705e47fef9eSflorian 		log_err("no support for TLS session ticket");
1706e47fef9eSflorian 		return 0;
1707e47fef9eSflorian 	}
1708e47fef9eSflorian #  else
1709e97c6e54Ssthen 	if(SSL_CTX_set_tlsext_ticket_key_cb(sslctx, tls_session_ticket_key_cb) == 0) {
1710e97c6e54Ssthen 		log_err("no support for TLS session ticket");
1711e97c6e54Ssthen 		return 0;
1712e97c6e54Ssthen 	}
1713e47fef9eSflorian #  endif
1714e97c6e54Ssthen 	return 1;
1715e97c6e54Ssthen #else
1716e97c6e54Ssthen 	(void)sslctx;
1717e97c6e54Ssthen 	(void)tls_session_ticket_keys;
1718e97c6e54Ssthen 	return 0;
1719e97c6e54Ssthen #endif
1720e97c6e54Ssthen 
1721e97c6e54Ssthen }
1722e97c6e54Ssthen 
1723e47fef9eSflorian #ifdef HAVE_SSL
1724e47fef9eSflorian int tls_session_ticket_key_cb(SSL *ATTR_UNUSED(sslctx), unsigned char* key_name,
1725e47fef9eSflorian 	unsigned char* iv, EVP_CIPHER_CTX *evp_sctx,
1726e47fef9eSflorian #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
1727e47fef9eSflorian 	EVP_MAC_CTX *hmac_ctx,
1728e47fef9eSflorian #else
1729e47fef9eSflorian 	HMAC_CTX* hmac_ctx,
1730e47fef9eSflorian #endif
1731e47fef9eSflorian 	int enc)
1732e97c6e54Ssthen {
1733e97c6e54Ssthen #ifdef HAVE_SSL
1734e47fef9eSflorian #  ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
1735e47fef9eSflorian 	OSSL_PARAM params[3];
1736e47fef9eSflorian #  else
1737e97c6e54Ssthen 	const EVP_MD *digest;
1738e47fef9eSflorian #  endif
1739e97c6e54Ssthen 	const EVP_CIPHER *cipher;
1740e97c6e54Ssthen 	int evp_cipher_length;
1741e47fef9eSflorian #  ifndef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
1742e97c6e54Ssthen 	digest = EVP_sha256();
1743e47fef9eSflorian #  endif
1744e97c6e54Ssthen 	cipher = EVP_aes_256_cbc();
1745e97c6e54Ssthen 	evp_cipher_length = EVP_CIPHER_iv_length(cipher);
1746e97c6e54Ssthen 	if( enc == 1 ) {
1747e97c6e54Ssthen 		/* encrypt */
1748e97c6e54Ssthen 		verbose(VERB_CLIENT, "start session encrypt");
1749e97c6e54Ssthen 		memcpy(key_name, ticket_keys->key_name, 16);
1750e97c6e54Ssthen 		if (RAND_bytes(iv, evp_cipher_length) != 1) {
1751e97c6e54Ssthen 			verbose(VERB_CLIENT, "RAND_bytes failed");
1752e97c6e54Ssthen 			return -1;
1753e97c6e54Ssthen 		}
1754e97c6e54Ssthen 		if (EVP_EncryptInit_ex(evp_sctx, cipher, NULL, ticket_keys->aes_key, iv) != 1) {
1755e97c6e54Ssthen 			verbose(VERB_CLIENT, "EVP_EncryptInit_ex failed");
1756e97c6e54Ssthen 			return -1;
1757e97c6e54Ssthen 		}
1758e47fef9eSflorian #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
1759e47fef9eSflorian 		params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
1760e47fef9eSflorian 			ticket_keys->hmac_key, 32);
1761e47fef9eSflorian 		params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
1762e47fef9eSflorian 			"sha256", 0);
1763e47fef9eSflorian 		params[2] = OSSL_PARAM_construct_end();
1764f4f0f0ceSflorian #ifdef HAVE_EVP_MAC_CTX_SET_PARAMS
1765f4f0f0ceSflorian 		EVP_MAC_CTX_set_params(hmac_ctx, params);
1766f4f0f0ceSflorian #else
1767e47fef9eSflorian 		EVP_MAC_set_ctx_params(hmac_ctx, params);
1768f4f0f0ceSflorian #endif
1769e47fef9eSflorian #elif !defined(HMAC_INIT_EX_RETURNS_VOID)
1770e97c6e54Ssthen 		if (HMAC_Init_ex(hmac_ctx, ticket_keys->hmac_key, 32, digest, NULL) != 1) {
1771e97c6e54Ssthen 			verbose(VERB_CLIENT, "HMAC_Init_ex failed");
1772e97c6e54Ssthen 			return -1;
1773e97c6e54Ssthen 		}
177457403691Sflorian #else
177557403691Sflorian 		HMAC_Init_ex(hmac_ctx, ticket_keys->hmac_key, 32, digest, NULL);
177657403691Sflorian #endif
1777e97c6e54Ssthen 		return 1;
1778e97c6e54Ssthen 	} else if (enc == 0) {
1779e97c6e54Ssthen 		/* decrypt */
1780e97c6e54Ssthen 		struct tls_session_ticket_key *key;
1781e97c6e54Ssthen 		verbose(VERB_CLIENT, "start session decrypt");
1782e97c6e54Ssthen 		for(key = ticket_keys; key->key_name != NULL; key++) {
1783e97c6e54Ssthen 			if (!memcmp(key_name, key->key_name, 16)) {
1784e97c6e54Ssthen 				verbose(VERB_CLIENT, "Found session_key");
1785e97c6e54Ssthen 				break;
1786e97c6e54Ssthen 			}
1787e97c6e54Ssthen 		}
1788e97c6e54Ssthen 		if(key->key_name == NULL) {
1789e97c6e54Ssthen 			verbose(VERB_CLIENT, "Not found session_key");
1790e97c6e54Ssthen 			return 0;
1791e97c6e54Ssthen 		}
1792e97c6e54Ssthen 
1793e47fef9eSflorian #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
1794e47fef9eSflorian 		params[0] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
1795e47fef9eSflorian 			key->hmac_key, 32);
1796e47fef9eSflorian 		params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
1797e47fef9eSflorian 			"sha256", 0);
1798e47fef9eSflorian 		params[2] = OSSL_PARAM_construct_end();
1799f4f0f0ceSflorian #ifdef HAVE_EVP_MAC_CTX_SET_PARAMS
1800f4f0f0ceSflorian 		EVP_MAC_CTX_set_params(hmac_ctx, params);
1801f4f0f0ceSflorian #else
1802e47fef9eSflorian 		EVP_MAC_set_ctx_params(hmac_ctx, params);
1803f4f0f0ceSflorian #endif
1804e47fef9eSflorian #elif !defined(HMAC_INIT_EX_RETURNS_VOID)
1805e97c6e54Ssthen 		if (HMAC_Init_ex(hmac_ctx, key->hmac_key, 32, digest, NULL) != 1) {
1806e97c6e54Ssthen 			verbose(VERB_CLIENT, "HMAC_Init_ex failed");
1807e97c6e54Ssthen 			return -1;
1808e97c6e54Ssthen 		}
180957403691Sflorian #else
181057403691Sflorian 		HMAC_Init_ex(hmac_ctx, key->hmac_key, 32, digest, NULL);
181157403691Sflorian #endif
1812e97c6e54Ssthen 		if (EVP_DecryptInit_ex(evp_sctx, cipher, NULL, key->aes_key, iv) != 1) {
1813e97c6e54Ssthen 			log_err("EVP_DecryptInit_ex failed");
1814e97c6e54Ssthen 			return -1;
1815e97c6e54Ssthen 		}
1816e97c6e54Ssthen 
1817e97c6e54Ssthen 		return (key == ticket_keys) ? 1 : 2;
1818e97c6e54Ssthen 	}
1819e97c6e54Ssthen 	return -1;
1820e97c6e54Ssthen #else
1821e97c6e54Ssthen 	(void)key_name;
1822e97c6e54Ssthen 	(void)iv;
1823e97c6e54Ssthen 	(void)evp_sctx;
1824e97c6e54Ssthen 	(void)hmac_ctx;
1825e97c6e54Ssthen 	(void)enc;
1826e97c6e54Ssthen 	return 0;
1827e97c6e54Ssthen #endif
1828e97c6e54Ssthen }
1829e47fef9eSflorian #endif /* HAVE_SSL */
1830e97c6e54Ssthen 
1831e97c6e54Ssthen void
1832e97c6e54Ssthen listen_sslctx_delete_ticket_keys(void)
1833e97c6e54Ssthen {
1834e97c6e54Ssthen 	struct tls_session_ticket_key *key;
1835e97c6e54Ssthen 	if(!ticket_keys) return;
1836e97c6e54Ssthen 	for(key = ticket_keys; key->key_name != NULL; key++) {
18379b465e50Sflorian 		/* wipe key data from memory*/
18389b465e50Sflorian #ifdef HAVE_EXPLICIT_BZERO
18399b465e50Sflorian 		explicit_bzero(key->key_name, 80);
18409b465e50Sflorian #else
18419b465e50Sflorian 		memset(key->key_name, 0xdd, 80);
18429b465e50Sflorian #endif
1843e97c6e54Ssthen 		free(key->key_name);
1844e97c6e54Ssthen 	}
1845e97c6e54Ssthen 	free(ticket_keys);
1846e97c6e54Ssthen 	ticket_keys = NULL;
1847e97c6e54Ssthen }
1848f4f0f0ceSflorian 
1849f4f0f0ceSflorian #  ifndef USE_WINSOCK
1850f4f0f0ceSflorian char*
1851f4f0f0ceSflorian sock_strerror(int errn)
1852f4f0f0ceSflorian {
1853f4f0f0ceSflorian 	return strerror(errn);
1854f4f0f0ceSflorian }
1855f4f0f0ceSflorian 
1856f4f0f0ceSflorian void
1857f4f0f0ceSflorian sock_close(int socket)
1858f4f0f0ceSflorian {
1859f4f0f0ceSflorian 	close(socket);
1860f4f0f0ceSflorian }
1861f4f0f0ceSflorian 
1862f4f0f0ceSflorian #  else
1863f4f0f0ceSflorian char*
1864f4f0f0ceSflorian sock_strerror(int ATTR_UNUSED(errn))
1865f4f0f0ceSflorian {
1866f4f0f0ceSflorian 	return wsa_strerror(WSAGetLastError());
1867f4f0f0ceSflorian }
1868f4f0f0ceSflorian 
1869f4f0f0ceSflorian void
1870f4f0f0ceSflorian sock_close(int socket)
1871f4f0f0ceSflorian {
1872f4f0f0ceSflorian 	closesocket(socket);
1873f4f0f0ceSflorian }
1874f4f0f0ceSflorian #  endif /* USE_WINSOCK */
1875*7037e34cSflorian 
1876*7037e34cSflorian ssize_t
1877*7037e34cSflorian hex_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize)
1878*7037e34cSflorian {
1879*7037e34cSflorian 	static char hexdigits[] = {
1880*7037e34cSflorian 		'0', '1', '2', '3', '4', '5', '6', '7',
1881*7037e34cSflorian 		'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
1882*7037e34cSflorian 	};
1883*7037e34cSflorian 	size_t i;
1884*7037e34cSflorian 
1885*7037e34cSflorian 	if (targsize < srclength * 2 + 1) {
1886*7037e34cSflorian 		return -1;
1887*7037e34cSflorian 	}
1888*7037e34cSflorian 
1889*7037e34cSflorian 	for (i = 0; i < srclength; ++i) {
1890*7037e34cSflorian 		*target++ = hexdigits[src[i] >> 4U];
1891*7037e34cSflorian 		*target++ = hexdigits[src[i] & 0xfU];
1892*7037e34cSflorian 	}
1893*7037e34cSflorian 	*target = '\0';
1894*7037e34cSflorian 	return 2 * srclength;
1895*7037e34cSflorian }
1896*7037e34cSflorian 
1897*7037e34cSflorian ssize_t
1898*7037e34cSflorian hex_pton(const char* src, uint8_t* target, size_t targsize)
1899*7037e34cSflorian {
1900*7037e34cSflorian 	uint8_t *t = target;
1901*7037e34cSflorian 	if(strlen(src) % 2 != 0 || strlen(src)/2 > targsize) {
1902*7037e34cSflorian 		return -1;
1903*7037e34cSflorian 	}
1904*7037e34cSflorian 	while(*src) {
1905*7037e34cSflorian 		if(!isxdigit((unsigned char)src[0]) ||
1906*7037e34cSflorian 			!isxdigit((unsigned char)src[1]))
1907*7037e34cSflorian 			return -1;
1908*7037e34cSflorian 		*t++ = sldns_hexdigit_to_int(src[0]) * 16 +
1909*7037e34cSflorian 			sldns_hexdigit_to_int(src[1]) ;
1910*7037e34cSflorian 		src += 2;
1911*7037e34cSflorian 	}
1912*7037e34cSflorian 	return t-target;
1913*7037e34cSflorian }
1914