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 ¶mObj, 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