clean up (and rename) request_json_require_nav to properly report parsing errors

This commit is contained in:
Christian Grothoff 2015-01-16 15:04:47 +01:00
parent 4bd515191b
commit 7fe250407c
4 changed files with 151 additions and 128 deletions

View File

@ -131,9 +131,10 @@ TALER_MINT_handler_deposit (struct RequestHandler *rh,
if (cond) { GNUNET_break (0); goto EXITIF_exit; } \ if (cond) { GNUNET_break (0); goto EXITIF_exit; } \
} while (0) } while (0)
#define PARSE_DATA(field, addr) \ #define PARSE_DATA(field, addr) \
EXITIF (GNUNET_OK != request_json_require_nav \ EXITIF (GNUNET_OK != \
(connection, json, \ GNUNET_MINT_parse_navigate_json \
JNAV_FIELD, field, JNAV_RET_DATA, addr, sizeof (*addr))) (connection, json, \
JNAV_FIELD, field, JNAV_RET_DATA, addr, sizeof (*addr)))
PARSE_DATA ("coin_pub", &deposit->coin_pub); PARSE_DATA ("coin_pub", &deposit->coin_pub);
PARSE_DATA ("denom_pub", &deposit->denom_pub); PARSE_DATA ("denom_pub", &deposit->denom_pub);
PARSE_DATA ("ubsig", &ubsig); PARSE_DATA ("ubsig", &ubsig);

View File

@ -271,44 +271,48 @@ TALER_MINT_parse_post_cleanup_callback (void *con_cls)
* @param ... navigation specification (see JNAV_*) * @param ... navigation specification (see JNAV_*)
* @return GNUNET_YES if navigation was successful * @return GNUNET_YES if navigation was successful
* GNUNET_NO if json is malformed, error response was generated * GNUNET_NO if json is malformed, error response was generated
* GNUNET_SYSERR on internal error * GNUNET_SYSERR on internal error (no response was generated,
* connection must be closed)
*/ */
int int
request_json_require_nav (struct MHD_Connection *connection, GNUNET_MINT_parse_navigate_json (struct MHD_Connection *connection,
const json_t *root, ...) const json_t *root,
...)
{ {
va_list argp; va_list argp;
int ignore = GNUNET_NO; int ret;
// what's our current path from 'root'? json_t *path; /* what's our current path from 'root'? */
json_t *path;
path = json_array (); path = json_array ();
va_start (argp, root);
va_start(argp, root); ret = 2;
while (2 == ret)
while (1)
{ {
int command = va_arg(argp, int); enum TALER_MINT_JsonNavigationCommand command
= va_arg (argp,
enum TALER_MINT_JsonNavigationCommand);
switch (command) switch (command)
{ {
case JNAV_FIELD: case JNAV_FIELD:
{ {
const char *fname = va_arg(argp, const char *); const char *fname = va_arg(argp, const char *);
if (GNUNET_YES == ignore)
break; json_array_append_new (path,
json_array_append_new (path, json_string (fname)); json_string (fname));
root = json_object_get (root, fname); root = json_object_get (root,
fname);
if (NULL == root) if (NULL == root)
{ {
/* FIXME: can't IGNORE this return value! */ ret = (MHD_YES ==
(void) TALER_MINT_reply_json_pack (connection, TALER_MINT_reply_json_pack (connection,
MHD_HTTP_BAD_REQUEST, MHD_HTTP_BAD_REQUEST,
"{s:s,s:o}", "{s:s,s:o}",
"error", "error",
"missing field in JSON", "missing field in JSON",
"path", "path",
path); path))
ignore = GNUNET_YES; ? GNUNET_NO : GNUNET_SYSERR;
break; break;
} }
} }
@ -316,19 +320,21 @@ request_json_require_nav (struct MHD_Connection *connection,
case JNAV_INDEX: case JNAV_INDEX:
{ {
int fnum = va_arg(argp, int); int fnum = va_arg(argp, int);
if (GNUNET_YES == ignore)
break; json_array_append_new (path,
json_array_append_new (path, json_integer (fnum)); json_integer (fnum));
root = json_array_get (root, fnum); root = json_array_get (root,
fnum);
if (NULL == root) if (NULL == root)
{ {
/* FIXME: can't IGNORE this return value! */ ret = (MHD_YES ==
(void) TALER_MINT_reply_json_pack (connection, TALER_MINT_reply_json_pack (connection,
MHD_HTTP_BAD_REQUEST, MHD_HTTP_BAD_REQUEST,
"{s:s, s:o}", "{s:s, s:o}",
"error", "missing index in JSON", "error",
"path", path); "missing index in JSON",
ignore = GNUNET_YES; "path", path))
? GNUNET_NO : GNUNET_SYSERR;
break; break;
} }
} }
@ -340,36 +346,36 @@ request_json_require_nav (struct MHD_Connection *connection,
const char *str; const char *str;
int res; int res;
va_end(argp);
if (GNUNET_YES == ignore)
return GNUNET_NO;
str = json_string_value (root); str = json_string_value (root);
if (NULL == str) if (NULL == str)
{ {
/* FIXME: can't IGNORE this return value! */ ret = (MHD_YES ==
(void) TALER_MINT_reply_json_pack (connection, TALER_MINT_reply_json_pack (connection,
MHD_HTTP_BAD_REQUEST, MHD_HTTP_BAD_REQUEST,
"{s:s, s:o}", "{s:s, s:o}",
"error", "error",
"string expected", "string expected",
"path", "path",
path); path))
return GNUNET_NO; ? GNUNET_NO : GNUNET_SYSERR;
break;
} }
res = GNUNET_STRINGS_string_to_data (str, strlen (str), res = GNUNET_STRINGS_string_to_data (str, strlen (str),
where, len); where, len);
if (GNUNET_OK != res) if (GNUNET_OK != res)
{ {
/* FIXME: can't IGNORE this return value! */ ret = (MHD_YES ==
(void) TALER_MINT_reply_json_pack (connection, TALER_MINT_reply_json_pack (connection,
MHD_HTTP_BAD_REQUEST, MHD_HTTP_BAD_REQUEST,
"{s:s,s:o}", "{s:s,s:o}",
"error", "error",
"malformed binary data in JSON", "malformed binary data in JSON",
"path", path); "path",
return GNUNET_NO; path))
? GNUNET_NO : GNUNET_SYSERR;
break;
} }
return GNUNET_YES; ret = GNUNET_OK;
} }
break; break;
case JNAV_RET_DATA_VAR: case JNAV_RET_DATA_VAR:
@ -378,35 +384,42 @@ request_json_require_nav (struct MHD_Connection *connection,
size_t *len = va_arg (argp, size_t *); size_t *len = va_arg (argp, size_t *);
const char *str; const char *str;
va_end(argp);
if (GNUNET_YES == ignore)
return GNUNET_NO;
str = json_string_value (root); str = json_string_value (root);
if (NULL == str) if (NULL == str)
{ {
GNUNET_break (0); ret = (MHD_YES ==
return GNUNET_SYSERR; TALER_MINT_reply_internal_error (connection,
"json_string_value() failed"))
? GNUNET_NO : GNUNET_SYSERR;
break;
} }
*len = (strlen (str) * 5) / 8; *len = (strlen (str) * 5) / 8;
if (where != NULL) if (NULL != where)
{ {
int res; int res;
*where = GNUNET_malloc (*len); *where = GNUNET_malloc (*len);
res = GNUNET_STRINGS_string_to_data (str, strlen (str), res = GNUNET_STRINGS_string_to_data (str,
*where, *len); strlen (str),
*where,
*len);
if (GNUNET_OK != res) if (GNUNET_OK != res)
{ {
/* FIXME: can't IGNORE this return value! */ GNUNET_free (*where);
(void) TALER_MINT_reply_json_pack (connection, *where = NULL;
*len = 0;
ret = (MHD_YES ==
TALER_MINT_reply_json_pack (connection,
MHD_HTTP_BAD_REQUEST, MHD_HTTP_BAD_REQUEST,
"{s:s, s:o}", "{s:s, s:o}",
"error", "error",
"malformed binary data in JSON", "malformed binary data in JSON",
"path", path); "path", path))
return GNUNET_NO; ? GNUNET_NO : GNUNET_SYSERR;
break;
} }
} }
return GNUNET_OK; ret = GNUNET_OK;
} }
break; break;
case JNAV_RET_TYPED_JSON: case JNAV_RET_TYPED_JSON:
@ -414,30 +427,35 @@ request_json_require_nav (struct MHD_Connection *connection,
int typ = va_arg (argp, int); int typ = va_arg (argp, int);
const json_t **r_json = va_arg (argp, const json_t **); const json_t **r_json = va_arg (argp, const json_t **);
va_end(argp); if ( (-1 != typ) && (json_typeof (root) != typ))
if (GNUNET_YES == ignore)
return GNUNET_NO;
if (typ != -1 && json_typeof (root) != typ)
{ {
/* FIXME: can't IGNORE this return value! */ ret = (MHD_YES ==
(void) TALER_MINT_reply_json_pack (connection, TALER_MINT_reply_json_pack (connection,
MHD_HTTP_BAD_REQUEST, MHD_HTTP_BAD_REQUEST,
"{s:s, s:i, s:i s:o}", "{s:s, s:i, s:i s:o}",
"error", "wrong JSON field type", "error", "wrong JSON field type",
"type_expected", typ, "type_expected", typ,
"type_actual", json_typeof (root), "type_actual", json_typeof (root),
"path", path); "path", path))
return GNUNET_NO; ? GNUNET_NO : GNUNET_SYSERR;
break;
} }
*r_json = root; *r_json = root;
return GNUNET_OK; ret = GNUNET_OK;
} }
break; break;
default: default:
GNUNET_assert (0); GNUNET_break (0);
ret = (MHD_YES ==
TALER_MINT_reply_internal_error (connection,
"unhandled value in switch"))
? GNUNET_NO : GNUNET_SYSERR;
break;
} }
} }
GNUNET_assert (0); va_end (argp);
json_decref (path);
return ret;
} }

View File

@ -30,43 +30,6 @@
#include <jansson.h> #include <jansson.h>
/**
* Constants for JSON navigation description.
*/
enum
{
/**
* Access a field.
* Param: const char *
*/
JNAV_FIELD,
/**
* Access an array index.
* Param: int
*/
JNAV_INDEX,
/**
* Return base32crockford encoded data of
* constant size.
* Params: (void *, size_t)
*/
JNAV_RET_DATA,
/**
* Return base32crockford encoded data of
* variable size.
* Params: (void **, size_t *)
*/
JNAV_RET_DATA_VAR,
/**
* Return a json object, which must be
* of the given type (JSON_* type constants,
* or -1 for any type).
* Params: (int, json_t **)
*/
JNAV_RET_TYPED_JSON
};
/** /**
* Process a POST request containing a JSON object. This * Process a POST request containing a JSON object. This
* function realizes an MHD POST processor that will * function realizes an MHD POST processor that will
@ -110,6 +73,47 @@ void
TALER_MINT_parse_post_cleanup_callback (void *con_cls); TALER_MINT_parse_post_cleanup_callback (void *con_cls);
/**
* Constants for JSON navigation description.
*/
enum TALER_MINT_JsonNavigationCommand
{
/**
* Access a field.
* Param: const char *
*/
JNAV_FIELD,
/**
* Access an array index.
* Param: int
*/
JNAV_INDEX,
/**
* Return base32crockford encoded data of
* constant size.
* Params: (void *, size_t)
*/
JNAV_RET_DATA,
/**
* Return base32crockford encoded data of
* variable size.
* Params: (void **, size_t *)
*/
JNAV_RET_DATA_VAR,
/**
* Return a json object, which must be
* of the given type (JSON_* type constants,
* or -1 for any type).
* Params: (int, json_t **)
*/
JNAV_RET_TYPED_JSON
};
/** /**
* Navigate through a JSON tree. * Navigate through a JSON tree.
* *
@ -124,7 +128,7 @@ TALER_MINT_parse_post_cleanup_callback (void *con_cls);
* GNUNET_SYSERR on internal error * GNUNET_SYSERR on internal error
*/ */
int int
request_json_require_nav (struct MHD_Connection *connection, GNUNET_MINT_parse_navigate_json (struct MHD_Connection *connection,
const json_t *root, ...); const json_t *root, ...);

View File

@ -125,7 +125,7 @@ refresh_accept_denoms (struct MHD_Connection *connection,
int res; int res;
json_t *new_denoms; json_t *new_denoms;
res = request_json_require_nav (connection, root, res = GNUNET_MINT_parse_navigate_json (connection, root,
JNAV_FIELD, "new_denoms", JNAV_FIELD, "new_denoms",
JNAV_RET_TYPED_JSON, JNAV_RET_TYPED_JSON,
JSON_ARRAY, JSON_ARRAY,
@ -142,7 +142,7 @@ refresh_accept_denoms (struct MHD_Connection *connection,
struct TALER_MINT_DenomKeyIssue *dki; struct TALER_MINT_DenomKeyIssue *dki;
struct TALER_Amount cost; struct TALER_Amount cost;
res = request_json_require_nav (connection, root, res = GNUNET_MINT_parse_navigate_json (connection, root,
JNAV_FIELD, "new_denoms", JNAV_FIELD, "new_denoms",
JNAV_INDEX, (int) i, JNAV_INDEX, (int) i,
JNAV_RET_DATA, JNAV_RET_DATA,
@ -210,7 +210,7 @@ check_confirm_signature (struct MHD_Connection *connection,
body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_CONFIRM); body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_CONFIRM);
body.session_pub = *session_pub; body.session_pub = *session_pub;
res = request_json_require_nav (connection, coin_info, res = GNUNET_MINT_parse_navigate_json (connection, coin_info,
JNAV_FIELD, "confirm_sig", JNAV_FIELD, "confirm_sig",
JNAV_RET_DATA, JNAV_RET_DATA,
&sig, &sig,
@ -259,7 +259,7 @@ request_json_require_coin_public_info (struct MHD_Connection *connection,
GNUNET_assert (NULL != root); GNUNET_assert (NULL != root);
ret = request_json_require_nav (connection, root, ret = GNUNET_MINT_parse_navigate_json (connection, root,
JNAV_FIELD, "coin_pub", JNAV_FIELD, "coin_pub",
JNAV_RET_DATA, JNAV_RET_DATA,
&r_public_info->coin_pub, &r_public_info->coin_pub,
@ -267,7 +267,7 @@ request_json_require_coin_public_info (struct MHD_Connection *connection,
if (GNUNET_OK != ret) if (GNUNET_OK != ret)
return ret; return ret;
ret = request_json_require_nav (connection, root, ret = GNUNET_MINT_parse_navigate_json (connection, root,
JNAV_FIELD, "denom_sig", JNAV_FIELD, "denom_sig",
JNAV_RET_DATA, JNAV_RET_DATA,
&r_public_info->denom_sig, &r_public_info->denom_sig,
@ -275,7 +275,7 @@ request_json_require_coin_public_info (struct MHD_Connection *connection,
if (GNUNET_OK != ret) if (GNUNET_OK != ret)
return ret; return ret;
ret = request_json_require_nav (connection, root, ret = GNUNET_MINT_parse_navigate_json (connection, root,
JNAV_FIELD, "denom_pub", JNAV_FIELD, "denom_pub",
JNAV_RET_DATA, JNAV_RET_DATA,
&r_public_info->denom_pub, &r_public_info->denom_pub,
@ -315,7 +315,7 @@ refresh_accept_melts (struct MHD_Connection *connection,
int res; int res;
json_t *melt_coins; json_t *melt_coins;
res = request_json_require_nav (connection, root, res = GNUNET_MINT_parse_navigate_json (connection, root,
JNAV_FIELD, "melt_coins", JNAV_FIELD, "melt_coins",
JNAV_RET_TYPED_JSON, JNAV_RET_TYPED_JSON,
JSON_ARRAY, JSON_ARRAY,
@ -512,7 +512,7 @@ request_json_check_signature (struct MHD_Connection *connection,
int res; int res;
json_t *el; json_t *el;
res = request_json_require_nav (connection, root, res = GNUNET_MINT_parse_navigate_json (connection, root,
JNAV_FIELD, "sig", JNAV_FIELD, "sig",
JNAV_RET_DATA, JNAV_RET_DATA,
&signature, &signature,
@ -521,7 +521,7 @@ request_json_check_signature (struct MHD_Connection *connection,
if (GNUNET_OK != res) if (GNUNET_OK != res)
return res; return res;
res = request_json_require_nav (connection, root, res = GNUNET_MINT_parse_navigate_json (connection, root,
JNAV_FIELD, "purpose", JNAV_FIELD, "purpose",
JNAV_RET_TYPED_JSON, JNAV_RET_TYPED_JSON,
JSON_INTEGER, JSON_INTEGER,
@ -541,7 +541,7 @@ request_json_check_signature (struct MHD_Connection *connection,
"error", "signature invalid (purpose)"); "error", "signature invalid (purpose)");
} }
res = request_json_require_nav (connection, root, res = GNUNET_MINT_parse_navigate_json (connection, root,
JNAV_FIELD, "size", JNAV_FIELD, "size",
JNAV_RET_TYPED_JSON, JNAV_RET_TYPED_JSON,
JSON_INTEGER, JSON_INTEGER,
@ -623,7 +623,7 @@ TALER_MINT_handler_refresh_melt (struct RequestHandler *rh,
} }
/* session_pub field must always be present */ /* session_pub field must always be present */
res = request_json_require_nav (connection, root, res = GNUNET_MINT_parse_navigate_json (connection, root,
JNAV_FIELD, "session_pub", JNAV_FIELD, "session_pub",
JNAV_RET_DATA, JNAV_RET_DATA,
&refresh_session_pub, &refresh_session_pub,
@ -833,7 +833,7 @@ TALER_MINT_handler_refresh_commit (struct RequestHandler *rh,
if ( (GNUNET_NO == res) || (NULL == root) ) if ( (GNUNET_NO == res) || (NULL == root) )
return MHD_YES; return MHD_YES;
res = request_json_require_nav (connection, root, res = GNUNET_MINT_parse_navigate_json (connection, root,
JNAV_FIELD, "session_pub", JNAV_FIELD, "session_pub",
JNAV_RET_DATA, JNAV_RET_DATA,
&refresh_session_pub, &refresh_session_pub,
@ -906,7 +906,7 @@ TALER_MINT_handler_refresh_commit (struct RequestHandler *rh,
{ {
struct RefreshCommitCoin commit_coin; struct RefreshCommitCoin commit_coin;
res = request_json_require_nav (connection, root, res = GNUNET_MINT_parse_navigate_json (connection, root,
JNAV_FIELD, "coin_evs", JNAV_FIELD, "coin_evs",
JNAV_INDEX, (int) i, JNAV_INDEX, (int) i,
JNAV_INDEX, (int) j, JNAV_INDEX, (int) j,
@ -927,7 +927,7 @@ TALER_MINT_handler_refresh_commit (struct RequestHandler *rh,
&commit_coin.coin_ev, &commit_coin.coin_ev,
sizeof (struct TALER_RSA_BlindedSignaturePurpose)); sizeof (struct TALER_RSA_BlindedSignaturePurpose));
res = request_json_require_nav (connection, root, res = GNUNET_MINT_parse_navigate_json (connection, root,
JNAV_FIELD, "link_encs", JNAV_FIELD, "link_encs",
JNAV_INDEX, (int) i, JNAV_INDEX, (int) i,
JNAV_INDEX, (int) j, JNAV_INDEX, (int) j,
@ -971,7 +971,7 @@ TALER_MINT_handler_refresh_commit (struct RequestHandler *rh,
{ {
struct RefreshCommitLink commit_link; struct RefreshCommitLink commit_link;
res = request_json_require_nav (connection, root, res = GNUNET_MINT_parse_navigate_json (connection, root,
JNAV_FIELD, "transfer_pubs", JNAV_FIELD, "transfer_pubs",
JNAV_INDEX, (int) i, JNAV_INDEX, (int) i,
JNAV_INDEX, (int) j, JNAV_INDEX, (int) j,
@ -991,7 +991,7 @@ TALER_MINT_handler_refresh_commit (struct RequestHandler *rh,
&commit_link.transfer_pub, &commit_link.transfer_pub,
sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
res = request_json_require_nav (connection, root, res = GNUNET_MINT_parse_navigate_json (connection, root,
JNAV_FIELD, "secret_encs", JNAV_FIELD, "secret_encs",
JNAV_INDEX, (int) i, JNAV_INDEX, (int) i,
JNAV_INDEX, (int) j, JNAV_INDEX, (int) j,
@ -1165,7 +1165,7 @@ TALER_MINT_handler_refresh_reveal (struct RequestHandler *rh,
if ( (GNUNET_NO == res) || (NULL == root) ) if ( (GNUNET_NO == res) || (NULL == root) )
return MHD_YES; return MHD_YES;
res = request_json_require_nav (connection, root, res = GNUNET_MINT_parse_navigate_json (connection, root,
JNAV_FIELD, "session_pub", JNAV_FIELD, "session_pub",
JNAV_RET_DATA, JNAV_RET_DATA,
&refresh_session_pub, &refresh_session_pub,
@ -1216,7 +1216,7 @@ TALER_MINT_handler_refresh_reveal (struct RequestHandler *rh,
struct GNUNET_HashCode transfer_secret; struct GNUNET_HashCode transfer_secret;
struct GNUNET_HashCode shared_secret; struct GNUNET_HashCode shared_secret;
res = request_json_require_nav (connection, root, res = GNUNET_MINT_parse_navigate_json (connection, root,
JNAV_FIELD, "transfer_privs", JNAV_FIELD, "transfer_privs",
JNAV_INDEX, (int) i, JNAV_INDEX, (int) i,
JNAV_INDEX, (int) j, JNAV_INDEX, (int) j,