taler-merchant-httpd_post-orders-ORDER_ID-pay.c (164148B)
1 /* 2 This file is part of TALER 3 (C) 2014-2026 Taler Systems SA 4 5 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 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_post-orders-ORDER_ID-pay.c 22 * @brief handling of POST /orders/$ID/pay requests 23 * @author Marcello Stanisci 24 * @author Christian Grothoff 25 * @author Florian Dold 26 */ 27 #include "taler/platform.h" 28 #include <gnunet/gnunet_common.h> 29 #include <gnunet/gnunet_db_lib.h> 30 #include <gnunet/gnunet_json_lib.h> 31 #include <gnunet/gnunet_time_lib.h> 32 #include <jansson.h> 33 #include <microhttpd.h> 34 #include <stddef.h> 35 #include <stdint.h> 36 #include <string.h> 37 #include <taler/taler_dbevents.h> 38 #include <taler/taler_error_codes.h> 39 #include <taler/taler_signatures.h> 40 #include <taler/taler_json_lib.h> 41 #include <taler/taler_exchange_service.h> 42 #include "taler-merchant-httpd.h" 43 #include "taler-merchant-httpd_exchanges.h" 44 #include "taler-merchant-httpd_get-exchanges.h" 45 #include "taler-merchant-httpd_helper.h" 46 #include "taler-merchant-httpd_post-orders-ORDER_ID-pay.h" 47 #include "taler-merchant-httpd_get-private-orders.h" 48 #include "taler/taler_merchant_util.h" 49 #include "taler/taler_merchantdb_plugin.h" 50 51 #ifdef HAVE_DONAU_DONAU_SERVICE_H 52 #include <donau/donau_service.h> 53 #include <donau/donau_util.h> 54 #include <donau/donau_json_lib.h> 55 #endif 56 57 /** 58 * How often do we retry the (complex!) database transaction? 59 */ 60 #define MAX_RETRIES 5 61 62 /** 63 * Maximum number of coins that we allow per transaction. 64 * Note that the limit for each batch deposit request to 65 * the exchange is lower, so we may break a very large 66 * number of coins up into multiple smaller requests to 67 * the exchange. 68 */ 69 #define MAX_COIN_ALLOWED_COINS 1024 70 71 /** 72 * Maximum number of tokens that we allow as inputs per transaction 73 */ 74 #define MAX_TOKEN_ALLOWED_INPUTS 64 75 76 /** 77 * Maximum number of tokens that we allow as outputs per transaction 78 */ 79 #define MAX_TOKEN_ALLOWED_OUTPUTS 64 80 81 /** 82 * How often do we ask the exchange again about our 83 * KYC status? Very rarely, as if the user actively 84 * changes it, we should usually notice anyway. 85 */ 86 #define KYC_RETRY_FREQUENCY GNUNET_TIME_UNIT_WEEKS 87 88 /** 89 * Information we keep for an individual call to the pay handler. 90 */ 91 struct PayContext; 92 93 94 /** 95 * Different phases of processing the /pay request. 96 */ 97 enum PayPhase 98 { 99 /** 100 * Initial phase where the request is parsed. 101 */ 102 PP_PARSE_PAY = 0, 103 104 /** 105 * Parse wallet data object from the pay request. 106 */ 107 PP_PARSE_WALLET_DATA, 108 109 /** 110 * Check database state for the given order. 111 */ 112 PP_CHECK_CONTRACT, 113 114 /** 115 * Validate provided tokens and token envelopes. 116 */ 117 PP_VALIDATE_TOKENS, 118 119 /** 120 * Check if contract has been paid. 121 */ 122 PP_CONTRACT_PAID, 123 124 /** 125 * Compute money pot changes. 126 */ 127 PP_COMPUTE_MONEY_POTS, 128 129 /** 130 * Execute payment transaction. 131 */ 132 PP_PAY_TRANSACTION, 133 134 /** 135 * Communicate with DONAU to generate a donation receipt from the donor BUDIs. 136 */ 137 PP_REQUEST_DONATION_RECEIPT, 138 139 /** 140 * Process the donation receipt response from DONAU (save the donau_sigs to the db). 141 */ 142 PP_FINAL_OUTPUT_TOKEN_PROCESSING, 143 144 /** 145 * Notify other processes about successful payment. 146 */ 147 PP_PAYMENT_NOTIFICATION, 148 149 /** 150 * Create final success response. 151 */ 152 PP_SUCCESS_RESPONSE, 153 154 /** 155 * Perform batch deposits with exchange(s). 156 */ 157 PP_BATCH_DEPOSITS, 158 159 /** 160 * Return response in payment context. 161 */ 162 PP_RETURN_RESPONSE, 163 164 /** 165 * An exchange denied a deposit, fail for 166 * legal reasons. 167 */ 168 PP_FAIL_LEGAL_REASONS, 169 170 /** 171 * Return #MHD_YES to end processing. 172 */ 173 PP_END_YES, 174 175 /** 176 * Return #MHD_NO to end processing. 177 */ 178 PP_END_NO 179 }; 180 181 182 /** 183 * Information kept during a pay request for each coin. 184 */ 185 struct DepositConfirmation 186 { 187 188 /** 189 * Reference to the main PayContext 190 */ 191 struct PayContext *pc; 192 193 /** 194 * URL of the exchange that issued this coin. 195 */ 196 char *exchange_url; 197 198 /** 199 * Details about the coin being deposited. 200 */ 201 struct TALER_EXCHANGE_CoinDepositDetail cdd; 202 203 /** 204 * Fee charged by the exchange for the deposit operation of this coin. 205 */ 206 struct TALER_Amount deposit_fee; 207 208 /** 209 * Fee charged by the exchange for the refund operation of this coin. 210 */ 211 struct TALER_Amount refund_fee; 212 213 /** 214 * If a minimum age was required (i. e. pc->minimum_age is large enough), 215 * this is the signature of the minimum age (as a single uint8_t), using the 216 * private key to the corresponding age group. Might be all zeroes for no 217 * age attestation. 218 */ 219 struct TALER_AgeAttestationP minimum_age_sig; 220 221 /** 222 * If a minimum age was required (i. e. pc->minimum_age is large enough), 223 * this is the age commitment (i. e. age mask and vector of EdDSA public 224 * keys, one per age group) that went into the mining of the coin. The 225 * SHA256 hash of the mask and the vector of public keys was bound to the 226 * key. 227 */ 228 struct TALER_AgeCommitment age_commitment; 229 230 /** 231 * Age mask in the denomination that defines the age groups. Only 232 * applicable, if minimum age was required. 233 */ 234 struct TALER_AgeMask age_mask; 235 236 /** 237 * Offset of this coin into the `dc` array of all coins in the 238 * @e pc. 239 */ 240 unsigned int index; 241 242 /** 243 * true, if no field "age_commitment" was found in the JSON blob 244 */ 245 bool no_age_commitment; 246 247 /** 248 * True, if no field "minimum_age_sig" was found in the JSON blob 249 */ 250 bool no_minimum_age_sig; 251 252 /** 253 * true, if no field "h_age_commitment" was found in the JSON blob 254 */ 255 bool no_h_age_commitment; 256 257 /** 258 * true if we found this coin in the database. 259 */ 260 bool found_in_db; 261 262 /** 263 * true if we #deposit_paid_check() matched this coin in the database. 264 */ 265 bool matched_in_db; 266 267 /** 268 * True if this coin is in the current batch. 269 */ 270 bool in_batch; 271 272 }; 273 274 struct TokenUseConfirmation 275 { 276 277 /** 278 * Signature on the deposit request made using the token use private key. 279 */ 280 struct TALER_TokenUseSignatureP sig; 281 282 /** 283 * Token use public key. This key was blindly signed by the merchant during 284 * the token issuance process. 285 */ 286 struct TALER_TokenUsePublicKeyP pub; 287 288 /** 289 * Unblinded signature on the token use public key done by the merchant. 290 */ 291 struct TALER_TokenIssueSignature unblinded_sig; 292 293 /** 294 * Hash of the token issue public key associated with this token. 295 * Note this is set in the validate_tokens phase. 296 */ 297 struct TALER_TokenIssuePublicKeyHashP h_issue; 298 299 /** 300 * true if we found this token in the database. 301 */ 302 bool found_in_db; 303 304 }; 305 306 307 /** 308 * Information about a token envelope. 309 */ 310 struct TokenEnvelope 311 { 312 313 /** 314 * Blinded token use public keys waiting to be signed. 315 */ 316 struct TALER_TokenEnvelope blinded_token; 317 318 }; 319 320 321 /** 322 * (Blindly) signed token to be returned to the wallet. 323 */ 324 struct SignedOutputToken 325 { 326 327 /** 328 * Index of the output token that produced 329 * this blindly signed token. 330 */ 331 unsigned int output_index; 332 333 /** 334 * Blinded token use public keys waiting to be signed. 335 */ 336 struct TALER_BlindedTokenIssueSignature sig; 337 338 /** 339 * Hash of token issue public key. 340 */ 341 struct TALER_TokenIssuePublicKeyHashP h_issue; 342 343 }; 344 345 346 /** 347 * Information kept during a pay request for each exchange. 348 */ 349 struct ExchangeGroup 350 { 351 352 /** 353 * Payment context this group is part of. 354 */ 355 struct PayContext *pc; 356 357 /** 358 * Handle to the batch deposit operation currently in flight for this 359 * exchange, NULL when no operation is pending. 360 */ 361 struct TALER_EXCHANGE_PostBatchDepositHandle *bdh; 362 363 /** 364 * Handle for operation to lookup /keys (and auditors) from 365 * the exchange used for this transaction; NULL if no operation is 366 * pending. 367 */ 368 struct TMH_EXCHANGES_KeysOperation *fo; 369 370 /** 371 * URL of the exchange that issued this coin. Aliases 372 * the exchange URL of one of the coins, do not free! 373 */ 374 const char *exchange_url; 375 376 /** 377 * The keys of the exchange. 378 */ 379 struct TALER_EXCHANGE_Keys *keys; 380 381 /** 382 * Total deposit amount in this exchange group. 383 */ 384 struct TALER_Amount total; 385 386 /** 387 * Wire fee that applies to this exchange for the 388 * given payment context's wire method. 389 */ 390 struct TALER_Amount wire_fee; 391 392 /** 393 * true if we already tried a forced /keys download. 394 */ 395 bool tried_force_keys; 396 397 /** 398 * Did this exchange deny the transaction for legal reasons? 399 */ 400 bool got_451; 401 }; 402 403 404 /** 405 * Information about donau, that can be fetched even 406 * if the merhchant doesn't support donau 407 */ 408 struct DonauData 409 { 410 /** 411 * The user-selected Donau URL. 412 */ 413 char *donau_url; 414 415 /** 416 * The donation year, as parsed from "year". 417 */ 418 uint64_t donation_year; 419 420 /** 421 * The original BUDI key-pairs array from the donor 422 * to be used for the receipt creation. 423 */ 424 const json_t *budikeypairs; 425 }; 426 427 /** 428 * Information we keep for an individual call to the /pay handler. 429 */ 430 struct PayContext 431 { 432 433 /** 434 * Stored in a DLL. 435 */ 436 struct PayContext *next; 437 438 /** 439 * Stored in a DLL. 440 */ 441 struct PayContext *prev; 442 443 /** 444 * MHD connection to return to 445 */ 446 struct MHD_Connection *connection; 447 448 /** 449 * Details about the client's request. 450 */ 451 struct TMH_HandlerContext *hc; 452 453 /** 454 * Transaction ID given in @e root. 455 */ 456 const char *order_id; 457 458 /** 459 * Response to return, NULL if we don't have one yet. 460 */ 461 struct MHD_Response *response; 462 463 /** 464 * Array with @e output_tokens_len signed tokens returned in 465 * the response to the wallet. 466 */ 467 struct SignedOutputToken *output_tokens; 468 469 /** 470 * Number of output tokens to return in the response. 471 * Length of the @e output_tokens array. 472 */ 473 unsigned int output_tokens_len; 474 475 /** 476 * Counter used to generate the output index in append_output_token_sig(). 477 */ 478 unsigned int output_index_gen; 479 480 /** 481 * Counter used to generate the output index in append_output_token_sig(). 482 * 483 * Counts the generated tokens _within_ the current output_index_gen. 484 */ 485 unsigned int output_token_cnt; 486 487 /** 488 * HTTP status code to use for the reply, i.e 200 for "OK". 489 * Special value UINT_MAX is used to indicate hard errors 490 * (no reply, return #MHD_NO). 491 */ 492 unsigned int response_code; 493 494 /** 495 * Payment processing phase we are in. 496 */ 497 enum PayPhase phase; 498 499 /** 500 * #GNUNET_NO if the @e connection was not suspended, 501 * #GNUNET_YES if the @e connection was suspended, 502 * #GNUNET_SYSERR if @e connection was resumed to as 503 * part of #MH_force_pc_resume during shutdown. 504 */ 505 enum GNUNET_GenericReturnValue suspended; 506 507 /** 508 * Results from the phase_parse_pay() 509 */ 510 struct 511 { 512 513 /** 514 * Array with @e num_exchanges exchanges we are depositing 515 * coins into. 516 */ 517 struct ExchangeGroup **egs; 518 519 /** 520 * Array with @e coins_cnt coins we are despositing. 521 */ 522 struct DepositConfirmation *dc; 523 524 /** 525 * Array with @e tokens_cnt input tokens passed to this request. 526 */ 527 struct TokenUseConfirmation *tokens; 528 529 /** 530 * Optional session id given in @e root. 531 * NULL if not given. 532 */ 533 char *session_id; 534 535 /** 536 * Wallet data json object from the request. Containing additional 537 * wallet data such as the selected choice_index. 538 */ 539 const json_t *wallet_data; 540 541 /** 542 * Number of coins this payment is made of. Length 543 * of the @e dc array. 544 */ 545 size_t coins_cnt; 546 547 /** 548 * Number of input tokens passed to this request. Length 549 * of the @e tokens array. 550 */ 551 size_t tokens_cnt; 552 553 /** 554 * Number of exchanges involved in the payment. Length 555 * of the @e eg array. 556 */ 557 unsigned int num_exchanges; 558 559 } parse_pay; 560 561 /** 562 * Results from the phase_wallet_data() 563 */ 564 struct 565 { 566 567 /** 568 * Array with @e token_envelopes_cnt (blinded) token envelopes. 569 */ 570 struct TokenEnvelope *token_envelopes; 571 572 /** 573 * Index of selected choice in the @e contract_terms choices array. 574 */ 575 int16_t choice_index; 576 577 /** 578 * Number of token envelopes passed to this request. 579 * Length of the @e token_envelopes array. 580 */ 581 size_t token_envelopes_cnt; 582 583 /** 584 * Hash of the canonicalized wallet data json object. 585 */ 586 struct GNUNET_HashCode h_wallet_data; 587 588 /** 589 * Donau related information 590 */ 591 struct DonauData donau; 592 593 /** 594 * Serial from the DB of the donau instance that we are using 595 */ 596 uint64_t donau_instance_serial; 597 598 #ifdef HAVE_DONAU_DONAU_SERVICE_H 599 /** 600 * Number of the blinded key pairs @e bkps 601 */ 602 unsigned int num_bkps; 603 604 /** 605 * Blinded key pairs received from the wallet 606 */ 607 struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkps; 608 609 /** 610 * The id of the charity as saved on the donau. 611 */ 612 uint64_t charity_id; 613 614 /** 615 * Private key of the charity(related to the private key of the merchant). 616 */ 617 struct DONAU_CharityPrivateKeyP charity_priv; 618 619 /** 620 * Maximum amount of donations that the charity can receive per year. 621 */ 622 struct TALER_Amount charity_max_per_year; 623 624 /** 625 * Amount of donations that the charity has received so far this year. 626 */ 627 struct TALER_Amount charity_receipts_to_date; 628 629 /** 630 * Donau keys, that we are using to get the information about the bkps. 631 */ 632 struct DONAU_Keys *donau_keys; 633 634 /** 635 * Amount from BKPS 636 */ 637 struct TALER_Amount donation_amount; 638 #endif 639 640 } parse_wallet_data; 641 642 /** 643 * Results from the phase_check_contract() 644 */ 645 struct 646 { 647 648 /** 649 * Hashed @e contract_terms. 650 */ 651 struct TALER_PrivateContractHashP h_contract_terms; 652 653 /** 654 * Our contract (or NULL if not available). 655 */ 656 json_t *contract_terms_json; 657 658 /** 659 * Parsed contract terms, NULL when parsing failed. 660 */ 661 struct TALER_MERCHANT_Contract *contract_terms; 662 663 /** 664 * What wire method (of the @e mi) was selected by the wallet? 665 * Set in #phase_parse_pay(). 666 */ 667 struct TMH_WireMethod *wm; 668 669 /** 670 * Set to the POS key, if applicable for this order. 671 */ 672 char *pos_key; 673 674 /** 675 * Serial number of this order in the database (set once we did the lookup). 676 */ 677 uint64_t order_serial; 678 679 /** 680 * Algorithm chosen for generating the confirmation code. 681 */ 682 enum TALER_MerchantConfirmationAlgorithm pos_alg; 683 684 } check_contract; 685 686 /** 687 * Results from the phase_validate_tokens() 688 */ 689 struct 690 { 691 692 /** 693 * Maximum fee the merchant is willing to pay, from @e root. 694 * Note that IF the total fee of the exchange is higher, that is 695 * acceptable to the merchant if the customer is willing to 696 * pay the difference 697 * (i.e. amount - max_fee <= actual_amount - actual_fee). 698 */ 699 struct TALER_Amount max_fee; 700 701 /** 702 * Amount from @e root. This is the amount the merchant expects 703 * to make, minus @e max_fee. 704 */ 705 struct TALER_Amount brutto; 706 707 /** 708 * Index of the donau output in the list of tokens. 709 * Set to -1 if no donau output exists. 710 */ 711 int donau_output_index; 712 713 } validate_tokens; 714 715 716 struct 717 { 718 /** 719 * Length of the @a pots and @a increments arrays. 720 */ 721 unsigned int num_pots; 722 723 /** 724 * Serial IDs of money pots to increment. 725 */ 726 uint64_t *pots; 727 728 /** 729 * Increment for the respective money pot. 730 */ 731 struct TALER_Amount *increments; 732 733 /** 734 * True if the money pots have already been computed. 735 */ 736 bool pots_computed; 737 738 } compute_money_pots; 739 740 /** 741 * Results from the phase_execute_pay_transaction() 742 */ 743 struct 744 { 745 746 /** 747 * Considering all the coins with the "found_in_db" flag 748 * set, what is the total amount we were so far paid on 749 * this contract? 750 */ 751 struct TALER_Amount total_paid; 752 753 /** 754 * Considering all the coins with the "found_in_db" flag 755 * set, what is the total amount we had to pay in deposit 756 * fees so far on this contract? 757 */ 758 struct TALER_Amount total_fees_paid; 759 760 /** 761 * Considering all the coins with the "found_in_db" flag 762 * set, what is the total amount we already refunded? 763 */ 764 struct TALER_Amount total_refunded; 765 766 /** 767 * Number of coin deposits pending. 768 */ 769 unsigned int pending; 770 771 /** 772 * How often have we retried the 'main' transaction? 773 */ 774 unsigned int retry_counter; 775 776 /** 777 * Set to true if the deposit currency of a coin 778 * does not match the contract currency. 779 */ 780 bool deposit_currency_mismatch; 781 782 /** 783 * Set to true if the database contains a (bogus) 784 * refund for a different currency. 785 */ 786 bool refund_currency_mismatch; 787 788 } pay_transaction; 789 790 /** 791 * Results from the phase_batch_deposits() 792 */ 793 struct 794 { 795 796 /** 797 * Task called when the (suspended) processing for 798 * the /pay request times out. 799 * Happens when we don't get a response from the exchange. 800 */ 801 struct GNUNET_SCHEDULER_Task *timeout_task; 802 803 /** 804 * Number of batch transactions pending. 805 */ 806 unsigned int pending_at_eg; 807 808 /** 809 * Did any exchange deny a deposit for legal reasons? 810 */ 811 bool got_451; 812 813 } batch_deposits; 814 815 #ifdef HAVE_DONAU_DONAU_SERVICE_H 816 /** 817 * Struct for #phase_request_donation_receipt() 818 */ 819 struct 820 { 821 /** 822 * Handler of the donau request 823 */ 824 struct DONAU_BatchIssueReceiptHandle *birh; 825 826 } donau_receipt; 827 #endif 828 }; 829 830 831 /** 832 * Head of active pay context DLL. 833 */ 834 static struct PayContext *pc_head; 835 836 /** 837 * Tail of active pay context DLL. 838 */ 839 static struct PayContext *pc_tail; 840 841 842 void 843 TMH_force_pc_resume () 844 { 845 for (struct PayContext *pc = pc_head; 846 NULL != pc; 847 pc = pc->next) 848 { 849 if (NULL != pc->batch_deposits.timeout_task) 850 { 851 GNUNET_SCHEDULER_cancel (pc->batch_deposits.timeout_task); 852 pc->batch_deposits.timeout_task = NULL; 853 } 854 if (GNUNET_YES == pc->suspended) 855 { 856 pc->suspended = GNUNET_SYSERR; 857 MHD_resume_connection (pc->connection); 858 } 859 } 860 } 861 862 863 /** 864 * Resume payment processing. 865 * 866 * @param[in,out] pc payment process to resume 867 */ 868 static void 869 pay_resume (struct PayContext *pc) 870 { 871 GNUNET_assert (GNUNET_YES == pc->suspended); 872 pc->suspended = GNUNET_NO; 873 MHD_resume_connection (pc->connection); 874 TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */ 875 } 876 877 878 /** 879 * Resume the given pay context and send the given response. 880 * Stores the response in the @a pc and signals MHD to resume 881 * the connection. Also ensures MHD runs immediately. 882 * 883 * @param pc payment context 884 * @param response_code response code to use 885 * @param response response data to send back 886 */ 887 static void 888 resume_pay_with_response (struct PayContext *pc, 889 unsigned int response_code, 890 struct MHD_Response *response) 891 { 892 pc->response_code = response_code; 893 pc->response = response; 894 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 895 "Resuming /pay handling. HTTP status for our reply is %u.\n", 896 response_code); 897 for (unsigned int i = 0; i<pc->parse_pay.num_exchanges; i++) 898 { 899 struct ExchangeGroup *eg = pc->parse_pay.egs[i]; 900 901 if (NULL != eg->fo) 902 { 903 TMH_EXCHANGES_keys4exchange_cancel (eg->fo); 904 eg->fo = NULL; 905 pc->batch_deposits.pending_at_eg--; 906 } 907 if (NULL != eg->bdh) 908 { 909 TALER_EXCHANGE_post_batch_deposit_cancel (eg->bdh); 910 eg->bdh = NULL; 911 pc->batch_deposits.pending_at_eg--; 912 } 913 } 914 GNUNET_assert (0 == pc->batch_deposits.pending_at_eg); 915 if (NULL != pc->batch_deposits.timeout_task) 916 { 917 GNUNET_SCHEDULER_cancel (pc->batch_deposits.timeout_task); 918 pc->batch_deposits.timeout_task = NULL; 919 } 920 pc->phase = PP_RETURN_RESPONSE; 921 pay_resume (pc); 922 } 923 924 925 /** 926 * Resume payment processing with an error. 927 * 928 * @param pc operation to resume 929 * @param ec taler error code to return 930 * @param msg human readable error message 931 */ 932 static void 933 resume_pay_with_error (struct PayContext *pc, 934 enum TALER_ErrorCode ec, 935 const char *msg) 936 { 937 resume_pay_with_response ( 938 pc, 939 TALER_ErrorCode_get_http_status_safe (ec), 940 TALER_MHD_make_error (ec, 941 msg)); 942 } 943 944 945 /** 946 * Conclude payment processing for @a pc with the 947 * given @a res MHD status code. 948 * 949 * @param[in,out] pc payment context for final state transition 950 * @param res MHD return code to end with 951 */ 952 static void 953 pay_end (struct PayContext *pc, 954 MHD_RESULT res) 955 { 956 pc->phase = (MHD_YES == res) 957 ? PP_END_YES 958 : PP_END_NO; 959 } 960 961 962 /** 963 * Return response stored in @a pc. 964 * 965 * @param[in,out] pc payment context we are processing 966 */ 967 static void 968 phase_return_response (struct PayContext *pc) 969 { 970 GNUNET_assert (0 != pc->response_code); 971 /* We are *done* processing the request, just queue the response (!) */ 972 if (UINT_MAX == pc->response_code) 973 { 974 GNUNET_break (0); 975 pay_end (pc, 976 MHD_NO); /* hard error */ 977 return; 978 } 979 pay_end (pc, 980 MHD_queue_response (pc->connection, 981 pc->response_code, 982 pc->response)); 983 } 984 985 986 /** 987 * Return a response indicating failure for legal reasons. 988 * 989 * @param[in,out] pc payment context we are processing 990 */ 991 static void 992 phase_fail_for_legal_reasons (struct PayContext *pc) 993 { 994 json_t *exchanges; 995 996 GNUNET_assert (0 == pc->pay_transaction.pending); 997 GNUNET_assert (pc->batch_deposits.got_451); 998 exchanges = json_array (); 999 GNUNET_assert (NULL != exchanges); 1000 for (unsigned int i = 0; i<pc->parse_pay.num_exchanges; i++) 1001 { 1002 struct ExchangeGroup *eg = pc->parse_pay.egs[i]; 1003 1004 GNUNET_assert (NULL == eg->fo); 1005 GNUNET_assert (NULL == eg->bdh); 1006 if (! eg->got_451) 1007 continue; 1008 GNUNET_assert ( 1009 0 == 1010 json_array_append_new ( 1011 exchanges, 1012 json_string (eg->exchange_url))); 1013 } 1014 pay_end (pc, 1015 TALER_MHD_REPLY_JSON_PACK ( 1016 pc->connection, 1017 MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS, 1018 TALER_JSON_pack_ec ( 1019 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_LEGALLY_REFUSED), 1020 GNUNET_JSON_pack_array_steal ("exchange_base_urls", 1021 exchanges))); 1022 } 1023 1024 1025 /** 1026 * Do database transaction for a completed batch deposit. 1027 * 1028 * @param eg group that completed 1029 * @param dr response from the server 1030 * @return transaction status 1031 */ 1032 static enum GNUNET_DB_QueryStatus 1033 batch_deposit_transaction ( 1034 const struct ExchangeGroup *eg, 1035 const struct TALER_EXCHANGE_PostBatchDepositResponse *dr) 1036 { 1037 const struct PayContext *pc = eg->pc; 1038 enum GNUNET_DB_QueryStatus qs; 1039 uint64_t b_dep_serial; 1040 uint32_t off = 0; 1041 1042 qs = TMH_db->insert_deposit_confirmation ( 1043 TMH_db->cls, 1044 pc->hc->instance->settings.id, 1045 dr->details.ok.deposit_timestamp, 1046 &pc->check_contract.h_contract_terms, 1047 eg->exchange_url, 1048 pc->check_contract.contract_terms->wire_deadline, 1049 &dr->details.ok.accumulated_total_without_fee, 1050 &eg->wire_fee, 1051 &pc->check_contract.wm->h_wire, 1052 dr->details.ok.exchange_sig, 1053 dr->details.ok.exchange_pub, 1054 &b_dep_serial); 1055 if (qs <= 0) 1056 return qs; /* Entire batch already known or failure, we're done */ 1057 1058 for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++) 1059 { 1060 struct DepositConfirmation *dc = &pc->parse_pay.dc[i]; 1061 1062 /* might want to group deposits by batch more explicitly ... */ 1063 if (0 != strcmp (eg->exchange_url, 1064 dc->exchange_url)) 1065 continue; 1066 if (dc->found_in_db) 1067 continue; 1068 if (! dc->in_batch) 1069 continue; 1070 /* FIXME-#9457: We might want to check if the order was fully paid concurrently 1071 by some other wallet here, and if so, issue an auto-refund. Right now, 1072 it is possible to over-pay if two wallets literally make a concurrent 1073 payment, as the earlier check for 'paid' is not in the same transaction 1074 scope as this 'insert' operation. */ 1075 qs = TMH_db->insert_deposit ( 1076 TMH_db->cls, 1077 off++, /* might want to group deposits by batch more explicitly ... */ 1078 b_dep_serial, 1079 &dc->cdd.coin_pub, 1080 &dc->cdd.coin_sig, 1081 &dc->cdd.amount, 1082 &dc->deposit_fee, 1083 &dc->refund_fee, 1084 GNUNET_TIME_absolute_add ( 1085 pc->check_contract.contract_terms->wire_deadline.abs_time, 1086 GNUNET_TIME_randomize (GNUNET_TIME_UNIT_MINUTES))); 1087 if (qs < 0) 1088 return qs; 1089 GNUNET_break (qs > 0); 1090 } 1091 return qs; 1092 } 1093 1094 1095 /** 1096 * Handle case where the batch deposit completed 1097 * with a status of #MHD_HTTP_OK. 1098 * 1099 * @param eg group that completed 1100 * @param dr response from the server 1101 */ 1102 static void 1103 handle_batch_deposit_ok ( 1104 struct ExchangeGroup *eg, 1105 const struct TALER_EXCHANGE_PostBatchDepositResponse *dr) 1106 { 1107 struct PayContext *pc = eg->pc; 1108 enum GNUNET_DB_QueryStatus qs 1109 = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; 1110 1111 /* store result to DB */ 1112 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1113 "Storing successful payment %s (%s) at instance `%s'\n", 1114 pc->hc->infix, 1115 GNUNET_h2s (&pc->check_contract.h_contract_terms.hash), 1116 pc->hc->instance->settings.id); 1117 for (unsigned int r = 0; r<MAX_RETRIES; r++) 1118 { 1119 TMH_db->preflight (TMH_db->cls); 1120 if (GNUNET_OK != 1121 TMH_db->start (TMH_db->cls, 1122 "batch-deposit-insert-confirmation")) 1123 { 1124 resume_pay_with_response ( 1125 pc, 1126 MHD_HTTP_INTERNAL_SERVER_ERROR, 1127 TALER_MHD_MAKE_JSON_PACK ( 1128 TALER_JSON_pack_ec ( 1129 TALER_EC_GENERIC_DB_START_FAILED), 1130 TMH_pack_exchange_reply (&dr->hr))); 1131 return; 1132 } 1133 qs = batch_deposit_transaction (eg, 1134 dr); 1135 if (GNUNET_DB_STATUS_SOFT_ERROR == qs) 1136 { 1137 TMH_db->rollback (TMH_db->cls); 1138 continue; 1139 } 1140 if (GNUNET_DB_STATUS_HARD_ERROR == qs) 1141 { 1142 GNUNET_break (0); 1143 resume_pay_with_error (pc, 1144 TALER_EC_GENERIC_DB_COMMIT_FAILED, 1145 "batch_deposit_transaction"); 1146 TMH_db->rollback (TMH_db->cls); 1147 return; 1148 } 1149 qs = TMH_db->commit (TMH_db->cls); 1150 if (GNUNET_DB_STATUS_SOFT_ERROR == qs) 1151 { 1152 TMH_db->rollback (TMH_db->cls); 1153 continue; 1154 } 1155 if (GNUNET_DB_STATUS_HARD_ERROR == qs) 1156 { 1157 GNUNET_break (0); 1158 resume_pay_with_error (pc, 1159 TALER_EC_GENERIC_DB_COMMIT_FAILED, 1160 "insert_deposit"); 1161 } 1162 break; /* DB transaction succeeded */ 1163 } 1164 if (GNUNET_DB_STATUS_SOFT_ERROR == qs) 1165 { 1166 resume_pay_with_error (pc, 1167 TALER_EC_GENERIC_DB_SOFT_FAILURE, 1168 "insert_deposit"); 1169 return; 1170 } 1171 1172 /* Transaction is done, mark affected coins as complete as well. */ 1173 for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++) 1174 { 1175 struct DepositConfirmation *dc = &pc->parse_pay.dc[i]; 1176 1177 if (0 != strcmp (eg->exchange_url, 1178 dc->exchange_url)) 1179 continue; 1180 if (dc->found_in_db) 1181 continue; 1182 if (! dc->in_batch) 1183 continue; 1184 dc->found_in_db = true; /* well, at least NOW it'd be true ;-) */ 1185 dc->in_batch = false; 1186 pc->pay_transaction.pending--; 1187 } 1188 } 1189 1190 1191 /** 1192 * Notify taler-merchant-kyccheck that we got a KYC 1193 * rule violation notification and should start to 1194 * check our KYC status. 1195 * 1196 * @param eg exchange group we were notified for 1197 */ 1198 static void 1199 notify_kyc_required (const struct ExchangeGroup *eg) 1200 { 1201 struct GNUNET_DB_EventHeaderP es = { 1202 .size = htons (sizeof (es)), 1203 .type = htons (TALER_DBEVENT_MERCHANT_EXCHANGE_KYC_RULE_TRIGGERED) 1204 }; 1205 char *hws; 1206 char *extra; 1207 1208 hws = GNUNET_STRINGS_data_to_string_alloc ( 1209 &eg->pc->check_contract.contract_terms->h_wire, 1210 sizeof (eg->pc->check_contract.contract_terms->h_wire)); 1211 GNUNET_asprintf (&extra, 1212 "%s %s", 1213 hws, 1214 eg->exchange_url); 1215 GNUNET_free (hws); 1216 TMH_db->event_notify (TMH_db->cls, 1217 &es, 1218 extra, 1219 strlen (extra) + 1); 1220 GNUNET_free (extra); 1221 } 1222 1223 1224 /** 1225 * Run batch deposits for @a eg. 1226 * 1227 * @param[in,out] eg group to do batch deposits for 1228 */ 1229 static void 1230 do_batch_deposits (struct ExchangeGroup *eg); 1231 1232 1233 /** 1234 * Callback to handle a batch deposit permission's response. 1235 * 1236 * @param cls a `struct ExchangeGroup` 1237 * @param dr HTTP response code details 1238 */ 1239 static void 1240 batch_deposit_cb ( 1241 void *cls, 1242 const struct TALER_EXCHANGE_PostBatchDepositResponse *dr) 1243 { 1244 struct ExchangeGroup *eg = cls; 1245 struct PayContext *pc = eg->pc; 1246 1247 eg->bdh = NULL; 1248 pc->batch_deposits.pending_at_eg--; 1249 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1250 "Batch deposit completed with status %u\n", 1251 dr->hr.http_status); 1252 GNUNET_assert (GNUNET_YES == pc->suspended); 1253 switch (dr->hr.http_status) 1254 { 1255 case MHD_HTTP_OK: 1256 handle_batch_deposit_ok (eg, 1257 dr); 1258 if (GNUNET_YES != pc->suspended) 1259 return; /* handle_batch_deposit_ok already resumed with an error */ 1260 do_batch_deposits (eg); 1261 return; 1262 case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS: 1263 for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++) 1264 { 1265 struct DepositConfirmation *dc = &pc->parse_pay.dc[i]; 1266 1267 if (0 != strcmp (eg->exchange_url, 1268 dc->exchange_url)) 1269 continue; 1270 dc->in_batch = false; 1271 } 1272 notify_kyc_required (eg); 1273 eg->got_451 = true; 1274 pc->batch_deposits.got_451 = true; 1275 /* update pc->pay_transaction.pending */ 1276 for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++) 1277 { 1278 struct DepositConfirmation *dc = &pc->parse_pay.dc[i]; 1279 1280 if (0 != strcmp (eg->exchange_url, 1281 pc->parse_pay.dc[i].exchange_url)) 1282 continue; 1283 if (dc->found_in_db) 1284 continue; 1285 pc->pay_transaction.pending--; 1286 } 1287 if (0 == pc->batch_deposits.pending_at_eg) 1288 { 1289 pc->phase = PP_COMPUTE_MONEY_POTS; 1290 pay_resume (pc); 1291 } 1292 return; 1293 default: 1294 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1295 "Deposit operation failed with HTTP code %u/%d\n", 1296 dr->hr.http_status, 1297 (int) dr->hr.ec); 1298 for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++) 1299 { 1300 struct DepositConfirmation *dc = &pc->parse_pay.dc[i]; 1301 1302 if (0 != strcmp (eg->exchange_url, 1303 dc->exchange_url)) 1304 continue; 1305 dc->in_batch = false; 1306 } 1307 /* Transaction failed */ 1308 if (5 == dr->hr.http_status / 100) 1309 { 1310 /* internal server error at exchange */ 1311 resume_pay_with_response (pc, 1312 MHD_HTTP_BAD_GATEWAY, 1313 TALER_MHD_MAKE_JSON_PACK ( 1314 TALER_JSON_pack_ec ( 1315 TALER_EC_MERCHANT_GENERIC_EXCHANGE_UNEXPECTED_STATUS), 1316 TMH_pack_exchange_reply (&dr->hr))); 1317 return; 1318 } 1319 if (NULL == dr->hr.reply) 1320 { 1321 /* We can't do anything meaningful here, the exchange did something wrong */ 1322 resume_pay_with_response ( 1323 pc, 1324 MHD_HTTP_BAD_GATEWAY, 1325 TALER_MHD_MAKE_JSON_PACK ( 1326 TALER_JSON_pack_ec ( 1327 TALER_EC_MERCHANT_GENERIC_EXCHANGE_REPLY_MALFORMED), 1328 TMH_pack_exchange_reply (&dr->hr))); 1329 return; 1330 } 1331 1332 /* Forward error, adding the "exchange_url" for which the 1333 error was being generated */ 1334 if (TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS == dr->hr.ec) 1335 { 1336 resume_pay_with_response ( 1337 pc, 1338 MHD_HTTP_CONFLICT, 1339 TALER_MHD_MAKE_JSON_PACK ( 1340 TALER_JSON_pack_ec ( 1341 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_INSUFFICIENT_FUNDS), 1342 TMH_pack_exchange_reply (&dr->hr), 1343 GNUNET_JSON_pack_string ("exchange_url", 1344 eg->exchange_url))); 1345 return; 1346 } 1347 resume_pay_with_response ( 1348 pc, 1349 MHD_HTTP_BAD_GATEWAY, 1350 TALER_MHD_MAKE_JSON_PACK ( 1351 TALER_JSON_pack_ec ( 1352 TALER_EC_MERCHANT_GENERIC_EXCHANGE_UNEXPECTED_STATUS), 1353 TMH_pack_exchange_reply (&dr->hr), 1354 GNUNET_JSON_pack_string ("exchange_url", 1355 eg->exchange_url))); 1356 return; 1357 } /* end switch */ 1358 } 1359 1360 1361 static void 1362 do_batch_deposits (struct ExchangeGroup *eg) 1363 { 1364 struct PayContext *pc = eg->pc; 1365 struct TMH_HandlerContext *hc = pc->hc; 1366 unsigned int group_size = 0; 1367 /* Initiate /batch-deposit operation for all coins of 1368 the current exchange (!) */ 1369 1370 GNUNET_assert (NULL != eg->keys); 1371 for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++) 1372 { 1373 struct DepositConfirmation *dc = &pc->parse_pay.dc[i]; 1374 1375 if (0 != strcmp (eg->exchange_url, 1376 pc->parse_pay.dc[i].exchange_url)) 1377 continue; 1378 if (dc->found_in_db) 1379 continue; 1380 group_size++; 1381 if (group_size >= TALER_MAX_COINS) 1382 break; 1383 } 1384 if (0 == group_size) 1385 { 1386 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1387 "Group size zero, %u batch transactions remain pending\n", 1388 pc->batch_deposits.pending_at_eg); 1389 if (0 == pc->batch_deposits.pending_at_eg) 1390 { 1391 pc->phase = PP_COMPUTE_MONEY_POTS; 1392 pay_resume (pc); 1393 return; 1394 } 1395 return; 1396 } 1397 /* Dispatch the next batch of up to TALER_MAX_COINS coins. 1398 On success, batch_deposit_cb() will re-invoke 1399 do_batch_deposits() to send further batches until 1400 all coins are done. */ 1401 { 1402 struct TALER_EXCHANGE_DepositContractDetail dcd = { 1403 .wire_deadline = pc->check_contract.contract_terms->wire_deadline, 1404 .merchant_payto_uri = pc->check_contract.wm->payto_uri, 1405 .extra_wire_subject_metadata 1406 = pc->check_contract.wm->extra_wire_subject_metadata, 1407 .wire_salt = pc->check_contract.wm->wire_salt, 1408 .h_contract_terms = pc->check_contract.h_contract_terms, 1409 .wallet_data_hash = pc->parse_wallet_data.h_wallet_data, 1410 .wallet_timestamp = pc->check_contract.contract_terms->timestamp, 1411 .merchant_pub = hc->instance->merchant_pub, 1412 .refund_deadline = pc->check_contract.contract_terms->refund_deadline 1413 }; 1414 /* Collect up to TALER_MAX_COINS eligible coins for this batch */ 1415 struct TALER_EXCHANGE_CoinDepositDetail cdds[group_size]; 1416 unsigned int batch_size = 0; 1417 enum TALER_ErrorCode ec; 1418 1419 /* FIXME-optimization: move signing outside of this 'loop' 1420 and into the code that runs long before we look at a 1421 specific exchange, otherwise we sign repeatedly! */ 1422 TALER_merchant_contract_sign (&pc->check_contract.h_contract_terms, 1423 &pc->hc->instance->merchant_priv, 1424 &dcd.merchant_sig); 1425 for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++) 1426 { 1427 struct DepositConfirmation *dc = &pc->parse_pay.dc[i]; 1428 1429 if (dc->found_in_db) 1430 continue; 1431 if (0 != strcmp (dc->exchange_url, 1432 eg->exchange_url)) 1433 continue; 1434 dc->in_batch = true; 1435 cdds[batch_size++] = dc->cdd; 1436 if (batch_size == group_size) 1437 break; 1438 } 1439 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1440 "Initiating batch deposit with %u coins\n", 1441 batch_size); 1442 /* Note: the coin signatures over the wallet_data_hash are 1443 checked inside of this call */ 1444 eg->bdh = TALER_EXCHANGE_post_batch_deposit_create ( 1445 TMH_curl_ctx, 1446 eg->exchange_url, 1447 eg->keys, 1448 &dcd, 1449 batch_size, 1450 cdds, 1451 &ec); 1452 if (NULL == eg->bdh) 1453 { 1454 /* Signature was invalid or some other constraint was not satisfied. If 1455 the exchange was unavailable, we'd get that information in the 1456 callback. */ 1457 GNUNET_break_op (0); 1458 resume_pay_with_response ( 1459 pc, 1460 TALER_ErrorCode_get_http_status_safe (ec), 1461 TALER_MHD_MAKE_JSON_PACK ( 1462 TALER_JSON_pack_ec (ec), 1463 GNUNET_JSON_pack_string ("exchange_url", 1464 eg->exchange_url))); 1465 return; 1466 } 1467 pc->batch_deposits.pending_at_eg++; 1468 if (TMH_force_audit) 1469 TALER_EXCHANGE_post_batch_deposit_force_dc (eg->bdh); 1470 TALER_EXCHANGE_post_batch_deposit_start (eg->bdh, 1471 &batch_deposit_cb, 1472 eg); 1473 } 1474 } 1475 1476 1477 /** 1478 * Force re-downloading keys for @a eg. 1479 * 1480 * @param[in,out] eg group to re-download keys for 1481 */ 1482 static void 1483 force_keys (struct ExchangeGroup *eg); 1484 1485 1486 /** 1487 * Function called with the result of our exchange keys lookup. 1488 * 1489 * @param cls the `struct ExchangeGroup` 1490 * @param keys the keys of the exchange 1491 * @param exchange representation of the exchange 1492 */ 1493 static void 1494 process_pay_with_keys ( 1495 void *cls, 1496 struct TALER_EXCHANGE_Keys *keys, 1497 struct TMH_Exchange *exchange) 1498 { 1499 struct ExchangeGroup *eg = cls; 1500 struct PayContext *pc = eg->pc; 1501 struct TMH_HandlerContext *hc = pc->hc; 1502 struct TALER_Amount max_amount; 1503 enum TMH_ExchangeStatus es; 1504 1505 eg->fo = NULL; 1506 pc->batch_deposits.pending_at_eg--; 1507 GNUNET_SCHEDULER_begin_async_scope (&hc->async_scope_id); 1508 eg->keys = TALER_EXCHANGE_keys_incref (keys); 1509 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1510 "Processing payment with keys from exchange %s\n", 1511 eg->exchange_url); 1512 GNUNET_assert (GNUNET_YES == pc->suspended); 1513 if (NULL == keys) 1514 { 1515 GNUNET_break_op (0); 1516 resume_pay_with_error ( 1517 pc, 1518 TALER_EC_MERCHANT_GENERIC_EXCHANGE_TIMEOUT, 1519 NULL); 1520 return; 1521 } 1522 if (! TMH_EXCHANGES_is_below_limit (keys, 1523 TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION, 1524 &eg->total)) 1525 { 1526 GNUNET_break_op (0); 1527 resume_pay_with_error ( 1528 pc, 1529 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_TRANSACTION_LIMIT_VIOLATION, 1530 eg->exchange_url); 1531 return; 1532 } 1533 1534 max_amount = eg->total; 1535 es = TMH_exchange_check_debit ( 1536 pc->hc->instance->settings.id, 1537 exchange, 1538 pc->check_contract.wm, 1539 &max_amount); 1540 if ( (TMH_ES_OK != es) && 1541 (TMH_ES_RETRY_OK != es) ) 1542 { 1543 if (eg->tried_force_keys || 1544 (0 == (TMH_ES_RETRY_OK & es)) ) 1545 { 1546 GNUNET_break_op (0); 1547 resume_pay_with_error ( 1548 pc, 1549 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_WIRE_METHOD_UNSUPPORTED, 1550 NULL); 1551 return; 1552 } 1553 force_keys (eg); 1554 return; 1555 } 1556 if (-1 == 1557 TALER_amount_cmp (&max_amount, 1558 &eg->total)) 1559 { 1560 /* max_amount < eg->total */ 1561 GNUNET_break_op (0); 1562 resume_pay_with_error ( 1563 pc, 1564 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_TRANSACTION_LIMIT_VIOLATION, 1565 eg->exchange_url); 1566 return; 1567 } 1568 1569 if (GNUNET_OK != 1570 TMH_EXCHANGES_lookup_wire_fee (exchange, 1571 pc->check_contract.wm->wire_method, 1572 &eg->wire_fee)) 1573 { 1574 if (eg->tried_force_keys) 1575 { 1576 GNUNET_break_op (0); 1577 resume_pay_with_error ( 1578 pc, 1579 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_WIRE_METHOD_UNSUPPORTED, 1580 pc->check_contract.wm->wire_method); 1581 return; 1582 } 1583 force_keys (eg); 1584 return; 1585 } 1586 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1587 "Got wire data for %s\n", 1588 eg->exchange_url); 1589 1590 /* Check all coins satisfy constraints like deposit deadlines 1591 and age restrictions */ 1592 for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++) 1593 { 1594 struct DepositConfirmation *dc = &pc->parse_pay.dc[i]; 1595 const struct TALER_EXCHANGE_DenomPublicKey *denom_details; 1596 bool is_age_restricted_denom = false; 1597 1598 if (0 != strcmp (eg->exchange_url, 1599 pc->parse_pay.dc[i].exchange_url)) 1600 continue; 1601 if (dc->found_in_db) 1602 continue; 1603 1604 denom_details 1605 = TALER_EXCHANGE_get_denomination_key_by_hash (keys, 1606 &dc->cdd.h_denom_pub); 1607 if (NULL == denom_details) 1608 { 1609 if (eg->tried_force_keys) 1610 { 1611 GNUNET_break_op (0); 1612 resume_pay_with_response ( 1613 pc, 1614 MHD_HTTP_BAD_REQUEST, 1615 TALER_MHD_MAKE_JSON_PACK ( 1616 TALER_JSON_pack_ec ( 1617 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_KEY_NOT_FOUND), 1618 GNUNET_JSON_pack_data_auto ("h_denom_pub", 1619 &dc->cdd.h_denom_pub), 1620 GNUNET_JSON_pack_allow_null ( 1621 GNUNET_JSON_pack_object_steal ( 1622 "exchange_keys", 1623 TALER_EXCHANGE_keys_to_json (keys))))); 1624 return; 1625 } 1626 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1627 "Missing denomination %s from exchange %s, updating keys\n", 1628 GNUNET_h2s (&dc->cdd.h_denom_pub.hash), 1629 eg->exchange_url); 1630 force_keys (eg); 1631 return; 1632 } 1633 dc->deposit_fee = denom_details->fees.deposit; 1634 dc->refund_fee = denom_details->fees.refund; 1635 1636 if (GNUNET_TIME_absolute_is_past ( 1637 denom_details->expire_deposit.abs_time)) 1638 { 1639 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1640 "Denomination key offered by client has expired for deposits\n"); 1641 resume_pay_with_response ( 1642 pc, 1643 MHD_HTTP_GONE, 1644 TALER_MHD_MAKE_JSON_PACK ( 1645 TALER_JSON_pack_ec ( 1646 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_DEPOSIT_EXPIRED), 1647 GNUNET_JSON_pack_data_auto ("h_denom_pub", 1648 &denom_details->h_key))); 1649 return; 1650 } 1651 1652 /* Now that we have the details about the denomination, we can verify age 1653 * restriction requirements, if applicable. Note that denominations with an 1654 * age_mask equal to zero always pass the age verification. */ 1655 is_age_restricted_denom = (0 != denom_details->key.age_mask.bits); 1656 1657 if (is_age_restricted_denom && 1658 (0 < pc->check_contract.contract_terms->minimum_age)) 1659 { 1660 /* Minimum age given and restricted coin provided: We need to verify the 1661 * minimum age */ 1662 unsigned int code = 0; 1663 1664 if (dc->no_age_commitment) 1665 { 1666 GNUNET_break_op (0); 1667 code = TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_MISSING; 1668 goto AGE_FAIL; 1669 } 1670 dc->age_commitment.mask = denom_details->key.age_mask; 1671 if (((int) (dc->age_commitment.num + 1)) != 1672 __builtin_popcount (dc->age_commitment.mask.bits)) 1673 { 1674 GNUNET_break_op (0); 1675 code = 1676 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_SIZE_MISMATCH; 1677 goto AGE_FAIL; 1678 } 1679 if (GNUNET_OK != 1680 TALER_age_commitment_verify ( 1681 &dc->age_commitment, 1682 pc->check_contract.contract_terms->minimum_age, 1683 &dc->minimum_age_sig)) 1684 code = TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AGE_VERIFICATION_FAILED; 1685 AGE_FAIL: 1686 if (0 < code) 1687 { 1688 GNUNET_break_op (0); 1689 TALER_age_commitment_free (&dc->age_commitment); 1690 resume_pay_with_response ( 1691 pc, 1692 MHD_HTTP_BAD_REQUEST, 1693 TALER_MHD_MAKE_JSON_PACK ( 1694 TALER_JSON_pack_ec (code), 1695 GNUNET_JSON_pack_data_auto ("h_denom_pub", 1696 &denom_details->h_key))); 1697 return; 1698 } 1699 1700 /* Age restriction successfully verified! 1701 * Calculate the hash of the age commitment. */ 1702 TALER_age_commitment_hash (&dc->age_commitment, 1703 &dc->cdd.h_age_commitment); 1704 TALER_age_commitment_free (&dc->age_commitment); 1705 } 1706 else if (is_age_restricted_denom && 1707 dc->no_h_age_commitment) 1708 { 1709 /* The contract did not ask for a minimum_age but the client paid 1710 * with a coin that has age restriction enabled. We lack the hash 1711 * of the age commitment in this case in order to verify the coin 1712 * and to deposit it with the exchange. */ 1713 GNUNET_break_op (0); 1714 resume_pay_with_response ( 1715 pc, 1716 MHD_HTTP_BAD_REQUEST, 1717 TALER_MHD_MAKE_JSON_PACK ( 1718 TALER_JSON_pack_ec ( 1719 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_HASH_MISSING), 1720 GNUNET_JSON_pack_data_auto ("h_denom_pub", 1721 &denom_details->h_key))); 1722 return; 1723 } 1724 } 1725 1726 do_batch_deposits (eg); 1727 } 1728 1729 1730 static void 1731 force_keys (struct ExchangeGroup *eg) 1732 { 1733 struct PayContext *pc = eg->pc; 1734 1735 eg->tried_force_keys = true; 1736 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1737 "Forcing /keys download (once)\n"); 1738 eg->fo = TMH_EXCHANGES_keys4exchange ( 1739 eg->exchange_url, 1740 true, 1741 &process_pay_with_keys, 1742 eg); 1743 if (NULL == eg->fo) 1744 { 1745 GNUNET_break_op (0); 1746 resume_pay_with_error (pc, 1747 TALER_EC_MERCHANT_GENERIC_EXCHANGE_UNTRUSTED, 1748 eg->exchange_url); 1749 return; 1750 } 1751 pc->batch_deposits.pending_at_eg++; 1752 } 1753 1754 1755 /** 1756 * Handle a timeout for the processing of the pay request. 1757 * 1758 * @param cls our `struct PayContext` 1759 */ 1760 static void 1761 handle_pay_timeout (void *cls) 1762 { 1763 struct PayContext *pc = cls; 1764 1765 pc->batch_deposits.timeout_task = NULL; 1766 GNUNET_assert (GNUNET_YES == pc->suspended); 1767 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1768 "Resuming pay with error after timeout\n"); 1769 resume_pay_with_error (pc, 1770 TALER_EC_MERCHANT_GENERIC_EXCHANGE_TIMEOUT, 1771 NULL); 1772 } 1773 1774 1775 /** 1776 * Compute the timeout for a /pay request based on the number of coins 1777 * involved. 1778 * 1779 * @param num_coins number of coins 1780 * @returns timeout for the /pay request 1781 */ 1782 static struct GNUNET_TIME_Relative 1783 get_pay_timeout (unsigned int num_coins) 1784 { 1785 struct GNUNET_TIME_Relative t; 1786 1787 /* FIXME-Performance-Optimization: Do some benchmarking to come up with a 1788 * better timeout. We've increased this value so the wallet integration 1789 * test passes again on my (Florian) machine. 1790 */ 1791 t = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1792 15 * (1 + (num_coins / 5))); 1793 1794 return t; 1795 } 1796 1797 1798 /** 1799 * Start batch deposits for all exchanges involved 1800 * in this payment. 1801 * 1802 * @param[in,out] pc payment context we are processing 1803 */ 1804 static void 1805 phase_batch_deposits (struct PayContext *pc) 1806 { 1807 for (unsigned int i = 0; i<pc->parse_pay.num_exchanges; i++) 1808 { 1809 struct ExchangeGroup *eg = pc->parse_pay.egs[i]; 1810 bool have_coins = false; 1811 1812 for (size_t j = 0; j<pc->parse_pay.coins_cnt; j++) 1813 { 1814 struct DepositConfirmation *dc = &pc->parse_pay.dc[j]; 1815 1816 if (0 != strcmp (eg->exchange_url, 1817 dc->exchange_url)) 1818 continue; 1819 if (dc->found_in_db) 1820 continue; 1821 have_coins = true; 1822 break; 1823 } 1824 if (! have_coins) 1825 continue; /* no coins left to deposit at this exchange */ 1826 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1827 "Getting /keys for %s\n", 1828 eg->exchange_url); 1829 eg->fo = TMH_EXCHANGES_keys4exchange ( 1830 eg->exchange_url, 1831 false, 1832 &process_pay_with_keys, 1833 eg); 1834 if (NULL == eg->fo) 1835 { 1836 GNUNET_break_op (0); 1837 pay_end (pc, 1838 TALER_MHD_reply_with_error ( 1839 pc->connection, 1840 MHD_HTTP_BAD_REQUEST, 1841 TALER_EC_MERCHANT_GENERIC_EXCHANGE_UNTRUSTED, 1842 eg->exchange_url)); 1843 return; 1844 } 1845 pc->batch_deposits.pending_at_eg++; 1846 } 1847 if (0 == pc->batch_deposits.pending_at_eg) 1848 { 1849 pc->phase = PP_COMPUTE_MONEY_POTS; 1850 pay_resume (pc); 1851 return; 1852 } 1853 /* Suspend while we interact with the exchange */ 1854 MHD_suspend_connection (pc->connection); 1855 pc->suspended = GNUNET_YES; 1856 GNUNET_assert (NULL == pc->batch_deposits.timeout_task); 1857 pc->batch_deposits.timeout_task 1858 = GNUNET_SCHEDULER_add_delayed (get_pay_timeout (pc->parse_pay.coins_cnt), 1859 &handle_pay_timeout, 1860 pc); 1861 } 1862 1863 1864 /** 1865 * Build JSON array of blindly signed token envelopes, 1866 * to be used in the response to the wallet. 1867 * 1868 * @param[in,out] pc payment context to use 1869 */ 1870 static json_t * 1871 build_token_sigs (struct PayContext *pc) 1872 { 1873 json_t *token_sigs; 1874 1875 if (0 == pc->output_tokens_len) 1876 return NULL; 1877 token_sigs = json_array (); 1878 GNUNET_assert (NULL != token_sigs); 1879 for (unsigned int i = 0; i < pc->output_tokens_len; i++) 1880 { 1881 GNUNET_assert (0 == 1882 json_array_append_new ( 1883 token_sigs, 1884 GNUNET_JSON_PACK ( 1885 GNUNET_JSON_pack_blinded_sig ( 1886 "blind_sig", 1887 pc->output_tokens[i].sig.signature) 1888 ))); 1889 } 1890 return token_sigs; 1891 } 1892 1893 1894 /** 1895 * Generate response (payment successful) 1896 * 1897 * @param[in,out] pc payment context where the payment was successful 1898 */ 1899 static void 1900 phase_success_response (struct PayContext *pc) 1901 { 1902 struct TALER_MerchantSignatureP sig; 1903 char *pos_confirmation; 1904 1905 /* Sign on our end (as the payment did go through, even if it may 1906 have been refunded already) */ 1907 TALER_merchant_pay_sign (&pc->check_contract.h_contract_terms, 1908 &pc->hc->instance->merchant_priv, 1909 &sig); 1910 /* Build the response */ 1911 pos_confirmation = (NULL == pc->check_contract.pos_key) 1912 ? NULL 1913 : TALER_build_pos_confirmation (pc->check_contract.pos_key, 1914 pc->check_contract.pos_alg, 1915 &pc->validate_tokens.brutto, 1916 pc->check_contract.contract_terms->timestamp 1917 ); 1918 pay_end (pc, 1919 TALER_MHD_REPLY_JSON_PACK ( 1920 pc->connection, 1921 MHD_HTTP_OK, 1922 GNUNET_JSON_pack_allow_null ( 1923 GNUNET_JSON_pack_string ("pos_confirmation", 1924 pos_confirmation)), 1925 GNUNET_JSON_pack_allow_null ( 1926 GNUNET_JSON_pack_array_steal ("token_sigs", 1927 build_token_sigs (pc))), 1928 GNUNET_JSON_pack_data_auto ("sig", 1929 &sig))); 1930 GNUNET_free (pos_confirmation); 1931 } 1932 1933 1934 /** 1935 * Use database to notify other clients about the 1936 * payment being completed. 1937 * 1938 * @param[in,out] pc context to trigger notification for 1939 */ 1940 static void 1941 phase_payment_notification (struct PayContext *pc) 1942 { 1943 { 1944 struct TMH_OrderPayEventP pay_eh = { 1945 .header.size = htons (sizeof (pay_eh)), 1946 .header.type = htons (TALER_DBEVENT_MERCHANT_ORDER_PAID), 1947 .merchant_pub = pc->hc->instance->merchant_pub 1948 }; 1949 1950 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1951 "Notifying clients about payment of order %s\n", 1952 pc->order_id); 1953 GNUNET_CRYPTO_hash (pc->order_id, 1954 strlen (pc->order_id), 1955 &pay_eh.h_order_id); 1956 TMH_db->event_notify (TMH_db->cls, 1957 &pay_eh.header, 1958 NULL, 1959 0); 1960 } 1961 { 1962 struct TMH_OrderPayEventP pay_eh = { 1963 .header.size = htons (sizeof (pay_eh)), 1964 .header.type = htons (TALER_DBEVENT_MERCHANT_ORDER_STATUS_CHANGED), 1965 .merchant_pub = pc->hc->instance->merchant_pub 1966 }; 1967 1968 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1969 "Notifying clients about status change of order %s\n", 1970 pc->order_id); 1971 GNUNET_CRYPTO_hash (pc->order_id, 1972 strlen (pc->order_id), 1973 &pay_eh.h_order_id); 1974 TMH_db->event_notify (TMH_db->cls, 1975 &pay_eh.header, 1976 NULL, 1977 0); 1978 } 1979 if ( (NULL != pc->parse_pay.session_id) && 1980 (NULL != pc->check_contract.contract_terms->fulfillment_url) ) 1981 { 1982 struct TMH_SessionEventP session_eh = { 1983 .header.size = htons (sizeof (session_eh)), 1984 .header.type = htons (TALER_DBEVENT_MERCHANT_SESSION_CAPTURED), 1985 .merchant_pub = pc->hc->instance->merchant_pub 1986 }; 1987 1988 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1989 "Notifying clients about session change to %s for %s\n", 1990 pc->parse_pay.session_id, 1991 pc->check_contract.contract_terms->fulfillment_url); 1992 GNUNET_CRYPTO_hash (pc->parse_pay.session_id, 1993 strlen (pc->parse_pay.session_id), 1994 &session_eh.h_session_id); 1995 GNUNET_CRYPTO_hash (pc->check_contract.contract_terms->fulfillment_url, 1996 strlen (pc->check_contract.contract_terms-> 1997 fulfillment_url), 1998 &session_eh.h_fulfillment_url); 1999 TMH_db->event_notify (TMH_db->cls, 2000 &session_eh.header, 2001 NULL, 2002 0); 2003 } 2004 pc->phase = PP_SUCCESS_RESPONSE; 2005 } 2006 2007 2008 /** 2009 * Phase to write all outputs to our database so we do 2010 * not re-request them in case the client re-plays the 2011 * request. 2012 * 2013 * @param[in,out] pc payment context 2014 */ 2015 static void 2016 phase_final_output_token_processing (struct PayContext *pc) 2017 { 2018 if (0 == pc->output_tokens_len) 2019 { 2020 pc->phase++; 2021 return; 2022 } 2023 for (unsigned int retry = 0; retry < MAX_RETRIES; retry++) 2024 { 2025 enum GNUNET_DB_QueryStatus qs; 2026 2027 TMH_db->preflight (TMH_db->cls); 2028 if (GNUNET_OK != 2029 TMH_db->start (TMH_db->cls, 2030 "insert_order_blinded_sigs")) 2031 { 2032 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2033 "start insert_order_blinded_sigs_failed"); 2034 pc->phase++; 2035 return; 2036 } 2037 #ifdef HAVE_DONAU_DONAU_SERVICE_H 2038 if (pc->parse_wallet_data.num_bkps > 0) 2039 { 2040 qs = TMH_db->update_donau_instance_receipts_amount ( 2041 TMH_db->cls, 2042 &pc->parse_wallet_data.donau_instance_serial, 2043 &pc->parse_wallet_data.charity_receipts_to_date); 2044 switch (qs) 2045 { 2046 case GNUNET_DB_STATUS_HARD_ERROR: 2047 TMH_db->rollback (TMH_db->cls); 2048 GNUNET_break (0); 2049 return; 2050 case GNUNET_DB_STATUS_SOFT_ERROR: 2051 TMH_db->rollback (TMH_db->cls); 2052 continue; 2053 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 2054 /* weird for an update */ 2055 GNUNET_break (0); 2056 break; 2057 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 2058 break; 2059 } 2060 } 2061 #endif 2062 for (unsigned int i = 0; 2063 i < pc->output_tokens_len; 2064 i++) 2065 { 2066 qs = TMH_db->insert_order_blinded_sigs ( 2067 TMH_db->cls, 2068 pc->order_id, 2069 i, 2070 &pc->output_tokens[i].h_issue.hash, 2071 pc->output_tokens[i].sig.signature); 2072 2073 switch (qs) 2074 { 2075 case GNUNET_DB_STATUS_HARD_ERROR: 2076 TMH_db->rollback (TMH_db->cls); 2077 pc->phase++; 2078 return; 2079 case GNUNET_DB_STATUS_SOFT_ERROR: 2080 TMH_db->rollback (TMH_db->cls); 2081 goto OUTER; 2082 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 2083 /* weird for an update */ 2084 GNUNET_break (0); 2085 break; 2086 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 2087 break; 2088 } 2089 } /* for i */ 2090 qs = TMH_db->commit (TMH_db->cls); 2091 switch (qs) 2092 { 2093 case GNUNET_DB_STATUS_HARD_ERROR: 2094 TMH_db->rollback (TMH_db->cls); 2095 pc->phase++; 2096 return; 2097 case GNUNET_DB_STATUS_SOFT_ERROR: 2098 TMH_db->rollback (TMH_db->cls); 2099 continue; 2100 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 2101 pc->phase++; 2102 return; /* success */ 2103 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 2104 pc->phase++; 2105 return; /* success */ 2106 } 2107 GNUNET_break (0); 2108 pc->phase++; 2109 return; /* strange */ 2110 OUTER: 2111 } /* for retry */ 2112 TMH_db->rollback (TMH_db->cls); 2113 pc->phase++; 2114 /* We continue anyway, as there is not much we can 2115 do here: the Donau *did* issue us the receipts; 2116 also, we'll eventually ask the Donau for the 2117 balance and get the correct one. Plus, we were 2118 paid by the client, so it's technically all still 2119 OK. If the request fails anyway, the wallet will 2120 most likely replay the request and then hopefully 2121 we will succeed the next time */ 2122 } 2123 2124 2125 #ifdef HAVE_DONAU_DONAU_SERVICE_H 2126 2127 /** 2128 * Add donation receipt outputs to the output_tokens. 2129 * 2130 * Note that under the current (odd, bad) libdonau 2131 * API *we* are responsible for freeing blinded_sigs, 2132 * so we truly own that array! 2133 * 2134 * @param[in,out] pc payment context 2135 * @param num_blinded_sigs number of signatures received 2136 * @param blinded_sigs blinded signatures from Donau 2137 * @return #GNUNET_OK on success, 2138 * #GNUNET_SYSERR on failure (state machine was 2139 * in that case already advanced) 2140 */ 2141 static enum GNUNET_GenericReturnValue 2142 add_donation_receipt_outputs ( 2143 struct PayContext *pc, 2144 size_t num_blinded_sigs, 2145 struct DONAU_BlindedDonationUnitSignature *blinded_sigs) 2146 { 2147 int donau_output_index = pc->validate_tokens.donau_output_index; 2148 2149 GNUNET_assert (pc->parse_wallet_data.num_bkps == 2150 num_blinded_sigs); 2151 2152 GNUNET_assert (donau_output_index >= 0); 2153 2154 for (unsigned int i = 0; i<pc->output_tokens_len; i++) 2155 { 2156 struct SignedOutputToken *sot 2157 = &pc->output_tokens[i]; 2158 2159 /* Only look at actual donau tokens. */ 2160 if (sot->output_index != donau_output_index) 2161 continue; 2162 2163 sot->sig.signature = GNUNET_CRYPTO_blind_sig_incref (blinded_sigs[i]. 2164 blinded_sig); 2165 sot->h_issue.hash = pc->parse_wallet_data.bkps[i].h_donation_unit_pub.hash; 2166 } 2167 return GNUNET_OK; 2168 } 2169 2170 2171 /** 2172 * Callback to handle the result of a batch issue request. 2173 * 2174 * @param cls our `struct PayContext` 2175 * @param resp the response from Donau 2176 */ 2177 static void 2178 merchant_donau_issue_receipt_cb ( 2179 void *cls, 2180 const struct DONAU_BatchIssueResponse *resp) 2181 { 2182 struct PayContext *pc = cls; 2183 /* Donau replies asynchronously, so we expect the PayContext 2184 * to be suspended. */ 2185 GNUNET_assert (GNUNET_YES == pc->suspended); 2186 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2187 "Donau responded with status=%u, ec=%u", 2188 resp->hr.http_status, 2189 resp->hr.ec); 2190 switch (resp->hr.http_status) 2191 { 2192 case 0: 2193 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2194 "Donau batch issue request from merchant-httpd failed (http_status==0)"); 2195 resume_pay_with_error (pc, 2196 TALER_EC_MERCHANT_GENERIC_DONAU_INVALID_RESPONSE, 2197 resp->hr.hint); 2198 return; 2199 case MHD_HTTP_OK: 2200 case MHD_HTTP_CREATED: 2201 if (TALER_EC_NONE != resp->hr.ec) 2202 { 2203 /* Most probably, it is just some small flaw from 2204 * donau so no point in failing, yet we have to display it */ 2205 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2206 "Donau signalled error %u despite HTTP %u", 2207 resp->hr.ec, 2208 resp->hr.http_status); 2209 } 2210 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 2211 "Donau accepted donation receipts with total_issued=%s", 2212 TALER_amount2s (&resp->details.ok.issued_amount)); 2213 if (GNUNET_OK != 2214 add_donation_receipt_outputs (pc, 2215 resp->details.ok.num_blinded_sigs, 2216 resp->details.ok.blinded_sigs)) 2217 return; /* state machine was already advanced */ 2218 pc->phase = PP_FINAL_OUTPUT_TOKEN_PROCESSING; 2219 pay_resume (pc); 2220 return; 2221 2222 case MHD_HTTP_BAD_REQUEST: 2223 case MHD_HTTP_FORBIDDEN: 2224 case MHD_HTTP_NOT_FOUND: 2225 case MHD_HTTP_INTERNAL_SERVER_ERROR: 2226 default: /* make sure that everything except 200/201 will end up here*/ 2227 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2228 "Donau replied with HTTP %u (ec=%u)", 2229 resp->hr.http_status, 2230 resp->hr.ec); 2231 resume_pay_with_error (pc, 2232 TALER_EC_MERCHANT_GENERIC_DONAU_INVALID_RESPONSE, 2233 resp->hr.hint); 2234 return; 2235 } 2236 } 2237 2238 2239 /** 2240 * Parse a bkp encoded in JSON. 2241 * 2242 * @param[out] bkp where to return the result 2243 * @param bkp_key_obj json to parse 2244 * @return #GNUNET_OK if all is fine, #GNUNET_SYSERR if @a bkp_key_obj 2245 * is malformed. 2246 */ 2247 static enum GNUNET_GenericReturnValue 2248 merchant_parse_json_bkp (struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkp, 2249 const json_t *bkp_key_obj) 2250 { 2251 struct GNUNET_JSON_Specification spec[] = { 2252 GNUNET_JSON_spec_fixed_auto ("h_donation_unit_pub", 2253 &bkp->h_donation_unit_pub), 2254 DONAU_JSON_spec_blinded_donation_identifier ("blinded_udi", 2255 &bkp->blinded_udi), 2256 GNUNET_JSON_spec_end () 2257 }; 2258 2259 if (GNUNET_OK != 2260 GNUNET_JSON_parse (bkp_key_obj, 2261 spec, 2262 NULL, 2263 NULL)) 2264 { 2265 GNUNET_break_op (0); 2266 return GNUNET_SYSERR; 2267 } 2268 return GNUNET_OK; 2269 } 2270 2271 2272 /** 2273 * Generate a donation signature for the bkp and charity. 2274 * 2275 * @param[in,out] pc payment context containing the charity and bkps 2276 */ 2277 static void 2278 phase_request_donation_receipt (struct PayContext *pc) 2279 { 2280 if ( (NULL == pc->parse_wallet_data.donau.donau_url) || 2281 (0 == pc->parse_wallet_data.num_bkps) ) 2282 { 2283 pc->phase++; 2284 return; 2285 } 2286 pc->donau_receipt.birh = 2287 DONAU_charity_issue_receipt ( 2288 TMH_curl_ctx, 2289 pc->parse_wallet_data.donau.donau_url, 2290 &pc->parse_wallet_data.charity_priv, 2291 pc->parse_wallet_data.charity_id, 2292 pc->parse_wallet_data.donau.donation_year, 2293 pc->parse_wallet_data.num_bkps, 2294 pc->parse_wallet_data.bkps, 2295 &merchant_donau_issue_receipt_cb, 2296 pc); 2297 if (NULL == pc->donau_receipt.birh) 2298 { 2299 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2300 "Failed to create Donau receipt request"); 2301 pay_end (pc, 2302 TALER_MHD_reply_with_error (pc->connection, 2303 MHD_HTTP_INTERNAL_SERVER_ERROR, 2304 TALER_EC_GENERIC_CLIENT_INTERNAL_ERROR, 2305 "Donau request creation error")); 2306 return; 2307 } 2308 MHD_suspend_connection (pc->connection); 2309 pc->suspended = GNUNET_YES; 2310 } 2311 2312 2313 #endif 2314 2315 2316 /** 2317 * Increment the money pot @a pot_id in @a pc by @a increment. 2318 * 2319 * @param[in,out] pc context to update 2320 * @param pot_id money pot to increment 2321 * @param increment amount to add 2322 */ 2323 static void 2324 increment_pot (struct PayContext *pc, 2325 uint64_t pot_id, 2326 const struct TALER_Amount *increment) 2327 { 2328 for (unsigned int i = 0; i<pc->compute_money_pots.num_pots; i++) 2329 { 2330 if (pot_id == pc->compute_money_pots.pots[i]) 2331 { 2332 struct TALER_Amount *p; 2333 2334 p = &pc->compute_money_pots.increments[i]; 2335 GNUNET_assert (0 <= 2336 TALER_amount_add (p, 2337 p, 2338 increment)); 2339 return; 2340 } 2341 } 2342 GNUNET_array_append (pc->compute_money_pots.pots, 2343 pc->compute_money_pots.num_pots, 2344 pot_id); 2345 pc->compute_money_pots.num_pots--; /* do not increment twice... */ 2346 GNUNET_array_append (pc->compute_money_pots.increments, 2347 pc->compute_money_pots.num_pots, 2348 *increment); 2349 } 2350 2351 2352 /** 2353 * Compute the total changes to money pots in preparation 2354 * for the #PP_PAY_TRANSACTION phase. 2355 * 2356 * @param[in,out] pc payment context to transact 2357 */ 2358 static void 2359 phase_compute_money_pots (struct PayContext *pc) 2360 { 2361 const struct TALER_MERCHANT_Contract *contract 2362 = pc->check_contract.contract_terms; 2363 struct TALER_Amount assigned; 2364 2365 if (0 == pc->parse_pay.coins_cnt) 2366 { 2367 /* Did not pay with any coins, so no currency/amount involved, 2368 hence no money pot update possible. */ 2369 pc->phase++; 2370 return; 2371 } 2372 2373 if (pc->compute_money_pots.pots_computed) 2374 { 2375 pc->phase++; 2376 return; 2377 } 2378 /* reset, in case this phase is run a 2nd time */ 2379 GNUNET_free (pc->compute_money_pots.pots); 2380 GNUNET_free (pc->compute_money_pots.increments); 2381 pc->compute_money_pots.num_pots = 0; 2382 2383 TALER_amount_set_zero (pc->parse_pay.dc[0].cdd.amount.currency, 2384 &assigned); 2385 GNUNET_assert (NULL != contract); 2386 for (size_t i = 0; i<contract->products_len; i++) 2387 { 2388 const struct TALER_MERCHANT_ProductSold *product 2389 = &contract->products[i]; 2390 const struct TALER_Amount *price = NULL; 2391 2392 /* find price in the right currency */ 2393 for (unsigned int j = 0; j<product->prices_length; j++) 2394 { 2395 if (GNUNET_OK == 2396 TALER_amount_cmp_currency (&assigned, 2397 &product->prices[j])) 2398 { 2399 price = &product->prices[j]; 2400 break; 2401 } 2402 } 2403 if (NULL == price) 2404 { 2405 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 2406 "Product `%s' has no price given in `%s'.\n", 2407 product->product_id, 2408 assigned.currency); 2409 continue; 2410 } 2411 if (0 != product->product_money_pot) 2412 { 2413 GNUNET_assert (0 <= 2414 TALER_amount_add (&assigned, 2415 &assigned, 2416 price)); 2417 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 2418 "Contributing to product money pot %llu increment of %s\n", 2419 (unsigned long long) product->product_money_pot, 2420 TALER_amount2s (price)); 2421 increment_pot (pc, 2422 product->product_money_pot, 2423 price); 2424 } 2425 } 2426 2427 { 2428 /* Compute what is left from the order total and account for that. 2429 Also sanity-check and handle the case where the overall order 2430 is below that of the sum of the products. */ 2431 struct TALER_Amount left; 2432 2433 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 2434 "Order brutto is %s\n", 2435 TALER_amount2s (&pc->validate_tokens.brutto)); 2436 if (0 > 2437 TALER_amount_subtract (&left, 2438 &pc->validate_tokens.brutto, 2439 &assigned)) 2440 { 2441 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 2442 "Total order brutto amount below sum from products, skipping per-product money pots\n"); 2443 GNUNET_free (pc->compute_money_pots.pots); 2444 GNUNET_free (pc->compute_money_pots.increments); 2445 pc->compute_money_pots.num_pots = 0; 2446 left = pc->validate_tokens.brutto; 2447 } 2448 2449 if ( (! TALER_amount_is_zero (&left)) && 2450 (0 != contract->default_money_pot) ) 2451 { 2452 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 2453 "Computing money pot %llu increment as %s\n", 2454 (unsigned long long) contract->default_money_pot, 2455 TALER_amount2s (&left)); 2456 increment_pot (pc, 2457 contract->default_money_pot, 2458 &left); 2459 } 2460 } 2461 pc->compute_money_pots.pots_computed = true; 2462 pc->phase++; 2463 } 2464 2465 2466 /** 2467 * Function called with information about a coin that was deposited. 2468 * 2469 * @param cls closure 2470 * @param exchange_url exchange where @a coin_pub was deposited 2471 * @param coin_pub public key of the coin 2472 * @param amount_with_fee amount the exchange will deposit for this coin 2473 * @param deposit_fee fee the exchange will charge for this coin 2474 * @param refund_fee fee the exchange will charge for refunding this coin 2475 */ 2476 static void 2477 check_coin_paid (void *cls, 2478 const char *exchange_url, 2479 const struct TALER_CoinSpendPublicKeyP *coin_pub, 2480 const struct TALER_Amount *amount_with_fee, 2481 const struct TALER_Amount *deposit_fee, 2482 const struct TALER_Amount *refund_fee) 2483 { 2484 struct PayContext *pc = cls; 2485 2486 for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++) 2487 { 2488 struct DepositConfirmation *dc = &pc->parse_pay.dc[i]; 2489 2490 if (dc->found_in_db) 2491 continue; /* processed earlier, skip "expensive" memcmp() */ 2492 /* Get matching coin from results*/ 2493 if ( (0 != GNUNET_memcmp (coin_pub, 2494 &dc->cdd.coin_pub)) || 2495 (0 != 2496 strcmp (exchange_url, 2497 dc->exchange_url)) || 2498 (GNUNET_OK != 2499 TALER_amount_cmp_currency (amount_with_fee, 2500 &dc->cdd.amount)) || 2501 (0 != TALER_amount_cmp (amount_with_fee, 2502 &dc->cdd.amount)) ) 2503 continue; /* does not match, skip */ 2504 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2505 "Deposit of coin `%s' already in our DB.\n", 2506 TALER_B2S (coin_pub)); 2507 if ( (GNUNET_OK != 2508 TALER_amount_cmp_currency (&pc->pay_transaction.total_paid, 2509 amount_with_fee)) || 2510 (GNUNET_OK != 2511 TALER_amount_cmp_currency (&pc->pay_transaction.total_fees_paid, 2512 deposit_fee)) ) 2513 { 2514 GNUNET_break_op (0); 2515 pc->pay_transaction.deposit_currency_mismatch = true; 2516 break; 2517 } 2518 GNUNET_assert (0 <= 2519 TALER_amount_add (&pc->pay_transaction.total_paid, 2520 &pc->pay_transaction.total_paid, 2521 amount_with_fee)); 2522 GNUNET_assert (0 <= 2523 TALER_amount_add (&pc->pay_transaction.total_fees_paid, 2524 &pc->pay_transaction.total_fees_paid, 2525 deposit_fee)); 2526 dc->deposit_fee = *deposit_fee; 2527 dc->refund_fee = *refund_fee; 2528 dc->cdd.amount = *amount_with_fee; 2529 dc->found_in_db = true; 2530 pc->pay_transaction.pending--; 2531 } 2532 } 2533 2534 2535 /** 2536 * Function called with information about a refund. Check if this coin was 2537 * claimed by the wallet for the transaction, and if so add the refunded 2538 * amount to the pc's "total_refunded" amount. 2539 * 2540 * @param cls closure with a `struct PayContext` 2541 * @param coin_pub public coin from which the refund comes from 2542 * @param refund_amount refund amount which is being taken from @a coin_pub 2543 */ 2544 static void 2545 check_coin_refunded (void *cls, 2546 const struct TALER_CoinSpendPublicKeyP *coin_pub, 2547 const struct TALER_Amount *refund_amount) 2548 { 2549 struct PayContext *pc = cls; 2550 2551 /* We look at refunds here that apply to the coins 2552 that the customer is currently trying to pay us with. 2553 2554 Such refunds are not "normal" refunds, but abort-pay refunds, which are 2555 given in the case that the wallet aborts the payment. 2556 In the case the wallet then decides to complete the payment *after* doing 2557 an abort-pay refund (an unusual but possible case), we need 2558 to make sure that existing refunds are accounted for. */ 2559 2560 for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++) 2561 { 2562 struct DepositConfirmation *dc = &pc->parse_pay.dc[i]; 2563 2564 /* Get matching coins from results. */ 2565 if (0 != GNUNET_memcmp (coin_pub, 2566 &dc->cdd.coin_pub)) 2567 continue; 2568 if (GNUNET_OK != 2569 TALER_amount_cmp_currency (&pc->pay_transaction.total_refunded, 2570 refund_amount)) 2571 { 2572 GNUNET_break (0); 2573 pc->pay_transaction.refund_currency_mismatch = true; 2574 break; 2575 } 2576 GNUNET_assert (0 <= 2577 TALER_amount_add (&pc->pay_transaction.total_refunded, 2578 &pc->pay_transaction.total_refunded, 2579 refund_amount)); 2580 break; 2581 } 2582 } 2583 2584 2585 /** 2586 * Check whether the amount paid is sufficient to cover the price. 2587 * 2588 * @param pc payment context to check 2589 * @return true if the payment is sufficient, false if it is 2590 * insufficient 2591 */ 2592 static bool 2593 check_payment_sufficient (struct PayContext *pc) 2594 { 2595 struct TALER_Amount acc_fee; 2596 struct TALER_Amount acc_amount; 2597 struct TALER_Amount final_amount; 2598 struct TALER_Amount total_wire_fee; 2599 struct TALER_Amount total_needed; 2600 2601 if (0 == pc->parse_pay.coins_cnt) 2602 return TALER_amount_is_zero (&pc->validate_tokens.brutto); 2603 GNUNET_assert (GNUNET_OK == 2604 TALER_amount_set_zero (pc->validate_tokens.brutto.currency, 2605 &total_wire_fee)); 2606 for (unsigned int i = 0; i < pc->parse_pay.num_exchanges; i++) 2607 { 2608 if (GNUNET_OK != 2609 TALER_amount_cmp_currency (&total_wire_fee, 2610 &pc->parse_pay.egs[i]->wire_fee)) 2611 { 2612 GNUNET_break_op (0); 2613 pay_end (pc, 2614 TALER_MHD_reply_with_error (pc->connection, 2615 MHD_HTTP_BAD_REQUEST, 2616 TALER_EC_GENERIC_CURRENCY_MISMATCH, 2617 total_wire_fee.currency)); 2618 return false; 2619 } 2620 if (0 > 2621 TALER_amount_add (&total_wire_fee, 2622 &total_wire_fee, 2623 &pc->parse_pay.egs[i]->wire_fee)) 2624 { 2625 GNUNET_break (0); 2626 pay_end (pc, 2627 TALER_MHD_reply_with_error ( 2628 pc->connection, 2629 MHD_HTTP_INTERNAL_SERVER_ERROR, 2630 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_WIRE_FEE_ADDITION_FAILED, 2631 "could not add exchange wire fee to total")); 2632 return false; 2633 } 2634 } 2635 2636 /** 2637 * This loops calculates what are the deposit fee / total 2638 * amount with fee / and wire fee, for all the coins. 2639 */ 2640 GNUNET_assert (GNUNET_OK == 2641 TALER_amount_set_zero (pc->validate_tokens.brutto.currency, 2642 &acc_fee)); 2643 GNUNET_assert (GNUNET_OK == 2644 TALER_amount_set_zero (pc->validate_tokens.brutto.currency, 2645 &acc_amount)); 2646 for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++) 2647 { 2648 struct DepositConfirmation *dc = &pc->parse_pay.dc[i]; 2649 2650 GNUNET_assert (dc->found_in_db); 2651 if ( (GNUNET_OK != 2652 TALER_amount_cmp_currency (&acc_fee, 2653 &dc->deposit_fee)) || 2654 (GNUNET_OK != 2655 TALER_amount_cmp_currency (&acc_amount, 2656 &dc->cdd.amount)) ) 2657 { 2658 GNUNET_break_op (0); 2659 pay_end (pc, 2660 TALER_MHD_reply_with_error ( 2661 pc->connection, 2662 MHD_HTTP_BAD_REQUEST, 2663 TALER_EC_GENERIC_CURRENCY_MISMATCH, 2664 dc->deposit_fee.currency)); 2665 return false; 2666 } 2667 if ( (0 > 2668 TALER_amount_add (&acc_fee, 2669 &dc->deposit_fee, 2670 &acc_fee)) || 2671 (0 > 2672 TALER_amount_add (&acc_amount, 2673 &dc->cdd.amount, 2674 &acc_amount)) ) 2675 { 2676 GNUNET_break (0); 2677 /* Overflow in these amounts? Very strange. */ 2678 pay_end (pc, 2679 TALER_MHD_reply_with_error ( 2680 pc->connection, 2681 MHD_HTTP_INTERNAL_SERVER_ERROR, 2682 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW, 2683 "Overflow adding up amounts")); 2684 return false; 2685 } 2686 if (1 == 2687 TALER_amount_cmp (&dc->deposit_fee, 2688 &dc->cdd.amount)) 2689 { 2690 GNUNET_break_op (0); 2691 pay_end (pc, 2692 TALER_MHD_reply_with_error ( 2693 pc->connection, 2694 MHD_HTTP_BAD_REQUEST, 2695 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_FEES_EXCEED_PAYMENT, 2696 "Deposit fees exceed coin's contribution")); 2697 return false; 2698 } 2699 } /* end deposit loop */ 2700 2701 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2702 "Amount received from wallet: %s\n", 2703 TALER_amount2s (&acc_amount)); 2704 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2705 "Deposit fee for all coins: %s\n", 2706 TALER_amount2s (&acc_fee)); 2707 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2708 "Total wire fee: %s\n", 2709 TALER_amount2s (&total_wire_fee)); 2710 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2711 "Deposit fee limit for merchant: %s\n", 2712 TALER_amount2s (&pc->validate_tokens.max_fee)); 2713 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2714 "Total refunded amount: %s\n", 2715 TALER_amount2s (&pc->pay_transaction.total_refunded)); 2716 2717 /* Now compare exchange wire fee compared to what we are willing to pay */ 2718 if (GNUNET_YES != 2719 TALER_amount_cmp_currency (&total_wire_fee, 2720 &acc_fee)) 2721 { 2722 GNUNET_break (0); 2723 pay_end (pc, 2724 TALER_MHD_reply_with_error ( 2725 pc->connection, 2726 MHD_HTTP_BAD_REQUEST, 2727 TALER_EC_GENERIC_CURRENCY_MISMATCH, 2728 total_wire_fee.currency)); 2729 return false; 2730 } 2731 2732 /* add wire fee to the total fees */ 2733 if (0 > 2734 TALER_amount_add (&acc_fee, 2735 &acc_fee, 2736 &total_wire_fee)) 2737 { 2738 GNUNET_break (0); 2739 pay_end (pc, 2740 TALER_MHD_reply_with_error ( 2741 pc->connection, 2742 MHD_HTTP_INTERNAL_SERVER_ERROR, 2743 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW, 2744 "Overflow adding up amounts")); 2745 return false; 2746 } 2747 if (-1 == TALER_amount_cmp (&pc->validate_tokens.max_fee, 2748 &acc_fee)) 2749 { 2750 /** 2751 * Sum of fees of *all* the different exchanges of all the coins are 2752 * higher than the fixed limit that the merchant is willing to pay. The 2753 * difference must be paid by the customer. 2754 */ 2755 struct TALER_Amount excess_fee; 2756 2757 /* compute fee amount to be covered by customer */ 2758 GNUNET_assert (TALER_AAR_RESULT_POSITIVE == 2759 TALER_amount_subtract (&excess_fee, 2760 &acc_fee, 2761 &pc->validate_tokens.max_fee)); 2762 /* add that to the total */ 2763 if (0 > 2764 TALER_amount_add (&total_needed, 2765 &excess_fee, 2766 &pc->validate_tokens.brutto)) 2767 { 2768 GNUNET_break (0); 2769 pay_end (pc, 2770 TALER_MHD_reply_with_error ( 2771 pc->connection, 2772 MHD_HTTP_INTERNAL_SERVER_ERROR, 2773 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW, 2774 "Overflow adding up amounts")); 2775 return false; 2776 } 2777 } 2778 else 2779 { 2780 /* Fees are fully covered by the merchant, all we require 2781 is that the total payment is not below the contract's amount */ 2782 total_needed = pc->validate_tokens.brutto; 2783 } 2784 2785 /* Do not count refunds towards the payment */ 2786 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 2787 "Subtracting total refunds from paid amount: %s\n", 2788 TALER_amount2s (&pc->pay_transaction.total_refunded)); 2789 if (0 > 2790 TALER_amount_subtract (&final_amount, 2791 &acc_amount, 2792 &pc->pay_transaction.total_refunded)) 2793 { 2794 GNUNET_break (0); 2795 pay_end (pc, 2796 TALER_MHD_reply_with_error ( 2797 pc->connection, 2798 MHD_HTTP_INTERNAL_SERVER_ERROR, 2799 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_REFUNDS_EXCEED_PAYMENTS, 2800 "refunded amount exceeds total payments")); 2801 return false; 2802 } 2803 2804 if (-1 == TALER_amount_cmp (&final_amount, 2805 &total_needed)) 2806 { 2807 /* acc_amount < total_needed */ 2808 if (-1 < TALER_amount_cmp (&acc_amount, 2809 &total_needed)) 2810 { 2811 GNUNET_break_op (0); 2812 pay_end (pc, 2813 TALER_MHD_reply_with_error ( 2814 pc->connection, 2815 MHD_HTTP_PAYMENT_REQUIRED, 2816 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_REFUNDED, 2817 "contract not paid up due to refunds")); 2818 return false; 2819 } 2820 if (-1 < TALER_amount_cmp (&acc_amount, 2821 &pc->validate_tokens.brutto)) 2822 { 2823 GNUNET_break_op (0); 2824 pay_end (pc, 2825 TALER_MHD_reply_with_error ( 2826 pc->connection, 2827 MHD_HTTP_BAD_REQUEST, 2828 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_INSUFFICIENT_DUE_TO_FEES, 2829 "contract not paid up due to fees (client may have calculated them badly)")); 2830 return false; 2831 } 2832 GNUNET_break_op (0); 2833 pay_end (pc, 2834 TALER_MHD_reply_with_error ( 2835 pc->connection, 2836 MHD_HTTP_BAD_REQUEST, 2837 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_PAYMENT_INSUFFICIENT, 2838 "payment insufficient")); 2839 return false; 2840 } 2841 return true; 2842 } 2843 2844 2845 /** 2846 * Execute the DB transaction. If required (from 2847 * soft/serialization errors), the transaction can be 2848 * restarted here. 2849 * 2850 * @param[in,out] pc payment context to transact 2851 */ 2852 static void 2853 phase_execute_pay_transaction (struct PayContext *pc) 2854 { 2855 struct TMH_HandlerContext *hc = pc->hc; 2856 const char *instance_id = hc->instance->settings.id; 2857 2858 if (pc->batch_deposits.got_451) 2859 { 2860 pc->phase = PP_FAIL_LEGAL_REASONS; 2861 return; 2862 } 2863 /* Avoid re-trying transactions on soft errors forever! */ 2864 if (pc->pay_transaction.retry_counter++ > MAX_RETRIES) 2865 { 2866 GNUNET_break (0); 2867 pay_end (pc, 2868 TALER_MHD_reply_with_error (pc->connection, 2869 MHD_HTTP_INTERNAL_SERVER_ERROR, 2870 TALER_EC_GENERIC_DB_SOFT_FAILURE, 2871 NULL)); 2872 return; 2873 } 2874 2875 /* Initialize some amount accumulators 2876 (used in check_coin_paid(), check_coin_refunded() 2877 and check_payment_sufficient()). */ 2878 GNUNET_break (GNUNET_OK == 2879 TALER_amount_set_zero (pc->validate_tokens.brutto.currency, 2880 &pc->pay_transaction.total_paid)); 2881 GNUNET_break (GNUNET_OK == 2882 TALER_amount_set_zero (pc->validate_tokens.brutto.currency, 2883 &pc->pay_transaction.total_fees_paid)); 2884 GNUNET_break (GNUNET_OK == 2885 TALER_amount_set_zero (pc->validate_tokens.brutto.currency, 2886 &pc->pay_transaction.total_refunded)); 2887 for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++) 2888 pc->parse_pay.dc[i].found_in_db = false; 2889 pc->pay_transaction.pending = pc->parse_pay.coins_cnt; 2890 2891 /* First, try to see if we have all we need already done */ 2892 TMH_db->preflight (TMH_db->cls); 2893 if (GNUNET_OK != 2894 TMH_db->start (TMH_db->cls, 2895 "run pay")) 2896 { 2897 GNUNET_break (0); 2898 pay_end (pc, 2899 TALER_MHD_reply_with_error (pc->connection, 2900 MHD_HTTP_INTERNAL_SERVER_ERROR, 2901 TALER_EC_GENERIC_DB_START_FAILED, 2902 NULL)); 2903 return; 2904 } 2905 2906 for (size_t i = 0; i<pc->parse_pay.tokens_cnt; i++) 2907 { 2908 struct TokenUseConfirmation *tuc = &pc->parse_pay.tokens[i]; 2909 enum GNUNET_DB_QueryStatus qs; 2910 2911 /* Insert used token into database, the unique constraint will 2912 case an error if this token was used before. */ 2913 qs = TMH_db->insert_spent_token (TMH_db->cls, 2914 &pc->check_contract.h_contract_terms, 2915 &tuc->h_issue, 2916 &tuc->pub, 2917 &tuc->sig, 2918 &tuc->unblinded_sig); 2919 2920 switch (qs) 2921 { 2922 case GNUNET_DB_STATUS_SOFT_ERROR: 2923 TMH_db->rollback (TMH_db->cls); 2924 return; /* do it again */ 2925 case GNUNET_DB_STATUS_HARD_ERROR: 2926 /* Always report on hard error as well to enable diagnostics */ 2927 TMH_db->rollback (TMH_db->cls); 2928 pay_end (pc, 2929 TALER_MHD_reply_with_error (pc->connection, 2930 MHD_HTTP_INTERNAL_SERVER_ERROR, 2931 TALER_EC_GENERIC_DB_STORE_FAILED, 2932 "insert used token")); 2933 return; 2934 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 2935 /* UNIQUE constraint violation, meaning this token was already used. */ 2936 TMH_db->rollback (TMH_db->cls); 2937 pay_end (pc, 2938 TALER_MHD_reply_with_error (pc->connection, 2939 MHD_HTTP_CONFLICT, 2940 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_TOKEN_INVALID, 2941 NULL)); 2942 return; 2943 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 2944 /* Good, proceed! */ 2945 break; 2946 } 2947 } /* for all tokens */ 2948 2949 { 2950 enum GNUNET_DB_QueryStatus qs; 2951 2952 /* Check if some of these coins already succeeded for _this_ contract. */ 2953 qs = TMH_db->lookup_deposits (TMH_db->cls, 2954 instance_id, 2955 &pc->check_contract.h_contract_terms, 2956 &check_coin_paid, 2957 pc); 2958 if (0 > qs) 2959 { 2960 TMH_db->rollback (TMH_db->cls); 2961 if (GNUNET_DB_STATUS_SOFT_ERROR == qs) 2962 return; /* do it again */ 2963 /* Always report on hard error as well to enable diagnostics */ 2964 GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs); 2965 pay_end (pc, 2966 TALER_MHD_reply_with_error (pc->connection, 2967 MHD_HTTP_INTERNAL_SERVER_ERROR, 2968 TALER_EC_GENERIC_DB_FETCH_FAILED, 2969 "lookup deposits")); 2970 return; 2971 } 2972 if (pc->pay_transaction.deposit_currency_mismatch) 2973 { 2974 TMH_db->rollback (TMH_db->cls); 2975 GNUNET_break_op (0); 2976 pay_end (pc, 2977 TALER_MHD_reply_with_error ( 2978 pc->connection, 2979 MHD_HTTP_BAD_REQUEST, 2980 TALER_EC_MERCHANT_GENERIC_CURRENCY_MISMATCH, 2981 pc->validate_tokens.brutto.currency)); 2982 return; 2983 } 2984 } 2985 2986 { 2987 enum GNUNET_DB_QueryStatus qs; 2988 2989 /* Check if we refunded some of the coins */ 2990 qs = TMH_db->lookup_refunds (TMH_db->cls, 2991 instance_id, 2992 &pc->check_contract.h_contract_terms, 2993 &check_coin_refunded, 2994 pc); 2995 if (0 > qs) 2996 { 2997 TMH_db->rollback (TMH_db->cls); 2998 if (GNUNET_DB_STATUS_SOFT_ERROR == qs) 2999 return; /* do it again */ 3000 /* Always report on hard error as well to enable diagnostics */ 3001 GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs); 3002 pay_end (pc, 3003 TALER_MHD_reply_with_error (pc->connection, 3004 MHD_HTTP_INTERNAL_SERVER_ERROR, 3005 TALER_EC_GENERIC_DB_FETCH_FAILED, 3006 "lookup refunds")); 3007 return; 3008 } 3009 if (pc->pay_transaction.refund_currency_mismatch) 3010 { 3011 TMH_db->rollback (TMH_db->cls); 3012 pay_end (pc, 3013 TALER_MHD_reply_with_error (pc->connection, 3014 MHD_HTTP_INTERNAL_SERVER_ERROR, 3015 TALER_EC_GENERIC_DB_FETCH_FAILED, 3016 "refund currency in database does not match order currency")); 3017 return; 3018 } 3019 } 3020 3021 /* Check if there are coins that still need to be processed */ 3022 if (0 != pc->pay_transaction.pending) 3023 { 3024 /* we made no DB changes, so we can just rollback */ 3025 TMH_db->rollback (TMH_db->cls); 3026 /* Ok, we need to first go to the network to process more coins. 3027 We that interaction in *tiny* transactions (hence the rollback 3028 above). */ 3029 pc->phase = PP_BATCH_DEPOSITS; 3030 return; 3031 } 3032 3033 /* 0 == pc->pay_transaction.pending: all coins processed, let's see if that was enough */ 3034 if (! check_payment_sufficient (pc)) 3035 { 3036 /* check_payment_sufficient() will have queued an error already. 3037 We need to still abort the transaction. */ 3038 TMH_db->rollback (TMH_db->cls); 3039 return; 3040 } 3041 /* Payment succeeded, save in database */ 3042 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 3043 "Order `%s' (%s) was fully paid\n", 3044 pc->order_id, 3045 GNUNET_h2s (&pc->check_contract.h_contract_terms.hash)); 3046 { 3047 enum GNUNET_DB_QueryStatus qs; 3048 3049 qs = TMH_db->mark_contract_paid (TMH_db->cls, 3050 instance_id, 3051 &pc->check_contract.h_contract_terms, 3052 pc->parse_pay.session_id, 3053 pc->parse_wallet_data.choice_index); 3054 if (qs < 0) 3055 { 3056 TMH_db->rollback (TMH_db->cls); 3057 if (GNUNET_DB_STATUS_SOFT_ERROR == qs) 3058 return; /* do it again */ 3059 GNUNET_break (0); 3060 pay_end (pc, 3061 TALER_MHD_reply_with_error (pc->connection, 3062 MHD_HTTP_INTERNAL_SERVER_ERROR, 3063 TALER_EC_GENERIC_DB_STORE_FAILED, 3064 "mark contract paid")); 3065 return; 3066 } 3067 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 3068 "Marked contract paid returned %d\n", 3069 (int) qs); 3070 3071 if ( (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) && 3072 (0 < pc->compute_money_pots.num_pots) ) 3073 { 3074 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 3075 "Incrementing %u money pots by %s\n", 3076 pc->compute_money_pots.num_pots, 3077 TALER_amount2s (&pc->compute_money_pots.increments[0])); 3078 qs = TMH_db->increment_money_pots (TMH_db->cls, 3079 instance_id, 3080 pc->compute_money_pots.num_pots, 3081 pc->compute_money_pots.pots, 3082 pc->compute_money_pots.increments); 3083 switch (qs) 3084 { 3085 case GNUNET_DB_STATUS_SOFT_ERROR: 3086 TMH_db->rollback (TMH_db->cls); 3087 return; /* do it again */ 3088 case GNUNET_DB_STATUS_HARD_ERROR: 3089 /* Always report on hard error as well to enable diagnostics */ 3090 TMH_db->rollback (TMH_db->cls); 3091 pay_end (pc, 3092 TALER_MHD_reply_with_error (pc->connection, 3093 MHD_HTTP_INTERNAL_SERVER_ERROR, 3094 TALER_EC_GENERIC_DB_STORE_FAILED, 3095 "increment_money_pots")); 3096 return; 3097 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 3098 /* strange */ 3099 GNUNET_break (0); 3100 break; 3101 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 3102 /* Good, proceed! */ 3103 break; 3104 } 3105 3106 } 3107 3108 3109 } 3110 3111 3112 { 3113 const struct TALER_MERCHANT_ContractChoice *choice = 3114 &pc->check_contract.contract_terms->details.v1 3115 .choices[pc->parse_wallet_data.choice_index]; 3116 3117 for (size_t i = 0; i<pc->output_tokens_len; i++) 3118 { 3119 unsigned int output_index; 3120 enum TALER_MERCHANT_ContractOutputType type; 3121 3122 output_index = pc->output_tokens[i].output_index; 3123 GNUNET_assert (output_index < choice->outputs_len); 3124 type = choice->outputs[output_index].type; 3125 3126 switch (type) 3127 { 3128 case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID: 3129 /* Well, good luck getting here */ 3130 GNUNET_break (0); 3131 pay_end (pc, 3132 TALER_MHD_reply_with_error (pc->connection, 3133 MHD_HTTP_INTERNAL_SERVER_ERROR, 3134 TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, 3135 "invalid output type")); 3136 break; 3137 case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT: 3138 /* We skip output tokens of donation receipts here, as they are handled in the 3139 * phase_final_output_token_processing() callback from donau */ 3140 break; 3141 case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN: 3142 struct SignedOutputToken *output = 3143 &pc->output_tokens[i]; 3144 enum GNUNET_DB_QueryStatus qs; 3145 3146 qs = TMH_db->insert_issued_token (TMH_db->cls, 3147 &pc->check_contract.h_contract_terms, 3148 &output->h_issue, 3149 &output->sig); 3150 switch (qs) 3151 { 3152 case GNUNET_DB_STATUS_HARD_ERROR: 3153 TMH_db->rollback (TMH_db->cls); 3154 GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs); 3155 pay_end (pc, 3156 TALER_MHD_reply_with_error (pc->connection, 3157 MHD_HTTP_INTERNAL_SERVER_ERROR, 3158 TALER_EC_GENERIC_DB_STORE_FAILED, 3159 "insert output token")); 3160 return; 3161 case GNUNET_DB_STATUS_SOFT_ERROR: 3162 /* Serialization failure, retry */ 3163 TMH_db->rollback (TMH_db->cls); 3164 return; 3165 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 3166 /* UNIQUE constraint violation, meaning this token was already used. */ 3167 TMH_db->rollback (TMH_db->cls); 3168 pay_end (pc, 3169 TALER_MHD_reply_with_error (pc->connection, 3170 MHD_HTTP_INTERNAL_SERVER_ERROR, 3171 TALER_EC_GENERIC_DB_STORE_FAILED, 3172 "duplicate output token")); 3173 return; 3174 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 3175 break; 3176 } 3177 break; 3178 } 3179 } 3180 } 3181 3182 TMH_notify_order_change (hc->instance, 3183 TMH_OSF_CLAIMED | TMH_OSF_PAID, 3184 pc->check_contract.contract_terms->timestamp, 3185 pc->check_contract.order_serial); 3186 { 3187 enum GNUNET_DB_QueryStatus qs; 3188 json_t *jhook; 3189 3190 jhook = GNUNET_JSON_PACK ( 3191 GNUNET_JSON_pack_object_incref ("contract_terms", 3192 pc->check_contract.contract_terms_json), 3193 GNUNET_JSON_pack_string ("order_id", 3194 pc->order_id) 3195 ); 3196 GNUNET_assert (NULL != jhook); 3197 qs = TMH_trigger_webhook (pc->hc->instance->settings.id, 3198 "pay", 3199 jhook); 3200 json_decref (jhook); 3201 if (qs < 0) 3202 { 3203 TMH_db->rollback (TMH_db->cls); 3204 if (GNUNET_DB_STATUS_SOFT_ERROR == qs) 3205 return; /* do it again */ 3206 GNUNET_break (0); 3207 pay_end (pc, 3208 TALER_MHD_reply_with_error (pc->connection, 3209 MHD_HTTP_INTERNAL_SERVER_ERROR, 3210 TALER_EC_GENERIC_DB_STORE_FAILED, 3211 "failed to trigger webhooks")); 3212 return; 3213 } 3214 } 3215 { 3216 enum GNUNET_DB_QueryStatus qs; 3217 3218 /* Now commit! */ 3219 qs = TMH_db->commit (TMH_db->cls); 3220 if (0 > qs) 3221 { 3222 /* commit failed */ 3223 TMH_db->rollback (TMH_db->cls); 3224 if (GNUNET_DB_STATUS_SOFT_ERROR == qs) 3225 return; /* do it again */ 3226 GNUNET_break (0); 3227 pay_end (pc, 3228 TALER_MHD_reply_with_error (pc->connection, 3229 MHD_HTTP_INTERNAL_SERVER_ERROR, 3230 TALER_EC_GENERIC_DB_COMMIT_FAILED, 3231 NULL)); 3232 return; 3233 } 3234 } 3235 pc->phase++; 3236 } 3237 3238 3239 /** 3240 * Ensures that the expected number of tokens for a @e key 3241 * are provided as inputs and have valid signatures. 3242 * 3243 * @param[in,out] pc payment context we are processing 3244 * @param family family the tokens should be from 3245 * @param index number of the input we are handling 3246 * @param expected_num number of tokens expected 3247 * @return #GNUNET_YES on success 3248 */ 3249 static enum GNUNET_GenericReturnValue 3250 find_valid_input_tokens ( 3251 struct PayContext *pc, 3252 const struct TALER_MERCHANT_ContractTokenFamily *family, 3253 unsigned int index, 3254 unsigned int expected_num) 3255 { 3256 unsigned int num_validated = 0; 3257 struct GNUNET_TIME_Timestamp now 3258 = GNUNET_TIME_timestamp_get (); 3259 const struct TALER_MERCHANT_ContractTokenFamilyKey *kig = NULL; 3260 3261 for (unsigned int j = 0; j < expected_num; j++) 3262 { 3263 struct TokenUseConfirmation *tuc 3264 = &pc->parse_pay.tokens[index + j]; 3265 const struct TALER_MERCHANT_ContractTokenFamilyKey *key = NULL; 3266 3267 for (unsigned int i = 0; i<family->keys_len; i++) 3268 { 3269 const struct TALER_MERCHANT_ContractTokenFamilyKey *ki 3270 = &family->keys[i]; 3271 3272 if (0 == 3273 GNUNET_memcmp (&ki->pub.public_key->pub_key_hash, 3274 &tuc->h_issue.hash)) 3275 { 3276 if (GNUNET_TIME_timestamp_cmp (ki->valid_after, 3277 >, 3278 now) || 3279 GNUNET_TIME_timestamp_cmp (ki->valid_before, 3280 <=, 3281 now)) 3282 { 3283 /* We have a match, but not in the current validity period */ 3284 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 3285 "Public key %s currently not valid\n", 3286 GNUNET_h2s (&ki->pub.public_key->pub_key_hash)); 3287 kig = ki; 3288 continue; 3289 } 3290 key = ki; 3291 break; 3292 } 3293 } 3294 if (NULL == key) 3295 { 3296 if (NULL != kig) 3297 { 3298 char start_str[128]; 3299 char end_str[128]; 3300 char emsg[350]; 3301 3302 GNUNET_snprintf (start_str, 3303 sizeof (start_str), 3304 "%s", 3305 GNUNET_STRINGS_timestamp_to_string (kig->valid_after)); 3306 GNUNET_snprintf (end_str, 3307 sizeof (end_str), 3308 "%s", 3309 GNUNET_STRINGS_timestamp_to_string (kig->valid_before)) 3310 ; 3311 /* FIXME: use more specific EC */ 3312 GNUNET_snprintf (emsg, 3313 sizeof (emsg), 3314 "Token is only valid from %s to %s", 3315 start_str, 3316 end_str); 3317 pay_end (pc, 3318 TALER_MHD_reply_with_error ( 3319 pc->connection, 3320 MHD_HTTP_GONE, 3321 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_OFFER_EXPIRED, 3322 emsg)); 3323 return GNUNET_NO; 3324 } 3325 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 3326 "Input token supplied for public key %s that is not acceptable\n", 3327 GNUNET_h2s (&tuc->h_issue.hash)); 3328 GNUNET_break_op (0); 3329 pay_end (pc, 3330 TALER_MHD_reply_with_error ( 3331 pc->connection, 3332 MHD_HTTP_BAD_REQUEST, 3333 TALER_EC_MERCHANT_GENERIC_TOKEN_KEY_UNKNOWN, 3334 NULL)); 3335 return GNUNET_NO; 3336 } 3337 if (GNUNET_OK != 3338 TALER_token_issue_verify (&tuc->pub, 3339 &key->pub, 3340 &tuc->unblinded_sig)) 3341 { 3342 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 3343 "Input token for public key with valid_after " 3344 "`%s' has invalid issue signature\n", 3345 GNUNET_TIME_timestamp2s (key->valid_after)); 3346 GNUNET_break (0); 3347 pay_end (pc, 3348 TALER_MHD_reply_with_error ( 3349 pc->connection, 3350 MHD_HTTP_BAD_REQUEST, 3351 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_TOKEN_ISSUE_SIG_INVALID, 3352 NULL)); 3353 return GNUNET_NO; 3354 } 3355 3356 if (GNUNET_OK != 3357 TALER_wallet_token_use_verify (&pc->check_contract.h_contract_terms, 3358 &pc->parse_wallet_data.h_wallet_data, 3359 &tuc->pub, 3360 &tuc->sig)) 3361 { 3362 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 3363 "Input token for public key with valid_before " 3364 "`%s' has invalid use signature\n", 3365 GNUNET_TIME_timestamp2s (key->valid_before)); 3366 GNUNET_break (0); 3367 pay_end (pc, 3368 TALER_MHD_reply_with_error ( 3369 pc->connection, 3370 MHD_HTTP_BAD_REQUEST, 3371 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_TOKEN_USE_SIG_INVALID, 3372 NULL)); 3373 return GNUNET_NO; 3374 } 3375 3376 num_validated++; 3377 } 3378 3379 if (num_validated != expected_num) 3380 { 3381 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 3382 "Expected %d tokens for family %s, but found %d\n", 3383 expected_num, 3384 family->slug, 3385 num_validated); 3386 GNUNET_break (0); 3387 pay_end (pc, 3388 TALER_MHD_reply_with_error ( 3389 pc->connection, 3390 MHD_HTTP_BAD_REQUEST, 3391 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_TOKEN_COUNT_MISMATCH, 3392 NULL)); 3393 return GNUNET_NO; 3394 } 3395 return GNUNET_YES; 3396 } 3397 3398 3399 /** 3400 * Check if an output token of the given @a tfk is mandatory, or if 3401 * wallets are allowed to simply not support it and still proceed. 3402 * 3403 * @param tfk token family kind to check 3404 * @return true if such outputs are mandatory and wallets must supply 3405 * the corresponding blinded input 3406 */ 3407 /* FIXME: this function belongs into a lower-level lib! */ 3408 static bool 3409 test_tfk_mandatory (enum TALER_MERCHANTDB_TokenFamilyKind tfk) 3410 { 3411 switch (tfk) 3412 { 3413 case TALER_MERCHANTDB_TFK_Discount: 3414 return false; 3415 case TALER_MERCHANTDB_TFK_Subscription: 3416 return true; 3417 } 3418 GNUNET_break (0); 3419 return false; 3420 } 3421 3422 3423 /** 3424 * Sign the tokens provided by the wallet for a particular @a key. 3425 * 3426 * @param[in,out] pc reference for payment we are processing 3427 * @param key token family data 3428 * @param priv private key to use to sign with 3429 * @param mandatory true if the token must exist, if false 3430 * and the client did not provide an envelope, that's OK and 3431 * we just also skimp on the signature 3432 * @param index offset in the token envelope array (from other families) 3433 * @param expected_num number of tokens of this type that we should create 3434 * @return #GNUNET_NO on failure 3435 * #GNUNET_OK on success 3436 */ 3437 static enum GNUNET_GenericReturnValue 3438 sign_token_envelopes ( 3439 struct PayContext *pc, 3440 const struct TALER_MERCHANT_ContractTokenFamilyKey *key, 3441 const struct TALER_TokenIssuePrivateKey *priv, 3442 bool mandatory, 3443 unsigned int index, 3444 unsigned int expected_num) 3445 { 3446 unsigned int num_signed = 0; 3447 3448 for (unsigned int j = 0; j<expected_num; j++) 3449 { 3450 unsigned int pos = index + j; 3451 const struct TokenEnvelope *env 3452 = &pc->parse_wallet_data.token_envelopes[pos]; 3453 struct SignedOutputToken *output 3454 = &pc->output_tokens[pos]; 3455 3456 if ( (pos >= pc->parse_wallet_data.token_envelopes_cnt) || 3457 (pos >= pc->output_tokens_len) ) 3458 { 3459 GNUNET_assert (0); /* this should not happen */ 3460 return GNUNET_NO; 3461 } 3462 if (NULL == env->blinded_token.blinded_pub) 3463 { 3464 if (! mandatory) 3465 continue; 3466 3467 /* mandatory token families require a token envelope. */ 3468 GNUNET_break_op (0); 3469 pay_end (pc, 3470 TALER_MHD_reply_with_error ( 3471 pc->connection, 3472 MHD_HTTP_BAD_REQUEST, 3473 TALER_EC_GENERIC_PARAMETER_MALFORMED, 3474 "Token envelope for mandatory token family missing")); 3475 return GNUNET_NO; 3476 } 3477 TALER_token_issue_sign (priv, 3478 &env->blinded_token, 3479 &output->sig); 3480 output->h_issue.hash 3481 = key->pub.public_key->pub_key_hash; 3482 num_signed++; 3483 } 3484 3485 if (mandatory && 3486 (num_signed != expected_num) ) 3487 { 3488 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 3489 "Expected %d token envelopes for public key with valid_after " 3490 "'%s', but found %d\n", 3491 expected_num, 3492 GNUNET_TIME_timestamp2s (key->valid_after), 3493 num_signed); 3494 GNUNET_break (0); 3495 pay_end (pc, 3496 TALER_MHD_reply_with_error ( 3497 pc->connection, 3498 MHD_HTTP_BAD_REQUEST, 3499 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_TOKEN_ENVELOPE_COUNT_MISMATCH, 3500 NULL)); 3501 return GNUNET_NO; 3502 } 3503 3504 return GNUNET_OK; 3505 } 3506 3507 3508 /** 3509 * Find the family entry for the family of the given @a slug 3510 * in @a pc. 3511 * 3512 * @param[in] pc payment context to search 3513 * @param slug slug to search for 3514 * @return NULL if @a slug was not found 3515 */ 3516 static const struct TALER_MERCHANT_ContractTokenFamily * 3517 find_family (const struct PayContext *pc, 3518 const char *slug) 3519 { 3520 for (unsigned int i = 0; 3521 i < pc->check_contract.contract_terms->details.v1.token_authorities_len; 3522 i++) 3523 { 3524 const struct TALER_MERCHANT_ContractTokenFamily *tfi 3525 = &pc->check_contract.contract_terms->details.v1.token_authorities[i]; 3526 3527 if (0 == strcmp (tfi->slug, 3528 slug)) 3529 { 3530 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 3531 "Token family %s found with %u keys\n", 3532 slug, 3533 tfi->keys_len); 3534 return tfi; 3535 } 3536 } 3537 return NULL; 3538 } 3539 3540 3541 /** 3542 * Handle contract output of type TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN. 3543 * Looks up the token family, loads the matching private key, 3544 * and signs the corresponding token envelopes from the wallet. 3545 * 3546 * @param pc context for the pay request 3547 * @param output contract output we need to process 3548 * @param output_index index of this output in the contract's outputs array 3549 * @return #GNUNET_OK on success, #GNUNET_NO if an error was encountered 3550 */ 3551 static enum GNUNET_GenericReturnValue 3552 handle_output_token (struct PayContext *pc, 3553 const struct TALER_MERCHANT_ContractOutput *output, 3554 unsigned int output_index) 3555 { 3556 const struct TALER_MERCHANT_ContractTokenFamily *family; 3557 struct TALER_MERCHANT_ContractTokenFamilyKey *key; 3558 struct TALER_MERCHANTDB_TokenFamilyKeyDetails details; 3559 enum GNUNET_DB_QueryStatus qs; 3560 bool mandatory; 3561 3562 /* Locate token family in the contract. 3563 This should ever fail as this invariant should 3564 have been checked when the contract was created. */ 3565 family = find_family (pc, 3566 output->details.token.token_family_slug); 3567 if (NULL == family) 3568 { 3569 /* This "should never happen", so treat it as an internal error */ 3570 GNUNET_break (0); 3571 pay_end (pc, 3572 TALER_MHD_reply_with_error ( 3573 pc->connection, 3574 MHD_HTTP_INTERNAL_SERVER_ERROR, 3575 TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, 3576 "token family not found in order")); 3577 return GNUNET_SYSERR; 3578 } 3579 3580 /* Check the key_index field from the output. */ 3581 if (output->details.token.key_index >= family->keys_len) 3582 { 3583 /* Also "should never happen", contract was presumably validated on insert */ 3584 GNUNET_break (0); 3585 pay_end (pc, 3586 TALER_MHD_reply_with_error ( 3587 pc->connection, 3588 MHD_HTTP_INTERNAL_SERVER_ERROR, 3589 TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, 3590 "key index invalid for token family")); 3591 return GNUNET_SYSERR; 3592 } 3593 3594 /* Pick the correct key inside that family. */ 3595 key = &family->keys[output->details.token.key_index]; 3596 3597 /* Fetch the private key from the DB for the merchant instance and 3598 * this particular family/time interval. */ 3599 qs = TMH_db->lookup_token_family_key ( 3600 TMH_db->cls, 3601 pc->hc->instance->settings.id, 3602 family->slug, 3603 pc->check_contract.contract_terms->timestamp, 3604 pc->check_contract.contract_terms->pay_deadline, 3605 &details); 3606 switch (qs) 3607 { 3608 case GNUNET_DB_STATUS_HARD_ERROR: 3609 case GNUNET_DB_STATUS_SOFT_ERROR: 3610 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 3611 "Database error looking up token-family key for %s\n", 3612 family->slug); 3613 GNUNET_break (0); 3614 pay_end (pc, 3615 TALER_MHD_reply_with_error ( 3616 pc->connection, 3617 MHD_HTTP_INTERNAL_SERVER_ERROR, 3618 TALER_EC_GENERIC_DB_FETCH_FAILED, 3619 NULL)); 3620 return GNUNET_NO; 3621 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 3622 GNUNET_log ( 3623 GNUNET_ERROR_TYPE_ERROR, 3624 "Token-family key for %s not found at [%llu,%llu]\n", 3625 family->slug, 3626 (unsigned long long) 3627 pc->check_contract.contract_terms->timestamp.abs_time.abs_value_us, 3628 (unsigned long long) 3629 pc->check_contract.contract_terms->pay_deadline.abs_time.abs_value_us 3630 ); 3631 GNUNET_break (0); 3632 pay_end (pc, 3633 TALER_MHD_reply_with_error ( 3634 pc->connection, 3635 MHD_HTTP_NOT_FOUND, 3636 TALER_EC_MERCHANT_GENERIC_TOKEN_KEY_UNKNOWN, 3637 family->slug)); 3638 return GNUNET_NO; 3639 3640 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 3641 break; 3642 } 3643 GNUNET_assert (NULL != details.priv.private_key); 3644 GNUNET_free (details.token_family.slug); 3645 GNUNET_free (details.token_family.name); 3646 GNUNET_free (details.token_family.description); 3647 json_decref (details.token_family.description_i18n); 3648 GNUNET_CRYPTO_blind_sign_pub_decref (details.pub.public_key); 3649 GNUNET_free (details.token_family.cipher_spec); 3650 3651 /* Depending on the token family, decide if the token envelope 3652 * is mandatory or optional. (Simplified logic here: adapt as needed.) */ 3653 mandatory = test_tfk_mandatory (details.token_family.kind); 3654 /* Actually sign the number of token envelopes specified in 'count'. 3655 * 'output_index' is the offset into the parse_wallet_data arrays. */ 3656 if (GNUNET_OK != 3657 sign_token_envelopes (pc, 3658 key, 3659 &details.priv, 3660 mandatory, 3661 output_index, 3662 output->details.token.count)) 3663 { 3664 /* sign_token_envelopes() already queued up an error via pay_end() */ 3665 GNUNET_break_op (0); 3666 return GNUNET_NO; 3667 } 3668 GNUNET_CRYPTO_blind_sign_priv_decref (details.priv.private_key); 3669 return GNUNET_OK; 3670 } 3671 3672 3673 #ifdef HAVE_DONAU_DONAU_SERVICE_H 3674 /** 3675 * Handle checks for contract output of type TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT. 3676 * For now, this does nothing and simply returns #GNUNET_OK. 3677 * 3678 * @param pc context for the pay request 3679 * @param output the contract output describing the donation receipt requirement 3680 * @return #GNUNET_OK on success, 3681 * #GNUNET_NO if an error was already queued 3682 */ 3683 static enum GNUNET_GenericReturnValue 3684 handle_output_donation_receipt ( 3685 struct PayContext *pc, 3686 const struct TALER_MERCHANT_ContractOutput *output) 3687 { 3688 enum GNUNET_GenericReturnValue ret; 3689 3690 ret = DONAU_get_donation_amount_from_bkps ( 3691 pc->parse_wallet_data.donau_keys, 3692 pc->parse_wallet_data.bkps, 3693 pc->parse_wallet_data.num_bkps, 3694 pc->parse_wallet_data.donau.donation_year, 3695 &pc->parse_wallet_data.donation_amount); 3696 switch (ret) 3697 { 3698 case GNUNET_SYSERR: 3699 GNUNET_break (0); 3700 pay_end (pc, 3701 TALER_MHD_reply_with_error ( 3702 pc->connection, 3703 MHD_HTTP_INTERNAL_SERVER_ERROR, 3704 TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, 3705 NULL)); 3706 return GNUNET_NO; 3707 case GNUNET_NO: 3708 GNUNET_break_op (0); 3709 pay_end (pc, 3710 TALER_MHD_reply_with_error ( 3711 pc->connection, 3712 MHD_HTTP_BAD_REQUEST, 3713 TALER_EC_GENERIC_PARAMETER_MALFORMED, 3714 "inconsistent bkps / donau keys")); 3715 return GNUNET_NO; 3716 case GNUNET_OK: 3717 break; 3718 } 3719 3720 if (GNUNET_OK != 3721 TALER_amount_cmp_currency (&pc->parse_wallet_data.donation_amount, 3722 &output->details.donation_receipt.amount)) 3723 { 3724 GNUNET_break_op (0); 3725 pay_end (pc, 3726 TALER_MHD_reply_with_error ( 3727 pc->connection, 3728 MHD_HTTP_BAD_REQUEST, 3729 TALER_EC_GENERIC_CURRENCY_MISMATCH, 3730 output->details.donation_receipt.amount.currency)); 3731 return GNUNET_NO; 3732 } 3733 3734 if (0 != 3735 TALER_amount_cmp (&pc->parse_wallet_data.donation_amount, 3736 &output->details.donation_receipt.amount)) 3737 { 3738 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 3739 "Wallet amount: %s\n", 3740 TALER_amount2s (&pc->parse_wallet_data.donation_amount)); 3741 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 3742 "Donation receipt amount: %s\n", 3743 TALER_amount2s (&output->details.donation_receipt.amount)); 3744 GNUNET_break_op (0); 3745 pay_end (pc, 3746 TALER_MHD_reply_with_error ( 3747 pc->connection, 3748 MHD_HTTP_CONFLICT, 3749 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_DONATION_AMOUNT_MISMATCH, 3750 "donation amount mismatch")); 3751 return GNUNET_NO; 3752 } 3753 { 3754 struct TALER_Amount receipts_to_date; 3755 3756 if (0 > 3757 TALER_amount_add (&receipts_to_date, 3758 &pc->parse_wallet_data.charity_receipts_to_date, 3759 &pc->parse_wallet_data.donation_amount)) 3760 { 3761 GNUNET_break (0); 3762 pay_end (pc, 3763 TALER_MHD_reply_with_error (pc->connection, 3764 MHD_HTTP_INTERNAL_SERVER_ERROR, 3765 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW, 3766 "adding donation amount")); 3767 return GNUNET_NO; 3768 } 3769 3770 if (1 == 3771 TALER_amount_cmp (&receipts_to_date, 3772 &pc->parse_wallet_data.charity_max_per_year)) 3773 { 3774 GNUNET_break_op (0); 3775 pay_end (pc, 3776 TALER_MHD_reply_with_error (pc->connection, 3777 MHD_HTTP_CONFLICT, 3778 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_DONATION_AMOUNT_MISMATCH, 3779 "donation limit exceeded")); 3780 return GNUNET_NO; 3781 } 3782 pc->parse_wallet_data.charity_receipts_to_date = receipts_to_date; 3783 } 3784 return GNUNET_OK; 3785 } 3786 3787 3788 #endif /* HAVE_DONAU_DONAU_SERVICE_H */ 3789 3790 3791 /** 3792 * Count tokens produced by an output. 3793 * 3794 * @param pc pay context 3795 * @param output output to consider 3796 * @returns number of output tokens 3797 */ 3798 static unsigned int 3799 count_output_tokens (const struct PayContext *pc, 3800 const struct TALER_MERCHANT_ContractOutput *output) 3801 { 3802 switch (output->type) 3803 { 3804 case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID: 3805 GNUNET_assert (0); 3806 break; 3807 case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN: 3808 return output->details.token.count; 3809 case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT: 3810 #ifdef HAVE_DONAU_DONAU_SERVICE_H 3811 return pc->parse_wallet_data.num_bkps; 3812 #else 3813 return 0; 3814 #endif 3815 } 3816 /* Not reached. */ 3817 GNUNET_assert (0); 3818 } 3819 3820 3821 /** 3822 * Validate tokens and token envelopes. First, we check if all tokens listed 3823 * in the 'inputs' array of the selected choice are present in the 'tokens' 3824 * array of the request. Then, we validate the signatures of each provided 3825 * token. 3826 * 3827 * @param[in,out] pc context we use to handle the payment 3828 */ 3829 static void 3830 phase_validate_tokens (struct PayContext *pc) 3831 { 3832 /* We haven't seen a donau output yet. */ 3833 pc->validate_tokens.donau_output_index = -1; 3834 3835 switch (pc->check_contract.contract_terms->version) 3836 { 3837 case TALER_MERCHANT_CONTRACT_VERSION_0: 3838 /* No tokens to validate */ 3839 pc->phase = PP_COMPUTE_MONEY_POTS; 3840 pc->validate_tokens.max_fee 3841 = pc->check_contract.contract_terms->details.v0.max_fee; 3842 pc->validate_tokens.brutto 3843 = pc->check_contract.contract_terms->details.v0.brutto; 3844 break; 3845 case TALER_MERCHANT_CONTRACT_VERSION_1: 3846 { 3847 const struct TALER_MERCHANT_ContractChoice *selected 3848 = &pc->check_contract.contract_terms->details.v1.choices[ 3849 pc->parse_wallet_data.choice_index]; 3850 unsigned int output_off; 3851 unsigned int cnt; 3852 3853 pc->validate_tokens.max_fee = selected->max_fee; 3854 pc->validate_tokens.brutto = selected->amount; 3855 3856 for (unsigned int i = 0; i<selected->inputs_len; i++) 3857 { 3858 const struct TALER_MERCHANT_ContractInput *input 3859 = &selected->inputs[i]; 3860 const struct TALER_MERCHANT_ContractTokenFamily *family; 3861 3862 switch (input->type) 3863 { 3864 case TALER_MERCHANT_CONTRACT_INPUT_TYPE_INVALID: 3865 GNUNET_break (0); 3866 pay_end (pc, 3867 TALER_MHD_reply_with_error ( 3868 pc->connection, 3869 MHD_HTTP_BAD_REQUEST, 3870 TALER_EC_GENERIC_PARAMETER_MALFORMED, 3871 "input token type not valid")); 3872 return; 3873 #if FUTURE 3874 case TALER_MERCHANT_CONTRACT_INPUT_TYPE_COIN: 3875 GNUNET_break (0); 3876 pay_end (pc, 3877 TALER_MHD_reply_with_error ( 3878 pc->connection, 3879 MHD_HTTP_NOT_IMPLEMENTED, 3880 TALER_EC_MERCHANT_GENERIC_FEATURE_NOT_AVAILABLE, 3881 "token type not yet supported")); 3882 return; 3883 #endif 3884 case TALER_MERCHANT_CONTRACT_INPUT_TYPE_TOKEN: 3885 family = find_family (pc, 3886 input->details.token.token_family_slug); 3887 if (NULL == family) 3888 { 3889 /* this should never happen, since the choices and 3890 token families are validated on insert. */ 3891 GNUNET_break (0); 3892 pay_end (pc, 3893 TALER_MHD_reply_with_error ( 3894 pc->connection, 3895 MHD_HTTP_INTERNAL_SERVER_ERROR, 3896 TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, 3897 "token family not found in order")); 3898 return; 3899 } 3900 if (GNUNET_NO == 3901 find_valid_input_tokens (pc, 3902 family, 3903 i, 3904 input->details.token.count)) 3905 { 3906 /* Error is already scheduled from find_valid_input_token. */ 3907 return; 3908 } 3909 } 3910 } 3911 3912 /* calculate pc->output_tokens_len */ 3913 output_off = 0; 3914 for (unsigned int i = 0; i<selected->outputs_len; i++) 3915 { 3916 const struct TALER_MERCHANT_ContractOutput *output 3917 = &selected->outputs[i]; 3918 3919 switch (output->type) 3920 { 3921 case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID: 3922 GNUNET_assert (0); 3923 break; 3924 case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN: 3925 cnt = output->details.token.count; 3926 if (output_off + cnt < output_off) 3927 { 3928 GNUNET_break_op (0); 3929 pay_end (pc, 3930 TALER_MHD_reply_with_error ( 3931 pc->connection, 3932 MHD_HTTP_BAD_REQUEST, 3933 TALER_EC_GENERIC_PARAMETER_MALFORMED, 3934 "output token counter overflow")); 3935 return; 3936 } 3937 output_off += cnt; 3938 break; 3939 case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT: 3940 /* check that this output type appears at most once */ 3941 if (pc->validate_tokens.donau_output_index >= 0) 3942 { 3943 /* This should have been prevented when the 3944 contract was initially created */ 3945 GNUNET_break (0); 3946 pay_end (pc, 3947 TALER_MHD_reply_with_error ( 3948 pc->connection, 3949 MHD_HTTP_INTERNAL_SERVER_ERROR, 3950 TALER_EC_GENERIC_DB_INVARIANT_FAILURE, 3951 "two donau output sets in same contract")); 3952 return; 3953 } 3954 pc->validate_tokens.donau_output_index = i; 3955 #ifdef HAVE_DONAU_DONAU_SERVICE_H 3956 if (output_off + pc->parse_wallet_data.num_bkps < output_off) 3957 { 3958 GNUNET_break_op (0); 3959 pay_end (pc, 3960 TALER_MHD_reply_with_error ( 3961 pc->connection, 3962 MHD_HTTP_BAD_REQUEST, 3963 TALER_EC_GENERIC_PARAMETER_MALFORMED, 3964 "output token counter overflow")); 3965 return; 3966 } 3967 output_off += pc->parse_wallet_data.num_bkps; 3968 #endif 3969 break; 3970 } 3971 } 3972 3973 3974 pc->output_tokens_len = output_off; 3975 pc->output_tokens 3976 = GNUNET_new_array (pc->output_tokens_len, 3977 struct SignedOutputToken); 3978 3979 /* calculate pc->output_tokens[].output_index */ 3980 output_off = 0; 3981 for (unsigned int i = 0; i<selected->outputs_len; i++) 3982 { 3983 const struct TALER_MERCHANT_ContractOutput *output 3984 = &selected->outputs[i]; 3985 cnt = count_output_tokens (pc, 3986 output); 3987 for (unsigned int j = 0; j<cnt; j++) 3988 pc->output_tokens[output_off + j].output_index = i; 3989 output_off += cnt; 3990 } 3991 3992 /* compute non-donau outputs */ 3993 output_off = 0; 3994 for (unsigned int i = 0; i<selected->outputs_len; i++) 3995 { 3996 const struct TALER_MERCHANT_ContractOutput *output 3997 = &selected->outputs[i]; 3998 3999 switch (output->type) 4000 { 4001 case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID: 4002 GNUNET_assert (0); 4003 break; 4004 case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN: 4005 cnt = output->details.token.count; 4006 GNUNET_assert (output_off + cnt 4007 <= pc->output_tokens_len); 4008 if (GNUNET_OK != 4009 handle_output_token (pc, 4010 output, 4011 output_off)) 4012 { 4013 /* Error is already scheduled from handle_output_token. */ 4014 return; 4015 } 4016 output_off += cnt; 4017 break; 4018 case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT: 4019 #ifndef HAVE_DONAU_DONAU_SERVICE_H 4020 /* We checked at parse time, and 4021 wallet didn't want donau, so OK! */ 4022 return; 4023 #else 4024 if ( (0 != pc->parse_wallet_data.num_bkps) && 4025 (GNUNET_OK != 4026 handle_output_donation_receipt (pc, 4027 output)) ) 4028 { 4029 /* Error is already scheduled from handle_output_donation_receipt. */ 4030 return; 4031 } 4032 output_off += pc->parse_wallet_data.num_bkps; 4033 continue; 4034 #endif 4035 } /* switch on output token */ 4036 } /* for all output token types */ 4037 } /* case contract v1 */ 4038 break; 4039 } /* switch on contract type */ 4040 4041 for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++) 4042 { 4043 const struct DepositConfirmation *dc = &pc->parse_pay.dc[i]; 4044 4045 if (GNUNET_OK != 4046 TALER_amount_cmp_currency (&dc->cdd.amount, 4047 &pc->validate_tokens.brutto)) 4048 { 4049 GNUNET_break_op (0); 4050 pay_end (pc, 4051 TALER_MHD_reply_with_error ( 4052 pc->connection, 4053 MHD_HTTP_CONFLICT, 4054 TALER_EC_MERCHANT_GENERIC_CURRENCY_MISMATCH, 4055 pc->validate_tokens.brutto.currency)); 4056 return; 4057 } 4058 } 4059 4060 pc->phase = PP_COMPUTE_MONEY_POTS; 4061 } 4062 4063 4064 /** 4065 * Function called with information about a coin that was deposited. 4066 * Checks if this coin is in our list of deposits as well. 4067 * 4068 * @param cls closure with our `struct PayContext *` 4069 * @param deposit_serial which deposit operation is this about 4070 * @param exchange_url URL of the exchange that issued the coin 4071 * @param h_wire hash of merchant's wire details 4072 * @param deposit_timestamp when was the deposit made 4073 * @param amount_with_fee amount the exchange will deposit for this coin 4074 * @param deposit_fee fee the exchange will charge for this coin 4075 * @param coin_pub public key of the coin 4076 */ 4077 static void 4078 deposit_paid_check ( 4079 void *cls, 4080 uint64_t deposit_serial, 4081 const char *exchange_url, 4082 const struct TALER_MerchantWireHashP *h_wire, 4083 struct GNUNET_TIME_Timestamp deposit_timestamp, 4084 const struct TALER_Amount *amount_with_fee, 4085 const struct TALER_Amount *deposit_fee, 4086 const struct TALER_CoinSpendPublicKeyP *coin_pub) 4087 { 4088 struct PayContext *pc = cls; 4089 4090 for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++) 4091 { 4092 struct DepositConfirmation *dci = &pc->parse_pay.dc[i]; 4093 4094 if ( (0 == 4095 GNUNET_memcmp (&dci->cdd.coin_pub, 4096 coin_pub)) && 4097 (0 == 4098 strcmp (dci->exchange_url, 4099 exchange_url)) && 4100 (GNUNET_YES == 4101 TALER_amount_cmp_currency (&dci->cdd.amount, 4102 amount_with_fee)) && 4103 (0 == 4104 TALER_amount_cmp (&dci->cdd.amount, 4105 amount_with_fee)) ) 4106 { 4107 dci->matched_in_db = true; 4108 break; 4109 } 4110 } 4111 } 4112 4113 4114 /** 4115 * Function called with information about a token that was spent. 4116 * FIXME: Replace this with a more specific function for this cb 4117 * 4118 * @param cls closure with `struct PayContext *` 4119 * @param spent_token_serial "serial" of the spent token unused 4120 * @param h_contract_terms hash of the contract terms unused 4121 * @param h_issue_pub hash of the token issue public key unused 4122 * @param use_pub public key of the token 4123 * @param use_sig signature of the token 4124 * @param issue_sig signature of the token issue 4125 */ 4126 static void 4127 input_tokens_paid_check ( 4128 void *cls, 4129 uint64_t spent_token_serial, 4130 const struct TALER_PrivateContractHashP *h_contract_terms, 4131 const struct TALER_TokenIssuePublicKeyHashP *h_issue_pub, 4132 const struct TALER_TokenUsePublicKeyP *use_pub, 4133 const struct TALER_TokenUseSignatureP *use_sig, 4134 const struct TALER_TokenIssueSignature *issue_sig) 4135 { 4136 struct PayContext *pc = cls; 4137 4138 for (size_t i = 0; i<pc->parse_pay.tokens_cnt; i++) 4139 { 4140 struct TokenUseConfirmation *tuc = &pc->parse_pay.tokens[i]; 4141 4142 if ( (0 == 4143 GNUNET_memcmp (&tuc->pub, 4144 use_pub)) && 4145 (0 == 4146 GNUNET_memcmp (&tuc->sig, 4147 use_sig)) && 4148 (0 == 4149 GNUNET_memcmp (&tuc->unblinded_sig, 4150 issue_sig)) ) 4151 { 4152 tuc->found_in_db = true; 4153 break; 4154 } 4155 } 4156 } 4157 4158 4159 /** 4160 * Small helper function to append an output token signature from db 4161 * 4162 * @param cls closure with `struct PayContext *` 4163 * @param h_issue hash of the token 4164 * @param sig signature of the token 4165 */ 4166 static void 4167 append_output_token_sig (void *cls, 4168 struct GNUNET_HashCode *h_issue, 4169 struct GNUNET_CRYPTO_BlindedSignature *sig) 4170 { 4171 struct PayContext *pc = cls; 4172 struct TALER_MERCHANT_ContractChoice *choice; 4173 const struct TALER_MERCHANT_ContractOutput *output; 4174 struct SignedOutputToken out; 4175 unsigned int cnt; 4176 4177 GNUNET_assert (TALER_MERCHANT_CONTRACT_VERSION_1 == 4178 pc->check_contract.contract_terms->version); 4179 choice = &pc->check_contract.contract_terms->details.v1 4180 .choices[pc->parse_wallet_data.choice_index]; 4181 output = &choice->outputs[pc->output_index_gen]; 4182 cnt = count_output_tokens (pc, 4183 output); 4184 out.output_index = pc->output_index_gen; 4185 out.h_issue.hash = *h_issue; 4186 out.sig.signature = sig; 4187 GNUNET_CRYPTO_blind_sig_incref (sig); 4188 GNUNET_array_append (pc->output_tokens, 4189 pc->output_tokens_len, 4190 out); 4191 /* Go to next output once we've output all tokens for the current one. */ 4192 pc->output_token_cnt++; 4193 if (pc->output_token_cnt >= cnt) 4194 { 4195 pc->output_token_cnt = 0; 4196 pc->output_index_gen++; 4197 } 4198 } 4199 4200 4201 /** 4202 * Handle case where contract was already paid. Either decides 4203 * the payment is idempotent, or refunds the excess payment. 4204 * 4205 * @param[in,out] pc context we use to handle the payment 4206 */ 4207 static void 4208 phase_contract_paid (struct PayContext *pc) 4209 { 4210 json_t *refunds; 4211 bool unmatched = false; 4212 4213 { 4214 enum GNUNET_DB_QueryStatus qs; 4215 4216 qs = TMH_db->lookup_deposits_by_order (TMH_db->cls, 4217 pc->check_contract.order_serial, 4218 &deposit_paid_check, 4219 pc); 4220 /* Since orders with choices can have a price of zero, 4221 0 is also a valid query state */ 4222 if (qs < 0) 4223 { 4224 GNUNET_break (0); 4225 pay_end (pc, 4226 TALER_MHD_reply_with_error ( 4227 pc->connection, 4228 MHD_HTTP_INTERNAL_SERVER_ERROR, 4229 TALER_EC_GENERIC_DB_FETCH_FAILED, 4230 "lookup_deposits_by_order")); 4231 return; 4232 } 4233 } 4234 for (size_t i = 0; 4235 i<pc->parse_pay.coins_cnt && ! unmatched; 4236 i++) 4237 { 4238 struct DepositConfirmation *dci = &pc->parse_pay.dc[i]; 4239 4240 if (! dci->matched_in_db) 4241 unmatched = true; 4242 } 4243 /* Check if provided input tokens match token in the database */ 4244 { 4245 enum GNUNET_DB_QueryStatus qs; 4246 4247 /* FIXME-Optimization: Maybe use h_contract instead of order_serial here? */ 4248 qs = TMH_db->lookup_spent_tokens_by_order (TMH_db->cls, 4249 pc->check_contract.order_serial, 4250 &input_tokens_paid_check, 4251 pc); 4252 4253 if (qs < 0) 4254 { 4255 GNUNET_break (0); 4256 pay_end (pc, 4257 TALER_MHD_reply_with_error ( 4258 pc->connection, 4259 MHD_HTTP_INTERNAL_SERVER_ERROR, 4260 TALER_EC_GENERIC_DB_FETCH_FAILED, 4261 "lookup_spent_tokens_by_order")); 4262 return; 4263 } 4264 } 4265 for (size_t i = 0; i<pc->parse_pay.tokens_cnt && ! unmatched; i++) 4266 { 4267 struct TokenUseConfirmation *tuc = &pc->parse_pay.tokens[i]; 4268 4269 if (! tuc->found_in_db) 4270 unmatched = true; 4271 } 4272 4273 /* In this part we are fetching token_sigs related output */ 4274 if (! unmatched) 4275 { 4276 /* Everything fine, idempotent request, generate response immediately */ 4277 enum GNUNET_DB_QueryStatus qs; 4278 4279 pc->output_index_gen = 0; 4280 qs = TMH_db->select_order_blinded_sigs ( 4281 TMH_db->cls, 4282 pc->order_id, 4283 &append_output_token_sig, 4284 pc); 4285 if (0 > qs) 4286 { 4287 GNUNET_break (0); 4288 pay_end (pc, 4289 TALER_MHD_reply_with_error ( 4290 pc->connection, 4291 MHD_HTTP_INTERNAL_SERVER_ERROR, 4292 TALER_EC_GENERIC_DB_FETCH_FAILED, 4293 "select_order_blinded_sigs")); 4294 return; 4295 } 4296 4297 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 4298 "Idempotent pay request for order `%s', signing again\n", 4299 pc->order_id); 4300 pc->phase = PP_SUCCESS_RESPONSE; 4301 return; 4302 } 4303 /* Conflict, double-payment detected! */ 4304 /* FIXME-#8674: What should we do with input tokens? 4305 Currently there is no refund for tokens. */ 4306 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 4307 "Client attempted to pay extra for already paid order `%s'\n", 4308 pc->order_id); 4309 refunds = json_array (); 4310 GNUNET_assert (NULL != refunds); 4311 for (size_t i = 0; i<pc->parse_pay.coins_cnt; i++) 4312 { 4313 struct DepositConfirmation *dci = &pc->parse_pay.dc[i]; 4314 struct TALER_MerchantSignatureP merchant_sig; 4315 4316 if (dci->matched_in_db) 4317 continue; 4318 TALER_merchant_refund_sign (&dci->cdd.coin_pub, 4319 &pc->check_contract.h_contract_terms, 4320 0, /* rtransaction id */ 4321 &dci->cdd.amount, 4322 &pc->hc->instance->merchant_priv, 4323 &merchant_sig); 4324 GNUNET_assert ( 4325 0 == 4326 json_array_append_new ( 4327 refunds, 4328 GNUNET_JSON_PACK ( 4329 GNUNET_JSON_pack_data_auto ( 4330 "coin_pub", 4331 &dci->cdd.coin_pub), 4332 GNUNET_JSON_pack_data_auto ( 4333 "merchant_sig", 4334 &merchant_sig), 4335 TALER_JSON_pack_amount ("amount", 4336 &dci->cdd.amount), 4337 GNUNET_JSON_pack_uint64 ("rtransaction_id", 4338 0)))); 4339 } 4340 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 4341 "Generating JSON response with code %d\n", 4342 (int) TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_ALREADY_PAID); 4343 pay_end (pc, 4344 TALER_MHD_REPLY_JSON_PACK ( 4345 pc->connection, 4346 MHD_HTTP_CONFLICT, 4347 TALER_MHD_PACK_EC ( 4348 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_ALREADY_PAID), 4349 GNUNET_JSON_pack_array_steal ("refunds", 4350 refunds))); 4351 } 4352 4353 4354 /** 4355 * Check the database state for the given order. 4356 * Schedules an error response in the connection on failure. 4357 * 4358 * @param[in,out] pc context we use to handle the payment 4359 */ 4360 static void 4361 phase_check_contract (struct PayContext *pc) 4362 { 4363 /* obtain contract terms */ 4364 enum GNUNET_DB_QueryStatus qs; 4365 bool paid = false; 4366 4367 if (NULL != pc->check_contract.contract_terms_json) 4368 { 4369 json_decref (pc->check_contract.contract_terms_json); 4370 pc->check_contract.contract_terms_json = NULL; 4371 } 4372 if (NULL != pc->check_contract.contract_terms) 4373 { 4374 TALER_MERCHANT_contract_free (pc->check_contract.contract_terms); 4375 pc->check_contract.contract_terms = NULL; 4376 } 4377 qs = TMH_db->lookup_contract_terms2 (TMH_db->cls, 4378 pc->hc->instance->settings.id, 4379 pc->order_id, 4380 &pc->check_contract.contract_terms_json, 4381 &pc->check_contract.order_serial, 4382 &paid, 4383 NULL, 4384 &pc->check_contract.pos_key, 4385 &pc->check_contract.pos_alg); 4386 if (0 > qs) 4387 { 4388 /* single, read-only SQL statements should never cause 4389 serialization problems */ 4390 GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs); 4391 /* Always report on hard error to enable diagnostics */ 4392 GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs); 4393 pay_end (pc, 4394 TALER_MHD_reply_with_error ( 4395 pc->connection, 4396 MHD_HTTP_INTERNAL_SERVER_ERROR, 4397 TALER_EC_GENERIC_DB_FETCH_FAILED, 4398 "contract terms")); 4399 return; 4400 } 4401 if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) 4402 { 4403 pay_end (pc, 4404 TALER_MHD_reply_with_error ( 4405 pc->connection, 4406 MHD_HTTP_NOT_FOUND, 4407 TALER_EC_MERCHANT_GENERIC_ORDER_UNKNOWN, 4408 pc->order_id)); 4409 return; 4410 } 4411 /* hash contract (needed later) */ 4412 #if DEBUG 4413 json_dumpf (pc->check_contract.contract_terms_json, 4414 stderr, 4415 JSON_INDENT (2)); 4416 #endif 4417 if (GNUNET_OK != 4418 TALER_JSON_contract_hash (pc->check_contract.contract_terms_json, 4419 &pc->check_contract.h_contract_terms)) 4420 { 4421 GNUNET_break (0); 4422 pay_end (pc, 4423 TALER_MHD_reply_with_error ( 4424 pc->connection, 4425 MHD_HTTP_INTERNAL_SERVER_ERROR, 4426 TALER_EC_GENERIC_FAILED_COMPUTE_JSON_HASH, 4427 NULL)); 4428 return; 4429 } 4430 4431 /* Parse the contract terms even for paid orders, 4432 as later phases need it. */ 4433 4434 pc->check_contract.contract_terms = TALER_MERCHANT_contract_parse ( 4435 pc->check_contract.contract_terms_json, 4436 true); 4437 4438 if (NULL == pc->check_contract.contract_terms) 4439 { 4440 /* invalid contract */ 4441 GNUNET_break (0); 4442 pay_end (pc, 4443 TALER_MHD_reply_with_error ( 4444 pc->connection, 4445 MHD_HTTP_INTERNAL_SERVER_ERROR, 4446 TALER_EC_MERCHANT_GENERIC_DB_CONTRACT_CONTENT_INVALID, 4447 pc->order_id)); 4448 return; 4449 } 4450 4451 if (paid) 4452 { 4453 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 4454 "Order `%s' paid, checking for double-payment\n", 4455 pc->order_id); 4456 pc->phase = PP_CONTRACT_PAID; 4457 return; 4458 } 4459 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 4460 "Handling payment for order `%s' with contract hash `%s'\n", 4461 pc->order_id, 4462 GNUNET_h2s (&pc->check_contract.h_contract_terms.hash)); 4463 4464 /* Check fundamentals */ 4465 { 4466 switch (pc->check_contract.contract_terms->version) 4467 { 4468 case TALER_MERCHANT_CONTRACT_VERSION_0: 4469 { 4470 if (pc->parse_wallet_data.choice_index > 0) 4471 { 4472 GNUNET_break (0); 4473 pay_end (pc, 4474 TALER_MHD_reply_with_error ( 4475 pc->connection, 4476 MHD_HTTP_BAD_REQUEST, 4477 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_CHOICE_INDEX_OUT_OF_BOUNDS, 4478 "contract terms v0 has no choices")); 4479 return; 4480 } 4481 } 4482 break; 4483 case TALER_MERCHANT_CONTRACT_VERSION_1: 4484 { 4485 if (pc->parse_wallet_data.choice_index < 0) 4486 { 4487 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 4488 "Order `%s' has non-empty choices array but" 4489 "request is missing 'choice_index' field\n", 4490 pc->order_id); 4491 GNUNET_break (0); 4492 pay_end (pc, 4493 TALER_MHD_reply_with_error ( 4494 pc->connection, 4495 MHD_HTTP_BAD_REQUEST, 4496 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_CHOICE_INDEX_MISSING, 4497 NULL)); 4498 return; 4499 } 4500 if (pc->parse_wallet_data.choice_index >= 4501 pc->check_contract.contract_terms->details.v1.choices_len) 4502 { 4503 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 4504 "Order `%s' has choices array with %u elements but " 4505 "request has 'choice_index' field with value %d\n", 4506 pc->order_id, 4507 pc->check_contract.contract_terms->details.v1.choices_len, 4508 pc->parse_wallet_data.choice_index); 4509 GNUNET_break (0); 4510 pay_end (pc, 4511 TALER_MHD_reply_with_error ( 4512 pc->connection, 4513 MHD_HTTP_BAD_REQUEST, 4514 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_CHOICE_INDEX_OUT_OF_BOUNDS, 4515 NULL)); 4516 return; 4517 } 4518 } 4519 break; 4520 default: 4521 GNUNET_break (0); 4522 pay_end (pc, 4523 TALER_MHD_reply_with_error ( 4524 pc->connection, 4525 MHD_HTTP_INTERNAL_SERVER_ERROR, 4526 TALER_EC_GENERIC_DB_FETCH_FAILED, 4527 "contract 'version' in database not supported by this backend") 4528 ); 4529 return; 4530 } 4531 } 4532 4533 if (GNUNET_TIME_timestamp_cmp (pc->check_contract.contract_terms-> 4534 wire_deadline, 4535 <, 4536 pc->check_contract.contract_terms-> 4537 refund_deadline)) 4538 { 4539 /* This should already have been checked when creating the order! */ 4540 GNUNET_break (0); 4541 pay_end (pc, 4542 TALER_MHD_reply_with_error ( 4543 pc->connection, 4544 MHD_HTTP_INTERNAL_SERVER_ERROR, 4545 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_REFUND_DEADLINE_PAST_WIRE_TRANSFER_DEADLINE, 4546 NULL)); 4547 return; 4548 } 4549 if (GNUNET_TIME_absolute_is_past (pc->check_contract.contract_terms-> 4550 pay_deadline.abs_time)) 4551 { 4552 /* too late */ 4553 pay_end (pc, 4554 TALER_MHD_reply_with_error ( 4555 pc->connection, 4556 MHD_HTTP_GONE, 4557 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_OFFER_EXPIRED, 4558 NULL)); 4559 return; 4560 } 4561 4562 /* Make sure wire method (still) exists for this instance */ 4563 { 4564 struct TMH_WireMethod *wm; 4565 4566 wm = pc->hc->instance->wm_head; 4567 while (0 != GNUNET_memcmp (&pc->check_contract.contract_terms->h_wire, 4568 &wm->h_wire)) 4569 wm = wm->next; 4570 if (NULL == wm) 4571 { 4572 GNUNET_break (0); 4573 pay_end (pc, 4574 TALER_MHD_reply_with_error ( 4575 pc->connection, 4576 MHD_HTTP_INTERNAL_SERVER_ERROR, 4577 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_WIRE_HASH_UNKNOWN, 4578 NULL)); 4579 return; 4580 } 4581 pc->check_contract.wm = wm; 4582 } 4583 pc->phase = PP_VALIDATE_TOKENS; 4584 } 4585 4586 4587 /** 4588 * Try to parse the wallet_data object of the pay request into 4589 * the given context. Schedules an error response in the connection 4590 * on failure. 4591 * 4592 * @param[in,out] pc context we use to handle the payment 4593 */ 4594 static void 4595 phase_parse_wallet_data (struct PayContext *pc) 4596 { 4597 const json_t *tokens_evs; 4598 const json_t *donau_obj; 4599 4600 struct GNUNET_JSON_Specification spec[] = { 4601 GNUNET_JSON_spec_mark_optional ( 4602 GNUNET_JSON_spec_int16 ("choice_index", 4603 &pc->parse_wallet_data.choice_index), 4604 NULL), 4605 GNUNET_JSON_spec_mark_optional ( 4606 GNUNET_JSON_spec_array_const ("tokens_evs", 4607 &tokens_evs), 4608 NULL), 4609 GNUNET_JSON_spec_mark_optional ( 4610 GNUNET_JSON_spec_object_const ("donau", 4611 &donau_obj), 4612 NULL), 4613 GNUNET_JSON_spec_end () 4614 }; 4615 4616 pc->parse_wallet_data.choice_index = -1; 4617 if (NULL == pc->parse_pay.wallet_data) 4618 { 4619 pc->phase = PP_CHECK_CONTRACT; 4620 return; 4621 } 4622 { 4623 enum GNUNET_GenericReturnValue res; 4624 4625 res = TALER_MHD_parse_json_data (pc->connection, 4626 pc->parse_pay.wallet_data, 4627 spec); 4628 if (GNUNET_YES != res) 4629 { 4630 GNUNET_break_op (0); 4631 pay_end (pc, 4632 (GNUNET_NO == res) 4633 ? MHD_YES 4634 : MHD_NO); 4635 return; 4636 } 4637 } 4638 4639 pc->parse_wallet_data.token_envelopes_cnt 4640 = json_array_size (tokens_evs); 4641 if (pc->parse_wallet_data.token_envelopes_cnt > 4642 MAX_TOKEN_ALLOWED_OUTPUTS) 4643 { 4644 GNUNET_break_op (0); 4645 pay_end (pc, 4646 TALER_MHD_reply_with_error ( 4647 pc->connection, 4648 MHD_HTTP_BAD_REQUEST, 4649 TALER_EC_GENERIC_PARAMETER_MALFORMED, 4650 "'tokens_evs' array too long")); 4651 return; 4652 } 4653 pc->parse_wallet_data.token_envelopes 4654 = GNUNET_new_array (pc->parse_wallet_data.token_envelopes_cnt, 4655 struct TokenEnvelope); 4656 4657 { 4658 unsigned int tokens_ev_index; 4659 json_t *token_ev; 4660 4661 json_array_foreach (tokens_evs, 4662 tokens_ev_index, 4663 token_ev) 4664 { 4665 struct TokenEnvelope *ev 4666 = &pc->parse_wallet_data.token_envelopes[tokens_ev_index]; 4667 struct GNUNET_JSON_Specification ispec[] = { 4668 TALER_JSON_spec_token_envelope (NULL, 4669 &ev->blinded_token), 4670 GNUNET_JSON_spec_end () 4671 }; 4672 enum GNUNET_GenericReturnValue res; 4673 4674 if (json_is_null (token_ev)) 4675 continue; 4676 res = TALER_MHD_parse_json_data (pc->connection, 4677 token_ev, 4678 ispec); 4679 if (GNUNET_YES != res) 4680 { 4681 GNUNET_break_op (0); 4682 pay_end (pc, 4683 (GNUNET_NO == res) 4684 ? MHD_YES 4685 : MHD_NO); 4686 return; 4687 } 4688 4689 for (unsigned int j = 0; j<tokens_ev_index; j++) 4690 { 4691 if (0 == 4692 GNUNET_memcmp (ev->blinded_token.blinded_pub, 4693 pc->parse_wallet_data.token_envelopes[j]. 4694 blinded_token.blinded_pub)) 4695 { 4696 GNUNET_break_op (0); 4697 pay_end (pc, 4698 TALER_MHD_reply_with_error ( 4699 pc->connection, 4700 MHD_HTTP_BAD_REQUEST, 4701 TALER_EC_GENERIC_PARAMETER_MALFORMED, 4702 "duplicate token envelope in list")); 4703 return; 4704 } 4705 } 4706 } 4707 } 4708 4709 #ifdef HAVE_DONAU_DONAU_SERVICE_H 4710 if (NULL != donau_obj) 4711 { 4712 const char *donau_url_tmp; 4713 const json_t *budikeypairs; 4714 json_t *donau_keys_json; 4715 4716 /* Fetching and checking that all 3 are present in some way */ 4717 struct GNUNET_JSON_Specification dspec[] = { 4718 GNUNET_JSON_spec_string ("url", 4719 &donau_url_tmp), 4720 GNUNET_JSON_spec_uint64 ("year", 4721 &pc->parse_wallet_data.donau.donation_year), 4722 GNUNET_JSON_spec_array_const ("budikeypairs", 4723 &budikeypairs), 4724 GNUNET_JSON_spec_end () 4725 }; 4726 enum GNUNET_GenericReturnValue res; 4727 4728 res = TALER_MHD_parse_json_data (pc->connection, 4729 donau_obj, 4730 dspec); 4731 if (GNUNET_YES != res) 4732 { 4733 GNUNET_break_op (0); 4734 pay_end (pc, 4735 (GNUNET_NO == res) 4736 ? MHD_YES 4737 : MHD_NO); 4738 return; 4739 } 4740 4741 /* Check if the needed data is present for the given donau URL */ 4742 { 4743 enum GNUNET_DB_QueryStatus qs; 4744 4745 qs = TMH_db->lookup_order_charity ( 4746 TMH_db->cls, 4747 pc->hc->instance->settings.id, 4748 donau_url_tmp, 4749 &pc->parse_wallet_data.charity_id, 4750 &pc->parse_wallet_data.charity_priv, 4751 &pc->parse_wallet_data.charity_max_per_year, 4752 &pc->parse_wallet_data.charity_receipts_to_date, 4753 &donau_keys_json, 4754 &pc->parse_wallet_data.donau_instance_serial); 4755 4756 switch (qs) 4757 { 4758 case GNUNET_DB_STATUS_HARD_ERROR: 4759 case GNUNET_DB_STATUS_SOFT_ERROR: 4760 TMH_db->rollback (TMH_db->cls); 4761 pay_end (pc, 4762 TALER_MHD_reply_with_error ( 4763 pc->connection, 4764 MHD_HTTP_INTERNAL_SERVER_ERROR, 4765 TALER_EC_GENERIC_DB_FETCH_FAILED, 4766 "lookup_order_charity")); 4767 return; 4768 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 4769 TMH_db->rollback (TMH_db->cls); 4770 pay_end (pc, 4771 TALER_MHD_reply_with_error ( 4772 pc->connection, 4773 MHD_HTTP_NOT_FOUND, 4774 TALER_EC_MERCHANT_GENERIC_DONAU_CHARITY_UNKNOWN, 4775 donau_url_tmp)); 4776 return; 4777 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 4778 pc->parse_wallet_data.donau.donau_url = 4779 GNUNET_strdup (donau_url_tmp); 4780 break; 4781 } 4782 } 4783 4784 { 4785 pc->parse_wallet_data.donau_keys = 4786 DONAU_keys_from_json (donau_keys_json); 4787 json_decref (donau_keys_json); 4788 if (NULL == pc->parse_wallet_data.donau_keys) 4789 { 4790 GNUNET_break_op (0); 4791 pay_end (pc, 4792 TALER_MHD_reply_with_error (pc->connection, 4793 MHD_HTTP_BAD_REQUEST, 4794 TALER_EC_GENERIC_PARAMETER_MALFORMED, 4795 "Invalid donau_keys")); 4796 return; 4797 } 4798 } 4799 4800 /* Stage to parse the budikeypairs from json to struct */ 4801 if (0 != json_array_size (budikeypairs)) 4802 { 4803 size_t num_bkps = json_array_size (budikeypairs); 4804 struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkps = 4805 GNUNET_new_array (num_bkps, 4806 struct DONAU_BlindedUniqueDonorIdentifierKeyPair); 4807 4808 /* Change to json for each*/ 4809 for (size_t i = 0; i < num_bkps; i++) 4810 { 4811 const json_t *bkp_obj = json_array_get (budikeypairs, 4812 i); 4813 if (GNUNET_SYSERR == 4814 merchant_parse_json_bkp (&bkps[i], 4815 bkp_obj)) 4816 { 4817 GNUNET_break_op (0); 4818 for (size_t j = 0; i < j; j++) 4819 GNUNET_CRYPTO_blinded_message_decref ( 4820 bkps[j].blinded_udi.blinded_message); 4821 GNUNET_free (bkps); 4822 pay_end (pc, 4823 TALER_MHD_reply_with_error (pc->connection, 4824 MHD_HTTP_BAD_REQUEST, 4825 TALER_EC_GENERIC_PARAMETER_MALFORMED, 4826 "Failed to parse budikeypairs")); 4827 return; 4828 } 4829 } 4830 4831 pc->parse_wallet_data.num_bkps = num_bkps; 4832 pc->parse_wallet_data.bkps = bkps; 4833 } 4834 } 4835 #else 4836 /* Donau not compiled in: reject request if a donau object was given. */ 4837 if (NULL != donau_obj) 4838 { 4839 pay_end (pc, 4840 TALER_MHD_reply_with_error ( 4841 pc->connection, 4842 MHD_HTTP_NOT_IMPLEMENTED, 4843 TALER_EC_MERCHANT_GENERIC_DONAU_NOT_CONFIGURED, 4844 "donau support disabled")); 4845 return; 4846 } 4847 #endif /* HAVE_DONAU_DONAU_SERVICE_H */ 4848 4849 TALER_json_hash (pc->parse_pay.wallet_data, 4850 &pc->parse_wallet_data.h_wallet_data); 4851 4852 pc->phase = PP_CHECK_CONTRACT; 4853 } 4854 4855 4856 /** 4857 * Try to parse the pay request into the given pay context. 4858 * Schedules an error response in the connection on failure. 4859 * 4860 * @param[in,out] pc context we use to handle the payment 4861 */ 4862 static void 4863 phase_parse_pay (struct PayContext *pc) 4864 { 4865 const char *session_id = NULL; 4866 const json_t *coins; 4867 const json_t *tokens; 4868 struct GNUNET_JSON_Specification spec[] = { 4869 GNUNET_JSON_spec_array_const ("coins", 4870 &coins), 4871 GNUNET_JSON_spec_mark_optional ( 4872 GNUNET_JSON_spec_string ("session_id", 4873 &session_id), 4874 NULL), 4875 GNUNET_JSON_spec_mark_optional ( 4876 GNUNET_JSON_spec_object_const ("wallet_data", 4877 &pc->parse_pay.wallet_data), 4878 NULL), 4879 GNUNET_JSON_spec_mark_optional ( 4880 GNUNET_JSON_spec_array_const ("tokens", 4881 &tokens), 4882 NULL), 4883 GNUNET_JSON_spec_end () 4884 }; 4885 4886 #if DEBUG 4887 { 4888 char *dump = json_dumps (pc->hc->request_body, 4889 JSON_INDENT (2) 4890 | JSON_ENCODE_ANY 4891 | JSON_SORT_KEYS); 4892 4893 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 4894 "POST /orders/%s/pay – request body follows:\n%s\n", 4895 pc->order_id, 4896 dump); 4897 4898 free (dump); 4899 4900 } 4901 #endif /* DEBUG */ 4902 4903 GNUNET_assert (PP_PARSE_PAY == pc->phase); 4904 { 4905 enum GNUNET_GenericReturnValue res; 4906 4907 res = TALER_MHD_parse_json_data (pc->connection, 4908 pc->hc->request_body, 4909 spec); 4910 if (GNUNET_YES != res) 4911 { 4912 GNUNET_break_op (0); 4913 pay_end (pc, 4914 (GNUNET_NO == res) 4915 ? MHD_YES 4916 : MHD_NO); 4917 return; 4918 } 4919 } 4920 4921 /* copy session ID (if set) */ 4922 if (NULL != session_id) 4923 { 4924 pc->parse_pay.session_id = GNUNET_strdup (session_id); 4925 } 4926 else 4927 { 4928 /* use empty string as default if client didn't specify it */ 4929 pc->parse_pay.session_id = GNUNET_strdup (""); 4930 } 4931 4932 pc->parse_pay.coins_cnt = json_array_size (coins); 4933 if (pc->parse_pay.coins_cnt > MAX_COIN_ALLOWED_COINS) 4934 { 4935 GNUNET_break_op (0); 4936 pay_end (pc, 4937 TALER_MHD_reply_with_error ( 4938 pc->connection, 4939 MHD_HTTP_BAD_REQUEST, 4940 TALER_EC_GENERIC_PARAMETER_MALFORMED, 4941 "'coins' array too long")); 4942 return; 4943 } 4944 /* note: 1 coin = 1 deposit confirmation expected */ 4945 pc->parse_pay.dc = GNUNET_new_array (pc->parse_pay.coins_cnt, 4946 struct DepositConfirmation); 4947 4948 /* This loop populates the array 'dc' in 'pc' */ 4949 { 4950 unsigned int coins_index; 4951 json_t *coin; 4952 4953 json_array_foreach (coins, coins_index, coin) 4954 { 4955 struct DepositConfirmation *dc = &pc->parse_pay.dc[coins_index]; 4956 const char *exchange_url; 4957 struct GNUNET_JSON_Specification ispec[] = { 4958 GNUNET_JSON_spec_fixed_auto ("coin_sig", 4959 &dc->cdd.coin_sig), 4960 GNUNET_JSON_spec_fixed_auto ("coin_pub", 4961 &dc->cdd.coin_pub), 4962 TALER_JSON_spec_denom_sig ("ub_sig", 4963 &dc->cdd.denom_sig), 4964 GNUNET_JSON_spec_fixed_auto ("h_denom", 4965 &dc->cdd.h_denom_pub), 4966 TALER_JSON_spec_amount_any ("contribution", 4967 &dc->cdd.amount), 4968 TALER_JSON_spec_web_url ("exchange_url", 4969 &exchange_url), 4970 /* if a minimum age was required, the minimum_age_sig and 4971 * age_commitment must be provided */ 4972 GNUNET_JSON_spec_mark_optional ( 4973 GNUNET_JSON_spec_fixed_auto ("minimum_age_sig", 4974 &dc->minimum_age_sig), 4975 &dc->no_minimum_age_sig), 4976 GNUNET_JSON_spec_mark_optional ( 4977 TALER_JSON_spec_age_commitment ("age_commitment", 4978 &dc->age_commitment), 4979 &dc->no_age_commitment), 4980 /* if minimum age was not required, but coin with age restriction set 4981 * was used, h_age_commitment must be provided. */ 4982 GNUNET_JSON_spec_mark_optional ( 4983 GNUNET_JSON_spec_fixed_auto ("h_age_commitment", 4984 &dc->cdd.h_age_commitment), 4985 &dc->no_h_age_commitment), 4986 GNUNET_JSON_spec_end () 4987 }; 4988 enum GNUNET_GenericReturnValue res; 4989 struct ExchangeGroup *eg = NULL; 4990 4991 res = TALER_MHD_parse_json_data (pc->connection, 4992 coin, 4993 ispec); 4994 if (GNUNET_YES != res) 4995 { 4996 GNUNET_break_op (0); 4997 pay_end (pc, 4998 (GNUNET_NO == res) 4999 ? MHD_YES 5000 : MHD_NO); 5001 return; 5002 } 5003 for (unsigned int j = 0; j<coins_index; j++) 5004 { 5005 if (0 == 5006 GNUNET_memcmp (&dc->cdd.coin_pub, 5007 &pc->parse_pay.dc[j].cdd.coin_pub)) 5008 { 5009 GNUNET_break_op (0); 5010 pay_end (pc, 5011 TALER_MHD_reply_with_error (pc->connection, 5012 MHD_HTTP_BAD_REQUEST, 5013 TALER_EC_GENERIC_PARAMETER_MALFORMED, 5014 "duplicate coin in list")); 5015 return; 5016 } 5017 } 5018 5019 dc->exchange_url = GNUNET_strdup (exchange_url); 5020 dc->index = coins_index; 5021 dc->pc = pc; 5022 5023 /* Check the consistency of the (potential) age restriction 5024 * information. */ 5025 if (dc->no_age_commitment != dc->no_minimum_age_sig) 5026 { 5027 GNUNET_break_op (0); 5028 pay_end (pc, 5029 TALER_MHD_reply_with_error ( 5030 pc->connection, 5031 MHD_HTTP_BAD_REQUEST, 5032 TALER_EC_GENERIC_PARAMETER_MALFORMED, 5033 "inconsistent: 'age_commitment' vs. 'minimum_age_sig'" 5034 )); 5035 return; 5036 } 5037 5038 /* Setup exchange group */ 5039 for (unsigned int i = 0; i<pc->parse_pay.num_exchanges; i++) 5040 { 5041 if (0 == 5042 strcmp (pc->parse_pay.egs[i]->exchange_url, 5043 exchange_url)) 5044 { 5045 eg = pc->parse_pay.egs[i]; 5046 break; 5047 } 5048 } 5049 if (NULL == eg) 5050 { 5051 eg = GNUNET_new (struct ExchangeGroup); 5052 eg->pc = pc; 5053 eg->exchange_url = dc->exchange_url; 5054 eg->total = dc->cdd.amount; 5055 GNUNET_array_append (pc->parse_pay.egs, 5056 pc->parse_pay.num_exchanges, 5057 eg); 5058 } 5059 else 5060 { 5061 if (0 > 5062 TALER_amount_add (&eg->total, 5063 &eg->total, 5064 &dc->cdd.amount)) 5065 { 5066 GNUNET_break_op (0); 5067 pay_end (pc, 5068 TALER_MHD_reply_with_error ( 5069 pc->connection, 5070 MHD_HTTP_INTERNAL_SERVER_ERROR, 5071 TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW, 5072 "Overflow adding up amounts")); 5073 return; 5074 } 5075 } 5076 } 5077 } 5078 5079 pc->parse_pay.tokens_cnt = json_array_size (tokens); 5080 if (pc->parse_pay.tokens_cnt > MAX_TOKEN_ALLOWED_INPUTS) 5081 { 5082 GNUNET_break_op (0); 5083 pay_end (pc, 5084 TALER_MHD_reply_with_error ( 5085 pc->connection, 5086 MHD_HTTP_BAD_REQUEST, 5087 TALER_EC_GENERIC_PARAMETER_MALFORMED, 5088 "'tokens' array too long")); 5089 return; 5090 } 5091 5092 pc->parse_pay.tokens = GNUNET_new_array (pc->parse_pay.tokens_cnt, 5093 struct TokenUseConfirmation); 5094 5095 /* This loop populates the array 'tokens' in 'pc' */ 5096 { 5097 unsigned int tokens_index; 5098 json_t *token; 5099 5100 json_array_foreach (tokens, tokens_index, token) 5101 { 5102 struct TokenUseConfirmation *tuc = &pc->parse_pay.tokens[tokens_index]; 5103 struct GNUNET_JSON_Specification ispec[] = { 5104 GNUNET_JSON_spec_fixed_auto ("token_sig", 5105 &tuc->sig), 5106 GNUNET_JSON_spec_fixed_auto ("token_pub", 5107 &tuc->pub), 5108 GNUNET_JSON_spec_fixed_auto ("h_issue", 5109 &tuc->h_issue), 5110 TALER_JSON_spec_token_issue_sig ("ub_sig", 5111 &tuc->unblinded_sig), 5112 GNUNET_JSON_spec_end () 5113 }; 5114 enum GNUNET_GenericReturnValue res; 5115 5116 res = TALER_MHD_parse_json_data (pc->connection, 5117 token, 5118 ispec); 5119 if (GNUNET_YES != res) 5120 { 5121 GNUNET_break_op (0); 5122 pay_end (pc, 5123 (GNUNET_NO == res) 5124 ? MHD_YES 5125 : MHD_NO); 5126 return; 5127 } 5128 5129 for (unsigned int j = 0; j<tokens_index; j++) 5130 { 5131 if (0 == 5132 GNUNET_memcmp (&tuc->pub, 5133 &pc->parse_pay.tokens[j].pub)) 5134 { 5135 GNUNET_break_op (0); 5136 pay_end (pc, 5137 TALER_MHD_reply_with_error (pc->connection, 5138 MHD_HTTP_BAD_REQUEST, 5139 TALER_EC_GENERIC_PARAMETER_MALFORMED, 5140 "duplicate token in list")); 5141 return; 5142 } 5143 } 5144 } 5145 } 5146 5147 pc->phase = PP_PARSE_WALLET_DATA; 5148 } 5149 5150 5151 /** 5152 * Custom cleanup routine for a `struct PayContext`. 5153 * 5154 * @param cls the `struct PayContext` to clean up. 5155 */ 5156 static void 5157 pay_context_cleanup (void *cls) 5158 { 5159 struct PayContext *pc = cls; 5160 5161 if (NULL != pc->batch_deposits.timeout_task) 5162 { 5163 GNUNET_SCHEDULER_cancel (pc->batch_deposits.timeout_task); 5164 pc->batch_deposits.timeout_task = NULL; 5165 } 5166 if (NULL != pc->check_contract.contract_terms_json) 5167 { 5168 json_decref (pc->check_contract.contract_terms_json); 5169 pc->check_contract.contract_terms_json = NULL; 5170 } 5171 for (unsigned int i = 0; i<pc->parse_pay.coins_cnt; i++) 5172 { 5173 struct DepositConfirmation *dc = &pc->parse_pay.dc[i]; 5174 5175 TALER_denom_sig_free (&dc->cdd.denom_sig); 5176 GNUNET_free (dc->exchange_url); 5177 } 5178 GNUNET_free (pc->parse_pay.dc); 5179 for (unsigned int i = 0; i<pc->parse_pay.tokens_cnt; i++) 5180 { 5181 struct TokenUseConfirmation *tuc = &pc->parse_pay.tokens[i]; 5182 5183 TALER_token_issue_sig_free (&tuc->unblinded_sig); 5184 } 5185 GNUNET_free (pc->parse_pay.tokens); 5186 for (unsigned int i = 0; i<pc->parse_pay.num_exchanges; i++) 5187 { 5188 struct ExchangeGroup *eg = pc->parse_pay.egs[i]; 5189 5190 if (NULL != eg->fo) 5191 TMH_EXCHANGES_keys4exchange_cancel (eg->fo); 5192 if (NULL != eg->bdh) 5193 TALER_EXCHANGE_post_batch_deposit_cancel (eg->bdh); 5194 if (NULL != eg->keys) 5195 TALER_EXCHANGE_keys_decref (eg->keys); 5196 GNUNET_free (eg); 5197 } 5198 GNUNET_free (pc->parse_pay.egs); 5199 if (NULL != pc->check_contract.contract_terms) 5200 { 5201 TALER_MERCHANT_contract_free (pc->check_contract.contract_terms); 5202 pc->check_contract.contract_terms = NULL; 5203 } 5204 if (NULL != pc->response) 5205 { 5206 MHD_destroy_response (pc->response); 5207 pc->response = NULL; 5208 } 5209 GNUNET_free (pc->parse_pay.session_id); 5210 GNUNET_CONTAINER_DLL_remove (pc_head, 5211 pc_tail, 5212 pc); 5213 GNUNET_free (pc->check_contract.pos_key); 5214 GNUNET_free (pc->compute_money_pots.pots); 5215 GNUNET_free (pc->compute_money_pots.increments); 5216 #ifdef HAVE_DONAU_DONAU_SERVICE_H 5217 if (NULL != pc->parse_wallet_data.bkps) 5218 { 5219 for (size_t i = 0; i < pc->parse_wallet_data.num_bkps; i++) 5220 GNUNET_CRYPTO_blinded_message_decref ( 5221 pc->parse_wallet_data.bkps[i].blinded_udi.blinded_message); 5222 GNUNET_array_grow (pc->parse_wallet_data.bkps, 5223 pc->parse_wallet_data.num_bkps, 5224 0); 5225 } 5226 if (NULL != pc->parse_wallet_data.donau_keys) 5227 { 5228 DONAU_keys_decref (pc->parse_wallet_data.donau_keys); 5229 pc->parse_wallet_data.donau_keys = NULL; 5230 } 5231 GNUNET_free (pc->parse_wallet_data.donau.donau_url); 5232 #endif 5233 for (unsigned int i = 0; i<pc->parse_wallet_data.token_envelopes_cnt; i++) 5234 { 5235 struct TokenEnvelope *ev 5236 = &pc->parse_wallet_data.token_envelopes[i]; 5237 5238 GNUNET_CRYPTO_blinded_message_decref (ev->blinded_token.blinded_pub); 5239 } 5240 GNUNET_free (pc->parse_wallet_data.token_envelopes); 5241 if (NULL != pc->output_tokens) 5242 { 5243 for (unsigned int i = 0; i<pc->output_tokens_len; i++) 5244 if (NULL != pc->output_tokens[i].sig.signature) 5245 GNUNET_CRYPTO_blinded_sig_decref (pc->output_tokens[i].sig.signature); 5246 GNUNET_free (pc->output_tokens); 5247 pc->output_tokens = NULL; 5248 } 5249 GNUNET_free (pc); 5250 } 5251 5252 5253 MHD_RESULT 5254 TMH_post_orders_ID_pay (const struct TMH_RequestHandler *rh, 5255 struct MHD_Connection *connection, 5256 struct TMH_HandlerContext *hc) 5257 { 5258 struct PayContext *pc = hc->ctx; 5259 5260 GNUNET_assert (NULL != hc->infix); 5261 if (NULL == pc) 5262 { 5263 pc = GNUNET_new (struct PayContext); 5264 pc->connection = connection; 5265 pc->hc = hc; 5266 pc->order_id = hc->infix; 5267 hc->ctx = pc; 5268 hc->cc = &pay_context_cleanup; 5269 GNUNET_CONTAINER_DLL_insert (pc_head, 5270 pc_tail, 5271 pc); 5272 } 5273 while (1) 5274 { 5275 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 5276 "Processing /pay in phase %d\n", 5277 (int) pc->phase); 5278 switch (pc->phase) 5279 { 5280 case PP_PARSE_PAY: 5281 phase_parse_pay (pc); 5282 break; 5283 case PP_PARSE_WALLET_DATA: 5284 phase_parse_wallet_data (pc); 5285 break; 5286 case PP_CHECK_CONTRACT: 5287 phase_check_contract (pc); 5288 break; 5289 case PP_VALIDATE_TOKENS: 5290 phase_validate_tokens (pc); 5291 break; 5292 case PP_CONTRACT_PAID: 5293 phase_contract_paid (pc); 5294 break; 5295 case PP_COMPUTE_MONEY_POTS: 5296 phase_compute_money_pots (pc); 5297 break; 5298 case PP_PAY_TRANSACTION: 5299 phase_execute_pay_transaction (pc); 5300 break; 5301 case PP_REQUEST_DONATION_RECEIPT: 5302 #ifdef HAVE_DONAU_DONAU_SERVICE_H 5303 phase_request_donation_receipt (pc); 5304 #else 5305 pc->phase++; 5306 #endif 5307 break; 5308 case PP_FINAL_OUTPUT_TOKEN_PROCESSING: 5309 phase_final_output_token_processing (pc); 5310 break; 5311 case PP_PAYMENT_NOTIFICATION: 5312 phase_payment_notification (pc); 5313 break; 5314 case PP_SUCCESS_RESPONSE: 5315 phase_success_response (pc); 5316 break; 5317 case PP_BATCH_DEPOSITS: 5318 phase_batch_deposits (pc); 5319 break; 5320 case PP_RETURN_RESPONSE: 5321 phase_return_response (pc); 5322 break; 5323 case PP_FAIL_LEGAL_REASONS: 5324 phase_fail_for_legal_reasons (pc); 5325 break; 5326 case PP_END_YES: 5327 return MHD_YES; 5328 case PP_END_NO: 5329 return MHD_NO; 5330 default: 5331 /* should not be reachable */ 5332 GNUNET_assert (0); 5333 return MHD_NO; 5334 } 5335 switch (pc->suspended) 5336 { 5337 case GNUNET_SYSERR: 5338 /* during shutdown, we don't generate any more replies */ 5339 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 5340 "Processing /pay ends due to shutdown in phase %d\n", 5341 (int) pc->phase); 5342 return MHD_NO; 5343 case GNUNET_NO: 5344 /* continue to next phase */ 5345 break; 5346 case GNUNET_YES: 5347 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 5348 "Processing /pay suspended in phase %d\n", 5349 (int) pc->phase); 5350 return MHD_YES; 5351 } 5352 } 5353 /* impossible to get here */ 5354 GNUNET_assert (0); 5355 return MHD_YES; 5356 } 5357 5358 5359 /* end of taler-merchant-httpd_post-orders-ORDER_ID-pay.c */