Annotation of embedaddon/dhcp/minires/ns_sign.c, revision 1.1.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
1.1.1.1 ! misho 25: static const char rcsid[] = "$Id: ns_sign.c,v 1.6.786.2 2009/07/24 22:04:52 sar Exp $";
1.1 misho 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>