1 /*
2 * Copyright (c) 2024 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 "relationship_sync_mgr.h"
17
18 #include <cstdint>
19 #include <vector>
20 #include "dm_crypto.h"
21 #include "dm_log.h"
22
23 namespace OHOS {
24 namespace DistributedHardware {
25 DM_IMPLEMENT_SINGLE_INSTANCE(ReleationShipSyncMgr);
26 namespace {
27 /**
28 * @brief account logout payload length 8
29 * | 2 bytes | 6 bytes |
30 * | userid lower 2 bytes | account id first 6 bytes |
31 */
32 const int32_t ACCOUNT_LOGOUT_PAYLOAD_LEN = 8;
33 /**
34 * @brief device unbind payload length 2
35 * | 2 bytes |
36 * | userid lower 2 bytes |
37 */
38 const int32_t DEVICE_UNBIND_PAYLOAD_LEN = 2;
39 /**
40 * @brief app unbind payload length 6
41 * | 2 bytes | 4 bytes |
42 * | userid lower 2 bytes | token id lower 4 bytes |
43 */
44 const int32_t APP_UNBIND_PAYLOAD_LEN = 6;
45 const int32_t USERID_PAYLOAD_LEN = 2;
46 const int32_t ACCOUNTID_PAYLOAD_LEN = 6;
47 const int32_t BIT_PER_BYTES = 8;
48 const int32_t INVALIED_PAYLOAD_SIZE = 12;
49
50 const char * const MSG_TYPE = "TYPE";
51 const char * const MSG_VALUE = "VALUE";
52 const char * const MSG_PEER_UDID = "PEER_UDID";
53 const char * const MSG_ACCOUNTID = "ACCOUNTID";
54 }
55
RelationShipChangeMsg()56 RelationShipChangeMsg::RelationShipChangeMsg() : type(RelationShipChangeType::TYPE_MAX),
57 userId(UINT32_MAX), accountId(""), tokenId(UINT64_MAX), peerUdid("")
58 {
59 }
60
ToBroadcastPayLoad(uint8_t *&msg, uint32_t &len) const61 bool RelationShipChangeMsg::ToBroadcastPayLoad(uint8_t *&msg, uint32_t &len) const
62 {
63 if (!IsValid()) {
64 LOGE("invalid");
65 return false;
66 }
67
68 bool ret = false;
69 switch (type) {
70 case RelationShipChangeType::ACCOUNT_LOGOUT:
71 ToAccountLogoutPayLoad(msg, len);
72 ret = true;
73 break;
74 case RelationShipChangeType::DEVICE_UNBIND:
75 ToDeviceUnbindPayLoad(msg, len);
76 ret = true;
77 break;
78 case RelationShipChangeType::APP_UNBIND:
79 ToAppUnbindPayLoad(msg, len);
80 ret = true;
81 break;
82 default:
83 LOGE("RelationShipChange type invalid");
84 break;
85 }
86 return ret;
87 }
88
FromBroadcastPayLoad(const cJSON *payloadJson, RelationShipChangeType type)89 bool RelationShipChangeMsg::FromBroadcastPayLoad(const cJSON *payloadJson, RelationShipChangeType type)
90 {
91 LOGI("FromBroadcastPayLoad type %{public}d.", type);
92 if (type == RelationShipChangeType::TYPE_MAX) {
93 LOGE("ChangeType invalid, type: %{public}d", type);
94 return false;
95 }
96 bool ret = false;
97 switch (type) {
98 case RelationShipChangeType::ACCOUNT_LOGOUT:
99 ret = FromAccountLogoutPayLoad(payloadJson);
100 break;
101 case RelationShipChangeType::DEVICE_UNBIND:
102 ret = FromDeviceUnbindPayLoad(payloadJson);
103 break;
104 case RelationShipChangeType::APP_UNBIND:
105 ret = FromAppUnbindPayLoad(payloadJson);
106 break;
107 default:
108 LOGE("RelationShipChange type invalid");
109 break;
110 }
111 return ret;
112 }
113
IsValid() const114 bool RelationShipChangeMsg::IsValid() const
115 {
116 bool ret = false;
117 switch (type) {
118 case RelationShipChangeType::ACCOUNT_LOGOUT:
119 ret = (userId != UINT32_MAX && accountId.length() >= ACCOUNTID_PAYLOAD_LEN);
120 break;
121 case RelationShipChangeType::DEVICE_UNBIND:
122 ret = (userId != UINT32_MAX);
123 break;
124 case RelationShipChangeType::APP_UNBIND:
125 ret = (userId != UINT32_MAX && tokenId != UINT64_MAX);
126 break;
127 case RelationShipChangeType::SERVICE_UNBIND:
128 case RelationShipChangeType::DEL_USER:
129 case RelationShipChangeType::APP_UNINSTALL:
130 // current NOT support
131 ret = false;
132 break;
133 case RelationShipChangeType::TYPE_MAX:
134 ret = false;
135 break;
136 default:
137 ret = false;
138 break;
139 }
140 return ret;
141 }
142
IsChangeTypeValid()143 bool RelationShipChangeMsg::IsChangeTypeValid()
144 {
145 return (type == RelationShipChangeType::ACCOUNT_LOGOUT) || (type == RelationShipChangeType::DEVICE_UNBIND) ||
146 (type == RelationShipChangeType::APP_UNBIND);
147 }
148
IsChangeTypeValid(uint32_t type)149 bool RelationShipChangeMsg::IsChangeTypeValid(uint32_t type)
150 {
151 return (type == (uint32_t)RelationShipChangeType::ACCOUNT_LOGOUT) ||
152 (type == (uint32_t)RelationShipChangeType::DEVICE_UNBIND) ||
153 (type == (uint32_t)RelationShipChangeType::APP_UNBIND);
154 }
155
ToAccountLogoutPayLoad(uint8_t *&msg, uint32_t &len) const156 void RelationShipChangeMsg::ToAccountLogoutPayLoad(uint8_t *&msg, uint32_t &len) const
157 {
158 msg = new uint8_t[ACCOUNT_LOGOUT_PAYLOAD_LEN]();
159 for (int i = 0; i < USERID_PAYLOAD_LEN; i++) {
160 msg[i] |= (userId >> (i * BIT_PER_BYTES)) & 0xFF;
161 }
162
163 for (int j = USERID_PAYLOAD_LEN; j < ACCOUNT_LOGOUT_PAYLOAD_LEN; j++) {
164 msg[j] = accountId[j - USERID_PAYLOAD_LEN];
165 }
166 len = ACCOUNT_LOGOUT_PAYLOAD_LEN;
167 }
168
ToDeviceUnbindPayLoad(uint8_t *&msg, uint32_t &len) const169 void RelationShipChangeMsg::ToDeviceUnbindPayLoad(uint8_t *&msg, uint32_t &len) const
170 {
171 msg = new uint8_t[DEVICE_UNBIND_PAYLOAD_LEN]();
172 for (int i = 0; i < USERID_PAYLOAD_LEN; i++) {
173 msg[i] |= (userId >> (i * BIT_PER_BYTES)) & 0xFF;
174 }
175 len = DEVICE_UNBIND_PAYLOAD_LEN;
176 }
177
ToAppUnbindPayLoad(uint8_t *&msg, uint32_t &len) const178 void RelationShipChangeMsg::ToAppUnbindPayLoad(uint8_t *&msg, uint32_t &len) const
179 {
180 msg = new uint8_t[APP_UNBIND_PAYLOAD_LEN]();
181 for (int i = 0; i < USERID_PAYLOAD_LEN; i++) {
182 msg[i] |= (userId >> (i * BIT_PER_BYTES)) & 0xFF;
183 }
184
185 for (int i = USERID_PAYLOAD_LEN; i < APP_UNBIND_PAYLOAD_LEN; i++) {
186 msg[i] |= (tokenId >> ((i - USERID_PAYLOAD_LEN) * BIT_PER_BYTES)) & 0xFF;
187 }
188
189 len = APP_UNBIND_PAYLOAD_LEN;
190 }
191
FromAccountLogoutPayLoad(const cJSON *payloadJson)192 bool RelationShipChangeMsg::FromAccountLogoutPayLoad(const cJSON *payloadJson)
193 {
194 if (payloadJson == NULL) {
195 LOGE("Account logout payloadJson is null.");
196 return false;
197 }
198 int32_t arraySize = cJSON_GetArraySize(payloadJson);
199 if (arraySize < ACCOUNT_LOGOUT_PAYLOAD_LEN || arraySize > INVALIED_PAYLOAD_SIZE) {
200 LOGE("Payload invalied,the size is %{public}d.", arraySize);
201 return false;
202 }
203 userId = 0;
204 for (uint32_t i = 0; i < USERID_PAYLOAD_LEN; i++) {
205 cJSON *payloadItem = cJSON_GetArrayItem(payloadJson, i);
206 CHECK_NULL_RETURN(payloadItem, false);
207 if (cJSON_IsNumber(payloadItem)) {
208 userId |= (static_cast<uint8_t>(payloadItem->valueint)) << (i * BIT_PER_BYTES);
209 }
210 }
211 accountId = "";
212 for (uint32_t j = USERID_PAYLOAD_LEN; j < ACCOUNT_LOGOUT_PAYLOAD_LEN; j++) {
213 cJSON *payloadItem = cJSON_GetArrayItem(payloadJson, j);
214 CHECK_NULL_RETURN(payloadItem, false);
215 if (cJSON_IsNumber(payloadItem)) {
216 accountId += static_cast<char>(payloadItem->valueint);
217 }
218 }
219 return true;
220 }
221
FromDeviceUnbindPayLoad(const cJSON *payloadJson)222 bool RelationShipChangeMsg::FromDeviceUnbindPayLoad(const cJSON *payloadJson)
223 {
224 if (payloadJson == NULL) {
225 LOGE("Device unbind payloadJson is null.");
226 return false;
227 }
228 int32_t arraySize = cJSON_GetArraySize(payloadJson);
229 if (arraySize < ACCOUNT_LOGOUT_PAYLOAD_LEN || arraySize > INVALIED_PAYLOAD_SIZE) {
230 LOGE("Payload invalied,the size is %{public}d.", arraySize);
231 return false;
232 }
233 userId = 0;
234 for (uint32_t i = 0; i < USERID_PAYLOAD_LEN; i++) {
235 cJSON *payloadItem = cJSON_GetArrayItem(payloadJson, i);
236 CHECK_NULL_RETURN(payloadItem, false);
237 if (cJSON_IsNumber(payloadItem)) {
238 userId |= (static_cast<uint8_t>(payloadItem->valueint)) << (i * BIT_PER_BYTES);
239 }
240 }
241 return true;
242 }
243
FromAppUnbindPayLoad(const cJSON *payloadJson)244 bool RelationShipChangeMsg::FromAppUnbindPayLoad(const cJSON *payloadJson)
245 {
246 if (payloadJson == NULL) {
247 LOGE("App unbind payloadJson is null.");
248 return false;
249 }
250 int32_t arraySize = cJSON_GetArraySize(payloadJson);
251 if (arraySize < ACCOUNT_LOGOUT_PAYLOAD_LEN || arraySize > INVALIED_PAYLOAD_SIZE) {
252 LOGE("Payload invalied,the size is %{public}d.", arraySize);
253 return false;
254 }
255 userId = 0;
256 for (uint32_t i = 0; i < USERID_PAYLOAD_LEN; i++) {
257 cJSON *payloadItem = cJSON_GetArrayItem(payloadJson, i);
258 CHECK_NULL_RETURN(payloadItem, false);
259 if (cJSON_IsNumber(payloadItem)) {
260 userId |= (static_cast<uint8_t>(payloadItem->valueint)) << (i * BIT_PER_BYTES);
261 }
262 }
263 tokenId = 0;
264 for (uint32_t j = USERID_PAYLOAD_LEN; j < APP_UNBIND_PAYLOAD_LEN; j++) {
265 cJSON *payloadItem = cJSON_GetArrayItem(payloadJson, j);
266 CHECK_NULL_RETURN(payloadItem, false);
267 if (cJSON_IsNumber(payloadItem)) {
268 tokenId |= (static_cast<uint8_t>(payloadItem->valueint)) << ((j - USERID_PAYLOAD_LEN) * BIT_PER_BYTES);
269 }
270 }
271 return true;
272 }
273
ToArrayJson() const274 cJSON *RelationShipChangeMsg::ToArrayJson() const
275 {
276 uint8_t *payload = nullptr;
277 uint32_t len = 0;
278 if (!this->ToBroadcastPayLoad(payload, len)) {
279 LOGE("Get broadcast payload failed");
280 return nullptr;
281 }
282 cJSON *arrayObj = cJSON_CreateArray();
283 if (arrayObj == nullptr) {
284 LOGE("cJSON_CreateArray failed");
285 if (payload != nullptr) {
286 delete[] payload;
287 }
288 return nullptr;
289 }
290 for (uint32_t index = 0; index < len; index++) {
291 cJSON_AddItemToArray(arrayObj, cJSON_CreateNumber(payload[index]));
292 }
293 if (payload != nullptr) {
294 delete[] payload;
295 }
296 return arrayObj;
297 }
298
ToJson() const299 std::string RelationShipChangeMsg::ToJson() const
300 {
301 cJSON *msg = cJSON_CreateObject();
302 if (msg == NULL) {
303 LOGE("failed to create cjson object");
304 return "";
305 }
306 cJSON_AddNumberToObject(msg, MSG_TYPE, (uint32_t)type);
307 cJSON *arrayObj = ToArrayJson();
308 if (arrayObj == nullptr) {
309 LOGE("ArrayObj is nullptr.");
310 cJSON_Delete(msg);
311 return "";
312 }
313 cJSON_AddItemToObject(msg, MSG_VALUE, arrayObj);
314
315 cJSON *udidArrayObj = cJSON_CreateArray();
316 if (udidArrayObj == nullptr) {
317 LOGE("cJSON_CreateArray failed");
318 cJSON_Delete(msg);
319 return "";
320 }
321 for (uint32_t index = 0; index < peerUdids.size(); index++) {
322 cJSON_AddItemToArray(udidArrayObj, cJSON_CreateString(peerUdids[index].c_str()));
323 }
324 cJSON_AddItemToObject(msg, MSG_PEER_UDID, udidArrayObj);
325 cJSON_AddStringToObject(msg, MSG_ACCOUNTID, accountName.c_str());
326 char *retStr = cJSON_PrintUnformatted(msg);
327 if (retStr == nullptr) {
328 LOGE("to json is nullptr.");
329 cJSON_Delete(msg);
330 return "";
331 }
332 std::string ret = std::string(retStr);
333 cJSON_Delete(msg);
334 cJSON_free(retStr);
335 return ret;
336 }
337
FromJson(const std::string &msgJson)338 bool RelationShipChangeMsg::FromJson(const std::string &msgJson)
339 {
340 cJSON *msgObj = cJSON_Parse(msgJson.c_str());
341 if (msgObj == NULL) {
342 LOGE("parse msg failed");
343 return false;
344 }
345
346 cJSON *typeJson = cJSON_GetObjectItem(msgObj, MSG_TYPE);
347 if (typeJson == NULL || !cJSON_IsNumber(typeJson) || !IsChangeTypeValid(typeJson->valueint)) {
348 LOGE("parse type failed.");
349 cJSON_Delete(msgObj);
350 return false;
351 }
352 this->type = (RelationShipChangeType)typeJson->valueint;
353
354 cJSON *payloadJson = cJSON_GetObjectItem(msgObj, MSG_VALUE);
355 if (payloadJson == NULL || !cJSON_IsArray(payloadJson)) {
356 LOGE("parse payload failed.");
357 cJSON_Delete(msgObj);
358 return false;
359 }
360 if (!this->FromBroadcastPayLoad(payloadJson, type)) {
361 LOGE("parse payload error.");
362 cJSON_Delete(msgObj);
363 return false;
364 }
365
366 cJSON *peerUdidJson = cJSON_GetObjectItem(msgObj, MSG_PEER_UDID);
367 if (peerUdidJson == NULL || !cJSON_IsString(peerUdidJson)) {
368 LOGE("parse peer udid failed.");
369 cJSON_Delete(msgObj);
370 return false;
371 }
372 this->peerUdid = std::string(peerUdidJson->valuestring);
373 cJSON_Delete(msgObj);
374 return true;
375 }
376
SyncTrustRelationShip(const RelationShipChangeMsg &msg)377 std::string ReleationShipSyncMgr::SyncTrustRelationShip(const RelationShipChangeMsg &msg)
378 {
379 return msg.ToJson();
380 }
381
ParseTrustRelationShipChange(const std::string &msgJson)382 RelationShipChangeMsg ReleationShipSyncMgr::ParseTrustRelationShipChange(const std::string &msgJson)
383 {
384 RelationShipChangeMsg msgObj;
385 if (!msgObj.FromJson(msgJson)) {
386 LOGE("Parse json failed");
387 }
388 return msgObj;
389 }
390 } // DistributedHardware
391 } // OHOS