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 <cstring>
19 #include <set>
20 #include <mutex>
21 #include <string>
22 #include <vector>
23 
24 #include <securec.h>
25 
26 #include "access_control_profile.h"
27 #include "anonymizer.h"
28 #include "auth_interface.h"
29 #include "bus_center_manager.h"
30 #include "distributed_device_profile_client.h"
31 #include "lnn_distributed_net_ledger.h"
32 #include "lnn_local_net_ledger.h"
33 #include "lnn_log.h"
34 #include "lnn_ohos_account_adapter.h"
35 #include "lnn_ohos_account.h"
36 #include "ohos_account_kits.h"
37 #include "os_account_manager.h"
38 #include "softbus_adapter_crypto.h"
39 #include "softbus_common.h"
40 #include "softbus_error_code.h"
41 #include "softbus_utils.h"
42 #include "trust_device_profile.h"
43 
44 using DpClient = OHOS::DistributedDeviceProfile::DistributedDeviceProfileClient;
45 static std::set<std::string> g_notTrustedDevices;
46 static std::mutex g_mutex;
47 static constexpr const int32_t LONG_TO_STRING_MAX_LEN = 21;
48 
IsNotTrustDevice(std::string deviceIdHash)49 static bool IsNotTrustDevice(std::string deviceIdHash)
50 {
51     std::lock_guard<std::mutex> autoLock(g_mutex);
52     if (g_notTrustedDevices.find(deviceIdHash) != g_notTrustedDevices.end()) {
53         return true;
54     }
55     return false;
56 }
57 
InsertNotTrustDevice(std::string deviceIdHash)58 static void InsertNotTrustDevice(std::string deviceIdHash)
59 {
60     std::lock_guard<std::mutex> autoLock(g_mutex);
61     g_notTrustedDevices.insert(deviceIdHash);
62 }
63 
DelNotTrustDevice(const char *udid)64 void DelNotTrustDevice(const char *udid)
65 {
66     if (udid == nullptr) {
67         LNN_LOGE(LNN_STATE, "udid is null");
68         return;
69     }
70     uint8_t udidHash[SHA_256_HASH_LEN] = {0};
71     char hashStr[CUST_UDID_LEN + 1] = {0};
72     if (SoftBusGenerateStrHash((const unsigned char *)udid, strlen(udid), udidHash) != SOFTBUS_OK) {
73         LNN_LOGE(LNN_STATE, "generate udidhash fail");
74         return;
75     }
76     if (ConvertBytesToHexString(hashStr, CUST_UDID_LEN + 1, udidHash, CUST_UDID_LEN / HEXIFY_UNIT_LEN) != SOFTBUS_OK) {
77         LNN_LOGE(LNN_STATE, "convert udidhash hex string fail");
78         return;
79     }
80     std::lock_guard<std::mutex> autoLock(g_mutex);
81     if (g_notTrustedDevices.find(hashStr) != g_notTrustedDevices.end()) {
82         LNN_LOGI(LNN_STATE, "remove not trust device");
83         g_notTrustedDevices.erase(hashStr);
84         return;
85     }
86     LNN_LOGI(LNN_STATE, "not need remove");
87 }
88 
IsTrustDevice(std::vector<OHOS::DistributedDeviceProfile::AccessControlProfile> &trustDevices, const char *deviceIdHash, const char *anonyDeviceIdHash)89 static bool IsTrustDevice(std::vector<OHOS::DistributedDeviceProfile::AccessControlProfile> &trustDevices,
90     const char *deviceIdHash, const char *anonyDeviceIdHash)
91 {
92     for (const auto &trustDevice : trustDevices) {
93         if (trustDevice.GetDeviceIdType() != (uint32_t)OHOS::DistributedDeviceProfile::DeviceIdType::UDID ||
94             trustDevice.GetBindType() == (uint32_t)OHOS::DistributedDeviceProfile::BindType::SAME_ACCOUNT ||
95             trustDevice.GetTrustDeviceId().empty()) {
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)123 bool IsPotentialTrustedDeviceDp(const char *deviceIdHash)
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)) {
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 }
DumpAccountId(int64_t localAccountId, int64_t peerAccountId)157 static void DumpAccountId(int64_t localAccountId, int64_t peerAccountId)
158 {
159     char localAccountString[LONG_TO_STRING_MAX_LEN] = {0};
160     if (sprintf_s(localAccountString, LONG_TO_STRING_MAX_LEN, "%" PRId64, localAccountId) == -1) {
161         LNN_LOGE(LNN_STATE, "long to string fail");
162         return;
163     }
164 
165     char peerAccountString[LONG_TO_STRING_MAX_LEN] = {0};
166     if (sprintf_s(peerAccountString, LONG_TO_STRING_MAX_LEN, "%" PRId64, peerAccountId) == -1) {
167         LNN_LOGE(LNN_STATE, "long to string fail");
168         return;
169     }
170 
171     char *anonyLocalAccountId = nullptr;
172     char *anonyPeerAccountId = nullptr;
173     Anonymize(localAccountString, &anonyLocalAccountId);
174     Anonymize(peerAccountString, &anonyPeerAccountId);
175     LNN_LOGI(LNN_STATE, "localAccountId=%{public}s, peerAccountId=%{public}s",
176         AnonymizeWrapper(anonyLocalAccountId), AnonymizeWrapper(anonyPeerAccountId));
177     AnonymizeFree(anonyLocalAccountId);
178     AnonymizeFree(anonyPeerAccountId);
179 }
180 
IsSameAccount(int64_t accountId)181 static bool IsSameAccount(int64_t accountId)
182 {
183     int64_t localAccountId = 0;
184     int32_t ret = LnnGetLocalNum64Info(NUM_KEY_ACCOUNT_LONG, &localAccountId);
185     if (ret != SOFTBUS_OK) {
186         LNN_LOGE(LNN_STATE, "get local accountId fail");
187         return false;
188     }
189     DumpAccountId(localAccountId, accountId);
190     if (localAccountId == accountId && !LnnIsDefaultOhosAccount()) {
191         return true;
192     }
193     return false;
194 }
195 
GenerateDpAccesserAndAccessee(OHOS::DistributedDeviceProfile::Accesser &accesser, OHOS::DistributedDeviceProfile::Accessee &accessee, std::string peerUdid)196 static int32_t GenerateDpAccesserAndAccessee(OHOS::DistributedDeviceProfile::Accesser &accesser,
197     OHOS::DistributedDeviceProfile::Accessee &accessee, std::string peerUdid)
198 {
199     char udid[UDID_BUF_LEN] = {0};
200     if (LnnGetLocalStrInfo(STRING_KEY_DEV_UDID, udid, UDID_BUF_LEN) != SOFTBUS_OK) {
201         LNN_LOGE(LNN_STATE, "get local udid fail");
202         return SOFTBUS_ERR;
203     }
204     std::string localUdid(udid);
205     accesser.SetAccesserDeviceId(localUdid);
206     accesser.SetAccesserUserId(GetActiveOsAccountIds());
207     OHOS::AccountSA::OhosAccountInfo accountInfo;
208     OHOS::ErrCode ret = OHOS::AccountSA::OhosAccountKits::GetInstance().GetOhosAccountInfo(accountInfo);
209     if (ret != OHOS::ERR_OK || accountInfo.uid_.empty()) {
210         LNN_LOGE(LNN_STATE, "getOhosAccountInfo fail ret=%{public}d", ret);
211         return SOFTBUS_ERR;
212     }
213     accesser.SetAccesserAccountId(accountInfo.uid_);
214     accessee.SetAccesseeDeviceId(peerUdid);
215     return SOFTBUS_OK;
216 }
217 
InsertDpSameAccount(const std::string udid)218 static void InsertDpSameAccount(const std::string udid)
219 {
220     std::vector<OHOS::DistributedDeviceProfile::AccessControlProfile> aclProfiles;
221     int32_t ret = DpClient::GetInstance().GetAllAccessControlProfile(aclProfiles);
222     if (ret != OHOS::DistributedDeviceProfile::DP_NOT_FIND_DATA && ret != OHOS::DistributedDeviceProfile::DP_SUCCESS) {
223         LNN_LOGE(LNN_STATE, "getAllAccessControlProfile failed, ret=%{public}d", ret);
224         return;
225     }
226     for (const auto &aclProfile : aclProfiles) {
227         if (aclProfile.GetDeviceIdType() == (uint32_t)OHOS::DistributedDeviceProfile::DeviceIdType::UDID &&
228             aclProfile.GetBindType() == (uint32_t)OHOS::DistributedDeviceProfile::BindType::SAME_ACCOUNT &&
229             udid == aclProfile.GetTrustDeviceId()) {
230             LNN_LOGI(LNN_STATE, "dp has same account no need insert");
231             return;
232         }
233     }
234 
235     OHOS::DistributedDeviceProfile::AccessControlProfile accessControlProfile;
236     OHOS::DistributedDeviceProfile::Accesser accesser;
237     OHOS::DistributedDeviceProfile::Accessee accessee;
238     ret = GenerateDpAccesserAndAccessee(accesser, accessee, udid);
239     if (ret != SOFTBUS_OK) {
240         LNN_LOGE(LNN_STATE, "generate accesser accessee fail");
241         return;
242     }
243     accessControlProfile.SetBindType((uint32_t)OHOS::DistributedDeviceProfile::BindType::SAME_ACCOUNT);
244     accessControlProfile.SetDeviceIdType((uint32_t)OHOS::DistributedDeviceProfile::DeviceIdType::UDID);
245     accessControlProfile.SetStatus((uint32_t)OHOS::DistributedDeviceProfile::Status::ACTIVE);
246     accessControlProfile.SetAuthenticationType((uint32_t)OHOS::DistributedDeviceProfile::
247         AuthenticationType::PERMANENT);
248     accessControlProfile.SetTrustDeviceId(udid);
249     accessControlProfile.SetAccesser(accesser);
250     accessControlProfile.SetAccessee(accessee);
251     ret = DpClient::GetInstance().PutAccessControlProfile(accessControlProfile);
252     if (ret != OHOS::DistributedDeviceProfile::DP_SUCCESS) {
253         LNN_LOGE(LNN_STATE, "putAccessControlProfile failed, ret=%{public}d", ret);
254         return;
255     }
256     char *anonyUdid = nullptr;
257     Anonymize(udid.c_str(), &anonyUdid);
258     LNN_LOGI(LNN_STATE, "insert dp same account succ, udid=%{public}s", AnonymizeWrapper(anonyUdid));
259     AnonymizeFree(anonyUdid);
260 }
261 
UpdateDpSameAccount(int64_t accountId, const char *deviceId)262 void UpdateDpSameAccount(int64_t accountId, const char *deviceId)
263 {
264     if (deviceId == nullptr) {
265         LNN_LOGE(LNN_STATE, "deviceId is null");
266         return;
267     }
268     std::string udid(deviceId);
269     if (IsSameAccount(accountId)) {
270         InsertDpSameAccount(udid);
271     }
272 }
273 
274