param_dac.c 9.7 KB
Newer Older
S
sun_fan 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * 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.
 */

#include <grp.h>
#include <pwd.h>
#include <sys/stat.h>
#include <sys/types.h>

21
#include "init_utils.h"
M
Mupceet 已提交
22
#include "param_manager.h"
S
sun_fan 已提交
23
#include "param_security.h"
M
Mupceet 已提交
24
#include "param_trie.h"
S
sun_fan 已提交
25 26
#include "param_utils.h"

M
Mupceet 已提交
27
#define USER_BUFFER_LEN 64
M
Mupceet 已提交
28
#define GROUP_FORMAT "const.group"
S
sun_fan 已提交
29

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

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

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

M
Mupceet 已提交
79
static int InitLocalSecurityLabel(ParamSecurityLabel *security, int isInit)
S
sun_fan 已提交
80 81
{
    UNUSED(isInit);
M
Mupceet 已提交
82 83 84 85 86 87 88 89 90
    PARAM_CHECK(security != NULL, return -1, "Invalid security");
    security->cred.pid = getpid();
#if defined __LITEOS_A__ || defined __LITEOS_M__
    security->cred.uid = getuid();
    security->cred.gid = 0;
    security->flags[PARAM_SECURITY_DAC] |= LABEL_CHECK_IN_ALL_PROCESS;
#else
    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;
X
xlei1030 已提交
93
#endif
S
sun_fan 已提交
94 95 96 97 98 99 100 101
    return 0;
}

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

M
Mupceet 已提交
102
static int LoadOneParam_(const uint32_t *context, const char *name, const char *value)
X
xionglei6 已提交
103 104 105 106 107
{
    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 已提交
108
    AddSecurityLabel(&auditData);
X
xionglei6 已提交
109 110 111
    return 0;
}

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

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

M
Mupceet 已提交
143
static int DacGetParamSecurityLabel(const char *path)
S
sun_fan 已提交
144
{
M
Mupceet 已提交
145
    PARAM_CHECK(path != NULL, return -1, "Invalid param");
S
sun_fan 已提交
146 147
    struct stat st;
    if ((stat(path, &st) == 0) && !S_ISDIR(st.st_mode)) {
M
Mupceet 已提交
148
        return ProcessParamFile(path, NULL);
S
sun_fan 已提交
149
    }
M
Mupceet 已提交
150 151
    PARAM_LOGV("DacGetParamSecurityLabel %s ", path);
    return ReadFileInDir(path, ".para.dac", ProcessParamFile, NULL);
S
sun_fan 已提交
152 153 154 155 156 157 158 159 160
}

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 已提交
161
static int CheckUserInGroup(WorkSpace *space, gid_t groupId, uid_t uid)
X
add ut  
xionglei6 已提交
162
{
M
Mupceet 已提交
163
#ifdef __MUSL__
M
Mupceet 已提交
164 165 166 167 168 169 170 171 172
    static char buffer[USER_BUFFER_LEN] = {0};
    uint32_t labelIndex = 0;
    int ret = sprintf_s(buffer, sizeof(buffer) - 1, "%s.%d.%d", GROUP_FORMAT, groupId, uid);
    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);
    ParamSecruityNode *node = (ParamSecruityNode *)GetTrieNode(space, labelIndex);
    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 已提交
173 174
        return 0;
    }
X
add ut  
xionglei6 已提交
175
    return -1;
M
Mupceet 已提交
176 177 178
#else
    return 0;
#endif
X
add ut  
xionglei6 已提交
179 180
}

M
Mupceet 已提交
181
static int DacCheckParamPermission(const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode)
S
sun_fan 已提交
182
{
M
Mupceet 已提交
183 184 185 186 187
#if defined(__LITEOS_A__)
    uid_t uid = getuid();
    return uid <= SYS_UID_INDEX ? DAC_RESULT_PERMISSION : DAC_RESULT_FORBIDED;
#endif
#if defined(__LITEOS_M__)
X
x00405909 已提交
188
    return DAC_RESULT_PERMISSION;
M
Mupceet 已提交
189 190
#endif

S
sun_fan 已提交
191
    int ret = DAC_RESULT_FORBIDED;
M
Mupceet 已提交
192 193 194 195 196 197 198
    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);
    ParamSecruityNode *node = (ParamSecruityNode *)GetTrieNode(space, labelIndex);
    PARAM_CHECK(node != NULL, return DAC_RESULT_FORBIDED, "Can not get security label %d", labelIndex);
S
sun_fan 已提交
199
    /**
M
Mupceet 已提交
200
     * DAC group
S
sun_fan 已提交
201 202
     * user:group:read|write|watch
     */
4
411148299@qq.com 已提交
203
    uint32_t localMode;
M
Mupceet 已提交
204
    if (srcLabel->cred.uid == node->uid) {
S
sun_fan 已提交
205
        localMode = mode & (DAC_READ | DAC_WRITE | DAC_WATCH);
M
Mupceet 已提交
206
    } else if (srcLabel->cred.gid == node->gid) {
S
sun_fan 已提交
207
        localMode = (mode & (DAC_READ | DAC_WRITE | DAC_WATCH)) >> DAC_GROUP_START;
M
Mupceet 已提交
208
    } else if (CheckUserInGroup(space, node->gid, srcLabel->cred.uid) == 0) {  // user in group
X
add ut  
xionglei6 已提交
209
        localMode = (mode & (DAC_READ | DAC_WRITE | DAC_WATCH)) >> DAC_GROUP_START;
S
sun_fan 已提交
210 211 212
    } else {
        localMode = (mode & (DAC_READ | DAC_WRITE | DAC_WATCH)) >> DAC_OTHER_START;
    }
M
Mupceet 已提交
213
    if ((node->mode & localMode) != 0) {
S
sun_fan 已提交
214 215
        ret = DAC_RESULT_PERMISSION;
    }
M
Mupceet 已提交
216 217
    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 已提交
218 219 220
    return ret;
}

M
Mupceet 已提交
221
int RegisterSecurityDacOps(ParamSecurityOps *ops, int isInit)
S
sun_fan 已提交
222 223
{
    PARAM_CHECK(ops != NULL, return -1, "Invalid param");
X
xionglei6 已提交
224
    PARAM_LOGV("RegisterSecurityDacOps %d", isInit);
M
Mupceet 已提交
225
    int ret = strcpy_s(ops->name, sizeof(ops->name), "dac");
S
sun_fan 已提交
226 227 228
    ops->securityGetLabel = NULL;
    ops->securityInitLabel = InitLocalSecurityLabel;
    ops->securityCheckFilePermission = CheckFilePermission;
M
Mupceet 已提交
229
    ops->securityCheckParamPermission = DacCheckParamPermission;
S
sun_fan 已提交
230 231
    ops->securityFreeLabel = FreeLocalSecurityLabel;
    if (isInit) {
M
Mupceet 已提交
232
        ops->securityGetLabel = DacGetParamSecurityLabel;
S
sun_fan 已提交
233
    }
M
Mupceet 已提交
234
    return ret;
S
sun_fan 已提交
235 236
}

M
Mupceet 已提交
237
static void AddGroupUser(int uid, int gid, int mode, const char *format)
S
sun_fan 已提交
238
{
M
Mupceet 已提交
239 240 241 242 243 244 245 246 247
    ParamAuditData auditData = {0};
    char buffer[USER_BUFFER_LEN] = {0};
    int ret = sprintf_s(buffer, sizeof(buffer) - 1, "%s.%d.%d", format, gid, uid);
    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 已提交
248
}
M
Mupceet 已提交
249 250 251

void LoadGroupUser(void)
{
M
Mupceet 已提交
252 253 254 255
#ifndef __MUSL__
    return;
#endif

M
Mupceet 已提交
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
#if !(defined __LITEOS_A__ || defined __LITEOS_M__)
    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 已提交
274
            AddGroupUser(uid, data->gr_gid, 0550, GROUP_FORMAT); // 0550 read and watch
M
Mupceet 已提交
275 276 277 278 279
            index++;
        }
    }
    PARAM_LOGV("LoadGroupUser getgrent fail errnor %d ", errno);
    endgrent();
X
add ut  
xionglei6 已提交
280
#endif
M
Mupceet 已提交
281
}