]> git.saurik.com Git - apple/ipsec.git/blame - ipsec-tools/racoon/getcertsbyname.c
ipsec-326.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
52b7d2ce
A
32#include "config.h"
33
7ebaebe2
A
34#if ENABLE_DNSSEC_CERTS
35
52b7d2ce
A
36#include <sys/types.h>
37#include <sys/param.h>
38#include <sys/socket.h>
39
40#include <netinet/in.h>
d1e348cf 41#include <arpa/nameser_compat.h>
7ebaebe2
A
42
43// Note: this is currently compiled out because ENABLE_DNSSEC_CERTS=0
44// TODO: switch to DNSServiceRef APIs before enabling
45#error "Need to switch to DNSServiceRef APIs before enabling"
52b7d2ce 46#include <resolv.h>
7ebaebe2 47
52b7d2ce
A
48#ifdef HAVE_LWRES_GETRRSETBYNAME
49#include <lwres/netdb.h>
50#include <lwres/lwres.h>
51#else
52#include <netdb.h>
53#endif
54#include <stdlib.h>
55#include <string.h>
56#include <errno.h>
57
58#ifdef DNSSEC_DEBUG
59#include <stdio.h>
60#include <strings.h>
61#endif
62
85f41bec 63#include "var.h"
52b7d2ce
A
64#include "netdb_dnssec.h"
65
66/* XXX should it use ci_errno to hold errno instead of h_errno ? */
67extern int h_errno;
68
65c25746
A
69static struct certinfo *getnewci (int, int, int, int, int,
70 unsigned char *);
52b7d2ce
A
71
72static struct certinfo *
73getnewci(qtype, keytag, algorithm, flags, certlen, cert)
74 int qtype, keytag, algorithm, flags, certlen;
75 unsigned char *cert;
76{
77 struct certinfo *res;
78
79 res = malloc(sizeof(*res));
80 if (!res)
81 return NULL;
82
83 memset(res, 0, sizeof(*res));
84 res->ci_type = qtype;
85 res->ci_keytag = keytag;
86 res->ci_algorithm = algorithm;
87 res->ci_flags = flags;
88 res->ci_certlen = certlen;
89 res->ci_cert = malloc(certlen);
90 if (!res->ci_cert) {
91 free(res);
92 return NULL;
93 }
94 memcpy(res->ci_cert, cert, certlen);
95
96 return res;
97}
98
99void
100freecertinfo(ci)
101 struct certinfo *ci;
102{
103 struct certinfo *next;
104
105 do {
106 next = ci->ci_next;
107 if (ci->ci_cert)
108 free(ci->ci_cert);
109 free(ci);
110 ci = next;
111 } while (ci);
112}
113
114/*
115 * get CERT RR by FQDN and create certinfo structure chain.
116 */
117#ifdef HAVE_LWRES_GETRRSETBYNAME
118#define getrrsetbyname lwres_getrrsetbyname
119#define freerrset lwres_freerrset
120#define hstrerror lwres_hstrerror
121#endif
122#if defined(HAVE_LWRES_GETRRSETBYNAME) || defined(HAVE_GETRRSETBYNAME) //%%% BUG FIX - HAVE misspelled
123int
124getcertsbyname(name, res)
125 char *name;
126 struct certinfo **res;
127{
128 int rdlength;
129 char *cp;
130 int type, keytag, algorithm;
131 struct certinfo head, *cur;
132 struct rrsetinfo *rr = NULL;
133 int i;
134 int error = -1;
135
136 /* initialize res */
137 *res = NULL;
138
139 memset(&head, 0, sizeof(head));
140 cur = &head;
141
142 error = getrrsetbyname(name, C_IN, T_CERT, 0, &rr);
143 if (error) {
144#ifdef DNSSEC_DEBUG
145 printf("getrrsetbyname: %s\n", hstrerror(error));
146#endif
147 h_errno = NO_RECOVERY;
148 goto end;
149 }
150
151 if (rr->rri_rdclass != C_IN
152 || rr->rri_rdtype != T_CERT
153 || rr->rri_nrdatas == 0) {
154#ifdef DNSSEC_DEBUG
155 printf("getrrsetbyname: %s", hstrerror(error));
156#endif
157 h_errno = NO_RECOVERY;
158 goto end;
159 }
160#ifdef DNSSEC_DEBUG
161 if (!(rr->rri_flags & LWRDATA_VALIDATED))
162 printf("rr is not valid");
163#endif
164
165 for (i = 0; i < rr->rri_nrdatas; i++) {
166 rdlength = rr->rri_rdatas[i].rdi_length;
167 cp = rr->rri_rdatas[i].rdi_data;
168
169 GETSHORT(type, cp); /* type */
170 rdlength -= INT16SZ;
171 GETSHORT(keytag, cp); /* key tag */
172 rdlength -= INT16SZ;
173 algorithm = *cp++; /* algorithm */
174 rdlength -= 1;
175
176#ifdef DNSSEC_DEBUG
177 printf("type=%d keytag=%d alg=%d len=%d\n",
178 type, keytag, algorithm, rdlength);
179#endif
180
181 /* create new certinfo */
182 cur->ci_next = getnewci(type, keytag, algorithm,
183 rr->rri_flags, rdlength, cp);
184 if (!cur->ci_next) {
185#ifdef DNSSEC_DEBUG
186 printf("getnewci: %s", strerror(errno));
187#endif
188 h_errno = NO_RECOVERY;
189 goto end;
190 }
191 cur = cur->ci_next;
192 }
193
194 *res = head.ci_next;
195 error = 0;
196
197end:
198 if (rr)
199 freerrset(rr);
200 if (error && head.ci_next)
201 freecertinfo(head.ci_next);
202
203 return error;
204}
205#else /*!HAVE_LWRES_GETRRSETBYNAME*/
206int
207getcertsbyname(name, res)
208 char *name;
209 struct certinfo **res;
210{
211 unsigned char *answer = NULL, *p;
212 int buflen, anslen, len;
213 HEADER *hp;
214 int qdcount, ancount, rdlength;
215 unsigned char *cp, *eom;
216 char hostbuf[1024]; /* XXX */
217 int qtype, qclass, keytag, algorithm;
218 struct certinfo head, *cur;
219 int error = -1;
220
221 /* initialize res */
222 *res = NULL;
223
224 memset(&head, 0, sizeof(head));
225 cur = &head;
226
227 /* get CERT RR */
228 buflen = 512;
229 do {
230
231 buflen *= 2;
232 p = realloc(answer, buflen);
233 if (!p) {
234#ifdef DNSSEC_DEBUG
235 printf("realloc: %s", strerror(errno));
236#endif
237 h_errno = NO_RECOVERY;
238 goto end;
239 }
240 answer = p;
241
7ebaebe2
A
242 // Note: this is currently compiled out because ENABLE_DNSSEC_CERTS=0
243 // TODO: switch to DNSServiceRef APIs before enabling
244 #error "Need to switch to DNSServiceRef APIs before enabling"
245
52b7d2ce
A
246 anslen = res_query(name, C_IN, T_CERT, answer, buflen);
247 if (anslen == -1)
248 goto end;
249
250 } while (buflen < anslen);
251
252#ifdef DNSSEC_DEBUG
253 printf("get a DNS packet len=%d\n", anslen);
254#endif
255
256 /* parse CERT RR */
257 eom = answer + anslen;
258
85f41bec 259 hp = ALIGNED_CAST(HEADER *)answer;
52b7d2ce
A
260 qdcount = ntohs(hp->qdcount);
261 ancount = ntohs(hp->ancount);
262
263 /* question section */
264 if (qdcount != 1) {
265#ifdef DNSSEC_DEBUG
266 printf("query count is not 1.\n");
267#endif
268 h_errno = NO_RECOVERY;
269 goto end;
270 }
271 cp = (unsigned char *)(hp + 1);
272 len = dn_expand(answer, eom, cp, hostbuf, sizeof(hostbuf));
273 if (len < 0) {
274#ifdef DNSSEC_DEBUG
275 printf("dn_expand failed.\n");
276#endif
277 goto end;
278 }
279 cp += len;
280 GETSHORT(qtype, cp); /* QTYPE */
281 GETSHORT(qclass, cp); /* QCLASS */
282
283 /* answer section */
284 while (ancount-- && cp < eom) {
285 len = dn_expand(answer, eom, cp, hostbuf, sizeof(hostbuf));
286 if (len < 0) {
287#ifdef DNSSEC_DEBUG
288 printf("dn_expand failed.\n");
289#endif
290 goto end;
291 }
292 cp += len;
293 GETSHORT(qtype, cp); /* TYPE */
294 GETSHORT(qclass, cp); /* CLASS */
295 cp += INT32SZ; /* TTL */
296 GETSHORT(rdlength, cp); /* RDLENGTH */
297
298 /* CERT RR */
299 if (qtype != T_CERT) {
300#ifdef DNSSEC_DEBUG
301 printf("not T_CERT\n");
302#endif
303 h_errno = NO_RECOVERY;
304 goto end;
305 }
306 GETSHORT(qtype, cp); /* type */
307 rdlength -= INT16SZ;
308 GETSHORT(keytag, cp); /* key tag */
309 rdlength -= INT16SZ;
310 algorithm = *cp++; /* algorithm */
311 rdlength -= 1;
312 if (cp + rdlength > eom) {
313#ifdef DNSSEC_DEBUG
314 printf("rdlength is too long.\n");
315#endif
316 h_errno = NO_RECOVERY;
317 goto end;
318 }
319#ifdef DNSSEC_DEBUG
320 printf("type=%d keytag=%d alg=%d len=%d\n",
321 qtype, keytag, algorithm, rdlength);
322#endif
323
324 /* create new certinfo */
325 cur->ci_next = getnewci(qtype, keytag, algorithm,
326 0, rdlength, cp);
327 if (!cur->ci_next) {
328#ifdef DNSSEC_DEBUG
329 printf("getnewci: %s", strerror(errno));
330#endif
331 h_errno = NO_RECOVERY;
332 goto end;
333 }
334 cur = cur->ci_next;
335
336 cp += rdlength;
337 }
338
339 *res = head.ci_next;
340 error = 0;
341
342end:
343 if (answer)
344 free(answer);
345 if (error && head.ci_next)
346 freecertinfo(head.ci_next);
347
348 return error;
349}
350#endif
351
352#ifdef DNSSEC_DEBUG
353int
354b64encode(p, len)
355 char *p;
356 int len;
357{
358 static const char b64t[] =
359 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
360 "abcdefghijklmnopqrstuvwxyz"
361 "0123456789+/=";
362
363 while (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) | ((p[2] >> 6) & 0x03)]);
367 printf("%c", b64t[p[2] & 0x3f]);
368 len -= 3;
369 p += 3;
370 }
371
372 if (len == 2) {
373 printf("%c", b64t[(p[0] >> 2) & 0x3f]);
374 printf("%c", b64t[((p[0] << 4) & 0x30)| ((p[1] >> 4) & 0x0f)]);
375 printf("%c", b64t[((p[1] << 2) & 0x3c)]);
376 printf("%c", '=');
377 } else if (len == 1) {
378 printf("%c", b64t[(p[0] >> 2) & 0x3f]);
379 printf("%c", b64t[((p[0] << 4) & 0x30)]);
380 printf("%c", '=');
381 printf("%c", '=');
382 }
383
384 return 0;
385}
386
387int
388main(ac, av)
389 int ac;
390 char **av;
391{
392 struct certinfo *res, *p;
393 int i;
394
395 if (ac < 2) {
396 printf("Usage: a.out (FQDN)\n");
397 exit(1);
398 }
399
400 i = getcertsbyname(*(av + 1), &res);
401 if (i != 0) {
402 herror("getcertsbyname");
403 exit(1);
404 }
405 printf("getcertsbyname succeeded.\n");
406
407 i = 0;
408 for (p = res; p; p = p->ci_next) {
409 printf("certinfo[%d]:\n", i);
410 printf("\tci_type=%d\n", p->ci_type);
411 printf("\tci_keytag=%d\n", p->ci_keytag);
412 printf("\tci_algorithm=%d\n", p->ci_algorithm);
413 printf("\tci_flags=%d\n", p->ci_flags);
414 printf("\tci_certlen=%d\n", p->ci_certlen);
415 printf("\tci_cert: ");
416 b64encode(p->ci_cert, p->ci_certlen);
417 printf("\n");
418 i++;
419 }
420
421 freecertinfo(res);
422
423 exit(0);
424}
425#endif
7ebaebe2
A
426
427#endif /* ENABLE_DNSSEC_CERTS */