169570cc8Sopenharmony_ci/*
269570cc8Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
369570cc8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
469570cc8Sopenharmony_ci * you may not use this file except in compliance with the License.
569570cc8Sopenharmony_ci * You may obtain a copy of the License at
669570cc8Sopenharmony_ci *
769570cc8Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
869570cc8Sopenharmony_ci *
969570cc8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1069570cc8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1169570cc8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1269570cc8Sopenharmony_ci * See the License for the specific language governing permissions and
1369570cc8Sopenharmony_ci * limitations under the License.
1469570cc8Sopenharmony_ci */
1569570cc8Sopenharmony_ci#include "appspawn_permission.h"
1669570cc8Sopenharmony_ci#ifdef APPSPAWN_CLIENT
1769570cc8Sopenharmony_ci#include "appspawn_mount_permission.h"
1869570cc8Sopenharmony_ci#else
1969570cc8Sopenharmony_ci#include "appspawn_sandbox.h"
2069570cc8Sopenharmony_ci#endif
2169570cc8Sopenharmony_ci#include "appspawn_msg.h"
2269570cc8Sopenharmony_ci#include "appspawn_utils.h"
2369570cc8Sopenharmony_ci#include "securec.h"
2469570cc8Sopenharmony_ci
2569570cc8Sopenharmony_cistatic int PermissionNodeCompareIndex(ListNode *node, void *data)
2669570cc8Sopenharmony_ci{
2769570cc8Sopenharmony_ci    SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node);
2869570cc8Sopenharmony_ci    return permissionNode->permissionIndex - *(int32_t *)data;
2969570cc8Sopenharmony_ci}
3069570cc8Sopenharmony_ci
3169570cc8Sopenharmony_cistatic int PermissionNodeCompareName(ListNode *node, void *data)
3269570cc8Sopenharmony_ci{
3369570cc8Sopenharmony_ci    SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node);
3469570cc8Sopenharmony_ci#ifdef APPSPAWN_CLIENT
3569570cc8Sopenharmony_ci    return strcmp(permissionNode->name, (char *)data);
3669570cc8Sopenharmony_ci#else
3769570cc8Sopenharmony_ci    return strcmp(permissionNode->section.name, (char *)data);
3869570cc8Sopenharmony_ci#endif
3969570cc8Sopenharmony_ci}
4069570cc8Sopenharmony_ci
4169570cc8Sopenharmony_cistatic int PermissionNodeCompareProc(ListNode *node, ListNode *newNode)
4269570cc8Sopenharmony_ci{
4369570cc8Sopenharmony_ci    SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node);
4469570cc8Sopenharmony_ci    SandboxPermissionNode *newPermissionNode = (SandboxPermissionNode *)ListEntry(newNode, SandboxMountNode, node);
4569570cc8Sopenharmony_ci#ifdef APPSPAWN_CLIENT
4669570cc8Sopenharmony_ci    return strcmp(permissionNode->name, newPermissionNode->name);
4769570cc8Sopenharmony_ci#else
4869570cc8Sopenharmony_ci    return strcmp(permissionNode->section.name, newPermissionNode->section.name);
4969570cc8Sopenharmony_ci#endif
5069570cc8Sopenharmony_ci}
5169570cc8Sopenharmony_ci
5269570cc8Sopenharmony_ciint AddSandboxPermissionNode(const char *name, SandboxQueue *queue)
5369570cc8Sopenharmony_ci{
5469570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(name != NULL && queue != NULL, return APPSPAWN_ARG_INVALID);
5569570cc8Sopenharmony_ci    APPSPAWN_LOGV("Add permission name %{public}s ", name);
5669570cc8Sopenharmony_ci    if (GetPermissionNodeInQueue(queue, name) != NULL) {
5769570cc8Sopenharmony_ci        APPSPAWN_LOGW("Permission name %{public}s has been exist", name);
5869570cc8Sopenharmony_ci        return 0;
5969570cc8Sopenharmony_ci    }
6069570cc8Sopenharmony_ci#ifndef APPSPAWN_CLIENT
6169570cc8Sopenharmony_ci    size_t len = sizeof(SandboxPermissionNode);
6269570cc8Sopenharmony_ci    SandboxPermissionNode *node = (SandboxPermissionNode *)CreateSandboxSection(
6369570cc8Sopenharmony_ci        name, len, SANDBOX_TAG_PERMISSION);
6469570cc8Sopenharmony_ci    APPSPAWN_CHECK(node != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to create permission node");
6569570cc8Sopenharmony_ci    node->permissionIndex = 0;
6669570cc8Sopenharmony_ci    OH_ListAddWithOrder(&queue->front, &node->section.sandboxNode.node, PermissionNodeCompareProc);
6769570cc8Sopenharmony_ci#else
6869570cc8Sopenharmony_ci    size_t len = APPSPAWN_ALIGN(strlen(name) + 1) + sizeof(SandboxPermissionNode);
6969570cc8Sopenharmony_ci    SandboxPermissionNode *node = (SandboxPermissionNode *)calloc(1, len);
7069570cc8Sopenharmony_ci    APPSPAWN_CHECK(node != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to create permission node");
7169570cc8Sopenharmony_ci    OH_ListInit(&node->sandboxNode.node);
7269570cc8Sopenharmony_ci    node->permissionIndex = 0;
7369570cc8Sopenharmony_ci    int ret = strcpy_s(node->name, len, name);
7469570cc8Sopenharmony_ci    APPSPAWN_CHECK(ret == 0, free(node);
7569570cc8Sopenharmony_ci        return APPSPAWN_SYSTEM_ERROR, "Failed to copy name");
7669570cc8Sopenharmony_ci    OH_ListAddWithOrder(&queue->front, &node->sandboxNode.node, PermissionNodeCompareProc);
7769570cc8Sopenharmony_ci#endif
7869570cc8Sopenharmony_ci    return 0;
7969570cc8Sopenharmony_ci}
8069570cc8Sopenharmony_ci
8169570cc8Sopenharmony_ciint32_t DeleteSandboxPermissions(SandboxQueue *queue)
8269570cc8Sopenharmony_ci{
8369570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(queue != NULL, return APPSPAWN_ARG_INVALID);
8469570cc8Sopenharmony_ci    ListNode *node = queue->front.next;
8569570cc8Sopenharmony_ci    while (node != &queue->front) {
8669570cc8Sopenharmony_ci        SandboxMountNode *sandboxNode = (SandboxMountNode *)ListEntry(node, SandboxMountNode, node);
8769570cc8Sopenharmony_ci        OH_ListRemove(&sandboxNode->node);
8869570cc8Sopenharmony_ci        OH_ListInit(&sandboxNode->node);
8969570cc8Sopenharmony_ci#ifndef APPSPAWN_CLIENT
9069570cc8Sopenharmony_ci        DeleteSandboxSection((SandboxSection *)sandboxNode);
9169570cc8Sopenharmony_ci#else
9269570cc8Sopenharmony_ci        free(sandboxNode);
9369570cc8Sopenharmony_ci#endif
9469570cc8Sopenharmony_ci        // get first
9569570cc8Sopenharmony_ci        node = queue->front.next;
9669570cc8Sopenharmony_ci    }
9769570cc8Sopenharmony_ci    return 0;
9869570cc8Sopenharmony_ci}
9969570cc8Sopenharmony_ci
10069570cc8Sopenharmony_ciint32_t PermissionRenumber(SandboxQueue *queue)
10169570cc8Sopenharmony_ci{
10269570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(queue != NULL, return -1);
10369570cc8Sopenharmony_ci    ListNode *node = queue->front.next;
10469570cc8Sopenharmony_ci    int index = -1;
10569570cc8Sopenharmony_ci    while (node != &queue->front) {
10669570cc8Sopenharmony_ci        SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node);
10769570cc8Sopenharmony_ci        permissionNode->permissionIndex = ++index;
10869570cc8Sopenharmony_ci#ifdef APPSPAWN_CLIENT
10969570cc8Sopenharmony_ci        APPSPAWN_LOGV("Permission index %{public}d name %{public}s",
11069570cc8Sopenharmony_ci            permissionNode->permissionIndex, permissionNode->name);
11169570cc8Sopenharmony_ci#else
11269570cc8Sopenharmony_ci        APPSPAWN_LOGV("Permission index %{public}d name %{public}s",
11369570cc8Sopenharmony_ci            permissionNode->permissionIndex, permissionNode->section.name);
11469570cc8Sopenharmony_ci#endif
11569570cc8Sopenharmony_ci        node = node->next;
11669570cc8Sopenharmony_ci    }
11769570cc8Sopenharmony_ci    return index + 1;
11869570cc8Sopenharmony_ci}
11969570cc8Sopenharmony_ci
12069570cc8Sopenharmony_ciconst SandboxPermissionNode *GetPermissionNodeInQueue(SandboxQueue *queue, const char *permission)
12169570cc8Sopenharmony_ci{
12269570cc8Sopenharmony_ci    if (queue == NULL || permission == NULL) {
12369570cc8Sopenharmony_ci        return NULL;
12469570cc8Sopenharmony_ci    }
12569570cc8Sopenharmony_ci    ListNode *node = OH_ListFind(&queue->front, (void *)permission, PermissionNodeCompareName);
12669570cc8Sopenharmony_ci    if (node == NULL) {
12769570cc8Sopenharmony_ci        return NULL;
12869570cc8Sopenharmony_ci    }
12969570cc8Sopenharmony_ci    return (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node);
13069570cc8Sopenharmony_ci}
13169570cc8Sopenharmony_ci
13269570cc8Sopenharmony_ciconst SandboxPermissionNode *GetPermissionNodeInQueueByIndex(SandboxQueue *queue, int32_t index)
13369570cc8Sopenharmony_ci{
13469570cc8Sopenharmony_ci    if (queue == NULL) {
13569570cc8Sopenharmony_ci        return NULL;
13669570cc8Sopenharmony_ci    }
13769570cc8Sopenharmony_ci    ListNode *node = OH_ListFind(&queue->front, (void *)&index, PermissionNodeCompareIndex);
13869570cc8Sopenharmony_ci    if (node == NULL) {
13969570cc8Sopenharmony_ci        return NULL;
14069570cc8Sopenharmony_ci    }
14169570cc8Sopenharmony_ci    return (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node);
14269570cc8Sopenharmony_ci}
14369570cc8Sopenharmony_ci
14469570cc8Sopenharmony_ciint32_t GetPermissionIndexInQueue(SandboxQueue *queue, const char *permission)
14569570cc8Sopenharmony_ci{
14669570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(queue != NULL && permission != NULL, return INVALID_PERMISSION_INDEX);
14769570cc8Sopenharmony_ci    const SandboxPermissionNode *permissionNode = GetPermissionNodeInQueue(queue, permission);
14869570cc8Sopenharmony_ci    return permissionNode == NULL ? INVALID_PERMISSION_INDEX : permissionNode->permissionIndex;
14969570cc8Sopenharmony_ci}