• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "config_policy_utils.h"
17 
18 #include <ctype.h>
19 #include <securec.h>
20 #include <stdbool.h>
21 #include <unistd.h>
22 
23 #include "config_policy_impl.h"
24 #ifndef __LITEOS__
25 #include "init_param.h"
26 #include "telephony_config_c.h"
27 #endif
28 
29 static const size_t MIN_APPEND_LEN = 32;
30 
31 #ifndef __LITEOS__
32 // set min opkey length
33 static const unsigned int MIN_OPKEY_LEN = 3;
34 // ':' split different x rules, example:":relPath,mode[,extra][:]"
35 // ',' split different param for x rules
36 // ":-" split for key:-value
37 // exampe:"etc/xml/config.xml,10:etc/xml/config1.xml,100,etc/carrier/${key:-value}"
38 static const char SEP_FOR_X_RULE = ':';
39 static const char SEP_FOR_X_PARAM = ',';
40 static const char *SEP_FOR_X_VALUE = ":-";
41 
42 typedef struct {
43     size_t size;   // allocated buffer size of p
44     size_t strLen; // strlen(p), less than size
45     char *p;       // just init to NULL, by malloc
46 } StringHolder;
47 #endif
48 
49 typedef struct {
50     int segCount; // count of char * in segs
51     char *orgStr;
52     char *segs[1];
53 } SplitedStr;
54 
55 #ifdef __LITEOS_M__
56 // The data will be used always, so prealloc to avoid memory fragment
57 static char gConfigPolicy[MINI_CONFIG_POLICY_BUF_SIZE] = {0};
SetMiniConfigPolicy(const char * policy)58 void SetMiniConfigPolicy(const char *policy)
59 {
60     if (gConfigPolicy[0] != 0) {
61         return; // now only set once
62     }
63     (void)strcpy_s(gConfigPolicy, sizeof(gConfigPolicy), policy);
64 }
65 
TrigSetMiniConfigPolicy()66 __WEAK void TrigSetMiniConfigPolicy()
67 {
68     return;
69 }
70 #endif
71 
72 /**
73  * query function, the memory is allocated in function
74  * @return value, or NULL if not exist or strlen(value) is 0
75  * @NOTICE caller should free the returned value
76  */
77 typedef char *(*QueryFunc)(const char *key);
78 static char *ExpandStr(char *src, const char *def, QueryFunc queryFunc);
79 
Min(size_t a,size_t b)80 static inline size_t Min(size_t a, size_t b)
81 {
82     return a < b ? a : b;
83 }
84 
Max(size_t a,size_t b)85 static inline size_t Max(size_t a, size_t b)
86 {
87     return a > b ? a : b;
88 }
89 
FreeIf(void * p)90 static void FreeIf(void *p)
91 {
92     if (p != NULL) {
93         free(p);
94     }
95 }
96 
97 #ifndef __LITEOS__
CustGetSystemParam(const char * name)98 static char *CustGetSystemParam(const char *name)
99 {
100     char *value = NULL;
101     unsigned int len = 0;
102 
103     if (SystemGetParameter(name, NULL, &len) != 0 || len <= 0 || len > PARAM_CONST_VALUE_LEN_MAX) {
104         return NULL;
105     }
106     value = (char *)calloc(len, sizeof(char));
107     if (value != NULL && SystemGetParameter(name, value, &len) == 0 && value[0]) {
108         return value;
109     }
110     FreeIf(value);
111     return NULL;
112 }
113 
GetOpkeyPath(int type)114 static char *GetOpkeyPath(int type)
115 {
116     char *result = NULL;
117     const char *opKeyDir = "etc/carrier/";
118     const char *opKeyName = CUST_OPKEY0;
119     if (type == FOLLOWX_MODE_SIM_1) {
120         opKeyName = CUST_OPKEY0;
121     } else if (type == FOLLOWX_MODE_SIM_2) {
122         opKeyName = CUST_OPKEY1;
123     } else {
124         unsigned int len = 0;
125         if (SystemGetParameter(CUST_OPKEY0, NULL, &len) == 0 && len > MIN_OPKEY_LEN) {
126             opKeyName = CUST_OPKEY0;
127         } else if (SystemGetParameter(CUST_OPKEY1, NULL, &len) == 0 && len > MIN_OPKEY_LEN) {
128             opKeyName = CUST_OPKEY1;
129         }
130     }
131     char *opKeyValue = CustGetSystemParam(opKeyName);
132     if (opKeyValue == NULL) {
133         return NULL;
134     }
135     size_t bufSize = strlen(opKeyDir) + strlen(opKeyValue) + 1;
136     bufSize = Min(bufSize, MAX_PATH_LEN);
137     result = (char *)calloc(bufSize, sizeof(char));
138     if (result != NULL && sprintf_s(result, bufSize, "%s%s", opKeyDir, opKeyValue) > 0) {
139         FreeIf(opKeyValue);
140         return result;
141     }
142     FreeIf(opKeyValue);
143     FreeIf(result);
144     return NULL;
145 }
146 
SplitStr(char * str,char delim)147 static SplitedStr *SplitStr(char *str, char delim)
148 {
149     int segCount = 1;
150     for (char *p = str; *p != '\0'; p++) {
151         (*p == delim) ? segCount++ : 0;
152     }
153     SplitedStr *result = (SplitedStr *)calloc(sizeof(SplitedStr) + sizeof(char *) * segCount, 1);
154     if (result == NULL) {
155         return NULL;
156     }
157     result->segCount = segCount;
158     result->orgStr = str;
159 
160     char *nextDelim = NULL;
161     char delimStr[] = {delim, 0};
162     result->segs[0] = strtok_s(str, delimStr, &nextDelim);
163     for (int index = 1; index < segCount; index++) {
164         result->segs[index] = strtok_s(NULL, delimStr, &nextDelim);
165     }
166     return result;
167 }
168 #endif // __LITEOS__
169 
FreeSplitedStr(SplitedStr * p)170 static void FreeSplitedStr(SplitedStr *p)
171 {
172     if (p != NULL) {
173         FreeIf(p->orgStr);
174         p->orgStr = NULL;
175         free(p);
176     }
177 }
178 
179 #ifndef __LITEOS__
180 // get follow x rule from param variant
181 // *mode: read from contains param variant, mode is output param.
182 // return: extra path rule.
183 // followPath format ":relPath,mode[,extra][:]"
184 // example: ":etc/xml/config.xml,10:etc/xml/config1.xml,100,etc/carrier/${key:-value}"
GetFollowXRule(const char * relPath,int * mode)185 static char *GetFollowXRule(const char *relPath, int *mode)
186 {
187     char *followRule = CustGetSystemParam(CUST_FOLLOW_X_RULES);
188     if (followRule == NULL) {
189         return NULL;
190     }
191 
192     size_t bufSize = strlen(relPath) + sizeof(":,") + 1;
193     bufSize = Min(bufSize, MAX_PATH_LEN);
194     char *search = (char *)calloc(bufSize, sizeof(char));
195     if (search == NULL || sprintf_s(search, bufSize, ":%s,", relPath) == -1) {
196         FreeIf(search);
197         FreeIf(followRule);
198         return NULL;
199     }
200 
201     char *addPath = NULL;
202     char *item = strstr(followRule, search);
203     if (item) {
204         item++; // skip delim ':', goto ":relPath,mode[,extra][:]"
205         char *endItem = strchr(item, SEP_FOR_X_RULE);
206         char *nextItem = endItem + 1;
207         while (endItem && *nextItem == '-') {
208             endItem = strchr(nextItem, SEP_FOR_X_RULE);
209             nextItem = endItem + 1;
210         }
211         if (endItem) {
212             *endItem = '\0';
213         }
214         char *modeStr = strchr(item, SEP_FOR_X_PARAM);
215         if (modeStr) {
216             modeStr++;
217             *mode = atoi(modeStr);
218         }
219         if (*mode == FOLLOWX_MODE_USER_DEFINE && modeStr) {
220             addPath = strchr(modeStr, SEP_FOR_X_PARAM);
221             if (addPath) {
222                 addPath++; // skip ',' get extra info
223             }
224         }
225     }
226 
227     char *result = (addPath && *addPath) ? strdup(addPath) : NULL;
228     FreeIf(followRule);
229     FreeIf(search);
230     return result;
231 }
232 
GetFollowXPathByMode(const char * relPath,int followMode,const char * extra)233 static SplitedStr *GetFollowXPathByMode(const char *relPath, int followMode, const char *extra)
234 {
235     char *followXPath = NULL;
236     char *modePathFromCfg = NULL;
237     const char *extraPath = extra;
238     if (followMode == FOLLOWX_MODE_DEFAULT) {
239         modePathFromCfg = GetFollowXRule(relPath, &followMode);
240         if (followMode == FOLLOWX_MODE_USER_DEFINE && modePathFromCfg && *modePathFromCfg) {
241             extraPath = modePathFromCfg;
242         }
243     }
244 
245     switch (followMode) {
246         case FOLLOWX_MODE_SIM_DEFAULT:
247             followXPath = GetOpkeyPath(FOLLOWX_MODE_SIM_DEFAULT);
248             break;
249         case FOLLOWX_MODE_SIM_1:
250             followXPath = GetOpkeyPath(FOLLOWX_MODE_SIM_1);
251             break;
252         case FOLLOWX_MODE_SIM_2:
253             followXPath = GetOpkeyPath(FOLLOWX_MODE_SIM_2);
254             break;
255         case FOLLOWX_MODE_USER_DEFINE:
256             followXPath = (extraPath && *extraPath) ? strdup(extraPath) : NULL;
257             break;
258         default:
259             break;
260     }
261     char *expandVal = (followXPath && *followXPath) ? ExpandStr(followXPath, "-x-", CustGetSystemParam) : NULL;
262     FreeIf(followXPath);
263     FreeIf(modePathFromCfg);
264     SplitedStr *result = expandVal ? SplitStr(expandVal, ',') : NULL;
265     return result;
266 }
267 
TrimInplace(char * str,bool moveToStart)268 static char *TrimInplace(char *str, bool moveToStart)
269 {
270     char *src = str;
271     while (isspace(*src)) {
272         src++;
273     }
274     for (int i = strlen(src) - 1; i >= 0 && isspace(src[i]); i--) {
275         src[i] = '\0';
276     }
277 
278     char *res = moveToStart ? str : src;
279     if (moveToStart && src != str) {
280         size_t len = strlen(src) + 1;
281         if (memmove_s(str, len, src, len) != EOK) {
282             return NULL;
283         }
284     }
285     return (*res != '\0') ? res : NULL;
286 }
287 
EnsureHolderSpace(StringHolder * holder,size_t leastSize)288 static bool EnsureHolderSpace(StringHolder *holder, size_t leastSize)
289 {
290     if (holder == NULL) {
291         return false;
292     }
293     if (holder->size < leastSize) {
294         size_t allocSize = Min(Max(leastSize * 2, MIN_APPEND_LEN), PARAM_CONST_VALUE_LEN_MAX);
295         char *newPtr = (char *)calloc(allocSize, sizeof(char));
296         if (newPtr == NULL) {
297             allocSize = leastSize;
298             newPtr = (char *)calloc(allocSize, sizeof(char));
299             if (newPtr == NULL) {
300                 return false;
301             }
302         }
303         if (holder->p != NULL && memcpy_s(newPtr, allocSize, holder->p, holder->strLen) != EOK) {
304             FreeIf(newPtr);
305             return false;
306         }
307         FreeIf(holder->p);
308         holder->p = newPtr;
309         holder->size = allocSize;
310     }
311     return true;
312 }
313 
AppendStr(StringHolder * holder,const char * s)314 static bool AppendStr(StringHolder *holder, const char *s)
315 {
316     if (holder == NULL || s == NULL) {
317         return false;
318     }
319     size_t leastSize = holder->strLen + strlen(s) + 1;
320     if (!EnsureHolderSpace(holder, leastSize)) {
321         return false;
322     }
323     if (strcat_s(holder->p, holder->size, s) != EOK) {
324         return false;
325     }
326     holder->strLen = leastSize - 1;
327     return true;
328 }
329 
ExpandStr(char * src,const char * def,QueryFunc queryFunc)330 static char *ExpandStr(char *src, const char *def, QueryFunc queryFunc)
331 {
332     bool ok = true;
333     StringHolder sh = { 0 };
334     char *copyCur = NULL;
335     char *searchCur = NULL;
336     char *end = src + strlen(src);
337     for (copyCur = searchCur = src; ok && searchCur < end;) {
338         char *varStart = NULL;
339         char *varEnd = NULL;
340         char *find = strchr(searchCur, '$');
341         if (!find) {
342             ok = ok && AppendStr(&sh, copyCur);
343             break;
344         } else if ((varStart = strchr(find, '{')) && (varStart == find + 1) && (varEnd = strchr(find, '}')) &&
345             varEnd - varStart > 0) { // Get user defined name
346             *find = *varEnd = 0;
347             ok = ok && AppendStr(&sh, copyCur);
348             char *name = find + 2;
349             char *defVal = strstr(name, SEP_FOR_X_VALUE);
350             if (defVal) {
351                 *defVal = 0;                                                   // cut for name end
352                 defVal = TrimInplace(defVal + strlen(SEP_FOR_X_VALUE), false); // skip ":-", get value
353             }
354             char *value = queryFunc(name);
355             if (value || defVal || def) {
356                 ok = ok && AppendStr(&sh, value ? value : (defVal ? defVal : def));
357                 FreeIf(value);
358             } else {
359                 errno = EINVAL;
360                 ok = false;
361                 break;
362             }
363             copyCur = searchCur = varEnd + 1;
364         } else {
365             searchCur = find + 1;
366         }
367     }
368     if (!ok) {
369         FreeIf(sh.p);
370         sh.p = NULL;
371     }
372     return sh.p;
373 }
374 #else
GetFollowXPathByMode(const char * relPath,int followMode,const char * extra)375 static SplitedStr *GetFollowXPathByMode(const char *relPath, int followMode, const char *extra)
376 {
377     return NULL;
378 }
379 #endif
380 
GetCfgDirRealPolicyValue(CfgDir * res)381 static void GetCfgDirRealPolicyValue(CfgDir *res)
382 {
383     if (res == NULL) {
384         return;
385     }
386 #ifdef __LITEOS_M__
387     if (gConfigPolicy[0] == '\0') {
388         TrigSetMiniConfigPolicy();
389     }
390     if (gConfigPolicy[0] != '\0') {
391         res->realPolicyValue = strdup(gConfigPolicy);
392     }
393 #elif defined(__LITEOS__)
394     // use default, now do nothing
395 #else
396     res->realPolicyValue = CustGetSystemParam(CUST_KEY_POLICY_LAYER);
397 #endif
398     if (res->realPolicyValue != NULL && res->realPolicyValue[0]) {
399         return;
400     }
401     res->realPolicyValue = strdup(DEFAULT_LAYER);
402 }
403 
FreeCfgFiles(CfgFiles * res)404 void FreeCfgFiles(CfgFiles *res)
405 {
406     if (res == NULL) {
407         return;
408     }
409     for (size_t i = 0; i < MAX_CFG_POLICY_DIRS_CNT; i++) {
410         if (res->paths[i] != NULL) {
411             free(res->paths[i]);
412             res->paths[i] = NULL;
413         }
414     }
415     free(res);
416 }
417 
FreeCfgDirList(CfgDir * res)418 void FreeCfgDirList(CfgDir *res)
419 {
420     if (res == NULL) {
421         return;
422     }
423     if (res->realPolicyValue != NULL) {
424         free(res->realPolicyValue);
425         res->realPolicyValue = NULL;
426     }
427     free(res);
428 }
429 
GetOneCfgFileEx(const char * pathSuffix,char * buf,unsigned int bufLength,int followMode,const char * extra)430 char *GetOneCfgFileEx(const char *pathSuffix, char *buf, unsigned int bufLength, int followMode, const char *extra)
431 {
432     if (pathSuffix == NULL || buf == NULL || bufLength < MAX_PATH_LEN) {
433         return NULL;
434     }
435     *buf = '\0';
436     CfgDir *dirs = GetCfgDirList();
437     if (dirs == NULL) {
438         return NULL;
439     }
440 
441     SplitedStr *result = GetFollowXPathByMode(pathSuffix, followMode, extra);
442     for (size_t i = MAX_CFG_POLICY_DIRS_CNT; i > 0; i--) {
443         if (dirs->paths[i - 1] == NULL) {
444             continue;
445         }
446         // check follow x
447         for (int j = (result ? result->segCount : 0); j > 0; j--) {
448             if (result->segs[j - 1] &&
449                 snprintf_s(buf, bufLength, bufLength - 1, "%s/%s/%s", dirs->paths[i - 1], result->segs[j - 1],
450                 pathSuffix) > 0 &&
451                 access(buf, F_OK) == 0) {
452                 break;
453             }
454             *buf = '\0';
455         }
456         if (*buf != '\0') {
457             break;
458         }
459         if (snprintf_s(buf, bufLength, bufLength - 1, "%s/%s", dirs->paths[i - 1], pathSuffix) > 0 &&
460             access(buf, F_OK) == 0) {
461             break;
462         }
463         *buf = '\0';
464     }
465     FreeCfgDirList(dirs);
466     FreeSplitedStr(result);
467     return (*buf != '\0') ? buf : NULL;
468 }
469 
GetOneCfgFile(const char * pathSuffix,char * buf,unsigned int bufLength)470 char *GetOneCfgFile(const char *pathSuffix, char *buf, unsigned int bufLength)
471 {
472     return GetOneCfgFileEx(pathSuffix, buf, bufLength, FOLLOWX_MODE_DEFAULT, NULL);
473 }
474 
GetCfgFilesEx(const char * pathSuffix,int followMode,const char * extra)475 CfgFiles *GetCfgFilesEx(const char *pathSuffix, int followMode, const char *extra)
476 {
477     if (pathSuffix == NULL) {
478         return NULL;
479     }
480     char buf[MAX_PATH_LEN] = {0};
481     CfgDir *dirs = GetCfgDirList();
482     if (dirs == NULL) {
483         return NULL;
484     }
485     CfgFiles *files = (CfgFiles *)(malloc(sizeof(CfgFiles)));
486     if (files == NULL) {
487         FreeCfgDirList(dirs);
488         return NULL;
489     }
490 
491     SplitedStr *result = GetFollowXPathByMode(pathSuffix, followMode, extra);
492     (void)memset_s(files, sizeof(CfgFiles), 0, sizeof(CfgFiles));
493     int index = 0;
494     for (size_t i = 0; i < MAX_CFG_POLICY_DIRS_CNT && index < MAX_CFG_POLICY_DIRS_CNT; i++) {
495         if (dirs->paths[i] == NULL) {
496             continue;
497         }
498         if (snprintf_s(buf, MAX_PATH_LEN, MAX_PATH_LEN - 1, "%s/%s", dirs->paths[i], pathSuffix) > 0 &&
499             access(buf, F_OK) == 0) {
500             files->paths[index++] = strdup(buf);
501         }
502         for (int j = 0; result && j < result->segCount; j++) {
503             if (result->segs[j] &&
504                 snprintf_s(buf, MAX_PATH_LEN, MAX_PATH_LEN - 1, "%s/%s/%s", dirs->paths[i], result->segs[j],
505                 pathSuffix) > 0 &&
506                 access(buf, F_OK) == 0) {
507                 files->paths[index++] = strdup(buf);
508             }
509         }
510     }
511     FreeCfgDirList(dirs);
512     FreeSplitedStr(result);
513     return files;
514 }
515 
GetCfgFiles(const char * pathSuffix)516 CfgFiles *GetCfgFiles(const char *pathSuffix)
517 {
518     return GetCfgFilesEx(pathSuffix, FOLLOWX_MODE_DEFAULT, NULL);
519 }
520 
GetCfgDirList()521 CfgDir *GetCfgDirList()
522 {
523     CfgDir *res = (CfgDir *)(malloc(sizeof(CfgDir)));
524     if (res == NULL) {
525         return NULL;
526     }
527     (void)memset_s(res, sizeof(CfgDir), 0, sizeof(CfgDir));
528     GetCfgDirRealPolicyValue(res);
529     char *next = res->realPolicyValue;
530     if (next == NULL) {
531         free(res);
532         return NULL;
533     }
534     for (size_t i = 0; i < MAX_CFG_POLICY_DIRS_CNT; i++) {
535         res->paths[i] = next;
536         next = strchr(next, ':');
537         if (next == NULL) {
538             break;
539         }
540         *next = 0;
541         next += 1;
542     }
543     return res;
544 }
545