Home | History | Annotate | Line # | Download | only in dist
misc.c revision 1.3
      1  1.3   jnemeth /*	$NetBSD: misc.c,v 1.3 2010/05/10 20:28:05 jnemeth Exp $	*/
      2  1.1  christos /* $OpenBSD: misc.c,v 1.71 2009/02/21 19:32:04 tobias Exp $ */
      3  1.1  christos /*
      4  1.1  christos  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
      5  1.1  christos  * Copyright (c) 2005,2006 Damien Miller.  All rights reserved.
      6  1.1  christos  *
      7  1.1  christos  * Redistribution and use in source and binary forms, with or without
      8  1.1  christos  * modification, are permitted provided that the following conditions
      9  1.1  christos  * are met:
     10  1.1  christos  * 1. Redistributions of source code must retain the above copyright
     11  1.1  christos  *    notice, this list of conditions and the following disclaimer.
     12  1.1  christos  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.1  christos  *    notice, this list of conditions and the following disclaimer in the
     14  1.1  christos  *    documentation and/or other materials provided with the distribution.
     15  1.1  christos  *
     16  1.1  christos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  1.1  christos  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  1.1  christos  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  1.1  christos  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  1.1  christos  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21  1.1  christos  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     22  1.1  christos  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     23  1.1  christos  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24  1.1  christos  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     25  1.1  christos  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  1.1  christos  */
     27  1.1  christos 
     28  1.2  christos #include "includes.h"
     29  1.3   jnemeth __RCSID("$NetBSD: misc.c,v 1.3 2010/05/10 20:28:05 jnemeth Exp $");
     30  1.1  christos #include <sys/types.h>
     31  1.1  christos #include <sys/ioctl.h>
     32  1.1  christos #include <sys/socket.h>
     33  1.1  christos #include <sys/param.h>
     34  1.1  christos 
     35  1.1  christos #include <net/if.h>
     36  1.2  christos #include <net/if_tun.h>
     37  1.1  christos #include <netinet/in.h>
     38  1.1  christos #include <netinet/tcp.h>
     39  1.1  christos 
     40  1.1  christos #include <errno.h>
     41  1.1  christos #include <fcntl.h>
     42  1.1  christos #include <netdb.h>
     43  1.1  christos #include <paths.h>
     44  1.1  christos #include <pwd.h>
     45  1.1  christos #include <stdarg.h>
     46  1.1  christos #include <stdio.h>
     47  1.1  christos #include <stdlib.h>
     48  1.1  christos #include <string.h>
     49  1.1  christos #include <unistd.h>
     50  1.1  christos 
     51  1.1  christos #include "xmalloc.h"
     52  1.1  christos #include "misc.h"
     53  1.1  christos #include "log.h"
     54  1.1  christos #include "ssh.h"
     55  1.1  christos 
     56  1.1  christos /* remove newline at end of string */
     57  1.1  christos char *
     58  1.1  christos chop(char *s)
     59  1.1  christos {
     60  1.1  christos 	char *t = s;
     61  1.1  christos 	while (*t) {
     62  1.1  christos 		if (*t == '\n' || *t == '\r') {
     63  1.1  christos 			*t = '\0';
     64  1.1  christos 			return s;
     65  1.1  christos 		}
     66  1.1  christos 		t++;
     67  1.1  christos 	}
     68  1.1  christos 	return s;
     69  1.1  christos 
     70  1.1  christos }
     71  1.1  christos 
     72  1.1  christos /* set/unset filedescriptor to non-blocking */
     73  1.1  christos int
     74  1.1  christos set_nonblock(int fd)
     75  1.1  christos {
     76  1.1  christos 	int val;
     77  1.1  christos 
     78  1.1  christos 	val = fcntl(fd, F_GETFL, 0);
     79  1.1  christos 	if (val < 0) {
     80  1.1  christos 		error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
     81  1.1  christos 		return (-1);
     82  1.1  christos 	}
     83  1.1  christos 	if (val & O_NONBLOCK) {
     84  1.1  christos 		debug3("fd %d is O_NONBLOCK", fd);
     85  1.1  christos 		return (0);
     86  1.1  christos 	}
     87  1.1  christos 	debug2("fd %d setting O_NONBLOCK", fd);
     88  1.1  christos 	val |= O_NONBLOCK;
     89  1.1  christos 	if (fcntl(fd, F_SETFL, val) == -1) {
     90  1.1  christos 		debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", fd,
     91  1.1  christos 		    strerror(errno));
     92  1.1  christos 		return (-1);
     93  1.1  christos 	}
     94  1.1  christos 	return (0);
     95  1.1  christos }
     96  1.1  christos 
     97  1.1  christos int
     98  1.1  christos unset_nonblock(int fd)
     99  1.1  christos {
    100  1.1  christos 	int val;
    101  1.1  christos 
    102  1.1  christos 	val = fcntl(fd, F_GETFL, 0);
    103  1.1  christos 	if (val < 0) {
    104  1.1  christos 		error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
    105  1.1  christos 		return (-1);
    106  1.1  christos 	}
    107  1.1  christos 	if (!(val & O_NONBLOCK)) {
    108  1.1  christos 		debug3("fd %d is not O_NONBLOCK", fd);
    109  1.1  christos 		return (0);
    110  1.1  christos 	}
    111  1.1  christos 	debug("fd %d clearing O_NONBLOCK", fd);
    112  1.1  christos 	val &= ~O_NONBLOCK;
    113  1.1  christos 	if (fcntl(fd, F_SETFL, val) == -1) {
    114  1.1  christos 		debug("fcntl(%d, F_SETFL, ~O_NONBLOCK): %s",
    115  1.1  christos 		    fd, strerror(errno));
    116  1.1  christos 		return (-1);
    117  1.1  christos 	}
    118  1.1  christos 	return (0);
    119  1.1  christos }
    120  1.1  christos 
    121  1.1  christos const char *
    122  1.1  christos ssh_gai_strerror(int gaierr)
    123  1.1  christos {
    124  1.1  christos 	if (gaierr == EAI_SYSTEM)
    125  1.1  christos 		return strerror(errno);
    126  1.1  christos 	return gai_strerror(gaierr);
    127  1.1  christos }
    128  1.1  christos 
    129  1.1  christos /* disable nagle on socket */
    130  1.1  christos void
    131  1.1  christos set_nodelay(int fd)
    132  1.1  christos {
    133  1.1  christos 	int opt;
    134  1.1  christos 	socklen_t optlen;
    135  1.1  christos 
    136  1.1  christos 	optlen = sizeof opt;
    137  1.1  christos 	if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) {
    138  1.1  christos 		debug("getsockopt TCP_NODELAY: %.100s", strerror(errno));
    139  1.1  christos 		return;
    140  1.1  christos 	}
    141  1.1  christos 	if (opt == 1) {
    142  1.1  christos 		debug2("fd %d is TCP_NODELAY", fd);
    143  1.1  christos 		return;
    144  1.1  christos 	}
    145  1.1  christos 	opt = 1;
    146  1.1  christos 	debug2("fd %d setting TCP_NODELAY", fd);
    147  1.1  christos 	if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof opt) == -1)
    148  1.1  christos 		error("setsockopt TCP_NODELAY: %.100s", strerror(errno));
    149  1.1  christos }
    150  1.1  christos 
    151  1.1  christos /* Characters considered whitespace in strsep calls. */
    152  1.1  christos #define WHITESPACE " \t\r\n"
    153  1.1  christos #define QUOTE	"\""
    154  1.1  christos 
    155  1.1  christos /* return next token in configuration line */
    156  1.1  christos char *
    157  1.1  christos strdelim(char **s)
    158  1.1  christos {
    159  1.1  christos 	char *old;
    160  1.1  christos 	int wspace = 0;
    161  1.1  christos 
    162  1.1  christos 	if (*s == NULL)
    163  1.1  christos 		return NULL;
    164  1.1  christos 
    165  1.1  christos 	old = *s;
    166  1.1  christos 
    167  1.1  christos 	*s = strpbrk(*s, WHITESPACE QUOTE "=");
    168  1.1  christos 	if (*s == NULL)
    169  1.1  christos 		return (old);
    170  1.1  christos 
    171  1.1  christos 	if (*s[0] == '\"') {
    172  1.1  christos 		memmove(*s, *s + 1, strlen(*s)); /* move nul too */
    173  1.1  christos 		/* Find matching quote */
    174  1.1  christos 		if ((*s = strpbrk(*s, QUOTE)) == NULL) {
    175  1.1  christos 			return (NULL);		/* no matching quote */
    176  1.1  christos 		} else {
    177  1.1  christos 			*s[0] = '\0';
    178  1.1  christos 			return (old);
    179  1.1  christos 		}
    180  1.1  christos 	}
    181  1.1  christos 
    182  1.1  christos 	/* Allow only one '=' to be skipped */
    183  1.1  christos 	if (*s[0] == '=')
    184  1.1  christos 		wspace = 1;
    185  1.1  christos 	*s[0] = '\0';
    186  1.1  christos 
    187  1.1  christos 	/* Skip any extra whitespace after first token */
    188  1.1  christos 	*s += strspn(*s + 1, WHITESPACE) + 1;
    189  1.1  christos 	if (*s[0] == '=' && !wspace)
    190  1.1  christos 		*s += strspn(*s + 1, WHITESPACE) + 1;
    191  1.1  christos 
    192  1.1  christos 	return (old);
    193  1.1  christos }
    194  1.1  christos 
    195  1.1  christos struct passwd *
    196  1.1  christos pwcopy(struct passwd *pw)
    197  1.1  christos {
    198  1.1  christos 	struct passwd *copy = xcalloc(1, sizeof(*copy));
    199  1.1  christos 
    200  1.1  christos 	copy->pw_name = xstrdup(pw->pw_name);
    201  1.1  christos 	copy->pw_passwd = xstrdup(pw->pw_passwd);
    202  1.1  christos 	copy->pw_gecos = xstrdup(pw->pw_gecos);
    203  1.1  christos 	copy->pw_uid = pw->pw_uid;
    204  1.1  christos 	copy->pw_gid = pw->pw_gid;
    205  1.1  christos 	copy->pw_expire = pw->pw_expire;
    206  1.1  christos 	copy->pw_change = pw->pw_change;
    207  1.1  christos 	copy->pw_class = xstrdup(pw->pw_class);
    208  1.1  christos 	copy->pw_dir = xstrdup(pw->pw_dir);
    209  1.1  christos 	copy->pw_shell = xstrdup(pw->pw_shell);
    210  1.1  christos 	return copy;
    211  1.1  christos }
    212  1.1  christos 
    213  1.1  christos /*
    214  1.1  christos  * Convert ASCII string to TCP/IP port number.
    215  1.1  christos  * Port must be >=0 and <=65535.
    216  1.1  christos  * Return -1 if invalid.
    217  1.1  christos  */
    218  1.1  christos int
    219  1.1  christos a2port(const char *s)
    220  1.1  christos {
    221  1.1  christos 	long long port;
    222  1.1  christos 	const char *errstr;
    223  1.1  christos 
    224  1.1  christos 	port = strtonum(s, 0, 65535, &errstr);
    225  1.1  christos 	if (errstr != NULL)
    226  1.1  christos 		return -1;
    227  1.1  christos 	return (int)port;
    228  1.1  christos }
    229  1.1  christos 
    230  1.1  christos int
    231  1.1  christos a2tun(const char *s, int *remote)
    232  1.1  christos {
    233  1.1  christos 	const char *errstr = NULL;
    234  1.1  christos 	char *sp, *ep;
    235  1.1  christos 	int tun;
    236  1.1  christos 
    237  1.1  christos 	if (remote != NULL) {
    238  1.1  christos 		*remote = SSH_TUNID_ANY;
    239  1.1  christos 		sp = xstrdup(s);
    240  1.1  christos 		if ((ep = strchr(sp, ':')) == NULL) {
    241  1.1  christos 			xfree(sp);
    242  1.1  christos 			return (a2tun(s, NULL));
    243  1.1  christos 		}
    244  1.1  christos 		ep[0] = '\0'; ep++;
    245  1.1  christos 		*remote = a2tun(ep, NULL);
    246  1.1  christos 		tun = a2tun(sp, NULL);
    247  1.1  christos 		xfree(sp);
    248  1.1  christos 		return (*remote == SSH_TUNID_ERR ? *remote : tun);
    249  1.1  christos 	}
    250  1.1  christos 
    251  1.1  christos 	if (strcasecmp(s, "any") == 0)
    252  1.1  christos 		return (SSH_TUNID_ANY);
    253  1.1  christos 
    254  1.1  christos 	tun = strtonum(s, 0, SSH_TUNID_MAX, &errstr);
    255  1.1  christos 	if (errstr != NULL)
    256  1.1  christos 		return (SSH_TUNID_ERR);
    257  1.1  christos 
    258  1.1  christos 	return (tun);
    259  1.1  christos }
    260  1.1  christos 
    261  1.1  christos #define SECONDS		1
    262  1.1  christos #define MINUTES		(SECONDS * 60)
    263  1.1  christos #define HOURS		(MINUTES * 60)
    264  1.1  christos #define DAYS		(HOURS * 24)
    265  1.1  christos #define WEEKS		(DAYS * 7)
    266  1.1  christos 
    267  1.1  christos /*
    268  1.1  christos  * Convert a time string into seconds; format is
    269  1.1  christos  * a sequence of:
    270  1.1  christos  *      time[qualifier]
    271  1.1  christos  *
    272  1.1  christos  * Valid time qualifiers are:
    273  1.1  christos  *      <none>  seconds
    274  1.1  christos  *      s|S     seconds
    275  1.1  christos  *      m|M     minutes
    276  1.1  christos  *      h|H     hours
    277  1.1  christos  *      d|D     days
    278  1.1  christos  *      w|W     weeks
    279  1.1  christos  *
    280  1.1  christos  * Examples:
    281  1.1  christos  *      90m     90 minutes
    282  1.1  christos  *      1h30m   90 minutes
    283  1.1  christos  *      2d      2 days
    284  1.1  christos  *      1w      1 week
    285  1.1  christos  *
    286  1.1  christos  * Return -1 if time string is invalid.
    287  1.1  christos  */
    288  1.1  christos long
    289  1.1  christos convtime(const char *s)
    290  1.1  christos {
    291  1.1  christos 	long total, secs;
    292  1.1  christos 	const char *p;
    293  1.1  christos 	char *endp;
    294  1.1  christos 
    295  1.1  christos 	errno = 0;
    296  1.1  christos 	total = 0;
    297  1.1  christos 	p = s;
    298  1.1  christos 
    299  1.1  christos 	if (p == NULL || *p == '\0')
    300  1.1  christos 		return -1;
    301  1.1  christos 
    302  1.1  christos 	while (*p) {
    303  1.1  christos 		secs = strtol(p, &endp, 10);
    304  1.1  christos 		if (p == endp ||
    305  1.1  christos 		    (errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) ||
    306  1.1  christos 		    secs < 0)
    307  1.1  christos 			return -1;
    308  1.1  christos 
    309  1.1  christos 		switch (*endp++) {
    310  1.1  christos 		case '\0':
    311  1.1  christos 			endp--;
    312  1.1  christos 			break;
    313  1.1  christos 		case 's':
    314  1.1  christos 		case 'S':
    315  1.1  christos 			break;
    316  1.1  christos 		case 'm':
    317  1.1  christos 		case 'M':
    318  1.1  christos 			secs *= MINUTES;
    319  1.1  christos 			break;
    320  1.1  christos 		case 'h':
    321  1.1  christos 		case 'H':
    322  1.1  christos 			secs *= HOURS;
    323  1.1  christos 			break;
    324  1.1  christos 		case 'd':
    325  1.1  christos 		case 'D':
    326  1.1  christos 			secs *= DAYS;
    327  1.1  christos 			break;
    328  1.1  christos 		case 'w':
    329  1.1  christos 		case 'W':
    330  1.1  christos 			secs *= WEEKS;
    331  1.1  christos 			break;
    332  1.1  christos 		default:
    333  1.1  christos 			return -1;
    334  1.1  christos 		}
    335  1.1  christos 		total += secs;
    336  1.1  christos 		if (total < 0)
    337  1.1  christos 			return -1;
    338  1.1  christos 		p = endp;
    339  1.1  christos 	}
    340  1.1  christos 
    341  1.1  christos 	return total;
    342  1.1  christos }
    343  1.1  christos 
    344  1.1  christos /*
    345  1.1  christos  * Returns a standardized host+port identifier string.
    346  1.1  christos  * Caller must free returned string.
    347  1.1  christos  */
    348  1.1  christos char *
    349  1.1  christos put_host_port(const char *host, u_short port)
    350  1.1  christos {
    351  1.1  christos 	char *hoststr;
    352  1.1  christos 
    353  1.1  christos 	if (port == 0 || port == SSH_DEFAULT_PORT)
    354  1.1  christos 		return(xstrdup(host));
    355  1.1  christos 	if (asprintf(&hoststr, "[%s]:%d", host, (int)port) < 0)
    356  1.1  christos 		fatal("put_host_port: asprintf: %s", strerror(errno));
    357  1.1  christos 	debug3("put_host_port: %s", hoststr);
    358  1.1  christos 	return hoststr;
    359  1.1  christos }
    360  1.1  christos 
    361  1.1  christos /*
    362  1.1  christos  * Search for next delimiter between hostnames/addresses and ports.
    363  1.1  christos  * Argument may be modified (for termination).
    364  1.1  christos  * Returns *cp if parsing succeeds.
    365  1.1  christos  * *cp is set to the start of the next delimiter, if one was found.
    366  1.1  christos  * If this is the last field, *cp is set to NULL.
    367  1.1  christos  */
    368  1.1  christos char *
    369  1.1  christos hpdelim(char **cp)
    370  1.1  christos {
    371  1.1  christos 	char *s, *old;
    372  1.1  christos 
    373  1.1  christos 	if (cp == NULL || *cp == NULL)
    374  1.1  christos 		return NULL;
    375  1.1  christos 
    376  1.1  christos 	old = s = *cp;
    377  1.1  christos 	if (*s == '[') {
    378  1.1  christos 		if ((s = strchr(s, ']')) == NULL)
    379  1.1  christos 			return NULL;
    380  1.1  christos 		else
    381  1.1  christos 			s++;
    382  1.1  christos 	} else if ((s = strpbrk(s, ":/")) == NULL)
    383  1.1  christos 		s = *cp + strlen(*cp); /* skip to end (see first case below) */
    384  1.1  christos 
    385  1.1  christos 	switch (*s) {
    386  1.1  christos 	case '\0':
    387  1.1  christos 		*cp = NULL;	/* no more fields*/
    388  1.1  christos 		break;
    389  1.1  christos 
    390  1.1  christos 	case ':':
    391  1.1  christos 	case '/':
    392  1.1  christos 		*s = '\0';	/* terminate */
    393  1.1  christos 		*cp = s + 1;
    394  1.1  christos 		break;
    395  1.1  christos 
    396  1.1  christos 	default:
    397  1.1  christos 		return NULL;
    398  1.1  christos 	}
    399  1.1  christos 
    400  1.1  christos 	return old;
    401  1.1  christos }
    402  1.1  christos 
    403  1.1  christos char *
    404  1.1  christos cleanhostname(char *host)
    405  1.1  christos {
    406  1.1  christos 	if (*host == '[' && host[strlen(host) - 1] == ']') {
    407  1.1  christos 		host[strlen(host) - 1] = '\0';
    408  1.1  christos 		return (host + 1);
    409  1.1  christos 	} else
    410  1.1  christos 		return host;
    411  1.1  christos }
    412  1.1  christos 
    413  1.1  christos char *
    414  1.1  christos colon(char *cp)
    415  1.1  christos {
    416  1.1  christos 	int flag = 0;
    417  1.1  christos 
    418  1.1  christos 	if (*cp == ':')		/* Leading colon is part of file name. */
    419  1.1  christos 		return (0);
    420  1.1  christos 	if (*cp == '[')
    421  1.1  christos 		flag = 1;
    422  1.1  christos 
    423  1.1  christos 	for (; *cp; ++cp) {
    424  1.1  christos 		if (*cp == '@' && *(cp+1) == '[')
    425  1.1  christos 			flag = 1;
    426  1.1  christos 		if (*cp == ']' && *(cp+1) == ':' && flag)
    427  1.1  christos 			return (cp+1);
    428  1.1  christos 		if (*cp == ':' && !flag)
    429  1.1  christos 			return (cp);
    430  1.1  christos 		if (*cp == '/')
    431  1.1  christos 			return (0);
    432  1.1  christos 	}
    433  1.1  christos 	return (0);
    434  1.1  christos }
    435  1.1  christos 
    436  1.1  christos /* function to assist building execv() arguments */
    437  1.1  christos void
    438  1.1  christos addargs(arglist *args, char *fmt, ...)
    439  1.1  christos {
    440  1.1  christos 	va_list ap;
    441  1.1  christos 	char *cp;
    442  1.1  christos 	u_int nalloc;
    443  1.1  christos 	int r;
    444  1.1  christos 
    445  1.1  christos 	va_start(ap, fmt);
    446  1.1  christos 	r = vasprintf(&cp, fmt, ap);
    447  1.1  christos 	va_end(ap);
    448  1.1  christos 	if (r == -1)
    449  1.1  christos 		fatal("addargs: argument too long");
    450  1.1  christos 
    451  1.1  christos 	nalloc = args->nalloc;
    452  1.1  christos 	if (args->list == NULL) {
    453  1.1  christos 		nalloc = 32;
    454  1.1  christos 		args->num = 0;
    455  1.1  christos 	} else if (args->num+2 >= nalloc)
    456  1.1  christos 		nalloc *= 2;
    457  1.1  christos 
    458  1.1  christos 	args->list = xrealloc(args->list, nalloc, sizeof(char *));
    459  1.1  christos 	args->nalloc = nalloc;
    460  1.1  christos 	args->list[args->num++] = cp;
    461  1.1  christos 	args->list[args->num] = NULL;
    462  1.1  christos }
    463  1.1  christos 
    464  1.1  christos void
    465  1.1  christos replacearg(arglist *args, u_int which, char *fmt, ...)
    466  1.1  christos {
    467  1.1  christos 	va_list ap;
    468  1.1  christos 	char *cp;
    469  1.1  christos 	int r;
    470  1.1  christos 
    471  1.1  christos 	va_start(ap, fmt);
    472  1.1  christos 	r = vasprintf(&cp, fmt, ap);
    473  1.1  christos 	va_end(ap);
    474  1.1  christos 	if (r == -1)
    475  1.1  christos 		fatal("replacearg: argument too long");
    476  1.1  christos 
    477  1.1  christos 	if (which >= args->num)
    478  1.1  christos 		fatal("replacearg: tried to replace invalid arg %d >= %d",
    479  1.1  christos 		    which, args->num);
    480  1.1  christos 	xfree(args->list[which]);
    481  1.1  christos 	args->list[which] = cp;
    482  1.1  christos }
    483  1.1  christos 
    484  1.1  christos void
    485  1.1  christos freeargs(arglist *args)
    486  1.1  christos {
    487  1.1  christos 	u_int i;
    488  1.1  christos 
    489  1.1  christos 	if (args->list != NULL) {
    490  1.1  christos 		for (i = 0; i < args->num; i++)
    491  1.1  christos 			xfree(args->list[i]);
    492  1.1  christos 		xfree(args->list);
    493  1.1  christos 		args->nalloc = args->num = 0;
    494  1.1  christos 		args->list = NULL;
    495  1.1  christos 	}
    496  1.1  christos }
    497  1.1  christos 
    498  1.1  christos /*
    499  1.1  christos  * Expands tildes in the file name.  Returns data allocated by xmalloc.
    500  1.1  christos  * Warning: this calls getpw*.
    501  1.1  christos  */
    502  1.1  christos char *
    503  1.1  christos tilde_expand_filename(const char *filename, uid_t uid)
    504  1.1  christos {
    505  1.2  christos 	const char *path, *homedir;
    506  1.1  christos 	char user[128], ret[MAXPATHLEN];
    507  1.1  christos 	struct passwd *pw;
    508  1.1  christos 	u_int len, slash;
    509  1.1  christos 
    510  1.1  christos 	if (*filename != '~')
    511  1.1  christos 		return (xstrdup(filename));
    512  1.1  christos 	filename++;
    513  1.1  christos 
    514  1.1  christos 	path = strchr(filename, '/');
    515  1.1  christos 	if (path != NULL && path > filename) {		/* ~user/path */
    516  1.1  christos 		slash = path - filename;
    517  1.1  christos 		if (slash > sizeof(user) - 1)
    518  1.1  christos 			fatal("tilde_expand_filename: ~username too long");
    519  1.1  christos 		memcpy(user, filename, slash);
    520  1.1  christos 		user[slash] = '\0';
    521  1.1  christos 		if ((pw = getpwnam(user)) == NULL)
    522  1.1  christos 			fatal("tilde_expand_filename: No such user %s", user);
    523  1.2  christos 		homedir = pw->pw_dir;
    524  1.2  christos 	} else {
    525  1.2  christos 		if ((pw = getpwuid(uid)) == NULL)	/* ~/path */
    526  1.2  christos 			fatal("tilde_expand_filename: No such uid %ld",
    527  1.2  christos 			    (long)uid);
    528  1.2  christos 		homedir = pw->pw_dir;
    529  1.2  christos 	}
    530  1.1  christos 
    531  1.2  christos 	if (strlcpy(ret, homedir, sizeof(ret)) >= sizeof(ret))
    532  1.1  christos 		fatal("tilde_expand_filename: Path too long");
    533  1.1  christos 
    534  1.1  christos 	/* Make sure directory has a trailing '/' */
    535  1.2  christos 	len = strlen(homedir);
    536  1.2  christos 	if ((len == 0 || homedir[len - 1] != '/') &&
    537  1.1  christos 	    strlcat(ret, "/", sizeof(ret)) >= sizeof(ret))
    538  1.1  christos 		fatal("tilde_expand_filename: Path too long");
    539  1.1  christos 
    540  1.1  christos 	/* Skip leading '/' from specified path */
    541  1.1  christos 	if (path != NULL)
    542  1.1  christos 		filename = path + 1;
    543  1.1  christos 	if (strlcat(ret, filename, sizeof(ret)) >= sizeof(ret))
    544  1.1  christos 		fatal("tilde_expand_filename: Path too long");
    545  1.1  christos 
    546  1.1  christos 	return (xstrdup(ret));
    547  1.1  christos }
    548  1.1  christos 
    549  1.1  christos /*
    550  1.1  christos  * Expand a string with a set of %[char] escapes. A number of escapes may be
    551  1.1  christos  * specified as (char *escape_chars, char *replacement) pairs. The list must
    552  1.1  christos  * be terminated by a NULL escape_char. Returns replaced string in memory
    553  1.1  christos  * allocated by xmalloc.
    554  1.1  christos  */
    555  1.1  christos char *
    556  1.1  christos percent_expand(const char *string, ...)
    557  1.1  christos {
    558  1.1  christos #define EXPAND_MAX_KEYS	16
    559  1.1  christos 	struct {
    560  1.1  christos 		const char *key;
    561  1.1  christos 		const char *repl;
    562  1.1  christos 	} keys[EXPAND_MAX_KEYS];
    563  1.1  christos 	u_int num_keys, i, j;
    564  1.1  christos 	char buf[4096];
    565  1.1  christos 	va_list ap;
    566  1.1  christos 
    567  1.1  christos 	/* Gather keys */
    568  1.1  christos 	va_start(ap, string);
    569  1.1  christos 	for (num_keys = 0; num_keys < EXPAND_MAX_KEYS; num_keys++) {
    570  1.1  christos 		keys[num_keys].key = va_arg(ap, char *);
    571  1.1  christos 		if (keys[num_keys].key == NULL)
    572  1.1  christos 			break;
    573  1.1  christos 		keys[num_keys].repl = va_arg(ap, char *);
    574  1.1  christos 		if (keys[num_keys].repl == NULL)
    575  1.1  christos 			fatal("percent_expand: NULL replacement");
    576  1.1  christos 	}
    577  1.1  christos 	va_end(ap);
    578  1.1  christos 
    579  1.1  christos 	if (num_keys >= EXPAND_MAX_KEYS)
    580  1.1  christos 		fatal("percent_expand: too many keys");
    581  1.1  christos 
    582  1.1  christos 	/* Expand string */
    583  1.1  christos 	*buf = '\0';
    584  1.1  christos 	for (i = 0; *string != '\0'; string++) {
    585  1.1  christos 		if (*string != '%') {
    586  1.1  christos  append:
    587  1.1  christos 			buf[i++] = *string;
    588  1.1  christos 			if (i >= sizeof(buf))
    589  1.1  christos 				fatal("percent_expand: string too long");
    590  1.1  christos 			buf[i] = '\0';
    591  1.1  christos 			continue;
    592  1.1  christos 		}
    593  1.1  christos 		string++;
    594  1.1  christos 		if (*string == '%')
    595  1.1  christos 			goto append;
    596  1.1  christos 		for (j = 0; j < num_keys; j++) {
    597  1.1  christos 			if (strchr(keys[j].key, *string) != NULL) {
    598  1.1  christos 				i = strlcat(buf, keys[j].repl, sizeof(buf));
    599  1.1  christos 				if (i >= sizeof(buf))
    600  1.1  christos 					fatal("percent_expand: string too long");
    601  1.1  christos 				break;
    602  1.1  christos 			}
    603  1.1  christos 		}
    604  1.1  christos 		if (j >= num_keys)
    605  1.1  christos 			fatal("percent_expand: unknown key %%%c", *string);
    606  1.1  christos 	}
    607  1.1  christos 	return (xstrdup(buf));
    608  1.1  christos #undef EXPAND_MAX_KEYS
    609  1.1  christos }
    610  1.1  christos 
    611  1.1  christos /*
    612  1.1  christos  * Read an entire line from a public key file into a static buffer, discarding
    613  1.1  christos  * lines that exceed the buffer size.  Returns 0 on success, -1 on failure.
    614  1.1  christos  */
    615  1.1  christos int
    616  1.1  christos read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz,
    617  1.1  christos    u_long *lineno)
    618  1.1  christos {
    619  1.1  christos 	while (fgets(buf, bufsz, f) != NULL) {
    620  1.1  christos 		if (buf[0] == '\0')
    621  1.1  christos 			continue;
    622  1.1  christos 		(*lineno)++;
    623  1.1  christos 		if (buf[strlen(buf) - 1] == '\n' || feof(f)) {
    624  1.1  christos 			return 0;
    625  1.1  christos 		} else {
    626  1.1  christos 			debug("%s: %s line %lu exceeds size limit", __func__,
    627  1.1  christos 			    filename, *lineno);
    628  1.1  christos 			/* discard remainder of line */
    629  1.1  christos 			while (fgetc(f) != '\n' && !feof(f))
    630  1.1  christos 				;	/* nothing */
    631  1.1  christos 		}
    632  1.1  christos 	}
    633  1.1  christos 	return -1;
    634  1.1  christos }
    635  1.1  christos 
    636  1.1  christos int
    637  1.1  christos tun_open(int tun, int mode)
    638  1.1  christos {
    639  1.1  christos 	struct ifreq ifr;
    640  1.2  christos 	int fd = -1, sock, flag;
    641  1.2  christos 	const char *tunbase = mode == SSH_TUNMODE_ETHERNET ? "tap" : "tun";
    642  1.1  christos 
    643  1.1  christos 	/* Open the tunnel device */
    644  1.1  christos 	if (tun <= SSH_TUNID_MAX) {
    645  1.2  christos 		snprintf(ifr.ifr_name, sizeof(ifr.ifr_name),
    646  1.2  christos 		    "/dev/%s%d", tunbase, tun);
    647  1.2  christos 		fd = open(ifr.ifr_name, O_RDWR);
    648  1.1  christos 	} else if (tun == SSH_TUNID_ANY) {
    649  1.1  christos 		for (tun = 100; tun >= 0; tun--) {
    650  1.2  christos 			snprintf(ifr.ifr_name, sizeof(ifr.ifr_name),
    651  1.2  christos 			    "/dev/%s%d", tunbase, tun);
    652  1.2  christos 			if ((fd = open(ifr.ifr_name, O_RDWR)) >= 0)
    653  1.1  christos 				break;
    654  1.1  christos 		}
    655  1.1  christos 	} else {
    656  1.1  christos 		debug("%s: invalid tunnel %u", __func__, tun);
    657  1.1  christos 		return (-1);
    658  1.1  christos 	}
    659  1.1  christos 
    660  1.1  christos 	if (fd < 0) {
    661  1.2  christos 		debug("%s: %s open failed: %s", __func__, ifr.ifr_name,
    662  1.2  christos 		    strerror(errno));
    663  1.1  christos 		return (-1);
    664  1.1  christos 	}
    665  1.1  christos 
    666  1.1  christos 
    667  1.2  christos 	/* Turn on tunnel headers */
    668  1.2  christos 	flag = 1;
    669  1.2  christos 	if (mode != SSH_TUNMODE_ETHERNET &&
    670  1.2  christos 	    ioctl(fd, TUNSIFHEAD, &flag) == -1) {
    671  1.2  christos 		debug("%s: ioctl(%d, TUNSIFHEAD, 1): %s", __func__, fd,
    672  1.2  christos 		    strerror(errno));
    673  1.2  christos 		close(fd);
    674  1.2  christos 		return -1;
    675  1.2  christos 	}
    676  1.2  christos 
    677  1.2  christos 	debug("%s: %s mode %d fd %d", __func__, ifr.ifr_name, mode, fd);
    678  1.1  christos 	/* Set the tunnel device operation mode */
    679  1.3   jnemeth 	snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", tunbase, tun);
    680  1.1  christos 	if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
    681  1.1  christos 		goto failed;
    682  1.1  christos 
    683  1.1  christos 	if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)
    684  1.1  christos 		goto failed;
    685  1.1  christos 
    686  1.2  christos #if 0
    687  1.1  christos 	/* Set interface mode */
    688  1.1  christos 	ifr.ifr_flags &= ~IFF_UP;
    689  1.1  christos 	if (mode == SSH_TUNMODE_ETHERNET)
    690  1.1  christos 		ifr.ifr_flags |= IFF_LINK0;
    691  1.1  christos 	else
    692  1.1  christos 		ifr.ifr_flags &= ~IFF_LINK0;
    693  1.1  christos 	if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1)
    694  1.1  christos 		goto failed;
    695  1.2  christos #endif
    696  1.1  christos 
    697  1.1  christos 	/* Bring interface up */
    698  1.1  christos 	ifr.ifr_flags |= IFF_UP;
    699  1.1  christos 	if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1)
    700  1.1  christos 		goto failed;
    701  1.1  christos 
    702  1.1  christos 	close(sock);
    703  1.1  christos 	return (fd);
    704  1.1  christos 
    705  1.1  christos  failed:
    706  1.1  christos 	if (fd >= 0)
    707  1.1  christos 		close(fd);
    708  1.1  christos 	if (sock >= 0)
    709  1.1  christos 		close(sock);
    710  1.2  christos 	debug("%s: failed to set %s mode %d: %s", __func__, ifr.ifr_name,
    711  1.1  christos 	    mode, strerror(errno));
    712  1.1  christos 	return (-1);
    713  1.1  christos }
    714  1.1  christos 
    715  1.1  christos void
    716  1.1  christos sanitise_stdfd(void)
    717  1.1  christos {
    718  1.1  christos 	int nullfd, dupfd;
    719  1.1  christos 
    720  1.1  christos 	if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) {
    721  1.1  christos 		fprintf(stderr, "Couldn't open /dev/null: %s\n",
    722  1.1  christos 		    strerror(errno));
    723  1.1  christos 		exit(1);
    724  1.1  christos 	}
    725  1.1  christos 	while (++dupfd <= 2) {
    726  1.1  christos 		/* Only clobber closed fds */
    727  1.1  christos 		if (fcntl(dupfd, F_GETFL, 0) >= 0)
    728  1.1  christos 			continue;
    729  1.1  christos 		if (dup2(nullfd, dupfd) == -1) {
    730  1.1  christos 			fprintf(stderr, "dup2: %s\n", strerror(errno));
    731  1.1  christos 			exit(1);
    732  1.1  christos 		}
    733  1.1  christos 	}
    734  1.1  christos 	if (nullfd > 2)
    735  1.1  christos 		close(nullfd);
    736  1.1  christos }
    737  1.1  christos 
    738  1.1  christos char *
    739  1.1  christos tohex(const void *vp, size_t l)
    740  1.1  christos {
    741  1.1  christos 	const u_char *p = (const u_char *)vp;
    742  1.1  christos 	char b[3], *r;
    743  1.1  christos 	size_t i, hl;
    744  1.1  christos 
    745  1.1  christos 	if (l > 65536)
    746  1.1  christos 		return xstrdup("tohex: length > 65536");
    747  1.1  christos 
    748  1.1  christos 	hl = l * 2 + 1;
    749  1.1  christos 	r = xcalloc(1, hl);
    750  1.1  christos 	for (i = 0; i < l; i++) {
    751  1.1  christos 		snprintf(b, sizeof(b), "%02x", p[i]);
    752  1.1  christos 		strlcat(r, b, hl);
    753  1.1  christos 	}
    754  1.1  christos 	return (r);
    755  1.1  christos }
    756  1.1  christos 
    757  1.1  christos u_int64_t
    758  1.1  christos get_u64(const void *vp)
    759  1.1  christos {
    760  1.1  christos 	const u_char *p = (const u_char *)vp;
    761  1.1  christos 	u_int64_t v;
    762  1.1  christos 
    763  1.1  christos 	v  = (u_int64_t)p[0] << 56;
    764  1.1  christos 	v |= (u_int64_t)p[1] << 48;
    765  1.1  christos 	v |= (u_int64_t)p[2] << 40;
    766  1.1  christos 	v |= (u_int64_t)p[3] << 32;
    767  1.1  christos 	v |= (u_int64_t)p[4] << 24;
    768  1.1  christos 	v |= (u_int64_t)p[5] << 16;
    769  1.1  christos 	v |= (u_int64_t)p[6] << 8;
    770  1.1  christos 	v |= (u_int64_t)p[7];
    771  1.1  christos 
    772  1.1  christos 	return (v);
    773  1.1  christos }
    774  1.1  christos 
    775  1.1  christos u_int32_t
    776  1.1  christos get_u32(const void *vp)
    777  1.1  christos {
    778  1.1  christos 	const u_char *p = (const u_char *)vp;
    779  1.1  christos 	u_int32_t v;
    780  1.1  christos 
    781  1.1  christos 	v  = (u_int32_t)p[0] << 24;
    782  1.1  christos 	v |= (u_int32_t)p[1] << 16;
    783  1.1  christos 	v |= (u_int32_t)p[2] << 8;
    784  1.1  christos 	v |= (u_int32_t)p[3];
    785  1.1  christos 
    786  1.1  christos 	return (v);
    787  1.1  christos }
    788  1.1  christos 
    789  1.1  christos u_int16_t
    790  1.1  christos get_u16(const void *vp)
    791  1.1  christos {
    792  1.1  christos 	const u_char *p = (const u_char *)vp;
    793  1.1  christos 	u_int16_t v;
    794  1.1  christos 
    795  1.1  christos 	v  = (u_int16_t)p[0] << 8;
    796  1.1  christos 	v |= (u_int16_t)p[1];
    797  1.1  christos 
    798  1.1  christos 	return (v);
    799  1.1  christos }
    800  1.1  christos 
    801  1.1  christos void
    802  1.1  christos put_u64(void *vp, u_int64_t v)
    803  1.1  christos {
    804  1.1  christos 	u_char *p = (u_char *)vp;
    805  1.1  christos 
    806  1.1  christos 	p[0] = (u_char)(v >> 56) & 0xff;
    807  1.1  christos 	p[1] = (u_char)(v >> 48) & 0xff;
    808  1.1  christos 	p[2] = (u_char)(v >> 40) & 0xff;
    809  1.1  christos 	p[3] = (u_char)(v >> 32) & 0xff;
    810  1.1  christos 	p[4] = (u_char)(v >> 24) & 0xff;
    811  1.1  christos 	p[5] = (u_char)(v >> 16) & 0xff;
    812  1.1  christos 	p[6] = (u_char)(v >> 8) & 0xff;
    813  1.1  christos 	p[7] = (u_char)v & 0xff;
    814  1.1  christos }
    815  1.1  christos 
    816  1.1  christos void
    817  1.1  christos put_u32(void *vp, u_int32_t v)
    818  1.1  christos {
    819  1.1  christos 	u_char *p = (u_char *)vp;
    820  1.1  christos 
    821  1.1  christos 	p[0] = (u_char)(v >> 24) & 0xff;
    822  1.1  christos 	p[1] = (u_char)(v >> 16) & 0xff;
    823  1.1  christos 	p[2] = (u_char)(v >> 8) & 0xff;
    824  1.1  christos 	p[3] = (u_char)v & 0xff;
    825  1.1  christos }
    826  1.1  christos 
    827  1.1  christos 
    828  1.1  christos void
    829  1.1  christos put_u16(void *vp, u_int16_t v)
    830  1.1  christos {
    831  1.1  christos 	u_char *p = (u_char *)vp;
    832  1.1  christos 
    833  1.1  christos 	p[0] = (u_char)(v >> 8) & 0xff;
    834  1.1  christos 	p[1] = (u_char)v & 0xff;
    835  1.1  christos }
    836  1.1  christos 
    837  1.1  christos void
    838  1.1  christos ms_subtract_diff(struct timeval *start, int *ms)
    839  1.1  christos {
    840  1.1  christos 	struct timeval diff, finish;
    841  1.1  christos 
    842  1.1  christos 	gettimeofday(&finish, NULL);
    843  1.1  christos 	timersub(&finish, start, &diff);
    844  1.1  christos 	*ms -= (diff.tv_sec * 1000) + (diff.tv_usec / 1000);
    845  1.1  christos }
    846  1.1  christos 
    847  1.1  christos void
    848  1.1  christos ms_to_timeval(struct timeval *tv, int ms)
    849  1.1  christos {
    850  1.1  christos 	if (ms < 0)
    851  1.1  christos 		ms = 0;
    852  1.1  christos 	tv->tv_sec = ms / 1000;
    853  1.1  christos 	tv->tv_usec = (ms % 1000) * 1000;
    854  1.1  christos }
    855  1.1  christos 
    856