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