PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/setools-3.3.7/python/setools/sesearch.c

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