Annotation of embedaddon/dhcp/dst/dst_support.c, revision 1.1.1.1

1.1.1.1 ! misho       1: static const char rcsid[] = "$Header: /tmp/cvstest/DHCP/dst/dst_support.c,v 1.4 2007/12/06 00:50:22 dhankins Exp $";
1.1       misho       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>