1ae8c6e27Sflorian /* 2ae8c6e27Sflorian * util/net_help.c - implementation of the network helper code 3ae8c6e27Sflorian * 4ae8c6e27Sflorian * Copyright (c) 2007, NLnet Labs. All rights reserved. 5ae8c6e27Sflorian * 6ae8c6e27Sflorian * This software is open source. 7ae8c6e27Sflorian * 8ae8c6e27Sflorian * Redistribution and use in source and binary forms, with or without 9ae8c6e27Sflorian * modification, are permitted provided that the following conditions 10ae8c6e27Sflorian * are met: 11ae8c6e27Sflorian * 12ae8c6e27Sflorian * Redistributions of source code must retain the above copyright notice, 13ae8c6e27Sflorian * this list of conditions and the following disclaimer. 14ae8c6e27Sflorian * 15ae8c6e27Sflorian * Redistributions in binary form must reproduce the above copyright notice, 16ae8c6e27Sflorian * this list of conditions and the following disclaimer in the documentation 17ae8c6e27Sflorian * and/or other materials provided with the distribution. 18ae8c6e27Sflorian * 19ae8c6e27Sflorian * Neither the name of the NLNET LABS nor the names of its contributors may 20ae8c6e27Sflorian * be used to endorse or promote products derived from this software without 21ae8c6e27Sflorian * specific prior written permission. 22ae8c6e27Sflorian * 23ae8c6e27Sflorian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24ae8c6e27Sflorian * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25ae8c6e27Sflorian * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26ae8c6e27Sflorian * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27ae8c6e27Sflorian * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28ae8c6e27Sflorian * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29ae8c6e27Sflorian * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30ae8c6e27Sflorian * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31ae8c6e27Sflorian * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32ae8c6e27Sflorian * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33ae8c6e27Sflorian * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34ae8c6e27Sflorian */ 35ae8c6e27Sflorian /** 36ae8c6e27Sflorian * \file 37ae8c6e27Sflorian * Implementation of net_help.h. 38ae8c6e27Sflorian */ 39ae8c6e27Sflorian 40ae8c6e27Sflorian #include "config.h" 41ebe14541Sflorian #ifdef HAVE_SYS_TYPES_H 42ebe14541Sflorian # include <sys/types.h> 43ebe14541Sflorian #endif 44ebe14541Sflorian #ifdef HAVE_NET_IF_H 45ebe14541Sflorian #include <net/if.h> 46ebe14541Sflorian #endif 47a1a7ba80Sflorian #ifdef HAVE_NETIOAPI_H 48a1a7ba80Sflorian #include <netioapi.h> 49a1a7ba80Sflorian #endif 50*7037e34cSflorian #include <ctype.h> 51ae8c6e27Sflorian #include "util/net_help.h" 52ae8c6e27Sflorian #include "util/log.h" 53ae8c6e27Sflorian #include "util/data/dname.h" 54ae8c6e27Sflorian #include "util/module.h" 55ae8c6e27Sflorian #include "util/regional.h" 56e97c6e54Ssthen #include "util/config_file.h" 57ae8c6e27Sflorian #include "sldns/parseutil.h" 58ae8c6e27Sflorian #include "sldns/wire2str.h" 59a1a7ba80Sflorian #include "sldns/str2wire.h" 60ae8c6e27Sflorian #include <fcntl.h> 61ae8c6e27Sflorian #ifdef HAVE_OPENSSL_SSL_H 62ae8c6e27Sflorian #include <openssl/ssl.h> 63e97c6e54Ssthen #include <openssl/evp.h> 64e97c6e54Ssthen #include <openssl/rand.h> 65ae8c6e27Sflorian #endif 66ae8c6e27Sflorian #ifdef HAVE_OPENSSL_ERR_H 67ae8c6e27Sflorian #include <openssl/err.h> 68ae8c6e27Sflorian #endif 69e47fef9eSflorian #ifdef HAVE_OPENSSL_CORE_NAMES_H 70e47fef9eSflorian #include <openssl/core_names.h> 71e47fef9eSflorian #endif 72ae8c6e27Sflorian #ifdef USE_WINSOCK 73ae8c6e27Sflorian #include <wincrypt.h> 74ae8c6e27Sflorian #endif 75f4f0f0ceSflorian #ifdef HAVE_NGHTTP2_NGHTTP2_H 76f4f0f0ceSflorian #include <nghttp2/nghttp2.h> 77f4f0f0ceSflorian #endif 78ae8c6e27Sflorian 79ae8c6e27Sflorian /** max length of an IP address (the address portion) that we allow */ 80ae8c6e27Sflorian #define MAX_ADDR_STRLEN 128 /* characters */ 81096314feSflorian /** max length of a hostname (with port and tls name) that we allow */ 82096314feSflorian #define MAX_HOST_STRLEN (LDNS_MAX_DOMAINLEN * 3) /* characters */ 83ae8c6e27Sflorian /** default value for EDNS ADVERTISED size */ 84ae8c6e27Sflorian uint16_t EDNS_ADVERTISED_SIZE = 4096; 85ae8c6e27Sflorian 86ae8c6e27Sflorian /** minimal responses when positive answer: default is no */ 87ae8c6e27Sflorian int MINIMAL_RESPONSES = 0; 88ae8c6e27Sflorian 89e47fef9eSflorian /** rrset order roundrobin: default is yes */ 90e47fef9eSflorian int RRSET_ROUNDROBIN = 1; 91ae8c6e27Sflorian 92e97c6e54Ssthen /** log tag queries with name instead of 'info' for filtering */ 93e97c6e54Ssthen int LOG_TAG_QUERYREPLY = 0; 94e97c6e54Ssthen 95e97c6e54Ssthen static struct tls_session_ticket_key { 96e97c6e54Ssthen unsigned char *key_name; 97e97c6e54Ssthen unsigned char *aes_key; 98e97c6e54Ssthen unsigned char *hmac_key; 99e97c6e54Ssthen } *ticket_keys; 100e97c6e54Ssthen 101f4f0f0ceSflorian #ifdef HAVE_SSL 102e47fef9eSflorian /** 103e47fef9eSflorian * callback TLS session ticket encrypt and decrypt 104e47fef9eSflorian * For use with SSL_CTX_set_tlsext_ticket_key_cb or 105e47fef9eSflorian * SSL_CTX_set_tlsext_ticket_key_evp_cb 106e47fef9eSflorian * @param s: the SSL_CTX to use (from connect_sslctx_create()) 107e47fef9eSflorian * @param key_name: secret name, 16 bytes 108e47fef9eSflorian * @param iv: up to EVP_MAX_IV_LENGTH. 109e47fef9eSflorian * @param evp_ctx: the evp cipher context, function sets this. 110e47fef9eSflorian * @param hmac_ctx: the hmac context, function sets this. 111e47fef9eSflorian * with ..key_cb it is of type HMAC_CTX* 112e47fef9eSflorian * with ..key_evp_cb it is of type EVP_MAC_CTX* 113e47fef9eSflorian * @param enc: 1 is encrypt, 0 is decrypt 114e47fef9eSflorian * @return 0 on no ticket, 1 for okay, and 2 for okay but renew the ticket 115e47fef9eSflorian * (the ticket is decrypt only). and <0 for failures. 116e47fef9eSflorian */ 117e47fef9eSflorian int tls_session_ticket_key_cb(SSL *s, unsigned char* key_name, 118e47fef9eSflorian unsigned char* iv, EVP_CIPHER_CTX *evp_ctx, 119e47fef9eSflorian #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB 120e47fef9eSflorian EVP_MAC_CTX *hmac_ctx, 121e47fef9eSflorian #else 122e47fef9eSflorian HMAC_CTX* hmac_ctx, 123e47fef9eSflorian #endif 124e47fef9eSflorian int enc); 125e47fef9eSflorian #endif /* HAVE_SSL */ 126e47fef9eSflorian 127ae8c6e27Sflorian /* returns true is string addr is an ip6 specced address */ 128ae8c6e27Sflorian int 129ae8c6e27Sflorian str_is_ip6(const char* str) 130ae8c6e27Sflorian { 131ae8c6e27Sflorian if(strchr(str, ':')) 132ae8c6e27Sflorian return 1; 133ae8c6e27Sflorian else return 0; 134ae8c6e27Sflorian } 135ae8c6e27Sflorian 136ae8c6e27Sflorian int 137ae8c6e27Sflorian fd_set_nonblock(int s) 138ae8c6e27Sflorian { 139ae8c6e27Sflorian #ifdef HAVE_FCNTL 140ae8c6e27Sflorian int flag; 141ae8c6e27Sflorian if((flag = fcntl(s, F_GETFL)) == -1) { 142ae8c6e27Sflorian log_err("can't fcntl F_GETFL: %s", strerror(errno)); 143ae8c6e27Sflorian flag = 0; 144ae8c6e27Sflorian } 145ae8c6e27Sflorian flag |= O_NONBLOCK; 146ae8c6e27Sflorian if(fcntl(s, F_SETFL, flag) == -1) { 147ae8c6e27Sflorian log_err("can't fcntl F_SETFL: %s", strerror(errno)); 148ae8c6e27Sflorian return 0; 149ae8c6e27Sflorian } 150ae8c6e27Sflorian #elif defined(HAVE_IOCTLSOCKET) 151ae8c6e27Sflorian unsigned long on = 1; 152ae8c6e27Sflorian if(ioctlsocket(s, FIONBIO, &on) != 0) { 153ae8c6e27Sflorian log_err("can't ioctlsocket FIONBIO on: %s", 154ae8c6e27Sflorian wsa_strerror(WSAGetLastError())); 155ae8c6e27Sflorian } 156ae8c6e27Sflorian #endif 157ae8c6e27Sflorian return 1; 158ae8c6e27Sflorian } 159ae8c6e27Sflorian 160ae8c6e27Sflorian int 161ae8c6e27Sflorian fd_set_block(int s) 162ae8c6e27Sflorian { 163ae8c6e27Sflorian #ifdef HAVE_FCNTL 164ae8c6e27Sflorian int flag; 165ae8c6e27Sflorian if((flag = fcntl(s, F_GETFL)) == -1) { 166ae8c6e27Sflorian log_err("cannot fcntl F_GETFL: %s", strerror(errno)); 167ae8c6e27Sflorian flag = 0; 168ae8c6e27Sflorian } 169ae8c6e27Sflorian flag &= ~O_NONBLOCK; 170ae8c6e27Sflorian if(fcntl(s, F_SETFL, flag) == -1) { 171ae8c6e27Sflorian log_err("cannot fcntl F_SETFL: %s", strerror(errno)); 172ae8c6e27Sflorian return 0; 173ae8c6e27Sflorian } 174ae8c6e27Sflorian #elif defined(HAVE_IOCTLSOCKET) 175ae8c6e27Sflorian unsigned long off = 0; 176ae8c6e27Sflorian if(ioctlsocket(s, FIONBIO, &off) != 0) { 177ae8c6e27Sflorian if(WSAGetLastError() != WSAEINVAL || verbosity >= 4) 178ae8c6e27Sflorian log_err("can't ioctlsocket FIONBIO off: %s", 179ae8c6e27Sflorian wsa_strerror(WSAGetLastError())); 180ae8c6e27Sflorian } 181ae8c6e27Sflorian #endif 182ae8c6e27Sflorian return 1; 183ae8c6e27Sflorian } 184ae8c6e27Sflorian 185ae8c6e27Sflorian int 186ae8c6e27Sflorian is_pow2(size_t num) 187ae8c6e27Sflorian { 188ae8c6e27Sflorian if(num == 0) return 1; 189ae8c6e27Sflorian return (num & (num-1)) == 0; 190ae8c6e27Sflorian } 191ae8c6e27Sflorian 192ae8c6e27Sflorian void* 193ae8c6e27Sflorian memdup(void* data, size_t len) 194ae8c6e27Sflorian { 195ae8c6e27Sflorian void* d; 196ae8c6e27Sflorian if(!data) return NULL; 197ae8c6e27Sflorian if(len == 0) return NULL; 198ae8c6e27Sflorian d = malloc(len); 199ae8c6e27Sflorian if(!d) return NULL; 200ae8c6e27Sflorian memcpy(d, data, len); 201ae8c6e27Sflorian return d; 202ae8c6e27Sflorian } 203ae8c6e27Sflorian 204ae8c6e27Sflorian void 205ae8c6e27Sflorian log_addr(enum verbosity_value v, const char* str, 206ae8c6e27Sflorian struct sockaddr_storage* addr, socklen_t addrlen) 207ae8c6e27Sflorian { 208ae8c6e27Sflorian uint16_t port; 209ae8c6e27Sflorian const char* family = "unknown"; 210ae8c6e27Sflorian char dest[100]; 211ae8c6e27Sflorian int af = (int)((struct sockaddr_in*)addr)->sin_family; 212ae8c6e27Sflorian void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 213ae8c6e27Sflorian if(verbosity < v) 214ae8c6e27Sflorian return; 215ae8c6e27Sflorian switch(af) { 216ae8c6e27Sflorian case AF_INET: family="ip4"; break; 217ae8c6e27Sflorian case AF_INET6: family="ip6"; 218ae8c6e27Sflorian sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; 219ae8c6e27Sflorian break; 220ae8c6e27Sflorian case AF_LOCAL: 221ae8c6e27Sflorian dest[0]=0; 222ae8c6e27Sflorian (void)inet_ntop(af, sinaddr, dest, 223ae8c6e27Sflorian (socklen_t)sizeof(dest)); 224ae8c6e27Sflorian verbose(v, "%s local %s", str, dest); 225ae8c6e27Sflorian return; /* do not continue and try to get port */ 226ae8c6e27Sflorian default: break; 227ae8c6e27Sflorian } 228ae8c6e27Sflorian if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { 229ae8c6e27Sflorian (void)strlcpy(dest, "(inet_ntop error)", sizeof(dest)); 230ae8c6e27Sflorian } 231ae8c6e27Sflorian dest[sizeof(dest)-1] = 0; 232ae8c6e27Sflorian port = ntohs(((struct sockaddr_in*)addr)->sin_port); 233ae8c6e27Sflorian if(verbosity >= 4) 234ae8c6e27Sflorian verbose(v, "%s %s %s port %d (len %d)", str, family, dest, 235ae8c6e27Sflorian (int)port, (int)addrlen); 236ae8c6e27Sflorian else verbose(v, "%s %s port %d", str, dest, (int)port); 237ae8c6e27Sflorian } 238ae8c6e27Sflorian 239ae8c6e27Sflorian int 240ae8c6e27Sflorian extstrtoaddr(const char* str, struct sockaddr_storage* addr, 2415c45b740Sflorian socklen_t* addrlen, int port) 242ae8c6e27Sflorian { 243ae8c6e27Sflorian char* s; 244ae8c6e27Sflorian if((s=strchr(str, '@'))) { 245ae8c6e27Sflorian char buf[MAX_ADDR_STRLEN]; 246ae8c6e27Sflorian if(s-str >= MAX_ADDR_STRLEN) { 247ae8c6e27Sflorian return 0; 248ae8c6e27Sflorian } 249ae8c6e27Sflorian (void)strlcpy(buf, str, sizeof(buf)); 250ae8c6e27Sflorian buf[s-str] = 0; 251ae8c6e27Sflorian port = atoi(s+1); 252ae8c6e27Sflorian if(port == 0 && strcmp(s+1,"0")!=0) { 253ae8c6e27Sflorian return 0; 254ae8c6e27Sflorian } 255ae8c6e27Sflorian return ipstrtoaddr(buf, port, addr, addrlen); 256ae8c6e27Sflorian } 257ae8c6e27Sflorian return ipstrtoaddr(str, port, addr, addrlen); 258ae8c6e27Sflorian } 259ae8c6e27Sflorian 260ae8c6e27Sflorian int 261ae8c6e27Sflorian ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr, 262ae8c6e27Sflorian socklen_t* addrlen) 263ae8c6e27Sflorian { 264ae8c6e27Sflorian uint16_t p; 265ae8c6e27Sflorian if(!ip) return 0; 266ae8c6e27Sflorian p = (uint16_t) port; 267ae8c6e27Sflorian if(str_is_ip6(ip)) { 268ae8c6e27Sflorian char buf[MAX_ADDR_STRLEN]; 269ae8c6e27Sflorian char* s; 270ae8c6e27Sflorian struct sockaddr_in6* sa = (struct sockaddr_in6*)addr; 271ae8c6e27Sflorian *addrlen = (socklen_t)sizeof(struct sockaddr_in6); 272ae8c6e27Sflorian memset(sa, 0, *addrlen); 273ae8c6e27Sflorian sa->sin6_family = AF_INET6; 274ae8c6e27Sflorian sa->sin6_port = (in_port_t)htons(p); 275ae8c6e27Sflorian if((s=strchr(ip, '%'))) { /* ip6%interface, rfc 4007 */ 276ae8c6e27Sflorian if(s-ip >= MAX_ADDR_STRLEN) 277ae8c6e27Sflorian return 0; 278ae8c6e27Sflorian (void)strlcpy(buf, ip, sizeof(buf)); 279ae8c6e27Sflorian buf[s-ip]=0; 280ebe14541Sflorian #ifdef HAVE_IF_NAMETOINDEX 281ebe14541Sflorian if (!(sa->sin6_scope_id = if_nametoindex(s+1))) 282ebe14541Sflorian #endif /* HAVE_IF_NAMETOINDEX */ 283ae8c6e27Sflorian sa->sin6_scope_id = (uint32_t)atoi(s+1); 284ae8c6e27Sflorian ip = buf; 285ae8c6e27Sflorian } 286ae8c6e27Sflorian if(inet_pton((int)sa->sin6_family, ip, &sa->sin6_addr) <= 0) { 287ae8c6e27Sflorian return 0; 288ae8c6e27Sflorian } 289ae8c6e27Sflorian } else { /* ip4 */ 290ae8c6e27Sflorian struct sockaddr_in* sa = (struct sockaddr_in*)addr; 291ae8c6e27Sflorian *addrlen = (socklen_t)sizeof(struct sockaddr_in); 292ae8c6e27Sflorian memset(sa, 0, *addrlen); 293ae8c6e27Sflorian sa->sin_family = AF_INET; 294ae8c6e27Sflorian sa->sin_port = (in_port_t)htons(p); 295ae8c6e27Sflorian if(inet_pton((int)sa->sin_family, ip, &sa->sin_addr) <= 0) { 296ae8c6e27Sflorian return 0; 297ae8c6e27Sflorian } 298ae8c6e27Sflorian } 299ae8c6e27Sflorian return 1; 300ae8c6e27Sflorian } 301ae8c6e27Sflorian 302ae8c6e27Sflorian int netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr, 303ae8c6e27Sflorian socklen_t* addrlen, int* net) 304ae8c6e27Sflorian { 305ae8c6e27Sflorian char buf[64]; 306ae8c6e27Sflorian char* s; 307ae8c6e27Sflorian *net = (str_is_ip6(str)?128:32); 308ae8c6e27Sflorian if((s=strchr(str, '/'))) { 309ae8c6e27Sflorian if(atoi(s+1) > *net) { 310ae8c6e27Sflorian log_err("netblock too large: %s", str); 311ae8c6e27Sflorian return 0; 312ae8c6e27Sflorian } 313ae8c6e27Sflorian *net = atoi(s+1); 314ae8c6e27Sflorian if(*net == 0 && strcmp(s+1, "0") != 0) { 315ae8c6e27Sflorian log_err("cannot parse netblock: '%s'", str); 316ae8c6e27Sflorian return 0; 317ae8c6e27Sflorian } 318ae8c6e27Sflorian strlcpy(buf, str, sizeof(buf)); 319ae8c6e27Sflorian s = strchr(buf, '/'); 320ae8c6e27Sflorian if(s) *s = 0; 321ae8c6e27Sflorian s = buf; 322ae8c6e27Sflorian } 323ae8c6e27Sflorian if(!ipstrtoaddr(s?s:str, port, addr, addrlen)) { 324ae8c6e27Sflorian log_err("cannot parse ip address: '%s'", str); 325ae8c6e27Sflorian return 0; 326ae8c6e27Sflorian } 327ae8c6e27Sflorian if(s) { 328ae8c6e27Sflorian addr_mask(addr, *addrlen, *net); 329ae8c6e27Sflorian } 330ae8c6e27Sflorian return 1; 331ae8c6e27Sflorian } 332ae8c6e27Sflorian 333d32eb43cSflorian /* RPZ format address dname to network byte order address */ 334d32eb43cSflorian static int ipdnametoaddr(uint8_t* dname, size_t dnamelen, 335d32eb43cSflorian struct sockaddr_storage* addr, socklen_t* addrlen, int* af) 336d32eb43cSflorian { 337d32eb43cSflorian uint8_t* ia; 338a8eaceedSflorian int dnamelabs = dname_count_labels(dname); 339d32eb43cSflorian uint8_t lablen; 340d32eb43cSflorian char* e = NULL; 341d32eb43cSflorian int z = 0; 342d32eb43cSflorian size_t len = 0; 343d32eb43cSflorian int i; 344d32eb43cSflorian *af = AF_INET; 345d32eb43cSflorian 346d32eb43cSflorian /* need 1 byte for label length */ 347d32eb43cSflorian if(dnamelen < 1) 348d32eb43cSflorian return 0; 349d32eb43cSflorian 350d32eb43cSflorian if(dnamelabs > 6 || 351d32eb43cSflorian dname_has_label(dname, dnamelen, (uint8_t*)"\002zz")) { 352d32eb43cSflorian *af = AF_INET6; 353d32eb43cSflorian } 354d32eb43cSflorian len = *dname; 355d32eb43cSflorian lablen = *dname++; 356d32eb43cSflorian i = (*af == AF_INET) ? 3 : 15; 357d32eb43cSflorian if(*af == AF_INET6) { 358d32eb43cSflorian struct sockaddr_in6* sa = (struct sockaddr_in6*)addr; 359d32eb43cSflorian *addrlen = (socklen_t)sizeof(struct sockaddr_in6); 360d32eb43cSflorian memset(sa, 0, *addrlen); 361d32eb43cSflorian sa->sin6_family = AF_INET6; 362d32eb43cSflorian ia = (uint8_t*)&sa->sin6_addr; 363d32eb43cSflorian } else { /* ip4 */ 364d32eb43cSflorian struct sockaddr_in* sa = (struct sockaddr_in*)addr; 365d32eb43cSflorian *addrlen = (socklen_t)sizeof(struct sockaddr_in); 366d32eb43cSflorian memset(sa, 0, *addrlen); 367d32eb43cSflorian sa->sin_family = AF_INET; 368d32eb43cSflorian ia = (uint8_t*)&sa->sin_addr; 369d32eb43cSflorian } 370d32eb43cSflorian while(lablen && i >= 0 && len <= dnamelen) { 371d32eb43cSflorian char buff[LDNS_MAX_LABELLEN+1]; 372d32eb43cSflorian uint16_t chunk; /* big enough to not overflow on IPv6 hextet */ 373d32eb43cSflorian if((*af == AF_INET && (lablen > 3 || dnamelabs > 6)) || 374d32eb43cSflorian (*af == AF_INET6 && (lablen > 4 || dnamelabs > 10))) { 375d32eb43cSflorian return 0; 376d32eb43cSflorian } 377d32eb43cSflorian if(memcmp(dname, "zz", 2) == 0 && *af == AF_INET6) { 378d32eb43cSflorian /* Add one or more 0 labels. Address is initialised at 379d32eb43cSflorian * 0, so just skip the zero part. */ 380d32eb43cSflorian int zl = 11 - dnamelabs; 381d32eb43cSflorian if(z || zl < 0) 382d32eb43cSflorian return 0; 383d32eb43cSflorian z = 1; 384d32eb43cSflorian i -= (zl*2); 385d32eb43cSflorian } else { 386d32eb43cSflorian memcpy(buff, dname, lablen); 387d32eb43cSflorian buff[lablen] = '\0'; 388d32eb43cSflorian chunk = strtol(buff, &e, (*af == AF_INET) ? 10 : 16); 389d32eb43cSflorian if(!e || *e != '\0' || (*af == AF_INET && chunk > 255)) 390d32eb43cSflorian return 0; 391d32eb43cSflorian if(*af == AF_INET) { 392d32eb43cSflorian log_assert(i < 4 && i >= 0); 393d32eb43cSflorian ia[i] = (uint8_t)chunk; 394d32eb43cSflorian i--; 395d32eb43cSflorian } else { 396d32eb43cSflorian log_assert(i < 16 && i >= 1); 397d32eb43cSflorian /* ia in network byte order */ 398d32eb43cSflorian ia[i-1] = (uint8_t)(chunk >> 8); 399d32eb43cSflorian ia[i] = (uint8_t)(chunk & 0x00FF); 400d32eb43cSflorian i -= 2; 401d32eb43cSflorian } 402d32eb43cSflorian } 403d32eb43cSflorian dname += lablen; 404d32eb43cSflorian lablen = *dname++; 405d32eb43cSflorian len += lablen; 406d32eb43cSflorian } 407d32eb43cSflorian if(i != -1) 408d32eb43cSflorian /* input too short */ 409d32eb43cSflorian return 0; 410d32eb43cSflorian return 1; 411d32eb43cSflorian } 412d32eb43cSflorian 413d32eb43cSflorian int netblockdnametoaddr(uint8_t* dname, size_t dnamelen, 414d32eb43cSflorian struct sockaddr_storage* addr, socklen_t* addrlen, int* net, int* af) 415d32eb43cSflorian { 416d32eb43cSflorian char buff[3 /* 3 digit netblock */ + 1]; 417d32eb43cSflorian size_t nlablen; 418d32eb43cSflorian if(dnamelen < 1 || *dname > 3) 419d32eb43cSflorian /* netblock invalid */ 420d32eb43cSflorian return 0; 421d32eb43cSflorian nlablen = *dname; 422d32eb43cSflorian 423d32eb43cSflorian if(dnamelen < 1 + nlablen) 424d32eb43cSflorian return 0; 425d32eb43cSflorian 426d32eb43cSflorian memcpy(buff, dname+1, nlablen); 427d32eb43cSflorian buff[nlablen] = '\0'; 428d32eb43cSflorian *net = atoi(buff); 429d32eb43cSflorian if(*net == 0 && strcmp(buff, "0") != 0) 430d32eb43cSflorian return 0; 431d32eb43cSflorian dname += nlablen; 432d32eb43cSflorian dname++; 433d32eb43cSflorian if(!ipdnametoaddr(dname, dnamelen-1-nlablen, addr, addrlen, af)) 434d32eb43cSflorian return 0; 435d32eb43cSflorian if((*af == AF_INET6 && *net > 128) || (*af == AF_INET && *net > 32)) 436d32eb43cSflorian return 0; 437d32eb43cSflorian return 1; 438d32eb43cSflorian } 439d32eb43cSflorian 440ae8c6e27Sflorian int authextstrtoaddr(char* str, struct sockaddr_storage* addr, 441ae8c6e27Sflorian socklen_t* addrlen, char** auth_name) 442ae8c6e27Sflorian { 443ae8c6e27Sflorian char* s; 444ae8c6e27Sflorian int port = UNBOUND_DNS_PORT; 445ae8c6e27Sflorian if((s=strchr(str, '@'))) { 446ae8c6e27Sflorian char buf[MAX_ADDR_STRLEN]; 447ae8c6e27Sflorian size_t len = (size_t)(s-str); 448ae8c6e27Sflorian char* hash = strchr(s+1, '#'); 449ae8c6e27Sflorian if(hash) { 450ae8c6e27Sflorian *auth_name = hash+1; 451ae8c6e27Sflorian } else { 452ae8c6e27Sflorian *auth_name = NULL; 453ae8c6e27Sflorian } 454ae8c6e27Sflorian if(len >= MAX_ADDR_STRLEN) { 455ae8c6e27Sflorian return 0; 456ae8c6e27Sflorian } 457ae8c6e27Sflorian (void)strlcpy(buf, str, sizeof(buf)); 458ae8c6e27Sflorian buf[len] = 0; 459ae8c6e27Sflorian port = atoi(s+1); 460ae8c6e27Sflorian if(port == 0) { 461ae8c6e27Sflorian if(!hash && strcmp(s+1,"0")!=0) 462ae8c6e27Sflorian return 0; 463ae8c6e27Sflorian if(hash && strncmp(s+1,"0#",2)!=0) 464ae8c6e27Sflorian return 0; 465ae8c6e27Sflorian } 466ae8c6e27Sflorian return ipstrtoaddr(buf, port, addr, addrlen); 467ae8c6e27Sflorian } 468ae8c6e27Sflorian if((s=strchr(str, '#'))) { 469ae8c6e27Sflorian char buf[MAX_ADDR_STRLEN]; 470ae8c6e27Sflorian size_t len = (size_t)(s-str); 471ae8c6e27Sflorian if(len >= MAX_ADDR_STRLEN) { 472ae8c6e27Sflorian return 0; 473ae8c6e27Sflorian } 474ae8c6e27Sflorian (void)strlcpy(buf, str, sizeof(buf)); 475ae8c6e27Sflorian buf[len] = 0; 476ae8c6e27Sflorian port = UNBOUND_DNS_OVER_TLS_PORT; 477ae8c6e27Sflorian *auth_name = s+1; 478ae8c6e27Sflorian return ipstrtoaddr(buf, port, addr, addrlen); 479ae8c6e27Sflorian } 480ae8c6e27Sflorian *auth_name = NULL; 481ae8c6e27Sflorian return ipstrtoaddr(str, port, addr, addrlen); 482ae8c6e27Sflorian } 483ae8c6e27Sflorian 484a1a7ba80Sflorian uint8_t* authextstrtodname(char* str, int* port, char** auth_name) 485a1a7ba80Sflorian { 486a1a7ba80Sflorian char* s; 487a1a7ba80Sflorian uint8_t* dname; 488a1a7ba80Sflorian size_t dname_len; 489a1a7ba80Sflorian *port = UNBOUND_DNS_PORT; 490a1a7ba80Sflorian *auth_name = NULL; 491a1a7ba80Sflorian if((s=strchr(str, '@'))) { 492096314feSflorian char buf[MAX_HOST_STRLEN]; 493096314feSflorian size_t len = (size_t)(s-str); 494a1a7ba80Sflorian char* hash = strchr(s+1, '#'); 495a1a7ba80Sflorian if(hash) { 496a1a7ba80Sflorian *auth_name = hash+1; 497a1a7ba80Sflorian } else { 498a1a7ba80Sflorian *auth_name = NULL; 499a1a7ba80Sflorian } 500096314feSflorian if(len >= MAX_HOST_STRLEN) { 501096314feSflorian return NULL; 502096314feSflorian } 503096314feSflorian (void)strlcpy(buf, str, sizeof(buf)); 504096314feSflorian buf[len] = 0; 505a1a7ba80Sflorian *port = atoi(s+1); 506a1a7ba80Sflorian if(*port == 0) { 507a1a7ba80Sflorian if(!hash && strcmp(s+1,"0")!=0) 508096314feSflorian return NULL; 509a1a7ba80Sflorian if(hash && strncmp(s+1,"0#",2)!=0) 510096314feSflorian return NULL; 511a1a7ba80Sflorian } 512096314feSflorian dname = sldns_str2wire_dname(buf, &dname_len); 513a1a7ba80Sflorian } else if((s=strchr(str, '#'))) { 514096314feSflorian char buf[MAX_HOST_STRLEN]; 515096314feSflorian size_t len = (size_t)(s-str); 516096314feSflorian if(len >= MAX_HOST_STRLEN) { 517096314feSflorian return NULL; 518096314feSflorian } 519096314feSflorian (void)strlcpy(buf, str, sizeof(buf)); 520096314feSflorian buf[len] = 0; 521a1a7ba80Sflorian *port = UNBOUND_DNS_OVER_TLS_PORT; 522a1a7ba80Sflorian *auth_name = s+1; 523096314feSflorian dname = sldns_str2wire_dname(buf, &dname_len); 524a1a7ba80Sflorian } else { 525a1a7ba80Sflorian dname = sldns_str2wire_dname(str, &dname_len); 526a1a7ba80Sflorian } 527a1a7ba80Sflorian return dname; 528a1a7ba80Sflorian } 529a1a7ba80Sflorian 530ae8c6e27Sflorian /** store port number into sockaddr structure */ 531ae8c6e27Sflorian void 532ae8c6e27Sflorian sockaddr_store_port(struct sockaddr_storage* addr, socklen_t addrlen, int port) 533ae8c6e27Sflorian { 534ae8c6e27Sflorian if(addr_is_ip6(addr, addrlen)) { 535ae8c6e27Sflorian struct sockaddr_in6* sa = (struct sockaddr_in6*)addr; 536ae8c6e27Sflorian sa->sin6_port = (in_port_t)htons((uint16_t)port); 537ae8c6e27Sflorian } else { 538ae8c6e27Sflorian struct sockaddr_in* sa = (struct sockaddr_in*)addr; 539ae8c6e27Sflorian sa->sin_port = (in_port_t)htons((uint16_t)port); 540ae8c6e27Sflorian } 541ae8c6e27Sflorian } 542ae8c6e27Sflorian 543ae8c6e27Sflorian void 544ae8c6e27Sflorian log_nametypeclass(enum verbosity_value v, const char* str, uint8_t* name, 545ae8c6e27Sflorian uint16_t type, uint16_t dclass) 546ae8c6e27Sflorian { 547ae8c6e27Sflorian char buf[LDNS_MAX_DOMAINLEN+1]; 548ae8c6e27Sflorian char t[12], c[12]; 549ae8c6e27Sflorian const char *ts, *cs; 550ae8c6e27Sflorian if(verbosity < v) 551ae8c6e27Sflorian return; 552ae8c6e27Sflorian dname_str(name, buf); 553ae8c6e27Sflorian if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG"; 554ae8c6e27Sflorian else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR"; 555ae8c6e27Sflorian else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR"; 556ae8c6e27Sflorian else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB"; 557ae8c6e27Sflorian else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA"; 558ae8c6e27Sflorian else if(type == LDNS_RR_TYPE_ANY) ts = "ANY"; 559ae8c6e27Sflorian else if(sldns_rr_descript(type) && sldns_rr_descript(type)->_name) 560ae8c6e27Sflorian ts = sldns_rr_descript(type)->_name; 561ae8c6e27Sflorian else { 562ae8c6e27Sflorian snprintf(t, sizeof(t), "TYPE%d", (int)type); 563ae8c6e27Sflorian ts = t; 564ae8c6e27Sflorian } 565ae8c6e27Sflorian if(sldns_lookup_by_id(sldns_rr_classes, (int)dclass) && 566ae8c6e27Sflorian sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name) 567ae8c6e27Sflorian cs = sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name; 568ae8c6e27Sflorian else { 569ae8c6e27Sflorian snprintf(c, sizeof(c), "CLASS%d", (int)dclass); 570ae8c6e27Sflorian cs = c; 571ae8c6e27Sflorian } 572ae8c6e27Sflorian log_info("%s %s %s %s", str, buf, ts, cs); 573ae8c6e27Sflorian } 574ae8c6e27Sflorian 575e97c6e54Ssthen void 576e97c6e54Ssthen log_query_in(const char* str, uint8_t* name, uint16_t type, uint16_t dclass) 577e97c6e54Ssthen { 578e97c6e54Ssthen char buf[LDNS_MAX_DOMAINLEN+1]; 579e97c6e54Ssthen char t[12], c[12]; 580e97c6e54Ssthen const char *ts, *cs; 581e97c6e54Ssthen dname_str(name, buf); 582e97c6e54Ssthen if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG"; 583e97c6e54Ssthen else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR"; 584e97c6e54Ssthen else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR"; 585e97c6e54Ssthen else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB"; 586e97c6e54Ssthen else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA"; 587e97c6e54Ssthen else if(type == LDNS_RR_TYPE_ANY) ts = "ANY"; 588e97c6e54Ssthen else if(sldns_rr_descript(type) && sldns_rr_descript(type)->_name) 589e97c6e54Ssthen ts = sldns_rr_descript(type)->_name; 590e97c6e54Ssthen else { 591e97c6e54Ssthen snprintf(t, sizeof(t), "TYPE%d", (int)type); 592e97c6e54Ssthen ts = t; 593e97c6e54Ssthen } 594e97c6e54Ssthen if(sldns_lookup_by_id(sldns_rr_classes, (int)dclass) && 595e97c6e54Ssthen sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name) 596e97c6e54Ssthen cs = sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name; 597e97c6e54Ssthen else { 598e97c6e54Ssthen snprintf(c, sizeof(c), "CLASS%d", (int)dclass); 599e97c6e54Ssthen cs = c; 600e97c6e54Ssthen } 601e97c6e54Ssthen if(LOG_TAG_QUERYREPLY) 602e97c6e54Ssthen log_query("%s %s %s %s", str, buf, ts, cs); 603e97c6e54Ssthen else log_info("%s %s %s %s", str, buf, ts, cs); 604e97c6e54Ssthen } 605e97c6e54Ssthen 606ae8c6e27Sflorian void log_name_addr(enum verbosity_value v, const char* str, uint8_t* zone, 607ae8c6e27Sflorian struct sockaddr_storage* addr, socklen_t addrlen) 608ae8c6e27Sflorian { 609ae8c6e27Sflorian uint16_t port; 610ae8c6e27Sflorian const char* family = "unknown_family "; 611ae8c6e27Sflorian char namebuf[LDNS_MAX_DOMAINLEN+1]; 612ae8c6e27Sflorian char dest[100]; 613ae8c6e27Sflorian int af = (int)((struct sockaddr_in*)addr)->sin_family; 614ae8c6e27Sflorian void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 615ae8c6e27Sflorian if(verbosity < v) 616ae8c6e27Sflorian return; 617ae8c6e27Sflorian switch(af) { 618ae8c6e27Sflorian case AF_INET: family=""; break; 619ae8c6e27Sflorian case AF_INET6: family=""; 620ae8c6e27Sflorian sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; 621ae8c6e27Sflorian break; 622ae8c6e27Sflorian case AF_LOCAL: family="local "; break; 623ae8c6e27Sflorian default: break; 624ae8c6e27Sflorian } 625ae8c6e27Sflorian if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { 626ae8c6e27Sflorian (void)strlcpy(dest, "(inet_ntop error)", sizeof(dest)); 627ae8c6e27Sflorian } 628ae8c6e27Sflorian dest[sizeof(dest)-1] = 0; 629ae8c6e27Sflorian port = ntohs(((struct sockaddr_in*)addr)->sin_port); 630ae8c6e27Sflorian dname_str(zone, namebuf); 631ae8c6e27Sflorian if(af != AF_INET && af != AF_INET6) 632ae8c6e27Sflorian verbose(v, "%s <%s> %s%s#%d (addrlen %d)", 633ae8c6e27Sflorian str, namebuf, family, dest, (int)port, (int)addrlen); 634ae8c6e27Sflorian else verbose(v, "%s <%s> %s%s#%d", 635ae8c6e27Sflorian str, namebuf, family, dest, (int)port); 636ae8c6e27Sflorian } 637ae8c6e27Sflorian 638ae8c6e27Sflorian void log_err_addr(const char* str, const char* err, 639ae8c6e27Sflorian struct sockaddr_storage* addr, socklen_t addrlen) 640ae8c6e27Sflorian { 641ae8c6e27Sflorian uint16_t port; 642ae8c6e27Sflorian char dest[100]; 643ae8c6e27Sflorian int af = (int)((struct sockaddr_in*)addr)->sin_family; 644ae8c6e27Sflorian void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 645ae8c6e27Sflorian if(af == AF_INET6) 646ae8c6e27Sflorian sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; 647ae8c6e27Sflorian if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { 648ae8c6e27Sflorian (void)strlcpy(dest, "(inet_ntop error)", sizeof(dest)); 649ae8c6e27Sflorian } 650ae8c6e27Sflorian dest[sizeof(dest)-1] = 0; 651ae8c6e27Sflorian port = ntohs(((struct sockaddr_in*)addr)->sin_port); 652ae8c6e27Sflorian if(verbosity >= 4) 653ae8c6e27Sflorian log_err("%s: %s for %s port %d (len %d)", str, err, dest, 654ae8c6e27Sflorian (int)port, (int)addrlen); 655ae8c6e27Sflorian else log_err("%s: %s for %s port %d", str, err, dest, (int)port); 656ae8c6e27Sflorian } 657ae8c6e27Sflorian 658ae8c6e27Sflorian int 659ae8c6e27Sflorian sockaddr_cmp(struct sockaddr_storage* addr1, socklen_t len1, 660ae8c6e27Sflorian struct sockaddr_storage* addr2, socklen_t len2) 661ae8c6e27Sflorian { 662ae8c6e27Sflorian struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1; 663ae8c6e27Sflorian struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2; 664ae8c6e27Sflorian struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1; 665ae8c6e27Sflorian struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2; 666ae8c6e27Sflorian if(len1 < len2) 667ae8c6e27Sflorian return -1; 668ae8c6e27Sflorian if(len1 > len2) 669ae8c6e27Sflorian return 1; 670ae8c6e27Sflorian log_assert(len1 == len2); 671ae8c6e27Sflorian if( p1_in->sin_family < p2_in->sin_family) 672ae8c6e27Sflorian return -1; 673ae8c6e27Sflorian if( p1_in->sin_family > p2_in->sin_family) 674ae8c6e27Sflorian return 1; 675ae8c6e27Sflorian log_assert( p1_in->sin_family == p2_in->sin_family ); 676ae8c6e27Sflorian /* compare ip4 */ 677ae8c6e27Sflorian if( p1_in->sin_family == AF_INET ) { 678ae8c6e27Sflorian /* just order it, ntohs not required */ 679ae8c6e27Sflorian if(p1_in->sin_port < p2_in->sin_port) 680ae8c6e27Sflorian return -1; 681ae8c6e27Sflorian if(p1_in->sin_port > p2_in->sin_port) 682ae8c6e27Sflorian return 1; 683ae8c6e27Sflorian log_assert(p1_in->sin_port == p2_in->sin_port); 684ae8c6e27Sflorian return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE); 685ae8c6e27Sflorian } else if (p1_in6->sin6_family == AF_INET6) { 686ae8c6e27Sflorian /* just order it, ntohs not required */ 687ae8c6e27Sflorian if(p1_in6->sin6_port < p2_in6->sin6_port) 688ae8c6e27Sflorian return -1; 689ae8c6e27Sflorian if(p1_in6->sin6_port > p2_in6->sin6_port) 690ae8c6e27Sflorian return 1; 691ae8c6e27Sflorian log_assert(p1_in6->sin6_port == p2_in6->sin6_port); 692ae8c6e27Sflorian return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr, 693ae8c6e27Sflorian INET6_SIZE); 694ae8c6e27Sflorian } else { 695ae8c6e27Sflorian /* eek unknown type, perform this comparison for sanity. */ 696ae8c6e27Sflorian return memcmp(addr1, addr2, len1); 697ae8c6e27Sflorian } 698ae8c6e27Sflorian } 699ae8c6e27Sflorian 700ae8c6e27Sflorian int 701ae8c6e27Sflorian sockaddr_cmp_addr(struct sockaddr_storage* addr1, socklen_t len1, 702ae8c6e27Sflorian struct sockaddr_storage* addr2, socklen_t len2) 703ae8c6e27Sflorian { 704ae8c6e27Sflorian struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1; 705ae8c6e27Sflorian struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2; 706ae8c6e27Sflorian struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1; 707ae8c6e27Sflorian struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2; 708ae8c6e27Sflorian if(len1 < len2) 709ae8c6e27Sflorian return -1; 710ae8c6e27Sflorian if(len1 > len2) 711ae8c6e27Sflorian return 1; 712ae8c6e27Sflorian log_assert(len1 == len2); 713ae8c6e27Sflorian if( p1_in->sin_family < p2_in->sin_family) 714ae8c6e27Sflorian return -1; 715ae8c6e27Sflorian if( p1_in->sin_family > p2_in->sin_family) 716ae8c6e27Sflorian return 1; 717ae8c6e27Sflorian log_assert( p1_in->sin_family == p2_in->sin_family ); 718ae8c6e27Sflorian /* compare ip4 */ 719ae8c6e27Sflorian if( p1_in->sin_family == AF_INET ) { 720ae8c6e27Sflorian return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE); 721ae8c6e27Sflorian } else if (p1_in6->sin6_family == AF_INET6) { 722ae8c6e27Sflorian return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr, 723ae8c6e27Sflorian INET6_SIZE); 724ae8c6e27Sflorian } else { 725ae8c6e27Sflorian /* eek unknown type, perform this comparison for sanity. */ 726ae8c6e27Sflorian return memcmp(addr1, addr2, len1); 727ae8c6e27Sflorian } 728ae8c6e27Sflorian } 729ae8c6e27Sflorian 730ae8c6e27Sflorian int 731ae8c6e27Sflorian addr_is_ip6(struct sockaddr_storage* addr, socklen_t len) 732ae8c6e27Sflorian { 733ae8c6e27Sflorian if(len == (socklen_t)sizeof(struct sockaddr_in6) && 734ae8c6e27Sflorian ((struct sockaddr_in6*)addr)->sin6_family == AF_INET6) 735ae8c6e27Sflorian return 1; 736ae8c6e27Sflorian else return 0; 737ae8c6e27Sflorian } 738ae8c6e27Sflorian 739ae8c6e27Sflorian void 740ae8c6e27Sflorian addr_mask(struct sockaddr_storage* addr, socklen_t len, int net) 741ae8c6e27Sflorian { 742ae8c6e27Sflorian uint8_t mask[8] = {0x0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe}; 743ae8c6e27Sflorian int i, max; 744ae8c6e27Sflorian uint8_t* s; 745ae8c6e27Sflorian if(addr_is_ip6(addr, len)) { 746ae8c6e27Sflorian s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr; 747ae8c6e27Sflorian max = 128; 748ae8c6e27Sflorian } else { 749ae8c6e27Sflorian s = (uint8_t*)&((struct sockaddr_in*)addr)->sin_addr; 750ae8c6e27Sflorian max = 32; 751ae8c6e27Sflorian } 752ae8c6e27Sflorian if(net >= max) 753ae8c6e27Sflorian return; 754ae8c6e27Sflorian for(i=net/8+1; i<max/8; i++) { 755ae8c6e27Sflorian s[i] = 0; 756ae8c6e27Sflorian } 757ae8c6e27Sflorian s[net/8] &= mask[net&0x7]; 758ae8c6e27Sflorian } 759ae8c6e27Sflorian 760ae8c6e27Sflorian int 761ae8c6e27Sflorian addr_in_common(struct sockaddr_storage* addr1, int net1, 762ae8c6e27Sflorian struct sockaddr_storage* addr2, int net2, socklen_t addrlen) 763ae8c6e27Sflorian { 764ae8c6e27Sflorian int min = (net1<net2)?net1:net2; 765ae8c6e27Sflorian int i, to; 766ae8c6e27Sflorian int match = 0; 767ae8c6e27Sflorian uint8_t* s1, *s2; 768ae8c6e27Sflorian if(addr_is_ip6(addr1, addrlen)) { 769ae8c6e27Sflorian s1 = (uint8_t*)&((struct sockaddr_in6*)addr1)->sin6_addr; 770ae8c6e27Sflorian s2 = (uint8_t*)&((struct sockaddr_in6*)addr2)->sin6_addr; 771ae8c6e27Sflorian to = 16; 772ae8c6e27Sflorian } else { 773ae8c6e27Sflorian s1 = (uint8_t*)&((struct sockaddr_in*)addr1)->sin_addr; 774ae8c6e27Sflorian s2 = (uint8_t*)&((struct sockaddr_in*)addr2)->sin_addr; 775ae8c6e27Sflorian to = 4; 776ae8c6e27Sflorian } 777ae8c6e27Sflorian /* match = bits_in_common(s1, s2, to); */ 778ae8c6e27Sflorian for(i=0; i<to; i++) { 779ae8c6e27Sflorian if(s1[i] == s2[i]) { 780ae8c6e27Sflorian match += 8; 781ae8c6e27Sflorian } else { 782ae8c6e27Sflorian uint8_t z = s1[i]^s2[i]; 783ae8c6e27Sflorian log_assert(z); 784ae8c6e27Sflorian while(!(z&0x80)) { 785ae8c6e27Sflorian match++; 786ae8c6e27Sflorian z<<=1; 787ae8c6e27Sflorian } 788ae8c6e27Sflorian break; 789ae8c6e27Sflorian } 790ae8c6e27Sflorian } 791ae8c6e27Sflorian if(match > min) match = min; 792ae8c6e27Sflorian return match; 793ae8c6e27Sflorian } 794ae8c6e27Sflorian 795ae8c6e27Sflorian void 796ae8c6e27Sflorian addr_to_str(struct sockaddr_storage* addr, socklen_t addrlen, 797ae8c6e27Sflorian char* buf, size_t len) 798ae8c6e27Sflorian { 799ae8c6e27Sflorian int af = (int)((struct sockaddr_in*)addr)->sin_family; 800ae8c6e27Sflorian void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 801ae8c6e27Sflorian if(addr_is_ip6(addr, addrlen)) 802ae8c6e27Sflorian sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; 803ae8c6e27Sflorian if(inet_ntop(af, sinaddr, buf, (socklen_t)len) == 0) { 804ae8c6e27Sflorian snprintf(buf, len, "(inet_ntop_error)"); 805ae8c6e27Sflorian } 806ae8c6e27Sflorian } 807ae8c6e27Sflorian 808ae8c6e27Sflorian int 809d500c338Sflorian prefixnet_is_nat64(int prefixnet) 810d500c338Sflorian { 811d500c338Sflorian return (prefixnet == 32 || prefixnet == 40 || 812d500c338Sflorian prefixnet == 48 || prefixnet == 56 || 813d500c338Sflorian prefixnet == 64 || prefixnet == 96); 814d500c338Sflorian } 815d500c338Sflorian 816d500c338Sflorian void 817d500c338Sflorian addr_to_nat64(const struct sockaddr_storage* addr, 818d500c338Sflorian const struct sockaddr_storage* nat64_prefix, 819d500c338Sflorian socklen_t nat64_prefixlen, int nat64_prefixnet, 820d500c338Sflorian struct sockaddr_storage* nat64_addr, socklen_t* nat64_addrlen) 821d500c338Sflorian { 822d500c338Sflorian struct sockaddr_in *sin = (struct sockaddr_in *)addr; 823d500c338Sflorian struct sockaddr_in6 *sin6; 824d500c338Sflorian uint8_t *v4_byte; 825fc357d0dSderaadt int i; 826d500c338Sflorian 827d500c338Sflorian /* This needs to be checked by the caller */ 828d500c338Sflorian log_assert(addr->ss_family == AF_INET); 829d500c338Sflorian /* Current usage is only from config values; prefix lengths enforced 830d500c338Sflorian * during config validation */ 831d500c338Sflorian log_assert(prefixnet_is_nat64(nat64_prefixnet)); 832d500c338Sflorian 833d500c338Sflorian *nat64_addr = *nat64_prefix; 834d500c338Sflorian *nat64_addrlen = nat64_prefixlen; 835d500c338Sflorian 836d500c338Sflorian sin6 = (struct sockaddr_in6 *)nat64_addr; 837d500c338Sflorian sin6->sin6_flowinfo = 0; 838d500c338Sflorian sin6->sin6_port = sin->sin_port; 839d500c338Sflorian 840d500c338Sflorian nat64_prefixnet = nat64_prefixnet / 8; 841d500c338Sflorian 842d500c338Sflorian v4_byte = (uint8_t *)&sin->sin_addr.s_addr; 843fc357d0dSderaadt for(i = 0; i < 4; i++) { 844d500c338Sflorian if(nat64_prefixnet == 8) { 845d500c338Sflorian /* bits 64...71 are MBZ */ 846d500c338Sflorian sin6->sin6_addr.s6_addr[nat64_prefixnet++] = 0; 847d500c338Sflorian } 848d500c338Sflorian sin6->sin6_addr.s6_addr[nat64_prefixnet++] = *v4_byte++; 849d500c338Sflorian } 850d500c338Sflorian } 851d500c338Sflorian 852d500c338Sflorian int 853ae8c6e27Sflorian addr_is_ip4mapped(struct sockaddr_storage* addr, socklen_t addrlen) 854ae8c6e27Sflorian { 855ae8c6e27Sflorian /* prefix for ipv4 into ipv6 mapping is ::ffff:x.x.x.x */ 856ae8c6e27Sflorian const uint8_t map_prefix[16] = 857ae8c6e27Sflorian {0,0,0,0, 0,0,0,0, 0,0,0xff,0xff, 0,0,0,0}; 858ae8c6e27Sflorian uint8_t* s; 859ae8c6e27Sflorian if(!addr_is_ip6(addr, addrlen)) 860ae8c6e27Sflorian return 0; 861ae8c6e27Sflorian /* s is 16 octet ipv6 address string */ 862ae8c6e27Sflorian s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr; 863ae8c6e27Sflorian return (memcmp(s, map_prefix, 12) == 0); 864ae8c6e27Sflorian } 865ae8c6e27Sflorian 866*7037e34cSflorian int addr_is_ip6linklocal(struct sockaddr_storage* addr, socklen_t addrlen) 867*7037e34cSflorian { 868*7037e34cSflorian const uint8_t prefix[2] = {0xfe, 0x80}; 869*7037e34cSflorian int af = (int)((struct sockaddr_in6*)addr)->sin6_family; 870*7037e34cSflorian void* sin6addr = &((struct sockaddr_in6*)addr)->sin6_addr; 871*7037e34cSflorian uint8_t start[2]; 872*7037e34cSflorian if(af != AF_INET6 || addrlen<(socklen_t)sizeof(struct sockaddr_in6)) 873*7037e34cSflorian return 0; 874*7037e34cSflorian /* Put the first 10 bits of sin6addr in start, match fe80::/10. */ 875*7037e34cSflorian memmove(start, sin6addr, 2); 876*7037e34cSflorian start[1] &= 0xc0; 877*7037e34cSflorian return memcmp(start, prefix, 2) == 0; 878*7037e34cSflorian } 879*7037e34cSflorian 880ae8c6e27Sflorian int addr_is_broadcast(struct sockaddr_storage* addr, socklen_t addrlen) 881ae8c6e27Sflorian { 882ae8c6e27Sflorian int af = (int)((struct sockaddr_in*)addr)->sin_family; 883ae8c6e27Sflorian void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 884ae8c6e27Sflorian return af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in) 885ae8c6e27Sflorian && memcmp(sinaddr, "\377\377\377\377", 4) == 0; 886ae8c6e27Sflorian } 887ae8c6e27Sflorian 888ae8c6e27Sflorian int addr_is_any(struct sockaddr_storage* addr, socklen_t addrlen) 889ae8c6e27Sflorian { 890ae8c6e27Sflorian int af = (int)((struct sockaddr_in*)addr)->sin_family; 891ae8c6e27Sflorian void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 892ae8c6e27Sflorian void* sin6addr = &((struct sockaddr_in6*)addr)->sin6_addr; 893ae8c6e27Sflorian if(af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in) 894ae8c6e27Sflorian && memcmp(sinaddr, "\000\000\000\000", 4) == 0) 895ae8c6e27Sflorian return 1; 896ae8c6e27Sflorian else if(af==AF_INET6 && addrlen>=(socklen_t)sizeof(struct sockaddr_in6) 897ae8c6e27Sflorian && memcmp(sin6addr, "\000\000\000\000\000\000\000\000" 898ae8c6e27Sflorian "\000\000\000\000\000\000\000\000", 16) == 0) 899ae8c6e27Sflorian return 1; 900ae8c6e27Sflorian return 0; 901ae8c6e27Sflorian } 902ae8c6e27Sflorian 903ae8c6e27Sflorian void sock_list_insert(struct sock_list** list, struct sockaddr_storage* addr, 904ae8c6e27Sflorian socklen_t len, struct regional* region) 905ae8c6e27Sflorian { 906ae8c6e27Sflorian struct sock_list* add = (struct sock_list*)regional_alloc(region, 907ae8c6e27Sflorian sizeof(*add) - sizeof(add->addr) + (size_t)len); 908ae8c6e27Sflorian if(!add) { 909ae8c6e27Sflorian log_err("out of memory in socketlist insert"); 910ae8c6e27Sflorian return; 911ae8c6e27Sflorian } 912ae8c6e27Sflorian log_assert(list); 913ae8c6e27Sflorian add->next = *list; 914ae8c6e27Sflorian add->len = len; 915ae8c6e27Sflorian *list = add; 916ae8c6e27Sflorian if(len) memmove(&add->addr, addr, len); 917ae8c6e27Sflorian } 918ae8c6e27Sflorian 919ae8c6e27Sflorian void sock_list_prepend(struct sock_list** list, struct sock_list* add) 920ae8c6e27Sflorian { 921ae8c6e27Sflorian struct sock_list* last = add; 922ae8c6e27Sflorian if(!last) 923ae8c6e27Sflorian return; 924ae8c6e27Sflorian while(last->next) 925ae8c6e27Sflorian last = last->next; 926ae8c6e27Sflorian last->next = *list; 927ae8c6e27Sflorian *list = add; 928ae8c6e27Sflorian } 929ae8c6e27Sflorian 930ae8c6e27Sflorian int sock_list_find(struct sock_list* list, struct sockaddr_storage* addr, 931ae8c6e27Sflorian socklen_t len) 932ae8c6e27Sflorian { 933ae8c6e27Sflorian while(list) { 934ae8c6e27Sflorian if(len == list->len) { 935ae8c6e27Sflorian if(len == 0 || sockaddr_cmp_addr(addr, len, 936ae8c6e27Sflorian &list->addr, list->len) == 0) 937ae8c6e27Sflorian return 1; 938ae8c6e27Sflorian } 939ae8c6e27Sflorian list = list->next; 940ae8c6e27Sflorian } 941ae8c6e27Sflorian return 0; 942ae8c6e27Sflorian } 943ae8c6e27Sflorian 944ae8c6e27Sflorian void sock_list_merge(struct sock_list** list, struct regional* region, 945ae8c6e27Sflorian struct sock_list* add) 946ae8c6e27Sflorian { 947ae8c6e27Sflorian struct sock_list* p; 948ae8c6e27Sflorian for(p=add; p; p=p->next) { 949ae8c6e27Sflorian if(!sock_list_find(*list, &p->addr, p->len)) 950ae8c6e27Sflorian sock_list_insert(list, &p->addr, p->len, region); 951ae8c6e27Sflorian } 952ae8c6e27Sflorian } 953ae8c6e27Sflorian 954ae8c6e27Sflorian void 955ae8c6e27Sflorian log_crypto_err(const char* str) 956ae8c6e27Sflorian { 957ae8c6e27Sflorian #ifdef HAVE_SSL 95857403691Sflorian log_crypto_err_code(str, ERR_get_error()); 95957403691Sflorian #else 96057403691Sflorian (void)str; 96157403691Sflorian #endif /* HAVE_SSL */ 96257403691Sflorian } 96357403691Sflorian 96457403691Sflorian void log_crypto_err_code(const char* str, unsigned long err) 96557403691Sflorian { 96657403691Sflorian #ifdef HAVE_SSL 967ae8c6e27Sflorian /* error:[error code]:[library name]:[function name]:[reason string] */ 968ae8c6e27Sflorian char buf[128]; 969ae8c6e27Sflorian unsigned long e; 97057403691Sflorian ERR_error_string_n(err, buf, sizeof(buf)); 971ae8c6e27Sflorian log_err("%s crypto %s", str, buf); 972ae8c6e27Sflorian while( (e=ERR_get_error()) ) { 973ae8c6e27Sflorian ERR_error_string_n(e, buf, sizeof(buf)); 974ae8c6e27Sflorian log_err("and additionally crypto %s", buf); 975ae8c6e27Sflorian } 976ae8c6e27Sflorian #else 977ae8c6e27Sflorian (void)str; 97857403691Sflorian (void)err; 979ae8c6e27Sflorian #endif /* HAVE_SSL */ 980ae8c6e27Sflorian } 981ae8c6e27Sflorian 982e47fef9eSflorian #ifdef HAVE_SSL 98354cc57acSflorian /** Print crypt erro with SSL_get_error want code and err_get_error code */ 98454cc57acSflorian static void log_crypto_err_io_code_arg(const char* str, int r, 98554cc57acSflorian unsigned long err, int err_present) 98654cc57acSflorian { 98754cc57acSflorian int print_errno = 0, print_crypto_err = 0; 98854cc57acSflorian const char* inf = NULL; 98954cc57acSflorian 99054cc57acSflorian switch(r) { 99154cc57acSflorian case SSL_ERROR_NONE: 99254cc57acSflorian inf = "no error"; 99354cc57acSflorian break; 99454cc57acSflorian case SSL_ERROR_ZERO_RETURN: 99554cc57acSflorian inf = "channel closed"; 99654cc57acSflorian break; 99754cc57acSflorian case SSL_ERROR_WANT_READ: 99854cc57acSflorian inf = "want read"; 99954cc57acSflorian break; 100054cc57acSflorian case SSL_ERROR_WANT_WRITE: 100154cc57acSflorian inf = "want write"; 100254cc57acSflorian break; 100354cc57acSflorian case SSL_ERROR_WANT_CONNECT: 100454cc57acSflorian inf = "want connect"; 100554cc57acSflorian break; 100654cc57acSflorian case SSL_ERROR_WANT_ACCEPT: 100754cc57acSflorian inf = "want accept"; 100854cc57acSflorian break; 100954cc57acSflorian case SSL_ERROR_WANT_X509_LOOKUP: 101054cc57acSflorian inf = "want X509 lookup"; 101154cc57acSflorian break; 101254cc57acSflorian #ifdef SSL_ERROR_WANT_ASYNC 101354cc57acSflorian case SSL_ERROR_WANT_ASYNC: 101454cc57acSflorian inf = "want async"; 101554cc57acSflorian break; 101654cc57acSflorian #endif 101754cc57acSflorian #ifdef SSL_ERROR_WANT_ASYNC_JOB 101854cc57acSflorian case SSL_ERROR_WANT_ASYNC_JOB: 101954cc57acSflorian inf = "want async job"; 102054cc57acSflorian break; 102154cc57acSflorian #endif 102254cc57acSflorian #ifdef SSL_ERROR_WANT_CLIENT_HELLO_CB 102354cc57acSflorian case SSL_ERROR_WANT_CLIENT_HELLO_CB: 102454cc57acSflorian inf = "want client hello cb"; 102554cc57acSflorian break; 102654cc57acSflorian #endif 102754cc57acSflorian case SSL_ERROR_SYSCALL: 102854cc57acSflorian print_errno = 1; 102954cc57acSflorian inf = "syscall"; 103054cc57acSflorian break; 103154cc57acSflorian case SSL_ERROR_SSL: 103254cc57acSflorian print_crypto_err = 1; 103354cc57acSflorian inf = "SSL, usually protocol, error"; 103454cc57acSflorian break; 103554cc57acSflorian default: 103654cc57acSflorian inf = "unknown SSL_get_error result code"; 103754cc57acSflorian print_errno = 1; 103854cc57acSflorian print_crypto_err = 1; 103954cc57acSflorian } 104054cc57acSflorian if(print_crypto_err) { 104154cc57acSflorian if(print_errno) { 104254cc57acSflorian char buf[1024]; 104354cc57acSflorian snprintf(buf, sizeof(buf), "%s with errno %s", 104454cc57acSflorian str, strerror(errno)); 104554cc57acSflorian if(err_present) 104654cc57acSflorian log_crypto_err_code(buf, err); 104754cc57acSflorian else log_crypto_err(buf); 104854cc57acSflorian } else { 104954cc57acSflorian if(err_present) 105054cc57acSflorian log_crypto_err_code(str, err); 105154cc57acSflorian else log_crypto_err(str); 105254cc57acSflorian } 105354cc57acSflorian } else { 105454cc57acSflorian if(print_errno) { 105554cc57acSflorian if(errno == 0) 1056096314feSflorian log_err("%s: syscall error with errno %s", 1057096314feSflorian str, strerror(errno)); 1058096314feSflorian else log_err("%s: %s", str, strerror(errno)); 105954cc57acSflorian } else { 1060096314feSflorian log_err("%s: %s", str, inf); 106154cc57acSflorian } 106254cc57acSflorian } 106354cc57acSflorian } 106454cc57acSflorian #endif /* HAVE_SSL */ 106554cc57acSflorian 106654cc57acSflorian void log_crypto_err_io(const char* str, int r) 106754cc57acSflorian { 106854cc57acSflorian #ifdef HAVE_SSL 106954cc57acSflorian log_crypto_err_io_code_arg(str, r, 0, 0); 107054cc57acSflorian #else 107154cc57acSflorian (void)str; 107254cc57acSflorian (void)r; 107354cc57acSflorian #endif /* HAVE_SSL */ 107454cc57acSflorian } 107554cc57acSflorian 107654cc57acSflorian void log_crypto_err_io_code(const char* str, int r, unsigned long err) 107754cc57acSflorian { 107854cc57acSflorian #ifdef HAVE_SSL 107954cc57acSflorian log_crypto_err_io_code_arg(str, r, err, 1); 108054cc57acSflorian #else 108154cc57acSflorian (void)str; 108254cc57acSflorian (void)r; 108354cc57acSflorian (void)err; 108454cc57acSflorian #endif /* HAVE_SSL */ 108554cc57acSflorian } 108654cc57acSflorian 108754cc57acSflorian #ifdef HAVE_SSL 1088e47fef9eSflorian /** log certificate details */ 1089e47fef9eSflorian void 1090e47fef9eSflorian log_cert(unsigned level, const char* str, void* cert) 1091e47fef9eSflorian { 1092e47fef9eSflorian BIO* bio; 1093e47fef9eSflorian char nul = 0; 1094e47fef9eSflorian char* pp = NULL; 1095e47fef9eSflorian long len; 1096e47fef9eSflorian if(verbosity < level) return; 1097e47fef9eSflorian bio = BIO_new(BIO_s_mem()); 1098e47fef9eSflorian if(!bio) return; 1099e47fef9eSflorian X509_print_ex(bio, (X509*)cert, 0, (unsigned long)-1 1100e47fef9eSflorian ^(X509_FLAG_NO_SUBJECT 1101e47fef9eSflorian |X509_FLAG_NO_ISSUER|X509_FLAG_NO_VALIDITY 1102e47fef9eSflorian |X509_FLAG_NO_EXTENSIONS|X509_FLAG_NO_AUX 1103e47fef9eSflorian |X509_FLAG_NO_ATTRIBUTES)); 1104e47fef9eSflorian BIO_write(bio, &nul, (int)sizeof(nul)); 1105e47fef9eSflorian len = BIO_get_mem_data(bio, &pp); 1106e47fef9eSflorian if(len != 0 && pp) { 1107a1a7ba80Sflorian /* reduce size of cert printout */ 1108a1a7ba80Sflorian char* s; 1109a1a7ba80Sflorian while((s=strstr(pp, " "))!=NULL) 1110a1a7ba80Sflorian memmove(s, s+1, strlen(s+1)+1); 1111a1a7ba80Sflorian while((s=strstr(pp, "\t\t"))!=NULL) 1112a1a7ba80Sflorian memmove(s, s+1, strlen(s+1)+1); 1113e47fef9eSflorian verbose(level, "%s: \n%s", str, pp); 1114e47fef9eSflorian } 1115e47fef9eSflorian BIO_free(bio); 1116e47fef9eSflorian } 1117e47fef9eSflorian #endif /* HAVE_SSL */ 1118e47fef9eSflorian 1119411c5950Sflorian #if defined(HAVE_SSL) && defined(HAVE_NGHTTP2) && defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB) 1120f4f0f0ceSflorian static int alpn_select_cb(SSL* ATTR_UNUSED(ssl), const unsigned char** out, 1121f4f0f0ceSflorian unsigned char* outlen, const unsigned char* in, unsigned int inlen, 1122f4f0f0ceSflorian void* ATTR_UNUSED(arg)) 1123f4f0f0ceSflorian { 1124f4f0f0ceSflorian int rv = nghttp2_select_next_protocol((unsigned char **)out, outlen, in, 1125f4f0f0ceSflorian inlen); 1126f4f0f0ceSflorian if(rv == -1) { 1127f4f0f0ceSflorian return SSL_TLSEXT_ERR_NOACK; 1128f4f0f0ceSflorian } 1129f4f0f0ceSflorian /* either http/1.1 or h2 selected */ 1130f4f0f0ceSflorian return SSL_TLSEXT_ERR_OK; 1131f4f0f0ceSflorian } 1132f4f0f0ceSflorian #endif 1133f4f0f0ceSflorian 1134ae8c6e27Sflorian int 1135ae8c6e27Sflorian listen_sslctx_setup(void* ctxt) 1136ae8c6e27Sflorian { 1137ae8c6e27Sflorian #ifdef HAVE_SSL 1138ae8c6e27Sflorian SSL_CTX* ctx = (SSL_CTX*)ctxt; 1139ae8c6e27Sflorian /* no SSLv2, SSLv3 because has defects */ 1140d32eb43cSflorian #if SSL_OP_NO_SSLv2 != 0 1141ae8c6e27Sflorian if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2) 1142ae8c6e27Sflorian != SSL_OP_NO_SSLv2){ 1143ae8c6e27Sflorian log_crypto_err("could not set SSL_OP_NO_SSLv2"); 1144ae8c6e27Sflorian return 0; 1145ae8c6e27Sflorian } 1146d32eb43cSflorian #endif 1147ae8c6e27Sflorian if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3) 1148ae8c6e27Sflorian != SSL_OP_NO_SSLv3){ 1149ae8c6e27Sflorian log_crypto_err("could not set SSL_OP_NO_SSLv3"); 1150ae8c6e27Sflorian return 0; 1151ae8c6e27Sflorian } 1152ae8c6e27Sflorian #if defined(SSL_OP_NO_TLSv1) && defined(SSL_OP_NO_TLSv1_1) 1153ae8c6e27Sflorian /* if we have tls 1.1 disable 1.0 */ 1154ae8c6e27Sflorian if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1) & SSL_OP_NO_TLSv1) 1155ae8c6e27Sflorian != SSL_OP_NO_TLSv1){ 1156ae8c6e27Sflorian log_crypto_err("could not set SSL_OP_NO_TLSv1"); 1157ae8c6e27Sflorian return 0; 1158ae8c6e27Sflorian } 1159ae8c6e27Sflorian #endif 1160ae8c6e27Sflorian #if defined(SSL_OP_NO_TLSv1_1) && defined(SSL_OP_NO_TLSv1_2) 1161ae8c6e27Sflorian /* if we have tls 1.2 disable 1.1 */ 1162ae8c6e27Sflorian if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_1) & SSL_OP_NO_TLSv1_1) 1163ae8c6e27Sflorian != SSL_OP_NO_TLSv1_1){ 1164ae8c6e27Sflorian log_crypto_err("could not set SSL_OP_NO_TLSv1_1"); 1165ae8c6e27Sflorian return 0; 1166ae8c6e27Sflorian } 1167ae8c6e27Sflorian #endif 1168da8c8390Sflorian #if defined(SSL_OP_NO_RENEGOTIATION) 1169da8c8390Sflorian /* disable client renegotiation */ 1170da8c8390Sflorian if((SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION) & 1171da8c8390Sflorian SSL_OP_NO_RENEGOTIATION) != SSL_OP_NO_RENEGOTIATION) { 1172da8c8390Sflorian log_crypto_err("could not set SSL_OP_NO_RENEGOTIATION"); 1173da8c8390Sflorian return 0; 1174da8c8390Sflorian } 1175da8c8390Sflorian #endif 1176ae8c6e27Sflorian #if defined(SHA256_DIGEST_LENGTH) && defined(USE_ECDSA) 1177a1a7ba80Sflorian /* if we detect system-wide crypto policies, use those */ 1178a1a7ba80Sflorian if (access( "/etc/crypto-policies/config", F_OK ) != 0 ) { 1179ae8c6e27Sflorian /* if we have sha256, set the cipher list to have no known vulns */ 1180ae8c6e27Sflorian 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")) 1181ae8c6e27Sflorian log_crypto_err("could not set cipher list with SSL_CTX_set_cipher_list"); 1182a1a7ba80Sflorian } 1183ae8c6e27Sflorian #endif 1184d500c338Sflorian #if defined(SSL_OP_IGNORE_UNEXPECTED_EOF) 1185d500c338Sflorian /* ignore errors when peers do not send the mandatory close_notify 1186d500c338Sflorian * alert on shutdown. 1187d500c338Sflorian * Relevant for openssl >= 3 */ 1188d500c338Sflorian if((SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF) & 1189d500c338Sflorian SSL_OP_IGNORE_UNEXPECTED_EOF) != SSL_OP_IGNORE_UNEXPECTED_EOF) { 1190d500c338Sflorian log_crypto_err("could not set SSL_OP_IGNORE_UNEXPECTED_EOF"); 1191d500c338Sflorian return 0; 1192d500c338Sflorian } 1193d500c338Sflorian #endif 1194ae8c6e27Sflorian 1195ae8c6e27Sflorian if((SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE) & 1196ae8c6e27Sflorian SSL_OP_CIPHER_SERVER_PREFERENCE) != 1197ae8c6e27Sflorian SSL_OP_CIPHER_SERVER_PREFERENCE) { 1198ae8c6e27Sflorian log_crypto_err("could not set SSL_OP_CIPHER_SERVER_PREFERENCE"); 1199ae8c6e27Sflorian return 0; 1200ae8c6e27Sflorian } 1201ae8c6e27Sflorian 1202ae8c6e27Sflorian #ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL 1203ae8c6e27Sflorian SSL_CTX_set_security_level(ctx, 0); 1204ae8c6e27Sflorian #endif 1205f4f0f0ceSflorian #if defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB) && defined(HAVE_NGHTTP2) 1206f4f0f0ceSflorian SSL_CTX_set_alpn_select_cb(ctx, alpn_select_cb, NULL); 1207f4f0f0ceSflorian #endif 1208ae8c6e27Sflorian #else 1209ae8c6e27Sflorian (void)ctxt; 1210ae8c6e27Sflorian #endif /* HAVE_SSL */ 1211ae8c6e27Sflorian return 1; 1212ae8c6e27Sflorian } 1213ae8c6e27Sflorian 1214ae8c6e27Sflorian void 1215ae8c6e27Sflorian listen_sslctx_setup_2(void* ctxt) 1216ae8c6e27Sflorian { 1217ae8c6e27Sflorian #ifdef HAVE_SSL 1218ae8c6e27Sflorian SSL_CTX* ctx = (SSL_CTX*)ctxt; 1219ae8c6e27Sflorian (void)ctx; 1220ae8c6e27Sflorian #if HAVE_DECL_SSL_CTX_SET_ECDH_AUTO 1221ae8c6e27Sflorian if(!SSL_CTX_set_ecdh_auto(ctx,1)) { 1222ae8c6e27Sflorian log_crypto_err("Error in SSL_CTX_ecdh_auto, not enabling ECDHE"); 1223ae8c6e27Sflorian } 1224*7037e34cSflorian #elif defined(USE_ECDSA) && defined(HAVE_SSL_CTX_SET_TMP_ECDH) 1225ae8c6e27Sflorian if(1) { 1226ae8c6e27Sflorian EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1); 1227ae8c6e27Sflorian if (!ecdh) { 1228ae8c6e27Sflorian log_crypto_err("could not find p256, not enabling ECDHE"); 1229ae8c6e27Sflorian } else { 1230ae8c6e27Sflorian if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh)) { 1231ae8c6e27Sflorian log_crypto_err("Error in SSL_CTX_set_tmp_ecdh, not enabling ECDHE"); 1232ae8c6e27Sflorian } 1233ae8c6e27Sflorian EC_KEY_free (ecdh); 1234ae8c6e27Sflorian } 1235ae8c6e27Sflorian } 1236ae8c6e27Sflorian #endif 1237ae8c6e27Sflorian #else 1238ae8c6e27Sflorian (void)ctxt; 1239ae8c6e27Sflorian #endif /* HAVE_SSL */ 1240ae8c6e27Sflorian } 1241ae8c6e27Sflorian 1242ae8c6e27Sflorian void* listen_sslctx_create(char* key, char* pem, char* verifypem) 1243ae8c6e27Sflorian { 1244ae8c6e27Sflorian #ifdef HAVE_SSL 1245ae8c6e27Sflorian SSL_CTX* ctx = SSL_CTX_new(SSLv23_server_method()); 1246ae8c6e27Sflorian if(!ctx) { 1247ae8c6e27Sflorian log_crypto_err("could not SSL_CTX_new"); 1248ae8c6e27Sflorian return NULL; 1249ae8c6e27Sflorian } 12509b465e50Sflorian if(!key || key[0] == 0) { 12519b465e50Sflorian log_err("error: no tls-service-key file specified"); 12529b465e50Sflorian SSL_CTX_free(ctx); 12539b465e50Sflorian return NULL; 12549b465e50Sflorian } 12559b465e50Sflorian if(!pem || pem[0] == 0) { 12569b465e50Sflorian log_err("error: no tls-service-pem file specified"); 12579b465e50Sflorian SSL_CTX_free(ctx); 12589b465e50Sflorian return NULL; 12599b465e50Sflorian } 1260ae8c6e27Sflorian if(!listen_sslctx_setup(ctx)) { 1261ae8c6e27Sflorian SSL_CTX_free(ctx); 1262ae8c6e27Sflorian return NULL; 1263ae8c6e27Sflorian } 1264ae8c6e27Sflorian if(!SSL_CTX_use_certificate_chain_file(ctx, pem)) { 1265ae8c6e27Sflorian log_err("error for cert file: %s", pem); 1266ae8c6e27Sflorian log_crypto_err("error in SSL_CTX use_certificate_chain_file"); 1267ae8c6e27Sflorian SSL_CTX_free(ctx); 1268ae8c6e27Sflorian return NULL; 1269ae8c6e27Sflorian } 1270ae8c6e27Sflorian if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) { 1271ae8c6e27Sflorian log_err("error for private key file: %s", key); 1272ae8c6e27Sflorian log_crypto_err("Error in SSL_CTX use_PrivateKey_file"); 1273ae8c6e27Sflorian SSL_CTX_free(ctx); 1274ae8c6e27Sflorian return NULL; 1275ae8c6e27Sflorian } 1276ae8c6e27Sflorian if(!SSL_CTX_check_private_key(ctx)) { 1277ae8c6e27Sflorian log_err("error for key file: %s", key); 1278ae8c6e27Sflorian log_crypto_err("Error in SSL_CTX check_private_key"); 1279ae8c6e27Sflorian SSL_CTX_free(ctx); 1280ae8c6e27Sflorian return NULL; 1281ae8c6e27Sflorian } 1282ae8c6e27Sflorian listen_sslctx_setup_2(ctx); 1283ae8c6e27Sflorian if(verifypem && verifypem[0]) { 1284ae8c6e27Sflorian if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) { 1285ae8c6e27Sflorian log_crypto_err("Error in SSL_CTX verify locations"); 1286ae8c6e27Sflorian SSL_CTX_free(ctx); 1287ae8c6e27Sflorian return NULL; 1288ae8c6e27Sflorian } 1289ae8c6e27Sflorian SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file( 1290ae8c6e27Sflorian verifypem)); 1291e47fef9eSflorian SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); 1292ae8c6e27Sflorian } 1293ae8c6e27Sflorian return ctx; 1294ae8c6e27Sflorian #else 1295ae8c6e27Sflorian (void)key; (void)pem; (void)verifypem; 1296ae8c6e27Sflorian return NULL; 1297ae8c6e27Sflorian #endif 1298ae8c6e27Sflorian } 1299ae8c6e27Sflorian 1300ae8c6e27Sflorian #ifdef USE_WINSOCK 1301ae8c6e27Sflorian /* For windows, the CA trust store is not read by openssl. 1302ae8c6e27Sflorian Add code to open the trust store using wincrypt API and add 1303ae8c6e27Sflorian the root certs into openssl trust store */ 1304ae8c6e27Sflorian static int 1305ae8c6e27Sflorian add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx) 1306ae8c6e27Sflorian { 1307ae8c6e27Sflorian HCERTSTORE hSystemStore; 1308ae8c6e27Sflorian PCCERT_CONTEXT pTargetCert = NULL; 1309ae8c6e27Sflorian X509_STORE* store; 1310ae8c6e27Sflorian 1311ae8c6e27Sflorian verbose(VERB_ALGO, "Adding Windows certificates from system root store to CA store"); 1312ae8c6e27Sflorian 1313ae8c6e27Sflorian /* load just once per context lifetime for this version 1314ae8c6e27Sflorian TODO: dynamically update CA trust changes as they are available */ 1315ae8c6e27Sflorian if (!tls_ctx) 1316ae8c6e27Sflorian return 0; 1317ae8c6e27Sflorian 1318ae8c6e27Sflorian /* Call wincrypt's CertOpenStore to open the CA root store. */ 1319ae8c6e27Sflorian 1320ae8c6e27Sflorian if ((hSystemStore = CertOpenStore( 1321ae8c6e27Sflorian CERT_STORE_PROV_SYSTEM, 1322ae8c6e27Sflorian 0, 1323ae8c6e27Sflorian 0, 1324ae8c6e27Sflorian /* NOTE: mingw does not have this const: replace with 1 << 16 from code 1325ae8c6e27Sflorian CERT_SYSTEM_STORE_CURRENT_USER, */ 1326ae8c6e27Sflorian 1 << 16, 1327ae8c6e27Sflorian L"root")) == 0) 1328ae8c6e27Sflorian { 1329ae8c6e27Sflorian return 0; 1330ae8c6e27Sflorian } 1331ae8c6e27Sflorian 1332ae8c6e27Sflorian store = SSL_CTX_get_cert_store(tls_ctx); 1333ae8c6e27Sflorian if (!store) 1334ae8c6e27Sflorian return 0; 1335ae8c6e27Sflorian 1336ae8c6e27Sflorian /* failure if the CA store is empty or the call fails */ 1337ae8c6e27Sflorian if ((pTargetCert = CertEnumCertificatesInStore( 1338ae8c6e27Sflorian hSystemStore, pTargetCert)) == 0) { 1339ae8c6e27Sflorian verbose(VERB_ALGO, "CA certificate store for Windows is empty."); 1340ae8c6e27Sflorian return 0; 1341ae8c6e27Sflorian } 1342ae8c6e27Sflorian /* iterate over the windows cert store and add to openssl store */ 1343ae8c6e27Sflorian do 1344ae8c6e27Sflorian { 1345ae8c6e27Sflorian X509 *cert1 = d2i_X509(NULL, 1346ae8c6e27Sflorian (const unsigned char **)&pTargetCert->pbCertEncoded, 1347ae8c6e27Sflorian pTargetCert->cbCertEncoded); 1348ae8c6e27Sflorian if (!cert1) { 13496d08cb1bSflorian unsigned long error = ERR_get_error(); 1350ae8c6e27Sflorian /* return error if a cert fails */ 1351ae8c6e27Sflorian verbose(VERB_ALGO, "%s %d:%s", 1352ae8c6e27Sflorian "Unable to parse certificate in memory", 13536d08cb1bSflorian (int)error, ERR_error_string(error, NULL)); 1354ae8c6e27Sflorian return 0; 1355ae8c6e27Sflorian } 1356ae8c6e27Sflorian else { 1357ae8c6e27Sflorian /* return error if a cert add to store fails */ 1358ae8c6e27Sflorian if (X509_STORE_add_cert(store, cert1) == 0) { 1359ae8c6e27Sflorian unsigned long error = ERR_peek_last_error(); 1360ae8c6e27Sflorian 1361ae8c6e27Sflorian /* Ignore error X509_R_CERT_ALREADY_IN_HASH_TABLE which means the 1362ae8c6e27Sflorian * certificate is already in the store. */ 1363ae8c6e27Sflorian if(ERR_GET_LIB(error) != ERR_LIB_X509 || 1364ae8c6e27Sflorian ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) { 13656d08cb1bSflorian error = ERR_get_error(); 1366ae8c6e27Sflorian verbose(VERB_ALGO, "%s %d:%s\n", 13676d08cb1bSflorian "Error adding certificate", (int)error, 13686d08cb1bSflorian ERR_error_string(error, NULL)); 1369ae8c6e27Sflorian X509_free(cert1); 1370ae8c6e27Sflorian return 0; 1371ae8c6e27Sflorian } 1372ae8c6e27Sflorian } 1373ae8c6e27Sflorian X509_free(cert1); 1374ae8c6e27Sflorian } 1375ae8c6e27Sflorian } while ((pTargetCert = CertEnumCertificatesInStore( 1376ae8c6e27Sflorian hSystemStore, pTargetCert)) != 0); 1377ae8c6e27Sflorian 1378ae8c6e27Sflorian /* Clean up memory and quit. */ 1379ae8c6e27Sflorian if (pTargetCert) 1380ae8c6e27Sflorian CertFreeCertificateContext(pTargetCert); 1381ae8c6e27Sflorian if (hSystemStore) 1382ae8c6e27Sflorian { 1383ae8c6e27Sflorian if (!CertCloseStore( 1384ae8c6e27Sflorian hSystemStore, 0)) 1385ae8c6e27Sflorian return 0; 1386ae8c6e27Sflorian } 1387ae8c6e27Sflorian verbose(VERB_ALGO, "Completed adding Windows certificates to CA store successfully"); 1388ae8c6e27Sflorian return 1; 1389ae8c6e27Sflorian } 1390ae8c6e27Sflorian #endif /* USE_WINSOCK */ 1391ae8c6e27Sflorian 1392ae8c6e27Sflorian void* connect_sslctx_create(char* key, char* pem, char* verifypem, int wincert) 1393ae8c6e27Sflorian { 1394ae8c6e27Sflorian #ifdef HAVE_SSL 1395ae8c6e27Sflorian SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method()); 1396ae8c6e27Sflorian if(!ctx) { 1397ae8c6e27Sflorian log_crypto_err("could not allocate SSL_CTX pointer"); 1398ae8c6e27Sflorian return NULL; 1399ae8c6e27Sflorian } 1400d32eb43cSflorian #if SSL_OP_NO_SSLv2 != 0 1401ae8c6e27Sflorian if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2) 1402ae8c6e27Sflorian != SSL_OP_NO_SSLv2) { 1403ae8c6e27Sflorian log_crypto_err("could not set SSL_OP_NO_SSLv2"); 1404ae8c6e27Sflorian SSL_CTX_free(ctx); 1405ae8c6e27Sflorian return NULL; 1406ae8c6e27Sflorian } 1407d32eb43cSflorian #endif 1408ae8c6e27Sflorian if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3) 1409ae8c6e27Sflorian != SSL_OP_NO_SSLv3) { 1410ae8c6e27Sflorian log_crypto_err("could not set SSL_OP_NO_SSLv3"); 1411ae8c6e27Sflorian SSL_CTX_free(ctx); 1412ae8c6e27Sflorian return NULL; 1413ae8c6e27Sflorian } 1414da8c8390Sflorian #if defined(SSL_OP_NO_RENEGOTIATION) 1415da8c8390Sflorian /* disable client renegotiation */ 1416da8c8390Sflorian if((SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION) & 1417da8c8390Sflorian SSL_OP_NO_RENEGOTIATION) != SSL_OP_NO_RENEGOTIATION) { 1418da8c8390Sflorian log_crypto_err("could not set SSL_OP_NO_RENEGOTIATION"); 1419a1a7ba80Sflorian SSL_CTX_free(ctx); 1420da8c8390Sflorian return 0; 1421da8c8390Sflorian } 1422da8c8390Sflorian #endif 1423d500c338Sflorian #if defined(SSL_OP_IGNORE_UNEXPECTED_EOF) 1424d500c338Sflorian /* ignore errors when peers do not send the mandatory close_notify 1425d500c338Sflorian * alert on shutdown. 1426d500c338Sflorian * Relevant for openssl >= 3 */ 1427d500c338Sflorian if((SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF) & 1428d500c338Sflorian SSL_OP_IGNORE_UNEXPECTED_EOF) != SSL_OP_IGNORE_UNEXPECTED_EOF) { 1429d500c338Sflorian log_crypto_err("could not set SSL_OP_IGNORE_UNEXPECTED_EOF"); 1430d500c338Sflorian SSL_CTX_free(ctx); 1431d500c338Sflorian return 0; 1432d500c338Sflorian } 1433d500c338Sflorian #endif 1434ae8c6e27Sflorian if(key && key[0]) { 1435ae8c6e27Sflorian if(!SSL_CTX_use_certificate_chain_file(ctx, pem)) { 1436ae8c6e27Sflorian log_err("error in client certificate %s", pem); 1437ae8c6e27Sflorian log_crypto_err("error in certificate file"); 1438ae8c6e27Sflorian SSL_CTX_free(ctx); 1439ae8c6e27Sflorian return NULL; 1440ae8c6e27Sflorian } 1441ae8c6e27Sflorian if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) { 1442ae8c6e27Sflorian log_err("error in client private key %s", key); 1443ae8c6e27Sflorian log_crypto_err("error in key file"); 1444ae8c6e27Sflorian SSL_CTX_free(ctx); 1445ae8c6e27Sflorian return NULL; 1446ae8c6e27Sflorian } 1447ae8c6e27Sflorian if(!SSL_CTX_check_private_key(ctx)) { 1448ae8c6e27Sflorian log_err("error in client key %s", key); 1449ae8c6e27Sflorian log_crypto_err("error in SSL_CTX_check_private_key"); 1450ae8c6e27Sflorian SSL_CTX_free(ctx); 1451ae8c6e27Sflorian return NULL; 1452ae8c6e27Sflorian } 1453ae8c6e27Sflorian } 1454ae8c6e27Sflorian if((verifypem && verifypem[0]) || wincert) { 1455ae8c6e27Sflorian if(verifypem && verifypem[0]) { 1456ae8c6e27Sflorian if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) { 1457ae8c6e27Sflorian log_crypto_err("error in SSL_CTX verify"); 1458ae8c6e27Sflorian SSL_CTX_free(ctx); 1459ae8c6e27Sflorian return NULL; 1460ae8c6e27Sflorian } 1461ae8c6e27Sflorian } 1462ae8c6e27Sflorian #ifdef USE_WINSOCK 1463ae8c6e27Sflorian if(wincert) { 1464ae8c6e27Sflorian if(!add_WIN_cacerts_to_openssl_store(ctx)) { 1465ae8c6e27Sflorian log_crypto_err("error in add_WIN_cacerts_to_openssl_store"); 1466ae8c6e27Sflorian SSL_CTX_free(ctx); 1467ae8c6e27Sflorian return NULL; 1468ae8c6e27Sflorian } 1469ae8c6e27Sflorian } 1470ae8c6e27Sflorian #else 14717a05b9dfSflorian if(wincert) { 14727a05b9dfSflorian if(!SSL_CTX_set_default_verify_paths(ctx)) { 14737a05b9dfSflorian log_crypto_err("error in default_verify_paths"); 14747a05b9dfSflorian SSL_CTX_free(ctx); 14757a05b9dfSflorian return NULL; 14767a05b9dfSflorian } 14777a05b9dfSflorian } 1478ae8c6e27Sflorian #endif 1479ae8c6e27Sflorian SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); 1480ae8c6e27Sflorian } 1481ae8c6e27Sflorian return ctx; 1482ae8c6e27Sflorian #else 1483ae8c6e27Sflorian (void)key; (void)pem; (void)verifypem; (void)wincert; 1484ae8c6e27Sflorian return NULL; 1485ae8c6e27Sflorian #endif 1486ae8c6e27Sflorian } 1487ae8c6e27Sflorian 1488ae8c6e27Sflorian void* incoming_ssl_fd(void* sslctx, int fd) 1489ae8c6e27Sflorian { 1490ae8c6e27Sflorian #ifdef HAVE_SSL 1491ae8c6e27Sflorian SSL* ssl = SSL_new((SSL_CTX*)sslctx); 1492ae8c6e27Sflorian if(!ssl) { 1493ae8c6e27Sflorian log_crypto_err("could not SSL_new"); 1494ae8c6e27Sflorian return NULL; 1495ae8c6e27Sflorian } 1496ae8c6e27Sflorian SSL_set_accept_state(ssl); 149757403691Sflorian (void)SSL_set_mode(ssl, (long)SSL_MODE_AUTO_RETRY); 1498ae8c6e27Sflorian if(!SSL_set_fd(ssl, fd)) { 1499ae8c6e27Sflorian log_crypto_err("could not SSL_set_fd"); 1500ae8c6e27Sflorian SSL_free(ssl); 1501ae8c6e27Sflorian return NULL; 1502ae8c6e27Sflorian } 1503ae8c6e27Sflorian return ssl; 1504ae8c6e27Sflorian #else 1505ae8c6e27Sflorian (void)sslctx; (void)fd; 1506ae8c6e27Sflorian return NULL; 1507ae8c6e27Sflorian #endif 1508ae8c6e27Sflorian } 1509ae8c6e27Sflorian 1510ae8c6e27Sflorian void* outgoing_ssl_fd(void* sslctx, int fd) 1511ae8c6e27Sflorian { 1512ae8c6e27Sflorian #ifdef HAVE_SSL 1513ae8c6e27Sflorian SSL* ssl = SSL_new((SSL_CTX*)sslctx); 1514ae8c6e27Sflorian if(!ssl) { 1515ae8c6e27Sflorian log_crypto_err("could not SSL_new"); 1516ae8c6e27Sflorian return NULL; 1517ae8c6e27Sflorian } 1518ae8c6e27Sflorian SSL_set_connect_state(ssl); 151957403691Sflorian (void)SSL_set_mode(ssl, (long)SSL_MODE_AUTO_RETRY); 1520ae8c6e27Sflorian if(!SSL_set_fd(ssl, fd)) { 1521ae8c6e27Sflorian log_crypto_err("could not SSL_set_fd"); 1522ae8c6e27Sflorian SSL_free(ssl); 1523ae8c6e27Sflorian return NULL; 1524ae8c6e27Sflorian } 1525ae8c6e27Sflorian return ssl; 1526ae8c6e27Sflorian #else 1527ae8c6e27Sflorian (void)sslctx; (void)fd; 1528ae8c6e27Sflorian return NULL; 1529ae8c6e27Sflorian #endif 1530ae8c6e27Sflorian } 1531ae8c6e27Sflorian 1532e47fef9eSflorian int check_auth_name_for_ssl(char* auth_name) 1533e47fef9eSflorian { 1534e47fef9eSflorian if(!auth_name) return 1; 1535e47fef9eSflorian #if defined(HAVE_SSL) && !defined(HAVE_SSL_SET1_HOST) && !defined(HAVE_X509_VERIFY_PARAM_SET1_HOST) 1536e47fef9eSflorian log_err("the query has an auth_name %s, but libssl has no call to " 1537e47fef9eSflorian "perform TLS authentication. Remove that name from config " 1538e47fef9eSflorian "or upgrade the ssl crypto library.", auth_name); 1539e47fef9eSflorian return 0; 1540e47fef9eSflorian #else 1541e47fef9eSflorian return 1; 1542e47fef9eSflorian #endif 1543e47fef9eSflorian } 1544e47fef9eSflorian 1545e47fef9eSflorian /** set the authname on an SSL structure, SSL* ssl */ 1546e47fef9eSflorian int set_auth_name_on_ssl(void* ssl, char* auth_name, int use_sni) 1547e47fef9eSflorian { 1548e47fef9eSflorian if(!auth_name) return 1; 1549e47fef9eSflorian #ifdef HAVE_SSL 1550e47fef9eSflorian if(use_sni) { 1551e47fef9eSflorian (void)SSL_set_tlsext_host_name(ssl, auth_name); 1552e47fef9eSflorian } 1553e47fef9eSflorian #else 1554e47fef9eSflorian (void)ssl; 1555e47fef9eSflorian (void)use_sni; 1556e47fef9eSflorian #endif 1557e47fef9eSflorian #ifdef HAVE_SSL_SET1_HOST 1558e47fef9eSflorian SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL); 1559e47fef9eSflorian /* setting the hostname makes openssl verify the 1560e47fef9eSflorian * host name in the x509 certificate in the 1561e47fef9eSflorian * SSL connection*/ 1562e47fef9eSflorian if(!SSL_set1_host(ssl, auth_name)) { 1563e47fef9eSflorian log_err("SSL_set1_host failed"); 1564e47fef9eSflorian return 0; 1565e47fef9eSflorian } 1566e47fef9eSflorian #elif defined(HAVE_X509_VERIFY_PARAM_SET1_HOST) 1567e47fef9eSflorian /* openssl 1.0.2 has this function that can be used for 1568e47fef9eSflorian * set1_host like verification */ 1569e47fef9eSflorian if(auth_name) { 1570e47fef9eSflorian X509_VERIFY_PARAM* param = SSL_get0_param(ssl); 1571e47fef9eSflorian # ifdef X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS 1572e47fef9eSflorian X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); 1573e47fef9eSflorian # endif 1574e47fef9eSflorian if(!X509_VERIFY_PARAM_set1_host(param, auth_name, strlen(auth_name))) { 1575e47fef9eSflorian log_err("X509_VERIFY_PARAM_set1_host failed"); 1576e47fef9eSflorian return 0; 1577e47fef9eSflorian } 1578e47fef9eSflorian SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL); 1579e47fef9eSflorian } 1580e47fef9eSflorian #else 1581e47fef9eSflorian verbose(VERB_ALGO, "the query has an auth_name, but libssl has no call to perform TLS authentication"); 1582e47fef9eSflorian #endif /* HAVE_SSL_SET1_HOST */ 1583e47fef9eSflorian return 1; 1584e47fef9eSflorian } 1585e47fef9eSflorian 1586ae8c6e27Sflorian #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L 1587ae8c6e27Sflorian /** global lock list for openssl locks */ 1588ae8c6e27Sflorian static lock_basic_type *ub_openssl_locks = NULL; 1589ae8c6e27Sflorian 1590ae8c6e27Sflorian /** callback that gets thread id for openssl */ 1591988ebc2dSflorian #ifdef HAVE_CRYPTO_THREADID_SET_CALLBACK 1592988ebc2dSflorian static void 1593988ebc2dSflorian ub_crypto_id_cb(CRYPTO_THREADID *id) 1594988ebc2dSflorian { 1595988ebc2dSflorian CRYPTO_THREADID_set_numeric(id, (unsigned long)log_thread_get()); 1596988ebc2dSflorian } 1597988ebc2dSflorian #else 1598ae8c6e27Sflorian static unsigned long 1599ae8c6e27Sflorian ub_crypto_id_cb(void) 1600ae8c6e27Sflorian { 1601ae8c6e27Sflorian return (unsigned long)log_thread_get(); 1602ae8c6e27Sflorian } 1603988ebc2dSflorian #endif 1604ae8c6e27Sflorian 1605ae8c6e27Sflorian static void 1606ae8c6e27Sflorian ub_crypto_lock_cb(int mode, int type, const char *ATTR_UNUSED(file), 1607ae8c6e27Sflorian int ATTR_UNUSED(line)) 1608ae8c6e27Sflorian { 1609ae8c6e27Sflorian if((mode&CRYPTO_LOCK)) { 1610ae8c6e27Sflorian lock_basic_lock(&ub_openssl_locks[type]); 1611ae8c6e27Sflorian } else { 1612ae8c6e27Sflorian lock_basic_unlock(&ub_openssl_locks[type]); 1613ae8c6e27Sflorian } 1614ae8c6e27Sflorian } 1615ae8c6e27Sflorian #endif /* OPENSSL_THREADS */ 1616ae8c6e27Sflorian 1617ae8c6e27Sflorian int ub_openssl_lock_init(void) 1618ae8c6e27Sflorian { 1619ae8c6e27Sflorian #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L 1620ae8c6e27Sflorian int i; 1621ae8c6e27Sflorian ub_openssl_locks = (lock_basic_type*)reallocarray( 1622ae8c6e27Sflorian NULL, (size_t)CRYPTO_num_locks(), sizeof(lock_basic_type)); 1623ae8c6e27Sflorian if(!ub_openssl_locks) 1624ae8c6e27Sflorian return 0; 1625ae8c6e27Sflorian for(i=0; i<CRYPTO_num_locks(); i++) { 1626ae8c6e27Sflorian lock_basic_init(&ub_openssl_locks[i]); 1627ae8c6e27Sflorian } 1628988ebc2dSflorian # ifdef HAVE_CRYPTO_THREADID_SET_CALLBACK 1629988ebc2dSflorian CRYPTO_THREADID_set_callback(&ub_crypto_id_cb); 1630988ebc2dSflorian # else 1631ae8c6e27Sflorian CRYPTO_set_id_callback(&ub_crypto_id_cb); 1632988ebc2dSflorian # endif 1633ae8c6e27Sflorian CRYPTO_set_locking_callback(&ub_crypto_lock_cb); 1634ae8c6e27Sflorian #endif /* OPENSSL_THREADS */ 1635ae8c6e27Sflorian return 1; 1636ae8c6e27Sflorian } 1637ae8c6e27Sflorian 1638ae8c6e27Sflorian void ub_openssl_lock_delete(void) 1639ae8c6e27Sflorian { 1640ae8c6e27Sflorian #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L 1641ae8c6e27Sflorian int i; 1642ae8c6e27Sflorian if(!ub_openssl_locks) 1643ae8c6e27Sflorian return; 1644988ebc2dSflorian # ifdef HAVE_CRYPTO_THREADID_SET_CALLBACK 1645988ebc2dSflorian CRYPTO_THREADID_set_callback(NULL); 1646988ebc2dSflorian # else 1647ae8c6e27Sflorian CRYPTO_set_id_callback(NULL); 1648988ebc2dSflorian # endif 1649ae8c6e27Sflorian CRYPTO_set_locking_callback(NULL); 1650ae8c6e27Sflorian for(i=0; i<CRYPTO_num_locks(); i++) { 1651ae8c6e27Sflorian lock_basic_destroy(&ub_openssl_locks[i]); 1652ae8c6e27Sflorian } 1653ae8c6e27Sflorian free(ub_openssl_locks); 1654ae8c6e27Sflorian #endif /* OPENSSL_THREADS */ 1655ae8c6e27Sflorian } 1656ae8c6e27Sflorian 1657e97c6e54Ssthen int listen_sslctx_setup_ticket_keys(void* sslctx, struct config_strlist* tls_session_ticket_keys) { 1658e97c6e54Ssthen #ifdef HAVE_SSL 1659e97c6e54Ssthen size_t s = 1; 1660e97c6e54Ssthen struct config_strlist* p; 1661e97c6e54Ssthen struct tls_session_ticket_key *keys; 1662e97c6e54Ssthen for(p = tls_session_ticket_keys; p; p = p->next) { 1663e97c6e54Ssthen s++; 1664e97c6e54Ssthen } 1665e97c6e54Ssthen keys = calloc(s, sizeof(struct tls_session_ticket_key)); 1666d32eb43cSflorian if(!keys) 1667d32eb43cSflorian return 0; 1668e97c6e54Ssthen memset(keys, 0, s*sizeof(*keys)); 1669e97c6e54Ssthen ticket_keys = keys; 1670e97c6e54Ssthen 1671e97c6e54Ssthen for(p = tls_session_ticket_keys; p; p = p->next) { 1672e97c6e54Ssthen size_t n; 1673d32eb43cSflorian unsigned char *data; 1674d32eb43cSflorian FILE *f; 1675d32eb43cSflorian 1676d32eb43cSflorian data = (unsigned char *)malloc(80); 1677d32eb43cSflorian if(!data) 1678d32eb43cSflorian return 0; 1679d32eb43cSflorian 1680e47fef9eSflorian f = fopen(p->str, "rb"); 1681e97c6e54Ssthen if(!f) { 1682e97c6e54Ssthen log_err("could not read tls-session-ticket-key %s: %s", p->str, strerror(errno)); 1683e97c6e54Ssthen free(data); 1684e97c6e54Ssthen return 0; 1685e97c6e54Ssthen } 1686e97c6e54Ssthen n = fread(data, 1, 80, f); 1687e97c6e54Ssthen fclose(f); 1688e97c6e54Ssthen 1689e97c6e54Ssthen if(n != 80) { 1690e97c6e54Ssthen log_err("tls-session-ticket-key %s is %d bytes, must be 80 bytes", p->str, (int)n); 1691e97c6e54Ssthen free(data); 1692e97c6e54Ssthen return 0; 1693e97c6e54Ssthen } 1694e97c6e54Ssthen verbose(VERB_OPS, "read tls-session-ticket-key: %s", p->str); 1695e97c6e54Ssthen 1696e97c6e54Ssthen keys->key_name = data; 1697e97c6e54Ssthen keys->aes_key = data + 16; 1698e97c6e54Ssthen keys->hmac_key = data + 48; 1699e97c6e54Ssthen keys++; 1700e97c6e54Ssthen } 1701e97c6e54Ssthen /* terminate array with NULL key name entry */ 1702e97c6e54Ssthen keys->key_name = NULL; 1703e47fef9eSflorian # ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB 1704e47fef9eSflorian if(SSL_CTX_set_tlsext_ticket_key_evp_cb(sslctx, tls_session_ticket_key_cb) == 0) { 1705e47fef9eSflorian log_err("no support for TLS session ticket"); 1706e47fef9eSflorian return 0; 1707e47fef9eSflorian } 1708e47fef9eSflorian # else 1709e97c6e54Ssthen if(SSL_CTX_set_tlsext_ticket_key_cb(sslctx, tls_session_ticket_key_cb) == 0) { 1710e97c6e54Ssthen log_err("no support for TLS session ticket"); 1711e97c6e54Ssthen return 0; 1712e97c6e54Ssthen } 1713e47fef9eSflorian # endif 1714e97c6e54Ssthen return 1; 1715e97c6e54Ssthen #else 1716e97c6e54Ssthen (void)sslctx; 1717e97c6e54Ssthen (void)tls_session_ticket_keys; 1718e97c6e54Ssthen return 0; 1719e97c6e54Ssthen #endif 1720e97c6e54Ssthen 1721e97c6e54Ssthen } 1722e97c6e54Ssthen 1723e47fef9eSflorian #ifdef HAVE_SSL 1724e47fef9eSflorian int tls_session_ticket_key_cb(SSL *ATTR_UNUSED(sslctx), unsigned char* key_name, 1725e47fef9eSflorian unsigned char* iv, EVP_CIPHER_CTX *evp_sctx, 1726e47fef9eSflorian #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB 1727e47fef9eSflorian EVP_MAC_CTX *hmac_ctx, 1728e47fef9eSflorian #else 1729e47fef9eSflorian HMAC_CTX* hmac_ctx, 1730e47fef9eSflorian #endif 1731e47fef9eSflorian int enc) 1732e97c6e54Ssthen { 1733e97c6e54Ssthen #ifdef HAVE_SSL 1734e47fef9eSflorian # ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB 1735e47fef9eSflorian OSSL_PARAM params[3]; 1736e47fef9eSflorian # else 1737e97c6e54Ssthen const EVP_MD *digest; 1738e47fef9eSflorian # endif 1739e97c6e54Ssthen const EVP_CIPHER *cipher; 1740e97c6e54Ssthen int evp_cipher_length; 1741e47fef9eSflorian # ifndef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB 1742e97c6e54Ssthen digest = EVP_sha256(); 1743e47fef9eSflorian # endif 1744e97c6e54Ssthen cipher = EVP_aes_256_cbc(); 1745e97c6e54Ssthen evp_cipher_length = EVP_CIPHER_iv_length(cipher); 1746e97c6e54Ssthen if( enc == 1 ) { 1747e97c6e54Ssthen /* encrypt */ 1748e97c6e54Ssthen verbose(VERB_CLIENT, "start session encrypt"); 1749e97c6e54Ssthen memcpy(key_name, ticket_keys->key_name, 16); 1750e97c6e54Ssthen if (RAND_bytes(iv, evp_cipher_length) != 1) { 1751e97c6e54Ssthen verbose(VERB_CLIENT, "RAND_bytes failed"); 1752e97c6e54Ssthen return -1; 1753e97c6e54Ssthen } 1754e97c6e54Ssthen if (EVP_EncryptInit_ex(evp_sctx, cipher, NULL, ticket_keys->aes_key, iv) != 1) { 1755e97c6e54Ssthen verbose(VERB_CLIENT, "EVP_EncryptInit_ex failed"); 1756e97c6e54Ssthen return -1; 1757e97c6e54Ssthen } 1758e47fef9eSflorian #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB 1759e47fef9eSflorian params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, 1760e47fef9eSflorian ticket_keys->hmac_key, 32); 1761e47fef9eSflorian params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, 1762e47fef9eSflorian "sha256", 0); 1763e47fef9eSflorian params[2] = OSSL_PARAM_construct_end(); 1764f4f0f0ceSflorian #ifdef HAVE_EVP_MAC_CTX_SET_PARAMS 1765f4f0f0ceSflorian EVP_MAC_CTX_set_params(hmac_ctx, params); 1766f4f0f0ceSflorian #else 1767e47fef9eSflorian EVP_MAC_set_ctx_params(hmac_ctx, params); 1768f4f0f0ceSflorian #endif 1769e47fef9eSflorian #elif !defined(HMAC_INIT_EX_RETURNS_VOID) 1770e97c6e54Ssthen if (HMAC_Init_ex(hmac_ctx, ticket_keys->hmac_key, 32, digest, NULL) != 1) { 1771e97c6e54Ssthen verbose(VERB_CLIENT, "HMAC_Init_ex failed"); 1772e97c6e54Ssthen return -1; 1773e97c6e54Ssthen } 177457403691Sflorian #else 177557403691Sflorian HMAC_Init_ex(hmac_ctx, ticket_keys->hmac_key, 32, digest, NULL); 177657403691Sflorian #endif 1777e97c6e54Ssthen return 1; 1778e97c6e54Ssthen } else if (enc == 0) { 1779e97c6e54Ssthen /* decrypt */ 1780e97c6e54Ssthen struct tls_session_ticket_key *key; 1781e97c6e54Ssthen verbose(VERB_CLIENT, "start session decrypt"); 1782e97c6e54Ssthen for(key = ticket_keys; key->key_name != NULL; key++) { 1783e97c6e54Ssthen if (!memcmp(key_name, key->key_name, 16)) { 1784e97c6e54Ssthen verbose(VERB_CLIENT, "Found session_key"); 1785e97c6e54Ssthen break; 1786e97c6e54Ssthen } 1787e97c6e54Ssthen } 1788e97c6e54Ssthen if(key->key_name == NULL) { 1789e97c6e54Ssthen verbose(VERB_CLIENT, "Not found session_key"); 1790e97c6e54Ssthen return 0; 1791e97c6e54Ssthen } 1792e97c6e54Ssthen 1793e47fef9eSflorian #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB 1794e47fef9eSflorian params[0] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, 1795e47fef9eSflorian key->hmac_key, 32); 1796e47fef9eSflorian params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, 1797e47fef9eSflorian "sha256", 0); 1798e47fef9eSflorian params[2] = OSSL_PARAM_construct_end(); 1799f4f0f0ceSflorian #ifdef HAVE_EVP_MAC_CTX_SET_PARAMS 1800f4f0f0ceSflorian EVP_MAC_CTX_set_params(hmac_ctx, params); 1801f4f0f0ceSflorian #else 1802e47fef9eSflorian EVP_MAC_set_ctx_params(hmac_ctx, params); 1803f4f0f0ceSflorian #endif 1804e47fef9eSflorian #elif !defined(HMAC_INIT_EX_RETURNS_VOID) 1805e97c6e54Ssthen if (HMAC_Init_ex(hmac_ctx, key->hmac_key, 32, digest, NULL) != 1) { 1806e97c6e54Ssthen verbose(VERB_CLIENT, "HMAC_Init_ex failed"); 1807e97c6e54Ssthen return -1; 1808e97c6e54Ssthen } 180957403691Sflorian #else 181057403691Sflorian HMAC_Init_ex(hmac_ctx, key->hmac_key, 32, digest, NULL); 181157403691Sflorian #endif 1812e97c6e54Ssthen if (EVP_DecryptInit_ex(evp_sctx, cipher, NULL, key->aes_key, iv) != 1) { 1813e97c6e54Ssthen log_err("EVP_DecryptInit_ex failed"); 1814e97c6e54Ssthen return -1; 1815e97c6e54Ssthen } 1816e97c6e54Ssthen 1817e97c6e54Ssthen return (key == ticket_keys) ? 1 : 2; 1818e97c6e54Ssthen } 1819e97c6e54Ssthen return -1; 1820e97c6e54Ssthen #else 1821e97c6e54Ssthen (void)key_name; 1822e97c6e54Ssthen (void)iv; 1823e97c6e54Ssthen (void)evp_sctx; 1824e97c6e54Ssthen (void)hmac_ctx; 1825e97c6e54Ssthen (void)enc; 1826e97c6e54Ssthen return 0; 1827e97c6e54Ssthen #endif 1828e97c6e54Ssthen } 1829e47fef9eSflorian #endif /* HAVE_SSL */ 1830e97c6e54Ssthen 1831e97c6e54Ssthen void 1832e97c6e54Ssthen listen_sslctx_delete_ticket_keys(void) 1833e97c6e54Ssthen { 1834e97c6e54Ssthen struct tls_session_ticket_key *key; 1835e97c6e54Ssthen if(!ticket_keys) return; 1836e97c6e54Ssthen for(key = ticket_keys; key->key_name != NULL; key++) { 18379b465e50Sflorian /* wipe key data from memory*/ 18389b465e50Sflorian #ifdef HAVE_EXPLICIT_BZERO 18399b465e50Sflorian explicit_bzero(key->key_name, 80); 18409b465e50Sflorian #else 18419b465e50Sflorian memset(key->key_name, 0xdd, 80); 18429b465e50Sflorian #endif 1843e97c6e54Ssthen free(key->key_name); 1844e97c6e54Ssthen } 1845e97c6e54Ssthen free(ticket_keys); 1846e97c6e54Ssthen ticket_keys = NULL; 1847e97c6e54Ssthen } 1848f4f0f0ceSflorian 1849f4f0f0ceSflorian # ifndef USE_WINSOCK 1850f4f0f0ceSflorian char* 1851f4f0f0ceSflorian sock_strerror(int errn) 1852f4f0f0ceSflorian { 1853f4f0f0ceSflorian return strerror(errn); 1854f4f0f0ceSflorian } 1855f4f0f0ceSflorian 1856f4f0f0ceSflorian void 1857f4f0f0ceSflorian sock_close(int socket) 1858f4f0f0ceSflorian { 1859f4f0f0ceSflorian close(socket); 1860f4f0f0ceSflorian } 1861f4f0f0ceSflorian 1862f4f0f0ceSflorian # else 1863f4f0f0ceSflorian char* 1864f4f0f0ceSflorian sock_strerror(int ATTR_UNUSED(errn)) 1865f4f0f0ceSflorian { 1866f4f0f0ceSflorian return wsa_strerror(WSAGetLastError()); 1867f4f0f0ceSflorian } 1868f4f0f0ceSflorian 1869f4f0f0ceSflorian void 1870f4f0f0ceSflorian sock_close(int socket) 1871f4f0f0ceSflorian { 1872f4f0f0ceSflorian closesocket(socket); 1873f4f0f0ceSflorian } 1874f4f0f0ceSflorian # endif /* USE_WINSOCK */ 1875*7037e34cSflorian 1876*7037e34cSflorian ssize_t 1877*7037e34cSflorian hex_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize) 1878*7037e34cSflorian { 1879*7037e34cSflorian static char hexdigits[] = { 1880*7037e34cSflorian '0', '1', '2', '3', '4', '5', '6', '7', 1881*7037e34cSflorian '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' 1882*7037e34cSflorian }; 1883*7037e34cSflorian size_t i; 1884*7037e34cSflorian 1885*7037e34cSflorian if (targsize < srclength * 2 + 1) { 1886*7037e34cSflorian return -1; 1887*7037e34cSflorian } 1888*7037e34cSflorian 1889*7037e34cSflorian for (i = 0; i < srclength; ++i) { 1890*7037e34cSflorian *target++ = hexdigits[src[i] >> 4U]; 1891*7037e34cSflorian *target++ = hexdigits[src[i] & 0xfU]; 1892*7037e34cSflorian } 1893*7037e34cSflorian *target = '\0'; 1894*7037e34cSflorian return 2 * srclength; 1895*7037e34cSflorian } 1896*7037e34cSflorian 1897*7037e34cSflorian ssize_t 1898*7037e34cSflorian hex_pton(const char* src, uint8_t* target, size_t targsize) 1899*7037e34cSflorian { 1900*7037e34cSflorian uint8_t *t = target; 1901*7037e34cSflorian if(strlen(src) % 2 != 0 || strlen(src)/2 > targsize) { 1902*7037e34cSflorian return -1; 1903*7037e34cSflorian } 1904*7037e34cSflorian while(*src) { 1905*7037e34cSflorian if(!isxdigit((unsigned char)src[0]) || 1906*7037e34cSflorian !isxdigit((unsigned char)src[1])) 1907*7037e34cSflorian return -1; 1908*7037e34cSflorian *t++ = sldns_hexdigit_to_int(src[0]) * 16 + 1909*7037e34cSflorian sldns_hexdigit_to_int(src[1]) ; 1910*7037e34cSflorian src += 2; 1911*7037e34cSflorian } 1912*7037e34cSflorian return t-target; 1913*7037e34cSflorian } 1914