From 7fe250407c440e59bece248747ffe8b29a8833b3 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 16 Jan 2015 15:04:47 +0100 Subject: clean up (and rename) request_json_require_nav to properly report parsing errors --- src/mint/taler-mint-httpd_deposit.c | 7 +- src/mint/taler-mint-httpd_parsing.c | 156 ++++++++++++++++++++---------------- src/mint/taler-mint-httpd_parsing.h | 80 +++++++++--------- src/mint/taler-mint-httpd_refresh.c | 36 ++++----- 4 files changed, 151 insertions(+), 128 deletions(-) diff --git a/src/mint/taler-mint-httpd_deposit.c b/src/mint/taler-mint-httpd_deposit.c index d92dd5ef7..eaced51c2 100644 --- a/src/mint/taler-mint-httpd_deposit.c +++ b/src/mint/taler-mint-httpd_deposit.c @@ -131,9 +131,10 @@ TALER_MINT_handler_deposit (struct RequestHandler *rh, if (cond) { GNUNET_break (0); goto EXITIF_exit; } \ } while (0) #define PARSE_DATA(field, addr) \ - EXITIF (GNUNET_OK != request_json_require_nav \ - (connection, json, \ - JNAV_FIELD, field, JNAV_RET_DATA, addr, sizeof (*addr))) + EXITIF (GNUNET_OK != \ + GNUNET_MINT_parse_navigate_json \ + (connection, json, \ + JNAV_FIELD, field, JNAV_RET_DATA, addr, sizeof (*addr))) PARSE_DATA ("coin_pub", &deposit->coin_pub); PARSE_DATA ("denom_pub", &deposit->denom_pub); PARSE_DATA ("ubsig", &ubsig); diff --git a/src/mint/taler-mint-httpd_parsing.c b/src/mint/taler-mint-httpd_parsing.c index 19c88d456..7d3f3b5e6 100644 --- a/src/mint/taler-mint-httpd_parsing.c +++ b/src/mint/taler-mint-httpd_parsing.c @@ -271,44 +271,48 @@ TALER_MINT_parse_post_cleanup_callback (void *con_cls) * @param ... navigation specification (see JNAV_*) * @return GNUNET_YES if navigation was successful * 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 -request_json_require_nav (struct MHD_Connection *connection, - const json_t *root, ...) +GNUNET_MINT_parse_navigate_json (struct MHD_Connection *connection, + const json_t *root, + ...) { va_list argp; - int ignore = GNUNET_NO; - // what's our current path from 'root'? - json_t *path; + int ret; + json_t *path; /* what's our current path from 'root'? */ path = json_array (); - - va_start(argp, root); - - while (1) + va_start (argp, root); + ret = 2; + while (2 == ret) { - int command = va_arg(argp, int); + 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 *); - if (GNUNET_YES == ignore) - break; - json_array_append_new (path, json_string (fname)); - root = json_object_get (root, fname); + + json_array_append_new (path, + json_string (fname)); + root = json_object_get (root, + fname); if (NULL == root) { - /* FIXME: can't IGNORE this return value! */ - (void) TALER_MINT_reply_json_pack (connection, + ret = (MHD_YES == + TALER_MINT_reply_json_pack (connection, MHD_HTTP_BAD_REQUEST, "{s:s,s:o}", "error", "missing field in JSON", "path", - path); - ignore = GNUNET_YES; + path)) + ? GNUNET_NO : GNUNET_SYSERR; break; } } @@ -316,19 +320,21 @@ request_json_require_nav (struct MHD_Connection *connection, case JNAV_INDEX: { int fnum = va_arg(argp, int); - if (GNUNET_YES == ignore) - break; - json_array_append_new (path, json_integer (fnum)); - root = json_array_get (root, fnum); + + json_array_append_new (path, + json_integer (fnum)); + root = json_array_get (root, + fnum); if (NULL == root) { - /* FIXME: can't IGNORE this return value! */ - (void) TALER_MINT_reply_json_pack (connection, + ret = (MHD_YES == + TALER_MINT_reply_json_pack (connection, MHD_HTTP_BAD_REQUEST, "{s:s, s:o}", - "error", "missing index in JSON", - "path", path); - ignore = GNUNET_YES; + "error", + "missing index in JSON", + "path", path)) + ? GNUNET_NO : GNUNET_SYSERR; break; } } @@ -340,36 +346,36 @@ request_json_require_nav (struct MHD_Connection *connection, const char *str; int res; - va_end(argp); - if (GNUNET_YES == ignore) - return GNUNET_NO; str = json_string_value (root); if (NULL == str) { - /* FIXME: can't IGNORE this return value! */ - (void) TALER_MINT_reply_json_pack (connection, + ret = (MHD_YES == + TALER_MINT_reply_json_pack (connection, MHD_HTTP_BAD_REQUEST, "{s:s, s:o}", "error", "string expected", "path", - path); - return GNUNET_NO; + path)) + ? GNUNET_NO : GNUNET_SYSERR; + break; } res = GNUNET_STRINGS_string_to_data (str, strlen (str), where, len); if (GNUNET_OK != res) { - /* FIXME: can't IGNORE this return value! */ - (void) TALER_MINT_reply_json_pack (connection, + 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); - return GNUNET_NO; + "path", + path)) + ? GNUNET_NO : GNUNET_SYSERR; + break; } - return GNUNET_YES; + ret = GNUNET_OK; } break; 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 *); const char *str; - va_end(argp); - if (GNUNET_YES == ignore) - return GNUNET_NO; str = json_string_value (root); if (NULL == str) { - GNUNET_break (0); - return GNUNET_SYSERR; + ret = (MHD_YES == + TALER_MINT_reply_internal_error (connection, + "json_string_value() failed")) + ? GNUNET_NO : GNUNET_SYSERR; + break; } *len = (strlen (str) * 5) / 8; - if (where != NULL) + if (NULL != where) { int res; + *where = GNUNET_malloc (*len); - res = GNUNET_STRINGS_string_to_data (str, strlen (str), - *where, *len); + res = GNUNET_STRINGS_string_to_data (str, + strlen (str), + *where, + *len); if (GNUNET_OK != res) { - /* FIXME: can't IGNORE this return value! */ - (void) TALER_MINT_reply_json_pack (connection, + 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); - return GNUNET_NO; + "path", path)) + ? GNUNET_NO : GNUNET_SYSERR; + break; } } - return GNUNET_OK; + ret = GNUNET_OK; } break; case JNAV_RET_TYPED_JSON: @@ -414,30 +427,35 @@ request_json_require_nav (struct MHD_Connection *connection, int typ = va_arg (argp, int); const json_t **r_json = va_arg (argp, const json_t **); - va_end(argp); - if (GNUNET_YES == ignore) - return GNUNET_NO; - if (typ != -1 && json_typeof (root) != typ) + if ( (-1 != typ) && (json_typeof (root) != typ)) { - /* FIXME: can't IGNORE this return value! */ - (void) 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); - return GNUNET_NO; + 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; - return GNUNET_OK; + ret = GNUNET_OK; } break; 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; } diff --git a/src/mint/taler-mint-httpd_parsing.h b/src/mint/taler-mint-httpd_parsing.h index c725187c5..a03f2b62d 100644 --- a/src/mint/taler-mint-httpd_parsing.h +++ b/src/mint/taler-mint-httpd_parsing.h @@ -30,43 +30,6 @@ #include -/** - * 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 * function realizes an MHD POST processor that will @@ -110,6 +73,47 @@ void 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. * @@ -124,7 +128,7 @@ TALER_MINT_parse_post_cleanup_callback (void *con_cls); * GNUNET_SYSERR on internal error */ int -request_json_require_nav (struct MHD_Connection *connection, +GNUNET_MINT_parse_navigate_json (struct MHD_Connection *connection, const json_t *root, ...); diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c index 1f19aedb2..ab21e814c 100644 --- a/src/mint/taler-mint-httpd_refresh.c +++ b/src/mint/taler-mint-httpd_refresh.c @@ -125,7 +125,7 @@ refresh_accept_denoms (struct MHD_Connection *connection, int res; json_t *new_denoms; - res = request_json_require_nav (connection, root, + res = GNUNET_MINT_parse_navigate_json (connection, root, JNAV_FIELD, "new_denoms", JNAV_RET_TYPED_JSON, JSON_ARRAY, @@ -142,7 +142,7 @@ refresh_accept_denoms (struct MHD_Connection *connection, struct TALER_MINT_DenomKeyIssue *dki; struct TALER_Amount cost; - res = request_json_require_nav (connection, root, + res = GNUNET_MINT_parse_navigate_json (connection, root, JNAV_FIELD, "new_denoms", JNAV_INDEX, (int) i, JNAV_RET_DATA, @@ -210,7 +210,7 @@ check_confirm_signature (struct MHD_Connection *connection, body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_CONFIRM); 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_RET_DATA, &sig, @@ -259,7 +259,7 @@ request_json_require_coin_public_info (struct MHD_Connection *connection, GNUNET_assert (NULL != root); - ret = request_json_require_nav (connection, root, + ret = GNUNET_MINT_parse_navigate_json (connection, root, JNAV_FIELD, "coin_pub", JNAV_RET_DATA, &r_public_info->coin_pub, @@ -267,7 +267,7 @@ request_json_require_coin_public_info (struct MHD_Connection *connection, if (GNUNET_OK != ret) return ret; - ret = request_json_require_nav (connection, root, + ret = GNUNET_MINT_parse_navigate_json (connection, root, JNAV_FIELD, "denom_sig", JNAV_RET_DATA, &r_public_info->denom_sig, @@ -275,7 +275,7 @@ request_json_require_coin_public_info (struct MHD_Connection *connection, if (GNUNET_OK != ret) return ret; - ret = request_json_require_nav (connection, root, + ret = GNUNET_MINT_parse_navigate_json (connection, root, JNAV_FIELD, "denom_pub", JNAV_RET_DATA, &r_public_info->denom_pub, @@ -315,7 +315,7 @@ refresh_accept_melts (struct MHD_Connection *connection, int res; json_t *melt_coins; - res = request_json_require_nav (connection, root, + res = GNUNET_MINT_parse_navigate_json (connection, root, JNAV_FIELD, "melt_coins", JNAV_RET_TYPED_JSON, JSON_ARRAY, @@ -512,7 +512,7 @@ request_json_check_signature (struct MHD_Connection *connection, int res; json_t *el; - res = request_json_require_nav (connection, root, + res = GNUNET_MINT_parse_navigate_json (connection, root, JNAV_FIELD, "sig", JNAV_RET_DATA, &signature, @@ -521,7 +521,7 @@ request_json_check_signature (struct MHD_Connection *connection, if (GNUNET_OK != res) return res; - res = request_json_require_nav (connection, root, + res = GNUNET_MINT_parse_navigate_json (connection, root, JNAV_FIELD, "purpose", JNAV_RET_TYPED_JSON, JSON_INTEGER, @@ -541,7 +541,7 @@ request_json_check_signature (struct MHD_Connection *connection, "error", "signature invalid (purpose)"); } - res = request_json_require_nav (connection, root, + res = GNUNET_MINT_parse_navigate_json (connection, root, JNAV_FIELD, "size", JNAV_RET_TYPED_JSON, JSON_INTEGER, @@ -623,7 +623,7 @@ TALER_MINT_handler_refresh_melt (struct RequestHandler *rh, } /* 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_RET_DATA, &refresh_session_pub, @@ -833,7 +833,7 @@ TALER_MINT_handler_refresh_commit (struct RequestHandler *rh, if ( (GNUNET_NO == res) || (NULL == root) ) return MHD_YES; - res = request_json_require_nav (connection, root, + res = GNUNET_MINT_parse_navigate_json (connection, root, JNAV_FIELD, "session_pub", JNAV_RET_DATA, &refresh_session_pub, @@ -906,7 +906,7 @@ TALER_MINT_handler_refresh_commit (struct RequestHandler *rh, { struct RefreshCommitCoin commit_coin; - res = request_json_require_nav (connection, root, + res = GNUNET_MINT_parse_navigate_json (connection, root, JNAV_FIELD, "coin_evs", JNAV_INDEX, (int) i, JNAV_INDEX, (int) j, @@ -927,7 +927,7 @@ TALER_MINT_handler_refresh_commit (struct RequestHandler *rh, &commit_coin.coin_ev, 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_INDEX, (int) i, JNAV_INDEX, (int) j, @@ -971,7 +971,7 @@ TALER_MINT_handler_refresh_commit (struct RequestHandler *rh, { struct RefreshCommitLink commit_link; - res = request_json_require_nav (connection, root, + res = GNUNET_MINT_parse_navigate_json (connection, root, JNAV_FIELD, "transfer_pubs", JNAV_INDEX, (int) i, JNAV_INDEX, (int) j, @@ -991,7 +991,7 @@ TALER_MINT_handler_refresh_commit (struct RequestHandler *rh, &commit_link.transfer_pub, 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_INDEX, (int) i, JNAV_INDEX, (int) j, @@ -1165,7 +1165,7 @@ TALER_MINT_handler_refresh_reveal (struct RequestHandler *rh, if ( (GNUNET_NO == res) || (NULL == root) ) return MHD_YES; - res = request_json_require_nav (connection, root, + res = GNUNET_MINT_parse_navigate_json (connection, root, JNAV_FIELD, "session_pub", JNAV_RET_DATA, &refresh_session_pub, @@ -1216,7 +1216,7 @@ TALER_MINT_handler_refresh_reveal (struct RequestHandler *rh, struct GNUNET_HashCode transfer_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_INDEX, (int) i, JNAV_INDEX, (int) j, -- cgit v1.2.3