/** * @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 #include "sechecker.h" #include "register_list.h" #include #include #include #include #include #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("\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("\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; }