Return to getcertsbyname.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon |
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