• 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 #include <errno.h>
16 #include <grp.h>
17 #include <pwd.h>
18 #include <sys/stat.h>
19 #include <dirent.h>
20 #include <string.h>
21 
22 #include "param_manager.h"
23 #include "param_security.h"
24 #include "param_trie.h"
25 #include "param_utils.h"
26 #include "param_base.h"
27 
28 #define MAX_BUF_SIZE  1024
29 #define INVALID_MODE 0550
30 #ifdef STARTUP_INIT_TEST
31 #define GROUP_FILE_PATH STARTUP_INIT_UT_PATH "/etc/group"
32 #else
33 #define GROUP_FILE_PATH "/etc/group"
34 #endif
35 #define OCT_BASE 8
36 #define INVALID_UID(uid) ((uid) == (uid_t)-1)
37 
GetUserIdByName(uid_t * uid,const char * name)38 static void GetUserIdByName(uid_t *uid, const char *name)
39 {
40     struct passwd *data = getpwnam(name);
41     if (data == NULL) {
42         *uid = -1;
43         return ;
44     }
45     *uid = data->pw_uid;
46 }
47 
GetGroupIdByName(gid_t * gid,const char * name)48 static void GetGroupIdByName(gid_t *gid, const char *name)
49 {
50     *gid = -1;
51     struct group *data = getgrnam(name);
52     if (data != NULL) {
53         *gid = data->gr_gid;
54         return;
55     }
56     while ((data = getgrent()) != NULL) {
57         if ((data->gr_name != NULL) && (strcmp(data->gr_name, name) == 0)) {
58             *gid = data->gr_gid;
59             break;
60         }
61     }
62     endgrent();
63 }
64 
65 // user:group:r|w
GetParamDacData(ParamDacData * dacData,const char * value)66 static int GetParamDacData(ParamDacData *dacData, const char *value)
67 {
68     static const struct {
69         const char *name;
70         int value;
71     } paramTypes[] = {
72         { "int", PARAM_TYPE_INT },
73         { "string", PARAM_TYPE_STRING },
74         { "bool", PARAM_TYPE_BOOL },
75     };
76 
77     char *groupName = strstr(value, ":");
78     if (groupName == NULL) {
79         return -1;
80     }
81     char *mode = strstr(groupName + 1, ":");
82     if (mode == NULL) {
83         return -1;
84     }
85 
86     uint32_t nameLen = groupName - value;
87     char *name = (char *)value;
88     name[nameLen] = '\0';
89     GetUserIdByName(&dacData->uid, name);
90     nameLen = mode - groupName - 1;
91     name = (char *)groupName + 1;
92     name[nameLen] = '\0';
93     GetGroupIdByName(&dacData->gid, name);
94 
95     dacData->paramType = PARAM_TYPE_STRING;
96     char *type = strstr(mode + 1, ":");
97     if (type != NULL) {
98         *type = '\0';
99         type++;
100         for (size_t i = 0; (type != NULL) && (i < ARRAY_LENGTH(paramTypes)); i++) {
101             if (strcmp(paramTypes[i].name, type) == 0) {
102                 dacData->paramType = paramTypes[i].value;
103             }
104         }
105     }
106     dacData->mode = (uint16_t)strtol(mode + 1, NULL, OCT_BASE);
107     return 0;
108 }
109 
InitLocalSecurityLabel(ParamSecurityLabel * security,int isInit)110 static int InitLocalSecurityLabel(ParamSecurityLabel *security, int isInit)
111 {
112     UNUSED(isInit);
113     PARAM_CHECK(security != NULL, return -1, "Invalid security");
114     security->cred.pid = getpid();
115     security->cred.uid = geteuid();
116     security->cred.gid = getegid();
117     // support check write permission in client
118     security->flags[PARAM_SECURITY_DAC] |= LABEL_CHECK_IN_ALL_PROCESS;
119     return 0;
120 }
121 
FreeLocalSecurityLabel(ParamSecurityLabel * srcLabel)122 static int FreeLocalSecurityLabel(ParamSecurityLabel *srcLabel)
123 {
124     return 0;
125 }
126 
LoadOneParam_(const uint32_t * context,const char * name,const char * value)127 static int LoadOneParam_(const uint32_t *context, const char *name, const char *value)
128 {
129     ParamAuditData auditData = {0};
130     auditData.dacData.gid = -1;
131     auditData.dacData.uid = -1;
132     auditData.name = name;
133     int ret = GetParamDacData(&auditData.dacData, value);
134     PARAM_CHECK(ret == 0, return -1, "Failed to get param info %d %s", ret, name);
135     if (INVALID_UID(auditData.dacData.gid) || INVALID_UID(auditData.dacData.uid)) {
136         PARAM_LOGW("Invalid dac for '%s' gid %d uid %d", name, auditData.dacData.gid, auditData.dacData.uid);
137     }
138     AddSecurityLabel(&auditData);
139     return 0;
140 }
141 
LoadParamLabels(const char * fileName)142 static int LoadParamLabels(const char *fileName)
143 {
144     uint32_t infoCount = 0;
145     FILE *fp = fopen(fileName, "r");
146     const uint32_t buffSize = PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX + 10;  // 10 size
147     char *buff = (char *)calloc(1, buffSize);
148     while (fp != NULL && buff != NULL && fgets(buff, buffSize, fp) != NULL) {
149         buff[buffSize - 1] = '\0';
150         int ret = SplitParamString(buff, NULL, 0, LoadOneParam_, NULL);
151         if (ret != 0) {
152             PARAM_LOGE("Failed to split string %s fileName %s", buff, fileName);
153             continue;
154         }
155         infoCount++;
156     }
157     PARAM_LOGI("Load parameter label total %u success %s", infoCount, fileName);
158     if (fp != NULL) {
159         (void)fclose(fp);
160     }
161     if (buff != NULL) {
162         free(buff);
163     }
164     return 0;
165 }
166 
ProcessParamFile(const char * fileName,void * context)167 static int ProcessParamFile(const char *fileName, void *context)
168 {
169     UNUSED(context);
170     return LoadParamLabels(fileName);
171 }
172 
DacGetParamSecurityLabel(const char * path)173 static int DacGetParamSecurityLabel(const char *path)
174 {
175     PARAM_CHECK(path != NULL, return -1, "Invalid param");
176     struct stat st;
177     if ((stat(path, &st) == 0) && !S_ISDIR(st.st_mode)) {
178         return ProcessParamFile(path, NULL);
179     }
180 
181     PARAM_LOGV("DacGetParamSecurityLabel %s ", path);
182     DIR *pDir = opendir(path);
183     PARAM_CHECK(pDir != NULL, return -1, "Read dir :%s failed.%d", path, errno);
184     char *fileName = malloc(MAX_BUF_SIZE);
185     PARAM_CHECK(fileName != NULL, closedir(pDir);
186         return -1, "Failed to malloc for %s", path);
187 
188     struct dirent *dp;
189     uint32_t count = 0;
190     while ((dp = readdir(pDir)) != NULL) {
191         if (dp->d_type == DT_DIR) {
192             continue;
193         }
194         char *tmp = strstr(dp->d_name, ".para.dac");
195         if (tmp == NULL) {
196             continue;
197         }
198         if (strcmp(tmp, ".para.dac") != 0) {
199             continue;
200         }
201         int ret = PARAM_SPRINTF(fileName, MAX_BUF_SIZE, "%s/%s", path, dp->d_name);
202         if (ret <= 0) {
203             PARAM_LOGE("Failed to get file name for %s", dp->d_name);
204             continue;
205         }
206         if ((stat(fileName, &st) == 0) && !S_ISDIR(st.st_mode)) {
207             count++;
208             ProcessParamFile(fileName, NULL);
209         }
210     }
211     PARAM_LOGV("Get parameter security label dac number is %d, from %s.", count, path);
212     free(fileName);
213     closedir(pDir);
214     return 0;
215 }
216 
CheckFilePermission(const ParamSecurityLabel * localLabel,const char * fileName,int flags)217 static int CheckFilePermission(const ParamSecurityLabel *localLabel, const char *fileName, int flags)
218 {
219     UNUSED(flags);
220     PARAM_CHECK(localLabel != NULL && fileName != NULL, return -1, "Invalid param");
221     return 0;
222 }
223 
RegisterSecurityDacOps(ParamSecurityOps * ops,int isInit)224 INIT_LOCAL_API int RegisterSecurityDacOps(ParamSecurityOps *ops, int isInit)
225 {
226     PARAM_CHECK(ops != NULL, return -1, "Invalid param");
227     PARAM_LOGV("RegisterSecurityDacOps %d", isInit);
228     int ret = PARAM_STRCPY(ops->name, sizeof(ops->name), "dac");
229     ops->securityInitLabel = InitLocalSecurityLabel;
230     ops->securityCheckFilePermission = CheckFilePermission;
231 #ifdef STARTUP_INIT_TEST
232     ops->securityCheckParamPermission = DacCheckParamPermission;
233 #endif
234     ops->securityFreeLabel = FreeLocalSecurityLabel;
235     if (isInit) {
236         ops->securityGetLabel = DacGetParamSecurityLabel;
237     }
238     return ret;
239 }
240 
AddGroupUser(const char * userName,gid_t gid)241 static void AddGroupUser(const char *userName, gid_t gid)
242 {
243     if (userName == NULL || strlen(userName) == 0) {
244         return;
245     }
246     uid_t uid = 0;
247     GetUserIdByName(&uid, userName);
248     PARAM_LOGV("Add group user '%s' gid %d uid %d", userName, gid, uid);
249     if (INVALID_UID(gid) || INVALID_UID(uid)) {
250         PARAM_LOGW("Invalid user for '%s' gid %d uid %d", userName, gid, uid);
251         return;
252     }
253     char buffer[USER_BUFFER_LEN] = {0};
254     int ret = PARAM_SPRINTF(buffer, sizeof(buffer), GROUP_FORMAT, gid, uid);
255     PARAM_CHECK(ret >= 0, return, "Failed to format name for %d.%d", gid, uid);
256     (void)AddParamEntry(WORKSPACE_INDEX_BASE, PARAM_TYPE_STRING, buffer, "1");
257 }
258 
259 #ifdef PARAM_DECODE_GROUPID_FROM_FILE
UserNameTrim(char * str)260 static char *UserNameTrim(char *str)
261 {
262     if (str == NULL) {
263         return NULL;
264     }
265     size_t len = strlen(str);
266     if (str == NULL || len == 0) {
267         return NULL;
268     }
269     char *end = str + len - 1;
270     while (end >= str && (*end == ' ' || *end == '\t' || *end == '\n' || *end == '\r')) {
271         *end = '\0';
272         end--;
273     }
274     len = strlen(str);
275     char *head = str;
276     end = str + strlen(str);
277     while (head < end && (*head == ' ' || *head == '\t' || *head == '\n' || *head == '\r')) {
278         *head = '\0';
279         head++;
280     }
281     if (strlen(str) == 0) {
282         return NULL;
283     }
284     return head;
285 }
286 
LoadGroupUser_(void)287 static void LoadGroupUser_(void)
288 {
289     // decode group file
290     FILE *fp = fopen(GROUP_FILE_PATH, "r");
291     const uint32_t buffSize = 1024;  // 1024 max buffer for decode
292     char *buff = (char *)calloc(1, buffSize);
293     while (fp != NULL && buff != NULL && fgets(buff, buffSize, fp) != NULL) {
294         buff[buffSize - 1] = '\0';
295         // deviceprivate:x:1053:root,shell,system,samgr,hdf_devmgr,deviceinfo,dsoftbus,dms,account
296         char *buffer = UserNameTrim(buff);
297         PARAM_CHECK(buffer != NULL, continue, "Invalid buffer %s", buff);
298 
299         PARAM_LOGV("LoadGroupUser_ '%s'", buffer);
300         // group name
301         char *groupName = strtok(buffer, ":");
302         groupName = UserNameTrim(groupName);
303         PARAM_CHECK(groupName != NULL, continue, "Invalid group name %s", buff);
304         gid_t gid = -1;
305         GetGroupIdByName(&gid, groupName);
306 
307         // skip x
308         (void)strtok(NULL, ":");
309         char *strGid = strtok(NULL, ":");
310         char *userName = strGid + strlen(strGid) + 1;
311         userName = UserNameTrim(userName);
312         PARAM_LOGV("LoadGroupUser_ %s userName '%s'", groupName, userName);
313         if (userName == NULL) {
314             AddGroupUser(groupName, gid);
315             continue;
316         }
317         char *tmp = strtok(userName, ",");
318         while (tmp != NULL) {
319             PARAM_LOGV("LoadGroupUser_ %s userName '%s'", groupName, tmp);
320             AddGroupUser(UserNameTrim(tmp), gid);
321             userName = tmp + strlen(tmp) + 1;
322             tmp = strtok(NULL, ",");
323         }
324         // last username
325         if (userName != NULL) {
326             AddGroupUser(UserNameTrim(userName), gid);
327         }
328     }
329     if (fp != NULL) {
330         (void)fclose(fp);
331     }
332     if (buff != NULL) {
333         free(buff);
334     }
335     return;
336 }
337 #else
LoadGroupUser_(void)338 static void LoadGroupUser_(void)
339 {
340     struct group *data = NULL;
341     while ((data = getgrent()) != NULL) {
342         if (data->gr_name == NULL || data->gr_mem == NULL) {
343             continue;
344         }
345         if (data->gr_mem[0] == NULL) { // default user in group
346             AddGroupUser(data->gr_name, data->gr_gid);
347             continue;
348         }
349         int index = 0;
350         while (data->gr_mem[index]) { // user in this group
351             AddGroupUser(data->gr_mem[index], data->gr_gid);
352             index++;
353         }
354     }
355     endgrent();
356 }
357 #endif
358 
LoadGroupUser(void)359 INIT_LOCAL_API void LoadGroupUser(void)
360 {
361     PARAM_LOGV("LoadGroupUser ");
362     LoadGroupUser_();
363 }
364