source: rtems-libbsd/ipsec-tools/src/racoon/getcertsbyname.c @ b376ae1

55-freebsd-126-freebsd-12
Last change on this file since b376ae1 was b376ae1, checked in by Christian Mauderer <christian.mauderer@…>, on 05/03/18 at 12:15:11

ipsec-tools: Port libipsec, setkey and racoon.

Note that this replaces the libipsec from FreeBSD with the one provided
by ipsec-tools.

  • Property mode set to 100644
File size: 9.5 KB
Line 
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 ? */
70extern int h_errno;
71
72static struct certinfo *getnewci __P((int, int, int, int, int,
73                        unsigned char *));
74
75static struct certinfo *
76getnewci(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
102void
103freecertinfo(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)
126int
127getcertsbyname(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
200end:
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*/
209int
210getcertsbyname(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
341end:
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
352int
353b64encode(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
386int
387main(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__ */
Note: See TracBrowser for help on using the repository browser.