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