File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dhcp / dst / dst_support.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:06:54 2012 UTC (11 years, 8 months ago) by misho
Branches: dhcp, MAIN
CVS tags: v4_1_R7p0, v4_1_R7, v4_1_R4, HEAD
dhcp 4.1 r7

    1: static const char rcsid[] = "$Header: /usr/local/www/users/anoncvs/cvs/embedaddon/dhcp/dst/dst_support.c,v 1.1.1.1 2012/10/09 09:06:54 misho 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>