testing_cmd_secret_share.c (10595B)
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_cmd_secret_share.c 18 * @brief command to execute the anastasis secret share service 19 * @author Christian Grothoff 20 * @author Dennis Neufeld 21 * @author Dominik Meister 22 */ 23 24 #include "platform.h" 25 #include "anastasis_testing_lib.h" 26 #include <taler/taler_util.h> 27 #include <taler/taler_testing_lib.h> 28 #include <taler/taler_merchant_service.h> 29 30 31 /** 32 * State for a "secret share" CMD. 33 */ 34 struct SecretShareState 35 { 36 /** 37 * Claim token we got back, if any. Otherwise all zeros. 38 */ 39 struct TALER_ClaimTokenP token; 40 41 /** 42 * The interpreter state. 43 */ 44 struct TALER_TESTING_Interpreter *is; 45 46 /** 47 * Label of this command. 48 */ 49 const char *label; 50 51 /** 52 * References to commands of previous policy creations. 53 */ 54 const char **cmd_label_array; 55 56 /** 57 * Data to derive user identifier from. 58 */ 59 json_t *id_data; 60 61 /** 62 * The core secret to backup/recover. 63 */ 64 const void *core_secret; 65 66 /** 67 * URL of the anastasis backend. 68 */ 69 const char *anastasis_url; 70 71 /** 72 * URL of a /config command for the @e anastasis_url. 73 */ 74 const char *config_ref; 75 76 /** 77 * The /truth GET operation handle. 78 */ 79 struct ANASTASIS_SecretShare *sso; 80 81 /** 82 * Reference to previous secret share command we expect to lookup. 83 */ 84 const char *prev_secret_share; 85 86 /** 87 * closure for the payment callback 88 */ 89 void *spc_cls; 90 91 /** 92 * closure for the result callback 93 */ 94 void *src_cls; 95 96 /** 97 * Payment order ID we got back, if any. Otherwise NULL. 98 */ 99 char *payment_order_id; 100 101 /** 102 * Size of core_secret. 103 */ 104 size_t core_secret_size; 105 106 /** 107 * Length of array of command labels (cmd_label_array). 108 */ 109 unsigned int cmd_label_array_length; 110 111 /** 112 * Expected status code. 113 */ 114 enum ANASTASIS_ShareStatus want_status; 115 116 /** 117 * Options for how we are supposed to do the upload. 118 */ 119 enum ANASTASIS_TESTING_SecretShareOption ssopt; 120 }; 121 122 123 /** 124 * Function called with the results of a #ANASTASIS_secret_share(). 125 * 126 * @param cls closure 127 * @param sr result from the operation 128 */ 129 static void 130 secret_share_result_cb (void *cls, 131 const struct ANASTASIS_ShareResult *sr) 132 { 133 struct SecretShareState *sss = cls; 134 135 sss->sso = NULL; 136 if (sr->ss != sss->want_status) 137 { 138 TALER_TESTING_interpreter_fail (sss->is); 139 } 140 switch (sr->ss) 141 { 142 case ANASTASIS_SHARE_STATUS_SUCCESS: 143 break; 144 case ANASTASIS_SHARE_STATUS_PAYMENT_REQUIRED: 145 { 146 struct TALER_MERCHANT_PayUriData pd; 147 148 GNUNET_assert (0 < sr->details.payment_required.payment_requests_length); 149 if (GNUNET_OK != 150 TALER_MERCHANT_parse_pay_uri ( 151 sr->details.payment_required.payment_requests[0].payment_request_url, 152 &pd)) 153 { 154 GNUNET_break (0); 155 TALER_TESTING_interpreter_fail (sss->is); 156 return; 157 } 158 sss->payment_order_id = GNUNET_strdup (pd.order_id); 159 TALER_MERCHANT_parse_pay_uri_free (&pd); 160 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 161 "Order ID from Anastasis service is `%s'\n", 162 sss->payment_order_id); 163 } 164 case ANASTASIS_SHARE_STATUS_PROVIDER_FAILED: 165 break; 166 } 167 TALER_TESTING_interpreter_next (sss->is); 168 } 169 170 171 /** 172 * Run a "secret share" CMD. 173 * 174 * @param cls closure. 175 * @param cmd command currently being run. 176 * @param is interpreter state. 177 */ 178 static void 179 secret_share_run (void *cls, 180 const struct TALER_TESTING_Command *cmd, 181 struct TALER_TESTING_Interpreter *is) 182 { 183 struct SecretShareState *sss = cls; 184 const struct ANASTASIS_Policy *policies[sss->cmd_label_array_length]; 185 struct ANASTASIS_ProviderDetails pds; 186 187 GNUNET_assert (sss->cmd_label_array_length > 0); 188 GNUNET_assert (NULL != sss->cmd_label_array); 189 sss->is = is; 190 if (NULL != sss->cmd_label_array) 191 { 192 for (unsigned int i = 0; i < sss->cmd_label_array_length; i++) 193 { 194 const struct TALER_TESTING_Command *ref; 195 const struct ANASTASIS_Policy **policy; 196 197 ref = TALER_TESTING_interpreter_lookup_command (is, 198 sss->cmd_label_array[i]); 199 if (NULL == ref) 200 { 201 GNUNET_break (0); 202 TALER_TESTING_interpreter_fail (sss->is); 203 return; 204 } 205 if (GNUNET_OK != 206 ANASTASIS_TESTING_get_trait_policy (ref, 207 &policy)) 208 { 209 GNUNET_break (0); 210 TALER_TESTING_interpreter_fail (sss->is); 211 return; 212 } 213 GNUNET_assert (NULL != *policy); 214 policies[i] = *policy; 215 } 216 } 217 218 if (NULL != sss->prev_secret_share) 219 { 220 const struct TALER_TESTING_Command *ref; 221 const char *order_id; 222 223 ref = TALER_TESTING_interpreter_lookup_command (is, 224 sss->prev_secret_share); 225 if (NULL == ref) 226 { 227 GNUNET_break (0); 228 TALER_TESTING_interpreter_fail (sss->is); 229 return; 230 } 231 if (GNUNET_OK != 232 TALER_TESTING_get_trait_order_id (ref, 233 &order_id)) 234 { 235 GNUNET_break (0); 236 TALER_TESTING_interpreter_fail (sss->is); 237 return; 238 } 239 sss->payment_order_id = GNUNET_strdup (order_id); 240 if (NULL == sss->payment_order_id) 241 { 242 GNUNET_break (0); 243 TALER_TESTING_interpreter_fail (sss->is); 244 return; 245 } 246 } 247 248 memset (&pds, 249 0, 250 sizeof (pds)); 251 if (NULL != sss->payment_order_id) 252 { 253 if (GNUNET_OK != 254 GNUNET_STRINGS_string_to_data ( 255 sss->payment_order_id, 256 strlen (sss->payment_order_id), 257 &pds.payment_secret, 258 sizeof (struct ANASTASIS_PaymentSecretP))) 259 { 260 GNUNET_break (0); 261 TALER_TESTING_interpreter_fail (sss->is); 262 GNUNET_free (sss->payment_order_id); 263 return; 264 } 265 GNUNET_free (sss->payment_order_id); 266 } 267 pds.provider_url = sss->anastasis_url; 268 { 269 const struct TALER_TESTING_Command *ref; 270 const struct ANASTASIS_CRYPTO_ProviderSaltP *provider_salt; 271 272 ref = TALER_TESTING_interpreter_lookup_command (is, 273 sss->config_ref); 274 if (NULL == ref) 275 { 276 GNUNET_break (0); 277 TALER_TESTING_interpreter_fail (sss->is); 278 return; 279 } 280 if (GNUNET_OK != 281 ANASTASIS_TESTING_get_trait_provider_salt (ref, 282 &provider_salt)) 283 { 284 GNUNET_break (0); 285 TALER_TESTING_interpreter_fail (sss->is); 286 return; 287 } 288 pds.provider_salt = *provider_salt; 289 } 290 291 sss->sso = ANASTASIS_secret_share ( 292 TALER_TESTING_interpreter_get_context (is), 293 sss->id_data, 294 &pds, 295 1, 296 policies, 297 sss->cmd_label_array_length, 298 false, 299 GNUNET_TIME_UNIT_ZERO, 300 &secret_share_result_cb, 301 sss, 302 "test-case", 303 sss->core_secret, 304 sss->core_secret_size); 305 if (NULL == sss->sso) 306 { 307 GNUNET_break (0); 308 TALER_TESTING_interpreter_fail (sss->is); 309 return; 310 } 311 } 312 313 314 /** 315 * Free the state of a "secret share" CMD, and possibly 316 * cancel it if it did not complete. 317 * 318 * @param cls closure. 319 * @param cmd command being freed. 320 */ 321 static void 322 secret_share_cleanup (void *cls, 323 const struct TALER_TESTING_Command *cmd) 324 { 325 struct SecretShareState *sss = cls; 326 327 if (NULL != sss->cmd_label_array) 328 { 329 GNUNET_free (sss->cmd_label_array); 330 } 331 if (NULL != sss->sso) 332 { 333 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 334 "Command '%s' did not complete\n", 335 cmd->label); 336 ANASTASIS_secret_share_cancel (sss->sso); 337 sss->sso = NULL; 338 } 339 json_decref (sss->id_data); 340 GNUNET_free (sss); 341 } 342 343 344 /** 345 * Offer internal data to other commands. 346 * 347 * @param cls closure 348 * @param[out] ret result (could be anything) 349 * @param trait name of the trait 350 * @param index index number of the object to extract. 351 * @return #GNUNET_OK on success 352 */ 353 static int 354 secret_share_traits (void *cls, 355 const void **ret, 356 const char *trait, 357 unsigned int index) 358 { 359 struct SecretShareState *sss = cls; 360 struct TALER_TESTING_Trait traits[] = { 361 TALER_TESTING_make_trait_claim_token (&sss->token), 362 ANASTASIS_TESTING_make_trait_core_secret (sss->core_secret), 363 TALER_TESTING_make_trait_order_id (sss->payment_order_id), 364 TALER_TESTING_trait_end () 365 }; 366 367 return TALER_TESTING_get_trait (traits, 368 ret, 369 trait, 370 index); 371 } 372 373 374 struct TALER_TESTING_Command 375 ANASTASIS_TESTING_cmd_secret_share ( 376 const char *label, 377 const char *anastasis_url, 378 const char *config_ref, 379 const char *prev_secret_share, 380 const json_t *id_data, 381 const void *core_secret, 382 size_t core_secret_size, 383 enum ANASTASIS_ShareStatus want_status, 384 enum ANASTASIS_TESTING_SecretShareOption sso, 385 ...) 386 { 387 struct SecretShareState *sss; 388 389 sss = GNUNET_new (struct SecretShareState); 390 sss->want_status = want_status; 391 sss->ssopt = sso; 392 sss->anastasis_url = anastasis_url; 393 sss->config_ref = config_ref; 394 sss->label = label; 395 sss->id_data = json_incref ((json_t *) id_data); 396 sss->core_secret = core_secret; 397 sss->core_secret_size = core_secret_size; 398 sss->prev_secret_share = prev_secret_share; 399 400 { 401 const char *policy_create_cmd; 402 va_list ap; 403 404 va_start (ap, 405 sso); 406 while (NULL != (policy_create_cmd = va_arg (ap, const char *))) 407 { 408 GNUNET_array_append (sss->cmd_label_array, 409 sss->cmd_label_array_length, 410 policy_create_cmd); 411 } 412 va_end (ap); 413 } 414 { 415 struct TALER_TESTING_Command cmd = { 416 .cls = sss, 417 .label = label, 418 .run = &secret_share_run, 419 .cleanup = &secret_share_cleanup, 420 .traits = &secret_share_traits 421 }; 422 423 return cmd; 424 } 425 } 426 427 428 /* end of testing_cmd_secret_share.c */