donau

Donation authority for GNU Taler (experimental)
Log | Files | Refs | Submodules | README | LICENSE

commit 1d20ecee10b8b7bfc554404f1963294d631fc75f
parent b2db2cbcdcdccaa22ac88659a32c9981ec68906c
Author: Matyja Lukas Adam <lukas.matyja@students.bfh.ch>
Date:   Thu, 21 Mar 2024 00:53:53 +0100

Merge remote-tracking branch 'refs/remotes/origin/master'

Diffstat:
Msrc/donau/Makefile.am | 1+
Msrc/donau/donau-httpd.c | 4++--
Msrc/donau/donau-httpd_keys.c | 1032++++++++++++++++++-------------------------------------------------------------
Msrc/include/Makefile.am | 4++--
Msrc/include/donau_json_lib.h | 13+++++++++++++
Msrc/json/json_helper.c | 620-------------------------------------------------------------------------------
Msrc/json/json_pack.c | 263+------------------------------------------------------------------------------
7 files changed, 256 insertions(+), 1681 deletions(-)

diff --git a/src/donau/Makefile.am b/src/donau/Makefile.am @@ -23,6 +23,7 @@ donau_httpd_LDADD = \ $(LIBGCRYPT_LIBS) \ $(top_builddir)/src/donaudb/libdonaudb.la \ $(top_builddir)/src/util/libdonauutil.la \ + $(top_builddir)/src/json/libdonaujson.la \ -lmicrohttpd \ -ltalermhd \ -ltalerutil \ diff --git a/src/donau/donau-httpd.c b/src/donau/donau-httpd.c @@ -27,10 +27,10 @@ #include <sched.h> #include <sys/resource.h> #include <limits.h> -// #include <taler/taler_templating_lib.h> #include <taler/taler_mhd_lib.h> #include "donaudb_lib.h" #include "donau_util.h" +#include "donau_json_lib.h" #include "donau-httpd_config.h" #include "donau-httpd_keys.h" #include "donau-httpd_charity.h" @@ -497,7 +497,7 @@ handle_mhd_request (void *cls, .nargs = 1, .nargs_is_upper_bound = true }, - /* POST batch issue receipts */ + /* POST batch issue receipts */ { .url = "batch-issue", .method = MHD_HTTP_METHOD_POST, diff --git a/src/donau/donau-httpd_keys.c b/src/donau/donau-httpd_keys.c @@ -24,6 +24,7 @@ #include <taler/platform.h> #include <taler/taler_json_lib.h> #include <taler/taler_mhd_lib.h> +#include "donau_json_lib.h" #include "donau-httpd.h" #include "donau-httpd_keys.h" #include "donau-httpd_config.h" @@ -117,172 +118,6 @@ static struct TALER_SecurityModulePublicKeyP donation_unit_cs_sm_pub; static struct TALER_SecurityModulePublicKeyP esign_sm_pub; /** - * Function called to forcefully resume suspended keys requests. - * - * @param cls unused, NULL - */ -static void -keys_timeout_cb (void *cls) -{ - struct SuspendedKeysRequests *skr; - - (void) cls; - keys_tt = NULL; - while (NULL != (skr = skr_head)) - { - if (GNUNET_TIME_absolute_is_future (skr->timeout)) - break; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Resuming /keys request due to timeout\n"); - GNUNET_CONTAINER_DLL_remove (skr_head, skr_tail, skr); - MHD_resume_connection (skr->connection); - TALER_MHD_daemon_trigger (); - GNUNET_free (skr); - } - if (NULL == skr) - return; - keys_tt = GNUNET_SCHEDULER_add_at (skr->timeout, &keys_timeout_cb, - NULL); -} - - -/** - * Suspend /keys request while we (hopefully) are waiting to be - * provisioned with key material. - * - * @param[in] connection to suspend - */ -static MHD_RESULT -suspend_request (struct MHD_Connection *connection) -{ - struct SuspendedKeysRequests *skr; - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Suspending /keys request until key material changes\n"); - if (terminating) - { - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING, - "Exchange terminating"); - } - skr = GNUNET_new (struct SuspendedKeysRequests); - skr->connection = connection; - MHD_suspend_connection (connection); - GNUNET_CONTAINER_DLL_insert (skr_head, - skr_tail, - skr); - skr->timeout = GNUNET_TIME_relative_to_absolute (KEYS_TIMEOUT); - if (NULL == keys_tt) - { - keys_tt = GNUNET_SCHEDULER_add_at (skr->timeout, - &keys_timeout_cb, - NULL); - } - skr_size++; - if (skr_size > SKR_LIMIT) - { - skr = skr_tail; - GNUNET_CONTAINER_DLL_remove (skr_head, - skr_tail, - skr); - skr_size--; - skr_connection = skr->connection; - MHD_resume_connection (skr->connection); - TALER_MHD_daemon_trigger (); - GNUNET_free (skr); - } - return MHD_YES; -} - - -/** - * Information about a donation unit on offer by the donation unit helper. - */ -struct HelperDonationUnit -{ - - /** - * When will the helper start to use this key for signing? - */ - struct GNUNET_TIME_Timestamp start_time; - - /** - * For how long will the helper allow signing? 0 if - * the key was revoked or purged. - */ - struct GNUNET_TIME_Relative validity_duration; - - /** - * Hash of the full donation unit key. - */ - struct DONAU_DonationUnitHashP h_donation_unit_pub; - - /** - * The (full) public key. - */ - struct DONAU_DonationUnitPublicKey donation_unit_pub; - - /** - * Signature over this key from the security module's key. - */ - struct TALER_SecurityModuleSignatureP sm_sig; - - /** - * Details depend on the @e donation_unit_pub.cipher type. - */ - union - { - - /** - * Hash of the RSA key. - */ - struct TALER_RsaPubHashP h_rsa; - - /** - * Hash of the CS key. - */ - struct TALER_CsPubHashP h_cs; - - } h_details; - - /** - * Name in configuration section for this donation unit type. - */ - char *section_name; - -}; - - -/** - * Information about a signing key on offer by the esign helper. - */ -struct HelperSignkey -{ - /** - * When will the helper start to use this key for signing? - */ - struct GNUNET_TIME_Timestamp start_time; - - /** - * For how long will the helper allow signing? 0 if - * the key was revoked or purged. - */ - struct GNUNET_TIME_Relative validity_duration; - - /** - * The public key. - */ - struct DONAU_DonauPublicKeyP donau_pub; - - /** - * Signature over this key from the security module's key. - */ - struct TALER_SecurityModuleSignatureP sm_sig; - -}; - -/** * Counter incremented whenever we have a reason to re-build the keys because * something external changed. See #DH_keys_get_state() and * #DH_keys_update_states() for uses of this variable. @@ -348,17 +183,6 @@ struct DH_KeyStateHandle struct GNUNET_CONTAINER_MultiPeerMap *signkey_map; /** - * Sorted array of responses to /keys (MUST be sorted by cherry-picking date) of - * length @e krd_array_length; - */ - struct KeysResponseData *krd_array; - - /** - * Length of the @e krd_array. - */ - unsigned int krd_array_length; - - /** * Information we track for the crypto helpers. Preserved * when the @e key_generation changes, thus kept separate. */ @@ -387,19 +211,9 @@ struct DH_KeyStateHandle */ struct GNUNET_TIME_Timestamp signature_expires; -}; - -/** - * Entry in (sorted) array with possible pre-build responses for /keys. - * We keep pre-build responses for the various (valid) cherry-picking - * values around. - */ -struct KeysResponseData -{ - /** - * Response to return if the client supports (deflate) compression. - */ + * Response to return if the client supports (deflate) compression. + */ struct MHD_Response *response_compressed; /** @@ -412,14 +226,6 @@ struct KeysResponseData */ char *etag; - /** - * Cherry-picking timestamp the client must have set for this - * response to be valid. 0 if this is the "full" response. - * The client's request must include this date or a higher one - * for this response to be applicable. - */ - struct GNUNET_TIME_Timestamp cherry_pick_date; - }; /** @@ -446,22 +252,22 @@ struct HelperState struct TALER_CRYPTO_CsDenominationHelper *csdh; /** - * Map from H(donation_unit_pub) to `struct HelperDonationUnit` entries. + * Map from H(donation_unit_pub) to `struct DH_DonationUnitKey` entries. */ struct GNUNET_CONTAINER_MultiHashMap *donation_unit; /** - * Map from H(rsa_pub) to `struct HelperDonationUnit` entries. + * Map from H(rsa_pub) to `struct DH_DonationUnitKey` entries. */ struct GNUNET_CONTAINER_MultiHashMap *rsa_keys; /** - * Map from H(cs_pub) to `struct HelperDonationUnit` entries. + * Map from H(cs_pub) to `struct DH_DonationUnitKey` entries. */ struct GNUNET_CONTAINER_MultiHashMap *cs_keys; /** - * Map from `struct TALER_ExchangePublicKey` to `struct HelperSignkey` + * Map from `struct TALER_ExchangePublicKey` to `struct SigningKey` * entries. Based on the fact that a `struct GNUNET_PeerIdentity` is also * an EdDSA public key. */ @@ -470,36 +276,105 @@ struct HelperState }; /** - * Closure for #insert_donation_unit_cb. + * Function called to forcefully resume suspended keys requests. + * + * @param cls unused, NULL */ -struct DonationUnitKeyCtx +static void +keys_timeout_cb (void *cls) { - /** - * Heap for sorting active donation unit keys by start time. - */ - struct GNUNET_CONTAINER_Heap *heap; + struct SuspendedKeysRequests *skr; + + (void) cls; + keys_tt = NULL; + while (NULL != (skr = skr_head)) + { + if (GNUNET_TIME_absolute_is_future (skr->timeout)) + break; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Resuming /keys request due to timeout\n"); + GNUNET_CONTAINER_DLL_remove (skr_head, skr_tail, skr); + MHD_resume_connection (skr->connection); + TALER_MHD_daemon_trigger (); + GNUNET_free (skr); + } + if (NULL == skr) + return; + keys_tt = GNUNET_SCHEDULER_add_at (skr->timeout, &keys_timeout_cb, + NULL); +} + + +/** + * Suspend /keys request while we (hopefully) are waiting to be + * provisioned with key material. + * + * @param[in] connection to suspend + */ +static MHD_RESULT +suspend_request (struct MHD_Connection *connection) +{ + struct SuspendedKeysRequests *skr; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Suspending /keys request until key material changes\n"); + if (terminating) + { + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING, + "Exchange terminating"); + } + skr = GNUNET_new (struct SuspendedKeysRequests); + skr->connection = connection; + MHD_suspend_connection (connection); + GNUNET_CONTAINER_DLL_insert (skr_head, + skr_tail, + skr); + skr->timeout = GNUNET_TIME_relative_to_absolute (KEYS_TIMEOUT); + if (NULL == keys_tt) + { + keys_tt = GNUNET_SCHEDULER_add_at (skr->timeout, + &keys_timeout_cb, + NULL); + } + skr_size++; + if (skr_size > SKR_LIMIT) + { + skr = skr_tail; + GNUNET_CONTAINER_DLL_remove (skr_head, + skr_tail, + skr); + skr_size--; + skr_connection = skr->connection; + MHD_resume_connection (skr->connection); + TALER_MHD_daemon_trigger (); + GNUNET_free (skr); + } + return MHD_YES; +} - /** - * What is the minimum key rotation frequency of - * valid donation unit keys? - */ - struct GNUNET_TIME_Relative min_dk_frequency; -}; /** - * Closure for #add_sign_key_cb. + * Closure for #insert_donation_unit_cb and #add_signkey_cb. */ -struct SignKeyCtx +struct KeysBuilderContext { /** - * What is the current rotation frequency for signing keys. Updated. + * Our key state. + */ + struct DH_KeyStateHandle *ksh; + + /** + * Array of donation unit keys. */ - struct GNUNET_TIME_Relative min_sk_frequency; + json_t *donation_units; /** - * JSON array of signing keys (being created). + * Array of signing keys. */ json_t *signkeys; + }; /** @@ -516,18 +391,11 @@ add_sign_key_cb (void *cls, const struct GNUNET_PeerIdentity *pid, void *value) { - struct SignKeyCtx *ctx = cls; + struct KeysBuilderContext *ctx = cls; struct SigningKey *sk = value; (void) pid; - if (GNUNET_TIME_absolute_is_future (sk->meta.expire_sign.abs_time)) - { - ctx->min_sk_frequency = - GNUNET_TIME_relative_min (ctx->min_sk_frequency, - GNUNET_TIME_absolute_get_difference ( - sk->meta.valid_from.abs_time, - sk->meta.expire_sign.abs_time)); - } + GNUNET_assert ( 0 == json_array_append_new ( @@ -578,29 +446,6 @@ setup_general_response_headers (void *cls, /** - * Closure for #insert_donation_unit_cb and #add_signkey_cb. - */ -struct KeysBuilderContext -{ - /** - * Our key state. - */ - struct DH_KeyStateHandle *ksh; - - /** - * Array of donation unit keys. - */ - json_t *donation_units; - - /** - * Array of signing keys. - */ - json_t *signkeys; - -}; - - -/** * Function called on all of our current and future donation unit keys * known to the helper process. Filters out those that are current * and adds the remaining donation unit keys (with their configuration @@ -608,7 +453,7 @@ struct KeysBuilderContext * * @param cls the `struct FutureBuilderContext *` * @param h_du_pub hash of the donation unit public key - * @param value a `struct HelperDonationUnit` + * @param value a `struct DH_DonationUnitKey` * @return #GNUNET_OK (continue to iterate) */ static enum GNUNET_GenericReturnValue @@ -617,78 +462,49 @@ insert_donation_unit_cb (void *cls, void *value) { struct KeysBuilderContext *kbc = cls; - struct HelperDonationUnit *hd = value; - struct DH_DonationUnitKey *du; - - du = GNUNET_CONTAINER_multihashmap_get ( - kbc->ksh->donation_unit_map, - h_du_pub); - - if (NULL != du) - return GNUNET_OK; /* skip: this key is already active! */ + struct DH_DonationUnitKey *du = value; // if (GNUNET_TIME_relative_is_zero (hd->validity_duration)) - // return GNUNET_OK; /* this key already expired! */ - - // if (GNUNET_OK != - // load_extension_data (hd->section_name, - // &meta)) - // { - // /* Woops, couldn't determine fee structure!? */ - // return GNUNET_OK; - // } - + // return GNUNET_OK; /* this key already expired! */ GNUNET_assert ( 0 == json_array_append_new ( kbc->donation_units, GNUNET_JSON_PACK ( - GNUNET_JSON_pack_data_auto ("donation_unit_pub", - &hd->donation_unit_pub), - // GNUNET_JSON_pack_uint64 ("validity_year", - // du->validity_year), - // TALER_JSON_pack_amount ("value", - // &du->value), - // GNUNET_JSON_pack_data_auto ("donation_unit_secmod_sig", - // &hd->sm_sig), - GNUNET_JSON_pack_string ("section_name", - hd->section_name) + DONAU_JSON_pack_donation_unit_pub ("donation_unit_pub", + &du->donation_unit_pub), + GNUNET_JSON_pack_uint64 ("year", + du->validity_year), + TALER_JSON_pack_amount ("value", + &du->value) ))); return GNUNET_OK; } /** - * Initialize @a krd using the given values for @a signkeys, + * Initialize @a ksh using the given values for @a signkeys, * and @a denoms. * - * @param[in,out] ksh key state handle we build @a krd for + * @param[in,out] ksh key state handle we build @a ksh for * @param[in] du_keys_hash hash over all the denomination keys in @a denoms - * @param last_cherry_pick_date timestamp to use * @param[in,out] signkeys list of sign keys to return * @param[in,out] grouped_donation_units list of grouped denominations to return * @return #GNUNET_OK on success */ static enum GNUNET_GenericReturnValue -create_krd (struct DH_KeyStateHandle *ksh, - const struct GNUNET_HashCode *du_keys_hash, - struct GNUNET_TIME_Timestamp last_cherry_pick_date, - json_t *signkeys, - json_t *grouped_donation_units) +create_keys_response (struct DH_KeyStateHandle *ksh, + const struct GNUNET_HashCode *du_keys_hash, + json_t *signkeys, + json_t *grouped_donation_units) { - struct KeysResponseData krd; struct DONAU_DonauPublicKeyP donau_pub; // struct DONAU_DonauSignatureP donau_sig; json_t *keys; - - // GNUNET_assert (! GNUNET_TIME_absolute_is_zero ( - // last_cherry_pick_date.abs_time)); GNUNET_assert (NULL != signkeys); GNUNET_assert (NULL != grouped_donation_units); GNUNET_assert (NULL != DH_currency); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Creating /keys at cherry pick date %s\n", - GNUNET_TIME_timestamp2s (last_cherry_pick_date)); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Creating /keys response"); /* Sign hash over master signatures of all denomination keys until this time (in reverse order). */ @@ -700,7 +516,6 @@ create_krd (struct DH_KeyStateHandle *ksh, // DONAU_donau_online_key_set_sign ( // &TEH_keys_donau_sign2_, // ksh, - // last_cherry_pick_date, // du_keys_hash, // &donau_pub, // &donau_sig))) @@ -774,100 +589,51 @@ create_krd (struct DH_KeyStateHandle *ksh, } /* Create uncompressed response */ - krd.response_uncompressed + ksh->response_uncompressed = MHD_create_response_from_buffer (keys_jsonz_size, keys_json, MHD_RESPMEM_MUST_FREE); - GNUNET_assert (NULL != krd.response_uncompressed); + GNUNET_assert (NULL != ksh->response_uncompressed); setup_general_response_headers (ksh, - krd.response_uncompressed); + ksh->response_uncompressed); GNUNET_break (MHD_YES == - MHD_add_response_header (krd.response_uncompressed, + MHD_add_response_header (ksh->response_uncompressed, MHD_HTTP_HEADER_ETAG, etag)); /* Also compute compressed version of /keys response */ comp = TALER_MHD_body_compress (&keys_jsonz, &keys_jsonz_size); - krd.response_compressed + ksh->response_compressed = MHD_create_response_from_buffer (keys_jsonz_size, keys_jsonz, MHD_RESPMEM_MUST_FREE); - GNUNET_assert (NULL != krd.response_compressed); + GNUNET_assert (NULL != ksh->response_compressed); /* If the response is actually compressed, set the respective header. */ GNUNET_assert ( (MHD_YES != comp) || (MHD_YES == - MHD_add_response_header (krd.response_compressed, + MHD_add_response_header (ksh->response_compressed, MHD_HTTP_HEADER_CONTENT_ENCODING, "deflate")) ); setup_general_response_headers (ksh, - krd.response_compressed); + ksh->response_compressed); /* Set cache control headers: our response varies depending on these headers */ GNUNET_break (MHD_YES == - MHD_add_response_header (krd.response_compressed, + MHD_add_response_header (ksh->response_compressed, MHD_HTTP_HEADER_VARY, MHD_HTTP_HEADER_ACCEPT_ENCODING)); /* Information is always public, revalidate after 1 day */ GNUNET_break (MHD_YES == - MHD_add_response_header (krd.response_compressed, + MHD_add_response_header (ksh->response_compressed, MHD_HTTP_HEADER_CACHE_CONTROL, "public,max-age=86400")); GNUNET_break (MHD_YES == - MHD_add_response_header (krd.response_compressed, + MHD_add_response_header (ksh->response_compressed, MHD_HTTP_HEADER_ETAG, etag)); - krd.etag = GNUNET_strdup (etag); + ksh->etag = GNUNET_strdup (etag); } - krd.cherry_pick_date = last_cherry_pick_date; - GNUNET_array_append (ksh->krd_array, - ksh->krd_array_length, - krd); - return GNUNET_OK; -} - -/** - *GroupData is the value we store for each group meta-data */ -struct GroupData -{ - /** - * The json blob with the group meta-data and list of denominations - */ - json_t *json; - - /** - * List of denominations for the group, - * included in @e json, do not free separately! - */ - json_t *list; - - /** - * Offset of the group in the final array. - */ - unsigned int group_off; - -}; - - -/** - * Helper function called to clean up the group data - * in the denominations_by_group below. - * - * @param cls unused - * @param key unused - * @param value a `struct GroupData` to free - * @return #GNUNET_OK - */ -static int -free_group (void *cls, - const struct GNUNET_HashCode *key, - void *value) -{ - struct GroupData *gd = value; - - (void) cls; - (void) key; - GNUNET_free (gd); return GNUNET_OK; } @@ -885,21 +651,18 @@ static enum GNUNET_GenericReturnValue finish_keys_response (struct DH_KeyStateHandle *ksh) { enum GNUNET_GenericReturnValue ret = GNUNET_SYSERR; - struct SignKeyCtx sctx; json_t *grouped_donation_units = NULL; - struct GNUNET_TIME_Timestamp last_cherry_pick_date; - struct GNUNET_CONTAINER_Heap *heap; struct GNUNET_HashContext *hash_context = NULL; + struct KeysBuilderContext kbc; - sctx.signkeys = json_array (); - GNUNET_assert (NULL != sctx.signkeys); - sctx.min_sk_frequency = GNUNET_TIME_UNIT_FOREVER_REL; + kbc.signkeys = json_array (); + GNUNET_assert (NULL != kbc.signkeys); GNUNET_CONTAINER_multipeermap_iterate (ksh->signkey_map, &add_sign_key_cb, - &sctx); + &kbc); - if (0 == json_array_size (sctx.signkeys)) + if (0 == json_array_size (kbc.signkeys)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "No online signing keys available. Refusing to generate /keys response.\n"); @@ -907,243 +670,56 @@ finish_keys_response (struct DH_KeyStateHandle *ksh) goto CLEANUP; } - heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MAX); - { - struct DonationUnitKeyCtx dkc = { - .heap = heap, - .min_dk_frequency = GNUNET_TIME_UNIT_FOREVER_REL, - }; - - GNUNET_CONTAINER_multihashmap_iterate (ksh->donation_unit_map, - &insert_donation_unit_cb, - &dkc); - // ksh->rekey_frequency - // = GNUNET_TIME_relative_min (dkc.min_dk_frequency, - // sctx.min_sk_frequency); - } + GNUNET_CONTAINER_multihashmap_iterate (ksh->donation_unit_map, + &insert_donation_unit_cb, + &kbc); - hash_context = GNUNET_CRYPTO_hash_context_start (); grouped_donation_units = json_array (); GNUNET_assert (NULL != grouped_donation_units); - last_cherry_pick_date = GNUNET_TIME_UNIT_ZERO_TS; - { struct DH_DonationUnitKey *dk; - struct GNUNET_CONTAINER_MultiHashMap *donation_units_by_group; - - donation_units_by_group = - GNUNET_CONTAINER_multihashmap_create (1024, - GNUNET_NO /* NO, because keys are only on the stack */ - ); - /* heap = max heap, sorted by start time */ - while (NULL != (dk = GNUNET_CONTAINER_heap_remove_root (heap))) - { - if (! GNUNET_TIME_absolute_is_zero (last_cherry_pick_date.abs_time)) - { - /* - * This is not the first entry in the heap (because last_cherry_pick_date != - * GNUNET_TIME_UNIT_ZERO_TS) and the previous entry had a different - * start time. Therefore, we create a new entry in ksh. - */ - struct GNUNET_HashCode hc; - - // compute_msig_hash (&sig_ctx, - // &hc); - if (GNUNET_OK != - create_krd (ksh, - &hc, - last_cherry_pick_date, - sctx.signkeys, - grouped_donation_units)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to generate key response data for %s\n", - GNUNET_TIME_timestamp2s (last_cherry_pick_date)); - /* drain heap before destroying it */ - while (NULL != (dk = GNUNET_CONTAINER_heap_remove_root (heap))) - /* intentionally empty */; - GNUNET_CONTAINER_heap_destroy (heap); - goto CLEANUP; - } - } - - // last_cherry_pick_date = dk->meta.validity_year; - - /* - * Group the donation_units by {cipher, value, fees, age_mask}. - * - * For each group we save the group meta-data and the list of - * donation_units in this group as a json-blob in the multihashmap - * donation_units_by_group. - */ - { - struct GroupData *group; - json_t *entry; - struct GNUNET_HashCode key; - struct DONAU_DonationUnitGroup meta = { - .cipher = dk->donation_unit_pub.bsign_pub_key->cipher, - .value = dk->value, - }; - - /* Search the group/JSON-blob for the key */ - DONAU_donation_unit_group_get_key (&meta, - &key); - group = GNUNET_CONTAINER_multihashmap_get ( - donation_units_by_group, - &key); - if (NULL == group) - { - /* There is no group for this meta-data yet, so we create a new group */ - const char *cipher; - - switch (meta.cipher) - { - case GNUNET_CRYPTO_BSA_RSA: - cipher = "RSA"; - break; - case GNUNET_CRYPTO_BSA_CS: - cipher = "CS"; - break; - default: - GNUNET_assert (false); - } - - group = GNUNET_new (struct GroupData); - - /* Create a new array for the donation_units in this group */ - group->list = json_array (); - GNUNET_assert (NULL != group->list); - group->json = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("cipher", - cipher), - GNUNET_JSON_pack_array_steal ("donation_units", - group->list), - TALER_JSON_pack_amount ("value", - &meta.value)); - GNUNET_assert (NULL != group->json); - - group->group_off - = json_array_size (grouped_donation_units); - GNUNET_assert (0 == - json_array_append_new ( - grouped_donation_units, - group->json)); - GNUNET_assert ( - GNUNET_OK == - GNUNET_CONTAINER_multihashmap_put (donation_units_by_group, - &key, - group, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) - ); - } - - /* Now that we have found/created the right group, add the - denomination to the list */ - { - struct HelperDonationUnit *hd; - struct GNUNET_JSON_PackSpec key_spec; - bool private_key_lost; - - hd = GNUNET_CONTAINER_multihashmap_get (ksh->helpers->donation_unit, - &dk->h_donation_unit_pub.hash) - ; - private_key_lost - = (NULL == hd) || - GNUNET_TIME_absolute_is_past ( - GNUNET_TIME_absolute_add ( - hd->start_time.abs_time, - hd->validity_duration)); - switch (meta.cipher) - { - case GNUNET_CRYPTO_BSA_RSA: - key_spec = - GNUNET_JSON_pack_rsa_public_key ( - "rsa_pub", - dk->donation_unit_pub.bsign_pub_key->details.rsa_public_key); - break; - case GNUNET_CRYPTO_BSA_CS: - key_spec = - GNUNET_JSON_pack_data_varsize ( - "cs_pub", - &dk->donation_unit_pub.bsign_pub_key->details.cs_public_key, - sizeof (dk->donation_unit_pub.bsign_pub_key->details. - cs_public_key)); - break; - default: - GNUNET_assert (false); - } - - entry = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_allow_null ( - private_key_lost - ? GNUNET_JSON_pack_bool ("lost", - true) - : GNUNET_JSON_pack_string ("dummy", - NULL)), - key_spec - ); - GNUNET_assert (NULL != entry); - } - - /* Build up the running hash of all master signatures of the - donation_units */ - // append_signature (&sig_ctx, - // group->group_off, - // (unsigned int) json_array_size (group->list), - // &dk->master_sig); - - /* Finally, add the denomination to the list of donation_units in this - group */ - GNUNET_assert (json_is_array (group->list)); - GNUNET_assert (0 == - json_array_append_new (group->list, - entry)); - } - } /* loop over heap ends */ - - GNUNET_CONTAINER_multihashmap_iterate (donation_units_by_group, - &free_group, - NULL); - GNUNET_CONTAINER_multihashmap_destroy (donation_units_by_group); - } - GNUNET_CONTAINER_heap_destroy (heap); - // if (! GNUNET_TIME_absolute_is_zero (last_cherry_pick_date.abs_time)) - if (true) - { - struct GNUNET_HashCode hc; - - GNUNET_CRYPTO_hash_context_finish (hash_context, &hc); - if (GNUNET_OK != - create_krd (ksh, - &hc, - last_cherry_pick_date, - sctx.signkeys, - grouped_donation_units)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to generate key response data for %s\n", - GNUNET_TIME_timestamp2s (last_cherry_pick_date)); - goto CLEANUP; - } + // while (NULL != (dk = )) + // { +// + // struct GNUNET_HashCode hc; + // // compute_msig_hash (&sig_ctx, + // // &hc); + // if (GNUNET_OK != + // create_keys_response (ksh, + // &hc, + // kbc.signkeys, + // grouped_donation_units)) + // { + // GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + // "Failed to generate key response data\n"); + // goto CLEANUP; + // } +// + // } } - else + + struct GNUNET_HashCode hc; + GNUNET_CRYPTO_hash_context_finish (hash_context, &hc); + if (GNUNET_OK != + create_keys_response (ksh, + &hc, + kbc.signkeys, + kbc.donation_units)) { - GNUNET_log ( - GNUNET_ERROR_TYPE_WARNING, - "No donation unit keys available. Refusing to generate /keys response.\n") - ; - GNUNET_CRYPTO_hash_context_abort (hash_context); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed to generate key response data\n"); + goto CLEANUP; } ret = GNUNET_OK; CLEANUP: - json_decref (grouped_donation_units); - if (NULL != sctx.signkeys) - json_decref (sctx.signkeys); + // json_decref (grouped_donation_units); + if (NULL != kbc.signkeys) + json_decref (kbc.signkeys); return ret; } @@ -1201,15 +777,8 @@ clear_signkey_cb (void *cls, static void clear_response_cache (struct DH_KeyStateHandle *ksh) { - for (unsigned int i = 0; i < ksh->krd_array_length; i++) - { - struct KeysResponseData *krd = &ksh->krd_array[i]; - - MHD_destroy_response (krd->response_compressed); - MHD_destroy_response (krd->response_uncompressed); - GNUNET_free (krd->etag); - } - GNUNET_array_grow (ksh->krd_array, ksh->krd_array_length, 0); + MHD_destroy_response (ksh->response_compressed); + MHD_destroy_response (ksh->response_uncompressed); } @@ -1328,9 +897,9 @@ check_esign_sm_pub (const struct TALER_SecurityModulePublicKeyP *sm_pub) * Helper function for #destroy_key_helpers to free all entries * in the `donation_unit` map. * - * @param cls the `struct HelperDonationUnit` + * @param cls the `struct DH_DonationUnitKey` * @param h_donation_unit_pub hash of the donation unit public key - * @param value the `struct HelperDonationUnit` to release + * @param value the `struct DH_DonationUnitKey` to release * @return #GNUNET_OK (continue to iterate) */ static enum GNUNET_GenericReturnValue @@ -1338,12 +907,11 @@ free_donation_unit_cb (void *cls, const struct GNUNET_HashCode *h_du_pub, void *value) { - struct HelperDonationUnit *hd = value; + struct DH_DonationUnitKey *hd = value; (void) cls; (void) h_du_pub; DONAU_donation_unit_pub_free (&hd->donation_unit_pub); - GNUNET_free (hd->section_name); GNUNET_free (hd); return GNUNET_OK; } @@ -1353,9 +921,9 @@ free_donation_unit_cb (void *cls, * Helper function for #destroy_key_helpers to free all entries * in the `esign_keys` map. * - * @param cls the `struct HelperSignkey` + * @param cls the `struct SigningKey` * @param pid unused, matches the donau public key - * @param value the `struct HelperSignkey` to release + * @param value the `struct SigningKey` to release * @return #GNUNET_OK (continue to iterate) */ static enum GNUNET_GenericReturnValue @@ -1363,7 +931,7 @@ free_esign_cb (void *cls, const struct GNUNET_PeerIdentity *pid, void *value) { - struct HelperSignkey *hsk = value; + struct SigningKey *hsk = value; (void) cls; (void) pid; @@ -1477,7 +1045,7 @@ helper_rsa_cb ( const struct TALER_SecurityModuleSignatureP *sm_sig) { struct HelperState *hs = cls; - struct HelperDonationUnit *hd; + struct DH_DonationUnitKey *hd; struct TALER_Amount value; enum GNUNET_DB_QueryStatus qs; @@ -1502,19 +1070,19 @@ helper_rsa_cb ( false)); hd = GNUNET_CONTAINER_multihashmap_get (hs->rsa_keys, &h_rsa->hash); - if (NULL != hd) - { - /* should be just an update (revocation!), so update existing entry */ - hd->validity_duration = validity_duration; - return; - } + // if (NULL != hd) + // { + // /* should be just an update (revocation!), so update existing entry */ + // hd->validity_duration = validity_duration; + // return; + // } GNUNET_assert (NULL != sm_pub); check_donation_unit_rsa_sm_pub (sm_pub); - hd = GNUNET_new (struct HelperDonationUnit); - hd->start_time = start_time; - hd->validity_duration = validity_duration; - hd->h_details.h_rsa = *h_rsa; - hd->sm_sig = *sm_sig; + hd = GNUNET_new (struct DH_DonationUnitKey); + // hd->start_time = start_time; + // hd->validity_duration = validity_duration; + // hd->h_details.h_rsa = *h_rsa; + // hd->sm_sig = *sm_sig; GNUNET_assert (GNUNET_CRYPTO_BSA_RSA == bs_pub->cipher); hd->donation_unit_pub.bsign_pub_key = GNUNET_CRYPTO_bsign_pub_incref (bs_pub); @@ -1534,7 +1102,7 @@ helper_rsa_cb ( GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Inserted donation unit of %s\n", TALER_amount2s (&value)); - hd->section_name = GNUNET_strdup (section_name); + GNUNET_assert ( GNUNET_OK == GNUNET_CONTAINER_multihashmap_put ( @@ -1542,13 +1110,13 @@ helper_rsa_cb ( &hd->h_donation_unit_pub.hash, hd, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); - GNUNET_assert ( - GNUNET_OK == - GNUNET_CONTAINER_multihashmap_put ( - hs->rsa_keys, - &hd->h_details.h_rsa.hash, - hd, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); + // GNUNET_assert ( + // GNUNET_OK == + // GNUNET_CONTAINER_multihashmap_put ( + // hs->rsa_keys, + // &hd->h_details.h_rsa.hash, + // hd, + // GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); key_generation++; DH_resume_keys_requests (false); } @@ -1581,7 +1149,7 @@ helper_cs_cb ( const struct TALER_SecurityModuleSignatureP *sm_sig) { struct HelperState *hs = cls; - struct HelperDonationUnit *hd; + struct DH_DonationUnitKey *hd; struct TALER_Amount value; enum GNUNET_DB_QueryStatus qs; @@ -1608,18 +1176,18 @@ helper_cs_cb ( hd = GNUNET_CONTAINER_multihashmap_get (hs->cs_keys, &h_cs->hash); - if (NULL != hd) - { - /* should be just an update (revocation!), so update existing entry */ - hd->validity_duration = validity_duration; - return; - } + // if (NULL != hd) + // { + // /* should be just an update (revocation!), so update existing entry */ + // hd->validity_duration = validity_duration; + // return; + // } GNUNET_assert (NULL != sm_pub); check_donation_unit_cs_sm_pub (sm_pub); - hd = GNUNET_new (struct HelperDonationUnit); - hd->start_time = start_time; - hd->validity_duration = validity_duration; - hd->h_details.h_cs = *h_cs; + hd = GNUNET_new (struct DH_DonationUnitKey); + // hd->start_time = start_time; + // hd->validity_duration = validity_duration; + // hd->h_details.h_cs = *h_cs; GNUNET_assert (GNUNET_CRYPTO_BSA_CS == bs_pub->cipher); hd->donation_unit_pub.bsign_pub_key = GNUNET_CRYPTO_bsign_pub_incref (bs_pub); @@ -1639,7 +1207,7 @@ helper_cs_cb ( GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Inserted donation unit of %s\n", TALER_amount2s (&value)); - hd->section_name = GNUNET_strdup (section_name); + GNUNET_assert ( GNUNET_OK == GNUNET_CONTAINER_multihashmap_put ( @@ -1647,13 +1215,13 @@ helper_cs_cb ( &hd->h_donation_unit_pub.hash, hd, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); - GNUNET_assert ( - GNUNET_OK == - GNUNET_CONTAINER_multihashmap_put ( - hs->cs_keys, - &hd->h_details.h_cs.hash, - hd, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); + // GNUNET_assert ( + // GNUNET_OK == + // GNUNET_CONTAINER_multihashmap_put ( + // hs->cs_keys, + // &hd->h_details.h_cs.hash, + // hd, + // GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); key_generation++; DH_resume_keys_requests (false); } @@ -1684,7 +1252,7 @@ helper_esign_cb ( const struct TALER_SecurityModuleSignatureP *sm_sig) { struct HelperState *hs = cls; - struct HelperSignkey *hsk; + struct SigningKey *hsk; struct GNUNET_PeerIdentity pid; /* need to "cast" because secmod works with TALER_ExchangePublicKeyP */ struct DONAU_DonauPublicKeyP donau_pubkey = { @@ -1701,18 +1269,18 @@ helper_esign_cb ( pid.public_key = donau_pub->eddsa_pub; hsk = GNUNET_CONTAINER_multipeermap_get (hs->esign_keys, &pid); - if (NULL != hsk) - { - GNUNET_break (0); // revocation not supported - /* should be just an update (revocation!), so update existing entry */ - // hsk->validity_duration = validity_duration; - return; - } + // if (NULL != hsk) + // { + // GNUNET_break (0); // revocation not supported + // /* should be just an update (revocation!), so update existing entry */ + // // hsk->validity_duration = validity_duration; + // return; + // } GNUNET_assert (NULL != sm_pub); check_esign_sm_pub (sm_pub); - hsk = GNUNET_new (struct HelperSignkey); - hsk->start_time = start_time; - hsk->validity_duration = validity_duration; + hsk = GNUNET_new (struct SigningKey); + // hsk->start_time = start_time; + // hsk->validity_duration = validity_duration; hsk->donau_pub = donau_pubkey; { struct DONAUDB_SignkeyMetaData meta = { @@ -1940,6 +1508,7 @@ build_key_state (struct HelperState *hs) /* NOTE: fetches master-signed signkeys, but ALSO those that were revoked! */ GNUNET_break (GNUNET_OK == DH_plugin->preflight (DH_plugin->cls)); + qs = DH_plugin->iterate_donation_units (DH_plugin->cls, &donation_unit_info_cb, ksh); @@ -2042,7 +1611,7 @@ DH_keys_get_state () * * @param cls the `struct FutureBuilderContext *` * @param pid actually the donau public key (type disguised) - * @param value a `struct HelperDonationUnit` + * @param value a `struct DH_DonationUnitKey` * @return #GNUNET_OK (continue to iterate) */ static enum GNUNET_GenericReturnValue @@ -2051,7 +1620,7 @@ add_signkey_cb (void *cls, void *value) { struct KeysBuilderContext *kbc = cls; - struct HelperSignkey *hsk = value; + struct SigningKey *hsk = value; struct SigningKey *sk; struct GNUNET_TIME_Timestamp stamp_expire; @@ -2064,9 +1633,9 @@ add_signkey_cb (void *cls, // if (GNUNET_TIME_relative_is_zero (hsk->validity_duration)) // return GNUNET_OK; /* this key already expired! */ - stamp_expire = GNUNET_TIME_absolute_to_timestamp ( - GNUNET_TIME_absolute_add (hsk->start_time.abs_time, - hsk->validity_duration)); + // stamp_expire = GNUNET_TIME_absolute_to_timestamp ( + // GNUNET_TIME_absolute_add (hsk->start_time.abs_time, + // hsk->validity_duration)); // legal_end = GNUNET_TIME_absolute_to_timestamp ( // GNUNET_TIME_absolute_add (stamp_expire.abs_time, @@ -2077,15 +1646,16 @@ add_signkey_cb (void *cls, kbc->signkeys, GNUNET_JSON_PACK ( GNUNET_JSON_pack_data_auto ("key", - &hsk->donau_pub), - GNUNET_JSON_pack_timestamp ("stamp_start", - hsk->start_time), - GNUNET_JSON_pack_timestamp ("stamp_expire", - stamp_expire), + &hsk->donau_pub) // , + // GNUNET_JSON_pack_timestamp ("stamp_start", + // hsk->start_time), + // GNUNET_JSON_pack_timestamp ("stamp_expire", + // stamp_expire), // GNUNET_JSON_pack_timestamp ("stamp_end", // legal_end), - GNUNET_JSON_pack_data_auto ("signkey_secmod_sig", - &hsk->sm_sig)))); + // GNUNET_JSON_pack_data_auto ("signkey_secmod_sig", + // &hsk->sm_sig) + ))); return GNUNET_OK; } @@ -2182,29 +1752,6 @@ DH_handler_keys (struct DH_RequestContext *rc, /** - * Comparator used for a binary search by cherry_pick_date for @a key in the - * `struct KeysResponseData` array. See libc's qsort() and bsearch() functions. - * - * @param key pointer to a `struct GNUNET_TIME_Timestamp` - * @param value pointer to a `struct KeysResponseData` array entry - * @return 0 if time matches, -1 if key is smaller, 1 if key is larger - */ -static int -krd_search_comparator (const void *key, - const void *value) -{ - const struct GNUNET_TIME_Timestamp *kd = key; - const struct KeysResponseData *krd = value; - - if (GNUNET_TIME_timestamp_cmp (*kd, >, krd->cherry_pick_date)) - return -1; - if (GNUNET_TIME_timestamp_cmp (*kd, <, krd->cherry_pick_date)) - return 1; - return 0; -} - - -/** * Callback used to set headers in a response. * * @param cls closure @@ -2238,113 +1785,4 @@ DH_RESPONSE_reply_not_modified (struct MHD_Connection *connection, } -// MHD_RESULT -// DH_keys_get_handler (struct DH_RequestContext *rc, -// const char *const args[]) -// { -// struct GNUNET_TIME_Timestamp last_issue_date; -// const char *etag; -// -// etag = MHD_lookup_connection_value (rc->connection, -// MHD_HEADER_KIND, -// MHD_HTTP_HEADER_IF_NONE_MATCH); -// (void) args; -// { -// const char *have_cherrypick; -// -// have_cherrypick = MHD_lookup_connection_value (rc->connection, -// MHD_GET_ARGUMENT_KIND, -// "last_issue_date"); -// if (NULL != have_cherrypick) -// { -// unsigned long long cherrypickn; -// -// if (1 != -// sscanf (have_cherrypick, -// "%llu", -// &cherrypickn)) -// { -// GNUNET_break_op (0); -// return TALER_MHD_reply_with_error (rc->connection, -// MHD_HTTP_BAD_REQUEST, -// TALER_EC_GENERIC_PARAMETER_MALFORMED, -// have_cherrypick); -// } -// /* The following multiplication may overflow; but this should not really -// be a problem, as giving back 'older' data than what the client asks for -// (given that the client asks for data in the distant future) is not -// problematic */ -// last_issue_date = GNUNET_TIME_timestamp_from_s (cherrypickn); -// } -// else -// { -// last_issue_date = GNUNET_TIME_UNIT_ZERO_TS; -// } -// } -// -// { -// struct DH_KeyStateHandle *ksh; -// const struct KeysResponseData *krd; -// -// ksh = DH_keys_get_state (); -// if ( (NULL == ksh) || -// (0 == ksh->krd_array_length) ) -// { -// if ( ( (SKR_LIMIT == skr_size) && -// (rc->connection == skr_connection) ) || -// DH_suicide) -// { -// return TALER_MHD_reply_with_error ( -// rc->connection, -// MHD_HTTP_SERVICE_UNAVAILABLE, -// TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING, -// DH_suicide -// ? "server terminating" -// : "too many connections suspended waiting on /keys"); -// } -// return suspend_request (rc->connection); -// } -// krd = bsearch (&last_issue_date, -// ksh->krd_array, -// ksh->krd_array_length, -// sizeof (struct KeysResponseData), -// &krd_search_comparator); -// GNUNET_log (GNUNET_ERROR_TYPE_INFO, -// "Filtering /keys by cherry pick date %s found entry %u/%u\n", -// GNUNET_TIME_timestamp2s (last_issue_date), -// (unsigned int) (krd - ksh->krd_array), -// ksh->krd_array_length); -// if ( (NULL == krd) && -// (ksh->krd_array_length > 0) ) -// { -// if (! GNUNET_TIME_absolute_is_zero (last_issue_date.abs_time)) -// GNUNET_log (GNUNET_ERROR_TYPE_WARNING, -// "Client provided invalid cherry picking timestamp %s, returning full response\n", -// GNUNET_TIME_timestamp2s (last_issue_date)); -// krd = &ksh->krd_array[ksh->krd_array_length - 1]; -// } -// if (NULL == krd) -// { -// /* Likely keys not ready *yet*. -// Wait until they are. */ -// return suspend_request (rc->connection); -// } -// if ( (NULL != etag) && -// (0 == strcmp (etag, -// krd->etag)) ) -// return DH_RESPONSE_reply_not_modified (rc->connection, -// krd->etag, -// &setup_general_response_headers, -// ksh); -// -// return MHD_queue_response (rc->connection, -// MHD_HTTP_OK, -// (MHD_YES == -// TALER_MHD_can_compress (rc->connection)) -// ? krd->response_compressed -// : krd->response_uncompressed); -// } -// } - - /* end of donau-httpd_keys.c */ diff --git a/src/include/Makefile.am b/src/include/Makefile.am @@ -1,7 +1,7 @@ # This Makefile.am is in the public domain -talerincludedir = $(includedir)/taler +donauincludedir = $(includedir)/donau -talerinclude_HEADERS = \ +donauinclude_HEADERS = \ donau_service.h \ donau_signatures.h \ donaudb_lib.h \ diff --git a/src/include/donau_json_lib.h b/src/include/donau_json_lib.h @@ -71,4 +71,17 @@ struct GNUNET_JSON_PackSpec DONAU_JSON_pack_uint32 (const char *name, uint64_t num); +/** + * Generate packer instruction for a JSON field of type + * denomination public key. + * + * @param name name of the field to add to the object + * @param pk public key + * @return json pack specification + */ +struct GNUNET_JSON_PackSpec +DONAU_JSON_pack_donation_unit_pub ( + const char *name, + const struct DONAU_DonationUnitPublicKey *pk); + #endif diff --git a/src/json/json_helper.c b/src/json/json_helper.c @@ -26,624 +26,4 @@ #include <taler/taler_json_lib.h> -/** - * Convert string value to numeric cipher value. - * - * @param cipher_s input string - * @return numeric cipher value - */ -static enum GNUNET_CRYPTO_BlindSignatureAlgorithm -string_to_cipher (const char *cipher_s) -{ - if ((0 == strcasecmp (cipher_s, - "RSA"))) - return GNUNET_CRYPTO_BSA_RSA; - if ((0 == strcasecmp (cipher_s, - "CS"))) - return GNUNET_CRYPTO_BSA_CS; - return GNUNET_CRYPTO_BSA_INVALID; -} - - -json_t * -TALER_JSON_from_amount (const struct TALER_Amount *amount) -{ - char *amount_str = TALER_amount_to_string (amount); - - GNUNET_assert (NULL != amount_str); - { - json_t *j = json_string (amount_str); - - GNUNET_free (amount_str); - return j; - } -} - - -/** - * Parse given JSON object to Amount - * - * @param cls closure, expected currency, or NULL - * @param root the json object representing data - * @param[out] spec where to write the data - * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error - */ -static enum GNUNET_GenericReturnValue -parse_amount (void *cls, - json_t *root, - struct GNUNET_JSON_Specification *spec) -{ - const char *currency = cls; - struct TALER_Amount *r_amount = spec->ptr; - - (void) cls; - if (! json_is_string (root)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if (GNUNET_OK != - TALER_string_to_amount (json_string_value (root), - r_amount)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if ( (NULL != currency) && - (0 != - strcasecmp (currency, - r_amount->currency)) ) - { - GNUNET_break_op (0); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Expected currency `%s', but amount used currency `%s' in field `%s'\n", - currency, - r_amount->currency, - spec->field); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -struct GNUNET_JSON_Specification -TALER_JSON_spec_amount (const char *name, - const char *currency, - struct TALER_Amount *r_amount) -{ - struct GNUNET_JSON_Specification ret = { - .parser = &parse_amount, - .cleaner = NULL, - .cls = (void *) currency, - .field = name, - .ptr = r_amount, - .ptr_size = 0, - .size_ptr = NULL - }; - - GNUNET_assert (NULL != currency); - return ret; -} - - -struct GNUNET_JSON_Specification -TALER_JSON_spec_amount_any (const char *name, - struct TALER_Amount *r_amount) -{ - struct GNUNET_JSON_Specification ret = { - .parser = &parse_amount, - .cleaner = NULL, - .cls = NULL, - .field = name, - .ptr = r_amount, - .ptr_size = 0, - .size_ptr = NULL - }; - - return ret; -} - - -/** - * Parse given JSON object to currency spec. - * - * @param cls closure, NULL - * @param root the json object representing data - * @param[out] spec where to write the data - * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error - */ -static enum GNUNET_GenericReturnValue -parse_cspec (void *cls, - json_t *root, - struct GNUNET_JSON_Specification *spec) -{ - struct TALER_CurrencySpecification *r_cspec = spec->ptr; - const char *currency = spec->cls; - const char *name; - uint32_t fid; - uint32_t fnd; - uint32_t ftzd; - const json_t *map; - struct GNUNET_JSON_Specification gspec[] = { - GNUNET_JSON_spec_string ("name", - &name), - GNUNET_JSON_spec_uint32 ("num_fractional_input_digits", - &fid), - GNUNET_JSON_spec_uint32 ("num_fractional_normal_digits", - &fnd), - GNUNET_JSON_spec_uint32 ("num_fractional_trailing_zero_digits", - &ftzd), - GNUNET_JSON_spec_object_const ("alt_unit_names", - &map), - GNUNET_JSON_spec_end () - }; - const char *emsg; - unsigned int eline; - - memset (r_cspec->currency, - 0, - sizeof (r_cspec->currency)); - if (GNUNET_OK != - GNUNET_JSON_parse (root, - gspec, - &emsg, - &eline)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to parse %s at %u: %s\n", - spec[eline].field, - eline, - emsg); - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if (strlen (currency) >= TALER_CURRENCY_LEN) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if ( (fid > TALER_AMOUNT_FRAC_LEN) || - (fnd > TALER_AMOUNT_FRAC_LEN) || - (ftzd > TALER_AMOUNT_FRAC_LEN) ) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if (GNUNET_OK != - TALER_check_currency (currency)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - strcpy (r_cspec->currency, - currency); - if (GNUNET_OK != - TALER_check_currency_scale_map (map)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - r_cspec->name = GNUNET_strdup (name); - r_cspec->map_alt_unit_names = json_incref ((json_t *) map); - return GNUNET_OK; -} - - -/** - * Cleanup data left from parsing encrypted contract. - * - * @param cls closure, NULL - * @param[out] spec where to free the data - */ -static void -clean_cspec (void *cls, - struct GNUNET_JSON_Specification *spec) -{ - struct TALER_CurrencySpecification *cspec = spec->ptr; - - (void) cls; - GNUNET_free (cspec->name); - json_decref (cspec->map_alt_unit_names); -} - - -struct GNUNET_JSON_Specification -TALER_JSON_spec_currency_specification ( - const char *name, - const char *currency, - struct TALER_CurrencySpecification *r_cspec) -{ - struct GNUNET_JSON_Specification ret = { - .parser = &parse_cspec, - .cleaner = &clean_cspec, - .cls = (void *) currency, - .field = name, - .ptr = r_cspec, - .ptr_size = sizeof (*r_cspec), - .size_ptr = NULL - }; - - memset (r_cspec, - 0, - sizeof (*r_cspec)); - return ret; -} - - -/** - * Parse given JSON object to an encrypted contract. - * - * @param cls closure, NULL - * @param root the json object representing data - * @param[out] spec where to write the data - * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error - */ -static enum GNUNET_GenericReturnValue -parse_econtract (void *cls, - json_t *root, - struct GNUNET_JSON_Specification *spec) -{ - struct TALER_EncryptedContract *econtract = spec->ptr; - struct GNUNET_JSON_Specification ispec[] = { - GNUNET_JSON_spec_varsize ("econtract", - &econtract->econtract, - &econtract->econtract_size), - GNUNET_JSON_spec_fixed_auto ("econtract_sig", - &econtract->econtract_sig), - GNUNET_JSON_spec_fixed_auto ("contract_pub", - &econtract->contract_pub), - GNUNET_JSON_spec_end () - }; - const char *emsg; - unsigned int eline; - - (void) cls; - if (GNUNET_OK != - GNUNET_JSON_parse (root, - ispec, - &emsg, - &eline)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -/** - * Cleanup data left from parsing encrypted contract. - * - * @param cls closure, NULL - * @param[out] spec where to free the data - */ -static void -clean_econtract (void *cls, - struct GNUNET_JSON_Specification *spec) -{ - struct TALER_EncryptedContract *econtract = spec->ptr; - - (void) cls; - GNUNET_free (econtract->econtract); -} - - -struct GNUNET_JSON_Specification -TALER_JSON_spec_econtract (const char *name, - struct TALER_EncryptedContract *econtract) -{ - struct GNUNET_JSON_Specification ret = { - .parser = &parse_econtract, - .cleaner = &clean_econtract, - .field = name, - .ptr = econtract - }; - - return ret; -} - - -/** - * Closure for #parse_i18n_string. - */ -struct I18nContext -{ - /** - * Language pattern to match. - */ - char *lp; - - /** - * Name of the field to match. - */ - const char *field; -}; - - -/** - * Parse given JSON object to internationalized string. - * - * @param cls closure, our `struct I18nContext *` - * @param root the json object representing data - * @param[out] spec where to write the data - * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error - */ -static enum GNUNET_GenericReturnValue -parse_i18n_string (void *cls, - json_t *root, - struct GNUNET_JSON_Specification *spec) -{ - struct I18nContext *ctx = cls; - json_t *i18n; - json_t *val; - - { - char *i18nf; - - GNUNET_asprintf (&i18nf, - "%s_i18n", - ctx->field); - i18n = json_object_get (root, - i18nf); - GNUNET_free (i18nf); - } - - val = json_object_get (root, - ctx->field); - if ( (NULL != i18n) && - (NULL != ctx->lp) ) - { - double best = 0.0; - json_t *pos; - const char *lang; - - json_object_foreach (i18n, lang, pos) - { - double score; - - score = TALER_language_matches (ctx->lp, - lang); - if (score > best) - { - best = score; - val = pos; - } - } - } - - { - const char *str; - - str = json_string_value (val); - *(const char **) spec->ptr = str; - } - return GNUNET_OK; -} - - -/** - * Function called to clean up data from earlier parsing. - * - * @param cls closure - * @param spec our specification entry with data to clean. - */ -static void -i18n_cleaner (void *cls, - struct GNUNET_JSON_Specification *spec) -{ - struct I18nContext *ctx = cls; - - (void) spec; - if (NULL != ctx) - { - GNUNET_free (ctx->lp); - GNUNET_free (ctx); - } -} - - -struct GNUNET_JSON_Specification -TALER_JSON_spec_i18n_string (const char *name, - const char *language_pattern, - const char **strptr) -{ - struct I18nContext *ctx = GNUNET_new (struct I18nContext); - struct GNUNET_JSON_Specification ret = { - .parser = &parse_i18n_string, - .cleaner = &i18n_cleaner, - .cls = ctx, - .field = NULL, /* we want the main object */ - .ptr = strptr, - .ptr_size = 0, - .size_ptr = NULL - }; - - ctx->lp = (NULL != language_pattern) - ? GNUNET_strdup (language_pattern) - : NULL; - ctx->field = name; - *strptr = NULL; - return ret; -} - - -struct GNUNET_JSON_Specification -TALER_JSON_spec_i18n_str (const char *name, - const char **strptr) -{ - const char *lang = getenv ("LANG"); - char *dot; - char *l; - struct GNUNET_JSON_Specification ret; - - if (NULL != lang) - { - dot = strchr (lang, - '.'); - if (NULL == dot) - l = GNUNET_strdup (lang); - else - l = GNUNET_strndup (lang, - dot - lang); - } - else - { - l = NULL; - } - ret = TALER_JSON_spec_i18n_string (name, - l, - strptr); - GNUNET_free (l); - return ret; -} - - -/** - * Parse given JSON object with Taler error code. - * - * @param cls closure, NULL - * @param root the json object representing data - * @param[out] spec where to write the data - * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error - */ -static enum GNUNET_GenericReturnValue -parse_ec (void *cls, - json_t *root, - struct GNUNET_JSON_Specification *spec) -{ - enum TALER_ErrorCode *ec = spec->ptr; - json_int_t num; - - (void) cls; - if (! json_is_integer (root)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - num = json_integer_value (root); - if (num < 0) - { - GNUNET_break_op (0); - *ec = TALER_EC_INVALID; - return GNUNET_SYSERR; - } - *ec = (enum TALER_ErrorCode) num; - return GNUNET_OK; -} - - -struct GNUNET_JSON_Specification -TALER_JSON_spec_ec (const char *field, - enum TALER_ErrorCode *ec) -{ - struct GNUNET_JSON_Specification ret = { - .parser = &parse_ec, - .field = field, - .ptr = ec - }; - - *ec = TALER_EC_NONE; - return ret; -} - - -/** - * Parse given JSON object to web URL. - * - * @param cls closure, NULL - * @param root the json object representing data - * @param[out] spec where to write the data - * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error - */ -static enum GNUNET_GenericReturnValue -parse_web_url (void *cls, - json_t *root, - struct GNUNET_JSON_Specification *spec) -{ - const char *str; - - (void) cls; - str = json_string_value (root); - if (NULL == str) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if (! TALER_is_web_url (str)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - *(const char **) spec->ptr = str; - return GNUNET_OK; -} - - -struct GNUNET_JSON_Specification -TALER_JSON_spec_web_url (const char *field, - const char **url) -{ - struct GNUNET_JSON_Specification ret = { - .parser = &parse_web_url, - .field = field, - .ptr = url - }; - - *url = NULL; - return ret; -} - - -/** - * Parse given JSON object with protocol version. - * - * @param cls closure, NULL - * @param root the json object representing data - * @param[out] spec where to write the data - * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error - */ -static enum GNUNET_GenericReturnValue -parse_protocol_version (void *cls, - json_t *root, - struct GNUNET_JSON_Specification *spec) -{ - struct TALER_JSON_ProtocolVersion *pv = spec->ptr; - const char *ver; - char dummy; - - (void) cls; - if (! json_is_string (root)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - ver = json_string_value (root); - if (3 != sscanf (ver, - "%u:%u:%u%c", - &pv->current, - &pv->revision, - &pv->age, - &dummy)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -struct GNUNET_JSON_Specification -TALER_JSON_spec_version (const char *field, - struct TALER_JSON_ProtocolVersion *ver) -{ - struct GNUNET_JSON_Specification ret = { - .parser = &parse_protocol_version, - .field = field, - .ptr = ver - }; - - return ret; -} - - /* end of json/json_helper.c */ diff --git a/src/json/json_pack.c b/src/json/json_pack.c @@ -22,84 +22,12 @@ #include <gnunet/gnunet_util_lib.h> #include <taler/taler_util.h> #include <taler/taler_json_lib.h> - - -struct GNUNET_JSON_PackSpec -TALER_JSON_pack_time_abs_human (const char *name, - struct GNUNET_TIME_Absolute at) -{ - struct GNUNET_JSON_PackSpec ps = { - .field_name = name, - .object = json_string ( - GNUNET_STRINGS_absolute_time_to_string (at)) - }; - - return ps; -} - - -struct GNUNET_JSON_PackSpec -TALER_JSON_pack_econtract ( - const char *name, - const struct TALER_EncryptedContract *econtract) -{ - struct GNUNET_JSON_PackSpec ps = { - .field_name = name, - }; - - if (NULL == econtract) - return ps; - ps.object - = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_data_varsize ("econtract", - econtract->econtract, - econtract->econtract_size), - GNUNET_JSON_pack_data_auto ("econtract_sig", - &econtract->econtract_sig), - GNUNET_JSON_pack_data_auto ("contract_pub", - &econtract->contract_pub)); - return ps; -} - +#include <donau_util.h> struct GNUNET_JSON_PackSpec -TALER_JSON_pack_age_commitment ( +DONAU_JSON_pack_donation_unit_pub ( const char *name, - const struct TALER_AgeCommitment *age_commitment) -{ - struct GNUNET_JSON_PackSpec ps = { - .field_name = name, - }; - json_t *keys; - - if (NULL == age_commitment || - 0 == age_commitment->num) - return ps; - - GNUNET_assert (NULL != - (keys = json_array ())); - - for (size_t i = 0; - i < age_commitment->num; - i++) - { - json_t *val; - val = GNUNET_JSON_from_data (&age_commitment->keys[i], - sizeof(age_commitment->keys[i])); - GNUNET_assert (NULL != val); - GNUNET_assert (0 == - json_array_append_new (keys, val)); - } - - ps.object = keys; - return ps; -} - - -struct GNUNET_JSON_PackSpec -TALER_JSON_pack_denom_pub ( - const char *name, - const struct TALER_DenominationPublicKey *pk) + const struct DONAU_DonationUnitPublicKey *pk) { const struct GNUNET_CRYPTO_BlindSignPublicKey *bsp; struct GNUNET_JSON_PackSpec ps = { @@ -118,8 +46,6 @@ TALER_JSON_pack_denom_pub ( = GNUNET_JSON_PACK ( GNUNET_JSON_pack_string ("cipher", "RSA"), - GNUNET_JSON_pack_uint64 ("age_mask", - pk->age_mask.bits), GNUNET_JSON_pack_rsa_public_key ("rsa_public_key", bsp->details.rsa_public_key)); return ps; @@ -128,8 +54,6 @@ TALER_JSON_pack_denom_pub ( = GNUNET_JSON_PACK ( GNUNET_JSON_pack_string ("cipher", "CS"), - GNUNET_JSON_pack_uint64 ("age_mask", - pk->age_mask.bits), GNUNET_JSON_pack_data_varsize ("cs_public_key", &bsp->details.cs_public_key, sizeof (bsp->details.cs_public_key))); @@ -140,185 +64,4 @@ TALER_JSON_pack_denom_pub ( } -struct GNUNET_JSON_PackSpec -TALER_JSON_pack_denom_sig ( - const char *name, - const struct TALER_DenominationSignature *sig) -{ - const struct GNUNET_CRYPTO_UnblindedSignature *bs; - struct GNUNET_JSON_PackSpec ps = { - .field_name = name, - }; - - if (NULL == sig) - return ps; - bs = sig->unblinded_sig; - switch (bs->cipher) - { - case GNUNET_CRYPTO_BSA_INVALID: - break; - case GNUNET_CRYPTO_BSA_RSA: - ps.object = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("cipher", - "RSA"), - GNUNET_JSON_pack_rsa_signature ("rsa_signature", - bs->details.rsa_signature)); - return ps; - case GNUNET_CRYPTO_BSA_CS: - ps.object = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("cipher", - "CS"), - GNUNET_JSON_pack_data_auto ("cs_signature_r", - &bs->details.cs_signature.r_point), - GNUNET_JSON_pack_data_auto ("cs_signature_s", - &bs->details.cs_signature.s_scalar)); - return ps; - } - GNUNET_assert (0); - return ps; -} - - -struct GNUNET_JSON_PackSpec -TALER_JSON_pack_exchange_withdraw_values ( - const char *name, - const struct TALER_ExchangeWithdrawValues *ewv) -{ - const struct GNUNET_CRYPTO_BlindingInputValues *biv; - struct GNUNET_JSON_PackSpec ps = { - .field_name = name, - }; - - if (NULL == ewv) - return ps; - biv = ewv->blinding_inputs; - switch (biv->cipher) - { - case GNUNET_CRYPTO_BSA_INVALID: - break; - case GNUNET_CRYPTO_BSA_RSA: - ps.object = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("cipher", - "RSA")); - return ps; - case GNUNET_CRYPTO_BSA_CS: - ps.object = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("cipher", - "CS"), - GNUNET_JSON_pack_data_varsize ( - "r_pub_0", - &biv->details.cs_values.r_pub[0], - sizeof(struct GNUNET_CRYPTO_CsRPublic)), - GNUNET_JSON_pack_data_varsize ( - "r_pub_1", - &biv->details.cs_values.r_pub[1], - sizeof(struct GNUNET_CRYPTO_CsRPublic)) - ); - return ps; - } - GNUNET_assert (0); - return ps; -} - - -struct GNUNET_JSON_PackSpec -TALER_JSON_pack_blinded_denom_sig ( - const char *name, - const struct TALER_BlindedDenominationSignature *sig) -{ - const struct GNUNET_CRYPTO_BlindedSignature *bs; - struct GNUNET_JSON_PackSpec ps = { - .field_name = name, - }; - - if (NULL == sig) - return ps; - bs = sig->blinded_sig; - switch (bs->cipher) - { - case GNUNET_CRYPTO_BSA_INVALID: - break; - case GNUNET_CRYPTO_BSA_RSA: - ps.object = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("cipher", - "RSA"), - GNUNET_JSON_pack_rsa_signature ("blinded_rsa_signature", - bs->details.blinded_rsa_signature)); - return ps; - case GNUNET_CRYPTO_BSA_CS: - ps.object = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("cipher", - "CS"), - GNUNET_JSON_pack_uint64 ("b", - bs->details.blinded_cs_answer.b), - GNUNET_JSON_pack_data_auto ("s", - &bs->details.blinded_cs_answer.s_scalar)); - return ps; - } - GNUNET_assert (0); - return ps; -} - - -struct GNUNET_JSON_PackSpec -TALER_JSON_pack_blinded_planchet ( - const char *name, - const struct TALER_BlindedPlanchet *blinded_planchet) -{ - const struct GNUNET_CRYPTO_BlindedMessage *bm; - struct GNUNET_JSON_PackSpec ps = { - .field_name = name, - }; - - if (NULL == blinded_planchet) - return ps; - bm = blinded_planchet->blinded_message; - switch (bm->cipher) - { - case GNUNET_CRYPTO_BSA_INVALID: - break; - case GNUNET_CRYPTO_BSA_RSA: - ps.object = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("cipher", - "RSA"), - GNUNET_JSON_pack_data_varsize ( - "rsa_blinded_planchet", - bm->details.rsa_blinded_message.blinded_msg, - bm->details.rsa_blinded_message.blinded_msg_size)); - return ps; - case GNUNET_CRYPTO_BSA_CS: - ps.object = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("cipher", - "CS"), - GNUNET_JSON_pack_data_auto ( - "cs_nonce", - &bm->details.cs_blinded_message.nonce), - GNUNET_JSON_pack_data_auto ( - "cs_blinded_c0", - &bm->details.cs_blinded_message.c[0]), - GNUNET_JSON_pack_data_auto ( - "cs_blinded_c1", - &bm->details.cs_blinded_message.c[1])); - return ps; - } - GNUNET_assert (0); - return ps; -} - - -struct GNUNET_JSON_PackSpec -TALER_JSON_pack_amount (const char *name, - const struct TALER_Amount *amount) -{ - struct GNUNET_JSON_PackSpec ps = { - .field_name = name, - .object = (NULL != amount) - ? TALER_JSON_from_amount (amount) - : NULL - }; - - return ps; -} - - /* End of json/json_pack.c */