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