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