gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnunet] 01/27: GNS: Implementation of SBOX records


From: gnunet
Subject: [gnunet] 01/27: GNS: Implementation of SBOX records
Date: Thu, 14 Dec 2023 19:22:55 +0100

This is an automated email from the git hooks/post-receive script.

sebi pushed a commit to branch master
in repository gnunet.

commit 065ac6e4a865adbf2faa2d1a834f9acfebeca8ad
Author: Sebastian Nadler <sebastian.nadler@tum.de>
AuthorDate: Tue Dec 5 17:37:52 2023 +0100

    GNS: Implementation of SBOX records
    
    Fix memory allocation and string handling issues in plugin_gnsrecord_gns.c 
and gnunet-service-gns_resolver.c
    
    GNS: sbox records
    
    Add SBox record
---
 contrib/gana                                  |   2 +-
 src/cli/gns/test_gns_sbox.sh                  |  40 ++++++++++
 src/include/gnu_name_system_record_types.h    |   6 ++
 src/include/gnunet_gnsrecord_lib.h            |  41 +++++++++--
 src/lib/util/gnunet_error_codes.c             |   1 -
 src/plugin/gns/plugin_gnsrecord_gns.c         | 101 ++++++++++++++++++++++++++
 src/service/gns/gnunet-service-gns_resolver.c |  87 +++++++++++++++++++---
 7 files changed, 257 insertions(+), 21 deletions(-)

diff --git a/contrib/gana b/contrib/gana
index 557051695..055954720 160000
--- a/contrib/gana
+++ b/contrib/gana
@@ -1 +1 @@
-Subproject commit 557051695c575b45fb1bfdbacbc69d67c6908425
+Subproject commit 055954720d88d80a98edb11abc232925b7d42758
diff --git a/src/cli/gns/test_gns_sbox.sh b/src/cli/gns/test_gns_sbox.sh
new file mode 100755
index 000000000..b00b813f7
--- /dev/null
+++ b/src/cli/gns/test_gns_sbox.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+# This file is in the public domain.
+trap "gnunet-arm -e -c test_gns_lookup.conf" INT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+       echo "GNUnet command line tools cannot be found, check environmental 
variables PATH and GNUNET_PREFIX"
+       exit 77
+fi
+
+rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME`
+which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 30"
+TEST_A="139.134.54.9"
+MY_EGO="myego"
+LABEL="testsbox"
+HASH="c93f1e400f26708f98cb19d936620da35eec8f72e57f9eec01c1afd6"
+SERVICE_TEXT="_tcp"
+gnunet-arm -s -c test_gns_lookup.conf
+gnunet-identity -C $MY_EGO -c test_gns_lookup.conf
+gnunet-namestore -p -z $MY_EGO -a -n $LABEL -t SBOX -V "$HASH.$SERVICE_TEXT 1 
$TEST_A" -e never -c test_gns_lookup.conf
+sleep 0.5
+RES_A=`$DO_TIMEOUT gnunet-gns --raw -u $HASH.$SERVICE_TEXT.$LABEL.$MY_EGO -t A 
-c test_gns_lookup.conf`
+gnunet-namestore -z $MY_EGO -d -n $LABEL -t SBOX -V "$HASH.$SERVICE_TEXT 1 
$TEST_A" -e never -c test_gns_lookup.conf
+gnunet-identity -D $MY_EGO -c test_gns_lookup.conf
+gnunet-arm -e -c test_gns_lookup.conf
+rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME`
+
+if [ "$RES_A" = "$TEST_A" ]
+then
+  exit 0
+else
+  echo "Failed to resolve to proper A, got '$RES_A'."
+  exit 1
+fi
diff --git a/src/include/gnu_name_system_record_types.h 
b/src/include/gnu_name_system_record_types.h
index 2cefce589..8ab9c09d5 100644
--- a/src/include/gnu_name_system_record_types.h
+++ b/src/include/gnu_name_system_record_types.h
@@ -97,6 +97,12 @@ extern "C" {
 #define GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET 65545
 
 
+/**
+ * SBox record
+ */
+#define GNUNET_GNSRECORD_TYPE_SBOX 65547
+
+
 /**
  * For ABD policies
  */
diff --git a/src/include/gnunet_gnsrecord_lib.h 
b/src/include/gnunet_gnsrecord_lib.h
index 813409340..b4e45727b 100644
--- a/src/include/gnunet_gnsrecord_lib.h
+++ b/src/include/gnunet_gnsrecord_lib.h
@@ -331,6 +331,31 @@ struct GNUNET_GNSRECORD_BoxRecord
   /* followed by the 'original' record */
 };
 
+
+/**
+ * Record type used to box up SMIMEA records.  For example, a
+ * SMIMEA record for "c93f1e400f26708f98cb19d936620da35eec8f72e57
+ * f9eec01c1afd6._smimecert.foo.gnu" will be stored under
+ * "foo.gnu" as a SBOX record with the local-path of the associated
+ * e-mails hash turnicated to 28 octets encoded as hex and protocol _smimecert
+ * and record_type "SMIMEA".  When a BOX record is received, GNS
+ * unboxes it if the name contained "hash._PROTO", otherwise GNS
+ * leaves it untouched.  This is done to ensure that SMIMEA
+ * records do not require a separate network request, thus making SMIMEA
+ * records inseparable from the "main" A/AAAA/VPN/etc. records.
+ */
+struct GNUNET_GNSRECORD_SBoxRecord
+{
+  /**
+   * GNS record type of the boxed record. In NBO.
+   */
+  uint32_t record_type GNUNET_PACKED;
+
+  /* followed by the zero terminated hostname prefix */
+  /* followed by the 'original' record */
+};
+
+
 /**
  * Record type used internally to keep track of reverse mappings into a
  * namespace.
@@ -836,9 +861,9 @@ GNUNET_GNSRECORD_label_check (const char*label, char 
**emsg);
 /**
  * Maximum length of a revocation
  */
-#define GNUNET_MAX_POW_SIZE sizeof(struct GNUNET_GNSRECORD_PowP) +\
-                                         sizeof(struct 
GNUNET_CRYPTO_PublicKey) +\
-                                         1024 //FIXME max sig_len
+#define GNUNET_MAX_POW_SIZE sizeof(struct GNUNET_GNSRECORD_PowP)  \
+  + sizeof(struct GNUNET_CRYPTO_PublicKey)  \
+  + 1024                                      // FIXME max sig_len
 
 /**
  * The proof-of-work narrowing factor.
@@ -910,8 +935,8 @@ struct GNUNET_GNSRECORD_PowCalculationHandle;
  */
 enum GNUNET_GenericReturnValue
 GNUNET_GNSRECORD_check_pow (const struct GNUNET_GNSRECORD_PowP *pow,
-                             unsigned int matching_bits,
-                             struct GNUNET_TIME_Relative epoch_duration);
+                            unsigned int matching_bits,
+                            struct GNUNET_TIME_Relative epoch_duration);
 
 
 /**
@@ -922,7 +947,7 @@ GNUNET_GNSRECORD_check_pow (const struct 
GNUNET_GNSRECORD_PowP *pow,
  */
 void
 GNUNET_GNSRECORD_pow_init (const struct GNUNET_CRYPTO_PrivateKey *key,
-                            struct GNUNET_GNSRECORD_PowP *pow);
+                           struct GNUNET_GNSRECORD_PowP *pow);
 
 
 /**
@@ -936,8 +961,8 @@ GNUNET_GNSRECORD_pow_init (const struct 
GNUNET_CRYPTO_PrivateKey *key,
  */
 struct GNUNET_GNSRECORD_PowCalculationHandle*
 GNUNET_GNSRECORD_pow_start (struct GNUNET_GNSRECORD_PowP *pow,
-                             int epochs,
-                             unsigned int difficulty);
+                            int epochs,
+                            unsigned int difficulty);
 
 
 /**
diff --git a/src/lib/util/gnunet_error_codes.c 
b/src/lib/util/gnunet_error_codes.c
index c286f2e52..11ce2d0c8 100644
--- a/src/lib/util/gnunet_error_codes.c
+++ b/src/lib/util/gnunet_error_codes.c
@@ -17,7 +17,6 @@
 
      SPDX-License-Identifier: AGPL3.0-or-later
  */
-#include "platform.h"
 #include "gnunet_error_codes.h"
 #include <stddef.h>
 #include <microhttpd.h>
diff --git a/src/plugin/gns/plugin_gnsrecord_gns.c 
b/src/plugin/gns/plugin_gnsrecord_gns.c
index 65587172d..2803d32a4 100644
--- a/src/plugin/gns/plugin_gnsrecord_gns.c
+++ b/src/plugin/gns/plugin_gnsrecord_gns.c
@@ -132,6 +132,36 @@ gns_value_to_string (void *cls,
       GNUNET_free (ival);
       return box_str;
     }
+  case GNUNET_GNSRECORD_TYPE_SBOX: {
+      struct GNUNET_GNSRECORD_SBoxRecord box;
+      uint32_t rt;
+      char *box_str;
+      char *ival;
+      char *prefix;
+
+      cdata = data;
+      if (data_size < sizeof(struct GNUNET_GNSRECORD_SBoxRecord))
+        return NULL; /* malformed */
+      GNUNET_memcpy (&box, data, sizeof(box));
+      rt = ntohl (box.record_type);
+
+      prefix = GNUNET_strdup (&cdata[sizeof(box)]);
+      ival = GNUNET_GNSRECORD_value_to_string (rt, &cdata[sizeof(box)
+                                                          + strlen (prefix)
+                                                          + 1],
+                                               data_size - sizeof(box)
+                                               - strlen (prefix) - 1);
+      if (NULL == ival)
+        return NULL; /* malformed */
+      GNUNET_asprintf (&box_str,
+                       "%s %u %s",
+                       prefix,
+                       (unsigned int) rt,
+                       ival);
+      GNUNET_free (prefix);
+      GNUNET_free (ival);
+      return box_str;
+    }
   case GNUNET_GNSRECORD_TYPE_TOMBSTONE: {
       return GNUNET_strdup (_ (
                               "This is a memento of an older block for 
internal maintenance."));
@@ -302,6 +332,76 @@ gns_string_to_value (void *cls,
       GNUNET_free (bval);
       return GNUNET_OK;
     }
+  case GNUNET_GNSRECORD_TYPE_SBOX: {
+      struct GNUNET_GNSRECORD_SBoxRecord *box;
+      size_t rest;
+      char *prefix;
+      unsigned int protocol;
+      unsigned int record_type;
+      void *bval;
+      size_t bval_size;
+      prefix = GNUNET_malloc (strlen (s)); // TODO The allocated memory is 
bigger than needed
+      size_t prefix_size;
+      if (2 != sscanf (s, "%s %u ", prefix, &record_type))
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    _ ("Unable to parse SBOX record string `%s'\n"),
+                    s);
+        return GNUNET_SYSERR;
+      }
+      if (prefix == NULL)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    _ (
+                      "Unable to parse SBOX record string `%s', no prefix 
found\n"),
+                    s);
+        return GNUNET_SYSERR;
+      }
+      char *last_underscore = strrchr (prefix, (int) '_');
+      if (last_underscore == NULL)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    _ (
+                      "Unable to parse SBOX record string `%s', no underscore 
fund\n"),
+                    prefix);
+        return GNUNET_SYSERR;
+      }
+      char *dot_in_last_prefix = strchr (last_underscore, '.');
+      if (dot_in_last_prefix != NULL)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    _ (
+                      "Unable to parse SBOX record string `%s', the last label 
does not have an underscore\n"),
+                    prefix);
+        return GNUNET_SYSERR;
+      }
+      if (prefix < last_underscore && last_underscore[-1] != '.')
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    _ (
+                      "Unable to parse SBOX record string `%s', the last label 
does not start with an underscore\n"),
+                    prefix);
+        return GNUNET_SYSERR;
+      }
+      rest = snprintf (NULL, 0, "%s %u ", prefix, record_type);
+      if (GNUNET_OK != GNUNET_GNSRECORD_string_to_value (record_type,
+                                                         &s[rest],
+                                                         &bval,
+                                                         &bval_size))
+        return GNUNET_SYSERR;
+      prefix_size = strlen (prefix) + 1; // with NULL terminator
+      *data_size = sizeof(struct GNUNET_GNSRECORD_SBoxRecord) + prefix_size
+                   + bval_size;
+      void *p = *data = box = GNUNET_malloc (*data_size);
+      box->record_type = htonl (record_type);
+      p += sizeof(struct GNUNET_GNSRECORD_SBoxRecord);
+      GNUNET_memcpy (p, prefix, prefix_size);
+      p += prefix_size;
+      GNUNET_memcpy (p, bval, bval_size);
+      GNUNET_free (bval);
+      GNUNET_free (prefix);
+      return GNUNET_OK;
+    }
   case GNUNET_GNSRECORD_TYPE_TOMBSTONE: {
       *data_size = 0;
       *data = NULL;
@@ -330,6 +430,7 @@ static struct
   { "VPN", GNUNET_GNSRECORD_TYPE_VPN },
   { "GNS2DNS", GNUNET_GNSRECORD_TYPE_GNS2DNS },
   { "BOX", GNUNET_GNSRECORD_TYPE_BOX },
+  { "SBOX", GNUNET_GNSRECORD_TYPE_SBOX },
   { "REDIRECT", GNUNET_GNSRECORD_TYPE_REDIRECT },
   /* Tombstones should never be added manually
                     * so this makes sense, kind of */
diff --git a/src/service/gns/gnunet-service-gns_resolver.c 
b/src/service/gns/gnunet-service-gns_resolver.c
index 445ae3346..85a72910a 100644
--- a/src/service/gns/gnunet-service-gns_resolver.c
+++ b/src/service/gns/gnunet-service-gns_resolver.c
@@ -368,6 +368,12 @@ struct GNS_ResolverHandle
    */
   int service;
 
+  /**
+   * For SMIMEA,OPENPGPKEY... records. NULL if no _ prefix was given.
+   */
+  char *prefix;
+
+
   /**
    * Desired type for the resolution.
    */
@@ -657,14 +663,13 @@ resolver_lookup_get_next_label (struct GNS_ResolverHandle 
*rh)
     rp = rh->name;
     rh->name_resolution_pos = 0;
   }
-  else if (('_' == dot[1]) &&
-           ('_' == rh->name[0]) &&
-           (dot == memchr (rh->name, (int) '.', rh->name_resolution_pos)))
+  else if ('_' == dot[1])
   {
     /**
      * Do not advance a label. This seems to be a name only consisting
-     * of a BOX indicator (_443,_tcp).
-     * Which means, it is a BOX under the empty label.
+     * of a prefix. Indicating a BOX record (_443,_tcp)
+     * Or some version of an SBOX record (HEX,_smimeacert)
+     * Which means, it is a BOX/SBOX under the empty label.
      * leaving name_resolution_pos as is and returning empty label.
      */
     rp = GNUNET_GNS_EMPTY_LABEL_AT;
@@ -679,8 +684,9 @@ resolver_lookup_get_next_label (struct GNS_ResolverHandle 
*rh)
   }
   rh->protocol = 0;
   rh->service = 0;
+  rh->prefix = NULL;
   ret = GNUNET_strndup (rp, len);
-  /* If we have labels starting with underscore with label on
+  /** If we have labels starting with underscore with label on
    * the right (SRV/DANE/BOX case), determine port/protocol;
    * The format of `rh->name` must be "_PORT._PROTOCOL".
    */
@@ -703,10 +709,12 @@ resolver_lookup_get_next_label (struct GNS_ResolverHandle 
*rh)
     if (0 == protocol)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  _ ("Protocol `%s' unknown, skipping labels.\n"),
+                  _ (
+                    "Protocol `%s' unknown, skipping labels as BOX retain as 
SBOX.\n"),
                   proto_name);
       GNUNET_free (proto_name);
       GNUNET_free (srv_name);
+      rh->prefix = GNUNET_strndup (rh->name, strlen (rh->name) - len - 1);
       return ret;
     }
     service = resolver_getservbyname (srv_name,
@@ -721,10 +729,12 @@ resolver_lookup_get_next_label (struct GNS_ResolverHandle 
*rh)
       if (1 != sscanf (srv_name, "%u", &rh->service))
       {
         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                    _ ("Service `%s' not a port, skipping service labels.\n"),
+                    _ (
+                      "Service `%s' not a port, skipping service labels as BOX 
retain as SBOX.\n"),
                     srv_name);
         GNUNET_free (proto_name);
         GNUNET_free (srv_name);
+        rh->prefix = GNUNET_strndup (rh->name, strlen (rh->name) - len - 1);
         return ret;
       }
     }
@@ -736,6 +746,20 @@ resolver_lookup_get_next_label (struct GNS_ResolverHandle 
*rh)
     GNUNET_free (proto_name);
     GNUNET_free (srv_name);
   }
+  /**
+  * If we have labels starting with underscore with label on
+  * the right, copy prefix to rh->prefix;
+  * The format of `rh->name` must be "*._label",
+  * where label is a string without '.'.
+  */
+  if ((NULL != (dot = memrchr (rh->name,
+                               (int) '.',
+                               rh->name_resolution_pos)) && '_' == dot[1]) ||
+      '_' == rh->name[0])
+  {
+    rh->name_resolution_pos = 0;
+    rh->prefix = GNUNET_strndup (rh->name, strlen (rh->name) - len - 1);
+  }
   return ret;
 }
 
@@ -2040,9 +2064,10 @@ handle_gns_resolution_result (void *cls,
     for (unsigned int i = 0; i < rd_count; i++)
     {
       GNUNET_assert (rd_off <= i);
-      if ((0 != rh->protocol) &&
-          (0 != rh->service) &&
-          (GNUNET_GNSRECORD_TYPE_BOX != rd[i].record_type))
+      if ((((0 != rh->protocol) &&
+            (0 != rh->service)) || (NULL != rh->prefix)) &&
+          (GNUNET_GNSRECORD_TYPE_BOX != rd[i].record_type &&
+           GNUNET_GNSRECORD_TYPE_SBOX != rd[i].record_type))
         if (GNUNET_GNSRECORD_TYPE_PKEY != rd[i].record_type &&
             GNUNET_GNSRECORD_TYPE_EDKEY != rd[i].record_type)
           continue;
@@ -2357,7 +2382,47 @@ handle_gns_resolution_result (void *cls,
           }
           break;
         }
+      case GNUNET_GNSRECORD_TYPE_SBOX:
+        {
+          /* unbox SMIMEA/OPENPGPKEY records if a specific one was requested */
+          if ((rh->prefix != NULL) &&
+              (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_SBoxRecord)))
+          {
+            const struct GNUNET_GNSRECORD_SBoxRecord *box;
 
+            box = rd[i].data;
+            char *prefix = GNUNET_strdup (&box[1]);
+            size_t prefix_len = strlen (prefix) + 1;
+            GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                        "Got SBOX record, checking if prefixes match... %s vs 
%s\n",
+                        prefix, rh->prefix);
+            if (strcmp (rh->prefix, prefix) == 0)
+            {
+              /* Box matches, unbox! */
+              GNUNET_assert (rd_off < rd_count);
+              rd_new[rd_off].record_type = ntohl (box->record_type);
+              rd_new[rd_off].data_size -= sizeof(struct
+                                                 GNUNET_GNSRECORD_SBoxRecord)
+                                          + prefix_len;
+              rd_new[rd_off].data = &rd[i].data[sizeof(struct
+                                                       
GNUNET_GNSRECORD_SBoxRecord)
+                                                + prefix_len];
+              rd_off++;
+            }
+            GNUNET_free (prefix);
+          }
+          else
+          {
+            GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                        _ (
+                          "GNS no specific protocol/service specified, 
preserve all SBOX `%s')\n"),
+                        rh->name);
+            /* no specific protocol/service specified, preserve all SBOX
+               records (for modern, GNS-enabled applications) */
+            rd_off++;
+          }
+          break;
+        }
       default:
         rd_off++;
         break;

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]