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