• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-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 
16 #include "app_provision.h"
17 #include <stdbool.h>
18 #include <string.h>
19 #include "app_common.h"
20 #include "app_verify_hal.h"
21 #include "cJSON.h"
22 #include "securec.h"
23 
ProfInit(ProfileProf * pf)24 static void ProfInit(ProfileProf *pf)
25 {
26     errno_t ret = memset_s(pf, sizeof(ProfileProf), 0, sizeof(ProfileProf));
27     if (ret != EOK) {
28         LOG_ERROR("memset failed");
29         return;
30     }
31     return;
32 }
33 
GetStringTag(const cJSON * root,const char * tag)34 static char *GetStringTag(const cJSON *root, const char *tag)
35 {
36     cJSON *jsonObj = cJSON_GetObjectItem(root, tag);
37     if ((jsonObj == NULL) || (jsonObj->valuestring == NULL)) {
38         LOG_PRINT_STR("failed to get %s", tag);
39         return NULL;
40     }
41     int objLen = strlen(jsonObj->valuestring);
42     if (objLen < 0) {
43         LOG_PRINT_STR("len error");
44         return NULL;
45     }
46     char *value = APPV_MALLOC(objLen + 1);
47     if (value == NULL) {
48         LOG_ERROR("malloc error: %d", objLen + 1);
49         return NULL;
50     }
51     errno_t ret = strcpy_s(value, objLen + 1, jsonObj->valuestring);
52     if (ret != EOK) {
53         APPV_FREE(value);
54         LOG_ERROR("strcpy error: %d", ret);
55         return NULL;
56     }
57     return value;
58 }
59 
FreeStringAttay(char ** array,int num)60 static void FreeStringAttay(char **array, int num)
61 {
62     if (array == NULL) {
63         return;
64     }
65     for (int i = 0; i < num; i++) {
66         if (array[i] != NULL) {
67             APPV_FREE(array[i]);
68         }
69     }
70     APPV_FREE(array);
71     return;
72 }
73 
GetStringArrayTag(const cJSON * root,const char * tag,int * numReturn)74 static char **GetStringArrayTag(const cJSON *root, const char *tag, int *numReturn)
75 {
76     cJSON *jsonObj = cJSON_GetObjectItem(root, tag);
77     if (jsonObj == NULL) {
78         LOG_PRINT_STR("failed to get %s", tag);
79         return NULL;
80     }
81     int num = cJSON_GetArraySize(jsonObj);
82     if (num == 0) {
83         LOG_ERROR("array num 0");
84         *numReturn = 0;
85         return NULL;
86     }
87     char **value = APPV_MALLOC(sizeof(char *) * num);
88     if (value == NULL) {
89         LOG_ERROR("value is null");
90         *numReturn = 0;
91         return NULL;
92     }
93     (void)memset_s(value, sizeof(char *) * num, 0, sizeof(char *) * num);
94 
95     for (int i = 0; i < num; i++) {
96         cJSON *item = cJSON_GetArrayItem(jsonObj, i);
97         P_NULL_GOTO_WTTH_LOG(item);
98         if (item->valuestring == NULL) {
99             LOG_ERROR("valuestring is NULL");
100             return NULL;
101         }
102         int len = strlen(item->valuestring);
103         value[i] = APPV_MALLOC(len + 1);
104         P_NULL_GOTO_WTTH_LOG(value[i]);
105 
106         errno_t ret = strcpy_s(value[i], len + 1, item->valuestring);
107         if (ret != EOK) {
108             LOG_ERROR("str cpy error : %d", ret);
109             FreeStringAttay(value, num);
110             return NULL;
111         }
112     }
113     *numReturn = num;
114     return value;
115 EXIT:
116     FreeStringAttay(value, num);
117     return NULL;
118 }
119 
GetProfValidity(const cJSON * root,ProfValidity * profVal)120 static int GetProfValidity(const cJSON *root, ProfValidity *profVal)
121 {
122     cJSON *jsonObj = cJSON_GetObjectItem(root, "validity");
123     if (jsonObj == NULL) {
124         LOG_ERROR("failed to get validity");
125         return V_ERR;
126     }
127 
128     cJSON *notBefore = cJSON_GetObjectItem(jsonObj, "not-before");
129     if (notBefore == NULL) {
130         LOG_ERROR("failed to get not-before");
131         return V_ERR;
132     }
133     profVal->notBefore = notBefore->valueint;
134 
135     cJSON *notAfter = cJSON_GetObjectItem(jsonObj, "not-after");
136     if (notAfter == NULL) {
137         LOG_ERROR("failed to get not-after");
138         return V_ERR;
139     }
140     profVal->notAfter = notAfter->valueint;
141     return V_OK;
142 }
143 
GetProfBundleInfo(const cJSON * root,ProfBundleInfo * profVal)144 static int GetProfBundleInfo(const cJSON *root, ProfBundleInfo *profVal)
145 {
146     cJSON *jsonObj = cJSON_GetObjectItem(root, "bundle-info");
147     if (jsonObj == NULL) {
148         LOG_ERROR("failed to get bundle-info");
149         return V_ERR;
150     }
151     /* if failed, free by caller */
152     profVal->developerId = GetStringTag(jsonObj, "developer-id");
153     P_NULL_RETURN_WTTH_LOG(profVal->developerId);
154 
155     profVal->devCert = (unsigned char *)GetStringTag(jsonObj, "development-certificate");
156     if (profVal->devCert == NULL) {
157         LOG_ERROR("get development-certificat failed");
158         profVal->devCert = APPV_MALLOC(sizeof(char));
159         P_NULL_RETURN_WTTH_LOG(profVal->devCert);
160         profVal->devCert[0] = '\0';
161     }
162 
163     profVal->releaseCert = (unsigned char *)GetStringTag(jsonObj, "distribution-certificate");
164     if (profVal->releaseCert == NULL) {
165         LOG_ERROR("get distribution-certificat failed");
166         profVal->releaseCert = APPV_MALLOC(sizeof(char));
167         P_NULL_RETURN_WTTH_LOG(profVal->releaseCert);
168         profVal->releaseCert[0] = '\0';
169     }
170 
171     profVal->bundleName = GetStringTag(jsonObj, "bundle-name");
172     P_NULL_RETURN_WTTH_LOG(profVal->bundleName);
173 
174     profVal->appFeature = GetStringTag(jsonObj, "app-feature");
175     P_NULL_RETURN_WTTH_LOG(profVal->appFeature);
176 
177     return V_OK;
178 }
179 
GetProfPermission(const cJSON * root,ProfPermission * profVal)180 static int GetProfPermission(const cJSON *root, ProfPermission *profVal)
181 {
182     cJSON *jsonObj = cJSON_GetObjectItem(root, "permissions");
183     if (jsonObj == NULL) {
184         LOG_ERROR("failed to get permissions");
185         return V_ERR;
186     }
187     profVal->permission = GetStringArrayTag(jsonObj, "feature-permissions", &profVal->permissionNum);
188     profVal->restricPermission = GetStringArrayTag(jsonObj, "restricted-permissions", &profVal->restricNum);
189     return V_OK;
190 }
191 
GetProfDebugInfo(const cJSON * root,ProfDebugInfo * profVal)192 static int GetProfDebugInfo(const cJSON *root, ProfDebugInfo *profVal)
193 {
194     cJSON *jsonObj = cJSON_GetObjectItem(root, "debug-info");
195     if (jsonObj == NULL) {
196         LOG_INFO("failed to get debug-info");
197         return V_OK;
198     }
199     profVal->devIdType = GetStringTag(jsonObj, "device-id-type");
200     if (profVal->devIdType == NULL) {
201         LOG_INFO("failed to get device-id-type");
202         return V_OK;
203     }
204     profVal->deviceId = GetStringArrayTag(jsonObj, "device-ids", &profVal->devidNum);
205     return V_OK;
206 }
207 
GetProfIssuerInfo(const cJSON * root,ProfileProf * pf)208 static int GetProfIssuerInfo(const cJSON *root, ProfileProf *pf)
209 {
210     pf->issuer = GetStringTag(root, "issuer");
211     if (pf->issuer == NULL) {
212         int len = strlen(APP_STORE);
213         pf->issuer = APPV_MALLOC(len + 1);
214         if (pf->issuer == NULL) {
215             return V_ERR;
216         }
217         errno_t ret = strcpy_s(pf->issuer, len + 1, APP_STORE);
218         if (ret != EOK) {
219             APPV_FREE(pf->issuer);
220             LOG_ERROR("str cpy error: %d", ret);
221         }
222         return ret;
223     }
224     return V_OK;
225 }
226 
FreeProfBundle(ProfBundleInfo * pfval)227 static void FreeProfBundle(ProfBundleInfo *pfval)
228 {
229     FREE_IF_NOT_NULL(pfval->appFeature);
230     FREE_IF_NOT_NULL(pfval->bundleName);
231     FREE_IF_NOT_NULL(pfval->devCert);
232     FREE_IF_NOT_NULL(pfval->developerId);
233     FREE_IF_NOT_NULL(pfval->releaseCert);
234     return;
235 }
236 
FreeProfPerssion(ProfPermission * pfval)237 static void FreeProfPerssion(ProfPermission *pfval)
238 {
239     FreeStringAttay(pfval->permission, pfval->permissionNum);
240     pfval->permissionNum = 0;
241     pfval->permission = NULL;
242 
243     FreeStringAttay(pfval->restricPermission, pfval->restricNum);
244     pfval->restricNum = 0;
245     pfval->restricPermission = NULL;
246     return;
247 }
248 
FreeProfDebuginfo(ProfDebugInfo * pfval)249 static void FreeProfDebuginfo(ProfDebugInfo *pfval)
250 {
251     FREE_IF_NOT_NULL(pfval->devIdType);
252 
253     FreeStringAttay(pfval->deviceId, pfval->devidNum);
254     pfval->devidNum = 0;
255     pfval->deviceId = NULL;
256 
257     return;
258 }
259 
ProfFreeData(ProfileProf * pf)260 void ProfFreeData(ProfileProf *pf)
261 {
262     if (pf == NULL) {
263         return;
264     }
265     FREE_IF_NOT_NULL(pf->versionName);
266     FREE_IF_NOT_NULL(pf->uuid);
267     FREE_IF_NOT_NULL(pf->type);
268     FREE_IF_NOT_NULL(pf->appDistType);
269     FreeProfBundle(&pf->bundleInfo);
270     FreeProfPerssion(&pf->permission);
271     FreeProfDebuginfo(&pf->debugInfo);
272     FREE_IF_NOT_NULL(pf->issuer);
273     FREE_IF_NOT_NULL(pf->appid);
274     return;
275 }
276 
277 /* parse profile */
ParseProfile(const char * buf,int len,ProfileProf * pf)278 int ParseProfile(const char *buf, int len, ProfileProf *pf)
279 {
280     P_NULL_RETURN_WTTH_LOG(pf);
281     P_NULL_RETURN_WTTH_LOG(buf);
282     ProfInit(pf);
283     int ret;
284     char *pfStr = strchr(buf, '{');
285     P_NULL_RETURN_WTTH_LOG(pfStr);
286 
287     cJSON *root = cJSON_Parse(pfStr);
288     P_NULL_RETURN_WTTH_LOG(root);
289 
290     cJSON *jsonObj = cJSON_GetObjectItem(root, "version-code");
291     P_NULL_GOTO_WTTH_LOG(jsonObj);
292     pf->versionCode = jsonObj->valueint;
293 
294     pf->versionName = GetStringTag(root, "version-name");
295     P_NULL_GOTO_WTTH_LOG(pf->versionName);
296 
297     pf->uuid = GetStringTag(root, "uuid");
298     P_NULL_GOTO_WTTH_LOG(pf->uuid);
299 
300     pf->type = GetStringTag(root, "type");
301     P_NULL_GOTO_WTTH_LOG(pf->type);
302 
303     pf->appDistType = GetStringTag(root, "app-distribution-type");
304     if (pf->appDistType == NULL) {
305         pf->appDistType = APPV_MALLOC(sizeof(char));
306         P_NULL_GOTO_WTTH_LOG(pf->appDistType);
307         pf->appDistType[0] = '\0';
308     }
309 
310     ret = GetProfValidity(root, &pf->validity);
311     P_ERR_GOTO_WTTH_LOG(ret);
312 
313     ret = GetProfBundleInfo(root, &pf->bundleInfo);
314     P_ERR_GOTO_WTTH_LOG(ret);
315 
316     ret = GetProfPermission(root, &pf->permission);
317     P_ERR_GOTO_WTTH_LOG(ret);
318 
319     ret = GetProfDebugInfo(root, &pf->debugInfo);
320     P_ERR_GOTO_WTTH_LOG(ret);
321 
322     ret = GetProfIssuerInfo(root, pf);
323     P_ERR_GOTO_WTTH_LOG(ret);
324 
325     LOG_INFO("parse profile json success");
326     cJSON_Delete(root);
327     return V_OK;
328 
329 EXIT:
330     cJSON_Delete(root);
331     ProfFreeData(pf);
332     return V_ERR;
333 }
334 
VerifyAppTypeAndDistribution(const ProfileProf * pf)335 static int VerifyAppTypeAndDistribution(const ProfileProf *pf)
336 {
337     if ((strcmp(pf->type, DEBUG_TYPE) != 0) && (strcmp(pf->type, RELEASE_TYPE) != 0)) {
338         LOG_PRINT_STR("invalid app type: %s", pf->type);
339         return V_ERR;
340     }
341     if (strcmp(pf->type, RELEASE_TYPE) == 0) {
342         if ((strcmp(pf->appDistType, "app_gallery") != 0) && (strcmp(pf->appDistType, "enterprise") != 0) &&
343             (strcmp(pf->appDistType, "os_integration") != 0)) {
344             LOG_PRINT_STR("invalid app dis type: %s", pf->appDistType);
345             return V_ERR;
346         }
347     }
348     return V_OK;
349 }
350 
VerifyAppBundleInfo(const ProfileProf * pf)351 static int VerifyAppBundleInfo(const ProfileProf *pf)
352 {
353     if (strcmp(pf->type, DEBUG_TYPE) == 0) {
354         if (strlen((char *)pf->bundleInfo.devCert) == 0) {
355             LOG_ERROR("debug app, dev cert null");
356             return V_ERR;
357         }
358     } else if (strcmp(pf->type, RELEASE_TYPE) == 0) {
359         if (strlen((char *)pf->bundleInfo.releaseCert) == 0) {
360             LOG_ERROR("debug app, dev cert null");
361             return V_ERR;
362         }
363     } else {
364         LOG_PRINT_STR("invalid app type: %s", pf->type);
365         return V_ERR;
366     }
367     return V_OK;
368 }
369 
VerifyUdid(const ProfileProf * pf)370 static int VerifyUdid(const ProfileProf *pf)
371 {
372     unsigned int size = UDID_VERIFY_BYTES + 1;
373     if (pf->debugInfo.devidNum > MAX_UDID_NUM) {
374         LOG_ERROR("udid num exceed maximum");
375         return V_ERR;
376     }
377     unsigned char *udid = APPV_MALLOC(size);
378     if (udid == NULL) {
379         LOG_ERROR("udid is null");
380         return V_ERR;
381     }
382     (void)memset_s(udid, size, 0, size);
383     int result = InquiryDeviceUdid(udid, size);
384     if (result != INQUIRY_UDID_OK) {
385         free(udid);
386         LOG_ERROR("get udid fail, ret: %d", result);
387         return V_ERR;
388     }
389     for (int i = 0; i < pf->debugInfo.devidNum; i++) {
390         if (strcmp((const char *)pf->debugInfo.deviceId[i], (const char *)udid) == 0) {
391             LOG_INFO("find right udid");
392             free(udid);
393             udid = NULL;
394             return V_OK;
395         }
396     }
397     LOG_ERROR("udid invalid");
398     free(udid);
399     udid = NULL;
400     return V_ERR;
401 }
402 
VerifyDebugInfo(const ProfileProf * pf)403 static int VerifyDebugInfo(const ProfileProf *pf)
404 {
405     if (strcmp(pf->type, DEBUG_TYPE) != 0) {
406         LOG_INFO("not debug app, return ok");
407         return V_OK;
408     }
409     LOG_PRINT_STR("devid type: %s", pf->debugInfo.devIdType);
410     int ret;
411     if (strcmp(pf->debugInfo.devIdType, "udid") == 0) {
412         ret = VerifyUdid(pf);
413     } else {
414         LOG_ERROR("devid type invalid");
415         ret = V_ERR;
416     }
417     return ret;
418 }
419 
VerifyProfileContent(const ProfileProf * pf)420 int VerifyProfileContent(const ProfileProf *pf)
421 {
422     P_NULL_RETURN_WTTH_LOG(pf);
423     int ret = VerifyAppTypeAndDistribution(pf);
424     if (ret != V_OK) {
425         LOG_PRINT_STR("invalid profile distribution type : %s", pf->appDistType);
426         return V_ERR_INVALID_DISP_TYPE;
427     }
428     ret = VerifyAppBundleInfo(pf);
429     if (ret != V_OK) {
430         LOG_ERROR("invalid profile app bundle info");
431         return V_ERR_INVALID_APP_BUNDLE;
432     }
433     /* verify debug device id */
434     ret = VerifyDebugInfo(pf);
435     if (ret != V_OK) {
436         LOG_ERROR("validate debug info");
437         return V_ERR_INVALID_DEVID;
438     }
439     return V_OK;
440 }
441