1 /* $NetBSD: utils.c,v 1.15 2006/08/26 18:14:28 christos 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.15 2006/08/26 18:14:28 christos Exp $"); 42 #endif 43 44 #include <sys/param.h> 45 46 #include <stdlib.h> 47 #include <string.h> 48 #include <err.h> 49 #include <util.h> 50 51 /* include the resolver gunk in order that we can use b64 routines */ 52 #include <netinet/in.h> 53 #include <arpa/nameser.h> 54 #include <resolv.h> 55 56 #include "utils.h" 57 58 59 /* just strsep(3), but skips empty fields. */ 60 61 static char * 62 strsep_getnext(char **stringp, const char *delim) 63 { 64 char *ret; 65 66 ret = strsep(stringp, delim); 67 while (ret && index(delim, *ret)) 68 ret = strsep(stringp, delim); 69 return ret; 70 } 71 72 /* 73 * this function returns a dynamically sized char ** of the words 74 * in the line. the caller is responsible for both free(3)ing 75 * each word and the superstructure by calling words_free(). 76 */ 77 char ** 78 words(const char *line, int *num) 79 { 80 int i = 0; 81 int nwords = 0; 82 char *cur; 83 char **ret; 84 const char *tmp; 85 char *tmp1, *tmpf; 86 87 *num = 0; 88 tmp = line; 89 if (tmp[0] == '\0') 90 return NULL; 91 while (tmp[0]) { 92 if ((tmp[1] == ' ' || tmp[1] == '\t' || tmp[1] == '\0') && 93 (tmp[0] != ' ' && tmp[0] != '\t')) 94 nwords++; 95 tmp++; 96 } 97 ret = emalloc((nwords+1) * sizeof(char *)); 98 tmp1 = tmpf = estrdup(line); 99 while ((cur = strsep_getnext(&tmpf, " \t")) != NULL) 100 ret[i++] = estrdup(cur); 101 ret[i] = NULL; 102 free(tmp1); 103 *num = nwords; 104 return ret; 105 } 106 107 void 108 words_free(char **w, int num) 109 { 110 int i; 111 112 for (i=0; i < num; i++) 113 free(w[i]); 114 } 115 116 /* 117 * this is a simple xor that has the same calling conventions as 118 * memcpy(3). 119 */ 120 121 void 122 memxor(void *res, const void *src, size_t len) 123 { 124 int i; 125 char *r; 126 const char *s; 127 128 r = res; 129 s = src; 130 for (i=0; i < len; i++) 131 r[i] ^= s[i]; 132 } 133 134 /* 135 * well, a very simple set of string functions... 136 * 137 * The goal here is basically to manage length encoded strings, 138 * but just for safety we nul terminate them anyway. 139 */ 140 141 /* for now we use a very simple encoding */ 142 143 struct string { 144 int length; 145 char *text; 146 }; 147 148 string_t * 149 string_new(const char *intext, int inlength) 150 { 151 string_t *out; 152 153 out = emalloc(sizeof(*out)); 154 out->length = inlength; 155 out->text = emalloc(out->length + 1); 156 memcpy(out->text, intext, out->length); 157 out->text[out->length] = '\0'; 158 return out; 159 } 160 161 string_t * 162 string_dup(const string_t *in) 163 { 164 165 return string_new(in->text, in->length); 166 } 167 168 void 169 string_free(string_t *s) 170 { 171 172 if (!s) 173 return; 174 free(s->text); 175 free(s); 176 } 177 178 void 179 string_assign(string_t **lhs, string_t *rhs) 180 { 181 182 string_free(*lhs); 183 *lhs = rhs; 184 } 185 186 string_t * 187 string_add(const string_t *a1, const string_t *a2) 188 { 189 string_t *sum; 190 191 sum = emalloc(sizeof(*sum)); 192 sum->length = a1->length + a2->length; 193 sum->text = emalloc(sum->length + 1); 194 memcpy(sum->text, a1->text, a1->length); 195 memcpy(sum->text + a1->length, a2->text, a2->length); 196 sum->text[sum->length] = '\0'; 197 return sum; 198 } 199 200 string_t * 201 string_add_d(string_t *a1, string_t *a2) 202 { 203 string_t *sum; 204 205 sum = string_add(a1, a2); 206 string_free(a1); 207 string_free(a2); 208 return sum; 209 } 210 211 string_t * 212 string_fromcharstar(const char *in) 213 { 214 215 return string_new(in, strlen(in)); 216 } 217 218 const char * 219 string_tocharstar(const string_t *in) 220 { 221 222 return in->text; 223 } 224 225 string_t * 226 string_fromint(int in) 227 { 228 string_t *ret; 229 230 ret = emalloc(sizeof(*ret)); 231 ret->length = asprintf(&ret->text, "%d", in); 232 if (ret->length == -1) 233 err(1, NULL); 234 return ret; 235 } 236 237 void 238 string_fprint(FILE *f, const string_t *s) 239 { 240 241 fwrite(s->text, s->length, 1, f); 242 } 243 244 struct bits { 245 int length; 246 char *text; 247 }; 248 249 bits_t * 250 bits_new(const void *buf, int len) 251 { 252 bits_t *b; 253 254 b = emalloc(sizeof(*b)); 255 b->length = len; 256 b->text = emalloc(BITS2BYTES(b->length)); 257 memcpy(b->text, buf, BITS2BYTES(b->length)); 258 return b; 259 } 260 261 bits_t * 262 bits_dup(const bits_t *in) 263 { 264 265 return bits_new(in->text, in->length); 266 } 267 268 void 269 bits_free(bits_t *b) 270 { 271 272 if (!b) 273 return; 274 free(b->text); 275 free(b); 276 } 277 278 void 279 bits_assign(bits_t **lhs, bits_t *rhs) 280 { 281 282 bits_free(*lhs); 283 *lhs = rhs; 284 } 285 286 const void * 287 bits_getbuf(bits_t *in) 288 { 289 290 return in->text; 291 } 292 293 int 294 bits_len(bits_t *in) 295 { 296 297 return in->length; 298 } 299 300 int 301 bits_match(const bits_t *b1, const bits_t *b2) 302 { 303 int i; 304 305 if (b1->length != b2->length) 306 return 0; 307 308 for (i = 0; i < BITS2BYTES(b1->length); i++) 309 if (b1->text[i] != b2->text[i]) 310 return 0; 311 312 return 1; 313 } 314 315 bits_t * 316 bits_xor(const bits_t *x1, const bits_t *x2) 317 { 318 bits_t *b; 319 int i; 320 321 b = emalloc(sizeof(*b)); 322 b->length = MAX(x1->length, x2->length); 323 b->text = ecalloc(1, BITS2BYTES(b->length)); 324 for (i=0; i < BITS2BYTES(MIN(x1->length, x2->length)); i++) 325 b->text[i] = x1->text[i] ^ x2->text[i]; 326 return b; 327 } 328 329 bits_t * 330 bits_xor_d(bits_t *x1, bits_t *x2) 331 { 332 bits_t *ret; 333 334 ret = bits_xor(x1, x2); 335 bits_free(x1); 336 bits_free(x2); 337 return ret; 338 } 339 340 /* 341 * bits_decode() reads an encoded base64 stream. We interpret 342 * the first 32 bits as an unsigned integer in network byte order 343 * specifying the number of bits in the stream to give a little 344 * resilience. 345 */ 346 347 bits_t * 348 bits_decode(const string_t *in) 349 { 350 bits_t *ret; 351 int len; 352 int nbits; 353 u_char *tmp; 354 355 len = in->length; 356 tmp = emalloc(len); 357 358 len = __b64_pton(in->text, tmp, len); 359 360 if (len == -1) { 361 fprintf(stderr, "bits_decode: mangled base64 stream\n"); 362 fprintf(stderr, " %s\n", in->text); 363 free(tmp); 364 return NULL; 365 } 366 367 nbits = ntohl(*((u_int32_t *)tmp)); 368 if (nbits > (len - 4) * 8) { 369 fprintf(stderr, "bits_decode: encoded bits claim to be " 370 "longer than they are (nbits=%u, stream len=%u bytes)\n", 371 (unsigned)nbits, (unsigned)len); 372 free(tmp); 373 return NULL; 374 } 375 376 ret = bits_new(tmp+4, nbits); 377 free(tmp); 378 return ret; 379 } 380 381 bits_t * 382 bits_decode_d(string_t *in) 383 { 384 bits_t *ret; 385 386 ret = bits_decode(in); 387 string_free(in); 388 return ret; 389 } 390 391 string_t * 392 bits_encode(const bits_t *in) 393 { 394 string_t *ret; 395 int len; 396 char *out; 397 u_char *tmp; 398 399 if (!in) 400 return NULL; 401 402 /* compute the total size of the input stream */ 403 len = BITS2BYTES(in->length) + 4; 404 405 tmp = emalloc(len); 406 out = emalloc(len * 2); 407 /* stuff the length up front */ 408 *((u_int32_t *)tmp) = htonl(in->length); 409 memcpy(tmp + 4, in->text, len - 4); 410 411 if ((len = __b64_ntop(tmp, len, out, len * 2)) == -1) { 412 free(out); 413 free(tmp); 414 return NULL; 415 } 416 ret = string_new(out, len); 417 free(tmp); 418 free(out); 419 return ret; 420 } 421 422 string_t * 423 bits_encode_d(bits_t *in) 424 { 425 string_t *ret; 426 427 ret = bits_encode(in); 428 bits_free(in); 429 return ret; 430 } 431 432 bits_t * 433 bits_fget(FILE *f, int len) 434 { 435 bits_t *bits; 436 int ret; 437 438 bits = emalloc(sizeof(*bits)); 439 bits->length = len; 440 bits->text = emalloc(BITS2BYTES(bits->length)); 441 ret = fread(bits->text, BITS2BYTES(bits->length), 1, f); 442 if (ret != 1) { 443 bits_free(bits); 444 return NULL; 445 } 446 return bits; 447 } 448 449 bits_t * 450 bits_cget(const char *fn, int len) 451 { 452 bits_t *bits; 453 FILE *f; 454 455 f = fopen(fn, "r"); 456 if (!f) 457 return NULL; 458 459 bits = bits_fget(f, len); 460 fclose(f); 461 return bits; 462 } 463 464 bits_t * 465 bits_getrandombits(int len, int hard) 466 { 467 468 return bits_cget((hard ? "/dev/random" : "/dev/urandom"), len); 469 } 470 471 void 472 bits_fprint(FILE *f, const bits_t *bits) 473 { 474 string_t *s; 475 476 s = bits_encode(bits); 477 string_fprint(f, s); 478 free(s); 479 } 480