Annotation of embedaddon/dhcp/dst/dst_support.c, revision 1.1
1.1 ! misho 1: static const char rcsid[] = "$Header: /proj/cvs/prod/DHCP/dst/dst_support.c,v 1.4 2007-12-06 00:50:22 dhankins Exp $";
! 2:
! 3:
! 4: /*
! 5: * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
! 6: * Portions Copyright (c) 2007 by Internet Systems Consortium, Inc. ("ISC")
! 7: *
! 8: * Permission to use, copy modify, and distribute this software for any
! 9: * purpose with or without fee is hereby granted, provided that the above
! 10: * copyright notice and this permission notice appear in all copies.
! 11: *
! 12: * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS
! 13: * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
! 14: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
! 15: * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT,
! 16: * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
! 17: * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
! 18: * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
! 19: * WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
! 20: */
! 21:
! 22: #include <stdio.h>
! 23: #include <unistd.h>
! 24: #include <memory.h>
! 25: #include <string.h>
! 26: #include <errno.h>
! 27: #include <sys/stat.h>
! 28: #include <netinet/in.h>
! 29: #include <sys/socket.h>
! 30:
! 31: #include "minires/minires.h"
! 32: #include "arpa/nameser.h"
! 33:
! 34: #include "dst_internal.h"
! 35:
! 36: /*
! 37: * dst_s_conv_bignum_u8_to_b64
! 38: * This function converts binary data stored as a u_char[] to a
! 39: * base-64 string. Leading zeroes are discarded. If a header is
! 40: * supplied, it is prefixed to the input prior to encoding. The
! 41: * output is \n\0 terminated (the \0 is not included in output length).
! 42: * Parameters
! 43: * out_buf binary data to convert
! 44: * header character string to prefix to the output (label)
! 45: * bin_data binary data
! 46: * bin_len size of binary data
! 47: * Return
! 48: * -1 not enough space in output work area
! 49: * 0 no output
! 50: * >0 number of bytes written to output work area
! 51: */
! 52:
! 53: int
! 54: dst_s_conv_bignum_u8_to_b64(char *out_buf, const unsigned out_len,
! 55: const char *header, const u_char *bin_data,
! 56: const unsigned bin_len)
! 57: {
! 58: const u_char *bp = bin_data;
! 59: char *op = out_buf;
! 60: unsigned lenh = 0, len64 = 0;
! 61: unsigned local_in_len = bin_len;
! 62: unsigned local_out_len = out_len;
! 63:
! 64: if (bin_data == NULL) /* no data no */
! 65: return (0);
! 66:
! 67: if (out_buf == NULL || out_len <= 0) /* no output_work area */
! 68: return (-1);
! 69:
! 70: /* suppress leading \0 */
! 71: for (; (*bp == 0x0) && (local_in_len > 0); local_in_len--)
! 72: bp++;
! 73:
! 74: if (header) { /* add header to output string */
! 75: lenh = strlen(header);
! 76: if (lenh < out_len)
! 77: memcpy(op, header, lenh);
! 78: else
! 79: return (-1);
! 80: local_out_len -= lenh;
! 81: op += lenh;
! 82: }
! 83: len64 = b64_ntop(bp, local_in_len, op, local_out_len - 2);
! 84: if (len64 < 0)
! 85: return (-1);
! 86: op += len64++;
! 87: *(op++) = '\n'; /* put CR in the output */
! 88: *op = '\0'; /* make sure output is 0 terminated */
! 89: return (lenh + len64);
! 90: }
! 91:
! 92:
! 93: /*
! 94: * dst_s_verify_str()
! 95: * Validate that the input string(*str) is at the head of the input
! 96: * buffer(**buf). If so, move the buffer head pointer (*buf) to
! 97: * the first byte of data following the string(*str).
! 98: * Parameters
! 99: * buf Input buffer.
! 100: * str Input string.
! 101: * Return
! 102: * 0 *str is not the head of **buff
! 103: * 1 *str is the head of **buff, *buf is is advanced to
! 104: * the tail of **buf.
! 105: */
! 106:
! 107: int
! 108: dst_s_verify_str(const char **buf, const char *str)
! 109: {
! 110: unsigned b, s;
! 111: if (*buf == NULL) /* error checks */
! 112: return (0);
! 113: if (str == NULL || *str == '\0')
! 114: return (1);
! 115:
! 116: b = strlen(*buf); /* get length of strings */
! 117: s = strlen(str);
! 118: if (s > b || strncmp(*buf, str, s)) /* check if same */
! 119: return (0); /* not a match */
! 120: (*buf) += s; /* advance pointer */
! 121: return (1);
! 122: }
! 123:
! 124:
! 125: /*
! 126: * dst_s_conv_bignum_b64_to_u8
! 127: * Read a line of base-64 encoded string from the input buffer,
! 128: * convert it to binary, and store it in an output area. The
! 129: * input buffer is read until reaching a newline marker or the
! 130: * end of the buffer. The binary data is stored in the last X
! 131: * number of bytes of the output area where X is the size of the
! 132: * binary output. If the operation is successful, the input buffer
! 133: * pointer is advanced. This procedure does not do network to host
! 134: * byte order conversion.
! 135: * Parameters
! 136: * buf Pointer to encoded input string. Pointer is updated if
! 137: * function is successful.
! 138: * loc Output area.
! 139: * loclen Size in bytes of output area.
! 140: * Return
! 141: * >0 Return = number of bytes of binary data stored in loc.
! 142: * 0 Failure.
! 143: */
! 144:
! 145: int
! 146: dst_s_conv_bignum_b64_to_u8(const char **buf,
! 147: u_char *loc, const unsigned loclen)
! 148: {
! 149: unsigned blen;
! 150: char *bp;
! 151: u_char bstr[RAW_KEY_SIZE];
! 152:
! 153: if (buf == NULL || *buf == NULL) { /* error checks */
! 154: EREPORT(("dst_s_conv_bignum_b64_to_u8: null input buffer.\n"));
! 155: return (0);
! 156: }
! 157: bp = strchr(*buf, '\n'); /* find length of input line */
! 158: if (bp != NULL)
! 159: *bp = '\0';
! 160:
! 161: blen = b64_pton(*buf, bstr, sizeof(bstr));
! 162: if (blen <= 0) {
! 163: EREPORT(("dst_s_conv_bignum_b64_to_u8: decoded value is null.\n"));
! 164: return (0);
! 165: }
! 166: else if (loclen < blen) {
! 167: EREPORT(("dst_s_conv_bignum_b64_to_u8: decoded value is longer than output buffer.\n"));
! 168: return (0);
! 169: }
! 170: if (bp)
! 171: *buf = bp; /* advancing buffer past \n */
! 172: memset(loc, 0, loclen - blen); /* clearing unused output area */
! 173: memcpy(loc + loclen - blen, bstr, blen); /* write last blen bytes */
! 174: return (blen);
! 175: }
! 176:
! 177:
! 178: /*
! 179: * dst_s_calculate_bits
! 180: * Given a binary number represented in a u_char[], determine
! 181: * the number of significant bits used.
! 182: * Parameters
! 183: * str An input character string containing a binary number.
! 184: * max_bits The maximum possible significant bits.
! 185: * Return
! 186: * N The number of significant bits in str.
! 187: */
! 188:
! 189: int
! 190: dst_s_calculate_bits(const u_char *str, const int max_bits)
! 191: {
! 192: const u_char *p = str;
! 193: u_char i, j = 0x80;
! 194: int bits;
! 195: for (bits = max_bits; *p == 0x00 && bits > 0; p++)
! 196: bits -= 8;
! 197: for (i = *p; (i & j) != j; j >>= 1)
! 198: bits--;
! 199: return (bits);
! 200: }
! 201:
! 202:
! 203: /*
! 204: * calculates a checksum used in kmt for a id.
! 205: * takes an array of bytes and a length.
! 206: * returns a 16 bit checksum.
! 207: */
! 208: u_int16_t
! 209: dst_s_id_calc(const u_char *key, const unsigned keysize)
! 210: {
! 211: u_int32_t ac;
! 212: const u_char *kp = key;
! 213: unsigned size = keysize;
! 214:
! 215: if (!key)
! 216: return 0;
! 217:
! 218: for (ac = 0; size > 1; size -= 2, kp += 2)
! 219: ac += ((*kp) << 8) + *(kp + 1);
! 220:
! 221: if (size > 0)
! 222: ac += ((*kp) << 8);
! 223: ac += (ac >> 16) & 0xffff;
! 224:
! 225: return (ac & 0xffff);
! 226: }
! 227:
! 228: /*
! 229: * dst_s_dns_key_id() Function to calculated DNSSEC footprint from KEY record
! 230: * rdata (all of record)
! 231: * Input:
! 232: * dns_key_rdata: the raw data in wire format
! 233: * rdata_len: the size of the input data
! 234: * Output:
! 235: * the key footprint/id calculated from the key data
! 236: */
! 237: u_int16_t
! 238: dst_s_dns_key_id(const u_char *dns_key_rdata, const unsigned rdata_len)
! 239: {
! 240: unsigned key_data = 4;
! 241:
! 242: if (!dns_key_rdata || (rdata_len < key_data))
! 243: return 0;
! 244:
! 245: /* check the extended parameters bit in the DNS Key RR flags */
! 246: if (dst_s_get_int16(dns_key_rdata) & DST_EXTEND_FLAG)
! 247: key_data += 2;
! 248:
! 249: /* compute id */
! 250: if (dns_key_rdata[3] == KEY_RSA) /* Algorithm RSA */
! 251: return dst_s_get_int16((const u_char *)
! 252: &dns_key_rdata[rdata_len - 3]);
! 253: else
! 254: /* compute a checksum on the key part of the key rr */
! 255: return dst_s_id_calc(&dns_key_rdata[key_data],
! 256: (rdata_len - key_data));
! 257: }
! 258:
! 259: /*
! 260: * dst_s_get_int16
! 261: * This routine extracts a 16 bit integer from a two byte character
! 262: * string. The character string is assumed to be in network byte
! 263: * order and may be unaligned. The number returned is in host order.
! 264: * Parameter
! 265: * buf A two byte character string.
! 266: * Return
! 267: * The converted integer value.
! 268: */
! 269:
! 270: u_int16_t
! 271: dst_s_get_int16(const u_char *buf)
! 272: {
! 273: register u_int16_t a = 0;
! 274: a = ((u_int16_t)(buf[0] << 8)) | ((u_int16_t)(buf[1]));
! 275: return (a);
! 276: }
! 277:
! 278:
! 279: /*
! 280: * dst_s_get_int32
! 281: * This routine extracts a 32 bit integer from a four byte character
! 282: * string. The character string is assumed to be in network byte
! 283: * order and may be unaligned. The number returned is in host order.
! 284: * Parameter
! 285: * buf A four byte character string.
! 286: * Return
! 287: * The converted integer value.
! 288: */
! 289:
! 290: u_int32_t
! 291: dst_s_get_int32(const u_char *buf)
! 292: {
! 293: register u_int32_t a = 0;
! 294: a = ((u_int32_t)(buf[0] << 24)) | ((u_int32_t)(buf[1] << 16)) |
! 295: ((u_int32_t)(buf[2] << 8)) | ((u_int32_t)(buf[3]));
! 296: return (a);
! 297: }
! 298:
! 299:
! 300: /*
! 301: * dst_s_put_int16
! 302: * Take a 16 bit integer and store the value in a two byte
! 303: * character string. The integer is assumed to be in network
! 304: * order and the string is returned in host order.
! 305: *
! 306: * Parameters
! 307: * buf Storage for a two byte character string.
! 308: * val 16 bit integer.
! 309: */
! 310:
! 311: void
! 312: dst_s_put_int16(u_int8_t *buf, const u_int16_t val)
! 313: {
! 314: buf[0] = (u_int8_t)(val >> 8);
! 315: buf[1] = (u_int8_t)(val);
! 316: }
! 317:
! 318:
! 319: /*
! 320: * dst_s_put_int32
! 321: * Take a 32 bit integer and store the value in a four byte
! 322: * character string. The integer is assumed to be in network
! 323: * order and the string is returned in host order.
! 324: *
! 325: * Parameters
! 326: * buf Storage for a four byte character string.
! 327: * val 32 bit integer.
! 328: */
! 329:
! 330: void
! 331: dst_s_put_int32(u_int8_t *buf, const u_int32_t val)
! 332: {
! 333: buf[0] = (u_int8_t)(val >> 24);
! 334: buf[1] = (u_int8_t)(val >> 16);
! 335: buf[2] = (u_int8_t)(val >> 8);
! 336: buf[3] = (u_int8_t)(val);
! 337: }
! 338:
! 339:
! 340: /*
! 341: * dst_s_filename_length
! 342: *
! 343: * This function returns the number of bytes needed to hold the
! 344: * filename for a key file. '/', '\' and ':' are not allowed.
! 345: * form: K<keyname>+<alg>+<id>.<suffix>
! 346: *
! 347: * Returns 0 if the filename would contain either '\', '/' or ':'
! 348: */
! 349: size_t
! 350: dst_s_filename_length(const char *name, const char *suffix)
! 351: {
! 352: if (name == NULL)
! 353: return (0);
! 354: if (strrchr(name, '\\'))
! 355: return (0);
! 356: if (strrchr(name, '/'))
! 357: return (0);
! 358: if (strrchr(name, ':'))
! 359: return (0);
! 360: if (suffix == NULL)
! 361: return (0);
! 362: if (strrchr(suffix, '\\'))
! 363: return (0);
! 364: if (strrchr(suffix, '/'))
! 365: return (0);
! 366: if (strrchr(suffix, ':'))
! 367: return (0);
! 368: return (1 + strlen(name) + 6 + strlen(suffix));
! 369: }
! 370:
! 371:
! 372: /*
! 373: * dst_s_build_filename ()
! 374: * Builds a key filename from the key name, it's id, and a
! 375: * suffix. '\', '/' and ':' are not allowed. fA filename is of the
! 376: * form: K<keyname><id>.<suffix>
! 377: * form: K<keyname>+<alg>+<id>.<suffix>
! 378: *
! 379: * Returns -1 if the conversion fails:
! 380: * if the filename would be too long for space allotted
! 381: * if the filename would contain a '\', '/' or ':'
! 382: * Returns 0 on success
! 383: */
! 384:
! 385: int
! 386: dst_s_build_filename(char *filename, const char *name, unsigned id,
! 387: int alg, const char *suffix, size_t filename_length)
! 388: {
! 389: unsigned my_id;
! 390: if (filename == NULL)
! 391: return (-1);
! 392: memset(filename, 0, filename_length);
! 393: if (name == NULL)
! 394: return (-1);
! 395: if (suffix == NULL)
! 396: return (-1);
! 397: if (filename_length < 1 + strlen(name) + 4 + 6 + 1 + strlen(suffix))
! 398: return (-1);
! 399: my_id = id;
! 400: sprintf(filename, "K%s+%03d+%05d.%s", name, alg, my_id,
! 401: (const char *) suffix);
! 402: if (strrchr(filename, '/'))
! 403: return (-1);
! 404: if (strrchr(filename, '\\'))
! 405: return (-1);
! 406: if (strrchr(filename, ':'))
! 407: return (-1);
! 408: return (0);
! 409: }
! 410:
! 411: /*
! 412: * dst_s_fopen ()
! 413: * Open a file in the dst_path directory. If perm is specified, the
! 414: * file is checked for existence first, and not opened if it exists.
! 415: * Parameters
! 416: * filename File to open
! 417: * mode Mode to open the file (passed directly to fopen)
! 418: * perm File permission, if creating a new file.
! 419: * Returns
! 420: * NULL Failure
! 421: * NON-NULL (FILE *) of opened file.
! 422: */
! 423: FILE *
! 424: dst_s_fopen(const char *filename, const char *mode, unsigned perm)
! 425: {
! 426: FILE *fp;
! 427: char pathname[PATH_MAX];
! 428: unsigned plen = sizeof(pathname);
! 429:
! 430: if (*dst_path != '\0') {
! 431: strcpy(pathname, dst_path);
! 432: plen -= strlen(pathname);
! 433: }
! 434: else
! 435: pathname[0] = '\0';
! 436:
! 437: if (plen > strlen(filename))
! 438: strncpy(&pathname[PATH_MAX - plen], filename, plen-1);
! 439: else
! 440: return (NULL);
! 441:
! 442: fp = fopen(pathname, mode);
! 443: if (perm)
! 444: chmod(pathname, perm);
! 445: return (fp);
! 446: }
! 447:
! 448: #if 0
! 449: void
! 450: dst_s_dump(const int mode, const u_char *data, const int size,
! 451: const char *msg)
! 452: {
! 453: if (size > 0) {
! 454: #ifdef LONG_TEST
! 455: static u_char scratch[1000];
! 456: int n ;
! 457: n = b64_ntop(data, scratch, size, sizeof(scratch));
! 458: printf("%s: %x %d %s\n", msg, mode, n, scratch);
! 459: #else
! 460: printf("%s,%x %d\n", msg, mode, size);
! 461: #endif
! 462: }
! 463: }
! 464: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>