aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2022-01-19 12:55:56 +0100
committerChristian Grothoff <christian@grothoff.org>2022-01-19 12:55:56 +0100
commit16bb30ce4b424fa5ada004c53721a6f3f202b538 (patch)
tree1e25885759a5b19201c972b023726dfc40c123ef
parentfbf87011b5129a44e2494758effc7bd6716d6d3b (diff)
downloadanastasis-16bb30ce4b424fa5ada004c53721a6f3f202b538.tar.gz
anastasis-16bb30ce4b424fa5ada004c53721a6f3f202b538.zip
add meta handler and client implementation
-rw-r--r--doc/sphinx/rest.rst35
-rw-r--r--src/backend/anastasis-httpd.c22
-rw-r--r--src/backend/anastasis-httpd_policy-meta.c195
-rw-r--r--src/backend/anastasis-httpd_policy-meta.h41
-rw-r--r--src/backend/anastasis-httpd_policy_upload.c41
-rw-r--r--src/include/anastasis_crypto_lib.h6
-rw-r--r--src/include/anastasis_service.h90
-rw-r--r--src/restclient/Makefile.am2
-rw-r--r--src/restclient/anastasis_api_policy_meta_lookup.c267
9 files changed, 687 insertions, 12 deletions
diff --git a/doc/sphinx/rest.rst b/doc/sphinx/rest.rst
index 605fc9f..7341992 100644
--- a/doc/sphinx/rest.rst
+++ b/doc/sphinx/rest.rst
@@ -141,6 +141,39 @@ In the following, UUID is always defined and used according to `RFC 4122`_.
141 141
142.. _`RFC 4122`: https://tools.ietf.org/html/rfc4122 142.. _`RFC 4122`: https://tools.ietf.org/html/rfc4122
143 143
144.. http:get:: /policy/$ACCOUNT_PUB/meta[?max_version=$NUMBER]
145
146 Get meta data about a customer's encrypted recovery documents.
147 If ``max_version`` is specified, only return results up to the
148 given version number. The response may not contain meta data
149 for all versions if there are way too many. In this case,
150 ``max_version`` must be used to incrementally fetch more versions.
151
152 **Response**:
153
154 :http:statuscode:`200 OK`:
155 The escrow provider responds with a RecoveryMetaSummary_ object.
156 :http:statuscode:`400 Bad request`:
157 The ``$ACCOUNT_PUB`` is not an EdDSA public key.
158 :http:statuscode:`402 Payment Required`:
159 The account's balance is too low for the specified operation.
160 See the Taler payment protocol specification for how to pay.
161 :http:statuscode:`404 Not found`:
162 The requested resource was not found.
163
164 **Details:**
165
166 .. _RecoveryMetaSummary:
167 .. ts:def:: RecoveryMetaSummary
168
169 interface RecoveryMetaSummary {
170 // Version numbers as a string (!) are used as keys,
171 // the value being the base32-encoded encrypted meta data
172 // for that version. A value can be NULL if the document
173 // exists but no meta data was provided.
174 "$VERSION": EncryptedMetaData;
175 }
176
144.. http:get:: /policy/$ACCOUNT_PUB[?version=$NUMBER] 177.. http:get:: /policy/$ACCOUNT_PUB[?version=$NUMBER]
145 178
146 Get the customer's encrypted recovery document. If ``version`` 179 Get the customer's encrypted recovery document. If ``version``
@@ -173,8 +206,6 @@ In the following, UUID is always defined and used according to `RFC 4122`_.
173 :http:statuscode:`402 Payment Required`: 206 :http:statuscode:`402 Payment Required`:
174 The account's balance is too low for the specified operation. 207 The account's balance is too low for the specified operation.
175 See the Taler payment protocol specification for how to pay. 208 See the Taler payment protocol specification for how to pay.
176 :http:statuscode:`403 Forbidden`:
177 The required account signature was invalid.
178 :http:statuscode:`404 Not found`: 209 :http:statuscode:`404 Not found`:
179 The requested resource was not found. 210 The requested resource was not found.
180 211
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,
361 strlen ("/policy/"))) 361 strlen ("/policy/")))
362 { 362 {
363 const char *account = url + strlen ("/policy/"); 363 const char *account = url + strlen ("/policy/");
364 const char *end = strchr (account, '/');
364 struct ANASTASIS_CRYPTO_AccountPublicKeyP account_pub; 365 struct ANASTASIS_CRYPTO_AccountPublicKeyP account_pub;
365 366
366 if (GNUNET_OK != 367 if (GNUNET_OK !=
367 GNUNET_STRINGS_string_to_data ( 368 GNUNET_STRINGS_string_to_data (
368 account, 369 account,
369 strlen (account), 370 (NULL == end)
371 ? strlen (account)
372 : end - account,
370 &account_pub, 373 &account_pub,
371 sizeof (struct ANASTASIS_CRYPTO_AccountPublicKeyP))) 374 sizeof (struct ANASTASIS_CRYPTO_AccountPublicKeyP)))
372 { 375 {
@@ -375,14 +378,23 @@ url_handler (void *cls,
375 TALER_EC_GENERIC_PARAMETER_MALFORMED, 378 TALER_EC_GENERIC_PARAMETER_MALFORMED,
376 "account public key"); 379 "account public key");
377 } 380 }
381 if ( (NULL != end) &&
382 (0 != strcmp (end,
383 "/meta")) )
384 return TMH_MHD_handler_static_response (&h404,
385 connection);
378 if (0 == strcmp (method, 386 if (0 == strcmp (method,
379 MHD_HTTP_METHOD_GET)) 387 MHD_HTTP_METHOD_GET))
380 { 388 {
381 return AH_policy_get (connection, 389 if (NULL == end)
382 &account_pub); 390 return AH_policy_get (connection,
391 &account_pub);
392 return AH_policy_meta_get (connection,
393 &account_pub);
383 } 394 }
384 if (0 == strcmp (method, 395 if ( (0 == strcmp (method,
385 MHD_HTTP_METHOD_POST)) 396 MHD_HTTP_METHOD_POST)) &&
397 (NULL == end) )
386 { 398 {
387 return AH_handler_policy_post (connection, 399 return AH_handler_policy_post (connection,
388 hc, 400 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 @@
1/*
2 This file is part of Anastasis
3 Copyright (C) 2022 Anastasis SARL
4
5 Anastasis is free software; you can redistribute it and/or modify it under the
6 terms of the GNU Affero General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
12
13 You should have received a copy of the GNU Affero General Public License along with
14 Anastasis; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
15*/
16/**
17 * @file anastasis-httpd_policy-meta.c
18 * @brief functions to handle incoming requests on /policy/$PID/meta
19 * @author Christian Grothoff
20 */
21#include "platform.h"
22#include "anastasis-httpd.h"
23#include "anastasis-httpd_policy-meta.h"
24#include "anastasis_service.h"
25#include <gnunet/gnunet_util_lib.h>
26#include <gnunet/gnunet_rest_lib.h>
27#include <taler/taler_json_lib.h>
28#include <taler/taler_merchant_service.h>
29#include <taler/taler_signatures.h>
30
31
32/**
33 * Function called on matching meta data. Note that if the client did
34 * not provide meta data for @a version, the function will be called
35 * with @a recovery_meta_data being NULL.
36 *
37 * @param cls closure with a `json_t *` to build up
38 * @param version the version of the recovery document
39 * @param recovery_meta_data contains meta data about the encrypted recovery document
40 * @param recovery_meta_data_size size of @a recovery_meta_data blob
41 * @return #GNUNET_OK to continue to iterate, #GNUNET_NO to abort iteration
42 */
43static enum GNUNET_GenericReturnValue
44build_meta_result (void *cls,
45 uint32_t version,
46 const void *recovery_meta_data,
47 size_t recovery_meta_data_size)
48{
49 json_t *result = cls;
50 char version_s[14];
51
52 GNUNET_snprintf (version_s,
53 sizeof (version_s),
54 "%u",
55 (unsigned int) version);
56 GNUNET_assert (0 ==
57 json_object_set_new (
58 result,
59 version_s,
60 (NULL == recovery_meta_data)
61 ? json_null ()
62 : GNUNET_JSON_from_data (
63 recovery_meta_data,
64 recovery_meta_data_size)));
65 return GNUNET_OK;
66}
67
68
69/**
70 * Return the meta data on recovery documents of @a account on @a
71 * connection.
72 *
73 * @param connection MHD connection to use
74 * @param account_pub account to query
75 * @return MHD result code
76 */
77static MHD_RESULT
78return_policy_meta (
79 struct MHD_Connection *connection,
80 const struct ANASTASIS_CRYPTO_AccountPublicKeyP *account_pub)
81{
82 enum GNUNET_DB_QueryStatus qs;
83 uint32_t max_version;
84 json_t *result;
85
86 {
87 const char *version_s;
88
89 version_s = MHD_lookup_connection_value (connection,
90 MHD_GET_ARGUMENT_KIND,
91 "max_version");
92 if (NULL != version_s)
93 {
94 char dummy;
95
96 if (1 != sscanf (version_s,
97 "%u%c",
98 &max_version,
99 &dummy))
100 {
101 return TALER_MHD_reply_with_error (connection,
102 MHD_HTTP_BAD_REQUEST,
103 TALER_EC_GENERIC_PARAMETER_MALFORMED,
104 "version");
105 }
106 }
107 }
108 result = json_object ();
109 GNUNET_assert (NULL != result);
110 qs = db->get_recovery_meta_data (db->cls,
111 account_pub,
112 max_version,
113 &build_meta_result,
114 result);
115
116 switch (qs)
117 {
118 case GNUNET_DB_STATUS_HARD_ERROR:
119 GNUNET_break (0);
120 return TALER_MHD_reply_with_error (connection,
121 MHD_HTTP_INTERNAL_SERVER_ERROR,
122 TALER_EC_GENERIC_DB_FETCH_FAILED,
123 "get_recovery_document");
124 case GNUNET_DB_STATUS_SOFT_ERROR:
125 GNUNET_break (0);
126 return TALER_MHD_reply_with_error (connection,
127 MHD_HTTP_INTERNAL_SERVER_ERROR,
128 TALER_EC_GENERIC_DB_SOFT_FAILURE,
129 "get_recovery_document");
130 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
131 return TALER_MHD_reply_with_error (connection,
132 MHD_HTTP_NOT_FOUND,
133 TALER_EC_ANASTASIS_POLICY_NOT_FOUND,
134 NULL);
135 default:
136 /* interesting case below */
137 break;
138 }
139
140 return TALER_MHD_reply_json_steal (connection,
141 result,
142 MHD_HTTP_OK);
143}
144
145
146MHD_RESULT
147AH_policy_meta_get (
148 struct MHD_Connection *connection,
149 const struct ANASTASIS_CRYPTO_AccountPublicKeyP *account_pub)
150{
151 struct GNUNET_HashCode recovery_data_hash;
152 enum ANASTASIS_DB_AccountStatus as;
153 MHD_RESULT ret;
154 uint32_t version;
155 struct GNUNET_TIME_Timestamp expiration;
156
157 as = db->lookup_account (db->cls,
158 account_pub,
159 &expiration,
160 &recovery_data_hash,
161 &version);
162 switch (as)
163 {
164 case ANASTASIS_DB_ACCOUNT_STATUS_PAYMENT_REQUIRED:
165 return TALER_MHD_reply_with_error (connection,
166 MHD_HTTP_NOT_FOUND,
167 TALER_EC_SYNC_ACCOUNT_UNKNOWN,
168 NULL);
169 case ANASTASIS_DB_ACCOUNT_STATUS_HARD_ERROR:
170 GNUNET_break (0);
171 return TALER_MHD_reply_with_error (connection,
172 MHD_HTTP_INTERNAL_SERVER_ERROR,
173 TALER_EC_GENERIC_DB_FETCH_FAILED,
174 "lookup account");
175 case ANASTASIS_DB_ACCOUNT_STATUS_NO_RESULTS:
176 {
177 struct MHD_Response *resp;
178
179 resp = MHD_create_response_from_buffer (0,
180 NULL,
181 MHD_RESPMEM_PERSISTENT);
182 TALER_MHD_add_global_headers (resp);
183 ret = MHD_queue_response (connection,
184 MHD_HTTP_NO_CONTENT,
185 resp);
186 MHD_destroy_response (resp);
187 }
188 return ret;
189 case ANASTASIS_DB_ACCOUNT_STATUS_VALID_HASH_RETURNED:
190 /* We have results, should fetch and return them! */
191 break;
192 }
193 return return_policy_meta (connection,
194 account_pub);
195}
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 @@
1/*
2 This file is part of Anastasis
3 Copyright (C) 2022 Anastasis SARL
4
5 Anastasis is free software; you can redistribute it and/or modify it under the
6 terms of the GNU Affero General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
12
13 You should have received a copy of the GNU Affero General Public License along with
14 Anastasis; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
15*/
16/**
17 * @file anastasis-httpd_policy-meta.h
18 * @brief functions to handle incoming requests on /policy/
19 * @author Dennis Neufeld
20 * @author Dominik Meister
21 * @author Christian Grothoff
22 */
23#ifndef ANASTASIS_HTTPD_POLICY_META_H
24#define ANASTASIS_HTTPD_POLICY_META_H
25#include <microhttpd.h>
26
27
28/**
29 * Handle GET /policy/$ACCOUNT_PUB/meta request.
30 *
31 * @param connection the MHD connection to handle
32 * @param account_pub public key of the account
33 * @return MHD result code
34 */
35MHD_RESULT
36AH_policy_meta_get (
37 struct MHD_Connection *connection,
38 const struct ANASTASIS_CRYPTO_AccountPublicKeyP *account_pub);
39
40
41#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
86 char *upload; 86 char *upload;
87 87
88 /** 88 /**
89 * Meta data uploaded by the client, or NULL for none.
90 */
91 void *meta_data;
92
93 /**
94 * Number of bytes in @e meta_data.
95 */
96 size_t meta_data_size;
97
98 /**
89 * Used while we are awaiting proposal creation. 99 * Used while we are awaiting proposal creation.
90 */ 100 */
91 struct TALER_MERCHANT_PostOrdersHandle *po; 101 struct TALER_MERCHANT_PostOrdersHandle *po;
@@ -220,6 +230,7 @@ cleanup_ctx (struct TM_HandlerContext *hc)
220 if (NULL != puc->resp) 230 if (NULL != puc->resp)
221 MHD_destroy_response (puc->resp); 231 MHD_destroy_response (puc->resp);
222 GNUNET_free (puc->upload); 232 GNUNET_free (puc->upload);
233 GNUNET_free (puc->meta_data);
223 GNUNET_free (puc); 234 GNUNET_free (puc);
224} 235}
225 236
@@ -680,6 +691,32 @@ AH_handler_policy_post (
680 } 691 }
681 } 692 }
682 puc->account = *account_pub; 693 puc->account = *account_pub;
694
695 /* check for meta-data */
696 {
697 const char *metas;
698
699 metas = MHD_lookup_connection_value (connection,
700 MHD_HEADER_KIND,
701 ANASTASIS_HTTP_HEADER_POLICY_META_DATA);
702 if (NULL != metas)
703 {
704 if (GNUNET_OK !=
705 GNUNET_STRINGS_string_to_data_alloc (metas,
706 strlen (metas),
707 &puc->meta_data,
708 &puc->meta_data_size))
709 {
710 GNUNET_break_op (0);
711 return TALER_MHD_reply_with_error (
712 connection,
713 MHD_HTTP_BAD_REQUEST,
714 TALER_EC_GENERIC_HTTP_HEADERS_MALFORMED,
715 ANASTASIS_HTTP_HEADER_POLICY_META_DATA
716 " header must include a base32-encoded value");
717 }
718 }
719 }
683 /* now setup 'puc' */ 720 /* now setup 'puc' */
684 { 721 {
685 const char *lens; 722 const char *lens;
@@ -1121,8 +1158,8 @@ AH_handler_policy_post (
1121 &puc->new_policy_upload_hash, 1158 &puc->new_policy_upload_hash,
1122 puc->upload, 1159 puc->upload,
1123 puc->upload_size, 1160 puc->upload_size,
1124 NULL, /* FIXME: meta-data! */ 1161 puc->meta_data,
1125 0, 1162 puc->meta_data_size,
1126 &puc->payment_identifier, 1163 &puc->payment_identifier,
1127 &version); 1164 &version);
1128 GNUNET_snprintf (version_s, 1165 GNUNET_snprintf (version_s,
diff --git a/src/include/anastasis_crypto_lib.h b/src/include/anastasis_crypto_lib.h
index 780fb34..c28b83a 100644
--- a/src/include/anastasis_crypto_lib.h
+++ b/src/include/anastasis_crypto_lib.h
@@ -41,6 +41,12 @@
41 "Anastasis-Truth-Decryption-Key" 41 "Anastasis-Truth-Decryption-Key"
42 42
43/** 43/**
44 * Client to server: please store this meta data.
45 */
46#define ANASTASIS_HTTP_HEADER_POLICY_META_DATA "Anastasis-Policy-Meta-Data"
47
48
49/**
44 * Client to server: I paid using this payment secret. 50 * Client to server: I paid using this payment secret.
45 */ 51 */
46#define ANASTASIS_HTTP_HEADER_PAYMENT_IDENTIFIER "Anastasis-Payment-Identifier" 52#define ANASTASIS_HTTP_HEADER_PAYMENT_IDENTIFIER "Anastasis-Payment-Identifier"
diff --git a/src/include/anastasis_service.h b/src/include/anastasis_service.h
index 0ef31d6..5a8ca21 100644
--- a/src/include/anastasis_service.h
+++ b/src/include/anastasis_service.h
@@ -156,6 +156,93 @@ ANASTASIS_config_cancel (struct ANASTASIS_ConfigOperation *co);
156 156
157 157
158/** 158/**
159 * Detailed meta data result.
160 */
161struct ANASTASIS_MetaDataEntry
162{
163
164 /**
165 * The encrypted meta data we downloaded.
166 */
167 const void *meta_data;
168
169 /**
170 * Number of bytes in @e meta_data.
171 */
172 size_t meta_data_size;
173
174 /**
175 * Policy version this @e meta_data is for.
176 */
177 uint32_t version;
178};
179
180
181/**
182 * Detailed results for meta data download.
183 */
184struct ANASTASIS_MetaDownloadDetails
185{
186
187 /**
188 * Version-sorted array of meta data we downloaded.
189 */
190 const struct ANASTASIS_MetaDataEntry *metas;
191
192 /**
193 * Number of entries in @e metas.
194 */
195 unsigned int metas_length;
196
197};
198
199
200/**
201 * Callback to process a GET /policy/$POL/meta request
202 *
203 * @param cls closure
204 * @param http_status HTTP status code for this request
205 * @param dd the response details
206 */
207typedef void
208(*ANASTASIS_PolicyMetaLookupCallback) (
209 void *cls,
210 unsigned int http_status,
211 const struct ANASTASIS_MetaDownloadDetails *dd);
212
213
214/**
215 * Does a GET /policy/$POL/meta.
216 *
217 * @param ctx execution context
218 * @param backend_url base URL of the merchant backend
219 * @param anastasis_pub public key of the user's account
220 * @param max_version maximum version number to fetch
221 * @param cb callback which will work the response gotten from the backend
222 * @param cb_cls closure to pass to the callback
223 * @return handle for this operation, NULL upon errors
224 */
225struct ANASTASIS_PolicyMetaLookupOperation *
226ANASTASIS_policy_meta_lookup (
227 struct GNUNET_CURL_Context *ctx,
228 const char *backend_url,
229 const struct ANASTASIS_CRYPTO_AccountPublicKeyP *anastasis_pub,
230 uint32_t max_version,
231 ANASTASIS_PolicyMetaLookupCallback cb,
232 void *cb_cls);
233
234
235/**
236 * Cancel a GET /policy/$POL/meta request.
237 *
238 * @param plo cancel the policy lookup operation
239 */
240void
241ANASTASIS_policy_meta_lookup_cancel (
242 struct ANASTASIS_PolicyMetaLookupOperation *plo);
243
244
245/**
159 * Detailed results from the successful download. 246 * Detailed results from the successful download.
160 */ 247 */
161struct ANASTASIS_DownloadDetails 248struct ANASTASIS_DownloadDetails
@@ -198,8 +285,7 @@ struct ANASTASIS_PolicyLookupOperation;
198 * 285 *
199 * @param cls closure 286 * @param cls closure
200 * @param http_status HTTP status code for this request 287 * @param http_status HTTP status code for this request
201 * @param ec anastasis-specific error code 288 * @param dd the response details
202 * @param obj the response body
203 */ 289 */
204typedef void 290typedef void
205(*ANASTASIS_PolicyLookupCallback) (void *cls, 291(*ANASTASIS_PolicyLookupCallback) (void *cls,
diff --git a/src/restclient/Makefile.am b/src/restclient/Makefile.am
index 075d3a7..19bf64c 100644
--- a/src/restclient/Makefile.am
+++ b/src/restclient/Makefile.am
@@ -19,6 +19,7 @@ libanastasisrest_la_SOURCES = \
19 anastasis_api_policy_store.c \ 19 anastasis_api_policy_store.c \
20 anastasis_api_truth_store.c \ 20 anastasis_api_truth_store.c \
21 anastasis_api_policy_lookup.c \ 21 anastasis_api_policy_lookup.c \
22 anastasis_api_policy_meta_lookup.c \
22 anastasis_api_keyshare_lookup.c \ 23 anastasis_api_keyshare_lookup.c \
23 anastasis_api_curl_defaults.c anastasis_api_curl_defaults.h 24 anastasis_api_curl_defaults.c anastasis_api_curl_defaults.h
24libanastasisrest_la_LIBADD = \ 25libanastasisrest_la_LIBADD = \
@@ -39,4 +40,3 @@ if HAVE_LIBGNURL
39libanastasisrest_la_LIBADD += -lgnurl 40libanastasisrest_la_LIBADD += -lgnurl
40endif 41endif
41endif 42endif
42
diff --git a/src/restclient/anastasis_api_policy_meta_lookup.c b/src/restclient/anastasis_api_policy_meta_lookup.c
new file mode 100644
index 0000000..9be49ca
--- /dev/null
+++ b/src/restclient/anastasis_api_policy_meta_lookup.c
@@ -0,0 +1,267 @@
1/*
2 This file is part of ANASTASIS
3 Copyright (C) 2022 Anastasis SARL
4
5 ANASTASIS is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as
7 published by the Free Software Foundation; either version 2.1,
8 or (at your option) any later version.
9
10 ANASTASIS is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public
16 License along with ANASTASIS; see the file COPYING.LGPL. If not,
17 see <http://www.gnu.org/licenses/>
18*/
19
20/**
21 * @file restclient/anastasis_api_policy_meta_lookup.c
22 * @brief Implementation of the /policy/$POL/meta GET request
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include <curl/curl.h>
27#include <jansson.h>
28#include <microhttpd.h> /* just for HTTP status codes */
29#include "anastasis_service.h"
30#include "anastasis_api_curl_defaults.h"
31#include <taler/taler_signatures.h>
32
33
34/**
35 * @brief A Meta Operation Handle
36 */
37struct ANASTASIS_PolicyMetaLookupOperation
38{
39
40 /**
41 * The url for this request, including parameters.
42 */
43 char *url;
44
45 /**
46 * Handle for the request.
47 */
48 struct GNUNET_CURL_Job *job;
49
50 /**
51 * Function to call with the result.
52 */
53 ANASTASIS_PolicyMetaLookupCallback cb;
54
55 /**
56 * Closure for @a cb.
57 */
58 void *cb_cls;
59
60 /**
61 * Reference to the execution context.
62 */
63 struct GNUNET_CURL_Context *ctx;
64
65 /**
66 * Public key of the account we are downloading from.
67 */
68 struct ANASTASIS_CRYPTO_AccountPublicKeyP account_pub;
69
70 /**
71 * Maximum version to fetch.
72 */
73 uint32_t max_version;
74
75};
76
77
78/**
79 * Process GET /policy/$POL/meta response
80 *
81 * @param cls our `struct ANASTASIS_PolicyMetaLookupOperation *`
82 * @param response_code HTTP status
83 * @param data response body, a `json_t *`, NULL on error
84 */
85static void
86handle_policy_meta_lookup_finished (void *cls,
87 long response_code,
88 const void *response)
89{
90 struct ANASTASIS_PolicyMetaLookupOperation *plo = cls;
91 const json_t *json = response;
92
93 plo->job = NULL;
94 switch (response_code)
95 {
96 case 0:
97 /* Hard error */
98 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
99 "Backend didn't even return from GET /policy\n");
100 break;
101 case MHD_HTTP_OK:
102 {
103 size_t mlen = json_object_size (json);
104
105 /* put a cap, as we will stack-allocate below and the
106 current service LIMITs the result to 1000 anyway;
107 could theoretically be increased in the future, but
108 then we should not put this onto the stack anymore... */
109 if (mlen > 10000)
110 {
111 GNUNET_break (0);
112 response_code = 0;
113 break;
114 }
115 {
116 struct ANASTASIS_MetaDataEntry metas[GNUNET_NZL (mlen)];
117 void *md[GNUNET_NZL (mlen)];
118 struct ANASTASIS_MetaDownloadDetails mdd = {
119 .metas = metas,
120 .metas_length = mlen
121 };
122 size_t off = 0;
123 const char *label;
124 const json_t *val;
125
126 memset (md,
127 0,
128 sizeof (md));
129 json_object_foreach ((json_t *) json,
130 label,
131 val)
132 {
133 unsigned int ver;
134 char dummy;
135 const char *vals;
136
137 if (1 != sscanf (label,
138 "%u%c",
139 &ver,
140 &dummy))
141 {
142 GNUNET_break (0);
143 break;
144 }
145 metas[off].version = (uint32_t) ver;
146 if (json_is_null (val))
147 {
148 metas[off].meta_data = NULL;
149 metas[off].meta_data_size = 0;
150 off++;
151 continue;
152 }
153 vals = json_string_value (val);
154 if ( (NULL == vals) ||
155 (GNUNET_OK !=
156 GNUNET_STRINGS_string_to_data_alloc (vals,
157 strlen (vals),
158 &md[off],
159 &metas[off].meta_data_size)) )
160 {
161 GNUNET_break (0);
162 break;
163 }
164 metas[off].version = (uint32_t) ver;
165 metas[off].meta_data = md[off];
166 off++;
167 }
168 if (off < mlen)
169 {
170 GNUNET_break (0);
171 response_code = 0;
172 for (size_t i = 0; i<off; i++)
173 GNUNET_free (md[i]);
174 break;
175 }
176 plo->cb (plo->cb_cls,
177 response_code,
178 &mdd);
179 for (size_t i = 0; i<off; i++)
180 GNUNET_free (md[i]);
181 plo->cb = NULL;
182 }
183 ANASTASIS_policy_meta_lookup_cancel (plo);
184 return;
185 }
186 case MHD_HTTP_BAD_REQUEST:
187 /* This should never happen, either us or the anastasis server is buggy
188 (or API version conflict); just pass JSON reply to the application */
189 break;
190 case MHD_HTTP_NOT_FOUND:
191 /* Nothing really to verify */
192 break;
193 case MHD_HTTP_INTERNAL_SERVER_ERROR:
194 /* Server had an internal issue; we should retry, but this API
195 leaves this to the application */
196 break;
197 default:
198 /* unexpected response code */
199 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
200 "Unexpected response code %u\n",
201 (unsigned int) response_code);
202 GNUNET_break (0);
203 response_code = 0;
204 break;
205 }
206 plo->cb (plo->cb_cls,
207 response_code,
208 NULL);
209 plo->cb = NULL;
210 ANASTASIS_policy_meta_lookup_cancel (plo);
211}
212
213
214struct ANASTASIS_PolicyMetaLookupOperation *
215ANASTASIS_policy_meta_lookup (
216 struct GNUNET_CURL_Context *ctx,
217 const char *backend_url,
218 const struct ANASTASIS_CRYPTO_AccountPublicKeyP *anastasis_pub,
219 uint32_t max_version,
220 ANASTASIS_PolicyMetaLookupCallback cb,
221 void *cb_cls)
222{
223 struct ANASTASIS_PolicyMetaLookupOperation *plo;
224 CURL *eh;
225 char *path;
226
227 GNUNET_assert (NULL != cb);
228 plo = GNUNET_new (struct ANASTASIS_PolicyMetaLookupOperation);
229 plo->account_pub = *anastasis_pub;
230 {
231 char *acc_pub_str;
232
233 acc_pub_str = GNUNET_STRINGS_data_to_string_alloc (anastasis_pub,
234 sizeof (*anastasis_pub));
235 GNUNET_asprintf (&path,
236 "policy/%s/meta",
237 acc_pub_str);
238 GNUNET_free (acc_pub_str);
239 }
240 plo->url = TALER_url_join (backend_url,
241 path,
242 NULL);
243 GNUNET_free (path);
244 eh = ANASTASIS_curl_easy_get_ (plo->url);
245 GNUNET_assert (NULL != eh);
246 plo->cb = cb;
247 plo->cb_cls = cb_cls;
248 plo->job = GNUNET_CURL_job_add (ctx,
249 eh,
250 &handle_policy_meta_lookup_finished,
251 plo);
252 return plo;
253}
254
255
256void
257ANASTASIS_policy_meta_lookup_cancel (struct
258 ANASTASIS_PolicyMetaLookupOperation *plo)
259{
260 if (NULL != plo->job)
261 {
262 GNUNET_CURL_job_cancel (plo->job);
263 plo->job = NULL;
264 }
265 GNUNET_free (plo->url);
266 GNUNET_free (plo);
267}