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