summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2021-11-21 00:53:11 +0100
committerChristian Grothoff <christian@grothoff.org>2021-11-21 00:53:11 +0100
commitae2ce4aaeed35fd077cac016795f069b35189756 (patch)
tree8aac04ba02cc1055f71ff0b2392c6eaec2ed39dc
parenta5a3b2ea9ab6fa47d06531b34599237b62742443 (diff)
downloadexchange-ae2ce4aaeed35fd077cac016795f069b35189756.tar.gz
exchange-ae2ce4aaeed35fd077cac016795f069b35189756.tar.bz2
exchange-ae2ce4aaeed35fd077cac016795f069b35189756.zip
trying to fix #7039 insanity for RFC 8785, Dold: please check
-rw-r--r--src/benchmark/taler-bank-benchmark.c1
-rw-r--r--src/json/Makefile.am1
-rw-r--r--src/json/json.c158
-rw-r--r--src/json/test_json.c36
4 files changed, 195 insertions, 1 deletions
diff --git a/src/benchmark/taler-bank-benchmark.c b/src/benchmark/taler-bank-benchmark.c
index b7bcc105c..4d7dbe35e 100644
--- a/src/benchmark/taler-bank-benchmark.c
+++ b/src/benchmark/taler-bank-benchmark.c
@@ -411,6 +411,7 @@ stop_fakebank (void *cls)
static void
never_task (void *cls)
{
+ (void) cls;
GNUNET_assert (0);
}
diff --git a/src/json/Makefile.am b/src/json/Makefile.am
index d3e4339fe..2f5ec3f17 100644
--- a/src/json/Makefile.am
+++ b/src/json/Makefile.am
@@ -22,6 +22,7 @@ libtalerjson_la_LIBADD = \
$(top_builddir)/src/util/libtalerutil.la \
-lgnunetjson \
-lgnunetutil \
+ -lunistring \
-ljansson \
-lm \
$(XLIB)
diff --git a/src/json/json.c b/src/json/json.c
index 479a0ae96..af2b84e27 100644
--- a/src/json/json.c
+++ b/src/json/json.c
@@ -23,6 +23,7 @@
#include <gnunet/gnunet_util_lib.h>
#include "taler_util.h"
#include "taler_json_lib.h"
+#include <unistr.h>
/**
@@ -61,6 +62,161 @@ contains_real (const json_t *json)
/**
+ * Dump character in the low range into @a buf
+ * following RFC 8785.
+ *
+ * @param[in,out] buf buffer to modify
+ * @param val value to dump
+ */
+static void
+lowdump (struct GNUNET_Buffer *buf,
+ unsigned char val)
+{
+ char scratch[7];
+
+ switch (val)
+ {
+ case 0x8:
+ GNUNET_buffer_write (buf,
+ "\b",
+ 2);
+ break;
+ case 0x9:
+ GNUNET_buffer_write (buf,
+ "\t",
+ 2);
+ break;
+ case 0xA:
+ GNUNET_buffer_write (buf,
+ "\n",
+ 2);
+ break;
+ case 0xC:
+ GNUNET_buffer_write (buf,
+ "\f",
+ 2);
+ break;
+ case 0xD:
+ GNUNET_buffer_write (buf,
+ "\r",
+ 2);
+ break;
+ default:
+ GNUNET_snprintf (scratch,
+ sizeof (scratch),
+ "\\u%04x",
+ (unsigned int) val);
+ GNUNET_buffer_write (buf,
+ scratch,
+ 6);
+ break;
+ }
+}
+
+
+/**
+ * Re-encode string at @a inp to match RFC 8785 (section 3.2.2.2).
+ *
+ * @param[in,out] inp pointer to string to re-encode
+ * @return number of bytes in resulting @a inp
+ */
+static size_t
+rfc8785encode (char **inp)
+{
+ struct GNUNET_Buffer buf = { 0 };
+ size_t left = strlen (*inp) + 1;
+ size_t olen;
+ char *in = *inp;
+ const char *pos = in;
+
+ GNUNET_buffer_prealloc (&buf,
+ left + 40);
+ buf.warn_grow = 0; /* disable, + 40 is just a wild guess */
+ while (1)
+ {
+ int mbl = u8_mblen ((unsigned char *) pos,
+ left);
+ unsigned char val;
+
+ if (0 == mbl)
+ break;
+ val = (unsigned char) *pos;
+ if ( (1 == mbl) &&
+ (val <= 0x1F) )
+ {
+ lowdump (&buf,
+ val);
+ }
+ else if ( (1 == mbl) && ('\\' == *pos) )
+ {
+ switch (*(pos + 1))
+ {
+ case '\\':
+ mbl = 2;
+ GNUNET_buffer_write (&buf,
+ pos,
+ mbl);
+ break;
+ case 'u':
+ {
+ unsigned int num;
+ uint32_t n32;
+ unsigned char res[8];
+ size_t rlen;
+
+ GNUNET_assert ( (1 ==
+ sscanf (pos + 2,
+ "%4x",
+ &num)) ||
+ (1 ==
+ sscanf (pos + 2,
+ "%4X",
+ &num)) );
+ mbl = 6;
+ n32 = (uint32_t) num;
+ rlen = sizeof (res);
+ u32_to_u8 (&n32,
+ 1,
+ res,
+ &rlen);
+ if ( (1 == rlen) &&
+ (res[0] <= 0x1F) )
+ {
+ lowdump (&buf,
+ res[0]);
+ }
+ else
+ {
+ GNUNET_buffer_write (&buf,
+ (const char *) res,
+ rlen);
+ }
+ }
+ break;
+ }
+ }
+ else
+ {
+ GNUNET_buffer_write (&buf,
+ pos,
+ mbl);
+ }
+ left -= mbl;
+ pos += mbl;
+ }
+
+ /* 0-terminate buffer */
+ GNUNET_buffer_write (&buf,
+ "",
+ 1);
+ GNUNET_free (in);
+ *inp = GNUNET_buffer_reap (&buf,
+ &olen);
+ return olen;
+}
+
+
+/**
* Dump the @a json to a string and hash it.
*
* @param json value to hash
@@ -97,7 +253,7 @@ dump_and_hash (const json_t *json,
GNUNET_break (0);
return GNUNET_SYSERR;
}
- len = strlen (wire_enc) + 1;
+ len = rfc8785encode (&wire_enc);
if (NULL == salt)
{
GNUNET_CRYPTO_hash (wire_enc,
diff --git a/src/json/test_json.c b/src/json/test_json.c
index ffc5b33c7..a8c1c6d8e 100644
--- a/src/json/test_json.c
+++ b/src/json/test_json.c
@@ -330,6 +330,40 @@ test_contract (void)
}
+static int
+test_rfc8785 (void)
+{
+ struct TALER_PrivateContractHash h1;
+ json_t *c1;
+
+ c1 = json_pack ("{s:s}",
+ "k1", "\x08\x0B\t\1\\\x0d");
+ GNUNET_assert (GNUNET_OK ==
+ TALER_JSON_contract_hash (c1,
+ &h1));
+ {
+ char *s;
+
+ s = GNUNET_STRINGS_data_to_string_alloc (&h1,
+ sizeof (h1));
+ if (0 !=
+ strcmp (s,
+ "J678K3PW9Y3DG63Z3T7ZYR2P7CEXMVZ2SFPQMABACK9TJRYREPP82542PCJ0P7Y7FAQAMWECDX50XH1RBTWHX6SSJHH6FXRV0JCS6R8"))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Invalid reference hash: %s\n",
+ s);
+ GNUNET_free (s);
+ json_decref (c1);
+ return 1;
+ }
+ GNUNET_free (s);
+ }
+ json_decref (c1);
+ return 0;
+}
+
+
int
main (int argc,
const char *const argv[])
@@ -343,6 +377,8 @@ main (int argc,
return 1;
if (0 != test_contract ())
return 2;
+ if (0 != test_rfc8785 ())
+ return 2;
return 0;
}