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