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