Use ADNS for PKA and SRV records if no other resolver is available.
authorWerner Koch <wk@gnupg.org>
Mon, 7 Dec 2009 15:52:27 +0000 (15:52 +0000)
committerWerner Koch <wk@gnupg.org>
Mon, 7 Dec 2009 15:52:27 +0000 (15:52 +0000)
ChangeLog
NEWS
common/ChangeLog
common/pka.c
common/srv.c
configure.ac
doc/DETAILS
tools/ChangeLog
tools/no-libgcrypt.c

index 813e25b..41de8ba 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2009-12-07  Werner Koch  <wk@g10code.com>
+
+       * configure.ac: Check for ADNS before checking for the BIND
+       resolver.
+
 2009-10-20  Marcus Brinkmann  <marcus@g10code.com>
 
        * configure.ac: Check for fusermount and encfs.
 2009-10-20  Marcus Brinkmann  <marcus@g10code.com>
 
        * configure.ac: Check for fusermount and encfs.
diff --git a/NEWS b/NEWS
index d240e82..0d543cd 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,8 @@ Noteworthy changes in version 2.1.x (under development)
  * Numerical values may now be used as an alternative to the
    debug-level keywords.
 
  * Numerical values may now be used as an alternative to the
    debug-level keywords.
 
+ * Support SRV and PKA records on W32.
+
 
 Noteworthy changes in version 2.0.13 (2009-09-04)
 -------------------------------------------------
 
 Noteworthy changes in version 2.0.13 (2009-09-04)
 -------------------------------------------------
index e2da8a0..6ec4582 100644 (file)
@@ -1,3 +1,10 @@
+2009-12-07  Werner Koch  <wk@g10code.com>
+
+       * pka.c (get_pka_info): Add support for ADNS.
+       * src.v (getsrv): Add support for ADNS.
+
+       * srv.c (getsrv): s/xrealloc/xtryrealloc/.
+
 2009-12-04  Werner Koch  <wk@g10code.com>
 
        * Makefile.am (audit-events.h, status-codes.h): Create files in
 2009-12-04  Werner Koch  <wk@g10code.com>
 
        * Makefile.am (audit-events.h, status-codes.h): Create files in
index 79a0bc3..e78f543 100644 (file)
 #include <resolv.h>
 #endif
 #endif /* USE_DNS_PKA */
 #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"
 
 #include "util.h"
 #include "pka.h"
@@ -106,6 +112,67 @@ parse_txt_record (char *buffer, unsigned char *fpr)
 char *
 get_pka_info (const char *address, 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;
   unsigned char answer[PACKETSZ];
   int anslen;
   int qdcount, ancount, nscount, arcount;
@@ -197,7 +264,9 @@ get_pka_info (const char *address, unsigned char *fpr)
     }
 
   return NULL;
     }
 
   return NULL;
+#endif /*!USE_ADNS*/
 }
 }
+
 #else /* !USE_DNS_PKA */
 
 /* Dummy version of the function if we can't use the resolver
 #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:
 
 /*
 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:
 */
 End:
 */
index 46d84b5..79ffc78 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
+#ifdef USE_ADNS
+# include <adns.h>
+# ifndef HAVE_ADNS_FREE
+#  define adns_free free
+# endif
+#endif
 
 #include "util.h"
 #include "srv.h"
 
 #include "util.h"
 #include "srv.h"
@@ -52,172 +58,232 @@ priosort(const void *a,const void *b)
     return 0;
 }
 
     return 0;
 }
 
+
 int
 int
-getsrv(const char *name,struct srventry **list)
+getsrv (const char *name,struct srventry **list)
 {
 {
-  unsigned char answer[2048];
-  int r,srvcount=0;
-  unsigned char *pt,*emsg;
-  u16 count,dlen;
-  HEADER *header=(HEADER *)answer;
-
-  *list=NULL;
+  int srvcount=0;
+  u16 count;
+  int i, rc;
+
+  *list = NULL;
+
+#ifdef USE_ADNS
+  {
+    adns_state state;
+    adns_answer *answer = NULL;
+    
+    rc = adns_init (&state, adns_if_noerrprint, NULL);
+    if (rc)
+      {
+        log_error ("error initializing adns: %s\n", strerror (errno));
+        return -1;
+      }
+
+    rc = adns_synchronous (state, name, adns_r_srv, adns_qf_quoteok_query,
+                           &answer);
+    if (rc)
+      {
+        log_error ("DNS query failed: %s\n", strerror (errno));
+        adns_finish (state);
+        return -1;
+      }
+    if (answer->status != adns_s_ok 
+        || answer->type != adns_r_srv || !answer->nrrs)
+      {
+        log_error ("DNS query returned an error or no records: %s (%s)\n",
+                   adns_strerror (answer->status),
+                   adns_errabbrev (answer->status));
+        adns_free (answer);
+        adns_finish (state);
+        return 0;
+      }
+
+    for (count = 0; count < answer->nrrs; count++)
+      {
+        struct srventry *srv = NULL;
+        struct srventry *newlist;
+
+        if (strlen (answer->rrs.srvha[count].ha.host) >= MAXDNAME)
+          {
+            log_info ("hostname in SRV record too long - skipped\n");
+            continue;
+          }
+      
+        newlist = xtryrealloc (*list, (srvcount+1)*sizeof(struct srventry));
+        if (!newlist)
+          goto fail;
+        *list = newlist;
+        memset (&(*list)[srvcount], 0, sizeof(struct srventry));
+        srv = &(*list)[srvcount];
+        srvcount++;
+      
+        srv->priority = answer->rrs.srvha[count].priority;
+        srv->weight   = answer->rrs.srvha[count].weight;
+        srv->port     = answer->rrs.srvha[count].port;
+        strcpy (srv->target, answer->rrs.srvha[count].ha.host);
+      }
+
+    adns_free (answer);
+    adns_finish (state);
+  }
+#else /*!USE_ADNS*/
+  {
+    unsigned char answer[2048];
+    HEADER *header = (HEADER *)answer;
+    unsigned char *pt, *emsg;
+    int r;
+    u16 dlen;
+    
+    r = res_query (name, C_IN, T_SRV, answer, sizeof answer);
+    if (r < sizeof (HEADER) || r > sizeof answer)
+      return -1;
+    if (header->rcode != NOERROR || !(count=ntohs (header->ancount)))
+      return 0; /* Error or no record found.  */
+    
+    emsg = &answer[r];
+    pt = &answer[sizeof(HEADER)];
+  
+    /* Skip over the query */
+    rc = dn_skipname (pt, emsg);
+    if (rc == -1)
+      goto fail;
+  
+    pt += rc + QFIXEDSZ;
+  
+    while (count-- > 0 && pt < emsg)
+      {
+        struct srventry *srv=NULL;
+        u16 type,class;
+        struct srventry *newlist;
+      
+        newlist = xtryrealloc (*list, (srvcount+1)*sizeof(struct srventry));
+        if (!newlist)
+          goto fail;
+        *list = newlist;
+        memset(&(*list)[srvcount],0,sizeof(struct srventry));
+        srv=&(*list)[srvcount];
+        srvcount++;
+      
+        rc = dn_skipname(pt,emsg); /* the name we just queried for */
+        if (rc == -1)
+          goto fail;
+        pt+=rc;
+      
+        /* Truncated message? */
+        if((emsg-pt)<16)
+          goto fail;
+      
+        type=*pt++ << 8;
+        type|=*pt++;
+        /* We asked for SRV and got something else !? */
+        if(type!=T_SRV)
+          goto fail;
+      
+        class=*pt++ << 8;
+        class|=*pt++;
+        /* We asked for IN and got something else !? */
+        if(class!=C_IN)
+          goto fail;
+      
+        pt+=4; /* ttl */
+        dlen=*pt++ << 8;
+        dlen|=*pt++;
+        srv->priority=*pt++ << 8;
+        srv->priority|=*pt++;
+        srv->weight=*pt++ << 8;
+        srv->weight|=*pt++;
+        srv->port=*pt++ << 8;
+        srv->port|=*pt++;
+      
+        /* Get the name.  2782 doesn't allow name compression, but
+           dn_expand still works to pull the name out of the
+           packet. */
+        rc = dn_expand(answer,emsg,pt,srv->target,MAXDNAME);
+        if (rc == 1 && srv->target[0] == 0) /* "." */
+          {
+            xfree(*list);
+            *list = NULL;
+            return 0;
+          }
+        if (rc == -1)
+          goto fail;
+        pt += rc;
+        /* Corrupt packet? */
+        if (dlen != rc+6)
+          goto fail;
+      }
+  }
+#endif /*!USE_ADNS*/
+  
+  /* Now we have an array of all the srv records. */
+  
+  /* Order by priority */
+  qsort(*list,srvcount,sizeof(struct srventry),priosort);
+  
+  /* For each priority, move the zero-weighted items first. */
+  for (i=0; i < srvcount; i++)
+    {
+      int j;
+      
+      for (j=i;j < srvcount && (*list)[i].priority == (*list)[j].priority; j++)
+        {
+          if((*list)[j].weight==0)
+            {
+              /* Swap j with i */
+              if(j!=i)
+                {
+                  struct srventry temp;
+                  
+                  memcpy (&temp,&(*list)[j],sizeof(struct srventry));
+                  memcpy (&(*list)[j],&(*list)[i],sizeof(struct srventry));
+                  memcpy (&(*list)[i],&temp,sizeof(struct srventry));
+                }
+              
+              break;
+            }
+        }
+    }
 
 
-  r=res_query(name,C_IN,T_SRV,answer,2048);
-  if(r<sizeof(HEADER) || r>2048)
-    return -1;
+  /* Run the RFC-2782 weighting algorithm.  We don't need very high
+     quality randomness for this, so regular libc srand/rand is
+     sufficient.  Fixme: It is a bit questionaly to reinitalize srand
+     - better use a gnupg fucntion for this.  */
+  srand(time(NULL)*getpid());
 
 
-  if(header->rcode==NOERROR && (count=ntohs(header->ancount)))
+  for (i=0; i < srvcount; i++)
     {
     {
-      int i,rc;
-
-      emsg=&answer[r];
-      pt=&answer[sizeof(HEADER)];
-
-      /* Skip over the query */
-
-      rc=dn_skipname(pt,emsg);
-      if(rc==-1)
-       goto fail;
-
-      pt+=rc+QFIXEDSZ;
-
-      while(count-->0 && pt<emsg)
-       {
-         struct srventry *srv=NULL;
-         u16 type,class;
-
-         *list=xrealloc(*list,(srvcount+1)*sizeof(struct srventry));
-         memset(&(*list)[srvcount],0,sizeof(struct srventry));
-         srv=&(*list)[srvcount];
-         srvcount++;
-
-         rc=dn_skipname(pt,emsg); /* the name we just queried for */
-         if(rc==-1)
-           goto fail;
-         pt+=rc;
-
-         /* Truncated message? */
-         if((emsg-pt)<16)
-           goto fail;
-
-         type=*pt++ << 8;
-         type|=*pt++;
-         /* We asked for SRV and got something else !? */
-         if(type!=T_SRV)
-           goto fail;
-
-         class=*pt++ << 8;
-         class|=*pt++;
-         /* We asked for IN and got something else !? */
-         if(class!=C_IN)
-           goto fail;
-
-         pt+=4; /* ttl */
-         dlen=*pt++ << 8;
-         dlen|=*pt++;
-         srv->priority=*pt++ << 8;
-         srv->priority|=*pt++;
-         srv->weight=*pt++ << 8;
-         srv->weight|=*pt++;
-         srv->port=*pt++ << 8;
-         srv->port|=*pt++;
-
-         /* Get the name.  2782 doesn't allow name compression, but
-            dn_expand still works to pull the name out of the
-            packet. */
-         rc=dn_expand(answer,emsg,pt,srv->target,MAXDNAME);
-         if(rc==1 && srv->target[0]==0) /* "." */
-           goto noanswer;
-         if(rc==-1)
-           goto fail;
-         pt+=rc;
-         /* Corrupt packet? */
-         if(dlen!=rc+6)
-           goto fail;
-
-#if 0
-         printf("count=%d\n",srvcount);
-         printf("priority=%d\n",srv->priority);
-         printf("weight=%d\n",srv->weight);
-         printf("port=%d\n",srv->port);
-         printf("target=%s\n",srv->target);
-#endif
-       }
-
-      /* Now we have an array of all the srv records. */
-
-      /* Order by priority */
-      qsort(*list,srvcount,sizeof(struct srventry),priosort);
-
-      /* For each priority, move the zero-weighted items first. */
-      for(i=0;i<srvcount;i++)
-       {
-         int j;
-
-         for(j=i;j<srvcount && (*list)[i].priority==(*list)[j].priority;j++)
-           {
-             if((*list)[j].weight==0)
-               {
-                 /* Swap j with i */
-                 if(j!=i)
-                   {
-                     struct srventry temp;
-
-                     memcpy(&temp,&(*list)[j],sizeof(struct srventry));
-                     memcpy(&(*list)[j],&(*list)[i],sizeof(struct srventry));
-                     memcpy(&(*list)[i],&temp,sizeof(struct srventry));
-                   }
-
-                 break;
-               }
-           }
-       }
-
-      /* Run the RFC-2782 weighting algorithm.  We don't need very
-        high quality randomness for this, so regular libc srand/rand
-        is sufficient. */
-      srand(time(NULL)*getpid());
-
-      for(i=0;i<srvcount;i++)
-       {
-         int j;
-         float prio_count=0,chose;
-
-         for(j=i;j<srvcount && (*list)[i].priority==(*list)[j].priority;j++)
-           {
-             prio_count+=(*list)[j].weight;
-             (*list)[j].run_count=prio_count;
-           }
-
-         chose=prio_count*rand()/RAND_MAX;
-
-         for(j=i;j<srvcount && (*list)[i].priority==(*list)[j].priority;j++)
-           {
-             if(chose<=(*list)[j].run_count)
-               {
-                 /* Swap j with i */
-                 if(j!=i)
-                   {
-                     struct srventry temp;
-
-                     memcpy(&temp,&(*list)[j],sizeof(struct srventry));
-                     memcpy(&(*list)[j],&(*list)[i],sizeof(struct srventry));
-                     memcpy(&(*list)[i],&temp,sizeof(struct srventry));
-                   }
-                 break;
-               }
-           }
-       }
+      int j;
+      float prio_count=0,chose;
+      
+      for (j=i; j < srvcount && (*list)[i].priority == (*list)[j].priority; j++)
+        {
+          prio_count+=(*list)[j].weight;
+          (*list)[j].run_count=prio_count;
+        }
+      
+      chose=prio_count*rand()/RAND_MAX;
+      
+      for (j=i;j<srvcount && (*list)[i].priority==(*list)[j].priority;j++)
+        {
+          if (chose<=(*list)[j].run_count)
+            {
+              /* Swap j with i */
+              if(j!=i)
+                {
+                  struct srventry temp;
+                  
+                  memcpy(&temp,&(*list)[j],sizeof(struct srventry));
+                  memcpy(&(*list)[j],&(*list)[i],sizeof(struct srventry));
+                  memcpy(&(*list)[i],&temp,sizeof(struct srventry));
+                }
+              break;
+            }
+        }
     }
   
   return srvcount;
 
     }
   
   return srvcount;
 
- noanswer:
-  xfree(*list);
-  *list=NULL;
-  return 0;
-
  fail:
   xfree(*list);
   *list=NULL;
  fail:
   xfree(*list);
   *list=NULL;
@@ -250,6 +316,6 @@ main(int argc,char *argv[])
 
 /*
 Local Variables:
 
 /*
 Local Variables:
-compile-command: "cc -DTEST -I.. -I../include -Wall -g -o srv srv.c -lresolv libutil.a"
+compile-command: "cc -DTEST -I.. -I../include -Wall -g -o srv srv.c -lresolv  ../tools/no-libgcrypt.o  ../jnlib/libjnlib.a"
 End:
 */
 End:
 */
index 42f4857..8797e79 100644 (file)
@@ -710,6 +710,35 @@ AC_CHECK_FUNC(gethostbyname, , AC_CHECK_LIB(nsl, gethostbyname,
 AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt,
        [NETLIBS="-lsocket $NETLIBS"]))
 
 AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt,
        [NETLIBS="-lsocket $NETLIBS"]))
 
+
+#
+# Check for ADNS.
+#
+_cppflags="${CPPFLAGS}"
+_ldflags="${LDFLAGS}"
+AC_ARG_WITH(adns,
+            AC_HELP_STRING([--with-adns=DIR],
+                           [look for the adns library in DIR]),
+            [if test -d "$withval"; then
+               CPPFLAGS="${CPPFLAGS} -I$withval/include"
+               LDFLAGS="${LDFLAGS} -L$withval/lib"
+             fi])
+if test "$with_adns" != "no"; then
+  AC_CHECK_HEADERS(adns.h,
+                AC_CHECK_LIB(adns, adns_init,
+                             [have_adns=yes],
+                             [CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}]),
+                [CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}])
+fi
+if test "$have_adns" = "yes"; then
+  ADNSLIBS="-ladns" 
+fi
+AC_SUBST(ADNSLIBS)
+# Newer adns versions feature a free function to be used under W32.
+AC_CHECK_FUNCS(adns_free)
+
+
+
 #
 # Now try for the resolver functions so we can use DNS for SRV, PA and CERT.
 #
 #
 # Now try for the resolver functions so we can use DNS for SRV, PA and CERT.
 #
@@ -747,7 +776,8 @@ if test x"$use_dns_pka" = xyes || test x"$use_dns_srv" = xyes \
     # Make sure that the BIND 4 resolver interface is workable before
     # enabling any code that calls it.  At some point I'll rewrite the
     # code to use the BIND 8 resolver API.
     # Make sure that the BIND 4 resolver interface is workable before
     # enabling any code that calls it.  At some point I'll rewrite the
     # code to use the BIND 8 resolver API.
-    # We might also want to use adns instead.
+    # We might also want to use adns instead.  Problem with ADNS is that
+    # it does not support v6.
 
     AC_MSG_CHECKING([whether the resolver is usable])
     AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <sys/types.h>
 
     AC_MSG_CHECKING([whether the resolver is usable])
     AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <sys/types.h>
@@ -802,6 +832,20 @@ if test x"$use_dns_pka" = xyes || test x"$use_dns_srv" = xyes \
      use_dns_srv=no
      use_dns_pka=no
      use_dns_cert=no
      use_dns_srv=no
      use_dns_pka=no
      use_dns_cert=no
+     # If we have no resolver library but ADNS (e.g. under W32) enable the
+     # code parts which can be used with ADNS.
+     if test x"$have_adns" = xyes ; then
+        DNSLIB="$ADNSLIBS"
+        AC_DEFINE(USE_ADNS,1,[Use ADNS as resolver library.])
+
+        if test x"$use_dns_srv" = xyes ; then
+           AC_DEFINE(USE_DNS_SRV,1)
+        fi
+
+        if test x"$use_dns_pka" = xyes ; then
+           AC_DEFINE(USE_DNS_PKA,1)
+        fi
+     fi
   fi
 
   LIBS=$_dns_save_libs
   fi
 
   LIBS=$_dns_save_libs
@@ -813,33 +857,6 @@ AM_CONDITIONAL(USE_DNS_SRV, test x"$use_dns_srv" = xyes)
 
 
 #
 
 
 #
-# Check for ADNS.
-#
-_cppflags="${CPPFLAGS}"
-_ldflags="${LDFLAGS}"
-AC_ARG_WITH(adns,
-            AC_HELP_STRING([--with-adns=DIR],
-                           [look for the adns library in DIR]),
-            [if test -d "$withval"; then
-               CPPFLAGS="${CPPFLAGS} -I$withval/include"
-               LDFLAGS="${LDFLAGS} -L$withval/lib"
-             fi])
-if test "$with_adns" != "no"; then
-  AC_CHECK_HEADERS(adns.h,
-                AC_CHECK_LIB(adns, adns_init,
-                             [have_adns=yes],
-                             [CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}]),
-                [CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}])
-fi
-if test "$have_adns" = "yes"; then
-  ADNSLIBS="-ladns" 
-fi
-AC_SUBST(ADNSLIBS)
-# Newer adns versions feature a free function to be used under W32.
-AC_CHECK_FUNCS(adns_free)
-
-
-#
 # Check for LDAP
 #
 if test "$try_ldap" = yes ; then
 # Check for LDAP
 #
 if test "$try_ldap" = yes ; then
index 8294079..89f9e86 100644 (file)
@@ -843,7 +843,7 @@ The format of this file is as follows:
         given but "default" is used the usage will be "sign".
      Subkey-Type: <algo-number>|<algo-string>
        This generates a secondary key.  Currently only one subkey
         given but "default" is used the usage will be "sign".
      Subkey-Type: <algo-number>|<algo-string>
        This generates a secondary key.  Currently only one subkey
-       can be handled.
+       can be handled.  "default" is also supported.
      Subkey-Length: <length-in-bits>
        Length of the subkey in bits.  The default is returned by running
         the command "gpg --gpgconf-list".
      Subkey-Length: <length-in-bits>
        Length of the subkey in bits.  The default is returned by running
         the command "gpg --gpgconf-list".
index eaa60bb..02e67f9 100644 (file)
@@ -1,3 +1,7 @@
+2009-12-07  Werner Koch  <wk@g10code.com>
+
+       * no-libgcrypt.c (gcry_strdup): Actually copy the string.
+
 2009-11-23  Werner Koch  <wk@g10code.com>
 
        * gpgconf-comp.c (gc_options_gpg): Add default_pubkey_algo.
 2009-11-23  Werner Koch  <wk@g10code.com>
 
        * gpgconf-comp.c (gc_options_gpg): Add default_pubkey_algo.
index 3428e57..4cfedcc 100644 (file)
@@ -55,7 +55,10 @@ gcry_xmalloc (size_t n)
 char *
 gcry_strdup (const char *string)
 {
 char *
 gcry_strdup (const char *string)
 {
-  return malloc (strlen (string)+1);
+  char *p = malloc (strlen (string)+1);
+  if (p)
+    strcpy (p, string);
+  return p;
 }
 
 
 }