aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/exchange/taler-exchange-httpd_deposit.c148
-rw-r--r--src/extensions/age_restriction/age_restriction.c4
-rw-r--r--src/extensions/extensions.c49
-rw-r--r--src/extensions/policy_brandt_vickrey_auction/policy_brandt_vickrey_auction.c72
-rw-r--r--src/include/taler_extensions.h101
5 files changed, 232 insertions, 142 deletions
diff --git a/src/exchange/taler-exchange-httpd_deposit.c b/src/exchange/taler-exchange-httpd_deposit.c
index 0199802c..033245f5 100644
--- a/src/exchange/taler-exchange-httpd_deposit.c
+++ b/src/exchange/taler-exchange-httpd_deposit.c
@@ -115,6 +115,11 @@ struct DepositContext
const struct TALER_EXCHANGEDB_Deposit *deposit;
/**
+ * Extension handler for policy, maybe NULL.
+ */
+ const struct TALER_Extension *policy_extension;
+
+ /**
* Our timestamp (when we received the request).
* Possibly updated by the transaction if the
* request is idempotent (was repeated).
@@ -156,6 +161,7 @@ deposit_transaction (void *cls,
enum GNUNET_DB_QueryStatus qs;
bool balance_ok;
bool in_conflict;
+ bool blocked_by_policy = false;
qs = TEH_make_coin_known (&dc->deposit->coin,
connection,
@@ -163,11 +169,30 @@ deposit_transaction (void *cls,
mhd_ret);
if (qs < 0)
return qs;
+
+ /* Check and apply policies, if applicable */
+ if (NULL != dc->policy_extension)
+ {
+ const struct TALER_Extension *ext = dc->policy_extension;
+ struct TALER_ExtensionsPolicySerialID serialID;
+ struct GNUNET_TIME_Timestamp deadline;
+ GNUNET_assert (ext->parse_policy_details);
+
+ qs = ext->parse_policy_details (dc->deposit->policy_details,
+ &serialID,
+ &deadline);
+
+ if (qs < 0)
+ return qs;
+
+ blocked_by_policy = true;
+ }
+
qs = TEH_plugin->do_deposit (TEH_plugin->cls,
dc->deposit,
dc->known_coin_id,
&dc->h_payto,
- false, /* FIXME-OEC: extension blocked #7270 */
+ blocked_by_policy,
&dc->exchange_timestamp,
&balance_ok,
&in_conflict);
@@ -208,86 +233,6 @@ deposit_transaction (void *cls,
}
-/**
- * @brief check the provided policy
- *
- * @param[in] policy_details JSON object provided by the client with prolicy
- * @param[out] hc On success, will contain the hash of the normalized policy_details object
- * @param[out] handler_out On success, the handler might provide an output
- * @param[out] error_hint On failure, might contain a hint of the error from the extension
- * @return GNUNET_OK on success.
- */
-enum GNUNET_GenericReturnValue
-check_policy_details (
- json_t *policy_details,
- struct TALER_ExtensionPolicyHashP *hc,
- json_t **handler_out,
- char **error_hint)
-{
- const char *type = NULL;
- const struct TALER_Extension *extension;
- enum GNUNET_GenericReturnValue ret;
-
- *error_hint = NULL;
-
- if ((NULL == policy_details) ||
- (! json_is_object (policy_details)))
- {
- *error_hint = "invalid policy object";
- return GNUNET_SYSERR;
- }
-
- // parse and evaluate the object
- {
- json_t *jtype = json_object_get (
- policy_details,
- "type");
- if (NULL == jtype)
- {
- *error_hint = "no type in policy object";
- return GNUNET_SYSERR;
- }
-
- type = json_string_value (jtype);
- if (NULL == type)
- {
- *error_hint = "invalid type in policy object";
- return GNUNET_SYSERR;
- }
-
- extension = TALER_extensions_get_by_name (type);
- if ((NULL == extension) ||
- (NULL == extension->deposit_handler))
- {
- GNUNET_break (0);
- *error_hint = "no such policy";
- return GNUNET_SYSERR;
- }
-
- ret = extension->deposit_handler (policy_details,
- handler_out);
- if (GNUNET_OK != ret)
- {
- GNUNET_break (0);
- if (NULL != *handler_out)
- {
- *error_hint = json_dumps (*handler_out, JSON_INDENT (2));
- }
- else
- {
- GNUNET_break (1);
- *error_hint = "unknown error with the policy";
- }
- return ret;
- }
- }
-
- TALER_deposit_policy_hash (policy_details,
- hc);
- return GNUNET_OK;
-}
-
-
MHD_RESULT
TEH_handler_deposit (struct MHD_Connection *connection,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
@@ -296,9 +241,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
struct DepositContext dc;
struct TALER_EXCHANGEDB_Deposit deposit;
const char *payto_uri;
- struct TALER_ExtensionPolicyHashP h_policy;
struct TALER_ExtensionPolicyHashP *ph_policy = NULL;
- bool no_policy;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_string ("merchant_payto_uri",
&payto_uri),
@@ -311,8 +254,6 @@ TEH_handler_deposit (struct MHD_Connection *connection,
&deposit.coin.denom_pub_hash),
TALER_JSON_spec_denom_sig ("ub_sig",
&deposit.coin.denom_sig),
- GNUNET_JSON_spec_fixed_auto ("merchant_pub",
- &deposit.merchant_pub),
GNUNET_JSON_spec_fixed_auto ("h_contract_terms",
&deposit.h_contract_terms),
GNUNET_JSON_spec_mark_optional (
@@ -324,17 +265,20 @@ TEH_handler_deposit (struct MHD_Connection *connection,
GNUNET_JSON_spec_timestamp ("timestamp",
&deposit.timestamp),
- /* TODO: this will move to an extension for refunds */
+ /* TODO: refund_deadline and merchant_pub will move into the
+ * extension policy_merchant_refunds */
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_timestamp ("refund_deadline",
&deposit.refund_deadline),
NULL),
+ GNUNET_JSON_spec_fixed_auto ("merchant_pub",
+ &deposit.merchant_pub),
+ GNUNET_JSON_spec_timestamp ("wire_transfer_deadline",
+ &deposit.wire_deadline),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_json ("policy",
&deposit.policy_details),
- &no_policy),
- GNUNET_JSON_spec_timestamp ("wire_transfer_deadline",
- &deposit.wire_deadline),
+ &deposit.no_policy_details),
GNUNET_JSON_spec_end ()
};
struct TALER_MerchantWireHashP h_wire;
@@ -472,29 +416,11 @@ TEH_handler_deposit (struct MHD_Connection *connection,
NULL);
}
- /* TODO: check policy_details */
- if (! no_policy)
+ if (! deposit.no_policy_details)
{
- char *hint;
- json_t *out;
- MHD_RESULT res;
-
- if (GNUNET_OK !=
- check_policy_details (dc.deposit->policy_details,
- &h_policy,
- &out,
- &hint))
- {
- res = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- /* TODO: new error type needed */
- TALER_EC_EXCHANGE_GENERIC_OPERATION_UNKNOWN,
- hint);
- GNUNET_free (hint);
- return res;
- }
-
- ph_policy = &h_policy;
+ TALER_deposit_policy_hash (deposit.policy_details,
+ &deposit.h_policy);
+ ph_policy = &deposit.h_policy;
}
deposit.deposit_fee = dk->meta.fees.deposit;
diff --git a/src/extensions/age_restriction/age_restriction.c b/src/extensions/age_restriction/age_restriction.c
index a1a11e4f..576a6039 100644
--- a/src/extensions/age_restriction/age_restriction.c
+++ b/src/extensions/age_restriction/age_restriction.c
@@ -151,7 +151,9 @@ struct TALER_Extension TE_age_restriction = {
.disable = &age_restriction_disable,
.load_config = &age_restriction_load_config,
.manifest = &age_restriction_manifest,
- .deposit_handler = NULL,
+
+ /* This extension is not a policy extension */
+ .parse_policy_details = NULL,
.http_get_handler = NULL,
.http_post_handler = NULL,
};
diff --git a/src/extensions/extensions.c b/src/extensions/extensions.c
index 02137d31..64574fc2 100644
--- a/src/extensions/extensions.c
+++ b/src/extensions/extensions.c
@@ -353,4 +353,53 @@ TALER_extensions_load_manifests (
}
+enum GNUNET_GenericReturnValue
+TALER_extensions_from_policy_details (
+ const json_t *policy_details,
+ const struct TALER_Extension **extension,
+ char **error_hint)
+{
+ const json_t *jtype;
+ const char *type;
+
+ *extension = NULL;
+ *error_hint = NULL;
+
+ if ((NULL == policy_details) ||
+ (! json_is_object (policy_details)))
+ {
+ *error_hint = "invalid policy object";
+ return GNUNET_SYSERR;
+ }
+
+ jtype = json_object_get (policy_details, "type");
+ if (NULL == jtype)
+ {
+ *error_hint = "no type in policy object";
+ return GNUNET_SYSERR;
+ }
+
+ type = json_string_value (jtype);
+ if (NULL == type)
+ {
+ *error_hint = "invalid type in policy object";
+ return GNUNET_SYSERR;
+ }
+
+ *extension = TALER_extensions_get_by_name (type);
+ if ((NULL == *extension) ||
+ (NULL == (*extension)->parse_policy_details))
+ {
+ GNUNET_break (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Unsupported extension policy '%s' requested\n",
+ type);
+ *extension = NULL;
+ return GNUNET_NO;
+ }
+
+ return GNUNET_OK;
+}
+
+
/* end of extensions.c */
diff --git a/src/extensions/policy_brandt_vickrey_auction/policy_brandt_vickrey_auction.c b/src/extensions/policy_brandt_vickrey_auction/policy_brandt_vickrey_auction.c
index 160250a6..e00f810f 100644
--- a/src/extensions/policy_brandt_vickrey_auction/policy_brandt_vickrey_auction.c
+++ b/src/extensions/policy_brandt_vickrey_auction/policy_brandt_vickrey_auction.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2021-2022 Taler Systems SA
+ Copyright (C) 2022 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
@@ -32,7 +32,7 @@
/* (public) configuration of this extension */
/* TODO: these fields need to be set in the init handler */
-static struct TALER_BrandtVickreyAuction BV_config = {
+static struct TALER_ExtensionPolicyBrandtVickreyAuctionConfig BV_config = {
.max_bidders = 10,
.max_prices = 10,
.auction_fee = {
@@ -497,7 +497,7 @@ static json_t *
auction_manifest (
const struct TALER_Extension *ext)
{
- struct TALER_BrandtVickreyAuction *conf = ext->config;
+ struct TALER_ExtensionPolicyBrandtVickreyAuctionConfig *conf = ext->config;
GNUNET_assert (conf);
json_t *config = GNUNET_JSON_PACK (
@@ -589,20 +589,66 @@ auction_http_post_handler (
/**
- * @brief implements the TALER_Extensions.deposit_handler interface.
+ * @brief implements the TALER_Extensions.parse_policy_details interface.
*
- * @param[in] input JSON input from the client during a deposit request
- * @param[out] output by this extension
+ * @param[in] input The policy_details for this handler during deposit
+ * @param[out] serial On success will contain the serial-ID under which the
+ * @param[out] deadline On success will contain a deadline, might be "forever"
+ * exchange should store the policy_details in the policy_details table.
* @return GNUNET_OK if the request was OK
*/
enum GNUNET_GenericReturnValue
-auction_deposit_handler (
- json_t *input,
- json_t **output)
+auction_parse_policy_details (
+ const json_t *input,
+ struct TALER_ExtensionsPolicySerialID *serial,
+ struct GNUNET_TIME_Timestamp *deadline)
{
- /* TODO */
- *output = NULL;
- return GNUNET_OK;
+ enum GNUNET_GenericReturnValue ret = GNUNET_NO;
+ struct GNUNET_CRYPTO_EddsaPublicKey pub;
+ struct GNUNET_HashCode hc;
+ struct GNUNET_JSON_Specification spec[] = {
+ /* We ignore the "type" field as it must have been parsed already upstream
+ * - or this handler wouldn't have been called in first place. */
+ GNUNET_JSON_spec_fixed_auto ("bidder_pub", &pub),
+ GNUNET_JSON_spec_fixed_auto ("h_auction", &hc),
+ GNUNET_JSON_spec_timestamp ("deadline", deadline),
+ GNUNET_JSON_spec_end (),
+ };
+
+ GNUNET_assert (serial);
+ GNUNET_assert (deadline);
+
+ do {
+ ret = GNUNET_JSON_parse (input,
+ spec,
+ NULL,
+ NULL);
+
+ if (GNUNET_OK != ret)
+ break;
+
+ /* FIXME: check the deadline */
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ LOG_PREFIX "check of deadline %ld not implemented!\n",
+ deadline->abs_time.abs_value_us);
+
+ /* Create serial as H(bidder_pub, h_auction) */
+ {
+ struct GNUNET_HashContext *hc = GNUNET_CRYPTO_hash_context_start ();
+ GNUNET_CRYPTO_hash_context_read (hc,
+ &pub,
+ sizeof(pub));
+ GNUNET_CRYPTO_hash_context_read (hc,
+ &hc,
+ sizeof(hc));
+ GNUNET_CRYPTO_hash_context_finish (hc,
+ &serial->hash);
+ }
+
+ ret = GNUNET_OK;
+ } while(0);
+
+ return ret;
}
@@ -617,7 +663,7 @@ struct TALER_Extension TE_auction_brandt = {
.disable = &auction_disable,
.load_config = &auction_load_config,
.manifest = &auction_manifest,
- .deposit_handler = &auction_deposit_handler,
+ .parse_policy_details = &auction_parse_policy_details,
.http_get_handler = &auction_http_get_handler,
.http_post_handler = &auction_http_post_handler,
};
diff --git a/src/include/taler_extensions.h b/src/include/taler_extensions.h
index 646d5a84..d76de25e 100644
--- a/src/include/taler_extensions.h
+++ b/src/include/taler_extensions.h
@@ -25,17 +25,21 @@
#include "taler_crypto_lib.h"
#include "taler_json_lib.h"
#include "taler_mhd_lib.h"
+#include "taler_exchangedb_plugin.h"
#define TALER_EXTENSION_SECTION_PREFIX "exchange-extension-"
enum TALER_Extension_Type
{
- TALER_Extension_AgeRestriction = 0,
- TALER_Extension_PolicyMerchantRefund = 1,
- TALER_Extension_PolicyBrandtVickeryAuction = 2,
- TALER_Extension_PolicyEscrowedPayment = 3,
- TALER_Extension_MaxPredefined = 4 // Must be last of the predefined
+ TALER_Extension_PolicyNull = 0,
+
+ TALER_Extension_AgeRestriction = 1,
+ TALER_Extension_PolicyMerchantRefund = 2,
+ TALER_Extension_PolicyBrandtVickeryAuction = 3,
+ TALER_Extension_PolicyEscrowedPayment = 4,
+
+ TALER_Extension_MaxPredefined = 5 // Must be last of the predefined
};
@@ -50,6 +54,15 @@ struct TALER_Extensions
};
/*
+ * @brief Serial ID under which the policy details to an deposit are stored in
+ * the policy_details table.
+ */
+struct TALER_ExtensionsPolicySerialID
+{
+ struct GNUNET_HashCode hash;
+};
+
+/*
* @brief Represents the implementation of an extension.
*
* An "Extension" is an optional feature for the Exchange.
@@ -151,22 +164,30 @@ struct TALER_Extension
json_t *(*manifest)(
const struct TALER_Extension *ext);
+ /* =========================
+ * Policy related handlers
+ * =========================
+ */
/**
- * @brief Handler for /{batch}-deposit requests. Can be NULL.
+ * @brief Handler to check a policy. Can be NULL;
*
* When a deposit request refers to this extension in its policy
* (see https://docs.taler.net/core/api-exchange.html#deposit), this handler
- * will be called during the deposit operation.
+ * will be called before the deposit transaction.
*
- * @param[in] input The policy/extension specific data, provided by the client in
- * the policy-field of the deposit request.
- * @param[out] output Potential output by the extension to be provided to the
- * client as part of the response to the deposit request. Can be NULL.
+ * @param[in] policy_details Details about the policy, provided by the client
+ * during a deposit request.
+ * @param[out] serial On success, will contain the serial-ID under which the
+ * exchange should save the policy_details in the deposit table.
+ * @param[out] deadline On sucess, set to the deadline until the policy must
+ * be fulfilled. Might be "forever". This value is used by an external
+ * mechanism to detect timeouts.
* @return GNUNET_OK if the data was accepted by the extension.
*/
- enum GNUNET_GenericReturnValue (*deposit_handler)(
- json_t *input,
- json_t **output);
+ enum GNUNET_GenericReturnValue (*parse_policy_details)(
+ const json_t *policy_details,
+ struct TALER_ExtensionsPolicySerialID *serial,
+ struct GNUNET_TIME_Timestamp *deadline);
/**
* @brief Handler for POST-requests to the /policy/$name endpoint. Can be NULL.
@@ -367,18 +388,64 @@ TALER_extensions_get_age_restriction_mask ();
/*
+ * ===================================
+ * Policy extensions related functions
+ * ===================================
+ */
+
+/*
+ * @brief Finds the extension for a given policy
+ *
+ * @param[in] policy_details JSON of the policy detail from a deposit request
+ * @param[out] extension On GNUNET_OK, the exentions handling the given policy
+ * @param[out] error_hint On GNUNET_SYSERR, will contain a hint for the reason why it failed
+ * @return GNUNET_OK on success, with *extension set to the correct extension.
+ * GNUNET_NO, when no extension was found. GNUNET_SYSERR when the JSON was
+ * invalid, with *error_hint maybe non-NULL.
+ */
+enum GNUNET_GenericReturnValue
+TALER_extensions_from_policy_details (
+ const json_t *policy_details,
+ const struct TALER_Extension **extension,
+ char **error_hint);
+
+/*
* ================================
- * Brandt-Vickrey Auctions
+ * Merchant refund policy
+ * ================================
+ */
+struct TALER_ExtensionPolicyMerchantRefundPolicyConfig
+{
+ struct GNUNET_TIME_Relative max_timeout;
+};
+
+/*
+ * ================================
+ * Brandt-Vickrey Auctions policy
* ================================
*/
/*
- * @brief Configuration for Brandt-Vickrey auctions
+ * @brief Configuration for Brandt-Vickrey auctions policy
*/
-struct TALER_BrandtVickreyAuction
+struct TALER_ExtensionPolicyBrandtVickreyAuctionConfig
{
uint16_t max_bidders;
uint16_t max_prices;
struct TALER_Amount auction_fee;
};
+
+/*
+ * ================================
+ * Escrowed Payments policy
+ * ================================
+ */
+/*
+ * @brief Configuration for escrowed payments policy
+ */
+struct TALER_ExtensionPolicyEscrowedPaymentsConfig
+{
+ struct GNUNET_TIME_Relative max_timeout;
+};
+
#endif