testing_api_cmd_truth_store.c (11686B)
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 #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 */ 30 struct 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 an #ANASTASIS_truth_store() 116 * operation. 117 * 118 * @param cls closure 119 * @param ud details about the upload operation 120 */ 121 static void 122 truth_store_cb (void *cls, 123 const struct ANASTASIS_UploadDetails *ud) 124 { 125 struct TruthStoreState *tss = cls; 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 (GNUNET_CRYPTO_QUALITY_NONCE, 224 &tss->uuid, 225 sizeof (struct ANASTASIS_CRYPTO_TruthUUIDP)); 226 GNUNET_CRYPTO_random_block ( 227 GNUNET_CRYPTO_QUALITY_WEAK, 228 &tss->encrypted_keyshare, 229 sizeof (struct ANASTASIS_CRYPTO_EncryptedKeyShareP)); 230 } 231 GNUNET_CRYPTO_random_block ( 232 GNUNET_CRYPTO_QUALITY_WEAK, 233 &tss->key, 234 sizeof (struct ANASTASIS_CRYPTO_TruthKeyP)); 235 236 { 237 void *encrypted_truth; 238 size_t size_encrypted_truth; 239 struct ANASTASIS_CRYPTO_NonceP nonce; 240 241 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, 242 &nonce, 243 sizeof (nonce)); 244 ANASTASIS_CRYPTO_truth_encrypt (&nonce, 245 &tss->key, 246 tss->truth_data, 247 tss->truth_data_size, 248 &encrypted_truth, 249 &size_encrypted_truth); 250 { 251 void *t; 252 size_t t_size; 253 254 ANASTASIS_CRYPTO_truth_decrypt (&tss->key, 255 encrypted_truth, 256 size_encrypted_truth, 257 &t, 258 &t_size); 259 if ( (t_size != tss->truth_data_size) || 260 (0 != memcmp (tss->truth_data, 261 t, 262 t_size)) ) 263 { 264 GNUNET_break (0); 265 TALER_TESTING_interpreter_fail (tss->is); 266 return; 267 } 268 GNUNET_free (t); 269 } 270 tss->tso = ANASTASIS_truth_store ( 271 TALER_TESTING_interpreter_get_context (is), 272 tss->anastasis_url, 273 &tss->uuid, 274 tss->method, 275 &tss->encrypted_keyshare, 276 tss->mime_type, 277 size_encrypted_truth, 278 encrypted_truth, 279 (0 != (ANASTASIS_TESTING_TSO_REQUEST_PAYMENT & tss->tsopt)), 280 GNUNET_TIME_UNIT_ZERO, 281 &truth_store_cb, 282 tss); 283 GNUNET_free (encrypted_truth); 284 } 285 if (NULL == tss->tso) 286 { 287 GNUNET_break (0); 288 TALER_TESTING_interpreter_fail (tss->is); 289 return; 290 } 291 } 292 293 294 /** 295 * Free the state of a "truth store" CMD, and possibly 296 * cancel it if it did not complete. 297 * 298 * @param cls closure. 299 * @param cmd command being freed. 300 */ 301 static void 302 truth_store_cleanup (void *cls, 303 const struct TALER_TESTING_Command *cmd) 304 { 305 struct TruthStoreState *tss = cls; 306 307 if (NULL != tss->tso) 308 { 309 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 310 "Command '%s' did not complete (truth post)\n", 311 cmd->label); 312 ANASTASIS_truth_store_cancel (tss->tso); 313 tss->tso = NULL; 314 } 315 GNUNET_free (tss->truth_data); 316 GNUNET_free (tss->pay_uri); 317 GNUNET_free (tss->filename); 318 GNUNET_free (tss); 319 } 320 321 322 /** 323 * Offer internal data to other commands. 324 * 325 * @param cls closure 326 * @param[out] ret result (could be anything) 327 * @param[out] trait name of the trait 328 * @param index index number of the object to extract. 329 * @return #GNUNET_OK on success 330 */ 331 static enum GNUNET_GenericReturnValue 332 truth_store_traits (void *cls, 333 const void **ret, 334 const char *trait, 335 unsigned int index) 336 { 337 struct TruthStoreState *tss = cls; 338 struct TALER_TESTING_Trait traits[] = { 339 ANASTASIS_TESTING_make_trait_truth_uuid (&tss->uuid), 340 ANASTASIS_TESTING_make_trait_truth_key (&tss->key), 341 ANASTASIS_TESTING_make_trait_eks (&tss->encrypted_keyshare), 342 ANASTASIS_TESTING_make_trait_payment_secret (&tss->payment_secret_response), 343 TALER_TESTING_make_trait_taler_uri (tss->pay_uri), 344 ANASTASIS_TESTING_make_trait_filename (tss->filename), 345 TALER_TESTING_trait_end () 346 }; 347 348 return TALER_TESTING_get_trait (traits, 349 ret, 350 trait, 351 index); 352 } 353 354 355 struct TALER_TESTING_Command 356 ANASTASIS_TESTING_cmd_truth_store (const char *label, 357 const char *anastasis_url, 358 const char *prev_upload, 359 const char *method, 360 const char *mime_type, 361 size_t truth_data_size, 362 const void *truth_data, 363 enum ANASTASIS_TESTING_TruthStoreOption tso, 364 unsigned int http_status) 365 { 366 struct TruthStoreState *tss; 367 368 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 369 "Storing %u bytes of truth\n", 370 (unsigned int) truth_data_size); 371 tss = GNUNET_new (struct TruthStoreState); 372 tss->http_status = http_status; 373 tss->tsopt = tso; 374 tss->anastasis_url = anastasis_url; 375 tss->prev_upload = prev_upload; 376 tss->method = method; 377 tss->mime_type = mime_type; 378 tss->truth_data = GNUNET_memdup (truth_data, 379 truth_data_size); 380 tss->truth_data_size = truth_data_size; 381 if (0 == strcasecmp (method, 382 "file")) 383 tss->filename = GNUNET_strndup (truth_data, 384 truth_data_size); 385 { 386 struct TALER_TESTING_Command cmd = { 387 .cls = tss, 388 .label = label, 389 .run = &truth_store_run, 390 .cleanup = &truth_store_cleanup, 391 .traits = &truth_store_traits 392 }; 393 394 return cmd; 395 } 396 } 397 398 399 struct TALER_TESTING_Command 400 ANASTASIS_TESTING_cmd_truth_question ( 401 const char *label, 402 const char *anastasis_url, 403 const char *prev_upload, 404 const char *answer, 405 enum ANASTASIS_TESTING_TruthStoreOption tso, 406 unsigned int http_status) 407 { 408 struct GNUNET_HashCode h; 409 410 GNUNET_CRYPTO_hash (answer, 411 strlen (answer), 412 &h); 413 return ANASTASIS_TESTING_cmd_truth_store (label, 414 anastasis_url, 415 prev_upload, 416 "question", 417 "binary/sha512", 418 sizeof (h), 419 &h, 420 tso, 421 http_status); 422 }