misc.c 23 KB
Newer Older
1
/* $OpenBSD: misc.c,v 1.94 2014/07/15 15:54:14 millert Exp $ */
2 3
/*
 * Copyright (c) 2000 Markus Friedl.  All rights reserved.
4
 * Copyright (c) 2005,2006 Damien Miller.  All rights reserved.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

Damien Miller's avatar
Damien Miller committed
27
#include "includes.h"
28

29
#include <sys/types.h>
30
#include <sys/ioctl.h>
31
#include <sys/socket.h>
32
#include <sys/un.h>
33
#include <sys/param.h>
34

35
#include <stdarg.h>
36
#include <stdio.h>
37
#include <stdlib.h>
38
#include <string.h>
39
#include <time.h>
40
#include <unistd.h>
41

42
#include <netinet/in.h>
43 44
#include <netinet/in_systm.h>
#include <netinet/ip.h>
45
#include <netinet/tcp.h>
46

47
#include <ctype.h>
48
#include <errno.h>
49
#include <fcntl.h>
50
#include <netdb.h>
51
#ifdef HAVE_PATHS_H
Damien Miller's avatar
Damien Miller committed
52
# include <paths.h>
53
#include <pwd.h>
54
#endif
55 56 57
#ifdef SSH_TUN_OPENBSD
#include <net/if.h>
#endif
Damien Miller's avatar
Damien Miller committed
58

59
#include "xmalloc.h"
60
#include "misc.h"
61
#include "log.h"
62
#include "ssh.h"
Damien Miller's avatar
Damien Miller committed
63

64
/* remove newline at end of string */
Damien Miller's avatar
Damien Miller committed
65 66 67 68 69
char *
chop(char *s)
{
	char *t = s;
	while (*t) {
70
		if (*t == '\n' || *t == '\r') {
Damien Miller's avatar
Damien Miller committed
71 72 73 74 75 76 77 78 79
			*t = '\0';
			return s;
		}
		t++;
	}
	return s;

}

80
/* set/unset filedescriptor to non-blocking */
81
int
Damien Miller's avatar
Damien Miller committed
82 83 84
set_nonblock(int fd)
{
	int val;
85

Damien Miller's avatar
Damien Miller committed
86 87 88
	val = fcntl(fd, F_GETFL, 0);
	if (val < 0) {
		error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
89
		return (-1);
Damien Miller's avatar
Damien Miller committed
90
	}
91
	if (val & O_NONBLOCK) {
92 93
		debug3("fd %d is O_NONBLOCK", fd);
		return (0);
94
	}
95
	debug2("fd %d setting O_NONBLOCK", fd);
Damien Miller's avatar
Damien Miller committed
96
	val |= O_NONBLOCK;
97 98 99 100 101 102
	if (fcntl(fd, F_SETFL, val) == -1) {
		debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", fd,
		    strerror(errno));
		return (-1);
	}
	return (0);
Damien Miller's avatar
Damien Miller committed
103 104
}

105
int
106 107 108 109 110 111 112
unset_nonblock(int fd)
{
	int val;

	val = fcntl(fd, F_GETFL, 0);
	if (val < 0) {
		error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
113
		return (-1);
114 115
	}
	if (!(val & O_NONBLOCK)) {
116 117
		debug3("fd %d is not O_NONBLOCK", fd);
		return (0);
118
	}
119
	debug("fd %d clearing O_NONBLOCK", fd);
120
	val &= ~O_NONBLOCK;
121 122
	if (fcntl(fd, F_SETFL, val) == -1) {
		debug("fcntl(%d, F_SETFL, ~O_NONBLOCK): %s",
123
		    fd, strerror(errno));
124 125 126
		return (-1);
	}
	return (0);
127 128
}

129 130 131
const char *
ssh_gai_strerror(int gaierr)
{
132
	if (gaierr == EAI_SYSTEM && errno != 0)
133 134
		return strerror(errno);
	return gai_strerror(gaierr);
135 136
}

137 138 139 140
/* disable nagle on socket */
void
set_nodelay(int fd)
{
141 142
	int opt;
	socklen_t optlen;
143

144 145
	optlen = sizeof opt;
	if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) {
146
		debug("getsockopt TCP_NODELAY: %.100s", strerror(errno));
147 148 149 150 151 152 153
		return;
	}
	if (opt == 1) {
		debug2("fd %d is TCP_NODELAY", fd);
		return;
	}
	opt = 1;
154
	debug2("fd %d setting TCP_NODELAY", fd);
155
	if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof opt) == -1)
156 157 158
		error("setsockopt TCP_NODELAY: %.100s", strerror(errno));
}

Damien Miller's avatar
Damien Miller committed
159 160
/* Characters considered whitespace in strsep calls. */
#define WHITESPACE " \t\r\n"
161
#define QUOTE	"\""
Damien Miller's avatar
Damien Miller committed
162

163
/* return next token in configuration line */
Damien Miller's avatar
Damien Miller committed
164 165 166 167 168 169 170 171 172 173 174
char *
strdelim(char **s)
{
	char *old;
	int wspace = 0;

	if (*s == NULL)
		return NULL;

	old = *s;

175
	*s = strpbrk(*s, WHITESPACE QUOTE "=");
Damien Miller's avatar
Damien Miller committed
176 177 178
	if (*s == NULL)
		return (old);

179 180 181 182 183 184 185
	if (*s[0] == '\"') {
		memmove(*s, *s + 1, strlen(*s)); /* move nul too */
		/* Find matching quote */
		if ((*s = strpbrk(*s, QUOTE)) == NULL) {
			return (NULL);		/* no matching quote */
		} else {
			*s[0] = '\0';
186
			*s += strspn(*s + 1, WHITESPACE) + 1;
187 188 189 190
			return (old);
		}
	}

Damien Miller's avatar
Damien Miller committed
191 192 193 194 195
	/* Allow only one '=' to be skipped */
	if (*s[0] == '=')
		wspace = 1;
	*s[0] = '\0';

196
	/* Skip any extra whitespace after first token */
Damien Miller's avatar
Damien Miller committed
197 198 199 200 201 202
	*s += strspn(*s + 1, WHITESPACE) + 1;
	if (*s[0] == '=' && !wspace)
		*s += strspn(*s + 1, WHITESPACE) + 1;

	return (old);
}
203

204 205 206
struct passwd *
pwcopy(struct passwd *pw)
{
207
	struct passwd *copy = xcalloc(1, sizeof(*copy));
208

209 210
	copy->pw_name = xstrdup(pw->pw_name);
	copy->pw_passwd = xstrdup(pw->pw_passwd);
211
#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
212
	copy->pw_gecos = xstrdup(pw->pw_gecos);
213
#endif
214 215
	copy->pw_uid = pw->pw_uid;
	copy->pw_gid = pw->pw_gid;
216
#ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
217
	copy->pw_expire = pw->pw_expire;
218
#endif
219
#ifdef HAVE_STRUCT_PASSWD_PW_CHANGE
220
	copy->pw_change = pw->pw_change;
221
#endif
222
#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
223
	copy->pw_class = xstrdup(pw->pw_class);
224
#endif
225 226 227 228 229
	copy->pw_dir = xstrdup(pw->pw_dir);
	copy->pw_shell = xstrdup(pw->pw_shell);
	return copy;
}

230 231
/*
 * Convert ASCII string to TCP/IP port number.
232 233
 * Port must be >=0 and <=65535.
 * Return -1 if invalid.
234 235 236
 */
int
a2port(const char *s)
237
{
238 239
	long long port;
	const char *errstr;
240

241 242 243 244
	port = strtonum(s, 0, 65535, &errstr);
	if (errstr != NULL)
		return -1;
	return (int)port;
245 246
}

247 248 249 250 251 252 253 254
int
a2tun(const char *s, int *remote)
{
	const char *errstr = NULL;
	char *sp, *ep;
	int tun;

	if (remote != NULL) {
255
		*remote = SSH_TUNID_ANY;
256 257
		sp = xstrdup(s);
		if ((ep = strchr(sp, ':')) == NULL) {
258
			free(sp);
259 260 261 262 263
			return (a2tun(s, NULL));
		}
		ep[0] = '\0'; ep++;
		*remote = a2tun(ep, NULL);
		tun = a2tun(sp, NULL);
264
		free(sp);
265
		return (*remote == SSH_TUNID_ERR ? *remote : tun);
266 267 268
	}

	if (strcasecmp(s, "any") == 0)
269
		return (SSH_TUNID_ANY);
270

271 272 273
	tun = strtonum(s, 0, SSH_TUNID_MAX, &errstr);
	if (errstr != NULL)
		return (SSH_TUNID_ERR);
274 275 276 277

	return (tun);
}

278 279 280 281 282 283
#define SECONDS		1
#define MINUTES		(SECONDS * 60)
#define HOURS		(MINUTES * 60)
#define DAYS		(HOURS * 24)
#define WEEKS		(DAYS * 7)

284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
/*
 * Convert a time string into seconds; format is
 * a sequence of:
 *      time[qualifier]
 *
 * Valid time qualifiers are:
 *      <none>  seconds
 *      s|S     seconds
 *      m|M     minutes
 *      h|H     hours
 *      d|D     days
 *      w|W     weeks
 *
 * Examples:
 *      90m     90 minutes
 *      1h30m   90 minutes
 *      2d      2 days
 *      1w      1 week
 *
 * Return -1 if time string is invalid.
 */
long
convtime(const char *s)
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
{
	long total, secs;
	const char *p;
	char *endp;

	errno = 0;
	total = 0;
	p = s;

	if (p == NULL || *p == '\0')
		return -1;

	while (*p) {
		secs = strtol(p, &endp, 10);
		if (p == endp ||
		    (errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) ||
		    secs < 0)
			return -1;

		switch (*endp++) {
		case '\0':
			endp--;
329
			break;
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
		case 's':
		case 'S':
			break;
		case 'm':
		case 'M':
			secs *= MINUTES;
			break;
		case 'h':
		case 'H':
			secs *= HOURS;
			break;
		case 'd':
		case 'D':
			secs *= DAYS;
			break;
		case 'w':
		case 'W':
			secs *= WEEKS;
			break;
		default:
			return -1;
		}
		total += secs;
		if (total < 0)
			return -1;
		p = endp;
	}

	return total;
}

361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
/*
 * Returns a standardized host+port identifier string.
 * Caller must free returned string.
 */
char *
put_host_port(const char *host, u_short port)
{
	char *hoststr;

	if (port == 0 || port == SSH_DEFAULT_PORT)
		return(xstrdup(host));
	if (asprintf(&hoststr, "[%s]:%d", host, (int)port) < 0)
		fatal("put_host_port: asprintf: %s", strerror(errno));
	debug3("put_host_port: %s", hoststr);
	return hoststr;
}

378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
/*
 * Search for next delimiter between hostnames/addresses and ports.
 * Argument may be modified (for termination).
 * Returns *cp if parsing succeeds.
 * *cp is set to the start of the next delimiter, if one was found.
 * If this is the last field, *cp is set to NULL.
 */
char *
hpdelim(char **cp)
{
	char *s, *old;

	if (cp == NULL || *cp == NULL)
		return NULL;

	old = s = *cp;
	if (*s == '[') {
		if ((s = strchr(s, ']')) == NULL)
			return NULL;
		else
			s++;
	} else if ((s = strpbrk(s, ":/")) == NULL)
		s = *cp + strlen(*cp); /* skip to end (see first case below) */

	switch (*s) {
	case '\0':
		*cp = NULL;	/* no more fields*/
		break;
406

407 408 409 410 411
	case ':':
	case '/':
		*s = '\0';	/* terminate */
		*cp = s + 1;
		break;
412

413 414 415 416 417 418 419
	default:
		return NULL;
	}

	return old;
}

420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435
char *
cleanhostname(char *host)
{
	if (*host == '[' && host[strlen(host) - 1] == ']') {
		host[strlen(host) - 1] = '\0';
		return (host + 1);
	} else
		return host;
}

char *
colon(char *cp)
{
	int flag = 0;

	if (*cp == ':')		/* Leading colon is part of file name. */
Damien Miller's avatar
Damien Miller committed
436
		return NULL;
437 438 439 440 441 442 443 444 445 446 447
	if (*cp == '[')
		flag = 1;

	for (; *cp; ++cp) {
		if (*cp == '@' && *(cp+1) == '[')
			flag = 1;
		if (*cp == ']' && *(cp+1) == ':' && flag)
			return (cp+1);
		if (*cp == ':' && !flag)
			return (cp);
		if (*cp == '/')
Damien Miller's avatar
Damien Miller committed
448
			return NULL;
449
	}
Damien Miller's avatar
Damien Miller committed
450
	return NULL;
451 452
}

453
/* function to assist building execv() arguments */
454 455 456 457
void
addargs(arglist *args, char *fmt, ...)
{
	va_list ap;
458
	char *cp;
459
	u_int nalloc;
460
	int r;
461 462

	va_start(ap, fmt);
463
	r = vasprintf(&cp, fmt, ap);
464
	va_end(ap);
465 466
	if (r == -1)
		fatal("addargs: argument too long");
467

468
	nalloc = args->nalloc;
469
	if (args->list == NULL) {
470
		nalloc = 32;
471
		args->num = 0;
472 473
	} else if (args->num+2 >= nalloc)
		nalloc *= 2;
474

475
	args->list = xrealloc(args->list, nalloc, sizeof(char *));
476
	args->nalloc = nalloc;
477
	args->list[args->num++] = cp;
478 479
	args->list[args->num] = NULL;
}
480

481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496
void
replacearg(arglist *args, u_int which, char *fmt, ...)
{
	va_list ap;
	char *cp;
	int r;

	va_start(ap, fmt);
	r = vasprintf(&cp, fmt, ap);
	va_end(ap);
	if (r == -1)
		fatal("replacearg: argument too long");

	if (which >= args->num)
		fatal("replacearg: tried to replace invalid arg %d >= %d",
		    which, args->num);
497
	free(args->list[which]);
498 499 500 501 502 503 504 505 506 507
	args->list[which] = cp;
}

void
freeargs(arglist *args)
{
	u_int i;

	if (args->list != NULL) {
		for (i = 0; i < args->num; i++)
508 509
			free(args->list[i]);
		free(args->list);
510 511 512 513 514
		args->nalloc = args->num = 0;
		args->list = NULL;
	}
}

515 516 517 518 519 520 521
/*
 * Expands tildes in the file name.  Returns data allocated by xmalloc.
 * Warning: this calls getpw*.
 */
char *
tilde_expand_filename(const char *filename, uid_t uid)
{
522 523
	const char *path, *sep;
	char user[128], *ret;
524
	struct passwd *pw;
525
	u_int len, slash;
526 527 528 529 530 531 532

	if (*filename != '~')
		return (xstrdup(filename));
	filename++;

	path = strchr(filename, '/');
	if (path != NULL && path > filename) {		/* ~user/path */
533 534
		slash = path - filename;
		if (slash > sizeof(user) - 1)
535
			fatal("tilde_expand_filename: ~username too long");
536 537
		memcpy(user, filename, slash);
		user[slash] = '\0';
538 539 540
		if ((pw = getpwnam(user)) == NULL)
			fatal("tilde_expand_filename: No such user %s", user);
	} else if ((pw = getpwuid(uid)) == NULL)	/* ~/path */
541
		fatal("tilde_expand_filename: No such uid %ld", (long)uid);
542 543 544

	/* Make sure directory has a trailing '/' */
	len = strlen(pw->pw_dir);
545
	if (len == 0 || pw->pw_dir[len - 1] != '/')
546 547 548
		sep = "/";
	else
		sep = "";
549 550 551 552

	/* Skip leading '/' from specified path */
	if (path != NULL)
		filename = path + 1;
553 554

	if (xasprintf(&ret, "%s%s%s", pw->pw_dir, sep, filename) >= MAXPATHLEN)
555 556
		fatal("tilde_expand_filename: Path too long");

557
	return (ret);
558 559
}

560 561 562
/*
 * Expand a string with a set of %[char] escapes. A number of escapes may be
 * specified as (char *escape_chars, char *replacement) pairs. The list must
563
 * be terminated by a NULL escape_char. Returns replaced string in memory
564 565 566 567 568 569
 * allocated by xmalloc.
 */
char *
percent_expand(const char *string, ...)
{
#define EXPAND_MAX_KEYS	16
570
	u_int num_keys, i, j;
571 572 573 574 575 576 577 578 579 580 581 582 583 584 585
	struct {
		const char *key;
		const char *repl;
	} keys[EXPAND_MAX_KEYS];
	char buf[4096];
	va_list ap;

	/* Gather keys */
	va_start(ap, string);
	for (num_keys = 0; num_keys < EXPAND_MAX_KEYS; num_keys++) {
		keys[num_keys].key = va_arg(ap, char *);
		if (keys[num_keys].key == NULL)
			break;
		keys[num_keys].repl = va_arg(ap, char *);
		if (keys[num_keys].repl == NULL)
586
			fatal("%s: NULL replacement", __func__);
587
	}
588 589
	if (num_keys == EXPAND_MAX_KEYS && va_arg(ap, char *) != NULL)
		fatal("%s: too many keys", __func__);
590 591 592 593 594 595 596 597 598
	va_end(ap);

	/* Expand string */
	*buf = '\0';
	for (i = 0; *string != '\0'; string++) {
		if (*string != '%') {
 append:
			buf[i++] = *string;
			if (i >= sizeof(buf))
599
				fatal("%s: string too long", __func__);
600 601 602 603
			buf[i] = '\0';
			continue;
		}
		string++;
604
		/* %% case */
605 606 607 608 609 610
		if (*string == '%')
			goto append;
		for (j = 0; j < num_keys; j++) {
			if (strchr(keys[j].key, *string) != NULL) {
				i = strlcat(buf, keys[j].repl, sizeof(buf));
				if (i >= sizeof(buf))
611
					fatal("%s: string too long", __func__);
612 613 614 615
				break;
			}
		}
		if (j >= num_keys)
616
			fatal("%s: unknown key %%%c", __func__, *string);
617 618 619 620 621
	}
	return (xstrdup(buf));
#undef EXPAND_MAX_KEYS
}

622 623 624 625 626 627
/*
 * Read an entire line from a public key file into a static buffer, discarding
 * lines that exceed the buffer size.  Returns 0 on success, -1 on failure.
 */
int
read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz,
628
   u_long *lineno)
629 630
{
	while (fgets(buf, bufsz, f) != NULL) {
631 632
		if (buf[0] == '\0')
			continue;
633 634 635 636
		(*lineno)++;
		if (buf[strlen(buf) - 1] == '\n' || feof(f)) {
			return 0;
		} else {
637 638
			debug("%s: %s line %lu exceeds size limit", __func__,
			    filename, *lineno);
639
			/* discard remainder of line */
640
			while (fgetc(f) != '\n' && !feof(f))
641 642 643 644 645
				;	/* nothing */
		}
	}
	return -1;
}
646

647
int
648
tun_open(int tun, int mode)
649
{
650 651
#if defined(CUSTOM_SYS_TUN_OPEN)
	return (sys_tun_open(tun, mode));
652
#elif defined(SSH_TUN_OPENBSD)
653
	struct ifreq ifr;
654
	char name[100];
655
	int fd = -1, sock;
656

657 658
	/* Open the tunnel device */
	if (tun <= SSH_TUNID_MAX) {
659
		snprintf(name, sizeof(name), "/dev/tun%d", tun);
660 661 662 663 664 665
		fd = open(name, O_RDWR);
	} else if (tun == SSH_TUNID_ANY) {
		for (tun = 100; tun >= 0; tun--) {
			snprintf(name, sizeof(name), "/dev/tun%d", tun);
			if ((fd = open(name, O_RDWR)) >= 0)
				break;
666 667
		}
	} else {
668
		debug("%s: invalid tunnel %u", __func__, tun);
669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685
		return (-1);
	}

	if (fd < 0) {
		debug("%s: %s open failed: %s", __func__, name, strerror(errno));
		return (-1);
	}

	debug("%s: %s mode %d fd %d", __func__, name, mode, fd);

	/* Set the tunnel device operation mode */
	snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "tun%d", tun);
	if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
		goto failed;

	if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)
		goto failed;
686 687 688 689

	/* Set interface mode */
	ifr.ifr_flags &= ~IFF_UP;
	if (mode == SSH_TUNMODE_ETHERNET)
690
		ifr.ifr_flags |= IFF_LINK0;
691 692 693 694 695 696
	else
		ifr.ifr_flags &= ~IFF_LINK0;
	if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1)
		goto failed;

	/* Bring interface up */
697 698 699 700 701 702 703 704 705 706 707 708 709 710
	ifr.ifr_flags |= IFF_UP;
	if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1)
		goto failed;

	close(sock);
	return (fd);

 failed:
	if (fd >= 0)
		close(fd);
	if (sock >= 0)
		close(sock);
	debug("%s: failed to set %s mode %d: %s", __func__, name,
	    mode, strerror(errno));
711
	return (-1);
712 713 714 715
#else
	error("Tunnel interfaces are not supported on this platform");
	return (-1);
#endif
716 717
}

718 719 720
void
sanitise_stdfd(void)
{
721
	int nullfd, dupfd;
722

723
	if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) {
724 725
		fprintf(stderr, "Couldn't open /dev/null: %s\n",
		    strerror(errno));
726 727
		exit(1);
	}
728 729 730 731 732
	while (++dupfd <= 2) {
		/* Only clobber closed fds */
		if (fcntl(dupfd, F_GETFL, 0) >= 0)
			continue;
		if (dup2(nullfd, dupfd) == -1) {
733
			fprintf(stderr, "dup2: %s\n", strerror(errno));
734 735 736 737 738 739 740
			exit(1);
		}
	}
	if (nullfd > 2)
		close(nullfd);
}

741
char *
742
tohex(const void *vp, size_t l)
743
{
744
	const u_char *p = (const u_char *)vp;
745
	char b[3], *r;
746 747 748 749
	size_t i, hl;

	if (l > 65536)
		return xstrdup("tohex: length > 65536");
750 751

	hl = l * 2 + 1;
752
	r = xcalloc(1, hl);
753
	for (i = 0; i < l; i++) {
754
		snprintf(b, sizeof(b), "%02x", p[i]);
755 756 757 758 759
		strlcat(r, b, hl);
	}
	return (r);
}

760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791
u_int64_t
get_u64(const void *vp)
{
	const u_char *p = (const u_char *)vp;
	u_int64_t v;

	v  = (u_int64_t)p[0] << 56;
	v |= (u_int64_t)p[1] << 48;
	v |= (u_int64_t)p[2] << 40;
	v |= (u_int64_t)p[3] << 32;
	v |= (u_int64_t)p[4] << 24;
	v |= (u_int64_t)p[5] << 16;
	v |= (u_int64_t)p[6] << 8;
	v |= (u_int64_t)p[7];

	return (v);
}

u_int32_t
get_u32(const void *vp)
{
	const u_char *p = (const u_char *)vp;
	u_int32_t v;

	v  = (u_int32_t)p[0] << 24;
	v |= (u_int32_t)p[1] << 16;
	v |= (u_int32_t)p[2] << 8;
	v |= (u_int32_t)p[3];

	return (v);
}

792 793 794 795 796 797 798 799 800 801 802 803 804 805
u_int32_t
get_u32_le(const void *vp)
{
	const u_char *p = (const u_char *)vp;
	u_int32_t v;

	v  = (u_int32_t)p[0];
	v |= (u_int32_t)p[1] << 8;
	v |= (u_int32_t)p[2] << 16;
	v |= (u_int32_t)p[3] << 24;

	return (v);
}

806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843
u_int16_t
get_u16(const void *vp)
{
	const u_char *p = (const u_char *)vp;
	u_int16_t v;

	v  = (u_int16_t)p[0] << 8;
	v |= (u_int16_t)p[1];

	return (v);
}

void
put_u64(void *vp, u_int64_t v)
{
	u_char *p = (u_char *)vp;

	p[0] = (u_char)(v >> 56) & 0xff;
	p[1] = (u_char)(v >> 48) & 0xff;
	p[2] = (u_char)(v >> 40) & 0xff;
	p[3] = (u_char)(v >> 32) & 0xff;
	p[4] = (u_char)(v >> 24) & 0xff;
	p[5] = (u_char)(v >> 16) & 0xff;
	p[6] = (u_char)(v >> 8) & 0xff;
	p[7] = (u_char)v & 0xff;
}

void
put_u32(void *vp, u_int32_t v)
{
	u_char *p = (u_char *)vp;

	p[0] = (u_char)(v >> 24) & 0xff;
	p[1] = (u_char)(v >> 16) & 0xff;
	p[2] = (u_char)(v >> 8) & 0xff;
	p[3] = (u_char)v & 0xff;
}

844 845 846 847 848 849 850 851 852 853
void
put_u32_le(void *vp, u_int32_t v)
{
	u_char *p = (u_char *)vp;

	p[0] = (u_char)v & 0xff;
	p[1] = (u_char)(v >> 8) & 0xff;
	p[2] = (u_char)(v >> 16) & 0xff;
	p[3] = (u_char)(v >> 24) & 0xff;
}
854 855 856 857 858 859 860 861 862

void
put_u16(void *vp, u_int16_t v)
{
	u_char *p = (u_char *)vp;

	p[0] = (u_char)(v >> 8) & 0xff;
	p[1] = (u_char)v & 0xff;
}
863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882

void
ms_subtract_diff(struct timeval *start, int *ms)
{
	struct timeval diff, finish;

	gettimeofday(&finish, NULL);
	timersub(&finish, start, &diff);	
	*ms -= (diff.tv_sec * 1000) + (diff.tv_usec / 1000);
}

void
ms_to_timeval(struct timeval *tv, int ms)
{
	if (ms < 0)
		ms = 0;
	tv->tv_sec = ms / 1000;
	tv->tv_usec = (ms % 1000) * 1000;
}

883 884 885
time_t
monotime(void)
{
886 887
#if defined(HAVE_CLOCK_GETTIME) && \
    (defined(CLOCK_MONOTONIC) || defined(CLOCK_BOOTTIME))
888
	struct timespec ts;
889
	static int gettime_failed = 0;
890

891
	if (!gettime_failed) {
892 893 894 895 896
#if defined(CLOCK_BOOTTIME)
		if (clock_gettime(CLOCK_BOOTTIME, &ts) == 0)
			return (ts.tv_sec);
#endif
#if defined(CLOCK_MONOTONIC)
897 898
		if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
			return (ts.tv_sec);
899
#endif
900 901 902
		debug3("clock_gettime: %s", strerror(errno));
		gettime_failed = 1;
	}
903
#endif /* HAVE_CLOCK_GETTIME && (CLOCK_MONOTONIC || CLOCK_BOOTTIME */
904

905
	return time(NULL);
906 907
}

908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970
void
bandwidth_limit_init(struct bwlimit *bw, u_int64_t kbps, size_t buflen)
{
	bw->buflen = buflen;
	bw->rate = kbps;
	bw->thresh = bw->rate;
	bw->lamt = 0;
	timerclear(&bw->bwstart);
	timerclear(&bw->bwend);
}	

/* Callback from read/write loop to insert bandwidth-limiting delays */
void
bandwidth_limit(struct bwlimit *bw, size_t read_len)
{
	u_int64_t waitlen;
	struct timespec ts, rm;

	if (!timerisset(&bw->bwstart)) {
		gettimeofday(&bw->bwstart, NULL);
		return;
	}

	bw->lamt += read_len;
	if (bw->lamt < bw->thresh)
		return;

	gettimeofday(&bw->bwend, NULL);
	timersub(&bw->bwend, &bw->bwstart, &bw->bwend);
	if (!timerisset(&bw->bwend))
		return;

	bw->lamt *= 8;
	waitlen = (double)1000000L * bw->lamt / bw->rate;

	bw->bwstart.tv_sec = waitlen / 1000000L;
	bw->bwstart.tv_usec = waitlen % 1000000L;

	if (timercmp(&bw->bwstart, &bw->bwend, >)) {
		timersub(&bw->bwstart, &bw->bwend, &bw->bwend);

		/* Adjust the wait time */
		if (bw->bwend.tv_sec) {
			bw->thresh /= 2;
			if (bw->thresh < bw->buflen / 4)
				bw->thresh = bw->buflen / 4;
		} else if (bw->bwend.tv_usec < 10000) {
			bw->thresh *= 2;
			if (bw->thresh > bw->buflen * 8)
				bw->thresh = bw->buflen * 8;
		}

		TIMEVAL_TO_TIMESPEC(&bw->bwend, &ts);
		while (nanosleep(&ts, &rm) == -1) {
			if (errno != EINTR)
				break;
			ts = rm;
		}
	}

	bw->lamt = 0;
	gettimeofday(&bw->bwstart, NULL);
}
971

972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988
/* Make a template filename for mk[sd]temp() */
void
mktemp_proto(char *s, size_t len)
{
	const char *tmpdir;
	int r;

	if ((tmpdir = getenv("TMPDIR")) != NULL) {
		r = snprintf(s, len, "%s/ssh-XXXXXXXXXXXX", tmpdir);
		if (r > 0 && (size_t)r < len)
			return;
	}
	r = snprintf(s, len, "/tmp/ssh-XXXXXXXXXXXX");
	if (r < 0 || (size_t)r >= len)
		fatal("%s: template string too short", __func__);
}

989 990 991 992 993 994 995
static const struct {
	const char *name;
	int value;
} ipqos[] = {
	{ "af11", IPTOS_DSCP_AF11 },
	{ "af12", IPTOS_DSCP_AF12 },
	{ "af13", IPTOS_DSCP_AF13 },
996
	{ "af21", IPTOS_DSCP_AF21 },
997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039
	{ "af22", IPTOS_DSCP_AF22 },
	{ "af23", IPTOS_DSCP_AF23 },
	{ "af31", IPTOS_DSCP_AF31 },
	{ "af32", IPTOS_DSCP_AF32 },
	{ "af33", IPTOS_DSCP_AF33 },
	{ "af41", IPTOS_DSCP_AF41 },
	{ "af42", IPTOS_DSCP_AF42 },
	{ "af43", IPTOS_DSCP_AF43 },
	{ "cs0", IPTOS_DSCP_CS0 },
	{ "cs1", IPTOS_DSCP_CS1 },
	{ "cs2", IPTOS_DSCP_CS2 },
	{ "cs3", IPTOS_DSCP_CS3 },
	{ "cs4", IPTOS_DSCP_CS4 },
	{ "cs5", IPTOS_DSCP_CS5 },
	{ "cs6", IPTOS_DSCP_CS6 },
	{ "cs7", IPTOS_DSCP_CS7 },
	{ "ef", IPTOS_DSCP_EF },
	{ "lowdelay", IPTOS_LOWDELAY },
	{ "throughput", IPTOS_THROUGHPUT },
	{ "reliability", IPTOS_RELIABILITY },
	{ NULL, -1 }
};

int
parse_ipqos(const char *cp)
{
	u_int i;
	char *ep;
	long val;

	if (cp == NULL)
		return -1;
	for (i = 0; ipqos[i].name != NULL; i++) {
		if (strcasecmp(cp, ipqos[i].name) == 0)
			return ipqos[i].value;
	}
	/* Try parsing as an integer */
	val = strtol(cp, &ep, 0);
	if (*cp == '\0' || *ep != '\0' || val < 0 || val > 255)
		return -1;
	return val;
}

1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052
const char *
iptos2str(int iptos)
{
	int i;
	static char iptos_str[sizeof "0xff"];

	for (i = 0; ipqos[i].name != NULL; i++) {
		if (ipqos[i].value == iptos)
			return ipqos[i].name;
	}
	snprintf(iptos_str, sizeof iptos_str, "0x%02x", iptos);
	return iptos_str;
}
1053 1054 1055 1056 1057 1058 1059

void
lowercase(char *s)
{
	for (; *s; s++)
		*s = tolower((u_char)*s);
}
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105

int
unix_listener(const char *path, int backlog, int unlink_first)
{
	struct sockaddr_un sunaddr;
	int saved_errno, sock;

	memset(&sunaddr, 0, sizeof(sunaddr));
	sunaddr.sun_family = AF_UNIX;
	if (strlcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path)) >= sizeof(sunaddr.sun_path)) {
		error("%s: \"%s\" too long for Unix domain socket", __func__,
		    path);
		errno = ENAMETOOLONG;
		return -1;
	}

	sock = socket(PF_UNIX, SOCK_STREAM, 0);
	if (sock < 0) {
		saved_errno = errno;
		error("socket: %.100s", strerror(errno));
		errno = saved_errno;
		return -1;
	}
	if (unlink_first == 1) {
		if (unlink(path) != 0 && errno != ENOENT)
			error("unlink(%s): %.100s", path, strerror(errno));
	}
	if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
		saved_errno = errno;
		error("bind: %.100s", strerror(errno));
		close(sock);
		error("%s: cannot bind to path: %s", __func__, path);
		errno = saved_errno;
		return -1;
	}
	if (listen(sock, backlog) < 0) {
		saved_errno = errno;
		error("listen: %.100s", strerror(errno));
		close(sock);
		unlink(path);
		error("%s: cannot listen on path: %s", __func__, path);
		errno = saved_errno;
		return -1;
	}
	return sock;
}
1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116
void
sock_set_v6only(int s)
{
#ifdef IPV6_V6ONLY
	int on = 1;

	debug3("%s: set socket %d IPV6_V6ONLY", __func__, s);
	if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1)
		error("setsockopt IPV6_V6ONLY: %s", strerror(errno));
#endif
}