int level_comp(const void *x, const void *y, const poldiff_t * diff) { const qpol_level_t *l1 = x; const qpol_level_t *l2 = y; const char *name1, *name2; if (qpol_level_get_name(diff->orig_qpol, l1, &name1) < 0 || qpol_level_get_name(diff->mod_qpol, l2, &name2) < 0) { return 0; } return strcmp(name1, name2); }
/** * Comparison function for two levels from the same policy. */ static int level_name_comp(const void *x, const void *y, void *arg) { const qpol_level_t *s1 = x; const qpol_level_t *s2 = y; apol_policy_t *p = arg; qpol_policy_t *q = apol_policy_get_qpol(p); const char *name1, *name2; if (qpol_level_get_name(q, s1, &name1) < 0 || qpol_level_get_name(q, s2, &name2) < 0) return 0; return strcmp(name1, name2); }
int level_deep_diff(poldiff_t * diff, const void *x, const void *y) { const qpol_level_t *l1 = x; const qpol_level_t *l2 = y; apol_vector_t *v1 = NULL, *v2 = NULL; apol_vector_t *added = NULL, *removed = NULL, *unmodified = NULL; const char *name; poldiff_level_t *l = NULL; int retval = -1, error = 0, compval; if (qpol_level_get_name(diff->orig_qpol, l1, &name) < 0 || (v1 = level_get_cats(diff, diff->orig_pol, l1)) == NULL || (v2 = level_get_cats(diff, diff->mod_pol, l2)) == NULL) { error = errno; goto cleanup; } apol_vector_sort(v1, apol_str_strcmp, NULL); apol_vector_sort(v2, apol_str_strcmp, NULL); compval = level_deep_diff_cats(diff, v1, v2, &added, &removed, &unmodified); if (compval < 0) { error = errno; goto cleanup; } else if (compval > 0) { if ((l = make_diff(diff, POLDIFF_FORM_MODIFIED, name)) == NULL) { error = errno; goto cleanup; } apol_vector_destroy(&l->added_cats); apol_vector_destroy(&l->removed_cats); apol_vector_destroy(&l->unmodified_cats); if ((l->added_cats = apol_vector_create_from_vector(added, apol_str_strdup, NULL, free)) == NULL || (l->removed_cats = apol_vector_create_from_vector(removed, apol_str_strdup, NULL, free)) == NULL || (l->unmodified_cats = apol_vector_create_from_vector(unmodified, apol_str_strdup, NULL, free)) == NULL) { error = errno; ERR(diff, "%s", strerror(error)); goto cleanup; } apol_vector_sort(l->removed_cats, level_cat_comp, diff->orig_qpol); apol_vector_sort(l->added_cats, level_cat_comp, diff->mod_qpol); apol_vector_sort(l->unmodified_cats, level_cat_comp, diff->orig_qpol); if (apol_vector_append(diff->level_diffs->diffs, l) < 0) { error = errno; ERR(diff, "%s", strerror(error)); goto cleanup; } diff->level_diffs->num_modified++; } retval = 0; cleanup: apol_vector_destroy(&v1); apol_vector_destroy(&v2); apol_vector_destroy(&added); apol_vector_destroy(&removed); apol_vector_destroy(&unmodified); if (retval != 0) { level_free(l); } errno = error; return retval; }
int level_new_diff(poldiff_t * diff, poldiff_form_e form, const void *item) { const qpol_level_t *l = item; const char *name = NULL; poldiff_level_t *pl = NULL; apol_policy_t *p; qpol_policy_t *q; apol_vector_t *v = NULL; int error = 0, retval = -1; if (form == POLDIFF_FORM_ADDED) { p = diff->mod_pol; q = diff->mod_qpol; } else { p = diff->orig_pol; q = diff->orig_qpol; } if (qpol_level_get_name(q, l, &name) < 0 || (pl = make_diff(diff, form, name)) == NULL) { error = errno; goto cleanup; } if ((v = level_get_cats(diff, p, l)) == NULL) { error = errno; ERR(diff, "%s", strerror(error)); goto cleanup; } if (form == POLDIFF_FORM_ADDED) { apol_vector_destroy(&pl->added_cats); if ((pl->added_cats = apol_vector_create_from_vector(v, apol_str_strdup, NULL, free)) == NULL) { error = errno; ERR(diff, "%s", strerror(error)); goto cleanup; } } else if (form == POLDIFF_FORM_REMOVED) { apol_vector_destroy(&pl->removed_cats); if ((pl->removed_cats = apol_vector_create_from_vector(v, apol_str_strdup, NULL, free)) == NULL) { error = errno; ERR(diff, "%s", strerror(error)); goto cleanup; } } if (apol_vector_append(diff->level_diffs->diffs, pl) < 0) { error = errno; ERR(diff, "%s", strerror(error)); goto cleanup; } if (form == POLDIFF_FORM_ADDED) { diff->level_diffs->num_added++; } else { diff->level_diffs->num_removed++; } retval = 0; cleanup: apol_vector_destroy(&v); if (retval < 0) { level_free(pl); errno = error; } return retval; }
/** * Gets a textual representation of a MLS category and * all of that category's sensitivies. * * @param type_datum Reference to sepol type_datum * @param policydb Reference to a policy */ static PyObject* get_cat_sens(const qpol_cat_t * cat_datum, const apol_policy_t * policydb) { const char *cat_name, *lvl_name; apol_level_query_t *query = NULL; apol_vector_t *v = NULL; const qpol_level_t *lvl_datum = NULL; qpol_policy_t *q = apol_policy_get_qpol(policydb); size_t i, n_sens = 0; int error = 0; PyObject *list = NULL; PyObject *dict = PyDict_New(); if (!dict) goto err; if (!cat_datum || !policydb) goto err; /* get category name for apol query */ if (qpol_cat_get_name(q, cat_datum, &cat_name)) goto cleanup; query = apol_level_query_create(); if (!query) goto err; if (apol_level_query_set_cat(policydb, query, cat_name)) goto err; if (apol_level_get_by_query(policydb, query, &v)) goto err; apol_vector_sort(v, &qpol_level_datum_compare, (void *)policydb); dict = PyDict_New(); if (!dict) goto err; if (py_insert_string(dict, "name", cat_name)) goto err; n_sens = apol_vector_get_size(v); list = PyList_New(0); if (!list) goto err; for (i = 0; i < n_sens; i++) { lvl_datum = (qpol_level_t *) apol_vector_get_element(v, i); if (!lvl_datum) goto err; if (qpol_level_get_name(q, lvl_datum, &lvl_name)) goto err; if (py_append_string(list, lvl_name)) goto err; } if (py_insert_obj(dict, "level", list)) goto err; Py_DECREF(list); goto cleanup; err: error = errno; PyErr_SetString(PyExc_RuntimeError,strerror(errno)); py_decref(list); list = NULL; py_decref(dict); dict = NULL; cleanup: apol_level_query_destroy(&query); apol_vector_destroy(&v); errno = error; return dict; }
/** * Get a policy's MLS sensitivities. * If this function is given a name, it will attempt to * get statistics about a particular sensitivity; otherwise * the function gets statistics about all of the policy's * sensitivities. * * @param name Reference to a sensitivity's name; if NULL, * all sensitivities will be considered * @param policydb Reference to a policy * * @return 0 on success, < 0 on error. */ static PyObject* get_sens(const char *name, const apol_policy_t * policydb) { PyObject *dict = NULL; int error = 0; int rt = 0; size_t i; char *tmp = NULL; const char *lvl_name = NULL; apol_level_query_t *query = NULL; apol_vector_t *v = NULL; const qpol_level_t *level = NULL; apol_mls_level_t *ap_mls_lvl = NULL; qpol_policy_t *q = apol_policy_get_qpol(policydb); query = apol_level_query_create(); if (!query) goto cleanup; if (apol_level_query_set_sens(policydb, query, name)) goto cleanup; if (apol_level_get_by_query(policydb, query, &v)) goto cleanup; dict = PyDict_New(); if (!dict) goto err; for (i = 0; i < apol_vector_get_size(v); i++) { level = apol_vector_get_element(v, i); if (qpol_level_get_name(q, level, &lvl_name)) goto err; ap_mls_lvl = (apol_mls_level_t *) apol_mls_level_create_from_qpol_level_datum(policydb, level); tmp = apol_mls_level_render(policydb, ap_mls_lvl); apol_mls_level_destroy(&ap_mls_lvl); if (!tmp) goto cleanup; if (py_insert_string(dict, lvl_name, tmp)) goto err; free(tmp); tmp = NULL; if (rt) goto err; } if (name && !apol_vector_get_size(v)) { goto cleanup; } goto cleanup; err: error = errno; PyErr_SetString(PyExc_RuntimeError,strerror(error)); py_decref(dict); dict = NULL; cleanup: free(tmp); apol_level_query_destroy(&query); apol_vector_destroy(&v); errno = error; return dict; }
apol_vector_t *apol_mls_range_get_levels(const apol_policy_t * p, const apol_mls_range_t * range) { qpol_policy_t *q = apol_policy_get_qpol(p); apol_vector_t *v = NULL, *catv = NULL; const qpol_level_t *l; uint32_t low_value, high_value, value; int error = 0; qpol_iterator_t *iter = NULL, *catiter = NULL; if (p == NULL || range == NULL || range->low == NULL) { error = EINVAL; ERR(p, "%s", strerror(error)); goto err; } apol_mls_level_t *low_level, *high_level; low_level = range->low; if (range->high == NULL) { high_level = low_level; } else { high_level = range->high; } if (qpol_policy_get_level_by_name(q, apol_mls_level_get_sens(low_level), &l) < 0 || qpol_level_get_value(q, l, &low_value) < 0) { error = errno; goto err; } if (qpol_policy_get_level_by_name(q, apol_mls_level_get_sens(high_level), &l) < 0 || qpol_level_get_value(q, l, &high_value) < 0) { error = errno; goto err; } assert(low_value <= high_value); if ((v = apol_vector_create(mls_level_free)) == NULL) { error = errno; ERR(p, "%s", strerror(error)); goto err; } if (qpol_policy_get_level_iter(q, &iter) < 0) { error = errno; goto err; } for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { const char *name; apol_mls_level_t *ml; if (qpol_iterator_get_item(iter, (void **)&l) < 0 || qpol_level_get_value(q, l, &value) < 0 || qpol_level_get_name(q, l, &name) < 0) { error = errno; goto err; } if (value < low_value || value > high_value) { continue; } if ((ml = apol_mls_level_create()) == NULL || (apol_mls_level_set_sens(p, ml, name) < 0)) { error = errno; apol_mls_level_destroy(&ml); ERR(p, "%s", strerror(error)); goto err; } if (qpol_level_get_cat_iter(q, l, &catiter) < 0 || (catv = apol_vector_create_from_iter(catiter, NULL)) == NULL) { error = errno; goto err; } const apol_vector_t *high_cats = apol_mls_level_get_cats(high_level); for (size_t i = 0; i < apol_vector_get_size(high_cats); i++) { char *cat_name = apol_vector_get_element(high_cats, i); size_t j; /* do not add categories that are not members of the level */ if (apol_vector_get_index(catv, cat_name, mls_level_name_to_cat_comp, q, &j) < 0) { /* this category is not legal under the given policy */ continue; } if (apol_mls_level_append_cats(p, ml, cat_name) < 0) { error = errno; apol_mls_level_destroy(&ml); ERR(p, "%s", strerror(error)); goto err; } } qpol_iterator_destroy(&catiter); apol_vector_destroy(&catv); if (apol_vector_append(v, ml) < 0) { error = errno; apol_mls_level_destroy(&ml); ERR(p, "%s", strerror(error)); goto err; } } apol_vector_sort(v, mls_range_comp, q); qpol_iterator_destroy(&iter); qpol_iterator_destroy(&catiter); apol_vector_destroy(&catv); return v; err: qpol_iterator_destroy(&iter); qpol_iterator_destroy(&catiter); apol_vector_destroy(&v); apol_vector_destroy(&catv); errno = error; return NULL; }