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