diff options
Diffstat (limited to 'sechecker/sechecker_cli.c')
-rw-r--r-- | sechecker/sechecker_cli.c | 361 |
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; +} |