diff options
author | Christian Grothoff <christian@grothoff.org> | 2022-01-19 12:55:56 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2022-01-19 12:55:56 +0100 |
commit | 16bb30ce4b424fa5ada004c53721a6f3f202b538 (patch) | |
tree | 1e25885759a5b19201c972b023726dfc40c123ef /src/backend | |
parent | fbf87011b5129a44e2494758effc7bd6716d6d3b (diff) | |
download | anastasis-16bb30ce4b424fa5ada004c53721a6f3f202b538.tar.gz anastasis-16bb30ce4b424fa5ada004c53721a6f3f202b538.tar.bz2 anastasis-16bb30ce4b424fa5ada004c53721a6f3f202b538.zip |
add meta handler and client implementation
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/anastasis-httpd.c | 22 | ||||
-rw-r--r-- | src/backend/anastasis-httpd_policy-meta.c | 195 | ||||
-rw-r--r-- | src/backend/anastasis-httpd_policy-meta.h | 41 | ||||
-rw-r--r-- | src/backend/anastasis-httpd_policy_upload.c | 41 |
4 files changed, 292 insertions, 7 deletions
diff --git a/src/backend/anastasis-httpd.c b/src/backend/anastasis-httpd.c index e2b363c..4ef6087 100644 --- a/src/backend/anastasis-httpd.c +++ b/src/backend/anastasis-httpd.c @@ -361,12 +361,15 @@ url_handler (void *cls, strlen ("/policy/"))) { const char *account = url + strlen ("/policy/"); + const char *end = strchr (account, '/'); struct ANASTASIS_CRYPTO_AccountPublicKeyP account_pub; if (GNUNET_OK != GNUNET_STRINGS_string_to_data ( account, - strlen (account), + (NULL == end) + ? strlen (account) + : end - account, &account_pub, sizeof (struct ANASTASIS_CRYPTO_AccountPublicKeyP))) { @@ -375,14 +378,23 @@ url_handler (void *cls, TALER_EC_GENERIC_PARAMETER_MALFORMED, "account public key"); } + if ( (NULL != end) && + (0 != strcmp (end, + "/meta")) ) + return TMH_MHD_handler_static_response (&h404, + connection); if (0 == strcmp (method, MHD_HTTP_METHOD_GET)) { - return AH_policy_get (connection, - &account_pub); + if (NULL == end) + return AH_policy_get (connection, + &account_pub); + return AH_policy_meta_get (connection, + &account_pub); } - if (0 == strcmp (method, - MHD_HTTP_METHOD_POST)) + if ( (0 == strcmp (method, + MHD_HTTP_METHOD_POST)) && + (NULL == end) ) { return AH_handler_policy_post (connection, hc, diff --git a/src/backend/anastasis-httpd_policy-meta.c b/src/backend/anastasis-httpd_policy-meta.c new file mode 100644 index 0000000..a786c68 --- /dev/null +++ b/src/backend/anastasis-httpd_policy-meta.c @@ -0,0 +1,195 @@ +/* + This file is part of Anastasis + Copyright (C) 2022 Anastasis SARL + + Anastasis is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with + Anastasis; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +*/ +/** + * @file anastasis-httpd_policy-meta.c + * @brief functions to handle incoming requests on /policy/$PID/meta + * @author Christian Grothoff + */ +#include "platform.h" +#include "anastasis-httpd.h" +#include "anastasis-httpd_policy-meta.h" +#include "anastasis_service.h" +#include <gnunet/gnunet_util_lib.h> +#include <gnunet/gnunet_rest_lib.h> +#include <taler/taler_json_lib.h> +#include <taler/taler_merchant_service.h> +#include <taler/taler_signatures.h> + + +/** + * Function called on matching meta data. Note that if the client did + * not provide meta data for @a version, the function will be called + * with @a recovery_meta_data being NULL. + * + * @param cls closure with a `json_t *` to build up + * @param version the version of the recovery document + * @param recovery_meta_data contains meta data about the encrypted recovery document + * @param recovery_meta_data_size size of @a recovery_meta_data blob + * @return #GNUNET_OK to continue to iterate, #GNUNET_NO to abort iteration + */ +static enum GNUNET_GenericReturnValue +build_meta_result (void *cls, + uint32_t version, + const void *recovery_meta_data, + size_t recovery_meta_data_size) +{ + json_t *result = cls; + char version_s[14]; + + GNUNET_snprintf (version_s, + sizeof (version_s), + "%u", + (unsigned int) version); + GNUNET_assert (0 == + json_object_set_new ( + result, + version_s, + (NULL == recovery_meta_data) + ? json_null () + : GNUNET_JSON_from_data ( + recovery_meta_data, + recovery_meta_data_size))); + return GNUNET_OK; +} + + +/** + * Return the meta data on recovery documents of @a account on @a + * connection. + * + * @param connection MHD connection to use + * @param account_pub account to query + * @return MHD result code + */ +static MHD_RESULT +return_policy_meta ( + struct MHD_Connection *connection, + const struct ANASTASIS_CRYPTO_AccountPublicKeyP *account_pub) +{ + enum GNUNET_DB_QueryStatus qs; + uint32_t max_version; + json_t *result; + + { + const char *version_s; + + version_s = MHD_lookup_connection_value (connection, + MHD_GET_ARGUMENT_KIND, + "max_version"); + if (NULL != version_s) + { + char dummy; + + if (1 != sscanf (version_s, + "%u%c", + &max_version, + &dummy)) + { + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + "version"); + } + } + } + result = json_object (); + GNUNET_assert (NULL != result); + qs = db->get_recovery_meta_data (db->cls, + account_pub, + max_version, + &build_meta_result, + result); + + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_FETCH_FAILED, + "get_recovery_document"); + case GNUNET_DB_STATUS_SOFT_ERROR: + GNUNET_break (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_SOFT_FAILURE, + "get_recovery_document"); + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_ANASTASIS_POLICY_NOT_FOUND, + NULL); + default: + /* interesting case below */ + break; + } + + return TALER_MHD_reply_json_steal (connection, + result, + MHD_HTTP_OK); +} + + +MHD_RESULT +AH_policy_meta_get ( + struct MHD_Connection *connection, + const struct ANASTASIS_CRYPTO_AccountPublicKeyP *account_pub) +{ + struct GNUNET_HashCode recovery_data_hash; + enum ANASTASIS_DB_AccountStatus as; + MHD_RESULT ret; + uint32_t version; + struct GNUNET_TIME_Timestamp expiration; + + as = db->lookup_account (db->cls, + account_pub, + &expiration, + &recovery_data_hash, + &version); + switch (as) + { + case ANASTASIS_DB_ACCOUNT_STATUS_PAYMENT_REQUIRED: + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_SYNC_ACCOUNT_UNKNOWN, + NULL); + case ANASTASIS_DB_ACCOUNT_STATUS_HARD_ERROR: + GNUNET_break (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_FETCH_FAILED, + "lookup account"); + case ANASTASIS_DB_ACCOUNT_STATUS_NO_RESULTS: + { + struct MHD_Response *resp; + + resp = MHD_create_response_from_buffer (0, + NULL, + MHD_RESPMEM_PERSISTENT); + TALER_MHD_add_global_headers (resp); + ret = MHD_queue_response (connection, + MHD_HTTP_NO_CONTENT, + resp); + MHD_destroy_response (resp); + } + return ret; + case ANASTASIS_DB_ACCOUNT_STATUS_VALID_HASH_RETURNED: + /* We have results, should fetch and return them! */ + break; + } + return return_policy_meta (connection, + account_pub); +} diff --git a/src/backend/anastasis-httpd_policy-meta.h b/src/backend/anastasis-httpd_policy-meta.h new file mode 100644 index 0000000..8c48fc6 --- /dev/null +++ b/src/backend/anastasis-httpd_policy-meta.h @@ -0,0 +1,41 @@ +/* + This file is part of Anastasis + Copyright (C) 2022 Anastasis SARL + + Anastasis is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with + Anastasis; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +*/ +/** + * @file anastasis-httpd_policy-meta.h + * @brief functions to handle incoming requests on /policy/ + * @author Dennis Neufeld + * @author Dominik Meister + * @author Christian Grothoff + */ +#ifndef ANASTASIS_HTTPD_POLICY_META_H +#define ANASTASIS_HTTPD_POLICY_META_H +#include <microhttpd.h> + + +/** + * Handle GET /policy/$ACCOUNT_PUB/meta request. + * + * @param connection the MHD connection to handle + * @param account_pub public key of the account + * @return MHD result code + */ +MHD_RESULT +AH_policy_meta_get ( + struct MHD_Connection *connection, + const struct ANASTASIS_CRYPTO_AccountPublicKeyP *account_pub); + + +#endif diff --git a/src/backend/anastasis-httpd_policy_upload.c b/src/backend/anastasis-httpd_policy_upload.c index b63a82e..2cc0389 100644 --- a/src/backend/anastasis-httpd_policy_upload.c +++ b/src/backend/anastasis-httpd_policy_upload.c @@ -86,6 +86,16 @@ struct PolicyUploadContext char *upload; /** + * Meta data uploaded by the client, or NULL for none. + */ + void *meta_data; + + /** + * Number of bytes in @e meta_data. + */ + size_t meta_data_size; + + /** * Used while we are awaiting proposal creation. */ struct TALER_MERCHANT_PostOrdersHandle *po; @@ -220,6 +230,7 @@ cleanup_ctx (struct TM_HandlerContext *hc) if (NULL != puc->resp) MHD_destroy_response (puc->resp); GNUNET_free (puc->upload); + GNUNET_free (puc->meta_data); GNUNET_free (puc); } @@ -680,6 +691,32 @@ AH_handler_policy_post ( } } puc->account = *account_pub; + + /* check for meta-data */ + { + const char *metas; + + metas = MHD_lookup_connection_value (connection, + MHD_HEADER_KIND, + ANASTASIS_HTTP_HEADER_POLICY_META_DATA); + if (NULL != metas) + { + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data_alloc (metas, + strlen (metas), + &puc->meta_data, + &puc->meta_data_size)) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error ( + connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_HTTP_HEADERS_MALFORMED, + ANASTASIS_HTTP_HEADER_POLICY_META_DATA + " header must include a base32-encoded value"); + } + } + } /* now setup 'puc' */ { const char *lens; @@ -1121,8 +1158,8 @@ AH_handler_policy_post ( &puc->new_policy_upload_hash, puc->upload, puc->upload_size, - NULL, /* FIXME: meta-data! */ - 0, + puc->meta_data, + puc->meta_data_size, &puc->payment_identifier, &version); GNUNET_snprintf (version_s, |