kyclogic_api.c (151039B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2022-2025 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU Affero General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. 12 13 You should have received a copy of the GNU Affero General Public License along with 14 TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file kyclogic_api.c 18 * @brief server-side KYC API 19 * @author Christian Grothoff 20 */ 21 #include "platform.h" /* UNNECESSARY? */ 22 #include "taler/taler_json_lib.h" 23 #include "taler/taler_kyclogic_lib.h" 24 25 /** 26 * Log verbosely, including possibly privacy-sensitive data. 27 */ 28 #define DEBUG 1 29 30 /** 31 * Name of the KYC measure that may never be passed. Useful if some 32 * operations/amounts are categorically forbidden. 33 */ 34 #define KYC_MEASURE_IMPOSSIBLE "verboten" 35 36 /** 37 * Information about a KYC provider. 38 */ 39 struct TALER_KYCLOGIC_KycProvider 40 { 41 42 /** 43 * Name of the provider. 44 */ 45 char *provider_name; 46 47 /** 48 * Logic to run for this provider. 49 */ 50 struct TALER_KYCLOGIC_Plugin *logic; 51 52 /** 53 * Provider-specific details to pass to the @e logic functions. 54 */ 55 struct TALER_KYCLOGIC_ProviderDetails *pd; 56 57 /** 58 * Maximum time to reuse a process when the provider does not report its 59 * authoritative expiration. 60 */ 61 struct GNUNET_TIME_Relative process_timeout; 62 63 }; 64 65 66 /** 67 * Rule that triggers some measure(s). 68 */ 69 struct TALER_KYCLOGIC_KycRule 70 { 71 72 /** 73 * Name of the rule (configuration section name). 74 * NULL if not from the configuration. 75 */ 76 char *rule_name; 77 78 /** 79 * Rule set with custom measures that this KYC rule 80 * is part of. 81 */ 82 const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs; 83 84 /** 85 * Timeframe to consider for computing the amount 86 * to compare against the @e limit. Zero for the 87 * wallet balance trigger (as not applicable). 88 */ 89 struct GNUNET_TIME_Relative timeframe; 90 91 /** 92 * Maximum amount that can be transacted until 93 * the rule triggers. 94 */ 95 struct TALER_Amount threshold; 96 97 /** 98 * Array of names of measures to apply on this trigger. 99 */ 100 char **next_measures; 101 102 /** 103 * Length of the @e next_measures array. 104 */ 105 unsigned int num_measures; 106 107 /** 108 * Display priority for this rule. 109 */ 110 uint32_t display_priority; 111 112 /** 113 * What operation type is this rule for? 114 */ 115 enum TALER_KYCLOGIC_KycTriggerEvent trigger; 116 117 /** 118 * True if all @e next_measures will eventually need to 119 * be satisfied, False if the user has a choice between them. 120 */ 121 bool is_and_combinator; 122 123 /** 124 * True if this rule and the general nature of the next measures 125 * should be exposed to the client. 126 */ 127 bool exposed; 128 129 /** 130 * True if any of the measures is 'verboten' and 131 * thus this rule cannot ever be satisfied. 132 */ 133 bool verboten; 134 135 }; 136 137 138 /** 139 * Set of rules that applies to an account. 140 */ 141 struct TALER_KYCLOGIC_LegitimizationRuleSet 142 { 143 144 /** 145 * When does this rule set expire? 146 */ 147 struct GNUNET_TIME_Timestamp expiration_time; 148 149 /** 150 * Name of the successor measure after expiration. 151 * NULL to revert to default rules. 152 */ 153 char *successor_measure; 154 155 /** 156 * Array of the rules. 157 */ 158 struct TALER_KYCLOGIC_KycRule *kyc_rules; 159 160 /** 161 * Array of custom measures the @e kyc_rules may refer 162 * to. 163 */ 164 struct TALER_KYCLOGIC_Measure *custom_measures; 165 166 /** 167 * Length of the @e kyc_rules array. 168 */ 169 unsigned int num_kyc_rules; 170 171 /** 172 * Length of the @e custom_measures array. 173 */ 174 unsigned int num_custom_measures; 175 176 }; 177 178 179 /** 180 * AML program inputs as per "-i" option of the AML program. 181 * This is a bitmask. 182 */ 183 enum AmlProgramInputs 184 { 185 /** 186 * No inputs are needed. 187 */ 188 API_NONE = 0, 189 190 /** 191 * Context is needed. 192 */ 193 API_CONTEXT = 1, 194 195 /** 196 * Current (just submitted) attributes needed. 197 */ 198 API_ATTRIBUTES = 2, 199 200 /** 201 * Current AML rules are needed. 202 */ 203 API_CURRENT_RULES = 4, 204 205 /** 206 * Default AML rules (that apply to fresh accounts) are needed. 207 */ 208 API_DEFAULT_RULES = 8, 209 210 /** 211 * Account AML history is needed, possibly length-limited, 212 * see ``aml_history_length_limit``. 213 */ 214 API_AML_HISTORY = 16, 215 216 /** 217 * Account KYC history is needed, possibly length-limited, 218 * see ``kyc_history_length_limit`` 219 */ 220 API_KYC_HISTORY = 32, 221 222 }; 223 224 225 /** 226 * AML programs. 227 */ 228 struct TALER_KYCLOGIC_AmlProgram 229 { 230 231 /** 232 * Name of the AML program configuration section. 233 */ 234 char *program_name; 235 236 /** 237 * Name of the AML program (binary) to run. 238 */ 239 char *command; 240 241 /** 242 * Human-readable description of what this AML helper 243 * program will do. 244 */ 245 char *description; 246 247 /** 248 * Name of an original measure to take in case the 249 * @e command fails, NULL to fallback to default rules. 250 */ 251 char *fallback; 252 253 /** 254 * Output of @e command "-r". 255 */ 256 char **required_contexts; 257 258 /** 259 * Length of the @e required_contexts array. 260 */ 261 unsigned int num_required_contexts; 262 263 /** 264 * Output of @e command "-a". 265 */ 266 char **required_attributes; 267 268 /** 269 * Length of the @e required_attributes array. 270 */ 271 unsigned int num_required_attributes; 272 273 /** 274 * Bitmask of inputs this AML program would like (based on '-i'). 275 */ 276 enum AmlProgramInputs input_mask; 277 278 /** 279 * How many entries of the AML history are requested; 280 * negative number if we want the latest entries only. 281 */ 282 long long aml_history_length_limit; 283 284 /** 285 * How many entries of the KYC history are requested; 286 * negative number if we want the latest entries only. 287 */ 288 long long kyc_history_length_limit; 289 290 }; 291 292 293 /** 294 * Array of @e num_kyc_logics KYC logic plugins we have loaded. 295 */ 296 static struct TALER_KYCLOGIC_Plugin **kyc_logics; 297 298 /** 299 * Length of the #kyc_logics array. 300 */ 301 static unsigned int num_kyc_logics; 302 303 /** 304 * Array of configured providers. 305 */ 306 static struct TALER_KYCLOGIC_KycProvider **kyc_providers; 307 308 /** 309 * Length of the #kyc_providers array. 310 */ 311 static unsigned int num_kyc_providers; 312 313 /** 314 * Array of @e num_kyc_checks known types of 315 * KYC checks. 316 */ 317 static struct TALER_KYCLOGIC_KycCheck **kyc_checks; 318 319 /** 320 * Length of the #kyc_checks array. 321 */ 322 static unsigned int num_kyc_checks; 323 324 /** 325 * Rules that apply if we do not have an AMLA record. 326 */ 327 static struct TALER_KYCLOGIC_LegitimizationRuleSet default_rules; 328 329 /** 330 * Array of available AML programs. 331 */ 332 static struct TALER_KYCLOGIC_AmlProgram **aml_programs; 333 334 /** 335 * Length of the #aml_programs array. 336 */ 337 static unsigned int num_aml_programs; 338 339 /** 340 * Name of our configuration file. 341 */ 342 static char *cfg_filename; 343 344 /** 345 * Currency we expect to see in all rules. 346 */ 347 static char *my_currency; 348 349 /** 350 * Default LegitimizationRuleSet for wallets. Excludes *default* measures 351 * even if these are the default rules. 352 */ 353 static json_t *wallet_default_lrs; 354 355 /** 356 * Default LegitimizationRuleSet for bank accounts. Excludes *default* measures 357 * even if these are the default rules. 358 */ 359 static json_t *bankaccount_default_lrs; 360 361 362 /** 363 * Convert the ASCII string in @a s to lower-case. Here, 364 * @a s must only contain the characters "[a-zA-Z0-9.-_]", 365 * otherwise the function fails and returns false. 366 * 367 * @param[in,out] s string to lower-case 368 * @return true on success, if false is returned, the 369 * value in @a s may be partially transformed 370 */ 371 static bool 372 ascii_lower (char *s) 373 { 374 for (size_t i = 0; '\0' != s[i]; i++) 375 { 376 int c = (int) s[i]; 377 378 if (isdigit (c)) 379 continue; 380 if (isalpha (c)) 381 { 382 s[i] = (char) tolower (c); 383 continue; 384 } 385 if ( ('-' == c) || 386 ('.' == c) || 387 ('_' == c) ) 388 continue; 389 return false; 390 } 391 return true; 392 } 393 394 395 /** 396 * Convert the ASCII string in @a s to lower-case. Here, 397 * @a s must only contain the characters "[a-zA-Z0-9 \n\t;.-_]", 398 * otherwise the function fails and returns false. 399 * Note that the main difference to ascii_lower is that 400 * " \n\t;" are allowed. 401 * 402 * @param[in,out] s string to lower-case 403 * @return true on success, if false is returned, the 404 * value in @a s may be partially transformed 405 */ 406 static bool 407 token_list_lower (char *s) 408 { 409 for (size_t i = 0; '\0' != s[i]; i++) 410 { 411 int c = (int) s[i]; 412 413 if (isdigit (c)) 414 continue; 415 if (isalpha (c)) 416 { 417 s[i] = (char) tolower (c); 418 continue; 419 } 420 if ( ('-' == c) || 421 (' ' == c) || 422 ('.' == c) || 423 ('\n' == c) || 424 ('\t' == c) || 425 (';' == c) || 426 ('_' == c) ) 427 continue; 428 return false; 429 } 430 return true; 431 } 432 433 434 /** 435 * Check that @a section begins with @a prefix and afterwards 436 * only contains characters "[a-zA-Z0-9-_]". If so, convert all 437 * characters to lower-case and return the result. 438 * 439 * @param prefix section prefix to match 440 * @param section section name to match against 441 * @return NULL if @a prefix does not match or @a section contains 442 * invalid characters after the prefix 443 */ 444 static char * 445 normalize_section_with_prefix (const char *prefix, 446 const char *section) 447 { 448 char *ret; 449 450 if (0 != strncasecmp (section, 451 prefix, 452 strlen (prefix))) 453 return NULL; /* no match */ 454 ret = GNUNET_strdup (section); 455 if (! ascii_lower (ret)) 456 { 457 GNUNET_free (ret); 458 return NULL; 459 } 460 return ret; 461 } 462 463 464 struct GNUNET_TIME_Timestamp 465 TALER_KYCLOGIC_rules_get_expiration ( 466 const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs) 467 { 468 if (NULL == lrs) 469 return GNUNET_TIME_UNIT_FOREVER_TS; 470 return lrs->expiration_time; 471 } 472 473 474 const struct TALER_KYCLOGIC_Measure * 475 TALER_KYCLOGIC_rules_get_successor ( 476 const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs) 477 { 478 const char *successor_measure_name = lrs->successor_measure; 479 480 if (NULL == successor_measure_name) 481 { 482 return NULL; 483 } 484 return TALER_KYCLOGIC_get_measure ( 485 lrs, 486 successor_measure_name); 487 } 488 489 490 /** 491 * Check if @a trigger applies to our context. 492 * 493 * @param trigger the trigger to evaluate 494 * @param is_wallet #GNUNET_YES if this is for a wallet, 495 * #GNUNET_NO for account, 496 * #GNUNET_SYSERR for unknown (returns all rules) 497 * @return true if @a trigger applies in this context 498 */ 499 static bool 500 trigger_applies (enum TALER_KYCLOGIC_KycTriggerEvent trigger, 501 enum GNUNET_GenericReturnValue is_wallet) 502 { 503 switch (trigger) 504 { 505 case TALER_KYCLOGIC_KYC_TRIGGER_NONE: 506 GNUNET_break (0); 507 break; 508 case TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW: 509 return GNUNET_YES != is_wallet; 510 case TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT: 511 return GNUNET_YES != is_wallet; 512 case TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE: 513 return GNUNET_NO != is_wallet; 514 case TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE: 515 return GNUNET_NO != is_wallet; 516 case TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE: 517 return GNUNET_YES != is_wallet; 518 case TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE: 519 return GNUNET_YES != is_wallet; 520 case TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION: 521 return true; 522 case TALER_KYCLOGIC_KYC_TRIGGER_REFUND: 523 return true; 524 } 525 GNUNET_break (0); 526 return true; 527 } 528 529 530 /** 531 * Lookup a KYC check by @a check_name 532 * 533 * @param check_name name to search for 534 * @return NULL if not found 535 */ 536 static struct TALER_KYCLOGIC_KycCheck * 537 find_check (const char *check_name) 538 { 539 for (unsigned int i = 0; i<num_kyc_checks; i++) 540 { 541 struct TALER_KYCLOGIC_KycCheck *kyc_check 542 = kyc_checks[i]; 543 544 if (0 == strcasecmp (check_name, 545 kyc_check->check_name)) 546 return kyc_check; 547 } 548 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 549 "Check `%s' unknown\n", 550 check_name); 551 return NULL; 552 } 553 554 555 /** 556 * Lookup AML program by @a program_name 557 * 558 * @param program_name name to search for 559 * @return NULL if not found 560 */ 561 static struct TALER_KYCLOGIC_AmlProgram * 562 find_program (const char *program_name) 563 { 564 if (NULL == program_name) 565 { 566 GNUNET_break (0); 567 return NULL; 568 } 569 for (unsigned int i = 0; i<num_aml_programs; i++) 570 { 571 struct TALER_KYCLOGIC_AmlProgram *program 572 = aml_programs[i]; 573 574 if (0 == strcasecmp (program_name, 575 program->program_name)) 576 return program; 577 } 578 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 579 "AML program `%s' unknown\n", 580 program_name); 581 return NULL; 582 } 583 584 585 /** 586 * Lookup KYC provider by @a provider_name 587 * 588 * @param provider_name name to search for 589 * @return NULL if not found 590 */ 591 static struct TALER_KYCLOGIC_KycProvider * 592 find_provider (const char *provider_name) 593 { 594 for (unsigned int i = 0; i<num_kyc_providers; i++) 595 { 596 struct TALER_KYCLOGIC_KycProvider *provider 597 = kyc_providers[i]; 598 599 if (0 == strcasecmp (provider_name, 600 provider->provider_name)) 601 return provider; 602 } 603 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 604 "KYC provider `%s' unknown\n", 605 provider_name); 606 return NULL; 607 } 608 609 610 /** 611 * Check that @a measure is well-formed and internally 612 * consistent. 613 * 614 * @param measure measure to check 615 * @return true if measure is well-formed 616 */ 617 static bool 618 check_measure (const struct TALER_KYCLOGIC_Measure *measure) 619 { 620 const struct TALER_KYCLOGIC_KycCheck *check; 621 622 if (! ascii_lower (measure->measure_name)) 623 { 624 GNUNET_break (0); 625 return false; 626 } 627 if (! ascii_lower (measure->check_name)) 628 { 629 GNUNET_break (0); 630 return false; 631 } 632 if ( (NULL != measure->prog_name) && 633 (! ascii_lower (measure->prog_name)) ) 634 { 635 GNUNET_break (0); 636 return false; 637 } 638 639 if (0 == strcasecmp (measure->check_name, 640 "skip")) 641 { 642 check = NULL; 643 } 644 else 645 { 646 check = find_check (measure->check_name); 647 if (NULL == check) 648 { 649 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 650 "Unknown check `%s' used in measure `%s'\n", 651 measure->check_name, 652 measure->measure_name); 653 return false; 654 } 655 } 656 if ( (NULL == check) || 657 (TALER_KYCLOGIC_CT_INFO != check->type) ) 658 { 659 const struct TALER_KYCLOGIC_AmlProgram *program; 660 661 program = find_program (measure->prog_name); 662 if (NULL == program) 663 { 664 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 665 "Unknown program `%s' used in measure `%s'\n", 666 measure->prog_name, 667 measure->measure_name); 668 return false; 669 } 670 for (unsigned int j = 0; j<program->num_required_contexts; j++) 671 { 672 const char *required_context = program->required_contexts[j]; 673 674 if (NULL == 675 json_object_get (measure->context, 676 required_context)) 677 { 678 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 679 "Measure `%s' lacks required context `%s' for AML program `%s'\n", 680 measure->measure_name, 681 required_context, 682 program->program_name); 683 return false; 684 } 685 } 686 if (0 == strcasecmp (measure->check_name, 687 "skip")) 688 { 689 if (0 != program->num_required_attributes) 690 { 691 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 692 "AML program `%s' of measure `%s' has required attributes, but check is of type `skip' and thus cannot provide any!\n", 693 program->program_name, 694 measure->measure_name); 695 return false; 696 } 697 return true; 698 } 699 for (unsigned int j = 0; j<program->num_required_attributes; j++) 700 { 701 const char *required_attribute = program->required_attributes[j]; 702 bool found = false; 703 704 if (NULL != check) 705 { 706 for (unsigned int i = 0; i<check->num_outputs; i++) 707 { 708 if (0 == strcasecmp (required_attribute, 709 check->outputs[i])) 710 { 711 found = true; 712 break; 713 } 714 } 715 } 716 if (! found) 717 { 718 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 719 "Check `%s' of measure `%s' does not provide required output `%s' for AML program `%s'\n", 720 measure->check_name, 721 measure->measure_name, 722 required_attribute, 723 program->program_name); 724 return false; 725 } 726 } 727 } 728 else 729 { 730 /* Check is of type "INFO" */ 731 if (NULL != measure->prog_name) 732 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 733 "Program `%s' used in INFO measure `%s' will never be used.\n", 734 measure->prog_name, 735 measure->measure_name); 736 if (0 == strcasecmp (measure->check_name, 737 "skip")) 738 { 739 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 740 "INFO check of measure `%s' should not be called `skip'.\n", 741 measure->measure_name); 742 return false; 743 } 744 } 745 if (NULL != check) 746 { 747 for (unsigned int j = 0; j<check->num_requires; j++) 748 { 749 const char *required_input = check->requires[j]; 750 751 if (NULL == 752 json_object_get (measure->context, 753 required_input)) 754 { 755 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 756 "Measure `%s' lacks required context `%s' for check `%s'\n", 757 measure->measure_name, 758 required_input, 759 measure->check_name); 760 return false; 761 } 762 } 763 } 764 return true; 765 } 766 767 768 /** 769 * Find measure @a measure_name in @a lrs. 770 * If measure is not found in @a lrs, fall back to 771 * default measures. 772 * 773 * @param lrs rule set to search, can be NULL to only search default measures 774 * @param measure_name name of measure to find 775 * @return NULL if not found, otherwise the measure 776 */ 777 static const struct TALER_KYCLOGIC_Measure * 778 find_measure ( 779 const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs, 780 const char *measure_name) 781 { 782 if (NULL != lrs) 783 { 784 for (unsigned int i = 0; i<lrs->num_custom_measures; i++) 785 { 786 const struct TALER_KYCLOGIC_Measure *cm 787 = &lrs->custom_measures[i]; 788 789 if (0 == strcasecmp (measure_name, 790 cm->measure_name)) 791 return cm; 792 } 793 } 794 if (lrs != &default_rules) 795 { 796 /* Try measures from default rules */ 797 for (unsigned int i = 0; i<default_rules.num_custom_measures; i++) 798 { 799 const struct TALER_KYCLOGIC_Measure *cm 800 = &default_rules.custom_measures[i]; 801 802 if (0 == strcasecmp (measure_name, 803 cm->measure_name)) 804 return cm; 805 } 806 } 807 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 808 "Measure `%s' not found\n", 809 measure_name); 810 return NULL; 811 } 812 813 814 struct TALER_KYCLOGIC_LegitimizationRuleSet * 815 TALER_KYCLOGIC_rules_parse (const json_t *jlrs) 816 { 817 struct GNUNET_TIME_Timestamp expiration_time; 818 const char *successor_measure = NULL; 819 const json_t *jrules; 820 const json_t *jcustom_measures; 821 struct GNUNET_JSON_Specification spec[] = { 822 GNUNET_JSON_spec_timestamp ( 823 "expiration_time", 824 &expiration_time), 825 GNUNET_JSON_spec_mark_optional ( 826 GNUNET_JSON_spec_string ( 827 "successor_measure", 828 &successor_measure), 829 NULL), 830 GNUNET_JSON_spec_array_const ("rules", 831 &jrules), 832 GNUNET_JSON_spec_object_const ("custom_measures", 833 &jcustom_measures), 834 GNUNET_JSON_spec_end () 835 }; 836 struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs; 837 const char *err; 838 unsigned int line; 839 840 if (NULL == jlrs) 841 { 842 GNUNET_break_op (0); 843 return NULL; 844 } 845 if (GNUNET_OK != 846 GNUNET_JSON_parse (jlrs, 847 spec, 848 &err, 849 &line)) 850 { 851 GNUNET_break_op (0); 852 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 853 "Legitimization rules have incorrect input field `%s'\n", 854 err); 855 json_dumpf (jlrs, 856 stderr, 857 JSON_INDENT (2)); 858 return NULL; 859 } 860 lrs = GNUNET_new (struct TALER_KYCLOGIC_LegitimizationRuleSet); 861 lrs->expiration_time = expiration_time; 862 lrs->successor_measure 863 = (NULL == successor_measure) 864 ? NULL 865 : GNUNET_strdup (successor_measure); 866 if ( (NULL != lrs->successor_measure) && 867 (! ascii_lower (lrs->successor_measure)) ) 868 { 869 GNUNET_break (0); 870 goto cleanup; 871 } 872 lrs->num_custom_measures 873 = (unsigned int) json_object_size (jcustom_measures); 874 if (((size_t) lrs->num_custom_measures) != 875 json_object_size (jcustom_measures)) 876 { 877 GNUNET_break (0); 878 goto cleanup; 879 } 880 881 if (0 != lrs->num_custom_measures) 882 { 883 lrs->custom_measures 884 = GNUNET_new_array (lrs->num_custom_measures, 885 struct TALER_KYCLOGIC_Measure); 886 887 { 888 const json_t *jmeasure; 889 const char *measure_name; 890 unsigned int off = 0; 891 892 json_object_foreach ((json_t *) jcustom_measures, 893 measure_name, 894 jmeasure) 895 { 896 const char *check_name; 897 const char *prog_name = NULL; 898 const json_t *context = NULL; 899 bool voluntary = false; 900 struct TALER_KYCLOGIC_Measure *measure 901 = &lrs->custom_measures[off++]; 902 struct GNUNET_JSON_Specification ispec[] = { 903 GNUNET_JSON_spec_string ("check_name", 904 &check_name), 905 GNUNET_JSON_spec_mark_optional ( 906 GNUNET_JSON_spec_string ("prog_name", 907 &prog_name), 908 NULL), 909 GNUNET_JSON_spec_mark_optional ( 910 GNUNET_JSON_spec_object_const ("context", 911 &context), 912 NULL), 913 GNUNET_JSON_spec_mark_optional ( 914 GNUNET_JSON_spec_bool ("voluntary", 915 &voluntary), 916 NULL), 917 GNUNET_JSON_spec_end () 918 }; 919 920 if (GNUNET_OK != 921 GNUNET_JSON_parse (jmeasure, 922 ispec, 923 NULL, NULL)) 924 { 925 GNUNET_break_op (0); 926 goto cleanup; 927 } 928 measure->measure_name 929 = GNUNET_strdup (measure_name); 930 measure->check_name 931 = GNUNET_strdup (check_name); 932 if (NULL != prog_name) 933 measure->prog_name 934 = GNUNET_strdup (prog_name); 935 measure->voluntary 936 = voluntary; 937 if (NULL != context) 938 measure->context 939 = json_incref ((json_t*) context); 940 if (! check_measure (measure)) 941 { 942 GNUNET_break_op (0); 943 goto cleanup; 944 } 945 } 946 } 947 } 948 949 lrs->num_kyc_rules 950 = (unsigned int) json_array_size (jrules); 951 if (((size_t) lrs->num_kyc_rules) != 952 json_array_size (jrules)) 953 { 954 GNUNET_break (0); 955 goto cleanup; 956 } 957 lrs->kyc_rules 958 = GNUNET_new_array (lrs->num_kyc_rules, 959 struct TALER_KYCLOGIC_KycRule); 960 { 961 const json_t *jrule; 962 size_t off; 963 964 json_array_foreach ((json_t *) jrules, 965 off, 966 jrule) 967 { 968 struct TALER_KYCLOGIC_KycRule *rule 969 = &lrs->kyc_rules[off]; 970 const json_t *jmeasures; 971 const char *rn = NULL; 972 struct GNUNET_JSON_Specification ispec[] = { 973 TALER_JSON_spec_kycte ("operation_type", 974 &rule->trigger), 975 TALER_JSON_spec_amount ("threshold", 976 my_currency, 977 &rule->threshold), 978 GNUNET_JSON_spec_relative_time ("timeframe", 979 &rule->timeframe), 980 GNUNET_JSON_spec_array_const ("measures", 981 &jmeasures), 982 GNUNET_JSON_spec_uint32 ("display_priority", 983 &rule->display_priority), 984 GNUNET_JSON_spec_mark_optional ( 985 GNUNET_JSON_spec_bool ("exposed", 986 &rule->exposed), 987 NULL), 988 GNUNET_JSON_spec_mark_optional ( 989 GNUNET_JSON_spec_string ("rule_name", 990 &rn), 991 NULL), 992 GNUNET_JSON_spec_mark_optional ( 993 GNUNET_JSON_spec_bool ("is_and_combinator", 994 &rule->is_and_combinator), 995 NULL), 996 GNUNET_JSON_spec_end () 997 }; 998 999 if (GNUNET_OK != 1000 GNUNET_JSON_parse (jrule, 1001 ispec, 1002 NULL, NULL)) 1003 { 1004 GNUNET_break_op (0); 1005 goto cleanup; 1006 } 1007 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1008 "Parsed KYC rule %u for %d with threshold %s\n", 1009 (unsigned int) off, 1010 (int) rule->trigger, 1011 TALER_amount2s (&rule->threshold)); 1012 rule->lrs = lrs; 1013 if (NULL != rn) 1014 rule->rule_name = GNUNET_strdup (rn); 1015 rule->num_measures = json_array_size (jmeasures); 1016 rule->next_measures 1017 = GNUNET_new_array (rule->num_measures, 1018 char *); 1019 if (((size_t) rule->num_measures) != 1020 json_array_size (jmeasures)) 1021 { 1022 GNUNET_break (0); 1023 goto cleanup; 1024 } 1025 { 1026 size_t j; 1027 json_t *jmeasure; 1028 1029 json_array_foreach (jmeasures, 1030 j, 1031 jmeasure) 1032 { 1033 const char *str; 1034 1035 str = json_string_value (jmeasure); 1036 if (NULL == str) 1037 { 1038 GNUNET_break (0); 1039 goto cleanup; 1040 } 1041 if (0 == strcasecmp (str, 1042 KYC_MEASURE_IMPOSSIBLE)) 1043 { 1044 rule->verboten = true; 1045 continue; 1046 } 1047 1048 rule->next_measures[j] 1049 = GNUNET_strdup (str); 1050 if (! ascii_lower (rule->next_measures[j])) 1051 { 1052 GNUNET_break (0); 1053 goto cleanup; 1054 } 1055 if (NULL == 1056 find_measure (lrs, 1057 rule->next_measures[j])) 1058 { 1059 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1060 "Measure `%s' specified in rule set unknown\n", 1061 str); 1062 GNUNET_break_op (0); 1063 goto cleanup; 1064 } 1065 } 1066 } 1067 } 1068 } 1069 return lrs; 1070 cleanup: 1071 TALER_KYCLOGIC_rules_free (lrs); 1072 return NULL; 1073 } 1074 1075 1076 /** 1077 * Free rules in @a lrs but not @a lrs itself. 1078 * 1079 * @param[in,out] lrs rule set to free 1080 */ 1081 static void 1082 free_rules (struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs) 1083 { 1084 if (NULL == lrs) 1085 return; 1086 for (unsigned int i = 0; i<lrs->num_kyc_rules; i++) 1087 { 1088 struct TALER_KYCLOGIC_KycRule *rule 1089 = &lrs->kyc_rules[i]; 1090 1091 for (unsigned int j = 0; j<rule->num_measures; j++) 1092 GNUNET_free (rule->next_measures[j]); 1093 GNUNET_array_grow (rule->next_measures, 1094 rule->num_measures, 1095 0); 1096 GNUNET_free (rule->rule_name); 1097 } 1098 GNUNET_array_grow (lrs->kyc_rules, 1099 lrs->num_kyc_rules, 1100 0); 1101 for (unsigned int i = 0; i<lrs->num_custom_measures; i++) 1102 { 1103 struct TALER_KYCLOGIC_Measure *measure 1104 = &lrs->custom_measures[i]; 1105 1106 GNUNET_free (measure->measure_name); 1107 GNUNET_free (measure->check_name); 1108 GNUNET_free (measure->prog_name); 1109 json_decref (measure->context); 1110 } 1111 GNUNET_array_grow (lrs->custom_measures, 1112 lrs->num_custom_measures, 1113 0); 1114 GNUNET_free (lrs->successor_measure); 1115 } 1116 1117 1118 void 1119 TALER_KYCLOGIC_rules_free (struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs) 1120 { 1121 if (NULL == lrs) 1122 return; 1123 free_rules (lrs); 1124 GNUNET_free (lrs); 1125 } 1126 1127 1128 const char * 1129 TALER_KYCLOGIC_rule2s ( 1130 const struct TALER_KYCLOGIC_KycRule *r) 1131 { 1132 return r->rule_name; 1133 } 1134 1135 1136 const char * 1137 TALER_KYCLOGIC_status2s (enum TALER_KYCLOGIC_KycStatus status) 1138 { 1139 switch (status) 1140 { 1141 case TALER_KYCLOGIC_STATUS_SUCCESS: 1142 return "success"; 1143 case TALER_KYCLOGIC_STATUS_USER: 1144 return "user"; 1145 case TALER_KYCLOGIC_STATUS_PROVIDER: 1146 return "provider"; 1147 case TALER_KYCLOGIC_STATUS_FAILED: 1148 return "failed"; 1149 case TALER_KYCLOGIC_STATUS_PENDING: 1150 return "pending"; 1151 case TALER_KYCLOGIC_STATUS_ABORTED: 1152 return "aborted"; 1153 case TALER_KYCLOGIC_STATUS_USER_PENDING: 1154 return "pending with user"; 1155 case TALER_KYCLOGIC_STATUS_PROVIDER_PENDING: 1156 return "pending at provider"; 1157 case TALER_KYCLOGIC_STATUS_USER_ABORTED: 1158 return "aborted by user"; 1159 case TALER_KYCLOGIC_STATUS_PROVIDER_FAILED: 1160 return "failed by provider"; 1161 case TALER_KYCLOGIC_STATUS_KEEP: 1162 return "keep"; 1163 case TALER_KYCLOGIC_STATUS_INTERNAL_ERROR: 1164 return "internal error"; 1165 } 1166 return "unknown status"; 1167 } 1168 1169 1170 json_t * 1171 TALER_KYCLOGIC_rules_to_limits (const json_t *jrules, 1172 enum GNUNET_GenericReturnValue is_wallet) 1173 { 1174 if (NULL == jrules) 1175 { 1176 /* default limits apply */ 1177 const struct TALER_KYCLOGIC_KycRule *rules 1178 = default_rules.kyc_rules; 1179 unsigned int num_rules 1180 = default_rules.num_kyc_rules; 1181 json_t *jlimits; 1182 1183 jlimits = json_array (); 1184 GNUNET_assert (NULL != jlimits); 1185 for (unsigned int i = 0; i<num_rules; i++) 1186 { 1187 const struct TALER_KYCLOGIC_KycRule *rule = &rules[i]; 1188 json_t *limit; 1189 1190 if (! rule->exposed) 1191 continue; 1192 if (! trigger_applies (rule->trigger, 1193 is_wallet)) 1194 continue; 1195 limit = GNUNET_JSON_PACK ( 1196 GNUNET_JSON_pack_allow_null ( 1197 GNUNET_JSON_pack_string ("rule_name", 1198 rule->rule_name)), 1199 GNUNET_JSON_pack_bool ("soft_limit", 1200 ! rule->verboten), 1201 TALER_JSON_pack_kycte ("operation_type", 1202 rule->trigger), 1203 GNUNET_JSON_pack_time_rel ("timeframe", 1204 rule->timeframe), 1205 TALER_JSON_pack_amount ("threshold", 1206 &rule->threshold) 1207 ); 1208 GNUNET_assert (0 == 1209 json_array_append_new (jlimits, 1210 limit)); 1211 } 1212 return jlimits; 1213 } 1214 1215 { 1216 const json_t *rules; 1217 json_t *limits; 1218 json_t *limit; 1219 json_t *rule; 1220 size_t idx; 1221 1222 rules = json_object_get (jrules, 1223 "rules"); 1224 limits = json_array (); 1225 GNUNET_assert (NULL != limits); 1226 json_array_foreach ((json_t *) rules, idx, rule) 1227 { 1228 struct GNUNET_TIME_Relative timeframe; 1229 struct TALER_Amount threshold; 1230 bool exposed = false; 1231 const json_t *jmeasures; 1232 const char *rule_name = NULL; 1233 enum TALER_KYCLOGIC_KycTriggerEvent operation_type; 1234 struct GNUNET_JSON_Specification spec[] = { 1235 TALER_JSON_spec_kycte ("operation_type", 1236 &operation_type), 1237 GNUNET_JSON_spec_relative_time ("timeframe", 1238 &timeframe), 1239 TALER_JSON_spec_amount ("threshold", 1240 my_currency, 1241 &threshold), 1242 GNUNET_JSON_spec_array_const ("measures", 1243 &jmeasures), 1244 GNUNET_JSON_spec_mark_optional ( 1245 GNUNET_JSON_spec_bool ("exposed", 1246 &exposed), 1247 NULL), 1248 GNUNET_JSON_spec_mark_optional ( 1249 GNUNET_JSON_spec_string ("rule_name", 1250 &rule_name), 1251 NULL), 1252 GNUNET_JSON_spec_end () 1253 }; 1254 bool forbidden = false; 1255 size_t i; 1256 json_t *jmeasure; 1257 1258 if (GNUNET_OK != 1259 GNUNET_JSON_parse (rule, 1260 spec, 1261 NULL, NULL)) 1262 { 1263 GNUNET_break_op (0); 1264 json_decref (limits); 1265 return NULL; 1266 } 1267 if (! exposed) 1268 continue; 1269 if (! trigger_applies (operation_type, 1270 is_wallet)) 1271 { 1272 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1273 "Skipping rule #%u that does not apply to %s\n", 1274 (unsigned int) idx, 1275 is_wallet ? "wallets" : "accounts"); 1276 json_dumpf (rule, 1277 stderr, 1278 JSON_INDENT (2)); 1279 continue; 1280 } 1281 json_array_foreach (jmeasures, i, jmeasure) 1282 { 1283 const char *val; 1284 1285 val = json_string_value (jmeasure); 1286 if (NULL == val) 1287 { 1288 GNUNET_break_op (0); 1289 json_decref (limits); 1290 return NULL; 1291 } 1292 if (0 == strcasecmp (KYC_MEASURE_IMPOSSIBLE, 1293 val)) 1294 forbidden = true; 1295 } 1296 1297 limit = GNUNET_JSON_PACK ( 1298 GNUNET_JSON_pack_allow_null ( 1299 GNUNET_JSON_pack_string ("rule_name", 1300 rule_name)), 1301 TALER_JSON_pack_kycte ( 1302 "operation_type", 1303 operation_type), 1304 GNUNET_JSON_pack_time_rel ( 1305 "timeframe", 1306 timeframe), 1307 TALER_JSON_pack_amount ( 1308 "threshold", 1309 &threshold), 1310 /* optional since v21, defaults to 'false' */ 1311 GNUNET_JSON_pack_bool ( 1312 "soft_limit", 1313 ! forbidden)); 1314 GNUNET_assert (0 == 1315 json_array_append_new (limits, 1316 limit)); 1317 } 1318 return limits; 1319 } 1320 } 1321 1322 1323 bool 1324 TALER_KYCLOGIC_rules_require_tos_acceptance (const json_t *jrules) 1325 { 1326 struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs; 1327 const struct TALER_KYCLOGIC_LegitimizationRuleSet *rs; 1328 bool found = false; 1329 1330 if (NULL == jrules) 1331 { 1332 /* default rules apply */ 1333 lrs = NULL; 1334 rs = &default_rules; 1335 } 1336 else 1337 { 1338 lrs = TALER_KYCLOGIC_rules_parse (jrules); 1339 if (NULL == lrs) 1340 { 1341 GNUNET_break_op (0); 1342 return false; 1343 } 1344 rs = lrs; 1345 } 1346 for (unsigned int i = 0; (! found) && (i < rs->num_kyc_rules); i++) 1347 { 1348 const struct TALER_KYCLOGIC_KycRule *rule = &rs->kyc_rules[i]; 1349 1350 if (rule->verboten) 1351 continue; /* verboten rules can never be satisfied and their 1352 next_measures[] entries are NULL (see rules_parse), 1353 so they never contribute a ToS-acceptance requirement */ 1354 for (unsigned int j = 0; j < rule->num_measures; j++) 1355 { 1356 const struct TALER_KYCLOGIC_Measure *m; 1357 const struct TALER_KYCLOGIC_KycCheck *c; 1358 1359 /* Resolve the measure to its check exactly as GET /kyc-info does 1360 (measure -> check -> form), so that our answer is consistent 1361 with the requirements the merchant will observe there. */ 1362 m = find_measure (lrs, 1363 rule->next_measures[j]); 1364 if (NULL == m) 1365 continue; 1366 c = find_check (m->check_name); 1367 if (NULL == c) 1368 continue; 1369 if ( (TALER_KYCLOGIC_CT_FORM == c->type) && 1370 (NULL != c->details.form.name) && 1371 (0 == strcasecmp (c->details.form.name, 1372 TALER_KYCLOGIC_TOS_ACCEPTANCE_FORM)) ) 1373 { 1374 found = true; 1375 break; 1376 } 1377 } 1378 } 1379 if (NULL != lrs) 1380 TALER_KYCLOGIC_rules_free (lrs); 1381 return found; 1382 } 1383 1384 1385 const struct TALER_KYCLOGIC_Measure * 1386 TALER_KYCLOGIC_rule_get_instant_measure ( 1387 const struct TALER_KYCLOGIC_KycRule *r) 1388 { 1389 const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs 1390 = r->lrs; 1391 1392 if (r->verboten) 1393 return NULL; 1394 for (unsigned int i = 0; i<r->num_measures; i++) 1395 { 1396 const char *measure_name = r->next_measures[i]; 1397 const struct TALER_KYCLOGIC_Measure *ms; 1398 1399 if (0 == strcasecmp (measure_name, 1400 KYC_MEASURE_IMPOSSIBLE)) 1401 { 1402 /* If any of the measures if verboten, we do not even 1403 consider execution of the instant measure. */ 1404 return NULL; 1405 } 1406 1407 ms = find_measure (lrs, 1408 measure_name); 1409 if (NULL == ms) 1410 { 1411 GNUNET_break (0); 1412 return NULL; 1413 } 1414 if (0 == strcasecmp (ms->check_name, 1415 "skip")) 1416 return ms; 1417 } 1418 return NULL; 1419 } 1420 1421 1422 json_t * 1423 TALER_KYCLOGIC_rule_to_measures ( 1424 const struct TALER_KYCLOGIC_KycRule *r) 1425 { 1426 const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs 1427 = r->lrs; 1428 json_t *jmeasures; 1429 1430 jmeasures = json_array (); 1431 GNUNET_assert (NULL != jmeasures); 1432 if (! r->verboten) 1433 { 1434 for (unsigned int i = 0; i<r->num_measures; i++) 1435 { 1436 const char *measure_name = r->next_measures[i]; 1437 const struct TALER_KYCLOGIC_Measure *ms; 1438 json_t *mi; 1439 1440 if (0 == 1441 strcasecmp (measure_name, 1442 KYC_MEASURE_IMPOSSIBLE)) 1443 { 1444 /* This case should be covered via the 'verboten' flag! */ 1445 GNUNET_break (0); 1446 continue; 1447 } 1448 ms = find_measure (lrs, 1449 measure_name); 1450 if (NULL == ms) 1451 { 1452 GNUNET_break (0); 1453 json_decref (jmeasures); 1454 return NULL; 1455 } 1456 mi = GNUNET_JSON_PACK ( 1457 GNUNET_JSON_pack_string ("check_name", 1458 ms->check_name), 1459 GNUNET_JSON_pack_allow_null ( 1460 GNUNET_JSON_pack_string ("prog_name", 1461 ms->prog_name)), 1462 GNUNET_JSON_pack_allow_null ( 1463 GNUNET_JSON_pack_object_incref ("context", 1464 ms->context))); 1465 GNUNET_assert (0 == 1466 json_array_append_new (jmeasures, 1467 mi)); 1468 } 1469 } 1470 1471 return GNUNET_JSON_PACK ( 1472 GNUNET_JSON_pack_array_steal ("measures", 1473 jmeasures), 1474 GNUNET_JSON_pack_bool ("is_and_combinator", 1475 r->is_and_combinator), 1476 GNUNET_JSON_pack_bool ("verboten", 1477 r->verboten)); 1478 } 1479 1480 1481 json_t * 1482 TALER_KYCLOGIC_zero_measures ( 1483 const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs, 1484 enum GNUNET_GenericReturnValue is_wallet) 1485 { 1486 json_t *zero_measures; 1487 const struct TALER_KYCLOGIC_KycRule *rules; 1488 unsigned int num_zero_measures = 0; 1489 1490 if (NULL == lrs) 1491 lrs = &default_rules; 1492 rules = lrs->kyc_rules; 1493 zero_measures = json_array (); 1494 GNUNET_assert (NULL != zero_measures); 1495 for (unsigned int i = 0; i<lrs->num_kyc_rules; i++) 1496 { 1497 const struct TALER_KYCLOGIC_KycRule *rule = &rules[i]; 1498 1499 if (! rule->exposed) 1500 continue; 1501 if (rule->verboten) 1502 continue; /* see: hard_limits */ 1503 if (! trigger_applies (rule->trigger, 1504 is_wallet)) 1505 continue; 1506 if (! TALER_amount_is_zero (&rule->threshold)) 1507 continue; 1508 for (unsigned int j = 0; j<rule->num_measures; j++) 1509 { 1510 const struct TALER_KYCLOGIC_Measure *ms; 1511 json_t *mi; 1512 1513 ms = find_measure (lrs, 1514 rule->next_measures[j]); 1515 if (NULL == ms) 1516 { 1517 /* Error in the configuration, should've been 1518 * caught before. We simply ignore the bad measure. */ 1519 GNUNET_break (0); 1520 continue; 1521 } 1522 if (0 == strcasecmp (KYC_MEASURE_IMPOSSIBLE, 1523 ms->check_name)) 1524 continue; /* not a measure to be selected */ 1525 mi = GNUNET_JSON_PACK ( 1526 GNUNET_JSON_pack_allow_null ( 1527 GNUNET_JSON_pack_string ("rule_name", 1528 rule->rule_name)), 1529 TALER_JSON_pack_kycte ("operation_type", 1530 rule->trigger), 1531 GNUNET_JSON_pack_string ("check_name", 1532 ms->check_name), 1533 GNUNET_JSON_pack_allow_null ( 1534 GNUNET_JSON_pack_string ("prog_name", 1535 ms->prog_name)), 1536 GNUNET_JSON_pack_allow_null ( 1537 GNUNET_JSON_pack_object_incref ("context", 1538 ms->context))); 1539 GNUNET_assert (0 == 1540 json_array_append_new (zero_measures, 1541 mi)); 1542 num_zero_measures++; 1543 } 1544 } 1545 if (0 == num_zero_measures) 1546 { 1547 json_decref (zero_measures); 1548 return NULL; 1549 } 1550 return GNUNET_JSON_PACK ( 1551 GNUNET_JSON_pack_array_steal ("measures", 1552 zero_measures), 1553 /* Zero-measures are always OR */ 1554 GNUNET_JSON_pack_bool ("is_and_combinator", 1555 false), 1556 /* OR means verboten measures do not matter */ 1557 GNUNET_JSON_pack_bool ("verboten", 1558 false)); 1559 } 1560 1561 1562 /** 1563 * Check if @a ms is a voluntary measure, and if so 1564 * convert to JSON and append to @a voluntary_measures. 1565 * 1566 * @param[in,out] voluntary_measures JSON array of MeasureInformation 1567 * @param ms a measure to possibly append 1568 */ 1569 static void 1570 append_voluntary_measure ( 1571 json_t *voluntary_measures, 1572 const struct TALER_KYCLOGIC_Measure *ms) 1573 { 1574 #if 0 1575 json_t *mj; 1576 #endif 1577 1578 if (! ms->voluntary) 1579 return; 1580 if (0 == strcasecmp (KYC_MEASURE_IMPOSSIBLE, 1581 ms->check_name)) 1582 return; /* very strange configuration */ 1583 #if 0 1584 /* FIXME: support vATTEST-#9048 (this API in kyclogic!) */ 1585 // NOTE: need to convert ms to "KycRequirementInformation" 1586 // *and* in particular generate "id" values that 1587 // are then understood to refer to the voluntary measures 1588 // by the rest of the API (which is the hard part!) 1589 // => need to change the API to encode the 1590 // legitimization_outcomes row ID of the lrs from 1591 // which the voluntary 'ms' originated, and 1592 // then update the kyc-upload/kyc-start endpoints 1593 // to recognize the new ID format! 1594 mj = GNUNET_JSON_PACK ( 1595 GNUNET_JSON_pack_string ("check_name", 1596 ms->check_name), 1597 GNUNET_JSON_pack_allow_null ( 1598 GNUNET_JSON_pack_string ("prog_name", 1599 ms->prog_name)), 1600 GNUNET_JSON_pack_allow_null ( 1601 GNUNET_JSON_pack_object_incref ("context", 1602 ms->context))); 1603 GNUNET_assert (0 == 1604 json_array_append_new (voluntary_measures, 1605 mj)); 1606 #endif 1607 } 1608 1609 1610 json_t * 1611 TALER_KYCLOGIC_voluntary_measures ( 1612 const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs) 1613 { 1614 json_t *voluntary_measures; 1615 1616 voluntary_measures = json_array (); 1617 GNUNET_assert (NULL != voluntary_measures); 1618 if (NULL != lrs) 1619 { 1620 for (unsigned int i = 0; i<lrs->num_custom_measures; i++) 1621 { 1622 const struct TALER_KYCLOGIC_Measure *ms 1623 = &lrs->custom_measures[i]; 1624 1625 append_voluntary_measure (voluntary_measures, 1626 ms); 1627 } 1628 } 1629 for (unsigned int i = 0; i<default_rules.num_custom_measures; i++) 1630 { 1631 const struct TALER_KYCLOGIC_Measure *ms 1632 = &default_rules.custom_measures[i]; 1633 1634 append_voluntary_measure (voluntary_measures, 1635 ms); 1636 } 1637 return voluntary_measures; 1638 } 1639 1640 1641 const struct TALER_KYCLOGIC_Measure * 1642 TALER_KYCLOGIC_get_instant_measure ( 1643 const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs, 1644 const char *measures_spec) 1645 { 1646 char *nm; 1647 const struct TALER_KYCLOGIC_Measure *ret = NULL; 1648 1649 GNUNET_assert (NULL != measures_spec); 1650 1651 if ('+' == measures_spec[0]) 1652 { 1653 nm = GNUNET_strdup (&measures_spec[1]); 1654 } 1655 else 1656 { 1657 nm = GNUNET_strdup (measures_spec); 1658 } 1659 if (! token_list_lower (nm)) 1660 { 1661 GNUNET_break (0); 1662 GNUNET_free (nm); 1663 return NULL; 1664 } 1665 for (const char *tok = strtok (nm, " "); 1666 NULL != tok; 1667 tok = strtok (NULL, " ")) 1668 { 1669 const struct TALER_KYCLOGIC_Measure *ms; 1670 1671 if (0 == strcasecmp (KYC_MEASURE_IMPOSSIBLE, 1672 tok)) 1673 { 1674 continue; 1675 } 1676 ms = find_measure (lrs, 1677 tok); 1678 if (NULL == ms) 1679 { 1680 GNUNET_break (0); 1681 continue; 1682 } 1683 if (0 == strcasecmp (KYC_MEASURE_IMPOSSIBLE, 1684 ms->check_name)) 1685 { 1686 continue; 1687 } 1688 if (0 == strcasecmp ("skip", 1689 ms->check_name)) 1690 { 1691 ret = ms; 1692 goto done; 1693 } 1694 } 1695 done: 1696 GNUNET_free (nm); 1697 return ret; 1698 } 1699 1700 1701 const struct TALER_KYCLOGIC_Measure * 1702 TALER_KYCLOGIC_get_measure ( 1703 const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs, 1704 const char *measure_name) 1705 { 1706 return find_measure (lrs, 1707 measure_name); 1708 } 1709 1710 1711 json_t * 1712 TALER_KYCLOGIC_get_jmeasures ( 1713 const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs, 1714 const char *measures_spec) 1715 { 1716 json_t *jmeasures; 1717 char *nm; 1718 bool verboten = false; 1719 bool is_and = false; 1720 1721 if ('+' == measures_spec[0]) 1722 { 1723 nm = GNUNET_strdup (&measures_spec[1]); 1724 is_and = true; 1725 } 1726 else 1727 { 1728 nm = GNUNET_strdup (measures_spec); 1729 } 1730 if (! token_list_lower (nm)) 1731 { 1732 GNUNET_break (0); 1733 GNUNET_free (nm); 1734 return NULL; 1735 } 1736 jmeasures = json_array (); 1737 GNUNET_assert (NULL != jmeasures); 1738 for (const char *tok = strtok (nm, " "); 1739 NULL != tok; 1740 tok = strtok (NULL, " ")) 1741 { 1742 const struct TALER_KYCLOGIC_Measure *ms; 1743 json_t *mi; 1744 1745 if (0 == strcasecmp (KYC_MEASURE_IMPOSSIBLE, 1746 tok)) 1747 { 1748 verboten = true; 1749 continue; 1750 } 1751 ms = find_measure (lrs, 1752 tok); 1753 if (NULL == ms) 1754 { 1755 /* A caller can supply an unknown measure name. That is a protocol 1756 violation, not an invariant violation in the exchange. */ 1757 GNUNET_break_op (0); 1758 GNUNET_free (nm); 1759 json_decref (jmeasures); 1760 return NULL; 1761 } 1762 mi = GNUNET_JSON_PACK ( 1763 GNUNET_JSON_pack_string ("check_name", 1764 ms->check_name), 1765 GNUNET_JSON_pack_allow_null ( 1766 GNUNET_JSON_pack_string ("prog_name", 1767 ms->prog_name)), 1768 GNUNET_JSON_pack_allow_null ( 1769 GNUNET_JSON_pack_object_incref ("context", 1770 ms->context))); 1771 GNUNET_assert (0 == 1772 json_array_append_new (jmeasures, 1773 mi)); 1774 } 1775 GNUNET_free (nm); 1776 return GNUNET_JSON_PACK ( 1777 GNUNET_JSON_pack_array_steal ("measures", 1778 jmeasures), 1779 GNUNET_JSON_pack_bool ("is_and_combinator", 1780 is_and), 1781 GNUNET_JSON_pack_bool ("verboten", 1782 verboten)); 1783 } 1784 1785 1786 json_t * 1787 TALER_KYCLOGIC_check_to_jmeasures ( 1788 const struct TALER_KYCLOGIC_KycCheckContext *kcc) 1789 { 1790 const struct TALER_KYCLOGIC_KycCheck *check 1791 = kcc->check; 1792 json_t *jmeasures; 1793 json_t *mi; 1794 1795 mi = GNUNET_JSON_PACK ( 1796 GNUNET_JSON_pack_string ("check_name", 1797 NULL == check 1798 ? "skip" 1799 : check->check_name), 1800 GNUNET_JSON_pack_allow_null ( 1801 GNUNET_JSON_pack_string ("prog_name", 1802 kcc->prog_name)), 1803 GNUNET_JSON_pack_allow_null ( 1804 GNUNET_JSON_pack_object_incref ("context", 1805 (json_t *) kcc->context))); 1806 jmeasures = json_array (); 1807 GNUNET_assert (NULL != jmeasures); 1808 GNUNET_assert (0 == 1809 json_array_append_new (jmeasures, 1810 mi)); 1811 return GNUNET_JSON_PACK ( 1812 GNUNET_JSON_pack_array_steal ("measures", 1813 jmeasures), 1814 GNUNET_JSON_pack_bool ("is_and_combinator", 1815 true), 1816 GNUNET_JSON_pack_bool ("verboten", 1817 false)); 1818 } 1819 1820 1821 json_t * 1822 TALER_KYCLOGIC_measure_to_jmeasures ( 1823 const struct TALER_KYCLOGIC_Measure *m) 1824 { 1825 json_t *jmeasures; 1826 json_t *mi; 1827 1828 mi = GNUNET_JSON_PACK ( 1829 GNUNET_JSON_pack_string ("check_name", 1830 m->check_name), 1831 GNUNET_JSON_pack_allow_null ( 1832 GNUNET_JSON_pack_string ("prog_name", 1833 m->prog_name)), 1834 GNUNET_JSON_pack_allow_null ( 1835 GNUNET_JSON_pack_object_incref ("context", 1836 (json_t *) m->context))); 1837 jmeasures = json_array (); 1838 GNUNET_assert (NULL != jmeasures); 1839 GNUNET_assert (0 == 1840 json_array_append_new (jmeasures, 1841 mi)); 1842 return GNUNET_JSON_PACK ( 1843 GNUNET_JSON_pack_array_steal ("measures", 1844 jmeasures), 1845 GNUNET_JSON_pack_bool ("is_and_combinator", 1846 false), 1847 GNUNET_JSON_pack_bool ("verboten", 1848 false)); 1849 } 1850 1851 1852 uint32_t 1853 TALER_KYCLOGIC_rule2priority ( 1854 const struct TALER_KYCLOGIC_KycRule *r) 1855 { 1856 return r->display_priority; 1857 } 1858 1859 1860 /** 1861 * Run @a command with @a argument and return the 1862 * respective output from stdout. 1863 * 1864 * @param command binary to run 1865 * @param argument command-line argument to pass 1866 * @return NULL if @a command failed 1867 */ 1868 static char * 1869 command_output (const char *command, 1870 const char *argument) 1871 { 1872 char *rval; 1873 unsigned int sval; 1874 size_t soff; 1875 ssize_t ret; 1876 int sout[2]; 1877 pid_t chld; 1878 const char *extra_args[] = { 1879 argument, 1880 "-c", 1881 cfg_filename, 1882 NULL, 1883 }; 1884 1885 if (0 != pipe (sout)) 1886 { 1887 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, 1888 "pipe"); 1889 return NULL; 1890 } 1891 chld = fork (); 1892 if (-1 == chld) 1893 { 1894 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, 1895 "fork"); 1896 GNUNET_break (0 == close (sout[0])); 1897 GNUNET_break (0 == close (sout[1])); 1898 return NULL; 1899 } 1900 if (0 == chld) 1901 { 1902 char **argv; 1903 1904 argv = TALER_words_split (command, 1905 extra_args); 1906 1907 GNUNET_break (0 == 1908 close (sout[0])); 1909 GNUNET_break (0 == 1910 close (STDOUT_FILENO)); 1911 GNUNET_assert (STDOUT_FILENO == 1912 dup2 (sout[1], 1913 STDOUT_FILENO)); 1914 GNUNET_break (0 == 1915 close (sout[1])); 1916 execvp (argv[0], 1917 argv); 1918 TALER_words_destroy (argv); 1919 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, 1920 "exec", 1921 command); 1922 exit (EXIT_FAILURE); 1923 } 1924 GNUNET_break (0 == 1925 close (sout[1])); 1926 sval = 1024; 1927 rval = GNUNET_malloc (sval); 1928 soff = 0; 1929 while (0 < (ret = read (sout[0], 1930 rval + soff, 1931 sval - soff)) ) 1932 { 1933 soff += ret; 1934 if (soff == sval) 1935 { 1936 GNUNET_array_grow (rval, 1937 sval, 1938 sval * 2); 1939 } 1940 } 1941 GNUNET_break (0 == close (sout[0])); 1942 { 1943 int wstatus; 1944 1945 GNUNET_break (chld == 1946 waitpid (chld, 1947 &wstatus, 1948 0)); 1949 if ( (! WIFEXITED (wstatus)) || 1950 (0 != WEXITSTATUS (wstatus)) ) 1951 { 1952 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1953 "Command `%s' %s failed with status %d\n", 1954 command, 1955 argument, 1956 wstatus); 1957 GNUNET_array_grow (rval, 1958 sval, 1959 0); 1960 return NULL; 1961 } 1962 } 1963 GNUNET_array_grow (rval, 1964 sval, 1965 soff + 1); 1966 rval[soff] = '\0'; 1967 return rval; 1968 } 1969 1970 1971 /** 1972 * Convert check type @a ctype_s into @a ctype. 1973 * 1974 * @param ctype_s check type as a string 1975 * @param[out] ctype set to check type as enum 1976 * @return #GNUNET_OK on success 1977 */ 1978 static enum GNUNET_GenericReturnValue 1979 check_type_from_string ( 1980 const char *ctype_s, 1981 enum TALER_KYCLOGIC_CheckType *ctype) 1982 { 1983 struct 1984 { 1985 const char *in; 1986 enum TALER_KYCLOGIC_CheckType out; 1987 } map [] = { 1988 { "INFO", TALER_KYCLOGIC_CT_INFO }, 1989 { "LINK", TALER_KYCLOGIC_CT_LINK }, 1990 { "FORM", TALER_KYCLOGIC_CT_FORM }, 1991 { NULL, 0 } 1992 }; 1993 1994 for (unsigned int i = 0; NULL != map[i].in; i++) 1995 if (0 == strcasecmp (map[i].in, 1996 ctype_s)) 1997 { 1998 *ctype = map[i].out; 1999 return GNUNET_OK; 2000 } 2001 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2002 "Invalid check type `%s'\n", 2003 ctype_s); 2004 return GNUNET_SYSERR; 2005 } 2006 2007 2008 enum GNUNET_GenericReturnValue 2009 TALER_KYCLOGIC_kyc_trigger_from_string ( 2010 const char *trigger_s, 2011 enum TALER_KYCLOGIC_KycTriggerEvent *trigger) 2012 { 2013 /* NOTE: if you change this, also change 2014 the code in src/json/json_helper.c! */ 2015 struct 2016 { 2017 const char *in; 2018 enum TALER_KYCLOGIC_KycTriggerEvent out; 2019 } map [] = { 2020 { "WITHDRAW", TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW }, 2021 { "DEPOSIT", TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT }, 2022 { "MERGE", TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE }, 2023 { "BALANCE", TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE }, 2024 { "CLOSE", TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE }, 2025 { "AGGREGATE", TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE }, 2026 { "TRANSACTION", TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION }, 2027 { "REFUND", TALER_KYCLOGIC_KYC_TRIGGER_REFUND }, 2028 { NULL, 0 } 2029 }; 2030 2031 for (unsigned int i = 0; NULL != map[i].in; i++) 2032 if (0 == strcasecmp (map[i].in, 2033 trigger_s)) 2034 { 2035 *trigger = map[i].out; 2036 return GNUNET_OK; 2037 } 2038 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2039 "Invalid KYC trigger `%s'\n", 2040 trigger_s); 2041 return GNUNET_SYSERR; 2042 } 2043 2044 2045 json_t * 2046 TALER_KYCLOGIC_get_wallet_thresholds (void) 2047 { 2048 json_t *ret; 2049 2050 ret = json_array (); 2051 GNUNET_assert (NULL != ret); 2052 for (unsigned int i = 0; i<default_rules.num_kyc_rules; i++) 2053 { 2054 struct TALER_KYCLOGIC_KycRule *rule 2055 = &default_rules.kyc_rules[i]; 2056 2057 if (TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE != rule->trigger) 2058 continue; 2059 GNUNET_assert ( 2060 0 == 2061 json_array_append_new ( 2062 ret, 2063 TALER_JSON_from_amount ( 2064 &rule->threshold))); 2065 } 2066 return ret; 2067 } 2068 2069 2070 /** 2071 * Load KYC logic plugin. 2072 * 2073 * @param cfg configuration to use 2074 * @param name name of the plugin 2075 * @return NULL on error 2076 */ 2077 static struct TALER_KYCLOGIC_Plugin * 2078 load_logic (const struct GNUNET_CONFIGURATION_Handle *cfg, 2079 const char *name) 2080 { 2081 char *lib_name; 2082 struct TALER_KYCLOGIC_Plugin *plugin; 2083 2084 2085 GNUNET_asprintf (&lib_name, 2086 "libtaler_plugin_kyclogic_%s", 2087 name); 2088 if (! ascii_lower (lib_name)) 2089 { 2090 GNUNET_free (lib_name); 2091 return NULL; 2092 } 2093 for (unsigned int i = 0; i<num_kyc_logics; i++) 2094 if (0 == strcasecmp (lib_name, 2095 kyc_logics[i]->library_name)) 2096 { 2097 GNUNET_free (lib_name); 2098 return kyc_logics[i]; 2099 } 2100 plugin = GNUNET_PLUGIN_load (TALER_EXCHANGE_project_data (), 2101 lib_name, 2102 (void *) cfg); 2103 if (NULL == plugin) 2104 { 2105 GNUNET_free (lib_name); 2106 return NULL; 2107 } 2108 plugin->library_name = lib_name; 2109 plugin->name = GNUNET_strdup (name); 2110 GNUNET_array_append (kyc_logics, 2111 num_kyc_logics, 2112 plugin); 2113 return plugin; 2114 } 2115 2116 2117 /** 2118 * Parse configuration of a KYC provider. 2119 * 2120 * @param cfg configuration to parse 2121 * @param section name of the section to analyze 2122 * @return #GNUNET_OK on success 2123 */ 2124 static enum GNUNET_GenericReturnValue 2125 add_provider (const struct GNUNET_CONFIGURATION_Handle *cfg, 2126 const char *section) 2127 { 2128 char *logic; 2129 struct TALER_KYCLOGIC_Plugin *lp; 2130 struct TALER_KYCLOGIC_ProviderDetails *pd; 2131 2132 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 2133 "Parsing KYC provider %s\n", 2134 section); 2135 if (GNUNET_OK != 2136 GNUNET_CONFIGURATION_get_value_string (cfg, 2137 section, 2138 "LOGIC", 2139 &logic)) 2140 { 2141 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 2142 section, 2143 "LOGIC"); 2144 return GNUNET_SYSERR; 2145 } 2146 if (! ascii_lower (logic)) 2147 { 2148 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 2149 section, 2150 "LOGIC", 2151 "Only [a-zA-Z0-9_0] are allowed"); 2152 return GNUNET_SYSERR; 2153 } 2154 lp = load_logic (cfg, 2155 logic); 2156 if (NULL == lp) 2157 { 2158 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 2159 section, 2160 "LOGIC", 2161 "logic plugin could not be loaded"); 2162 GNUNET_free (logic); 2163 return GNUNET_SYSERR; 2164 } 2165 GNUNET_free (logic); 2166 pd = lp->load_configuration (lp->cls, 2167 section); 2168 if (NULL == pd) 2169 return GNUNET_SYSERR; 2170 2171 { 2172 struct TALER_KYCLOGIC_KycProvider *kp; 2173 2174 kp = GNUNET_new (struct TALER_KYCLOGIC_KycProvider); 2175 kp->provider_name 2176 = GNUNET_strdup (§ion[strlen ("kyc-provider-")]); 2177 kp->logic = lp; 2178 kp->pd = pd; 2179 kp->process_timeout = GNUNET_TIME_UNIT_DAYS; 2180 if (GNUNET_YES == 2181 GNUNET_CONFIGURATION_have_value (cfg, 2182 section, 2183 "KYC_PROCESS_TIMEOUT")) 2184 { 2185 if (GNUNET_OK != 2186 GNUNET_CONFIGURATION_get_value_time (cfg, 2187 section, 2188 "KYC_PROCESS_TIMEOUT", 2189 &kp->process_timeout)) 2190 { 2191 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 2192 section, 2193 "KYC_PROCESS_TIMEOUT", 2194 "finite positive duration required"); 2195 GNUNET_free (kp->provider_name); 2196 GNUNET_free (kp); 2197 lp->unload_configuration (pd); 2198 return GNUNET_SYSERR; 2199 } 2200 } 2201 if ( (0 == kp->process_timeout.rel_value_us) || 2202 (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == 2203 kp->process_timeout.rel_value_us) ) 2204 { 2205 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 2206 section, 2207 "KYC_PROCESS_TIMEOUT", 2208 "finite positive duration required"); 2209 GNUNET_free (kp->provider_name); 2210 GNUNET_free (kp); 2211 lp->unload_configuration (pd); 2212 return GNUNET_SYSERR; 2213 } 2214 GNUNET_array_append (kyc_providers, 2215 num_kyc_providers, 2216 kp); 2217 } 2218 return GNUNET_OK; 2219 } 2220 2221 2222 struct GNUNET_TIME_Relative 2223 TALER_KYCLOGIC_provider_get_process_timeout ( 2224 const struct TALER_KYCLOGIC_KycProvider *provider) 2225 { 2226 return provider->process_timeout; 2227 } 2228 2229 2230 /** 2231 * Tokenize @a input along @a token 2232 * and build an array of the tokens. 2233 * 2234 * @param[in,out] input the input to tokenize; clobbered 2235 * @param sep separator between tokens to separate @a input on 2236 * @param[out] p_strs where to put array of tokens 2237 * @param[out] num_strs set to length of @a p_strs array 2238 */ 2239 static void 2240 add_tokens (char *input, 2241 const char *sep, 2242 char ***p_strs, 2243 unsigned int *num_strs) 2244 { 2245 char *sptr; 2246 char **rstr = NULL; 2247 unsigned int num_rstr = 0; 2248 2249 for (char *tok = strtok_r (input, sep, &sptr); 2250 NULL != tok; 2251 tok = strtok_r (NULL, sep, &sptr)) 2252 { 2253 GNUNET_array_append (rstr, 2254 num_rstr, 2255 GNUNET_strdup (tok)); 2256 } 2257 *p_strs = rstr; 2258 *num_strs = num_rstr; 2259 } 2260 2261 2262 /** 2263 * Closure for the handle_XXX_section functions 2264 * that parse configuration sections matching certain 2265 * prefixes. 2266 */ 2267 struct SectionContext 2268 { 2269 /** 2270 * Configuration to handle. 2271 */ 2272 const struct GNUNET_CONFIGURATION_Handle *cfg; 2273 2274 /** 2275 * Result to return, set to false on failures. 2276 */ 2277 bool result; 2278 }; 2279 2280 2281 /** 2282 * Function to iterate over configuration sections. 2283 * 2284 * @param cls a `struct SectionContext *` 2285 * @param section name of the section 2286 */ 2287 static void 2288 handle_provider_section (void *cls, 2289 const char *section) 2290 { 2291 struct SectionContext *sc = cls; 2292 char *s; 2293 2294 if (! sc->result) 2295 return; 2296 s = normalize_section_with_prefix ("kyc-provider-", 2297 section); 2298 if (NULL == s) 2299 return; 2300 if (GNUNET_OK != 2301 add_provider (sc->cfg, 2302 s)) 2303 { 2304 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2305 "Setup failed in configuration section `%s'\n", 2306 section); 2307 sc->result = false; 2308 } 2309 GNUNET_free (s); 2310 } 2311 2312 2313 /** 2314 * Parse configuration @a cfg in section @a section for 2315 * the specification of a KYC check. 2316 * 2317 * @param cfg configuration to parse 2318 * @param section configuration section to parse 2319 * @return #GNUNET_OK on success 2320 */ 2321 static enum GNUNET_GenericReturnValue 2322 add_check (const struct GNUNET_CONFIGURATION_Handle *cfg, 2323 const char *section) 2324 { 2325 enum TALER_KYCLOGIC_CheckType ct; 2326 char *description = NULL; 2327 json_t *description_i18n = NULL; 2328 char *requires = NULL; 2329 char *outputs = NULL; 2330 char *fallback = NULL; 2331 2332 if (0 == strcasecmp (§ion[strlen ("kyc-check-")], 2333 "skip")) 2334 { 2335 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2336 "The kyc-check-skip section must not exist, 'skip' is reserved name for a built-in check\n"); 2337 return GNUNET_SYSERR; 2338 } 2339 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 2340 "Parsing KYC check %s\n", 2341 section); 2342 { 2343 char *type_s; 2344 2345 if (GNUNET_OK != 2346 GNUNET_CONFIGURATION_get_value_string (cfg, 2347 section, 2348 "TYPE", 2349 &type_s)) 2350 { 2351 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 2352 section, 2353 "TYPE"); 2354 return GNUNET_SYSERR; 2355 } 2356 if (GNUNET_OK != 2357 check_type_from_string (type_s, 2358 &ct)) 2359 { 2360 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 2361 section, 2362 "TYPE", 2363 "valid check type required"); 2364 GNUNET_free (type_s); 2365 goto fail; 2366 } 2367 GNUNET_free (type_s); 2368 } 2369 2370 if (GNUNET_OK != 2371 GNUNET_CONFIGURATION_get_value_string (cfg, 2372 section, 2373 "DESCRIPTION", 2374 &description)) 2375 { 2376 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 2377 section, 2378 "DESCRIPTION"); 2379 goto fail; 2380 } 2381 2382 { 2383 char *tmp; 2384 2385 if (GNUNET_OK == 2386 GNUNET_CONFIGURATION_get_value_string (cfg, 2387 section, 2388 "DESCRIPTION_I18N", 2389 &tmp)) 2390 { 2391 json_error_t err; 2392 2393 description_i18n = json_loads (tmp, 2394 JSON_REJECT_DUPLICATES, 2395 &err); 2396 GNUNET_free (tmp); 2397 if (NULL == description_i18n) 2398 { 2399 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 2400 section, 2401 "DESCRIPTION_I18N", 2402 err.text); 2403 goto fail; 2404 } 2405 if (! TALER_JSON_check_i18n (description_i18n) ) 2406 { 2407 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 2408 section, 2409 "DESCRIPTION_I18N", 2410 "JSON with internationalization map required"); 2411 goto fail; 2412 } 2413 } 2414 } 2415 2416 if (GNUNET_OK != 2417 GNUNET_CONFIGURATION_get_value_string (cfg, 2418 section, 2419 "REQUIRES", 2420 &requires)) 2421 { 2422 /* no requirements is OK */ 2423 requires = GNUNET_strdup (""); 2424 } 2425 2426 if (GNUNET_OK != 2427 GNUNET_CONFIGURATION_get_value_string (cfg, 2428 section, 2429 "OUTPUTS", 2430 &outputs)) 2431 { 2432 /* no outputs is OK */ 2433 outputs = GNUNET_strdup (""); 2434 } 2435 2436 if (GNUNET_OK != 2437 GNUNET_CONFIGURATION_get_value_string (cfg, 2438 section, 2439 "FALLBACK", 2440 &fallback)) 2441 { 2442 /* We do *not* allow NULL to fall back to default rules because fallbacks 2443 are used when there is actually a serious error and thus some action 2444 (usually an investigation) is always in order, and that's basically 2445 never the default. And as fallbacks should be rare, we really insist on 2446 them at least being explicitly configured. Otherwise these errors may 2447 go undetected simply because someone forgot to configure a fallback and 2448 then nothing happens. */ 2449 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 2450 section, 2451 "FALLBACK"); 2452 goto fail; 2453 } 2454 if (! ascii_lower (fallback)) 2455 { 2456 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 2457 section, 2458 "FALLBACK", 2459 "Only [a-zA-Z0-9_0] are allowed"); 2460 goto fail; 2461 } 2462 2463 { 2464 struct TALER_KYCLOGIC_KycCheck *kc; 2465 2466 kc = GNUNET_new (struct TALER_KYCLOGIC_KycCheck); 2467 switch (ct) 2468 { 2469 case TALER_KYCLOGIC_CT_INFO: 2470 /* nothing to do */ 2471 break; 2472 case TALER_KYCLOGIC_CT_FORM: 2473 { 2474 char *form_name; 2475 2476 if (GNUNET_OK != 2477 GNUNET_CONFIGURATION_get_value_string (cfg, 2478 section, 2479 "FORM_NAME", 2480 &form_name)) 2481 { 2482 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 2483 section, 2484 "FORM_NAME"); 2485 goto fail; 2486 } 2487 if (! ascii_lower (form_name)) 2488 { 2489 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 2490 section, 2491 "FORM_NAME", 2492 "Only [a-zA-Z0-9_0] are allowed"); 2493 goto fail; 2494 } 2495 kc->details.form.name = form_name; 2496 } 2497 break; 2498 case TALER_KYCLOGIC_CT_LINK: 2499 { 2500 char *provider_id; 2501 2502 if (GNUNET_OK != 2503 GNUNET_CONFIGURATION_get_value_string (cfg, 2504 section, 2505 "PROVIDER_ID", 2506 &provider_id)) 2507 { 2508 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 2509 section, 2510 "PROVIDER_ID"); 2511 goto fail; 2512 } 2513 if (! ascii_lower (provider_id)) 2514 { 2515 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 2516 section, 2517 "PROVIDER_ID", 2518 "Only [a-zA-Z0-9_0] are allowed"); 2519 goto fail; 2520 } 2521 kc->details.link.provider = find_provider (provider_id); 2522 if (NULL == kc->details.link.provider) 2523 { 2524 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2525 "Unknown KYC provider `%s' used in check `%s'\n", 2526 provider_id, 2527 §ion[strlen ("kyc-check-")]); 2528 GNUNET_free (kc); 2529 GNUNET_free (provider_id); 2530 goto fail; 2531 } 2532 GNUNET_free (provider_id); 2533 } 2534 break; 2535 } 2536 kc->check_name = GNUNET_strdup (§ion[strlen ("kyc-check-")]); 2537 kc->description = description; 2538 kc->description_i18n = description_i18n; 2539 kc->fallback = fallback; 2540 kc->type = ct; 2541 add_tokens (requires, 2542 "; \n\t", 2543 &kc->requires, 2544 &kc->num_requires); 2545 GNUNET_free (requires); 2546 add_tokens (outputs, 2547 "; \n\t", 2548 &kc->outputs, 2549 &kc->num_outputs); 2550 GNUNET_free (outputs); 2551 GNUNET_array_append (kyc_checks, 2552 num_kyc_checks, 2553 kc); 2554 } 2555 2556 return GNUNET_OK; 2557 fail: 2558 GNUNET_free (description); 2559 json_decref (description_i18n); 2560 GNUNET_free (requires); 2561 GNUNET_free (outputs); 2562 GNUNET_free (fallback); 2563 return GNUNET_SYSERR; 2564 } 2565 2566 2567 /** 2568 * Function to iterate over configuration sections. 2569 * 2570 * @param cls a `struct SectionContext *` 2571 * @param section name of the section 2572 */ 2573 static void 2574 handle_check_section (void *cls, 2575 const char *section) 2576 { 2577 struct SectionContext *sc = cls; 2578 char *s; 2579 2580 if (! sc->result) 2581 return; 2582 s = normalize_section_with_prefix ("kyc-check-", 2583 section); 2584 if (NULL == s) 2585 return; 2586 if (GNUNET_OK != 2587 add_check (sc->cfg, 2588 s)) 2589 sc->result = false; 2590 GNUNET_free (s); 2591 } 2592 2593 2594 /** 2595 * Parse configuration @a cfg in section @a section for 2596 * the specification of a KYC rule. 2597 * 2598 * @param cfg configuration to parse 2599 * @param section configuration section to parse 2600 * @return #GNUNET_OK on success 2601 */ 2602 static enum GNUNET_GenericReturnValue 2603 add_rule (const struct GNUNET_CONFIGURATION_Handle *cfg, 2604 const char *section) 2605 { 2606 struct TALER_Amount threshold; 2607 struct GNUNET_TIME_Relative timeframe; 2608 enum TALER_KYCLOGIC_KycTriggerEvent ot; 2609 char *measures; 2610 bool exposed; 2611 bool is_and; 2612 2613 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 2614 "Parsing KYC rule from %s\n", 2615 section); 2616 { 2617 enum GNUNET_GenericReturnValue r; 2618 2619 r = GNUNET_CONFIGURATION_get_value_yesno (cfg, 2620 section, 2621 "ENABLED"); 2622 if ( (GNUNET_SYSERR == r) && 2623 (GNUNET_YES == 2624 GNUNET_CONFIGURATION_have_value (cfg, 2625 section, 2626 "ENABLED")) ) 2627 { 2628 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 2629 section, 2630 "ENABLED", 2631 "YES or NO required"); 2632 return GNUNET_SYSERR; 2633 } 2634 if (GNUNET_YES != r) 2635 return GNUNET_OK; 2636 } 2637 if (GNUNET_OK != 2638 TALER_config_get_amount (cfg, 2639 section, 2640 "THRESHOLD", 2641 &threshold)) 2642 { 2643 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 2644 section, 2645 "THRESHOLD", 2646 "amount required"); 2647 return GNUNET_SYSERR; 2648 } 2649 if (0 != 2650 strcasecmp (threshold.currency, 2651 my_currency)) 2652 { 2653 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 2654 section, 2655 "THRESHOLD", 2656 "currency mismatch"); 2657 return GNUNET_SYSERR; 2658 } 2659 { 2660 enum GNUNET_GenericReturnValue r; 2661 2662 r = GNUNET_CONFIGURATION_get_value_yesno (cfg, 2663 section, 2664 "EXPOSED"); 2665 if ( (GNUNET_SYSERR == r) && 2666 (GNUNET_YES == 2667 GNUNET_CONFIGURATION_have_value (cfg, 2668 section, 2669 "EXPOSED")) ) 2670 { 2671 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 2672 section, 2673 "EXPOSED", 2674 "YES or NO required"); 2675 return GNUNET_SYSERR; 2676 } 2677 exposed = (GNUNET_YES == r); 2678 } 2679 { 2680 enum GNUNET_GenericReturnValue r; 2681 2682 r = GNUNET_CONFIGURATION_get_value_yesno (cfg, 2683 section, 2684 "IS_AND_COMBINATOR"); 2685 if (GNUNET_SYSERR == r) 2686 { 2687 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 2688 section, 2689 "IS_AND_COMBINATOR", 2690 "YES or NO required"); 2691 return GNUNET_SYSERR; 2692 } 2693 is_and = (GNUNET_YES == r); 2694 } 2695 2696 { 2697 char *ot_s; 2698 2699 if (GNUNET_OK != 2700 GNUNET_CONFIGURATION_get_value_string (cfg, 2701 section, 2702 "OPERATION_TYPE", 2703 &ot_s)) 2704 { 2705 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 2706 section, 2707 "OPERATION_TYPE"); 2708 return GNUNET_SYSERR; 2709 } 2710 if (GNUNET_OK != 2711 TALER_KYCLOGIC_kyc_trigger_from_string (ot_s, 2712 &ot)) 2713 { 2714 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 2715 section, 2716 "OPERATION_TYPE", 2717 "valid trigger type required"); 2718 GNUNET_free (ot_s); 2719 return GNUNET_SYSERR; 2720 } 2721 GNUNET_free (ot_s); 2722 } 2723 2724 if (GNUNET_OK != 2725 GNUNET_CONFIGURATION_get_value_time (cfg, 2726 section, 2727 "TIMEFRAME", 2728 &timeframe)) 2729 { 2730 if (TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE == ot) 2731 { 2732 timeframe = GNUNET_TIME_UNIT_ZERO; 2733 } 2734 else 2735 { 2736 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 2737 section, 2738 "TIMEFRAME", 2739 "duration required"); 2740 return GNUNET_SYSERR; 2741 } 2742 } 2743 if (GNUNET_OK != 2744 GNUNET_CONFIGURATION_get_value_string (cfg, 2745 section, 2746 "NEXT_MEASURES", 2747 &measures)) 2748 { 2749 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 2750 section, 2751 "NEXT_MEASURES"); 2752 return GNUNET_SYSERR; 2753 } 2754 if (! token_list_lower (measures)) 2755 { 2756 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 2757 section, 2758 "NEXT_MEASURES", 2759 "Only [a-zA-Z0-9 _-] are allowed"); 2760 GNUNET_free (measures); 2761 return GNUNET_SYSERR; 2762 } 2763 2764 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 2765 "Adding KYC rule %s for trigger %d with threshold %s\n", 2766 section, 2767 (int) ot, 2768 TALER_amount2s (&threshold)); 2769 { 2770 struct TALER_KYCLOGIC_KycRule kt = { 2771 .lrs = &default_rules, 2772 .rule_name = GNUNET_strdup (§ion[strlen ("kyc-rule-")]), 2773 .timeframe = timeframe, 2774 .threshold = threshold, 2775 .trigger = ot, 2776 .is_and_combinator = is_and, 2777 .exposed = exposed, 2778 .display_priority = 0, 2779 .verboten = false 2780 }; 2781 2782 add_tokens (measures, 2783 "; \n\t", 2784 &kt.next_measures, 2785 &kt.num_measures); 2786 for (unsigned int i=0; i<kt.num_measures; i++) 2787 if (0 == strcasecmp (KYC_MEASURE_IMPOSSIBLE, 2788 kt.next_measures[i])) 2789 kt.verboten = true; 2790 GNUNET_free (measures); 2791 GNUNET_array_append (default_rules.kyc_rules, 2792 default_rules.num_kyc_rules, 2793 kt); 2794 } 2795 return GNUNET_OK; 2796 } 2797 2798 2799 /** 2800 * Function to iterate over configuration sections. 2801 * 2802 * @param cls a `struct SectionContext *` 2803 * @param section name of the section 2804 */ 2805 static void 2806 handle_rule_section (void *cls, 2807 const char *section) 2808 { 2809 struct SectionContext *sc = cls; 2810 char *s; 2811 2812 if (! sc->result) 2813 return; 2814 s = normalize_section_with_prefix ("kyc-rule-", 2815 section); 2816 if (NULL == s) 2817 return; 2818 if (GNUNET_OK != 2819 add_rule (sc->cfg, 2820 s)) 2821 sc->result = false; 2822 GNUNET_free (s); 2823 } 2824 2825 2826 /** 2827 * Parse array dimension argument of @a tok (if present) 2828 * and store result in @a dimp. Does nothing if 2829 * @a tok does not contain '['. Otherwise does some input 2830 * validation. 2831 * 2832 * @param section name of configuration section for logging 2833 * @param tok input to parse, of form "text[$DIM]" 2834 * @param[out] dimp set to value of $DIM 2835 * @return true on success 2836 */ 2837 static bool 2838 parse_dim (const char *section, 2839 const char *tok, 2840 long long *dimp) 2841 { 2842 const char *dim = strchr (tok, 2843 '['); 2844 char dummy; 2845 2846 if (NULL == dim) 2847 return true; 2848 if (1 != 2849 sscanf (dim, 2850 "[%lld]%c", 2851 dimp, 2852 &dummy)) 2853 { 2854 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 2855 section, 2856 "COMMAND", 2857 "output for -i invalid (bad dimension given)"); 2858 return false; 2859 } 2860 return true; 2861 } 2862 2863 2864 /** 2865 * Parse configuration @a cfg in section @a section for 2866 * the specification of an AML program. 2867 * 2868 * @param cfg configuration to parse 2869 * @param section configuration section to parse 2870 * @return #GNUNET_OK on success 2871 */ 2872 static enum GNUNET_GenericReturnValue 2873 add_program (const struct GNUNET_CONFIGURATION_Handle *cfg, 2874 const char *section) 2875 { 2876 char *command = NULL; 2877 char *description = NULL; 2878 char *fallback = NULL; 2879 char *required_contexts = NULL; 2880 char *required_attributes = NULL; 2881 char *required_inputs = NULL; 2882 enum AmlProgramInputs input_mask = API_NONE; 2883 long long aml_history_length_limit = INT64_MAX; 2884 long long kyc_history_length_limit = INT64_MAX; 2885 2886 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 2887 "Parsing KYC program %s\n", 2888 section); 2889 if (GNUNET_OK != 2890 GNUNET_CONFIGURATION_get_value_string (cfg, 2891 section, 2892 "COMMAND", 2893 &command)) 2894 { 2895 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 2896 section, 2897 "COMMAND", 2898 "command required"); 2899 goto fail; 2900 } 2901 if (GNUNET_OK != 2902 GNUNET_CONFIGURATION_get_value_string (cfg, 2903 section, 2904 "DESCRIPTION", 2905 &description)) 2906 { 2907 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 2908 section, 2909 "DESCRIPTION", 2910 "description required"); 2911 goto fail; 2912 } 2913 if (GNUNET_OK != 2914 GNUNET_CONFIGURATION_get_value_string (cfg, 2915 section, 2916 "FALLBACK", 2917 &fallback)) 2918 { 2919 /* We do *not* allow NULL to fall back to default rules because fallbacks 2920 are used when there is actually a serious error and thus some action 2921 (usually an investigation) is always in order, and that's basically 2922 never the default. And as fallbacks should be rare, we really insist on 2923 them at least being explicitly configured. Otherwise these errors may 2924 go undetected simply because someone forgot to configure a fallback and 2925 then nothing happens. */ 2926 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 2927 section, 2928 "FALLBACK", 2929 "fallback measure name required"); 2930 goto fail; 2931 } 2932 2933 required_contexts = command_output (command, 2934 "-r"); 2935 if (NULL == required_contexts) 2936 { 2937 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 2938 section, 2939 "COMMAND", 2940 "output for -r invalid"); 2941 goto fail; 2942 } 2943 2944 required_attributes = command_output (command, 2945 "-a"); 2946 if (NULL == required_attributes) 2947 { 2948 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 2949 section, 2950 "COMMAND", 2951 "output for -a invalid"); 2952 goto fail; 2953 } 2954 2955 required_inputs = command_output (command, 2956 "-i"); 2957 if (NULL == required_inputs) 2958 { 2959 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 2960 section, 2961 "COMMAND", 2962 "output for -i invalid"); 2963 goto fail; 2964 } 2965 2966 { 2967 char *sptr; 2968 2969 for (char *tok = strtok_r (required_inputs, 2970 ";\n \t", 2971 &sptr); 2972 NULL != tok; 2973 tok = strtok_r (NULL, 2974 ";\n \t", 2975 &sptr) ) 2976 { 2977 if (0 == strcasecmp (tok, 2978 "context")) 2979 input_mask |= API_CONTEXT; 2980 else if (0 == strcasecmp (tok, 2981 "attributes")) 2982 input_mask |= API_ATTRIBUTES; 2983 else if (0 == strcasecmp (tok, 2984 "current_rules")) 2985 input_mask |= API_CURRENT_RULES; 2986 else if (0 == strcasecmp (tok, 2987 "default_rules")) 2988 input_mask |= API_DEFAULT_RULES; 2989 else if (0 == strncasecmp (tok, 2990 "aml_history", 2991 strlen ("aml_history"))) 2992 { 2993 input_mask |= API_AML_HISTORY; 2994 if (! parse_dim (section, 2995 tok, 2996 &aml_history_length_limit)) 2997 goto fail; 2998 } 2999 else if (0 == strncasecmp (tok, 3000 "kyc_history", 3001 strlen ("kyc_history"))) 3002 { 3003 input_mask |= API_KYC_HISTORY; 3004 if (! parse_dim (section, 3005 tok, 3006 &kyc_history_length_limit)) 3007 goto fail; 3008 } 3009 else 3010 { 3011 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 3012 section, 3013 "COMMAND", 3014 "output for -i invalid (unsupported input)"); 3015 goto fail; 3016 } 3017 } 3018 } 3019 GNUNET_free (required_inputs); 3020 3021 { 3022 struct TALER_KYCLOGIC_AmlProgram *ap; 3023 3024 ap = GNUNET_new (struct TALER_KYCLOGIC_AmlProgram); 3025 ap->program_name = GNUNET_strdup (§ion[strlen ("aml-program-")]); 3026 ap->command = command; 3027 ap->description = description; 3028 ap->fallback = fallback; 3029 ap->input_mask = input_mask; 3030 ap->aml_history_length_limit = aml_history_length_limit; 3031 ap->kyc_history_length_limit = kyc_history_length_limit; 3032 add_tokens (required_contexts, 3033 "; \n\t", 3034 &ap->required_contexts, 3035 &ap->num_required_contexts); 3036 GNUNET_free (required_contexts); 3037 add_tokens (required_attributes, 3038 "; \n\t", 3039 &ap->required_attributes, 3040 &ap->num_required_attributes); 3041 GNUNET_free (required_attributes); 3042 GNUNET_array_append (aml_programs, 3043 num_aml_programs, 3044 ap); 3045 } 3046 return GNUNET_OK; 3047 fail: 3048 GNUNET_free (command); 3049 GNUNET_free (description); 3050 GNUNET_free (required_inputs); 3051 GNUNET_free (required_contexts); 3052 GNUNET_free (required_attributes); 3053 GNUNET_free (fallback); 3054 return GNUNET_SYSERR; 3055 } 3056 3057 3058 /** 3059 * Function to iterate over configuration sections. 3060 * 3061 * @param cls a `struct SectionContext *` 3062 * @param section name of the section 3063 */ 3064 static void 3065 handle_program_section (void *cls, 3066 const char *section) 3067 { 3068 struct SectionContext *sc = cls; 3069 char *s; 3070 3071 if (! sc->result) 3072 return; 3073 s = normalize_section_with_prefix ("aml-program-", 3074 section); 3075 if (NULL == s) 3076 return; 3077 if (GNUNET_OK != 3078 add_program (sc->cfg, 3079 s)) 3080 sc->result = false; 3081 GNUNET_free (s); 3082 } 3083 3084 3085 /** 3086 * Parse configuration @a cfg in section @a section for 3087 * the specification of a KYC measure. 3088 * 3089 * @param cfg configuration to parse 3090 * @param section configuration section to parse 3091 * @return #GNUNET_OK on success 3092 */ 3093 static enum GNUNET_GenericReturnValue 3094 add_measure (const struct GNUNET_CONFIGURATION_Handle *cfg, 3095 const char *section) 3096 { 3097 bool voluntary; 3098 char *check_name = NULL; 3099 struct TALER_KYCLOGIC_KycCheck *kc = NULL; 3100 char *context_str = NULL; 3101 char *program = NULL; 3102 json_t *context; 3103 json_error_t err; 3104 3105 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 3106 "Parsing KYC measure %s\n", 3107 section); 3108 if (GNUNET_OK != 3109 GNUNET_CONFIGURATION_get_value_string (cfg, 3110 section, 3111 "CHECK_NAME", 3112 &check_name)) 3113 { 3114 check_name = GNUNET_strdup ("skip"); 3115 } 3116 if (0 != strcasecmp (check_name, 3117 "skip")) 3118 { 3119 kc = find_check (check_name); 3120 if (NULL == kc) 3121 { 3122 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 3123 section, 3124 "CHECK_NAME", 3125 "check unknown"); 3126 goto fail; 3127 } 3128 } 3129 if (GNUNET_OK != 3130 GNUNET_CONFIGURATION_get_value_string (cfg, 3131 section, 3132 "PROGRAM", 3133 &program)) 3134 { 3135 if ( (NULL == kc) || 3136 (TALER_KYCLOGIC_CT_INFO != kc->type) ) 3137 { 3138 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 3139 section, 3140 "PROGRAM"); 3141 goto fail; 3142 } 3143 } 3144 else 3145 { 3146 /* AML program given, but do we want one? */ 3147 if ( (NULL != kc) && 3148 (TALER_KYCLOGIC_CT_INFO == kc->type) ) 3149 { 3150 GNUNET_log_config_invalid ( 3151 GNUNET_ERROR_TYPE_WARNING, 3152 section, 3153 "PROGRAM", 3154 "AML program specified for a check of type INFO (ignored)"); 3155 GNUNET_free (program); 3156 } 3157 } 3158 voluntary = (GNUNET_YES == 3159 GNUNET_CONFIGURATION_get_value_yesno (cfg, 3160 section, 3161 "VOLUNTARY")); 3162 if (GNUNET_OK != 3163 GNUNET_CONFIGURATION_get_value_string (cfg, 3164 section, 3165 "CONTEXT", 3166 &context_str)) 3167 { 3168 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 3169 section, 3170 "CONTEXT"); 3171 goto fail; 3172 } 3173 context = json_loads (context_str, 3174 JSON_REJECT_DUPLICATES, 3175 &err); 3176 GNUNET_free (context_str); 3177 if (NULL == context) 3178 { 3179 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 3180 section, 3181 "CONTEXT", 3182 err.text); 3183 goto fail; 3184 } 3185 3186 { 3187 struct TALER_KYCLOGIC_Measure m; 3188 3189 m.measure_name = GNUNET_strdup (§ion[strlen ("kyc-measure-")]); 3190 m.check_name = check_name; 3191 m.prog_name = program; 3192 m.context = context; 3193 m.voluntary = voluntary; 3194 GNUNET_array_append (default_rules.custom_measures, 3195 default_rules.num_custom_measures, 3196 m); 3197 } 3198 return GNUNET_OK; 3199 fail: 3200 GNUNET_free (check_name); 3201 GNUNET_free (program); 3202 GNUNET_free (context_str); 3203 return GNUNET_SYSERR; 3204 } 3205 3206 3207 /** 3208 * Function to iterate over configuration sections. 3209 * 3210 * @param cls a `struct SectionContext *` 3211 * @param section name of the section 3212 */ 3213 static void 3214 handle_measure_section (void *cls, 3215 const char *section) 3216 { 3217 struct SectionContext *sc = cls; 3218 char *s; 3219 3220 if (! sc->result) 3221 return; 3222 s = normalize_section_with_prefix ("kyc-measure-", 3223 section); 3224 if (NULL == s) 3225 return; 3226 if (GNUNET_OK != 3227 add_measure (sc->cfg, 3228 s)) 3229 sc->result = false; 3230 GNUNET_free (s); 3231 } 3232 3233 3234 /** 3235 * Comparator for qsort. Compares two rules 3236 * by timeframe to sort rules by time. 3237 * 3238 * @param p1 first trigger to compare 3239 * @param p2 second trigger to compare 3240 * @return -1 if p1 < p2, 0 if p1==p2, 1 if p1 > p2. 3241 */ 3242 static int 3243 sort_by_timeframe (const void *p1, 3244 const void *p2) 3245 { 3246 struct TALER_KYCLOGIC_KycRule *r1 3247 = (struct TALER_KYCLOGIC_KycRule *) p1; 3248 struct TALER_KYCLOGIC_KycRule *r2 3249 = (struct TALER_KYCLOGIC_KycRule *) p2; 3250 3251 if (GNUNET_TIME_relative_cmp (r1->timeframe, 3252 <, 3253 r2->timeframe)) 3254 return -1; 3255 if (GNUNET_TIME_relative_cmp (r1->timeframe, 3256 >, 3257 r2->timeframe)) 3258 return 1; 3259 return 0; 3260 } 3261 3262 3263 enum GNUNET_GenericReturnValue 3264 TALER_KYCLOGIC_kyc_init ( 3265 const struct GNUNET_CONFIGURATION_Handle *cfg, 3266 const char *cfg_fn) 3267 { 3268 struct SectionContext sc = { 3269 .cfg = cfg, 3270 .result = true 3271 }; 3272 json_t *jkyc_rules_w; 3273 json_t *jkyc_rules_a; 3274 3275 if (NULL != cfg_fn) 3276 cfg_filename = GNUNET_strdup (cfg_fn); 3277 GNUNET_assert (GNUNET_OK == 3278 TALER_config_get_currency (cfg, 3279 "exchange", 3280 &my_currency)); 3281 GNUNET_CONFIGURATION_iterate_sections (cfg, 3282 &handle_provider_section, 3283 &sc); 3284 if (! sc.result) 3285 { 3286 TALER_KYCLOGIC_kyc_done (); 3287 return GNUNET_SYSERR; 3288 } 3289 GNUNET_CONFIGURATION_iterate_sections (cfg, 3290 &handle_check_section, 3291 &sc); 3292 if (! sc.result) 3293 { 3294 TALER_KYCLOGIC_kyc_done (); 3295 return GNUNET_SYSERR; 3296 } 3297 GNUNET_CONFIGURATION_iterate_sections (cfg, 3298 &handle_rule_section, 3299 &sc); 3300 if (! sc.result) 3301 { 3302 TALER_KYCLOGIC_kyc_done (); 3303 return GNUNET_SYSERR; 3304 } 3305 GNUNET_CONFIGURATION_iterate_sections (cfg, 3306 &handle_program_section, 3307 &sc); 3308 if (! sc.result) 3309 { 3310 TALER_KYCLOGIC_kyc_done (); 3311 return GNUNET_SYSERR; 3312 } 3313 GNUNET_CONFIGURATION_iterate_sections (cfg, 3314 &handle_measure_section, 3315 &sc); 3316 if (! sc.result) 3317 { 3318 TALER_KYCLOGIC_kyc_done (); 3319 return GNUNET_SYSERR; 3320 } 3321 3322 if (0 != default_rules.num_kyc_rules) 3323 qsort (default_rules.kyc_rules, 3324 default_rules.num_kyc_rules, 3325 sizeof (struct TALER_KYCLOGIC_KycRule), 3326 &sort_by_timeframe); 3327 jkyc_rules_w = json_array (); 3328 GNUNET_assert (NULL != jkyc_rules_w); 3329 jkyc_rules_a = json_array (); 3330 GNUNET_assert (NULL != jkyc_rules_a); 3331 3332 for (unsigned int i=0; i<default_rules.num_kyc_rules; i++) 3333 { 3334 const struct TALER_KYCLOGIC_KycRule *rule 3335 = &default_rules.kyc_rules[i]; 3336 json_t *jrule; 3337 json_t *jmeasures; 3338 3339 jmeasures = json_array (); 3340 GNUNET_assert (NULL != jmeasures); 3341 for (unsigned int j=0; j<rule->num_measures; j++) 3342 { 3343 const char *measure_name = rule->next_measures[j]; 3344 const struct TALER_KYCLOGIC_Measure *m; 3345 3346 if (0 == strcasecmp (KYC_MEASURE_IMPOSSIBLE, 3347 measure_name)) 3348 { 3349 GNUNET_assert ( 3350 0 == 3351 json_array_append_new (jmeasures, 3352 json_string (KYC_MEASURE_IMPOSSIBLE))); 3353 continue; 3354 } 3355 m = find_measure (&default_rules, 3356 measure_name); 3357 if (NULL == m) 3358 { 3359 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 3360 "Unknown measure `%s' used in rule `%s'\n", 3361 measure_name, 3362 rule->rule_name); 3363 return GNUNET_SYSERR; 3364 } 3365 GNUNET_assert (0 == 3366 json_array_append_new (jmeasures, 3367 json_string (measure_name))); 3368 } 3369 jrule = GNUNET_JSON_PACK ( 3370 GNUNET_JSON_pack_allow_null ( 3371 GNUNET_JSON_pack_string ("rule_name", 3372 rule->rule_name)), 3373 TALER_JSON_pack_kycte ("operation_type", 3374 rule->trigger), 3375 TALER_JSON_pack_amount ("threshold", 3376 &rule->threshold), 3377 GNUNET_JSON_pack_time_rel ("timeframe", 3378 rule->timeframe), 3379 GNUNET_JSON_pack_array_steal ("measures", 3380 jmeasures), 3381 GNUNET_JSON_pack_uint64 ("display_priority", 3382 rule->display_priority), 3383 GNUNET_JSON_pack_bool ("exposed", 3384 rule->exposed), 3385 GNUNET_JSON_pack_bool ("is_and_combinator", 3386 rule->is_and_combinator) 3387 ); 3388 switch (rule->trigger) 3389 { 3390 case TALER_KYCLOGIC_KYC_TRIGGER_NONE: 3391 GNUNET_break (0); 3392 break; 3393 case TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW: 3394 GNUNET_assert (0 == 3395 json_array_append (jkyc_rules_a, 3396 jrule)); 3397 break; 3398 case TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT: 3399 GNUNET_assert (0 == 3400 json_array_append (jkyc_rules_a, 3401 jrule)); 3402 break; 3403 case TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE: 3404 GNUNET_assert (0 == 3405 json_array_append (jkyc_rules_w, 3406 jrule)); 3407 break; 3408 case TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE: 3409 GNUNET_assert (0 == 3410 json_array_append (jkyc_rules_w, 3411 jrule)); 3412 break; 3413 case TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE: 3414 GNUNET_assert (0 == 3415 json_array_append (jkyc_rules_a, 3416 jrule)); 3417 break; 3418 case TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE: 3419 GNUNET_assert (0 == 3420 json_array_append (jkyc_rules_a, 3421 jrule)); 3422 break; 3423 case TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION: 3424 GNUNET_assert (0 == 3425 json_array_append (jkyc_rules_a, 3426 jrule)); 3427 GNUNET_assert (0 == 3428 json_array_append (jkyc_rules_w, 3429 jrule)); 3430 break; 3431 case TALER_KYCLOGIC_KYC_TRIGGER_REFUND: 3432 GNUNET_assert (0 == 3433 json_array_append (jkyc_rules_a, 3434 jrule)); 3435 GNUNET_assert (0 == 3436 json_array_append (jkyc_rules_w, 3437 jrule)); 3438 break; 3439 } 3440 json_decref (jrule); 3441 } 3442 { 3443 json_t *empty = json_object (); 3444 3445 GNUNET_assert (NULL != empty); 3446 wallet_default_lrs 3447 = GNUNET_JSON_PACK ( 3448 GNUNET_JSON_pack_timestamp ("expiration_time", 3449 GNUNET_TIME_UNIT_FOREVER_TS), 3450 GNUNET_JSON_pack_array_steal ("rules", 3451 jkyc_rules_w), 3452 GNUNET_JSON_pack_object_incref ("custom_measures", 3453 empty) 3454 ); 3455 bankaccount_default_lrs 3456 = GNUNET_JSON_PACK ( 3457 GNUNET_JSON_pack_timestamp ("expiration_time", 3458 GNUNET_TIME_UNIT_FOREVER_TS), 3459 GNUNET_JSON_pack_array_steal ("rules", 3460 jkyc_rules_a), 3461 GNUNET_JSON_pack_object_incref ("custom_measures", 3462 empty) 3463 ); 3464 json_decref (empty); 3465 } 3466 for (unsigned int i=0; i<default_rules.num_custom_measures; i++) 3467 { 3468 const struct TALER_KYCLOGIC_Measure *measure 3469 = &default_rules.custom_measures[i]; 3470 3471 if (! check_measure (measure)) 3472 { 3473 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 3474 "Configuration of AML measures incorrect. Exiting.\n"); 3475 return GNUNET_SYSERR; 3476 } 3477 } 3478 3479 for (unsigned int i=0; i<num_aml_programs; i++) 3480 { 3481 const struct TALER_KYCLOGIC_AmlProgram *program 3482 = aml_programs[i]; 3483 const struct TALER_KYCLOGIC_Measure *m; 3484 3485 m = find_measure (&default_rules, 3486 program->fallback); 3487 if (NULL == m) 3488 { 3489 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 3490 "Unknown fallback measure `%s' used in program `%s'\n", 3491 program->fallback, 3492 program->program_name); 3493 return GNUNET_SYSERR; 3494 } 3495 if (0 != strcasecmp (m->check_name, 3496 "skip")) 3497 { 3498 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 3499 "Fallback measure `%s' used in AML program `%s' has a check `%s' but fallbacks must have a check of type 'skip'\n", 3500 program->fallback, 3501 program->program_name, 3502 m->check_name); 3503 return GNUNET_SYSERR; 3504 } 3505 if (NULL != m->prog_name) 3506 { 3507 const struct TALER_KYCLOGIC_AmlProgram *fprogram; 3508 3509 fprogram = find_program (m->prog_name); 3510 GNUNET_assert (NULL != fprogram); 3511 if (API_NONE != (fprogram->input_mask & (API_CONTEXT | API_ATTRIBUTES))) 3512 { 3513 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 3514 "Fallback program %s of fallback measure `%s' used in AML program `%s' has required inputs, but fallback measures must not require any inputs\n", 3515 m->prog_name, 3516 program->program_name, 3517 m->check_name); 3518 return GNUNET_SYSERR; 3519 } 3520 } 3521 } 3522 3523 for (unsigned int i = 0; i<num_kyc_checks; i++) 3524 { 3525 struct TALER_KYCLOGIC_KycCheck *kyc_check 3526 = kyc_checks[i]; 3527 const struct TALER_KYCLOGIC_Measure *measure; 3528 3529 measure = find_measure (&default_rules, 3530 kyc_check->fallback); 3531 if (NULL == measure) 3532 { 3533 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 3534 "Unknown fallback measure `%s' used in check `%s'\n", 3535 kyc_check->fallback, 3536 kyc_check->check_name); 3537 return GNUNET_SYSERR; 3538 } 3539 if (0 != strcasecmp (measure->check_name, 3540 "skip")) 3541 { 3542 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 3543 "Fallback measure `%s' used in KYC check `%s' has a check `%s' but fallbacks must have a check of type 'skip'\n", 3544 kyc_check->fallback, 3545 kyc_check->check_name, 3546 measure->check_name); 3547 return GNUNET_SYSERR; 3548 } 3549 if (NULL != measure->prog_name) 3550 { 3551 const struct TALER_KYCLOGIC_AmlProgram *fprogram; 3552 3553 fprogram = find_program (measure->prog_name); 3554 GNUNET_assert (NULL != fprogram); 3555 if (API_NONE != (fprogram->input_mask & (API_CONTEXT | API_ATTRIBUTES))) 3556 { 3557 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 3558 "AML program `%s' used fallback measure `%s' of KYC check `%s' has required inputs, but fallback measures must not require any inputs\n", 3559 measure->prog_name, 3560 kyc_check->fallback, 3561 kyc_check->check_name); 3562 return GNUNET_SYSERR; 3563 } 3564 } 3565 } 3566 3567 return GNUNET_OK; 3568 } 3569 3570 3571 void 3572 TALER_KYCLOGIC_kyc_done (void) 3573 { 3574 free_rules (&default_rules); 3575 memset (&default_rules, 3576 0, 3577 sizeof (default_rules)); 3578 for (unsigned int i = 0; i<num_kyc_providers; i++) 3579 { 3580 struct TALER_KYCLOGIC_KycProvider *kp = kyc_providers[i]; 3581 3582 kp->logic->unload_configuration (kp->pd); 3583 GNUNET_free (kp->provider_name); 3584 GNUNET_free (kp); 3585 } 3586 GNUNET_array_grow (kyc_providers, 3587 num_kyc_providers, 3588 0); 3589 for (unsigned int i = 0; i<num_kyc_logics; i++) 3590 { 3591 struct TALER_KYCLOGIC_Plugin *lp = kyc_logics[i]; 3592 char *lib_name = lp->library_name; 3593 3594 GNUNET_free (lp->name); 3595 GNUNET_assert (NULL == GNUNET_PLUGIN_unload (lib_name, 3596 lp)); 3597 GNUNET_free (lib_name); 3598 } 3599 GNUNET_array_grow (kyc_logics, 3600 num_kyc_logics, 3601 0); 3602 for (unsigned int i = 0; i<num_kyc_checks; i++) 3603 { 3604 struct TALER_KYCLOGIC_KycCheck *kc = kyc_checks[i]; 3605 3606 GNUNET_free (kc->check_name); 3607 GNUNET_free (kc->description); 3608 json_decref (kc->description_i18n); 3609 for (unsigned int j = 0; j<kc->num_requires; j++) 3610 GNUNET_free (kc->requires[j]); 3611 GNUNET_array_grow (kc->requires, 3612 kc->num_requires, 3613 0); 3614 GNUNET_free (kc->fallback); 3615 for (unsigned int j = 0; j<kc->num_outputs; j++) 3616 GNUNET_free (kc->outputs[j]); 3617 GNUNET_array_grow (kc->outputs, 3618 kc->num_outputs, 3619 0); 3620 switch (kc->type) 3621 { 3622 case TALER_KYCLOGIC_CT_INFO: 3623 break; 3624 case TALER_KYCLOGIC_CT_FORM: 3625 GNUNET_free (kc->details.form.name); 3626 break; 3627 case TALER_KYCLOGIC_CT_LINK: 3628 break; 3629 } 3630 GNUNET_free (kc); 3631 } 3632 GNUNET_array_grow (kyc_checks, 3633 num_kyc_checks, 3634 0); 3635 for (unsigned int i = 0; i<num_aml_programs; i++) 3636 { 3637 struct TALER_KYCLOGIC_AmlProgram *ap = aml_programs[i]; 3638 3639 GNUNET_free (ap->program_name); 3640 GNUNET_free (ap->command); 3641 GNUNET_free (ap->description); 3642 GNUNET_free (ap->fallback); 3643 for (unsigned int j = 0; j<ap->num_required_contexts; j++) 3644 GNUNET_free (ap->required_contexts[j]); 3645 GNUNET_array_grow (ap->required_contexts, 3646 ap->num_required_contexts, 3647 0); 3648 for (unsigned int j = 0; j<ap->num_required_attributes; j++) 3649 GNUNET_free (ap->required_attributes[j]); 3650 GNUNET_array_grow (ap->required_attributes, 3651 ap->num_required_attributes, 3652 0); 3653 GNUNET_free (ap); 3654 } 3655 GNUNET_array_grow (aml_programs, 3656 num_aml_programs, 3657 0); 3658 GNUNET_free (cfg_filename); 3659 } 3660 3661 3662 void 3663 TALER_KYCLOGIC_provider_to_logic ( 3664 const struct TALER_KYCLOGIC_KycProvider *provider, 3665 struct TALER_KYCLOGIC_Plugin **plugin, 3666 struct TALER_KYCLOGIC_ProviderDetails **pd, 3667 const char **provider_name) 3668 { 3669 *plugin = provider->logic; 3670 *pd = provider->pd; 3671 *provider_name = provider->provider_name; 3672 } 3673 3674 3675 enum GNUNET_GenericReturnValue 3676 TALER_KYCLOGIC_get_original_measure ( 3677 const char *measure_name, 3678 struct TALER_KYCLOGIC_KycCheckContext *kcc) 3679 { 3680 const struct TALER_KYCLOGIC_Measure *measure; 3681 3682 measure = find_measure (&default_rules, 3683 measure_name); 3684 if (NULL == measure) 3685 { 3686 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 3687 "Default measure `%s' unknown\n", 3688 measure_name); 3689 return GNUNET_SYSERR; 3690 } 3691 if (0 == strcasecmp (measure->check_name, 3692 "skip")) 3693 { 3694 kcc->check = NULL; 3695 kcc->prog_name = measure->prog_name; 3696 kcc->context = measure->context; 3697 return GNUNET_OK; 3698 } 3699 3700 for (unsigned int i = 0; i<num_kyc_checks; i++) 3701 if (0 == strcasecmp (measure->check_name, 3702 kyc_checks[i]->check_name)) 3703 { 3704 kcc->check = kyc_checks[i]; 3705 kcc->prog_name = measure->prog_name; 3706 kcc->context = measure->context; 3707 return GNUNET_OK; 3708 } 3709 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 3710 "Check `%s' unknown (but required by measure `%s')\n", 3711 measure->check_name, 3712 measure_name); 3713 return GNUNET_SYSERR; 3714 } 3715 3716 3717 enum GNUNET_GenericReturnValue 3718 TALER_KYCLOGIC_requirements_to_check ( 3719 const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs, 3720 const struct TALER_KYCLOGIC_KycRule *kyc_rule, 3721 const char *measure_name, 3722 struct TALER_KYCLOGIC_KycCheckContext *kcc) 3723 { 3724 bool found = false; 3725 const struct TALER_KYCLOGIC_Measure *measure = NULL; 3726 3727 if (NULL == lrs) 3728 lrs = &default_rules; 3729 if (NULL == measure_name) 3730 { 3731 GNUNET_break (0); 3732 return GNUNET_SYSERR; 3733 } 3734 if (NULL != kyc_rule) 3735 { 3736 if (kyc_rule->verboten) 3737 { 3738 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 3739 "Rule says operation is categorically is verboten, cannot take measures\n"); 3740 return GNUNET_SYSERR; 3741 } 3742 for (unsigned int i = 0; i<kyc_rule->num_measures; i++) 3743 { 3744 if (0 != strcasecmp (measure_name, 3745 kyc_rule->next_measures[i])) 3746 continue; 3747 found = true; 3748 break; 3749 } 3750 if (! found) 3751 { 3752 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 3753 "Measure `%s' not allowed for rule `%s'\n", 3754 measure_name, 3755 kyc_rule->rule_name); 3756 return GNUNET_SYSERR; 3757 } 3758 } 3759 measure = find_measure (lrs, 3760 measure_name); 3761 if (NULL == measure) 3762 { 3763 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 3764 "Measure `%s' unknown (but allowed by rule `%s')\n", 3765 measure_name, 3766 NULL != kyc_rule 3767 ? kyc_rule->rule_name 3768 : "<NONE>"); 3769 return GNUNET_SYSERR; 3770 } 3771 3772 if (0 == strcasecmp (measure->check_name, 3773 "skip")) 3774 { 3775 kcc->check = NULL; 3776 kcc->prog_name = measure->prog_name; 3777 kcc->context = measure->context; 3778 return GNUNET_OK; 3779 } 3780 3781 for (unsigned int i = 0; i<num_kyc_checks; i++) 3782 if (0 == strcasecmp (measure->check_name, 3783 kyc_checks[i]->check_name)) 3784 { 3785 kcc->check = kyc_checks[i]; 3786 kcc->prog_name = measure->prog_name; 3787 kcc->context = measure->context; 3788 return GNUNET_OK; 3789 } 3790 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 3791 "Check `%s' unknown (but required by measure `%s')\n", 3792 measure->check_name, 3793 measure_name); 3794 return GNUNET_SYSERR; 3795 } 3796 3797 3798 enum GNUNET_GenericReturnValue 3799 TALER_KYCLOGIC_lookup_logic ( 3800 const char *name, 3801 struct TALER_KYCLOGIC_Plugin **plugin, 3802 struct TALER_KYCLOGIC_ProviderDetails **pd, 3803 const char **provider_name) 3804 { 3805 for (unsigned int i = 0; i<num_kyc_providers; i++) 3806 { 3807 struct TALER_KYCLOGIC_KycProvider *kp = kyc_providers[i]; 3808 3809 if (0 != 3810 strcasecmp (name, 3811 kp->provider_name)) 3812 continue; 3813 *plugin = kp->logic; 3814 *pd = kp->pd; 3815 *provider_name = kp->provider_name; 3816 return GNUNET_OK; 3817 } 3818 for (unsigned int i = 0; i<num_kyc_logics; i++) 3819 { 3820 struct TALER_KYCLOGIC_Plugin *logic = kyc_logics[i]; 3821 3822 if (0 != 3823 strcasecmp (logic->name, 3824 name)) 3825 continue; 3826 *plugin = logic; 3827 *pd = NULL; 3828 *provider_name = NULL; 3829 return GNUNET_OK; 3830 } 3831 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 3832 "Provider `%s' unknown\n", 3833 name); 3834 return GNUNET_SYSERR; 3835 } 3836 3837 3838 void 3839 TALER_KYCLOGIC_kyc_get_details ( 3840 const char *logic_name, 3841 TALER_KYCLOGIC_DetailsCallback cb, 3842 void *cb_cls) 3843 { 3844 for (unsigned int i = 0; i<num_kyc_providers; i++) 3845 { 3846 struct TALER_KYCLOGIC_KycProvider *kp 3847 = kyc_providers[i]; 3848 3849 if (0 != 3850 strcasecmp (kp->logic->name, 3851 logic_name)) 3852 continue; 3853 if (GNUNET_OK != 3854 cb (cb_cls, 3855 kp->pd, 3856 kp->logic->cls)) 3857 return; 3858 } 3859 } 3860 3861 3862 /** 3863 * Closure for check_amount(). 3864 */ 3865 struct KycTestContext 3866 { 3867 /** 3868 * Rule set we apply. 3869 */ 3870 const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs; 3871 3872 /** 3873 * Events we care about. 3874 */ 3875 enum TALER_KYCLOGIC_KycTriggerEvent event; 3876 3877 /** 3878 * Total amount encountered so far, invalid if zero. 3879 */ 3880 struct TALER_Amount sum; 3881 3882 /** 3883 * Set to the triggered rule. 3884 */ 3885 const struct TALER_KYCLOGIC_KycRule *triggered_rule; 3886 3887 }; 3888 3889 3890 /** 3891 * Function called on each @a amount that was found to 3892 * be relevant for a KYC check. Evaluates the given 3893 * @a amount and @a date against all the applicable 3894 * rules in the legitimization rule set. 3895 * 3896 * @param cls our `struct KycTestContext *` 3897 * @param amount encountered transaction amount 3898 * @param date when was the amount encountered 3899 * @return #GNUNET_OK to continue to iterate, 3900 * #GNUNET_NO to abort iteration, 3901 * #GNUNET_SYSERR on internal error (also abort itaration) 3902 */ 3903 static enum GNUNET_GenericReturnValue 3904 check_amount ( 3905 void *cls, 3906 const struct TALER_Amount *amount, 3907 struct GNUNET_TIME_Absolute date) 3908 { 3909 struct KycTestContext *ktc = cls; 3910 struct GNUNET_TIME_Relative dur; 3911 3912 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 3913 "KYC checking transaction amount %s from %s against %u rules\n", 3914 TALER_amount2s (amount), 3915 GNUNET_TIME_absolute2s (date), 3916 ktc->lrs->num_kyc_rules); 3917 dur = GNUNET_TIME_absolute_get_duration (date); 3918 if (GNUNET_OK != 3919 TALER_amount_is_valid (&ktc->sum)) 3920 ktc->sum = *amount; 3921 else 3922 GNUNET_assert (0 <= 3923 TALER_amount_add (&ktc->sum, 3924 &ktc->sum, 3925 amount)); 3926 for (unsigned int i=0; i<ktc->lrs->num_kyc_rules; i++) 3927 { 3928 const struct TALER_KYCLOGIC_KycRule *rule 3929 = &ktc->lrs->kyc_rules[i]; 3930 3931 if (ktc->event != rule->trigger) 3932 { 3933 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 3934 "Wrong event type (%d) for rule %u (%d)\n", 3935 (int) ktc->event, 3936 i, 3937 (int) rule->trigger); 3938 continue; /* wrong trigger event type */ 3939 } 3940 if (GNUNET_TIME_relative_cmp (dur, 3941 >, 3942 rule->timeframe)) 3943 { 3944 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 3945 "Out of time range for rule %u\n", 3946 i); 3947 continue; /* out of time range for rule */ 3948 } 3949 /* 3950 * A KYC threshold is the inclusive maximum permitted by the rule: 3951 * clients may transact up to and including this amount. The rule is 3952 * triggered only once the accumulated total exceeds the threshold. 3953 * Keeping equality on the permitted side is also important because 3954 * exposed AccountLimit values are advertised as maximum contributions. 3955 */ 3956 if (0 >= TALER_amount_cmp (&ktc->sum, 3957 &rule->threshold)) 3958 { 3959 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 3960 "At or below threshold of %s for rule %u\n", 3961 TALER_amount2s (&rule->threshold), 3962 i); 3963 continue; /* sum <= threshold */ 3964 } 3965 if ( (NULL != ktc->triggered_rule) && 3966 (1 == TALER_amount_cmp (&ktc->triggered_rule->threshold, 3967 &rule->threshold)) ) 3968 { 3969 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 3970 "Higher than threshold of already triggered rule\n"); 3971 continue; /* threshold of triggered_rule > rule */ 3972 } 3973 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 3974 "Remembering rule %s as triggered\n", 3975 rule->rule_name); 3976 ktc->triggered_rule = rule; 3977 } 3978 return GNUNET_OK; 3979 } 3980 3981 3982 enum GNUNET_DB_QueryStatus 3983 TALER_KYCLOGIC_kyc_test_required ( 3984 enum TALER_KYCLOGIC_KycTriggerEvent event, 3985 const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs, 3986 TALER_KYCLOGIC_KycAmountIterator ai, 3987 void *ai_cls, 3988 const struct TALER_KYCLOGIC_KycRule **triggered_rule, 3989 struct TALER_Amount *next_threshold) 3990 { 3991 struct GNUNET_TIME_Relative range 3992 = GNUNET_TIME_UNIT_ZERO; 3993 enum GNUNET_DB_QueryStatus qs; 3994 bool have_threshold = false; 3995 3996 memset (next_threshold, 3997 0, 3998 sizeof (struct TALER_Amount)); 3999 if (NULL == lrs) 4000 lrs = &default_rules; 4001 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 4002 "Testing %u KYC rules for trigger %d\n", 4003 lrs->num_kyc_rules, 4004 event); 4005 for (unsigned int i=0; i<lrs->num_kyc_rules; i++) 4006 { 4007 const struct TALER_KYCLOGIC_KycRule *rule 4008 = &lrs->kyc_rules[i]; 4009 4010 if (event != rule->trigger) 4011 { 4012 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 4013 "Rule %u is for a different trigger (%d/%d)\n", 4014 i, 4015 (int) event, 4016 (int) rule->trigger); 4017 continue; 4018 } 4019 if (have_threshold) 4020 { 4021 GNUNET_assert (GNUNET_OK == 4022 TALER_amount_min (next_threshold, 4023 next_threshold, 4024 &rule->threshold)); 4025 } 4026 else 4027 { 4028 *next_threshold = rule->threshold; 4029 have_threshold = true; 4030 } 4031 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 4032 "Matched rule %u with timeframe %s and threshold %s\n", 4033 i, 4034 GNUNET_TIME_relative2s (rule->timeframe, 4035 true), 4036 TALER_amount2s (&rule->threshold)); 4037 range = GNUNET_TIME_relative_max (range, 4038 rule->timeframe); 4039 } 4040 4041 if (! have_threshold) 4042 { 4043 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 4044 "No rules apply\n"); 4045 *triggered_rule = NULL; 4046 return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; 4047 } 4048 4049 { 4050 struct GNUNET_TIME_Absolute now 4051 = GNUNET_TIME_absolute_get (); 4052 struct KycTestContext ktc = { 4053 .lrs = lrs, 4054 .event = event 4055 }; 4056 4057 qs = ai (ai_cls, 4058 GNUNET_TIME_absolute_subtract (now, 4059 range), 4060 &check_amount, 4061 &ktc); 4062 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 4063 "Triggered rule is %s\n", 4064 (NULL == ktc.triggered_rule) 4065 ? "NONE" 4066 : ktc.triggered_rule->rule_name); 4067 *triggered_rule = ktc.triggered_rule; 4068 } 4069 return qs; 4070 } 4071 4072 4073 json_t * 4074 TALER_KYCLOGIC_measure_to_requirement ( 4075 const char *check_name, 4076 const json_t *context, 4077 const struct TALER_AccountAccessTokenP *access_token, 4078 size_t offset, 4079 uint64_t legitimization_measure_row_id) 4080 { 4081 struct TALER_KYCLOGIC_KycCheck *kc; 4082 json_t *kri; 4083 struct TALER_KycMeasureAuthorizationHashP shv; 4084 char *ids; 4085 char *xids; 4086 4087 kc = find_check (check_name); 4088 if (NULL == kc) 4089 { 4090 GNUNET_break (0); 4091 return NULL; 4092 } 4093 GNUNET_assert (offset <= UINT32_MAX); 4094 TALER_kyc_measure_authorization_hash (access_token, 4095 legitimization_measure_row_id, 4096 (uint32_t) offset, 4097 &shv); 4098 switch (kc->type) 4099 { 4100 case TALER_KYCLOGIC_CT_INFO: 4101 return GNUNET_JSON_PACK ( 4102 GNUNET_JSON_pack_string ("form", 4103 "INFO"), 4104 GNUNET_JSON_pack_string ("description", 4105 kc->description), 4106 GNUNET_JSON_pack_allow_null ( 4107 GNUNET_JSON_pack_object_incref ("description_i18n", 4108 (json_t *) kc->description_i18n))); 4109 case TALER_KYCLOGIC_CT_FORM: 4110 GNUNET_assert (offset <= UINT_MAX); 4111 ids = GNUNET_STRINGS_data_to_string_alloc (&shv, 4112 sizeof (shv)); 4113 GNUNET_asprintf (&xids, 4114 "%s-%u-%llu", 4115 ids, 4116 (unsigned int) offset, 4117 (unsigned long long) legitimization_measure_row_id); 4118 GNUNET_free (ids); 4119 kri = GNUNET_JSON_PACK ( 4120 GNUNET_JSON_pack_string ("form", 4121 kc->details.form.name), 4122 GNUNET_JSON_pack_string ("id", 4123 xids), 4124 GNUNET_JSON_pack_allow_null ( 4125 GNUNET_JSON_pack_object_incref ("context", 4126 (json_t *) context)), 4127 GNUNET_JSON_pack_string ("description", 4128 kc->description), 4129 GNUNET_JSON_pack_allow_null ( 4130 GNUNET_JSON_pack_object_incref ("description_i18n", 4131 (json_t *) kc->description_i18n))); 4132 GNUNET_free (xids); 4133 return kri; 4134 case TALER_KYCLOGIC_CT_LINK: 4135 GNUNET_assert (offset <= UINT_MAX); 4136 ids = GNUNET_STRINGS_data_to_string_alloc (&shv, 4137 sizeof (shv)); 4138 GNUNET_asprintf (&xids, 4139 "%s-%u-%llu", 4140 ids, 4141 (unsigned int) offset, 4142 (unsigned long long) legitimization_measure_row_id); 4143 GNUNET_free (ids); 4144 kri = GNUNET_JSON_PACK ( 4145 GNUNET_JSON_pack_string ("form", 4146 "LINK"), 4147 GNUNET_JSON_pack_string ("id", 4148 xids), 4149 GNUNET_JSON_pack_string ("description", 4150 kc->description), 4151 GNUNET_JSON_pack_allow_null ( 4152 GNUNET_JSON_pack_object_incref ("description_i18n", 4153 (json_t *) kc->description_i18n))); 4154 GNUNET_free (xids); 4155 return kri; 4156 } 4157 GNUNET_break (0); /* invalid type */ 4158 return NULL; 4159 } 4160 4161 4162 void 4163 TALER_KYCLOGIC_get_measure_configuration ( 4164 json_t **proots, 4165 json_t **pprograms, 4166 json_t **pchecks, 4167 json_t **pdefault_rules) 4168 { 4169 json_t *roots; 4170 json_t *programs; 4171 json_t *checks; 4172 json_t *drules; 4173 4174 roots = json_object (); 4175 GNUNET_assert (NULL != roots); 4176 for (unsigned int i = 0; i<default_rules.num_custom_measures; i++) 4177 { 4178 const struct TALER_KYCLOGIC_Measure *m 4179 = &default_rules.custom_measures[i]; 4180 json_t *jm; 4181 4182 jm = GNUNET_JSON_PACK ( 4183 GNUNET_JSON_pack_string ("check_name", 4184 m->check_name), 4185 GNUNET_JSON_pack_allow_null ( 4186 GNUNET_JSON_pack_string ("prog_name", 4187 m->prog_name)), 4188 GNUNET_JSON_pack_allow_null ( 4189 GNUNET_JSON_pack_object_incref ("context", 4190 m->context))); 4191 GNUNET_assert (0 == 4192 json_object_set_new (roots, 4193 m->measure_name, 4194 jm)); 4195 } 4196 4197 programs = json_object (); 4198 GNUNET_assert (NULL != programs); 4199 for (unsigned int i = 0; i<num_aml_programs; i++) 4200 { 4201 const struct TALER_KYCLOGIC_AmlProgram *ap 4202 = aml_programs[i]; 4203 json_t *jp; 4204 json_t *ctx; 4205 json_t *inp; 4206 4207 ctx = json_array (); 4208 GNUNET_assert (NULL != ctx); 4209 for (unsigned int j = 0; j<ap->num_required_contexts; j++) 4210 { 4211 const char *rc = ap->required_contexts[j]; 4212 4213 GNUNET_assert (0 == 4214 json_array_append_new (ctx, 4215 json_string (rc))); 4216 } 4217 inp = json_array (); 4218 GNUNET_assert (NULL != inp); 4219 for (unsigned int j = 0; j<ap->num_required_attributes; j++) 4220 { 4221 const char *ra = ap->required_attributes[j]; 4222 4223 GNUNET_assert (0 == 4224 json_array_append_new (inp, 4225 json_string (ra))); 4226 } 4227 4228 jp = GNUNET_JSON_PACK ( 4229 GNUNET_JSON_pack_string ("description", 4230 ap->description), 4231 GNUNET_JSON_pack_array_steal ("context", 4232 ctx), 4233 GNUNET_JSON_pack_array_steal ("inputs", 4234 inp)); 4235 GNUNET_assert (0 == 4236 json_object_set_new (programs, 4237 ap->program_name, 4238 jp)); 4239 } 4240 4241 checks = json_object (); 4242 GNUNET_assert (NULL != checks); 4243 for (unsigned int i = 0; i<num_kyc_checks; i++) 4244 { 4245 const struct TALER_KYCLOGIC_KycCheck *ck 4246 = kyc_checks[i]; 4247 json_t *jc; 4248 json_t *requires; 4249 json_t *outputs; 4250 4251 requires = json_array (); 4252 GNUNET_assert (NULL != requires); 4253 for (unsigned int j = 0; j<ck->num_requires; j++) 4254 { 4255 const char *ra = ck->requires[j]; 4256 4257 GNUNET_assert (0 == 4258 json_array_append_new (requires, 4259 json_string (ra))); 4260 } 4261 outputs = json_array (); 4262 GNUNET_assert (NULL != outputs); 4263 for (unsigned int j = 0; j<ck->num_outputs; j++) 4264 { 4265 const char *out = ck->outputs[j]; 4266 4267 GNUNET_assert (0 == 4268 json_array_append_new (outputs, 4269 json_string (out))); 4270 } 4271 4272 jc = GNUNET_JSON_PACK ( 4273 GNUNET_JSON_pack_string ("description", 4274 ck->description), 4275 GNUNET_JSON_pack_allow_null ( 4276 GNUNET_JSON_pack_object_incref ("description_i18n", 4277 ck->description_i18n)), 4278 GNUNET_JSON_pack_array_steal ("requires", 4279 requires), 4280 GNUNET_JSON_pack_array_steal ("outputs", 4281 outputs), 4282 GNUNET_JSON_pack_string ("fallback", 4283 ck->fallback)); 4284 GNUNET_assert (0 == 4285 json_object_set_new (checks, 4286 ck->check_name, 4287 jc)); 4288 } 4289 drules = json_array (); 4290 GNUNET_assert (NULL != drules); 4291 { 4292 const struct TALER_KYCLOGIC_KycRule *rules 4293 = default_rules.kyc_rules; 4294 unsigned int num_rules 4295 = default_rules.num_kyc_rules; 4296 4297 for (unsigned int i = 0; i<num_rules; i++) 4298 { 4299 const struct TALER_KYCLOGIC_KycRule *rule = &rules[i]; 4300 json_t *measures; 4301 json_t *limit; 4302 4303 measures = json_array (); 4304 GNUNET_assert (NULL != measures); 4305 for (unsigned int j = 0; j<rule->num_measures; j++) 4306 GNUNET_assert ( 4307 0 == 4308 json_array_append_new (measures, 4309 json_string ( 4310 rule->next_measures[j]))); 4311 limit = GNUNET_JSON_PACK ( 4312 GNUNET_JSON_pack_allow_null ( 4313 GNUNET_JSON_pack_string ("rule_name", 4314 rule->rule_name)), 4315 TALER_JSON_pack_kycte ("operation_type", 4316 rule->trigger), 4317 TALER_JSON_pack_amount ("threshold", 4318 &rule->threshold), 4319 GNUNET_JSON_pack_time_rel ("timeframe", 4320 rule->timeframe), 4321 GNUNET_JSON_pack_array_steal ("measures", 4322 measures), 4323 GNUNET_JSON_pack_uint64 ("display_priority", 4324 rule->display_priority), 4325 GNUNET_JSON_pack_bool ("soft_limit", 4326 ! rule->verboten), 4327 GNUNET_JSON_pack_bool ("exposed", 4328 rule->exposed), 4329 GNUNET_JSON_pack_bool ("is_and_combinator", 4330 rule->is_and_combinator) 4331 ); 4332 GNUNET_assert (0 == 4333 json_array_append_new (drules, 4334 limit)); 4335 } 4336 } 4337 4338 *proots = roots; 4339 *pprograms = programs; 4340 *pchecks = checks; 4341 *pdefault_rules = drules; 4342 } 4343 4344 4345 enum TALER_ErrorCode 4346 TALER_KYCLOGIC_select_measure ( 4347 const json_t *jmeasures, 4348 size_t measure_index, 4349 const char **check_name, 4350 const char **prog_name, 4351 const json_t **context) 4352 { 4353 const json_t *jmeasure_arr; 4354 struct GNUNET_JSON_Specification spec[] = { 4355 GNUNET_JSON_spec_array_const ("measures", 4356 &jmeasure_arr), 4357 GNUNET_JSON_spec_end () 4358 }; 4359 const json_t *jmeasure; 4360 struct GNUNET_JSON_Specification ispec[] = { 4361 GNUNET_JSON_spec_string ("check_name", 4362 check_name), 4363 GNUNET_JSON_spec_mark_optional ( 4364 GNUNET_JSON_spec_string ("prog_name", 4365 prog_name), 4366 NULL), 4367 GNUNET_JSON_spec_mark_optional ( 4368 GNUNET_JSON_spec_object_const ("context", 4369 context), 4370 NULL), 4371 GNUNET_JSON_spec_end () 4372 }; 4373 4374 *check_name = NULL; 4375 *prog_name = NULL; 4376 *context = NULL; 4377 if (GNUNET_OK != 4378 GNUNET_JSON_parse (jmeasures, 4379 spec, 4380 NULL, NULL)) 4381 { 4382 GNUNET_break (0); 4383 return TALER_EC_EXCHANGE_KYC_MEASURES_MALFORMED; 4384 } 4385 if (measure_index >= json_array_size (jmeasure_arr)) 4386 { 4387 GNUNET_break_op (0); 4388 return TALER_EC_EXCHANGE_KYC_MEASURE_INDEX_INVALID; 4389 } 4390 jmeasure = json_array_get (jmeasure_arr, 4391 measure_index); 4392 if (GNUNET_OK != 4393 GNUNET_JSON_parse (jmeasure, 4394 ispec, 4395 NULL, NULL)) 4396 { 4397 GNUNET_break (0); 4398 return TALER_EC_EXCHANGE_KYC_MEASURES_MALFORMED; 4399 } 4400 return TALER_EC_NONE; 4401 } 4402 4403 4404 enum TALER_ErrorCode 4405 TALER_KYCLOGIC_check_form ( 4406 const json_t *jmeasures, 4407 size_t measure_index, 4408 const json_t *form_data, 4409 char **form_name, 4410 const char **error_message) 4411 { 4412 const char *check_name; 4413 const char *prog_name; 4414 const json_t *context; 4415 struct TALER_KYCLOGIC_KycCheck *kc; 4416 struct TALER_KYCLOGIC_AmlProgram *prog; 4417 4418 *error_message = NULL; 4419 *form_name = NULL; 4420 if (TALER_EC_NONE != 4421 TALER_KYCLOGIC_select_measure (jmeasures, 4422 measure_index, 4423 &check_name, 4424 &prog_name, 4425 &context)) 4426 { 4427 GNUNET_break_op (0); 4428 return TALER_EC_EXCHANGE_KYC_MEASURE_INDEX_INVALID; 4429 } 4430 kc = find_check (check_name); 4431 if (NULL == kc) 4432 { 4433 GNUNET_break (0); 4434 *error_message = check_name; 4435 return TALER_EC_EXCHANGE_KYC_GENERIC_CHECK_GONE; 4436 } 4437 if (TALER_KYCLOGIC_CT_FORM != kc->type) 4438 { 4439 GNUNET_break_op (0); 4440 return TALER_EC_EXCHANGE_KYC_NOT_A_FORM; 4441 } 4442 if (NULL == prog_name) 4443 { 4444 /* non-INFO checks must have an AML program */ 4445 GNUNET_break (0); 4446 return TALER_EC_EXCHANGE_KYC_GENERIC_LOGIC_BUG; 4447 } 4448 for (unsigned int i = 0; i<kc->num_outputs; i++) 4449 { 4450 const char *rattr = kc->outputs[i]; 4451 4452 if (NULL == json_object_get (form_data, 4453 rattr)) 4454 { 4455 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 4456 "Form data lacks required attribute `%s' for KYC check `%s'\n", 4457 rattr, 4458 check_name); 4459 *error_message = rattr; 4460 return TALER_EC_EXCHANGE_KYC_AML_FORM_INCOMPLETE; 4461 } 4462 } 4463 prog = find_program (prog_name); 4464 if (NULL == prog) 4465 { 4466 GNUNET_break (0); 4467 *error_message = prog_name; 4468 return TALER_EC_EXCHANGE_KYC_GENERIC_AML_PROGRAM_GONE; 4469 } 4470 for (unsigned int i = 0; i<prog->num_required_attributes; i++) 4471 { 4472 const char *rattr = prog->required_attributes[i]; 4473 4474 if (NULL == json_object_get (form_data, 4475 rattr)) 4476 { 4477 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 4478 "Form data lacks required attribute `%s' for AML program %s\n", 4479 rattr, 4480 prog_name); 4481 *error_message = rattr; 4482 return TALER_EC_EXCHANGE_KYC_AML_FORM_INCOMPLETE; 4483 } 4484 } 4485 *form_name = GNUNET_strdup (kc->details.form.name); 4486 return TALER_EC_NONE; 4487 } 4488 4489 4490 const char * 4491 TALER_KYCLOGIC_get_aml_program_fallback (const char *prog_name) 4492 { 4493 struct TALER_KYCLOGIC_AmlProgram *prog; 4494 4495 prog = find_program (prog_name); 4496 if (NULL == prog) 4497 { 4498 GNUNET_break (0); 4499 return NULL; 4500 } 4501 return prog->fallback; 4502 } 4503 4504 4505 const struct TALER_KYCLOGIC_KycProvider * 4506 TALER_KYCLOGIC_check_to_provider (const char *check_name) 4507 { 4508 struct TALER_KYCLOGIC_KycCheck *kc; 4509 4510 if (NULL == check_name) 4511 return NULL; 4512 if (0 == strcasecmp (check_name, 4513 "skip")) 4514 return NULL; 4515 kc = find_check (check_name); 4516 if (NULL == kc) 4517 { 4518 GNUNET_break (0); 4519 return NULL; 4520 } 4521 switch (kc->type) 4522 { 4523 case TALER_KYCLOGIC_CT_FORM: 4524 case TALER_KYCLOGIC_CT_INFO: 4525 return NULL; 4526 case TALER_KYCLOGIC_CT_LINK: 4527 break; 4528 } 4529 return kc->details.link.provider; 4530 } 4531 4532 4533 struct TALER_KYCLOGIC_AmlProgramRunnerHandle 4534 { 4535 /** 4536 * Function to call back with the result. 4537 */ 4538 TALER_KYCLOGIC_AmlProgramResultCallback aprc; 4539 4540 /** 4541 * Closure for @e aprc. 4542 */ 4543 void *aprc_cls; 4544 4545 /** 4546 * Handle to an external process. 4547 */ 4548 struct TALER_JSON_ExternalConversion *proc; 4549 4550 /** 4551 * AML program to turn. 4552 */ 4553 const struct TALER_KYCLOGIC_AmlProgram *program; 4554 4555 /** 4556 * Task to return @e apr result asynchronously. 4557 */ 4558 struct GNUNET_SCHEDULER_Task *async_cb; 4559 4560 /** 4561 * Result returned to the client. 4562 */ 4563 struct TALER_KYCLOGIC_AmlProgramResult apr; 4564 4565 /** 4566 * How long do we allow the AML program to run? 4567 */ 4568 struct GNUNET_TIME_Relative timeout; 4569 4570 }; 4571 4572 4573 /** 4574 * Function that that receives a JSON @a result from 4575 * the AML program. 4576 * 4577 * @param cls closure of type `struct TALER_KYCLOGIC_AmlProgramRunnerHandle` 4578 * @param status_type how did the process die 4579 * @param code termination status code from the process, 4580 * non-zero if AML checks are required next 4581 * @param result some JSON result, NULL if we failed to get an JSON output 4582 */ 4583 static void 4584 handle_aml_output ( 4585 void *cls, 4586 enum GNUNET_OS_ProcessStatusType status_type, 4587 unsigned long code, 4588 const json_t *result) 4589 { 4590 struct TALER_KYCLOGIC_AmlProgramRunnerHandle *aprh = cls; 4591 const char *fallback_measure = aprh->program->fallback; 4592 struct TALER_KYCLOGIC_AmlProgramResult *apr = &aprh->apr; 4593 const char **evs = NULL; 4594 4595 aprh->proc = NULL; 4596 if (NULL != aprh->async_cb) 4597 { 4598 GNUNET_SCHEDULER_cancel (aprh->async_cb); 4599 aprh->async_cb = NULL; 4600 } 4601 #if DEBUG 4602 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 4603 "AML program %s output is:\n", 4604 aprh->program->program_name); 4605 json_dumpf (result, 4606 stderr, 4607 JSON_INDENT (2)); 4608 #endif 4609 memset (apr, 4610 0, 4611 sizeof (*apr)); 4612 if ( (GNUNET_OS_PROCESS_EXITED != status_type) || 4613 (0 != code) ) 4614 { 4615 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 4616 "AML program %s returned non-zero status %d/%d\n", 4617 aprh->program->program_name, 4618 (int) status_type, 4619 (int) code); 4620 apr->status = TALER_KYCLOGIC_AMLR_FAILURE; 4621 apr->details.failure.fallback_measure 4622 = fallback_measure; 4623 apr->details.failure.error_message 4624 = "AML program returned non-zero exit code"; 4625 apr->details.failure.ec 4626 = TALER_EC_EXCHANGE_KYC_AML_PROGRAM_FAILURE; 4627 goto ready; 4628 } 4629 4630 { 4631 const json_t *jevents = NULL; 4632 struct GNUNET_JSON_Specification spec[] = { 4633 GNUNET_JSON_spec_mark_optional ( 4634 GNUNET_JSON_spec_bool ( 4635 "to_investigate", 4636 &apr->details.success.to_investigate), 4637 NULL), 4638 GNUNET_JSON_spec_mark_optional ( 4639 GNUNET_JSON_spec_object_const ( 4640 "properties", 4641 &apr->details.success.account_properties), 4642 NULL), 4643 GNUNET_JSON_spec_mark_optional ( 4644 GNUNET_JSON_spec_array_const ( 4645 "events", 4646 &jevents), 4647 NULL), 4648 GNUNET_JSON_spec_object_const ( 4649 "new_rules", 4650 &apr->details.success.new_rules), 4651 GNUNET_JSON_spec_mark_optional ( 4652 GNUNET_JSON_spec_string ( 4653 "new_measures", 4654 &apr->details.success.new_measures), 4655 NULL), 4656 GNUNET_JSON_spec_end () 4657 }; 4658 const char *err; 4659 unsigned int line; 4660 4661 if (GNUNET_OK != 4662 GNUNET_JSON_parse (result, 4663 spec, 4664 &err, 4665 &line)) 4666 { 4667 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 4668 "AML program output is malformed at `%s'\n", 4669 err); 4670 json_dumpf (result, 4671 stderr, 4672 JSON_INDENT (2)); 4673 apr->status = TALER_KYCLOGIC_AMLR_FAILURE; 4674 apr->details.failure.fallback_measure 4675 = fallback_measure; 4676 apr->details.failure.error_message 4677 = err; 4678 apr->details.failure.ec 4679 = TALER_EC_EXCHANGE_KYC_AML_PROGRAM_MALFORMED_RESULT; 4680 goto ready; 4681 } 4682 apr->details.success.num_events 4683 = json_array_size (jevents); 4684 4685 GNUNET_assert (((size_t) apr->details.success.num_events) == 4686 json_array_size (jevents)); 4687 evs = GNUNET_new_array ( 4688 apr->details.success.num_events, 4689 const char *); 4690 for (unsigned int i = 0; i<apr->details.success.num_events; i++) 4691 { 4692 evs[i] = json_string_value ( 4693 json_array_get (jevents, 4694 i)); 4695 if (NULL == evs[i]) 4696 { 4697 apr->status = TALER_KYCLOGIC_AMLR_FAILURE; 4698 apr->details.failure.fallback_measure 4699 = fallback_measure; 4700 apr->details.failure.error_message 4701 = "events"; 4702 apr->details.failure.ec 4703 = TALER_EC_EXCHANGE_KYC_AML_PROGRAM_MALFORMED_RESULT; 4704 goto ready; 4705 } 4706 } 4707 apr->status = TALER_KYCLOGIC_AMLR_SUCCESS; 4708 apr->details.success.events = evs; 4709 { 4710 /* check new_rules */ 4711 struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs; 4712 4713 lrs = TALER_KYCLOGIC_rules_parse ( 4714 apr->details.success.new_rules); 4715 if (NULL == lrs) 4716 { 4717 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 4718 "AML program output is malformed at `%s'\n", 4719 "new_rules"); 4720 4721 apr->status = TALER_KYCLOGIC_AMLR_FAILURE; 4722 apr->details.failure.fallback_measure 4723 = fallback_measure; 4724 apr->details.failure.error_message 4725 = "new_rules"; 4726 apr->details.failure.ec 4727 = TALER_EC_EXCHANGE_KYC_AML_PROGRAM_MALFORMED_RESULT; 4728 goto ready; 4729 } 4730 apr->details.success.expiration_time 4731 = lrs->expiration_time; 4732 TALER_KYCLOGIC_rules_free (lrs); 4733 } 4734 } 4735 ready: 4736 aprh->aprc (aprh->aprc_cls, 4737 &aprh->apr); 4738 GNUNET_free (evs); 4739 TALER_KYCLOGIC_run_aml_program_cancel (aprh); 4740 } 4741 4742 4743 /** 4744 * Helper function to asynchronously return the result. 4745 * 4746 * @param[in] cls a `struct TALER_KYCLOGIC_AmlProgramRunnerHandle` to return results for 4747 */ 4748 static void 4749 async_return_task (void *cls) 4750 { 4751 struct TALER_KYCLOGIC_AmlProgramRunnerHandle *aprh = cls; 4752 4753 aprh->async_cb = NULL; 4754 aprh->aprc (aprh->aprc_cls, 4755 &aprh->apr); 4756 TALER_KYCLOGIC_run_aml_program_cancel (aprh); 4757 } 4758 4759 4760 /** 4761 * Helper function called on timeout on the fallback measure. 4762 * 4763 * @param[in] cls a `struct TALER_KYCLOGIC_AmlProgramRunnerHandle` to return results for 4764 */ 4765 static void 4766 handle_aml_timeout2 (void *cls) 4767 { 4768 struct TALER_KYCLOGIC_AmlProgramRunnerHandle *aprh = cls; 4769 struct TALER_KYCLOGIC_AmlProgramResult *apr = &aprh->apr; 4770 const char *fallback_measure = aprh->program->fallback; 4771 4772 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 4773 "Fallback measure %s ran into timeout (!)\n", 4774 aprh->program->program_name); 4775 if (NULL != aprh->proc) 4776 { 4777 TALER_JSON_external_conversion_stop (aprh->proc); 4778 aprh->proc = NULL; 4779 } 4780 apr->status = TALER_KYCLOGIC_AMLR_FAILURE; 4781 apr->details.failure.fallback_measure 4782 = fallback_measure; 4783 apr->details.failure.error_message 4784 = aprh->program->program_name; 4785 apr->details.failure.ec 4786 = TALER_EC_EXCHANGE_KYC_GENERIC_AML_PROGRAM_TIMEOUT; 4787 async_return_task (aprh); 4788 } 4789 4790 4791 /** 4792 * Helper function called on timeout of an AML program. 4793 * Runs the fallback measure. 4794 * 4795 * @param[in] cls a `struct TALER_KYCLOGIC_AmlProgramRunnerHandle` to return results for 4796 */ 4797 static void 4798 handle_aml_timeout (void *cls) 4799 { 4800 struct TALER_KYCLOGIC_AmlProgramRunnerHandle *aprh = cls; 4801 struct TALER_KYCLOGIC_AmlProgramResult *apr = &aprh->apr; 4802 const char *fallback_measure = aprh->program->fallback; 4803 const struct TALER_KYCLOGIC_Measure *m; 4804 const struct TALER_KYCLOGIC_AmlProgram *fprogram; 4805 4806 aprh->async_cb = NULL; 4807 GNUNET_assert (NULL != fallback_measure); 4808 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 4809 "AML program %s ran into timeout\n", 4810 aprh->program->program_name); 4811 if (NULL != aprh->proc) 4812 { 4813 TALER_JSON_external_conversion_stop (aprh->proc); 4814 aprh->proc = NULL; 4815 } 4816 4817 m = TALER_KYCLOGIC_get_measure (&default_rules, 4818 fallback_measure); 4819 /* Fallback program could have "disappeared" due to configuration change, 4820 as we do not check all rule sets in the database when our configuration 4821 is updated... */ 4822 if (NULL == m) 4823 { 4824 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 4825 "Fallback measure `%s' does not exist (anymore?).\n", 4826 fallback_measure); 4827 apr->status = TALER_KYCLOGIC_AMLR_FAILURE; 4828 apr->details.failure.fallback_measure 4829 = fallback_measure; 4830 apr->details.failure.error_message 4831 = aprh->program->program_name; 4832 apr->details.failure.ec 4833 = TALER_EC_EXCHANGE_KYC_GENERIC_AML_PROGRAM_TIMEOUT; 4834 async_return_task (aprh); 4835 return; 4836 } 4837 /* We require fallback measures to have a 'skip' check */ 4838 GNUNET_break (0 == 4839 strcasecmp (m->check_name, 4840 "skip")); 4841 fprogram = find_program (m->prog_name); 4842 /* Program associated with an original measure must exist */ 4843 GNUNET_assert (NULL != fprogram); 4844 if (API_NONE != (fprogram->input_mask & (API_CONTEXT | API_ATTRIBUTES))) 4845 { 4846 /* We might not have recognized the fallback measure as such 4847 because it was not used as such in the plain configuration, 4848 and legitimization rule sets might have referred to an older 4849 configuration. So this should be super-rare but possible. */ 4850 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 4851 "Program `%s' used in fallback measure `%s' requires inputs and is thus unsuitable as a fallback measure!\n", 4852 m->prog_name, 4853 fallback_measure); 4854 apr->status = TALER_KYCLOGIC_AMLR_FAILURE; 4855 apr->details.failure.fallback_measure 4856 = fallback_measure; 4857 apr->details.failure.error_message 4858 = aprh->program->program_name; 4859 apr->details.failure.ec 4860 = TALER_EC_EXCHANGE_KYC_GENERIC_AML_PROGRAM_TIMEOUT; 4861 async_return_task (aprh); 4862 return; 4863 } 4864 { 4865 /* Run fallback AML program */ 4866 json_t *input = json_object (); 4867 const char *extra_args[] = { 4868 "-c", 4869 cfg_filename, 4870 NULL, 4871 }; 4872 char **args; 4873 4874 args = TALER_words_split (fprogram->command, 4875 extra_args); 4876 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 4877 "Running fallback measure `%s' (%s)\n", 4878 fallback_measure, 4879 fprogram->command); 4880 aprh->proc = TALER_JSON_external_conversion_start ( 4881 input, 4882 &handle_aml_output, 4883 aprh, 4884 args[0], 4885 (const char **) args); 4886 TALER_words_destroy (args); 4887 json_decref (input); 4888 } 4889 aprh->async_cb = GNUNET_SCHEDULER_add_delayed (aprh->timeout, 4890 &handle_aml_timeout2, 4891 aprh); 4892 } 4893 4894 4895 struct TALER_KYCLOGIC_AmlProgramRunnerHandle * 4896 TALER_KYCLOGIC_run_aml_program ( 4897 const json_t *jmeasures, 4898 bool is_wallet, 4899 unsigned int measure_index, 4900 TALER_KYCLOGIC_HistoryBuilderCallback current_attributes_cb, 4901 void *current_attributes_cb_cls, 4902 TALER_KYCLOGIC_HistoryBuilderCallback current_rules_cb, 4903 void *current_rules_cb_cls, 4904 TALER_KYCLOGIC_HistoryBuilderCallback aml_history_cb, 4905 void *aml_history_cb_cls, 4906 TALER_KYCLOGIC_HistoryBuilderCallback kyc_history_cb, 4907 void *kyc_history_cb_cls, 4908 struct GNUNET_TIME_Relative timeout, 4909 TALER_KYCLOGIC_AmlProgramResultCallback aprc, 4910 void *aprc_cls) 4911 { 4912 const json_t *context; 4913 const char *check_name; 4914 const char *prog_name; 4915 4916 { 4917 enum TALER_ErrorCode ec; 4918 4919 ec = TALER_KYCLOGIC_select_measure (jmeasures, 4920 measure_index, 4921 &check_name, 4922 &prog_name, 4923 &context); 4924 if (TALER_EC_NONE != ec) 4925 { 4926 GNUNET_break (0); 4927 return NULL; 4928 } 4929 } 4930 if (NULL == prog_name) 4931 { 4932 /* Trying to run AML program on a measure that does not 4933 have one, and that should thus be an INFO check which 4934 should never lead here. Very strange. */ 4935 GNUNET_break (0); 4936 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 4937 "Measure %u with check `%s' does not have an AML program!\n", 4938 measure_index, 4939 check_name); 4940 json_dumpf (jmeasures, 4941 stderr, 4942 JSON_INDENT (2)); 4943 return NULL; 4944 } 4945 return TALER_KYCLOGIC_run_aml_program2 (prog_name, 4946 context, 4947 is_wallet, 4948 current_attributes_cb, 4949 current_attributes_cb_cls, 4950 current_rules_cb, 4951 current_rules_cb_cls, 4952 aml_history_cb, 4953 aml_history_cb_cls, 4954 kyc_history_cb, 4955 kyc_history_cb_cls, 4956 timeout, 4957 aprc, 4958 aprc_cls); 4959 } 4960 4961 4962 struct TALER_KYCLOGIC_AmlProgramRunnerHandle * 4963 TALER_KYCLOGIC_run_aml_program2 ( 4964 const char *prog_name, 4965 const json_t *context, 4966 bool is_wallet, 4967 TALER_KYCLOGIC_HistoryBuilderCallback current_attributes_cb, 4968 void *current_attributes_cb_cls, 4969 TALER_KYCLOGIC_HistoryBuilderCallback current_rules_cb, 4970 void *current_rules_cb_cls, 4971 TALER_KYCLOGIC_HistoryBuilderCallback aml_history_cb, 4972 void *aml_history_cb_cls, 4973 TALER_KYCLOGIC_HistoryBuilderCallback kyc_history_cb, 4974 void *kyc_history_cb_cls, 4975 struct GNUNET_TIME_Relative timeout, 4976 TALER_KYCLOGIC_AmlProgramResultCallback aprc, 4977 void *aprc_cls) 4978 { 4979 struct TALER_KYCLOGIC_AmlProgramRunnerHandle *aprh; 4980 struct TALER_KYCLOGIC_AmlProgram *prog; 4981 const json_t *jdefault_rules; 4982 json_t *current_rules; 4983 json_t *aml_history; 4984 json_t *kyc_history; 4985 json_t *attributes; 4986 4987 prog = find_program (prog_name); 4988 if (NULL == prog) 4989 { 4990 GNUNET_break (0); 4991 return NULL; 4992 } 4993 aprh = GNUNET_new (struct TALER_KYCLOGIC_AmlProgramRunnerHandle); 4994 aprh->aprc = aprc; 4995 aprh->aprc_cls = aprc_cls; 4996 aprh->program = prog; 4997 if (0 != (API_ATTRIBUTES & prog->input_mask)) 4998 { 4999 attributes = current_attributes_cb (current_attributes_cb_cls); 5000 #if DEBUG 5001 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 5002 "KYC attributes for AML program %s are:\n", 5003 prog_name); 5004 json_dumpf (attributes, 5005 stderr, 5006 JSON_INDENT (2)); 5007 fprintf (stderr, 5008 "\n"); 5009 #endif 5010 for (unsigned int i = 0; i<prog->num_required_attributes; i++) 5011 { 5012 const char *rattr = prog->required_attributes[i]; 5013 5014 if (NULL == json_object_get (attributes, 5015 rattr)) 5016 { 5017 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 5018 "KYC attributes lack required attribute `%s' for AML program %s\n", 5019 rattr, 5020 prog->program_name); 5021 #if DEBUG 5022 json_dumpf (attributes, 5023 stderr, 5024 JSON_INDENT (2)); 5025 #endif 5026 aprh->apr.status = TALER_KYCLOGIC_AMLR_FAILURE; 5027 aprh->apr.details.failure.fallback_measure 5028 = prog->fallback; 5029 aprh->apr.details.failure.error_message 5030 = rattr; 5031 aprh->apr.details.failure.ec 5032 = TALER_EC_EXCHANGE_KYC_GENERIC_PROVIDER_INCOMPLETE_REPLY; 5033 aprh->async_cb 5034 = GNUNET_SCHEDULER_add_now (&async_return_task, 5035 aprh); 5036 json_decref (attributes); 5037 return aprh; 5038 } 5039 } 5040 } 5041 else 5042 { 5043 attributes = NULL; 5044 } 5045 if (0 != (API_CONTEXT & prog->input_mask)) 5046 { 5047 for (unsigned int i = 0; i<prog->num_required_contexts; i++) 5048 { 5049 const char *rctx = prog->required_contexts[i]; 5050 5051 if (NULL == json_object_get (context, 5052 rctx)) 5053 { 5054 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 5055 "Context lacks required field `%s' for AML program %s\n", 5056 rctx, 5057 prog->program_name); 5058 #if DEBUG 5059 json_dumpf (context, 5060 stderr, 5061 JSON_INDENT (2)); 5062 #endif 5063 aprh->apr.status = TALER_KYCLOGIC_AMLR_FAILURE; 5064 aprh->apr.details.failure.fallback_measure 5065 = prog->fallback; 5066 aprh->apr.details.failure.error_message 5067 = rctx; 5068 aprh->apr.details.failure.ec 5069 = TALER_EC_EXCHANGE_KYC_GENERIC_PROVIDER_INCOMPLETE_CONTEXT; 5070 aprh->async_cb 5071 = GNUNET_SCHEDULER_add_now (&async_return_task, 5072 aprh); 5073 json_decref (attributes); 5074 return aprh; 5075 } 5076 } 5077 } 5078 else 5079 { 5080 context = NULL; 5081 } 5082 if (0 == (API_AML_HISTORY & prog->input_mask)) 5083 aml_history = NULL; 5084 else 5085 aml_history = aml_history_cb (aml_history_cb_cls); 5086 if (0 == (API_KYC_HISTORY & prog->input_mask)) 5087 kyc_history = NULL; 5088 else 5089 kyc_history = kyc_history_cb (kyc_history_cb_cls); 5090 if (0 == (API_CURRENT_RULES & prog->input_mask)) 5091 current_rules = NULL; 5092 else 5093 current_rules = current_rules_cb (current_rules_cb_cls); 5094 if (0 != (API_DEFAULT_RULES & prog->input_mask)) 5095 jdefault_rules = 5096 (is_wallet 5097 ? wallet_default_lrs 5098 : bankaccount_default_lrs); 5099 else 5100 jdefault_rules = NULL; 5101 { 5102 json_t *input; 5103 const char *extra_args[] = { 5104 "-c", 5105 cfg_filename, 5106 NULL, 5107 }; 5108 char **args; 5109 5110 input = GNUNET_JSON_PACK ( 5111 GNUNET_JSON_pack_allow_null ( 5112 GNUNET_JSON_pack_object_steal ("current_rules", 5113 current_rules)), 5114 GNUNET_JSON_pack_allow_null ( 5115 GNUNET_JSON_pack_object_incref ("default_rules", 5116 (json_t *) jdefault_rules)), 5117 GNUNET_JSON_pack_allow_null ( 5118 GNUNET_JSON_pack_object_incref ("context", 5119 (json_t *) context)), 5120 GNUNET_JSON_pack_allow_null ( 5121 GNUNET_JSON_pack_object_steal ("attributes", 5122 attributes)), 5123 GNUNET_JSON_pack_allow_null ( 5124 GNUNET_JSON_pack_array_steal ("aml_history", 5125 aml_history)), 5126 GNUNET_JSON_pack_allow_null ( 5127 GNUNET_JSON_pack_array_steal ("kyc_history", 5128 kyc_history)) 5129 ); 5130 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 5131 "Running AML program %s\n", 5132 prog->command); 5133 args = TALER_words_split (prog->command, 5134 extra_args); 5135 GNUNET_assert (NULL != args); 5136 GNUNET_assert (NULL != args[0]); 5137 #if DEBUG 5138 json_dumpf (input, 5139 stderr, 5140 JSON_INDENT (2)); 5141 #endif 5142 aprh->proc = TALER_JSON_external_conversion_start ( 5143 input, 5144 &handle_aml_output, 5145 aprh, 5146 args[0], 5147 (const char **) args); 5148 TALER_words_destroy (args); 5149 json_decref (input); 5150 } 5151 aprh->timeout = timeout; 5152 aprh->async_cb = GNUNET_SCHEDULER_add_delayed (timeout, 5153 &handle_aml_timeout, 5154 aprh); 5155 return aprh; 5156 } 5157 5158 5159 struct TALER_KYCLOGIC_AmlProgramRunnerHandle * 5160 TALER_KYCLOGIC_run_aml_program3 ( 5161 bool is_wallet, 5162 const struct TALER_KYCLOGIC_Measure *measure, 5163 TALER_KYCLOGIC_HistoryBuilderCallback current_attributes_cb, 5164 void *current_attributes_cb_cls, 5165 TALER_KYCLOGIC_HistoryBuilderCallback current_rules_cb, 5166 void *current_rules_cb_cls, 5167 TALER_KYCLOGIC_HistoryBuilderCallback aml_history_cb, 5168 void *aml_history_cb_cls, 5169 TALER_KYCLOGIC_HistoryBuilderCallback kyc_history_cb, 5170 void *kyc_history_cb_cls, 5171 struct GNUNET_TIME_Relative timeout, 5172 TALER_KYCLOGIC_AmlProgramResultCallback aprc, 5173 void *aprc_cls) 5174 { 5175 return TALER_KYCLOGIC_run_aml_program2 ( 5176 measure->prog_name, 5177 measure->context, 5178 is_wallet, 5179 current_attributes_cb, 5180 current_attributes_cb_cls, 5181 current_rules_cb, 5182 current_rules_cb_cls, 5183 aml_history_cb, 5184 aml_history_cb_cls, 5185 kyc_history_cb, 5186 kyc_history_cb_cls, 5187 timeout, 5188 aprc, 5189 aprc_cls); 5190 } 5191 5192 5193 const char * 5194 TALER_KYCLOGIC_run_aml_program_get_name ( 5195 const struct TALER_KYCLOGIC_AmlProgramRunnerHandle *aprh) 5196 { 5197 return aprh->program->program_name; 5198 } 5199 5200 5201 void 5202 TALER_KYCLOGIC_run_aml_program_cancel ( 5203 struct TALER_KYCLOGIC_AmlProgramRunnerHandle *aprh) 5204 { 5205 if (NULL != aprh->proc) 5206 { 5207 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 5208 "Killing AML program\n"); 5209 TALER_JSON_external_conversion_stop (aprh->proc); 5210 aprh->proc = NULL; 5211 } 5212 if (NULL != aprh->async_cb) 5213 { 5214 GNUNET_SCHEDULER_cancel (aprh->async_cb); 5215 aprh->async_cb = NULL; 5216 } 5217 GNUNET_free (aprh); 5218 } 5219 5220 5221 json_t * 5222 TALER_KYCLOGIC_get_hard_limits () 5223 { 5224 const struct TALER_KYCLOGIC_KycRule *rules 5225 = default_rules.kyc_rules; 5226 unsigned int num_rules 5227 = default_rules.num_kyc_rules; 5228 json_t *hard_limits; 5229 5230 hard_limits = json_array (); 5231 GNUNET_assert (NULL != hard_limits); 5232 for (unsigned int i = 0; i<num_rules; i++) 5233 { 5234 const struct TALER_KYCLOGIC_KycRule *rule = &rules[i]; 5235 json_t *hard_limit; 5236 5237 if (! rule->verboten) 5238 continue; 5239 if (! rule->exposed) 5240 continue; 5241 hard_limit = GNUNET_JSON_PACK ( 5242 GNUNET_JSON_pack_allow_null ( 5243 GNUNET_JSON_pack_string ("rule_name", 5244 rule->rule_name)), 5245 TALER_JSON_pack_kycte ("operation_type", 5246 rule->trigger), 5247 GNUNET_JSON_pack_time_rel ("timeframe", 5248 rule->timeframe), 5249 TALER_JSON_pack_amount ("threshold", 5250 &rule->threshold) 5251 ); 5252 GNUNET_assert (0 == 5253 json_array_append_new (hard_limits, 5254 hard_limit)); 5255 } 5256 return hard_limits; 5257 } 5258 5259 5260 json_t * 5261 TALER_KYCLOGIC_get_zero_limits () 5262 { 5263 const struct TALER_KYCLOGIC_KycRule *rules 5264 = default_rules.kyc_rules; 5265 unsigned int num_rules 5266 = default_rules.num_kyc_rules; 5267 json_t *zero_limits; 5268 5269 zero_limits = json_array (); 5270 GNUNET_assert (NULL != zero_limits); 5271 for (unsigned int i = 0; i<num_rules; i++) 5272 { 5273 const struct TALER_KYCLOGIC_KycRule *rule = &rules[i]; 5274 json_t *zero_limit; 5275 5276 if (! rule->exposed) 5277 continue; 5278 if (rule->verboten) 5279 continue; /* see: hard_limits */ 5280 if (! TALER_amount_is_zero (&rule->threshold)) 5281 continue; 5282 zero_limit = GNUNET_JSON_PACK ( 5283 GNUNET_JSON_pack_allow_null ( 5284 GNUNET_JSON_pack_string ("rule_name", 5285 rule->rule_name)), 5286 TALER_JSON_pack_kycte ("operation_type", 5287 rule->trigger)); 5288 GNUNET_assert (0 == 5289 json_array_append_new (zero_limits, 5290 zero_limit)); 5291 } 5292 return zero_limits; 5293 } 5294 5295 5296 json_t * 5297 TALER_KYCLOGIC_get_default_legi_rules (bool for_wallet) 5298 { 5299 const json_t *r; 5300 5301 r = (for_wallet 5302 ? wallet_default_lrs 5303 : bankaccount_default_lrs); 5304 return json_incref ((json_t *) r); 5305 } 5306 5307 5308 /* end of kyclogic_api.c */