diff options
-rw-r--r-- | src/backend/taler-merchant-httpd_post-orders-ID-pay.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c index 14edfd55..2bdf891f 100644 --- a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c +++ b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c @@ -25,6 +25,8 @@ * @author Florian Dold */ #include "platform.h" +#include <gnunet/gnunet_json_lib.h> +#include <stdint.h> #include <taler/taler_dbevents.h> #include <taler/taler_signatures.h> #include <taler/taler_json_lib.h> @@ -46,6 +48,12 @@ #define MAX_COIN_ALLOWED_COINS 1024 /** + * TODO: What is a good value for this? + * Maximum number of tokens that we allow per transaction + */ +#define MAX_TOKEN_ALLOWED_TOKENS 128 + +/** * How often do we ask the exchange again about our * KYC status? Very rarely, as if the user actively * changes it, we should usually notice anyway. @@ -202,6 +210,36 @@ struct DepositConfirmation }; +struct TokenUseConfirmation +{ + + /** + * Slug of the token family this token belongs to. + */ + char *slug; + + /** + * Signature on the deposit request made using the token private key. + */ + struct TALER_TokenUseSignature sig; + + /** + * Public key of the token. + */ + struct TALER_TokenUsePublicKey pub; + + /** + * Unblinded signature done by the merchant. + */ + struct TALER_TokenIssueSignature unblinded_sig; + + /** + * Hash of the token issue public key associated with this token. + */ + struct TALER_TokenIssuePublicKeyHash h_issue; + +}; + /** * Information kept during a pay request for each exchange. @@ -274,6 +312,11 @@ struct PayContext struct DepositConfirmation *dc; /** + * Array with @e tokens_cnt tokens we are using. + */ + struct TokenUseConfirmation *tokens; + + /** * MHD connection to return to */ struct MHD_Connection *connection; @@ -302,6 +345,11 @@ struct PayContext struct MHD_Response *response; /** + * Index of selected choice in the @e contract_terms choices array. + */ + int64_t choice_index; + + /** * Our contract (or NULL if not available). */ json_t *contract_terms; @@ -421,6 +469,12 @@ struct PayContext size_t coins_cnt; /** + * Number of tokens this payment uses. Length + * of the @e tokens array. + */ + size_t tokens_cnt; + + /** * Number of exchanges involved in the payment. Length * of the @e eg array. */ @@ -2405,6 +2459,7 @@ phase_parse_pay (struct PayContext *pc) { const char *session_id = NULL; const json_t *coins; + const json_t *tokens; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_array_const ("coins", &coins), @@ -2412,6 +2467,14 @@ phase_parse_pay (struct PayContext *pc) GNUNET_JSON_spec_string ("session_id", &session_id), NULL), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_int64 ("choice_index", + &pc->choice_index), + NULL), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_array_const ("tokens", + &tokens), + NULL), GNUNET_JSON_spec_end () }; @@ -2456,10 +2519,26 @@ phase_parse_pay (struct PayContext *pc) return; } + pc->tokens_cnt = json_array_size (tokens); + if (pc->tokens_cnt > MAX_TOKEN_ALLOWED_TOKENS) + { + GNUNET_break_op (0); + pay_end (pc, + TALER_MHD_reply_with_error ( + pc->connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + "'tokens' array too long")); + return; + } + /* note: 1 coin = 1 deposit confirmation expected */ pc->dc = GNUNET_new_array (pc->coins_cnt, struct DepositConfirmation); + pc->tokens = GNUNET_new_array (pc->tokens_cnt, + struct TokenUseConfirmation); + /* This loop populates the array 'dc' in 'pc' */ { unsigned int coins_index; @@ -2574,6 +2653,57 @@ phase_parse_pay (struct PayContext *pc) } } } + + /* This look populates the array 'tokens' in 'pc' */ + { + unsigned int tokens_index; + json_t *token; + + json_array_foreach (tokens, tokens_index, token) + { + struct TokenUseConfirmation *tuc = &pc->tokens[tokens_index]; + struct GNUNET_JSON_Specification ispec[] = { + GNUNET_JSON_spec_fixed_auto ("token_sig", + &tuc->sig), + GNUNET_JSON_spec_fixed_auto ("token_pub", + &tuc->pub), + // TALER_JSON_spec_denom_sig ("ub_sig", + // &tuc->unblinded_sig), + GNUNET_JSON_spec_fixed_auto ("h_issue", + &tuc->h_issue), + GNUNET_JSON_spec_end () + }; + enum GNUNET_GenericReturnValue res; + + res = TALER_MHD_parse_json_data (pc->connection, + token, + ispec); + if (GNUNET_YES != res) + { + GNUNET_break_op (0); + pay_end (pc, + (GNUNET_NO == res) + ? MHD_YES + : MHD_NO); + return; + } + for (unsigned int j = 0; j<tokens_index; j++) + { + if (0 == + GNUNET_memcmp (&tuc->pub, + &pc->tokens[j].pub)) + { + GNUNET_break_op (0); + pay_end (pc, + TALER_MHD_reply_with_error (pc->connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + "duplicate token in list")); + return; + } + } + } + } pc->phase = PP_CHECK_CONTRACT; } |