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", anonyUdid, anonyDeviceIdHash);
101         AnonymizeFree(anonyUdid);
102         uint8_t udidHash[SHA_256_HASH_LEN] = {0};
103         char hashStr[CUST_UDID_LEN + 1] = {0};
104         if (SoftBusGenerateStrHash((const unsigned char *)trustDevice.GetTrustDeviceId().c_str(),
105             trustDevice.GetTrustDeviceId().length(), udidHash) != SOFTBUS_OK) {
106             LNN_LOGE(LNN_STATE, "generate udidhash fail");
107             continue;
108         }
109         if (ConvertBytesToHexString(hashStr, CUST_UDID_LEN + 1, udidHash,
110             CUST_UDID_LEN / HEXIFY_UNIT_LEN) != SOFTBUS_OK) {
111             LNN_LOGE(LNN_STATE, "convert udidhash hex string fail");
112             continue;
113         }
114         if (strncmp(hashStr, deviceIdHash, strlen(deviceIdHash)) == 0) {
115             LNN_LOGI(LNN_STATE, "device trusted in dp continue verify, deviceIdHash=%{public}s", anonyDeviceIdHash);
116             return true;
117         }
118     }
119     return false;
120 }
121 
IsPotentialTrustedDeviceDp(const char * deviceIdHash)122 bool IsPotentialTrustedDeviceDp(const char *deviceIdHash)
123 {
124     if (deviceIdHash == nullptr) {
125         LNN_LOGE(LNN_STATE, "deviceIdHash is null");
126         return false;
127     }
128     if (IsNotTrustDevice(deviceIdHash)) {
129         LNN_LOGD(LNN_STATE, "device not trusted");
130         return false;
131     }
132     std::vector<OHOS::DistributedDeviceProfile::AccessControlProfile> aclProfiles;
133     int32_t ret = DpClient::GetInstance().GetAllAccessControlProfile(aclProfiles);
134     if (ret != OHOS::DistributedDeviceProfile::DP_NOT_FIND_DATA && ret != OHOS::DistributedDeviceProfile::DP_SUCCESS) {
135         LNN_LOGE(LNN_STATE, "GetAllAccessControlProfile ret=%{public}d", ret);
136         return false;
137     }
138     if (aclProfiles.empty()) {
139         LNN_LOGE(LNN_STATE, "aclProfiles is empty");
140         InsertNotTrustDevice(deviceIdHash);
141         return false;
142     }
143     char *anonyDeviceIdHash = nullptr;
144     Anonymize(deviceIdHash, &anonyDeviceIdHash);
145     static uint32_t callCount = 0;
146     if (IsTrustDevice(aclProfiles, deviceIdHash, anonyDeviceIdHash)) {
147         AnonymizeFree(anonyDeviceIdHash);
148         return true;
149     }
150     InsertNotTrustDevice(deviceIdHash);
151     LNN_LOGI(LNN_STATE, "device is not trusted in dp, deviceIdHash=%{public}s, callCount=%{public}u",
152         anonyDeviceIdHash, callCount++);
153     AnonymizeFree(anonyDeviceIdHash);
154     return false;
155 }
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 
InsertDpSameAccount(const std::string peerUdid)196 static void InsertDpSameAccount(const std::string peerUdid)
197 {
198     OHOS::DistributedDeviceProfile::AccessControlProfile accessControlProfile;
199     OHOS::DistributedDeviceProfile::Accesser accesser;
200     OHOS::DistributedDeviceProfile::Accessee accessee;
201     char udid[UDID_BUF_LEN] = {0};
202     if (LnnGetLocalStrInfo(STRING_KEY_DEV_UDID, udid, UDID_BUF_LEN) != SOFTBUS_OK) {
203         LNN_LOGE(LNN_STATE, "get local udid fail");
204         return;
205     }
206     std::string localUdid(udid);
207     accesser.SetAccesserDeviceId(localUdid);
208     accesser.SetAccesserUserId(GetActiveOsAccountIds());
209     OHOS::AccountSA::OhosAccountInfo accountInfo;
210     OHOS::ErrCode ret = OHOS::AccountSA::OhosAccountKits::GetInstance().GetOhosAccountInfo(accountInfo);
211     if (ret != OHOS::ERR_OK || accountInfo.uid_.empty()) {
212         LNN_LOGE(LNN_STATE, "getOhosAccountInfo fail ret=%{public}d", ret);
213         return;
214     }
215     accesser.SetAccesserAccountId(accountInfo.uid_);
216     accessee.SetAccesseeDeviceId(peerUdid);
217     accessControlProfile.SetBindType((uint32_t)OHOS::DistributedDeviceProfile::BindType::SAME_ACCOUNT);
218     accessControlProfile.SetDeviceIdType((uint32_t)OHOS::DistributedDeviceProfile::DeviceIdType::UDID);
219     accessControlProfile.SetStatus((uint32_t)OHOS::DistributedDeviceProfile::Status::ACTIVE);
220     accessControlProfile.SetAuthenticationType((uint32_t)OHOS::DistributedDeviceProfile::
221         AuthenticationType::PERMANENT);
222     accessControlProfile.SetTrustDeviceId(peerUdid);
223     accessControlProfile.SetAccesser(accesser);
224     accessControlProfile.SetAccessee(accessee);
225     ret = DpClient::GetInstance().PutAccessControlProfile(accessControlProfile);
226     if (ret != OHOS::DistributedDeviceProfile::DP_SUCCESS) {
227         LNN_LOGE(LNN_STATE, "putAccessControlProfile failed, ret=%{public}d", ret);
228         return;
229     }
230     char *anonyUdid = nullptr;
231     Anonymize(peerUdid.c_str(), &anonyUdid);
232     LNN_LOGI(LNN_STATE, "insert dp same account succ, udid=%{public}s", anonyUdid);
233     AnonymizeFree(anonyUdid);
234 }
235 
UpdateDpSameAccount(int64_t accountId,const char * deviceId)236 void UpdateDpSameAccount(int64_t accountId, const char *deviceId)
237 {
238     if (deviceId == nullptr) {
239         LNN_LOGE(LNN_STATE, "deviceId is null");
240         return;
241     }
242     std::string peerUdid(deviceId);
243     if (IsSameAccount(accountId)) {
244         InsertDpSameAccount(peerUdid);
245     }
246 }
247