1 /*
2 * Copyright (c) 2022 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 #include "soft_bus_manager.h"
16
17 #include <securec.h>
18 #include "constant_common.h"
19 #include "device_info_manager.h"
20 #include "softbus_bus_center.h"
21 #include "dm_device_info.h"
22 #include "remote_command_manager.h"
23
24 namespace OHOS {
25 namespace Security {
26 namespace AccessToken {
27 namespace {
28 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_ACCESSTOKEN, "SoftBusManager"};
29 }
30 namespace {
31 static const std::string SESSION_GROUP_ID = "atm_dsoftbus_session_group_id";
32 static const SessionAttribute SESSION_ATTR = {.dataType = TYPE_BYTES};
33
34 static const int REASON_EXIST = -3;
35 static const int OPENSESSION_RETRY_TIMES = 10 * 3;
36 static const int OPENSESSION_RETRY_INTERVAL_MS = 100;
37 static const int UDID_MAX_LENGTH = 128; // udid/uuid max length
38 } // namespace
39
40 const std::string SoftBusManager::TOKEN_SYNC_PACKAGE_NAME = "ohos.security.distributed_access_token";
41 const std::string SoftBusManager::SESSION_NAME = "ohos.security.atm_channel";
42
SoftBusManager()43 SoftBusManager::SoftBusManager() : isSoftBusServiceBindSuccess_(false), inited_(false), mutex_(), fulfillMutex_()
44 {
45 ACCESSTOKEN_LOG_DEBUG(LABEL, "SoftBusManager()");
46 }
47
~SoftBusManager()48 SoftBusManager::~SoftBusManager()
49 {
50 ACCESSTOKEN_LOG_DEBUG(LABEL, "~SoftBusManager()");
51 }
52
GetInstance()53 SoftBusManager &SoftBusManager::GetInstance()
54 {
55 static SoftBusManager instance;
56 return instance;
57 }
58
AddTrustedDeviceInfo()59 int SoftBusManager::AddTrustedDeviceInfo()
60 {
61 std::string packageName = TOKEN_SYNC_PACKAGE_NAME;
62 std::string extra = "";
63 std::vector<DistributedHardware::DmDeviceInfo> deviceList;
64
65 int32_t ret = DistributedHardware::DeviceManager::GetInstance().GetTrustedDeviceList(packageName,
66 extra, deviceList);
67 if (ret != Constant::SUCCESS) {
68 ACCESSTOKEN_LOG_ERROR(LABEL, "AddTrustedDeviceInfo: GetTrustedDeviceList error, result: %{public}d", ret);
69 return Constant::FAILURE;
70 }
71
72 for (const DistributedHardware::DmDeviceInfo& device : deviceList) {
73 std::string uuid = GetUuidByNodeId(device.networkId);
74 std::string udid = GetUdidByNodeId(device.networkId);
75 if (uuid.empty() || udid.empty()) {
76 ACCESSTOKEN_LOG_ERROR(LABEL, "uuid = %{public}s, udid = %{public}s, uuid or udid is empty, abort.",
77 uuid.c_str(), ConstantCommon::EncryptDevId(udid).c_str());
78 continue;
79 }
80
81 DeviceInfoManager::GetInstance().AddDeviceInfo(device.networkId, uuid, udid, device.deviceName,
82 std::to_string(device.deviceTypeId));
83 RemoteCommandManager::GetInstance().NotifyDeviceOnline(udid);
84 }
85
86 return Constant::SUCCESS;
87 }
88
DeviceInit()89 int SoftBusManager::DeviceInit()
90 {
91 std::string packageName = TOKEN_SYNC_PACKAGE_NAME;
92 std::shared_ptr<MyDmInitCallback> ptrDmInitCallback = std::make_shared<MyDmInitCallback>();
93
94 int ret = DistributedHardware::DeviceManager::GetInstance().InitDeviceManager(packageName, ptrDmInitCallback);
95 if (ret != ERR_OK) {
96 ACCESSTOKEN_LOG_ERROR(LABEL, "Initialize: InitDeviceManager error, result: %{public}d", ret);
97 return ret;
98 }
99
100 ret = AddTrustedDeviceInfo();
101 if (ret != ERR_OK) {
102 ACCESSTOKEN_LOG_ERROR(LABEL, "Initialize: AddTrustedDeviceInfo error, result: %{public}d", ret);
103 return ret;
104 }
105
106 std::string extra = "";
107 std::shared_ptr<SoftBusDeviceConnectionListener> ptrDeviceStateCallback =
108 std::make_shared<SoftBusDeviceConnectionListener>();
109 ret = DistributedHardware::DeviceManager::GetInstance().RegisterDevStateCallback(packageName, extra,
110 ptrDeviceStateCallback);
111 if (ret != ERR_OK) {
112 ACCESSTOKEN_LOG_ERROR(LABEL, "Initialize: RegisterDevStateCallback error, result: %{public}d", ret);
113 return ret;
114 }
115
116 return ERR_OK;
117 }
118
SessionInit()119 int SoftBusManager::SessionInit()
120 {
121 // register session listener
122 ISessionListener sessionListener;
123 sessionListener.OnSessionOpened = SoftBusSessionListener::OnSessionOpened;
124 sessionListener.OnSessionClosed = SoftBusSessionListener::OnSessionClosed;
125 sessionListener.OnBytesReceived = SoftBusSessionListener::OnBytesReceived;
126 sessionListener.OnMessageReceived = SoftBusSessionListener::OnMessageReceived;
127
128 int ret = ::CreateSessionServer(TOKEN_SYNC_PACKAGE_NAME.c_str(), SESSION_NAME.c_str(), &sessionListener);
129 ACCESSTOKEN_LOG_INFO(LABEL, "Initialize: createSessionServer, result: %{public}d", ret);
130 // REASON_EXIST
131 if ((ret != Constant::SUCCESS) && (ret != REASON_EXIST)) {
132 ACCESSTOKEN_LOG_ERROR(LABEL, "Initialize: CreateSessionServer error, result: %{public}d", ret);
133 return ret;
134 }
135
136 return ERR_OK;
137 }
138
Initialize()139 void SoftBusManager::Initialize()
140 {
141 bool inited = false;
142 // cas failed means already inited.
143 if (!inited_.compare_exchange_strong(inited, true)) {
144 ACCESSTOKEN_LOG_DEBUG(LABEL, "already initialized, skip");
145 return;
146 }
147
148 std::function<void()> runner = [&]() {
149 auto sleepTime = std::chrono::milliseconds(1000);
150 while (1) {
151 std::unique_lock<std::mutex> lock(mutex_);
152
153 int ret = DeviceInit();
154 if (ret != ERR_OK) {
155 std::this_thread::sleep_for(sleepTime);
156 continue;
157 }
158
159 ret = SessionInit();
160 if (ret != ERR_OK) {
161 std::this_thread::sleep_for(sleepTime);
162 continue;
163 }
164
165 isSoftBusServiceBindSuccess_ = true;
166 this->FulfillLocalDeviceInfo();
167 return;
168 }
169 };
170
171 std::thread initThread(runner);
172 initThread.detach();
173 ACCESSTOKEN_LOG_DEBUG(LABEL, "Initialize thread started");
174 }
175
Destroy()176 void SoftBusManager::Destroy()
177 {
178 ACCESSTOKEN_LOG_DEBUG(LABEL, "destroy, init: %{public}d, isSoftBusServiceBindSuccess: %{public}d", inited_.load(),
179 isSoftBusServiceBindSuccess_);
180
181 if (!inited_.load()) {
182 ACCESSTOKEN_LOG_DEBUG(LABEL, "not inited, skip");
183 return;
184 }
185
186 std::unique_lock<std::mutex> lock(mutex_);
187 if (!inited_.load()) {
188 ACCESSTOKEN_LOG_DEBUG(LABEL, "not inited, skip");
189 return;
190 }
191
192 if (isSoftBusServiceBindSuccess_) {
193 int32_t ret = ::RemoveSessionServer(TOKEN_SYNC_PACKAGE_NAME.c_str(), SESSION_NAME.c_str());
194 ACCESSTOKEN_LOG_DEBUG(LABEL, "destroy, RemoveSessionServer: %{public}d", ret);
195 isSoftBusServiceBindSuccess_ = false;
196 }
197
198 std::string packageName = TOKEN_SYNC_PACKAGE_NAME;
199 int ret = DistributedHardware::DeviceManager::GetInstance().UnRegisterDevStateCallback(packageName);
200 if (ret != ERR_OK) {
201 ACCESSTOKEN_LOG_ERROR(LABEL, "UnRegisterDevStateCallback failed, code: %{public}d", ret);
202 }
203 ret = DistributedHardware::DeviceManager::GetInstance().UnInitDeviceManager(packageName);
204 if (ret != ERR_OK) {
205 ACCESSTOKEN_LOG_ERROR(LABEL, "UnInitDeviceManager failed, code: %{public}d", ret);
206 }
207
208 inited_.store(false);
209
210 ACCESSTOKEN_LOG_DEBUG(LABEL, "destroy, done");
211 }
212
OpenSession(const std::string & deviceId)213 int32_t SoftBusManager::OpenSession(const std::string &deviceId)
214 {
215 #ifdef DEBUG_API_PERFORMANCE
216 ACCESSTOKEN_LOG_INFO(LABEL, "api_performance:start open session");
217 #endif
218
219 DeviceInfo info;
220 bool result = DeviceInfoManager::GetInstance().GetDeviceInfo(deviceId, DeviceIdType::UNKNOWN, info);
221 if (!result) {
222 ACCESSTOKEN_LOG_WARN(LABEL, "device info notfound for deviceId %{public}s",
223 ConstantCommon::EncryptDevId(deviceId).c_str());
224 return Constant::FAILURE;
225 }
226 std::string networkId = info.deviceId.networkId;
227 ACCESSTOKEN_LOG_INFO(LABEL, "openSession, networkId: %{public}s", networkId.c_str());
228
229 // async open session, should waitting for OnSessionOpened event.
230 int sessionId = ::OpenSession(SESSION_NAME.c_str(), SESSION_NAME.c_str(), networkId.c_str(),
231 SESSION_GROUP_ID.c_str(), &SESSION_ATTR);
232
233 ACCESSTOKEN_LOG_DEBUG(LABEL, "async open session");
234
235 // wait session opening
236 int retryTimes = 0;
237 int logSpan = 10;
238 auto sleepTime = std::chrono::milliseconds(OPENSESSION_RETRY_INTERVAL_MS);
239 while (retryTimes++ < OPENSESSION_RETRY_TIMES) {
240 if (SoftBusSessionListener::GetSessionState(sessionId) < 0) {
241 std::this_thread::sleep_for(sleepTime);
242 if (retryTimes % logSpan == 0) {
243 ACCESSTOKEN_LOG_INFO(LABEL, "openSession, waitting for: %{public}d ms",
244 retryTimes * OPENSESSION_RETRY_INTERVAL_MS);
245 }
246 continue;
247 }
248 break;
249 }
250 #ifdef DEBUG_API_PERFORMANCE
251 ACCESSTOKEN_LOG_INFO(LABEL, "api_performance:start open session success");
252 #endif
253 int64_t state = SoftBusSessionListener::GetSessionState(sessionId);
254 if (state < 0) {
255 ACCESSTOKEN_LOG_ERROR(LABEL, "openSession, timeout, session: %{public}" PRId64, state);
256 return Constant::FAILURE;
257 }
258
259 SoftBusSessionListener::DeleteSessionIdFromMap(sessionId);
260
261 ACCESSTOKEN_LOG_DEBUG(LABEL, "openSession, succeed, session: %{public}" PRId64, state);
262 return sessionId;
263 }
264
CloseSession(int sessionId)265 int SoftBusManager::CloseSession(int sessionId)
266 {
267 if (sessionId < 0) {
268 ACCESSTOKEN_LOG_INFO(LABEL, "closeSession: session is invalid");
269 return Constant::FAILURE;
270 }
271
272 ::CloseSession(sessionId);
273 ACCESSTOKEN_LOG_INFO(LABEL, "closeSession ");
274 return Constant::SUCCESS;
275 }
276
GetUniversallyUniqueIdByNodeId(const std::string & nodeId)277 std::string SoftBusManager::GetUniversallyUniqueIdByNodeId(const std::string &nodeId)
278 {
279 if (!DataValidator::IsDeviceIdValid(nodeId)) {
280 ACCESSTOKEN_LOG_ERROR(LABEL, "invalid nodeId: %{public}s", ConstantCommon::EncryptDevId(nodeId).c_str());
281 return "";
282 }
283
284 std::string uuid = GetUuidByNodeId(nodeId);
285 if (uuid.empty()) {
286 ACCESSTOKEN_LOG_ERROR(LABEL, "softbus return null or empty string");
287 return "";
288 }
289
290 DeviceInfo info;
291 bool result = DeviceInfoManager::GetInstance().GetDeviceInfo(uuid, DeviceIdType::UNIVERSALLY_UNIQUE_ID, info);
292 if (!result) {
293 ACCESSTOKEN_LOG_DEBUG(LABEL, "local device info not found for uuid %{public}s", uuid.c_str());
294 } else {
295 std::string dimUuid = info.deviceId.universallyUniqueId;
296 if (uuid == dimUuid) {
297 // refresh cache
298 std::function<void()> fulfillDeviceInfo = std::bind(&SoftBusManager::FulfillLocalDeviceInfo, this);
299 std::thread fulfill(fulfillDeviceInfo);
300 fulfill.detach();
301 }
302 }
303
304 return uuid;
305 }
306
GetUniqueDeviceIdByNodeId(const std::string & nodeId)307 std::string SoftBusManager::GetUniqueDeviceIdByNodeId(const std::string &nodeId)
308 {
309 if (!DataValidator::IsDeviceIdValid(nodeId)) {
310 ACCESSTOKEN_LOG_ERROR(LABEL, "invalid nodeId: %{public}s", ConstantCommon::EncryptDevId(nodeId).c_str());
311 return "";
312 }
313 std::string udid = GetUdidByNodeId(nodeId);
314 if (udid.empty()) {
315 ACCESSTOKEN_LOG_ERROR(LABEL, "softbus return null or empty string: %{public}s",
316 ConstantCommon::EncryptDevId(udid).c_str());
317 return "";
318 }
319 std::string localUdid = ConstantCommon::GetLocalDeviceId();
320 if (udid == localUdid) {
321 // refresh cache
322 std::function<void()> fulfillDeviceInfo = std::bind(&SoftBusManager::FulfillLocalDeviceInfo, this);
323 std::thread fulfill(fulfillDeviceInfo);
324 fulfill.detach();
325 }
326 return udid;
327 }
328
GetUuidByNodeId(const std::string & nodeId) const329 std::string SoftBusManager::GetUuidByNodeId(const std::string &nodeId) const
330 {
331 uint8_t *info = new (std::nothrow) uint8_t[UDID_MAX_LENGTH + 1];
332 if (info == nullptr) {
333 ACCESSTOKEN_LOG_ERROR(LABEL, "no enough memory: %{public}d", UDID_MAX_LENGTH);
334 return "";
335 }
336 (void)memset_s(info, UDID_MAX_LENGTH + 1, 0, UDID_MAX_LENGTH + 1);
337 int32_t ret = ::GetNodeKeyInfo(TOKEN_SYNC_PACKAGE_NAME.c_str(), nodeId.c_str(),
338 NodeDeviceInfoKey::NODE_KEY_UUID, info, UDID_MAX_LENGTH);
339 if (ret != Constant::SUCCESS) {
340 delete[] info;
341 ACCESSTOKEN_LOG_WARN(LABEL, "GetNodeKeyInfo error, return code: %{public}d", ret);
342 return "";
343 }
344 std::string uuid(reinterpret_cast<char *>(info));
345 delete[] info;
346 ACCESSTOKEN_LOG_DEBUG(LABEL, "call softbus finished. nodeId(in): %{public}s, uuid: %{public}s",
347 ConstantCommon::EncryptDevId(nodeId).c_str(), uuid.c_str());
348 return uuid;
349 }
350
GetUdidByNodeId(const std::string & nodeId) const351 std::string SoftBusManager::GetUdidByNodeId(const std::string &nodeId) const
352 {
353 uint8_t *info = new (std::nothrow) uint8_t[UDID_MAX_LENGTH + 1];
354 if (info == nullptr) {
355 ACCESSTOKEN_LOG_ERROR(LABEL, "no enough memory: %{public}d", UDID_MAX_LENGTH);
356 return "";
357 }
358 (void)memset_s(info, UDID_MAX_LENGTH + 1, 0, UDID_MAX_LENGTH + 1);
359 int32_t ret = ::GetNodeKeyInfo(TOKEN_SYNC_PACKAGE_NAME.c_str(), nodeId.c_str(),
360 NodeDeviceInfoKey::NODE_KEY_UDID, info, UDID_MAX_LENGTH);
361 if (ret != Constant::SUCCESS) {
362 delete[] info;
363 ACCESSTOKEN_LOG_WARN(LABEL, "GetNodeKeyInfo error, code: %{public}d", ret);
364 return "";
365 }
366 std::string udid(reinterpret_cast<char *>(info));
367 delete[] info;
368 ACCESSTOKEN_LOG_DEBUG(LABEL, "call softbus finished: nodeId(in): %{public}s",
369 ConstantCommon::EncryptDevId(nodeId).c_str());
370 return udid;
371 }
372
FulfillLocalDeviceInfo()373 int SoftBusManager::FulfillLocalDeviceInfo()
374 {
375 // repeated task will just skip
376 if (!fulfillMutex_.try_lock()) {
377 ACCESSTOKEN_LOG_INFO(LABEL, "FulfillLocalDeviceInfo already running, skip.");
378 return Constant::SUCCESS;
379 }
380
381 NodeBasicInfo info;
382 int32_t ret = ::GetLocalNodeDeviceInfo(TOKEN_SYNC_PACKAGE_NAME.c_str(), &info);
383 if (ret != Constant::SUCCESS) {
384 ACCESSTOKEN_LOG_ERROR(LABEL, "GetLocalNodeDeviceInfo error");
385 fulfillMutex_.unlock();
386 return Constant::FAILURE;
387 }
388
389 ACCESSTOKEN_LOG_DEBUG(LABEL, "call softbus finished, type:%{public}d", info.deviceTypeId);
390
391 std::string uuid = GetUuidByNodeId(info.networkId);
392 std::string udid = GetUdidByNodeId(info.networkId);
393 if (uuid.empty() || udid.empty()) {
394 ACCESSTOKEN_LOG_ERROR(LABEL, "FulfillLocalDeviceInfo: uuid or udid is empty, abort.");
395 fulfillMutex_.unlock();
396 return Constant::FAILURE;
397 }
398
399 DeviceInfoManager::GetInstance().AddDeviceInfo(info.networkId, uuid, udid, info.deviceName,
400 std::to_string(info.deviceTypeId));
401 ACCESSTOKEN_LOG_DEBUG(LABEL, "AddDeviceInfo finished");
402
403 fulfillMutex_.unlock();
404 return Constant::SUCCESS;
405 }
406 } // namespace AccessToken
407 } // namespace Security
408 } // namespace OHOS
409