• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "network/softbus/softbus_permission_check.h"
17 
18 #include "device_manager.h"
19 #include "dfs_error.h"
20 #include "dm_device_info.h"
21 #include "ipc_skeleton.h"
22 #include "ohos_account_kits.h"
23 #include "os_account_manager.h"
24 #include "transport/socket.h"
25 #include "utils_directory.h"
26 #include "utils_log.h"
27 
28 namespace OHOS {
29 namespace Storage {
30 namespace DistributedFile {
31 constexpr const char *ACCOUNT_ID = "accountId";
32 static inline const std::string SERVICE_NAME { "ohos.storage.distributedfile.daemon" };
33 #ifdef SUPPORT_SAME_ACCOUNT
34 constexpr const char* PARAM_KEY_OS_TYPE = "OS_TYPE";
35 constexpr int32_t DEVICE_OS_TYPE_OH = 10;
36 constexpr uint32_t MAX_ONLINE_DEVICE_SIZE = 10000;
37 #endif
38 using namespace DistributedHardware;
CheckSrcPermission(const std::string & sinkNetworkId)39 bool SoftBusPermissionCheck::CheckSrcPermission(const std::string &sinkNetworkId)
40 {
41     LOGI("Begin");
42     AccountInfo localAccountInfo;
43     if (!GetLocalAccountInfo(localAccountInfo)) {
44         LOGE("Get os account data failed");
45         return false;
46     }
47 #ifdef SUPPORT_SAME_ACCOUNT
48     if (!CheckSrcIsSameAccount(sinkNetworkId, localAccountInfo)) {
49         LOGE("Check src same account failed");
50         return false;
51     }
52 #endif
53     return true;
54 }
55 
CheckSinkPermission(const AccountInfo & callerAccountInfo)56 bool SoftBusPermissionCheck::CheckSinkPermission(const AccountInfo &callerAccountInfo)
57 {
58     LOGI("Begin");
59     AccountInfo localAccountInfo;
60     if (!GetLocalAccountInfo(localAccountInfo)) {
61         LOGE("Get local account info failed");
62         return false;
63     }
64 #ifdef SUPPORT_SAME_ACCOUNT
65     if (!CheckSinkIsSameAccount(callerAccountInfo, localAccountInfo)) {
66         LOGE("Check sink same account failed");
67         return false;
68     }
69 #endif
70     return true;
71 }
72 
GetLocalAccountInfo(AccountInfo & localAccountInfo)73 bool SoftBusPermissionCheck::GetLocalAccountInfo(AccountInfo &localAccountInfo)
74 {
75     int32_t userId = GetCurrentUserId();
76     if (userId == INVALID_USER_ID) {
77         LOGE("Get current userid failed");
78         return false;
79     }
80     localAccountInfo.userId_ = userId;
81 #ifdef SUPPORT_SAME_ACCOUNT
82     AccountSA::OhosAccountInfo osAccountInfo;
83     int ret = AccountSA::OhosAccountKits::GetInstance().GetOhosAccountInfo(osAccountInfo);
84     if (ret != 0 || osAccountInfo.uid_ == "") {
85         LOGE("Get accountId from Ohos account info failed, ret: %{public}d.", ret);
86         return false;
87     }
88     localAccountInfo.accountId_ = osAccountInfo.uid_;
89 #endif
90     localAccountInfo.tokenId_ = IPCSkeleton::GetSelfTokenID();
91 
92     if (!GetLocalNetworkId(localAccountInfo.networkId_)) {
93         LOGE("Get local networkid failed");
94         return false;
95     }
96     LOGI("Get local accountinfo success");
97     return true;
98 }
99 
CheckSrcIsSameAccount(const std::string & sinkNetworkId,const AccountInfo & localAccountInfo)100 bool SoftBusPermissionCheck::CheckSrcIsSameAccount(const std::string &sinkNetworkId,
101     const AccountInfo &localAccountInfo)
102 {
103 #ifdef SUPPORT_SAME_ACCOUNT
104     DmAccessCaller caller = {
105         .accountId = localAccountInfo.accountId_,
106         .networkId = localAccountInfo.networkId_,
107         .userId = localAccountInfo.userId_,
108     };
109     DmAccessCallee callee = {
110         .networkId = sinkNetworkId
111     };
112     if (!DeviceManager::GetInstance().CheckSrcIsSameAccount(caller, callee)) {
113         LOGE("Check src same account failed");
114         return false;
115     }
116 #endif
117     return true;
118 }
119 
CheckSinkIsSameAccount(const AccountInfo & callerAccountInfo,const AccountInfo & calleeAccountInfo)120 bool SoftBusPermissionCheck::CheckSinkIsSameAccount(const AccountInfo &callerAccountInfo,
121     const AccountInfo &calleeAccountInfo)
122 {
123 #ifdef SUPPORT_SAME_ACCOUNT
124     DmAccessCaller caller = {
125         .accountId = callerAccountInfo.accountId_,
126         .networkId = callerAccountInfo.networkId_,
127         .userId = callerAccountInfo.userId_,
128     };
129     DmAccessCallee callee = {
130         .accountId = calleeAccountInfo.accountId_,
131         .networkId = calleeAccountInfo.networkId_,
132         .userId = calleeAccountInfo.userId_,
133     };
134     if (!DeviceManager::GetInstance().CheckSinkIsSameAccount(caller, callee)) {
135         LOGE("Check sink same account failed");
136         return false;
137     }
138 #endif
139     return true;
140 }
141 
CheckSrcAccessControl(const std::string & sinkNetworkId,const AccountInfo & localAccountInfo)142 bool SoftBusPermissionCheck::CheckSrcAccessControl(const std::string &sinkNetworkId,
143     const AccountInfo &localAccountInfo)
144 {
145     DmAccessCaller caller = {
146         .accountId = localAccountInfo.accountId_,
147         .pkgName = SERVICE_NAME,
148         .networkId = localAccountInfo.networkId_,
149         .userId = localAccountInfo.userId_,
150         .tokenId = localAccountInfo.tokenId_,
151     };
152     DmAccessCallee callee = {
153         .networkId = sinkNetworkId,
154     };
155     if (!DeviceManager::GetInstance().CheckSrcAccessControl(caller, callee)) {
156         LOGE("Check src acl failed");
157         return false;
158     }
159     return true;
160 }
161 
CheckSinkAccessControl(const AccountInfo & callerAccountInfo,const AccountInfo & calleeAccountInfo)162 bool SoftBusPermissionCheck::CheckSinkAccessControl(const AccountInfo &callerAccountInfo,
163     const AccountInfo &calleeAccountInfo)
164 {
165     DmAccessCaller caller = {
166         .accountId = callerAccountInfo.accountId_,
167         .pkgName = SERVICE_NAME,
168         .networkId = callerAccountInfo.networkId_,
169         .userId = callerAccountInfo.userId_,
170         .tokenId = callerAccountInfo.tokenId_,
171     };
172     DmAccessCallee callee = {
173         .accountId = calleeAccountInfo.accountId_,
174         .networkId = calleeAccountInfo.networkId_,
175         .pkgName = SERVICE_NAME,
176         .userId = calleeAccountInfo.userId_,
177         .tokenId = calleeAccountInfo.tokenId_,
178     };
179     if (!DeviceManager::GetInstance().CheckSinkAccessControl(caller, callee)) {
180         LOGE("Check sink acl failed");
181         return false;
182     }
183     return true;
184 }
185 
GetCurrentUserId()186 int32_t SoftBusPermissionCheck::GetCurrentUserId()
187 {
188     std::vector<int32_t> userIds{};
189     auto ret = AccountSA::OsAccountManager::QueryActiveOsAccountIds(userIds);
190     if (ret != NO_ERROR || userIds.empty()) {
191         LOGE("Query active os account id failed, ret = %{public}d", ret);
192         return INVALID_USER_ID;
193     }
194     return userIds[0];
195 }
196 
GetLocalNetworkId(std::string & networkId)197 bool SoftBusPermissionCheck::GetLocalNetworkId(std::string &networkId)
198 {
199     DistributedHardware::DmDeviceInfo localDeviceInfo{};
200     int errCode = DeviceManager::GetInstance().GetLocalDeviceInfo(SERVICE_NAME, localDeviceInfo);
201     if (errCode != 0) {
202         LOGE("Get localdeviceInfo failed, ret = %{public}d", errCode);
203         return false;
204     }
205     networkId = localDeviceInfo.networkId;
206     return true;
207 }
208 
SetAccessInfoToSocket(const int32_t sessionId)209 bool SoftBusPermissionCheck::SetAccessInfoToSocket(const int32_t sessionId)
210 {
211 #ifdef SUPPORT_SAME_ACCOUNT
212     AccountInfo accountInfo;
213     if (!GetLocalAccountInfo(accountInfo)) {
214         LOGE("GetOsAccountData failed.");
215         return false;
216     }
217     nlohmann::json jsonObj;
218     jsonObj[ACCOUNT_ID] = accountInfo.accountId_;
219 
220     SocketAccessInfo accessInfo;
221     accessInfo.userId = accountInfo.userId_;
222     std::string jsonStr = jsonObj.dump();
223     size_t len = jsonStr.size();
224     std::shared_ptr<char> charArr(new char[len + 1], [](char *p) {delete[] p;});
225     if (strcpy_s(charArr.get(), len + 1, jsonStr.c_str()) != 0) {
226         LOGE("strcpy_s failed.");
227         return false;
228     }
229     accessInfo.extraAccessInfo = charArr.get();
230     accessInfo.localTokenId = accountInfo.tokenId_;
231     if (SetAccessInfo(sessionId, accessInfo) != 0) {
232         LOGE("set access info failed");
233         return false;
234     }
235 #endif
236     return true;
237 }
238 
TransCallerInfo(SocketAccessInfo * callerInfo,AccountInfo & callerAccountInfo,const std::string & networkId)239 bool SoftBusPermissionCheck::TransCallerInfo(SocketAccessInfo *callerInfo,
240     AccountInfo &callerAccountInfo, const std::string &networkId)
241 {
242     if (callerInfo == nullptr || callerInfo->extraAccessInfo == nullptr) {
243         LOGE("callerInfo or extraAccessInfo is nullptr.");
244         return true;
245     }
246     nlohmann::json jsonObj = nlohmann::json::parse(std::string(callerInfo->extraAccessInfo), nullptr, false);
247     if (jsonObj.is_discarded()) {
248         LOGE("jsonObj parse failed.");
249         return false;
250     }
251     if (!jsonObj.contains(ACCOUNT_ID) || !jsonObj[ACCOUNT_ID].is_string()) {
252         LOGE("get ext jsonObj parse failed.");
253         return false;
254     }
255     callerAccountInfo.accountId_ = jsonObj[ACCOUNT_ID].get<std::string>();
256     callerAccountInfo.userId_ = callerInfo->userId;
257     callerAccountInfo.networkId_ = networkId;
258     LOGI("TransCallerInfo success");
259     return true;
260 }
261 
FillLocalInfo(SocketAccessInfo * localInfo)262 bool SoftBusPermissionCheck::FillLocalInfo(SocketAccessInfo *localInfo)
263 {
264     if (localInfo == nullptr) {
265         LOGE("localInfo is nullptr.");
266         return false;
267     }
268     int32_t userId = GetCurrentUserId();
269     if (userId == INVALID_USER_ID) {
270         LOGE("get current user id falied");
271         return false;
272     }
273     localInfo->userId = userId;
274     localInfo->localTokenId = IPCSkeleton::GetSelfTokenID();
275     return true;
276 }
277 
IsSameAccount(const std::string & networkId)278 bool SoftBusPermissionCheck::IsSameAccount(const std::string &networkId)
279 {
280 #ifdef SUPPORT_SAME_ACCOUNT
281     LOGI("SoftBusPermissionCheck::IsSameAccount called");
282     std::vector<DistributedHardware::DmDeviceInfo> deviceList;
283     DistributedHardware::DeviceManager::GetInstance().GetTrustedDeviceList(SERVICE_NAME, "", deviceList);
284     if (deviceList.size() == 0 || deviceList.size() > MAX_ONLINE_DEVICE_SIZE) {
285         LOGE("Trust device list size is invalid, size=%zu", deviceList.size());
286         return false;
287     }
288     DistributedHardware::DmDeviceInfo deviceInfoTemp;
289     for (const auto &deviceInfo : deviceList) {
290         if (std::string(deviceInfo.networkId) == networkId) {
291             deviceInfoTemp = deviceInfo;
292             break;
293         }
294     }
295     if (deviceInfoTemp.authForm != DistributedHardware::DmAuthForm::IDENTICAL_ACCOUNT) {
296         LOGE("The source and sink device is not same account, not support.");
297         return false;
298     }
299     if (deviceInfoTemp.extraData.empty()) {
300         LOGE("Device extraData is empty");
301         return false;
302     }
303     nlohmann::json entraDataJson = nlohmann::json::parse(deviceInfoTemp.extraData, nullptr, false);
304     if (entraDataJson.is_discarded()) {
305         LOGE("Device entraDataJson parse failed.");
306         return false;
307     }
308     if (!Utils::IsInt32(entraDataJson, PARAM_KEY_OS_TYPE)) {
309         LOGE("Device error json int32_t param.");
310         return false;
311     }
312     int32_t osType = entraDataJson[PARAM_KEY_OS_TYPE].get<int32_t>();
313     if (osType != DEVICE_OS_TYPE_OH) {
314         LOGE("Device os type = %{public}d is not openharmony.", osType);
315         return false;
316     }
317     LOGI("SoftBusPermissionCheck::IsSameAccount end");
318 #endif
319     return true;
320 }
321 } // namespace DistributedFile
322 } // namespace Storage
323 } // namespace OHOS