1 /* cert.c - DNS CERT code
2 * Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
4 * This file is part of GNUPG.
6 * GNUPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GNUPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include <sys/types.h>
26 #include <netinet/in.h>
27 #include <arpa/nameser.h>
28 #include <arpa/inet.h>
37 /* Not every installation has gotten around to supporting CERTs
42 # include "cert_vms.h"
43 # endif /* def __VMS */
48 /* Returns -1 on error, 0 for no answer, 1 for PGP provided and 2 for
51 get_cert (const char *name, int want_ipgp, size_t max_size,IOBUF *iobuf,
52 unsigned char **fpr, size_t *fpr_len, char **url)
54 unsigned char *answer;
64 answer=xmalloc(max_size);
66 r=res_query(name,C_IN,T_CERT,answer,max_size);
67 /* Not too big, not too small, no errors and at least 1 answer. */
68 if(r>=sizeof(HEADER) && r<=max_size
69 && (((HEADER *)answer)->rcode)==NOERROR
70 && (count=ntohs(((HEADER *)answer)->ancount)))
73 unsigned char *pt,*emsg;
77 pt=&answer[sizeof(HEADER)];
79 /* Skip over the query */
81 rc=dn_skipname(pt,emsg);
87 /* There are several possible response types for a CERT request.
88 We're interested in the PGP (a key) and IPGP (a URI) types.
89 Skip all others. TODO: A key is better than a URI since
90 we've gone through all this bother to fetch it, so favor that
91 if we have both PGP and IPGP? */
93 while(count-->0 && pt<emsg)
95 u16 type,class,dlen,ctype;
97 rc=dn_skipname(pt,emsg); /* the name we just queried for */
103 /* Truncated message? 15 bytes takes us to the point where
104 we start looking at the ctype. */
113 /* We asked for IN and got something else !? */
124 /* We asked for CERT and got something else - might be a
125 CNAME, so loop around again. */
136 /* Skip the CERT key tag and algo which we don't need. */
141 /* 15 bytes takes us to here */
143 if (want_ipgp && ctype != 6)
144 ; /* Skip non IPGP cert records. */
145 else if (ctype==3 && iobuf && dlen)
148 *iobuf=iobuf_temp_with_content((char *)pt,dlen);
152 else if(ctype==6 && dlen && dlen<1023 && dlen>=pt[0]+1
153 && fpr && fpr_len && url)
160 *fpr=xmalloc(*fpr_len);
161 memcpy(*fpr,&pt[1],*fpr_len);
168 *url=xmalloc(dlen-(*fpr_len+1)+1);
169 memcpy(*url,&pt[*fpr_len+1],dlen-(*fpr_len+1));
170 (*url)[dlen-(*fpr_len+1)]='\0';
179 /* Neither type matches, so go around to the next answer. */
190 #else /* !USE_DNS_CERT */
193 get_cert (const char *name, int want_ipgp, size_t max_size,IOBUF *iobuf,
194 unsigned char **fpr, size_t *fpr_len, char **url)
201 /* Test with simon.josefsson.org */
205 main(int argc,char *argv[])
215 printf("cert-test [name]\n");
219 printf("CERT lookup on %s\n",argv[1]);
221 rc=get_cert (argv[1], 0, 16384, &iobuf, &fpr, &fpr_len, &url);
225 printf("no answer\n");
228 printf("key found: %d bytes\n",(int)iobuf_get_temp_length(iobuf));
236 printf("Fingerprint found (%d bytes): ",(int)fpr_len);
237 for(i=0;i<fpr_len;i++)
238 printf("%02X",fpr[i]);
242 printf("No fingerprint found\n");
245 printf("URL found: %s\n",url);
247 printf("No URL found\n");