1*00b67f09SDavid van Moolenbroek /* $NetBSD: cc.c,v 1.8 2014/12/10 04:38:01 christos Exp $ */
2*00b67f09SDavid van Moolenbroek
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek * Portions Copyright (C) 2004-2007, 2012, 2013 Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek * Portions Copyright (C) 2001-2003 Internet Software Consortium.
6*00b67f09SDavid van Moolenbroek *
7*00b67f09SDavid van Moolenbroek * Permission to use, copy, modify, and/or distribute this software for any
8*00b67f09SDavid van Moolenbroek * purpose with or without fee is hereby granted, provided that the above
9*00b67f09SDavid van Moolenbroek * copyright notice and this permission notice appear in all copies.
10*00b67f09SDavid van Moolenbroek *
11*00b67f09SDavid van Moolenbroek * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NOMINUM DISCLAIMS ALL
12*00b67f09SDavid van Moolenbroek * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
13*00b67f09SDavid van Moolenbroek * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY
14*00b67f09SDavid van Moolenbroek * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15*00b67f09SDavid van Moolenbroek * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16*00b67f09SDavid van Moolenbroek * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17*00b67f09SDavid van Moolenbroek * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek *
19*00b67f09SDavid van Moolenbroek * Portions Copyright (C) 2001 Nominum, Inc.
20*00b67f09SDavid van Moolenbroek *
21*00b67f09SDavid van Moolenbroek * Permission to use, copy, modify, and/or distribute this software for any
22*00b67f09SDavid van Moolenbroek * purpose with or without fee is hereby granted, provided that the above
23*00b67f09SDavid van Moolenbroek * copyright notice and this permission notice appear in all copies.
24*00b67f09SDavid van Moolenbroek *
25*00b67f09SDavid van Moolenbroek * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NOMINUM DISCLAIMS ALL
26*00b67f09SDavid van Moolenbroek * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
27*00b67f09SDavid van Moolenbroek * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY
28*00b67f09SDavid van Moolenbroek * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
29*00b67f09SDavid van Moolenbroek * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
30*00b67f09SDavid van Moolenbroek * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
31*00b67f09SDavid van Moolenbroek * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
32*00b67f09SDavid van Moolenbroek */
33*00b67f09SDavid van Moolenbroek
34*00b67f09SDavid van Moolenbroek /* Id: cc.c,v 1.18 2007/08/28 07:20:43 tbox Exp */
35*00b67f09SDavid van Moolenbroek
36*00b67f09SDavid van Moolenbroek /*! \file */
37*00b67f09SDavid van Moolenbroek
38*00b67f09SDavid van Moolenbroek #include <config.h>
39*00b67f09SDavid van Moolenbroek
40*00b67f09SDavid van Moolenbroek #include <stdio.h>
41*00b67f09SDavid van Moolenbroek #include <string.h>
42*00b67f09SDavid van Moolenbroek #include <errno.h>
43*00b67f09SDavid van Moolenbroek
44*00b67f09SDavid van Moolenbroek #include <isc/assertions.h>
45*00b67f09SDavid van Moolenbroek #include <isc/hmacmd5.h>
46*00b67f09SDavid van Moolenbroek #include <isc/hmacsha.h>
47*00b67f09SDavid van Moolenbroek #include <isc/print.h>
48*00b67f09SDavid van Moolenbroek #include <isc/safe.h>
49*00b67f09SDavid van Moolenbroek #include <isc/stdlib.h>
50*00b67f09SDavid van Moolenbroek
51*00b67f09SDavid van Moolenbroek #include <isccc/alist.h>
52*00b67f09SDavid van Moolenbroek #include <isccc/base64.h>
53*00b67f09SDavid van Moolenbroek #include <isccc/cc.h>
54*00b67f09SDavid van Moolenbroek #include <isccc/result.h>
55*00b67f09SDavid van Moolenbroek #include <isccc/sexpr.h>
56*00b67f09SDavid van Moolenbroek #include <isccc/symtab.h>
57*00b67f09SDavid van Moolenbroek #include <isccc/symtype.h>
58*00b67f09SDavid van Moolenbroek #include <isccc/util.h>
59*00b67f09SDavid van Moolenbroek
60*00b67f09SDavid van Moolenbroek #define MAX_TAGS 256
61*00b67f09SDavid van Moolenbroek #define DUP_LIFETIME 900
62*00b67f09SDavid van Moolenbroek
63*00b67f09SDavid van Moolenbroek typedef isccc_sexpr_t *sexpr_ptr;
64*00b67f09SDavid van Moolenbroek
65*00b67f09SDavid van Moolenbroek static unsigned char auth_hmd5[] = {
66*00b67f09SDavid van Moolenbroek 0x05, 0x5f, 0x61, 0x75, 0x74, 0x68, /*%< len + _auth */
67*00b67f09SDavid van Moolenbroek ISCCC_CCMSGTYPE_TABLE, /*%< message type */
68*00b67f09SDavid van Moolenbroek 0x00, 0x00, 0x00, 0x20, /*%< length == 32 */
69*00b67f09SDavid van Moolenbroek 0x04, 0x68, 0x6d, 0x64, 0x35, /*%< len + hmd5 */
70*00b67f09SDavid van Moolenbroek ISCCC_CCMSGTYPE_BINARYDATA, /*%< message type */
71*00b67f09SDavid van Moolenbroek 0x00, 0x00, 0x00, 0x16, /*%< length == 22 */
72*00b67f09SDavid van Moolenbroek /*
73*00b67f09SDavid van Moolenbroek * The base64 encoding of one of our HMAC-MD5 signatures is
74*00b67f09SDavid van Moolenbroek * 22 bytes.
75*00b67f09SDavid van Moolenbroek */
76*00b67f09SDavid van Moolenbroek 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77*00b67f09SDavid van Moolenbroek 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
78*00b67f09SDavid van Moolenbroek 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
79*00b67f09SDavid van Moolenbroek };
80*00b67f09SDavid van Moolenbroek
81*00b67f09SDavid van Moolenbroek #define HMD5_OFFSET 21 /*%< 21 = 6 + 1 + 4 + 5 + 1 + 4 */
82*00b67f09SDavid van Moolenbroek #define HMD5_LENGTH 22
83*00b67f09SDavid van Moolenbroek
84*00b67f09SDavid van Moolenbroek static unsigned char auth_hsha[] = {
85*00b67f09SDavid van Moolenbroek 0x05, 0x5f, 0x61, 0x75, 0x74, 0x68, /*%< len + _auth */
86*00b67f09SDavid van Moolenbroek ISCCC_CCMSGTYPE_TABLE, /*%< message type */
87*00b67f09SDavid van Moolenbroek 0x00, 0x00, 0x00, 0x63, /*%< length == 99 */
88*00b67f09SDavid van Moolenbroek 0x04, 0x68, 0x73, 0x68, 0x61, /*%< len + hsha */
89*00b67f09SDavid van Moolenbroek ISCCC_CCMSGTYPE_BINARYDATA, /*%< message type */
90*00b67f09SDavid van Moolenbroek 0x00, 0x00, 0x00, 0x59, /*%< length == 89 */
91*00b67f09SDavid van Moolenbroek 0x00, /*%< algorithm */
92*00b67f09SDavid van Moolenbroek /*
93*00b67f09SDavid van Moolenbroek * The base64 encoding of one of our HMAC-SHA* signatures is
94*00b67f09SDavid van Moolenbroek * 88 bytes.
95*00b67f09SDavid van Moolenbroek */
96*00b67f09SDavid van Moolenbroek 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97*00b67f09SDavid van Moolenbroek 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
98*00b67f09SDavid van Moolenbroek 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99*00b67f09SDavid van Moolenbroek 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100*00b67f09SDavid van Moolenbroek 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101*00b67f09SDavid van Moolenbroek 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102*00b67f09SDavid van Moolenbroek 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
103*00b67f09SDavid van Moolenbroek 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
104*00b67f09SDavid van Moolenbroek 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105*00b67f09SDavid van Moolenbroek 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
106*00b67f09SDavid van Moolenbroek 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
107*00b67f09SDavid van Moolenbroek };
108*00b67f09SDavid van Moolenbroek
109*00b67f09SDavid van Moolenbroek #define HSHA_OFFSET 22 /*%< 21 = 6 + 1 + 4 + 5 + 1 + 4 + 1 */
110*00b67f09SDavid van Moolenbroek #define HSHA_LENGTH 88
111*00b67f09SDavid van Moolenbroek
112*00b67f09SDavid van Moolenbroek static isc_result_t
113*00b67f09SDavid van Moolenbroek table_towire(isccc_sexpr_t *alist, isccc_region_t *target);
114*00b67f09SDavid van Moolenbroek
115*00b67f09SDavid van Moolenbroek static isc_result_t
116*00b67f09SDavid van Moolenbroek list_towire(isccc_sexpr_t *alist, isccc_region_t *target);
117*00b67f09SDavid van Moolenbroek
118*00b67f09SDavid van Moolenbroek static isc_result_t
value_towire(isccc_sexpr_t * elt,isccc_region_t * target)119*00b67f09SDavid van Moolenbroek value_towire(isccc_sexpr_t *elt, isccc_region_t *target)
120*00b67f09SDavid van Moolenbroek {
121*00b67f09SDavid van Moolenbroek unsigned int len;
122*00b67f09SDavid van Moolenbroek unsigned char *lenp;
123*00b67f09SDavid van Moolenbroek isccc_region_t *vr;
124*00b67f09SDavid van Moolenbroek isc_result_t result;
125*00b67f09SDavid van Moolenbroek
126*00b67f09SDavid van Moolenbroek if (isccc_sexpr_binaryp(elt)) {
127*00b67f09SDavid van Moolenbroek vr = isccc_sexpr_tobinary(elt);
128*00b67f09SDavid van Moolenbroek len = REGION_SIZE(*vr);
129*00b67f09SDavid van Moolenbroek if (REGION_SIZE(*target) < 1 + 4 + len)
130*00b67f09SDavid van Moolenbroek return (ISC_R_NOSPACE);
131*00b67f09SDavid van Moolenbroek PUT8(ISCCC_CCMSGTYPE_BINARYDATA, target->rstart);
132*00b67f09SDavid van Moolenbroek PUT32(len, target->rstart);
133*00b67f09SDavid van Moolenbroek if (REGION_SIZE(*target) < len)
134*00b67f09SDavid van Moolenbroek return (ISC_R_NOSPACE);
135*00b67f09SDavid van Moolenbroek PUT_MEM(vr->rstart, len, target->rstart);
136*00b67f09SDavid van Moolenbroek } else if (isccc_alist_alistp(elt)) {
137*00b67f09SDavid van Moolenbroek if (REGION_SIZE(*target) < 1 + 4)
138*00b67f09SDavid van Moolenbroek return (ISC_R_NOSPACE);
139*00b67f09SDavid van Moolenbroek PUT8(ISCCC_CCMSGTYPE_TABLE, target->rstart);
140*00b67f09SDavid van Moolenbroek /*
141*00b67f09SDavid van Moolenbroek * Emit a placeholder length.
142*00b67f09SDavid van Moolenbroek */
143*00b67f09SDavid van Moolenbroek lenp = target->rstart;
144*00b67f09SDavid van Moolenbroek PUT32(0, target->rstart);
145*00b67f09SDavid van Moolenbroek /*
146*00b67f09SDavid van Moolenbroek * Emit the table.
147*00b67f09SDavid van Moolenbroek */
148*00b67f09SDavid van Moolenbroek result = table_towire(elt, target);
149*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
150*00b67f09SDavid van Moolenbroek return (result);
151*00b67f09SDavid van Moolenbroek len = (unsigned int)(target->rstart - lenp);
152*00b67f09SDavid van Moolenbroek /*
153*00b67f09SDavid van Moolenbroek * 'len' is 4 bytes too big, since it counts
154*00b67f09SDavid van Moolenbroek * the placeholder length too. Adjust and
155*00b67f09SDavid van Moolenbroek * emit.
156*00b67f09SDavid van Moolenbroek */
157*00b67f09SDavid van Moolenbroek INSIST(len >= 4U);
158*00b67f09SDavid van Moolenbroek len -= 4;
159*00b67f09SDavid van Moolenbroek PUT32(len, lenp);
160*00b67f09SDavid van Moolenbroek } else if (isccc_sexpr_listp(elt)) {
161*00b67f09SDavid van Moolenbroek if (REGION_SIZE(*target) < 1 + 4)
162*00b67f09SDavid van Moolenbroek return (ISC_R_NOSPACE);
163*00b67f09SDavid van Moolenbroek PUT8(ISCCC_CCMSGTYPE_LIST, target->rstart);
164*00b67f09SDavid van Moolenbroek /*
165*00b67f09SDavid van Moolenbroek * Emit a placeholder length and count.
166*00b67f09SDavid van Moolenbroek */
167*00b67f09SDavid van Moolenbroek lenp = target->rstart;
168*00b67f09SDavid van Moolenbroek PUT32(0, target->rstart);
169*00b67f09SDavid van Moolenbroek /*
170*00b67f09SDavid van Moolenbroek * Emit the list.
171*00b67f09SDavid van Moolenbroek */
172*00b67f09SDavid van Moolenbroek result = list_towire(elt, target);
173*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
174*00b67f09SDavid van Moolenbroek return (result);
175*00b67f09SDavid van Moolenbroek len = (unsigned int)(target->rstart - lenp);
176*00b67f09SDavid van Moolenbroek /*
177*00b67f09SDavid van Moolenbroek * 'len' is 4 bytes too big, since it counts
178*00b67f09SDavid van Moolenbroek * the placeholder length. Adjust and emit.
179*00b67f09SDavid van Moolenbroek */
180*00b67f09SDavid van Moolenbroek INSIST(len >= 4U);
181*00b67f09SDavid van Moolenbroek len -= 4;
182*00b67f09SDavid van Moolenbroek PUT32(len, lenp);
183*00b67f09SDavid van Moolenbroek }
184*00b67f09SDavid van Moolenbroek
185*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
186*00b67f09SDavid van Moolenbroek }
187*00b67f09SDavid van Moolenbroek
188*00b67f09SDavid van Moolenbroek static isc_result_t
table_towire(isccc_sexpr_t * alist,isccc_region_t * target)189*00b67f09SDavid van Moolenbroek table_towire(isccc_sexpr_t *alist, isccc_region_t *target)
190*00b67f09SDavid van Moolenbroek {
191*00b67f09SDavid van Moolenbroek isccc_sexpr_t *kv, *elt, *k, *v;
192*00b67f09SDavid van Moolenbroek char *ks;
193*00b67f09SDavid van Moolenbroek isc_result_t result;
194*00b67f09SDavid van Moolenbroek size_t len;
195*00b67f09SDavid van Moolenbroek
196*00b67f09SDavid van Moolenbroek for (elt = isccc_alist_first(alist);
197*00b67f09SDavid van Moolenbroek elt != NULL;
198*00b67f09SDavid van Moolenbroek elt = ISCCC_SEXPR_CDR(elt)) {
199*00b67f09SDavid van Moolenbroek kv = ISCCC_SEXPR_CAR(elt);
200*00b67f09SDavid van Moolenbroek k = ISCCC_SEXPR_CAR(kv);
201*00b67f09SDavid van Moolenbroek ks = isccc_sexpr_tostring(k);
202*00b67f09SDavid van Moolenbroek v = ISCCC_SEXPR_CDR(kv);
203*00b67f09SDavid van Moolenbroek len = strlen(ks);
204*00b67f09SDavid van Moolenbroek INSIST(len <= 255U);
205*00b67f09SDavid van Moolenbroek /*
206*00b67f09SDavid van Moolenbroek * Emit the key name.
207*00b67f09SDavid van Moolenbroek */
208*00b67f09SDavid van Moolenbroek if (REGION_SIZE(*target) < 1 + len)
209*00b67f09SDavid van Moolenbroek return (ISC_R_NOSPACE);
210*00b67f09SDavid van Moolenbroek PUT8(len, target->rstart);
211*00b67f09SDavid van Moolenbroek PUT_MEM(ks, len, target->rstart);
212*00b67f09SDavid van Moolenbroek /*
213*00b67f09SDavid van Moolenbroek * Emit the value.
214*00b67f09SDavid van Moolenbroek */
215*00b67f09SDavid van Moolenbroek result = value_towire(v, target);
216*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
217*00b67f09SDavid van Moolenbroek return (result);
218*00b67f09SDavid van Moolenbroek }
219*00b67f09SDavid van Moolenbroek
220*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
221*00b67f09SDavid van Moolenbroek }
222*00b67f09SDavid van Moolenbroek
223*00b67f09SDavid van Moolenbroek static isc_result_t
list_towire(isccc_sexpr_t * list,isccc_region_t * target)224*00b67f09SDavid van Moolenbroek list_towire(isccc_sexpr_t *list, isccc_region_t *target)
225*00b67f09SDavid van Moolenbroek {
226*00b67f09SDavid van Moolenbroek isc_result_t result;
227*00b67f09SDavid van Moolenbroek
228*00b67f09SDavid van Moolenbroek while (list != NULL) {
229*00b67f09SDavid van Moolenbroek result = value_towire(ISCCC_SEXPR_CAR(list), target);
230*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
231*00b67f09SDavid van Moolenbroek return (result);
232*00b67f09SDavid van Moolenbroek list = ISCCC_SEXPR_CDR(list);
233*00b67f09SDavid van Moolenbroek }
234*00b67f09SDavid van Moolenbroek
235*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
236*00b67f09SDavid van Moolenbroek }
237*00b67f09SDavid van Moolenbroek
238*00b67f09SDavid van Moolenbroek static isc_result_t
sign(unsigned char * data,unsigned int length,unsigned char * hmac,isc_uint32_t algorithm,isccc_region_t * secret)239*00b67f09SDavid van Moolenbroek sign(unsigned char *data, unsigned int length, unsigned char *hmac,
240*00b67f09SDavid van Moolenbroek isc_uint32_t algorithm, isccc_region_t *secret)
241*00b67f09SDavid van Moolenbroek {
242*00b67f09SDavid van Moolenbroek union {
243*00b67f09SDavid van Moolenbroek isc_hmacmd5_t hmd5;
244*00b67f09SDavid van Moolenbroek isc_hmacsha1_t hsha;
245*00b67f09SDavid van Moolenbroek isc_hmacsha224_t h224;
246*00b67f09SDavid van Moolenbroek isc_hmacsha256_t h256;
247*00b67f09SDavid van Moolenbroek isc_hmacsha384_t h384;
248*00b67f09SDavid van Moolenbroek isc_hmacsha512_t h512;
249*00b67f09SDavid van Moolenbroek } ctx;
250*00b67f09SDavid van Moolenbroek isc_result_t result;
251*00b67f09SDavid van Moolenbroek isccc_region_t source, target;
252*00b67f09SDavid van Moolenbroek unsigned char digest[ISC_SHA512_DIGESTLENGTH];
253*00b67f09SDavid van Moolenbroek unsigned char digestb64[HSHA_LENGTH + 4];
254*00b67f09SDavid van Moolenbroek
255*00b67f09SDavid van Moolenbroek source.rstart = digest;
256*00b67f09SDavid van Moolenbroek
257*00b67f09SDavid van Moolenbroek switch (algorithm) {
258*00b67f09SDavid van Moolenbroek case ISCCC_ALG_HMACMD5:
259*00b67f09SDavid van Moolenbroek isc_hmacmd5_init(&ctx.hmd5, secret->rstart,
260*00b67f09SDavid van Moolenbroek REGION_SIZE(*secret));
261*00b67f09SDavid van Moolenbroek isc_hmacmd5_update(&ctx.hmd5, data, length);
262*00b67f09SDavid van Moolenbroek isc_hmacmd5_sign(&ctx.hmd5, digest);
263*00b67f09SDavid van Moolenbroek source.rend = digest + ISC_MD5_DIGESTLENGTH;
264*00b67f09SDavid van Moolenbroek break;
265*00b67f09SDavid van Moolenbroek
266*00b67f09SDavid van Moolenbroek case ISCCC_ALG_HMACSHA1:
267*00b67f09SDavid van Moolenbroek isc_hmacsha1_init(&ctx.hsha, secret->rstart,
268*00b67f09SDavid van Moolenbroek REGION_SIZE(*secret));
269*00b67f09SDavid van Moolenbroek isc_hmacsha1_update(&ctx.hsha, data, length);
270*00b67f09SDavid van Moolenbroek isc_hmacsha1_sign(&ctx.hsha, digest,
271*00b67f09SDavid van Moolenbroek ISC_SHA1_DIGESTLENGTH);
272*00b67f09SDavid van Moolenbroek source.rend = digest + ISC_SHA1_DIGESTLENGTH;
273*00b67f09SDavid van Moolenbroek break;
274*00b67f09SDavid van Moolenbroek
275*00b67f09SDavid van Moolenbroek case ISCCC_ALG_HMACSHA224:
276*00b67f09SDavid van Moolenbroek isc_hmacsha224_init(&ctx.h224, secret->rstart,
277*00b67f09SDavid van Moolenbroek REGION_SIZE(*secret));
278*00b67f09SDavid van Moolenbroek isc_hmacsha224_update(&ctx.h224, data, length);
279*00b67f09SDavid van Moolenbroek isc_hmacsha224_sign(&ctx.h224, digest,
280*00b67f09SDavid van Moolenbroek ISC_SHA224_DIGESTLENGTH);
281*00b67f09SDavid van Moolenbroek source.rend = digest + ISC_SHA224_DIGESTLENGTH;
282*00b67f09SDavid van Moolenbroek break;
283*00b67f09SDavid van Moolenbroek
284*00b67f09SDavid van Moolenbroek case ISCCC_ALG_HMACSHA256:
285*00b67f09SDavid van Moolenbroek isc_hmacsha256_init(&ctx.h256, secret->rstart,
286*00b67f09SDavid van Moolenbroek REGION_SIZE(*secret));
287*00b67f09SDavid van Moolenbroek isc_hmacsha256_update(&ctx.h256, data, length);
288*00b67f09SDavid van Moolenbroek isc_hmacsha256_sign(&ctx.h256, digest,
289*00b67f09SDavid van Moolenbroek ISC_SHA256_DIGESTLENGTH);
290*00b67f09SDavid van Moolenbroek source.rend = digest + ISC_SHA256_DIGESTLENGTH;
291*00b67f09SDavid van Moolenbroek break;
292*00b67f09SDavid van Moolenbroek
293*00b67f09SDavid van Moolenbroek case ISCCC_ALG_HMACSHA384:
294*00b67f09SDavid van Moolenbroek isc_hmacsha384_init(&ctx.h384, secret->rstart,
295*00b67f09SDavid van Moolenbroek REGION_SIZE(*secret));
296*00b67f09SDavid van Moolenbroek isc_hmacsha384_update(&ctx.h384, data, length);
297*00b67f09SDavid van Moolenbroek isc_hmacsha384_sign(&ctx.h384, digest,
298*00b67f09SDavid van Moolenbroek ISC_SHA384_DIGESTLENGTH);
299*00b67f09SDavid van Moolenbroek source.rend = digest + ISC_SHA384_DIGESTLENGTH;
300*00b67f09SDavid van Moolenbroek break;
301*00b67f09SDavid van Moolenbroek
302*00b67f09SDavid van Moolenbroek case ISCCC_ALG_HMACSHA512:
303*00b67f09SDavid van Moolenbroek isc_hmacsha512_init(&ctx.h512, secret->rstart,
304*00b67f09SDavid van Moolenbroek REGION_SIZE(*secret));
305*00b67f09SDavid van Moolenbroek isc_hmacsha512_update(&ctx.h512, data, length);
306*00b67f09SDavid van Moolenbroek isc_hmacsha512_sign(&ctx.h512, digest,
307*00b67f09SDavid van Moolenbroek ISC_SHA512_DIGESTLENGTH);
308*00b67f09SDavid van Moolenbroek source.rend = digest + ISC_SHA512_DIGESTLENGTH;
309*00b67f09SDavid van Moolenbroek break;
310*00b67f09SDavid van Moolenbroek
311*00b67f09SDavid van Moolenbroek default:
312*00b67f09SDavid van Moolenbroek return (ISC_R_FAILURE);
313*00b67f09SDavid van Moolenbroek }
314*00b67f09SDavid van Moolenbroek
315*00b67f09SDavid van Moolenbroek memset(digestb64, 0, sizeof(digestb64));
316*00b67f09SDavid van Moolenbroek target.rstart = digestb64;
317*00b67f09SDavid van Moolenbroek target.rend = digestb64 + sizeof(digestb64);
318*00b67f09SDavid van Moolenbroek result = isccc_base64_encode(&source, 64, "", &target);
319*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
320*00b67f09SDavid van Moolenbroek return (result);
321*00b67f09SDavid van Moolenbroek if (algorithm == ISCCC_ALG_HMACMD5)
322*00b67f09SDavid van Moolenbroek PUT_MEM(digestb64, HMD5_LENGTH, hmac);
323*00b67f09SDavid van Moolenbroek else
324*00b67f09SDavid van Moolenbroek PUT_MEM(digestb64, HSHA_LENGTH, hmac);
325*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
326*00b67f09SDavid van Moolenbroek }
327*00b67f09SDavid van Moolenbroek
328*00b67f09SDavid van Moolenbroek isc_result_t
isccc_cc_towire(isccc_sexpr_t * alist,isccc_region_t * target,isc_uint32_t algorithm,isccc_region_t * secret)329*00b67f09SDavid van Moolenbroek isccc_cc_towire(isccc_sexpr_t *alist, isccc_region_t *target,
330*00b67f09SDavid van Moolenbroek isc_uint32_t algorithm, isccc_region_t *secret)
331*00b67f09SDavid van Moolenbroek {
332*00b67f09SDavid van Moolenbroek unsigned char *hmac_rstart, *signed_rstart;
333*00b67f09SDavid van Moolenbroek isc_result_t result;
334*00b67f09SDavid van Moolenbroek
335*00b67f09SDavid van Moolenbroek if (algorithm == ISCCC_ALG_HMACMD5) {
336*00b67f09SDavid van Moolenbroek if (REGION_SIZE(*target) < 4 + sizeof(auth_hmd5))
337*00b67f09SDavid van Moolenbroek return (ISC_R_NOSPACE);
338*00b67f09SDavid van Moolenbroek } else {
339*00b67f09SDavid van Moolenbroek if (REGION_SIZE(*target) < 4 + sizeof(auth_hsha))
340*00b67f09SDavid van Moolenbroek return (ISC_R_NOSPACE);
341*00b67f09SDavid van Moolenbroek }
342*00b67f09SDavid van Moolenbroek
343*00b67f09SDavid van Moolenbroek /*
344*00b67f09SDavid van Moolenbroek * Emit protocol version.
345*00b67f09SDavid van Moolenbroek */
346*00b67f09SDavid van Moolenbroek PUT32(1, target->rstart);
347*00b67f09SDavid van Moolenbroek if (secret != NULL) {
348*00b67f09SDavid van Moolenbroek /*
349*00b67f09SDavid van Moolenbroek * Emit _auth section with zeroed HMAC signature.
350*00b67f09SDavid van Moolenbroek * We'll replace the zeros with the real signature once
351*00b67f09SDavid van Moolenbroek * we know what it is.
352*00b67f09SDavid van Moolenbroek */
353*00b67f09SDavid van Moolenbroek if (algorithm == ISCCC_ALG_HMACMD5) {
354*00b67f09SDavid van Moolenbroek hmac_rstart = target->rstart + HMD5_OFFSET;
355*00b67f09SDavid van Moolenbroek PUT_MEM(auth_hmd5, sizeof(auth_hmd5), target->rstart);
356*00b67f09SDavid van Moolenbroek } else {
357*00b67f09SDavid van Moolenbroek unsigned char *hmac_alg;
358*00b67f09SDavid van Moolenbroek
359*00b67f09SDavid van Moolenbroek hmac_rstart = target->rstart + HSHA_OFFSET;
360*00b67f09SDavid van Moolenbroek hmac_alg = hmac_rstart - 1;
361*00b67f09SDavid van Moolenbroek PUT_MEM(auth_hsha, sizeof(auth_hsha), target->rstart);
362*00b67f09SDavid van Moolenbroek PUT8(algorithm, hmac_alg);
363*00b67f09SDavid van Moolenbroek }
364*00b67f09SDavid van Moolenbroek } else
365*00b67f09SDavid van Moolenbroek hmac_rstart = NULL;
366*00b67f09SDavid van Moolenbroek signed_rstart = target->rstart;
367*00b67f09SDavid van Moolenbroek /*
368*00b67f09SDavid van Moolenbroek * Delete any existing _auth section so that we don't try
369*00b67f09SDavid van Moolenbroek * to encode it.
370*00b67f09SDavid van Moolenbroek */
371*00b67f09SDavid van Moolenbroek isccc_alist_delete(alist, "_auth");
372*00b67f09SDavid van Moolenbroek /*
373*00b67f09SDavid van Moolenbroek * Emit the message.
374*00b67f09SDavid van Moolenbroek */
375*00b67f09SDavid van Moolenbroek result = table_towire(alist, target);
376*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
377*00b67f09SDavid van Moolenbroek return (result);
378*00b67f09SDavid van Moolenbroek if (secret != NULL)
379*00b67f09SDavid van Moolenbroek return (sign(signed_rstart,
380*00b67f09SDavid van Moolenbroek (unsigned int)(target->rstart - signed_rstart),
381*00b67f09SDavid van Moolenbroek hmac_rstart, algorithm, secret));
382*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
383*00b67f09SDavid van Moolenbroek }
384*00b67f09SDavid van Moolenbroek
385*00b67f09SDavid van Moolenbroek static isc_result_t
verify(isccc_sexpr_t * alist,unsigned char * data,unsigned int length,isc_uint32_t algorithm,isccc_region_t * secret)386*00b67f09SDavid van Moolenbroek verify(isccc_sexpr_t *alist, unsigned char *data, unsigned int length,
387*00b67f09SDavid van Moolenbroek isc_uint32_t algorithm, isccc_region_t *secret)
388*00b67f09SDavid van Moolenbroek {
389*00b67f09SDavid van Moolenbroek union {
390*00b67f09SDavid van Moolenbroek isc_hmacmd5_t hmd5;
391*00b67f09SDavid van Moolenbroek isc_hmacsha1_t hsha;
392*00b67f09SDavid van Moolenbroek isc_hmacsha224_t h224;
393*00b67f09SDavid van Moolenbroek isc_hmacsha256_t h256;
394*00b67f09SDavid van Moolenbroek isc_hmacsha384_t h384;
395*00b67f09SDavid van Moolenbroek isc_hmacsha512_t h512;
396*00b67f09SDavid van Moolenbroek } ctx;
397*00b67f09SDavid van Moolenbroek isccc_region_t source;
398*00b67f09SDavid van Moolenbroek isccc_region_t target;
399*00b67f09SDavid van Moolenbroek isc_result_t result;
400*00b67f09SDavid van Moolenbroek isccc_sexpr_t *_auth, *hmac;
401*00b67f09SDavid van Moolenbroek unsigned char digest[ISC_SHA512_DIGESTLENGTH];
402*00b67f09SDavid van Moolenbroek unsigned char digestb64[HSHA_LENGTH * 4];
403*00b67f09SDavid van Moolenbroek
404*00b67f09SDavid van Moolenbroek /*
405*00b67f09SDavid van Moolenbroek * Extract digest.
406*00b67f09SDavid van Moolenbroek */
407*00b67f09SDavid van Moolenbroek _auth = isccc_alist_lookup(alist, "_auth");
408*00b67f09SDavid van Moolenbroek if (_auth == NULL)
409*00b67f09SDavid van Moolenbroek return (ISC_R_FAILURE);
410*00b67f09SDavid van Moolenbroek if (algorithm == ISCCC_ALG_HMACMD5)
411*00b67f09SDavid van Moolenbroek hmac = isccc_alist_lookup(_auth, "hmd5");
412*00b67f09SDavid van Moolenbroek else
413*00b67f09SDavid van Moolenbroek hmac = isccc_alist_lookup(_auth, "hsha");
414*00b67f09SDavid van Moolenbroek if (hmac == NULL)
415*00b67f09SDavid van Moolenbroek return (ISC_R_FAILURE);
416*00b67f09SDavid van Moolenbroek /*
417*00b67f09SDavid van Moolenbroek * Compute digest.
418*00b67f09SDavid van Moolenbroek */
419*00b67f09SDavid van Moolenbroek source.rstart = digest;
420*00b67f09SDavid van Moolenbroek target.rstart = digestb64;
421*00b67f09SDavid van Moolenbroek switch (algorithm) {
422*00b67f09SDavid van Moolenbroek case ISCCC_ALG_HMACMD5:
423*00b67f09SDavid van Moolenbroek isc_hmacmd5_init(&ctx.hmd5, secret->rstart,
424*00b67f09SDavid van Moolenbroek REGION_SIZE(*secret));
425*00b67f09SDavid van Moolenbroek isc_hmacmd5_update(&ctx.hmd5, data, length);
426*00b67f09SDavid van Moolenbroek isc_hmacmd5_sign(&ctx.hmd5, digest);
427*00b67f09SDavid van Moolenbroek source.rend = digest + ISC_MD5_DIGESTLENGTH;
428*00b67f09SDavid van Moolenbroek break;
429*00b67f09SDavid van Moolenbroek
430*00b67f09SDavid van Moolenbroek case ISCCC_ALG_HMACSHA1:
431*00b67f09SDavid van Moolenbroek isc_hmacsha1_init(&ctx.hsha, secret->rstart,
432*00b67f09SDavid van Moolenbroek REGION_SIZE(*secret));
433*00b67f09SDavid van Moolenbroek isc_hmacsha1_update(&ctx.hsha, data, length);
434*00b67f09SDavid van Moolenbroek isc_hmacsha1_sign(&ctx.hsha, digest,
435*00b67f09SDavid van Moolenbroek ISC_SHA1_DIGESTLENGTH);
436*00b67f09SDavid van Moolenbroek source.rend = digest + ISC_SHA1_DIGESTLENGTH;
437*00b67f09SDavid van Moolenbroek break;
438*00b67f09SDavid van Moolenbroek
439*00b67f09SDavid van Moolenbroek case ISCCC_ALG_HMACSHA224:
440*00b67f09SDavid van Moolenbroek isc_hmacsha224_init(&ctx.h224, secret->rstart,
441*00b67f09SDavid van Moolenbroek REGION_SIZE(*secret));
442*00b67f09SDavid van Moolenbroek isc_hmacsha224_update(&ctx.h224, data, length);
443*00b67f09SDavid van Moolenbroek isc_hmacsha224_sign(&ctx.h224, digest,
444*00b67f09SDavid van Moolenbroek ISC_SHA224_DIGESTLENGTH);
445*00b67f09SDavid van Moolenbroek source.rend = digest + ISC_SHA224_DIGESTLENGTH;
446*00b67f09SDavid van Moolenbroek break;
447*00b67f09SDavid van Moolenbroek
448*00b67f09SDavid van Moolenbroek case ISCCC_ALG_HMACSHA256:
449*00b67f09SDavid van Moolenbroek isc_hmacsha256_init(&ctx.h256, secret->rstart,
450*00b67f09SDavid van Moolenbroek REGION_SIZE(*secret));
451*00b67f09SDavid van Moolenbroek isc_hmacsha256_update(&ctx.h256, data, length);
452*00b67f09SDavid van Moolenbroek isc_hmacsha256_sign(&ctx.h256, digest,
453*00b67f09SDavid van Moolenbroek ISC_SHA256_DIGESTLENGTH);
454*00b67f09SDavid van Moolenbroek source.rend = digest + ISC_SHA256_DIGESTLENGTH;
455*00b67f09SDavid van Moolenbroek break;
456*00b67f09SDavid van Moolenbroek
457*00b67f09SDavid van Moolenbroek case ISCCC_ALG_HMACSHA384:
458*00b67f09SDavid van Moolenbroek isc_hmacsha384_init(&ctx.h384, secret->rstart,
459*00b67f09SDavid van Moolenbroek REGION_SIZE(*secret));
460*00b67f09SDavid van Moolenbroek isc_hmacsha384_update(&ctx.h384, data, length);
461*00b67f09SDavid van Moolenbroek isc_hmacsha384_sign(&ctx.h384, digest,
462*00b67f09SDavid van Moolenbroek ISC_SHA384_DIGESTLENGTH);
463*00b67f09SDavid van Moolenbroek source.rend = digest + ISC_SHA384_DIGESTLENGTH;
464*00b67f09SDavid van Moolenbroek break;
465*00b67f09SDavid van Moolenbroek
466*00b67f09SDavid van Moolenbroek case ISCCC_ALG_HMACSHA512:
467*00b67f09SDavid van Moolenbroek isc_hmacsha512_init(&ctx.h512, secret->rstart,
468*00b67f09SDavid van Moolenbroek REGION_SIZE(*secret));
469*00b67f09SDavid van Moolenbroek isc_hmacsha512_update(&ctx.h512, data, length);
470*00b67f09SDavid van Moolenbroek isc_hmacsha512_sign(&ctx.h512, digest,
471*00b67f09SDavid van Moolenbroek ISC_SHA512_DIGESTLENGTH);
472*00b67f09SDavid van Moolenbroek source.rend = digest + ISC_SHA512_DIGESTLENGTH;
473*00b67f09SDavid van Moolenbroek break;
474*00b67f09SDavid van Moolenbroek
475*00b67f09SDavid van Moolenbroek default:
476*00b67f09SDavid van Moolenbroek return (ISC_R_FAILURE);
477*00b67f09SDavid van Moolenbroek }
478*00b67f09SDavid van Moolenbroek target.rstart = digestb64;
479*00b67f09SDavid van Moolenbroek target.rend = digestb64 + sizeof(digestb64);
480*00b67f09SDavid van Moolenbroek memset(digestb64, 0, sizeof(digestb64));
481*00b67f09SDavid van Moolenbroek result = isccc_base64_encode(&source, 64, "", &target);
482*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
483*00b67f09SDavid van Moolenbroek return (result);
484*00b67f09SDavid van Moolenbroek
485*00b67f09SDavid van Moolenbroek /*
486*00b67f09SDavid van Moolenbroek * Verify.
487*00b67f09SDavid van Moolenbroek */
488*00b67f09SDavid van Moolenbroek if (algorithm == ISCCC_ALG_HMACMD5) {
489*00b67f09SDavid van Moolenbroek unsigned char *value;
490*00b67f09SDavid van Moolenbroek
491*00b67f09SDavid van Moolenbroek value = (unsigned char *) isccc_sexpr_tostring(hmac);
492*00b67f09SDavid van Moolenbroek if (!isc_safe_memcmp(value, digestb64, HMD5_LENGTH))
493*00b67f09SDavid van Moolenbroek return (ISCCC_R_BADAUTH);
494*00b67f09SDavid van Moolenbroek } else {
495*00b67f09SDavid van Moolenbroek unsigned char *value;
496*00b67f09SDavid van Moolenbroek isc_uint32_t valalg;
497*00b67f09SDavid van Moolenbroek
498*00b67f09SDavid van Moolenbroek value = (unsigned char *) isccc_sexpr_tostring(hmac);
499*00b67f09SDavid van Moolenbroek GET8(valalg, value);
500*00b67f09SDavid van Moolenbroek if ((valalg != algorithm) ||
501*00b67f09SDavid van Moolenbroek (!isc_safe_memcmp(value, digestb64, HSHA_LENGTH)))
502*00b67f09SDavid van Moolenbroek return (ISCCC_R_BADAUTH);
503*00b67f09SDavid van Moolenbroek }
504*00b67f09SDavid van Moolenbroek
505*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
506*00b67f09SDavid van Moolenbroek }
507*00b67f09SDavid van Moolenbroek
508*00b67f09SDavid van Moolenbroek static isc_result_t
509*00b67f09SDavid van Moolenbroek table_fromwire(isccc_region_t *source, isccc_region_t *secret,
510*00b67f09SDavid van Moolenbroek isc_uint32_t algorithm, isccc_sexpr_t **alistp);
511*00b67f09SDavid van Moolenbroek
512*00b67f09SDavid van Moolenbroek static isc_result_t
513*00b67f09SDavid van Moolenbroek list_fromwire(isccc_region_t *source, isccc_sexpr_t **listp);
514*00b67f09SDavid van Moolenbroek
515*00b67f09SDavid van Moolenbroek static isc_result_t
value_fromwire(isccc_region_t * source,isccc_sexpr_t ** valuep)516*00b67f09SDavid van Moolenbroek value_fromwire(isccc_region_t *source, isccc_sexpr_t **valuep)
517*00b67f09SDavid van Moolenbroek {
518*00b67f09SDavid van Moolenbroek unsigned int msgtype;
519*00b67f09SDavid van Moolenbroek isc_uint32_t len;
520*00b67f09SDavid van Moolenbroek isccc_sexpr_t *value;
521*00b67f09SDavid van Moolenbroek isccc_region_t active;
522*00b67f09SDavid van Moolenbroek isc_result_t result;
523*00b67f09SDavid van Moolenbroek
524*00b67f09SDavid van Moolenbroek if (REGION_SIZE(*source) < 1 + 4)
525*00b67f09SDavid van Moolenbroek return (ISC_R_UNEXPECTEDEND);
526*00b67f09SDavid van Moolenbroek GET8(msgtype, source->rstart);
527*00b67f09SDavid van Moolenbroek GET32(len, source->rstart);
528*00b67f09SDavid van Moolenbroek if (REGION_SIZE(*source) < len)
529*00b67f09SDavid van Moolenbroek return (ISC_R_UNEXPECTEDEND);
530*00b67f09SDavid van Moolenbroek active.rstart = source->rstart;
531*00b67f09SDavid van Moolenbroek active.rend = active.rstart + len;
532*00b67f09SDavid van Moolenbroek source->rstart = active.rend;
533*00b67f09SDavid van Moolenbroek if (msgtype == ISCCC_CCMSGTYPE_BINARYDATA) {
534*00b67f09SDavid van Moolenbroek value = isccc_sexpr_frombinary(&active);
535*00b67f09SDavid van Moolenbroek if (value != NULL) {
536*00b67f09SDavid van Moolenbroek *valuep = value;
537*00b67f09SDavid van Moolenbroek result = ISC_R_SUCCESS;
538*00b67f09SDavid van Moolenbroek } else
539*00b67f09SDavid van Moolenbroek result = ISC_R_NOMEMORY;
540*00b67f09SDavid van Moolenbroek } else if (msgtype == ISCCC_CCMSGTYPE_TABLE)
541*00b67f09SDavid van Moolenbroek result = table_fromwire(&active, NULL, 0, valuep);
542*00b67f09SDavid van Moolenbroek else if (msgtype == ISCCC_CCMSGTYPE_LIST)
543*00b67f09SDavid van Moolenbroek result = list_fromwire(&active, valuep);
544*00b67f09SDavid van Moolenbroek else
545*00b67f09SDavid van Moolenbroek result = ISCCC_R_SYNTAX;
546*00b67f09SDavid van Moolenbroek
547*00b67f09SDavid van Moolenbroek return (result);
548*00b67f09SDavid van Moolenbroek }
549*00b67f09SDavid van Moolenbroek
550*00b67f09SDavid van Moolenbroek static isc_result_t
table_fromwire(isccc_region_t * source,isccc_region_t * secret,isc_uint32_t algorithm,isccc_sexpr_t ** alistp)551*00b67f09SDavid van Moolenbroek table_fromwire(isccc_region_t *source, isccc_region_t *secret,
552*00b67f09SDavid van Moolenbroek isc_uint32_t algorithm, isccc_sexpr_t **alistp)
553*00b67f09SDavid van Moolenbroek {
554*00b67f09SDavid van Moolenbroek char key[256];
555*00b67f09SDavid van Moolenbroek isc_uint32_t len;
556*00b67f09SDavid van Moolenbroek isc_result_t result;
557*00b67f09SDavid van Moolenbroek isccc_sexpr_t *alist, *value;
558*00b67f09SDavid van Moolenbroek isc_boolean_t first_tag;
559*00b67f09SDavid van Moolenbroek unsigned char *checksum_rstart;
560*00b67f09SDavid van Moolenbroek
561*00b67f09SDavid van Moolenbroek REQUIRE(alistp != NULL && *alistp == NULL);
562*00b67f09SDavid van Moolenbroek
563*00b67f09SDavid van Moolenbroek checksum_rstart = NULL;
564*00b67f09SDavid van Moolenbroek first_tag = ISC_TRUE;
565*00b67f09SDavid van Moolenbroek alist = isccc_alist_create();
566*00b67f09SDavid van Moolenbroek if (alist == NULL)
567*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
568*00b67f09SDavid van Moolenbroek
569*00b67f09SDavid van Moolenbroek while (!REGION_EMPTY(*source)) {
570*00b67f09SDavid van Moolenbroek GET8(len, source->rstart);
571*00b67f09SDavid van Moolenbroek if (REGION_SIZE(*source) < len) {
572*00b67f09SDavid van Moolenbroek result = ISC_R_UNEXPECTEDEND;
573*00b67f09SDavid van Moolenbroek goto bad;
574*00b67f09SDavid van Moolenbroek }
575*00b67f09SDavid van Moolenbroek GET_MEM(key, len, source->rstart);
576*00b67f09SDavid van Moolenbroek key[len] = '\0'; /* Ensure NUL termination. */
577*00b67f09SDavid van Moolenbroek value = NULL;
578*00b67f09SDavid van Moolenbroek result = value_fromwire(source, &value);
579*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
580*00b67f09SDavid van Moolenbroek goto bad;
581*00b67f09SDavid van Moolenbroek if (isccc_alist_define(alist, key, value) == NULL) {
582*00b67f09SDavid van Moolenbroek result = ISC_R_NOMEMORY;
583*00b67f09SDavid van Moolenbroek goto bad;
584*00b67f09SDavid van Moolenbroek }
585*00b67f09SDavid van Moolenbroek if (first_tag && secret != NULL && strcmp(key, "_auth") == 0)
586*00b67f09SDavid van Moolenbroek checksum_rstart = source->rstart;
587*00b67f09SDavid van Moolenbroek first_tag = ISC_FALSE;
588*00b67f09SDavid van Moolenbroek }
589*00b67f09SDavid van Moolenbroek
590*00b67f09SDavid van Moolenbroek if (secret != NULL) {
591*00b67f09SDavid van Moolenbroek if (checksum_rstart != NULL)
592*00b67f09SDavid van Moolenbroek result = verify(alist, checksum_rstart,
593*00b67f09SDavid van Moolenbroek (unsigned int)
594*00b67f09SDavid van Moolenbroek (source->rend - checksum_rstart),
595*00b67f09SDavid van Moolenbroek algorithm, secret);
596*00b67f09SDavid van Moolenbroek else
597*00b67f09SDavid van Moolenbroek result = ISCCC_R_BADAUTH;
598*00b67f09SDavid van Moolenbroek } else
599*00b67f09SDavid van Moolenbroek result = ISC_R_SUCCESS;
600*00b67f09SDavid van Moolenbroek
601*00b67f09SDavid van Moolenbroek bad:
602*00b67f09SDavid van Moolenbroek if (result == ISC_R_SUCCESS)
603*00b67f09SDavid van Moolenbroek *alistp = alist;
604*00b67f09SDavid van Moolenbroek else
605*00b67f09SDavid van Moolenbroek isccc_sexpr_free(&alist);
606*00b67f09SDavid van Moolenbroek
607*00b67f09SDavid van Moolenbroek return (result);
608*00b67f09SDavid van Moolenbroek }
609*00b67f09SDavid van Moolenbroek
610*00b67f09SDavid van Moolenbroek static isc_result_t
list_fromwire(isccc_region_t * source,isccc_sexpr_t ** listp)611*00b67f09SDavid van Moolenbroek list_fromwire(isccc_region_t *source, isccc_sexpr_t **listp)
612*00b67f09SDavid van Moolenbroek {
613*00b67f09SDavid van Moolenbroek isccc_sexpr_t *list, *value;
614*00b67f09SDavid van Moolenbroek isc_result_t result;
615*00b67f09SDavid van Moolenbroek
616*00b67f09SDavid van Moolenbroek list = NULL;
617*00b67f09SDavid van Moolenbroek while (!REGION_EMPTY(*source)) {
618*00b67f09SDavid van Moolenbroek value = NULL;
619*00b67f09SDavid van Moolenbroek result = value_fromwire(source, &value);
620*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
621*00b67f09SDavid van Moolenbroek isccc_sexpr_free(&list);
622*00b67f09SDavid van Moolenbroek return (result);
623*00b67f09SDavid van Moolenbroek }
624*00b67f09SDavid van Moolenbroek if (isccc_sexpr_addtolist(&list, value) == NULL) {
625*00b67f09SDavid van Moolenbroek isccc_sexpr_free(&value);
626*00b67f09SDavid van Moolenbroek isccc_sexpr_free(&list);
627*00b67f09SDavid van Moolenbroek return (result);
628*00b67f09SDavid van Moolenbroek }
629*00b67f09SDavid van Moolenbroek }
630*00b67f09SDavid van Moolenbroek
631*00b67f09SDavid van Moolenbroek *listp = list;
632*00b67f09SDavid van Moolenbroek
633*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
634*00b67f09SDavid van Moolenbroek }
635*00b67f09SDavid van Moolenbroek
636*00b67f09SDavid van Moolenbroek isc_result_t
isccc_cc_fromwire(isccc_region_t * source,isccc_sexpr_t ** alistp,isc_uint32_t algorithm,isccc_region_t * secret)637*00b67f09SDavid van Moolenbroek isccc_cc_fromwire(isccc_region_t *source, isccc_sexpr_t **alistp,
638*00b67f09SDavid van Moolenbroek isc_uint32_t algorithm, isccc_region_t *secret)
639*00b67f09SDavid van Moolenbroek {
640*00b67f09SDavid van Moolenbroek unsigned int size;
641*00b67f09SDavid van Moolenbroek isc_uint32_t version;
642*00b67f09SDavid van Moolenbroek
643*00b67f09SDavid van Moolenbroek size = REGION_SIZE(*source);
644*00b67f09SDavid van Moolenbroek if (size < 4)
645*00b67f09SDavid van Moolenbroek return (ISC_R_UNEXPECTEDEND);
646*00b67f09SDavid van Moolenbroek GET32(version, source->rstart);
647*00b67f09SDavid van Moolenbroek if (version != 1)
648*00b67f09SDavid van Moolenbroek return (ISCCC_R_UNKNOWNVERSION);
649*00b67f09SDavid van Moolenbroek
650*00b67f09SDavid van Moolenbroek return (table_fromwire(source, secret, algorithm, alistp));
651*00b67f09SDavid van Moolenbroek }
652*00b67f09SDavid van Moolenbroek
653*00b67f09SDavid van Moolenbroek static isc_result_t
createmessage(isc_uint32_t version,const char * from,const char * to,isc_uint32_t serial,isccc_time_t now,isccc_time_t expires,isccc_sexpr_t ** alistp,isc_boolean_t want_expires)654*00b67f09SDavid van Moolenbroek createmessage(isc_uint32_t version, const char *from, const char *to,
655*00b67f09SDavid van Moolenbroek isc_uint32_t serial, isccc_time_t now,
656*00b67f09SDavid van Moolenbroek isccc_time_t expires, isccc_sexpr_t **alistp,
657*00b67f09SDavid van Moolenbroek isc_boolean_t want_expires)
658*00b67f09SDavid van Moolenbroek {
659*00b67f09SDavid van Moolenbroek isccc_sexpr_t *alist, *_ctrl, *_data;
660*00b67f09SDavid van Moolenbroek isc_result_t result;
661*00b67f09SDavid van Moolenbroek
662*00b67f09SDavid van Moolenbroek REQUIRE(alistp != NULL && *alistp == NULL);
663*00b67f09SDavid van Moolenbroek
664*00b67f09SDavid van Moolenbroek if (version != 1)
665*00b67f09SDavid van Moolenbroek return (ISCCC_R_UNKNOWNVERSION);
666*00b67f09SDavid van Moolenbroek
667*00b67f09SDavid van Moolenbroek alist = isccc_alist_create();
668*00b67f09SDavid van Moolenbroek if (alist == NULL)
669*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
670*00b67f09SDavid van Moolenbroek
671*00b67f09SDavid van Moolenbroek result = ISC_R_NOMEMORY;
672*00b67f09SDavid van Moolenbroek
673*00b67f09SDavid van Moolenbroek _ctrl = isccc_alist_create();
674*00b67f09SDavid van Moolenbroek if (_ctrl == NULL)
675*00b67f09SDavid van Moolenbroek goto bad;
676*00b67f09SDavid van Moolenbroek if (isccc_alist_define(alist, "_ctrl", _ctrl) == NULL) {
677*00b67f09SDavid van Moolenbroek isccc_sexpr_free(&_ctrl);
678*00b67f09SDavid van Moolenbroek goto bad;
679*00b67f09SDavid van Moolenbroek }
680*00b67f09SDavid van Moolenbroek
681*00b67f09SDavid van Moolenbroek _data = isccc_alist_create();
682*00b67f09SDavid van Moolenbroek if (_data == NULL)
683*00b67f09SDavid van Moolenbroek goto bad;
684*00b67f09SDavid van Moolenbroek if (isccc_alist_define(alist, "_data", _data) == NULL) {
685*00b67f09SDavid van Moolenbroek isccc_sexpr_free(&_data);
686*00b67f09SDavid van Moolenbroek goto bad;
687*00b67f09SDavid van Moolenbroek }
688*00b67f09SDavid van Moolenbroek
689*00b67f09SDavid van Moolenbroek if (isccc_cc_defineuint32(_ctrl, "_ser", serial) == NULL ||
690*00b67f09SDavid van Moolenbroek isccc_cc_defineuint32(_ctrl, "_tim", now) == NULL ||
691*00b67f09SDavid van Moolenbroek (want_expires &&
692*00b67f09SDavid van Moolenbroek isccc_cc_defineuint32(_ctrl, "_exp", expires) == NULL))
693*00b67f09SDavid van Moolenbroek goto bad;
694*00b67f09SDavid van Moolenbroek if (from != NULL &&
695*00b67f09SDavid van Moolenbroek isccc_cc_definestring(_ctrl, "_frm", from) == NULL)
696*00b67f09SDavid van Moolenbroek goto bad;
697*00b67f09SDavid van Moolenbroek if (to != NULL &&
698*00b67f09SDavid van Moolenbroek isccc_cc_definestring(_ctrl, "_to", to) == NULL)
699*00b67f09SDavid van Moolenbroek goto bad;
700*00b67f09SDavid van Moolenbroek
701*00b67f09SDavid van Moolenbroek *alistp = alist;
702*00b67f09SDavid van Moolenbroek
703*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
704*00b67f09SDavid van Moolenbroek
705*00b67f09SDavid van Moolenbroek bad:
706*00b67f09SDavid van Moolenbroek isccc_sexpr_free(&alist);
707*00b67f09SDavid van Moolenbroek
708*00b67f09SDavid van Moolenbroek return (result);
709*00b67f09SDavid van Moolenbroek }
710*00b67f09SDavid van Moolenbroek
711*00b67f09SDavid van Moolenbroek isc_result_t
isccc_cc_createmessage(isc_uint32_t version,const char * from,const char * to,isc_uint32_t serial,isccc_time_t now,isccc_time_t expires,isccc_sexpr_t ** alistp)712*00b67f09SDavid van Moolenbroek isccc_cc_createmessage(isc_uint32_t version, const char *from, const char *to,
713*00b67f09SDavid van Moolenbroek isc_uint32_t serial, isccc_time_t now,
714*00b67f09SDavid van Moolenbroek isccc_time_t expires, isccc_sexpr_t **alistp)
715*00b67f09SDavid van Moolenbroek {
716*00b67f09SDavid van Moolenbroek return (createmessage(version, from, to, serial, now, expires,
717*00b67f09SDavid van Moolenbroek alistp, ISC_TRUE));
718*00b67f09SDavid van Moolenbroek }
719*00b67f09SDavid van Moolenbroek
720*00b67f09SDavid van Moolenbroek isc_result_t
isccc_cc_createack(isccc_sexpr_t * message,isc_boolean_t ok,isccc_sexpr_t ** ackp)721*00b67f09SDavid van Moolenbroek isccc_cc_createack(isccc_sexpr_t *message, isc_boolean_t ok,
722*00b67f09SDavid van Moolenbroek isccc_sexpr_t **ackp)
723*00b67f09SDavid van Moolenbroek {
724*00b67f09SDavid van Moolenbroek char *_frm, *_to;
725*00b67f09SDavid van Moolenbroek isc_uint32_t serial;
726*00b67f09SDavid van Moolenbroek isccc_sexpr_t *ack, *_ctrl;
727*00b67f09SDavid van Moolenbroek isc_result_t result;
728*00b67f09SDavid van Moolenbroek isccc_time_t t;
729*00b67f09SDavid van Moolenbroek
730*00b67f09SDavid van Moolenbroek REQUIRE(ackp != NULL && *ackp == NULL);
731*00b67f09SDavid van Moolenbroek
732*00b67f09SDavid van Moolenbroek _ctrl = isccc_alist_lookup(message, "_ctrl");
733*00b67f09SDavid van Moolenbroek if (_ctrl == NULL ||
734*00b67f09SDavid van Moolenbroek isccc_cc_lookupuint32(_ctrl, "_ser", &serial) != ISC_R_SUCCESS ||
735*00b67f09SDavid van Moolenbroek isccc_cc_lookupuint32(_ctrl, "_tim", &t) != ISC_R_SUCCESS)
736*00b67f09SDavid van Moolenbroek return (ISC_R_FAILURE);
737*00b67f09SDavid van Moolenbroek /*
738*00b67f09SDavid van Moolenbroek * _frm and _to are optional.
739*00b67f09SDavid van Moolenbroek */
740*00b67f09SDavid van Moolenbroek _frm = NULL;
741*00b67f09SDavid van Moolenbroek (void)isccc_cc_lookupstring(_ctrl, "_frm", &_frm);
742*00b67f09SDavid van Moolenbroek _to = NULL;
743*00b67f09SDavid van Moolenbroek (void)isccc_cc_lookupstring(_ctrl, "_to", &_to);
744*00b67f09SDavid van Moolenbroek /*
745*00b67f09SDavid van Moolenbroek * Create the ack.
746*00b67f09SDavid van Moolenbroek */
747*00b67f09SDavid van Moolenbroek ack = NULL;
748*00b67f09SDavid van Moolenbroek result = createmessage(1, _to, _frm, serial, t, 0, &ack, ISC_FALSE);
749*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
750*00b67f09SDavid van Moolenbroek return (result);
751*00b67f09SDavid van Moolenbroek
752*00b67f09SDavid van Moolenbroek _ctrl = isccc_alist_lookup(ack, "_ctrl");
753*00b67f09SDavid van Moolenbroek if (_ctrl == NULL) {
754*00b67f09SDavid van Moolenbroek result = ISC_R_FAILURE;
755*00b67f09SDavid van Moolenbroek goto bad;
756*00b67f09SDavid van Moolenbroek }
757*00b67f09SDavid van Moolenbroek if (isccc_cc_definestring(ack, "_ack", (ok) ? "1" : "0") == NULL) {
758*00b67f09SDavid van Moolenbroek result = ISC_R_NOMEMORY;
759*00b67f09SDavid van Moolenbroek goto bad;
760*00b67f09SDavid van Moolenbroek }
761*00b67f09SDavid van Moolenbroek
762*00b67f09SDavid van Moolenbroek *ackp = ack;
763*00b67f09SDavid van Moolenbroek
764*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
765*00b67f09SDavid van Moolenbroek
766*00b67f09SDavid van Moolenbroek bad:
767*00b67f09SDavid van Moolenbroek isccc_sexpr_free(&ack);
768*00b67f09SDavid van Moolenbroek
769*00b67f09SDavid van Moolenbroek return (result);
770*00b67f09SDavid van Moolenbroek }
771*00b67f09SDavid van Moolenbroek
772*00b67f09SDavid van Moolenbroek isc_boolean_t
isccc_cc_isack(isccc_sexpr_t * message)773*00b67f09SDavid van Moolenbroek isccc_cc_isack(isccc_sexpr_t *message)
774*00b67f09SDavid van Moolenbroek {
775*00b67f09SDavid van Moolenbroek isccc_sexpr_t *_ctrl;
776*00b67f09SDavid van Moolenbroek
777*00b67f09SDavid van Moolenbroek _ctrl = isccc_alist_lookup(message, "_ctrl");
778*00b67f09SDavid van Moolenbroek if (_ctrl == NULL)
779*00b67f09SDavid van Moolenbroek return (ISC_FALSE);
780*00b67f09SDavid van Moolenbroek if (isccc_cc_lookupstring(_ctrl, "_ack", NULL) == ISC_R_SUCCESS)
781*00b67f09SDavid van Moolenbroek return (ISC_TRUE);
782*00b67f09SDavid van Moolenbroek return (ISC_FALSE);
783*00b67f09SDavid van Moolenbroek }
784*00b67f09SDavid van Moolenbroek
785*00b67f09SDavid van Moolenbroek isc_boolean_t
isccc_cc_isreply(isccc_sexpr_t * message)786*00b67f09SDavid van Moolenbroek isccc_cc_isreply(isccc_sexpr_t *message)
787*00b67f09SDavid van Moolenbroek {
788*00b67f09SDavid van Moolenbroek isccc_sexpr_t *_ctrl;
789*00b67f09SDavid van Moolenbroek
790*00b67f09SDavid van Moolenbroek _ctrl = isccc_alist_lookup(message, "_ctrl");
791*00b67f09SDavid van Moolenbroek if (_ctrl == NULL)
792*00b67f09SDavid van Moolenbroek return (ISC_FALSE);
793*00b67f09SDavid van Moolenbroek if (isccc_cc_lookupstring(_ctrl, "_rpl", NULL) == ISC_R_SUCCESS)
794*00b67f09SDavid van Moolenbroek return (ISC_TRUE);
795*00b67f09SDavid van Moolenbroek return (ISC_FALSE);
796*00b67f09SDavid van Moolenbroek }
797*00b67f09SDavid van Moolenbroek
798*00b67f09SDavid van Moolenbroek isc_result_t
isccc_cc_createresponse(isccc_sexpr_t * message,isccc_time_t now,isccc_time_t expires,isccc_sexpr_t ** alistp)799*00b67f09SDavid van Moolenbroek isccc_cc_createresponse(isccc_sexpr_t *message, isccc_time_t now,
800*00b67f09SDavid van Moolenbroek isccc_time_t expires, isccc_sexpr_t **alistp)
801*00b67f09SDavid van Moolenbroek {
802*00b67f09SDavid van Moolenbroek char *_frm, *_to, *type = NULL;
803*00b67f09SDavid van Moolenbroek isc_uint32_t serial;
804*00b67f09SDavid van Moolenbroek isccc_sexpr_t *alist, *_ctrl, *_data;
805*00b67f09SDavid van Moolenbroek isc_result_t result;
806*00b67f09SDavid van Moolenbroek
807*00b67f09SDavid van Moolenbroek REQUIRE(alistp != NULL && *alistp == NULL);
808*00b67f09SDavid van Moolenbroek
809*00b67f09SDavid van Moolenbroek _ctrl = isccc_alist_lookup(message, "_ctrl");
810*00b67f09SDavid van Moolenbroek _data = isccc_alist_lookup(message, "_data");
811*00b67f09SDavid van Moolenbroek if (_ctrl == NULL || _data == NULL ||
812*00b67f09SDavid van Moolenbroek isccc_cc_lookupuint32(_ctrl, "_ser", &serial) != ISC_R_SUCCESS ||
813*00b67f09SDavid van Moolenbroek isccc_cc_lookupstring(_data, "type", &type) != ISC_R_SUCCESS)
814*00b67f09SDavid van Moolenbroek return (ISC_R_FAILURE);
815*00b67f09SDavid van Moolenbroek /*
816*00b67f09SDavid van Moolenbroek * _frm and _to are optional.
817*00b67f09SDavid van Moolenbroek */
818*00b67f09SDavid van Moolenbroek _frm = NULL;
819*00b67f09SDavid van Moolenbroek (void)isccc_cc_lookupstring(_ctrl, "_frm", &_frm);
820*00b67f09SDavid van Moolenbroek _to = NULL;
821*00b67f09SDavid van Moolenbroek (void)isccc_cc_lookupstring(_ctrl, "_to", &_to);
822*00b67f09SDavid van Moolenbroek /*
823*00b67f09SDavid van Moolenbroek * Create the response.
824*00b67f09SDavid van Moolenbroek */
825*00b67f09SDavid van Moolenbroek alist = NULL;
826*00b67f09SDavid van Moolenbroek result = isccc_cc_createmessage(1, _to, _frm, serial, now, expires,
827*00b67f09SDavid van Moolenbroek &alist);
828*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
829*00b67f09SDavid van Moolenbroek return (result);
830*00b67f09SDavid van Moolenbroek
831*00b67f09SDavid van Moolenbroek _ctrl = isccc_alist_lookup(alist, "_ctrl");
832*00b67f09SDavid van Moolenbroek if (_ctrl == NULL) {
833*00b67f09SDavid van Moolenbroek result = ISC_R_FAILURE;
834*00b67f09SDavid van Moolenbroek goto bad;
835*00b67f09SDavid van Moolenbroek }
836*00b67f09SDavid van Moolenbroek
837*00b67f09SDavid van Moolenbroek _data = isccc_alist_lookup(alist, "_data");
838*00b67f09SDavid van Moolenbroek if (_data == NULL) {
839*00b67f09SDavid van Moolenbroek result = ISC_R_FAILURE;
840*00b67f09SDavid van Moolenbroek goto bad;
841*00b67f09SDavid van Moolenbroek }
842*00b67f09SDavid van Moolenbroek
843*00b67f09SDavid van Moolenbroek if (isccc_cc_definestring(_ctrl, "_rpl", "1") == NULL ||
844*00b67f09SDavid van Moolenbroek isccc_cc_definestring(_data, "type", type) == NULL)
845*00b67f09SDavid van Moolenbroek {
846*00b67f09SDavid van Moolenbroek result = ISC_R_NOMEMORY;
847*00b67f09SDavid van Moolenbroek goto bad;
848*00b67f09SDavid van Moolenbroek }
849*00b67f09SDavid van Moolenbroek
850*00b67f09SDavid van Moolenbroek *alistp = alist;
851*00b67f09SDavid van Moolenbroek
852*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
853*00b67f09SDavid van Moolenbroek
854*00b67f09SDavid van Moolenbroek bad:
855*00b67f09SDavid van Moolenbroek isccc_sexpr_free(&alist);
856*00b67f09SDavid van Moolenbroek return (result);
857*00b67f09SDavid van Moolenbroek }
858*00b67f09SDavid van Moolenbroek
859*00b67f09SDavid van Moolenbroek isccc_sexpr_t *
isccc_cc_definestring(isccc_sexpr_t * alist,const char * key,const char * str)860*00b67f09SDavid van Moolenbroek isccc_cc_definestring(isccc_sexpr_t *alist, const char *key, const char *str)
861*00b67f09SDavid van Moolenbroek {
862*00b67f09SDavid van Moolenbroek size_t len;
863*00b67f09SDavid van Moolenbroek isccc_region_t r;
864*00b67f09SDavid van Moolenbroek
865*00b67f09SDavid van Moolenbroek len = strlen(str);
866*00b67f09SDavid van Moolenbroek DE_CONST(str, r.rstart);
867*00b67f09SDavid van Moolenbroek r.rend = r.rstart + len;
868*00b67f09SDavid van Moolenbroek
869*00b67f09SDavid van Moolenbroek return (isccc_alist_definebinary(alist, key, &r));
870*00b67f09SDavid van Moolenbroek }
871*00b67f09SDavid van Moolenbroek
872*00b67f09SDavid van Moolenbroek isccc_sexpr_t *
isccc_cc_defineuint32(isccc_sexpr_t * alist,const char * key,isc_uint32_t i)873*00b67f09SDavid van Moolenbroek isccc_cc_defineuint32(isccc_sexpr_t *alist, const char *key, isc_uint32_t i)
874*00b67f09SDavid van Moolenbroek {
875*00b67f09SDavid van Moolenbroek char b[100];
876*00b67f09SDavid van Moolenbroek size_t len;
877*00b67f09SDavid van Moolenbroek isccc_region_t r;
878*00b67f09SDavid van Moolenbroek
879*00b67f09SDavid van Moolenbroek snprintf(b, sizeof(b), "%u", i);
880*00b67f09SDavid van Moolenbroek len = strlen(b);
881*00b67f09SDavid van Moolenbroek r.rstart = (unsigned char *)b;
882*00b67f09SDavid van Moolenbroek r.rend = (unsigned char *)b + len;
883*00b67f09SDavid van Moolenbroek
884*00b67f09SDavid van Moolenbroek return (isccc_alist_definebinary(alist, key, &r));
885*00b67f09SDavid van Moolenbroek }
886*00b67f09SDavid van Moolenbroek
887*00b67f09SDavid van Moolenbroek isc_result_t
isccc_cc_lookupstring(isccc_sexpr_t * alist,const char * key,char ** strp)888*00b67f09SDavid van Moolenbroek isccc_cc_lookupstring(isccc_sexpr_t *alist, const char *key, char **strp)
889*00b67f09SDavid van Moolenbroek {
890*00b67f09SDavid van Moolenbroek isccc_sexpr_t *kv, *v;
891*00b67f09SDavid van Moolenbroek
892*00b67f09SDavid van Moolenbroek REQUIRE(strp == NULL || *strp == NULL);
893*00b67f09SDavid van Moolenbroek
894*00b67f09SDavid van Moolenbroek kv = isccc_alist_assq(alist, key);
895*00b67f09SDavid van Moolenbroek if (kv != NULL) {
896*00b67f09SDavid van Moolenbroek v = ISCCC_SEXPR_CDR(kv);
897*00b67f09SDavid van Moolenbroek if (isccc_sexpr_binaryp(v)) {
898*00b67f09SDavid van Moolenbroek if (strp != NULL)
899*00b67f09SDavid van Moolenbroek *strp = isccc_sexpr_tostring(v);
900*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
901*00b67f09SDavid van Moolenbroek } else
902*00b67f09SDavid van Moolenbroek return (ISC_R_EXISTS);
903*00b67f09SDavid van Moolenbroek }
904*00b67f09SDavid van Moolenbroek
905*00b67f09SDavid van Moolenbroek return (ISC_R_NOTFOUND);
906*00b67f09SDavid van Moolenbroek }
907*00b67f09SDavid van Moolenbroek
908*00b67f09SDavid van Moolenbroek isc_result_t
isccc_cc_lookupuint32(isccc_sexpr_t * alist,const char * key,isc_uint32_t * uintp)909*00b67f09SDavid van Moolenbroek isccc_cc_lookupuint32(isccc_sexpr_t *alist, const char *key,
910*00b67f09SDavid van Moolenbroek isc_uint32_t *uintp)
911*00b67f09SDavid van Moolenbroek {
912*00b67f09SDavid van Moolenbroek isccc_sexpr_t *kv, *v;
913*00b67f09SDavid van Moolenbroek
914*00b67f09SDavid van Moolenbroek kv = isccc_alist_assq(alist, key);
915*00b67f09SDavid van Moolenbroek if (kv != NULL) {
916*00b67f09SDavid van Moolenbroek v = ISCCC_SEXPR_CDR(kv);
917*00b67f09SDavid van Moolenbroek if (isccc_sexpr_binaryp(v)) {
918*00b67f09SDavid van Moolenbroek if (uintp != NULL)
919*00b67f09SDavid van Moolenbroek *uintp = (isc_uint32_t)
920*00b67f09SDavid van Moolenbroek strtoul(isccc_sexpr_tostring(v),
921*00b67f09SDavid van Moolenbroek NULL, 10);
922*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
923*00b67f09SDavid van Moolenbroek } else
924*00b67f09SDavid van Moolenbroek return (ISC_R_EXISTS);
925*00b67f09SDavid van Moolenbroek }
926*00b67f09SDavid van Moolenbroek
927*00b67f09SDavid van Moolenbroek return (ISC_R_NOTFOUND);
928*00b67f09SDavid van Moolenbroek }
929*00b67f09SDavid van Moolenbroek
930*00b67f09SDavid van Moolenbroek static void
symtab_undefine(char * key,unsigned int type,isccc_symvalue_t value,void * arg)931*00b67f09SDavid van Moolenbroek symtab_undefine(char *key, unsigned int type, isccc_symvalue_t value,
932*00b67f09SDavid van Moolenbroek void *arg)
933*00b67f09SDavid van Moolenbroek {
934*00b67f09SDavid van Moolenbroek UNUSED(type);
935*00b67f09SDavid van Moolenbroek UNUSED(value);
936*00b67f09SDavid van Moolenbroek UNUSED(arg);
937*00b67f09SDavid van Moolenbroek
938*00b67f09SDavid van Moolenbroek free(key);
939*00b67f09SDavid van Moolenbroek }
940*00b67f09SDavid van Moolenbroek
941*00b67f09SDavid van Moolenbroek static isc_boolean_t
symtab_clean(char * key,unsigned int type,isccc_symvalue_t value,void * arg)942*00b67f09SDavid van Moolenbroek symtab_clean(char *key, unsigned int type, isccc_symvalue_t value,
943*00b67f09SDavid van Moolenbroek void *arg)
944*00b67f09SDavid van Moolenbroek {
945*00b67f09SDavid van Moolenbroek isccc_time_t *now;
946*00b67f09SDavid van Moolenbroek
947*00b67f09SDavid van Moolenbroek UNUSED(key);
948*00b67f09SDavid van Moolenbroek UNUSED(type);
949*00b67f09SDavid van Moolenbroek
950*00b67f09SDavid van Moolenbroek now = arg;
951*00b67f09SDavid van Moolenbroek
952*00b67f09SDavid van Moolenbroek if (*now < value.as_uinteger)
953*00b67f09SDavid van Moolenbroek return (ISC_FALSE);
954*00b67f09SDavid van Moolenbroek if ((*now - value.as_uinteger) < DUP_LIFETIME)
955*00b67f09SDavid van Moolenbroek return (ISC_FALSE);
956*00b67f09SDavid van Moolenbroek return (ISC_TRUE);
957*00b67f09SDavid van Moolenbroek }
958*00b67f09SDavid van Moolenbroek
959*00b67f09SDavid van Moolenbroek isc_result_t
isccc_cc_createsymtab(isccc_symtab_t ** symtabp)960*00b67f09SDavid van Moolenbroek isccc_cc_createsymtab(isccc_symtab_t **symtabp)
961*00b67f09SDavid van Moolenbroek {
962*00b67f09SDavid van Moolenbroek return (isccc_symtab_create(11897, symtab_undefine, NULL, ISC_FALSE,
963*00b67f09SDavid van Moolenbroek symtabp));
964*00b67f09SDavid van Moolenbroek }
965*00b67f09SDavid van Moolenbroek
966*00b67f09SDavid van Moolenbroek void
isccc_cc_cleansymtab(isccc_symtab_t * symtab,isccc_time_t now)967*00b67f09SDavid van Moolenbroek isccc_cc_cleansymtab(isccc_symtab_t *symtab, isccc_time_t now)
968*00b67f09SDavid van Moolenbroek {
969*00b67f09SDavid van Moolenbroek isccc_symtab_foreach(symtab, symtab_clean, &now);
970*00b67f09SDavid van Moolenbroek }
971*00b67f09SDavid van Moolenbroek
972*00b67f09SDavid van Moolenbroek static isc_boolean_t
has_whitespace(const char * str)973*00b67f09SDavid van Moolenbroek has_whitespace(const char *str)
974*00b67f09SDavid van Moolenbroek {
975*00b67f09SDavid van Moolenbroek char c;
976*00b67f09SDavid van Moolenbroek
977*00b67f09SDavid van Moolenbroek if (str == NULL)
978*00b67f09SDavid van Moolenbroek return (ISC_FALSE);
979*00b67f09SDavid van Moolenbroek while ((c = *str++) != '\0') {
980*00b67f09SDavid van Moolenbroek if (c == ' ' || c == '\t' || c == '\n')
981*00b67f09SDavid van Moolenbroek return (ISC_TRUE);
982*00b67f09SDavid van Moolenbroek }
983*00b67f09SDavid van Moolenbroek return (ISC_FALSE);
984*00b67f09SDavid van Moolenbroek }
985*00b67f09SDavid van Moolenbroek
986*00b67f09SDavid van Moolenbroek isc_result_t
isccc_cc_checkdup(isccc_symtab_t * symtab,isccc_sexpr_t * message,isccc_time_t now)987*00b67f09SDavid van Moolenbroek isccc_cc_checkdup(isccc_symtab_t *symtab, isccc_sexpr_t *message,
988*00b67f09SDavid van Moolenbroek isccc_time_t now)
989*00b67f09SDavid van Moolenbroek {
990*00b67f09SDavid van Moolenbroek const char *_frm;
991*00b67f09SDavid van Moolenbroek const char *_to;
992*00b67f09SDavid van Moolenbroek char *_ser = NULL, *_tim = NULL, *tmp;
993*00b67f09SDavid van Moolenbroek isc_result_t result;
994*00b67f09SDavid van Moolenbroek char *key;
995*00b67f09SDavid van Moolenbroek size_t len;
996*00b67f09SDavid van Moolenbroek isccc_symvalue_t value;
997*00b67f09SDavid van Moolenbroek isccc_sexpr_t *_ctrl;
998*00b67f09SDavid van Moolenbroek
999*00b67f09SDavid van Moolenbroek _ctrl = isccc_alist_lookup(message, "_ctrl");
1000*00b67f09SDavid van Moolenbroek if (_ctrl == NULL ||
1001*00b67f09SDavid van Moolenbroek isccc_cc_lookupstring(_ctrl, "_ser", &_ser) != ISC_R_SUCCESS ||
1002*00b67f09SDavid van Moolenbroek isccc_cc_lookupstring(_ctrl, "_tim", &_tim) != ISC_R_SUCCESS)
1003*00b67f09SDavid van Moolenbroek return (ISC_R_FAILURE);
1004*00b67f09SDavid van Moolenbroek
1005*00b67f09SDavid van Moolenbroek INSIST(_ser != NULL);
1006*00b67f09SDavid van Moolenbroek INSIST(_tim != NULL);
1007*00b67f09SDavid van Moolenbroek
1008*00b67f09SDavid van Moolenbroek /*
1009*00b67f09SDavid van Moolenbroek * _frm and _to are optional.
1010*00b67f09SDavid van Moolenbroek */
1011*00b67f09SDavid van Moolenbroek tmp = NULL;
1012*00b67f09SDavid van Moolenbroek if (isccc_cc_lookupstring(_ctrl, "_frm", &tmp) != ISC_R_SUCCESS)
1013*00b67f09SDavid van Moolenbroek _frm = "";
1014*00b67f09SDavid van Moolenbroek else
1015*00b67f09SDavid van Moolenbroek _frm = tmp;
1016*00b67f09SDavid van Moolenbroek tmp = NULL;
1017*00b67f09SDavid van Moolenbroek if (isccc_cc_lookupstring(_ctrl, "_to", &tmp) != ISC_R_SUCCESS)
1018*00b67f09SDavid van Moolenbroek _to = "";
1019*00b67f09SDavid van Moolenbroek else
1020*00b67f09SDavid van Moolenbroek _to = tmp;
1021*00b67f09SDavid van Moolenbroek /*
1022*00b67f09SDavid van Moolenbroek * Ensure there is no newline in any of the strings. This is so
1023*00b67f09SDavid van Moolenbroek * we can write them to a file later.
1024*00b67f09SDavid van Moolenbroek */
1025*00b67f09SDavid van Moolenbroek if (has_whitespace(_frm) || has_whitespace(_to) ||
1026*00b67f09SDavid van Moolenbroek has_whitespace(_ser) || has_whitespace(_tim))
1027*00b67f09SDavid van Moolenbroek return (ISC_R_FAILURE);
1028*00b67f09SDavid van Moolenbroek len = strlen(_frm) + strlen(_to) + strlen(_ser) + strlen(_tim) + 4;
1029*00b67f09SDavid van Moolenbroek key = malloc(len);
1030*00b67f09SDavid van Moolenbroek if (key == NULL)
1031*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
1032*00b67f09SDavid van Moolenbroek snprintf(key, len, "%s;%s;%s;%s", _frm, _to, _ser, _tim);
1033*00b67f09SDavid van Moolenbroek value.as_uinteger = now;
1034*00b67f09SDavid van Moolenbroek result = isccc_symtab_define(symtab, key, ISCCC_SYMTYPE_CCDUP, value,
1035*00b67f09SDavid van Moolenbroek isccc_symexists_reject);
1036*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
1037*00b67f09SDavid van Moolenbroek free(key);
1038*00b67f09SDavid van Moolenbroek return (result);
1039*00b67f09SDavid van Moolenbroek }
1040*00b67f09SDavid van Moolenbroek
1041*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
1042*00b67f09SDavid van Moolenbroek }
1043