Home | History | Annotate | Line # | Download | only in cgdconfig
      1 /* $NetBSD: utils.c,v 1.21 2012/03/20 18:50:30 matt Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Roland C. Dowdeswell.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 #ifndef lint
     34 __RCSID("$NetBSD: utils.c,v 1.21 2012/03/20 18:50:30 matt Exp $");
     35 #endif
     36 
     37 #include <sys/param.h>
     38 
     39 #include <stdlib.h>
     40 #include <string.h>
     41 #include <err.h>
     42 #include <util.h>
     43 
     44 /* include the resolver gunk in order that we can use b64 routines */
     45 #include <netinet/in.h>
     46 #include <arpa/nameser.h>
     47 #include <resolv.h>
     48 
     49 #include "utils.h"
     50 
     51 
     52 /* just strsep(3), but skips empty fields. */
     53 
     54 static char *
     55 strsep_getnext(char **stringp, const char *delim)
     56 {
     57 	char	*ret;
     58 
     59 	ret = strsep(stringp, delim);
     60 	while (ret && index(delim, *ret))
     61 		ret = strsep(stringp, delim);
     62 	return ret;
     63 }
     64 
     65 /*
     66  * this function returns a dynamically sized char ** of the words
     67  * in the line.  the caller is responsible for both free(3)ing
     68  * each word and the superstructure by calling words_free().
     69  */
     70 char **
     71 words(const char *line, int *num)
     72 {
     73 	int	  i = 0;
     74 	int	  nwords = 0;
     75 	char	 *cur;
     76 	char	**ret;
     77 	const char	 *tmp;
     78 	char	 *tmp1, *tmpf;
     79 
     80 	*num = 0;
     81 	tmp = line;
     82 	if (tmp[0] == '\0')
     83 		return NULL;
     84 	while (tmp[0]) {
     85 		if ((tmp[1] == ' ' || tmp[1] == '\t' || tmp[1] == '\0') &&
     86 		    (tmp[0] != ' ' && tmp[0] != '\t'))
     87 			nwords++;
     88 		tmp++;
     89 	}
     90 	ret = emalloc((nwords+1) * sizeof(char *));
     91 	tmp1 = tmpf = estrdup(line);
     92 	while ((cur = strsep_getnext(&tmpf, " \t")) != NULL)
     93 		ret[i++] = estrdup(cur);
     94 	ret[i] = NULL;
     95 	free(tmp1);
     96 	*num = nwords;
     97 	return ret;
     98 }
     99 
    100 void
    101 words_free(char **w, int num)
    102 {
    103 	int	i;
    104 
    105 	for (i=0; i < num; i++)
    106 		free(w[i]);
    107 }
    108 
    109 /*
    110  * this is a simple xor that has the same calling conventions as
    111  * memcpy(3).
    112  */
    113 
    114 void
    115 memxor(void *res, const void *src, size_t len)
    116 {
    117 	char *r;
    118 	const char *s;
    119 	size_t i;
    120 
    121 	r = res;
    122 	s = src;
    123 	for (i = 0; i < len; i++)
    124 		r[i] ^= s[i];
    125 }
    126 
    127 /*
    128  * well, a very simple set of string functions...
    129  *
    130  * The goal here is basically to manage length encoded strings,
    131  * but just for safety we nul terminate them anyway.
    132  */
    133 
    134 /* for now we use a very simple encoding */
    135 
    136 struct string {
    137 	char	*text;
    138 	size_t	 length;
    139 };
    140 
    141 string_t *
    142 string_zero(void)
    143 {
    144 	string_t *out;
    145 
    146 	out = emalloc(sizeof(*out));
    147 	out->length = 0;
    148 	out->text = NULL;
    149 	return out;
    150 }
    151 
    152 string_t *
    153 string_new(const char *intext, size_t inlength)
    154 {
    155 	string_t *out;
    156 
    157 	out = emalloc(sizeof(*out));
    158 	out->length = inlength;
    159 	out->text = emalloc(out->length + 1);
    160 	(void)memcpy(out->text, intext, out->length);
    161 	out->text[out->length] = '\0';
    162 	return out;
    163 }
    164 
    165 string_t *
    166 string_dup(const string_t *in)
    167 {
    168 
    169 	return string_new(in->text, in->length);
    170 }
    171 
    172 void
    173 string_free(string_t *s)
    174 {
    175 
    176 	if (!s)
    177 		return;
    178 	free(s->text);
    179 	free(s);
    180 }
    181 
    182 void
    183 string_assign(string_t **lhs, string_t *rhs)
    184 {
    185 
    186 	string_free(*lhs);
    187 	*lhs = rhs;
    188 }
    189 
    190 string_t *
    191 string_add(const string_t *a1, const string_t *a2)
    192 {
    193 	string_t *sum;
    194 
    195 	sum = emalloc(sizeof(*sum));
    196 	sum->length = a1->length + a2->length;
    197 	sum->text = emalloc(sum->length + 1);
    198 	(void)memcpy(sum->text, a1->text, a1->length);
    199 	(void)memcpy(sum->text + a1->length, a2->text, a2->length);
    200 	sum->text[sum->length] = '\0';
    201 	return sum;
    202 }
    203 
    204 string_t *
    205 string_add_d(string_t *a1, string_t *a2)
    206 {
    207 	string_t *sum;
    208 
    209 	sum = string_add(a1, a2);
    210 	string_free(a1);
    211 	string_free(a2);
    212 	return sum;
    213 }
    214 
    215 string_t *
    216 string_fromcharstar(const char *in)
    217 {
    218 
    219 	return string_new(in, strlen(in));
    220 }
    221 
    222 const char *
    223 string_tocharstar(const string_t *in)
    224 {
    225 
    226 	return in->text;
    227 }
    228 
    229 string_t *
    230 string_fromint(int in)
    231 {
    232 	string_t *ret;
    233 
    234 	ret = emalloc(sizeof(*ret));
    235 	ret->length = asprintf(&ret->text, "%d", in);
    236 	if (ret->text == NULL)
    237 		err(1, NULL);
    238 	return ret;
    239 }
    240 
    241 void
    242 string_fprint(FILE *f, const string_t *s)
    243 {
    244 	(void)fwrite(s->text, s->length, 1, f);
    245 }
    246 
    247 struct bits {
    248 	size_t	 length;
    249 	char	*text;
    250 };
    251 
    252 bits_t *
    253 bits_new(const void *buf, size_t len)
    254 {
    255 	bits_t	*b;
    256 
    257 	b = emalloc(sizeof(*b));
    258 	b->length = len;
    259 	b->text = emalloc(BITS2BYTES(b->length));
    260 	(void)memcpy(b->text, buf, BITS2BYTES(b->length));
    261 	return b;
    262 }
    263 
    264 bits_t *
    265 bits_dup(const bits_t *in)
    266 {
    267 
    268 	return bits_new(in->text, in->length);
    269 }
    270 
    271 void
    272 bits_free(bits_t *b)
    273 {
    274 
    275 	if (!b)
    276 		return;
    277 	free(b->text);
    278 	free(b);
    279 }
    280 
    281 void
    282 bits_assign(bits_t **lhs, bits_t *rhs)
    283 {
    284 
    285 	bits_free(*lhs);
    286 	*lhs = rhs;
    287 }
    288 
    289 const void *
    290 bits_getbuf(bits_t *in)
    291 {
    292 
    293 	return in->text;
    294 }
    295 
    296 size_t
    297 bits_len(bits_t *in)
    298 {
    299 
    300 	return in->length;
    301 }
    302 
    303 int
    304 bits_match(const bits_t *b1, const bits_t *b2)
    305 {
    306 	size_t i;
    307 
    308 	if (b1->length != b2->length)
    309 		return 0;
    310 
    311 	for (i = 0; i < BITS2BYTES(b1->length); i++)
    312 		if (b1->text[i] != b2->text[i])
    313 			return 0;
    314 
    315 	return 1;
    316 }
    317 
    318 bits_t *
    319 bits_xor(const bits_t *x1, const bits_t *x2)
    320 {
    321 	bits_t	*b;
    322 	size_t	 i;
    323 
    324 	b = emalloc(sizeof(*b));
    325 	b->length = MAX(x1->length, x2->length);
    326 	b->text = ecalloc(1, BITS2BYTES(b->length));
    327 	for (i=0; i < BITS2BYTES(MIN(x1->length, x2->length)); i++)
    328 		b->text[i] = x1->text[i] ^ x2->text[i];
    329 	return b;
    330 }
    331 
    332 bits_t *
    333 bits_xor_d(bits_t *x1, bits_t *x2)
    334 {
    335 	bits_t	*ret;
    336 
    337 	ret = bits_xor(x1, x2);
    338 	bits_free(x1);
    339 	bits_free(x2);
    340 	return ret;
    341 }
    342 
    343 /*
    344  * bits_decode() reads an encoded base64 stream.  We interpret
    345  * the first 32 bits as an unsigned integer in network byte order
    346  * specifying the number of bits in the stream to give a little
    347  * resilience.
    348  */
    349 
    350 bits_t *
    351 bits_decode(const string_t *in)
    352 {
    353 	bits_t	*ret;
    354 	size_t	 len;
    355 	size_t	 nbits;
    356 	u_int32_t	*tmp;
    357 
    358 	len = in->length;
    359 	tmp = emalloc(len);
    360 
    361 	len = __b64_pton(in->text, (void *)tmp, len);
    362 
    363 	if (len == (size_t)-1) {
    364 		warnx("bits_decode: mangled base64 stream");
    365 		warnx("  %s", in->text);
    366 		free(tmp);
    367 		return NULL;
    368 	}
    369 
    370 	nbits = ntohl(*tmp);
    371 	if (nbits > (len - sizeof(*tmp)) * NBBY) {
    372 		warnx("bits_decode: encoded bits claim to be "
    373 		    "longer than they are (nbits=%zu, stream len=%zu bytes)",
    374 		    nbits, len);
    375 		free(tmp);
    376 		return NULL;
    377 	}
    378 
    379 	ret = bits_new(tmp + 1, nbits);
    380 	free(tmp);
    381 	return ret;
    382 }
    383 
    384 bits_t *
    385 bits_decode_d(string_t *in)
    386 {
    387 	bits_t *ret;
    388 
    389 	ret = bits_decode(in);
    390 	string_free(in);
    391 	return ret;
    392 }
    393 
    394 string_t *
    395 bits_encode(const bits_t *in)
    396 {
    397 	string_t *ret;
    398 	size_t	 len;
    399 	char	*out;
    400 	u_int32_t *tmp;
    401 
    402 	if (!in)
    403 		return NULL;
    404 
    405 	/* compute the total size of the input stream */
    406 	len = BITS2BYTES(in->length) + sizeof(*tmp);
    407 
    408 	tmp = emalloc(len);
    409 	out = emalloc(len * 2);
    410 	/* stuff the length up front */
    411 	*tmp = htonl(in->length);
    412 	(void)memcpy(tmp + 1, in->text, len - sizeof(*tmp));
    413 
    414 	if ((len = __b64_ntop((void *)tmp, len, out, len * 2)) == (size_t)-1) {
    415 		free(out);
    416 		free(tmp);
    417 		return NULL;
    418 	}
    419 	ret = string_new(out, len);
    420 	free(tmp);
    421 	free(out);
    422 	return ret;
    423 }
    424 
    425 string_t *
    426 bits_encode_d(bits_t *in)
    427 {
    428 	string_t *ret;
    429 
    430 	ret = bits_encode(in);
    431 	bits_free(in);
    432 	return ret;
    433 }
    434 
    435 bits_t *
    436 bits_fget(FILE *f, size_t len)
    437 {
    438 	bits_t	*bits;
    439 	int	 ret;
    440 
    441 	bits = emalloc(sizeof(*bits));
    442 	bits->length = len;
    443 	bits->text = emalloc(BITS2BYTES(bits->length));
    444 	ret = fread(bits->text, BITS2BYTES(bits->length), 1, f);
    445 	if (ret != 1) {
    446 		bits_free(bits);
    447 		return NULL;
    448 	}
    449 	return bits;
    450 }
    451 
    452 bits_t *
    453 bits_cget(const char *fn, size_t len)
    454 {
    455 	bits_t	*bits;
    456 	FILE	*f;
    457 
    458 	f = fopen(fn, "r");
    459 	if (!f)
    460 		return NULL;
    461 
    462 	bits = bits_fget(f, len);
    463 	(void)fclose(f);
    464 	return bits;
    465 }
    466 
    467 bits_t *
    468 bits_getrandombits(size_t len, int hard)
    469 {
    470 
    471 	return bits_cget((hard ? "/dev/random" : "/dev/urandom"), len);
    472 }
    473 
    474 void
    475 bits_fprint(FILE *f, const bits_t *bits)
    476 {
    477 	string_t *s;
    478 
    479 	s = bits_encode(bits);
    480 	string_fprint(f, s);
    481 	free(s);
    482 }
    483