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 "risk_event_manager.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()
76 : SystemAbility(SUBSYS_USERIAM_SYS_ABILITY_AUTHEXECUTORMGR, true), CoAuthStub(true)
77 {
78 IAM_LOGI("CoAuthService init");
79 }
80
OnStart()81 void CoAuthService::OnStart()
82 {
83 std::lock_guard<std::recursive_mutex> guard(mutex_);
84 IAM_LOGI("Sa start CoAuthService");
85 IPCSkeleton::SetMaxWorkThreadNum(USERIAM_IPC_THREAD_NUM);
86 if (!Publish(this)) {
87 IAM_LOGE("Failed to publish service");
88 return;
89 }
90
91 ServiceInitManager::GetInstance().OnCoAuthServiceStart();
92 }
93
OnStop()94 void CoAuthService::OnStop()
95 {
96 IAM_LOGI("Sa stop CoAuthService");
97 ServiceInitManager::GetInstance().OnCoAuthServiceStop();
98 }
99
SetIsReady(bool isReady)100 void CoAuthService::SetIsReady(bool isReady)
101 {
102 std::lock_guard<std::recursive_mutex> guard(mutex_);
103 isReady_ = isReady;
104 IAM_LOGI("Set isReady %{public}d", isReady);
105 }
106
SetAccessTokenReady(bool isReady)107 void CoAuthService::SetAccessTokenReady(bool isReady)
108 {
109 std::lock_guard<std::recursive_mutex> guard(mutex_);
110 accessTokenReady_ = isReady;
111 IAM_LOGI("Set accesstk ready %{public}d", isReady);
112 }
113
IsFwkReady()114 bool CoAuthService::IsFwkReady()
115 {
116 std::lock_guard<std::recursive_mutex> guard(mutex_);
117 return isReady_ && accessTokenReady_;
118 }
119
AddExecutorDeathRecipient(uint64_t executorIndex,AuthType authType,ExecutorRole role,std::shared_ptr<IExecutorCallback> callback)120 void CoAuthService::AddExecutorDeathRecipient(uint64_t executorIndex, AuthType authType, ExecutorRole role,
121 std::shared_ptr<IExecutorCallback> callback)
122 {
123 IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
124 auto obj = callback->AsObject();
125 IF_FALSE_LOGE_AND_RETURN(obj != nullptr);
126
127 obj->AddDeathRecipient(new (std::nothrow) IpcCommon::PeerDeathRecipient([executorIndex, authType, role]() {
128 IAM_LOGE("executorCallback is down");
129 auto weakNode = ResourceNodePool::Instance().Select(executorIndex);
130 auto sharedNode = weakNode.lock();
131 if (sharedNode != nullptr) {
132 auto result = ResourceNodePool::Instance().Delete(executorIndex);
133 IAM_LOGI("delete executor %{public}s, executorIndex is ****%{public}hx authType is %{public}d "
134 "executorRole is %{public}d", (result ? "succ" : "failed"), static_cast<uint16_t>(executorIndex),
135 sharedNode->GetAuthType(), sharedNode->GetExecutorRole());
136 }
137 LoadModeHandler::GetInstance().OnExecutorUnregistered(authType, role);
138 std::string executorDesc = "executor, type " + std::to_string(authType);
139 UserIam::UserAuth::ReportSystemFault(Common::GetNowTimeString(), executorDesc);
140 IAM_LOGI("executorCallback is down processed");
141 }));
142 }
143
ProcExecutorRegisterSuccess(std::shared_ptr<ResourceNode> & resourceNode,const std::shared_ptr<IExecutorCallback> & callback,std::vector<uint64_t> & templateIdList,std::vector<uint8_t> & fwkPublicKey)144 int32_t CoAuthService::ProcExecutorRegisterSuccess(std::shared_ptr<ResourceNode> &resourceNode,
145 const std::shared_ptr<IExecutorCallback> &callback, std::vector<uint64_t> &templateIdList,
146 std::vector<uint8_t> &fwkPublicKey)
147 {
148 IAM_LOGI("start");
149 uint64_t executorIndex = resourceNode->GetExecutorIndex();
150 auto handler = ThreadHandler::GetSingleThreadInstance();
151 std::weak_ptr<ResourceNode> weakNode = resourceNode;
152 IF_FALSE_LOGE_AND_RETURN_VAL(handler != nullptr, GENERAL_ERROR);
153 handler->PostTask([callback, fwkPublicKey, templateIdList, weakNode, executorIndex]() {
154 auto resourceNode = weakNode.lock();
155 IF_FALSE_LOGE_AND_RETURN(resourceNode != nullptr);
156 sptr<IExecutorMessenger> messenger = ExecutorMessengerService::GetInstance();
157 callback->OnMessengerReady(messenger, fwkPublicKey, templateIdList);
158 IAM_LOGI("register successful, executorType is %{public}d, executorRole is %{public}d, "
159 "executorIndex is ****%{public}hx",
160 resourceNode->GetAuthType(), resourceNode->GetExecutorRole(), static_cast<uint16_t>(executorIndex));
161 LoadModeHandler::GetInstance().OnExecutorRegistered(resourceNode->GetAuthType(),
162 resourceNode->GetExecutorRole());
163 AddExecutorDeathRecipient(executorIndex, resourceNode->GetAuthType(), resourceNode->GetExecutorRole(),
164 callback);
165 IAM_LOGI("update template cache after register success");
166 TemplateCacheManager::GetInstance().UpdateTemplateCache(resourceNode->GetAuthType());
167 RiskEventManager::GetInstance().SyncRiskEvents();
168 });
169
170 return SUCCESS;
171 }
172
ExecutorRegister(const IpcExecutorRegisterInfo & ipcExecutorRegisterInfo,const sptr<IExecutorCallback> & executorCallback,uint64_t & executorIndex)173 int32_t CoAuthService::ExecutorRegister(const IpcExecutorRegisterInfo &ipcExecutorRegisterInfo,
174 const sptr<IExecutorCallback> &executorCallback, uint64_t &executorIndex)
175 {
176 IAM_LOGI("register resource node begin");
177 executorIndex = INVALID_EXECUTOR_INDEX;
178 Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
179 if (executorCallback == nullptr) {
180 IAM_LOGE("executor callback is nullptr");
181 return INVALID_PARAMETERS;
182 }
183
184 std::lock_guard<std::recursive_mutex> guard(mutex_);
185 if (!IsFwkReady()) {
186 IAM_LOGE("framework is not ready");
187 return GENERAL_ERROR;
188 }
189
190 if (!IpcCommon::CheckPermission(*this, ACCESS_AUTH_RESPOOL)) {
191 IAM_LOGE("failed to check permission");
192 return CHECK_PERMISSION_FAILED;
193 }
194
195 std::vector<uint64_t> templateIdList;
196 std::vector<uint8_t> fwkPublicKey;
197 ExecutorRegisterInfo executorRegisterInfo = {};
198 InitExecutorRegisterInfo(ipcExecutorRegisterInfo, executorRegisterInfo);
199 sptr<IExecutorCallback> tempCallBack = executorCallback;
200 auto callback = Common::SptrToStdSharedPtr<IExecutorCallback>(tempCallBack);
201 auto resourceNode = ResourceNode::MakeNewResource(executorRegisterInfo, callback,
202 templateIdList, fwkPublicKey);
203 if (resourceNode == nullptr) {
204 IAM_LOGE("create resource node failed");
205 return GENERAL_ERROR;
206 }
207 if (!ResourceNodePool::Instance().Insert(resourceNode)) {
208 IAM_LOGE("insert resource node failed");
209 return GENERAL_ERROR;
210 }
211 executorIndex = resourceNode->GetExecutorIndex();
212 return ProcExecutorRegisterSuccess(resourceNode, callback, templateIdList, fwkPublicKey);
213 }
214
ExecutorUnregister(uint64_t executorIndex)215 int32_t CoAuthService::ExecutorUnregister(uint64_t executorIndex)
216 {
217 IAM_LOGI("delete resource node begin");
218 Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
219 std::lock_guard<std::recursive_mutex> guard(mutex_);
220 if (!IsFwkReady()) {
221 IAM_LOGE("framework is not ready");
222 return SUCCESS;
223 }
224
225 if (!IpcCommon::CheckPermission(*this, ACCESS_AUTH_RESPOOL)) {
226 IAM_LOGE("failed to check permission");
227 return CHECK_PERMISSION_FAILED;
228 }
229
230 {
231 auto resourceNode = ResourceNodePool::Instance().Select(executorIndex).lock();
232 IF_FALSE_LOGE_AND_RETURN_VAL(resourceNode != nullptr, GENERAL_ERROR);
233 LoadModeHandler::GetInstance().OnExecutorUnregistered(resourceNode->GetAuthType(),
234 resourceNode->GetExecutorRole());
235 }
236
237 if (!ResourceNodePool::Instance().Delete(executorIndex)) {
238 IAM_LOGE("delete resource node failed");
239 return GENERAL_ERROR;
240 }
241 IAM_LOGI("delete resource node success, executorIndex is ****%{public}hx", static_cast<uint16_t>(executorIndex));
242 return SUCCESS;
243 }
244
OnDriverStart()245 void CoAuthService::OnDriverStart()
246 {
247 std::lock_guard<std::recursive_mutex> guard(mutex_);
248 IAM_LOGI("process driver start begin");
249 if (isReady_) {
250 IAM_LOGI("already ready");
251 return;
252 }
253 std::string localUdid;
254 bool getLocalUdidRet = DeviceManagerUtil::GetInstance().GetLocalDeviceUdid(localUdid);
255 IF_FALSE_LOGE_AND_RETURN(getLocalUdidRet);
256 auto service = HdiWrapper::GetHdiInstance();
257 IF_FALSE_LOGE_AND_RETURN(service != nullptr);
258 int32_t initRet = service->Init(localUdid);
259 IF_FALSE_LOGE_AND_RETURN(initRet == HDF_SUCCESS);
260 auto callbackService = HdiMessageCallbackService::GetInstance();
261 IF_FALSE_LOGE_AND_RETURN(callbackService != nullptr);
262 callbackService->OnHdiConnect();
263 SetIsReady(true);
264 NotifyFwkReady();
265 IAM_LOGI("process driver start success");
266 }
267
OnDriverStop()268 void CoAuthService::OnDriverStop()
269 {
270 std::lock_guard<std::recursive_mutex> guard(mutex_);
271 IAM_LOGE("process driver stop begin");
272 if (isReady_) {
273 IAM_LOGI("service is ready, clear status");
274 ResourceNodePool::Instance().DeleteAll();
275 UserIam::UserAuth::ReportSystemFault(Common::GetNowTimeString(), "user_auth_hdi host");
276 SetIsReady(false);
277 }
278 IAM_LOGI("process driver stop success");
279 }
280
Dump(int fd,const std::vector<std::u16string> & args)281 int CoAuthService::Dump(int fd, const std::vector<std::u16string> &args)
282 {
283 IAM_LOGI("start");
284 if (fd < 0) {
285 IAM_LOGE("invalid parameters");
286 return INVALID_PARAMETERS;
287 }
288 std::string arg0 = (args.empty() ? "" : Str16ToStr8(args[0]));
289 if (arg0.empty() || arg0.compare("-h") == 0) {
290 dprintf(fd, "Usage:\n");
291 dprintf(fd, " -h: command help.\n");
292 dprintf(fd, " -l: resource pool dump.\n");
293 return SUCCESS;
294 }
295 if (arg0.compare("-l") == 0) {
296 ResourceNodePool::Instance().Enumerate([fd](const std::weak_ptr<ResourceNode> &node) {
297 auto nodeTmp = node.lock();
298 if (nodeTmp != nullptr) {
299 dprintf(fd, "ExecutorIndex is: %" PRIx64 ".\n", nodeTmp->GetExecutorIndex());
300 dprintf(fd, "ExecutorType is: %s.\n", Common::AuthTypeToStr(nodeTmp->GetAuthType()));
301 dprintf(fd, "ExecutorRole is: %s.\n", Common::ExecutorRoleToStr(nodeTmp->GetExecutorRole()));
302 }
303 });
304 return SUCCESS;
305 }
306 IAM_LOGE("invalid option");
307 dprintf(fd, "Invalid option\n");
308 return GENERAL_ERROR;
309 }
310
RegisterAccessTokenListener()311 ResultCode CoAuthService::RegisterAccessTokenListener()
312 {
313 IAM_LOGD("start.");
314 std::lock_guard<std::recursive_mutex> lock(mutex_);
315 if (accessTokenListener_ != nullptr) {
316 IAM_LOGI("accessTokenListener_ is not nullptr.");
317 return SUCCESS;
318 }
319
320 accessTokenListener_ = SystemAbilityListener::Subscribe("accesstoken_service", ACCESS_TOKEN_MANAGER_SERVICE_ID,
321 []() {
322 auto instance = CoAuthService::GetInstance();
323 if (instance == nullptr) {
324 IAM_LOGE("CoAuthService instance is nullptr.");
325 return;
326 }
327 instance->SetAccessTokenReady(true);
328 instance->NotifyFwkReady();
329 },
330 nullptr);
331 if (accessTokenListener_ == nullptr) {
332 IAM_LOGE("accessTokenListener_ is nullptr.");
333 return GENERAL_ERROR;
334 }
335
336 IAM_LOGI("RegisterAccessTokenListener success.");
337 return SUCCESS;
338 }
339
UnRegisterAccessTokenListener()340 ResultCode CoAuthService::UnRegisterAccessTokenListener()
341 {
342 IAM_LOGD("start.");
343 std::lock_guard<std::recursive_mutex> lock(mutex_);
344 if (accessTokenListener_ == nullptr) {
345 IAM_LOGI("accessTokenListener_ is nullptr.");
346 return SUCCESS;
347 }
348
349 int32_t ret = SystemAbilityListener::UnSubscribe(ACCESS_TOKEN_MANAGER_SERVICE_ID, accessTokenListener_);
350 if (ret != SUCCESS) {
351 IAM_LOGE("UnSubscribe service fail.");
352 return GENERAL_ERROR;
353 }
354
355 accessTokenListener_ = nullptr;
356 IAM_LOGI("UnRegisterAccessTokenListener success.");
357 return SUCCESS;
358 }
359
NotifyFwkReady()360 void CoAuthService::NotifyFwkReady()
361 {
362 IAM_LOGD("start.");
363 if (IsFwkReady()) {
364 LoadModeHandler::GetInstance().OnFwkReady();
365 }
366 }
367
InitExecutorRegisterInfo(const IpcExecutorRegisterInfo & ipcExecutorRegisterInfo,ExecutorRegisterInfo & executorRegisterInfo)368 void CoAuthService::InitExecutorRegisterInfo(const IpcExecutorRegisterInfo &ipcExecutorRegisterInfo,
369 ExecutorRegisterInfo &executorRegisterInfo)
370 {
371 executorRegisterInfo.authType = static_cast<AuthType>(ipcExecutorRegisterInfo.authType);
372 executorRegisterInfo.executorRole = static_cast<ExecutorRole>(ipcExecutorRegisterInfo.executorRole);
373 executorRegisterInfo.executorSensorHint = ipcExecutorRegisterInfo.executorSensorHint;
374 executorRegisterInfo.executorMatcher = ipcExecutorRegisterInfo.executorMatcher;
375 executorRegisterInfo.esl = static_cast<ExecutorSecureLevel>(ipcExecutorRegisterInfo.esl);
376 executorRegisterInfo.maxTemplateAcl = ipcExecutorRegisterInfo.maxTemplateAcl;
377 executorRegisterInfo.publicKey = ipcExecutorRegisterInfo.publicKey;
378 executorRegisterInfo.deviceUdid = ipcExecutorRegisterInfo.deviceUdid;
379 executorRegisterInfo.signedRemoteExecutorInfo = ipcExecutorRegisterInfo.signedRemoteExecutorInfo;
380 }
381
CallbackEnter(uint32_t code)382 int32_t CoAuthService::CallbackEnter([[maybe_unused]] uint32_t code)
383 {
384 IAM_LOGI("start, code:%{public}u", code);
385 return SUCCESS;
386 }
387
CallbackExit(uint32_t code,int32_t result)388 int32_t CoAuthService::CallbackExit([[maybe_unused]] uint32_t code, [[maybe_unused]] int32_t result)
389 {
390 IAM_LOGI("leave, code:%{public}u, result:%{public}d", code, result);
391 return SUCCESS;
392 }
393 } // namespace UserAuth
394 } // namespace UserIam
395 } // namespace OHOS