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