param_dac.c 10.4 KB
Newer Older
S
sun_fan 已提交
1
/*
M
Mupceet 已提交
2
 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
S
sun_fan 已提交
3 4 5 6 7 8 9 10 11 12 13 14
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
M
Mupceet 已提交
15
#include <errno.h>
S
sun_fan 已提交
16 17 18 19
#include <grp.h>
#include <pwd.h>
#include <sys/stat.h>
#include <sys/types.h>
M
Mupceet 已提交
20 21 22
#include <errno.h>
#include <dirent.h>
#include <fcntl.h>
S
sun_fan 已提交
23

24
#include "init_utils.h"
M
Mupceet 已提交
25
#include "param_manager.h"
S
sun_fan 已提交
26
#include "param_security.h"
M
Mupceet 已提交
27
#include "param_trie.h"
S
sun_fan 已提交
28
#include "param_utils.h"
M
Mupceet 已提交
29
#include "param_base.h"
S
sun_fan 已提交
30

M
Mupceet 已提交
31
#define USER_BUFFER_LEN 64
M
Mupceet 已提交
32
#define MAX_BUF_SIZE  1024
M
Mupceet 已提交
33
#define GROUP_FORMAT "const.group"
S
sun_fan 已提交
34

M
Mupceet 已提交
35
#define OCT_BASE 8
X
xionglei6 已提交
36
static void GetUserIdByName(uid_t *uid, const char *name, uint32_t nameLen)
S
sun_fan 已提交
37 38 39
{
    *uid = -1;
    struct passwd *data = NULL;
X
xionglei6 已提交
40
    while ((data = getpwent()) != NULL) {
4
411148299@qq.com 已提交
41 42
        if ((data->pw_name != NULL) && (strlen(data->pw_name) == nameLen) &&
            (strncmp(data->pw_name, name, nameLen) == 0)) {
S
sun_fan 已提交
43
            *uid = data->pw_uid;
X
xionglei6 已提交
44
            break;
S
sun_fan 已提交
45 46
        }
    }
X
xionglei6 已提交
47
    endpwent();
S
sun_fan 已提交
48 49
}

X
xionglei6 已提交
50
static void GetGroupIdByName(gid_t *gid, const char *name, uint32_t nameLen)
S
sun_fan 已提交
51 52 53
{
    *gid = -1;
    struct group *data = NULL;
X
xionglei6 已提交
54
    while ((data = getgrent()) != NULL) {
4
411148299@qq.com 已提交
55 56
        if ((data->gr_name != NULL) && (strlen(data->gr_name) == nameLen) &&
            (strncmp(data->gr_name, name, nameLen) == 0)) {
S
sun_fan 已提交
57 58 59 60
            *gid = data->gr_gid;
            break;
        }
    }
X
xionglei6 已提交
61
    endgrent();
S
sun_fan 已提交
62 63 64
}

// user:group:r|w
X
xionglei6 已提交
65
static int GetParamDacData(ParamDacData *dacData, const char *value)
S
sun_fan 已提交
66
{
4
411148299@qq.com 已提交
67 68 69
    if (dacData == NULL) {
        return -1;
    }
S
sun_fan 已提交
70 71 72 73 74 75 76 77
    char *groupName = strstr(value, ":");
    if (groupName == NULL) {
        return -1;
    }
    char *mode = strstr(groupName + 1, ":");
    if (mode == NULL) {
        return -1;
    }
X
xionglei6 已提交
78 79
    GetUserIdByName(&dacData->uid, value, groupName - value);
    GetGroupIdByName(&dacData->gid, groupName + 1, mode - groupName - 1);
S
sun_fan 已提交
80 81 82 83
    dacData->mode = strtol(mode + 1, NULL, OCT_BASE);
    return 0;
}

M
Mupceet 已提交
84
static int InitLocalSecurityLabel(ParamSecurityLabel *security, int isInit)
S
sun_fan 已提交
85 86
{
    UNUSED(isInit);
M
Mupceet 已提交
87 88 89 90
    PARAM_CHECK(security != NULL, return -1, "Invalid security");
    security->cred.pid = getpid();
    security->cred.uid = geteuid();
    security->cred.gid = getegid();
S
sun_fan 已提交
91
    // support check write permission in client
M
Mupceet 已提交
92
    security->flags[PARAM_SECURITY_DAC] |= LABEL_CHECK_IN_ALL_PROCESS;
S
sun_fan 已提交
93 94 95 96 97 98 99 100
    return 0;
}

static int FreeLocalSecurityLabel(ParamSecurityLabel *srcLabel)
{
    return 0;
}

M
Mupceet 已提交
101
static int LoadOneParam_(const uint32_t *context, const char *name, const char *value)
X
xionglei6 已提交
102 103 104 105 106
{
    ParamAuditData auditData = {0};
    auditData.name = name;
    int ret = GetParamDacData(&auditData.dacData, value);
    PARAM_CHECK(ret == 0, return -1, "Failed to get param info %d %s", ret, name);
M
Mupceet 已提交
107
    AddSecurityLabel(&auditData);
X
xionglei6 已提交
108 109 110
    return 0;
}

M
Mupceet 已提交
111
static int LoadParamLabels(const char *fileName)
S
sun_fan 已提交
112
{
4
411148299@qq.com 已提交
113
    uint32_t infoCount = 0;
S
sun_fan 已提交
114
    FILE *fp = fopen(fileName, "r");
M
Mupceet 已提交
115 116
    const uint32_t buffSize = PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX + 10;  // 10 size
    char *buff = (char *)calloc(1, buffSize);
X
xionglei6 已提交
117 118
    while (fp != NULL && buff != NULL && fgets(buff, buffSize, fp) != NULL) {
        buff[buffSize - 1] = '\0';
M
Mupceet 已提交
119
        int ret = SpliteString(buff, NULL, 0, LoadOneParam_, NULL);
X
xionglei6 已提交
120
        if (ret != 0) {
121
            PARAM_LOGE("Failed to split string %s fileName %s", buff, fileName);
S
sun_fan 已提交
122 123 124 125 126
            continue;
        }
        infoCount++;
    }
    PARAM_LOGI("Load parameter label total %u success %s", infoCount, fileName);
4
411148299@qq.com 已提交
127
    if (fp != NULL) {
S
sun_fan 已提交
128 129
        (void)fclose(fp);
    }
4
411148299@qq.com 已提交
130 131 132
    if (buff != NULL) {
        free(buff);
    }
S
sun_fan 已提交
133 134 135 136 137
    return 0;
}

static int ProcessParamFile(const char *fileName, void *context)
{
M
Mupceet 已提交
138 139
    UNUSED(context);
    return LoadParamLabels(fileName);
S
sun_fan 已提交
140 141
}

M
Mupceet 已提交
142
static int DacGetParamSecurityLabel(const char *path)
S
sun_fan 已提交
143
{
M
Mupceet 已提交
144
    PARAM_CHECK(path != NULL, return -1, "Invalid param");
S
sun_fan 已提交
145 146
    struct stat st;
    if ((stat(path, &st) == 0) && !S_ISDIR(st.st_mode)) {
M
Mupceet 已提交
147
        return ProcessParamFile(path, NULL);
S
sun_fan 已提交
148
    }
M
Mupceet 已提交
149

M
Mupceet 已提交
150
    PARAM_LOGV("DacGetParamSecurityLabel %s ", path);
M
Mupceet 已提交
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
    DIR *pDir = opendir(path);
    PARAM_CHECK(pDir != NULL, return -1, "Read dir :%s failed.%d", path, errno);
    char *fileName = malloc(MAX_BUF_SIZE);
    PARAM_CHECK(fileName != NULL, closedir(pDir);
        return -1, "Failed to malloc for %s", path);

    struct dirent *dp;
    uint32_t count = 0;
    while ((dp = readdir(pDir)) != NULL) {
        if (dp->d_type == DT_DIR) {
            continue;
        }
        char *tmp = strstr(dp->d_name, ".para.dac");
        if (tmp == NULL) {
            continue;
        }
        if (strcmp(tmp, ".para.dac") != 0) {
            continue;
        }
        int ret = ParamSprintf(fileName, MAX_BUF_SIZE, "%s/%s", path, dp->d_name);
        if (ret <= 0) {
            PARAM_LOGE("Failed to get file name for %s", dp->d_name);
            continue;
        }
        if ((stat(fileName, &st) == 0) && !S_ISDIR(st.st_mode)) {
            count++;
            ProcessParamFile(fileName, NULL);
        }
    }
    PARAM_LOGI("DacGetParamSecurityLabel path %s %d", path, count);
    free(fileName);
    closedir(pDir);
    return 0;
S
sun_fan 已提交
184 185 186 187 188 189 190 191 192
}

static int CheckFilePermission(const ParamSecurityLabel *localLabel, const char *fileName, int flags)
{
    UNUSED(flags);
    PARAM_CHECK(localLabel != NULL && fileName != NULL, return -1, "Invalid param");
    return 0;
}

M
Mupceet 已提交
193
static int CheckUserInGroup(WorkSpace *space, gid_t groupId, uid_t uid)
X
add ut  
xionglei6 已提交
194
{
M
Mupceet 已提交
195
#ifdef __MUSL__
M
Mupceet 已提交
196 197
    static char buffer[USER_BUFFER_LEN] = {0};
    uint32_t labelIndex = 0;
M
Mupceet 已提交
198
    int ret = ParamSprintf(buffer, sizeof(buffer), "%s.%d.%d", GROUP_FORMAT, groupId, uid);
M
Mupceet 已提交
199 200
    PARAM_CHECK(ret >= 0, return -1, "Failed to format name for %s.%d.%d", GROUP_FORMAT, groupId, uid);
    (void)FindTrieNode(space, buffer, strlen(buffer), &labelIndex);
M
Mupceet 已提交
201
    ParamSecurityNode *node = (ParamSecurityNode *)GetTrieNode(space, labelIndex);
M
Mupceet 已提交
202 203 204
    PARAM_CHECK(node != NULL, return DAC_RESULT_FORBIDED, "Can not get security label %d", labelIndex);
    PARAM_LOGV("CheckUserInGroup %s groupid %d uid %d", buffer, groupId, uid);
    if (node->gid == groupId && node->uid == uid) {
X
xionglei6 已提交
205 206
        return 0;
    }
X
add ut  
xionglei6 已提交
207
    return -1;
M
Mupceet 已提交
208 209 210
#else
    return 0;
#endif
X
add ut  
xionglei6 已提交
211 212
}

M
Mupceet 已提交
213
static int DacCheckParamPermission(const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode)
S
sun_fan 已提交
214 215
{
    int ret = DAC_RESULT_FORBIDED;
M
Mupceet 已提交
216 217 218 219 220
    uint32_t labelIndex = 0;
    // get dac label
    WorkSpace *space = GetWorkSpace(WORKSPACE_NAME_DAC);
    PARAM_CHECK(space != NULL, return DAC_RESULT_FORBIDED, "Failed to get dac space %s", name);
    (void)FindTrieNode(space, name, strlen(name), &labelIndex);
M
Mupceet 已提交
221
    ParamSecurityNode *node = (ParamSecurityNode *)GetTrieNode(space, labelIndex);
M
Mupceet 已提交
222
    PARAM_CHECK(node != NULL, return DAC_RESULT_FORBIDED, "Can not get security label %d", labelIndex);
S
sun_fan 已提交
223
    /**
M
Mupceet 已提交
224
     * DAC group
S
sun_fan 已提交
225 226
     * user:group:read|write|watch
     */
4
411148299@qq.com 已提交
227
    uint32_t localMode;
M
Mupceet 已提交
228
    if (srcLabel->cred.uid == node->uid) {
S
sun_fan 已提交
229
        localMode = mode & (DAC_READ | DAC_WRITE | DAC_WATCH);
M
Mupceet 已提交
230
    } else if (srcLabel->cred.gid == node->gid) {
S
sun_fan 已提交
231
        localMode = (mode & (DAC_READ | DAC_WRITE | DAC_WATCH)) >> DAC_GROUP_START;
M
Mupceet 已提交
232
    } else if (CheckUserInGroup(space, node->gid, srcLabel->cred.uid) == 0) {  // user in group
X
add ut  
xionglei6 已提交
233
        localMode = (mode & (DAC_READ | DAC_WRITE | DAC_WATCH)) >> DAC_GROUP_START;
S
sun_fan 已提交
234 235 236
    } else {
        localMode = (mode & (DAC_READ | DAC_WRITE | DAC_WATCH)) >> DAC_OTHER_START;
    }
M
Mupceet 已提交
237
    if ((node->mode & localMode) != 0) {
S
sun_fan 已提交
238 239
        ret = DAC_RESULT_PERMISSION;
    }
M
Mupceet 已提交
240 241
    PARAM_LOGV("Param '%s' label gid:%d uid:%d mode 0%o", name, srcLabel->cred.gid, srcLabel->cred.uid, localMode);
    PARAM_LOGV("Cfg label %d gid:%d uid:%d mode 0%o result %d", labelIndex, node->gid, node->uid, node->mode, ret);
S
sun_fan 已提交
242 243 244
    return ret;
}

M
Mupceet 已提交
245
INIT_LOCAL_API int RegisterSecurityDacOps(ParamSecurityOps *ops, int isInit)
S
sun_fan 已提交
246 247
{
    PARAM_CHECK(ops != NULL, return -1, "Invalid param");
X
xionglei6 已提交
248
    PARAM_LOGV("RegisterSecurityDacOps %d", isInit);
M
Mupceet 已提交
249
    int ret = ParamStrCpy(ops->name, sizeof(ops->name), "dac");
S
sun_fan 已提交
250 251
    ops->securityInitLabel = InitLocalSecurityLabel;
    ops->securityCheckFilePermission = CheckFilePermission;
M
Mupceet 已提交
252
    ops->securityCheckParamPermission = DacCheckParamPermission;
S
sun_fan 已提交
253 254
    ops->securityFreeLabel = FreeLocalSecurityLabel;
    if (isInit) {
M
Mupceet 已提交
255
        ops->securityGetLabel = DacGetParamSecurityLabel;
S
sun_fan 已提交
256
    }
M
Mupceet 已提交
257
    return ret;
S
sun_fan 已提交
258 259
}

M
Mupceet 已提交
260
static void AddGroupUser(unsigned int uid, unsigned int gid, int mode, const char *format)
S
sun_fan 已提交
261
{
M
Mupceet 已提交
262 263
    ParamAuditData auditData = {0};
    char buffer[USER_BUFFER_LEN] = {0};
M
Mupceet 已提交
264
    int ret = ParamSprintf(buffer, sizeof(buffer), "%s.%u.%u", format, gid, uid);
M
Mupceet 已提交
265 266 267 268 269 270
    PARAM_CHECK(ret >= 0, return, "Failed to format name for %s.%d.%d", format, gid, uid);
    auditData.name = buffer;
    auditData.dacData.uid = uid;
    auditData.dacData.gid = gid;
    auditData.dacData.mode = mode;
    AddSecurityLabel(&auditData);
S
sun_fan 已提交
271
}
M
Mupceet 已提交
272

M
Mupceet 已提交
273
INIT_LOCAL_API void LoadGroupUser(void)
M
Mupceet 已提交
274
{
M
Mupceet 已提交
275 276 277
#ifndef __MUSL__
    return;
#endif
M
Mupceet 已提交
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294
    PARAM_LOGV("LoadGroupUser ");
    uid_t uid = 0;
    struct group *data = NULL;
    while ((data = getgrent()) != NULL) {
        if (data->gr_name == NULL || data->gr_mem == NULL) {
            continue;
        }
        if (data->gr_mem[0] == NULL) { // default user in group
            GetUserIdByName(&uid, data->gr_name, strlen(data->gr_name));
            PARAM_LOGV("LoadGroupUser %s gid %d uid %d", data->gr_name, data->gr_gid, uid);
            AddGroupUser(uid, data->gr_gid, 0550, GROUP_FORMAT); // 0550 read and watch
            continue;
        }
        int index = 0;
        while (data->gr_mem[index]) { // user in this group
            GetUserIdByName(&uid, data->gr_mem[index], strlen(data->gr_mem[index]));
            PARAM_LOGV("LoadGroupUser %s gid %d uid %d user %s", data->gr_name, data->gr_gid, uid, data->gr_mem[index]);
M
Mupceet 已提交
295
            AddGroupUser(uid, data->gr_gid, 0550, GROUP_FORMAT); // 0550 read and watch
M
Mupceet 已提交
296 297 298 299 300
            index++;
        }
    }
    PARAM_LOGV("LoadGroupUser getgrent fail errnor %d ", errno);
    endgrent();
301
}