/setroubleshoot-3.1.12/src/sesearch/sesearch.c

# · C · 424 lines · 340 code · 48 blank · 36 comment · 78 complexity · fc0ecc335aca4e0d611ef78046e70b21 MD5 · raw file

  1. /**
  2. * @file
  3. * Command line tool to search TE rules.
  4. *
  5. * @author Frank Mayer mayerf@tresys.com
  6. * @author Jeremy A. Mowery jmowery@tresys.com
  7. * @author Paul Rosenfeld prosenfeld@tresys.com
  8. * @author Thomas Liu <tliu@redhat.com>
  9. *
  10. * Copyright (C) 2003-2008 Tresys Technology, LLC
  11. *
  12. * This program is free software; you can redistribute it and/or modify
  13. * it under the terms of the GNU General Public License as published by
  14. * the Free Software Foundation; either version 2 of the License, or
  15. * (at your option) any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program; if not, write to the Free Software
  24. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  25. */
  26. /**
  27. * This is a modified version of sesearch to be used as part of a library for
  28. * Python bindings.
  29. */
  30. #include "Python.h"
  31. /* libapol */
  32. #include <apol/policy.h>
  33. #include <apol/policy-query.h>
  34. #include <apol/render.h>
  35. #include <apol/util.h>
  36. #include <apol/vector.h>
  37. /* libqpol*/
  38. #include <qpol/policy.h>
  39. #include <qpol/policy_extend.h>
  40. #include <qpol/syn_rule_query.h>
  41. #include <qpol/util.h>
  42. /* other */
  43. #include <errno.h>
  44. #include <stdlib.h>
  45. #include <stdio.h>
  46. #include <assert.h>
  47. #include <getopt.h>
  48. #include <string.h>
  49. #include <stdbool.h>
  50. #define COPYRIGHT_INFO "Copyright (C) 2003-2007 Tresys Technology, LLC"
  51. static char *policy_file = NULL;
  52. enum opt_values
  53. {
  54. RULE_NEVERALLOW = 256, RULE_AUDIT, RULE_AUDITALLOW, RULE_DONTAUDIT,
  55. RULE_ROLE_ALLOW, RULE_ROLE_TRANS, RULE_RANGE_TRANS, RULE_ALL,
  56. EXPR_ROLE_SOURCE, EXPR_ROLE_TARGET
  57. };
  58. ;
  59. typedef struct options
  60. {
  61. char *src_name;
  62. char *tgt_name;
  63. char *src_role_name;
  64. char *tgt_role_name;
  65. char *class_name;
  66. char *permlist;
  67. char *bool_name;
  68. apol_vector_t *class_vector;
  69. bool all;
  70. bool lineno;
  71. bool semantic;
  72. bool indirect;
  73. bool allow;
  74. bool nallow;
  75. bool auditallow;
  76. bool dontaudit;
  77. bool type;
  78. bool rtrans;
  79. bool role_allow;
  80. bool role_trans;
  81. bool useregex;
  82. bool show_cond;
  83. apol_vector_t *perm_vector;
  84. } options_t;
  85. static int perform_av_query(const apol_policy_t * policy, const options_t * opt, apol_vector_t ** v)
  86. {
  87. apol_avrule_query_t *avq = NULL;
  88. unsigned int rules = 0;
  89. int error = 0;
  90. char *tmp = NULL, *tok = NULL, *s = NULL;
  91. if (!policy || !opt || !v) {
  92. ERR(policy, "%s", strerror(EINVAL));
  93. errno = EINVAL;
  94. return -1;
  95. }
  96. if (!opt->all && !opt->allow && !opt->nallow && !opt->auditallow && !opt->dontaudit) {
  97. *v = NULL;
  98. return 0; /* no search to do */
  99. }
  100. avq = apol_avrule_query_create();
  101. if (!avq) {
  102. ERR(policy, "%s", strerror(ENOMEM));
  103. errno = ENOMEM;
  104. return -1;
  105. }
  106. if (opt->allow || opt->all)
  107. rules |= QPOL_RULE_ALLOW;
  108. if ((opt->nallow || opt->all) && qpol_policy_has_capability(apol_policy_get_qpol(policy), QPOL_CAP_NEVERALLOW))
  109. rules |= QPOL_RULE_NEVERALLOW;
  110. if (opt->auditallow || opt->all)
  111. rules |= QPOL_RULE_AUDITALLOW;
  112. if (opt->dontaudit || opt->all)
  113. rules |= QPOL_RULE_DONTAUDIT;
  114. apol_avrule_query_set_rules(policy, avq, rules);
  115. apol_avrule_query_set_regex(policy, avq, opt->useregex);
  116. if (opt->src_name)
  117. apol_avrule_query_set_source(policy, avq, opt->src_name, opt->indirect);
  118. if (opt->tgt_name)
  119. apol_avrule_query_set_target(policy, avq, opt->tgt_name, opt->indirect);
  120. if (opt->bool_name)
  121. apol_avrule_query_set_bool(policy, avq, opt->bool_name);
  122. if (opt->class_name) {
  123. if (opt->class_vector == NULL) {
  124. if (apol_avrule_query_append_class(policy, avq, opt->class_name)) {
  125. error = errno;
  126. goto err;
  127. }
  128. } else {
  129. size_t i;
  130. for (i = 0; i < apol_vector_get_size(opt->class_vector); ++i) {
  131. char *class_name;
  132. class_name = apol_vector_get_element(opt->class_vector, i);
  133. if (!class_name)
  134. continue;
  135. if (apol_avrule_query_append_class(policy, avq, class_name)) {
  136. error = errno;
  137. goto err;
  138. }
  139. }
  140. }
  141. }
  142. if (opt->permlist) {
  143. tmp = strdup(opt->permlist);
  144. for (tok = strtok(tmp, ","); tok; tok = strtok(NULL, ",")) {
  145. if (apol_avrule_query_append_perm(policy, avq, tok)) {
  146. error = errno;
  147. goto err;
  148. }
  149. if ((s = strdup(tok)) == NULL || apol_vector_append(opt->perm_vector, s) < 0) {
  150. error = errno;
  151. goto err;
  152. }
  153. s = NULL;
  154. }
  155. free(tmp);
  156. }
  157. if (!(opt->semantic) && qpol_policy_has_capability(apol_policy_get_qpol(policy), QPOL_CAP_SYN_RULES)) {
  158. if (apol_syn_avrule_get_by_query(policy, avq, v)) {
  159. error = errno;
  160. goto err;
  161. }
  162. } else {
  163. if (apol_avrule_get_by_query(policy, avq, v)) {
  164. error = errno;
  165. goto err;
  166. }
  167. }
  168. apol_avrule_query_destroy(&avq);
  169. return 0;
  170. err:
  171. apol_vector_destroy(v);
  172. apol_avrule_query_destroy(&avq);
  173. free(tmp);
  174. free(s);
  175. ERR(policy, "%s", strerror(error));
  176. errno = error;
  177. return -1;
  178. }
  179. static PyObject* print_av_results(const apol_policy_t * policy, const options_t * opt, const apol_vector_t * v)
  180. {
  181. PyObject *list = NULL;
  182. qpol_policy_t *q = apol_policy_get_qpol(policy);
  183. size_t i, num_rules = 0;
  184. const qpol_avrule_t *rule = NULL;
  185. char *tmp = NULL, *rule_str = NULL, *expr = NULL;
  186. char enable_char = ' ', branch_char = ' ';
  187. qpol_iterator_t *iter = NULL;
  188. uint32_t enabled = 0;
  189. if (!policy || !v)
  190. return 0;
  191. if (!(num_rules = apol_vector_get_size(v)))
  192. return 0;
  193. list = PyList_New(0);
  194. for (i = 0; i < num_rules; i++) {
  195. enable_char = branch_char = ' ';
  196. if (!(rule = apol_vector_get_element(v, i)))
  197. goto cleanup;
  198. if (qpol_avrule_get_is_enabled(q, rule, &enabled))
  199. goto cleanup;
  200. if (!enabled)
  201. continue;
  202. const qpol_type_t *type;
  203. const char *tmp_name;
  204. uint32_t rule_type = 0;
  205. const qpol_class_t *obj_class = NULL;
  206. PyObject *dict = PyDict_New();
  207. qpol_avrule_get_rule_type(q, rule, &rule_type);
  208. tmp_name = apol_rule_type_to_str(rule_type);
  209. PyDict_SetItemString(dict, "type", PyString_FromString(tmp_name));
  210. // source
  211. qpol_avrule_get_source_type(q, rule, &type);
  212. qpol_type_get_name(q, type, &tmp_name);
  213. PyDict_SetItemString(dict, "scontext", PyString_FromString(tmp_name));
  214. qpol_avrule_get_target_type(q, rule, &type);
  215. qpol_type_get_name(q, type, &tmp_name);
  216. PyDict_SetItemString(dict, "tcontext", PyString_FromString(tmp_name));
  217. qpol_avrule_get_object_class(q, rule, &obj_class);
  218. qpol_type_get_name(q, type, &tmp_name);
  219. PyDict_SetItemString(dict, "class", PyString_FromString(tmp_name));
  220. qpol_avrule_get_perm_iter(q, rule, &iter);
  221. PyObject *permlist = PyList_New(0);
  222. for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
  223. const char *perm_name = NULL;
  224. qpol_iterator_get_item(iter, (void **)&perm_name);
  225. PyList_Append(permlist, PyString_FromString(perm_name));
  226. }
  227. PyDict_SetItemString(dict, "permlist", permlist);
  228. PyList_Append(list, dict);
  229. free(rule_str);
  230. rule_str = NULL;
  231. free(expr);
  232. expr = NULL;
  233. }
  234. cleanup:
  235. free(tmp);
  236. free(rule_str);
  237. free(expr);
  238. return list;
  239. }
  240. PyObject* sesearch(bool allow,
  241. bool neverallow,
  242. bool auditallow,
  243. bool dontaudit,
  244. const char *src_name,
  245. const char *tgt_name,
  246. const char *class_name,
  247. const char *permlist
  248. )
  249. {
  250. options_t cmd_opts;
  251. int rt = -1;
  252. apol_policy_t *policy = NULL;
  253. apol_vector_t *v = NULL;
  254. apol_policy_path_t *pol_path = NULL;
  255. apol_vector_t *mod_paths = NULL;
  256. apol_policy_path_type_e path_type = APOL_POLICY_PATH_TYPE_MONOLITHIC;
  257. memset(&cmd_opts, 0, sizeof(cmd_opts));
  258. cmd_opts.indirect = true;
  259. cmd_opts.allow = allow;
  260. cmd_opts.nallow = neverallow;
  261. cmd_opts.auditallow = auditallow;
  262. cmd_opts.dontaudit = dontaudit;
  263. if (src_name)
  264. cmd_opts.src_name = strdup(src_name);
  265. if (tgt_name)
  266. cmd_opts.tgt_name = strdup(tgt_name);
  267. if (class_name)
  268. cmd_opts.class_name = strdup(class_name);
  269. if (permlist){
  270. cmd_opts.perm_vector = apol_vector_create(free);
  271. cmd_opts.permlist = strdup(permlist);
  272. }
  273. int pol_opt = 0;
  274. if (!(cmd_opts.nallow || cmd_opts.all))
  275. pol_opt |= QPOL_POLICY_OPTION_NO_NEVERALLOWS;
  276. rt = qpol_default_policy_find(&policy_file);
  277. if (rt < 0) {
  278. fprintf(stderr, "Default policy search failed: %s\n", strerror(errno));
  279. exit(1);
  280. } else if (rt != 0) {
  281. fprintf(stderr, "No default policy found.\n");
  282. exit(1);
  283. }
  284. pol_opt |= QPOL_POLICY_OPTION_MATCH_SYSTEM;
  285. if (apol_file_is_policy_path_list(policy_file) > 0) {
  286. pol_path = apol_policy_path_create_from_file(policy_file);
  287. if (!pol_path) {
  288. ERR(policy, "%s", "invalid policy list");
  289. free(policy_file);
  290. exit(1);
  291. }
  292. }
  293. if (!pol_path)
  294. pol_path = apol_policy_path_create(path_type, policy_file, mod_paths);
  295. if (!pol_path) {
  296. ERR(policy, "%s", strerror(ENOMEM));
  297. free(policy_file);
  298. apol_vector_destroy(&mod_paths);
  299. exit(1);
  300. }
  301. free(policy_file);
  302. apol_vector_destroy(&mod_paths);
  303. policy = apol_policy_create_from_policy_path(pol_path, pol_opt, NULL, NULL);
  304. if (!policy) {
  305. ERR(policy, "%s", strerror(errno));
  306. apol_policy_path_destroy(&pol_path);
  307. exit(1);
  308. }
  309. /* handle regex for class name */
  310. if (cmd_opts.useregex && cmd_opts.class_name != NULL) {
  311. cmd_opts.class_vector = apol_vector_create(NULL);
  312. apol_vector_t *qpol_matching_classes = NULL;
  313. apol_class_query_t *regex_match_query = apol_class_query_create();
  314. apol_class_query_set_regex(policy, regex_match_query, 1);
  315. apol_class_query_set_class(policy, regex_match_query, cmd_opts.class_name);
  316. if (apol_class_get_by_query(policy, regex_match_query, &qpol_matching_classes)) {
  317. apol_class_query_destroy(&regex_match_query);
  318. goto cleanup;
  319. }
  320. const qpol_class_t *class = NULL;
  321. size_t i;
  322. for (i = 0; i < apol_vector_get_size(qpol_matching_classes); ++i) {
  323. const char *class_name;
  324. class = apol_vector_get_element(qpol_matching_classes, i);
  325. if (!class)
  326. break;
  327. qpol_class_get_name(apol_policy_get_qpol(policy), class, &class_name);
  328. apol_vector_append(cmd_opts.class_vector, (void *)class_name);
  329. }
  330. if (!apol_vector_get_size(qpol_matching_classes)) {
  331. apol_vector_destroy(&qpol_matching_classes);
  332. apol_class_query_destroy(&regex_match_query);
  333. ERR(policy, "No classes match expression %s", cmd_opts.class_name);
  334. goto cleanup;
  335. }
  336. apol_vector_destroy(&qpol_matching_classes);
  337. apol_class_query_destroy(&regex_match_query);
  338. }
  339. if (!cmd_opts.semantic && qpol_policy_has_capability(apol_policy_get_qpol(policy), QPOL_CAP_SYN_RULES)) {
  340. if (qpol_policy_build_syn_rule_table(apol_policy_get_qpol(policy))) {
  341. apol_policy_destroy(&policy);
  342. exit(1);
  343. }
  344. }
  345. /* if syntactic rules are not available always do semantic search */
  346. if (!qpol_policy_has_capability(apol_policy_get_qpol(policy), QPOL_CAP_SYN_RULES)) {
  347. cmd_opts.semantic = 1;
  348. }
  349. /* supress line numbers if doing semantic search or not available */
  350. if (cmd_opts.semantic || !qpol_policy_has_capability(apol_policy_get_qpol(policy), QPOL_CAP_LINE_NUMBERS)) {
  351. cmd_opts.lineno = 0;
  352. }
  353. PyObject *output = NULL;
  354. if (perform_av_query(policy, &cmd_opts, &v)) {
  355. rt = 1;
  356. goto cleanup;
  357. }
  358. if (v) {
  359. output = print_av_results(policy, &cmd_opts, v);
  360. }
  361. apol_vector_destroy(&v);
  362. rt = 0;
  363. cleanup:
  364. apol_policy_destroy(&policy);
  365. apol_policy_path_destroy(&pol_path);
  366. free(cmd_opts.src_name);
  367. free(cmd_opts.tgt_name);
  368. free(cmd_opts.class_name);
  369. free(cmd_opts.permlist);
  370. free(cmd_opts.bool_name);
  371. free(cmd_opts.src_role_name);
  372. free(cmd_opts.tgt_role_name);
  373. apol_vector_destroy(&cmd_opts.perm_vector);
  374. apol_vector_destroy(&cmd_opts.class_vector);
  375. return output;
  376. }