summaryrefslogtreecommitdiff
path: root/src/json
diff options
context:
space:
mode:
Diffstat (limited to 'src/json')
-rw-r--r--src/json/json.c98
-rw-r--r--src/json/test_json.c69
2 files changed, 163 insertions, 4 deletions
diff --git a/src/json/json.c b/src/json/json.c
index e9fbb91f8..4b91c0c52 100644
--- a/src/json/json.c
+++ b/src/json/json.c
@@ -17,6 +17,7 @@
* @file json/json.c
* @brief helper functions for JSON processing using libjansson
* @author Sree Harsha Totakura <sreeharsha@totakura.in>
+ * @author Christian Grothoff
*/
#include "platform.h"
#include <gnunet/gnunet_util_lib.h>
@@ -25,6 +26,41 @@
/**
+ * Check if @a json contains a 'real' value anywhere.
+ *
+ * @param json json to check
+ * @return true if a real is in it somewhere
+ */
+static bool
+contains_real (const json_t *json)
+{
+ if (json_is_real (json))
+ return true;
+ if (json_is_object (json))
+ {
+ json_t *member;
+ const char *name;
+
+ json_object_foreach ((json_t *) json, name, member)
+ if (contains_real (member))
+ return true;
+ return false;
+ }
+ if (json_is_array (json))
+ {
+ json_t *member;
+ size_t index;
+
+ json_array_foreach ((json_t *) json, index, member)
+ if (contains_real (member))
+ return true;
+ return false;
+ }
+ return false;
+}
+
+
+/**
* Dump the @a json to a string and hash it.
*
* @param json value to hash
@@ -41,7 +77,16 @@ dump_and_hash (const json_t *json,
char *wire_enc;
size_t len;
- GNUNET_break (NULL != json);
+ if (NULL == json)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ if (contains_real (json))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
if (NULL == (wire_enc = json_dumps (json,
JSON_ENCODE_ANY
| JSON_COMPACT
@@ -79,7 +124,7 @@ dump_and_hash (const json_t *json,
/**
- * Replace "forgettable" parts of a JSON object with its salted hash.
+ * Replace "forgettable" parts of a JSON object with their salted hash.
*
* @param[in] in some JSON value
* @return NULL on error
@@ -87,6 +132,12 @@ dump_and_hash (const json_t *json,
static json_t *
forget (const json_t *in)
{
+ if (json_is_real (in))
+ {
+ /* floating point is not allowed! */
+ GNUNET_break (0);
+ return NULL;
+ }
if (json_is_array (in))
{
/* array is a JSON array */
@@ -202,6 +253,16 @@ forget (const json_t *in)
return NULL;
}
json_decref (t);
+ /* scrub salt */
+ if (0 !=
+ json_object_del (fg,
+ key))
+ {
+ GNUNET_break (0);
+ json_decref (ret);
+ json_decref (rx);
+ return NULL;
+ }
if (NULL == rx)
rx = json_object ();
if (NULL == rx)
@@ -268,8 +329,11 @@ TALER_JSON_contract_hash (const json_t *json,
{
int ret;
json_t *cjson;
+ json_t *dc;
- cjson = forget (json);
+ dc = json_deep_copy (json);
+ cjson = forget (dc);
+ json_decref (dc);
if (NULL == cjson)
{
GNUNET_break (0);
@@ -295,9 +359,26 @@ TALER_JSON_contract_mark_forgettable (json_t *json,
GNUNET_break (0);
return GNUNET_SYSERR;
}
+ /* check field name is legal for forgettable field */
+ for (const char *f = field; '\0' != *f; f++)
+ {
+ char c = *f;
+
+ if ( (c >= 'a') && (c <= 'z') )
+ continue;
+ if ( (c >= 'A') && (c <= 'Z') )
+ continue;
+ if ( (c >= '0') && (c <= '9') )
+ continue;
+ if ('_' == c)
+ continue;
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
if (NULL == json_object_get (json,
field))
{
+ /* field must exist */
GNUNET_break (0);
return GNUNET_SYSERR;
}
@@ -335,7 +416,7 @@ int
TALER_JSON_contract_part_forget (json_t *json,
const char *field)
{
- const json_t *fg;
+ json_t *fg;
const json_t *part;
json_t *fp;
json_t *rx;
@@ -391,6 +472,15 @@ TALER_JSON_contract_part_forget (json_t *json,
return GNUNET_SYSERR;
}
json_decref (fp);
+ /* drop salt */
+ if (0 !=
+ json_object_del (fg,
+ field))
+ {
+ json_decref (fp);
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
rx = json_object_get (json,
"_forgotten");
diff --git a/src/json/test_json.c b/src/json/test_json.c
index 066ba4e73..21073d697 100644
--- a/src/json/test_json.c
+++ b/src/json/test_json.c
@@ -105,11 +105,48 @@ test_contract (void)
TALER_JSON_contract_mark_forgettable (c1,
"k1"));
GNUNET_assert (GNUNET_OK ==
+ TALER_JSON_contract_mark_forgettable (c1,
+ "k2"));
+ GNUNET_assert (GNUNET_OK ==
TALER_JSON_contract_hash (c1,
&h1));
GNUNET_assert (GNUNET_OK ==
TALER_JSON_contract_part_forget (c1,
"k1"));
+ /* check salt was forgotten */
+ GNUNET_assert (NULL ==
+ json_object_get (json_object_get (c1,
+ "_forgettable"),
+ "k1"));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_JSON_contract_hash (c1,
+ &h2));
+ if (0 !=
+ GNUNET_memcmp (&h1,
+ &h2))
+ {
+ GNUNET_break (0);
+ json_decref (c1);
+ return 1;
+ }
+ GNUNET_assert (GNUNET_OK ==
+ TALER_JSON_contract_part_forget (json_object_get (c1,
+ "k2"),
+ "n1"));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_JSON_contract_hash (c1,
+ &h2));
+ if (0 !=
+ GNUNET_memcmp (&h1,
+ &h2))
+ {
+ GNUNET_break (0);
+ json_decref (c1);
+ return 1;
+ }
+ GNUNET_assert (GNUNET_OK ==
+ TALER_JSON_contract_part_forget (c1,
+ "k2"));
GNUNET_assert (GNUNET_OK ==
TALER_JSON_contract_hash (c1,
&h2));
@@ -121,6 +158,38 @@ test_contract (void)
GNUNET_break (0);
return 1;
}
+
+
+ c1 = json_pack ("{s:I, s:{s:s}, s:{s:b, s:{s:s}}, s:{s:s}}",
+ "k1", 1,
+ "_forgettable", "k1", "SALT",
+ "k2", "n1", true,
+ /***/ "_forgettable", "n1", "salt",
+ "k3", "n1", "string");
+ GNUNET_assert (GNUNET_OK ==
+ TALER_JSON_contract_hash (c1,
+ &h1));
+ json_dumpf (c1, stderr, JSON_INDENT (2));
+ json_decref (c1);
+ {
+ char *s;
+
+ s = GNUNET_STRINGS_data_to_string_alloc (&h1,
+ sizeof (h1));
+ if (0 !=
+ strcmp (s,
+ "287VXK8T6PXKD05W8Y94QJNEFCMRXBC9S7KNKTWGH2G2J2D7RYKPSHNH1HG9NT1K2HRHGC67W6QM6GEC4BSN1DPNEBCS0AVDT2DBP5G"))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Invalid reference hash: %s\n",
+ s);
+ GNUNET_free (s);
+ return 1;
+ }
+ GNUNET_free (s);
+ }
+
+
c2 = json_pack ("{s:s}",
"n1", "n2");
GNUNET_assert (NULL != c2);