1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15#include "appspawn_permission.h"
16#ifdef APPSPAWN_CLIENT
17#include "appspawn_mount_permission.h"
18#else
19#include "appspawn_sandbox.h"
20#endif
21#include "appspawn_msg.h"
22#include "appspawn_utils.h"
23#include "securec.h"
24
25static int PermissionNodeCompareIndex(ListNode *node, void *data)
26{
27    SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node);
28    return permissionNode->permissionIndex - *(int32_t *)data;
29}
30
31static int PermissionNodeCompareName(ListNode *node, void *data)
32{
33    SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node);
34#ifdef APPSPAWN_CLIENT
35    return strcmp(permissionNode->name, (char *)data);
36#else
37    return strcmp(permissionNode->section.name, (char *)data);
38#endif
39}
40
41static int PermissionNodeCompareProc(ListNode *node, ListNode *newNode)
42{
43    SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node);
44    SandboxPermissionNode *newPermissionNode = (SandboxPermissionNode *)ListEntry(newNode, SandboxMountNode, node);
45#ifdef APPSPAWN_CLIENT
46    return strcmp(permissionNode->name, newPermissionNode->name);
47#else
48    return strcmp(permissionNode->section.name, newPermissionNode->section.name);
49#endif
50}
51
52int AddSandboxPermissionNode(const char *name, SandboxQueue *queue)
53{
54    APPSPAWN_CHECK_ONLY_EXPER(name != NULL && queue != NULL, return APPSPAWN_ARG_INVALID);
55    APPSPAWN_LOGV("Add permission name %{public}s ", name);
56    if (GetPermissionNodeInQueue(queue, name) != NULL) {
57        APPSPAWN_LOGW("Permission name %{public}s has been exist", name);
58        return 0;
59    }
60#ifndef APPSPAWN_CLIENT
61    size_t len = sizeof(SandboxPermissionNode);
62    SandboxPermissionNode *node = (SandboxPermissionNode *)CreateSandboxSection(
63        name, len, SANDBOX_TAG_PERMISSION);
64    APPSPAWN_CHECK(node != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to create permission node");
65    node->permissionIndex = 0;
66    OH_ListAddWithOrder(&queue->front, &node->section.sandboxNode.node, PermissionNodeCompareProc);
67#else
68    size_t len = APPSPAWN_ALIGN(strlen(name) + 1) + sizeof(SandboxPermissionNode);
69    SandboxPermissionNode *node = (SandboxPermissionNode *)calloc(1, len);
70    APPSPAWN_CHECK(node != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to create permission node");
71    OH_ListInit(&node->sandboxNode.node);
72    node->permissionIndex = 0;
73    int ret = strcpy_s(node->name, len, name);
74    APPSPAWN_CHECK(ret == 0, free(node);
75        return APPSPAWN_SYSTEM_ERROR, "Failed to copy name");
76    OH_ListAddWithOrder(&queue->front, &node->sandboxNode.node, PermissionNodeCompareProc);
77#endif
78    return 0;
79}
80
81int32_t DeleteSandboxPermissions(SandboxQueue *queue)
82{
83    APPSPAWN_CHECK_ONLY_EXPER(queue != NULL, return APPSPAWN_ARG_INVALID);
84    ListNode *node = queue->front.next;
85    while (node != &queue->front) {
86        SandboxMountNode *sandboxNode = (SandboxMountNode *)ListEntry(node, SandboxMountNode, node);
87        OH_ListRemove(&sandboxNode->node);
88        OH_ListInit(&sandboxNode->node);
89#ifndef APPSPAWN_CLIENT
90        DeleteSandboxSection((SandboxSection *)sandboxNode);
91#else
92        free(sandboxNode);
93#endif
94        // get first
95        node = queue->front.next;
96    }
97    return 0;
98}
99
100int32_t PermissionRenumber(SandboxQueue *queue)
101{
102    APPSPAWN_CHECK_ONLY_EXPER(queue != NULL, return -1);
103    ListNode *node = queue->front.next;
104    int index = -1;
105    while (node != &queue->front) {
106        SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node);
107        permissionNode->permissionIndex = ++index;
108#ifdef APPSPAWN_CLIENT
109        APPSPAWN_LOGV("Permission index %{public}d name %{public}s",
110            permissionNode->permissionIndex, permissionNode->name);
111#else
112        APPSPAWN_LOGV("Permission index %{public}d name %{public}s",
113            permissionNode->permissionIndex, permissionNode->section.name);
114#endif
115        node = node->next;
116    }
117    return index + 1;
118}
119
120const SandboxPermissionNode *GetPermissionNodeInQueue(SandboxQueue *queue, const char *permission)
121{
122    if (queue == NULL || permission == NULL) {
123        return NULL;
124    }
125    ListNode *node = OH_ListFind(&queue->front, (void *)permission, PermissionNodeCompareName);
126    if (node == NULL) {
127        return NULL;
128    }
129    return (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node);
130}
131
132const SandboxPermissionNode *GetPermissionNodeInQueueByIndex(SandboxQueue *queue, int32_t index)
133{
134    if (queue == NULL) {
135        return NULL;
136    }
137    ListNode *node = OH_ListFind(&queue->front, (void *)&index, PermissionNodeCompareIndex);
138    if (node == NULL) {
139        return NULL;
140    }
141    return (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node);
142}
143
144int32_t GetPermissionIndexInQueue(SandboxQueue *queue, const char *permission)
145{
146    APPSPAWN_CHECK_ONLY_EXPER(queue != NULL && permission != NULL, return INVALID_PERMISSION_INDEX);
147    const SandboxPermissionNode *permissionNode = GetPermissionNodeInQueue(queue, permission);
148    return permissionNode == NULL ? INVALID_PERMISSION_INDEX : permissionNode->permissionIndex;
149}