1b7579f77SDag-Erling Smørgrav /* 2b7579f77SDag-Erling Smørgrav * util/net_help.c - implementation of the network helper code 3b7579f77SDag-Erling Smørgrav * 4b7579f77SDag-Erling Smørgrav * Copyright (c) 2007, NLnet Labs. All rights reserved. 5b7579f77SDag-Erling Smørgrav * 6b7579f77SDag-Erling Smørgrav * This software is open source. 7b7579f77SDag-Erling Smørgrav * 8b7579f77SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 9b7579f77SDag-Erling Smørgrav * modification, are permitted provided that the following conditions 10b7579f77SDag-Erling Smørgrav * are met: 11b7579f77SDag-Erling Smørgrav * 12b7579f77SDag-Erling Smørgrav * Redistributions of source code must retain the above copyright notice, 13b7579f77SDag-Erling Smørgrav * this list of conditions and the following disclaimer. 14b7579f77SDag-Erling Smørgrav * 15b7579f77SDag-Erling Smørgrav * Redistributions in binary form must reproduce the above copyright notice, 16b7579f77SDag-Erling Smørgrav * this list of conditions and the following disclaimer in the documentation 17b7579f77SDag-Erling Smørgrav * and/or other materials provided with the distribution. 18b7579f77SDag-Erling Smørgrav * 19b7579f77SDag-Erling Smørgrav * Neither the name of the NLNET LABS nor the names of its contributors may 20b7579f77SDag-Erling Smørgrav * be used to endorse or promote products derived from this software without 21b7579f77SDag-Erling Smørgrav * specific prior written permission. 22b7579f77SDag-Erling Smørgrav * 23b7579f77SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2417d15b25SDag-Erling Smørgrav * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2517d15b25SDag-Erling Smørgrav * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2617d15b25SDag-Erling Smørgrav * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2717d15b25SDag-Erling Smørgrav * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2817d15b25SDag-Erling Smørgrav * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 2917d15b25SDag-Erling Smørgrav * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 3017d15b25SDag-Erling Smørgrav * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 3117d15b25SDag-Erling Smørgrav * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 3217d15b25SDag-Erling Smørgrav * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3317d15b25SDag-Erling Smørgrav * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34b7579f77SDag-Erling Smørgrav */ 35b7579f77SDag-Erling Smørgrav /** 36b7579f77SDag-Erling Smørgrav * \file 37b7579f77SDag-Erling Smørgrav * Implementation of net_help.h. 38b7579f77SDag-Erling Smørgrav */ 39b7579f77SDag-Erling Smørgrav 40b7579f77SDag-Erling Smørgrav #include "config.h" 4124e36522SCy Schubert #ifdef HAVE_SYS_TYPES_H 4224e36522SCy Schubert # include <sys/types.h> 4324e36522SCy Schubert #endif 4424e36522SCy Schubert #ifdef HAVE_NET_IF_H 4524e36522SCy Schubert #include <net/if.h> 4624e36522SCy Schubert #endif 479cf5bc93SCy Schubert #ifdef HAVE_NETIOAPI_H 489cf5bc93SCy Schubert #include <netioapi.h> 499cf5bc93SCy Schubert #endif 50b7579f77SDag-Erling Smørgrav #include "util/net_help.h" 51b7579f77SDag-Erling Smørgrav #include "util/log.h" 52b7579f77SDag-Erling Smørgrav #include "util/data/dname.h" 53b7579f77SDag-Erling Smørgrav #include "util/module.h" 54b7579f77SDag-Erling Smørgrav #include "util/regional.h" 55e86b9096SDag-Erling Smørgrav #include "util/config_file.h" 5609a3aaf3SDag-Erling Smørgrav #include "sldns/parseutil.h" 5709a3aaf3SDag-Erling Smørgrav #include "sldns/wire2str.h" 589cf5bc93SCy Schubert #include "sldns/str2wire.h" 59b7579f77SDag-Erling Smørgrav #include <fcntl.h> 608ed2b524SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_SSL_H 61b7579f77SDag-Erling Smørgrav #include <openssl/ssl.h> 62e86b9096SDag-Erling Smørgrav #include <openssl/evp.h> 63e86b9096SDag-Erling Smørgrav #include <openssl/rand.h> 648ed2b524SDag-Erling Smørgrav #endif 658ed2b524SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_ERR_H 66b7579f77SDag-Erling Smørgrav #include <openssl/err.h> 678ed2b524SDag-Erling Smørgrav #endif 6825039b37SCy Schubert #ifdef HAVE_OPENSSL_CORE_NAMES_H 6925039b37SCy Schubert #include <openssl/core_names.h> 7025039b37SCy Schubert #endif 713bd4df0aSDag-Erling Smørgrav #ifdef USE_WINSOCK 723bd4df0aSDag-Erling Smørgrav #include <wincrypt.h> 733bd4df0aSDag-Erling Smørgrav #endif 74c0caa2e2SCy Schubert #ifdef HAVE_NGHTTP2_NGHTTP2_H 75c0caa2e2SCy Schubert #include <nghttp2/nghttp2.h> 76c0caa2e2SCy Schubert #endif 77b7579f77SDag-Erling Smørgrav 78b7579f77SDag-Erling Smørgrav /** max length of an IP address (the address portion) that we allow */ 79b7579f77SDag-Erling Smørgrav #define MAX_ADDR_STRLEN 128 /* characters */ 80b7579f77SDag-Erling Smørgrav /** default value for EDNS ADVERTISED size */ 81b7579f77SDag-Erling Smørgrav uint16_t EDNS_ADVERTISED_SIZE = 4096; 82b7579f77SDag-Erling Smørgrav 83b7579f77SDag-Erling Smørgrav /** minimal responses when positive answer: default is no */ 84b7579f77SDag-Erling Smørgrav int MINIMAL_RESPONSES = 0; 85b7579f77SDag-Erling Smørgrav 8625039b37SCy Schubert /** rrset order roundrobin: default is yes */ 8725039b37SCy Schubert int RRSET_ROUNDROBIN = 1; 88b7579f77SDag-Erling Smørgrav 89e86b9096SDag-Erling Smørgrav /** log tag queries with name instead of 'info' for filtering */ 90e86b9096SDag-Erling Smørgrav int LOG_TAG_QUERYREPLY = 0; 91e86b9096SDag-Erling Smørgrav 92e86b9096SDag-Erling Smørgrav static struct tls_session_ticket_key { 93e86b9096SDag-Erling Smørgrav unsigned char *key_name; 94e86b9096SDag-Erling Smørgrav unsigned char *aes_key; 95e86b9096SDag-Erling Smørgrav unsigned char *hmac_key; 96e86b9096SDag-Erling Smørgrav } *ticket_keys; 97e86b9096SDag-Erling Smørgrav 98c0caa2e2SCy Schubert #ifdef HAVE_SSL 9925039b37SCy Schubert /** 10025039b37SCy Schubert * callback TLS session ticket encrypt and decrypt 10125039b37SCy Schubert * For use with SSL_CTX_set_tlsext_ticket_key_cb or 10225039b37SCy Schubert * SSL_CTX_set_tlsext_ticket_key_evp_cb 10325039b37SCy Schubert * @param s: the SSL_CTX to use (from connect_sslctx_create()) 10425039b37SCy Schubert * @param key_name: secret name, 16 bytes 10525039b37SCy Schubert * @param iv: up to EVP_MAX_IV_LENGTH. 10625039b37SCy Schubert * @param evp_ctx: the evp cipher context, function sets this. 10725039b37SCy Schubert * @param hmac_ctx: the hmac context, function sets this. 10825039b37SCy Schubert * with ..key_cb it is of type HMAC_CTX* 10925039b37SCy Schubert * with ..key_evp_cb it is of type EVP_MAC_CTX* 11025039b37SCy Schubert * @param enc: 1 is encrypt, 0 is decrypt 11125039b37SCy Schubert * @return 0 on no ticket, 1 for okay, and 2 for okay but renew the ticket 11225039b37SCy Schubert * (the ticket is decrypt only). and <0 for failures. 11325039b37SCy Schubert */ 11425039b37SCy Schubert int tls_session_ticket_key_cb(SSL *s, unsigned char* key_name, 11525039b37SCy Schubert unsigned char* iv, EVP_CIPHER_CTX *evp_ctx, 11625039b37SCy Schubert #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB 11725039b37SCy Schubert EVP_MAC_CTX *hmac_ctx, 11825039b37SCy Schubert #else 11925039b37SCy Schubert HMAC_CTX* hmac_ctx, 12025039b37SCy Schubert #endif 12125039b37SCy Schubert int enc); 12225039b37SCy Schubert #endif /* HAVE_SSL */ 12325039b37SCy Schubert 124b7579f77SDag-Erling Smørgrav /* returns true is string addr is an ip6 specced address */ 125b7579f77SDag-Erling Smørgrav int 126b7579f77SDag-Erling Smørgrav str_is_ip6(const char* str) 127b7579f77SDag-Erling Smørgrav { 128b7579f77SDag-Erling Smørgrav if(strchr(str, ':')) 129b7579f77SDag-Erling Smørgrav return 1; 130b7579f77SDag-Erling Smørgrav else return 0; 131b7579f77SDag-Erling Smørgrav } 132b7579f77SDag-Erling Smørgrav 133b7579f77SDag-Erling Smørgrav int 134b7579f77SDag-Erling Smørgrav fd_set_nonblock(int s) 135b7579f77SDag-Erling Smørgrav { 136b7579f77SDag-Erling Smørgrav #ifdef HAVE_FCNTL 137b7579f77SDag-Erling Smørgrav int flag; 138b7579f77SDag-Erling Smørgrav if((flag = fcntl(s, F_GETFL)) == -1) { 139b7579f77SDag-Erling Smørgrav log_err("can't fcntl F_GETFL: %s", strerror(errno)); 140b7579f77SDag-Erling Smørgrav flag = 0; 141b7579f77SDag-Erling Smørgrav } 142b7579f77SDag-Erling Smørgrav flag |= O_NONBLOCK; 143b7579f77SDag-Erling Smørgrav if(fcntl(s, F_SETFL, flag) == -1) { 144b7579f77SDag-Erling Smørgrav log_err("can't fcntl F_SETFL: %s", strerror(errno)); 145b7579f77SDag-Erling Smørgrav return 0; 146b7579f77SDag-Erling Smørgrav } 147b7579f77SDag-Erling Smørgrav #elif defined(HAVE_IOCTLSOCKET) 148b7579f77SDag-Erling Smørgrav unsigned long on = 1; 149b7579f77SDag-Erling Smørgrav if(ioctlsocket(s, FIONBIO, &on) != 0) { 150b7579f77SDag-Erling Smørgrav log_err("can't ioctlsocket FIONBIO on: %s", 151b7579f77SDag-Erling Smørgrav wsa_strerror(WSAGetLastError())); 152b7579f77SDag-Erling Smørgrav } 153b7579f77SDag-Erling Smørgrav #endif 154b7579f77SDag-Erling Smørgrav return 1; 155b7579f77SDag-Erling Smørgrav } 156b7579f77SDag-Erling Smørgrav 157b7579f77SDag-Erling Smørgrav int 158b7579f77SDag-Erling Smørgrav fd_set_block(int s) 159b7579f77SDag-Erling Smørgrav { 160b7579f77SDag-Erling Smørgrav #ifdef HAVE_FCNTL 161b7579f77SDag-Erling Smørgrav int flag; 162b7579f77SDag-Erling Smørgrav if((flag = fcntl(s, F_GETFL)) == -1) { 163b7579f77SDag-Erling Smørgrav log_err("cannot fcntl F_GETFL: %s", strerror(errno)); 164b7579f77SDag-Erling Smørgrav flag = 0; 165b7579f77SDag-Erling Smørgrav } 166b7579f77SDag-Erling Smørgrav flag &= ~O_NONBLOCK; 167b7579f77SDag-Erling Smørgrav if(fcntl(s, F_SETFL, flag) == -1) { 168b7579f77SDag-Erling Smørgrav log_err("cannot fcntl F_SETFL: %s", strerror(errno)); 169b7579f77SDag-Erling Smørgrav return 0; 170b7579f77SDag-Erling Smørgrav } 171b7579f77SDag-Erling Smørgrav #elif defined(HAVE_IOCTLSOCKET) 172b7579f77SDag-Erling Smørgrav unsigned long off = 0; 173b7579f77SDag-Erling Smørgrav if(ioctlsocket(s, FIONBIO, &off) != 0) { 174971980c3SDag-Erling Smørgrav if(WSAGetLastError() != WSAEINVAL || verbosity >= 4) 175b7579f77SDag-Erling Smørgrav log_err("can't ioctlsocket FIONBIO off: %s", 176b7579f77SDag-Erling Smørgrav wsa_strerror(WSAGetLastError())); 177b7579f77SDag-Erling Smørgrav } 178b7579f77SDag-Erling Smørgrav #endif 179b7579f77SDag-Erling Smørgrav return 1; 180b7579f77SDag-Erling Smørgrav } 181b7579f77SDag-Erling Smørgrav 182b7579f77SDag-Erling Smørgrav int 183b7579f77SDag-Erling Smørgrav is_pow2(size_t num) 184b7579f77SDag-Erling Smørgrav { 185b7579f77SDag-Erling Smørgrav if(num == 0) return 1; 186b7579f77SDag-Erling Smørgrav return (num & (num-1)) == 0; 187b7579f77SDag-Erling Smørgrav } 188b7579f77SDag-Erling Smørgrav 189b7579f77SDag-Erling Smørgrav void* 190b7579f77SDag-Erling Smørgrav memdup(void* data, size_t len) 191b7579f77SDag-Erling Smørgrav { 192b7579f77SDag-Erling Smørgrav void* d; 193b7579f77SDag-Erling Smørgrav if(!data) return NULL; 194b7579f77SDag-Erling Smørgrav if(len == 0) return NULL; 195b7579f77SDag-Erling Smørgrav d = malloc(len); 196b7579f77SDag-Erling Smørgrav if(!d) return NULL; 197b7579f77SDag-Erling Smørgrav memcpy(d, data, len); 198b7579f77SDag-Erling Smørgrav return d; 199b7579f77SDag-Erling Smørgrav } 200b7579f77SDag-Erling Smørgrav 201b7579f77SDag-Erling Smørgrav void 202b7579f77SDag-Erling Smørgrav log_addr(enum verbosity_value v, const char* str, 203b7579f77SDag-Erling Smørgrav struct sockaddr_storage* addr, socklen_t addrlen) 204b7579f77SDag-Erling Smørgrav { 205b7579f77SDag-Erling Smørgrav uint16_t port; 206b7579f77SDag-Erling Smørgrav const char* family = "unknown"; 207b7579f77SDag-Erling Smørgrav char dest[100]; 208b7579f77SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family; 209b7579f77SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 210b7579f77SDag-Erling Smørgrav if(verbosity < v) 211b7579f77SDag-Erling Smørgrav return; 212b7579f77SDag-Erling Smørgrav switch(af) { 213b7579f77SDag-Erling Smørgrav case AF_INET: family="ip4"; break; 214b7579f77SDag-Erling Smørgrav case AF_INET6: family="ip6"; 215b7579f77SDag-Erling Smørgrav sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; 216b7579f77SDag-Erling Smørgrav break; 2176480faa8SDag-Erling Smørgrav case AF_LOCAL: 2186480faa8SDag-Erling Smørgrav dest[0]=0; 2196480faa8SDag-Erling Smørgrav (void)inet_ntop(af, sinaddr, dest, 2206480faa8SDag-Erling Smørgrav (socklen_t)sizeof(dest)); 2216480faa8SDag-Erling Smørgrav verbose(v, "%s local %s", str, dest); 2226480faa8SDag-Erling Smørgrav return; /* do not continue and try to get port */ 223b7579f77SDag-Erling Smørgrav default: break; 224b7579f77SDag-Erling Smørgrav } 225b7579f77SDag-Erling Smørgrav if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { 22617d15b25SDag-Erling Smørgrav (void)strlcpy(dest, "(inet_ntop error)", sizeof(dest)); 227b7579f77SDag-Erling Smørgrav } 228b7579f77SDag-Erling Smørgrav dest[sizeof(dest)-1] = 0; 229b7579f77SDag-Erling Smørgrav port = ntohs(((struct sockaddr_in*)addr)->sin_port); 230b7579f77SDag-Erling Smørgrav if(verbosity >= 4) 231b7579f77SDag-Erling Smørgrav verbose(v, "%s %s %s port %d (len %d)", str, family, dest, 232b7579f77SDag-Erling Smørgrav (int)port, (int)addrlen); 233b7579f77SDag-Erling Smørgrav else verbose(v, "%s %s port %d", str, dest, (int)port); 234b7579f77SDag-Erling Smørgrav } 235b7579f77SDag-Erling Smørgrav 236b7579f77SDag-Erling Smørgrav int 237b7579f77SDag-Erling Smørgrav extstrtoaddr(const char* str, struct sockaddr_storage* addr, 238865f46b2SCy Schubert socklen_t* addrlen, int port) 239b7579f77SDag-Erling Smørgrav { 240b7579f77SDag-Erling Smørgrav char* s; 241b7579f77SDag-Erling Smørgrav if((s=strchr(str, '@'))) { 242b7579f77SDag-Erling Smørgrav char buf[MAX_ADDR_STRLEN]; 243b7579f77SDag-Erling Smørgrav if(s-str >= MAX_ADDR_STRLEN) { 244b7579f77SDag-Erling Smørgrav return 0; 245b7579f77SDag-Erling Smørgrav } 24617d15b25SDag-Erling Smørgrav (void)strlcpy(buf, str, sizeof(buf)); 247b7579f77SDag-Erling Smørgrav buf[s-str] = 0; 248b7579f77SDag-Erling Smørgrav port = atoi(s+1); 249b7579f77SDag-Erling Smørgrav if(port == 0 && strcmp(s+1,"0")!=0) { 250b7579f77SDag-Erling Smørgrav return 0; 251b7579f77SDag-Erling Smørgrav } 252b7579f77SDag-Erling Smørgrav return ipstrtoaddr(buf, port, addr, addrlen); 253b7579f77SDag-Erling Smørgrav } 254b7579f77SDag-Erling Smørgrav return ipstrtoaddr(str, port, addr, addrlen); 255b7579f77SDag-Erling Smørgrav } 256b7579f77SDag-Erling Smørgrav 257b7579f77SDag-Erling Smørgrav int 258b7579f77SDag-Erling Smørgrav ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr, 259b7579f77SDag-Erling Smørgrav socklen_t* addrlen) 260b7579f77SDag-Erling Smørgrav { 261b7579f77SDag-Erling Smørgrav uint16_t p; 262b7579f77SDag-Erling Smørgrav if(!ip) return 0; 263b7579f77SDag-Erling Smørgrav p = (uint16_t) port; 264b7579f77SDag-Erling Smørgrav if(str_is_ip6(ip)) { 265b7579f77SDag-Erling Smørgrav char buf[MAX_ADDR_STRLEN]; 266b7579f77SDag-Erling Smørgrav char* s; 267b7579f77SDag-Erling Smørgrav struct sockaddr_in6* sa = (struct sockaddr_in6*)addr; 268b7579f77SDag-Erling Smørgrav *addrlen = (socklen_t)sizeof(struct sockaddr_in6); 269b7579f77SDag-Erling Smørgrav memset(sa, 0, *addrlen); 270b7579f77SDag-Erling Smørgrav sa->sin6_family = AF_INET6; 271b7579f77SDag-Erling Smørgrav sa->sin6_port = (in_port_t)htons(p); 272b7579f77SDag-Erling Smørgrav if((s=strchr(ip, '%'))) { /* ip6%interface, rfc 4007 */ 273b7579f77SDag-Erling Smørgrav if(s-ip >= MAX_ADDR_STRLEN) 274b7579f77SDag-Erling Smørgrav return 0; 27517d15b25SDag-Erling Smørgrav (void)strlcpy(buf, ip, sizeof(buf)); 276b7579f77SDag-Erling Smørgrav buf[s-ip]=0; 27724e36522SCy Schubert #ifdef HAVE_IF_NAMETOINDEX 27824e36522SCy Schubert if (!(sa->sin6_scope_id = if_nametoindex(s+1))) 27924e36522SCy Schubert #endif /* HAVE_IF_NAMETOINDEX */ 280b7579f77SDag-Erling Smørgrav sa->sin6_scope_id = (uint32_t)atoi(s+1); 281b7579f77SDag-Erling Smørgrav ip = buf; 282b7579f77SDag-Erling Smørgrav } 283b7579f77SDag-Erling Smørgrav if(inet_pton((int)sa->sin6_family, ip, &sa->sin6_addr) <= 0) { 284b7579f77SDag-Erling Smørgrav return 0; 285b7579f77SDag-Erling Smørgrav } 286b7579f77SDag-Erling Smørgrav } else { /* ip4 */ 287b7579f77SDag-Erling Smørgrav struct sockaddr_in* sa = (struct sockaddr_in*)addr; 288b7579f77SDag-Erling Smørgrav *addrlen = (socklen_t)sizeof(struct sockaddr_in); 289b7579f77SDag-Erling Smørgrav memset(sa, 0, *addrlen); 290b7579f77SDag-Erling Smørgrav sa->sin_family = AF_INET; 291b7579f77SDag-Erling Smørgrav sa->sin_port = (in_port_t)htons(p); 292b7579f77SDag-Erling Smørgrav if(inet_pton((int)sa->sin_family, ip, &sa->sin_addr) <= 0) { 293b7579f77SDag-Erling Smørgrav return 0; 294b7579f77SDag-Erling Smørgrav } 295b7579f77SDag-Erling Smørgrav } 296b7579f77SDag-Erling Smørgrav return 1; 297b7579f77SDag-Erling Smørgrav } 298b7579f77SDag-Erling Smørgrav 299b7579f77SDag-Erling Smørgrav int netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr, 300b7579f77SDag-Erling Smørgrav socklen_t* addrlen, int* net) 301b7579f77SDag-Erling Smørgrav { 3020fb34990SDag-Erling Smørgrav char buf[64]; 3030fb34990SDag-Erling Smørgrav char* s; 304b7579f77SDag-Erling Smørgrav *net = (str_is_ip6(str)?128:32); 305b7579f77SDag-Erling Smørgrav if((s=strchr(str, '/'))) { 306b7579f77SDag-Erling Smørgrav if(atoi(s+1) > *net) { 307b7579f77SDag-Erling Smørgrav log_err("netblock too large: %s", str); 308b7579f77SDag-Erling Smørgrav return 0; 309b7579f77SDag-Erling Smørgrav } 310b7579f77SDag-Erling Smørgrav *net = atoi(s+1); 311b7579f77SDag-Erling Smørgrav if(*net == 0 && strcmp(s+1, "0") != 0) { 312b7579f77SDag-Erling Smørgrav log_err("cannot parse netblock: '%s'", str); 313b7579f77SDag-Erling Smørgrav return 0; 314b7579f77SDag-Erling Smørgrav } 3150fb34990SDag-Erling Smørgrav strlcpy(buf, str, sizeof(buf)); 3160fb34990SDag-Erling Smørgrav s = strchr(buf, '/'); 3170fb34990SDag-Erling Smørgrav if(s) *s = 0; 3180fb34990SDag-Erling Smørgrav s = buf; 319b7579f77SDag-Erling Smørgrav } 320b7579f77SDag-Erling Smørgrav if(!ipstrtoaddr(s?s:str, port, addr, addrlen)) { 321b7579f77SDag-Erling Smørgrav log_err("cannot parse ip address: '%s'", str); 322b7579f77SDag-Erling Smørgrav return 0; 323b7579f77SDag-Erling Smørgrav } 324b7579f77SDag-Erling Smørgrav if(s) { 325b7579f77SDag-Erling Smørgrav addr_mask(addr, *addrlen, *net); 326b7579f77SDag-Erling Smørgrav } 327b7579f77SDag-Erling Smørgrav return 1; 328b7579f77SDag-Erling Smørgrav } 329b7579f77SDag-Erling Smørgrav 330091e9e46SCy Schubert /* RPZ format address dname to network byte order address */ 331091e9e46SCy Schubert static int ipdnametoaddr(uint8_t* dname, size_t dnamelen, 332091e9e46SCy Schubert struct sockaddr_storage* addr, socklen_t* addrlen, int* af) 333091e9e46SCy Schubert { 334091e9e46SCy Schubert uint8_t* ia; 335f44e67d1SCy Schubert int dnamelabs = dname_count_labels(dname); 336091e9e46SCy Schubert uint8_t lablen; 337091e9e46SCy Schubert char* e = NULL; 338091e9e46SCy Schubert int z = 0; 339091e9e46SCy Schubert size_t len = 0; 340091e9e46SCy Schubert int i; 341091e9e46SCy Schubert *af = AF_INET; 342091e9e46SCy Schubert 343091e9e46SCy Schubert /* need 1 byte for label length */ 344091e9e46SCy Schubert if(dnamelen < 1) 345091e9e46SCy Schubert return 0; 346091e9e46SCy Schubert 347091e9e46SCy Schubert if(dnamelabs > 6 || 348091e9e46SCy Schubert dname_has_label(dname, dnamelen, (uint8_t*)"\002zz")) { 349091e9e46SCy Schubert *af = AF_INET6; 350091e9e46SCy Schubert } 351091e9e46SCy Schubert len = *dname; 352091e9e46SCy Schubert lablen = *dname++; 353091e9e46SCy Schubert i = (*af == AF_INET) ? 3 : 15; 354091e9e46SCy Schubert if(*af == AF_INET6) { 355091e9e46SCy Schubert struct sockaddr_in6* sa = (struct sockaddr_in6*)addr; 356091e9e46SCy Schubert *addrlen = (socklen_t)sizeof(struct sockaddr_in6); 357091e9e46SCy Schubert memset(sa, 0, *addrlen); 358091e9e46SCy Schubert sa->sin6_family = AF_INET6; 359091e9e46SCy Schubert ia = (uint8_t*)&sa->sin6_addr; 360091e9e46SCy Schubert } else { /* ip4 */ 361091e9e46SCy Schubert struct sockaddr_in* sa = (struct sockaddr_in*)addr; 362091e9e46SCy Schubert *addrlen = (socklen_t)sizeof(struct sockaddr_in); 363091e9e46SCy Schubert memset(sa, 0, *addrlen); 364091e9e46SCy Schubert sa->sin_family = AF_INET; 365091e9e46SCy Schubert ia = (uint8_t*)&sa->sin_addr; 366091e9e46SCy Schubert } 367091e9e46SCy Schubert while(lablen && i >= 0 && len <= dnamelen) { 368091e9e46SCy Schubert char buff[LDNS_MAX_LABELLEN+1]; 369091e9e46SCy Schubert uint16_t chunk; /* big enough to not overflow on IPv6 hextet */ 370091e9e46SCy Schubert if((*af == AF_INET && (lablen > 3 || dnamelabs > 6)) || 371091e9e46SCy Schubert (*af == AF_INET6 && (lablen > 4 || dnamelabs > 10))) { 372091e9e46SCy Schubert return 0; 373091e9e46SCy Schubert } 374091e9e46SCy Schubert if(memcmp(dname, "zz", 2) == 0 && *af == AF_INET6) { 375091e9e46SCy Schubert /* Add one or more 0 labels. Address is initialised at 376091e9e46SCy Schubert * 0, so just skip the zero part. */ 377091e9e46SCy Schubert int zl = 11 - dnamelabs; 378091e9e46SCy Schubert if(z || zl < 0) 379091e9e46SCy Schubert return 0; 380091e9e46SCy Schubert z = 1; 381091e9e46SCy Schubert i -= (zl*2); 382091e9e46SCy Schubert } else { 383091e9e46SCy Schubert memcpy(buff, dname, lablen); 384091e9e46SCy Schubert buff[lablen] = '\0'; 385091e9e46SCy Schubert chunk = strtol(buff, &e, (*af == AF_INET) ? 10 : 16); 386091e9e46SCy Schubert if(!e || *e != '\0' || (*af == AF_INET && chunk > 255)) 387091e9e46SCy Schubert return 0; 388091e9e46SCy Schubert if(*af == AF_INET) { 389091e9e46SCy Schubert log_assert(i < 4 && i >= 0); 390091e9e46SCy Schubert ia[i] = (uint8_t)chunk; 391091e9e46SCy Schubert i--; 392091e9e46SCy Schubert } else { 393091e9e46SCy Schubert log_assert(i < 16 && i >= 1); 394091e9e46SCy Schubert /* ia in network byte order */ 395091e9e46SCy Schubert ia[i-1] = (uint8_t)(chunk >> 8); 396091e9e46SCy Schubert ia[i] = (uint8_t)(chunk & 0x00FF); 397091e9e46SCy Schubert i -= 2; 398091e9e46SCy Schubert } 399091e9e46SCy Schubert } 400091e9e46SCy Schubert dname += lablen; 401091e9e46SCy Schubert lablen = *dname++; 402091e9e46SCy Schubert len += lablen; 403091e9e46SCy Schubert } 404091e9e46SCy Schubert if(i != -1) 405091e9e46SCy Schubert /* input too short */ 406091e9e46SCy Schubert return 0; 407091e9e46SCy Schubert return 1; 408091e9e46SCy Schubert } 409091e9e46SCy Schubert 410091e9e46SCy Schubert int netblockdnametoaddr(uint8_t* dname, size_t dnamelen, 411091e9e46SCy Schubert struct sockaddr_storage* addr, socklen_t* addrlen, int* net, int* af) 412091e9e46SCy Schubert { 413091e9e46SCy Schubert char buff[3 /* 3 digit netblock */ + 1]; 414091e9e46SCy Schubert size_t nlablen; 415091e9e46SCy Schubert if(dnamelen < 1 || *dname > 3) 416091e9e46SCy Schubert /* netblock invalid */ 417091e9e46SCy Schubert return 0; 418091e9e46SCy Schubert nlablen = *dname; 419091e9e46SCy Schubert 420091e9e46SCy Schubert if(dnamelen < 1 + nlablen) 421091e9e46SCy Schubert return 0; 422091e9e46SCy Schubert 423091e9e46SCy Schubert memcpy(buff, dname+1, nlablen); 424091e9e46SCy Schubert buff[nlablen] = '\0'; 425091e9e46SCy Schubert *net = atoi(buff); 426091e9e46SCy Schubert if(*net == 0 && strcmp(buff, "0") != 0) 427091e9e46SCy Schubert return 0; 428091e9e46SCy Schubert dname += nlablen; 429091e9e46SCy Schubert dname++; 430091e9e46SCy Schubert if(!ipdnametoaddr(dname, dnamelen-1-nlablen, addr, addrlen, af)) 431091e9e46SCy Schubert return 0; 432091e9e46SCy Schubert if((*af == AF_INET6 && *net > 128) || (*af == AF_INET && *net > 32)) 433091e9e46SCy Schubert return 0; 434091e9e46SCy Schubert return 1; 435091e9e46SCy Schubert } 436091e9e46SCy Schubert 4370fb34990SDag-Erling Smørgrav int authextstrtoaddr(char* str, struct sockaddr_storage* addr, 4380fb34990SDag-Erling Smørgrav socklen_t* addrlen, char** auth_name) 4390fb34990SDag-Erling Smørgrav { 4400fb34990SDag-Erling Smørgrav char* s; 4410fb34990SDag-Erling Smørgrav int port = UNBOUND_DNS_PORT; 4420fb34990SDag-Erling Smørgrav if((s=strchr(str, '@'))) { 4430fb34990SDag-Erling Smørgrav char buf[MAX_ADDR_STRLEN]; 4440fb34990SDag-Erling Smørgrav size_t len = (size_t)(s-str); 4450fb34990SDag-Erling Smørgrav char* hash = strchr(s+1, '#'); 4460fb34990SDag-Erling Smørgrav if(hash) { 4470fb34990SDag-Erling Smørgrav *auth_name = hash+1; 4480fb34990SDag-Erling Smørgrav } else { 4490fb34990SDag-Erling Smørgrav *auth_name = NULL; 4500fb34990SDag-Erling Smørgrav } 4510fb34990SDag-Erling Smørgrav if(len >= MAX_ADDR_STRLEN) { 4520fb34990SDag-Erling Smørgrav return 0; 4530fb34990SDag-Erling Smørgrav } 4540fb34990SDag-Erling Smørgrav (void)strlcpy(buf, str, sizeof(buf)); 4550fb34990SDag-Erling Smørgrav buf[len] = 0; 4560fb34990SDag-Erling Smørgrav port = atoi(s+1); 4570fb34990SDag-Erling Smørgrav if(port == 0) { 4580fb34990SDag-Erling Smørgrav if(!hash && strcmp(s+1,"0")!=0) 4590fb34990SDag-Erling Smørgrav return 0; 4600fb34990SDag-Erling Smørgrav if(hash && strncmp(s+1,"0#",2)!=0) 4610fb34990SDag-Erling Smørgrav return 0; 4620fb34990SDag-Erling Smørgrav } 4630fb34990SDag-Erling Smørgrav return ipstrtoaddr(buf, port, addr, addrlen); 4640fb34990SDag-Erling Smørgrav } 4650fb34990SDag-Erling Smørgrav if((s=strchr(str, '#'))) { 4660fb34990SDag-Erling Smørgrav char buf[MAX_ADDR_STRLEN]; 4670fb34990SDag-Erling Smørgrav size_t len = (size_t)(s-str); 4680fb34990SDag-Erling Smørgrav if(len >= MAX_ADDR_STRLEN) { 4690fb34990SDag-Erling Smørgrav return 0; 4700fb34990SDag-Erling Smørgrav } 4710fb34990SDag-Erling Smørgrav (void)strlcpy(buf, str, sizeof(buf)); 4720fb34990SDag-Erling Smørgrav buf[len] = 0; 4730fb34990SDag-Erling Smørgrav port = UNBOUND_DNS_OVER_TLS_PORT; 4740fb34990SDag-Erling Smørgrav *auth_name = s+1; 4750fb34990SDag-Erling Smørgrav return ipstrtoaddr(buf, port, addr, addrlen); 4760fb34990SDag-Erling Smørgrav } 4770fb34990SDag-Erling Smørgrav *auth_name = NULL; 4780fb34990SDag-Erling Smørgrav return ipstrtoaddr(str, port, addr, addrlen); 4790fb34990SDag-Erling Smørgrav } 4800fb34990SDag-Erling Smørgrav 4819cf5bc93SCy Schubert uint8_t* authextstrtodname(char* str, int* port, char** auth_name) 4829cf5bc93SCy Schubert { 4839cf5bc93SCy Schubert char* s; 4849cf5bc93SCy Schubert uint8_t* dname; 4859cf5bc93SCy Schubert size_t dname_len; 4869cf5bc93SCy Schubert *port = UNBOUND_DNS_PORT; 4879cf5bc93SCy Schubert *auth_name = NULL; 4889cf5bc93SCy Schubert if((s=strchr(str, '@'))) { 4899cf5bc93SCy Schubert char* hash = strchr(s+1, '#'); 4909cf5bc93SCy Schubert if(hash) { 4919cf5bc93SCy Schubert *auth_name = hash+1; 4929cf5bc93SCy Schubert } else { 4939cf5bc93SCy Schubert *auth_name = NULL; 4949cf5bc93SCy Schubert } 4959cf5bc93SCy Schubert *port = atoi(s+1); 4969cf5bc93SCy Schubert if(*port == 0) { 4979cf5bc93SCy Schubert if(!hash && strcmp(s+1,"0")!=0) 4989cf5bc93SCy Schubert return 0; 4999cf5bc93SCy Schubert if(hash && strncmp(s+1,"0#",2)!=0) 5009cf5bc93SCy Schubert return 0; 5019cf5bc93SCy Schubert } 5029cf5bc93SCy Schubert *s = 0; 5039cf5bc93SCy Schubert dname = sldns_str2wire_dname(str, &dname_len); 5049cf5bc93SCy Schubert *s = '@'; 5059cf5bc93SCy Schubert } else if((s=strchr(str, '#'))) { 5069cf5bc93SCy Schubert *port = UNBOUND_DNS_OVER_TLS_PORT; 5079cf5bc93SCy Schubert *auth_name = s+1; 5089cf5bc93SCy Schubert *s = 0; 5099cf5bc93SCy Schubert dname = sldns_str2wire_dname(str, &dname_len); 5109cf5bc93SCy Schubert *s = '#'; 5119cf5bc93SCy Schubert } else { 5129cf5bc93SCy Schubert dname = sldns_str2wire_dname(str, &dname_len); 5139cf5bc93SCy Schubert } 5149cf5bc93SCy Schubert return dname; 5159cf5bc93SCy Schubert } 5169cf5bc93SCy Schubert 51757bddd21SDag-Erling Smørgrav /** store port number into sockaddr structure */ 51857bddd21SDag-Erling Smørgrav void 51957bddd21SDag-Erling Smørgrav sockaddr_store_port(struct sockaddr_storage* addr, socklen_t addrlen, int port) 52057bddd21SDag-Erling Smørgrav { 52157bddd21SDag-Erling Smørgrav if(addr_is_ip6(addr, addrlen)) { 52257bddd21SDag-Erling Smørgrav struct sockaddr_in6* sa = (struct sockaddr_in6*)addr; 52357bddd21SDag-Erling Smørgrav sa->sin6_port = (in_port_t)htons((uint16_t)port); 52457bddd21SDag-Erling Smørgrav } else { 52557bddd21SDag-Erling Smørgrav struct sockaddr_in* sa = (struct sockaddr_in*)addr; 52657bddd21SDag-Erling Smørgrav sa->sin_port = (in_port_t)htons((uint16_t)port); 52757bddd21SDag-Erling Smørgrav } 52857bddd21SDag-Erling Smørgrav } 52957bddd21SDag-Erling Smørgrav 530b7579f77SDag-Erling Smørgrav void 531b7579f77SDag-Erling Smørgrav log_nametypeclass(enum verbosity_value v, const char* str, uint8_t* name, 532b7579f77SDag-Erling Smørgrav uint16_t type, uint16_t dclass) 533b7579f77SDag-Erling Smørgrav { 534b7579f77SDag-Erling Smørgrav char buf[LDNS_MAX_DOMAINLEN+1]; 535b7579f77SDag-Erling Smørgrav char t[12], c[12]; 536b7579f77SDag-Erling Smørgrav const char *ts, *cs; 537b7579f77SDag-Erling Smørgrav if(verbosity < v) 538b7579f77SDag-Erling Smørgrav return; 539b7579f77SDag-Erling Smørgrav dname_str(name, buf); 540b7579f77SDag-Erling Smørgrav if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG"; 541b7579f77SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR"; 542b7579f77SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR"; 543b7579f77SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB"; 544b7579f77SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA"; 545b7579f77SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_ANY) ts = "ANY"; 54617d15b25SDag-Erling Smørgrav else if(sldns_rr_descript(type) && sldns_rr_descript(type)->_name) 54717d15b25SDag-Erling Smørgrav ts = sldns_rr_descript(type)->_name; 548b7579f77SDag-Erling Smørgrav else { 549b7579f77SDag-Erling Smørgrav snprintf(t, sizeof(t), "TYPE%d", (int)type); 550b7579f77SDag-Erling Smørgrav ts = t; 551b7579f77SDag-Erling Smørgrav } 55217d15b25SDag-Erling Smørgrav if(sldns_lookup_by_id(sldns_rr_classes, (int)dclass) && 55317d15b25SDag-Erling Smørgrav sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name) 55417d15b25SDag-Erling Smørgrav cs = sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name; 555b7579f77SDag-Erling Smørgrav else { 556b7579f77SDag-Erling Smørgrav snprintf(c, sizeof(c), "CLASS%d", (int)dclass); 557b7579f77SDag-Erling Smørgrav cs = c; 558b7579f77SDag-Erling Smørgrav } 559b7579f77SDag-Erling Smørgrav log_info("%s %s %s %s", str, buf, ts, cs); 560b7579f77SDag-Erling Smørgrav } 561b7579f77SDag-Erling Smørgrav 562e86b9096SDag-Erling Smørgrav void 563e86b9096SDag-Erling Smørgrav log_query_in(const char* str, uint8_t* name, uint16_t type, uint16_t dclass) 564e86b9096SDag-Erling Smørgrav { 565e86b9096SDag-Erling Smørgrav char buf[LDNS_MAX_DOMAINLEN+1]; 566e86b9096SDag-Erling Smørgrav char t[12], c[12]; 567e86b9096SDag-Erling Smørgrav const char *ts, *cs; 568e86b9096SDag-Erling Smørgrav dname_str(name, buf); 569e86b9096SDag-Erling Smørgrav if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG"; 570e86b9096SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR"; 571e86b9096SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR"; 572e86b9096SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB"; 573e86b9096SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA"; 574e86b9096SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_ANY) ts = "ANY"; 575e86b9096SDag-Erling Smørgrav else if(sldns_rr_descript(type) && sldns_rr_descript(type)->_name) 576e86b9096SDag-Erling Smørgrav ts = sldns_rr_descript(type)->_name; 577e86b9096SDag-Erling Smørgrav else { 578e86b9096SDag-Erling Smørgrav snprintf(t, sizeof(t), "TYPE%d", (int)type); 579e86b9096SDag-Erling Smørgrav ts = t; 580e86b9096SDag-Erling Smørgrav } 581e86b9096SDag-Erling Smørgrav if(sldns_lookup_by_id(sldns_rr_classes, (int)dclass) && 582e86b9096SDag-Erling Smørgrav sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name) 583e86b9096SDag-Erling Smørgrav cs = sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name; 584e86b9096SDag-Erling Smørgrav else { 585e86b9096SDag-Erling Smørgrav snprintf(c, sizeof(c), "CLASS%d", (int)dclass); 586e86b9096SDag-Erling Smørgrav cs = c; 587e86b9096SDag-Erling Smørgrav } 588e86b9096SDag-Erling Smørgrav if(LOG_TAG_QUERYREPLY) 589e86b9096SDag-Erling Smørgrav log_query("%s %s %s %s", str, buf, ts, cs); 590e86b9096SDag-Erling Smørgrav else log_info("%s %s %s %s", str, buf, ts, cs); 591e86b9096SDag-Erling Smørgrav } 592e86b9096SDag-Erling Smørgrav 593b7579f77SDag-Erling Smørgrav void log_name_addr(enum verbosity_value v, const char* str, uint8_t* zone, 594b7579f77SDag-Erling Smørgrav struct sockaddr_storage* addr, socklen_t addrlen) 595b7579f77SDag-Erling Smørgrav { 596b7579f77SDag-Erling Smørgrav uint16_t port; 597b7579f77SDag-Erling Smørgrav const char* family = "unknown_family "; 598b7579f77SDag-Erling Smørgrav char namebuf[LDNS_MAX_DOMAINLEN+1]; 599b7579f77SDag-Erling Smørgrav char dest[100]; 600b7579f77SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family; 601b7579f77SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 602b7579f77SDag-Erling Smørgrav if(verbosity < v) 603b7579f77SDag-Erling Smørgrav return; 604b7579f77SDag-Erling Smørgrav switch(af) { 605b7579f77SDag-Erling Smørgrav case AF_INET: family=""; break; 606b7579f77SDag-Erling Smørgrav case AF_INET6: family=""; 607b7579f77SDag-Erling Smørgrav sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; 608b7579f77SDag-Erling Smørgrav break; 60931099b50SDag-Erling Smørgrav case AF_LOCAL: family="local "; break; 610b7579f77SDag-Erling Smørgrav default: break; 611b7579f77SDag-Erling Smørgrav } 612b7579f77SDag-Erling Smørgrav if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { 61317d15b25SDag-Erling Smørgrav (void)strlcpy(dest, "(inet_ntop error)", sizeof(dest)); 614b7579f77SDag-Erling Smørgrav } 615b7579f77SDag-Erling Smørgrav dest[sizeof(dest)-1] = 0; 616b7579f77SDag-Erling Smørgrav port = ntohs(((struct sockaddr_in*)addr)->sin_port); 617b7579f77SDag-Erling Smørgrav dname_str(zone, namebuf); 618b7579f77SDag-Erling Smørgrav if(af != AF_INET && af != AF_INET6) 619b7579f77SDag-Erling Smørgrav verbose(v, "%s <%s> %s%s#%d (addrlen %d)", 620b7579f77SDag-Erling Smørgrav str, namebuf, family, dest, (int)port, (int)addrlen); 621b7579f77SDag-Erling Smørgrav else verbose(v, "%s <%s> %s%s#%d", 622b7579f77SDag-Erling Smørgrav str, namebuf, family, dest, (int)port); 623b7579f77SDag-Erling Smørgrav } 624b7579f77SDag-Erling Smørgrav 625ff825849SDag-Erling Smørgrav void log_err_addr(const char* str, const char* err, 626ff825849SDag-Erling Smørgrav struct sockaddr_storage* addr, socklen_t addrlen) 627ff825849SDag-Erling Smørgrav { 628ff825849SDag-Erling Smørgrav uint16_t port; 629ff825849SDag-Erling Smørgrav char dest[100]; 630ff825849SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family; 631ff825849SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 632ff825849SDag-Erling Smørgrav if(af == AF_INET6) 633ff825849SDag-Erling Smørgrav sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; 634ff825849SDag-Erling Smørgrav if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { 635ff825849SDag-Erling Smørgrav (void)strlcpy(dest, "(inet_ntop error)", sizeof(dest)); 636ff825849SDag-Erling Smørgrav } 637ff825849SDag-Erling Smørgrav dest[sizeof(dest)-1] = 0; 638ff825849SDag-Erling Smørgrav port = ntohs(((struct sockaddr_in*)addr)->sin_port); 639ff825849SDag-Erling Smørgrav if(verbosity >= 4) 640ff825849SDag-Erling Smørgrav log_err("%s: %s for %s port %d (len %d)", str, err, dest, 641ff825849SDag-Erling Smørgrav (int)port, (int)addrlen); 6424c75e3aaSDag-Erling Smørgrav else log_err("%s: %s for %s port %d", str, err, dest, (int)port); 643ff825849SDag-Erling Smørgrav } 644ff825849SDag-Erling Smørgrav 645b7579f77SDag-Erling Smørgrav int 646b7579f77SDag-Erling Smørgrav sockaddr_cmp(struct sockaddr_storage* addr1, socklen_t len1, 647b7579f77SDag-Erling Smørgrav struct sockaddr_storage* addr2, socklen_t len2) 648b7579f77SDag-Erling Smørgrav { 649b7579f77SDag-Erling Smørgrav struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1; 650b7579f77SDag-Erling Smørgrav struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2; 651b7579f77SDag-Erling Smørgrav struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1; 652b7579f77SDag-Erling Smørgrav struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2; 653b7579f77SDag-Erling Smørgrav if(len1 < len2) 654b7579f77SDag-Erling Smørgrav return -1; 655b7579f77SDag-Erling Smørgrav if(len1 > len2) 656b7579f77SDag-Erling Smørgrav return 1; 657b7579f77SDag-Erling Smørgrav log_assert(len1 == len2); 658b7579f77SDag-Erling Smørgrav if( p1_in->sin_family < p2_in->sin_family) 659b7579f77SDag-Erling Smørgrav return -1; 660b7579f77SDag-Erling Smørgrav if( p1_in->sin_family > p2_in->sin_family) 661b7579f77SDag-Erling Smørgrav return 1; 662b7579f77SDag-Erling Smørgrav log_assert( p1_in->sin_family == p2_in->sin_family ); 663b7579f77SDag-Erling Smørgrav /* compare ip4 */ 664b7579f77SDag-Erling Smørgrav if( p1_in->sin_family == AF_INET ) { 665b7579f77SDag-Erling Smørgrav /* just order it, ntohs not required */ 666b7579f77SDag-Erling Smørgrav if(p1_in->sin_port < p2_in->sin_port) 667b7579f77SDag-Erling Smørgrav return -1; 668b7579f77SDag-Erling Smørgrav if(p1_in->sin_port > p2_in->sin_port) 669b7579f77SDag-Erling Smørgrav return 1; 670b7579f77SDag-Erling Smørgrav log_assert(p1_in->sin_port == p2_in->sin_port); 671b7579f77SDag-Erling Smørgrav return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE); 672b7579f77SDag-Erling Smørgrav } else if (p1_in6->sin6_family == AF_INET6) { 673b7579f77SDag-Erling Smørgrav /* just order it, ntohs not required */ 674b7579f77SDag-Erling Smørgrav if(p1_in6->sin6_port < p2_in6->sin6_port) 675b7579f77SDag-Erling Smørgrav return -1; 676b7579f77SDag-Erling Smørgrav if(p1_in6->sin6_port > p2_in6->sin6_port) 677b7579f77SDag-Erling Smørgrav return 1; 678b7579f77SDag-Erling Smørgrav log_assert(p1_in6->sin6_port == p2_in6->sin6_port); 679b7579f77SDag-Erling Smørgrav return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr, 680b7579f77SDag-Erling Smørgrav INET6_SIZE); 681b7579f77SDag-Erling Smørgrav } else { 682b7579f77SDag-Erling Smørgrav /* eek unknown type, perform this comparison for sanity. */ 683b7579f77SDag-Erling Smørgrav return memcmp(addr1, addr2, len1); 684b7579f77SDag-Erling Smørgrav } 685b7579f77SDag-Erling Smørgrav } 686b7579f77SDag-Erling Smørgrav 687b7579f77SDag-Erling Smørgrav int 688b7579f77SDag-Erling Smørgrav sockaddr_cmp_addr(struct sockaddr_storage* addr1, socklen_t len1, 689b7579f77SDag-Erling Smørgrav struct sockaddr_storage* addr2, socklen_t len2) 690b7579f77SDag-Erling Smørgrav { 691b7579f77SDag-Erling Smørgrav struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1; 692b7579f77SDag-Erling Smørgrav struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2; 693b7579f77SDag-Erling Smørgrav struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1; 694b7579f77SDag-Erling Smørgrav struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2; 695b7579f77SDag-Erling Smørgrav if(len1 < len2) 696b7579f77SDag-Erling Smørgrav return -1; 697b7579f77SDag-Erling Smørgrav if(len1 > len2) 698b7579f77SDag-Erling Smørgrav return 1; 699b7579f77SDag-Erling Smørgrav log_assert(len1 == len2); 700b7579f77SDag-Erling Smørgrav if( p1_in->sin_family < p2_in->sin_family) 701b7579f77SDag-Erling Smørgrav return -1; 702b7579f77SDag-Erling Smørgrav if( p1_in->sin_family > p2_in->sin_family) 703b7579f77SDag-Erling Smørgrav return 1; 704b7579f77SDag-Erling Smørgrav log_assert( p1_in->sin_family == p2_in->sin_family ); 705b7579f77SDag-Erling Smørgrav /* compare ip4 */ 706b7579f77SDag-Erling Smørgrav if( p1_in->sin_family == AF_INET ) { 707b7579f77SDag-Erling Smørgrav return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE); 708b7579f77SDag-Erling Smørgrav } else if (p1_in6->sin6_family == AF_INET6) { 709b7579f77SDag-Erling Smørgrav return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr, 710b7579f77SDag-Erling Smørgrav INET6_SIZE); 711b7579f77SDag-Erling Smørgrav } else { 712b7579f77SDag-Erling Smørgrav /* eek unknown type, perform this comparison for sanity. */ 713b7579f77SDag-Erling Smørgrav return memcmp(addr1, addr2, len1); 714b7579f77SDag-Erling Smørgrav } 715b7579f77SDag-Erling Smørgrav } 716b7579f77SDag-Erling Smørgrav 717b7579f77SDag-Erling Smørgrav int 718b7579f77SDag-Erling Smørgrav addr_is_ip6(struct sockaddr_storage* addr, socklen_t len) 719b7579f77SDag-Erling Smørgrav { 720b7579f77SDag-Erling Smørgrav if(len == (socklen_t)sizeof(struct sockaddr_in6) && 721b7579f77SDag-Erling Smørgrav ((struct sockaddr_in6*)addr)->sin6_family == AF_INET6) 722b7579f77SDag-Erling Smørgrav return 1; 723b7579f77SDag-Erling Smørgrav else return 0; 724b7579f77SDag-Erling Smørgrav } 725b7579f77SDag-Erling Smørgrav 726b7579f77SDag-Erling Smørgrav void 727b7579f77SDag-Erling Smørgrav addr_mask(struct sockaddr_storage* addr, socklen_t len, int net) 728b7579f77SDag-Erling Smørgrav { 729b7579f77SDag-Erling Smørgrav uint8_t mask[8] = {0x0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe}; 730b7579f77SDag-Erling Smørgrav int i, max; 731b7579f77SDag-Erling Smørgrav uint8_t* s; 732b7579f77SDag-Erling Smørgrav if(addr_is_ip6(addr, len)) { 733b7579f77SDag-Erling Smørgrav s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr; 734b7579f77SDag-Erling Smørgrav max = 128; 735b7579f77SDag-Erling Smørgrav } else { 736b7579f77SDag-Erling Smørgrav s = (uint8_t*)&((struct sockaddr_in*)addr)->sin_addr; 737b7579f77SDag-Erling Smørgrav max = 32; 738b7579f77SDag-Erling Smørgrav } 739b7579f77SDag-Erling Smørgrav if(net >= max) 740b7579f77SDag-Erling Smørgrav return; 741b7579f77SDag-Erling Smørgrav for(i=net/8+1; i<max/8; i++) { 742b7579f77SDag-Erling Smørgrav s[i] = 0; 743b7579f77SDag-Erling Smørgrav } 744b7579f77SDag-Erling Smørgrav s[net/8] &= mask[net&0x7]; 745b7579f77SDag-Erling Smørgrav } 746b7579f77SDag-Erling Smørgrav 747b7579f77SDag-Erling Smørgrav int 748b7579f77SDag-Erling Smørgrav addr_in_common(struct sockaddr_storage* addr1, int net1, 749b7579f77SDag-Erling Smørgrav struct sockaddr_storage* addr2, int net2, socklen_t addrlen) 750b7579f77SDag-Erling Smørgrav { 751b7579f77SDag-Erling Smørgrav int min = (net1<net2)?net1:net2; 752b7579f77SDag-Erling Smørgrav int i, to; 753b7579f77SDag-Erling Smørgrav int match = 0; 754b7579f77SDag-Erling Smørgrav uint8_t* s1, *s2; 755b7579f77SDag-Erling Smørgrav if(addr_is_ip6(addr1, addrlen)) { 756b7579f77SDag-Erling Smørgrav s1 = (uint8_t*)&((struct sockaddr_in6*)addr1)->sin6_addr; 757b7579f77SDag-Erling Smørgrav s2 = (uint8_t*)&((struct sockaddr_in6*)addr2)->sin6_addr; 758b7579f77SDag-Erling Smørgrav to = 16; 759b7579f77SDag-Erling Smørgrav } else { 760b7579f77SDag-Erling Smørgrav s1 = (uint8_t*)&((struct sockaddr_in*)addr1)->sin_addr; 761b7579f77SDag-Erling Smørgrav s2 = (uint8_t*)&((struct sockaddr_in*)addr2)->sin_addr; 762b7579f77SDag-Erling Smørgrav to = 4; 763b7579f77SDag-Erling Smørgrav } 764b7579f77SDag-Erling Smørgrav /* match = bits_in_common(s1, s2, to); */ 765b7579f77SDag-Erling Smørgrav for(i=0; i<to; i++) { 766b7579f77SDag-Erling Smørgrav if(s1[i] == s2[i]) { 767b7579f77SDag-Erling Smørgrav match += 8; 768b7579f77SDag-Erling Smørgrav } else { 769b7579f77SDag-Erling Smørgrav uint8_t z = s1[i]^s2[i]; 770b7579f77SDag-Erling Smørgrav log_assert(z); 771b7579f77SDag-Erling Smørgrav while(!(z&0x80)) { 772b7579f77SDag-Erling Smørgrav match++; 773b7579f77SDag-Erling Smørgrav z<<=1; 774b7579f77SDag-Erling Smørgrav } 775b7579f77SDag-Erling Smørgrav break; 776b7579f77SDag-Erling Smørgrav } 777b7579f77SDag-Erling Smørgrav } 778b7579f77SDag-Erling Smørgrav if(match > min) match = min; 779b7579f77SDag-Erling Smørgrav return match; 780b7579f77SDag-Erling Smørgrav } 781b7579f77SDag-Erling Smørgrav 782b7579f77SDag-Erling Smørgrav void 783b7579f77SDag-Erling Smørgrav addr_to_str(struct sockaddr_storage* addr, socklen_t addrlen, 784b7579f77SDag-Erling Smørgrav char* buf, size_t len) 785b7579f77SDag-Erling Smørgrav { 786b7579f77SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family; 787b7579f77SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 788b7579f77SDag-Erling Smørgrav if(addr_is_ip6(addr, addrlen)) 789b7579f77SDag-Erling Smørgrav sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; 790b7579f77SDag-Erling Smørgrav if(inet_ntop(af, sinaddr, buf, (socklen_t)len) == 0) { 791b7579f77SDag-Erling Smørgrav snprintf(buf, len, "(inet_ntop_error)"); 792b7579f77SDag-Erling Smørgrav } 793b7579f77SDag-Erling Smørgrav } 794b7579f77SDag-Erling Smørgrav 795b7579f77SDag-Erling Smørgrav int 796*8f76bb7dSCy Schubert prefixnet_is_nat64(int prefixnet) 797*8f76bb7dSCy Schubert { 798*8f76bb7dSCy Schubert return (prefixnet == 32 || prefixnet == 40 || 799*8f76bb7dSCy Schubert prefixnet == 48 || prefixnet == 56 || 800*8f76bb7dSCy Schubert prefixnet == 64 || prefixnet == 96); 801*8f76bb7dSCy Schubert } 802*8f76bb7dSCy Schubert 803*8f76bb7dSCy Schubert void 804*8f76bb7dSCy Schubert addr_to_nat64(const struct sockaddr_storage* addr, 805*8f76bb7dSCy Schubert const struct sockaddr_storage* nat64_prefix, 806*8f76bb7dSCy Schubert socklen_t nat64_prefixlen, int nat64_prefixnet, 807*8f76bb7dSCy Schubert struct sockaddr_storage* nat64_addr, socklen_t* nat64_addrlen) 808*8f76bb7dSCy Schubert { 809*8f76bb7dSCy Schubert struct sockaddr_in *sin = (struct sockaddr_in *)addr; 810*8f76bb7dSCy Schubert struct sockaddr_in6 *sin6; 811*8f76bb7dSCy Schubert uint8_t *v4_byte; 812*8f76bb7dSCy Schubert 813*8f76bb7dSCy Schubert /* This needs to be checked by the caller */ 814*8f76bb7dSCy Schubert log_assert(addr->ss_family == AF_INET); 815*8f76bb7dSCy Schubert /* Current usage is only from config values; prefix lengths enforced 816*8f76bb7dSCy Schubert * during config validation */ 817*8f76bb7dSCy Schubert log_assert(prefixnet_is_nat64(nat64_prefixnet)); 818*8f76bb7dSCy Schubert 819*8f76bb7dSCy Schubert *nat64_addr = *nat64_prefix; 820*8f76bb7dSCy Schubert *nat64_addrlen = nat64_prefixlen; 821*8f76bb7dSCy Schubert 822*8f76bb7dSCy Schubert sin6 = (struct sockaddr_in6 *)nat64_addr; 823*8f76bb7dSCy Schubert sin6->sin6_flowinfo = 0; 824*8f76bb7dSCy Schubert sin6->sin6_port = sin->sin_port; 825*8f76bb7dSCy Schubert 826*8f76bb7dSCy Schubert nat64_prefixnet = nat64_prefixnet / 8; 827*8f76bb7dSCy Schubert 828*8f76bb7dSCy Schubert v4_byte = (uint8_t *)&sin->sin_addr.s_addr; 829*8f76bb7dSCy Schubert for(int i = 0; i < 4; i++) { 830*8f76bb7dSCy Schubert if(nat64_prefixnet == 8) { 831*8f76bb7dSCy Schubert /* bits 64...71 are MBZ */ 832*8f76bb7dSCy Schubert sin6->sin6_addr.s6_addr[nat64_prefixnet++] = 0; 833*8f76bb7dSCy Schubert } 834*8f76bb7dSCy Schubert sin6->sin6_addr.s6_addr[nat64_prefixnet++] = *v4_byte++; 835*8f76bb7dSCy Schubert } 836*8f76bb7dSCy Schubert } 837*8f76bb7dSCy Schubert 838*8f76bb7dSCy Schubert int 839b7579f77SDag-Erling Smørgrav addr_is_ip4mapped(struct sockaddr_storage* addr, socklen_t addrlen) 840b7579f77SDag-Erling Smørgrav { 841b7579f77SDag-Erling Smørgrav /* prefix for ipv4 into ipv6 mapping is ::ffff:x.x.x.x */ 842b7579f77SDag-Erling Smørgrav const uint8_t map_prefix[16] = 843b7579f77SDag-Erling Smørgrav {0,0,0,0, 0,0,0,0, 0,0,0xff,0xff, 0,0,0,0}; 844b7579f77SDag-Erling Smørgrav uint8_t* s; 845b7579f77SDag-Erling Smørgrav if(!addr_is_ip6(addr, addrlen)) 846b7579f77SDag-Erling Smørgrav return 0; 847b7579f77SDag-Erling Smørgrav /* s is 16 octet ipv6 address string */ 848b7579f77SDag-Erling Smørgrav s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr; 849b7579f77SDag-Erling Smørgrav return (memcmp(s, map_prefix, 12) == 0); 850b7579f77SDag-Erling Smørgrav } 851b7579f77SDag-Erling Smørgrav 852b7579f77SDag-Erling Smørgrav int addr_is_broadcast(struct sockaddr_storage* addr, socklen_t addrlen) 853b7579f77SDag-Erling Smørgrav { 854b7579f77SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family; 855b7579f77SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 856b7579f77SDag-Erling Smørgrav return af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in) 857b7579f77SDag-Erling Smørgrav && memcmp(sinaddr, "\377\377\377\377", 4) == 0; 858b7579f77SDag-Erling Smørgrav } 859b7579f77SDag-Erling Smørgrav 860b7579f77SDag-Erling Smørgrav int addr_is_any(struct sockaddr_storage* addr, socklen_t addrlen) 861b7579f77SDag-Erling Smørgrav { 862b7579f77SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family; 863b7579f77SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 864b7579f77SDag-Erling Smørgrav void* sin6addr = &((struct sockaddr_in6*)addr)->sin6_addr; 865b7579f77SDag-Erling Smørgrav if(af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in) 866b7579f77SDag-Erling Smørgrav && memcmp(sinaddr, "\000\000\000\000", 4) == 0) 867b7579f77SDag-Erling Smørgrav return 1; 868b7579f77SDag-Erling Smørgrav else if(af==AF_INET6 && addrlen>=(socklen_t)sizeof(struct sockaddr_in6) 869b7579f77SDag-Erling Smørgrav && memcmp(sin6addr, "\000\000\000\000\000\000\000\000" 870b7579f77SDag-Erling Smørgrav "\000\000\000\000\000\000\000\000", 16) == 0) 871b7579f77SDag-Erling Smørgrav return 1; 872b7579f77SDag-Erling Smørgrav return 0; 873b7579f77SDag-Erling Smørgrav } 874b7579f77SDag-Erling Smørgrav 875b7579f77SDag-Erling Smørgrav void sock_list_insert(struct sock_list** list, struct sockaddr_storage* addr, 876b7579f77SDag-Erling Smørgrav socklen_t len, struct regional* region) 877b7579f77SDag-Erling Smørgrav { 878b7579f77SDag-Erling Smørgrav struct sock_list* add = (struct sock_list*)regional_alloc(region, 879b7579f77SDag-Erling Smørgrav sizeof(*add) - sizeof(add->addr) + (size_t)len); 880b7579f77SDag-Erling Smørgrav if(!add) { 881b7579f77SDag-Erling Smørgrav log_err("out of memory in socketlist insert"); 882b7579f77SDag-Erling Smørgrav return; 883b7579f77SDag-Erling Smørgrav } 884b7579f77SDag-Erling Smørgrav log_assert(list); 885b7579f77SDag-Erling Smørgrav add->next = *list; 886b7579f77SDag-Erling Smørgrav add->len = len; 887b7579f77SDag-Erling Smørgrav *list = add; 888b7579f77SDag-Erling Smørgrav if(len) memmove(&add->addr, addr, len); 889b7579f77SDag-Erling Smørgrav } 890b7579f77SDag-Erling Smørgrav 891b7579f77SDag-Erling Smørgrav void sock_list_prepend(struct sock_list** list, struct sock_list* add) 892b7579f77SDag-Erling Smørgrav { 893b7579f77SDag-Erling Smørgrav struct sock_list* last = add; 894b7579f77SDag-Erling Smørgrav if(!last) 895b7579f77SDag-Erling Smørgrav return; 896b7579f77SDag-Erling Smørgrav while(last->next) 897b7579f77SDag-Erling Smørgrav last = last->next; 898b7579f77SDag-Erling Smørgrav last->next = *list; 899b7579f77SDag-Erling Smørgrav *list = add; 900b7579f77SDag-Erling Smørgrav } 901b7579f77SDag-Erling Smørgrav 902b7579f77SDag-Erling Smørgrav int sock_list_find(struct sock_list* list, struct sockaddr_storage* addr, 903b7579f77SDag-Erling Smørgrav socklen_t len) 904b7579f77SDag-Erling Smørgrav { 905b7579f77SDag-Erling Smørgrav while(list) { 906b7579f77SDag-Erling Smørgrav if(len == list->len) { 907b7579f77SDag-Erling Smørgrav if(len == 0 || sockaddr_cmp_addr(addr, len, 908b7579f77SDag-Erling Smørgrav &list->addr, list->len) == 0) 909b7579f77SDag-Erling Smørgrav return 1; 910b7579f77SDag-Erling Smørgrav } 911b7579f77SDag-Erling Smørgrav list = list->next; 912b7579f77SDag-Erling Smørgrav } 913b7579f77SDag-Erling Smørgrav return 0; 914b7579f77SDag-Erling Smørgrav } 915b7579f77SDag-Erling Smørgrav 916b7579f77SDag-Erling Smørgrav void sock_list_merge(struct sock_list** list, struct regional* region, 917b7579f77SDag-Erling Smørgrav struct sock_list* add) 918b7579f77SDag-Erling Smørgrav { 919b7579f77SDag-Erling Smørgrav struct sock_list* p; 920b7579f77SDag-Erling Smørgrav for(p=add; p; p=p->next) { 921b7579f77SDag-Erling Smørgrav if(!sock_list_find(*list, &p->addr, p->len)) 922b7579f77SDag-Erling Smørgrav sock_list_insert(list, &p->addr, p->len, region); 923b7579f77SDag-Erling Smørgrav } 924b7579f77SDag-Erling Smørgrav } 925b7579f77SDag-Erling Smørgrav 926b7579f77SDag-Erling Smørgrav void 927b7579f77SDag-Erling Smørgrav log_crypto_err(const char* str) 928b7579f77SDag-Erling Smørgrav { 9298ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL 9300eefd307SCy Schubert log_crypto_err_code(str, ERR_get_error()); 9310eefd307SCy Schubert #else 9320eefd307SCy Schubert (void)str; 9330eefd307SCy Schubert #endif /* HAVE_SSL */ 9340eefd307SCy Schubert } 9350eefd307SCy Schubert 9360eefd307SCy Schubert void log_crypto_err_code(const char* str, unsigned long err) 9370eefd307SCy Schubert { 9380eefd307SCy Schubert #ifdef HAVE_SSL 939b7579f77SDag-Erling Smørgrav /* error:[error code]:[library name]:[function name]:[reason string] */ 940b7579f77SDag-Erling Smørgrav char buf[128]; 941b7579f77SDag-Erling Smørgrav unsigned long e; 9420eefd307SCy Schubert ERR_error_string_n(err, buf, sizeof(buf)); 943b7579f77SDag-Erling Smørgrav log_err("%s crypto %s", str, buf); 944b7579f77SDag-Erling Smørgrav while( (e=ERR_get_error()) ) { 945b7579f77SDag-Erling Smørgrav ERR_error_string_n(e, buf, sizeof(buf)); 946b7579f77SDag-Erling Smørgrav log_err("and additionally crypto %s", buf); 947b7579f77SDag-Erling Smørgrav } 9488ed2b524SDag-Erling Smørgrav #else 9498ed2b524SDag-Erling Smørgrav (void)str; 9500eefd307SCy Schubert (void)err; 9518ed2b524SDag-Erling Smørgrav #endif /* HAVE_SSL */ 952b7579f77SDag-Erling Smørgrav } 953b7579f77SDag-Erling Smørgrav 95425039b37SCy Schubert #ifdef HAVE_SSL 95525039b37SCy Schubert /** log certificate details */ 95625039b37SCy Schubert void 95725039b37SCy Schubert log_cert(unsigned level, const char* str, void* cert) 95825039b37SCy Schubert { 95925039b37SCy Schubert BIO* bio; 96025039b37SCy Schubert char nul = 0; 96125039b37SCy Schubert char* pp = NULL; 96225039b37SCy Schubert long len; 96325039b37SCy Schubert if(verbosity < level) return; 96425039b37SCy Schubert bio = BIO_new(BIO_s_mem()); 96525039b37SCy Schubert if(!bio) return; 96625039b37SCy Schubert X509_print_ex(bio, (X509*)cert, 0, (unsigned long)-1 96725039b37SCy Schubert ^(X509_FLAG_NO_SUBJECT 96825039b37SCy Schubert |X509_FLAG_NO_ISSUER|X509_FLAG_NO_VALIDITY 96925039b37SCy Schubert |X509_FLAG_NO_EXTENSIONS|X509_FLAG_NO_AUX 97025039b37SCy Schubert |X509_FLAG_NO_ATTRIBUTES)); 97125039b37SCy Schubert BIO_write(bio, &nul, (int)sizeof(nul)); 97225039b37SCy Schubert len = BIO_get_mem_data(bio, &pp); 97325039b37SCy Schubert if(len != 0 && pp) { 97424e36522SCy Schubert /* reduce size of cert printout */ 97524e36522SCy Schubert char* s; 97624e36522SCy Schubert while((s=strstr(pp, " "))!=NULL) 97724e36522SCy Schubert memmove(s, s+1, strlen(s+1)+1); 97824e36522SCy Schubert while((s=strstr(pp, "\t\t"))!=NULL) 97924e36522SCy Schubert memmove(s, s+1, strlen(s+1)+1); 98025039b37SCy Schubert verbose(level, "%s: \n%s", str, pp); 98125039b37SCy Schubert } 98225039b37SCy Schubert BIO_free(bio); 98325039b37SCy Schubert } 98425039b37SCy Schubert #endif /* HAVE_SSL */ 98525039b37SCy Schubert 9865469a995SCy Schubert #if defined(HAVE_SSL) && defined(HAVE_NGHTTP2) && defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB) 987c0caa2e2SCy Schubert static int alpn_select_cb(SSL* ATTR_UNUSED(ssl), const unsigned char** out, 988c0caa2e2SCy Schubert unsigned char* outlen, const unsigned char* in, unsigned int inlen, 989c0caa2e2SCy Schubert void* ATTR_UNUSED(arg)) 990c0caa2e2SCy Schubert { 991c0caa2e2SCy Schubert int rv = nghttp2_select_next_protocol((unsigned char **)out, outlen, in, 992c0caa2e2SCy Schubert inlen); 993c0caa2e2SCy Schubert if(rv == -1) { 994c0caa2e2SCy Schubert return SSL_TLSEXT_ERR_NOACK; 995c0caa2e2SCy Schubert } 996c0caa2e2SCy Schubert /* either http/1.1 or h2 selected */ 997c0caa2e2SCy Schubert return SSL_TLSEXT_ERR_OK; 998c0caa2e2SCy Schubert } 999c0caa2e2SCy Schubert #endif 1000c0caa2e2SCy Schubert 1001971980c3SDag-Erling Smørgrav int 1002971980c3SDag-Erling Smørgrav listen_sslctx_setup(void* ctxt) 1003971980c3SDag-Erling Smørgrav { 1004971980c3SDag-Erling Smørgrav #ifdef HAVE_SSL 1005971980c3SDag-Erling Smørgrav SSL_CTX* ctx = (SSL_CTX*)ctxt; 1006971980c3SDag-Erling Smørgrav /* no SSLv2, SSLv3 because has defects */ 1007091e9e46SCy Schubert #if SSL_OP_NO_SSLv2 != 0 1008971980c3SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2) 1009971980c3SDag-Erling Smørgrav != SSL_OP_NO_SSLv2){ 1010971980c3SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_NO_SSLv2"); 1011971980c3SDag-Erling Smørgrav return 0; 1012971980c3SDag-Erling Smørgrav } 1013091e9e46SCy Schubert #endif 1014971980c3SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3) 1015971980c3SDag-Erling Smørgrav != SSL_OP_NO_SSLv3){ 1016971980c3SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_NO_SSLv3"); 1017971980c3SDag-Erling Smørgrav return 0; 1018971980c3SDag-Erling Smørgrav } 1019971980c3SDag-Erling Smørgrav #if defined(SSL_OP_NO_TLSv1) && defined(SSL_OP_NO_TLSv1_1) 1020971980c3SDag-Erling Smørgrav /* if we have tls 1.1 disable 1.0 */ 1021971980c3SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1) & SSL_OP_NO_TLSv1) 1022971980c3SDag-Erling Smørgrav != SSL_OP_NO_TLSv1){ 1023971980c3SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_NO_TLSv1"); 1024971980c3SDag-Erling Smørgrav return 0; 1025971980c3SDag-Erling Smørgrav } 1026971980c3SDag-Erling Smørgrav #endif 1027971980c3SDag-Erling Smørgrav #if defined(SSL_OP_NO_TLSv1_1) && defined(SSL_OP_NO_TLSv1_2) 1028971980c3SDag-Erling Smørgrav /* if we have tls 1.2 disable 1.1 */ 1029971980c3SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_1) & SSL_OP_NO_TLSv1_1) 1030971980c3SDag-Erling Smørgrav != SSL_OP_NO_TLSv1_1){ 1031971980c3SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_NO_TLSv1_1"); 1032971980c3SDag-Erling Smørgrav return 0; 1033971980c3SDag-Erling Smørgrav } 1034971980c3SDag-Erling Smørgrav #endif 10350eefd307SCy Schubert #if defined(SSL_OP_NO_RENEGOTIATION) 10360eefd307SCy Schubert /* disable client renegotiation */ 10370eefd307SCy Schubert if((SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION) & 10380eefd307SCy Schubert SSL_OP_NO_RENEGOTIATION) != SSL_OP_NO_RENEGOTIATION) { 10390eefd307SCy Schubert log_crypto_err("could not set SSL_OP_NO_RENEGOTIATION"); 10400eefd307SCy Schubert return 0; 10410eefd307SCy Schubert } 10420eefd307SCy Schubert #endif 1043971980c3SDag-Erling Smørgrav #if defined(SHA256_DIGEST_LENGTH) && defined(USE_ECDSA) 104424e36522SCy Schubert /* if we detect system-wide crypto policies, use those */ 104524e36522SCy Schubert if (access( "/etc/crypto-policies/config", F_OK ) != 0 ) { 1046971980c3SDag-Erling Smørgrav /* if we have sha256, set the cipher list to have no known vulns */ 104757bddd21SDag-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")) 1048971980c3SDag-Erling Smørgrav log_crypto_err("could not set cipher list with SSL_CTX_set_cipher_list"); 104924e36522SCy Schubert } 1050971980c3SDag-Erling Smørgrav #endif 1051*8f76bb7dSCy Schubert #if defined(SSL_OP_IGNORE_UNEXPECTED_EOF) 1052*8f76bb7dSCy Schubert /* ignore errors when peers do not send the mandatory close_notify 1053*8f76bb7dSCy Schubert * alert on shutdown. 1054*8f76bb7dSCy Schubert * Relevant for openssl >= 3 */ 1055*8f76bb7dSCy Schubert if((SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF) & 1056*8f76bb7dSCy Schubert SSL_OP_IGNORE_UNEXPECTED_EOF) != SSL_OP_IGNORE_UNEXPECTED_EOF) { 1057*8f76bb7dSCy Schubert log_crypto_err("could not set SSL_OP_IGNORE_UNEXPECTED_EOF"); 1058*8f76bb7dSCy Schubert return 0; 1059*8f76bb7dSCy Schubert } 1060*8f76bb7dSCy Schubert #endif 1061971980c3SDag-Erling Smørgrav 1062971980c3SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE) & 1063971980c3SDag-Erling Smørgrav SSL_OP_CIPHER_SERVER_PREFERENCE) != 1064971980c3SDag-Erling Smørgrav SSL_OP_CIPHER_SERVER_PREFERENCE) { 1065971980c3SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_CIPHER_SERVER_PREFERENCE"); 1066971980c3SDag-Erling Smørgrav return 0; 1067971980c3SDag-Erling Smørgrav } 1068971980c3SDag-Erling Smørgrav 1069971980c3SDag-Erling Smørgrav #ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL 1070971980c3SDag-Erling Smørgrav SSL_CTX_set_security_level(ctx, 0); 1071971980c3SDag-Erling Smørgrav #endif 1072c0caa2e2SCy Schubert #if defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB) && defined(HAVE_NGHTTP2) 1073c0caa2e2SCy Schubert SSL_CTX_set_alpn_select_cb(ctx, alpn_select_cb, NULL); 1074c0caa2e2SCy Schubert #endif 1075971980c3SDag-Erling Smørgrav #else 1076971980c3SDag-Erling Smørgrav (void)ctxt; 1077971980c3SDag-Erling Smørgrav #endif /* HAVE_SSL */ 1078971980c3SDag-Erling Smørgrav return 1; 1079971980c3SDag-Erling Smørgrav } 1080971980c3SDag-Erling Smørgrav 1081971980c3SDag-Erling Smørgrav void 1082971980c3SDag-Erling Smørgrav listen_sslctx_setup_2(void* ctxt) 1083971980c3SDag-Erling Smørgrav { 1084971980c3SDag-Erling Smørgrav #ifdef HAVE_SSL 1085971980c3SDag-Erling Smørgrav SSL_CTX* ctx = (SSL_CTX*)ctxt; 1086971980c3SDag-Erling Smørgrav (void)ctx; 1087971980c3SDag-Erling Smørgrav #if HAVE_DECL_SSL_CTX_SET_ECDH_AUTO 1088971980c3SDag-Erling Smørgrav if(!SSL_CTX_set_ecdh_auto(ctx,1)) { 1089971980c3SDag-Erling Smørgrav log_crypto_err("Error in SSL_CTX_ecdh_auto, not enabling ECDHE"); 1090971980c3SDag-Erling Smørgrav } 1091971980c3SDag-Erling Smørgrav #elif defined(USE_ECDSA) 1092971980c3SDag-Erling Smørgrav if(1) { 1093971980c3SDag-Erling Smørgrav EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1); 1094971980c3SDag-Erling Smørgrav if (!ecdh) { 1095971980c3SDag-Erling Smørgrav log_crypto_err("could not find p256, not enabling ECDHE"); 1096971980c3SDag-Erling Smørgrav } else { 1097971980c3SDag-Erling Smørgrav if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh)) { 1098971980c3SDag-Erling Smørgrav log_crypto_err("Error in SSL_CTX_set_tmp_ecdh, not enabling ECDHE"); 1099971980c3SDag-Erling Smørgrav } 1100971980c3SDag-Erling Smørgrav EC_KEY_free (ecdh); 1101971980c3SDag-Erling Smørgrav } 1102971980c3SDag-Erling Smørgrav } 1103971980c3SDag-Erling Smørgrav #endif 1104971980c3SDag-Erling Smørgrav #else 1105971980c3SDag-Erling Smørgrav (void)ctxt; 1106971980c3SDag-Erling Smørgrav #endif /* HAVE_SSL */ 1107971980c3SDag-Erling Smørgrav } 1108971980c3SDag-Erling Smørgrav 1109b7579f77SDag-Erling Smørgrav void* listen_sslctx_create(char* key, char* pem, char* verifypem) 1110b7579f77SDag-Erling Smørgrav { 11118ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL 1112b7579f77SDag-Erling Smørgrav SSL_CTX* ctx = SSL_CTX_new(SSLv23_server_method()); 1113b7579f77SDag-Erling Smørgrav if(!ctx) { 1114b7579f77SDag-Erling Smørgrav log_crypto_err("could not SSL_CTX_new"); 1115b7579f77SDag-Erling Smørgrav return NULL; 1116b7579f77SDag-Erling Smørgrav } 1117e86b9096SDag-Erling Smørgrav if(!key || key[0] == 0) { 1118e86b9096SDag-Erling Smørgrav log_err("error: no tls-service-key file specified"); 1119e86b9096SDag-Erling Smørgrav SSL_CTX_free(ctx); 1120e86b9096SDag-Erling Smørgrav return NULL; 1121e86b9096SDag-Erling Smørgrav } 1122e86b9096SDag-Erling Smørgrav if(!pem || pem[0] == 0) { 1123e86b9096SDag-Erling Smørgrav log_err("error: no tls-service-pem file specified"); 1124e86b9096SDag-Erling Smørgrav SSL_CTX_free(ctx); 1125e86b9096SDag-Erling Smørgrav return NULL; 1126e86b9096SDag-Erling Smørgrav } 1127971980c3SDag-Erling Smørgrav if(!listen_sslctx_setup(ctx)) { 1128ff825849SDag-Erling Smørgrav SSL_CTX_free(ctx); 1129ff825849SDag-Erling Smørgrav return NULL; 1130ff825849SDag-Erling Smørgrav } 1131b75612f8SDag-Erling Smørgrav if(!SSL_CTX_use_certificate_chain_file(ctx, pem)) { 1132b7579f77SDag-Erling Smørgrav log_err("error for cert file: %s", pem); 1133b75612f8SDag-Erling Smørgrav log_crypto_err("error in SSL_CTX use_certificate_chain_file"); 1134b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 1135b7579f77SDag-Erling Smørgrav return NULL; 1136b7579f77SDag-Erling Smørgrav } 1137b7579f77SDag-Erling Smørgrav if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) { 1138b7579f77SDag-Erling Smørgrav log_err("error for private key file: %s", key); 1139b7579f77SDag-Erling Smørgrav log_crypto_err("Error in SSL_CTX use_PrivateKey_file"); 1140b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 1141b7579f77SDag-Erling Smørgrav return NULL; 1142b7579f77SDag-Erling Smørgrav } 1143b7579f77SDag-Erling Smørgrav if(!SSL_CTX_check_private_key(ctx)) { 1144b7579f77SDag-Erling Smørgrav log_err("error for key file: %s", key); 1145b7579f77SDag-Erling Smørgrav log_crypto_err("Error in SSL_CTX check_private_key"); 1146b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 1147b7579f77SDag-Erling Smørgrav return NULL; 1148b7579f77SDag-Erling Smørgrav } 1149971980c3SDag-Erling Smørgrav listen_sslctx_setup_2(ctx); 1150b7579f77SDag-Erling Smørgrav if(verifypem && verifypem[0]) { 1151b7579f77SDag-Erling Smørgrav if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) { 1152b7579f77SDag-Erling Smørgrav log_crypto_err("Error in SSL_CTX verify locations"); 1153b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 1154b7579f77SDag-Erling Smørgrav return NULL; 1155b7579f77SDag-Erling Smørgrav } 1156b7579f77SDag-Erling Smørgrav SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file( 1157b7579f77SDag-Erling Smørgrav verifypem)); 115825039b37SCy Schubert SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); 1159b7579f77SDag-Erling Smørgrav } 1160b7579f77SDag-Erling Smørgrav return ctx; 11618ed2b524SDag-Erling Smørgrav #else 11628ed2b524SDag-Erling Smørgrav (void)key; (void)pem; (void)verifypem; 11638ed2b524SDag-Erling Smørgrav return NULL; 11648ed2b524SDag-Erling Smørgrav #endif 1165b7579f77SDag-Erling Smørgrav } 1166b7579f77SDag-Erling Smørgrav 11673bd4df0aSDag-Erling Smørgrav #ifdef USE_WINSOCK 11683bd4df0aSDag-Erling Smørgrav /* For windows, the CA trust store is not read by openssl. 11693bd4df0aSDag-Erling Smørgrav Add code to open the trust store using wincrypt API and add 11703bd4df0aSDag-Erling Smørgrav the root certs into openssl trust store */ 11713bd4df0aSDag-Erling Smørgrav static int 11723bd4df0aSDag-Erling Smørgrav add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx) 11733bd4df0aSDag-Erling Smørgrav { 11743bd4df0aSDag-Erling Smørgrav HCERTSTORE hSystemStore; 11753bd4df0aSDag-Erling Smørgrav PCCERT_CONTEXT pTargetCert = NULL; 11763bd4df0aSDag-Erling Smørgrav X509_STORE* store; 11773bd4df0aSDag-Erling Smørgrav 11783bd4df0aSDag-Erling Smørgrav verbose(VERB_ALGO, "Adding Windows certificates from system root store to CA store"); 11793bd4df0aSDag-Erling Smørgrav 11803bd4df0aSDag-Erling Smørgrav /* load just once per context lifetime for this version 11813bd4df0aSDag-Erling Smørgrav TODO: dynamically update CA trust changes as they are available */ 11823bd4df0aSDag-Erling Smørgrav if (!tls_ctx) 11833bd4df0aSDag-Erling Smørgrav return 0; 11843bd4df0aSDag-Erling Smørgrav 11853bd4df0aSDag-Erling Smørgrav /* Call wincrypt's CertOpenStore to open the CA root store. */ 11863bd4df0aSDag-Erling Smørgrav 11873bd4df0aSDag-Erling Smørgrav if ((hSystemStore = CertOpenStore( 11883bd4df0aSDag-Erling Smørgrav CERT_STORE_PROV_SYSTEM, 11893bd4df0aSDag-Erling Smørgrav 0, 11903bd4df0aSDag-Erling Smørgrav 0, 11913bd4df0aSDag-Erling Smørgrav /* NOTE: mingw does not have this const: replace with 1 << 16 from code 11923bd4df0aSDag-Erling Smørgrav CERT_SYSTEM_STORE_CURRENT_USER, */ 11933bd4df0aSDag-Erling Smørgrav 1 << 16, 11943bd4df0aSDag-Erling Smørgrav L"root")) == 0) 11953bd4df0aSDag-Erling Smørgrav { 11963bd4df0aSDag-Erling Smørgrav return 0; 11973bd4df0aSDag-Erling Smørgrav } 11983bd4df0aSDag-Erling Smørgrav 11993bd4df0aSDag-Erling Smørgrav store = SSL_CTX_get_cert_store(tls_ctx); 12003bd4df0aSDag-Erling Smørgrav if (!store) 12013bd4df0aSDag-Erling Smørgrav return 0; 12023bd4df0aSDag-Erling Smørgrav 12033bd4df0aSDag-Erling Smørgrav /* failure if the CA store is empty or the call fails */ 12043bd4df0aSDag-Erling Smørgrav if ((pTargetCert = CertEnumCertificatesInStore( 12053bd4df0aSDag-Erling Smørgrav hSystemStore, pTargetCert)) == 0) { 12063bd4df0aSDag-Erling Smørgrav verbose(VERB_ALGO, "CA certificate store for Windows is empty."); 12073bd4df0aSDag-Erling Smørgrav return 0; 12083bd4df0aSDag-Erling Smørgrav } 12093bd4df0aSDag-Erling Smørgrav /* iterate over the windows cert store and add to openssl store */ 12103bd4df0aSDag-Erling Smørgrav do 12113bd4df0aSDag-Erling Smørgrav { 12123bd4df0aSDag-Erling Smørgrav X509 *cert1 = d2i_X509(NULL, 12133bd4df0aSDag-Erling Smørgrav (const unsigned char **)&pTargetCert->pbCertEncoded, 12143bd4df0aSDag-Erling Smørgrav pTargetCert->cbCertEncoded); 12153bd4df0aSDag-Erling Smørgrav if (!cert1) { 12160a92a9fcSCy Schubert unsigned long error = ERR_get_error(); 12173bd4df0aSDag-Erling Smørgrav /* return error if a cert fails */ 12183bd4df0aSDag-Erling Smørgrav verbose(VERB_ALGO, "%s %d:%s", 12193bd4df0aSDag-Erling Smørgrav "Unable to parse certificate in memory", 12200a92a9fcSCy Schubert (int)error, ERR_error_string(error, NULL)); 12213bd4df0aSDag-Erling Smørgrav return 0; 12223bd4df0aSDag-Erling Smørgrav } 12233bd4df0aSDag-Erling Smørgrav else { 12243bd4df0aSDag-Erling Smørgrav /* return error if a cert add to store fails */ 12253bd4df0aSDag-Erling Smørgrav if (X509_STORE_add_cert(store, cert1) == 0) { 12263bd4df0aSDag-Erling Smørgrav unsigned long error = ERR_peek_last_error(); 12273bd4df0aSDag-Erling Smørgrav 12283bd4df0aSDag-Erling Smørgrav /* Ignore error X509_R_CERT_ALREADY_IN_HASH_TABLE which means the 12293bd4df0aSDag-Erling Smørgrav * certificate is already in the store. */ 12303bd4df0aSDag-Erling Smørgrav if(ERR_GET_LIB(error) != ERR_LIB_X509 || 12313bd4df0aSDag-Erling Smørgrav ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) { 12320a92a9fcSCy Schubert error = ERR_get_error(); 12333bd4df0aSDag-Erling Smørgrav verbose(VERB_ALGO, "%s %d:%s\n", 12340a92a9fcSCy Schubert "Error adding certificate", (int)error, 12350a92a9fcSCy Schubert ERR_error_string(error, NULL)); 12363bd4df0aSDag-Erling Smørgrav X509_free(cert1); 12373bd4df0aSDag-Erling Smørgrav return 0; 12383bd4df0aSDag-Erling Smørgrav } 12393bd4df0aSDag-Erling Smørgrav } 12403bd4df0aSDag-Erling Smørgrav X509_free(cert1); 12413bd4df0aSDag-Erling Smørgrav } 12423bd4df0aSDag-Erling Smørgrav } while ((pTargetCert = CertEnumCertificatesInStore( 12433bd4df0aSDag-Erling Smørgrav hSystemStore, pTargetCert)) != 0); 12443bd4df0aSDag-Erling Smørgrav 12453bd4df0aSDag-Erling Smørgrav /* Clean up memory and quit. */ 12463bd4df0aSDag-Erling Smørgrav if (pTargetCert) 12473bd4df0aSDag-Erling Smørgrav CertFreeCertificateContext(pTargetCert); 12483bd4df0aSDag-Erling Smørgrav if (hSystemStore) 12493bd4df0aSDag-Erling Smørgrav { 12503bd4df0aSDag-Erling Smørgrav if (!CertCloseStore( 12513bd4df0aSDag-Erling Smørgrav hSystemStore, 0)) 12523bd4df0aSDag-Erling Smørgrav return 0; 12533bd4df0aSDag-Erling Smørgrav } 12543bd4df0aSDag-Erling Smørgrav verbose(VERB_ALGO, "Completed adding Windows certificates to CA store successfully"); 12553bd4df0aSDag-Erling Smørgrav return 1; 12563bd4df0aSDag-Erling Smørgrav } 12573bd4df0aSDag-Erling Smørgrav #endif /* USE_WINSOCK */ 12583bd4df0aSDag-Erling Smørgrav 12593bd4df0aSDag-Erling Smørgrav void* connect_sslctx_create(char* key, char* pem, char* verifypem, int wincert) 1260b7579f77SDag-Erling Smørgrav { 12618ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL 1262b7579f77SDag-Erling Smørgrav SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method()); 1263b7579f77SDag-Erling Smørgrav if(!ctx) { 1264b7579f77SDag-Erling Smørgrav log_crypto_err("could not allocate SSL_CTX pointer"); 1265b7579f77SDag-Erling Smørgrav return NULL; 1266b7579f77SDag-Erling Smørgrav } 1267091e9e46SCy Schubert #if SSL_OP_NO_SSLv2 != 0 126805ab2901SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2) 126905ab2901SDag-Erling Smørgrav != SSL_OP_NO_SSLv2) { 1270b7579f77SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_NO_SSLv2"); 1271b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 1272b7579f77SDag-Erling Smørgrav return NULL; 1273b7579f77SDag-Erling Smørgrav } 1274091e9e46SCy Schubert #endif 127505ab2901SDag-Erling Smørgrav if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3) 127605ab2901SDag-Erling Smørgrav != SSL_OP_NO_SSLv3) { 1277ff825849SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_NO_SSLv3"); 1278ff825849SDag-Erling Smørgrav SSL_CTX_free(ctx); 1279ff825849SDag-Erling Smørgrav return NULL; 1280ff825849SDag-Erling Smørgrav } 12810eefd307SCy Schubert #if defined(SSL_OP_NO_RENEGOTIATION) 12820eefd307SCy Schubert /* disable client renegotiation */ 12830eefd307SCy Schubert if((SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION) & 12840eefd307SCy Schubert SSL_OP_NO_RENEGOTIATION) != SSL_OP_NO_RENEGOTIATION) { 12850eefd307SCy Schubert log_crypto_err("could not set SSL_OP_NO_RENEGOTIATION"); 128624e36522SCy Schubert SSL_CTX_free(ctx); 12870eefd307SCy Schubert return 0; 12880eefd307SCy Schubert } 12890eefd307SCy Schubert #endif 1290*8f76bb7dSCy Schubert #if defined(SSL_OP_IGNORE_UNEXPECTED_EOF) 1291*8f76bb7dSCy Schubert /* ignore errors when peers do not send the mandatory close_notify 1292*8f76bb7dSCy Schubert * alert on shutdown. 1293*8f76bb7dSCy Schubert * Relevant for openssl >= 3 */ 1294*8f76bb7dSCy Schubert if((SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF) & 1295*8f76bb7dSCy Schubert SSL_OP_IGNORE_UNEXPECTED_EOF) != SSL_OP_IGNORE_UNEXPECTED_EOF) { 1296*8f76bb7dSCy Schubert log_crypto_err("could not set SSL_OP_IGNORE_UNEXPECTED_EOF"); 1297*8f76bb7dSCy Schubert SSL_CTX_free(ctx); 1298*8f76bb7dSCy Schubert return 0; 1299*8f76bb7dSCy Schubert } 1300*8f76bb7dSCy Schubert #endif 1301b7579f77SDag-Erling Smørgrav if(key && key[0]) { 1302b75612f8SDag-Erling Smørgrav if(!SSL_CTX_use_certificate_chain_file(ctx, pem)) { 1303b7579f77SDag-Erling Smørgrav log_err("error in client certificate %s", pem); 1304b7579f77SDag-Erling Smørgrav log_crypto_err("error in certificate file"); 1305b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 1306b7579f77SDag-Erling Smørgrav return NULL; 1307b7579f77SDag-Erling Smørgrav } 1308b7579f77SDag-Erling Smørgrav if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) { 1309b7579f77SDag-Erling Smørgrav log_err("error in client private key %s", key); 1310b7579f77SDag-Erling Smørgrav log_crypto_err("error in key file"); 1311b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 1312b7579f77SDag-Erling Smørgrav return NULL; 1313b7579f77SDag-Erling Smørgrav } 1314b7579f77SDag-Erling Smørgrav if(!SSL_CTX_check_private_key(ctx)) { 1315b7579f77SDag-Erling Smørgrav log_err("error in client key %s", key); 1316b7579f77SDag-Erling Smørgrav log_crypto_err("error in SSL_CTX_check_private_key"); 1317b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 1318b7579f77SDag-Erling Smørgrav return NULL; 1319b7579f77SDag-Erling Smørgrav } 1320b7579f77SDag-Erling Smørgrav } 13213bd4df0aSDag-Erling Smørgrav if((verifypem && verifypem[0]) || wincert) { 1322b7579f77SDag-Erling Smørgrav if(verifypem && verifypem[0]) { 1323ff825849SDag-Erling Smørgrav if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) { 1324b7579f77SDag-Erling Smørgrav log_crypto_err("error in SSL_CTX verify"); 1325b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 1326b7579f77SDag-Erling Smørgrav return NULL; 1327b7579f77SDag-Erling Smørgrav } 13283bd4df0aSDag-Erling Smørgrav } 13293bd4df0aSDag-Erling Smørgrav #ifdef USE_WINSOCK 13303bd4df0aSDag-Erling Smørgrav if(wincert) { 13313bd4df0aSDag-Erling Smørgrav if(!add_WIN_cacerts_to_openssl_store(ctx)) { 13323bd4df0aSDag-Erling Smørgrav log_crypto_err("error in add_WIN_cacerts_to_openssl_store"); 13333bd4df0aSDag-Erling Smørgrav SSL_CTX_free(ctx); 13343bd4df0aSDag-Erling Smørgrav return NULL; 13353bd4df0aSDag-Erling Smørgrav } 13363bd4df0aSDag-Erling Smørgrav } 13373bd4df0aSDag-Erling Smørgrav #else 1338a39a5a69SCy Schubert if(wincert) { 1339a39a5a69SCy Schubert if(!SSL_CTX_set_default_verify_paths(ctx)) { 1340a39a5a69SCy Schubert log_crypto_err("error in default_verify_paths"); 1341a39a5a69SCy Schubert SSL_CTX_free(ctx); 1342a39a5a69SCy Schubert return NULL; 1343a39a5a69SCy Schubert } 1344a39a5a69SCy Schubert } 13453bd4df0aSDag-Erling Smørgrav #endif 1346b7579f77SDag-Erling Smørgrav SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); 1347b7579f77SDag-Erling Smørgrav } 1348b7579f77SDag-Erling Smørgrav return ctx; 13498ed2b524SDag-Erling Smørgrav #else 13503bd4df0aSDag-Erling Smørgrav (void)key; (void)pem; (void)verifypem; (void)wincert; 13518ed2b524SDag-Erling Smørgrav return NULL; 13528ed2b524SDag-Erling Smørgrav #endif 1353b7579f77SDag-Erling Smørgrav } 1354b7579f77SDag-Erling Smørgrav 1355b7579f77SDag-Erling Smørgrav void* incoming_ssl_fd(void* sslctx, int fd) 1356b7579f77SDag-Erling Smørgrav { 13578ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL 1358b7579f77SDag-Erling Smørgrav SSL* ssl = SSL_new((SSL_CTX*)sslctx); 1359b7579f77SDag-Erling Smørgrav if(!ssl) { 1360b7579f77SDag-Erling Smørgrav log_crypto_err("could not SSL_new"); 1361b7579f77SDag-Erling Smørgrav return NULL; 1362b7579f77SDag-Erling Smørgrav } 1363b7579f77SDag-Erling Smørgrav SSL_set_accept_state(ssl); 13640eefd307SCy Schubert (void)SSL_set_mode(ssl, (long)SSL_MODE_AUTO_RETRY); 1365b7579f77SDag-Erling Smørgrav if(!SSL_set_fd(ssl, fd)) { 1366b7579f77SDag-Erling Smørgrav log_crypto_err("could not SSL_set_fd"); 1367b7579f77SDag-Erling Smørgrav SSL_free(ssl); 1368b7579f77SDag-Erling Smørgrav return NULL; 1369b7579f77SDag-Erling Smørgrav } 1370b7579f77SDag-Erling Smørgrav return ssl; 13718ed2b524SDag-Erling Smørgrav #else 13728ed2b524SDag-Erling Smørgrav (void)sslctx; (void)fd; 13738ed2b524SDag-Erling Smørgrav return NULL; 13748ed2b524SDag-Erling Smørgrav #endif 1375b7579f77SDag-Erling Smørgrav } 1376b7579f77SDag-Erling Smørgrav 1377b7579f77SDag-Erling Smørgrav void* outgoing_ssl_fd(void* sslctx, int fd) 1378b7579f77SDag-Erling Smørgrav { 13798ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL 1380b7579f77SDag-Erling Smørgrav SSL* ssl = SSL_new((SSL_CTX*)sslctx); 1381b7579f77SDag-Erling Smørgrav if(!ssl) { 1382b7579f77SDag-Erling Smørgrav log_crypto_err("could not SSL_new"); 1383b7579f77SDag-Erling Smørgrav return NULL; 1384b7579f77SDag-Erling Smørgrav } 1385b7579f77SDag-Erling Smørgrav SSL_set_connect_state(ssl); 13860eefd307SCy Schubert (void)SSL_set_mode(ssl, (long)SSL_MODE_AUTO_RETRY); 1387b7579f77SDag-Erling Smørgrav if(!SSL_set_fd(ssl, fd)) { 1388b7579f77SDag-Erling Smørgrav log_crypto_err("could not SSL_set_fd"); 1389b7579f77SDag-Erling Smørgrav SSL_free(ssl); 1390b7579f77SDag-Erling Smørgrav return NULL; 1391b7579f77SDag-Erling Smørgrav } 1392b7579f77SDag-Erling Smørgrav return ssl; 13938ed2b524SDag-Erling Smørgrav #else 13948ed2b524SDag-Erling Smørgrav (void)sslctx; (void)fd; 13958ed2b524SDag-Erling Smørgrav return NULL; 13968ed2b524SDag-Erling Smørgrav #endif 1397b7579f77SDag-Erling Smørgrav } 13988ed2b524SDag-Erling Smørgrav 139925039b37SCy Schubert int check_auth_name_for_ssl(char* auth_name) 140025039b37SCy Schubert { 140125039b37SCy Schubert if(!auth_name) return 1; 140225039b37SCy Schubert #if defined(HAVE_SSL) && !defined(HAVE_SSL_SET1_HOST) && !defined(HAVE_X509_VERIFY_PARAM_SET1_HOST) 140325039b37SCy Schubert log_err("the query has an auth_name %s, but libssl has no call to " 140425039b37SCy Schubert "perform TLS authentication. Remove that name from config " 140525039b37SCy Schubert "or upgrade the ssl crypto library.", auth_name); 140625039b37SCy Schubert return 0; 140725039b37SCy Schubert #else 140825039b37SCy Schubert return 1; 140925039b37SCy Schubert #endif 141025039b37SCy Schubert } 141125039b37SCy Schubert 141225039b37SCy Schubert /** set the authname on an SSL structure, SSL* ssl */ 141325039b37SCy Schubert int set_auth_name_on_ssl(void* ssl, char* auth_name, int use_sni) 141425039b37SCy Schubert { 141525039b37SCy Schubert if(!auth_name) return 1; 141625039b37SCy Schubert #ifdef HAVE_SSL 141725039b37SCy Schubert if(use_sni) { 141825039b37SCy Schubert (void)SSL_set_tlsext_host_name(ssl, auth_name); 141925039b37SCy Schubert } 142025039b37SCy Schubert #else 142125039b37SCy Schubert (void)ssl; 142225039b37SCy Schubert (void)use_sni; 142325039b37SCy Schubert #endif 142425039b37SCy Schubert #ifdef HAVE_SSL_SET1_HOST 142525039b37SCy Schubert SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL); 142625039b37SCy Schubert /* setting the hostname makes openssl verify the 142725039b37SCy Schubert * host name in the x509 certificate in the 142825039b37SCy Schubert * SSL connection*/ 142925039b37SCy Schubert if(!SSL_set1_host(ssl, auth_name)) { 143025039b37SCy Schubert log_err("SSL_set1_host failed"); 143125039b37SCy Schubert return 0; 143225039b37SCy Schubert } 143325039b37SCy Schubert #elif defined(HAVE_X509_VERIFY_PARAM_SET1_HOST) 143425039b37SCy Schubert /* openssl 1.0.2 has this function that can be used for 143525039b37SCy Schubert * set1_host like verification */ 143625039b37SCy Schubert if(auth_name) { 143725039b37SCy Schubert X509_VERIFY_PARAM* param = SSL_get0_param(ssl); 143825039b37SCy Schubert # ifdef X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS 143925039b37SCy Schubert X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); 144025039b37SCy Schubert # endif 144125039b37SCy Schubert if(!X509_VERIFY_PARAM_set1_host(param, auth_name, strlen(auth_name))) { 144225039b37SCy Schubert log_err("X509_VERIFY_PARAM_set1_host failed"); 144325039b37SCy Schubert return 0; 144425039b37SCy Schubert } 144525039b37SCy Schubert SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL); 144625039b37SCy Schubert } 144725039b37SCy Schubert #else 144825039b37SCy Schubert verbose(VERB_ALGO, "the query has an auth_name, but libssl has no call to perform TLS authentication"); 144925039b37SCy Schubert #endif /* HAVE_SSL_SET1_HOST */ 145025039b37SCy Schubert return 1; 145125039b37SCy Schubert } 145225039b37SCy Schubert 1453b5663de9SDag-Erling Smørgrav #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L 14548ed2b524SDag-Erling Smørgrav /** global lock list for openssl locks */ 14553005e0a3SDag-Erling Smørgrav static lock_basic_type *ub_openssl_locks = NULL; 14568ed2b524SDag-Erling Smørgrav 14578ed2b524SDag-Erling Smørgrav /** callback that gets thread id for openssl */ 1458e86b9096SDag-Erling Smørgrav #ifdef HAVE_CRYPTO_THREADID_SET_CALLBACK 1459e86b9096SDag-Erling Smørgrav static void 1460e86b9096SDag-Erling Smørgrav ub_crypto_id_cb(CRYPTO_THREADID *id) 1461e86b9096SDag-Erling Smørgrav { 1462e86b9096SDag-Erling Smørgrav CRYPTO_THREADID_set_numeric(id, (unsigned long)log_thread_get()); 1463e86b9096SDag-Erling Smørgrav } 1464e86b9096SDag-Erling Smørgrav #else 14658ed2b524SDag-Erling Smørgrav static unsigned long 14668ed2b524SDag-Erling Smørgrav ub_crypto_id_cb(void) 14678ed2b524SDag-Erling Smørgrav { 146809a3aaf3SDag-Erling Smørgrav return (unsigned long)log_thread_get(); 14698ed2b524SDag-Erling Smørgrav } 1470e86b9096SDag-Erling Smørgrav #endif 14718ed2b524SDag-Erling Smørgrav 14728ed2b524SDag-Erling Smørgrav static void 14738ed2b524SDag-Erling Smørgrav ub_crypto_lock_cb(int mode, int type, const char *ATTR_UNUSED(file), 14748ed2b524SDag-Erling Smørgrav int ATTR_UNUSED(line)) 14758ed2b524SDag-Erling Smørgrav { 14768ed2b524SDag-Erling Smørgrav if((mode&CRYPTO_LOCK)) { 14778ed2b524SDag-Erling Smørgrav lock_basic_lock(&ub_openssl_locks[type]); 14788ed2b524SDag-Erling Smørgrav } else { 14798ed2b524SDag-Erling Smørgrav lock_basic_unlock(&ub_openssl_locks[type]); 14808ed2b524SDag-Erling Smørgrav } 14818ed2b524SDag-Erling Smørgrav } 14828ed2b524SDag-Erling Smørgrav #endif /* OPENSSL_THREADS */ 14838ed2b524SDag-Erling Smørgrav 14848ed2b524SDag-Erling Smørgrav int ub_openssl_lock_init(void) 14858ed2b524SDag-Erling Smørgrav { 1486b5663de9SDag-Erling Smørgrav #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L 14878ed2b524SDag-Erling Smørgrav int i; 14883005e0a3SDag-Erling Smørgrav ub_openssl_locks = (lock_basic_type*)reallocarray( 14893005e0a3SDag-Erling Smørgrav NULL, (size_t)CRYPTO_num_locks(), sizeof(lock_basic_type)); 14908ed2b524SDag-Erling Smørgrav if(!ub_openssl_locks) 14918ed2b524SDag-Erling Smørgrav return 0; 14928ed2b524SDag-Erling Smørgrav for(i=0; i<CRYPTO_num_locks(); i++) { 14938ed2b524SDag-Erling Smørgrav lock_basic_init(&ub_openssl_locks[i]); 14948ed2b524SDag-Erling Smørgrav } 1495e86b9096SDag-Erling Smørgrav # ifdef HAVE_CRYPTO_THREADID_SET_CALLBACK 1496e86b9096SDag-Erling Smørgrav CRYPTO_THREADID_set_callback(&ub_crypto_id_cb); 1497e86b9096SDag-Erling Smørgrav # else 14988ed2b524SDag-Erling Smørgrav CRYPTO_set_id_callback(&ub_crypto_id_cb); 1499e86b9096SDag-Erling Smørgrav # endif 15008ed2b524SDag-Erling Smørgrav CRYPTO_set_locking_callback(&ub_crypto_lock_cb); 15018ed2b524SDag-Erling Smørgrav #endif /* OPENSSL_THREADS */ 15028ed2b524SDag-Erling Smørgrav return 1; 15038ed2b524SDag-Erling Smørgrav } 15048ed2b524SDag-Erling Smørgrav 15058ed2b524SDag-Erling Smørgrav void ub_openssl_lock_delete(void) 15068ed2b524SDag-Erling Smørgrav { 1507b5663de9SDag-Erling Smørgrav #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L 15088ed2b524SDag-Erling Smørgrav int i; 15098ed2b524SDag-Erling Smørgrav if(!ub_openssl_locks) 15108ed2b524SDag-Erling Smørgrav return; 1511e86b9096SDag-Erling Smørgrav # ifdef HAVE_CRYPTO_THREADID_SET_CALLBACK 1512e86b9096SDag-Erling Smørgrav CRYPTO_THREADID_set_callback(NULL); 1513e86b9096SDag-Erling Smørgrav # else 15148ed2b524SDag-Erling Smørgrav CRYPTO_set_id_callback(NULL); 1515e86b9096SDag-Erling Smørgrav # endif 15168ed2b524SDag-Erling Smørgrav CRYPTO_set_locking_callback(NULL); 15178ed2b524SDag-Erling Smørgrav for(i=0; i<CRYPTO_num_locks(); i++) { 15188ed2b524SDag-Erling Smørgrav lock_basic_destroy(&ub_openssl_locks[i]); 15198ed2b524SDag-Erling Smørgrav } 15208ed2b524SDag-Erling Smørgrav free(ub_openssl_locks); 15218ed2b524SDag-Erling Smørgrav #endif /* OPENSSL_THREADS */ 15228ed2b524SDag-Erling Smørgrav } 15238ed2b524SDag-Erling Smørgrav 1524e86b9096SDag-Erling Smørgrav int listen_sslctx_setup_ticket_keys(void* sslctx, struct config_strlist* tls_session_ticket_keys) { 1525e86b9096SDag-Erling Smørgrav #ifdef HAVE_SSL 1526e86b9096SDag-Erling Smørgrav size_t s = 1; 1527e86b9096SDag-Erling Smørgrav struct config_strlist* p; 1528e86b9096SDag-Erling Smørgrav struct tls_session_ticket_key *keys; 1529e86b9096SDag-Erling Smørgrav for(p = tls_session_ticket_keys; p; p = p->next) { 1530e86b9096SDag-Erling Smørgrav s++; 1531e86b9096SDag-Erling Smørgrav } 1532e86b9096SDag-Erling Smørgrav keys = calloc(s, sizeof(struct tls_session_ticket_key)); 1533091e9e46SCy Schubert if(!keys) 1534091e9e46SCy Schubert return 0; 1535e86b9096SDag-Erling Smørgrav memset(keys, 0, s*sizeof(*keys)); 1536e86b9096SDag-Erling Smørgrav ticket_keys = keys; 1537e86b9096SDag-Erling Smørgrav 1538e86b9096SDag-Erling Smørgrav for(p = tls_session_ticket_keys; p; p = p->next) { 1539e86b9096SDag-Erling Smørgrav size_t n; 1540091e9e46SCy Schubert unsigned char *data; 1541091e9e46SCy Schubert FILE *f; 1542091e9e46SCy Schubert 1543091e9e46SCy Schubert data = (unsigned char *)malloc(80); 1544091e9e46SCy Schubert if(!data) 1545091e9e46SCy Schubert return 0; 1546091e9e46SCy Schubert 154725039b37SCy Schubert f = fopen(p->str, "rb"); 1548e86b9096SDag-Erling Smørgrav if(!f) { 1549e86b9096SDag-Erling Smørgrav log_err("could not read tls-session-ticket-key %s: %s", p->str, strerror(errno)); 1550e86b9096SDag-Erling Smørgrav free(data); 1551e86b9096SDag-Erling Smørgrav return 0; 1552e86b9096SDag-Erling Smørgrav } 1553e86b9096SDag-Erling Smørgrav n = fread(data, 1, 80, f); 1554e86b9096SDag-Erling Smørgrav fclose(f); 1555e86b9096SDag-Erling Smørgrav 1556e86b9096SDag-Erling Smørgrav if(n != 80) { 1557e86b9096SDag-Erling Smørgrav log_err("tls-session-ticket-key %s is %d bytes, must be 80 bytes", p->str, (int)n); 1558e86b9096SDag-Erling Smørgrav free(data); 1559e86b9096SDag-Erling Smørgrav return 0; 1560e86b9096SDag-Erling Smørgrav } 1561e86b9096SDag-Erling Smørgrav verbose(VERB_OPS, "read tls-session-ticket-key: %s", p->str); 1562e86b9096SDag-Erling Smørgrav 1563e86b9096SDag-Erling Smørgrav keys->key_name = data; 1564e86b9096SDag-Erling Smørgrav keys->aes_key = data + 16; 1565e86b9096SDag-Erling Smørgrav keys->hmac_key = data + 48; 1566e86b9096SDag-Erling Smørgrav keys++; 1567e86b9096SDag-Erling Smørgrav } 1568e86b9096SDag-Erling Smørgrav /* terminate array with NULL key name entry */ 1569e86b9096SDag-Erling Smørgrav keys->key_name = NULL; 157025039b37SCy Schubert # ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB 157125039b37SCy Schubert if(SSL_CTX_set_tlsext_ticket_key_evp_cb(sslctx, tls_session_ticket_key_cb) == 0) { 157225039b37SCy Schubert log_err("no support for TLS session ticket"); 157325039b37SCy Schubert return 0; 157425039b37SCy Schubert } 157525039b37SCy Schubert # else 1576e86b9096SDag-Erling Smørgrav if(SSL_CTX_set_tlsext_ticket_key_cb(sslctx, tls_session_ticket_key_cb) == 0) { 1577e86b9096SDag-Erling Smørgrav log_err("no support for TLS session ticket"); 1578e86b9096SDag-Erling Smørgrav return 0; 1579e86b9096SDag-Erling Smørgrav } 158025039b37SCy Schubert # endif 1581e86b9096SDag-Erling Smørgrav return 1; 1582e86b9096SDag-Erling Smørgrav #else 1583e86b9096SDag-Erling Smørgrav (void)sslctx; 1584e86b9096SDag-Erling Smørgrav (void)tls_session_ticket_keys; 1585e86b9096SDag-Erling Smørgrav return 0; 1586e86b9096SDag-Erling Smørgrav #endif 1587e86b9096SDag-Erling Smørgrav 1588e86b9096SDag-Erling Smørgrav } 1589e86b9096SDag-Erling Smørgrav 159025039b37SCy Schubert #ifdef HAVE_SSL 159125039b37SCy Schubert int tls_session_ticket_key_cb(SSL *ATTR_UNUSED(sslctx), unsigned char* key_name, 159225039b37SCy Schubert unsigned char* iv, EVP_CIPHER_CTX *evp_sctx, 159325039b37SCy Schubert #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB 159425039b37SCy Schubert EVP_MAC_CTX *hmac_ctx, 159525039b37SCy Schubert #else 159625039b37SCy Schubert HMAC_CTX* hmac_ctx, 159725039b37SCy Schubert #endif 159825039b37SCy Schubert int enc) 1599e86b9096SDag-Erling Smørgrav { 1600e86b9096SDag-Erling Smørgrav #ifdef HAVE_SSL 160125039b37SCy Schubert # ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB 160225039b37SCy Schubert OSSL_PARAM params[3]; 160325039b37SCy Schubert # else 1604e86b9096SDag-Erling Smørgrav const EVP_MD *digest; 160525039b37SCy Schubert # endif 1606e86b9096SDag-Erling Smørgrav const EVP_CIPHER *cipher; 1607e86b9096SDag-Erling Smørgrav int evp_cipher_length; 160825039b37SCy Schubert # ifndef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB 1609e86b9096SDag-Erling Smørgrav digest = EVP_sha256(); 161025039b37SCy Schubert # endif 1611e86b9096SDag-Erling Smørgrav cipher = EVP_aes_256_cbc(); 1612e86b9096SDag-Erling Smørgrav evp_cipher_length = EVP_CIPHER_iv_length(cipher); 1613e86b9096SDag-Erling Smørgrav if( enc == 1 ) { 1614e86b9096SDag-Erling Smørgrav /* encrypt */ 1615e86b9096SDag-Erling Smørgrav verbose(VERB_CLIENT, "start session encrypt"); 1616e86b9096SDag-Erling Smørgrav memcpy(key_name, ticket_keys->key_name, 16); 1617e86b9096SDag-Erling Smørgrav if (RAND_bytes(iv, evp_cipher_length) != 1) { 1618e86b9096SDag-Erling Smørgrav verbose(VERB_CLIENT, "RAND_bytes failed"); 1619e86b9096SDag-Erling Smørgrav return -1; 1620e86b9096SDag-Erling Smørgrav } 1621e86b9096SDag-Erling Smørgrav if (EVP_EncryptInit_ex(evp_sctx, cipher, NULL, ticket_keys->aes_key, iv) != 1) { 1622e86b9096SDag-Erling Smørgrav verbose(VERB_CLIENT, "EVP_EncryptInit_ex failed"); 1623e86b9096SDag-Erling Smørgrav return -1; 1624e86b9096SDag-Erling Smørgrav } 162525039b37SCy Schubert #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB 162625039b37SCy Schubert params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, 162725039b37SCy Schubert ticket_keys->hmac_key, 32); 162825039b37SCy Schubert params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, 162925039b37SCy Schubert "sha256", 0); 163025039b37SCy Schubert params[2] = OSSL_PARAM_construct_end(); 1631c0caa2e2SCy Schubert #ifdef HAVE_EVP_MAC_CTX_SET_PARAMS 1632c0caa2e2SCy Schubert EVP_MAC_CTX_set_params(hmac_ctx, params); 1633c0caa2e2SCy Schubert #else 163425039b37SCy Schubert EVP_MAC_set_ctx_params(hmac_ctx, params); 1635c0caa2e2SCy Schubert #endif 163625039b37SCy Schubert #elif !defined(HMAC_INIT_EX_RETURNS_VOID) 1637e86b9096SDag-Erling Smørgrav if (HMAC_Init_ex(hmac_ctx, ticket_keys->hmac_key, 32, digest, NULL) != 1) { 1638e86b9096SDag-Erling Smørgrav verbose(VERB_CLIENT, "HMAC_Init_ex failed"); 1639e86b9096SDag-Erling Smørgrav return -1; 1640e86b9096SDag-Erling Smørgrav } 16410eefd307SCy Schubert #else 16420eefd307SCy Schubert HMAC_Init_ex(hmac_ctx, ticket_keys->hmac_key, 32, digest, NULL); 16430eefd307SCy Schubert #endif 1644e86b9096SDag-Erling Smørgrav return 1; 1645e86b9096SDag-Erling Smørgrav } else if (enc == 0) { 1646e86b9096SDag-Erling Smørgrav /* decrypt */ 1647e86b9096SDag-Erling Smørgrav struct tls_session_ticket_key *key; 1648e86b9096SDag-Erling Smørgrav verbose(VERB_CLIENT, "start session decrypt"); 1649e86b9096SDag-Erling Smørgrav for(key = ticket_keys; key->key_name != NULL; key++) { 1650e86b9096SDag-Erling Smørgrav if (!memcmp(key_name, key->key_name, 16)) { 1651e86b9096SDag-Erling Smørgrav verbose(VERB_CLIENT, "Found session_key"); 1652e86b9096SDag-Erling Smørgrav break; 1653e86b9096SDag-Erling Smørgrav } 1654e86b9096SDag-Erling Smørgrav } 1655e86b9096SDag-Erling Smørgrav if(key->key_name == NULL) { 1656e86b9096SDag-Erling Smørgrav verbose(VERB_CLIENT, "Not found session_key"); 1657e86b9096SDag-Erling Smørgrav return 0; 1658e86b9096SDag-Erling Smørgrav } 1659e86b9096SDag-Erling Smørgrav 166025039b37SCy Schubert #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB 166125039b37SCy Schubert params[0] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, 166225039b37SCy Schubert key->hmac_key, 32); 166325039b37SCy Schubert params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, 166425039b37SCy Schubert "sha256", 0); 166525039b37SCy Schubert params[2] = OSSL_PARAM_construct_end(); 1666c0caa2e2SCy Schubert #ifdef HAVE_EVP_MAC_CTX_SET_PARAMS 1667c0caa2e2SCy Schubert EVP_MAC_CTX_set_params(hmac_ctx, params); 1668c0caa2e2SCy Schubert #else 166925039b37SCy Schubert EVP_MAC_set_ctx_params(hmac_ctx, params); 1670c0caa2e2SCy Schubert #endif 167125039b37SCy Schubert #elif !defined(HMAC_INIT_EX_RETURNS_VOID) 1672e86b9096SDag-Erling Smørgrav if (HMAC_Init_ex(hmac_ctx, key->hmac_key, 32, digest, NULL) != 1) { 1673e86b9096SDag-Erling Smørgrav verbose(VERB_CLIENT, "HMAC_Init_ex failed"); 1674e86b9096SDag-Erling Smørgrav return -1; 1675e86b9096SDag-Erling Smørgrav } 16760eefd307SCy Schubert #else 16770eefd307SCy Schubert HMAC_Init_ex(hmac_ctx, key->hmac_key, 32, digest, NULL); 16780eefd307SCy Schubert #endif 1679e86b9096SDag-Erling Smørgrav if (EVP_DecryptInit_ex(evp_sctx, cipher, NULL, key->aes_key, iv) != 1) { 1680e86b9096SDag-Erling Smørgrav log_err("EVP_DecryptInit_ex failed"); 1681e86b9096SDag-Erling Smørgrav return -1; 1682e86b9096SDag-Erling Smørgrav } 1683e86b9096SDag-Erling Smørgrav 1684e86b9096SDag-Erling Smørgrav return (key == ticket_keys) ? 1 : 2; 1685e86b9096SDag-Erling Smørgrav } 1686e86b9096SDag-Erling Smørgrav return -1; 1687e86b9096SDag-Erling Smørgrav #else 1688e86b9096SDag-Erling Smørgrav (void)key_name; 1689e86b9096SDag-Erling Smørgrav (void)iv; 1690e86b9096SDag-Erling Smørgrav (void)evp_sctx; 1691e86b9096SDag-Erling Smørgrav (void)hmac_ctx; 1692e86b9096SDag-Erling Smørgrav (void)enc; 1693e86b9096SDag-Erling Smørgrav return 0; 1694e86b9096SDag-Erling Smørgrav #endif 1695e86b9096SDag-Erling Smørgrav } 169625039b37SCy Schubert #endif /* HAVE_SSL */ 1697e86b9096SDag-Erling Smørgrav 1698e86b9096SDag-Erling Smørgrav void 1699e86b9096SDag-Erling Smørgrav listen_sslctx_delete_ticket_keys(void) 1700e86b9096SDag-Erling Smørgrav { 1701e86b9096SDag-Erling Smørgrav struct tls_session_ticket_key *key; 1702e86b9096SDag-Erling Smørgrav if(!ticket_keys) return; 1703e86b9096SDag-Erling Smørgrav for(key = ticket_keys; key->key_name != NULL; key++) { 1704e86b9096SDag-Erling Smørgrav /* wipe key data from memory*/ 1705e86b9096SDag-Erling Smørgrav #ifdef HAVE_EXPLICIT_BZERO 1706e86b9096SDag-Erling Smørgrav explicit_bzero(key->key_name, 80); 1707e86b9096SDag-Erling Smørgrav #else 1708e86b9096SDag-Erling Smørgrav memset(key->key_name, 0xdd, 80); 1709e86b9096SDag-Erling Smørgrav #endif 1710e86b9096SDag-Erling Smørgrav free(key->key_name); 1711e86b9096SDag-Erling Smørgrav } 1712e86b9096SDag-Erling Smørgrav free(ticket_keys); 1713e86b9096SDag-Erling Smørgrav ticket_keys = NULL; 1714e86b9096SDag-Erling Smørgrav } 1715c0caa2e2SCy Schubert 1716c0caa2e2SCy Schubert # ifndef USE_WINSOCK 1717c0caa2e2SCy Schubert char* 1718c0caa2e2SCy Schubert sock_strerror(int errn) 1719c0caa2e2SCy Schubert { 1720c0caa2e2SCy Schubert return strerror(errn); 1721c0caa2e2SCy Schubert } 1722c0caa2e2SCy Schubert 1723c0caa2e2SCy Schubert void 1724c0caa2e2SCy Schubert sock_close(int socket) 1725c0caa2e2SCy Schubert { 1726c0caa2e2SCy Schubert close(socket); 1727c0caa2e2SCy Schubert } 1728c0caa2e2SCy Schubert 1729c0caa2e2SCy Schubert # else 1730c0caa2e2SCy Schubert char* 1731c0caa2e2SCy Schubert sock_strerror(int ATTR_UNUSED(errn)) 1732c0caa2e2SCy Schubert { 1733c0caa2e2SCy Schubert return wsa_strerror(WSAGetLastError()); 1734c0caa2e2SCy Schubert } 1735c0caa2e2SCy Schubert 1736c0caa2e2SCy Schubert void 1737c0caa2e2SCy Schubert sock_close(int socket) 1738c0caa2e2SCy Schubert { 1739c0caa2e2SCy Schubert closesocket(socket); 1740c0caa2e2SCy Schubert } 1741c0caa2e2SCy Schubert # endif /* USE_WINSOCK */ 1742