param_dac.c 9.8 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"
S
sun_fan 已提交
22 23 24 25 26 27
#include "param_security.h"
#include "param_utils.h"

#define OCT_BASE 8
static ParamSecurityLabel g_localSecurityLabel = {};

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

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

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

static int InitLocalSecurityLabel(ParamSecurityLabel **security, int isInit)
{
    UNUSED(isInit);
X
xionglei6 已提交
79
    PARAM_LOGV("InitLocalSecurityLabel uid:%d gid:%d euid: %d egid: %d ", getuid(), getgid(), geteuid(), getegid());
S
sun_fan 已提交
80 81 82 83 84 85
    g_localSecurityLabel.cred.pid = getpid();
    g_localSecurityLabel.cred.uid = geteuid();
    g_localSecurityLabel.cred.gid = getegid();
    *security = &g_localSecurityLabel;
    // support check write permission in client
    (*security)->flags |= LABEL_CHECK_FOR_ALL_PROCESS;
X
xlei1030 已提交
86 87 88
#ifdef WITH_SELINUX
    (*security)->flags = 0;
#endif
S
sun_fan 已提交
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
    return 0;
}

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

static int EncodeSecurityLabel(const ParamSecurityLabel *srcLabel, char *buffer, uint32_t *bufferSize)
{
    PARAM_CHECK(bufferSize != NULL, return -1, "Invalid param");
    if (buffer == NULL) {
        *bufferSize = sizeof(ParamSecurityLabel);
        return 0;
    }
    PARAM_CHECK(*bufferSize >= sizeof(ParamSecurityLabel), return -1, "Invalid buffersize %u", *bufferSize);
    *bufferSize = sizeof(ParamSecurityLabel);
    return memcpy_s(buffer, *bufferSize, srcLabel, sizeof(ParamSecurityLabel));
}

4
411148299@qq.com 已提交
109
static int DecodeSecurityLabel(ParamSecurityLabel **srcLabel, const char *buffer, uint32_t bufferSize)
S
sun_fan 已提交
110 111 112 113 114 115 116
{
    PARAM_CHECK(bufferSize >= sizeof(ParamSecurityLabel), return -1, "Invalid buffersize %u", bufferSize);
    PARAM_CHECK(srcLabel != NULL && buffer != NULL, return -1, "Invalid param");
    *srcLabel = (ParamSecurityLabel *)buffer;
    return 0;
}

X
xionglei6 已提交
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
typedef struct {
    SecurityLabelFunc label;
    void *context;
} LoadContext;

static int LoadOneParam_ (const uint32_t *context, const char *name, const char *value)
{
    LoadContext *loadContext = (LoadContext *)context;
    ParamAuditData auditData = {0};
    auditData.name = name;
#ifdef STARTUP_INIT_TEST
    auditData.label = value;
#endif
    int ret = GetParamDacData(&auditData.dacData, value);
    PARAM_CHECK(ret == 0, return -1, "Failed to get param info %d %s", ret, name);
    ret = loadContext->label(&auditData, loadContext->context);
    PARAM_CHECK(ret == 0, return -1, "Failed to write param info %d \"%s\"", ret, name);
    return 0;
}

S
sun_fan 已提交
137 138
static int LoadParamLabels(const char *fileName, SecurityLabelFunc label, void *context)
{
X
xionglei6 已提交
139 140 141
    LoadContext loadContext = {
        label, context
    };
4
411148299@qq.com 已提交
142
    uint32_t infoCount = 0;
S
sun_fan 已提交
143
    FILE *fp = fopen(fileName, "r");
X
xionglei6 已提交
144 145 146 147 148 149 150 151
    const uint32_t buffSize = PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX + 10; // 10 size
    char *buff = (char *)calloc(1,  buffSize);
    while (fp != NULL && buff != NULL && fgets(buff, buffSize, fp) != NULL) {
        buff[buffSize - 1] = '\0';

        int ret = SpliteString(buff, NULL, 0, LoadOneParam_, (uint32_t *)&loadContext);
        if (ret != 0) {
            PARAM_LOGE("Failed to splite string %s fileName %s", buff, fileName);
S
sun_fan 已提交
152 153 154 155 156
            continue;
        }
        infoCount++;
    }
    PARAM_LOGI("Load parameter label total %u success %s", infoCount, fileName);
4
411148299@qq.com 已提交
157
    if (fp != NULL) {
S
sun_fan 已提交
158 159
        (void)fclose(fp);
    }
4
411148299@qq.com 已提交
160 161 162
    if (buff != NULL) {
        free(buff);
    }
S
sun_fan 已提交
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
    return 0;
}

static int ProcessParamFile(const char *fileName, void *context)
{
    LabelFuncContext *cxt = (LabelFuncContext *)context;
    return LoadParamLabels(fileName, cxt->label, cxt->context);
}

static int GetParamSecurityLabel(SecurityLabelFunc label, const char *path, void *context)
{
    PARAM_CHECK(label != NULL && path != NULL, return -1, "Invalid param");
    struct stat st;
    LabelFuncContext cxt = {label, context};
    if ((stat(path, &st) == 0) && !S_ISDIR(st.st_mode)) {
        return ProcessParamFile(path, &cxt);
    }
X
xionglei6 已提交
180
    PARAM_LOGV("GetParamSecurityLabel %s ", path);
S
sun_fan 已提交
181 182 183 184 185 186 187 188 189 190
    return ReadFileInDir(path, ".para.dac", ProcessParamFile, &cxt);
}

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;
}

X
xionglei6 已提交
191
#ifdef PARAM_SUPPORT_DAC_CHECK
X
add ut  
xionglei6 已提交
192 193
static int CheckUserInGroup(gid_t groupId, uid_t uid)
{
X
xionglei6 已提交
194 195 196 197 198
    static char buffer[255] = {0}; // 255 max size
    static char userBuff[255] = {0}; // 255 max size
    struct group *grpResult = NULL;
    struct group grp = {};
    int ret = getgrgid_r(groupId, &grp, buffer, sizeof(buffer), &grpResult);
X
xionglei6 已提交
199
    if (ret != 0 || grpResult == NULL || grpResult->gr_name == NULL) {
X
add ut  
xionglei6 已提交
200 201
        return -1;
    }
X
xionglei6 已提交
202 203 204
    struct passwd data = {};
    struct passwd *userResult = NULL;
    ret = getpwuid_r(uid, &data, userBuff, sizeof(userBuff), &userResult);
X
xionglei6 已提交
205
    if (ret != 0 || userResult == NULL || userResult->pw_name == NULL) {
X
add ut  
xionglei6 已提交
206 207 208
        return -1;
    }

X
xionglei6 已提交
209 210 211 212
    PARAM_LOGV("CheckUserInGroup pw_name %s ", userResult->pw_name);
    if (strcmp(grpResult->gr_name, userResult->pw_name) == 0) {
        return 0;
    }
X
add ut  
xionglei6 已提交
213
    int index = 0;
X
xionglei6 已提交
214 215 216
    while (grpResult->gr_mem[index]) {
        PARAM_LOGV("CheckUserInGroup %s ", grpResult->gr_mem[index]);
        if (strcmp(grpResult->gr_mem[index], userResult->pw_name) == 0) {
X
add ut  
xionglei6 已提交
217 218 219 220 221 222
            return 0;
        }
        index++;
    }
    return -1;
}
X
xionglei6 已提交
223
#endif
X
add ut  
xionglei6 已提交
224

4
411148299@qq.com 已提交
225
static int CheckParamPermission(const ParamSecurityLabel *srcLabel, const ParamAuditData *auditData, uint32_t mode)
S
sun_fan 已提交
226
{
X
x00405909 已提交
227 228
#ifndef PARAM_SUPPORT_DAC_CHECK
    return DAC_RESULT_PERMISSION;
X
x00405909 已提交
229
#else
S
sun_fan 已提交
230 231 232
    int ret = DAC_RESULT_FORBIDED;
    PARAM_CHECK(srcLabel != NULL && auditData != NULL && auditData->name != NULL, return ret, "Invalid param");
    PARAM_CHECK((mode & (DAC_READ | DAC_WRITE | DAC_WATCH)) != 0, return ret, "Invalid mode %x", mode);
X
xlei1030 已提交
233
    if (srcLabel->cred.uid == 0) {
X
xlei1030 已提交
234 235
        return DAC_RESULT_PERMISSION;
    }
S
sun_fan 已提交
236 237 238 239
    /**
     * DAC group 实现的label的定义
     * user:group:read|write|watch
     */
4
411148299@qq.com 已提交
240
    uint32_t localMode;
S
sun_fan 已提交
241 242 243 244
    if (srcLabel->cred.uid == auditData->dacData.uid) {
        localMode = mode & (DAC_READ | DAC_WRITE | DAC_WATCH);
    } else if (srcLabel->cred.gid == auditData->dacData.gid) {
        localMode = (mode & (DAC_READ | DAC_WRITE | DAC_WATCH)) >> DAC_GROUP_START;
X
xionglei6 已提交
245
    } else if (CheckUserInGroup(auditData->dacData.gid, srcLabel->cred.uid) == 0) {  // user in group
X
add ut  
xionglei6 已提交
246
        localMode = (mode & (DAC_READ | DAC_WRITE | DAC_WATCH)) >> DAC_GROUP_START;
S
sun_fan 已提交
247 248 249 250 251 252
    } else {
        localMode = (mode & (DAC_READ | DAC_WRITE | DAC_WATCH)) >> DAC_OTHER_START;
    }
    if ((auditData->dacData.mode & localMode) != 0) {
        ret = DAC_RESULT_PERMISSION;
    }
X
xionglei6 已提交
253 254
    PARAM_LOGI("Src label gid:%d uid:%d ", srcLabel->cred.gid, srcLabel->cred.uid);
    PARAM_LOGI("local label gid:%d uid:%d mode %o",
4
411148299@qq.com 已提交
255
        auditData->dacData.gid, auditData->dacData.uid, auditData->dacData.mode);
X
xionglei6 已提交
256
    PARAM_LOGI("%s check %o localMode %o ret %d", auditData->name, mode, localMode, ret);
S
sun_fan 已提交
257
    return ret;
X
x00405909 已提交
258
#endif
S
sun_fan 已提交
259 260 261 262 263
}

PARAM_STATIC int RegisterSecurityDacOps(ParamSecurityOps *ops, int isInit)
{
    PARAM_CHECK(ops != NULL, return -1, "Invalid param");
X
xionglei6 已提交
264
    PARAM_LOGV("RegisterSecurityDacOps %d", isInit);
S
sun_fan 已提交
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
    ops->securityGetLabel = NULL;
    ops->securityDecodeLabel = NULL;
    ops->securityEncodeLabel = NULL;
    ops->securityInitLabel = InitLocalSecurityLabel;
    ops->securityCheckFilePermission = CheckFilePermission;
    ops->securityCheckParamPermission = CheckParamPermission;
    ops->securityFreeLabel = FreeLocalSecurityLabel;
    if (isInit) {
        ops->securityGetLabel = GetParamSecurityLabel;
        ops->securityDecodeLabel = DecodeSecurityLabel;
    } else {
        ops->securityEncodeLabel = EncodeSecurityLabel;
    }
    return 0;
}

#ifdef PARAM_SUPPORT_DAC
int RegisterSecurityOps(ParamSecurityOps *ops, int isInit)
{
    return RegisterSecurityDacOps(ops, isInit);
}
X
add ut  
xionglei6 已提交
286
#endif