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>