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>