1 /*
2 * Copyright (c) 2022 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
16 #include <cstdlib>
17 #include <getopt.h>
18 #include <iosfwd>
19 #include <iostream>
20 #include <istream>
21 #include <memory>
22 #include <ostream>
23 #include <string>
24 #include <unistd.h>
25
26 #include "selinux/avc.h"
27 #include "hdf_service_checker.h"
28 #include "selinux_error.h"
29 #include "service_checker.h"
30
31 using namespace Selinux;
32
33 static std::unique_ptr<ServiceChecker> g_service = nullptr;
34
35 struct TestInput {
36 char cmd = '\0';
37 bool isHdf = false;
38 std::string serviceName;
39 };
40
PrintUsage()41 static void PrintUsage()
42 {
43 std::cout << "Options:" << std::endl;
44 std::cout << " -h (--help) show the help information. [eg: service_check -h]" << std::endl;
45 std::cout << "***********************optinal*************************************************" << std::endl;
46 std::cout << " -d (--isHdf) service or hdf_service. [eg: service_check -d]" << std::endl;
47 std::cout << " -n (--serviceName) serviceName. [eg: service_check -n service_name]"
48 << std::endl;
49 std::cout << "***********************requered: 1 in 4****************************************" << std::endl;
50 std::cout << " -a (--add) add service check. [eg: service_check -a]" << std::endl;
51 std::cout << " -g (--get) get service check. [eg: service_check -g]" << std::endl;
52 std::cout << " -r (--get_remote) get remote service check. [eg: service_check -r]" << std::endl;
53 std::cout << " -l (--list) list service check. [eg: service_check -l]" << std::endl;
54 std::cout << "" << std::endl;
55 std::cout << "Usage:" << std::endl;
56 std::cout << ">>>>>>> choice 1: continuous input parameters" << std::endl;
57 std::cout << "step 1:" << std::endl;
58 std::cout << "service_check (-d) -a|-g|-r|-l" << std::endl;
59 std::cout << "step 2:" << std::endl;
60 std::cout << "input service name and press 'enter' to continue, or ctrl+C to end process" << std::endl;
61 std::cout << ">>>>>>> choice 2: single input parameter" << std::endl;
62 std::cout << "service_check (-d) -a|-g|-r|-l -n service_name" << std::endl;
63 std::cout << "" << std::endl;
64 }
65
SetOptions(int argc,char * argv[],const option * options,TestInput & input)66 static void SetOptions(int argc, char *argv[], const option *options, TestInput &input)
67 {
68 int index = 0;
69 const char *optStr = "dhlagrn:";
70 int para = 0;
71 while ((para = getopt_long(argc, argv, optStr, options, &index)) != -1) {
72 switch (para) {
73 case 'h': {
74 PrintUsage();
75 exit(0);
76 }
77 case 'n': {
78 input.serviceName = optarg;
79 break;
80 }
81 case 'd': {
82 input.isHdf = true;
83 break;
84 }
85 case 'a': {
86 input.cmd = 'a';
87 break;
88 }
89 case 'g': {
90 input.cmd = 'g';
91 break;
92 }
93 case 'r': {
94 input.cmd = 'r';
95 break;
96 }
97 case 'l': {
98 input.cmd = 'l';
99 break;
100 }
101 default:
102 std::cout << "Try 'service_check -h' for more information." << std::endl;
103 exit(-1);
104 }
105 }
106 }
107
GetSidForCurrentProcess(std::string & sid)108 static int GetSidForCurrentProcess(std::string &sid)
109 {
110 char *con = nullptr;
111 if (getcon(&con) < 0) {
112 return -1;
113 }
114 sid = con;
115 freecon(con);
116 return 0;
117 }
118
TestAddService(bool isHdf,const std::string & serviceName)119 static void TestAddService(bool isHdf, const std::string &serviceName)
120 {
121 std::string sid;
122 if (GetSidForCurrentProcess(sid) < 0) {
123 return;
124 }
125 if (!serviceName.empty()) {
126 std::cout << GetErrStr(isHdf ? HdfAddServiceCheck(sid.c_str(), serviceName.c_str())
127 : g_service->AddServiceCheck(sid, serviceName))
128 << std::endl;
129 exit(0);
130 }
131 std::string serName;
132 while (std::cin >> serName) {
133 std::cout << GetErrStr(isHdf ? HdfAddServiceCheck(sid.c_str(), serName.c_str())
134 : g_service->AddServiceCheck(sid, serName))
135 << std::endl;
136 }
137 }
138
TestGetService(bool isHdf,const std::string & serviceName)139 static void TestGetService(bool isHdf, const std::string &serviceName)
140 {
141 std::string sid;
142 if (GetSidForCurrentProcess(sid) < 0) {
143 return;
144 }
145 if (!serviceName.empty()) {
146 std::cout << GetErrStr(isHdf ? HdfGetServiceCheck(sid.c_str(), serviceName.c_str())
147 : g_service->GetServiceCheck(sid, serviceName))
148 << std::endl;
149 exit(0);
150 }
151 std::string serName;
152 while (std::cin >> serName) {
153 std::cout << GetErrStr(isHdf ? HdfGetServiceCheck(sid.c_str(), serName.c_str())
154 : g_service->GetServiceCheck(sid, serName))
155 << std::endl;
156 }
157 }
158
TestGetRemoteService(bool isHdf,const std::string & serviceName)159 static void TestGetRemoteService(bool isHdf, const std::string &serviceName)
160 {
161 std::string sid;
162 if (GetSidForCurrentProcess(sid) < 0) {
163 return;
164 }
165 if (!serviceName.empty()) {
166 std::cout << GetErrStr(isHdf ? SELINUX_PERMISSION_DENY
167 : g_service->GetRemoteServiceCheck(sid, serviceName))
168 << std::endl;
169 exit(0);
170 }
171 std::string serName;
172 while (std::cin >> serName) {
173 std::cout << GetErrStr(isHdf ? SELINUX_PERMISSION_DENY : g_service->GetRemoteServiceCheck(sid, serName))
174 << std::endl;
175 }
176 }
177
TestListService(bool isHdf)178 static void TestListService(bool isHdf)
179 {
180 std::string sid;
181 if (GetSidForCurrentProcess(sid) < 0) {
182 return;
183 }
184 std::cout << GetErrStr(isHdf ? HdfListServiceCheck(sid.c_str()) : g_service->ListServiceCheck(sid)) << std::endl;
185 }
186
Test(const TestInput & testCmd)187 static void Test(const TestInput &testCmd)
188 {
189 switch (testCmd.cmd) {
190 case 'a': {
191 TestAddService(testCmd.isHdf, testCmd.serviceName);
192 exit(0);
193 }
194 case 'g': {
195 TestGetService(testCmd.isHdf, testCmd.serviceName);
196 exit(0);
197 }
198 case 'r': {
199 TestGetRemoteService(testCmd.isHdf, testCmd.serviceName);
200 exit(0);
201 }
202 case 'l': {
203 TestListService(testCmd.isHdf);
204 exit(0);
205 }
206 default:
207 exit(-1);
208 }
209 }
210
main(int argc,char * argv[])211 int main(int argc, char *argv[])
212 {
213 struct option options[] = {
214 {"help", no_argument, nullptr, 'h'}, {"add", no_argument, nullptr, 'a'},
215 {"get", no_argument, nullptr, 'g'}, {"get_remote", no_argument, nullptr, 'r'},
216 {"isHdf", no_argument, nullptr, 'd'}, {"list", no_argument, nullptr, 'l'},
217 {"serviceName", required_argument, nullptr, 'n'}, {nullptr, no_argument, nullptr, 0},
218 };
219
220 if (argc == 1) {
221 PrintUsage();
222 exit(0);
223 }
224
225 TestInput input;
226 SetOptions(argc, argv, options, input);
227 if (!input.isHdf) {
228 g_service = std::make_unique<ServiceChecker>(false);
229 }
230 Test(input);
231
232 exit(0);
233 }
234