diff options
author | Christian Grothoff <christian@grothoff.org> | 2023-04-30 23:37:01 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2023-05-01 22:34:35 +0200 |
commit | faca037018820ba3c21724c7f6ab41a72206e4ff (patch) | |
tree | b8e383ae5375e1594376f9f384be2cbddf4a5fb1 | |
parent | 75f75c4a51c4700da9bde18cc9a9b5d9df1e8457 (diff) |
expose TALER_EXCHANGE_parse_accounts() in external API
m--------- | contrib/gana | 0 | ||||
-rw-r--r-- | src/include/taler_exchange_service.h | 27 | ||||
-rw-r--r-- | src/lib/exchange_api_common.c | 192 | ||||
-rw-r--r-- | src/lib/exchange_api_wire.c | 208 |
4 files changed, 231 insertions, 196 deletions
diff --git a/contrib/gana b/contrib/gana -Subproject 5cfe18c5bbfd404a5f7cf27a78577c881ddb9eb +Subproject d831c7f72a5030e20efb4ada7babc103ccd01fa diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h index f9330ec5c..fc5fb284b 100644 --- a/src/include/taler_exchange_service.h +++ b/src/include/taler_exchange_service.h @@ -910,6 +910,33 @@ struct TALER_EXCHANGE_WireAccount /** + * Parse array of @a accounts of the exchange into @a was. + * + * @param master_pub master public key of the exchange, NULL to not verify signatures + * @param accounts array of accounts to parse + * @param[out] was where to write the result (already allocated) + * @param was_length length of the @a was array, must match the length of @a accounts + * @return #GNUNET_OK if parsing @a accounts succeeded + */ +enum GNUNET_GenericReturnValue +TALER_EXCHANGE_parse_accounts (const struct TALER_MasterPublicKeyP *master_pub, + const json_t *accounts, + struct TALER_EXCHANGE_WireAccount was[], + unsigned int was_length); + + +/** + * Free data within @a was, but not @a was itself. + * + * @param was array of wire account data + * @param was_len length of the @a was array + */ +void +TALER_EXCHANGE_free_accounts (struct TALER_EXCHANGE_WireAccount *was, + unsigned int was_len); + + +/** * Response to a /wire request. */ struct TALER_EXCHANGE_WireResponse diff --git a/src/lib/exchange_api_common.c b/src/lib/exchange_api_common.c index b895bf9a8..285a5292a 100644 --- a/src/lib/exchange_api_common.c +++ b/src/lib/exchange_api_common.c @@ -2194,4 +2194,196 @@ TALER_EXCHANGE_verify_deposit_signature_ ( } +/** + * Parse account restriction in @a jrest into @a rest. + * + * @param jrest array of account restrictions in JSON + * @param[out] resta_len set to length of @a resta + * @param[out] resta account restriction array to set + * @return #GNUNET_OK on success + */ +static enum GNUNET_GenericReturnValue +parse_restrictions (const json_t *jresta, + unsigned int *resta_len, + struct TALER_EXCHANGE_AccountRestriction **resta) +{ + if (! json_is_array (jresta)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + *resta_len = json_array_size (jresta); + if (0 == *resta_len) + { + /* no restrictions, perfectly OK */ + *resta = NULL; + return GNUNET_OK; + } + *resta = GNUNET_new_array (*resta_len, + struct TALER_EXCHANGE_AccountRestriction); + for (unsigned int i = 0; i<*resta_len; i++) + { + const json_t *jr = json_array_get (jresta, + i); + struct TALER_EXCHANGE_AccountRestriction *ar = &(*resta)[i]; + const char *type = json_string_value (json_object_get (jr, + "type")); + + if (NULL == type) + { + GNUNET_break (0); + goto fail; + } + if (0 == strcmp (type, + "deny")) + { + ar->type = TALER_EXCHANGE_AR_DENY; + continue; + } + if (0 == strcmp (type, + "regex")) + { + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_string ( + "payto_regex", + &ar->details.regex.posix_egrep), + GNUNET_JSON_spec_string ( + "human_hint", + &ar->details.regex.human_hint), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_object_const ( + "human_hint_i18n", + &ar->details.regex.human_hint_i18n), + NULL), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (jr, + spec, + NULL, NULL)) + { + /* bogus reply */ + GNUNET_break_op (0); + goto fail; + } + ar->type = TALER_EXCHANGE_AR_REGEX; + continue; + } + /* unsupported type */ + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +fail: + GNUNET_free (*resta); + *resta_len = 0; + return GNUNET_SYSERR; +} + + +enum GNUNET_GenericReturnValue +TALER_EXCHANGE_parse_accounts (const struct TALER_MasterPublicKeyP *master_pub, + const json_t *accounts, + struct TALER_EXCHANGE_WireAccount was[], + unsigned int was_length) +{ + memset (was, + 0, + sizeof (struct TALER_EXCHANGE_WireAccount) * was_length); + GNUNET_assert (was_length == + json_array_size (accounts)); + for (unsigned int i = 0; + i<was_length; + i++) + { + struct TALER_EXCHANGE_WireAccount *wa = &was[i]; + json_t *credit_restrictions; + json_t *debit_restrictions; + struct GNUNET_JSON_Specification spec_account[] = { + GNUNET_JSON_spec_string ("payto_uri", + &wa->payto_uri), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_string ("conversion_url", + &wa->conversion_url), + NULL), + GNUNET_JSON_spec_json ("credit_restrictions", + &credit_restrictions), + GNUNET_JSON_spec_json ("debit_restrictions", + &debit_restrictions), + GNUNET_JSON_spec_fixed_auto ("master_sig", + &wa->master_sig), + GNUNET_JSON_spec_end () + }; + json_t *account; + + account = json_array_get (accounts, + i); + if (GNUNET_OK != + GNUNET_JSON_parse (account, + spec_account, + NULL, NULL)) + { + /* bogus reply */ + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + { + char *err; + + err = TALER_payto_validate (wa->payto_uri); + if (NULL != err) + { + GNUNET_break_op (0); + GNUNET_free (err); + return GNUNET_SYSERR; + } + } + + if ( (NULL != master_pub) && + (GNUNET_OK != + TALER_exchange_wire_signature_check (wa->payto_uri, + wa->conversion_url, + debit_restrictions, + credit_restrictions, + master_pub, + &wa->master_sig)) ) + { + /* bogus reply */ + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + if ( (GNUNET_OK != + parse_restrictions (credit_restrictions, + &wa->credit_restrictions_length, + &wa->credit_restrictions)) || + (GNUNET_OK != + parse_restrictions (debit_restrictions, + &wa->debit_restrictions_length, + &wa->debit_restrictions)) ) + { + /* bogus reply */ + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + GNUNET_JSON_parse_free (spec_account); + } /* end 'for all accounts */ + return GNUNET_OK; +} + + +void +TALER_EXCHANGE_free_accounts (struct TALER_EXCHANGE_WireAccount *was, + unsigned int was_len) +{ + for (unsigned int i = 0; i<was_len; i++) + { + struct TALER_EXCHANGE_WireAccount *wa = &was[i]; + + GNUNET_free (wa->credit_restrictions); + GNUNET_free (wa->debit_restrictions); + } +} + + /* end of exchange_api_common.c */ diff --git a/src/lib/exchange_api_wire.c b/src/lib/exchange_api_wire.c index 498265282..f38ca86b6 100644 --- a/src/lib/exchange_api_wire.c +++ b/src/lib/exchange_api_wire.c @@ -174,114 +174,6 @@ parse_fees (const struct TALER_MasterPublicKeyP *master_pub, /** - * Parse account restriction in @a jrest into @a rest. - * - * @param jrest array of account restrictions in JSON - * @param[out] resta_len set to length of @a resta - * @param[out] resta account restriction array to set - * @return #GNUNET_OK on success - */ -static enum GNUNET_GenericReturnValue -parse_restrictions (const json_t *jresta, - unsigned int *resta_len, - struct TALER_EXCHANGE_AccountRestriction **resta) -{ - if (! json_is_array (jresta)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - *resta_len = json_array_size (jresta); - if (0 == *resta_len) - { - /* no restrictions, perfectly OK */ - *resta = NULL; - return GNUNET_OK; - } - *resta = GNUNET_new_array (*resta_len, - struct TALER_EXCHANGE_AccountRestriction); - for (unsigned int i = 0; i<*resta_len; i++) - { - const json_t *jr = json_array_get (jresta, - i); - struct TALER_EXCHANGE_AccountRestriction *ar = &(*resta)[i]; - const char *type = json_string_value (json_object_get (jr, - "type")); - - if (NULL == type) - { - GNUNET_break (0); - goto fail; - } - if (0 == strcmp (type, - "deny")) - { - ar->type = TALER_EXCHANGE_AR_DENY; - continue; - } - if (0 == strcmp (type, - "regex")) - { - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_string ( - "payto_regex", - &ar->details.regex.posix_egrep), - GNUNET_JSON_spec_string ( - "human_hint", - &ar->details.regex.human_hint), - GNUNET_JSON_spec_mark_optional ( - GNUNET_JSON_spec_object_const ( - "human_hint_i18n", - &ar->details.regex.human_hint_i18n), - NULL), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse (jr, - spec, - NULL, NULL)) - { - /* bogus reply */ - GNUNET_break_op (0); - goto fail; - } - ar->type = TALER_EXCHANGE_AR_REGEX; - continue; - } - /* unsupported type */ - GNUNET_break (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; -fail: - GNUNET_free (*resta); - *resta_len = 0; - return GNUNET_SYSERR; -} - - -/** - * Free data within @a was, but not @a was itself. - * - * @param was array of wire account data - * @param was_len length of the @a was array - */ -static void -free_accounts (struct TALER_EXCHANGE_WireAccount *was, - unsigned int was_len) -{ - for (unsigned int i = 0; i<was_len; i++) - { - struct TALER_EXCHANGE_WireAccount *wa = &was[i]; - - GNUNET_free (wa->credit_restrictions); - GNUNET_free (wa->debit_restrictions); - } -} - - -/** * Function called when we're done processing the * HTTP /wire request. * @@ -383,101 +275,25 @@ handle_wire_finished (void *cls, { struct TALER_EXCHANGE_WireAccount was[wr.details.ok.accounts_len]; - memset (was, - 0, - sizeof (was)); wr.details.ok.accounts = was; - for (unsigned int i = 0; - i<wr.details.ok.accounts_len; - i++) + if (GNUNET_OK != + TALER_EXCHANGE_parse_accounts (&master_pub, + accounts, + was, + wr.details.ok.accounts_len)) { - struct TALER_EXCHANGE_WireAccount *wa = &was[i]; - json_t *credit_restrictions; - json_t *debit_restrictions; - struct GNUNET_JSON_Specification spec_account[] = { - GNUNET_JSON_spec_string ("payto_uri", - &wa->payto_uri), - GNUNET_JSON_spec_mark_optional ( - GNUNET_JSON_spec_string ("conversion_url", - &wa->conversion_url), - NULL), - GNUNET_JSON_spec_json ("credit_restrictions", - &credit_restrictions), - GNUNET_JSON_spec_json ("debit_restrictions", - &debit_restrictions), - GNUNET_JSON_spec_fixed_auto ("master_sig", - &wa->master_sig), - GNUNET_JSON_spec_end () - }; - json_t *account; - - account = json_array_get (accounts, - i); - if (GNUNET_OK != - GNUNET_JSON_parse (account, - spec_account, - NULL, NULL)) - { - /* bogus reply */ - GNUNET_break_op (0); - wr.hr.http_status = 0; - wr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - break; - } - { - char *err; - - err = TALER_payto_validate (wa->payto_uri); - if (NULL != err) - { - GNUNET_break_op (0); - wr.hr.http_status = 0; - wr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - GNUNET_free (err); - break; - } - } - - if (GNUNET_OK != - TALER_exchange_wire_signature_check (wa->payto_uri, - wa->conversion_url, - debit_restrictions, - credit_restrictions, - &master_pub, - &wa->master_sig)) - { - /* bogus reply */ - GNUNET_break_op (0); - wr.hr.http_status = 0; - wr.hr.ec = TALER_EC_EXCHANGE_WIRE_SIGNATURE_INVALID; - break; - } - if ( (GNUNET_OK != - parse_restrictions (credit_restrictions, - &wa->credit_restrictions_length, - &wa->credit_restrictions)) || - (GNUNET_OK != - parse_restrictions (debit_restrictions, - &wa->debit_restrictions_length, - &wa->debit_restrictions)) ) - { - /* bogus reply */ - GNUNET_break_op (0); - wr.hr.http_status = 0; - wr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - break; - } - GNUNET_JSON_parse_free (spec_account); - } /* end 'for all accounts */ - if ( (0 != wr.hr.http_status) && - (NULL != wh->cb) ) + GNUNET_break_op (0); + wr.hr.http_status = 0; + wr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + } + else if (NULL != wh->cb) { wh->cb (wh->cb_cls, &wr); wh->cb = NULL; } - free_accounts (was, - wr.details.ok.accounts_len); + TALER_EXCHANGE_free_accounts (was, + wr.details.ok.accounts_len); } /* end of 'parse accounts */ free_fees (fbm, wr.details.ok.fees_len); |