testing_api_cmd_bank_admin_add_kycauth.c (10574B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2024 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it 6 under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3, or (at your 8 option) any later version. 9 10 TALER is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 General Public License for more details. 14 15 You should have received a copy of the GNU General Public 16 License along with TALER; see the file COPYING. If not, see 17 <http://www.gnu.org/licenses/> 18 */ 19 /** 20 * @file testing/testing_api_cmd_bank_admin_add_kycauth.c 21 * @brief implementation of a bank /admin/add-kycauth command 22 * @author Christian Grothoff 23 * @author Marcello Stanisci 24 */ 25 #include "taler/taler_json_lib.h" 26 #include <gnunet/gnunet_curl_lib.h> 27 #include "taler/taler_bank_service.h" 28 #include "taler/taler_signatures.h" 29 #include "taler/taler_testing_lib.h" 30 31 32 /** 33 * State for a KYCAUTH wire transfer CMD. 34 */ 35 struct AdminAddKycauthState 36 { 37 38 /** 39 * Label of any command that can trait-offer an account priv. 40 */ 41 const char *account_ref; 42 43 /** 44 * Wire transfer amount. 45 */ 46 struct TALER_Amount amount; 47 48 /** 49 * Base URL of the credited account. 50 */ 51 const char *exchange_credit_url; 52 53 /** 54 * Money sender payto URL. 55 */ 56 struct TALER_FullPayto payto_debit_account; 57 58 /** 59 * Username to use for authentication. 60 */ 61 struct TALER_BANK_AuthenticationData auth; 62 63 /** 64 * Set (by the interpreter) to the account's private key 65 * we used to make a wire transfer subject line with. 66 */ 67 union TALER_AccountPrivateKeyP account_priv; 68 69 /** 70 * Account public key matching @e account_priv. 71 */ 72 union TALER_AccountPublicKeyP account_pub; 73 74 /** 75 * Handle to the pending request at the bank. 76 */ 77 struct TALER_BANK_AdminAddKycauthHandle *aih; 78 79 /** 80 * Interpreter state. 81 */ 82 struct TALER_TESTING_Interpreter *is; 83 84 /** 85 * Set to the wire transfer's unique ID. 86 */ 87 uint64_t serial_id; 88 89 /** 90 * Timestamp of the transaction (as returned from the bank). 91 */ 92 struct GNUNET_TIME_Timestamp timestamp; 93 94 /** 95 * Expected HTTP status code. 96 */ 97 unsigned int expected_http_status; 98 99 /** 100 * Do we have @e account_priv? 101 */ 102 bool have_priv; 103 }; 104 105 106 /** 107 * This callback will process the bank response to the wire 108 * transfer. It just checks whether the HTTP response code is 109 * acceptable. 110 * 111 * @param cls closure with the interpreter state 112 * @param air response details 113 */ 114 static void 115 confirmation_cb (void *cls, 116 const struct TALER_BANK_AdminAddKycauthResponse *air) 117 { 118 struct AdminAddKycauthState *fts = cls; 119 struct TALER_TESTING_Interpreter *is = fts->is; 120 121 fts->aih = NULL; 122 if (air->http_status != fts->expected_http_status) 123 { 124 TALER_TESTING_unexpected_status (is, 125 air->http_status, 126 fts->expected_http_status); 127 return; 128 } 129 switch (air->http_status) 130 { 131 case MHD_HTTP_OK: 132 fts->serial_id 133 = air->details.ok.serial_id; 134 fts->timestamp 135 = air->details.ok.timestamp; 136 TALER_TESTING_interpreter_next (is); 137 return; 138 case MHD_HTTP_UNAUTHORIZED: 139 switch (fts->auth.method) 140 { 141 case TALER_BANK_AUTH_NONE: 142 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 143 "Authentication required, but none configure.\n"); 144 break; 145 case TALER_BANK_AUTH_BASIC: 146 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 147 "Basic authentication (%s) failed.\n", 148 fts->auth.details.basic.username); 149 break; 150 case TALER_BANK_AUTH_BEARER: 151 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 152 "Bearer authentication (%s) failed.\n", 153 fts->auth.details.bearer.token); 154 break; 155 } 156 break; 157 case MHD_HTTP_CONFLICT: 158 TALER_TESTING_interpreter_next (is); 159 return; 160 default: 161 GNUNET_break (0); 162 break; 163 } 164 GNUNET_break (0); 165 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 166 "Bank returned HTTP status %u/%d\n", 167 air->http_status, 168 (int) air->ec); 169 TALER_TESTING_interpreter_fail (is); 170 } 171 172 173 /** 174 * Run the KYC AUTH transfer CMD. 175 * 176 * @param cls closure. 177 * @param cmd CMD being run. 178 * @param is interpreter state. 179 */ 180 static void 181 admin_add_kycauth_run (void *cls, 182 const struct TALER_TESTING_Command *cmd, 183 struct TALER_TESTING_Interpreter *is) 184 { 185 struct AdminAddKycauthState *fts = cls; 186 187 (void) cmd; 188 fts->is = is; 189 /* Use account public key as subject */ 190 if (NULL != fts->account_ref) 191 { 192 const struct TALER_TESTING_Command *ref; 193 const union TALER_AccountPrivateKeyP *account_priv; 194 195 ref = TALER_TESTING_interpreter_lookup_command ( 196 is, 197 fts->account_ref); 198 if (NULL == ref) 199 { 200 GNUNET_break (0); 201 TALER_TESTING_interpreter_fail (is); 202 return; 203 } 204 if (GNUNET_OK != 205 TALER_TESTING_get_trait_account_priv (ref, 206 &account_priv)) 207 { 208 const union TALER_AccountPublicKeyP *account_pub; 209 210 if (GNUNET_OK != 211 TALER_TESTING_get_trait_account_pub (ref, 212 &account_pub)) 213 { 214 GNUNET_break (0); 215 TALER_TESTING_interpreter_fail (is); 216 return; 217 } 218 fts->account_pub = *account_pub; 219 } 220 else 221 { 222 fts->account_priv = *account_priv; 223 fts->have_priv = true; 224 GNUNET_CRYPTO_eddsa_key_get_public ( 225 &fts->account_priv.merchant_priv.eddsa_priv, 226 &fts->account_pub.merchant_pub.eddsa_pub); 227 } 228 } 229 else 230 { 231 /* No referenced account, no instance to take priv 232 * from, no explicit subject given: create new key! */ 233 GNUNET_CRYPTO_eddsa_key_create ( 234 &fts->account_priv.merchant_priv.eddsa_priv); 235 fts->have_priv = true; 236 GNUNET_CRYPTO_eddsa_key_get_public ( 237 &fts->account_priv.merchant_priv.eddsa_priv, 238 &fts->account_pub.merchant_pub.eddsa_pub); 239 } 240 fts->aih 241 = TALER_BANK_admin_add_kycauth ( 242 TALER_TESTING_interpreter_get_context (is), 243 &fts->auth, 244 &fts->account_pub, 245 &fts->amount, 246 fts->payto_debit_account, 247 &confirmation_cb, 248 fts); 249 if (NULL == fts->aih) 250 { 251 GNUNET_break (0); 252 TALER_TESTING_interpreter_fail (is); 253 return; 254 } 255 } 256 257 258 /** 259 * Free the state of a "/admin/add-kycauth" CMD, and possibly 260 * cancel a pending operation thereof. 261 * 262 * @param cls closure 263 * @param cmd current CMD being cleaned up. 264 */ 265 static void 266 admin_add_kycauth_cleanup (void *cls, 267 const struct TALER_TESTING_Command *cmd) 268 { 269 struct AdminAddKycauthState *fts = cls; 270 271 if (NULL != fts->aih) 272 { 273 TALER_TESTING_command_incomplete (fts->is, 274 cmd->label); 275 TALER_BANK_admin_add_kycauth_cancel (fts->aih); 276 fts->aih = NULL; 277 } 278 GNUNET_free (fts); 279 } 280 281 282 /** 283 * Offer internal data from a "/admin/add-kycauth" CMD to other 284 * commands. 285 * 286 * @param cls closure. 287 * @param[out] ret result 288 * @param trait name of the trait. 289 * @param index index number of the object to offer. 290 * @return #GNUNET_OK on success. 291 */ 292 static enum GNUNET_GenericReturnValue 293 admin_add_kycauth_traits (void *cls, 294 const void **ret, 295 const char *trait, 296 unsigned int index) 297 { 298 struct AdminAddKycauthState *fts = cls; 299 static struct TALER_FullPayto void_uri = { 300 .full_payto = (char *) "payto://void/the-exchange?receiver=name=exchange" 301 }; 302 struct TALER_TESTING_Trait traits[] = { 303 /* must be first! */ 304 TALER_TESTING_make_trait_account_priv (&fts->account_priv), 305 TALER_TESTING_make_trait_bank_row (&fts->serial_id), 306 TALER_TESTING_make_trait_debit_payto_uri (&fts->payto_debit_account), 307 TALER_TESTING_make_trait_full_payto_uri (&fts->payto_debit_account), 308 /* Used as a marker, content does not matter */ 309 TALER_TESTING_make_trait_credit_payto_uri (&void_uri), 310 TALER_TESTING_make_trait_exchange_bank_account_url ( 311 fts->exchange_credit_url), 312 TALER_TESTING_make_trait_amount (&fts->amount), 313 TALER_TESTING_make_trait_timestamp (0, 314 &fts->timestamp), 315 TALER_TESTING_make_trait_account_pub (&fts->account_pub), 316 TALER_TESTING_trait_end () 317 }; 318 319 if (MHD_HTTP_OK != 320 fts->expected_http_status) 321 return GNUNET_NO; /* requests that failed generate no history */ 322 323 return TALER_TESTING_get_trait (traits + (fts->have_priv ? 0 : 1), 324 ret, 325 trait, 326 index); 327 } 328 329 330 /** 331 * Create internal state for "/admin/add-kycauth" CMD. 332 * 333 * @param amount the amount to transfer. 334 * @param payto_debit_account which account sends money 335 * @param auth authentication data 336 * @param account_ref reference to command with account 337 * private key to use; NULL to create a fresh key pair 338 * @return the internal state 339 */ 340 static struct AdminAddKycauthState * 341 make_fts (const char *amount, 342 const struct TALER_BANK_AuthenticationData *auth, 343 const struct TALER_FullPayto payto_debit_account, 344 const char *account_ref) 345 { 346 struct AdminAddKycauthState *fts; 347 348 fts = GNUNET_new (struct AdminAddKycauthState); 349 fts->exchange_credit_url = auth->wire_gateway_url; 350 fts->payto_debit_account = payto_debit_account; 351 fts->account_ref = account_ref; 352 fts->auth = *auth; 353 fts->expected_http_status = MHD_HTTP_OK; 354 if (GNUNET_OK != 355 TALER_string_to_amount (amount, 356 &fts->amount)) 357 { 358 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 359 "Failed to parse amount `%s'\n", 360 amount); 361 GNUNET_assert (0); 362 } 363 return fts; 364 } 365 366 367 struct TALER_TESTING_Command 368 TALER_TESTING_cmd_admin_add_kycauth ( 369 const char *label, 370 const char *amount, 371 const struct TALER_BANK_AuthenticationData *auth, 372 const struct TALER_FullPayto payto_debit_account, 373 const char *account_ref) 374 { 375 struct TALER_TESTING_Command cmd = { 376 .cls = make_fts (amount, 377 auth, 378 payto_debit_account, 379 account_ref), 380 .label = label, 381 .run = &admin_add_kycauth_run, 382 .cleanup = &admin_add_kycauth_cleanup, 383 .traits = &admin_add_kycauth_traits 384 }; 385 386 return cmd; 387 } 388 389 390 /* end of testing_api_cmd_bank_admin_add_kycauth.c */