File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon / getcertsbyname.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:39:10 2012 UTC (12 years, 4 months ago) by misho
Branches: ipsec-tools, MAIN
CVS tags: v0_8_2p2, v0_8_1p0, v0_8_1, v0_8_0p0, v0_8_0, HEAD
ipsec-tools

    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>