make TALER_MINT_parse_json_data more expressive, add RSA types as well
This commit is contained in:
parent
a284561298
commit
4a27969e5e
@ -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;
|
||||
}
|
||||
|
@ -260,402 +260,6 @@ TALER_MINT_parse_post_cleanup_callback (void *con_cls)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Navigate through a JSON tree.
|
||||
*
|
||||
* Sends an error response if navigation is impossible (i.e.
|
||||
* the JSON object is invalid)
|
||||
*
|
||||
* @param connection the connection to send an error response to
|
||||
* @param root the JSON node to start the navigation at.
|
||||
* @param ... navigation specification (see `enum TALER_MINT_JsonNavigationCommand`)
|
||||
* @return
|
||||
* #GNUNET_YES if navigation was successful
|
||||
* #GNUNET_NO if json is malformed, error response was generated
|
||||
* #GNUNET_SYSERR on internal error (no response was generated,
|
||||
* connection must be closed)
|
||||
*/
|
||||
int
|
||||
GNUNET_MINT_parse_navigate_json (struct MHD_Connection *connection,
|
||||
const json_t *root,
|
||||
...)
|
||||
{
|
||||
va_list argp;
|
||||
int ret;
|
||||
json_t *path; /* what's our current path from 'root'? */
|
||||
|
||||
path = json_array ();
|
||||
va_start (argp, root);
|
||||
ret = 2; /* just not any of the valid return values */
|
||||
while (2 == ret)
|
||||
{
|
||||
enum TALER_MINT_JsonNavigationCommand command
|
||||
= va_arg (argp,
|
||||
enum TALER_MINT_JsonNavigationCommand);
|
||||
|
||||
switch (command)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
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_RET_DATA:
|
||||
{
|
||||
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);
|
||||
if (GNUNET_OK != res)
|
||||
{
|
||||
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;
|
||||
case JNAV_RET_DATA_VAR:
|
||||
{
|
||||
void **where = va_arg (argp, void **);
|
||||
size_t *len = va_arg (argp, size_t *);
|
||||
const char *str;
|
||||
|
||||
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;
|
||||
}
|
||||
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))
|
||||
{
|
||||
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;
|
||||
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);
|
||||
json_decref (path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse JSON object into components based on the given field
|
||||
* specification.
|
||||
*
|
||||
* @param connection the connection to send an error response to
|
||||
* @param root the JSON node to start the navigation at.
|
||||
* @param spec field specification for the parser
|
||||
* @return
|
||||
* #GNUNET_YES if navigation was successful (caller is responsible
|
||||
* for freeing allocated variable-size data using
|
||||
* #TALER_MINT_release_parsed_data() when done)
|
||||
* #GNUNET_NO if json is malformed, error response was generated
|
||||
* #GNUNET_SYSERR on internal error
|
||||
*/
|
||||
int
|
||||
TALER_MINT_parse_json_data (struct MHD_Connection *connection,
|
||||
const json_t *root,
|
||||
struct GNUNET_MINT_ParseFieldSpec *spec)
|
||||
{
|
||||
unsigned int i;
|
||||
int ret;
|
||||
void *ptr;
|
||||
|
||||
ret = GNUNET_YES;
|
||||
for (i=0; NULL != spec[i].field_name; i++)
|
||||
{
|
||||
switch (spec[i].command)
|
||||
{
|
||||
case JNAV_FIELD:
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
case JNAV_INDEX:
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
case JNAV_RET_DATA:
|
||||
if (GNUNET_YES != ret)
|
||||
break;
|
||||
ret = GNUNET_MINT_parse_navigate_json (connection,
|
||||
root,
|
||||
JNAV_FIELD,
|
||||
spec[i].field_name,
|
||||
JNAV_RET_DATA,
|
||||
spec[i].destination,
|
||||
spec[i].destination_size_in);
|
||||
break;
|
||||
case JNAV_RET_DATA_VAR:
|
||||
if (GNUNET_YES != ret)
|
||||
break;
|
||||
ptr = NULL;
|
||||
ret = GNUNET_MINT_parse_navigate_json (connection,
|
||||
root,
|
||||
JNAV_FIELD,
|
||||
spec[i].field_name,
|
||||
JNAV_RET_DATA_VAR,
|
||||
&ptr,
|
||||
&spec[i].destination_size_out);
|
||||
spec[i].destination = ptr;
|
||||
break;
|
||||
case JNAV_RET_TYPED_JSON:
|
||||
if (GNUNET_YES != ret)
|
||||
break;
|
||||
ptr = NULL;
|
||||
ret = GNUNET_MINT_parse_navigate_json (connection,
|
||||
root,
|
||||
JNAV_FIELD,
|
||||
spec[i].field_name,
|
||||
JNAV_RET_TYPED_JSON,
|
||||
spec[i].type,
|
||||
&ptr);
|
||||
spec[i].destination = ptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (GNUNET_YES != ret)
|
||||
TALER_MINT_release_parsed_data (spec);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Release all memory allocated for the variable-size fields in
|
||||
* the parser specification.
|
||||
*
|
||||
* @param spec specification to free
|
||||
*/
|
||||
void
|
||||
TALER_MINT_release_parsed_data (struct GNUNET_MINT_ParseFieldSpec *spec)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i=0; NULL != spec[i].field_name; i++)
|
||||
{
|
||||
switch (spec[i].command)
|
||||
{
|
||||
case JNAV_FIELD:
|
||||
GNUNET_break (0);
|
||||
return;
|
||||
case JNAV_INDEX:
|
||||
GNUNET_break (0);
|
||||
return;
|
||||
case JNAV_RET_DATA:
|
||||
break;
|
||||
case JNAV_RET_DATA_VAR:
|
||||
if (0 != spec[i].destination_size_out)
|
||||
{
|
||||
GNUNET_free (spec[i].destination);
|
||||
spec[i].destination = NULL;
|
||||
spec[i].destination_size_out = 0;
|
||||
}
|
||||
break;
|
||||
case JNAV_RET_TYPED_JSON:
|
||||
if (NULL != spec[i].destination)
|
||||
{
|
||||
json_decref (spec[i].destination);
|
||||
spec[i].destination = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse amount specified in JSON format.
|
||||
*
|
||||
* @param connection the MHD connection (to report errors)
|
||||
* @param f json specification of the amount
|
||||
* @param amount[OUT] set to the amount specified in @a f
|
||||
* @return
|
||||
* #GNUNET_YES if parsing was successful
|
||||
* #GNUNET_NO if json is malformed, error response was generated
|
||||
* #GNUNET_SYSERR on internal error, error response was not generated
|
||||
*/
|
||||
int
|
||||
TALER_MINT_parse_amount_json (struct MHD_Connection *connection,
|
||||
json_t *f,
|
||||
struct TALER_Amount *amount)
|
||||
{
|
||||
json_int_t value;
|
||||
json_int_t fraction;
|
||||
const char *currency;
|
||||
struct TALER_Amount a;
|
||||
|
||||
if (-1 == json_unpack (f,
|
||||
"{s:I, s:I, s:s}",
|
||||
"value", &value,
|
||||
"fraction", &fraction,
|
||||
"currency", ¤cy))
|
||||
{
|
||||
LOG_WARNING ("Failed to parse JSON amount specification\n");
|
||||
if (MHD_YES !=
|
||||
TALER_MINT_reply_json_pack (connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
"{s:s}",
|
||||
"error", "Bad format"))
|
||||
return GNUNET_SYSERR;
|
||||
return GNUNET_NO;
|
||||
}
|
||||
if ( (value < 0) ||
|
||||
(fraction < 0) ||
|
||||
(value > UINT32_MAX) ||
|
||||
(fraction > UINT32_MAX) )
|
||||
{
|
||||
LOG_WARNING ("Amount specified not in allowed range\n");
|
||||
if (MHD_YES !=
|
||||
TALER_MINT_reply_json_pack (connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
"{s:s}",
|
||||
"error", "Amount outside of allowed range"))
|
||||
return GNUNET_SYSERR;
|
||||
return GNUNET_NO;
|
||||
}
|
||||
if (0 != strcmp (currency,
|
||||
MINT_CURRENCY))
|
||||
{
|
||||
LOG_WARNING ("Currency specified not supported by this mint\n");
|
||||
if (MHD_YES !=
|
||||
TALER_MINT_reply_json_pack (connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
"{s:s, s:s}",
|
||||
"error", "Currency not supported",
|
||||
"currency", currency))
|
||||
return GNUNET_SYSERR;
|
||||
return GNUNET_NO;
|
||||
}
|
||||
a.value = (uint32_t) value;
|
||||
a.fraction = (uint32_t) fraction;
|
||||
GNUNET_assert (strlen (MINT_CURRENCY) < TALER_CURRENCY_LEN);
|
||||
strcpy (a.currency, MINT_CURRENCY);
|
||||
*amount = TALER_amount_normalize (a);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract base32crockford encoded data from request.
|
||||
*
|
||||
@ -756,5 +360,576 @@ TALER_MINT_mhd_request_var_arg_data (struct MHD_Connection *connection,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Navigate through a JSON tree.
|
||||
*
|
||||
* Sends an error response if navigation is impossible (i.e.
|
||||
* the JSON object is invalid)
|
||||
*
|
||||
* @param connection the connection to send an error response to
|
||||
* @param root the JSON node to start the navigation at.
|
||||
* @param ... navigation specification (see `enum TALER_MINT_JsonNavigationCommand`)
|
||||
* @return
|
||||
* #GNUNET_YES if navigation was successful
|
||||
* #GNUNET_NO if json is malformed, error response was generated
|
||||
* #GNUNET_SYSERR on internal error (no response was generated,
|
||||
* connection must be closed)
|
||||
*/
|
||||
int
|
||||
GNUNET_MINT_parse_navigate_json (struct MHD_Connection *connection,
|
||||
const json_t *root,
|
||||
...)
|
||||
{
|
||||
va_list argp;
|
||||
int ret;
|
||||
json_t *path; /* what's our current path from 'root'? */
|
||||
|
||||
path = json_array ();
|
||||
va_start (argp, root);
|
||||
ret = 2; /* just not any of the valid return values */
|
||||
while (2 == ret)
|
||||
{
|
||||
enum TALER_MINT_JsonNavigationCommand command
|
||||
= va_arg (argp,
|
||||
enum TALER_MINT_JsonNavigationCommand);
|
||||
|
||||
switch (command)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
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_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)
|
||||
{
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
*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;
|
||||
}
|
||||
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))
|
||||
{
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
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_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;
|
||||
}
|
||||
|
||||
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);
|
||||
json_decref (path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse JSON object into components based on the given field
|
||||
* specification.
|
||||
*
|
||||
* @param connection the connection to send an error response to
|
||||
* @param root the JSON node to start the navigation at.
|
||||
* @param spec field specification for the parser
|
||||
* @return
|
||||
* #GNUNET_YES if navigation was successful (caller is responsible
|
||||
* for freeing allocated variable-size data using
|
||||
* #TALER_MINT_release_parsed_data() when done)
|
||||
* #GNUNET_NO if json is malformed, error response was generated
|
||||
* #GNUNET_SYSERR on internal error
|
||||
*/
|
||||
int
|
||||
TALER_MINT_parse_json_data (struct MHD_Connection *connection,
|
||||
const json_t *root,
|
||||
struct GNUNET_MINT_ParseFieldSpec *spec)
|
||||
{
|
||||
unsigned int i;
|
||||
int ret;
|
||||
void *ptr;
|
||||
|
||||
ret = GNUNET_YES;
|
||||
for (i=0; NULL != spec[i].field_name; i++)
|
||||
{
|
||||
switch (spec[i].command)
|
||||
{
|
||||
case JNAV_FIELD:
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
case JNAV_INDEX:
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
case JNAV_RET_DATA:
|
||||
if (GNUNET_YES != ret)
|
||||
break;
|
||||
ret = GNUNET_MINT_parse_navigate_json (connection,
|
||||
root,
|
||||
JNAV_FIELD,
|
||||
spec[i].field_name,
|
||||
JNAV_RET_DATA,
|
||||
spec[i].destination,
|
||||
spec[i].destination_size_in);
|
||||
break;
|
||||
case JNAV_RET_DATA_VAR:
|
||||
if (GNUNET_YES != ret)
|
||||
break;
|
||||
ptr = NULL;
|
||||
ret = GNUNET_MINT_parse_navigate_json (connection,
|
||||
root,
|
||||
JNAV_FIELD,
|
||||
spec[i].field_name,
|
||||
JNAV_RET_DATA_VAR,
|
||||
&ptr,
|
||||
&spec[i].destination_size_out);
|
||||
spec[i].destination = ptr;
|
||||
break;
|
||||
case JNAV_RET_TYPED_JSON:
|
||||
if (GNUNET_YES != ret)
|
||||
break;
|
||||
ptr = NULL;
|
||||
ret = GNUNET_MINT_parse_navigate_json (connection,
|
||||
root,
|
||||
JNAV_FIELD,
|
||||
spec[i].field_name,
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (GNUNET_YES != ret)
|
||||
TALER_MINT_release_parsed_data (spec);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Release all memory allocated for the variable-size fields in
|
||||
* the parser specification.
|
||||
*
|
||||
* @param spec specification to free
|
||||
*/
|
||||
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++)
|
||||
{
|
||||
switch (spec[i].command)
|
||||
{
|
||||
case JNAV_FIELD:
|
||||
GNUNET_break (0);
|
||||
return;
|
||||
case JNAV_INDEX:
|
||||
GNUNET_break (0);
|
||||
return;
|
||||
case JNAV_RET_DATA:
|
||||
break;
|
||||
case JNAV_RET_DATA_VAR:
|
||||
if (0 != spec[i].destination_size_out)
|
||||
{
|
||||
GNUNET_free (spec[i].destination);
|
||||
spec[i].destination = NULL;
|
||||
spec[i].destination_size_out = 0;
|
||||
}
|
||||
break;
|
||||
case JNAV_RET_TYPED_JSON:
|
||||
ptr = *(void **) spec[i].destination;
|
||||
if (NULL != ptr)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse amount specified in JSON format.
|
||||
*
|
||||
* @param connection the MHD connection (to report errors)
|
||||
* @param f json specification of the amount
|
||||
* @param amount[OUT] set to the amount specified in @a f
|
||||
* @return
|
||||
* #GNUNET_YES if parsing was successful
|
||||
* #GNUNET_NO if json is malformed, error response was generated
|
||||
* #GNUNET_SYSERR on internal error, error response was not generated
|
||||
*/
|
||||
int
|
||||
TALER_MINT_parse_amount_json (struct MHD_Connection *connection,
|
||||
json_t *f,
|
||||
struct TALER_Amount *amount)
|
||||
{
|
||||
json_int_t value;
|
||||
json_int_t fraction;
|
||||
const char *currency;
|
||||
struct TALER_Amount a;
|
||||
|
||||
if (-1 == json_unpack (f,
|
||||
"{s:I, s:I, s:s}",
|
||||
"value", &value,
|
||||
"fraction", &fraction,
|
||||
"currency", ¤cy))
|
||||
{
|
||||
LOG_WARNING ("Failed to parse JSON amount specification\n");
|
||||
if (MHD_YES !=
|
||||
TALER_MINT_reply_json_pack (connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
"{s:s}",
|
||||
"error", "Bad format"))
|
||||
return GNUNET_SYSERR;
|
||||
return GNUNET_NO;
|
||||
}
|
||||
if ( (value < 0) ||
|
||||
(fraction < 0) ||
|
||||
(value > UINT32_MAX) ||
|
||||
(fraction > UINT32_MAX) )
|
||||
{
|
||||
LOG_WARNING ("Amount specified not in allowed range\n");
|
||||
if (MHD_YES !=
|
||||
TALER_MINT_reply_json_pack (connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
"{s:s}",
|
||||
"error", "Amount outside of allowed range"))
|
||||
return GNUNET_SYSERR;
|
||||
return GNUNET_NO;
|
||||
}
|
||||
if (0 != strcmp (currency,
|
||||
MINT_CURRENCY))
|
||||
{
|
||||
LOG_WARNING ("Currency specified not supported by this mint\n");
|
||||
if (MHD_YES !=
|
||||
TALER_MINT_reply_json_pack (connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
"{s:s, s:s}",
|
||||
"error", "Currency not supported",
|
||||
"currency", currency))
|
||||
return GNUNET_SYSERR;
|
||||
return GNUNET_NO;
|
||||
}
|
||||
a.value = (uint32_t) value;
|
||||
a.fraction = (uint32_t) fraction;
|
||||
GNUNET_assert (strlen (MINT_CURRENCY) < TALER_CURRENCY_LEN);
|
||||
strcpy (a.currency, MINT_CURRENCY);
|
||||
*amount = TALER_amount_normalize (a);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* end of taler-mint-httpd_parsing.c */
|
||||
|
@ -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 }
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
@ -108,8 +108,8 @@ request_json_require_coin_public_info (struct MHD_Connection *connection,
|
||||
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_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,
|
||||
@ -458,6 +381,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
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user