Home | History | Annotate | Download | only in common
      1 /*
      2  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     15  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     16  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     18  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     19  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     20  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     22  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     23  */
     24 /*
     25  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     26  * Use is subject to license terms.
     27  */
     28 
     29 #include "includes.h"
     30 RCSID("$OpenBSD: misc.c,v 1.19 2002/03/04 17:27:39 stevesk Exp $");
     31 
     32 #include "misc.h"
     33 #include "log.h"
     34 #include "xmalloc.h"
     35 
     36 /* remove newline at end of string */
     37 char *
     38 chop(char *s)
     39 {
     40 	char *t = s;
     41 	while (*t) {
     42 		if (*t == '\n' || *t == '\r') {
     43 			*t = '\0';
     44 			return s;
     45 		}
     46 		t++;
     47 	}
     48 	return s;
     49 
     50 }
     51 
     52 /* set/unset filedescriptor to non-blocking */
     53 void
     54 set_nonblock(int fd)
     55 {
     56 	int val;
     57 
     58 	val = fcntl(fd, F_GETFL, 0);
     59 	if (val < 0) {
     60 		error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
     61 		return;
     62 	}
     63 	if (val & O_NONBLOCK) {
     64 		debug2("fd %d is O_NONBLOCK", fd);
     65 		return;
     66 	}
     67 	debug("fd %d setting O_NONBLOCK", fd);
     68 	val |= O_NONBLOCK;
     69 	if (fcntl(fd, F_SETFL, val) == -1)
     70 		debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s",
     71 		    fd, strerror(errno));
     72 }
     73 
     74 void
     75 unset_nonblock(int fd)
     76 {
     77 	int val;
     78 
     79 	val = fcntl(fd, F_GETFL, 0);
     80 	if (val < 0) {
     81 		error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
     82 		return;
     83 	}
     84 	if (!(val & O_NONBLOCK)) {
     85 		debug2("fd %d is not O_NONBLOCK", fd);
     86 		return;
     87 	}
     88 	debug("fd %d clearing O_NONBLOCK", fd);
     89 	val &= ~O_NONBLOCK;
     90 	if (fcntl(fd, F_SETFL, val) == -1)
     91 		debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s",
     92 		    fd, strerror(errno));
     93 }
     94 
     95 /* disable nagle on socket */
     96 void
     97 set_nodelay(int fd)
     98 {
     99 	int opt;
    100 	socklen_t optlen;
    101 
    102 	optlen = sizeof opt;
    103 	if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) {
    104 		error("getsockopt TCP_NODELAY: %.100s", strerror(errno));
    105 		return;
    106 	}
    107 	if (opt == 1) {
    108 		debug2("fd %d is TCP_NODELAY", fd);
    109 		return;
    110 	}
    111 	opt = 1;
    112 	debug("fd %d setting TCP_NODELAY", fd);
    113 	if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof opt) == -1)
    114 		error("setsockopt TCP_NODELAY: %.100s", strerror(errno));
    115 }
    116 
    117 /* Characters considered whitespace in strsep calls. */
    118 #define WHITESPACE " \t\r\n"
    119 
    120 /*
    121  * Function returns a pointer to the 1st token on the line. Such a token can
    122  * be an empty string in the case of '*s' equal to " value". It changes the
    123  * first whitespace token or '=' character after the 1st token to '\0'. Upon
    124  * return it changes '*s' to point to the first character of the next token.
    125  * That token may be an empty string if the 1st token was followed only by
    126  * whitespace or it could be a NULL pointer if the line contained one token
    127  * only.
    128  */
    129 char *
    130 strdelim(char **s)
    131 {
    132 	char *old;
    133 	int wspace = 0;
    134 
    135 	if (*s == NULL)
    136 		return NULL;
    137 
    138 	old = *s;
    139 
    140 	*s = strpbrk(*s, WHITESPACE "=");
    141 	if (*s == NULL)
    142 		return (old);
    143 
    144 	/* Allow only one '=' to be skipped */
    145 	if (*s[0] == '=')
    146 		wspace = 1;
    147 	*s[0] = '\0';
    148 
    149 	*s += strspn(*s + 1, WHITESPACE) + 1;
    150 	if (*s[0] == '=' && !wspace)
    151 		*s += strspn(*s + 1, WHITESPACE) + 1;
    152 
    153 	return (old);
    154 }
    155 
    156 struct passwd *
    157 pwcopy(struct passwd *pw)
    158 {
    159 	struct passwd *copy = xmalloc(sizeof(*copy));
    160 
    161 	memset(copy, 0, sizeof(*copy));
    162 	copy->pw_name = xstrdup(pw->pw_name);
    163 	copy->pw_passwd = xstrdup(pw->pw_passwd);
    164 	copy->pw_gecos = xstrdup(pw->pw_gecos);
    165 	copy->pw_uid = pw->pw_uid;
    166 	copy->pw_gid = pw->pw_gid;
    167 #ifdef HAVE_PW_EXPIRE_IN_PASSWD
    168 	copy->pw_expire = pw->pw_expire;
    169 #endif
    170 #ifdef HAVE_PW_CHANGE_IN_PASSWD
    171 	copy->pw_change = pw->pw_change;
    172 #endif
    173 #ifdef HAVE_PW_CLASS_IN_PASSWD
    174 	copy->pw_class = xstrdup(pw->pw_class);
    175 #endif
    176 	copy->pw_dir = xstrdup(pw->pw_dir);
    177 	copy->pw_shell = xstrdup(pw->pw_shell);
    178 	return copy;
    179 }
    180 
    181 void
    182 pwfree(struct passwd **pw)
    183 {
    184 	struct passwd *p;
    185 
    186 	if (pw == NULL || *pw == NULL)
    187 		return;
    188 
    189 	p = *pw;
    190 	*pw = NULL;
    191 
    192 	xfree(p->pw_name);
    193 	xfree(p->pw_passwd);
    194 	xfree(p->pw_gecos);
    195 #ifdef HAVE_PW_CLASS_IN_PASSWD
    196 	xfree(p->pw_class);
    197 #endif
    198 	xfree(p->pw_dir);
    199 	xfree(p->pw_shell);
    200 	xfree(p);
    201 }
    202 
    203 /*
    204  * Convert ASCII string to TCP/IP port number.
    205  * Port must be >0 and <=65535.
    206  * Return 0 if invalid.
    207  */
    208 int
    209 a2port(const char *s)
    210 {
    211 	long port;
    212 	char *endp;
    213 
    214 	errno = 0;
    215 	port = strtol(s, &endp, 0);
    216 	if (s == endp || *endp != '\0' ||
    217 	    (errno == ERANGE && (port == LONG_MIN || port == LONG_MAX)) ||
    218 	    port <= 0 || port > 65535)
    219 		return 0;
    220 
    221 	return port;
    222 }
    223 
    224 #define SECONDS		1
    225 #define MINUTES		(SECONDS * 60)
    226 #define HOURS		(MINUTES * 60)
    227 #define DAYS		(HOURS * 24)
    228 #define WEEKS		(DAYS * 7)
    229 
    230 /*
    231  * Convert a time string into seconds; format is
    232  * a sequence of:
    233  *      time[qualifier]
    234  *
    235  * Valid time qualifiers are:
    236  *      <none>  seconds
    237  *      s|S     seconds
    238  *      m|M     minutes
    239  *      h|H     hours
    240  *      d|D     days
    241  *      w|W     weeks
    242  *
    243  * Examples:
    244  *      90m     90 minutes
    245  *      1h30m   90 minutes
    246  *      2d      2 days
    247  *      1w      1 week
    248  *
    249  * Return -1 if time string is invalid.
    250  */
    251 long
    252 convtime(const char *s)
    253 {
    254 	long total, secs;
    255 	const char *p;
    256 	char *endp;
    257 
    258 	errno = 0;
    259 	total = 0;
    260 	p = s;
    261 
    262 	if (p == NULL || *p == '\0')
    263 		return -1;
    264 
    265 	while (*p) {
    266 		secs = strtol(p, &endp, 10);
    267 		if (p == endp ||
    268 		    (errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) ||
    269 		    secs < 0)
    270 			return -1;
    271 
    272 		switch (*endp++) {
    273 		case '\0':
    274 			endp--;
    275 			break;
    276 		case 's':
    277 		case 'S':
    278 			break;
    279 		case 'm':
    280 		case 'M':
    281 			secs *= MINUTES;
    282 			break;
    283 		case 'h':
    284 		case 'H':
    285 			secs *= HOURS;
    286 			break;
    287 		case 'd':
    288 		case 'D':
    289 			secs *= DAYS;
    290 			break;
    291 		case 'w':
    292 		case 'W':
    293 			secs *= WEEKS;
    294 			break;
    295 		default:
    296 			return -1;
    297 		}
    298 		total += secs;
    299 		if (total < 0)
    300 			return -1;
    301 		p = endp;
    302 	}
    303 
    304 	return total;
    305 }
    306 
    307 /*
    308  * Search for next delimiter between hostnames/addresses and ports.
    309  * Argument may be modified (for termination).
    310  * Returns *cp if parsing succeeds.
    311  * *cp is set to the start of the next delimiter, if one was found.
    312  * If this is the last field, *cp is set to NULL.
    313  */
    314 char *
    315 hpdelim(char **cp)
    316 {
    317 	char *s, *old;
    318 
    319 	if (cp == NULL || *cp == NULL)
    320 		return NULL;
    321 
    322 	old = s = *cp;
    323 	if (*s == '[') {
    324 		if ((s = strchr(s, ']')) == NULL)
    325 			return NULL;
    326 		else
    327 			s++;
    328 	} else if ((s = strpbrk(s, ":/")) == NULL)
    329 		s = *cp + strlen(*cp); /* skip to end (see first case below) */
    330 
    331 	switch (*s) {
    332 	case '\0':
    333 		*cp = NULL;	/* no more fields*/
    334 		break;
    335 
    336 	case ':':
    337 	case '/':
    338 		*s = '\0';	/* terminate */
    339 		*cp = s + 1;
    340 		break;
    341 
    342 	default:
    343 		return NULL;
    344 	}
    345 
    346 	return old;
    347 }
    348 
    349 char *
    350 cleanhostname(char *host)
    351 {
    352 	if (*host == '[' && host[strlen(host) - 1] == ']') {
    353 		host[strlen(host) - 1] = '\0';
    354 		return (host + 1);
    355 	} else
    356 		return host;
    357 }
    358 
    359 char *
    360 colon(char *cp)
    361 {
    362 	int flag = 0;
    363 
    364 	if (*cp == ':')		/* Leading colon is part of file name. */
    365 		return (0);
    366 	if (*cp == '[')
    367 		flag = 1;
    368 
    369 	for (; *cp; ++cp) {
    370 		if (*cp == '@' && *(cp+1) == '[')
    371 			flag = 1;
    372 		if (*cp == ']' && *(cp+1) == ':' && flag)
    373 			return (cp+1);
    374 		if (*cp == ':' && !flag)
    375 			return (cp);
    376 		if (*cp == '/')
    377 			return (0);
    378 	}
    379 	return (0);
    380 }
    381 
    382 /* function to assist building execv() arguments */
    383 /* PRINTFLIKE2 */
    384 void
    385 addargs(arglist *args, char *fmt, ...)
    386 {
    387 	va_list ap;
    388 	char buf[1024];
    389 
    390 	va_start(ap, fmt);
    391 	vsnprintf(buf, sizeof(buf), fmt, ap);
    392 	va_end(ap);
    393 
    394 	if (args->list == NULL) {
    395 		args->nalloc = 32;
    396 		args->num = 0;
    397 	} else if (args->num+2 >= args->nalloc)
    398 		args->nalloc *= 2;
    399 
    400 	args->list = xrealloc(args->list, args->nalloc * sizeof(char *));
    401 	args->list[args->num++] = xstrdup(buf);
    402 	args->list[args->num] = NULL;
    403 }
    404 
    405 void
    406 replacearg(arglist *args, u_int which, char *fmt, ...)
    407 {
    408 	va_list ap;
    409 	char *cp;
    410 	int r;
    411 
    412 	va_start(ap, fmt);
    413 	r = vasprintf(&cp, fmt, ap);
    414 	va_end(ap);
    415 	if (r == -1)
    416 		fatal("replacearg: argument too long");
    417 
    418 	if (which >= args->num)
    419 		fatal("replacearg: tried to replace invalid arg %d >= %d",
    420 		    which, args->num);
    421 	xfree(args->list[which]);
    422 	args->list[which] = cp;
    423 }
    424 
    425 void
    426 freeargs(arglist *args)
    427 {
    428 	u_int i;
    429 
    430 	if (args->list != NULL) {
    431 		for (i = 0; i < args->num; i++)
    432 			xfree(args->list[i]);
    433 		xfree(args->list);
    434 		args->nalloc = args->num = 0;
    435 		args->list = NULL;
    436 	}
    437 }
    438 
    439 /*
    440  * Expand a string with a set of %[char] escapes. A number of escapes may be
    441  * specified as (char *escape_chars, char *replacement) pairs. The list must
    442  * be terminated by a NULL escape_char. Returns replaced string in memory
    443  * allocated by xmalloc.
    444  */
    445 char *
    446 percent_expand(const char *string, ...)
    447 {
    448 #define EXPAND_MAX_KEYS	16
    449 	struct {
    450 		const char *key;
    451 		const char *repl;
    452 	} keys[EXPAND_MAX_KEYS];
    453 	u_int num_keys, i, j;
    454 	char buf[4096];
    455 	va_list ap;
    456 
    457 	/* Gather keys */
    458 	va_start(ap, string);
    459 	for (num_keys = 0; num_keys < EXPAND_MAX_KEYS; num_keys++) {
    460 		keys[num_keys].key = va_arg(ap, char *);
    461 		if (keys[num_keys].key == NULL)
    462 			break;
    463 		keys[num_keys].repl = va_arg(ap, char *);
    464 		if (keys[num_keys].repl == NULL)
    465 			fatal("percent_expand: NULL replacement");
    466 	}
    467 	va_end(ap);
    468 
    469 	if (num_keys >= EXPAND_MAX_KEYS)
    470 		fatal("percent_expand: too many keys");
    471 
    472 	/* Expand string */
    473 	*buf = '\0';
    474 	for (i = 0; *string != '\0'; string++) {
    475 		if (*string != '%') {
    476  append:
    477 			buf[i++] = *string;
    478 			if (i >= sizeof(buf))
    479 				fatal("percent_expand: string too long");
    480 			buf[i] = '\0';
    481 			continue;
    482 		}
    483 		string++;
    484 		if (*string == '%')
    485 			goto append;
    486 		for (j = 0; j < num_keys; j++) {
    487 			if (strchr(keys[j].key, *string) != NULL) {
    488 				i = strlcat(buf, keys[j].repl, sizeof(buf));
    489 				if (i >= sizeof(buf))
    490 					fatal("percent_expand: string too long");
    491 				break;
    492 			}
    493 		}
    494 		if (j >= num_keys)
    495 			fatal("percent_expand: unknown key %%%c", *string);
    496 	}
    497 	return (xstrdup(buf));
    498 #undef EXPAND_MAX_KEYS
    499 }
    500 
    501 /*
    502  * Ensure that file descriptors 0, 1 and 2 are open or directed to /dev/null,
    503  * do not touch those that are already open.
    504  */
    505 void
    506 sanitise_stdfd(void)
    507 {
    508 	int nullfd, dupfd;
    509 
    510 	if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) {
    511 		fprintf(stderr, "Couldn't open /dev/null: %s", strerror(errno));
    512 		exit(1);
    513 	}
    514 	while (++dupfd <= 2) {
    515 		/* Only clobber closed fds */
    516 		if (fcntl(dupfd, F_GETFL, 0) >= 0)
    517 			continue;
    518 		if (dup2(nullfd, dupfd) == -1) {
    519 			fprintf(stderr, "dup2: %s", strerror(errno));
    520 			exit(1);
    521 		}
    522 	}
    523 	if (nullfd > 2)
    524 		close(nullfd);
    525 }
    526 
    527 char *
    528 tohex(const void *vp, size_t l)
    529 {
    530 	const u_char *p = (const u_char *)vp;
    531 	char b[3], *r;
    532 	size_t i, hl;
    533 
    534 	if (l > 65536)
    535 		return xstrdup("tohex: length > 65536");
    536 
    537 	hl = l * 2 + 1;
    538 	r = xcalloc(1, hl);
    539 	for (i = 0; i < l; i++) {
    540 		snprintf(b, sizeof(b), "%02x", p[i]);
    541 		strlcat(r, b, hl);
    542 	}
    543 	return (r);
    544 }
    545 
    546 u_int64_t
    547 get_u64(const void *vp)
    548 {
    549 	const u_char *p = (const u_char *)vp;
    550 	u_int64_t v;
    551 
    552 	v  = (u_int64_t)p[0] << 56;
    553 	v |= (u_int64_t)p[1] << 48;
    554 	v |= (u_int64_t)p[2] << 40;
    555 	v |= (u_int64_t)p[3] << 32;
    556 	v |= (u_int64_t)p[4] << 24;
    557 	v |= (u_int64_t)p[5] << 16;
    558 	v |= (u_int64_t)p[6] << 8;
    559 	v |= (u_int64_t)p[7];
    560 
    561 	return (v);
    562 }
    563 
    564 u_int32_t
    565 get_u32(const void *vp)
    566 {
    567 	const u_char *p = (const u_char *)vp;
    568 	u_int32_t v;
    569 
    570 	v  = (u_int32_t)p[0] << 24;
    571 	v |= (u_int32_t)p[1] << 16;
    572 	v |= (u_int32_t)p[2] << 8;
    573 	v |= (u_int32_t)p[3];
    574 
    575 	return (v);
    576 }
    577 
    578 u_int16_t
    579 get_u16(const void *vp)
    580 {
    581 	const u_char *p = (const u_char *)vp;
    582 	u_int16_t v;
    583 
    584 	v  = (u_int16_t)p[0] << 8;
    585 	v |= (u_int16_t)p[1];
    586 
    587 	return (v);
    588 }
    589 
    590 void
    591 put_u64(void *vp, u_int64_t v)
    592 {
    593 	u_char *p = (u_char *)vp;
    594 
    595 	p[0] = (u_char)(v >> 56) & 0xff;
    596 	p[1] = (u_char)(v >> 48) & 0xff;
    597 	p[2] = (u_char)(v >> 40) & 0xff;
    598 	p[3] = (u_char)(v >> 32) & 0xff;
    599 	p[4] = (u_char)(v >> 24) & 0xff;
    600 	p[5] = (u_char)(v >> 16) & 0xff;
    601 	p[6] = (u_char)(v >> 8) & 0xff;
    602 	p[7] = (u_char)v & 0xff;
    603 }
    604 
    605 void
    606 put_u32(void *vp, u_int32_t v)
    607 {
    608 	u_char *p = (u_char *)vp;
    609 
    610 	p[0] = (u_char)(v >> 24) & 0xff;
    611 	p[1] = (u_char)(v >> 16) & 0xff;
    612 	p[2] = (u_char)(v >> 8) & 0xff;
    613 	p[3] = (u_char)v & 0xff;
    614 }
    615 
    616 
    617 void
    618 put_u16(void *vp, u_int16_t v)
    619 {
    620 	u_char *p = (u_char *)vp;
    621 
    622 	p[0] = (u_char)(v >> 8) & 0xff;
    623 	p[1] = (u_char)v & 0xff;
    624 }
    625 
    626 mysig_t
    627 mysignal(int sig, mysig_t act)
    628 {
    629 #ifdef HAVE_SIGACTION
    630 	struct sigaction sa, osa;
    631 
    632 	if (sigaction(sig, NULL, &osa) == -1)
    633 		return (mysig_t) -1;
    634 	if (osa.sa_handler != act) {
    635 		memset(&sa, 0, sizeof(sa));
    636 		sigemptyset(&sa.sa_mask);
    637 		sa.sa_flags = 0;
    638 #if defined(SA_INTERRUPT)
    639 		if (sig == SIGALRM)
    640 			sa.sa_flags |= SA_INTERRUPT;
    641 #endif
    642 		sa.sa_handler = act;
    643 		if (sigaction(sig, &sa, NULL) == -1)
    644 			return (mysig_t) -1;
    645 	}
    646 	return (osa.sa_handler);
    647 #else
    648 	return (signal(sig, act));
    649 #endif
    650 }
    651 
    652 /*
    653  * Return true if argument is one of "yes", "true", "no" or "false". If
    654  * 'active' is 0 than we are in a non-matching Host section of the
    655  * configuration file so we check the syntax but will not set the value of
    656  * '*option'. Otherwise we set its value if not already set.
    657  */
    658 int
    659 get_yes_no_flag(int *option, const char *arg, const char *filename, int linenum,
    660     int active)
    661 {
    662 	int value = -1;
    663 
    664 	if (arg == NULL || *arg == '\0')
    665 		fatal("%.200s line %d: Missing argument.", filename, linenum);
    666 	if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
    667 		value = 1;
    668 	else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
    669 		value = 0;
    670 
    671 	if (active && *option == -1 && value != -1)
    672 		*option = value;
    673 
    674 	return (value != -1);
    675 }
    676 
    677 /*
    678  * Convert a string to lowercase. The string returned is an internally allocated
    679  * one so the consumer of this function is not expected to change it or free it.
    680  */
    681 char *
    682 tolowercase(const char *s)
    683 {
    684 	int i, len;
    685 	static int lenret = 0;
    686 	static char *ret = NULL;
    687 
    688 	/* allocate a new string if the old one it not long enough to store s */
    689 	len = strlen(s) + 1;
    690 	if (len > lenret) {
    691 		if (ret != NULL)
    692 			xfree(ret);
    693 		ret = xmalloc(len);
    694 		lenret = len;
    695 	}
    696 
    697 	/* process the string including the ending '\0' */
    698 	for (i = 0; i < len; ++i)
    699 		ret[i] = tolower(s[i]);
    700 
    701 	return (ret);
    702 }
    703