diff options
author | Christian Grothoff <christian@grothoff.org> | 2015-08-08 23:03:26 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2015-08-08 23:03:26 +0200 |
commit | 7e47853a5e2bbba529fad06a349d67439d03e5ab (patch) | |
tree | 28b13ba065eaee768bfe3ca6a02337c5ec8ea15a | |
parent | cb47e13322e3fefac95a80b4a32d2551f62202d1 (diff) |
implement parse_refresh_link_ok
-rw-r--r-- | src/include/taler_mint_service.h | 2 | ||||
-rw-r--r-- | src/mint-lib/mint_api_refresh_link.c | 231 | ||||
-rw-r--r-- | src/mint-lib/mint_api_withdraw.c | 1 |
3 files changed, 206 insertions, 28 deletions
diff --git a/src/include/taler_mint_service.h b/src/include/taler_mint_service.h index fa1f7a507..ea06d95fb 100644 --- a/src/include/taler_mint_service.h +++ b/src/include/taler_mint_service.h @@ -841,6 +841,7 @@ struct TALER_MINT_RefreshLinkHandle; * @param num_coins number of fresh coins created, length of the @a sigs and @a coin_privs arrays, 0 if the operation failed * @param coin_privs array of @a num_coins private keys for the coins that were created, NULL on error * @param sigs array of signature over @a num_coins coins, NULL on error + * @param pubs array of public keys for the @a sigs, NULL on error * @param full_response full response from the mint (for logging, in case of errors) */ typedef void @@ -849,6 +850,7 @@ typedef void unsigned int num_coins, const struct TALER_CoinSpendPrivateKeyP *coin_privs, const struct TALER_DenominationSignature *sigs, + const struct TALER_DenominationPublicKey *pubs, json_t *full_response); diff --git a/src/mint-lib/mint_api_refresh_link.c b/src/mint-lib/mint_api_refresh_link.c index 3ea6b23e4..f17949af0 100644 --- a/src/mint-lib/mint_api_refresh_link.c +++ b/src/mint-lib/mint_api_refresh_link.c @@ -48,11 +48,6 @@ struct TALER_MINT_RefreshLinkHandle char *url; /** - * JSON encoding of the request to POST. - */ - char *json_enc; - - /** * Handle for the request. */ struct MAC_Job *job; @@ -72,10 +67,191 @@ struct TALER_MINT_RefreshLinkHandle */ struct MAC_DownloadBuffer db; + /** + * Private key of the coin, required to decode link information. + */ + struct TALER_CoinSpendPrivateKeyP coin_priv; + }; /** + * Parse the provided linkage data from the "200 OK" response + * for one of the coins. + * + * @param rlh refresh link handle + * @param json json reply with the data for one coin + * @param trans_pub our transfer public key + * @param secret_enc encrypted key to decrypt link data + * @param[out] coin_priv where to return private coin key + * @param[out] sig where to return private coin signature + * @param[out] pub where to return the public key for the coin + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + */ +static int +parse_refresh_link_coin (const struct TALER_MINT_RefreshLinkHandle *rlh, + json_t *json, + const struct TALER_TransferPublicKeyP *trans_pub, + const struct TALER_EncryptedLinkSecretP *secret_enc, + struct TALER_CoinSpendPrivateKeyP *coin_priv, + struct TALER_DenominationSignature *sig, + struct TALER_DenominationPublicKey *pub) +{ + void *link_enc; + size_t link_enc_size; + struct GNUNET_CRYPTO_rsa_Signature *bsig; + struct MAJ_Specification spec[] = { + MAJ_spec_varsize ("link_enc", &link_enc, &link_enc_size), + MAJ_spec_rsa_public_key ("denom_pub", &pub->rsa_public_key), + MAJ_spec_rsa_signature ("ev_sig", &bsig), + MAJ_spec_end + }; + struct TALER_RefreshLinkEncrypted *rle; + struct TALER_RefreshLinkDecrypted *rld; + struct TALER_LinkSecretP secret; + + /* parse reply */ + if (GNUNET_OK != + MAJ_parse_json (json, + spec)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + + /* decode and decrypt link data */ + rle = TALER_refresh_link_encrypted_decode (link_enc, + link_enc_size); + if (NULL == rle) + { + GNUNET_break_op (0); + MAJ_parse_free (spec); + return GNUNET_SYSERR; + } + if (GNUNET_OK != + TALER_link_decrypt_secret2 (secret_enc, + trans_pub, + &rlh->coin_priv, + &secret)) + { + GNUNET_break_op (0); + MAJ_parse_free (spec); + return GNUNET_SYSERR; + } + rld = TALER_refresh_decrypt (rle, + &secret); + if (NULL == rld) + { + GNUNET_break_op (0); + MAJ_parse_free (spec); + return GNUNET_SYSERR; + } + + /* extract coin and signature */ + *coin_priv = rld->coin_priv; + sig->rsa_signature + = GNUNET_CRYPTO_rsa_unblind (bsig, + rld->blinding_key.rsa_blinding_key, + pub->rsa_public_key); + + /* clean up */ + GNUNET_free (rld); + MAJ_parse_free (spec); + return GNUNET_OK; +} + + +/** + * Parse the provided linkage data from the "200 OK" response + * for one of the coins. + * + * @param[in,out] rlh refresh link handle (callback may be zero'ed out) + * @param json json reply with the data for one coin + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + */ +static int +parse_refresh_link_ok (struct TALER_MINT_RefreshLinkHandle *rlh, + json_t *json) +{ + json_t *jsona; + struct TALER_TransferPublicKeyP trans_pub; + struct TALER_EncryptedLinkSecretP secret_enc; + struct MAJ_Specification spec[] = { + MAJ_spec_json ("new_coins", &jsona), + MAJ_spec_fixed_auto ("trans_pub", &trans_pub), + MAJ_spec_fixed_auto ("secret_enc", &secret_enc), + MAJ_spec_end + }; + unsigned int num_coins; + int ret; + + if (GNUNET_OK != + MAJ_parse_json (json, + spec)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + if (! json_is_array (jsona)) + { + GNUNET_break_op (0); + MAJ_parse_free (spec); + return GNUNET_SYSERR; + } + + /* decode all coins */ + num_coins = json_array_size (json); + { + unsigned int i; + struct TALER_CoinSpendPrivateKeyP coin_privs[num_coins]; + struct TALER_DenominationSignature sigs[num_coins]; + struct TALER_DenominationPublicKey pubs[num_coins]; + + for (i=0;i<num_coins;i++) + { + if (GNUNET_OK != + parse_refresh_link_coin (rlh, + json_array_get (json, i), + &trans_pub, + &secret_enc, + &coin_privs[i], + &sigs[i], + &pubs[i])) + { + GNUNET_break_op (0); + break; + } + } + + /* check if we really got all, then invoke callback */ + if (i != num_coins) + { + GNUNET_break_op (0); + ret = GNUNET_SYSERR; + } + else + { + rlh->link_cb (rlh->link_cb_cls, + MHD_HTTP_OK, + num_coins, + coin_privs, + sigs, + pubs, + json); + rlh->link_cb = NULL; + ret = GNUNET_OK; + } + + /* clean up */ + for (i=0;i<num_coins;i++) + if (NULL != sigs[i].rsa_signature) + GNUNET_CRYPTO_rsa_signature_free (sigs[i].rsa_signature); + } + return ret; +} + + +/** * Function called when we're done processing the * HTTP /refresh/link request. * @@ -99,8 +275,13 @@ handle_refresh_link_finished (void *cls, case 0: break; case MHD_HTTP_OK: - GNUNET_break (0); // FIXME: NOT implemented! - // rh->link_cb = NULL; (call with real result, do not call again below) + if (GNUNET_OK != + parse_refresh_link_ok (rlh, + json)) + { + GNUNET_break_op (0); + response_code = 0; + } break; case MHD_HTTP_BAD_REQUEST: /* This should never happen, either us or the mint is buggy @@ -126,7 +307,7 @@ handle_refresh_link_finished (void *cls, if (NULL != rlh->link_cb) rlh->link_cb (rlh->link_cb_cls, response_code, - 0, NULL, NULL, + 0, NULL, NULL, NULL, json); json_decref (json); TALER_MINT_refresh_link_cancel (rlh); @@ -153,10 +334,12 @@ TALER_MINT_refresh_link (struct TALER_MINT_Handle *mint, TALER_MINT_RefreshLinkCallback link_cb, void *link_cb_cls) { - json_t *link_obj; struct TALER_MINT_RefreshLinkHandle *rlh; CURL *eh; struct TALER_MINT_Context *ctx; + struct TALER_CoinSpendPublicKeyP coin_pub; + char *pub_str; + char *arg_str; if (GNUNET_YES != MAH_handle_is_ready (mint)) @@ -164,38 +347,31 @@ TALER_MINT_refresh_link (struct TALER_MINT_Handle *mint, GNUNET_break (0); return NULL; } - /* FIXME: totally bogus request building here: */ - link_obj = json_pack ("{s:o, s:O}", /* f/wire */ - "4", 42, - "6", 62); + GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv, + &coin_pub.eddsa_pub); + pub_str = GNUNET_STRINGS_data_to_string_alloc (&coin_pub, + sizeof (struct TALER_CoinSpendPublicKeyP)); + GNUNET_asprintf (&arg_str, + "/refresh/link?coin_pub=%s", + pub_str); + GNUNET_free (pub_str); rlh = GNUNET_new (struct TALER_MINT_RefreshLinkHandle); rlh->mint = mint; rlh->link_cb = link_cb; rlh->link_cb_cls = link_cb_cls; - - rlh->url = MAH_path_to_url (mint, "/refresh/link"); + rlh->coin_priv = *coin_priv; + rlh->url = MAH_path_to_url (mint, arg_str); + GNUNET_free (arg_str); eh = curl_easy_init (); - GNUNET_assert (NULL != (rlh->json_enc = - json_dumps (link_obj, - JSON_COMPACT))); - json_decref (link_obj); GNUNET_assert (CURLE_OK == curl_easy_setopt (eh, CURLOPT_URL, rlh->url)); GNUNET_assert (CURLE_OK == curl_easy_setopt (eh, - CURLOPT_POSTFIELDS, - rlh->json_enc)); - GNUNET_assert (CURLE_OK == - curl_easy_setopt (eh, - CURLOPT_POSTFIELDSIZE, - strlen (rlh->json_enc))); - GNUNET_assert (CURLE_OK == - curl_easy_setopt (eh, CURLOPT_WRITEFUNCTION, &MAC_download_cb)); GNUNET_assert (CURLE_OK == @@ -228,7 +404,6 @@ TALER_MINT_refresh_link_cancel (struct TALER_MINT_RefreshLinkHandle *rlh) } GNUNET_free_non_null (rlh->db.buf); GNUNET_free (rlh->url); - GNUNET_free (rlh->json_enc); GNUNET_free (rlh); } diff --git a/src/mint-lib/mint_api_withdraw.c b/src/mint-lib/mint_api_withdraw.c index e7a1a61d4..ddabb8116 100644 --- a/src/mint-lib/mint_api_withdraw.c +++ b/src/mint-lib/mint_api_withdraw.c @@ -287,6 +287,7 @@ handle_withdraw_status_finished (void *cls, break; case MHD_HTTP_OK: { + /* TODO: move into separate function... */ json_t *history; unsigned int len; struct TALER_Amount balance; |