[BACK]Return to ns_sign.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libresolv

Annotation of src/lib/libresolv/ns_sign.c, Revision 1.1

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

CVSweb <webmaster@jp.NetBSD.org>