summaryrefslogtreecommitdiffstats
path: root/sechecker/sechecker_cli.c
diff options
context:
space:
mode:
Diffstat (limited to 'sechecker/sechecker_cli.c')
-rw-r--r--sechecker/sechecker_cli.c361
1 files changed, 361 insertions, 0 deletions
diff --git a/sechecker/sechecker_cli.c b/sechecker/sechecker_cli.c
new file mode 100644
index 0000000..9fbbd96
--- /dev/null
+++ b/sechecker/sechecker_cli.c
@@ -0,0 +1,361 @@
+/**
+ * @file
+ * Main function and command line parser for the sechecker program.
+ *
+ * @author Jeremy A. Mowery jmowery@tresys.com
+ * @author Jason Tang jtang@tresys.com
+ *
+ * Copyright (C) 2005-2007 Tresys Technology, LLC
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <config.h>
+
+#include "sechecker.h"
+#include "register_list.h"
+#include <apol/policy.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <getopt.h>
+#include <errno.h>
+
+#define COPYRIGHT_INFO "Copyright (C) 2005-2007 Tresys Technology, LLC"
+
+extern sechk_module_name_reg_t sechk_register_list[];
+
+enum opt_values
+{
+ OPT_FCFILE = 256, OPT_MIN_SEV
+};
+
+/* command line options struct */
+static struct option const longopts[] = {
+ {"list", no_argument, NULL, 'l'},
+ {"help", optional_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'V'},
+ {"quiet", no_argument, NULL, 'q'},
+ {"short", no_argument, NULL, 's'},
+ {"verbose", no_argument, NULL, 'v'},
+ {"profile", required_argument, NULL, 'p'},
+ {"fcfile", required_argument, NULL, OPT_FCFILE},
+ {"module", required_argument, NULL, 'm'},
+ {"min-sev", required_argument, NULL, OPT_MIN_SEV},
+ {NULL, 0, NULL, 0}
+};
+
+/* display usage help */
+void usage(const char *arg0, bool brief)
+{
+ printf("Usage: sechecker [OPTIONS] -p profile [POLICY ...]\n");
+ printf(" sechecker [OPTIONS] -m module [POLICY ...]\n");
+ printf(" sechecker [OPTIONS] -p profile -m module [POLICY ...]\n");
+ printf("\n");
+ if (brief) {
+ printf("\tTry %s --help for more help.\n\n", arg0);
+ } else {
+ printf("Perform modular checks on a SELinux policy.\n");
+ printf("\n");
+ printf(" -p PROF, --profile=PROF name or path of profile to load\n");
+ printf(" if used without -m, run all modules in profile\n");
+ printf(" -m MODULE, --module=MODULE MODULE to run\n");
+ printf(" --fcfile=FILE file_contexts file to load\n");
+ printf("\n");
+ printf(" -q, --quiet suppress output\n");
+ printf(" -s, --short print short output\n");
+ printf(" -v, --verbose print verbose output\n");
+ printf(" --min-sev={low|med|high} set the minimum severity to report\n");
+ printf("\n");
+ printf(" -l, --list print a list of profiles and modules and exit\n");
+ printf(" -h[MODULE], --help[=MODULE] print this help text or help for MODULE\n");
+ printf(" -V, --version print version information and exit\n");
+ printf("\n");
+ }
+}
+
+/* print list of modules and installed profiles */
+int sechk_print_list(sechk_lib_t * lib)
+{
+ const sechk_profile_name_reg_t *profiles;
+ size_t num_profiles, i;
+ sechk_module_t *mod = NULL;
+
+ printf("\nProfiles:\n");
+ profiles = sechk_register_list_get_profiles();
+ num_profiles = sechk_register_list_get_num_profiles();
+ for (i = 0; i < num_profiles; i++) {
+ printf("%20s\t%s\n", profiles[i].name, profiles[i].desc);
+ }
+ if (num_profiles == 0)
+ printf("<none>\n");
+
+ printf("Modules:\n");
+ for (i = 0; i < apol_vector_get_size(lib->modules); i++) {
+ mod = apol_vector_get_element(lib->modules, i);
+ printf("%20s\t%s\n", mod->name, mod->brief_description);
+ }
+ if (apol_vector_get_size(lib->modules) == 0)
+ printf("<none>\n");
+ printf("\n");
+ return 0;
+}
+
+/* main application */
+int main(int argc, char **argv)
+{
+ int optc = 0, retv = 0;
+ size_t i;
+ char *fcpath = NULL;
+ char *modname = NULL;
+ char *prof_name = NULL;
+ char *base_path = NULL;
+ apol_policy_path_t *pol_path = NULL;
+ apol_policy_path_type_e path_type = APOL_POLICY_PATH_TYPE_MONOLITHIC;
+ char *minsev = NULL;
+ unsigned char output_override = 0;
+ sechk_lib_t *lib;
+ sechk_module_t *mod = NULL;
+ bool list_stop = false;
+ bool module_help = false;
+ apol_vector_t *policy_mods = NULL;
+
+ while ((optc = getopt_long(argc, argv, "p:m:qsvlh::V", longopts, NULL)) != -1) {
+ switch (optc) {
+ case 'p':
+ prof_name = strdup(optarg);
+ break;
+ case 'm':
+ if (minsev) {
+ fprintf(stderr, "Error: --min-sev does not work with --module.\n");
+ exit(1);
+ }
+ modname = strdup(optarg);
+ break;
+ case OPT_FCFILE:
+ fcpath = strdup(optarg);
+ break;
+ case 'q':
+ if (output_override) {
+ fprintf(stderr, "Error: multiple output formats specified.\n");
+ usage(argv[0], 1);
+ exit(1);
+ } else {
+ output_override = SECHK_OUT_QUIET;
+ }
+ break;
+ case 's':
+ if (output_override) {
+ fprintf(stderr, "Error: multiple output formats specified.\n");
+ usage(argv[0], 1);
+ exit(1);
+ } else {
+ output_override = SECHK_OUT_SHORT;
+ }
+ break;
+ case 'v':
+ if (output_override) {
+ fprintf(stderr, "Error: multiple output formats specified.\n");
+ usage(argv[0], 1);
+ exit(1);
+ } else {
+ output_override = SECHK_OUT_VERBOSE;
+ }
+ break;
+ case OPT_MIN_SEV:
+ if (modname) {
+ fprintf(stderr, "Error: --min-sev does not work with --module.\n");
+ exit(1);
+ }
+ minsev = strdup(optarg);
+ break;
+ case 'l':
+ list_stop = true;
+ break;
+ case 'h':
+ if (optarg != NULL) {
+ modname = strdup(optarg);
+ module_help = true;
+ break;
+ }
+ usage(argv[0], 0);
+ exit(0);
+ case 'V':
+ printf("sechecker %s\n%s\n", VERSION, COPYRIGHT_INFO);
+ exit(0);
+ default:
+ usage(argv[0], 1);
+ exit(1);
+ }
+ }
+
+ if (!prof_name && !modname && !list_stop) {
+ fprintf(stderr, "Error: no module or profile specified\n\n");
+ usage(argv[0], 1);
+ exit(1);
+ }
+
+ /* create the module library */
+ lib = sechk_lib_new();
+ if (!lib)
+ goto exit_err;
+
+ /* print the list */
+ if (list_stop == true) {
+ sechk_print_list(lib);
+ goto exit;
+ }
+
+ /* print help for a module */
+ if (module_help == true) {
+ retv = sechk_lib_get_module_idx(modname, lib);
+ if (retv < 0) {
+ fprintf(stderr, "Error: Module %s does not exist.\n", modname);
+ goto exit_err;
+ }
+ mod = apol_vector_get_element(lib->modules, retv);
+ printf("\nModule name: %s\n%s\n%s\n", mod->name, mod->detailed_description, mod->opt_description);
+ goto exit;
+ }
+
+ /* load profile if specified */
+ if (prof_name) {
+ retv = sechk_lib_load_profile(prof_name, lib);
+ if (retv) {
+ retv = errno;
+ if (!output_override || !(output_override & ~(SECHK_OUT_QUIET))) {
+ fprintf(stderr, "Error: could not load profile %s\n", prof_name);
+ errno = retv;
+ perror("Error");
+ }
+ goto exit_err;
+ }
+ }
+
+ /* initialize the policy */
+ if (argc - optind) {
+ base_path = argv[optind];
+ optind++;
+ if (argc - optind) {
+ if (!(policy_mods = apol_vector_create(NULL)))
+ goto exit_err;
+ while (argc - optind) {
+ if (apol_vector_append(policy_mods, argv[optind++]))
+ goto exit_err;
+ path_type = APOL_POLICY_PATH_TYPE_MODULAR;
+ }
+ } else if (apol_file_is_policy_path_list(base_path) > 0) {
+ pol_path = apol_policy_path_create_from_file(base_path);
+ if (!pol_path) {
+ fprintf(stderr, "Error: invalid policy list\n");
+ goto exit_err;
+ }
+ }
+ if (!pol_path)
+ pol_path = apol_policy_path_create(path_type, base_path, policy_mods);
+ if (!pol_path)
+ goto exit_err;
+ if (sechk_lib_load_policy(pol_path, lib)) {
+ pol_path = NULL;
+ goto exit_err;
+ }
+ } else {
+ if (sechk_lib_load_policy(NULL, lib))
+ goto exit_err;
+ }
+ /* library now owns path object */
+ pol_path = NULL;
+
+ /* set the minimum severity */
+ if (minsev && sechk_lib_set_minsev(minsev, lib) < 0)
+ goto exit_err;
+
+ /* initialize the file contexts */
+ if (sechk_lib_load_fc(fcpath, lib) < 0)
+ goto exit_err;
+ /* initialize the output format */
+ if (output_override) {
+ if (sechk_lib_set_outputformat(output_override, lib) < 0)
+ goto exit_err;
+ }
+
+ /* if running only one module, deselect all others */
+ if (modname) {
+ retv = sechk_lib_get_module_idx(modname, lib);
+ if (retv == -1 || (size_t) retv >= apol_vector_get_size(lib->modules)) {
+ fprintf(stderr, "Error: module %s not found\n", modname);
+ goto exit_err;
+ }
+ for (i = 0; i < apol_vector_get_size(lib->modules); i++) {
+ mod = apol_vector_get_element(lib->modules, i);
+ mod->selected = false;
+ }
+ mod = apol_vector_get_element(lib->modules, retv);
+ mod->selected = true;
+ }
+
+ /* process dependencies for selected modules */
+ if (sechk_lib_check_module_dependencies(lib) < 0)
+ goto exit_err;
+
+ /* process requirements for selected modules */
+ if (sechk_lib_check_module_requirements(lib) < 0)
+ goto exit_err;
+
+ /* initialize the modules */
+ if (sechk_lib_init_modules(lib))
+ goto exit_err;
+
+ /* run the modules */
+ if (sechk_lib_run_modules(lib))
+ goto exit_err;
+
+ /* if running only one module, deselect all others again before printing */
+ if (modname) {
+ retv = sechk_lib_get_module_idx(modname, lib);
+ if (retv == -1 || (size_t) retv >= apol_vector_get_size(lib->modules)) {
+ fprintf(stderr, "Error: module %s not found\n", modname);
+ goto exit_err;
+ }
+ for (i = 0; i < apol_vector_get_size(lib->modules); i++) {
+ mod = apol_vector_get_element(lib->modules, i);
+ mod->selected = false;
+ }
+ mod = apol_vector_get_element(lib->modules, retv);
+ mod->selected = true;
+ }
+
+ /* print the report */
+ if (sechk_lib_print_modules_report(lib))
+ goto exit_err;
+
+ exit:
+ free(fcpath);
+ apol_vector_destroy(&policy_mods);
+ free(minsev);
+ free(prof_name);
+ free(modname);
+ sechk_lib_destroy(&lib);
+ return 0;
+
+ exit_err:
+ free(fcpath);
+ apol_vector_destroy(&policy_mods);
+ free(minsev);
+ free(prof_name);
+ free(modname);
+ apol_policy_path_destroy(&pol_path);
+ sechk_lib_destroy(&lib);
+ return 1;
+}