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