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>