已关闭
[TDD用例补充] #902
UUUnni创建于 8月24日关闭于 8月29日
[TDD用例补充] #902
已关闭
共 17 个文件变更+6687-1
| @@ -35,6 +35,8 @@ group("dlp_permission_build_module_test") { | |||
| 35 | ":dlp_permission_sdk_load_test", | 35 | ":dlp_permission_sdk_load_test", |
| 36 | ":dlp_transparent_enc_manager_test", | 36 | ":dlp_transparent_enc_manager_test", |
| 37 | ":dlp_transparent_enc_policy_test", | 37 | ":dlp_transparent_enc_policy_test", |
| 38 | + ":huks_adapt_manager_static_test", | ||
| 39 | + ":dlp_permission_service_ext_branch_test", | ||
| 38 | ] | 40 | ] |
| 39 | } | 41 | } |
| 40 | } | 42 | } |
| @@ -509,6 +511,207 @@ ohos_unittest("dlp_credential_static_test") { | |||
| 509 | ] | 511 | ] |
| 510 | } | 512 | } |
| 511 | 513 | ||
| 514 | +ohos_unittest("dlp_permission_service_ext_branch_test") { | ||
| 515 | + branch_protector_ret = "pac_ret" | ||
| 516 | + | ||
| 517 | + sanitize = { | ||
| 518 | + integer_overflow = true | ||
| 519 | + cfi = true | ||
| 520 | + cfi_cross_dso = true | ||
| 521 | + debug = false | ||
| 522 | + } | ||
| 523 | + | ||
| 524 | + subsystem_name = "security" | ||
| 525 | + part_name = "dlp_permission_service" | ||
| 526 | + module_out_path = part_name + "/" + part_name | ||
| 527 | + | ||
| 528 | + include_dirs = [ | ||
| 529 | + "${dlp_root_dir}/test/unittest/sa/mock", | ||
| 530 | + "${dlp_root_dir}/services/dlp_permission/sa/adapt_utils/account_adapt", | ||
| 531 | + "${dlp_root_dir}/services/dlp_permission/sa/adapt_utils/alg_adapt/alg_manager/include", | ||
| 532 | + "${dlp_root_dir}/services/dlp_permission/sa/adapt_utils/alg_adapt/huks_adapt_manager/include", | ||
| 533 | + "${dlp_root_dir}/services/dlp_permission/sa/adapt_utils/app_observer", | ||
| 534 | + "${dlp_root_dir}/services/dlp_permission/sa/adapt_utils/critical_handler", | ||
| 535 | + "${dlp_root_dir}/services/dlp_permission/sa/adapt_utils/file_manager", | ||
| 536 | + "${dlp_root_dir}/services/dlp_permission/sa/mock", | ||
| 537 | + "${dlp_root_dir}/services/dlp_permission/sa/sa_main", | ||
| 538 | + "${dlp_root_dir}/services/dlp_permission/sa/sa_common", | ||
| 539 | + "${dlp_root_dir}/services/dlp_permission/sa/storage/include", | ||
| 540 | + "${dlp_root_dir}/services/dlp_permission/sa/callback/dlp_sandbox_change_callback/", | ||
| 541 | + "${dlp_root_dir}/services/dlp_permission/sa/callback/open_dlp_file_callback/", | ||
| 542 | + "${dlp_root_dir}/frameworks/common/include", | ||
| 543 | + "${dlp_root_dir}/frameworks/dlp_permission/include", | ||
| 544 | + "${dlp_root_dir}/interfaces/inner_api/dlp_permission/include", | ||
| 545 | + "${dlp_root_dir}/interfaces/inner_api/dlp_parse/include", | ||
| 546 | + "${dlp_root_dir}/test/sa/static", | ||
| 547 | + ] | ||
| 548 | + | ||
| 549 | + sources = [ | ||
| 550 | + "unittest/sa/src/dlp_permission_service_ext_branch_test.cpp", | ||
| 551 | + "${dlp_root_dir}/test/unittest/sa/mock/dlp_os_account_mock.cpp", | ||
| 552 | + "${dlp_root_dir}/services/dlp_permission/sa/sa_main/dlp_credential.cpp", | ||
| 553 | + "${dlp_root_dir}/services/dlp_permission/sa/sa_main/dlp_permission_async_proxy.cpp", | ||
| 554 | + "${dlp_root_dir}/services/dlp_permission/sa/sa_main/dlp_permission_service.cpp", | ||
| 555 | + "${dlp_root_dir}/services/dlp_permission/sa/sa_main/dlp_permission_service_ext.cpp", | ||
| 556 | + "${dlp_root_dir}/frameworks/common/src/cert_parcel.cpp", | ||
| 557 | + "${dlp_root_dir}/frameworks/common/src/permission_policy.cpp", | ||
| 558 | + "${dlp_root_dir}/frameworks/common/src/retention_sandbox_info.cpp", | ||
| 559 | + "${dlp_root_dir}/frameworks/common/src/visited_dlp_file_info.cpp", | ||
| 560 | + "${dlp_root_dir}/frameworks/dlp_permission/src/auth_user_info_parcel.cpp", | ||
| 561 | + "${dlp_root_dir}/frameworks/dlp_permission/src/dlp_permission_info_parcel.cpp", | ||
| 562 | + "${dlp_root_dir}/frameworks/dlp_permission/src/dlp_policy_parcel.cpp", | ||
| 563 | + "${dlp_root_dir}/frameworks/dlp_permission/src/dlp_sandbox_callback_info_parcel.cpp", | ||
| 564 | + "${dlp_root_dir}/frameworks/dlp_permission/src/open_dlp_file_callback_info_parcel.cpp", | ||
| 565 | + "${dlp_root_dir}/interfaces/inner_api/dlp_permission/src/dlp_permission_public_interface.cpp", | ||
| 566 | + "${dlp_root_dir}/interfaces/inner_api/dlp_parse/src/dlp_utils.cpp", | ||
| 567 | + "${dlp_root_dir}/interfaces/inner_api/dlp_parse/src/dlp_zip.cpp", | ||
| 568 | + "${dlp_root_dir}/services/dlp_permission/sa/adapt_utils/alg_adapt/alg_manager/src/alg_manager.cpp", | ||
| 569 | + "${dlp_root_dir}/services/dlp_permission/sa/adapt_utils/alg_adapt/alg_manager/src/alg_utils.cpp", | ||
| 570 | + "${dlp_root_dir}/services/dlp_permission/sa/adapt_utils/alg_adapt/huks_adapt_manager/src/huks_adapt_manager.cpp", | ||
| 571 | + "${dlp_root_dir}/services/dlp_permission/sa/adapt_utils/account_adapt/account_adapt.cpp", | ||
| 572 | + "${dlp_root_dir}/services/dlp_permission/sa/adapt_utils/app_observer/app_state_observer.cpp", | ||
| 573 | + "${dlp_root_dir}/services/dlp_permission/sa/adapt_utils/app_observer/app_uninstall_observer.cpp", | ||
| 574 | + "${dlp_root_dir}/services/dlp_permission/sa/adapt_utils/critical_handler/critical_handler.cpp", | ||
| 575 | + "${dlp_root_dir}/services/dlp_permission/sa/adapt_utils/critical_handler/critical_helper.cpp", | ||
| 576 | + "${dlp_root_dir}/services/dlp_permission/sa/adapt_utils/file_manager/file_operator.cpp", | ||
| 577 | + "${dlp_root_dir}/services/dlp_permission/sa/adapt_utils/file_manager/retention_file_manager.cpp", | ||
| 578 | + "${dlp_root_dir}/services/dlp_permission/sa/adapt_utils/file_manager/sandbox_json_manager.cpp", | ||
| 579 | + "${dlp_root_dir}/services/dlp_permission/sa/adapt_utils/file_manager/visit_record_file_manager.cpp", | ||
| 580 | + "${dlp_root_dir}/services/dlp_permission/sa/adapt_utils/file_manager/visit_record_json_manager.cpp", | ||
| 581 | + "${dlp_root_dir}/services/dlp_permission/sa/callback/dlp_sandbox_change_callback/dlp_sandbox_change_callback_death_recipient.cpp", | ||
| 582 | + "${dlp_root_dir}/services/dlp_permission/sa/callback/dlp_sandbox_change_callback/dlp_sandbox_change_callback_manager.cpp", | ||
| 583 | + "${dlp_root_dir}/services/dlp_permission/sa/callback/dlp_sandbox_change_callback/dlp_sandbox_change_callback_proxy.cpp", | ||
| 584 | + "${dlp_root_dir}/services/dlp_permission/sa/callback/open_dlp_file_callback/open_dlp_file_callback_death_recipient.cpp", | ||
| 585 | + "${dlp_root_dir}/services/dlp_permission/sa/callback/open_dlp_file_callback/open_dlp_file_callback_manager.cpp", | ||
| 586 | + "${dlp_root_dir}/services/dlp_permission/sa/callback/open_dlp_file_callback/open_dlp_file_callback_proxy.cpp", | ||
| 587 | + "${dlp_root_dir}/services/dlp_permission/sa/mock/dlp_credential_service.c", | ||
| 588 | + "${dlp_root_dir}/services/dlp_permission/sa/mock/mock_utils.cpp", | ||
| 589 | + "${dlp_root_dir}/services/dlp_permission/sa/sa_common/access_token_adapter.cpp", | ||
| 590 | + "${dlp_root_dir}/services/dlp_permission/sa/sa_common/bundle_manager_adapter.cpp", | ||
| 591 | + "${dlp_root_dir}/services/dlp_permission/sa/sa_common/dlp_common_func.cpp", | ||
| 592 | + "${dlp_root_dir}/services/dlp_permission/sa/sa_common/dlp_feature_info.cpp", | ||
| 593 | + "${dlp_root_dir}/services/dlp_permission/sa/sa_common/permission_manager_adapter.cpp", | ||
| 594 | + "${dlp_root_dir}/services/dlp_permission/sa/sa_common/dlp_ability_adapter.cpp", | ||
| 595 | + "${dlp_root_dir}/services/dlp_permission/sa/sa_common/dlp_ability_conn.cpp", | ||
| 596 | + "${dlp_root_dir}/services/dlp_permission/sa/sa_common/dlp_ability_proxy.cpp", | ||
| 597 | + "${dlp_root_dir}/services/dlp_permission/sa/sa_common/dlp_ability_stub.cpp", | ||
| 598 | + "${dlp_root_dir}/services/dlp_permission/sa/sa_common/account_event_subscriber.cpp", | ||
| 599 | + "${dlp_root_dir}/services/dlp_permission/sa/sa_common/account_status_listener.cpp", | ||
| 600 | + "${dlp_root_dir}/services/dlp_permission/sa/storage/src/dlp_kv_data_storage.cpp", | ||
| 601 | + "${dlp_root_dir}/services/dlp_permission/sa/storage/src/sandbox_config_kv_data_storage.cpp", | ||
| 602 | + ] | ||
| 603 | + | ||
| 604 | + configs = [ | ||
| 605 | + "${dlp_root_dir}/config:coverage_flags", | ||
| 606 | + ":stub_tdd_need_skip_timer_config", | ||
| 607 | + ] | ||
| 608 | + | ||
| 609 | + cflags_cc = [ | ||
| 610 | + "-DHILOG_ENABLE", | ||
| 611 | + "-DDLP_UNIT_TEST", | ||
| 612 | + ] | ||
| 613 | + cflags = [ "-DHILOG_ENABLE" ] | ||
| 614 | + | ||
| 615 | + deps = [ | ||
| 616 | + "${dlp_permission_public_config_path}/:dlp_permission_stub", | ||
| 617 | + "${dlp_root_dir}/services/dlp_permission/sa:dlp_hex_string_static", | ||
| 618 | + "${dlp_root_dir}/services/dlp_permission/sa:dlp_permission_serializer_static", | ||
| 619 | + "${dlp_root_dir}/services/dlp_permission/sa:dlp_permission_service.rc", | ||
| 620 | + "${dlp_root_dir}/services/dlp_permission/sa/etc:param_files", | ||
| 621 | + ] | ||
| 622 | + | ||
| 623 | + external_deps = [ | ||
| 624 | + "ability_base:want", | ||
| 625 | + "ability_base:zuri", | ||
| 626 | + "ability_runtime:app_manager", | ||
| 627 | + "ability_runtime:extension_manager", | ||
| 628 | + "ability_runtime:ability_manager", | ||
| 629 | + "ability_runtime:ability_connect_callback_stub", | ||
| 630 | + "access_token:libaccesstoken_sdk", | ||
| 631 | + "access_token:libtokenid_sdk", | ||
| 632 | + "app_file_service:fileuri_native", | ||
| 633 | + "bounds_checking_function:libsec_shared", | ||
| 634 | + "bundle_framework:appexecfwk_base", | ||
| 635 | + "bundle_framework:appexecfwk_core", | ||
| 636 | + "c_utils:utils", | ||
| 637 | + "common_event_service:cesfwk_core", | ||
| 638 | + "common_event_service:cesfwk_innerkits", | ||
| 639 | + "config_policy:configpolicy_util", | ||
| 640 | + "eventhandler:libeventhandler", | ||
| 641 | + "hilog:libhilog", | ||
| 642 | + "hisysevent:libhisysevent", | ||
| 643 | + "huks:libhukssdk", | ||
| 644 | + "init:libbegetutil", | ||
| 645 | + "ipc:ipc_core", | ||
| 646 | + "json:nlohmann_json_static", | ||
| 647 | + "kv_store:distributeddata_inner", | ||
| 648 | + "memmgr:memmgrclient", | ||
| 649 | + "os_account:domain_account_innerkits", | ||
| 650 | + "os_account:libaccountkits", | ||
| 651 | + "os_account:os_account_innerkits", | ||
| 652 | + "safwk:system_ability_fwk", | ||
| 653 | + "samgr:samgr_proxy", | ||
| 654 | + "zlib:shared_libz", | ||
| 655 | + "window_manager:libwm_lite", | ||
| 656 | + "image_framework:image_native", | ||
| 657 | + "image_framework:image_source", | ||
| 658 | + "image_framework:image_source_ndk", | ||
| 659 | + "image_framework:pixelmap_ndk", | ||
| 660 | + "image_framework:pixelmap", | ||
| 661 | + "resource_management:librawfile", | ||
| 662 | + "graphic_2d:librender_service_client", | ||
| 663 | + "graphic_2d:librender_service_base", | ||
| 664 | + "napi:ace_napi", | ||
| 665 | + "ability_base:configuration", | ||
| 666 | + ] | ||
| 667 | +} | ||
| 668 | + | ||
| 669 | +ohos_unittest("huks_adapt_manager_static_test") { | ||
| 670 | + branch_protector_ret = "pac_ret" | ||
| 671 | + | ||
| 672 | + sanitize = { | ||
| 673 | + integer_overflow = true | ||
| 674 | + cfi = true | ||
| 675 | + cfi_cross_dso = true | ||
| 676 | + debug = false | ||
| 677 | + } | ||
| 678 | + | ||
| 679 | + subsystem_name = "security" | ||
| 680 | + part_name = "dlp_permission_service" | ||
| 681 | + module_out_path = part_name + "/" + part_name | ||
| 682 | + | ||
| 683 | + include_dirs = [ | ||
| 684 | + "${dlp_root_dir}/test/unittest/mock", | ||
| 685 | + "${dlp_root_dir}/frameworks/common/include", | ||
| 686 | + "${dlp_root_dir}/services/dlp_permission/sa/adapt_utils/alg_adapt/alg_manager/include", | ||
| 687 | + "${dlp_root_dir}/services/dlp_permission/sa/adapt_utils/alg_adapt/huks_adapt_manager/include", | ||
| 688 | + "${dlp_root_dir}/services/dlp_permission/sa/adapt_utils/alg_adapt/huks_adapt_manager/src", | ||
| 689 | + ] | ||
| 690 | + | ||
| 691 | + sources = [ | ||
| 692 | + "unittest/sa/static/huks_adapt_manager_static_test.cpp", | ||
| 693 | + "${dlp_root_dir}/test/unittest/mock/c_mock_common.cpp", | ||
| 694 | + "${dlp_root_dir}/test/unittest/mock/huks_mock.cpp", | ||
| 695 | + ] | ||
| 696 | + | ||
| 697 | + configs = [ | ||
| 698 | + "${dlp_root_dir}/config:coverage_flags", | ||
| 699 | + ":stub_tdd_need_skip_timer_config", | ||
| 700 | + ] | ||
| 701 | + | ||
| 702 | + cflags_cc = [ | ||
| 703 | + "-DHILOG_ENABLE", | ||
| 704 | + "-DDLP_UNIT_TEST", | ||
| 705 | + ] | ||
| 706 | + cflags = [ "-DHILOG_ENABLE" ] | ||
| 707 | + | ||
| 708 | + external_deps = [ | ||
| 709 | + "bounds_checking_function:libsec_shared", | ||
| 710 | + "hilog:libhilog", | ||
| 711 | + "huks:libhukssdk", | ||
| 712 | + ] | ||
| 713 | +} | ||
| 714 | + | ||
| 512 | ohos_unittest("dlp_permission_service_test") { | 715 | ohos_unittest("dlp_permission_service_test") { |
| 513 | branch_protector_ret = "pac_ret" | 716 | branch_protector_ret = "pac_ret" |
| 514 | 717 | ||
| @@ -1017,3 +1017,275 @@ HWTEST_F(DlpCryptTest, DlpOpensslAesEncryptAndDecrypt009, TestSize.Level0) | |||
| 1017 | ret = DlpOpensslAesDecrypt(&key, &usage, &mIn, &mEnc); | 1017 | ret = DlpOpensslAesDecrypt(&key, &usage, &mIn, &mEnc); |
| 1018 | EXPECT_EQ(DLP_PARSE_ERROR_VALUE_INVALID, ret); | 1018 | EXPECT_EQ(DLP_PARSE_ERROR_VALUE_INVALID, ret); |
| 1019 | } | 1019 | } |
| 1020 | + | ||
| 1021 | +namespace { | ||
| 1022 | +// constants for the branch cases below (aligned with dlp_crypt.cpp) | ||
| 1023 | +constexpr uint32_t KEY_SIZE_TOO_SMALL = 4; | ||
| 1024 | +constexpr uint32_t KEY_SIZE_TOO_LARGE = 1024 * 1024 + 8; | ||
| 1025 | +constexpr uint32_t HMAC_OUT_SIZE_SMALL = 31; | ||
| 1026 | +constexpr uint32_t DIGEST_ALG_SHA384 = DLP_DIGEST_SHA384; | ||
| 1027 | +constexpr uint32_t DIGEST_ALG_SHA512 = DLP_DIGEST_SHA512; | ||
| 1028 | +constexpr uint32_t DIGEST_ALG_UNKNOWN = 999; | ||
| 1029 | +constexpr uint32_t HIAE_IN_LEN = 16; | ||
| 1030 | +} | ||
| 1031 | + | ||
| 1032 | +/** | ||
| 1033 | + * @tc.name: ClearDlpHIAEMgrNullHandle001 | ||
| 1034 | + * @tc.desc: cover null handle early return branch of ClearDlpHIAEMgr | ||
| 1035 | + * @tc.type: FUNC | ||
| 1036 | + * @tc.require: | ||
| 1037 | + */ | ||
| 1038 | +HWTEST_F(DlpCryptTest, ClearDlpHIAEMgrNullHandle001, TestSize.Level0) | ||
| 1039 | +{ | ||
| 1040 | + DLP_LOG_INFO(LABEL, "ClearDlpHIAEMgrNullHandle001"); | ||
| 1041 | + // the HIAE sdk never loaded in the unit test environment: the handle is null and | ||
| 1042 | + // ClearDlpHIAEMgr returns early | ||
| 1043 | + ClearDlpHIAEMgr(); | ||
| 1044 | + // a second call keeps taking the same branch (g_hIAECnt may go negative, harmless) | ||
| 1045 | + ClearDlpHIAEMgr(); | ||
| 1046 | +} | ||
| 1047 | + | ||
| 1048 | +/** | ||
| 1049 | + * @tc.name: DlpHIAEParamCheckBranch001 | ||
| 1050 | + * @tc.desc: cover usageSpec/message/cipherText null branches of HIAEParamCheck | ||
| 1051 | + * @tc.type: FUNC | ||
| 1052 | + * @tc.require: | ||
| 1053 | + */ | ||
| 1054 | +HWTEST_F(DlpCryptTest, DlpHIAEParamCheckBranch001, TestSize.Level0) | ||
| 1055 | +{ | ||
| 1056 | + DLP_LOG_INFO(LABEL, "DlpHIAEParamCheckBranch001"); | ||
| 1057 | + struct DlpBlob key = {32, g_key}; | ||
| 1058 | + struct DlpCipherParam tagIv = {{16, g_iv}}; | ||
| 1059 | + struct DlpUsageSpec usage = {DLP_MODE_HIAE, &tagIv}; | ||
| 1060 | + | ||
| 1061 | + uint8_t input[16] = "aaaaaaaaaaaaaaa"; | ||
| 1062 | + uint8_t out[16] = {0}; | ||
| 1063 | + | ||
| 1064 | + // usageSpec == nullptr | ||
| 1065 | + ASSERT_EQ(DLP_PARSE_ERROR_VALUE_INVALID, DlpHIAEEncrypt(&key, nullptr, HIAE_IN_LEN, input, out)); | ||
| 1066 | + ASSERT_EQ(DLP_PARSE_ERROR_VALUE_INVALID, DlpHIAEDecrypt(&key, nullptr, HIAE_IN_LEN, input, out)); | ||
| 1067 | + | ||
| 1068 | + // algParam == nullptr | ||
| 1069 | + struct DlpUsageSpec usageNoParam = {DLP_MODE_HIAE, nullptr}; | ||
| 1070 | + ASSERT_EQ(DLP_PARSE_ERROR_VALUE_INVALID, DlpHIAEEncrypt(&key, &usageNoParam, HIAE_IN_LEN, input, out)); | ||
| 1071 | + ASSERT_EQ(DLP_PARSE_ERROR_VALUE_INVALID, DlpHIAEDecrypt(&key, &usageNoParam, HIAE_IN_LEN, input, out)); | ||
| 1072 | + | ||
| 1073 | + // message == nullptr | ||
| 1074 | + ASSERT_EQ(DLP_PARSE_ERROR_VALUE_INVALID, DlpHIAEEncrypt(&key, &usage, HIAE_IN_LEN, nullptr, out)); | ||
| 1075 | + ASSERT_EQ(DLP_PARSE_ERROR_VALUE_INVALID, DlpHIAEDecrypt(&key, &usage, HIAE_IN_LEN, nullptr, out)); | ||
| 1076 | + | ||
| 1077 | + // cipherText/plainText == nullptr | ||
| 1078 | + ASSERT_EQ(DLP_PARSE_ERROR_VALUE_INVALID, DlpHIAEEncrypt(&key, &usage, HIAE_IN_LEN, input, nullptr)); | ||
| 1079 | + ASSERT_EQ(DLP_PARSE_ERROR_VALUE_INVALID, DlpHIAEDecrypt(&key, &usage, HIAE_IN_LEN, input, nullptr)); | ||
| 1080 | + | ||
| 1081 | + // key data == nullptr | ||
| 1082 | + struct DlpBlob nullKey = {32, nullptr}; | ||
| 1083 | + ASSERT_EQ(DLP_PARSE_ERROR_VALUE_INVALID, DlpHIAEEncrypt(&nullKey, &usage, HIAE_IN_LEN, input, out)); | ||
| 1084 | + ASSERT_EQ(DLP_PARSE_ERROR_VALUE_INVALID, DlpHIAEDecrypt(&nullKey, &usage, HIAE_IN_LEN, input, out)); | ||
| 1085 | +} | ||
| 1086 | + | ||
| 1087 | +/** | ||
| 1088 | + * @tc.name: DlpHIAEHandleNull001 | ||
| 1089 | + * @tc.desc: cover AlgHIAE init/clear/update bodies with null handle | ||
| 1090 | + * @tc.type: FUNC | ||
| 1091 | + * @tc.require: | ||
| 1092 | + */ | ||
| 1093 | +HWTEST_F(DlpCryptTest, DlpHIAEHandleNull001, TestSize.Level0) | ||
| 1094 | +{ | ||
| 1095 | + DLP_LOG_INFO(LABEL, "DlpHIAEHandleNull001"); | ||
| 1096 | + struct DlpBlob key = {32, g_key}; | ||
| 1097 | + struct DlpCipherParam tagIv = {{16, g_iv}}; | ||
| 1098 | + struct DlpUsageSpec usage = {DLP_MODE_HIAE, &tagIv}; | ||
| 1099 | + | ||
| 1100 | + uint8_t input[16] = "aaaaaaaaaaaaaaa"; | ||
| 1101 | + uint8_t out[16] = {0}; | ||
| 1102 | + | ||
| 1103 | + // all params are valid: HIAEParamCheck passes, AlgHIAEInit/Update/Clear run with the | ||
| 1104 | + // null handle (HIAE sdk not loaded) and VALUE_INVALID is returned | ||
| 1105 | + ASSERT_EQ(DLP_PARSE_ERROR_VALUE_INVALID, DlpHIAEEncrypt(&key, &usage, HIAE_IN_LEN, input, out)); | ||
| 1106 | + ASSERT_EQ(DLP_PARSE_ERROR_VALUE_INVALID, DlpHIAEDecrypt(&key, &usage, HIAE_IN_LEN, input, out)); | ||
| 1107 | +} | ||
| 1108 | + | ||
| 1109 | +/** | ||
| 1110 | + * @tc.name: DlpOpensslGenerateRandomBranch001 | ||
| 1111 | + * @tc.desc: cover key nullptr and key size invalid branches of DlpOpensslGenerateRandom | ||
| 1112 | + * @tc.type: FUNC | ||
| 1113 | + * @tc.require: | ||
| 1114 | + */ | ||
| 1115 | +HWTEST_F(DlpCryptTest, DlpOpensslGenerateRandomBranch001, TestSize.Level0) | ||
| 1116 | +{ | ||
| 1117 | + DLP_LOG_INFO(LABEL, "DlpOpensslGenerateRandomBranch001"); | ||
| 1118 | + struct DlpBlob key = {16, g_key}; | ||
| 1119 | + | ||
| 1120 | + // key == nullptr | ||
| 1121 | + ASSERT_EQ(DLP_PARSE_ERROR_VALUE_INVALID, DlpOpensslGenerateRandom(64, nullptr)); | ||
| 1122 | + // keySize < BIT_NUM_OF_UINT8 | ||
| 1123 | + ASSERT_EQ(DLP_PARSE_ERROR_VALUE_INVALID, DlpOpensslGenerateRandom(KEY_SIZE_TOO_SMALL, &key)); | ||
| 1124 | + // keySize > DLP_RANDOM_MAX_SIZE | ||
| 1125 | + ASSERT_EQ(DLP_PARSE_ERROR_VALUE_INVALID, DlpOpensslGenerateRandom(KEY_SIZE_TOO_LARGE, &key)); | ||
| 1126 | +} | ||
| 1127 | + | ||
| 1128 | +/** | ||
| 1129 | + * @tc.name: GetOpensslAlgBranch001 | ||
| 1130 | + * @tc.desc: cover SHA384/SHA512/unknown alg branches of GetOpensslAlg | ||
| 1131 | + * @tc.type: FUNC | ||
| 1132 | + * @tc.require: | ||
| 1133 | + */ | ||
| 1134 | +HWTEST_F(DlpCryptTest, GetOpensslAlgBranch001, TestSize.Level0) | ||
| 1135 | +{ | ||
| 1136 | + DLP_LOG_INFO(LABEL, "GetOpensslAlgBranch001"); | ||
| 1137 | + // SHA384 and SHA512 branches return the matching digest | ||
| 1138 | + ASSERT_NE(nullptr, GetOpensslAlg(DIGEST_ALG_SHA384)); | ||
| 1139 | + ASSERT_NE(nullptr, GetOpensslAlg(DIGEST_ALG_SHA512)); | ||
| 1140 | + // unknown alg returns nullptr | ||
| 1141 | + ASSERT_EQ(nullptr, GetOpensslAlg(DIGEST_ALG_UNKNOWN)); | ||
| 1142 | +} | ||
| 1143 | + | ||
| 1144 | +/** | ||
| 1145 | + * @tc.name: DlpHmacEncodeForRawParam001 | ||
| 1146 | + * @tc.desc: cover key and out invalid branches of DlpHmacEncodeForRaw and DlpHmacEncode | ||
| 1147 | + * @tc.type: FUNC | ||
| 1148 | + * @tc.require: | ||
| 1149 | + */ | ||
| 1150 | +HWTEST_F(DlpCryptTest, DlpHmacEncodeForRawParam001, TestSize.Level0) | ||
| 1151 | +{ | ||
| 1152 | + DLP_LOG_INFO(LABEL, "DlpHmacEncodeForRawParam001"); | ||
| 1153 | + int fd = open("/data/fuse_test.txt", O_RDWR | O_CREAT | O_TRUNC, S_IRWXU); | ||
| 1154 | + ASSERT_NE(fd, -1); | ||
| 1155 | + uint8_t buffer[SIXTEEN] = {0}; | ||
| 1156 | + write(fd, buffer, SIXTEEN); | ||
| 1157 | + lseek(fd, 0, SEEK_SET); | ||
| 1158 | + | ||
| 1159 | + uint8_t* hmacKeyData = new (std::nothrow) uint8_t[HMAC_SIZE]; | ||
| 1160 | + ASSERT_NE(hmacKeyData, nullptr); | ||
| 1161 | + struct DlpBlob key = {.size = HMAC_SIZE, .data = hmacKeyData}; | ||
| 1162 | + uint8_t* outBuf = new (std::nothrow) uint8_t[HMAC_SIZE]; | ||
| 1163 | + ASSERT_NE(outBuf, nullptr); | ||
| 1164 | + struct DlpBlob out = {.size = HMAC_SIZE, .data = outBuf}; | ||
| 1165 | + | ||
| 1166 | + // key.data == nullptr: DlpHmacEncodeForRaw | ||
| 1167 | + struct DlpBlob nullKey = {.size = HMAC_SIZE, .data = nullptr}; | ||
| 1168 | + ASSERT_EQ(DLP_PARSE_ERROR_DIGEST_INVALID, DlpHmacEncodeForRaw(nullKey, fd, SIXTEEN, out)); | ||
| 1169 | + // key.size != SHA256_KEY_LEN | ||
| 1170 | + struct DlpBlob shortKey = {.size = SIXTEEN, .data = hmacKeyData}; | ||
| 1171 | + ASSERT_EQ(DLP_PARSE_ERROR_DIGEST_INVALID, DlpHmacEncodeForRaw(shortKey, fd, SIXTEEN, out)); | ||
| 1172 | + // out.data == nullptr | ||
| 1173 | + struct DlpBlob nullOut = {.size = HMAC_SIZE, .data = nullptr}; | ||
| 1174 | + ASSERT_EQ(DLP_PARSE_ERROR_DIGEST_INVALID, DlpHmacEncodeForRaw(key, fd, SIXTEEN, nullOut)); | ||
| 1175 | + // out.size < HMAC_SIZE | ||
| 1176 | + struct DlpBlob smallOut = {.size = HMAC_OUT_SIZE_SMALL, .data = outBuf}; | ||
| 1177 | + ASSERT_EQ(DLP_PARSE_ERROR_DIGEST_INVALID, DlpHmacEncodeForRaw(key, fd, SIXTEEN, smallOut)); | ||
| 1178 | + | ||
| 1179 | + // same param checks for DlpHmacEncode | ||
| 1180 | + lseek(fd, 0, SEEK_SET); | ||
| 1181 | + ASSERT_EQ(DLP_PARSE_ERROR_DIGEST_INVALID, DlpHmacEncode(nullKey, fd, out)); | ||
| 1182 | + ASSERT_EQ(DLP_PARSE_ERROR_DIGEST_INVALID, DlpHmacEncode(shortKey, fd, out)); | ||
| 1183 | + lseek(fd, 0, SEEK_SET); | ||
| 1184 | + ASSERT_EQ(DLP_PARSE_ERROR_DIGEST_INVALID, DlpHmacEncode(key, fd, nullOut)); | ||
| 1185 | + ASSERT_EQ(DLP_PARSE_ERROR_DIGEST_INVALID, DlpHmacEncode(key, fd, smallOut)); | ||
| 1186 | + | ||
| 1187 | + delete[] hmacKeyData; | ||
| 1188 | + delete[] outBuf; | ||
| 1189 | + close(fd); | ||
| 1190 | + unlink("/data/fuse_test.txt"); | ||
| 1191 | +} | ||
| 1192 | + | ||
| 1193 | +/** | ||
| 1194 | + * @tc.name: DlpHmacEncodeForRawHmacFail001 | ||
| 1195 | + * @tc.desc: cover HMAC_Init_ex and HMAC_Final fail branches of DlpHmacEncodeForRaw | ||
| 1196 | + * @tc.type: FUNC | ||
| 1197 | + * @tc.require: | ||
| 1198 | + */ | ||
| 1199 | +HWTEST_F(DlpCryptTest, DlpHmacEncodeForRawHmacFail001, TestSize.Level0) | ||
| 1200 | +{ | ||
| 1201 | + DLP_LOG_INFO(LABEL, "DlpHmacEncodeForRawHmacFail001"); | ||
| 1202 | + int fd = open("/data/fuse_test.txt", O_RDWR | O_CREAT | O_TRUNC, S_IRWXU); | ||
| 1203 | + ASSERT_NE(fd, -1); | ||
| 1204 | + uint8_t buffer[SIXTEEN] = {0}; | ||
| 1205 | + write(fd, buffer, SIXTEEN); | ||
| 1206 | + lseek(fd, 0, SEEK_SET); | ||
| 1207 | + | ||
| 1208 | + uint8_t* hmacKeyData = new (std::nothrow) uint8_t[HMAC_SIZE]; | ||
| 1209 | + ASSERT_NE(hmacKeyData, nullptr); | ||
| 1210 | + struct DlpBlob key = {.size = HMAC_SIZE, .data = hmacKeyData}; | ||
| 1211 | + uint8_t* outBuf = new (std::nothrow) uint8_t[HMAC_SIZE]; | ||
| 1212 | + ASSERT_NE(outBuf, nullptr); | ||
| 1213 | + struct DlpBlob out = {.size = HMAC_SIZE, .data = outBuf}; | ||
| 1214 | + | ||
| 1215 | + // HMAC_Init_ex fails (mocked) | ||
| 1216 | + DlpCMockCondition condition; | ||
| 1217 | + condition.mockSequence = { true }; | ||
| 1218 | + SetMockConditions("HMAC_Init_ex", condition); | ||
| 1219 | + ASSERT_EQ(DLP_PARSE_ERROR_CRYPTO_ENGINE_ERROR, DlpHmacEncodeForRaw(key, fd, SIXTEEN, out)); | ||
| 1220 | + CleanMockConditions(); | ||
| 1221 | + | ||
| 1222 | + // HMAC_Update fails (mocked): the read loop reports the engine error | ||
| 1223 | + lseek(fd, 0, SEEK_SET); | ||
| 1224 | + condition.mockSequence = { false, true }; | ||
| 1225 | + SetMockConditions("HMAC_Init_ex", condition); | ||
| 1226 | + DlpCMockCondition updateCondition; | ||
| 1227 | + updateCondition.mockSequence = { true }; | ||
| 1228 | + SetMockConditions("HMAC_Update", updateCondition); | ||
| 1229 | + ASSERT_EQ(DLP_PARSE_ERROR_CRYPTO_ENGINE_ERROR, DlpHmacEncodeForRaw(key, fd, SIXTEEN, out)); | ||
| 1230 | + CleanMockConditions(); | ||
| 1231 | + | ||
| 1232 | + // HMAC_Final fails (mocked): fileSize 0 skips the loop and the final step fails | ||
| 1233 | + lseek(fd, 0, SEEK_SET); | ||
| 1234 | + condition.mockSequence = { false }; | ||
| 1235 | + SetMockConditions("HMAC_Init_ex", condition); | ||
| 1236 | + DlpCMockCondition finalCondition; | ||
| 1237 | + finalCondition.mockSequence = { true }; | ||
| 1238 | + SetMockConditions("HMAC_Final", finalCondition); | ||
| 1239 | + ASSERT_EQ(DLP_PARSE_ERROR_CRYPTO_ENGINE_ERROR, DlpHmacEncodeForRaw(key, fd, 0, out)); | ||
| 1240 | + CleanMockConditions(); | ||
| 1241 | + | ||
| 1242 | + delete[] hmacKeyData; | ||
| 1243 | + delete[] outBuf; | ||
| 1244 | + close(fd); | ||
| 1245 | + unlink("/data/fuse_test.txt"); | ||
| 1246 | +} | ||
| 1247 | + | ||
| 1248 | +/** | ||
| 1249 | + * @tc.name: DlpHmacEncodeHmacFail001 | ||
| 1250 | + * @tc.desc: cover HMAC_Init_ex and HMAC_Final fail branches of DlpHmacEncode | ||
| 1251 | + * @tc.type: FUNC | ||
| 1252 | + * @tc.require: | ||
| 1253 | + */ | ||
| 1254 | +HWTEST_F(DlpCryptTest, DlpHmacEncodeHmacFail001, TestSize.Level0) | ||
| 1255 | +{ | ||
| 1256 | + DLP_LOG_INFO(LABEL, "DlpHmacEncodeHmacFail001"); | ||
| 1257 | + int fd = open("/data/fuse_test.txt", O_RDWR | O_CREAT | O_TRUNC, S_IRWXU); | ||
| 1258 | + ASSERT_NE(fd, -1); | ||
| 1259 | + uint8_t buffer[SIXTEEN] = {0}; | ||
| 1260 | + write(fd, buffer, SIXTEEN); | ||
| 1261 | + lseek(fd, 0, SEEK_SET); | ||
| 1262 | + | ||
| 1263 | + uint8_t* hmacKeyData = new (std::nothrow) uint8_t[HMAC_SIZE]; | ||
| 1264 | + ASSERT_NE(hmacKeyData, nullptr); | ||
| 1265 | + struct DlpBlob key = {.size = HMAC_SIZE, .data = hmacKeyData}; | ||
| 1266 | + uint8_t* outBuf = new (std::nothrow) uint8_t[HMAC_SIZE]; | ||
| 1267 | + ASSERT_NE(outBuf, nullptr); | ||
| 1268 | + struct DlpBlob out = {.size = HMAC_SIZE, .data = outBuf}; | ||
| 1269 | + | ||
| 1270 | + // HMAC_Init_ex fails (mocked) | ||
| 1271 | + DlpCMockCondition condition; | ||
| 1272 | + condition.mockSequence = { true }; | ||
| 1273 | + SetMockConditions("HMAC_Init_ex", condition); | ||
| 1274 | + ASSERT_EQ(DLP_PARSE_ERROR_CRYPTO_ENGINE_ERROR, DlpHmacEncode(key, fd, out)); | ||
| 1275 | + CleanMockConditions(); | ||
| 1276 | + | ||
| 1277 | + // HMAC_Final fails (mocked): the read loop consumes the file and the final step fails | ||
| 1278 | + lseek(fd, 0, SEEK_SET); | ||
| 1279 | + condition.mockSequence = { false }; | ||
| 1280 | + SetMockConditions("HMAC_Init_ex", condition); | ||
| 1281 | + DlpCMockCondition finalCondition; | ||
| 1282 | + finalCondition.mockSequence = { true }; | ||
| 1283 | + SetMockConditions("HMAC_Final", finalCondition); | ||
| 1284 | + ASSERT_EQ(DLP_PARSE_ERROR_CRYPTO_ENGINE_ERROR, DlpHmacEncode(key, fd, out)); | ||
| 1285 | + CleanMockConditions(); | ||
| 1286 | + | ||
| 1287 | + delete[] hmacKeyData; | ||
| 1288 | + delete[] outBuf; | ||
| 1289 | + close(fd); | ||
| 1290 | + unlink("/data/fuse_test.txt"); | ||
| 1291 | +} | ||
| @@ -1003,6 +1003,394 @@ HWTEST_F(DlpFileKitsTest, ConvertAbilityInfoWithSupportDlp012, TestSize.Level0) | |||
| 1003 | // No customFlag parameter set, should go through normal flow | 1003 | // No customFlag parameter set, should go through normal flow |
| 1004 | std::vector<OHOS::AppExecFwk::AbilityInfo> abilityInfos; | 1004 | std::vector<OHOS::AppExecFwk::AbilityInfo> abilityInfos; |
| 1005 | DlpFileKits::ConvertAbilityInfoWithSupportDlp(want, abilityInfos); | 1005 | DlpFileKits::ConvertAbilityInfoWithSupportDlp(want, abilityInfos); |
| 1006 | - | 1006 | + |
| 1007 | EXPECT_EQ(abilityInfos.size(), 0); | 1007 | EXPECT_EQ(abilityInfos.size(), 0); |
| 1008 | +} | ||
| 1009 | + | ||
| 1010 | +namespace { | ||
| 1011 | +// constants for the branch cases below (aligned with dlp_file_kits.cpp) | ||
| 1012 | +static const std::string SHORT_NAME_URI = "file://data/test/a.b"; | ||
| 1013 | +static const std::string INVALID_CONTENT_DLP_URI = "file://data/test/invalid.txt.dlp"; | ||
| 1014 | +static const std::string INVALID_CONTENT_FILE = "/data/test/invalid.txt.dlp"; | ||
| 1015 | +static const std::string RAW_DLP_FILE = "/data/test/rawtest.docx.dlp"; | ||
| 1016 | +static const std::string RAW_DLP_URI = "file://data/test/rawtest.docx.dlp"; | ||
| 1017 | +static const std::string RAW_UNKNOWN_TYPE_DLP_FILE = "/data/test/rawunknown.xyz.dlp"; | ||
| 1018 | +static const std::string RAW_UNKNOWN_TYPE_DLP_URI = "file://data/test/rawunknown.xyz.dlp"; | ||
| 1019 | +static const uint32_t RAW_HMAC_HEX_SIZE = 64; | ||
| 1020 | +static const uint32_t RAW_FILE_HEAD = 8; | ||
| 1021 | +static constexpr int32_t INVALID_VERSION = 2; | ||
| 1022 | +static constexpr int32_t ENTERPRISE_HEAD_SIZE = sizeof(struct DlpHeader) + RAW_FILE_HEAD; | ||
| 1023 | +static constexpr int32_t FILE_TYPE_TXT = 1; | ||
| 1024 | +static constexpr int32_t FILE_TYPE_UNKNOWN = 999; | ||
| 1025 | +static constexpr int32_t FILE_TYPE_COUNTDOWN_OFFSET = 10000; | ||
| 1026 | +static constexpr int32_t OPEN_COUNT_FLAG_ON = 1; | ||
| 1027 | +static constexpr int32_t WATERMARK_FLAG_ON = 1; | ||
| 1028 | +static constexpr int32_t TAIL_BUF_SIZE = 110; | ||
| 1029 | + | ||
| 1030 | +// write a minimal valid raw dlp header (contactAccountSize 1, certOffset == txtOffset) | ||
| 1031 | +static void WriteRawDlpHeader(int32_t fd, uint32_t fileType) | ||
| 1032 | +{ | ||
| 1033 | + struct DlpHeader header = { | ||
| 1034 | + .magic = DLP_FILE_MAGIC, | ||
| 1035 | + .fileType = fileType, | ||
| 1036 | + .offlineAccess = 0, | ||
| 1037 | + .algType = DLP_MODE_CTR, | ||
| 1038 | + .txtOffset = sizeof(struct DlpHeader) + RAW_FILE_HEAD + 1, | ||
| 1039 | + .txtSize = 0, | ||
| 1040 | + .hmacOffset = sizeof(struct DlpHeader) + RAW_FILE_HEAD + 1, | ||
| 1041 | + .hmacSize = RAW_HMAC_HEX_SIZE, | ||
| 1042 | + .certOffset = sizeof(struct DlpHeader) + RAW_FILE_HEAD + 1, | ||
| 1043 | + .certSize = 16, | ||
| 1044 | + .contactAccountOffset = sizeof(struct DlpHeader) + RAW_FILE_HEAD, | ||
| 1045 | + .contactAccountSize = 1, | ||
| 1046 | + .offlineCertOffset = 0, | ||
| 1047 | + .offlineCertSize = 0 | ||
| 1048 | + }; | ||
| 1049 | + uint32_t version = CURRENT_VERSION; | ||
| 1050 | + uint32_t dlpHeaderSize = sizeof(struct DlpHeader); | ||
| 1051 | + write(fd, &version, sizeof(uint32_t)); | ||
| 1052 | + write(fd, &dlpHeaderSize, sizeof(uint32_t)); | ||
| 1053 | + write(fd, &header, sizeof(struct DlpHeader)); | ||
| 1054 | + // trailing bytes so the header checks pass: contact account + hmac + cert + file id tail | ||
| 1055 | + uint8_t body[16] = {0}; | ||
| 1056 | + write(fd, body, sizeof(body)); | ||
| 1057 | + write(fd, body, RAW_HMAC_HEX_SIZE); | ||
| 1058 | + write(fd, body, 16); | ||
| 1059 | + uint8_t tail[TAIL_BUF_SIZE] = {0}; | ||
| 1060 | + write(fd, tail, sizeof(tail)); | ||
| 1061 | +} | ||
| 1062 | + | ||
| 1063 | +// generate a real raw dlp file through the manager so IsDlpFile recognizes it | ||
| 1064 | +static int32_t CreateRawDlpFile(const std::string& path) | ||
| 1065 | +{ | ||
| 1066 | + int32_t plainFd = open(PLAIN_FILE_NAME.c_str(), O_CREAT | O_RDWR | O_TRUNC, DLP_FILE_PERMISSION); | ||
| 1067 | + if (plainFd < 0) { | ||
| 1068 | + return -1; | ||
| 1069 | + } | ||
| 1070 | + char buffer[] = "123456"; | ||
| 1071 | + write(plainFd, buffer, sizeof(buffer)); | ||
| 1072 | + int32_t dlpFd = open(path.c_str(), O_CREAT | O_RDWR | O_TRUNC, DLP_FILE_PERMISSION); | ||
| 1073 | + if (dlpFd < 0) { | ||
| 1074 | + close(plainFd); | ||
| 1075 | + return -1; | ||
| 1076 | + } | ||
| 1077 | + DlpProperty prop; | ||
| 1078 | + prop.ownerAccount = "ohosAnonymousName"; | ||
| 1079 | + prop.ownerAccountId = "ohosAnonymousName"; | ||
| 1080 | + prop.ownerAccountType = CLOUD_ACCOUNT; | ||
| 1081 | + prop.contactAccount = "test@test.com"; | ||
| 1082 | + std::shared_ptr<DlpFile> filePtr; | ||
| 1083 | + int ret = DlpFileManager::GetInstance().GenerateDlpFile(plainFd, dlpFd, prop, filePtr, DLP_TEST_DIR); | ||
| 1084 | + close(plainFd); | ||
| 1085 | + if (ret != DLP_OK) { | ||
| 1086 | + close(dlpFd); | ||
| 1087 | + return -1; | ||
| 1088 | + } | ||
| 1089 | + DlpFileManager::GetInstance().CloseDlpFile(filePtr); | ||
| 1090 | + return dlpFd; | ||
| 1091 | +} | ||
| 1092 | +} | ||
| 1093 | + | ||
| 1094 | +/** | ||
| 1095 | + * @tc.name: GetSandboxFlagShortName001 | ||
| 1096 | + * @tc.desc: cover fileNameLen < dlpSuffixLen branch of IsDlpFileName | ||
| 1097 | + * @tc.type: FUNC | ||
| 1098 | + */ | ||
| 1099 | +HWTEST_F(DlpFileKitsTest, GetSandboxFlagShortName001, TestSize.Level0) | ||
| 1100 | +{ | ||
| 1101 | + DLP_LOG_INFO(LABEL, "GetSandboxFlagShortName001"); | ||
| 1102 | + OHOS::AAFwk::Want want; | ||
| 1103 | + want.SetAction(TAG_ACTION_VIEW); | ||
| 1104 | + // the file name part is shorter than ".dlp": IsDlpFileName returns false | ||
| 1105 | + want.SetUri(SHORT_NAME_URI); | ||
| 1106 | + ASSERT_FALSE(DlpFileKits::GetSandboxFlag(want)); | ||
| 1107 | +} | ||
| 1108 | + | ||
| 1109 | +/** | ||
| 1110 | + * @tc.name: IsDlpFileInvalidHeader001 | ||
| 1111 | + * @tc.desc: cover IsValidDlpHeader fail branch of IsDlpFile | ||
| 1112 | + * @tc.type: FUNC | ||
| 1113 | + */ | ||
| 1114 | +HWTEST_F(DlpFileKitsTest, IsDlpFileInvalidHeader001, TestSize.Level0) | ||
| 1115 | +{ | ||
| 1116 | + DLP_LOG_INFO(LABEL, "IsDlpFileInvalidHeader001"); | ||
| 1117 | + int32_t fd = open(INVALID_CONTENT_FILE.c_str(), O_CREAT | O_RDWR | O_TRUNC, DLP_FILE_PERMISSION); | ||
| 1118 | + ASSERT_GE(fd, 0); | ||
| 1119 | + | ||
| 1120 | + // valid version and header size, but the header fields are inconsistent | ||
| 1121 | + uint32_t version = CURRENT_VERSION; | ||
| 1122 | + uint32_t dlpHeaderSize = sizeof(struct DlpHeader); | ||
| 1123 | + write(fd, &version, sizeof(uint32_t)); | ||
| 1124 | + write(fd, &dlpHeaderSize, sizeof(uint32_t)); | ||
| 1125 | + struct DlpHeader header = {}; | ||
| 1126 | + header.magic = DLP_FILE_MAGIC; | ||
| 1127 | + header.certSize = 16; | ||
| 1128 | + header.contactAccountSize = 1; | ||
| 1129 | + // all offsets are wrong so IsValidDlpHeader fails | ||
| 1130 | + header.contactAccountOffset = 1; | ||
| 1131 | + header.txtOffset = 2; | ||
| 1132 | + header.hmacOffset = 3; | ||
| 1133 | + header.certOffset = 4; | ||
| 1134 | + header.hmacSize = RAW_HMAC_HEX_SIZE; | ||
| 1135 | + write(fd, &header, sizeof(struct DlpHeader)); | ||
| 1136 | + uint8_t body[32] = {0}; | ||
| 1137 | + write(fd, body, sizeof(body)); | ||
| 1138 | + lseek(fd, 0, SEEK_SET); | ||
| 1139 | + | ||
| 1140 | + // IsValidDlpHeader returns false: IsDlpFile reports not a dlp file | ||
| 1141 | + ASSERT_FALSE(DlpFileKits::IsDlpFile(fd)); | ||
| 1142 | + close(fd); | ||
| 1143 | + unlink(INVALID_CONTENT_FILE.c_str()); | ||
| 1144 | +} | ||
| 1145 | + | ||
| 1146 | +/** | ||
| 1147 | + * @tc.name: IsDlpFileInvalidVersion001 | ||
| 1148 | + * @tc.desc: cover version or dlpHeaderSize invalid branch of IsDlpFile | ||
| 1149 | + * @tc.type: FUNC | ||
| 1150 | + */ | ||
| 1151 | +HWTEST_F(DlpFileKitsTest, IsDlpFileInvalidVersion001, TestSize.Level0) | ||
| 1152 | +{ | ||
| 1153 | + DLP_LOG_INFO(LABEL, "IsDlpFileInvalidVersion001"); | ||
| 1154 | + int32_t fd = open(INVALID_CONTENT_FILE.c_str(), O_CREAT | O_RDWR | O_TRUNC, DLP_FILE_PERMISSION); | ||
| 1155 | + ASSERT_GE(fd, 0); | ||
| 1156 | + | ||
| 1157 | + // version is not CURRENT_VERSION: the read loop breaks with checkFlag false | ||
| 1158 | + uint32_t version = INVALID_VERSION; | ||
| 1159 | + uint32_t dlpHeaderSize = sizeof(struct DlpHeader); | ||
| 1160 | + write(fd, &version, sizeof(uint32_t)); | ||
| 1161 | + write(fd, &dlpHeaderSize, sizeof(uint32_t)); | ||
| 1162 | + uint8_t body[32] = {0}; | ||
| 1163 | + write(fd, body, sizeof(body)); | ||
| 1164 | + lseek(fd, 0, SEEK_SET); | ||
| 1165 | + ASSERT_FALSE(DlpFileKits::IsDlpFile(fd)); | ||
| 1166 | + | ||
| 1167 | + // dlpHeaderSize is larger than sizeof(DlpHeader) but exceeds ENTERPRISE_HEAD_MAX | ||
| 1168 | + lseek(fd, 0, SEEK_SET); | ||
| 1169 | + ftruncate(fd, 0); | ||
| 1170 | + lseek(fd, 0, SEEK_SET); | ||
| 1171 | + version = CURRENT_VERSION; | ||
| 1172 | + dlpHeaderSize = ENTERPRISE_HEAD_MAX + 1; | ||
| 1173 | + write(fd, &version, sizeof(uint32_t)); | ||
| 1174 | + write(fd, &dlpHeaderSize, sizeof(uint32_t)); | ||
| 1175 | + write(fd, body, sizeof(body)); | ||
| 1176 | + lseek(fd, 0, SEEK_SET); | ||
| 1177 | + ASSERT_FALSE(DlpFileKits::IsDlpFile(fd)); | ||
| 1178 | + | ||
| 1179 | + close(fd); | ||
| 1180 | + unlink(INVALID_CONTENT_FILE.c_str()); | ||
| 1181 | +} | ||
| 1182 | + | ||
| 1183 | +/** | ||
| 1184 | + * @tc.name: IsDlpFileEnterpriseInvalidHeader001 | ||
| 1185 | + * @tc.desc: cover IsValidEnterpriseDlpHeader fail branch of IsDlpFile | ||
| 1186 | + * @tc.type: FUNC | ||
| 1187 | + */ | ||
| 1188 | +HWTEST_F(DlpFileKitsTest, IsDlpFileEnterpriseInvalidHeader001, TestSize.Level0) | ||
| 1189 | +{ | ||
| 1190 | + DLP_LOG_INFO(LABEL, "IsDlpFileEnterpriseInvalidHeader001"); | ||
| 1191 | + int32_t fd = open(INVALID_CONTENT_FILE.c_str(), O_CREAT | O_RDWR | O_TRUNC, DLP_FILE_PERMISSION); | ||
| 1192 | + ASSERT_GE(fd, 0); | ||
| 1193 | + | ||
| 1194 | + // enterprise header size with inconsistent fields: IsValidEnterpriseDlpHeader fails | ||
| 1195 | + uint32_t version = CURRENT_VERSION; | ||
| 1196 | + uint32_t dlpHeaderSize = sizeof(struct DlpHeader) + RAW_FILE_HEAD; | ||
| 1197 | + write(fd, &version, sizeof(uint32_t)); | ||
| 1198 | + write(fd, &dlpHeaderSize, sizeof(uint32_t)); | ||
| 1199 | + struct DlpHeader header = {}; | ||
| 1200 | + header.magic = DLP_FILE_MAGIC; | ||
| 1201 | + header.certSize = 16; | ||
| 1202 | + header.contactAccountSize = 0; | ||
| 1203 | + // the offsets do not match the enterprise layout rules | ||
| 1204 | + header.contactAccountOffset = 1; | ||
| 1205 | + header.txtOffset = 2; | ||
| 1206 | + header.hmacOffset = 3; | ||
| 1207 | + header.certOffset = 4; | ||
| 1208 | + header.hmacSize = RAW_HMAC_HEX_SIZE; | ||
| 1209 | + write(fd, &header, sizeof(struct DlpHeader)); | ||
| 1210 | + uint8_t body[32] = {0}; | ||
| 1211 | + write(fd, body, sizeof(body)); | ||
| 1212 | + lseek(fd, 0, SEEK_SET); | ||
| 1213 | + ASSERT_FALSE(DlpFileKits::IsDlpFile(fd)); | ||
| 1214 | + | ||
| 1215 | + close(fd); | ||
| 1216 | + unlink(INVALID_CONTENT_FILE.c_str()); | ||
| 1217 | +} | ||
| 1218 | + | ||
| 1219 | +/** | ||
| 1220 | + * @tc.name: GetSandboxFlagNotDlpContent001 | ||
| 1221 | + * @tc.desc: cover IsDlpFile false and QueryDockerPolicyNeedSandbox branch of GetSandboxFlag | ||
| 1222 | + * @tc.type: FUNC | ||
| 1223 | + */ | ||
| 1224 | +HWTEST_F(DlpFileKitsTest, GetSandboxFlagNotDlpContent001, TestSize.Level0) | ||
| 1225 | +{ | ||
| 1226 | + DLP_LOG_INFO(LABEL, "GetSandboxFlagNotDlpContent001"); | ||
| 1227 | + // a file with the .dlp suffix but plain content: IsDlpFile fails, docker policy returns false | ||
| 1228 | + int32_t fd = open(INVALID_CONTENT_FILE.c_str(), O_CREAT | O_RDWR | O_TRUNC, DLP_FILE_PERMISSION); | ||
| 1229 | + ASSERT_GE(fd, 0); | ||
| 1230 | + char buffer[] = "123456"; | ||
| 1231 | + write(fd, buffer, sizeof(buffer)); | ||
| 1232 | + close(fd); | ||
| 1233 | + | ||
| 1234 | + OHOS::AAFwk::Want want; | ||
| 1235 | + want.SetAction(TAG_ACTION_VIEW); | ||
| 1236 | + want.SetUri(INVALID_CONTENT_DLP_URI); | ||
| 1237 | + // IsDlpFile is false: the fd is closed and false is returned after the docker policy query | ||
| 1238 | + ASSERT_FALSE(DlpFileKits::GetSandboxFlag(want)); | ||
| 1239 | + unlink(INVALID_CONTENT_FILE.c_str()); | ||
| 1240 | +} | ||
| 1241 | + | ||
| 1242 | +/** | ||
| 1243 | + * @tc.name: GetSandboxFlagRemoveNotOriginalDlp001 | ||
| 1244 | + * @tc.desc: cover RemoveNotOriginalDlpFlag branch of GetSandboxFlag | ||
| 1245 | + * @tc.type: FUNC | ||
| 1246 | + */ | ||
| 1247 | +HWTEST_F(DlpFileKitsTest, GetSandboxFlagRemoveNotOriginalDlp001, TestSize.Level0) | ||
| 1248 | +{ | ||
| 1249 | + DLP_LOG_INFO(LABEL, "GetSandboxFlagRemoveNotOriginalDlp001"); | ||
| 1250 | + OHOS::AAFwk::Want want; | ||
| 1251 | + want.SetAction(TAG_ACTION_VIEW); | ||
| 1252 | + want.SetUri(DLP_FILE_URI); | ||
| 1253 | + // the notOriginalDlp parameter is removed when the name is a dlp file | ||
| 1254 | + want.SetParam("ohos.dlp.params.notOriginalDlp", true); | ||
| 1255 | + ASSERT_TRUE(DlpFileKits::GetSandboxFlag(want)); | ||
| 1256 | + // the parameter has been removed by RemoveNotOriginalDlpFlag | ||
| 1257 | + ASSERT_FALSE(want.HasParameter("ohos.dlp.params.notOriginalDlp")); | ||
| 1258 | +} | ||
| 1259 | + | ||
| 1260 | +/** | ||
| 1261 | + * @tc.name: GetSandboxFlagRawFile001 | ||
| 1262 | + * @tc.desc: cover raw-file branches of SetWantType and GetIsReadOnceOrWaterMark | ||
| 1263 | + * @tc.type: FUNC | ||
| 1264 | + */ | ||
| 1265 | +HWTEST_F(DlpFileKitsTest, GetSandboxFlagRawFile001, TestSize.Level0) | ||
| 1266 | +{ | ||
| 1267 | + DLP_LOG_INFO(LABEL, "GetSandboxFlagRawFile001"); | ||
| 1268 | + // generate a real raw (non-zip) dlp file: docx takes the raw generation path | ||
| 1269 | + int32_t rawFd = CreateRawDlpFile(RAW_DLP_FILE); | ||
| 1270 | + ASSERT_GE(rawFd, 0); | ||
| 1271 | + OHOS::AppFileService::ModuleFileUri::SetMockGetRealPath(RAW_DLP_FILE); | ||
| 1272 | + OHOS::AppFileService::ModuleFileUri::SetMockGetRealPathCount(1); | ||
| 1273 | + | ||
| 1274 | + OHOS::AAFwk::Want want; | ||
| 1275 | + want.SetAction(TAG_ACTION_VIEW); | ||
| 1276 | + want.SetUri(RAW_DLP_URI); | ||
| 1277 | + // IsDlpFile passes on the raw file and SetWantType runs through the raw branch | ||
| 1278 | + ASSERT_TRUE(DlpFileKits::GetSandboxFlag(want)); | ||
| 1279 | + // docx maps to a known mimetype | ||
| 1280 | + EXPECT_EQ(want.GetType(), "application/vnd.openxmlformats-officedocument.wordprocessingml.document"); | ||
| 1281 | + close(rawFd); | ||
| 1282 | + unlink(RAW_DLP_FILE.c_str()); | ||
| 1283 | +} | ||
| 1284 | + | ||
| 1285 | +/** | ||
| 1286 | + * @tc.name: GetSandboxFlagRawUnknownType001 | ||
| 1287 | + * @tc.desc: cover unknown real suffix branch of SetWantType | ||
| 1288 | + * @tc.type: FUNC | ||
| 1289 | + */ | ||
| 1290 | +HWTEST_F(DlpFileKitsTest, GetSandboxFlagRawUnknownType001, TestSize.Level0) | ||
| 1291 | +{ | ||
| 1292 | + DLP_LOG_INFO(LABEL, "GetSandboxFlagRawUnknownType001"); | ||
| 1293 | + // build a raw dlp file whose fileType maps to no known suffix: the origin type stays | ||
| 1294 | + int32_t fd = open(RAW_UNKNOWN_TYPE_DLP_FILE.c_str(), O_CREAT | O_RDWR | O_TRUNC, DLP_FILE_PERMISSION); | ||
| 1295 | + ASSERT_GE(fd, 0); | ||
| 1296 | + WriteRawDlpHeader(fd, FILE_TYPE_UNKNOWN); | ||
| 1297 | + lseek(fd, 0, SEEK_SET); | ||
| 1298 | + ASSERT_TRUE(DlpFileKits::IsDlpFile(fd)); | ||
| 1299 | + close(fd); | ||
| 1300 | + | ||
| 1301 | + OHOS::AppFileService::ModuleFileUri::SetMockGetRealPath(RAW_UNKNOWN_TYPE_DLP_FILE); | ||
| 1302 | + OHOS::AppFileService::ModuleFileUri::SetMockGetRealPathCount(1); | ||
| 1303 | + OHOS::AAFwk::Want want; | ||
| 1304 | + want.SetAction(TAG_ACTION_VIEW); | ||
| 1305 | + want.SetUri(RAW_UNKNOWN_TYPE_DLP_URI); | ||
| 1306 | + // the real suffix is unknown: the mimetype falls back to image/jpeg | ||
| 1307 | + ASSERT_TRUE(DlpFileKits::GetSandboxFlag(want)); | ||
| 1308 | + EXPECT_EQ(want.GetType(), "image/jpeg"); | ||
| 1309 | + unlink(RAW_UNKNOWN_TYPE_DLP_FILE.c_str()); | ||
| 1310 | +} | ||
| 1311 | + | ||
| 1312 | +/** | ||
| 1313 | + * @tc.name: GetSandboxFlagRawReadOnce001 | ||
| 1314 | + * @tc.desc: cover readOnce/waterMark branch of GetIsReadOnceOrWaterMark for raw files | ||
| 1315 | + * @tc.type: FUNC | ||
| 1316 | + */ | ||
| 1317 | +HWTEST_F(DlpFileKitsTest, GetSandboxFlagRawReadOnce001, TestSize.Level0) | ||
| 1318 | +{ | ||
| 1319 | + DLP_LOG_INFO(LABEL, "GetSandboxFlagRawReadOnce001"); | ||
| 1320 | + // build a raw dlp file with a file id tail whose first byte is non-zero: | ||
| 1321 | + // GetRawFileAllowedOpenCount reports allowedOpenCount 1 for non-owner readers | ||
| 1322 | + int32_t fd = open(RAW_UNKNOWN_TYPE_DLP_FILE.c_str(), O_CREAT | O_RDWR | O_TRUNC, DLP_FILE_PERMISSION); | ||
| 1323 | + ASSERT_GE(fd, 0); | ||
| 1324 | + WriteRawDlpHeader(fd, FILE_TYPE_TXT); | ||
| 1325 | + // rewrite the tail: watermark flag off, open-count flag off, non-zero first fileId byte | ||
| 1326 | + ftruncate(fd, 0); | ||
| 1327 | + lseek(fd, 0, SEEK_SET); | ||
| 1328 | + uint32_t version = CURRENT_VERSION; | ||
| 1329 | + uint32_t dlpHeaderSize = sizeof(struct DlpHeader); | ||
| 1330 | + struct DlpHeader header = { | ||
| 1331 | + .magic = DLP_FILE_MAGIC, | ||
| 1332 | + .fileType = FILE_TYPE_TXT, | ||
| 1333 | + .txtOffset = sizeof(struct DlpHeader) + RAW_FILE_HEAD + 1, | ||
| 1334 | + .txtSize = 0, | ||
| 1335 | + .hmacOffset = sizeof(struct DlpHeader) + RAW_FILE_HEAD + 1, | ||
| 1336 | + .hmacSize = RAW_HMAC_HEX_SIZE, | ||
| 1337 | + .certOffset = sizeof(struct DlpHeader) + RAW_FILE_HEAD + 1, | ||
| 1338 | + .certSize = 16, | ||
| 1339 | + .contactAccountOffset = sizeof(struct DlpHeader) + RAW_FILE_HEAD, | ||
| 1340 | + .contactAccountSize = 1, | ||
| 1341 | + }; | ||
| 1342 | + write(fd, &version, sizeof(uint32_t)); | ||
| 1343 | + write(fd, &dlpHeaderSize, sizeof(uint32_t)); | ||
| 1344 | + write(fd, &header, sizeof(struct DlpHeader)); | ||
| 1345 | + uint8_t body[16] = {0}; | ||
| 1346 | + write(fd, body, sizeof(body)); | ||
| 1347 | + write(fd, body, RAW_HMAC_HEX_SIZE); | ||
| 1348 | + write(fd, body, 16); | ||
| 1349 | + // tail layout: watermark(4) + flag(4) + allowedOpenCount(4) + fileId(46) | ||
| 1350 | + int32_t watermark = 0; | ||
| 1351 | + int32_t flag = 0; | ||
| 1352 | + int32_t allowedOpenCount = 0; | ||
| 1353 | + uint8_t fileId[46] = {0}; | ||
| 1354 | + fileId[0] = 1; // non-zero first byte with flag 0: allowedOpenCount becomes 1 | ||
| 1355 | + write(fd, &watermark, sizeof(int32_t)); | ||
| 1356 | + write(fd, &flag, sizeof(int32_t)); | ||
| 1357 | + write(fd, &allowedOpenCount, sizeof(int32_t)); | ||
| 1358 | + write(fd, fileId, sizeof(fileId)); | ||
| 1359 | + lseek(fd, 0, SEEK_SET); | ||
| 1360 | + ASSERT_TRUE(DlpFileKits::IsDlpFile(fd)); | ||
| 1361 | + close(fd); | ||
| 1362 | + | ||
| 1363 | + OHOS::AppFileService::ModuleFileUri::SetMockGetRealPath(RAW_UNKNOWN_TYPE_DLP_FILE); | ||
| 1364 | + OHOS::AppFileService::ModuleFileUri::SetMockGetRealPathCount(1); | ||
| 1365 | + OHOS::AAFwk::Want want; | ||
| 1366 | + want.SetAction(TAG_ACTION_VIEW); | ||
| 1367 | + want.SetUri(RAW_UNKNOWN_TYPE_DLP_URI); | ||
| 1368 | + // allowedOpenCount becomes 1 through the non-zero fileId: the type is forced to image/jpeg | ||
| 1369 | + ASSERT_TRUE(DlpFileKits::GetSandboxFlag(want)); | ||
| 1370 | + EXPECT_EQ(want.GetType(), "image/jpeg"); | ||
| 1371 | + unlink(RAW_UNKNOWN_TYPE_DLP_FILE.c_str()); | ||
| 1372 | +} | ||
| 1373 | + | ||
| 1374 | +/** | ||
| 1375 | + * @tc.name: ConvertAbilityInfoUnknownMime001 | ||
| 1376 | + * @tc.desc: cover fileType empty branch of GetRealFileType | ||
| 1377 | + * @tc.type: FUNC | ||
| 1378 | + */ | ||
| 1379 | +HWTEST_F(DlpFileKitsTest, ConvertAbilityInfoUnknownMime001, TestSize.Level0) | ||
| 1380 | +{ | ||
| 1381 | + DLP_LOG_INFO(LABEL, "ConvertAbilityInfoUnknownMime001"); | ||
| 1382 | + OHOS::AAFwk::Want want; | ||
| 1383 | + want.SetUri(DLP_FILE_URI); | ||
| 1384 | + // an unknown mimetype maps to no suffix: GetFileTypeBySuffix returns empty | ||
| 1385 | + want.SetType("application/x-unknown-type"); | ||
| 1386 | + | ||
| 1387 | + std::vector<OHOS::AppExecFwk::AbilityInfo> abilityInfos; | ||
| 1388 | + OHOS::AppExecFwk::AbilityInfo abilityInfo; | ||
| 1389 | + abilityInfo.bundleName = "bundle.keep"; | ||
| 1390 | + abilityInfos.push_back(abilityInfo); | ||
| 1391 | + | ||
| 1392 | + // fileType is empty: the function returns early and the abilities are not filtered | ||
| 1393 | + DlpFileKits::ConvertAbilityInfoWithSupportDlp(want, abilityInfos); | ||
| 1394 | + EXPECT_EQ(abilityInfos.size(), 1); | ||
| 1395 | + EXPECT_EQ(want.GetType(), "application/x-unknown-type"); | ||
| 1008 | } | 1396 | } |
| @@ -18,6 +18,9 @@ | |||
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 21 | 24 | ||
| 22 | 25 | ||
| 23 | 26 | ||
| @@ -1292,6 +1295,547 @@ HWTEST_F(DlpFileManagerTest, GenRawDlpFile_PrepareDirsFail, TestSize.Level0) | |||
| 1292 | close(plainFileFd); | 1295 | close(plainFileFd); |
| 1293 | } | 1296 | } |
| 1294 | 1297 | ||
| 1298 | +namespace { | ||
| 1299 | +// constants for the branch cases below | ||
| 1300 | +static constexpr int32_t OPEN_COUNT_AT_LEAST_ONE = 1; | ||
| 1301 | +static constexpr int32_t OPEN_COUNT_ZERO = 0; | ||
| 1302 | +static constexpr uint32_t EXPIRE_TIME_NON_ZERO = 1; | ||
| 1303 | +static constexpr int32_t INVALID_ACTION_UPON_EXPIRY = 2; | ||
| 1304 | +static constexpr int32_t TRUNCATED_FILE_SIZE = 4; | ||
| 1305 | + | ||
| 1306 | +// build a valid dlp property for encrypting a cloud-account file | ||
| 1307 | +static DlpProperty BuildCloudProperty() | ||
| 1308 | +{ | ||
| 1309 | + DlpProperty property; | ||
| 1310 | + property.ownerAccount = "owner"; | ||
| 1311 | + property.ownerAccountId = "owner"; | ||
| 1312 | + property.contactAccount = "owner"; | ||
| 1313 | + property.ownerAccountType = CLOUD_ACCOUNT; | ||
| 1314 | + return property; | ||
| 1315 | +} | ||
| 1316 | + | ||
| 1317 | +// generate a real raw dlp file (document type takes the raw path) and leave both fds open | ||
| 1318 | +static bool GenCloudRawDlpFile(int32_t& plainFd, int32_t& dlpFd) | ||
| 1319 | +{ | ||
| 1320 | + plainFd = open("/data/file_test.txt", O_CREAT | O_RDWR | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO); | ||
| 1321 | + if (plainFd < 0) { | ||
| 1322 | + return false; | ||
| 1323 | + } | ||
| 1324 | + dlpFd = open("/data/file_test.docx.dlp", O_CREAT | O_RDWR | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO); | ||
| 1325 | + if (dlpFd < 0) { | ||
| 1326 | + close(plainFd); | ||
| 1327 | + return false; | ||
| 1328 | + } | ||
| 1329 | + char buffer[] = "123456"; | ||
| 1330 | + if (write(plainFd, buffer, sizeof(buffer)) == -1) { | ||
| 1331 | + close(plainFd); | ||
| 1332 | + close(dlpFd); | ||
| 1333 | + return false; | ||
| 1334 | + } | ||
| 1335 | + DlpProperty property = BuildCloudProperty(); | ||
| 1336 | + std::shared_ptr<DlpFile> filePtr; | ||
| 1337 | + if (DlpFileManager::GetInstance().GenerateDlpFile(plainFd, dlpFd, property, filePtr, | ||
| 1338 | + DLP_TEST_DIR) != DLP_OK) { | ||
| 1339 | + close(plainFd); | ||
| 1340 | + close(dlpFd); | ||
| 1341 | + return false; | ||
| 1342 | + } | ||
| 1343 | + lseek(plainFd, 0, SEEK_SET); | ||
| 1344 | + lseek(dlpFd, 0, SEEK_SET); | ||
| 1345 | + return true; | ||
| 1346 | +} | ||
| 1347 | +} | ||
| 1348 | + | ||
| 1349 | +/** | ||
| 1350 | + * @tc.name: PrepareDlpEncryptParmsHmacFail001 | ||
| 1351 | + * @tc.desc: cover hmac key generate fail branch of PrepareDlpEncryptParms | ||
| 1352 | + * @tc.type: FUNC | ||
| 1353 | + * @tc.require: | ||
| 1354 | + */ | ||
| 1355 | +HWTEST_F(DlpFileManagerTest, PrepareDlpEncryptParmsHmacFail001, TestSize.Level0) | ||
| 1356 | +{ | ||
| 1357 | + DLP_LOG_INFO(LABEL, "PrepareDlpEncryptParmsHmacFail001"); | ||
| 1358 | + | ||
| 1359 | + PermissionPolicy policy; | ||
| 1360 | + policy.ownerAccountType_ = CLOUD_ACCOUNT; | ||
| 1361 | + policy.ownerAccount_ = "owner"; | ||
| 1362 | + policy.ownerAccountId_ = "owner"; | ||
| 1363 | + struct DlpBlob key; | ||
| 1364 | + struct DlpUsageSpec usage; | ||
| 1365 | + struct DlpBlob certData; | ||
| 1366 | + struct DlpBlob hmacKey; | ||
| 1367 | + | ||
| 1368 | + // the 3rd RAND_bytes call (hmac key) fails: CleanTempBlob and the error are returned | ||
| 1369 | + DlpCMockCondition condition; | ||
| 1370 | + condition.mockSequence = { false, false, true }; | ||
| 1371 | + SetMockConditions("RAND_bytes", condition); | ||
| 1372 | + EXPECT_EQ(DLP_PARSE_ERROR_CRYPTO_ENGINE_ERROR, | ||
| 1373 | + DlpFileManager::GetInstance().PrepareDlpEncryptParms(policy, key, usage, certData, hmacKey)); | ||
| 1374 | + CleanMockConditions(); | ||
| 1375 | +} | ||
| 1376 | + | ||
| 1377 | +/** | ||
| 1378 | + * @tc.name: UpdateDlpFileBranch001 | ||
| 1379 | + * @tc.desc: cover allowedOpenCount >= 1 and CheckDlpFile fail branches of UpdateDlpFile | ||
| 1380 | + * @tc.type: FUNC | ||
| 1381 | + * @tc.require: | ||
| 1382 | + */ | ||
| 1383 | +HWTEST_F(DlpFileManagerTest, UpdateDlpFileBranch001, TestSize.Level0) | ||
| 1384 | +{ | ||
| 1385 | + DLP_LOG_INFO(LABEL, "UpdateDlpFileBranch001"); | ||
| 1386 | + std::vector<uint8_t> cert; | ||
| 1387 | + | ||
| 1388 | + // allowedOpenCount >= 1: return DLP_OK directly without touching the file | ||
| 1389 | + std::shared_ptr<DlpFile> filePtr = std::make_shared<DlpZipFile>(1000, DLP_TEST_DIR, 0, "txt"); | ||
| 1390 | + ASSERT_NE(filePtr, nullptr); | ||
| 1391 | + EXPECT_EQ(DLP_OK, DlpFileManager::GetInstance().UpdateDlpFile(cert, filePtr, OPEN_COUNT_AT_LEAST_ONE)); | ||
| 1392 | + | ||
| 1393 | + // CheckDlpFile fails on the invalid fd: the error is propagated | ||
| 1394 | + EXPECT_NE(DLP_OK, DlpFileManager::GetInstance().UpdateDlpFile(cert, filePtr, OPEN_COUNT_ZERO)); | ||
| 1395 | +} | ||
| 1396 | + | ||
| 1397 | +/** | ||
| 1398 | + * @tc.name: SetDlpFileParamsInvalidAction001 | ||
| 1399 | + * @tc.desc: cover CheckActionUponExpiry fail branch of SetDlpParams | ||
| 1400 | + * @tc.type: FUNC | ||
| 1401 | + * @tc.require: | ||
| 1402 | + */ | ||
| 1403 | +HWTEST_F(DlpFileManagerTest, SetDlpFileParamsInvalidAction001, TestSize.Level0) | ||
| 1404 | +{ | ||
| 1405 | + DLP_LOG_INFO(LABEL, "SetDlpFileParamsInvalidAction001"); | ||
| 1406 | + std::shared_ptr<DlpFile> filePtr = std::make_shared<DlpZipFile>(1000, DLP_TEST_DIR, 0, "txt"); | ||
| 1407 | + ASSERT_NE(filePtr, nullptr); | ||
| 1408 | + | ||
| 1409 | + // expireTime != 0 and actionUponExpiry > OPEN: CheckActionUponExpiry fails | ||
| 1410 | + DlpProperty property = BuildCloudProperty(); | ||
| 1411 | + property.expireTime = EXPIRE_TIME_NON_ZERO; | ||
| 1412 | + property.actionUponExpiry = static_cast<ActionType>(INVALID_ACTION_UPON_EXPIRY); | ||
| 1413 | + EXPECT_EQ(DLP_PARSE_ERROR_VALUE_INVALID, | ||
| 1414 | + DlpFileManager::GetInstance().SetDlpFileParams(filePtr, property)); | ||
| 1415 | +} | ||
| 1416 | + | ||
| 1417 | +/** | ||
| 1418 | + * @tc.name: GenZipDlpFileBranch001 | ||
| 1419 | + * @tc.desc: cover random dir fail, SetDlpFileParams fail and GenFile fail branches of GenZipDlpFile | ||
| 1420 | + * @tc.type: FUNC | ||
| 1421 | + * @tc.require: | ||
| 1422 | + */ | ||
| 1423 | +HWTEST_F(DlpFileManagerTest, GenZipDlpFileBranch001, TestSize.Level0) | ||
| 1424 | +{ | ||
| 1425 | + DLP_LOG_INFO(LABEL, "GenZipDlpFileBranch001"); | ||
| 1426 | + int32_t plainFd = open("/data/file_test.txt", O_CREAT | O_RDWR | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO); | ||
| 1427 | + ASSERT_NE(plainFd, -1); | ||
| 1428 | + char buffer[] = "123456"; | ||
| 1429 | + ASSERT_NE(write(plainFd, buffer, sizeof(buffer)), -1); | ||
| 1430 | + DlpFileManager::DlpFileMes mes = {plainFd, 1000, "txt"}; | ||
| 1431 | + DlpProperty property = BuildCloudProperty(); | ||
| 1432 | + std::shared_ptr<DlpFile> filePtr; | ||
| 1433 | + | ||
| 1434 | + // GenerateRandomWorkDir fails (RAND_bytes mocked) | ||
| 1435 | + DlpCMockCondition condition; | ||
| 1436 | + condition.mockSequence = { true }; | ||
| 1437 | + SetMockConditions("RAND_bytes", condition); | ||
| 1438 | + EXPECT_EQ(DLP_PARSE_ERROR_CRYPTO_ENGINE_ERROR, | ||
| 1439 | + DlpFileManager::GetInstance().GenZipDlpFile(mes, property, filePtr, DLP_TEST_DIR)); | ||
| 1440 | + CleanMockConditions(); | ||
| 1441 | + | ||
| 1442 | + // SetDlpFileParams fails: empty ownerAccount makes SetPolicy fail | ||
| 1443 | + DlpProperty badProperty; | ||
| 1444 | + badProperty.ownerAccount = ""; | ||
| 1445 | + badProperty.ownerAccountId = "owner"; | ||
| 1446 | + badProperty.contactAccount = "owner"; | ||
| 1447 | + badProperty.ownerAccountType = CLOUD_ACCOUNT; | ||
| 1448 | + EXPECT_EQ(DLP_PARSE_ERROR_VALUE_INVALID, | ||
| 1449 | + DlpFileManager::GetInstance().GenZipDlpFile(mes, badProperty, filePtr, DLP_TEST_DIR)); | ||
| 1450 | + | ||
| 1451 | + // GenFile fails: lseek on the plain fd fails (lseek mocked) | ||
| 1452 | + lseek(plainFd, 0, SEEK_SET); | ||
| 1453 | + condition.mockSequence = { true }; | ||
| 1454 | + SetMockConditions("lseek", condition); | ||
| 1455 | + EXPECT_EQ(DLP_PARSE_ERROR_FILE_OPERATE_FAIL, | ||
| 1456 | + DlpFileManager::GetInstance().GenZipDlpFile(mes, property, filePtr, DLP_TEST_DIR)); | ||
| 1457 | + CleanMockConditions(); | ||
| 1458 | + | ||
| 1459 | + close(plainFd); | ||
| 1460 | +} | ||
| 1461 | + | ||
| 1462 | +/** | ||
| 1463 | + * @tc.name: GenRawDlpFileGenFileFail001 | ||
| 1464 | + * @tc.desc: cover GenFile fail branch of GenRawDlpFile | ||
| 1465 | + * @tc.type: FUNC | ||
| 1466 | + * @tc.require: | ||
| 1467 | + */ | ||
| 1468 | +HWTEST_F(DlpFileManagerTest, GenRawDlpFileGenFileFail001, TestSize.Level0) | ||
| 1469 | +{ | ||
| 1470 | + DLP_LOG_INFO(LABEL, "GenRawDlpFileGenFileFail001"); | ||
| 1471 | + int32_t plainFd = open("/data/file_test.txt", O_CREAT | O_RDWR | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO); | ||
| 1472 | + ASSERT_NE(plainFd, -1); | ||
| 1473 | + char buffer[] = "123456"; | ||
| 1474 | + ASSERT_NE(write(plainFd, buffer, sizeof(buffer)), -1); | ||
| 1475 | + DlpFileManager::DlpFileMes mes = {plainFd, 1000, "mp4"}; | ||
| 1476 | + DlpProperty property = BuildCloudProperty(); | ||
| 1477 | + std::shared_ptr<DlpFile> filePtr; | ||
| 1478 | + | ||
| 1479 | + // SetDlpFileParams succeeds but GenFile fails (lseek mocked) | ||
| 1480 | + DlpCMockCondition condition; | ||
| 1481 | + condition.mockSequence = { true }; | ||
| 1482 | + SetMockConditions("lseek", condition); | ||
| 1483 | + EXPECT_EQ(DLP_PARSE_ERROR_FILE_OPERATE_FAIL, | ||
| 1484 | + DlpFileManager::GetInstance().GenRawDlpFile(mes, property, filePtr)); | ||
| 1485 | + CleanMockConditions(); | ||
| 1486 | + | ||
| 1487 | + close(plainFd); | ||
| 1488 | +} | ||
| 1489 | + | ||
| 1490 | +/** | ||
| 1491 | + * @tc.name: GenerateDlpFileAlreadyOpened001 | ||
| 1492 | + * @tc.desc: cover already opened branch of GenerateDlpFile | ||
| 1493 | + * @tc.type: FUNC | ||
| 1494 | + * @tc.require: | ||
| 1495 | + */ | ||
| 1496 | +HWTEST_F(DlpFileManagerTest, GenerateDlpFileAlreadyOpened001, TestSize.Level0) | ||
| 1497 | +{ | ||
| 1498 | + DLP_LOG_INFO(LABEL, "GenerateDlpFileAlreadyOpened001"); | ||
| 1499 | + int32_t plainFd = -1; | ||
| 1500 | + int32_t dlpFd = -1; | ||
| 1501 | + ASSERT_TRUE(GenCloudRawDlpFile(plainFd, dlpFd)); | ||
| 1502 | + DlpProperty property = BuildCloudProperty(); | ||
| 1503 | + | ||
| 1504 | + // register the dlp fd in the open-file map: GenerateDlpFile reports already opened | ||
| 1505 | + std::shared_ptr<DlpFile> openedPtr = std::make_shared<DlpZipFile>(dlpFd, DLP_TEST_DIR, 0, "txt"); | ||
| 1506 | + ASSERT_EQ(DLP_OK, DlpFileManager::GetInstance().AddDlpFileNode(openedPtr)); | ||
| 1507 | + std::shared_ptr<DlpFile> filePtr; | ||
| 1508 | + EXPECT_EQ(DLP_PARSE_ERROR_FILE_ALREADY_OPENED, | ||
| 1509 | + DlpFileManager::GetInstance().GenerateDlpFile(plainFd, dlpFd, property, filePtr, DLP_TEST_DIR)); | ||
| 1510 | + DlpFileManager::GetInstance().RemoveDlpFileNode(openedPtr); | ||
| 1511 | + | ||
| 1512 | + close(plainFd); | ||
| 1513 | + close(dlpFd); | ||
| 1514 | + unlink("/data/file_test.txt"); | ||
| 1515 | + unlink("/data/file_test.docx.dlp"); | ||
| 1516 | +} | ||
| 1517 | + | ||
| 1518 | +/** | ||
| 1519 | + * @tc.name: GenerateDlpFileUnknownSuffix001 | ||
| 1520 | + * @tc.desc: cover GetFileTypeBySuffix fail branch of GenerateDlpFile | ||
| 1521 | + * @tc.type: FUNC | ||
| 1522 | + * @tc.require: | ||
| 1523 | + */ | ||
| 1524 | +HWTEST_F(DlpFileManagerTest, GenerateDlpFileUnknownSuffix001, TestSize.Level0) | ||
| 1525 | +{ | ||
| 1526 | + DLP_LOG_INFO(LABEL, "GenerateDlpFileUnknownSuffix001"); | ||
| 1527 | + int32_t plainFd = open("/data/file_test.txt", O_CREAT | O_RDWR | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO); | ||
| 1528 | + ASSERT_NE(plainFd, -1); | ||
| 1529 | + char buffer[] = "123456"; | ||
| 1530 | + ASSERT_NE(write(plainFd, buffer, sizeof(buffer)), -1); | ||
| 1531 | + // a valid fd whose link name ends with an unsupported suffix | ||
| 1532 | + int32_t dlpFd = open("/data/file_test.xyz.dlp", O_CREAT | O_RDWR | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO); | ||
| 1533 | + ASSERT_NE(dlpFd, -1); | ||
| 1534 | + | ||
| 1535 | + DlpProperty property = BuildCloudProperty(); | ||
| 1536 | + std::shared_ptr<DlpFile> filePtr; | ||
| 1537 | + // suffix "xyz" is not in FILE_TYPE_MAP: GetFileTypeBySuffix returns empty | ||
| 1538 | + EXPECT_EQ(DLP_PARSE_ERROR_VALUE_INVALID, | ||
| 1539 | + DlpFileManager::GetInstance().GenerateDlpFile(plainFd, dlpFd, property, filePtr, DLP_TEST_DIR)); | ||
| 1540 | + | ||
| 1541 | + close(plainFd); | ||
| 1542 | + close(dlpFd); | ||
| 1543 | + unlink("/data/file_test.txt"); | ||
| 1544 | + unlink("/data/file_test.xyz.dlp"); | ||
| 1545 | +} | ||
| 1546 | + | ||
| 1547 | +/** | ||
| 1548 | + * @tc.name: DlpRawHmacCheckAndUpdateTruncated001 | ||
| 1549 | + * @tc.desc: cover UpdateDlpFile fail branch of DlpRawHmacCheckAndUpdate | ||
| 1550 | + * @tc.type: FUNC | ||
| 1551 | + * @tc.require: | ||
| 1552 | + */ | ||
| 1553 | +HWTEST_F(DlpFileManagerTest, DlpRawHmacCheckAndUpdateTruncated001, TestSize.Level0) | ||
| 1554 | +{ | ||
| 1555 | + DLP_LOG_INFO(LABEL, "DlpRawHmacCheckAndUpdateTruncated001"); | ||
| 1556 | + int32_t plainFd = -1; | ||
| 1557 | + int32_t dlpFd = -1; | ||
| 1558 | + ASSERT_TRUE(GenCloudRawDlpFile(plainFd, dlpFd)); | ||
| 1559 | + | ||
| 1560 | + // the generated raw dlp file passes HmacCheck; truncate it so CheckDlpFile | ||
| 1561 | + // fails inside UpdateDlpFile (fileLen <= FILE_HEAD) | ||
| 1562 | + ASSERT_EQ(0, ftruncate(dlpFd, TRUNCATED_FILE_SIZE)); | ||
| 1563 | + lseek(dlpFd, 0, SEEK_SET); | ||
| 1564 | + std::vector<uint8_t> offlineCert; | ||
| 1565 | + std::shared_ptr<DlpFile> filePtr = std::make_shared<DlpRawFile>(dlpFd, "txt"); | ||
| 1566 | + ASSERT_NE(filePtr, nullptr); | ||
| 1567 | + EXPECT_NE(DLP_OK, | ||
| 1568 | + DlpFileManager::GetInstance().DlpRawHmacCheckAndUpdate(filePtr, offlineCert, OPEN_COUNT_ZERO)); | ||
| 1569 | + | ||
| 1570 | + close(plainFd); | ||
| 1571 | + close(dlpFd); | ||
| 1572 | + unlink("/data/file_test.txt"); | ||
| 1573 | + unlink("/data/file_test.docx.dlp"); | ||
| 1574 | +} | ||
| 1575 | + | ||
| 1576 | +/** | ||
| 1577 | + * @tc.name: OpenZipDlpFilePrepareFail001 | ||
| 1578 | + * @tc.desc: cover PrepareDirs fail and GenerateRandomWorkDir fail branches of OpenZipDlpFile | ||
| 1579 | + * @tc.type: FUNC | ||
| 1580 | + * @tc.require: | ||
| 1581 | + */ | ||
| 1582 | +HWTEST_F(DlpFileManagerTest, OpenZipDlpFilePrepareFail001, TestSize.Level0) | ||
| 1583 | +{ | ||
| 1584 | + DLP_LOG_INFO(LABEL, "OpenZipDlpFilePrepareFail001"); | ||
| 1585 | + std::shared_ptr<DlpFile> filePtr; | ||
| 1586 | + std::string appId = "test_appId"; | ||
| 1587 | + | ||
| 1588 | + // PrepareDirs fails: the parent of the work dir does not exist | ||
| 1589 | + EXPECT_NE(DLP_OK, DlpFileManager::GetInstance().OpenZipDlpFile(1000, filePtr, | ||
| 1590 | + "/data/nonexistent_parent_dir/sub", appId, "txt")); | ||
| 1591 | + | ||
| 1592 | + // GenerateRandomWorkDir fails (RAND_bytes mocked) | ||
| 1593 | + DlpCMockCondition condition; | ||
| 1594 | + condition.mockSequence = { true }; | ||
| 1595 | + SetMockConditions("RAND_bytes", condition); | ||
| 1596 | + EXPECT_EQ(DLP_PARSE_ERROR_CRYPTO_ENGINE_ERROR, | ||
| 1597 | + DlpFileManager::GetInstance().OpenZipDlpFile(1000, filePtr, DLP_TEST_DIR, appId, "txt")); | ||
| 1598 | + CleanMockConditions(); | ||
| 1599 | +} | ||
| 1600 | + | ||
| 1601 | +/** | ||
| 1602 | + * @tc.name: OpenDlpFileAlreadyOpened001 | ||
| 1603 | + * @tc.desc: cover already opened branch of OpenDlpFile | ||
| 1604 | + * @tc.type: FUNC | ||
| 1605 | + * @tc.require: | ||
| 1606 | + */ | ||
| 1607 | +HWTEST_F(DlpFileManagerTest, OpenDlpFileAlreadyOpened001, TestSize.Level0) | ||
| 1608 | +{ | ||
| 1609 | + DLP_LOG_INFO(LABEL, "OpenDlpFileAlreadyOpened001"); | ||
| 1610 | + int32_t plainFd = -1; | ||
| 1611 | + int32_t dlpFd = -1; | ||
| 1612 | + ASSERT_TRUE(GenCloudRawDlpFile(plainFd, dlpFd)); | ||
| 1613 | + std::string appId = "test_appId"; | ||
| 1614 | + | ||
| 1615 | + // the dlp fd is registered in the map: OpenDlpFile returns DLP_OK with the mapped object | ||
| 1616 | + std::shared_ptr<DlpFile> openedPtr = std::make_shared<DlpRawFile>(dlpFd, "txt"); | ||
| 1617 | + ASSERT_EQ(DLP_OK, DlpFileManager::GetInstance().AddDlpFileNode(openedPtr)); | ||
| 1618 | + std::shared_ptr<DlpFile> filePtr; | ||
| 1619 | + EXPECT_EQ(DLP_OK, DlpFileManager::GetInstance().OpenDlpFile(dlpFd, filePtr, DLP_TEST_DIR, appId)); | ||
| 1620 | + EXPECT_EQ(openedPtr, filePtr); | ||
| 1621 | + DlpFileManager::GetInstance().RemoveDlpFileNode(openedPtr); | ||
| 1622 | + | ||
| 1623 | + close(plainFd); | ||
| 1624 | + close(dlpFd); | ||
| 1625 | + unlink("/data/file_test.txt"); | ||
| 1626 | + unlink("/data/file_test.docx.dlp"); | ||
| 1627 | +} | ||
| 1628 | + | ||
| 1629 | +/** | ||
| 1630 | + * @tc.name: OpenDlpFileRawBranch001 | ||
| 1631 | + * @tc.desc: cover the raw-file branch of OpenDlpFile | ||
| 1632 | + * @tc.type: FUNC | ||
| 1633 | + * @tc.require: | ||
| 1634 | + */ | ||
| 1635 | +HWTEST_F(DlpFileManagerTest, OpenDlpFileRawBranch001, TestSize.Level0) | ||
| 1636 | +{ | ||
| 1637 | + DLP_LOG_INFO(LABEL, "OpenDlpFileRawBranch001"); | ||
| 1638 | + int32_t plainFd = -1; | ||
| 1639 | + int32_t dlpFd = -1; | ||
| 1640 | + ASSERT_TRUE(GenCloudRawDlpFile(plainFd, dlpFd)); | ||
| 1641 | + std::string appId = "test_appId"; | ||
| 1642 | + | ||
| 1643 | + // the generated file is a raw (non-zip) dlp file: OpenRawDlpFile path is taken | ||
| 1644 | + std::shared_ptr<DlpFile> filePtr; | ||
| 1645 | + int32_t ret = DlpFileManager::GetInstance().OpenDlpFile(dlpFd, filePtr, DLP_TEST_DIR, appId); | ||
| 1646 | + if (ret == DLP_OK) { | ||
| 1647 | + // close it through the manager to clean the node | ||
| 1648 | + DlpFileManager::GetInstance().CloseDlpFile(filePtr); | ||
| 1649 | + } | ||
| 1650 | + close(plainFd); | ||
| 1651 | + close(dlpFd); | ||
| 1652 | + unlink("/data/file_test.txt"); | ||
| 1653 | + unlink("/data/file_test.docx.dlp"); | ||
| 1654 | +} | ||
| 1655 | + | ||
| 1656 | +/** | ||
| 1657 | + * @tc.name: VerifyAndGetWaterMarkBranch001 | ||
| 1658 | + * @tc.desc: cover canFind fallback and VerifyConsistent fail branches via ParseZipDlpFile | ||
| 1659 | + * @tc.type: FUNC | ||
| 1660 | + * @tc.require: | ||
| 1661 | + */ | ||
| 1662 | +HWTEST_F(DlpFileManagerTest, VerifyAndGetWaterMarkBranch001, TestSize.Level0) | ||
| 1663 | +{ | ||
| 1664 | + DLP_LOG_INFO(LABEL, "VerifyAndGetWaterMarkBranch001"); | ||
| 1665 | + int32_t fd = open("/data/fuse_test_dlp.txt", O_RDWR | O_CREAT | O_TRUNC, S_IRWXU); | ||
| 1666 | + ASSERT_NE(fd, -1); | ||
| 1667 | + std::shared_ptr<DlpFile> filePtr = std::make_shared<DlpZipFile>(fd, DLP_TEST_DIR, 0, "txt"); | ||
| 1668 | + ASSERT_NE(filePtr, nullptr); | ||
| 1669 | + // cert with an empty fileId (matches the empty file plaintext) and countdown 0: | ||
| 1670 | + // the file object countdown is 100 so VerifyConsistent fails on the countdown check | ||
| 1671 | + sptr<CertParcel> certParcel = BuildCertParcelByType(CLOUD_ACCOUNT); | ||
| 1672 | + ASSERT_NE(certParcel, nullptr); | ||
| 1673 | + ordered_json jsonObj = ordered_json::parse( | ||
| 1674 | + std::string(certParcel->cert.begin(), certParcel->cert.end()), nullptr, false); | ||
| 1675 | + ASSERT_TRUE(!jsonObj.is_discarded() && jsonObj.is_object()); | ||
| 1676 | + jsonObj["fileId"] = ""; | ||
| 1677 | + jsonObj["countdown"] = 0; | ||
| 1678 | + std::string certStr = jsonObj.dump(); | ||
| 1679 | + certParcel->cert = std::vector<uint8_t>(certStr.begin(), certStr.end()); | ||
| 1680 | + certParcel->fileId = ""; | ||
| 1681 | + filePtr->SetCountdown(100); | ||
| 1682 | + | ||
| 1683 | + int32_t ret = DlpFileManager::GetInstance().ParseZipDlpFile(filePtr, "app_id", fd, certParcel); | ||
| 1684 | + EXPECT_NE(DLP_OK, ret); | ||
| 1685 | + close(fd); | ||
| 1686 | + unlink("/data/fuse_test_dlp.txt"); | ||
| 1687 | +} | ||
| 1688 | + | ||
| 1689 | +/** | ||
| 1690 | + * @tc.name: ParseZipDlpFileSetCipherFail001 | ||
| 1691 | + * @tc.desc: cover SetCipher fail branch of ParseZipDlpFile | ||
| 1692 | + * @tc.type: FUNC | ||
| 1693 | + * @tc.require: | ||
| 1694 | + */ | ||
| 1695 | +HWTEST_F(DlpFileManagerTest, ParseZipDlpFileSetCipherFail001, TestSize.Level0) | ||
| 1696 | +{ | ||
| 1697 | + DLP_LOG_INFO(LABEL, "ParseZipDlpFileSetCipherFail001"); | ||
| 1698 | + int32_t fd = open("/data/fuse_test_dlp.txt", O_RDWR | O_CREAT | O_TRUNC, S_IRWXU); | ||
| 1699 | + ASSERT_NE(fd, -1); | ||
| 1700 | + std::shared_ptr<DlpFile> filePtr = std::make_shared<DlpZipFile>(fd, DLP_TEST_DIR, 0, "txt"); | ||
| 1701 | + ASSERT_NE(filePtr, nullptr); | ||
| 1702 | + | ||
| 1703 | + // SetCipher fails: memcpy_s mocked late in the sequence | ||
| 1704 | + sptr<CertParcel> certParcel = BuildCertParcelByType(CLOUD_ACCOUNT); | ||
| 1705 | + ASSERT_NE(certParcel, nullptr); | ||
| 1706 | + DlpCMockCondition condition; | ||
| 1707 | + condition.mockSequence = { false, true }; | ||
| 1708 | + SetMockConditions("memcpy_s", condition); | ||
| 1709 | + int32_t ret = DlpFileManager::GetInstance().ParseZipDlpFile(filePtr, "app_id", fd, certParcel); | ||
| 1710 | + CleanMockConditions(); | ||
| 1711 | + EXPECT_NE(DLP_OK, ret); | ||
| 1712 | + close(fd); | ||
| 1713 | + unlink("/data/fuse_test_dlp.txt"); | ||
| 1714 | +} | ||
| 1715 | + | ||
| 1716 | +/** | ||
| 1717 | + * @tc.name: ParseZipDlpFileSetNotOwnerFail001 | ||
| 1718 | + * @tc.desc: cover SetNotOwnerAndReadOnce fail branch of ParseZipDlpFile | ||
| 1719 | + * @tc.type: FUNC | ||
| 1720 | + * @tc.require: | ||
| 1721 | + */ | ||
| 1722 | +HWTEST_F(DlpFileManagerTest, ParseZipDlpFileSetNotOwnerFail001, TestSize.Level0) | ||
| 1723 | +{ | ||
| 1724 | + DLP_LOG_INFO(LABEL, "ParseZipDlpFileSetNotOwnerFail001"); | ||
| 1725 | + int32_t fd = open("/data/fuse_test_dlp.txt", O_RDWR | O_CREAT | O_TRUNC, S_IRWXU); | ||
| 1726 | + ASSERT_NE(fd, -1); | ||
| 1727 | + std::shared_ptr<DlpFile> filePtr = std::make_shared<DlpZipFile>(fd, DLP_TEST_DIR, 0, "txt"); | ||
| 1728 | + ASSERT_NE(filePtr, nullptr); | ||
| 1729 | + | ||
| 1730 | + // SetNotOwnerAndReadOnce fails on the invalid dlp fd passed to GetFilePathByFd | ||
| 1731 | + sptr<CertParcel> certParcel = BuildCertParcelByType(CLOUD_ACCOUNT); | ||
| 1732 | + ASSERT_NE(certParcel, nullptr); | ||
| 1733 | + int32_t ret = DlpFileManager::GetInstance().ParseZipDlpFile(filePtr, "app_id", -1, certParcel); | ||
| 1734 | + EXPECT_NE(DLP_OK, ret); | ||
| 1735 | + close(fd); | ||
| 1736 | + unlink("/data/fuse_test_dlp.txt"); | ||
| 1737 | +} | ||
| 1738 | + | ||
| 1739 | +/** | ||
| 1740 | + * @tc.name: ParseZipDlpFileEnterpriseHmacFail001 | ||
| 1741 | + * @tc.desc: cover SetEnterpriseInfoForDlpFileAndCheck fail branch of ParseZipDlpFile | ||
| 1742 | + * @tc.type: FUNC | ||
| 1743 | + * @tc.require: | ||
| 1744 | + */ | ||
| 1745 | +HWTEST_F(DlpFileManagerTest, ParseZipDlpFileEnterpriseHmacFail001, TestSize.Level0) | ||
| 1746 | +{ | ||
| 1747 | + DLP_LOG_INFO(LABEL, "ParseZipDlpFileEnterpriseHmacFail001"); | ||
| 1748 | + int32_t fd = open("/data/fuse_test_dlp.txt", O_RDWR | O_CREAT | O_TRUNC, S_IRWXU); | ||
| 1749 | + ASSERT_NE(fd, -1); | ||
| 1750 | + std::shared_ptr<DlpFile> filePtr = std::make_shared<DlpZipFile>(fd, DLP_TEST_DIR, 0, "txt"); | ||
| 1751 | + ASSERT_NE(filePtr, nullptr); | ||
| 1752 | + // the enterprise path runs SetEnterpriseInfoForDlpFile and then HmacCheck fails on the | ||
| 1753 | + // zip file object whose encDataFd_ is invalid | ||
| 1754 | + filePtr->SetAccountType(ENTERPRISE_ACCOUNT); | ||
| 1755 | + | ||
| 1756 | + // build an enterprise cert without fileId so VerifyConsistent passes (empty == empty) | ||
| 1757 | + sptr<CertParcel> certParcel = BuildCertParcelByType(ENTERPRISE_ACCOUNT); | ||
| 1758 | + ASSERT_NE(certParcel, nullptr); | ||
| 1759 | + ordered_json jsonObj = ordered_json::parse( | ||
| 1760 | + std::string(certParcel->cert.begin(), certParcel->cert.end()), nullptr, false); | ||
| 1761 | + ASSERT_TRUE(!jsonObj.is_discarded() && jsonObj.is_object()); | ||
| 1762 | + jsonObj.erase("fileId"); | ||
| 1763 | + std::string certStr = jsonObj.dump(); | ||
| 1764 | + certParcel->cert = std::vector<uint8_t>(certStr.begin(), certStr.end()); | ||
| 1765 | + certParcel->fileId = ""; | ||
| 1766 | + | ||
| 1767 | + int32_t ret = DlpFileManager::GetInstance().ParseZipDlpFile(filePtr, "app_id", fd, certParcel); | ||
| 1768 | + EXPECT_NE(DLP_OK, ret); | ||
| 1769 | + close(fd); | ||
| 1770 | + unlink("/data/fuse_test_dlp.txt"); | ||
| 1771 | +} | ||
| 1772 | + | ||
| 1773 | +/** | ||
| 1774 | + * @tc.name: ParseRawDlpFileVerifyFail001 | ||
| 1775 | + * @tc.desc: cover VerifyAndGetWaterMark fail and SetNotOwnerAndReadOnce fail branches of ParseRawDlpFile | ||
| 1776 | + * @tc.type: FUNC | ||
| 1777 | + * @tc.require: | ||
| 1778 | + */ | ||
| 1779 | +HWTEST_F(DlpFileManagerTest, ParseRawDlpFileVerifyFail001, TestSize.Level0) | ||
| 1780 | +{ | ||
| 1781 | + DLP_LOG_INFO(LABEL, "ParseRawDlpFileVerifyFail001"); | ||
| 1782 | + int32_t fd = open("/data/fuse_test_dlp.txt", O_RDWR | O_CREAT | O_TRUNC, S_IRWXU); | ||
| 1783 | + ASSERT_NE(fd, -1); | ||
| 1784 | + | ||
| 1785 | + // cloud account with fileId in the cert but empty file plaintext: VerifyConsistent fails | ||
| 1786 | + std::shared_ptr<DlpFile> filePtr = std::make_shared<DlpRawFile>(fd, "txt"); | ||
| 1787 | + ASSERT_NE(filePtr, nullptr); | ||
| 1788 | + sptr<CertParcel> certParcel = BuildCertParcelByType(CLOUD_ACCOUNT); | ||
| 1789 | + ASSERT_NE(certParcel, nullptr); | ||
| 1790 | + EXPECT_NE(DLP_OK, | ||
| 1791 | + DlpFileManager::GetInstance().ParseRawDlpFile(fd, filePtr, "app_id", "txt", certParcel)); | ||
| 1792 | + | ||
| 1793 | + // empty-fileId cert passes the consistency checks: with the invalid dlp fd the flow | ||
| 1794 | + // reaches SetNotOwnerAndReadOnce and fails at GetFilePathByFd | ||
| 1795 | + std::shared_ptr<DlpFile> filePtr2 = std::make_shared<DlpRawFile>(fd, "txt"); | ||
| 1796 | + ASSERT_NE(filePtr2, nullptr); | ||
| 1797 | + ordered_json jsonObj = ordered_json::parse( | ||
| 1798 | + std::string(certParcel->cert.begin(), certParcel->cert.end()), nullptr, false); | ||
| 1799 | + ASSERT_TRUE(!jsonObj.is_discarded() && jsonObj.is_object()); | ||
| 1800 | + jsonObj["fileId"] = ""; | ||
| 1801 | + std::string certStr = jsonObj.dump(); | ||
| 1802 | + sptr<CertParcel> certParcel2 = new (std::nothrow) CertParcel(); | ||
| 1803 | + ASSERT_NE(certParcel2, nullptr); | ||
| 1804 | + certParcel2->cert = std::vector<uint8_t>(certStr.begin(), certStr.end()); | ||
| 1805 | + certParcel2->fileId = ""; | ||
| 1806 | + EXPECT_NE(DLP_OK, | ||
| 1807 | + DlpFileManager::GetInstance().ParseRawDlpFile(-1, filePtr2, "app_id", "txt", certParcel2)); | ||
| 1808 | + | ||
| 1809 | + close(fd); | ||
| 1810 | + unlink("/data/fuse_test_dlp.txt"); | ||
| 1811 | +} | ||
| 1812 | + | ||
| 1813 | +/** | ||
| 1814 | + * @tc.name: OpenRawDlpFileOfflineCert001 | ||
| 1815 | + * @tc.desc: cover offlineCert branch and ParseRawDlpFile fail branch of OpenRawDlpFile | ||
| 1816 | + * @tc.type: FUNC | ||
| 1817 | + * @tc.require: | ||
| 1818 | + */ | ||
| 1819 | +HWTEST_F(DlpFileManagerTest, OpenRawDlpFileOfflineCert001, TestSize.Level0) | ||
| 1820 | +{ | ||
| 1821 | + DLP_LOG_INFO(LABEL, "OpenRawDlpFileOfflineCert001"); | ||
| 1822 | + int32_t plainFd = -1; | ||
| 1823 | + int32_t dlpFd = -1; | ||
| 1824 | + ASSERT_TRUE(GenCloudRawDlpFile(plainFd, dlpFd)); | ||
| 1825 | + std::string appId = "test_appId"; | ||
| 1826 | + | ||
| 1827 | + // offline access with count 0: GetOfflineCertSize != 0 path is prepared; the parse | ||
| 1828 | + // eventually fails on the account checks so the offline cert branch is exercised | ||
| 1829 | + std::shared_ptr<DlpFile> filePtr; | ||
| 1830 | + int32_t ret = DlpFileManager::GetInstance().OpenRawDlpFile(dlpFd, filePtr, appId, "txt"); | ||
| 1831 | + EXPECT_NE(DLP_PARSE_ERROR_PTR_NULL, ret); | ||
| 1832 | + | ||
| 1833 | + close(plainFd); | ||
| 1834 | + close(dlpFd); | ||
| 1835 | + unlink("/data/file_test.txt"); | ||
| 1836 | + unlink("/data/file_test.docx.dlp"); | ||
| 1837 | +} | ||
| 1838 | + | ||
| 1295 | } // namespace DlpPermission | 1839 | } // namespace DlpPermission |
| 1296 | } // namespace Security | 1840 | } // namespace Security |
| 1297 | } // namespace OHOS | 1841 | } // namespace OHOS |
| @@ -20,6 +20,7 @@ | |||
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | 22 | ||
| 23 | + | ||
| 23 | 24 | ||
| 24 | 25 | ||
| 25 | 26 | ||
| @@ -30,6 +31,8 @@ | |||
| 30 | 31 | ||
| 31 | 32 | ||
| 32 | 33 | ||
| 34 | + | ||
| 35 | + | ||
| 33 | 36 | ||
| 34 | using namespace testing::ext; | 37 | using namespace testing::ext; |
| 35 | using namespace OHOS::Security::DlpPermission; | 38 | using namespace OHOS::Security::DlpPermission; |
| @@ -43,6 +46,113 @@ static const std::string PPT_STRINGS = "ppt"; | |||
| 43 | static const std::string DLP_MANAGER_BUNDLE = "com.ohos.dlpmanager"; | 46 | static const std::string DLP_MANAGER_BUNDLE = "com.ohos.dlpmanager"; |
| 44 | static const std::string PASTEBOARD_SERVICE_NAME = "pasteboard_service"; | 47 | static const std::string PASTEBOARD_SERVICE_NAME = "pasteboard_service"; |
| 45 | const int32_t FILEID_SIZE_VALID = 1; | 48 | const int32_t FILEID_SIZE_VALID = 1; |
| 49 | +// constants for the branch cases below (aligned with dlp_utils.cpp) | ||
| 50 | +const int32_t RAW_FILEID_SIZE = 46; | ||
| 51 | +const uint32_t DLP_VERSION_NO_HMAC = 2; | ||
| 52 | +const uint32_t LARGE_FILE_SIZE = 102400; | ||
| 53 | +const uint32_t LONG_PATH_SEG_COUNT = 40; | ||
| 54 | +const char DEEP_DIR_PREFIX[] = "/data/fuse_test_deep"; | ||
| 55 | +const char OVERSIZE_FILE[] = "/data/fuse_test_oversize.txt"; | ||
| 56 | +const char FILEID_NONZERO = 1; | ||
| 57 | +const int32_t OPEN_COUNT_FLAG_ON = 1; | ||
| 58 | +const int32_t OPEN_COUNT_FLAG_OFF = 0; | ||
| 59 | +const int32_t WATERMARK_FLAG_ON = 1; | ||
| 60 | +const int32_t COUNTDOWN_VALUE = 1; | ||
| 61 | +const int32_t ALLOWED_OPEN_COUNT_VALUE = 0; | ||
| 62 | + | ||
| 63 | +// create a nested directory chain of segmentCount segments under the prefix | ||
| 64 | +static bool CreateNestedDirs(std::string& deepDir, uint32_t segmentCount, const std::string& segName) | ||
| 65 | +{ | ||
| 66 | + if (mkdir(DEEP_DIR_PREFIX, S_IRWXU | S_IRWXG | S_IRWXO) != 0) { | ||
| 67 | + return false; | ||
| 68 | + } | ||
| 69 | + deepDir = DEEP_DIR_PREFIX; | ||
| 70 | + for (uint32_t i = 0; i < segmentCount; i++) { | ||
| 71 | + deepDir += "/" + segName + std::to_string(i); | ||
| 72 | + if (mkdir(deepDir.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) != 0) { | ||
| 73 | + return false; | ||
| 74 | + } | ||
| 75 | + } | ||
| 76 | + return true; | ||
| 77 | +} | ||
| 78 | + | ||
| 79 | +// remove the nested directory chain from the deepest level up | ||
| 80 | +static void RemoveNestedDirs(std::string deepDir) | ||
| 81 | +{ | ||
| 82 | + while (deepDir != DEEP_DIR_PREFIX) { | ||
| 83 | + rmdir(deepDir.c_str()); | ||
| 84 | + size_t last = deepDir.find_last_of('/'); | ||
| 85 | + deepDir = deepDir.substr(0, last); | ||
| 86 | + } | ||
| 87 | + rmdir(DEEP_DIR_PREFIX); | ||
| 88 | +} | ||
| 89 | + | ||
| 90 | +// pre-create the sandbox cache path chain used by GetGenerateInfoStr so the zip | ||
| 91 | +// success path is reachable; returns true when the cache dir exists afterwards | ||
| 92 | +static bool PrepareSandboxCachePath() | ||
| 93 | +{ | ||
| 94 | + const std::string cacheChain = "/data/storage/el2/base/files/cache"; | ||
| 95 | + std::string cur; | ||
| 96 | + size_t pos = 0; | ||
| 97 | + while (pos != std::string::npos) { | ||
| 98 | + size_t next = cacheChain.find('/', pos + 1); | ||
| 99 | + cur = (next == std::string::npos) ? cacheChain : cacheChain.substr(0, next); | ||
| 100 | + if (!cur.empty() && mkdir(cur.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) != 0 && errno != EEXIST) { | ||
| 101 | + return false; | ||
| 102 | + } | ||
| 103 | + pos = next; | ||
| 104 | + } | ||
| 105 | + struct stat buf = {}; | ||
| 106 | + return stat(cacheChain.c_str(), &buf) == 0 && S_ISDIR(buf.st_mode); | ||
| 107 | +} | ||
| 108 | + | ||
| 109 | +// build a dlp zip with the 3 required entries; the general info content is caller-provided | ||
| 110 | +static int32_t BuildDlpZipFile(const char* zipPath, const std::string& generalInfo) | ||
| 111 | +{ | ||
| 112 | + std::string infoFile("dlp_general_info"); | ||
| 113 | + std::string certFile("dlp_cert"); | ||
| 114 | + std::string dataFile("encrypted_data"); | ||
| 115 | + int32_t fdInfo = open(infoFile.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0666); | ||
| 116 | + if (fdInfo < 0) { | ||
| 117 | + return -1; | ||
| 118 | + } | ||
| 119 | + write(fdInfo, generalInfo.c_str(), generalInfo.size()); | ||
| 120 | + lseek(fdInfo, 0, SEEK_SET); | ||
| 121 | + int32_t fdCert = open(certFile.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0666); | ||
| 122 | + int32_t fdData = open(dataFile.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0666); | ||
| 123 | + if (fdCert < 0 || fdData < 0) { | ||
| 124 | + close(fdInfo); | ||
| 125 | + if (fdCert >= 0) { | ||
| 126 | + close(fdCert); | ||
| 127 | + } | ||
| 128 | + if (fdData >= 0) { | ||
| 129 | + close(fdData); | ||
| 130 | + } | ||
| 131 | + return -1; | ||
| 132 | + } | ||
| 133 | + int32_t zf = open(zipPath, O_RDWR | O_CREAT | O_TRUNC, 0666); | ||
| 134 | + if (zf < 0) { | ||
| 135 | + close(fdInfo); | ||
| 136 | + close(fdCert); | ||
| 137 | + close(fdData); | ||
| 138 | + return -1; | ||
| 139 | + } | ||
| 140 | + int32_t res = AddFileContextToZip(fdInfo, infoFile.c_str(), zipPath); | ||
| 141 | + if (res == 0) { | ||
| 142 | + res = AddFileContextToZip(fdCert, certFile.c_str(), zipPath); | ||
| 143 | + } | ||
| 144 | + if (res == 0) { | ||
| 145 | + res = AddFileContextToZip(fdData, dataFile.c_str(), zipPath); | ||
| 146 | + } | ||
| 147 | + close(fdInfo); | ||
| 148 | + close(fdCert); | ||
| 149 | + close(fdData); | ||
| 150 | + close(zf); | ||
| 151 | + unlink(infoFile.c_str()); | ||
| 152 | + unlink(certFile.c_str()); | ||
| 153 | + unlink(dataFile.c_str()); | ||
| 154 | + return res; | ||
| 155 | +} | ||
| 46 | } | 156 | } |
| 47 | 157 | ||
| 48 | static bool GetBundleInfoForSelfByCurrentToken(int32_t& ret, OHOS::AppExecFwk::BundleInfo& bundleInfo) | 158 | static bool GetBundleInfoForSelfByCurrentToken(int32_t& ret, OHOS::AppExecFwk::BundleInfo& bundleInfo) |
| @@ -772,3 +882,319 @@ HWTEST_F(DlpUtilsTest, IsExistFileLargeFile001, TestSize.Level1) | |||
| 772 | 882 | ||
| 773 | unlink(path.c_str()); | 883 | unlink(path.c_str()); |
| 774 | } | 884 | } |
| 885 | + | ||
| 886 | +/** | ||
| 887 | + * @tc.name: GetFilePathByFdTruncate001 | ||
| 888 | + * @tc.desc: cover readlink result longer than MAX_DLP_FILE_SIZE branches of | ||
| 889 | + * GetFilePathByFd and GetFileNameWithFd | ||
| 890 | + * @tc.type: FUNC | ||
| 891 | + * @tc.require: | ||
| 892 | + */ | ||
| 893 | +HWTEST_F(DlpUtilsTest, GetFilePathByFdTruncate001, TestSize.Level1) | ||
| 894 | +{ | ||
| 895 | + DLP_LOG_INFO(UT_LABEL, "GetFilePathByFdTruncate001"); | ||
| 896 | + | ||
| 897 | + // build a nested path longer than MAX_DLP_FILE_SIZE (1000) | ||
| 898 | + std::string deepDir; | ||
| 899 | + ASSERT_TRUE(CreateNestedDirs(deepDir, LONG_PATH_SEG_COUNT, "dirdirdirdirdirdirdirdirdirdir_")); | ||
| 900 | + std::string deepFile = deepDir + "/f.txt"; | ||
| 901 | + ASSERT_LT(1000u, deepFile.size()); | ||
| 902 | + int fd = open(deepFile.c_str(), O_RDWR | O_CREAT | O_TRUNC, S_IRWXU); | ||
| 903 | + ASSERT_NE(fd, -1); | ||
| 904 | + | ||
| 905 | + std::string path; | ||
| 906 | + // readlink returns more than MAX_DLP_FILE_SIZE: truncated path is rejected | ||
| 907 | + ASSERT_EQ(DLP_PARSE_ERROR_FD_ERROR, DlpUtils::GetFilePathByFd(fd, path)); | ||
| 908 | + std::string fileName; | ||
| 909 | + ASSERT_EQ(DLP_PARSE_ERROR_FD_ERROR, DlpUtils::GetFileNameWithFd(fd, fileName)); | ||
| 910 | + | ||
| 911 | + close(fd); | ||
| 912 | + unlink(deepFile.c_str()); | ||
| 913 | + RemoveNestedDirs(deepDir); | ||
| 914 | +} | ||
| 915 | + | ||
| 916 | +/** | ||
| 917 | + * @tc.name: IsExistFileTooLarge001 | ||
| 918 | + * @tc.desc: cover file size >= FILE_MAX_SIZE branch of IsExistFile | ||
| 919 | + * @tc.type: FUNC | ||
| 920 | + * @tc.require: | ||
| 921 | + */ | ||
| 922 | +HWTEST_F(DlpUtilsTest, IsExistFileTooLarge001, TestSize.Level1) | ||
| 923 | +{ | ||
| 924 | + DLP_LOG_INFO(UT_LABEL, "IsExistFileTooLarge001"); | ||
| 925 | + int fd = open(OVERSIZE_FILE, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU); | ||
| 926 | + ASSERT_NE(fd, -1); | ||
| 927 | + // write a buffer so the file is larger than FILE_MAX_SIZE (102400) | ||
| 928 | + std::string bigBuf(LARGE_FILE_SIZE + 1, 'a'); | ||
| 929 | + ASSERT_EQ(static_cast<ssize_t>(bigBuf.size()), write(fd, bigBuf.c_str(), bigBuf.size())); | ||
| 930 | + close(fd); | ||
| 931 | + | ||
| 932 | + // st_size >= FILE_MAX_SIZE: IsExistFile returns false | ||
| 933 | + EXPECT_FALSE(IsExistFile(OVERSIZE_FILE)); | ||
| 934 | + unlink(OVERSIZE_FILE); | ||
| 935 | +} | ||
| 936 | + | ||
| 937 | +/** | ||
| 938 | + * @tc.name: GetGenerateInfoStrGetcwdFail001 | ||
| 939 | + * @tc.desc: cover getcwd fail branch of GetGenerateInfoStr | ||
| 940 | + * @tc.type: FUNC | ||
| 941 | + * @tc.require: | ||
| 942 | + */ | ||
| 943 | +HWTEST_F(DlpUtilsTest, GetGenerateInfoStrGetcwdFail001, TestSize.Level1) | ||
| 944 | +{ | ||
| 945 | + DLP_LOG_INFO(UT_LABEL, "GetGenerateInfoStrGetcwdFail001"); | ||
| 946 | + char originCwd[256] = {0}; | ||
| 947 | + ASSERT_NE(nullptr, getcwd(originCwd, sizeof(originCwd))); | ||
| 948 | + | ||
| 949 | + // build a path longer than DLP_CWD_MAX (256) and chdir into it: getcwd with a | ||
| 950 | + // 256-byte buffer fails with ERANGE | ||
| 951 | + std::string deepDir; | ||
| 952 | + ASSERT_TRUE(CreateNestedDirs(deepDir, LONG_PATH_SEG_COUNT, "dir_dir_dir_")); | ||
| 953 | + ASSERT_LT(256u, deepDir.size()); | ||
| 954 | + ASSERT_EQ(0, chdir(deepDir.c_str())); | ||
| 955 | + | ||
| 956 | + int32_t fd = open("/data/fuse_test_zip_fd.txt", O_RDWR | O_CREAT | O_TRUNC, S_IRWXU); | ||
| 957 | + ASSERT_NE(fd, -1); | ||
| 958 | + // getcwd fails inside GetGenerateInfoStr: empty string is returned | ||
| 959 | + EXPECT_EQ(DEFAULT_STRINGS, GetGenerateInfoStr(fd)); | ||
| 960 | + close(fd); | ||
| 961 | + unlink("/data/fuse_test_zip_fd.txt"); | ||
| 962 | + | ||
| 963 | + // restore the working directory and clean the nested chain | ||
| 964 | + ASSERT_EQ(0, chdir(originCwd)); | ||
| 965 | + RemoveNestedDirs(deepDir); | ||
| 966 | +} | ||
| 967 | + | ||
| 968 | +/** | ||
| 969 | + * @tc.name: GetGenerateInfoStrZipBranch001 | ||
| 970 | + * @tc.desc: cover CheckUnzipFileInfo fail and success content branches of GetGenerateInfoStr | ||
| 971 | + * @tc.type: FUNC | ||
| 972 | + * @tc.require: | ||
| 973 | + */ | ||
| 974 | +HWTEST_F(DlpUtilsTest, GetGenerateInfoStrZipBranch001, TestSize.Level1) | ||
| 975 | +{ | ||
| 976 | + DLP_LOG_INFO(UT_LABEL, "GetGenerateInfoStrZipBranch001"); | ||
| 977 | + const char* zipPath = "/data/fuse_test_gen_info.dlp"; | ||
| 978 | + | ||
| 979 | + // valid general info: dlpVersion 2 (no hmacValue required), realType support_txt_dlp | ||
| 980 | + GenerateInfoParams params = { | ||
| 981 | + .version = DLP_VERSION_NO_HMAC, | ||
| 982 | + .offlineAccessFlag = false, | ||
| 983 | + .contactAccount = "contact", | ||
| 984 | + .extraInfo = {}, | ||
| 985 | + .hmacVal = "", | ||
| 986 | + .realType = "support_txt_dlp", | ||
| 987 | + .certSize = 0, | ||
| 988 | + .fileId = "", | ||
| 989 | + .allowedOpenCount = 0, | ||
| 990 | + .waterMarkConfig = false, | ||
| 991 | + .countdown = 0, | ||
| 992 | + .nickNameMask = "", | ||
| 993 | + }; | ||
| 994 | + std::string generalInfo; | ||
| 995 | + ASSERT_EQ(DLP_OK, GenerateDlpGeneralInfo(params, generalInfo)); | ||
| 996 | + | ||
| 997 | + // build a full 3-entry dlp zip: the general info content is read back | ||
| 998 | + ASSERT_EQ(0, BuildDlpZipFile(zipPath, generalInfo)); | ||
| 999 | + int32_t fd = open(zipPath, O_RDONLY); | ||
| 1000 | + ASSERT_NE(fd, -1); | ||
| 1001 | + ASSERT_EQ(true, IsZipFile(fd)); | ||
| 1002 | + if (PrepareSandboxCachePath()) { | ||
| 1003 | + // CheckUnzipFileInfo ok and UnzipSpecificFile ok: the general info string is returned | ||
| 1004 | + std::string result = GetGenerateInfoStr(fd); | ||
| 1005 | + EXPECT_NE(DEFAULT_STRINGS, result); | ||
| 1006 | + } | ||
| 1007 | + close(fd); | ||
| 1008 | + unlink(zipPath); | ||
| 1009 | +} | ||
| 1010 | + | ||
| 1011 | +/** | ||
| 1012 | + * @tc.name: GetGenerateInfoStrCheckFail001 | ||
| 1013 | + * @tc.desc: cover CheckUnzipFileInfo fail branch of GetGenerateInfoStr | ||
| 1014 | + * @tc.type: FUNC | ||
| 1015 | + * @tc.require: | ||
| 1016 | + */ | ||
| 1017 | +HWTEST_F(DlpUtilsTest, GetGenerateInfoStrCheckFail001, TestSize.Level1) | ||
| 1018 | +{ | ||
| 1019 | + DLP_LOG_INFO(UT_LABEL, "GetGenerateInfoStrCheckFail001"); | ||
| 1020 | + const char* zipPath = "/data/fuse_test_gen_info.dlp"; | ||
| 1021 | + | ||
| 1022 | + // build a single-entry zip: IsZipFile is true (has dlp_general_info) but | ||
| 1023 | + // CheckUnzipFileInfo fails (entry count != 3) | ||
| 1024 | + std::string infoFile("dlp_general_info"); | ||
| 1025 | + int32_t fdInfo = open(infoFile.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0666); | ||
| 1026 | + ASSERT_NE(fdInfo, -1); | ||
| 1027 | + std::string content = "{\"dlpVersion\":2,\"extraInfo\":[],\"offlineAccess\":false,\"contactAccount\":\"c\"}"; | ||
| 1028 | + write(fdInfo, content.c_str(), content.size()); | ||
| 1029 | + lseek(fdInfo, 0, SEEK_SET); | ||
| 1030 | + int32_t zf = open(zipPath, O_RDWR | O_CREAT | O_TRUNC, 0666); | ||
| 1031 | + ASSERT_NE(zf, -1); | ||
| 1032 | + ASSERT_EQ(0, AddFileContextToZip(fdInfo, infoFile.c_str(), zipPath)); | ||
| 1033 | + close(fdInfo); | ||
| 1034 | + unlink(infoFile.c_str()); | ||
| 1035 | + | ||
| 1036 | + int32_t fd = open(zipPath, O_RDONLY); | ||
| 1037 | + ASSERT_NE(fd, -1); | ||
| 1038 | + ASSERT_EQ(true, IsZipFile(fd)); | ||
| 1039 | + // CheckUnzipFileInfo fails: empty string is returned | ||
| 1040 | + if (PrepareSandboxCachePath()) { | ||
| 1041 | + EXPECT_EQ(DEFAULT_STRINGS, GetGenerateInfoStr(fd)); | ||
| 1042 | + } | ||
| 1043 | + close(fd); | ||
| 1044 | + close(zf); | ||
| 1045 | + unlink(zipPath); | ||
| 1046 | +} | ||
| 1047 | + | ||
| 1048 | +/** | ||
| 1049 | + * @tc.name: GetRealTypeWithFdZipBranch001 | ||
| 1050 | + * @tc.desc: cover the zip branch of GetRealTypeWithFd | ||
| 1051 | + * @tc.type: FUNC | ||
| 1052 | + * @tc.require: | ||
| 1053 | + */ | ||
| 1054 | +HWTEST_F(DlpUtilsTest, GetRealTypeWithFdZipBranch001, TestSize.Level1) | ||
| 1055 | +{ | ||
| 1056 | + DLP_LOG_INFO(UT_LABEL, "GetRealTypeWithFdZipBranch001"); | ||
| 1057 | + const char* zipPath = "/data/fuse_test_realtype.dlp"; | ||
| 1058 | + | ||
| 1059 | + // build a full dlp zip whose general info carries realType support_txt_dlp | ||
| 1060 | + GenerateInfoParams params = { | ||
| 1061 | + .version = DLP_VERSION_NO_HMAC, | ||
| 1062 | + .offlineAccessFlag = false, | ||
| 1063 | + .contactAccount = "contact", | ||
| 1064 | + .extraInfo = {}, | ||
| 1065 | + .hmacVal = "", | ||
| 1066 | + .realType = "support_txt_dlp", | ||
| 1067 | + .certSize = 0, | ||
| 1068 | + .fileId = "", | ||
| 1069 | + .allowedOpenCount = 0, | ||
| 1070 | + .waterMarkConfig = false, | ||
| 1071 | + .countdown = 0, | ||
| 1072 | + .nickNameMask = "", | ||
| 1073 | + }; | ||
| 1074 | + std::string generalInfo; | ||
| 1075 | + ASSERT_EQ(DLP_OK, GenerateDlpGeneralInfo(params, generalInfo)); | ||
| 1076 | + ASSERT_EQ(0, BuildDlpZipFile(zipPath, generalInfo)); | ||
| 1077 | + int32_t fd = open(zipPath, O_RDONLY); | ||
| 1078 | + ASSERT_NE(fd, -1); | ||
| 1079 | + | ||
| 1080 | + // IsZipFile is true: the type is extracted from dlp_general_info | ||
| 1081 | + if (PrepareSandboxCachePath()) { | ||
| 1082 | + bool isFromUriName = false; | ||
| 1083 | + std::string generateInfoStr; | ||
| 1084 | + ASSERT_EQ(TXT_STRINGS, DlpUtils::GetRealTypeWithFd(fd, isFromUriName, generateInfoStr)); | ||
| 1085 | + } | ||
| 1086 | + close(fd); | ||
| 1087 | + unlink(zipPath); | ||
| 1088 | +} | ||
| 1089 | + | ||
| 1090 | +/** | ||
| 1091 | + * @tc.name: GetRealTypeWithRawFileCountdown001 | ||
| 1092 | + * @tc.desc: cover fileType bigger than COUNTDOWN_FILETYPE branch of GetRealTypeWithRawFile | ||
| 1093 | + * @tc.type: FUNC | ||
| 1094 | + * @tc.require: | ||
| 1095 | + */ | ||
| 1096 | +HWTEST_F(DlpUtilsTest, GetRealTypeWithRawFileCountdown001, TestSize.Level1) | ||
| 1097 | +{ | ||
| 1098 | + DLP_LOG_INFO(UT_LABEL, "GetRealTypeWithRawFileCountdown001"); | ||
| 1099 | + int fd = open("/data/fuse_test.txt.dlp", O_RDWR | O_CREAT | O_TRUNC, S_IRWXU); | ||
| 1100 | + ASSERT_NE(fd, -1); | ||
| 1101 | + | ||
| 1102 | + // full header with fileType 10001: fileType - COUNTDOWN_FILETYPE = 1 -> txt | ||
| 1103 | + struct DlpHeader header = { | ||
| 1104 | + .magic = DLP_FILE_MAGIC, | ||
| 1105 | + .certSize = 20, | ||
| 1106 | + .contactAccountSize = 20, | ||
| 1107 | + .fileType = 10001, | ||
| 1108 | + }; | ||
| 1109 | + uint8_t buffer[8] = {0}; | ||
| 1110 | + write(fd, buffer, 8); | ||
| 1111 | + write(fd, &header, sizeof(header)); | ||
| 1112 | + lseek(fd, 0, SEEK_SET); | ||
| 1113 | + ASSERT_EQ(TXT_STRINGS, DlpUtils::GetRealTypeWithRawFile(fd)); | ||
| 1114 | + close(fd); | ||
| 1115 | + unlink("/data/fuse_test.txt.dlp"); | ||
| 1116 | +} | ||
| 1117 | + | ||
| 1118 | +/** | ||
| 1119 | + * @tc.name: GetRawFileAllowedOpenCountFullTail001 | ||
| 1120 | + * @tc.desc: cover full tail branches of GetRawFileAllowedOpenCount | ||
| 1121 | + * @tc.type: FUNC | ||
| 1122 | + * @tc.require: | ||
| 1123 | + */ | ||
| 1124 | +HWTEST_F(DlpUtilsTest, GetRawFileAllowedOpenCountFullTail001, TestSize.Level1) | ||
| 1125 | +{ | ||
| 1126 | + DLP_LOG_INFO(UT_LABEL, "GetRawFileAllowedOpenCountFullTail001"); | ||
| 1127 | + int fd = open("/data/fuse_test.txt.dlp", O_RDWR | O_CREAT | O_TRUNC, S_IRWXU); | ||
| 1128 | + ASSERT_NE(fd, -1); | ||
| 1129 | + | ||
| 1130 | + // file tail layout: watermark(4) flag(4) allowedOpenCount(4) fileId(46) | ||
| 1131 | + int32_t watermark = WATERMARK_FLAG_ON; | ||
| 1132 | + int32_t flag = OPEN_COUNT_FLAG_OFF; | ||
| 1133 | + int32_t allowedOpenCount = ALLOWED_OPEN_COUNT_VALUE; | ||
| 1134 | + uint8_t fileId[RAW_FILEID_SIZE] = {0}; | ||
| 1135 | + fileId[0] = FILEID_NONZERO; // first fileId byte non-zero with flag == 0 | ||
| 1136 | + write(fd, &watermark, sizeof(int32_t)); | ||
| 1137 | + write(fd, &flag, sizeof(int32_t)); | ||
| 1138 | + write(fd, &allowedOpenCount, sizeof(int32_t)); | ||
| 1139 | + write(fd, fileId, RAW_FILEID_SIZE); | ||
| 1140 | + | ||
| 1141 | + int32_t count = 0; | ||
| 1142 | + bool watermarkConfig = false; | ||
| 1143 | + // watermark and flag are read, allowedOpenCount stays 0, fileId[0] != 0 sets it to 1 | ||
| 1144 | + ASSERT_EQ(DLP_OK, DlpUtils::GetRawFileAllowedOpenCount(fd, count, watermarkConfig)); | ||
| 1145 | + EXPECT_TRUE(watermarkConfig); | ||
| 1146 | + EXPECT_EQ(OPEN_COUNT_FLAG_ON, count); | ||
| 1147 | + | ||
| 1148 | + // flag == 1: allowedOpenCount is read from the file and keeps its value | ||
| 1149 | + lseek(fd, 0, SEEK_SET); | ||
| 1150 | + ftruncate(fd, 0); | ||
| 1151 | + lseek(fd, 0, SEEK_SET); | ||
| 1152 | + flag = OPEN_COUNT_FLAG_ON; | ||
| 1153 | + allowedOpenCount = COUNTDOWN_VALUE; | ||
| 1154 | + fileId[0] = 0; | ||
| 1155 | + write(fd, &watermark, sizeof(int32_t)); | ||
| 1156 | + write(fd, &flag, sizeof(int32_t)); | ||
| 1157 | + write(fd, &allowedOpenCount, sizeof(int32_t)); | ||
| 1158 | + write(fd, fileId, RAW_FILEID_SIZE); | ||
| 1159 | + ASSERT_EQ(DLP_OK, DlpUtils::GetRawFileAllowedOpenCount(fd, count, watermarkConfig)); | ||
| 1160 | + EXPECT_EQ(COUNTDOWN_VALUE, count); | ||
| 1161 | + | ||
| 1162 | + close(fd); | ||
| 1163 | + unlink("/data/fuse_test.txt.dlp"); | ||
| 1164 | +} | ||
| 1165 | + | ||
| 1166 | +/** | ||
| 1167 | + * @tc.name: GetRealTypeWithFdFileNameFail001 | ||
| 1168 | + * @tc.desc: cover GetFileNameWithFd fail branch of GetRealTypeWithFd | ||
| 1169 | + * @tc.type: FUNC | ||
| 1170 | + * @tc.require: | ||
| 1171 | + */ | ||
| 1172 | +HWTEST_F(DlpUtilsTest, GetRealTypeWithFdFileNameFail001, TestSize.Level1) | ||
| 1173 | +{ | ||
| 1174 | + DLP_LOG_INFO(UT_LABEL, "GetRealTypeWithFdFileNameFail001"); | ||
| 1175 | + | ||
| 1176 | + // invalid fd: the raw type is empty and GetFileNameWithFd fails, empty string returned | ||
| 1177 | + bool isFromUriName = false; | ||
| 1178 | + std::string generateInfoStr; | ||
| 1179 | + ASSERT_EQ(DEFAULT_STRINGS, DlpUtils::GetRealTypeWithFd(-1, isFromUriName, generateInfoStr)); | ||
| 1180 | + ASSERT_EQ(DEFAULT_STRINGS, DlpUtils::GetRealTypeWithFd(-1, isFromUriName, generateInfoStr, true)); | ||
| 1181 | +} | ||
| 1182 | + | ||
| 1183 | +/** | ||
| 1184 | + * @tc.name: GetUdid001 | ||
| 1185 | + * @tc.desc: cover success branch of GetUdid | ||
| 1186 | + * @tc.type: FUNC | ||
| 1187 | + * @tc.require: | ||
| 1188 | + */ | ||
| 1189 | +HWTEST_F(DlpUtilsTest, GetUdid001, TestSize.Level1) | ||
| 1190 | +{ | ||
| 1191 | + DLP_LOG_INFO(UT_LABEL, "GetUdid001"); | ||
| 1192 | + std::string udid; | ||
| 1193 | + // GetDevUdid succeeds on device: the udid string is filled and true returned | ||
| 1194 | + if (DlpUtils::GetUdid(udid)) { | ||
| 1195 | + EXPECT_FALSE(udid.empty()); | ||
| 1196 | + } else { | ||
| 1197 | + // no device udid in the current environment | ||
| 1198 | + EXPECT_TRUE(udid.empty()); | ||
| 1199 | + } | ||
| 1200 | +} | ||
| @@ -835,4 +835,369 @@ HWTEST_F(DlpZipTest, UnzipSpecificFile004, TestSize.Level0) | |||
| 835 | CleanMockConditions(); | 835 | CleanMockConditions(); |
| 836 | CloseAndUnlink(fd, zipFile.c_str()); | 836 | CloseAndUnlink(fd, zipFile.c_str()); |
| 837 | CloseAndUnlink(fd1, inZipInfo.c_str()); | 837 | CloseAndUnlink(fd1, inZipInfo.c_str()); |
| 838 | +} | ||
| 839 | + | ||
| 840 | +namespace { | ||
| 841 | +// callback that closes the current file via the real api and reports failure | ||
| 842 | +static int UnzCloseCurrentFileReply(unzFile file) | ||
| 843 | +{ | ||
| 844 | + unzCloseCurrentFile(file); | ||
| 845 | + return DLP_ZIP_FAIL; | ||
| 846 | +} | ||
| 847 | + | ||
| 848 | +// callback that fills the file info with compressed_size < uncompressed_size so the size check fails | ||
| 849 | +static int UnzGetFileInfoSizeReply(unzFile file, unz_file_info64* pfile_info, | ||
| 850 | + char* szFileName, uLong fileNameBufferSize, | ||
| 851 | + void* extraField, uLong extraFiledBufferSize, | ||
| 852 | + char* szComment, uLong commentBufferSize) | ||
| 853 | +{ | ||
| 854 | + int res = unzGetCurrentFileInfo64(file, pfile_info, szFileName, fileNameBufferSize, | ||
| 855 | + extraField, extraFiledBufferSize, szComment, commentBufferSize); | ||
| 856 | + if (res == UNZ_OK) { | ||
| 857 | + pfile_info->compressed_size = 0; | ||
| 858 | + pfile_info->uncompressed_size = 1; | ||
| 859 | + } | ||
| 860 | + return res; | ||
| 861 | +} | ||
| 862 | +} | ||
| 863 | + | ||
| 864 | +/** | ||
| 865 | + * @tc.name: AddBuffToZip007 | ||
| 866 | + * @tc.desc: cover zipName nullptr and dlp_cert zero buffer write fail branches | ||
| 867 | + * @tc.type: FUNC | ||
| 868 | + * @tc.require: | ||
| 869 | + */ | ||
| 870 | +HWTEST_F(DlpZipTest, AddBuffToZip007, TestSize.Level0) | ||
| 871 | +{ | ||
| 872 | + DLP_LOG_INFO(LABEL, "AddBuffToZip007"); | ||
| 873 | + std::string buf("123"); | ||
| 874 | + std::string nameInZip("dlp_cert"); | ||
| 875 | + std::string zipName("dlp_test_zip"); | ||
| 876 | + | ||
| 877 | + int32_t fd = open(zipName.c_str(), O_RDWR | O_CREAT, 0666); | ||
| 878 | + ASSERT_NE(fd, -1); | ||
| 879 | + | ||
| 880 | + // zipName == nullptr: return DLP_ZIP_FAIL | ||
| 881 | + ASSERT_EQ(DLP_ZIP_FAIL, AddBuffToZip(buf.c_str(), buf.size(), nameInZip.c_str(), nullptr)); | ||
| 882 | + | ||
| 883 | + // nameInZip is dlp_cert: the zero padding write (2nd zipWriteInFileInZip) fails | ||
| 884 | + DlpCMockCondition condition; | ||
| 885 | + condition.mockSequence = { false, true }; | ||
| 886 | + SetMockConditions("zipWriteInFileInZip", condition); | ||
| 887 | + ASSERT_EQ(DLP_ZIP_FAIL, AddBuffToZip(buf.c_str(), buf.size(), nameInZip.c_str(), zipName.c_str())); | ||
| 888 | + CleanMockConditions(); | ||
| 889 | + | ||
| 890 | + close(fd); | ||
| 891 | + unlink(zipName.c_str()); | ||
| 892 | +} | ||
| 893 | + | ||
| 894 | +/** | ||
| 895 | + * @tc.name: AddBuffToZip008 | ||
| 896 | + * @tc.desc: cover zipOpenNewFileInZip3_64, zipCloseFileInZip and zipClose fail branches | ||
| 897 | + * @tc.type: FUNC | ||
| 898 | + * @tc.require: | ||
| 899 | + */ | ||
| 900 | +HWTEST_F(DlpZipTest, AddBuffToZip008, TestSize.Level0) | ||
| 901 | +{ | ||
| 902 | + DLP_LOG_INFO(LABEL, "AddBuffToZip008"); | ||
| 903 | + std::string buf("123"); | ||
| 904 | + std::string nameInZip("dlp_general_info"); | ||
| 905 | + std::string zipName("dlp_test_zip"); | ||
| 906 | + | ||
| 907 | + int32_t fd = open(zipName.c_str(), O_RDWR | O_CREAT, 0666); | ||
| 908 | + ASSERT_NE(fd, -1); | ||
| 909 | + | ||
| 910 | + // zipOpenNewFileInZip3_64 fails: return DLP_ZIP_FAIL | ||
| 911 | + DlpCMockCondition condition; | ||
| 912 | + condition.mockSequence = { true }; | ||
| 913 | + SetMockConditions("zipOpenNewFileInZip3_64", condition); | ||
| 914 | + ASSERT_EQ(DLP_ZIP_FAIL, AddBuffToZip(buf.c_str(), buf.size(), nameInZip.c_str(), zipName.c_str())); | ||
| 915 | + CleanMockConditions(); | ||
| 916 | + | ||
| 917 | + // first zipWriteInFileInZip fails: res is DLP_ZIP_FAIL | ||
| 918 | + condition.mockSequence = { true }; | ||
| 919 | + SetMockConditions("zipWriteInFileInZip", condition); | ||
| 920 | + ASSERT_EQ(DLP_ZIP_FAIL, AddBuffToZip(buf.c_str(), buf.size(), nameInZip.c_str(), zipName.c_str())); | ||
| 921 | + CleanMockConditions(); | ||
| 922 | + | ||
| 923 | + // zipCloseFileInZip fails: res is DLP_ZIP_FAIL | ||
| 924 | + condition.mockSequence = { true }; | ||
| 925 | + SetMockConditions("zipCloseFileInZip", condition); | ||
| 926 | + SetMockCallback("zipCloseFileInZip", reinterpret_cast<CommonMockFuncT>(ZipCloseFileInZipReply)); | ||
| 927 | + ASSERT_EQ(DLP_ZIP_FAIL, AddBuffToZip(buf.c_str(), buf.size(), nameInZip.c_str(), zipName.c_str())); | ||
| 928 | + CleanMockConditions(); | ||
| 929 | + | ||
| 930 | + // zipClose fails: return DLP_ZIP_FAIL | ||
| 931 | + condition.mockSequence = { true }; | ||
| 932 | + SetMockConditions("zipClose", condition); | ||
| 933 | + SetMockCallback("zipClose", reinterpret_cast<CommonMockFuncT>(ZipCloseReply)); | ||
| 934 | + ASSERT_EQ(DLP_ZIP_FAIL, AddBuffToZip(buf.c_str(), buf.size(), nameInZip.c_str(), zipName.c_str())); | ||
| 935 | + CleanMockConditions(); | ||
| 936 | + | ||
| 937 | + close(fd); | ||
| 938 | + unlink(zipName.c_str()); | ||
| 939 | +} | ||
| 940 | + | ||
| 941 | +/** | ||
| 942 | + * @tc.name: AddFileContextToZip007 | ||
| 943 | + * @tc.desc: cover open new file, write, close file and close zip fail branches | ||
| 944 | + * @tc.type: FUNC | ||
| 945 | + * @tc.require: | ||
| 946 | + */ | ||
| 947 | +HWTEST_F(DlpZipTest, AddFileContextToZip007, TestSize.Level0) | ||
| 948 | +{ | ||
| 949 | + DLP_LOG_INFO(LABEL, "AddFileContextToZip007"); | ||
| 950 | + std::string inZip("dlp_general_info"); | ||
| 951 | + std::string zipFile("test_zip"); | ||
| 952 | + | ||
| 953 | + int32_t fd = open(zipFile.c_str(), O_RDWR | O_CREAT, 0666); | ||
| 954 | + ASSERT_NE(fd, -1); | ||
| 955 | + int32_t fd2 = open(inZip.c_str(), O_RDWR | O_CREAT, 0666); | ||
| 956 | + ASSERT_NE(fd2, -1); | ||
| 957 | + std::string data = "123"; | ||
| 958 | + write(fd2, data.c_str(), data.size()); | ||
| 959 | + lseek(fd2, 0, SEEK_SET); | ||
| 960 | + | ||
| 961 | + // zipOpenNewFileInZip3_64 fails | ||
| 962 | + DlpCMockCondition condition; | ||
| 963 | + condition.mockSequence = { true }; | ||
| 964 | + SetMockConditions("zipOpenNewFileInZip3_64", condition); | ||
| 965 | + ASSERT_EQ(DLP_ZIP_FAIL, AddFileContextToZip(fd2, inZip.c_str(), zipFile.c_str())); | ||
| 966 | + CleanMockConditions(); | ||
| 967 | + | ||
| 968 | + // zipWriteInFileInZip fails inside the read loop | ||
| 969 | + lseek(fd2, 0, SEEK_SET); | ||
| 970 | + condition.mockSequence = { true }; | ||
| 971 | + SetMockConditions("zipWriteInFileInZip", condition); | ||
| 972 | + ASSERT_EQ(DLP_ZIP_FAIL, AddFileContextToZip(fd2, inZip.c_str(), zipFile.c_str())); | ||
| 973 | + CleanMockConditions(); | ||
| 974 | + | ||
| 975 | + // zipCloseFileInZip fails | ||
| 976 | + lseek(fd2, 0, SEEK_SET); | ||
| 977 | + condition.mockSequence = { true }; | ||
| 978 | + SetMockConditions("zipCloseFileInZip", condition); | ||
| 979 | + SetMockCallback("zipCloseFileInZip", reinterpret_cast<CommonMockFuncT>(ZipCloseFileInZipReply)); | ||
| 980 | + ASSERT_EQ(DLP_ZIP_FAIL, AddFileContextToZip(fd2, inZip.c_str(), zipFile.c_str())); | ||
| 981 | + CleanMockConditions(); | ||
| 982 | + | ||
| 983 | + // zipClose fails | ||
| 984 | + lseek(fd2, 0, SEEK_SET); | ||
| 985 | + condition.mockSequence = { true }; | ||
| 986 | + SetMockConditions("zipClose", condition); | ||
| 987 | + SetMockCallback("zipClose", reinterpret_cast<CommonMockFuncT>(ZipCloseReply)); | ||
| 988 | + ASSERT_EQ(DLP_ZIP_FAIL, AddFileContextToZip(fd2, inZip.c_str(), zipFile.c_str())); | ||
| 989 | + CleanMockConditions(); | ||
| 990 | + | ||
| 991 | + CloseAndUnlink(fd, inZip.c_str()); | ||
| 992 | + CloseAndUnlink(fd2, zipFile.c_str()); | ||
| 993 | +} | ||
| 994 | + | ||
| 995 | +/** | ||
| 996 | + * @tc.name: CheckUnzipFileInfo005 | ||
| 997 | + * @tc.desc: cover unzGetGlobalInfo64 fail, file count mismatch and entry name mismatch branches | ||
| 998 | + * @tc.type: FUNC | ||
| 999 | + * @tc.require: | ||
| 1000 | + */ | ||
| 1001 | +HWTEST_F(DlpZipTest, CheckUnzipFileInfo005, TestSize.Level0) | ||
| 1002 | +{ | ||
| 1003 | + DLP_LOG_INFO(LABEL, "CheckUnzipFileInfo005"); | ||
| 1004 | + | ||
| 1005 | + std::string inZipInfo("dlp_general_info"); | ||
| 1006 | + std::string zipFile("test_zip"); | ||
| 1007 | + | ||
| 1008 | + int32_t fd = open(zipFile.c_str(), O_RDWR | O_CREAT, 0666); | ||
| 1009 | + ASSERT_NE(fd, -1); | ||
| 1010 | + int32_t fd1 = open(inZipInfo.c_str(), O_RDWR | O_CREAT, 0666); | ||
| 1011 | + ASSERT_NE(fd1, -1); | ||
| 1012 | + std::string data = "123"; | ||
| 1013 | + write(fd1, data.c_str(), data.size()); | ||
| 1014 | + lseek(fd1, 0, SEEK_SET); | ||
| 1015 | + ASSERT_EQ(DLP_ZIP_OK, AddFileContextToZip(fd1, inZipInfo.c_str(), zipFile.c_str())); | ||
| 1016 | + ASSERT_EQ(true, IsZipFile(fd)); | ||
| 1017 | + | ||
| 1018 | + // unzGetGlobalInfo64 fails: return false | ||
| 1019 | + DlpCMockCondition condition; | ||
| 1020 | + condition.mockSequence = { true }; | ||
| 1021 | + SetMockConditions("unzGetGlobalInfo64", condition); | ||
| 1022 | + ASSERT_EQ(false, CheckUnzipFileInfo(fd)); | ||
| 1023 | + CleanMockConditions(); | ||
| 1024 | + | ||
| 1025 | + // single entry zip: number_entry != FILE_COUNT, return false | ||
| 1026 | + ASSERT_EQ(false, CheckUnzipFileInfo(fd)); | ||
| 1027 | + | ||
| 1028 | + CloseAndUnlink(fd, zipFile.c_str()); | ||
| 1029 | + CloseAndUnlink(fd1, inZipInfo.c_str()); | ||
| 1030 | +} | ||
| 1031 | + | ||
| 1032 | +/** | ||
| 1033 | + * @tc.name: CheckUnzipFileInfo006 | ||
| 1034 | + * @tc.desc: cover entry name not in FILE_NAME_SET branch of CheckSingleFileEntry | ||
| 1035 | + * @tc.type: FUNC | ||
| 1036 | + * @tc.require: | ||
| 1037 | + */ | ||
| 1038 | +HWTEST_F(DlpZipTest, CheckUnzipFileInfo006, TestSize.Level0) | ||
| 1039 | +{ | ||
| 1040 | + DLP_LOG_INFO(LABEL, "CheckUnzipFileInfo006"); | ||
| 1041 | + | ||
| 1042 | + // build a zip with 3 entries where the second one has an unknown name | ||
| 1043 | + std::string inZipInfo("dlp_general_info"); | ||
| 1044 | + std::string inZipWrong("wrong_name"); | ||
| 1045 | + std::string inZipData("encrypted_data"); | ||
| 1046 | + std::string zipFile("test_zip"); | ||
| 1047 | + | ||
| 1048 | + int32_t fd = open(zipFile.c_str(), O_RDWR | O_CREAT, 0666); | ||
| 1049 | + ASSERT_NE(fd, -1); | ||
| 1050 | + int32_t fd1 = open(inZipInfo.c_str(), O_RDWR | O_CREAT, 0666); | ||
| 1051 | + ASSERT_NE(fd1, -1); | ||
| 1052 | + int32_t fd2 = open(inZipWrong.c_str(), O_RDWR | O_CREAT, 0666); | ||
| 1053 | + ASSERT_NE(fd2, -1); | ||
| 1054 | + int32_t fd3 = open(inZipData.c_str(), O_RDWR | O_CREAT, 0666); | ||
| 1055 | + ASSERT_NE(fd3, -1); | ||
| 1056 | + ASSERT_EQ(DLP_ZIP_OK, AddFileContextToZip(fd1, inZipInfo.c_str(), zipFile.c_str())); | ||
| 1057 | + ASSERT_EQ(DLP_ZIP_OK, AddFileContextToZip(fd2, inZipWrong.c_str(), zipFile.c_str())); | ||
| 1058 | + ASSERT_EQ(DLP_ZIP_OK, AddFileContextToZip(fd3, inZipData.c_str(), zipFile.c_str())); | ||
| 1059 | + ASSERT_EQ(true, IsZipFile(fd)); | ||
| 1060 | + | ||
| 1061 | + // the second entry name is not in FILE_NAME_SET: CheckSingleFileEntry returns false | ||
| 1062 | + ASSERT_EQ(false, CheckUnzipFileInfo(fd)); | ||
| 1063 | + | ||
| 1064 | + CloseAndUnlink(fd, zipFile.c_str()); | ||
| 1065 | + CloseAndUnlink(fd1, inZipInfo.c_str()); | ||
| 1066 | + CloseAndUnlink(fd2, inZipWrong.c_str()); | ||
| 1067 | + CloseAndUnlink(fd3, inZipData.c_str()); | ||
| 1068 | +} | ||
| 1069 | + | ||
| 1070 | +/** | ||
| 1071 | + * @tc.name: CheckUnzipFileInfo007 | ||
| 1072 | + * @tc.desc: cover compressed_size < uncompressed_size branch of CheckSingleFileEntry | ||
| 1073 | + * @tc.type: FUNC | ||
| 1074 | + * @tc.require: | ||
| 1075 | + */ | ||
| 1076 | +HWTEST_F(DlpZipTest, CheckUnzipFileInfo007, TestSize.Level0) | ||
| 1077 | +{ | ||
| 1078 | + DLP_LOG_INFO(LABEL, "CheckUnzipFileInfo007"); | ||
| 1079 | + | ||
| 1080 | + // build a zip with the 3 valid dlp entries | ||
| 1081 | + std::string inZipInfo("dlp_general_info"); | ||
| 1082 | + std::string inZipCert("dlp_cert"); | ||
| 1083 | + std::string inZipData("encrypted_data"); | ||
| 1084 | + std::string zipFile("test_zip"); | ||
| 1085 | + | ||
| 1086 | + int32_t fd = open(zipFile.c_str(), O_RDWR | O_CREAT, 0666); | ||
| 1087 | + ASSERT_NE(fd, -1); | ||
| 1088 | + int32_t fd1 = open(inZipInfo.c_str(), O_RDWR | O_CREAT, 0666); | ||
| 1089 | + ASSERT_NE(fd1, -1); | ||
| 1090 | + int32_t fd2 = open(inZipCert.c_str(), O_RDWR | O_CREAT, 0666); | ||
| 1091 | + ASSERT_NE(fd2, -1); | ||
| 1092 | + int32_t fd3 = open(inZipData.c_str(), O_RDWR | O_CREAT, 0666); | ||
| 1093 | + ASSERT_NE(fd3, -1); | ||
| 1094 | + ASSERT_EQ(DLP_ZIP_OK, AddFileContextToZip(fd1, inZipInfo.c_str(), zipFile.c_str())); | ||
| 1095 | + ASSERT_EQ(DLP_ZIP_OK, AddFileContextToZip(fd2, inZipCert.c_str(), zipFile.c_str())); | ||
| 1096 | + ASSERT_EQ(DLP_ZIP_OK, AddFileContextToZip(fd3, inZipData.c_str(), zipFile.c_str())); | ||
| 1097 | + ASSERT_EQ(true, IsZipFile(fd)); | ||
| 1098 | + | ||
| 1099 | + // unzGetCurrentFileInfo64 reports compressed_size < uncompressed_size: size check fails | ||
| 1100 | + DlpCMockCondition condition; | ||
| 1101 | + condition.mockSequence = { true }; | ||
| 1102 | + SetMockConditions("unzGetCurrentFileInfo64", condition); | ||
| 1103 | + SetMockCallback("unzGetCurrentFileInfo64", | ||
| 1104 | + reinterpret_cast<CommonMockFuncT>(UnzGetFileInfoSizeReply)); | ||
| 1105 | + ASSERT_EQ(false, CheckUnzipFileInfo(fd)); | ||
| 1106 | + CleanMockConditions(); | ||
| 1107 | + | ||
| 1108 | + // unzGetCurrentFileInfo64 fails directly: return false | ||
| 1109 | + condition.mockSequence = { true }; | ||
| 1110 | + SetMockConditions("unzGetCurrentFileInfo64", condition); | ||
| 1111 | + ASSERT_EQ(false, CheckUnzipFileInfo(fd)); | ||
| 1112 | + CleanMockConditions(); | ||
| 1113 | + | ||
| 1114 | + CloseAndUnlink(fd, zipFile.c_str()); | ||
| 1115 | + CloseAndUnlink(fd1, inZipInfo.c_str()); | ||
| 1116 | + CloseAndUnlink(fd2, inZipCert.c_str()); | ||
| 1117 | + CloseAndUnlink(fd3, inZipData.c_str()); | ||
| 1118 | +} | ||
| 1119 | + | ||
| 1120 | +/** | ||
| 1121 | + * @tc.name: UnzipSpecificFile005 | ||
| 1122 | + * @tc.desc: cover unzCloseCurrentFile fail and unzClose fail branches | ||
| 1123 | + * @tc.type: FUNC | ||
| 1124 | + * @tc.require: | ||
| 1125 | + */ | ||
| 1126 | +HWTEST_F(DlpZipTest, UnzipSpecificFile005, TestSize.Level0) | ||
| 1127 | +{ | ||
| 1128 | + DLP_LOG_INFO(LABEL, "UnzipSpecificFile005"); | ||
| 1129 | + | ||
| 1130 | + std::string inZipInfo("dlp_general_info"); | ||
| 1131 | + std::string zipFile("test_zip"); | ||
| 1132 | + std::string unZip("unzip"); | ||
| 1133 | + | ||
| 1134 | + int32_t fd = open(zipFile.c_str(), O_RDWR | O_CREAT, 0666); | ||
| 1135 | + ASSERT_NE(fd, -1); | ||
| 1136 | + int32_t fd1 = open(inZipInfo.c_str(), O_RDWR | O_CREAT, 0666); | ||
| 1137 | + ASSERT_NE(fd1, -1); | ||
| 1138 | + std::string data = "123"; | ||
| 1139 | + write(fd1, data.c_str(), data.size()); | ||
| 1140 | + lseek(fd1, 0, SEEK_SET); | ||
| 1141 | + ASSERT_EQ(DLP_ZIP_OK, AddFileContextToZip(fd1, inZipInfo.c_str(), zipFile.c_str())); | ||
| 1142 | + ASSERT_EQ(true, IsZipFile(fd)); | ||
| 1143 | + | ||
| 1144 | + // unzLocateFile fails: return DLP_ZIP_FAIL | ||
| 1145 | + DlpCMockCondition condition; | ||
| 1146 | + condition.mockSequence = { true }; | ||
| 1147 | + SetMockConditions("unzLocateFile", condition); | ||
| 1148 | + ASSERT_EQ(DLP_ZIP_FAIL, UnzipSpecificFile(fd, inZipInfo.c_str(), unZip.c_str())); | ||
| 1149 | + CleanMockConditions(); | ||
| 1150 | + | ||
| 1151 | + // unzOpenCurrentFile fails: return DLP_ZIP_FAIL | ||
| 1152 | + condition.mockSequence = { true }; | ||
| 1153 | + SetMockConditions("unzOpenCurrentFile", condition); | ||
| 1154 | + ASSERT_EQ(DLP_ZIP_FAIL, UnzipSpecificFile(fd, inZipInfo.c_str(), unZip.c_str())); | ||
| 1155 | + CleanMockConditions(); | ||
| 1156 | + | ||
| 1157 | + // unzReadCurrentFile fails: WriteUnzipFileContent records the error and returns DLP_ZIP_FAIL | ||
| 1158 | + condition.mockSequence = { true }; | ||
| 1159 | + SetMockConditions("unzReadCurrentFile", condition); | ||
| 1160 | + ASSERT_EQ(DLP_ZIP_FAIL, UnzipSpecificFile(fd, inZipInfo.c_str(), unZip.c_str())); | ||
| 1161 | + CleanMockConditions(); | ||
| 1162 | + | ||
| 1163 | + // unzCloseCurrentFile fails: only logs, res stays DLP_ZIP_OK | ||
| 1164 | + condition.mockSequence = { true }; | ||
| 1165 | + SetMockConditions("unzCloseCurrentFile", condition); | ||
| 1166 | + SetMockCallback("unzCloseCurrentFile", | ||
| 1167 | + reinterpret_cast<CommonMockFuncT>(UnzCloseCurrentFileReply)); | ||
| 1168 | + ASSERT_EQ(DLP_ZIP_OK, UnzipSpecificFile(fd, inZipInfo.c_str(), unZip.c_str())); | ||
| 1169 | + CleanMockConditions(); | ||
| 1170 | + | ||
| 1171 | + // unzClose fails: return DLP_ZIP_FAIL | ||
| 1172 | + condition.mockSequence = { true }; | ||
| 1173 | + SetMockConditions("unzClose", condition); | ||
| 1174 | + SetMockCallback("unzClose", reinterpret_cast<CommonMockFuncT>(UnzCloseReply)); | ||
| 1175 | + ASSERT_EQ(DLP_ZIP_FAIL, UnzipSpecificFile(fd, inZipInfo.c_str(), unZip.c_str())); | ||
| 1176 | + CleanMockConditions(); | ||
| 1177 | + | ||
| 1178 | + CloseAndUnlink(fd, zipFile.c_str()); | ||
| 1179 | + CloseAndUnlink(fd1, inZipInfo.c_str()); | ||
| 1180 | + unlink(unZip.c_str()); | ||
| 1181 | +} | ||
| 1182 | + | ||
| 1183 | +/** | ||
| 1184 | + * @tc.name: UnzipSpecificFile006 | ||
| 1185 | + * @tc.desc: cover OpenZipFile fail branch of UnzipSpecificFile | ||
| 1186 | + * @tc.type: FUNC | ||
| 1187 | + * @tc.require: | ||
| 1188 | + */ | ||
| 1189 | +HWTEST_F(DlpZipTest, UnzipSpecificFile006, TestSize.Level0) | ||
| 1190 | +{ | ||
| 1191 | + DLP_LOG_INFO(LABEL, "UnzipSpecificFile006"); | ||
| 1192 | + | ||
| 1193 | + std::string inZipInfo("dlp_general_info"); | ||
| 1194 | + std::string unZip("unzip"); | ||
| 1195 | + | ||
| 1196 | + // unzOpen2 fails: OpenZipFile returns nullptr and UnzipSpecificFile fails | ||
| 1197 | + DlpCMockCondition condition; | ||
| 1198 | + condition.mockSequence = { true }; | ||
| 1199 | + SetMockConditions("unzOpen2", condition); | ||
| 1200 | + ASSERT_EQ(DLP_ZIP_FAIL, UnzipSpecificFile(-1, inZipInfo.c_str(), unZip.c_str())); | ||
| 1201 | + CleanMockConditions(); | ||
| 1202 | + unlink(unZip.c_str()); | ||
| 838 | } | 1203 | } |
| @@ -0,0 +1,86 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | +extern "C" { | ||
| 23 | + | ||
| 24 | + | ||
| 25 | +/* | ||
| 26 | + * Failure-injection mock for the HUKS APIs used by huks_adapt_manager.cpp. | ||
| 27 | + * Enable a mock with SetMockConditions("HksXxx", condition); the mocked call | ||
| 28 | + * then returns HKS_FAILURE (no-op for void functions). When not mocked, the | ||
| 29 | + * call returns HKS_SUCCESS directly without touching the real HUKS service, | ||
| 30 | + * so the dedicated failure-injection test target does not depend on real | ||
| 31 | + * huks key storage. Success paths of huks_adapt_manager.cpp are covered by | ||
| 32 | + * huks_adapt_manager_test.cpp with the real libhukssdk. | ||
| 33 | + */ | ||
| 34 | + | ||
| 35 | +int32_t HksInitParamSet(struct HksParamSet **) | ||
| 36 | +{ | ||
| 37 | + return IsFuncNeedMock("HksInitParamSet") ? HKS_FAILURE : HKS_SUCCESS; | ||
| 38 | +} | ||
| 39 | + | ||
| 40 | +int32_t HksAddParams(struct HksParamSet *, const struct HksParam *, uint32_t) | ||
| 41 | +{ | ||
| 42 | + return IsFuncNeedMock("HksAddParams") ? HKS_FAILURE : HKS_SUCCESS; | ||
| 43 | +} | ||
| 44 | + | ||
| 45 | +int32_t HksBuildParamSet(struct HksParamSet **) | ||
| 46 | +{ | ||
| 47 | + return IsFuncNeedMock("HksBuildParamSet") ? HKS_FAILURE : HKS_SUCCESS; | ||
| 48 | +} | ||
| 49 | + | ||
| 50 | +void HksFreeParamSet(struct HksParamSet **) | ||
| 51 | +{ | ||
| 52 | + (void)IsFuncNeedMock("HksFreeParamSet"); | ||
| 53 | +} | ||
| 54 | + | ||
| 55 | +int32_t HksGenerateKey(const struct HksBlob *, const struct HksParamSet *, struct HksParamSet *) | ||
| 56 | +{ | ||
| 57 | + return IsFuncNeedMock("HksGenerateKey") ? HKS_FAILURE : HKS_SUCCESS; | ||
| 58 | +} | ||
| 59 | + | ||
| 60 | +int32_t HksKeyExist(const struct HksBlob *, const struct HksParamSet *) | ||
| 61 | +{ | ||
| 62 | + return IsFuncNeedMock("HksKeyExist") ? HKS_FAILURE : HKS_SUCCESS; | ||
| 63 | +} | ||
| 64 | + | ||
| 65 | +int32_t HksInit(const struct HksBlob *, const struct HksParamSet *, struct HksBlob *, struct HksBlob *) | ||
| 66 | +{ | ||
| 67 | + return IsFuncNeedMock("HksInit") ? HKS_FAILURE : HKS_SUCCESS; | ||
| 68 | +} | ||
| 69 | + | ||
| 70 | +int32_t HksUpdate(const struct HksBlob *, const struct HksParamSet *, const struct HksBlob *, struct HksBlob *) | ||
| 71 | +{ | ||
| 72 | + return IsFuncNeedMock("HksUpdate") ? HKS_FAILURE : HKS_SUCCESS; | ||
| 73 | +} | ||
| 74 | + | ||
| 75 | +int32_t HksFinish(const struct HksBlob *, const struct HksParamSet *, const struct HksBlob *, struct HksBlob *) | ||
| 76 | +{ | ||
| 77 | + return IsFuncNeedMock("HksFinish") ? HKS_FAILURE : HKS_SUCCESS; | ||
| 78 | +} | ||
| 79 | + | ||
| 80 | +int32_t HksAbort(const struct HksBlob *, const struct HksParamSet *) | ||
| 81 | +{ | ||
| 82 | + return IsFuncNeedMock("HksAbort") ? HKS_FAILURE : HKS_SUCCESS; | ||
| 83 | +} | ||
| 84 | + | ||
| 85 | +} | ||
| 86 | + | ||
| @@ -17,6 +17,7 @@ | |||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | + | ||
| 20 | 21 | ||
| 21 | 22 | ||
| 22 | 23 | ||
| @@ -410,6 +411,52 @@ int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s) | |||
| 410 | } | 411 | } |
| 411 | return (*func)(ctx, md, s); | 412 | return (*func)(ctx, md, s); |
| 412 | } | 413 | } |
| 414 | + | ||
| 415 | +typedef int (*HmacInitExFunc)(HMAC_CTX *ctx, const void *key, int key_len, const EVP_MD *md, ENGINE *impl); | ||
| 416 | +typedef int (*HmacFinalFunc)(HMAC_CTX *ctx, unsigned char *md, unsigned int *len); | ||
| 417 | +typedef int (*HmacUpdateFunc)(HMAC_CTX *ctx, const unsigned char *data, size_t len); | ||
| 418 | + | ||
| 419 | +int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int key_len, const EVP_MD *md, ENGINE *impl) | ||
| 420 | +{ | ||
| 421 | + if (IsFuncNeedMock("HMAC_Init_ex")) { | ||
| 422 | + return -1; | ||
| 423 | + } | ||
| 424 | + | ||
| 425 | + HmacInitExFunc func = | ||
| 426 | + reinterpret_cast<HmacInitExFunc>(GetOpensslLibFunc("HMAC_Init_ex")); | ||
| 427 | + if (func == nullptr) { | ||
| 428 | + return -1; | ||
| 429 | + } | ||
| 430 | + return (*func)(ctx, key, key_len, md, impl); | ||
| 431 | +} | ||
| 432 | + | ||
| 433 | +int HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len) | ||
| 434 | +{ | ||
| 435 | + if (IsFuncNeedMock("HMAC_Update")) { | ||
| 436 | + return -1; | ||
| 437 | + } | ||
| 438 | + | ||
| 439 | + HmacUpdateFunc func = | ||
| 440 | + reinterpret_cast<HmacUpdateFunc>(GetOpensslLibFunc("HMAC_Update")); | ||
| 441 | + if (func == nullptr) { | ||
| 442 | + return -1; | ||
| 443 | + } | ||
| 444 | + return (*func)(ctx, data, len); | ||
| 445 | +} | ||
| 446 | + | ||
| 447 | +int HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len) | ||
| 448 | +{ | ||
| 449 | + if (IsFuncNeedMock("HMAC_Final")) { | ||
| 450 | + return -1; | ||
| 451 | + } | ||
| 452 | + | ||
| 453 | + HmacFinalFunc func = | ||
| 454 | + reinterpret_cast<HmacFinalFunc>(GetOpensslLibFunc("HMAC_Final")); | ||
| 455 | + if (func == nullptr) { | ||
| 456 | + return -1; | ||
| 457 | + } | ||
| 458 | + return (*func)(ctx, md, len); | ||
| 459 | +} | ||
| 413 | 460 | ||
| 414 | } | 461 | } |
| 415 | 462 | ||
| @@ -23,6 +23,8 @@ | |||
| 23 | 23 | ||
| 24 | 24 | ||
| 25 | 25 | ||
| 26 | + | ||
| 27 | + | ||
| 26 | 28 | ||
| 27 | using namespace testing::ext; | 29 | using namespace testing::ext; |
| 28 | using namespace OHOS; | 30 | using namespace OHOS; |
| @@ -69,6 +71,16 @@ private: | |||
| 69 | std::vector<RunningProcessInfo> infoVec_; | 71 | std::vector<RunningProcessInfo> infoVec_; |
| 70 | }; | 72 | }; |
| 71 | 73 | ||
| 74 | +class MockAppMgrProxyFail final : public AppExecFwk::AppMgrProxy { | ||
| 75 | +public: | ||
| 76 | + MockAppMgrProxyFail() : AppExecFwk::AppMgrProxy(nullptr) {} | ||
| 77 | + | ||
| 78 | + int32_t GetAllRunningProcesses(std::vector<RunningProcessInfo>& infoVec) override | ||
| 79 | + { | ||
| 80 | + return 1; // not ERR_OK | ||
| 81 | + } | ||
| 82 | +}; | ||
| 83 | + | ||
| 72 | static RunningProcessInfo MakeRunningProcessInfo(int32_t uid, const std::string& processName, | 84 | static RunningProcessInfo MakeRunningProcessInfo(int32_t uid, const std::string& processName, |
| 73 | AppExecFwk::AppProcessState state, int32_t pid) | 85 | AppExecFwk::AppProcessState state, int32_t pid) |
| 74 | { | 86 | { |
| @@ -131,6 +143,56 @@ static DlpSandboxInfo MakeEnterpriseSandboxInfo(const EnterpriseSandboxSpec& spe | |||
| 131 | }; | 143 | }; |
| 132 | } | 144 | } |
| 133 | 145 | ||
| 146 | +/* | ||
| 147 | + * Link-time interposition stubs for the account APIs used by app_state_observer.cpp, | ||
| 148 | + * with the same technique as the OsAccountManager::GetOsAccountLocalIdFromUid stub | ||
| 149 | + * defined in dlp_permission_service_test.cpp (the definition in the test binary | ||
| 150 | + * preempts the shared library one). Defaults keep the on-device behavior so | ||
| 151 | + * existing tests are unaffected; DecMaskInfoCnt002 flips the flag temporarily. | ||
| 152 | + * Note: only static member functions can be interposed this way. Virtual ones | ||
| 153 | + * (e.g. OhosAccountKits::QueryOhosAccountInfo) are dispatched through the vtable | ||
| 154 | + * of the SDK-internal derived object and cannot be preempted, so they must not | ||
| 155 | + * be stubbed here. | ||
| 156 | + */ | ||
| 157 | +namespace OHOS { | ||
| 158 | +namespace AccountSA { | ||
| 159 | +bool g_foregroundAccountQueryOk = true; // real query succeeds on device; ext-branch tests flip it | ||
| 160 | +static const int32_t FOREGROUND_OS_ACCOUNT_ID = 100; // same as on device | ||
| 161 | + | ||
| 162 | +int OsAccountManager::GetForegroundOsAccountLocalId(int32_t &localId) | ||
| 163 | +{ | ||
| 164 | + localId = FOREGROUND_OS_ACCOUNT_ID; | ||
| 165 | + return g_foregroundAccountQueryOk ? 0 : 1; | ||
| 166 | +} | ||
| 167 | +} // namespace AccountSA | ||
| 168 | +} // namespace OHOS | ||
| 169 | + | ||
| 170 | +/* | ||
| 171 | + * Link-time interposition stubs for the common event APIs used by | ||
| 172 | + * app_uninstall_observer.cpp, with the same technique as the account stubs | ||
| 173 | + * above (the definition in the test binary preempts the shared library one). | ||
| 174 | + * The default keeps the on-device behavior (subscription succeeds), so | ||
| 175 | + * existing tests are unaffected; the DlpEventSubSubscriber case flips the | ||
| 176 | + * flag temporarily to cover the failure branch. | ||
| 177 | + */ | ||
| 178 | +namespace OHOS { | ||
| 179 | +namespace EventFwk { | ||
| 180 | +static bool g_subscribeCommonEventRet = true; // real subscription succeeds on device | ||
| 181 | + | ||
| 182 | +bool CommonEventManager::SubscribeCommonEvent(const std::shared_ptr<CommonEventSubscriber>& subscriber) | ||
| 183 | +{ | ||
| 184 | + (void)subscriber; | ||
| 185 | + return g_subscribeCommonEventRet; | ||
| 186 | +} | ||
| 187 | + | ||
| 188 | +bool CommonEventManager::UnSubscribeCommonEvent(const std::shared_ptr<CommonEventSubscriber>& subscriber) | ||
| 189 | +{ | ||
| 190 | + (void)subscriber; | ||
| 191 | + return true; | ||
| 192 | +} | ||
| 193 | +} // namespace EventFwk | ||
| 194 | +} // namespace OHOS | ||
| 195 | + | ||
| 134 | void AppStateObserverTest::SetUpTestCase() {} | 196 | void AppStateObserverTest::SetUpTestCase() {} |
| 135 | 197 | ||
| 136 | void AppStateObserverTest::TearDownTestCase() {} | 198 | void AppStateObserverTest::TearDownTestCase() {} |
| @@ -2102,4 +2164,369 @@ HWTEST_F(AppStateObserverTest, GetEnterpriseFileIdsByUid005, TestSize.Level1) | |||
| 2102 | ASSERT_EQ(fileIds, "f2"); | 2164 | ASSERT_EQ(fileIds, "f2"); |
| 2103 | 2165 | ||
| 2104 | ASSERT_FALSE(observer.GetEnterpriseFileIdsByUid(999, fileIds)); | 2166 | ASSERT_FALSE(observer.GetEnterpriseFileIdsByUid(999, fileIds)); |
| 2167 | +} | ||
| 2168 | + | ||
| 2169 | +/** | ||
| 2170 | + * @tc.name: UninstallDlpSandboxTest003 | ||
| 2171 | + * @tc.desc: cover hipreview bind sandbox uninstall branch | ||
| 2172 | + * @tc.type: FUNC | ||
| 2173 | + * @tc.require: | ||
| 2174 | + */ | ||
| 2175 | +HWTEST_F(AppStateObserverTest, UninstallDlpSandboxTest003, TestSize.Level1) | ||
| 2176 | +{ | ||
| 2177 | + DLP_LOG_INFO(LABEL, "UninstallDlpSandboxTest003"); | ||
| 2178 | + | ||
| 2179 | + AppStateObserver observer; | ||
| 2180 | + DlpSandboxInfo appInfo = { | ||
| 2181 | + .uid = 1, | ||
| 2182 | + .userId = 123, | ||
| 2183 | + .appIndex = 2, | ||
| 2184 | + .bindAppIndex = 1001, | ||
| 2185 | + .tokenId = 100, | ||
| 2186 | + .bundleName = HIPREVIEW_HIGH | ||
| 2187 | + }; | ||
| 2188 | + // appIndex > 0, bindAppIndex > HIPREVIEW_SANDBOX_LOW_BOUND and bundleName is HIPREVIEW_HIGH | ||
| 2189 | + observer.UninstallDlpSandbox(appInfo); | ||
| 2190 | + ASSERT_EQ(appInfo.tokenId, 100); | ||
| 2191 | +} | ||
| 2192 | + | ||
| 2193 | +/** | ||
| 2194 | + * @tc.name: UninstallAllDlpSandboxForUser001 | ||
| 2195 | + * @tc.desc: cover matching and mismatching userId branches of UninstallAllDlpSandboxForUser | ||
| 2196 | + * @tc.type: FUNC | ||
| 2197 | + * @tc.require: | ||
| 2198 | + */ | ||
| 2199 | +HWTEST_F(AppStateObserverTest, UninstallAllDlpSandboxForUser001, TestSize.Level1) | ||
| 2200 | +{ | ||
| 2201 | + DLP_LOG_INFO(LABEL, "UninstallAllDlpSandboxForUser001"); | ||
| 2202 | + | ||
| 2203 | + AppStateObserver observer; | ||
| 2204 | + DlpSandboxInfo matchInfo = { | ||
| 2205 | + .uid = 1, | ||
| 2206 | + .userId = 123, | ||
| 2207 | + .appIndex = 2, | ||
| 2208 | + .tokenId = 100, | ||
| 2209 | + .bundleName = "testbundle1" | ||
| 2210 | + }; | ||
| 2211 | + observer.AddSandboxInfo(matchInfo); | ||
| 2212 | + DlpSandboxInfo mismatchInfo = { | ||
| 2213 | + .uid = 2, | ||
| 2214 | + .userId = 456, | ||
| 2215 | + .appIndex = 2, | ||
| 2216 | + .tokenId = 101, | ||
| 2217 | + .bundleName = "testbundle2" | ||
| 2218 | + }; | ||
| 2219 | + observer.AddSandboxInfo(mismatchInfo); | ||
| 2220 | + | ||
| 2221 | + // entry with the same userId is erased with callback, entry with another userId is kept | ||
| 2222 | + observer.UninstallAllDlpSandboxForUser(123); | ||
| 2223 | + ASSERT_EQ(observer.sandboxInfo_.size(), 1); | ||
| 2224 | + ASSERT_TRUE(observer.sandboxInfo_.count(2) > 0); | ||
| 2225 | +} | ||
| 2226 | + | ||
| 2227 | +/** | ||
| 2228 | + * @tc.name: AddDlpSandboxInfo002 | ||
| 2229 | + * @tc.desc: cover GetUserIdFromUid failed branch of AddDlpSandboxInfo | ||
| 2230 | + * @tc.type: FUNC | ||
| 2231 | + * @tc.require: | ||
| 2232 | + */ | ||
| 2233 | +HWTEST_F(AppStateObserverTest, AddDlpSandboxInfo002, TestSize.Level1) | ||
| 2234 | +{ | ||
| 2235 | + DLP_LOG_INFO(LABEL, "AddDlpSandboxInfo002"); | ||
| 2236 | + | ||
| 2237 | + AppStateObserver observer; | ||
| 2238 | + DlpSandboxInfo appInfo = { | ||
| 2239 | + .uid = INCORRECT_UID, | ||
| 2240 | + .userId = 100, | ||
| 2241 | + .appIndex = 2, | ||
| 2242 | + .tokenId = 100, | ||
| 2243 | + .bundleName = "testbundle1" | ||
| 2244 | + }; | ||
| 2245 | + // GetUserIdFromUid fails for INCORRECT_UID (stubbed in dlp_permission_service_test.cpp) | ||
| 2246 | + observer.AddDlpSandboxInfo(appInfo); | ||
| 2247 | + ASSERT_TRUE(observer.sandboxInfo_.empty()); | ||
| 2248 | + ASSERT_TRUE(observer.userIdList_.empty()); | ||
| 2249 | +} | ||
| 2250 | + | ||
| 2251 | +/** | ||
| 2252 | + * @tc.name: DecMaskInfoCnt002 | ||
| 2253 | + * @tc.desc: cover GetUserIdByForegroundAccount failed branch of DecMaskInfoCnt | ||
| 2254 | + * @tc.type: FUNC | ||
| 2255 | + * @tc.require: | ||
| 2256 | + */ | ||
| 2257 | +HWTEST_F(AppStateObserverTest, DecMaskInfoCnt002, TestSize.Level1) | ||
| 2258 | +{ | ||
| 2259 | + DLP_LOG_INFO(LABEL, "DecMaskInfoCnt002"); | ||
| 2260 | + | ||
| 2261 | + AppStateObserver observer; | ||
| 2262 | + DlpSandboxInfo appInfo; | ||
| 2263 | + appInfo.isWatermark = true; | ||
| 2264 | + | ||
| 2265 | + // GetUserIdByForegroundAccount fails (interposition stub) | ||
| 2266 | + OHOS::AccountSA::g_foregroundAccountQueryOk = false; | ||
| 2267 | + observer.DecMaskInfoCnt(appInfo); | ||
| 2268 | + OHOS::AccountSA::g_foregroundAccountQueryOk = true; | ||
| 2269 | + ASSERT_TRUE(observer.maskInfoMap_.empty()); | ||
| 2270 | +} | ||
| 2271 | + | ||
| 2272 | +/** | ||
| 2273 | + * @tc.name: GetRunningProcessesInfo002 | ||
| 2274 | + * @tc.desc: cover GetAllRunningProcesses failed branch of GetRunningProcessesInfo | ||
| 2275 | + * @tc.type: FUNC | ||
| 2276 | + * @tc.require: | ||
| 2277 | + */ | ||
| 2278 | +HWTEST_F(AppStateObserverTest, GetRunningProcessesInfo002, TestSize.Level1) | ||
| 2279 | +{ | ||
| 2280 | + DLP_LOG_INFO(LABEL, "GetRunningProcessesInfo002"); | ||
| 2281 | + | ||
| 2282 | + AppStateObserver observer; | ||
| 2283 | + std::vector<RunningProcessInfo> infoVec; | ||
| 2284 | + observer.SetAppProxy(new (std::nothrow) MockAppMgrProxyFail()); | ||
| 2285 | + | ||
| 2286 | + // GetAllRunningProcesses returns error | ||
| 2287 | + ASSERT_FALSE(observer.GetRunningProcessesInfo(infoVec)); | ||
| 2288 | + ASSERT_TRUE(infoVec.empty()); | ||
| 2289 | +} | ||
| 2290 | + | ||
| 2291 | +/** | ||
| 2292 | + * @tc.name: GetOpeningSandboxInfo003 | ||
| 2293 | + * @tc.desc: cover uri/fileId mismatch and full match branches of GetOpeningSandboxInfo | ||
| 2294 | + * @tc.type: FUNC | ||
| 2295 | + * @tc.require: | ||
| 2296 | + */ | ||
| 2297 | +HWTEST_F(AppStateObserverTest, GetOpeningSandboxInfo003, TestSize.Level1) | ||
| 2298 | +{ | ||
| 2299 | + DLP_LOG_INFO(LABEL, "GetOpeningSandboxInfo003"); | ||
| 2300 | + | ||
| 2301 | + AppStateObserver observer; | ||
| 2302 | + SandboxInfo sandboxInfo; | ||
| 2303 | + std::string bundleName = "testbundle1"; | ||
| 2304 | + int32_t userId = 100; | ||
| 2305 | + std::string uri = "uriB"; | ||
| 2306 | + std::string fileId = "f2"; | ||
| 2307 | + | ||
| 2308 | + // userId and bundleName match but uri differs: continue | ||
| 2309 | + DlpSandboxInfo uriMismatch = { | ||
| 2310 | + .uid = 1, | ||
| 2311 | + .userId = 100, | ||
| 2312 | + .appIndex = 2, | ||
| 2313 | + .tokenId = 11, | ||
| 2314 | + .bundleName = "testbundle1", | ||
| 2315 | + .uri = "uriA", | ||
| 2316 | + .fileId = "f2" | ||
| 2317 | + }; | ||
| 2318 | + observer.AddSandboxInfo(uriMismatch); | ||
| 2319 | + | ||
| 2320 | + // uri matches but fileId differs: continue | ||
| 2321 | + DlpSandboxInfo fileIdMismatch = { | ||
| 2322 | + .uid = 2, | ||
| 2323 | + .userId = 100, | ||
| 2324 | + .appIndex = 3, | ||
| 2325 | + .tokenId = 22, | ||
| 2326 | + .bundleName = "testbundle1", | ||
| 2327 | + .uri = "uriB", | ||
| 2328 | + .fileId = "wrong" | ||
| 2329 | + }; | ||
| 2330 | + observer.AddSandboxInfo(fileIdMismatch); | ||
| 2331 | + | ||
| 2332 | + // all fields match: FillSandboxInfoIfProcessRunning is called | ||
| 2333 | + DlpSandboxInfo fullMatch = { | ||
| 2334 | + .uid = 3, | ||
| 2335 | + .userId = 100, | ||
| 2336 | + .appIndex = 4, | ||
| 2337 | + .bindAppIndex = 5, | ||
| 2338 | + .tokenId = 33, | ||
| 2339 | + .bundleName = "testbundle1", | ||
| 2340 | + .uri = "uriB", | ||
| 2341 | + .fileId = "f2" | ||
| 2342 | + }; | ||
| 2343 | + observer.AddSandboxInfo(fullMatch); | ||
| 2344 | + | ||
| 2345 | + SetMockAppProxy(observer, { | ||
| 2346 | + MakeRunningProcessInfo(3, "testbundle1", AppExecFwk::AppProcessState::APP_STATE_FOREGROUND, 300), | ||
| 2347 | + }); | ||
| 2348 | + ASSERT_TRUE(observer.GetOpeningSandboxInfo(bundleName, uri, userId, sandboxInfo, fileId)); | ||
| 2349 | + ASSERT_EQ(sandboxInfo.appIndex, 4); | ||
| 2350 | + ASSERT_EQ(sandboxInfo.bindAppIndex, 5); | ||
| 2351 | + ASSERT_EQ(sandboxInfo.tokenId, 33); | ||
| 2352 | +} | ||
| 2353 | + | ||
| 2354 | +/** | ||
| 2355 | + * @tc.name: CanUninstallByGid001 | ||
| 2356 | + * @tc.desc: cover all branches of CanUninstallByGid | ||
| 2357 | + * @tc.type: FUNC | ||
| 2358 | + * @tc.require: | ||
| 2359 | + */ | ||
| 2360 | +HWTEST_F(AppStateObserverTest, CanUninstallByGid001, TestSize.Level1) | ||
| 2361 | +{ | ||
| 2362 | + DLP_LOG_INFO(LABEL, "CanUninstallByGid001"); | ||
| 2363 | + | ||
| 2364 | + AppStateObserver observer; | ||
| 2365 | + DlpSandboxInfo appInfo; | ||
| 2366 | + appInfo.uid = 100; | ||
| 2367 | + appInfo.bundleName = "testbundle1"; | ||
| 2368 | + OHOS::AppExecFwk::ProcessData processData; | ||
| 2369 | + processData.pid = 500; | ||
| 2370 | + | ||
| 2371 | + // uid mismatch or empty bundleNames: continue | ||
| 2372 | + RunningProcessInfo uidMismatch = MakeRunningProcessInfo( | ||
| 2373 | + 999, "other", AppExecFwk::AppProcessState::APP_STATE_FOREGROUND, 501); | ||
| 2374 | + RunningProcessInfo noBundle = MakeRunningProcessInfo( | ||
| 2375 | + 100, "other2", AppExecFwk::AppProcessState::APP_STATE_FOREGROUND, 502); | ||
| 2376 | + noBundle.bundleNames.clear(); | ||
| 2377 | + SetMockAppProxy(observer, {uidMismatch, noBundle}); | ||
| 2378 | + ASSERT_TRUE(observer.CanUninstallByGid(appInfo, processData)); | ||
| 2379 | + | ||
| 2380 | + // dead process with the same pid: log only, can uninstall | ||
| 2381 | + SetMockAppProxy(observer, { | ||
| 2382 | + MakeRunningProcessInfo(100, "testbundle1", AppExecFwk::AppProcessState::APP_STATE_END, 500), | ||
| 2383 | + }); | ||
| 2384 | + ASSERT_TRUE(observer.CanUninstallByGid(appInfo, processData)); | ||
| 2385 | + | ||
| 2386 | + // dead process with a different pid: can not uninstall | ||
| 2387 | + SetMockAppProxy(observer, { | ||
| 2388 | + MakeRunningProcessInfo(100, "testbundle1", AppExecFwk::AppProcessState::APP_STATE_TERMINATED, 779), | ||
| 2389 | + }); | ||
| 2390 | + ASSERT_FALSE(observer.CanUninstallByGid(appInfo, processData)); | ||
| 2391 | + | ||
| 2392 | + // running process with a different pid: can not uninstall | ||
| 2393 | + SetMockAppProxy(observer, { | ||
| 2394 | + MakeRunningProcessInfo(100, "testbundle1", AppExecFwk::AppProcessState::APP_STATE_FOREGROUND, 777), | ||
| 2395 | + }); | ||
| 2396 | + ASSERT_FALSE(observer.CanUninstallByGid(appInfo, processData)); | ||
| 2397 | + | ||
| 2398 | + // running process whose name contains "svr": can uninstall | ||
| 2399 | + RunningProcessInfo svrInfo = MakeRunningProcessInfo( | ||
| 2400 | + 100, "testbundle1", AppExecFwk::AppProcessState::APP_STATE_FOREGROUND, 778); | ||
| 2401 | + svrInfo.processName_ = "svr_testbundle1"; | ||
| 2402 | + SetMockAppProxy(observer, {svrInfo}); | ||
| 2403 | + ASSERT_TRUE(observer.CanUninstallByGid(appInfo, processData)); | ||
| 2404 | +} | ||
| 2405 | + | ||
| 2406 | +/** | ||
| 2407 | + * @tc.name: OnProcessDied005 | ||
| 2408 | + * @tc.desc: cover CanUninstallByGid false branch of OnProcessDied | ||
| 2409 | + * @tc.type: FUNC | ||
| 2410 | + * @tc.require: | ||
| 2411 | + */ | ||
| 2412 | +HWTEST_F(AppStateObserverTest, OnProcessDied005, TestSize.Level1) | ||
| 2413 | +{ | ||
| 2414 | + DLP_LOG_INFO(LABEL, "OnProcessDied005"); | ||
| 2415 | + | ||
| 2416 | + AppStateObserver observer; | ||
| 2417 | + DlpSandboxInfo appInfo = { | ||
| 2418 | + .uid = 600, | ||
| 2419 | + .userId = 100, | ||
| 2420 | + .appIndex = 2, | ||
| 2421 | + .tokenId = 600, | ||
| 2422 | + .bundleName = "testbundle1" | ||
| 2423 | + }; | ||
| 2424 | + observer.AddSandboxInfo(appInfo); | ||
| 2425 | + | ||
| 2426 | + // sandbox process is still running with a different pid: can not uninstall | ||
| 2427 | + SetMockAppProxy(observer, { | ||
| 2428 | + MakeRunningProcessInfo(600, "testbundle1", AppExecFwk::AppProcessState::APP_STATE_FOREGROUND, 777), | ||
| 2429 | + }); | ||
| 2430 | + | ||
| 2431 | + OHOS::AppExecFwk::ProcessData processData; | ||
| 2432 | + processData.bundleName = "testbundle1"; | ||
| 2433 | + processData.processName = "testbundle1"; | ||
| 2434 | + processData.uid = 600; | ||
| 2435 | + processData.pid = 888; | ||
| 2436 | + processData.renderUid = -1; | ||
| 2437 | + | ||
| 2438 | + observer.OnProcessDied(processData); | ||
| 2439 | + ASSERT_EQ(observer.sandboxInfo_.size(), 1); | ||
| 2440 | + ASSERT_TRUE(observer.sandboxInfo_.count(600) > 0); | ||
| 2441 | +} | ||
| 2442 | + | ||
| 2443 | +/** | ||
| 2444 | + * @tc.name: GetSandboxInfoByTokenId001 | ||
| 2445 | + * @tc.desc: cover sandbox info found branch of GetSandboxInfoByTokenId | ||
| 2446 | + * @tc.type: FUNC | ||
| 2447 | + * @tc.require: | ||
| 2448 | + */ | ||
| 2449 | +HWTEST_F(AppStateObserverTest, GetSandboxInfoByTokenId001, TestSize.Level1) | ||
| 2450 | +{ | ||
| 2451 | + DLP_LOG_INFO(LABEL, "GetSandboxInfoByTokenId001"); | ||
| 2452 | + | ||
| 2453 | + AppStateObserver observer; | ||
| 2454 | + observer.AddUidWithTokenId(700, 700); | ||
| 2455 | + DlpSandboxInfo appInfo = { | ||
| 2456 | + .uid = 700, | ||
| 2457 | + .userId = 100, | ||
| 2458 | + .appIndex = 2, | ||
| 2459 | + .tokenId = 700, | ||
| 2460 | + .bundleName = "testbundle1" | ||
| 2461 | + }; | ||
| 2462 | + observer.AddSandboxInfo(appInfo); | ||
| 2463 | + | ||
| 2464 | + // tokenId maps to uid and the sandbox info exists | ||
| 2465 | + DlpSandboxInfo result; | ||
| 2466 | + ASSERT_TRUE(observer.GetSandboxInfoByTokenId(700, result)); | ||
| 2467 | + ASSERT_EQ(result.uid, 700); | ||
| 2468 | + ASSERT_EQ(result.bundleName, "testbundle1"); | ||
| 2469 | +} | ||
| 2470 | + | ||
| 2471 | +/** | ||
| 2472 | + * @tc.name: AppUninstallObserver001 | ||
| 2473 | + * @tc.desc: cover HasRetentionSandboxInfo true branch of AppUninstallObserver OnReceiveEvent | ||
| 2474 | + * @tc.type: FUNC | ||
| 2475 | + * @tc.require: | ||
| 2476 | + */ | ||
| 2477 | +HWTEST_F(AppStateObserverTest, AppUninstallObserver001, TestSize.Level1) | ||
| 2478 | +{ | ||
| 2479 | + DLP_LOG_INFO(LABEL, "AppUninstallObserver001"); | ||
| 2480 | + | ||
| 2481 | + EventFwk::MatchingSkills matchingSkills; | ||
| 2482 | + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED); | ||
| 2483 | + EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills); | ||
| 2484 | + std::shared_ptr<AppUninstallObserver> observer = std::make_shared<AppUninstallObserver>(subscribeInfo); | ||
| 2485 | + | ||
| 2486 | + // add retention info into the RetentionFileManager singleton (GetUserIdByForegroundAccount returns 100) | ||
| 2487 | + RetentionInfo retentionInfo = { | ||
| 2488 | + .appIndex = 1, | ||
| 2489 | + .tokenId = 827819, | ||
| 2490 | + .bundleName = "testbundle_uninstall", | ||
| 2491 | + .dlpFileAccess = DLPFileAccess::CONTENT_EDIT, | ||
| 2492 | + .userId = DEFAULT_USERID | ||
| 2493 | + }; | ||
| 2494 | + ASSERT_EQ(DLP_OK, RetentionFileManager::GetInstance().AddSandboxInfo(retentionInfo)); | ||
| 2495 | + ASSERT_TRUE(RetentionFileManager::GetInstance().HasRetentionSandboxInfo("testbundle_uninstall")); | ||
| 2496 | + | ||
| 2497 | + // action matches and HasRetentionSandboxInfo returns true: RemoveRetentionState is called | ||
| 2498 | + EventFwk::CommonEventData data; | ||
| 2499 | + OHOS::AAFwk::Want want; | ||
| 2500 | + want.SetBundle("testbundle_uninstall"); | ||
| 2501 | + want.SetAction(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED); | ||
| 2502 | + data.SetWant(want); | ||
| 2503 | + observer->OnReceiveEvent(data); | ||
| 2504 | + | ||
| 2505 | + // retention state of the uninstalled bundle has been removed | ||
| 2506 | + ASSERT_FALSE(RetentionFileManager::GetInstance().HasRetentionSandboxInfo("testbundle_uninstall")); | ||
| 2507 | +} | ||
| 2508 | + | ||
| 2509 | +/** | ||
| 2510 | + * @tc.name: DlpEventSubSubscriber001 | ||
| 2511 | + * @tc.desc: cover subscribe failed and destructor unsubscribe branches of DlpEventSubSubscriber | ||
| 2512 | + * @tc.type: FUNC | ||
| 2513 | + * @tc.require: | ||
| 2514 | + */ | ||
| 2515 | +HWTEST_F(AppStateObserverTest, DlpEventSubSubscriber001, TestSize.Level1) | ||
| 2516 | +{ | ||
| 2517 | + DLP_LOG_INFO(LABEL, "DlpEventSubSubscriber001"); | ||
| 2518 | + | ||
| 2519 | + // SubscribeCommonEvent fails: subscriber_ is reset to nullptr | ||
| 2520 | + OHOS::EventFwk::g_subscribeCommonEventRet = false; | ||
| 2521 | + { | ||
| 2522 | + DlpEventSubSubscriber subscriber; | ||
| 2523 | + ASSERT_TRUE(subscriber.subscriber_ == nullptr); | ||
| 2524 | + } | ||
| 2525 | + OHOS::EventFwk::g_subscribeCommonEventRet = true; | ||
| 2526 | + | ||
| 2527 | + // SubscribeCommonEvent succeeds: subscriber_ is kept | ||
| 2528 | + { | ||
| 2529 | + DlpEventSubSubscriber subscriber; | ||
| 2530 | + ASSERT_TRUE(subscriber.subscriber_ != nullptr); | ||
| 2531 | + } // destructor calls UnSubscribeCommonEvent since subscriber_ is not nullptr | ||
| 2105 | } | 2532 | } |
| @@ -0,0 +1,146 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | +using namespace testing::ext; | ||
| 27 | +using namespace OHOS; | ||
| 28 | +using namespace OHOS::Security::DlpPermission; | ||
| 29 | +using namespace std; | ||
| 30 | + | ||
| 31 | +/* | ||
| 32 | + * Helper defined in test/unittest/sa/mock/dlp_os_account_mock.cpp, which is compiled into | ||
| 33 | + * this target together with the mock os_account headers (test/unittest/sa/mock precedes the | ||
| 34 | + * SDK include paths), so the foreground account query and the domain info of OsAccountInfo | ||
| 35 | + * are fully controlled by the mock. | ||
| 36 | + */ | ||
| 37 | +namespace OHOS { | ||
| 38 | +namespace Security { | ||
| 39 | +namespace DlpPermissionUnitTest { | ||
| 40 | +void SetForegroundOsAccountLocalIdRet(int32_t ret); | ||
| 41 | +} // namespace DlpPermissionUnitTest | ||
| 42 | +} // namespace Security | ||
| 43 | +} // namespace OHOS | ||
| 44 | + | ||
| 45 | +namespace { | ||
| 46 | +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { | ||
| 47 | + LOG_CORE, SECURITY_DOMAIN_DLP_PERMISSION, "DlpPermissionServiceExtBranchTest"}; | ||
| 48 | +static constexpr int32_t SA_ID_DLP_PERMISSION_SERVICE = 3521; | ||
| 49 | +static const int32_t FOREGROUND_QUERY_OK = 0; | ||
| 50 | +static const int32_t FOREGROUND_QUERY_FAIL = 1; | ||
| 51 | +static const uint32_t FEATURE_ENABLED = 1; | ||
| 52 | +static const uint32_t FEATURE_DISABLED = 0; | ||
| 53 | +static const std::string MDM_BUNDLE_NAME_KEY = "appId"; // aligned with dlp_permission_service_common.h | ||
| 54 | +static const std::string MDM_ENABLE_VALUE_KEY = "status"; // aligned with dlp_permission_service_common.h | ||
| 55 | +static const char* FEATURE_INFO_DATA_FILE_PATH = | ||
| 56 | + "/data/service/el1/public/dlp_permission_service/dlp_feature_info.txt"; | ||
| 57 | +static const std::string INVALID_FILE_CONTENT = "not_a_hmac_protected_file"; | ||
| 58 | +} | ||
| 59 | + | ||
| 60 | +void DlpPermissionServiceExtBranchTest::SetUpTestCase() {} | ||
| 61 | + | ||
| 62 | +void DlpPermissionServiceExtBranchTest::TearDownTestCase() {} | ||
| 63 | + | ||
| 64 | +void DlpPermissionServiceExtBranchTest::SetUp() | ||
| 65 | +{ | ||
| 66 | + if (service_ != nullptr) { | ||
| 67 | + return; | ||
| 68 | + } | ||
| 69 | + service_ = std::make_shared<DlpPermissionService>(SA_ID_DLP_PERMISSION_SERVICE, true); | ||
| 70 | + ASSERT_NE(nullptr, service_); | ||
| 71 | + service_->appStateObserver_ = new (std::nothrow) AppStateObserver(); | ||
| 72 | + ASSERT_TRUE(service_->appStateObserver_ != nullptr); | ||
| 73 | +} | ||
| 74 | + | ||
| 75 | +void DlpPermissionServiceExtBranchTest::TearDown() | ||
| 76 | +{ | ||
| 77 | + if (service_ != nullptr) { | ||
| 78 | + service_->appStateObserver_ = nullptr; | ||
| 79 | + } | ||
| 80 | + service_ = nullptr; | ||
| 81 | +} | ||
| 82 | + | ||
| 83 | +/** | ||
| 84 | + * @tc.name: CheckIfEnterpriseAccount001 | ||
| 85 | + * @tc.desc: cover GetForegroundOsAccountLocalId failed and enterprise account branches of | ||
| 86 | + * CheckIfEnterpriseAccount | ||
| 87 | + * @tc.type: FUNC | ||
| 88 | + * @tc.require: | ||
| 89 | + */ | ||
| 90 | +HWTEST_F(DlpPermissionServiceExtBranchTest, CheckIfEnterpriseAccount001, TestSize.Level1) | ||
| 91 | +{ | ||
| 92 | + DLP_LOG_INFO(LABEL, "CheckIfEnterpriseAccount001"); | ||
| 93 | + // mock domain info is non-empty: foreground account is an enterprise account | ||
| 94 | + int32_t ret = service_->CheckIfEnterpriseAccount(); | ||
| 95 | + ASSERT_EQ(DLP_OK, ret); | ||
| 96 | + | ||
| 97 | + // GetForegroundOsAccountLocalId fails (mock): return DLP_PARSE_ERROR_ACCOUNT_INVALID | ||
| 98 | + SetForegroundOsAccountLocalIdRet(FOREGROUND_QUERY_FAIL); | ||
| 99 | + ret = service_->CheckIfEnterpriseAccount(); | ||
| 100 | + SetForegroundOsAccountLocalIdRet(FOREGROUND_QUERY_OK); | ||
| 101 | + ASSERT_EQ(DLP_PARSE_ERROR_ACCOUNT_INVALID, ret); | ||
| 102 | +} | ||
| 103 | + | ||
| 104 | +/** | ||
| 105 | + * @tc.name: IsDlpFeatureProvidedByEnterprise001 | ||
| 106 | + * @tc.desc: cover feature info file branches of IsDLPFeatureProvided for an enterprise account | ||
| 107 | + * @tc.type: FUNC | ||
| 108 | + * @tc.require: | ||
| 109 | + */ | ||
| 110 | +HWTEST_F(DlpPermissionServiceExtBranchTest, IsDlpFeatureProvidedByEnterprise001, TestSize.Level1) | ||
| 111 | +{ | ||
| 112 | + DLP_LOG_INFO(LABEL, "IsDlpFeatureProvidedByEnterprise001"); | ||
| 113 | + bool isProvideDLPFeature = false; | ||
| 114 | + | ||
| 115 | + // feature info file does not exist: fall back to the system parameter (not "true") | ||
| 116 | + remove(FEATURE_INFO_DATA_FILE_PATH); | ||
| 117 | + int32_t ret = service_->IsDLPFeatureProvided(isProvideDLPFeature); | ||
| 118 | + ASSERT_EQ(DLP_OK, ret); | ||
| 119 | + ASSERT_FALSE(isProvideDLPFeature); | ||
| 120 | + | ||
| 121 | + // valid file with the feature enabled: dlpFeature == ENABLE_VALUE_TRUE | ||
| 122 | + unordered_json featureJson; | ||
| 123 | + featureJson[MDM_BUNDLE_NAME_KEY] = "app_stub"; | ||
| 124 | + featureJson[MDM_ENABLE_VALUE_KEY] = FEATURE_ENABLED; | ||
| 125 | + ASSERT_EQ(DLP_OK, DlpFeatureInfo::SaveDlpFeatureInfoToFile(featureJson)); | ||
| 126 | + ret = service_->IsDLPFeatureProvided(isProvideDLPFeature); | ||
| 127 | + ASSERT_EQ(DLP_OK, ret); | ||
| 128 | + ASSERT_TRUE(isProvideDLPFeature); | ||
| 129 | + | ||
| 130 | + // valid file with the feature disabled: dlpFeature != ENABLE_VALUE_TRUE | ||
| 131 | + featureJson[MDM_ENABLE_VALUE_KEY] = FEATURE_DISABLED; | ||
| 132 | + ASSERT_EQ(DLP_OK, DlpFeatureInfo::SaveDlpFeatureInfoToFile(featureJson)); | ||
| 133 | + ret = service_->IsDLPFeatureProvided(isProvideDLPFeature); | ||
| 134 | + ASSERT_EQ(DLP_OK, ret); | ||
| 135 | + ASSERT_FALSE(isProvideDLPFeature); | ||
| 136 | + | ||
| 137 | + // file exists but is not a valid hmac-protected file: GetDlpFeatureInfoFromFile fails | ||
| 138 | + FileOperator fileOperator; | ||
| 139 | + ASSERT_EQ(DLP_OK, fileOperator.InputFileByPathAndContent(FEATURE_INFO_DATA_FILE_PATH, INVALID_FILE_CONTENT)); | ||
| 140 | + ret = service_->IsDLPFeatureProvided(isProvideDLPFeature); | ||
| 141 | + ASSERT_EQ(DLP_OK, ret); | ||
| 142 | + ASSERT_FALSE(isProvideDLPFeature); | ||
| 143 | + | ||
| 144 | + // cleanup: keep the feature info file absent as before the case | ||
| 145 | + remove(FEATURE_INFO_DATA_FILE_PATH); | ||
| 146 | +} | ||
| @@ -0,0 +1,41 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | +namespace OHOS { | ||
| 27 | +namespace Security { | ||
| 28 | +namespace DlpPermission { | ||
| 29 | +class DlpPermissionServiceExtBranchTest : public testing::Test { | ||
| 30 | +public: | ||
| 31 | + static void SetUpTestCase(); | ||
| 32 | + static void TearDownTestCase(); | ||
| 33 | + void SetUp(); | ||
| 34 | + void TearDown(); | ||
| 35 | + | ||
| 36 | + std::shared_ptr<DlpPermissionService> service_ = nullptr; | ||
| 37 | +}; | ||
| 38 | +} // namespace DlpPermission | ||
| 39 | +} // namespace Security | ||
| 40 | +} // namespace OHOS | ||
| 41 | + | ||