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