xref: /freebsd/contrib/unbound/util/net_help.c (revision a39a5a6905612447def27b66ffe73b9d11efd80c)
1b7579f77SDag-Erling Smørgrav /*
2b7579f77SDag-Erling Smørgrav  * util/net_help.c - implementation of the network helper code
3b7579f77SDag-Erling Smørgrav  *
4b7579f77SDag-Erling Smørgrav  * Copyright (c) 2007, NLnet Labs. All rights reserved.
5b7579f77SDag-Erling Smørgrav  *
6b7579f77SDag-Erling Smørgrav  * This software is open source.
7b7579f77SDag-Erling Smørgrav  *
8b7579f77SDag-Erling Smørgrav  * Redistribution and use in source and binary forms, with or without
9b7579f77SDag-Erling Smørgrav  * modification, are permitted provided that the following conditions
10b7579f77SDag-Erling Smørgrav  * are met:
11b7579f77SDag-Erling Smørgrav  *
12b7579f77SDag-Erling Smørgrav  * Redistributions of source code must retain the above copyright notice,
13b7579f77SDag-Erling Smørgrav  * this list of conditions and the following disclaimer.
14b7579f77SDag-Erling Smørgrav  *
15b7579f77SDag-Erling Smørgrav  * Redistributions in binary form must reproduce the above copyright notice,
16b7579f77SDag-Erling Smørgrav  * this list of conditions and the following disclaimer in the documentation
17b7579f77SDag-Erling Smørgrav  * and/or other materials provided with the distribution.
18b7579f77SDag-Erling Smørgrav  *
19b7579f77SDag-Erling Smørgrav  * Neither the name of the NLNET LABS nor the names of its contributors may
20b7579f77SDag-Erling Smørgrav  * be used to endorse or promote products derived from this software without
21b7579f77SDag-Erling Smørgrav  * specific prior written permission.
22b7579f77SDag-Erling Smørgrav  *
23b7579f77SDag-Erling Smørgrav  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2417d15b25SDag-Erling Smørgrav  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2517d15b25SDag-Erling Smørgrav  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2617d15b25SDag-Erling Smørgrav  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2717d15b25SDag-Erling Smørgrav  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2817d15b25SDag-Erling Smørgrav  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
2917d15b25SDag-Erling Smørgrav  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
3017d15b25SDag-Erling Smørgrav  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3117d15b25SDag-Erling Smørgrav  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3217d15b25SDag-Erling Smørgrav  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3317d15b25SDag-Erling Smørgrav  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34b7579f77SDag-Erling Smørgrav  */
35b7579f77SDag-Erling Smørgrav /**
36b7579f77SDag-Erling Smørgrav  * \file
37b7579f77SDag-Erling Smørgrav  * Implementation of net_help.h.
38b7579f77SDag-Erling Smørgrav  */
39b7579f77SDag-Erling Smørgrav 
40b7579f77SDag-Erling Smørgrav #include "config.h"
4124e36522SCy Schubert #ifdef HAVE_SYS_TYPES_H
4224e36522SCy Schubert #  include <sys/types.h>
4324e36522SCy Schubert #endif
4424e36522SCy Schubert #ifdef HAVE_NET_IF_H
4524e36522SCy Schubert #include <net/if.h>
4624e36522SCy Schubert #endif
479cf5bc93SCy Schubert #ifdef HAVE_NETIOAPI_H
489cf5bc93SCy Schubert #include <netioapi.h>
499cf5bc93SCy Schubert #endif
50b7579f77SDag-Erling Smørgrav #include "util/net_help.h"
51b7579f77SDag-Erling Smørgrav #include "util/log.h"
52b7579f77SDag-Erling Smørgrav #include "util/data/dname.h"
53b7579f77SDag-Erling Smørgrav #include "util/module.h"
54b7579f77SDag-Erling Smørgrav #include "util/regional.h"
55e86b9096SDag-Erling Smørgrav #include "util/config_file.h"
5609a3aaf3SDag-Erling Smørgrav #include "sldns/parseutil.h"
5709a3aaf3SDag-Erling Smørgrav #include "sldns/wire2str.h"
589cf5bc93SCy Schubert #include "sldns/str2wire.h"
59b7579f77SDag-Erling Smørgrav #include <fcntl.h>
608ed2b524SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_SSL_H
61b7579f77SDag-Erling Smørgrav #include <openssl/ssl.h>
62e86b9096SDag-Erling Smørgrav #include <openssl/evp.h>
63e86b9096SDag-Erling Smørgrav #include <openssl/rand.h>
648ed2b524SDag-Erling Smørgrav #endif
658ed2b524SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_ERR_H
66b7579f77SDag-Erling Smørgrav #include <openssl/err.h>
678ed2b524SDag-Erling Smørgrav #endif
6825039b37SCy Schubert #ifdef HAVE_OPENSSL_CORE_NAMES_H
6925039b37SCy Schubert #include <openssl/core_names.h>
7025039b37SCy Schubert #endif
713bd4df0aSDag-Erling Smørgrav #ifdef USE_WINSOCK
723bd4df0aSDag-Erling Smørgrav #include <wincrypt.h>
733bd4df0aSDag-Erling Smørgrav #endif
74c0caa2e2SCy Schubert #ifdef HAVE_NGHTTP2_NGHTTP2_H
75c0caa2e2SCy Schubert #include <nghttp2/nghttp2.h>
76c0caa2e2SCy Schubert #endif
77b7579f77SDag-Erling Smørgrav 
78b7579f77SDag-Erling Smørgrav /** max length of an IP address (the address portion) that we allow */
79b7579f77SDag-Erling Smørgrav #define MAX_ADDR_STRLEN 128 /* characters */
80b7579f77SDag-Erling Smørgrav /** default value for EDNS ADVERTISED size */
81b7579f77SDag-Erling Smørgrav uint16_t EDNS_ADVERTISED_SIZE = 4096;
82b7579f77SDag-Erling Smørgrav 
83b7579f77SDag-Erling Smørgrav /** minimal responses when positive answer: default is no */
84b7579f77SDag-Erling Smørgrav int MINIMAL_RESPONSES = 0;
85b7579f77SDag-Erling Smørgrav 
8625039b37SCy Schubert /** rrset order roundrobin: default is yes */
8725039b37SCy Schubert int RRSET_ROUNDROBIN = 1;
88b7579f77SDag-Erling Smørgrav 
89e86b9096SDag-Erling Smørgrav /** log tag queries with name instead of 'info' for filtering */
90e86b9096SDag-Erling Smørgrav int LOG_TAG_QUERYREPLY = 0;
91e86b9096SDag-Erling Smørgrav 
92e86b9096SDag-Erling Smørgrav static struct tls_session_ticket_key {
93e86b9096SDag-Erling Smørgrav 	unsigned char *key_name;
94e86b9096SDag-Erling Smørgrav 	unsigned char *aes_key;
95e86b9096SDag-Erling Smørgrav 	unsigned char *hmac_key;
96e86b9096SDag-Erling Smørgrav } *ticket_keys;
97e86b9096SDag-Erling Smørgrav 
98c0caa2e2SCy Schubert #ifdef HAVE_SSL
9925039b37SCy Schubert /**
10025039b37SCy Schubert  * callback TLS session ticket encrypt and decrypt
10125039b37SCy Schubert  * For use with SSL_CTX_set_tlsext_ticket_key_cb or
10225039b37SCy Schubert  * SSL_CTX_set_tlsext_ticket_key_evp_cb
10325039b37SCy Schubert  * @param s: the SSL_CTX to use (from connect_sslctx_create())
10425039b37SCy Schubert  * @param key_name: secret name, 16 bytes
10525039b37SCy Schubert  * @param iv: up to EVP_MAX_IV_LENGTH.
10625039b37SCy Schubert  * @param evp_ctx: the evp cipher context, function sets this.
10725039b37SCy Schubert  * @param hmac_ctx: the hmac context, function sets this.
10825039b37SCy Schubert  * 	with ..key_cb it is of type HMAC_CTX*
10925039b37SCy Schubert  * 	with ..key_evp_cb it is of type EVP_MAC_CTX*
11025039b37SCy Schubert  * @param enc: 1 is encrypt, 0 is decrypt
11125039b37SCy Schubert  * @return 0 on no ticket, 1 for okay, and 2 for okay but renew the ticket
11225039b37SCy Schubert  * 	(the ticket is decrypt only). and <0 for failures.
11325039b37SCy Schubert  */
11425039b37SCy Schubert int tls_session_ticket_key_cb(SSL *s, unsigned char* key_name,
11525039b37SCy Schubert 	unsigned char* iv, EVP_CIPHER_CTX *evp_ctx,
11625039b37SCy Schubert #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
11725039b37SCy Schubert 	EVP_MAC_CTX *hmac_ctx,
11825039b37SCy Schubert #else
11925039b37SCy Schubert 	HMAC_CTX* hmac_ctx,
12025039b37SCy Schubert #endif
12125039b37SCy Schubert 	int enc);
12225039b37SCy Schubert #endif /* HAVE_SSL */
12325039b37SCy Schubert 
124b7579f77SDag-Erling Smørgrav /* returns true is string addr is an ip6 specced address */
125b7579f77SDag-Erling Smørgrav int
126b7579f77SDag-Erling Smørgrav str_is_ip6(const char* str)
127b7579f77SDag-Erling Smørgrav {
128b7579f77SDag-Erling Smørgrav 	if(strchr(str, ':'))
129b7579f77SDag-Erling Smørgrav 		return 1;
130b7579f77SDag-Erling Smørgrav 	else    return 0;
131b7579f77SDag-Erling Smørgrav }
132b7579f77SDag-Erling Smørgrav 
133b7579f77SDag-Erling Smørgrav int
134b7579f77SDag-Erling Smørgrav fd_set_nonblock(int s)
135b7579f77SDag-Erling Smørgrav {
136b7579f77SDag-Erling Smørgrav #ifdef HAVE_FCNTL
137b7579f77SDag-Erling Smørgrav 	int flag;
138b7579f77SDag-Erling Smørgrav 	if((flag = fcntl(s, F_GETFL)) == -1) {
139b7579f77SDag-Erling Smørgrav 		log_err("can't fcntl F_GETFL: %s", strerror(errno));
140b7579f77SDag-Erling Smørgrav 		flag = 0;
141b7579f77SDag-Erling Smørgrav 	}
142b7579f77SDag-Erling Smørgrav 	flag |= O_NONBLOCK;
143b7579f77SDag-Erling Smørgrav 	if(fcntl(s, F_SETFL, flag) == -1) {
144b7579f77SDag-Erling Smørgrav 		log_err("can't fcntl F_SETFL: %s", strerror(errno));
145b7579f77SDag-Erling Smørgrav 		return 0;
146b7579f77SDag-Erling Smørgrav 	}
147b7579f77SDag-Erling Smørgrav #elif defined(HAVE_IOCTLSOCKET)
148b7579f77SDag-Erling Smørgrav 	unsigned long on = 1;
149b7579f77SDag-Erling Smørgrav 	if(ioctlsocket(s, FIONBIO, &on) != 0) {
150b7579f77SDag-Erling Smørgrav 		log_err("can't ioctlsocket FIONBIO on: %s",
151b7579f77SDag-Erling Smørgrav 			wsa_strerror(WSAGetLastError()));
152b7579f77SDag-Erling Smørgrav 	}
153b7579f77SDag-Erling Smørgrav #endif
154b7579f77SDag-Erling Smørgrav 	return 1;
155b7579f77SDag-Erling Smørgrav }
156b7579f77SDag-Erling Smørgrav 
157b7579f77SDag-Erling Smørgrav int
158b7579f77SDag-Erling Smørgrav fd_set_block(int s)
159b7579f77SDag-Erling Smørgrav {
160b7579f77SDag-Erling Smørgrav #ifdef HAVE_FCNTL
161b7579f77SDag-Erling Smørgrav 	int flag;
162b7579f77SDag-Erling Smørgrav 	if((flag = fcntl(s, F_GETFL)) == -1) {
163b7579f77SDag-Erling Smørgrav 		log_err("cannot fcntl F_GETFL: %s", strerror(errno));
164b7579f77SDag-Erling Smørgrav 		flag = 0;
165b7579f77SDag-Erling Smørgrav 	}
166b7579f77SDag-Erling Smørgrav 	flag &= ~O_NONBLOCK;
167b7579f77SDag-Erling Smørgrav 	if(fcntl(s, F_SETFL, flag) == -1) {
168b7579f77SDag-Erling Smørgrav 		log_err("cannot fcntl F_SETFL: %s", strerror(errno));
169b7579f77SDag-Erling Smørgrav 		return 0;
170b7579f77SDag-Erling Smørgrav 	}
171b7579f77SDag-Erling Smørgrav #elif defined(HAVE_IOCTLSOCKET)
172b7579f77SDag-Erling Smørgrav 	unsigned long off = 0;
173b7579f77SDag-Erling Smørgrav 	if(ioctlsocket(s, FIONBIO, &off) != 0) {
174971980c3SDag-Erling Smørgrav 		if(WSAGetLastError() != WSAEINVAL || verbosity >= 4)
175b7579f77SDag-Erling Smørgrav 			log_err("can't ioctlsocket FIONBIO off: %s",
176b7579f77SDag-Erling Smørgrav 				wsa_strerror(WSAGetLastError()));
177b7579f77SDag-Erling Smørgrav 	}
178b7579f77SDag-Erling Smørgrav #endif
179b7579f77SDag-Erling Smørgrav 	return 1;
180b7579f77SDag-Erling Smørgrav }
181b7579f77SDag-Erling Smørgrav 
182b7579f77SDag-Erling Smørgrav int
183b7579f77SDag-Erling Smørgrav is_pow2(size_t num)
184b7579f77SDag-Erling Smørgrav {
185b7579f77SDag-Erling Smørgrav 	if(num == 0) return 1;
186b7579f77SDag-Erling Smørgrav 	return (num & (num-1)) == 0;
187b7579f77SDag-Erling Smørgrav }
188b7579f77SDag-Erling Smørgrav 
189b7579f77SDag-Erling Smørgrav void*
190b7579f77SDag-Erling Smørgrav memdup(void* data, size_t len)
191b7579f77SDag-Erling Smørgrav {
192b7579f77SDag-Erling Smørgrav 	void* d;
193b7579f77SDag-Erling Smørgrav 	if(!data) return NULL;
194b7579f77SDag-Erling Smørgrav 	if(len == 0) return NULL;
195b7579f77SDag-Erling Smørgrav 	d = malloc(len);
196b7579f77SDag-Erling Smørgrav 	if(!d) return NULL;
197b7579f77SDag-Erling Smørgrav 	memcpy(d, data, len);
198b7579f77SDag-Erling Smørgrav 	return d;
199b7579f77SDag-Erling Smørgrav }
200b7579f77SDag-Erling Smørgrav 
201b7579f77SDag-Erling Smørgrav void
202b7579f77SDag-Erling Smørgrav log_addr(enum verbosity_value v, const char* str,
203b7579f77SDag-Erling Smørgrav 	struct sockaddr_storage* addr, socklen_t addrlen)
204b7579f77SDag-Erling Smørgrav {
205b7579f77SDag-Erling Smørgrav 	uint16_t port;
206b7579f77SDag-Erling Smørgrav 	const char* family = "unknown";
207b7579f77SDag-Erling Smørgrav 	char dest[100];
208b7579f77SDag-Erling Smørgrav 	int af = (int)((struct sockaddr_in*)addr)->sin_family;
209b7579f77SDag-Erling Smørgrav 	void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
210b7579f77SDag-Erling Smørgrav 	if(verbosity < v)
211b7579f77SDag-Erling Smørgrav 		return;
212b7579f77SDag-Erling Smørgrav 	switch(af) {
213b7579f77SDag-Erling Smørgrav 		case AF_INET: family="ip4"; break;
214b7579f77SDag-Erling Smørgrav 		case AF_INET6: family="ip6";
215b7579f77SDag-Erling Smørgrav 			sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
216b7579f77SDag-Erling Smørgrav 			break;
2176480faa8SDag-Erling Smørgrav 		case AF_LOCAL:
2186480faa8SDag-Erling Smørgrav 			dest[0]=0;
2196480faa8SDag-Erling Smørgrav 			(void)inet_ntop(af, sinaddr, dest,
2206480faa8SDag-Erling Smørgrav 				(socklen_t)sizeof(dest));
2216480faa8SDag-Erling Smørgrav 			verbose(v, "%s local %s", str, dest);
2226480faa8SDag-Erling Smørgrav 			return; /* do not continue and try to get port */
223b7579f77SDag-Erling Smørgrav 		default: break;
224b7579f77SDag-Erling Smørgrav 	}
225b7579f77SDag-Erling Smørgrav 	if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
22617d15b25SDag-Erling Smørgrav 		(void)strlcpy(dest, "(inet_ntop error)", sizeof(dest));
227b7579f77SDag-Erling Smørgrav 	}
228b7579f77SDag-Erling Smørgrav 	dest[sizeof(dest)-1] = 0;
229b7579f77SDag-Erling Smørgrav 	port = ntohs(((struct sockaddr_in*)addr)->sin_port);
230b7579f77SDag-Erling Smørgrav 	if(verbosity >= 4)
231b7579f77SDag-Erling Smørgrav 		verbose(v, "%s %s %s port %d (len %d)", str, family, dest,
232b7579f77SDag-Erling Smørgrav 			(int)port, (int)addrlen);
233b7579f77SDag-Erling Smørgrav 	else	verbose(v, "%s %s port %d", str, dest, (int)port);
234b7579f77SDag-Erling Smørgrav }
235b7579f77SDag-Erling Smørgrav 
236b7579f77SDag-Erling Smørgrav int
237b7579f77SDag-Erling Smørgrav extstrtoaddr(const char* str, struct sockaddr_storage* addr,
238b7579f77SDag-Erling Smørgrav 	socklen_t* addrlen)
239b7579f77SDag-Erling Smørgrav {
240b7579f77SDag-Erling Smørgrav 	char* s;
241b7579f77SDag-Erling Smørgrav 	int port = UNBOUND_DNS_PORT;
242b7579f77SDag-Erling Smørgrav 	if((s=strchr(str, '@'))) {
243b7579f77SDag-Erling Smørgrav 		char buf[MAX_ADDR_STRLEN];
244b7579f77SDag-Erling Smørgrav 		if(s-str >= MAX_ADDR_STRLEN) {
245b7579f77SDag-Erling Smørgrav 			return 0;
246b7579f77SDag-Erling Smørgrav 		}
24717d15b25SDag-Erling Smørgrav 		(void)strlcpy(buf, str, sizeof(buf));
248b7579f77SDag-Erling Smørgrav 		buf[s-str] = 0;
249b7579f77SDag-Erling Smørgrav 		port = atoi(s+1);
250b7579f77SDag-Erling Smørgrav 		if(port == 0 && strcmp(s+1,"0")!=0) {
251b7579f77SDag-Erling Smørgrav 			return 0;
252b7579f77SDag-Erling Smørgrav 		}
253b7579f77SDag-Erling Smørgrav 		return ipstrtoaddr(buf, port, addr, addrlen);
254b7579f77SDag-Erling Smørgrav 	}
255b7579f77SDag-Erling Smørgrav 	return ipstrtoaddr(str, port, addr, addrlen);
256b7579f77SDag-Erling Smørgrav }
257b7579f77SDag-Erling Smørgrav 
258b7579f77SDag-Erling Smørgrav 
259b7579f77SDag-Erling Smørgrav int
260b7579f77SDag-Erling Smørgrav ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr,
261b7579f77SDag-Erling Smørgrav 	socklen_t* addrlen)
262b7579f77SDag-Erling Smørgrav {
263b7579f77SDag-Erling Smørgrav 	uint16_t p;
264b7579f77SDag-Erling Smørgrav 	if(!ip) return 0;
265b7579f77SDag-Erling Smørgrav 	p = (uint16_t) port;
266b7579f77SDag-Erling Smørgrav 	if(str_is_ip6(ip)) {
267b7579f77SDag-Erling Smørgrav 		char buf[MAX_ADDR_STRLEN];
268b7579f77SDag-Erling Smørgrav 		char* s;
269b7579f77SDag-Erling Smørgrav 		struct sockaddr_in6* sa = (struct sockaddr_in6*)addr;
270b7579f77SDag-Erling Smørgrav 		*addrlen = (socklen_t)sizeof(struct sockaddr_in6);
271b7579f77SDag-Erling Smørgrav 		memset(sa, 0, *addrlen);
272b7579f77SDag-Erling Smørgrav 		sa->sin6_family = AF_INET6;
273b7579f77SDag-Erling Smørgrav 		sa->sin6_port = (in_port_t)htons(p);
274b7579f77SDag-Erling Smørgrav 		if((s=strchr(ip, '%'))) { /* ip6%interface, rfc 4007 */
275b7579f77SDag-Erling Smørgrav 			if(s-ip >= MAX_ADDR_STRLEN)
276b7579f77SDag-Erling Smørgrav 				return 0;
27717d15b25SDag-Erling Smørgrav 			(void)strlcpy(buf, ip, sizeof(buf));
278b7579f77SDag-Erling Smørgrav 			buf[s-ip]=0;
27924e36522SCy Schubert #ifdef HAVE_IF_NAMETOINDEX
28024e36522SCy Schubert 			if (!(sa->sin6_scope_id = if_nametoindex(s+1)))
28124e36522SCy Schubert #endif /* HAVE_IF_NAMETOINDEX */
282b7579f77SDag-Erling Smørgrav 				sa->sin6_scope_id = (uint32_t)atoi(s+1);
283b7579f77SDag-Erling Smørgrav 			ip = buf;
284b7579f77SDag-Erling Smørgrav 		}
285b7579f77SDag-Erling Smørgrav 		if(inet_pton((int)sa->sin6_family, ip, &sa->sin6_addr) <= 0) {
286b7579f77SDag-Erling Smørgrav 			return 0;
287b7579f77SDag-Erling Smørgrav 		}
288b7579f77SDag-Erling Smørgrav 	} else { /* ip4 */
289b7579f77SDag-Erling Smørgrav 		struct sockaddr_in* sa = (struct sockaddr_in*)addr;
290b7579f77SDag-Erling Smørgrav 		*addrlen = (socklen_t)sizeof(struct sockaddr_in);
291b7579f77SDag-Erling Smørgrav 		memset(sa, 0, *addrlen);
292b7579f77SDag-Erling Smørgrav 		sa->sin_family = AF_INET;
293b7579f77SDag-Erling Smørgrav 		sa->sin_port = (in_port_t)htons(p);
294b7579f77SDag-Erling Smørgrav 		if(inet_pton((int)sa->sin_family, ip, &sa->sin_addr) <= 0) {
295b7579f77SDag-Erling Smørgrav 			return 0;
296b7579f77SDag-Erling Smørgrav 		}
297b7579f77SDag-Erling Smørgrav 	}
298b7579f77SDag-Erling Smørgrav 	return 1;
299b7579f77SDag-Erling Smørgrav }
300b7579f77SDag-Erling Smørgrav 
301b7579f77SDag-Erling Smørgrav int netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr,
302b7579f77SDag-Erling Smørgrav         socklen_t* addrlen, int* net)
303b7579f77SDag-Erling Smørgrav {
3040fb34990SDag-Erling Smørgrav 	char buf[64];
3050fb34990SDag-Erling Smørgrav 	char* s;
306b7579f77SDag-Erling Smørgrav 	*net = (str_is_ip6(str)?128:32);
307b7579f77SDag-Erling Smørgrav 	if((s=strchr(str, '/'))) {
308b7579f77SDag-Erling Smørgrav 		if(atoi(s+1) > *net) {
309b7579f77SDag-Erling Smørgrav 			log_err("netblock too large: %s", str);
310b7579f77SDag-Erling Smørgrav 			return 0;
311b7579f77SDag-Erling Smørgrav 		}
312b7579f77SDag-Erling Smørgrav 		*net = atoi(s+1);
313b7579f77SDag-Erling Smørgrav 		if(*net == 0 && strcmp(s+1, "0") != 0) {
314b7579f77SDag-Erling Smørgrav 			log_err("cannot parse netblock: '%s'", str);
315b7579f77SDag-Erling Smørgrav 			return 0;
316b7579f77SDag-Erling Smørgrav 		}
3170fb34990SDag-Erling Smørgrav 		strlcpy(buf, str, sizeof(buf));
3180fb34990SDag-Erling Smørgrav 		s = strchr(buf, '/');
3190fb34990SDag-Erling Smørgrav 		if(s) *s = 0;
3200fb34990SDag-Erling Smørgrav 		s = buf;
321b7579f77SDag-Erling Smørgrav 	}
322b7579f77SDag-Erling Smørgrav 	if(!ipstrtoaddr(s?s:str, port, addr, addrlen)) {
323b7579f77SDag-Erling Smørgrav 		log_err("cannot parse ip address: '%s'", str);
324b7579f77SDag-Erling Smørgrav 		return 0;
325b7579f77SDag-Erling Smørgrav 	}
326b7579f77SDag-Erling Smørgrav 	if(s) {
327b7579f77SDag-Erling Smørgrav 		addr_mask(addr, *addrlen, *net);
328b7579f77SDag-Erling Smørgrav 	}
329b7579f77SDag-Erling Smørgrav 	return 1;
330b7579f77SDag-Erling Smørgrav }
331b7579f77SDag-Erling Smørgrav 
332091e9e46SCy Schubert /* RPZ format address dname to network byte order address */
333091e9e46SCy Schubert static int ipdnametoaddr(uint8_t* dname, size_t dnamelen,
334091e9e46SCy Schubert 	struct sockaddr_storage* addr, socklen_t* addrlen, int* af)
335091e9e46SCy Schubert {
336091e9e46SCy Schubert 	uint8_t* ia;
337f44e67d1SCy Schubert 	int dnamelabs = dname_count_labels(dname);
338091e9e46SCy Schubert 	uint8_t lablen;
339091e9e46SCy Schubert 	char* e = NULL;
340091e9e46SCy Schubert 	int z = 0;
341091e9e46SCy Schubert 	size_t len = 0;
342091e9e46SCy Schubert 	int i;
343091e9e46SCy Schubert 	*af = AF_INET;
344091e9e46SCy Schubert 
345091e9e46SCy Schubert 	/* need 1 byte for label length */
346091e9e46SCy Schubert 	if(dnamelen < 1)
347091e9e46SCy Schubert 		return 0;
348091e9e46SCy Schubert 
349091e9e46SCy Schubert 	if(dnamelabs > 6 ||
350091e9e46SCy Schubert 		dname_has_label(dname, dnamelen, (uint8_t*)"\002zz")) {
351091e9e46SCy Schubert 		*af = AF_INET6;
352091e9e46SCy Schubert 	}
353091e9e46SCy Schubert 	len = *dname;
354091e9e46SCy Schubert 	lablen = *dname++;
355091e9e46SCy Schubert 	i = (*af == AF_INET) ? 3 : 15;
356091e9e46SCy Schubert 	if(*af == AF_INET6) {
357091e9e46SCy Schubert 		struct sockaddr_in6* sa = (struct sockaddr_in6*)addr;
358091e9e46SCy Schubert 		*addrlen = (socklen_t)sizeof(struct sockaddr_in6);
359091e9e46SCy Schubert 		memset(sa, 0, *addrlen);
360091e9e46SCy Schubert 		sa->sin6_family = AF_INET6;
361091e9e46SCy Schubert 		ia = (uint8_t*)&sa->sin6_addr;
362091e9e46SCy Schubert 	} else { /* ip4 */
363091e9e46SCy Schubert 		struct sockaddr_in* sa = (struct sockaddr_in*)addr;
364091e9e46SCy Schubert 		*addrlen = (socklen_t)sizeof(struct sockaddr_in);
365091e9e46SCy Schubert 		memset(sa, 0, *addrlen);
366091e9e46SCy Schubert 		sa->sin_family = AF_INET;
367091e9e46SCy Schubert 		ia = (uint8_t*)&sa->sin_addr;
368091e9e46SCy Schubert 	}
369091e9e46SCy Schubert 	while(lablen && i >= 0 && len <= dnamelen) {
370091e9e46SCy Schubert 		char buff[LDNS_MAX_LABELLEN+1];
371091e9e46SCy Schubert 		uint16_t chunk; /* big enough to not overflow on IPv6 hextet */
372091e9e46SCy Schubert 		if((*af == AF_INET && (lablen > 3 || dnamelabs > 6)) ||
373091e9e46SCy Schubert 			(*af == AF_INET6 && (lablen > 4 || dnamelabs > 10))) {
374091e9e46SCy Schubert 			return 0;
375091e9e46SCy Schubert 		}
376091e9e46SCy Schubert 		if(memcmp(dname, "zz", 2) == 0 && *af == AF_INET6) {
377091e9e46SCy Schubert 			/* Add one or more 0 labels. Address is initialised at
378091e9e46SCy Schubert 			 * 0, so just skip the zero part. */
379091e9e46SCy Schubert 			int zl = 11 - dnamelabs;
380091e9e46SCy Schubert 			if(z || zl < 0)
381091e9e46SCy Schubert 				return 0;
382091e9e46SCy Schubert 			z = 1;
383091e9e46SCy Schubert 			i -= (zl*2);
384091e9e46SCy Schubert 		} else {
385091e9e46SCy Schubert 			memcpy(buff, dname, lablen);
386091e9e46SCy Schubert 			buff[lablen] = '\0';
387091e9e46SCy Schubert 			chunk = strtol(buff, &e, (*af == AF_INET) ? 10 : 16);
388091e9e46SCy Schubert 			if(!e || *e != '\0' || (*af == AF_INET && chunk > 255))
389091e9e46SCy Schubert 				return 0;
390091e9e46SCy Schubert 			if(*af == AF_INET) {
391091e9e46SCy Schubert 				log_assert(i < 4 && i >= 0);
392091e9e46SCy Schubert 				ia[i] = (uint8_t)chunk;
393091e9e46SCy Schubert 				i--;
394091e9e46SCy Schubert 			} else {
395091e9e46SCy Schubert 				log_assert(i < 16 && i >= 1);
396091e9e46SCy Schubert 				/* ia in network byte order */
397091e9e46SCy Schubert 				ia[i-1] = (uint8_t)(chunk >> 8);
398091e9e46SCy Schubert 				ia[i] = (uint8_t)(chunk & 0x00FF);
399091e9e46SCy Schubert 				i -= 2;
400091e9e46SCy Schubert 			}
401091e9e46SCy Schubert 		}
402091e9e46SCy Schubert 		dname += lablen;
403091e9e46SCy Schubert 		lablen = *dname++;
404091e9e46SCy Schubert 		len += lablen;
405091e9e46SCy Schubert 	}
406091e9e46SCy Schubert 	if(i != -1)
407091e9e46SCy Schubert 		/* input too short */
408091e9e46SCy Schubert 		return 0;
409091e9e46SCy Schubert 	return 1;
410091e9e46SCy Schubert }
411091e9e46SCy Schubert 
412091e9e46SCy Schubert int netblockdnametoaddr(uint8_t* dname, size_t dnamelen,
413091e9e46SCy Schubert 	struct sockaddr_storage* addr, socklen_t* addrlen, int* net, int* af)
414091e9e46SCy Schubert {
415091e9e46SCy Schubert 	char buff[3 /* 3 digit netblock */ + 1];
416091e9e46SCy Schubert 	size_t nlablen;
417091e9e46SCy Schubert 	if(dnamelen < 1 || *dname > 3)
418091e9e46SCy Schubert 		/* netblock invalid */
419091e9e46SCy Schubert 		return 0;
420091e9e46SCy Schubert 	nlablen = *dname;
421091e9e46SCy Schubert 
422091e9e46SCy Schubert 	if(dnamelen < 1 + nlablen)
423091e9e46SCy Schubert 		return 0;
424091e9e46SCy Schubert 
425091e9e46SCy Schubert 	memcpy(buff, dname+1, nlablen);
426091e9e46SCy Schubert 	buff[nlablen] = '\0';
427091e9e46SCy Schubert 	*net = atoi(buff);
428091e9e46SCy Schubert 	if(*net == 0 && strcmp(buff, "0") != 0)
429091e9e46SCy Schubert 		return 0;
430091e9e46SCy Schubert 	dname += nlablen;
431091e9e46SCy Schubert 	dname++;
432091e9e46SCy Schubert 	if(!ipdnametoaddr(dname, dnamelen-1-nlablen, addr, addrlen, af))
433091e9e46SCy Schubert 		return 0;
434091e9e46SCy Schubert 	if((*af == AF_INET6 && *net > 128) || (*af == AF_INET && *net > 32))
435091e9e46SCy Schubert 		return 0;
436091e9e46SCy Schubert 	return 1;
437091e9e46SCy Schubert }
438091e9e46SCy Schubert 
4390fb34990SDag-Erling Smørgrav int authextstrtoaddr(char* str, struct sockaddr_storage* addr,
4400fb34990SDag-Erling Smørgrav 	socklen_t* addrlen, char** auth_name)
4410fb34990SDag-Erling Smørgrav {
4420fb34990SDag-Erling Smørgrav 	char* s;
4430fb34990SDag-Erling Smørgrav 	int port = UNBOUND_DNS_PORT;
4440fb34990SDag-Erling Smørgrav 	if((s=strchr(str, '@'))) {
4450fb34990SDag-Erling Smørgrav 		char buf[MAX_ADDR_STRLEN];
4460fb34990SDag-Erling Smørgrav 		size_t len = (size_t)(s-str);
4470fb34990SDag-Erling Smørgrav 		char* hash = strchr(s+1, '#');
4480fb34990SDag-Erling Smørgrav 		if(hash) {
4490fb34990SDag-Erling Smørgrav 			*auth_name = hash+1;
4500fb34990SDag-Erling Smørgrav 		} else {
4510fb34990SDag-Erling Smørgrav 			*auth_name = NULL;
4520fb34990SDag-Erling Smørgrav 		}
4530fb34990SDag-Erling Smørgrav 		if(len >= MAX_ADDR_STRLEN) {
4540fb34990SDag-Erling Smørgrav 			return 0;
4550fb34990SDag-Erling Smørgrav 		}
4560fb34990SDag-Erling Smørgrav 		(void)strlcpy(buf, str, sizeof(buf));
4570fb34990SDag-Erling Smørgrav 		buf[len] = 0;
4580fb34990SDag-Erling Smørgrav 		port = atoi(s+1);
4590fb34990SDag-Erling Smørgrav 		if(port == 0) {
4600fb34990SDag-Erling Smørgrav 			if(!hash && strcmp(s+1,"0")!=0)
4610fb34990SDag-Erling Smørgrav 				return 0;
4620fb34990SDag-Erling Smørgrav 			if(hash && strncmp(s+1,"0#",2)!=0)
4630fb34990SDag-Erling Smørgrav 				return 0;
4640fb34990SDag-Erling Smørgrav 		}
4650fb34990SDag-Erling Smørgrav 		return ipstrtoaddr(buf, port, addr, addrlen);
4660fb34990SDag-Erling Smørgrav 	}
4670fb34990SDag-Erling Smørgrav 	if((s=strchr(str, '#'))) {
4680fb34990SDag-Erling Smørgrav 		char buf[MAX_ADDR_STRLEN];
4690fb34990SDag-Erling Smørgrav 		size_t len = (size_t)(s-str);
4700fb34990SDag-Erling Smørgrav 		if(len >= MAX_ADDR_STRLEN) {
4710fb34990SDag-Erling Smørgrav 			return 0;
4720fb34990SDag-Erling Smørgrav 		}
4730fb34990SDag-Erling Smørgrav 		(void)strlcpy(buf, str, sizeof(buf));
4740fb34990SDag-Erling Smørgrav 		buf[len] = 0;
4750fb34990SDag-Erling Smørgrav 		port = UNBOUND_DNS_OVER_TLS_PORT;
4760fb34990SDag-Erling Smørgrav 		*auth_name = s+1;
4770fb34990SDag-Erling Smørgrav 		return ipstrtoaddr(buf, port, addr, addrlen);
4780fb34990SDag-Erling Smørgrav 	}
4790fb34990SDag-Erling Smørgrav 	*auth_name = NULL;
4800fb34990SDag-Erling Smørgrav 	return ipstrtoaddr(str, port, addr, addrlen);
4810fb34990SDag-Erling Smørgrav }
4820fb34990SDag-Erling Smørgrav 
4839cf5bc93SCy Schubert uint8_t* authextstrtodname(char* str, int* port, char** auth_name)
4849cf5bc93SCy Schubert {
4859cf5bc93SCy Schubert 	char* s;
4869cf5bc93SCy Schubert 	uint8_t* dname;
4879cf5bc93SCy Schubert 	size_t dname_len;
4889cf5bc93SCy Schubert 	*port = UNBOUND_DNS_PORT;
4899cf5bc93SCy Schubert 	*auth_name = NULL;
4909cf5bc93SCy Schubert 	if((s=strchr(str, '@'))) {
4919cf5bc93SCy Schubert 		char* hash = strchr(s+1, '#');
4929cf5bc93SCy Schubert 		if(hash) {
4939cf5bc93SCy Schubert 			*auth_name = hash+1;
4949cf5bc93SCy Schubert 		} else {
4959cf5bc93SCy Schubert 			*auth_name = NULL;
4969cf5bc93SCy Schubert 		}
4979cf5bc93SCy Schubert 		*port = atoi(s+1);
4989cf5bc93SCy Schubert 		if(*port == 0) {
4999cf5bc93SCy Schubert 			if(!hash && strcmp(s+1,"0")!=0)
5009cf5bc93SCy Schubert 				return 0;
5019cf5bc93SCy Schubert 			if(hash && strncmp(s+1,"0#",2)!=0)
5029cf5bc93SCy Schubert 				return 0;
5039cf5bc93SCy Schubert 		}
5049cf5bc93SCy Schubert 		*s = 0;
5059cf5bc93SCy Schubert 		dname = sldns_str2wire_dname(str, &dname_len);
5069cf5bc93SCy Schubert 		*s = '@';
5079cf5bc93SCy Schubert 	} else if((s=strchr(str, '#'))) {
5089cf5bc93SCy Schubert 		*port = UNBOUND_DNS_OVER_TLS_PORT;
5099cf5bc93SCy Schubert 		*auth_name = s+1;
5109cf5bc93SCy Schubert 		*s = 0;
5119cf5bc93SCy Schubert 		dname = sldns_str2wire_dname(str, &dname_len);
5129cf5bc93SCy Schubert 		*s = '#';
5139cf5bc93SCy Schubert 	} else {
5149cf5bc93SCy Schubert 		dname = sldns_str2wire_dname(str, &dname_len);
5159cf5bc93SCy Schubert 	}
5169cf5bc93SCy Schubert 	return dname;
5179cf5bc93SCy Schubert }
5189cf5bc93SCy Schubert 
51957bddd21SDag-Erling Smørgrav /** store port number into sockaddr structure */
52057bddd21SDag-Erling Smørgrav void
52157bddd21SDag-Erling Smørgrav sockaddr_store_port(struct sockaddr_storage* addr, socklen_t addrlen, int port)
52257bddd21SDag-Erling Smørgrav {
52357bddd21SDag-Erling Smørgrav 	if(addr_is_ip6(addr, addrlen)) {
52457bddd21SDag-Erling Smørgrav 		struct sockaddr_in6* sa = (struct sockaddr_in6*)addr;
52557bddd21SDag-Erling Smørgrav 		sa->sin6_port = (in_port_t)htons((uint16_t)port);
52657bddd21SDag-Erling Smørgrav 	} else {
52757bddd21SDag-Erling Smørgrav 		struct sockaddr_in* sa = (struct sockaddr_in*)addr;
52857bddd21SDag-Erling Smørgrav 		sa->sin_port = (in_port_t)htons((uint16_t)port);
52957bddd21SDag-Erling Smørgrav 	}
53057bddd21SDag-Erling Smørgrav }
53157bddd21SDag-Erling Smørgrav 
532b7579f77SDag-Erling Smørgrav void
533b7579f77SDag-Erling Smørgrav log_nametypeclass(enum verbosity_value v, const char* str, uint8_t* name,
534b7579f77SDag-Erling Smørgrav 	uint16_t type, uint16_t dclass)
535b7579f77SDag-Erling Smørgrav {
536b7579f77SDag-Erling Smørgrav 	char buf[LDNS_MAX_DOMAINLEN+1];
537b7579f77SDag-Erling Smørgrav 	char t[12], c[12];
538b7579f77SDag-Erling Smørgrav 	const char *ts, *cs;
539b7579f77SDag-Erling Smørgrav 	if(verbosity < v)
540b7579f77SDag-Erling Smørgrav 		return;
541b7579f77SDag-Erling Smørgrav 	dname_str(name, buf);
542b7579f77SDag-Erling Smørgrav 	if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG";
543b7579f77SDag-Erling Smørgrav 	else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR";
544b7579f77SDag-Erling Smørgrav 	else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR";
545b7579f77SDag-Erling Smørgrav 	else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB";
546b7579f77SDag-Erling Smørgrav 	else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA";
547b7579f77SDag-Erling Smørgrav 	else if(type == LDNS_RR_TYPE_ANY) ts = "ANY";
54817d15b25SDag-Erling Smørgrav 	else if(sldns_rr_descript(type) && sldns_rr_descript(type)->_name)
54917d15b25SDag-Erling Smørgrav 		ts = sldns_rr_descript(type)->_name;
550b7579f77SDag-Erling Smørgrav 	else {
551b7579f77SDag-Erling Smørgrav 		snprintf(t, sizeof(t), "TYPE%d", (int)type);
552b7579f77SDag-Erling Smørgrav 		ts = t;
553b7579f77SDag-Erling Smørgrav 	}
55417d15b25SDag-Erling Smørgrav 	if(sldns_lookup_by_id(sldns_rr_classes, (int)dclass) &&
55517d15b25SDag-Erling Smørgrav 		sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name)
55617d15b25SDag-Erling Smørgrav 		cs = sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name;
557b7579f77SDag-Erling Smørgrav 	else {
558b7579f77SDag-Erling Smørgrav 		snprintf(c, sizeof(c), "CLASS%d", (int)dclass);
559b7579f77SDag-Erling Smørgrav 		cs = c;
560b7579f77SDag-Erling Smørgrav 	}
561b7579f77SDag-Erling Smørgrav 	log_info("%s %s %s %s", str, buf, ts, cs);
562b7579f77SDag-Erling Smørgrav }
563b7579f77SDag-Erling Smørgrav 
564e86b9096SDag-Erling Smørgrav void
565e86b9096SDag-Erling Smørgrav log_query_in(const char* str, uint8_t* name, uint16_t type, uint16_t dclass)
566e86b9096SDag-Erling Smørgrav {
567e86b9096SDag-Erling Smørgrav 	char buf[LDNS_MAX_DOMAINLEN+1];
568e86b9096SDag-Erling Smørgrav 	char t[12], c[12];
569e86b9096SDag-Erling Smørgrav 	const char *ts, *cs;
570e86b9096SDag-Erling Smørgrav 	dname_str(name, buf);
571e86b9096SDag-Erling Smørgrav 	if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG";
572e86b9096SDag-Erling Smørgrav 	else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR";
573e86b9096SDag-Erling Smørgrav 	else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR";
574e86b9096SDag-Erling Smørgrav 	else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB";
575e86b9096SDag-Erling Smørgrav 	else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA";
576e86b9096SDag-Erling Smørgrav 	else if(type == LDNS_RR_TYPE_ANY) ts = "ANY";
577e86b9096SDag-Erling Smørgrav 	else if(sldns_rr_descript(type) && sldns_rr_descript(type)->_name)
578e86b9096SDag-Erling Smørgrav 		ts = sldns_rr_descript(type)->_name;
579e86b9096SDag-Erling Smørgrav 	else {
580e86b9096SDag-Erling Smørgrav 		snprintf(t, sizeof(t), "TYPE%d", (int)type);
581e86b9096SDag-Erling Smørgrav 		ts = t;
582e86b9096SDag-Erling Smørgrav 	}
583e86b9096SDag-Erling Smørgrav 	if(sldns_lookup_by_id(sldns_rr_classes, (int)dclass) &&
584e86b9096SDag-Erling Smørgrav 		sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name)
585e86b9096SDag-Erling Smørgrav 		cs = sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name;
586e86b9096SDag-Erling Smørgrav 	else {
587e86b9096SDag-Erling Smørgrav 		snprintf(c, sizeof(c), "CLASS%d", (int)dclass);
588e86b9096SDag-Erling Smørgrav 		cs = c;
589e86b9096SDag-Erling Smørgrav 	}
590e86b9096SDag-Erling Smørgrav 	if(LOG_TAG_QUERYREPLY)
591e86b9096SDag-Erling Smørgrav 		log_query("%s %s %s %s", str, buf, ts, cs);
592e86b9096SDag-Erling Smørgrav 	else	log_info("%s %s %s %s", str, buf, ts, cs);
593e86b9096SDag-Erling Smørgrav }
594e86b9096SDag-Erling Smørgrav 
595b7579f77SDag-Erling Smørgrav void log_name_addr(enum verbosity_value v, const char* str, uint8_t* zone,
596b7579f77SDag-Erling Smørgrav 	struct sockaddr_storage* addr, socklen_t addrlen)
597b7579f77SDag-Erling Smørgrav {
598b7579f77SDag-Erling Smørgrav 	uint16_t port;
599b7579f77SDag-Erling Smørgrav 	const char* family = "unknown_family ";
600b7579f77SDag-Erling Smørgrav 	char namebuf[LDNS_MAX_DOMAINLEN+1];
601b7579f77SDag-Erling Smørgrav 	char dest[100];
602b7579f77SDag-Erling Smørgrav 	int af = (int)((struct sockaddr_in*)addr)->sin_family;
603b7579f77SDag-Erling Smørgrav 	void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
604b7579f77SDag-Erling Smørgrav 	if(verbosity < v)
605b7579f77SDag-Erling Smørgrav 		return;
606b7579f77SDag-Erling Smørgrav 	switch(af) {
607b7579f77SDag-Erling Smørgrav 		case AF_INET: family=""; break;
608b7579f77SDag-Erling Smørgrav 		case AF_INET6: family="";
609b7579f77SDag-Erling Smørgrav 			sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
610b7579f77SDag-Erling Smørgrav 			break;
61131099b50SDag-Erling Smørgrav 		case AF_LOCAL: family="local "; break;
612b7579f77SDag-Erling Smørgrav 		default: break;
613b7579f77SDag-Erling Smørgrav 	}
614b7579f77SDag-Erling Smørgrav 	if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
61517d15b25SDag-Erling Smørgrav 		(void)strlcpy(dest, "(inet_ntop error)", sizeof(dest));
616b7579f77SDag-Erling Smørgrav 	}
617b7579f77SDag-Erling Smørgrav 	dest[sizeof(dest)-1] = 0;
618b7579f77SDag-Erling Smørgrav 	port = ntohs(((struct sockaddr_in*)addr)->sin_port);
619b7579f77SDag-Erling Smørgrav 	dname_str(zone, namebuf);
620b7579f77SDag-Erling Smørgrav 	if(af != AF_INET && af != AF_INET6)
621b7579f77SDag-Erling Smørgrav 		verbose(v, "%s <%s> %s%s#%d (addrlen %d)",
622b7579f77SDag-Erling Smørgrav 			str, namebuf, family, dest, (int)port, (int)addrlen);
623b7579f77SDag-Erling Smørgrav 	else	verbose(v, "%s <%s> %s%s#%d",
624b7579f77SDag-Erling Smørgrav 			str, namebuf, family, dest, (int)port);
625b7579f77SDag-Erling Smørgrav }
626b7579f77SDag-Erling Smørgrav 
627ff825849SDag-Erling Smørgrav void log_err_addr(const char* str, const char* err,
628ff825849SDag-Erling Smørgrav 	struct sockaddr_storage* addr, socklen_t addrlen)
629ff825849SDag-Erling Smørgrav {
630ff825849SDag-Erling Smørgrav 	uint16_t port;
631ff825849SDag-Erling Smørgrav 	char dest[100];
632ff825849SDag-Erling Smørgrav 	int af = (int)((struct sockaddr_in*)addr)->sin_family;
633ff825849SDag-Erling Smørgrav 	void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
634ff825849SDag-Erling Smørgrav 	if(af == AF_INET6)
635ff825849SDag-Erling Smørgrav 		sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
636ff825849SDag-Erling Smørgrav 	if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
637ff825849SDag-Erling Smørgrav 		(void)strlcpy(dest, "(inet_ntop error)", sizeof(dest));
638ff825849SDag-Erling Smørgrav 	}
639ff825849SDag-Erling Smørgrav 	dest[sizeof(dest)-1] = 0;
640ff825849SDag-Erling Smørgrav 	port = ntohs(((struct sockaddr_in*)addr)->sin_port);
641ff825849SDag-Erling Smørgrav 	if(verbosity >= 4)
642ff825849SDag-Erling Smørgrav 		log_err("%s: %s for %s port %d (len %d)", str, err, dest,
643ff825849SDag-Erling Smørgrav 			(int)port, (int)addrlen);
6444c75e3aaSDag-Erling Smørgrav 	else	log_err("%s: %s for %s port %d", str, err, dest, (int)port);
645ff825849SDag-Erling Smørgrav }
646ff825849SDag-Erling Smørgrav 
647b7579f77SDag-Erling Smørgrav int
648b7579f77SDag-Erling Smørgrav sockaddr_cmp(struct sockaddr_storage* addr1, socklen_t len1,
649b7579f77SDag-Erling Smørgrav 	struct sockaddr_storage* addr2, socklen_t len2)
650b7579f77SDag-Erling Smørgrav {
651b7579f77SDag-Erling Smørgrav 	struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1;
652b7579f77SDag-Erling Smørgrav 	struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2;
653b7579f77SDag-Erling Smørgrav 	struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1;
654b7579f77SDag-Erling Smørgrav 	struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2;
655b7579f77SDag-Erling Smørgrav 	if(len1 < len2)
656b7579f77SDag-Erling Smørgrav 		return -1;
657b7579f77SDag-Erling Smørgrav 	if(len1 > len2)
658b7579f77SDag-Erling Smørgrav 		return 1;
659b7579f77SDag-Erling Smørgrav 	log_assert(len1 == len2);
660b7579f77SDag-Erling Smørgrav 	if( p1_in->sin_family < p2_in->sin_family)
661b7579f77SDag-Erling Smørgrav 		return -1;
662b7579f77SDag-Erling Smørgrav 	if( p1_in->sin_family > p2_in->sin_family)
663b7579f77SDag-Erling Smørgrav 		return 1;
664b7579f77SDag-Erling Smørgrav 	log_assert( p1_in->sin_family == p2_in->sin_family );
665b7579f77SDag-Erling Smørgrav 	/* compare ip4 */
666b7579f77SDag-Erling Smørgrav 	if( p1_in->sin_family == AF_INET ) {
667b7579f77SDag-Erling Smørgrav 		/* just order it, ntohs not required */
668b7579f77SDag-Erling Smørgrav 		if(p1_in->sin_port < p2_in->sin_port)
669b7579f77SDag-Erling Smørgrav 			return -1;
670b7579f77SDag-Erling Smørgrav 		if(p1_in->sin_port > p2_in->sin_port)
671b7579f77SDag-Erling Smørgrav 			return 1;
672b7579f77SDag-Erling Smørgrav 		log_assert(p1_in->sin_port == p2_in->sin_port);
673b7579f77SDag-Erling Smørgrav 		return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE);
674b7579f77SDag-Erling Smørgrav 	} else if (p1_in6->sin6_family == AF_INET6) {
675b7579f77SDag-Erling Smørgrav 		/* just order it, ntohs not required */
676b7579f77SDag-Erling Smørgrav 		if(p1_in6->sin6_port < p2_in6->sin6_port)
677b7579f77SDag-Erling Smørgrav 			return -1;
678b7579f77SDag-Erling Smørgrav 		if(p1_in6->sin6_port > p2_in6->sin6_port)
679b7579f77SDag-Erling Smørgrav 			return 1;
680b7579f77SDag-Erling Smørgrav 		log_assert(p1_in6->sin6_port == p2_in6->sin6_port);
681b7579f77SDag-Erling Smørgrav 		return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr,
682b7579f77SDag-Erling Smørgrav 			INET6_SIZE);
683b7579f77SDag-Erling Smørgrav 	} else {
684b7579f77SDag-Erling Smørgrav 		/* eek unknown type, perform this comparison for sanity. */
685b7579f77SDag-Erling Smørgrav 		return memcmp(addr1, addr2, len1);
686b7579f77SDag-Erling Smørgrav 	}
687b7579f77SDag-Erling Smørgrav }
688b7579f77SDag-Erling Smørgrav 
689b7579f77SDag-Erling Smørgrav int
690b7579f77SDag-Erling Smørgrav sockaddr_cmp_addr(struct sockaddr_storage* addr1, socklen_t len1,
691b7579f77SDag-Erling Smørgrav 	struct sockaddr_storage* addr2, socklen_t len2)
692b7579f77SDag-Erling Smørgrav {
693b7579f77SDag-Erling Smørgrav 	struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1;
694b7579f77SDag-Erling Smørgrav 	struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2;
695b7579f77SDag-Erling Smørgrav 	struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1;
696b7579f77SDag-Erling Smørgrav 	struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2;
697b7579f77SDag-Erling Smørgrav 	if(len1 < len2)
698b7579f77SDag-Erling Smørgrav 		return -1;
699b7579f77SDag-Erling Smørgrav 	if(len1 > len2)
700b7579f77SDag-Erling Smørgrav 		return 1;
701b7579f77SDag-Erling Smørgrav 	log_assert(len1 == len2);
702b7579f77SDag-Erling Smørgrav 	if( p1_in->sin_family < p2_in->sin_family)
703b7579f77SDag-Erling Smørgrav 		return -1;
704b7579f77SDag-Erling Smørgrav 	if( p1_in->sin_family > p2_in->sin_family)
705b7579f77SDag-Erling Smørgrav 		return 1;
706b7579f77SDag-Erling Smørgrav 	log_assert( p1_in->sin_family == p2_in->sin_family );
707b7579f77SDag-Erling Smørgrav 	/* compare ip4 */
708b7579f77SDag-Erling Smørgrav 	if( p1_in->sin_family == AF_INET ) {
709b7579f77SDag-Erling Smørgrav 		return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE);
710b7579f77SDag-Erling Smørgrav 	} else if (p1_in6->sin6_family == AF_INET6) {
711b7579f77SDag-Erling Smørgrav 		return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr,
712b7579f77SDag-Erling Smørgrav 			INET6_SIZE);
713b7579f77SDag-Erling Smørgrav 	} else {
714b7579f77SDag-Erling Smørgrav 		/* eek unknown type, perform this comparison for sanity. */
715b7579f77SDag-Erling Smørgrav 		return memcmp(addr1, addr2, len1);
716b7579f77SDag-Erling Smørgrav 	}
717b7579f77SDag-Erling Smørgrav }
718b7579f77SDag-Erling Smørgrav 
719b7579f77SDag-Erling Smørgrav int
720b7579f77SDag-Erling Smørgrav addr_is_ip6(struct sockaddr_storage* addr, socklen_t len)
721b7579f77SDag-Erling Smørgrav {
722b7579f77SDag-Erling Smørgrav 	if(len == (socklen_t)sizeof(struct sockaddr_in6) &&
723b7579f77SDag-Erling Smørgrav 		((struct sockaddr_in6*)addr)->sin6_family == AF_INET6)
724b7579f77SDag-Erling Smørgrav 		return 1;
725b7579f77SDag-Erling Smørgrav 	else    return 0;
726b7579f77SDag-Erling Smørgrav }
727b7579f77SDag-Erling Smørgrav 
728b7579f77SDag-Erling Smørgrav void
729b7579f77SDag-Erling Smørgrav addr_mask(struct sockaddr_storage* addr, socklen_t len, int net)
730b7579f77SDag-Erling Smørgrav {
731b7579f77SDag-Erling Smørgrav 	uint8_t mask[8] = {0x0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe};
732b7579f77SDag-Erling Smørgrav 	int i, max;
733b7579f77SDag-Erling Smørgrav 	uint8_t* s;
734b7579f77SDag-Erling Smørgrav 	if(addr_is_ip6(addr, len)) {
735b7579f77SDag-Erling Smørgrav 		s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr;
736b7579f77SDag-Erling Smørgrav 		max = 128;
737b7579f77SDag-Erling Smørgrav 	} else {
738b7579f77SDag-Erling Smørgrav 		s = (uint8_t*)&((struct sockaddr_in*)addr)->sin_addr;
739b7579f77SDag-Erling Smørgrav 		max = 32;
740b7579f77SDag-Erling Smørgrav 	}
741b7579f77SDag-Erling Smørgrav 	if(net >= max)
742b7579f77SDag-Erling Smørgrav 		return;
743b7579f77SDag-Erling Smørgrav 	for(i=net/8+1; i<max/8; i++) {
744b7579f77SDag-Erling Smørgrav 		s[i] = 0;
745b7579f77SDag-Erling Smørgrav 	}
746b7579f77SDag-Erling Smørgrav 	s[net/8] &= mask[net&0x7];
747b7579f77SDag-Erling Smørgrav }
748b7579f77SDag-Erling Smørgrav 
749b7579f77SDag-Erling Smørgrav int
750b7579f77SDag-Erling Smørgrav addr_in_common(struct sockaddr_storage* addr1, int net1,
751b7579f77SDag-Erling Smørgrav 	struct sockaddr_storage* addr2, int net2, socklen_t addrlen)
752b7579f77SDag-Erling Smørgrav {
753b7579f77SDag-Erling Smørgrav 	int min = (net1<net2)?net1:net2;
754b7579f77SDag-Erling Smørgrav 	int i, to;
755b7579f77SDag-Erling Smørgrav 	int match = 0;
756b7579f77SDag-Erling Smørgrav 	uint8_t* s1, *s2;
757b7579f77SDag-Erling Smørgrav 	if(addr_is_ip6(addr1, addrlen)) {
758b7579f77SDag-Erling Smørgrav 		s1 = (uint8_t*)&((struct sockaddr_in6*)addr1)->sin6_addr;
759b7579f77SDag-Erling Smørgrav 		s2 = (uint8_t*)&((struct sockaddr_in6*)addr2)->sin6_addr;
760b7579f77SDag-Erling Smørgrav 		to = 16;
761b7579f77SDag-Erling Smørgrav 	} else {
762b7579f77SDag-Erling Smørgrav 		s1 = (uint8_t*)&((struct sockaddr_in*)addr1)->sin_addr;
763b7579f77SDag-Erling Smørgrav 		s2 = (uint8_t*)&((struct sockaddr_in*)addr2)->sin_addr;
764b7579f77SDag-Erling Smørgrav 		to = 4;
765b7579f77SDag-Erling Smørgrav 	}
766b7579f77SDag-Erling Smørgrav 	/* match = bits_in_common(s1, s2, to); */
767b7579f77SDag-Erling Smørgrav 	for(i=0; i<to; i++) {
768b7579f77SDag-Erling Smørgrav 		if(s1[i] == s2[i]) {
769b7579f77SDag-Erling Smørgrav 			match += 8;
770b7579f77SDag-Erling Smørgrav 		} else {
771b7579f77SDag-Erling Smørgrav 			uint8_t z = s1[i]^s2[i];
772b7579f77SDag-Erling Smørgrav 			log_assert(z);
773b7579f77SDag-Erling Smørgrav 			while(!(z&0x80)) {
774b7579f77SDag-Erling Smørgrav 				match++;
775b7579f77SDag-Erling Smørgrav 				z<<=1;
776b7579f77SDag-Erling Smørgrav 			}
777b7579f77SDag-Erling Smørgrav 			break;
778b7579f77SDag-Erling Smørgrav 		}
779b7579f77SDag-Erling Smørgrav 	}
780b7579f77SDag-Erling Smørgrav 	if(match > min) match = min;
781b7579f77SDag-Erling Smørgrav 	return match;
782b7579f77SDag-Erling Smørgrav }
783b7579f77SDag-Erling Smørgrav 
784b7579f77SDag-Erling Smørgrav void
785b7579f77SDag-Erling Smørgrav addr_to_str(struct sockaddr_storage* addr, socklen_t addrlen,
786b7579f77SDag-Erling Smørgrav 	char* buf, size_t len)
787b7579f77SDag-Erling Smørgrav {
788b7579f77SDag-Erling Smørgrav 	int af = (int)((struct sockaddr_in*)addr)->sin_family;
789b7579f77SDag-Erling Smørgrav 	void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
790b7579f77SDag-Erling Smørgrav 	if(addr_is_ip6(addr, addrlen))
791b7579f77SDag-Erling Smørgrav 		sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
792b7579f77SDag-Erling Smørgrav 	if(inet_ntop(af, sinaddr, buf, (socklen_t)len) == 0) {
793b7579f77SDag-Erling Smørgrav 		snprintf(buf, len, "(inet_ntop_error)");
794b7579f77SDag-Erling Smørgrav 	}
795b7579f77SDag-Erling Smørgrav }
796b7579f77SDag-Erling Smørgrav 
797b7579f77SDag-Erling Smørgrav int
798b7579f77SDag-Erling Smørgrav addr_is_ip4mapped(struct sockaddr_storage* addr, socklen_t addrlen)
799b7579f77SDag-Erling Smørgrav {
800b7579f77SDag-Erling Smørgrav 	/* prefix for ipv4 into ipv6 mapping is ::ffff:x.x.x.x */
801b7579f77SDag-Erling Smørgrav 	const uint8_t map_prefix[16] =
802b7579f77SDag-Erling Smørgrav 		{0,0,0,0,  0,0,0,0, 0,0,0xff,0xff, 0,0,0,0};
803b7579f77SDag-Erling Smørgrav 	uint8_t* s;
804b7579f77SDag-Erling Smørgrav 	if(!addr_is_ip6(addr, addrlen))
805b7579f77SDag-Erling Smørgrav 		return 0;
806b7579f77SDag-Erling Smørgrav 	/* s is 16 octet ipv6 address string */
807b7579f77SDag-Erling Smørgrav 	s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr;
808b7579f77SDag-Erling Smørgrav 	return (memcmp(s, map_prefix, 12) == 0);
809b7579f77SDag-Erling Smørgrav }
810b7579f77SDag-Erling Smørgrav 
811b7579f77SDag-Erling Smørgrav int addr_is_broadcast(struct sockaddr_storage* addr, socklen_t addrlen)
812b7579f77SDag-Erling Smørgrav {
813b7579f77SDag-Erling Smørgrav 	int af = (int)((struct sockaddr_in*)addr)->sin_family;
814b7579f77SDag-Erling Smørgrav 	void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
815b7579f77SDag-Erling Smørgrav 	return af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in)
816b7579f77SDag-Erling Smørgrav 		&& memcmp(sinaddr, "\377\377\377\377", 4) == 0;
817b7579f77SDag-Erling Smørgrav }
818b7579f77SDag-Erling Smørgrav 
819b7579f77SDag-Erling Smørgrav int addr_is_any(struct sockaddr_storage* addr, socklen_t addrlen)
820b7579f77SDag-Erling Smørgrav {
821b7579f77SDag-Erling Smørgrav 	int af = (int)((struct sockaddr_in*)addr)->sin_family;
822b7579f77SDag-Erling Smørgrav 	void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
823b7579f77SDag-Erling Smørgrav 	void* sin6addr = &((struct sockaddr_in6*)addr)->sin6_addr;
824b7579f77SDag-Erling Smørgrav 	if(af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in)
825b7579f77SDag-Erling Smørgrav 		&& memcmp(sinaddr, "\000\000\000\000", 4) == 0)
826b7579f77SDag-Erling Smørgrav 		return 1;
827b7579f77SDag-Erling Smørgrav 	else if(af==AF_INET6 && addrlen>=(socklen_t)sizeof(struct sockaddr_in6)
828b7579f77SDag-Erling Smørgrav 		&& memcmp(sin6addr, "\000\000\000\000\000\000\000\000"
829b7579f77SDag-Erling Smørgrav 		"\000\000\000\000\000\000\000\000", 16) == 0)
830b7579f77SDag-Erling Smørgrav 		return 1;
831b7579f77SDag-Erling Smørgrav 	return 0;
832b7579f77SDag-Erling Smørgrav }
833b7579f77SDag-Erling Smørgrav 
834b7579f77SDag-Erling Smørgrav void sock_list_insert(struct sock_list** list, struct sockaddr_storage* addr,
835b7579f77SDag-Erling Smørgrav 	socklen_t len, struct regional* region)
836b7579f77SDag-Erling Smørgrav {
837b7579f77SDag-Erling Smørgrav 	struct sock_list* add = (struct sock_list*)regional_alloc(region,
838b7579f77SDag-Erling Smørgrav 		sizeof(*add) - sizeof(add->addr) + (size_t)len);
839b7579f77SDag-Erling Smørgrav 	if(!add) {
840b7579f77SDag-Erling Smørgrav 		log_err("out of memory in socketlist insert");
841b7579f77SDag-Erling Smørgrav 		return;
842b7579f77SDag-Erling Smørgrav 	}
843b7579f77SDag-Erling Smørgrav 	log_assert(list);
844b7579f77SDag-Erling Smørgrav 	add->next = *list;
845b7579f77SDag-Erling Smørgrav 	add->len = len;
846b7579f77SDag-Erling Smørgrav 	*list = add;
847b7579f77SDag-Erling Smørgrav 	if(len) memmove(&add->addr, addr, len);
848b7579f77SDag-Erling Smørgrav }
849b7579f77SDag-Erling Smørgrav 
850b7579f77SDag-Erling Smørgrav void sock_list_prepend(struct sock_list** list, struct sock_list* add)
851b7579f77SDag-Erling Smørgrav {
852b7579f77SDag-Erling Smørgrav 	struct sock_list* last = add;
853b7579f77SDag-Erling Smørgrav 	if(!last)
854b7579f77SDag-Erling Smørgrav 		return;
855b7579f77SDag-Erling Smørgrav 	while(last->next)
856b7579f77SDag-Erling Smørgrav 		last = last->next;
857b7579f77SDag-Erling Smørgrav 	last->next = *list;
858b7579f77SDag-Erling Smørgrav 	*list = add;
859b7579f77SDag-Erling Smørgrav }
860b7579f77SDag-Erling Smørgrav 
861b7579f77SDag-Erling Smørgrav int sock_list_find(struct sock_list* list, struct sockaddr_storage* addr,
862b7579f77SDag-Erling Smørgrav         socklen_t len)
863b7579f77SDag-Erling Smørgrav {
864b7579f77SDag-Erling Smørgrav 	while(list) {
865b7579f77SDag-Erling Smørgrav 		if(len == list->len) {
866b7579f77SDag-Erling Smørgrav 			if(len == 0 || sockaddr_cmp_addr(addr, len,
867b7579f77SDag-Erling Smørgrav 				&list->addr, list->len) == 0)
868b7579f77SDag-Erling Smørgrav 				return 1;
869b7579f77SDag-Erling Smørgrav 		}
870b7579f77SDag-Erling Smørgrav 		list = list->next;
871b7579f77SDag-Erling Smørgrav 	}
872b7579f77SDag-Erling Smørgrav 	return 0;
873b7579f77SDag-Erling Smørgrav }
874b7579f77SDag-Erling Smørgrav 
875b7579f77SDag-Erling Smørgrav void sock_list_merge(struct sock_list** list, struct regional* region,
876b7579f77SDag-Erling Smørgrav 	struct sock_list* add)
877b7579f77SDag-Erling Smørgrav {
878b7579f77SDag-Erling Smørgrav 	struct sock_list* p;
879b7579f77SDag-Erling Smørgrav 	for(p=add; p; p=p->next) {
880b7579f77SDag-Erling Smørgrav 		if(!sock_list_find(*list, &p->addr, p->len))
881b7579f77SDag-Erling Smørgrav 			sock_list_insert(list, &p->addr, p->len, region);
882b7579f77SDag-Erling Smørgrav 	}
883b7579f77SDag-Erling Smørgrav }
884b7579f77SDag-Erling Smørgrav 
885b7579f77SDag-Erling Smørgrav void
886b7579f77SDag-Erling Smørgrav log_crypto_err(const char* str)
887b7579f77SDag-Erling Smørgrav {
8888ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL
8890eefd307SCy Schubert 	log_crypto_err_code(str, ERR_get_error());
8900eefd307SCy Schubert #else
8910eefd307SCy Schubert 	(void)str;
8920eefd307SCy Schubert #endif /* HAVE_SSL */
8930eefd307SCy Schubert }
8940eefd307SCy Schubert 
8950eefd307SCy Schubert void log_crypto_err_code(const char* str, unsigned long err)
8960eefd307SCy Schubert {
8970eefd307SCy Schubert #ifdef HAVE_SSL
898b7579f77SDag-Erling Smørgrav 	/* error:[error code]:[library name]:[function name]:[reason string] */
899b7579f77SDag-Erling Smørgrav 	char buf[128];
900b7579f77SDag-Erling Smørgrav 	unsigned long e;
9010eefd307SCy Schubert 	ERR_error_string_n(err, buf, sizeof(buf));
902b7579f77SDag-Erling Smørgrav 	log_err("%s crypto %s", str, buf);
903b7579f77SDag-Erling Smørgrav 	while( (e=ERR_get_error()) ) {
904b7579f77SDag-Erling Smørgrav 		ERR_error_string_n(e, buf, sizeof(buf));
905b7579f77SDag-Erling Smørgrav 		log_err("and additionally crypto %s", buf);
906b7579f77SDag-Erling Smørgrav 	}
9078ed2b524SDag-Erling Smørgrav #else
9088ed2b524SDag-Erling Smørgrav 	(void)str;
9090eefd307SCy Schubert 	(void)err;
9108ed2b524SDag-Erling Smørgrav #endif /* HAVE_SSL */
911b7579f77SDag-Erling Smørgrav }
912b7579f77SDag-Erling Smørgrav 
91325039b37SCy Schubert #ifdef HAVE_SSL
91425039b37SCy Schubert /** log certificate details */
91525039b37SCy Schubert void
91625039b37SCy Schubert log_cert(unsigned level, const char* str, void* cert)
91725039b37SCy Schubert {
91825039b37SCy Schubert 	BIO* bio;
91925039b37SCy Schubert 	char nul = 0;
92025039b37SCy Schubert 	char* pp = NULL;
92125039b37SCy Schubert 	long len;
92225039b37SCy Schubert 	if(verbosity < level) return;
92325039b37SCy Schubert 	bio = BIO_new(BIO_s_mem());
92425039b37SCy Schubert 	if(!bio) return;
92525039b37SCy Schubert 	X509_print_ex(bio, (X509*)cert, 0, (unsigned long)-1
92625039b37SCy Schubert 		^(X509_FLAG_NO_SUBJECT
92725039b37SCy Schubert                         |X509_FLAG_NO_ISSUER|X509_FLAG_NO_VALIDITY
92825039b37SCy Schubert 			|X509_FLAG_NO_EXTENSIONS|X509_FLAG_NO_AUX
92925039b37SCy Schubert 			|X509_FLAG_NO_ATTRIBUTES));
93025039b37SCy Schubert 	BIO_write(bio, &nul, (int)sizeof(nul));
93125039b37SCy Schubert 	len = BIO_get_mem_data(bio, &pp);
93225039b37SCy Schubert 	if(len != 0 && pp) {
93324e36522SCy Schubert 		/* reduce size of cert printout */
93424e36522SCy Schubert 		char* s;
93524e36522SCy Schubert 		while((s=strstr(pp, "  "))!=NULL)
93624e36522SCy Schubert 			memmove(s, s+1, strlen(s+1)+1);
93724e36522SCy Schubert 		while((s=strstr(pp, "\t\t"))!=NULL)
93824e36522SCy Schubert 			memmove(s, s+1, strlen(s+1)+1);
93925039b37SCy Schubert 		verbose(level, "%s: \n%s", str, pp);
94025039b37SCy Schubert 	}
94125039b37SCy Schubert 	BIO_free(bio);
94225039b37SCy Schubert }
94325039b37SCy Schubert #endif /* HAVE_SSL */
94425039b37SCy Schubert 
9455469a995SCy Schubert #if defined(HAVE_SSL) && defined(HAVE_NGHTTP2) && defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB)
946c0caa2e2SCy Schubert static int alpn_select_cb(SSL* ATTR_UNUSED(ssl), const unsigned char** out,
947c0caa2e2SCy Schubert 	unsigned char* outlen, const unsigned char* in, unsigned int inlen,
948c0caa2e2SCy Schubert 	void* ATTR_UNUSED(arg))
949c0caa2e2SCy Schubert {
950c0caa2e2SCy Schubert 	int rv = nghttp2_select_next_protocol((unsigned char **)out, outlen, in,
951c0caa2e2SCy Schubert 		inlen);
952c0caa2e2SCy Schubert 	if(rv == -1) {
953c0caa2e2SCy Schubert 		return SSL_TLSEXT_ERR_NOACK;
954c0caa2e2SCy Schubert 	}
955c0caa2e2SCy Schubert 	/* either http/1.1 or h2 selected */
956c0caa2e2SCy Schubert 	return SSL_TLSEXT_ERR_OK;
957c0caa2e2SCy Schubert }
958c0caa2e2SCy Schubert #endif
959c0caa2e2SCy Schubert 
960971980c3SDag-Erling Smørgrav int
961971980c3SDag-Erling Smørgrav listen_sslctx_setup(void* ctxt)
962971980c3SDag-Erling Smørgrav {
963971980c3SDag-Erling Smørgrav #ifdef HAVE_SSL
964971980c3SDag-Erling Smørgrav 	SSL_CTX* ctx = (SSL_CTX*)ctxt;
965971980c3SDag-Erling Smørgrav 	/* no SSLv2, SSLv3 because has defects */
966091e9e46SCy Schubert #if SSL_OP_NO_SSLv2 != 0
967971980c3SDag-Erling Smørgrav 	if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
968971980c3SDag-Erling Smørgrav 		!= SSL_OP_NO_SSLv2){
969971980c3SDag-Erling Smørgrav 		log_crypto_err("could not set SSL_OP_NO_SSLv2");
970971980c3SDag-Erling Smørgrav 		return 0;
971971980c3SDag-Erling Smørgrav 	}
972091e9e46SCy Schubert #endif
973971980c3SDag-Erling Smørgrav 	if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
974971980c3SDag-Erling Smørgrav 		!= SSL_OP_NO_SSLv3){
975971980c3SDag-Erling Smørgrav 		log_crypto_err("could not set SSL_OP_NO_SSLv3");
976971980c3SDag-Erling Smørgrav 		return 0;
977971980c3SDag-Erling Smørgrav 	}
978971980c3SDag-Erling Smørgrav #if defined(SSL_OP_NO_TLSv1) && defined(SSL_OP_NO_TLSv1_1)
979971980c3SDag-Erling Smørgrav 	/* if we have tls 1.1 disable 1.0 */
980971980c3SDag-Erling Smørgrav 	if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1) & SSL_OP_NO_TLSv1)
981971980c3SDag-Erling Smørgrav 		!= SSL_OP_NO_TLSv1){
982971980c3SDag-Erling Smørgrav 		log_crypto_err("could not set SSL_OP_NO_TLSv1");
983971980c3SDag-Erling Smørgrav 		return 0;
984971980c3SDag-Erling Smørgrav 	}
985971980c3SDag-Erling Smørgrav #endif
986971980c3SDag-Erling Smørgrav #if defined(SSL_OP_NO_TLSv1_1) && defined(SSL_OP_NO_TLSv1_2)
987971980c3SDag-Erling Smørgrav 	/* if we have tls 1.2 disable 1.1 */
988971980c3SDag-Erling Smørgrav 	if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_1) & SSL_OP_NO_TLSv1_1)
989971980c3SDag-Erling Smørgrav 		!= SSL_OP_NO_TLSv1_1){
990971980c3SDag-Erling Smørgrav 		log_crypto_err("could not set SSL_OP_NO_TLSv1_1");
991971980c3SDag-Erling Smørgrav 		return 0;
992971980c3SDag-Erling Smørgrav 	}
993971980c3SDag-Erling Smørgrav #endif
9940eefd307SCy Schubert #if defined(SSL_OP_NO_RENEGOTIATION)
9950eefd307SCy Schubert 	/* disable client renegotiation */
9960eefd307SCy Schubert 	if((SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION) &
9970eefd307SCy Schubert 		SSL_OP_NO_RENEGOTIATION) != SSL_OP_NO_RENEGOTIATION) {
9980eefd307SCy Schubert 		log_crypto_err("could not set SSL_OP_NO_RENEGOTIATION");
9990eefd307SCy Schubert 		return 0;
10000eefd307SCy Schubert 	}
10010eefd307SCy Schubert #endif
1002971980c3SDag-Erling Smørgrav #if defined(SHA256_DIGEST_LENGTH) && defined(USE_ECDSA)
100324e36522SCy Schubert 	/* if we detect system-wide crypto policies, use those */
100424e36522SCy Schubert 	if (access( "/etc/crypto-policies/config", F_OK ) != 0 ) {
1005971980c3SDag-Erling Smørgrav 	/* if we have sha256, set the cipher list to have no known vulns */
100657bddd21SDag-Erling Smørgrav 		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"))
1007971980c3SDag-Erling Smørgrav 			log_crypto_err("could not set cipher list with SSL_CTX_set_cipher_list");
100824e36522SCy Schubert 	}
1009971980c3SDag-Erling Smørgrav #endif
1010971980c3SDag-Erling Smørgrav 
1011971980c3SDag-Erling Smørgrav 	if((SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE) &
1012971980c3SDag-Erling Smørgrav 		SSL_OP_CIPHER_SERVER_PREFERENCE) !=
1013971980c3SDag-Erling Smørgrav 		SSL_OP_CIPHER_SERVER_PREFERENCE) {
1014971980c3SDag-Erling Smørgrav 		log_crypto_err("could not set SSL_OP_CIPHER_SERVER_PREFERENCE");
1015971980c3SDag-Erling Smørgrav 		return 0;
1016971980c3SDag-Erling Smørgrav 	}
1017971980c3SDag-Erling Smørgrav 
1018971980c3SDag-Erling Smørgrav #ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL
1019971980c3SDag-Erling Smørgrav 	SSL_CTX_set_security_level(ctx, 0);
1020971980c3SDag-Erling Smørgrav #endif
1021c0caa2e2SCy Schubert #if defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB) && defined(HAVE_NGHTTP2)
1022c0caa2e2SCy Schubert 	SSL_CTX_set_alpn_select_cb(ctx, alpn_select_cb, NULL);
1023c0caa2e2SCy Schubert #endif
1024971980c3SDag-Erling Smørgrav #else
1025971980c3SDag-Erling Smørgrav 	(void)ctxt;
1026971980c3SDag-Erling Smørgrav #endif /* HAVE_SSL */
1027971980c3SDag-Erling Smørgrav 	return 1;
1028971980c3SDag-Erling Smørgrav }
1029971980c3SDag-Erling Smørgrav 
1030971980c3SDag-Erling Smørgrav void
1031971980c3SDag-Erling Smørgrav listen_sslctx_setup_2(void* ctxt)
1032971980c3SDag-Erling Smørgrav {
1033971980c3SDag-Erling Smørgrav #ifdef HAVE_SSL
1034971980c3SDag-Erling Smørgrav 	SSL_CTX* ctx = (SSL_CTX*)ctxt;
1035971980c3SDag-Erling Smørgrav 	(void)ctx;
1036971980c3SDag-Erling Smørgrav #if HAVE_DECL_SSL_CTX_SET_ECDH_AUTO
1037971980c3SDag-Erling Smørgrav 	if(!SSL_CTX_set_ecdh_auto(ctx,1)) {
1038971980c3SDag-Erling Smørgrav 		log_crypto_err("Error in SSL_CTX_ecdh_auto, not enabling ECDHE");
1039971980c3SDag-Erling Smørgrav 	}
1040971980c3SDag-Erling Smørgrav #elif defined(USE_ECDSA)
1041971980c3SDag-Erling Smørgrav 	if(1) {
1042971980c3SDag-Erling Smørgrav 		EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1);
1043971980c3SDag-Erling Smørgrav 		if (!ecdh) {
1044971980c3SDag-Erling Smørgrav 			log_crypto_err("could not find p256, not enabling ECDHE");
1045971980c3SDag-Erling Smørgrav 		} else {
1046971980c3SDag-Erling Smørgrav 			if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh)) {
1047971980c3SDag-Erling Smørgrav 				log_crypto_err("Error in SSL_CTX_set_tmp_ecdh, not enabling ECDHE");
1048971980c3SDag-Erling Smørgrav 			}
1049971980c3SDag-Erling Smørgrav 			EC_KEY_free (ecdh);
1050971980c3SDag-Erling Smørgrav 		}
1051971980c3SDag-Erling Smørgrav 	}
1052971980c3SDag-Erling Smørgrav #endif
1053971980c3SDag-Erling Smørgrav #else
1054971980c3SDag-Erling Smørgrav 	(void)ctxt;
1055971980c3SDag-Erling Smørgrav #endif /* HAVE_SSL */
1056971980c3SDag-Erling Smørgrav }
1057971980c3SDag-Erling Smørgrav 
1058b7579f77SDag-Erling Smørgrav void* listen_sslctx_create(char* key, char* pem, char* verifypem)
1059b7579f77SDag-Erling Smørgrav {
10608ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL
1061b7579f77SDag-Erling Smørgrav 	SSL_CTX* ctx = SSL_CTX_new(SSLv23_server_method());
1062b7579f77SDag-Erling Smørgrav 	if(!ctx) {
1063b7579f77SDag-Erling Smørgrav 		log_crypto_err("could not SSL_CTX_new");
1064b7579f77SDag-Erling Smørgrav 		return NULL;
1065b7579f77SDag-Erling Smørgrav 	}
1066e86b9096SDag-Erling Smørgrav 	if(!key || key[0] == 0) {
1067e86b9096SDag-Erling Smørgrav 		log_err("error: no tls-service-key file specified");
1068e86b9096SDag-Erling Smørgrav 		SSL_CTX_free(ctx);
1069e86b9096SDag-Erling Smørgrav 		return NULL;
1070e86b9096SDag-Erling Smørgrav 	}
1071e86b9096SDag-Erling Smørgrav 	if(!pem || pem[0] == 0) {
1072e86b9096SDag-Erling Smørgrav 		log_err("error: no tls-service-pem file specified");
1073e86b9096SDag-Erling Smørgrav 		SSL_CTX_free(ctx);
1074e86b9096SDag-Erling Smørgrav 		return NULL;
1075e86b9096SDag-Erling Smørgrav 	}
1076971980c3SDag-Erling Smørgrav 	if(!listen_sslctx_setup(ctx)) {
1077ff825849SDag-Erling Smørgrav 		SSL_CTX_free(ctx);
1078ff825849SDag-Erling Smørgrav 		return NULL;
1079ff825849SDag-Erling Smørgrav 	}
1080b75612f8SDag-Erling Smørgrav 	if(!SSL_CTX_use_certificate_chain_file(ctx, pem)) {
1081b7579f77SDag-Erling Smørgrav 		log_err("error for cert file: %s", pem);
1082b75612f8SDag-Erling Smørgrav 		log_crypto_err("error in SSL_CTX use_certificate_chain_file");
1083b7579f77SDag-Erling Smørgrav 		SSL_CTX_free(ctx);
1084b7579f77SDag-Erling Smørgrav 		return NULL;
1085b7579f77SDag-Erling Smørgrav 	}
1086b7579f77SDag-Erling Smørgrav 	if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) {
1087b7579f77SDag-Erling Smørgrav 		log_err("error for private key file: %s", key);
1088b7579f77SDag-Erling Smørgrav 		log_crypto_err("Error in SSL_CTX use_PrivateKey_file");
1089b7579f77SDag-Erling Smørgrav 		SSL_CTX_free(ctx);
1090b7579f77SDag-Erling Smørgrav 		return NULL;
1091b7579f77SDag-Erling Smørgrav 	}
1092b7579f77SDag-Erling Smørgrav 	if(!SSL_CTX_check_private_key(ctx)) {
1093b7579f77SDag-Erling Smørgrav 		log_err("error for key file: %s", key);
1094b7579f77SDag-Erling Smørgrav 		log_crypto_err("Error in SSL_CTX check_private_key");
1095b7579f77SDag-Erling Smørgrav 		SSL_CTX_free(ctx);
1096b7579f77SDag-Erling Smørgrav 		return NULL;
1097b7579f77SDag-Erling Smørgrav 	}
1098971980c3SDag-Erling Smørgrav 	listen_sslctx_setup_2(ctx);
1099b7579f77SDag-Erling Smørgrav 	if(verifypem && verifypem[0]) {
1100b7579f77SDag-Erling Smørgrav 		if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) {
1101b7579f77SDag-Erling Smørgrav 			log_crypto_err("Error in SSL_CTX verify locations");
1102b7579f77SDag-Erling Smørgrav 			SSL_CTX_free(ctx);
1103b7579f77SDag-Erling Smørgrav 			return NULL;
1104b7579f77SDag-Erling Smørgrav 		}
1105b7579f77SDag-Erling Smørgrav 		SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(
1106b7579f77SDag-Erling Smørgrav 			verifypem));
110725039b37SCy Schubert 		SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
1108b7579f77SDag-Erling Smørgrav 	}
1109b7579f77SDag-Erling Smørgrav 	return ctx;
11108ed2b524SDag-Erling Smørgrav #else
11118ed2b524SDag-Erling Smørgrav 	(void)key; (void)pem; (void)verifypem;
11128ed2b524SDag-Erling Smørgrav 	return NULL;
11138ed2b524SDag-Erling Smørgrav #endif
1114b7579f77SDag-Erling Smørgrav }
1115b7579f77SDag-Erling Smørgrav 
11163bd4df0aSDag-Erling Smørgrav #ifdef USE_WINSOCK
11173bd4df0aSDag-Erling Smørgrav /* For windows, the CA trust store is not read by openssl.
11183bd4df0aSDag-Erling Smørgrav    Add code to open the trust store using wincrypt API and add
11193bd4df0aSDag-Erling Smørgrav    the root certs into openssl trust store */
11203bd4df0aSDag-Erling Smørgrav static int
11213bd4df0aSDag-Erling Smørgrav add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx)
11223bd4df0aSDag-Erling Smørgrav {
11233bd4df0aSDag-Erling Smørgrav 	HCERTSTORE      hSystemStore;
11243bd4df0aSDag-Erling Smørgrav 	PCCERT_CONTEXT  pTargetCert = NULL;
11253bd4df0aSDag-Erling Smørgrav 	X509_STORE*	store;
11263bd4df0aSDag-Erling Smørgrav 
11273bd4df0aSDag-Erling Smørgrav 	verbose(VERB_ALGO, "Adding Windows certificates from system root store to CA store");
11283bd4df0aSDag-Erling Smørgrav 
11293bd4df0aSDag-Erling Smørgrav 	/* load just once per context lifetime for this version
11303bd4df0aSDag-Erling Smørgrav 	   TODO: dynamically update CA trust changes as they are available */
11313bd4df0aSDag-Erling Smørgrav 	if (!tls_ctx)
11323bd4df0aSDag-Erling Smørgrav 		return 0;
11333bd4df0aSDag-Erling Smørgrav 
11343bd4df0aSDag-Erling Smørgrav 	/* Call wincrypt's CertOpenStore to open the CA root store. */
11353bd4df0aSDag-Erling Smørgrav 
11363bd4df0aSDag-Erling Smørgrav 	if ((hSystemStore = CertOpenStore(
11373bd4df0aSDag-Erling Smørgrav 		CERT_STORE_PROV_SYSTEM,
11383bd4df0aSDag-Erling Smørgrav 		0,
11393bd4df0aSDag-Erling Smørgrav 		0,
11403bd4df0aSDag-Erling Smørgrav 		/* NOTE: mingw does not have this const: replace with 1 << 16 from code
11413bd4df0aSDag-Erling Smørgrav 		   CERT_SYSTEM_STORE_CURRENT_USER, */
11423bd4df0aSDag-Erling Smørgrav 		1 << 16,
11433bd4df0aSDag-Erling Smørgrav 		L"root")) == 0)
11443bd4df0aSDag-Erling Smørgrav 	{
11453bd4df0aSDag-Erling Smørgrav 		return 0;
11463bd4df0aSDag-Erling Smørgrav 	}
11473bd4df0aSDag-Erling Smørgrav 
11483bd4df0aSDag-Erling Smørgrav 	store = SSL_CTX_get_cert_store(tls_ctx);
11493bd4df0aSDag-Erling Smørgrav 	if (!store)
11503bd4df0aSDag-Erling Smørgrav 		return 0;
11513bd4df0aSDag-Erling Smørgrav 
11523bd4df0aSDag-Erling Smørgrav 	/* failure if the CA store is empty or the call fails */
11533bd4df0aSDag-Erling Smørgrav 	if ((pTargetCert = CertEnumCertificatesInStore(
11543bd4df0aSDag-Erling Smørgrav 		hSystemStore, pTargetCert)) == 0) {
11553bd4df0aSDag-Erling Smørgrav 		verbose(VERB_ALGO, "CA certificate store for Windows is empty.");
11563bd4df0aSDag-Erling Smørgrav 		return 0;
11573bd4df0aSDag-Erling Smørgrav 	}
11583bd4df0aSDag-Erling Smørgrav 	/* iterate over the windows cert store and add to openssl store */
11593bd4df0aSDag-Erling Smørgrav 	do
11603bd4df0aSDag-Erling Smørgrav 	{
11613bd4df0aSDag-Erling Smørgrav 		X509 *cert1 = d2i_X509(NULL,
11623bd4df0aSDag-Erling Smørgrav 			(const unsigned char **)&pTargetCert->pbCertEncoded,
11633bd4df0aSDag-Erling Smørgrav 			pTargetCert->cbCertEncoded);
11643bd4df0aSDag-Erling Smørgrav 		if (!cert1) {
11653bd4df0aSDag-Erling Smørgrav 			/* return error if a cert fails */
11663bd4df0aSDag-Erling Smørgrav 			verbose(VERB_ALGO, "%s %d:%s",
11673bd4df0aSDag-Erling Smørgrav 				"Unable to parse certificate in memory",
11683bd4df0aSDag-Erling Smørgrav 				(int)ERR_get_error(), ERR_error_string(ERR_get_error(), NULL));
11693bd4df0aSDag-Erling Smørgrav 			return 0;
11703bd4df0aSDag-Erling Smørgrav 		}
11713bd4df0aSDag-Erling Smørgrav 		else {
11723bd4df0aSDag-Erling Smørgrav 			/* return error if a cert add to store fails */
11733bd4df0aSDag-Erling Smørgrav 			if (X509_STORE_add_cert(store, cert1) == 0) {
11743bd4df0aSDag-Erling Smørgrav 				unsigned long error = ERR_peek_last_error();
11753bd4df0aSDag-Erling Smørgrav 
11763bd4df0aSDag-Erling Smørgrav 				/* Ignore error X509_R_CERT_ALREADY_IN_HASH_TABLE which means the
11773bd4df0aSDag-Erling Smørgrav 				* certificate is already in the store.  */
11783bd4df0aSDag-Erling Smørgrav 				if(ERR_GET_LIB(error) != ERR_LIB_X509 ||
11793bd4df0aSDag-Erling Smørgrav 				   ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
11803bd4df0aSDag-Erling Smørgrav 					verbose(VERB_ALGO, "%s %d:%s\n",
11813bd4df0aSDag-Erling Smørgrav 					    "Error adding certificate", (int)ERR_get_error(),
11823bd4df0aSDag-Erling Smørgrav 					     ERR_error_string(ERR_get_error(), NULL));
11833bd4df0aSDag-Erling Smørgrav 					X509_free(cert1);
11843bd4df0aSDag-Erling Smørgrav 					return 0;
11853bd4df0aSDag-Erling Smørgrav 				}
11863bd4df0aSDag-Erling Smørgrav 			}
11873bd4df0aSDag-Erling Smørgrav 			X509_free(cert1);
11883bd4df0aSDag-Erling Smørgrav 		}
11893bd4df0aSDag-Erling Smørgrav 	} while ((pTargetCert = CertEnumCertificatesInStore(
11903bd4df0aSDag-Erling Smørgrav 		hSystemStore, pTargetCert)) != 0);
11913bd4df0aSDag-Erling Smørgrav 
11923bd4df0aSDag-Erling Smørgrav 	/* Clean up memory and quit. */
11933bd4df0aSDag-Erling Smørgrav 	if (pTargetCert)
11943bd4df0aSDag-Erling Smørgrav 		CertFreeCertificateContext(pTargetCert);
11953bd4df0aSDag-Erling Smørgrav 	if (hSystemStore)
11963bd4df0aSDag-Erling Smørgrav 	{
11973bd4df0aSDag-Erling Smørgrav 		if (!CertCloseStore(
11983bd4df0aSDag-Erling Smørgrav 			hSystemStore, 0))
11993bd4df0aSDag-Erling Smørgrav 			return 0;
12003bd4df0aSDag-Erling Smørgrav 	}
12013bd4df0aSDag-Erling Smørgrav 	verbose(VERB_ALGO, "Completed adding Windows certificates to CA store successfully");
12023bd4df0aSDag-Erling Smørgrav 	return 1;
12033bd4df0aSDag-Erling Smørgrav }
12043bd4df0aSDag-Erling Smørgrav #endif /* USE_WINSOCK */
12053bd4df0aSDag-Erling Smørgrav 
12063bd4df0aSDag-Erling Smørgrav void* connect_sslctx_create(char* key, char* pem, char* verifypem, int wincert)
1207b7579f77SDag-Erling Smørgrav {
12088ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL
1209b7579f77SDag-Erling Smørgrav 	SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method());
1210b7579f77SDag-Erling Smørgrav 	if(!ctx) {
1211b7579f77SDag-Erling Smørgrav 		log_crypto_err("could not allocate SSL_CTX pointer");
1212b7579f77SDag-Erling Smørgrav 		return NULL;
1213b7579f77SDag-Erling Smørgrav 	}
1214091e9e46SCy Schubert #if SSL_OP_NO_SSLv2 != 0
121505ab2901SDag-Erling Smørgrav 	if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
121605ab2901SDag-Erling Smørgrav 		!= SSL_OP_NO_SSLv2) {
1217b7579f77SDag-Erling Smørgrav 		log_crypto_err("could not set SSL_OP_NO_SSLv2");
1218b7579f77SDag-Erling Smørgrav 		SSL_CTX_free(ctx);
1219b7579f77SDag-Erling Smørgrav 		return NULL;
1220b7579f77SDag-Erling Smørgrav 	}
1221091e9e46SCy Schubert #endif
122205ab2901SDag-Erling Smørgrav 	if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
122305ab2901SDag-Erling Smørgrav 		!= SSL_OP_NO_SSLv3) {
1224ff825849SDag-Erling Smørgrav 		log_crypto_err("could not set SSL_OP_NO_SSLv3");
1225ff825849SDag-Erling Smørgrav 		SSL_CTX_free(ctx);
1226ff825849SDag-Erling Smørgrav 		return NULL;
1227ff825849SDag-Erling Smørgrav 	}
12280eefd307SCy Schubert #if defined(SSL_OP_NO_RENEGOTIATION)
12290eefd307SCy Schubert 	/* disable client renegotiation */
12300eefd307SCy Schubert 	if((SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION) &
12310eefd307SCy Schubert 		SSL_OP_NO_RENEGOTIATION) != SSL_OP_NO_RENEGOTIATION) {
12320eefd307SCy Schubert 		log_crypto_err("could not set SSL_OP_NO_RENEGOTIATION");
123324e36522SCy Schubert 		SSL_CTX_free(ctx);
12340eefd307SCy Schubert 		return 0;
12350eefd307SCy Schubert 	}
12360eefd307SCy Schubert #endif
1237b7579f77SDag-Erling Smørgrav 	if(key && key[0]) {
1238b75612f8SDag-Erling Smørgrav 		if(!SSL_CTX_use_certificate_chain_file(ctx, pem)) {
1239b7579f77SDag-Erling Smørgrav 			log_err("error in client certificate %s", pem);
1240b7579f77SDag-Erling Smørgrav 			log_crypto_err("error in certificate file");
1241b7579f77SDag-Erling Smørgrav 			SSL_CTX_free(ctx);
1242b7579f77SDag-Erling Smørgrav 			return NULL;
1243b7579f77SDag-Erling Smørgrav 		}
1244b7579f77SDag-Erling Smørgrav 		if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) {
1245b7579f77SDag-Erling Smørgrav 			log_err("error in client private key %s", key);
1246b7579f77SDag-Erling Smørgrav 			log_crypto_err("error in key file");
1247b7579f77SDag-Erling Smørgrav 			SSL_CTX_free(ctx);
1248b7579f77SDag-Erling Smørgrav 			return NULL;
1249b7579f77SDag-Erling Smørgrav 		}
1250b7579f77SDag-Erling Smørgrav 		if(!SSL_CTX_check_private_key(ctx)) {
1251b7579f77SDag-Erling Smørgrav 			log_err("error in client key %s", key);
1252b7579f77SDag-Erling Smørgrav 			log_crypto_err("error in SSL_CTX_check_private_key");
1253b7579f77SDag-Erling Smørgrav 			SSL_CTX_free(ctx);
1254b7579f77SDag-Erling Smørgrav 			return NULL;
1255b7579f77SDag-Erling Smørgrav 		}
1256b7579f77SDag-Erling Smørgrav 	}
12573bd4df0aSDag-Erling Smørgrav 	if((verifypem && verifypem[0]) || wincert) {
1258b7579f77SDag-Erling Smørgrav 		if(verifypem && verifypem[0]) {
1259ff825849SDag-Erling Smørgrav 			if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) {
1260b7579f77SDag-Erling Smørgrav 				log_crypto_err("error in SSL_CTX verify");
1261b7579f77SDag-Erling Smørgrav 				SSL_CTX_free(ctx);
1262b7579f77SDag-Erling Smørgrav 				return NULL;
1263b7579f77SDag-Erling Smørgrav 			}
12643bd4df0aSDag-Erling Smørgrav 		}
12653bd4df0aSDag-Erling Smørgrav #ifdef USE_WINSOCK
12663bd4df0aSDag-Erling Smørgrav 		if(wincert) {
12673bd4df0aSDag-Erling Smørgrav 			if(!add_WIN_cacerts_to_openssl_store(ctx)) {
12683bd4df0aSDag-Erling Smørgrav 				log_crypto_err("error in add_WIN_cacerts_to_openssl_store");
12693bd4df0aSDag-Erling Smørgrav 				SSL_CTX_free(ctx);
12703bd4df0aSDag-Erling Smørgrav 				return NULL;
12713bd4df0aSDag-Erling Smørgrav 			}
12723bd4df0aSDag-Erling Smørgrav 		}
12733bd4df0aSDag-Erling Smørgrav #else
1274*a39a5a69SCy Schubert 		if(wincert) {
1275*a39a5a69SCy Schubert 			if(!SSL_CTX_set_default_verify_paths(ctx)) {
1276*a39a5a69SCy Schubert 				log_crypto_err("error in default_verify_paths");
1277*a39a5a69SCy Schubert 				SSL_CTX_free(ctx);
1278*a39a5a69SCy Schubert 				return NULL;
1279*a39a5a69SCy Schubert 			}
1280*a39a5a69SCy Schubert 		}
12813bd4df0aSDag-Erling Smørgrav #endif
1282b7579f77SDag-Erling Smørgrav 		SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
1283b7579f77SDag-Erling Smørgrav 	}
1284b7579f77SDag-Erling Smørgrav 	return ctx;
12858ed2b524SDag-Erling Smørgrav #else
12863bd4df0aSDag-Erling Smørgrav 	(void)key; (void)pem; (void)verifypem; (void)wincert;
12878ed2b524SDag-Erling Smørgrav 	return NULL;
12888ed2b524SDag-Erling Smørgrav #endif
1289b7579f77SDag-Erling Smørgrav }
1290b7579f77SDag-Erling Smørgrav 
1291b7579f77SDag-Erling Smørgrav void* incoming_ssl_fd(void* sslctx, int fd)
1292b7579f77SDag-Erling Smørgrav {
12938ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL
1294b7579f77SDag-Erling Smørgrav 	SSL* ssl = SSL_new((SSL_CTX*)sslctx);
1295b7579f77SDag-Erling Smørgrav 	if(!ssl) {
1296b7579f77SDag-Erling Smørgrav 		log_crypto_err("could not SSL_new");
1297b7579f77SDag-Erling Smørgrav 		return NULL;
1298b7579f77SDag-Erling Smørgrav 	}
1299b7579f77SDag-Erling Smørgrav 	SSL_set_accept_state(ssl);
13000eefd307SCy Schubert 	(void)SSL_set_mode(ssl, (long)SSL_MODE_AUTO_RETRY);
1301b7579f77SDag-Erling Smørgrav 	if(!SSL_set_fd(ssl, fd)) {
1302b7579f77SDag-Erling Smørgrav 		log_crypto_err("could not SSL_set_fd");
1303b7579f77SDag-Erling Smørgrav 		SSL_free(ssl);
1304b7579f77SDag-Erling Smørgrav 		return NULL;
1305b7579f77SDag-Erling Smørgrav 	}
1306b7579f77SDag-Erling Smørgrav 	return ssl;
13078ed2b524SDag-Erling Smørgrav #else
13088ed2b524SDag-Erling Smørgrav 	(void)sslctx; (void)fd;
13098ed2b524SDag-Erling Smørgrav 	return NULL;
13108ed2b524SDag-Erling Smørgrav #endif
1311b7579f77SDag-Erling Smørgrav }
1312b7579f77SDag-Erling Smørgrav 
1313b7579f77SDag-Erling Smørgrav void* outgoing_ssl_fd(void* sslctx, int fd)
1314b7579f77SDag-Erling Smørgrav {
13158ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL
1316b7579f77SDag-Erling Smørgrav 	SSL* ssl = SSL_new((SSL_CTX*)sslctx);
1317b7579f77SDag-Erling Smørgrav 	if(!ssl) {
1318b7579f77SDag-Erling Smørgrav 		log_crypto_err("could not SSL_new");
1319b7579f77SDag-Erling Smørgrav 		return NULL;
1320b7579f77SDag-Erling Smørgrav 	}
1321b7579f77SDag-Erling Smørgrav 	SSL_set_connect_state(ssl);
13220eefd307SCy Schubert 	(void)SSL_set_mode(ssl, (long)SSL_MODE_AUTO_RETRY);
1323b7579f77SDag-Erling Smørgrav 	if(!SSL_set_fd(ssl, fd)) {
1324b7579f77SDag-Erling Smørgrav 		log_crypto_err("could not SSL_set_fd");
1325b7579f77SDag-Erling Smørgrav 		SSL_free(ssl);
1326b7579f77SDag-Erling Smørgrav 		return NULL;
1327b7579f77SDag-Erling Smørgrav 	}
1328b7579f77SDag-Erling Smørgrav 	return ssl;
13298ed2b524SDag-Erling Smørgrav #else
13308ed2b524SDag-Erling Smørgrav 	(void)sslctx; (void)fd;
13318ed2b524SDag-Erling Smørgrav 	return NULL;
13328ed2b524SDag-Erling Smørgrav #endif
1333b7579f77SDag-Erling Smørgrav }
13348ed2b524SDag-Erling Smørgrav 
133525039b37SCy Schubert int check_auth_name_for_ssl(char* auth_name)
133625039b37SCy Schubert {
133725039b37SCy Schubert 	if(!auth_name) return 1;
133825039b37SCy Schubert #if defined(HAVE_SSL) && !defined(HAVE_SSL_SET1_HOST) && !defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
133925039b37SCy Schubert 	log_err("the query has an auth_name %s, but libssl has no call to "
134025039b37SCy Schubert 		"perform TLS authentication.  Remove that name from config "
134125039b37SCy Schubert 		"or upgrade the ssl crypto library.", auth_name);
134225039b37SCy Schubert 	return 0;
134325039b37SCy Schubert #else
134425039b37SCy Schubert 	return 1;
134525039b37SCy Schubert #endif
134625039b37SCy Schubert }
134725039b37SCy Schubert 
134825039b37SCy Schubert /** set the authname on an SSL structure, SSL* ssl */
134925039b37SCy Schubert int set_auth_name_on_ssl(void* ssl, char* auth_name, int use_sni)
135025039b37SCy Schubert {
135125039b37SCy Schubert 	if(!auth_name) return 1;
135225039b37SCy Schubert #ifdef HAVE_SSL
135325039b37SCy Schubert 	if(use_sni) {
135425039b37SCy Schubert 		(void)SSL_set_tlsext_host_name(ssl, auth_name);
135525039b37SCy Schubert 	}
135625039b37SCy Schubert #else
135725039b37SCy Schubert 	(void)ssl;
135825039b37SCy Schubert 	(void)use_sni;
135925039b37SCy Schubert #endif
136025039b37SCy Schubert #ifdef HAVE_SSL_SET1_HOST
136125039b37SCy Schubert 	SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL);
136225039b37SCy Schubert 	/* setting the hostname makes openssl verify the
136325039b37SCy Schubert 	 * host name in the x509 certificate in the
136425039b37SCy Schubert 	 * SSL connection*/
136525039b37SCy Schubert 	if(!SSL_set1_host(ssl, auth_name)) {
136625039b37SCy Schubert 		log_err("SSL_set1_host failed");
136725039b37SCy Schubert 		return 0;
136825039b37SCy Schubert 	}
136925039b37SCy Schubert #elif defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
137025039b37SCy Schubert 	/* openssl 1.0.2 has this function that can be used for
137125039b37SCy Schubert 	 * set1_host like verification */
137225039b37SCy Schubert 	if(auth_name) {
137325039b37SCy Schubert 		X509_VERIFY_PARAM* param = SSL_get0_param(ssl);
137425039b37SCy Schubert #  ifdef X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS
137525039b37SCy Schubert 		X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
137625039b37SCy Schubert #  endif
137725039b37SCy Schubert 		if(!X509_VERIFY_PARAM_set1_host(param, auth_name, strlen(auth_name))) {
137825039b37SCy Schubert 			log_err("X509_VERIFY_PARAM_set1_host failed");
137925039b37SCy Schubert 			return 0;
138025039b37SCy Schubert 		}
138125039b37SCy Schubert 		SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL);
138225039b37SCy Schubert 	}
138325039b37SCy Schubert #else
138425039b37SCy Schubert 	verbose(VERB_ALGO, "the query has an auth_name, but libssl has no call to perform TLS authentication");
138525039b37SCy Schubert #endif /* HAVE_SSL_SET1_HOST */
138625039b37SCy Schubert 	return 1;
138725039b37SCy Schubert }
138825039b37SCy Schubert 
1389b5663de9SDag-Erling Smørgrav #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L
13908ed2b524SDag-Erling Smørgrav /** global lock list for openssl locks */
13913005e0a3SDag-Erling Smørgrav static lock_basic_type *ub_openssl_locks = NULL;
13928ed2b524SDag-Erling Smørgrav 
13938ed2b524SDag-Erling Smørgrav /** callback that gets thread id for openssl */
1394e86b9096SDag-Erling Smørgrav #ifdef HAVE_CRYPTO_THREADID_SET_CALLBACK
1395e86b9096SDag-Erling Smørgrav static void
1396e86b9096SDag-Erling Smørgrav ub_crypto_id_cb(CRYPTO_THREADID *id)
1397e86b9096SDag-Erling Smørgrav {
1398e86b9096SDag-Erling Smørgrav 	CRYPTO_THREADID_set_numeric(id, (unsigned long)log_thread_get());
1399e86b9096SDag-Erling Smørgrav }
1400e86b9096SDag-Erling Smørgrav #else
14018ed2b524SDag-Erling Smørgrav static unsigned long
14028ed2b524SDag-Erling Smørgrav ub_crypto_id_cb(void)
14038ed2b524SDag-Erling Smørgrav {
140409a3aaf3SDag-Erling Smørgrav 	return (unsigned long)log_thread_get();
14058ed2b524SDag-Erling Smørgrav }
1406e86b9096SDag-Erling Smørgrav #endif
14078ed2b524SDag-Erling Smørgrav 
14088ed2b524SDag-Erling Smørgrav static void
14098ed2b524SDag-Erling Smørgrav ub_crypto_lock_cb(int mode, int type, const char *ATTR_UNUSED(file),
14108ed2b524SDag-Erling Smørgrav 	int ATTR_UNUSED(line))
14118ed2b524SDag-Erling Smørgrav {
14128ed2b524SDag-Erling Smørgrav 	if((mode&CRYPTO_LOCK)) {
14138ed2b524SDag-Erling Smørgrav 		lock_basic_lock(&ub_openssl_locks[type]);
14148ed2b524SDag-Erling Smørgrav 	} else {
14158ed2b524SDag-Erling Smørgrav 		lock_basic_unlock(&ub_openssl_locks[type]);
14168ed2b524SDag-Erling Smørgrav 	}
14178ed2b524SDag-Erling Smørgrav }
14188ed2b524SDag-Erling Smørgrav #endif /* OPENSSL_THREADS */
14198ed2b524SDag-Erling Smørgrav 
14208ed2b524SDag-Erling Smørgrav int ub_openssl_lock_init(void)
14218ed2b524SDag-Erling Smørgrav {
1422b5663de9SDag-Erling Smørgrav #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L
14238ed2b524SDag-Erling Smørgrav 	int i;
14243005e0a3SDag-Erling Smørgrav 	ub_openssl_locks = (lock_basic_type*)reallocarray(
14253005e0a3SDag-Erling Smørgrav 		NULL, (size_t)CRYPTO_num_locks(), sizeof(lock_basic_type));
14268ed2b524SDag-Erling Smørgrav 	if(!ub_openssl_locks)
14278ed2b524SDag-Erling Smørgrav 		return 0;
14288ed2b524SDag-Erling Smørgrav 	for(i=0; i<CRYPTO_num_locks(); i++) {
14298ed2b524SDag-Erling Smørgrav 		lock_basic_init(&ub_openssl_locks[i]);
14308ed2b524SDag-Erling Smørgrav 	}
1431e86b9096SDag-Erling Smørgrav #  ifdef HAVE_CRYPTO_THREADID_SET_CALLBACK
1432e86b9096SDag-Erling Smørgrav 	CRYPTO_THREADID_set_callback(&ub_crypto_id_cb);
1433e86b9096SDag-Erling Smørgrav #  else
14348ed2b524SDag-Erling Smørgrav 	CRYPTO_set_id_callback(&ub_crypto_id_cb);
1435e86b9096SDag-Erling Smørgrav #  endif
14368ed2b524SDag-Erling Smørgrav 	CRYPTO_set_locking_callback(&ub_crypto_lock_cb);
14378ed2b524SDag-Erling Smørgrav #endif /* OPENSSL_THREADS */
14388ed2b524SDag-Erling Smørgrav 	return 1;
14398ed2b524SDag-Erling Smørgrav }
14408ed2b524SDag-Erling Smørgrav 
14418ed2b524SDag-Erling Smørgrav void ub_openssl_lock_delete(void)
14428ed2b524SDag-Erling Smørgrav {
1443b5663de9SDag-Erling Smørgrav #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L
14448ed2b524SDag-Erling Smørgrav 	int i;
14458ed2b524SDag-Erling Smørgrav 	if(!ub_openssl_locks)
14468ed2b524SDag-Erling Smørgrav 		return;
1447e86b9096SDag-Erling Smørgrav #  ifdef HAVE_CRYPTO_THREADID_SET_CALLBACK
1448e86b9096SDag-Erling Smørgrav 	CRYPTO_THREADID_set_callback(NULL);
1449e86b9096SDag-Erling Smørgrav #  else
14508ed2b524SDag-Erling Smørgrav 	CRYPTO_set_id_callback(NULL);
1451e86b9096SDag-Erling Smørgrav #  endif
14528ed2b524SDag-Erling Smørgrav 	CRYPTO_set_locking_callback(NULL);
14538ed2b524SDag-Erling Smørgrav 	for(i=0; i<CRYPTO_num_locks(); i++) {
14548ed2b524SDag-Erling Smørgrav 		lock_basic_destroy(&ub_openssl_locks[i]);
14558ed2b524SDag-Erling Smørgrav 	}
14568ed2b524SDag-Erling Smørgrav 	free(ub_openssl_locks);
14578ed2b524SDag-Erling Smørgrav #endif /* OPENSSL_THREADS */
14588ed2b524SDag-Erling Smørgrav }
14598ed2b524SDag-Erling Smørgrav 
1460e86b9096SDag-Erling Smørgrav int listen_sslctx_setup_ticket_keys(void* sslctx, struct config_strlist* tls_session_ticket_keys) {
1461e86b9096SDag-Erling Smørgrav #ifdef HAVE_SSL
1462e86b9096SDag-Erling Smørgrav 	size_t s = 1;
1463e86b9096SDag-Erling Smørgrav 	struct config_strlist* p;
1464e86b9096SDag-Erling Smørgrav 	struct tls_session_ticket_key *keys;
1465e86b9096SDag-Erling Smørgrav 	for(p = tls_session_ticket_keys; p; p = p->next) {
1466e86b9096SDag-Erling Smørgrav 		s++;
1467e86b9096SDag-Erling Smørgrav 	}
1468e86b9096SDag-Erling Smørgrav 	keys = calloc(s, sizeof(struct tls_session_ticket_key));
1469091e9e46SCy Schubert 	if(!keys)
1470091e9e46SCy Schubert 		return 0;
1471e86b9096SDag-Erling Smørgrav 	memset(keys, 0, s*sizeof(*keys));
1472e86b9096SDag-Erling Smørgrav 	ticket_keys = keys;
1473e86b9096SDag-Erling Smørgrav 
1474e86b9096SDag-Erling Smørgrav 	for(p = tls_session_ticket_keys; p; p = p->next) {
1475e86b9096SDag-Erling Smørgrav 		size_t n;
1476091e9e46SCy Schubert 		unsigned char *data;
1477091e9e46SCy Schubert 		FILE *f;
1478091e9e46SCy Schubert 
1479091e9e46SCy Schubert 		data = (unsigned char *)malloc(80);
1480091e9e46SCy Schubert 		if(!data)
1481091e9e46SCy Schubert 			return 0;
1482091e9e46SCy Schubert 
148325039b37SCy Schubert 		f = fopen(p->str, "rb");
1484e86b9096SDag-Erling Smørgrav 		if(!f) {
1485e86b9096SDag-Erling Smørgrav 			log_err("could not read tls-session-ticket-key %s: %s", p->str, strerror(errno));
1486e86b9096SDag-Erling Smørgrav 			free(data);
1487e86b9096SDag-Erling Smørgrav 			return 0;
1488e86b9096SDag-Erling Smørgrav 		}
1489e86b9096SDag-Erling Smørgrav 		n = fread(data, 1, 80, f);
1490e86b9096SDag-Erling Smørgrav 		fclose(f);
1491e86b9096SDag-Erling Smørgrav 
1492e86b9096SDag-Erling Smørgrav 		if(n != 80) {
1493e86b9096SDag-Erling Smørgrav 			log_err("tls-session-ticket-key %s is %d bytes, must be 80 bytes", p->str, (int)n);
1494e86b9096SDag-Erling Smørgrav 			free(data);
1495e86b9096SDag-Erling Smørgrav 			return 0;
1496e86b9096SDag-Erling Smørgrav 		}
1497e86b9096SDag-Erling Smørgrav 		verbose(VERB_OPS, "read tls-session-ticket-key: %s", p->str);
1498e86b9096SDag-Erling Smørgrav 
1499e86b9096SDag-Erling Smørgrav 		keys->key_name = data;
1500e86b9096SDag-Erling Smørgrav 		keys->aes_key = data + 16;
1501e86b9096SDag-Erling Smørgrav 		keys->hmac_key = data + 48;
1502e86b9096SDag-Erling Smørgrav 		keys++;
1503e86b9096SDag-Erling Smørgrav 	}
1504e86b9096SDag-Erling Smørgrav 	/* terminate array with NULL key name entry */
1505e86b9096SDag-Erling Smørgrav 	keys->key_name = NULL;
150625039b37SCy Schubert #  ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
150725039b37SCy Schubert 	if(SSL_CTX_set_tlsext_ticket_key_evp_cb(sslctx, tls_session_ticket_key_cb) == 0) {
150825039b37SCy Schubert 		log_err("no support for TLS session ticket");
150925039b37SCy Schubert 		return 0;
151025039b37SCy Schubert 	}
151125039b37SCy Schubert #  else
1512e86b9096SDag-Erling Smørgrav 	if(SSL_CTX_set_tlsext_ticket_key_cb(sslctx, tls_session_ticket_key_cb) == 0) {
1513e86b9096SDag-Erling Smørgrav 		log_err("no support for TLS session ticket");
1514e86b9096SDag-Erling Smørgrav 		return 0;
1515e86b9096SDag-Erling Smørgrav 	}
151625039b37SCy Schubert #  endif
1517e86b9096SDag-Erling Smørgrav 	return 1;
1518e86b9096SDag-Erling Smørgrav #else
1519e86b9096SDag-Erling Smørgrav 	(void)sslctx;
1520e86b9096SDag-Erling Smørgrav 	(void)tls_session_ticket_keys;
1521e86b9096SDag-Erling Smørgrav 	return 0;
1522e86b9096SDag-Erling Smørgrav #endif
1523e86b9096SDag-Erling Smørgrav 
1524e86b9096SDag-Erling Smørgrav }
1525e86b9096SDag-Erling Smørgrav 
152625039b37SCy Schubert #ifdef HAVE_SSL
152725039b37SCy Schubert int tls_session_ticket_key_cb(SSL *ATTR_UNUSED(sslctx), unsigned char* key_name,
152825039b37SCy Schubert 	unsigned char* iv, EVP_CIPHER_CTX *evp_sctx,
152925039b37SCy Schubert #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
153025039b37SCy Schubert 	EVP_MAC_CTX *hmac_ctx,
153125039b37SCy Schubert #else
153225039b37SCy Schubert 	HMAC_CTX* hmac_ctx,
153325039b37SCy Schubert #endif
153425039b37SCy Schubert 	int enc)
1535e86b9096SDag-Erling Smørgrav {
1536e86b9096SDag-Erling Smørgrav #ifdef HAVE_SSL
153725039b37SCy Schubert #  ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
153825039b37SCy Schubert 	OSSL_PARAM params[3];
153925039b37SCy Schubert #  else
1540e86b9096SDag-Erling Smørgrav 	const EVP_MD *digest;
154125039b37SCy Schubert #  endif
1542e86b9096SDag-Erling Smørgrav 	const EVP_CIPHER *cipher;
1543e86b9096SDag-Erling Smørgrav 	int evp_cipher_length;
154425039b37SCy Schubert #  ifndef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
1545e86b9096SDag-Erling Smørgrav 	digest = EVP_sha256();
154625039b37SCy Schubert #  endif
1547e86b9096SDag-Erling Smørgrav 	cipher = EVP_aes_256_cbc();
1548e86b9096SDag-Erling Smørgrav 	evp_cipher_length = EVP_CIPHER_iv_length(cipher);
1549e86b9096SDag-Erling Smørgrav 	if( enc == 1 ) {
1550e86b9096SDag-Erling Smørgrav 		/* encrypt */
1551e86b9096SDag-Erling Smørgrav 		verbose(VERB_CLIENT, "start session encrypt");
1552e86b9096SDag-Erling Smørgrav 		memcpy(key_name, ticket_keys->key_name, 16);
1553e86b9096SDag-Erling Smørgrav 		if (RAND_bytes(iv, evp_cipher_length) != 1) {
1554e86b9096SDag-Erling Smørgrav 			verbose(VERB_CLIENT, "RAND_bytes failed");
1555e86b9096SDag-Erling Smørgrav 			return -1;
1556e86b9096SDag-Erling Smørgrav 		}
1557e86b9096SDag-Erling Smørgrav 		if (EVP_EncryptInit_ex(evp_sctx, cipher, NULL, ticket_keys->aes_key, iv) != 1) {
1558e86b9096SDag-Erling Smørgrav 			verbose(VERB_CLIENT, "EVP_EncryptInit_ex failed");
1559e86b9096SDag-Erling Smørgrav 			return -1;
1560e86b9096SDag-Erling Smørgrav 		}
156125039b37SCy Schubert #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
156225039b37SCy Schubert 		params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
156325039b37SCy Schubert 			ticket_keys->hmac_key, 32);
156425039b37SCy Schubert 		params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
156525039b37SCy Schubert 			"sha256", 0);
156625039b37SCy Schubert 		params[2] = OSSL_PARAM_construct_end();
1567c0caa2e2SCy Schubert #ifdef HAVE_EVP_MAC_CTX_SET_PARAMS
1568c0caa2e2SCy Schubert 		EVP_MAC_CTX_set_params(hmac_ctx, params);
1569c0caa2e2SCy Schubert #else
157025039b37SCy Schubert 		EVP_MAC_set_ctx_params(hmac_ctx, params);
1571c0caa2e2SCy Schubert #endif
157225039b37SCy Schubert #elif !defined(HMAC_INIT_EX_RETURNS_VOID)
1573e86b9096SDag-Erling Smørgrav 		if (HMAC_Init_ex(hmac_ctx, ticket_keys->hmac_key, 32, digest, NULL) != 1) {
1574e86b9096SDag-Erling Smørgrav 			verbose(VERB_CLIENT, "HMAC_Init_ex failed");
1575e86b9096SDag-Erling Smørgrav 			return -1;
1576e86b9096SDag-Erling Smørgrav 		}
15770eefd307SCy Schubert #else
15780eefd307SCy Schubert 		HMAC_Init_ex(hmac_ctx, ticket_keys->hmac_key, 32, digest, NULL);
15790eefd307SCy Schubert #endif
1580e86b9096SDag-Erling Smørgrav 		return 1;
1581e86b9096SDag-Erling Smørgrav 	} else if (enc == 0) {
1582e86b9096SDag-Erling Smørgrav 		/* decrypt */
1583e86b9096SDag-Erling Smørgrav 		struct tls_session_ticket_key *key;
1584e86b9096SDag-Erling Smørgrav 		verbose(VERB_CLIENT, "start session decrypt");
1585e86b9096SDag-Erling Smørgrav 		for(key = ticket_keys; key->key_name != NULL; key++) {
1586e86b9096SDag-Erling Smørgrav 			if (!memcmp(key_name, key->key_name, 16)) {
1587e86b9096SDag-Erling Smørgrav 				verbose(VERB_CLIENT, "Found session_key");
1588e86b9096SDag-Erling Smørgrav 				break;
1589e86b9096SDag-Erling Smørgrav 			}
1590e86b9096SDag-Erling Smørgrav 		}
1591e86b9096SDag-Erling Smørgrav 		if(key->key_name == NULL) {
1592e86b9096SDag-Erling Smørgrav 			verbose(VERB_CLIENT, "Not found session_key");
1593e86b9096SDag-Erling Smørgrav 			return 0;
1594e86b9096SDag-Erling Smørgrav 		}
1595e86b9096SDag-Erling Smørgrav 
159625039b37SCy Schubert #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
159725039b37SCy Schubert 		params[0] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
159825039b37SCy Schubert 			key->hmac_key, 32);
159925039b37SCy Schubert 		params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
160025039b37SCy Schubert 			"sha256", 0);
160125039b37SCy Schubert 		params[2] = OSSL_PARAM_construct_end();
1602c0caa2e2SCy Schubert #ifdef HAVE_EVP_MAC_CTX_SET_PARAMS
1603c0caa2e2SCy Schubert 		EVP_MAC_CTX_set_params(hmac_ctx, params);
1604c0caa2e2SCy Schubert #else
160525039b37SCy Schubert 		EVP_MAC_set_ctx_params(hmac_ctx, params);
1606c0caa2e2SCy Schubert #endif
160725039b37SCy Schubert #elif !defined(HMAC_INIT_EX_RETURNS_VOID)
1608e86b9096SDag-Erling Smørgrav 		if (HMAC_Init_ex(hmac_ctx, key->hmac_key, 32, digest, NULL) != 1) {
1609e86b9096SDag-Erling Smørgrav 			verbose(VERB_CLIENT, "HMAC_Init_ex failed");
1610e86b9096SDag-Erling Smørgrav 			return -1;
1611e86b9096SDag-Erling Smørgrav 		}
16120eefd307SCy Schubert #else
16130eefd307SCy Schubert 		HMAC_Init_ex(hmac_ctx, key->hmac_key, 32, digest, NULL);
16140eefd307SCy Schubert #endif
1615e86b9096SDag-Erling Smørgrav 		if (EVP_DecryptInit_ex(evp_sctx, cipher, NULL, key->aes_key, iv) != 1) {
1616e86b9096SDag-Erling Smørgrav 			log_err("EVP_DecryptInit_ex failed");
1617e86b9096SDag-Erling Smørgrav 			return -1;
1618e86b9096SDag-Erling Smørgrav 		}
1619e86b9096SDag-Erling Smørgrav 
1620e86b9096SDag-Erling Smørgrav 		return (key == ticket_keys) ? 1 : 2;
1621e86b9096SDag-Erling Smørgrav 	}
1622e86b9096SDag-Erling Smørgrav 	return -1;
1623e86b9096SDag-Erling Smørgrav #else
1624e86b9096SDag-Erling Smørgrav 	(void)key_name;
1625e86b9096SDag-Erling Smørgrav 	(void)iv;
1626e86b9096SDag-Erling Smørgrav 	(void)evp_sctx;
1627e86b9096SDag-Erling Smørgrav 	(void)hmac_ctx;
1628e86b9096SDag-Erling Smørgrav 	(void)enc;
1629e86b9096SDag-Erling Smørgrav 	return 0;
1630e86b9096SDag-Erling Smørgrav #endif
1631e86b9096SDag-Erling Smørgrav }
163225039b37SCy Schubert #endif /* HAVE_SSL */
1633e86b9096SDag-Erling Smørgrav 
1634e86b9096SDag-Erling Smørgrav void
1635e86b9096SDag-Erling Smørgrav listen_sslctx_delete_ticket_keys(void)
1636e86b9096SDag-Erling Smørgrav {
1637e86b9096SDag-Erling Smørgrav 	struct tls_session_ticket_key *key;
1638e86b9096SDag-Erling Smørgrav 	if(!ticket_keys) return;
1639e86b9096SDag-Erling Smørgrav 	for(key = ticket_keys; key->key_name != NULL; key++) {
1640e86b9096SDag-Erling Smørgrav 		/* wipe key data from memory*/
1641e86b9096SDag-Erling Smørgrav #ifdef HAVE_EXPLICIT_BZERO
1642e86b9096SDag-Erling Smørgrav 		explicit_bzero(key->key_name, 80);
1643e86b9096SDag-Erling Smørgrav #else
1644e86b9096SDag-Erling Smørgrav 		memset(key->key_name, 0xdd, 80);
1645e86b9096SDag-Erling Smørgrav #endif
1646e86b9096SDag-Erling Smørgrav 		free(key->key_name);
1647e86b9096SDag-Erling Smørgrav 	}
1648e86b9096SDag-Erling Smørgrav 	free(ticket_keys);
1649e86b9096SDag-Erling Smørgrav 	ticket_keys = NULL;
1650e86b9096SDag-Erling Smørgrav }
1651c0caa2e2SCy Schubert 
1652c0caa2e2SCy Schubert #  ifndef USE_WINSOCK
1653c0caa2e2SCy Schubert char*
1654c0caa2e2SCy Schubert sock_strerror(int errn)
1655c0caa2e2SCy Schubert {
1656c0caa2e2SCy Schubert 	return strerror(errn);
1657c0caa2e2SCy Schubert }
1658c0caa2e2SCy Schubert 
1659c0caa2e2SCy Schubert void
1660c0caa2e2SCy Schubert sock_close(int socket)
1661c0caa2e2SCy Schubert {
1662c0caa2e2SCy Schubert 	close(socket);
1663c0caa2e2SCy Schubert }
1664c0caa2e2SCy Schubert 
1665c0caa2e2SCy Schubert #  else
1666c0caa2e2SCy Schubert char*
1667c0caa2e2SCy Schubert sock_strerror(int ATTR_UNUSED(errn))
1668c0caa2e2SCy Schubert {
1669c0caa2e2SCy Schubert 	return wsa_strerror(WSAGetLastError());
1670c0caa2e2SCy Schubert }
1671c0caa2e2SCy Schubert 
1672c0caa2e2SCy Schubert void
1673c0caa2e2SCy Schubert sock_close(int socket)
1674c0caa2e2SCy Schubert {
1675c0caa2e2SCy Schubert 	closesocket(socket);
1676c0caa2e2SCy Schubert }
1677c0caa2e2SCy Schubert #  endif /* USE_WINSOCK */
1678