1 /*
2 * Copyright (c) 2022 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 "co_auth_service.h"
17
18 #include <cinttypes>
19 #include <thread>
20
21 #include "string_ex.h"
22
23 #include "device_manager_util.h"
24 #include "driver_state_manager.h"
25 #include "executor_messenger_service.h"
26 #include "hdi_message_callback_service.h"
27 #include "hdi_wrapper.h"
28 #include "hisysevent_adapter.h"
29 #include "iam_logger.h"
30 #include "iam_ptr.h"
31 #include "iam_para2str.h"
32 #include "ipc_common.h"
33 #include "iam_check.h"
34 #include "iam_time.h"
35 #include "iam_common_defines.h"
36 #include "ipc_skeleton.h"
37 #include "load_mode_handler.h"
38 #include "parameter.h"
39 #include "relative_timer.h"
40 #include "remote_connect_manager.h"
41 #include "resource_node_pool.h"
42 #include "service_init_manager.h"
43 #include "system_param_manager.h"
44 #include "template_cache_manager.h"
45 #include "remote_msg_util.h"
46 #include "xcollie_helper.h"
47
48 #define LOG_TAG "USER_AUTH_SA"
49
50 namespace OHOS {
51 namespace UserIam {
52 namespace UserAuth {
53 namespace {
54 const bool REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility(CoAuthService::GetInstance().get());
55 } // namespace
56
57 constexpr int32_t USERIAM_IPC_THREAD_NUM = 4;
58 std::shared_ptr<CoAuthService> CoAuthService::instance_ = nullptr;
59
GetInstance()60 std::shared_ptr<CoAuthService> CoAuthService::GetInstance()
61 {
62 static std::recursive_mutex mutex;
63 if (instance_ == nullptr) {
64 std::lock_guard<std::recursive_mutex> guard(mutex);
65 if (instance_ == nullptr) {
66 instance_ = Common::MakeShared<CoAuthService>();
67 if (instance_ == nullptr) {
68 IAM_LOGE("make share failed");
69 }
70 }
71 }
72 return instance_;
73 }
74
CoAuthService()75 CoAuthService::CoAuthService() : SystemAbility(SUBSYS_USERIAM_SYS_ABILITY_AUTHEXECUTORMGR, true)
76 {
77 IAM_LOGI("CoAuthService init");
78 DriverStateManager::GetInstance().RegisterDriverStartCallback([]() {
79 std::shared_ptr<CoAuthService> instance = CoAuthService::GetInstance();
80 if (instance == nullptr) {
81 IAM_LOGE("CoAuthService instance is null");
82 return;
83 }
84 instance->OnDriverStart();
85 });
86 DriverStateManager::GetInstance().RegisterDriverStopCallback([]() {
87 std::shared_ptr<CoAuthService> instance = CoAuthService::GetInstance();
88 if (instance == nullptr) {
89 IAM_LOGE("CoAuthService instance is null");
90 return;
91 }
92 instance->OnDriverStop();
93 });
94 }
95
OnStart()96 void CoAuthService::OnStart()
97 {
98 std::lock_guard<std::recursive_mutex> guard(mutex_);
99 IAM_LOGI("Sa start CoAuthService");
100 IPCSkeleton::SetMaxWorkThreadNum(USERIAM_IPC_THREAD_NUM);
101 if (!Publish(this)) {
102 IAM_LOGE("Failed to publish service");
103 return;
104 }
105
106 ServiceInitManager::GetInstance().OnCoAuthServiceStart();
107 }
108
OnStop()109 void CoAuthService::OnStop()
110 {
111 IAM_LOGI("Sa stop CoAuthService");
112 ServiceInitManager::GetInstance().OnCoAuthServiceStop();
113 }
114
SetIsReady(bool isReady)115 void CoAuthService::SetIsReady(bool isReady)
116 {
117 std::lock_guard<std::recursive_mutex> guard(mutex_);
118 isReady_ = isReady;
119 IAM_LOGI("Set isReady %{public}d", isReady);
120 }
121
SetAccessTokenReady(bool isReady)122 void CoAuthService::SetAccessTokenReady(bool isReady)
123 {
124 std::lock_guard<std::recursive_mutex> guard(mutex_);
125 accessTokenReady_ = isReady;
126 IAM_LOGI("Set accesstoken ready %{public}d", accessTokenReady_);
127 }
128
IsFwkReady()129 bool CoAuthService::IsFwkReady()
130 {
131 std::lock_guard<std::recursive_mutex> guard(mutex_);
132 return isReady_ && accessTokenReady_;
133 }
134
AddExecutorDeathRecipient(uint64_t executorIndex,AuthType authType,ExecutorRole role,std::shared_ptr<ExecutorCallbackInterface> callback)135 void CoAuthService::AddExecutorDeathRecipient(uint64_t executorIndex, AuthType authType, ExecutorRole role,
136 std::shared_ptr<ExecutorCallbackInterface> callback)
137 {
138 IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
139 auto obj = callback->AsObject();
140 IF_FALSE_LOGE_AND_RETURN(obj != nullptr);
141
142 obj->AddDeathRecipient(new (std::nothrow) IpcCommon::PeerDeathRecipient([executorIndex, authType, role]() {
143 IAM_LOGE("executorCallback is down");
144 auto weakNode = ResourceNodePool::Instance().Select(executorIndex);
145 auto sharedNode = weakNode.lock();
146 if (sharedNode != nullptr) {
147 auto result = ResourceNodePool::Instance().Delete(executorIndex);
148 IAM_LOGI("delete executor %{public}s, executorIndex is ****%{public}hx authType is %{public}d "
149 "executorRole is %{public}d", (result ? "succ" : "failed"), static_cast<uint16_t>(executorIndex),
150 sharedNode->GetAuthType(), sharedNode->GetExecutorRole());
151 }
152 LoadModeHandler::GetInstance().OnExecutorUnregistered(authType, role);
153 std::string executorDesc = "executor, type " + std::to_string(authType);
154 UserIam::UserAuth::ReportSystemFault(Common::GetNowTimeString(), executorDesc);
155 IAM_LOGI("executorCallback is down processed");
156 }));
157 }
158
ExecutorRegister(const ExecutorRegisterInfo & info,sptr<ExecutorCallbackInterface> & callback)159 uint64_t CoAuthService::ExecutorRegister(const ExecutorRegisterInfo &info, sptr<ExecutorCallbackInterface> &callback)
160 {
161 IAM_LOGI("register resource node begin");
162 Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
163 if (callback == nullptr) {
164 IAM_LOGE("executor callback is nullptr");
165 return INVALID_EXECUTOR_INDEX;
166 }
167
168 std::lock_guard<std::recursive_mutex> guard(mutex_);
169 if (!IsFwkReady()) {
170 IAM_LOGE("framework is not ready");
171 return INVALID_EXECUTOR_INDEX;
172 }
173
174 if (!IpcCommon::CheckPermission(*this, ACCESS_AUTH_RESPOOL)) {
175 IAM_LOGE("failed to check permission");
176 return INVALID_EXECUTOR_INDEX;
177 }
178
179 std::vector<uint64_t> templateIdList;
180 std::vector<uint8_t> fwkPublicKey;
181 auto executorCallback = Common::SptrToStdSharedPtr<ExecutorCallbackInterface>(callback);
182 auto resourceNode = ResourceNode::MakeNewResource(info, executorCallback, templateIdList, fwkPublicKey);
183 if (resourceNode == nullptr) {
184 IAM_LOGE("create resource node failed");
185 return INVALID_EXECUTOR_INDEX;
186 }
187 if (!ResourceNodePool::Instance().Insert(resourceNode)) {
188 IAM_LOGE("insert resource node failed");
189 return INVALID_EXECUTOR_INDEX;
190 }
191
192 uint64_t executorIndex = resourceNode->GetExecutorIndex();
193 auto handler = ThreadHandler::GetSingleThreadInstance();
194 std::weak_ptr<ResourceNode> weakNode = resourceNode;
195 IF_FALSE_LOGE_AND_RETURN_VAL(handler != nullptr, GENERAL_ERROR);
196 handler->PostTask([executorCallback, fwkPublicKey, templateIdList, weakNode, executorIndex]() {
197 auto resourceNode = weakNode.lock();
198 IF_FALSE_LOGE_AND_RETURN(resourceNode != nullptr);
199 sptr<ExecutorMessengerInterface> messenger = ExecutorMessengerService::GetInstance();
200 executorCallback->OnMessengerReady(messenger, fwkPublicKey, templateIdList);
201 IAM_LOGI("register successful, executorType is %{public}d, executorRole is %{public}d, "
202 "executorIndex is ****%{public}hx",
203 resourceNode->GetAuthType(), resourceNode->GetExecutorRole(), static_cast<uint16_t>(executorIndex));
204 LoadModeHandler::GetInstance().OnExecutorRegistered(resourceNode->GetAuthType(),
205 resourceNode->GetExecutorRole());
206 AddExecutorDeathRecipient(executorIndex, resourceNode->GetAuthType(), resourceNode->GetExecutorRole(),
207 executorCallback);
208 IAM_LOGI("update template cache after register success");
209 TemplateCacheManager::GetInstance().UpdateTemplateCache(resourceNode->GetAuthType());
210 });
211 return executorIndex;
212 }
213
ExecutorUnregister(uint64_t executorIndex)214 void CoAuthService::ExecutorUnregister(uint64_t executorIndex)
215 {
216 IAM_LOGI("delete resource node begin");
217 Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
218 std::lock_guard<std::recursive_mutex> guard(mutex_);
219 if (!IsFwkReady()) {
220 IAM_LOGE("framework is not ready");
221 return;
222 }
223
224 if (!IpcCommon::CheckPermission(*this, ACCESS_AUTH_RESPOOL)) {
225 IAM_LOGE("failed to check permission");
226 return;
227 }
228
229 {
230 auto resourceNode = ResourceNodePool::Instance().Select(executorIndex).lock();
231 IF_FALSE_LOGE_AND_RETURN(resourceNode != nullptr);
232 LoadModeHandler::GetInstance().OnExecutorUnregistered(resourceNode->GetAuthType(),
233 resourceNode->GetExecutorRole());
234 }
235
236 if (!ResourceNodePool::Instance().Delete(executorIndex)) {
237 IAM_LOGE("delete resource node failed");
238 return;
239 }
240 IAM_LOGI("delete resource node success, executorIndex is ****%{public}hx", static_cast<uint16_t>(executorIndex));
241 }
242
OnDriverStart()243 void CoAuthService::OnDriverStart()
244 {
245 std::lock_guard<std::recursive_mutex> guard(mutex_);
246 IAM_LOGI("process driver start begin");
247 if (isReady_) {
248 IAM_LOGI("already ready");
249 return;
250 }
251 std::string localUdid;
252 bool getLocalUdidRet = DeviceManagerUtil::GetInstance().GetLocalDeviceUdid(localUdid);
253 IF_FALSE_LOGE_AND_RETURN(getLocalUdidRet);
254 auto service = HdiWrapper::GetHdiInstance();
255 IF_FALSE_LOGE_AND_RETURN(service != nullptr);
256 int32_t initRet = service->Init(localUdid);
257 IF_FALSE_LOGE_AND_RETURN(initRet == HDF_SUCCESS);
258 auto callbackService = HdiMessageCallbackService::GetInstance();
259 IF_FALSE_LOGE_AND_RETURN(callbackService != nullptr);
260 callbackService->OnHdiConnect();
261 SetIsReady(true);
262 NotifyFwkReady();
263 IAM_LOGI("process driver start success");
264 }
265
OnDriverStop()266 void CoAuthService::OnDriverStop()
267 {
268 std::lock_guard<std::recursive_mutex> guard(mutex_);
269 IAM_LOGE("process driver stop begin");
270 if (isReady_) {
271 IAM_LOGI("service is ready, clear status");
272 ResourceNodePool::Instance().DeleteAll();
273 UserIam::UserAuth::ReportSystemFault(Common::GetNowTimeString(), "user_auth_hdi host");
274 SetIsReady(false);
275 }
276 IAM_LOGI("process driver stop success");
277 }
278
Dump(int fd,const std::vector<std::u16string> & args)279 int CoAuthService::Dump(int fd, const std::vector<std::u16string> &args)
280 {
281 IAM_LOGI("start");
282 if (fd < 0) {
283 IAM_LOGE("invalid parameters");
284 return INVALID_PARAMETERS;
285 }
286 std::string arg0 = (args.empty() ? "" : Str16ToStr8(args[0]));
287 if (arg0.empty() || arg0.compare("-h") == 0) {
288 dprintf(fd, "Usage:\n");
289 dprintf(fd, " -h: command help.\n");
290 dprintf(fd, " -l: resource pool dump.\n");
291 return SUCCESS;
292 }
293 if (arg0.compare("-l") == 0) {
294 ResourceNodePool::Instance().Enumerate([fd](const std::weak_ptr<ResourceNode> &node) {
295 auto nodeTmp = node.lock();
296 if (nodeTmp != nullptr) {
297 dprintf(fd, "ExecutorIndex is: %" PRIx64 ".\n", nodeTmp->GetExecutorIndex());
298 dprintf(fd, "ExecutorType is: %s.\n", Common::AuthTypeToStr(nodeTmp->GetAuthType()));
299 dprintf(fd, "ExecutorRole is: %s.\n", Common::ExecutorRoleToStr(nodeTmp->GetExecutorRole()));
300 }
301 });
302 return SUCCESS;
303 }
304 IAM_LOGE("invalid option");
305 dprintf(fd, "Invalid option\n");
306 return GENERAL_ERROR;
307 }
308
RegisterAccessTokenListener()309 ResultCode CoAuthService::RegisterAccessTokenListener()
310 {
311 IAM_LOGD("start.");
312 std::lock_guard<std::recursive_mutex> lock(mutex_);
313 if (accessTokenListener_ != nullptr) {
314 IAM_LOGI("accessTokenListener_ is not nullptr.");
315 return SUCCESS;
316 }
317
318 accessTokenListener_ = SystemAbilityListener::Subscribe("accesstoken_service", ACCESS_TOKEN_MANAGER_SERVICE_ID,
319 []() {
320 auto instance = CoAuthService::GetInstance();
321 if (instance == nullptr) {
322 IAM_LOGE("CoAuthService instance is nullptr.");
323 return;
324 }
325 instance->SetAccessTokenReady(true);
326 instance->NotifyFwkReady();
327 },
328 nullptr);
329 if (accessTokenListener_ == nullptr) {
330 IAM_LOGE("accessTokenListener_ is nullptr.");
331 return GENERAL_ERROR;
332 }
333
334 IAM_LOGI("RegisterAccessTokenListener success.");
335 return SUCCESS;
336 }
337
UnRegisterAccessTokenListener()338 ResultCode CoAuthService::UnRegisterAccessTokenListener()
339 {
340 IAM_LOGD("start.");
341 std::lock_guard<std::recursive_mutex> lock(mutex_);
342 if (accessTokenListener_ == nullptr) {
343 IAM_LOGI("accessTokenListener_ is nullptr.");
344 return SUCCESS;
345 }
346
347 int32_t ret = SystemAbilityListener::UnSubscribe(ACCESS_TOKEN_MANAGER_SERVICE_ID, accessTokenListener_);
348 if (ret != SUCCESS) {
349 IAM_LOGE("UnSubscribe service fail.");
350 return GENERAL_ERROR;
351 }
352
353 accessTokenListener_ = nullptr;
354 IAM_LOGI("UnRegisterAccessTokenListener success.");
355 return SUCCESS;
356 }
357
NotifyFwkReady()358 void CoAuthService::NotifyFwkReady()
359 {
360 IAM_LOGD("start.");
361 if (IsFwkReady()) {
362 LoadModeHandler::GetInstance().OnFwkReady();
363 }
364 }
365 } // namespace UserAuth
366 } // namespace UserIam
367 } // namespace OHOS