1 /* 2 * util/net_help.c - implementation of the network helper code 3 * 4 * Copyright (c) 2007, NLnet Labs. All rights reserved. 5 * 6 * This software is open source. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * Redistributions of source code must retain the above copyright notice, 13 * this list of conditions and the following disclaimer. 14 * 15 * Redistributions in binary form must reproduce the above copyright notice, 16 * this list of conditions and the following disclaimer in the documentation 17 * and/or other materials provided with the distribution. 18 * 19 * Neither the name of the NLNET LABS nor the names of its contributors may 20 * be used to endorse or promote products derived from this software without 21 * specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 /** 36 * \file 37 * Implementation of net_help.h. 38 */ 39 40 #include "config.h" 41 #include "util/net_help.h" 42 #include "util/log.h" 43 #include "util/data/dname.h" 44 #include "util/module.h" 45 #include "util/regional.h" 46 #include "ldns/parseutil.h" 47 #include "ldns/wire2str.h" 48 #include <fcntl.h> 49 #ifdef HAVE_OPENSSL_SSL_H 50 #include <openssl/ssl.h> 51 #endif 52 #ifdef HAVE_OPENSSL_ERR_H 53 #include <openssl/err.h> 54 #endif 55 56 /** max length of an IP address (the address portion) that we allow */ 57 #define MAX_ADDR_STRLEN 128 /* characters */ 58 /** default value for EDNS ADVERTISED size */ 59 uint16_t EDNS_ADVERTISED_SIZE = 4096; 60 61 /** minimal responses when positive answer: default is no */ 62 int MINIMAL_RESPONSES = 0; 63 64 /** rrset order roundrobin: default is no */ 65 int RRSET_ROUNDROBIN = 0; 66 67 /* returns true is string addr is an ip6 specced address */ 68 int 69 str_is_ip6(const char* str) 70 { 71 if(strchr(str, ':')) 72 return 1; 73 else return 0; 74 } 75 76 int 77 fd_set_nonblock(int s) 78 { 79 #ifdef HAVE_FCNTL 80 int flag; 81 if((flag = fcntl(s, F_GETFL)) == -1) { 82 log_err("can't fcntl F_GETFL: %s", strerror(errno)); 83 flag = 0; 84 } 85 flag |= O_NONBLOCK; 86 if(fcntl(s, F_SETFL, flag) == -1) { 87 log_err("can't fcntl F_SETFL: %s", strerror(errno)); 88 return 0; 89 } 90 #elif defined(HAVE_IOCTLSOCKET) 91 unsigned long on = 1; 92 if(ioctlsocket(s, FIONBIO, &on) != 0) { 93 log_err("can't ioctlsocket FIONBIO on: %s", 94 wsa_strerror(WSAGetLastError())); 95 } 96 #endif 97 return 1; 98 } 99 100 int 101 fd_set_block(int s) 102 { 103 #ifdef HAVE_FCNTL 104 int flag; 105 if((flag = fcntl(s, F_GETFL)) == -1) { 106 log_err("cannot fcntl F_GETFL: %s", strerror(errno)); 107 flag = 0; 108 } 109 flag &= ~O_NONBLOCK; 110 if(fcntl(s, F_SETFL, flag) == -1) { 111 log_err("cannot fcntl F_SETFL: %s", strerror(errno)); 112 return 0; 113 } 114 #elif defined(HAVE_IOCTLSOCKET) 115 unsigned long off = 0; 116 if(ioctlsocket(s, FIONBIO, &off) != 0) { 117 log_err("can't ioctlsocket FIONBIO off: %s", 118 wsa_strerror(WSAGetLastError())); 119 } 120 #endif 121 return 1; 122 } 123 124 int 125 is_pow2(size_t num) 126 { 127 if(num == 0) return 1; 128 return (num & (num-1)) == 0; 129 } 130 131 void* 132 memdup(void* data, size_t len) 133 { 134 void* d; 135 if(!data) return NULL; 136 if(len == 0) return NULL; 137 d = malloc(len); 138 if(!d) return NULL; 139 memcpy(d, data, len); 140 return d; 141 } 142 143 void 144 log_addr(enum verbosity_value v, const char* str, 145 struct sockaddr_storage* addr, socklen_t addrlen) 146 { 147 uint16_t port; 148 const char* family = "unknown"; 149 char dest[100]; 150 int af = (int)((struct sockaddr_in*)addr)->sin_family; 151 void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 152 if(verbosity < v) 153 return; 154 switch(af) { 155 case AF_INET: family="ip4"; break; 156 case AF_INET6: family="ip6"; 157 sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; 158 break; 159 case AF_UNIX: family="unix"; break; 160 default: break; 161 } 162 if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { 163 (void)strlcpy(dest, "(inet_ntop error)", sizeof(dest)); 164 } 165 dest[sizeof(dest)-1] = 0; 166 port = ntohs(((struct sockaddr_in*)addr)->sin_port); 167 if(verbosity >= 4) 168 verbose(v, "%s %s %s port %d (len %d)", str, family, dest, 169 (int)port, (int)addrlen); 170 else verbose(v, "%s %s port %d", str, dest, (int)port); 171 } 172 173 int 174 extstrtoaddr(const char* str, struct sockaddr_storage* addr, 175 socklen_t* addrlen) 176 { 177 char* s; 178 int port = UNBOUND_DNS_PORT; 179 if((s=strchr(str, '@'))) { 180 char buf[MAX_ADDR_STRLEN]; 181 if(s-str >= MAX_ADDR_STRLEN) { 182 return 0; 183 } 184 (void)strlcpy(buf, str, sizeof(buf)); 185 buf[s-str] = 0; 186 port = atoi(s+1); 187 if(port == 0 && strcmp(s+1,"0")!=0) { 188 return 0; 189 } 190 return ipstrtoaddr(buf, port, addr, addrlen); 191 } 192 return ipstrtoaddr(str, port, addr, addrlen); 193 } 194 195 196 int 197 ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr, 198 socklen_t* addrlen) 199 { 200 uint16_t p; 201 if(!ip) return 0; 202 p = (uint16_t) port; 203 if(str_is_ip6(ip)) { 204 char buf[MAX_ADDR_STRLEN]; 205 char* s; 206 struct sockaddr_in6* sa = (struct sockaddr_in6*)addr; 207 *addrlen = (socklen_t)sizeof(struct sockaddr_in6); 208 memset(sa, 0, *addrlen); 209 sa->sin6_family = AF_INET6; 210 sa->sin6_port = (in_port_t)htons(p); 211 if((s=strchr(ip, '%'))) { /* ip6%interface, rfc 4007 */ 212 if(s-ip >= MAX_ADDR_STRLEN) 213 return 0; 214 (void)strlcpy(buf, ip, sizeof(buf)); 215 buf[s-ip]=0; 216 sa->sin6_scope_id = (uint32_t)atoi(s+1); 217 ip = buf; 218 } 219 if(inet_pton((int)sa->sin6_family, ip, &sa->sin6_addr) <= 0) { 220 return 0; 221 } 222 } else { /* ip4 */ 223 struct sockaddr_in* sa = (struct sockaddr_in*)addr; 224 *addrlen = (socklen_t)sizeof(struct sockaddr_in); 225 memset(sa, 0, *addrlen); 226 sa->sin_family = AF_INET; 227 sa->sin_port = (in_port_t)htons(p); 228 if(inet_pton((int)sa->sin_family, ip, &sa->sin_addr) <= 0) { 229 return 0; 230 } 231 } 232 return 1; 233 } 234 235 int netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr, 236 socklen_t* addrlen, int* net) 237 { 238 char* s = NULL; 239 *net = (str_is_ip6(str)?128:32); 240 if((s=strchr(str, '/'))) { 241 if(atoi(s+1) > *net) { 242 log_err("netblock too large: %s", str); 243 return 0; 244 } 245 *net = atoi(s+1); 246 if(*net == 0 && strcmp(s+1, "0") != 0) { 247 log_err("cannot parse netblock: '%s'", str); 248 return 0; 249 } 250 if(!(s = strdup(str))) { 251 log_err("out of memory"); 252 return 0; 253 } 254 *strchr(s, '/') = '\0'; 255 } 256 if(!ipstrtoaddr(s?s:str, port, addr, addrlen)) { 257 free(s); 258 log_err("cannot parse ip address: '%s'", str); 259 return 0; 260 } 261 if(s) { 262 free(s); 263 addr_mask(addr, *addrlen, *net); 264 } 265 return 1; 266 } 267 268 void 269 log_nametypeclass(enum verbosity_value v, const char* str, uint8_t* name, 270 uint16_t type, uint16_t dclass) 271 { 272 char buf[LDNS_MAX_DOMAINLEN+1]; 273 char t[12], c[12]; 274 const char *ts, *cs; 275 if(verbosity < v) 276 return; 277 dname_str(name, buf); 278 if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG"; 279 else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR"; 280 else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR"; 281 else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB"; 282 else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA"; 283 else if(type == LDNS_RR_TYPE_ANY) ts = "ANY"; 284 else if(sldns_rr_descript(type) && sldns_rr_descript(type)->_name) 285 ts = sldns_rr_descript(type)->_name; 286 else { 287 snprintf(t, sizeof(t), "TYPE%d", (int)type); 288 ts = t; 289 } 290 if(sldns_lookup_by_id(sldns_rr_classes, (int)dclass) && 291 sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name) 292 cs = sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name; 293 else { 294 snprintf(c, sizeof(c), "CLASS%d", (int)dclass); 295 cs = c; 296 } 297 log_info("%s %s %s %s", str, buf, ts, cs); 298 } 299 300 void log_name_addr(enum verbosity_value v, const char* str, uint8_t* zone, 301 struct sockaddr_storage* addr, socklen_t addrlen) 302 { 303 uint16_t port; 304 const char* family = "unknown_family "; 305 char namebuf[LDNS_MAX_DOMAINLEN+1]; 306 char dest[100]; 307 int af = (int)((struct sockaddr_in*)addr)->sin_family; 308 void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 309 if(verbosity < v) 310 return; 311 switch(af) { 312 case AF_INET: family=""; break; 313 case AF_INET6: family=""; 314 sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; 315 break; 316 case AF_UNIX: family="unix_family "; break; 317 default: break; 318 } 319 if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { 320 (void)strlcpy(dest, "(inet_ntop error)", sizeof(dest)); 321 } 322 dest[sizeof(dest)-1] = 0; 323 port = ntohs(((struct sockaddr_in*)addr)->sin_port); 324 dname_str(zone, namebuf); 325 if(af != AF_INET && af != AF_INET6) 326 verbose(v, "%s <%s> %s%s#%d (addrlen %d)", 327 str, namebuf, family, dest, (int)port, (int)addrlen); 328 else verbose(v, "%s <%s> %s%s#%d", 329 str, namebuf, family, dest, (int)port); 330 } 331 332 int 333 sockaddr_cmp(struct sockaddr_storage* addr1, socklen_t len1, 334 struct sockaddr_storage* addr2, socklen_t len2) 335 { 336 struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1; 337 struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2; 338 struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1; 339 struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2; 340 if(len1 < len2) 341 return -1; 342 if(len1 > len2) 343 return 1; 344 log_assert(len1 == len2); 345 if( p1_in->sin_family < p2_in->sin_family) 346 return -1; 347 if( p1_in->sin_family > p2_in->sin_family) 348 return 1; 349 log_assert( p1_in->sin_family == p2_in->sin_family ); 350 /* compare ip4 */ 351 if( p1_in->sin_family == AF_INET ) { 352 /* just order it, ntohs not required */ 353 if(p1_in->sin_port < p2_in->sin_port) 354 return -1; 355 if(p1_in->sin_port > p2_in->sin_port) 356 return 1; 357 log_assert(p1_in->sin_port == p2_in->sin_port); 358 return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE); 359 } else if (p1_in6->sin6_family == AF_INET6) { 360 /* just order it, ntohs not required */ 361 if(p1_in6->sin6_port < p2_in6->sin6_port) 362 return -1; 363 if(p1_in6->sin6_port > p2_in6->sin6_port) 364 return 1; 365 log_assert(p1_in6->sin6_port == p2_in6->sin6_port); 366 return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr, 367 INET6_SIZE); 368 } else { 369 /* eek unknown type, perform this comparison for sanity. */ 370 return memcmp(addr1, addr2, len1); 371 } 372 } 373 374 int 375 sockaddr_cmp_addr(struct sockaddr_storage* addr1, socklen_t len1, 376 struct sockaddr_storage* addr2, socklen_t len2) 377 { 378 struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1; 379 struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2; 380 struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1; 381 struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2; 382 if(len1 < len2) 383 return -1; 384 if(len1 > len2) 385 return 1; 386 log_assert(len1 == len2); 387 if( p1_in->sin_family < p2_in->sin_family) 388 return -1; 389 if( p1_in->sin_family > p2_in->sin_family) 390 return 1; 391 log_assert( p1_in->sin_family == p2_in->sin_family ); 392 /* compare ip4 */ 393 if( p1_in->sin_family == AF_INET ) { 394 return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE); 395 } else if (p1_in6->sin6_family == AF_INET6) { 396 return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr, 397 INET6_SIZE); 398 } else { 399 /* eek unknown type, perform this comparison for sanity. */ 400 return memcmp(addr1, addr2, len1); 401 } 402 } 403 404 int 405 addr_is_ip6(struct sockaddr_storage* addr, socklen_t len) 406 { 407 if(len == (socklen_t)sizeof(struct sockaddr_in6) && 408 ((struct sockaddr_in6*)addr)->sin6_family == AF_INET6) 409 return 1; 410 else return 0; 411 } 412 413 void 414 addr_mask(struct sockaddr_storage* addr, socklen_t len, int net) 415 { 416 uint8_t mask[8] = {0x0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe}; 417 int i, max; 418 uint8_t* s; 419 if(addr_is_ip6(addr, len)) { 420 s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr; 421 max = 128; 422 } else { 423 s = (uint8_t*)&((struct sockaddr_in*)addr)->sin_addr; 424 max = 32; 425 } 426 if(net >= max) 427 return; 428 for(i=net/8+1; i<max/8; i++) { 429 s[i] = 0; 430 } 431 s[net/8] &= mask[net&0x7]; 432 } 433 434 int 435 addr_in_common(struct sockaddr_storage* addr1, int net1, 436 struct sockaddr_storage* addr2, int net2, socklen_t addrlen) 437 { 438 int min = (net1<net2)?net1:net2; 439 int i, to; 440 int match = 0; 441 uint8_t* s1, *s2; 442 if(addr_is_ip6(addr1, addrlen)) { 443 s1 = (uint8_t*)&((struct sockaddr_in6*)addr1)->sin6_addr; 444 s2 = (uint8_t*)&((struct sockaddr_in6*)addr2)->sin6_addr; 445 to = 16; 446 } else { 447 s1 = (uint8_t*)&((struct sockaddr_in*)addr1)->sin_addr; 448 s2 = (uint8_t*)&((struct sockaddr_in*)addr2)->sin_addr; 449 to = 4; 450 } 451 /* match = bits_in_common(s1, s2, to); */ 452 for(i=0; i<to; i++) { 453 if(s1[i] == s2[i]) { 454 match += 8; 455 } else { 456 uint8_t z = s1[i]^s2[i]; 457 log_assert(z); 458 while(!(z&0x80)) { 459 match++; 460 z<<=1; 461 } 462 break; 463 } 464 } 465 if(match > min) match = min; 466 return match; 467 } 468 469 void 470 addr_to_str(struct sockaddr_storage* addr, socklen_t addrlen, 471 char* buf, size_t len) 472 { 473 int af = (int)((struct sockaddr_in*)addr)->sin_family; 474 void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 475 if(addr_is_ip6(addr, addrlen)) 476 sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; 477 if(inet_ntop(af, sinaddr, buf, (socklen_t)len) == 0) { 478 snprintf(buf, len, "(inet_ntop_error)"); 479 } 480 } 481 482 int 483 addr_is_ip4mapped(struct sockaddr_storage* addr, socklen_t addrlen) 484 { 485 /* prefix for ipv4 into ipv6 mapping is ::ffff:x.x.x.x */ 486 const uint8_t map_prefix[16] = 487 {0,0,0,0, 0,0,0,0, 0,0,0xff,0xff, 0,0,0,0}; 488 uint8_t* s; 489 if(!addr_is_ip6(addr, addrlen)) 490 return 0; 491 /* s is 16 octet ipv6 address string */ 492 s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr; 493 return (memcmp(s, map_prefix, 12) == 0); 494 } 495 496 int addr_is_broadcast(struct sockaddr_storage* addr, socklen_t addrlen) 497 { 498 int af = (int)((struct sockaddr_in*)addr)->sin_family; 499 void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 500 return af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in) 501 && memcmp(sinaddr, "\377\377\377\377", 4) == 0; 502 } 503 504 int addr_is_any(struct sockaddr_storage* addr, socklen_t addrlen) 505 { 506 int af = (int)((struct sockaddr_in*)addr)->sin_family; 507 void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 508 void* sin6addr = &((struct sockaddr_in6*)addr)->sin6_addr; 509 if(af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in) 510 && memcmp(sinaddr, "\000\000\000\000", 4) == 0) 511 return 1; 512 else if(af==AF_INET6 && addrlen>=(socklen_t)sizeof(struct sockaddr_in6) 513 && memcmp(sin6addr, "\000\000\000\000\000\000\000\000" 514 "\000\000\000\000\000\000\000\000", 16) == 0) 515 return 1; 516 return 0; 517 } 518 519 void sock_list_insert(struct sock_list** list, struct sockaddr_storage* addr, 520 socklen_t len, struct regional* region) 521 { 522 struct sock_list* add = (struct sock_list*)regional_alloc(region, 523 sizeof(*add) - sizeof(add->addr) + (size_t)len); 524 if(!add) { 525 log_err("out of memory in socketlist insert"); 526 return; 527 } 528 log_assert(list); 529 add->next = *list; 530 add->len = len; 531 *list = add; 532 if(len) memmove(&add->addr, addr, len); 533 } 534 535 void sock_list_prepend(struct sock_list** list, struct sock_list* add) 536 { 537 struct sock_list* last = add; 538 if(!last) 539 return; 540 while(last->next) 541 last = last->next; 542 last->next = *list; 543 *list = add; 544 } 545 546 int sock_list_find(struct sock_list* list, struct sockaddr_storage* addr, 547 socklen_t len) 548 { 549 while(list) { 550 if(len == list->len) { 551 if(len == 0 || sockaddr_cmp_addr(addr, len, 552 &list->addr, list->len) == 0) 553 return 1; 554 } 555 list = list->next; 556 } 557 return 0; 558 } 559 560 void sock_list_merge(struct sock_list** list, struct regional* region, 561 struct sock_list* add) 562 { 563 struct sock_list* p; 564 for(p=add; p; p=p->next) { 565 if(!sock_list_find(*list, &p->addr, p->len)) 566 sock_list_insert(list, &p->addr, p->len, region); 567 } 568 } 569 570 void 571 log_crypto_err(const char* str) 572 { 573 #ifdef HAVE_SSL 574 /* error:[error code]:[library name]:[function name]:[reason string] */ 575 char buf[128]; 576 unsigned long e; 577 ERR_error_string_n(ERR_get_error(), buf, sizeof(buf)); 578 log_err("%s crypto %s", str, buf); 579 while( (e=ERR_get_error()) ) { 580 ERR_error_string_n(e, buf, sizeof(buf)); 581 log_err("and additionally crypto %s", buf); 582 } 583 #else 584 (void)str; 585 #endif /* HAVE_SSL */ 586 } 587 588 void* listen_sslctx_create(char* key, char* pem, char* verifypem) 589 { 590 #ifdef HAVE_SSL 591 SSL_CTX* ctx = SSL_CTX_new(SSLv23_server_method()); 592 if(!ctx) { 593 log_crypto_err("could not SSL_CTX_new"); 594 return NULL; 595 } 596 /* no SSLv2 because has defects */ 597 if(!(SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)){ 598 log_crypto_err("could not set SSL_OP_NO_SSLv2"); 599 SSL_CTX_free(ctx); 600 return NULL; 601 } 602 if(!SSL_CTX_use_certificate_file(ctx, pem, SSL_FILETYPE_PEM)) { 603 log_err("error for cert file: %s", pem); 604 log_crypto_err("error in SSL_CTX use_certificate_file"); 605 SSL_CTX_free(ctx); 606 return NULL; 607 } 608 if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) { 609 log_err("error for private key file: %s", key); 610 log_crypto_err("Error in SSL_CTX use_PrivateKey_file"); 611 SSL_CTX_free(ctx); 612 return NULL; 613 } 614 if(!SSL_CTX_check_private_key(ctx)) { 615 log_err("error for key file: %s", key); 616 log_crypto_err("Error in SSL_CTX check_private_key"); 617 SSL_CTX_free(ctx); 618 return NULL; 619 } 620 621 if(verifypem && verifypem[0]) { 622 if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) { 623 log_crypto_err("Error in SSL_CTX verify locations"); 624 SSL_CTX_free(ctx); 625 return NULL; 626 } 627 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file( 628 verifypem)); 629 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); 630 } 631 return ctx; 632 #else 633 (void)key; (void)pem; (void)verifypem; 634 return NULL; 635 #endif 636 } 637 638 void* connect_sslctx_create(char* key, char* pem, char* verifypem) 639 { 640 #ifdef HAVE_SSL 641 SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method()); 642 if(!ctx) { 643 log_crypto_err("could not allocate SSL_CTX pointer"); 644 return NULL; 645 } 646 if(!(SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)) { 647 log_crypto_err("could not set SSL_OP_NO_SSLv2"); 648 SSL_CTX_free(ctx); 649 return NULL; 650 } 651 if(key && key[0]) { 652 if(!SSL_CTX_use_certificate_file(ctx, pem, SSL_FILETYPE_PEM)) { 653 log_err("error in client certificate %s", pem); 654 log_crypto_err("error in certificate file"); 655 SSL_CTX_free(ctx); 656 return NULL; 657 } 658 if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) { 659 log_err("error in client private key %s", key); 660 log_crypto_err("error in key file"); 661 SSL_CTX_free(ctx); 662 return NULL; 663 } 664 if(!SSL_CTX_check_private_key(ctx)) { 665 log_err("error in client key %s", key); 666 log_crypto_err("error in SSL_CTX_check_private_key"); 667 SSL_CTX_free(ctx); 668 return NULL; 669 } 670 } 671 if(verifypem && verifypem[0]) { 672 if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL) != 1) { 673 log_crypto_err("error in SSL_CTX verify"); 674 SSL_CTX_free(ctx); 675 return NULL; 676 } 677 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); 678 } 679 return ctx; 680 #else 681 (void)key; (void)pem; (void)verifypem; 682 return NULL; 683 #endif 684 } 685 686 void* incoming_ssl_fd(void* sslctx, int fd) 687 { 688 #ifdef HAVE_SSL 689 SSL* ssl = SSL_new((SSL_CTX*)sslctx); 690 if(!ssl) { 691 log_crypto_err("could not SSL_new"); 692 return NULL; 693 } 694 SSL_set_accept_state(ssl); 695 (void)SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); 696 if(!SSL_set_fd(ssl, fd)) { 697 log_crypto_err("could not SSL_set_fd"); 698 SSL_free(ssl); 699 return NULL; 700 } 701 return ssl; 702 #else 703 (void)sslctx; (void)fd; 704 return NULL; 705 #endif 706 } 707 708 void* outgoing_ssl_fd(void* sslctx, int fd) 709 { 710 #ifdef HAVE_SSL 711 SSL* ssl = SSL_new((SSL_CTX*)sslctx); 712 if(!ssl) { 713 log_crypto_err("could not SSL_new"); 714 return NULL; 715 } 716 SSL_set_connect_state(ssl); 717 (void)SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); 718 if(!SSL_set_fd(ssl, fd)) { 719 log_crypto_err("could not SSL_set_fd"); 720 SSL_free(ssl); 721 return NULL; 722 } 723 return ssl; 724 #else 725 (void)sslctx; (void)fd; 726 return NULL; 727 #endif 728 } 729 730 #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) 731 /** global lock list for openssl locks */ 732 static lock_basic_t *ub_openssl_locks = NULL; 733 734 /** callback that gets thread id for openssl */ 735 static unsigned long 736 ub_crypto_id_cb(void) 737 { 738 return (unsigned long)ub_thread_self(); 739 } 740 741 static void 742 ub_crypto_lock_cb(int mode, int type, const char *ATTR_UNUSED(file), 743 int ATTR_UNUSED(line)) 744 { 745 if((mode&CRYPTO_LOCK)) { 746 lock_basic_lock(&ub_openssl_locks[type]); 747 } else { 748 lock_basic_unlock(&ub_openssl_locks[type]); 749 } 750 } 751 #endif /* OPENSSL_THREADS */ 752 753 int ub_openssl_lock_init(void) 754 { 755 #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) 756 int i; 757 ub_openssl_locks = (lock_basic_t*)malloc( 758 sizeof(lock_basic_t)*CRYPTO_num_locks()); 759 if(!ub_openssl_locks) 760 return 0; 761 for(i=0; i<CRYPTO_num_locks(); i++) { 762 lock_basic_init(&ub_openssl_locks[i]); 763 } 764 CRYPTO_set_id_callback(&ub_crypto_id_cb); 765 CRYPTO_set_locking_callback(&ub_crypto_lock_cb); 766 #endif /* OPENSSL_THREADS */ 767 return 1; 768 } 769 770 void ub_openssl_lock_delete(void) 771 { 772 #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) 773 int i; 774 if(!ub_openssl_locks) 775 return; 776 CRYPTO_set_id_callback(NULL); 777 CRYPTO_set_locking_callback(NULL); 778 for(i=0; i<CRYPTO_num_locks(); i++) { 779 lock_basic_destroy(&ub_openssl_locks[i]); 780 } 781 free(ub_openssl_locks); 782 #endif /* OPENSSL_THREADS */ 783 } 784 785