1 /* $MirOS: src/sbin/isakmpd/util.c,v 1.3 2005/04/26 15:42:39 tg Exp $ */
2 /* $OpenBSD: util.c,v 1.57 2005/04/08 23:15:26 hshoexer Exp $	 */
3 /* $EOM: util.c,v 1.23 2000/11/23 12:22:08 niklas Exp $	 */
4 
5 /*
6  * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist.  All rights reserved.
7  * Copyright (c) 2000, 2001, 2004 H�kan Olsson.  All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 /*
31  * This code was written under funding by Ericsson Radio Systems.
32  */
33 
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <sys/stat.h>
37 #include <netinet/in.h>
38 #include <arpa/inet.h>
39 #include <limits.h>
40 #include <netdb.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <unistd.h>
44 #include <errno.h>
45 #include <ifaddrs.h>
46 #include <net/route.h>
47 #include <net/if.h>
48 
49 #include "log.h"
50 #include "message.h"
51 #include "monitor.h"
52 #include "sysdep.h"
53 #include "transport.h"
54 #include "util.h"
55 
56 /*
57  * Set if -N is given, allowing name lookups to be done, possibly stalling
58  * the daemon for quite a while.
59  */
60 int	allow_name_lookups = 0;
61 
62 #if defined(INSECURE_RAND)
63 /*
64  * This is set to true in case of regression-test mode, when it will
65  * cause predictable random numbers be generated.
66  */
67 int	regrand = 0;
68 #endif
69 
70 /*
71  * If in regression-test mode, this is the seed used.
72  */
73 u_long	seed;
74 
75 /*
76  * XXX These might be turned into inlines or macros, maybe even
77  * machine-dependent ones, for performance reasons.
78  */
79 u_int16_t
decode_16(u_int8_t * cp)80 decode_16(u_int8_t *cp)
81 {
82 	return cp[0] << 8 | cp[1];
83 }
84 
85 u_int32_t
decode_32(u_int8_t * cp)86 decode_32(u_int8_t *cp)
87 {
88 	return cp[0] << 24 | cp[1] << 16 | cp[2] << 8 | cp[3];
89 }
90 
91 u_int64_t
decode_64(u_int8_t * cp)92 decode_64(u_int8_t *cp)
93 {
94 	return (u_int64_t) cp[0] << 56 | (u_int64_t) cp[1] << 48 |
95 	    (u_int64_t) cp[2] << 40 | (u_int64_t) cp[3] << 32 |
96 	    cp[4] << 24 | cp[5] << 16 | cp[6] << 8 | cp[7];
97 }
98 
99 void
encode_16(u_int8_t * cp,u_int16_t x)100 encode_16(u_int8_t *cp, u_int16_t x)
101 {
102 	*cp++ = x >> 8;
103 	*cp = x & 0xff;
104 }
105 
106 void
encode_32(u_int8_t * cp,u_int32_t x)107 encode_32(u_int8_t *cp, u_int32_t x)
108 {
109 	*cp++ = x >> 24;
110 	*cp++ = (x >> 16) & 0xff;
111 	*cp++ = (x >> 8) & 0xff;
112 	*cp = x & 0xff;
113 }
114 
115 void
encode_64(u_int8_t * cp,u_int64_t x)116 encode_64(u_int8_t *cp, u_int64_t x)
117 {
118 	*cp++ = x >> 56;
119 	*cp++ = (x >> 48) & 0xff;
120 	*cp++ = (x >> 40) & 0xff;
121 	*cp++ = (x >> 32) & 0xff;
122 	*cp++ = (x >> 24) & 0xff;
123 	*cp++ = (x >> 16) & 0xff;
124 	*cp++ = (x >> 8) & 0xff;
125 	*cp = x & 0xff;
126 }
127 
128 /* Check a buffer for all zeroes.  */
129 int
zero_test(const u_int8_t * p,size_t sz)130 zero_test(const u_int8_t *p, size_t sz)
131 {
132 	while (sz-- > 0)
133 		if (*p++ != 0)
134 			return 0;
135 	return 1;
136 }
137 
138 /* Check a buffer for all ones.  */
139 int
ones_test(const u_int8_t * p,size_t sz)140 ones_test(const u_int8_t *p, size_t sz)
141 {
142 	while (sz-- > 0)
143 		if (*p++ != 0xff)
144 			return 0;
145 	return 1;
146 }
147 
148 /*
149  * Generate 32 bits of random data.  If compiled with INSECURE_RAND
150  * and -r option is specified, then return deterministic data.
151  */
152 u_int32_t
rand_32(void)153 rand_32(void)
154 {
155 #if !defined(INSECURE_RAND)
156 	return arc4random();
157 #else
158 	if (regrand)
159 		return random();
160 	else
161 		return arc4random();
162 #endif
163 }
164 
165 /*
166  * Generate a random data, len bytes long.
167  */
168 u_int8_t *
getrandom(u_int8_t * buf,size_t len)169 getrandom(u_int8_t *buf, size_t len)
170 {
171 	u_int32_t	tmp = 0;
172 	size_t		i;
173 
174 	for (i = 0; i < len; i++) {
175 		if (i % sizeof tmp == 0)
176 			tmp = rand_32();
177 
178 		buf[i] = tmp & 0xff;
179 		tmp >>= 8;
180 	}
181 
182 	return buf;
183 }
184 
185 static __inline int
hex2nibble(char c)186 hex2nibble(char c)
187 {
188 	if (c >= '0' && c <= '9')
189 		return c - '0';
190 	if (c >= 'a' && c <= 'f')
191 		return c - 'a' + 10;
192 	if (c >= 'A' && c <= 'F')
193 		return c - 'A' + 10;
194 	return -1;
195 }
196 
197 /*
198  * Convert hexadecimal string in S to raw binary buffer at BUF sized SZ
199  * bytes.  Return 0 if everything is OK, -1 otherwise.
200  */
201 int
hex2raw(char * s,u_int8_t * buf,size_t sz)202 hex2raw(char *s, u_int8_t *buf, size_t sz)
203 {
204 	u_int8_t *bp;
205 	char	*p;
206 	int	tmp;
207 
208 	if (strlen(s) > sz * 2)
209 		return -1;
210 	for (p = s + strlen(s) - 1, bp = &buf[sz - 1]; bp >= buf; bp--) {
211 		*bp = 0;
212 		if (p >= s) {
213 			tmp = hex2nibble(*p--);
214 			if (tmp == -1)
215 				return -1;
216 			*bp = tmp;
217 		}
218 		if (p >= s) {
219 			tmp = hex2nibble(*p--);
220 			if (tmp == -1)
221 				return -1;
222 			*bp |= tmp << 4;
223 		}
224 	}
225 	return 0;
226 }
227 
228 in_port_t
text2port(char * port_str)229 text2port(char *port_str)
230 {
231 	char           *port_str_end;
232 	long            port_long;
233 	struct servent *service;
234 
235 	port_long = strtol(port_str, &port_str_end, 0);
236 	if (port_str == port_str_end) {
237 		service = getservbyname(port_str, "udp");
238 		if (!service) {
239 			log_print("text2port: service \"%s\" unknown",
240 			    port_str);
241 			return 0;
242 		}
243 		return ntohs(service->s_port);
244 	} else if (port_long < 1 || port_long > (long)USHRT_MAX) {
245 		log_print("text2port: port %ld out of range", port_long);
246 		return 0;
247 	}
248 	return port_long;
249 }
250 
251 int
text2sockaddr(char * address,char * port,struct sockaddr ** sa,sa_family_t af,int netmask)252 text2sockaddr(char *address, char *port, struct sockaddr **sa, sa_family_t af,
253     int netmask)
254 {
255 	struct addrinfo *ai, hints;
256 	struct sockaddr_storage tmp_sas;
257 	struct ifaddrs *ifap, *ifa = NULL, *llifa = NULL;
258 	char *np = address;
259 	char ifname[IFNAMSIZ];
260 	u_char buf[BUFSIZ];
261 	struct rt_msghdr *rtm;
262 	struct sockaddr *sa2;
263 	struct sockaddr_in *sin;
264 	struct sockaddr_in6 *sin6;
265 	int fd = 0, seq, len, b;
266 	pid_t pid;
267 
268 	bzero(&hints, sizeof hints);
269 	if (!allow_name_lookups)
270 		hints.ai_flags = AI_NUMERICHOST;
271 	hints.ai_family = PF_UNSPEC;
272 	hints.ai_socktype = SOCK_DGRAM;
273 	hints.ai_protocol = IPPROTO_UDP;
274 
275 	if (getaddrinfo(address, port, &hints, &ai)) {
276 		/*
277 		 * If the 'default' keyword is used, do a route lookup for
278 		 * the default route, and use the interface associated with
279 		 * it to select a source address.
280 		 */
281 		if (!strcmp(address, "default")) {
282 			fd = socket(PF_ROUTE, SOCK_RAW, af);
283 
284 			memset(buf, 0, sizeof(buf));
285 
286 			rtm = (struct rt_msghdr *)buf;
287 			rtm->rtm_version = RTM_VERSION;
288 			rtm->rtm_type = RTM_GET;
289 			rtm->rtm_flags = RTF_UP;
290 			rtm->rtm_addrs = RTA_DST;
291 			rtm->rtm_seq = seq = arc4random();
292 
293 			/* default destination */
294 			sa2 = (struct sockaddr *)(rtm + 1);
295 			switch (af) {
296 			case AF_INET: {
297 				sin = (struct sockaddr_in *)sa2;
298 				sin->sin_len = sizeof(*sin);
299 				sin->sin_family = af;
300 				break;
301 			}
302 			case AF_INET6: {
303 				sin6 = (struct sockaddr_in6 *)sa2;
304 				sin6->sin6_len = sizeof(*sin6);
305 				sin6->sin6_family = af;
306 				break;
307 			}
308 			default:
309 				close(fd);
310 				return (-1);
311 			}
312 			rtm->rtm_addrs |= RTA_NETMASK|RTA_IFP|RTA_IFA;
313 			rtm->rtm_msglen = sizeof(*rtm) + sizeof(*sa2);
314 
315 			if ((b = write(fd, buf, rtm->rtm_msglen)) < 0) {
316 				close(fd);
317 				return (-1);
318 			}
319 
320 			pid = getpid();
321 
322 			while ((len = read(fd, buf, sizeof(buf))) > 0) {
323 				if (len < sizeof(*rtm)) {
324 					close(fd);
325 					return (-1);
326 				}
327 
328 				if (rtm->rtm_type == RTM_GET &&
329 				    rtm->rtm_pid == pid &&
330 				    rtm->rtm_seq == seq) {
331 					if (rtm->rtm_errno) {
332 						close(fd);
333 						return (-1);
334 					}
335 					break;
336 				}
337 			}
338 			close(fd);
339 
340 			if ((rtm->rtm_addrs & (RTA_DST|RTA_GATEWAY)) ==
341 			    (RTA_DST|RTA_GATEWAY)) {
342 				np = if_indextoname(rtm->rtm_index, ifname);
343 				if (np == NULL)
344 					return (-1);
345 			}
346 		}
347 
348 		if (getifaddrs(&ifap) != 0)
349 			return (-1);
350 
351 		switch (af) {
352 		default:
353 		case AF_INET:
354 			for (ifa = ifap; ifa; ifa = ifa->ifa_next)
355 				if (!strcmp(ifa->ifa_name, np) &&
356 				    ifa->ifa_addr != NULL &&
357 				    ifa->ifa_addr->sa_family == AF_INET)
358 					break;
359 			break;
360 		case AF_INET6:
361 			for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
362 				if (!strcmp(ifa->ifa_name, np) &&
363 				    ifa->ifa_addr != NULL &&
364 				    ifa->ifa_addr->sa_family == AF_INET6) {
365 					if (IN6_IS_ADDR_LINKLOCAL(
366 					    &((struct sockaddr_in6 *)
367 					    ifa->ifa_addr)->sin6_addr) &&
368 					    llifa == NULL)
369 						llifa = ifa;
370 					else
371 						break;
372 				}
373 			}
374 			if (ifa == NULL) {
375 				ifa = llifa;
376 			}
377 			break;
378 		}
379 
380 		if (ifa) {
381 			if (netmask)
382 				memcpy(&tmp_sas, ifa->ifa_netmask,
383 				    SA_LEN(ifa->ifa_netmask));
384 			else
385 				memcpy(&tmp_sas, ifa->ifa_addr,
386 				    SA_LEN(ifa->ifa_addr));
387 			freeifaddrs(ifap);
388 		} else {
389 			freeifaddrs(ifap);
390 			return -1;
391 		}
392 	} else {
393 		memcpy(&tmp_sas, ai->ai_addr, SA_LEN(ai->ai_addr));
394 		freeaddrinfo(ai);
395 	}
396 
397 	*sa = malloc(SA_LEN((struct sockaddr *)&tmp_sas));
398 	if (!*sa)
399 		return -1;
400 
401 	memcpy(*sa, &tmp_sas, SA_LEN((struct sockaddr *)&tmp_sas));
402 	return 0;
403 }
404 
405 /*
406  * Convert a sockaddr to text. With zflag non-zero fill out with zeroes,
407  * i.e 10.0.0.10 --> "010.000.000.010"
408  */
409 int
sockaddr2text(struct sockaddr * sa,char ** address,int zflag)410 sockaddr2text(struct sockaddr *sa, char **address, int zflag)
411 {
412 	char	buf[NI_MAXHOST], *token, *bstart, *ep;
413 	int	addrlen, i, j;
414 	long	val;
415 
416 	if (getnameinfo(sa, SA_LEN(sa), buf, sizeof buf, 0, 0,
417 			allow_name_lookups ? 0 : NI_NUMERICHOST))
418 		return -1;
419 
420 	if (zflag == 0) {
421 		*address = strdup(buf);
422 		if (!*address)
423 			return -1;
424 	} else
425 		switch (sa->sa_family) {
426 		case AF_INET:
427 			addrlen = sizeof "000.000.000.000";
428 			*address = malloc(addrlen);
429 			if (!*address)
430 				return -1;
431 			buf[addrlen] = '\0';
432 			bstart = buf;
433 			**address = '\0';
434 			while ((token = strsep(&bstart, ".")) != NULL) {
435 				if (strlen(*address) > 12) {
436 					free(*address);
437 					return -1;
438 				}
439 				val = strtol(token, &ep, 10);
440 				if (ep == token || val < (long)0 ||
441 				    val > (long)UCHAR_MAX) {
442 					free(*address);
443 					return -1;
444 				}
445 				snprintf(*address + strlen(*address),
446 				    addrlen - strlen(*address), "%03ld", val);
447 				if (bstart)
448 					strlcat(*address, ".", addrlen);
449 			}
450 			break;
451 
452 		case AF_INET6:
453 			/*
454 			 * XXX In the algorithm below there are some magic
455 			 * numbers we probably could give explaining names.
456 			 */
457 			addrlen =
458 			    sizeof "0000:0000:0000:0000:0000:0000:0000:0000";
459 			*address = malloc(addrlen);
460 			if (!*address)
461 				return -1;
462 
463 			for (i = 0, j = 0; i < 8; i++) {
464 				snprintf((*address) + j, addrlen - j,
465 				    "%02x%02x",
466 				    ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[2*i],
467 				    ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[2*i + 1]);
468 				j += 4;
469 				(*address)[j] =
470 				    (j < (addrlen - 1)) ? ':' : '\0';
471 				j++;
472 			}
473 			break;
474 
475 		default:
476 			*address = strdup("<error>");
477 			if (!*address)
478 				return -1;
479 		}
480 
481 	return 0;
482 }
483 
484 /*
485  * sockaddr_addrlen and sockaddr_addrdata return the relevant sockaddr info
486  * depending on address family.  Useful to keep other code shorter(/clearer?).
487  */
488 int
sockaddr_addrlen(struct sockaddr * sa)489 sockaddr_addrlen(struct sockaddr *sa)
490 {
491 	switch (sa->sa_family) {
492 	case AF_INET6:
493 		return sizeof((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr;
494 	case AF_INET:
495 		return sizeof((struct sockaddr_in *)sa)->sin_addr.s_addr;
496 	default:
497 		log_print("sockaddr_addrlen: unsupported protocol family %d",
498 		    sa->sa_family);
499 		return 0;
500 	}
501 }
502 
503 u_int8_t *
sockaddr_addrdata(struct sockaddr * sa)504 sockaddr_addrdata(struct sockaddr *sa)
505 {
506 	switch (sa->sa_family) {
507 	case AF_INET6:
508 		return (u_int8_t *)&((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr;
509 	case AF_INET:
510 		return (u_int8_t *)&((struct sockaddr_in *)sa)->sin_addr.s_addr;
511 	default:
512 		log_print("sockaddr_addrdata: unsupported protocol family %d",
513 		    sa->sa_family);
514 		return 0;
515 	}
516 }
517 
518 in_port_t
sockaddr_port(struct sockaddr * sa)519 sockaddr_port(struct sockaddr *sa)
520 {
521 	switch (sa->sa_family) {
522 	case AF_INET6:
523 		return ((struct sockaddr_in6 *)sa)->sin6_port;
524 	case AF_INET:
525 		return ((struct sockaddr_in *)sa)->sin_port;
526 	default:
527 		log_print("sockaddr_port: unsupported protocol family %d",
528 		    sa->sa_family);
529 		return 0;
530 	}
531 }
532 
533 /* Utility function used to set the port of a sockaddr.  */
534 void
sockaddr_set_port(struct sockaddr * sa,in_port_t port)535 sockaddr_set_port(struct sockaddr *sa, in_port_t port)
536 {
537 	switch (sa->sa_family) {
538 	case AF_INET:
539 		((struct sockaddr_in *)sa)->sin_port = htons (port);
540 		break;
541 
542 	case AF_INET6:
543 		((struct sockaddr_in6 *)sa)->sin6_port = htons (port);
544 		break;
545 	}
546 }
547 
548 /*
549  * Convert network address to text. The network address does not need
550  * to be properly aligned.
551  */
552 void
util_ntoa(char ** buf,int af,u_int8_t * addr)553 util_ntoa(char **buf, int af, u_int8_t *addr)
554 {
555 	struct sockaddr_storage from;
556 	struct sockaddr *sfrom = (struct sockaddr *) & from;
557 	socklen_t	fromlen = sizeof from;
558 
559 	bzero(&from, fromlen);
560 	sfrom->sa_family = af;
561 
562 	switch (af) {
563 	case AF_INET:
564 		sfrom->sa_len = sizeof(struct sockaddr_in);
565 		break;
566 	case AF_INET6:
567 		sfrom->sa_len = sizeof(struct sockaddr_in6);
568 		break;
569 	}
570 
571 	memcpy(sockaddr_addrdata(sfrom), addr, sockaddr_addrlen(sfrom));
572 
573 	if (sockaddr2text(sfrom, buf, 0)) {
574 		log_print("util_ntoa: could not make printable address out "
575 		    "of sockaddr %p", sfrom);
576 		*buf = 0;
577 	}
578 }
579 
580 /*
581  * Perform sanity check on files containing secret information.
582  * Returns -1 on failure, 0 otherwise.
583  * Also, if FILE_SIZE is a not a null pointer, store file size here.
584  */
585 
586 int
check_file_secrecy_fd(int fd,char * name,size_t * file_size)587 check_file_secrecy_fd(int fd, char *name, size_t *file_size)
588 {
589 	struct stat st;
590 
591 	if (fstat(fd, &st) == -1) {
592 		log_error("check_file_secrecy: stat (\"%s\") failed", name);
593 		return -1;
594 	}
595 	if (st.st_uid != 0 && st.st_uid != getuid()) {
596 		log_print("check_file_secrecy_fd: "
597 		    "not loading %s - file owner is not process user", name);
598 		errno = EPERM;
599 		return -1;
600 	}
601 	if ((st.st_mode & (S_IRWXG | S_IRWXO)) != 0) {
602 		log_print("check_file_secrecy_fd: not loading %s - too open "
603 		    "permissions", name);
604 		errno = EPERM;
605 		return -1;
606 	}
607 	if (file_size)
608 		*file_size = (size_t)st.st_size;
609 
610 	return 0;
611 }
612 
613 /* Special for compiling with Boehms GC. See Makefile and sysdep.h  */
614 #if defined (USE_BOEHM_GC)
615 char *
gc_strdup(const char * x)616 gc_strdup(const char *x)
617 {
618 	char *strcpy(char *,const char *);
619 	char *y = malloc(strlen(x) + 1);
620 	return strcpy(y,x);
621 }
622 #endif
623