diff options
author | Christian Grothoff <christian@grothoff.org> | 2015-01-29 15:45:05 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2015-01-29 15:45:05 +0100 |
commit | 4a27969e5e439fb0f277dcf9f0461817d83e36b4 (patch) | |
tree | 9dbcea3e7bb5723438a1817a9a8c840f55ce92f2 /src/mint/taler-mint-httpd_parsing.c | |
parent | a284561298af60ade27eb18008f29ebf63ac62b7 (diff) |
make TALER_MINT_parse_json_data more expressive, add RSA types as well
Diffstat (limited to 'src/mint/taler-mint-httpd_parsing.c')
-rw-r--r-- | src/mint/taler-mint-httpd_parsing.c | 643 |
1 files changed, 409 insertions, 234 deletions
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 */ |