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