1 /*
2 * Copyright (c) 2020 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 "want_utils.h"
17 #include "element_name_utils.h"
18
19 #include <securec.h>
20 #ifdef OHOS_APPEXECFWK_BMS_BUNDLEMANAGER
21 #include <string>
22 #include "ipc_skeleton.h"
23 #endif
24
25 #include "log.h"
26 #include "utils.h"
27
28 #ifdef OHOS_APPEXECFWK_BMS_BUNDLEMANAGER
29 using UriKeyType = enum {
30 BEGIN,
31 DEVICE,
32 BUNDLE,
33 ABILITY,
34 END,
35 };
36
37 using UriProperties = struct {
38 const char *key; /* key of uri property */
39 uint8_t keyLen; /* key length of uri property */
40 UriKeyType type; /* key type of uri property */
41 };
42
43 const static UriProperties URI_PROPERTIES[] = {
44 { "#Want", 5, BEGIN },
45 { "device=", 7, DEVICE },
46 { "bundle=", 7, BUNDLE },
47 { "ability=", 8, ABILITY },
48 { "end", 3, END },
49 };
50
51 constexpr static char URI_SEPARATOR = ';';
52 constexpr static int VALUE_NULL = 0;
53 constexpr static int VALUE_OBJECT = 1;
54 constexpr static int DATA_LENGTH = 2048;
55 #endif
56
57 constexpr uint8_t INT_VALUE_TYPE = 6;
58 constexpr uint8_t STRING_VALUE_TYPE = 13;
59 constexpr uint8_t KEY_VALUE_PAIR_TYPE = 97;
60
ClearWant(Want * want)61 void ClearWant(Want *want)
62 {
63 if (want == nullptr) {
64 return;
65 }
66
67 ClearElement(want->element);
68 AdapterFree(want->element);
69 #ifdef OHOS_APPEXECFWK_BMS_BUNDLEMANAGER
70 AdapterFree(want->sid);
71 #endif
72 AdapterFree(want->data);
73 }
74
SetWantElement(Want * want,ElementName element)75 bool SetWantElement(Want *want, ElementName element)
76 {
77 if (want == nullptr) {
78 return false;
79 }
80
81 ClearElement(want->element);
82 AdapterFree(want->element);
83 want->element = reinterpret_cast<ElementName *>(AdapterMalloc(sizeof(ElementName)));
84 if (want->element == nullptr) {
85 return false;
86 }
87 want->element->deviceId = OHOS::Utils::Strdup(element.deviceId);
88 want->element->bundleName = OHOS::Utils::Strdup(element.bundleName);
89 want->element->abilityName = OHOS::Utils::Strdup(element.abilityName);
90 return true;
91 }
92
EncapTlv(uint8_t type,uint8_t length,const void * value,uint8_t valueLen)93 Tlv *EncapTlv(uint8_t type, uint8_t length, const void *value, uint8_t valueLen)
94 {
95 void *entity = nullptr;
96
97 // Tlv header can only has 2 bytes.
98 uint8_t totalLen = valueLen + 2;
99 entity = AdapterMalloc(totalLen);
100 if (entity == nullptr) {
101 return nullptr;
102 }
103
104 if (memcpy_s((unsigned char *)entity, 1, &type, 1) != 0 ||
105 memcpy_s((unsigned char *)entity + 1, 1, &length, 1) != 0 ||
106 memcpy_s((unsigned char *)entity + 2, valueLen, value, valueLen) != 0) {
107 AdapterFree(entity);
108 return nullptr;
109 }
110
111 Tlv *newTlv = reinterpret_cast<Tlv *>(AdapterMalloc(sizeof(Tlv)));
112 if (newTlv == nullptr) {
113 AdapterFree(entity);
114 return nullptr;
115 }
116
117 newTlv->type = type;
118 newTlv->entity = entity;
119 newTlv->totalLen = totalLen;
120 return newTlv;
121 }
122
FreeTlvStruct(Tlv * tlv)123 void FreeTlvStruct(Tlv *tlv)
124 {
125 AdapterFree(tlv->entity);
126 AdapterFree(tlv);
127 }
128
CombineKeyValueTlv(Tlv * keyTlv,Tlv * valueTlv)129 Tlv *CombineKeyValueTlv(Tlv *keyTlv, Tlv *valueTlv)
130 {
131 uint8_t newTlvValueLen = keyTlv->totalLen + valueTlv->totalLen;
132 void *newTlvValue = AdapterMalloc(newTlvValueLen);
133 if (newTlvValue == nullptr) {
134 return nullptr;
135 }
136 if (memcpy_s((unsigned char *)newTlvValue, keyTlv->totalLen, keyTlv->entity, keyTlv->totalLen) != 0 ||
137 memcpy_s((unsigned char *)newTlvValue + keyTlv->totalLen, valueTlv->totalLen,
138 valueTlv->entity, valueTlv->totalLen) != 0) {
139 AdapterFree(newTlvValue);
140 return nullptr;
141 }
142
143 Tlv *newTlv = EncapTlv(KEY_VALUE_PAIR_TYPE, newTlvValueLen, newTlvValue, newTlvValueLen);
144 AdapterFree(newTlvValue);
145 return newTlv;
146 }
147
UpdateWantData(Want * want,Tlv * tlv)148 bool UpdateWantData(Want *want, Tlv *tlv)
149 {
150 bool result = false;
151 if (want->data != nullptr) {
152 void *newWantData = AdapterMalloc(tlv->totalLen + want->dataLength);
153 if (newWantData == nullptr) {
154 return result;
155 }
156 if (memcpy_s(newWantData, want->dataLength, want->data, want->dataLength) != 0 ||
157 memcpy_s((unsigned char*)newWantData + want->dataLength, tlv->totalLen, tlv->entity, tlv->totalLen) != 0) {
158 AdapterFree(newWantData);
159 return result;
160 }
161 SetWantData(want, newWantData, tlv->totalLen + want->dataLength);
162 AdapterFree(newWantData);
163 result = true;
164 } else {
165 SetWantData(want, tlv->entity, tlv->totalLen);
166 result = true;
167 }
168 return result;
169 }
170
SetIntParam(Want * want,const char * key,uint8_t keyLen,int32_t value)171 bool SetIntParam(Want *want, const char *key, uint8_t keyLen, int32_t value)
172 {
173 bool result = false;
174 if (keyLen <= 0) {
175 return result;
176 }
177
178 Tlv *keyTlv = EncapTlv(STRING_VALUE_TYPE, keyLen, (void *)key, keyLen);
179 if (keyTlv == nullptr) {
180 return result;
181 }
182 if (value < 0) {
183 HILOG_ERROR(HILOG_MODULE_APP, "SetIntParam value should be positive");
184 FreeTlvStruct(keyTlv);
185 return result;
186 }
187 int intBufferNumber = 4;
188 unsigned char intBuffer[4] = {0};
189 for (int i = 0; i < intBufferNumber; i++) {
190 intBuffer[i] = value >> (8 * (3- i));
191 }
192 Tlv *valueTlv = EncapTlv(INT_VALUE_TYPE, sizeof(int), (void *)intBuffer, sizeof(int));
193 if (valueTlv == nullptr) {
194 FreeTlvStruct(keyTlv);
195 return result;
196 }
197 Tlv *newTlv = CombineKeyValueTlv(keyTlv, valueTlv);
198 FreeTlvStruct(keyTlv);
199 FreeTlvStruct(valueTlv);
200 if (newTlv == nullptr) {
201 return result;
202 }
203 if (UpdateWantData(want, newTlv)) {
204 result = true;
205 }
206 AdapterFree(newTlv);
207 return result;
208 }
209
SetStrParam(Want * want,const char * key,uint8_t keyLen,const char * value,uint8_t valueLen)210 bool SetStrParam(Want *want, const char *key, uint8_t keyLen, const char *value, uint8_t valueLen)
211 {
212 bool result = false;
213 if (keyLen <= 0 || valueLen <= 0) {
214 return result;
215 }
216
217 Tlv *keyTlv = EncapTlv(STRING_VALUE_TYPE, keyLen, (void *)key, keyLen);
218 if (keyTlv == nullptr) {
219 return result;
220 }
221
222 Tlv *valueTlv = EncapTlv(STRING_VALUE_TYPE, valueLen, (void *)value, valueLen);
223 if (valueTlv == nullptr) {
224 FreeTlvStruct(keyTlv);
225 return result;
226 }
227 Tlv *newTlv = CombineKeyValueTlv(keyTlv, valueTlv);
228 FreeTlvStruct(keyTlv);
229 FreeTlvStruct(valueTlv);
230 if (newTlv == nullptr) {
231 return result;
232 }
233 if (UpdateWantData(want, newTlv)) {
234 result = true;
235 }
236 AdapterFree(newTlv);
237 return result;
238 }
239
240 #ifdef OHOS_APPEXECFWK_BMS_BUNDLEMANAGER
SetWantSvcIdentity(Want * want,SvcIdentity sid)241 bool SetWantSvcIdentity(Want *want, SvcIdentity sid)
242 {
243 if (want == nullptr) {
244 return false;
245 }
246
247 AdapterFree(want->sid);
248 want->sid = reinterpret_cast<SvcIdentity *>(AdapterMalloc(sizeof(SvcIdentity)));
249 if (want->sid == nullptr) {
250 return false;
251 }
252 if (memcpy_s(want->sid, sizeof(SvcIdentity), &sid, sizeof(SvcIdentity)) != EOK) {
253 AdapterFree(want->sid);
254 return false;
255 }
256
257 return true;
258 }
259 #endif
260
SetWantData(Want * want,const void * data,uint16_t dataLength)261 bool SetWantData(Want *want, const void *data, uint16_t dataLength)
262 {
263 if (want == nullptr) {
264 return false;
265 }
266
267 AdapterFree(want->data);
268 want->data = OHOS::Utils::Memdup(data, dataLength);
269 if (want->data == nullptr) {
270 want->dataLength = 0;
271 return false;
272 }
273
274 want->dataLength = dataLength;
275 return true;
276 }
277
278 #ifdef OHOS_APPEXECFWK_BMS_BUNDLEMANAGER
SerializeWant(IpcIo * io,const Want * want)279 bool SerializeWant(IpcIo *io, const Want *want)
280 {
281 if ((io == nullptr) || (want == nullptr) || (want->dataLength > DATA_LENGTH)) {
282 return false;
283 }
284
285 if (want->element == nullptr) {
286 WriteInt32(io, VALUE_NULL);
287 } else {
288 WriteInt32(io, VALUE_OBJECT);
289 if (!SerializeElement(io, want->element)) {
290 return false;
291 }
292 }
293 WriteInt32(io, want->dataLength);
294 if (want->dataLength > 0) {
295 WriteBuffer(io, want->data, want->dataLength);
296 }
297 if (want->sid == nullptr) {
298 WriteInt32(io, VALUE_NULL);
299 } else {
300 WriteInt32(io, VALUE_OBJECT);
301 bool ret = WriteRemoteObject(io, want->sid);
302 if (!ret) {
303 return false;
304 }
305 }
306
307 return true;
308 }
309
DeserializeWant(Want * want,IpcIo * io)310 bool DeserializeWant(Want *want, IpcIo *io)
311 {
312 if ((want == nullptr) || (io == nullptr)) {
313 return false;
314 }
315
316 int ret = 0;
317 ReadInt32(io, &ret);
318 if (ret == VALUE_OBJECT) {
319 want->element = reinterpret_cast<ElementName *>(AdapterMalloc(sizeof(ElementName)));
320 if (want->element == nullptr ||
321 memset_s(want->element, sizeof(ElementName), 0, sizeof(ElementName)) != EOK ||
322 !DeserializeElement(want->element, io)) {
323 AdapterFree(want->element);
324 return false;
325 }
326 }
327 uint32_t size = 0;
328 ReadUint32(io, &size);
329 if (size > 0) {
330 void *data = (void*)ReadBuffer(io, (size_t)size);
331 if (!SetWantData(want, data, size)) {
332 ClearWant(want);
333 return false;
334 }
335 }
336 ReadInt32(io, &ret);
337 if (ret == VALUE_OBJECT) {
338 SvcIdentity svc;
339 bool ret = ReadRemoteObject(io, &svc);
340 if (!ret || !SetWantSvcIdentity(want, svc)) {
341 ClearWant(want);
342 return false;
343 }
344 }
345
346 return true;
347 }
348
WantParseUri(const char * uri)349 Want *WantParseUri(const char *uri)
350 {
351 if (uri == nullptr) {
352 return nullptr;
353 }
354 char *parseUri = OHOS::Utils::Strdup(uri);
355 if (parseUri == nullptr) {
356 return nullptr;
357 }
358 ElementName element = { nullptr, nullptr, nullptr };
359 char *beginIndex = parseUri;
360 for (auto property : URI_PROPERTIES) {
361 if (strstr(beginIndex, property.key) != beginIndex) {
362 AdapterFree(parseUri);
363 return nullptr;
364 }
365 if (property.type == END) {
366 break;
367 }
368 char *endIndex = strchr(beginIndex, URI_SEPARATOR);
369 if ((endIndex == nullptr) || (endIndex <= beginIndex)) {
370 AdapterFree(parseUri);
371 return nullptr;
372 }
373 *endIndex = '\0';
374 beginIndex += property.keyLen;
375 switch (property.type) {
376 case DEVICE: {
377 SetElementDeviceID(&element, beginIndex);
378 break;
379 }
380 case BUNDLE: {
381 SetElementBundleName(&element, beginIndex);
382 break;
383 }
384 case ABILITY: {
385 SetElementAbilityName(&element, beginIndex);
386 break;
387 }
388 default: {
389 break;
390 }
391 }
392 beginIndex = endIndex + 1;
393 }
394 AdapterFree(parseUri);
395 Want *want = new Want();
396 if ((memset_s(want, sizeof(Want), 0, sizeof(Want)) != EOK) || !SetWantElement(want, element)) {
397 ClearElement(&element);
398 delete want;
399 return nullptr;
400 }
401 ClearElement(&element);
402 return want;
403 }
404
WantToUri(Want want)405 const char *WantToUri(Want want)
406 {
407 std::string uriString;
408
409 for (auto property : URI_PROPERTIES) {
410 uriString += property.key;
411 switch (property.type) {
412 case BEGIN: {
413 uriString += URI_SEPARATOR;
414 break;
415 }
416 case DEVICE: {
417 if ((want.element != nullptr) && (want.element->deviceId != nullptr)) {
418 uriString += want.element->deviceId;
419 }
420 uriString += URI_SEPARATOR;
421 break;
422 }
423 case BUNDLE: {
424 if ((want.element != nullptr) && (want.element->bundleName != nullptr)) {
425 uriString += want.element->bundleName;
426 }
427 uriString += URI_SEPARATOR;
428 break;
429 }
430 case ABILITY: {
431 if ((want.element != nullptr) && (want.element->abilityName != nullptr)) {
432 uriString += want.element->abilityName;
433 }
434 uriString += URI_SEPARATOR;
435 break;
436 }
437 default: {
438 break;
439 }
440 }
441 }
442
443 uint16_t len = uriString.size();
444 char *uri = reinterpret_cast<char *>(AdapterMalloc(len + 1));
445 if (uri == nullptr) {
446 return nullptr;
447 }
448 if (strncpy_s(uri, len + 1, uriString.c_str(), len) < 0) {
449 AdapterFree(uri);
450 return nullptr;
451 }
452
453 return uri;
454 }
455 #endif
456