diff options
author | Christian Blättler <blatc2@bfh.ch> | 2024-06-06 14:03:39 +0200 |
---|---|---|
committer | Christian Blättler <blatc2@bfh.ch> | 2024-06-06 14:03:39 +0200 |
commit | 6f4486ffac5db888832e125ab4a9fbd673b69369 (patch) | |
tree | 9668b2f721f3a4cc3803dc35bf87f86769fd6ba0 /src/backend/taler-merchant-httpd_private-post-orders.c | |
parent | 3fa00294bee477ca58c9195baf39e0397c9b1b6e (diff) |
check validity period of token families and keys
Diffstat (limited to 'src/backend/taler-merchant-httpd_private-post-orders.c')
-rw-r--r-- | src/backend/taler-merchant-httpd_private-post-orders.c | 84 |
1 files changed, 70 insertions, 14 deletions
diff --git a/src/backend/taler-merchant-httpd_private-post-orders.c b/src/backend/taler-merchant-httpd_private-post-orders.c index 9eb63516..e8332c70 100644 --- a/src/backend/taler-merchant-httpd_private-post-orders.c +++ b/src/backend/taler-merchant-httpd_private-post-orders.c @@ -1537,6 +1537,23 @@ set_token_family (struct OrderContext *oc, return GNUNET_SYSERR; } + struct GNUNET_TIME_Timestamp now = GNUNET_TIME_timestamp_get (); + + /* Verify that the token family is valid right now. */ + if (GNUNET_TIME_timestamp_cmp (key_details.token_family.valid_after, >, now) || + GNUNET_TIME_timestamp_cmp (key_details.token_family.valid_before, <=, now)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Token family expired or not yet valid\n"); + reply_with_error (oc, + /* TODO: HTTP Status Code GONE would be more elegant, + but that is already used to indicate that a product is out of stock. */ + MHD_HTTP_CONFLICT, + TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_TOKEN_FAMILY_NOT_VALID, + key_details.token_family.slug); + return GNUNET_SYSERR; + } + /* slug is not needed */ GNUNET_free (key_details.token_family.slug); @@ -1577,7 +1594,7 @@ set_token_family (struct OrderContext *oc, if (NULL == key_details.pub.public_key) { /* There is no matching key for this token family yet. */ - /* We have to generate one. */ + /* We have to generate a fresh key pair. */ /* If public key is NULL, private key must also be NULL */ GNUNET_assert (NULL == key_details.priv.private_key); @@ -1585,10 +1602,28 @@ set_token_family (struct OrderContext *oc, struct GNUNET_CRYPTO_BlindSignPrivateKey *priv; struct GNUNET_CRYPTO_BlindSignPublicKey *pub; struct GNUNET_TIME_Timestamp valid_before = - GNUNET_TIME_absolute_to_timestamp( + GNUNET_TIME_absolute_to_timestamp ( GNUNET_TIME_absolute_add (min_valid_after.abs_time, key_details.token_family.duration)); + if (GNUNET_TIME_timestamp_cmp (min_valid_after, + <, + key_details.token_family.valid_after)) + { + /* If key would start before validity of token family, + set valid_after of key to the value of the token family. */ + min_valid_after = key_details.token_family.valid_after; + } + + if (GNUNET_TIME_timestamp_cmp (valid_before, + >, + key_details.token_family.valid_before)) + { + /* If key would end after validity of token family, + set valid_before of key to the value of the token family. */ + valid_before = key_details.token_family.valid_before; + } + GNUNET_CRYPTO_blind_sign_keys_create (&priv, &pub, /* TODO: Make cipher and key length configurable */ @@ -1603,11 +1638,11 @@ set_token_family (struct OrderContext *oc, }; iqs = TMH_db->insert_token_family_key (TMH_db->cls, - slug, - &token_pub, - &token_priv, - min_valid_after, - valid_before); + slug, + &token_pub, + &token_priv, + min_valid_after, + valid_before); GNUNET_CRYPTO_blind_sign_priv_decref (priv); @@ -1729,6 +1764,7 @@ serialize_order (struct OrderContext *oc) struct TALER_MerchantContractTokenFamilyKey key = family->keys[j]; json_t *jkey = GNUNET_JSON_PACK ( + /* TODO: Remove h_pub. */ GNUNET_JSON_pack_data_auto ("h_pub", &key.pub.public_key->pub_key_hash), GNUNET_JSON_pack_allow_null( @@ -1970,8 +2006,8 @@ set_max_fee (struct OrderContext *oc) static bool set_exchanges (struct OrderContext *oc) { - /* Note: re-building 'oc->exchanges' every time here might be a tad - expensive; could likely consider caching the result if it starts to + /* Note: re-building 'oc->set_exchanges.exchanges' every time here might be a + tad expensive; could likely consider caching the result if it starts to matter. */ if (NULL == oc->set_exchanges.exchanges) { @@ -2042,7 +2078,8 @@ parse_order (struct OrderContext *oc) * mostly because in GNUnet relative times can't * be negative. */ bool no_fee; - /* TODO: Check if the parsing of the nonce field is missing here. */ + /* TODO: Move "amount" field to choices. This entails moving the + stefan-base fee calculation to the parse_choices phase. */ struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_string ("version", @@ -2504,10 +2541,14 @@ parse_choices (struct OrderContext *oc) const json_t *jinputs; const json_t *joutputs; struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_array_const ("inputs", - &jinputs), - GNUNET_JSON_spec_array_const ("outputs", - &joutputs), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_array_const ("inputs", + &jinputs), + NULL), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_array_const ("outputs", + &joutputs), + NULL), GNUNET_JSON_spec_end () }; enum GNUNET_GenericReturnValue ret; @@ -2529,6 +2570,18 @@ parse_choices (struct OrderContext *oc) return; } + if (0 == json_array_size(jinputs) && 0 == json_array_size(joutputs)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Choice #%u must have at least one input or output\n", + i); + reply_with_error (oc, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + "choice"); + return; + } + { // TODO: Maybe move to a separate function const json_t *jinput; @@ -2545,6 +2598,8 @@ parse_choices (struct OrderContext *oc) &kind), GNUNET_JSON_spec_string ("token_family_slug", &input.details.token.token_family_slug), + /* TODO: Remove valid_after field for inputs, + use current system time instead. */ GNUNET_JSON_spec_timestamp ("valid_after", &input.details.token.valid_after), GNUNET_JSON_spec_mark_optional ( @@ -2620,6 +2675,7 @@ parse_choices (struct OrderContext *oc) &kind), GNUNET_JSON_spec_string ("token_family_slug", &output.details.token.token_family_slug), + /* TODO: Make valid_after optional, default to current system time. */ GNUNET_JSON_spec_timestamp ("valid_after", &output.details.token.valid_after), GNUNET_JSON_spec_mark_optional ( |