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