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