Annotation of embedaddon/dhcp/minires/ns_sign.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (c) 2004,2009 by Internet Systems Consortium, Inc. ("ISC")
        !             3:  * Copyright (c) 1999-2003 by Internet Software Consortium
        !             4:  *
        !             5:  * Permission to use, copy, modify, and distribute this software for any
        !             6:  * purpose with or without fee is hereby granted, provided that the above
        !             7:  * copyright notice and this permission notice appear in all copies.
        !             8:  *
        !             9:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
        !            10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            11:  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
        !            12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
        !            15:  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            16:  *
        !            17:  *   Internet Systems Consortium, Inc.
        !            18:  *   950 Charter Street
        !            19:  *   Redwood City, CA 94063
        !            20:  *   <info@isc.org>
        !            21:  *   https://www.isc.org/
        !            22:  */
        !            23: 
        !            24: #ifndef lint
        !            25: static const char rcsid[] = "$Id: ns_sign.c,v 1.6.786.2 2009-07-24 22:04:52 sar Exp $";
        !            26: #endif
        !            27: 
        !            28: #if defined (TRACING)
        !            29: #define time(x)                trace_mr_time (x)
        !            30: time_t trace_mr_time (time_t *);
        !            31: #endif
        !            32: 
        !            33: /* Import. */
        !            34: 
        !            35: #include <sys/types.h>
        !            36: #include <sys/param.h>
        !            37: 
        !            38: #include <netinet/in.h>
        !            39: #include <arpa/inet.h>
        !            40: #include <sys/socket.h>
        !            41: 
        !            42: #include <errno.h>
        !            43: #include <netdb.h>
        !            44: #include <stdio.h>
        !            45: #include <stdlib.h>
        !            46: #include <string.h>
        !            47: #include <unistd.h>
        !            48: #include <time.h>
        !            49: 
        !            50: #include "minires/minires.h"
        !            51: #include "arpa/nameser.h"
        !            52: 
        !            53: #include <isc-dhcp/dst.h>
        !            54: 
        !            55: #define BOUNDS_CHECK(ptr, count) \
        !            56:        do { \
        !            57:                if ((ptr) + (count) > eob) { \
        !            58:                        return ISC_R_NOSPACE; \
        !            59:                } \
        !            60:        } while (0)
        !            61: 
        !            62: /* ns_sign
        !            63:  * Parameters:
        !            64:  *     msg             message to be sent
        !            65:  *     msglen          input - length of message
        !            66:  *                     output - length of signed message
        !            67:  *     msgsize         length of buffer containing message
        !            68:  *     error           value to put in the error field
        !            69:  *     key             tsig key used for signing
        !            70:  *     querysig        (response), the signature in the query
        !            71:  *     querysiglen     (response), the length of the signature in the query
        !            72:  *     sig             a buffer to hold the generated signature
        !            73:  *     siglen          input - length of signature buffer
        !            74:  *                     output - length of signature
        !            75:  *
        !            76:  * Errors:
        !            77:  *     - bad input data (-1)
        !            78:  *     - bad key / sign failed (-BADKEY)
        !            79:  *     - not enough space (NS_TSIG_ERROR_NO_SPACE)
        !            80:  */
        !            81: isc_result_t
        !            82: ns_sign(u_char *msg, unsigned *msglen, unsigned msgsize, int error, void *k,
        !            83:        const u_char *querysig, unsigned querysiglen, u_char *sig,
        !            84:        unsigned *siglen, time_t in_timesigned)
        !            85: {
        !            86:        HEADER *hp = (HEADER *)msg;
        !            87:        DST_KEY *key = (DST_KEY *)k;
        !            88:        u_char *cp = msg + *msglen, *eob = msg + msgsize;
        !            89:        u_char *lenp;
        !            90:        u_char *name, *alg;
        !            91:        unsigned n;
        !            92:        time_t timesigned;
        !            93: 
        !            94:        dst_init();
        !            95:        if (msg == NULL || msglen == NULL || sig == NULL || siglen == NULL)
        !            96:                return ISC_R_INVALIDARG;
        !            97: 
        !            98:        /* Name. */
        !            99:        if (key != NULL && error != ns_r_badsig && error != ns_r_badkey)
        !           100:                n = dn_comp(key->dk_key_name,
        !           101:                            cp, (unsigned)(eob - cp), NULL, NULL);
        !           102:        else
        !           103:                n = dn_comp("", cp, (unsigned)(eob - cp), NULL, NULL);
        !           104:        if (n < 0)
        !           105:                return ISC_R_NOSPACE;
        !           106:        name = cp;
        !           107:        cp += n;
        !           108: 
        !           109:        /* Type, class, ttl, length (not filled in yet). */
        !           110:        BOUNDS_CHECK(cp, INT16SZ + INT16SZ + INT32SZ + INT16SZ);
        !           111:        PUTSHORT(ns_t_tsig, cp);
        !           112:        PUTSHORT(ns_c_any, cp);
        !           113:        PUTLONG(0, cp);         /* TTL */
        !           114:        lenp = cp;
        !           115:        cp += 2;
        !           116: 
        !           117:        /* Alg. */
        !           118:        if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) {
        !           119:                if (key->dk_alg != KEY_HMAC_MD5)
        !           120:                        return ISC_R_BADKEY;
        !           121:                n = dn_comp(NS_TSIG_ALG_HMAC_MD5,
        !           122:                            cp, (unsigned)(eob - cp), NULL, NULL);
        !           123:        }
        !           124:        else
        !           125:                n = dn_comp("", cp, (unsigned)(eob - cp), NULL, NULL);
        !           126:        if (n < 0)
        !           127:                return ISC_R_NOSPACE;
        !           128:        alg = cp;
        !           129:        cp += n;
        !           130:        
        !           131:        /* Time. */
        !           132:        BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ);
        !           133:        PUTSHORT(0, cp);
        !           134:        timesigned = time(NULL);
        !           135:        if (error != ns_r_badtime)
        !           136:                PUTLONG(timesigned, cp);
        !           137:        else
        !           138:                PUTLONG(in_timesigned, cp);
        !           139:        PUTSHORT(NS_TSIG_FUDGE, cp);
        !           140: 
        !           141:        /* Compute the signature. */
        !           142:        if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) {
        !           143:                void *ctx;
        !           144:                u_char buf[MAXDNAME], *cp2;
        !           145:                unsigned n;
        !           146: 
        !           147:                dst_sign_data(SIG_MODE_INIT, key, &ctx, NULL, 0, NULL, 0);
        !           148: 
        !           149:                /* Digest the query signature, if this is a response. */
        !           150:                if (querysiglen > 0 && querysig != NULL) {
        !           151:                        u_int16_t len_n = htons(querysiglen);
        !           152:                        dst_sign_data(SIG_MODE_UPDATE, key, &ctx,
        !           153:                                      (u_char *)&len_n, INT16SZ, NULL, 0);
        !           154:                        dst_sign_data(SIG_MODE_UPDATE, key, &ctx,
        !           155:                                      querysig, querysiglen, NULL, 0);
        !           156:                }
        !           157: 
        !           158:                /* Digest the message. */
        !           159:                dst_sign_data(SIG_MODE_UPDATE, key, &ctx, msg, *msglen,
        !           160:                              NULL, 0);
        !           161: 
        !           162:                /* Digest the key name. */
        !           163:                n = ns_name_ntol(name, buf, sizeof(buf));
        !           164:                dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0);
        !           165: 
        !           166:                /* Digest the class and TTL. */
        !           167:                cp2 = buf;
        !           168:                PUTSHORT(ns_c_any, cp2);
        !           169:                PUTLONG(0, cp2);
        !           170:                dst_sign_data(SIG_MODE_UPDATE, key, &ctx,
        !           171:                              buf, (unsigned)(cp2-buf), NULL, 0);
        !           172: 
        !           173:                /* Digest the algorithm. */
        !           174:                n = ns_name_ntol(alg, buf, sizeof(buf));
        !           175:                dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0);
        !           176: 
        !           177:                /* Digest the time signed, fudge, error, and other data */
        !           178:                cp2 = buf;
        !           179:                PUTSHORT(0, cp2);       /* Top 16 bits of time */
        !           180:                if (error != ns_r_badtime)
        !           181:                        PUTLONG(timesigned, cp2);
        !           182:                else
        !           183:                        PUTLONG(in_timesigned, cp2);
        !           184:                PUTSHORT(NS_TSIG_FUDGE, cp2);
        !           185:                PUTSHORT(error, cp2);   /* Error */
        !           186:                if (error != ns_r_badtime)
        !           187:                        PUTSHORT(0, cp2);       /* Other data length */
        !           188:                else {
        !           189:                        PUTSHORT(INT16SZ+INT32SZ, cp2); /* Other data length */
        !           190:                        PUTSHORT(0, cp2);       /* Top 16 bits of time */
        !           191:                        PUTLONG(timesigned, cp2);
        !           192:                }
        !           193:                dst_sign_data(SIG_MODE_UPDATE, key, &ctx,
        !           194:                              buf, (unsigned)(cp2-buf), NULL, 0);
        !           195: 
        !           196:                n = dst_sign_data(SIG_MODE_FINAL, key, &ctx, NULL, 0,
        !           197:                                  sig, *siglen);
        !           198:                if (n < 0)
        !           199:                        return ISC_R_BADKEY;
        !           200:                *siglen = n;
        !           201:        } else
        !           202:                *siglen = 0;
        !           203: 
        !           204:        /* Add the signature. */
        !           205:        BOUNDS_CHECK(cp, INT16SZ + (*siglen));
        !           206:        PUTSHORT(*siglen, cp);
        !           207:        memcpy(cp, sig, *siglen);
        !           208:        cp += (*siglen);
        !           209: 
        !           210:        /* The original message ID & error. */
        !           211:        BOUNDS_CHECK(cp, INT16SZ + INT16SZ);
        !           212:        PUTSHORT(ntohs(hp->id), cp);    /* already in network order */
        !           213:        PUTSHORT(error, cp);
        !           214: 
        !           215:        /* Other data. */
        !           216:        BOUNDS_CHECK(cp, INT16SZ);
        !           217:        if (error != ns_r_badtime)
        !           218:                PUTSHORT(0, cp);        /* Other data length */
        !           219:        else {
        !           220:                PUTSHORT(INT16SZ+INT32SZ, cp);  /* Other data length */
        !           221:                BOUNDS_CHECK(cp, INT32SZ+INT16SZ);
        !           222:                PUTSHORT(0, cp);        /* Top 16 bits of time */
        !           223:                PUTLONG(timesigned, cp);
        !           224:        }
        !           225: 
        !           226:        /* Go back and fill in the length. */
        !           227:        PUTSHORT(cp - lenp - INT16SZ, lenp);
        !           228: 
        !           229:        hp->arcount = htons(ntohs(hp->arcount) + 1);
        !           230:        *msglen = (cp - msg);
        !           231:        return ISC_R_SUCCESS;
        !           232: }
        !           233: 
        !           234: #if 0
        !           235: isc_result_t
        !           236: ns_sign_tcp_init(void *k, const u_char *querysig, unsigned querysiglen,
        !           237:                 ns_tcp_tsig_state *state)
        !           238: {
        !           239:        dst_init();
        !           240:        if (state == NULL || k == NULL || querysig == NULL || querysiglen < 0)
        !           241:                return ISC_R_INVALIDARG;
        !           242:        state->counter = -1;
        !           243:        state->key = k;
        !           244:        if (state->key->dk_alg != KEY_HMAC_MD5)
        !           245:                return ISC_R_BADKEY;
        !           246:        if (querysiglen > sizeof(state->sig))
        !           247:                return ISC_R_NOSPACE;
        !           248:        memcpy(state->sig, querysig, querysiglen);
        !           249:        state->siglen = querysiglen;
        !           250:        return ISC_R_SUCCESS;
        !           251: }
        !           252: 
        !           253: isc_result_t
        !           254: ns_sign_tcp(u_char *msg, unsigned *msglen, unsigned msgsize, int error,
        !           255:            ns_tcp_tsig_state *state, int done)
        !           256: {
        !           257:        u_char *cp, *eob, *lenp;
        !           258:        u_char buf[MAXDNAME], *cp2;
        !           259:        HEADER *hp = (HEADER *)msg;
        !           260:        time_t timesigned;
        !           261:        int n;
        !           262: 
        !           263:        if (msg == NULL || msglen == NULL || state == NULL)
        !           264:                return ISC_R_INVALIDARG;
        !           265: 
        !           266:        state->counter++;
        !           267:        if (state->counter == 0)
        !           268:                return ns_sign(msg, msglen, msgsize, error, state->key,
        !           269:                               state->sig, state->siglen,
        !           270:                               state->sig, &state->siglen, 0);
        !           271: 
        !           272:        if (state->siglen > 0) {
        !           273:                u_int16_t siglen_n = htons(state->siglen);
        !           274:                dst_sign_data(SIG_MODE_INIT, state->key, &state->ctx,
        !           275:                              NULL, 0, NULL, 0);
        !           276:                dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx,
        !           277:                              (u_char *)&siglen_n, INT16SZ, NULL, 0);
        !           278:                dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx,
        !           279:                              state->sig, state->siglen, NULL, 0);
        !           280:                state->siglen = 0;
        !           281:        }
        !           282: 
        !           283:        dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx, msg, *msglen,
        !           284:                      NULL, 0);
        !           285: 
        !           286:        if (done == 0 && (state->counter % 100 != 0))
        !           287:                return ISC_R_SUCCESS;
        !           288: 
        !           289:        cp = msg + *msglen;
        !           290:        eob = msg + msgsize;
        !           291: 
        !           292:        /* Name. */
        !           293:        n = dn_comp(state->key->dk_key_name,
        !           294:                    cp, (unsigned)(eob - cp), NULL, NULL);
        !           295:        if (n < 0)
        !           296:                return ISC_R_NOSPACE;
        !           297:        cp += n;
        !           298: 
        !           299:        /* Type, class, ttl, length (not filled in yet). */
        !           300:        BOUNDS_CHECK(cp, INT16SZ + INT16SZ + INT32SZ + INT16SZ);
        !           301:        PUTSHORT(ns_t_tsig, cp);
        !           302:        PUTSHORT(ns_c_any, cp);
        !           303:        PUTLONG(0, cp);         /* TTL */
        !           304:        lenp = cp;
        !           305:        cp += 2;
        !           306: 
        !           307:        /* Alg. */
        !           308:        n = dn_comp(NS_TSIG_ALG_HMAC_MD5,
        !           309:                    cp, (unsigned)(eob - cp), NULL, NULL);
        !           310:        if (n < 0)
        !           311:                return ISC_R_NOSPACE;
        !           312:        cp += n;
        !           313:        
        !           314:        /* Time. */
        !           315:        BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ);
        !           316:        PUTSHORT(0, cp);
        !           317:        timesigned = time(NULL);
        !           318:        PUTLONG(timesigned, cp);
        !           319:        PUTSHORT(NS_TSIG_FUDGE, cp);
        !           320: 
        !           321:        /*
        !           322:         * Compute the signature.
        !           323:         */
        !           324: 
        !           325:        /* Digest the time signed and fudge. */
        !           326:        cp2 = buf;
        !           327:        PUTSHORT(0, cp2);       /* Top 16 bits of time */
        !           328:        PUTLONG(timesigned, cp2);
        !           329:        PUTSHORT(NS_TSIG_FUDGE, cp2);
        !           330: 
        !           331:        dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx,
        !           332:                      buf, (unsigned)(cp2 - buf), NULL, 0);
        !           333: 
        !           334:        n = dst_sign_data(SIG_MODE_FINAL, state->key, &state->ctx, NULL, 0,
        !           335:                          state->sig, sizeof(state->sig));
        !           336:        if (n < 0)
        !           337:                return ISC_R_BADKEY;
        !           338:        state->siglen = n;
        !           339: 
        !           340:        /* Add the signature. */
        !           341:        BOUNDS_CHECK(cp, INT16SZ + state->siglen);
        !           342:        PUTSHORT(state->siglen, cp);
        !           343:        memcpy(cp, state->sig, state->siglen);
        !           344:        cp += state->siglen;
        !           345: 
        !           346:        /* The original message ID & error. */
        !           347:        BOUNDS_CHECK(cp, INT16SZ + INT16SZ);
        !           348:        PUTSHORT(ntohs(hp->id), cp);    /* already in network order */
        !           349:        PUTSHORT(error, cp);
        !           350: 
        !           351:        /* Other data. */
        !           352:        BOUNDS_CHECK(cp, INT16SZ);
        !           353:        PUTSHORT(0, cp);
        !           354: 
        !           355:        /* Go back and fill in the length. */
        !           356:        PUTSHORT(cp - lenp - INT16SZ, lenp);
        !           357: 
        !           358:        hp->arcount = htons(ntohs(hp->arcount) + 1);
        !           359:        *msglen = (cp - msg);
        !           360:        return ISC_R_SUCCESS;
        !           361: }
        !           362: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>