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" 41b7579f77SDag-Erling Smørgrav #include "util/net_help.h" 42b7579f77SDag-Erling Smørgrav #include "util/log.h" 43b7579f77SDag-Erling Smørgrav #include "util/data/dname.h" 44b7579f77SDag-Erling Smørgrav #include "util/module.h" 45b7579f77SDag-Erling Smørgrav #include "util/regional.h" 4609a3aaf3SDag-Erling Smørgrav #include "sldns/parseutil.h" 4709a3aaf3SDag-Erling Smørgrav #include "sldns/wire2str.h" 48b7579f77SDag-Erling Smørgrav #include <fcntl.h> 498ed2b524SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_SSL_H 50b7579f77SDag-Erling Smørgrav #include <openssl/ssl.h> 518ed2b524SDag-Erling Smørgrav #endif 528ed2b524SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_ERR_H 53b7579f77SDag-Erling Smørgrav #include <openssl/err.h> 548ed2b524SDag-Erling Smørgrav #endif 553bd4df0aSDag-Erling Smørgrav #ifdef USE_WINSOCK 563bd4df0aSDag-Erling Smørgrav #include <wincrypt.h> 573bd4df0aSDag-Erling Smørgrav #endif 58b7579f77SDag-Erling Smørgrav 59b7579f77SDag-Erling Smørgrav /** max length of an IP address (the address portion) that we allow */ 60b7579f77SDag-Erling Smørgrav #define MAX_ADDR_STRLEN 128 /* characters */ 61b7579f77SDag-Erling Smørgrav /** default value for EDNS ADVERTISED size */ 62b7579f77SDag-Erling Smørgrav uint16_t EDNS_ADVERTISED_SIZE = 4096; 63b7579f77SDag-Erling Smørgrav 64b7579f77SDag-Erling Smørgrav /** minimal responses when positive answer: default is no */ 65b7579f77SDag-Erling Smørgrav int MINIMAL_RESPONSES = 0; 66b7579f77SDag-Erling Smørgrav 67b7579f77SDag-Erling Smørgrav /** rrset order roundrobin: default is no */ 68b7579f77SDag-Erling Smørgrav int RRSET_ROUNDROBIN = 0; 69b7579f77SDag-Erling Smørgrav 70b7579f77SDag-Erling Smørgrav /* returns true is string addr is an ip6 specced address */ 71b7579f77SDag-Erling Smørgrav int 72b7579f77SDag-Erling Smørgrav str_is_ip6(const char* str) 73b7579f77SDag-Erling Smørgrav { 74b7579f77SDag-Erling Smørgrav if(strchr(str, ':')) 75b7579f77SDag-Erling Smørgrav return 1; 76b7579f77SDag-Erling Smørgrav else return 0; 77b7579f77SDag-Erling Smørgrav } 78b7579f77SDag-Erling Smørgrav 79b7579f77SDag-Erling Smørgrav int 80b7579f77SDag-Erling Smørgrav fd_set_nonblock(int s) 81b7579f77SDag-Erling Smørgrav { 82b7579f77SDag-Erling Smørgrav #ifdef HAVE_FCNTL 83b7579f77SDag-Erling Smørgrav int flag; 84b7579f77SDag-Erling Smørgrav if((flag = fcntl(s, F_GETFL)) == -1) { 85b7579f77SDag-Erling Smørgrav log_err("can't fcntl F_GETFL: %s", strerror(errno)); 86b7579f77SDag-Erling Smørgrav flag = 0; 87b7579f77SDag-Erling Smørgrav } 88b7579f77SDag-Erling Smørgrav flag |= O_NONBLOCK; 89b7579f77SDag-Erling Smørgrav if(fcntl(s, F_SETFL, flag) == -1) { 90b7579f77SDag-Erling Smørgrav log_err("can't fcntl F_SETFL: %s", strerror(errno)); 91b7579f77SDag-Erling Smørgrav return 0; 92b7579f77SDag-Erling Smørgrav } 93b7579f77SDag-Erling Smørgrav #elif defined(HAVE_IOCTLSOCKET) 94b7579f77SDag-Erling Smørgrav unsigned long on = 1; 95b7579f77SDag-Erling Smørgrav if(ioctlsocket(s, FIONBIO, &on) != 0) { 96b7579f77SDag-Erling Smørgrav log_err("can't ioctlsocket FIONBIO on: %s", 97b7579f77SDag-Erling Smørgrav wsa_strerror(WSAGetLastError())); 98b7579f77SDag-Erling Smørgrav } 99b7579f77SDag-Erling Smørgrav #endif 100b7579f77SDag-Erling Smørgrav return 1; 101b7579f77SDag-Erling Smørgrav } 102b7579f77SDag-Erling Smørgrav 103b7579f77SDag-Erling Smørgrav int 104b7579f77SDag-Erling Smørgrav fd_set_block(int s) 105b7579f77SDag-Erling Smørgrav { 106b7579f77SDag-Erling Smørgrav #ifdef HAVE_FCNTL 107b7579f77SDag-Erling Smørgrav int flag; 108b7579f77SDag-Erling Smørgrav if((flag = fcntl(s, F_GETFL)) == -1) { 109b7579f77SDag-Erling Smørgrav log_err("cannot fcntl F_GETFL: %s", strerror(errno)); 110b7579f77SDag-Erling Smørgrav flag = 0; 111b7579f77SDag-Erling Smørgrav } 112b7579f77SDag-Erling Smørgrav flag &= ~O_NONBLOCK; 113b7579f77SDag-Erling Smørgrav if(fcntl(s, F_SETFL, flag) == -1) { 114b7579f77SDag-Erling Smørgrav log_err("cannot fcntl F_SETFL: %s", strerror(errno)); 115b7579f77SDag-Erling Smørgrav return 0; 116b7579f77SDag-Erling Smørgrav } 117b7579f77SDag-Erling Smørgrav #elif defined(HAVE_IOCTLSOCKET) 118b7579f77SDag-Erling Smørgrav unsigned long off = 0; 119b7579f77SDag-Erling Smørgrav if(ioctlsocket(s, FIONBIO, &off) != 0) { 120971980c3SDag-Erling Smørgrav if(WSAGetLastError() != WSAEINVAL || verbosity >= 4) 121b7579f77SDag-Erling Smørgrav log_err("can't ioctlsocket FIONBIO off: %s", 122b7579f77SDag-Erling Smørgrav wsa_strerror(WSAGetLastError())); 123b7579f77SDag-Erling Smørgrav } 124b7579f77SDag-Erling Smørgrav #endif 125b7579f77SDag-Erling Smørgrav return 1; 126b7579f77SDag-Erling Smørgrav } 127b7579f77SDag-Erling Smørgrav 128b7579f77SDag-Erling Smørgrav int 129b7579f77SDag-Erling Smørgrav is_pow2(size_t num) 130b7579f77SDag-Erling Smørgrav { 131b7579f77SDag-Erling Smørgrav if(num == 0) return 1; 132b7579f77SDag-Erling Smørgrav return (num & (num-1)) == 0; 133b7579f77SDag-Erling Smørgrav } 134b7579f77SDag-Erling Smørgrav 135b7579f77SDag-Erling Smørgrav void* 136b7579f77SDag-Erling Smørgrav memdup(void* data, size_t len) 137b7579f77SDag-Erling Smørgrav { 138b7579f77SDag-Erling Smørgrav void* d; 139b7579f77SDag-Erling Smørgrav if(!data) return NULL; 140b7579f77SDag-Erling Smørgrav if(len == 0) return NULL; 141b7579f77SDag-Erling Smørgrav d = malloc(len); 142b7579f77SDag-Erling Smørgrav if(!d) return NULL; 143b7579f77SDag-Erling Smørgrav memcpy(d, data, len); 144b7579f77SDag-Erling Smørgrav return d; 145b7579f77SDag-Erling Smørgrav } 146b7579f77SDag-Erling Smørgrav 147b7579f77SDag-Erling Smørgrav void 148b7579f77SDag-Erling Smørgrav log_addr(enum verbosity_value v, const char* str, 149b7579f77SDag-Erling Smørgrav struct sockaddr_storage* addr, socklen_t addrlen) 150b7579f77SDag-Erling Smørgrav { 151b7579f77SDag-Erling Smørgrav uint16_t port; 152b7579f77SDag-Erling Smørgrav const char* family = "unknown"; 153b7579f77SDag-Erling Smørgrav char dest[100]; 154b7579f77SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family; 155b7579f77SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 156b7579f77SDag-Erling Smørgrav if(verbosity < v) 157b7579f77SDag-Erling Smørgrav return; 158b7579f77SDag-Erling Smørgrav switch(af) { 159b7579f77SDag-Erling Smørgrav case AF_INET: family="ip4"; break; 160b7579f77SDag-Erling Smørgrav case AF_INET6: family="ip6"; 161b7579f77SDag-Erling Smørgrav sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; 162b7579f77SDag-Erling Smørgrav break; 1636480faa8SDag-Erling Smørgrav case AF_LOCAL: 1646480faa8SDag-Erling Smørgrav dest[0]=0; 1656480faa8SDag-Erling Smørgrav (void)inet_ntop(af, sinaddr, dest, 1666480faa8SDag-Erling Smørgrav (socklen_t)sizeof(dest)); 1676480faa8SDag-Erling Smørgrav verbose(v, "%s local %s", str, dest); 1686480faa8SDag-Erling Smørgrav return; /* do not continue and try to get port */ 169b7579f77SDag-Erling Smørgrav default: break; 170b7579f77SDag-Erling Smørgrav } 171b7579f77SDag-Erling Smørgrav if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { 17217d15b25SDag-Erling Smørgrav (void)strlcpy(dest, "(inet_ntop error)", sizeof(dest)); 173b7579f77SDag-Erling Smørgrav } 174b7579f77SDag-Erling Smørgrav dest[sizeof(dest)-1] = 0; 175b7579f77SDag-Erling Smørgrav port = ntohs(((struct sockaddr_in*)addr)->sin_port); 176b7579f77SDag-Erling Smørgrav if(verbosity >= 4) 177b7579f77SDag-Erling Smørgrav verbose(v, "%s %s %s port %d (len %d)", str, family, dest, 178b7579f77SDag-Erling Smørgrav (int)port, (int)addrlen); 179b7579f77SDag-Erling Smørgrav else verbose(v, "%s %s port %d", str, dest, (int)port); 180b7579f77SDag-Erling Smørgrav } 181b7579f77SDag-Erling Smørgrav 182b7579f77SDag-Erling Smørgrav int 183b7579f77SDag-Erling Smørgrav extstrtoaddr(const char* str, struct sockaddr_storage* addr, 184b7579f77SDag-Erling Smørgrav socklen_t* addrlen) 185b7579f77SDag-Erling Smørgrav { 186b7579f77SDag-Erling Smørgrav char* s; 187b7579f77SDag-Erling Smørgrav int port = UNBOUND_DNS_PORT; 188b7579f77SDag-Erling Smørgrav if((s=strchr(str, '@'))) { 189b7579f77SDag-Erling Smørgrav char buf[MAX_ADDR_STRLEN]; 190b7579f77SDag-Erling Smørgrav if(s-str >= MAX_ADDR_STRLEN) { 191b7579f77SDag-Erling Smørgrav return 0; 192b7579f77SDag-Erling Smørgrav } 19317d15b25SDag-Erling Smørgrav (void)strlcpy(buf, str, sizeof(buf)); 194b7579f77SDag-Erling Smørgrav buf[s-str] = 0; 195b7579f77SDag-Erling Smørgrav port = atoi(s+1); 196b7579f77SDag-Erling Smørgrav if(port == 0 && strcmp(s+1,"0")!=0) { 197b7579f77SDag-Erling Smørgrav return 0; 198b7579f77SDag-Erling Smørgrav } 199b7579f77SDag-Erling Smørgrav return ipstrtoaddr(buf, port, addr, addrlen); 200b7579f77SDag-Erling Smørgrav } 201b7579f77SDag-Erling Smørgrav return ipstrtoaddr(str, port, addr, addrlen); 202b7579f77SDag-Erling Smørgrav } 203b7579f77SDag-Erling Smørgrav 204b7579f77SDag-Erling Smørgrav 205b7579f77SDag-Erling Smørgrav int 206b7579f77SDag-Erling Smørgrav ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr, 207b7579f77SDag-Erling Smørgrav socklen_t* addrlen) 208b7579f77SDag-Erling Smørgrav { 209b7579f77SDag-Erling Smørgrav uint16_t p; 210b7579f77SDag-Erling Smørgrav if(!ip) return 0; 211b7579f77SDag-Erling Smørgrav p = (uint16_t) port; 212b7579f77SDag-Erling Smørgrav if(str_is_ip6(ip)) { 213b7579f77SDag-Erling Smørgrav char buf[MAX_ADDR_STRLEN]; 214b7579f77SDag-Erling Smørgrav char* s; 215b7579f77SDag-Erling Smørgrav struct sockaddr_in6* sa = (struct sockaddr_in6*)addr; 216b7579f77SDag-Erling Smørgrav *addrlen = (socklen_t)sizeof(struct sockaddr_in6); 217b7579f77SDag-Erling Smørgrav memset(sa, 0, *addrlen); 218b7579f77SDag-Erling Smørgrav sa->sin6_family = AF_INET6; 219b7579f77SDag-Erling Smørgrav sa->sin6_port = (in_port_t)htons(p); 220b7579f77SDag-Erling Smørgrav if((s=strchr(ip, '%'))) { /* ip6%interface, rfc 4007 */ 221b7579f77SDag-Erling Smørgrav if(s-ip >= MAX_ADDR_STRLEN) 222b7579f77SDag-Erling Smørgrav return 0; 22317d15b25SDag-Erling Smørgrav (void)strlcpy(buf, ip, sizeof(buf)); 224b7579f77SDag-Erling Smørgrav buf[s-ip]=0; 225b7579f77SDag-Erling Smørgrav sa->sin6_scope_id = (uint32_t)atoi(s+1); 226b7579f77SDag-Erling Smørgrav ip = buf; 227b7579f77SDag-Erling Smørgrav } 228b7579f77SDag-Erling Smørgrav if(inet_pton((int)sa->sin6_family, ip, &sa->sin6_addr) <= 0) { 229b7579f77SDag-Erling Smørgrav return 0; 230b7579f77SDag-Erling Smørgrav } 231b7579f77SDag-Erling Smørgrav } else { /* ip4 */ 232b7579f77SDag-Erling Smørgrav struct sockaddr_in* sa = (struct sockaddr_in*)addr; 233b7579f77SDag-Erling Smørgrav *addrlen = (socklen_t)sizeof(struct sockaddr_in); 234b7579f77SDag-Erling Smørgrav memset(sa, 0, *addrlen); 235b7579f77SDag-Erling Smørgrav sa->sin_family = AF_INET; 236b7579f77SDag-Erling Smørgrav sa->sin_port = (in_port_t)htons(p); 237b7579f77SDag-Erling Smørgrav if(inet_pton((int)sa->sin_family, ip, &sa->sin_addr) <= 0) { 238b7579f77SDag-Erling Smørgrav return 0; 239b7579f77SDag-Erling Smørgrav } 240b7579f77SDag-Erling Smørgrav } 241b7579f77SDag-Erling Smørgrav return 1; 242b7579f77SDag-Erling Smørgrav } 243b7579f77SDag-Erling Smørgrav 244b7579f77SDag-Erling Smørgrav int netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr, 245b7579f77SDag-Erling Smørgrav socklen_t* addrlen, int* net) 246b7579f77SDag-Erling Smørgrav { 2470fb34990SDag-Erling Smørgrav char buf[64]; 2480fb34990SDag-Erling Smørgrav char* s; 249b7579f77SDag-Erling Smørgrav *net = (str_is_ip6(str)?128:32); 250b7579f77SDag-Erling Smørgrav if((s=strchr(str, '/'))) { 251b7579f77SDag-Erling Smørgrav if(atoi(s+1) > *net) { 252b7579f77SDag-Erling Smørgrav log_err("netblock too large: %s", str); 253b7579f77SDag-Erling Smørgrav return 0; 254b7579f77SDag-Erling Smørgrav } 255b7579f77SDag-Erling Smørgrav *net = atoi(s+1); 256b7579f77SDag-Erling Smørgrav if(*net == 0 && strcmp(s+1, "0") != 0) { 257b7579f77SDag-Erling Smørgrav log_err("cannot parse netblock: '%s'", str); 258b7579f77SDag-Erling Smørgrav return 0; 259b7579f77SDag-Erling Smørgrav } 2600fb34990SDag-Erling Smørgrav strlcpy(buf, str, sizeof(buf)); 2610fb34990SDag-Erling Smørgrav s = strchr(buf, '/'); 2620fb34990SDag-Erling Smørgrav if(s) *s = 0; 2630fb34990SDag-Erling Smørgrav s = buf; 264b7579f77SDag-Erling Smørgrav } 265b7579f77SDag-Erling Smørgrav if(!ipstrtoaddr(s?s:str, port, addr, addrlen)) { 266b7579f77SDag-Erling Smørgrav log_err("cannot parse ip address: '%s'", str); 267b7579f77SDag-Erling Smørgrav return 0; 268b7579f77SDag-Erling Smørgrav } 269b7579f77SDag-Erling Smørgrav if(s) { 270b7579f77SDag-Erling Smørgrav addr_mask(addr, *addrlen, *net); 271b7579f77SDag-Erling Smørgrav } 272b7579f77SDag-Erling Smørgrav return 1; 273b7579f77SDag-Erling Smørgrav } 274b7579f77SDag-Erling Smørgrav 2750fb34990SDag-Erling Smørgrav int authextstrtoaddr(char* str, struct sockaddr_storage* addr, 2760fb34990SDag-Erling Smørgrav socklen_t* addrlen, char** auth_name) 2770fb34990SDag-Erling Smørgrav { 2780fb34990SDag-Erling Smørgrav char* s; 2790fb34990SDag-Erling Smørgrav int port = UNBOUND_DNS_PORT; 2800fb34990SDag-Erling Smørgrav if((s=strchr(str, '@'))) { 2810fb34990SDag-Erling Smørgrav char buf[MAX_ADDR_STRLEN]; 2820fb34990SDag-Erling Smørgrav size_t len = (size_t)(s-str); 2830fb34990SDag-Erling Smørgrav char* hash = strchr(s+1, '#'); 2840fb34990SDag-Erling Smørgrav if(hash) { 2850fb34990SDag-Erling Smørgrav *auth_name = hash+1; 2860fb34990SDag-Erling Smørgrav } else { 2870fb34990SDag-Erling Smørgrav *auth_name = NULL; 2880fb34990SDag-Erling Smørgrav } 2890fb34990SDag-Erling Smørgrav if(len >= MAX_ADDR_STRLEN) { 2900fb34990SDag-Erling Smørgrav return 0; 2910fb34990SDag-Erling Smørgrav } 2920fb34990SDag-Erling Smørgrav (void)strlcpy(buf, str, sizeof(buf)); 2930fb34990SDag-Erling Smørgrav buf[len] = 0; 2940fb34990SDag-Erling Smørgrav port = atoi(s+1); 2950fb34990SDag-Erling Smørgrav if(port == 0) { 2960fb34990SDag-Erling Smørgrav if(!hash && strcmp(s+1,"0")!=0) 2970fb34990SDag-Erling Smørgrav return 0; 2980fb34990SDag-Erling Smørgrav if(hash && strncmp(s+1,"0#",2)!=0) 2990fb34990SDag-Erling Smørgrav return 0; 3000fb34990SDag-Erling Smørgrav } 3010fb34990SDag-Erling Smørgrav return ipstrtoaddr(buf, port, addr, addrlen); 3020fb34990SDag-Erling Smørgrav } 3030fb34990SDag-Erling Smørgrav if((s=strchr(str, '#'))) { 3040fb34990SDag-Erling Smørgrav char buf[MAX_ADDR_STRLEN]; 3050fb34990SDag-Erling Smørgrav size_t len = (size_t)(s-str); 3060fb34990SDag-Erling Smørgrav if(len >= MAX_ADDR_STRLEN) { 3070fb34990SDag-Erling Smørgrav return 0; 3080fb34990SDag-Erling Smørgrav } 3090fb34990SDag-Erling Smørgrav (void)strlcpy(buf, str, sizeof(buf)); 3100fb34990SDag-Erling Smørgrav buf[len] = 0; 3110fb34990SDag-Erling Smørgrav port = UNBOUND_DNS_OVER_TLS_PORT; 3120fb34990SDag-Erling Smørgrav *auth_name = s+1; 3130fb34990SDag-Erling Smørgrav return ipstrtoaddr(buf, port, addr, addrlen); 3140fb34990SDag-Erling Smørgrav } 3150fb34990SDag-Erling Smørgrav *auth_name = NULL; 3160fb34990SDag-Erling Smørgrav return ipstrtoaddr(str, port, addr, addrlen); 3170fb34990SDag-Erling Smørgrav } 3180fb34990SDag-Erling Smørgrav 31957bddd21SDag-Erling Smørgrav /** store port number into sockaddr structure */ 32057bddd21SDag-Erling Smørgrav void 32157bddd21SDag-Erling Smørgrav sockaddr_store_port(struct sockaddr_storage* addr, socklen_t addrlen, int port) 32257bddd21SDag-Erling Smørgrav { 32357bddd21SDag-Erling Smørgrav if(addr_is_ip6(addr, addrlen)) { 32457bddd21SDag-Erling Smørgrav struct sockaddr_in6* sa = (struct sockaddr_in6*)addr; 32557bddd21SDag-Erling Smørgrav sa->sin6_port = (in_port_t)htons((uint16_t)port); 32657bddd21SDag-Erling Smørgrav } else { 32757bddd21SDag-Erling Smørgrav struct sockaddr_in* sa = (struct sockaddr_in*)addr; 32857bddd21SDag-Erling Smørgrav sa->sin_port = (in_port_t)htons((uint16_t)port); 32957bddd21SDag-Erling Smørgrav } 33057bddd21SDag-Erling Smørgrav } 33157bddd21SDag-Erling Smørgrav 332b7579f77SDag-Erling Smørgrav void 333b7579f77SDag-Erling Smørgrav log_nametypeclass(enum verbosity_value v, const char* str, uint8_t* name, 334b7579f77SDag-Erling Smørgrav uint16_t type, uint16_t dclass) 335b7579f77SDag-Erling Smørgrav { 336b7579f77SDag-Erling Smørgrav char buf[LDNS_MAX_DOMAINLEN+1]; 337b7579f77SDag-Erling Smørgrav char t[12], c[12]; 338b7579f77SDag-Erling Smørgrav const char *ts, *cs; 339b7579f77SDag-Erling Smørgrav if(verbosity < v) 340b7579f77SDag-Erling Smørgrav return; 341b7579f77SDag-Erling Smørgrav dname_str(name, buf); 342b7579f77SDag-Erling Smørgrav if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG"; 343b7579f77SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR"; 344b7579f77SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR"; 345b7579f77SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB"; 346b7579f77SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA"; 347b7579f77SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_ANY) ts = "ANY"; 34817d15b25SDag-Erling Smørgrav else if(sldns_rr_descript(type) && sldns_rr_descript(type)->_name) 34917d15b25SDag-Erling Smørgrav ts = sldns_rr_descript(type)->_name; 350b7579f77SDag-Erling Smørgrav else { 351b7579f77SDag-Erling Smørgrav snprintf(t, sizeof(t), "TYPE%d", (int)type); 352b7579f77SDag-Erling Smørgrav ts = t; 353b7579f77SDag-Erling Smørgrav } 35417d15b25SDag-Erling Smørgrav if(sldns_lookup_by_id(sldns_rr_classes, (int)dclass) && 35517d15b25SDag-Erling Smørgrav sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name) 35617d15b25SDag-Erling Smørgrav cs = sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name; 357b7579f77SDag-Erling Smørgrav else { 358b7579f77SDag-Erling Smørgrav snprintf(c, sizeof(c), "CLASS%d", (int)dclass); 359b7579f77SDag-Erling Smørgrav cs = c; 360b7579f77SDag-Erling Smørgrav } 361b7579f77SDag-Erling Smørgrav log_info("%s %s %s %s", str, buf, ts, cs); 362b7579f77SDag-Erling Smørgrav } 363b7579f77SDag-Erling Smørgrav 364b7579f77SDag-Erling Smørgrav void log_name_addr(enum verbosity_value v, const char* str, uint8_t* zone, 365b7579f77SDag-Erling Smørgrav struct sockaddr_storage* addr, socklen_t addrlen) 366b7579f77SDag-Erling Smørgrav { 367b7579f77SDag-Erling Smørgrav uint16_t port; 368b7579f77SDag-Erling Smørgrav const char* family = "unknown_family "; 369b7579f77SDag-Erling Smørgrav char namebuf[LDNS_MAX_DOMAINLEN+1]; 370b7579f77SDag-Erling Smørgrav char dest[100]; 371b7579f77SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family; 372b7579f77SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 373b7579f77SDag-Erling Smørgrav if(verbosity < v) 374b7579f77SDag-Erling Smørgrav return; 375b7579f77SDag-Erling Smørgrav switch(af) { 376b7579f77SDag-Erling Smørgrav case AF_INET: family=""; break; 377b7579f77SDag-Erling Smørgrav case AF_INET6: family=""; 378b7579f77SDag-Erling Smørgrav sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; 379b7579f77SDag-Erling Smørgrav break; 38031099b50SDag-Erling Smørgrav case AF_LOCAL: family="local "; break; 381b7579f77SDag-Erling Smørgrav default: break; 382b7579f77SDag-Erling Smørgrav } 383b7579f77SDag-Erling Smørgrav if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { 38417d15b25SDag-Erling Smørgrav (void)strlcpy(dest, "(inet_ntop error)", sizeof(dest)); 385b7579f77SDag-Erling Smørgrav } 386b7579f77SDag-Erling Smørgrav dest[sizeof(dest)-1] = 0; 387b7579f77SDag-Erling Smørgrav port = ntohs(((struct sockaddr_in*)addr)->sin_port); 388b7579f77SDag-Erling Smørgrav dname_str(zone, namebuf); 389b7579f77SDag-Erling Smørgrav if(af != AF_INET && af != AF_INET6) 390b7579f77SDag-Erling Smørgrav verbose(v, "%s <%s> %s%s#%d (addrlen %d)", 391b7579f77SDag-Erling Smørgrav str, namebuf, family, dest, (int)port, (int)addrlen); 392b7579f77SDag-Erling Smørgrav else verbose(v, "%s <%s> %s%s#%d", 393b7579f77SDag-Erling Smørgrav str, namebuf, family, dest, (int)port); 394b7579f77SDag-Erling Smørgrav } 395b7579f77SDag-Erling Smørgrav 396ff825849SDag-Erling Smørgrav void log_err_addr(const char* str, const char* err, 397ff825849SDag-Erling Smørgrav struct sockaddr_storage* addr, socklen_t addrlen) 398ff825849SDag-Erling Smørgrav { 399ff825849SDag-Erling Smørgrav uint16_t port; 400ff825849SDag-Erling Smørgrav char dest[100]; 401ff825849SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family; 402ff825849SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 403ff825849SDag-Erling Smørgrav if(af == AF_INET6) 404ff825849SDag-Erling Smørgrav sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; 405ff825849SDag-Erling Smørgrav if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { 406ff825849SDag-Erling Smørgrav (void)strlcpy(dest, "(inet_ntop error)", sizeof(dest)); 407ff825849SDag-Erling Smørgrav } 408ff825849SDag-Erling Smørgrav dest[sizeof(dest)-1] = 0; 409ff825849SDag-Erling Smørgrav port = ntohs(((struct sockaddr_in*)addr)->sin_port); 410ff825849SDag-Erling Smørgrav if(verbosity >= 4) 411ff825849SDag-Erling Smørgrav log_err("%s: %s for %s port %d (len %d)", str, err, dest, 412ff825849SDag-Erling Smørgrav (int)port, (int)addrlen); 413*4c75e3aaSDag-Erling Smørgrav else log_err("%s: %s for %s port %d", str, err, dest, (int)port); 414ff825849SDag-Erling Smørgrav } 415ff825849SDag-Erling Smørgrav 416b7579f77SDag-Erling Smørgrav int 417b7579f77SDag-Erling Smørgrav sockaddr_cmp(struct sockaddr_storage* addr1, socklen_t len1, 418b7579f77SDag-Erling Smørgrav struct sockaddr_storage* addr2, socklen_t len2) 419b7579f77SDag-Erling Smørgrav { 420b7579f77SDag-Erling Smørgrav struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1; 421b7579f77SDag-Erling Smørgrav struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2; 422b7579f77SDag-Erling Smørgrav struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1; 423b7579f77SDag-Erling Smørgrav struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2; 424b7579f77SDag-Erling Smørgrav if(len1 < len2) 425b7579f77SDag-Erling Smørgrav return -1; 426b7579f77SDag-Erling Smørgrav if(len1 > len2) 427b7579f77SDag-Erling Smørgrav return 1; 428b7579f77SDag-Erling Smørgrav log_assert(len1 == len2); 429b7579f77SDag-Erling Smørgrav if( p1_in->sin_family < p2_in->sin_family) 430b7579f77SDag-Erling Smørgrav return -1; 431b7579f77SDag-Erling Smørgrav if( p1_in->sin_family > p2_in->sin_family) 432b7579f77SDag-Erling Smørgrav return 1; 433b7579f77SDag-Erling Smørgrav log_assert( p1_in->sin_family == p2_in->sin_family ); 434b7579f77SDag-Erling Smørgrav /* compare ip4 */ 435b7579f77SDag-Erling Smørgrav if( p1_in->sin_family == AF_INET ) { 436b7579f77SDag-Erling Smørgrav /* just order it, ntohs not required */ 437b7579f77SDag-Erling Smørgrav if(p1_in->sin_port < p2_in->sin_port) 438b7579f77SDag-Erling Smørgrav return -1; 439b7579f77SDag-Erling Smørgrav if(p1_in->sin_port > p2_in->sin_port) 440b7579f77SDag-Erling Smørgrav return 1; 441b7579f77SDag-Erling Smørgrav log_assert(p1_in->sin_port == p2_in->sin_port); 442b7579f77SDag-Erling Smørgrav return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE); 443b7579f77SDag-Erling Smørgrav } else if (p1_in6->sin6_family == AF_INET6) { 444b7579f77SDag-Erling Smørgrav /* just order it, ntohs not required */ 445b7579f77SDag-Erling Smørgrav if(p1_in6->sin6_port < p2_in6->sin6_port) 446b7579f77SDag-Erling Smørgrav return -1; 447b7579f77SDag-Erling Smørgrav if(p1_in6->sin6_port > p2_in6->sin6_port) 448b7579f77SDag-Erling Smørgrav return 1; 449b7579f77SDag-Erling Smørgrav log_assert(p1_in6->sin6_port == p2_in6->sin6_port); 450b7579f77SDag-Erling Smørgrav return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr, 451b7579f77SDag-Erling Smørgrav INET6_SIZE); 452b7579f77SDag-Erling Smørgrav } else { 453b7579f77SDag-Erling Smørgrav /* eek unknown type, perform this comparison for sanity. */ 454b7579f77SDag-Erling Smørgrav return memcmp(addr1, addr2, len1); 455b7579f77SDag-Erling Smørgrav } 456b7579f77SDag-Erling Smørgrav } 457b7579f77SDag-Erling Smørgrav 458b7579f77SDag-Erling Smørgrav int 459b7579f77SDag-Erling Smørgrav sockaddr_cmp_addr(struct sockaddr_storage* addr1, socklen_t len1, 460b7579f77SDag-Erling Smørgrav struct sockaddr_storage* addr2, socklen_t len2) 461b7579f77SDag-Erling Smørgrav { 462b7579f77SDag-Erling Smørgrav struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1; 463b7579f77SDag-Erling Smørgrav struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2; 464b7579f77SDag-Erling Smørgrav struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1; 465b7579f77SDag-Erling Smørgrav struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2; 466b7579f77SDag-Erling Smørgrav if(len1 < len2) 467b7579f77SDag-Erling Smørgrav return -1; 468b7579f77SDag-Erling Smørgrav if(len1 > len2) 469b7579f77SDag-Erling Smørgrav return 1; 470b7579f77SDag-Erling Smørgrav log_assert(len1 == len2); 471b7579f77SDag-Erling Smørgrav if( p1_in->sin_family < p2_in->sin_family) 472b7579f77SDag-Erling Smørgrav return -1; 473b7579f77SDag-Erling Smørgrav if( p1_in->sin_family > p2_in->sin_family) 474b7579f77SDag-Erling Smørgrav return 1; 475b7579f77SDag-Erling Smørgrav log_assert( p1_in->sin_family == p2_in->sin_family ); 476b7579f77SDag-Erling Smørgrav /* compare ip4 */ 477b7579f77SDag-Erling Smørgrav if( p1_in->sin_family == AF_INET ) { 478b7579f77SDag-Erling Smørgrav return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE); 479b7579f77SDag-Erling Smørgrav } else if (p1_in6->sin6_family == AF_INET6) { 480b7579f77SDag-Erling Smørgrav return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr, 481b7579f77SDag-Erling Smørgrav INET6_SIZE); 482b7579f77SDag-Erling Smørgrav } else { 483b7579f77SDag-Erling Smørgrav /* eek unknown type, perform this comparison for sanity. */ 484b7579f77SDag-Erling Smørgrav return memcmp(addr1, addr2, len1); 485b7579f77SDag-Erling Smørgrav } 486b7579f77SDag-Erling Smørgrav } 487b7579f77SDag-Erling Smørgrav 488b7579f77SDag-Erling Smørgrav int 489b7579f77SDag-Erling Smørgrav addr_is_ip6(struct sockaddr_storage* addr, socklen_t len) 490b7579f77SDag-Erling Smørgrav { 491b7579f77SDag-Erling Smørgrav if(len == (socklen_t)sizeof(struct sockaddr_in6) && 492b7579f77SDag-Erling Smørgrav ((struct sockaddr_in6*)addr)->sin6_family == AF_INET6) 493b7579f77SDag-Erling Smørgrav return 1; 494b7579f77SDag-Erling Smørgrav else return 0; 495b7579f77SDag-Erling Smørgrav } 496b7579f77SDag-Erling Smørgrav 497b7579f77SDag-Erling Smørgrav void 498b7579f77SDag-Erling Smørgrav addr_mask(struct sockaddr_storage* addr, socklen_t len, int net) 499b7579f77SDag-Erling Smørgrav { 500b7579f77SDag-Erling Smørgrav uint8_t mask[8] = {0x0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe}; 501b7579f77SDag-Erling Smørgrav int i, max; 502b7579f77SDag-Erling Smørgrav uint8_t* s; 503b7579f77SDag-Erling Smørgrav if(addr_is_ip6(addr, len)) { 504b7579f77SDag-Erling Smørgrav s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr; 505b7579f77SDag-Erling Smørgrav max = 128; 506b7579f77SDag-Erling Smørgrav } else { 507b7579f77SDag-Erling Smørgrav s = (uint8_t*)&((struct sockaddr_in*)addr)->sin_addr; 508b7579f77SDag-Erling Smørgrav max = 32; 509b7579f77SDag-Erling Smørgrav } 510b7579f77SDag-Erling Smørgrav if(net >= max) 511b7579f77SDag-Erling Smørgrav return; 512b7579f77SDag-Erling Smørgrav for(i=net/8+1; i<max/8; i++) { 513b7579f77SDag-Erling Smørgrav s[i] = 0; 514b7579f77SDag-Erling Smørgrav } 515b7579f77SDag-Erling Smørgrav s[net/8] &= mask[net&0x7]; 516b7579f77SDag-Erling Smørgrav } 517b7579f77SDag-Erling Smørgrav 518b7579f77SDag-Erling Smørgrav int 519b7579f77SDag-Erling Smørgrav addr_in_common(struct sockaddr_storage* addr1, int net1, 520b7579f77SDag-Erling Smørgrav struct sockaddr_storage* addr2, int net2, socklen_t addrlen) 521b7579f77SDag-Erling Smørgrav { 522b7579f77SDag-Erling Smørgrav int min = (net1<net2)?net1:net2; 523b7579f77SDag-Erling Smørgrav int i, to; 524b7579f77SDag-Erling Smørgrav int match = 0; 525b7579f77SDag-Erling Smørgrav uint8_t* s1, *s2; 526b7579f77SDag-Erling Smørgrav if(addr_is_ip6(addr1, addrlen)) { 527b7579f77SDag-Erling Smørgrav s1 = (uint8_t*)&((struct sockaddr_in6*)addr1)->sin6_addr; 528b7579f77SDag-Erling Smørgrav s2 = (uint8_t*)&((struct sockaddr_in6*)addr2)->sin6_addr; 529b7579f77SDag-Erling Smørgrav to = 16; 530b7579f77SDag-Erling Smørgrav } else { 531b7579f77SDag-Erling Smørgrav s1 = (uint8_t*)&((struct sockaddr_in*)addr1)->sin_addr; 532b7579f77SDag-Erling Smørgrav s2 = (uint8_t*)&((struct sockaddr_in*)addr2)->sin_addr; 533b7579f77SDag-Erling Smørgrav to = 4; 534b7579f77SDag-Erling Smørgrav } 535b7579f77SDag-Erling Smørgrav /* match = bits_in_common(s1, s2, to); */ 536b7579f77SDag-Erling Smørgrav for(i=0; i<to; i++) { 537b7579f77SDag-Erling Smørgrav if(s1[i] == s2[i]) { 538b7579f77SDag-Erling Smørgrav match += 8; 539b7579f77SDag-Erling Smørgrav } else { 540b7579f77SDag-Erling Smørgrav uint8_t z = s1[i]^s2[i]; 541b7579f77SDag-Erling Smørgrav log_assert(z); 542b7579f77SDag-Erling Smørgrav while(!(z&0x80)) { 543b7579f77SDag-Erling Smørgrav match++; 544b7579f77SDag-Erling Smørgrav z<<=1; 545b7579f77SDag-Erling Smørgrav } 546b7579f77SDag-Erling Smørgrav break; 547b7579f77SDag-Erling Smørgrav } 548b7579f77SDag-Erling Smørgrav } 549b7579f77SDag-Erling Smørgrav if(match > min) match = min; 550b7579f77SDag-Erling Smørgrav return match; 551b7579f77SDag-Erling Smørgrav } 552b7579f77SDag-Erling Smørgrav 553b7579f77SDag-Erling Smørgrav void 554b7579f77SDag-Erling Smørgrav addr_to_str(struct sockaddr_storage* addr, socklen_t addrlen, 555b7579f77SDag-Erling Smørgrav char* buf, size_t len) 556b7579f77SDag-Erling Smørgrav { 557b7579f77SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family; 558b7579f77SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 559b7579f77SDag-Erling Smørgrav if(addr_is_ip6(addr, addrlen)) 560b7579f77SDag-Erling Smørgrav sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; 561b7579f77SDag-Erling Smørgrav if(inet_ntop(af, sinaddr, buf, (socklen_t)len) == 0) { 562b7579f77SDag-Erling Smørgrav snprintf(buf, len, "(inet_ntop_error)"); 563b7579f77SDag-Erling Smørgrav } 564b7579f77SDag-Erling Smørgrav } 565b7579f77SDag-Erling Smørgrav 566b7579f77SDag-Erling Smørgrav int 567b7579f77SDag-Erling Smørgrav addr_is_ip4mapped(struct sockaddr_storage* addr, socklen_t addrlen) 568b7579f77SDag-Erling Smørgrav { 569b7579f77SDag-Erling Smørgrav /* prefix for ipv4 into ipv6 mapping is ::ffff:x.x.x.x */ 570b7579f77SDag-Erling Smørgrav const uint8_t map_prefix[16] = 571b7579f77SDag-Erling Smørgrav {0,0,0,0, 0,0,0,0, 0,0,0xff,0xff, 0,0,0,0}; 572b7579f77SDag-Erling Smørgrav uint8_t* s; 573b7579f77SDag-Erling Smørgrav if(!addr_is_ip6(addr, addrlen)) 574b7579f77SDag-Erling Smørgrav return 0; 575b7579f77SDag-Erling Smørgrav /* s is 16 octet ipv6 address string */ 576b7579f77SDag-Erling Smørgrav s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr; 577b7579f77SDag-Erling Smørgrav return (memcmp(s, map_prefix, 12) == 0); 578b7579f77SDag-Erling Smørgrav } 579b7579f77SDag-Erling Smørgrav 580b7579f77SDag-Erling Smørgrav int addr_is_broadcast(struct sockaddr_storage* addr, socklen_t addrlen) 581b7579f77SDag-Erling Smørgrav { 582b7579f77SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family; 583b7579f77SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 584b7579f77SDag-Erling Smørgrav return af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in) 585b7579f77SDag-Erling Smørgrav && memcmp(sinaddr, "\377\377\377\377", 4) == 0; 586b7579f77SDag-Erling Smørgrav } 587b7579f77SDag-Erling Smørgrav 588b7579f77SDag-Erling Smørgrav int addr_is_any(struct sockaddr_storage* addr, socklen_t addrlen) 589b7579f77SDag-Erling Smørgrav { 590b7579f77SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family; 591b7579f77SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 592b7579f77SDag-Erling Smørgrav void* sin6addr = &((struct sockaddr_in6*)addr)->sin6_addr; 593b7579f77SDag-Erling Smørgrav if(af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in) 594b7579f77SDag-Erling Smørgrav && memcmp(sinaddr, "\000\000\000\000", 4) == 0) 595b7579f77SDag-Erling Smørgrav return 1; 596b7579f77SDag-Erling Smørgrav else if(af==AF_INET6 && addrlen>=(socklen_t)sizeof(struct sockaddr_in6) 597b7579f77SDag-Erling Smørgrav && memcmp(sin6addr, "\000\000\000\000\000\000\000\000" 598b7579f77SDag-Erling Smørgrav "\000\000\000\000\000\000\000\000", 16) == 0) 599b7579f77SDag-Erling Smørgrav return 1; 600b7579f77SDag-Erling Smørgrav return 0; 601b7579f77SDag-Erling Smørgrav } 602b7579f77SDag-Erling Smørgrav 603b7579f77SDag-Erling Smørgrav void sock_list_insert(struct sock_list** list, struct sockaddr_storage* addr, 604b7579f77SDag-Erling Smørgrav socklen_t len, struct regional* region) 605b7579f77SDag-Erling Smørgrav { 606b7579f77SDag-Erling Smørgrav struct sock_list* add = (struct sock_list*)regional_alloc(region, 607b7579f77SDag-Erling Smørgrav sizeof(*add) - sizeof(add->addr) + (size_t)len); 608b7579f77SDag-Erling Smørgrav if(!add) { 609b7579f77SDag-Erling Smørgrav log_err("out of memory in socketlist insert"); 610b7579f77SDag-Erling Smørgrav return; 611b7579f77SDag-Erling Smørgrav } 612b7579f77SDag-Erling Smørgrav log_assert(list); 613b7579f77SDag-Erling Smørgrav add->next = *list; 614b7579f77SDag-Erling Smørgrav add->len = len; 615b7579f77SDag-Erling Smørgrav *list = add; 616b7579f77SDag-Erling Smørgrav if(len) memmove(&add->addr, addr, len); 617b7579f77SDag-Erling Smørgrav } 618b7579f77SDag-Erling Smørgrav 619b7579f77SDag-Erling Smørgrav void sock_list_prepend(struct sock_list** list, struct sock_list* add) 620b7579f77SDag-Erling Smørgrav { 621b7579f77SDag-Erling Smørgrav struct sock_list* last = add; 622b7579f77SDag-Erling Smørgrav if(!last) 623b7579f77SDag-Erling Smørgrav return; 624b7579f77SDag-Erling Smørgrav while(last->next) 625b7579f77SDag-Erling Smørgrav last = last->next; 626b7579f77SDag-Erling Smørgrav last->next = *list; 627b7579f77SDag-Erling Smørgrav *list = add; 628b7579f77SDag-Erling Smørgrav } 629b7579f77SDag-Erling Smørgrav 630b7579f77SDag-Erling Smørgrav int sock_list_find(struct sock_list* list, struct sockaddr_storage* addr, 631b7579f77SDag-Erling Smørgrav socklen_t len) 632b7579f77SDag-Erling Smørgrav { 633b7579f77SDag-Erling Smørgrav while(list) { 634b7579f77SDag-Erling Smørgrav if(len == list->len) { 635b7579f77SDag-Erling Smørgrav if(len == 0 || sockaddr_cmp_addr(addr, len, 636b7579f77SDag-Erling Smørgrav &list->addr, list->len) == 0) 637b7579f77SDag-Erling Smørgrav return 1; 638b7579f77SDag-Erling Smørgrav } 639b7579f77SDag-Erling Smørgrav list = list->next; 640b7579f77SDag-Erling Smørgrav } 641b7579f77SDag-Erling Smørgrav return 0; 642b7579f77SDag-Erling Smørgrav } 643b7579f77SDag-Erling Smørgrav 644b7579f77SDag-Erling Smørgrav void sock_list_merge(struct sock_list** list, struct regional* region, 645b7579f77SDag-Erling Smørgrav struct sock_list* add) 646b7579f77SDag-Erling Smørgrav { 647b7579f77SDag-Erling Smørgrav struct sock_list* p; 648b7579f77SDag-Erling Smørgrav for(p=add; p; p=p->next) { 649b7579f77SDag-Erling Smørgrav if(!sock_list_find(*list, &p->addr, p->len)) 650b7579f77SDag-Erling Smørgrav sock_list_insert(list, &p->addr, p->len, region); 651b7579f77SDag-Erling Smørgrav } 652b7579f77SDag-Erling Smørgrav } 653b7579f77SDag-Erling Smørgrav 654b7579f77SDag-Erling Smørgrav void 655b7579f77SDag-Erling Smørgrav log_crypto_err(const char* str) 656b7579f77SDag-Erling Smørgrav { 6578ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL 658b7579f77SDag-Erling Smørgrav /* error:[error code]:[library name]:[function name]:[reason string] */ 659b7579f77SDag-Erling Smørgrav char buf[128]; 660b7579f77SDag-Erling Smørgrav unsigned long e; 661b7579f77SDag-Erling Smørgrav ERR_error_string_n(ERR_get_error(), buf, sizeof(buf)); 662b7579f77SDag-Erling Smørgrav log_err("%s crypto %s", str, buf); 663b7579f77SDag-Erling Smørgrav while( (e=ERR_get_error()) ) { 664b7579f77SDag-Erling Smørgrav ERR_error_string_n(e, buf, sizeof(buf)); 665b7579f77SDag-Erling Smørgrav log_err("and additionally crypto %s", buf); 666b7579f77SDag-Erling Smørgrav } 6678ed2b524SDag-Erling Smørgrav #else 6688ed2b524SDag-Erling Smørgrav (void)str; 6698ed2b524SDag-Erling Smørgrav #endif /* HAVE_SSL */ 670b7579f77SDag-Erling Smørgrav } 671b7579f77SDag-Erling Smørgrav 672971980c3SDag-Erling Smørgrav int 673971980c3SDag-Erling Smørgrav listen_sslctx_setup(void* ctxt) 674971980c3SDag-Erling Smørgrav { 675971980c3SDag-Erling Smørgrav #ifdef HAVE_SSL 676971980c3SDag-Erling Smørgrav SSL_CTX* ctx = (SSL_CTX*)ctxt; 677971980c3SDag-Erling Smørgrav /* no SSLv2, SSLv3 because has defects */ 678971980c3SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2) 679971980c3SDag-Erling Smørgrav != SSL_OP_NO_SSLv2){ 680971980c3SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_NO_SSLv2"); 681971980c3SDag-Erling Smørgrav return 0; 682971980c3SDag-Erling Smørgrav } 683971980c3SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3) 684971980c3SDag-Erling Smørgrav != SSL_OP_NO_SSLv3){ 685971980c3SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_NO_SSLv3"); 686971980c3SDag-Erling Smørgrav return 0; 687971980c3SDag-Erling Smørgrav } 688971980c3SDag-Erling Smørgrav #if defined(SSL_OP_NO_TLSv1) && defined(SSL_OP_NO_TLSv1_1) 689971980c3SDag-Erling Smørgrav /* if we have tls 1.1 disable 1.0 */ 690971980c3SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1) & SSL_OP_NO_TLSv1) 691971980c3SDag-Erling Smørgrav != SSL_OP_NO_TLSv1){ 692971980c3SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_NO_TLSv1"); 693971980c3SDag-Erling Smørgrav return 0; 694971980c3SDag-Erling Smørgrav } 695971980c3SDag-Erling Smørgrav #endif 696971980c3SDag-Erling Smørgrav #if defined(SSL_OP_NO_TLSv1_1) && defined(SSL_OP_NO_TLSv1_2) 697971980c3SDag-Erling Smørgrav /* if we have tls 1.2 disable 1.1 */ 698971980c3SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_1) & SSL_OP_NO_TLSv1_1) 699971980c3SDag-Erling Smørgrav != SSL_OP_NO_TLSv1_1){ 700971980c3SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_NO_TLSv1_1"); 701971980c3SDag-Erling Smørgrav return 0; 702971980c3SDag-Erling Smørgrav } 703971980c3SDag-Erling Smørgrav #endif 704971980c3SDag-Erling Smørgrav #if defined(SHA256_DIGEST_LENGTH) && defined(USE_ECDSA) 705971980c3SDag-Erling Smørgrav /* if we have sha256, set the cipher list to have no known vulns */ 70657bddd21SDag-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")) 707971980c3SDag-Erling Smørgrav log_crypto_err("could not set cipher list with SSL_CTX_set_cipher_list"); 708971980c3SDag-Erling Smørgrav #endif 709971980c3SDag-Erling Smørgrav 710971980c3SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE) & 711971980c3SDag-Erling Smørgrav SSL_OP_CIPHER_SERVER_PREFERENCE) != 712971980c3SDag-Erling Smørgrav SSL_OP_CIPHER_SERVER_PREFERENCE) { 713971980c3SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_CIPHER_SERVER_PREFERENCE"); 714971980c3SDag-Erling Smørgrav return 0; 715971980c3SDag-Erling Smørgrav } 716971980c3SDag-Erling Smørgrav 717971980c3SDag-Erling Smørgrav #ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL 718971980c3SDag-Erling Smørgrav SSL_CTX_set_security_level(ctx, 0); 719971980c3SDag-Erling Smørgrav #endif 720971980c3SDag-Erling Smørgrav #else 721971980c3SDag-Erling Smørgrav (void)ctxt; 722971980c3SDag-Erling Smørgrav #endif /* HAVE_SSL */ 723971980c3SDag-Erling Smørgrav return 1; 724971980c3SDag-Erling Smørgrav } 725971980c3SDag-Erling Smørgrav 726971980c3SDag-Erling Smørgrav void 727971980c3SDag-Erling Smørgrav listen_sslctx_setup_2(void* ctxt) 728971980c3SDag-Erling Smørgrav { 729971980c3SDag-Erling Smørgrav #ifdef HAVE_SSL 730971980c3SDag-Erling Smørgrav SSL_CTX* ctx = (SSL_CTX*)ctxt; 731971980c3SDag-Erling Smørgrav (void)ctx; 732971980c3SDag-Erling Smørgrav #if HAVE_DECL_SSL_CTX_SET_ECDH_AUTO 733971980c3SDag-Erling Smørgrav if(!SSL_CTX_set_ecdh_auto(ctx,1)) { 734971980c3SDag-Erling Smørgrav log_crypto_err("Error in SSL_CTX_ecdh_auto, not enabling ECDHE"); 735971980c3SDag-Erling Smørgrav } 736971980c3SDag-Erling Smørgrav #elif defined(USE_ECDSA) 737971980c3SDag-Erling Smørgrav if(1) { 738971980c3SDag-Erling Smørgrav EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1); 739971980c3SDag-Erling Smørgrav if (!ecdh) { 740971980c3SDag-Erling Smørgrav log_crypto_err("could not find p256, not enabling ECDHE"); 741971980c3SDag-Erling Smørgrav } else { 742971980c3SDag-Erling Smørgrav if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh)) { 743971980c3SDag-Erling Smørgrav log_crypto_err("Error in SSL_CTX_set_tmp_ecdh, not enabling ECDHE"); 744971980c3SDag-Erling Smørgrav } 745971980c3SDag-Erling Smørgrav EC_KEY_free (ecdh); 746971980c3SDag-Erling Smørgrav } 747971980c3SDag-Erling Smørgrav } 748971980c3SDag-Erling Smørgrav #endif 749971980c3SDag-Erling Smørgrav #else 750971980c3SDag-Erling Smørgrav (void)ctxt; 751971980c3SDag-Erling Smørgrav #endif /* HAVE_SSL */ 752971980c3SDag-Erling Smørgrav } 753971980c3SDag-Erling Smørgrav 754b7579f77SDag-Erling Smørgrav void* listen_sslctx_create(char* key, char* pem, char* verifypem) 755b7579f77SDag-Erling Smørgrav { 7568ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL 757b7579f77SDag-Erling Smørgrav SSL_CTX* ctx = SSL_CTX_new(SSLv23_server_method()); 758b7579f77SDag-Erling Smørgrav if(!ctx) { 759b7579f77SDag-Erling Smørgrav log_crypto_err("could not SSL_CTX_new"); 760b7579f77SDag-Erling Smørgrav return NULL; 761b7579f77SDag-Erling Smørgrav } 762971980c3SDag-Erling Smørgrav if(!listen_sslctx_setup(ctx)) { 763ff825849SDag-Erling Smørgrav SSL_CTX_free(ctx); 764ff825849SDag-Erling Smørgrav return NULL; 765ff825849SDag-Erling Smørgrav } 766b75612f8SDag-Erling Smørgrav if(!SSL_CTX_use_certificate_chain_file(ctx, pem)) { 767b7579f77SDag-Erling Smørgrav log_err("error for cert file: %s", pem); 768b75612f8SDag-Erling Smørgrav log_crypto_err("error in SSL_CTX use_certificate_chain_file"); 769b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 770b7579f77SDag-Erling Smørgrav return NULL; 771b7579f77SDag-Erling Smørgrav } 772b7579f77SDag-Erling Smørgrav if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) { 773b7579f77SDag-Erling Smørgrav log_err("error for private key file: %s", key); 774b7579f77SDag-Erling Smørgrav log_crypto_err("Error in SSL_CTX use_PrivateKey_file"); 775b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 776b7579f77SDag-Erling Smørgrav return NULL; 777b7579f77SDag-Erling Smørgrav } 778b7579f77SDag-Erling Smørgrav if(!SSL_CTX_check_private_key(ctx)) { 779b7579f77SDag-Erling Smørgrav log_err("error for key file: %s", key); 780b7579f77SDag-Erling Smørgrav log_crypto_err("Error in SSL_CTX check_private_key"); 781b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 782b7579f77SDag-Erling Smørgrav return NULL; 783b7579f77SDag-Erling Smørgrav } 784971980c3SDag-Erling Smørgrav listen_sslctx_setup_2(ctx); 785b7579f77SDag-Erling Smørgrav if(verifypem && verifypem[0]) { 786b7579f77SDag-Erling Smørgrav if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) { 787b7579f77SDag-Erling Smørgrav log_crypto_err("Error in SSL_CTX verify locations"); 788b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 789b7579f77SDag-Erling Smørgrav return NULL; 790b7579f77SDag-Erling Smørgrav } 791b7579f77SDag-Erling Smørgrav SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file( 792b7579f77SDag-Erling Smørgrav verifypem)); 793b7579f77SDag-Erling Smørgrav SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); 794b7579f77SDag-Erling Smørgrav } 795b7579f77SDag-Erling Smørgrav return ctx; 7968ed2b524SDag-Erling Smørgrav #else 7978ed2b524SDag-Erling Smørgrav (void)key; (void)pem; (void)verifypem; 7988ed2b524SDag-Erling Smørgrav return NULL; 7998ed2b524SDag-Erling Smørgrav #endif 800b7579f77SDag-Erling Smørgrav } 801b7579f77SDag-Erling Smørgrav 8023bd4df0aSDag-Erling Smørgrav #ifdef USE_WINSOCK 8033bd4df0aSDag-Erling Smørgrav /* For windows, the CA trust store is not read by openssl. 8043bd4df0aSDag-Erling Smørgrav Add code to open the trust store using wincrypt API and add 8053bd4df0aSDag-Erling Smørgrav the root certs into openssl trust store */ 8063bd4df0aSDag-Erling Smørgrav static int 8073bd4df0aSDag-Erling Smørgrav add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx) 8083bd4df0aSDag-Erling Smørgrav { 8093bd4df0aSDag-Erling Smørgrav HCERTSTORE hSystemStore; 8103bd4df0aSDag-Erling Smørgrav PCCERT_CONTEXT pTargetCert = NULL; 8113bd4df0aSDag-Erling Smørgrav X509_STORE* store; 8123bd4df0aSDag-Erling Smørgrav 8133bd4df0aSDag-Erling Smørgrav verbose(VERB_ALGO, "Adding Windows certificates from system root store to CA store"); 8143bd4df0aSDag-Erling Smørgrav 8153bd4df0aSDag-Erling Smørgrav /* load just once per context lifetime for this version 8163bd4df0aSDag-Erling Smørgrav TODO: dynamically update CA trust changes as they are available */ 8173bd4df0aSDag-Erling Smørgrav if (!tls_ctx) 8183bd4df0aSDag-Erling Smørgrav return 0; 8193bd4df0aSDag-Erling Smørgrav 8203bd4df0aSDag-Erling Smørgrav /* Call wincrypt's CertOpenStore to open the CA root store. */ 8213bd4df0aSDag-Erling Smørgrav 8223bd4df0aSDag-Erling Smørgrav if ((hSystemStore = CertOpenStore( 8233bd4df0aSDag-Erling Smørgrav CERT_STORE_PROV_SYSTEM, 8243bd4df0aSDag-Erling Smørgrav 0, 8253bd4df0aSDag-Erling Smørgrav 0, 8263bd4df0aSDag-Erling Smørgrav /* NOTE: mingw does not have this const: replace with 1 << 16 from code 8273bd4df0aSDag-Erling Smørgrav CERT_SYSTEM_STORE_CURRENT_USER, */ 8283bd4df0aSDag-Erling Smørgrav 1 << 16, 8293bd4df0aSDag-Erling Smørgrav L"root")) == 0) 8303bd4df0aSDag-Erling Smørgrav { 8313bd4df0aSDag-Erling Smørgrav return 0; 8323bd4df0aSDag-Erling Smørgrav } 8333bd4df0aSDag-Erling Smørgrav 8343bd4df0aSDag-Erling Smørgrav store = SSL_CTX_get_cert_store(tls_ctx); 8353bd4df0aSDag-Erling Smørgrav if (!store) 8363bd4df0aSDag-Erling Smørgrav return 0; 8373bd4df0aSDag-Erling Smørgrav 8383bd4df0aSDag-Erling Smørgrav /* failure if the CA store is empty or the call fails */ 8393bd4df0aSDag-Erling Smørgrav if ((pTargetCert = CertEnumCertificatesInStore( 8403bd4df0aSDag-Erling Smørgrav hSystemStore, pTargetCert)) == 0) { 8413bd4df0aSDag-Erling Smørgrav verbose(VERB_ALGO, "CA certificate store for Windows is empty."); 8423bd4df0aSDag-Erling Smørgrav return 0; 8433bd4df0aSDag-Erling Smørgrav } 8443bd4df0aSDag-Erling Smørgrav /* iterate over the windows cert store and add to openssl store */ 8453bd4df0aSDag-Erling Smørgrav do 8463bd4df0aSDag-Erling Smørgrav { 8473bd4df0aSDag-Erling Smørgrav X509 *cert1 = d2i_X509(NULL, 8483bd4df0aSDag-Erling Smørgrav (const unsigned char **)&pTargetCert->pbCertEncoded, 8493bd4df0aSDag-Erling Smørgrav pTargetCert->cbCertEncoded); 8503bd4df0aSDag-Erling Smørgrav if (!cert1) { 8513bd4df0aSDag-Erling Smørgrav /* return error if a cert fails */ 8523bd4df0aSDag-Erling Smørgrav verbose(VERB_ALGO, "%s %d:%s", 8533bd4df0aSDag-Erling Smørgrav "Unable to parse certificate in memory", 8543bd4df0aSDag-Erling Smørgrav (int)ERR_get_error(), ERR_error_string(ERR_get_error(), NULL)); 8553bd4df0aSDag-Erling Smørgrav return 0; 8563bd4df0aSDag-Erling Smørgrav } 8573bd4df0aSDag-Erling Smørgrav else { 8583bd4df0aSDag-Erling Smørgrav /* return error if a cert add to store fails */ 8593bd4df0aSDag-Erling Smørgrav if (X509_STORE_add_cert(store, cert1) == 0) { 8603bd4df0aSDag-Erling Smørgrav unsigned long error = ERR_peek_last_error(); 8613bd4df0aSDag-Erling Smørgrav 8623bd4df0aSDag-Erling Smørgrav /* Ignore error X509_R_CERT_ALREADY_IN_HASH_TABLE which means the 8633bd4df0aSDag-Erling Smørgrav * certificate is already in the store. */ 8643bd4df0aSDag-Erling Smørgrav if(ERR_GET_LIB(error) != ERR_LIB_X509 || 8653bd4df0aSDag-Erling Smørgrav ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) { 8663bd4df0aSDag-Erling Smørgrav verbose(VERB_ALGO, "%s %d:%s\n", 8673bd4df0aSDag-Erling Smørgrav "Error adding certificate", (int)ERR_get_error(), 8683bd4df0aSDag-Erling Smørgrav ERR_error_string(ERR_get_error(), NULL)); 8693bd4df0aSDag-Erling Smørgrav X509_free(cert1); 8703bd4df0aSDag-Erling Smørgrav return 0; 8713bd4df0aSDag-Erling Smørgrav } 8723bd4df0aSDag-Erling Smørgrav } 8733bd4df0aSDag-Erling Smørgrav X509_free(cert1); 8743bd4df0aSDag-Erling Smørgrav } 8753bd4df0aSDag-Erling Smørgrav } while ((pTargetCert = CertEnumCertificatesInStore( 8763bd4df0aSDag-Erling Smørgrav hSystemStore, pTargetCert)) != 0); 8773bd4df0aSDag-Erling Smørgrav 8783bd4df0aSDag-Erling Smørgrav /* Clean up memory and quit. */ 8793bd4df0aSDag-Erling Smørgrav if (pTargetCert) 8803bd4df0aSDag-Erling Smørgrav CertFreeCertificateContext(pTargetCert); 8813bd4df0aSDag-Erling Smørgrav if (hSystemStore) 8823bd4df0aSDag-Erling Smørgrav { 8833bd4df0aSDag-Erling Smørgrav if (!CertCloseStore( 8843bd4df0aSDag-Erling Smørgrav hSystemStore, 0)) 8853bd4df0aSDag-Erling Smørgrav return 0; 8863bd4df0aSDag-Erling Smørgrav } 8873bd4df0aSDag-Erling Smørgrav verbose(VERB_ALGO, "Completed adding Windows certificates to CA store successfully"); 8883bd4df0aSDag-Erling Smørgrav return 1; 8893bd4df0aSDag-Erling Smørgrav } 8903bd4df0aSDag-Erling Smørgrav #endif /* USE_WINSOCK */ 8913bd4df0aSDag-Erling Smørgrav 8923bd4df0aSDag-Erling Smørgrav void* connect_sslctx_create(char* key, char* pem, char* verifypem, int wincert) 893b7579f77SDag-Erling Smørgrav { 8948ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL 895b7579f77SDag-Erling Smørgrav SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method()); 896b7579f77SDag-Erling Smørgrav if(!ctx) { 897b7579f77SDag-Erling Smørgrav log_crypto_err("could not allocate SSL_CTX pointer"); 898b7579f77SDag-Erling Smørgrav return NULL; 899b7579f77SDag-Erling Smørgrav } 90005ab2901SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2) 90105ab2901SDag-Erling Smørgrav != SSL_OP_NO_SSLv2) { 902b7579f77SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_NO_SSLv2"); 903b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 904b7579f77SDag-Erling Smørgrav return NULL; 905b7579f77SDag-Erling Smørgrav } 90605ab2901SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3) 90705ab2901SDag-Erling Smørgrav != SSL_OP_NO_SSLv3) { 908ff825849SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_NO_SSLv3"); 909ff825849SDag-Erling Smørgrav SSL_CTX_free(ctx); 910ff825849SDag-Erling Smørgrav return NULL; 911ff825849SDag-Erling Smørgrav } 912b7579f77SDag-Erling Smørgrav if(key && key[0]) { 913b75612f8SDag-Erling Smørgrav if(!SSL_CTX_use_certificate_chain_file(ctx, pem)) { 914b7579f77SDag-Erling Smørgrav log_err("error in client certificate %s", pem); 915b7579f77SDag-Erling Smørgrav log_crypto_err("error in certificate file"); 916b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 917b7579f77SDag-Erling Smørgrav return NULL; 918b7579f77SDag-Erling Smørgrav } 919b7579f77SDag-Erling Smørgrav if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) { 920b7579f77SDag-Erling Smørgrav log_err("error in client private key %s", key); 921b7579f77SDag-Erling Smørgrav log_crypto_err("error in key file"); 922b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 923b7579f77SDag-Erling Smørgrav return NULL; 924b7579f77SDag-Erling Smørgrav } 925b7579f77SDag-Erling Smørgrav if(!SSL_CTX_check_private_key(ctx)) { 926b7579f77SDag-Erling Smørgrav log_err("error in client key %s", key); 927b7579f77SDag-Erling Smørgrav log_crypto_err("error in SSL_CTX_check_private_key"); 928b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 929b7579f77SDag-Erling Smørgrav return NULL; 930b7579f77SDag-Erling Smørgrav } 931b7579f77SDag-Erling Smørgrav } 9323bd4df0aSDag-Erling Smørgrav if((verifypem && verifypem[0]) || wincert) { 933b7579f77SDag-Erling Smørgrav if(verifypem && verifypem[0]) { 934ff825849SDag-Erling Smørgrav if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) { 935b7579f77SDag-Erling Smørgrav log_crypto_err("error in SSL_CTX verify"); 936b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 937b7579f77SDag-Erling Smørgrav return NULL; 938b7579f77SDag-Erling Smørgrav } 9393bd4df0aSDag-Erling Smørgrav } 9403bd4df0aSDag-Erling Smørgrav #ifdef USE_WINSOCK 9413bd4df0aSDag-Erling Smørgrav if(wincert) { 9423bd4df0aSDag-Erling Smørgrav if(!add_WIN_cacerts_to_openssl_store(ctx)) { 9433bd4df0aSDag-Erling Smørgrav log_crypto_err("error in add_WIN_cacerts_to_openssl_store"); 9443bd4df0aSDag-Erling Smørgrav SSL_CTX_free(ctx); 9453bd4df0aSDag-Erling Smørgrav return NULL; 9463bd4df0aSDag-Erling Smørgrav } 9473bd4df0aSDag-Erling Smørgrav } 9483bd4df0aSDag-Erling Smørgrav #else 9493bd4df0aSDag-Erling Smørgrav (void)wincert; 9503bd4df0aSDag-Erling Smørgrav #endif 951b7579f77SDag-Erling Smørgrav SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); 952b7579f77SDag-Erling Smørgrav } 953b7579f77SDag-Erling Smørgrav return ctx; 9548ed2b524SDag-Erling Smørgrav #else 9553bd4df0aSDag-Erling Smørgrav (void)key; (void)pem; (void)verifypem; (void)wincert; 9568ed2b524SDag-Erling Smørgrav return NULL; 9578ed2b524SDag-Erling Smørgrav #endif 958b7579f77SDag-Erling Smørgrav } 959b7579f77SDag-Erling Smørgrav 960b7579f77SDag-Erling Smørgrav void* incoming_ssl_fd(void* sslctx, int fd) 961b7579f77SDag-Erling Smørgrav { 9628ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL 963b7579f77SDag-Erling Smørgrav SSL* ssl = SSL_new((SSL_CTX*)sslctx); 964b7579f77SDag-Erling Smørgrav if(!ssl) { 965b7579f77SDag-Erling Smørgrav log_crypto_err("could not SSL_new"); 966b7579f77SDag-Erling Smørgrav return NULL; 967b7579f77SDag-Erling Smørgrav } 968b7579f77SDag-Erling Smørgrav SSL_set_accept_state(ssl); 969b7579f77SDag-Erling Smørgrav (void)SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); 970b7579f77SDag-Erling Smørgrav if(!SSL_set_fd(ssl, fd)) { 971b7579f77SDag-Erling Smørgrav log_crypto_err("could not SSL_set_fd"); 972b7579f77SDag-Erling Smørgrav SSL_free(ssl); 973b7579f77SDag-Erling Smørgrav return NULL; 974b7579f77SDag-Erling Smørgrav } 975b7579f77SDag-Erling Smørgrav return ssl; 9768ed2b524SDag-Erling Smørgrav #else 9778ed2b524SDag-Erling Smørgrav (void)sslctx; (void)fd; 9788ed2b524SDag-Erling Smørgrav return NULL; 9798ed2b524SDag-Erling Smørgrav #endif 980b7579f77SDag-Erling Smørgrav } 981b7579f77SDag-Erling Smørgrav 982b7579f77SDag-Erling Smørgrav void* outgoing_ssl_fd(void* sslctx, int fd) 983b7579f77SDag-Erling Smørgrav { 9848ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL 985b7579f77SDag-Erling Smørgrav SSL* ssl = SSL_new((SSL_CTX*)sslctx); 986b7579f77SDag-Erling Smørgrav if(!ssl) { 987b7579f77SDag-Erling Smørgrav log_crypto_err("could not SSL_new"); 988b7579f77SDag-Erling Smørgrav return NULL; 989b7579f77SDag-Erling Smørgrav } 990b7579f77SDag-Erling Smørgrav SSL_set_connect_state(ssl); 991b7579f77SDag-Erling Smørgrav (void)SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); 992b7579f77SDag-Erling Smørgrav if(!SSL_set_fd(ssl, fd)) { 993b7579f77SDag-Erling Smørgrav log_crypto_err("could not SSL_set_fd"); 994b7579f77SDag-Erling Smørgrav SSL_free(ssl); 995b7579f77SDag-Erling Smørgrav return NULL; 996b7579f77SDag-Erling Smørgrav } 997b7579f77SDag-Erling Smørgrav return ssl; 9988ed2b524SDag-Erling Smørgrav #else 9998ed2b524SDag-Erling Smørgrav (void)sslctx; (void)fd; 10008ed2b524SDag-Erling Smørgrav return NULL; 10018ed2b524SDag-Erling Smørgrav #endif 1002b7579f77SDag-Erling Smørgrav } 10038ed2b524SDag-Erling Smørgrav 1004b5663de9SDag-Erling Smørgrav #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L 10058ed2b524SDag-Erling Smørgrav /** global lock list for openssl locks */ 10063005e0a3SDag-Erling Smørgrav static lock_basic_type *ub_openssl_locks = NULL; 10078ed2b524SDag-Erling Smørgrav 10088ed2b524SDag-Erling Smørgrav /** callback that gets thread id for openssl */ 10098ed2b524SDag-Erling Smørgrav static unsigned long 10108ed2b524SDag-Erling Smørgrav ub_crypto_id_cb(void) 10118ed2b524SDag-Erling Smørgrav { 101209a3aaf3SDag-Erling Smørgrav return (unsigned long)log_thread_get(); 10138ed2b524SDag-Erling Smørgrav } 10148ed2b524SDag-Erling Smørgrav 10158ed2b524SDag-Erling Smørgrav static void 10168ed2b524SDag-Erling Smørgrav ub_crypto_lock_cb(int mode, int type, const char *ATTR_UNUSED(file), 10178ed2b524SDag-Erling Smørgrav int ATTR_UNUSED(line)) 10188ed2b524SDag-Erling Smørgrav { 10198ed2b524SDag-Erling Smørgrav if((mode&CRYPTO_LOCK)) { 10208ed2b524SDag-Erling Smørgrav lock_basic_lock(&ub_openssl_locks[type]); 10218ed2b524SDag-Erling Smørgrav } else { 10228ed2b524SDag-Erling Smørgrav lock_basic_unlock(&ub_openssl_locks[type]); 10238ed2b524SDag-Erling Smørgrav } 10248ed2b524SDag-Erling Smørgrav } 10258ed2b524SDag-Erling Smørgrav #endif /* OPENSSL_THREADS */ 10268ed2b524SDag-Erling Smørgrav 10278ed2b524SDag-Erling Smørgrav int ub_openssl_lock_init(void) 10288ed2b524SDag-Erling Smørgrav { 1029b5663de9SDag-Erling Smørgrav #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L 10308ed2b524SDag-Erling Smørgrav int i; 10313005e0a3SDag-Erling Smørgrav ub_openssl_locks = (lock_basic_type*)reallocarray( 10323005e0a3SDag-Erling Smørgrav NULL, (size_t)CRYPTO_num_locks(), sizeof(lock_basic_type)); 10338ed2b524SDag-Erling Smørgrav if(!ub_openssl_locks) 10348ed2b524SDag-Erling Smørgrav return 0; 10358ed2b524SDag-Erling Smørgrav for(i=0; i<CRYPTO_num_locks(); i++) { 10368ed2b524SDag-Erling Smørgrav lock_basic_init(&ub_openssl_locks[i]); 10378ed2b524SDag-Erling Smørgrav } 10388ed2b524SDag-Erling Smørgrav CRYPTO_set_id_callback(&ub_crypto_id_cb); 10398ed2b524SDag-Erling Smørgrav CRYPTO_set_locking_callback(&ub_crypto_lock_cb); 10408ed2b524SDag-Erling Smørgrav #endif /* OPENSSL_THREADS */ 10418ed2b524SDag-Erling Smørgrav return 1; 10428ed2b524SDag-Erling Smørgrav } 10438ed2b524SDag-Erling Smørgrav 10448ed2b524SDag-Erling Smørgrav void ub_openssl_lock_delete(void) 10458ed2b524SDag-Erling Smørgrav { 1046b5663de9SDag-Erling Smørgrav #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L 10478ed2b524SDag-Erling Smørgrav int i; 10488ed2b524SDag-Erling Smørgrav if(!ub_openssl_locks) 10498ed2b524SDag-Erling Smørgrav return; 10508ed2b524SDag-Erling Smørgrav CRYPTO_set_id_callback(NULL); 10518ed2b524SDag-Erling Smørgrav CRYPTO_set_locking_callback(NULL); 10528ed2b524SDag-Erling Smørgrav for(i=0; i<CRYPTO_num_locks(); i++) { 10538ed2b524SDag-Erling Smørgrav lock_basic_destroy(&ub_openssl_locks[i]); 10548ed2b524SDag-Erling Smørgrav } 10558ed2b524SDag-Erling Smørgrav free(ub_openssl_locks); 10568ed2b524SDag-Erling Smørgrav #endif /* OPENSSL_THREADS */ 10578ed2b524SDag-Erling Smørgrav } 10588ed2b524SDag-Erling Smørgrav 1059