Annotation of embedaddon/ipsec-tools/src/racoon/getcertsbyname.c, revision 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>