1d9f0492fSopenharmony_ci/* 2d9f0492fSopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3d9f0492fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4d9f0492fSopenharmony_ci * you may not use this file except in compliance with the License. 5d9f0492fSopenharmony_ci * You may obtain a copy of the License at 6d9f0492fSopenharmony_ci * 7d9f0492fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8d9f0492fSopenharmony_ci * 9d9f0492fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10d9f0492fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11d9f0492fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12d9f0492fSopenharmony_ci * See the License for the specific language governing permissions and 13d9f0492fSopenharmony_ci * limitations under the License. 14d9f0492fSopenharmony_ci */ 15d9f0492fSopenharmony_ci#include <errno.h> 16d9f0492fSopenharmony_ci#include <grp.h> 17d9f0492fSopenharmony_ci#include <pwd.h> 18d9f0492fSopenharmony_ci#include <sys/stat.h> 19d9f0492fSopenharmony_ci#include <dirent.h> 20d9f0492fSopenharmony_ci#include <string.h> 21d9f0492fSopenharmony_ci 22d9f0492fSopenharmony_ci#include "param_manager.h" 23d9f0492fSopenharmony_ci#include "param_security.h" 24d9f0492fSopenharmony_ci#include "param_trie.h" 25d9f0492fSopenharmony_ci#include "param_utils.h" 26d9f0492fSopenharmony_ci#include "param_base.h" 27d9f0492fSopenharmony_ci 28d9f0492fSopenharmony_ci#define MAX_MEMBER_IN_GROUP 128 29d9f0492fSopenharmony_ci#define MAX_BUF_SIZE 1024 30d9f0492fSopenharmony_ci#define INVALID_MODE 0550 31d9f0492fSopenharmony_ci#ifdef STARTUP_INIT_TEST 32d9f0492fSopenharmony_ci#define GROUP_FILE_PATH STARTUP_INIT_UT_PATH "/etc/group" 33d9f0492fSopenharmony_ci#else 34d9f0492fSopenharmony_ci#define GROUP_FILE_PATH "/etc/group" 35d9f0492fSopenharmony_ci#endif 36d9f0492fSopenharmony_ci#define OCT_BASE 8 37d9f0492fSopenharmony_ci#define INVALID_UID(uid) ((uid) == (uid_t)-1) 38d9f0492fSopenharmony_ci 39d9f0492fSopenharmony_cistatic void GetUserIdByName(uid_t *uid, const char *name) 40d9f0492fSopenharmony_ci{ 41d9f0492fSopenharmony_ci struct passwd *data = getpwnam(name); 42d9f0492fSopenharmony_ci if (data == NULL) { 43d9f0492fSopenharmony_ci *uid = -1; 44d9f0492fSopenharmony_ci return ; 45d9f0492fSopenharmony_ci } 46d9f0492fSopenharmony_ci *uid = data->pw_uid; 47d9f0492fSopenharmony_ci} 48d9f0492fSopenharmony_ci 49d9f0492fSopenharmony_cistatic void GetGroupIdByName(gid_t *gid, const char *name) 50d9f0492fSopenharmony_ci{ 51d9f0492fSopenharmony_ci *gid = -1; 52d9f0492fSopenharmony_ci struct group *data = getgrnam(name); 53d9f0492fSopenharmony_ci if (data != NULL) { 54d9f0492fSopenharmony_ci *gid = data->gr_gid; 55d9f0492fSopenharmony_ci return; 56d9f0492fSopenharmony_ci } 57d9f0492fSopenharmony_ci while ((data = getgrent()) != NULL) { 58d9f0492fSopenharmony_ci if ((data->gr_name != NULL) && (strcmp(data->gr_name, name) == 0)) { 59d9f0492fSopenharmony_ci *gid = data->gr_gid; 60d9f0492fSopenharmony_ci break; 61d9f0492fSopenharmony_ci } 62d9f0492fSopenharmony_ci } 63d9f0492fSopenharmony_ci endgrent(); 64d9f0492fSopenharmony_ci} 65d9f0492fSopenharmony_ci 66d9f0492fSopenharmony_ci// user:group:r|w 67d9f0492fSopenharmony_cistatic int GetParamDacData(ParamDacData *dacData, const char *value) 68d9f0492fSopenharmony_ci{ 69d9f0492fSopenharmony_ci static const struct { 70d9f0492fSopenharmony_ci const char *name; 71d9f0492fSopenharmony_ci int value; 72d9f0492fSopenharmony_ci } paramTypes[] = { 73d9f0492fSopenharmony_ci { "int", PARAM_TYPE_INT }, 74d9f0492fSopenharmony_ci { "string", PARAM_TYPE_STRING }, 75d9f0492fSopenharmony_ci { "bool", PARAM_TYPE_BOOL }, 76d9f0492fSopenharmony_ci }; 77d9f0492fSopenharmony_ci 78d9f0492fSopenharmony_ci char *groupName = strstr(value, ":"); 79d9f0492fSopenharmony_ci if (groupName == NULL) { 80d9f0492fSopenharmony_ci return -1; 81d9f0492fSopenharmony_ci } 82d9f0492fSopenharmony_ci char *mode = strstr(groupName + 1, ":"); 83d9f0492fSopenharmony_ci if (mode == NULL) { 84d9f0492fSopenharmony_ci return -1; 85d9f0492fSopenharmony_ci } 86d9f0492fSopenharmony_ci 87d9f0492fSopenharmony_ci uint32_t nameLen = groupName - value; 88d9f0492fSopenharmony_ci char *name = (char *)value; 89d9f0492fSopenharmony_ci name[nameLen] = '\0'; 90d9f0492fSopenharmony_ci GetUserIdByName(&dacData->uid, name); 91d9f0492fSopenharmony_ci nameLen = mode - groupName - 1; 92d9f0492fSopenharmony_ci name = (char *)groupName + 1; 93d9f0492fSopenharmony_ci name[nameLen] = '\0'; 94d9f0492fSopenharmony_ci GetGroupIdByName(&dacData->gid, name); 95d9f0492fSopenharmony_ci 96d9f0492fSopenharmony_ci dacData->paramType = PARAM_TYPE_STRING; 97d9f0492fSopenharmony_ci char *type = strstr(mode + 1, ":"); 98d9f0492fSopenharmony_ci if (type != NULL) { 99d9f0492fSopenharmony_ci *type = '\0'; 100d9f0492fSopenharmony_ci type++; 101d9f0492fSopenharmony_ci for (size_t i = 0; (type != NULL) && (i < ARRAY_LENGTH(paramTypes)); i++) { 102d9f0492fSopenharmony_ci if (strcmp(paramTypes[i].name, type) == 0) { 103d9f0492fSopenharmony_ci dacData->paramType = paramTypes[i].value; 104d9f0492fSopenharmony_ci } 105d9f0492fSopenharmony_ci } 106d9f0492fSopenharmony_ci } 107d9f0492fSopenharmony_ci dacData->mode = (uint16_t)strtol(mode + 1, NULL, OCT_BASE); 108d9f0492fSopenharmony_ci return 0; 109d9f0492fSopenharmony_ci} 110d9f0492fSopenharmony_ci 111d9f0492fSopenharmony_cistatic int InitLocalSecurityLabel(ParamSecurityLabel *security, int isInit) 112d9f0492fSopenharmony_ci{ 113d9f0492fSopenharmony_ci UNUSED(isInit); 114d9f0492fSopenharmony_ci PARAM_CHECK(security != NULL, return -1, "Invalid security"); 115d9f0492fSopenharmony_ci security->cred.pid = getpid(); 116d9f0492fSopenharmony_ci security->cred.uid = geteuid(); 117d9f0492fSopenharmony_ci security->cred.gid = getegid(); 118d9f0492fSopenharmony_ci // support check write permission in client 119d9f0492fSopenharmony_ci security->flags[PARAM_SECURITY_DAC] |= LABEL_CHECK_IN_ALL_PROCESS; 120d9f0492fSopenharmony_ci return 0; 121d9f0492fSopenharmony_ci} 122d9f0492fSopenharmony_ci 123d9f0492fSopenharmony_cistatic int FreeLocalSecurityLabel(ParamSecurityLabel *srcLabel) 124d9f0492fSopenharmony_ci{ 125d9f0492fSopenharmony_ci return 0; 126d9f0492fSopenharmony_ci} 127d9f0492fSopenharmony_ci 128d9f0492fSopenharmony_cistatic int DacGetGroupMember(gid_t gid, uid_t *member, uint32_t *memberSize) 129d9f0492fSopenharmony_ci{ 130d9f0492fSopenharmony_ci int32_t inputLen = (int32_t)*memberSize; 131d9f0492fSopenharmony_ci *memberSize = 0; 132d9f0492fSopenharmony_ci struct group *data = getgrgid(gid); 133d9f0492fSopenharmony_ci if (data == NULL || data->gr_mem == NULL) { 134d9f0492fSopenharmony_ci return 0; 135d9f0492fSopenharmony_ci } 136d9f0492fSopenharmony_ci int i = 0; 137d9f0492fSopenharmony_ci int memIndex = 0; 138d9f0492fSopenharmony_ci while (data->gr_mem[i]) { 139d9f0492fSopenharmony_ci uid_t uid; 140d9f0492fSopenharmony_ci GetUserIdByName(&uid, data->gr_mem[i]); 141d9f0492fSopenharmony_ci if (INVALID_UID(uid)) { 142d9f0492fSopenharmony_ci i++; 143d9f0492fSopenharmony_ci continue; 144d9f0492fSopenharmony_ci } 145d9f0492fSopenharmony_ci if ((memIndex + 1) > inputLen) { 146d9f0492fSopenharmony_ci PARAM_LOGE("Not enough memory for uid member %u", gid); 147d9f0492fSopenharmony_ci break; 148d9f0492fSopenharmony_ci } 149d9f0492fSopenharmony_ci member[memIndex++] = uid; 150d9f0492fSopenharmony_ci i++; 151d9f0492fSopenharmony_ci } 152d9f0492fSopenharmony_ci uid_t uid = 0; 153d9f0492fSopenharmony_ci GetUserIdByName(&uid, data->gr_name); 154d9f0492fSopenharmony_ci if (!INVALID_UID(uid) && ((memIndex + 1) < inputLen)) { 155d9f0492fSopenharmony_ci member[memIndex++] = uid; 156d9f0492fSopenharmony_ci } 157d9f0492fSopenharmony_ci *memberSize = memIndex; 158d9f0492fSopenharmony_ci return 0; 159d9f0492fSopenharmony_ci} 160d9f0492fSopenharmony_ci 161d9f0492fSopenharmony_cistatic int LoadOneParam_(const uint32_t *context, const char *name, const char *value) 162d9f0492fSopenharmony_ci{ 163d9f0492fSopenharmony_ci ParamAuditData *auditData = (ParamAuditData *)context; 164d9f0492fSopenharmony_ci auditData->dacData.gid = -1; 165d9f0492fSopenharmony_ci auditData->dacData.uid = -1; 166d9f0492fSopenharmony_ci auditData->name = name; 167d9f0492fSopenharmony_ci int ret = GetParamDacData(&auditData->dacData, value); 168d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return -1, "Failed to get param info %d %s", ret, name); 169d9f0492fSopenharmony_ci if (INVALID_UID(auditData->dacData.gid) || INVALID_UID(auditData->dacData.uid)) { 170d9f0492fSopenharmony_ci PARAM_LOGW("Invalid dac for '%s' gid %d uid %d", name, auditData->dacData.gid, auditData->dacData.uid); 171d9f0492fSopenharmony_ci } 172d9f0492fSopenharmony_ci // get uid from group 173d9f0492fSopenharmony_ci auditData->memberNum = MAX_MEMBER_IN_GROUP; 174d9f0492fSopenharmony_ci ret = DacGetGroupMember(auditData->dacData.gid, auditData->members, &auditData->memberNum); 175d9f0492fSopenharmony_ci if (ret != 0) { 176d9f0492fSopenharmony_ci auditData->memberNum = 1; 177d9f0492fSopenharmony_ci auditData->members[0] = auditData->dacData.gid; 178d9f0492fSopenharmony_ci } 179d9f0492fSopenharmony_ci 180d9f0492fSopenharmony_ci return AddSecurityLabel(auditData); 181d9f0492fSopenharmony_ci} 182d9f0492fSopenharmony_ci 183d9f0492fSopenharmony_cistatic int LoadParamLabels(const char *fileName) 184d9f0492fSopenharmony_ci{ 185d9f0492fSopenharmony_ci int result = 0; 186d9f0492fSopenharmony_ci ParamAuditData *auditData = (ParamAuditData *)calloc(1, 187d9f0492fSopenharmony_ci sizeof(ParamAuditData) + sizeof(uid_t) * MAX_MEMBER_IN_GROUP); 188d9f0492fSopenharmony_ci if (auditData == NULL) { 189d9f0492fSopenharmony_ci PARAM_LOGE("Failed to alloc memory %s", fileName); 190d9f0492fSopenharmony_ci return result; 191d9f0492fSopenharmony_ci } 192d9f0492fSopenharmony_ci uint32_t infoCount = 0; 193d9f0492fSopenharmony_ci FILE *fp = fopen(fileName, "r"); 194d9f0492fSopenharmony_ci const uint32_t buffSize = PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX + 10; // 10 size 195d9f0492fSopenharmony_ci char *buff = (char *)calloc(1, buffSize); 196d9f0492fSopenharmony_ci while (fp != NULL && buff != NULL && fgets(buff, buffSize, fp) != NULL) { 197d9f0492fSopenharmony_ci buff[buffSize - 1] = '\0'; 198d9f0492fSopenharmony_ci result = SplitParamString(buff, NULL, 0, LoadOneParam_, (const uint32_t *)auditData); 199d9f0492fSopenharmony_ci if (result != 0) { 200d9f0492fSopenharmony_ci PARAM_LOGE("Failed to split string %s fileName %s, result is:%d", buff, fileName, result); 201d9f0492fSopenharmony_ci break; 202d9f0492fSopenharmony_ci } 203d9f0492fSopenharmony_ci infoCount++; 204d9f0492fSopenharmony_ci } 205d9f0492fSopenharmony_ci 206d9f0492fSopenharmony_ci if (result == 0) { 207d9f0492fSopenharmony_ci PARAM_LOGI("Load parameter label total %u success %s", infoCount, fileName); 208d9f0492fSopenharmony_ci } 209d9f0492fSopenharmony_ci 210d9f0492fSopenharmony_ci if (fp != NULL) { 211d9f0492fSopenharmony_ci (void)fclose(fp); 212d9f0492fSopenharmony_ci } 213d9f0492fSopenharmony_ci if (buff != NULL) { 214d9f0492fSopenharmony_ci free(buff); 215d9f0492fSopenharmony_ci } 216d9f0492fSopenharmony_ci if (auditData != NULL) { 217d9f0492fSopenharmony_ci free(auditData); 218d9f0492fSopenharmony_ci } 219d9f0492fSopenharmony_ci return result; 220d9f0492fSopenharmony_ci} 221d9f0492fSopenharmony_ci 222d9f0492fSopenharmony_cistatic int ProcessParamFile(const char *fileName, void *context) 223d9f0492fSopenharmony_ci{ 224d9f0492fSopenharmony_ci UNUSED(context); 225d9f0492fSopenharmony_ci return LoadParamLabels(fileName); 226d9f0492fSopenharmony_ci} 227d9f0492fSopenharmony_ci 228d9f0492fSopenharmony_cistatic int DacGetParamSecurityLabel(const char *path) 229d9f0492fSopenharmony_ci{ 230d9f0492fSopenharmony_ci PARAM_CHECK(path != NULL, return -1, "Invalid param"); 231d9f0492fSopenharmony_ci struct stat st; 232d9f0492fSopenharmony_ci if ((stat(path, &st) == 0) && !S_ISDIR(st.st_mode)) { 233d9f0492fSopenharmony_ci return ProcessParamFile(path, NULL); 234d9f0492fSopenharmony_ci } 235d9f0492fSopenharmony_ci 236d9f0492fSopenharmony_ci PARAM_LOGV("DacGetParamSecurityLabel %s ", path); 237d9f0492fSopenharmony_ci DIR *pDir = opendir(path); 238d9f0492fSopenharmony_ci PARAM_CHECK(pDir != NULL, return -1, "Read dir :%s failed.%d", path, errno); 239d9f0492fSopenharmony_ci char *fileName = calloc(1, MAX_BUF_SIZE); 240d9f0492fSopenharmony_ci PARAM_CHECK(fileName != NULL, closedir(pDir); 241d9f0492fSopenharmony_ci return -1, "Failed to malloc for %s", path); 242d9f0492fSopenharmony_ci 243d9f0492fSopenharmony_ci struct dirent *dp; 244d9f0492fSopenharmony_ci uint32_t count = 0; 245d9f0492fSopenharmony_ci while ((dp = readdir(pDir)) != NULL) { 246d9f0492fSopenharmony_ci if (dp->d_type == DT_DIR) { 247d9f0492fSopenharmony_ci continue; 248d9f0492fSopenharmony_ci } 249d9f0492fSopenharmony_ci char *tmp = strstr(dp->d_name, ".para.dac"); 250d9f0492fSopenharmony_ci if (tmp == NULL) { 251d9f0492fSopenharmony_ci continue; 252d9f0492fSopenharmony_ci } 253d9f0492fSopenharmony_ci if (strcmp(tmp, ".para.dac") != 0) { 254d9f0492fSopenharmony_ci continue; 255d9f0492fSopenharmony_ci } 256d9f0492fSopenharmony_ci int ret = PARAM_SPRINTF(fileName, MAX_BUF_SIZE, "%s/%s", path, dp->d_name); 257d9f0492fSopenharmony_ci if (ret <= 0) { 258d9f0492fSopenharmony_ci PARAM_LOGE("Failed to get file name for %s", dp->d_name); 259d9f0492fSopenharmony_ci continue; 260d9f0492fSopenharmony_ci } 261d9f0492fSopenharmony_ci if ((stat(fileName, &st) == 0) && !S_ISDIR(st.st_mode)) { 262d9f0492fSopenharmony_ci count++; 263d9f0492fSopenharmony_ci ret = ProcessParamFile(fileName, NULL); 264d9f0492fSopenharmony_ci if (ret != 0) { 265d9f0492fSopenharmony_ci free(fileName); 266d9f0492fSopenharmony_ci closedir(pDir); 267d9f0492fSopenharmony_ci return ret; 268d9f0492fSopenharmony_ci }; 269d9f0492fSopenharmony_ci } 270d9f0492fSopenharmony_ci } 271d9f0492fSopenharmony_ci PARAM_LOGV("Get parameter security label dac number is %d, from %s.", count, path); 272d9f0492fSopenharmony_ci free(fileName); 273d9f0492fSopenharmony_ci closedir(pDir); 274d9f0492fSopenharmony_ci return 0; 275d9f0492fSopenharmony_ci} 276d9f0492fSopenharmony_ci 277d9f0492fSopenharmony_cistatic int CheckFilePermission(const ParamSecurityLabel *localLabel, const char *fileName, int flags) 278d9f0492fSopenharmony_ci{ 279d9f0492fSopenharmony_ci UNUSED(flags); 280d9f0492fSopenharmony_ci PARAM_CHECK(localLabel != NULL && fileName != NULL, return -1, "Invalid param"); 281d9f0492fSopenharmony_ci return 0; 282d9f0492fSopenharmony_ci} 283d9f0492fSopenharmony_ci 284d9f0492fSopenharmony_ciINIT_LOCAL_API int RegisterSecurityDacOps(ParamSecurityOps *ops, int isInit) 285d9f0492fSopenharmony_ci{ 286d9f0492fSopenharmony_ci PARAM_CHECK(ops != NULL, return -1, "Invalid param"); 287d9f0492fSopenharmony_ci PARAM_LOGV("RegisterSecurityDacOps %d", isInit); 288d9f0492fSopenharmony_ci int ret = PARAM_STRCPY(ops->name, sizeof(ops->name), "dac"); 289d9f0492fSopenharmony_ci ops->securityInitLabel = InitLocalSecurityLabel; 290d9f0492fSopenharmony_ci ops->securityCheckFilePermission = CheckFilePermission; 291d9f0492fSopenharmony_ci#ifdef STARTUP_INIT_TEST 292d9f0492fSopenharmony_ci ops->securityCheckParamPermission = DacCheckParamPermission; 293d9f0492fSopenharmony_ci#endif 294d9f0492fSopenharmony_ci ops->securityFreeLabel = FreeLocalSecurityLabel; 295d9f0492fSopenharmony_ci if (isInit) { 296d9f0492fSopenharmony_ci ops->securityGetLabel = DacGetParamSecurityLabel; 297d9f0492fSopenharmony_ci } 298d9f0492fSopenharmony_ci return ret; 299d9f0492fSopenharmony_ci} 300