Home | History | Annotate | Download | only in dropbear
      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 /*RCSID("OpenBSD: misc.c,v 1.22 2003/09/18 08:49:45 markus Exp ");*/
     26 
     27 /* For xmalloc, xfree etc:
     28  * Author: Tatu Ylonen <ylo (at) cs.hut.fi>
     29  * Copyright (c) 1995 Tatu Ylonen <ylo (at) cs.hut.fi>, Espoo, Finland
     30  *                    All rights reserved
     31  * Versions of malloc and friends that check their results, and never return
     32  * failure (they call fatal if they encounter an error).
     33  *
     34  * As far as I am concerned, the code I have written for this software
     35  * can be used freely for any purpose.  Any derived versions of this
     36  * software must be clearly marked as such, and if the derived work is
     37  * incompatible with the protocol description in the RFC file, it must be
     38  * called by a name other than "ssh" or "Secure Shell".
     39  */
     40 
     41 /*RCSID("OpenBSD: xmalloc.c,v 1.16 2001/07/23 18:21:46 stevesk Exp ");*/
     42 
     43 #include "includes.h"
     44 #include "scpmisc.h"
     45 
     46 void *
     47 xmalloc(size_t size)
     48 {
     49 	void *ptr;
     50 
     51 	if (size == 0) {
     52 		fprintf(stderr, "xmalloc: zero size\n");
     53 		exit(EXIT_FAILURE);
     54 	}
     55 	ptr = malloc(size);
     56 	if (ptr == NULL) {
     57 		fprintf(stderr, "xmalloc: out of memory (allocating %lu bytes)\n", (u_long) size);
     58 		exit(EXIT_FAILURE);
     59 	}
     60 	return ptr;
     61 }
     62 
     63 void *
     64 xrealloc(void *ptr, size_t new_size)
     65 {
     66 	void *new_ptr;
     67 
     68 	if (new_size == 0) {
     69 		fprintf(stderr, "xrealloc: zero size\n");
     70 		exit(EXIT_FAILURE);
     71 	}
     72 	if (ptr == NULL)
     73 		new_ptr = malloc(new_size);
     74 	else
     75 		new_ptr = realloc(ptr, new_size);
     76 	if (new_ptr == NULL) {
     77 		fprintf(stderr, "xrealloc: out of memory (new_size %lu bytes)\n", (u_long) new_size);
     78 		exit(EXIT_FAILURE);
     79 	}
     80 	return new_ptr;
     81 }
     82 
     83 void
     84 xfree(void *ptr)
     85 {
     86 	if (ptr == NULL) {
     87 		fprintf(stderr, "xfree: NULL pointer given as argument\n");
     88 		exit(EXIT_FAILURE);
     89 	}
     90 	free(ptr);
     91 }
     92 
     93 char *
     94 xstrdup(const char *str)
     95 {
     96 	size_t len;
     97 	char *cp;
     98 
     99 	len = strlen(str) + 1;
    100 	cp = xmalloc(len);
    101 	strncpy(cp, str, len);
    102 	return cp;
    103 }
    104 
    105 char *
    106 cleanhostname(char *host)
    107 {
    108 	if (*host == '[' && host[strlen(host) - 1] == ']') {
    109 		host[strlen(host) - 1] = '\0';
    110 		return (host + 1);
    111 	} else
    112 		return host;
    113 }
    114 
    115 char *
    116 colon(char *cp)
    117 {
    118 	int flag = 0;
    119 
    120 	if (*cp == ':')		/* Leading colon is part of file name. */
    121 		return (0);
    122 	if (*cp == '[')
    123 		flag = 1;
    124 
    125 	for (; *cp; ++cp) {
    126 		if (*cp == '@' && *(cp+1) == '[')
    127 			flag = 1;
    128 		if (*cp == ']' && *(cp+1) == ':' && flag)
    129 			return (cp+1);
    130 		if (*cp == ':' && !flag)
    131 			return (cp);
    132 		if (*cp == '/')
    133 			return (0);
    134 	}
    135 	return (0);
    136 }
    137 
    138 /* function to assist building execv() arguments */
    139 void
    140 addargs(arglist *args, char *fmt, ...)
    141 {
    142 	va_list ap;
    143 	char *cp;
    144 	u_int nalloc;
    145 	int r;
    146 
    147 	va_start(ap, fmt);
    148 	r = vasprintf(&cp, fmt, ap);
    149 	va_end(ap);
    150 	if (r == -1)
    151 		fatal("addargs: argument too long");
    152 
    153 	nalloc = args->nalloc;
    154 	if (args->list == NULL) {
    155 		nalloc = 32;
    156 		args->num = 0;
    157 	} else if (args->num+2 >= nalloc)
    158 		nalloc *= 2;
    159 
    160 	args->list = xrealloc(args->list, nalloc * sizeof(char *));
    161 	args->nalloc = nalloc;
    162 	args->list[args->num++] = cp;
    163 	args->list[args->num] = NULL;
    164 }
    165 
    166 void
    167 replacearg(arglist *args, u_int which, char *fmt, ...)
    168 {
    169 	va_list ap;
    170 	char *cp;
    171 	int r;
    172 
    173 	va_start(ap, fmt);
    174 	r = vasprintf(&cp, fmt, ap);
    175 	va_end(ap);
    176 	if (r == -1)
    177 		fatal("replacearg: argument too long");
    178 
    179 	if (which >= args->num)
    180 		fatal("replacearg: tried to replace invalid arg %d >= %d",
    181 		    which, args->num);
    182 	xfree(args->list[which]);
    183 	args->list[which] = cp;
    184 }
    185 
    186 void
    187 freeargs(arglist *args)
    188 {
    189 	u_int i;
    190 
    191 	if (args->list != NULL) {
    192 		for (i = 0; i < args->num; i++)
    193 			xfree(args->list[i]);
    194 		xfree(args->list);
    195 		args->nalloc = args->num = 0;
    196 		args->list = NULL;
    197 	}
    198 }
    199 
    200 /*
    201  * NB. duplicate __progname in case it is an alias for argv[0]
    202  * Otherwise it may get clobbered by setproctitle()
    203  */
    204 char *ssh_get_progname(char *argv0)
    205 {
    206 	char *p;
    207 
    208 	if (argv0 == NULL)
    209 		return ("unknown");	/* XXX */
    210 	p = strrchr(argv0, '/');
    211 	if (p == NULL)
    212 		p = argv0;
    213 	else
    214 		p++;
    215 
    216 	return (xstrdup(p));
    217 }
    218 
    219 void fatal(char* fmt,...)
    220 {
    221 	va_list args;
    222 	va_start(args, fmt);
    223 	vfprintf(stderr, fmt, args);
    224 	va_end(args);
    225 	exit(255);
    226 }
    227 
    228 void
    229 sanitise_stdfd(void)
    230 {
    231 	int nullfd, dupfd;
    232 
    233 	if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) {
    234 		fprintf(stderr, "Couldn't open /dev/null: %s", strerror(errno));
    235 		exit(1);
    236 	}
    237 	while (++dupfd <= 2) {
    238 		/* Only clobber closed fds */
    239 		if (fcntl(dupfd, F_GETFL, 0) >= 0)
    240 			continue;
    241 		if (dup2(nullfd, dupfd) == -1) {
    242 			fprintf(stderr, "dup2: %s", strerror(errno));
    243 			exit(1);
    244 		}
    245 	}
    246 	if (nullfd > 2)
    247 		close(nullfd);
    248 }
    249