]> git.saurik.com Git - apple/ipsec.git/blame - ipsec-tools/racoon/getcertsbyname.c
ipsec-34.0.3.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / getcertsbyname.c
CommitLineData
52b7d2ce
A
1/* $KAME: getcertsbyname.c,v 1.7 2001/11/16 04:12:59 sakane Exp $ */
2
3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32//%%%HWR Do we need this?
33#define BIND_8_COMPAT
34
35#include "config.h"
36
37#include <sys/types.h>
38#include <sys/param.h>
39#include <sys/socket.h>
40
41#include <netinet/in.h>
42#include <arpa/nameser.h>
43#include <resolv.h>
44#ifdef HAVE_LWRES_GETRRSETBYNAME
45#include <lwres/netdb.h>
46#include <lwres/lwres.h>
47#else
48#include <netdb.h>
49#endif
50#include <stdlib.h>
51#include <string.h>
52#include <errno.h>
53
54#ifdef DNSSEC_DEBUG
55#include <stdio.h>
56#include <strings.h>
57#endif
58
59#include "netdb_dnssec.h"
60
61/* XXX should it use ci_errno to hold errno instead of h_errno ? */
62extern int h_errno;
63
64static struct certinfo *getnewci __P((int, int, int, int, int,
65 unsigned char *));
66
67static struct certinfo *
68getnewci(qtype, keytag, algorithm, flags, certlen, cert)
69 int qtype, keytag, algorithm, flags, certlen;
70 unsigned char *cert;
71{
72 struct certinfo *res;
73
74 res = malloc(sizeof(*res));
75 if (!res)
76 return NULL;
77
78 memset(res, 0, sizeof(*res));
79 res->ci_type = qtype;
80 res->ci_keytag = keytag;
81 res->ci_algorithm = algorithm;
82 res->ci_flags = flags;
83 res->ci_certlen = certlen;
84 res->ci_cert = malloc(certlen);
85 if (!res->ci_cert) {
86 free(res);
87 return NULL;
88 }
89 memcpy(res->ci_cert, cert, certlen);
90
91 return res;
92}
93
94void
95freecertinfo(ci)
96 struct certinfo *ci;
97{
98 struct certinfo *next;
99
100 do {
101 next = ci->ci_next;
102 if (ci->ci_cert)
103 free(ci->ci_cert);
104 free(ci);
105 ci = next;
106 } while (ci);
107}
108
109/*
110 * get CERT RR by FQDN and create certinfo structure chain.
111 */
112#ifdef HAVE_LWRES_GETRRSETBYNAME
113#define getrrsetbyname lwres_getrrsetbyname
114#define freerrset lwres_freerrset
115#define hstrerror lwres_hstrerror
116#endif
117#if defined(HAVE_LWRES_GETRRSETBYNAME) || defined(HAVE_GETRRSETBYNAME) //%%% BUG FIX - HAVE misspelled
118int
119getcertsbyname(name, res)
120 char *name;
121 struct certinfo **res;
122{
123 int rdlength;
124 char *cp;
125 int type, keytag, algorithm;
126 struct certinfo head, *cur;
127 struct rrsetinfo *rr = NULL;
128 int i;
129 int error = -1;
130
131 /* initialize res */
132 *res = NULL;
133
134 memset(&head, 0, sizeof(head));
135 cur = &head;
136
137 error = getrrsetbyname(name, C_IN, T_CERT, 0, &rr);
138 if (error) {
139#ifdef DNSSEC_DEBUG
140 printf("getrrsetbyname: %s\n", hstrerror(error));
141#endif
142 h_errno = NO_RECOVERY;
143 goto end;
144 }
145
146 if (rr->rri_rdclass != C_IN
147 || rr->rri_rdtype != T_CERT
148 || rr->rri_nrdatas == 0) {
149#ifdef DNSSEC_DEBUG
150 printf("getrrsetbyname: %s", hstrerror(error));
151#endif
152 h_errno = NO_RECOVERY;
153 goto end;
154 }
155#ifdef DNSSEC_DEBUG
156 if (!(rr->rri_flags & LWRDATA_VALIDATED))
157 printf("rr is not valid");
158#endif
159
160 for (i = 0; i < rr->rri_nrdatas; i++) {
161 rdlength = rr->rri_rdatas[i].rdi_length;
162 cp = rr->rri_rdatas[i].rdi_data;
163
164 GETSHORT(type, cp); /* type */
165 rdlength -= INT16SZ;
166 GETSHORT(keytag, cp); /* key tag */
167 rdlength -= INT16SZ;
168 algorithm = *cp++; /* algorithm */
169 rdlength -= 1;
170
171#ifdef DNSSEC_DEBUG
172 printf("type=%d keytag=%d alg=%d len=%d\n",
173 type, keytag, algorithm, rdlength);
174#endif
175
176 /* create new certinfo */
177 cur->ci_next = getnewci(type, keytag, algorithm,
178 rr->rri_flags, rdlength, cp);
179 if (!cur->ci_next) {
180#ifdef DNSSEC_DEBUG
181 printf("getnewci: %s", strerror(errno));
182#endif
183 h_errno = NO_RECOVERY;
184 goto end;
185 }
186 cur = cur->ci_next;
187 }
188
189 *res = head.ci_next;
190 error = 0;
191
192end:
193 if (rr)
194 freerrset(rr);
195 if (error && head.ci_next)
196 freecertinfo(head.ci_next);
197
198 return error;
199}
200#else /*!HAVE_LWRES_GETRRSETBYNAME*/
201int
202getcertsbyname(name, res)
203 char *name;
204 struct certinfo **res;
205{
206 unsigned char *answer = NULL, *p;
207 int buflen, anslen, len;
208 HEADER *hp;
209 int qdcount, ancount, rdlength;
210 unsigned char *cp, *eom;
211 char hostbuf[1024]; /* XXX */
212 int qtype, qclass, keytag, algorithm;
213 struct certinfo head, *cur;
214 int error = -1;
215
216 /* initialize res */
217 *res = NULL;
218
219 memset(&head, 0, sizeof(head));
220 cur = &head;
221
222 /* get CERT RR */
223 buflen = 512;
224 do {
225
226 buflen *= 2;
227 p = realloc(answer, buflen);
228 if (!p) {
229#ifdef DNSSEC_DEBUG
230 printf("realloc: %s", strerror(errno));
231#endif
232 h_errno = NO_RECOVERY;
233 goto end;
234 }
235 answer = p;
236
237 anslen = res_query(name, C_IN, T_CERT, answer, buflen);
238 if (anslen == -1)
239 goto end;
240
241 } while (buflen < anslen);
242
243#ifdef DNSSEC_DEBUG
244 printf("get a DNS packet len=%d\n", anslen);
245#endif
246
247 /* parse CERT RR */
248 eom = answer + anslen;
249
250 hp = (HEADER *)answer;
251 qdcount = ntohs(hp->qdcount);
252 ancount = ntohs(hp->ancount);
253
254 /* question section */
255 if (qdcount != 1) {
256#ifdef DNSSEC_DEBUG
257 printf("query count is not 1.\n");
258#endif
259 h_errno = NO_RECOVERY;
260 goto end;
261 }
262 cp = (unsigned char *)(hp + 1);
263 len = dn_expand(answer, eom, cp, hostbuf, sizeof(hostbuf));
264 if (len < 0) {
265#ifdef DNSSEC_DEBUG
266 printf("dn_expand failed.\n");
267#endif
268 goto end;
269 }
270 cp += len;
271 GETSHORT(qtype, cp); /* QTYPE */
272 GETSHORT(qclass, cp); /* QCLASS */
273
274 /* answer section */
275 while (ancount-- && cp < eom) {
276 len = dn_expand(answer, eom, cp, hostbuf, sizeof(hostbuf));
277 if (len < 0) {
278#ifdef DNSSEC_DEBUG
279 printf("dn_expand failed.\n");
280#endif
281 goto end;
282 }
283 cp += len;
284 GETSHORT(qtype, cp); /* TYPE */
285 GETSHORT(qclass, cp); /* CLASS */
286 cp += INT32SZ; /* TTL */
287 GETSHORT(rdlength, cp); /* RDLENGTH */
288
289 /* CERT RR */
290 if (qtype != T_CERT) {
291#ifdef DNSSEC_DEBUG
292 printf("not T_CERT\n");
293#endif
294 h_errno = NO_RECOVERY;
295 goto end;
296 }
297 GETSHORT(qtype, cp); /* type */
298 rdlength -= INT16SZ;
299 GETSHORT(keytag, cp); /* key tag */
300 rdlength -= INT16SZ;
301 algorithm = *cp++; /* algorithm */
302 rdlength -= 1;
303 if (cp + rdlength > eom) {
304#ifdef DNSSEC_DEBUG
305 printf("rdlength is too long.\n");
306#endif
307 h_errno = NO_RECOVERY;
308 goto end;
309 }
310#ifdef DNSSEC_DEBUG
311 printf("type=%d keytag=%d alg=%d len=%d\n",
312 qtype, keytag, algorithm, rdlength);
313#endif
314
315 /* create new certinfo */
316 cur->ci_next = getnewci(qtype, keytag, algorithm,
317 0, rdlength, cp);
318 if (!cur->ci_next) {
319#ifdef DNSSEC_DEBUG
320 printf("getnewci: %s", strerror(errno));
321#endif
322 h_errno = NO_RECOVERY;
323 goto end;
324 }
325 cur = cur->ci_next;
326
327 cp += rdlength;
328 }
329
330 *res = head.ci_next;
331 error = 0;
332
333end:
334 if (answer)
335 free(answer);
336 if (error && head.ci_next)
337 freecertinfo(head.ci_next);
338
339 return error;
340}
341#endif
342
343#ifdef DNSSEC_DEBUG
344int
345b64encode(p, len)
346 char *p;
347 int len;
348{
349 static const char b64t[] =
350 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
351 "abcdefghijklmnopqrstuvwxyz"
352 "0123456789+/=";
353
354 while (len > 2) {
355 printf("%c", b64t[(p[0] >> 2) & 0x3f]);
356 printf("%c", b64t[((p[0] << 4) & 0x30) | ((p[1] >> 4) & 0x0f)]);
357 printf("%c", b64t[((p[1] << 2) & 0x3c) | ((p[2] >> 6) & 0x03)]);
358 printf("%c", b64t[p[2] & 0x3f]);
359 len -= 3;
360 p += 3;
361 }
362
363 if (len == 2) {
364 printf("%c", b64t[(p[0] >> 2) & 0x3f]);
365 printf("%c", b64t[((p[0] << 4) & 0x30)| ((p[1] >> 4) & 0x0f)]);
366 printf("%c", b64t[((p[1] << 2) & 0x3c)]);
367 printf("%c", '=');
368 } else if (len == 1) {
369 printf("%c", b64t[(p[0] >> 2) & 0x3f]);
370 printf("%c", b64t[((p[0] << 4) & 0x30)]);
371 printf("%c", '=');
372 printf("%c", '=');
373 }
374
375 return 0;
376}
377
378int
379main(ac, av)
380 int ac;
381 char **av;
382{
383 struct certinfo *res, *p;
384 int i;
385
386 if (ac < 2) {
387 printf("Usage: a.out (FQDN)\n");
388 exit(1);
389 }
390
391 i = getcertsbyname(*(av + 1), &res);
392 if (i != 0) {
393 herror("getcertsbyname");
394 exit(1);
395 }
396 printf("getcertsbyname succeeded.\n");
397
398 i = 0;
399 for (p = res; p; p = p->ci_next) {
400 printf("certinfo[%d]:\n", i);
401 printf("\tci_type=%d\n", p->ci_type);
402 printf("\tci_keytag=%d\n", p->ci_keytag);
403 printf("\tci_algorithm=%d\n", p->ci_algorithm);
404 printf("\tci_flags=%d\n", p->ci_flags);
405 printf("\tci_certlen=%d\n", p->ci_certlen);
406 printf("\tci_cert: ");
407 b64encode(p->ci_cert, p->ci_certlen);
408 printf("\n");
409 i++;
410 }
411
412 freecertinfo(res);
413
414 exit(0);
415}
416#endif