Use ADNS for PKA and SRV records if no other resolver is available.
[gnupg.git] / common / pka.c
index 3d442d1..e78f543 100644 (file)
@@ -5,7 +5,7 @@
  *
  * 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
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * GnuPG is distributed in the hope that it will be useful,
@@ -14,9 +14,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 #include <resolv.h>
 #endif
 #endif /* USE_DNS_PKA */
+#ifdef USE_ADNS
+# include <adns.h>
+# ifndef HAVE_ADNS_FREE
+#  define adns_free free
+# endif
+#endif
 
 #include "util.h"
 #include "pka.h"
@@ -100,7 +104,7 @@ parse_txt_record (char *buffer, unsigned char *fpr)
 
    On success the 20 byte SHA-1 fingerprint is stored at FPR and the
    URI will be returned in an allocated buffer.  Note that the URI
-   might be an zero length string as this information is optiobnal.
+   might be an zero length string as this information is optional.
    Caller must xfree the returned string.
 
    On error NULL is returned and the 20 bytes at FPR are not
@@ -108,6 +112,67 @@ parse_txt_record (char *buffer, unsigned char *fpr)
 char *
 get_pka_info (const char *address, unsigned char *fpr)
 {
+#ifdef USE_ADNS
+  int rc;
+  adns_state state;
+  const char *domain;
+  char *name;
+  adns_answer *answer = NULL;
+  char *buffer = NULL;
+  
+  domain = strrchr (address, '@');
+  if (!domain || domain == address || !domain[1])
+    return NULL; /* Invalid mail address given.  */
+  name = xtrymalloc (strlen (address) + 5 + 1);
+  if (!name)
+    return NULL;
+  memcpy (name, address, domain - address);
+  strcpy (stpcpy (name + (domain-address), "._pka."), domain+1);
+
+  rc = adns_init (&state, adns_if_noerrprint, NULL);
+  if (rc)
+    {
+      log_error ("error initializing adns: %s\n", strerror (errno));
+      xfree (name);
+      return NULL;
+    }
+
+  rc = adns_synchronous (state, name, adns_r_txt, adns_qf_quoteok_query,
+                         &answer);
+  xfree (name);
+  if (rc)
+    {
+      log_error ("DNS query failed: %s\n", strerror (errno));
+      adns_finish (state);
+      return NULL;
+    }
+  if (answer->status != adns_s_ok 
+      || answer->type != adns_r_txt || !answer->nrrs)
+    {
+      log_error ("DNS query returned an error: %s (%s)\n",
+                 adns_strerror (answer->status),
+                 adns_errabbrev (answer->status));
+      adns_free (answer);
+      adns_finish (state);
+      return NULL;
+    }
+
+  /* We use a PKA records iff there is exactly one record.  */
+  if (answer->nrrs == 1 && answer->rrs.manyistr[0]->i != -1)
+    {
+      buffer = xtrystrdup (answer->rrs.manyistr[0]->str);
+      if (parse_txt_record (buffer, fpr))
+        {
+          xfree (buffer);
+          buffer = NULL;   /* Not a valid gpg trustdns RR. */
+        }
+    }
+
+  adns_free (answer);
+  adns_finish (state);
+  return buffer;
+
+#else /*!USE_ADNS*/
   unsigned char answer[PACKETSZ];
   int anslen;
   int qdcount, ancount, nscount, arcount;
@@ -121,7 +186,9 @@ get_pka_info (const char *address, unsigned char *fpr)
   if (!domain || domain == address || !domain[1])
     return NULL; /* invalid mail address given. */
 
-  name = malloc (strlen (address) + 5 + 1);
+  name = xtrymalloc (strlen (address) + 5 + 1);
+  if (!name)
+    return NULL;
   memcpy (name, address, domain - address);
   strcpy (stpcpy (name + (domain-address), "._pka."), domain+1);
 
@@ -197,7 +264,9 @@ get_pka_info (const char *address, unsigned char *fpr)
     }
 
   return NULL;
+#endif /*!USE_ADNS*/
 }
+
 #else /* !USE_DNS_PKA */
 
 /* Dummy version of the function if we can't use the resolver
@@ -247,6 +316,6 @@ main(int argc,char *argv[])
 
 /*
 Local Variables:
-compile-command: "cc -DUSE_DNS_PKA -DTEST -I.. -I../include -Wall -g -o pka pka.c -lresolv libutil.a"
+compile-command: "cc -DUSE_DNS_PKA -DTEST -I.. -I../include -Wall -g -o pka pka.c -lresolv ../tools/no-libgcrypt.o ../jnlib/libjnlib.a"
 End:
 */