aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2015-01-29 15:45:05 +0100
committerChristian Grothoff <christian@grothoff.org>2015-01-29 15:45:05 +0100
commit4a27969e5e439fb0f277dcf9f0461817d83e36b4 (patch)
tree9dbcea3e7bb5723438a1817a9a8c840f55ce92f2
parenta284561298af60ade27eb18008f29ebf63ac62b7 (diff)
make TALER_MINT_parse_json_data more expressive, add RSA types as well
-rw-r--r--src/mint/taler-mint-httpd_deposit.c29
-rw-r--r--src/mint/taler-mint-httpd_parsing.c643
-rw-r--r--src/mint/taler-mint-httpd_parsing.h37
-rw-r--r--src/mint/taler-mint-httpd_refresh.c183
4 files changed, 528 insertions, 364 deletions
diff --git a/src/mint/taler-mint-httpd_deposit.c b/src/mint/taler-mint-httpd_deposit.c
index ec75c3ec0..78d424b80 100644
--- a/src/mint/taler-mint-httpd_deposit.c
+++ b/src/mint/taler-mint-httpd_deposit.c
@@ -127,8 +127,8 @@ parse_and_handle_deposit_request (struct MHD_Connection *connection,
char *wire_enc;
size_t len;
struct GNUNET_MINT_ParseFieldSpec spec[] = {
- TALER_MINT_PARSE_VARIABLE ("denom_pub"),
- TALER_MINT_PARSE_VARIABLE ("ubsig"),
+ TALER_MINT_PARSE_RSA_PUBLIC_KEY ("denom_pub", &deposit.coin.denom_pub),
+ TALER_MINT_PARSE_RSA_SIGNATURE ("ubsig", &deposit.coin.denom_sig),
TALER_MINT_PARSE_FIXED ("coin_pub", &deposit.coin.coin_pub),
TALER_MINT_PARSE_FIXED ("merchant_pub", &deposit.merchant_pub),
TALER_MINT_PARSE_FIXED ("H_a", &deposit.h_contract),
@@ -146,32 +146,9 @@ parse_and_handle_deposit_request (struct MHD_Connection *connection,
return MHD_NO; /* hard failure */
if (GNUNET_NO == res)
return MHD_YES; /* failure */
- deposit.coin.denom_pub
- = GNUNET_CRYPTO_rsa_public_key_decode (spec[0].destination,
- spec[0].destination_size_out);
- if (NULL == deposit.coin.denom_pub)
- {
- LOG_WARNING ("Failed to parse denomination key for /deposit request\n");
- TALER_MINT_release_parsed_data (spec);
- return TALER_MINT_reply_arg_invalid (connection,
- "denom_pub");
- }
- deposit.coin.denom_sig
- = GNUNET_CRYPTO_rsa_signature_decode (spec[1].destination,
- spec[1].destination_size_out);
- if (NULL == deposit.coin.denom_sig)
- {
- LOG_WARNING ("Failed to parse unblinded signature for /deposit request\n");
- GNUNET_CRYPTO_rsa_public_key_free (deposit.coin.denom_pub);
- TALER_MINT_release_parsed_data (spec);
- return TALER_MINT_reply_arg_invalid (connection,
- "denom_pub");
- }
/* FIXME: check that "wire" is formatted correctly */
if (NULL == (wire_enc = json_dumps (wire, JSON_COMPACT | JSON_SORT_KEYS)))
{
- GNUNET_CRYPTO_rsa_public_key_free (deposit.coin.denom_pub);
- GNUNET_CRYPTO_rsa_signature_free (deposit.coin.denom_sig);
LOG_WARNING ("Failed to parse JSON wire format specification for /deposit request\n");
TALER_MINT_release_parsed_data (spec);
return TALER_MINT_reply_arg_invalid (connection,
@@ -187,8 +164,6 @@ parse_and_handle_deposit_request (struct MHD_Connection *connection,
deposit.amount = *amount;
res = verify_and_execute_deposit (connection,
&deposit);
- GNUNET_CRYPTO_rsa_public_key_free (deposit.coin.denom_pub);
- GNUNET_CRYPTO_rsa_signature_free (deposit.coin.denom_sig);
TALER_MINT_release_parsed_data (spec);
return res;
}
diff --git a/src/mint/taler-mint-httpd_parsing.c b/src/mint/taler-mint-httpd_parsing.c
index 165654193..9c732ce6e 100644
--- a/src/mint/taler-mint-httpd_parsing.c
+++ b/src/mint/taler-mint-httpd_parsing.c
@@ -261,6 +261,106 @@ TALER_MINT_parse_post_cleanup_callback (void *con_cls)
/**
+ * Extract base32crockford encoded data from request.
+ *
+ * Queues an error response to the connection if the parameter is missing or
+ * invalid.
+ *
+ * @param connection the MHD connection
+ * @param param_name the name of the parameter with the key
+ * @param[out] out_data pointer to store the result
+ * @param out_size expected size of data
+ * @return
+ * #GNUNET_YES if the the argument is present
+ * #GNUNET_NO if the argument is absent or malformed
+ * #GNUNET_SYSERR on internal error (error response could not be sent)
+ */
+int
+TALER_MINT_mhd_request_arg_data (struct MHD_Connection *connection,
+ const char *param_name,
+ void *out_data,
+ size_t out_size)
+{
+ const char *str;
+
+ str = MHD_lookup_connection_value (connection,
+ MHD_GET_ARGUMENT_KIND,
+ param_name);
+ if (NULL == str)
+ {
+ return (MHD_NO ==
+ TALER_MINT_reply_arg_missing (connection, param_name))
+ ? GNUNET_SYSERR : GNUNET_NO;
+ }
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (str,
+ strlen (str),
+ out_data,
+ out_size))
+ return (MHD_NO ==
+ TALER_MINT_reply_arg_invalid (connection, param_name))
+ ? GNUNET_SYSERR : GNUNET_NO;
+ return GNUNET_OK;
+}
+
+
+/**
+ * Extraxt variable-size base32crockford encoded data from request.
+ *
+ * Queues an error response to the connection if the parameter is missing
+ * or the encoding is invalid.
+ *
+ * @param connection the MHD connection
+ * @param param_name the name of the parameter with the key
+ * @param[out] out_data pointer to allocate buffer and store the result
+ * @param[out] out_size set to the size of the buffer allocated in @a out_data
+ * @return
+ * #GNUNET_YES if the the argument is present
+ * #GNUNET_NO if the argument is absent or malformed
+ * #GNUNET_SYSERR on internal error (error response could not be sent)
+ */
+int
+TALER_MINT_mhd_request_var_arg_data (struct MHD_Connection *connection,
+ const char *param_name,
+ void **out_data,
+ size_t *out_size)
+{
+ const char *str;
+ size_t slen;
+ size_t olen;
+ void *out;
+
+ str = MHD_lookup_connection_value (connection,
+ MHD_GET_ARGUMENT_KIND,
+ param_name);
+ if (NULL == str)
+ {
+ return (MHD_NO ==
+ TALER_MINT_reply_arg_missing (connection, param_name))
+ ? GNUNET_SYSERR : GNUNET_NO;
+ }
+ slen = strlen (str);
+ olen = (slen * 5) / 8;
+ out = GNUNET_malloc (olen);
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (str,
+ strlen (str),
+ out,
+ olen))
+ {
+ GNUNET_free (out);
+ *out_size = 0;
+ return (MHD_NO ==
+ TALER_MINT_reply_arg_invalid (connection, param_name))
+ ? GNUNET_SYSERR : GNUNET_NO;
+ }
+ *out_data = out;
+ *out_size = olen;
+ return GNUNET_OK;
+}
+
+
+/**
* Navigate through a JSON tree.
*
* Sends an error response if navigation is impossible (i.e.
@@ -295,165 +395,298 @@ GNUNET_MINT_parse_navigate_json (struct MHD_Connection *connection,
switch (command)
{
- case JNAV_FIELD:
+ case JNAV_FIELD:
+ {
+ const char *fname = va_arg(argp, const char *);
+
+ json_array_append_new (path,
+ json_string (fname));
+ root = json_object_get (root,
+ fname);
+ if (NULL == root)
{
- const char *fname = va_arg(argp, const char *);
+ ret = (MHD_YES ==
+ TALER_MINT_reply_json_pack (connection,
+ MHD_HTTP_BAD_REQUEST,
+ "{s:s, s:s, s:o}",
+ "error",
+ "missing field in JSON",
+ "field",
+ fname,
+ "path",
+ path))
+ ? GNUNET_NO : GNUNET_SYSERR;
+ break;
+ }
+ }
+ break;
- json_array_append_new (path,
- json_string (fname));
- root = json_object_get (root,
- fname);
- if (NULL == root)
- {
- ret = (MHD_YES ==
- TALER_MINT_reply_json_pack (connection,
- MHD_HTTP_BAD_REQUEST,
- "{s:s, s:s, s:o}",
- "error",
- "missing field in JSON",
- "field",
- fname,
- "path",
- path))
- ? GNUNET_NO : GNUNET_SYSERR;
- break;
- }
+ case JNAV_INDEX:
+ {
+ int fnum = va_arg(argp, int);
+
+ json_array_append_new (path,
+ json_integer (fnum));
+ root = json_array_get (root,
+ fnum);
+ if (NULL == root)
+ {
+ ret = (MHD_YES ==
+ TALER_MINT_reply_json_pack (connection,
+ MHD_HTTP_BAD_REQUEST,
+ "{s:s, s:o}",
+ "error",
+ "missing index in JSON",
+ "path", path))
+ ? GNUNET_NO : GNUNET_SYSERR;
+ break;
}
- break;
- case JNAV_INDEX:
+ }
+ break;
+
+ case JNAV_RET_DATA:
+ {
+ void *where = va_arg (argp, void *);
+ size_t len = va_arg (argp, size_t);
+ const char *str;
+ int res;
+
+ // FIXME: avoidable code duplication here...
+ str = json_string_value (root);
+ if (NULL == str)
+ {
+ ret = (MHD_YES ==
+ TALER_MINT_reply_json_pack (connection,
+ MHD_HTTP_BAD_REQUEST,
+ "{s:s, s:o}",
+ "error",
+ "string expected",
+ "path",
+ path))
+ ? GNUNET_NO : GNUNET_SYSERR;
+ break;
+ }
+ res = GNUNET_STRINGS_string_to_data (str, strlen (str),
+ where, len);
+ if (GNUNET_OK != res)
{
- int fnum = va_arg(argp, int);
+ ret = (MHD_YES ==
+ TALER_MINT_reply_json_pack (connection,
+ MHD_HTTP_BAD_REQUEST,
+ "{s:s, s:o}",
+ "error",
+ "malformed binary data in JSON",
+ "path",
+ path))
+ ? GNUNET_NO : GNUNET_SYSERR;
+ break;
+ }
+ ret = GNUNET_OK;
+ }
+ break;
- json_array_append_new (path,
- json_integer (fnum));
- root = json_array_get (root,
- fnum);
- if (NULL == root)
- {
- ret = (MHD_YES ==
- TALER_MINT_reply_json_pack (connection,
- MHD_HTTP_BAD_REQUEST,
- "{s:s, s:o}",
- "error",
- "missing index in JSON",
- "path", path))
- ? GNUNET_NO : GNUNET_SYSERR;
- break;
- }
+ case JNAV_RET_DATA_VAR:
+ {
+ void **where = va_arg (argp, void **);
+ size_t *len = va_arg (argp, size_t *);
+ const char *str;
+
+ // FIXME: avoidable code duplication here...
+ str = json_string_value (root);
+ if (NULL == str)
+ {
+ ret = (MHD_YES ==
+ TALER_MINT_reply_internal_error (connection,
+ "json_string_value() failed"))
+ ? GNUNET_NO : GNUNET_SYSERR;
+ break;
}
- break;
- case JNAV_RET_DATA:
+ *len = (strlen (str) * 5) / 8;
+ if (NULL != where)
{
- void *where = va_arg (argp, void *);
- size_t len = va_arg (argp, size_t);
- const char *str;
int res;
- str = json_string_value (root);
- if (NULL == str)
- {
- ret = (MHD_YES ==
- TALER_MINT_reply_json_pack (connection,
- MHD_HTTP_BAD_REQUEST,
- "{s:s, s:o}",
- "error",
- "string expected",
- "path",
- path))
- ? GNUNET_NO : GNUNET_SYSERR;
- break;
- }
- res = GNUNET_STRINGS_string_to_data (str, strlen (str),
- where, len);
+ *where = GNUNET_malloc (*len);
+ res = GNUNET_STRINGS_string_to_data (str,
+ strlen (str),
+ *where,
+ *len);
if (GNUNET_OK != res)
{
+ GNUNET_free (*where);
+ *where = NULL;
+ *len = 0;
ret = (MHD_YES ==
TALER_MINT_reply_json_pack (connection,
MHD_HTTP_BAD_REQUEST,
"{s:s, s:o}",
"error",
"malformed binary data in JSON",
- "path",
- path))
+ "path", path))
? GNUNET_NO : GNUNET_SYSERR;
break;
}
- ret = GNUNET_OK;
}
- break;
- case JNAV_RET_DATA_VAR:
+ ret = GNUNET_OK;
+ }
+ break;
+
+ case JNAV_RET_TYPED_JSON:
+ {
+ int typ = va_arg (argp, int);
+ const json_t **r_json = va_arg (argp, const json_t **);
+
+ if ( (-1 != typ) && (json_typeof (root) != typ))
{
- void **where = va_arg (argp, void **);
- size_t *len = va_arg (argp, size_t *);
- const char *str;
+ ret = (MHD_YES ==
+ TALER_MINT_reply_json_pack (connection,
+ MHD_HTTP_BAD_REQUEST,
+ "{s:s, s:i, s:i, s:o}",
+ "error", "wrong JSON field type",
+ "type_expected", typ,
+ "type_actual", json_typeof (root),
+ "path", path))
+ ? GNUNET_NO : GNUNET_SYSERR;
+ break;
+ }
+ *r_json = root;
+ ret = GNUNET_OK;
+ }
+ break;
- str = json_string_value (root);
- if (NULL == str)
- {
- ret = (MHD_YES ==
- TALER_MINT_reply_internal_error (connection,
- "json_string_value() failed"))
- ? GNUNET_NO : GNUNET_SYSERR;
- break;
- }
- *len = (strlen (str) * 5) / 8;
- if (NULL != where)
- {
- int res;
-
- *where = GNUNET_malloc (*len);
- res = GNUNET_STRINGS_string_to_data (str,
- strlen (str),
- *where,
- *len);
- if (GNUNET_OK != res)
- {
- GNUNET_free (*where);
- *where = NULL;
- *len = 0;
- ret = (MHD_YES ==
- TALER_MINT_reply_json_pack (connection,
- MHD_HTTP_BAD_REQUEST,
- "{s:s, s:o}",
- "error",
- "malformed binary data in JSON",
- "path", path))
- ? GNUNET_NO : GNUNET_SYSERR;
- break;
- }
- }
- ret = GNUNET_OK;
+ case JNAV_RET_RSA_PUBLIC_KEY:
+ {
+ void **where = va_arg (argp, void **);
+ size_t len;
+ const char *str;
+ int res;
+ void *buf;
+
+ // FIXME: avoidable code duplication here...
+ str = json_string_value (root);
+ if (NULL == str)
+ {
+ ret = (MHD_YES ==
+ TALER_MINT_reply_json_pack (connection,
+ MHD_HTTP_BAD_REQUEST,
+ "{s:s, s:o}",
+ "error",
+ "string expected",
+ "path",
+ path))
+ ? GNUNET_NO : GNUNET_SYSERR;
+ break;
}
- break;
- case JNAV_RET_TYPED_JSON:
+ len = (strlen (str) * 5) / 8;
+ buf = GNUNET_malloc (len);
+ res = GNUNET_STRINGS_string_to_data (str,
+ strlen (str),
+ buf,
+ len);
+ if (GNUNET_OK != res)
{
- int typ = va_arg (argp, int);
- const json_t **r_json = va_arg (argp, const json_t **);
-
- if ( (-1 != typ) && (json_typeof (root) != typ))
- {
- ret = (MHD_YES ==
- TALER_MINT_reply_json_pack (connection,
- MHD_HTTP_BAD_REQUEST,
- "{s:s, s:i, s:i, s:o}",
- "error", "wrong JSON field type",
- "type_expected", typ,
- "type_actual", json_typeof (root),
- "path", path))
- ? GNUNET_NO : GNUNET_SYSERR;
- break;
- }
- *r_json = root;
- ret = GNUNET_OK;
+ GNUNET_free (buf);
+ ret = (MHD_YES ==
+ TALER_MINT_reply_json_pack (connection,
+ MHD_HTTP_BAD_REQUEST,
+ "{s:s, s:o}",
+ "error",
+ "malformed binary data in JSON",
+ "path",
+ path))
+ ? GNUNET_NO : GNUNET_SYSERR;
+ break;
}
+ *where = GNUNET_CRYPTO_rsa_public_key_decode (buf,
+ len);
+ GNUNET_free (buf);
+ if (NULL == *where)
+ {
+ ret = (MHD_YES ==
+ TALER_MINT_reply_json_pack (connection,
+ MHD_HTTP_BAD_REQUEST,
+ "{s:s, s:o}",
+ "error",
+ "malformed RSA public key in JSON",
+ "path",
+ path))
+ ? GNUNET_NO : GNUNET_SYSERR;
+ break;
+ }
+ ret = GNUNET_OK;
break;
- default:
- GNUNET_break (0);
- ret = (MHD_YES ==
- TALER_MINT_reply_internal_error (connection,
- "unhandled value in switch"))
- ? GNUNET_NO : GNUNET_SYSERR;
+ }
+
+ case JNAV_RET_RSA_SIGNATURE:
+ {
+ void **where = va_arg (argp, void **);
+ size_t len;
+ const char *str;
+ int res;
+ void *buf;
+
+ // FIXME: avoidable code duplication here...
+ str = json_string_value (root);
+ if (NULL == str)
+ {
+ ret = (MHD_YES ==
+ TALER_MINT_reply_json_pack (connection,
+ MHD_HTTP_BAD_REQUEST,
+ "{s:s, s:o}",
+ "error",
+ "string expected",
+ "path",
+ path))
+ ? GNUNET_NO : GNUNET_SYSERR;
+ break;
+ }
+ len = (strlen (str) * 5) / 8;
+ buf = GNUNET_malloc (len);
+ res = GNUNET_STRINGS_string_to_data (str,
+ strlen (str),
+ buf,
+ len);
+ if (GNUNET_OK != res)
+ {
+ GNUNET_free (buf);
+ ret = (MHD_YES ==
+ TALER_MINT_reply_json_pack (connection,
+ MHD_HTTP_BAD_REQUEST,
+ "{s:s, s:o}",
+ "error",
+ "malformed binary data in JSON",
+ "path",
+ path))
+ ? GNUNET_NO : GNUNET_SYSERR;
+ break;
+ }
+ *where = GNUNET_CRYPTO_rsa_signature_decode (buf,
+ len);
+ GNUNET_free (buf);
+ if (NULL == *where)
+ {
+ ret = (MHD_YES ==
+ TALER_MINT_reply_json_pack (connection,
+ MHD_HTTP_BAD_REQUEST,
+ "{s:s, s:o}",
+ "error",
+ "malformed RSA signature in JSON",
+ "path",
+ path))
+ ? GNUNET_NO : GNUNET_SYSERR;
+ break;
+ }
+ ret = GNUNET_OK;
break;
+ }
+
+ default:
+ GNUNET_break (0);
+ ret = (MHD_YES ==
+ TALER_MINT_reply_internal_error (connection,
+ "unhandled value in switch"))
+ ? GNUNET_NO : GNUNET_SYSERR;
+ break;
}
}
va_end (argp);
@@ -531,6 +764,30 @@ TALER_MINT_parse_json_data (struct MHD_Connection *connection,
JNAV_RET_TYPED_JSON,
spec[i].type,
&ptr);
+ *((void**)spec[i].destination) = ptr;
+ break;
+ case JNAV_RET_RSA_PUBLIC_KEY:
+ if (GNUNET_YES != ret)
+ break;
+ ptr = NULL;
+ ret = GNUNET_MINT_parse_navigate_json (connection,
+ root,
+ JNAV_FIELD,
+ spec[i].field_name,
+ JNAV_RET_RSA_PUBLIC_KEY,
+ &ptr);
+ spec[i].destination = ptr;
+ break;
+ case JNAV_RET_RSA_SIGNATURE:
+ if (GNUNET_YES != ret)
+ break;
+ ptr = NULL;
+ ret = GNUNET_MINT_parse_navigate_json (connection,
+ root,
+ JNAV_FIELD,
+ spec[i].field_name,
+ JNAV_RET_RSA_SIGNATURE,
+ &ptr);
spec[i].destination = ptr;
break;
}
@@ -551,6 +808,7 @@ void
TALER_MINT_release_parsed_data (struct GNUNET_MINT_ParseFieldSpec *spec)
{
unsigned int i;
+ void *ptr;
for (i=0; NULL != spec[i].field_name; i++)
{
@@ -573,10 +831,27 @@ TALER_MINT_release_parsed_data (struct GNUNET_MINT_ParseFieldSpec *spec)
}
break;
case JNAV_RET_TYPED_JSON:
- if (NULL != spec[i].destination)
+ ptr = *(void **) spec[i].destination;
+ if (NULL != ptr)
{
- json_decref (spec[i].destination);
- spec[i].destination = NULL;
+ json_decref (ptr);
+ *(void**) spec[i].destination = NULL;
+ }
+ break;
+ case JNAV_RET_RSA_PUBLIC_KEY:
+ ptr = *(void **) spec[i].destination;
+ if (NULL != ptr)
+ {
+ GNUNET_CRYPTO_rsa_public_key_free (ptr);
+ *(void**) spec[i].destination = NULL;
+ }
+ break;
+ case JNAV_RET_RSA_SIGNATURE:
+ ptr = *(void **) spec[i].destination;
+ if (NULL != ptr)
+ {
+ GNUNET_CRYPTO_rsa_signature_free (ptr);
+ *(void**) spec[i].destination = NULL;
}
break;
}
@@ -656,105 +931,5 @@ TALER_MINT_parse_amount_json (struct MHD_Connection *connection,
}
-/**
- * Extract base32crockford encoded data from request.
- *
- * Queues an error response to the connection if the parameter is missing or
- * invalid.
- *
- * @param connection the MHD connection
- * @param param_name the name of the parameter with the key
- * @param[out] out_data pointer to store the result
- * @param out_size expected size of data
- * @return
- * #GNUNET_YES if the the argument is present
- * #GNUNET_NO if the argument is absent or malformed
- * #GNUNET_SYSERR on internal error (error response could not be sent)
- */
-int
-TALER_MINT_mhd_request_arg_data (struct MHD_Connection *connection,
- const char *param_name,
- void *out_data,
- size_t out_size)
-{
- const char *str;
-
- str = MHD_lookup_connection_value (connection,
- MHD_GET_ARGUMENT_KIND,
- param_name);
- if (NULL == str)
- {
- return (MHD_NO ==
- TALER_MINT_reply_arg_missing (connection, param_name))
- ? GNUNET_SYSERR : GNUNET_NO;
- }
- if (GNUNET_OK !=
- GNUNET_STRINGS_string_to_data (str,
- strlen (str),
- out_data,
- out_size))
- return (MHD_NO ==
- TALER_MINT_reply_arg_invalid (connection, param_name))
- ? GNUNET_SYSERR : GNUNET_NO;
- return GNUNET_OK;
-}
-
-
-/**
- * Extraxt variable-size base32crockford encoded data from request.
- *
- * Queues an error response to the connection if the parameter is missing
- * or the encoding is invalid.
- *
- * @param connection the MHD connection
- * @param param_name the name of the parameter with the key
- * @param[out] out_data pointer to allocate buffer and store the result
- * @param[out] out_size set to the size of the buffer allocated in @a out_data
- * @return
- * #GNUNET_YES if the the argument is present
- * #GNUNET_NO if the argument is absent or malformed
- * #GNUNET_SYSERR on internal error (error response could not be sent)
- */
-int
-TALER_MINT_mhd_request_var_arg_data (struct MHD_Connection *connection,
- const char *param_name,
- void **out_data,
- size_t *out_size)
-{
- const char *str;
- size_t slen;
- size_t olen;
- void *out;
-
- str = MHD_lookup_connection_value (connection,
- MHD_GET_ARGUMENT_KIND,
- param_name);
- if (NULL == str)
- {
- return (MHD_NO ==
- TALER_MINT_reply_arg_missing (connection, param_name))
- ? GNUNET_SYSERR : GNUNET_NO;
- }
- slen = strlen (str);
- olen = (slen * 5) / 8;
- out = GNUNET_malloc (olen);
- if (GNUNET_OK !=
- GNUNET_STRINGS_string_to_data (str,
- strlen (str),
- out,
- olen))
- {
- GNUNET_free (out);
- *out_size = 0;
- return (MHD_NO ==
- TALER_MINT_reply_arg_invalid (connection, param_name))
- ? GNUNET_SYSERR : GNUNET_NO;
- }
- *out_data = out;
- *out_size = olen;
- return GNUNET_OK;
-}
-
-
/* end of taler-mint-httpd_parsing.c */
diff --git a/src/mint/taler-mint-httpd_parsing.h b/src/mint/taler-mint-httpd_parsing.h
index 86205a070..f14090172 100644
--- a/src/mint/taler-mint-httpd_parsing.h
+++ b/src/mint/taler-mint-httpd_parsing.h
@@ -108,7 +108,19 @@ enum TALER_MINT_JsonNavigationCommand
* or -1 for any type).
* Params: (int, json_t **)
*/
- JNAV_RET_TYPED_JSON
+ JNAV_RET_TYPED_JSON,
+
+ /**
+ * Return a `struct GNUNET_CRYPTO_rsa_PublicKey` which was
+ * encoded as variable-size base32crockford encoded data.
+ */
+ JNAV_RET_RSA_PUBLIC_KEY,
+
+ /**
+ * Return a `struct GNUNET_CRYPTO_rsa_Signature` which was
+ * encoded as variable-size base32crockford encoded data.
+ */
+ JNAV_RET_RSA_SIGNATURE
};
@@ -230,15 +242,34 @@ TALER_MINT_release_parsed_data (struct GNUNET_MINT_ParseFieldSpec *spec);
* Generate line in parser specification for JSON array value.
*
* @param field name of the field
+ * @param ptraddr address of pointer to initialize (a `void **`)
*/
-#define TALER_MINT_PARSE_ARRAY(field) { field, NULL, 0, 0, JNAV_RET_TYPED_JSON, JSON_ARRAY }
+#define TALER_MINT_PARSE_ARRAY(field,ptraddr) { field, ptraddr, 0, 0, JNAV_RET_TYPED_JSON, JSON_ARRAY }
/**
* Generate line in parser specification for JSON object value.
*
* @param field name of the field
+ * @param ptraddr address of pointer to initialize (a `void **`)
*/
-#define TALER_MINT_PARSE_OBJECT(field) { field, NULL, 0, 0, JNAV_RET_TYPED_JSON, JSON_OBJECT }
+#define TALER_MINT_PARSE_OBJECT(field,ptraddr) { field, ptraddr, 0, 0, JNAV_RET_TYPED_JSON, JSON_OBJECT }
+
+/**
+ * Generate line in parser specification for RSA public key.
+ *
+ * @param field name of the field
+ * @param ptraddr address of `struct GNUNET_CRYPTO_rsa_PublicKey *` initialize
+ */
+#define TALER_MINT_PARSE_RSA_PUBLIC_KEY(field,ptrpk) { field, ptrpk, 0, 0, JNAV_RET_RSA_PUBLIC_KEY, 0 }
+
+/**
+ * Generate line in parser specification for RSA public key.
+ *
+ * @param field name of the field
+ * @param ptrsig address of `struct GNUNET_CRYPTO_rsa_Signature *` initialize
+ */
+#define TALER_MINT_PARSE_RSA_SIGNATURE(field,ptrsig) { field, ptrsig, 0, 0, JNAV_RET_RSA_SIGNATURE, 0 }
+
/**
diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c
index 89aff83ab..198ad423e 100644
--- a/src/mint/taler-mint-httpd_refresh.c
+++ b/src/mint/taler-mint-httpd_refresh.c
@@ -107,9 +107,9 @@ request_json_require_coin_public_info (struct MHD_Connection *connection,
struct GNUNET_CRYPTO_rsa_PublicKey *pk;
struct GNUNET_MINT_ParseFieldSpec spec[] =
{
- TALER_MINT_PARSE_FIXED("coin_pub", &r_public_info->coin_pub),
- TALER_MINT_PARSE_VARIABLE("denom_sig"),
- TALER_MINT_PARSE_VARIABLE("denom_pub"),
+ TALER_MINT_PARSE_FIXED ("coin_pub", &r_public_info->coin_pub),
+ TALER_MINT_PARSE_RSA_SIGNATURE ("denom_sig", &sig),
+ TALER_MINT_PARSE_RSA_PUBLIC_KEY ("denom_pub", &pk),
TALER_MINT_PARSE_END
};
@@ -118,21 +118,7 @@ request_json_require_coin_public_info (struct MHD_Connection *connection,
spec);
if (GNUNET_OK != ret)
return ret;
- sig = GNUNET_CRYPTO_rsa_signature_decode (spec[1].destination,
- spec[1].destination_size_out);
- pk = GNUNET_CRYPTO_rsa_public_key_decode (spec[2].destination,
- spec[2].destination_size_out);
- TALER_MINT_release_parsed_data (spec);
- if ( (NULL == pk) ||
- (NULL == sig) )
- {
- if (NULL != sig)
- GNUNET_CRYPTO_rsa_signature_free (sig);
- if (NULL != pk)
- GNUNET_CRYPTO_rsa_public_key_free (pk);
- // FIXME: send error reply...
- return GNUNET_NO;
- }
+ // TALER_MINT_release_parsed_data (spec);
r_public_info->denom_sig = sig;
r_public_info->denom_pub = pk;
return GNUNET_OK;
@@ -152,8 +138,8 @@ request_json_require_coin_public_info (struct MHD_Connection *connection,
*/
static int
request_json_check_signature (struct MHD_Connection *connection,
- json_t *root,
- struct GNUNET_CRYPTO_EddsaPublicKey *pub,
+ const json_t *root,
+ const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
{
struct GNUNET_CRYPTO_EddsaSignature signature;
@@ -230,100 +216,38 @@ request_json_check_signature (struct MHD_Connection *connection,
/**
- * Handle a "/refresh/melt" request
+ * Handle a "/refresh/melt" request after the first parsing has happened.
+ * We now need to validate the coins being melted and the session signature
+ * and then hand things of to execute the melt operation.
*
- * @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[IN|OUT] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data
+ * @param refresh_session_pub public key of the melt operation
+ * @param new_denoms array of denomination keys
+ * @param melt_coins array of coins to melt
+ * @param melt_sig_json signature affirming the melt operation
* @return MHD result code
*/
-int
-TALER_MINT_handler_refresh_melt (struct RequestHandler *rh,
- struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size)
+static int
+handle_refresh_melt_json (struct MHD_Connection *connection,
+ const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub,
+ const json_t *new_denoms,
+ const json_t *melt_coins,
+ const json_t *melt_sig_json)
{
- json_t *root;
- struct GNUNET_CRYPTO_EddsaPublicKey refresh_session_pub;
int res;
- json_t *new_denoms;
unsigned int num_new_denoms;
unsigned int i;
struct GNUNET_CRYPTO_rsa_PublicKey **denom_pubs;
- json_t *melt_coins;
struct TALER_CoinPublicInfo *coin_public_infos;
unsigned int coin_count;
struct GNUNET_HashContext *hash_context;
struct GNUNET_HashCode melt_hash;
struct MintKeyState *key_state;
struct RefreshMeltSignatureBody body;
- json_t *melt_sig_json;
char *buf;
size_t buf_size;
struct TALER_MINT_DenomKeyIssuePriv *dki;
- res = TALER_MINT_parse_post_json (connection,
- connection_cls,
- upload_data,
- upload_data_size,
- &root);
- if (GNUNET_SYSERR == res)
- return MHD_NO;
- if ( (GNUNET_NO == res) || (NULL == root) )
- return MHD_YES;
-
- res = GNUNET_MINT_parse_navigate_json (connection,
- root,
- JNAV_FIELD,
- "session_pub",
- JNAV_RET_DATA,
- &refresh_session_pub,
- sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
- if (GNUNET_SYSERR == res)
- return MHD_NO;
- if (GNUNET_NO == res)
- return MHD_YES;
- res = GNUNET_MINT_parse_navigate_json (connection,
- root,
- JNAV_FIELD,
- "new_denoms",
- JNAV_RET_TYPED_JSON,
- JSON_ARRAY,
- &new_denoms);
- if (GNUNET_SYSERR == res)
- return MHD_NO;
- if (GNUNET_NO == res)
- return MHD_YES;
-
- res = GNUNET_MINT_parse_navigate_json (connection,
- root,
- JNAV_FIELD,
- "melt_coins",
- JNAV_RET_TYPED_JSON,
- JSON_ARRAY,
- &melt_coins);
- if (GNUNET_OK != res)
- {
- // FIXME: leaks!
- return res;
- }
-
- melt_sig_json = json_object_get (root,
- "melt_signature");
- if (NULL == melt_sig_json)
- {
- return TALER_MINT_reply_json_pack (connection,
- MHD_HTTP_BAD_REQUEST,
- "{s:s}",
- "error",
- "melt_signature missing");
- }
-
-
-
num_new_denoms = json_array_size (new_denoms);
denom_pubs = GNUNET_malloc (num_new_denoms *
@@ -331,8 +255,7 @@ TALER_MINT_handler_refresh_melt (struct RequestHandler *rh,
for (i=0;i<num_new_denoms;i++)
{
- res = GNUNET_MINT_parse_navigate_json (connection, root,
- JNAV_FIELD, "new_denoms",
+ res = GNUNET_MINT_parse_navigate_json (connection, new_denoms,
JNAV_INDEX, (int) i,
JNAV_RET_DATA_VAR,
&buf,
@@ -380,7 +303,7 @@ TALER_MINT_handler_refresh_melt (struct RequestHandler *rh,
(res = check_confirm_signature (connection,
json_array_get (melt_coins, i),
&coin_public_infos[i].coin_pub,
- &refresh_session_pub)))
+ refresh_session_pub)))
{
GNUNET_break (GNUNET_SYSERR != res);
// FIXME: leaks!
@@ -439,7 +362,7 @@ TALER_MINT_handler_refresh_melt (struct RequestHandler *rh,
if (GNUNET_OK !=
(res = request_json_check_signature (connection,
melt_sig_json,
- &refresh_session_pub,
+ refresh_session_pub,
&body.purpose)))
{
// FIXME: generate proper error reply
@@ -448,7 +371,7 @@ TALER_MINT_handler_refresh_melt (struct RequestHandler *rh,
res = TALER_MINT_db_execute_refresh_melt (connection,
- &refresh_session_pub,
+ refresh_session_pub,
num_new_denoms,
denom_pubs,
coin_count,
@@ -459,6 +382,66 @@ TALER_MINT_handler_refresh_melt (struct RequestHandler *rh,
/**
+ * Handle a "/refresh/melt" request. Parses the request into the JSON
+ * components and then hands things of to #handle_referesh_melt_json()
+ * to validate the melted coins, the signature and execute the melt.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[IN|OUT] connection_cls the connection's closure (can be updated)
+ * @param upload_data upload data
+ * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data
+ * @return MHD result code
+ */
+int
+TALER_MINT_handler_refresh_melt (struct RequestHandler *rh,
+ struct MHD_Connection *connection,
+ void **connection_cls,
+ const char *upload_data,
+ size_t *upload_data_size)
+{
+ json_t *root;
+ json_t *new_denoms;
+ json_t *melt_coins;
+ json_t *melt_sig_json;
+ struct GNUNET_CRYPTO_EddsaPublicKey refresh_session_pub;
+ int res;
+ struct GNUNET_MINT_ParseFieldSpec spec[] = {
+ TALER_MINT_PARSE_FIXED ("session_pub", &refresh_session_pub),
+ TALER_MINT_PARSE_ARRAY ("new_denoms", &new_denoms),
+ TALER_MINT_PARSE_ARRAY ("melt_coins", &melt_coins),
+ TALER_MINT_PARSE_ARRAY ("melt_signature", &melt_sig_json),
+ TALER_MINT_PARSE_END
+ };
+
+ res = TALER_MINT_parse_post_json (connection,
+ connection_cls,
+ upload_data,
+ upload_data_size,
+ &root);
+ if (GNUNET_SYSERR == res)
+ return MHD_NO;
+ if ( (GNUNET_NO == res) || (NULL == root) )
+ return MHD_YES;
+
+ res = TALER_MINT_parse_json_data (connection,
+ root,
+ spec);
+ if (GNUNET_SYSERR == res)
+ return MHD_NO;
+ if (GNUNET_NO == res)
+ return MHD_YES;
+ res = handle_refresh_melt_json (connection,
+ &refresh_session_pub,
+ new_denoms,
+ melt_coins,
+ melt_sig_json);
+ TALER_MINT_release_parsed_data (spec);
+ return res;
+}
+
+
+/**
* Handle a "/refresh/commit" request
*
* @param rh context of the handler