From 2ca543cd073a55f241c39b0905588a20882f7c93 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 15 Jun 2015 14:18:37 +0200 Subject: fix #3818 and handle coins being melted into multiple sessions --- src/mint/taler-mint-httpd_db.c | 145 ++++++++++++++++++++++++++-------- src/mint/taler-mint-httpd_responses.c | 89 +++++++++++---------- src/mint/taler-mint-httpd_responses.h | 34 ++++++-- 3 files changed, 189 insertions(+), 79 deletions(-) (limited to 'src/mint') diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index 26122d1e1..8a46a1839 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -1231,6 +1231,92 @@ TMH_DB_execute_refresh_reveal (struct MHD_Connection *connection, } +/** + * Closure for #handle_transfer_data(). + */ +struct HTD_Context +{ + + /** + * Session link data we collect. + */ + struct TMH_RESPONSE_LinkSessionInfo *sessions; + + /** + * Database session. Nothing to do with @a sessions. + */ + struct TALER_MINTDB_Session *session; + + /** + * MHD connection, for queueing replies. + */ + struct MHD_Connection *connection; + + /** + * Number of sessions the coin was melted into. + */ + unsigned int num_sessions; + + /** + * How are we expected to proceed. #GNUNET_SYSERR if we + * failed to return an error (should return #MHD_NO). + * #GNUNET_NO if we succeeded in queueing an MHD error + * (should return #MHD_YES from #TMH_execute_refresh_link), + * #GNUNET_OK if we should call #TMH_RESPONSE_reply_refresh_link_success(). + */ + int status; +}; + + +/** + * Function called with the session hashes and transfer secret + * information for a given coin. Gets the linkage data and + * builds the reply for the client. + * + * + * @param cls closure, a `struct HTD_Context` + * @param session_hash a session the coin was melted in + * @param transfer_pub public transfer key for the session + * @param shared_secret_enc set to shared secret for the session + */ +static void +handle_transfer_data (void *cls, + const struct GNUNET_HashCode *session_hash, + const struct TALER_TransferPublicKeyP *transfer_pub, + const struct TALER_EncryptedLinkSecretP *shared_secret_enc) +{ + struct HTD_Context *ctx = cls; + struct TALER_MINTDB_LinkDataList *ldl; + struct TMH_RESPONSE_LinkSessionInfo *lsi; + + if (GNUNET_OK != ctx->status) + return; + ldl = TMH_plugin->get_link_data_list (TMH_plugin->cls, + ctx->session, + session_hash); + if (NULL == ldl) + { + GNUNET_break (0); + ctx->status = GNUNET_NO; + if (MHD_NO == + TMH_RESPONSE_reply_json_pack (ctx->connection, + MHD_HTTP_NOT_FOUND, + "{s:s}", + "error", + "link data not found (link)")) + ctx->status = GNUNET_SYSERR; + return; + } + GNUNET_array_grow (ctx->sessions, + ctx->num_sessions, + ctx->num_sessions + 1); + lsi = &ctx->sessions[ctx->num_sessions - 1]; + lsi->transfer_pub = *transfer_pub; + lsi->shared_secret_enc = *shared_secret_enc; + lsi->ldl = ldl; +} + + /** * Execute a "/refresh/link". Returns the linkage information that * will allow the owner of a coin to follow the refresh trail to @@ -1244,52 +1330,47 @@ int TMH_DB_execute_refresh_link (struct MHD_Connection *connection, const struct TALER_CoinSpendPublicKeyP *coin_pub) { + struct HTD_Context ctx; int res; - struct TALER_MINTDB_Session *session; - struct TALER_TransferPublicKeyP transfer_pub; - struct TALER_EncryptedLinkSecretP shared_secret_enc; - struct TALER_MINTDB_LinkDataList *ldl; + unsigned int i; - if (NULL == (session = TMH_plugin->get_session (TMH_plugin->cls, - GNUNET_NO))) + if (NULL == (ctx.session = TMH_plugin->get_session (TMH_plugin->cls, + GNUNET_NO))) { GNUNET_break (0); return TMH_RESPONSE_reply_internal_db_error (connection); } + ctx.connection = connection; + ctx.num_sessions = 0; + ctx.sessions = NULL; + ctx.status = GNUNET_OK; res = TMH_plugin->get_transfer (TMH_plugin->cls, - session, + ctx.session, coin_pub, - &transfer_pub, - &shared_secret_enc); - if (GNUNET_SYSERR == res) + &handle_transfer_data, + &ctx); + if (GNUNET_SYSERR == ctx.status) { - GNUNET_break (0); - return TMH_RESPONSE_reply_internal_db_error (connection); + res = MHD_NO; + goto cleanup; } - if (GNUNET_NO == res) + if (GNUNET_NO == ctx.status) { + res = MHD_YES; + goto cleanup; + } + GNUNET_assert (GNUNET_OK == ctx.status); + if (0 == ctx.num_sessions) return TMH_RESPONSE_reply_arg_unknown (connection, "coin_pub"); - } - GNUNET_assert (GNUNET_OK == res); - - ldl = TMH_plugin->get_link_data_list (TMH_plugin->cls, - session, - coin_pub); - if (NULL == ldl) - { - return TMH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_NOT_FOUND, - "{s:s}", - "error", - "link data not found (link)"); - } res = TMH_RESPONSE_reply_refresh_link_success (connection, - &transfer_pub, - &shared_secret_enc, - ldl); - TMH_plugin->free_link_data_list (TMH_plugin->cls, - ldl); + ctx.num_sessions, + ctx.sessions); + cleanup: + for (i=0;ifree_link_data_list (TMH_plugin->cls, + ctx.sessions[i].ldl); + GNUNET_free (ctx.sessions); return res; } diff --git a/src/mint/taler-mint-httpd_responses.c b/src/mint/taler-mint-httpd_responses.c index f8240df52..ccc144e29 100644 --- a/src/mint/taler-mint-httpd_responses.c +++ b/src/mint/taler-mint-httpd_responses.c @@ -908,58 +908,65 @@ TMH_RESPONSE_reply_refresh_reveal_missmatch (struct MHD_Connection *connection, * Send a response for "/refresh/link". * * @param connection the connection to send the response to - * @param transfer_pub transfer public key - * @param shared_secret_enc encrypted shared secret - * @param ldl linked list with link data + * @param num_sessions number of sessions the coin was used in + * @param sessions array of @a num_session entries with + * information for each session * @return a MHD result code */ int TMH_RESPONSE_reply_refresh_link_success (struct MHD_Connection *connection, - const struct TALER_TransferPublicKeyP *transfer_pub, - const struct TALER_EncryptedLinkSecretP *shared_secret_enc, - const struct TALER_MINTDB_LinkDataList *ldl) + unsigned int num_sessions, + const struct TMH_RESPONSE_LinkSessionInfo *sessions) { - const struct TALER_MINTDB_LinkDataList *pos; json_t *root; - json_t *list; + json_t *mlist; int res; + unsigned int i; - list = json_array (); - for (pos = ldl; NULL != pos; pos = pos->next) + mlist = json_array (); + for (i=0;ilink_data_enc->coin_priv_enc, - sizeof (struct TALER_CoinSpendPrivateKeyP) + - ldl->link_data_enc->blinding_key_enc_size)); - json_object_set_new (obj, - "denom_pub", - TALER_json_from_rsa_public_key (ldl->denom_pub.rsa_public_key)); - json_object_set_new (obj, - "ev_sig", - TALER_json_from_rsa_signature (ldl->ev_sig.rsa_signature)); - json_array_append_new (list, obj); - } + const struct TALER_MINTDB_LinkDataList *pos; + json_t *list = json_array (); - root = json_object (); - json_object_set_new (root, - "new_coins", - list); - json_object_set_new (root, - "transfer_pub", - TALER_json_from_data (transfer_pub, - sizeof (struct TALER_TransferPublicKeyP))); - json_object_set_new (root, - "secret_enc", - TALER_json_from_data (shared_secret_enc, - sizeof (struct TALER_EncryptedLinkSecretP))); + for (pos = sessions[i].ldl; NULL != pos; pos = pos->next) + { + json_t *obj; + + obj = json_object (); + json_object_set_new (obj, + "link_enc", + TALER_json_from_data (pos->link_data_enc->coin_priv_enc, + sizeof (struct TALER_CoinSpendPrivateKeyP) + + pos->link_data_enc->blinding_key_enc_size)); + json_object_set_new (obj, + "denom_pub", + TALER_json_from_rsa_public_key (pos->denom_pub.rsa_public_key)); + json_object_set_new (obj, + "ev_sig", + TALER_json_from_rsa_signature (pos->ev_sig.rsa_signature)); + json_array_append_new (list, + obj); + } + root = json_object (); + json_object_set_new (root, + "new_coins", + list); + json_object_set_new (root, + "transfer_pub", + TALER_json_from_data (&sessions[i].transfer_pub, + sizeof (struct TALER_TransferPublicKeyP))); + json_object_set_new (root, + "secret_enc", + TALER_json_from_data (&sessions[i].shared_secret_enc, + sizeof (struct TALER_EncryptedLinkSecretP))); + json_array_append_new (mlist, + root); + } res = TMH_RESPONSE_reply_json (connection, - root, - MHD_HTTP_OK); - json_decref (root); + mlist, + MHD_HTTP_OK); + json_decref (mlist); return res; } diff --git a/src/mint/taler-mint-httpd_responses.h b/src/mint/taler-mint-httpd_responses.h index 8392e73d7..2ae06209d 100644 --- a/src/mint/taler-mint-httpd_responses.h +++ b/src/mint/taler-mint-httpd_responses.h @@ -334,20 +334,42 @@ TMH_RESPONSE_reply_refresh_reveal_missmatch (struct MHD_Connection *connection, const char *missmatch_object); +/** + * Information for each session a coin was melted into. + */ +struct TMH_RESPONSE_LinkSessionInfo +{ + /** + * Transfer public key of the coin. + */ + struct TALER_TransferPublicKeyP transfer_pub; + + /** + * Encrypted shared secret for decrypting the transfer secrets. + */ + struct TALER_EncryptedLinkSecretP shared_secret_enc; + + /** + * Linked data of coins being created in the session. + */ + struct TALER_MINTDB_LinkDataList *ldl; + +}; + + /** * Send a response for "/refresh/link". * * @param connection the connection to send the response to - * @param transfer_pub transfer public key - * @param shared_secret_enc encrypted shared secret - * @param ldl linked list with link data + * @param num_sessions number of sessions the coin was used in + * @param sessions array of @a num_session entries with + * information for each session * @return a MHD result code */ int TMH_RESPONSE_reply_refresh_link_success (struct MHD_Connection *connection, - const struct TALER_TransferPublicKeyP *transfer_pub, - const struct TALER_EncryptedLinkSecretP *shared_secret_enc, - const struct TALER_MINTDB_LinkDataList *ldl); + unsigned int num_sessions, + const struct TMH_RESPONSE_LinkSessionInfo *sessions); #endif -- cgit v1.2.3