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 "route_head_handler_impl.h"
16
17 #define LOG_TAG "RouteHeadHandler"
18
19 #include "auth/auth_delegate.h"
20 #include "device_kvstore_impl.h"
21 #include "kvstore_meta_manager.h"
22 #include "log_print.h"
23 #include "securec.h"
24 #include "upgrade_manager.h"
25 #include "utils/anonymous.h"
26 #include "utils/endian_converter.h"
27
28 namespace OHOS::DistributedData {
29 using namespace OHOS::DistributedKv;
30 constexpr const int ALIGN_WIDTH = 8;
Create(const ExtendInfo & info)31 std::shared_ptr<RouteHeadHandler> RouteHeadHandlerImpl::Create(const ExtendInfo &info)
32 {
33 auto handler = std::make_shared<RouteHeadHandlerImpl>(info);
34 if (handler == nullptr) {
35 ZLOGE("new instance failed");
36 return nullptr;
37 }
38 handler->Init();
39 return handler;
40 }
41
RouteHeadHandlerImpl(const ExtendInfo & info)42 RouteHeadHandlerImpl::RouteHeadHandlerImpl(const ExtendInfo &info)
43 : userId_(info.userId), appId_(info.appId), storeId_(info.storeId), deviceId_(info.dstTarget), headSize_(0)
44 {
45 ZLOGI("init route handler, app:%{public}s, user:%{public}s, peer:%{public}s", appId_.c_str(), userId_.c_str(),
46 deviceId_.c_str());
47 }
48
Init()49 void RouteHeadHandlerImpl::Init()
50 {
51 ZLOGD("begin");
52 if (deviceId_.empty()) {
53 return;
54 }
55 SessionPoint localPoint { DeviceKvStoreImpl::GetLocalDeviceId(), std::stoi(userId_), appId_ };
56 session_ = SessionManager::GetInstance().GetSession(localPoint, deviceId_);
57 ZLOGD("valid session:appId:%{public}s, srcDevId:%{public}s, srcUser:%{public}u, trgDevId:%{public}s,",
58 session_.appId.c_str(), Anonymous::Change(session_.sourceDeviceId).c_str(),
59 session_.sourceUserId, Anonymous::Change(session_.targetDeviceId).c_str());
60 }
61
GetHeadDataSize(uint32_t & headSize)62 DistributedDB::DBStatus RouteHeadHandlerImpl::GetHeadDataSize(uint32_t &headSize)
63 {
64 ZLOGD("begin");
65 headSize = 0;
66 if (appId_ == DistributedKv::KvStoreMetaManager::META_DB_APP_ID) {
67 ZLOGI("meta data permitted");
68 return DistributedDB::OK;
69 }
70 bool flag = false;
71 auto peerCap = UpgradeManager::GetInstance().GetCapability(session_.targetDeviceId, flag);
72 if (!flag) {
73 ZLOGI("get peer cap failed");
74 return DistributedDB::DB_ERROR;
75 }
76 if (peerCap.version == CapMetaData::INVALID_VERSION) {
77 // older versions ignore pack extend head
78 ZLOGI("ignore older version device");
79 return DistributedDB::OK;
80 }
81 if (!session_.IsValid()) {
82 ZLOGI("no valid session to peer device");
83 return DistributedDB::DB_ERROR;
84 }
85 size_t expectSize = sizeof(RouteHead) + sizeof(SessionDevicePair) + sizeof(SessionUserPair)
86 + session_.targetUserIds.size() * sizeof(int) + sizeof(SessionAppId) + session_.appId.size();
87
88 // align message uint width
89 headSize = GET_ALIGNED_SIZE(expectSize, ALIGN_WIDTH);
90 ZLOGI("packed size:%{public}u", headSize);
91 headSize_ = headSize;
92 return DistributedDB::OK;
93 }
94
FillHeadData(uint8_t * data,uint32_t headSize,uint32_t totalLen)95 DistributedDB::DBStatus RouteHeadHandlerImpl::FillHeadData(uint8_t *data, uint32_t headSize, uint32_t totalLen)
96 {
97 ZLOGD("begin");
98 if (headSize != headSize_) {
99 ZLOGI("size not match");
100 return DistributedDB::DB_ERROR;
101 }
102 if (headSize_ == 0) {
103 ZLOGI("ignore older version device");
104 return DistributedDB::OK;
105 }
106 auto packRet = PackData(data, headSize);
107 ZLOGD("pack result:%{public}d", packRet);
108 return packRet ? DistributedDB::OK : DistributedDB::DB_ERROR;
109 }
110
PackData(uint8_t * data,uint32_t totalLen)111 bool RouteHeadHandlerImpl::PackData(uint8_t *data, uint32_t totalLen)
112 {
113 if (headSize_ > totalLen) {
114 ZLOGE("the buffer size is not enough");
115 return false;
116 }
117
118 auto isOk = PackDataHead(data, headSize_);
119 if (isOk) {
120 return PackDataBody(data + sizeof(RouteHead), headSize_ - sizeof(RouteHead));
121 }
122 return false;
123 }
124
PackDataHead(uint8_t * data,uint32_t totalLen)125 bool RouteHeadHandlerImpl::PackDataHead(uint8_t *data, uint32_t totalLen)
126 {
127 uint8_t *ptr = data;
128 if (headSize_ < sizeof(RouteHead)) {
129 return false;
130 }
131 RouteHead *head = reinterpret_cast<RouteHead *>(ptr);
132 head->magic = HostToNet(RouteHead::MAGIC_NUMBER);
133 head->version = HostToNet(RouteHead::VERSION);
134 head->checkSum = HostToNet(uint64_t(0));
135 head->dataLen = HostToNet(uint32_t(totalLen - sizeof(RouteHead)));
136 return true;
137 }
138
PackDataBody(uint8_t * data,uint32_t totalLen)139 bool RouteHeadHandlerImpl::PackDataBody(uint8_t *data, uint32_t totalLen)
140 {
141 uint8_t *ptr = data;
142 SessionDevicePair *devicePair = reinterpret_cast<SessionDevicePair *>(ptr);
143 auto ret = strcpy_s(devicePair->sourceDeviceId, DEVICE_ID_SIZE_MAX, session_.sourceDeviceId.c_str());
144 if (ret != 0) {
145 ZLOGE("strcpy for source device id failed");
146 return false;
147 }
148 ret = strcpy_s(devicePair->targetDeviceId, DEVICE_ID_SIZE_MAX, session_.targetDeviceId.c_str());
149 if (ret != 0) {
150 ZLOGE("strcpy for target device id failed");
151 return false;
152 }
153 ptr += sizeof(SessionDevicePair);
154
155 SessionUserPair *userPair = reinterpret_cast<SessionUserPair *>(ptr);
156 userPair->sourceUserId = HostToNet(session_.sourceUserId);
157 userPair->targetUserCount = session_.targetUserIds.size();
158 for (size_t i = 0; i < session_.targetUserIds.size(); ++i) {
159 *(userPair->targetUserIds + i) = HostToNet(session_.targetUserIds[i]);
160 }
161 ptr += (sizeof(SessionUserPair) + session_.targetUserIds.size() * sizeof(int));
162
163 SessionAppId *appPair = reinterpret_cast<SessionAppId *>(ptr);
164 ptr += sizeof(SessionAppId);
165
166 uint32_t appLen = data + totalLen - ptr;
167 appPair->len = HostToNet(appLen); // left size
168 ret = strcpy_s(appPair->appId, appLen, session_.appId.c_str());
169 if (ret != 0) {
170 ZLOGE("strcpy for app id failed");
171 return false;
172 }
173 return true;
174 }
175
ParseHeadData(const uint8_t * data,uint32_t len,uint32_t & headSize,std::vector<std::string> & users)176 bool RouteHeadHandlerImpl::ParseHeadData(
177 const uint8_t *data, uint32_t len, uint32_t &headSize, std::vector<std::string> &users)
178 {
179 auto ret = UnPackData(data, len, headSize);
180 if (!ret) {
181 headSize = 0;
182 ZLOGE("unpack data head failed");
183 return false;
184 }
185 ZLOGI("unpacked size:%{public}u", headSize);
186 // flip the local and peer ends
187 SessionPoint local { .deviceId = session_.targetDeviceId, .appId = session_.appId };
188 SessionPoint peer { .deviceId = session_.sourceDeviceId, .userId = session_.sourceUserId, .appId = session_.appId };
189 ZLOGD("valid session:appId:%{public}s, srcDevId:%{public}s, srcUser:%{public}u, trgDevId:%{public}s,",
190 session_.appId.c_str(), Anonymous::Change(session_.sourceDeviceId).c_str(),
191 session_.sourceUserId, Anonymous::Change(session_.targetDeviceId).c_str());
192 for (const auto &item : session_.targetUserIds) {
193 local.userId = item;
194 if (SessionManager::GetInstance().CheckSession(local, peer)) {
195 users.emplace_back(std::to_string(item));
196 }
197 }
198 return true;
199 }
200
UnPackData(const uint8_t * data,uint32_t totalLen,uint32_t & unpackedSize)201 bool RouteHeadHandlerImpl::UnPackData(const uint8_t *data, uint32_t totalLen, uint32_t &unpackedSize)
202 {
203 if (data == nullptr || totalLen < sizeof(RouteHead)) {
204 ZLOGE("invalid input data");
205 return false;
206 }
207 unpackedSize = 0;
208 RouteHead head = { 0 };
209 bool result = UnPackDataHead(data, totalLen, head);
210 if (result && head.version == RouteHead::VERSION) {
211 auto isOk = UnPackDataBody(data + sizeof(RouteHead), totalLen - sizeof(RouteHead));
212 if (isOk) {
213 unpackedSize = sizeof(RouteHead) + head.dataLen;
214 }
215 return isOk;
216 }
217 return false;
218 }
219
UnPackDataHead(const uint8_t * data,uint32_t totalLen,RouteHead & routeHead)220 bool RouteHeadHandlerImpl::UnPackDataHead(const uint8_t *data, uint32_t totalLen, RouteHead &routeHead)
221 {
222 if (totalLen < sizeof(RouteHead)) {
223 ZLOGE("invalid route head len");
224 return false;
225 }
226 const RouteHead *head = reinterpret_cast<const RouteHead *>(data);
227 routeHead.magic = NetToHost(head->magic);
228 routeHead.version = NetToHost(head->version);
229 routeHead.checkSum = NetToHost(head->checkSum);
230 routeHead.dataLen = NetToHost(head->dataLen);
231 if (routeHead.magic != RouteHead::MAGIC_NUMBER) {
232 ZLOGW("not route head data");
233 return false;
234 }
235 if (totalLen - sizeof(RouteHead) < routeHead.dataLen) {
236 ZLOGE("invalid route data len");
237 return false;
238 }
239 return true;
240 }
241
UnPackDataBody(const uint8_t * data,uint32_t totalLen)242 bool RouteHeadHandlerImpl::UnPackDataBody(const uint8_t *data, uint32_t totalLen)
243 {
244 const uint8_t *ptr = data;
245 uint32_t leftSize = totalLen;
246
247 if (leftSize < sizeof(SessionDevicePair)) {
248 ZLOGE("failed to parse device pair");
249 return false;
250 }
251 const SessionDevicePair *devicePair = reinterpret_cast<const SessionDevicePair *>(ptr);
252 session_.sourceDeviceId.append(devicePair->sourceDeviceId, DEVICE_ID_SIZE_MAX);
253 session_.targetDeviceId.append(devicePair->targetDeviceId, DEVICE_ID_SIZE_MAX);
254 ptr += sizeof(SessionDevicePair);
255 leftSize -= sizeof(SessionDevicePair);
256
257 if (leftSize < sizeof(SessionUserPair)) {
258 ZLOGE("failed to parse user pair");
259 return false;
260 }
261 const SessionUserPair *userPair = reinterpret_cast<const SessionUserPair *>(ptr);
262 session_.sourceUserId = NetToHost(userPair->sourceUserId);
263
264 auto userPairSize = sizeof(SessionUserPair) + userPair->targetUserCount * sizeof(uint32_t);
265 if (leftSize < userPairSize) {
266 ZLOGE("failed to parse user pair, target user");
267 return false;
268 }
269 for (int i = 0; i < userPair->targetUserCount; ++i) {
270 session_.targetUserIds.push_back(NetToHost(*(userPair->targetUserIds + i)));
271 }
272 ptr += userPairSize;
273 leftSize -= userPairSize;
274
275 if (leftSize < sizeof(SessionAppId)) {
276 ZLOGE("failed to parse app id len");
277 return false;
278 }
279 const SessionAppId *appId = reinterpret_cast<const SessionAppId *>(ptr);
280 auto appIdLen = NetToHost(appId->len);
281 if (leftSize - sizeof(SessionAppId) < appIdLen) {
282 ZLOGE("failed to parse app id");
283 return false;
284 }
285 session_.appId.append(appId->appId, appIdLen);
286 return true;
287 }
288 } // namespace OHOS::DistributedData
289