1 /* $NetBSD: utils.c,v 1.18 2008/04/28 20:23:08 martin 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.18 2008/04/28 20:23:08 martin 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_new(const char *intext, size_t inlength) 143 { 144 string_t *out; 145 146 out = emalloc(sizeof(*out)); 147 out->length = inlength; 148 out->text = emalloc(out->length + 1); 149 (void)memcpy(out->text, intext, out->length); 150 out->text[out->length] = '\0'; 151 return out; 152 } 153 154 string_t * 155 string_dup(const string_t *in) 156 { 157 158 return string_new(in->text, in->length); 159 } 160 161 void 162 string_free(string_t *s) 163 { 164 165 if (!s) 166 return; 167 free(s->text); 168 free(s); 169 } 170 171 void 172 string_assign(string_t **lhs, string_t *rhs) 173 { 174 175 string_free(*lhs); 176 *lhs = rhs; 177 } 178 179 string_t * 180 string_add(const string_t *a1, const string_t *a2) 181 { 182 string_t *sum; 183 184 sum = emalloc(sizeof(*sum)); 185 sum->length = a1->length + a2->length; 186 sum->text = emalloc(sum->length + 1); 187 (void)memcpy(sum->text, a1->text, a1->length); 188 (void)memcpy(sum->text + a1->length, a2->text, a2->length); 189 sum->text[sum->length] = '\0'; 190 return sum; 191 } 192 193 string_t * 194 string_add_d(string_t *a1, string_t *a2) 195 { 196 string_t *sum; 197 198 sum = string_add(a1, a2); 199 string_free(a1); 200 string_free(a2); 201 return sum; 202 } 203 204 string_t * 205 string_fromcharstar(const char *in) 206 { 207 208 return string_new(in, strlen(in)); 209 } 210 211 const char * 212 string_tocharstar(const string_t *in) 213 { 214 215 return in->text; 216 } 217 218 string_t * 219 string_fromint(int in) 220 { 221 string_t *ret; 222 223 ret = emalloc(sizeof(*ret)); 224 ret->length = asprintf(&ret->text, "%d", in); 225 if (ret->text == NULL) 226 err(1, NULL); 227 return ret; 228 } 229 230 void 231 string_fprint(FILE *f, const string_t *s) 232 { 233 (void)fwrite(s->text, s->length, 1, f); 234 } 235 236 struct bits { 237 size_t length; 238 char *text; 239 }; 240 241 bits_t * 242 bits_new(const void *buf, size_t len) 243 { 244 bits_t *b; 245 246 b = emalloc(sizeof(*b)); 247 b->length = len; 248 b->text = emalloc(BITS2BYTES(b->length)); 249 (void)memcpy(b->text, buf, BITS2BYTES(b->length)); 250 return b; 251 } 252 253 bits_t * 254 bits_dup(const bits_t *in) 255 { 256 257 return bits_new(in->text, in->length); 258 } 259 260 void 261 bits_free(bits_t *b) 262 { 263 264 if (!b) 265 return; 266 free(b->text); 267 free(b); 268 } 269 270 void 271 bits_assign(bits_t **lhs, bits_t *rhs) 272 { 273 274 bits_free(*lhs); 275 *lhs = rhs; 276 } 277 278 const void * 279 bits_getbuf(bits_t *in) 280 { 281 282 return in->text; 283 } 284 285 size_t 286 bits_len(bits_t *in) 287 { 288 289 return in->length; 290 } 291 292 int 293 bits_match(const bits_t *b1, const bits_t *b2) 294 { 295 int i; 296 297 if (b1->length != b2->length) 298 return 0; 299 300 for (i = 0; i < BITS2BYTES(b1->length); i++) 301 if (b1->text[i] != b2->text[i]) 302 return 0; 303 304 return 1; 305 } 306 307 bits_t * 308 bits_xor(const bits_t *x1, const bits_t *x2) 309 { 310 bits_t *b; 311 int i; 312 313 b = emalloc(sizeof(*b)); 314 b->length = MAX(x1->length, x2->length); 315 b->text = ecalloc(1, BITS2BYTES(b->length)); 316 for (i=0; i < BITS2BYTES(MIN(x1->length, x2->length)); i++) 317 b->text[i] = x1->text[i] ^ x2->text[i]; 318 return b; 319 } 320 321 bits_t * 322 bits_xor_d(bits_t *x1, bits_t *x2) 323 { 324 bits_t *ret; 325 326 ret = bits_xor(x1, x2); 327 bits_free(x1); 328 bits_free(x2); 329 return ret; 330 } 331 332 /* 333 * bits_decode() reads an encoded base64 stream. We interpret 334 * the first 32 bits as an unsigned integer in network byte order 335 * specifying the number of bits in the stream to give a little 336 * resilience. 337 */ 338 339 bits_t * 340 bits_decode(const string_t *in) 341 { 342 bits_t *ret; 343 size_t len; 344 size_t nbits; 345 u_int32_t *tmp; 346 347 len = in->length; 348 tmp = emalloc(len); 349 350 len = __b64_pton(in->text, (void *)tmp, len); 351 352 if (len == (size_t)-1) { 353 warnx("bits_decode: mangled base64 stream"); 354 warnx(" %s", in->text); 355 free(tmp); 356 return NULL; 357 } 358 359 nbits = ntohl(*tmp); 360 if (nbits > (len - sizeof(*tmp)) * NBBY) { 361 warnx("bits_decode: encoded bits claim to be " 362 "longer than they are (nbits=%zu, stream len=%zu bytes)", 363 nbits, len); 364 free(tmp); 365 return NULL; 366 } 367 368 ret = bits_new(tmp + 1, nbits); 369 free(tmp); 370 return ret; 371 } 372 373 bits_t * 374 bits_decode_d(string_t *in) 375 { 376 bits_t *ret; 377 378 ret = bits_decode(in); 379 string_free(in); 380 return ret; 381 } 382 383 string_t * 384 bits_encode(const bits_t *in) 385 { 386 string_t *ret; 387 size_t len; 388 char *out; 389 u_int32_t *tmp; 390 391 if (!in) 392 return NULL; 393 394 /* compute the total size of the input stream */ 395 len = BITS2BYTES(in->length) + sizeof(*tmp); 396 397 tmp = emalloc(len); 398 out = emalloc(len * 2); 399 /* stuff the length up front */ 400 *tmp = htonl(in->length); 401 (void)memcpy(tmp + 1, in->text, len - sizeof(*tmp)); 402 403 if ((len = __b64_ntop((void *)tmp, len, out, len * 2)) == (size_t)-1) { 404 free(out); 405 free(tmp); 406 return NULL; 407 } 408 ret = string_new(out, len); 409 free(tmp); 410 free(out); 411 return ret; 412 } 413 414 string_t * 415 bits_encode_d(bits_t *in) 416 { 417 string_t *ret; 418 419 ret = bits_encode(in); 420 bits_free(in); 421 return ret; 422 } 423 424 bits_t * 425 bits_fget(FILE *f, size_t len) 426 { 427 bits_t *bits; 428 int ret; 429 430 bits = emalloc(sizeof(*bits)); 431 bits->length = len; 432 bits->text = emalloc(BITS2BYTES(bits->length)); 433 ret = fread(bits->text, BITS2BYTES(bits->length), 1, f); 434 if (ret != 1) { 435 bits_free(bits); 436 return NULL; 437 } 438 return bits; 439 } 440 441 bits_t * 442 bits_cget(const char *fn, size_t len) 443 { 444 bits_t *bits; 445 FILE *f; 446 447 f = fopen(fn, "r"); 448 if (!f) 449 return NULL; 450 451 bits = bits_fget(f, len); 452 (void)fclose(f); 453 return bits; 454 } 455 456 bits_t * 457 bits_getrandombits(size_t len, int hard) 458 { 459 460 return bits_cget((hard ? "/dev/random" : "/dev/urandom"), len); 461 } 462 463 void 464 bits_fprint(FILE *f, const bits_t *bits) 465 { 466 string_t *s; 467 468 s = bits_encode(bits); 469 string_fprint(f, s); 470 free(s); 471 } 472