taler-merchant-httpd_get-private-kyc.c (52463B)
1 /* 2 This file is part of GNU Taler 3 (C) 2021-2026 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 src/backend/taler-merchant-httpd_get-private-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_exchanges.h" 27 #include "taler-merchant-httpd_get-private-kyc.h" 28 #include "taler-merchant-httpd_kyc-order.h" 29 #include "taler-merchant-httpd_helper.h" 30 #include "taler-merchant-httpd_get-exchanges.h" 31 #include <taler/taler_json_lib.h> 32 #include <taler/taler_templating_lib.h> 33 #include <taler/taler_dbevents.h> 34 #include <regex.h> 35 #include "merchant-database/iterate_kyc_statuses.h" 36 #include "merchant-database/event_listen.h" 37 #include "merchant-database/set_instance.h" 38 #include "merchant-database/get_tos_accepted_early.h" 39 40 /** 41 * Information we keep per /kyc request. 42 */ 43 struct KycContext; 44 45 46 /** 47 * Structure for tracking requests to the exchange's 48 * ``/kyc-check`` API. 49 */ 50 struct ExchangeKycRequest 51 { 52 /** 53 * Kept in a DLL. 54 */ 55 struct ExchangeKycRequest *next; 56 57 /** 58 * Kept in a DLL. 59 */ 60 struct ExchangeKycRequest *prev; 61 62 /** 63 * Find operation where we connect to the respective exchange. 64 */ 65 struct TMH_EXCHANGES_KeysOperation *fo; 66 67 /** 68 * JSON array of payto-URIs with KYC auth wire transfer 69 * instructions. Provided if @e auth_ok is false and 70 * @e kyc_auth_conflict is false. 71 */ 72 json_t *pkaa; 73 74 /** 75 * The keys of the exchange. 76 */ 77 struct TALER_EXCHANGE_Keys *keys; 78 79 /** 80 * KYC request this exchange request is made for. 81 */ 82 struct KycContext *kc; 83 84 /** 85 * JSON array of AccountLimits that apply, NULL if 86 * unknown (and likely defaults apply). 87 */ 88 json_t *jlimits; 89 90 /** 91 * Our account's payto URI. 92 */ 93 struct TALER_FullPayto payto_uri; 94 95 /** 96 * Base URL of the exchange. 97 */ 98 char *exchange_url; 99 100 /** 101 * Hash of the wire account (with salt) we are checking. 102 */ 103 struct TALER_MerchantWireHashP h_wire; 104 105 /** 106 * Current access token for the KYC SPA. Only set 107 * if @e auth_ok is true. 108 */ 109 struct TALER_AccountAccessTokenP access_token; 110 111 /** 112 * Timestamp when we last got a reply from the exchange. 113 */ 114 struct GNUNET_TIME_Timestamp last_check; 115 116 /** 117 * Last HTTP status code obtained via /kyc-check from the exchange. 118 */ 119 unsigned int last_http_status; 120 121 /** 122 * Last Taler error code returned from /kyc-check. 123 */ 124 enum TALER_ErrorCode last_ec; 125 126 /** 127 * True if this account cannot work at this exchange because KYC auth is 128 * impossible. 129 */ 130 bool kyc_auth_conflict; 131 132 /** 133 * We could not get /keys from the exchange. 134 */ 135 bool no_keys; 136 137 /** 138 * True if @e access_token is available. 139 */ 140 bool auth_ok; 141 142 /** 143 * True if we believe no KYC is currently required 144 * for this account at this exchange. 145 */ 146 bool kyc_ok; 147 148 /** 149 * True if the exchange exposed to us that the account 150 * is currently under AML review. 151 */ 152 bool in_aml_review; 153 154 }; 155 156 157 /** 158 * Information we keep per /kyc request. 159 */ 160 struct KycContext 161 { 162 /** 163 * Stored in a DLL. 164 */ 165 struct KycContext *next; 166 167 /** 168 * Stored in a DLL. 169 */ 170 struct KycContext *prev; 171 172 /** 173 * Connection we are handling. 174 */ 175 struct MHD_Connection *connection; 176 177 /** 178 * Instance we are serving. 179 */ 180 struct TMH_MerchantInstance *mi; 181 182 /** 183 * Our handler context. 184 */ 185 struct TMH_HandlerContext *hc; 186 187 /** 188 * JSON array where we are building up the array with 189 * pending KYC operations. 190 */ 191 json_t *kycs_data; 192 193 /** 194 * Head of DLL of requests we are making to an 195 * exchange to inquire about the latest KYC status. 196 */ 197 struct ExchangeKycRequest *exchange_pending_head; 198 199 /** 200 * Tail of DLL of requests we are making to an 201 * exchange to inquire about the latest KYC status. 202 */ 203 struct ExchangeKycRequest *exchange_pending_tail; 204 205 /** 206 * Notification handler from database on changes 207 * to the KYC status. 208 */ 209 struct GNUNET_DB_EventHandler *eh; 210 211 /** 212 * Set to the exchange URL, or NULL to not filter by 213 * exchange. "exchange_url" query parameter. 214 */ 215 const char *exchange_url; 216 217 /** 218 * How long are we willing to wait for the exchange(s)? 219 * Based on "timeout_ms" query parameter. 220 */ 221 struct GNUNET_TIME_Absolute timeout; 222 223 /** 224 * Set to the h_wire of the merchant account if 225 * @a have_h_wire is true, used to filter by account. 226 * Set from "h_wire" query parameter. 227 */ 228 struct TALER_MerchantWireHashP h_wire; 229 230 /** 231 * Set to the Etag of a response already known to the 232 * client. We should only return from long-polling 233 * on timeout (with "Not Modified") or when the Etag 234 * of the response differs from what is given here. 235 * Only set if @a have_lp_not_etag is true. 236 * Set from "lp_etag" query parameter. 237 */ 238 struct GNUNET_ShortHashCode lp_not_etag; 239 240 /** 241 * Specifies what status change we are long-polling for. If specified, the 242 * endpoint will only return once the status *matches* the given value. If 243 * multiple accounts or exchanges match the query, any account reaching the 244 * STATUS will cause the response to be returned. 245 */ 246 const char *lp_status; 247 248 /** 249 * Specifies what status change we are long-polling for. If specified, the 250 * endpoint will only return once the status no longer matches the given 251 * value. If multiple accounts or exchanges *no longer matches* the given 252 * STATUS will cause the response to be returned. 253 */ 254 const char *lp_not_status; 255 256 /** 257 * #GNUNET_NO if the @e connection was not suspended, 258 * #GNUNET_YES if the @e connection was suspended, 259 * #GNUNET_SYSERR if @e connection was resumed to as 260 * part of #MH_force_pc_resume during shutdown. 261 */ 262 enum GNUNET_GenericReturnValue suspended; 263 264 /** 265 * What state are we long-polling for? "lpt" argument. 266 */ 267 enum TALER_EXCHANGE_KycLongPollTarget lpt; 268 269 /** 270 * Processing phase. 271 */ 272 enum 273 { 274 PHASE_INIT = 0, 275 PHASE_DETERMINE_LONG_POLL, 276 PHASE_DATABASE_KYC_CHECK, 277 PHASE_NO_ACCOUNTS, 278 PHASE_GENERATE_RESPONSE, 279 PHASE_IN_SHUTDOWN = 999, 280 PHASE_RETURN_YES, 281 PHASE_RETURN_NO, 282 PHASE_SUSPENDED_ON_ACCOUNT, 283 PHASE_SUSPENDED_ON_EXCHANGE, 284 } phase; 285 286 /** 287 * Output format requested by the client. 288 */ 289 enum 290 { 291 POF_JSON, 292 POF_TEXT, 293 POF_PDF 294 } format; 295 296 /** 297 * Set to true if the database notified us about a change 298 * in the account but we did not yet check the database 299 * status as we were waiting on something else. 300 */ 301 bool account_signal; 302 303 /** 304 * True if @e h_wire was given. 305 */ 306 bool have_h_wire; 307 308 /** 309 * True if @e lp_not_etag was given. 310 */ 311 bool have_lp_not_etag; 312 313 /** 314 * We're still waiting on the exchange to determine 315 * the KYC status of our deposit(s). 316 */ 317 bool return_immediately; 318 319 /** 320 * Are we currently still iterating over the database and 321 * thus must not yet respond? 322 */ 323 bool in_db; 324 325 /** 326 * The initial database read already requested an exchange refresh. 327 */ 328 bool refresh_requested; 329 }; 330 331 332 /** 333 * Head of DLL. 334 */ 335 static struct KycContext *kc_head; 336 337 /** 338 * Tail of DLL. 339 */ 340 static struct KycContext *kc_tail; 341 342 343 /* ******************* cleanup ***************** */ 344 345 void 346 TMH_force_kyc_resume () 347 { 348 for (struct KycContext *kc = kc_head; 349 NULL != kc; 350 kc = kc->next) 351 { 352 if (GNUNET_YES == kc->suspended) 353 { 354 kc->suspended = GNUNET_SYSERR; 355 kc->phase = PHASE_IN_SHUTDOWN; 356 MHD_resume_connection (kc->connection); 357 } 358 } 359 } 360 361 362 /** 363 * Release resources of @a ekr 364 * 365 * @param[in] ekr key request data to clean up 366 */ 367 static void 368 ekr_cleanup (struct ExchangeKycRequest *ekr) 369 { 370 struct KycContext *kc = ekr->kc; 371 372 GNUNET_CONTAINER_DLL_remove (kc->exchange_pending_head, 373 kc->exchange_pending_tail, 374 ekr); 375 if (NULL != ekr->fo) 376 { 377 TMH_EXCHANGES_keys4exchange_cancel (ekr->fo); 378 ekr->fo = NULL; 379 } 380 json_decref (ekr->pkaa); 381 json_decref (ekr->jlimits); 382 if (NULL != ekr->keys) 383 TALER_EXCHANGE_keys_decref (ekr->keys); 384 GNUNET_free (ekr->exchange_url); 385 GNUNET_free (ekr->payto_uri.full_payto); 386 GNUNET_free (ekr); 387 } 388 389 390 /** 391 * Custom cleanup routine for a `struct KycContext`. 392 * 393 * @param cls the `struct KycContext` to clean up. 394 */ 395 static void 396 kyc_context_cleanup (void *cls) 397 { 398 struct KycContext *kc = cls; 399 struct ExchangeKycRequest *ekr; 400 401 while (NULL != (ekr = kc->exchange_pending_head)) 402 { 403 ekr_cleanup (ekr); 404 } 405 if (NULL != kc->eh) 406 { 407 TALER_MERCHANTDB_event_listen_cancel (kc->eh); 408 kc->eh = NULL; 409 } 410 GNUNET_CONTAINER_DLL_remove (kc_head, 411 kc_tail, 412 kc); 413 json_decref (kc->kycs_data); 414 GNUNET_free (kc); 415 } 416 417 418 /** 419 * Finish handling the connection returning @a ret to MHD 420 * 421 * @param[in,out] kc connection we are handling 422 * @param mhd_ret result to return for the @a kc request 423 */ 424 static void 425 finish_request (struct KycContext *kc, 426 enum MHD_Result mhd_ret) 427 { 428 kc->phase = (MHD_YES == mhd_ret) 429 ? PHASE_RETURN_YES 430 : PHASE_RETURN_NO; 431 } 432 433 434 /* ******************* phase_init ***************** */ 435 436 437 /** 438 * Initialize basic data structures of the connection, 439 * finishes parsing the request. 440 * 441 * @param[in,out] kc connection we are handling 442 */ 443 static void 444 phase_init (struct KycContext *kc) 445 { 446 kc->kycs_data = json_array (); 447 GNUNET_assert (NULL != kc->kycs_data); 448 /* process 'exchange_url' argument */ 449 kc->exchange_url = MHD_lookup_connection_value ( 450 kc->connection, 451 MHD_GET_ARGUMENT_KIND, 452 "exchange_url"); 453 if ( (NULL != kc->exchange_url) && 454 ( (! TALER_url_valid_charset (kc->exchange_url)) || 455 (! TALER_is_web_url (kc->exchange_url)) ) ) 456 { 457 GNUNET_break_op (0); 458 finish_request (kc, 459 TALER_MHD_reply_with_error ( 460 kc->connection, 461 MHD_HTTP_BAD_REQUEST, 462 TALER_EC_GENERIC_PARAMETER_MALFORMED, 463 "exchange_url must be a valid HTTP(s) URL")); 464 return; 465 } 466 467 /* Determine desired output format from Accept header */ 468 { 469 const char *mime; 470 471 mime = MHD_lookup_connection_value (kc->connection, 472 MHD_HEADER_KIND, 473 MHD_HTTP_HEADER_ACCEPT); 474 if (NULL == mime) 475 mime = "application/json"; 476 if (0 == strcmp (mime, 477 "*/*")) 478 mime = "application/json"; 479 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 480 "KYC status requested for format %s\n", 481 mime); 482 if (0 == strcmp (mime, 483 "application/json")) 484 { 485 kc->format = POF_JSON; 486 } 487 else if (0 == strcmp (mime, 488 "text/plain")) 489 { 490 kc->format = POF_TEXT; 491 } 492 #if FUTURE 493 else if (0 == strcmp (mime, 494 "application/pdf")) 495 { 496 kc->format = POF_PDF; 497 } 498 #endif 499 else 500 { 501 GNUNET_break_op (0); 502 finish_request (kc, 503 TALER_MHD_REPLY_JSON_PACK ( 504 kc->connection, 505 MHD_HTTP_NOT_ACCEPTABLE, 506 GNUNET_JSON_pack_string ("hint", 507 mime))); 508 return; 509 } 510 } 511 kc->phase++; 512 } 513 514 515 /* ******************* phase_determine_long_poll ***************** */ 516 517 518 /** 519 * Handle a DB event about an update relevant 520 * for the processing of the kyc request. 521 * 522 * @param cls our `struct KycContext` 523 * @param extra additional event data provided 524 * @param extra_size number of bytes in @a extra 525 */ 526 static void 527 kyc_change_cb (void *cls, 528 const void *extra, 529 size_t extra_size) 530 { 531 struct KycContext *kc = cls; 532 533 if ( (GNUNET_YES == kc->suspended) && 534 (PHASE_SUSPENDED_ON_ACCOUNT == kc->phase) ) 535 { 536 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 537 "Resuming KYC with gateway timeout\n"); 538 kc->suspended = GNUNET_NO; 539 kc->phase = PHASE_DATABASE_KYC_CHECK; 540 MHD_resume_connection (kc->connection); 541 TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */ 542 } 543 else 544 { 545 /* remember for later */ 546 kc->account_signal = true; 547 } 548 } 549 550 551 void 552 TMH_kyc_keys_changed (const char *exchange_url) 553 { 554 for (struct KycContext *kc = kc_head; 555 NULL != kc; 556 kc = kc->next) 557 { 558 size_t off; 559 const json_t *entry; 560 bool affected = false; 561 562 if (NULL == kc->eh) 563 continue; /* no long poll */ 564 /* Completed account lookups live in the response; other lookups may 565 still be waiting for keys. Check both to cover updates during reads. */ 566 json_array_foreach (kc->kycs_data, off, entry) 567 { 568 const char *url = json_string_value (json_object_get (entry, 569 "exchange_url")); 570 571 if ( (NULL != url) && 572 (0 == strcmp (url, exchange_url)) ) 573 { 574 affected = true; 575 break; 576 } 577 } 578 for (struct ExchangeKycRequest *ekr = kc->exchange_pending_head; 579 (! affected) && (NULL != ekr); 580 ekr = ekr->next) 581 affected = (0 == strcmp (ekr->exchange_url, exchange_url)); 582 if (affected) 583 { 584 /* Keys affect ToS flags, default limits and KYC auth instructions. 585 Recompute the full response and let its ETag determine whether to 586 return. Like a status notification, this does not force a refresh. */ 587 kyc_change_cb (kc, NULL, 0); 588 } 589 } 590 } 591 592 593 /** 594 * Suspend @a kc until we have a change in the account status. 595 * 596 * @param[in,out] kc request to suspend 597 */ 598 static void 599 wait_for_account (struct KycContext *kc) 600 { 601 GNUNET_assert (GNUNET_NO == kc->suspended); 602 if (kc->account_signal) 603 { 604 /* we got a NOTIFY earlier, handle it immediately */ 605 kc->account_signal = false; 606 kc->phase = PHASE_DATABASE_KYC_CHECK; 607 return; 608 } 609 /* Wait on account notification */ 610 MHD_suspend_connection (kc->connection); 611 kc->suspended = GNUNET_YES; 612 kc->phase = PHASE_SUSPENDED_ON_ACCOUNT; 613 } 614 615 616 /** 617 * Setup long-polling for the connection, if applicable. 618 * 619 * @param[in,out] kc connection we are handling 620 */ 621 static void 622 phase_determine_long_poll (struct KycContext *kc) 623 { 624 if (GNUNET_TIME_absolute_is_past (kc->timeout)) 625 { 626 kc->phase++; 627 return; 628 } 629 if (kc->have_h_wire) 630 { 631 struct TALER_MERCHANTDB_MerchantKycStatusChangeEventP ev = { 632 .header.size = htons (sizeof (ev)), 633 .header.type = htons ( 634 TALER_DBEVENT_MERCHANT_EXCHANGE_KYC_STATUS_CHANGED 635 ), 636 .merchant_pub = kc->mi->merchant_pub, 637 .h_wire = kc->h_wire 638 }; 639 640 kc->eh = TALER_MERCHANTDB_event_listen ( 641 TMH_db, 642 &ev.header, 643 GNUNET_TIME_absolute_get_remaining (kc->timeout), 644 &kyc_change_cb, 645 kc); 646 } 647 else 648 { 649 struct TALER_MERCHANTDB_InstanceKycStatusChangeEventP hdr = { 650 .header.size = htons (sizeof (hdr)), 651 .header.type = htons (TALER_DBEVENT_MERCHANT_KYC_STATUS_CHANGED), 652 .merchant_pub = kc->mi->merchant_pub 653 }; 654 655 kc->eh = TALER_MERCHANTDB_event_listen ( 656 TMH_db, 657 &hdr.header, 658 GNUNET_TIME_absolute_get_remaining (kc->timeout), 659 &kyc_change_cb, 660 kc); 661 } 662 kc->phase++; 663 } 664 665 666 /* ***************** phase_database_kyc_check ************** */ 667 668 669 /** 670 * Maps @a ekr to a status code for clients to interpret the 671 * overall result. 672 * 673 * @param ekr request summary 674 * @return status of the KYC state as a string 675 */ 676 static const char * 677 map_to_status (const struct ExchangeKycRequest *ekr) 678 { 679 if (ekr->no_keys) 680 { 681 return "no-exchange-keys"; 682 } 683 if (TALER_EC_MERCHANT_PRIVATE_ACCOUNT_NOT_ELIGIBLE_FOR_EXCHANGE == 684 ekr->last_ec) 685 return "unsupported-account"; 686 if (ekr->kyc_ok) 687 { 688 if (NULL != ekr->jlimits) 689 { 690 size_t off; 691 json_t *limit; 692 json_array_foreach (ekr->jlimits, off, limit) 693 { 694 struct TALER_Amount threshold; 695 enum TALER_KYCLOGIC_KycTriggerEvent operation_type; 696 bool soft = false; 697 struct GNUNET_JSON_Specification spec[] = { 698 TALER_JSON_spec_kycte ("operation_type", 699 &operation_type), 700 TALER_JSON_spec_amount_any ("threshold", 701 &threshold), 702 GNUNET_JSON_spec_mark_optional ( 703 GNUNET_JSON_spec_bool ("soft_limit", 704 &soft), 705 NULL), 706 GNUNET_JSON_spec_end () 707 }; 708 709 if (GNUNET_OK != 710 GNUNET_JSON_parse (limit, 711 spec, 712 NULL, NULL)) 713 { 714 GNUNET_break (0); 715 return "merchant-internal-error"; 716 } 717 if (! TALER_amount_is_zero (&threshold)) 718 continue; /* only care about zero-limits */ 719 if (! soft) 720 continue; /* only care about soft limits */ 721 if ( (operation_type == TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT) || 722 (operation_type == TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE) || 723 (operation_type == TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION) ) 724 { 725 if (! ekr->auth_ok) 726 { 727 if (ekr->kyc_auth_conflict) 728 return "kyc-wire-impossible"; 729 return "kyc-wire-required"; 730 } 731 return "kyc-required"; 732 } 733 } 734 } 735 if (NULL == ekr->jlimits) 736 { 737 /* check default limits */ 738 const struct TALER_EXCHANGE_Keys *keys = ekr->keys; 739 740 for (unsigned int i = 0; i < keys->zero_limits_length; i++) 741 { 742 enum TALER_KYCLOGIC_KycTriggerEvent operation_type 743 = keys->zero_limits[i].operation_type; 744 745 if ( (operation_type == TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT) || 746 (operation_type == TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE) || 747 (operation_type == TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION) ) 748 { 749 if (! ekr->auth_ok) 750 { 751 if (ekr->kyc_auth_conflict) 752 return "kyc-wire-impossible"; 753 return "kyc-wire-required"; 754 } 755 return "kyc-required"; 756 } 757 } 758 } 759 return "ready"; 760 } 761 if (! ekr->auth_ok) 762 { 763 if (ekr->kyc_auth_conflict) 764 return "kyc-wire-impossible"; 765 return "kyc-wire-required"; 766 } 767 if (ekr->in_aml_review) 768 return "awaiting-aml-review"; 769 switch (ekr->last_http_status) 770 { 771 case 0: 772 return "exchange-unreachable"; 773 case MHD_HTTP_OK: 774 /* then we should have kyc_ok */ 775 GNUNET_break (0); 776 return NULL; 777 case MHD_HTTP_ACCEPTED: 778 /* Then KYC is really what is needed */ 779 return "kyc-required"; 780 case MHD_HTTP_NO_CONTENT: 781 /* then we should have had kyc_ok! */ 782 GNUNET_break (0); 783 return NULL; 784 case MHD_HTTP_FORBIDDEN: 785 /* then we should have had ! auth_ok */ 786 GNUNET_break (0); 787 return NULL; 788 case MHD_HTTP_NOT_FOUND: 789 /* then we should have had ! auth_ok */ 790 GNUNET_break (0); 791 return NULL; 792 case MHD_HTTP_CONFLICT: 793 /* then we should have had ! auth_ok */ 794 GNUNET_break (0); 795 return NULL; 796 case MHD_HTTP_INTERNAL_SERVER_ERROR: 797 return "exchange-internal-error"; 798 case MHD_HTTP_GATEWAY_TIMEOUT: 799 return "exchange-gateway-timeout"; 800 default: 801 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 802 "Exchange responded with unexpected HTTP status %u to /kyc-check request!\n", 803 ekr->last_http_status); 804 break; 805 } 806 return "exchange-status-invalid"; 807 } 808 809 810 /** 811 * We have found an exchange in status @a status. Clear any 812 * long-pollers that wait for us having (or not having) this 813 * status. 814 * 815 * @param[in,out] kc context 816 * @param status the status we encountered 817 */ 818 static void 819 clear_status (struct KycContext *kc, 820 const char *status) 821 { 822 if ( (NULL != kc->lp_status) && 823 (0 == strcmp (kc->lp_status, 824 status)) ) 825 kc->lp_status = NULL; /* satisfied! */ 826 if ( (NULL != kc->lp_not_status) && 827 (0 != strcmp (kc->lp_not_status, 828 status) ) ) 829 kc->lp_not_status = NULL; /* satisfied! */ 830 } 831 832 833 /** 834 * Pack the given @a limit into the JSON @a limits array. 835 * 836 * @param kc overall request context 837 * @param limit account limit to pack 838 * @param[in,out] limits JSON array to extend 839 */ 840 static void 841 pack_limit (const struct KycContext *kc, 842 const struct TALER_EXCHANGE_AccountLimit *limit, 843 json_t *limits) 844 { 845 json_t *jl; 846 847 jl = GNUNET_JSON_PACK ( 848 TALER_JSON_pack_kycte ("operation_type", 849 limit->operation_type), 850 (POF_TEXT == kc->format) 851 ? GNUNET_JSON_pack_string ("interval", 852 GNUNET_TIME_relative2s (limit->timeframe, 853 true)) 854 : GNUNET_JSON_pack_time_rel ("timeframe", 855 limit->timeframe), 856 TALER_JSON_pack_amount ("threshold", 857 &limit->threshold), 858 GNUNET_JSON_pack_bool ("soft_limit", 859 limit->soft_limit) 860 ); 861 GNUNET_assert (0 == 862 json_array_append_new (limits, 863 jl)); 864 } 865 866 867 /** 868 * Return JSON array with AccountLimit objects giving 869 * the current limits for this exchange. 870 * 871 * @param[in,out] ekr overall request context 872 */ 873 static json_t * 874 get_exchange_limits ( 875 struct ExchangeKycRequest *ekr) 876 { 877 const struct TALER_EXCHANGE_Keys *keys = ekr->keys; 878 json_t *limits; 879 880 if (NULL != ekr->jlimits) 881 { 882 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 883 "Returning custom KYC limits\n"); 884 return json_incref (ekr->jlimits); 885 } 886 if (NULL == keys) 887 { 888 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 889 "No keys, thus no default KYC limits known\n"); 890 return NULL; 891 } 892 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 893 "Returning default KYC limits (%u/%u)\n", 894 keys->hard_limits_length, 895 keys->zero_limits_length); 896 limits = json_array (); 897 GNUNET_assert (NULL != limits); 898 for (unsigned int i = 0; i<keys->hard_limits_length; i++) 899 { 900 const struct TALER_EXCHANGE_AccountLimit *limit 901 = &keys->hard_limits[i]; 902 903 pack_limit (ekr->kc, 904 limit, 905 limits); 906 } 907 for (unsigned int i = 0; i<keys->zero_limits_length; i++) 908 { 909 const struct TALER_EXCHANGE_ZeroLimitedOperation *zlimit 910 = &keys->zero_limits[i]; 911 json_t *jl; 912 struct TALER_Amount zero; 913 914 GNUNET_assert (GNUNET_OK == 915 TALER_amount_set_zero (keys->currency, 916 &zero)); 917 jl = GNUNET_JSON_PACK ( 918 TALER_JSON_pack_kycte ("operation_type", 919 zlimit->operation_type), 920 GNUNET_JSON_pack_bool ( 921 "disallowed", 922 true), 923 (POF_TEXT == ekr->kc->format) 924 ? GNUNET_JSON_pack_string ( 925 "interval", 926 GNUNET_TIME_relative2s (GNUNET_TIME_UNIT_ZERO, 927 true)) 928 : GNUNET_JSON_pack_time_rel ("timeframe", 929 GNUNET_TIME_UNIT_ZERO), 930 TALER_JSON_pack_amount ("threshold", 931 &zero), 932 GNUNET_JSON_pack_bool ("soft_limit", 933 true) 934 ); 935 GNUNET_assert (0 == 936 json_array_append_new (limits, 937 jl)); 938 } 939 return limits; 940 } 941 942 943 /** 944 * Take data from @a ekr to expand our response. 945 * 946 * @param ekr exchange we are done inspecting 947 */ 948 static void 949 ekr_expand_response (struct ExchangeKycRequest *ekr) 950 { 951 const struct KycContext *kc = ekr->kc; 952 struct TMH_Exchange *e = TMH_EXCHANGES_lookup_exchange (ekr->exchange_url); 953 const char *status; 954 const char *q; 955 char *short_account; 956 bool kyc_swap_tos_acceptance = false; 957 char *tos_accepted_early = NULL; 958 959 GNUNET_assert (NULL != e); 960 status = map_to_status (ekr); 961 if (NULL == status) 962 { 963 GNUNET_break (0); 964 status = "logic-bug"; 965 } 966 clear_status (ekr->kc, 967 status); 968 q = strchr (ekr->payto_uri.full_payto, 969 '?'); 970 if (NULL == q) 971 short_account = GNUNET_strdup (ekr->payto_uri.full_payto); 972 else 973 short_account = GNUNET_strndup (ekr->payto_uri.full_payto, 974 q - ekr->payto_uri.full_payto); 975 if (NULL != ekr->keys) 976 kyc_swap_tos_acceptance = ekr->keys->kyc_swap_tos_acceptance; 977 { 978 enum GNUNET_DB_QueryStatus qs; 979 980 qs = TALER_MERCHANTDB_set_instance ( 981 TMH_db, 982 kc->mi->settings.id); 983 if (0 >= qs) 984 { 985 GNUNET_break (0); 986 tos_accepted_early = NULL; 987 } 988 else 989 { 990 qs = TALER_MERCHANTDB_get_tos_accepted_early (TMH_db, 991 kc->mi->settings.id, 992 ekr->exchange_url, 993 &tos_accepted_early); 994 GNUNET_break (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == 995 TALER_MERCHANTDB_set_instance ( 996 TMH_db, 997 NULL)); 998 if (qs < 0) 999 { 1000 GNUNET_break (0); 1001 /* fall through with tos_accepted_early == NULL */ 1002 tos_accepted_early = NULL; 1003 } 1004 } 1005 } 1006 GNUNET_assert ( 1007 0 == 1008 json_array_append_new ( 1009 ekr->kc->kycs_data, 1010 GNUNET_JSON_PACK ( 1011 (POF_TEXT == kc->format) 1012 ? GNUNET_JSON_pack_string ( 1013 "short_payto_uri", 1014 short_account) 1015 : TALER_JSON_pack_full_payto ( 1016 "payto_uri", 1017 ekr->payto_uri), 1018 GNUNET_JSON_pack_data_auto ( 1019 "h_wire", 1020 &ekr->h_wire), 1021 GNUNET_JSON_pack_string ( 1022 "status", 1023 status), 1024 GNUNET_JSON_pack_string ( 1025 "exchange_url", 1026 ekr->exchange_url), 1027 GNUNET_JSON_pack_string ( 1028 "exchange_currency", 1029 TMH_EXCHANGES_get_currency (e)), 1030 GNUNET_JSON_pack_bool ("no_keys", 1031 ekr->no_keys), 1032 GNUNET_JSON_pack_bool ("auth_conflict", 1033 ekr->kyc_auth_conflict), 1034 GNUNET_JSON_pack_bool ("kyc_swap_tos_acceptance", 1035 kyc_swap_tos_acceptance), 1036 GNUNET_JSON_pack_allow_null ( 1037 GNUNET_JSON_pack_string ( 1038 "tos_accepted_early", 1039 tos_accepted_early)), 1040 GNUNET_JSON_pack_uint64 ("exchange_http_status", 1041 ekr->last_http_status), 1042 GNUNET_JSON_pack_conditional ( 1043 TALER_EC_NONE != ekr->last_ec, 1044 GNUNET_JSON_pack_uint64 ("exchange_code", 1045 ekr->last_ec)), 1046 GNUNET_JSON_pack_conditional ( 1047 ekr->auth_ok, 1048 GNUNET_JSON_pack_data_auto ( 1049 "access_token", 1050 &ekr->access_token)), 1051 GNUNET_JSON_pack_allow_null ( 1052 GNUNET_JSON_pack_array_steal ( 1053 "limits", 1054 get_exchange_limits (ekr))), 1055 GNUNET_JSON_pack_allow_null ( 1056 GNUNET_JSON_pack_array_incref ("payto_kycauths", 1057 ekr->pkaa)) 1058 ))); 1059 GNUNET_free (tos_accepted_early); 1060 GNUNET_free (short_account); 1061 } 1062 1063 1064 /** 1065 * We are done with the KYC request @a ekr. Remove it from the work list and 1066 * check if we are done overall. 1067 * 1068 * @param[in] ekr key request that is done (and will be freed) 1069 */ 1070 static void 1071 ekr_finished (struct ExchangeKycRequest *ekr) 1072 { 1073 struct KycContext *kc = ekr->kc; 1074 1075 ekr_expand_response (ekr); 1076 ekr_cleanup (ekr); 1077 if (NULL != kc->exchange_pending_head) 1078 return; /* wait for more */ 1079 if (kc->in_db) 1080 return; 1081 GNUNET_assert (GNUNET_YES == kc->suspended); 1082 kc->phase = PHASE_GENERATE_RESPONSE; 1083 kc->suspended = GNUNET_NO; 1084 MHD_resume_connection (kc->connection); 1085 TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */ 1086 } 1087 1088 1089 /** 1090 * Figure out which exchange accounts from @a keys could 1091 * be used for a KYC auth wire transfer from the account 1092 * that @a ekr is checking. Will set the "pkaa" array 1093 * in @a ekr. 1094 * 1095 * @param[in,out] ekr request we are processing 1096 */ 1097 static void 1098 determine_eligible_accounts ( 1099 struct ExchangeKycRequest *ekr) 1100 { 1101 struct KycContext *kc = ekr->kc; 1102 const struct TALER_EXCHANGE_Keys *keys = ekr->keys; 1103 struct TALER_Amount kyc_amount; 1104 char *merchant_pub_str; 1105 struct TALER_NormalizedPayto np; 1106 1107 { 1108 const struct TALER_EXCHANGE_GlobalFee *gf; 1109 1110 gf = TALER_EXCHANGE_get_global_fee (keys, 1111 GNUNET_TIME_timestamp_get ()); 1112 if (NULL == gf) 1113 { 1114 GNUNET_assert (GNUNET_OK == 1115 TALER_amount_set_zero (keys->currency, 1116 &kyc_amount)); 1117 } 1118 else 1119 { 1120 /* FIXME-#9427: history fee should be globally renamed to KYC fee... */ 1121 kyc_amount = gf->fees.history; 1122 } 1123 } 1124 1125 merchant_pub_str 1126 = GNUNET_STRINGS_data_to_string_alloc ( 1127 &kc->mi->merchant_pub, 1128 sizeof (kc->mi->merchant_pub)); 1129 /* For all accounts of the exchange */ 1130 np = TALER_payto_normalize (ekr->payto_uri); 1131 for (unsigned int i = 0; i<keys->accounts_len; i++) 1132 { 1133 const struct TALER_EXCHANGE_WireAccount *account 1134 = &keys->accounts[i]; 1135 1136 /* KYC auth transfers are never supported with conversion */ 1137 if (NULL != account->conversion_url) 1138 continue; 1139 /* filter by source account by credit_restrictions */ 1140 if (GNUNET_YES != 1141 TALER_EXCHANGE_test_account_allowed (account, 1142 true, /* credit */ 1143 np)) 1144 continue; 1145 /* exchange account is allowed, add it */ 1146 // FIXME: #11520: support short wire transfer subjects! 1147 // if (NULL != account->prepared_transfer_url) // ... 1148 { 1149 const char *exchange_account_payto 1150 = account->fpayto_uri.full_payto; 1151 char *payto_kycauth; 1152 1153 if (TALER_amount_is_zero (&kyc_amount)) 1154 GNUNET_asprintf (&payto_kycauth, 1155 "%s%cmessage=KYC:%s", 1156 exchange_account_payto, 1157 (NULL == strchr (exchange_account_payto, 1158 '?')) 1159 ? '?' 1160 : '&', 1161 merchant_pub_str); 1162 else 1163 GNUNET_asprintf (&payto_kycauth, 1164 "%s%camount=%s&message=KYC:%s", 1165 exchange_account_payto, 1166 (NULL == strchr (exchange_account_payto, 1167 '?')) 1168 ? '?' 1169 : '&', 1170 TALER_amount2s (&kyc_amount), 1171 merchant_pub_str); 1172 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1173 "Found account %s where KYC auth is possible\n", 1174 payto_kycauth); 1175 GNUNET_assert (0 == 1176 json_array_append_new (ekr->pkaa, 1177 json_string (payto_kycauth))); 1178 GNUNET_free (payto_kycauth); 1179 } 1180 } 1181 GNUNET_free (np.normalized_payto); 1182 GNUNET_free (merchant_pub_str); 1183 } 1184 1185 1186 /** 1187 * Function called with the result of a #TMH_EXCHANGES_keys4exchange() 1188 * operation. Runs the KYC check against the exchange. 1189 * 1190 * @param cls closure with our `struct ExchangeKycRequest *` 1191 * @param keys keys of the exchange context 1192 * @param exchange representation of the exchange 1193 */ 1194 static void 1195 kyc_with_exchange (void *cls, 1196 struct TALER_EXCHANGE_Keys *keys, 1197 struct TMH_Exchange *exchange) 1198 { 1199 struct ExchangeKycRequest *ekr = cls; 1200 1201 (void) exchange; 1202 ekr->fo = NULL; 1203 if (NULL == keys) 1204 { 1205 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1206 "Failed to download `%skeys`\n", 1207 ekr->exchange_url); 1208 ekr->no_keys = true; 1209 ekr_finished (ekr); 1210 return; 1211 } 1212 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1213 "Got /keys for `%s'\n", 1214 ekr->exchange_url); 1215 ekr->keys = TALER_EXCHANGE_keys_incref (keys); 1216 if (! ekr->auth_ok) 1217 { 1218 ekr->pkaa = json_array (); 1219 GNUNET_assert (NULL != ekr->pkaa); 1220 determine_eligible_accounts (ekr); 1221 if (0 == json_array_size (ekr->pkaa)) 1222 { 1223 /* No KYC auth wire transfers are possible to this exchange from 1224 our merchant bank account, so we cannot use this account with 1225 this exchange if it has any KYC requirements! */ 1226 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1227 "KYC auth to `%s' impossible for merchant account `%s'\n", 1228 ekr->exchange_url, 1229 ekr->payto_uri.full_payto); 1230 ekr->kyc_auth_conflict = true; 1231 } 1232 } 1233 ekr_finished (ekr); 1234 } 1235 1236 1237 /** 1238 * Closure for add_unreachable_status(). 1239 */ 1240 struct UnreachableContext 1241 { 1242 /** 1243 * Where we are building the response. 1244 */ 1245 struct KycContext *kc; 1246 1247 /** 1248 * Pointer to our account hash. 1249 */ 1250 const struct TALER_MerchantWireHashP *h_wire; 1251 1252 /** 1253 * Bank account for which we have no status from any exchange. 1254 */ 1255 struct TALER_FullPayto payto_uri; 1256 1257 }; 1258 1259 1260 /** 1261 * Add all trusted exchanges with "unknown" status for the 1262 * bank account given in the context. 1263 * 1264 * @param cls a `struct UnreachableContext` 1265 * @param url base URL of the exchange 1266 * @param exchange internal handle for the exchange 1267 */ 1268 static void 1269 add_unreachable_status (void *cls, 1270 const char *url, 1271 const struct TMH_Exchange *exchange) 1272 { 1273 struct UnreachableContext *uc = cls; 1274 struct KycContext *kc = uc->kc; 1275 1276 clear_status (kc, 1277 "exchange-unreachable"); 1278 GNUNET_assert ( 1279 0 == 1280 json_array_append_new ( 1281 kc->kycs_data, 1282 GNUNET_JSON_PACK ( 1283 TALER_JSON_pack_full_payto ( 1284 "payto_uri", 1285 uc->payto_uri), 1286 GNUNET_JSON_pack_data_auto ( 1287 "h_wire", 1288 uc->h_wire), 1289 GNUNET_JSON_pack_string ( 1290 "exchange_currency", 1291 TMH_EXCHANGES_get_currency (exchange)), 1292 GNUNET_JSON_pack_string ( 1293 "status", 1294 "exchange-unreachable"), 1295 GNUNET_JSON_pack_string ( 1296 "exchange_url", 1297 url), 1298 GNUNET_JSON_pack_bool ("no_keys", 1299 true), 1300 GNUNET_JSON_pack_bool ("auth_conflict", 1301 false), 1302 GNUNET_JSON_pack_uint64 ("exchange_http_status", 1303 0) 1304 ))); 1305 1306 } 1307 1308 1309 /** 1310 * Function called from iterate_kyc_statuses() with KYC status information 1311 * for this merchant. 1312 * 1313 * @param cls our `struct KycContext *` 1314 * @param h_wire hash of the wire account 1315 * @param payto_uri payto:// URI of the merchant's bank account 1316 * @param exchange_url base URL of the exchange for which this is a status 1317 * @param last_check when did we last get an update on our KYC status from the exchange 1318 * @param kyc_ok true if we satisfied the KYC requirements 1319 * @param access_token access token for the KYC SPA, NULL if we cannot access it yet (need KYC auth wire transfer) 1320 * @param last_http_status last HTTP status from /kyc-check 1321 * @param last_ec last Taler error code from /kyc-check 1322 * @param in_aml_review true if the account is pending review 1323 * @param jlimits JSON array of applicable AccountLimits, or NULL if unknown (like defaults apply) 1324 */ 1325 static void 1326 kyc_status_cb ( 1327 void *cls, 1328 const struct TALER_MerchantWireHashP *h_wire, 1329 struct TALER_FullPayto payto_uri, 1330 const char *exchange_url, 1331 struct GNUNET_TIME_Timestamp last_check, 1332 bool kyc_ok, 1333 const struct TALER_AccountAccessTokenP *access_token, 1334 unsigned int last_http_status, 1335 enum TALER_ErrorCode last_ec, 1336 bool in_aml_review, 1337 const json_t *jlimits) 1338 { 1339 struct KycContext *kc = cls; 1340 struct ExchangeKycRequest *ekr; 1341 1342 if (NULL == exchange_url) 1343 { 1344 struct UnreachableContext uc = { 1345 .kc = kc, 1346 .h_wire = h_wire, 1347 .payto_uri = payto_uri 1348 }; 1349 1350 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1351 "Account has unknown KYC status for all exchanges.\n"); 1352 TMH_exchange_get_trusted (&add_unreachable_status, 1353 &uc); 1354 return; 1355 } 1356 if (! TMH_EXCHANGES_check_trusted (exchange_url)) 1357 { 1358 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1359 "Skipping exchange `%s': not trusted\n", 1360 exchange_url); 1361 return; 1362 } 1363 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1364 "KYC status for `%s' at `%s' is %u/%s/%s/%s\n", 1365 payto_uri.full_payto, 1366 exchange_url, 1367 last_http_status, 1368 kyc_ok ? "KYC OK" : "KYC NEEDED", 1369 in_aml_review ? "IN AML REVIEW" : "NO AML REVIEW", 1370 NULL == jlimits ? "DEFAULT LIMITS" : "CUSTOM LIMITS"); 1371 switch (kc->lpt) 1372 { 1373 case TALER_EXCHANGE_KLPT_NONE: 1374 break; 1375 case TALER_EXCHANGE_KLPT_KYC_AUTH_TRANSFER: 1376 if (NULL != access_token) 1377 kc->return_immediately = true; 1378 break; 1379 case TALER_EXCHANGE_KLPT_INVESTIGATION_DONE: 1380 if (! in_aml_review) 1381 kc->return_immediately = true; 1382 break; 1383 case TALER_EXCHANGE_KLPT_KYC_OK: 1384 if (kyc_ok) 1385 kc->return_immediately = true; 1386 break; 1387 } 1388 ekr = GNUNET_new (struct ExchangeKycRequest); 1389 GNUNET_CONTAINER_DLL_insert (kc->exchange_pending_head, 1390 kc->exchange_pending_tail, 1391 ekr); 1392 ekr->last_http_status = last_http_status; 1393 ekr->last_ec = last_ec; 1394 if (NULL != jlimits) 1395 ekr->jlimits = json_incref ((json_t *) jlimits); 1396 ekr->h_wire = *h_wire; 1397 ekr->exchange_url = GNUNET_strdup (exchange_url); 1398 ekr->payto_uri.full_payto 1399 = GNUNET_strdup (payto_uri.full_payto); 1400 ekr->last_check = last_check; 1401 ekr->kyc_ok = kyc_ok; 1402 ekr->kc = kc; 1403 ekr->in_aml_review = in_aml_review; 1404 ekr->auth_ok = (NULL != access_token); 1405 if ( (! ekr->auth_ok) || 1406 (NULL == ekr->jlimits) ) 1407 { 1408 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1409 "Awaiting /keys from `%s'\n", 1410 exchange_url); 1411 /* Figure out wire transfer instructions */ 1412 ekr->fo = TMH_EXCHANGES_keys4exchange ( 1413 exchange_url, 1414 false, 1415 &kyc_with_exchange, 1416 ekr); 1417 if (NULL == ekr->fo) 1418 { 1419 GNUNET_break (0); 1420 ekr_finished (ekr); 1421 return; 1422 } 1423 return; 1424 } 1425 ekr->access_token = *access_token; 1426 ekr_finished (ekr); 1427 } 1428 1429 1430 /** 1431 * Check our database for the KYC status. Determines if we then 1432 * need to wait on exchange data or have no exchange and can 1433 * immediately proceed to return 204. 1434 * 1435 * @param[in,out] kc connection we are handling 1436 */ 1437 static void 1438 phase_database_kyc_check (struct KycContext *kc) 1439 { 1440 enum GNUNET_DB_QueryStatus qs; 1441 1442 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1443 "Checking KYC status for %s (%d/%s)\n", 1444 kc->mi->settings.id, 1445 kc->have_h_wire, 1446 kc->exchange_url); 1447 /* We may run repeatedly due to long-polling; clear data 1448 from previous runs first */ 1449 GNUNET_break (0 == 1450 json_array_clear (kc->kycs_data)); 1451 kc->in_db = true; 1452 qs = TALER_MERCHANTDB_iterate_kyc_statuses ( 1453 TMH_db, 1454 kc->mi->settings.id, 1455 kc->have_h_wire 1456 ? &kc->h_wire 1457 : NULL, 1458 kc->exchange_url, 1459 ! kc->refresh_requested, 1460 &kyc_status_cb, 1461 kc); 1462 kc->in_db = false; 1463 if (qs >= 0) 1464 kc->refresh_requested = true; 1465 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1466 "iterate_kyc_statuses returned %d records\n", 1467 (int) qs); 1468 switch (qs) 1469 { 1470 case GNUNET_DB_STATUS_HARD_ERROR: 1471 case GNUNET_DB_STATUS_SOFT_ERROR: 1472 /* Database error */ 1473 GNUNET_break (0); 1474 finish_request (kc, 1475 TALER_MHD_reply_with_ec ( 1476 kc->connection, 1477 TALER_EC_GENERIC_DB_FETCH_FAILED, 1478 "iterate_kyc_statuses")); 1479 return; 1480 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 1481 kc->phase = PHASE_NO_ACCOUNTS; 1482 return; 1483 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 1484 /* Handled below */ 1485 break; 1486 } 1487 if (NULL == kc->exchange_pending_head) 1488 { 1489 kc->phase = PHASE_GENERATE_RESPONSE; 1490 return; 1491 } 1492 MHD_suspend_connection (kc->connection); 1493 kc->suspended = GNUNET_YES; 1494 kc->phase = PHASE_SUSPENDED_ON_EXCHANGE; 1495 } 1496 1497 1498 /* ********************* phase_no_accounts *********** */ 1499 1500 /** 1501 * We have no accounts, return a 204 No content, 1502 * or suspend if long-polling. 1503 * 1504 * @param[in,out] kc connection we are handling 1505 */ 1506 static void 1507 phase_no_accounts (struct KycContext *kc) 1508 { 1509 /* We use an Etag of all zeros for the 204 status code */ 1510 static struct GNUNET_ShortHashCode zero_etag; 1511 struct MHD_Response *response; 1512 1513 /* no matching accounts, could not have suspended */ 1514 GNUNET_assert (GNUNET_NO == kc->suspended); 1515 if (kc->have_lp_not_etag && 1516 (0 == GNUNET_memcmp (&zero_etag, 1517 &kc->lp_not_etag)) && 1518 (! GNUNET_TIME_absolute_is_past (kc->timeout)) ) 1519 { 1520 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1521 "No matching accounts, suspending to wait for this to change\n"); 1522 MHD_suspend_connection (kc->connection); 1523 kc->suspended = GNUNET_YES; 1524 kc->phase = PHASE_SUSPENDED_ON_ACCOUNT; 1525 return; 1526 } 1527 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1528 "No matching accounts, returning empty response\n"); 1529 response = MHD_create_response_from_buffer_static (0, 1530 NULL); 1531 TALER_MHD_add_global_headers (response, 1532 false); 1533 { 1534 char *etag; 1535 1536 etag = GNUNET_STRINGS_data_to_string_alloc (&zero_etag, 1537 sizeof (zero_etag)); 1538 GNUNET_break (MHD_YES == 1539 MHD_add_response_header (response, 1540 MHD_HTTP_HEADER_ETAG, 1541 etag)); 1542 GNUNET_free (etag); 1543 } 1544 finish_request (kc, 1545 MHD_queue_response (kc->connection, 1546 MHD_HTTP_NO_CONTENT, 1547 response)); 1548 MHD_destroy_response (response); 1549 } 1550 1551 1552 /* ********************* phase_generate_response *********** */ 1553 1554 /** 1555 * Resume the given KYC context and send the final response. Stores the 1556 * response in the @a kc and signals MHD to resume the connection. Also 1557 * ensures MHD runs immediately. 1558 * 1559 * @param kc KYC context 1560 */ 1561 static void 1562 resume_kyc_with_response (struct KycContext *kc) 1563 { 1564 struct GNUNET_ShortHashCode sh; 1565 bool not_modified; 1566 char *can; 1567 unsigned int response_code; 1568 struct MHD_Response *response; 1569 1570 /* The database returns KYC records in a stable order, but entries that 1571 require exchange /keys data are appended when their asynchronous lookup 1572 finishes. Sort only after all lookups are done so callback timing and 1573 synthetic exchange-unreachable entries cannot affect the response or its 1574 ETag. */ 1575 TMH_kyc_data_sort (kc->kycs_data); 1576 can = TALER_JSON_canonicalize (kc->kycs_data); 1577 GNUNET_assert (GNUNET_YES == 1578 GNUNET_CRYPTO_hkdf_gnunet (&sh, 1579 sizeof (sh), 1580 "KYC-SALT", 1581 strlen ("KYC-SALT"), 1582 can, 1583 strlen (can))); 1584 not_modified = kc->have_lp_not_etag && 1585 (0 == GNUNET_memcmp (&sh, 1586 &kc->lp_not_etag)); 1587 if (not_modified && 1588 (! GNUNET_TIME_absolute_is_past (kc->timeout)) ) 1589 { 1590 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1591 "Status unchanged, not returning response yet\n"); 1592 wait_for_account (kc); 1593 GNUNET_free (can); 1594 return; 1595 } 1596 { 1597 const char *inm; 1598 1599 inm = MHD_lookup_connection_value (kc->connection, 1600 MHD_HEADER_KIND, 1601 MHD_HTTP_HEADER_IF_NONE_MATCH); 1602 if ( (NULL == inm) || 1603 ('"' != inm[0]) || 1604 ('"' != inm[strlen (inm) - 1]) || 1605 (0 != strncmp (inm + 1, 1606 can, 1607 strlen (can))) ) 1608 not_modified = false; /* must return full response */ 1609 } 1610 GNUNET_free (can); 1611 response_code = not_modified 1612 ? MHD_HTTP_NOT_MODIFIED 1613 : MHD_HTTP_OK; 1614 switch (kc->format) 1615 { 1616 case POF_JSON: 1617 response = TALER_MHD_MAKE_JSON_PACK ( 1618 GNUNET_JSON_pack_array_incref ("kyc_data", 1619 kc->kycs_data)); 1620 break; 1621 case POF_TEXT: 1622 { 1623 enum GNUNET_GenericReturnValue ret; 1624 json_t *obj; 1625 1626 obj = GNUNET_JSON_PACK ( 1627 GNUNET_JSON_pack_array_incref ("kyc_data", 1628 kc->kycs_data)); 1629 ret = TALER_TEMPLATING_build (kc->connection, 1630 &response_code, 1631 "kyc_text", 1632 kc->mi->settings.id, 1633 NULL, 1634 obj, 1635 &response); 1636 json_decref (obj); 1637 switch (ret) 1638 { 1639 case GNUNET_SYSERR: 1640 /* failed to even produce a response */ 1641 GNUNET_break (0); 1642 kc->phase = PHASE_RETURN_NO; 1643 return; 1644 case GNUNET_NO: 1645 finish_request (kc, 1646 MHD_queue_response ( 1647 kc->connection, 1648 response_code, 1649 response)); 1650 MHD_destroy_response (response); 1651 return; 1652 case GNUNET_OK: 1653 TALER_MHD_add_global_headers (response, 1654 false); 1655 GNUNET_break (MHD_YES == 1656 MHD_add_response_header (response, 1657 MHD_HTTP_HEADER_CONTENT_TYPE, 1658 "text/plain")); 1659 break; 1660 } /* switch (ret) */ 1661 } 1662 break; 1663 case POF_PDF: 1664 // not yet implemented 1665 GNUNET_assert (0); 1666 break; 1667 } 1668 { 1669 char *etag; 1670 char *qetag; 1671 1672 etag = GNUNET_STRINGS_data_to_string_alloc (&sh, 1673 sizeof (sh)); 1674 GNUNET_asprintf (&qetag, 1675 "\"%s\"", 1676 etag); 1677 GNUNET_break (MHD_YES == 1678 MHD_add_response_header (response, 1679 MHD_HTTP_HEADER_ETAG, 1680 qetag)); 1681 GNUNET_free (qetag); 1682 GNUNET_free (etag); 1683 } 1684 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1685 "Resuming /kyc handling as exchange interaction is done (%u)\n", 1686 MHD_HTTP_OK); 1687 finish_request (kc, 1688 MHD_queue_response ( 1689 kc->connection, 1690 response_code, 1691 response)); 1692 MHD_destroy_response (response); 1693 } 1694 1695 1696 /** 1697 * We are done with asynchronous processing, generate the 1698 * response for the @e kc. 1699 * 1700 * @param[in,out] kc KYC context to respond for 1701 */ 1702 static void 1703 phase_generate_response (struct KycContext *kc) 1704 { 1705 GNUNET_assert (NULL == kc->exchange_pending_head); 1706 GNUNET_assert (GNUNET_NO == kc->suspended); 1707 /* FIXME: mixing these two suspend conditions like this 1708 does not seem sane */ 1709 if ( (! kc->return_immediately) && 1710 (! GNUNET_TIME_absolute_is_past (kc->timeout)) ) 1711 { 1712 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1713 "Suspending: long poll target %d not reached\n", 1714 kc->lpt); 1715 wait_for_account (kc); 1716 return; 1717 } 1718 if ( (! GNUNET_TIME_absolute_is_past (kc->timeout)) && 1719 ( (NULL != kc->lp_not_status) || 1720 (NULL != kc->lp_status) ) ) 1721 { 1722 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1723 "Long-poll target status not reached, not returning response yet\n"); 1724 wait_for_account (kc); 1725 return; 1726 } 1727 /* All exchange requests done, create final 1728 big response from cumulated replies */ 1729 resume_kyc_with_response (kc); 1730 } 1731 1732 1733 /* ******************* main logic ***************** */ 1734 1735 /** 1736 * Check the KYC status of an instance. 1737 * 1738 * @param mi instance to check KYC status of 1739 * @param connection the MHD connection to handle 1740 * @param[in,out] hc context with further information about the request 1741 * @return MHD result code 1742 */ 1743 static enum MHD_Result 1744 get_instances_ID_kyc ( 1745 struct TMH_MerchantInstance *mi, 1746 struct MHD_Connection *connection, 1747 struct TMH_HandlerContext *hc) 1748 { 1749 struct KycContext *kc = hc->ctx; 1750 1751 if (NULL == kc) 1752 { 1753 kc = GNUNET_new (struct KycContext); 1754 kc->mi = mi; 1755 hc->ctx = kc; 1756 hc->cc = &kyc_context_cleanup; 1757 GNUNET_CONTAINER_DLL_insert (kc_head, 1758 kc_tail, 1759 kc); 1760 kc->connection = connection; 1761 kc->hc = hc; 1762 TALER_MHD_parse_request_timeout (connection, 1763 &kc->timeout); 1764 { 1765 uint64_t num = 0; 1766 int val; 1767 1768 TALER_MHD_parse_request_number (connection, 1769 "lpt", 1770 &num); 1771 val = (int) num; 1772 if ( (val < 0) || 1773 (val > TALER_EXCHANGE_KLPT_MAX) ) 1774 { 1775 /* Protocol violation, but we can be graceful and 1776 just ignore the long polling! */ 1777 GNUNET_break_op (0); 1778 val = TALER_EXCHANGE_KLPT_NONE; 1779 } 1780 kc->lpt = (enum TALER_EXCHANGE_KycLongPollTarget) val; 1781 } 1782 kc->return_immediately 1783 = (TALER_EXCHANGE_KLPT_NONE == kc->lpt); 1784 kc->lp_status = MHD_lookup_connection_value ( 1785 connection, 1786 MHD_GET_ARGUMENT_KIND, 1787 "lp_status"); 1788 kc->lp_not_status = MHD_lookup_connection_value ( 1789 connection, 1790 MHD_GET_ARGUMENT_KIND, 1791 "lp_not_status"); 1792 TALER_MHD_parse_request_arg_auto (connection, 1793 "h_wire", 1794 &kc->h_wire, 1795 kc->have_h_wire); 1796 TALER_MHD_parse_request_arg_auto (connection, 1797 "lp_not_etag", 1798 &kc->lp_not_etag, 1799 kc->have_lp_not_etag); 1800 } 1801 while (1) 1802 { 1803 switch (kc->phase) 1804 { 1805 case PHASE_INIT: 1806 phase_init (kc); 1807 break; 1808 case PHASE_DETERMINE_LONG_POLL: 1809 phase_determine_long_poll (kc); 1810 break; 1811 case PHASE_DATABASE_KYC_CHECK: 1812 phase_database_kyc_check (kc); 1813 break; 1814 case PHASE_NO_ACCOUNTS: 1815 phase_no_accounts (kc); 1816 break; 1817 case PHASE_GENERATE_RESPONSE: 1818 phase_generate_response (kc); 1819 break; 1820 case PHASE_IN_SHUTDOWN: 1821 /* during shutdown, we don't generate any more replies */ 1822 GNUNET_assert (GNUNET_SYSERR == kc->suspended); 1823 return MHD_NO; 1824 case PHASE_RETURN_YES: 1825 return MHD_YES; 1826 case PHASE_RETURN_NO: 1827 return MHD_NO; 1828 case PHASE_SUSPENDED_ON_ACCOUNT: 1829 /* suspended */ 1830 GNUNET_assert (GNUNET_YES == kc->suspended); 1831 return MHD_YES; 1832 case PHASE_SUSPENDED_ON_EXCHANGE: 1833 /* suspended */ 1834 GNUNET_assert (GNUNET_YES == kc->suspended); 1835 return MHD_YES; 1836 } 1837 } 1838 } 1839 1840 1841 enum MHD_Result 1842 TMH_private_get_instances_ID_kyc ( 1843 const struct TMH_RequestHandler *rh, 1844 struct MHD_Connection *connection, 1845 struct TMH_HandlerContext *hc) 1846 { 1847 struct TMH_MerchantInstance *mi = hc->instance; 1848 1849 (void) rh; 1850 return get_instances_ID_kyc (mi, 1851 connection, 1852 hc); 1853 } 1854 1855 1856 enum MHD_Result 1857 TMH_private_get_instances_default_ID_kyc ( 1858 const struct TMH_RequestHandler *rh, 1859 struct MHD_Connection *connection, 1860 struct TMH_HandlerContext *hc) 1861 { 1862 struct TMH_MerchantInstance *mi; 1863 1864 (void) rh; 1865 mi = TMH_lookup_instance (hc->infix); 1866 if (NULL == mi) 1867 { 1868 return TALER_MHD_reply_with_error ( 1869 connection, 1870 MHD_HTTP_NOT_FOUND, 1871 TALER_EC_MERCHANT_GENERIC_INSTANCE_UNKNOWN, 1872 hc->infix); 1873 } 1874 return get_instances_ID_kyc (mi, 1875 connection, 1876 hc); 1877 } 1878 1879 1880 /* end of taler-merchant-httpd_get-private-kyc.c */