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