1 /*
2 * Copyright (c) 2023-2024 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 permission and
13 * limitations under the License.
14 */
15
16 #include "auth_deviceprofile.h"
17
18 #include <securec.h>
19
20 #include "anonymizer.h"
21 #include "bus_center_manager.h"
22 #include "distributed_device_profile_client.h"
23 #include "lnn_distributed_net_ledger.h"
24 #include "lnn_log.h"
25 #include "lnn_ohos_account.h"
26 #include "ohos_account_kits.h"
27 #include "softbus_adapter_crypto.h"
28 #include "softbus_utils.h"
29
30 using DpClient = OHOS::DistributedDeviceProfile::DistributedDeviceProfileClient;
31 static std::set<std::string> g_notTrustedDevices;
32 static std::mutex g_mutex;
33 static constexpr const int32_t LONG_TO_STRING_MAX_LEN = 21;
34
IsNotTrustDevice(std::string deviceIdHash)35 static bool IsNotTrustDevice(std::string deviceIdHash)
36 {
37 std::lock_guard<std::mutex> autoLock(g_mutex);
38 if (g_notTrustedDevices.find(deviceIdHash) != g_notTrustedDevices.end()) {
39 return true;
40 }
41 return false;
42 }
43
InsertNotTrustDevice(std::string deviceIdHash)44 static void InsertNotTrustDevice(std::string deviceIdHash)
45 {
46 std::lock_guard<std::mutex> autoLock(g_mutex);
47 g_notTrustedDevices.insert(deviceIdHash);
48 }
49
DelNotTrustDevice(const char * udid)50 void DelNotTrustDevice(const char *udid)
51 {
52 if (udid == nullptr) {
53 LNN_LOGE(LNN_STATE, "udid is null");
54 return;
55 }
56 uint8_t udidHash[SHA_256_HASH_LEN] = {0};
57 char hashStr[CUST_UDID_LEN + 1] = {0};
58 if (SoftBusGenerateStrHash((const unsigned char *)udid, strlen(udid), udidHash) != SOFTBUS_OK) {
59 LNN_LOGE(LNN_STATE, "generate udidhash fail");
60 return;
61 }
62 if (ConvertBytesToHexString(hashStr, CUST_UDID_LEN + 1, udidHash, CUST_UDID_LEN / HEXIFY_UNIT_LEN) != SOFTBUS_OK) {
63 LNN_LOGE(LNN_STATE, "convert udidhash hex string fail");
64 return;
65 }
66 std::lock_guard<std::mutex> autoLock(g_mutex);
67 if (g_notTrustedDevices.find(hashStr) != g_notTrustedDevices.end()) {
68 LNN_LOGI(LNN_STATE, "remove not trust device");
69 g_notTrustedDevices.erase(hashStr);
70 return;
71 }
72 LNN_LOGI(LNN_STATE, "not need remove");
73 }
74
GetAclLocalUserId(const OHOS::DistributedDeviceProfile::AccessControlProfile & trustDevice)75 static int32_t GetAclLocalUserId(const OHOS::DistributedDeviceProfile::AccessControlProfile &trustDevice)
76 {
77 if (trustDevice.GetTrustDeviceId() == trustDevice.GetAccessee().GetAccesseeDeviceId()) {
78 return trustDevice.GetAccesser().GetAccesserUserId();
79 }
80 return trustDevice.GetAccessee().GetAccesseeUserId();
81 }
82
IsTrustDevice(std::vector<OHOS::DistributedDeviceProfile::AccessControlProfile> & trustDevices,const char * deviceIdHash,const char * anonyDeviceIdHash,bool isOnlyPointToPoint)83 static bool IsTrustDevice(std::vector<OHOS::DistributedDeviceProfile::AccessControlProfile> &trustDevices,
84 const char *deviceIdHash, const char *anonyDeviceIdHash, bool isOnlyPointToPoint)
85 {
86 int32_t localUserId = GetActiveOsAccountIds();
87 for (const auto &trustDevice : trustDevices) {
88 if (isOnlyPointToPoint &&
89 trustDevice.GetBindType() == (uint32_t)OHOS::DistributedDeviceProfile::BindType::SAME_ACCOUNT) {
90 continue;
91 }
92 if (trustDevice.GetDeviceIdType() != (uint32_t)OHOS::DistributedDeviceProfile::DeviceIdType::UDID ||
93 trustDevice.GetTrustDeviceId().empty() ||
94 trustDevice.GetStatus() == (uint32_t)OHOS::DistributedDeviceProfile::Status::INACTIVE ||
95 localUserId != GetAclLocalUserId(trustDevice)) {
96 continue;
97 }
98 char *anonyUdid = nullptr;
99 Anonymize(trustDevice.GetTrustDeviceId().c_str(), &anonyUdid);
100 LNN_LOGI(LNN_STATE, "udid=%{public}s, deviceIdHash=%{public}s",
101 AnonymizeWrapper(anonyUdid), anonyDeviceIdHash);
102 AnonymizeFree(anonyUdid);
103 uint8_t udidHash[SHA_256_HASH_LEN] = {0};
104 char hashStr[CUST_UDID_LEN + 1] = {0};
105 if (SoftBusGenerateStrHash((const unsigned char *)trustDevice.GetTrustDeviceId().c_str(),
106 trustDevice.GetTrustDeviceId().length(), udidHash) != SOFTBUS_OK) {
107 LNN_LOGE(LNN_STATE, "generate udidhash fail");
108 continue;
109 }
110 if (ConvertBytesToHexString(hashStr, CUST_UDID_LEN + 1, udidHash,
111 CUST_UDID_LEN / HEXIFY_UNIT_LEN) != SOFTBUS_OK) {
112 LNN_LOGE(LNN_STATE, "convert udidhash hex string fail");
113 continue;
114 }
115 if (strncmp(hashStr, deviceIdHash, strlen(deviceIdHash)) == 0) {
116 LNN_LOGI(LNN_STATE, "device trusted in dp continue verify, deviceIdHash=%{public}s", anonyDeviceIdHash);
117 return true;
118 }
119 }
120 return false;
121 }
122
IsPotentialTrustedDeviceDp(const char * deviceIdHash,bool isOnlyPointToPoint)123 bool IsPotentialTrustedDeviceDp(const char *deviceIdHash, bool isOnlyPointToPoint)
124 {
125 if (deviceIdHash == nullptr) {
126 LNN_LOGE(LNN_STATE, "deviceIdHash is null");
127 return false;
128 }
129 if (IsNotTrustDevice(deviceIdHash)) {
130 LNN_LOGD(LNN_STATE, "device not trusted");
131 return false;
132 }
133 std::vector<OHOS::DistributedDeviceProfile::AccessControlProfile> aclProfiles;
134 int32_t ret = DpClient::GetInstance().GetAllAccessControlProfile(aclProfiles);
135 if (ret != OHOS::DistributedDeviceProfile::DP_NOT_FIND_DATA && ret != OHOS::DistributedDeviceProfile::DP_SUCCESS) {
136 LNN_LOGE(LNN_STATE, "GetAllAccessControlProfile ret=%{public}d", ret);
137 return false;
138 }
139 if (aclProfiles.empty()) {
140 LNN_LOGE(LNN_STATE, "aclProfiles is empty");
141 InsertNotTrustDevice(deviceIdHash);
142 return false;
143 }
144 char *anonyDeviceIdHash = nullptr;
145 Anonymize(deviceIdHash, &anonyDeviceIdHash);
146 static uint32_t callCount = 0;
147 if (IsTrustDevice(aclProfiles, deviceIdHash, anonyDeviceIdHash, isOnlyPointToPoint)) {
148 AnonymizeFree(anonyDeviceIdHash);
149 return true;
150 }
151 InsertNotTrustDevice(deviceIdHash);
152 LNN_LOGI(LNN_STATE, "device is not trusted in dp, deviceIdHash=%{public}s, callCount=%{public}u",
153 AnonymizeWrapper(anonyDeviceIdHash), callCount++);
154 AnonymizeFree(anonyDeviceIdHash);
155 return false;
156 }
157
DpHasAccessControlProfile(const char * udid,bool isNeedUserId,int32_t localUserId)158 bool DpHasAccessControlProfile(const char *udid, bool isNeedUserId, int32_t localUserId)
159 {
160 if (udid == nullptr) {
161 LNN_LOGE(LNN_STATE, "udid is null");
162 return false;
163 }
164
165 char *anonyUdid = nullptr;
166 Anonymize(udid, &anonyUdid);
167 LNN_LOGI(LNN_STATE, "udid=%{public}s, isNeedUserId=%{public}d, localUserId=%{public}d",
168 AnonymizeWrapper(anonyUdid), isNeedUserId, localUserId);
169 AnonymizeFree(anonyUdid);
170 std::vector<OHOS::DistributedDeviceProfile::AccessControlProfile> aclProfiles;
171 int32_t ret = DpClient::GetInstance().GetAllAccessControlProfile(aclProfiles);
172 if (ret != OHOS::DistributedDeviceProfile::DP_NOT_FIND_DATA && ret != OHOS::DistributedDeviceProfile::DP_SUCCESS) {
173 LNN_LOGE(LNN_STATE, "GetAllAccessControlProfile ret=%{public}d", ret);
174 return false;
175 }
176 if (aclProfiles.empty()) {
177 LNN_LOGE(LNN_STATE, "aclProfiles is empty");
178 return false;
179 }
180 for (const auto &trustDevice :aclProfiles) {
181 if (trustDevice.GetDeviceIdType() != (uint32_t)OHOS::DistributedDeviceProfile::DeviceIdType::UDID ||
182 trustDevice.GetTrustDeviceId().empty() ||
183 trustDevice.GetTrustDeviceId() != udid) {
184 continue;
185 }
186 if (isNeedUserId && GetAclLocalUserId(trustDevice) != localUserId) {
187 continue;
188 }
189
190 LNN_LOGI(LNN_STATE, "dp has accessControlProfile");
191 return true;
192 }
193 LNN_LOGI(LNN_STATE, "dp not has accessControlProfile");
194 return false;
195 }
196
DumpAccountId(int64_t localAccountId,int64_t peerAccountId)197 static void DumpAccountId(int64_t localAccountId, int64_t peerAccountId)
198 {
199 char localAccountString[LONG_TO_STRING_MAX_LEN] = {0};
200 if (sprintf_s(localAccountString, LONG_TO_STRING_MAX_LEN, "%" PRId64, localAccountId) == -1) {
201 LNN_LOGE(LNN_STATE, "long to string fail");
202 return;
203 }
204
205 char peerAccountString[LONG_TO_STRING_MAX_LEN] = {0};
206 if (sprintf_s(peerAccountString, LONG_TO_STRING_MAX_LEN, "%" PRId64, peerAccountId) == -1) {
207 LNN_LOGE(LNN_STATE, "long to string fail");
208 return;
209 }
210
211 char *anonyLocalAccountId = nullptr;
212 char *anonyPeerAccountId = nullptr;
213 Anonymize(localAccountString, &anonyLocalAccountId);
214 Anonymize(peerAccountString, &anonyPeerAccountId);
215 LNN_LOGI(LNN_STATE, "localAccountId=%{public}s, peerAccountId=%{public}s",
216 AnonymizeWrapper(anonyLocalAccountId), AnonymizeWrapper(anonyPeerAccountId));
217 AnonymizeFree(anonyLocalAccountId);
218 AnonymizeFree(anonyPeerAccountId);
219 }
220
IsSameAccount(int64_t accountId)221 static bool IsSameAccount(int64_t accountId)
222 {
223 int64_t localAccountId = 0;
224 int32_t ret = LnnGetLocalNum64Info(NUM_KEY_ACCOUNT_LONG, &localAccountId);
225 if (ret != SOFTBUS_OK) {
226 LNN_LOGE(LNN_STATE, "get local accountId fail");
227 return false;
228 }
229 DumpAccountId(localAccountId, accountId);
230 if (localAccountId == accountId && !LnnIsDefaultOhosAccount()) {
231 return true;
232 }
233 return false;
234 }
235
DumpDpAclInfo(const std::string peerUdid,int32_t localUserId,int32_t peerUserId,const OHOS::DistributedDeviceProfile::AccessControlProfile & aclProfile)236 static void DumpDpAclInfo(const std::string peerUdid, int32_t localUserId, int32_t peerUserId,
237 const OHOS::DistributedDeviceProfile::AccessControlProfile &aclProfile)
238 {
239 char *anonyUdid = nullptr;
240 Anonymize(peerUdid.c_str(), &anonyUdid);
241 LNN_LOGI(LNN_STATE,
242 "dp has acl. udid=%{public}s, localUserId=%{public}d, peerUserId=%{public}d, "
243 "Status=%{public}d",
244 AnonymizeWrapper(anonyUdid), localUserId, peerUserId, aclProfile.GetStatus());
245 AnonymizeFree(anonyUdid);
246 }
247
UpdateDpSameAccountAcl(const std::string peerUdid,int32_t peerUserId)248 static UpdateDpAclResult UpdateDpSameAccountAcl(const std::string peerUdid, int32_t peerUserId)
249 {
250 if (peerUserId == 0) {
251 // old acl dp userid is -1, use -1 to match acl
252 peerUserId = -1;
253 LNN_LOGI(LNN_STATE, "peer device is old version");
254 }
255 std::vector<OHOS::DistributedDeviceProfile::AccessControlProfile> aclProfiles;
256 int32_t ret = DpClient::GetInstance().GetAllAccessControlProfile(aclProfiles);
257 if (ret != OHOS::DistributedDeviceProfile::DP_SUCCESS) {
258 LNN_LOGE(LNN_STATE, "GetAllAccessControlProfile ret=%{public}d", ret);
259 return GET_ALL_ACL_FAIL;
260 }
261 if (aclProfiles.empty()) {
262 LNN_LOGE(LNN_STATE, "aclProfiles is empty");
263 return GET_ALL_ACL_IS_EMPTY;
264 }
265
266 UpdateDpAclResult updateResult = UPDATE_ACL_NOT_MATCH;
267 int32_t localUserId = GetActiveOsAccountIds();
268 char udid[UDID_BUF_LEN] = { 0 };
269 if (LnnGetLocalStrInfo(STRING_KEY_DEV_UDID, udid, UDID_BUF_LEN) != SOFTBUS_OK) {
270 LNN_LOGE(LNN_STATE, "get local udid fail");
271 }
272 std::string localUdid(udid);
273 for (auto &aclProfile :aclProfiles) {
274 if (aclProfile.GetDeviceIdType() != (uint32_t)OHOS::DistributedDeviceProfile::DeviceIdType::UDID ||
275 aclProfile.GetTrustDeviceId().empty() ||
276 aclProfile.GetTrustDeviceId() != peerUdid ||
277 aclProfile.GetBindType() != (uint32_t)OHOS::DistributedDeviceProfile::BindType::SAME_ACCOUNT ||
278 aclProfile.GetAccesser().GetAccesserUserId() != localUserId ||
279 aclProfile.GetAccessee().GetAccesseeUserId() != peerUserId) {
280 continue;
281 }
282 if (aclProfile.GetAccessee().GetAccesseeDeviceId() == peerUdid &&
283 aclProfile.GetAccesser().GetAccesserDeviceId() != localUdid) {
284 LNN_LOGI(LNN_STATE, "localUdid change, need update accessControlProfile");
285 continue;
286 }
287 DumpDpAclInfo(peerUdid, localUserId, peerUserId, aclProfile);
288 if (aclProfile.GetStatus() != (int32_t)OHOS::DistributedDeviceProfile::Status::ACTIVE) {
289 aclProfile.SetStatus((int32_t)OHOS::DistributedDeviceProfile::Status::ACTIVE);
290 ret = DpClient::GetInstance().UpdateAccessControlProfile(aclProfile);
291 LNN_LOGI(LNN_STATE, "UpdateAccessControlProfile ret=%{public}d", ret);
292 }
293 updateResult = UPDATE_ACL_SUCC;
294 }
295 return updateResult;
296 }
297
InsertDpSameAccountAcl(const std::string peerUdid,int32_t peerUserId)298 static void InsertDpSameAccountAcl(const std::string peerUdid, int32_t peerUserId)
299 {
300 OHOS::DistributedDeviceProfile::AccessControlProfile accessControlProfile;
301 OHOS::DistributedDeviceProfile::Accesser accesser;
302 OHOS::DistributedDeviceProfile::Accessee accessee;
303 char udid[UDID_BUF_LEN] = {0};
304 if (LnnGetLocalStrInfo(STRING_KEY_DEV_UDID, udid, UDID_BUF_LEN) != SOFTBUS_OK) {
305 LNN_LOGE(LNN_STATE, "get local udid fail");
306 return;
307 }
308 std::string localUdid(udid);
309 accesser.SetAccesserDeviceId(localUdid);
310 accesser.SetAccesserUserId(GetActiveOsAccountIds());
311 OHOS::AccountSA::OhosAccountInfo accountInfo;
312 OHOS::ErrCode ret = OHOS::AccountSA::OhosAccountKits::GetInstance().GetOhosAccountInfo(accountInfo);
313 if (ret != OHOS::ERR_OK || accountInfo.uid_.empty()) {
314 LNN_LOGE(LNN_STATE, "getOhosAccountInfo fail ret=%{public}d", ret);
315 return;
316 }
317 accesser.SetAccesserAccountId(accountInfo.uid_);
318 accessee.SetAccesseeDeviceId(peerUdid);
319 if (peerUserId != 0) {
320 accessee.SetAccesseeUserId(peerUserId);
321 }
322 accessee.SetAccesseeAccountId(accountInfo.uid_);
323 accessControlProfile.SetBindType((uint32_t)OHOS::DistributedDeviceProfile::BindType::SAME_ACCOUNT);
324 accessControlProfile.SetDeviceIdType((uint32_t)OHOS::DistributedDeviceProfile::DeviceIdType::UDID);
325 accessControlProfile.SetStatus((uint32_t)OHOS::DistributedDeviceProfile::Status::ACTIVE);
326 accessControlProfile.SetAuthenticationType((uint32_t)OHOS::DistributedDeviceProfile::
327 AuthenticationType::PERMANENT);
328 accessControlProfile.SetTrustDeviceId(peerUdid);
329 accessControlProfile.SetAccesser(accesser);
330 accessControlProfile.SetAccessee(accessee);
331 ret = DpClient::GetInstance().PutAccessControlProfile(accessControlProfile);
332 if (ret != OHOS::DistributedDeviceProfile::DP_SUCCESS) {
333 LNN_LOGE(LNN_STATE, "putAccessControlProfile failed, ret=%{public}d", ret);
334 return;
335 }
336 char *anonyUdid = nullptr;
337 Anonymize(peerUdid.c_str(), &anonyUdid);
338 LNN_LOGI(LNN_STATE, "insert dp same account succ, udid=%{public}s, localUserId=%{public}d, peerUserId=%{public}d",
339 AnonymizeWrapper(anonyUdid), accesser.GetAccesserUserId(), accessee.GetAccesseeUserId());
340 AnonymizeFree(anonyUdid);
341 }
342
UpdateDpSameAccount(int64_t accountId,const char * deviceId,int32_t peerUserId)343 void UpdateDpSameAccount(int64_t accountId, const char *deviceId, int32_t peerUserId)
344 {
345 if (deviceId == nullptr) {
346 LNN_LOGE(LNN_STATE, "deviceId is null");
347 return;
348 }
349 std::string peerUdid(deviceId);
350 if (IsSameAccount(accountId)) {
351 UpdateDpAclResult ret = UpdateDpSameAccountAcl(peerUdid, peerUserId);
352 if (ret != UPDATE_ACL_SUCC) {
353 InsertDpSameAccountAcl(peerUdid, peerUserId);
354 }
355 }
356 }
357
GetSessionKeyProfile(int32_t sessionKeyId,uint8_t * sessionKey,uint32_t * length)358 bool GetSessionKeyProfile(int32_t sessionKeyId, uint8_t *sessionKey, uint32_t *length)
359 {
360 LNN_CHECK_AND_RETURN_RET_LOGE(sessionKey != NULL, SOFTBUS_INVALID_PARAM, LNN_EVENT, "sessionKey is null");
361 LNN_CHECK_AND_RETURN_RET_LOGE(length != NULL, SOFTBUS_INVALID_PARAM, LNN_EVENT, "length is null");
362 std::vector<uint8_t> vecSessionKey;
363 int32_t localUserId = GetActiveOsAccountIds();
364 if (localUserId < 0) {
365 LNN_LOGE(LNN_STATE, "GetUserId failed");
366 return false;
367 }
368 int32_t rc = DpClient::GetInstance().GetSessionKey(localUserId, sessionKeyId, vecSessionKey);
369 if (rc != OHOS::DistributedDeviceProfile::DP_SUCCESS) {
370 LNN_LOGE(LNN_STATE, "GetSessionKey failed, ret=%{public}d", rc);
371 return false;
372 }
373 std::copy(vecSessionKey.begin(), vecSessionKey.end(), sessionKey);
374 *length = vecSessionKey.size();
375 return true;
376 }
377
DelSessionKeyProfile(int32_t sessionKeyId)378 void DelSessionKeyProfile(int32_t sessionKeyId)
379 {
380 int32_t localUserId = GetActiveOsAccountIds();
381 if (localUserId < 0) {
382 LNN_LOGE(LNN_STATE, "GetUserId failed");
383 return;
384 }
385 int32_t rc = DpClient::GetInstance().DeleteSessionKey(localUserId, sessionKeyId);
386 if (rc != OHOS::DistributedDeviceProfile::DP_SUCCESS) {
387 LNN_LOGE(LNN_STATE, "DelSessionKey failed, ret=%{public}d", rc);
388 }
389 }
390
391