[git] ADNS-g10 - branch, master, updated. adns-1.4-g10-3-2-g859ca67

by Werner Koch cvs at cvs.gnupg.org
Wed Mar 19 16:42:43 CET 2014


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "ADNS migrated to autotools/libtool".

The branch, master has been updated
       via  859ca67cbff1c6d7e850e53d99a9e57c93021b16 (commit)
      from  0e63141f80e5eba46b6bb2a29cd1b93fdcdff8f7 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 859ca67cbff1c6d7e850e53d99a9e57c93021b16
Author: Werner Koch <wk at gnupg.org>
Date:   Wed Mar 19 16:35:52 2014 +0100

    adnslogres: Support IPv6 and improve privacy mode.
    
    * client/adnslogres.c: Add assert.h.
    (TRUNCIPLEN): New.
    (OPT_VHOST): New.
    (expand_v6): New.
    (ipaddr2domain): Rewrite.
    (printline): Print truncated IP if resolving failed and append 4 or 6
    to indicate the used protocol.
    (readline): Request raw ptr vor v6.  Handle new parameters.
    (main): Add option -x.

diff --git a/client/adnslogres.c b/client/adnslogres.c
index 1e07f12..cd3ac23 100644
--- a/client/adnslogres.c
+++ b/client/adnslogres.c
@@ -43,6 +43,7 @@
 #include <errno.h>
 #include <stdarg.h>
 #include <stdint.h>
+#include <assert.h>
 
 #include "config.h"
 #include "adns.h"
@@ -60,10 +61,15 @@
 /* maximum length of a line */
 #define MAXLINE 2048
 
+/* Max length of a truncated IP string.
+   "nnnn:nnnn:n000::"  or "nnn.nnn.0.0"  */
+#define TRUNCIPLEN 16
+
 /* option flags */
 #define OPT_DEBUG 1
 #define OPT_POLL 2
 #define OPT_PRIVACY 4
+#define OPT_VHOST 8
 
 static const char *const progname= "adnslogres";
 static const char *config_text;
@@ -488,43 +494,195 @@ rmd160_hash_buffer (void *outbuf, const void *buffer, size_t length)
 }
 
 
+/* Expand an IPv6 address string by inserting missing '0', changing
+   letters to lowercase, and removing the the colons.  Returns a
+   pointer to a static buffer or NULL on error.  Example:
+   "2001:aA8:fff1:2100::60" gives
+   "20010aa8fff121000000000000000060".  */
+static char *
+expand_v6 (const char *addrstr)
+{
+  static char buffer[32+1];
+  char tmpbuf[4];
+  int tmpidx, idx, i;
+  const char *s;
+  int ncolon;
+
+  for (s=addrstr, ncolon=0; *s && !sensible_ctype (isspace, *s); s++)
+    {
+      if (*s == ':')
+        ncolon++;
+    }
+  if (ncolon > 8)
+    return NULL;  /* Oops.  */
+
+  memset (buffer, '0', 32);
+  buffer[32] = 0;
+  idx = tmpidx = 0;
+  for (s=addrstr; *s && !sensible_ctype (isspace, *s); s++)
+    {
+      if (*s == ':')
+        {
+          idx += 4 - tmpidx;
+          for (i=0; i < tmpidx; i++)
+            {
+              if (idx >= sizeof buffer)
+                return NULL;
+              buffer[idx++] = tmpbuf[i];
+            }
+          tmpidx = 0;
+          if (s[1] == ':') /* Double colon.  */
+            {
+              s++;
+              if (!ncolon || s[1] == ':')
+                return NULL;  /* More than one double colon. */
+              idx += 4*(8 - ncolon);
+              ncolon = 0;
+            }
+        }
+      else if (tmpidx > 3)
+        return NULL;  /* Invalid address.  */
+      else if (!sensible_ctype (isxdigit, *s))
+        return NULL;  /* Invalid character.  */
+      else
+        tmpbuf[tmpidx++] = sensible_ctype (tolower, *s);
+    }
+
+  idx += 4 - tmpidx;
+  for (i=0; i < tmpidx; i++)
+    {
+      if (idx >= sizeof buffer)
+        return NULL;
+      buffer[idx++] = tmpbuf[i];
+    }
+
+  return buffer;
+}
+
+
 /*
- * Parse the IP address and convert to a reverse domain name.
+ * Parse the IP address and convert to a reverse domain name.  ON
+ * return a truncated IP address is stored at TRUNCIP which is
+ * expected to be a buffer of at least TRUNCIPLEN+1 bytes.
  */
-static char *ipaddr2domain(char *start, char **addr, char **rest) {
-  static char buf[30]; /* "123.123.123.123.in-addr.arpa.\0" */
-  char *ptrs[5];
+static char *
+ipaddr2domain(char *start, char **addr, char **rest, char *truncip,
+              int *r_is_v6, int opts)
+{
+  /* Sample values BUF needs to hold:
+   * "123.123.123.123.in-addr.arpa."
+   * "0.6.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.2.1.f.f.f.8.a.a.0.1.0.0.2.ip6.arpa."
+   */
+  static char buf[74];
   int i;
+  char *endp;
+  int ndots = 0;
 
-  ptrs[0]= start;
-retry:
-  while (!sensible_ctype(isdigit,*ptrs[0]))
-    if (!*ptrs[0]++) {
-      strcpy(buf, "invalid.");
-      *addr= *rest= NULL;
-      return buf;
+  *r_is_v6 = 0;
+
+  /* Better skip leading spaces which might have been create by some
+     log processing scripts.  */
+  while (sensible_ctype(isspace, *start))
+    start++;
+
+  if ((opts & OPT_VHOST))
+    {
+      while (!sensible_ctype(isspace, *start))
+        start++;
+      while (sensible_ctype(isspace, *start))
+        start++;
     }
-  for (i= 1; i < 5; i++) {
-    ptrs[i]= ptrs[i-1];
-    while (sensible_ctype(isdigit,*ptrs[i]++));
-    if ((i == 4 && !sensible_ctype(isspace,ptrs[i][-1])) ||
-	(i != 4 && ptrs[i][-1] != '.') ||
-	(ptrs[i]-ptrs[i-1] > 4)) {
-      ptrs[0]= ptrs[i]-1;
-      goto retry;
+
+  for (endp = start; !sensible_ctype(isspace, *endp); endp++)
+    {
+      if (*endp == ':')
+        *r_is_v6 = 1;
+      else if (*endp == '.')
+        ndots++;
     }
-  }
-  sprintf(buf, "%.*s.%.*s.%.*s.%.*s.in-addr.arpa.",
-	  (int)(ptrs[4]-ptrs[3]-1), ptrs[3],
-	  (int)(ptrs[3]-ptrs[2]-1), ptrs[2],
-	  (int)(ptrs[2]-ptrs[1]-1), ptrs[1],
-	  (int)(ptrs[1]-ptrs[0]-1), ptrs[0]);
-  *addr= ptrs[0];
-  *rest= ptrs[4]-1;
+  if (endp == start)
+    {
+      strcpy (buf, "invalid");
+      *addr = *rest = NULL;
+      goto leave;
+    }
+
+  if (*r_is_v6)
+    {
+      const char *exp = expand_v6 (start);
+      const char *s;
+      char *p;
+      size_t len;
+
+      if (!exp)
+        {
+          strcpy (buf, "invalid_v6");
+          *addr = *rest = NULL;
+          goto leave;
+        }
+
+      len = strlen (exp);
+      assert (len + 9 + 1 <= sizeof buf);
+      p = buf;
+      for (s = exp + len - 1; s >= exp; s--)
+        {
+          *p++ = *s;
+          *p++ = '.';
+        }
+      strcpy (p, "ip6.arpa.");
+      snprintf (truncip, TRUNCIPLEN+1, "%.4s:%.4s:%.1s000::",
+                exp, exp+4, exp+8);
+      *addr = start;
+      *rest = endp;
+    }
+  else /* v4 */
+    {
+      char *ptrs[5];
+
+      /* Largest expected string is "255.255.255.255".  */
+      if ((endp - start) > 15 || ndots != 3)
+        {
+          strcpy (buf, "invalid_v4");
+          *addr = *rest = NULL;
+          goto leave;
+        }
+      ptrs[0] = start;
+      for (i = 1; i < 5; i++)
+        {
+          ptrs[i] = ptrs[i-1];
+          while (sensible_ctype (isdigit, *ptrs[i]++))
+            ;
+          if ((i == 4 && !sensible_ctype (isspace, ptrs[i][-1]))
+              || (i != 4 && ptrs[i][-1] != '.')
+              || (ptrs[i]-ptrs[i-1] > 4)
+              || (i!=4 && !sensible_ctype (isdigit, ptrs[i][0])))
+            {
+              strcpy (buf, "invalid_v4");
+              *addr = *rest = NULL;
+              goto leave;
+            }
+        }
+
+      snprintf (buf, sizeof buf, "%.*s.%.*s.%.*s.%.*s.in-addr.arpa.",
+                (int)(ptrs[4]-ptrs[3]-1), ptrs[3],
+                (int)(ptrs[3]-ptrs[2]-1), ptrs[2],
+                (int)(ptrs[2]-ptrs[1]-1), ptrs[1],
+                (int)(ptrs[1]-ptrs[0]-1), ptrs[0]);
+      snprintf (truncip, TRUNCIPLEN+1, "%.*s.%.*s.0.0",
+                (int)(ptrs[1]-ptrs[0]-1), ptrs[0],
+                (int)(ptrs[2]-ptrs[1]-1), ptrs[1]);
+      *addr= ptrs[0];
+      *rest= ptrs[4]-1;
+    }
+
+ leave:
   return buf;
 }
 
-static void printline(FILE *outf, char *start, char *addr, char *rest, char *domain, int opts) {
+static void
+printline(FILE *outf, char *start, char *addr, char *rest, char *domain,
+          const char *truncip, int is_v6, int opts)
+{
   if (domain)
     {
       char *p;
@@ -539,11 +697,13 @@ static void printline(FILE *outf, char *start, char *addr, char *rest, char *dom
           fprintf(outf, "%.*sp", (int)(addr - start), start);
           for (i=0; i < 4; i++)
             fprintf (outf, "%02x", hash[i]);
-          fprintf(outf, "%s%s", p, rest);
+          fprintf(outf, "%c%s%s", is_v6? '6':'4', p, rest);
         }
       else
         fprintf(outf, "%.*s%s%s", (int)(addr - start), start, domain, rest);
     }
+  else if ((opts & OPT_PRIVACY))
+    fprintf(outf, "%.*s%s%s", (int)(addr - start), start, truncip, rest);
   else
     fputs(start, outf);
   if (ferror(outf)) aargh("write output");
@@ -552,6 +712,8 @@ static void printline(FILE *outf, char *start, char *addr, char *rest, char *dom
 typedef struct logline {
   struct logline *next;
   char *start, *addr, *rest;
+  char truncip[TRUNCIPLEN+1];
+  int is_v6;
   adns_query query;
 } logline;
 
@@ -566,11 +728,16 @@ static logline *readline(FILE *inf, adns_state adns, int opts) {
     line= (logline*)str;
     line->next= NULL;
     line->start= str+sizeof(logline);
+    line->is_v6 = 0;
+    *line->truncip = 0;
     strcpy(line->start, buf);
-    str= ipaddr2domain(line->start, &line->addr, &line->rest);
+    str= ipaddr2domain(line->start, &line->addr, &line->rest, line->truncip,
+                       &line->is_v6, opts);
     if (opts & OPT_DEBUG)
       msg("submitting %.*s -> %s", (int)(line->rest-line->addr), guard_null(line->addr), str);
-    if (adns_submit(adns, str, adns_r_ptr,
+    /* Note: ADNS does not yet support "ptr" for IPv6.  */
+    if (adns_submit(adns, str,
+                    line->is_v6? adns_r_ptr_raw : adns_r_ptr,
 		    adns_qf_quoteok_cname|adns_qf_cname_loose,
 		    NULL, &line->query))
       aargh("adns_submit");
@@ -616,7 +783,8 @@ static void proclog(FILE *inf, FILE *outf, int maxpending, int opts) {
 	exit(1);
       }
       printline(outf, head->start, head->addr, head->rest,
-		answer->status == adns_s_ok ? *answer->rrs.str : NULL, opts);
+		answer->status == adns_s_ok ? *answer->rrs.str : NULL,
+                head->truncip, head->is_v6, opts);
       line= head; head= head->next;
       free(line);
       free(answer);
@@ -643,8 +811,13 @@ static void printhelp(FILE *file) {
 	"         -p                use poll(2) instead of select(2)\n"
 	"         -d                turn on debugging\n"
         "         -P                privacy mode\n"
+        "         -x                first field is the virtual host\n"
         "         -S <salt>         salt for the privacy mode\n"
-	"         -C <config>       use instead of contents of resolv.conf\n",
+	"         -C <config>       use instead of contents of resolv.conf\n"
+        "\n"
+        "The privacy mode replaces resolved addresses by a 32 bit hash value\n"
+        "or truncates IP addresses to 16/40 bit.  A random salt should be\n"
+        "used to make testing for addresses hard.\n",
 	stdout);
 }
 
@@ -672,7 +845,7 @@ int main(int argc, char *argv[]) {
 
   maxpending= DEFMAXPENDING;
   opts= 0;
-  while ((c= getopt(argc, argv, "c:C:dpPS:")) != -1)
+  while ((c= getopt(argc, argv, "c:C:dxpPS:")) != -1)
     switch (c) {
     case 'c':
       maxpending= atoi(optarg);
@@ -687,6 +860,9 @@ int main(int argc, char *argv[]) {
     case 'd':
       opts|= OPT_DEBUG;
       break;
+    case 'x':
+      opts|= OPT_VHOST;
+      break;
     case 'P':
       opts|= OPT_PRIVACY;
       break;

-----------------------------------------------------------------------

Summary of changes:
 client/adnslogres.c |  244 ++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 210 insertions(+), 34 deletions(-)


hooks/post-receive
-- 
ADNS migrated to autotools/libtool
http://git.gnupg.org




More information about the Gnupg-commits mailing list