xref: /freebsd/contrib/unbound/util/net_help.c (revision 24e365220007c415f495cf8dcb228ece6002b8b7)
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"
41*24e36522SCy Schubert #ifdef HAVE_SYS_TYPES_H
42*24e36522SCy Schubert #  include <sys/types.h>
43*24e36522SCy Schubert #endif
44*24e36522SCy Schubert #ifdef HAVE_NET_IF_H
45*24e36522SCy Schubert #include <net/if.h>
46*24e36522SCy Schubert #endif
47b7579f77SDag-Erling Smørgrav #include "util/net_help.h"
48b7579f77SDag-Erling Smørgrav #include "util/log.h"
49b7579f77SDag-Erling Smørgrav #include "util/data/dname.h"
50b7579f77SDag-Erling Smørgrav #include "util/module.h"
51b7579f77SDag-Erling Smørgrav #include "util/regional.h"
52e86b9096SDag-Erling Smørgrav #include "util/config_file.h"
5309a3aaf3SDag-Erling Smørgrav #include "sldns/parseutil.h"
5409a3aaf3SDag-Erling Smørgrav #include "sldns/wire2str.h"
55b7579f77SDag-Erling Smørgrav #include <fcntl.h>
568ed2b524SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_SSL_H
57b7579f77SDag-Erling Smørgrav #include <openssl/ssl.h>
58e86b9096SDag-Erling Smørgrav #include <openssl/evp.h>
59e86b9096SDag-Erling Smørgrav #include <openssl/rand.h>
608ed2b524SDag-Erling Smørgrav #endif
618ed2b524SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_ERR_H
62b7579f77SDag-Erling Smørgrav #include <openssl/err.h>
638ed2b524SDag-Erling Smørgrav #endif
6425039b37SCy Schubert #ifdef HAVE_OPENSSL_CORE_NAMES_H
6525039b37SCy Schubert #include <openssl/core_names.h>
6625039b37SCy Schubert #endif
673bd4df0aSDag-Erling Smørgrav #ifdef USE_WINSOCK
683bd4df0aSDag-Erling Smørgrav #include <wincrypt.h>
693bd4df0aSDag-Erling Smørgrav #endif
70c0caa2e2SCy Schubert #ifdef HAVE_NGHTTP2_NGHTTP2_H
71c0caa2e2SCy Schubert #include <nghttp2/nghttp2.h>
72c0caa2e2SCy Schubert #endif
73b7579f77SDag-Erling Smørgrav 
74b7579f77SDag-Erling Smørgrav /** max length of an IP address (the address portion) that we allow */
75b7579f77SDag-Erling Smørgrav #define MAX_ADDR_STRLEN 128 /* characters */
76b7579f77SDag-Erling Smørgrav /** default value for EDNS ADVERTISED size */
77b7579f77SDag-Erling Smørgrav uint16_t EDNS_ADVERTISED_SIZE = 4096;
78b7579f77SDag-Erling Smørgrav 
79b7579f77SDag-Erling Smørgrav /** minimal responses when positive answer: default is no */
80b7579f77SDag-Erling Smørgrav int MINIMAL_RESPONSES = 0;
81b7579f77SDag-Erling Smørgrav 
8225039b37SCy Schubert /** rrset order roundrobin: default is yes */
8325039b37SCy Schubert int RRSET_ROUNDROBIN = 1;
84b7579f77SDag-Erling Smørgrav 
85e86b9096SDag-Erling Smørgrav /** log tag queries with name instead of 'info' for filtering */
86e86b9096SDag-Erling Smørgrav int LOG_TAG_QUERYREPLY = 0;
87e86b9096SDag-Erling Smørgrav 
88e86b9096SDag-Erling Smørgrav static struct tls_session_ticket_key {
89e86b9096SDag-Erling Smørgrav 	unsigned char *key_name;
90e86b9096SDag-Erling Smørgrav 	unsigned char *aes_key;
91e86b9096SDag-Erling Smørgrav 	unsigned char *hmac_key;
92e86b9096SDag-Erling Smørgrav } *ticket_keys;
93e86b9096SDag-Erling Smørgrav 
94c0caa2e2SCy Schubert #ifdef HAVE_SSL
9525039b37SCy Schubert /**
9625039b37SCy Schubert  * callback TLS session ticket encrypt and decrypt
9725039b37SCy Schubert  * For use with SSL_CTX_set_tlsext_ticket_key_cb or
9825039b37SCy Schubert  * SSL_CTX_set_tlsext_ticket_key_evp_cb
9925039b37SCy Schubert  * @param s: the SSL_CTX to use (from connect_sslctx_create())
10025039b37SCy Schubert  * @param key_name: secret name, 16 bytes
10125039b37SCy Schubert  * @param iv: up to EVP_MAX_IV_LENGTH.
10225039b37SCy Schubert  * @param evp_ctx: the evp cipher context, function sets this.
10325039b37SCy Schubert  * @param hmac_ctx: the hmac context, function sets this.
10425039b37SCy Schubert  * 	with ..key_cb it is of type HMAC_CTX*
10525039b37SCy Schubert  * 	with ..key_evp_cb it is of type EVP_MAC_CTX*
10625039b37SCy Schubert  * @param enc: 1 is encrypt, 0 is decrypt
10725039b37SCy Schubert  * @return 0 on no ticket, 1 for okay, and 2 for okay but renew the ticket
10825039b37SCy Schubert  * 	(the ticket is decrypt only). and <0 for failures.
10925039b37SCy Schubert  */
11025039b37SCy Schubert int tls_session_ticket_key_cb(SSL *s, unsigned char* key_name,
11125039b37SCy Schubert 	unsigned char* iv, EVP_CIPHER_CTX *evp_ctx,
11225039b37SCy Schubert #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
11325039b37SCy Schubert 	EVP_MAC_CTX *hmac_ctx,
11425039b37SCy Schubert #else
11525039b37SCy Schubert 	HMAC_CTX* hmac_ctx,
11625039b37SCy Schubert #endif
11725039b37SCy Schubert 	int enc);
11825039b37SCy Schubert #endif /* HAVE_SSL */
11925039b37SCy Schubert 
120b7579f77SDag-Erling Smørgrav /* returns true is string addr is an ip6 specced address */
121b7579f77SDag-Erling Smørgrav int
122b7579f77SDag-Erling Smørgrav str_is_ip6(const char* str)
123b7579f77SDag-Erling Smørgrav {
124b7579f77SDag-Erling Smørgrav 	if(strchr(str, ':'))
125b7579f77SDag-Erling Smørgrav 		return 1;
126b7579f77SDag-Erling Smørgrav 	else    return 0;
127b7579f77SDag-Erling Smørgrav }
128b7579f77SDag-Erling Smørgrav 
129b7579f77SDag-Erling Smørgrav int
130b7579f77SDag-Erling Smørgrav fd_set_nonblock(int s)
131b7579f77SDag-Erling Smørgrav {
132b7579f77SDag-Erling Smørgrav #ifdef HAVE_FCNTL
133b7579f77SDag-Erling Smørgrav 	int flag;
134b7579f77SDag-Erling Smørgrav 	if((flag = fcntl(s, F_GETFL)) == -1) {
135b7579f77SDag-Erling Smørgrav 		log_err("can't fcntl F_GETFL: %s", strerror(errno));
136b7579f77SDag-Erling Smørgrav 		flag = 0;
137b7579f77SDag-Erling Smørgrav 	}
138b7579f77SDag-Erling Smørgrav 	flag |= O_NONBLOCK;
139b7579f77SDag-Erling Smørgrav 	if(fcntl(s, F_SETFL, flag) == -1) {
140b7579f77SDag-Erling Smørgrav 		log_err("can't fcntl F_SETFL: %s", strerror(errno));
141b7579f77SDag-Erling Smørgrav 		return 0;
142b7579f77SDag-Erling Smørgrav 	}
143b7579f77SDag-Erling Smørgrav #elif defined(HAVE_IOCTLSOCKET)
144b7579f77SDag-Erling Smørgrav 	unsigned long on = 1;
145b7579f77SDag-Erling Smørgrav 	if(ioctlsocket(s, FIONBIO, &on) != 0) {
146b7579f77SDag-Erling Smørgrav 		log_err("can't ioctlsocket FIONBIO on: %s",
147b7579f77SDag-Erling Smørgrav 			wsa_strerror(WSAGetLastError()));
148b7579f77SDag-Erling Smørgrav 	}
149b7579f77SDag-Erling Smørgrav #endif
150b7579f77SDag-Erling Smørgrav 	return 1;
151b7579f77SDag-Erling Smørgrav }
152b7579f77SDag-Erling Smørgrav 
153b7579f77SDag-Erling Smørgrav int
154b7579f77SDag-Erling Smørgrav fd_set_block(int s)
155b7579f77SDag-Erling Smørgrav {
156b7579f77SDag-Erling Smørgrav #ifdef HAVE_FCNTL
157b7579f77SDag-Erling Smørgrav 	int flag;
158b7579f77SDag-Erling Smørgrav 	if((flag = fcntl(s, F_GETFL)) == -1) {
159b7579f77SDag-Erling Smørgrav 		log_err("cannot fcntl F_GETFL: %s", strerror(errno));
160b7579f77SDag-Erling Smørgrav 		flag = 0;
161b7579f77SDag-Erling Smørgrav 	}
162b7579f77SDag-Erling Smørgrav 	flag &= ~O_NONBLOCK;
163b7579f77SDag-Erling Smørgrav 	if(fcntl(s, F_SETFL, flag) == -1) {
164b7579f77SDag-Erling Smørgrav 		log_err("cannot fcntl F_SETFL: %s", strerror(errno));
165b7579f77SDag-Erling Smørgrav 		return 0;
166b7579f77SDag-Erling Smørgrav 	}
167b7579f77SDag-Erling Smørgrav #elif defined(HAVE_IOCTLSOCKET)
168b7579f77SDag-Erling Smørgrav 	unsigned long off = 0;
169b7579f77SDag-Erling Smørgrav 	if(ioctlsocket(s, FIONBIO, &off) != 0) {
170971980c3SDag-Erling Smørgrav 		if(WSAGetLastError() != WSAEINVAL || verbosity >= 4)
171b7579f77SDag-Erling Smørgrav 			log_err("can't ioctlsocket FIONBIO off: %s",
172b7579f77SDag-Erling Smørgrav 				wsa_strerror(WSAGetLastError()));
173b7579f77SDag-Erling Smørgrav 	}
174b7579f77SDag-Erling Smørgrav #endif
175b7579f77SDag-Erling Smørgrav 	return 1;
176b7579f77SDag-Erling Smørgrav }
177b7579f77SDag-Erling Smørgrav 
178b7579f77SDag-Erling Smørgrav int
179b7579f77SDag-Erling Smørgrav is_pow2(size_t num)
180b7579f77SDag-Erling Smørgrav {
181b7579f77SDag-Erling Smørgrav 	if(num == 0) return 1;
182b7579f77SDag-Erling Smørgrav 	return (num & (num-1)) == 0;
183b7579f77SDag-Erling Smørgrav }
184b7579f77SDag-Erling Smørgrav 
185b7579f77SDag-Erling Smørgrav void*
186b7579f77SDag-Erling Smørgrav memdup(void* data, size_t len)
187b7579f77SDag-Erling Smørgrav {
188b7579f77SDag-Erling Smørgrav 	void* d;
189b7579f77SDag-Erling Smørgrav 	if(!data) return NULL;
190b7579f77SDag-Erling Smørgrav 	if(len == 0) return NULL;
191b7579f77SDag-Erling Smørgrav 	d = malloc(len);
192b7579f77SDag-Erling Smørgrav 	if(!d) return NULL;
193b7579f77SDag-Erling Smørgrav 	memcpy(d, data, len);
194b7579f77SDag-Erling Smørgrav 	return d;
195b7579f77SDag-Erling Smørgrav }
196b7579f77SDag-Erling Smørgrav 
197b7579f77SDag-Erling Smørgrav void
198b7579f77SDag-Erling Smørgrav log_addr(enum verbosity_value v, const char* str,
199b7579f77SDag-Erling Smørgrav 	struct sockaddr_storage* addr, socklen_t addrlen)
200b7579f77SDag-Erling Smørgrav {
201b7579f77SDag-Erling Smørgrav 	uint16_t port;
202b7579f77SDag-Erling Smørgrav 	const char* family = "unknown";
203b7579f77SDag-Erling Smørgrav 	char dest[100];
204b7579f77SDag-Erling Smørgrav 	int af = (int)((struct sockaddr_in*)addr)->sin_family;
205b7579f77SDag-Erling Smørgrav 	void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
206b7579f77SDag-Erling Smørgrav 	if(verbosity < v)
207b7579f77SDag-Erling Smørgrav 		return;
208b7579f77SDag-Erling Smørgrav 	switch(af) {
209b7579f77SDag-Erling Smørgrav 		case AF_INET: family="ip4"; break;
210b7579f77SDag-Erling Smørgrav 		case AF_INET6: family="ip6";
211b7579f77SDag-Erling Smørgrav 			sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
212b7579f77SDag-Erling Smørgrav 			break;
2136480faa8SDag-Erling Smørgrav 		case AF_LOCAL:
2146480faa8SDag-Erling Smørgrav 			dest[0]=0;
2156480faa8SDag-Erling Smørgrav 			(void)inet_ntop(af, sinaddr, dest,
2166480faa8SDag-Erling Smørgrav 				(socklen_t)sizeof(dest));
2176480faa8SDag-Erling Smørgrav 			verbose(v, "%s local %s", str, dest);
2186480faa8SDag-Erling Smørgrav 			return; /* do not continue and try to get port */
219b7579f77SDag-Erling Smørgrav 		default: break;
220b7579f77SDag-Erling Smørgrav 	}
221b7579f77SDag-Erling Smørgrav 	if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
22217d15b25SDag-Erling Smørgrav 		(void)strlcpy(dest, "(inet_ntop error)", sizeof(dest));
223b7579f77SDag-Erling Smørgrav 	}
224b7579f77SDag-Erling Smørgrav 	dest[sizeof(dest)-1] = 0;
225b7579f77SDag-Erling Smørgrav 	port = ntohs(((struct sockaddr_in*)addr)->sin_port);
226b7579f77SDag-Erling Smørgrav 	if(verbosity >= 4)
227b7579f77SDag-Erling Smørgrav 		verbose(v, "%s %s %s port %d (len %d)", str, family, dest,
228b7579f77SDag-Erling Smørgrav 			(int)port, (int)addrlen);
229b7579f77SDag-Erling Smørgrav 	else	verbose(v, "%s %s port %d", str, dest, (int)port);
230b7579f77SDag-Erling Smørgrav }
231b7579f77SDag-Erling Smørgrav 
232b7579f77SDag-Erling Smørgrav int
233b7579f77SDag-Erling Smørgrav extstrtoaddr(const char* str, struct sockaddr_storage* addr,
234b7579f77SDag-Erling Smørgrav 	socklen_t* addrlen)
235b7579f77SDag-Erling Smørgrav {
236b7579f77SDag-Erling Smørgrav 	char* s;
237b7579f77SDag-Erling Smørgrav 	int port = UNBOUND_DNS_PORT;
238b7579f77SDag-Erling Smørgrav 	if((s=strchr(str, '@'))) {
239b7579f77SDag-Erling Smørgrav 		char buf[MAX_ADDR_STRLEN];
240b7579f77SDag-Erling Smørgrav 		if(s-str >= MAX_ADDR_STRLEN) {
241b7579f77SDag-Erling Smørgrav 			return 0;
242b7579f77SDag-Erling Smørgrav 		}
24317d15b25SDag-Erling Smørgrav 		(void)strlcpy(buf, str, sizeof(buf));
244b7579f77SDag-Erling Smørgrav 		buf[s-str] = 0;
245b7579f77SDag-Erling Smørgrav 		port = atoi(s+1);
246b7579f77SDag-Erling Smørgrav 		if(port == 0 && strcmp(s+1,"0")!=0) {
247b7579f77SDag-Erling Smørgrav 			return 0;
248b7579f77SDag-Erling Smørgrav 		}
249b7579f77SDag-Erling Smørgrav 		return ipstrtoaddr(buf, port, addr, addrlen);
250b7579f77SDag-Erling Smørgrav 	}
251b7579f77SDag-Erling Smørgrav 	return ipstrtoaddr(str, port, addr, addrlen);
252b7579f77SDag-Erling Smørgrav }
253b7579f77SDag-Erling Smørgrav 
254b7579f77SDag-Erling Smørgrav 
255b7579f77SDag-Erling Smørgrav int
256b7579f77SDag-Erling Smørgrav ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr,
257b7579f77SDag-Erling Smørgrav 	socklen_t* addrlen)
258b7579f77SDag-Erling Smørgrav {
259b7579f77SDag-Erling Smørgrav 	uint16_t p;
260b7579f77SDag-Erling Smørgrav 	if(!ip) return 0;
261b7579f77SDag-Erling Smørgrav 	p = (uint16_t) port;
262b7579f77SDag-Erling Smørgrav 	if(str_is_ip6(ip)) {
263b7579f77SDag-Erling Smørgrav 		char buf[MAX_ADDR_STRLEN];
264b7579f77SDag-Erling Smørgrav 		char* s;
265b7579f77SDag-Erling Smørgrav 		struct sockaddr_in6* sa = (struct sockaddr_in6*)addr;
266b7579f77SDag-Erling Smørgrav 		*addrlen = (socklen_t)sizeof(struct sockaddr_in6);
267b7579f77SDag-Erling Smørgrav 		memset(sa, 0, *addrlen);
268b7579f77SDag-Erling Smørgrav 		sa->sin6_family = AF_INET6;
269b7579f77SDag-Erling Smørgrav 		sa->sin6_port = (in_port_t)htons(p);
270b7579f77SDag-Erling Smørgrav 		if((s=strchr(ip, '%'))) { /* ip6%interface, rfc 4007 */
271b7579f77SDag-Erling Smørgrav 			if(s-ip >= MAX_ADDR_STRLEN)
272b7579f77SDag-Erling Smørgrav 				return 0;
27317d15b25SDag-Erling Smørgrav 			(void)strlcpy(buf, ip, sizeof(buf));
274b7579f77SDag-Erling Smørgrav 			buf[s-ip]=0;
275*24e36522SCy Schubert #ifdef HAVE_IF_NAMETOINDEX
276*24e36522SCy Schubert 			if (!(sa->sin6_scope_id = if_nametoindex(s+1)))
277*24e36522SCy Schubert #endif /* HAVE_IF_NAMETOINDEX */
278b7579f77SDag-Erling Smørgrav 				sa->sin6_scope_id = (uint32_t)atoi(s+1);
279b7579f77SDag-Erling Smørgrav 			ip = buf;
280b7579f77SDag-Erling Smørgrav 		}
281b7579f77SDag-Erling Smørgrav 		if(inet_pton((int)sa->sin6_family, ip, &sa->sin6_addr) <= 0) {
282b7579f77SDag-Erling Smørgrav 			return 0;
283b7579f77SDag-Erling Smørgrav 		}
284b7579f77SDag-Erling Smørgrav 	} else { /* ip4 */
285b7579f77SDag-Erling Smørgrav 		struct sockaddr_in* sa = (struct sockaddr_in*)addr;
286b7579f77SDag-Erling Smørgrav 		*addrlen = (socklen_t)sizeof(struct sockaddr_in);
287b7579f77SDag-Erling Smørgrav 		memset(sa, 0, *addrlen);
288b7579f77SDag-Erling Smørgrav 		sa->sin_family = AF_INET;
289b7579f77SDag-Erling Smørgrav 		sa->sin_port = (in_port_t)htons(p);
290b7579f77SDag-Erling Smørgrav 		if(inet_pton((int)sa->sin_family, ip, &sa->sin_addr) <= 0) {
291b7579f77SDag-Erling Smørgrav 			return 0;
292b7579f77SDag-Erling Smørgrav 		}
293b7579f77SDag-Erling Smørgrav 	}
294b7579f77SDag-Erling Smørgrav 	return 1;
295b7579f77SDag-Erling Smørgrav }
296b7579f77SDag-Erling Smørgrav 
297b7579f77SDag-Erling Smørgrav int netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr,
298b7579f77SDag-Erling Smørgrav         socklen_t* addrlen, int* net)
299b7579f77SDag-Erling Smørgrav {
3000fb34990SDag-Erling Smørgrav 	char buf[64];
3010fb34990SDag-Erling Smørgrav 	char* s;
302b7579f77SDag-Erling Smørgrav 	*net = (str_is_ip6(str)?128:32);
303b7579f77SDag-Erling Smørgrav 	if((s=strchr(str, '/'))) {
304b7579f77SDag-Erling Smørgrav 		if(atoi(s+1) > *net) {
305b7579f77SDag-Erling Smørgrav 			log_err("netblock too large: %s", str);
306b7579f77SDag-Erling Smørgrav 			return 0;
307b7579f77SDag-Erling Smørgrav 		}
308b7579f77SDag-Erling Smørgrav 		*net = atoi(s+1);
309b7579f77SDag-Erling Smørgrav 		if(*net == 0 && strcmp(s+1, "0") != 0) {
310b7579f77SDag-Erling Smørgrav 			log_err("cannot parse netblock: '%s'", str);
311b7579f77SDag-Erling Smørgrav 			return 0;
312b7579f77SDag-Erling Smørgrav 		}
3130fb34990SDag-Erling Smørgrav 		strlcpy(buf, str, sizeof(buf));
3140fb34990SDag-Erling Smørgrav 		s = strchr(buf, '/');
3150fb34990SDag-Erling Smørgrav 		if(s) *s = 0;
3160fb34990SDag-Erling Smørgrav 		s = buf;
317b7579f77SDag-Erling Smørgrav 	}
318b7579f77SDag-Erling Smørgrav 	if(!ipstrtoaddr(s?s:str, port, addr, addrlen)) {
319b7579f77SDag-Erling Smørgrav 		log_err("cannot parse ip address: '%s'", str);
320b7579f77SDag-Erling Smørgrav 		return 0;
321b7579f77SDag-Erling Smørgrav 	}
322b7579f77SDag-Erling Smørgrav 	if(s) {
323b7579f77SDag-Erling Smørgrav 		addr_mask(addr, *addrlen, *net);
324b7579f77SDag-Erling Smørgrav 	}
325b7579f77SDag-Erling Smørgrav 	return 1;
326b7579f77SDag-Erling Smørgrav }
327b7579f77SDag-Erling Smørgrav 
328091e9e46SCy Schubert /* RPZ format address dname to network byte order address */
329091e9e46SCy Schubert static int ipdnametoaddr(uint8_t* dname, size_t dnamelen,
330091e9e46SCy Schubert 	struct sockaddr_storage* addr, socklen_t* addrlen, int* af)
331091e9e46SCy Schubert {
332091e9e46SCy Schubert 	uint8_t* ia;
333f44e67d1SCy Schubert 	int dnamelabs = dname_count_labels(dname);
334091e9e46SCy Schubert 	uint8_t lablen;
335091e9e46SCy Schubert 	char* e = NULL;
336091e9e46SCy Schubert 	int z = 0;
337091e9e46SCy Schubert 	size_t len = 0;
338091e9e46SCy Schubert 	int i;
339091e9e46SCy Schubert 	*af = AF_INET;
340091e9e46SCy Schubert 
341091e9e46SCy Schubert 	/* need 1 byte for label length */
342091e9e46SCy Schubert 	if(dnamelen < 1)
343091e9e46SCy Schubert 		return 0;
344091e9e46SCy Schubert 
345091e9e46SCy Schubert 	if(dnamelabs > 6 ||
346091e9e46SCy Schubert 		dname_has_label(dname, dnamelen, (uint8_t*)"\002zz")) {
347091e9e46SCy Schubert 		*af = AF_INET6;
348091e9e46SCy Schubert 	}
349091e9e46SCy Schubert 	len = *dname;
350091e9e46SCy Schubert 	lablen = *dname++;
351091e9e46SCy Schubert 	i = (*af == AF_INET) ? 3 : 15;
352091e9e46SCy Schubert 	if(*af == AF_INET6) {
353091e9e46SCy Schubert 		struct sockaddr_in6* sa = (struct sockaddr_in6*)addr;
354091e9e46SCy Schubert 		*addrlen = (socklen_t)sizeof(struct sockaddr_in6);
355091e9e46SCy Schubert 		memset(sa, 0, *addrlen);
356091e9e46SCy Schubert 		sa->sin6_family = AF_INET6;
357091e9e46SCy Schubert 		ia = (uint8_t*)&sa->sin6_addr;
358091e9e46SCy Schubert 	} else { /* ip4 */
359091e9e46SCy Schubert 		struct sockaddr_in* sa = (struct sockaddr_in*)addr;
360091e9e46SCy Schubert 		*addrlen = (socklen_t)sizeof(struct sockaddr_in);
361091e9e46SCy Schubert 		memset(sa, 0, *addrlen);
362091e9e46SCy Schubert 		sa->sin_family = AF_INET;
363091e9e46SCy Schubert 		ia = (uint8_t*)&sa->sin_addr;
364091e9e46SCy Schubert 	}
365091e9e46SCy Schubert 	while(lablen && i >= 0 && len <= dnamelen) {
366091e9e46SCy Schubert 		char buff[LDNS_MAX_LABELLEN+1];
367091e9e46SCy Schubert 		uint16_t chunk; /* big enough to not overflow on IPv6 hextet */
368091e9e46SCy Schubert 		if((*af == AF_INET && (lablen > 3 || dnamelabs > 6)) ||
369091e9e46SCy Schubert 			(*af == AF_INET6 && (lablen > 4 || dnamelabs > 10))) {
370091e9e46SCy Schubert 			return 0;
371091e9e46SCy Schubert 		}
372091e9e46SCy Schubert 		if(memcmp(dname, "zz", 2) == 0 && *af == AF_INET6) {
373091e9e46SCy Schubert 			/* Add one or more 0 labels. Address is initialised at
374091e9e46SCy Schubert 			 * 0, so just skip the zero part. */
375091e9e46SCy Schubert 			int zl = 11 - dnamelabs;
376091e9e46SCy Schubert 			if(z || zl < 0)
377091e9e46SCy Schubert 				return 0;
378091e9e46SCy Schubert 			z = 1;
379091e9e46SCy Schubert 			i -= (zl*2);
380091e9e46SCy Schubert 		} else {
381091e9e46SCy Schubert 			memcpy(buff, dname, lablen);
382091e9e46SCy Schubert 			buff[lablen] = '\0';
383091e9e46SCy Schubert 			chunk = strtol(buff, &e, (*af == AF_INET) ? 10 : 16);
384091e9e46SCy Schubert 			if(!e || *e != '\0' || (*af == AF_INET && chunk > 255))
385091e9e46SCy Schubert 				return 0;
386091e9e46SCy Schubert 			if(*af == AF_INET) {
387091e9e46SCy Schubert 				log_assert(i < 4 && i >= 0);
388091e9e46SCy Schubert 				ia[i] = (uint8_t)chunk;
389091e9e46SCy Schubert 				i--;
390091e9e46SCy Schubert 			} else {
391091e9e46SCy Schubert 				log_assert(i < 16 && i >= 1);
392091e9e46SCy Schubert 				/* ia in network byte order */
393091e9e46SCy Schubert 				ia[i-1] = (uint8_t)(chunk >> 8);
394091e9e46SCy Schubert 				ia[i] = (uint8_t)(chunk & 0x00FF);
395091e9e46SCy Schubert 				i -= 2;
396091e9e46SCy Schubert 			}
397091e9e46SCy Schubert 		}
398091e9e46SCy Schubert 		dname += lablen;
399091e9e46SCy Schubert 		lablen = *dname++;
400091e9e46SCy Schubert 		len += lablen;
401091e9e46SCy Schubert 	}
402091e9e46SCy Schubert 	if(i != -1)
403091e9e46SCy Schubert 		/* input too short */
404091e9e46SCy Schubert 		return 0;
405091e9e46SCy Schubert 	return 1;
406091e9e46SCy Schubert }
407091e9e46SCy Schubert 
408091e9e46SCy Schubert int netblockdnametoaddr(uint8_t* dname, size_t dnamelen,
409091e9e46SCy Schubert 	struct sockaddr_storage* addr, socklen_t* addrlen, int* net, int* af)
410091e9e46SCy Schubert {
411091e9e46SCy Schubert 	char buff[3 /* 3 digit netblock */ + 1];
412091e9e46SCy Schubert 	size_t nlablen;
413091e9e46SCy Schubert 	if(dnamelen < 1 || *dname > 3)
414091e9e46SCy Schubert 		/* netblock invalid */
415091e9e46SCy Schubert 		return 0;
416091e9e46SCy Schubert 	nlablen = *dname;
417091e9e46SCy Schubert 
418091e9e46SCy Schubert 	if(dnamelen < 1 + nlablen)
419091e9e46SCy Schubert 		return 0;
420091e9e46SCy Schubert 
421091e9e46SCy Schubert 	memcpy(buff, dname+1, nlablen);
422091e9e46SCy Schubert 	buff[nlablen] = '\0';
423091e9e46SCy Schubert 	*net = atoi(buff);
424091e9e46SCy Schubert 	if(*net == 0 && strcmp(buff, "0") != 0)
425091e9e46SCy Schubert 		return 0;
426091e9e46SCy Schubert 	dname += nlablen;
427091e9e46SCy Schubert 	dname++;
428091e9e46SCy Schubert 	if(!ipdnametoaddr(dname, dnamelen-1-nlablen, addr, addrlen, af))
429091e9e46SCy Schubert 		return 0;
430091e9e46SCy Schubert 	if((*af == AF_INET6 && *net > 128) || (*af == AF_INET && *net > 32))
431091e9e46SCy Schubert 		return 0;
432091e9e46SCy Schubert 	return 1;
433091e9e46SCy Schubert }
434091e9e46SCy Schubert 
4350fb34990SDag-Erling Smørgrav int authextstrtoaddr(char* str, struct sockaddr_storage* addr,
4360fb34990SDag-Erling Smørgrav 	socklen_t* addrlen, char** auth_name)
4370fb34990SDag-Erling Smørgrav {
4380fb34990SDag-Erling Smørgrav 	char* s;
4390fb34990SDag-Erling Smørgrav 	int port = UNBOUND_DNS_PORT;
4400fb34990SDag-Erling Smørgrav 	if((s=strchr(str, '@'))) {
4410fb34990SDag-Erling Smørgrav 		char buf[MAX_ADDR_STRLEN];
4420fb34990SDag-Erling Smørgrav 		size_t len = (size_t)(s-str);
4430fb34990SDag-Erling Smørgrav 		char* hash = strchr(s+1, '#');
4440fb34990SDag-Erling Smørgrav 		if(hash) {
4450fb34990SDag-Erling Smørgrav 			*auth_name = hash+1;
4460fb34990SDag-Erling Smørgrav 		} else {
4470fb34990SDag-Erling Smørgrav 			*auth_name = NULL;
4480fb34990SDag-Erling Smørgrav 		}
4490fb34990SDag-Erling Smørgrav 		if(len >= MAX_ADDR_STRLEN) {
4500fb34990SDag-Erling Smørgrav 			return 0;
4510fb34990SDag-Erling Smørgrav 		}
4520fb34990SDag-Erling Smørgrav 		(void)strlcpy(buf, str, sizeof(buf));
4530fb34990SDag-Erling Smørgrav 		buf[len] = 0;
4540fb34990SDag-Erling Smørgrav 		port = atoi(s+1);
4550fb34990SDag-Erling Smørgrav 		if(port == 0) {
4560fb34990SDag-Erling Smørgrav 			if(!hash && strcmp(s+1,"0")!=0)
4570fb34990SDag-Erling Smørgrav 				return 0;
4580fb34990SDag-Erling Smørgrav 			if(hash && strncmp(s+1,"0#",2)!=0)
4590fb34990SDag-Erling Smørgrav 				return 0;
4600fb34990SDag-Erling Smørgrav 		}
4610fb34990SDag-Erling Smørgrav 		return ipstrtoaddr(buf, port, addr, addrlen);
4620fb34990SDag-Erling Smørgrav 	}
4630fb34990SDag-Erling Smørgrav 	if((s=strchr(str, '#'))) {
4640fb34990SDag-Erling Smørgrav 		char buf[MAX_ADDR_STRLEN];
4650fb34990SDag-Erling Smørgrav 		size_t len = (size_t)(s-str);
4660fb34990SDag-Erling Smørgrav 		if(len >= MAX_ADDR_STRLEN) {
4670fb34990SDag-Erling Smørgrav 			return 0;
4680fb34990SDag-Erling Smørgrav 		}
4690fb34990SDag-Erling Smørgrav 		(void)strlcpy(buf, str, sizeof(buf));
4700fb34990SDag-Erling Smørgrav 		buf[len] = 0;
4710fb34990SDag-Erling Smørgrav 		port = UNBOUND_DNS_OVER_TLS_PORT;
4720fb34990SDag-Erling Smørgrav 		*auth_name = s+1;
4730fb34990SDag-Erling Smørgrav 		return ipstrtoaddr(buf, port, addr, addrlen);
4740fb34990SDag-Erling Smørgrav 	}
4750fb34990SDag-Erling Smørgrav 	*auth_name = NULL;
4760fb34990SDag-Erling Smørgrav 	return ipstrtoaddr(str, port, addr, addrlen);
4770fb34990SDag-Erling Smørgrav }
4780fb34990SDag-Erling Smørgrav 
47957bddd21SDag-Erling Smørgrav /** store port number into sockaddr structure */
48057bddd21SDag-Erling Smørgrav void
48157bddd21SDag-Erling Smørgrav sockaddr_store_port(struct sockaddr_storage* addr, socklen_t addrlen, int port)
48257bddd21SDag-Erling Smørgrav {
48357bddd21SDag-Erling Smørgrav 	if(addr_is_ip6(addr, addrlen)) {
48457bddd21SDag-Erling Smørgrav 		struct sockaddr_in6* sa = (struct sockaddr_in6*)addr;
48557bddd21SDag-Erling Smørgrav 		sa->sin6_port = (in_port_t)htons((uint16_t)port);
48657bddd21SDag-Erling Smørgrav 	} else {
48757bddd21SDag-Erling Smørgrav 		struct sockaddr_in* sa = (struct sockaddr_in*)addr;
48857bddd21SDag-Erling Smørgrav 		sa->sin_port = (in_port_t)htons((uint16_t)port);
48957bddd21SDag-Erling Smørgrav 	}
49057bddd21SDag-Erling Smørgrav }
49157bddd21SDag-Erling Smørgrav 
492b7579f77SDag-Erling Smørgrav void
493b7579f77SDag-Erling Smørgrav log_nametypeclass(enum verbosity_value v, const char* str, uint8_t* name,
494b7579f77SDag-Erling Smørgrav 	uint16_t type, uint16_t dclass)
495b7579f77SDag-Erling Smørgrav {
496b7579f77SDag-Erling Smørgrav 	char buf[LDNS_MAX_DOMAINLEN+1];
497b7579f77SDag-Erling Smørgrav 	char t[12], c[12];
498b7579f77SDag-Erling Smørgrav 	const char *ts, *cs;
499b7579f77SDag-Erling Smørgrav 	if(verbosity < v)
500b7579f77SDag-Erling Smørgrav 		return;
501b7579f77SDag-Erling Smørgrav 	dname_str(name, buf);
502b7579f77SDag-Erling Smørgrav 	if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG";
503b7579f77SDag-Erling Smørgrav 	else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR";
504b7579f77SDag-Erling Smørgrav 	else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR";
505b7579f77SDag-Erling Smørgrav 	else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB";
506b7579f77SDag-Erling Smørgrav 	else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA";
507b7579f77SDag-Erling Smørgrav 	else if(type == LDNS_RR_TYPE_ANY) ts = "ANY";
50817d15b25SDag-Erling Smørgrav 	else if(sldns_rr_descript(type) && sldns_rr_descript(type)->_name)
50917d15b25SDag-Erling Smørgrav 		ts = sldns_rr_descript(type)->_name;
510b7579f77SDag-Erling Smørgrav 	else {
511b7579f77SDag-Erling Smørgrav 		snprintf(t, sizeof(t), "TYPE%d", (int)type);
512b7579f77SDag-Erling Smørgrav 		ts = t;
513b7579f77SDag-Erling Smørgrav 	}
51417d15b25SDag-Erling Smørgrav 	if(sldns_lookup_by_id(sldns_rr_classes, (int)dclass) &&
51517d15b25SDag-Erling Smørgrav 		sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name)
51617d15b25SDag-Erling Smørgrav 		cs = sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name;
517b7579f77SDag-Erling Smørgrav 	else {
518b7579f77SDag-Erling Smørgrav 		snprintf(c, sizeof(c), "CLASS%d", (int)dclass);
519b7579f77SDag-Erling Smørgrav 		cs = c;
520b7579f77SDag-Erling Smørgrav 	}
521b7579f77SDag-Erling Smørgrav 	log_info("%s %s %s %s", str, buf, ts, cs);
522b7579f77SDag-Erling Smørgrav }
523b7579f77SDag-Erling Smørgrav 
524e86b9096SDag-Erling Smørgrav void
525e86b9096SDag-Erling Smørgrav log_query_in(const char* str, uint8_t* name, uint16_t type, uint16_t dclass)
526e86b9096SDag-Erling Smørgrav {
527e86b9096SDag-Erling Smørgrav 	char buf[LDNS_MAX_DOMAINLEN+1];
528e86b9096SDag-Erling Smørgrav 	char t[12], c[12];
529e86b9096SDag-Erling Smørgrav 	const char *ts, *cs;
530e86b9096SDag-Erling Smørgrav 	dname_str(name, buf);
531e86b9096SDag-Erling Smørgrav 	if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG";
532e86b9096SDag-Erling Smørgrav 	else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR";
533e86b9096SDag-Erling Smørgrav 	else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR";
534e86b9096SDag-Erling Smørgrav 	else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB";
535e86b9096SDag-Erling Smørgrav 	else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA";
536e86b9096SDag-Erling Smørgrav 	else if(type == LDNS_RR_TYPE_ANY) ts = "ANY";
537e86b9096SDag-Erling Smørgrav 	else if(sldns_rr_descript(type) && sldns_rr_descript(type)->_name)
538e86b9096SDag-Erling Smørgrav 		ts = sldns_rr_descript(type)->_name;
539e86b9096SDag-Erling Smørgrav 	else {
540e86b9096SDag-Erling Smørgrav 		snprintf(t, sizeof(t), "TYPE%d", (int)type);
541e86b9096SDag-Erling Smørgrav 		ts = t;
542e86b9096SDag-Erling Smørgrav 	}
543e86b9096SDag-Erling Smørgrav 	if(sldns_lookup_by_id(sldns_rr_classes, (int)dclass) &&
544e86b9096SDag-Erling Smørgrav 		sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name)
545e86b9096SDag-Erling Smørgrav 		cs = sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name;
546e86b9096SDag-Erling Smørgrav 	else {
547e86b9096SDag-Erling Smørgrav 		snprintf(c, sizeof(c), "CLASS%d", (int)dclass);
548e86b9096SDag-Erling Smørgrav 		cs = c;
549e86b9096SDag-Erling Smørgrav 	}
550e86b9096SDag-Erling Smørgrav 	if(LOG_TAG_QUERYREPLY)
551e86b9096SDag-Erling Smørgrav 		log_query("%s %s %s %s", str, buf, ts, cs);
552e86b9096SDag-Erling Smørgrav 	else	log_info("%s %s %s %s", str, buf, ts, cs);
553e86b9096SDag-Erling Smørgrav }
554e86b9096SDag-Erling Smørgrav 
555b7579f77SDag-Erling Smørgrav void log_name_addr(enum verbosity_value v, const char* str, uint8_t* zone,
556b7579f77SDag-Erling Smørgrav 	struct sockaddr_storage* addr, socklen_t addrlen)
557b7579f77SDag-Erling Smørgrav {
558b7579f77SDag-Erling Smørgrav 	uint16_t port;
559b7579f77SDag-Erling Smørgrav 	const char* family = "unknown_family ";
560b7579f77SDag-Erling Smørgrav 	char namebuf[LDNS_MAX_DOMAINLEN+1];
561b7579f77SDag-Erling Smørgrav 	char dest[100];
562b7579f77SDag-Erling Smørgrav 	int af = (int)((struct sockaddr_in*)addr)->sin_family;
563b7579f77SDag-Erling Smørgrav 	void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
564b7579f77SDag-Erling Smørgrav 	if(verbosity < v)
565b7579f77SDag-Erling Smørgrav 		return;
566b7579f77SDag-Erling Smørgrav 	switch(af) {
567b7579f77SDag-Erling Smørgrav 		case AF_INET: family=""; break;
568b7579f77SDag-Erling Smørgrav 		case AF_INET6: family="";
569b7579f77SDag-Erling Smørgrav 			sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
570b7579f77SDag-Erling Smørgrav 			break;
57131099b50SDag-Erling Smørgrav 		case AF_LOCAL: family="local "; break;
572b7579f77SDag-Erling Smørgrav 		default: break;
573b7579f77SDag-Erling Smørgrav 	}
574b7579f77SDag-Erling Smørgrav 	if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
57517d15b25SDag-Erling Smørgrav 		(void)strlcpy(dest, "(inet_ntop error)", sizeof(dest));
576b7579f77SDag-Erling Smørgrav 	}
577b7579f77SDag-Erling Smørgrav 	dest[sizeof(dest)-1] = 0;
578b7579f77SDag-Erling Smørgrav 	port = ntohs(((struct sockaddr_in*)addr)->sin_port);
579b7579f77SDag-Erling Smørgrav 	dname_str(zone, namebuf);
580b7579f77SDag-Erling Smørgrav 	if(af != AF_INET && af != AF_INET6)
581b7579f77SDag-Erling Smørgrav 		verbose(v, "%s <%s> %s%s#%d (addrlen %d)",
582b7579f77SDag-Erling Smørgrav 			str, namebuf, family, dest, (int)port, (int)addrlen);
583b7579f77SDag-Erling Smørgrav 	else	verbose(v, "%s <%s> %s%s#%d",
584b7579f77SDag-Erling Smørgrav 			str, namebuf, family, dest, (int)port);
585b7579f77SDag-Erling Smørgrav }
586b7579f77SDag-Erling Smørgrav 
587ff825849SDag-Erling Smørgrav void log_err_addr(const char* str, const char* err,
588ff825849SDag-Erling Smørgrav 	struct sockaddr_storage* addr, socklen_t addrlen)
589ff825849SDag-Erling Smørgrav {
590ff825849SDag-Erling Smørgrav 	uint16_t port;
591ff825849SDag-Erling Smørgrav 	char dest[100];
592ff825849SDag-Erling Smørgrav 	int af = (int)((struct sockaddr_in*)addr)->sin_family;
593ff825849SDag-Erling Smørgrav 	void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
594ff825849SDag-Erling Smørgrav 	if(af == AF_INET6)
595ff825849SDag-Erling Smørgrav 		sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
596ff825849SDag-Erling Smørgrav 	if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
597ff825849SDag-Erling Smørgrav 		(void)strlcpy(dest, "(inet_ntop error)", sizeof(dest));
598ff825849SDag-Erling Smørgrav 	}
599ff825849SDag-Erling Smørgrav 	dest[sizeof(dest)-1] = 0;
600ff825849SDag-Erling Smørgrav 	port = ntohs(((struct sockaddr_in*)addr)->sin_port);
601ff825849SDag-Erling Smørgrav 	if(verbosity >= 4)
602ff825849SDag-Erling Smørgrav 		log_err("%s: %s for %s port %d (len %d)", str, err, dest,
603ff825849SDag-Erling Smørgrav 			(int)port, (int)addrlen);
6044c75e3aaSDag-Erling Smørgrav 	else	log_err("%s: %s for %s port %d", str, err, dest, (int)port);
605ff825849SDag-Erling Smørgrav }
606ff825849SDag-Erling Smørgrav 
607b7579f77SDag-Erling Smørgrav int
608b7579f77SDag-Erling Smørgrav sockaddr_cmp(struct sockaddr_storage* addr1, socklen_t len1,
609b7579f77SDag-Erling Smørgrav 	struct sockaddr_storage* addr2, socklen_t len2)
610b7579f77SDag-Erling Smørgrav {
611b7579f77SDag-Erling Smørgrav 	struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1;
612b7579f77SDag-Erling Smørgrav 	struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2;
613b7579f77SDag-Erling Smørgrav 	struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1;
614b7579f77SDag-Erling Smørgrav 	struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2;
615b7579f77SDag-Erling Smørgrav 	if(len1 < len2)
616b7579f77SDag-Erling Smørgrav 		return -1;
617b7579f77SDag-Erling Smørgrav 	if(len1 > len2)
618b7579f77SDag-Erling Smørgrav 		return 1;
619b7579f77SDag-Erling Smørgrav 	log_assert(len1 == len2);
620b7579f77SDag-Erling Smørgrav 	if( p1_in->sin_family < p2_in->sin_family)
621b7579f77SDag-Erling Smørgrav 		return -1;
622b7579f77SDag-Erling Smørgrav 	if( p1_in->sin_family > p2_in->sin_family)
623b7579f77SDag-Erling Smørgrav 		return 1;
624b7579f77SDag-Erling Smørgrav 	log_assert( p1_in->sin_family == p2_in->sin_family );
625b7579f77SDag-Erling Smørgrav 	/* compare ip4 */
626b7579f77SDag-Erling Smørgrav 	if( p1_in->sin_family == AF_INET ) {
627b7579f77SDag-Erling Smørgrav 		/* just order it, ntohs not required */
628b7579f77SDag-Erling Smørgrav 		if(p1_in->sin_port < p2_in->sin_port)
629b7579f77SDag-Erling Smørgrav 			return -1;
630b7579f77SDag-Erling Smørgrav 		if(p1_in->sin_port > p2_in->sin_port)
631b7579f77SDag-Erling Smørgrav 			return 1;
632b7579f77SDag-Erling Smørgrav 		log_assert(p1_in->sin_port == p2_in->sin_port);
633b7579f77SDag-Erling Smørgrav 		return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE);
634b7579f77SDag-Erling Smørgrav 	} else if (p1_in6->sin6_family == AF_INET6) {
635b7579f77SDag-Erling Smørgrav 		/* just order it, ntohs not required */
636b7579f77SDag-Erling Smørgrav 		if(p1_in6->sin6_port < p2_in6->sin6_port)
637b7579f77SDag-Erling Smørgrav 			return -1;
638b7579f77SDag-Erling Smørgrav 		if(p1_in6->sin6_port > p2_in6->sin6_port)
639b7579f77SDag-Erling Smørgrav 			return 1;
640b7579f77SDag-Erling Smørgrav 		log_assert(p1_in6->sin6_port == p2_in6->sin6_port);
641b7579f77SDag-Erling Smørgrav 		return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr,
642b7579f77SDag-Erling Smørgrav 			INET6_SIZE);
643b7579f77SDag-Erling Smørgrav 	} else {
644b7579f77SDag-Erling Smørgrav 		/* eek unknown type, perform this comparison for sanity. */
645b7579f77SDag-Erling Smørgrav 		return memcmp(addr1, addr2, len1);
646b7579f77SDag-Erling Smørgrav 	}
647b7579f77SDag-Erling Smørgrav }
648b7579f77SDag-Erling Smørgrav 
649b7579f77SDag-Erling Smørgrav int
650b7579f77SDag-Erling Smørgrav sockaddr_cmp_addr(struct sockaddr_storage* addr1, socklen_t len1,
651b7579f77SDag-Erling Smørgrav 	struct sockaddr_storage* addr2, socklen_t len2)
652b7579f77SDag-Erling Smørgrav {
653b7579f77SDag-Erling Smørgrav 	struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1;
654b7579f77SDag-Erling Smørgrav 	struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2;
655b7579f77SDag-Erling Smørgrav 	struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1;
656b7579f77SDag-Erling Smørgrav 	struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2;
657b7579f77SDag-Erling Smørgrav 	if(len1 < len2)
658b7579f77SDag-Erling Smørgrav 		return -1;
659b7579f77SDag-Erling Smørgrav 	if(len1 > len2)
660b7579f77SDag-Erling Smørgrav 		return 1;
661b7579f77SDag-Erling Smørgrav 	log_assert(len1 == len2);
662b7579f77SDag-Erling Smørgrav 	if( p1_in->sin_family < p2_in->sin_family)
663b7579f77SDag-Erling Smørgrav 		return -1;
664b7579f77SDag-Erling Smørgrav 	if( p1_in->sin_family > p2_in->sin_family)
665b7579f77SDag-Erling Smørgrav 		return 1;
666b7579f77SDag-Erling Smørgrav 	log_assert( p1_in->sin_family == p2_in->sin_family );
667b7579f77SDag-Erling Smørgrav 	/* compare ip4 */
668b7579f77SDag-Erling Smørgrav 	if( p1_in->sin_family == AF_INET ) {
669b7579f77SDag-Erling Smørgrav 		return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE);
670b7579f77SDag-Erling Smørgrav 	} else if (p1_in6->sin6_family == AF_INET6) {
671b7579f77SDag-Erling Smørgrav 		return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr,
672b7579f77SDag-Erling Smørgrav 			INET6_SIZE);
673b7579f77SDag-Erling Smørgrav 	} else {
674b7579f77SDag-Erling Smørgrav 		/* eek unknown type, perform this comparison for sanity. */
675b7579f77SDag-Erling Smørgrav 		return memcmp(addr1, addr2, len1);
676b7579f77SDag-Erling Smørgrav 	}
677b7579f77SDag-Erling Smørgrav }
678b7579f77SDag-Erling Smørgrav 
679b7579f77SDag-Erling Smørgrav int
680b7579f77SDag-Erling Smørgrav addr_is_ip6(struct sockaddr_storage* addr, socklen_t len)
681b7579f77SDag-Erling Smørgrav {
682b7579f77SDag-Erling Smørgrav 	if(len == (socklen_t)sizeof(struct sockaddr_in6) &&
683b7579f77SDag-Erling Smørgrav 		((struct sockaddr_in6*)addr)->sin6_family == AF_INET6)
684b7579f77SDag-Erling Smørgrav 		return 1;
685b7579f77SDag-Erling Smørgrav 	else    return 0;
686b7579f77SDag-Erling Smørgrav }
687b7579f77SDag-Erling Smørgrav 
688b7579f77SDag-Erling Smørgrav void
689b7579f77SDag-Erling Smørgrav addr_mask(struct sockaddr_storage* addr, socklen_t len, int net)
690b7579f77SDag-Erling Smørgrav {
691b7579f77SDag-Erling Smørgrav 	uint8_t mask[8] = {0x0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe};
692b7579f77SDag-Erling Smørgrav 	int i, max;
693b7579f77SDag-Erling Smørgrav 	uint8_t* s;
694b7579f77SDag-Erling Smørgrav 	if(addr_is_ip6(addr, len)) {
695b7579f77SDag-Erling Smørgrav 		s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr;
696b7579f77SDag-Erling Smørgrav 		max = 128;
697b7579f77SDag-Erling Smørgrav 	} else {
698b7579f77SDag-Erling Smørgrav 		s = (uint8_t*)&((struct sockaddr_in*)addr)->sin_addr;
699b7579f77SDag-Erling Smørgrav 		max = 32;
700b7579f77SDag-Erling Smørgrav 	}
701b7579f77SDag-Erling Smørgrav 	if(net >= max)
702b7579f77SDag-Erling Smørgrav 		return;
703b7579f77SDag-Erling Smørgrav 	for(i=net/8+1; i<max/8; i++) {
704b7579f77SDag-Erling Smørgrav 		s[i] = 0;
705b7579f77SDag-Erling Smørgrav 	}
706b7579f77SDag-Erling Smørgrav 	s[net/8] &= mask[net&0x7];
707b7579f77SDag-Erling Smørgrav }
708b7579f77SDag-Erling Smørgrav 
709b7579f77SDag-Erling Smørgrav int
710b7579f77SDag-Erling Smørgrav addr_in_common(struct sockaddr_storage* addr1, int net1,
711b7579f77SDag-Erling Smørgrav 	struct sockaddr_storage* addr2, int net2, socklen_t addrlen)
712b7579f77SDag-Erling Smørgrav {
713b7579f77SDag-Erling Smørgrav 	int min = (net1<net2)?net1:net2;
714b7579f77SDag-Erling Smørgrav 	int i, to;
715b7579f77SDag-Erling Smørgrav 	int match = 0;
716b7579f77SDag-Erling Smørgrav 	uint8_t* s1, *s2;
717b7579f77SDag-Erling Smørgrav 	if(addr_is_ip6(addr1, addrlen)) {
718b7579f77SDag-Erling Smørgrav 		s1 = (uint8_t*)&((struct sockaddr_in6*)addr1)->sin6_addr;
719b7579f77SDag-Erling Smørgrav 		s2 = (uint8_t*)&((struct sockaddr_in6*)addr2)->sin6_addr;
720b7579f77SDag-Erling Smørgrav 		to = 16;
721b7579f77SDag-Erling Smørgrav 	} else {
722b7579f77SDag-Erling Smørgrav 		s1 = (uint8_t*)&((struct sockaddr_in*)addr1)->sin_addr;
723b7579f77SDag-Erling Smørgrav 		s2 = (uint8_t*)&((struct sockaddr_in*)addr2)->sin_addr;
724b7579f77SDag-Erling Smørgrav 		to = 4;
725b7579f77SDag-Erling Smørgrav 	}
726b7579f77SDag-Erling Smørgrav 	/* match = bits_in_common(s1, s2, to); */
727b7579f77SDag-Erling Smørgrav 	for(i=0; i<to; i++) {
728b7579f77SDag-Erling Smørgrav 		if(s1[i] == s2[i]) {
729b7579f77SDag-Erling Smørgrav 			match += 8;
730b7579f77SDag-Erling Smørgrav 		} else {
731b7579f77SDag-Erling Smørgrav 			uint8_t z = s1[i]^s2[i];
732b7579f77SDag-Erling Smørgrav 			log_assert(z);
733b7579f77SDag-Erling Smørgrav 			while(!(z&0x80)) {
734b7579f77SDag-Erling Smørgrav 				match++;
735b7579f77SDag-Erling Smørgrav 				z<<=1;
736b7579f77SDag-Erling Smørgrav 			}
737b7579f77SDag-Erling Smørgrav 			break;
738b7579f77SDag-Erling Smørgrav 		}
739b7579f77SDag-Erling Smørgrav 	}
740b7579f77SDag-Erling Smørgrav 	if(match > min) match = min;
741b7579f77SDag-Erling Smørgrav 	return match;
742b7579f77SDag-Erling Smørgrav }
743b7579f77SDag-Erling Smørgrav 
744b7579f77SDag-Erling Smørgrav void
745b7579f77SDag-Erling Smørgrav addr_to_str(struct sockaddr_storage* addr, socklen_t addrlen,
746b7579f77SDag-Erling Smørgrav 	char* buf, size_t len)
747b7579f77SDag-Erling Smørgrav {
748b7579f77SDag-Erling Smørgrav 	int af = (int)((struct sockaddr_in*)addr)->sin_family;
749b7579f77SDag-Erling Smørgrav 	void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
750b7579f77SDag-Erling Smørgrav 	if(addr_is_ip6(addr, addrlen))
751b7579f77SDag-Erling Smørgrav 		sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
752b7579f77SDag-Erling Smørgrav 	if(inet_ntop(af, sinaddr, buf, (socklen_t)len) == 0) {
753b7579f77SDag-Erling Smørgrav 		snprintf(buf, len, "(inet_ntop_error)");
754b7579f77SDag-Erling Smørgrav 	}
755b7579f77SDag-Erling Smørgrav }
756b7579f77SDag-Erling Smørgrav 
757b7579f77SDag-Erling Smørgrav int
758b7579f77SDag-Erling Smørgrav addr_is_ip4mapped(struct sockaddr_storage* addr, socklen_t addrlen)
759b7579f77SDag-Erling Smørgrav {
760b7579f77SDag-Erling Smørgrav 	/* prefix for ipv4 into ipv6 mapping is ::ffff:x.x.x.x */
761b7579f77SDag-Erling Smørgrav 	const uint8_t map_prefix[16] =
762b7579f77SDag-Erling Smørgrav 		{0,0,0,0,  0,0,0,0, 0,0,0xff,0xff, 0,0,0,0};
763b7579f77SDag-Erling Smørgrav 	uint8_t* s;
764b7579f77SDag-Erling Smørgrav 	if(!addr_is_ip6(addr, addrlen))
765b7579f77SDag-Erling Smørgrav 		return 0;
766b7579f77SDag-Erling Smørgrav 	/* s is 16 octet ipv6 address string */
767b7579f77SDag-Erling Smørgrav 	s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr;
768b7579f77SDag-Erling Smørgrav 	return (memcmp(s, map_prefix, 12) == 0);
769b7579f77SDag-Erling Smørgrav }
770b7579f77SDag-Erling Smørgrav 
771b7579f77SDag-Erling Smørgrav int addr_is_broadcast(struct sockaddr_storage* addr, socklen_t addrlen)
772b7579f77SDag-Erling Smørgrav {
773b7579f77SDag-Erling Smørgrav 	int af = (int)((struct sockaddr_in*)addr)->sin_family;
774b7579f77SDag-Erling Smørgrav 	void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
775b7579f77SDag-Erling Smørgrav 	return af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in)
776b7579f77SDag-Erling Smørgrav 		&& memcmp(sinaddr, "\377\377\377\377", 4) == 0;
777b7579f77SDag-Erling Smørgrav }
778b7579f77SDag-Erling Smørgrav 
779b7579f77SDag-Erling Smørgrav int addr_is_any(struct sockaddr_storage* addr, socklen_t addrlen)
780b7579f77SDag-Erling Smørgrav {
781b7579f77SDag-Erling Smørgrav 	int af = (int)((struct sockaddr_in*)addr)->sin_family;
782b7579f77SDag-Erling Smørgrav 	void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
783b7579f77SDag-Erling Smørgrav 	void* sin6addr = &((struct sockaddr_in6*)addr)->sin6_addr;
784b7579f77SDag-Erling Smørgrav 	if(af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in)
785b7579f77SDag-Erling Smørgrav 		&& memcmp(sinaddr, "\000\000\000\000", 4) == 0)
786b7579f77SDag-Erling Smørgrav 		return 1;
787b7579f77SDag-Erling Smørgrav 	else if(af==AF_INET6 && addrlen>=(socklen_t)sizeof(struct sockaddr_in6)
788b7579f77SDag-Erling Smørgrav 		&& memcmp(sin6addr, "\000\000\000\000\000\000\000\000"
789b7579f77SDag-Erling Smørgrav 		"\000\000\000\000\000\000\000\000", 16) == 0)
790b7579f77SDag-Erling Smørgrav 		return 1;
791b7579f77SDag-Erling Smørgrav 	return 0;
792b7579f77SDag-Erling Smørgrav }
793b7579f77SDag-Erling Smørgrav 
794b7579f77SDag-Erling Smørgrav void sock_list_insert(struct sock_list** list, struct sockaddr_storage* addr,
795b7579f77SDag-Erling Smørgrav 	socklen_t len, struct regional* region)
796b7579f77SDag-Erling Smørgrav {
797b7579f77SDag-Erling Smørgrav 	struct sock_list* add = (struct sock_list*)regional_alloc(region,
798b7579f77SDag-Erling Smørgrav 		sizeof(*add) - sizeof(add->addr) + (size_t)len);
799b7579f77SDag-Erling Smørgrav 	if(!add) {
800b7579f77SDag-Erling Smørgrav 		log_err("out of memory in socketlist insert");
801b7579f77SDag-Erling Smørgrav 		return;
802b7579f77SDag-Erling Smørgrav 	}
803b7579f77SDag-Erling Smørgrav 	log_assert(list);
804b7579f77SDag-Erling Smørgrav 	add->next = *list;
805b7579f77SDag-Erling Smørgrav 	add->len = len;
806b7579f77SDag-Erling Smørgrav 	*list = add;
807b7579f77SDag-Erling Smørgrav 	if(len) memmove(&add->addr, addr, len);
808b7579f77SDag-Erling Smørgrav }
809b7579f77SDag-Erling Smørgrav 
810b7579f77SDag-Erling Smørgrav void sock_list_prepend(struct sock_list** list, struct sock_list* add)
811b7579f77SDag-Erling Smørgrav {
812b7579f77SDag-Erling Smørgrav 	struct sock_list* last = add;
813b7579f77SDag-Erling Smørgrav 	if(!last)
814b7579f77SDag-Erling Smørgrav 		return;
815b7579f77SDag-Erling Smørgrav 	while(last->next)
816b7579f77SDag-Erling Smørgrav 		last = last->next;
817b7579f77SDag-Erling Smørgrav 	last->next = *list;
818b7579f77SDag-Erling Smørgrav 	*list = add;
819b7579f77SDag-Erling Smørgrav }
820b7579f77SDag-Erling Smørgrav 
821b7579f77SDag-Erling Smørgrav int sock_list_find(struct sock_list* list, struct sockaddr_storage* addr,
822b7579f77SDag-Erling Smørgrav         socklen_t len)
823b7579f77SDag-Erling Smørgrav {
824b7579f77SDag-Erling Smørgrav 	while(list) {
825b7579f77SDag-Erling Smørgrav 		if(len == list->len) {
826b7579f77SDag-Erling Smørgrav 			if(len == 0 || sockaddr_cmp_addr(addr, len,
827b7579f77SDag-Erling Smørgrav 				&list->addr, list->len) == 0)
828b7579f77SDag-Erling Smørgrav 				return 1;
829b7579f77SDag-Erling Smørgrav 		}
830b7579f77SDag-Erling Smørgrav 		list = list->next;
831b7579f77SDag-Erling Smørgrav 	}
832b7579f77SDag-Erling Smørgrav 	return 0;
833b7579f77SDag-Erling Smørgrav }
834b7579f77SDag-Erling Smørgrav 
835b7579f77SDag-Erling Smørgrav void sock_list_merge(struct sock_list** list, struct regional* region,
836b7579f77SDag-Erling Smørgrav 	struct sock_list* add)
837b7579f77SDag-Erling Smørgrav {
838b7579f77SDag-Erling Smørgrav 	struct sock_list* p;
839b7579f77SDag-Erling Smørgrav 	for(p=add; p; p=p->next) {
840b7579f77SDag-Erling Smørgrav 		if(!sock_list_find(*list, &p->addr, p->len))
841b7579f77SDag-Erling Smørgrav 			sock_list_insert(list, &p->addr, p->len, region);
842b7579f77SDag-Erling Smørgrav 	}
843b7579f77SDag-Erling Smørgrav }
844b7579f77SDag-Erling Smørgrav 
845b7579f77SDag-Erling Smørgrav void
846b7579f77SDag-Erling Smørgrav log_crypto_err(const char* str)
847b7579f77SDag-Erling Smørgrav {
8488ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL
8490eefd307SCy Schubert 	log_crypto_err_code(str, ERR_get_error());
8500eefd307SCy Schubert #else
8510eefd307SCy Schubert 	(void)str;
8520eefd307SCy Schubert #endif /* HAVE_SSL */
8530eefd307SCy Schubert }
8540eefd307SCy Schubert 
8550eefd307SCy Schubert void log_crypto_err_code(const char* str, unsigned long err)
8560eefd307SCy Schubert {
8570eefd307SCy Schubert #ifdef HAVE_SSL
858b7579f77SDag-Erling Smørgrav 	/* error:[error code]:[library name]:[function name]:[reason string] */
859b7579f77SDag-Erling Smørgrav 	char buf[128];
860b7579f77SDag-Erling Smørgrav 	unsigned long e;
8610eefd307SCy Schubert 	ERR_error_string_n(err, buf, sizeof(buf));
862b7579f77SDag-Erling Smørgrav 	log_err("%s crypto %s", str, buf);
863b7579f77SDag-Erling Smørgrav 	while( (e=ERR_get_error()) ) {
864b7579f77SDag-Erling Smørgrav 		ERR_error_string_n(e, buf, sizeof(buf));
865b7579f77SDag-Erling Smørgrav 		log_err("and additionally crypto %s", buf);
866b7579f77SDag-Erling Smørgrav 	}
8678ed2b524SDag-Erling Smørgrav #else
8688ed2b524SDag-Erling Smørgrav 	(void)str;
8690eefd307SCy Schubert 	(void)err;
8708ed2b524SDag-Erling Smørgrav #endif /* HAVE_SSL */
871b7579f77SDag-Erling Smørgrav }
872b7579f77SDag-Erling Smørgrav 
87325039b37SCy Schubert #ifdef HAVE_SSL
87425039b37SCy Schubert /** log certificate details */
87525039b37SCy Schubert void
87625039b37SCy Schubert log_cert(unsigned level, const char* str, void* cert)
87725039b37SCy Schubert {
87825039b37SCy Schubert 	BIO* bio;
87925039b37SCy Schubert 	char nul = 0;
88025039b37SCy Schubert 	char* pp = NULL;
88125039b37SCy Schubert 	long len;
88225039b37SCy Schubert 	if(verbosity < level) return;
88325039b37SCy Schubert 	bio = BIO_new(BIO_s_mem());
88425039b37SCy Schubert 	if(!bio) return;
88525039b37SCy Schubert 	X509_print_ex(bio, (X509*)cert, 0, (unsigned long)-1
88625039b37SCy Schubert 		^(X509_FLAG_NO_SUBJECT
88725039b37SCy Schubert                         |X509_FLAG_NO_ISSUER|X509_FLAG_NO_VALIDITY
88825039b37SCy Schubert 			|X509_FLAG_NO_EXTENSIONS|X509_FLAG_NO_AUX
88925039b37SCy Schubert 			|X509_FLAG_NO_ATTRIBUTES));
89025039b37SCy Schubert 	BIO_write(bio, &nul, (int)sizeof(nul));
89125039b37SCy Schubert 	len = BIO_get_mem_data(bio, &pp);
89225039b37SCy Schubert 	if(len != 0 && pp) {
893*24e36522SCy Schubert 		/* reduce size of cert printout */
894*24e36522SCy Schubert 		char* s;
895*24e36522SCy Schubert 		while((s=strstr(pp, "  "))!=NULL)
896*24e36522SCy Schubert 			memmove(s, s+1, strlen(s+1)+1);
897*24e36522SCy Schubert 		while((s=strstr(pp, "\t\t"))!=NULL)
898*24e36522SCy Schubert 			memmove(s, s+1, strlen(s+1)+1);
89925039b37SCy Schubert 		verbose(level, "%s: \n%s", str, pp);
90025039b37SCy Schubert 	}
90125039b37SCy Schubert 	BIO_free(bio);
90225039b37SCy Schubert }
90325039b37SCy Schubert #endif /* HAVE_SSL */
90425039b37SCy Schubert 
9055469a995SCy Schubert #if defined(HAVE_SSL) && defined(HAVE_NGHTTP2) && defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB)
906c0caa2e2SCy Schubert static int alpn_select_cb(SSL* ATTR_UNUSED(ssl), const unsigned char** out,
907c0caa2e2SCy Schubert 	unsigned char* outlen, const unsigned char* in, unsigned int inlen,
908c0caa2e2SCy Schubert 	void* ATTR_UNUSED(arg))
909c0caa2e2SCy Schubert {
910c0caa2e2SCy Schubert 	int rv = nghttp2_select_next_protocol((unsigned char **)out, outlen, in,
911c0caa2e2SCy Schubert 		inlen);
912c0caa2e2SCy Schubert 	if(rv == -1) {
913c0caa2e2SCy Schubert 		return SSL_TLSEXT_ERR_NOACK;
914c0caa2e2SCy Schubert 	}
915c0caa2e2SCy Schubert 	/* either http/1.1 or h2 selected */
916c0caa2e2SCy Schubert 	return SSL_TLSEXT_ERR_OK;
917c0caa2e2SCy Schubert }
918c0caa2e2SCy Schubert #endif
919c0caa2e2SCy Schubert 
920971980c3SDag-Erling Smørgrav int
921971980c3SDag-Erling Smørgrav listen_sslctx_setup(void* ctxt)
922971980c3SDag-Erling Smørgrav {
923971980c3SDag-Erling Smørgrav #ifdef HAVE_SSL
924971980c3SDag-Erling Smørgrav 	SSL_CTX* ctx = (SSL_CTX*)ctxt;
925971980c3SDag-Erling Smørgrav 	/* no SSLv2, SSLv3 because has defects */
926091e9e46SCy Schubert #if SSL_OP_NO_SSLv2 != 0
927971980c3SDag-Erling Smørgrav 	if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
928971980c3SDag-Erling Smørgrav 		!= SSL_OP_NO_SSLv2){
929971980c3SDag-Erling Smørgrav 		log_crypto_err("could not set SSL_OP_NO_SSLv2");
930971980c3SDag-Erling Smørgrav 		return 0;
931971980c3SDag-Erling Smørgrav 	}
932091e9e46SCy Schubert #endif
933971980c3SDag-Erling Smørgrav 	if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
934971980c3SDag-Erling Smørgrav 		!= SSL_OP_NO_SSLv3){
935971980c3SDag-Erling Smørgrav 		log_crypto_err("could not set SSL_OP_NO_SSLv3");
936971980c3SDag-Erling Smørgrav 		return 0;
937971980c3SDag-Erling Smørgrav 	}
938971980c3SDag-Erling Smørgrav #if defined(SSL_OP_NO_TLSv1) && defined(SSL_OP_NO_TLSv1_1)
939971980c3SDag-Erling Smørgrav 	/* if we have tls 1.1 disable 1.0 */
940971980c3SDag-Erling Smørgrav 	if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1) & SSL_OP_NO_TLSv1)
941971980c3SDag-Erling Smørgrav 		!= SSL_OP_NO_TLSv1){
942971980c3SDag-Erling Smørgrav 		log_crypto_err("could not set SSL_OP_NO_TLSv1");
943971980c3SDag-Erling Smørgrav 		return 0;
944971980c3SDag-Erling Smørgrav 	}
945971980c3SDag-Erling Smørgrav #endif
946971980c3SDag-Erling Smørgrav #if defined(SSL_OP_NO_TLSv1_1) && defined(SSL_OP_NO_TLSv1_2)
947971980c3SDag-Erling Smørgrav 	/* if we have tls 1.2 disable 1.1 */
948971980c3SDag-Erling Smørgrav 	if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_1) & SSL_OP_NO_TLSv1_1)
949971980c3SDag-Erling Smørgrav 		!= SSL_OP_NO_TLSv1_1){
950971980c3SDag-Erling Smørgrav 		log_crypto_err("could not set SSL_OP_NO_TLSv1_1");
951971980c3SDag-Erling Smørgrav 		return 0;
952971980c3SDag-Erling Smørgrav 	}
953971980c3SDag-Erling Smørgrav #endif
9540eefd307SCy Schubert #if defined(SSL_OP_NO_RENEGOTIATION)
9550eefd307SCy Schubert 	/* disable client renegotiation */
9560eefd307SCy Schubert 	if((SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION) &
9570eefd307SCy Schubert 		SSL_OP_NO_RENEGOTIATION) != SSL_OP_NO_RENEGOTIATION) {
9580eefd307SCy Schubert 		log_crypto_err("could not set SSL_OP_NO_RENEGOTIATION");
9590eefd307SCy Schubert 		return 0;
9600eefd307SCy Schubert 	}
9610eefd307SCy Schubert #endif
962971980c3SDag-Erling Smørgrav #if defined(SHA256_DIGEST_LENGTH) && defined(USE_ECDSA)
963*24e36522SCy Schubert 	/* if we detect system-wide crypto policies, use those */
964*24e36522SCy Schubert 	if (access( "/etc/crypto-policies/config", F_OK ) != 0 ) {
965971980c3SDag-Erling Smørgrav 	/* if we have sha256, set the cipher list to have no known vulns */
96657bddd21SDag-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"))
967971980c3SDag-Erling Smørgrav 			log_crypto_err("could not set cipher list with SSL_CTX_set_cipher_list");
968*24e36522SCy Schubert 	}
969971980c3SDag-Erling Smørgrav #endif
970971980c3SDag-Erling Smørgrav 
971971980c3SDag-Erling Smørgrav 	if((SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE) &
972971980c3SDag-Erling Smørgrav 		SSL_OP_CIPHER_SERVER_PREFERENCE) !=
973971980c3SDag-Erling Smørgrav 		SSL_OP_CIPHER_SERVER_PREFERENCE) {
974971980c3SDag-Erling Smørgrav 		log_crypto_err("could not set SSL_OP_CIPHER_SERVER_PREFERENCE");
975971980c3SDag-Erling Smørgrav 		return 0;
976971980c3SDag-Erling Smørgrav 	}
977971980c3SDag-Erling Smørgrav 
978971980c3SDag-Erling Smørgrav #ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL
979971980c3SDag-Erling Smørgrav 	SSL_CTX_set_security_level(ctx, 0);
980971980c3SDag-Erling Smørgrav #endif
981c0caa2e2SCy Schubert #if defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB) && defined(HAVE_NGHTTP2)
982c0caa2e2SCy Schubert 	SSL_CTX_set_alpn_select_cb(ctx, alpn_select_cb, NULL);
983c0caa2e2SCy Schubert #endif
984971980c3SDag-Erling Smørgrav #else
985971980c3SDag-Erling Smørgrav 	(void)ctxt;
986971980c3SDag-Erling Smørgrav #endif /* HAVE_SSL */
987971980c3SDag-Erling Smørgrav 	return 1;
988971980c3SDag-Erling Smørgrav }
989971980c3SDag-Erling Smørgrav 
990971980c3SDag-Erling Smørgrav void
991971980c3SDag-Erling Smørgrav listen_sslctx_setup_2(void* ctxt)
992971980c3SDag-Erling Smørgrav {
993971980c3SDag-Erling Smørgrav #ifdef HAVE_SSL
994971980c3SDag-Erling Smørgrav 	SSL_CTX* ctx = (SSL_CTX*)ctxt;
995971980c3SDag-Erling Smørgrav 	(void)ctx;
996971980c3SDag-Erling Smørgrav #if HAVE_DECL_SSL_CTX_SET_ECDH_AUTO
997971980c3SDag-Erling Smørgrav 	if(!SSL_CTX_set_ecdh_auto(ctx,1)) {
998971980c3SDag-Erling Smørgrav 		log_crypto_err("Error in SSL_CTX_ecdh_auto, not enabling ECDHE");
999971980c3SDag-Erling Smørgrav 	}
1000971980c3SDag-Erling Smørgrav #elif defined(USE_ECDSA)
1001971980c3SDag-Erling Smørgrav 	if(1) {
1002971980c3SDag-Erling Smørgrav 		EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1);
1003971980c3SDag-Erling Smørgrav 		if (!ecdh) {
1004971980c3SDag-Erling Smørgrav 			log_crypto_err("could not find p256, not enabling ECDHE");
1005971980c3SDag-Erling Smørgrav 		} else {
1006971980c3SDag-Erling Smørgrav 			if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh)) {
1007971980c3SDag-Erling Smørgrav 				log_crypto_err("Error in SSL_CTX_set_tmp_ecdh, not enabling ECDHE");
1008971980c3SDag-Erling Smørgrav 			}
1009971980c3SDag-Erling Smørgrav 			EC_KEY_free (ecdh);
1010971980c3SDag-Erling Smørgrav 		}
1011971980c3SDag-Erling Smørgrav 	}
1012971980c3SDag-Erling Smørgrav #endif
1013971980c3SDag-Erling Smørgrav #else
1014971980c3SDag-Erling Smørgrav 	(void)ctxt;
1015971980c3SDag-Erling Smørgrav #endif /* HAVE_SSL */
1016971980c3SDag-Erling Smørgrav }
1017971980c3SDag-Erling Smørgrav 
1018b7579f77SDag-Erling Smørgrav void* listen_sslctx_create(char* key, char* pem, char* verifypem)
1019b7579f77SDag-Erling Smørgrav {
10208ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL
1021b7579f77SDag-Erling Smørgrav 	SSL_CTX* ctx = SSL_CTX_new(SSLv23_server_method());
1022b7579f77SDag-Erling Smørgrav 	if(!ctx) {
1023b7579f77SDag-Erling Smørgrav 		log_crypto_err("could not SSL_CTX_new");
1024b7579f77SDag-Erling Smørgrav 		return NULL;
1025b7579f77SDag-Erling Smørgrav 	}
1026e86b9096SDag-Erling Smørgrav 	if(!key || key[0] == 0) {
1027e86b9096SDag-Erling Smørgrav 		log_err("error: no tls-service-key file specified");
1028e86b9096SDag-Erling Smørgrav 		SSL_CTX_free(ctx);
1029e86b9096SDag-Erling Smørgrav 		return NULL;
1030e86b9096SDag-Erling Smørgrav 	}
1031e86b9096SDag-Erling Smørgrav 	if(!pem || pem[0] == 0) {
1032e86b9096SDag-Erling Smørgrav 		log_err("error: no tls-service-pem file specified");
1033e86b9096SDag-Erling Smørgrav 		SSL_CTX_free(ctx);
1034e86b9096SDag-Erling Smørgrav 		return NULL;
1035e86b9096SDag-Erling Smørgrav 	}
1036971980c3SDag-Erling Smørgrav 	if(!listen_sslctx_setup(ctx)) {
1037ff825849SDag-Erling Smørgrav 		SSL_CTX_free(ctx);
1038ff825849SDag-Erling Smørgrav 		return NULL;
1039ff825849SDag-Erling Smørgrav 	}
1040b75612f8SDag-Erling Smørgrav 	if(!SSL_CTX_use_certificate_chain_file(ctx, pem)) {
1041b7579f77SDag-Erling Smørgrav 		log_err("error for cert file: %s", pem);
1042b75612f8SDag-Erling Smørgrav 		log_crypto_err("error in SSL_CTX use_certificate_chain_file");
1043b7579f77SDag-Erling Smørgrav 		SSL_CTX_free(ctx);
1044b7579f77SDag-Erling Smørgrav 		return NULL;
1045b7579f77SDag-Erling Smørgrav 	}
1046b7579f77SDag-Erling Smørgrav 	if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) {
1047b7579f77SDag-Erling Smørgrav 		log_err("error for private key file: %s", key);
1048b7579f77SDag-Erling Smørgrav 		log_crypto_err("Error in SSL_CTX use_PrivateKey_file");
1049b7579f77SDag-Erling Smørgrav 		SSL_CTX_free(ctx);
1050b7579f77SDag-Erling Smørgrav 		return NULL;
1051b7579f77SDag-Erling Smørgrav 	}
1052b7579f77SDag-Erling Smørgrav 	if(!SSL_CTX_check_private_key(ctx)) {
1053b7579f77SDag-Erling Smørgrav 		log_err("error for key file: %s", key);
1054b7579f77SDag-Erling Smørgrav 		log_crypto_err("Error in SSL_CTX check_private_key");
1055b7579f77SDag-Erling Smørgrav 		SSL_CTX_free(ctx);
1056b7579f77SDag-Erling Smørgrav 		return NULL;
1057b7579f77SDag-Erling Smørgrav 	}
1058971980c3SDag-Erling Smørgrav 	listen_sslctx_setup_2(ctx);
1059b7579f77SDag-Erling Smørgrav 	if(verifypem && verifypem[0]) {
1060b7579f77SDag-Erling Smørgrav 		if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) {
1061b7579f77SDag-Erling Smørgrav 			log_crypto_err("Error in SSL_CTX verify locations");
1062b7579f77SDag-Erling Smørgrav 			SSL_CTX_free(ctx);
1063b7579f77SDag-Erling Smørgrav 			return NULL;
1064b7579f77SDag-Erling Smørgrav 		}
1065b7579f77SDag-Erling Smørgrav 		SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(
1066b7579f77SDag-Erling Smørgrav 			verifypem));
106725039b37SCy Schubert 		SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
1068b7579f77SDag-Erling Smørgrav 	}
1069b7579f77SDag-Erling Smørgrav 	return ctx;
10708ed2b524SDag-Erling Smørgrav #else
10718ed2b524SDag-Erling Smørgrav 	(void)key; (void)pem; (void)verifypem;
10728ed2b524SDag-Erling Smørgrav 	return NULL;
10738ed2b524SDag-Erling Smørgrav #endif
1074b7579f77SDag-Erling Smørgrav }
1075b7579f77SDag-Erling Smørgrav 
10763bd4df0aSDag-Erling Smørgrav #ifdef USE_WINSOCK
10773bd4df0aSDag-Erling Smørgrav /* For windows, the CA trust store is not read by openssl.
10783bd4df0aSDag-Erling Smørgrav    Add code to open the trust store using wincrypt API and add
10793bd4df0aSDag-Erling Smørgrav    the root certs into openssl trust store */
10803bd4df0aSDag-Erling Smørgrav static int
10813bd4df0aSDag-Erling Smørgrav add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx)
10823bd4df0aSDag-Erling Smørgrav {
10833bd4df0aSDag-Erling Smørgrav 	HCERTSTORE      hSystemStore;
10843bd4df0aSDag-Erling Smørgrav 	PCCERT_CONTEXT  pTargetCert = NULL;
10853bd4df0aSDag-Erling Smørgrav 	X509_STORE*	store;
10863bd4df0aSDag-Erling Smørgrav 
10873bd4df0aSDag-Erling Smørgrav 	verbose(VERB_ALGO, "Adding Windows certificates from system root store to CA store");
10883bd4df0aSDag-Erling Smørgrav 
10893bd4df0aSDag-Erling Smørgrav 	/* load just once per context lifetime for this version
10903bd4df0aSDag-Erling Smørgrav 	   TODO: dynamically update CA trust changes as they are available */
10913bd4df0aSDag-Erling Smørgrav 	if (!tls_ctx)
10923bd4df0aSDag-Erling Smørgrav 		return 0;
10933bd4df0aSDag-Erling Smørgrav 
10943bd4df0aSDag-Erling Smørgrav 	/* Call wincrypt's CertOpenStore to open the CA root store. */
10953bd4df0aSDag-Erling Smørgrav 
10963bd4df0aSDag-Erling Smørgrav 	if ((hSystemStore = CertOpenStore(
10973bd4df0aSDag-Erling Smørgrav 		CERT_STORE_PROV_SYSTEM,
10983bd4df0aSDag-Erling Smørgrav 		0,
10993bd4df0aSDag-Erling Smørgrav 		0,
11003bd4df0aSDag-Erling Smørgrav 		/* NOTE: mingw does not have this const: replace with 1 << 16 from code
11013bd4df0aSDag-Erling Smørgrav 		   CERT_SYSTEM_STORE_CURRENT_USER, */
11023bd4df0aSDag-Erling Smørgrav 		1 << 16,
11033bd4df0aSDag-Erling Smørgrav 		L"root")) == 0)
11043bd4df0aSDag-Erling Smørgrav 	{
11053bd4df0aSDag-Erling Smørgrav 		return 0;
11063bd4df0aSDag-Erling Smørgrav 	}
11073bd4df0aSDag-Erling Smørgrav 
11083bd4df0aSDag-Erling Smørgrav 	store = SSL_CTX_get_cert_store(tls_ctx);
11093bd4df0aSDag-Erling Smørgrav 	if (!store)
11103bd4df0aSDag-Erling Smørgrav 		return 0;
11113bd4df0aSDag-Erling Smørgrav 
11123bd4df0aSDag-Erling Smørgrav 	/* failure if the CA store is empty or the call fails */
11133bd4df0aSDag-Erling Smørgrav 	if ((pTargetCert = CertEnumCertificatesInStore(
11143bd4df0aSDag-Erling Smørgrav 		hSystemStore, pTargetCert)) == 0) {
11153bd4df0aSDag-Erling Smørgrav 		verbose(VERB_ALGO, "CA certificate store for Windows is empty.");
11163bd4df0aSDag-Erling Smørgrav 		return 0;
11173bd4df0aSDag-Erling Smørgrav 	}
11183bd4df0aSDag-Erling Smørgrav 	/* iterate over the windows cert store and add to openssl store */
11193bd4df0aSDag-Erling Smørgrav 	do
11203bd4df0aSDag-Erling Smørgrav 	{
11213bd4df0aSDag-Erling Smørgrav 		X509 *cert1 = d2i_X509(NULL,
11223bd4df0aSDag-Erling Smørgrav 			(const unsigned char **)&pTargetCert->pbCertEncoded,
11233bd4df0aSDag-Erling Smørgrav 			pTargetCert->cbCertEncoded);
11243bd4df0aSDag-Erling Smørgrav 		if (!cert1) {
11253bd4df0aSDag-Erling Smørgrav 			/* return error if a cert fails */
11263bd4df0aSDag-Erling Smørgrav 			verbose(VERB_ALGO, "%s %d:%s",
11273bd4df0aSDag-Erling Smørgrav 				"Unable to parse certificate in memory",
11283bd4df0aSDag-Erling Smørgrav 				(int)ERR_get_error(), ERR_error_string(ERR_get_error(), NULL));
11293bd4df0aSDag-Erling Smørgrav 			return 0;
11303bd4df0aSDag-Erling Smørgrav 		}
11313bd4df0aSDag-Erling Smørgrav 		else {
11323bd4df0aSDag-Erling Smørgrav 			/* return error if a cert add to store fails */
11333bd4df0aSDag-Erling Smørgrav 			if (X509_STORE_add_cert(store, cert1) == 0) {
11343bd4df0aSDag-Erling Smørgrav 				unsigned long error = ERR_peek_last_error();
11353bd4df0aSDag-Erling Smørgrav 
11363bd4df0aSDag-Erling Smørgrav 				/* Ignore error X509_R_CERT_ALREADY_IN_HASH_TABLE which means the
11373bd4df0aSDag-Erling Smørgrav 				* certificate is already in the store.  */
11383bd4df0aSDag-Erling Smørgrav 				if(ERR_GET_LIB(error) != ERR_LIB_X509 ||
11393bd4df0aSDag-Erling Smørgrav 				   ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
11403bd4df0aSDag-Erling Smørgrav 					verbose(VERB_ALGO, "%s %d:%s\n",
11413bd4df0aSDag-Erling Smørgrav 					    "Error adding certificate", (int)ERR_get_error(),
11423bd4df0aSDag-Erling Smørgrav 					     ERR_error_string(ERR_get_error(), NULL));
11433bd4df0aSDag-Erling Smørgrav 					X509_free(cert1);
11443bd4df0aSDag-Erling Smørgrav 					return 0;
11453bd4df0aSDag-Erling Smørgrav 				}
11463bd4df0aSDag-Erling Smørgrav 			}
11473bd4df0aSDag-Erling Smørgrav 			X509_free(cert1);
11483bd4df0aSDag-Erling Smørgrav 		}
11493bd4df0aSDag-Erling Smørgrav 	} while ((pTargetCert = CertEnumCertificatesInStore(
11503bd4df0aSDag-Erling Smørgrav 		hSystemStore, pTargetCert)) != 0);
11513bd4df0aSDag-Erling Smørgrav 
11523bd4df0aSDag-Erling Smørgrav 	/* Clean up memory and quit. */
11533bd4df0aSDag-Erling Smørgrav 	if (pTargetCert)
11543bd4df0aSDag-Erling Smørgrav 		CertFreeCertificateContext(pTargetCert);
11553bd4df0aSDag-Erling Smørgrav 	if (hSystemStore)
11563bd4df0aSDag-Erling Smørgrav 	{
11573bd4df0aSDag-Erling Smørgrav 		if (!CertCloseStore(
11583bd4df0aSDag-Erling Smørgrav 			hSystemStore, 0))
11593bd4df0aSDag-Erling Smørgrav 			return 0;
11603bd4df0aSDag-Erling Smørgrav 	}
11613bd4df0aSDag-Erling Smørgrav 	verbose(VERB_ALGO, "Completed adding Windows certificates to CA store successfully");
11623bd4df0aSDag-Erling Smørgrav 	return 1;
11633bd4df0aSDag-Erling Smørgrav }
11643bd4df0aSDag-Erling Smørgrav #endif /* USE_WINSOCK */
11653bd4df0aSDag-Erling Smørgrav 
11663bd4df0aSDag-Erling Smørgrav void* connect_sslctx_create(char* key, char* pem, char* verifypem, int wincert)
1167b7579f77SDag-Erling Smørgrav {
11688ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL
1169b7579f77SDag-Erling Smørgrav 	SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method());
1170b7579f77SDag-Erling Smørgrav 	if(!ctx) {
1171b7579f77SDag-Erling Smørgrav 		log_crypto_err("could not allocate SSL_CTX pointer");
1172b7579f77SDag-Erling Smørgrav 		return NULL;
1173b7579f77SDag-Erling Smørgrav 	}
1174091e9e46SCy Schubert #if SSL_OP_NO_SSLv2 != 0
117505ab2901SDag-Erling Smørgrav 	if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
117605ab2901SDag-Erling Smørgrav 		!= SSL_OP_NO_SSLv2) {
1177b7579f77SDag-Erling Smørgrav 		log_crypto_err("could not set SSL_OP_NO_SSLv2");
1178b7579f77SDag-Erling Smørgrav 		SSL_CTX_free(ctx);
1179b7579f77SDag-Erling Smørgrav 		return NULL;
1180b7579f77SDag-Erling Smørgrav 	}
1181091e9e46SCy Schubert #endif
118205ab2901SDag-Erling Smørgrav 	if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
118305ab2901SDag-Erling Smørgrav 		!= SSL_OP_NO_SSLv3) {
1184ff825849SDag-Erling Smørgrav 		log_crypto_err("could not set SSL_OP_NO_SSLv3");
1185ff825849SDag-Erling Smørgrav 		SSL_CTX_free(ctx);
1186ff825849SDag-Erling Smørgrav 		return NULL;
1187ff825849SDag-Erling Smørgrav 	}
11880eefd307SCy Schubert #if defined(SSL_OP_NO_RENEGOTIATION)
11890eefd307SCy Schubert 	/* disable client renegotiation */
11900eefd307SCy Schubert 	if((SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION) &
11910eefd307SCy Schubert 		SSL_OP_NO_RENEGOTIATION) != SSL_OP_NO_RENEGOTIATION) {
11920eefd307SCy Schubert 		log_crypto_err("could not set SSL_OP_NO_RENEGOTIATION");
1193*24e36522SCy Schubert 		SSL_CTX_free(ctx);
11940eefd307SCy Schubert 		return 0;
11950eefd307SCy Schubert 	}
11960eefd307SCy Schubert #endif
1197b7579f77SDag-Erling Smørgrav 	if(key && key[0]) {
1198b75612f8SDag-Erling Smørgrav 		if(!SSL_CTX_use_certificate_chain_file(ctx, pem)) {
1199b7579f77SDag-Erling Smørgrav 			log_err("error in client certificate %s", pem);
1200b7579f77SDag-Erling Smørgrav 			log_crypto_err("error in certificate file");
1201b7579f77SDag-Erling Smørgrav 			SSL_CTX_free(ctx);
1202b7579f77SDag-Erling Smørgrav 			return NULL;
1203b7579f77SDag-Erling Smørgrav 		}
1204b7579f77SDag-Erling Smørgrav 		if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) {
1205b7579f77SDag-Erling Smørgrav 			log_err("error in client private key %s", key);
1206b7579f77SDag-Erling Smørgrav 			log_crypto_err("error in key file");
1207b7579f77SDag-Erling Smørgrav 			SSL_CTX_free(ctx);
1208b7579f77SDag-Erling Smørgrav 			return NULL;
1209b7579f77SDag-Erling Smørgrav 		}
1210b7579f77SDag-Erling Smørgrav 		if(!SSL_CTX_check_private_key(ctx)) {
1211b7579f77SDag-Erling Smørgrav 			log_err("error in client key %s", key);
1212b7579f77SDag-Erling Smørgrav 			log_crypto_err("error in SSL_CTX_check_private_key");
1213b7579f77SDag-Erling Smørgrav 			SSL_CTX_free(ctx);
1214b7579f77SDag-Erling Smørgrav 			return NULL;
1215b7579f77SDag-Erling Smørgrav 		}
1216b7579f77SDag-Erling Smørgrav 	}
12173bd4df0aSDag-Erling Smørgrav 	if((verifypem && verifypem[0]) || wincert) {
1218b7579f77SDag-Erling Smørgrav 		if(verifypem && verifypem[0]) {
1219ff825849SDag-Erling Smørgrav 			if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) {
1220b7579f77SDag-Erling Smørgrav 				log_crypto_err("error in SSL_CTX verify");
1221b7579f77SDag-Erling Smørgrav 				SSL_CTX_free(ctx);
1222b7579f77SDag-Erling Smørgrav 				return NULL;
1223b7579f77SDag-Erling Smørgrav 			}
12243bd4df0aSDag-Erling Smørgrav 		}
12253bd4df0aSDag-Erling Smørgrav #ifdef USE_WINSOCK
12263bd4df0aSDag-Erling Smørgrav 		if(wincert) {
12273bd4df0aSDag-Erling Smørgrav 			if(!add_WIN_cacerts_to_openssl_store(ctx)) {
12283bd4df0aSDag-Erling Smørgrav 				log_crypto_err("error in add_WIN_cacerts_to_openssl_store");
12293bd4df0aSDag-Erling Smørgrav 				SSL_CTX_free(ctx);
12303bd4df0aSDag-Erling Smørgrav 				return NULL;
12313bd4df0aSDag-Erling Smørgrav 			}
12323bd4df0aSDag-Erling Smørgrav 		}
12333bd4df0aSDag-Erling Smørgrav #else
12343bd4df0aSDag-Erling Smørgrav 		(void)wincert;
12353bd4df0aSDag-Erling Smørgrav #endif
1236b7579f77SDag-Erling Smørgrav 		SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
1237b7579f77SDag-Erling Smørgrav 	}
1238b7579f77SDag-Erling Smørgrav 	return ctx;
12398ed2b524SDag-Erling Smørgrav #else
12403bd4df0aSDag-Erling Smørgrav 	(void)key; (void)pem; (void)verifypem; (void)wincert;
12418ed2b524SDag-Erling Smørgrav 	return NULL;
12428ed2b524SDag-Erling Smørgrav #endif
1243b7579f77SDag-Erling Smørgrav }
1244b7579f77SDag-Erling Smørgrav 
1245b7579f77SDag-Erling Smørgrav void* incoming_ssl_fd(void* sslctx, int fd)
1246b7579f77SDag-Erling Smørgrav {
12478ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL
1248b7579f77SDag-Erling Smørgrav 	SSL* ssl = SSL_new((SSL_CTX*)sslctx);
1249b7579f77SDag-Erling Smørgrav 	if(!ssl) {
1250b7579f77SDag-Erling Smørgrav 		log_crypto_err("could not SSL_new");
1251b7579f77SDag-Erling Smørgrav 		return NULL;
1252b7579f77SDag-Erling Smørgrav 	}
1253b7579f77SDag-Erling Smørgrav 	SSL_set_accept_state(ssl);
12540eefd307SCy Schubert 	(void)SSL_set_mode(ssl, (long)SSL_MODE_AUTO_RETRY);
1255b7579f77SDag-Erling Smørgrav 	if(!SSL_set_fd(ssl, fd)) {
1256b7579f77SDag-Erling Smørgrav 		log_crypto_err("could not SSL_set_fd");
1257b7579f77SDag-Erling Smørgrav 		SSL_free(ssl);
1258b7579f77SDag-Erling Smørgrav 		return NULL;
1259b7579f77SDag-Erling Smørgrav 	}
1260b7579f77SDag-Erling Smørgrav 	return ssl;
12618ed2b524SDag-Erling Smørgrav #else
12628ed2b524SDag-Erling Smørgrav 	(void)sslctx; (void)fd;
12638ed2b524SDag-Erling Smørgrav 	return NULL;
12648ed2b524SDag-Erling Smørgrav #endif
1265b7579f77SDag-Erling Smørgrav }
1266b7579f77SDag-Erling Smørgrav 
1267b7579f77SDag-Erling Smørgrav void* outgoing_ssl_fd(void* sslctx, int fd)
1268b7579f77SDag-Erling Smørgrav {
12698ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL
1270b7579f77SDag-Erling Smørgrav 	SSL* ssl = SSL_new((SSL_CTX*)sslctx);
1271b7579f77SDag-Erling Smørgrav 	if(!ssl) {
1272b7579f77SDag-Erling Smørgrav 		log_crypto_err("could not SSL_new");
1273b7579f77SDag-Erling Smørgrav 		return NULL;
1274b7579f77SDag-Erling Smørgrav 	}
1275b7579f77SDag-Erling Smørgrav 	SSL_set_connect_state(ssl);
12760eefd307SCy Schubert 	(void)SSL_set_mode(ssl, (long)SSL_MODE_AUTO_RETRY);
1277b7579f77SDag-Erling Smørgrav 	if(!SSL_set_fd(ssl, fd)) {
1278b7579f77SDag-Erling Smørgrav 		log_crypto_err("could not SSL_set_fd");
1279b7579f77SDag-Erling Smørgrav 		SSL_free(ssl);
1280b7579f77SDag-Erling Smørgrav 		return NULL;
1281b7579f77SDag-Erling Smørgrav 	}
1282b7579f77SDag-Erling Smørgrav 	return ssl;
12838ed2b524SDag-Erling Smørgrav #else
12848ed2b524SDag-Erling Smørgrav 	(void)sslctx; (void)fd;
12858ed2b524SDag-Erling Smørgrav 	return NULL;
12868ed2b524SDag-Erling Smørgrav #endif
1287b7579f77SDag-Erling Smørgrav }
12888ed2b524SDag-Erling Smørgrav 
128925039b37SCy Schubert int check_auth_name_for_ssl(char* auth_name)
129025039b37SCy Schubert {
129125039b37SCy Schubert 	if(!auth_name) return 1;
129225039b37SCy Schubert #if defined(HAVE_SSL) && !defined(HAVE_SSL_SET1_HOST) && !defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
129325039b37SCy Schubert 	log_err("the query has an auth_name %s, but libssl has no call to "
129425039b37SCy Schubert 		"perform TLS authentication.  Remove that name from config "
129525039b37SCy Schubert 		"or upgrade the ssl crypto library.", auth_name);
129625039b37SCy Schubert 	return 0;
129725039b37SCy Schubert #else
129825039b37SCy Schubert 	return 1;
129925039b37SCy Schubert #endif
130025039b37SCy Schubert }
130125039b37SCy Schubert 
130225039b37SCy Schubert /** set the authname on an SSL structure, SSL* ssl */
130325039b37SCy Schubert int set_auth_name_on_ssl(void* ssl, char* auth_name, int use_sni)
130425039b37SCy Schubert {
130525039b37SCy Schubert 	if(!auth_name) return 1;
130625039b37SCy Schubert #ifdef HAVE_SSL
130725039b37SCy Schubert 	if(use_sni) {
130825039b37SCy Schubert 		(void)SSL_set_tlsext_host_name(ssl, auth_name);
130925039b37SCy Schubert 	}
131025039b37SCy Schubert #else
131125039b37SCy Schubert 	(void)ssl;
131225039b37SCy Schubert 	(void)use_sni;
131325039b37SCy Schubert #endif
131425039b37SCy Schubert #ifdef HAVE_SSL_SET1_HOST
131525039b37SCy Schubert 	SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL);
131625039b37SCy Schubert 	/* setting the hostname makes openssl verify the
131725039b37SCy Schubert 	 * host name in the x509 certificate in the
131825039b37SCy Schubert 	 * SSL connection*/
131925039b37SCy Schubert 	if(!SSL_set1_host(ssl, auth_name)) {
132025039b37SCy Schubert 		log_err("SSL_set1_host failed");
132125039b37SCy Schubert 		return 0;
132225039b37SCy Schubert 	}
132325039b37SCy Schubert #elif defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
132425039b37SCy Schubert 	/* openssl 1.0.2 has this function that can be used for
132525039b37SCy Schubert 	 * set1_host like verification */
132625039b37SCy Schubert 	if(auth_name) {
132725039b37SCy Schubert 		X509_VERIFY_PARAM* param = SSL_get0_param(ssl);
132825039b37SCy Schubert #  ifdef X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS
132925039b37SCy Schubert 		X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
133025039b37SCy Schubert #  endif
133125039b37SCy Schubert 		if(!X509_VERIFY_PARAM_set1_host(param, auth_name, strlen(auth_name))) {
133225039b37SCy Schubert 			log_err("X509_VERIFY_PARAM_set1_host failed");
133325039b37SCy Schubert 			return 0;
133425039b37SCy Schubert 		}
133525039b37SCy Schubert 		SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL);
133625039b37SCy Schubert 	}
133725039b37SCy Schubert #else
133825039b37SCy Schubert 	verbose(VERB_ALGO, "the query has an auth_name, but libssl has no call to perform TLS authentication");
133925039b37SCy Schubert #endif /* HAVE_SSL_SET1_HOST */
134025039b37SCy Schubert 	return 1;
134125039b37SCy Schubert }
134225039b37SCy Schubert 
1343b5663de9SDag-Erling Smørgrav #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L
13448ed2b524SDag-Erling Smørgrav /** global lock list for openssl locks */
13453005e0a3SDag-Erling Smørgrav static lock_basic_type *ub_openssl_locks = NULL;
13468ed2b524SDag-Erling Smørgrav 
13478ed2b524SDag-Erling Smørgrav /** callback that gets thread id for openssl */
1348e86b9096SDag-Erling Smørgrav #ifdef HAVE_CRYPTO_THREADID_SET_CALLBACK
1349e86b9096SDag-Erling Smørgrav static void
1350e86b9096SDag-Erling Smørgrav ub_crypto_id_cb(CRYPTO_THREADID *id)
1351e86b9096SDag-Erling Smørgrav {
1352e86b9096SDag-Erling Smørgrav 	CRYPTO_THREADID_set_numeric(id, (unsigned long)log_thread_get());
1353e86b9096SDag-Erling Smørgrav }
1354e86b9096SDag-Erling Smørgrav #else
13558ed2b524SDag-Erling Smørgrav static unsigned long
13568ed2b524SDag-Erling Smørgrav ub_crypto_id_cb(void)
13578ed2b524SDag-Erling Smørgrav {
135809a3aaf3SDag-Erling Smørgrav 	return (unsigned long)log_thread_get();
13598ed2b524SDag-Erling Smørgrav }
1360e86b9096SDag-Erling Smørgrav #endif
13618ed2b524SDag-Erling Smørgrav 
13628ed2b524SDag-Erling Smørgrav static void
13638ed2b524SDag-Erling Smørgrav ub_crypto_lock_cb(int mode, int type, const char *ATTR_UNUSED(file),
13648ed2b524SDag-Erling Smørgrav 	int ATTR_UNUSED(line))
13658ed2b524SDag-Erling Smørgrav {
13668ed2b524SDag-Erling Smørgrav 	if((mode&CRYPTO_LOCK)) {
13678ed2b524SDag-Erling Smørgrav 		lock_basic_lock(&ub_openssl_locks[type]);
13688ed2b524SDag-Erling Smørgrav 	} else {
13698ed2b524SDag-Erling Smørgrav 		lock_basic_unlock(&ub_openssl_locks[type]);
13708ed2b524SDag-Erling Smørgrav 	}
13718ed2b524SDag-Erling Smørgrav }
13728ed2b524SDag-Erling Smørgrav #endif /* OPENSSL_THREADS */
13738ed2b524SDag-Erling Smørgrav 
13748ed2b524SDag-Erling Smørgrav int ub_openssl_lock_init(void)
13758ed2b524SDag-Erling Smørgrav {
1376b5663de9SDag-Erling Smørgrav #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L
13778ed2b524SDag-Erling Smørgrav 	int i;
13783005e0a3SDag-Erling Smørgrav 	ub_openssl_locks = (lock_basic_type*)reallocarray(
13793005e0a3SDag-Erling Smørgrav 		NULL, (size_t)CRYPTO_num_locks(), sizeof(lock_basic_type));
13808ed2b524SDag-Erling Smørgrav 	if(!ub_openssl_locks)
13818ed2b524SDag-Erling Smørgrav 		return 0;
13828ed2b524SDag-Erling Smørgrav 	for(i=0; i<CRYPTO_num_locks(); i++) {
13838ed2b524SDag-Erling Smørgrav 		lock_basic_init(&ub_openssl_locks[i]);
13848ed2b524SDag-Erling Smørgrav 	}
1385e86b9096SDag-Erling Smørgrav #  ifdef HAVE_CRYPTO_THREADID_SET_CALLBACK
1386e86b9096SDag-Erling Smørgrav 	CRYPTO_THREADID_set_callback(&ub_crypto_id_cb);
1387e86b9096SDag-Erling Smørgrav #  else
13888ed2b524SDag-Erling Smørgrav 	CRYPTO_set_id_callback(&ub_crypto_id_cb);
1389e86b9096SDag-Erling Smørgrav #  endif
13908ed2b524SDag-Erling Smørgrav 	CRYPTO_set_locking_callback(&ub_crypto_lock_cb);
13918ed2b524SDag-Erling Smørgrav #endif /* OPENSSL_THREADS */
13928ed2b524SDag-Erling Smørgrav 	return 1;
13938ed2b524SDag-Erling Smørgrav }
13948ed2b524SDag-Erling Smørgrav 
13958ed2b524SDag-Erling Smørgrav void ub_openssl_lock_delete(void)
13968ed2b524SDag-Erling Smørgrav {
1397b5663de9SDag-Erling Smørgrav #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L
13988ed2b524SDag-Erling Smørgrav 	int i;
13998ed2b524SDag-Erling Smørgrav 	if(!ub_openssl_locks)
14008ed2b524SDag-Erling Smørgrav 		return;
1401e86b9096SDag-Erling Smørgrav #  ifdef HAVE_CRYPTO_THREADID_SET_CALLBACK
1402e86b9096SDag-Erling Smørgrav 	CRYPTO_THREADID_set_callback(NULL);
1403e86b9096SDag-Erling Smørgrav #  else
14048ed2b524SDag-Erling Smørgrav 	CRYPTO_set_id_callback(NULL);
1405e86b9096SDag-Erling Smørgrav #  endif
14068ed2b524SDag-Erling Smørgrav 	CRYPTO_set_locking_callback(NULL);
14078ed2b524SDag-Erling Smørgrav 	for(i=0; i<CRYPTO_num_locks(); i++) {
14088ed2b524SDag-Erling Smørgrav 		lock_basic_destroy(&ub_openssl_locks[i]);
14098ed2b524SDag-Erling Smørgrav 	}
14108ed2b524SDag-Erling Smørgrav 	free(ub_openssl_locks);
14118ed2b524SDag-Erling Smørgrav #endif /* OPENSSL_THREADS */
14128ed2b524SDag-Erling Smørgrav }
14138ed2b524SDag-Erling Smørgrav 
1414e86b9096SDag-Erling Smørgrav int listen_sslctx_setup_ticket_keys(void* sslctx, struct config_strlist* tls_session_ticket_keys) {
1415e86b9096SDag-Erling Smørgrav #ifdef HAVE_SSL
1416e86b9096SDag-Erling Smørgrav 	size_t s = 1;
1417e86b9096SDag-Erling Smørgrav 	struct config_strlist* p;
1418e86b9096SDag-Erling Smørgrav 	struct tls_session_ticket_key *keys;
1419e86b9096SDag-Erling Smørgrav 	for(p = tls_session_ticket_keys; p; p = p->next) {
1420e86b9096SDag-Erling Smørgrav 		s++;
1421e86b9096SDag-Erling Smørgrav 	}
1422e86b9096SDag-Erling Smørgrav 	keys = calloc(s, sizeof(struct tls_session_ticket_key));
1423091e9e46SCy Schubert 	if(!keys)
1424091e9e46SCy Schubert 		return 0;
1425e86b9096SDag-Erling Smørgrav 	memset(keys, 0, s*sizeof(*keys));
1426e86b9096SDag-Erling Smørgrav 	ticket_keys = keys;
1427e86b9096SDag-Erling Smørgrav 
1428e86b9096SDag-Erling Smørgrav 	for(p = tls_session_ticket_keys; p; p = p->next) {
1429e86b9096SDag-Erling Smørgrav 		size_t n;
1430091e9e46SCy Schubert 		unsigned char *data;
1431091e9e46SCy Schubert 		FILE *f;
1432091e9e46SCy Schubert 
1433091e9e46SCy Schubert 		data = (unsigned char *)malloc(80);
1434091e9e46SCy Schubert 		if(!data)
1435091e9e46SCy Schubert 			return 0;
1436091e9e46SCy Schubert 
143725039b37SCy Schubert 		f = fopen(p->str, "rb");
1438e86b9096SDag-Erling Smørgrav 		if(!f) {
1439e86b9096SDag-Erling Smørgrav 			log_err("could not read tls-session-ticket-key %s: %s", p->str, strerror(errno));
1440e86b9096SDag-Erling Smørgrav 			free(data);
1441e86b9096SDag-Erling Smørgrav 			return 0;
1442e86b9096SDag-Erling Smørgrav 		}
1443e86b9096SDag-Erling Smørgrav 		n = fread(data, 1, 80, f);
1444e86b9096SDag-Erling Smørgrav 		fclose(f);
1445e86b9096SDag-Erling Smørgrav 
1446e86b9096SDag-Erling Smørgrav 		if(n != 80) {
1447e86b9096SDag-Erling Smørgrav 			log_err("tls-session-ticket-key %s is %d bytes, must be 80 bytes", p->str, (int)n);
1448e86b9096SDag-Erling Smørgrav 			free(data);
1449e86b9096SDag-Erling Smørgrav 			return 0;
1450e86b9096SDag-Erling Smørgrav 		}
1451e86b9096SDag-Erling Smørgrav 		verbose(VERB_OPS, "read tls-session-ticket-key: %s", p->str);
1452e86b9096SDag-Erling Smørgrav 
1453e86b9096SDag-Erling Smørgrav 		keys->key_name = data;
1454e86b9096SDag-Erling Smørgrav 		keys->aes_key = data + 16;
1455e86b9096SDag-Erling Smørgrav 		keys->hmac_key = data + 48;
1456e86b9096SDag-Erling Smørgrav 		keys++;
1457e86b9096SDag-Erling Smørgrav 	}
1458e86b9096SDag-Erling Smørgrav 	/* terminate array with NULL key name entry */
1459e86b9096SDag-Erling Smørgrav 	keys->key_name = NULL;
146025039b37SCy Schubert #  ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
146125039b37SCy Schubert 	if(SSL_CTX_set_tlsext_ticket_key_evp_cb(sslctx, tls_session_ticket_key_cb) == 0) {
146225039b37SCy Schubert 		log_err("no support for TLS session ticket");
146325039b37SCy Schubert 		return 0;
146425039b37SCy Schubert 	}
146525039b37SCy Schubert #  else
1466e86b9096SDag-Erling Smørgrav 	if(SSL_CTX_set_tlsext_ticket_key_cb(sslctx, tls_session_ticket_key_cb) == 0) {
1467e86b9096SDag-Erling Smørgrav 		log_err("no support for TLS session ticket");
1468e86b9096SDag-Erling Smørgrav 		return 0;
1469e86b9096SDag-Erling Smørgrav 	}
147025039b37SCy Schubert #  endif
1471e86b9096SDag-Erling Smørgrav 	return 1;
1472e86b9096SDag-Erling Smørgrav #else
1473e86b9096SDag-Erling Smørgrav 	(void)sslctx;
1474e86b9096SDag-Erling Smørgrav 	(void)tls_session_ticket_keys;
1475e86b9096SDag-Erling Smørgrav 	return 0;
1476e86b9096SDag-Erling Smørgrav #endif
1477e86b9096SDag-Erling Smørgrav 
1478e86b9096SDag-Erling Smørgrav }
1479e86b9096SDag-Erling Smørgrav 
148025039b37SCy Schubert #ifdef HAVE_SSL
148125039b37SCy Schubert int tls_session_ticket_key_cb(SSL *ATTR_UNUSED(sslctx), unsigned char* key_name,
148225039b37SCy Schubert 	unsigned char* iv, EVP_CIPHER_CTX *evp_sctx,
148325039b37SCy Schubert #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
148425039b37SCy Schubert 	EVP_MAC_CTX *hmac_ctx,
148525039b37SCy Schubert #else
148625039b37SCy Schubert 	HMAC_CTX* hmac_ctx,
148725039b37SCy Schubert #endif
148825039b37SCy Schubert 	int enc)
1489e86b9096SDag-Erling Smørgrav {
1490e86b9096SDag-Erling Smørgrav #ifdef HAVE_SSL
149125039b37SCy Schubert #  ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
149225039b37SCy Schubert 	OSSL_PARAM params[3];
149325039b37SCy Schubert #  else
1494e86b9096SDag-Erling Smørgrav 	const EVP_MD *digest;
149525039b37SCy Schubert #  endif
1496e86b9096SDag-Erling Smørgrav 	const EVP_CIPHER *cipher;
1497e86b9096SDag-Erling Smørgrav 	int evp_cipher_length;
149825039b37SCy Schubert #  ifndef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
1499e86b9096SDag-Erling Smørgrav 	digest = EVP_sha256();
150025039b37SCy Schubert #  endif
1501e86b9096SDag-Erling Smørgrav 	cipher = EVP_aes_256_cbc();
1502e86b9096SDag-Erling Smørgrav 	evp_cipher_length = EVP_CIPHER_iv_length(cipher);
1503e86b9096SDag-Erling Smørgrav 	if( enc == 1 ) {
1504e86b9096SDag-Erling Smørgrav 		/* encrypt */
1505e86b9096SDag-Erling Smørgrav 		verbose(VERB_CLIENT, "start session encrypt");
1506e86b9096SDag-Erling Smørgrav 		memcpy(key_name, ticket_keys->key_name, 16);
1507e86b9096SDag-Erling Smørgrav 		if (RAND_bytes(iv, evp_cipher_length) != 1) {
1508e86b9096SDag-Erling Smørgrav 			verbose(VERB_CLIENT, "RAND_bytes failed");
1509e86b9096SDag-Erling Smørgrav 			return -1;
1510e86b9096SDag-Erling Smørgrav 		}
1511e86b9096SDag-Erling Smørgrav 		if (EVP_EncryptInit_ex(evp_sctx, cipher, NULL, ticket_keys->aes_key, iv) != 1) {
1512e86b9096SDag-Erling Smørgrav 			verbose(VERB_CLIENT, "EVP_EncryptInit_ex failed");
1513e86b9096SDag-Erling Smørgrav 			return -1;
1514e86b9096SDag-Erling Smørgrav 		}
151525039b37SCy Schubert #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
151625039b37SCy Schubert 		params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
151725039b37SCy Schubert 			ticket_keys->hmac_key, 32);
151825039b37SCy Schubert 		params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
151925039b37SCy Schubert 			"sha256", 0);
152025039b37SCy Schubert 		params[2] = OSSL_PARAM_construct_end();
1521c0caa2e2SCy Schubert #ifdef HAVE_EVP_MAC_CTX_SET_PARAMS
1522c0caa2e2SCy Schubert 		EVP_MAC_CTX_set_params(hmac_ctx, params);
1523c0caa2e2SCy Schubert #else
152425039b37SCy Schubert 		EVP_MAC_set_ctx_params(hmac_ctx, params);
1525c0caa2e2SCy Schubert #endif
152625039b37SCy Schubert #elif !defined(HMAC_INIT_EX_RETURNS_VOID)
1527e86b9096SDag-Erling Smørgrav 		if (HMAC_Init_ex(hmac_ctx, ticket_keys->hmac_key, 32, digest, NULL) != 1) {
1528e86b9096SDag-Erling Smørgrav 			verbose(VERB_CLIENT, "HMAC_Init_ex failed");
1529e86b9096SDag-Erling Smørgrav 			return -1;
1530e86b9096SDag-Erling Smørgrav 		}
15310eefd307SCy Schubert #else
15320eefd307SCy Schubert 		HMAC_Init_ex(hmac_ctx, ticket_keys->hmac_key, 32, digest, NULL);
15330eefd307SCy Schubert #endif
1534e86b9096SDag-Erling Smørgrav 		return 1;
1535e86b9096SDag-Erling Smørgrav 	} else if (enc == 0) {
1536e86b9096SDag-Erling Smørgrav 		/* decrypt */
1537e86b9096SDag-Erling Smørgrav 		struct tls_session_ticket_key *key;
1538e86b9096SDag-Erling Smørgrav 		verbose(VERB_CLIENT, "start session decrypt");
1539e86b9096SDag-Erling Smørgrav 		for(key = ticket_keys; key->key_name != NULL; key++) {
1540e86b9096SDag-Erling Smørgrav 			if (!memcmp(key_name, key->key_name, 16)) {
1541e86b9096SDag-Erling Smørgrav 				verbose(VERB_CLIENT, "Found session_key");
1542e86b9096SDag-Erling Smørgrav 				break;
1543e86b9096SDag-Erling Smørgrav 			}
1544e86b9096SDag-Erling Smørgrav 		}
1545e86b9096SDag-Erling Smørgrav 		if(key->key_name == NULL) {
1546e86b9096SDag-Erling Smørgrav 			verbose(VERB_CLIENT, "Not found session_key");
1547e86b9096SDag-Erling Smørgrav 			return 0;
1548e86b9096SDag-Erling Smørgrav 		}
1549e86b9096SDag-Erling Smørgrav 
155025039b37SCy Schubert #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
155125039b37SCy Schubert 		params[0] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
155225039b37SCy Schubert 			key->hmac_key, 32);
155325039b37SCy Schubert 		params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
155425039b37SCy Schubert 			"sha256", 0);
155525039b37SCy Schubert 		params[2] = OSSL_PARAM_construct_end();
1556c0caa2e2SCy Schubert #ifdef HAVE_EVP_MAC_CTX_SET_PARAMS
1557c0caa2e2SCy Schubert 		EVP_MAC_CTX_set_params(hmac_ctx, params);
1558c0caa2e2SCy Schubert #else
155925039b37SCy Schubert 		EVP_MAC_set_ctx_params(hmac_ctx, params);
1560c0caa2e2SCy Schubert #endif
156125039b37SCy Schubert #elif !defined(HMAC_INIT_EX_RETURNS_VOID)
1562e86b9096SDag-Erling Smørgrav 		if (HMAC_Init_ex(hmac_ctx, key->hmac_key, 32, digest, NULL) != 1) {
1563e86b9096SDag-Erling Smørgrav 			verbose(VERB_CLIENT, "HMAC_Init_ex failed");
1564e86b9096SDag-Erling Smørgrav 			return -1;
1565e86b9096SDag-Erling Smørgrav 		}
15660eefd307SCy Schubert #else
15670eefd307SCy Schubert 		HMAC_Init_ex(hmac_ctx, key->hmac_key, 32, digest, NULL);
15680eefd307SCy Schubert #endif
1569e86b9096SDag-Erling Smørgrav 		if (EVP_DecryptInit_ex(evp_sctx, cipher, NULL, key->aes_key, iv) != 1) {
1570e86b9096SDag-Erling Smørgrav 			log_err("EVP_DecryptInit_ex failed");
1571e86b9096SDag-Erling Smørgrav 			return -1;
1572e86b9096SDag-Erling Smørgrav 		}
1573e86b9096SDag-Erling Smørgrav 
1574e86b9096SDag-Erling Smørgrav 		return (key == ticket_keys) ? 1 : 2;
1575e86b9096SDag-Erling Smørgrav 	}
1576e86b9096SDag-Erling Smørgrav 	return -1;
1577e86b9096SDag-Erling Smørgrav #else
1578e86b9096SDag-Erling Smørgrav 	(void)key_name;
1579e86b9096SDag-Erling Smørgrav 	(void)iv;
1580e86b9096SDag-Erling Smørgrav 	(void)evp_sctx;
1581e86b9096SDag-Erling Smørgrav 	(void)hmac_ctx;
1582e86b9096SDag-Erling Smørgrav 	(void)enc;
1583e86b9096SDag-Erling Smørgrav 	return 0;
1584e86b9096SDag-Erling Smørgrav #endif
1585e86b9096SDag-Erling Smørgrav }
158625039b37SCy Schubert #endif /* HAVE_SSL */
1587e86b9096SDag-Erling Smørgrav 
1588e86b9096SDag-Erling Smørgrav void
1589e86b9096SDag-Erling Smørgrav listen_sslctx_delete_ticket_keys(void)
1590e86b9096SDag-Erling Smørgrav {
1591e86b9096SDag-Erling Smørgrav 	struct tls_session_ticket_key *key;
1592e86b9096SDag-Erling Smørgrav 	if(!ticket_keys) return;
1593e86b9096SDag-Erling Smørgrav 	for(key = ticket_keys; key->key_name != NULL; key++) {
1594e86b9096SDag-Erling Smørgrav 		/* wipe key data from memory*/
1595e86b9096SDag-Erling Smørgrav #ifdef HAVE_EXPLICIT_BZERO
1596e86b9096SDag-Erling Smørgrav 		explicit_bzero(key->key_name, 80);
1597e86b9096SDag-Erling Smørgrav #else
1598e86b9096SDag-Erling Smørgrav 		memset(key->key_name, 0xdd, 80);
1599e86b9096SDag-Erling Smørgrav #endif
1600e86b9096SDag-Erling Smørgrav 		free(key->key_name);
1601e86b9096SDag-Erling Smørgrav 	}
1602e86b9096SDag-Erling Smørgrav 	free(ticket_keys);
1603e86b9096SDag-Erling Smørgrav 	ticket_keys = NULL;
1604e86b9096SDag-Erling Smørgrav }
1605c0caa2e2SCy Schubert 
1606c0caa2e2SCy Schubert #  ifndef USE_WINSOCK
1607c0caa2e2SCy Schubert char*
1608c0caa2e2SCy Schubert sock_strerror(int errn)
1609c0caa2e2SCy Schubert {
1610c0caa2e2SCy Schubert 	return strerror(errn);
1611c0caa2e2SCy Schubert }
1612c0caa2e2SCy Schubert 
1613c0caa2e2SCy Schubert void
1614c0caa2e2SCy Schubert sock_close(int socket)
1615c0caa2e2SCy Schubert {
1616c0caa2e2SCy Schubert 	close(socket);
1617c0caa2e2SCy Schubert }
1618c0caa2e2SCy Schubert 
1619c0caa2e2SCy Schubert #  else
1620c0caa2e2SCy Schubert char*
1621c0caa2e2SCy Schubert sock_strerror(int ATTR_UNUSED(errn))
1622c0caa2e2SCy Schubert {
1623c0caa2e2SCy Schubert 	return wsa_strerror(WSAGetLastError());
1624c0caa2e2SCy Schubert }
1625c0caa2e2SCy Schubert 
1626c0caa2e2SCy Schubert void
1627c0caa2e2SCy Schubert sock_close(int socket)
1628c0caa2e2SCy Schubert {
1629c0caa2e2SCy Schubert 	closesocket(socket);
1630c0caa2e2SCy Schubert }
1631c0caa2e2SCy Schubert #  endif /* USE_WINSOCK */
1632