1 /** 2 * @file 3 * Command line tool to search TE rules. 4 * 5 * @author Frank Mayer mayerf (at) tresys.com 6 * @author Jeremy A. Mowery jmowery (at) tresys.com 7 * @author Paul Rosenfeld prosenfeld (at) tresys.com 8 * @author Thomas Liu <tliu (at) redhat.com> 9 * @author Dan Walsh <dwalsh (at) 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 /** 29 * This is a modified version of seinfo to be used as part of a library for 30 * Python bindings. 31 */ 32 33 #include "common.h" 34 #include "policy.h" 35 36 /* libapol */ 37 #include <apol/policy-query.h> 38 #include <apol/render.h> 39 #include <apol/util.h> 40 #include <apol/vector.h> 41 42 /* libqpol */ 43 #include <qpol/policy.h> 44 #include <qpol/util.h> 45 46 /* other */ 47 #include <errno.h> 48 #include <stdlib.h> 49 #include <stdio.h> 50 #include <string.h> 51 #include <assert.h> 52 53 #define COPYRIGHT_INFO "Copyright (C) 2003-2007 Tresys Technology, LLC" 54 55 enum input 56 { 57 TYPE, ATTRIBUTE, ROLE, USER, PORT, BOOLEAN, CLASS, SENS, CATS 58 }; 59 60 static int py_insert_long(PyObject *dict, const char *name, int value) 61 { 62 int rt; 63 PyObject *obj = PyLong_FromLong(value); 64 if (!obj) return -1; 65 rt = PyDict_SetItemString(dict, name, obj); 66 Py_DECREF(obj); 67 return rt; 68 } 69 70 static int py_insert_bool(PyObject *dict, const char *name, int value) 71 { 72 int rt; 73 PyObject *obj = PyBool_FromLong(value); 74 if (!obj) return -1; 75 rt = PyDict_SetItemString(dict, name, obj); 76 Py_DECREF(obj); 77 return rt; 78 } 79 80 /** 81 * Get a policy's MLS sensitivities. 82 * If this function is given a name, it will attempt to 83 * get statistics about a particular sensitivity; otherwise 84 * the function gets statistics about all of the policy's 85 * sensitivities. 86 * 87 * @param name Reference to a sensitivity's name; if NULL, 88 * all sensitivities will be considered 89 * @param policydb Reference to a policy 90 * 91 * @return 0 on success, < 0 on error. 92 */ 93 static PyObject* get_sens(const char *name, const apol_policy_t * policydb) 94 { 95 PyObject *dict = NULL; 96 int error = 0; 97 int rt = 0; 98 size_t i; 99 char *tmp = NULL; 100 const char *lvl_name = NULL; 101 apol_level_query_t *query = NULL; 102 apol_vector_t *v = NULL; 103 const qpol_level_t *level = NULL; 104 apol_mls_level_t *ap_mls_lvl = NULL; 105 qpol_policy_t *q = apol_policy_get_qpol(policydb); 106 107 query = apol_level_query_create(); 108 if (!query) 109 goto cleanup; 110 if (apol_level_query_set_sens(policydb, query, name)) 111 goto cleanup; 112 if (apol_level_get_by_query(policydb, query, &v)) 113 goto cleanup; 114 115 dict = PyDict_New(); 116 if (!dict) goto err; 117 for (i = 0; i < apol_vector_get_size(v); i++) { 118 level = apol_vector_get_element(v, i); 119 if (qpol_level_get_name(q, level, &lvl_name)) 120 goto err; 121 ap_mls_lvl = (apol_mls_level_t *) apol_mls_level_create_from_qpol_level_datum(policydb, level); 122 tmp = apol_mls_level_render(policydb, ap_mls_lvl); 123 apol_mls_level_destroy(&ap_mls_lvl); 124 if (!tmp) 125 goto cleanup; 126 if (py_insert_string(dict, lvl_name, tmp)) 127 goto err; 128 free(tmp); tmp = NULL; 129 if (rt) goto err; 130 } 131 132 if (name && !apol_vector_get_size(v)) { 133 goto cleanup; 134 } 135 136 goto cleanup; 137 err: 138 error = errno; 139 PyErr_SetString(PyExc_RuntimeError,strerror(error)); 140 py_decref(dict); dict = NULL; 141 cleanup: 142 free(tmp); 143 apol_level_query_destroy(&query); 144 apol_vector_destroy(&v); 145 errno = error; 146 return dict; 147 } 148 149 /** 150 * Compare two qpol_cat_datum_t objects. 151 * This function is meant to be passed to apol_vector_compare 152 * as the callback for performing comparisons. 153 * 154 * @param datum1 Reference to a qpol_type_datum_t object 155 * @param datum2 Reference to a qpol_type_datum_t object 156 * @param data Reference to a policy 157 * @return Greater than 0 if the first argument is less than the second argument, 158 * less than 0 if the first argument is greater than the second argument, 159 * 0 if the arguments are equal 160 */ 161 static int qpol_cat_datum_compare(const void *datum1, const void *datum2, void *data) 162 { 163 const qpol_cat_t *cat_datum1 = NULL, *cat_datum2 = NULL; 164 apol_policy_t *policydb = NULL; 165 qpol_policy_t *q; 166 uint32_t val1, val2; 167 168 policydb = (apol_policy_t *) data; 169 q = apol_policy_get_qpol(policydb); 170 assert(policydb); 171 172 if (!datum1 || !datum2) 173 goto exit_err; 174 cat_datum1 = datum1; 175 cat_datum2 = datum2; 176 177 if (qpol_cat_get_value(q, cat_datum1, &val1)) 178 goto exit_err; 179 if (qpol_cat_get_value(q, cat_datum2, &val2)) 180 goto exit_err; 181 182 return (val1 > val2) ? 1 : ((val1 == val2) ? 0 : -1); 183 184 exit_err: 185 assert(0); 186 return 0; 187 } 188 189 /** 190 * Compare two qpol_level_datum_t objects. 191 * This function is meant to be passed to apol_vector_compare 192 * as the callback for performing comparisons. 193 * 194 * @param datum1 Reference to a qpol_level_datum_t object 195 * @param datum2 Reference to a qpol_level_datum_t object 196 * @param data Reference to a policy 197 * @return Greater than 0 if the first argument is less than the second argument, 198 * less than 0 if the first argument is greater than the second argument, 199 * 0 if the arguments are equal 200 */ 201 static int qpol_level_datum_compare(const void *datum1, const void *datum2, void *data) 202 { 203 const qpol_level_t *lvl_datum1 = NULL, *lvl_datum2 = NULL; 204 apol_policy_t *policydb = NULL; 205 qpol_policy_t *q; 206 uint32_t val1, val2; 207 208 policydb = (apol_policy_t *) data; 209 assert(policydb); 210 q = apol_policy_get_qpol(policydb); 211 212 if (!datum1 || !datum2) 213 goto exit_err; 214 lvl_datum1 = datum1; 215 lvl_datum2 = datum2; 216 217 if (qpol_level_get_value(q, lvl_datum1, &val1)) 218 goto exit_err; 219 if (qpol_level_get_value(q, lvl_datum2, &val2)) 220 goto exit_err; 221 222 return (val1 > val2) ? 1 : ((val1 == val2) ? 0 : -1); 223 224 exit_err: 225 assert(0); 226 return 0; 227 } 228 229 /** 230 * Gets a textual representation of a MLS category and 231 * all of that category's sensitivies. 232 * 233 * @param type_datum Reference to sepol type_datum 234 * @param policydb Reference to a policy 235 */ 236 static PyObject* get_cat_sens(const qpol_cat_t * cat_datum, const apol_policy_t * policydb) 237 { 238 const char *cat_name, *lvl_name; 239 apol_level_query_t *query = NULL; 240 apol_vector_t *v = NULL; 241 const qpol_level_t *lvl_datum = NULL; 242 qpol_policy_t *q = apol_policy_get_qpol(policydb); 243 size_t i, n_sens = 0; 244 int error = 0; 245 PyObject *list = NULL; 246 PyObject *dict = PyDict_New(); 247 if (!dict) goto err; 248 if (!cat_datum || !policydb) 249 goto err; 250 251 /* get category name for apol query */ 252 if (qpol_cat_get_name(q, cat_datum, &cat_name)) 253 goto cleanup; 254 255 query = apol_level_query_create(); 256 if (!query) 257 goto err; 258 if (apol_level_query_set_cat(policydb, query, cat_name)) 259 goto err; 260 if (apol_level_get_by_query(policydb, query, &v)) 261 goto err; 262 apol_vector_sort(v, &qpol_level_datum_compare, (void *)policydb); 263 dict = PyDict_New(); 264 if (!dict) goto err; 265 if (py_insert_string(dict, "name", cat_name)) 266 goto err; 267 n_sens = apol_vector_get_size(v); 268 list = PyList_New(0); 269 if (!list) goto err; 270 for (i = 0; i < n_sens; i++) { 271 lvl_datum = (qpol_level_t *) apol_vector_get_element(v, i); 272 if (!lvl_datum) 273 goto err; 274 if (qpol_level_get_name(q, lvl_datum, &lvl_name)) 275 goto err; 276 if (py_append_string(list, lvl_name)) 277 goto err; 278 } 279 if (py_insert_obj(dict, "level", list)) 280 goto err; 281 Py_DECREF(list); 282 283 goto cleanup; 284 err: 285 error = errno; 286 PyErr_SetString(PyExc_RuntimeError,strerror(errno)); 287 py_decref(list); list = NULL; 288 py_decref(dict); dict = NULL; 289 cleanup: 290 apol_level_query_destroy(&query); 291 apol_vector_destroy(&v); 292 errno = error; 293 return dict; 294 } 295 296 /** 297 * Prints statistics regarding a policy's MLS categories. 298 * If this function is given a name, it will attempt to 299 * get statistics about a particular category; otherwise 300 * the function gets statistics about all of the policy's 301 * categories. 302 * 303 * @param name Reference to a MLS category's name; if NULL, 304 * all categories will be considered 305 * @param policydb Reference to a policy 306 * 307 * @return 0 on success, < 0 on error. 308 */ 309 static PyObject* get_cats(const char *name, const apol_policy_t * policydb) 310 { 311 PyObject *obj = NULL; 312 apol_cat_query_t *query = NULL; 313 apol_vector_t *v = NULL; 314 const qpol_cat_t *cat_datum = NULL; 315 size_t i, n_cats; 316 int error = 0; 317 int rt; 318 PyObject *list = PyList_New(0); 319 if (!list) goto err; 320 321 query = apol_cat_query_create(); 322 if (!query) 323 goto err; 324 if (apol_cat_query_set_cat(policydb, query, name)) 325 goto err; 326 if (apol_cat_get_by_query(policydb, query, &v)) 327 goto err; 328 n_cats = apol_vector_get_size(v); 329 apol_vector_sort(v, &qpol_cat_datum_compare, (void *)policydb); 330 331 for (i = 0; i < n_cats; i++) { 332 cat_datum = apol_vector_get_element(v, i); 333 if (!cat_datum) 334 goto err; 335 obj = get_cat_sens(cat_datum, policydb); 336 if (!obj) 337 goto err; 338 rt = py_append_obj(list, obj); 339 Py_DECREF(obj); 340 if (rt) goto err; 341 } 342 343 if (name && !n_cats) { 344 goto err; 345 } 346 347 goto cleanup; 348 err: 349 error = errno; 350 PyErr_SetString(PyExc_RuntimeError,strerror(errno)); 351 py_decref(list); list = NULL; 352 cleanup: 353 apol_cat_query_destroy(&query); 354 apol_vector_destroy(&v); 355 errno = error; 356 return list; 357 } 358 359 /** 360 * Get the alias of a type. 361 * 362 * @param type_datum Reference to sepol type_datum 363 * @param policydb Reference to a policy 364 * attributes 365 */ 366 static PyObject* get_type_aliases(const qpol_type_t * type_datum, const apol_policy_t * policydb) 367 { 368 qpol_iterator_t *iter = NULL; 369 size_t alias_size; 370 unsigned char isattr, isalias; 371 const char *type_name = NULL; 372 const char *alias_name; 373 int error = 0; 374 qpol_policy_t *q = apol_policy_get_qpol(policydb); 375 PyObject *list = PyList_New(0); 376 if (!list) goto err; 377 378 if (qpol_type_get_name(q, type_datum, &type_name)) 379 goto cleanup; 380 if (qpol_type_get_isattr(q, type_datum, &isattr)) 381 goto cleanup; 382 if (qpol_type_get_isalias(q, type_datum, &isalias)) 383 goto cleanup; 384 385 if (qpol_type_get_alias_iter(q, type_datum, &iter)) 386 goto cleanup; 387 if (qpol_iterator_get_size(iter, &alias_size)) 388 goto cleanup; 389 if (alias_size > 0) { 390 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { 391 if (qpol_iterator_get_item(iter, (void **)&alias_name)) 392 goto err; 393 if (py_append_string(list, alias_name)) 394 goto err; 395 } 396 } 397 goto cleanup; 398 399 err: 400 error = errno; 401 PyErr_SetString(PyExc_RuntimeError,strerror(errno)); 402 py_decref(list); list = NULL; 403 404 cleanup: 405 qpol_iterator_destroy(&iter); 406 errno = error; 407 return list; 408 } 409 410 /** 411 * Gets a textual representation of an attribute, and 412 * all of that attribute's types. 413 * 414 * @param type_datum Reference to sepol type_datum 415 * @param policydb Reference to a policy 416 */ 417 static PyObject* get_attr(const qpol_type_t * type_datum, const apol_policy_t * policydb) 418 { 419 PyObject *list = NULL; 420 const qpol_type_t *attr_datum = NULL; 421 qpol_iterator_t *iter = NULL; 422 const char *attr_name = NULL, *type_name = NULL; 423 qpol_policy_t *q = apol_policy_get_qpol(policydb); 424 unsigned char isattr; 425 int error = 0; 426 int rt = 0; 427 PyObject *dict = PyDict_New(); 428 if (!dict) goto err; 429 430 if (qpol_type_get_name(q, type_datum, &attr_name)) 431 goto err; 432 433 if (py_insert_string(dict, "name", attr_name)) 434 goto err; 435 436 /* get an iterator over all types this attribute has */ 437 if (qpol_type_get_isattr(q, type_datum, &isattr)) 438 goto err; 439 440 if (isattr) { /* sanity check */ 441 if (qpol_type_get_type_iter(q, type_datum, &iter)) 442 goto err; 443 list = PyList_New(0); 444 if (!list) goto err; 445 446 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { 447 if (qpol_iterator_get_item(iter, (void **)&attr_datum)) 448 goto err; 449 if (qpol_type_get_name(q, attr_datum, &type_name)) 450 goto err; 451 if (py_append_string(list, type_name)) 452 goto err; 453 } 454 qpol_iterator_destroy(&iter); 455 rt = PyDict_SetItemString(dict, "types", list); 456 Py_DECREF(list); list = NULL; 457 if (rt) goto err; 458 } else /* this should never happen */ 459 goto err; 460 goto cleanup; 461 462 err: 463 error = errno; 464 PyErr_SetString(PyExc_RuntimeError,strerror(errno)); 465 py_decref(dict); dict = NULL; 466 py_decref(list); 467 468 cleanup: 469 qpol_iterator_destroy(&iter); 470 errno = error; 471 return dict; 472 } 473 474 /** 475 * Gets statistics regarding a policy's attributes. 476 * If this function is given a name, it will attempt to 477 * get statistics about a particular attribute; otherwise 478 * the function gets statistics about all of the policy's 479 * attributes. 480 * 481 * @param name Reference to an attribute's name; if NULL, 482 * all object classes will be considered 483 * @param policydb Reference to a policy 484 * 485 * @return 0 on success, < 0 on error. 486 */ 487 static PyObject* get_attribs(const char *name, const apol_policy_t * policydb) 488 { 489 PyObject *obj; 490 apol_attr_query_t *attr_query = NULL; 491 apol_vector_t *v = NULL; 492 const qpol_type_t *type_datum = NULL; 493 size_t n_attrs, i; 494 int error = 0; 495 int rt = 0; 496 PyObject *list = PyList_New(0); 497 if (!list) goto err; 498 499 /* we are only getting information about 1 attribute */ 500 if (name != NULL) { 501 attr_query = apol_attr_query_create(); 502 if (!attr_query) 503 goto err; 504 if (apol_attr_query_set_attr(policydb, attr_query, name)) 505 goto err; 506 if (apol_attr_get_by_query(policydb, attr_query, &v)) 507 goto err; 508 apol_attr_query_destroy(&attr_query); 509 if (apol_vector_get_size(v) == 0) { 510 apol_vector_destroy(&v); 511 errno = EINVAL; 512 goto err; 513 } 514 515 type_datum = apol_vector_get_element(v, (size_t) 0); 516 obj = get_attr(type_datum, policydb); 517 rt = py_append_obj(list, obj); 518 Py_DECREF(obj); 519 if (rt) goto err; 520 } else { 521 attr_query = apol_attr_query_create(); 522 if (!attr_query) 523 goto err; 524 if (apol_attr_get_by_query(policydb, attr_query, &v)) 525 goto err; 526 apol_attr_query_destroy(&attr_query); 527 n_attrs = apol_vector_get_size(v); 528 529 for (i = 0; i < n_attrs; i++) { 530 /* get qpol_type_t* item from vector */ 531 type_datum = (qpol_type_t *) apol_vector_get_element(v, (size_t) i); 532 if (!type_datum) 533 goto err; 534 obj = get_attr(type_datum, policydb); 535 rt = py_append_obj(list, obj); 536 Py_DECREF(obj); 537 if (rt) goto err; 538 } 539 } 540 apol_vector_destroy(&v); 541 goto cleanup; 542 543 err: 544 error = errno; 545 PyErr_SetString(PyExc_RuntimeError,strerror(errno)); 546 py_decref(list); list = NULL; 547 548 cleanup: 549 apol_attr_query_destroy(&attr_query); 550 apol_vector_destroy(&v); 551 errno = error; 552 return list; 553 } 554 555 /** 556 * Get a textual representation of a type, and 557 * all of that type's attributes. 558 * 559 * @param type_datum Reference to sepol type_datum 560 * @param policydb Reference to a policy 561 */ 562 static PyObject* get_type_attrs(const qpol_type_t * type_datum, const apol_policy_t * policydb) 563 { 564 qpol_iterator_t *iter = NULL; 565 const char *attr_name = NULL; 566 const qpol_type_t *attr_datum = NULL; 567 qpol_policy_t *q = apol_policy_get_qpol(policydb); 568 int error = 0; 569 PyObject *list = PyList_New(0); 570 if (!list) goto err; 571 572 if (qpol_type_get_attr_iter(q, type_datum, &iter)) 573 goto err; 574 575 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { 576 if (qpol_iterator_get_item(iter, (void **)&attr_datum)) 577 goto err; 578 if (qpol_type_get_name(q, attr_datum, &attr_name)) 579 goto err; 580 if (py_append_string(list, attr_name)) 581 goto err; 582 } 583 goto cleanup; 584 585 err: 586 error = errno; 587 PyErr_SetString(PyExc_RuntimeError,strerror(errno)); 588 py_decref(list); list = NULL; 589 590 cleanup: 591 qpol_iterator_destroy(&iter); 592 errno = error; 593 return list; 594 } 595 596 static PyObject* get_type(const qpol_type_t * type_datum, const apol_policy_t * policydb) { 597 598 PyObject *obj; 599 qpol_policy_t *q = apol_policy_get_qpol(policydb); 600 const char *type_name = NULL; 601 int error = 0; 602 int rt; 603 unsigned char isalias, ispermissive, isattr; 604 PyObject *dict = PyDict_New(); 605 if (!dict) goto err; 606 607 if (qpol_type_get_name(q, type_datum, &type_name)) 608 goto err; 609 if (qpol_type_get_isalias(q, type_datum, &isalias)) 610 goto err; 611 if (qpol_type_get_isattr(q, type_datum, &isattr)) 612 goto err; 613 if (qpol_type_get_ispermissive(q, type_datum, &ispermissive)) 614 goto err; 615 616 if (py_insert_string(dict, "name", type_name)) 617 goto err; 618 619 if (py_insert_bool(dict, "permissive", ispermissive)) 620 goto err; 621 622 if (!isattr && !isalias) { 623 obj = get_type_attrs(type_datum, policydb); 624 rt = py_insert_obj(dict, "attributes", obj); 625 Py_DECREF(obj); 626 if (rt) goto err; 627 } 628 629 obj = get_type_aliases(type_datum, policydb); 630 rt = py_insert_obj(dict, "aliases", obj); 631 Py_DECREF(obj); 632 if (rt) goto err; 633 goto cleanup; 634 635 err: 636 error = errno; 637 PyErr_SetString(PyExc_RuntimeError,strerror(error)); 638 py_decref(dict); dict = NULL; 639 640 cleanup: 641 errno = error; 642 return dict; 643 } 644 645 /** 646 * Gets statistics regarding a policy's booleans. 647 * If this function is given a name, it will attempt to 648 * get statistics about a particular boolean; otherwise 649 * the function gets statistics about all of the policy's booleans. 650 * 651 * @param name Reference to a boolean's name; if NULL, 652 * all booleans will be considered 653 * @param policydb Reference to a policy 654 * 655 * @return new reference, or NULL (setting an exception) 656 */ 657 static PyObject* get_booleans(const char *name, const apol_policy_t * policydb) 658 { 659 PyObject *dict = NULL; 660 int error = 0; 661 int rt = 0; 662 const char *bool_name = NULL; 663 int state; 664 qpol_bool_t *bool_datum = NULL; 665 qpol_iterator_t *iter = NULL; 666 qpol_policy_t *q = apol_policy_get_qpol(policydb); 667 size_t n_bools = 0; 668 PyObject *list = PyList_New(0); 669 if (!list) goto err; 670 671 if (name != NULL) { 672 if (qpol_policy_get_bool_by_name(q, name, &bool_datum)) 673 goto err; 674 if (qpol_bool_get_state(q, bool_datum, &state)) 675 goto err; 676 677 dict = PyDict_New(); 678 if (!dict) goto err; 679 if (py_insert_string(dict, "name", name)) 680 goto err; 681 if (py_insert_bool(dict, "name", state)) 682 goto err; 683 rt = py_append_obj(list, dict); 684 Py_DECREF(dict); dict = NULL; 685 if (rt) goto err; 686 } else { 687 if (qpol_policy_get_bool_iter(q, &iter)) 688 goto err; 689 if (qpol_iterator_get_size(iter, &n_bools)) 690 goto err; 691 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { 692 if (qpol_iterator_get_item(iter, (void **)&bool_datum)) 693 goto err; 694 if (qpol_bool_get_name(q, bool_datum, &bool_name)) 695 goto err; 696 if (qpol_bool_get_state(q, bool_datum, &state)) 697 goto err; 698 699 dict = PyDict_New(); 700 if (!dict) goto err; 701 if (py_insert_string(dict, "name", bool_name)) 702 goto err; 703 if (py_insert_bool(dict, "state", state)) 704 goto err; 705 rt = py_append_obj(list, dict); 706 Py_DECREF(dict); dict = NULL; 707 if (rt) goto err; 708 } 709 qpol_iterator_destroy(&iter); 710 } 711 goto cleanup; 712 713 err: 714 error = errno; 715 PyErr_SetString(PyExc_RuntimeError,strerror(error)); 716 py_decref(list); list = NULL; 717 py_decref(dict); dict = NULL; 718 719 cleanup: 720 qpol_iterator_destroy(&iter); 721 errno = error; 722 return list; 723 } 724 725 /** 726 * Gets a textual representation of a user, and 727 * all of that user's roles. 728 * 729 * @param type_datum Reference to sepol type_datum 730 * @param policydb Reference to a policy 731 * roles 732 */ 733 static PyObject* get_user(const qpol_user_t * user_datum, const apol_policy_t * policydb) 734 { 735 int error = 0; 736 int rt; 737 const qpol_role_t *role_datum = NULL; 738 qpol_iterator_t *iter = NULL; 739 const qpol_mls_range_t *range = NULL; 740 const qpol_mls_level_t *dflt_level = NULL; 741 apol_mls_level_t *ap_lvl = NULL; 742 apol_mls_range_t *ap_range = NULL; 743 qpol_policy_t *q = apol_policy_get_qpol(policydb); 744 char *tmp = NULL; 745 const char *user_name, *role_name; 746 PyObject *dict = NULL; 747 PyObject *list = PyList_New(0); 748 if (!list) goto err; 749 750 if (qpol_user_get_name(q, user_datum, &user_name)) 751 goto err; 752 753 dict = PyDict_New(); 754 if (!dict) goto err; 755 756 if (py_insert_string(dict, "name", user_name)) 757 goto err; 758 759 if (qpol_policy_has_capability(q, QPOL_CAP_MLS)) { 760 if (qpol_user_get_dfltlevel(q, user_datum, &dflt_level)) 761 goto err; 762 ap_lvl = apol_mls_level_create_from_qpol_mls_level(policydb, dflt_level); 763 tmp = apol_mls_level_render(policydb, ap_lvl); 764 if (!tmp) goto err; 765 if (py_insert_string(dict, "level", tmp)) 766 goto err; 767 free(tmp); tmp = NULL; 768 769 if (qpol_user_get_range(q, user_datum, &range)) 770 goto err; 771 ap_range = apol_mls_range_create_from_qpol_mls_range(policydb, range); 772 tmp = apol_mls_range_render(policydb, ap_range); 773 if (!tmp) goto err; 774 if (py_insert_string(dict, "range", tmp)) 775 goto err; 776 free(tmp); tmp=NULL; 777 } 778 779 if (qpol_user_get_role_iter(q, user_datum, &iter)) 780 goto err; 781 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { 782 if (qpol_iterator_get_item(iter, (void **)&role_datum)) 783 goto err; 784 if (qpol_role_get_name(q, role_datum, &role_name)) 785 goto err; 786 if (py_append_string(list, role_name)) 787 goto err; 788 } 789 790 rt = py_insert_obj(dict, "roles", list); 791 Py_DECREF(list); list=NULL; 792 if (rt) goto err; 793 goto cleanup; 794 795 err: 796 error = errno; 797 PyErr_SetString(PyExc_RuntimeError,strerror(errno)); 798 py_decref(list); list=NULL; 799 py_decref(dict); dict=NULL; 800 801 cleanup: 802 free(tmp); 803 qpol_iterator_destroy(&iter); 804 apol_mls_level_destroy(&ap_lvl); 805 apol_mls_range_destroy(&ap_range); 806 errno = error; 807 return dict; 808 } 809 810 /** 811 * Prints a textual representation of an object class and possibly 812 * all of that object class' permissions. 813 * 814 * @param type_datum Reference to sepol type_datum 815 * @param policydb Reference to a policy 816 */ 817 static PyObject* get_class(const qpol_class_t * class_datum, const apol_policy_t * policydb) 818 { 819 const char *class_name = NULL, *perm_name = NULL; 820 qpol_iterator_t *iter = NULL; 821 const qpol_common_t *common_datum = NULL; 822 qpol_policy_t *q = apol_policy_get_qpol(policydb); 823 int error = 0; 824 int rt; 825 PyObject *list = NULL; 826 PyObject *dict = PyDict_New(); 827 if (!dict) goto err; 828 829 if (!class_datum) 830 goto err; 831 832 if (qpol_class_get_name(q, class_datum, &class_name)) 833 goto err; 834 835 if (py_insert_string(dict, "name", class_name)) 836 goto err; 837 /* get commons for this class */ 838 if (qpol_class_get_common(q, class_datum, &common_datum)) 839 goto err; 840 841 list = PyList_New(0); 842 if (!list) goto err; 843 844 if (common_datum) { 845 if (qpol_common_get_perm_iter(q, common_datum, &iter)) 846 goto err; 847 /* print perms for the common */ 848 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { 849 if (qpol_iterator_get_item(iter, (void **)&perm_name)) 850 goto err; 851 if (py_append_string(list, perm_name)) 852 goto err; 853 } 854 } 855 /* print unique perms for this class */ 856 if (qpol_class_get_perm_iter(q, class_datum, &iter)) 857 goto err; 858 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { 859 if (qpol_iterator_get_item(iter, (void **)&perm_name)) 860 goto err; 861 if (py_append_string(list, perm_name)) 862 goto err; 863 } 864 rt = py_insert_obj(dict, "permlist", list); 865 Py_DECREF(list); list = NULL; 866 if (rt) goto err; 867 qpol_iterator_destroy(&iter); 868 goto cleanup; 869 870 err: 871 error = errno; 872 PyErr_SetString(PyExc_RuntimeError,strerror(errno)); 873 py_decref(list); list=NULL; 874 py_decref(dict); dict=NULL; 875 876 cleanup: 877 errno = error; 878 qpol_iterator_destroy(&iter); 879 return dict; 880 } 881 882 /** 883 * Get statistics regarding a policy's object classes. 884 * If this function is given a name, it will attempt to 885 * print statistics about a particular object class; otherwise 886 * the function prints statistics about all of the policy's object 887 * classes. 888 * 889 * @param name Reference to an object class' name; if NULL, 890 * all object classes will be considered 891 * @param policydb Reference to a policy 892 * 893 * @return 0 on success, < 0 on error. 894 */ 895 static PyObject* get_classes(const char *name, const apol_policy_t * policydb) 896 { 897 qpol_iterator_t *iter = NULL; 898 size_t n_classes = 0; 899 const qpol_class_t *class_datum = NULL; 900 qpol_policy_t *q = apol_policy_get_qpol(policydb); 901 int error = 0; 902 int rt; 903 PyObject *obj; 904 PyObject *list = PyList_New(0); 905 if (!list) goto err; 906 907 if (name != NULL) { 908 if (qpol_policy_get_class_by_name(q, name, &class_datum)) 909 goto err; 910 obj = get_class(class_datum, policydb); 911 rt = py_append_obj(list, obj); 912 Py_DECREF(obj); 913 if (rt) goto err; 914 } else { 915 if (qpol_policy_get_class_iter(q, &iter)) 916 goto err; 917 if (qpol_iterator_get_size(iter, &n_classes)) 918 goto err; 919 920 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { 921 if (qpol_iterator_get_item(iter, (void **)&class_datum)) 922 goto err; 923 obj = get_class(class_datum, policydb); 924 rt = py_append_obj(list, obj); 925 Py_DECREF(obj); 926 if (rt) goto err; 927 } 928 qpol_iterator_destroy(&iter); 929 } 930 goto cleanup; 931 err: 932 error = errno; 933 PyErr_SetString(PyExc_RuntimeError,strerror(errno)); 934 py_decref(list); list = NULL; 935 936 cleanup: 937 qpol_iterator_destroy(&iter); 938 errno = error; 939 return list; 940 } 941 942 /** 943 * Gets statistics regarding a policy's users. 944 * If this function is given a name, it will attempt to 945 * get statistics about a particular user; otherwise 946 * the function gets statistics about all of the policy's 947 * users. 948 * 949 * @param name Reference to a user's name; if NULL, 950 * all users will be considered 951 * @param policydb Reference to a policy 952 * 953 * @return 0 on success, < 0 on error. 954 */ 955 static PyObject* get_users(const char *name, const apol_policy_t * policydb) 956 { 957 qpol_iterator_t *iter = NULL; 958 const qpol_user_t *user_datum = NULL; 959 qpol_policy_t *q = apol_policy_get_qpol(policydb); 960 int error = 0; 961 int rt; 962 PyObject *obj; 963 PyObject *list = PyList_New(0); 964 if (!list) goto err; 965 966 if (name != NULL) { 967 if (qpol_policy_get_user_by_name(q, name, &user_datum)) { 968 errno = EINVAL; 969 goto err; 970 } 971 obj = get_user(user_datum, policydb); 972 rt = py_append_obj(list, obj); 973 Py_DECREF(obj); 974 if (rt) goto err; 975 } else { 976 if (qpol_policy_get_user_iter(q, &iter)) 977 goto err; 978 979 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { 980 if (qpol_iterator_get_item(iter, (void **)&user_datum)) 981 goto err; 982 obj = get_user(user_datum, policydb); 983 rt = py_append_obj(list, obj); 984 Py_DECREF(obj); 985 if (rt) goto err; 986 } 987 qpol_iterator_destroy(&iter); 988 } 989 goto cleanup; 990 991 err: 992 error = errno; 993 PyErr_SetString(PyExc_RuntimeError,strerror(errno)); 994 py_decref(list); list = NULL; 995 996 cleanup: 997 qpol_iterator_destroy(&iter); 998 errno = error; 999 return list; 1000 } 1001 1002 /** 1003 * get a textual representation of a role, and 1004 * all of that role's types. 1005 * 1006 * @param type_datum Reference to sepol type_datum 1007 * @param policydb Reference to a policy 1008 * types 1009 */ 1010 static PyObject* get_role(const qpol_role_t * role_datum, const apol_policy_t * policydb) 1011 { 1012 const char *role_name = NULL, *type_name = NULL; 1013 const qpol_role_t *dom_datum = NULL; 1014 const qpol_type_t *type_datum = NULL; 1015 qpol_iterator_t *iter = NULL; 1016 qpol_policy_t *q = apol_policy_get_qpol(policydb); 1017 size_t n_dom = 0, n_types = 0; 1018 int error = 0; 1019 int rt; 1020 PyObject *list = NULL; 1021 PyObject *dict = PyDict_New(); 1022 if (!dict) goto err; 1023 1024 if (qpol_role_get_name(q, role_datum, &role_name)) 1025 goto err; 1026 if (py_insert_string(dict, "name", role_name)) 1027 goto err; 1028 1029 if (qpol_role_get_dominate_iter(q, role_datum, &iter)) 1030 goto err; 1031 if (qpol_iterator_get_size(iter, &n_dom)) 1032 goto err; 1033 if ((int)n_dom > 0) { 1034 list = PyList_New(0); 1035 if (!list) goto err; 1036 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { 1037 if (qpol_iterator_get_item(iter, (void **)&dom_datum)) 1038 goto err; 1039 if (qpol_role_get_name(q, dom_datum, &role_name)) 1040 goto err; 1041 if (py_append_string(list, role_name)) 1042 goto err; 1043 } 1044 rt = py_insert_obj(dict, "roles", list); 1045 Py_DECREF(list); list = NULL; 1046 if (rt) goto err; 1047 } 1048 qpol_iterator_destroy(&iter); 1049 1050 if (qpol_role_get_type_iter(q, role_datum, &iter)) 1051 goto err; 1052 if (qpol_iterator_get_size(iter, &n_types)) 1053 goto err; 1054 if ((int)n_types > 0) { 1055 list = PyList_New(0); 1056 if (!list) goto err; 1057 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { 1058 if (qpol_iterator_get_item(iter, (void **)&type_datum)) 1059 goto err; 1060 if (qpol_type_get_name(q, type_datum, &type_name)) 1061 goto err; 1062 if (py_append_string(list, type_name)) 1063 goto err; 1064 } 1065 rt = py_insert_obj(dict, "types", list); 1066 Py_DECREF(list); list = NULL; 1067 if (rt) goto err; 1068 } 1069 goto cleanup; 1070 1071 err: 1072 error = errno; 1073 PyErr_SetString(PyExc_RuntimeError,strerror(errno)); 1074 py_decref(list); list = NULL; 1075 py_decref(dict); dict = NULL; 1076 1077 cleanup: 1078 qpol_iterator_destroy(&iter); 1079 errno = error; 1080 return dict; 1081 } 1082 1083 /** 1084 * Get statistics regarding a policy's ports. 1085 * If this function is given a name, it will attempt to 1086 * get statistics about a particular port; otherwise 1087 * the function get statistics about all of the policy's ports. 1088 * 1089 * @param name Reference to an port's name; if NULL, 1090 * all ports will be considered 1091 * @param policydb Reference to a policy 1092 * 1093 * @return 0 on success, < 0 on error. 1094 */ 1095 static PyObject* get_ports(const char *num, const apol_policy_t * policydb) 1096 { 1097 const qpol_portcon_t *portcon = NULL; 1098 qpol_iterator_t *iter = NULL; 1099 uint16_t low_port, high_port; 1100 uint8_t ocon_proto; 1101 qpol_policy_t *q = apol_policy_get_qpol(policydb); 1102 const qpol_context_t *ctxt = NULL; 1103 const char *proto_str = NULL; 1104 const char *type = NULL; 1105 const apol_mls_range_t *range = NULL; 1106 char *range_str = NULL; 1107 apol_context_t *c = NULL; 1108 int error = 0; 1109 int rt = 0; 1110 PyObject *dict = NULL; 1111 PyObject *list = PyList_New(0); 1112 if (!list) goto err; 1113 1114 if (qpol_policy_get_portcon_iter(q, &iter)) 1115 goto err; 1116 1117 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { 1118 if (qpol_iterator_get_item(iter, (void **)&portcon)) 1119 goto err; 1120 if (qpol_portcon_get_low_port(q, portcon, &low_port)) 1121 goto err; 1122 if (qpol_portcon_get_high_port(q, portcon, &high_port)) 1123 goto err; 1124 if (qpol_portcon_get_protocol(q, portcon, &ocon_proto)) 1125 goto err; 1126 if (num) { 1127 if (atoi(num) < low_port || atoi(num) > high_port) 1128 continue; 1129 } 1130 1131 if ((ocon_proto != IPPROTO_TCP) && 1132 (ocon_proto != IPPROTO_UDP)) 1133 goto err; 1134 1135 if (qpol_portcon_get_context(q, portcon, &ctxt)) { 1136 PyErr_SetString(PyExc_RuntimeError, "Could not get for port context."); 1137 goto err; 1138 } 1139 1140 if ((proto_str = apol_protocol_to_str(ocon_proto)) == NULL) { 1141 PyErr_SetString(PyExc_RuntimeError, "Invalid protocol for port"); 1142 goto err; 1143 } 1144 1145 if ((c = apol_context_create_from_qpol_context(policydb, ctxt)) == NULL) { 1146 goto err; 1147 } 1148 1149 if((type = apol_context_get_type(c)) == NULL) { 1150 apol_context_destroy(&c); 1151 goto err; 1152 } 1153 1154 dict = PyDict_New(); 1155 if (!dict) goto err; 1156 if (py_insert_string(dict, "type", type)) 1157 goto err; 1158 1159 if((range = apol_context_get_range(c)) != NULL) { 1160 range_str = apol_mls_range_render(policydb, range); 1161 if (range_str == NULL) { 1162 goto err; 1163 } 1164 if (py_insert_string(dict, "range", range_str)) 1165 goto err; 1166 } 1167 1168 if (py_insert_string(dict, "protocol", proto_str)) 1169 goto err; 1170 1171 if (py_insert_long(dict, "high", high_port)) 1172 goto err; 1173 1174 if (py_insert_long(dict, "low", low_port)) 1175 goto err; 1176 1177 rt = py_append_obj(list, dict); 1178 Py_DECREF(dict); dict = NULL; 1179 if (rt) goto err; 1180 } 1181 goto cleanup; 1182 1183 err: 1184 error = errno; 1185 PyErr_SetString(PyExc_RuntimeError,strerror(errno)); 1186 py_decref(list); list = NULL; 1187 py_decref(dict); dict = NULL; 1188 1189 cleanup: 1190 free(range_str); 1191 apol_context_destroy(&c); 1192 qpol_iterator_destroy(&iter); 1193 errno = error; 1194 return list; 1195 } 1196 1197 /** 1198 * Get statistics regarding a policy's roles. 1199 * If this function is given a name, it will attempt to 1200 * get statistics about a particular role; otherwise 1201 * the function get statistics about all of the policy's roles. 1202 * 1203 * @param name Reference to an role's name; if NULL, 1204 * all roles will be considered 1205 * @param policydb Reference to a policy 1206 * 1207 * @return 0 on success, < 0 on error. 1208 */ 1209 static PyObject* get_roles(const char *name, const apol_policy_t * policydb) 1210 { 1211 const qpol_role_t *role_datum = NULL; 1212 qpol_iterator_t *iter = NULL; 1213 qpol_policy_t *q = apol_policy_get_qpol(policydb); 1214 int error = 0; 1215 int rt; 1216 PyObject *obj; 1217 PyObject *list = PyList_New(0); 1218 if (!list) goto err; 1219 1220 if (name != NULL) { 1221 if (qpol_policy_get_role_by_name(q, name, &role_datum)) { 1222 errno = EINVAL; 1223 goto err; 1224 } 1225 obj = get_role(role_datum, policydb); 1226 rt = py_append_obj(list, obj); 1227 Py_DECREF(obj); 1228 if (rt) goto err; 1229 } else { 1230 if (qpol_policy_get_role_iter(q, &iter)) 1231 goto err; 1232 1233 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { 1234 if (qpol_iterator_get_item(iter, (void **)&role_datum)) 1235 goto err; 1236 obj = get_role(role_datum, policydb); 1237 rt = py_append_obj(list, obj); 1238 Py_DECREF(obj); 1239 if (rt) goto err; 1240 } 1241 qpol_iterator_destroy(&iter); 1242 } 1243 goto cleanup; 1244 1245 err: 1246 error = errno; 1247 PyErr_SetString(PyExc_RuntimeError,strerror(errno)); 1248 py_decref(list); list = NULL; 1249 1250 cleanup: 1251 qpol_iterator_destroy(&iter); 1252 errno = error; 1253 return list; 1254 } 1255 1256 /** 1257 * Get statistics regarding a policy's types. 1258 * If this function is given a name, it will attempt to 1259 * print statistics about a particular type; otherwise 1260 * the function prints statistics about all of the policy's types. 1261 * 1262 * @param name Reference to a type's name; if NULL, 1263 * all object classes will be considered 1264 * @param policydb Reference to a policy 1265 * 1266 * @return 0 on success, < 0 on error. 1267 */ 1268 static PyObject* get_types(const char *name, const apol_policy_t * policydb) 1269 { 1270 const qpol_type_t *type_datum = NULL; 1271 qpol_iterator_t *iter = NULL; 1272 qpol_policy_t *q = apol_policy_get_qpol(policydb); 1273 int error = 0; 1274 int rt; 1275 PyObject *obj; 1276 PyObject *list = PyList_New(0); 1277 if (!list) goto err; 1278 /* if name was provided, only print that name */ 1279 if (name != NULL) { 1280 if (qpol_policy_get_type_by_name(q, name, &type_datum)) { 1281 errno = EINVAL; 1282 goto err; 1283 } 1284 obj = get_type(type_datum, policydb); 1285 rt = py_append_obj(list, obj); 1286 Py_DECREF(obj); 1287 if (rt) goto err; 1288 } else { 1289 if (qpol_policy_get_type_iter(q, &iter)) 1290 goto err; 1291 1292 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { 1293 if (qpol_iterator_get_item(iter, (void **)&type_datum)) 1294 goto err; 1295 obj = get_type(type_datum, policydb); 1296 rt = py_append_obj(list, obj); 1297 Py_DECREF(obj); 1298 if (rt) goto err; 1299 } 1300 } 1301 goto cleanup; 1302 1303 err: 1304 error = errno; 1305 PyErr_SetString(PyExc_RuntimeError,strerror(errno)); 1306 py_decref(list); list = NULL; 1307 1308 cleanup: 1309 qpol_iterator_destroy(&iter); 1310 errno = error; 1311 return list; 1312 } 1313 1314 PyObject* info( int type, const char *name) 1315 { 1316 PyObject* output = NULL; 1317 1318 switch(type) { 1319 /* display requested info */ 1320 case TYPE: 1321 output = get_types(name, policy); 1322 break; 1323 case ATTRIBUTE: 1324 output = get_attribs(name, policy); 1325 break; 1326 case ROLE: 1327 output = get_roles(name, policy); 1328 break; 1329 case USER: 1330 output = get_users(name, policy); 1331 break; 1332 case CLASS: 1333 output = get_classes(name, policy); 1334 break; 1335 case BOOLEAN: 1336 output = get_booleans(name, policy); 1337 break; 1338 case PORT: 1339 output = get_ports(name, policy); 1340 break; 1341 case SENS: 1342 output = get_sens(name, policy); 1343 break; 1344 case CATS: 1345 output = get_cats(name, policy); 1346 break; 1347 default: 1348 errno = EINVAL; 1349 PyErr_SetString(PyExc_RuntimeError,strerror(errno)); 1350 break; 1351 } 1352 1353 return output; 1354 } 1355 1356 PyObject *wrap_info(PyObject *UNUSED(self), PyObject *args){ 1357 int type; 1358 const char *name; 1359 1360 if (!policy) { 1361 PyErr_SetString(PyExc_RuntimeError,"Policy not loaded"); 1362 return NULL; 1363 } 1364 1365 if (!PyArg_ParseTuple(args, "iz", &type, &name)) 1366 return NULL; 1367 1368 return info(type, name); 1369 } 1370 1371 void init_info (PyObject *m) { 1372 PyModule_AddIntConstant(m, "ATTRIBUTE", ATTRIBUTE); 1373 PyModule_AddIntConstant(m, "PORT", PORT); 1374 PyModule_AddIntConstant(m, "ROLE", ROLE); 1375 PyModule_AddIntConstant(m, "TYPE", TYPE); 1376 PyModule_AddIntConstant(m, "USER", USER); 1377 PyModule_AddIntConstant(m, "CLASS", CLASS); 1378 PyModule_AddIntConstant(m, "BOOLEAN", BOOLEAN); 1379 PyModule_AddIntConstant(m, "SENS", SENS); 1380 PyModule_AddIntConstant(m, "CATS", CATS); 1381 } 1382