GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/isakmpd/util.c Lines: 0 250 0.0 %
Date: 2017-11-07 Branches: 0 165 0.0 %

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