diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c index 2e0058ba9..b435ee4ae 100644 --- a/src/exchange/taler-exchange-httpd.c +++ b/src/exchange/taler-exchange-httpd.c @@ -147,6 +147,25 @@ int TEH_check_invariants_flag; */ bool TEH_suicide; +/** + * The global manifest with the list supported extensions, sorted by + * TALER_Extension_Type. + **/ +const struct TALER_Extension TEH_extensions[TALER_Extension_Max] = { + [TALER_Extension_Peer2Peer] = { + .type = TALER_Extension_Peer2Peer, + .name = "peer2peer", + .critical = false, + .config = NULL, // disabled per default + }, + [TALER_Extension_AgeRestriction] = { + .type = TALER_Extension_AgeRestriction, + .name = "age_restriction", + .critical = false, + .config = NULL, // disabled per default + }, +}; + /** * Value to return from main() */ @@ -185,26 +204,6 @@ struct GNUNET_CURL_Context *TEH_curl_ctx; */ static struct GNUNET_CURL_RescheduleContext *exchange_curl_rc; -/** - * TEH_extensions is the global manifest with the list supported extensions, - * sorted by TALER_Extension_Type. - **/ -static struct TALER_Extension TEH_extensions[TALER_Extension_Max] = { - [TALER_Extension_Peer2Peer] = { - .type = TALER_Extension_Peer2Peer, - .name = "peer2peer", - .critical = false, - .config = NULL, // == disabled - }, - [TALER_Extension_AgeRestriction] = { - .type = TALER_Extension_AgeRestriction, - .name = "age_restriction", - .critical = false, - .config = NULL, // == disabled - }, -}; - - /** * Signature of functions that handle operations on coins. * diff --git a/src/exchange/taler-exchange-httpd.h b/src/exchange/taler-exchange-httpd.h index cad74d2ed..fa47af6f4 100644 --- a/src/exchange/taler-exchange-httpd.h +++ b/src/exchange/taler-exchange-httpd.h @@ -26,6 +26,7 @@ #include #include "taler_json_lib.h" #include "taler_crypto_lib.h" +#include "taler_extensions.h" #include @@ -200,6 +201,11 @@ extern volatile bool MHD_terminating; */ extern struct GNUNET_CURL_Context *TEH_curl_ctx; +/** + * The manifest of the available extensions + */ +extern const struct TALER_Extension TEH_extensions[TALER_Extension_Max]; + /** * @brief Struct describing an URL and the handler for it. */ diff --git a/src/exchange/taler-exchange-httpd_management_extensions.c b/src/exchange/taler-exchange-httpd_management_extensions.c index dd3ac6f81..6a771bf43 100644 --- a/src/exchange/taler-exchange-httpd_management_extensions.c +++ b/src/exchange/taler-exchange-httpd_management_extensions.c @@ -31,19 +31,25 @@ #include "taler_extensions.h" -/** - * TODO oec - */ struct Extension { - char *name; - json_t *config; + enum TALER_Extension_Type type; + json_t *config_json; + + // This union contains the parsed configuration for each extension. + union + { + // configuration for the age restriction + struct TALER_AgeMask mask; + + /* TODO oec - peer2peer config */ + }; }; /** - * Closure for the #set_extention transaction + * Closure for the #set_extensions transaction */ -struct SetExtensionContext +struct SetExtensionsContext { uint32_t num_extensions; struct Extension *extensions; @@ -51,8 +57,8 @@ struct SetExtensionContext }; /** - * Function implementing database transaction to set the configuration of an - * extension. It tuns the transaction logic. + * Function implementing database transaction to set the configuration of + * extensions. It runs the transaction logic. * - IF it returns a non-error code, the transaction logic MUST NOT queue a * MHD response. * - IF it returns an hard error, the transaction logic MUST queue a MHD @@ -60,16 +66,16 @@ struct SetExtensionContext * - IF it returns the soft error code, the function MAY be called again to * retry and MUST not queue a MHD response. * - * @param cls closure with a `struct AddKeysContext` + * @param cls closure with a `struct SetExtensionsContext` * @param connection MHD request which triggered the transaction * @param[out] mhd_ret set to MHD response status for @a connection, * if transaction failed (!) * @return transaction status */ static enum GNUNET_DB_QueryStatus -set_extension (void *cls, - struct MHD_Connection *connection, - MHD_RESULT *mhd_ret) +set_extensions (void *cls, + struct MHD_Connection *connection, + MHD_RESULT *mhd_ret) { // struct SetExtensionContext *sec = cls; @@ -83,7 +89,7 @@ TEH_handler_management_post_extensions ( struct MHD_Connection *connection, const json_t *root) { - struct SetExtensionContext sec; + struct SetExtensionsContext sec = {0}; json_t *extensions; json_t *extensions_sigs; struct GNUNET_JSON_Specification spec[] = { @@ -135,20 +141,24 @@ TEH_handler_management_post_extensions ( GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received /management/extensions\n"); + sec.extensions = GNUNET_new_array (sec.num_extensions, + struct Extension); sec.extensions_sigs = GNUNET_new_array (sec.num_extensions, struct TALER_MasterSignatureP); ok = true; + for (unsigned int i = 0; imaster_sig), - GNUNET_JSON_spec_fixed_auto ("exchange_pub", - &s->exchange_pub), - GNUNET_JSON_spec_end () - }; - enum GNUNET_GenericReturnValue res; - res = TALER_MHD_parse_json_data (connection, - json_array_get (signkey_sigs, - i), - ispec); - if (GNUNET_SYSERR == res) - { - ret = MHD_NO; /* hard failure */ - ok = false; - break; - } - if (GNUNET_NO == res) - { - ret = MHD_YES; - ok = false; - break; - } - } - if (! ok) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failure to handle /management/keys\n"); - GNUNET_free (akc.d_sigs); - GNUNET_free (akc.s_sigs); - GNUNET_JSON_parse_free (spec); - return ret; - } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Received %u denomination and %u signing key signatures\n", - akc.nd_sigs, - akc.ns_sigs); + "Received %u extensions\n", + sec.num_extensions); + { enum GNUNET_GenericReturnValue res; res = TEH_DB_run_transaction (connection, - "add keys", + "set extensions", TEH_MT_OTHER, &ret, - &add_keys, - &akc); - GNUNET_free (akc.d_sigs); - GNUNET_free (akc.s_sigs); + &set_extensions, + &sec); + + GNUNET_free (sec.extensions); + GNUNET_free (sec.extensions_sigs); GNUNET_JSON_parse_free (spec); if (GNUNET_SYSERR == res) return ret; } - TEH_keys_update_states (); -#endif return TALER_MHD_reply_static ( connection, diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index e6c5e2a4d..4ffee54c9 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -2518,4 +2518,36 @@ TALER_merchant_wire_signature_make ( struct TALER_MerchantSignatureP *merch_sig); +/* **************** /management/extensions offline signing **************** */ + +/** + * Create a signature for age restriction groups + * + * @param mask The bitmask representing age groups + * @param master_priv private key to sign with + * @param[out] master_sig where to write the signature + */ +void +TALER_exchange_offline_extension_agemask_sign ( + const struct TALER_AgeMask mask, + const struct TALER_MasterPrivateKeyP *master_priv, + struct TALER_MasterSignatureP *master_sig); + + +/** + * Verify the signature in @a master_sig. + * + * @param mask bit mask representing an age group for age restriction + * @param master_pub master public key of the exchange + * @param master_sig signature of the exchange + * @return #GNUNET_OK if signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_offline_extension_agemask_verify ( + const struct TALER_AgeMask mask, + const struct TALER_MasterPublicKeyP *master_pub, + const struct TALER_MasterSignatureP *master_sig + ); + + #endif diff --git a/src/include/taler_extensions.h b/src/include/taler_extensions.h index fe2b86aac..b6d5c826c 100644 --- a/src/include/taler_extensions.h +++ b/src/include/taler_extensions.h @@ -37,8 +37,8 @@ enum TALER_Extension_ReturnValue enum TALER_Extension_Type { - TALER_Extension_Peer2Peer = 0, - TALER_Extension_AgeRestriction = 1, + TALER_Extension_AgeRestriction = 0, + TALER_Extension_Peer2Peer = 1, TALER_Extension_Max = 2 }; diff --git a/src/include/taler_json_lib.h b/src/include/taler_json_lib.h index b20bd4ea4..888256385 100644 --- a/src/include/taler_json_lib.h +++ b/src/include/taler_json_lib.h @@ -542,6 +542,18 @@ TALER_deposit_extension_hash (const json_t *extensions, struct TALER_ExtensionContractHash *ech); +/** + * Parses a JSON object { "extension": "age_restriction", "mask": }. + * + * @param root is the json object + * @param[out] mask on succes, will contain the age mask + * @return GNUNET_OK on success and GNUNET_SYSERR on failure. + */ +enum GNUNET_GenericReturnValue +TALER_agemask_parse_json (const json_t *root, + struct TALER_AgeMask *mask); + + #endif /* TALER_JSON_LIB_H_ */ /* End of taler_json_lib.h */ diff --git a/src/json/json_helper.c b/src/json/json_helper.c index 949354e24..3b4da5595 100644 --- a/src/json/json_helper.c +++ b/src/json/json_helper.c @@ -659,4 +659,36 @@ TALER_JSON_spec_i18n_str (const char *name, } +enum GNUNET_GenericReturnValue +TALER_agemask_parse_json (const json_t *root, + struct TALER_AgeMask *mask) +{ + const char *name; + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_string ("extension", + &name), + GNUNET_JSON_spec_uint32 ("mask", + &mask->mask), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != GNUNET_JSON_parse (root, + spec, + NULL, + NULL)) + { + return GNUNET_SYSERR; + } + + if (! strncmp (name, + "age_restriction", + sizeof("age_restriction"))) + { + return GNUNET_SYSERR; + } + + return GNUNET_OK; +} + + /* end of json/json_helper.c */ diff --git a/src/lib/exchange_api_management_post_extensions.c b/src/lib/exchange_api_management_post_extensions.c index 550756827..a2de2454c 100644 --- a/src/lib/exchange_api_management_post_extensions.c +++ b/src/lib/exchange_api_management_post_extensions.c @@ -130,7 +130,6 @@ TALER_EXCHANGE_management_post_extensions ( void *cb_cls) { struct TALER_EXCHANGE_ManagementPostExtensionsHandle *ph; - // FIXME-oec: TODO! CURL *eh = NULL; json_t *body = NULL; json_t *extensions = NULL; @@ -156,16 +155,18 @@ TALER_EXCHANGE_management_post_extensions ( { json_t *config; const struct TALER_AgeMask *mask; - const struct TALER_Extension *ext - = &pkd->extensions[i]; + const struct TALER_Extension *ext = &pkd->extensions[i]; switch (ext->type) { // TODO: case TALER_Extension_Peer2Peer case TALER_Extension_AgeRestriction: - mask = (struct TALER_AgeMask *) (&ext->config); - config = GNUNET_JSON_PACK (GNUNET_JSON_pack_data_auto ("mask", - &mask->mask)); + mask = (const struct TALER_AgeMask *) (&ext->config); + config = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_string ("extension", + ext->name), + GNUNET_JSON_pack_data_auto ("mask", + &mask->mask)); GNUNET_assert (NULL != config); break; default: diff --git a/src/util/offline_signatures.c b/src/util/offline_signatures.c index 192023578..7fbec826b 100644 --- a/src/util/offline_signatures.c +++ b/src/util/offline_signatures.c @@ -491,7 +491,7 @@ TALER_exchange_offline_wire_fee_verify ( void -TALER_exchange_offline_extension_age_sign ( +TALER_exchange_offline_extension_agemask_sign ( const struct TALER_AgeMask mask, const struct TALER_MasterPrivateKeyP *master_priv, struct TALER_MasterSignatureP *master_sig) @@ -508,7 +508,7 @@ TALER_exchange_offline_extension_age_sign ( enum GNUNET_GenericReturnValue -TALER_exchange_offline_extension_age_verify ( +TALER_exchange_offline_extension_agemask_verify ( const struct TALER_AgeMask mask, const struct TALER_MasterPublicKeyP *master_pub, const struct TALER_MasterSignatureP *master_sig @@ -528,6 +528,7 @@ TALER_exchange_offline_extension_age_verify ( #if 0 +/* TODO peer2peer */ void TALER_exchange_offline_extension_p2p_sign ( // TODO