post keys client logic

This commit is contained in:
Christian Grothoff 2020-11-25 21:55:01 +01:00
parent 1ab3f7a90b
commit 19ca32693a
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
3 changed files with 182 additions and 19 deletions

View File

@ -2134,12 +2134,12 @@ struct TALER_EXCHANGE_ManagementPostKeysData
/** /**
* Array of the master signatures for the exchange's online signing keys. * Array of the master signatures for the exchange's online signing keys.
*/ */
struct TALER_EXCHANGE_SigningKeySignatures *sign_sigs; struct TALER_EXCHANGE_SigningKeySignature *sign_sigs;
/** /**
* Array of the master signatures for the exchange's denomination keys. * Array of the master signatures for the exchange's denomination keys.
*/ */
struct TALER_EXCHANGE_DenominationKeySignatures *denom_sigs; struct TALER_EXCHANGE_DenominationKeySignature *denom_sigs;
/** /**
* Length of the @e sign_keys array (number of valid entries). * Length of the @e sign_keys array (number of valid entries).
@ -2185,7 +2185,7 @@ TALER_EXCHANGE_post_management_keys (
struct GNUNET_CURL_Context *ctx, struct GNUNET_CURL_Context *ctx,
const char *url, const char *url,
const struct TALER_EXCHANGE_ManagementPostKeysData *pkd, const struct TALER_EXCHANGE_ManagementPostKeysData *pkd,
TALER_EXCHANGE_ManagementGetKeysCallback cb, TALER_EXCHANGE_ManagementPostKeysCallback cb,
void *cb_cls); void *cb_cls);

View File

@ -29,10 +29,11 @@ libtalerexchange_la_SOURCES = \
exchange_api_link.c \ exchange_api_link.c \
exchange_api_management_auditor_disable.c \ exchange_api_management_auditor_disable.c \
exchange_api_management_auditor_enable.c \ exchange_api_management_auditor_enable.c \
exchange_api_management_wire_disable.c \ exchange_api_management_post_keys.c \
exchange_api_management_wire_enable.c \
exchange_api_management_revoke_denomination_key.c \ exchange_api_management_revoke_denomination_key.c \
exchange_api_management_revoke_signing_key.c \ exchange_api_management_revoke_signing_key.c \
exchange_api_management_wire_disable.c \
exchange_api_management_wire_enable.c \
exchange_api_melt.c \ exchange_api_melt.c \
exchange_api_recoup.c \ exchange_api_recoup.c \
exchange_api_refresh_common.c exchange_api_refresh_common.h \ exchange_api_refresh_common.c exchange_api_refresh_common.h \

View File

@ -24,6 +24,8 @@
#include <gnunet/gnunet_curl_lib.h> #include <gnunet/gnunet_curl_lib.h>
#include "taler_exchange_service.h" #include "taler_exchange_service.h"
#include "taler_signatures.h" #include "taler_signatures.h"
#include "taler_curl_lib.h"
#include "taler_json_lib.h"
/** /**
@ -37,6 +39,11 @@ struct TALER_EXCHANGE_ManagementPostKeysHandle
*/ */
char *url; char *url;
/**
* Minor context that holds body and headers.
*/
struct TALER_CURL_PostContext post_ctx;
/** /**
* Handle for the request. * Handle for the request.
*/ */
@ -45,7 +52,7 @@ struct TALER_EXCHANGE_ManagementPostKeysHandle
/** /**
* Function to call with the result. * Function to call with the result.
*/ */
TALER_EXCHANGE_ManagementGetKeysCallback cb; TALER_EXCHANGE_ManagementPostKeysCallback cb;
/** /**
* Closure for @a cb. * Closure for @a cb.
@ -60,28 +67,182 @@ struct TALER_EXCHANGE_ManagementPostKeysHandle
/** /**
* Provide master-key signatures to the exchange. * Function called when we're done processing the
* HTTP POST /management/keys request.
* *
* @param ctx the context * @param cls the `struct TALER_EXCHANGE_ManagementPostKeysHandle *`
* @param url HTTP base URL for the exchange * @param response_code HTTP response code, 0 on error
* @param cb function to call with the exchange's result * @param response response body, NULL if not in JSON
* @param cb_cls closure for @a cb
* @return the request handle; NULL upon error
*/ */
static void
handle_post_keys_finished (void *cls,
long response_code,
const void *response)
{
struct TALER_EXCHANGE_ManagementPostKeysHandle *ph = cls;
const json_t *json = response;
struct TALER_EXCHANGE_HttpResponse hr = {
.http_status = (unsigned int) response_code,
.reply = json
};
ph->job = NULL;
switch (response_code)
{
case MHD_HTTP_NO_CONTENT:
break;
case MHD_HTTP_FORBIDDEN:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
break;
default:
/* unexpected response code */
GNUNET_break_op (0);
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d\n",
(unsigned int) response_code,
(int) hr.ec);
break;
}
if (NULL != ph->cb)
{
ph->cb (ph->cb_cls,
&hr);
ph->cb = NULL;
}
TALER_EXCHANGE_post_management_keys_cancel (ph);
}
struct TALER_EXCHANGE_ManagementPostKeysHandle * struct TALER_EXCHANGE_ManagementPostKeysHandle *
TALER_EXCHANGE_post_management_keys ( TALER_EXCHANGE_post_management_keys (
struct GNUNET_CURL_Context *ctx, struct GNUNET_CURL_Context *ctx,
const char *url, const char *url,
const struct TALER_EXCHANGE_ManagementPostKeysData *pkd, const struct TALER_EXCHANGE_ManagementPostKeysData *pkd,
TALER_EXCHANGE_ManagementGetKeysCallback cb, TALER_EXCHANGE_ManagementPostKeysCallback cb,
void *cb_cls); void *cb_cls)
{
struct TALER_EXCHANGE_ManagementPostKeysHandle *ph;
CURL *eh;
json_t *body;
json_t *denom_sigs;
json_t *signkey_sigs;
ph = GNUNET_new (struct TALER_EXCHANGE_ManagementPostKeysHandle);
ph->cb = cb;
ph->cb_cls = cb_cls;
ph->ctx = ctx;
ph->url = TALER_url_join (url,
"management/keys",
NULL);
if (NULL == ph->url)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Could not construct request URL.\n");
GNUNET_free (ph);
return NULL;
}
denom_sigs = json_array ();
if (NULL == denom_sigs)
{
GNUNET_free (ph->url);
GNUNET_free (ph);
return NULL;
}
for (unsigned int i = 0; i<pkd->num_denom_sigs; i++)
{
if (0 !=
json_array_append_new (
denom_sigs,
json_pack ("{s:o, s:o}",
"h_denom_pub",
GNUNET_JSON_from_data_auto (
&pkd->denom_sigs[i].h_denom_pub),
"master_sig",
GNUNET_JSON_from_data_auto (
&pkd->denom_sigs[i].master_sig))))
{
json_decref (denom_sigs);
GNUNET_free (ph->url);
GNUNET_free (ph);
return NULL;
}
}
signkey_sigs = json_array ();
if (NULL == signkey_sigs)
{
json_decref (denom_sigs);
GNUNET_free (ph->url);
GNUNET_free (ph);
return NULL;
}
for (unsigned int i = 0; i<pkd->num_sign_sigs; i++)
{
if (0 !=
json_array_append_new (
signkey_sigs,
json_pack ("{s:o, s:o}",
"exchange_pub",
GNUNET_JSON_from_data_auto (
&pkd->sign_sigs[i].exchange_pub),
"master_sig",
GNUNET_JSON_from_data_auto (
&pkd->sign_sigs[i].master_sig))))
{
json_decref (signkey_sigs);
json_decref (denom_sigs);
GNUNET_free (ph->url);
GNUNET_free (ph);
return NULL;
}
}
body = json_pack ("{s:o, s:o}",
"denom_sigs",
denom_sigs,
"signkey_sigs",
signkey_sigs);
if (NULL == body)
{
GNUNET_break (0);
GNUNET_free (ph->url);
GNUNET_free (ph);
return NULL;
}
eh = curl_easy_init ();
if (GNUNET_OK !=
TALER_curl_easy_post (&ph->post_ctx,
eh,
body))
{
GNUNET_break (0);
json_decref (body);
GNUNET_free (ph->url);
GNUNET_free (eh);
return NULL;
}
json_decref (body);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Requesting URL '%s'\n",
ph->url);
GNUNET_assert (CURLE_OK == curl_easy_setopt (eh,
CURLOPT_URL,
ph->url));
ph->job = GNUNET_CURL_job_add2 (ctx,
eh,
ph->post_ctx.headers,
&handle_post_keys_finished,
ph);
if (NULL == ph->job)
{
TALER_EXCHANGE_post_management_keys_cancel (ph);
return NULL;
}
return ph;
}
/**
* Cancel #TALER_EXCHANGE_post_management_keys() operation.
*
* @param gh handle of the operation to cancel
*/
void void
TALER_EXCHANGE_post_management_keys_cancel ( TALER_EXCHANGE_post_management_keys_cancel (
struct TALER_EXCHANGE_ManagementPostKeysHandle *ph) struct TALER_EXCHANGE_ManagementPostKeysHandle *ph)
@ -91,6 +252,7 @@ TALER_EXCHANGE_post_management_keys_cancel (
GNUNET_CURL_job_cancel (ph->job); GNUNET_CURL_job_cancel (ph->job);
ph->job = NULL; ph->job = NULL;
} }
TALER_curl_easy_post_finished (&ph->post_ctx);
GNUNET_free (ph->url); GNUNET_free (ph->url);
GNUNET_free (ph); GNUNET_free (ph);
} }