taler-merchant-httpd_private-get-instances-ID-kyc.c (35203B)
1 /* 2 This file is part of GNU Taler 3 (C) 2021-2024 Taler Systems SA 4 5 GNU Taler is free software; you can redistribute it and/or modify 6 it under the terms of the GNU Affero General Public License as 7 published by the Free Software Foundation; either version 3, 8 or (at your option) any later version. 9 10 GNU 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 13 GNU 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, 17 see <http://www.gnu.org/licenses/> 18 */ 19 20 /** 21 * @file taler-merchant-httpd_private-get-instances-ID-kyc.c 22 * @brief implementing GET /instances/$ID/kyc request handling 23 * @author Christian Grothoff 24 */ 25 #include "platform.h" 26 #include "taler-merchant-httpd_private-get-instances-ID-kyc.h" 27 #include "taler-merchant-httpd_helper.h" 28 #include "taler-merchant-httpd_exchanges.h" 29 #include <taler/taler_json_lib.h> 30 #include <taler/taler_dbevents.h> 31 #include <regex.h> 32 33 /** 34 * Information we keep per /kyc request. 35 */ 36 struct KycContext; 37 38 39 /** 40 * Structure for tracking requests to the exchange's 41 * ``/kyc-check`` API. 42 */ 43 struct ExchangeKycRequest 44 { 45 /** 46 * Kept in a DLL. 47 */ 48 struct ExchangeKycRequest *next; 49 50 /** 51 * Kept in a DLL. 52 */ 53 struct ExchangeKycRequest *prev; 54 55 /** 56 * Find operation where we connect to the respective exchange. 57 */ 58 struct TMH_EXCHANGES_KeysOperation *fo; 59 60 /** 61 * JSON array of payto-URIs with KYC auth wire transfer 62 * instructions. Provided if @e auth_ok is false and 63 * @e kyc_auth_conflict is false. 64 */ 65 json_t *pkaa; 66 67 /** 68 * The keys of the exchange. 69 */ 70 struct TALER_EXCHANGE_Keys *keys; 71 72 /** 73 * KYC request this exchange request is made for. 74 */ 75 struct KycContext *kc; 76 77 /** 78 * JSON array of AccountLimits that apply, NULL if 79 * unknown (and likely defaults apply). 80 */ 81 json_t *jlimits; 82 83 /** 84 * Our account's payto URI. 85 */ 86 struct TALER_FullPayto payto_uri; 87 88 /** 89 * Base URL of the exchange. 90 */ 91 char *exchange_url; 92 93 /** 94 * Hash of the wire account (with salt) we are checking. 95 */ 96 struct TALER_MerchantWireHashP h_wire; 97 98 /** 99 * Current access token for the KYC SPA. Only set 100 * if @e auth_ok is true. 101 */ 102 struct TALER_AccountAccessTokenP access_token; 103 104 /** 105 * Timestamp when we last got a reply from the exchange. 106 */ 107 struct GNUNET_TIME_Timestamp last_check; 108 109 /** 110 * Last HTTP status code obtained via /kyc-check from 111 * the exchange. 112 */ 113 unsigned int last_http_status; 114 115 /** 116 * Last Taler error code returned from /kyc-check. 117 */ 118 enum TALER_ErrorCode last_ec; 119 120 /** 121 * True if this account 122 * cannot work at this exchange because KYC auth is 123 * impossible. 124 */ 125 bool kyc_auth_conflict; 126 127 /** 128 * We could not get /keys from the exchange. 129 */ 130 bool no_keys; 131 132 /** 133 * True if @e access_token is available. 134 */ 135 bool auth_ok; 136 137 /** 138 * True if we believe no KYC is currently required 139 * for this account at this exchange. 140 */ 141 bool kyc_ok; 142 143 /** 144 * True if the exchange exposed to us that the account 145 * is currently under AML review. 146 */ 147 bool in_aml_review; 148 149 150 }; 151 152 153 /** 154 * Information we keep per /kyc request. 155 */ 156 struct KycContext 157 { 158 /** 159 * Stored in a DLL. 160 */ 161 struct KycContext *next; 162 163 /** 164 * Stored in a DLL. 165 */ 166 struct KycContext *prev; 167 168 /** 169 * Connection we are handling. 170 */ 171 struct MHD_Connection *connection; 172 173 /** 174 * Instance we are serving. 175 */ 176 struct TMH_MerchantInstance *mi; 177 178 /** 179 * Our handler context. 180 */ 181 struct TMH_HandlerContext *hc; 182 183 /** 184 * Response to return, NULL if we don't have one yet. 185 */ 186 struct MHD_Response *response; 187 188 /** 189 * JSON array where we are building up the array with 190 * pending KYC operations. 191 */ 192 json_t *kycs_data; 193 194 /** 195 * Head of DLL of requests we are making to an 196 * exchange to inquire about the latest KYC status. 197 */ 198 struct ExchangeKycRequest *exchange_pending_head; 199 200 /** 201 * Tail of DLL of requests we are making to an 202 * exchange to inquire about the latest KYC status. 203 */ 204 struct ExchangeKycRequest *exchange_pending_tail; 205 206 /** 207 * Set to the exchange URL, or NULL to not filter by 208 * exchange. 209 */ 210 const char *exchange_url; 211 212 /** 213 * Notification handler from database on changes 214 * to the KYC status. 215 */ 216 struct GNUNET_DB_EventHandler *eh; 217 218 /** 219 * Set to the h_wire of the merchant account if 220 * @a have_h_wire is true, used to filter by account. 221 */ 222 struct TALER_MerchantWireHashP h_wire; 223 224 /** 225 * How long are we willing to wait for the exchange(s)? 226 */ 227 struct GNUNET_TIME_Absolute timeout; 228 229 /** 230 * HTTP status code to use for the reply, i.e 200 for "OK". 231 * Special value UINT_MAX is used to indicate hard errors 232 * (no reply, return #MHD_NO). 233 */ 234 unsigned int response_code; 235 236 /** 237 * #GNUNET_NO if the @e connection was not suspended, 238 * #GNUNET_YES if the @e connection was suspended, 239 * #GNUNET_SYSERR if @e connection was resumed to as 240 * part of #MH_force_pc_resume during shutdown. 241 */ 242 enum GNUNET_GenericReturnValue suspended; 243 244 /** 245 * What state are we long-polling for? 246 */ 247 enum TALER_EXCHANGE_KycLongPollTarget lpt; 248 249 /** 250 * True if @e h_wire was given. 251 */ 252 bool have_h_wire; 253 254 /** 255 * We're still waiting on the exchange to determine 256 * the KYC status of our deposit(s). 257 */ 258 bool return_immediately; 259 260 }; 261 262 263 /** 264 * Head of DLL. 265 */ 266 static struct KycContext *kc_head; 267 268 /** 269 * Tail of DLL. 270 */ 271 static struct KycContext *kc_tail; 272 273 274 void 275 TMH_force_kyc_resume () 276 { 277 for (struct KycContext *kc = kc_head; 278 NULL != kc; 279 kc = kc->next) 280 { 281 if (GNUNET_YES == kc->suspended) 282 { 283 kc->suspended = GNUNET_SYSERR; 284 MHD_resume_connection (kc->connection); 285 } 286 } 287 } 288 289 290 /** 291 * Custom cleanup routine for a `struct KycContext`. 292 * 293 * @param cls the `struct KycContext` to clean up. 294 */ 295 static void 296 kyc_context_cleanup (void *cls) 297 { 298 struct KycContext *kc = cls; 299 struct ExchangeKycRequest *ekr; 300 301 while (NULL != (ekr = kc->exchange_pending_head)) 302 { 303 GNUNET_CONTAINER_DLL_remove (kc->exchange_pending_head, 304 kc->exchange_pending_tail, 305 ekr); 306 if (NULL != ekr->fo) 307 { 308 TMH_EXCHANGES_keys4exchange_cancel (ekr->fo); 309 ekr->fo = NULL; 310 } 311 json_decref (ekr->pkaa); 312 json_decref (ekr->jlimits); 313 if (NULL != ekr->keys) 314 TALER_EXCHANGE_keys_decref (ekr->keys); 315 GNUNET_free (ekr->exchange_url); 316 GNUNET_free (ekr->payto_uri.full_payto); 317 GNUNET_free (ekr); 318 } 319 if (NULL != kc->eh) 320 { 321 TMH_db->event_listen_cancel (kc->eh); 322 kc->eh = NULL; 323 } 324 if (NULL != kc->response) 325 { 326 MHD_destroy_response (kc->response); 327 kc->response = NULL; 328 } 329 GNUNET_CONTAINER_DLL_remove (kc_head, 330 kc_tail, 331 kc); 332 json_decref (kc->kycs_data); 333 GNUNET_free (kc); 334 } 335 336 337 /** 338 * Resume the given KYC context and send the final response. Stores the 339 * response in the @a kc and signals MHD to resume the connection. Also 340 * ensures MHD runs immediately. 341 * 342 * @param kc KYC context 343 */ 344 static void 345 resume_kyc_with_response (struct KycContext *kc) 346 { 347 kc->response_code = MHD_HTTP_OK; 348 kc->response = TALER_MHD_MAKE_JSON_PACK ( 349 GNUNET_JSON_pack_array_incref ("kyc_data", 350 kc->kycs_data)); 351 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 352 "Resuming /kyc handling as exchange interaction is done (%u)\n", 353 MHD_HTTP_OK); 354 if (GNUNET_YES == kc->suspended) 355 { 356 kc->suspended = GNUNET_NO; 357 MHD_resume_connection (kc->connection); 358 TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */ 359 } 360 } 361 362 363 /** 364 * Handle a DB event about an update relevant 365 * for the processing of the kyc request. 366 * 367 * @param cls our `struct KycContext` 368 * @param extra additional event data provided 369 * @param extra_size number of bytes in @a extra 370 */ 371 static void 372 kyc_change_cb (void *cls, 373 const void *extra, 374 size_t extra_size) 375 { 376 struct KycContext *kc = cls; 377 378 if (GNUNET_YES == kc->suspended) 379 { 380 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 381 "Resuming KYC with gateway timeout\n"); 382 kc->suspended = GNUNET_NO; 383 MHD_resume_connection (kc->connection); 384 TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */ 385 } 386 } 387 388 389 /** 390 * Pack the given @a limit into the JSON @a limits array. 391 * 392 * @param limit account limit to pack 393 * @param[in,out] limits JSON array to extend 394 */ 395 static void 396 pack_limit (const struct TALER_EXCHANGE_AccountLimit *limit, 397 json_t *limits) 398 { 399 json_t *jl; 400 401 jl = GNUNET_JSON_PACK ( 402 TALER_JSON_pack_kycte ("operation_type", 403 limit->operation_type), 404 GNUNET_JSON_pack_time_rel ("timeframe", 405 limit->timeframe), 406 TALER_JSON_pack_amount ("threshold", 407 &limit->threshold), 408 GNUNET_JSON_pack_bool ("soft_limit", 409 limit->soft_limit) 410 ); 411 GNUNET_assert (0 == 412 json_array_append_new (limits, 413 jl)); 414 } 415 416 417 /** 418 * Return JSON array with AccountLimit objects giving 419 * the current limits for this exchange. 420 * 421 * @param[in,out] ekr overall request context 422 */ 423 static json_t * 424 get_exchange_limits ( 425 struct ExchangeKycRequest *ekr) 426 { 427 const struct TALER_EXCHANGE_Keys *keys = ekr->keys; 428 json_t *limits; 429 430 if (NULL != ekr->jlimits) 431 { 432 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 433 "Returning custom KYC limits\n"); 434 return json_incref (ekr->jlimits); 435 } 436 if (NULL == keys) 437 { 438 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 439 "No keys, thus no default KYC limits known\n"); 440 return NULL; 441 } 442 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 443 "Returning default KYC limits (%u/%u)\n", 444 keys->hard_limits_length, 445 keys->zero_limits_length); 446 limits = json_array (); 447 GNUNET_assert (NULL != limits); 448 for (unsigned int i = 0; i<keys->hard_limits_length; i++) 449 { 450 const struct TALER_EXCHANGE_AccountLimit *limit 451 = &keys->hard_limits[i]; 452 453 pack_limit (limit, 454 limits); 455 } 456 for (unsigned int i = 0; i<keys->zero_limits_length; i++) 457 { 458 const struct TALER_EXCHANGE_ZeroLimitedOperation *zlimit 459 = &keys->zero_limits[i]; 460 json_t *jl; 461 struct TALER_Amount zero; 462 463 GNUNET_assert (GNUNET_OK == 464 TALER_amount_set_zero (keys->currency, 465 &zero)); 466 jl = GNUNET_JSON_PACK ( 467 TALER_JSON_pack_kycte ("operation_type", 468 zlimit->operation_type), 469 GNUNET_JSON_pack_time_rel ("timeframe", 470 GNUNET_TIME_UNIT_ZERO), 471 TALER_JSON_pack_amount ("threshold", 472 &zero), 473 GNUNET_JSON_pack_bool ("soft_limit", 474 true) 475 ); 476 GNUNET_assert (0 == 477 json_array_append_new (limits, 478 jl)); 479 } 480 return limits; 481 } 482 483 484 /** 485 * Maps @a ekr to a status code for clients to interpret the 486 * overall result. 487 * 488 * @param ekr request summary 489 * @return status of the KYC state as a string 490 */ 491 static const char * 492 map_to_status (const struct ExchangeKycRequest *ekr) 493 { 494 if (ekr->no_keys) 495 { 496 return "no-exchange-keys"; 497 } 498 if (ekr->kyc_ok) 499 { 500 if (NULL != ekr->jlimits) 501 { 502 size_t off; 503 json_t *limit; 504 json_array_foreach (ekr->jlimits, off, limit) 505 { 506 struct TALER_Amount threshold; 507 enum TALER_KYCLOGIC_KycTriggerEvent operation_type; 508 bool soft = false; 509 struct GNUNET_JSON_Specification spec[] = { 510 TALER_JSON_spec_kycte ("operation_type", 511 &operation_type), 512 TALER_JSON_spec_amount_any ("threshold", 513 &threshold), 514 GNUNET_JSON_spec_mark_optional ( 515 GNUNET_JSON_spec_bool ("soft_limit", 516 &soft), 517 NULL), 518 GNUNET_JSON_spec_end () 519 }; 520 521 if (GNUNET_OK != 522 GNUNET_JSON_parse (limit, 523 spec, 524 NULL, NULL)) 525 { 526 GNUNET_break (0); 527 return "merchant-internal-error"; 528 } 529 if (! TALER_amount_is_zero (&threshold)) 530 continue; /* only care about zero-limits */ 531 if (! soft) 532 continue; /* only care about soft limits */ 533 if ( (operation_type == TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT) || 534 (operation_type == TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE) || 535 (operation_type == TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION) ) 536 { 537 if (! ekr->auth_ok) 538 { 539 if (ekr->kyc_auth_conflict) 540 return "kyc-wire-impossible"; 541 return "kyc-wire-required"; 542 } 543 return "kyc-required"; 544 } 545 } 546 } 547 if (NULL == ekr->jlimits) 548 { 549 /* check default limits */ 550 const struct TALER_EXCHANGE_Keys *keys = ekr->keys; 551 552 for (unsigned int i = 0; i < keys->zero_limits_length; i++) 553 { 554 enum TALER_KYCLOGIC_KycTriggerEvent operation_type 555 = keys->zero_limits[i].operation_type; 556 557 if ( (operation_type == TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT) || 558 (operation_type == TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE) || 559 (operation_type == TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION) ) 560 { 561 if (! ekr->auth_ok) 562 { 563 if (ekr->kyc_auth_conflict) 564 return "kyc-wire-impossible"; 565 return "kyc-wire-required"; 566 } 567 return "kyc-required"; 568 } 569 } 570 } 571 return "ready"; 572 } 573 if (! ekr->auth_ok) 574 { 575 if (ekr->kyc_auth_conflict) 576 return "kyc-wire-impossible"; 577 return "kyc-wire-required"; 578 } 579 if (ekr->in_aml_review) 580 return "awaiting-aml-review"; 581 switch (ekr->last_http_status) 582 { 583 case 0: 584 return "exchange-unreachable"; 585 case MHD_HTTP_OK: 586 /* then we should have kyc_ok */ 587 GNUNET_break (0); 588 return NULL; 589 case MHD_HTTP_ACCEPTED: 590 /* Then KYC is really what is needed */ 591 return "kyc-required"; 592 case MHD_HTTP_NO_CONTENT: 593 /* then we should have had kyc_ok! */ 594 GNUNET_break (0); 595 return NULL; 596 case MHD_HTTP_FORBIDDEN: 597 /* then we should have had ! auth_ok */ 598 GNUNET_break (0); 599 return NULL; 600 case MHD_HTTP_NOT_FOUND: 601 /* then we should have had ! auth_ok */ 602 GNUNET_break (0); 603 return NULL; 604 case MHD_HTTP_CONFLICT: 605 /* then we should have had ! auth_ok */ 606 GNUNET_break (0); 607 return NULL; 608 case MHD_HTTP_INTERNAL_SERVER_ERROR: 609 return "exchange-internal-error"; 610 case MHD_HTTP_GATEWAY_TIMEOUT: 611 return "exchange-gateway-timeout"; 612 default: 613 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 614 "Exchange responded with unexpected HTTP status %u to /kyc-check request!\n", 615 ekr->last_http_status); 616 break; 617 } 618 return "exchange-status-invalid"; 619 } 620 621 622 /** 623 * Take data from @a ekr to expand our response. 624 * 625 * @param ekr exchange we are done inspecting 626 */ 627 static void 628 ekr_expand_response (struct ExchangeKycRequest *ekr) 629 { 630 const char *status; 631 632 status = map_to_status (ekr); 633 if (NULL == status) 634 { 635 GNUNET_break (0); 636 status = "logic-bug"; 637 } 638 GNUNET_assert ( 639 0 == 640 json_array_append_new ( 641 ekr->kc->kycs_data, 642 GNUNET_JSON_PACK ( 643 TALER_JSON_pack_full_payto ( 644 "payto_uri", 645 ekr->payto_uri), 646 GNUNET_JSON_pack_data_auto ( 647 "h_wire", 648 &ekr->h_wire), 649 GNUNET_JSON_pack_string ( 650 "status", 651 status), 652 GNUNET_JSON_pack_string ( 653 "exchange_url", 654 ekr->exchange_url), 655 GNUNET_JSON_pack_bool ("no_keys", 656 ekr->no_keys), 657 GNUNET_JSON_pack_bool ("auth_conflict", 658 ekr->kyc_auth_conflict), 659 GNUNET_JSON_pack_uint64 ("exchange_http_status", 660 ekr->last_http_status), 661 (TALER_EC_NONE == ekr->last_ec) 662 ? GNUNET_JSON_pack_allow_null ( 663 GNUNET_JSON_pack_string ( 664 "dummy", 665 NULL)) 666 : GNUNET_JSON_pack_uint64 ("exchange_code", 667 ekr->last_ec), 668 ekr->auth_ok 669 ? GNUNET_JSON_pack_data_auto ( 670 "access_token", 671 &ekr->access_token) 672 : GNUNET_JSON_pack_allow_null ( 673 GNUNET_JSON_pack_string ( 674 "dummy", 675 NULL)), 676 GNUNET_JSON_pack_allow_null ( 677 GNUNET_JSON_pack_array_steal ( 678 "limits", 679 get_exchange_limits (ekr))), 680 GNUNET_JSON_pack_allow_null ( 681 GNUNET_JSON_pack_array_incref ("payto_kycauths", 682 ekr->pkaa)) 683 ))); 684 } 685 686 687 /** 688 * We are done with asynchronous processing, generate the 689 * response for the @e kc. 690 * 691 * @param[in,out] kc KYC context to respond for 692 */ 693 static void 694 kc_respond (struct KycContext *kc) 695 { 696 if ( (! kc->return_immediately) && 697 (! GNUNET_TIME_absolute_is_past (kc->timeout)) ) 698 { 699 if (GNUNET_NO == kc->suspended) 700 { 701 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 702 "Suspending: long poll target %d not reached\n", 703 kc->lpt); 704 MHD_suspend_connection (kc->connection); 705 kc->suspended = GNUNET_YES; 706 } 707 else 708 { 709 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 710 "Remaining suspended: long poll target %d not reached\n", 711 kc->lpt); 712 } 713 return; 714 } 715 /* All exchange requests done, create final 716 big response from cumulated replies */ 717 resume_kyc_with_response (kc); 718 } 719 720 721 /** 722 * We are done with the KYC request @a ekr. Remove it from the work list and 723 * check if we are done overall. 724 * 725 * @param[in] ekr key request that is done (and will be freed) 726 */ 727 static void 728 ekr_finished (struct ExchangeKycRequest *ekr) 729 { 730 struct KycContext *kc = ekr->kc; 731 732 ekr_expand_response (ekr); 733 GNUNET_CONTAINER_DLL_remove (kc->exchange_pending_head, 734 kc->exchange_pending_tail, 735 ekr); 736 json_decref (ekr->jlimits); 737 json_decref (ekr->pkaa); 738 if (NULL != ekr->keys) 739 TALER_EXCHANGE_keys_decref (ekr->keys); 740 GNUNET_free (ekr->exchange_url); 741 GNUNET_free (ekr->payto_uri.full_payto); 742 GNUNET_free (ekr); 743 744 if (NULL != kc->exchange_pending_head) 745 return; /* wait for more */ 746 kc_respond (kc); 747 } 748 749 750 /** 751 * Figure out which exchange accounts from @a keys could 752 * be used for a KYC auth wire transfer from the account 753 * that @a ekr is checking. Will set the "pkaa" array 754 * in @a ekr. 755 * 756 * @param[in,out] ekr request we are processing 757 */ 758 static void 759 determine_eligible_accounts ( 760 struct ExchangeKycRequest *ekr) 761 { 762 struct KycContext *kc = ekr->kc; 763 const struct TALER_EXCHANGE_Keys *keys = ekr->keys; 764 struct TALER_Amount kyc_amount; 765 char *merchant_pub_str; 766 struct TALER_NormalizedPayto np; 767 768 ekr->pkaa = json_array (); 769 GNUNET_assert (NULL != ekr->pkaa); 770 { 771 const struct TALER_EXCHANGE_GlobalFee *gf; 772 773 gf = TALER_EXCHANGE_get_global_fee (keys, 774 GNUNET_TIME_timestamp_get ()); 775 if (NULL == gf) 776 { 777 GNUNET_assert (GNUNET_OK == 778 TALER_amount_set_zero (keys->currency, 779 &kyc_amount)); 780 } 781 else 782 { 783 /* FIXME-#9427: history fee should be globally renamed to KYC fee... */ 784 kyc_amount = gf->fees.history; 785 } 786 } 787 788 merchant_pub_str 789 = GNUNET_STRINGS_data_to_string_alloc ( 790 &kc->mi->merchant_pub, 791 sizeof (kc->mi->merchant_pub)); 792 /* For all accounts of the exchange */ 793 np = TALER_payto_normalize (ekr->payto_uri); 794 for (unsigned int i = 0; i<keys->accounts_len; i++) 795 { 796 const struct TALER_EXCHANGE_WireAccount *account 797 = &keys->accounts[i]; 798 799 /* KYC auth transfers are never supported with conversion */ 800 if (NULL != account->conversion_url) 801 continue; 802 /* filter by source account by credit_restrictions */ 803 if (GNUNET_YES != 804 TALER_EXCHANGE_test_account_allowed (account, 805 true, /* credit */ 806 np)) 807 continue; 808 /* exchange account is allowed, add it */ 809 { 810 const char *exchange_account_payto 811 = account->fpayto_uri.full_payto; 812 char *payto_kycauth; 813 814 if (TALER_amount_is_zero (&kyc_amount)) 815 GNUNET_asprintf (&payto_kycauth, 816 "%s%cmessage=KYC:%s", 817 exchange_account_payto, 818 (NULL == strchr (exchange_account_payto, 819 '?')) 820 ? '?' 821 : '&', 822 merchant_pub_str); 823 else 824 GNUNET_asprintf (&payto_kycauth, 825 "%s%camount=%s&message=KYC:%s", 826 exchange_account_payto, 827 (NULL == strchr (exchange_account_payto, 828 '?')) 829 ? '?' 830 : '&', 831 TALER_amount2s (&kyc_amount), 832 merchant_pub_str); 833 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 834 "Found account %s where KYC auth is possible\n", 835 payto_kycauth); 836 GNUNET_assert (0 == 837 json_array_append_new (ekr->pkaa, 838 json_string (payto_kycauth))); 839 GNUNET_free (payto_kycauth); 840 } 841 } 842 GNUNET_free (np.normalized_payto); 843 GNUNET_free (merchant_pub_str); 844 } 845 846 847 /** 848 * Function called with the result of a #TMH_EXCHANGES_keys4exchange() 849 * operation. Runs the KYC check against the exchange. 850 * 851 * @param cls closure with our `struct ExchangeKycRequest *` 852 * @param keys keys of the exchange context 853 * @param exchange representation of the exchange 854 */ 855 static void 856 kyc_with_exchange (void *cls, 857 struct TALER_EXCHANGE_Keys *keys, 858 struct TMH_Exchange *exchange) 859 { 860 struct ExchangeKycRequest *ekr = cls; 861 862 (void) exchange; 863 ekr->fo = NULL; 864 if (NULL == keys) 865 { 866 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 867 "Failed to download `%skeys`\n", 868 ekr->exchange_url); 869 ekr->no_keys = true; 870 ekr_finished (ekr); 871 return; 872 } 873 ekr->keys = TALER_EXCHANGE_keys_incref (keys); 874 if (! ekr->auth_ok) 875 { 876 determine_eligible_accounts (ekr); 877 if (0 == json_array_size (ekr->pkaa)) 878 { 879 /* No KYC auth wire transfers are possible to this exchange from 880 our merchant bank account, so we cannot use this account with 881 this exchange if it has any KYC requirements! */ 882 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 883 "KYC auth to `%s' impossible for merchant account `%s'\n", 884 ekr->exchange_url, 885 ekr->payto_uri.full_payto); 886 ekr->kyc_auth_conflict = true; 887 } 888 } 889 ekr_finished (ekr); 890 } 891 892 893 /** 894 * Closure for add_unreachable_status(). 895 */ 896 struct UnreachableContext 897 { 898 /** 899 * Where we are building the response. 900 */ 901 struct KycContext *kc; 902 903 /** 904 * Pointer to our account hash. 905 */ 906 const struct TALER_MerchantWireHashP *h_wire; 907 908 /** 909 * Bank account for which we have no status from any exchange. 910 */ 911 struct TALER_FullPayto payto_uri; 912 913 }; 914 915 /** 916 * Add all trusted exchanges with "unknown" status for the 917 * bank account given in the context. 918 * 919 * @param cls a `struct UnreachableContext` 920 * @param url base URL of the exchange 921 * @param exchange internal handle for the exchange 922 */ 923 static void 924 add_unreachable_status (void *cls, 925 const char *url, 926 const struct TMH_Exchange *exchange) 927 { 928 struct UnreachableContext *uc = cls; 929 struct KycContext *kc = uc->kc; 930 931 GNUNET_assert ( 932 0 == 933 json_array_append_new ( 934 kc->kycs_data, 935 GNUNET_JSON_PACK ( 936 TALER_JSON_pack_full_payto ( 937 "payto_uri", 938 uc->payto_uri), 939 GNUNET_JSON_pack_data_auto ( 940 "h_wire", 941 uc->h_wire), 942 GNUNET_JSON_pack_string ( 943 "status", 944 "exchange-unreachable"), 945 GNUNET_JSON_pack_string ( 946 "exchange_url", 947 url), 948 GNUNET_JSON_pack_bool ("no_keys", 949 true), 950 GNUNET_JSON_pack_bool ("auth_conflict", 951 false), 952 GNUNET_JSON_pack_uint64 ("exchange_http_status", 953 0) 954 ))); 955 956 } 957 958 959 /** 960 * Function called from account_kyc_get_status() with KYC status information 961 * for this merchant. 962 * 963 * @param cls our `struct KycContext *` 964 * @param h_wire hash of the wire account 965 * @param payto_uri payto:// URI of the merchant's bank account 966 * @param exchange_url base URL of the exchange for which this is a status 967 * @param last_check when did we last get an update on our KYC status from the exchange 968 * @param kyc_ok true if we satisfied the KYC requirements 969 * @param access_token access token for the KYC SPA, NULL if we cannot access it yet (need KYC auth wire transfer) 970 * @param last_http_status last HTTP status from /kyc-check 971 * @param last_ec last Taler error code from /kyc-check 972 * @param in_aml_review true if the account is pending review 973 * @param jlimits JSON array of applicable AccountLimits, or NULL if unknown (like defaults apply) 974 */ 975 static void 976 kyc_status_cb ( 977 void *cls, 978 const struct TALER_MerchantWireHashP *h_wire, 979 struct TALER_FullPayto payto_uri, 980 const char *exchange_url, 981 struct GNUNET_TIME_Timestamp last_check, 982 bool kyc_ok, 983 const struct TALER_AccountAccessTokenP *access_token, 984 unsigned int last_http_status, 985 enum TALER_ErrorCode last_ec, 986 bool in_aml_review, 987 const json_t *jlimits) 988 { 989 struct KycContext *kc = cls; 990 struct ExchangeKycRequest *ekr; 991 992 if (NULL == exchange_url) 993 { 994 struct UnreachableContext uc = { 995 .kc = kc, 996 .h_wire = h_wire, 997 .payto_uri = payto_uri 998 }; 999 1000 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1001 "Account has unknown KYC status for all exchanges.\n"); 1002 TMH_exchange_get_trusted (&add_unreachable_status, 1003 &uc); 1004 kc_respond (kc); 1005 return; 1006 } 1007 if (! TMH_EXCHANGES_check_trusted (exchange_url)) 1008 { 1009 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1010 "Skipping exchange `%s': not trusted\n", 1011 exchange_url); 1012 return; 1013 } 1014 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1015 "KYC status for `%s' at `%s' is %u/%s/%s/%s\n", 1016 payto_uri.full_payto, 1017 exchange_url, 1018 last_http_status, 1019 kyc_ok ? "KYC OK" : "KYC NEEDED", 1020 in_aml_review ? "IN AML REVIEW" : "NO AML REVIEW", 1021 NULL == jlimits ? "DEFAULT LIMITS" : "CUSTOM LIMITS"); 1022 switch (kc->lpt) 1023 { 1024 case TALER_EXCHANGE_KLPT_NONE: 1025 break; 1026 case TALER_EXCHANGE_KLPT_KYC_AUTH_TRANSFER: 1027 if (NULL != access_token) 1028 kc->return_immediately = true; 1029 break; 1030 case TALER_EXCHANGE_KLPT_INVESTIGATION_DONE: 1031 if (! in_aml_review) 1032 kc->return_immediately = true; 1033 break; 1034 case TALER_EXCHANGE_KLPT_KYC_OK: 1035 if (kyc_ok) 1036 kc->return_immediately = true; 1037 break; 1038 } 1039 ekr = GNUNET_new (struct ExchangeKycRequest); 1040 GNUNET_CONTAINER_DLL_insert (kc->exchange_pending_head, 1041 kc->exchange_pending_tail, 1042 ekr); 1043 ekr->last_http_status = last_http_status; 1044 ekr->last_ec = last_ec; 1045 if (NULL != jlimits) 1046 ekr->jlimits = json_incref ((json_t *) jlimits); 1047 ekr->h_wire = *h_wire; 1048 ekr->exchange_url = GNUNET_strdup (exchange_url); 1049 ekr->payto_uri.full_payto 1050 = GNUNET_strdup (payto_uri.full_payto); 1051 ekr->last_check = last_check; 1052 ekr->kyc_ok = kyc_ok; 1053 ekr->kc = kc; 1054 ekr->in_aml_review = in_aml_review; 1055 ekr->auth_ok = (NULL != access_token); 1056 if ( (! ekr->auth_ok) || 1057 (NULL == ekr->jlimits) ) 1058 { 1059 /* Figure out wire transfer instructions */ 1060 if (GNUNET_NO == kc->suspended) 1061 { 1062 MHD_suspend_connection (kc->connection); 1063 kc->suspended = GNUNET_YES; 1064 } 1065 ekr->fo = TMH_EXCHANGES_keys4exchange ( 1066 exchange_url, 1067 false, 1068 &kyc_with_exchange, 1069 ekr); 1070 if (NULL == ekr->fo) 1071 { 1072 GNUNET_break (0); 1073 ekr_finished (ekr); 1074 return; 1075 } 1076 return; 1077 } 1078 ekr->access_token = *access_token; 1079 ekr_finished (ekr); 1080 } 1081 1082 1083 /** 1084 * Check the KYC status of an instance. 1085 * 1086 * @param mi instance to check KYC status of 1087 * @param connection the MHD connection to handle 1088 * @param[in,out] hc context with further information about the request 1089 * @return MHD result code 1090 */ 1091 static MHD_RESULT 1092 get_instances_ID_kyc ( 1093 struct TMH_MerchantInstance *mi, 1094 struct MHD_Connection *connection, 1095 struct TMH_HandlerContext *hc) 1096 { 1097 struct KycContext *kc = hc->ctx; 1098 1099 if (NULL == kc) 1100 { 1101 kc = GNUNET_new (struct KycContext); 1102 kc->mi = mi; 1103 hc->ctx = kc; 1104 hc->cc = &kyc_context_cleanup; 1105 GNUNET_CONTAINER_DLL_insert (kc_head, 1106 kc_tail, 1107 kc); 1108 kc->connection = connection; 1109 kc->hc = hc; 1110 kc->kycs_data = json_array (); 1111 GNUNET_assert (NULL != kc->kycs_data); 1112 TALER_MHD_parse_request_timeout (connection, 1113 &kc->timeout); 1114 { 1115 uint64_t num = 0; 1116 int val; 1117 1118 TALER_MHD_parse_request_number (connection, 1119 "lpt", 1120 &num); 1121 val = (int) num; 1122 if ( (val < 0) || 1123 (val > TALER_EXCHANGE_KLPT_MAX) ) 1124 { 1125 /* Protocol violation, but we can be graceful and 1126 just ignore the long polling! */ 1127 GNUNET_break_op (0); 1128 val = TALER_EXCHANGE_KLPT_NONE; 1129 } 1130 kc->lpt = (enum TALER_EXCHANGE_KycLongPollTarget) val; 1131 } 1132 kc->return_immediately 1133 = (TALER_EXCHANGE_KLPT_NONE == kc->lpt); 1134 /* process 'exchange_url' argument */ 1135 kc->exchange_url = MHD_lookup_connection_value ( 1136 connection, 1137 MHD_GET_ARGUMENT_KIND, 1138 "exchange_url"); 1139 if ( (NULL != kc->exchange_url) && 1140 ( (! TALER_url_valid_charset (kc->exchange_url)) || 1141 (! TALER_is_web_url (kc->exchange_url)) ) ) 1142 { 1143 GNUNET_break_op (0); 1144 return TALER_MHD_reply_with_error ( 1145 connection, 1146 MHD_HTTP_BAD_REQUEST, 1147 TALER_EC_GENERIC_PARAMETER_MALFORMED, 1148 "exchange_url must be a valid HTTP(s) URL"); 1149 } 1150 1151 TALER_MHD_parse_request_arg_auto (connection, 1152 "h_wire", 1153 &kc->h_wire, 1154 kc->have_h_wire); 1155 1156 if ( (TALER_EXCHANGE_KLPT_NONE != kc->lpt) && 1157 (! GNUNET_TIME_absolute_is_past (kc->timeout)) ) 1158 { 1159 if (kc->have_h_wire) 1160 { 1161 struct TALER_MERCHANTDB_MerchantKycStatusChangeEventP ev = { 1162 .header.size = htons (sizeof (ev)), 1163 .header.type = htons ( 1164 TALER_DBEVENT_MERCHANT_EXCHANGE_KYC_STATUS_CHANGED 1165 ), 1166 .h_wire = kc->h_wire 1167 }; 1168 1169 kc->eh = TMH_db->event_listen ( 1170 TMH_db->cls, 1171 &ev.header, 1172 GNUNET_TIME_absolute_get_remaining (kc->timeout), 1173 &kyc_change_cb, 1174 kc); 1175 } 1176 else 1177 { 1178 struct GNUNET_DB_EventHeaderP hdr = { 1179 .size = htons (sizeof (hdr)), 1180 .type = htons (TALER_DBEVENT_MERCHANT_KYC_STATUS_CHANGED) 1181 }; 1182 1183 kc->eh = TMH_db->event_listen ( 1184 TMH_db->cls, 1185 &hdr, 1186 GNUNET_TIME_absolute_get_remaining (kc->timeout), 1187 &kyc_change_cb, 1188 kc); 1189 } 1190 } /* end register LISTEN hooks */ 1191 } /* end 1st time initialization */ 1192 1193 if (GNUNET_SYSERR == kc->suspended) 1194 return MHD_NO; /* during shutdown, we don't generate any more replies */ 1195 GNUNET_assert (GNUNET_NO == kc->suspended); 1196 1197 if (NULL != kc->response) 1198 return MHD_queue_response (connection, 1199 kc->response_code, 1200 kc->response); 1201 1202 /* Check our database */ 1203 { 1204 enum GNUNET_DB_QueryStatus qs; 1205 1206 GNUNET_break (0 == 1207 json_array_clear (kc->kycs_data)); 1208 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1209 "Checking KYC status for %s (%d/%s)\n", 1210 mi->settings.id, 1211 kc->have_h_wire, 1212 kc->exchange_url); 1213 qs = TMH_db->account_kyc_get_status ( 1214 TMH_db->cls, 1215 mi->settings.id, 1216 kc->have_h_wire 1217 ? &kc->h_wire 1218 : NULL, 1219 kc->exchange_url, 1220 &kyc_status_cb, 1221 kc); 1222 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1223 "account_kyc_get_status returned %d records\n", 1224 (int) qs); 1225 if (qs < 0) 1226 { 1227 /* Database error */ 1228 GNUNET_break (0); 1229 if (GNUNET_YES == kc->suspended) 1230 { 1231 /* must have suspended before DB error, resume! */ 1232 MHD_resume_connection (connection); 1233 kc->suspended = GNUNET_NO; 1234 } 1235 return TALER_MHD_reply_with_ec ( 1236 connection, 1237 TALER_EC_GENERIC_DB_FETCH_FAILED, 1238 "account_kyc_get_status"); 1239 } 1240 if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) 1241 { 1242 /* no matching accounts, could not have suspended */ 1243 GNUNET_assert (GNUNET_NO == kc->suspended); 1244 return TALER_MHD_reply_static (connection, 1245 MHD_HTTP_NO_CONTENT, 1246 NULL, 1247 NULL, 1248 0); 1249 } 1250 } 1251 if (GNUNET_YES == kc->suspended) 1252 return MHD_YES; 1253 /* Should have generated a response */ 1254 GNUNET_break (NULL != kc->response); 1255 return MHD_queue_response (connection, 1256 kc->response_code, 1257 kc->response); 1258 } 1259 1260 1261 MHD_RESULT 1262 TMH_private_get_instances_ID_kyc ( 1263 const struct TMH_RequestHandler *rh, 1264 struct MHD_Connection *connection, 1265 struct TMH_HandlerContext *hc) 1266 { 1267 struct TMH_MerchantInstance *mi = hc->instance; 1268 1269 (void) rh; 1270 return get_instances_ID_kyc (mi, 1271 connection, 1272 hc); 1273 } 1274 1275 1276 MHD_RESULT 1277 TMH_private_get_instances_default_ID_kyc ( 1278 const struct TMH_RequestHandler *rh, 1279 struct MHD_Connection *connection, 1280 struct TMH_HandlerContext *hc) 1281 { 1282 struct TMH_MerchantInstance *mi; 1283 1284 (void) rh; 1285 mi = TMH_lookup_instance (hc->infix); 1286 if (NULL == mi) 1287 { 1288 return TALER_MHD_reply_with_error ( 1289 connection, 1290 MHD_HTTP_NOT_FOUND, 1291 TALER_EC_MERCHANT_GENERIC_INSTANCE_UNKNOWN, 1292 hc->infix); 1293 } 1294 return get_instances_ID_kyc (mi, 1295 connection, 1296 hc); 1297 } 1298 1299 1300 /* end of taler-merchant-httpd_private-get-instances-ID-kyc.c */