• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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