• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 #include "bundle_mgr_interface.h"
16 #include "bundle_mgr_proxy.h"
17 #include "iservice_registry.h"
18 #include "system_ability_definition.h"
19 
20 #include "auth_manager.h"
21 #include "access_control_profile.h"
22 #include "deviceprofile_connector.h"
23 #include "distributed_device_profile_errors.h"
24 #include "dm_anonymous.h"
25 #include "dm_auth_attest_common.h"
26 #include "dm_auth_cert.h"
27 #include "dm_auth_context.h"
28 #include "dm_auth_state.h"
29 #include "dm_auth_state_machine.h"
30 #include "dm_crypto.h"
31 #include "dm_dialog_manager.h"
32 #include "dm_language_manager.h"
33 #include "dm_log.h"
34 #include "dm_negotiate_process.h"
35 #include "dm_softbus_cache.h"
36 #include "ffrt.h"
37 #include "multiple_user_connector.h"
38 
39 namespace OHOS {
40 namespace DistributedHardware {
41 
42 constexpr const char* TAG_CRED_ID = "credId";
43 constexpr const char* TAG_CUSTOM_DESCRIPTION = "CUSTOMDESC";
44 constexpr const char* TAG_LOCAL_DEVICE_TYPE = "LOCALDEVICETYPE";
45 constexpr const char* TAG_REQUESTER = "REQUESTER";
46 constexpr const char* UNVALID_CREDTID = "invalidCredId";
47 constexpr const char* TAG_IS_SUPPORT_ULTRASONIC = "isSupportUltrasonic";
48 // authType fallback table
49 using FallBackKey = std::pair<std::string, DmAuthType>; // accessee.bundleName, authType
50 static std::map<FallBackKey, DmAuthType> g_pinAuthTypeFallBackMap = {
51     {{"cast_engine_service", DmAuthType::AUTH_TYPE_NFC}, DmAuthType::AUTH_TYPE_PIN},
52 };
53 // Maximum number of recursive lookups
54 constexpr size_t MAX_FALLBACK_LOOPKUP_TIMES = 2;
55 
GetStateType()56 DmAuthStateType AuthSrcConfirmState::GetStateType()
57 {
58     return DmAuthStateType::AUTH_SRC_CONFIRM_STATE;
59 }
60 
NegotiateCredential(std::shared_ptr<DmAuthContext> context,JsonObject & credTypeNegoResult)61 void AuthSrcConfirmState::NegotiateCredential(std::shared_ptr<DmAuthContext> context, JsonObject &credTypeNegoResult)
62 {
63     CHECK_NULL_VOID(context);
64     JsonObject accesseeCredTypeList;
65     accesseeCredTypeList.Parse(context->accessee.credTypeList);
66     JsonObject accesserCredTypeList;
67     accesserCredTypeList.Parse(context->accesser.credTypeList);
68     if (accesseeCredTypeList.IsDiscarded() || accesserCredTypeList.IsDiscarded()) {
69         LOGE("CredTypeList invalid.");
70         return;
71     }
72     if (accesseeCredTypeList.Contains("identicalCredType") && accesserCredTypeList.Contains("identicalCredType")) {
73         LOGI("have identical credential.");
74         credTypeNegoResult["identicalCredType"] = DM_IDENTICAL_ACCOUNT;
75         context->accesser.isGenerateLnnCredential = false;
76     }
77     if (accesseeCredTypeList.Contains("shareCredType") && accesserCredTypeList.Contains("shareCredType")) {
78         LOGI("have share credential.");
79         credTypeNegoResult["shareCredType"] = DM_SHARE;
80         context->accesser.isGenerateLnnCredential = false;
81     }
82     if (accesseeCredTypeList.Contains("pointTopointCredType") &&
83         accesserCredTypeList.Contains("pointTopointCredType")) {
84         LOGI("have point_to_point credential.");
85         credTypeNegoResult["pointTopointCredType"] = DM_POINT_TO_POINT;
86     }
87     if (accesseeCredTypeList.Contains("lnnCredType") && accesserCredTypeList.Contains("lnnCredType")) {
88         LOGI("have lnn credential.");
89         credTypeNegoResult["lnnCredType"] = DM_LNN;
90         context->accesser.isGenerateLnnCredential = false;
91     }
92 }
93 
NegotiateProxyCredential(std::shared_ptr<DmAuthContext> context)94 void AuthSrcConfirmState::NegotiateProxyCredential(std::shared_ptr<DmAuthContext> context)
95 {
96     CHECK_NULL_VOID(context);
97     if (!context->IsProxyBind) {
98         return;
99     }
100     if (context->subjectProxyOnes.empty()) {
101         return;
102     }
103     for (auto item = context->subjectProxyOnes.begin(); item != context->subjectProxyOnes.end(); ++item) {
104         JsonObject credTypeNegoResult;
105         JsonObject accesseeCredTypeList;
106         accesseeCredTypeList.Parse(item->proxyAccessee.credTypeList);
107         JsonObject accesserCredTypeList;
108         accesserCredTypeList.Parse(item->proxyAccesser.credTypeList);
109         if (accesseeCredTypeList.IsDiscarded() || accesserCredTypeList.IsDiscarded()) {
110             item->proxyAccesser.credTypeList = credTypeNegoResult.Dump();
111             continue;
112         }
113         if (accesseeCredTypeList.Contains("pointTopointCredType") &&
114             accesserCredTypeList.Contains("pointTopointCredType")) {
115             credTypeNegoResult["pointTopointCredType"] = DM_POINT_TO_POINT;
116             item->proxyAccesser.credTypeList = credTypeNegoResult.Dump();
117             continue;
118         }
119         item->proxyAccesser.credTypeList = credTypeNegoResult.Dump();
120     }
121 }
122 
NegotiateAcl(std::shared_ptr<DmAuthContext> context,JsonObject & aclNegoResult)123 void AuthSrcConfirmState::NegotiateAcl(std::shared_ptr<DmAuthContext> context, JsonObject &aclNegoResult)
124 {
125     CHECK_NULL_VOID(context);
126     JsonObject accesseeAclList;
127     accesseeAclList.Parse(context->accessee.aclTypeList);
128     JsonObject accesserAclList;
129     accesserAclList.Parse(context->accesser.aclTypeList);
130     if (accesseeAclList.IsDiscarded() || accesserAclList.IsDiscarded()) {
131         LOGE("aclList invalid.");
132         return;
133     }
134     if (accesseeAclList.Contains("identicalAcl") && accesserAclList.Contains("identicalAcl")) {
135         LOGI("have identical acl.");
136         aclNegoResult["identicalAcl"] = DM_IDENTICAL_ACCOUNT;
137         context->accesser.isAuthed = true;
138         context->accesser.isUserLevelAuthed = true;
139         context->accesser.isPutLnnAcl = false;
140     }
141     if (accesseeAclList.Contains("shareAcl") && accesserAclList.Contains("shareAcl")) {
142         LOGI("have share acl.");
143         aclNegoResult["shareAcl"] = DM_SHARE;
144         context->accesser.isAuthed = true;
145         context->accesser.isUserLevelAuthed = true;
146         context->accesser.isPutLnnAcl = false;
147     }
148     if (accesseeAclList.Contains("pointTopointAcl") && accesserAclList.Contains("pointTopointAcl")) {
149         LOGI("have point_to_point acl.");
150         aclNegoResult["pointTopointAcl"] = DM_POINT_TO_POINT;
151         context->accesser.isAuthed = true;
152     }
153     if (accesseeAclList.Contains("lnnAcl") && accesserAclList.Contains("lnnAcl")) {
154         LOGI("have lnn acl.");
155         aclNegoResult["lnnAcl"] = DM_LNN;
156         context->accesser.isPutLnnAcl = false;
157     }
158 }
159 
NegotiateProxyAcl(std::shared_ptr<DmAuthContext> context)160 void AuthSrcConfirmState::NegotiateProxyAcl(std::shared_ptr<DmAuthContext> context)
161 {
162     CHECK_NULL_VOID(context);
163     if (!context->IsProxyBind) {
164         return;
165     }
166     if (context->subjectProxyOnes.empty()) {
167         return;
168     }
169     for (auto item = context->subjectProxyOnes.begin(); item != context->subjectProxyOnes.end(); ++item) {
170         JsonObject aclNegoResult;
171         JsonObject accesseeAclList;
172         if (!item->proxyAccessee.aclTypeList.empty()) {
173             accesseeAclList.Parse(item->proxyAccessee.aclTypeList);
174         }
175         JsonObject accesserAclList;
176         if (!item->proxyAccesser.aclTypeList.empty()) {
177             accesserAclList.Parse(item->proxyAccesser.aclTypeList);
178         }
179         if (accesseeAclList.IsDiscarded() || accesserAclList.IsDiscarded()) {
180             item->proxyAccesser.aclTypeList = aclNegoResult.Dump();
181             continue;
182         }
183         if (accesseeAclList.Contains("pointTopointAcl") && accesserAclList.Contains("pointTopointAcl")) {
184             LOGI("have point_to_point acl bundleName: %{public}s.", item->proxyAccesser.bundleName.c_str());
185             aclNegoResult["pointTopointAcl"] = DM_POINT_TO_POINT;
186             item->proxyAccesser.aclTypeList = aclNegoResult.Dump();
187             item->proxyAccesser.isAuthed = true;
188             continue;
189         }
190         item->proxyAccesser.aclTypeList = aclNegoResult.Dump();
191     }
192 }
193 
GetSrcCredType(std::shared_ptr<DmAuthContext> context,JsonObject & credInfo,JsonObject & aclInfo,JsonObject & credTypeJson)194 void AuthSrcConfirmState::GetSrcCredType(std::shared_ptr<DmAuthContext> context,
195     JsonObject &credInfo, JsonObject &aclInfo, JsonObject &credTypeJson)
196 {
197     CHECK_NULL_VOID(context);
198     std::vector<std::string> deleteCredInfo;
199     for (const auto &item : credInfo.Items()) {
200         if (!item.Contains(FILED_CRED_ID) || !item[FILED_CRED_ID].IsString()) {
201             continue;
202         }
203         if (!item.Contains(FILED_CRED_TYPE) || !item[FILED_CRED_TYPE].IsNumberInteger()) {
204             deleteCredInfo.push_back(item[FILED_CRED_ID].Get<std::string>());
205             DirectlyDeleteCredential(context, context->accesser.userId, item);
206             continue;
207         }
208         int32_t credType = item[FILED_CRED_TYPE].Get<int32_t>();
209         LOGI("credType %{public}d.", credType);
210         switch (credType) {
211             case DM_IDENTICAL_ACCOUNT:
212                 credTypeJson["identicalCredType"] = credType;
213                 context->accesser.credentialInfos[credType] = item.Dump();
214                 break;
215             case DM_SHARE:
216                 credTypeJson["shareCredType"] = credType;
217                 context->accesser.credentialInfos[credType] = item.Dump();
218                 break;
219             case DM_POINT_TO_POINT:
220                 GetSrcCredTypeForP2P(context, item, aclInfo, credTypeJson, credType, deleteCredInfo);
221                 break;
222             case DM_LNN:
223                 if (!aclInfo.Contains("lnnAcl") ||
224                     (context->accesser.aclProfiles[DM_LNN].GetAccesser().GetAccesserCredentialIdStr() !=
225                     item[FILED_CRED_ID].Get<std::string>() &&
226                     context->accesser.aclProfiles[DM_LNN].GetAccessee().GetAccesseeCredentialIdStr() !=
227                     item[FILED_CRED_ID].Get<std::string>())) {
228                     deleteCredInfo.push_back(item[FILED_CRED_ID].Get<std::string>());
229                     DirectlyDeleteCredential(context, context->accesser.userId, item);
230                 } else {
231                     credTypeJson["lnnCredType"] = credType;
232                     context->accesser.credentialInfos[credType] = item.Dump();
233                 }
234                 break;
235             default:
236                 LOGE("invalid credType %{public}d.", credType);
237                 break;
238         }
239     }
240     GetSrcProxyCredTypeForP2P(context, deleteCredInfo);
241     for (const auto &item : deleteCredInfo) {
242         credInfo.Erase(item);
243     }
244 }
245 
GetSrcCredTypeForP2P(std::shared_ptr<DmAuthContext> context,const JsonItemObject & credObj,JsonObject & aclInfo,JsonObject & credTypeJson,int32_t credType,std::vector<std::string> & deleteCredInfo)246 void AuthSrcConfirmState::GetSrcCredTypeForP2P(std::shared_ptr<DmAuthContext> context, const JsonItemObject &credObj,
247     JsonObject &aclInfo, JsonObject &credTypeJson, int32_t credType, std::vector<std::string> &deleteCredInfo)
248 {
249     CHECK_NULL_VOID(context);
250     if (!aclInfo.Contains("pointTopointAcl") ||
251         (context->accesser.aclProfiles[DM_POINT_TO_POINT].GetAccesser().GetAccesserCredentialIdStr() !=
252         credObj[FILED_CRED_ID].Get<std::string>() &&
253         context->accesser.aclProfiles[DM_POINT_TO_POINT].GetAccessee().GetAccesseeCredentialIdStr() !=
254         credObj[FILED_CRED_ID].Get<std::string>())) {
255         deleteCredInfo.push_back(credObj[FILED_CRED_ID].Get<std::string>());
256         DeleteCredential(context, context->accesser.userId, credObj, context->accesser.aclProfiles[DM_POINT_TO_POINT]);
257     } else {
258         credTypeJson["pointTopointCredType"] = credType;
259         context->accesser.credentialInfos[credType] = credObj.Dump();
260     }
261 }
262 
GetSrcProxyCredTypeForP2P(std::shared_ptr<DmAuthContext> context,std::vector<std::string> & deleteCredInfo)263 void AuthSrcConfirmState::GetSrcProxyCredTypeForP2P(std::shared_ptr<DmAuthContext> context,
264     std::vector<std::string> &deleteCredInfo)
265 {
266     CHECK_NULL_VOID(context);
267     if (!context->IsProxyBind || context->subjectProxyOnes.empty()) {
268         return;
269     }
270     for (auto item = context->subjectProxyOnes.begin(); item != context->subjectProxyOnes.end(); ++item) {
271         JsonObject credInfoJson;
272         if (!item->proxyAccesser.credInfoJson.empty()) {
273             credInfoJson.Parse(item->proxyAccesser.credInfoJson);
274         }
275         for (const auto &credItem : credInfoJson.Items()) {
276             if (!credItem.Contains(FILED_CRED_ID) || !credItem[FILED_CRED_ID].IsString()) {
277                 continue;
278             }
279             if (!credItem.Contains(FILED_CRED_TYPE) || !credItem[FILED_CRED_TYPE].IsNumberInteger()) {
280                 deleteCredInfo.push_back(credItem[FILED_CRED_ID].Get<std::string>());
281                 DirectlyDeleteCredential(context, context->accesser.userId, credItem);
282                 continue;
283             }
284             int32_t credType = credItem[FILED_CRED_TYPE].Get<int32_t>();
285             if (credType != static_cast<int32_t>(DM_POINT_TO_POINT)) {
286                 continue;
287             }
288             std::string credId = credItem[FILED_CRED_ID].Get<std::string>();
289             JsonObject aclTypeJson;
290             if (!item->proxyAccesser.aclTypeList.empty()) {
291                 aclTypeJson.Parse(item->proxyAccesser.aclTypeList);
292             }
293             if (!aclTypeJson.Contains("pointTopointAcl") ||
294                 item->proxyAccesser.aclProfiles.find(DM_POINT_TO_POINT) == item->proxyAccesser.aclProfiles.end() ||
295                 (item->proxyAccesser.aclProfiles[DM_POINT_TO_POINT].GetAccessee().GetAccesseeCredentialIdStr() !=
296                     credItem[FILED_CRED_ID].Get<std::string>() &&
297                 item->proxyAccesser.aclProfiles[DM_POINT_TO_POINT].GetAccesser().GetAccesserCredentialIdStr() !=
298                 credItem[FILED_CRED_ID].Get<std::string>())) {
299                 deleteCredInfo.push_back(credItem[FILED_CRED_ID].Get<std::string>());
300                 DeleteCredential(context, context->accesser.userId, credItem,
301                     item->proxyAccesser.aclProfiles[DM_POINT_TO_POINT]);
302                 continue;
303             }
304             JsonObject validCredInfoJson;
305             if (!item->proxyAccesser.credTypeList.empty()) {
306                 validCredInfoJson.Parse(item->proxyAccesser.credTypeList);
307             }
308             validCredInfoJson["pointTopointCredType"] = credType;
309             item->proxyAccesser.credTypeList = validCredInfoJson.Dump();
310             item->proxyAccesser.credentialInfos[credType] = credItem.Dump();
311         }
312     }
313 }
314 
GetSrcAclInfo(std::shared_ptr<DmAuthContext> context,JsonObject & credInfo,JsonObject & aclInfo)315 void AuthSrcConfirmState::GetSrcAclInfo(std::shared_ptr<DmAuthContext> context,
316     JsonObject &credInfo, JsonObject &aclInfo)
317 {
318     CHECK_NULL_VOID(context);
319     std::vector<DistributedDeviceProfile::AccessControlProfile> profiles =
320         DeviceProfileConnector::GetInstance().GetAllAclIncludeLnnAcl();
321     FilterProfilesByContext(profiles, context);
322     uint32_t bindLevel = DM_INVALIED_TYPE;
323     for (const auto &item : profiles) {
324         std::string trustDeviceId = item.GetTrustDeviceId();
325         std::string trustDeviceIdHash = Crypto::GetUdidHash(trustDeviceId);
326         if ((trustDeviceIdHash != context->accessee.deviceIdHash &&
327             trustDeviceIdHash != context->accesser.deviceIdHash)) {
328             LOGE("devId %{public}s hash %{public}s, accesser devId %{public}s.", GetAnonyString(trustDeviceId).c_str(),
329                 GetAnonyString(trustDeviceIdHash).c_str(), GetAnonyString(context->accesser.deviceIdHash).c_str());
330             continue;
331         }
332         bindLevel = item.GetBindLevel();
333         switch (item.GetBindType()) {
334             case DM_IDENTICAL_ACCOUNT:
335                 if (IdenticalAccountAclCompare(context, item.GetAccesser(), item.GetAccessee())) {
336                     aclInfo["identicalAcl"] = DM_IDENTICAL_ACCOUNT;
337                     context->accesser.aclProfiles[DM_IDENTICAL_ACCOUNT] = item;
338                 }
339                 break;
340             case DM_SHARE:
341                 if (ShareAclCompare(context, item.GetAccesser(), item.GetAccessee()) &&
342                     CheckCredIdInAcl(context, item, credInfo, DM_SHARE)) {
343                     aclInfo["shareAcl"] = DM_SHARE;
344                     context->accesser.aclProfiles[DM_SHARE] = item;
345                 }
346                 break;
347             case DM_POINT_TO_POINT:
348                 GetSrcAclInfoForP2P(context, item, credInfo, aclInfo);
349                 break;
350             default:
351                 LOGE("invalid bindType %{public}d.", item.GetBindType());
352                 break;
353         }
354     }
355     if (aclInfo.Contains("pointTopointAcl") && !aclInfo.Contains("lnnAcl") && bindLevel != USER) {
356         aclInfo.Erase("pointTopointAcl");
357         DeleteAcl(context, context->accesser.aclProfiles[DM_POINT_TO_POINT]);
358     }
359 }
360 
GetSrcAclInfoForP2P(std::shared_ptr<DmAuthContext> context,const DistributedDeviceProfile::AccessControlProfile & profile,JsonObject & credInfo,JsonObject & aclInfo)361 void AuthSrcConfirmState::GetSrcAclInfoForP2P(std::shared_ptr<DmAuthContext> context,
362     const DistributedDeviceProfile::AccessControlProfile &profile, JsonObject &credInfo, JsonObject &aclInfo)
363 {
364     CHECK_NULL_VOID(context);
365     if (Point2PointAclCompare(context, profile.GetAccesser(), profile.GetAccessee()) &&
366         CheckCredIdInAcl(context, profile, credInfo, DM_POINT_TO_POINT)) {
367         aclInfo["pointTopointAcl"] = DM_POINT_TO_POINT;
368         context->accesser.aclProfiles[DM_POINT_TO_POINT] = profile;
369     }
370     if (LnnAclCompare(context, profile.GetAccesser(), profile.GetAccessee()) &&
371         CheckCredIdInAcl(context, profile, credInfo, DM_LNN) && profile.GetBindLevel() == USER) {
372         aclInfo["lnnAcl"] = DM_LNN;
373         context->accesser.aclProfiles[DM_LNN] = profile;
374     }
375     GetSrcProxyAclInfoForP2P(context, profile);
376 }
377 
GetSrcProxyAclInfoForP2P(std::shared_ptr<DmAuthContext> context,const DistributedDeviceProfile::AccessControlProfile & profile)378 void AuthSrcConfirmState::GetSrcProxyAclInfoForP2P(std::shared_ptr<DmAuthContext> context,
379     const DistributedDeviceProfile::AccessControlProfile &profile)
380 {
381     CHECK_NULL_VOID(context);
382     if (!context->IsProxyBind || context->subjectProxyOnes.empty()) {
383         return;
384     }
385     for (auto &app : context->subjectProxyOnes) {
386         if ((profile.GetAccesser().GetAccesserTokenId() == app.proxyAccesser.tokenId &&
387             Crypto::GetTokenIdHash(std::to_string(profile.GetAccessee().GetAccesseeTokenId())) ==
388             app.proxyAccessee.tokenIdHash) ||
389             (profile.GetAccessee().GetAccesseeTokenId() == app.proxyAccesser.tokenId &&
390             Crypto::GetTokenIdHash(std::to_string(profile.GetAccesser().GetAccesserTokenId())) ==
391             app.proxyAccessee.tokenIdHash)) {
392             std::string credId;
393             if (!IsAclHasCredential(profile, app.proxyAccesser.credInfoJson, credId)) {
394                 continue;
395             }
396             std::vector<std::string> appList;
397             JsonObject credInfoJsonObj;
398             if (!app.proxyAccesser.credInfoJson.empty()) {
399                 credInfoJsonObj.Parse(app.proxyAccesser.credInfoJson);
400             }
401             credInfoJsonObj[credId][FILED_AUTHORIZED_APP_LIST].Get(appList);
402             const size_t APP_LIST_SIZE = 2;
403             if (appList.size() < APP_LIST_SIZE ||
404                 std::find(appList.begin(), appList.end(),
405                     std::to_string(profile.GetAccesser().GetAccesserTokenId())) == appList.end() ||
406                 std::find(appList.begin(), appList.end(),
407                     std::to_string(profile.GetAccessee().GetAccesseeTokenId())) == appList.end()) {
408                 continue;
409             }
410             JsonObject aclTypeJson;
411             if (!app.proxyAccesser.aclTypeList.empty()) {
412                 aclTypeJson.Parse(app.proxyAccesser.aclTypeList);
413             }
414             aclTypeJson["pointTopointAcl"] = DM_POINT_TO_POINT;
415             app.proxyAccesser.aclTypeList = aclTypeJson.Dump();
416             app.proxyAccesser.aclProfiles[DM_POINT_TO_POINT] = profile;
417         }
418     }
419 }
420 
CheckCredIdInAcl(std::shared_ptr<DmAuthContext> context,const DistributedDeviceProfile::AccessControlProfile & profile,JsonObject & credInfo,uint32_t bindType)421 bool AuthSrcConfirmState::CheckCredIdInAcl(std::shared_ptr<DmAuthContext> context,
422     const DistributedDeviceProfile::AccessControlProfile &profile, JsonObject &credInfo, uint32_t bindType)
423 {
424     LOGI("start.");
425     std::string credId = profile.GetAccesser().GetAccesserCredentialIdStr();
426     if (!credInfo.Contains(credId)) {
427         credId = profile.GetAccessee().GetAccesseeCredentialIdStr();
428         if (!credInfo.Contains(credId)) {
429             LOGE("credInfoJson not contain credId %{public}s.", GetAnonyString(credId).c_str());
430             DeleteAclAndSk(context, profile);
431             return false;
432         }
433     }
434     if (credInfo.Contains(credId) && (!credInfo[credId].IsObject() || !credInfo[credId].Contains(FILED_CRED_TYPE) ||
435         !credInfo[credId][FILED_CRED_TYPE].IsNumberInteger())) {
436         LOGE("credId %{public}s contain credInfoJson invalid.", credId.c_str());
437         DeleteAcl(context, profile);
438         credInfo.Erase(credId);
439         return false;
440     }
441     bool checkResult = false;
442     switch (bindType) {
443         LOGI("bindType %{public}d.", bindType);
444         case DM_IDENTICAL_ACCOUNT:
445         case DM_SHARE:
446         case DM_LNN:
447             if (credInfo[credId][FILED_CRED_TYPE].Get<uint32_t>() == bindType) {
448                 checkResult = true;
449             } else {
450                 DeleteAcl(context, profile);
451             }
452             break;
453         case DM_POINT_TO_POINT:
454             CheckCredIdInAclForP2P(context, credId, profile, credInfo, bindType, checkResult);
455             break;
456         default:
457             break;
458     }
459     return checkResult;
460 }
461 
CheckCredIdInAclForP2P(std::shared_ptr<DmAuthContext> context,std::string & credId,const DistributedDeviceProfile::AccessControlProfile & profile,JsonObject & credInfo,uint32_t bindType,bool & checkResult)462 void AuthSrcConfirmState::CheckCredIdInAclForP2P(std::shared_ptr<DmAuthContext> context, std::string &credId,
463     const DistributedDeviceProfile::AccessControlProfile &profile, JsonObject &credInfo, uint32_t bindType,
464     bool &checkResult)
465 {
466     if (!DmAuthState::IsMatchCredentialAndP2pACL(credInfo, credId, profile)) {
467         LOGE("acl bindlevel and credential authorizedScope not match");
468         DeleteAcl(context, profile);
469         credInfo.Erase(credId);
470         return;
471     }
472     if (credInfo[credId][FILED_CRED_TYPE].Get<uint32_t>() == bindType) {
473         std::vector<std::string> appList;
474         credInfo[credId][FILED_AUTHORIZED_APP_LIST].Get(appList);
475         const size_t APP_LIST_SIZE = 2;
476         if (appList.size() >= APP_LIST_SIZE &&
477             ((std::to_string(profile.GetAccesser().GetAccesserTokenId()) == appList[0] &&
478             std::to_string(profile.GetAccessee().GetAccesseeTokenId()) == appList[1]) ||
479             (std::to_string(profile.GetAccesser().GetAccesserTokenId()) == appList[1] &&
480             std::to_string(profile.GetAccessee().GetAccesseeTokenId()) == appList[0]))) {
481             checkResult = true;
482         } else {
483             DeleteAclAndSk(context, profile);
484         }
485     }
486 }
487 
IdenticalAccountAclCompare(std::shared_ptr<DmAuthContext> context,const DistributedDeviceProfile::Accesser & accesser,const DistributedDeviceProfile::Accessee & accessee)488 bool AuthSrcConfirmState::IdenticalAccountAclCompare(std::shared_ptr<DmAuthContext> context,
489     const DistributedDeviceProfile::Accesser &accesser, const DistributedDeviceProfile::Accessee &accessee)
490 {
491     LOGI("start.");
492     return accesser.GetAccesserDeviceId() == context->accesser.deviceId &&
493         accesser.GetAccesserUserId() == context->accesser.userId &&
494         Crypto::GetUdidHash(accessee.GetAccesseeDeviceId()) == context->accessee.deviceIdHash;
495 }
496 
ShareAclCompare(std::shared_ptr<DmAuthContext> context,const DistributedDeviceProfile::Accesser & accesser,const DistributedDeviceProfile::Accessee & accessee)497 bool AuthSrcConfirmState::ShareAclCompare(std::shared_ptr<DmAuthContext> context,
498     const DistributedDeviceProfile::Accesser &accesser, const DistributedDeviceProfile::Accessee &accessee)
499 {
500     LOGI("start.");
501     return accesser.GetAccesserDeviceId() == context->accesser.deviceId &&
502         accesser.GetAccesserUserId() == context->accesser.userId &&
503         Crypto::GetUdidHash(accessee.GetAccesseeDeviceId()) == context->accessee.deviceIdHash;
504 }
505 
Point2PointAclCompare(std::shared_ptr<DmAuthContext> context,const DistributedDeviceProfile::Accesser & accesser,const DistributedDeviceProfile::Accessee & accessee)506 bool AuthSrcConfirmState::Point2PointAclCompare(std::shared_ptr<DmAuthContext> context,
507     const DistributedDeviceProfile::Accesser &accesser, const DistributedDeviceProfile::Accessee &accessee)
508 {
509     LOGI("start.");
510     return (accesser.GetAccesserDeviceId() == context->accesser.deviceId &&
511         accesser.GetAccesserUserId() == context->accesser.userId &&
512         accesser.GetAccesserTokenId() == context->accesser.tokenId &&
513         Crypto::GetUdidHash(accessee.GetAccesseeDeviceId()) == context->accessee.deviceIdHash &&
514         Crypto::GetTokenIdHash(std::to_string(accessee.GetAccesseeTokenId())) == context->accessee.tokenIdHash) ||
515         (accessee.GetAccesseeDeviceId() == context->accesser.deviceId &&
516         accessee.GetAccesseeUserId() == context->accesser.userId &&
517         accessee.GetAccesseeTokenId() == context->accesser.tokenId &&
518         Crypto::GetUdidHash(accesser.GetAccesserDeviceId()) == context->accessee.deviceIdHash &&
519         Crypto::GetTokenIdHash(std::to_string(accesser.GetAccesserTokenId())) == context->accessee.tokenIdHash);
520 }
521 
LnnAclCompare(std::shared_ptr<DmAuthContext> context,const DistributedDeviceProfile::Accesser & accesser,const DistributedDeviceProfile::Accessee & accessee)522 bool AuthSrcConfirmState::LnnAclCompare(std::shared_ptr<DmAuthContext> context,
523     const DistributedDeviceProfile::Accesser &accesser, const DistributedDeviceProfile::Accessee &accessee)
524 {
525     LOGI("start.");
526     return ((accesser.GetAccesserDeviceId() == context->accesser.deviceId &&
527         accesser.GetAccesserUserId() == context->accesser.userId) ||
528         (accessee.GetAccesseeDeviceId() == context->accesser.deviceId &&
529         accessee.GetAccesseeUserId() == context->accesser.userId)) &&
530         accesser.GetAccesserTokenId() == 0 && accesser.GetAccesserBundleName() == "" &&
531         (Crypto::GetUdidHash(accessee.GetAccesseeDeviceId()) == context->accessee.deviceIdHash ||
532         Crypto::GetUdidHash(accesser.GetAccesserDeviceId()) == context->accessee.deviceIdHash) &&
533         accessee.GetAccesseeTokenId() == 0 && accessee.GetAccesseeBundleName() == "";
534 }
535 
GetSrcCredentialInfo(std::shared_ptr<DmAuthContext> context,JsonObject & credInfo)536 void AuthSrcConfirmState::GetSrcCredentialInfo(std::shared_ptr<DmAuthContext> context, JsonObject &credInfo)
537 {
538     LOGI("start.");
539     CHECK_NULL_VOID(context);
540     // get identical credential
541     if (context->accesser.accountIdHash == context->accessee.accountIdHash) {
542         GetIdenticalCredentialInfo(context, credInfo);
543     }
544     // get share credential
545     if (context->accesser.accountIdHash != context->accessee.accountIdHash &&
546         context->accesser.accountIdHash != Crypto::GetAccountIdHash16("ohosAnonymousUid") &&
547         context->accessee.accountIdHash != Crypto::GetAccountIdHash16("ohosAnonymousUid")) {
548         GetShareCredentialInfo(context, credInfo);
549         GetP2PCredentialInfo(context, credInfo);
550     }
551     // get point_to_point credential
552     if (context->accesser.accountIdHash == Crypto::GetAccountIdHash16("ohosAnonymousUid") ||
553         context->accessee.accountIdHash == Crypto::GetAccountIdHash16("ohosAnonymousUid")) {
554         GetP2PCredentialInfo(context, credInfo);
555     }
556     std::vector<std::string> deleteCredInfo;
557     for (auto &item : credInfo.Items()) { // id1:json1, id2:json2, id3:json3
558         if (!item.Contains(FILED_CRED_ID) || !item[FILED_CRED_ID].IsString()) {
559             continue;
560         }
561         uint32_t credType = DmAuthState::GetCredentialType(context, item);
562         if (credType == DM_INVALIED_TYPE || !item.Contains(FILED_CRED_TYPE) ||
563             !item[FILED_CRED_TYPE].IsNumberInteger()) {
564             deleteCredInfo.push_back(item[FILED_CRED_ID].Get<std::string>());
565             continue;
566         }
567         item[FILED_CRED_TYPE] = credType;
568     }
569     for (const auto &item : deleteCredInfo) {
570         credInfo.Erase(item);
571     }
572 }
573 
GetIdenticalCredentialInfo(std::shared_ptr<DmAuthContext> context,JsonObject & credInfo)574 void AuthSrcConfirmState::GetIdenticalCredentialInfo(std::shared_ptr<DmAuthContext> context,
575     JsonObject &credInfo)
576 {
577     LOGI("start.");
578     CHECK_NULL_VOID(context);
579     JsonObject queryParams;
580     queryParams[FILED_DEVICE_ID] = context->accesser.deviceId;
581     queryParams[FILED_USER_ID] = MultipleUserConnector::GetOhosAccountNameByUserId(context->accesser.userId);
582     queryParams[FILED_CRED_TYPE] = DM_AUTH_CREDENTIAL_ACCOUNT_RELATED;
583     CHECK_NULL_VOID(context->hiChainAuthConnector);
584     int32_t ret = context->hiChainAuthConnector->QueryCredentialInfo(context->accesser.userId, queryParams, credInfo);
585     if (ret != DM_OK) {
586         LOGE("QueryCredentialInfo failed ret %{public}d.", ret);
587     }
588 }
589 
GetShareCredentialInfo(std::shared_ptr<DmAuthContext> context,JsonObject & credInfo)590 void AuthSrcConfirmState::GetShareCredentialInfo(std::shared_ptr<DmAuthContext> context,
591     JsonObject &credInfo)
592 {
593     LOGI("start.");
594     CHECK_NULL_VOID(context);
595     JsonObject queryParams;
596     queryParams[FILED_DEVICE_ID_HASH] = context->accessee.deviceIdHash;
597     queryParams[FILED_PEER_USER_SPACE_ID] = std::to_string(context->accessee.userId);
598     queryParams[FILED_CRED_TYPE] = DM_AUTH_CREDENTIAL_ACCOUNT_ACROSS;
599     CHECK_NULL_VOID(context->hiChainAuthConnector);
600     int32_t ret = context->hiChainAuthConnector->QueryCredentialInfo(context->accesser.userId, queryParams, credInfo);
601     if (ret != DM_OK) {
602         LOGE("QueryCredentialInfo failed ret %{public}d.", ret);
603     }
604 }
605 
GetP2PCredentialInfo(std::shared_ptr<DmAuthContext> context,JsonObject & credInfo)606 void AuthSrcConfirmState::GetP2PCredentialInfo(std::shared_ptr<DmAuthContext> context,
607     JsonObject &credInfo)
608 {
609     LOGI("start.");
610     CHECK_NULL_VOID(context);
611     JsonObject queryParams;
612     queryParams[FILED_DEVICE_ID_HASH] = context->accessee.deviceIdHash;
613     queryParams[FILED_PEER_USER_SPACE_ID] = std::to_string(context->accessee.userId);
614     queryParams[FILED_CRED_TYPE] = DM_AUTH_CREDENTIAL_ACCOUNT_UNRELATED;
615     queryParams[FILED_CRED_OWNER] = "DM";
616     CHECK_NULL_VOID(context->hiChainAuthConnector);
617     int32_t ret = context->hiChainAuthConnector->QueryCredentialInfo(context->accesser.userId, queryParams, credInfo);
618     if (ret != DM_OK) {
619         LOGE("QueryCredentialInfo failed ret %{public}d.", ret);
620     }
621 }
622 
GenerateCertificate(std::shared_ptr<DmAuthContext> context)623 void AuthSrcConfirmState::GenerateCertificate(std::shared_ptr<DmAuthContext> context)
624 {
625     if (context == nullptr) {
626         LOGE("context is nullptr!");
627         return;
628     }
629 #ifdef DEVICE_MANAGER_COMMON_FLAG
630     context->accesser.isCommonFlag = true;
631     LOGI("open device do not generate cert!");
632     context->accesser.cert = "common";
633 #else
634     DmCertChain dmCertChain;
635     int32_t certRet = -1;
636     if (CompareVersion(context->accessee.dmVersion, DM_VERSION_5_1_3)) {
637         certRet = AuthCert::GetInstance().GenerateCertificateV2(dmCertChain, context->accessee.certRandom);
638     } else {
639         certRet = AuthCert::GetInstance().GenerateCertificate(dmCertChain);
640     }
641     if (certRet != DM_OK) {
642         LOGE("generate cert fail, certRet = %{public}d", certRet);
643         return;
644     }
645     {
646         std::lock_guard<std::mutex> lock(context->certMtx_);
647         context->accesser.cert = AuthAttestCommon::GetInstance().SerializeDmCertChain(&dmCertChain);
648     }
649     context->certCV_.notify_all();
650     AuthAttestCommon::GetInstance().FreeDmCertChain(dmCertChain);
651 #endif
652     return;
653 }
654 
Action(std::shared_ptr<DmAuthContext> context)655 int32_t AuthSrcConfirmState::Action(std::shared_ptr<DmAuthContext> context)
656 {
657     LOGI("AuthSrcConfirmState start.");
658     CHECK_NULL_RETURN(context, ERR_DM_POINT_NULL);
659     context->timer->DeleteTimer(std::string(NEGOTIATE_TIMEOUT_TASK));
660     ResetBindLevel(context);
661     GetCustomDescBySinkLanguage(context);
662     context->accessee.isOnline = SoftbusCache::GetInstance().CheckIsOnline(context->accessee.deviceIdHash);
663     JsonObject credInfo;
664     GetSrcCredentialInfo(context, credInfo);
665     JsonObject aclInfo;
666     GetSrcAclInfo(context, credInfo, aclInfo);
667     context->accesser.aclTypeList = aclInfo.Dump();
668     JsonObject credTypeJson;
669     GetSrcCredType(context, credInfo, aclInfo, credTypeJson);
670     context->accesser.credTypeList = credTypeJson.Dump();
671     // update credType negotiate result
672     JsonObject credTypeNegoResult;
673     NegotiateCredential(context, credTypeNegoResult);
674     context->accesser.credTypeList = credTypeNegoResult.Dump();
675     NegotiateProxyCredential(context);
676     // update acl negotiate result
677     JsonObject aclNegoResult;
678     NegotiateAcl(context, aclNegoResult);
679     context->accesser.aclTypeList = aclNegoResult.Dump();
680     NegotiateProxyAcl(context);
681     NegotiateUltrasonic(context);
682     context->authMessageProcessor->CreateAndSendMsg(MSG_TYPE_REQ_USER_CONFIRM, context);
683     // generate cert sync
684     ffrt::submit([=]() { GenerateCertificate(context);});
685     context->listener->OnAuthResult(context->processInfo, context->peerTargetId.deviceId, context->accessee.tokenIdHash,
686         static_cast<int32_t>(STATUS_DM_SHOW_AUTHORIZE_UI), DM_OK);
687     context->listener->OnBindResult(context->processInfo, context->peerTargetId,
688         DM_OK, static_cast<int32_t>(STATUS_DM_SHOW_AUTHORIZE_UI), "");
689     context->timer->StartTimer(std::string(CONFIRM_TIMEOUT_TASK),
690         DmAuthState::GetTaskTimeout(context, CONFIRM_TIMEOUT_TASK, CONFIRM_TIMEOUT),
691         [context] (std::string name) {
692             HandleAuthenticateTimeout(context, name);
693         });
694     return DM_OK;
695 }
696 
NegotiateUltrasonic(std::shared_ptr<DmAuthContext> context)697 void AuthSrcConfirmState::NegotiateUltrasonic(std::shared_ptr<DmAuthContext> context)
698 {
699     CHECK_NULL_VOID(context);
700     if (context->authType != AUTH_TYPE_PIN_ULTRASONIC) {
701         LOGE("auth type not ultrasonic.");
702         return;
703     }
704     if (context->accessee.extraInfo.empty()) {
705         LOGE("extraInfo empty.");
706         return;
707     }
708     JsonObject json;
709     json.Parse(context->accessee.extraInfo);
710     if (json.IsDiscarded()) {
711         LOGE("extraInfo invalid.");
712         return;
713     }
714     bool isSupportUltrasonic = true;
715     if (IsBool(json, TAG_IS_SUPPORT_ULTRASONIC)) {
716         isSupportUltrasonic = json[TAG_IS_SUPPORT_ULTRASONIC].Get<bool>();
717     }
718     if (!isSupportUltrasonic) {
719         context->authType = AUTH_TYPE_PIN;
720     }
721 }
722 
ResetBindLevel(std::shared_ptr<DmAuthContext> context)723 void AuthSrcConfirmState::ResetBindLevel(std::shared_ptr<DmAuthContext> context)
724 {
725     CHECK_NULL_VOID(context);
726     if (context->accesser.bindLevel != DmRole::DM_ROLE_USER || !context->IsProxyBind) {
727         return;
728     }
729     context->accesser.bindLevel = DmRole::DM_ROLE_SA;
730 }
731 
GetCustomDescBySinkLanguage(std::shared_ptr<DmAuthContext> context)732 void AuthSrcConfirmState::GetCustomDescBySinkLanguage(std::shared_ptr<DmAuthContext> context)
733 {
734     if (context == nullptr || context->customData.empty()) {
735         LOGI("customDesc is empty.");
736         return;
737     }
738     context->customData = DmLanguageManager::GetInstance().GetTextBySystemLanguage(context->customData,
739         context->accessee.language);
740 }
741 
GetStateType()742 DmAuthStateType AuthSinkConfirmState::GetStateType()
743 {
744     return DmAuthStateType::AUTH_SINK_CONFIRM_STATE;
745 }
746 
ShowConfigDialog(std::shared_ptr<DmAuthContext> context)747 int32_t AuthSinkConfirmState::ShowConfigDialog(std::shared_ptr<DmAuthContext> context)
748 {
749     LOGI("AuthSinkConfirmState::ShowConfigDialog start");
750 
751     if (context->authType == AUTH_TYPE_PIN_ULTRASONIC &&
752         context->ultrasonicInfo == DmUltrasonicInfo::DM_Ultrasonic_Invalid) {
753         LOGE("AuthSinkConfirmState::ShowConfigDialog ultrasonicInfo invalid.");
754         return STOP_BIND;
755     }
756 
757     NodeBasicInfo nodeBasicInfo;
758     int32_t result = GetLocalNodeDeviceInfo(DM_PKG_NAME, &nodeBasicInfo);
759     if (result != SOFTBUS_OK) {
760         LOGE("GetLocalNodeDeviceInfo from dsofbus fail, result=%{public}d", result);
761         return STOP_BIND;
762     }
763 
764     if (nodeBasicInfo.deviceTypeId == TYPE_TV_ID) {
765         int32_t ret = AuthManagerBase::EndDream();
766         if (ret != DM_OK) {
767             LOGE("fail to end dream, err:%{public}d", ret);
768             return STOP_BIND;
769         }
770     } else if (IsScreenLocked()) {
771         LOGE("AuthSinkConfirmState::ShowStartAuthDialog screen is locked.");
772         context->reason = ERR_DM_BIND_USER_CANCEL;
773         context->authStateMachine->NotifyEventFinish(DmEventType::ON_FAIL);
774         return STOP_BIND;
775     }
776     JsonObject jsonObj;
777     jsonObj[TAG_CUSTOM_DESCRIPTION] = context->customData;
778     jsonObj[TAG_LOCAL_DEVICE_TYPE] = context->accesser.deviceType;
779     jsonObj[TAG_REQUESTER] = context->accesser.deviceName;
780     jsonObj[TAG_USER_ID] = context->accessee.userId;    // Reserved
781     jsonObj[TAG_HOST_PKGLABEL] = context->pkgLabel;
782     GetBundleLabel(context);
783     CreateProxyData(context, jsonObj);
784     const std::string params = jsonObj.Dump();
785     DmDialogManager::GetInstance().ShowConfirmDialog(params);
786 
787     LOGI("AuthSinkConfirmState::ShowConfigDialog end");
788     return DM_OK;
789 }
790 
GetBundleLabel(std::shared_ptr<DmAuthContext> context)791 void AuthSinkConfirmState::GetBundleLabel(std::shared_ptr<DmAuthContext> context)
792 {
793     CHECK_NULL_VOID(context);
794     if (!context->IsProxyBind || context->subjectProxyOnes.empty()) {
795         return;
796     }
797     auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
798     if (samgr == nullptr) {
799         LOGE("Get ability manager failed");
800         return;
801     }
802 
803     sptr<IRemoteObject> object = samgr->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
804     if (object == nullptr) {
805         LOGE("object is NULL.");
806         return;
807     }
808 
809     sptr<OHOS::AppExecFwk::IBundleMgr> bms = iface_cast<OHOS::AppExecFwk::IBundleMgr>(object);
810     if (bms == nullptr) {
811         LOGE("bundle manager service is NULL.");
812         return;
813     }
814 
815     auto bundleResourceProxy = bms->GetBundleResourceProxy();
816     if (bundleResourceProxy == nullptr) {
817         LOGE("GetBundleResourceProxy fail");
818         return;
819     }
820     for (auto &app : context->subjectProxyOnes) {
821         AppExecFwk::BundleResourceInfo resourceInfo;
822         auto result = bundleResourceProxy->GetBundleResourceInfo(app.proxyAccessee.bundleName,
823             static_cast<uint32_t>(OHOS::AppExecFwk::ResourceFlag::GET_RESOURCE_INFO_ALL), resourceInfo);
824         if (result == ERR_OK) {
825             app.proxyAccessee.pkgLabel = resourceInfo.label;
826         }
827     }
828 }
829 
CreateProxyData(std::shared_ptr<DmAuthContext> context,JsonObject & jsonObj)830 int32_t AuthSinkConfirmState::CreateProxyData(std::shared_ptr<DmAuthContext> context, JsonObject &jsonObj)
831 {
832     CHECK_NULL_RETURN(context, ERR_DM_POINT_NULL);
833     if (!context->IsProxyBind || context->subjectProxyOnes.empty()) {
834         jsonObj[PARAM_KEY_IS_PROXY_BIND] = false;
835         return DM_OK;
836     }
837     jsonObj[PARAM_KEY_IS_PROXY_BIND] = context->IsProxyBind;
838     JsonObject allProxyObj(JsonCreateType::JSON_CREATE_TYPE_ARRAY);
839     for (const auto &app : context->subjectProxyOnes) {
840         JsonObject object;
841         object[TAG_HOST_PKGLABEL] = !app.proxyAccessee.pkgLabel.empty() ? app.proxyAccessee.pkgLabel :
842             app.proxyAccessee.bundleName;
843         object[TAG_BUNDLE_NAME] = app.proxyAccessee.bundleName;
844         object[BUNDLE_INFO] = app.proxyAccessee.bundleInfo;
845         allProxyObj.PushBack(object);
846     }
847     jsonObj[APP_USER_DATA] = allProxyObj.Dump();
848     jsonObj[TITLE] = context->title;
849     return DM_OK;
850 }
851 
NegotiateCredential(std::shared_ptr<DmAuthContext> context,JsonObject & credTypeNegoResult)852 void AuthSinkConfirmState::NegotiateCredential(std::shared_ptr<DmAuthContext> context, JsonObject &credTypeNegoResult)
853 {
854     CHECK_NULL_VOID(context);
855     JsonObject accesseeCredTypeList;
856     accesseeCredTypeList.Parse(context->accessee.credTypeList);
857     JsonObject accesserCredTypeList;
858     accesserCredTypeList.Parse(context->accesser.credTypeList);
859     if (accesseeCredTypeList.IsDiscarded() || accesserCredTypeList.IsDiscarded()) {
860         LOGE("CredTypeList invalid.");
861         return;
862     }
863     if (accesseeCredTypeList.Contains("identicalCredType") && accesserCredTypeList.Contains("identicalCredType")) {
864         LOGI("have identical credential.");
865         credTypeNegoResult["identicalCredType"] = DM_IDENTICAL_ACCOUNT;
866         context->accessee.isGenerateLnnCredential = false;
867     }
868     if (accesseeCredTypeList.Contains("shareCredType") && accesserCredTypeList.Contains("shareCredType")) {
869         LOGI("have share credential.");
870         credTypeNegoResult["shareCredType"] = DM_SHARE;
871         context->accessee.isGenerateLnnCredential = false;
872     }
873     if (accesseeCredTypeList.Contains("pointTopointCredType") &&
874         accesserCredTypeList.Contains("pointTopointCredType")) {
875         LOGI("have point_to_point credential.");
876         credTypeNegoResult["pointTopointCredType"] = DM_POINT_TO_POINT;
877     }
878     if (accesseeCredTypeList.Contains("lnnCredType") && accesserCredTypeList.Contains("lnnCredType")) {
879         LOGI("have lnn credential.");
880         credTypeNegoResult["lnnCredType"] = DM_LNN;
881         context->accessee.isGenerateLnnCredential = false;
882     }
883     return;
884 }
885 
NegotiateProxyCredential(std::shared_ptr<DmAuthContext> context)886 void AuthSinkConfirmState::NegotiateProxyCredential(std::shared_ptr<DmAuthContext> context)
887 {
888     CHECK_NULL_VOID(context);
889     if (!context->IsProxyBind || context->subjectProxyOnes.empty()) {
890         return;
891     }
892     for (auto item = context->subjectProxyOnes.begin(); item != context->subjectProxyOnes.end(); ++item) {
893         JsonObject credTypeNegoResult;
894         JsonObject accesseeCredTypeList;
895         accesseeCredTypeList.Parse(item->proxyAccessee.credTypeList);
896         JsonObject accesserCredTypeList;
897         accesserCredTypeList.Parse(item->proxyAccesser.credTypeList);
898         if (accesseeCredTypeList.IsDiscarded() || accesserCredTypeList.IsDiscarded()) {
899             item->proxyAccessee.credTypeList = credTypeNegoResult.Dump();
900             continue;
901         }
902         if (accesseeCredTypeList.Contains("pointTopointCredType") &&
903             accesserCredTypeList.Contains("pointTopointCredType")) {
904             credTypeNegoResult["pointTopointCredType"] = DM_POINT_TO_POINT;
905             item->proxyAccessee.credTypeList = credTypeNegoResult.Dump();
906             continue;
907         }
908         item->proxyAccessee.credTypeList = credTypeNegoResult.Dump();
909     }
910 }
911 
NegotiateAcl(std::shared_ptr<DmAuthContext> context,JsonObject & aclNegoResult)912 void AuthSinkConfirmState::NegotiateAcl(std::shared_ptr<DmAuthContext> context, JsonObject &aclNegoResult)
913 {
914     CHECK_NULL_VOID(context);
915     JsonObject accesseeAclList;
916     accesseeAclList.Parse(context->accessee.aclTypeList);
917     JsonObject accesserAclList;
918     accesserAclList.Parse(context->accesser.aclTypeList);
919     if (accesseeAclList.IsDiscarded() || accesserAclList.IsDiscarded()) {
920         LOGE("aclList invalid.");
921         return;
922     }
923     if (accesseeAclList.Contains("identicalAcl") && accesserAclList.Contains("identicalAcl")) {
924         LOGI("have identical acl.");
925         aclNegoResult["identicalAcl"] = DM_IDENTICAL_ACCOUNT;
926         context->accessee.isPutLnnAcl = false;
927         context->accessee.isAuthed = true;
928         context->accessee.isUserLevelAuthed = true;
929     }
930     if (accesseeAclList.Contains("shareCredType") && accesserAclList.Contains("shareCredType")) {
931         LOGI("have share acl.");
932         aclNegoResult["shareAcl"] = DM_SHARE;
933         context->accessee.isPutLnnAcl = false;
934         context->accessee.isAuthed = true;
935         context->accessee.isUserLevelAuthed = true;
936     }
937     if (accesseeAclList.Contains("pointTopointAcl") && accesserAclList.Contains("pointTopointAcl")) {
938         LOGI("have point_to_point acl.");
939         aclNegoResult["pointTopointAcl"] = DM_POINT_TO_POINT;
940         context->accessee.isAuthed = true;
941     }
942     if (accesseeAclList.Contains("lnnAcl") && accesserAclList.Contains("lnnAcl")) {
943         LOGI("have lnn acl.");
944         aclNegoResult["lnnAcl"] = DM_LNN;
945         context->accessee.isPutLnnAcl = false;
946     }
947 }
948 
NegotiateProxyAcl(std::shared_ptr<DmAuthContext> context)949 void AuthSinkConfirmState::NegotiateProxyAcl(std::shared_ptr<DmAuthContext> context)
950 {
951     CHECK_NULL_VOID(context);
952     if (!context->IsProxyBind || context->subjectProxyOnes.empty()) {
953         return;
954     }
955     for (auto item = context->subjectProxyOnes.begin(); item != context->subjectProxyOnes.end(); ++item) {
956         JsonObject aclNegoResult;
957         JsonObject accesseeAclList;
958         if (!item->proxyAccessee.aclTypeList.empty()) {
959             accesseeAclList.Parse(item->proxyAccessee.aclTypeList);
960         }
961         JsonObject accesserAclList;
962         if (!item->proxyAccesser.aclTypeList.empty()) {
963             accesserAclList.Parse(item->proxyAccesser.aclTypeList);
964         }
965         if (accesseeAclList.IsDiscarded() || accesserAclList.IsDiscarded()) {
966             item->proxyAccessee.aclTypeList = aclNegoResult.Dump();
967             continue;
968         }
969         if (accesseeAclList.Contains("pointTopointAcl") && accesserAclList.Contains("pointTopointAcl")) {
970             LOGI("have point_to_point acl bundleName: %{public}s.", item->proxyAccesser.bundleName.c_str());
971             aclNegoResult["pointTopointAcl"] = DM_POINT_TO_POINT;
972             item->proxyAccessee.aclTypeList = aclNegoResult.Dump();
973             item->proxyAccessee.isAuthed = true;
974             continue;
975         }
976         item->proxyAccessee.aclTypeList = aclNegoResult.Dump();
977     }
978 }
979 
MatchFallBackCandidateList(std::shared_ptr<DmAuthContext> context,DmAuthType authType)980 void AuthSinkConfirmState::MatchFallBackCandidateList(
981     std::shared_ptr<DmAuthContext> context, DmAuthType authType)
982 {
983     for (size_t i = 0; i < MAX_FALLBACK_LOOPKUP_TIMES; i++) {
984         auto it = g_pinAuthTypeFallBackMap.find({context->accessee.bundleName, authType});
985         if (it != g_pinAuthTypeFallBackMap.end()) {
986             authType = it->second;
987             context->authTypeList.push_back(authType);
988         } else {
989             break;
990         }
991     }
992 }
993 
ReadServiceInfo(std::shared_ptr<DmAuthContext> context)994 void AuthSinkConfirmState::ReadServiceInfo(std::shared_ptr<DmAuthContext> context)
995 {
996     // query ServiceInfo by accessee.pkgName and authType from client
997     OHOS::DistributedDeviceProfile::LocalServiceInfo srvInfo;
998     auto ret = DeviceProfileConnector::GetInstance().GetLocalServiceInfoByBundleNameAndPinExchangeType(
999         context->accessee.pkgName, context->authType, srvInfo);
1000     if (ret == OHOS::DistributedDeviceProfile::DP_SUCCESS) {
1001         LOGI("AuthSinkConfirmState::ReadServiceInfo found");
1002         // ServiceInfo found
1003         context->serviceInfoFound = true;
1004         // read authBoxType
1005         context->authBoxType = static_cast<DMLocalServiceInfoAuthBoxType>(srvInfo.GetAuthBoxType());
1006         if (DmAuthState::IsImportAuthCodeCompatibility(context->authType)) {
1007             std::string pinCode = srvInfo.GetPinCode(); // read pincode
1008             if (AuthSinkStatePinAuthComm::IsPinCodeValid(pinCode)) {
1009                 context->pinCode = pinCode;
1010             }
1011             srvInfo.SetPinCode("******");
1012             DeviceProfileConnector::GetInstance().UpdateLocalServiceInfo(srvInfo);
1013         }
1014         if (context->authBoxType == DMLocalServiceInfoAuthBoxType::SKIP_CONFIRM) { // no authorization box
1015             int32_t confirmOperation = srvInfo.GetAuthType(); // read confirmOperation
1016             if (confirmOperation == static_cast<int32_t>(DMLocalServiceInfoAuthType::TRUST_ONETIME)) {
1017                 context->confirmOperation = UiAction::USER_OPERATION_TYPE_ALLOW_AUTH;
1018             } else if (confirmOperation == static_cast<int32_t>(DMLocalServiceInfoAuthType::CANCEL)) {
1019                 context->confirmOperation = UiAction::USER_OPERATION_TYPE_CANCEL_AUTH;
1020             } else if (confirmOperation == static_cast<int32_t>(DMLocalServiceInfoAuthType::TRUST_ALWAYS)) {
1021                 context->confirmOperation = UiAction::USER_OPERATION_TYPE_ALLOW_AUTH_ALWAYS;
1022             } else {
1023                 context->confirmOperation = UiAction::USER_OPERATION_TYPE_CANCEL_AUTH;
1024             }
1025         }
1026         context->customData = srvInfo.GetDescription(); // read customData
1027         context->srvExtarInfo = srvInfo.GetExtraInfo();
1028     } else if (DmAuthState::IsImportAuthCodeCompatibility(context->authType) &&
1029         AuthSinkStatePinAuthComm::IsAuthCodeReady(context)) {
1030         // only special scenarios can import pincode
1031         context->authBoxType = DMLocalServiceInfoAuthBoxType::SKIP_CONFIRM; // no authorization box
1032     } else {
1033         // not special scenarios, reset confirmOperation to cancel
1034         context->confirmOperation = UiAction::USER_OPERATION_TYPE_CANCEL_AUTH;
1035         context->authBoxType = DMLocalServiceInfoAuthBoxType::STATE3; // default: tristate box
1036     }
1037 }
1038 
Action(std::shared_ptr<DmAuthContext> context)1039 int32_t AuthSinkConfirmState::Action(std::shared_ptr<DmAuthContext> context)
1040 {
1041     LOGI("start.");
1042     CHECK_NULL_RETURN(context, ERR_DM_POINT_NULL);
1043     JsonObject credTypeNegoResult;
1044     JsonObject aclNegoResult;
1045     NegotiateCredential(context, credTypeNegoResult);
1046     context->accessee.credTypeList = credTypeNegoResult.Dump();
1047     NegotiateProxyCredential(context);
1048     NegotiateAcl(context, aclNegoResult);
1049     context->accessee.aclTypeList = aclNegoResult.Dump();
1050     NegotiateProxyAcl(context);
1051     if (credTypeNegoResult.Dump() != context->accesser.credTypeList ||
1052         aclNegoResult.Dump() != context->accesser.aclTypeList) {
1053         LOGE("compability negotiate not match.");
1054         context->reason = ERR_DM_CAPABILITY_NEGOTIATE_FAILED;
1055         return ERR_DM_FAILED;
1056     }
1057     if (!ProcessServerAuthorize(context)) {
1058         LOGE("no srvExtarInfo");
1059         context->reason = ERR_DM_AUTH_PEER_REJECT;
1060         return ERR_DM_FAILED;
1061     }
1062     int32_t ret = NegotiateProcess::GetInstance().HandleNegotiateResult(context);
1063     if (ret != DM_OK) {
1064         LOGE("HandleNegotiateResult failed ret %{public}d.", ret);
1065         context->reason = ret;
1066         return ret;
1067     }
1068     if (IsNeedBind(context)) {
1069         return ProcessBindAuthorize(context);
1070     } else {
1071         return ProcessNoBindAuthorize(context);
1072     }
1073 }
1074 
ProcessBindAuthorize(std::shared_ptr<DmAuthContext> context)1075 int32_t AuthSinkConfirmState::ProcessBindAuthorize(std::shared_ptr<DmAuthContext> context)
1076 {
1077     LOGI("start.");
1078     CHECK_NULL_RETURN(context, ERR_DM_POINT_NULL);
1079     ReadServiceInfo(context);
1080     context->authTypeList.clear();
1081     context->authTypeList.push_back(context->authType);
1082     if (context->authType == AUTH_TYPE_PIN_ULTRASONIC) {
1083         context->authTypeList.push_back(AUTH_TYPE_PIN);
1084     } else {
1085         MatchFallBackCandidateList(context, context->authType);
1086     }
1087     if ((DmAuthState::IsImportAuthCodeCompatibility(context->authType) ||
1088         context->authType == DmAuthType::AUTH_TYPE_PIN_ULTRASONIC) &&
1089         (context->serviceInfoFound || AuthSinkStatePinAuthComm::IsAuthCodeReady(context)) &&
1090         context->authBoxType == DMLocalServiceInfoAuthBoxType::SKIP_CONFIRM) {
1091         context->authMessageProcessor->CreateAndSendMsg(MSG_TYPE_RESP_USER_CONFIRM, context);
1092         context->authStateMachine->TransitionTo(std::make_shared<AuthSinkPinNegotiateStartState>());
1093         return DM_OK;
1094     }
1095     if ((context->authType == DmAuthType::AUTH_TYPE_PIN || context->authType == DmAuthType::AUTH_TYPE_NFC ||
1096         context->authType == DmAuthType::AUTH_TYPE_PIN_ULTRASONIC) &&
1097         context->authBoxType == DMLocalServiceInfoAuthBoxType::STATE3) {
1098         return ProcessUserAuthorize(context);
1099     }
1100     context->confirmOperation = UiAction::USER_OPERATION_TYPE_CANCEL_AUTH;
1101     return ERR_DM_FAILED;
1102 }
1103 
ProcessUserAuthorize(std::shared_ptr<DmAuthContext> context)1104 int32_t AuthSinkConfirmState::ProcessUserAuthorize(std::shared_ptr<DmAuthContext> context)
1105 {
1106     CHECK_NULL_RETURN(context, ERR_DM_POINT_NULL);
1107     context->timer->DeleteTimer(std::string(WAIT_REQUEST_TIMEOUT_TASK));
1108     if (ShowConfigDialog(context) != DM_OK) {
1109         LOGE("ShowConfigDialog failed");
1110         context->reason = ERR_DM_SHOW_CONFIRM_FAILED;
1111         return ERR_DM_FAILED;
1112     }
1113     if (DmEventType::ON_USER_OPERATION !=
1114         context->authStateMachine->WaitExpectEvent(DmEventType::ON_USER_OPERATION)) {
1115         LOGE("AuthSinkConfirmState::Action ON_USER_OPERATION err");
1116         return ERR_DM_FAILED;
1117     }
1118     if (context->confirmOperation == USER_OPERATION_TYPE_CANCEL_AUTH) {
1119         LOGE("AuthSinkConfirmState::Action USER_OPERATION_TYPE_CANCEL_AUTH");
1120         context->reason = ERR_DM_AUTH_PEER_REJECT;
1121         return ERR_DM_FAILED;
1122     }
1123     if (!ProcessUserOption(context, context->userOperationParam)) {
1124         LOGE("user reject");
1125         context->reason = ERR_DM_AUTH_PEER_REJECT;
1126         return ERR_DM_FAILED;
1127     }
1128     context->authMessageProcessor->CreateAndSendMsg(MSG_TYPE_RESP_USER_CONFIRM, context);
1129     context->authStateMachine->TransitionTo(std::make_shared<AuthSinkPinNegotiateStartState>());
1130     return DM_OK;
1131 }
1132 
ProcessUserOption(std::shared_ptr<DmAuthContext> context,const std::string & authorizeInfo)1133 bool AuthSinkConfirmState::ProcessUserOption(std::shared_ptr<DmAuthContext> context,
1134     const std::string &authorizeInfo)
1135 {
1136     if (context == nullptr) {
1137         return false;
1138     }
1139     if (!context->IsProxyBind) {
1140         return true;
1141     }
1142     if (authorizeInfo.empty() && !context->IsCallingProxyAsSubject) {
1143         LOGE("no proxy data");
1144         context->subjectProxyOnes.clear();
1145         return false;
1146     }
1147     JsonObject jsonObj;
1148     jsonObj.Parse(authorizeInfo);
1149     if (jsonObj.IsDiscarded() || !jsonObj.Contains(APP_USER_DATA) ||
1150         !IsArray(jsonObj, APP_USER_DATA)) {
1151         context->subjectProxyOnes.clear();
1152         LOGE("no subject proxy data");
1153         return context->IsCallingProxyAsSubject;
1154     }
1155     JsonObject appDataObj;
1156     std::string appDataStr = jsonObj[APP_USER_DATA].Dump();
1157     appDataObj.Parse(appDataStr);
1158     for (auto item = context->subjectProxyOnes.begin(); item != context->subjectProxyOnes.end();) {
1159         if (IsUserAuthorize(appDataObj, item->proxyAccessee)) {
1160             item++;
1161         } else {
1162             item = context->subjectProxyOnes.erase(item);
1163         }
1164     }
1165     return context->subjectProxyOnes.size() > 0 || context->IsCallingProxyAsSubject;
1166 }
1167 
ProcessServerAuthorize(std::shared_ptr<DmAuthContext> context)1168 bool AuthSinkConfirmState::ProcessServerAuthorize(std::shared_ptr<DmAuthContext> context)
1169 {
1170     if (context == nullptr) {
1171         return false;
1172     }
1173     if (!context->IsProxyBind) {
1174         return true;
1175     }
1176     OHOS::DistributedDeviceProfile::LocalServiceInfo srvInfo;
1177     auto ret = DeviceProfileConnector::GetInstance().GetLocalServiceInfoByBundleNameAndPinExchangeType(
1178         context->accessee.pkgName, context->authType, srvInfo);
1179     if (ret != OHOS::DistributedDeviceProfile::DP_SUCCESS) {
1180         LOGE("ReadServiceInfo not found");
1181         return false;
1182     }
1183     std::string srvExtarInfo = srvInfo.GetExtraInfo();
1184     if (srvExtarInfo.empty()) {
1185         LOGE("no proxy data");
1186         context->subjectProxyOnes.clear();
1187         return false;
1188     }
1189     JsonObject jsonObj;
1190     jsonObj.Parse(srvExtarInfo);
1191     if (jsonObj.IsDiscarded() || !jsonObj.Contains(APP_USER_DATA) ||
1192         !IsArray(jsonObj, APP_USER_DATA)) {
1193         context->subjectProxyOnes.clear();
1194         LOGE("no subject proxy data");
1195         return false;
1196     }
1197     if (IsString(jsonObj, TITLE)) {
1198         context->title = jsonObj[TITLE].Get<std::string>();
1199     }
1200     JsonObject appDataObj;
1201     std::string appDataStr = jsonObj[APP_USER_DATA].Dump();
1202     appDataObj.Parse(appDataStr);
1203     for (auto item = context->subjectProxyOnes.begin(); item != context->subjectProxyOnes.end();) {
1204         if (IsUserAuthorize(appDataObj, item->proxyAccessee)) {
1205             item++;
1206         } else {
1207             item = context->subjectProxyOnes.erase(item);
1208         }
1209     }
1210     return context->subjectProxyOnes.size() > 0;
1211 }
1212 
IsUserAuthorize(JsonObject & paramObj,DmProxyAccess & access)1213 bool AuthSinkConfirmState::IsUserAuthorize(JsonObject &paramObj, DmProxyAccess &access)
1214 {
1215     if (paramObj.IsDiscarded()) {
1216         return false;
1217     }
1218     for (auto const &item : paramObj.Items()) {
1219         if (!IsString(item, TAG_BUNDLE_NAME)) {
1220             continue;
1221         }
1222         if (access.bundleName == item[TAG_BUNDLE_NAME].Get<std::string>()) {
1223             if (IsString(item, BUNDLE_INFO)) {
1224                 access.bundleInfo = item[BUNDLE_INFO].Get<std::string>();
1225             }
1226             return true;
1227         }
1228     }
1229     return false;
1230 }
1231 
ProcessNoBindAuthorize(std::shared_ptr<DmAuthContext> context)1232 int32_t AuthSinkConfirmState::ProcessNoBindAuthorize(std::shared_ptr<DmAuthContext> context)
1233 {
1234     LOGI("start.");
1235     CHECK_NULL_RETURN(context, ERR_DM_POINT_NULL);
1236     JsonObject accesseeCredTypeList;
1237     accesseeCredTypeList.Parse(context->accessee.credTypeList);
1238     if (accesseeCredTypeList.IsDiscarded()) {
1239         LOGE("CredTypeList invalid.");
1240         context->reason = ERR_DM_CAPABILITY_NEGOTIATE_FAILED;
1241         return ERR_DM_FAILED;
1242     }
1243     if (accesseeCredTypeList.Contains("identicalCredType")) {
1244         context->confirmOperation = UiAction::USER_OPERATION_TYPE_ALLOW_AUTH_ALWAYS;
1245         context->accessee.transmitCredentialId = GetCredIdByCredType(context, DM_IDENTICAL_ACCOUNT);
1246     } else if (accesseeCredTypeList.Contains("shareCredType")) {
1247         context->confirmOperation = UiAction::USER_OPERATION_TYPE_ALLOW_AUTH_ALWAYS;
1248         context->accessee.transmitCredentialId = GetCredIdByCredType(context, DM_SHARE);
1249     } else if (accesseeCredTypeList.Contains("pointTopointCredType")) {
1250         context->accessee.transmitCredentialId = GetCredIdByCredType(context, DM_POINT_TO_POINT);
1251     } else if (accesseeCredTypeList.Contains("lnnCredType")) {
1252         context->accessee.lnnCredentialId = GetCredIdByCredType(context, DM_LNN);
1253     } else {
1254         LOGE("credTypeList invalid.");
1255         context->reason = ERR_DM_CAPABILITY_NEGOTIATE_FAILED;
1256         return ERR_DM_FAILED;
1257     }
1258     context->authMessageProcessor->CreateAndSendMsg(MSG_TYPE_RESP_USER_CONFIRM, context);
1259     context->authStateMachine->TransitionTo(std::make_shared<AuthSinkCredentialAuthStartState>());
1260     return DM_OK;
1261 }
1262 
GetCredIdByCredType(std::shared_ptr<DmAuthContext> context,int32_t credType)1263 std::string AuthSinkConfirmState::GetCredIdByCredType(std::shared_ptr<DmAuthContext> context, int32_t credType)
1264 {
1265     LOGI("credType %{public}d.", credType);
1266     CHECK_NULL_RETURN(context, UNVALID_CREDTID);
1267     if (context->accessee.credentialInfos.find(credType) != context->accessee.credentialInfos.end()) {
1268         LOGE("invalid credType.");
1269         return UNVALID_CREDTID;
1270     }
1271     std::string credInfoStr = context->accessee.credentialInfos[credType];
1272     JsonObject credInfoJson;
1273     credInfoJson.Parse(credInfoStr);
1274     if (credInfoJson.IsDiscarded() || !credInfoJson.Contains(FILED_CRED_ID) ||
1275         !credInfoJson[FILED_CRED_ID].IsNumberInteger()) {
1276         LOGE("credInfoStr invalid.");
1277         return UNVALID_CREDTID;
1278     }
1279     return credInfoJson[FILED_CRED_ID].Get<std::string>();
1280 }
1281 } // namespace DistributedHardware
1282 } // namespace OHOS