From d9fdfeb4e6db447b413ea857fb3aa1295854f6fc Mon Sep 17 00:00:00 2001 From: GengYinzong Date: Tue, 11 Feb 2025 00:23:52 -0800 Subject: [PATCH] fix Signed-off-by: GengYinzong --- .../file_share/include/file_permission.h | 10 ++ .../native/file_share/src/file_permission.cpp | 43 +++++ .../js/file_share/fileshare_n_exporter.cpp | 53 ++++++ .../kits/js/file_share/fileshare_n_exporter.h | 2 + .../kits/js/file_share/grant_permissions.cpp | 151 ++++++++++++++++++ .../kits/js/file_share/grant_permissions.h | 1 + .../src/file_permission_test.cpp | 26 +++ 7 files changed, 286 insertions(+) diff --git a/interfaces/innerkits/native/file_share/include/file_permission.h b/interfaces/innerkits/native/file_share/include/file_permission.h index 407673abf..362b26660 100644 --- a/interfaces/innerkits/native/file_share/include/file_permission.h +++ b/interfaces/innerkits/native/file_share/include/file_permission.h @@ -47,6 +47,11 @@ enum PolicyErrorCode { PERMISSION_NOT_PERSISTED = 4, }; +enum PolicyType { + TEMPORARY_TYPE = 0, + PERSISTENT_TYPE = 1, +}; + struct UriPolicyInfo { string uri = ""; uint32_t mode = OperationMode::READ_MODE; @@ -75,6 +80,10 @@ public: deque &errorResults); static int32_t CheckPersistentPermission(const vector &uriPolicies, vector &errorResults); static string GetPathByPermission(const std::string &permission); + static int32_t CheckPathPermission(uint32_t tokenId, + const vector &uriPolicies, + int32_t policyType, + vector &errorResults); #ifdef SANDBOX_MANAGER private: static void ParseErrorResults(const vector &resultCodes, @@ -88,6 +97,7 @@ private: static int32_t CheckUriPersistentPermission(uint32_t tokenId, const vector &uriPolicies, vector &errorResults); + static vector GetSandboxPolicyInfo(const vector &pathPolicies); #endif }; } // namespace AppFileService diff --git a/interfaces/innerkits/native/file_share/src/file_permission.cpp b/interfaces/innerkits/native/file_share/src/file_permission.cpp index d06a1cba5..302a29c8e 100644 --- a/interfaces/innerkits/native/file_share/src/file_permission.cpp +++ b/interfaces/innerkits/native/file_share/src/file_permission.cpp @@ -203,6 +203,16 @@ vector FilePermission::GetPathPolicyInfoFromUriPolicyInfo(const vect return pathPolicies; } +vector FilePermission::GetSandboxPolicyInfo(const vector &pathPolicies) +{ + vector policies; + for (const auto &policy: pathPolicies) { + PolicyInfo policyInfo = {policy.path, policy.mode}; + policies.emplace_back(policyInfo); + } + return policies; +} + static bool CheckPermission(uint64_t tokenCaller, const string &permission) { return Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenCaller, permission) == @@ -249,6 +259,39 @@ int32_t FilePermission::CheckUriPersistentPermission(uint32_t tokenId, } #endif +int32_t FilePermission::CheckPathPermission(uint32_t tokenId, const vector &pathPolicies, + int32_t policyType, vector &errorResults) +{ + LOGI("CheckPathPermission pathPolicies size:%{public}zu policyType:%{public}d", pathPolicies.size(), policyType); + int errorCode = 0; +#ifdef SANDBOX_MANAGER + if (tokenId == 0) { + LOGE("tokenId is invalid"); + return FileManagement::LibN::E_PARAMS; + } + if (pathPolicies.size() == 0 || pathPolicies.size() > MAX_ARRAY_SIZE) { + LOGE("The number of policy is invalid"); + return FileManagement::LibN::E_PARAMS; + } + if (policyType < 0 || policyType > PERSISTENT_TYPE) { + LOGE("The policyType is invalid type:%{public}d", policyType); + return FileManagement::LibN::E_PARAMS; + } + + int32_t sandboxManagerErrorCode = 0; + vector policies = GetSandboxPolicyInfo(pathPolicies); + if (policyType == TEMPORARY_TYPE) { + sandboxManagerErrorCode = SandboxManagerKit::CheckPolicy(tokenId, policies, errorResults); + } else if (policyType == PERSISTENT_TYPE) { + sandboxManagerErrorCode = SandboxManagerKit::CheckPersistPolicy(tokenId, policies, errorResults); + } else { + LOGE("invalid policy type %{public}d", policyType); + } + errorCode = ErrorCodeConversion(sandboxManagerErrorCode); +#endif + return errorCode; +} + int32_t FilePermission::PersistPermission(const vector &uriPolicies, deque &errorResults) { diff --git a/interfaces/kits/js/file_share/fileshare_n_exporter.cpp b/interfaces/kits/js/file_share/fileshare_n_exporter.cpp index 8502be925..68fd338d9 100644 --- a/interfaces/kits/js/file_share/fileshare_n_exporter.cpp +++ b/interfaces/kits/js/file_share/fileshare_n_exporter.cpp @@ -30,7 +30,9 @@ using namespace FileManagement::LibN; napi_value FileShareExport(napi_env env, napi_value exports) { InitOperationMode(env, exports); + InitPolicyType(env, exports); InitPolicyInfo(env, exports); + InitPathPolicyInfo(env, exports); InitPolicyErrorCode(env, exports); InitPolicyErrorResult(env, exports); static napi_property_descriptor desc[] = { @@ -40,6 +42,7 @@ napi_value FileShareExport(napi_env env, napi_value exports) DECLARE_NAPI_FUNCTION("activatePermission", ActivatePermission), DECLARE_NAPI_FUNCTION("deactivatePermission", DeactivatePermission), DECLARE_NAPI_FUNCTION("checkPersistentPermission", CheckPersistentPermission), + DECLARE_NAPI_FUNCTION("checkPathPermission", CheckPathPermission), }; napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); return exports; @@ -86,6 +89,33 @@ void InitOperationMode(napi_env env, napi_value exports) } } +void InitPolicyType(napi_env env, napi_value exports) +{ + char propertyName[] = "PolicyType"; + napi_property_descriptor desc[] = { + DECLARE_NAPI_STATIC_PROPERTY("TEMPORARY_TYPE", + NVal::CreateUint32(env, static_cast(TEMPORARY_TYPE)).val_), + DECLARE_NAPI_STATIC_PROPERTY("PERSISTENT_TYPE", + NVal::CreateUint32(env, static_cast(PERSISTENT_TYPE)).val_), + }; + napi_value obj = nullptr; + napi_status status = napi_create_object(env, &obj); + if (status != napi_ok) { + HILOGE("Failed to create object at initializing PolicyType"); + return; + } + status = napi_define_properties(env, obj, sizeof(desc) / sizeof(desc[0]), desc); + if (status != napi_ok) { + HILOGE("Failed to set properties of character at initializing PolicyType"); + return; + } + status = napi_set_named_property(env, exports, propertyName, obj); + if (status != napi_ok) { + HILOGE("Failed to set direction property at initializing PolicyType"); + return; + } +} + void InitPolicyErrorCode(napi_env env, napi_value exports) { char propertyName[] = "PolicyErrorCode"; @@ -163,6 +193,29 @@ void InitPolicyInfo(napi_env env, napi_value exports) } } +void InitPathPolicyInfo(napi_env env, napi_value exports) +{ + char className[] = "PathPolicyInfo"; + napi_property_descriptor desc[] = { + DECLARE_NAPI_STATIC_PROPERTY("path", NVal::CreateUTF8String(env, "path").val_), + DECLARE_NAPI_STATIC_PROPERTY("operationMode", + NVal::CreateUint32(env, static_cast(OperationMode::READ_MODE)).val_), + }; + napi_value obj = nullptr; + napi_status status = napi_define_class(env, className, NAPI_AUTO_LENGTH, InitPolicyConstructor, nullptr, + sizeof(desc) / sizeof(desc[0]), desc, &obj); + napi_create_object(env, &obj); + if (status != napi_ok) { + HILOGE("Failed to define class at initializing PathPolicyInfo"); + return; + } + status = napi_set_named_property(env, exports, className, obj); + if (status != napi_ok) { + HILOGE("Failed to set direction property at initializing PathPolicyInfo"); + return; + } +} + NAPI_MODULE(fileshare, FileShareExport) } // namespace ModuleFileShare } // namespace AppFileService diff --git a/interfaces/kits/js/file_share/fileshare_n_exporter.h b/interfaces/kits/js/file_share/fileshare_n_exporter.h index 3b1a82004..b042a0fb2 100644 --- a/interfaces/kits/js/file_share/fileshare_n_exporter.h +++ b/interfaces/kits/js/file_share/fileshare_n_exporter.h @@ -22,7 +22,9 @@ namespace AppFileService { namespace ModuleFileShare { void InitOperationMode(napi_env env, napi_value exports); void InitPolicyFlag(napi_env env, napi_value exports); +void InitPolicyType(napi_env env, napi_value exports); void InitPolicyInfo(napi_env env, napi_value exports); +void InitPathPolicyInfo(napi_env env, napi_value exports); void InitPolicyErrorResult(napi_env env, napi_value exports); void InitPolicyErrorCode(napi_env env, napi_value exports); napi_value FileShareExport(napi_env env, napi_value exports); diff --git a/interfaces/kits/js/file_share/grant_permissions.cpp b/interfaces/kits/js/file_share/grant_permissions.cpp index ba2386395..69a3ea273 100644 --- a/interfaces/kits/js/file_share/grant_permissions.cpp +++ b/interfaces/kits/js/file_share/grant_permissions.cpp @@ -30,6 +30,7 @@ namespace OHOS { namespace AppFileService { namespace ModuleFileShare { using namespace OHOS::FileManagement::LibN; +using namespace OHOS::Security::AccessToken; using namespace std; namespace { @@ -152,6 +153,74 @@ static napi_status GetUriPoliciesArg(napi_env env, napi_value agrv, std::vector< return napi_ok; } +static napi_status CheckPathArray(napi_env env, napi_value agrv, uint32_t &count) +{ + napi_status status = napi_get_array_length(env, agrv, &count); + if (status != napi_ok) { + LOGE("get array length failed"); + return status; + } + if (count == 0 || count > MAX_ARRAY_SIZE) { + LOGE("The length of the array is extra-long or length is 0"); + return napi_invalid_arg; + } + return napi_ok; +} + +static napi_status GetPathPoliciesArg(napi_env env, napi_value agrv, std::vector &pathPolicies) +{ + uint32_t count; + napi_status status = CheckPathArray(env, agrv, count); + if (status != napi_ok) { + return status; + } + for (uint32_t i = 0; i < count; i++) { + napi_handle_scope scope; + status = napi_open_handle_scope(env, &scope); + if (status != napi_ok) { + LOGE("open handle scope failed"); + return status; + } + napi_value object; + status = napi_get_element(env, agrv, i, &object); + if (status != napi_ok) { + LOGE("get element failed"); + return status; + } + napi_value pathValue; + napi_value modeValue; + status = napi_get_named_property(env, object, "path", &pathValue); + if (status != napi_ok) { + LOGE("get named property failed"); + return status; + } + status = napi_get_named_property(env, object, "operationMode", &modeValue); + if (status != napi_ok) { + LOGE("get named property failed"); + return status; + } + auto [succStr, str, ignore] = NVal(env, pathValue).ToUTF8String(); + auto [succMode, mode] = NVal(env, modeValue).ToUint32(); + if (!succStr || !succMode) { + LOGE("the argument error"); + return napi_invalid_arg; + } + PathPolicyInfo pathPolicy {.path = str.get(), .mode = mode}; + pathPolicies.emplace_back(pathPolicy); + status = napi_close_handle_scope(env, scope); + if (status != napi_ok) { + return status; + } + } + return napi_ok; +} + +static bool IsSystemApp() +{ + uint64_t fullTokenId = OHOS::IPCSkeleton::GetCallingFullTokenID(); + return TokenIdKit::IsSystemAppByFullTokenID(fullTokenId); +} + napi_value PersistPermission(napi_env env, napi_callback_info info) { if (!CheckFileManagerFullMountEnable()) { @@ -367,6 +436,88 @@ napi_value CheckPersistentPermission(napi_env env, napi_callback_info info) return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbCompl).val_; } +static bool CheckTokenIdPermission(uint32_t tokenCaller, const string &permission) +{ + return AccessTokenKit::VerifyAccessToken(tokenCaller, permission) == + PermissionState::PERMISSION_GRANTED; +} + +static bool CheckArgs(napi_env env, napi_callback_info info, NFuncArg& funcArg) +{ + if (!funcArg.InitArgs(NARG_CNT::THREE)) { + LOGE("ActivatePermission Number of arguments unmatched"); + return false; + } + + auto [succTokenId, tokenId] = NVal(env, funcArg[NARG_POS::FIRST]).ToInt32(); + if (!succTokenId || tokenId == 0) { + LOGE("Failed to get tokenid or tokenid is 0"); + return false; + } + + auto [succPolicyType, policyType] = NVal(env, funcArg[NARG_POS::THIRD]).ToInt32(); + if (!succPolicyType || policyType < TEMPORARY_TYPE || policyType > PERSISTENT_TYPE) { + LOGE("Failed to get policy type or policy type is invalid"); + return false; + } + return true; +} + +napi_value CheckPathPermission(napi_env env, napi_callback_info info) +{ + if (!IsSystemApp()) { + LOGE("FileShare::CheckPathPermission is not System App!"); + NError(E_PERMISSION_SYS).ThrowErr(env); + return nullptr; + } + + NFuncArg funcArg(env, info); + if (!CheckArgs(env, info, funcArg)) { + NError(E_PARAMS).ThrowErr(env); + return nullptr; + } + + auto [succTokenId, tokenId] = NVal(env, funcArg[NARG_POS::FIRST]).ToInt32(); + + uint32_t callerTokenId = OHOS::IPCSkeleton::GetCallingTokenID(); + if (tokenId != static_cast(callerTokenId)) { + if (!CheckTokenIdPermission(callerTokenId, "ohos.permission.CHECK_SANDBOX_POLICY")) { + NError(E_PERMISSION).ThrowErr(env); + return nullptr; + } + } + + std::vector pathPolicies; + if (GetPathPoliciesArg(env, funcArg[NARG_POS::SECOND], pathPolicies) != napi_ok) { + NError(E_PARAMS).ThrowErr(env); + return nullptr; + } + + auto [succPolicyType, policyType] = NVal(env, funcArg[NARG_POS::THIRD]).ToInt32(); + + LOGI("check permission target:%{public}d type:%{public}d", tokenId, policyType); + + shared_ptr arg = make_shared(); + if (arg == nullptr) { + LOGE("PolicyInfoResultArgs make_shared is failed"); + NError(E_UNKNOWN_ERROR).ThrowErr(env); + return nullptr; + } + auto cbExec = [tokenId { move(tokenId)}, pathPolicies, policyType { move(policyType)}, arg]() -> NError { + arg->errNo = FilePermission::CheckPathPermission(tokenId, pathPolicies, policyType, arg->resultData); + return NError(arg->errNo); + }; + auto cbCompl = [arg](napi_env env, NError err) -> NVal { + if (arg->errNo != 0) { + return {env, err.GetNapiErr(env)}; + } + return {env, GetResultData(env, arg->resultData)}; + }; + const string procedureName = "check_path_permission"; + NVal thisVar(env, funcArg.GetThisVar()); + return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbCompl).val_; +} + } // namespace ModuleFileShare } // namespace AppFileService } // namespace OHOS diff --git a/interfaces/kits/js/file_share/grant_permissions.h b/interfaces/kits/js/file_share/grant_permissions.h index 285033667..c42c040f3 100644 --- a/interfaces/kits/js/file_share/grant_permissions.h +++ b/interfaces/kits/js/file_share/grant_permissions.h @@ -29,6 +29,7 @@ napi_value RevokePermission(napi_env env, napi_callback_info info); napi_value ActivatePermission(napi_env env, napi_callback_info info); napi_value DeactivatePermission(napi_env env, napi_callback_info info); napi_value CheckPersistentPermission(napi_env env, napi_callback_info info); +napi_value CheckPathPermission(napi_env env, napi_callback_info info); struct PolicyErrorArgs { deque errorResults; diff --git a/test/unittest/file_permission_native/src/file_permission_test.cpp b/test/unittest/file_permission_native/src/file_permission_test.cpp index 148765cb5..e7a45a552 100644 --- a/test/unittest/file_permission_native/src/file_permission_test.cpp +++ b/test/unittest/file_permission_native/src/file_permission_test.cpp @@ -603,6 +603,32 @@ HWTEST_F(FilePermissionTest, CheckPersistentPermission_test_0003, testing::ext:: }; GTEST_LOG_(INFO) << "FileShareTest-end CheckPersistentPermission_test_0003"; } +/** + * @tc.name: CheckPathPermission_test_1000 + * @tc.desc: Test function of CheckPathPermission() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: + */ +HWTEST_F(FilePermissionTest, CheckPathPermission_test_1000, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FileShareTest-begin CheckPathPermission_test_1000"; + PathPolicyInfo infoTestA = {.path = "/storage/Users/currentUser/Documents/1.txt", + .mode = OperationMode::READ_MODE | OperationMode::WRITE_MODE}; + std::vector pathPolicies; + pathPolicies.emplace_back(infoTestA); + vector errorResults; + EXPECT_CALL(*sandboxMock_, CheckPersistPolicy(_, _, _)).WillOnce(Return(SANDBOX_MANAGER_OK)); + uint32_t tokenId = 537688848; + int32_t policyType = PERSISTENT_TYPE; + int32_t ret = FilePermission::CheckPathPermission(tokenId, pathPolicies, policyType, errorResults); + EXPECT_EQ(ret, 0); + + ret = FilePermission::CheckPathPermission(tokenId, pathPolicies, 2, errorResults); + EXPECT_EQ(ret, 401); + GTEST_LOG_(INFO) << "FileShareTest-end CheckPathPermission_test_1000"; +} #endif } // namespace AppFileService } // namespace OHOS \ No newline at end of file -- Gitee