• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "sehap_contexts_trie.h"
16 #include <deque>
17 
18 #include "src/callbacks.h"
19 #include "selinux/selinux.h"
20 #include "selinux_log.h"
21 #include <iostream>
22 
SplitString(const std::string & paraName)23 std::vector<std::string> SehapContextsTrie::SplitString(const std::string& paraName)
24 {
25     std::vector<std::string> words;
26     std::string delimiter = ".";
27     size_t len = paraName.length();
28     size_t index = 0;
29     while (index < len) {
30         size_t pos;
31         if ((pos = paraName.substr(index).find(delimiter)) == std::string::npos) {
32             break;
33         }
34         std::string element = paraName.substr(index, pos);
35         if (!element.empty()) {
36             words.emplace_back(element);
37         }
38         index += pos + delimiter.length();
39     }
40     if (!paraName.substr(index).empty()) {
41         words.emplace_back(paraName.substr(index));
42     }
43     return words;
44 }
45 
FindChild(const std::string & element)46 SehapContextsTrie* SehapContextsTrie::FindChild(const std::string& element)
47 {
48     SehapContextsTrie* node = this;
49     auto iter = node->children.find(element);
50     if (iter != node->children.end()) {
51         return iter->second;
52     }
53     return nullptr;
54 }
55 
Insert(const SehapInsertParamInfo & paramInfo)56 void NodeTypeInfo::Insert(const SehapInsertParamInfo &paramInfo)
57 {
58     if (!paramInfo.extension.empty()) {
59         ExtensionInfo extInfo;
60         extInfo.domain = paramInfo.domain;
61 #ifdef MCS_ENABLE
62         extInfo.levelFrom = paramInfo.levelFrom;
63         extInfo.user = paramInfo.user;
64 #endif
65         extensionMap[paramInfo.extension] = extInfo;
66     } else {
67         this->domain = paramInfo.domain;
68         this->type = paramInfo.type;
69 #ifdef MCS_ENABLE
70         this->levelFrom = paramInfo.levelFrom;
71         this->user = paramInfo.user;
72 #endif
73     }
74     this->isEnd = true;
75 }
76 
Insert(const std::string & paraName,const SehapInsertParamInfo & paramInfo)77 bool SehapContextsTrie::Insert(const std::string& paraName, const SehapInsertParamInfo &paramInfo)
78 {
79     SehapContextsTrie* node = this;
80     std::vector<std::string> words = SplitString(paraName);
81     for (const std::string& word : words) {
82         if (word == "*") {
83             break;
84         }
85         if (node->children[word] == nullptr) {
86             node->children[word] = new (std::nothrow) SehapContextsTrie();
87             if (node->children[word] == nullptr) {
88                 selinux_log(SELINUX_ERROR, "new child sehapcontextstrie failed!");
89                 return false;
90             }
91         }
92         node = node->children[word];
93     }
94 
95     if ((paraName.back() == '.') || (paraName.back() == '*')) {
96         node->prefixInfo.Insert(paramInfo);
97     } else {
98         node->matchedInfo.Insert(paramInfo);
99     }
100 
101     return true;
102 }
103 
Search(bool isDomain,const std::string & extension) const104 SehapContextInfo NodeTypeInfo::Search(bool isDomain, const std::string& extension) const
105 {
106     SehapContextInfo contextInfo;
107     if (isDomain && !extension.empty()) {
108         auto it = extensionMap.find(extension);
109         if (it != extensionMap.end()) {
110             contextInfo.context = it->second.domain;
111             contextInfo.isDomain = isDomain;
112 #ifdef MCS_ENABLE
113             contextInfo.levelFrom = it->second.levelFrom;
114             contextInfo.user = it->second.user;
115 #endif
116             return contextInfo;
117         }
118     }
119     contextInfo.context = isDomain ? domain : type;
120     contextInfo.isDomain = isDomain;
121 #ifdef MCS_ENABLE
122     contextInfo.levelFrom = levelFrom;
123     contextInfo.user = user;
124 #endif
125     return contextInfo;
126 }
127 
Search(const std::string & paraName,bool isDomain,const std::string & extension)128 SehapContextInfo SehapContextsTrie::Search(const std::string& paraName, bool isDomain, const std::string& extension)
129 {
130     std::vector<std::string> words = SplitString(paraName);
131     SehapContextInfo contextInfo;
132     SehapContextsTrie* root = this;
133     for (size_t i = 0; i < words.size(); i++) {
134         const std::string& word = words[i];
135         auto child = root->FindChild(word);
136         if (child == nullptr) {
137             break;
138         }
139         root = child;
140         if ((root->prefixInfo.isEnd) && (i != words.size() - 1)) {
141             contextInfo = root->prefixInfo.Search(isDomain, extension);
142         }
143         if ((root->matchedInfo.isEnd) && (i == words.size() - 1)) {
144             contextInfo = root->matchedInfo.Search(isDomain, extension);
145         }
146     }
147     return contextInfo;
148 }
149 
Clear()150 void SehapContextsTrie::Clear()
151 {
152     SehapContextsTrie* root = this;
153     std::deque<SehapContextsTrie*> nodeDeque;
154     for (auto child : root->children) {
155         nodeDeque.emplace_back(child.second);
156     }
157     while (!nodeDeque.empty()) {
158         root = nodeDeque.front();
159         nodeDeque.pop_front();
160         if (root != nullptr) {
161             for (auto child : root->children) {
162                 nodeDeque.emplace_back(child.second);
163             }
164             delete root;
165         }
166     }
167 }