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