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