aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2015-08-08 23:03:26 +0200
committerChristian Grothoff <christian@grothoff.org>2015-08-08 23:03:26 +0200
commit7e47853a5e2bbba529fad06a349d67439d03e5ab (patch)
tree28b13ba065eaee768bfe3ca6a02337c5ec8ea15a
parentcb47e13322e3fefac95a80b4a32d2551f62202d1 (diff)
implement parse_refresh_link_ok
-rw-r--r--src/include/taler_mint_service.h2
-rw-r--r--src/mint-lib/mint_api_refresh_link.c231
-rw-r--r--src/mint-lib/mint_api_withdraw.c1
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;