New code to do DNS CERT queries.
authorDavid Shaw <dshaw@jabberwocky.com>
Fri, 23 Dec 2005 18:15:24 +0000 (18:15 +0000)
committerDavid Shaw <dshaw@jabberwocky.com>
Fri, 23 Dec 2005 18:15:24 +0000 (18:15 +0000)
ChangeLog
configure.ac
include/ChangeLog
include/util.h
util/ChangeLog
util/Makefile.am
util/cert.c [new file with mode: 0644]

index e96c16c..ce40992 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2005-12-23  David Shaw  <dshaw@jabberwocky.com>
+
+       * configure.ac: Add switch for DNS CERT.
+
 2005-12-22  David Shaw  <dshaw@jabberwocky.com>
 
        * configure.ac: Split PKA checking off from DNS SRV checking.
index f88a986..ea64287 100644 (file)
@@ -555,8 +555,8 @@ AC_CHECK_FUNC(gethostbyname, , AC_CHECK_LIB(nsl, gethostbyname,
 AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt,
        [NETLIBS="-lsocket $NETLIBS"]))
 
-dnl Now try for the resolver functions so we can use DNS SRV and our 
-dnl PKA feature.
+dnl Now try for the resolver functions so we can use DNS for SRV, PKA,
+dnl and CERT.
 
 if test x"$try_hkp" = xyes || test x"$try_http" = xyes ; then
    AC_ARG_ENABLE(dns-srv,
@@ -570,7 +570,12 @@ AC_ARG_ENABLE(dns-pka,
        [disable the use of PKA records in DNS]),
    use_dns_pka=$enableval,use_dns_pka=yes)
 
-if test x"$use_dns_pka" = xyes || test x"$use_dns_srv" = xyes ; then
+AC_ARG_ENABLE(dns-cert,
+   AC_HELP_STRING([--disable-dns-cert],
+       [disable the use of CERT records in DNS]),
+   use_dns_cert=$enableval,use_dns_cert=yes)
+
+if test x"$use_dns_pka" = xyes || test x"$use_dns_srv" = xyes || test x"$use_dns_cert" = xyes; then
   _srv_save_libs=$LIBS
   LIBS=""
   # the double underscore thing is a glibc-ism?
@@ -601,9 +606,14 @@ if test x"$use_dns_pka" = xyes || test x"$use_dns_srv" = xyes ; then
      if test x"$use_dns_pka" = xyes ; then
         AC_DEFINE(USE_DNS_PKA,1,[define to use our experimental DNS PKA])
      fi
+
+     if test x"$use_dns_cert" = xyes ; then
+        AC_DEFINE(USE_DNS_CERT,1,[define to use DNS CERT])
+     fi
   else
      use_dns_srv=no
      use_dns_pka=no
+     use_dns_cert=no
   fi
 
   LIBS=$_srv_save_libs
index 0f748a9..c7442a6 100644 (file)
@@ -1,3 +1,7 @@
+2005-12-23  David Shaw  <dshaw@jabberwocky.com>
+
+       * util.h: Prototype get_cert().
+
 2005-07-27  Werner Koch  <wk@g10code.com>
 
        * memory.h (m_free, m_alloc, m_realloc, m_strdup): Removed and
index 77b2b66..eba1c84 100644 (file)
@@ -256,7 +256,8 @@ int asprintf (char **buf, const char *fmt, ...);
 /*-- pka.c --*/
 char *get_pka_info (const char *address, unsigned char *fpr);
 
-
+/*-- cert.c --*/
+int get_cert(const char *name,size_t max_size,IOBUF *iobuf,char **url);
 
 /**** other missing stuff ****/
 #ifndef HAVE_ATEXIT  /* For SunOS */
index 16c2338..c8e151b 100644 (file)
@@ -1,3 +1,7 @@
+2005-12-23  David Shaw  <dshaw@jabberwocky.com>
+
+       * cert.c, Makefile.am: New code to do DNS CERT queries.
+
 2005-12-22  David Shaw  <dshaw@jabberwocky.com>
 
        * srv.c, Makefile.am: Only build srv.c if we need to.
index 15b3617..2a3f07c 100644 (file)
@@ -24,7 +24,7 @@ noinst_LIBRARIES = libutil.a
 
 libutil_a_SOURCES = logger.c fileutil.c miscutil.c strgutil.c \
                    ttyio.c argparse.c memory.c secmem.c errors.c iobuf.c \
-                   dotlock.c http.c pka.c membuf.c
+                   dotlock.c http.c pka.c membuf.c cert.c
 
 if USE_SIMPLE_GETTEXT
 libutil_a_SOURCES+=simple-gettext.c
@@ -67,3 +67,7 @@ srv-test:  srv.c
 pka-test:  pka.c
        cc -DHAVE_CONFIG_H -I. -I. -I.. $(INCLUDES) $(LDFLAGS) -g -Wall \
           -DTEST -o pka-test pka.c libutil.a @LIBINTL@ @SRVLIBS@ @CAPLIBS@
+
+cert-test:  cert.c
+       cc -DHAVE_CONFIG_H -I. -I. -I.. $(INCLUDES) $(LDFLAGS) -g -Wall \
+          -DTEST -o cert-test cert.c libutil.a @LIBINTL@ @SRVLIBS@ @CAPLIBS@
diff --git a/util/cert.c b/util/cert.c
new file mode 100644 (file)
index 0000000..94e6bed
--- /dev/null
@@ -0,0 +1,200 @@
+/* cert.c - DNS CERT code
+ * Copyright (C) 2005 Free Software Foundation, Inc.
+ *
+ * This file is part of GNUPG.
+ *
+ * GNUPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GNUPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#include <config.h>
+#include <sys/types.h>
+#ifdef USE_DNS_CERT
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#endif
+#include <string.h>
+#include "memory.h"
+#endif
+#include "iobuf.h"
+
+/* Not every installation has gotten around to supporting CERTs
+   yet... */
+#ifndef T_CERT
+#define T_CERT 37
+#endif
+
+#ifdef USE_DNS_CERT
+
+/* Returns -1 on error, 0 for no answer, 1 for PGP provided and 2 for
+   IPGP provided. */
+int
+get_cert(const char *name,size_t max_size,IOBUF *iobuf,char **url)
+{
+  unsigned char *answer;
+  int r,ret=-1;
+  u16 count;
+
+  answer=xmalloc(max_size);
+
+  r=res_query(name,C_IN,T_CERT,answer,max_size);
+  /* Not too big, not too small, no errors and at least 1 answer. */
+  if(r>=sizeof(HEADER) && r<=max_size
+     && (((HEADER *)answer)->rcode)==NOERROR
+     && (count=ntohs(((HEADER *)answer)->ancount)))
+    {
+      int rc;
+      unsigned char *pt,*emsg;
+
+      emsg=&answer[r];
+
+      pt=&answer[sizeof(HEADER)];
+
+      /* Skip over the query */
+
+      rc=dn_skipname(pt,emsg);
+      if(rc==-1)
+       goto fail;
+
+      pt+=rc+QFIXEDSZ;
+
+      /* There are several possible response types for a CERT request.
+        We're interested in the PGP (a key) and IPGP (a URI) types.
+        Skip all others.  TODO: A key is better than a URI since
+        we've gone through all this bother to fetch it, so favor that
+        if we have both PGP and IPGP? */
+
+      while(count-->0 && pt<emsg)
+       {
+         u16 type,class,dlen,ctype;
+
+         rc=dn_skipname(pt,emsg); /* the name we just queried for */
+         if(rc==-1)
+           break;
+
+         pt+=rc;
+
+         /* Truncated message? */
+         if((emsg-pt)<15)
+           break;
+
+         type=*pt++ << 8;
+         type|=*pt++;
+         /* We asked for CERT and got something else !? */
+         if(type!=T_CERT)
+           break;
+
+         class=*pt++ << 8;
+         class|=*pt++;
+         /* We asked for IN and got something else !? */
+         if(class!=C_IN)
+           break;
+
+         /* ttl */
+         pt+=4;
+
+         /* data length */
+         dlen=*pt++ << 8;
+         dlen|=*pt++;
+
+         /* The CERT type */
+         ctype=*pt++ << 8;
+         ctype|=*pt++;
+
+         /* Skip the CERT key tag and algo which we don't need. */
+         pt+=3;
+
+         dlen-=5;
+
+         if(ctype==3 && iobuf)
+           {
+             /* PGP type */
+             *iobuf=iobuf_temp_with_content(pt,dlen);
+             ret=1;
+             break;
+           }
+         else if(ctype==6 && dlen<1023 && url)
+           {
+             /* Sanity check the IPGP URL type that the URL isn't too
+                long */
+
+             *url=xmalloc(dlen+1);
+             memcpy(*url,pt,dlen);
+             ret=2;
+             break;
+           }
+
+         /* Neither type matches, so go around to the next answer. */
+         pt+=dlen;
+       }
+    }
+
+ fail:
+  xfree(answer);
+
+  return ret;
+}
+
+#else /* !USE_DNS_CERT */
+
+int
+get_cert(const char *name,size_t max_size,IOBUF *iobuf,char **url)
+{
+  return -1;
+}
+
+#endif
+
+/* Test with simon.josefsson.org */
+
+#ifdef TEST
+int
+main(int argc,char *argv[])
+{
+  char *url;
+  int rc;
+  IOBUF iobuf;
+
+  if(argc!=2)
+    {
+      printf("cert-test [name]\n");
+      return 1;
+    }
+
+  printf("CERT lookup on %s\n",argv[1]);
+
+  rc=get_cert(argv[1],16384,&iobuf,&url);
+  if(rc==-1)
+    printf("error\n");
+  else if(rc==0)
+    printf("no answer\n");
+  else if(rc==1)
+    {
+      printf("key found: %d bytes\n",iobuf_get_temp_length(iobuf));
+      iobuf_close(iobuf);
+    }
+  else if(rc==2)
+    {
+      printf("URL found: %s\n",url);
+      xfree(url);
+    }
+
+  return 0;
+}
+#endif /* TEST */