1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "short_grant_manager.h"
17 
18 #include <chrono>
19 #include <iostream>
20 #include <thread>
21 
22 #include "access_token.h"
23 #include "access_token_error.h"
24 #include "permission_manager.h"
25 
26 namespace OHOS {
27 namespace Security {
28 namespace AccessToken {
29 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_ACCESSTOKEN, "ShortGrantManager"};
30 std::recursive_mutex g_instanceMutex;
31 static constexpr int32_t DEFAULT_MAX_TIME_MILLISECONDS = 30 * 60; // 30 minutes
32 static constexpr int32_t DEFAULT_MAX_ONCE_TIME_MILLISECONDS = 5 * 60; // 5 minutes
33 static const std::string TASK_NAME_SHORT_GRANT_PERMISSION = "atm_permission_manager_short_grant";
34 static const std::vector<std::string> g_shortGrantPermission = {
35     "ohos.permission.SHORT_TERM_WRITE_IMAGEVIDEO"
36 };
37 
GetInstance()38 ShortGrantManager& ShortGrantManager::GetInstance()
39 {
40     static ShortGrantManager* instance = nullptr;
41     if (instance == nullptr) {
42         std::lock_guard<std::recursive_mutex> lock(g_instanceMutex);
43         if (instance == nullptr) {
44             instance = new ShortGrantManager();
45         }
46     }
47     return *instance;
48 }
49 
InitEventHandler(const std::shared_ptr<AccessEventHandler> & eventHandler)50 void ShortGrantManager::InitEventHandler(const std::shared_ptr<AccessEventHandler>& eventHandler)
51 {
52     eventHandler_ = eventHandler;
53 }
54 
CancelTaskOfPermissionRevoking(const std::string & taskName)55 bool ShortGrantManager::CancelTaskOfPermissionRevoking(const std::string& taskName)
56 {
57 #ifdef EVENTHANDLER_ENABLE
58     if (eventHandler_ == nullptr) {
59         ACCESSTOKEN_LOG_ERROR(LABEL, "Fail to get EventHandler");
60         return false;
61     }
62 
63     ACCESSTOKEN_LOG_INFO(LABEL, "Revoke permission task name:%{public}s", taskName.c_str());
64     eventHandler_->ProxyRemoveTask(taskName);
65     return true;
66 #else
67     ACCESSTOKEN_LOG_WARN(LABEL, "EventHandler is not existed");
68     return false;
69 #endif
70 }
71 
RefreshPermission(AccessTokenID tokenID,const std::string & permission,uint32_t onceTime)72 int ShortGrantManager::RefreshPermission(AccessTokenID tokenID, const std::string& permission, uint32_t onceTime)
73 {
74     if (tokenID == 0 || onceTime == 0 || onceTime > DEFAULT_MAX_ONCE_TIME_MILLISECONDS || onceTime > maxTime_) {
75         ACCESSTOKEN_LOG_ERROR(LABEL,
76             "Input invalid, tokenID is: %{public}d, onceTime is %{public}u!", tokenID, onceTime);
77         return AccessTokenError::ERR_PARAM_INVALID;
78     }
79     std::string taskName = TASK_NAME_SHORT_GRANT_PERMISSION + std::to_string(tokenID) + permission;
80     std::unique_lock<std::mutex> lck(shortGrantDataMutex_);
81 
82     auto iter = std::find_if(
83         shortGrantData_.begin(), shortGrantData_.end(), [tokenID, permission](const PermTimerData& data) {
84         return data.tokenID == tokenID && data.permissionName == permission;
85     });
86     if (iter == shortGrantData_.end()) {
87         auto iterator = std::find(g_shortGrantPermission.begin(), g_shortGrantPermission.end(), permission);
88         if (iterator == g_shortGrantPermission.end()) {
89             ACCESSTOKEN_LOG_ERROR(LABEL, "Permission is not available to short grant: %{public}s!", permission.c_str());
90             return AccessTokenError::ERR_PARAM_INVALID;
91         }
92         PermTimerData data;
93         data.tokenID = tokenID;
94         data.permissionName = permission;
95         data.firstGrantTimes = GetCurrentTime();
96         data.revokeTimes = data.firstGrantTimes + onceTime;
97         int32_t ret = PermissionManager::GetInstance().GrantPermission(tokenID, permission, PERMISSION_USER_FIXED);
98         if (ret != RET_SUCCESS) {
99             ACCESSTOKEN_LOG_ERROR(LABEL, "GrantPermission failed result %{public}d", ret);
100             return ret;
101         }
102         shortGrantData_.emplace_back(data);
103         ShortGrantManager::GetInstance().ScheduleRevokeTask(tokenID, permission, taskName, onceTime);
104         return RET_SUCCESS;
105     }
106 
107     uint32_t maxRemainedTime = maxTime_ > (GetCurrentTime() - iter->firstGrantTimes) ?
108         (maxTime_ - (GetCurrentTime() - iter->firstGrantTimes)) : 0;
109     uint32_t currRemainedTime = iter->revokeTimes > GetCurrentTime() ?
110         (iter->revokeTimes - GetCurrentTime()) : 0;
111     uint32_t cancelTimes = (maxRemainedTime > onceTime) ? onceTime : maxRemainedTime;
112     if (cancelTimes > currRemainedTime) {
113         iter->revokeTimes = GetCurrentTime() + cancelTimes;
114         ShortGrantManager::GetInstance().CancelTaskOfPermissionRevoking(taskName);
115         int32_t ret = PermissionManager::GetInstance().GrantPermission(tokenID, permission, PERMISSION_USER_FIXED);
116         if (ret != RET_SUCCESS) {
117             ACCESSTOKEN_LOG_ERROR(LABEL, "GrantPermission failed result %{public}d", ret);
118             return ret;
119         }
120         ShortGrantManager::GetInstance().ScheduleRevokeTask(iter->tokenID, iter->permissionName, taskName, cancelTimes);
121     }
122     return RET_SUCCESS;
123 }
124 
ClearShortPermissionData(AccessTokenID tokenID,const std::string & permission)125 void ShortGrantManager::ClearShortPermissionData(AccessTokenID tokenID, const std::string& permission)
126 {
127     std::unique_lock<std::mutex> lck(shortGrantDataMutex_);
128     auto item = shortGrantData_.begin();
129     while (item != shortGrantData_.end()) {
130         if (item->tokenID == tokenID && item->permissionName == permission) {
131             // revoke without kill the app
132             if (PermissionManager::GetInstance().UpdatePermission(
133                 tokenID, permission, false, PERMISSION_USER_FIXED, false) != RET_SUCCESS) {
134                 ACCESSTOKEN_LOG_ERROR(LABEL, "TokenID:%{public}d revoke permission:%{public}s failed!",
135                     tokenID, permission.c_str());
136                 return;
137             }
138             // clear data
139             shortGrantData_.erase(item);
140             break;
141         } else {
142             ++item;
143         }
144     }
145 }
146 
ScheduleRevokeTask(AccessTokenID tokenID,const std::string & permission,const std::string & taskName,uint32_t cancelTimes)147 void ShortGrantManager::ScheduleRevokeTask(AccessTokenID tokenID, const std::string& permission,
148     const std::string& taskName, uint32_t cancelTimes)
149 {
150 #ifdef EVENTHANDLER_ENABLE
151     if (eventHandler_ == nullptr) {
152         ACCESSTOKEN_LOG_ERROR(LABEL, "Fail to get EventHandler");
153         return;
154     }
155 
156     ACCESSTOKEN_LOG_INFO(LABEL, "Add permission task name:%{public}s", taskName.c_str());
157 
158     std::function<void()> delayed = ([tokenID, permission]() {
159         ShortGrantManager::GetInstance().ClearShortPermissionData(tokenID, permission);
160         ACCESSTOKEN_LOG_INFO(LABEL,
161             "Token: %{public}d, permission: %{public}s, delay revoke permission end.", tokenID, permission.c_str());
162     });
163     eventHandler_->ProxyPostTask(delayed, taskName, cancelTimes * 1000); // 1000 means to ms
164     return;
165 #else
166     ACCESSTOKEN_LOG_WARN(LABEL, "eventHandler is not existed");
167     return;
168 #endif
169 }
170 
GetCurrentTime()171 uint32_t ShortGrantManager::GetCurrentTime()
172 {
173     return static_cast<uint32_t>(std::chrono::system_clock::now().time_since_epoch() / std::chrono::seconds(1));
174 }
175 
IsShortGrantPermission(const std::string & permissionName)176 bool ShortGrantManager::IsShortGrantPermission(const std::string& permissionName)
177 {
178     auto it = find(g_shortGrantPermission.begin(), g_shortGrantPermission.end(), permissionName);
179     if (it == g_shortGrantPermission.end()) {
180         return false;
181     }
182     return true;
183 }
184 
ShortGrantManager()185 ShortGrantManager::ShortGrantManager() : maxTime_(DEFAULT_MAX_TIME_MILLISECONDS)
186 {}
187 } // namespace AccessToken
188 } // namespace Security
189 } // namespace OHOS