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" 46e86b9096SDag-Erling Smørgrav #include "util/config_file.h" 4709a3aaf3SDag-Erling Smørgrav #include "sldns/parseutil.h" 4809a3aaf3SDag-Erling Smørgrav #include "sldns/wire2str.h" 49b7579f77SDag-Erling Smørgrav #include <fcntl.h> 508ed2b524SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_SSL_H 51b7579f77SDag-Erling Smørgrav #include <openssl/ssl.h> 52e86b9096SDag-Erling Smørgrav #include <openssl/evp.h> 53e86b9096SDag-Erling Smørgrav #include <openssl/rand.h> 548ed2b524SDag-Erling Smørgrav #endif 558ed2b524SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_ERR_H 56b7579f77SDag-Erling Smørgrav #include <openssl/err.h> 578ed2b524SDag-Erling Smørgrav #endif 583bd4df0aSDag-Erling Smørgrav #ifdef USE_WINSOCK 593bd4df0aSDag-Erling Smørgrav #include <wincrypt.h> 603bd4df0aSDag-Erling Smørgrav #endif 61b7579f77SDag-Erling Smørgrav 62b7579f77SDag-Erling Smørgrav /** max length of an IP address (the address portion) that we allow */ 63b7579f77SDag-Erling Smørgrav #define MAX_ADDR_STRLEN 128 /* characters */ 64b7579f77SDag-Erling Smørgrav /** default value for EDNS ADVERTISED size */ 65b7579f77SDag-Erling Smørgrav uint16_t EDNS_ADVERTISED_SIZE = 4096; 66b7579f77SDag-Erling Smørgrav 67b7579f77SDag-Erling Smørgrav /** minimal responses when positive answer: default is no */ 68b7579f77SDag-Erling Smørgrav int MINIMAL_RESPONSES = 0; 69b7579f77SDag-Erling Smørgrav 70b7579f77SDag-Erling Smørgrav /** rrset order roundrobin: default is no */ 71b7579f77SDag-Erling Smørgrav int RRSET_ROUNDROBIN = 0; 72b7579f77SDag-Erling Smørgrav 73e86b9096SDag-Erling Smørgrav /** log tag queries with name instead of 'info' for filtering */ 74e86b9096SDag-Erling Smørgrav int LOG_TAG_QUERYREPLY = 0; 75e86b9096SDag-Erling Smørgrav 76e86b9096SDag-Erling Smørgrav static struct tls_session_ticket_key { 77e86b9096SDag-Erling Smørgrav unsigned char *key_name; 78e86b9096SDag-Erling Smørgrav unsigned char *aes_key; 79e86b9096SDag-Erling Smørgrav unsigned char *hmac_key; 80e86b9096SDag-Erling Smørgrav } *ticket_keys; 81e86b9096SDag-Erling Smørgrav 82b7579f77SDag-Erling Smørgrav /* returns true is string addr is an ip6 specced address */ 83b7579f77SDag-Erling Smørgrav int 84b7579f77SDag-Erling Smørgrav str_is_ip6(const char* str) 85b7579f77SDag-Erling Smørgrav { 86b7579f77SDag-Erling Smørgrav if(strchr(str, ':')) 87b7579f77SDag-Erling Smørgrav return 1; 88b7579f77SDag-Erling Smørgrav else return 0; 89b7579f77SDag-Erling Smørgrav } 90b7579f77SDag-Erling Smørgrav 91b7579f77SDag-Erling Smørgrav int 92b7579f77SDag-Erling Smørgrav fd_set_nonblock(int s) 93b7579f77SDag-Erling Smørgrav { 94b7579f77SDag-Erling Smørgrav #ifdef HAVE_FCNTL 95b7579f77SDag-Erling Smørgrav int flag; 96b7579f77SDag-Erling Smørgrav if((flag = fcntl(s, F_GETFL)) == -1) { 97b7579f77SDag-Erling Smørgrav log_err("can't fcntl F_GETFL: %s", strerror(errno)); 98b7579f77SDag-Erling Smørgrav flag = 0; 99b7579f77SDag-Erling Smørgrav } 100b7579f77SDag-Erling Smørgrav flag |= O_NONBLOCK; 101b7579f77SDag-Erling Smørgrav if(fcntl(s, F_SETFL, flag) == -1) { 102b7579f77SDag-Erling Smørgrav log_err("can't fcntl F_SETFL: %s", strerror(errno)); 103b7579f77SDag-Erling Smørgrav return 0; 104b7579f77SDag-Erling Smørgrav } 105b7579f77SDag-Erling Smørgrav #elif defined(HAVE_IOCTLSOCKET) 106b7579f77SDag-Erling Smørgrav unsigned long on = 1; 107b7579f77SDag-Erling Smørgrav if(ioctlsocket(s, FIONBIO, &on) != 0) { 108b7579f77SDag-Erling Smørgrav log_err("can't ioctlsocket FIONBIO on: %s", 109b7579f77SDag-Erling Smørgrav wsa_strerror(WSAGetLastError())); 110b7579f77SDag-Erling Smørgrav } 111b7579f77SDag-Erling Smørgrav #endif 112b7579f77SDag-Erling Smørgrav return 1; 113b7579f77SDag-Erling Smørgrav } 114b7579f77SDag-Erling Smørgrav 115b7579f77SDag-Erling Smørgrav int 116b7579f77SDag-Erling Smørgrav fd_set_block(int s) 117b7579f77SDag-Erling Smørgrav { 118b7579f77SDag-Erling Smørgrav #ifdef HAVE_FCNTL 119b7579f77SDag-Erling Smørgrav int flag; 120b7579f77SDag-Erling Smørgrav if((flag = fcntl(s, F_GETFL)) == -1) { 121b7579f77SDag-Erling Smørgrav log_err("cannot fcntl F_GETFL: %s", strerror(errno)); 122b7579f77SDag-Erling Smørgrav flag = 0; 123b7579f77SDag-Erling Smørgrav } 124b7579f77SDag-Erling Smørgrav flag &= ~O_NONBLOCK; 125b7579f77SDag-Erling Smørgrav if(fcntl(s, F_SETFL, flag) == -1) { 126b7579f77SDag-Erling Smørgrav log_err("cannot fcntl F_SETFL: %s", strerror(errno)); 127b7579f77SDag-Erling Smørgrav return 0; 128b7579f77SDag-Erling Smørgrav } 129b7579f77SDag-Erling Smørgrav #elif defined(HAVE_IOCTLSOCKET) 130b7579f77SDag-Erling Smørgrav unsigned long off = 0; 131b7579f77SDag-Erling Smørgrav if(ioctlsocket(s, FIONBIO, &off) != 0) { 132971980c3SDag-Erling Smørgrav if(WSAGetLastError() != WSAEINVAL || verbosity >= 4) 133b7579f77SDag-Erling Smørgrav log_err("can't ioctlsocket FIONBIO off: %s", 134b7579f77SDag-Erling Smørgrav wsa_strerror(WSAGetLastError())); 135b7579f77SDag-Erling Smørgrav } 136b7579f77SDag-Erling Smørgrav #endif 137b7579f77SDag-Erling Smørgrav return 1; 138b7579f77SDag-Erling Smørgrav } 139b7579f77SDag-Erling Smørgrav 140b7579f77SDag-Erling Smørgrav int 141b7579f77SDag-Erling Smørgrav is_pow2(size_t num) 142b7579f77SDag-Erling Smørgrav { 143b7579f77SDag-Erling Smørgrav if(num == 0) return 1; 144b7579f77SDag-Erling Smørgrav return (num & (num-1)) == 0; 145b7579f77SDag-Erling Smørgrav } 146b7579f77SDag-Erling Smørgrav 147b7579f77SDag-Erling Smørgrav void* 148b7579f77SDag-Erling Smørgrav memdup(void* data, size_t len) 149b7579f77SDag-Erling Smørgrav { 150b7579f77SDag-Erling Smørgrav void* d; 151b7579f77SDag-Erling Smørgrav if(!data) return NULL; 152b7579f77SDag-Erling Smørgrav if(len == 0) return NULL; 153b7579f77SDag-Erling Smørgrav d = malloc(len); 154b7579f77SDag-Erling Smørgrav if(!d) return NULL; 155b7579f77SDag-Erling Smørgrav memcpy(d, data, len); 156b7579f77SDag-Erling Smørgrav return d; 157b7579f77SDag-Erling Smørgrav } 158b7579f77SDag-Erling Smørgrav 159b7579f77SDag-Erling Smørgrav void 160b7579f77SDag-Erling Smørgrav log_addr(enum verbosity_value v, const char* str, 161b7579f77SDag-Erling Smørgrav struct sockaddr_storage* addr, socklen_t addrlen) 162b7579f77SDag-Erling Smørgrav { 163b7579f77SDag-Erling Smørgrav uint16_t port; 164b7579f77SDag-Erling Smørgrav const char* family = "unknown"; 165b7579f77SDag-Erling Smørgrav char dest[100]; 166b7579f77SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family; 167b7579f77SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 168b7579f77SDag-Erling Smørgrav if(verbosity < v) 169b7579f77SDag-Erling Smørgrav return; 170b7579f77SDag-Erling Smørgrav switch(af) { 171b7579f77SDag-Erling Smørgrav case AF_INET: family="ip4"; break; 172b7579f77SDag-Erling Smørgrav case AF_INET6: family="ip6"; 173b7579f77SDag-Erling Smørgrav sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; 174b7579f77SDag-Erling Smørgrav break; 1756480faa8SDag-Erling Smørgrav case AF_LOCAL: 1766480faa8SDag-Erling Smørgrav dest[0]=0; 1776480faa8SDag-Erling Smørgrav (void)inet_ntop(af, sinaddr, dest, 1786480faa8SDag-Erling Smørgrav (socklen_t)sizeof(dest)); 1796480faa8SDag-Erling Smørgrav verbose(v, "%s local %s", str, dest); 1806480faa8SDag-Erling Smørgrav return; /* do not continue and try to get port */ 181b7579f77SDag-Erling Smørgrav default: break; 182b7579f77SDag-Erling Smørgrav } 183b7579f77SDag-Erling Smørgrav if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { 18417d15b25SDag-Erling Smørgrav (void)strlcpy(dest, "(inet_ntop error)", sizeof(dest)); 185b7579f77SDag-Erling Smørgrav } 186b7579f77SDag-Erling Smørgrav dest[sizeof(dest)-1] = 0; 187b7579f77SDag-Erling Smørgrav port = ntohs(((struct sockaddr_in*)addr)->sin_port); 188b7579f77SDag-Erling Smørgrav if(verbosity >= 4) 189b7579f77SDag-Erling Smørgrav verbose(v, "%s %s %s port %d (len %d)", str, family, dest, 190b7579f77SDag-Erling Smørgrav (int)port, (int)addrlen); 191b7579f77SDag-Erling Smørgrav else verbose(v, "%s %s port %d", str, dest, (int)port); 192b7579f77SDag-Erling Smørgrav } 193b7579f77SDag-Erling Smørgrav 194b7579f77SDag-Erling Smørgrav int 195b7579f77SDag-Erling Smørgrav extstrtoaddr(const char* str, struct sockaddr_storage* addr, 196b7579f77SDag-Erling Smørgrav socklen_t* addrlen) 197b7579f77SDag-Erling Smørgrav { 198b7579f77SDag-Erling Smørgrav char* s; 199b7579f77SDag-Erling Smørgrav int port = UNBOUND_DNS_PORT; 200b7579f77SDag-Erling Smørgrav if((s=strchr(str, '@'))) { 201b7579f77SDag-Erling Smørgrav char buf[MAX_ADDR_STRLEN]; 202b7579f77SDag-Erling Smørgrav if(s-str >= MAX_ADDR_STRLEN) { 203b7579f77SDag-Erling Smørgrav return 0; 204b7579f77SDag-Erling Smørgrav } 20517d15b25SDag-Erling Smørgrav (void)strlcpy(buf, str, sizeof(buf)); 206b7579f77SDag-Erling Smørgrav buf[s-str] = 0; 207b7579f77SDag-Erling Smørgrav port = atoi(s+1); 208b7579f77SDag-Erling Smørgrav if(port == 0 && strcmp(s+1,"0")!=0) { 209b7579f77SDag-Erling Smørgrav return 0; 210b7579f77SDag-Erling Smørgrav } 211b7579f77SDag-Erling Smørgrav return ipstrtoaddr(buf, port, addr, addrlen); 212b7579f77SDag-Erling Smørgrav } 213b7579f77SDag-Erling Smørgrav return ipstrtoaddr(str, port, addr, addrlen); 214b7579f77SDag-Erling Smørgrav } 215b7579f77SDag-Erling Smørgrav 216b7579f77SDag-Erling Smørgrav 217b7579f77SDag-Erling Smørgrav int 218b7579f77SDag-Erling Smørgrav ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr, 219b7579f77SDag-Erling Smørgrav socklen_t* addrlen) 220b7579f77SDag-Erling Smørgrav { 221b7579f77SDag-Erling Smørgrav uint16_t p; 222b7579f77SDag-Erling Smørgrav if(!ip) return 0; 223b7579f77SDag-Erling Smørgrav p = (uint16_t) port; 224b7579f77SDag-Erling Smørgrav if(str_is_ip6(ip)) { 225b7579f77SDag-Erling Smørgrav char buf[MAX_ADDR_STRLEN]; 226b7579f77SDag-Erling Smørgrav char* s; 227b7579f77SDag-Erling Smørgrav struct sockaddr_in6* sa = (struct sockaddr_in6*)addr; 228b7579f77SDag-Erling Smørgrav *addrlen = (socklen_t)sizeof(struct sockaddr_in6); 229b7579f77SDag-Erling Smørgrav memset(sa, 0, *addrlen); 230b7579f77SDag-Erling Smørgrav sa->sin6_family = AF_INET6; 231b7579f77SDag-Erling Smørgrav sa->sin6_port = (in_port_t)htons(p); 232b7579f77SDag-Erling Smørgrav if((s=strchr(ip, '%'))) { /* ip6%interface, rfc 4007 */ 233b7579f77SDag-Erling Smørgrav if(s-ip >= MAX_ADDR_STRLEN) 234b7579f77SDag-Erling Smørgrav return 0; 23517d15b25SDag-Erling Smørgrav (void)strlcpy(buf, ip, sizeof(buf)); 236b7579f77SDag-Erling Smørgrav buf[s-ip]=0; 237b7579f77SDag-Erling Smørgrav sa->sin6_scope_id = (uint32_t)atoi(s+1); 238b7579f77SDag-Erling Smørgrav ip = buf; 239b7579f77SDag-Erling Smørgrav } 240b7579f77SDag-Erling Smørgrav if(inet_pton((int)sa->sin6_family, ip, &sa->sin6_addr) <= 0) { 241b7579f77SDag-Erling Smørgrav return 0; 242b7579f77SDag-Erling Smørgrav } 243b7579f77SDag-Erling Smørgrav } else { /* ip4 */ 244b7579f77SDag-Erling Smørgrav struct sockaddr_in* sa = (struct sockaddr_in*)addr; 245b7579f77SDag-Erling Smørgrav *addrlen = (socklen_t)sizeof(struct sockaddr_in); 246b7579f77SDag-Erling Smørgrav memset(sa, 0, *addrlen); 247b7579f77SDag-Erling Smørgrav sa->sin_family = AF_INET; 248b7579f77SDag-Erling Smørgrav sa->sin_port = (in_port_t)htons(p); 249b7579f77SDag-Erling Smørgrav if(inet_pton((int)sa->sin_family, ip, &sa->sin_addr) <= 0) { 250b7579f77SDag-Erling Smørgrav return 0; 251b7579f77SDag-Erling Smørgrav } 252b7579f77SDag-Erling Smørgrav } 253b7579f77SDag-Erling Smørgrav return 1; 254b7579f77SDag-Erling Smørgrav } 255b7579f77SDag-Erling Smørgrav 256b7579f77SDag-Erling Smørgrav int netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr, 257b7579f77SDag-Erling Smørgrav socklen_t* addrlen, int* net) 258b7579f77SDag-Erling Smørgrav { 2590fb34990SDag-Erling Smørgrav char buf[64]; 2600fb34990SDag-Erling Smørgrav char* s; 261b7579f77SDag-Erling Smørgrav *net = (str_is_ip6(str)?128:32); 262b7579f77SDag-Erling Smørgrav if((s=strchr(str, '/'))) { 263b7579f77SDag-Erling Smørgrav if(atoi(s+1) > *net) { 264b7579f77SDag-Erling Smørgrav log_err("netblock too large: %s", str); 265b7579f77SDag-Erling Smørgrav return 0; 266b7579f77SDag-Erling Smørgrav } 267b7579f77SDag-Erling Smørgrav *net = atoi(s+1); 268b7579f77SDag-Erling Smørgrav if(*net == 0 && strcmp(s+1, "0") != 0) { 269b7579f77SDag-Erling Smørgrav log_err("cannot parse netblock: '%s'", str); 270b7579f77SDag-Erling Smørgrav return 0; 271b7579f77SDag-Erling Smørgrav } 2720fb34990SDag-Erling Smørgrav strlcpy(buf, str, sizeof(buf)); 2730fb34990SDag-Erling Smørgrav s = strchr(buf, '/'); 2740fb34990SDag-Erling Smørgrav if(s) *s = 0; 2750fb34990SDag-Erling Smørgrav s = buf; 276b7579f77SDag-Erling Smørgrav } 277b7579f77SDag-Erling Smørgrav if(!ipstrtoaddr(s?s:str, port, addr, addrlen)) { 278b7579f77SDag-Erling Smørgrav log_err("cannot parse ip address: '%s'", str); 279b7579f77SDag-Erling Smørgrav return 0; 280b7579f77SDag-Erling Smørgrav } 281b7579f77SDag-Erling Smørgrav if(s) { 282b7579f77SDag-Erling Smørgrav addr_mask(addr, *addrlen, *net); 283b7579f77SDag-Erling Smørgrav } 284b7579f77SDag-Erling Smørgrav return 1; 285b7579f77SDag-Erling Smørgrav } 286b7579f77SDag-Erling Smørgrav 287*091e9e46SCy Schubert /* RPZ format address dname to network byte order address */ 288*091e9e46SCy Schubert static int ipdnametoaddr(uint8_t* dname, size_t dnamelen, 289*091e9e46SCy Schubert struct sockaddr_storage* addr, socklen_t* addrlen, int* af) 290*091e9e46SCy Schubert { 291*091e9e46SCy Schubert uint8_t* ia; 292*091e9e46SCy Schubert size_t dnamelabs = dname_count_labels(dname); 293*091e9e46SCy Schubert uint8_t lablen; 294*091e9e46SCy Schubert char* e = NULL; 295*091e9e46SCy Schubert int z = 0; 296*091e9e46SCy Schubert size_t len = 0; 297*091e9e46SCy Schubert int i; 298*091e9e46SCy Schubert *af = AF_INET; 299*091e9e46SCy Schubert 300*091e9e46SCy Schubert /* need 1 byte for label length */ 301*091e9e46SCy Schubert if(dnamelen < 1) 302*091e9e46SCy Schubert return 0; 303*091e9e46SCy Schubert 304*091e9e46SCy Schubert if(dnamelabs > 6 || 305*091e9e46SCy Schubert dname_has_label(dname, dnamelen, (uint8_t*)"\002zz")) { 306*091e9e46SCy Schubert *af = AF_INET6; 307*091e9e46SCy Schubert } 308*091e9e46SCy Schubert len = *dname; 309*091e9e46SCy Schubert lablen = *dname++; 310*091e9e46SCy Schubert i = (*af == AF_INET) ? 3 : 15; 311*091e9e46SCy Schubert if(*af == AF_INET6) { 312*091e9e46SCy Schubert struct sockaddr_in6* sa = (struct sockaddr_in6*)addr; 313*091e9e46SCy Schubert *addrlen = (socklen_t)sizeof(struct sockaddr_in6); 314*091e9e46SCy Schubert memset(sa, 0, *addrlen); 315*091e9e46SCy Schubert sa->sin6_family = AF_INET6; 316*091e9e46SCy Schubert ia = (uint8_t*)&sa->sin6_addr; 317*091e9e46SCy Schubert } else { /* ip4 */ 318*091e9e46SCy Schubert struct sockaddr_in* sa = (struct sockaddr_in*)addr; 319*091e9e46SCy Schubert *addrlen = (socklen_t)sizeof(struct sockaddr_in); 320*091e9e46SCy Schubert memset(sa, 0, *addrlen); 321*091e9e46SCy Schubert sa->sin_family = AF_INET; 322*091e9e46SCy Schubert ia = (uint8_t*)&sa->sin_addr; 323*091e9e46SCy Schubert } 324*091e9e46SCy Schubert while(lablen && i >= 0 && len <= dnamelen) { 325*091e9e46SCy Schubert char buff[LDNS_MAX_LABELLEN+1]; 326*091e9e46SCy Schubert uint16_t chunk; /* big enough to not overflow on IPv6 hextet */ 327*091e9e46SCy Schubert if((*af == AF_INET && (lablen > 3 || dnamelabs > 6)) || 328*091e9e46SCy Schubert (*af == AF_INET6 && (lablen > 4 || dnamelabs > 10))) { 329*091e9e46SCy Schubert return 0; 330*091e9e46SCy Schubert } 331*091e9e46SCy Schubert if(memcmp(dname, "zz", 2) == 0 && *af == AF_INET6) { 332*091e9e46SCy Schubert /* Add one or more 0 labels. Address is initialised at 333*091e9e46SCy Schubert * 0, so just skip the zero part. */ 334*091e9e46SCy Schubert int zl = 11 - dnamelabs; 335*091e9e46SCy Schubert if(z || zl < 0) 336*091e9e46SCy Schubert return 0; 337*091e9e46SCy Schubert z = 1; 338*091e9e46SCy Schubert i -= (zl*2); 339*091e9e46SCy Schubert } else { 340*091e9e46SCy Schubert memcpy(buff, dname, lablen); 341*091e9e46SCy Schubert buff[lablen] = '\0'; 342*091e9e46SCy Schubert chunk = strtol(buff, &e, (*af == AF_INET) ? 10 : 16); 343*091e9e46SCy Schubert if(!e || *e != '\0' || (*af == AF_INET && chunk > 255)) 344*091e9e46SCy Schubert return 0; 345*091e9e46SCy Schubert if(*af == AF_INET) { 346*091e9e46SCy Schubert log_assert(i < 4 && i >= 0); 347*091e9e46SCy Schubert ia[i] = (uint8_t)chunk; 348*091e9e46SCy Schubert i--; 349*091e9e46SCy Schubert } else { 350*091e9e46SCy Schubert log_assert(i < 16 && i >= 1); 351*091e9e46SCy Schubert /* ia in network byte order */ 352*091e9e46SCy Schubert ia[i-1] = (uint8_t)(chunk >> 8); 353*091e9e46SCy Schubert ia[i] = (uint8_t)(chunk & 0x00FF); 354*091e9e46SCy Schubert i -= 2; 355*091e9e46SCy Schubert } 356*091e9e46SCy Schubert } 357*091e9e46SCy Schubert dname += lablen; 358*091e9e46SCy Schubert lablen = *dname++; 359*091e9e46SCy Schubert len += lablen; 360*091e9e46SCy Schubert } 361*091e9e46SCy Schubert if(i != -1) 362*091e9e46SCy Schubert /* input too short */ 363*091e9e46SCy Schubert return 0; 364*091e9e46SCy Schubert return 1; 365*091e9e46SCy Schubert } 366*091e9e46SCy Schubert 367*091e9e46SCy Schubert int netblockdnametoaddr(uint8_t* dname, size_t dnamelen, 368*091e9e46SCy Schubert struct sockaddr_storage* addr, socklen_t* addrlen, int* net, int* af) 369*091e9e46SCy Schubert { 370*091e9e46SCy Schubert char buff[3 /* 3 digit netblock */ + 1]; 371*091e9e46SCy Schubert size_t nlablen; 372*091e9e46SCy Schubert if(dnamelen < 1 || *dname > 3) 373*091e9e46SCy Schubert /* netblock invalid */ 374*091e9e46SCy Schubert return 0; 375*091e9e46SCy Schubert nlablen = *dname; 376*091e9e46SCy Schubert 377*091e9e46SCy Schubert if(dnamelen < 1 + nlablen) 378*091e9e46SCy Schubert return 0; 379*091e9e46SCy Schubert 380*091e9e46SCy Schubert memcpy(buff, dname+1, nlablen); 381*091e9e46SCy Schubert buff[nlablen] = '\0'; 382*091e9e46SCy Schubert *net = atoi(buff); 383*091e9e46SCy Schubert if(*net == 0 && strcmp(buff, "0") != 0) 384*091e9e46SCy Schubert return 0; 385*091e9e46SCy Schubert dname += nlablen; 386*091e9e46SCy Schubert dname++; 387*091e9e46SCy Schubert if(!ipdnametoaddr(dname, dnamelen-1-nlablen, addr, addrlen, af)) 388*091e9e46SCy Schubert return 0; 389*091e9e46SCy Schubert if((*af == AF_INET6 && *net > 128) || (*af == AF_INET && *net > 32)) 390*091e9e46SCy Schubert return 0; 391*091e9e46SCy Schubert return 1; 392*091e9e46SCy Schubert } 393*091e9e46SCy Schubert 3940fb34990SDag-Erling Smørgrav int authextstrtoaddr(char* str, struct sockaddr_storage* addr, 3950fb34990SDag-Erling Smørgrav socklen_t* addrlen, char** auth_name) 3960fb34990SDag-Erling Smørgrav { 3970fb34990SDag-Erling Smørgrav char* s; 3980fb34990SDag-Erling Smørgrav int port = UNBOUND_DNS_PORT; 3990fb34990SDag-Erling Smørgrav if((s=strchr(str, '@'))) { 4000fb34990SDag-Erling Smørgrav char buf[MAX_ADDR_STRLEN]; 4010fb34990SDag-Erling Smørgrav size_t len = (size_t)(s-str); 4020fb34990SDag-Erling Smørgrav char* hash = strchr(s+1, '#'); 4030fb34990SDag-Erling Smørgrav if(hash) { 4040fb34990SDag-Erling Smørgrav *auth_name = hash+1; 4050fb34990SDag-Erling Smørgrav } else { 4060fb34990SDag-Erling Smørgrav *auth_name = NULL; 4070fb34990SDag-Erling Smørgrav } 4080fb34990SDag-Erling Smørgrav if(len >= MAX_ADDR_STRLEN) { 4090fb34990SDag-Erling Smørgrav return 0; 4100fb34990SDag-Erling Smørgrav } 4110fb34990SDag-Erling Smørgrav (void)strlcpy(buf, str, sizeof(buf)); 4120fb34990SDag-Erling Smørgrav buf[len] = 0; 4130fb34990SDag-Erling Smørgrav port = atoi(s+1); 4140fb34990SDag-Erling Smørgrav if(port == 0) { 4150fb34990SDag-Erling Smørgrav if(!hash && strcmp(s+1,"0")!=0) 4160fb34990SDag-Erling Smørgrav return 0; 4170fb34990SDag-Erling Smørgrav if(hash && strncmp(s+1,"0#",2)!=0) 4180fb34990SDag-Erling Smørgrav return 0; 4190fb34990SDag-Erling Smørgrav } 4200fb34990SDag-Erling Smørgrav return ipstrtoaddr(buf, port, addr, addrlen); 4210fb34990SDag-Erling Smørgrav } 4220fb34990SDag-Erling Smørgrav if((s=strchr(str, '#'))) { 4230fb34990SDag-Erling Smørgrav char buf[MAX_ADDR_STRLEN]; 4240fb34990SDag-Erling Smørgrav size_t len = (size_t)(s-str); 4250fb34990SDag-Erling Smørgrav if(len >= MAX_ADDR_STRLEN) { 4260fb34990SDag-Erling Smørgrav return 0; 4270fb34990SDag-Erling Smørgrav } 4280fb34990SDag-Erling Smørgrav (void)strlcpy(buf, str, sizeof(buf)); 4290fb34990SDag-Erling Smørgrav buf[len] = 0; 4300fb34990SDag-Erling Smørgrav port = UNBOUND_DNS_OVER_TLS_PORT; 4310fb34990SDag-Erling Smørgrav *auth_name = s+1; 4320fb34990SDag-Erling Smørgrav return ipstrtoaddr(buf, port, addr, addrlen); 4330fb34990SDag-Erling Smørgrav } 4340fb34990SDag-Erling Smørgrav *auth_name = NULL; 4350fb34990SDag-Erling Smørgrav return ipstrtoaddr(str, port, addr, addrlen); 4360fb34990SDag-Erling Smørgrav } 4370fb34990SDag-Erling Smørgrav 43857bddd21SDag-Erling Smørgrav /** store port number into sockaddr structure */ 43957bddd21SDag-Erling Smørgrav void 44057bddd21SDag-Erling Smørgrav sockaddr_store_port(struct sockaddr_storage* addr, socklen_t addrlen, int port) 44157bddd21SDag-Erling Smørgrav { 44257bddd21SDag-Erling Smørgrav if(addr_is_ip6(addr, addrlen)) { 44357bddd21SDag-Erling Smørgrav struct sockaddr_in6* sa = (struct sockaddr_in6*)addr; 44457bddd21SDag-Erling Smørgrav sa->sin6_port = (in_port_t)htons((uint16_t)port); 44557bddd21SDag-Erling Smørgrav } else { 44657bddd21SDag-Erling Smørgrav struct sockaddr_in* sa = (struct sockaddr_in*)addr; 44757bddd21SDag-Erling Smørgrav sa->sin_port = (in_port_t)htons((uint16_t)port); 44857bddd21SDag-Erling Smørgrav } 44957bddd21SDag-Erling Smørgrav } 45057bddd21SDag-Erling Smørgrav 451b7579f77SDag-Erling Smørgrav void 452b7579f77SDag-Erling Smørgrav log_nametypeclass(enum verbosity_value v, const char* str, uint8_t* name, 453b7579f77SDag-Erling Smørgrav uint16_t type, uint16_t dclass) 454b7579f77SDag-Erling Smørgrav { 455b7579f77SDag-Erling Smørgrav char buf[LDNS_MAX_DOMAINLEN+1]; 456b7579f77SDag-Erling Smørgrav char t[12], c[12]; 457b7579f77SDag-Erling Smørgrav const char *ts, *cs; 458b7579f77SDag-Erling Smørgrav if(verbosity < v) 459b7579f77SDag-Erling Smørgrav return; 460b7579f77SDag-Erling Smørgrav dname_str(name, buf); 461b7579f77SDag-Erling Smørgrav if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG"; 462b7579f77SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR"; 463b7579f77SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR"; 464b7579f77SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB"; 465b7579f77SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA"; 466b7579f77SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_ANY) ts = "ANY"; 46717d15b25SDag-Erling Smørgrav else if(sldns_rr_descript(type) && sldns_rr_descript(type)->_name) 46817d15b25SDag-Erling Smørgrav ts = sldns_rr_descript(type)->_name; 469b7579f77SDag-Erling Smørgrav else { 470b7579f77SDag-Erling Smørgrav snprintf(t, sizeof(t), "TYPE%d", (int)type); 471b7579f77SDag-Erling Smørgrav ts = t; 472b7579f77SDag-Erling Smørgrav } 47317d15b25SDag-Erling Smørgrav if(sldns_lookup_by_id(sldns_rr_classes, (int)dclass) && 47417d15b25SDag-Erling Smørgrav sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name) 47517d15b25SDag-Erling Smørgrav cs = sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name; 476b7579f77SDag-Erling Smørgrav else { 477b7579f77SDag-Erling Smørgrav snprintf(c, sizeof(c), "CLASS%d", (int)dclass); 478b7579f77SDag-Erling Smørgrav cs = c; 479b7579f77SDag-Erling Smørgrav } 480b7579f77SDag-Erling Smørgrav log_info("%s %s %s %s", str, buf, ts, cs); 481b7579f77SDag-Erling Smørgrav } 482b7579f77SDag-Erling Smørgrav 483e86b9096SDag-Erling Smørgrav void 484e86b9096SDag-Erling Smørgrav log_query_in(const char* str, uint8_t* name, uint16_t type, uint16_t dclass) 485e86b9096SDag-Erling Smørgrav { 486e86b9096SDag-Erling Smørgrav char buf[LDNS_MAX_DOMAINLEN+1]; 487e86b9096SDag-Erling Smørgrav char t[12], c[12]; 488e86b9096SDag-Erling Smørgrav const char *ts, *cs; 489e86b9096SDag-Erling Smørgrav dname_str(name, buf); 490e86b9096SDag-Erling Smørgrav if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG"; 491e86b9096SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR"; 492e86b9096SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR"; 493e86b9096SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB"; 494e86b9096SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA"; 495e86b9096SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_ANY) ts = "ANY"; 496e86b9096SDag-Erling Smørgrav else if(sldns_rr_descript(type) && sldns_rr_descript(type)->_name) 497e86b9096SDag-Erling Smørgrav ts = sldns_rr_descript(type)->_name; 498e86b9096SDag-Erling Smørgrav else { 499e86b9096SDag-Erling Smørgrav snprintf(t, sizeof(t), "TYPE%d", (int)type); 500e86b9096SDag-Erling Smørgrav ts = t; 501e86b9096SDag-Erling Smørgrav } 502e86b9096SDag-Erling Smørgrav if(sldns_lookup_by_id(sldns_rr_classes, (int)dclass) && 503e86b9096SDag-Erling Smørgrav sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name) 504e86b9096SDag-Erling Smørgrav cs = sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name; 505e86b9096SDag-Erling Smørgrav else { 506e86b9096SDag-Erling Smørgrav snprintf(c, sizeof(c), "CLASS%d", (int)dclass); 507e86b9096SDag-Erling Smørgrav cs = c; 508e86b9096SDag-Erling Smørgrav } 509e86b9096SDag-Erling Smørgrav if(LOG_TAG_QUERYREPLY) 510e86b9096SDag-Erling Smørgrav log_query("%s %s %s %s", str, buf, ts, cs); 511e86b9096SDag-Erling Smørgrav else log_info("%s %s %s %s", str, buf, ts, cs); 512e86b9096SDag-Erling Smørgrav } 513e86b9096SDag-Erling Smørgrav 514b7579f77SDag-Erling Smørgrav void log_name_addr(enum verbosity_value v, const char* str, uint8_t* zone, 515b7579f77SDag-Erling Smørgrav struct sockaddr_storage* addr, socklen_t addrlen) 516b7579f77SDag-Erling Smørgrav { 517b7579f77SDag-Erling Smørgrav uint16_t port; 518b7579f77SDag-Erling Smørgrav const char* family = "unknown_family "; 519b7579f77SDag-Erling Smørgrav char namebuf[LDNS_MAX_DOMAINLEN+1]; 520b7579f77SDag-Erling Smørgrav char dest[100]; 521b7579f77SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family; 522b7579f77SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 523b7579f77SDag-Erling Smørgrav if(verbosity < v) 524b7579f77SDag-Erling Smørgrav return; 525b7579f77SDag-Erling Smørgrav switch(af) { 526b7579f77SDag-Erling Smørgrav case AF_INET: family=""; break; 527b7579f77SDag-Erling Smørgrav case AF_INET6: family=""; 528b7579f77SDag-Erling Smørgrav sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; 529b7579f77SDag-Erling Smørgrav break; 53031099b50SDag-Erling Smørgrav case AF_LOCAL: family="local "; break; 531b7579f77SDag-Erling Smørgrav default: break; 532b7579f77SDag-Erling Smørgrav } 533b7579f77SDag-Erling Smørgrav if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { 53417d15b25SDag-Erling Smørgrav (void)strlcpy(dest, "(inet_ntop error)", sizeof(dest)); 535b7579f77SDag-Erling Smørgrav } 536b7579f77SDag-Erling Smørgrav dest[sizeof(dest)-1] = 0; 537b7579f77SDag-Erling Smørgrav port = ntohs(((struct sockaddr_in*)addr)->sin_port); 538b7579f77SDag-Erling Smørgrav dname_str(zone, namebuf); 539b7579f77SDag-Erling Smørgrav if(af != AF_INET && af != AF_INET6) 540b7579f77SDag-Erling Smørgrav verbose(v, "%s <%s> %s%s#%d (addrlen %d)", 541b7579f77SDag-Erling Smørgrav str, namebuf, family, dest, (int)port, (int)addrlen); 542b7579f77SDag-Erling Smørgrav else verbose(v, "%s <%s> %s%s#%d", 543b7579f77SDag-Erling Smørgrav str, namebuf, family, dest, (int)port); 544b7579f77SDag-Erling Smørgrav } 545b7579f77SDag-Erling Smørgrav 546ff825849SDag-Erling Smørgrav void log_err_addr(const char* str, const char* err, 547ff825849SDag-Erling Smørgrav struct sockaddr_storage* addr, socklen_t addrlen) 548ff825849SDag-Erling Smørgrav { 549ff825849SDag-Erling Smørgrav uint16_t port; 550ff825849SDag-Erling Smørgrav char dest[100]; 551ff825849SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family; 552ff825849SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 553ff825849SDag-Erling Smørgrav if(af == AF_INET6) 554ff825849SDag-Erling Smørgrav sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; 555ff825849SDag-Erling Smørgrav if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { 556ff825849SDag-Erling Smørgrav (void)strlcpy(dest, "(inet_ntop error)", sizeof(dest)); 557ff825849SDag-Erling Smørgrav } 558ff825849SDag-Erling Smørgrav dest[sizeof(dest)-1] = 0; 559ff825849SDag-Erling Smørgrav port = ntohs(((struct sockaddr_in*)addr)->sin_port); 560ff825849SDag-Erling Smørgrav if(verbosity >= 4) 561ff825849SDag-Erling Smørgrav log_err("%s: %s for %s port %d (len %d)", str, err, dest, 562ff825849SDag-Erling Smørgrav (int)port, (int)addrlen); 5634c75e3aaSDag-Erling Smørgrav else log_err("%s: %s for %s port %d", str, err, dest, (int)port); 564ff825849SDag-Erling Smørgrav } 565ff825849SDag-Erling Smørgrav 566b7579f77SDag-Erling Smørgrav int 567b7579f77SDag-Erling Smørgrav sockaddr_cmp(struct sockaddr_storage* addr1, socklen_t len1, 568b7579f77SDag-Erling Smørgrav struct sockaddr_storage* addr2, socklen_t len2) 569b7579f77SDag-Erling Smørgrav { 570b7579f77SDag-Erling Smørgrav struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1; 571b7579f77SDag-Erling Smørgrav struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2; 572b7579f77SDag-Erling Smørgrav struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1; 573b7579f77SDag-Erling Smørgrav struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2; 574b7579f77SDag-Erling Smørgrav if(len1 < len2) 575b7579f77SDag-Erling Smørgrav return -1; 576b7579f77SDag-Erling Smørgrav if(len1 > len2) 577b7579f77SDag-Erling Smørgrav return 1; 578b7579f77SDag-Erling Smørgrav log_assert(len1 == len2); 579b7579f77SDag-Erling Smørgrav if( p1_in->sin_family < p2_in->sin_family) 580b7579f77SDag-Erling Smørgrav return -1; 581b7579f77SDag-Erling Smørgrav if( p1_in->sin_family > p2_in->sin_family) 582b7579f77SDag-Erling Smørgrav return 1; 583b7579f77SDag-Erling Smørgrav log_assert( p1_in->sin_family == p2_in->sin_family ); 584b7579f77SDag-Erling Smørgrav /* compare ip4 */ 585b7579f77SDag-Erling Smørgrav if( p1_in->sin_family == AF_INET ) { 586b7579f77SDag-Erling Smørgrav /* just order it, ntohs not required */ 587b7579f77SDag-Erling Smørgrav if(p1_in->sin_port < p2_in->sin_port) 588b7579f77SDag-Erling Smørgrav return -1; 589b7579f77SDag-Erling Smørgrav if(p1_in->sin_port > p2_in->sin_port) 590b7579f77SDag-Erling Smørgrav return 1; 591b7579f77SDag-Erling Smørgrav log_assert(p1_in->sin_port == p2_in->sin_port); 592b7579f77SDag-Erling Smørgrav return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE); 593b7579f77SDag-Erling Smørgrav } else if (p1_in6->sin6_family == AF_INET6) { 594b7579f77SDag-Erling Smørgrav /* just order it, ntohs not required */ 595b7579f77SDag-Erling Smørgrav if(p1_in6->sin6_port < p2_in6->sin6_port) 596b7579f77SDag-Erling Smørgrav return -1; 597b7579f77SDag-Erling Smørgrav if(p1_in6->sin6_port > p2_in6->sin6_port) 598b7579f77SDag-Erling Smørgrav return 1; 599b7579f77SDag-Erling Smørgrav log_assert(p1_in6->sin6_port == p2_in6->sin6_port); 600b7579f77SDag-Erling Smørgrav return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr, 601b7579f77SDag-Erling Smørgrav INET6_SIZE); 602b7579f77SDag-Erling Smørgrav } else { 603b7579f77SDag-Erling Smørgrav /* eek unknown type, perform this comparison for sanity. */ 604b7579f77SDag-Erling Smørgrav return memcmp(addr1, addr2, len1); 605b7579f77SDag-Erling Smørgrav } 606b7579f77SDag-Erling Smørgrav } 607b7579f77SDag-Erling Smørgrav 608b7579f77SDag-Erling Smørgrav int 609b7579f77SDag-Erling Smørgrav sockaddr_cmp_addr(struct sockaddr_storage* addr1, socklen_t len1, 610b7579f77SDag-Erling Smørgrav struct sockaddr_storage* addr2, socklen_t len2) 611b7579f77SDag-Erling Smørgrav { 612b7579f77SDag-Erling Smørgrav struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1; 613b7579f77SDag-Erling Smørgrav struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2; 614b7579f77SDag-Erling Smørgrav struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1; 615b7579f77SDag-Erling Smørgrav struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2; 616b7579f77SDag-Erling Smørgrav if(len1 < len2) 617b7579f77SDag-Erling Smørgrav return -1; 618b7579f77SDag-Erling Smørgrav if(len1 > len2) 619b7579f77SDag-Erling Smørgrav return 1; 620b7579f77SDag-Erling Smørgrav log_assert(len1 == len2); 621b7579f77SDag-Erling Smørgrav if( p1_in->sin_family < p2_in->sin_family) 622b7579f77SDag-Erling Smørgrav return -1; 623b7579f77SDag-Erling Smørgrav if( p1_in->sin_family > p2_in->sin_family) 624b7579f77SDag-Erling Smørgrav return 1; 625b7579f77SDag-Erling Smørgrav log_assert( p1_in->sin_family == p2_in->sin_family ); 626b7579f77SDag-Erling Smørgrav /* compare ip4 */ 627b7579f77SDag-Erling Smørgrav if( p1_in->sin_family == AF_INET ) { 628b7579f77SDag-Erling Smørgrav return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE); 629b7579f77SDag-Erling Smørgrav } else if (p1_in6->sin6_family == AF_INET6) { 630b7579f77SDag-Erling Smørgrav return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr, 631b7579f77SDag-Erling Smørgrav INET6_SIZE); 632b7579f77SDag-Erling Smørgrav } else { 633b7579f77SDag-Erling Smørgrav /* eek unknown type, perform this comparison for sanity. */ 634b7579f77SDag-Erling Smørgrav return memcmp(addr1, addr2, len1); 635b7579f77SDag-Erling Smørgrav } 636b7579f77SDag-Erling Smørgrav } 637b7579f77SDag-Erling Smørgrav 638b7579f77SDag-Erling Smørgrav int 639b7579f77SDag-Erling Smørgrav addr_is_ip6(struct sockaddr_storage* addr, socklen_t len) 640b7579f77SDag-Erling Smørgrav { 641b7579f77SDag-Erling Smørgrav if(len == (socklen_t)sizeof(struct sockaddr_in6) && 642b7579f77SDag-Erling Smørgrav ((struct sockaddr_in6*)addr)->sin6_family == AF_INET6) 643b7579f77SDag-Erling Smørgrav return 1; 644b7579f77SDag-Erling Smørgrav else return 0; 645b7579f77SDag-Erling Smørgrav } 646b7579f77SDag-Erling Smørgrav 647b7579f77SDag-Erling Smørgrav void 648b7579f77SDag-Erling Smørgrav addr_mask(struct sockaddr_storage* addr, socklen_t len, int net) 649b7579f77SDag-Erling Smørgrav { 650b7579f77SDag-Erling Smørgrav uint8_t mask[8] = {0x0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe}; 651b7579f77SDag-Erling Smørgrav int i, max; 652b7579f77SDag-Erling Smørgrav uint8_t* s; 653b7579f77SDag-Erling Smørgrav if(addr_is_ip6(addr, len)) { 654b7579f77SDag-Erling Smørgrav s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr; 655b7579f77SDag-Erling Smørgrav max = 128; 656b7579f77SDag-Erling Smørgrav } else { 657b7579f77SDag-Erling Smørgrav s = (uint8_t*)&((struct sockaddr_in*)addr)->sin_addr; 658b7579f77SDag-Erling Smørgrav max = 32; 659b7579f77SDag-Erling Smørgrav } 660b7579f77SDag-Erling Smørgrav if(net >= max) 661b7579f77SDag-Erling Smørgrav return; 662b7579f77SDag-Erling Smørgrav for(i=net/8+1; i<max/8; i++) { 663b7579f77SDag-Erling Smørgrav s[i] = 0; 664b7579f77SDag-Erling Smørgrav } 665b7579f77SDag-Erling Smørgrav s[net/8] &= mask[net&0x7]; 666b7579f77SDag-Erling Smørgrav } 667b7579f77SDag-Erling Smørgrav 668b7579f77SDag-Erling Smørgrav int 669b7579f77SDag-Erling Smørgrav addr_in_common(struct sockaddr_storage* addr1, int net1, 670b7579f77SDag-Erling Smørgrav struct sockaddr_storage* addr2, int net2, socklen_t addrlen) 671b7579f77SDag-Erling Smørgrav { 672b7579f77SDag-Erling Smørgrav int min = (net1<net2)?net1:net2; 673b7579f77SDag-Erling Smørgrav int i, to; 674b7579f77SDag-Erling Smørgrav int match = 0; 675b7579f77SDag-Erling Smørgrav uint8_t* s1, *s2; 676b7579f77SDag-Erling Smørgrav if(addr_is_ip6(addr1, addrlen)) { 677b7579f77SDag-Erling Smørgrav s1 = (uint8_t*)&((struct sockaddr_in6*)addr1)->sin6_addr; 678b7579f77SDag-Erling Smørgrav s2 = (uint8_t*)&((struct sockaddr_in6*)addr2)->sin6_addr; 679b7579f77SDag-Erling Smørgrav to = 16; 680b7579f77SDag-Erling Smørgrav } else { 681b7579f77SDag-Erling Smørgrav s1 = (uint8_t*)&((struct sockaddr_in*)addr1)->sin_addr; 682b7579f77SDag-Erling Smørgrav s2 = (uint8_t*)&((struct sockaddr_in*)addr2)->sin_addr; 683b7579f77SDag-Erling Smørgrav to = 4; 684b7579f77SDag-Erling Smørgrav } 685b7579f77SDag-Erling Smørgrav /* match = bits_in_common(s1, s2, to); */ 686b7579f77SDag-Erling Smørgrav for(i=0; i<to; i++) { 687b7579f77SDag-Erling Smørgrav if(s1[i] == s2[i]) { 688b7579f77SDag-Erling Smørgrav match += 8; 689b7579f77SDag-Erling Smørgrav } else { 690b7579f77SDag-Erling Smørgrav uint8_t z = s1[i]^s2[i]; 691b7579f77SDag-Erling Smørgrav log_assert(z); 692b7579f77SDag-Erling Smørgrav while(!(z&0x80)) { 693b7579f77SDag-Erling Smørgrav match++; 694b7579f77SDag-Erling Smørgrav z<<=1; 695b7579f77SDag-Erling Smørgrav } 696b7579f77SDag-Erling Smørgrav break; 697b7579f77SDag-Erling Smørgrav } 698b7579f77SDag-Erling Smørgrav } 699b7579f77SDag-Erling Smørgrav if(match > min) match = min; 700b7579f77SDag-Erling Smørgrav return match; 701b7579f77SDag-Erling Smørgrav } 702b7579f77SDag-Erling Smørgrav 703b7579f77SDag-Erling Smørgrav void 704b7579f77SDag-Erling Smørgrav addr_to_str(struct sockaddr_storage* addr, socklen_t addrlen, 705b7579f77SDag-Erling Smørgrav char* buf, size_t len) 706b7579f77SDag-Erling Smørgrav { 707b7579f77SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family; 708b7579f77SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 709b7579f77SDag-Erling Smørgrav if(addr_is_ip6(addr, addrlen)) 710b7579f77SDag-Erling Smørgrav sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; 711b7579f77SDag-Erling Smørgrav if(inet_ntop(af, sinaddr, buf, (socklen_t)len) == 0) { 712b7579f77SDag-Erling Smørgrav snprintf(buf, len, "(inet_ntop_error)"); 713b7579f77SDag-Erling Smørgrav } 714b7579f77SDag-Erling Smørgrav } 715b7579f77SDag-Erling Smørgrav 716b7579f77SDag-Erling Smørgrav int 717b7579f77SDag-Erling Smørgrav addr_is_ip4mapped(struct sockaddr_storage* addr, socklen_t addrlen) 718b7579f77SDag-Erling Smørgrav { 719b7579f77SDag-Erling Smørgrav /* prefix for ipv4 into ipv6 mapping is ::ffff:x.x.x.x */ 720b7579f77SDag-Erling Smørgrav const uint8_t map_prefix[16] = 721b7579f77SDag-Erling Smørgrav {0,0,0,0, 0,0,0,0, 0,0,0xff,0xff, 0,0,0,0}; 722b7579f77SDag-Erling Smørgrav uint8_t* s; 723b7579f77SDag-Erling Smørgrav if(!addr_is_ip6(addr, addrlen)) 724b7579f77SDag-Erling Smørgrav return 0; 725b7579f77SDag-Erling Smørgrav /* s is 16 octet ipv6 address string */ 726b7579f77SDag-Erling Smørgrav s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr; 727b7579f77SDag-Erling Smørgrav return (memcmp(s, map_prefix, 12) == 0); 728b7579f77SDag-Erling Smørgrav } 729b7579f77SDag-Erling Smørgrav 730b7579f77SDag-Erling Smørgrav int addr_is_broadcast(struct sockaddr_storage* addr, socklen_t addrlen) 731b7579f77SDag-Erling Smørgrav { 732b7579f77SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family; 733b7579f77SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 734b7579f77SDag-Erling Smørgrav return af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in) 735b7579f77SDag-Erling Smørgrav && memcmp(sinaddr, "\377\377\377\377", 4) == 0; 736b7579f77SDag-Erling Smørgrav } 737b7579f77SDag-Erling Smørgrav 738b7579f77SDag-Erling Smørgrav int addr_is_any(struct sockaddr_storage* addr, socklen_t addrlen) 739b7579f77SDag-Erling Smørgrav { 740b7579f77SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family; 741b7579f77SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 742b7579f77SDag-Erling Smørgrav void* sin6addr = &((struct sockaddr_in6*)addr)->sin6_addr; 743b7579f77SDag-Erling Smørgrav if(af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in) 744b7579f77SDag-Erling Smørgrav && memcmp(sinaddr, "\000\000\000\000", 4) == 0) 745b7579f77SDag-Erling Smørgrav return 1; 746b7579f77SDag-Erling Smørgrav else if(af==AF_INET6 && addrlen>=(socklen_t)sizeof(struct sockaddr_in6) 747b7579f77SDag-Erling Smørgrav && memcmp(sin6addr, "\000\000\000\000\000\000\000\000" 748b7579f77SDag-Erling Smørgrav "\000\000\000\000\000\000\000\000", 16) == 0) 749b7579f77SDag-Erling Smørgrav return 1; 750b7579f77SDag-Erling Smørgrav return 0; 751b7579f77SDag-Erling Smørgrav } 752b7579f77SDag-Erling Smørgrav 753b7579f77SDag-Erling Smørgrav void sock_list_insert(struct sock_list** list, struct sockaddr_storage* addr, 754b7579f77SDag-Erling Smørgrav socklen_t len, struct regional* region) 755b7579f77SDag-Erling Smørgrav { 756b7579f77SDag-Erling Smørgrav struct sock_list* add = (struct sock_list*)regional_alloc(region, 757b7579f77SDag-Erling Smørgrav sizeof(*add) - sizeof(add->addr) + (size_t)len); 758b7579f77SDag-Erling Smørgrav if(!add) { 759b7579f77SDag-Erling Smørgrav log_err("out of memory in socketlist insert"); 760b7579f77SDag-Erling Smørgrav return; 761b7579f77SDag-Erling Smørgrav } 762b7579f77SDag-Erling Smørgrav log_assert(list); 763b7579f77SDag-Erling Smørgrav add->next = *list; 764b7579f77SDag-Erling Smørgrav add->len = len; 765b7579f77SDag-Erling Smørgrav *list = add; 766b7579f77SDag-Erling Smørgrav if(len) memmove(&add->addr, addr, len); 767b7579f77SDag-Erling Smørgrav } 768b7579f77SDag-Erling Smørgrav 769b7579f77SDag-Erling Smørgrav void sock_list_prepend(struct sock_list** list, struct sock_list* add) 770b7579f77SDag-Erling Smørgrav { 771b7579f77SDag-Erling Smørgrav struct sock_list* last = add; 772b7579f77SDag-Erling Smørgrav if(!last) 773b7579f77SDag-Erling Smørgrav return; 774b7579f77SDag-Erling Smørgrav while(last->next) 775b7579f77SDag-Erling Smørgrav last = last->next; 776b7579f77SDag-Erling Smørgrav last->next = *list; 777b7579f77SDag-Erling Smørgrav *list = add; 778b7579f77SDag-Erling Smørgrav } 779b7579f77SDag-Erling Smørgrav 780b7579f77SDag-Erling Smørgrav int sock_list_find(struct sock_list* list, struct sockaddr_storage* addr, 781b7579f77SDag-Erling Smørgrav socklen_t len) 782b7579f77SDag-Erling Smørgrav { 783b7579f77SDag-Erling Smørgrav while(list) { 784b7579f77SDag-Erling Smørgrav if(len == list->len) { 785b7579f77SDag-Erling Smørgrav if(len == 0 || sockaddr_cmp_addr(addr, len, 786b7579f77SDag-Erling Smørgrav &list->addr, list->len) == 0) 787b7579f77SDag-Erling Smørgrav return 1; 788b7579f77SDag-Erling Smørgrav } 789b7579f77SDag-Erling Smørgrav list = list->next; 790b7579f77SDag-Erling Smørgrav } 791b7579f77SDag-Erling Smørgrav return 0; 792b7579f77SDag-Erling Smørgrav } 793b7579f77SDag-Erling Smørgrav 794b7579f77SDag-Erling Smørgrav void sock_list_merge(struct sock_list** list, struct regional* region, 795b7579f77SDag-Erling Smørgrav struct sock_list* add) 796b7579f77SDag-Erling Smørgrav { 797b7579f77SDag-Erling Smørgrav struct sock_list* p; 798b7579f77SDag-Erling Smørgrav for(p=add; p; p=p->next) { 799b7579f77SDag-Erling Smørgrav if(!sock_list_find(*list, &p->addr, p->len)) 800b7579f77SDag-Erling Smørgrav sock_list_insert(list, &p->addr, p->len, region); 801b7579f77SDag-Erling Smørgrav } 802b7579f77SDag-Erling Smørgrav } 803b7579f77SDag-Erling Smørgrav 804b7579f77SDag-Erling Smørgrav void 805b7579f77SDag-Erling Smørgrav log_crypto_err(const char* str) 806b7579f77SDag-Erling Smørgrav { 8078ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL 8080eefd307SCy Schubert log_crypto_err_code(str, ERR_get_error()); 8090eefd307SCy Schubert #else 8100eefd307SCy Schubert (void)str; 8110eefd307SCy Schubert #endif /* HAVE_SSL */ 8120eefd307SCy Schubert } 8130eefd307SCy Schubert 8140eefd307SCy Schubert void log_crypto_err_code(const char* str, unsigned long err) 8150eefd307SCy Schubert { 8160eefd307SCy Schubert #ifdef HAVE_SSL 817b7579f77SDag-Erling Smørgrav /* error:[error code]:[library name]:[function name]:[reason string] */ 818b7579f77SDag-Erling Smørgrav char buf[128]; 819b7579f77SDag-Erling Smørgrav unsigned long e; 8200eefd307SCy Schubert ERR_error_string_n(err, buf, sizeof(buf)); 821b7579f77SDag-Erling Smørgrav log_err("%s crypto %s", str, buf); 822b7579f77SDag-Erling Smørgrav while( (e=ERR_get_error()) ) { 823b7579f77SDag-Erling Smørgrav ERR_error_string_n(e, buf, sizeof(buf)); 824b7579f77SDag-Erling Smørgrav log_err("and additionally crypto %s", buf); 825b7579f77SDag-Erling Smørgrav } 8268ed2b524SDag-Erling Smørgrav #else 8278ed2b524SDag-Erling Smørgrav (void)str; 8280eefd307SCy Schubert (void)err; 8298ed2b524SDag-Erling Smørgrav #endif /* HAVE_SSL */ 830b7579f77SDag-Erling Smørgrav } 831b7579f77SDag-Erling Smørgrav 832971980c3SDag-Erling Smørgrav int 833971980c3SDag-Erling Smørgrav listen_sslctx_setup(void* ctxt) 834971980c3SDag-Erling Smørgrav { 835971980c3SDag-Erling Smørgrav #ifdef HAVE_SSL 836971980c3SDag-Erling Smørgrav SSL_CTX* ctx = (SSL_CTX*)ctxt; 837971980c3SDag-Erling Smørgrav /* no SSLv2, SSLv3 because has defects */ 838*091e9e46SCy Schubert #if SSL_OP_NO_SSLv2 != 0 839971980c3SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2) 840971980c3SDag-Erling Smørgrav != SSL_OP_NO_SSLv2){ 841971980c3SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_NO_SSLv2"); 842971980c3SDag-Erling Smørgrav return 0; 843971980c3SDag-Erling Smørgrav } 844*091e9e46SCy Schubert #endif 845971980c3SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3) 846971980c3SDag-Erling Smørgrav != SSL_OP_NO_SSLv3){ 847971980c3SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_NO_SSLv3"); 848971980c3SDag-Erling Smørgrav return 0; 849971980c3SDag-Erling Smørgrav } 850971980c3SDag-Erling Smørgrav #if defined(SSL_OP_NO_TLSv1) && defined(SSL_OP_NO_TLSv1_1) 851971980c3SDag-Erling Smørgrav /* if we have tls 1.1 disable 1.0 */ 852971980c3SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1) & SSL_OP_NO_TLSv1) 853971980c3SDag-Erling Smørgrav != SSL_OP_NO_TLSv1){ 854971980c3SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_NO_TLSv1"); 855971980c3SDag-Erling Smørgrav return 0; 856971980c3SDag-Erling Smørgrav } 857971980c3SDag-Erling Smørgrav #endif 858971980c3SDag-Erling Smørgrav #if defined(SSL_OP_NO_TLSv1_1) && defined(SSL_OP_NO_TLSv1_2) 859971980c3SDag-Erling Smørgrav /* if we have tls 1.2 disable 1.1 */ 860971980c3SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_1) & SSL_OP_NO_TLSv1_1) 861971980c3SDag-Erling Smørgrav != SSL_OP_NO_TLSv1_1){ 862971980c3SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_NO_TLSv1_1"); 863971980c3SDag-Erling Smørgrav return 0; 864971980c3SDag-Erling Smørgrav } 865971980c3SDag-Erling Smørgrav #endif 8660eefd307SCy Schubert #if defined(SSL_OP_NO_RENEGOTIATION) 8670eefd307SCy Schubert /* disable client renegotiation */ 8680eefd307SCy Schubert if((SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION) & 8690eefd307SCy Schubert SSL_OP_NO_RENEGOTIATION) != SSL_OP_NO_RENEGOTIATION) { 8700eefd307SCy Schubert log_crypto_err("could not set SSL_OP_NO_RENEGOTIATION"); 8710eefd307SCy Schubert return 0; 8720eefd307SCy Schubert } 8730eefd307SCy Schubert #endif 874971980c3SDag-Erling Smørgrav #if defined(SHA256_DIGEST_LENGTH) && defined(USE_ECDSA) 875971980c3SDag-Erling Smørgrav /* if we have sha256, set the cipher list to have no known vulns */ 87657bddd21SDag-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")) 877971980c3SDag-Erling Smørgrav log_crypto_err("could not set cipher list with SSL_CTX_set_cipher_list"); 878971980c3SDag-Erling Smørgrav #endif 879971980c3SDag-Erling Smørgrav 880971980c3SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE) & 881971980c3SDag-Erling Smørgrav SSL_OP_CIPHER_SERVER_PREFERENCE) != 882971980c3SDag-Erling Smørgrav SSL_OP_CIPHER_SERVER_PREFERENCE) { 883971980c3SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_CIPHER_SERVER_PREFERENCE"); 884971980c3SDag-Erling Smørgrav return 0; 885971980c3SDag-Erling Smørgrav } 886971980c3SDag-Erling Smørgrav 887971980c3SDag-Erling Smørgrav #ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL 888971980c3SDag-Erling Smørgrav SSL_CTX_set_security_level(ctx, 0); 889971980c3SDag-Erling Smørgrav #endif 890971980c3SDag-Erling Smørgrav #else 891971980c3SDag-Erling Smørgrav (void)ctxt; 892971980c3SDag-Erling Smørgrav #endif /* HAVE_SSL */ 893971980c3SDag-Erling Smørgrav return 1; 894971980c3SDag-Erling Smørgrav } 895971980c3SDag-Erling Smørgrav 896971980c3SDag-Erling Smørgrav void 897971980c3SDag-Erling Smørgrav listen_sslctx_setup_2(void* ctxt) 898971980c3SDag-Erling Smørgrav { 899971980c3SDag-Erling Smørgrav #ifdef HAVE_SSL 900971980c3SDag-Erling Smørgrav SSL_CTX* ctx = (SSL_CTX*)ctxt; 901971980c3SDag-Erling Smørgrav (void)ctx; 902971980c3SDag-Erling Smørgrav #if HAVE_DECL_SSL_CTX_SET_ECDH_AUTO 903971980c3SDag-Erling Smørgrav if(!SSL_CTX_set_ecdh_auto(ctx,1)) { 904971980c3SDag-Erling Smørgrav log_crypto_err("Error in SSL_CTX_ecdh_auto, not enabling ECDHE"); 905971980c3SDag-Erling Smørgrav } 906971980c3SDag-Erling Smørgrav #elif defined(USE_ECDSA) 907971980c3SDag-Erling Smørgrav if(1) { 908971980c3SDag-Erling Smørgrav EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1); 909971980c3SDag-Erling Smørgrav if (!ecdh) { 910971980c3SDag-Erling Smørgrav log_crypto_err("could not find p256, not enabling ECDHE"); 911971980c3SDag-Erling Smørgrav } else { 912971980c3SDag-Erling Smørgrav if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh)) { 913971980c3SDag-Erling Smørgrav log_crypto_err("Error in SSL_CTX_set_tmp_ecdh, not enabling ECDHE"); 914971980c3SDag-Erling Smørgrav } 915971980c3SDag-Erling Smørgrav EC_KEY_free (ecdh); 916971980c3SDag-Erling Smørgrav } 917971980c3SDag-Erling Smørgrav } 918971980c3SDag-Erling Smørgrav #endif 919971980c3SDag-Erling Smørgrav #else 920971980c3SDag-Erling Smørgrav (void)ctxt; 921971980c3SDag-Erling Smørgrav #endif /* HAVE_SSL */ 922971980c3SDag-Erling Smørgrav } 923971980c3SDag-Erling Smørgrav 924b7579f77SDag-Erling Smørgrav void* listen_sslctx_create(char* key, char* pem, char* verifypem) 925b7579f77SDag-Erling Smørgrav { 9268ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL 927b7579f77SDag-Erling Smørgrav SSL_CTX* ctx = SSL_CTX_new(SSLv23_server_method()); 928b7579f77SDag-Erling Smørgrav if(!ctx) { 929b7579f77SDag-Erling Smørgrav log_crypto_err("could not SSL_CTX_new"); 930b7579f77SDag-Erling Smørgrav return NULL; 931b7579f77SDag-Erling Smørgrav } 932e86b9096SDag-Erling Smørgrav if(!key || key[0] == 0) { 933e86b9096SDag-Erling Smørgrav log_err("error: no tls-service-key file specified"); 934e86b9096SDag-Erling Smørgrav SSL_CTX_free(ctx); 935e86b9096SDag-Erling Smørgrav return NULL; 936e86b9096SDag-Erling Smørgrav } 937e86b9096SDag-Erling Smørgrav if(!pem || pem[0] == 0) { 938e86b9096SDag-Erling Smørgrav log_err("error: no tls-service-pem file specified"); 939e86b9096SDag-Erling Smørgrav SSL_CTX_free(ctx); 940e86b9096SDag-Erling Smørgrav return NULL; 941e86b9096SDag-Erling Smørgrav } 942971980c3SDag-Erling Smørgrav if(!listen_sslctx_setup(ctx)) { 943ff825849SDag-Erling Smørgrav SSL_CTX_free(ctx); 944ff825849SDag-Erling Smørgrav return NULL; 945ff825849SDag-Erling Smørgrav } 946b75612f8SDag-Erling Smørgrav if(!SSL_CTX_use_certificate_chain_file(ctx, pem)) { 947b7579f77SDag-Erling Smørgrav log_err("error for cert file: %s", pem); 948b75612f8SDag-Erling Smørgrav log_crypto_err("error in SSL_CTX use_certificate_chain_file"); 949b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 950b7579f77SDag-Erling Smørgrav return NULL; 951b7579f77SDag-Erling Smørgrav } 952b7579f77SDag-Erling Smørgrav if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) { 953b7579f77SDag-Erling Smørgrav log_err("error for private key file: %s", key); 954b7579f77SDag-Erling Smørgrav log_crypto_err("Error in SSL_CTX use_PrivateKey_file"); 955b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 956b7579f77SDag-Erling Smørgrav return NULL; 957b7579f77SDag-Erling Smørgrav } 958b7579f77SDag-Erling Smørgrav if(!SSL_CTX_check_private_key(ctx)) { 959b7579f77SDag-Erling Smørgrav log_err("error for key file: %s", key); 960b7579f77SDag-Erling Smørgrav log_crypto_err("Error in SSL_CTX check_private_key"); 961b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 962b7579f77SDag-Erling Smørgrav return NULL; 963b7579f77SDag-Erling Smørgrav } 964971980c3SDag-Erling Smørgrav listen_sslctx_setup_2(ctx); 965b7579f77SDag-Erling Smørgrav if(verifypem && verifypem[0]) { 966b7579f77SDag-Erling Smørgrav if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) { 967b7579f77SDag-Erling Smørgrav log_crypto_err("Error in SSL_CTX verify locations"); 968b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 969b7579f77SDag-Erling Smørgrav return NULL; 970b7579f77SDag-Erling Smørgrav } 971b7579f77SDag-Erling Smørgrav SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file( 972b7579f77SDag-Erling Smørgrav verifypem)); 973b7579f77SDag-Erling Smørgrav SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); 974b7579f77SDag-Erling Smørgrav } 975b7579f77SDag-Erling Smørgrav return ctx; 9768ed2b524SDag-Erling Smørgrav #else 9778ed2b524SDag-Erling Smørgrav (void)key; (void)pem; (void)verifypem; 9788ed2b524SDag-Erling Smørgrav return NULL; 9798ed2b524SDag-Erling Smørgrav #endif 980b7579f77SDag-Erling Smørgrav } 981b7579f77SDag-Erling Smørgrav 9823bd4df0aSDag-Erling Smørgrav #ifdef USE_WINSOCK 9833bd4df0aSDag-Erling Smørgrav /* For windows, the CA trust store is not read by openssl. 9843bd4df0aSDag-Erling Smørgrav Add code to open the trust store using wincrypt API and add 9853bd4df0aSDag-Erling Smørgrav the root certs into openssl trust store */ 9863bd4df0aSDag-Erling Smørgrav static int 9873bd4df0aSDag-Erling Smørgrav add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx) 9883bd4df0aSDag-Erling Smørgrav { 9893bd4df0aSDag-Erling Smørgrav HCERTSTORE hSystemStore; 9903bd4df0aSDag-Erling Smørgrav PCCERT_CONTEXT pTargetCert = NULL; 9913bd4df0aSDag-Erling Smørgrav X509_STORE* store; 9923bd4df0aSDag-Erling Smørgrav 9933bd4df0aSDag-Erling Smørgrav verbose(VERB_ALGO, "Adding Windows certificates from system root store to CA store"); 9943bd4df0aSDag-Erling Smørgrav 9953bd4df0aSDag-Erling Smørgrav /* load just once per context lifetime for this version 9963bd4df0aSDag-Erling Smørgrav TODO: dynamically update CA trust changes as they are available */ 9973bd4df0aSDag-Erling Smørgrav if (!tls_ctx) 9983bd4df0aSDag-Erling Smørgrav return 0; 9993bd4df0aSDag-Erling Smørgrav 10003bd4df0aSDag-Erling Smørgrav /* Call wincrypt's CertOpenStore to open the CA root store. */ 10013bd4df0aSDag-Erling Smørgrav 10023bd4df0aSDag-Erling Smørgrav if ((hSystemStore = CertOpenStore( 10033bd4df0aSDag-Erling Smørgrav CERT_STORE_PROV_SYSTEM, 10043bd4df0aSDag-Erling Smørgrav 0, 10053bd4df0aSDag-Erling Smørgrav 0, 10063bd4df0aSDag-Erling Smørgrav /* NOTE: mingw does not have this const: replace with 1 << 16 from code 10073bd4df0aSDag-Erling Smørgrav CERT_SYSTEM_STORE_CURRENT_USER, */ 10083bd4df0aSDag-Erling Smørgrav 1 << 16, 10093bd4df0aSDag-Erling Smørgrav L"root")) == 0) 10103bd4df0aSDag-Erling Smørgrav { 10113bd4df0aSDag-Erling Smørgrav return 0; 10123bd4df0aSDag-Erling Smørgrav } 10133bd4df0aSDag-Erling Smørgrav 10143bd4df0aSDag-Erling Smørgrav store = SSL_CTX_get_cert_store(tls_ctx); 10153bd4df0aSDag-Erling Smørgrav if (!store) 10163bd4df0aSDag-Erling Smørgrav return 0; 10173bd4df0aSDag-Erling Smørgrav 10183bd4df0aSDag-Erling Smørgrav /* failure if the CA store is empty or the call fails */ 10193bd4df0aSDag-Erling Smørgrav if ((pTargetCert = CertEnumCertificatesInStore( 10203bd4df0aSDag-Erling Smørgrav hSystemStore, pTargetCert)) == 0) { 10213bd4df0aSDag-Erling Smørgrav verbose(VERB_ALGO, "CA certificate store for Windows is empty."); 10223bd4df0aSDag-Erling Smørgrav return 0; 10233bd4df0aSDag-Erling Smørgrav } 10243bd4df0aSDag-Erling Smørgrav /* iterate over the windows cert store and add to openssl store */ 10253bd4df0aSDag-Erling Smørgrav do 10263bd4df0aSDag-Erling Smørgrav { 10273bd4df0aSDag-Erling Smørgrav X509 *cert1 = d2i_X509(NULL, 10283bd4df0aSDag-Erling Smørgrav (const unsigned char **)&pTargetCert->pbCertEncoded, 10293bd4df0aSDag-Erling Smørgrav pTargetCert->cbCertEncoded); 10303bd4df0aSDag-Erling Smørgrav if (!cert1) { 10313bd4df0aSDag-Erling Smørgrav /* return error if a cert fails */ 10323bd4df0aSDag-Erling Smørgrav verbose(VERB_ALGO, "%s %d:%s", 10333bd4df0aSDag-Erling Smørgrav "Unable to parse certificate in memory", 10343bd4df0aSDag-Erling Smørgrav (int)ERR_get_error(), ERR_error_string(ERR_get_error(), NULL)); 10353bd4df0aSDag-Erling Smørgrav return 0; 10363bd4df0aSDag-Erling Smørgrav } 10373bd4df0aSDag-Erling Smørgrav else { 10383bd4df0aSDag-Erling Smørgrav /* return error if a cert add to store fails */ 10393bd4df0aSDag-Erling Smørgrav if (X509_STORE_add_cert(store, cert1) == 0) { 10403bd4df0aSDag-Erling Smørgrav unsigned long error = ERR_peek_last_error(); 10413bd4df0aSDag-Erling Smørgrav 10423bd4df0aSDag-Erling Smørgrav /* Ignore error X509_R_CERT_ALREADY_IN_HASH_TABLE which means the 10433bd4df0aSDag-Erling Smørgrav * certificate is already in the store. */ 10443bd4df0aSDag-Erling Smørgrav if(ERR_GET_LIB(error) != ERR_LIB_X509 || 10453bd4df0aSDag-Erling Smørgrav ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) { 10463bd4df0aSDag-Erling Smørgrav verbose(VERB_ALGO, "%s %d:%s\n", 10473bd4df0aSDag-Erling Smørgrav "Error adding certificate", (int)ERR_get_error(), 10483bd4df0aSDag-Erling Smørgrav ERR_error_string(ERR_get_error(), NULL)); 10493bd4df0aSDag-Erling Smørgrav X509_free(cert1); 10503bd4df0aSDag-Erling Smørgrav return 0; 10513bd4df0aSDag-Erling Smørgrav } 10523bd4df0aSDag-Erling Smørgrav } 10533bd4df0aSDag-Erling Smørgrav X509_free(cert1); 10543bd4df0aSDag-Erling Smørgrav } 10553bd4df0aSDag-Erling Smørgrav } while ((pTargetCert = CertEnumCertificatesInStore( 10563bd4df0aSDag-Erling Smørgrav hSystemStore, pTargetCert)) != 0); 10573bd4df0aSDag-Erling Smørgrav 10583bd4df0aSDag-Erling Smørgrav /* Clean up memory and quit. */ 10593bd4df0aSDag-Erling Smørgrav if (pTargetCert) 10603bd4df0aSDag-Erling Smørgrav CertFreeCertificateContext(pTargetCert); 10613bd4df0aSDag-Erling Smørgrav if (hSystemStore) 10623bd4df0aSDag-Erling Smørgrav { 10633bd4df0aSDag-Erling Smørgrav if (!CertCloseStore( 10643bd4df0aSDag-Erling Smørgrav hSystemStore, 0)) 10653bd4df0aSDag-Erling Smørgrav return 0; 10663bd4df0aSDag-Erling Smørgrav } 10673bd4df0aSDag-Erling Smørgrav verbose(VERB_ALGO, "Completed adding Windows certificates to CA store successfully"); 10683bd4df0aSDag-Erling Smørgrav return 1; 10693bd4df0aSDag-Erling Smørgrav } 10703bd4df0aSDag-Erling Smørgrav #endif /* USE_WINSOCK */ 10713bd4df0aSDag-Erling Smørgrav 10723bd4df0aSDag-Erling Smørgrav void* connect_sslctx_create(char* key, char* pem, char* verifypem, int wincert) 1073b7579f77SDag-Erling Smørgrav { 10748ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL 1075b7579f77SDag-Erling Smørgrav SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method()); 1076b7579f77SDag-Erling Smørgrav if(!ctx) { 1077b7579f77SDag-Erling Smørgrav log_crypto_err("could not allocate SSL_CTX pointer"); 1078b7579f77SDag-Erling Smørgrav return NULL; 1079b7579f77SDag-Erling Smørgrav } 1080*091e9e46SCy Schubert #if SSL_OP_NO_SSLv2 != 0 108105ab2901SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2) 108205ab2901SDag-Erling Smørgrav != SSL_OP_NO_SSLv2) { 1083b7579f77SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_NO_SSLv2"); 1084b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 1085b7579f77SDag-Erling Smørgrav return NULL; 1086b7579f77SDag-Erling Smørgrav } 1087*091e9e46SCy Schubert #endif 108805ab2901SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3) 108905ab2901SDag-Erling Smørgrav != SSL_OP_NO_SSLv3) { 1090ff825849SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_NO_SSLv3"); 1091ff825849SDag-Erling Smørgrav SSL_CTX_free(ctx); 1092ff825849SDag-Erling Smørgrav return NULL; 1093ff825849SDag-Erling Smørgrav } 10940eefd307SCy Schubert #if defined(SSL_OP_NO_RENEGOTIATION) 10950eefd307SCy Schubert /* disable client renegotiation */ 10960eefd307SCy Schubert if((SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION) & 10970eefd307SCy Schubert SSL_OP_NO_RENEGOTIATION) != SSL_OP_NO_RENEGOTIATION) { 10980eefd307SCy Schubert log_crypto_err("could not set SSL_OP_NO_RENEGOTIATION"); 10990eefd307SCy Schubert return 0; 11000eefd307SCy Schubert } 11010eefd307SCy Schubert #endif 1102b7579f77SDag-Erling Smørgrav if(key && key[0]) { 1103b75612f8SDag-Erling Smørgrav if(!SSL_CTX_use_certificate_chain_file(ctx, pem)) { 1104b7579f77SDag-Erling Smørgrav log_err("error in client certificate %s", pem); 1105b7579f77SDag-Erling Smørgrav log_crypto_err("error in certificate file"); 1106b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 1107b7579f77SDag-Erling Smørgrav return NULL; 1108b7579f77SDag-Erling Smørgrav } 1109b7579f77SDag-Erling Smørgrav if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) { 1110b7579f77SDag-Erling Smørgrav log_err("error in client private key %s", key); 1111b7579f77SDag-Erling Smørgrav log_crypto_err("error in key file"); 1112b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 1113b7579f77SDag-Erling Smørgrav return NULL; 1114b7579f77SDag-Erling Smørgrav } 1115b7579f77SDag-Erling Smørgrav if(!SSL_CTX_check_private_key(ctx)) { 1116b7579f77SDag-Erling Smørgrav log_err("error in client key %s", key); 1117b7579f77SDag-Erling Smørgrav log_crypto_err("error in SSL_CTX_check_private_key"); 1118b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 1119b7579f77SDag-Erling Smørgrav return NULL; 1120b7579f77SDag-Erling Smørgrav } 1121b7579f77SDag-Erling Smørgrav } 11223bd4df0aSDag-Erling Smørgrav if((verifypem && verifypem[0]) || wincert) { 1123b7579f77SDag-Erling Smørgrav if(verifypem && verifypem[0]) { 1124ff825849SDag-Erling Smørgrav if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) { 1125b7579f77SDag-Erling Smørgrav log_crypto_err("error in SSL_CTX verify"); 1126b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 1127b7579f77SDag-Erling Smørgrav return NULL; 1128b7579f77SDag-Erling Smørgrav } 11293bd4df0aSDag-Erling Smørgrav } 11303bd4df0aSDag-Erling Smørgrav #ifdef USE_WINSOCK 11313bd4df0aSDag-Erling Smørgrav if(wincert) { 11323bd4df0aSDag-Erling Smørgrav if(!add_WIN_cacerts_to_openssl_store(ctx)) { 11333bd4df0aSDag-Erling Smørgrav log_crypto_err("error in add_WIN_cacerts_to_openssl_store"); 11343bd4df0aSDag-Erling Smørgrav SSL_CTX_free(ctx); 11353bd4df0aSDag-Erling Smørgrav return NULL; 11363bd4df0aSDag-Erling Smørgrav } 11373bd4df0aSDag-Erling Smørgrav } 11383bd4df0aSDag-Erling Smørgrav #else 11393bd4df0aSDag-Erling Smørgrav (void)wincert; 11403bd4df0aSDag-Erling Smørgrav #endif 1141b7579f77SDag-Erling Smørgrav SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); 1142b7579f77SDag-Erling Smørgrav } 1143b7579f77SDag-Erling Smørgrav return ctx; 11448ed2b524SDag-Erling Smørgrav #else 11453bd4df0aSDag-Erling Smørgrav (void)key; (void)pem; (void)verifypem; (void)wincert; 11468ed2b524SDag-Erling Smørgrav return NULL; 11478ed2b524SDag-Erling Smørgrav #endif 1148b7579f77SDag-Erling Smørgrav } 1149b7579f77SDag-Erling Smørgrav 1150b7579f77SDag-Erling Smørgrav void* incoming_ssl_fd(void* sslctx, int fd) 1151b7579f77SDag-Erling Smørgrav { 11528ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL 1153b7579f77SDag-Erling Smørgrav SSL* ssl = SSL_new((SSL_CTX*)sslctx); 1154b7579f77SDag-Erling Smørgrav if(!ssl) { 1155b7579f77SDag-Erling Smørgrav log_crypto_err("could not SSL_new"); 1156b7579f77SDag-Erling Smørgrav return NULL; 1157b7579f77SDag-Erling Smørgrav } 1158b7579f77SDag-Erling Smørgrav SSL_set_accept_state(ssl); 11590eefd307SCy Schubert (void)SSL_set_mode(ssl, (long)SSL_MODE_AUTO_RETRY); 1160b7579f77SDag-Erling Smørgrav if(!SSL_set_fd(ssl, fd)) { 1161b7579f77SDag-Erling Smørgrav log_crypto_err("could not SSL_set_fd"); 1162b7579f77SDag-Erling Smørgrav SSL_free(ssl); 1163b7579f77SDag-Erling Smørgrav return NULL; 1164b7579f77SDag-Erling Smørgrav } 1165b7579f77SDag-Erling Smørgrav return ssl; 11668ed2b524SDag-Erling Smørgrav #else 11678ed2b524SDag-Erling Smørgrav (void)sslctx; (void)fd; 11688ed2b524SDag-Erling Smørgrav return NULL; 11698ed2b524SDag-Erling Smørgrav #endif 1170b7579f77SDag-Erling Smørgrav } 1171b7579f77SDag-Erling Smørgrav 1172b7579f77SDag-Erling Smørgrav void* outgoing_ssl_fd(void* sslctx, int fd) 1173b7579f77SDag-Erling Smørgrav { 11748ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL 1175b7579f77SDag-Erling Smørgrav SSL* ssl = SSL_new((SSL_CTX*)sslctx); 1176b7579f77SDag-Erling Smørgrav if(!ssl) { 1177b7579f77SDag-Erling Smørgrav log_crypto_err("could not SSL_new"); 1178b7579f77SDag-Erling Smørgrav return NULL; 1179b7579f77SDag-Erling Smørgrav } 1180b7579f77SDag-Erling Smørgrav SSL_set_connect_state(ssl); 11810eefd307SCy Schubert (void)SSL_set_mode(ssl, (long)SSL_MODE_AUTO_RETRY); 1182b7579f77SDag-Erling Smørgrav if(!SSL_set_fd(ssl, fd)) { 1183b7579f77SDag-Erling Smørgrav log_crypto_err("could not SSL_set_fd"); 1184b7579f77SDag-Erling Smørgrav SSL_free(ssl); 1185b7579f77SDag-Erling Smørgrav return NULL; 1186b7579f77SDag-Erling Smørgrav } 1187b7579f77SDag-Erling Smørgrav return ssl; 11888ed2b524SDag-Erling Smørgrav #else 11898ed2b524SDag-Erling Smørgrav (void)sslctx; (void)fd; 11908ed2b524SDag-Erling Smørgrav return NULL; 11918ed2b524SDag-Erling Smørgrav #endif 1192b7579f77SDag-Erling Smørgrav } 11938ed2b524SDag-Erling Smørgrav 1194b5663de9SDag-Erling Smørgrav #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L 11958ed2b524SDag-Erling Smørgrav /** global lock list for openssl locks */ 11963005e0a3SDag-Erling Smørgrav static lock_basic_type *ub_openssl_locks = NULL; 11978ed2b524SDag-Erling Smørgrav 11988ed2b524SDag-Erling Smørgrav /** callback that gets thread id for openssl */ 1199e86b9096SDag-Erling Smørgrav #ifdef HAVE_CRYPTO_THREADID_SET_CALLBACK 1200e86b9096SDag-Erling Smørgrav static void 1201e86b9096SDag-Erling Smørgrav ub_crypto_id_cb(CRYPTO_THREADID *id) 1202e86b9096SDag-Erling Smørgrav { 1203e86b9096SDag-Erling Smørgrav CRYPTO_THREADID_set_numeric(id, (unsigned long)log_thread_get()); 1204e86b9096SDag-Erling Smørgrav } 1205e86b9096SDag-Erling Smørgrav #else 12068ed2b524SDag-Erling Smørgrav static unsigned long 12078ed2b524SDag-Erling Smørgrav ub_crypto_id_cb(void) 12088ed2b524SDag-Erling Smørgrav { 120909a3aaf3SDag-Erling Smørgrav return (unsigned long)log_thread_get(); 12108ed2b524SDag-Erling Smørgrav } 1211e86b9096SDag-Erling Smørgrav #endif 12128ed2b524SDag-Erling Smørgrav 12138ed2b524SDag-Erling Smørgrav static void 12148ed2b524SDag-Erling Smørgrav ub_crypto_lock_cb(int mode, int type, const char *ATTR_UNUSED(file), 12158ed2b524SDag-Erling Smørgrav int ATTR_UNUSED(line)) 12168ed2b524SDag-Erling Smørgrav { 12178ed2b524SDag-Erling Smørgrav if((mode&CRYPTO_LOCK)) { 12188ed2b524SDag-Erling Smørgrav lock_basic_lock(&ub_openssl_locks[type]); 12198ed2b524SDag-Erling Smørgrav } else { 12208ed2b524SDag-Erling Smørgrav lock_basic_unlock(&ub_openssl_locks[type]); 12218ed2b524SDag-Erling Smørgrav } 12228ed2b524SDag-Erling Smørgrav } 12238ed2b524SDag-Erling Smørgrav #endif /* OPENSSL_THREADS */ 12248ed2b524SDag-Erling Smørgrav 12258ed2b524SDag-Erling Smørgrav int ub_openssl_lock_init(void) 12268ed2b524SDag-Erling Smørgrav { 1227b5663de9SDag-Erling Smørgrav #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L 12288ed2b524SDag-Erling Smørgrav int i; 12293005e0a3SDag-Erling Smørgrav ub_openssl_locks = (lock_basic_type*)reallocarray( 12303005e0a3SDag-Erling Smørgrav NULL, (size_t)CRYPTO_num_locks(), sizeof(lock_basic_type)); 12318ed2b524SDag-Erling Smørgrav if(!ub_openssl_locks) 12328ed2b524SDag-Erling Smørgrav return 0; 12338ed2b524SDag-Erling Smørgrav for(i=0; i<CRYPTO_num_locks(); i++) { 12348ed2b524SDag-Erling Smørgrav lock_basic_init(&ub_openssl_locks[i]); 12358ed2b524SDag-Erling Smørgrav } 1236e86b9096SDag-Erling Smørgrav # ifdef HAVE_CRYPTO_THREADID_SET_CALLBACK 1237e86b9096SDag-Erling Smørgrav CRYPTO_THREADID_set_callback(&ub_crypto_id_cb); 1238e86b9096SDag-Erling Smørgrav # else 12398ed2b524SDag-Erling Smørgrav CRYPTO_set_id_callback(&ub_crypto_id_cb); 1240e86b9096SDag-Erling Smørgrav # endif 12418ed2b524SDag-Erling Smørgrav CRYPTO_set_locking_callback(&ub_crypto_lock_cb); 12428ed2b524SDag-Erling Smørgrav #endif /* OPENSSL_THREADS */ 12438ed2b524SDag-Erling Smørgrav return 1; 12448ed2b524SDag-Erling Smørgrav } 12458ed2b524SDag-Erling Smørgrav 12468ed2b524SDag-Erling Smørgrav void ub_openssl_lock_delete(void) 12478ed2b524SDag-Erling Smørgrav { 1248b5663de9SDag-Erling Smørgrav #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L 12498ed2b524SDag-Erling Smørgrav int i; 12508ed2b524SDag-Erling Smørgrav if(!ub_openssl_locks) 12518ed2b524SDag-Erling Smørgrav return; 1252e86b9096SDag-Erling Smørgrav # ifdef HAVE_CRYPTO_THREADID_SET_CALLBACK 1253e86b9096SDag-Erling Smørgrav CRYPTO_THREADID_set_callback(NULL); 1254e86b9096SDag-Erling Smørgrav # else 12558ed2b524SDag-Erling Smørgrav CRYPTO_set_id_callback(NULL); 1256e86b9096SDag-Erling Smørgrav # endif 12578ed2b524SDag-Erling Smørgrav CRYPTO_set_locking_callback(NULL); 12588ed2b524SDag-Erling Smørgrav for(i=0; i<CRYPTO_num_locks(); i++) { 12598ed2b524SDag-Erling Smørgrav lock_basic_destroy(&ub_openssl_locks[i]); 12608ed2b524SDag-Erling Smørgrav } 12618ed2b524SDag-Erling Smørgrav free(ub_openssl_locks); 12628ed2b524SDag-Erling Smørgrav #endif /* OPENSSL_THREADS */ 12638ed2b524SDag-Erling Smørgrav } 12648ed2b524SDag-Erling Smørgrav 1265e86b9096SDag-Erling Smørgrav int listen_sslctx_setup_ticket_keys(void* sslctx, struct config_strlist* tls_session_ticket_keys) { 1266e86b9096SDag-Erling Smørgrav #ifdef HAVE_SSL 1267e86b9096SDag-Erling Smørgrav size_t s = 1; 1268e86b9096SDag-Erling Smørgrav struct config_strlist* p; 1269e86b9096SDag-Erling Smørgrav struct tls_session_ticket_key *keys; 1270e86b9096SDag-Erling Smørgrav for(p = tls_session_ticket_keys; p; p = p->next) { 1271e86b9096SDag-Erling Smørgrav s++; 1272e86b9096SDag-Erling Smørgrav } 1273e86b9096SDag-Erling Smørgrav keys = calloc(s, sizeof(struct tls_session_ticket_key)); 1274*091e9e46SCy Schubert if(!keys) 1275*091e9e46SCy Schubert return 0; 1276e86b9096SDag-Erling Smørgrav memset(keys, 0, s*sizeof(*keys)); 1277e86b9096SDag-Erling Smørgrav ticket_keys = keys; 1278e86b9096SDag-Erling Smørgrav 1279e86b9096SDag-Erling Smørgrav for(p = tls_session_ticket_keys; p; p = p->next) { 1280e86b9096SDag-Erling Smørgrav size_t n; 1281*091e9e46SCy Schubert unsigned char *data; 1282*091e9e46SCy Schubert FILE *f; 1283*091e9e46SCy Schubert 1284*091e9e46SCy Schubert data = (unsigned char *)malloc(80); 1285*091e9e46SCy Schubert if(!data) 1286*091e9e46SCy Schubert return 0; 1287*091e9e46SCy Schubert 1288*091e9e46SCy Schubert f = fopen(p->str, "r"); 1289e86b9096SDag-Erling Smørgrav if(!f) { 1290e86b9096SDag-Erling Smørgrav log_err("could not read tls-session-ticket-key %s: %s", p->str, strerror(errno)); 1291e86b9096SDag-Erling Smørgrav free(data); 1292e86b9096SDag-Erling Smørgrav return 0; 1293e86b9096SDag-Erling Smørgrav } 1294e86b9096SDag-Erling Smørgrav n = fread(data, 1, 80, f); 1295e86b9096SDag-Erling Smørgrav fclose(f); 1296e86b9096SDag-Erling Smørgrav 1297e86b9096SDag-Erling Smørgrav if(n != 80) { 1298e86b9096SDag-Erling Smørgrav log_err("tls-session-ticket-key %s is %d bytes, must be 80 bytes", p->str, (int)n); 1299e86b9096SDag-Erling Smørgrav free(data); 1300e86b9096SDag-Erling Smørgrav return 0; 1301e86b9096SDag-Erling Smørgrav } 1302e86b9096SDag-Erling Smørgrav verbose(VERB_OPS, "read tls-session-ticket-key: %s", p->str); 1303e86b9096SDag-Erling Smørgrav 1304e86b9096SDag-Erling Smørgrav keys->key_name = data; 1305e86b9096SDag-Erling Smørgrav keys->aes_key = data + 16; 1306e86b9096SDag-Erling Smørgrav keys->hmac_key = data + 48; 1307e86b9096SDag-Erling Smørgrav keys++; 1308e86b9096SDag-Erling Smørgrav } 1309e86b9096SDag-Erling Smørgrav /* terminate array with NULL key name entry */ 1310e86b9096SDag-Erling Smørgrav keys->key_name = NULL; 1311e86b9096SDag-Erling Smørgrav if(SSL_CTX_set_tlsext_ticket_key_cb(sslctx, tls_session_ticket_key_cb) == 0) { 1312e86b9096SDag-Erling Smørgrav log_err("no support for TLS session ticket"); 1313e86b9096SDag-Erling Smørgrav return 0; 1314e86b9096SDag-Erling Smørgrav } 1315e86b9096SDag-Erling Smørgrav return 1; 1316e86b9096SDag-Erling Smørgrav #else 1317e86b9096SDag-Erling Smørgrav (void)sslctx; 1318e86b9096SDag-Erling Smørgrav (void)tls_session_ticket_keys; 1319e86b9096SDag-Erling Smørgrav return 0; 1320e86b9096SDag-Erling Smørgrav #endif 1321e86b9096SDag-Erling Smørgrav 1322e86b9096SDag-Erling Smørgrav } 1323e86b9096SDag-Erling Smørgrav 1324e86b9096SDag-Erling Smørgrav int tls_session_ticket_key_cb(void *ATTR_UNUSED(sslctx), unsigned char* key_name, unsigned char* iv, void *evp_sctx, void *hmac_ctx, int enc) 1325e86b9096SDag-Erling Smørgrav { 1326e86b9096SDag-Erling Smørgrav #ifdef HAVE_SSL 1327e86b9096SDag-Erling Smørgrav const EVP_MD *digest; 1328e86b9096SDag-Erling Smørgrav const EVP_CIPHER *cipher; 1329e86b9096SDag-Erling Smørgrav int evp_cipher_length; 1330e86b9096SDag-Erling Smørgrav digest = EVP_sha256(); 1331e86b9096SDag-Erling Smørgrav cipher = EVP_aes_256_cbc(); 1332e86b9096SDag-Erling Smørgrav evp_cipher_length = EVP_CIPHER_iv_length(cipher); 1333e86b9096SDag-Erling Smørgrav if( enc == 1 ) { 1334e86b9096SDag-Erling Smørgrav /* encrypt */ 1335e86b9096SDag-Erling Smørgrav verbose(VERB_CLIENT, "start session encrypt"); 1336e86b9096SDag-Erling Smørgrav memcpy(key_name, ticket_keys->key_name, 16); 1337e86b9096SDag-Erling Smørgrav if (RAND_bytes(iv, evp_cipher_length) != 1) { 1338e86b9096SDag-Erling Smørgrav verbose(VERB_CLIENT, "RAND_bytes failed"); 1339e86b9096SDag-Erling Smørgrav return -1; 1340e86b9096SDag-Erling Smørgrav } 1341e86b9096SDag-Erling Smørgrav if (EVP_EncryptInit_ex(evp_sctx, cipher, NULL, ticket_keys->aes_key, iv) != 1) { 1342e86b9096SDag-Erling Smørgrav verbose(VERB_CLIENT, "EVP_EncryptInit_ex failed"); 1343e86b9096SDag-Erling Smørgrav return -1; 1344e86b9096SDag-Erling Smørgrav } 13450eefd307SCy Schubert #ifndef HMAC_INIT_EX_RETURNS_VOID 1346e86b9096SDag-Erling Smørgrav if (HMAC_Init_ex(hmac_ctx, ticket_keys->hmac_key, 32, digest, NULL) != 1) { 1347e86b9096SDag-Erling Smørgrav verbose(VERB_CLIENT, "HMAC_Init_ex failed"); 1348e86b9096SDag-Erling Smørgrav return -1; 1349e86b9096SDag-Erling Smørgrav } 13500eefd307SCy Schubert #else 13510eefd307SCy Schubert HMAC_Init_ex(hmac_ctx, ticket_keys->hmac_key, 32, digest, NULL); 13520eefd307SCy Schubert #endif 1353e86b9096SDag-Erling Smørgrav return 1; 1354e86b9096SDag-Erling Smørgrav } else if (enc == 0) { 1355e86b9096SDag-Erling Smørgrav /* decrypt */ 1356e86b9096SDag-Erling Smørgrav struct tls_session_ticket_key *key; 1357e86b9096SDag-Erling Smørgrav verbose(VERB_CLIENT, "start session decrypt"); 1358e86b9096SDag-Erling Smørgrav for(key = ticket_keys; key->key_name != NULL; key++) { 1359e86b9096SDag-Erling Smørgrav if (!memcmp(key_name, key->key_name, 16)) { 1360e86b9096SDag-Erling Smørgrav verbose(VERB_CLIENT, "Found session_key"); 1361e86b9096SDag-Erling Smørgrav break; 1362e86b9096SDag-Erling Smørgrav } 1363e86b9096SDag-Erling Smørgrav } 1364e86b9096SDag-Erling Smørgrav if(key->key_name == NULL) { 1365e86b9096SDag-Erling Smørgrav verbose(VERB_CLIENT, "Not found session_key"); 1366e86b9096SDag-Erling Smørgrav return 0; 1367e86b9096SDag-Erling Smørgrav } 1368e86b9096SDag-Erling Smørgrav 13690eefd307SCy Schubert #ifndef HMAC_INIT_EX_RETURNS_VOID 1370e86b9096SDag-Erling Smørgrav if (HMAC_Init_ex(hmac_ctx, key->hmac_key, 32, digest, NULL) != 1) { 1371e86b9096SDag-Erling Smørgrav verbose(VERB_CLIENT, "HMAC_Init_ex failed"); 1372e86b9096SDag-Erling Smørgrav return -1; 1373e86b9096SDag-Erling Smørgrav } 13740eefd307SCy Schubert #else 13750eefd307SCy Schubert HMAC_Init_ex(hmac_ctx, key->hmac_key, 32, digest, NULL); 13760eefd307SCy Schubert #endif 1377e86b9096SDag-Erling Smørgrav if (EVP_DecryptInit_ex(evp_sctx, cipher, NULL, key->aes_key, iv) != 1) { 1378e86b9096SDag-Erling Smørgrav log_err("EVP_DecryptInit_ex failed"); 1379e86b9096SDag-Erling Smørgrav return -1; 1380e86b9096SDag-Erling Smørgrav } 1381e86b9096SDag-Erling Smørgrav 1382e86b9096SDag-Erling Smørgrav return (key == ticket_keys) ? 1 : 2; 1383e86b9096SDag-Erling Smørgrav } 1384e86b9096SDag-Erling Smørgrav return -1; 1385e86b9096SDag-Erling Smørgrav #else 1386e86b9096SDag-Erling Smørgrav (void)key_name; 1387e86b9096SDag-Erling Smørgrav (void)iv; 1388e86b9096SDag-Erling Smørgrav (void)evp_sctx; 1389e86b9096SDag-Erling Smørgrav (void)hmac_ctx; 1390e86b9096SDag-Erling Smørgrav (void)enc; 1391e86b9096SDag-Erling Smørgrav return 0; 1392e86b9096SDag-Erling Smørgrav #endif 1393e86b9096SDag-Erling Smørgrav } 1394e86b9096SDag-Erling Smørgrav 1395e86b9096SDag-Erling Smørgrav void 1396e86b9096SDag-Erling Smørgrav listen_sslctx_delete_ticket_keys(void) 1397e86b9096SDag-Erling Smørgrav { 1398e86b9096SDag-Erling Smørgrav struct tls_session_ticket_key *key; 1399e86b9096SDag-Erling Smørgrav if(!ticket_keys) return; 1400e86b9096SDag-Erling Smørgrav for(key = ticket_keys; key->key_name != NULL; key++) { 1401e86b9096SDag-Erling Smørgrav /* wipe key data from memory*/ 1402e86b9096SDag-Erling Smørgrav #ifdef HAVE_EXPLICIT_BZERO 1403e86b9096SDag-Erling Smørgrav explicit_bzero(key->key_name, 80); 1404e86b9096SDag-Erling Smørgrav #else 1405e86b9096SDag-Erling Smørgrav memset(key->key_name, 0xdd, 80); 1406e86b9096SDag-Erling Smørgrav #endif 1407e86b9096SDag-Erling Smørgrav free(key->key_name); 1408e86b9096SDag-Erling Smørgrav } 1409e86b9096SDag-Erling Smørgrav free(ticket_keys); 1410e86b9096SDag-Erling Smørgrav ticket_keys = NULL; 1411e86b9096SDag-Erling Smørgrav } 1412