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