From 17a92849606f03e56f0fa01b3dc6b3b8efdce94d Mon Sep 17 00:00:00 2001 From: mamingshuai Date: Wed, 2 Jun 2021 00:43:21 +0800 Subject: [PATCH] update OpenHarmony 2.0 Canary --- .gitattributes | 15 + BUILD.gn | 34 ++ LICENSE | 0 OAT.xml | 64 +++ README.md | 407 ++++++++++++--- README_zh.md | 407 ++++++++++++--- figures/bms策略举例.png | Bin 12558 -> 0 bytes figures/en-us_image_0000001113598272.png | Bin 0 -> 25160 bytes figures/zh-cn_image_0000001113598272.png | Bin 0 -> 23284 bytes figures/全局策略2.png | Bin 9833 -> 0 bytes figures/策略类型2.png | Bin 7247 -> 0 bytes .../permissioncommunicationadapter/BUILD.gn | 43 ++ .../main/cpp/include/i_permission_manager.h | 85 +++ .../main/cpp/include/permission_def_parcel.h | 40 ++ .../main/cpp/src/permission_def_parcel.cpp | 62 +++ .../permissioninfrastructure/BUILD.gn | 38 ++ .../main/cpp/include/data_validator.h | 37 ++ .../main/cpp/include/permission_log.h | 63 +++ .../main/cpp/include/test_const.h | 39 ++ .../main/cpp/src/data_validator.cpp | 37 ++ .../permission_lite/pms_interface_inner.h | 0 .../permissionsdk/BUILD.gn | 58 +++ .../main/cpp/include/permission/permission.h | 46 ++ .../cpp/include/permission/permission_def.h | 38 ++ .../cpp/include/permission/permission_kit.h | 57 +++ .../cpp/src/permission/permission_kit.cpp | 142 ++++++ .../permission/permission_manager_client.cpp | 227 +++++++++ .../permission/permission_manager_client.h | 72 +++ .../permission/permission_manager_proxy.cpp | 482 ++++++++++++++++++ .../src/permission/permission_manager_proxy.h | 67 +++ .../permissionsdk/test/BUILD.gn | 40 ++ .../unittest/cpp/src/permission_kit_test.cpp | 357 +++++++++++++ .../unittest/cpp/src/permission_kit_test.h | 37 ++ interfaces/kits/permission_lite/BUILD.gn | 0 .../kits/permission_lite/pms_interface.h | 0 interfaces/kits/permission_standard/BUILD.gn | 14 + ohos.build | 30 ++ services/permission_lite/BUILD.gn | 0 .../ipc_auth/include/policy_preset.h | 0 .../ipc_auth/src/ipc_auth_impl.c | 0 services/permission_lite/js_api/BUILD.gn | 0 .../js_api/include/perm_module.h | 0 .../js_api/src/perm_module.cpp | 0 services/permission_lite/pms/BUILD.gn | 0 .../pms/include/hals/hal_pms.h | 0 .../permission_lite/pms/include/perm_define.h | 0 .../pms/include/perm_operate.h | 0 services/permission_lite/pms/include/pms.h | 0 .../permission_lite/pms/include/pms_inner.h | 0 .../permission_lite/pms/src/perm_operate.c | 0 services/permission_lite/pms/src/pms_impl.c | 0 services/permission_lite/pms/src/pms_inner.c | 0 services/permission_lite/pms/src/pms_server.c | 0 .../pms/src/pms_server_internal.c | 0 services/permission_lite/pms_base/BUILD.gn | 0 .../pms_base/include/pms_common.h | 0 services/permission_lite/pms_client/BUILD.gn | 0 .../permission_lite/pms_client/perm_client.c | 0 .../permissionmanagerservice/BUILD.gn | 58 +++ .../main/cpp/src/data_storage.cpp | 29 ++ .../main/cpp/src/data_storage.h | 49 ++ .../main/cpp/src/data_translator.cpp | 82 +++ .../main/cpp/src/data_translator.h | 39 ++ .../main/cpp/src/field_const.h | 38 ++ .../main/cpp/src/generic_values.cpp | 73 +++ .../main/cpp/src/generic_values.h | 53 ++ .../cpp/src/permission_definition_cache.cpp | 133 +++++ .../cpp/src/permission_definition_cache.h | 71 +++ .../cpp/src/permission_definition_manager.cpp | 152 ++++++ .../cpp/src/permission_definition_manager.h | 67 +++ .../cpp/src/permission_manager_service.cpp | 189 +++++++ .../main/cpp/src/permission_manager_service.h | 76 +++ .../main/cpp/src/permission_manager_stub.cpp | 266 ++++++++++ .../main/cpp/src/permission_manager_stub.h | 56 ++ .../main/cpp/src/permission_req.h | 33 ++ .../main/cpp/src/permission_state_cache.cpp | 378 ++++++++++++++ .../main/cpp/src/permission_state_cache.h | 121 +++++ .../main/cpp/src/permission_state_manager.cpp | 265 ++++++++++ .../main/cpp/src/permission_state_manager.h | 80 +++ .../main/cpp/src/sqlite_helper.cpp | 188 +++++++ .../main/cpp/src/sqlite_helper.h | 62 +++ .../main/cpp/src/sqlite_storage.cpp | 337 ++++++++++++ .../main/cpp/src/sqlite_storage.h | 86 ++++ .../main/cpp/src/statement.cpp | 125 +++++ .../main/cpp/src/statement.h | 57 +++ .../main/cpp/src/variant_value.cpp | 61 +++ .../main/cpp/src/variant_value.h | 52 ++ .../main/sa_profile/3501.xml | 24 + .../main/sa_profile/BUILD.gn | 20 + .../permissionmanagerservice/test/BUILD.gn | 48 ++ .../permission_definition_manager_test.cpp | 88 ++++ .../src/permission_definition_manager_test.h | 37 ++ .../cpp/src/permission_state_manager_test.cpp | 44 ++ .../cpp/src/permission_state_manager_test.h | 37 ++ 94 files changed, 6470 insertions(+), 142 deletions(-) create mode 100644 .gitattributes create mode 100755 BUILD.gn mode change 100644 => 100755 LICENSE create mode 100755 OAT.xml delete mode 100755 figures/bms策略举例.png create mode 100644 figures/en-us_image_0000001113598272.png create mode 100644 figures/zh-cn_image_0000001113598272.png delete mode 100755 figures/全局策略2.png delete mode 100755 figures/策略类型2.png create mode 100644 frameworks/permission_standard/permissioncommunicationadapter/BUILD.gn create mode 100644 frameworks/permission_standard/permissioncommunicationadapter/main/cpp/include/i_permission_manager.h create mode 100755 frameworks/permission_standard/permissioncommunicationadapter/main/cpp/include/permission_def_parcel.h create mode 100755 frameworks/permission_standard/permissioncommunicationadapter/main/cpp/src/permission_def_parcel.cpp create mode 100644 frameworks/permission_standard/permissioninfrastructure/BUILD.gn create mode 100755 frameworks/permission_standard/permissioninfrastructure/main/cpp/include/data_validator.h create mode 100644 frameworks/permission_standard/permissioninfrastructure/main/cpp/include/permission_log.h create mode 100644 frameworks/permission_standard/permissioninfrastructure/main/cpp/include/test_const.h create mode 100644 frameworks/permission_standard/permissioninfrastructure/main/cpp/src/data_validator.cpp mode change 100644 => 100755 interfaces/innerkits/permission_lite/pms_interface_inner.h create mode 100755 interfaces/innerkits/permission_standard/permissionsdk/BUILD.gn create mode 100755 interfaces/innerkits/permission_standard/permissionsdk/main/cpp/include/permission/permission.h create mode 100755 interfaces/innerkits/permission_standard/permissionsdk/main/cpp/include/permission/permission_def.h create mode 100755 interfaces/innerkits/permission_standard/permissionsdk/main/cpp/include/permission/permission_kit.h create mode 100755 interfaces/innerkits/permission_standard/permissionsdk/main/cpp/src/permission/permission_kit.cpp create mode 100644 interfaces/innerkits/permission_standard/permissionsdk/main/cpp/src/permission/permission_manager_client.cpp create mode 100755 interfaces/innerkits/permission_standard/permissionsdk/main/cpp/src/permission/permission_manager_client.h create mode 100644 interfaces/innerkits/permission_standard/permissionsdk/main/cpp/src/permission/permission_manager_proxy.cpp create mode 100644 interfaces/innerkits/permission_standard/permissionsdk/main/cpp/src/permission/permission_manager_proxy.h create mode 100755 interfaces/innerkits/permission_standard/permissionsdk/test/BUILD.gn create mode 100755 interfaces/innerkits/permission_standard/permissionsdk/test/unittest/cpp/src/permission_kit_test.cpp create mode 100644 interfaces/innerkits/permission_standard/permissionsdk/test/unittest/cpp/src/permission_kit_test.h mode change 100644 => 100755 interfaces/kits/permission_lite/BUILD.gn mode change 100644 => 100755 interfaces/kits/permission_lite/pms_interface.h create mode 100644 interfaces/kits/permission_standard/BUILD.gn create mode 100755 ohos.build mode change 100644 => 100755 services/permission_lite/BUILD.gn mode change 100644 => 100755 services/permission_lite/ipc_auth/include/policy_preset.h mode change 100644 => 100755 services/permission_lite/ipc_auth/src/ipc_auth_impl.c mode change 100644 => 100755 services/permission_lite/js_api/BUILD.gn mode change 100644 => 100755 services/permission_lite/js_api/include/perm_module.h mode change 100644 => 100755 services/permission_lite/js_api/src/perm_module.cpp mode change 100644 => 100755 services/permission_lite/pms/BUILD.gn mode change 100644 => 100755 services/permission_lite/pms/include/hals/hal_pms.h mode change 100644 => 100755 services/permission_lite/pms/include/perm_define.h mode change 100644 => 100755 services/permission_lite/pms/include/perm_operate.h mode change 100644 => 100755 services/permission_lite/pms/include/pms.h mode change 100644 => 100755 services/permission_lite/pms/include/pms_inner.h mode change 100644 => 100755 services/permission_lite/pms/src/perm_operate.c mode change 100644 => 100755 services/permission_lite/pms/src/pms_impl.c mode change 100644 => 100755 services/permission_lite/pms/src/pms_inner.c mode change 100644 => 100755 services/permission_lite/pms/src/pms_server.c mode change 100644 => 100755 services/permission_lite/pms/src/pms_server_internal.c mode change 100644 => 100755 services/permission_lite/pms_base/BUILD.gn mode change 100644 => 100755 services/permission_lite/pms_base/include/pms_common.h mode change 100644 => 100755 services/permission_lite/pms_client/BUILD.gn mode change 100644 => 100755 services/permission_lite/pms_client/perm_client.c create mode 100755 services/permission_standard/permissionmanagerservice/BUILD.gn create mode 100644 services/permission_standard/permissionmanagerservice/main/cpp/src/data_storage.cpp create mode 100644 services/permission_standard/permissionmanagerservice/main/cpp/src/data_storage.h create mode 100644 services/permission_standard/permissionmanagerservice/main/cpp/src/data_translator.cpp create mode 100755 services/permission_standard/permissionmanagerservice/main/cpp/src/data_translator.h create mode 100644 services/permission_standard/permissionmanagerservice/main/cpp/src/field_const.h create mode 100644 services/permission_standard/permissionmanagerservice/main/cpp/src/generic_values.cpp create mode 100755 services/permission_standard/permissionmanagerservice/main/cpp/src/generic_values.h create mode 100644 services/permission_standard/permissionmanagerservice/main/cpp/src/permission_definition_cache.cpp create mode 100755 services/permission_standard/permissionmanagerservice/main/cpp/src/permission_definition_cache.h create mode 100644 services/permission_standard/permissionmanagerservice/main/cpp/src/permission_definition_manager.cpp create mode 100755 services/permission_standard/permissionmanagerservice/main/cpp/src/permission_definition_manager.h create mode 100755 services/permission_standard/permissionmanagerservice/main/cpp/src/permission_manager_service.cpp create mode 100755 services/permission_standard/permissionmanagerservice/main/cpp/src/permission_manager_service.h create mode 100644 services/permission_standard/permissionmanagerservice/main/cpp/src/permission_manager_stub.cpp create mode 100644 services/permission_standard/permissionmanagerservice/main/cpp/src/permission_manager_stub.h create mode 100644 services/permission_standard/permissionmanagerservice/main/cpp/src/permission_req.h create mode 100644 services/permission_standard/permissionmanagerservice/main/cpp/src/permission_state_cache.cpp create mode 100755 services/permission_standard/permissionmanagerservice/main/cpp/src/permission_state_cache.h create mode 100644 services/permission_standard/permissionmanagerservice/main/cpp/src/permission_state_manager.cpp create mode 100755 services/permission_standard/permissionmanagerservice/main/cpp/src/permission_state_manager.h create mode 100755 services/permission_standard/permissionmanagerservice/main/cpp/src/sqlite_helper.cpp create mode 100644 services/permission_standard/permissionmanagerservice/main/cpp/src/sqlite_helper.h create mode 100644 services/permission_standard/permissionmanagerservice/main/cpp/src/sqlite_storage.cpp create mode 100644 services/permission_standard/permissionmanagerservice/main/cpp/src/sqlite_storage.h create mode 100644 services/permission_standard/permissionmanagerservice/main/cpp/src/statement.cpp create mode 100755 services/permission_standard/permissionmanagerservice/main/cpp/src/statement.h create mode 100644 services/permission_standard/permissionmanagerservice/main/cpp/src/variant_value.cpp create mode 100755 services/permission_standard/permissionmanagerservice/main/cpp/src/variant_value.h create mode 100755 services/permission_standard/permissionmanagerservice/main/sa_profile/3501.xml create mode 100644 services/permission_standard/permissionmanagerservice/main/sa_profile/BUILD.gn create mode 100644 services/permission_standard/permissionmanagerservice/test/BUILD.gn create mode 100755 services/permission_standard/permissionmanagerservice/test/unittest/cpp/src/permission_definition_manager_test.cpp create mode 100644 services/permission_standard/permissionmanagerservice/test/unittest/cpp/src/permission_definition_manager_test.h create mode 100644 services/permission_standard/permissionmanagerservice/test/unittest/cpp/src/permission_state_manager_test.cpp create mode 100644 services/permission_standard/permissionmanagerservice/test/unittest/cpp/src/permission_state_manager_test.h diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..51c63e2 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,15 @@ +*.tgz filter=lfs diff=lfs merge=lfs -text +*.trp filter=lfs diff=lfs merge=lfs -text +*.apk filter=lfs diff=lfs merge=lfs -text +*.jar filter=lfs diff=lfs merge=lfs -text +*.mp4 filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.asm filter=lfs diff=lfs merge=lfs -text +*.8svn filter=lfs diff=lfs merge=lfs -text +*.9svn filter=lfs diff=lfs merge=lfs -text +*.dylib filter=lfs diff=lfs merge=lfs -text +*.exe filter=lfs diff=lfs merge=lfs -text +*.a filter=lfs diff=lfs merge=lfs -text +*.so filter=lfs diff=lfs merge=lfs -text +*.bin filter=lfs diff=lfs merge=lfs -text +*.dll filter=lfs diff=lfs merge=lfs -text diff --git a/BUILD.gn b/BUILD.gn new file mode 100755 index 0000000..b664388 --- /dev/null +++ b/BUILD.gn @@ -0,0 +1,34 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +group("permission_build_module_standard") { + if (is_standard_system) { + deps = [ + "//base/security/permission/interfaces/innerkits/permission_standard/permissionsdk:libpermissionsdk_standard", + "//base/security/permission/services/permission_standard/permissionmanagerservice:permission_manager_service_standard", + "//base/security/permission/services/permission_standard/permissionmanagerservice/main/sa_profile:permission_sa_profile_standard", + ] + } +} + +group("permission_build_module_standard_test") { + testonly = true + deps = [] + if (is_standard_system) { + deps += [ + "//base/security/permission/interfaces/innerkits/permission_standard/permissionsdk/test:unittest", + "//base/security/permission/services/permission_standard/permissionmanagerservice/test:unittest", + ] + } +} diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/OAT.xml b/OAT.xml new file mode 100755 index 0000000..881c860 --- /dev/null +++ b/OAT.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + diff --git a/README.md b/README.md index f1e1947..93b8688 100755 --- a/README.md +++ b/README.md @@ -1,104 +1,369 @@ -# permission\_lite +# security\_permission -- [Application Permission Management](#section20822104317111) -- [IPC Authentication](#section156859591110) +- [Introduction](#section11660541593) +- [Directory Structure](#section161941989596) +- [Constraints](#section119744591305) +- [Usage](#section137768191623) + - [Available APIs](#section1551164914237) + - [Usage Guidelines](#section129654513264) -## Application Permission Management +- [Repositories Involved](#section1371113476307) -Application permissions are used to control access to system resources and features related to personal privacy, for example, accessing hardware features of personal devices such as cameras and microphones, and reading and writing media files. The OS protects such data and features through application permission management. +## Introduction -The following table describes fields in a permission. +In OpenHarmony, apps and system services run in independent sandboxes. Both processes and data are isolated from each other to protect the security of app data. However, services or apps running in the sandboxes provide some APIs to implement specific functionalities. To access these APIs across processes, apps in other sandboxes need the required permissions, which are granted and managed based on a permission management mechanism. - -

Field

+- App permission management provides a mechanism for defining permissions, allowing system services and apps to define new permissions for their sensitive APIs. To access these APIs, other apps need the required permissions. + +- App permission management also allows apps to request permissions that are defined by the system or other apps. Upon obtaining the permissions, apps can access the sensitive APIs provided by the system or other apps. +- In addition, app permission management allows users to view and manage the permission granting status. + +**Figure 1** App permission management architecture + + +![](figures/en-us_image_0000001113598272.png) + +App permission management provides permission management for the application framework subsystem and provides APIs for apps to request permissions and query the permission granting status. Currently, app permission management is available for large and standard systems. + +- Mini system: refers to the system running on the devices whose memory is greater than or equal to 128 KB and that are equipped with MCU processors such as ARM Cortex-M and 32-bit RISC-V. This system provides multiple lightweight network protocols and graphics frameworks, and a wide range of read/write components for the IoT bus. Typical products include connection modules, sensors, and wearables for smart home. +- Small system: refers to the system running on the devices whose memory is greater than or equal to 1 MB and that are equipped with app processors such as ARM Cortex-A. This system provides higher security capabilities, standard graphics frameworks, and video encoding and decoding capabilities. Typical products include smart home IP cameras, electronic cat eyes, and routers, and event data recorders \(EDRs\) for smart travel. +- Standard system: refers to the system running on the devices whose memory is greater than or equal to 128 MB and that are equipped with app processors such as ARM Cortex-A. This system provides a complete application framework supporting the enhanced interaction, 3D GPU, hardware composer, diverse components, and rich animations. This system applies to high-end refrigerator displays. + +## Directory Structure + +``` +/base/security/permission +├── frameworks # Frameworks +│ └── permission_standard # Permission management framework for the standard system +├── interfaces # APIs +│ ├── innerkits # Internal APIs +│ │ ├── permission_lite # Internal permission management APIs for the mini and small systems +│ │ └── permission_standard # Internal permission management APIs for the standard system +│ └── kits # External APIs +│ ├── permission_lite # External permission management APIs for the mini and small systems +│ └── permission_standard # External permission management APIs for the standard system +└── services # Services + ├── permission_lite # Permission management services for the mini and small systems + └── permission_standard # Permission management services for the standard system +``` + +## Constraints + +- Currently, C++ APIs are available only for local permission management in the standard system. Distributed permission management APIs are not provided yet. + +## Usage + +### Available APIs + +**App permission management for a standard system**: provides basic permission management and verification capabilities for the application framework subsystem of a standard system and is unavailable for third-party apps. The following table describes the available APIs. + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + +

API

Value

-

Description

+

Description

name

+

int VerifyPermission(const string& bundleName, const string& permissionName, int userId)

String

-

Permission name

+

Checks whether a specified app has been granted the given permission.

reason

+

bool CanRequestPermission(const string& bundleName, const string& permissionName, int userId)

Multi-language string ID

-

Purpose of requesting the permission

+

Checks whether a specified app can request the given permission through a pop-up window.

used-scene{

-

ability,

-

when

-

}

+

int GrantUserGrantedPermission(const string& bundleName, const string& permissionName, int userId)

ability: string of the component class name

-

when:inuse, always

+

Grants a specified user_grant permission to the given app.

Scene where the APIs controlled by this permission are called.

-

This field declares what components can call the APIs controlled by this permission in the specified scene (foreground/background).

+

int GrantSystemGrantedPermission(const string& bundleName, const string& permissionName)

+

Grants a specified system_grant permission to the given app.

+

int RevokeUserGrantedPermission(const string& bundleName, const string& permissionName, int userId)

+

Revokes a specified user_grant permission from the given app.

+

int RevokeSystemGrantedPermission(const string& bundleName, const string& permissionName)

+

Revokes a specified system_grant permission from the given app.

+

int AddUserGrantedReqPermissions(const string& bundleName, const std::vector<string>& permList, int userId)

+

Adds user_grant permissions requested by a specified app.

+

int AddSystemGrantedReqPermissions(const string& bundleName, const std::vector<string>& permList)

+

Adds system_grant permissions requested by a specified app.

+

int RemoveUserGrantedReqPermissions(const string& bundleName, int userId)

+

Removes all the user_grant permissions requested by a specified app.

+

int RemoveSystemGrantedReqPermissions(const string& bundleName)

+

Removes all the system_grant permissions requested by a specified app.

+

int AddDefPermissions(const std::vector<PermissionDef>& permList)

+

Adds the permissions defined by the app.

+

int GetDefPermission(const string& permissionName, PermissionDef& permissionDefResult)

+

Obtains the definition of the permission with a specified name.

-## IPC Authentication +**App permission management for a mini or small system**: The following table lists the available APIs, which can be called only by system apps and services. -- If system services registered with Samgr provide APIs for other processes to access the services through IPC, access control policies must be configured; otherwise, access to the system services will be denied. -- You can configure access control policies in **base/security/permission/services/permission\_lite/ipc\_auth/include/policy\_preset.h**. + + + + + + + + + + + + + + + + + + + + + + + + + + + +

API

+

Description

+

int CheckPermission(int uid, const char *permissionName)

+

Checks whether the app with a specified UID has the permission to access system service APIs.

+

int CheckSelfPermission(const char *permissionName)

+

Checks whether the caller has the permission to access system service APIs.

+

int QueryPermission(const char *identifier, PermissionSaved **permissions, int *permNum)

+

Queries all permissions requested by the app and checks whether the requested permissions have been granted.

+

int GrantPermission(const char *identifier, const char *permName)

+

Grants a specified permission to the app.

+

int RevokePermission(const char *identifier, const char *permName)

+

Revokes a specified permission from the app.

+

int GrantRuntimePermission(int uid, const char *permissionName)

+

Grants a specified runtime permission to the app.

+

int RevokeRuntimePermission(int uid, const char *permissionName)

+

Revokes a specified runtime permission from the app.

+
- 1. Define the policies for each feature. +**IPC authentication for a mini or small system** - 2. Add the feature policies to the global policy. + + + + + + + + + + + + +

API

+

Description

+

int GetCommunicationStrategy(RegParams params, PolicyTrans **policies, unsigned int *policyNum)

+

Obtains the access policies of a service API.

+

int IsCommunicationAllowed(AuthParams params)

+

Checks whether a process has the permission to access an API of another process.

+
+ +### Usage Guidelines + +**App permission management for a standard system** + +The APIs provided are for internal use and unavailable to developers. During the authentication, you only need to call **VerifyPermission**. + +1. Determine the app UID and the name of the permission to verify. +2. Obtain the app bundle name based on the app UID. +3. Obtain the user ID of the app based on the UID. +4. Pass the permission name, bundle name, and user ID to **VerifyPermission\(string permissionName, string bundleName, int userId\)**. +5. Obtain the verification result. + +**App permission management for a mini or small system** + +This section uses the bundle manager as an example to describe the app permission development. Before starting development, you need to declare the required sensitive permissions in the **config.json** file. During app installation, the BMS calls APIs of the app permission management component to check whether the required permissions have been granted. If yes, the installation proceeds; if not, the installation fails. + +1. Declare the required permission \(**ohos.permission.INSTALL\_BUNDLE**\) in the **config.json** file. + + ``` + { + ... + "module": { + "package": "ohos.demo.kitframework", + "deviceType": [ + "phone", "tv","tablet", "pc","car","smartWatch","sportsWatch","smartCamera", "smartVision" + ], + "reqPermissions": [{ + // Declare the ohos.permission.INSTALL_BUNDLE permission required for installing the app. + "name": "ohos.permission.INSTALL_BUNDLE", + "reason": "install bundle", + "usedScene": { + "ability": [ + "KitFramework" + ], + "when": "always" + } + }, + { + "name": "ohos.permission.LISTEN_BUNDLE_CHANGE", + "reason": "install bundle", + "usedScene": { + "ability": [ + "KitFramework" + ], + "when": "always" + } + }, + { + "name": "ohos.permission.GET_BUNDLE_INFO", + "reason": "install bundle", + "usedScene": { + "ability": [ + "KitFramework" + ], + "when": "always" + } + } + ], + ... + } + ``` + +2. The BMS calls the corresponding API of the app permission management component \(for example, the **CheckPermission** function with **ohos.permission.INSTALL\_BUNDLE** as an input parameter\) to check whether the BMS has the permission to install the app. If yes, the installation proceeds; if not, the installation fails. + + ``` + constexpr static char PERMISSION_INSTALL_BUNDLE[] = "ohos.permission.INSTALL_BUNDLE"; + + bool Install(const char *hapPath, const InstallParam *installParam, InstallerCallback installerCallback) + { + if ((hapPath == nullptr) || (installerCallback == nullptr) || (installParam == nullptr)) { + HILOG_ERROR(HILOG_MODULE_APP, "BundleManager install failed due to nullptr parameters"); + return false; + } + // Check whether the ohos.permission.INSTALL_BUNDLE permission has been granted. + if (CheckPermission(0, static_cast(PERMISSION_INSTALL_BUNDLE)) != GRANTED) { + HILOG_ERROR(HILOG_MODULE_APP, "BundleManager install failed due to permission denied"); + return false; // App installation fails. + } + // App installation process + ... + } + ``` -Eg. For example, to configure an access policy for the BMS service, whose service registered with Samgr is **bundlems** and whose registered feature is **BmsFeature**, perform the following operations: +**IPC authentication for a mini or small system** -1. Define feature policies. You can configure multiple features and configure multiple access policies for each feature. +This section uses the bundle manager as an example to describe how to configure access policies for APIs provided by the IPC authentication component. In this example, the service registered by BMS with Samgr is **bundlems**, and the feature registered for open APIs is **BmsFeature**. -**Figure 1** Example feature policy +1. Configure access policies in the **base/security/permission/services/permission\_lite/ipc\_auth/include/policy\_preset.h** file. Access policies are classified into the following three types: + + 1. **RANGE**: Processes with a specified range of UIDs can access BMS APIs. **uidMin** and **uidMax** must be specified. + + 2. **FIXED**: Processes with specified UIDs can access BMS APIs. **fixedUid** must be specified, and a maximum of eight UIDs are allowed. + + 3. **BUNDLENAME**: An app with a specified **bundleName** can access BMS APIs. + + ``` + FeaturePolicy bmsFeature[] = { + { + "BmsFeature", + { + { + .type=FIXED, // Processes with specified UIDs can access BMS APIs. + .fixedUid={2, 3, 8} + }, + { + .type=RANGE, // Processes with a specified range of UIDs can access BMS APIs. + .uidMin=100, + .uidMax=__INT_MAX__, + }, + } + }, + { + "BmsInnerFeature", + { + { + .type=FIXED, // Processes with specified UIDs can access BMS APIs. + .fixedUid={2, 3, 8} + }, + { + .type=RANGE, + .uidMin=100, + .uidMax=999, + }, + } + }, + }; + ``` + +2. Add the policies configured for the features in [Step 1](#li15901515152517) to the global policy settings. You need to set the number of features. + + ``` + static PolicySetting g_presetPolicies[] = { + {"permissionms", pmsFeature, 1}, + {"abilityms", amsFeature, 2}, + {"bundlems", bmsFeature, 2}, // Add the policies configured for the two features in [Step 1](#li15901515152517) to the global policy settings. + {"dtbschedsrv", dmsFeature, 1}, + {"samgr", samgrFeature, 1}, + {"appspawn", appspawnFeature, 1}, + {"WMS", wmsFeature, 1}, + {"bundle_daemon", bdsFeature, 1}, + }; + ``` + +3. Register the **BmsFeature** defined in [Step 1](#li15901515152517) with Samgr. + + ``` + const char BMS_SERVICE[] = "bundlems"; + const char BMS_FEATURE[] = "BmsFeature"; + static void Init() + { + SamgrLite *sm = SAMGR_GetInstance(); + if (sm == nullptr) { + return; + } + // Register the BmsFeature with Samgr. + sm->RegisterFeature(BMS_SERVICE, reinterpret_cast(BundleMsFeature::GetInstance())); + sm->RegisterFeatureApi(BMS_SERVICE, BMS_FEATURE, + GetBmsFeatureApi(reinterpret_cast(BundleMsFeature::GetInstance()))); + HILOG_DEBUG(HILOG_MODULE_APP, "BundleMS feature start success"); + } + APP_FEATURE_INIT(Init); + ``` -![](figures/bms策略举例.png) +When you register a service with Samgr, Samgr calls the **GetCommunicationStrategy** function of the IPC authentication component to obtain access policies of the service. When other services or apps access this service through IPC, Samgr calls the **IsCommunicationAllowed** function of the IPC authentication component to check whether the services or apps have the access permission. -There are three types of access policies: - -**Figure 2** Access policy structure - - -![](figures/策略类型2.png) - -1. **RANGE**: Processes with UIDs in a specified range can access the BMS service. **uidMin** and **uidMax** must be specified. - -2. **FIXED**: Processes with specified UIDs can access the BMS service. **fixedUid** must be specified, and a maximum of eight UIDs are allowed. - -3. **BUNDLENAME**: A specified application can access the BMS service. **bundleName** must be specified. - -2. Add the defined feature policies to the global policy. You need to configure the number of features. - -**Figure 3** Registering a feature policy - - -![](figures/全局策略2.png) - -UID allocation rules: - -1. Init process: 0 - -2. appspawn process: 1 - -3. Shell process: 2 - -4. Other built-in system services: less than or equal to 99 - -5. System applications \(such as settings, home screen, and camera\): 100–999 - -6. Preset applications: 1000–9999 - -7. Common third-party applications: 10000 to **INT\_MAX** +## Repositories Involved +security +security\_permission diff --git a/README_zh.md b/README_zh.md index c169db0..a3eccd3 100755 --- a/README_zh.md +++ b/README_zh.md @@ -1,104 +1,369 @@ -# 项目介绍 +# 应用权限管理 -- [应用权限管理](#section20822104317111) -- [IPC通信鉴权](#section156859591110) +- [简介](#section11660541593) +- [目录](#section161941989596) +- [约束](#section119744591305) +- [使用](#section137768191623) + - [接口说明](#section1551164914237) + - [使用说明](#section129654513264) -## 应用权限管理 +- [相关仓](#section1371113476307) -应用权限是软件用来访问系统资源和使用系统能力的一种通行方式,存在涉及个人隐私相关功能和数据的场景,例如:访问个人设备的硬件特性,如摄像头、麦克风,以及读写媒体文件等。操作系统通过应用权限管理来保护这些数据以及能力。 +## 简介 -权限定义字段说明: +OpenHarmony中应用和系统服务均运行在独立的沙箱中,进程空间和程序数据都是相互隔离的,以保护应用数据的安全性;但是运行在独立沙箱中的服务或应用同时需要对外提供一些API以实现所需功能,其他独立沙箱中的应用在跨进程访问这些API时,需要系统提供一种权限管理机制对这些API的访问者进行授权。 - -

字段

+- 应用权限管理提供了权限定义机制,允许系统服务和应用为自己的敏感API定义新的权限,其他应用必须申请此权限才能访问此敏感API; + +- 应用权限管理提供了权限申请机制,允许应用申请权限,这些权限由系统或者其他应用定义,权限申请通过后就能访问这个权限相关的系统或其他应用提供的敏感API; +- 应用权限管理也为用户提供了一些必须的功能,方便用户查看和管理权限授予情况。 + +**图 1** 应用权限管理架构 + + +![](figures/zh-cn_image_0000001113598272.png) + +应用权限管理为用户程序框架子系统提供权限管理功能,并且为上层应用提供权限申请和授权状态查询接口。本次开源的应用权限管理功能适用于大型系统和标准系统。 + +- 轻量系统(mini system)面向MCU类处理器例如Arm Cortex-M、RISC-V 32位的设备,硬件资源极其有限,参考内存≥128KB,可以提供多种轻量级网络协议,轻量级的图形框架,以及丰富的IOT总线读写部件等。可支撑的产品如智能家居领域的连接类模组、传感器设备、穿戴类设备等。 +- 小型系统(small system)面向应用处理器例如Arm Cortex-A的设备,参考内存≥1MB,可以提供更高的安全能力、标准的图形框架、视频编解码的多媒体能力。可支撑的产品如智能家居领域的IP Camera、电子猫眼、路由器以及智慧出行域的行车记录仪等。 +- 标准系统(standard system)面向应用处理器例如Arm Cortex-A的设备,参考内存≥128MB,可以提供增强的交互能力、3D GPU以及硬件合成能力、更多控件以及动效更丰富的图形能力、完整的应用框架。可支撑的产品如高端的冰箱显示屏。 + +## 目录 + +``` +/base/security/permission +├── frameworks # 基础设施层 +│ └── permission_standard # 标准系统权限管理基础设施层 +├── interfaces # 接口层 +│ ├── innerkits # 内部接口层 +│ │ ├── permission_lite # 轻量系统、小型系统权限管理内部接口层 +│ │ └── permission_standard # 标准系统权限管理内部接口层 +│ └── kits # 外部接口层 +│ ├── permission_lite # 轻量系统、小型系统权限管理外部接口层 +│ └── permission_standard # 标准系统权限管理外部接口层 +└── services # 服务层 + ├── permission_lite # 轻量系统、小型系统权限管理服务层 + └── permission_standard # 标准系统权限管理服务层 +``` + +## 约束 + +- 标准系统应用权限管理本期仅提供本地权限管理的C++接口,不涉及分布式权限管理。 + +## 使用 + +### 接口说明 + +**标准系统应用权限管理**:此模块主要为标准系统用户程序框架子系统提供权限管理基础校验能力,不对三方app开放,并提供如下API: + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + +

接口名

取值

-

意义

+

说明

name

+

int VerifyPermission(const string& bundleName, const string& permissionName, int userId)

字符串

-

权限名。

+

校验应用是否已授予对应的权限

reason

+

bool CanRequestPermission(const string& bundleName, const string& permissionName, int userId)

多语言字符串id

-

应用申请此权限的目的。

+

判断应用是否需要弹框申请权限

used-scene{

-

ability,

-

when

-

}

+

int GrantUserGrantedPermission(const string& bundleName, const string& permissionName, int userId)

ability:组件类名字符串

-

when:inuse, always

+

授予应用对应的user_grant权限

调用受此权限管控的接口的场景。

-

声明在哪些组件和场景(前台/后台)下调用受管控的接口。

+

int GrantSystemGrantedPermission(const string& bundleName, const string& permissionName)

+

授予应用对应的system_grant权限

+

int RevokeUserGrantedPermission(const string& bundleName, const string& permissionName, int userId)

+

撤销应用对应的user_grant权限

+

int RevokeSystemGrantedPermission(const string& bundleName, const string& permissionName)

+

撤销应用对应的system_grant权限

+

int AddUserGrantedReqPermissions(const string& bundleName, const std::vector<string>& permList, int userId)

+

添加应用申请的user_grant权限

+

int AddSystemGrantedReqPermissions(const string& bundleName, const std::vector<string>& permList)

+

添加应用申请的system_grant权限

+

int RemoveUserGrantedReqPermissions(const string& bundleName, int userId)

+

移除应用申请的所有user_grant权限

+

int RemoveSystemGrantedReqPermissions(const string& bundleName)

+

移除应用申请的所有system_grant权限

+

int AddDefPermissions(const std::vector<PermissionDef>& permList)

+

添加应用定义的权限

+

int GetDefPermission(const string& permissionName, PermissionDef& permissionDefResult)

+

获取指定权限名的权限定义信息

-## IPC通信鉴权 +**轻量系统、小型系统应用权限管理**:当前仅供系统应用和系统服务调用,具体API接口如下: -- 在Samgr中注册的系统服务如果通过进程间通信的方式暴露接口给其他进程访问,需要配置相应的访问控制策略。若不进行相关配置,访问会被拒绝。 -- 配置方式:在头文件base/security/permission/services/permission\_lite/ipc\_auth/include/policy\_preset.h中配置访问策略。 + + + + + + + + + + + + + + + + + + + + + + + + + + + +

接口名

+

描述

+

int CheckPermission(int uid, const char *permissionName)

+

检查指定UID的应用进程是否具有访问系统服务API的权限

+

int CheckSelfPermission(const char *permissionName)

+

检查调用者是否具有访问系统服务API的权限

+

int QueryPermission(const char *identifier, PermissionSaved **permissions, int *permNum)

+

查询应用申请的所有权限,并检查权限是否被授予

+

int GrantPermission(const char *identifier, const char *permName)

+

将指定权限授予应用程序

+

int RevokePermission(const char *identifier, const char *permName)

+

收回应用程序的指定权限

+

int GrantRuntimePermission(int uid, const char *permissionName)

+

应用运行时动态授予指定权限

+

int RevokeRuntimePermission(int uid, const char *permissionName)

+

应用运行时动态撤销指定权限

+
- 1. 定义各个Feature的策略 +**轻量系统、小型系统IPC通信鉴权**: - 2. 将Feature的策略加到全局策略中 + + + + + + + + + + + + +

接口名

+

描述

+

int GetCommunicationStrategy(RegParams params, PolicyTrans **policies, unsigned int *policyNum)

+

服务注册过程中查询调用接口对应的访问策略,仅供Samgr调用

+

int IsCommunicationAllowed(AuthParams params)

+

检查访问主体进程是否有权限调用受访客体进程的接口,仅供Samgr调用

+
+ +### 使用说明 + +**标准系统应用权限管理**: + +使用说明:所有接口均为内部接口,仅提供底层能力,不对开发者开放。鉴权过程中直接调用VerifyPermission接口即可。 + +1. 明确要校验应用的UID及需要校验的权限名称permissionName +2. 根据UID获取应用的包名 bundleName +3. 根据UID获取应用的用户ID userId +4. 将需要校验的权限名permissionName, 包名bundleName和userId传入接口VerifyPermission\(string permissionName, string bundleName, int userId\) +5. 得到校验结果 + +**轻量系统、小型系统应用权限管理**: + +使用说明:以包管理器的应用权限开发为例进行讲解。开发过程中,首先需要明确涉及的敏感权限,并在config.json中声明该权限,在安装应用程序时,包管理器会调用应用权限管理组件的接口检查该权限是否被授予,若授予,安装流程正常进行,否则安装失败。 + +1. 在开发过程中,包管理器明确需要安装应用的权限(ohos.permission.INSTALL\_BUNDLE),并在config.json中声明该权限; + + ``` + { + ... + "module": { + "package": "ohos.demo.kitframework", + "deviceType": [ + "phone", "tv","tablet", "pc","car","smartWatch","sportsWatch","smartCamera", "smartVision" + ], + "reqPermissions": [{ + // 声明需要的权限:安装应用程序的权限名 + "name": "ohos.permission.INSTALL_BUNDLE", + "reason": "install bundle", + "usedScene": { + "ability": [ + "KitFramework" + ], + "when": "always" + } + }, + { + "name": "ohos.permission.LISTEN_BUNDLE_CHANGE", + "reason": "install bundle", + "usedScene": { + "ability": [ + "KitFramework" + ], + "when": "always" + } + }, + { + "name": "ohos.permission.GET_BUNDLE_INFO", + "reason": "install bundle", + "usedScene": { + "ability": [ + "KitFramework" + ], + "when": "always" + } + } + ], + ... + } + ``` + +2. 当包管理器开发应用安装功能接口时,会调用权限管理相关接口检查自身是否具有安装应用程序的权限,例如:以安装应用的权限名"ohos.permission.INSTALL\_BUNDLE"作为入参,调用CheckPermission接口检查包管理器是否具有安装应用的权限,如果有权限,安装流程继续执行,否则返回安装失败; + + ``` + constexpr static char PERMISSION_INSTALL_BUNDLE[] = "ohos.permission.INSTALL_BUNDLE"; + + bool Install(const char *hapPath, const InstallParam *installParam, InstallerCallback installerCallback) + { + if ((hapPath == nullptr) || (installerCallback == nullptr) || (installParam == nullptr)) { + HILOG_ERROR(HILOG_MODULE_APP, "BundleManager install failed due to nullptr parameters"); + return false; + } + // 检查ohos.permission.INSTALL_BUNDLE权限是否被授予 + if (CheckPermission(0, static_cast(PERMISSION_INSTALL_BUNDLE)) != GRANTED) { + HILOG_ERROR(HILOG_MODULE_APP, "BundleManager install failed due to permission denied"); + return false; // 返回安装失败 + } + // 安装流程 + ... + } + ``` -Eg. 比如当前需要为BMS服务配置访问策略,BMS在Samgr中注册的service为bundlems,注册的Feature为BmsFeature。 +**轻量系统、小型系统IPC通信鉴权**: -一、首先定义Feature的策略,可配置多个Feature,每个Feature可以配置多个访问策略,策略的声明方式参考图1 +使用说明:以BMS服务通过IPC通信方式对外开放接口为例,讲解如何通过IPC通信鉴权组件配置对应接口的访问策略。这里BMS在Samgr中注册的service为bundlems,为开放的接口注册的Feature为BmsFeature。 -**图 1** Feature策略示例 +1. 在源码路径下的头文件base/security/permission/services/permission\_lite/ipc\_auth/include/policy\_preset.h中配置相应的访问策略,访问策略主要有三种类型: + + (1)type为RANGE类型:允许某个特定范围UID的进程访问,需要指定uidMin和uidMax; + + (2)type为FIXED类型:允许指定的几个UID的进程访问,需要指定fixedUid,最多配置8个; + + (3)type为BUNDLENAME类型:只允许特定的应用访问,需要指定bundleName(包名); + + ``` + FeaturePolicy bmsFeature[] = { + { + "BmsFeature", + { + { + .type=FIXED, // 允许指定UID的进程访问的方式 + .fixedUid={2, 3, 8} + }, + { + .type=RANGE, // 允许特定范围内的UID的进程访问的方式 + .uidMin=100, + .uidMax=__INT_MAX__, + }, + } + }, + { + "BmsInnerFeature", + { + { + .type=FIXED, // 允许指定UID的进程访问的方式 + .fixedUid={2, 3, 8} + }, + { + .type=RANGE, + .uidMin=100, + .uidMax=999, + }, + } + }, + }; + ``` + +2. 将步骤1中定义的Feature的策略加配到全局策略中,需要配置feature数量; + + ``` + static PolicySetting g_presetPolicies[] = { + {"permissionms", pmsFeature, 1}, + {"abilityms", amsFeature, 2}, + {"bundlems", bmsFeature, 2}, // 步骤1定义的BMS的feature,数量为2 + {"dtbschedsrv", dmsFeature, 1}, + {"samgr", samgrFeature, 1}, + {"appspawn", appspawnFeature, 1}, + {"WMS", wmsFeature, 1}, + {"bundle_daemon", bdsFeature, 1}, + }; + ``` + +3. 将步骤1中定义的BmsFeature注册到Samgr; + + ``` + const char BMS_SERVICE[] = "bundlems"; + const char BMS_FEATURE[] = "BmsFeature"; + static void Init() + { + SamgrLite *sm = SAMGR_GetInstance(); + if (sm == nullptr) { + return; + } + // 注册服务到Samgr + sm->RegisterFeature(BMS_SERVICE, reinterpret_cast(BundleMsFeature::GetInstance())); + sm->RegisterFeatureApi(BMS_SERVICE, BMS_FEATURE, + GetBmsFeatureApi(reinterpret_cast(BundleMsFeature::GetInstance()))); + HILOG_DEBUG(HILOG_MODULE_APP, "BundleMS feature start success"); + } + APP_FEATURE_INIT(Init); + ``` -![](figures/bms策略举例.png) +完成以上开发步骤后,开发者在Samgr注册服务时,Samgr会调用IPC通信鉴权组件的GetCommunicationStrategy接口获取服务的访问策略;当其他服务或应用通过IPC方式访问这些服务时,Samgr会调用IPC通信鉴权组件的IsCommunicationAllowed接口检查调用者服务的权限,如果满足访问策略,则可以访问开发者接口,否则拒绝访问。 -访问策略有三种类型: - -**图 2** 访问策略结构体 - - -![](figures/策略类型2.png) - -1. type为RANGE类型:允许某个特定范围UID的进程访问,需要指定uidMin和uidMax - -2. type为FIXED类型:允许指定的几个UID的进程访问,需要指定fixedUid,最多配置8个 - -3. type为BUNDLENAME类型:只允许特定的应用访问,需要指定bundleName(包名) - -二、将定义的Feature的策略加配到全局策略中,需要配置feature数量,注册参考图3 - -**图 3** feature策略注册 - - -![](figures/全局策略2.png) - -UID分配规则 - -1. Init进程:0 - -2. appspawn进程:1 - -3. Shell进程:2 - -4. 其他内置系统服务UID <= 99 - -5. 系统应用(如设置、桌面、相机):100 \~ 999 - -6. 预置厂商应用:1000 \~ 9999 - -7. 普通三方应用:10000 \~ INT\_MAX +## 相关仓 +安全子系统 +security\_permission diff --git a/figures/bms策略举例.png b/figures/bms策略举例.png deleted file mode 100755 index fb9c3d8c66673f5c5b69718f59bb09dab16e48a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12558 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 diff --git a/figures/en-us_image_0000001113598272.png b/figures/en-us_image_0000001113598272.png new file mode 100644 index 0000000000000000000000000000000000000000..b9cd9677c107f631ad1e6dab6cb68198012cf6d1 GIT binary patch literal 25160 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 N7G^f4)h4$e{tw*UteOA- diff --git a/figures/策略类型2.png b/figures/策略类型2.png deleted file mode 100755 index 1ad38251b4d9abba2076bfc2df91fa14c81ac07d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7247 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 + +#include "permission_def_parcel.h" + +#include "iremote_broker.h" +#include "errors.h" + +namespace OHOS { +namespace Security { +namespace Permission { +class IPermissionManager : public IRemoteBroker { +public: + static const int SA_ID_PERMISSION_MANAGER_SERVICE = 3501; + + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.security.permission.IPermissionManager"); + + virtual int VerifyPermission(const std::string& bundleName, const std::string& permissionName, int userId) = 0; + + virtual bool CanRequestPermission(const std::string& bundleName, const std::string& permissionName, int userId) = 0; + + virtual int GrantUserGrantedPermission( + const std::string& bundleName, const std::string& permissionName, int userId) = 0; + + virtual int GrantSystemGrantedPermission(const std::string& bundleName, const std::string& permissionName) = 0; + + virtual int RevokeUserGrantedPermission( + const std::string& bundleName, const std::string& permissionName, int userId) = 0; + + virtual int RevokeSystemGrantedPermission(const std::string& bundleName, const std::string& permissionName) = 0; + + virtual int AddUserGrantedReqPermissions( + const std::string& bundleName, const std::vector& permList, int userId) = 0; + + virtual int AddSystemGrantedReqPermissions( + const std::string& bundleName, const std::vector& permList) = 0; + + virtual int RemoveUserGrantedReqPermissions(const std::string& bundleName, int userId) = 0; + + virtual int RemoveSystemGrantedReqPermissions(const std::string& bundleName) = 0; + + virtual int AddDefPermissions(const std::vector& permDefList) = 0; + + virtual int RemoveDefPermissions(const std::string& bundleName) = 0; + + virtual int GetDefPermission(const std::string& permissionName, PermissionDefParcel& permissionDefResult) = 0; + + enum class InterfaceCode { + VERIFY_PERMISSION = 0xff01, + CAN_REQUEST_PERMISSION = 0xff02, + GRANT_USER_GRANTED_PERMISSION = 0xff03, + GRANT_SYSTEM_GRANTED_PERMISSION = 0xff04, + REVOKE_USER_GRANTED_PERMISSION = 0xff05, + REVOKE_SYSTEM_GRANTED_PERMISSION = 0xff06, + ADD_USER_GRANTED_REQ_PERMISSIONS = 0xff07, + ADD_SYSTEM_GRANTED_REQ_PERMISSIONS = 0xff08, + REMOVE_USER_GRANTED_REQ_PERMISSIONS = 0xff09, + REMOVE_SYSTEM_GRANTED_REQ_PERMISSIONS = 0xff10, + ADD_DEF_PERMISSIONS = 0xff11, + REMOVE_DEF_PERMISSIONS = 0xff12, + GET_DEF_PERMISSION = 0xff13, + }; +}; +} // namespace Permission +} // namespace Security +} // namespace OHOS + +#endif // I_PERMISSION_MANAGER_H diff --git a/frameworks/permission_standard/permissioncommunicationadapter/main/cpp/include/permission_def_parcel.h b/frameworks/permission_standard/permissioncommunicationadapter/main/cpp/include/permission_def_parcel.h new file mode 100755 index 0000000..e1e8504 --- /dev/null +++ b/frameworks/permission_standard/permissioncommunicationadapter/main/cpp/include/permission_def_parcel.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PERMISSION_DEF_PARCEL_H +#define PERMISSION_DEF_PARCEL_H + +#include "permission_def.h" + +#include "parcel.h" + +namespace OHOS { +namespace Security { +namespace Permission { +struct PermissionDefParcel final : public Parcelable { + PermissionDefParcel() = default; + + ~PermissionDefParcel() override = default; + + bool Marshalling(Parcel& out) const override; + + static PermissionDefParcel* Unmarshalling(Parcel& in); + + PermissionDef permissionDef; +}; +} // namespace Permission +} // namespace Security +} // namespace OHOS +#endif // PERMISSION_DEF_PARCEL_H diff --git a/frameworks/permission_standard/permissioncommunicationadapter/main/cpp/src/permission_def_parcel.cpp b/frameworks/permission_standard/permissioncommunicationadapter/main/cpp/src/permission_def_parcel.cpp new file mode 100755 index 0000000..e9cc927 --- /dev/null +++ b/frameworks/permission_standard/permissioncommunicationadapter/main/cpp/src/permission_def_parcel.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "permission_def_parcel.h" + +namespace OHOS { +namespace Security { +namespace Permission { +#define RETURN_IF_FALSE(expr) \ + if (!(expr)) { \ + return false; \ + } + +#define RELEASE_IF_FALSE(expr, obj) \ + if (!(expr)) { \ + delete (obj); \ + (obj) = nullptr; \ + return (obj); \ + } + +bool PermissionDefParcel::Marshalling(Parcel& out) const +{ + RETURN_IF_FALSE(out.WriteString(this->permissionDef.permissionName)); + RETURN_IF_FALSE(out.WriteString(this->permissionDef.bundleName)); + RETURN_IF_FALSE(out.WriteInt32(this->permissionDef.grantMode)); + RETURN_IF_FALSE(out.WriteInt32(this->permissionDef.availableScope)); + RETURN_IF_FALSE(out.WriteString(this->permissionDef.label)); + RETURN_IF_FALSE(out.WriteInt32(this->permissionDef.labelId)); + RETURN_IF_FALSE(out.WriteString(this->permissionDef.description)); + RETURN_IF_FALSE(out.WriteInt32(this->permissionDef.descriptionId)); + return true; +} + +PermissionDefParcel* PermissionDefParcel::Unmarshalling(Parcel& in) +{ + auto* permissionDefParcel = new (std::nothrow) PermissionDefParcel(); + RELEASE_IF_FALSE(permissionDefParcel != nullptr, permissionDefParcel); + permissionDefParcel->permissionDef.permissionName = in.ReadString(); + permissionDefParcel->permissionDef.bundleName = in.ReadString(); + RELEASE_IF_FALSE(in.ReadInt32(permissionDefParcel->permissionDef.grantMode), permissionDefParcel); + RELEASE_IF_FALSE(in.ReadInt32(permissionDefParcel->permissionDef.availableScope), permissionDefParcel); + permissionDefParcel->permissionDef.label = in.ReadString(); + RELEASE_IF_FALSE(in.ReadInt32(permissionDefParcel->permissionDef.labelId), permissionDefParcel); + permissionDefParcel->permissionDef.description = in.ReadString(); + RELEASE_IF_FALSE(in.ReadInt32(permissionDefParcel->permissionDef.descriptionId), permissionDefParcel); + return permissionDefParcel; +} +} // namespace Permission +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/permission_standard/permissioninfrastructure/BUILD.gn b/frameworks/permission_standard/permissioninfrastructure/BUILD.gn new file mode 100644 index 0000000..1903866 --- /dev/null +++ b/frameworks/permission_standard/permissioninfrastructure/BUILD.gn @@ -0,0 +1,38 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") + +################################################################ +# C++, Main source file here. +################################################################ +config("permission_standard_infrastructure_cxx_public_config") { + visibility = [ ":*" ] + include_dirs = [ "main/cpp/include" ] +} + +ohos_shared_library("permission_standard_infrastructure_cxx") { + subsystem_name = "security" + part_name = "permission_standard" + + public_configs = [ ":permission_standard_infrastructure_cxx_public_config" ] + + include_dirs = [] + + sources = [ "main/cpp/src/data_validator.cpp" ] + + deps = [ "//utils/native/base:utils" ] + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] + + cflags_cc = [ "-DHILOG_ENABLE" ] +} diff --git a/frameworks/permission_standard/permissioninfrastructure/main/cpp/include/data_validator.h b/frameworks/permission_standard/permissioninfrastructure/main/cpp/include/data_validator.h new file mode 100755 index 0000000..1976865 --- /dev/null +++ b/frameworks/permission_standard/permissioninfrastructure/main/cpp/include/data_validator.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#ifndef DATA_VALIDATOR_H +#define DATA_VALIDATOR_H +namespace OHOS { +namespace Security { +namespace Permission { +class DataValidator final { +public: + static bool IsBundleNameValid(const std::string& bundleName); + + static bool IsPermissionNameValid(const std::string& permissionName); + + static bool IsUserIdValid(const int userId); + +private: + const static int MAX_LENGTH = 256; +}; +} // namespace Permission +} // namespace Security +} // namespace OHOS +#endif // DATA_VALIDATOR_H diff --git a/frameworks/permission_standard/permissioninfrastructure/main/cpp/include/permission_log.h b/frameworks/permission_standard/permissioninfrastructure/main/cpp/include/permission_log.h new file mode 100644 index 0000000..30cbae7 --- /dev/null +++ b/frameworks/permission_standard/permissioninfrastructure/main/cpp/include/permission_log.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PERMISSION_LOG_H +#define PERMISSION_LOG_H + +#ifdef HILOG_ENABLE + +#include "hilog/log.h" + +#ifndef __cplusplus + +#define PERMISSION_LOG_DEBUG(fmt, ...) HILOG_DEBUG(LOG_CORE, fmt, ##__VA_ARGS__) +#define PERMISSION_LOG_INFO(fmt, ...) HILOG_INFO(LOG_CORE, fmt, ##__VA_ARGS__) +#define PERMISSION_LOG_WARN(fmt, ...) HILOG_WARN(LOG_CORE, fmt, ##__VA_ARGS__) +#define PERMISSION_LOG_ERROR(fmt, ...) HILOG_ERROR(LOG_CORE, fmt, ##__VA_ARGS__) +#define PERMISSION_LOG_FATAL(fmt, ...) HILOG_FATAL(LOG_CORE, fmt, ##__VA_ARGS__) + +#else + +#define PERMISSION_LOG_DEBUG(label, fmt, ...) OHOS::HiviewDFX::HiLog::Debug(label, fmt, ##__VA_ARGS__) +#define PERMISSION_LOG_INFO(label, fmt, ...) OHOS::HiviewDFX::HiLog::Info(label, fmt, ##__VA_ARGS__) +#define PERMISSION_LOG_WARN(label, fmt, ...) OHOS::HiviewDFX::HiLog::Warn(label, fmt, ##__VA_ARGS__) +#define PERMISSION_LOG_ERROR(label, fmt, ...) OHOS::HiviewDFX::HiLog::Error(label, fmt, ##__VA_ARGS__) +#define PERMISSION_LOG_FATAL(label, fmt, ...) OHOS::HiviewDFX::HiLog::Fatal(label, fmt, ##__VA_ARGS__) + +#endif // __cplusplus + +/* define LOG_TAG as "security_*" at your submodule, * means your submodule name such as "security_dac" */ +#undef LOG_TAG +#undef LOG_DOMAIN + +static constexpr unsigned int SECURITY_DOMAIN_PERMISSION = 0xD002F01; + +#else + +#include +#include + +/* define LOG_TAG as "security_*" at your submodule, * means your submodule name such as "security_dac" */ +#undef LOG_TAG + +#define PERMISSION_LOG_DEBUG(fmt, ...) printf("[%s] debug: %s: " fmt "\n", LOG_TAG, __func__, ##__VA_ARGS__) +#define PERMISSION_LOG_INFO(fmt, ...) printf("[%s] info: %s: " fmt "\n", LOG_TAG, __func__, ##__VA_ARGS__) +#define PERMISSION_LOG_WARN(fmt, ...) printf("[%s] warn: %s: " fmt "\n", LOG_TAG, __func__, ##__VA_ARGS__) +#define PERMISSION_LOG_ERROR(fmt, ...) printf("[%s] error: %s: " fmt "\n", LOG_TAG, __func__, ##__VA_ARGS__) +#define PERMISSION_LOG_FATAL(fmt, ...) printf("[%s] fatal: %s: " fmt "\n", LOG_TAG, __func__, ##__VA_ARGS__) + +#endif // HILOG_ENABLE + +#endif // PERMISSION_LOG_H diff --git a/frameworks/permission_standard/permissioninfrastructure/main/cpp/include/test_const.h b/frameworks/permission_standard/permissioninfrastructure/main/cpp/include/test_const.h new file mode 100644 index 0000000..d34f157 --- /dev/null +++ b/frameworks/permission_standard/permissioninfrastructure/main/cpp/include/test_const.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TEST_CONST_H +#define TEST_CONST_H + +#include + +namespace OHOS { +namespace Security { +namespace Permission { +static const std::string TEST_BUNDLE_NAME = "ohos"; +static const std::string TEST_PERMISSION_NAME_ALPHA = "ohos.permission.ALPHA"; +static const std::string TEST_PERMISSION_NAME_BETA = "ohos.permission.BETA"; +static const std::string TEST_PERMISSION_NAME_GAMMA = "ohos.permission.GAMMA"; +static const std::string TEST_LABEL = "test label"; +static const std::string TEST_DESCRIPTION = "test description"; + +static const int TEST_LABEL_ID = 9527; +static const int TEST_DESCRIPTION_ID = 9528; +static const int TEST_INVALID_USER_ID = -1; +static const int TEST_USER_ID = 0; +static const int TEST_SUB_USER_ID = 10; +} // namespace Permission +} // namespace Security +} // namespace OHOS +#endif // TEST_CONST_H diff --git a/frameworks/permission_standard/permissioninfrastructure/main/cpp/src/data_validator.cpp b/frameworks/permission_standard/permissioninfrastructure/main/cpp/src/data_validator.cpp new file mode 100644 index 0000000..445be70 --- /dev/null +++ b/frameworks/permission_standard/permissioninfrastructure/main/cpp/src/data_validator.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "data_validator.h" + +namespace OHOS { +namespace Security { +namespace Permission { +bool DataValidator::IsBundleNameValid(const std::string& bundleName) +{ + return !bundleName.empty() && (bundleName.length() <= MAX_LENGTH); +} + +bool DataValidator::IsPermissionNameValid(const std::string& permissionName) +{ + return !permissionName.empty() && (permissionName.length() <= MAX_LENGTH); +} + +bool DataValidator::IsUserIdValid(const int userId) +{ + return userId >= 0; +} +} // namespace Permission +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/innerkits/permission_lite/pms_interface_inner.h b/interfaces/innerkits/permission_lite/pms_interface_inner.h old mode 100644 new mode 100755 diff --git a/interfaces/innerkits/permission_standard/permissionsdk/BUILD.gn b/interfaces/innerkits/permission_standard/permissionsdk/BUILD.gn new file mode 100755 index 0000000..38fb93b --- /dev/null +++ b/interfaces/innerkits/permission_standard/permissionsdk/BUILD.gn @@ -0,0 +1,58 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") + +################################################################ +# C++, Main, source file here. +################################################################ +config("permission_sdk_cxx_public_config_standard") { + visibility = [ ":*" ] + include_dirs = [ "main/cpp/include" ] +} + +ohos_shared_library("libpermissionsdk_standard") { + subsystem_name = "security" + part_name = "permission_standard" + + output_name = "libpermissionsdk_standard" + + public_configs = [ ":permission_sdk_cxx_public_config_standard" ] + + include_dirs = [ + "//utils/native/base/include", + "main/cpp/include", + "main/cpp/src", + "//base/security/permission/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/include/permission", + ] + + sources = [ + "main/cpp/src/permission/permission_kit.cpp", + "main/cpp/src/permission/permission_manager_client.cpp", + "main/cpp/src/permission/permission_manager_proxy.cpp", + ] + + deps = [ + "//base/security/permission/frameworks/permission_standard/permissioncommunicationadapter:permission_standard_communication_adapter_cxx", + "//base/security/permission/frameworks/permission_standard/permissioninfrastructure:permission_standard_infrastructure_cxx", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "samgr_L2:samgr_proxy", + ] + + cflags_cc = [ "-DHILOG_ENABLE" ] +} diff --git a/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/include/permission/permission.h b/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/include/permission/permission.h new file mode 100755 index 0000000..fc9bb16 --- /dev/null +++ b/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/include/permission/permission.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_INNER_KITS_PERMISSION_PERMISSION_H +#define INTERFACES_INNER_KITS_PERMISSION_PERMISSION_H + +namespace OHOS { +namespace Security { +namespace Permission { +enum PermissionKitRet { + RET_FAILED = -1, + RET_SUCCESS = 0, +}; + +typedef enum TypePermissionState { + PERMISSION_NOT_GRANTED = -1, + PERMISSION_GRANTED = 0, +} PermissionState; + +typedef enum TypeGrantMode { + USER_GRANT = 0, + SYSTEM_GRANT = 1, +} GrantMode; + +typedef enum TypeAvailableScope { + AVAILABLE_SCOPE_ALL = 1 << 0, + AVAILABLE_SCOPE_SIGNATURE = 1 << 1, + AVAILABLE_SCOPE_RESTRICTED = 1 << 2 +} AvailableScope; +} // namespace Permission +} // namespace Security +} // namespace OHOS + +#endif // INTERFACES_INNER_KITS_PERMISSION_PERMISSION_H \ No newline at end of file diff --git a/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/include/permission/permission_def.h b/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/include/permission/permission_def.h new file mode 100755 index 0000000..39aefdf --- /dev/null +++ b/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/include/permission/permission_def.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_INNER_KITS_PERMISSION_PERMISSION_DEF_H +#define INTERFACES_INNER_KITS_PERMISSION_PERMISSION_DEF_H + +#include + +namespace OHOS { +namespace Security { +namespace Permission { +struct PermissionDef { + std::string permissionName; + std::string bundleName; + int grantMode; + int availableScope; + std::string label; + int labelId; + std::string description; + int descriptionId; +}; +} // namespace Permission +} // namespace Security +} // namespace OHOS + +#endif // INTERFACES_INNER_KITS_PERMISSION_PERMISSION_DEF_H \ No newline at end of file diff --git a/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/include/permission/permission_kit.h b/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/include/permission/permission_kit.h new file mode 100755 index 0000000..33bf3fc --- /dev/null +++ b/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/include/permission/permission_kit.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_INNER_KITS_PERMISSION_PERMISSION_KIT_H +#define INTERFACES_INNER_KITS_PERMISSION_PERMISSION_KIT_H + +#include +#include + +#include "permission/permission.h" +#include "permission/permission_def.h" + +namespace OHOS { +namespace Security { +namespace Permission { +class PermissionKit { +public: + static int VerifyPermission(const std::string& bundleName, const std::string& permissionName, int userId); + static bool CanRequestPermission(const std::string& bundleName, const std::string& permissionName, int userId); + + static int GrantUserGrantedPermission( + const std::string& bundleName, const std::string& permissionName, int userId); + static int GrantSystemGrantedPermission(const std::string& bundleName, const std::string& permissionName); + + static int RevokeUserGrantedPermission( + const std::string& bundleName, const std::string& permissionName, int userId); + static int RevokeSystemGrantedPermission(const std::string& bundleName, const std::string& permissionName); + + static int AddUserGrantedReqPermissions( + const std::string& bundleName, const std::vector& permList, int userId); + static int AddSystemGrantedReqPermissions( + const std::string& bundleName, const std::vector& permList); + + static int RemoveUserGrantedReqPermissions(const std::string& bundleName, int userId); + static int RemoveSystemGrantedReqPermissions(const std::string& bundleName); + + static int AddDefPermissions(const std::vector& permList); + static int RemoveDefPermissions(const std::string& bundleName); + static int GetDefPermission(const std::string& permissionName, PermissionDef& permissionDefResult); +}; +} // namespace Permission +} // namespace Security +} // namespace OHOS + +#endif diff --git a/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/src/permission/permission_kit.cpp b/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/src/permission/permission_kit.cpp new file mode 100755 index 0000000..a5df2a5 --- /dev/null +++ b/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/src/permission/permission_kit.cpp @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "permission/permission_kit.h" + +#include +#include + +#include "permission_log.h" +#include "permission_manager_client.h" +#include "data_validator.h" + +namespace OHOS { +namespace Security { +namespace Permission { +using namespace std; + +namespace { +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_PERMISSION, "PermissionKit"}; +} // namespace + +int PermissionKit::VerifyPermission(const string& bundleName, const string& permissionName, int userId) +{ + PERMISSION_LOG_INFO(LABEL, "%{public}s called", __func__); + PERMISSION_LOG_INFO(LABEL, "bundleName=%{public}s, permissionName=%{public}s, userId=%{public}d", + bundleName.c_str(), permissionName.c_str(), userId); + if (!DataValidator::IsBundleNameValid(bundleName) || !DataValidator::IsPermissionNameValid(permissionName) || + !DataValidator::IsUserIdValid(userId)) { + return PERMISSION_NOT_GRANTED; + } + return PermissionManagerClient::GetInstance().VerifyPermission(bundleName, permissionName, userId); +} + +bool PermissionKit::CanRequestPermission(const string& bundleName, const string& permissionName, int userId) +{ + PERMISSION_LOG_INFO(LABEL, "%{public}s called", __func__); + PERMISSION_LOG_INFO(LABEL, "bundleName=%{public}s, permissionName=%{public}s, userId=%{public}d", + bundleName.c_str(), permissionName.c_str(), userId); + if (!DataValidator::IsBundleNameValid(bundleName) || !DataValidator::IsPermissionNameValid(permissionName) || + !DataValidator::IsUserIdValid(userId)) { + return false; + } + return PermissionManagerClient::GetInstance().CanRequestPermission(bundleName, permissionName, userId); +} + +int PermissionKit::GrantUserGrantedPermission(const string& bundleName, const string& permissionName, int userId) +{ + PERMISSION_LOG_INFO(LABEL, "%{public}s called", __func__); + PERMISSION_LOG_INFO(LABEL, "bundleName=%{public}s, permissionName=%{public}s, userId=%{public}d", + bundleName.c_str(), permissionName.c_str(), userId); + return PermissionManagerClient::GetInstance().GrantUserGrantedPermission(bundleName, permissionName, userId); +} + +int PermissionKit::GrantSystemGrantedPermission(const string& bundleName, const string& permissionName) +{ + PERMISSION_LOG_INFO(LABEL, "%{public}s called", __func__); + PERMISSION_LOG_INFO( + LABEL, "bundleName=%{public}s, permissionName=%{public}s", bundleName.c_str(), permissionName.c_str()); + return PermissionManagerClient::GetInstance().GrantSystemGrantedPermission(bundleName, permissionName); +} + +int PermissionKit::RevokeUserGrantedPermission(const string& bundleName, const string& permissionName, int userId) +{ + PERMISSION_LOG_INFO(LABEL, "%{public}s called", __func__); + PERMISSION_LOG_INFO(LABEL, "bundleName=%{public}s, permissionName=%{public}s, userId=%{public}d", + bundleName.c_str(), permissionName.c_str(), userId); + return PermissionManagerClient::GetInstance().RevokeUserGrantedPermission(bundleName, permissionName, userId); +} + +int PermissionKit::RevokeSystemGrantedPermission(const string& bundleName, const string& permissionName) +{ + PERMISSION_LOG_INFO(LABEL, "%{public}s called", __func__); + PERMISSION_LOG_INFO( + LABEL, "bundleName=%{public}s, permissionName=%{public}s", bundleName.c_str(), permissionName.c_str()); + return PermissionManagerClient::GetInstance().RevokeSystemGrantedPermission(bundleName, permissionName); +} + +int PermissionKit::AddUserGrantedReqPermissions( + const string& bundleName, const std::vector& permList, int userId) +{ + PERMISSION_LOG_INFO(LABEL, "%{public}s called", __func__); + PERMISSION_LOG_INFO(LABEL, "bundleName=%{public}s, userId=%{public}d", bundleName.c_str(), userId); + return PermissionManagerClient::GetInstance().AddUserGrantedReqPermissions(bundleName, permList, userId); +} + +int PermissionKit::AddSystemGrantedReqPermissions(const string& bundleName, const std::vector& permList) +{ + PERMISSION_LOG_INFO(LABEL, "%{public}s called", __func__); + PERMISSION_LOG_INFO(LABEL, "bundleName=%{public}s", bundleName.c_str()); + return PermissionManagerClient::GetInstance().AddSystemGrantedReqPermissions(bundleName, permList); +} + +int PermissionKit::RemoveUserGrantedReqPermissions(const string& bundleName, int userId) +{ + PERMISSION_LOG_INFO(LABEL, "%{public}s called", __func__); + PERMISSION_LOG_INFO(LABEL, "bundleName=%{public}s, userId=%{public}d", bundleName.c_str(), userId); + return PermissionManagerClient::GetInstance().RemoveUserGrantedReqPermissions(bundleName, userId); +} + +int PermissionKit::RemoveSystemGrantedReqPermissions(const string& bundleName) +{ + PERMISSION_LOG_INFO(LABEL, "%{public}s called", __func__); + PERMISSION_LOG_INFO(LABEL, "bundleName=%{public}s", bundleName.c_str()); + return PermissionManagerClient::GetInstance().RemoveSystemGrantedReqPermissions(bundleName); +} + +int PermissionKit::AddDefPermissions(const std::vector& permList) +{ + PERMISSION_LOG_INFO(LABEL, "%{public}s called", __func__); + return PermissionManagerClient::GetInstance().AddDefPermissions(permList); +} + +int PermissionKit::RemoveDefPermissions(const string& bundleName) +{ + PERMISSION_LOG_INFO(LABEL, "%{public}s called", __func__); + PERMISSION_LOG_INFO(LABEL, "bundleName=%{public}s", bundleName.c_str()); + return PermissionManagerClient::GetInstance().RemoveDefPermissions(bundleName); +} + +int PermissionKit::GetDefPermission(const string& permissionName, PermissionDef& permissionDefResult) +{ + PERMISSION_LOG_INFO(LABEL, "%{public}s called", __func__); + PERMISSION_LOG_INFO(LABEL, "permissionName=%{public}s", permissionName.c_str()); + int ret = PermissionManagerClient::GetInstance().GetDefPermission(permissionName, permissionDefResult); + PERMISSION_LOG_INFO(LABEL, "GetDefPermission bundleName = %{public}s", permissionDefResult.bundleName.c_str()); + return ret; +} +} // namespace Permission +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/src/permission/permission_manager_client.cpp b/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/src/permission/permission_manager_client.cpp new file mode 100644 index 0000000..1d0779d --- /dev/null +++ b/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/src/permission/permission_manager_client.cpp @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "permission_manager_client.h" + +#include "permission.h" +#include "permission_log.h" + +#include "iservice_registry.h" + +namespace OHOS { +namespace Security { +namespace Permission { +namespace { +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_PERMISSION, "PermissionManagerClient"}; +} // namespace + +PermissionManagerClient& PermissionManagerClient::GetInstance() +{ + static PermissionManagerClient instance; + return instance; +} + +PermissionManagerClient::PermissionManagerClient() +{} + +PermissionManagerClient::~PermissionManagerClient() +{} + +int PermissionManagerClient::VerifyPermission( + const std::string& bundleName, const std::string& permissionName, int userId) const +{ + PERMISSION_LOG_DEBUG(LABEL, "%{public}s: called!", __func__); + auto proxy = GetProxy(); + if (proxy == nullptr) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: proxy is null", __func__); + return PERMISSION_NOT_GRANTED; + } + return proxy->VerifyPermission(bundleName, permissionName, userId); +} + +bool PermissionManagerClient::CanRequestPermission( + const std::string& bundleName, const std::string& permissionName, int userId) const +{ + PERMISSION_LOG_DEBUG(LABEL, "%{public}s: called!", __func__); + auto proxy = GetProxy(); + if (proxy == nullptr) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: proxy is null", __func__); + return false; + } + return proxy->CanRequestPermission(bundleName, permissionName, userId); +} + +int PermissionManagerClient::GrantUserGrantedPermission( + const std::string& bundleName, const std::string& permissionName, int userId) const +{ + PERMISSION_LOG_DEBUG(LABEL, "%{public}s: called!", __func__); + auto proxy = GetProxy(); + if (proxy == nullptr) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: proxy is null", __func__); + return RET_FAILED; + } + return proxy->GrantUserGrantedPermission(bundleName, permissionName, userId); +} + +int PermissionManagerClient::GrantSystemGrantedPermission( + const std::string& bundleName, const std::string& permissionName) const +{ + PERMISSION_LOG_DEBUG(LABEL, "%{public}s: called!", __func__); + auto proxy = GetProxy(); + if (proxy == nullptr) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: proxy is null", __func__); + return RET_FAILED; + } + return proxy->GrantSystemGrantedPermission(bundleName, permissionName); +} + +int PermissionManagerClient::RevokeUserGrantedPermission( + const std::string& bundleName, const std::string& permissionName, int userId) const +{ + PERMISSION_LOG_DEBUG(LABEL, "%{public}s: called!", __func__); + auto proxy = GetProxy(); + if (proxy == nullptr) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: proxy is null", __func__); + return RET_FAILED; + } + return proxy->RevokeUserGrantedPermission(bundleName, permissionName, userId); +} + +int PermissionManagerClient::RevokeSystemGrantedPermission( + const std::string& bundleName, const std::string& permissionName) const +{ + PERMISSION_LOG_DEBUG(LABEL, "%{public}s: called!", __func__); + auto proxy = GetProxy(); + if (proxy == nullptr) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: proxy is null", __func__); + return RET_FAILED; + } + return proxy->RevokeSystemGrantedPermission(bundleName, permissionName); +} + +int PermissionManagerClient::AddUserGrantedReqPermissions( + const std::string& bundleName, const std::vector& permList, int userId) const +{ + PERMISSION_LOG_DEBUG(LABEL, "%{public}s: called!", __func__); + auto proxy = GetProxy(); + if (proxy == nullptr) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: proxy is null", __func__); + return RET_FAILED; + } + return proxy->AddUserGrantedReqPermissions(bundleName, permList, userId); +} + +int PermissionManagerClient::AddSystemGrantedReqPermissions( + const std::string& bundleName, const std::vector& permList) const +{ + PERMISSION_LOG_DEBUG(LABEL, "%{public}s: called!", __func__); + auto proxy = GetProxy(); + if (proxy == nullptr) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: proxy is null", __func__); + return RET_FAILED; + } + return proxy->AddSystemGrantedReqPermissions(bundleName, permList); +} + +int PermissionManagerClient::RemoveUserGrantedReqPermissions(const std::string& bundleName, int userId) const +{ + PERMISSION_LOG_DEBUG(LABEL, "%{public}s: called!", __func__); + auto proxy = GetProxy(); + if (proxy == nullptr) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: proxy is null", __func__); + return RET_FAILED; + } + return proxy->RemoveUserGrantedReqPermissions(bundleName, userId); +} + +int PermissionManagerClient::RemoveSystemGrantedReqPermissions(const std::string& bundleName) const +{ + PERMISSION_LOG_DEBUG(LABEL, "%{public}s: called!", __func__); + auto proxy = GetProxy(); + if (proxy == nullptr) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: proxy is null", __func__); + return RET_FAILED; + } + return proxy->RemoveSystemGrantedReqPermissions(bundleName); +} + +int PermissionManagerClient::AddDefPermissions(const std::vector& permDefList) const +{ + PERMISSION_LOG_DEBUG(LABEL, "%{public}s: called!", __func__); + auto proxy = GetProxy(); + if (proxy == nullptr) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: proxy is null", __func__); + return RET_FAILED; + } + std::vector parcelList; + for (auto permDef : permDefList) { + PermissionDefParcel parcel; + parcel.permissionDef = permDef; + parcelList.emplace_back(parcel); + } + PERMISSION_LOG_INFO(LABEL, "%{public}s called, permList size: %{public}d", __func__, (int) parcelList.size()); + return proxy->AddDefPermissions(parcelList); +} + +int PermissionManagerClient::RemoveDefPermissions(const std::string& bundleName) const +{ + PERMISSION_LOG_DEBUG(LABEL, "%{public}s: called!", __func__); + auto proxy = GetProxy(); + if (proxy == nullptr) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: proxy is null", __func__); + return RET_FAILED; + } + return proxy->RemoveDefPermissions(bundleName); +} + +int PermissionManagerClient::GetDefPermission( + const std::string& permissionName, PermissionDef& permissionDefResult) const +{ + PERMISSION_LOG_DEBUG(LABEL, "%{public}s: called!", __func__); + auto proxy = GetProxy(); + if (proxy == nullptr) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: proxy is null", __func__); + return RET_FAILED; + } + PermissionDefParcel permissionDefParcel; + int result = proxy->GetDefPermission(permissionName, permissionDefParcel); + permissionDefResult = permissionDefParcel.permissionDef; + return result; +} + +sptr PermissionManagerClient::GetProxy() const +{ + auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (sam == nullptr) { + PERMISSION_LOG_DEBUG(LABEL, "%{public}s: GetSystemAbilityManager is null", __func__); + return nullptr; + } + auto permissionSa = sam->GetSystemAbility(IPermissionManager::SA_ID_PERMISSION_MANAGER_SERVICE); + if (permissionSa == nullptr) { + PERMISSION_LOG_DEBUG(LABEL, "%{public}s: GetSystemAbility %{public}d is null", __func__, + IPermissionManager::SA_ID_PERMISSION_MANAGER_SERVICE); + return nullptr; + } + + auto proxy = iface_cast(permissionSa); + if (proxy == nullptr) { + PERMISSION_LOG_DEBUG(LABEL, "%{public}s: iface_cast get null", __func__); + return nullptr; + } + return proxy; +} +} // namespace Permission +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/src/permission/permission_manager_client.h b/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/src/permission/permission_manager_client.h new file mode 100755 index 0000000..a320048 --- /dev/null +++ b/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/src/permission/permission_manager_client.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PERMISSION_MANAGER_CLIENT_H +#define PERMISSION_MANAGER_CLIENT_H + +#include + +#include "i_permission_manager.h" +#include "permission/permission_def.h" + +#include "nocopyable.h" + +namespace OHOS { +namespace Security { +namespace Permission { +class PermissionManagerClient final { +public: + static PermissionManagerClient& GetInstance(); + + virtual ~PermissionManagerClient(); + + int VerifyPermission(const std::string& bundleName, const std::string& permissionName, int userId) const; + + bool CanRequestPermission(const std::string& bundleName, const std::string& permissionName, int userId) const; + + int GrantUserGrantedPermission(const std::string& bundleName, const std::string& permissionName, int userId) const; + + int GrantSystemGrantedPermission(const std::string& bundleName, const std::string& permissionName) const; + + int RevokeUserGrantedPermission(const std::string& bundleName, const std::string& permissionName, int userId) const; + + int RevokeSystemGrantedPermission(const std::string& bundleName, const std::string& permissionName) const; + + int AddUserGrantedReqPermissions( + const std::string& bundleName, const std::vector& permList, int userId) const; + + int AddSystemGrantedReqPermissions(const std::string& bundleName, const std::vector& permList) const; + + int RemoveUserGrantedReqPermissions(const std::string& bundleName, int userId) const; + + int RemoveSystemGrantedReqPermissions(const std::string& bundleName) const; + + int AddDefPermissions(const std::vector& permDefList) const; + + int RemoveDefPermissions(const std::string& bundleName) const; + + int GetDefPermission(const std::string& permissionName, PermissionDef& permissionDefResult) const; + +private: + PermissionManagerClient(); + + DISALLOW_COPY_AND_MOVE(PermissionManagerClient); + + sptr GetProxy() const; +}; +} // namespace Permission +} // namespace Security +} // namespace OHOS +#endif // PERMISSION_MANAGER_CLIENT_H diff --git a/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/src/permission/permission_manager_proxy.cpp b/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/src/permission/permission_manager_proxy.cpp new file mode 100644 index 0000000..3a57008 --- /dev/null +++ b/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/src/permission/permission_manager_proxy.cpp @@ -0,0 +1,482 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "permission_manager_proxy.h" + +#include "permission/permission.h" +#include "permission_log.h" + +#include "parcel.h" +#include "string_ex.h" + +namespace OHOS { +namespace Security { +namespace Permission { +namespace { +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_PERMISSION, "PermissionManagerProxy"}; +} + +PermissionManagerProxy::PermissionManagerProxy(const sptr& impl) : IRemoteProxy(impl) +{} + +PermissionManagerProxy::~PermissionManagerProxy() +{} + +int PermissionManagerProxy::VerifyPermission( + const std::string& bundleName, const std::string& permissionName, int userId) +{ + MessageParcel data; + data.WriteInterfaceToken(IPermissionManager::GetDescriptor()); + if (!data.WriteString(bundleName)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: Failed to write bundleName", __func__); + return PERMISSION_NOT_GRANTED; + } + if (!data.WriteString(permissionName)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: Failed to write permissionName", __func__); + return PERMISSION_NOT_GRANTED; + } + if (!data.WriteInt32(userId)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: Failed to write userId", __func__); + return PERMISSION_NOT_GRANTED; + } + + MessageParcel reply; + MessageOption option; + sptr remote = Remote(); + if (remote == nullptr) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: remote service null.", __func__); + return PERMISSION_NOT_GRANTED; + } + int32_t requestResult = remote->SendRequest( + static_cast(IPermissionManager::InterfaceCode::VERIFY_PERMISSION), data, reply, option); + if (requestResult != NO_ERROR) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s send request fail, result: %{public}d", __func__, requestResult); + return PERMISSION_NOT_GRANTED; + } + + int32_t result = reply.ReadInt32(); + PERMISSION_LOG_DEBUG(LABEL, "%{public}s get result from server data = %{public}d", __func__, result); + return result; +} + +bool PermissionManagerProxy::CanRequestPermission( + const std::string& bundleName, const std::string& permissionName, int userId) +{ + MessageParcel data; + data.WriteInterfaceToken(IPermissionManager::GetDescriptor()); + if (!data.WriteString(bundleName)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: Failed to write bundleName", __func__); + return false; + } + if (!data.WriteString(permissionName)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: Failed to write permissionName", __func__); + return false; + } + if (!data.WriteInt32(userId)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: Failed to write userId", __func__); + return false; + } + + MessageParcel reply; + MessageOption option; + sptr remote = Remote(); + if (remote == nullptr) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: remote service null.", __func__); + return false; + } + int32_t requestResult = remote->SendRequest( + static_cast(IPermissionManager::InterfaceCode::CAN_REQUEST_PERMISSION), data, reply, option); + if (requestResult != NO_ERROR) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s send request fail, result: %{public}d", __func__, requestResult); + return false; + } + + bool result = reply.ReadBool(); + PERMISSION_LOG_DEBUG(LABEL, "%{public}s get result from server data = %{public}d", __func__, result); + return result; +} + +int PermissionManagerProxy::GrantUserGrantedPermission( + const std::string& bundleName, const std::string& permissionName, int userId) +{ + MessageParcel data; + data.WriteInterfaceToken(IPermissionManager::GetDescriptor()); + if (!data.WriteString(bundleName)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: Failed to write bundleName", __func__); + return RET_FAILED; + } + if (!data.WriteString(permissionName)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: Failed to write permissionName", __func__); + return RET_FAILED; + } + if (!data.WriteInt32(userId)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: Failed to write userId", __func__); + return RET_FAILED; + } + + MessageParcel reply; + MessageOption option; + sptr remote = Remote(); + if (remote == nullptr) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: remote service null.", __func__); + return RET_FAILED; + } + int32_t requestResult = remote->SendRequest( + static_cast(IPermissionManager::InterfaceCode::GRANT_USER_GRANTED_PERMISSION), data, reply, option); + if (requestResult != NO_ERROR) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s send request fail, result: %{public}d", __func__, requestResult); + return RET_FAILED; + } + + int32_t result = reply.ReadInt32(); + PERMISSION_LOG_DEBUG(LABEL, "%{public}s get result from server data = %{public}d", __func__, result); + return result; +} + +int PermissionManagerProxy::GrantSystemGrantedPermission( + const std::string& bundleName, const std::string& permissionName) +{ + MessageParcel data; + data.WriteInterfaceToken(IPermissionManager::GetDescriptor()); + if (!data.WriteString(bundleName)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: Failed to write bundleName", __func__); + return RET_FAILED; + } + if (!data.WriteString(permissionName)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: Failed to write permissionName", __func__); + return RET_FAILED; + } + + MessageParcel reply; + MessageOption option; + sptr remote = Remote(); + if (remote == nullptr) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: remote service null.", __func__); + return RET_FAILED; + } + int32_t requestResult = remote->SendRequest( + static_cast(IPermissionManager::InterfaceCode::GRANT_SYSTEM_GRANTED_PERMISSION), data, reply, option); + if (requestResult != NO_ERROR) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s send request fail, result: %{public}d", __func__, requestResult); + return RET_FAILED; + } + + int32_t result = reply.ReadInt32(); + PERMISSION_LOG_DEBUG(LABEL, "%{public}s get result from server data = %{public}d", __func__, result); + return result; +} + +int PermissionManagerProxy::RevokeUserGrantedPermission( + const std::string& bundleName, const std::string& permissionName, int userId) +{ + MessageParcel data; + data.WriteInterfaceToken(IPermissionManager::GetDescriptor()); + if (!data.WriteString(bundleName)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: Failed to write bundleName", __func__); + return RET_FAILED; + } + if (!data.WriteString(permissionName)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: Failed to write permissionName", __func__); + return RET_FAILED; + } + if (!data.WriteInt32(userId)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: Failed to write userId", __func__); + return RET_FAILED; + } + + MessageParcel reply; + MessageOption option; + sptr remote = Remote(); + if (remote == nullptr) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: remote service null.", __func__); + return RET_FAILED; + } + int32_t requestResult = remote->SendRequest( + static_cast(IPermissionManager::InterfaceCode::REVOKE_USER_GRANTED_PERMISSION), data, reply, option); + if (requestResult != NO_ERROR) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s send request fail, result: %{public}d", __func__, requestResult); + return RET_FAILED; + } + + int32_t result = reply.ReadInt32(); + PERMISSION_LOG_DEBUG(LABEL, "%{public}s get result from server data = %{public}d", __func__, result); + return result; +} + +int PermissionManagerProxy::RevokeSystemGrantedPermission( + const std::string& bundleName, const std::string& permissionName) +{ + MessageParcel data; + data.WriteInterfaceToken(IPermissionManager::GetDescriptor()); + if (!data.WriteString(bundleName)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: Failed to write bundleName", __func__); + return RET_FAILED; + } + if (!data.WriteString(permissionName)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: Failed to write permissionName", __func__); + return RET_FAILED; + } + + MessageParcel reply; + MessageOption option; + sptr remote = Remote(); + if (remote == nullptr) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: remote service null.", __func__); + return RET_FAILED; + } + int32_t requestResult = + remote->SendRequest(static_cast(IPermissionManager::InterfaceCode::REVOKE_SYSTEM_GRANTED_PERMISSION), + data, reply, option); + if (requestResult != NO_ERROR) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s send request fail, result: %{public}d", __func__, requestResult); + return RET_FAILED; + } + + int32_t result = reply.ReadInt32(); + PERMISSION_LOG_DEBUG(LABEL, "%{public}s get result from server data = %{public}d", __func__, result); + return result; +} + +int PermissionManagerProxy::AddUserGrantedReqPermissions( + const std::string& bundleName, const std::vector& permList, int userId) +{ + MessageParcel data; + data.WriteInterfaceToken(IPermissionManager::GetDescriptor()); + if (!data.WriteString(bundleName)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: Failed to write bundleName", __func__); + return RET_FAILED; + } + if (!data.WriteStringVector(permList)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: Failed to write permList", __func__); + return RET_FAILED; + } + if (!data.WriteInt32(userId)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: Failed to write userId", __func__); + return RET_FAILED; + } + + MessageParcel reply; + MessageOption option; + sptr remote = Remote(); + if (remote == nullptr) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: remote service null.", __func__); + return RET_FAILED; + } + int32_t requestResult = + remote->SendRequest(static_cast(IPermissionManager::InterfaceCode::ADD_USER_GRANTED_REQ_PERMISSIONS), + data, reply, option); + if (requestResult != NO_ERROR) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s send request fail, result: %{public}d", __func__, requestResult); + return RET_FAILED; + } + + int32_t result = reply.ReadInt32(); + PERMISSION_LOG_DEBUG(LABEL, "%{public}s get result from server data = %{public}d", __func__, result); + return result; +} + +int PermissionManagerProxy::AddSystemGrantedReqPermissions( + const std::string& bundleName, const std::vector& permList) +{ + MessageParcel data; + data.WriteInterfaceToken(IPermissionManager::GetDescriptor()); + if (!data.WriteString(bundleName)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: Failed to write bundleName", __func__); + return RET_FAILED; + } + if (!data.WriteStringVector(permList)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: Failed to write permList", __func__); + return RET_FAILED; + } + + MessageParcel reply; + MessageOption option; + sptr remote = Remote(); + if (remote == nullptr) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: remote service null.", __func__); + return RET_FAILED; + } + int32_t requestResult = remote->SendRequest( + static_cast(IPermissionManager::InterfaceCode::ADD_SYSTEM_GRANTED_REQ_PERMISSIONS), data, reply, + option); + if (requestResult != NO_ERROR) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s send request fail, result: %{public}d", __func__, requestResult); + return RET_FAILED; + } + + int32_t result = reply.ReadInt32(); + PERMISSION_LOG_DEBUG(LABEL, "%{public}s get result from server data = %{public}d", __func__, result); + return result; +} + +int PermissionManagerProxy::RemoveUserGrantedReqPermissions(const std::string& bundleName, int userId) +{ + MessageParcel data; + data.WriteInterfaceToken(IPermissionManager::GetDescriptor()); + if (!data.WriteString(bundleName)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: Failed to write bundleName", __func__); + return RET_FAILED; + } + if (!data.WriteInt32(userId)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: Failed to write userId", __func__); + return RET_FAILED; + } + + MessageParcel reply; + MessageOption option; + sptr remote = Remote(); + if (remote == nullptr) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: remote service null.", __func__); + return RET_FAILED; + } + int32_t requestResult = remote->SendRequest( + static_cast(IPermissionManager::InterfaceCode::REMOVE_USER_GRANTED_REQ_PERMISSIONS), data, reply, + option); + if (requestResult != NO_ERROR) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s send request fail, result: %{public}d", __func__, requestResult); + return RET_FAILED; + } + + int32_t result = reply.ReadInt32(); + PERMISSION_LOG_DEBUG(LABEL, "%{public}s get result from server data = %{public}d", __func__, result); + return result; +} + +int PermissionManagerProxy::RemoveSystemGrantedReqPermissions(const std::string& bundleName) +{ + MessageParcel data; + data.WriteInterfaceToken(IPermissionManager::GetDescriptor()); + if (!data.WriteString(bundleName)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: Failed to write bundleName", __func__); + return RET_FAILED; + } + + MessageParcel reply; + MessageOption option; + sptr remote = Remote(); + if (remote == nullptr) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: remote service null.", __func__); + return RET_FAILED; + } + int32_t requestResult = remote->SendRequest( + static_cast(IPermissionManager::InterfaceCode::REMOVE_SYSTEM_GRANTED_REQ_PERMISSIONS), data, reply, + option); + if (requestResult != NO_ERROR) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s send request fail, result: %{public}d", __func__, requestResult); + return RET_FAILED; + } + + int32_t result = reply.ReadInt32(); + PERMISSION_LOG_DEBUG(LABEL, "%{public}s get result from server data = %{public}d", __func__, result); + return result; +} + +int PermissionManagerProxy::AddDefPermissions(const std::vector& permDefList) +{ + MessageParcel data; + data.WriteInterfaceToken(IPermissionManager::GetDescriptor()); + if (!data.WriteInt32(permDefList.size())) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: Failed to write permDefList's size", __func__); + return RET_FAILED; + } + for (auto permissionDef : permDefList) { + if (!data.WriteParcelable(&permissionDef)) { + return RET_FAILED; + } + } + + MessageParcel reply; + MessageOption option; + sptr remote = Remote(); + if (remote == nullptr) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: remote service null.", __func__); + return RET_FAILED; + } + int32_t requestResult = remote->SendRequest( + static_cast(IPermissionManager::InterfaceCode::ADD_DEF_PERMISSIONS), data, reply, option); + if (requestResult != NO_ERROR) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s send request fail, result: %{public}d", __func__, requestResult); + return RET_FAILED; + } + + int32_t result = reply.ReadInt32(); + PERMISSION_LOG_DEBUG(LABEL, "%{public}s get result from server data = %{public}d", __func__, result); + return result; +} + +int PermissionManagerProxy::RemoveDefPermissions(const std::string& bundleName) +{ + MessageParcel data; + data.WriteInterfaceToken(IPermissionManager::GetDescriptor()); + if (!data.WriteString(bundleName)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: Failed to write bundleName", __func__); + return RET_FAILED; + } + + MessageParcel reply; + MessageOption option; + sptr remote = Remote(); + if (remote == nullptr) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: remote service null.", __func__); + return RET_FAILED; + } + int32_t requestResult = remote->SendRequest( + static_cast(IPermissionManager::InterfaceCode::REMOVE_DEF_PERMISSIONS), data, reply, option); + if (requestResult != NO_ERROR) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s send request fail, result: %{public}d", __func__, requestResult); + return RET_FAILED; + } + + int32_t result = reply.ReadInt32(); + PERMISSION_LOG_DEBUG(LABEL, "%{public}s get result from server data = %{public}d", __func__, result); + return result; +} + +int PermissionManagerProxy::GetDefPermission( + const std::string& permissionName, PermissionDefParcel& permissionDefResult) +{ + MessageParcel data; + data.WriteInterfaceToken(IPermissionManager::GetDescriptor()); + if (!data.WriteString(permissionName)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: Failed to write permissionName", __func__); + return RET_FAILED; + } + + MessageParcel reply; + MessageOption option; + sptr remote = Remote(); + if (remote == nullptr) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: remote service null.", __func__); + return RET_FAILED; + } + int32_t requestResult = remote->SendRequest( + static_cast(IPermissionManager::InterfaceCode::GET_DEF_PERMISSION), data, reply, option); + if (requestResult != NO_ERROR) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s send request fail, result: %{public}d", __func__, requestResult); + return RET_FAILED; + } + sptr resultSptr = reply.ReadParcelable(); + if (resultSptr == nullptr) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s ReadParcelable fail", __func__); + return RET_FAILED; + } + permissionDefResult = *resultSptr; + int32_t result = reply.ReadInt32(); + PERMISSION_LOG_DEBUG(LABEL, "%{public}s get result from server data = %{public}d", __func__, result); + return result; +} +} // namespace Permission +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/src/permission/permission_manager_proxy.h b/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/src/permission/permission_manager_proxy.h new file mode 100644 index 0000000..c12e7b8 --- /dev/null +++ b/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/src/permission/permission_manager_proxy.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PERMISSION_MANAGER_PROXY_H +#define PERMISSION_MANAGER_PROXY_H + +#include "i_permission_manager.h" + +#include "iremote_proxy.h" + +namespace OHOS { +namespace Security { +namespace Permission { +class PermissionManagerProxy : public IRemoteProxy { +public: + explicit PermissionManagerProxy(const sptr& impl); + virtual ~PermissionManagerProxy() override; + + int VerifyPermission(const std::string& packageName, const std::string& permissionName, int userId) override; + + bool CanRequestPermission(const std::string& bundleName, const std::string& permissionName, int userId) override; + + int GrantUserGrantedPermission( + const std::string& bundleName, const std::string& permissionName, int userId) override; + + int GrantSystemGrantedPermission(const std::string& bundleName, const std::string& permissionName) override; + + int RevokeUserGrantedPermission( + const std::string& bundleName, const std::string& permissionName, int userId) override; + + int RevokeSystemGrantedPermission(const std::string& bundleName, const std::string& permissionName) override; + + int AddUserGrantedReqPermissions( + const std::string& bundleName, const std::vector& permList, int userId) override; + + int AddSystemGrantedReqPermissions( + const std::string& bundleName, const std::vector& permList) override; + + int RemoveUserGrantedReqPermissions(const std::string& bundleName, int userId) override; + + int RemoveSystemGrantedReqPermissions(const std::string& bundleName) override; + + int AddDefPermissions(const std::vector& permDefList) override; + + int RemoveDefPermissions(const std::string& bundleName) override; + + int GetDefPermission(const std::string& permissionName, PermissionDefParcel& permissionDefResult) override; + +private: + static inline BrokerDelegator delegator_; +}; +} // namespace Permission +} // namespace Security +} // namespace OHOS +#endif // PERMISSION_MANAGER_PROXY_H diff --git a/interfaces/innerkits/permission_standard/permissionsdk/test/BUILD.gn b/interfaces/innerkits/permission_standard/permissionsdk/test/BUILD.gn new file mode 100755 index 0000000..f62c840 --- /dev/null +++ b/interfaces/innerkits/permission_standard/permissionsdk/test/BUILD.gn @@ -0,0 +1,40 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") + +ohos_unittest("libpermissionsdk_standard_test") { + subsystem_name = "security" + part_name = "permission_standard" + module_out_path = part_name + "/" + part_name + + include_dirs = [ + "//utils/native/base/include", + "//base/security/permission/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/include/permission/", + ] + + sources = [ "unittest/cpp/src/permission_kit_test.cpp" ] + + cflags_cc = [ "-DHILOG_ENABLE" ] + + deps = [ + "//base/security/permission/frameworks/permission_standard/permissioninfrastructure:permission_standard_infrastructure_cxx", + "//base/security/permission/interfaces/innerkits/permission_standard/permissionsdk:libpermissionsdk_standard", + "//utils/native/base:utils", + ] +} + +group("unittest") { + testonly = true + deps = [ ":libpermissionsdk_standard_test" ] +} diff --git a/interfaces/innerkits/permission_standard/permissionsdk/test/unittest/cpp/src/permission_kit_test.cpp b/interfaces/innerkits/permission_standard/permissionsdk/test/unittest/cpp/src/permission_kit_test.cpp new file mode 100755 index 0000000..a4ec9f4 --- /dev/null +++ b/interfaces/innerkits/permission_standard/permissionsdk/test/unittest/cpp/src/permission_kit_test.cpp @@ -0,0 +1,357 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "permission_kit_test.h" + +#include "test_const.h" +#include "permission_kit.h" + +using namespace testing::ext; +using namespace OHOS::Security::Permission; + +void PermissionKitTest::SetUpTestCase() +{} + +void PermissionKitTest::TearDownTestCase() +{ + PermissionKit::RemoveDefPermissions(TEST_BUNDLE_NAME); + PermissionKit::RemoveUserGrantedReqPermissions(TEST_BUNDLE_NAME, TEST_USER_ID); + PermissionKit::RemoveSystemGrantedReqPermissions(TEST_BUNDLE_NAME); +} + +void PermissionKitTest::SetUp() +{ + vector permDefList; + PermissionDef permissionDefAlpha = { + .permissionName = TEST_PERMISSION_NAME_ALPHA, + .bundleName = TEST_BUNDLE_NAME, + .grantMode = GrantMode::USER_GRANT, + .availableScope = AVAILABLE_SCOPE_ALL, + .label = TEST_LABEL, + .labelId = TEST_LABEL_ID, + .description = TEST_DESCRIPTION, + .descriptionId = TEST_DESCRIPTION_ID + }; + + PermissionDef permissionDefBeta = { + .permissionName = TEST_PERMISSION_NAME_BETA, + .bundleName = TEST_BUNDLE_NAME, + .grantMode = GrantMode::SYSTEM_GRANT, + .availableScope = AVAILABLE_SCOPE_ALL, + .label = TEST_LABEL, + .labelId = TEST_LABEL_ID, + .description = TEST_DESCRIPTION, + .descriptionId = TEST_DESCRIPTION_ID + }; + + permDefList.emplace_back(permissionDefAlpha); + permDefList.emplace_back(permissionDefBeta); + PermissionKit::AddDefPermissions(permDefList); +} + +void PermissionKitTest::TearDown() +{} + +/** + * @tc.name: AddDefPermissions001 + * @tc.desc: Get permission definition info successfully after AddDefPermissions function has been invoked + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PermissionKitTest, AddDefPermissions001, TestSize.Level1) +{ + PermissionDef permissionDefResultAlpha; + int ret = PermissionKit::GetDefPermission(TEST_PERMISSION_NAME_ALPHA, permissionDefResultAlpha); + ASSERT_EQ(RET_SUCCESS, ret); + + PermissionDef permissionDefResultBeta; + ret = PermissionKit::GetDefPermission(TEST_PERMISSION_NAME_BETA, permissionDefResultBeta); + ASSERT_EQ(RET_SUCCESS, ret); +} + +/** + * @tc.name: RemoveDefPermissions001 + * @tc.desc: Cannot get permission definition info after RemoveDefPermissions has been invoked + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PermissionKitTest, RemoveDefPermissions001, TestSize.Level1) +{ + PermissionDef permissionDefResultAlpha; + int ret = PermissionKit::GetDefPermission(TEST_PERMISSION_NAME_ALPHA, permissionDefResultAlpha); + ASSERT_EQ(RET_SUCCESS, ret); + + ret = PermissionKit::RemoveDefPermissions(TEST_BUNDLE_NAME); + ASSERT_EQ(RET_SUCCESS, ret); + + PermissionDef result; + ret = PermissionKit::GetDefPermission(TEST_PERMISSION_NAME_ALPHA, result); + ASSERT_EQ(RET_FAILED, ret); +} + +/** + * @tc.name: VerifyPermission001 + * @tc.desc: Verify user granted permission + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PermissionKitTest, VerifyPermission001, TestSize.Level1) +{ + vector permList; + permList.push_back(TEST_PERMISSION_NAME_ALPHA); + + int ret = PermissionKit::AddUserGrantedReqPermissions(TEST_BUNDLE_NAME, permList, TEST_USER_ID); + ASSERT_EQ(RET_SUCCESS, ret); + + ret = PermissionKit::GrantUserGrantedPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_ALPHA, TEST_USER_ID); + ASSERT_EQ(RET_SUCCESS, ret); + + ret = PermissionKit::VerifyPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_ALPHA, TEST_USER_ID); + ASSERT_EQ(PERMISSION_GRANTED, ret); + + ret = PermissionKit::RevokeUserGrantedPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_ALPHA, TEST_USER_ID); + ASSERT_EQ(RET_SUCCESS, ret); + + ret = PermissionKit::VerifyPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_ALPHA, TEST_USER_ID); + ASSERT_EQ(PERMISSION_NOT_GRANTED, ret); + + ret = PermissionKit::RemoveUserGrantedReqPermissions(TEST_BUNDLE_NAME, TEST_USER_ID); + ASSERT_EQ(RET_SUCCESS, ret); +} + +/** + * @tc.name: VerifyPermission002 + * @tc.desc: Verify system granted permission + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PermissionKitTest, VerifyPermission002, TestSize.Level1) +{ + vector permList; + permList.push_back(TEST_PERMISSION_NAME_BETA); + + int ret = PermissionKit::AddSystemGrantedReqPermissions(TEST_BUNDLE_NAME, permList); + ASSERT_EQ(RET_SUCCESS, ret); + + ret = PermissionKit::GrantSystemGrantedPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_BETA); + ASSERT_EQ(RET_SUCCESS, ret); + + ret = PermissionKit::VerifyPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_BETA, TEST_USER_ID); + ASSERT_EQ(PERMISSION_GRANTED, ret); + + ret = PermissionKit::VerifyPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_BETA, TEST_SUB_USER_ID); + ASSERT_EQ(PERMISSION_GRANTED, ret); + + ret = PermissionKit::RevokeSystemGrantedPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_BETA); + ASSERT_EQ(RET_SUCCESS, ret); + + ret = PermissionKit::VerifyPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_BETA, TEST_USER_ID); + ASSERT_EQ(PERMISSION_NOT_GRANTED, ret); + + ret = PermissionKit::VerifyPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_BETA, TEST_SUB_USER_ID); + ASSERT_EQ(PERMISSION_NOT_GRANTED, ret); + + ret = PermissionKit::RemoveSystemGrantedReqPermissions(TEST_BUNDLE_NAME); + ASSERT_EQ(RET_SUCCESS, ret); +} + +/** + * @tc.name: VerifyPermission003 + * @tc.desc: Verify permission that has not been defined. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PermissionKitTest, VerifyPermission003, TestSize.Level1) +{ + int ret = PermissionKit::VerifyPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_GAMMA, TEST_USER_ID); + ASSERT_EQ(PERMISSION_NOT_GRANTED, ret); +} + +/** + * @tc.name: VerifyPermissionErrorUserGrant001 + * @tc.desc: Verify permission error that user granted but request system granted. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PermissionKitTest, VerifyPermissionErrorUserGrant001, TestSize.Level1) +{ + vector permList; + permList.push_back(TEST_PERMISSION_NAME_ALPHA); + + int ret = PermissionKit::AddSystemGrantedReqPermissions(TEST_BUNDLE_NAME, permList); + ASSERT_EQ(RET_SUCCESS, ret); + + ret = PermissionKit::GrantUserGrantedPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_ALPHA, TEST_USER_ID); + ASSERT_EQ(RET_SUCCESS, ret); + + ret = PermissionKit::VerifyPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_ALPHA, TEST_USER_ID); + ASSERT_EQ(PERMISSION_NOT_GRANTED, ret); + + ret = PermissionKit::RevokeUserGrantedPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_ALPHA, TEST_USER_ID); + ASSERT_EQ(RET_SUCCESS, ret); + + ret = PermissionKit::VerifyPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_ALPHA, TEST_USER_ID); + ASSERT_EQ(PERMISSION_NOT_GRANTED, ret); + + ret = PermissionKit::RemoveUserGrantedReqPermissions(TEST_BUNDLE_NAME, TEST_USER_ID); + ASSERT_EQ(RET_SUCCESS, ret); +} + +/** + * @tc.name: VerifyPermissionErrorUserGrant002 + * @tc.desc: Verify permission error that user granted but grant system granted. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PermissionKitTest, VerifyPermissionErrorUserGrant002, TestSize.Level1) +{ + vector permList; + permList.push_back(TEST_PERMISSION_NAME_ALPHA); + + int ret = PermissionKit::AddUserGrantedReqPermissions(TEST_BUNDLE_NAME, permList, TEST_USER_ID); + ASSERT_EQ(RET_SUCCESS, ret); + + ret = PermissionKit::GrantSystemGrantedPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_ALPHA); + ASSERT_EQ(RET_SUCCESS, ret); + + ret = PermissionKit::VerifyPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_ALPHA, TEST_USER_ID); + ASSERT_EQ(PERMISSION_NOT_GRANTED, ret); + + ret = PermissionKit::RevokeUserGrantedPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_ALPHA, TEST_USER_ID); + ASSERT_EQ(RET_SUCCESS, ret); + + ret = PermissionKit::VerifyPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_ALPHA, TEST_USER_ID); + ASSERT_EQ(PERMISSION_NOT_GRANTED, ret); + + ret = PermissionKit::RemoveUserGrantedReqPermissions(TEST_BUNDLE_NAME, TEST_USER_ID); + ASSERT_EQ(RET_SUCCESS, ret); +} + +/** + * @tc.name: VerifyPermissionErrorSystemGrant001 + * @tc.desc: Verify permission error that system granted but request user granted. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PermissionKitTest, VerifyPermissionErrorSystemGrant001, TestSize.Level1) +{ + vector permList; + permList.push_back(TEST_PERMISSION_NAME_BETA); + + int ret = PermissionKit::AddUserGrantedReqPermissions(TEST_BUNDLE_NAME, permList, TEST_USER_ID); + ASSERT_EQ(RET_SUCCESS, ret); + + ret = PermissionKit::GrantSystemGrantedPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_BETA); + ASSERT_EQ(RET_SUCCESS, ret); + + ret = PermissionKit::VerifyPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_BETA, TEST_USER_ID); + ASSERT_EQ(PERMISSION_NOT_GRANTED, ret); + + ret = PermissionKit::RevokeSystemGrantedPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_BETA); + ASSERT_EQ(RET_SUCCESS, ret); + + ret = PermissionKit::VerifyPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_BETA, TEST_USER_ID); + ASSERT_EQ(PERMISSION_NOT_GRANTED, ret); + + ret = PermissionKit::RemoveUserGrantedReqPermissions(TEST_BUNDLE_NAME, TEST_USER_ID); + ASSERT_EQ(RET_SUCCESS, ret); +} + +/** + * @tc.name: VerifyPermissionErrorSystemGrant002 + * @tc.desc: Verify permission error that system granted but grant user granted. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PermissionKitTest, VerifyPermissionErrorSystemGrant002, TestSize.Level1) +{ + vector permList; + permList.push_back(TEST_PERMISSION_NAME_BETA); + + int ret = PermissionKit::AddSystemGrantedReqPermissions(TEST_BUNDLE_NAME, permList); + ASSERT_EQ(RET_SUCCESS, ret); + + ret = PermissionKit::GrantUserGrantedPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_BETA, TEST_USER_ID); + ASSERT_EQ(RET_SUCCESS, ret); + + ret = PermissionKit::VerifyPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_BETA, TEST_USER_ID); + ASSERT_EQ(PERMISSION_NOT_GRANTED, ret); + + ret = PermissionKit::VerifyPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_BETA, TEST_SUB_USER_ID); + ASSERT_EQ(PERMISSION_NOT_GRANTED, ret); + + ret = PermissionKit::RevokeSystemGrantedPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_BETA); + ASSERT_EQ(RET_SUCCESS, ret); + + ret = PermissionKit::VerifyPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_BETA, TEST_USER_ID); + ASSERT_EQ(PERMISSION_NOT_GRANTED, ret); + + ret = PermissionKit::VerifyPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_BETA, TEST_SUB_USER_ID); + ASSERT_EQ(PERMISSION_NOT_GRANTED, ret); + + ret = PermissionKit::RemoveUserGrantedReqPermissions(TEST_BUNDLE_NAME, TEST_USER_ID); + ASSERT_EQ(RET_SUCCESS, ret); +} + +/** + * @tc.name: CanRequestPermission001 + * @tc.desc: For user granted permission and permission is granted, can request permission + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PermissionKitTest, CanRequestPermission001, TestSize.Level1) +{ + vector permList; + permList.push_back(TEST_PERMISSION_NAME_ALPHA); + + int ret = PermissionKit::AddUserGrantedReqPermissions(TEST_BUNDLE_NAME, permList, TEST_USER_ID); + ASSERT_EQ(RET_SUCCESS, ret); + + bool isCanRequest = PermissionKit::CanRequestPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_ALPHA, TEST_USER_ID); + ASSERT_TRUE(isCanRequest); + + ret = PermissionKit::GrantUserGrantedPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_ALPHA, TEST_USER_ID); + ASSERT_EQ(RET_SUCCESS, ret); + + isCanRequest = PermissionKit::CanRequestPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_ALPHA, TEST_USER_ID); + ASSERT_FALSE(isCanRequest); + + ret = PermissionKit::RemoveDefPermissions(TEST_BUNDLE_NAME); + ASSERT_EQ(RET_SUCCESS, ret); + + isCanRequest = PermissionKit::CanRequestPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_ALPHA, TEST_USER_ID); + ASSERT_FALSE(isCanRequest); +} + +/** + * @tc.name: CanRequestPermission001 + * @tc.desc: For non user granted permission, can not request permission + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PermissionKitTest, CanRequestPermission002, TestSize.Level1) +{ + vector permList; + permList.push_back(TEST_PERMISSION_NAME_BETA); + + int ret = PermissionKit::AddSystemGrantedReqPermissions(TEST_BUNDLE_NAME, permList); + ASSERT_EQ(RET_SUCCESS, ret); + + bool isCanRequest = PermissionKit::CanRequestPermission(TEST_BUNDLE_NAME, TEST_PERMISSION_NAME_BETA, TEST_USER_ID); + ASSERT_FALSE(isCanRequest); + + isCanRequest = PermissionKit::CanRequestPermission("", "", TEST_INVALID_USER_ID); + ASSERT_FALSE(isCanRequest); +} \ No newline at end of file diff --git a/interfaces/innerkits/permission_standard/permissionsdk/test/unittest/cpp/src/permission_kit_test.h b/interfaces/innerkits/permission_standard/permissionsdk/test/unittest/cpp/src/permission_kit_test.h new file mode 100644 index 0000000..daba1bd --- /dev/null +++ b/interfaces/innerkits/permission_standard/permissionsdk/test/unittest/cpp/src/permission_kit_test.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PERMISSION_KIT_TEST_H +#define PERMISSION_KIT_TEST_H + +#include + +namespace OHOS { +namespace Security { +namespace Permission { +class PermissionKitTest : public testing::Test { +public: + static void SetUpTestCase(); + + static void TearDownTestCase(); + + void SetUp(); + + void TearDown(); +}; +} // namespace Permission +} // namespace Security +} // namespace OHOS +#endif // PERMISSION_KIT_TEST_H diff --git a/interfaces/kits/permission_lite/BUILD.gn b/interfaces/kits/permission_lite/BUILD.gn old mode 100644 new mode 100755 diff --git a/interfaces/kits/permission_lite/pms_interface.h b/interfaces/kits/permission_lite/pms_interface.h old mode 100644 new mode 100755 diff --git a/interfaces/kits/permission_standard/BUILD.gn b/interfaces/kits/permission_standard/BUILD.gn new file mode 100644 index 0000000..11f42d3 --- /dev/null +++ b/interfaces/kits/permission_standard/BUILD.gn @@ -0,0 +1,14 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") diff --git a/ohos.build b/ohos.build new file mode 100755 index 0000000..3be6fe1 --- /dev/null +++ b/ohos.build @@ -0,0 +1,30 @@ +{ + "subsystem": "security", + "parts": { + "permission_standard": { + "variants": [ + "phone", + "wearable" + ], + "inner_kits": [ + { + "name": "//base/security/permission/interfaces/innerkits/permission_standard/permissionsdk:libpermissionsdk_standard", + "header": { + "header_files": [ + "permission/permission.h", + "permission/permission_def.h", + "permission/permission_kit.h" + ], + "header_base": "//base/security/permission/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/include" + } + } + ], + "module_list": [ + "//base/security/permission:permission_build_module_standard" + ], + "test_list": [ + "//base/security/permission:permission_build_module_standard_test" + ] + } + } +} \ No newline at end of file diff --git a/services/permission_lite/BUILD.gn b/services/permission_lite/BUILD.gn old mode 100644 new mode 100755 diff --git a/services/permission_lite/ipc_auth/include/policy_preset.h b/services/permission_lite/ipc_auth/include/policy_preset.h old mode 100644 new mode 100755 diff --git a/services/permission_lite/ipc_auth/src/ipc_auth_impl.c b/services/permission_lite/ipc_auth/src/ipc_auth_impl.c old mode 100644 new mode 100755 diff --git a/services/permission_lite/js_api/BUILD.gn b/services/permission_lite/js_api/BUILD.gn old mode 100644 new mode 100755 diff --git a/services/permission_lite/js_api/include/perm_module.h b/services/permission_lite/js_api/include/perm_module.h old mode 100644 new mode 100755 diff --git a/services/permission_lite/js_api/src/perm_module.cpp b/services/permission_lite/js_api/src/perm_module.cpp old mode 100644 new mode 100755 diff --git a/services/permission_lite/pms/BUILD.gn b/services/permission_lite/pms/BUILD.gn old mode 100644 new mode 100755 diff --git a/services/permission_lite/pms/include/hals/hal_pms.h b/services/permission_lite/pms/include/hals/hal_pms.h old mode 100644 new mode 100755 diff --git a/services/permission_lite/pms/include/perm_define.h b/services/permission_lite/pms/include/perm_define.h old mode 100644 new mode 100755 diff --git a/services/permission_lite/pms/include/perm_operate.h b/services/permission_lite/pms/include/perm_operate.h old mode 100644 new mode 100755 diff --git a/services/permission_lite/pms/include/pms.h b/services/permission_lite/pms/include/pms.h old mode 100644 new mode 100755 diff --git a/services/permission_lite/pms/include/pms_inner.h b/services/permission_lite/pms/include/pms_inner.h old mode 100644 new mode 100755 diff --git a/services/permission_lite/pms/src/perm_operate.c b/services/permission_lite/pms/src/perm_operate.c old mode 100644 new mode 100755 diff --git a/services/permission_lite/pms/src/pms_impl.c b/services/permission_lite/pms/src/pms_impl.c old mode 100644 new mode 100755 diff --git a/services/permission_lite/pms/src/pms_inner.c b/services/permission_lite/pms/src/pms_inner.c old mode 100644 new mode 100755 diff --git a/services/permission_lite/pms/src/pms_server.c b/services/permission_lite/pms/src/pms_server.c old mode 100644 new mode 100755 diff --git a/services/permission_lite/pms/src/pms_server_internal.c b/services/permission_lite/pms/src/pms_server_internal.c old mode 100644 new mode 100755 diff --git a/services/permission_lite/pms_base/BUILD.gn b/services/permission_lite/pms_base/BUILD.gn old mode 100644 new mode 100755 diff --git a/services/permission_lite/pms_base/include/pms_common.h b/services/permission_lite/pms_base/include/pms_common.h old mode 100644 new mode 100755 diff --git a/services/permission_lite/pms_client/BUILD.gn b/services/permission_lite/pms_client/BUILD.gn old mode 100644 new mode 100755 diff --git a/services/permission_lite/pms_client/perm_client.c b/services/permission_lite/pms_client/perm_client.c old mode 100644 new mode 100755 diff --git a/services/permission_standard/permissionmanagerservice/BUILD.gn b/services/permission_standard/permissionmanagerservice/BUILD.gn new file mode 100755 index 0000000..8d9b43f --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/BUILD.gn @@ -0,0 +1,58 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") + +ohos_shared_library("permission_manager_service_standard") { + subsystem_name = "security" + part_name = "permission_standard" + + include_dirs = [ + "include", + "//utils/system/safwk/native/include", + "//base/security/permission/frameworks/permission_standard/permissioninfrastructure", + "//base/security/permission/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/include/permission", + ] + + sources = [ + "main/cpp/src/data_storage.cpp", + "main/cpp/src/data_translator.cpp", + "main/cpp/src/generic_values.cpp", + "main/cpp/src/permission_definition_cache.cpp", + "main/cpp/src/permission_definition_manager.cpp", + "main/cpp/src/permission_manager_service.cpp", + "main/cpp/src/permission_manager_stub.cpp", + "main/cpp/src/permission_state_cache.cpp", + "main/cpp/src/permission_state_manager.cpp", + "main/cpp/src/sqlite_helper.cpp", + "main/cpp/src/sqlite_storage.cpp", + "main/cpp/src/statement.cpp", + "main/cpp/src/variant_value.cpp", + ] + + cflags_cc = [ "-DHILOG_ENABLE" ] + + deps = [ + "//base/security/permission/frameworks/permission_standard/permissioncommunicationadapter:permission_standard_communication_adapter_cxx", + "//base/security/permission/frameworks/permission_standard/permissioninfrastructure:permission_standard_infrastructure_cxx", + "//third_party/sqlite:sqlite", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "safwk:system_ability_fwk", + "samgr_L2:samgr_proxy", + ] +} diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/data_storage.cpp b/services/permission_standard/permissionmanagerservice/main/cpp/src/data_storage.cpp new file mode 100644 index 0000000..f28cec1 --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/data_storage.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "data_storage.h" + +#include "sqlite_storage.h" + +namespace OHOS { +namespace Security { +namespace Permission { +DataStorage& DataStorage::GetRealDataStorage() +{ + return SqliteStorage::GetInstance(); +} +} // namespace Permission +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/data_storage.h b/services/permission_standard/permissionmanagerservice/main/cpp/src/data_storage.h new file mode 100644 index 0000000..c7295e3 --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/data_storage.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DATA_STORAGE_H +#define DATA_STORAGE_H + +#include +#include + +#include "generic_values.h" + +namespace OHOS { +namespace Security { +namespace Permission { +class DataStorage { +public: + enum DataType { PERMISSION_DEF, PERMISSIONS_STAT_USER_GRANTED, PERMISSIONS_STAT_SYSTEM_GRANTED }; + + static DataStorage& GetRealDataStorage(); + + virtual ~DataStorage() = default; + + virtual int Add(const DataType type, const std::vector& values) = 0; + + virtual int Remove(const DataType type, const GenericValues& conditions) = 0; + + virtual int Modify(const DataType type, const GenericValues& modifyValues, const GenericValues& conditions) = 0; + + virtual int Find(const DataType type, std::vector& results) = 0; + + virtual int RefreshAll(const DataType type, const std::vector& values) = 0; +}; +} // namespace Permission +} // namespace Security +} // namespace OHOS + +#endif // DATA_STORAGE_H \ No newline at end of file diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/data_translator.cpp b/services/permission_standard/permissionmanagerservice/main/cpp/src/data_translator.cpp new file mode 100644 index 0000000..38b578d --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/data_translator.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "data_translator.h" + +#include "permission.h" +#include "field_const.h" + +namespace OHOS { +namespace Security { +namespace Permission { +int DataTranslator::TranslationIntoPermissionDef(const GenericValues& inGenericValues, PermissionDef& outPermissionDef) +{ + outPermissionDef.permissionName = inGenericValues.GetString(FIELD_PERMISSION_NAME); + outPermissionDef.bundleName = inGenericValues.GetString(FIELD_BUNDLE_NAME); + outPermissionDef.grantMode = inGenericValues.GetInt(FIELD_GRANT_MODE); + outPermissionDef.availableScope = inGenericValues.GetInt(FIELD_AVAILABLE_SCOPE); + outPermissionDef.label = inGenericValues.GetString(FIELD_LABEL); + outPermissionDef.labelId = inGenericValues.GetInt(FIELD_LABEL_ID); + outPermissionDef.description = inGenericValues.GetString(FIELD_DESCRIPTION); + outPermissionDef.descriptionId = inGenericValues.GetInt(FIELD_DESCRIPTION_ID); + return RET_SUCCESS; +} + +int DataTranslator::TranslationIntoGenericValues(const PermissionDef& inPermissionDef, GenericValues& outGenericValues) +{ + outGenericValues.Put(FIELD_PERMISSION_NAME, inPermissionDef.permissionName); + outGenericValues.Put(FIELD_BUNDLE_NAME, inPermissionDef.bundleName); + outGenericValues.Put(FIELD_GRANT_MODE, inPermissionDef.grantMode); + outGenericValues.Put(FIELD_AVAILABLE_SCOPE, inPermissionDef.availableScope); + outGenericValues.Put(FIELD_LABEL, inPermissionDef.label); + outGenericValues.Put(FIELD_LABEL_ID, inPermissionDef.labelId); + outGenericValues.Put(FIELD_DESCRIPTION, inPermissionDef.description); + outGenericValues.Put(FIELD_DESCRIPTION_ID, inPermissionDef.descriptionId); + return RET_SUCCESS; +} + +int DataTranslator::TranslationIntoPermissionReq(const GenericValues& inGenericValues, PermissionReq& outPermissionReq) +{ + outPermissionReq.reqPermissionName = inGenericValues.GetString(FIELD_PERMISSION_NAME); + outPermissionReq.isGranted = inGenericValues.GetInt(FIELD_GRANTED) != 0; + outPermissionReq.flags = inGenericValues.GetInt(FIELD_FLAGS); + return RET_SUCCESS; +} + +int DataTranslator::TranslationIntoGenericValues(const PermissionReq& inPermissionReq, GenericValues& outGenericValues) +{ + outGenericValues.Put(FIELD_PERMISSION_NAME, inPermissionReq.reqPermissionName); + outGenericValues.Put(FIELD_GRANTED, inPermissionReq.isGranted ? 1 : 0); + outGenericValues.Put(FIELD_FLAGS, inPermissionReq.flags); + return RET_SUCCESS; +} + +std::string DataTranslator::ToString(const PermissionDef& inPermissionDef) +{ + std::string infos; + infos.append(R"({"permissionName": ")" + inPermissionDef.permissionName + R"(")"); + infos.append(R"(, "bundleName": ")" + inPermissionDef.bundleName + R"(")"); + infos.append(R"(, "grantMode": )" + std::to_string(inPermissionDef.grantMode)); + infos.append(R"(, "availableScope": )" + std::to_string(inPermissionDef.availableScope)); + infos.append(R"(, "label": ")" + inPermissionDef.label + R"(")"); + infos.append(R"(, "labelId": )" + std::to_string(inPermissionDef.labelId)); + infos.append(R"(, "description": ")" + inPermissionDef.description + R"(")"); + infos.append(R"(, "descriptionId": )" + std::to_string(inPermissionDef.descriptionId)); + infos.append("}"); + return infos; +} +} // namespace Permission +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/data_translator.h b/services/permission_standard/permissionmanagerservice/main/cpp/src/data_translator.h new file mode 100755 index 0000000..8412be1 --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/data_translator.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DATA_TRANSLATOR_H +#define DATA_TRANSLATOR_H + +#include + +#include "permission_def.h" +#include "permission_req.h" +#include "generic_values.h" + +namespace OHOS { +namespace Security { +namespace Permission { +class DataTranslator final { +public: + static int TranslationIntoPermissionDef(const GenericValues& inGenericValues, PermissionDef& outPermissionDef); + static int TranslationIntoPermissionReq(const GenericValues& inGenericValues, PermissionReq& outPermissionReq); + static int TranslationIntoGenericValues(const PermissionDef& inPermissionDef, GenericValues& outGenericValues); + static int TranslationIntoGenericValues(const PermissionReq& inPermissionReq, GenericValues& outGenericValues); + static std::string ToString(const PermissionDef& inPermissionDef); +}; +} // namespace Permission +} // namespace Security +} // namespace OHOS +#endif // DATA_TRANSLATOR_H diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/field_const.h b/services/permission_standard/permissionmanagerservice/main/cpp/src/field_const.h new file mode 100644 index 0000000..fc98bbe --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/field_const.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIELD_CONST_H +#define FIELD_CONST_H + +#include + +namespace OHOS { +namespace Security { +namespace Permission { +const std::string FIELD_PERMISSION_NAME = "permission_name"; +const std::string FIELD_BUNDLE_NAME = "bundle_name"; +const std::string FIELD_GRANT_MODE = "grant_mode"; +const std::string FIELD_AVAILABLE_SCOPE = "available_scope"; +const std::string FIELD_LABEL = "label"; +const std::string FIELD_LABEL_ID = "label_id"; +const std::string FIELD_DESCRIPTION = "description"; +const std::string FIELD_DESCRIPTION_ID = "description_id"; +const std::string FIELD_USER_ID = "user_id"; +const std::string FIELD_GRANTED = "granted"; +const std::string FIELD_FLAGS = "flags"; +} // namespace Permission +} // namespace Security +} // namespace OHOS +#endif // FIELD_CONST_H diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/generic_values.cpp b/services/permission_standard/permissionmanagerservice/main/cpp/src/generic_values.cpp new file mode 100644 index 0000000..d8d0691 --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/generic_values.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "generic_values.h" + +namespace OHOS { +namespace Security { +namespace Permission { +void GenericValues::Put(const std::string& key, int value) +{ + map_.insert(std::make_pair(key, VariantValue(value))); +} + +void GenericValues::Put(const std::string& key, const std::string& value) +{ + map_.insert(std::make_pair(key, VariantValue(value))); +} + +void GenericValues::Put(const std::string& key, const VariantValue& value) +{ + map_.insert(std::make_pair(key, value)); +} + +VariantValue GenericValues::Get(const std::string& key) const +{ + auto iter = map_.find(key); + if (iter == map_.end()) { + return VariantValue(); + } + return iter->second; +} + +int GenericValues::GetInt(const std::string& key) const +{ + auto it = map_.find(key); + if (it == map_.end()) { + return VariantValue::DEFAULT_VALUE; + } + return it->second.GetInt(); +} + +std::string GenericValues::GetString(const std::string& key) const +{ + auto it = map_.find(key); + if (it == map_.end()) { + return std::string(); + } + return it->second.GetString(); +} + +std::vector GenericValues::GetAllKeys() const +{ + std::vector keys; + for (auto it = map_.begin(); it != map_.end(); ++it) { + keys.emplace_back(it->first); + } + return keys; +} +} // namespace Permission +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/generic_values.h b/services/permission_standard/permissionmanagerservice/main/cpp/src/generic_values.h new file mode 100755 index 0000000..04c99dc --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/generic_values.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GENERIC_VALUES_H +#define GENERIC_VALUES_H + +#include +#include +#include + +#include "variant_value.h" + +namespace OHOS { +namespace Security { +namespace Permission { +class GenericValues final { +public: + GenericValues() = default; + virtual ~GenericValues() = default; + + void Put(const std::string& key, int value); + + void Put(const std::string& key, const std::string& value); + + void Put(const std::string& key, const VariantValue& value); + + std::vector GetAllKeys() const; + + VariantValue Get(const std::string& key) const; + + int GetInt(const std::string& key) const; + + std::string GetString(const std::string& key) const; + +private: + std::map map_; +}; +} // namespace Permission +} // namespace Security +} // namespace OHOS +#endif // GENERIC_VALUES_H diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_definition_cache.cpp b/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_definition_cache.cpp new file mode 100644 index 0000000..951ceff --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_definition_cache.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "permission_definition_cache.h" + +#include "permission.h" +#include "data_translator.h" +#include "permission_log.h" + +namespace OHOS { +namespace Security { +namespace Permission { +namespace { +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { + LOG_CORE, SECURITY_DOMAIN_PERMISSION, "PermissionDefinitionCache" +}; +} + +PermissionDefinitionCache& PermissionDefinitionCache::GetInstance() +{ + static PermissionDefinitionCache instance; + return instance; +} + +PermissionDefinitionCache::PermissionDefinitionCache() +{} + +PermissionDefinitionCache::~PermissionDefinitionCache() +{} + +bool PermissionDefinitionCache::Insert(const PermissionDef& info) +{ + Utils::UniqueWriteGuard cacheGuard(this->cacheLock_); + auto it = permissionDefinitionMap_.find(info.permissionName); + if (it != permissionDefinitionMap_.end()) { + PERMISSION_LOG_WARN(LABEL, "%{public}s: info for permission: %{public}s has been insert, please check!", + __func__, info.permissionName.c_str()); + return false; + } + permissionDefinitionMap_[info.permissionName] = info; + return true; +} + +void PermissionDefinitionCache::DeleteByBundleName(const std::string& bundleName) +{ + Utils::UniqueWriteGuard cacheGuard(this->cacheLock_); + auto it = permissionDefinitionMap_.begin(); + while (it != permissionDefinitionMap_.end()) { + if (bundleName == it->second.bundleName) { + permissionDefinitionMap_.erase(it++); + } else { + ++it; + } + } +} + +int PermissionDefinitionCache::FindByPermissionName(const std::string& permissionName, PermissionDef& info) +{ + Utils::UniqueReadGuard cacheGuard(this->cacheLock_); + auto it = permissionDefinitionMap_.find(permissionName); + if (it == permissionDefinitionMap_.end()) { + PERMISSION_LOG_DEBUG(LABEL, "%{public}s: can not find definition info for permission: %{public}s", __func__, + permissionName.c_str()); + return RET_FAILED; + } + info = it->second; + return RET_SUCCESS; +} + +bool PermissionDefinitionCache::IsSystemGrantedPermission(const std::string& permissionName) +{ + Utils::UniqueReadGuard cacheGuard(this->cacheLock_); + return IsGrantedModeEqualInner(permissionName, SYSTEM_GRANT); +} + +bool PermissionDefinitionCache::IsUserGrantedPermission(const std::string& permissionName) +{ + Utils::UniqueReadGuard cacheGuard(this->cacheLock_); + return IsGrantedModeEqualInner(permissionName, USER_GRANT); +} + +std::string PermissionDefinitionCache::ToString() +{ + Utils::UniqueReadGuard cacheGuard(this->cacheLock_); + std::string infos = R"({"Cache": "Default", "DefPermissions": [)"; + for (const auto& request : permissionDefinitionMap_) { + PermissionDef permissionDef = request.second; + infos.append(DataTranslator::ToString(request.second)); + infos.append(", "); + } + infos = infos + "]}"; + return infos; +} + +bool PermissionDefinitionCache::IsGrantedModeEqualInner(const std::string& permissionName, int grantMode) const +{ + auto it = permissionDefinitionMap_.find(permissionName); + if (it == permissionDefinitionMap_.end()) { + return false; + } + return it->second.grantMode == grantMode; +} + +bool PermissionDefinitionCache::HasDefinition(const std::string& permissionName) +{ + Utils::UniqueReadGuard cacheGuard(this->cacheLock_); + return permissionDefinitionMap_.count(permissionName) == 1; +} + +void PermissionDefinitionCache::QueryCurrentCache(std::vector& valueList) +{ + Utils::UniqueReadGuard cacheGuard(this->cacheLock_); + for (auto it = permissionDefinitionMap_.begin(); it != permissionDefinitionMap_.end(); ++it) { + GenericValues genericValues; + DataTranslator::TranslationIntoGenericValues(it->second, genericValues); + valueList.emplace_back(genericValues); + } +} +} // namespace Permission +} // namespace Security +} // namespace OHOS diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_definition_cache.h b/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_definition_cache.h new file mode 100755 index 0000000..483fc65 --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_definition_cache.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PERMISSION_DEFINITION_CACHE_H +#define PERMISSION_DEFINITION_CACHE_H + +#include +#include + +#include "permission_def.h" +#include "generic_values.h" + +#include "rwlock.h" +#include "nocopyable.h" + +namespace OHOS { +namespace Security { +namespace Permission { +class PermissionDefinitionCache final { +public: + static PermissionDefinitionCache& GetInstance(); + + virtual ~PermissionDefinitionCache(); + + bool Insert(const PermissionDef& info); + + void DeleteByBundleName(const std::string& bundleName); + + int FindByPermissionName(const std::string& permissionName, PermissionDef& info); + + bool IsSystemGrantedPermission(const std::string& permissionName); + + bool IsUserGrantedPermission(const std::string& permissionName); + + bool HasDefinition(const std::string& permissionName); + + void QueryCurrentCache(std::vector& valueList); + + std::string ToString(); + +private: + PermissionDefinitionCache(); + + bool IsGrantedModeEqualInner(const std::string& permissionName, int grantMode) const; + + DISALLOW_COPY_AND_MOVE(PermissionDefinitionCache); + + /** + * key: permission name. + * value: PermissionDef. + */ + std::map permissionDefinitionMap_; + + OHOS::Utils::RWLock cacheLock_; +}; +} // namespace Permission +} // namespace Security +} // namespace OHOS +#endif // PERMISSION_DEFINITION_CACHE_H diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_definition_manager.cpp b/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_definition_manager.cpp new file mode 100644 index 0000000..25dc450 --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_definition_manager.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "permission_definition_manager.h" + +#include "permission_definition_cache.h" +#include "data_storage.h" +#include "data_translator.h" +#include "permission_log.h" +#include "permission.h" +#include "data_validator.h" + +namespace OHOS { +namespace Security { +namespace Permission { +namespace { +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { + LOG_CORE, SECURITY_DOMAIN_PERMISSION, "PermissionDefinitionManager" +}; +} + +PermissionDefinitionManager& PermissionDefinitionManager::GetInstance() +{ + static PermissionDefinitionManager instance; + return instance; +} + +PermissionDefinitionManager::PermissionDefinitionManager() : hasInited_(false) +{} + +PermissionDefinitionManager::~PermissionDefinitionManager() +{ + if (!hasInited_) { + return; + } + this->permissionDefDataAccessWorker_.Stop(); + this->hasInited_ = false; +} + +void PermissionDefinitionManager::Init() +{ + OHOS::Utils::UniqueWriteGuard lk(this->rwLock_); + if (hasInited_) { + return; + } + PERMISSION_LOG_INFO(LABEL, "init begin!"); + std::vector results; + DataStorage::GetRealDataStorage().Find(DataStorage::PERMISSION_DEF, results); + for (auto value : results) { + PermissionDef permissionDef; + DataTranslator::TranslationIntoPermissionDef(value, permissionDef); + PermissionDefinitionCache::GetInstance().Insert(permissionDef); + } + this->permissionDefDataAccessWorker_.Start(1); + hasInited_ = true; + PERMISSION_LOG_INFO(LABEL, "Init success"); +} + +void PermissionDefinitionManager::AddDefPermissions(const std::vector& permList) +{ + if (permList.empty()) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: invalid params!", __func__); + return; + } + for (const auto& permissionDefParcel : permList) { + if (!IsPermissionDefValid(permissionDefParcel.permissionDef)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: invalid permission definition info: %{public}s", __func__, + DataTranslator::ToString(permissionDefParcel.permissionDef).c_str()); + continue; + } + PermissionDefinitionCache::GetInstance().Insert(permissionDefParcel.permissionDef); + } + RefreshPersistentDataIfNeeded(); +} + +void PermissionDefinitionManager::RemoveDefPermissions(const std::string& bundleName) +{ + if (!DataValidator::IsBundleNameValid(bundleName)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: invalid params!", __func__); + return; + } + PermissionDefinitionCache::GetInstance().DeleteByBundleName(bundleName); + RefreshPersistentDataIfNeeded(); +} + +int PermissionDefinitionManager::GetDefPermission( + const std::string& permissionName, PermissionDefParcel& permissionDefParcel) const +{ + if (!DataValidator::IsPermissionNameValid(permissionName)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: invalid params!", __func__); + return RET_FAILED; + } + return PermissionDefinitionCache::GetInstance().FindByPermissionName( + permissionName, permissionDefParcel.permissionDef); +} + +bool PermissionDefinitionManager::IsGrantModeValid(const int grantMode) const +{ + return grantMode == GrantMode::SYSTEM_GRANT || grantMode == GrantMode::USER_GRANT; +} + +bool PermissionDefinitionManager::IsAvailableScopeValid(const int availableScope) const +{ + return availableScope == AvailableScope::AVAILABLE_SCOPE_ALL || + availableScope == AvailableScope::AVAILABLE_SCOPE_RESTRICTED || + availableScope == AvailableScope::AVAILABLE_SCOPE_SIGNATURE; +} + +bool PermissionDefinitionManager::IsPermissionDefValid(const PermissionDef& permissionDef) const +{ + if (!DataValidator::IsPermissionNameValid(permissionDef.permissionName)) { + return false; + } + if (!DataValidator::IsBundleNameValid(permissionDef.bundleName)) { + return false; + } + if (!IsGrantModeValid(permissionDef.grantMode)) { + return false; + } + return IsAvailableScopeValid(permissionDef.availableScope); +} + +void PermissionDefinitionManager::RefreshPersistentDataIfNeeded() +{ + if (permissionDefDataAccessWorker_.GetCurTaskNum() > 1) { + PERMISSION_LOG_WARN(LABEL, "%{public}s: has refresh task!", __func__); + return; + } + permissionDefDataAccessWorker_.AddTask([]() { + std::vector valueList; + PermissionDefinitionCache::GetInstance().QueryCurrentCache(valueList); + DataStorage::GetRealDataStorage().RefreshAll(DataStorage::PERMISSION_DEF, valueList); + + // Sleep for one second to avoid frequent refresh of the database. + std::this_thread::sleep_for(std::chrono::seconds(1)); + }); +} +} // namespace Permission +} // namespace Security +} // namespace OHOS diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_definition_manager.h b/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_definition_manager.h new file mode 100755 index 0000000..abe4519 --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_definition_manager.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PERMISSION_DEFINITION_MANAGER_H +#define PERMISSION_DEFINITION_MANAGER_H + +#include + +#include "permission_def_parcel.h" +#include "field_const.h" +#include "nocopyable.h" +#include "thread_pool.h" +#include "rwlock.h" + +namespace OHOS { +namespace Security { +namespace Permission { +class PermissionDefinitionManager final { +public: + static PermissionDefinitionManager& GetInstance(); + + void Init(); + + virtual ~PermissionDefinitionManager(); + + void AddDefPermissions(const std::vector& permList); + + void RemoveDefPermissions(const std::string& bundleName); + + int GetDefPermission(const std::string& permissionName, PermissionDefParcel& permissionDefParcel) const; + +private: + PermissionDefinitionManager(); + + DISALLOW_COPY_AND_MOVE(PermissionDefinitionManager); + + bool IsGrantModeValid(const int grantMode) const; + + bool IsAvailableScopeValid(const int availableScope) const; + + bool IsPermissionDefValid(const PermissionDef& permissionDef) const; + + void RefreshPersistentDataIfNeeded(); + + OHOS::ThreadPool permissionDefDataAccessWorker_; + + bool hasInited_; + + OHOS::Utils::RWLock rwLock_; +}; +} // namespace Permission +} // namespace Security +} // namespace OHOS + +#endif // PERMISSION_DEFINITION_MANAGER_H diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_manager_service.cpp b/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_manager_service.cpp new file mode 100755 index 0000000..110906d --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_manager_service.cpp @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "permission_manager_service.h" + +#include "permission.h" +#include "permission_definition_manager.h" +#include "permission_state_manager.h" +#include "permission_log.h" + +namespace OHOS { +namespace Security { +namespace Permission { +namespace { +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_PERMISSION, "PermissionManagerService"}; +} + +const bool REGISTER_RESULT = + SystemAbility::MakeAndRegisterAbility(DelayedSingleton::GetInstance().get()); + +PermissionManagerService::PermissionManagerService() + : SystemAbility(SA_ID_PERMISSION_MANAGER_SERVICE, true), state_(ServiceRunningState::STATE_NOT_START) +{ + PERMISSION_LOG_INFO(LABEL, "PermissionManagerService()"); +} + +PermissionManagerService::~PermissionManagerService() +{ + PERMISSION_LOG_INFO(LABEL, "~PermissionManagerService()"); +} + +void PermissionManagerService::OnStart() +{ + if (state_ == ServiceRunningState::STATE_RUNNING) { + PERMISSION_LOG_INFO(LABEL, "PermissionManagerService has already started!"); + return; + } + PERMISSION_LOG_INFO(LABEL, "PermissionManagerService is starting"); + if (!Initialize()) { + PERMISSION_LOG_ERROR(LABEL, "Failed to initialize"); + return; + } + state_ = ServiceRunningState::STATE_RUNNING; + bool ret = Publish(DelayedSingleton::GetInstance().get()); + if (!ret) { + PERMISSION_LOG_ERROR(LABEL, "Failed to publish service!"); + return; + } + PERMISSION_LOG_INFO(LABEL, "Congratulations, PermissionManagerService start successfully!"); +} + +void PermissionManagerService::OnStop() +{ + PERMISSION_LOG_INFO(LABEL, "stop service"); + state_ = ServiceRunningState::STATE_NOT_START; +} + +int PermissionManagerService::VerifyPermission( + const std::string& bundleName, const std::string& permissionName, int userId) +{ + PERMISSION_LOG_INFO(LABEL, + "%{public}s called, packageName: %{public}s, permissionName: %{public}s, userId: %{public}d", __func__, + bundleName.c_str(), permissionName.c_str(), userId); + return PermissionStateManager::GetInstance().VerifyPermission(bundleName, permissionName, userId); +} + +bool PermissionManagerService::CanRequestPermission( + const std::string& bundleName, const std::string& permissionName, int userId) +{ + PERMISSION_LOG_INFO(LABEL, + "%{public}s called, bundleName: %{public}s, permissionName: %{public}s, userId: %{public}d", __func__, + bundleName.c_str(), permissionName.c_str(), userId); + return PermissionStateManager::GetInstance().CanRequestPermission(bundleName, permissionName, userId); +} + +int PermissionManagerService::GrantUserGrantedPermission( + const std::string& bundleName, const std::string& permissionName, int userId) +{ + PERMISSION_LOG_INFO(LABEL, + "%{public}s called, bundleName: %{public}s, permissionName: %{public}s, userId: %{public}d", __func__, + bundleName.c_str(), permissionName.c_str(), userId); + PermissionStateManager::GetInstance().GrantUserGrantedPermission(bundleName, permissionName, userId); + return RET_SUCCESS; +} + +int PermissionManagerService::GrantSystemGrantedPermission( + const std::string& bundleName, const std::string& permissionName) +{ + PERMISSION_LOG_INFO(LABEL, "%{public}s called, bundleName: %{public}s, permissionName: %{public}s", __func__, + bundleName.c_str(), permissionName.c_str()); + PermissionStateManager::GetInstance().GrantSystemGrantedPermission(bundleName, permissionName); + return RET_SUCCESS; +} + +int PermissionManagerService::RevokeUserGrantedPermission( + const std::string& bundleName, const std::string& permissionName, int userId) +{ + PERMISSION_LOG_INFO(LABEL, + "%{public}s called, bundleName: %{public}s, permissionName: %{public}s, userId: %{public}d", __func__, + bundleName.c_str(), permissionName.c_str(), userId); + PermissionStateManager::GetInstance().RevokeUserGrantedPermission(bundleName, permissionName, userId); + return RET_SUCCESS; +} + +int PermissionManagerService::RevokeSystemGrantedPermission( + const std::string& bundleName, const std::string& permissionName) +{ + PERMISSION_LOG_INFO(LABEL, "%{public}s called, bundleName: %{public}s, permissionName: %{public}s", __func__, + bundleName.c_str(), permissionName.c_str()); + PermissionStateManager::GetInstance().RevokeSystemGrantedPermission(bundleName, permissionName); + return RET_SUCCESS; +} + +int PermissionManagerService::AddUserGrantedReqPermissions( + const std::string& bundleName, const std::vector& permList, int userId) +{ + PERMISSION_LOG_INFO(LABEL, + "%{public}s called, bundleName: %{public}s, permList size: %{public}d, userId: %{public}d", __func__, + bundleName.c_str(), (int) permList.size(), userId); + PermissionStateManager::GetInstance().AddUserGrantedReqPermissions(bundleName, permList, userId); + return RET_SUCCESS; +} + +int PermissionManagerService::AddSystemGrantedReqPermissions( + const std::string& bundleName, const std::vector& permList) +{ + PERMISSION_LOG_INFO(LABEL, "%{public}s called, bundleName: %{public}s, permList size: %{public}d", __func__, + bundleName.c_str(), (int) permList.size()); + PermissionStateManager::GetInstance().AddSystemGrantedReqPermissions(bundleName, permList); + return RET_SUCCESS; +} + +int PermissionManagerService::RemoveUserGrantedReqPermissions(const std::string& bundleName, int userId) +{ + PERMISSION_LOG_INFO( + LABEL, "%{public}s called, bundleName: %{public}s, userId: %{public}d", __func__, bundleName.c_str(), userId); + PermissionStateManager::GetInstance().RemoveUserGrantedReqPermissions(bundleName, userId); + return RET_SUCCESS; +} + +int PermissionManagerService::RemoveSystemGrantedReqPermissions(const std::string& bundleName) +{ + PERMISSION_LOG_INFO(LABEL, "%{public}s called, bundleName: %{public}s", __func__, bundleName.c_str()); + PermissionStateManager::GetInstance().RemoveSystemGrantedReqPermissions(bundleName); + return RET_SUCCESS; +} + +int PermissionManagerService::AddDefPermissions(const std::vector& permDefList) +{ + PERMISSION_LOG_INFO(LABEL, "%{public}s called, permList size: %{public}d", __func__, (int) permDefList.size()); + PermissionDefinitionManager::GetInstance().AddDefPermissions(permDefList); + return RET_SUCCESS; +} + +int PermissionManagerService::RemoveDefPermissions(const std::string& bundleName) +{ + PERMISSION_LOG_INFO(LABEL, "%{public}s called, bundleName: %{public}s", __func__, bundleName.c_str()); + PermissionDefinitionManager::GetInstance().RemoveDefPermissions(bundleName); + return RET_SUCCESS; +} + +int PermissionManagerService::GetDefPermission( + const std::string& permissionName, PermissionDefParcel& permissionDefResult) +{ + PERMISSION_LOG_INFO(LABEL, "%{public}s called, bundleName: %{public}s", __func__, permissionName.c_str()); + return PermissionDefinitionManager::GetInstance().GetDefPermission(permissionName, permissionDefResult); +} + +bool PermissionManagerService::Initialize() const +{ + PermissionDefinitionManager::GetInstance().Init(); + PermissionStateManager::GetInstance().Init(); + return true; +} +} // namespace Permission +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_manager_service.h b/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_manager_service.h new file mode 100755 index 0000000..d049ea5 --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_manager_service.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PERMISSION_MANAGER_SERVICE_H +#define PERMISSION_MANAGER_SERVICE_H + +#include "permission_manager_stub.h" + +#include "singleton.h" +#include "iremote_object.h" +#include "system_ability.h" +#include "nocopyable.h" + +namespace OHOS { +namespace Security { +namespace Permission { +enum class ServiceRunningState { STATE_NOT_START, STATE_RUNNING }; +class PermissionManagerService final : public SystemAbility, public PermissionManagerStub { + DECLARE_DELAYED_SINGLETON(PermissionManagerService); + DECLEAR_SYSTEM_ABILITY(PermissionManagerService); + +public: + void OnStart() override; + void OnStop() override; + + int VerifyPermission(const std::string& bundleName, const std::string& permissionName, int userId) override; + + bool CanRequestPermission(const std::string& bundleName, const std::string& permissionName, int userId) override; + + int GrantUserGrantedPermission( + const std::string& bundleName, const std::string& permissionName, int userId) override; + + int GrantSystemGrantedPermission(const std::string& bundleName, const std::string& permissionName) override; + + int RevokeUserGrantedPermission( + const std::string& bundleName, const std::string& permissionName, int userId) override; + + int RevokeSystemGrantedPermission(const std::string& bundleName, const std::string& permissionName) override; + + int AddUserGrantedReqPermissions( + const std::string& bundleName, const std::vector& permList, int userId) override; + + int AddSystemGrantedReqPermissions( + const std::string& bundleName, const std::vector& permList) override; + + int RemoveUserGrantedReqPermissions(const std::string& bundleName, int userId) override; + + int RemoveSystemGrantedReqPermissions(const std::string& bundleName) override; + + int AddDefPermissions(const std::vector& permDefList) override; + + int RemoveDefPermissions(const std::string& bundleName) override; + + int GetDefPermission(const std::string& permissionName, PermissionDefParcel& permissionDefResult) override; + +private: + bool Initialize() const; + + ServiceRunningState state_; +}; +} // namespace Permission +} // namespace Security +} // namespace OHOS +#endif // PERMISSION_MANAGER_SERVICE_H diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_manager_stub.cpp b/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_manager_stub.cpp new file mode 100644 index 0000000..ba76cb8 --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_manager_stub.cpp @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "permission_manager_stub.h" + +#include "permission.h" +#include "permission_log.h" + +#include "ipc_skeleton.h" +#include "string_ex.h" + +namespace OHOS { +namespace Security { +namespace Permission { +namespace { +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_PERMISSION, "PermissionManagerStub"}; +} + +int32_t PermissionManagerStub::OnRemoteRequest( + uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option) +{ + PERMISSION_LOG_INFO(LABEL, "%{public}s called, code: %{public}d", __func__, code); + std::u16string descriptor = data.ReadInterfaceToken(); + if (descriptor != IPermissionManager::GetDescriptor()) { + PERMISSION_LOG_ERROR(LABEL, "get unexpect descriptor: %{public}s", Str16ToStr8(descriptor).c_str()); + return RET_FAILED; + } + switch (code) { + case static_cast(IPermissionManager::InterfaceCode::VERIFY_PERMISSION): + VerifyPermissionInner(data, reply); + break; + case static_cast(IPermissionManager::InterfaceCode::CAN_REQUEST_PERMISSION): + CanRequestPermissionInner(data, reply); + break; + case static_cast(IPermissionManager::InterfaceCode::GRANT_USER_GRANTED_PERMISSION): + GrantUserGrantedPermissionInner(data, reply); + break; + case static_cast(IPermissionManager::InterfaceCode::GRANT_SYSTEM_GRANTED_PERMISSION): + GrantSystemGrantedPermissionInner(data, reply); + break; + case static_cast(IPermissionManager::InterfaceCode::REVOKE_USER_GRANTED_PERMISSION): + RevokeUserGrantedPermissionInner(data, reply); + break; + case static_cast(IPermissionManager::InterfaceCode::REVOKE_SYSTEM_GRANTED_PERMISSION): + RevokeSystemGrantedPermissionInner(data, reply); + break; + case static_cast(IPermissionManager::InterfaceCode::ADD_USER_GRANTED_REQ_PERMISSIONS): + AddUserGrantedReqPermissionsInner(data, reply); + break; + case static_cast(IPermissionManager::InterfaceCode::ADD_SYSTEM_GRANTED_REQ_PERMISSIONS): + AddSystemGrantedReqPermissionsInner(data, reply); + break; + case static_cast(IPermissionManager::InterfaceCode::REMOVE_USER_GRANTED_REQ_PERMISSIONS): + RemoveUserGrantedReqPermissionsInner(data, reply); + break; + case static_cast(IPermissionManager::InterfaceCode::REMOVE_SYSTEM_GRANTED_REQ_PERMISSIONS): + RemoveSystemGrantedReqPermissionsInner(data, reply); + break; + case static_cast(IPermissionManager::InterfaceCode::ADD_DEF_PERMISSIONS): + AddDefPermissionsInner(data, reply); + break; + case static_cast(IPermissionManager::InterfaceCode::REMOVE_DEF_PERMISSIONS): + RemoveDefPermissionsInner(data, reply); + break; + case static_cast(IPermissionManager::InterfaceCode::GET_DEF_PERMISSION): + GetDefPermissionInner(data, reply); + break; + default: + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); + } + return NO_ERROR; +} + +void PermissionManagerStub::VerifyPermissionInner(MessageParcel& data, MessageParcel& reply) +{ + std::string bundleName = data.ReadString(); + std::string permissionName = data.ReadString(); + int userId = data.ReadInt32(); + int result = this->VerifyPermission(bundleName, permissionName, userId); + reply.WriteInt32(result); +} + +void PermissionManagerStub::CanRequestPermissionInner(MessageParcel& data, MessageParcel& reply) +{ + std::string bundleName = data.ReadString(); + std::string permissionName = data.ReadString(); + int userId = data.ReadInt32(); + int result = this->CanRequestPermission(bundleName, permissionName, userId); + reply.WriteBool(result); +} + +void PermissionManagerStub::GrantUserGrantedPermissionInner(MessageParcel& data, MessageParcel& reply) +{ + if (!IsAuthorizedCalling()) { + PERMISSION_LOG_INFO(LABEL, "%{public}s called, permission denied", __func__); + reply.WriteInt32(RET_FAILED); + return; + } + std::string bundleName = data.ReadString(); + std::string permissionName = data.ReadString(); + int userId = data.ReadInt32(); + int result = this->GrantUserGrantedPermission(bundleName, permissionName, userId); + reply.WriteInt32(result); +} + +void PermissionManagerStub::GrantSystemGrantedPermissionInner(MessageParcel& data, MessageParcel& reply) +{ + if (!IsAuthorizedCalling()) { + PERMISSION_LOG_INFO(LABEL, "%{public}s called, permission denied", __func__); + reply.WriteInt32(RET_FAILED); + return; + } + std::string bundleName = data.ReadString(); + std::string permissionName = data.ReadString(); + int result = this->GrantSystemGrantedPermission(bundleName, permissionName); + reply.WriteInt32(result); +} + +void PermissionManagerStub::RevokeUserGrantedPermissionInner(MessageParcel& data, MessageParcel& reply) +{ + if (!IsAuthorizedCalling()) { + PERMISSION_LOG_INFO(LABEL, "%{public}s called, permission denied", __func__); + reply.WriteInt32(RET_FAILED); + return; + } + std::string bundleName = data.ReadString(); + std::string permissionName = data.ReadString(); + int userId = data.ReadInt32(); + int result = this->RevokeUserGrantedPermission(bundleName, permissionName, userId); + reply.WriteInt32(result); +} + +void PermissionManagerStub::RevokeSystemGrantedPermissionInner(MessageParcel& data, MessageParcel& reply) +{ + if (!IsAuthorizedCalling()) { + PERMISSION_LOG_INFO(LABEL, "%{public}s called, permission denied", __func__); + reply.WriteInt32(RET_FAILED); + return; + } + std::string bundleName = data.ReadString(); + std::string permissionName = data.ReadString(); + int result = this->RevokeSystemGrantedPermission(bundleName, permissionName); + reply.WriteInt32(result); +} + +void PermissionManagerStub::AddUserGrantedReqPermissionsInner(MessageParcel& data, MessageParcel& reply) +{ + if (!IsAuthorizedCalling()) { + PERMISSION_LOG_INFO(LABEL, "%{public}s called, permission denied", __func__); + reply.WriteInt32(RET_FAILED); + return; + } + std::string bundleName = data.ReadString(); + std::vector permList; + data.ReadStringVector(&permList); + int userId = data.ReadInt32(); + int result = this->AddUserGrantedReqPermissions(bundleName, permList, userId); + reply.WriteInt32(result); +} + +void PermissionManagerStub::AddSystemGrantedReqPermissionsInner(MessageParcel& data, MessageParcel& reply) +{ + if (!IsAuthorizedCalling()) { + PERMISSION_LOG_INFO(LABEL, "%{public}s called, permission denied", __func__); + reply.WriteInt32(RET_FAILED); + return; + } + std::string bundleName = data.ReadString(); + std::vector permList; + data.ReadStringVector(&permList); + int result = this->AddSystemGrantedReqPermissions(bundleName, permList); + reply.WriteInt32(result); +} + +void PermissionManagerStub::RemoveUserGrantedReqPermissionsInner(MessageParcel& data, MessageParcel& reply) +{ + if (!IsAuthorizedCalling()) { + PERMISSION_LOG_INFO(LABEL, "%{public}s called, permission denied", __func__); + reply.WriteInt32(RET_FAILED); + return; + } + std::string bundleName = data.ReadString(); + int userId = data.ReadInt32(); + int result = this->RemoveUserGrantedReqPermissions(bundleName, userId); + reply.WriteInt32(result); +} + +void PermissionManagerStub::RemoveSystemGrantedReqPermissionsInner(MessageParcel& data, MessageParcel& reply) +{ + if (!IsAuthorizedCalling()) { + PERMISSION_LOG_INFO(LABEL, "%{public}s called, permission denied", __func__); + reply.WriteInt32(RET_FAILED); + return; + } + std::string bundleName = data.ReadString(); + int result = this->RemoveSystemGrantedReqPermissions(bundleName); + reply.WriteInt32(result); +} + +void PermissionManagerStub::AddDefPermissionsInner(MessageParcel& data, MessageParcel& reply) +{ + if (!IsAuthorizedCalling()) { + PERMISSION_LOG_INFO(LABEL, "%{public}s called, permission denied", __func__); + reply.WriteInt32(RET_FAILED); + return; + } + int size = 0; + data.ReadInt32(size); + std::vector permList; + for (int i = 0; i < size; i++) { + sptr permissionDef = data.ReadParcelable(); + if (permissionDef != nullptr) { + permList.emplace_back(*permissionDef); + } + } + PERMISSION_LOG_INFO(LABEL, "%{public}s called, permList size: %{public}d", __func__, (int) permList.size()); + int result = this->AddDefPermissions(permList); + reply.WriteInt32(result); +} + +void PermissionManagerStub::RemoveDefPermissionsInner(MessageParcel& data, MessageParcel& reply) +{ + if (!IsAuthorizedCalling()) { + PERMISSION_LOG_INFO(LABEL, "%{public}s called, permission denied", __func__); + reply.WriteInt32(RET_FAILED); + return; + } + std::string bundleName = data.ReadString(); + int result = this->RemoveDefPermissions(bundleName); + reply.WriteInt32(result); +} + +void PermissionManagerStub::GetDefPermissionInner(MessageParcel& data, MessageParcel& reply) +{ + if (!IsAuthorizedCalling()) { + PERMISSION_LOG_INFO(LABEL, "%{public}s called, permission denied", __func__); + return; + } + std::string permissionName = data.ReadString(); + PermissionDefParcel permissionDefParcel; + int result = this->GetDefPermission(permissionName, permissionDefParcel); + reply.WriteParcelable(&permissionDefParcel); + reply.WriteInt32(result); +} + +bool PermissionManagerStub::IsAuthorizedCalling() const +{ + int callingUid = IPCSkeleton::GetCallingUid(); + PERMISSION_LOG_INFO(LABEL, "Calling uid: %{public}d", callingUid); + return callingUid == SYSTEM_UID || callingUid == ROOT_UID; +} +} // namespace Permission +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_manager_stub.h b/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_manager_stub.h new file mode 100644 index 0000000..212460b --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_manager_stub.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PERMISSION_MANAGER_STUB_H +#define PERMISSION_MANAGER_STUB_H + +#include "i_permission_manager.h" + +#include "iremote_stub.h" +#include "nocopyable.h" + +namespace OHOS { +namespace Security { +namespace Permission { +class PermissionManagerStub : public IRemoteStub { +public: + PermissionManagerStub() = default; + virtual ~PermissionManagerStub() = default; + + int OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& options) override; + +private: + void VerifyPermissionInner(MessageParcel& data, MessageParcel& reply); + void CanRequestPermissionInner(MessageParcel& data, MessageParcel& reply); + void GrantUserGrantedPermissionInner(MessageParcel& data, MessageParcel& reply); + void GrantSystemGrantedPermissionInner(MessageParcel& data, MessageParcel& reply); + void RevokeUserGrantedPermissionInner(MessageParcel& data, MessageParcel& reply); + void RevokeSystemGrantedPermissionInner(MessageParcel& data, MessageParcel& reply); + void AddUserGrantedReqPermissionsInner(MessageParcel& data, MessageParcel& reply); + void AddSystemGrantedReqPermissionsInner(MessageParcel& data, MessageParcel& reply); + void RemoveUserGrantedReqPermissionsInner(MessageParcel& data, MessageParcel& reply); + void RemoveSystemGrantedReqPermissionsInner(MessageParcel& data, MessageParcel& reply); + void AddDefPermissionsInner(MessageParcel& data, MessageParcel& reply); + void RemoveDefPermissionsInner(MessageParcel& data, MessageParcel& reply); + void GetDefPermissionInner(MessageParcel& data, MessageParcel& reply); + bool IsAuthorizedCalling() const; + + static const int SYSTEM_UID = 1000; + static const int ROOT_UID = 0; +}; +} // namespace Permission +} // namespace Security +} // namespace OHOS +#endif // PERMISSION_MANAGER_STUB_H diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_req.h b/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_req.h new file mode 100644 index 0000000..f350417 --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_req.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PERMISSION_STANDARD__PERMISSION_REQ_H +#define PERMISSION_STANDARD__PERMISSION_REQ_H + +#include + +namespace OHOS { +namespace Security { +namespace Permission { +struct PermissionReq { + std::string reqPermissionName; + bool isGranted; + int flags; +}; +} // namespace Permission +} // namespace Security +} // namespace OHOS + +#endif // PERMISSION_STANDARD__PERMISSION_REQ_H \ No newline at end of file diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_state_cache.cpp b/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_state_cache.cpp new file mode 100644 index 0000000..09ec25a --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_state_cache.cpp @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "permission_state_cache.h" + +#include + +#include "permission.h" +#include "permission_log.h" + +namespace OHOS { +namespace Security { +namespace Permission { +namespace { +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_PERMISSION, "PermissionStateCache"}; +} +int PermissionStateCache::AddReqPermission( + const int userId, const std::string& bundleName, const std::string& permissionName) +{ + Utils::UniqueWriteGuard cacheGuard(this->cacheLock_); + BundleInfo& bundleInfo = Root::GetRoot().GetOrCreateUserInfo(userId).GetOrCreateBundleInfo(bundleName); + return bundleInfo.AddReqPermission(permissionName); +} + +int PermissionStateCache::AddReqPermission( + const int userId, const std::string& bundleName, const std::vector& permList) +{ + Utils::UniqueWriteGuard cacheGuard(this->cacheLock_); + BundleInfo& bundleInfo = Root::GetRoot().GetOrCreateUserInfo(userId).GetOrCreateBundleInfo(bundleName); + for (const auto& permissionName : permList) { + bundleInfo.AddReqPermission(permissionName); + } + return RET_SUCCESS; +} + +int PermissionStateCache::ReplaceReqPermission( + int userId, const std::string& bundleName, const PermissionReq& permissionReq) +{ + Utils::UniqueWriteGuard cacheGuard(this->cacheLock_); + return Root::GetRoot().GetOrCreateUserInfo(userId).ReplaceReqPermission(bundleName, permissionReq); +} + +int PermissionStateCache::RemoveReqPermission(const int userId, const std::string& bundleName) +{ + Utils::UniqueWriteGuard cacheGuard(this->cacheLock_); + if (!Root::GetRoot().HasUserInfo(userId)) { + return RET_FAILED; + } + return Root::GetRoot().GetOrCreateUserInfo(userId).RemoveReqPermission(bundleName); +} + +int PermissionStateCache::UpdatePermissionState( + int userId, const std::string& bundleName, const std::string& permissionName, bool isGranted) +{ + Utils::UniqueWriteGuard cacheGuard(this->cacheLock_); + if (!Root::GetRoot().HasUserInfo(userId)) { + return RET_FAILED; + } + return Root::GetRoot().GetOrCreateUserInfo(userId).UpdatePermissionState(bundleName, permissionName, isGranted); +} + +int PermissionStateCache::UpdatePermissionFlags( + int userId, const std::string& bundleName, const std::string& permissionName, int flags) +{ + Utils::UniqueWriteGuard cacheGuard(this->cacheLock_); + if (!Root::GetRoot().HasUserInfo(userId)) { + return RET_FAILED; + } + return Root::GetRoot().GetOrCreateUserInfo(userId).UpdatePermissionFlags(bundleName, permissionName, flags); +} + +bool PermissionStateCache::IsGranted(const int userId, const std::string& bundleName, const std::string& permissionName) +{ + Utils::UniqueReadGuard cacheGuard(this->cacheLock_); + if (!Root::GetRoot().HasUserInfo(userId)) { + return false; + } + return Root::GetRoot().GetOrCreateUserInfo(userId).IsGranted(bundleName, permissionName); +} + +int PermissionStateCache::GetPermissionFlags( + const int userId, const std::string& bundleName, const std::string& permissionName) +{ + if (!Root::GetRoot().HasUserInfo(userId)) { + return DEFAULT_PERMISSION_FLAGS; + } + return Root::GetRoot().GetOrCreateUserInfo(userId).GetPermissionFlags(bundleName, permissionName); +} + +std::string PermissionStateCache::ToString() +{ + Utils::UniqueReadGuard cacheGuard(this->cacheLock_); + return Root::GetRoot().ToString(); +} + +void PermissionStateCache::QueryCurrentCache(bool isSystemGranted, std::vector& valueList) +{ + Utils::UniqueReadGuard cacheGuard(this->cacheLock_); + + if (isSystemGranted) { + if (!Root::GetRoot().HasUserInfo(SYSTEM_GRANTED_USER_ID)) { + return; + } + UserInfo userInfo = Root::GetRoot().GetOrCreateUserInfo(SYSTEM_GRANTED_USER_ID); + QueryForUser(userInfo, valueList); + return; + } + + std::vector userInfoList; + Root::GetRoot().GetUserGrantedUserInfo(userInfoList); + for (auto userInfo : userInfoList) { + QueryForUser(userInfo, valueList); + } +} + +void PermissionStateCache::QueryForUser(const UserInfo& userInfo, std::vector& valueList) const +{ + std::vector bundleInfoList; + userInfo.GetAllBundleInfo(bundleInfoList); + for (auto bundleInfo : bundleInfoList) { + QueryForBundle(userInfo.userId_, bundleInfo, valueList); + } +} + +void PermissionStateCache::QueryForBundle( + const int userId, const BundleInfo& bundleInfo, std::vector& valueList) const +{ + std::vector permissionReqList; + bundleInfo.GetAllPermissionReq(permissionReqList); + for (auto permissionReq : permissionReqList) { + GenericValues genericValues; + genericValues.Put(FIELD_BUNDLE_NAME, bundleInfo.bundleName_); + DataTranslator::TranslationIntoGenericValues(permissionReq, genericValues); + if (userId == SYSTEM_GRANTED_USER_ID) { + valueList.emplace_back(genericValues); + } else { + genericValues.Put(FIELD_USER_ID, userId); + valueList.emplace_back(genericValues); + } + } +} + +PermissionStateCache& PermissionStateCache::GetInstance() +{ + static PermissionStateCache instance; + return instance; +} + +Root& Root::GetRoot() +{ + static Root root; + return root; +} + +bool Root::HasUserInfo(int userId) const +{ + return userInfos_.count(userId) == 1; +} + +UserInfo& Root::GetOrCreateUserInfo(const int userId) +{ + if (!HasUserInfo(userId)) { + UserInfo userInfo(userId); + userInfos_[userId] = userInfo; + PERMISSION_LOG_DEBUG( + LABEL, "%{public}s: userInfos_[userId]: %{public}s", __func__, userInfos_[userId].ToString().c_str()); + } + return userInfos_[userId]; +} + +void Root::GetUserGrantedUserInfo(std::vector& bundleInfoList) const +{ + for (auto it = userInfos_.begin(); it != userInfos_.end(); ++it) { + if (it->first != PermissionStateCache::SYSTEM_GRANTED_USER_ID) { + bundleInfoList.emplace_back(it->second); + } + } +} + +std::string Root::ToString() const +{ + std::string infos = R"({"Root": "Default", "UserInfos": [)"; + for (auto userInfo : userInfos_) { + infos.append(userInfo.second.ToString() + ", "); + } + infos = infos + "]}"; + return infos; +} + +UserInfo::UserInfo(int userId) +{ + userId_ = userId; +} + +bool UserInfo::HasBundleInfo(const std::string& bundleName) const +{ + return bundleInfos_.count(bundleName) == 1; +} + +BundleInfo& UserInfo::GetOrCreateBundleInfo(const std::string& bundleName) +{ + if (!HasBundleInfo(bundleName)) { + BundleInfo bundleInfo(bundleName); + bundleInfos_[bundleName] = bundleInfo; + } + return bundleInfos_[bundleName]; +} + +void UserInfo::GetAllBundleInfo(std::vector& bundleInfoList) const +{ + for (auto it = bundleInfos_.begin(); it != bundleInfos_.end(); ++it) { + bundleInfoList.emplace_back(it->second); + } +} + +std::string UserInfo::ToString() const +{ + std::string infos = R"({"userId": )" + std::to_string(userId_) + R"(, "BundleInfos": [)"; + for (auto bundleInfo : bundleInfos_) { + infos.append(bundleInfo.second.ToString() + ", "); + } + infos.append("]}"); + return infos; +} + +int UserInfo::ReplaceReqPermission(const std::string& bundleName, const PermissionReq& permissionReq) +{ + return GetOrCreateBundleInfo(bundleName).ReplaceReqPermission(permissionReq); +} + +int UserInfo::RemoveReqPermission(const std::string& bundleName) +{ + if (!HasBundleInfo(bundleName)) { + return RET_SUCCESS; + } + bundleInfos_[bundleName].RemoveReqPermissions(); + return RET_SUCCESS; +} + +int UserInfo::UpdatePermissionState(const std::string& bundleName, const std::string& permissionName, bool isGranted) +{ + if (!HasBundleInfo(bundleName)) { + return RET_FAILED; + } + return bundleInfos_[bundleName].UpdateGrantedState(permissionName, isGranted); +} + +int UserInfo::UpdatePermissionFlags(const std::string& bundleName, const std::string& permissionName, int flags) +{ + if (!HasBundleInfo(bundleName)) { + return RET_FAILED; + } + return bundleInfos_[bundleName].UpdatePermissionFlags(permissionName, flags); +} + +bool UserInfo::IsGranted(const std::string& bundleName, const std::string& permissionName) +{ + if (!HasBundleInfo(bundleName)) { + return false; + } + return bundleInfos_[bundleName].IsGranted(permissionName); +} + +int UserInfo::GetPermissionFlags(const std::string& bundleName, const std::string& permissionName) +{ + if (!HasBundleInfo(bundleName)) { + return DEFAULT_PERMISSION_FLAGS; + } + return bundleInfos_[bundleName].GetPermissionFlags(permissionName); +} + +BundleInfo::BundleInfo(std::string bundleName) +{ + bundleName_ = std::move(bundleName); +} + +int BundleInfo::AddReqPermission(const std::string& permissionName) +{ + if (HasReqPermission(permissionName)) { + PERMISSION_LOG_DEBUG( + LABEL, "%{public}s failed, reqPermission is exist, name: %{public}s", __func__, permissionName.c_str()); + return RET_FAILED; + } + PermissionReq permissionReq = {permissionName, false, DEFAULT_PERMISSION_FLAGS}; + permissionRequests_[permissionName] = permissionReq; + return RET_SUCCESS; +} + +int BundleInfo::ReplaceReqPermission(const PermissionReq& permissionReq) +{ + permissionRequests_[permissionReq.reqPermissionName] = permissionReq; + return RET_SUCCESS; +} + +PermissionReq& BundleInfo::GetReqPermission(const std::string& permissionName) +{ + return permissionRequests_[permissionName]; +} + +bool BundleInfo::HasReqPermission(const std::string& permissionName) const +{ + return permissionRequests_.count(permissionName) == 1; +} + +void BundleInfo::RemoveReqPermissions() +{ + permissionRequests_.clear(); +} + +int BundleInfo::UpdateGrantedState(const std::string& permissionName, bool isGranted) +{ + if (!HasReqPermission(permissionName)) { + return RET_FAILED; + } + GetReqPermission(permissionName).isGranted = isGranted; + return RET_SUCCESS; +} + +int BundleInfo::UpdatePermissionFlags(const std::string& permissionName, int flags) +{ + if (!HasReqPermission(permissionName)) { + return RET_FAILED; + } + GetReqPermission(permissionName).flags = flags; + return RET_SUCCESS; +} + +bool BundleInfo::IsGranted(const std::string& permissionName) +{ + if (!HasReqPermission(permissionName)) { + return false; + } + return GetReqPermission(permissionName).isGranted; +} + +int BundleInfo::GetPermissionFlags(const std::string& permissionName) +{ + if (!HasReqPermission(permissionName)) { + return DEFAULT_PERMISSION_FLAGS; + } + return GetReqPermission(permissionName).flags; +} + +void BundleInfo::GetAllPermissionReq(std::vector& permissionReqList) const +{ + for (auto it = permissionRequests_.begin(); it != permissionRequests_.end(); ++it) { + permissionReqList.emplace_back(it->second); + } +} + +std::string BundleInfo::ToString() const +{ + std::string infos = R"({"bundleName": ")" + bundleName_ + R"(", "ReqPermissions": [)"; + for (const auto& request : permissionRequests_) { + PermissionReq permissionReq = request.second; + infos.append(R"({"permissionName": ")" + permissionReq.reqPermissionName + R"(")"); + infos.append(R"(, "isGranted": )" + std::to_string(permissionReq.isGranted)); + infos.append(R"(, "flags": )" + std::to_string(permissionReq.flags)); + infos.append("}, "); + } + infos = infos + "]}"; + return infos; +} +} // namespace Permission +} // namespace Security +} // namespace OHOS diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_state_cache.h b/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_state_cache.h new file mode 100755 index 0000000..ed0e2d8 --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_state_cache.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PERMISSION_STANDARD_PERMISSION_STATE_CACHE_H +#define PERMISSION_STANDARD_PERMISSION_STATE_CACHE_H + +#include +#include +#include + +#include "permission_req.h" +#include "generic_values.h" +#include "data_translator.h" +#include "field_const.h" + +#include "rwlock.h" + +namespace OHOS { +namespace Security { +namespace Permission { +static const int DEFAULT_PERMISSION_FLAGS = 0; +class BundleInfo final { +public: + std::string bundleName_; + BundleInfo() = default; + virtual ~BundleInfo() = default; + explicit BundleInfo(std::string bundleName); + int AddReqPermission(const std::string& permissionName); + int ReplaceReqPermission(const PermissionReq& permissionReq); + PermissionReq& GetReqPermission(const std::string& permissionName); + void RemoveReqPermissions(); + bool HasReqPermission(const std::string& permissionName) const; + int UpdateGrantedState(const std::string& permissionName, bool isGranted); + int UpdatePermissionFlags(const std::string& permissionName, int flags); + bool IsGranted(const std::string& permissionName); + int GetPermissionFlags(const std::string& permissionName); + void GetAllPermissionReq(std::vector& permissionReqList) const; + std::string ToString() const; + +private: + std::map permissionRequests_; +}; + +class UserInfo final { +public: + int userId_; + UserInfo() : userId_(0) + {} + virtual ~UserInfo() = default; + explicit UserInfo(int userId); + bool HasBundleInfo(const std::string& bundleName) const; + BundleInfo& GetOrCreateBundleInfo(const std::string& bundleName); + int ReplaceReqPermission(const std::string& bundleName, const PermissionReq& permissionReq); + int RemoveReqPermission(const std::string& bundleName); + int UpdatePermissionState(const std::string& bundleName, const std::string& permissionName, bool isGranted); + int UpdatePermissionFlags(const std::string& bundleName, const std::string& permissionName, int flags); + bool IsGranted(const std::string& bundleName, const std::string& permissionName); + int GetPermissionFlags(const std::string& bundleName, const std::string& permissionName); + void GetAllBundleInfo(std::vector& bundleInfoList) const; + std::string ToString() const; + +private: + std::map bundleInfos_; +}; + +class Root final { +public: + static Root& GetRoot(); + bool HasUserInfo(int userId) const; + UserInfo& GetOrCreateUserInfo(int userId); + void GetUserGrantedUserInfo(std::vector& userInfoList) const; + std::string ToString() const; + +private: + std::map userInfos_; +}; + +class PermissionStateCache final { +public: + static const int SYSTEM_GRANTED_USER_ID = -1; + static PermissionStateCache& GetInstance(); + virtual ~PermissionStateCache() = default; + std::string ToString(); + int AddReqPermission(int userId, const std::string& bundleName, const std::string& permissionName); + int AddReqPermission(int userId, const std::string& bundleName, const std::vector& permList); + int ReplaceReqPermission(int userId, const std::string& bundleName, const PermissionReq& permissionReq); + int RemoveReqPermission(int userId, const std::string& bundleName); + int UpdatePermissionState( + int userId, const std::string& bundleName, const std::string& permissionName, bool isGranted); + int UpdatePermissionFlags(int userId, const std::string& bundleName, const std::string& permissionName, int flags); + bool IsGranted(int userId, const std::string& bundleName, const std::string& permissionName); + int GetPermissionFlags(int userId, const std::string& bundleName, const std::string& permissionName); + void QueryCurrentCache(bool isSystemGranted, std::vector& valueList); + +private: + PermissionStateCache() = default; + + DISALLOW_COPY_AND_MOVE(PermissionStateCache); + + void QueryForUser(const UserInfo& userInfo, std::vector& valueList) const; + + void QueryForBundle(const int userId, const BundleInfo& bundleInfo, std::vector& valueList) const; + + OHOS::Utils::RWLock cacheLock_; +}; +} // namespace Permission +} // namespace Security +} // namespace OHOS +#endif // PERMISSION_STANDARD_PERMISSION_STATE_CACHE_H diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_state_manager.cpp b/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_state_manager.cpp new file mode 100644 index 0000000..e7aa235 --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_state_manager.cpp @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "permission_state_manager.h" + +#include "permission.h" +#include "data_storage.h" +#include "permission_log.h" +#include "permission_definition_cache.h" +#include "permission_state_cache.h" +#include "data_translator.h" +#include "data_validator.h" + +namespace OHOS { +namespace Security { +namespace Permission { +namespace { +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_PERMISSION, "PermissionStateManager"}; +} +PermissionStateManager& PermissionStateManager::GetInstance() +{ + static PermissionStateManager instance; + return instance; +} + +PermissionStateManager::PermissionStateManager() : hasInited_(false) +{} + +PermissionStateManager::~PermissionStateManager() +{ + if (!hasInited_) { + return; + } + this->systemGrantedDataAccessWorker_.Stop(); + this->userGrantedDataAccessWorker_.Stop(); + this->hasInited_ = false; +} + +void PermissionStateManager::Init() +{ + OHOS::Utils::UniqueWriteGuard lk(this->rwLock_); + if (hasInited_) { + return; + } + PERMISSION_LOG_INFO(LABEL, "init begin!"); + std::vector results; + DataStorage::GetRealDataStorage().Find(DataStorage::PERMISSIONS_STAT_SYSTEM_GRANTED, results); + for (auto value : results) { + std::string bundleName = value.GetString(FIELD_BUNDLE_NAME); + PERMISSION_LOG_INFO(LABEL, "Cache recover system grant %{public}s", bundleName.c_str()); + PermissionReq permissionReq; + DataTranslator::TranslationIntoPermissionReq(value, permissionReq); + PermissionStateCache::GetInstance().ReplaceReqPermission( + PermissionStateCache::SYSTEM_GRANTED_USER_ID, bundleName, permissionReq); + } + + DataStorage::GetRealDataStorage().Find(DataStorage::PERMISSIONS_STAT_USER_GRANTED, results); + for (auto value : results) { + std::string bundleName = value.GetString(FIELD_BUNDLE_NAME); + int userId = value.GetInt(FIELD_USER_ID); + PERMISSION_LOG_INFO(LABEL, "Cache recover user grant %{public}d, %{public}s", userId, bundleName.c_str()); + PermissionReq permissionReq; + DataTranslator::TranslationIntoPermissionReq(value, permissionReq); + PermissionStateCache::GetInstance().ReplaceReqPermission(userId, bundleName, permissionReq); + } + this->systemGrantedDataAccessWorker_.Start(1); + this->userGrantedDataAccessWorker_.Start(1); + hasInited_ = true; + PERMISSION_LOG_INFO(LABEL, "Init success"); +} + +void PermissionStateManager::AddUserGrantedReqPermissions( + const std::string& bundleName, const std::vector& permList, int userId) +{ + if (!DataValidator::IsBundleNameValid(bundleName) || permList.empty() || !DataValidator::IsUserIdValid(userId)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: invalid params!", __func__); + return; + } + + std::vector values; + for (const auto& permission : permList) { + if (!PermissionDefinitionCache::GetInstance().IsUserGrantedPermission(permission)) { + PERMISSION_LOG_ERROR(LABEL, + "%{public}s: permission: %{public}s is not user-granted permission, check please!", __func__, + permission.c_str()); + continue; + } + PermissionStateCache::GetInstance().AddReqPermission(userId, bundleName, permission); + } + RefreshUserGrantedPersistentDataIfNeeded(); +} + +void PermissionStateManager::RemoveUserGrantedReqPermissions(const std::string& bundleName, int userId) +{ + if (!DataValidator::IsBundleNameValid(bundleName) || !DataValidator::IsUserIdValid(userId)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: invalid params!", __func__); + return; + } + PermissionStateCache::GetInstance().RemoveReqPermission(userId, bundleName); + RefreshUserGrantedPersistentDataIfNeeded(); +} + +void PermissionStateManager::GrantUserGrantedPermission( + const std::string& bundleName, const std::string& permissionName, int userId) +{ + if (!DataValidator::IsBundleNameValid(bundleName) || !DataValidator::IsPermissionNameValid(permissionName) || + !DataValidator::IsUserIdValid(userId)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: invalid params!", __func__); + return; + } + PermissionStateCache::GetInstance().UpdatePermissionState(userId, bundleName, permissionName, true); + RefreshUserGrantedPersistentDataIfNeeded(); +} + +void PermissionStateManager::RevokeUserGrantedPermission( + const std::string& bundleName, const std::string& permissionName, int userId) +{ + if (!DataValidator::IsBundleNameValid(bundleName) || !DataValidator::IsPermissionNameValid(permissionName) || + !DataValidator::IsUserIdValid(userId)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: invalid params!", __func__); + return; + } + PermissionStateCache::GetInstance().UpdatePermissionState(userId, bundleName, permissionName, false); + RefreshUserGrantedPersistentDataIfNeeded(); +} + +void PermissionStateManager::AddSystemGrantedReqPermissions( + const std::string& bundleName, const std::vector& permList) +{ + if (!DataValidator::IsBundleNameValid(bundleName) || permList.empty()) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: invalid params!", __func__); + return; + } + + std::vector values; + for (const auto& permission : permList) { + if (!PermissionDefinitionCache::GetInstance().IsSystemGrantedPermission(permission)) { + PERMISSION_LOG_ERROR(LABEL, + "%{public}s: permission: %{public}s is not system-granted permission, check please!", __func__, + permission.c_str()); + continue; + } + PermissionStateCache::GetInstance().AddReqPermission( + PermissionStateCache::SYSTEM_GRANTED_USER_ID, bundleName, permission); + } + RefreshSystemGrantedPersistentDataIfNeeded(); +} + +void PermissionStateManager::RemoveSystemGrantedReqPermissions(const std::string& bundleName) +{ + if (!DataValidator::IsBundleNameValid(bundleName)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: invalid params!", __func__); + return; + } + PermissionStateCache::GetInstance().RemoveReqPermission(PermissionStateCache::SYSTEM_GRANTED_USER_ID, bundleName); + RefreshSystemGrantedPersistentDataIfNeeded(); +} + +void PermissionStateManager::GrantSystemGrantedPermission( + const std::string& bundleName, const std::string& permissionName) +{ + if (!DataValidator::IsBundleNameValid(bundleName) || !DataValidator::IsPermissionNameValid(permissionName)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: invalid params!", __func__); + return; + } + PermissionStateCache::GetInstance().UpdatePermissionState( + PermissionStateCache::SYSTEM_GRANTED_USER_ID, bundleName, permissionName, true); + RefreshSystemGrantedPersistentDataIfNeeded(); +} + +void PermissionStateManager::RevokeSystemGrantedPermission( + const std::string& bundleName, const std::string& permissionName) +{ + if (!DataValidator::IsBundleNameValid(bundleName) || !DataValidator::IsPermissionNameValid(permissionName)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: invalid params!", __func__); + return; + } + PermissionStateCache::GetInstance().UpdatePermissionState( + PermissionStateCache::SYSTEM_GRANTED_USER_ID, bundleName, permissionName, false); + RefreshSystemGrantedPersistentDataIfNeeded(); +} + +int PermissionStateManager::VerifyPermission( + const std::string& bundleName, const std::string& permissionName, int userId) const +{ + if (!DataValidator::IsBundleNameValid(bundleName) || !DataValidator::IsPermissionNameValid(permissionName) || + !DataValidator::IsUserIdValid(userId)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: invalid params!", __func__); + return PERMISSION_NOT_GRANTED; + } + if (!PermissionDefinitionCache::GetInstance().HasDefinition(permissionName)) { + PERMISSION_LOG_ERROR( + LABEL, "%{public}s: no definition for permission: %{public}s!", __func__, permissionName.c_str()); + return PERMISSION_NOT_GRANTED; + } + bool isGranted = false; + if (PermissionDefinitionCache::GetInstance().IsSystemGrantedPermission(permissionName)) { + isGranted = PermissionStateCache::GetInstance().IsGranted( + PermissionStateCache::SYSTEM_GRANTED_USER_ID, bundleName, permissionName); + } else { + isGranted = PermissionStateCache::GetInstance().IsGranted(userId, bundleName, permissionName); + } + PERMISSION_LOG_INFO(LABEL, "VerifyPermission %{public}s, %{public}s, %{public}d isGranted: %{public}d", + bundleName.c_str(), permissionName.c_str(), userId, isGranted); + return isGranted ? PERMISSION_GRANTED : PERMISSION_NOT_GRANTED; +} + +bool PermissionStateManager::CanRequestPermission( + const std::string& bundleName, const std::string& permissionName, int userId) const +{ + if (!DataValidator::IsBundleNameValid(bundleName) || !DataValidator::IsPermissionNameValid(permissionName) || + !DataValidator::IsUserIdValid(userId)) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: invalid params!", __func__); + return false; + } + return PermissionDefinitionCache::GetInstance().IsUserGrantedPermission(permissionName) && + !PermissionStateCache::GetInstance().IsGranted(userId, bundleName, permissionName); +} + +void PermissionStateManager::RefreshSystemGrantedPersistentDataIfNeeded() +{ + if (systemGrantedDataAccessWorker_.GetCurTaskNum() > 1) { + PERMISSION_LOG_WARN(LABEL, "%{public}s: has refresh task!", __func__); + return; + } + systemGrantedDataAccessWorker_.AddTask([]() { + std::vector valueList; + PermissionStateCache::GetInstance().QueryCurrentCache(true, valueList); + DataStorage::GetRealDataStorage().RefreshAll(DataStorage::PERMISSIONS_STAT_SYSTEM_GRANTED, valueList); + + // Sleep for one second to avoid frequent refresh of the database. + std::this_thread::sleep_for(std::chrono::seconds(1)); + }); +} + +void PermissionStateManager::RefreshUserGrantedPersistentDataIfNeeded() +{ + if (userGrantedDataAccessWorker_.GetCurTaskNum() > 1) { + PERMISSION_LOG_WARN(LABEL, "%{public}s: has refresh task!", __func__); + return; + } + userGrantedDataAccessWorker_.AddTask([]() { + std::vector valueList; + PermissionStateCache::GetInstance().QueryCurrentCache(false, valueList); + DataStorage::GetRealDataStorage().RefreshAll(DataStorage::PERMISSIONS_STAT_USER_GRANTED, valueList); + + // Sleep for one second to avoid frequent refresh of the database. + std::this_thread::sleep_for(std::chrono::seconds(1)); + }); +} +} // namespace Permission +} // namespace Security +} // namespace OHOS diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_state_manager.h b/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_state_manager.h new file mode 100755 index 0000000..8af5be3 --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/permission_state_manager.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PERMISSION_STATE_MANAGER_H +#define PERMISSION_STATE_MANAGER_H + +#include + +#include "field_const.h" + +#include "nocopyable.h" +#include "thread_pool.h" +#include "rwlock.h" + +namespace OHOS { +namespace Security { +namespace Permission { +class PermissionStateManager final { +public: + static PermissionStateManager& GetInstance(); + + virtual ~PermissionStateManager(); + + void Init(); + + void AddUserGrantedReqPermissions( + const std::string& bundleName, const std::vector& permList, int userId); + + void RemoveUserGrantedReqPermissions(const std::string& bundleName, int userId); + + void GrantUserGrantedPermission(const std::string& bundleName, const std::string& permissionName, int userId); + + void RevokeUserGrantedPermission(const std::string& bundleName, const std::string& permissionName, int userId); + + void AddSystemGrantedReqPermissions(const std::string& bundleName, const std::vector& permList); + + void RemoveSystemGrantedReqPermissions(const std::string& bundleName); + + void GrantSystemGrantedPermission(const std::string& bundleName, const std::string& permissionName); + + void RevokeSystemGrantedPermission(const std::string& bundleName, const std::string& permissionName); + + int VerifyPermission(const std::string& bundleName, const std::string& permissionName, int userId) const; + + bool CanRequestPermission(const std::string& bundleName, const std::string& permissionName, int userId) const; + +private: + PermissionStateManager(); + + DISALLOW_COPY_AND_MOVE(PermissionStateManager); + + void RefreshSystemGrantedPersistentDataIfNeeded(); + + void RefreshUserGrantedPersistentDataIfNeeded(); + + OHOS::ThreadPool systemGrantedDataAccessWorker_; + + OHOS::ThreadPool userGrantedDataAccessWorker_; + + bool hasInited_; + + OHOS::Utils::RWLock rwLock_; +}; +} // namespace Permission +} // namespace Security +} // namespace OHOS + +#endif // PERMISSION_STATE_MANAGER_H diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/sqlite_helper.cpp b/services/permission_standard/permissionmanagerservice/main/cpp/src/sqlite_helper.cpp new file mode 100755 index 0000000..4c3b3cc --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/sqlite_helper.cpp @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "sqlite_helper.h" + +#include "permission_log.h" + +namespace OHOS { +namespace Security { +namespace Permission { +namespace { +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_PERMISSION, "SqliteHelper"}; +} + +SqliteHelper::SqliteHelper(const std::string& dbName, const std::string& dbPath, int version) + : dbName_(dbName), dbPath_(dbPath), currentVersion_(version), db_(nullptr) +{} + +SqliteHelper::~SqliteHelper() +{} + +void SqliteHelper::Open() +{ + if (db_ != nullptr) { + return; + } + if (dbName_.empty() || dbPath_.empty() || currentVersion_ < 0) { + return; + } + std::string fileName = dbPath_ + dbName_; + int res = sqlite3_open(fileName.c_str(), &db_); + if (res != SQLITE_OK) { + PERMISSION_LOG_ERROR(LABEL, "Failed to open db: %{public}s", sqlite3_errmsg(db_)); + return; + } + + int version = GetVersion(); + if (version == currentVersion_) { + return; + } + + BeginTransaction(); + if (version == 0) { + OnCreate(); + } else { + if (version < currentVersion_) { + OnUpdate(); + } + } + SetVersion(); + CommitTransaction(); +} + +void SqliteHelper::Close() +{ + if (db_ == nullptr) { + PERMISSION_LOG_WARN(LABEL, "%{public}s: do open data base first!", __func__); + return; + } + int ret = sqlite3_close(db_); + if (ret != SQLITE_OK) { + PERMISSION_LOG_WARN(LABEL, "sqlite3_close error, ret=%{public}d", ret); + return; + } + db_ = nullptr; +} + +int SqliteHelper::BeginTransaction() const +{ + if (db_ == nullptr) { + PERMISSION_LOG_WARN(LABEL, "%{public}s: do open data base first!", __func__); + return GENERAL_ERROR; + } + char* errorMessage = nullptr; + int result = 0; + int ret = sqlite3_exec(db_, "BEGIN;", nullptr, nullptr, &errorMessage); + if (ret != SQLITE_OK) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: failed, errorMsg: %{public}s", __func__, errorMessage); + result = GENERAL_ERROR; + } + sqlite3_free(errorMessage); + return result; +} + +int SqliteHelper::CommitTransaction() const +{ + if (db_ == nullptr) { + PERMISSION_LOG_WARN(LABEL, "%{public}s: do open data base first!", __func__); + return GENERAL_ERROR; + } + char* errorMessage = nullptr; + int result = 0; + int ret = sqlite3_exec(db_, "COMMIT;", nullptr, nullptr, &errorMessage); + if (ret != SQLITE_OK) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: failed, errorMsg: %{public}s", __func__, errorMessage); + result = GENERAL_ERROR; + } + sqlite3_free(errorMessage); + return result; +} + +int SqliteHelper::RollbackTransaction() const +{ + if (db_ == nullptr) { + PERMISSION_LOG_WARN(LABEL, "%{public}s: do open data base first!", __func__); + return GENERAL_ERROR; + } + int result = 0; + char* errorMessage = nullptr; + int ret = sqlite3_exec(db_, "ROLLBACK;", nullptr, nullptr, &errorMessage); + if (ret != SQLITE_OK) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: failed, errorMsg: %{public}s", __func__, errorMessage); + result = GENERAL_ERROR; + } + sqlite3_free(errorMessage); + return result; +} + +Statement SqliteHelper::Prepare(const std::string& sql) const +{ + return Statement(db_, sql); +} + +int SqliteHelper::ExecuteSql(const std::string& sql) const +{ + if (db_ == nullptr) { + PERMISSION_LOG_WARN(LABEL, "%{public}s: do open data base first!", __func__); + return GENERAL_ERROR; + } + char* errorMessage = nullptr; + int result = 0; + int res = sqlite3_exec(db_, sql.c_str(), nullptr, nullptr, &errorMessage); + if (res != SQLITE_OK) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: failed, errorMsg: %{public}s", __func__, errorMessage); + result = GENERAL_ERROR; + } + sqlite3_free(errorMessage); + return result; +} + +int SqliteHelper::GetVersion() const +{ + if (db_ == nullptr) { + PERMISSION_LOG_WARN(LABEL, "%{public}s: do open data base first!", __func__); + return GENERAL_ERROR; + } + auto statement = Prepare(PRAGMA_VERSION_COMMAND); + int version = 0; + while (statement.Step() == Statement::State::ROW) { + version = statement.GetColumnInt(0); + } + PERMISSION_LOG_INFO(LABEL, "%{public}s: version: %{public}d", __func__, version); + return version; +} + +void SqliteHelper::SetVersion() const +{ + if (db_ == nullptr) { + PERMISSION_LOG_WARN(LABEL, "%{public}s: do open data base first!", __func__); + return; + } + auto statement = Prepare(PRAGMA_VERSION_COMMAND + " = " + std::to_string(currentVersion_)); + statement.Step(); +} + +std::string SqliteHelper::SpitError() const +{ + if (db_ == nullptr) { + PERMISSION_LOG_WARN(LABEL, "%{public}s: do open data base first!", __func__); + return ""; + } + return sqlite3_errmsg(db_); +} +} // namespace Permission +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/sqlite_helper.h b/services/permission_standard/permissionmanagerservice/main/cpp/src/sqlite_helper.h new file mode 100644 index 0000000..2f81fdd --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/sqlite_helper.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SQLITE_HELPER_H +#define SQLITE_HELPER_H + +#include + +#include "statement.h" + +#include "sqlite3sym.h" + +namespace OHOS { +namespace Security { +namespace Permission { +class SqliteHelper { +public: + explicit SqliteHelper(const std::string& dbName, const std::string& dbPath, int version); + virtual ~SqliteHelper(); + + void Open(); + void Close(); + + int BeginTransaction() const; + int CommitTransaction() const; + int RollbackTransaction() const; + + Statement Prepare(const std::string& sql) const; + int ExecuteSql(const std::string& sql) const; + std::string SpitError() const; + + virtual void OnCreate() = 0; + virtual void OnUpdate() = 0; + +private: + inline static const std::string PRAGMA_VERSION_COMMAND = "PRAGMA user_version"; + static const int GENERAL_ERROR = -1; + + const std::string dbName_; + const std::string dbPath_; + int currentVersion_; + sqlite3* db_; + + int GetVersion() const; + void SetVersion() const; +}; +} // namespace Permission +} // namespace Security +} // namespace OHOS +#endif // SQLITE_HELPER_H diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/sqlite_storage.cpp b/services/permission_standard/permissionmanagerservice/main/cpp/src/sqlite_storage.cpp new file mode 100644 index 0000000..008c158 --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/sqlite_storage.cpp @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "sqlite_storage.h" + +#include "permission_log.h" + +namespace OHOS { +namespace Security { +namespace Permission { +namespace { +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_PERMISSION, "SqliteStorage"}; +} + +SqliteStorage& SqliteStorage::GetInstance() +{ + static SqliteStorage instance; + return instance; +} + +SqliteStorage::~SqliteStorage() +{ + Close(); +} + +void SqliteStorage::OnCreate() +{ + PERMISSION_LOG_INFO(LABEL, "%{public}s called.", __func__); + CreatePermissionDefinitionTable(); + CreateSystemGrantedPermissionStateTable(); + CreateUserGrantedPermissionStateTable(); +} + +void SqliteStorage::OnUpdate() +{ + PERMISSION_LOG_INFO(LABEL, "%{public}s called.", __func__); +} + +SqliteStorage::SqliteStorage() : SqliteHelper(DATABASE_NAME, DATABASE_PATH, DATABASE_VERSION) +{ + SqliteTable permissionDefTable; + permissionDefTable.tableName_ = PERMISSION_DEF_TABLE; + permissionDefTable.tableColumnNames_ = { + FIELD_PERMISSION_NAME, + FIELD_BUNDLE_NAME, + FIELD_GRANT_MODE, + FIELD_AVAILABLE_SCOPE, + FIELD_LABEL, + FIELD_LABEL_ID, + FIELD_DESCRIPTION, + FIELD_DESCRIPTION_ID + }; + + SqliteTable sysGrantPermStatTable; + sysGrantPermStatTable.tableName_ = SYS_GRANTED_PERMISSION_STATE_TABLE; + sysGrantPermStatTable.tableColumnNames_ = { + FIELD_BUNDLE_NAME, + FIELD_PERMISSION_NAME, + FIELD_GRANTED, + FIELD_FLAGS + }; + + SqliteTable userGrantPermStatTable; + userGrantPermStatTable.tableName_ = USER_GRANTED_PERMISSION_STATE_TABLE; + userGrantPermStatTable.tableColumnNames_ = { + FIELD_BUNDLE_NAME, + FIELD_PERMISSION_NAME, + FIELD_USER_ID, + FIELD_GRANTED, + FIELD_FLAGS + }; + + dataTypeToSqlTable_ = { + {PERMISSION_DEF, permissionDefTable}, + {PERMISSIONS_STAT_SYSTEM_GRANTED, sysGrantPermStatTable}, + {PERMISSIONS_STAT_USER_GRANTED, userGrantPermStatTable} + }; + + Open(); +} + +int SqliteStorage::Add(const DataType type, const std::vector& values) +{ + OHOS::Utils::UniqueWriteGuard lock(this->rwLock_); + std::string prepareSql = CreateInsertPrepareSqlCmd(type); + auto statement = Prepare(prepareSql); + BeginTransaction(); + bool isExecuteSuccessfully = true; + for (auto value : values) { + std::vector columnNames = value.GetAllKeys(); + for (auto columnName : columnNames) { + statement.Bind(columnName, value.Get(columnName)); + } + int ret = statement.Step(); + if (ret != Statement::State::DONE) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: failed, errorMsg: %{public}s", __func__, SpitError().c_str()); + isExecuteSuccessfully = false; + } + statement.Reset(); + } + if (!isExecuteSuccessfully) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: rollback transaction.", __func__); + RollbackTransaction(); + return FAILURE; + } + PERMISSION_LOG_INFO(LABEL, "%{public}s: commit transaction.", __func__); + CommitTransaction(); + return SUCCESS; +} + +int SqliteStorage::Remove(const DataType type, const GenericValues& conditions) +{ + OHOS::Utils::UniqueWriteGuard lock(this->rwLock_); + std::vector columnNames = conditions.GetAllKeys(); + std::string prepareSql = CreateDeletePrepareSqlCmd(type, columnNames); + auto statement = Prepare(prepareSql); + for (auto columnName : columnNames) { + statement.Bind(columnName, conditions.Get(columnName)); + } + int ret = statement.Step(); + return (ret == Statement::State::DONE) ? SUCCESS : FAILURE; +} + +int SqliteStorage::Modify(const DataType type, const GenericValues& modifyValues, const GenericValues& conditions) +{ + OHOS::Utils::UniqueWriteGuard lock(this->rwLock_); + std::vector modifyColumns = modifyValues.GetAllKeys(); + std::vector conditionColumns = conditions.GetAllKeys(); + std::string prepareSql = CreateUpdatePrepareSqlCmd(type, modifyColumns, conditionColumns); + auto statement = Prepare(prepareSql); + for (auto columnName : modifyColumns) { + statement.Bind(columnName, modifyValues.Get(columnName)); + } + for (auto columnName : conditionColumns) { + statement.Bind(columnName, conditions.Get(columnName)); + } + int ret = statement.Step(); + return (ret == Statement::State::DONE) ? SUCCESS : FAILURE; +} + +int SqliteStorage::Find(const DataType type, std::vector& results) +{ + OHOS::Utils::UniqueWriteGuard lock(this->rwLock_); + std::string prepareSql = CreateSelectPrepareSqlCmd(type); + auto statement = Prepare(prepareSql); + while (statement.Step() == Statement::State::ROW) { + int columnCount = statement.GetColumnCount(); + GenericValues value; + for (int i = 0; i < columnCount; i++) { + value.Put(statement.GetColumnName(i), statement.GetValue(i)); + } + results.emplace_back(value); + } + return SUCCESS; +} + +int SqliteStorage::RefreshAll(const DataType type, const std::vector& values) +{ + OHOS::Utils::UniqueWriteGuard lock(this->rwLock_); + std::string deleteSql = CreateDeletePrepareSqlCmd(type); + std::string insertSql = CreateInsertPrepareSqlCmd(type); + auto deleteStatement = Prepare(deleteSql); + auto insertStatement = Prepare(insertSql); + BeginTransaction(); + bool canCommit = deleteStatement.Step() == Statement::State::DONE; + for (auto value : values) { + std::vector columnNames = value.GetAllKeys(); + for (auto columnName : columnNames) { + insertStatement.Bind(columnName, value.Get(columnName)); + } + int ret = insertStatement.Step(); + if (ret != Statement::State::DONE) { + PERMISSION_LOG_ERROR( + LABEL, "%{public}s: insert failed, errorMsg: %{public}s", __func__, SpitError().c_str()); + canCommit = false; + } + insertStatement.Reset(); + } + if (!canCommit) { + PERMISSION_LOG_ERROR(LABEL, "%{public}s: rollback transaction.", __func__); + RollbackTransaction(); + return FAILURE; + } + PERMISSION_LOG_INFO(LABEL, "%{public}s: commit transaction.", __func__); + CommitTransaction(); + return SUCCESS; +} + +std::string SqliteStorage::CreateInsertPrepareSqlCmd(const DataType type) const +{ + auto it = dataTypeToSqlTable_.find(type); + if (it == dataTypeToSqlTable_.end()) { + return std::string(); + } + std::string sql = "insert into " + it->second.tableName_ + " values("; + int i = 1; + for (const auto& columnName : it->second.tableColumnNames_) { + sql.append(":" + columnName); + if (i < (int) it->second.tableColumnNames_.size()) { + sql.append(","); + } + i += 1; + } + sql.append(")"); + return sql; +} + +std::string SqliteStorage::CreateDeletePrepareSqlCmd( + const DataType type, const std::vector& columnNames) const +{ + auto it = dataTypeToSqlTable_.find(type); + if (it == dataTypeToSqlTable_.end()) { + return std::string(); + } + std::string sql = "delete from " + it->second.tableName_ + " where 1 = 1"; + for (auto columnName : columnNames) { + sql.append(" and "); + sql.append(columnName + "=:" + columnName); + } + return sql; +} + +std::string SqliteStorage::CreateUpdatePrepareSqlCmd(const DataType type, const std::vector& modifyColumns, + const std::vector& conditionColumns) const +{ + if (modifyColumns.empty()) { + return std::string(); + } + + auto it = dataTypeToSqlTable_.find(type); + if (it == dataTypeToSqlTable_.end()) { + return std::string(); + } + + std::string sql = "update " + it->second.tableName_ + " set "; + int i = 1; + for (const auto& columnName : modifyColumns) { + sql.append(columnName + "=:" + columnName); + if (i < (int) modifyColumns.size()) { + sql.append(","); + } + i += 1; + } + + if (!conditionColumns.empty()) { + sql.append(" where 1 = 1"); + for (const auto& columnName : conditionColumns) { + sql.append(" and "); + sql.append(columnName + "=:" + columnName); + } + } + return sql; +} + +std::string SqliteStorage::CreateSelectPrepareSqlCmd(const DataType type) const +{ + auto it = dataTypeToSqlTable_.find(type); + if (it == dataTypeToSqlTable_.end()) { + return std::string(); + } + std::string sql = "select * from " + it->second.tableName_; + return sql; +} + +int SqliteStorage::CreatePermissionDefinitionTable() const +{ + auto it = dataTypeToSqlTable_.find(DataType::PERMISSION_DEF); + if (it == dataTypeToSqlTable_.end()) { + return FAILURE; + } + std::string sql = "create table if not exists "; + sql.append(it->second.tableName_ + " (") + .append(FIELD_PERMISSION_NAME + " text not null,") + .append(FIELD_BUNDLE_NAME + " text not null,") + .append(FIELD_GRANT_MODE + " integer not null,") + .append(FIELD_AVAILABLE_SCOPE + " integer not null,") + .append(FIELD_LABEL + " text not null,") + .append(FIELD_LABEL_ID + " integer not null,") + .append(FIELD_DESCRIPTION + " text not null,") + .append(FIELD_DESCRIPTION_ID + " integer not null,") + .append("primary key(" + FIELD_PERMISSION_NAME) + .append("))"); + return ExecuteSql(sql); +} + +int SqliteStorage::CreateSystemGrantedPermissionStateTable() const +{ + auto it = dataTypeToSqlTable_.find(DataType::PERMISSIONS_STAT_SYSTEM_GRANTED); + if (it == dataTypeToSqlTable_.end()) { + return FAILURE; + } + std::string sql = "create table if not exists "; + sql.append(it->second.tableName_ + " (") + .append(FIELD_BUNDLE_NAME + " text not null,") + .append(FIELD_PERMISSION_NAME + " text not null,") + .append(FIELD_GRANTED + " integer not null,") + .append(FIELD_FLAGS + " integer not null,") + .append("primary key(" + FIELD_BUNDLE_NAME) + .append("," + FIELD_PERMISSION_NAME) + .append("))"); + return ExecuteSql(sql); +} + +int SqliteStorage::CreateUserGrantedPermissionStateTable() const +{ + auto it = dataTypeToSqlTable_.find(DataType::PERMISSIONS_STAT_USER_GRANTED); + if (it == dataTypeToSqlTable_.end()) { + return FAILURE; + } + std::string sql = "create table if not exists "; + sql.append(it->second.tableName_ + " (") + .append(FIELD_BUNDLE_NAME + " text not null,") + .append(FIELD_PERMISSION_NAME + " text not null,") + .append(FIELD_USER_ID + " integer not null,") + .append(FIELD_GRANTED + " integer not null,") + .append(FIELD_FLAGS + " integer not null,") + .append("primary key(" + FIELD_BUNDLE_NAME) + .append("," + FIELD_PERMISSION_NAME) + .append("," + FIELD_USER_ID) + .append("))"); + return ExecuteSql(sql); +} +} // namespace Permission +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/sqlite_storage.h b/services/permission_standard/permissionmanagerservice/main/cpp/src/sqlite_storage.h new file mode 100644 index 0000000..cb3ea23 --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/sqlite_storage.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SQLITE_STORAGE_H +#define SQLITE_STORAGE_H + +#include "data_storage.h" +#include "sqlite_helper.h" +#include "field_const.h" + +#include "nocopyable.h" +#include "rwlock.h" + +namespace OHOS { +namespace Security { +namespace Permission { +class SqliteStorage : public DataStorage, public SqliteHelper { +public: + enum ExecuteResult { FAILURE = -1, SUCCESS }; + + struct SqliteTable { + public: + std::string tableName_; + std::vector tableColumnNames_; + }; + + static SqliteStorage& GetInstance(); + + ~SqliteStorage() override; + + int Add(const DataType type, const std::vector& values) override; + + int Remove(const DataType type, const GenericValues& conditions) override; + + int Modify(const DataType type, const GenericValues& modifyValues, const GenericValues& conditions) override; + + int Find(const DataType type, std::vector& results) override; + + int RefreshAll(const DataType type, const std::vector& values) override; + + void OnCreate() override; + void OnUpdate() override; + +private: + SqliteStorage(); + DISALLOW_COPY_AND_MOVE(SqliteStorage); + + std::map dataTypeToSqlTable_; + OHOS::Utils::RWLock rwLock_; + + int CreatePermissionDefinitionTable() const; + int CreateSystemGrantedPermissionStateTable() const; + int CreateUserGrantedPermissionStateTable() const; + + std::string CreateInsertPrepareSqlCmd(const DataType type) const; + std::string CreateDeletePrepareSqlCmd( + const DataType type, const std::vector& columnNames = std::vector()) const; + std::string CreateUpdatePrepareSqlCmd(const DataType type, const std::vector& modifyColumns, + const std::vector& conditionColumns) const; + std::string CreateSelectPrepareSqlCmd(const DataType type) const; + +private: + inline static const std::string PERMISSION_DEF_TABLE = "permission_definition_table"; + inline static const std::string SYS_GRANTED_PERMISSION_STATE_TABLE = "system_granted_permission_state_table"; + inline static const std::string USER_GRANTED_PERMISSION_STATE_TABLE = "user_granted_permission_state_table"; + inline static const std::string DATABASE_NAME = "permission.db"; + inline static const std::string DATABASE_PATH = "/data/system/"; + static const int DATABASE_VERSION = 1; +}; +} // namespace Permission +} // namespace Security +} // namespace OHOS + +#endif // SQLITE_STORAGE_H diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/statement.cpp b/services/permission_standard/permissionmanagerservice/main/cpp/src/statement.cpp new file mode 100644 index 0000000..4133603 --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/statement.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "statement.h" + +#include "permission_log.h" + +namespace OHOS { +namespace Security { +namespace Permission { +namespace { +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_PERMISSION, "Statement"}; +} + +Statement::Statement(sqlite3* db, const std::string& sql) : db_(db), sql_(sql) +{ + if (sqlite3_prepare_v2(db, sql.c_str(), sql.size(), &statement_, nullptr) != SQLITE_OK) { + PERMISSION_LOG_ERROR(LABEL, "Cannot prepare, errorMsg: %{public}s", sqlite3_errmsg(db_)); + } +} + +Statement::~Statement() +{ + sqlite3_finalize(statement_); + statement_ = nullptr; +} + +void Statement::Bind(const int index, const std::string& text) +{ + if (sqlite3_bind_text(statement_, index, text.c_str(), text.size(), SQLITE_TRANSIENT) != SQLITE_OK) { + PERMISSION_LOG_ERROR(LABEL, "Cannot bind string, errorMsg: %{public}s", sqlite3_errmsg(db_)); + } +} + +void Statement::Bind(const int index, int value) +{ + if (sqlite3_bind_int(statement_, index, value) != SQLITE_OK) { + PERMISSION_LOG_ERROR(LABEL, "Cannot bind int, errorMsg: %{public}s", sqlite3_errmsg(db_)); + } +} + +int Statement::GetColumnInt(const int column) const +{ + return sqlite3_column_int(statement_, column); +} + +std::string Statement::GetColumnString(const int column) const +{ + return std::string(reinterpret_cast(sqlite3_column_text(statement_, column))); +} + +std::string Statement::GetColumnName(const int column) const +{ + return sqlite3_column_name(statement_, column); +} + +Statement::State Statement::Step() +{ + int ret = sqlite3_step(statement_); + switch (ret) { + case SQLITE_ROW: + return Statement::State::ROW; + case SQLITE_DONE: + return Statement::State::DONE; + case SQLITE_BUSY: + return Statement::State::BUSY; + case SQLITE_MISUSE: + return Statement::State::MISUSE; + default: + return Statement::State::UNKNOWN; + } +} + +int Statement::GetParameterIndex(const std::string& name) const +{ + return sqlite3_bind_parameter_index(statement_, name.c_str()); +} + +void Statement::Bind(const std::string& tableColumnName, const VariantValue& value) +{ + int index = GetParameterIndex(":" + tableColumnName); + if (value.GetType() == ValueType::TYPE_STRING) { + Bind(index, value.GetString()); + } else if (value.GetType() == ValueType::TYPE_INT) { + Bind(index, value.GetInt()); + } +} + +int Statement::Reset() +{ + return sqlite3_reset(statement_); +} + +int Statement::GetColumnCount() const +{ + return sqlite3_column_count(statement_); +} + +VariantValue Statement::GetValue(const int column) const +{ + int type = sqlite3_column_type(statement_, column); + switch (type) { + case SQLITE_INTEGER: + return VariantValue(GetColumnInt(column)); + case SQLITE_TEXT: + return VariantValue(GetColumnString(column)); + default: + return VariantValue(); + } +} +} // namespace Permission +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/statement.h b/services/permission_standard/permissionmanagerservice/main/cpp/src/statement.h new file mode 100755 index 0000000..a6ec3d8 --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/statement.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STATEMENT_H +#define STATEMENT_H + +#include + +#include "variant_value.h" + +#include "sqlite3sym.h" + +namespace OHOS { +namespace Security { +namespace Permission { +class Statement final { +public: + enum State { BUSY, ROW, DONE, MISUSE, UNKNOWN }; + + Statement(sqlite3* db, const std::string& sql); + virtual ~Statement(); + + void Bind(const int index, const std::string& text); + void Bind(const int index, int value); + void Bind(const std::string& tableColumnName, const VariantValue& value); + + State Step(); + int Reset(); + + std::string GetColumnString(const int column) const; + int GetColumnInt(const int column) const; + std::string GetColumnName(const int column) const; + int GetParameterIndex(const std::string& name) const; + int GetColumnCount() const; + VariantValue GetValue(const int column) const; + +private: + sqlite3* db_; + sqlite3_stmt* statement_; + const std::string sql_; +}; +} // namespace Permission +} // namespace Security +} // namespace OHOS +#endif // STATEMENT_H diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/variant_value.cpp b/services/permission_standard/permissionmanagerservice/main/cpp/src/variant_value.cpp new file mode 100644 index 0000000..70b7d58 --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/variant_value.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "variant_value.h" + +namespace OHOS { +namespace Security { +namespace Permission { +VariantValue::VariantValue() : type_(ValueType::TYPE_NULL) +{} + +VariantValue::~VariantValue() +{} + +VariantValue::VariantValue(int value) : type_(ValueType::TYPE_INT) +{ + value_ = value; +} + +VariantValue::VariantValue(const std::string& value) : type_(ValueType::TYPE_STRING) +{ + value_ = value; +} + +ValueType VariantValue::GetType() const +{ + return type_; +} + +int VariantValue::GetInt() const +{ + if (type_ != ValueType::TYPE_INT) { + return DEFAULT_VALUE; + } + + return std::get(value_); +} + +std::string VariantValue::GetString() const +{ + if (type_ != ValueType::TYPE_STRING) { + return std::string(); + } + + return std::get(value_); +} +} // namespace Permission +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/services/permission_standard/permissionmanagerservice/main/cpp/src/variant_value.h b/services/permission_standard/permissionmanagerservice/main/cpp/src/variant_value.h new file mode 100755 index 0000000..30e265a --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/cpp/src/variant_value.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VARIANT_VALUE_H +#define VARIANT_VALUE_H + +#include +#include + +namespace OHOS { +namespace Security { +namespace Permission { +enum class ValueType { + TYPE_NULL, + TYPE_INT, + TYPE_STRING, +}; + +class VariantValue final { +public: + VariantValue(); + virtual ~VariantValue(); + + explicit VariantValue(int value); + explicit VariantValue(const std::string& value); + + ValueType GetType() const; + int GetInt() const; + std::string GetString() const; + + static const int DEFAULT_VALUE = -1; + +private: + ValueType type_; + std::variant value_; +}; +} // namespace Permission +} // namespace Security +} // namespace OHOS +#endif // VARIANT_VALUE_H diff --git a/services/permission_standard/permissionmanagerservice/main/sa_profile/3501.xml b/services/permission_standard/permissionmanagerservice/main/sa_profile/3501.xml new file mode 100755 index 0000000..c3af26d --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/sa_profile/3501.xml @@ -0,0 +1,24 @@ + + + + foundation + + 3501 + libpermission_manager_service_standard.z.so + true + false + 1 + + \ No newline at end of file diff --git a/services/permission_standard/permissionmanagerservice/main/sa_profile/BUILD.gn b/services/permission_standard/permissionmanagerservice/main/sa_profile/BUILD.gn new file mode 100644 index 0000000..6b2918c --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/main/sa_profile/BUILD.gn @@ -0,0 +1,20 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos/sa_profile/sa_profile.gni") + +ohos_sa_profile("permission_sa_profile_standard") { + part_name = "permission_standard" + + sources = [ "3501.xml" ] +} diff --git a/services/permission_standard/permissionmanagerservice/test/BUILD.gn b/services/permission_standard/permissionmanagerservice/test/BUILD.gn new file mode 100644 index 0000000..16ecdcd --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/test/BUILD.gn @@ -0,0 +1,48 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") + +ohos_unittest("libpermission_manager_service_standard_test") { + subsystem_name = "security" + part_name = "permission_standard" + module_out_path = part_name + "/" + part_name + + include_dirs = [ + "//utils/native/base/include", + "//base/security/permission/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/include/permission", + "//base/security/permission/services/permission_standard/permissionmanagerservice/main/cpp/src/", + ] + + sources = [ + "unittest/cpp/src/permission_definition_manager_test.cpp", + "unittest/cpp/src/permission_state_manager_test.cpp", + ] + + cflags_cc = [ "-DHILOG_ENABLE" ] + + deps = [ + "//base/security/permission/frameworks/permission_standard/permissioncommunicationadapter:permission_standard_communication_adapter_cxx", + "//base/security/permission/frameworks/permission_standard/permissioninfrastructure:permission_standard_infrastructure_cxx", + "//base/security/permission/services/permission_standard/permissionmanagerservice:permission_manager_service_standard", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] +} + +group("unittest") { + testonly = true + deps = [ ":libpermission_manager_service_standard_test" ] +} diff --git a/services/permission_standard/permissionmanagerservice/test/unittest/cpp/src/permission_definition_manager_test.cpp b/services/permission_standard/permissionmanagerservice/test/unittest/cpp/src/permission_definition_manager_test.cpp new file mode 100755 index 0000000..29d6d6d --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/test/unittest/cpp/src/permission_definition_manager_test.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "permission_definition_manager_test.h" + +#include + +#include "permission_definition_manager.h" +#include "permission.h" +#include "test_const.h" + +using namespace testing::ext; +using namespace OHOS::Security::Permission; + +void PermissionDefinitionManagerTest::SetUpTestCase() +{} + +void PermissionDefinitionManagerTest::TearDownTestCase() +{} + +void PermissionDefinitionManagerTest::SetUp() +{} + +void PermissionDefinitionManagerTest::TearDown() +{ + PermissionDefinitionManager::GetInstance().RemoveDefPermissions(TEST_BUNDLE_NAME); +} + +HWTEST_F(PermissionDefinitionManagerTest, AddDefPermissions001, TestSize.Level1) +{ + vector defs; + PermissionDefParcel permissionDefParcel; + permissionDefParcel.permissionDef.permissionName = TEST_PERMISSION_NAME_ALPHA; + permissionDefParcel.permissionDef.bundleName = TEST_BUNDLE_NAME; + permissionDefParcel.permissionDef.grantMode = GrantMode::SYSTEM_GRANT; + permissionDefParcel.permissionDef.availableScope = AvailableScope::AVAILABLE_SCOPE_ALL; + permissionDefParcel.permissionDef.label = TEST_LABEL; + permissionDefParcel.permissionDef.labelId = TEST_LABEL_ID; + permissionDefParcel.permissionDef.description = TEST_DESCRIPTION; + permissionDefParcel.permissionDef.descriptionId = TEST_DESCRIPTION_ID; + defs.emplace_back(permissionDefParcel); + PermissionDefinitionManager::GetInstance().AddDefPermissions(defs); + + PermissionDefParcel result; + PermissionDefinitionManager::GetInstance().GetDefPermission(TEST_PERMISSION_NAME_ALPHA, result); + ASSERT_EQ(TEST_PERMISSION_NAME_ALPHA, result.permissionDef.permissionName); + ASSERT_EQ(TEST_BUNDLE_NAME, result.permissionDef.bundleName); + ASSERT_EQ(GrantMode::SYSTEM_GRANT, result.permissionDef.grantMode); + ASSERT_EQ(AvailableScope::AVAILABLE_SCOPE_ALL, result.permissionDef.availableScope); + ASSERT_EQ(TEST_LABEL, result.permissionDef.label); + ASSERT_EQ(TEST_LABEL_ID, result.permissionDef.labelId); + ASSERT_EQ(TEST_DESCRIPTION, result.permissionDef.description); + ASSERT_EQ(TEST_DESCRIPTION_ID, result.permissionDef.descriptionId); +} + +HWTEST_F(PermissionDefinitionManagerTest, RemoveDefPermissions001, TestSize.Level1) +{ + vector defs; + PermissionDefParcel permissionDefParcel; + permissionDefParcel.permissionDef.permissionName = TEST_PERMISSION_NAME_ALPHA; + permissionDefParcel.permissionDef.bundleName = TEST_BUNDLE_NAME; + permissionDefParcel.permissionDef.grantMode = GrantMode::SYSTEM_GRANT; + permissionDefParcel.permissionDef.availableScope = AVAILABLE_SCOPE_SIGNATURE; + defs.emplace_back(permissionDefParcel); + PermissionDefinitionManager::GetInstance().AddDefPermissions(defs); + + PermissionDefParcel result; + int ret = PermissionDefinitionManager::GetInstance().GetDefPermission(TEST_PERMISSION_NAME_ALPHA, result); + ASSERT_EQ(RET_SUCCESS, ret); + + PermissionDefinitionManager::GetInstance().RemoveDefPermissions(TEST_BUNDLE_NAME); + + PermissionDefParcel defParcel; + ret = PermissionDefinitionManager::GetInstance().GetDefPermission(TEST_PERMISSION_NAME_ALPHA, defParcel); + ASSERT_EQ(RET_FAILED, ret); +} diff --git a/services/permission_standard/permissionmanagerservice/test/unittest/cpp/src/permission_definition_manager_test.h b/services/permission_standard/permissionmanagerservice/test/unittest/cpp/src/permission_definition_manager_test.h new file mode 100644 index 0000000..3eccbdc --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/test/unittest/cpp/src/permission_definition_manager_test.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PERMISSION_DEFINITION_MANAGER_TEST_H +#define PERMISSION_DEFINITION_MANAGER_TEST_H + +#include + +namespace OHOS { +namespace Security { +namespace Permission { +class PermissionDefinitionManagerTest : public testing::Test { +public: + static void SetUpTestCase(); + + static void TearDownTestCase(); + + void SetUp(); + + void TearDown(); +}; +} // namespace Permission +} // namespace Security +} // namespace OHOS +#endif // PERMISSION_DEFINITION_MANAGER_TEST_H diff --git a/services/permission_standard/permissionmanagerservice/test/unittest/cpp/src/permission_state_manager_test.cpp b/services/permission_standard/permissionmanagerservice/test/unittest/cpp/src/permission_state_manager_test.cpp new file mode 100644 index 0000000..f273d07 --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/test/unittest/cpp/src/permission_state_manager_test.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "permission_state_manager_test.h" + +#include + +#include "permission_state_manager.h" +#include "test_const.h" + +using namespace testing::ext; +using namespace OHOS::Security::Permission; + +void PermissionStateManagerTest::SetUpTestCase() +{} + +void PermissionStateManagerTest::TearDownTestCase() +{} + +void PermissionStateManagerTest::SetUp() +{} + +void PermissionStateManagerTest::TearDown() +{} + +HWTEST_F(PermissionStateManagerTest, AddUserGrantedReqPermissions001, TestSize.Level1) +{ + std::vector permList; + permList.emplace_back(TEST_PERMISSION_NAME_ALPHA); + PermissionStateManager::GetInstance().AddUserGrantedReqPermissions(TEST_BUNDLE_NAME, permList, 0); + PermissionStateManager::GetInstance().AddUserGrantedReqPermissions(TEST_BUNDLE_NAME, permList, TEST_SUB_USER_ID); +} \ No newline at end of file diff --git a/services/permission_standard/permissionmanagerservice/test/unittest/cpp/src/permission_state_manager_test.h b/services/permission_standard/permissionmanagerservice/test/unittest/cpp/src/permission_state_manager_test.h new file mode 100644 index 0000000..f522bf3 --- /dev/null +++ b/services/permission_standard/permissionmanagerservice/test/unittest/cpp/src/permission_state_manager_test.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PERMISSION_STATE_MANAGER_TEST_H +#define PERMISSION_STATE_MANAGER_TEST_H + +#include + +namespace OHOS { +namespace Security { +namespace Permission { +class PermissionStateManagerTest : public testing::Test { +public: + static void SetUpTestCase(); + + static void TearDownTestCase(); + + void SetUp(); + + void TearDown(); +}; +} // namespace Permission +} // namespace Security +} // namespace OHOS +#endif // PERMISSION_STATE_MANAGER_TEST_H