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>