• 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 "user_idm_service.h"
17 
18 #include "string_ex.h"
19 #include "accesstoken_kit.h"
20 
21 #include "context_factory.h"
22 #include "context_helper.h"
23 #include "context_pool.h"
24 #include "hdi_wrapper.h"
25 #include "iam_check.h"
26 #include "iam_logger.h"
27 #include "iam_para2str.h"
28 #include "iam_defines.h"
29 #include "ipc_common.h"
30 #include "iam_common_defines.h"
31 #include "resource_node_pool.h"
32 #include "resource_node_utils.h"
33 #include "user_idm_callback_proxy.h"
34 #include "user_idm_database.h"
35 #include "user_idm_session_controller.h"
36 
37 #define LOG_LABEL UserIam::Common::LABEL_USER_AUTH_SA
38 namespace OHOS {
39 namespace UserIam {
40 namespace UserAuth {
41 REGISTER_SYSTEM_ABILITY_BY_ID(UserIdmService, SUBSYS_USERIAM_SYS_ABILITY_USERIDM, true);
42 
UserIdmService(int32_t systemAbilityId,bool runOnCreate)43 UserIdmService::UserIdmService(int32_t systemAbilityId, bool runOnCreate) : SystemAbility(systemAbilityId, runOnCreate)
44 {
45 }
46 
OnStart()47 void UserIdmService::OnStart()
48 {
49     IAM_LOGI("start service");
50     if (!Publish(this)) {
51         IAM_LOGE("failed to publish service");
52     }
53 }
54 
OnStop()55 void UserIdmService::OnStop()
56 {
57     IAM_LOGI("stop service");
58 }
59 
OpenSession(int32_t userId,std::vector<uint8_t> & challenge)60 int32_t UserIdmService::OpenSession(int32_t userId, std::vector<uint8_t> &challenge)
61 {
62     IAM_LOGI("start");
63     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
64         IAM_LOGE("failed to check permission");
65         return CHECK_PERMISSION_FAILED;
66     }
67 
68     auto contextList = ContextPool::Instance().Select(CONTEXT_ENROLL);
69     for (const auto &context : contextList) {
70         if (auto ctx = context.lock(); ctx != nullptr) {
71             IAM_LOGE("force stop the old context ****%{public}hx", static_cast<uint16_t>(ctx->GetContextId()));
72             ctx->Stop();
73             ContextPool::Instance().Delete(ctx->GetContextId());
74         }
75     }
76 
77     if (!UserIdmSessionController::Instance().OpenSession(userId, challenge)) {
78         IAM_LOGE("failed to open session");
79         return GENERAL_ERROR;
80     }
81 
82     return SUCCESS;
83 }
84 
CloseSession(int32_t userId)85 void UserIdmService::CloseSession(int32_t userId)
86 {
87     IAM_LOGI("start");
88     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
89         IAM_LOGE("failed to check permission");
90         return;
91     }
92 
93     if (!UserIdmSessionController::Instance().CloseSession(userId)) {
94         IAM_LOGE("failed to get close session");
95     }
96 }
97 
GetCredentialInfo(int32_t userId,AuthType authType,const sptr<IdmGetCredInfoCallbackInterface> & callback)98 int32_t UserIdmService::GetCredentialInfo(int32_t userId, AuthType authType,
99     const sptr<IdmGetCredInfoCallbackInterface> &callback)
100 {
101     if (callback == nullptr) {
102         IAM_LOGE("callback is nullptr");
103         return INVALID_PARAMETERS;
104     }
105     std::vector<std::shared_ptr<CredentialInfo>> credInfos;
106     std::optional<PinSubType> pinSubType = std::nullopt;
107     if (!IpcCommon::CheckPermission(*this, USE_USER_IDM_PERMISSION)) {
108         IAM_LOGE("failed to check permission");
109         callback->OnCredentialInfos(credInfos, pinSubType);
110         return CHECK_PERMISSION_FAILED;
111     }
112 
113     credInfos = UserIdmDatabase::Instance().GetCredentialInfo(userId, authType);
114     if (credInfos.empty()) {
115         IAM_LOGI("no cred enrolled");
116         callback->OnCredentialInfos(credInfos, pinSubType);
117         return NOT_ENROLLED;
118     }
119 
120     auto userInfo = UserIdmDatabase::Instance().GetSecUserInfo(userId);
121     if (userInfo == nullptr) {
122         IAM_LOGE("failed to get userInfo");
123         callback->OnCredentialInfos(credInfos, pinSubType);
124         return INVALID_PARAMETERS;
125     }
126 
127     pinSubType = userInfo->GetPinSubType();
128     IAM_LOGE("before OnCredentialInfos");
129     callback->OnCredentialInfos(credInfos, pinSubType);
130 
131     return SUCCESS;
132 }
133 
GetSecInfo(int32_t userId,const sptr<IdmGetSecureUserInfoCallbackInterface> & callback)134 int32_t UserIdmService::GetSecInfo(int32_t userId, const sptr<IdmGetSecureUserInfoCallbackInterface> &callback)
135 {
136     if (callback == nullptr) {
137         IAM_LOGE("callback is nullptr");
138         return INVALID_PARAMETERS;
139     }
140     std::shared_ptr<SecureUserInfo> userInfos = nullptr;
141     if (!IpcCommon::CheckPermission(*this, USE_USER_IDM_PERMISSION)) {
142         IAM_LOGE("failed to check permission");
143         callback->OnSecureUserInfo(userInfos);
144         return CHECK_PERMISSION_FAILED;
145     }
146 
147     userInfos = UserIdmDatabase::Instance().GetSecUserInfo(userId);
148     if (userInfos == nullptr) {
149         IAM_LOGE("current userid %{public}d is not existed", userId);
150         callback->OnSecureUserInfo(userInfos);
151         return INVALID_PARAMETERS;
152     }
153     callback->OnSecureUserInfo(userInfos);
154 
155     return SUCCESS;
156 }
157 
AddCredential(int32_t userId,const CredentialPara & credPara,const sptr<IdmCallbackInterface> & callback,bool isUpdate)158 void UserIdmService::AddCredential(int32_t userId, const CredentialPara &credPara,
159     const sptr<IdmCallbackInterface> &callback, bool isUpdate)
160 {
161     if (callback == nullptr) {
162         IAM_LOGE("callback is nullptr");
163         return;
164     }
165 
166     Attributes extraInfo;
167     auto contextCallback = ContextCallback::NewInstance(callback,
168         isUpdate ? TRACE_UPDATE_CREDENTIAL : TRACE_ADD_CREDENTIAL);
169     if (contextCallback == nullptr) {
170         IAM_LOGE("failed to construct context callback");
171         callback->OnResult(GENERAL_ERROR, extraInfo);
172         return;
173     }
174     uint64_t callingUid = static_cast<uint64_t>(this->GetCallingUid());
175     contextCallback->SetTraceAuthType(credPara.authType);
176     contextCallback->SetTraceCallingUid(callingUid);
177     contextCallback->SetTraceUserId(userId);
178 
179     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
180         IAM_LOGE("failed to check permission");
181         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
182         return;
183     }
184 
185     std::lock_guard<std::mutex> lock(mutex_);
186     CancelCurrentEnrollIfExist();
187     auto tokenId = IpcCommon::GetAccessTokenId(*this);
188     ContextFactory::EnrollContextPara para = {};
189     para.authType = credPara.authType;
190     para.userId = userId;
191     para.pinType = credPara.pinType;
192     para.tokenId = tokenId;
193     para.token = credPara.token;
194     auto context = ContextFactory::CreateEnrollContext(para, contextCallback);
195     if (!ContextPool::Instance().Insert(context)) {
196         IAM_LOGE("failed to insert context");
197         contextCallback->OnResult(GENERAL_ERROR, extraInfo);
198         return;
199     }
200 
201     auto cleaner = ContextHelper::Cleaner(context);
202     contextCallback->SetCleaner(cleaner);
203 
204     if (!context->Start()) {
205         IAM_LOGE("failed to start enroll");
206         contextCallback->OnResult(context->GetLatestError(), extraInfo);
207     }
208 }
209 
UpdateCredential(int32_t userId,const CredentialPara & credPara,const sptr<IdmCallbackInterface> & callback)210 void UserIdmService::UpdateCredential(int32_t userId, const CredentialPara &credPara,
211     const sptr<IdmCallbackInterface> &callback)
212 {
213     if (callback == nullptr) {
214         IAM_LOGE("callback is nullptr");
215         return;
216     }
217 
218     Attributes extraInfo;
219     if (credPara.token.empty()) {
220         IAM_LOGE("token is empty in update");
221         callback->OnResult(GENERAL_ERROR, extraInfo);
222         return;
223     }
224 
225     auto credInfos = UserIdmDatabase::Instance().GetCredentialInfo(userId, credPara.authType);
226     if (credInfos.empty()) {
227         IAM_LOGE("current userid %{public}d has no credential for type %{public}u", userId, credPara.authType);
228         callback->OnResult(NOT_ENROLLED, extraInfo);
229         return;
230     }
231 
232     AddCredential(userId, credPara, callback, true);
233 }
234 
Cancel(int32_t userId)235 int32_t UserIdmService::Cancel(int32_t userId)
236 {
237     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
238         IAM_LOGE("failed to check permission");
239         return CHECK_PERMISSION_FAILED;
240     }
241     if (!UserIdmSessionController::Instance().IsSessionOpened(userId)) {
242         IAM_LOGE("both user id and challenge are invalid");
243         return GENERAL_ERROR;
244     }
245 
246     std::lock_guard<std::mutex> lock(mutex_);
247     return CancelCurrentEnroll();
248 }
249 
CancelCurrentEnrollIfExist()250 void UserIdmService::CancelCurrentEnrollIfExist()
251 {
252     if (ContextPool::Instance().Select(CONTEXT_ENROLL).size() == 0) {
253         return;
254     }
255 
256     IAM_LOGI("cancel current enroll due to new add credential request or delete");
257     CancelCurrentEnroll();
258 }
259 
CancelCurrentEnroll()260 int32_t UserIdmService::CancelCurrentEnroll()
261 {
262     IAM_LOGD("start");
263     auto contextList = ContextPool::Instance().Select(CONTEXT_ENROLL);
264     int32_t ret = GENERAL_ERROR;
265     for (const auto &context : contextList) {
266         if (auto ctx = context.lock(); ctx != nullptr) {
267             IAM_LOGE("stop the old context %{public}s", GET_MASKED_STRING(ctx->GetContextId()).c_str());
268             ctx->Stop();
269             ContextPool::Instance().Delete(ctx->GetContextId());
270             ret = SUCCESS;
271         }
272     }
273     IAM_LOGI("result %{public}d", ret);
274     return ret;
275 }
276 
EnforceDelUser(int32_t userId,const sptr<IdmCallbackInterface> & callback)277 int32_t UserIdmService::EnforceDelUser(int32_t userId, const sptr<IdmCallbackInterface> &callback)
278 {
279     IAM_LOGI("to delete userid: %{public}d", userId);
280     IF_FALSE_LOGE_AND_RETURN_VAL(callback != nullptr, INVALID_PARAMETERS);
281 
282     Attributes extraInfo;
283     auto contextCallback = ContextCallback::NewInstance(callback, TRACE_ENFORCE_DELETE_USER);
284     if (contextCallback == nullptr) {
285         IAM_LOGE("failed to construct context callback");
286         callback->OnResult(GENERAL_ERROR, extraInfo);
287         return GENERAL_ERROR;
288     }
289     contextCallback->SetTraceUserId(userId);
290 
291     if (!IpcCommon::CheckPermission(*this, ENFORCE_USER_IDM)) {
292         IAM_LOGE("failed to check permission");
293         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
294         return CHECK_PERMISSION_FAILED;
295     }
296 
297     std::lock_guard<std::mutex> lock(mutex_);
298     CancelCurrentEnrollIfExist();
299 
300     auto userInfo = UserIdmDatabase::Instance().GetSecUserInfo(userId);
301     if (userInfo == nullptr) {
302         IAM_LOGE("current userid %{public}d is not existed", userId);
303         contextCallback->OnResult(INVALID_PARAMETERS, extraInfo);
304         return INVALID_PARAMETERS;
305     }
306 
307     std::vector<std::shared_ptr<CredentialInfo>> credInfos;
308     int32_t ret = UserIdmDatabase::Instance().DeleteUserEnforce(userId, credInfos);
309     if (ret != SUCCESS) {
310         IAM_LOGE("failed to enforce delete user");
311         static_cast<void>(extraInfo.SetUint64Value(Attributes::ATTR_CREDENTIAL_ID, 0));
312         contextCallback->OnResult(ret, extraInfo);
313         return ret;
314     }
315 
316     ret = ResourceNodeUtils::NotifyExecutorToDeleteTemplates(credInfos);
317     if (ret != SUCCESS) {
318         IAM_LOGE("failed to delete executor info, error code : %{public}d", ret);
319     }
320 
321     IAM_LOGI("delete user success");
322     contextCallback->OnResult(SUCCESS, extraInfo);
323     return SUCCESS;
324 }
325 
DelUser(int32_t userId,const std::vector<uint8_t> authToken,const sptr<IdmCallbackInterface> & callback)326 void UserIdmService::DelUser(int32_t userId, const std::vector<uint8_t> authToken,
327     const sptr<IdmCallbackInterface> &callback)
328 {
329     IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
330 
331     Attributes extraInfo;
332     auto contextCallback = ContextCallback::NewInstance(callback, TRACE_DELETE_USER);
333     if (contextCallback == nullptr) {
334         IAM_LOGE("failed to construct context callback");
335         callback->OnResult(GENERAL_ERROR, extraInfo);
336         return;
337     }
338     contextCallback->SetTraceUserId(userId);
339 
340     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
341         IAM_LOGE("failed to check permission");
342         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
343         return;
344     }
345 
346     std::lock_guard<std::mutex> lock(mutex_);
347     CancelCurrentEnrollIfExist();
348 
349     if (authToken.empty()) {
350         IAM_LOGE("token is empty in delete");
351         contextCallback->OnResult(INVALID_PARAMETERS, extraInfo);
352         return;
353     }
354 
355     std::vector<std::shared_ptr<CredentialInfo>> credInfos;
356     int32_t ret = UserIdmDatabase::Instance().DeleteUser(userId, authToken, credInfos);
357     if (ret != SUCCESS) {
358         IAM_LOGE("failed to delete user");
359         contextCallback->OnResult(ret, extraInfo);
360         return;
361     }
362 
363     ret = ResourceNodeUtils::NotifyExecutorToDeleteTemplates(credInfos);
364     if (ret != SUCCESS) {
365         IAM_LOGE("failed to delete executor info, error code : %{public}d", ret);
366     }
367     IAM_LOGI("delete user end");
368 
369     contextCallback->OnResult(ret, extraInfo);
370 }
371 
DelCredential(int32_t userId,uint64_t credentialId,const std::vector<uint8_t> & authToken,const sptr<IdmCallbackInterface> & callback)372 void UserIdmService::DelCredential(int32_t userId, uint64_t credentialId,
373     const std::vector<uint8_t> &authToken, const sptr<IdmCallbackInterface> &callback)
374 {
375     IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
376 
377     Attributes extraInfo;
378     auto contextCallback = ContextCallback::NewInstance(callback, TRACE_DELETE_CREDENTIAL);
379     if (contextCallback == nullptr) {
380         IAM_LOGE("failed to construct context callback");
381         callback->OnResult(GENERAL_ERROR, extraInfo);
382         return;
383     }
384     contextCallback->SetTraceUserId(userId);
385 
386     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
387         IAM_LOGE("failed to check permission");
388         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
389         return;
390     }
391 
392     std::lock_guard<std::mutex> lock(mutex_);
393     CancelCurrentEnrollIfExist();
394 
395     std::shared_ptr<CredentialInfo> oldInfo;
396     auto ret = UserIdmDatabase::Instance().DeleteCredentialInfo(userId, credentialId, authToken, oldInfo);
397     if (ret != SUCCESS) {
398         IAM_LOGE("failed to delete CredentialInfo");
399         contextCallback->OnResult(ret, extraInfo);
400         return;
401     }
402     if (oldInfo != nullptr) {
403         contextCallback->SetTraceAuthType(oldInfo->GetAuthType());
404     }
405 
406     IAM_LOGI("delete credentialInfo success");
407     std::vector<std::shared_ptr<CredentialInfo>> list = {oldInfo};
408     ret = ResourceNodeUtils::NotifyExecutorToDeleteTemplates(list);
409     if (ret != SUCCESS) {
410         IAM_LOGE("failed to delete executor info, error code : %{public}d", ret);
411     }
412 
413     contextCallback->OnResult(ret, extraInfo);
414 }
415 
Dump(int fd,const std::vector<std::u16string> & args)416 int UserIdmService::Dump(int fd, const std::vector<std::u16string> &args)
417 {
418     IAM_LOGI("start");
419     if (fd < 0) {
420         IAM_LOGE("invalid parameters");
421         dprintf(fd, "Invalid parameters.\n");
422         return INVALID_PARAMETERS;
423     }
424     std::string arg0 = (args.empty() ? "" : Str16ToStr8(args[0]));
425     if (arg0.empty() || arg0.compare("-h") == 0) {
426         dprintf(fd, "Usage:\n");
427         dprintf(fd, "      -h: command help.\n");
428         dprintf(fd, "      -l: active user info dump.\n");
429         return SUCCESS;
430     }
431     if (arg0.compare("-l") == 0) {
432         std::optional<int32_t> activeUserId;
433         if (IpcCommon::GetActiveUserId(activeUserId) != SUCCESS) {
434             dprintf(fd, "Internal error.\n");
435             IAM_LOGE("failed to get active id");
436             return GENERAL_ERROR;
437         }
438         dprintf(fd, "Active user is %d\n", activeUserId.value());
439         auto userInfo = UserIdmDatabase::Instance().GetSecUserInfo(activeUserId.value());
440         if (userInfo != nullptr) {
441             auto enrolledInfo = userInfo->GetEnrolledInfo();
442             for (auto &info : enrolledInfo) {
443                 if (info != nullptr) {
444                     dprintf(fd, "AuthType %s is enrolled.\n", Common::AuthTypeToStr(info->GetAuthType()));
445                 }
446             }
447         }
448         return SUCCESS;
449     }
450     IAM_LOGE("invalid option");
451     dprintf(fd, "Invalid option\n");
452     return GENERAL_ERROR;
453 }
454 } // namespace UserAuth
455 } // namespace UserIam
456 } // namespace OHOS