aboutsummaryrefslogtreecommitdiff
path: root/src/testing/testing_api_cmd_truth_store.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/testing/testing_api_cmd_truth_store.c')
-rw-r--r--src/testing/testing_api_cmd_truth_store.c436
1 files changed, 436 insertions, 0 deletions
diff --git a/src/testing/testing_api_cmd_truth_store.c b/src/testing/testing_api_cmd_truth_store.c
new file mode 100644
index 0000000..0883406
--- /dev/null
+++ b/src/testing/testing_api_cmd_truth_store.c
@@ -0,0 +1,436 @@
1/*
2 This file is part of Anastasis
3 Copyright (C) 2020 Taler Systems SA
4
5 Anastasis is free software; you can redistribute it and/or modify it under the
6 terms of the GNU Lesser 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 General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along with
14 Anastasis; see the file COPYING.GPL. If not, see <http://www.gnu.org/licenses/>
15*/
16/**
17 * @file lib/testing_api_cmd_truth_store.c
18 * @brief command to execute the anastasis backend service.
19 * @author Dennis Neufeld
20 */
21#include "platform.h"
22#include "anastasis_testing_lib.h"
23#include <taler/taler_util.h>
24#include <taler/taler_testing_lib.h>
25#include <taler/taler_merchant_service.h>
26
27/**
28 * State for a "truth store" CMD.
29 */
30struct TruthStoreState
31{
32 /**
33 * UUID of the uploaded truth
34 */
35 struct ANASTASIS_CRYPTO_TruthUUIDP uuid;
36
37 /**
38 * Key used to encrypt the @e truth_data on the server.
39 */
40 struct ANASTASIS_CRYPTO_TruthKeyP key;
41
42 /**
43 * "Encrypted" key share data we store at the server.
44 */
45 struct ANASTASIS_CRYPTO_EncryptedKeyShareP encrypted_keyshare;
46
47 /**
48 * The /truth POST operation handle.
49 */
50 struct ANASTASIS_TruthStoreOperation *tso;
51
52 /**
53 * URL of the anastasis backend.
54 */
55 const char *anastasis_url;
56
57 /**
58 * The interpreter state.
59 */
60 struct TALER_TESTING_Interpreter *is;
61
62 /**
63 * Previous upload, or NULL for none. Used to calculate what THIS
64 * upload is based on.
65 */
66 const char *prev_upload;
67
68 /**
69 * Authorization method / plugin name.
70 */
71 const char *method;
72
73 /**
74 * Mimetype of @e truth_data.
75 */
76 const char *mime_type;
77
78 /**
79 * Number of bytes in @e truth_data
80 */
81 size_t truth_data_size;
82
83 /**
84 * Data used by the authorization process.
85 */
86 void *truth_data;
87
88 /**
89 * Name of the file where the service will write the challenge, or NULL.
90 */
91 char *filename;
92
93 /**
94 * Expected status code.
95 */
96 unsigned int http_status;
97
98 /**
99 * Payment request we got back, or NULL.
100 */
101 char *pay_uri;
102
103 /**
104 * Payment order ID we got back, or all zeros.
105 */
106 struct ANASTASIS_PaymentSecretP payment_secret_response;
107
108 /**
109 * Options for how we are supposed to do the upload.
110 */
111 enum ANASTASIS_TESTING_TruthStoreOption tsopt;
112};
113
114/**
115 * Function called with the results of a #truth_store().
116 *
117 * @param cls closure
118 * @param ec ANASTASIS error code
119 * @param http_status HTTP status of the request
120 * @param ud details about the upload operation
121 */
122static void
123truth_store_cb (void *cls,
124 const struct ANASTASIS_UploadDetails *ud)
125{
126 struct TruthStoreState *tss = cls;
127
128 tss->tso = NULL;
129 if ( (NULL == ud) ||
130 (ud->http_status != tss->http_status) )
131 {
132 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
133 "Unexpected response code %u to command %s in %s:%u\n",
134 (NULL != ud) ? ud->http_status : 0,
135 tss->is->commands[tss->is->ip].label,
136 __FILE__,
137 __LINE__);
138 TALER_TESTING_interpreter_fail (tss->is);
139 return;
140 }
141 switch (ud->us)
142 {
143 case ANASTASIS_US_SUCCESS:
144 break;
145 case ANASTASIS_US_PAYMENT_REQUIRED:
146 tss->pay_uri = GNUNET_strdup (ud->details.payment.payment_request);
147 tss->payment_secret_response = ud->details.payment.ps;
148 break;
149 case ANASTASIS_US_CONFLICTING_TRUTH:
150 GNUNET_break (0);
151 TALER_TESTING_interpreter_fail (tss->is);
152 return;
153 case ANASTASIS_US_HTTP_ERROR:
154 GNUNET_break (0);
155 TALER_TESTING_interpreter_fail (tss->is);
156 return;
157 case ANASTASIS_US_CLIENT_ERROR:
158 GNUNET_break (0);
159 TALER_TESTING_interpreter_fail (tss->is);
160 return;
161 case ANASTASIS_US_SERVER_ERROR:
162 GNUNET_break (0);
163 TALER_TESTING_interpreter_fail (tss->is);
164 return;
165 default:
166 GNUNET_break (0);
167 TALER_TESTING_interpreter_fail (tss->is);
168 return;
169 }
170 TALER_TESTING_interpreter_next (tss->is);
171}
172
173
174/**
175 * Run a "truth store" CMD.
176 *
177 * @param cls closure.
178 * @param cmd command currently being run.
179 * @param is interpreter state.
180 */
181static void
182truth_store_run (void *cls,
183 const struct TALER_TESTING_Command *cmd,
184 struct TALER_TESTING_Interpreter *is)
185{
186 struct TruthStoreState *tss = cls;
187
188 tss->is = is;
189 if (NULL != tss->prev_upload)
190 {
191 const struct TALER_TESTING_Command *ref;
192
193 ref = TALER_TESTING_interpreter_lookup_command (is,
194 tss->prev_upload);
195 if (NULL == ref)
196 {
197 GNUNET_break (0);
198 TALER_TESTING_interpreter_fail (tss->is);
199 return;
200 }
201
202 if (0 != (ANASTASIS_TESTING_TSO_REFERENCE_UUID & tss->tsopt))
203 {
204 const struct ANASTASIS_CRYPTO_TruthUUIDP *uuid;
205 const struct ANASTASIS_CRYPTO_EncryptedKeyShareP *eks;
206
207 if (GNUNET_OK !=
208 ANASTASIS_TESTING_get_trait_truth_uuid (ref,
209 0,
210 &uuid))
211 {
212 GNUNET_break (0);
213 TALER_TESTING_interpreter_fail (tss->is);
214 return;
215 }
216 tss->uuid = *uuid;
217 if (GNUNET_OK !=
218 ANASTASIS_TESTING_get_trait_eks (ref,
219 0,
220 &eks))
221 {
222 GNUNET_break (0);
223 TALER_TESTING_interpreter_fail (tss->is);
224 return;
225 }
226 tss->encrypted_keyshare = *eks;
227 }
228 }
229 else
230 {
231 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
232 &tss->uuid,
233 sizeof (struct ANASTASIS_CRYPTO_TruthUUIDP));
234 GNUNET_CRYPTO_random_block (
235 GNUNET_CRYPTO_QUALITY_WEAK,
236 &tss->encrypted_keyshare,
237 sizeof (struct ANASTASIS_CRYPTO_EncryptedKeyShareP));
238 }
239 GNUNET_CRYPTO_random_block (
240 GNUNET_CRYPTO_QUALITY_WEAK,
241 &tss->key,
242 sizeof (struct ANASTASIS_CRYPTO_TruthKeyP));
243
244 {
245 void *encrypted_truth;
246 size_t size_encrypted_truth;
247 struct ANASTASIS_CRYPTO_NonceP nonce;
248
249 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
250 &nonce,
251 sizeof (nonce));
252 ANASTASIS_CRYPTO_truth_encrypt (&nonce,
253 &tss->key,
254 tss->truth_data,
255 tss->truth_data_size,
256 &encrypted_truth,
257 &size_encrypted_truth);
258 {
259 void *t;
260 size_t t_size;
261
262 ANASTASIS_CRYPTO_truth_decrypt (&tss->key,
263 encrypted_truth,
264 size_encrypted_truth,
265 &t,
266 &t_size);
267 if ( (t_size != tss->truth_data_size) ||
268 (0 != memcmp (tss->truth_data,
269 t,
270 t_size)) )
271 {
272 GNUNET_break (0);
273 TALER_TESTING_interpreter_fail (tss->is);
274 return;
275 }
276 GNUNET_free (t);
277 }
278 tss->tso = ANASTASIS_truth_store (
279 is->ctx,
280 tss->anastasis_url,
281 &tss->uuid,
282 tss->method,
283 &tss->encrypted_keyshare,
284 tss->mime_type,
285 size_encrypted_truth,
286 encrypted_truth,
287 (0 != (ANASTASIS_TESTING_TSO_REQUEST_PAYMENT & tss->tsopt)),
288 GNUNET_TIME_UNIT_ZERO,
289 &truth_store_cb,
290 tss);
291 GNUNET_free (encrypted_truth);
292 }
293 if (NULL == tss->tso)
294 {
295 GNUNET_break (0);
296 TALER_TESTING_interpreter_fail (tss->is);
297 return;
298 }
299}
300
301
302/**
303 * Free the state of a "truth store" CMD, and possibly
304 * cancel it if it did not complete.
305 *
306 * @param cls closure.
307 * @param cmd command being freed.
308 */
309static void
310truth_store_cleanup (void *cls,
311 const struct TALER_TESTING_Command *cmd)
312{
313 struct TruthStoreState *tss = cls;
314
315 if (NULL != tss->tso)
316 {
317 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
318 "Command '%s' did not complete (truth post)\n",
319 cmd->label);
320 ANASTASIS_truth_store_cancel (tss->tso);
321 tss->tso = NULL;
322 }
323 GNUNET_free (tss->truth_data);
324 GNUNET_free (tss->pay_uri);
325 GNUNET_free (tss->filename);
326 GNUNET_free (tss);
327}
328
329
330/**
331 * Offer internal data to other commands.
332 *
333 * @param cls closure
334 * @param[out] ret result (could be anything)
335 * @param[out] trait name of the trait
336 * @param index index number of the object to extract.
337 * @return #GNUNET_OK on success
338 */
339static int
340truth_store_traits (void *cls,
341 const void **ret,
342 const char *trait,
343 unsigned int index)
344{
345 struct TruthStoreState *tss = cls;
346 struct TALER_TESTING_Trait traits[] = {
347 ANASTASIS_TESTING_make_trait_truth_uuid (0,
348 &tss->uuid),
349 ANASTASIS_TESTING_make_trait_truth_key (0,
350 &tss->key),
351 ANASTASIS_TESTING_make_trait_eks (0,
352 &tss->encrypted_keyshare),
353 ANASTASIS_TESTING_make_trait_payment_secret (0,
354 &tss->payment_secret_response),
355 TALER_TESTING_make_trait_url (TALER_TESTING_UT_TALER_URL,
356 tss->pay_uri),
357 TALER_TESTING_make_trait_string (0,
358 tss->filename),
359 TALER_TESTING_trait_end ()
360 };
361
362 return TALER_TESTING_get_trait (traits,
363 ret,
364 trait,
365 index);
366}
367
368
369struct TALER_TESTING_Command
370ANASTASIS_TESTING_cmd_truth_store (const char *label,
371 const char *anastasis_url,
372 const char *prev_upload,
373 const char *method,
374 const char *mime_type,
375 size_t truth_data_size,
376 const void *truth_data,
377 enum ANASTASIS_TESTING_TruthStoreOption tso,
378 unsigned int http_status)
379{
380 struct TruthStoreState *tss;
381
382 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
383 "Storing %u bytes of truth\n",
384 (unsigned int) truth_data_size);
385 tss = GNUNET_new (struct TruthStoreState);
386 tss->http_status = http_status;
387 tss->tsopt = tso;
388 tss->anastasis_url = anastasis_url;
389 tss->prev_upload = prev_upload;
390 tss->method = method;
391 tss->mime_type = mime_type;
392 tss->truth_data = GNUNET_memdup (truth_data,
393 truth_data_size);
394 tss->truth_data_size = truth_data_size;
395 if (0 == strcasecmp (method,
396 "file"))
397 tss->filename = GNUNET_strndup (truth_data,
398 truth_data_size);
399 {
400 struct TALER_TESTING_Command cmd = {
401 .cls = tss,
402 .label = label,
403 .run = &truth_store_run,
404 .cleanup = &truth_store_cleanup,
405 .traits = &truth_store_traits
406 };
407
408 return cmd;
409 }
410}
411
412
413struct TALER_TESTING_Command
414ANASTASIS_TESTING_cmd_truth_question (
415 const char *label,
416 const char *anastasis_url,
417 const char *prev_upload,
418 const char *answer,
419 enum ANASTASIS_TESTING_TruthStoreOption tso,
420 unsigned int http_status)
421{
422 struct GNUNET_HashCode h;
423
424 GNUNET_CRYPTO_hash (answer,
425 strlen (answer),
426 &h);
427 return ANASTASIS_TESTING_cmd_truth_store (label,
428 anastasis_url,
429 prev_upload,
430 "question",
431 "binary/sha512",
432 sizeof (h),
433 &h,
434 tso,
435 http_status);
436}