1b7579f77SDag-Erling Smørgrav /*
2b7579f77SDag-Erling Smørgrav * util/net_help.c - implementation of the network helper code
3b7579f77SDag-Erling Smørgrav *
4b7579f77SDag-Erling Smørgrav * Copyright (c) 2007, NLnet Labs. All rights reserved.
5b7579f77SDag-Erling Smørgrav *
6b7579f77SDag-Erling Smørgrav * This software is open source.
7b7579f77SDag-Erling Smørgrav *
8b7579f77SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without
9b7579f77SDag-Erling Smørgrav * modification, are permitted provided that the following conditions
10b7579f77SDag-Erling Smørgrav * are met:
11b7579f77SDag-Erling Smørgrav *
12b7579f77SDag-Erling Smørgrav * Redistributions of source code must retain the above copyright notice,
13b7579f77SDag-Erling Smørgrav * this list of conditions and the following disclaimer.
14b7579f77SDag-Erling Smørgrav *
15b7579f77SDag-Erling Smørgrav * Redistributions in binary form must reproduce the above copyright notice,
16b7579f77SDag-Erling Smørgrav * this list of conditions and the following disclaimer in the documentation
17b7579f77SDag-Erling Smørgrav * and/or other materials provided with the distribution.
18b7579f77SDag-Erling Smørgrav *
19b7579f77SDag-Erling Smørgrav * Neither the name of the NLNET LABS nor the names of its contributors may
20b7579f77SDag-Erling Smørgrav * be used to endorse or promote products derived from this software without
21b7579f77SDag-Erling Smørgrav * specific prior written permission.
22b7579f77SDag-Erling Smørgrav *
23b7579f77SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2417d15b25SDag-Erling Smørgrav * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2517d15b25SDag-Erling Smørgrav * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2617d15b25SDag-Erling Smørgrav * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2717d15b25SDag-Erling Smørgrav * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2817d15b25SDag-Erling Smørgrav * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
2917d15b25SDag-Erling Smørgrav * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
3017d15b25SDag-Erling Smørgrav * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3117d15b25SDag-Erling Smørgrav * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3217d15b25SDag-Erling Smørgrav * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3317d15b25SDag-Erling Smørgrav * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34b7579f77SDag-Erling Smørgrav */
35b7579f77SDag-Erling Smørgrav /**
36b7579f77SDag-Erling Smørgrav * \file
37b7579f77SDag-Erling Smørgrav * Implementation of net_help.h.
38b7579f77SDag-Erling Smørgrav */
39b7579f77SDag-Erling Smørgrav
40b7579f77SDag-Erling Smørgrav #include "config.h"
4124e36522SCy Schubert #ifdef HAVE_SYS_TYPES_H
4224e36522SCy Schubert # include <sys/types.h>
4324e36522SCy Schubert #endif
4424e36522SCy Schubert #ifdef HAVE_NET_IF_H
4524e36522SCy Schubert #include <net/if.h>
4624e36522SCy Schubert #endif
479cf5bc93SCy Schubert #ifdef HAVE_NETIOAPI_H
489cf5bc93SCy Schubert #include <netioapi.h>
499cf5bc93SCy Schubert #endif
50*56850988SCy Schubert #include <ctype.h>
51b7579f77SDag-Erling Smørgrav #include "util/net_help.h"
52b7579f77SDag-Erling Smørgrav #include "util/log.h"
53b7579f77SDag-Erling Smørgrav #include "util/data/dname.h"
54b7579f77SDag-Erling Smørgrav #include "util/module.h"
55b7579f77SDag-Erling Smørgrav #include "util/regional.h"
56e86b9096SDag-Erling Smørgrav #include "util/config_file.h"
5709a3aaf3SDag-Erling Smørgrav #include "sldns/parseutil.h"
5809a3aaf3SDag-Erling Smørgrav #include "sldns/wire2str.h"
599cf5bc93SCy Schubert #include "sldns/str2wire.h"
60b7579f77SDag-Erling Smørgrav #include <fcntl.h>
618ed2b524SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_SSL_H
62b7579f77SDag-Erling Smørgrav #include <openssl/ssl.h>
63e86b9096SDag-Erling Smørgrav #include <openssl/evp.h>
64e86b9096SDag-Erling Smørgrav #include <openssl/rand.h>
658ed2b524SDag-Erling Smørgrav #endif
668ed2b524SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_ERR_H
67b7579f77SDag-Erling Smørgrav #include <openssl/err.h>
688ed2b524SDag-Erling Smørgrav #endif
6925039b37SCy Schubert #ifdef HAVE_OPENSSL_CORE_NAMES_H
7025039b37SCy Schubert #include <openssl/core_names.h>
7125039b37SCy Schubert #endif
723bd4df0aSDag-Erling Smørgrav #ifdef USE_WINSOCK
733bd4df0aSDag-Erling Smørgrav #include <wincrypt.h>
743bd4df0aSDag-Erling Smørgrav #endif
75c0caa2e2SCy Schubert #ifdef HAVE_NGHTTP2_NGHTTP2_H
76c0caa2e2SCy Schubert #include <nghttp2/nghttp2.h>
77c0caa2e2SCy Schubert #endif
78b7579f77SDag-Erling Smørgrav
79b7579f77SDag-Erling Smørgrav /** max length of an IP address (the address portion) that we allow */
80b7579f77SDag-Erling Smørgrav #define MAX_ADDR_STRLEN 128 /* characters */
81335c7cdaSCy Schubert /** max length of a hostname (with port and tls name) that we allow */
82335c7cdaSCy Schubert #define MAX_HOST_STRLEN (LDNS_MAX_DOMAINLEN * 3) /* characters */
83b7579f77SDag-Erling Smørgrav /** default value for EDNS ADVERTISED size */
84b7579f77SDag-Erling Smørgrav uint16_t EDNS_ADVERTISED_SIZE = 4096;
85b7579f77SDag-Erling Smørgrav
86b7579f77SDag-Erling Smørgrav /** minimal responses when positive answer: default is no */
87b7579f77SDag-Erling Smørgrav int MINIMAL_RESPONSES = 0;
88b7579f77SDag-Erling Smørgrav
8925039b37SCy Schubert /** rrset order roundrobin: default is yes */
9025039b37SCy Schubert int RRSET_ROUNDROBIN = 1;
91b7579f77SDag-Erling Smørgrav
92e86b9096SDag-Erling Smørgrav /** log tag queries with name instead of 'info' for filtering */
93e86b9096SDag-Erling Smørgrav int LOG_TAG_QUERYREPLY = 0;
94e86b9096SDag-Erling Smørgrav
95e86b9096SDag-Erling Smørgrav static struct tls_session_ticket_key {
96e86b9096SDag-Erling Smørgrav unsigned char *key_name;
97e86b9096SDag-Erling Smørgrav unsigned char *aes_key;
98e86b9096SDag-Erling Smørgrav unsigned char *hmac_key;
99e86b9096SDag-Erling Smørgrav } *ticket_keys;
100e86b9096SDag-Erling Smørgrav
101c0caa2e2SCy Schubert #ifdef HAVE_SSL
10225039b37SCy Schubert /**
10325039b37SCy Schubert * callback TLS session ticket encrypt and decrypt
10425039b37SCy Schubert * For use with SSL_CTX_set_tlsext_ticket_key_cb or
10525039b37SCy Schubert * SSL_CTX_set_tlsext_ticket_key_evp_cb
10625039b37SCy Schubert * @param s: the SSL_CTX to use (from connect_sslctx_create())
10725039b37SCy Schubert * @param key_name: secret name, 16 bytes
10825039b37SCy Schubert * @param iv: up to EVP_MAX_IV_LENGTH.
10925039b37SCy Schubert * @param evp_ctx: the evp cipher context, function sets this.
11025039b37SCy Schubert * @param hmac_ctx: the hmac context, function sets this.
11125039b37SCy Schubert * with ..key_cb it is of type HMAC_CTX*
11225039b37SCy Schubert * with ..key_evp_cb it is of type EVP_MAC_CTX*
11325039b37SCy Schubert * @param enc: 1 is encrypt, 0 is decrypt
11425039b37SCy Schubert * @return 0 on no ticket, 1 for okay, and 2 for okay but renew the ticket
11525039b37SCy Schubert * (the ticket is decrypt only). and <0 for failures.
11625039b37SCy Schubert */
11725039b37SCy Schubert int tls_session_ticket_key_cb(SSL *s, unsigned char* key_name,
11825039b37SCy Schubert unsigned char* iv, EVP_CIPHER_CTX *evp_ctx,
11925039b37SCy Schubert #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
12025039b37SCy Schubert EVP_MAC_CTX *hmac_ctx,
12125039b37SCy Schubert #else
12225039b37SCy Schubert HMAC_CTX* hmac_ctx,
12325039b37SCy Schubert #endif
12425039b37SCy Schubert int enc);
12525039b37SCy Schubert #endif /* HAVE_SSL */
12625039b37SCy Schubert
127b7579f77SDag-Erling Smørgrav /* returns true is string addr is an ip6 specced address */
128b7579f77SDag-Erling Smørgrav int
str_is_ip6(const char * str)129b7579f77SDag-Erling Smørgrav str_is_ip6(const char* str)
130b7579f77SDag-Erling Smørgrav {
131b7579f77SDag-Erling Smørgrav if(strchr(str, ':'))
132b7579f77SDag-Erling Smørgrav return 1;
133b7579f77SDag-Erling Smørgrav else return 0;
134b7579f77SDag-Erling Smørgrav }
135b7579f77SDag-Erling Smørgrav
136b7579f77SDag-Erling Smørgrav int
fd_set_nonblock(int s)137b7579f77SDag-Erling Smørgrav fd_set_nonblock(int s)
138b7579f77SDag-Erling Smørgrav {
139b7579f77SDag-Erling Smørgrav #ifdef HAVE_FCNTL
140b7579f77SDag-Erling Smørgrav int flag;
141b7579f77SDag-Erling Smørgrav if((flag = fcntl(s, F_GETFL)) == -1) {
142b7579f77SDag-Erling Smørgrav log_err("can't fcntl F_GETFL: %s", strerror(errno));
143b7579f77SDag-Erling Smørgrav flag = 0;
144b7579f77SDag-Erling Smørgrav }
145b7579f77SDag-Erling Smørgrav flag |= O_NONBLOCK;
146b7579f77SDag-Erling Smørgrav if(fcntl(s, F_SETFL, flag) == -1) {
147b7579f77SDag-Erling Smørgrav log_err("can't fcntl F_SETFL: %s", strerror(errno));
148b7579f77SDag-Erling Smørgrav return 0;
149b7579f77SDag-Erling Smørgrav }
150b7579f77SDag-Erling Smørgrav #elif defined(HAVE_IOCTLSOCKET)
151b7579f77SDag-Erling Smørgrav unsigned long on = 1;
152b7579f77SDag-Erling Smørgrav if(ioctlsocket(s, FIONBIO, &on) != 0) {
153b7579f77SDag-Erling Smørgrav log_err("can't ioctlsocket FIONBIO on: %s",
154b7579f77SDag-Erling Smørgrav wsa_strerror(WSAGetLastError()));
155b7579f77SDag-Erling Smørgrav }
156b7579f77SDag-Erling Smørgrav #endif
157b7579f77SDag-Erling Smørgrav return 1;
158b7579f77SDag-Erling Smørgrav }
159b7579f77SDag-Erling Smørgrav
160b7579f77SDag-Erling Smørgrav int
fd_set_block(int s)161b7579f77SDag-Erling Smørgrav fd_set_block(int s)
162b7579f77SDag-Erling Smørgrav {
163b7579f77SDag-Erling Smørgrav #ifdef HAVE_FCNTL
164b7579f77SDag-Erling Smørgrav int flag;
165b7579f77SDag-Erling Smørgrav if((flag = fcntl(s, F_GETFL)) == -1) {
166b7579f77SDag-Erling Smørgrav log_err("cannot fcntl F_GETFL: %s", strerror(errno));
167b7579f77SDag-Erling Smørgrav flag = 0;
168b7579f77SDag-Erling Smørgrav }
169b7579f77SDag-Erling Smørgrav flag &= ~O_NONBLOCK;
170b7579f77SDag-Erling Smørgrav if(fcntl(s, F_SETFL, flag) == -1) {
171b7579f77SDag-Erling Smørgrav log_err("cannot fcntl F_SETFL: %s", strerror(errno));
172b7579f77SDag-Erling Smørgrav return 0;
173b7579f77SDag-Erling Smørgrav }
174b7579f77SDag-Erling Smørgrav #elif defined(HAVE_IOCTLSOCKET)
175b7579f77SDag-Erling Smørgrav unsigned long off = 0;
176b7579f77SDag-Erling Smørgrav if(ioctlsocket(s, FIONBIO, &off) != 0) {
177971980c3SDag-Erling Smørgrav if(WSAGetLastError() != WSAEINVAL || verbosity >= 4)
178b7579f77SDag-Erling Smørgrav log_err("can't ioctlsocket FIONBIO off: %s",
179b7579f77SDag-Erling Smørgrav wsa_strerror(WSAGetLastError()));
180b7579f77SDag-Erling Smørgrav }
181b7579f77SDag-Erling Smørgrav #endif
182b7579f77SDag-Erling Smørgrav return 1;
183b7579f77SDag-Erling Smørgrav }
184b7579f77SDag-Erling Smørgrav
185b7579f77SDag-Erling Smørgrav int
is_pow2(size_t num)186b7579f77SDag-Erling Smørgrav is_pow2(size_t num)
187b7579f77SDag-Erling Smørgrav {
188b7579f77SDag-Erling Smørgrav if(num == 0) return 1;
189b7579f77SDag-Erling Smørgrav return (num & (num-1)) == 0;
190b7579f77SDag-Erling Smørgrav }
191b7579f77SDag-Erling Smørgrav
192b7579f77SDag-Erling Smørgrav void*
memdup(void * data,size_t len)193b7579f77SDag-Erling Smørgrav memdup(void* data, size_t len)
194b7579f77SDag-Erling Smørgrav {
195b7579f77SDag-Erling Smørgrav void* d;
196b7579f77SDag-Erling Smørgrav if(!data) return NULL;
197b7579f77SDag-Erling Smørgrav if(len == 0) return NULL;
198b7579f77SDag-Erling Smørgrav d = malloc(len);
199b7579f77SDag-Erling Smørgrav if(!d) return NULL;
200b7579f77SDag-Erling Smørgrav memcpy(d, data, len);
201b7579f77SDag-Erling Smørgrav return d;
202b7579f77SDag-Erling Smørgrav }
203b7579f77SDag-Erling Smørgrav
204b7579f77SDag-Erling Smørgrav void
log_addr(enum verbosity_value v,const char * str,struct sockaddr_storage * addr,socklen_t addrlen)205b7579f77SDag-Erling Smørgrav log_addr(enum verbosity_value v, const char* str,
206b7579f77SDag-Erling Smørgrav struct sockaddr_storage* addr, socklen_t addrlen)
207b7579f77SDag-Erling Smørgrav {
208b7579f77SDag-Erling Smørgrav uint16_t port;
209b7579f77SDag-Erling Smørgrav const char* family = "unknown";
210b7579f77SDag-Erling Smørgrav char dest[100];
211b7579f77SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family;
212b7579f77SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
213b7579f77SDag-Erling Smørgrav if(verbosity < v)
214b7579f77SDag-Erling Smørgrav return;
215b7579f77SDag-Erling Smørgrav switch(af) {
216b7579f77SDag-Erling Smørgrav case AF_INET: family="ip4"; break;
217b7579f77SDag-Erling Smørgrav case AF_INET6: family="ip6";
218b7579f77SDag-Erling Smørgrav sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
219b7579f77SDag-Erling Smørgrav break;
2206480faa8SDag-Erling Smørgrav case AF_LOCAL:
2216480faa8SDag-Erling Smørgrav dest[0]=0;
2226480faa8SDag-Erling Smørgrav (void)inet_ntop(af, sinaddr, dest,
2236480faa8SDag-Erling Smørgrav (socklen_t)sizeof(dest));
2246480faa8SDag-Erling Smørgrav verbose(v, "%s local %s", str, dest);
2256480faa8SDag-Erling Smørgrav return; /* do not continue and try to get port */
226b7579f77SDag-Erling Smørgrav default: break;
227b7579f77SDag-Erling Smørgrav }
228b7579f77SDag-Erling Smørgrav if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
22917d15b25SDag-Erling Smørgrav (void)strlcpy(dest, "(inet_ntop error)", sizeof(dest));
230b7579f77SDag-Erling Smørgrav }
231b7579f77SDag-Erling Smørgrav dest[sizeof(dest)-1] = 0;
232b7579f77SDag-Erling Smørgrav port = ntohs(((struct sockaddr_in*)addr)->sin_port);
233b7579f77SDag-Erling Smørgrav if(verbosity >= 4)
234b7579f77SDag-Erling Smørgrav verbose(v, "%s %s %s port %d (len %d)", str, family, dest,
235b7579f77SDag-Erling Smørgrav (int)port, (int)addrlen);
236b7579f77SDag-Erling Smørgrav else verbose(v, "%s %s port %d", str, dest, (int)port);
237b7579f77SDag-Erling Smørgrav }
238b7579f77SDag-Erling Smørgrav
239b7579f77SDag-Erling Smørgrav int
extstrtoaddr(const char * str,struct sockaddr_storage * addr,socklen_t * addrlen,int port)240b7579f77SDag-Erling Smørgrav extstrtoaddr(const char* str, struct sockaddr_storage* addr,
241865f46b2SCy Schubert socklen_t* addrlen, int port)
242b7579f77SDag-Erling Smørgrav {
243b7579f77SDag-Erling Smørgrav char* s;
244b7579f77SDag-Erling Smørgrav if((s=strchr(str, '@'))) {
245b7579f77SDag-Erling Smørgrav char buf[MAX_ADDR_STRLEN];
246b7579f77SDag-Erling Smørgrav if(s-str >= MAX_ADDR_STRLEN) {
247b7579f77SDag-Erling Smørgrav return 0;
248b7579f77SDag-Erling Smørgrav }
24917d15b25SDag-Erling Smørgrav (void)strlcpy(buf, str, sizeof(buf));
250b7579f77SDag-Erling Smørgrav buf[s-str] = 0;
251b7579f77SDag-Erling Smørgrav port = atoi(s+1);
252b7579f77SDag-Erling Smørgrav if(port == 0 && strcmp(s+1,"0")!=0) {
253b7579f77SDag-Erling Smørgrav return 0;
254b7579f77SDag-Erling Smørgrav }
255b7579f77SDag-Erling Smørgrav return ipstrtoaddr(buf, port, addr, addrlen);
256b7579f77SDag-Erling Smørgrav }
257b7579f77SDag-Erling Smørgrav return ipstrtoaddr(str, port, addr, addrlen);
258b7579f77SDag-Erling Smørgrav }
259b7579f77SDag-Erling Smørgrav
260b7579f77SDag-Erling Smørgrav int
ipstrtoaddr(const char * ip,int port,struct sockaddr_storage * addr,socklen_t * addrlen)261b7579f77SDag-Erling Smørgrav ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr,
262b7579f77SDag-Erling Smørgrav socklen_t* addrlen)
263b7579f77SDag-Erling Smørgrav {
264b7579f77SDag-Erling Smørgrav uint16_t p;
265b7579f77SDag-Erling Smørgrav if(!ip) return 0;
266b7579f77SDag-Erling Smørgrav p = (uint16_t) port;
267b7579f77SDag-Erling Smørgrav if(str_is_ip6(ip)) {
268b7579f77SDag-Erling Smørgrav char buf[MAX_ADDR_STRLEN];
269b7579f77SDag-Erling Smørgrav char* s;
270b7579f77SDag-Erling Smørgrav struct sockaddr_in6* sa = (struct sockaddr_in6*)addr;
271b7579f77SDag-Erling Smørgrav *addrlen = (socklen_t)sizeof(struct sockaddr_in6);
272b7579f77SDag-Erling Smørgrav memset(sa, 0, *addrlen);
273b7579f77SDag-Erling Smørgrav sa->sin6_family = AF_INET6;
274b7579f77SDag-Erling Smørgrav sa->sin6_port = (in_port_t)htons(p);
275b7579f77SDag-Erling Smørgrav if((s=strchr(ip, '%'))) { /* ip6%interface, rfc 4007 */
276b7579f77SDag-Erling Smørgrav if(s-ip >= MAX_ADDR_STRLEN)
277b7579f77SDag-Erling Smørgrav return 0;
27817d15b25SDag-Erling Smørgrav (void)strlcpy(buf, ip, sizeof(buf));
279b7579f77SDag-Erling Smørgrav buf[s-ip]=0;
28024e36522SCy Schubert #ifdef HAVE_IF_NAMETOINDEX
28124e36522SCy Schubert if (!(sa->sin6_scope_id = if_nametoindex(s+1)))
28224e36522SCy Schubert #endif /* HAVE_IF_NAMETOINDEX */
283b7579f77SDag-Erling Smørgrav sa->sin6_scope_id = (uint32_t)atoi(s+1);
284b7579f77SDag-Erling Smørgrav ip = buf;
285b7579f77SDag-Erling Smørgrav }
286b7579f77SDag-Erling Smørgrav if(inet_pton((int)sa->sin6_family, ip, &sa->sin6_addr) <= 0) {
287b7579f77SDag-Erling Smørgrav return 0;
288b7579f77SDag-Erling Smørgrav }
289b7579f77SDag-Erling Smørgrav } else { /* ip4 */
290b7579f77SDag-Erling Smørgrav struct sockaddr_in* sa = (struct sockaddr_in*)addr;
291b7579f77SDag-Erling Smørgrav *addrlen = (socklen_t)sizeof(struct sockaddr_in);
292b7579f77SDag-Erling Smørgrav memset(sa, 0, *addrlen);
293b7579f77SDag-Erling Smørgrav sa->sin_family = AF_INET;
294b7579f77SDag-Erling Smørgrav sa->sin_port = (in_port_t)htons(p);
295b7579f77SDag-Erling Smørgrav if(inet_pton((int)sa->sin_family, ip, &sa->sin_addr) <= 0) {
296b7579f77SDag-Erling Smørgrav return 0;
297b7579f77SDag-Erling Smørgrav }
298b7579f77SDag-Erling Smørgrav }
299b7579f77SDag-Erling Smørgrav return 1;
300b7579f77SDag-Erling Smørgrav }
301b7579f77SDag-Erling Smørgrav
netblockstrtoaddr(const char * str,int port,struct sockaddr_storage * addr,socklen_t * addrlen,int * net)302b7579f77SDag-Erling Smørgrav int netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr,
303b7579f77SDag-Erling Smørgrav socklen_t* addrlen, int* net)
304b7579f77SDag-Erling Smørgrav {
3050fb34990SDag-Erling Smørgrav char buf[64];
3060fb34990SDag-Erling Smørgrav char* s;
307b7579f77SDag-Erling Smørgrav *net = (str_is_ip6(str)?128:32);
308b7579f77SDag-Erling Smørgrav if((s=strchr(str, '/'))) {
309b7579f77SDag-Erling Smørgrav if(atoi(s+1) > *net) {
310b7579f77SDag-Erling Smørgrav log_err("netblock too large: %s", str);
311b7579f77SDag-Erling Smørgrav return 0;
312b7579f77SDag-Erling Smørgrav }
313b7579f77SDag-Erling Smørgrav *net = atoi(s+1);
314b7579f77SDag-Erling Smørgrav if(*net == 0 && strcmp(s+1, "0") != 0) {
315b7579f77SDag-Erling Smørgrav log_err("cannot parse netblock: '%s'", str);
316b7579f77SDag-Erling Smørgrav return 0;
317b7579f77SDag-Erling Smørgrav }
3180fb34990SDag-Erling Smørgrav strlcpy(buf, str, sizeof(buf));
3190fb34990SDag-Erling Smørgrav s = strchr(buf, '/');
3200fb34990SDag-Erling Smørgrav if(s) *s = 0;
3210fb34990SDag-Erling Smørgrav s = buf;
322b7579f77SDag-Erling Smørgrav }
323b7579f77SDag-Erling Smørgrav if(!ipstrtoaddr(s?s:str, port, addr, addrlen)) {
324b7579f77SDag-Erling Smørgrav log_err("cannot parse ip address: '%s'", str);
325b7579f77SDag-Erling Smørgrav return 0;
326b7579f77SDag-Erling Smørgrav }
327b7579f77SDag-Erling Smørgrav if(s) {
328b7579f77SDag-Erling Smørgrav addr_mask(addr, *addrlen, *net);
329b7579f77SDag-Erling Smørgrav }
330b7579f77SDag-Erling Smørgrav return 1;
331b7579f77SDag-Erling Smørgrav }
332b7579f77SDag-Erling Smørgrav
333091e9e46SCy Schubert /* RPZ format address dname to network byte order address */
ipdnametoaddr(uint8_t * dname,size_t dnamelen,struct sockaddr_storage * addr,socklen_t * addrlen,int * af)334091e9e46SCy Schubert static int ipdnametoaddr(uint8_t* dname, size_t dnamelen,
335091e9e46SCy Schubert struct sockaddr_storage* addr, socklen_t* addrlen, int* af)
336091e9e46SCy Schubert {
337091e9e46SCy Schubert uint8_t* ia;
338f44e67d1SCy Schubert int dnamelabs = dname_count_labels(dname);
339091e9e46SCy Schubert uint8_t lablen;
340091e9e46SCy Schubert char* e = NULL;
341091e9e46SCy Schubert int z = 0;
342091e9e46SCy Schubert size_t len = 0;
343091e9e46SCy Schubert int i;
344091e9e46SCy Schubert *af = AF_INET;
345091e9e46SCy Schubert
346091e9e46SCy Schubert /* need 1 byte for label length */
347091e9e46SCy Schubert if(dnamelen < 1)
348091e9e46SCy Schubert return 0;
349091e9e46SCy Schubert
350091e9e46SCy Schubert if(dnamelabs > 6 ||
351091e9e46SCy Schubert dname_has_label(dname, dnamelen, (uint8_t*)"\002zz")) {
352091e9e46SCy Schubert *af = AF_INET6;
353091e9e46SCy Schubert }
354091e9e46SCy Schubert len = *dname;
355091e9e46SCy Schubert lablen = *dname++;
356091e9e46SCy Schubert i = (*af == AF_INET) ? 3 : 15;
357091e9e46SCy Schubert if(*af == AF_INET6) {
358091e9e46SCy Schubert struct sockaddr_in6* sa = (struct sockaddr_in6*)addr;
359091e9e46SCy Schubert *addrlen = (socklen_t)sizeof(struct sockaddr_in6);
360091e9e46SCy Schubert memset(sa, 0, *addrlen);
361091e9e46SCy Schubert sa->sin6_family = AF_INET6;
362091e9e46SCy Schubert ia = (uint8_t*)&sa->sin6_addr;
363091e9e46SCy Schubert } else { /* ip4 */
364091e9e46SCy Schubert struct sockaddr_in* sa = (struct sockaddr_in*)addr;
365091e9e46SCy Schubert *addrlen = (socklen_t)sizeof(struct sockaddr_in);
366091e9e46SCy Schubert memset(sa, 0, *addrlen);
367091e9e46SCy Schubert sa->sin_family = AF_INET;
368091e9e46SCy Schubert ia = (uint8_t*)&sa->sin_addr;
369091e9e46SCy Schubert }
370091e9e46SCy Schubert while(lablen && i >= 0 && len <= dnamelen) {
371091e9e46SCy Schubert char buff[LDNS_MAX_LABELLEN+1];
372091e9e46SCy Schubert uint16_t chunk; /* big enough to not overflow on IPv6 hextet */
373091e9e46SCy Schubert if((*af == AF_INET && (lablen > 3 || dnamelabs > 6)) ||
374091e9e46SCy Schubert (*af == AF_INET6 && (lablen > 4 || dnamelabs > 10))) {
375091e9e46SCy Schubert return 0;
376091e9e46SCy Schubert }
377091e9e46SCy Schubert if(memcmp(dname, "zz", 2) == 0 && *af == AF_INET6) {
378091e9e46SCy Schubert /* Add one or more 0 labels. Address is initialised at
379091e9e46SCy Schubert * 0, so just skip the zero part. */
380091e9e46SCy Schubert int zl = 11 - dnamelabs;
381091e9e46SCy Schubert if(z || zl < 0)
382091e9e46SCy Schubert return 0;
383091e9e46SCy Schubert z = 1;
384091e9e46SCy Schubert i -= (zl*2);
385091e9e46SCy Schubert } else {
386091e9e46SCy Schubert memcpy(buff, dname, lablen);
387091e9e46SCy Schubert buff[lablen] = '\0';
388091e9e46SCy Schubert chunk = strtol(buff, &e, (*af == AF_INET) ? 10 : 16);
389091e9e46SCy Schubert if(!e || *e != '\0' || (*af == AF_INET && chunk > 255))
390091e9e46SCy Schubert return 0;
391091e9e46SCy Schubert if(*af == AF_INET) {
392091e9e46SCy Schubert log_assert(i < 4 && i >= 0);
393091e9e46SCy Schubert ia[i] = (uint8_t)chunk;
394091e9e46SCy Schubert i--;
395091e9e46SCy Schubert } else {
396091e9e46SCy Schubert log_assert(i < 16 && i >= 1);
397091e9e46SCy Schubert /* ia in network byte order */
398091e9e46SCy Schubert ia[i-1] = (uint8_t)(chunk >> 8);
399091e9e46SCy Schubert ia[i] = (uint8_t)(chunk & 0x00FF);
400091e9e46SCy Schubert i -= 2;
401091e9e46SCy Schubert }
402091e9e46SCy Schubert }
403091e9e46SCy Schubert dname += lablen;
404091e9e46SCy Schubert lablen = *dname++;
405091e9e46SCy Schubert len += lablen;
406091e9e46SCy Schubert }
407091e9e46SCy Schubert if(i != -1)
408091e9e46SCy Schubert /* input too short */
409091e9e46SCy Schubert return 0;
410091e9e46SCy Schubert return 1;
411091e9e46SCy Schubert }
412091e9e46SCy Schubert
netblockdnametoaddr(uint8_t * dname,size_t dnamelen,struct sockaddr_storage * addr,socklen_t * addrlen,int * net,int * af)413091e9e46SCy Schubert int netblockdnametoaddr(uint8_t* dname, size_t dnamelen,
414091e9e46SCy Schubert struct sockaddr_storage* addr, socklen_t* addrlen, int* net, int* af)
415091e9e46SCy Schubert {
416091e9e46SCy Schubert char buff[3 /* 3 digit netblock */ + 1];
417091e9e46SCy Schubert size_t nlablen;
418091e9e46SCy Schubert if(dnamelen < 1 || *dname > 3)
419091e9e46SCy Schubert /* netblock invalid */
420091e9e46SCy Schubert return 0;
421091e9e46SCy Schubert nlablen = *dname;
422091e9e46SCy Schubert
423091e9e46SCy Schubert if(dnamelen < 1 + nlablen)
424091e9e46SCy Schubert return 0;
425091e9e46SCy Schubert
426091e9e46SCy Schubert memcpy(buff, dname+1, nlablen);
427091e9e46SCy Schubert buff[nlablen] = '\0';
428091e9e46SCy Schubert *net = atoi(buff);
429091e9e46SCy Schubert if(*net == 0 && strcmp(buff, "0") != 0)
430091e9e46SCy Schubert return 0;
431091e9e46SCy Schubert dname += nlablen;
432091e9e46SCy Schubert dname++;
433091e9e46SCy Schubert if(!ipdnametoaddr(dname, dnamelen-1-nlablen, addr, addrlen, af))
434091e9e46SCy Schubert return 0;
435091e9e46SCy Schubert if((*af == AF_INET6 && *net > 128) || (*af == AF_INET && *net > 32))
436091e9e46SCy Schubert return 0;
437091e9e46SCy Schubert return 1;
438091e9e46SCy Schubert }
439091e9e46SCy Schubert
authextstrtoaddr(char * str,struct sockaddr_storage * addr,socklen_t * addrlen,char ** auth_name)4400fb34990SDag-Erling Smørgrav int authextstrtoaddr(char* str, struct sockaddr_storage* addr,
4410fb34990SDag-Erling Smørgrav socklen_t* addrlen, char** auth_name)
4420fb34990SDag-Erling Smørgrav {
4430fb34990SDag-Erling Smørgrav char* s;
4440fb34990SDag-Erling Smørgrav int port = UNBOUND_DNS_PORT;
4450fb34990SDag-Erling Smørgrav if((s=strchr(str, '@'))) {
4460fb34990SDag-Erling Smørgrav char buf[MAX_ADDR_STRLEN];
4470fb34990SDag-Erling Smørgrav size_t len = (size_t)(s-str);
4480fb34990SDag-Erling Smørgrav char* hash = strchr(s+1, '#');
4490fb34990SDag-Erling Smørgrav if(hash) {
4500fb34990SDag-Erling Smørgrav *auth_name = hash+1;
4510fb34990SDag-Erling Smørgrav } else {
4520fb34990SDag-Erling Smørgrav *auth_name = NULL;
4530fb34990SDag-Erling Smørgrav }
4540fb34990SDag-Erling Smørgrav if(len >= MAX_ADDR_STRLEN) {
4550fb34990SDag-Erling Smørgrav return 0;
4560fb34990SDag-Erling Smørgrav }
4570fb34990SDag-Erling Smørgrav (void)strlcpy(buf, str, sizeof(buf));
4580fb34990SDag-Erling Smørgrav buf[len] = 0;
4590fb34990SDag-Erling Smørgrav port = atoi(s+1);
4600fb34990SDag-Erling Smørgrav if(port == 0) {
4610fb34990SDag-Erling Smørgrav if(!hash && strcmp(s+1,"0")!=0)
4620fb34990SDag-Erling Smørgrav return 0;
4630fb34990SDag-Erling Smørgrav if(hash && strncmp(s+1,"0#",2)!=0)
4640fb34990SDag-Erling Smørgrav return 0;
4650fb34990SDag-Erling Smørgrav }
4660fb34990SDag-Erling Smørgrav return ipstrtoaddr(buf, port, addr, addrlen);
4670fb34990SDag-Erling Smørgrav }
4680fb34990SDag-Erling Smørgrav if((s=strchr(str, '#'))) {
4690fb34990SDag-Erling Smørgrav char buf[MAX_ADDR_STRLEN];
4700fb34990SDag-Erling Smørgrav size_t len = (size_t)(s-str);
4710fb34990SDag-Erling Smørgrav if(len >= MAX_ADDR_STRLEN) {
4720fb34990SDag-Erling Smørgrav return 0;
4730fb34990SDag-Erling Smørgrav }
4740fb34990SDag-Erling Smørgrav (void)strlcpy(buf, str, sizeof(buf));
4750fb34990SDag-Erling Smørgrav buf[len] = 0;
4760fb34990SDag-Erling Smørgrav port = UNBOUND_DNS_OVER_TLS_PORT;
4770fb34990SDag-Erling Smørgrav *auth_name = s+1;
4780fb34990SDag-Erling Smørgrav return ipstrtoaddr(buf, port, addr, addrlen);
4790fb34990SDag-Erling Smørgrav }
4800fb34990SDag-Erling Smørgrav *auth_name = NULL;
4810fb34990SDag-Erling Smørgrav return ipstrtoaddr(str, port, addr, addrlen);
4820fb34990SDag-Erling Smørgrav }
4830fb34990SDag-Erling Smørgrav
authextstrtodname(char * str,int * port,char ** auth_name)4849cf5bc93SCy Schubert uint8_t* authextstrtodname(char* str, int* port, char** auth_name)
4859cf5bc93SCy Schubert {
4869cf5bc93SCy Schubert char* s;
4879cf5bc93SCy Schubert uint8_t* dname;
4889cf5bc93SCy Schubert size_t dname_len;
4899cf5bc93SCy Schubert *port = UNBOUND_DNS_PORT;
4909cf5bc93SCy Schubert *auth_name = NULL;
4919cf5bc93SCy Schubert if((s=strchr(str, '@'))) {
492335c7cdaSCy Schubert char buf[MAX_HOST_STRLEN];
493335c7cdaSCy Schubert size_t len = (size_t)(s-str);
4949cf5bc93SCy Schubert char* hash = strchr(s+1, '#');
4959cf5bc93SCy Schubert if(hash) {
4969cf5bc93SCy Schubert *auth_name = hash+1;
4979cf5bc93SCy Schubert } else {
4989cf5bc93SCy Schubert *auth_name = NULL;
4999cf5bc93SCy Schubert }
500335c7cdaSCy Schubert if(len >= MAX_HOST_STRLEN) {
501335c7cdaSCy Schubert return NULL;
502335c7cdaSCy Schubert }
503335c7cdaSCy Schubert (void)strlcpy(buf, str, sizeof(buf));
504335c7cdaSCy Schubert buf[len] = 0;
5059cf5bc93SCy Schubert *port = atoi(s+1);
5069cf5bc93SCy Schubert if(*port == 0) {
5079cf5bc93SCy Schubert if(!hash && strcmp(s+1,"0")!=0)
508335c7cdaSCy Schubert return NULL;
5099cf5bc93SCy Schubert if(hash && strncmp(s+1,"0#",2)!=0)
510335c7cdaSCy Schubert return NULL;
5119cf5bc93SCy Schubert }
512335c7cdaSCy Schubert dname = sldns_str2wire_dname(buf, &dname_len);
5139cf5bc93SCy Schubert } else if((s=strchr(str, '#'))) {
514335c7cdaSCy Schubert char buf[MAX_HOST_STRLEN];
515335c7cdaSCy Schubert size_t len = (size_t)(s-str);
516335c7cdaSCy Schubert if(len >= MAX_HOST_STRLEN) {
517335c7cdaSCy Schubert return NULL;
518335c7cdaSCy Schubert }
519335c7cdaSCy Schubert (void)strlcpy(buf, str, sizeof(buf));
520335c7cdaSCy Schubert buf[len] = 0;
5219cf5bc93SCy Schubert *port = UNBOUND_DNS_OVER_TLS_PORT;
5229cf5bc93SCy Schubert *auth_name = s+1;
523335c7cdaSCy Schubert dname = sldns_str2wire_dname(buf, &dname_len);
5249cf5bc93SCy Schubert } else {
5259cf5bc93SCy Schubert dname = sldns_str2wire_dname(str, &dname_len);
5269cf5bc93SCy Schubert }
5279cf5bc93SCy Schubert return dname;
5289cf5bc93SCy Schubert }
5299cf5bc93SCy Schubert
53057bddd21SDag-Erling Smørgrav /** store port number into sockaddr structure */
53157bddd21SDag-Erling Smørgrav void
sockaddr_store_port(struct sockaddr_storage * addr,socklen_t addrlen,int port)53257bddd21SDag-Erling Smørgrav sockaddr_store_port(struct sockaddr_storage* addr, socklen_t addrlen, int port)
53357bddd21SDag-Erling Smørgrav {
53457bddd21SDag-Erling Smørgrav if(addr_is_ip6(addr, addrlen)) {
53557bddd21SDag-Erling Smørgrav struct sockaddr_in6* sa = (struct sockaddr_in6*)addr;
53657bddd21SDag-Erling Smørgrav sa->sin6_port = (in_port_t)htons((uint16_t)port);
53757bddd21SDag-Erling Smørgrav } else {
53857bddd21SDag-Erling Smørgrav struct sockaddr_in* sa = (struct sockaddr_in*)addr;
53957bddd21SDag-Erling Smørgrav sa->sin_port = (in_port_t)htons((uint16_t)port);
54057bddd21SDag-Erling Smørgrav }
54157bddd21SDag-Erling Smørgrav }
54257bddd21SDag-Erling Smørgrav
543b7579f77SDag-Erling Smørgrav void
log_nametypeclass(enum verbosity_value v,const char * str,uint8_t * name,uint16_t type,uint16_t dclass)544b7579f77SDag-Erling Smørgrav log_nametypeclass(enum verbosity_value v, const char* str, uint8_t* name,
545b7579f77SDag-Erling Smørgrav uint16_t type, uint16_t dclass)
546b7579f77SDag-Erling Smørgrav {
547b7579f77SDag-Erling Smørgrav char buf[LDNS_MAX_DOMAINLEN+1];
548b7579f77SDag-Erling Smørgrav char t[12], c[12];
549b7579f77SDag-Erling Smørgrav const char *ts, *cs;
550b7579f77SDag-Erling Smørgrav if(verbosity < v)
551b7579f77SDag-Erling Smørgrav return;
552b7579f77SDag-Erling Smørgrav dname_str(name, buf);
553b7579f77SDag-Erling Smørgrav if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG";
554b7579f77SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR";
555b7579f77SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR";
556b7579f77SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB";
557b7579f77SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA";
558b7579f77SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_ANY) ts = "ANY";
55917d15b25SDag-Erling Smørgrav else if(sldns_rr_descript(type) && sldns_rr_descript(type)->_name)
56017d15b25SDag-Erling Smørgrav ts = sldns_rr_descript(type)->_name;
561b7579f77SDag-Erling Smørgrav else {
562b7579f77SDag-Erling Smørgrav snprintf(t, sizeof(t), "TYPE%d", (int)type);
563b7579f77SDag-Erling Smørgrav ts = t;
564b7579f77SDag-Erling Smørgrav }
56517d15b25SDag-Erling Smørgrav if(sldns_lookup_by_id(sldns_rr_classes, (int)dclass) &&
56617d15b25SDag-Erling Smørgrav sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name)
56717d15b25SDag-Erling Smørgrav cs = sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name;
568b7579f77SDag-Erling Smørgrav else {
569b7579f77SDag-Erling Smørgrav snprintf(c, sizeof(c), "CLASS%d", (int)dclass);
570b7579f77SDag-Erling Smørgrav cs = c;
571b7579f77SDag-Erling Smørgrav }
572b7579f77SDag-Erling Smørgrav log_info("%s %s %s %s", str, buf, ts, cs);
573b7579f77SDag-Erling Smørgrav }
574b7579f77SDag-Erling Smørgrav
575e86b9096SDag-Erling Smørgrav void
log_query_in(const char * str,uint8_t * name,uint16_t type,uint16_t dclass)576e86b9096SDag-Erling Smørgrav log_query_in(const char* str, uint8_t* name, uint16_t type, uint16_t dclass)
577e86b9096SDag-Erling Smørgrav {
578e86b9096SDag-Erling Smørgrav char buf[LDNS_MAX_DOMAINLEN+1];
579e86b9096SDag-Erling Smørgrav char t[12], c[12];
580e86b9096SDag-Erling Smørgrav const char *ts, *cs;
581e86b9096SDag-Erling Smørgrav dname_str(name, buf);
582e86b9096SDag-Erling Smørgrav if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG";
583e86b9096SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR";
584e86b9096SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR";
585e86b9096SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB";
586e86b9096SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA";
587e86b9096SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_ANY) ts = "ANY";
588e86b9096SDag-Erling Smørgrav else if(sldns_rr_descript(type) && sldns_rr_descript(type)->_name)
589e86b9096SDag-Erling Smørgrav ts = sldns_rr_descript(type)->_name;
590e86b9096SDag-Erling Smørgrav else {
591e86b9096SDag-Erling Smørgrav snprintf(t, sizeof(t), "TYPE%d", (int)type);
592e86b9096SDag-Erling Smørgrav ts = t;
593e86b9096SDag-Erling Smørgrav }
594e86b9096SDag-Erling Smørgrav if(sldns_lookup_by_id(sldns_rr_classes, (int)dclass) &&
595e86b9096SDag-Erling Smørgrav sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name)
596e86b9096SDag-Erling Smørgrav cs = sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name;
597e86b9096SDag-Erling Smørgrav else {
598e86b9096SDag-Erling Smørgrav snprintf(c, sizeof(c), "CLASS%d", (int)dclass);
599e86b9096SDag-Erling Smørgrav cs = c;
600e86b9096SDag-Erling Smørgrav }
601e86b9096SDag-Erling Smørgrav if(LOG_TAG_QUERYREPLY)
602e86b9096SDag-Erling Smørgrav log_query("%s %s %s %s", str, buf, ts, cs);
603e86b9096SDag-Erling Smørgrav else log_info("%s %s %s %s", str, buf, ts, cs);
604e86b9096SDag-Erling Smørgrav }
605e86b9096SDag-Erling Smørgrav
log_name_addr(enum verbosity_value v,const char * str,uint8_t * zone,struct sockaddr_storage * addr,socklen_t addrlen)606b7579f77SDag-Erling Smørgrav void log_name_addr(enum verbosity_value v, const char* str, uint8_t* zone,
607b7579f77SDag-Erling Smørgrav struct sockaddr_storage* addr, socklen_t addrlen)
608b7579f77SDag-Erling Smørgrav {
609b7579f77SDag-Erling Smørgrav uint16_t port;
610b7579f77SDag-Erling Smørgrav const char* family = "unknown_family ";
611b7579f77SDag-Erling Smørgrav char namebuf[LDNS_MAX_DOMAINLEN+1];
612b7579f77SDag-Erling Smørgrav char dest[100];
613b7579f77SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family;
614b7579f77SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
615b7579f77SDag-Erling Smørgrav if(verbosity < v)
616b7579f77SDag-Erling Smørgrav return;
617b7579f77SDag-Erling Smørgrav switch(af) {
618b7579f77SDag-Erling Smørgrav case AF_INET: family=""; break;
619b7579f77SDag-Erling Smørgrav case AF_INET6: family="";
620b7579f77SDag-Erling Smørgrav sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
621b7579f77SDag-Erling Smørgrav break;
62231099b50SDag-Erling Smørgrav case AF_LOCAL: family="local "; break;
623b7579f77SDag-Erling Smørgrav default: break;
624b7579f77SDag-Erling Smørgrav }
625b7579f77SDag-Erling Smørgrav if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
62617d15b25SDag-Erling Smørgrav (void)strlcpy(dest, "(inet_ntop error)", sizeof(dest));
627b7579f77SDag-Erling Smørgrav }
628b7579f77SDag-Erling Smørgrav dest[sizeof(dest)-1] = 0;
629b7579f77SDag-Erling Smørgrav port = ntohs(((struct sockaddr_in*)addr)->sin_port);
630b7579f77SDag-Erling Smørgrav dname_str(zone, namebuf);
631b7579f77SDag-Erling Smørgrav if(af != AF_INET && af != AF_INET6)
632b7579f77SDag-Erling Smørgrav verbose(v, "%s <%s> %s%s#%d (addrlen %d)",
633b7579f77SDag-Erling Smørgrav str, namebuf, family, dest, (int)port, (int)addrlen);
634b7579f77SDag-Erling Smørgrav else verbose(v, "%s <%s> %s%s#%d",
635b7579f77SDag-Erling Smørgrav str, namebuf, family, dest, (int)port);
636b7579f77SDag-Erling Smørgrav }
637b7579f77SDag-Erling Smørgrav
log_err_addr(const char * str,const char * err,struct sockaddr_storage * addr,socklen_t addrlen)638ff825849SDag-Erling Smørgrav void log_err_addr(const char* str, const char* err,
639ff825849SDag-Erling Smørgrav struct sockaddr_storage* addr, socklen_t addrlen)
640ff825849SDag-Erling Smørgrav {
641ff825849SDag-Erling Smørgrav uint16_t port;
642ff825849SDag-Erling Smørgrav char dest[100];
643ff825849SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family;
644ff825849SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
645ff825849SDag-Erling Smørgrav if(af == AF_INET6)
646ff825849SDag-Erling Smørgrav sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
647ff825849SDag-Erling Smørgrav if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
648ff825849SDag-Erling Smørgrav (void)strlcpy(dest, "(inet_ntop error)", sizeof(dest));
649ff825849SDag-Erling Smørgrav }
650ff825849SDag-Erling Smørgrav dest[sizeof(dest)-1] = 0;
651ff825849SDag-Erling Smørgrav port = ntohs(((struct sockaddr_in*)addr)->sin_port);
652ff825849SDag-Erling Smørgrav if(verbosity >= 4)
653ff825849SDag-Erling Smørgrav log_err("%s: %s for %s port %d (len %d)", str, err, dest,
654ff825849SDag-Erling Smørgrav (int)port, (int)addrlen);
6554c75e3aaSDag-Erling Smørgrav else log_err("%s: %s for %s port %d", str, err, dest, (int)port);
656ff825849SDag-Erling Smørgrav }
657ff825849SDag-Erling Smørgrav
658b7579f77SDag-Erling Smørgrav int
sockaddr_cmp(struct sockaddr_storage * addr1,socklen_t len1,struct sockaddr_storage * addr2,socklen_t len2)659b7579f77SDag-Erling Smørgrav sockaddr_cmp(struct sockaddr_storage* addr1, socklen_t len1,
660b7579f77SDag-Erling Smørgrav struct sockaddr_storage* addr2, socklen_t len2)
661b7579f77SDag-Erling Smørgrav {
662b7579f77SDag-Erling Smørgrav struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1;
663b7579f77SDag-Erling Smørgrav struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2;
664b7579f77SDag-Erling Smørgrav struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1;
665b7579f77SDag-Erling Smørgrav struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2;
666b7579f77SDag-Erling Smørgrav if(len1 < len2)
667b7579f77SDag-Erling Smørgrav return -1;
668b7579f77SDag-Erling Smørgrav if(len1 > len2)
669b7579f77SDag-Erling Smørgrav return 1;
670b7579f77SDag-Erling Smørgrav log_assert(len1 == len2);
671b7579f77SDag-Erling Smørgrav if( p1_in->sin_family < p2_in->sin_family)
672b7579f77SDag-Erling Smørgrav return -1;
673b7579f77SDag-Erling Smørgrav if( p1_in->sin_family > p2_in->sin_family)
674b7579f77SDag-Erling Smørgrav return 1;
675b7579f77SDag-Erling Smørgrav log_assert( p1_in->sin_family == p2_in->sin_family );
676b7579f77SDag-Erling Smørgrav /* compare ip4 */
677b7579f77SDag-Erling Smørgrav if( p1_in->sin_family == AF_INET ) {
678b7579f77SDag-Erling Smørgrav /* just order it, ntohs not required */
679b7579f77SDag-Erling Smørgrav if(p1_in->sin_port < p2_in->sin_port)
680b7579f77SDag-Erling Smørgrav return -1;
681b7579f77SDag-Erling Smørgrav if(p1_in->sin_port > p2_in->sin_port)
682b7579f77SDag-Erling Smørgrav return 1;
683b7579f77SDag-Erling Smørgrav log_assert(p1_in->sin_port == p2_in->sin_port);
684b7579f77SDag-Erling Smørgrav return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE);
685b7579f77SDag-Erling Smørgrav } else if (p1_in6->sin6_family == AF_INET6) {
686b7579f77SDag-Erling Smørgrav /* just order it, ntohs not required */
687b7579f77SDag-Erling Smørgrav if(p1_in6->sin6_port < p2_in6->sin6_port)
688b7579f77SDag-Erling Smørgrav return -1;
689b7579f77SDag-Erling Smørgrav if(p1_in6->sin6_port > p2_in6->sin6_port)
690b7579f77SDag-Erling Smørgrav return 1;
691b7579f77SDag-Erling Smørgrav log_assert(p1_in6->sin6_port == p2_in6->sin6_port);
692b7579f77SDag-Erling Smørgrav return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr,
693b7579f77SDag-Erling Smørgrav INET6_SIZE);
694b7579f77SDag-Erling Smørgrav } else {
695b7579f77SDag-Erling Smørgrav /* eek unknown type, perform this comparison for sanity. */
696b7579f77SDag-Erling Smørgrav return memcmp(addr1, addr2, len1);
697b7579f77SDag-Erling Smørgrav }
698b7579f77SDag-Erling Smørgrav }
699b7579f77SDag-Erling Smørgrav
700b7579f77SDag-Erling Smørgrav int
sockaddr_cmp_addr(struct sockaddr_storage * addr1,socklen_t len1,struct sockaddr_storage * addr2,socklen_t len2)701b7579f77SDag-Erling Smørgrav sockaddr_cmp_addr(struct sockaddr_storage* addr1, socklen_t len1,
702b7579f77SDag-Erling Smørgrav struct sockaddr_storage* addr2, socklen_t len2)
703b7579f77SDag-Erling Smørgrav {
704b7579f77SDag-Erling Smørgrav struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1;
705b7579f77SDag-Erling Smørgrav struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2;
706b7579f77SDag-Erling Smørgrav struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1;
707b7579f77SDag-Erling Smørgrav struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2;
708b7579f77SDag-Erling Smørgrav if(len1 < len2)
709b7579f77SDag-Erling Smørgrav return -1;
710b7579f77SDag-Erling Smørgrav if(len1 > len2)
711b7579f77SDag-Erling Smørgrav return 1;
712b7579f77SDag-Erling Smørgrav log_assert(len1 == len2);
713b7579f77SDag-Erling Smørgrav if( p1_in->sin_family < p2_in->sin_family)
714b7579f77SDag-Erling Smørgrav return -1;
715b7579f77SDag-Erling Smørgrav if( p1_in->sin_family > p2_in->sin_family)
716b7579f77SDag-Erling Smørgrav return 1;
717b7579f77SDag-Erling Smørgrav log_assert( p1_in->sin_family == p2_in->sin_family );
718b7579f77SDag-Erling Smørgrav /* compare ip4 */
719b7579f77SDag-Erling Smørgrav if( p1_in->sin_family == AF_INET ) {
720b7579f77SDag-Erling Smørgrav return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE);
721b7579f77SDag-Erling Smørgrav } else if (p1_in6->sin6_family == AF_INET6) {
722b7579f77SDag-Erling Smørgrav return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr,
723b7579f77SDag-Erling Smørgrav INET6_SIZE);
724b7579f77SDag-Erling Smørgrav } else {
725b7579f77SDag-Erling Smørgrav /* eek unknown type, perform this comparison for sanity. */
726b7579f77SDag-Erling Smørgrav return memcmp(addr1, addr2, len1);
727b7579f77SDag-Erling Smørgrav }
728b7579f77SDag-Erling Smørgrav }
729b7579f77SDag-Erling Smørgrav
730b7579f77SDag-Erling Smørgrav int
addr_is_ip6(struct sockaddr_storage * addr,socklen_t len)731b7579f77SDag-Erling Smørgrav addr_is_ip6(struct sockaddr_storage* addr, socklen_t len)
732b7579f77SDag-Erling Smørgrav {
733b7579f77SDag-Erling Smørgrav if(len == (socklen_t)sizeof(struct sockaddr_in6) &&
734b7579f77SDag-Erling Smørgrav ((struct sockaddr_in6*)addr)->sin6_family == AF_INET6)
735b7579f77SDag-Erling Smørgrav return 1;
736b7579f77SDag-Erling Smørgrav else return 0;
737b7579f77SDag-Erling Smørgrav }
738b7579f77SDag-Erling Smørgrav
739b7579f77SDag-Erling Smørgrav void
addr_mask(struct sockaddr_storage * addr,socklen_t len,int net)740b7579f77SDag-Erling Smørgrav addr_mask(struct sockaddr_storage* addr, socklen_t len, int net)
741b7579f77SDag-Erling Smørgrav {
742b7579f77SDag-Erling Smørgrav uint8_t mask[8] = {0x0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe};
743b7579f77SDag-Erling Smørgrav int i, max;
744b7579f77SDag-Erling Smørgrav uint8_t* s;
745b7579f77SDag-Erling Smørgrav if(addr_is_ip6(addr, len)) {
746b7579f77SDag-Erling Smørgrav s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr;
747b7579f77SDag-Erling Smørgrav max = 128;
748b7579f77SDag-Erling Smørgrav } else {
749b7579f77SDag-Erling Smørgrav s = (uint8_t*)&((struct sockaddr_in*)addr)->sin_addr;
750b7579f77SDag-Erling Smørgrav max = 32;
751b7579f77SDag-Erling Smørgrav }
752b7579f77SDag-Erling Smørgrav if(net >= max)
753b7579f77SDag-Erling Smørgrav return;
754b7579f77SDag-Erling Smørgrav for(i=net/8+1; i<max/8; i++) {
755b7579f77SDag-Erling Smørgrav s[i] = 0;
756b7579f77SDag-Erling Smørgrav }
757b7579f77SDag-Erling Smørgrav s[net/8] &= mask[net&0x7];
758b7579f77SDag-Erling Smørgrav }
759b7579f77SDag-Erling Smørgrav
760b7579f77SDag-Erling Smørgrav int
addr_in_common(struct sockaddr_storage * addr1,int net1,struct sockaddr_storage * addr2,int net2,socklen_t addrlen)761b7579f77SDag-Erling Smørgrav addr_in_common(struct sockaddr_storage* addr1, int net1,
762b7579f77SDag-Erling Smørgrav struct sockaddr_storage* addr2, int net2, socklen_t addrlen)
763b7579f77SDag-Erling Smørgrav {
764b7579f77SDag-Erling Smørgrav int min = (net1<net2)?net1:net2;
765b7579f77SDag-Erling Smørgrav int i, to;
766b7579f77SDag-Erling Smørgrav int match = 0;
767b7579f77SDag-Erling Smørgrav uint8_t* s1, *s2;
768b7579f77SDag-Erling Smørgrav if(addr_is_ip6(addr1, addrlen)) {
769b7579f77SDag-Erling Smørgrav s1 = (uint8_t*)&((struct sockaddr_in6*)addr1)->sin6_addr;
770b7579f77SDag-Erling Smørgrav s2 = (uint8_t*)&((struct sockaddr_in6*)addr2)->sin6_addr;
771b7579f77SDag-Erling Smørgrav to = 16;
772b7579f77SDag-Erling Smørgrav } else {
773b7579f77SDag-Erling Smørgrav s1 = (uint8_t*)&((struct sockaddr_in*)addr1)->sin_addr;
774b7579f77SDag-Erling Smørgrav s2 = (uint8_t*)&((struct sockaddr_in*)addr2)->sin_addr;
775b7579f77SDag-Erling Smørgrav to = 4;
776b7579f77SDag-Erling Smørgrav }
777b7579f77SDag-Erling Smørgrav /* match = bits_in_common(s1, s2, to); */
778b7579f77SDag-Erling Smørgrav for(i=0; i<to; i++) {
779b7579f77SDag-Erling Smørgrav if(s1[i] == s2[i]) {
780b7579f77SDag-Erling Smørgrav match += 8;
781b7579f77SDag-Erling Smørgrav } else {
782b7579f77SDag-Erling Smørgrav uint8_t z = s1[i]^s2[i];
783b7579f77SDag-Erling Smørgrav log_assert(z);
784b7579f77SDag-Erling Smørgrav while(!(z&0x80)) {
785b7579f77SDag-Erling Smørgrav match++;
786b7579f77SDag-Erling Smørgrav z<<=1;
787b7579f77SDag-Erling Smørgrav }
788b7579f77SDag-Erling Smørgrav break;
789b7579f77SDag-Erling Smørgrav }
790b7579f77SDag-Erling Smørgrav }
791b7579f77SDag-Erling Smørgrav if(match > min) match = min;
792b7579f77SDag-Erling Smørgrav return match;
793b7579f77SDag-Erling Smørgrav }
794b7579f77SDag-Erling Smørgrav
795b7579f77SDag-Erling Smørgrav void
addr_to_str(struct sockaddr_storage * addr,socklen_t addrlen,char * buf,size_t len)796b7579f77SDag-Erling Smørgrav addr_to_str(struct sockaddr_storage* addr, socklen_t addrlen,
797b7579f77SDag-Erling Smørgrav char* buf, size_t len)
798b7579f77SDag-Erling Smørgrav {
799b7579f77SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family;
800b7579f77SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
801b7579f77SDag-Erling Smørgrav if(addr_is_ip6(addr, addrlen))
802b7579f77SDag-Erling Smørgrav sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
803b7579f77SDag-Erling Smørgrav if(inet_ntop(af, sinaddr, buf, (socklen_t)len) == 0) {
804b7579f77SDag-Erling Smørgrav snprintf(buf, len, "(inet_ntop_error)");
805b7579f77SDag-Erling Smørgrav }
806b7579f77SDag-Erling Smørgrav }
807b7579f77SDag-Erling Smørgrav
808b7579f77SDag-Erling Smørgrav int
prefixnet_is_nat64(int prefixnet)8098f76bb7dSCy Schubert prefixnet_is_nat64(int prefixnet)
8108f76bb7dSCy Schubert {
8118f76bb7dSCy Schubert return (prefixnet == 32 || prefixnet == 40 ||
8128f76bb7dSCy Schubert prefixnet == 48 || prefixnet == 56 ||
8138f76bb7dSCy Schubert prefixnet == 64 || prefixnet == 96);
8148f76bb7dSCy Schubert }
8158f76bb7dSCy Schubert
8168f76bb7dSCy Schubert void
addr_to_nat64(const struct sockaddr_storage * addr,const struct sockaddr_storage * nat64_prefix,socklen_t nat64_prefixlen,int nat64_prefixnet,struct sockaddr_storage * nat64_addr,socklen_t * nat64_addrlen)8178f76bb7dSCy Schubert addr_to_nat64(const struct sockaddr_storage* addr,
8188f76bb7dSCy Schubert const struct sockaddr_storage* nat64_prefix,
8198f76bb7dSCy Schubert socklen_t nat64_prefixlen, int nat64_prefixnet,
8208f76bb7dSCy Schubert struct sockaddr_storage* nat64_addr, socklen_t* nat64_addrlen)
8218f76bb7dSCy Schubert {
8228f76bb7dSCy Schubert struct sockaddr_in *sin = (struct sockaddr_in *)addr;
8238f76bb7dSCy Schubert struct sockaddr_in6 *sin6;
8248f76bb7dSCy Schubert uint8_t *v4_byte;
825103ba509SCy Schubert int i;
8268f76bb7dSCy Schubert
8278f76bb7dSCy Schubert /* This needs to be checked by the caller */
8288f76bb7dSCy Schubert log_assert(addr->ss_family == AF_INET);
8298f76bb7dSCy Schubert /* Current usage is only from config values; prefix lengths enforced
8308f76bb7dSCy Schubert * during config validation */
8318f76bb7dSCy Schubert log_assert(prefixnet_is_nat64(nat64_prefixnet));
8328f76bb7dSCy Schubert
8338f76bb7dSCy Schubert *nat64_addr = *nat64_prefix;
8348f76bb7dSCy Schubert *nat64_addrlen = nat64_prefixlen;
8358f76bb7dSCy Schubert
8368f76bb7dSCy Schubert sin6 = (struct sockaddr_in6 *)nat64_addr;
8378f76bb7dSCy Schubert sin6->sin6_flowinfo = 0;
8388f76bb7dSCy Schubert sin6->sin6_port = sin->sin_port;
8398f76bb7dSCy Schubert
8408f76bb7dSCy Schubert nat64_prefixnet = nat64_prefixnet / 8;
8418f76bb7dSCy Schubert
8428f76bb7dSCy Schubert v4_byte = (uint8_t *)&sin->sin_addr.s_addr;
843103ba509SCy Schubert for(i = 0; i < 4; i++) {
8448f76bb7dSCy Schubert if(nat64_prefixnet == 8) {
8458f76bb7dSCy Schubert /* bits 64...71 are MBZ */
8468f76bb7dSCy Schubert sin6->sin6_addr.s6_addr[nat64_prefixnet++] = 0;
8478f76bb7dSCy Schubert }
8488f76bb7dSCy Schubert sin6->sin6_addr.s6_addr[nat64_prefixnet++] = *v4_byte++;
8498f76bb7dSCy Schubert }
8508f76bb7dSCy Schubert }
8518f76bb7dSCy Schubert
8528f76bb7dSCy Schubert int
addr_is_ip4mapped(struct sockaddr_storage * addr,socklen_t addrlen)853b7579f77SDag-Erling Smørgrav addr_is_ip4mapped(struct sockaddr_storage* addr, socklen_t addrlen)
854b7579f77SDag-Erling Smørgrav {
855b7579f77SDag-Erling Smørgrav /* prefix for ipv4 into ipv6 mapping is ::ffff:x.x.x.x */
856b7579f77SDag-Erling Smørgrav const uint8_t map_prefix[16] =
857b7579f77SDag-Erling Smørgrav {0,0,0,0, 0,0,0,0, 0,0,0xff,0xff, 0,0,0,0};
858b7579f77SDag-Erling Smørgrav uint8_t* s;
859b7579f77SDag-Erling Smørgrav if(!addr_is_ip6(addr, addrlen))
860b7579f77SDag-Erling Smørgrav return 0;
861b7579f77SDag-Erling Smørgrav /* s is 16 octet ipv6 address string */
862b7579f77SDag-Erling Smørgrav s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr;
863b7579f77SDag-Erling Smørgrav return (memcmp(s, map_prefix, 12) == 0);
864b7579f77SDag-Erling Smørgrav }
865b7579f77SDag-Erling Smørgrav
addr_is_ip6linklocal(struct sockaddr_storage * addr,socklen_t addrlen)866*56850988SCy Schubert int addr_is_ip6linklocal(struct sockaddr_storage* addr, socklen_t addrlen)
867*56850988SCy Schubert {
868*56850988SCy Schubert const uint8_t prefix[2] = {0xfe, 0x80};
869*56850988SCy Schubert int af = (int)((struct sockaddr_in6*)addr)->sin6_family;
870*56850988SCy Schubert void* sin6addr = &((struct sockaddr_in6*)addr)->sin6_addr;
871*56850988SCy Schubert uint8_t start[2];
872*56850988SCy Schubert if(af != AF_INET6 || addrlen<(socklen_t)sizeof(struct sockaddr_in6))
873*56850988SCy Schubert return 0;
874*56850988SCy Schubert /* Put the first 10 bits of sin6addr in start, match fe80::/10. */
875*56850988SCy Schubert memmove(start, sin6addr, 2);
876*56850988SCy Schubert start[1] &= 0xc0;
877*56850988SCy Schubert return memcmp(start, prefix, 2) == 0;
878*56850988SCy Schubert }
879*56850988SCy Schubert
addr_is_broadcast(struct sockaddr_storage * addr,socklen_t addrlen)880b7579f77SDag-Erling Smørgrav int addr_is_broadcast(struct sockaddr_storage* addr, socklen_t addrlen)
881b7579f77SDag-Erling Smørgrav {
882b7579f77SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family;
883b7579f77SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
884b7579f77SDag-Erling Smørgrav return af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in)
885b7579f77SDag-Erling Smørgrav && memcmp(sinaddr, "\377\377\377\377", 4) == 0;
886b7579f77SDag-Erling Smørgrav }
887b7579f77SDag-Erling Smørgrav
addr_is_any(struct sockaddr_storage * addr,socklen_t addrlen)888b7579f77SDag-Erling Smørgrav int addr_is_any(struct sockaddr_storage* addr, socklen_t addrlen)
889b7579f77SDag-Erling Smørgrav {
890b7579f77SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family;
891b7579f77SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
892b7579f77SDag-Erling Smørgrav void* sin6addr = &((struct sockaddr_in6*)addr)->sin6_addr;
893b7579f77SDag-Erling Smørgrav if(af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in)
894b7579f77SDag-Erling Smørgrav && memcmp(sinaddr, "\000\000\000\000", 4) == 0)
895b7579f77SDag-Erling Smørgrav return 1;
896b7579f77SDag-Erling Smørgrav else if(af==AF_INET6 && addrlen>=(socklen_t)sizeof(struct sockaddr_in6)
897b7579f77SDag-Erling Smørgrav && memcmp(sin6addr, "\000\000\000\000\000\000\000\000"
898b7579f77SDag-Erling Smørgrav "\000\000\000\000\000\000\000\000", 16) == 0)
899b7579f77SDag-Erling Smørgrav return 1;
900b7579f77SDag-Erling Smørgrav return 0;
901b7579f77SDag-Erling Smørgrav }
902b7579f77SDag-Erling Smørgrav
sock_list_insert(struct sock_list ** list,struct sockaddr_storage * addr,socklen_t len,struct regional * region)903b7579f77SDag-Erling Smørgrav void sock_list_insert(struct sock_list** list, struct sockaddr_storage* addr,
904b7579f77SDag-Erling Smørgrav socklen_t len, struct regional* region)
905b7579f77SDag-Erling Smørgrav {
906b7579f77SDag-Erling Smørgrav struct sock_list* add = (struct sock_list*)regional_alloc(region,
907b7579f77SDag-Erling Smørgrav sizeof(*add) - sizeof(add->addr) + (size_t)len);
908b7579f77SDag-Erling Smørgrav if(!add) {
909b7579f77SDag-Erling Smørgrav log_err("out of memory in socketlist insert");
910b7579f77SDag-Erling Smørgrav return;
911b7579f77SDag-Erling Smørgrav }
912b7579f77SDag-Erling Smørgrav log_assert(list);
913b7579f77SDag-Erling Smørgrav add->next = *list;
914b7579f77SDag-Erling Smørgrav add->len = len;
915b7579f77SDag-Erling Smørgrav *list = add;
916b7579f77SDag-Erling Smørgrav if(len) memmove(&add->addr, addr, len);
917b7579f77SDag-Erling Smørgrav }
918b7579f77SDag-Erling Smørgrav
sock_list_prepend(struct sock_list ** list,struct sock_list * add)919b7579f77SDag-Erling Smørgrav void sock_list_prepend(struct sock_list** list, struct sock_list* add)
920b7579f77SDag-Erling Smørgrav {
921b7579f77SDag-Erling Smørgrav struct sock_list* last = add;
922b7579f77SDag-Erling Smørgrav if(!last)
923b7579f77SDag-Erling Smørgrav return;
924b7579f77SDag-Erling Smørgrav while(last->next)
925b7579f77SDag-Erling Smørgrav last = last->next;
926b7579f77SDag-Erling Smørgrav last->next = *list;
927b7579f77SDag-Erling Smørgrav *list = add;
928b7579f77SDag-Erling Smørgrav }
929b7579f77SDag-Erling Smørgrav
sock_list_find(struct sock_list * list,struct sockaddr_storage * addr,socklen_t len)930b7579f77SDag-Erling Smørgrav int sock_list_find(struct sock_list* list, struct sockaddr_storage* addr,
931b7579f77SDag-Erling Smørgrav socklen_t len)
932b7579f77SDag-Erling Smørgrav {
933b7579f77SDag-Erling Smørgrav while(list) {
934b7579f77SDag-Erling Smørgrav if(len == list->len) {
935b7579f77SDag-Erling Smørgrav if(len == 0 || sockaddr_cmp_addr(addr, len,
936b7579f77SDag-Erling Smørgrav &list->addr, list->len) == 0)
937b7579f77SDag-Erling Smørgrav return 1;
938b7579f77SDag-Erling Smørgrav }
939b7579f77SDag-Erling Smørgrav list = list->next;
940b7579f77SDag-Erling Smørgrav }
941b7579f77SDag-Erling Smørgrav return 0;
942b7579f77SDag-Erling Smørgrav }
943b7579f77SDag-Erling Smørgrav
sock_list_merge(struct sock_list ** list,struct regional * region,struct sock_list * add)944b7579f77SDag-Erling Smørgrav void sock_list_merge(struct sock_list** list, struct regional* region,
945b7579f77SDag-Erling Smørgrav struct sock_list* add)
946b7579f77SDag-Erling Smørgrav {
947b7579f77SDag-Erling Smørgrav struct sock_list* p;
948b7579f77SDag-Erling Smørgrav for(p=add; p; p=p->next) {
949b7579f77SDag-Erling Smørgrav if(!sock_list_find(*list, &p->addr, p->len))
950b7579f77SDag-Erling Smørgrav sock_list_insert(list, &p->addr, p->len, region);
951b7579f77SDag-Erling Smørgrav }
952b7579f77SDag-Erling Smørgrav }
953b7579f77SDag-Erling Smørgrav
954b7579f77SDag-Erling Smørgrav void
log_crypto_err(const char * str)955b7579f77SDag-Erling Smørgrav log_crypto_err(const char* str)
956b7579f77SDag-Erling Smørgrav {
9578ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL
9580eefd307SCy Schubert log_crypto_err_code(str, ERR_get_error());
9590eefd307SCy Schubert #else
9600eefd307SCy Schubert (void)str;
9610eefd307SCy Schubert #endif /* HAVE_SSL */
9620eefd307SCy Schubert }
9630eefd307SCy Schubert
log_crypto_err_code(const char * str,unsigned long err)9640eefd307SCy Schubert void log_crypto_err_code(const char* str, unsigned long err)
9650eefd307SCy Schubert {
9660eefd307SCy Schubert #ifdef HAVE_SSL
967b7579f77SDag-Erling Smørgrav /* error:[error code]:[library name]:[function name]:[reason string] */
968b7579f77SDag-Erling Smørgrav char buf[128];
969b7579f77SDag-Erling Smørgrav unsigned long e;
9700eefd307SCy Schubert ERR_error_string_n(err, buf, sizeof(buf));
971b7579f77SDag-Erling Smørgrav log_err("%s crypto %s", str, buf);
972b7579f77SDag-Erling Smørgrav while( (e=ERR_get_error()) ) {
973b7579f77SDag-Erling Smørgrav ERR_error_string_n(e, buf, sizeof(buf));
974b7579f77SDag-Erling Smørgrav log_err("and additionally crypto %s", buf);
975b7579f77SDag-Erling Smørgrav }
9768ed2b524SDag-Erling Smørgrav #else
9778ed2b524SDag-Erling Smørgrav (void)str;
9780eefd307SCy Schubert (void)err;
9798ed2b524SDag-Erling Smørgrav #endif /* HAVE_SSL */
980b7579f77SDag-Erling Smørgrav }
981b7579f77SDag-Erling Smørgrav
98225039b37SCy Schubert #ifdef HAVE_SSL
983103ba509SCy Schubert /** Print crypt erro with SSL_get_error want code and err_get_error code */
log_crypto_err_io_code_arg(const char * str,int r,unsigned long err,int err_present)984103ba509SCy Schubert static void log_crypto_err_io_code_arg(const char* str, int r,
985103ba509SCy Schubert unsigned long err, int err_present)
986103ba509SCy Schubert {
987103ba509SCy Schubert int print_errno = 0, print_crypto_err = 0;
988103ba509SCy Schubert const char* inf = NULL;
989103ba509SCy Schubert
990103ba509SCy Schubert switch(r) {
991103ba509SCy Schubert case SSL_ERROR_NONE:
992103ba509SCy Schubert inf = "no error";
993103ba509SCy Schubert break;
994103ba509SCy Schubert case SSL_ERROR_ZERO_RETURN:
995103ba509SCy Schubert inf = "channel closed";
996103ba509SCy Schubert break;
997103ba509SCy Schubert case SSL_ERROR_WANT_READ:
998103ba509SCy Schubert inf = "want read";
999103ba509SCy Schubert break;
1000103ba509SCy Schubert case SSL_ERROR_WANT_WRITE:
1001103ba509SCy Schubert inf = "want write";
1002103ba509SCy Schubert break;
1003103ba509SCy Schubert case SSL_ERROR_WANT_CONNECT:
1004103ba509SCy Schubert inf = "want connect";
1005103ba509SCy Schubert break;
1006103ba509SCy Schubert case SSL_ERROR_WANT_ACCEPT:
1007103ba509SCy Schubert inf = "want accept";
1008103ba509SCy Schubert break;
1009103ba509SCy Schubert case SSL_ERROR_WANT_X509_LOOKUP:
1010103ba509SCy Schubert inf = "want X509 lookup";
1011103ba509SCy Schubert break;
1012103ba509SCy Schubert #ifdef SSL_ERROR_WANT_ASYNC
1013103ba509SCy Schubert case SSL_ERROR_WANT_ASYNC:
1014103ba509SCy Schubert inf = "want async";
1015103ba509SCy Schubert break;
1016103ba509SCy Schubert #endif
1017103ba509SCy Schubert #ifdef SSL_ERROR_WANT_ASYNC_JOB
1018103ba509SCy Schubert case SSL_ERROR_WANT_ASYNC_JOB:
1019103ba509SCy Schubert inf = "want async job";
1020103ba509SCy Schubert break;
1021103ba509SCy Schubert #endif
1022103ba509SCy Schubert #ifdef SSL_ERROR_WANT_CLIENT_HELLO_CB
1023103ba509SCy Schubert case SSL_ERROR_WANT_CLIENT_HELLO_CB:
1024103ba509SCy Schubert inf = "want client hello cb";
1025103ba509SCy Schubert break;
1026103ba509SCy Schubert #endif
1027103ba509SCy Schubert case SSL_ERROR_SYSCALL:
1028103ba509SCy Schubert print_errno = 1;
1029103ba509SCy Schubert inf = "syscall";
1030103ba509SCy Schubert break;
1031103ba509SCy Schubert case SSL_ERROR_SSL:
1032103ba509SCy Schubert print_crypto_err = 1;
1033103ba509SCy Schubert inf = "SSL, usually protocol, error";
1034103ba509SCy Schubert break;
1035103ba509SCy Schubert default:
1036103ba509SCy Schubert inf = "unknown SSL_get_error result code";
1037103ba509SCy Schubert print_errno = 1;
1038103ba509SCy Schubert print_crypto_err = 1;
1039103ba509SCy Schubert }
1040103ba509SCy Schubert if(print_crypto_err) {
1041103ba509SCy Schubert if(print_errno) {
1042103ba509SCy Schubert char buf[1024];
1043103ba509SCy Schubert snprintf(buf, sizeof(buf), "%s with errno %s",
1044103ba509SCy Schubert str, strerror(errno));
1045103ba509SCy Schubert if(err_present)
1046103ba509SCy Schubert log_crypto_err_code(buf, err);
1047103ba509SCy Schubert else log_crypto_err(buf);
1048103ba509SCy Schubert } else {
1049103ba509SCy Schubert if(err_present)
1050103ba509SCy Schubert log_crypto_err_code(str, err);
1051103ba509SCy Schubert else log_crypto_err(str);
1052103ba509SCy Schubert }
1053103ba509SCy Schubert } else {
1054103ba509SCy Schubert if(print_errno) {
1055103ba509SCy Schubert if(errno == 0)
1056335c7cdaSCy Schubert log_err("%s: syscall error with errno %s",
1057335c7cdaSCy Schubert str, strerror(errno));
1058335c7cdaSCy Schubert else log_err("%s: %s", str, strerror(errno));
1059103ba509SCy Schubert } else {
1060335c7cdaSCy Schubert log_err("%s: %s", str, inf);
1061103ba509SCy Schubert }
1062103ba509SCy Schubert }
1063103ba509SCy Schubert }
1064103ba509SCy Schubert #endif /* HAVE_SSL */
1065103ba509SCy Schubert
log_crypto_err_io(const char * str,int r)1066103ba509SCy Schubert void log_crypto_err_io(const char* str, int r)
1067103ba509SCy Schubert {
1068103ba509SCy Schubert #ifdef HAVE_SSL
1069103ba509SCy Schubert log_crypto_err_io_code_arg(str, r, 0, 0);
1070103ba509SCy Schubert #else
1071103ba509SCy Schubert (void)str;
1072103ba509SCy Schubert (void)r;
1073103ba509SCy Schubert #endif /* HAVE_SSL */
1074103ba509SCy Schubert }
1075103ba509SCy Schubert
log_crypto_err_io_code(const char * str,int r,unsigned long err)1076103ba509SCy Schubert void log_crypto_err_io_code(const char* str, int r, unsigned long err)
1077103ba509SCy Schubert {
1078103ba509SCy Schubert #ifdef HAVE_SSL
1079103ba509SCy Schubert log_crypto_err_io_code_arg(str, r, err, 1);
1080103ba509SCy Schubert #else
1081103ba509SCy Schubert (void)str;
1082103ba509SCy Schubert (void)r;
1083103ba509SCy Schubert (void)err;
1084103ba509SCy Schubert #endif /* HAVE_SSL */
1085103ba509SCy Schubert }
1086103ba509SCy Schubert
1087103ba509SCy Schubert #ifdef HAVE_SSL
108825039b37SCy Schubert /** log certificate details */
108925039b37SCy Schubert void
log_cert(unsigned level,const char * str,void * cert)109025039b37SCy Schubert log_cert(unsigned level, const char* str, void* cert)
109125039b37SCy Schubert {
109225039b37SCy Schubert BIO* bio;
109325039b37SCy Schubert char nul = 0;
109425039b37SCy Schubert char* pp = NULL;
109525039b37SCy Schubert long len;
109625039b37SCy Schubert if(verbosity < level) return;
109725039b37SCy Schubert bio = BIO_new(BIO_s_mem());
109825039b37SCy Schubert if(!bio) return;
109925039b37SCy Schubert X509_print_ex(bio, (X509*)cert, 0, (unsigned long)-1
110025039b37SCy Schubert ^(X509_FLAG_NO_SUBJECT
110125039b37SCy Schubert |X509_FLAG_NO_ISSUER|X509_FLAG_NO_VALIDITY
110225039b37SCy Schubert |X509_FLAG_NO_EXTENSIONS|X509_FLAG_NO_AUX
110325039b37SCy Schubert |X509_FLAG_NO_ATTRIBUTES));
110425039b37SCy Schubert BIO_write(bio, &nul, (int)sizeof(nul));
110525039b37SCy Schubert len = BIO_get_mem_data(bio, &pp);
110625039b37SCy Schubert if(len != 0 && pp) {
110724e36522SCy Schubert /* reduce size of cert printout */
110824e36522SCy Schubert char* s;
110924e36522SCy Schubert while((s=strstr(pp, " "))!=NULL)
111024e36522SCy Schubert memmove(s, s+1, strlen(s+1)+1);
111124e36522SCy Schubert while((s=strstr(pp, "\t\t"))!=NULL)
111224e36522SCy Schubert memmove(s, s+1, strlen(s+1)+1);
111325039b37SCy Schubert verbose(level, "%s: \n%s", str, pp);
111425039b37SCy Schubert }
111525039b37SCy Schubert BIO_free(bio);
111625039b37SCy Schubert }
111725039b37SCy Schubert #endif /* HAVE_SSL */
111825039b37SCy Schubert
11195469a995SCy Schubert #if defined(HAVE_SSL) && defined(HAVE_NGHTTP2) && defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB)
alpn_select_cb(SSL * ATTR_UNUSED (ssl),const unsigned char ** out,unsigned char * outlen,const unsigned char * in,unsigned int inlen,void * ATTR_UNUSED (arg))1120c0caa2e2SCy Schubert static int alpn_select_cb(SSL* ATTR_UNUSED(ssl), const unsigned char** out,
1121c0caa2e2SCy Schubert unsigned char* outlen, const unsigned char* in, unsigned int inlen,
1122c0caa2e2SCy Schubert void* ATTR_UNUSED(arg))
1123c0caa2e2SCy Schubert {
1124c0caa2e2SCy Schubert int rv = nghttp2_select_next_protocol((unsigned char **)out, outlen, in,
1125c0caa2e2SCy Schubert inlen);
1126c0caa2e2SCy Schubert if(rv == -1) {
1127c0caa2e2SCy Schubert return SSL_TLSEXT_ERR_NOACK;
1128c0caa2e2SCy Schubert }
1129c0caa2e2SCy Schubert /* either http/1.1 or h2 selected */
1130c0caa2e2SCy Schubert return SSL_TLSEXT_ERR_OK;
1131c0caa2e2SCy Schubert }
1132c0caa2e2SCy Schubert #endif
1133c0caa2e2SCy Schubert
1134971980c3SDag-Erling Smørgrav int
listen_sslctx_setup(void * ctxt)1135971980c3SDag-Erling Smørgrav listen_sslctx_setup(void* ctxt)
1136971980c3SDag-Erling Smørgrav {
1137971980c3SDag-Erling Smørgrav #ifdef HAVE_SSL
1138971980c3SDag-Erling Smørgrav SSL_CTX* ctx = (SSL_CTX*)ctxt;
1139971980c3SDag-Erling Smørgrav /* no SSLv2, SSLv3 because has defects */
1140091e9e46SCy Schubert #if SSL_OP_NO_SSLv2 != 0
1141971980c3SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
1142971980c3SDag-Erling Smørgrav != SSL_OP_NO_SSLv2){
1143971980c3SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_NO_SSLv2");
1144971980c3SDag-Erling Smørgrav return 0;
1145971980c3SDag-Erling Smørgrav }
1146091e9e46SCy Schubert #endif
1147971980c3SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
1148971980c3SDag-Erling Smørgrav != SSL_OP_NO_SSLv3){
1149971980c3SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_NO_SSLv3");
1150971980c3SDag-Erling Smørgrav return 0;
1151971980c3SDag-Erling Smørgrav }
1152971980c3SDag-Erling Smørgrav #if defined(SSL_OP_NO_TLSv1) && defined(SSL_OP_NO_TLSv1_1)
1153971980c3SDag-Erling Smørgrav /* if we have tls 1.1 disable 1.0 */
1154971980c3SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1) & SSL_OP_NO_TLSv1)
1155971980c3SDag-Erling Smørgrav != SSL_OP_NO_TLSv1){
1156971980c3SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_NO_TLSv1");
1157971980c3SDag-Erling Smørgrav return 0;
1158971980c3SDag-Erling Smørgrav }
1159971980c3SDag-Erling Smørgrav #endif
1160971980c3SDag-Erling Smørgrav #if defined(SSL_OP_NO_TLSv1_1) && defined(SSL_OP_NO_TLSv1_2)
1161971980c3SDag-Erling Smørgrav /* if we have tls 1.2 disable 1.1 */
1162971980c3SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_1) & SSL_OP_NO_TLSv1_1)
1163971980c3SDag-Erling Smørgrav != SSL_OP_NO_TLSv1_1){
1164971980c3SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_NO_TLSv1_1");
1165971980c3SDag-Erling Smørgrav return 0;
1166971980c3SDag-Erling Smørgrav }
1167971980c3SDag-Erling Smørgrav #endif
11680eefd307SCy Schubert #if defined(SSL_OP_NO_RENEGOTIATION)
11690eefd307SCy Schubert /* disable client renegotiation */
11700eefd307SCy Schubert if((SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION) &
11710eefd307SCy Schubert SSL_OP_NO_RENEGOTIATION) != SSL_OP_NO_RENEGOTIATION) {
11720eefd307SCy Schubert log_crypto_err("could not set SSL_OP_NO_RENEGOTIATION");
11730eefd307SCy Schubert return 0;
11740eefd307SCy Schubert }
11750eefd307SCy Schubert #endif
1176971980c3SDag-Erling Smørgrav #if defined(SHA256_DIGEST_LENGTH) && defined(USE_ECDSA)
117724e36522SCy Schubert /* if we detect system-wide crypto policies, use those */
117824e36522SCy Schubert if (access( "/etc/crypto-policies/config", F_OK ) != 0 ) {
1179971980c3SDag-Erling Smørgrav /* if we have sha256, set the cipher list to have no known vulns */
118057bddd21SDag-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"))
1181971980c3SDag-Erling Smørgrav log_crypto_err("could not set cipher list with SSL_CTX_set_cipher_list");
118224e36522SCy Schubert }
1183971980c3SDag-Erling Smørgrav #endif
11848f76bb7dSCy Schubert #if defined(SSL_OP_IGNORE_UNEXPECTED_EOF)
11858f76bb7dSCy Schubert /* ignore errors when peers do not send the mandatory close_notify
11868f76bb7dSCy Schubert * alert on shutdown.
11878f76bb7dSCy Schubert * Relevant for openssl >= 3 */
11888f76bb7dSCy Schubert if((SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF) &
11898f76bb7dSCy Schubert SSL_OP_IGNORE_UNEXPECTED_EOF) != SSL_OP_IGNORE_UNEXPECTED_EOF) {
11908f76bb7dSCy Schubert log_crypto_err("could not set SSL_OP_IGNORE_UNEXPECTED_EOF");
11918f76bb7dSCy Schubert return 0;
11928f76bb7dSCy Schubert }
11938f76bb7dSCy Schubert #endif
1194971980c3SDag-Erling Smørgrav
1195971980c3SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE) &
1196971980c3SDag-Erling Smørgrav SSL_OP_CIPHER_SERVER_PREFERENCE) !=
1197971980c3SDag-Erling Smørgrav SSL_OP_CIPHER_SERVER_PREFERENCE) {
1198971980c3SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_CIPHER_SERVER_PREFERENCE");
1199971980c3SDag-Erling Smørgrav return 0;
1200971980c3SDag-Erling Smørgrav }
1201971980c3SDag-Erling Smørgrav
1202971980c3SDag-Erling Smørgrav #ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL
1203971980c3SDag-Erling Smørgrav SSL_CTX_set_security_level(ctx, 0);
1204971980c3SDag-Erling Smørgrav #endif
1205c0caa2e2SCy Schubert #if defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB) && defined(HAVE_NGHTTP2)
1206c0caa2e2SCy Schubert SSL_CTX_set_alpn_select_cb(ctx, alpn_select_cb, NULL);
1207c0caa2e2SCy Schubert #endif
1208971980c3SDag-Erling Smørgrav #else
1209971980c3SDag-Erling Smørgrav (void)ctxt;
1210971980c3SDag-Erling Smørgrav #endif /* HAVE_SSL */
1211971980c3SDag-Erling Smørgrav return 1;
1212971980c3SDag-Erling Smørgrav }
1213971980c3SDag-Erling Smørgrav
1214971980c3SDag-Erling Smørgrav void
listen_sslctx_setup_2(void * ctxt)1215971980c3SDag-Erling Smørgrav listen_sslctx_setup_2(void* ctxt)
1216971980c3SDag-Erling Smørgrav {
1217971980c3SDag-Erling Smørgrav #ifdef HAVE_SSL
1218971980c3SDag-Erling Smørgrav SSL_CTX* ctx = (SSL_CTX*)ctxt;
1219971980c3SDag-Erling Smørgrav (void)ctx;
1220971980c3SDag-Erling Smørgrav #if HAVE_DECL_SSL_CTX_SET_ECDH_AUTO
1221971980c3SDag-Erling Smørgrav if(!SSL_CTX_set_ecdh_auto(ctx,1)) {
1222971980c3SDag-Erling Smørgrav log_crypto_err("Error in SSL_CTX_ecdh_auto, not enabling ECDHE");
1223971980c3SDag-Erling Smørgrav }
1224*56850988SCy Schubert #elif defined(USE_ECDSA) && defined(HAVE_SSL_CTX_SET_TMP_ECDH)
1225971980c3SDag-Erling Smørgrav if(1) {
1226971980c3SDag-Erling Smørgrav EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1);
1227971980c3SDag-Erling Smørgrav if (!ecdh) {
1228971980c3SDag-Erling Smørgrav log_crypto_err("could not find p256, not enabling ECDHE");
1229971980c3SDag-Erling Smørgrav } else {
1230971980c3SDag-Erling Smørgrav if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh)) {
1231971980c3SDag-Erling Smørgrav log_crypto_err("Error in SSL_CTX_set_tmp_ecdh, not enabling ECDHE");
1232971980c3SDag-Erling Smørgrav }
1233971980c3SDag-Erling Smørgrav EC_KEY_free (ecdh);
1234971980c3SDag-Erling Smørgrav }
1235971980c3SDag-Erling Smørgrav }
1236971980c3SDag-Erling Smørgrav #endif
1237971980c3SDag-Erling Smørgrav #else
1238971980c3SDag-Erling Smørgrav (void)ctxt;
1239971980c3SDag-Erling Smørgrav #endif /* HAVE_SSL */
1240971980c3SDag-Erling Smørgrav }
1241971980c3SDag-Erling Smørgrav
listen_sslctx_create(char * key,char * pem,char * verifypem)1242b7579f77SDag-Erling Smørgrav void* listen_sslctx_create(char* key, char* pem, char* verifypem)
1243b7579f77SDag-Erling Smørgrav {
12448ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL
1245b7579f77SDag-Erling Smørgrav SSL_CTX* ctx = SSL_CTX_new(SSLv23_server_method());
1246b7579f77SDag-Erling Smørgrav if(!ctx) {
1247b7579f77SDag-Erling Smørgrav log_crypto_err("could not SSL_CTX_new");
1248b7579f77SDag-Erling Smørgrav return NULL;
1249b7579f77SDag-Erling Smørgrav }
1250e86b9096SDag-Erling Smørgrav if(!key || key[0] == 0) {
1251e86b9096SDag-Erling Smørgrav log_err("error: no tls-service-key file specified");
1252e86b9096SDag-Erling Smørgrav SSL_CTX_free(ctx);
1253e86b9096SDag-Erling Smørgrav return NULL;
1254e86b9096SDag-Erling Smørgrav }
1255e86b9096SDag-Erling Smørgrav if(!pem || pem[0] == 0) {
1256e86b9096SDag-Erling Smørgrav log_err("error: no tls-service-pem file specified");
1257e86b9096SDag-Erling Smørgrav SSL_CTX_free(ctx);
1258e86b9096SDag-Erling Smørgrav return NULL;
1259e86b9096SDag-Erling Smørgrav }
1260971980c3SDag-Erling Smørgrav if(!listen_sslctx_setup(ctx)) {
1261ff825849SDag-Erling Smørgrav SSL_CTX_free(ctx);
1262ff825849SDag-Erling Smørgrav return NULL;
1263ff825849SDag-Erling Smørgrav }
1264b75612f8SDag-Erling Smørgrav if(!SSL_CTX_use_certificate_chain_file(ctx, pem)) {
1265b7579f77SDag-Erling Smørgrav log_err("error for cert file: %s", pem);
1266b75612f8SDag-Erling Smørgrav log_crypto_err("error in SSL_CTX use_certificate_chain_file");
1267b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx);
1268b7579f77SDag-Erling Smørgrav return NULL;
1269b7579f77SDag-Erling Smørgrav }
1270b7579f77SDag-Erling Smørgrav if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) {
1271b7579f77SDag-Erling Smørgrav log_err("error for private key file: %s", key);
1272b7579f77SDag-Erling Smørgrav log_crypto_err("Error in SSL_CTX use_PrivateKey_file");
1273b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx);
1274b7579f77SDag-Erling Smørgrav return NULL;
1275b7579f77SDag-Erling Smørgrav }
1276b7579f77SDag-Erling Smørgrav if(!SSL_CTX_check_private_key(ctx)) {
1277b7579f77SDag-Erling Smørgrav log_err("error for key file: %s", key);
1278b7579f77SDag-Erling Smørgrav log_crypto_err("Error in SSL_CTX check_private_key");
1279b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx);
1280b7579f77SDag-Erling Smørgrav return NULL;
1281b7579f77SDag-Erling Smørgrav }
1282971980c3SDag-Erling Smørgrav listen_sslctx_setup_2(ctx);
1283b7579f77SDag-Erling Smørgrav if(verifypem && verifypem[0]) {
1284b7579f77SDag-Erling Smørgrav if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) {
1285b7579f77SDag-Erling Smørgrav log_crypto_err("Error in SSL_CTX verify locations");
1286b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx);
1287b7579f77SDag-Erling Smørgrav return NULL;
1288b7579f77SDag-Erling Smørgrav }
1289b7579f77SDag-Erling Smørgrav SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(
1290b7579f77SDag-Erling Smørgrav verifypem));
129125039b37SCy Schubert SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
1292b7579f77SDag-Erling Smørgrav }
1293b7579f77SDag-Erling Smørgrav return ctx;
12948ed2b524SDag-Erling Smørgrav #else
12958ed2b524SDag-Erling Smørgrav (void)key; (void)pem; (void)verifypem;
12968ed2b524SDag-Erling Smørgrav return NULL;
12978ed2b524SDag-Erling Smørgrav #endif
1298b7579f77SDag-Erling Smørgrav }
1299b7579f77SDag-Erling Smørgrav
13003bd4df0aSDag-Erling Smørgrav #ifdef USE_WINSOCK
13013bd4df0aSDag-Erling Smørgrav /* For windows, the CA trust store is not read by openssl.
13023bd4df0aSDag-Erling Smørgrav Add code to open the trust store using wincrypt API and add
13033bd4df0aSDag-Erling Smørgrav the root certs into openssl trust store */
13043bd4df0aSDag-Erling Smørgrav static int
add_WIN_cacerts_to_openssl_store(SSL_CTX * tls_ctx)13053bd4df0aSDag-Erling Smørgrav add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx)
13063bd4df0aSDag-Erling Smørgrav {
13073bd4df0aSDag-Erling Smørgrav HCERTSTORE hSystemStore;
13083bd4df0aSDag-Erling Smørgrav PCCERT_CONTEXT pTargetCert = NULL;
13093bd4df0aSDag-Erling Smørgrav X509_STORE* store;
13103bd4df0aSDag-Erling Smørgrav
13113bd4df0aSDag-Erling Smørgrav verbose(VERB_ALGO, "Adding Windows certificates from system root store to CA store");
13123bd4df0aSDag-Erling Smørgrav
13133bd4df0aSDag-Erling Smørgrav /* load just once per context lifetime for this version
13143bd4df0aSDag-Erling Smørgrav TODO: dynamically update CA trust changes as they are available */
13153bd4df0aSDag-Erling Smørgrav if (!tls_ctx)
13163bd4df0aSDag-Erling Smørgrav return 0;
13173bd4df0aSDag-Erling Smørgrav
13183bd4df0aSDag-Erling Smørgrav /* Call wincrypt's CertOpenStore to open the CA root store. */
13193bd4df0aSDag-Erling Smørgrav
13203bd4df0aSDag-Erling Smørgrav if ((hSystemStore = CertOpenStore(
13213bd4df0aSDag-Erling Smørgrav CERT_STORE_PROV_SYSTEM,
13223bd4df0aSDag-Erling Smørgrav 0,
13233bd4df0aSDag-Erling Smørgrav 0,
13243bd4df0aSDag-Erling Smørgrav /* NOTE: mingw does not have this const: replace with 1 << 16 from code
13253bd4df0aSDag-Erling Smørgrav CERT_SYSTEM_STORE_CURRENT_USER, */
13263bd4df0aSDag-Erling Smørgrav 1 << 16,
13273bd4df0aSDag-Erling Smørgrav L"root")) == 0)
13283bd4df0aSDag-Erling Smørgrav {
13293bd4df0aSDag-Erling Smørgrav return 0;
13303bd4df0aSDag-Erling Smørgrav }
13313bd4df0aSDag-Erling Smørgrav
13323bd4df0aSDag-Erling Smørgrav store = SSL_CTX_get_cert_store(tls_ctx);
13333bd4df0aSDag-Erling Smørgrav if (!store)
13343bd4df0aSDag-Erling Smørgrav return 0;
13353bd4df0aSDag-Erling Smørgrav
13363bd4df0aSDag-Erling Smørgrav /* failure if the CA store is empty or the call fails */
13373bd4df0aSDag-Erling Smørgrav if ((pTargetCert = CertEnumCertificatesInStore(
13383bd4df0aSDag-Erling Smørgrav hSystemStore, pTargetCert)) == 0) {
13393bd4df0aSDag-Erling Smørgrav verbose(VERB_ALGO, "CA certificate store for Windows is empty.");
13403bd4df0aSDag-Erling Smørgrav return 0;
13413bd4df0aSDag-Erling Smørgrav }
13423bd4df0aSDag-Erling Smørgrav /* iterate over the windows cert store and add to openssl store */
13433bd4df0aSDag-Erling Smørgrav do
13443bd4df0aSDag-Erling Smørgrav {
13453bd4df0aSDag-Erling Smørgrav X509 *cert1 = d2i_X509(NULL,
13463bd4df0aSDag-Erling Smørgrav (const unsigned char **)&pTargetCert->pbCertEncoded,
13473bd4df0aSDag-Erling Smørgrav pTargetCert->cbCertEncoded);
13483bd4df0aSDag-Erling Smørgrav if (!cert1) {
13490a92a9fcSCy Schubert unsigned long error = ERR_get_error();
13503bd4df0aSDag-Erling Smørgrav /* return error if a cert fails */
13513bd4df0aSDag-Erling Smørgrav verbose(VERB_ALGO, "%s %d:%s",
13523bd4df0aSDag-Erling Smørgrav "Unable to parse certificate in memory",
13530a92a9fcSCy Schubert (int)error, ERR_error_string(error, NULL));
13543bd4df0aSDag-Erling Smørgrav return 0;
13553bd4df0aSDag-Erling Smørgrav }
13563bd4df0aSDag-Erling Smørgrav else {
13573bd4df0aSDag-Erling Smørgrav /* return error if a cert add to store fails */
13583bd4df0aSDag-Erling Smørgrav if (X509_STORE_add_cert(store, cert1) == 0) {
13593bd4df0aSDag-Erling Smørgrav unsigned long error = ERR_peek_last_error();
13603bd4df0aSDag-Erling Smørgrav
13613bd4df0aSDag-Erling Smørgrav /* Ignore error X509_R_CERT_ALREADY_IN_HASH_TABLE which means the
13623bd4df0aSDag-Erling Smørgrav * certificate is already in the store. */
13633bd4df0aSDag-Erling Smørgrav if(ERR_GET_LIB(error) != ERR_LIB_X509 ||
13643bd4df0aSDag-Erling Smørgrav ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
13650a92a9fcSCy Schubert error = ERR_get_error();
13663bd4df0aSDag-Erling Smørgrav verbose(VERB_ALGO, "%s %d:%s\n",
13670a92a9fcSCy Schubert "Error adding certificate", (int)error,
13680a92a9fcSCy Schubert ERR_error_string(error, NULL));
13693bd4df0aSDag-Erling Smørgrav X509_free(cert1);
13703bd4df0aSDag-Erling Smørgrav return 0;
13713bd4df0aSDag-Erling Smørgrav }
13723bd4df0aSDag-Erling Smørgrav }
13733bd4df0aSDag-Erling Smørgrav X509_free(cert1);
13743bd4df0aSDag-Erling Smørgrav }
13753bd4df0aSDag-Erling Smørgrav } while ((pTargetCert = CertEnumCertificatesInStore(
13763bd4df0aSDag-Erling Smørgrav hSystemStore, pTargetCert)) != 0);
13773bd4df0aSDag-Erling Smørgrav
13783bd4df0aSDag-Erling Smørgrav /* Clean up memory and quit. */
13793bd4df0aSDag-Erling Smørgrav if (pTargetCert)
13803bd4df0aSDag-Erling Smørgrav CertFreeCertificateContext(pTargetCert);
13813bd4df0aSDag-Erling Smørgrav if (hSystemStore)
13823bd4df0aSDag-Erling Smørgrav {
13833bd4df0aSDag-Erling Smørgrav if (!CertCloseStore(
13843bd4df0aSDag-Erling Smørgrav hSystemStore, 0))
13853bd4df0aSDag-Erling Smørgrav return 0;
13863bd4df0aSDag-Erling Smørgrav }
13873bd4df0aSDag-Erling Smørgrav verbose(VERB_ALGO, "Completed adding Windows certificates to CA store successfully");
13883bd4df0aSDag-Erling Smørgrav return 1;
13893bd4df0aSDag-Erling Smørgrav }
13903bd4df0aSDag-Erling Smørgrav #endif /* USE_WINSOCK */
13913bd4df0aSDag-Erling Smørgrav
connect_sslctx_create(char * key,char * pem,char * verifypem,int wincert)13923bd4df0aSDag-Erling Smørgrav void* connect_sslctx_create(char* key, char* pem, char* verifypem, int wincert)
1393b7579f77SDag-Erling Smørgrav {
13948ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL
1395b7579f77SDag-Erling Smørgrav SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method());
1396b7579f77SDag-Erling Smørgrav if(!ctx) {
1397b7579f77SDag-Erling Smørgrav log_crypto_err("could not allocate SSL_CTX pointer");
1398b7579f77SDag-Erling Smørgrav return NULL;
1399b7579f77SDag-Erling Smørgrav }
1400091e9e46SCy Schubert #if SSL_OP_NO_SSLv2 != 0
140105ab2901SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
140205ab2901SDag-Erling Smørgrav != SSL_OP_NO_SSLv2) {
1403b7579f77SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_NO_SSLv2");
1404b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx);
1405b7579f77SDag-Erling Smørgrav return NULL;
1406b7579f77SDag-Erling Smørgrav }
1407091e9e46SCy Schubert #endif
140805ab2901SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
140905ab2901SDag-Erling Smørgrav != SSL_OP_NO_SSLv3) {
1410ff825849SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_NO_SSLv3");
1411ff825849SDag-Erling Smørgrav SSL_CTX_free(ctx);
1412ff825849SDag-Erling Smørgrav return NULL;
1413ff825849SDag-Erling Smørgrav }
14140eefd307SCy Schubert #if defined(SSL_OP_NO_RENEGOTIATION)
14150eefd307SCy Schubert /* disable client renegotiation */
14160eefd307SCy Schubert if((SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION) &
14170eefd307SCy Schubert SSL_OP_NO_RENEGOTIATION) != SSL_OP_NO_RENEGOTIATION) {
14180eefd307SCy Schubert log_crypto_err("could not set SSL_OP_NO_RENEGOTIATION");
141924e36522SCy Schubert SSL_CTX_free(ctx);
14200eefd307SCy Schubert return 0;
14210eefd307SCy Schubert }
14220eefd307SCy Schubert #endif
14238f76bb7dSCy Schubert #if defined(SSL_OP_IGNORE_UNEXPECTED_EOF)
14248f76bb7dSCy Schubert /* ignore errors when peers do not send the mandatory close_notify
14258f76bb7dSCy Schubert * alert on shutdown.
14268f76bb7dSCy Schubert * Relevant for openssl >= 3 */
14278f76bb7dSCy Schubert if((SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF) &
14288f76bb7dSCy Schubert SSL_OP_IGNORE_UNEXPECTED_EOF) != SSL_OP_IGNORE_UNEXPECTED_EOF) {
14298f76bb7dSCy Schubert log_crypto_err("could not set SSL_OP_IGNORE_UNEXPECTED_EOF");
14308f76bb7dSCy Schubert SSL_CTX_free(ctx);
14318f76bb7dSCy Schubert return 0;
14328f76bb7dSCy Schubert }
14338f76bb7dSCy Schubert #endif
1434b7579f77SDag-Erling Smørgrav if(key && key[0]) {
1435b75612f8SDag-Erling Smørgrav if(!SSL_CTX_use_certificate_chain_file(ctx, pem)) {
1436b7579f77SDag-Erling Smørgrav log_err("error in client certificate %s", pem);
1437b7579f77SDag-Erling Smørgrav log_crypto_err("error in certificate file");
1438b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx);
1439b7579f77SDag-Erling Smørgrav return NULL;
1440b7579f77SDag-Erling Smørgrav }
1441b7579f77SDag-Erling Smørgrav if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) {
1442b7579f77SDag-Erling Smørgrav log_err("error in client private key %s", key);
1443b7579f77SDag-Erling Smørgrav log_crypto_err("error in key file");
1444b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx);
1445b7579f77SDag-Erling Smørgrav return NULL;
1446b7579f77SDag-Erling Smørgrav }
1447b7579f77SDag-Erling Smørgrav if(!SSL_CTX_check_private_key(ctx)) {
1448b7579f77SDag-Erling Smørgrav log_err("error in client key %s", key);
1449b7579f77SDag-Erling Smørgrav log_crypto_err("error in SSL_CTX_check_private_key");
1450b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx);
1451b7579f77SDag-Erling Smørgrav return NULL;
1452b7579f77SDag-Erling Smørgrav }
1453b7579f77SDag-Erling Smørgrav }
14543bd4df0aSDag-Erling Smørgrav if((verifypem && verifypem[0]) || wincert) {
1455b7579f77SDag-Erling Smørgrav if(verifypem && verifypem[0]) {
1456ff825849SDag-Erling Smørgrav if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) {
1457b7579f77SDag-Erling Smørgrav log_crypto_err("error in SSL_CTX verify");
1458b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx);
1459b7579f77SDag-Erling Smørgrav return NULL;
1460b7579f77SDag-Erling Smørgrav }
14613bd4df0aSDag-Erling Smørgrav }
14623bd4df0aSDag-Erling Smørgrav #ifdef USE_WINSOCK
14633bd4df0aSDag-Erling Smørgrav if(wincert) {
14643bd4df0aSDag-Erling Smørgrav if(!add_WIN_cacerts_to_openssl_store(ctx)) {
14653bd4df0aSDag-Erling Smørgrav log_crypto_err("error in add_WIN_cacerts_to_openssl_store");
14663bd4df0aSDag-Erling Smørgrav SSL_CTX_free(ctx);
14673bd4df0aSDag-Erling Smørgrav return NULL;
14683bd4df0aSDag-Erling Smørgrav }
14693bd4df0aSDag-Erling Smørgrav }
14703bd4df0aSDag-Erling Smørgrav #else
1471a39a5a69SCy Schubert if(wincert) {
1472a39a5a69SCy Schubert if(!SSL_CTX_set_default_verify_paths(ctx)) {
1473a39a5a69SCy Schubert log_crypto_err("error in default_verify_paths");
1474a39a5a69SCy Schubert SSL_CTX_free(ctx);
1475a39a5a69SCy Schubert return NULL;
1476a39a5a69SCy Schubert }
1477a39a5a69SCy Schubert }
14783bd4df0aSDag-Erling Smørgrav #endif
1479b7579f77SDag-Erling Smørgrav SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
1480b7579f77SDag-Erling Smørgrav }
1481b7579f77SDag-Erling Smørgrav return ctx;
14828ed2b524SDag-Erling Smørgrav #else
14833bd4df0aSDag-Erling Smørgrav (void)key; (void)pem; (void)verifypem; (void)wincert;
14848ed2b524SDag-Erling Smørgrav return NULL;
14858ed2b524SDag-Erling Smørgrav #endif
1486b7579f77SDag-Erling Smørgrav }
1487b7579f77SDag-Erling Smørgrav
incoming_ssl_fd(void * sslctx,int fd)1488b7579f77SDag-Erling Smørgrav void* incoming_ssl_fd(void* sslctx, int fd)
1489b7579f77SDag-Erling Smørgrav {
14908ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL
1491b7579f77SDag-Erling Smørgrav SSL* ssl = SSL_new((SSL_CTX*)sslctx);
1492b7579f77SDag-Erling Smørgrav if(!ssl) {
1493b7579f77SDag-Erling Smørgrav log_crypto_err("could not SSL_new");
1494b7579f77SDag-Erling Smørgrav return NULL;
1495b7579f77SDag-Erling Smørgrav }
1496b7579f77SDag-Erling Smørgrav SSL_set_accept_state(ssl);
14970eefd307SCy Schubert (void)SSL_set_mode(ssl, (long)SSL_MODE_AUTO_RETRY);
1498b7579f77SDag-Erling Smørgrav if(!SSL_set_fd(ssl, fd)) {
1499b7579f77SDag-Erling Smørgrav log_crypto_err("could not SSL_set_fd");
1500b7579f77SDag-Erling Smørgrav SSL_free(ssl);
1501b7579f77SDag-Erling Smørgrav return NULL;
1502b7579f77SDag-Erling Smørgrav }
1503b7579f77SDag-Erling Smørgrav return ssl;
15048ed2b524SDag-Erling Smørgrav #else
15058ed2b524SDag-Erling Smørgrav (void)sslctx; (void)fd;
15068ed2b524SDag-Erling Smørgrav return NULL;
15078ed2b524SDag-Erling Smørgrav #endif
1508b7579f77SDag-Erling Smørgrav }
1509b7579f77SDag-Erling Smørgrav
outgoing_ssl_fd(void * sslctx,int fd)1510b7579f77SDag-Erling Smørgrav void* outgoing_ssl_fd(void* sslctx, int fd)
1511b7579f77SDag-Erling Smørgrav {
15128ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL
1513b7579f77SDag-Erling Smørgrav SSL* ssl = SSL_new((SSL_CTX*)sslctx);
1514b7579f77SDag-Erling Smørgrav if(!ssl) {
1515b7579f77SDag-Erling Smørgrav log_crypto_err("could not SSL_new");
1516b7579f77SDag-Erling Smørgrav return NULL;
1517b7579f77SDag-Erling Smørgrav }
1518b7579f77SDag-Erling Smørgrav SSL_set_connect_state(ssl);
15190eefd307SCy Schubert (void)SSL_set_mode(ssl, (long)SSL_MODE_AUTO_RETRY);
1520b7579f77SDag-Erling Smørgrav if(!SSL_set_fd(ssl, fd)) {
1521b7579f77SDag-Erling Smørgrav log_crypto_err("could not SSL_set_fd");
1522b7579f77SDag-Erling Smørgrav SSL_free(ssl);
1523b7579f77SDag-Erling Smørgrav return NULL;
1524b7579f77SDag-Erling Smørgrav }
1525b7579f77SDag-Erling Smørgrav return ssl;
15268ed2b524SDag-Erling Smørgrav #else
15278ed2b524SDag-Erling Smørgrav (void)sslctx; (void)fd;
15288ed2b524SDag-Erling Smørgrav return NULL;
15298ed2b524SDag-Erling Smørgrav #endif
1530b7579f77SDag-Erling Smørgrav }
15318ed2b524SDag-Erling Smørgrav
check_auth_name_for_ssl(char * auth_name)153225039b37SCy Schubert int check_auth_name_for_ssl(char* auth_name)
153325039b37SCy Schubert {
153425039b37SCy Schubert if(!auth_name) return 1;
153525039b37SCy Schubert #if defined(HAVE_SSL) && !defined(HAVE_SSL_SET1_HOST) && !defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
153625039b37SCy Schubert log_err("the query has an auth_name %s, but libssl has no call to "
153725039b37SCy Schubert "perform TLS authentication. Remove that name from config "
153825039b37SCy Schubert "or upgrade the ssl crypto library.", auth_name);
153925039b37SCy Schubert return 0;
154025039b37SCy Schubert #else
154125039b37SCy Schubert return 1;
154225039b37SCy Schubert #endif
154325039b37SCy Schubert }
154425039b37SCy Schubert
154525039b37SCy Schubert /** set the authname on an SSL structure, SSL* ssl */
set_auth_name_on_ssl(void * ssl,char * auth_name,int use_sni)154625039b37SCy Schubert int set_auth_name_on_ssl(void* ssl, char* auth_name, int use_sni)
154725039b37SCy Schubert {
154825039b37SCy Schubert if(!auth_name) return 1;
154925039b37SCy Schubert #ifdef HAVE_SSL
155025039b37SCy Schubert if(use_sni) {
155125039b37SCy Schubert (void)SSL_set_tlsext_host_name(ssl, auth_name);
155225039b37SCy Schubert }
155325039b37SCy Schubert #else
155425039b37SCy Schubert (void)ssl;
155525039b37SCy Schubert (void)use_sni;
155625039b37SCy Schubert #endif
155725039b37SCy Schubert #ifdef HAVE_SSL_SET1_HOST
155825039b37SCy Schubert SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL);
155925039b37SCy Schubert /* setting the hostname makes openssl verify the
156025039b37SCy Schubert * host name in the x509 certificate in the
156125039b37SCy Schubert * SSL connection*/
156225039b37SCy Schubert if(!SSL_set1_host(ssl, auth_name)) {
156325039b37SCy Schubert log_err("SSL_set1_host failed");
156425039b37SCy Schubert return 0;
156525039b37SCy Schubert }
156625039b37SCy Schubert #elif defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
156725039b37SCy Schubert /* openssl 1.0.2 has this function that can be used for
156825039b37SCy Schubert * set1_host like verification */
156925039b37SCy Schubert if(auth_name) {
157025039b37SCy Schubert X509_VERIFY_PARAM* param = SSL_get0_param(ssl);
157125039b37SCy Schubert # ifdef X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS
157225039b37SCy Schubert X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
157325039b37SCy Schubert # endif
157425039b37SCy Schubert if(!X509_VERIFY_PARAM_set1_host(param, auth_name, strlen(auth_name))) {
157525039b37SCy Schubert log_err("X509_VERIFY_PARAM_set1_host failed");
157625039b37SCy Schubert return 0;
157725039b37SCy Schubert }
157825039b37SCy Schubert SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL);
157925039b37SCy Schubert }
158025039b37SCy Schubert #else
158125039b37SCy Schubert verbose(VERB_ALGO, "the query has an auth_name, but libssl has no call to perform TLS authentication");
158225039b37SCy Schubert #endif /* HAVE_SSL_SET1_HOST */
158325039b37SCy Schubert return 1;
158425039b37SCy Schubert }
158525039b37SCy Schubert
1586b5663de9SDag-Erling Smørgrav #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L
15878ed2b524SDag-Erling Smørgrav /** global lock list for openssl locks */
15883005e0a3SDag-Erling Smørgrav static lock_basic_type *ub_openssl_locks = NULL;
15898ed2b524SDag-Erling Smørgrav
15908ed2b524SDag-Erling Smørgrav /** callback that gets thread id for openssl */
1591e86b9096SDag-Erling Smørgrav #ifdef HAVE_CRYPTO_THREADID_SET_CALLBACK
1592e86b9096SDag-Erling Smørgrav static void
ub_crypto_id_cb(CRYPTO_THREADID * id)1593e86b9096SDag-Erling Smørgrav ub_crypto_id_cb(CRYPTO_THREADID *id)
1594e86b9096SDag-Erling Smørgrav {
1595e86b9096SDag-Erling Smørgrav CRYPTO_THREADID_set_numeric(id, (unsigned long)log_thread_get());
1596e86b9096SDag-Erling Smørgrav }
1597e86b9096SDag-Erling Smørgrav #else
15988ed2b524SDag-Erling Smørgrav static unsigned long
ub_crypto_id_cb(void)15998ed2b524SDag-Erling Smørgrav ub_crypto_id_cb(void)
16008ed2b524SDag-Erling Smørgrav {
160109a3aaf3SDag-Erling Smørgrav return (unsigned long)log_thread_get();
16028ed2b524SDag-Erling Smørgrav }
1603e86b9096SDag-Erling Smørgrav #endif
16048ed2b524SDag-Erling Smørgrav
16058ed2b524SDag-Erling Smørgrav static void
ub_crypto_lock_cb(int mode,int type,const char * ATTR_UNUSED (file),int ATTR_UNUSED (line))16068ed2b524SDag-Erling Smørgrav ub_crypto_lock_cb(int mode, int type, const char *ATTR_UNUSED(file),
16078ed2b524SDag-Erling Smørgrav int ATTR_UNUSED(line))
16088ed2b524SDag-Erling Smørgrav {
16098ed2b524SDag-Erling Smørgrav if((mode&CRYPTO_LOCK)) {
16108ed2b524SDag-Erling Smørgrav lock_basic_lock(&ub_openssl_locks[type]);
16118ed2b524SDag-Erling Smørgrav } else {
16128ed2b524SDag-Erling Smørgrav lock_basic_unlock(&ub_openssl_locks[type]);
16138ed2b524SDag-Erling Smørgrav }
16148ed2b524SDag-Erling Smørgrav }
16158ed2b524SDag-Erling Smørgrav #endif /* OPENSSL_THREADS */
16168ed2b524SDag-Erling Smørgrav
ub_openssl_lock_init(void)16178ed2b524SDag-Erling Smørgrav int ub_openssl_lock_init(void)
16188ed2b524SDag-Erling Smørgrav {
1619b5663de9SDag-Erling Smørgrav #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L
16208ed2b524SDag-Erling Smørgrav int i;
16213005e0a3SDag-Erling Smørgrav ub_openssl_locks = (lock_basic_type*)reallocarray(
16223005e0a3SDag-Erling Smørgrav NULL, (size_t)CRYPTO_num_locks(), sizeof(lock_basic_type));
16238ed2b524SDag-Erling Smørgrav if(!ub_openssl_locks)
16248ed2b524SDag-Erling Smørgrav return 0;
16258ed2b524SDag-Erling Smørgrav for(i=0; i<CRYPTO_num_locks(); i++) {
16268ed2b524SDag-Erling Smørgrav lock_basic_init(&ub_openssl_locks[i]);
16278ed2b524SDag-Erling Smørgrav }
1628e86b9096SDag-Erling Smørgrav # ifdef HAVE_CRYPTO_THREADID_SET_CALLBACK
1629e86b9096SDag-Erling Smørgrav CRYPTO_THREADID_set_callback(&ub_crypto_id_cb);
1630e86b9096SDag-Erling Smørgrav # else
16318ed2b524SDag-Erling Smørgrav CRYPTO_set_id_callback(&ub_crypto_id_cb);
1632e86b9096SDag-Erling Smørgrav # endif
16338ed2b524SDag-Erling Smørgrav CRYPTO_set_locking_callback(&ub_crypto_lock_cb);
16348ed2b524SDag-Erling Smørgrav #endif /* OPENSSL_THREADS */
16358ed2b524SDag-Erling Smørgrav return 1;
16368ed2b524SDag-Erling Smørgrav }
16378ed2b524SDag-Erling Smørgrav
ub_openssl_lock_delete(void)16388ed2b524SDag-Erling Smørgrav void ub_openssl_lock_delete(void)
16398ed2b524SDag-Erling Smørgrav {
1640b5663de9SDag-Erling Smørgrav #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L
16418ed2b524SDag-Erling Smørgrav int i;
16428ed2b524SDag-Erling Smørgrav if(!ub_openssl_locks)
16438ed2b524SDag-Erling Smørgrav return;
1644e86b9096SDag-Erling Smørgrav # ifdef HAVE_CRYPTO_THREADID_SET_CALLBACK
1645e86b9096SDag-Erling Smørgrav CRYPTO_THREADID_set_callback(NULL);
1646e86b9096SDag-Erling Smørgrav # else
16478ed2b524SDag-Erling Smørgrav CRYPTO_set_id_callback(NULL);
1648e86b9096SDag-Erling Smørgrav # endif
16498ed2b524SDag-Erling Smørgrav CRYPTO_set_locking_callback(NULL);
16508ed2b524SDag-Erling Smørgrav for(i=0; i<CRYPTO_num_locks(); i++) {
16518ed2b524SDag-Erling Smørgrav lock_basic_destroy(&ub_openssl_locks[i]);
16528ed2b524SDag-Erling Smørgrav }
16538ed2b524SDag-Erling Smørgrav free(ub_openssl_locks);
16548ed2b524SDag-Erling Smørgrav #endif /* OPENSSL_THREADS */
16558ed2b524SDag-Erling Smørgrav }
16568ed2b524SDag-Erling Smørgrav
listen_sslctx_setup_ticket_keys(void * sslctx,struct config_strlist * tls_session_ticket_keys)1657e86b9096SDag-Erling Smørgrav int listen_sslctx_setup_ticket_keys(void* sslctx, struct config_strlist* tls_session_ticket_keys) {
1658e86b9096SDag-Erling Smørgrav #ifdef HAVE_SSL
1659e86b9096SDag-Erling Smørgrav size_t s = 1;
1660e86b9096SDag-Erling Smørgrav struct config_strlist* p;
1661e86b9096SDag-Erling Smørgrav struct tls_session_ticket_key *keys;
1662e86b9096SDag-Erling Smørgrav for(p = tls_session_ticket_keys; p; p = p->next) {
1663e86b9096SDag-Erling Smørgrav s++;
1664e86b9096SDag-Erling Smørgrav }
1665e86b9096SDag-Erling Smørgrav keys = calloc(s, sizeof(struct tls_session_ticket_key));
1666091e9e46SCy Schubert if(!keys)
1667091e9e46SCy Schubert return 0;
1668e86b9096SDag-Erling Smørgrav memset(keys, 0, s*sizeof(*keys));
1669e86b9096SDag-Erling Smørgrav ticket_keys = keys;
1670e86b9096SDag-Erling Smørgrav
1671e86b9096SDag-Erling Smørgrav for(p = tls_session_ticket_keys; p; p = p->next) {
1672e86b9096SDag-Erling Smørgrav size_t n;
1673091e9e46SCy Schubert unsigned char *data;
1674091e9e46SCy Schubert FILE *f;
1675091e9e46SCy Schubert
1676091e9e46SCy Schubert data = (unsigned char *)malloc(80);
1677091e9e46SCy Schubert if(!data)
1678091e9e46SCy Schubert return 0;
1679091e9e46SCy Schubert
168025039b37SCy Schubert f = fopen(p->str, "rb");
1681e86b9096SDag-Erling Smørgrav if(!f) {
1682e86b9096SDag-Erling Smørgrav log_err("could not read tls-session-ticket-key %s: %s", p->str, strerror(errno));
1683e86b9096SDag-Erling Smørgrav free(data);
1684e86b9096SDag-Erling Smørgrav return 0;
1685e86b9096SDag-Erling Smørgrav }
1686e86b9096SDag-Erling Smørgrav n = fread(data, 1, 80, f);
1687e86b9096SDag-Erling Smørgrav fclose(f);
1688e86b9096SDag-Erling Smørgrav
1689e86b9096SDag-Erling Smørgrav if(n != 80) {
1690e86b9096SDag-Erling Smørgrav log_err("tls-session-ticket-key %s is %d bytes, must be 80 bytes", p->str, (int)n);
1691e86b9096SDag-Erling Smørgrav free(data);
1692e86b9096SDag-Erling Smørgrav return 0;
1693e86b9096SDag-Erling Smørgrav }
1694e86b9096SDag-Erling Smørgrav verbose(VERB_OPS, "read tls-session-ticket-key: %s", p->str);
1695e86b9096SDag-Erling Smørgrav
1696e86b9096SDag-Erling Smørgrav keys->key_name = data;
1697e86b9096SDag-Erling Smørgrav keys->aes_key = data + 16;
1698e86b9096SDag-Erling Smørgrav keys->hmac_key = data + 48;
1699e86b9096SDag-Erling Smørgrav keys++;
1700e86b9096SDag-Erling Smørgrav }
1701e86b9096SDag-Erling Smørgrav /* terminate array with NULL key name entry */
1702e86b9096SDag-Erling Smørgrav keys->key_name = NULL;
170325039b37SCy Schubert # ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
170425039b37SCy Schubert if(SSL_CTX_set_tlsext_ticket_key_evp_cb(sslctx, tls_session_ticket_key_cb) == 0) {
170525039b37SCy Schubert log_err("no support for TLS session ticket");
170625039b37SCy Schubert return 0;
170725039b37SCy Schubert }
170825039b37SCy Schubert # else
1709e86b9096SDag-Erling Smørgrav if(SSL_CTX_set_tlsext_ticket_key_cb(sslctx, tls_session_ticket_key_cb) == 0) {
1710e86b9096SDag-Erling Smørgrav log_err("no support for TLS session ticket");
1711e86b9096SDag-Erling Smørgrav return 0;
1712e86b9096SDag-Erling Smørgrav }
171325039b37SCy Schubert # endif
1714e86b9096SDag-Erling Smørgrav return 1;
1715e86b9096SDag-Erling Smørgrav #else
1716e86b9096SDag-Erling Smørgrav (void)sslctx;
1717e86b9096SDag-Erling Smørgrav (void)tls_session_ticket_keys;
1718e86b9096SDag-Erling Smørgrav return 0;
1719e86b9096SDag-Erling Smørgrav #endif
1720e86b9096SDag-Erling Smørgrav
1721e86b9096SDag-Erling Smørgrav }
1722e86b9096SDag-Erling Smørgrav
172325039b37SCy Schubert #ifdef HAVE_SSL
tls_session_ticket_key_cb(SSL * ATTR_UNUSED (sslctx),unsigned char * key_name,unsigned char * iv,EVP_CIPHER_CTX * evp_sctx,EVP_MAC_CTX * hmac_ctx,int enc)172425039b37SCy Schubert int tls_session_ticket_key_cb(SSL *ATTR_UNUSED(sslctx), unsigned char* key_name,
172525039b37SCy Schubert unsigned char* iv, EVP_CIPHER_CTX *evp_sctx,
172625039b37SCy Schubert #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
172725039b37SCy Schubert EVP_MAC_CTX *hmac_ctx,
172825039b37SCy Schubert #else
172925039b37SCy Schubert HMAC_CTX* hmac_ctx,
173025039b37SCy Schubert #endif
173125039b37SCy Schubert int enc)
1732e86b9096SDag-Erling Smørgrav {
1733e86b9096SDag-Erling Smørgrav #ifdef HAVE_SSL
173425039b37SCy Schubert # ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
173525039b37SCy Schubert OSSL_PARAM params[3];
173625039b37SCy Schubert # else
1737e86b9096SDag-Erling Smørgrav const EVP_MD *digest;
173825039b37SCy Schubert # endif
1739e86b9096SDag-Erling Smørgrav const EVP_CIPHER *cipher;
1740e86b9096SDag-Erling Smørgrav int evp_cipher_length;
174125039b37SCy Schubert # ifndef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
1742e86b9096SDag-Erling Smørgrav digest = EVP_sha256();
174325039b37SCy Schubert # endif
1744e86b9096SDag-Erling Smørgrav cipher = EVP_aes_256_cbc();
1745e86b9096SDag-Erling Smørgrav evp_cipher_length = EVP_CIPHER_iv_length(cipher);
1746e86b9096SDag-Erling Smørgrav if( enc == 1 ) {
1747e86b9096SDag-Erling Smørgrav /* encrypt */
1748e86b9096SDag-Erling Smørgrav verbose(VERB_CLIENT, "start session encrypt");
1749e86b9096SDag-Erling Smørgrav memcpy(key_name, ticket_keys->key_name, 16);
1750e86b9096SDag-Erling Smørgrav if (RAND_bytes(iv, evp_cipher_length) != 1) {
1751e86b9096SDag-Erling Smørgrav verbose(VERB_CLIENT, "RAND_bytes failed");
1752e86b9096SDag-Erling Smørgrav return -1;
1753e86b9096SDag-Erling Smørgrav }
1754e86b9096SDag-Erling Smørgrav if (EVP_EncryptInit_ex(evp_sctx, cipher, NULL, ticket_keys->aes_key, iv) != 1) {
1755e86b9096SDag-Erling Smørgrav verbose(VERB_CLIENT, "EVP_EncryptInit_ex failed");
1756e86b9096SDag-Erling Smørgrav return -1;
1757e86b9096SDag-Erling Smørgrav }
175825039b37SCy Schubert #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
175925039b37SCy Schubert params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
176025039b37SCy Schubert ticket_keys->hmac_key, 32);
176125039b37SCy Schubert params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
176225039b37SCy Schubert "sha256", 0);
176325039b37SCy Schubert params[2] = OSSL_PARAM_construct_end();
1764c0caa2e2SCy Schubert #ifdef HAVE_EVP_MAC_CTX_SET_PARAMS
1765c0caa2e2SCy Schubert EVP_MAC_CTX_set_params(hmac_ctx, params);
1766c0caa2e2SCy Schubert #else
176725039b37SCy Schubert EVP_MAC_set_ctx_params(hmac_ctx, params);
1768c0caa2e2SCy Schubert #endif
176925039b37SCy Schubert #elif !defined(HMAC_INIT_EX_RETURNS_VOID)
1770e86b9096SDag-Erling Smørgrav if (HMAC_Init_ex(hmac_ctx, ticket_keys->hmac_key, 32, digest, NULL) != 1) {
1771e86b9096SDag-Erling Smørgrav verbose(VERB_CLIENT, "HMAC_Init_ex failed");
1772e86b9096SDag-Erling Smørgrav return -1;
1773e86b9096SDag-Erling Smørgrav }
17740eefd307SCy Schubert #else
17750eefd307SCy Schubert HMAC_Init_ex(hmac_ctx, ticket_keys->hmac_key, 32, digest, NULL);
17760eefd307SCy Schubert #endif
1777e86b9096SDag-Erling Smørgrav return 1;
1778e86b9096SDag-Erling Smørgrav } else if (enc == 0) {
1779e86b9096SDag-Erling Smørgrav /* decrypt */
1780e86b9096SDag-Erling Smørgrav struct tls_session_ticket_key *key;
1781e86b9096SDag-Erling Smørgrav verbose(VERB_CLIENT, "start session decrypt");
1782e86b9096SDag-Erling Smørgrav for(key = ticket_keys; key->key_name != NULL; key++) {
1783e86b9096SDag-Erling Smørgrav if (!memcmp(key_name, key->key_name, 16)) {
1784e86b9096SDag-Erling Smørgrav verbose(VERB_CLIENT, "Found session_key");
1785e86b9096SDag-Erling Smørgrav break;
1786e86b9096SDag-Erling Smørgrav }
1787e86b9096SDag-Erling Smørgrav }
1788e86b9096SDag-Erling Smørgrav if(key->key_name == NULL) {
1789e86b9096SDag-Erling Smørgrav verbose(VERB_CLIENT, "Not found session_key");
1790e86b9096SDag-Erling Smørgrav return 0;
1791e86b9096SDag-Erling Smørgrav }
1792e86b9096SDag-Erling Smørgrav
179325039b37SCy Schubert #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
179425039b37SCy Schubert params[0] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
179525039b37SCy Schubert key->hmac_key, 32);
179625039b37SCy Schubert params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
179725039b37SCy Schubert "sha256", 0);
179825039b37SCy Schubert params[2] = OSSL_PARAM_construct_end();
1799c0caa2e2SCy Schubert #ifdef HAVE_EVP_MAC_CTX_SET_PARAMS
1800c0caa2e2SCy Schubert EVP_MAC_CTX_set_params(hmac_ctx, params);
1801c0caa2e2SCy Schubert #else
180225039b37SCy Schubert EVP_MAC_set_ctx_params(hmac_ctx, params);
1803c0caa2e2SCy Schubert #endif
180425039b37SCy Schubert #elif !defined(HMAC_INIT_EX_RETURNS_VOID)
1805e86b9096SDag-Erling Smørgrav if (HMAC_Init_ex(hmac_ctx, key->hmac_key, 32, digest, NULL) != 1) {
1806e86b9096SDag-Erling Smørgrav verbose(VERB_CLIENT, "HMAC_Init_ex failed");
1807e86b9096SDag-Erling Smørgrav return -1;
1808e86b9096SDag-Erling Smørgrav }
18090eefd307SCy Schubert #else
18100eefd307SCy Schubert HMAC_Init_ex(hmac_ctx, key->hmac_key, 32, digest, NULL);
18110eefd307SCy Schubert #endif
1812e86b9096SDag-Erling Smørgrav if (EVP_DecryptInit_ex(evp_sctx, cipher, NULL, key->aes_key, iv) != 1) {
1813e86b9096SDag-Erling Smørgrav log_err("EVP_DecryptInit_ex failed");
1814e86b9096SDag-Erling Smørgrav return -1;
1815e86b9096SDag-Erling Smørgrav }
1816e86b9096SDag-Erling Smørgrav
1817e86b9096SDag-Erling Smørgrav return (key == ticket_keys) ? 1 : 2;
1818e86b9096SDag-Erling Smørgrav }
1819e86b9096SDag-Erling Smørgrav return -1;
1820e86b9096SDag-Erling Smørgrav #else
1821e86b9096SDag-Erling Smørgrav (void)key_name;
1822e86b9096SDag-Erling Smørgrav (void)iv;
1823e86b9096SDag-Erling Smørgrav (void)evp_sctx;
1824e86b9096SDag-Erling Smørgrav (void)hmac_ctx;
1825e86b9096SDag-Erling Smørgrav (void)enc;
1826e86b9096SDag-Erling Smørgrav return 0;
1827e86b9096SDag-Erling Smørgrav #endif
1828e86b9096SDag-Erling Smørgrav }
182925039b37SCy Schubert #endif /* HAVE_SSL */
1830e86b9096SDag-Erling Smørgrav
1831e86b9096SDag-Erling Smørgrav void
listen_sslctx_delete_ticket_keys(void)1832e86b9096SDag-Erling Smørgrav listen_sslctx_delete_ticket_keys(void)
1833e86b9096SDag-Erling Smørgrav {
1834e86b9096SDag-Erling Smørgrav struct tls_session_ticket_key *key;
1835e86b9096SDag-Erling Smørgrav if(!ticket_keys) return;
1836e86b9096SDag-Erling Smørgrav for(key = ticket_keys; key->key_name != NULL; key++) {
1837e86b9096SDag-Erling Smørgrav /* wipe key data from memory*/
1838e86b9096SDag-Erling Smørgrav #ifdef HAVE_EXPLICIT_BZERO
1839e86b9096SDag-Erling Smørgrav explicit_bzero(key->key_name, 80);
1840e86b9096SDag-Erling Smørgrav #else
1841e86b9096SDag-Erling Smørgrav memset(key->key_name, 0xdd, 80);
1842e86b9096SDag-Erling Smørgrav #endif
1843e86b9096SDag-Erling Smørgrav free(key->key_name);
1844e86b9096SDag-Erling Smørgrav }
1845e86b9096SDag-Erling Smørgrav free(ticket_keys);
1846e86b9096SDag-Erling Smørgrav ticket_keys = NULL;
1847e86b9096SDag-Erling Smørgrav }
1848c0caa2e2SCy Schubert
1849c0caa2e2SCy Schubert # ifndef USE_WINSOCK
1850c0caa2e2SCy Schubert char*
sock_strerror(int errn)1851c0caa2e2SCy Schubert sock_strerror(int errn)
1852c0caa2e2SCy Schubert {
1853c0caa2e2SCy Schubert return strerror(errn);
1854c0caa2e2SCy Schubert }
1855c0caa2e2SCy Schubert
1856c0caa2e2SCy Schubert void
sock_close(int socket)1857c0caa2e2SCy Schubert sock_close(int socket)
1858c0caa2e2SCy Schubert {
1859c0caa2e2SCy Schubert close(socket);
1860c0caa2e2SCy Schubert }
1861c0caa2e2SCy Schubert
1862c0caa2e2SCy Schubert # else
1863c0caa2e2SCy Schubert char*
sock_strerror(int ATTR_UNUSED (errn))1864c0caa2e2SCy Schubert sock_strerror(int ATTR_UNUSED(errn))
1865c0caa2e2SCy Schubert {
1866c0caa2e2SCy Schubert return wsa_strerror(WSAGetLastError());
1867c0caa2e2SCy Schubert }
1868c0caa2e2SCy Schubert
1869c0caa2e2SCy Schubert void
sock_close(int socket)1870c0caa2e2SCy Schubert sock_close(int socket)
1871c0caa2e2SCy Schubert {
1872c0caa2e2SCy Schubert closesocket(socket);
1873c0caa2e2SCy Schubert }
1874c0caa2e2SCy Schubert # endif /* USE_WINSOCK */
1875*56850988SCy Schubert
1876*56850988SCy Schubert ssize_t
hex_ntop(uint8_t const * src,size_t srclength,char * target,size_t targsize)1877*56850988SCy Schubert hex_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize)
1878*56850988SCy Schubert {
1879*56850988SCy Schubert static char hexdigits[] = {
1880*56850988SCy Schubert '0', '1', '2', '3', '4', '5', '6', '7',
1881*56850988SCy Schubert '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
1882*56850988SCy Schubert };
1883*56850988SCy Schubert size_t i;
1884*56850988SCy Schubert
1885*56850988SCy Schubert if (targsize < srclength * 2 + 1) {
1886*56850988SCy Schubert return -1;
1887*56850988SCy Schubert }
1888*56850988SCy Schubert
1889*56850988SCy Schubert for (i = 0; i < srclength; ++i) {
1890*56850988SCy Schubert *target++ = hexdigits[src[i] >> 4U];
1891*56850988SCy Schubert *target++ = hexdigits[src[i] & 0xfU];
1892*56850988SCy Schubert }
1893*56850988SCy Schubert *target = '\0';
1894*56850988SCy Schubert return 2 * srclength;
1895*56850988SCy Schubert }
1896*56850988SCy Schubert
1897*56850988SCy Schubert ssize_t
hex_pton(const char * src,uint8_t * target,size_t targsize)1898*56850988SCy Schubert hex_pton(const char* src, uint8_t* target, size_t targsize)
1899*56850988SCy Schubert {
1900*56850988SCy Schubert uint8_t *t = target;
1901*56850988SCy Schubert if(strlen(src) % 2 != 0 || strlen(src)/2 > targsize) {
1902*56850988SCy Schubert return -1;
1903*56850988SCy Schubert }
1904*56850988SCy Schubert while(*src) {
1905*56850988SCy Schubert if(!isxdigit((unsigned char)src[0]) ||
1906*56850988SCy Schubert !isxdigit((unsigned char)src[1]))
1907*56850988SCy Schubert return -1;
1908*56850988SCy Schubert *t++ = sldns_hexdigit_to_int(src[0]) * 16 +
1909*56850988SCy Schubert sldns_hexdigit_to_int(src[1]) ;
1910*56850988SCy Schubert src += 2;
1911*56850988SCy Schubert }
1912*56850988SCy Schubert return t-target;
1913*56850988SCy Schubert }
1914