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