level_diff.c File Reference


Detailed Description

Implementation for computing semantic differences in levels.

Author:
Jeremy A. Mowery jmowery@tresys.com

Jason Tang jtang@tresys.com

Copyright (C) 2007 Tresys Technology, LLC

This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.

This library 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 Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

Definition in file level_diff.c.

#include <config.h>
#include "poldiff_internal.h"
#include <apol/util.h>
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>

Go to the source code of this file.


Classes

struct  poldiff_level_summary

Functions

void poldiff_level_get_stats (const poldiff_t *diff, size_t stats[5])
 Get an array of statistics for the number of differences of each form for levels.
const apol_vector_tpoldiff_get_level_vector (const poldiff_t *diff)
 Get the vector of level differences from the level difference summary.
char * poldiff_level_to_string (const poldiff_t *diff, const void *level)
 Obtain a newly allocated string representation of a difference in a level.
char * poldiff_level_to_string_brief (const poldiff_t *diff, const poldiff_level_t *level)
 Allocate and return a string rendering of a poldiff_level_t, suitable for embedding within some other component's to_string function (e.g., a user's default level).
const char * poldiff_level_get_name (const poldiff_level_t *level)
 Get the name of the level (i.e., the sensitivity) from a level diff.
poldiff_form_e poldiff_level_get_form (const void *level)
 Get the form of difference from a level diff.
const apol_vector_tpoldiff_level_get_added_cats (const poldiff_level_t *level)
 Get a vector of categories added to the level.
const apol_vector_tpoldiff_level_get_removed_cats (const poldiff_level_t *level)
 Get a vector of categories removed from the level.
const apol_vector_tpoldiff_level_get_unmodified_cats (const poldiff_level_t *level)
 Get a vector of unmodified categories from the level.
poldiff_level_summary_tlevel_create (void)
 Allocate and return a new poldiff_level_summary_t object.
void level_destroy (poldiff_level_summary_t **ls)
 Deallocate all space associated with a poldiff_level_summary_t object, including the pointer itself.
int level_reset (poldiff_t *diff)
 Reset the state of all level differences.
int level_name_comp (const void *x, const void *y, void *arg)
 Comparison function for two levels from the same policy.
apol_vector_tlevel_get_items (poldiff_t *diff, const apol_policy_t *policy)
 Get a vector of all levels from the given policy, sorted by name.
int level_comp (const void *x, const void *y, const poldiff_t *diff)
 Compare two qpol_level_t objects, determining if they have the same level name or not.
poldiff_level_tmake_diff (const poldiff_t *diff, poldiff_form_e form, const char *name)
 Allocate and return a new level difference object.
apol_vector_tlevel_get_cats (const poldiff_t *diff, const apol_policy_t *p, const qpol_level_t *level)
 Given a level, return a vector of its allowed categories (in the form of strings).
int level_new_diff (poldiff_t *diff, poldiff_form_e form, const void *item)
 Create, initialize, and insert a new semantic difference entry for a level.
int level_cat_comp (const void *a, const void *b, void *data)
 Comparison function for two category names from the same policy.
int level_deep_diff (poldiff_t *diff, const void *x, const void *y)
 Compute the semantic difference of two levels for which the compare callback returns 0.
poldiff_level_tlevel_create_from_apol_mls_level (const apol_mls_level_t *level, poldiff_form_e form)
 Allocate and return a poldiff_level_t object.
void level_free (void *elem)
 Deallocate all space associated with a poldiff_level_t, including the pointer itself.
int level_deep_diff_apol_mls_levels (poldiff_t *diff, const apol_mls_level_t *level1, const apol_mls_level_t *level2, poldiff_level_t **orig_pl, poldiff_level_t **mod_pl)
 Perform a deep diff of two levels.
int level_deep_diff_cats (poldiff_t *diff, const apol_vector_t *v1, const apol_vector_t *v2, apol_vector_t **added, apol_vector_t **removed, apol_vector_t **unmodified)
 Calculate the differences between two sorted vectors of category names.

Function Documentation

void poldiff_level_get_stats const poldiff_t diff,
size_t  stats[5]
 

Get an array of statistics for the number of differences of each form for levels.

Parameters:
diff The policy difference structure from which to get the stats.
stats Array into which to write the numbers (array must be pre-allocated). The order of the values written to the array is as follows: number of items of form POLDIFF_FORM_ADDED, number of POLDIFF_FORM_REMOVED, number of POLDIFF_FORM_MODIFIED, number of POLDIFF_FORM_ADD_TYPE, and number of POLDIFF_FORM_REMOVE_TYPE.

Definition at line 43 of file level_diff.c.

References diff, ERR, poldiff::level_diffs, poldiff_level_summary::num_added, poldiff_level_summary::num_modified, poldiff_level_summary::num_removed, and poldiff_t.

00044 {
00045         if (diff == NULL || stats == NULL) {
00046                 ERR(diff, "%s", strerror(EINVAL));
00047                 errno = EINVAL;
00048                 return;
00049         }
00050         stats[0] = diff->level_diffs->num_added;
00051         stats[1] = diff->level_diffs->num_removed;
00052         stats[2] = diff->level_diffs->num_modified;
00053         stats[3] = 0;
00054         stats[4] = 0;
00055 }

const apol_vector_t* poldiff_get_level_vector const poldiff_t diff  ) 
 

Get the vector of level differences from the level difference summary.

Parameters:
diff The policy difference structure associated with the level difference summary.
Returns:
A vector of elements of type poldiff_level_t, or NULL on error. The caller should not destroy the vector returned. If the call fails, errno will be set.

Definition at line 57 of file level_diff.c.

References apol_vector_t, diff, poldiff_level_summary::diffs, poldiff::level_diffs, and poldiff_t.

Referenced by build_level_vecs().

00058 {
00059         if (diff == NULL) {
00060                 errno = EINVAL;
00061                 return NULL;
00062         }
00063         return diff->level_diffs->diffs;
00064 }

char* poldiff_level_to_string const poldiff_t diff,
const void *  level
 

Obtain a newly allocated string representation of a difference in a level.

Parameters:
diff The policy difference structure associated with the level.
level The level from which to generate the string.
Returns:
A string representation of level difference; the caller is responsible for free()ing this string. On error, return NULL and set errno.

Definition at line 66 of file level_diff.c.

References poldiff_level::added_cats, apol_str_append(), apol_str_appendf(), apol_vector_get_element(), apol_vector_get_size(), diff, ERR, poldiff_level::form, level, poldiff_level::name, POLDIFF_FORM_ADDED, POLDIFF_FORM_MODIFIED, POLDIFF_FORM_REMOVED, poldiff_level_t, poldiff_t, and poldiff_level::removed_cats.

00067 {
00068         poldiff_level_t *l = (poldiff_level_t *) level;
00069         size_t num_added, num_removed, len = 0, i;
00070         char *s = NULL, *cat;
00071         if (diff == NULL || level == NULL) {
00072                 ERR(diff, "%s", strerror(EINVAL));
00073                 errno = EINVAL;
00074                 return NULL;
00075         }
00076         num_added = apol_vector_get_size(l->added_cats);
00077         num_removed = apol_vector_get_size(l->removed_cats);
00078         switch (l->form) {
00079         case POLDIFF_FORM_ADDED:
00080         {
00081                 if (apol_str_appendf(&s, &len, "+ %s", l->name) < 0) {
00082                         break;
00083                 }
00084                 return s;
00085         }
00086         case POLDIFF_FORM_REMOVED:
00087         {
00088                 if (apol_str_appendf(&s, &len, "- %s", l->name) < 0) {
00089                         break;
00090                 }
00091                 return s;
00092         }
00093         case POLDIFF_FORM_MODIFIED:
00094         {
00095                 if (apol_str_appendf(&s, &len, "* %s (", l->name) < 0) {
00096                         break;
00097                 }
00098                 if (num_added > 0) {
00099                         if (apol_str_appendf(&s, &len, "%zd Added %s", num_added, (num_added == 1 ? "Category" : "Categories")) < 0) {
00100                                 break;
00101                         }
00102                 }
00103                 if (num_removed > 0) {
00104                         if (apol_str_appendf
00105                             (&s, &len, "%s%zd Removed %s", (num_added > 0 ? ", " : ""), num_removed,
00106                              (num_removed == 1 ? "Category" : "Categories")) < 0) {
00107                                 break;
00108                         }
00109                 }
00110                 if (apol_str_append(&s, &len, ")\n") < 0) {
00111                         break;
00112                 }
00113                 for (i = 0; i < apol_vector_get_size(l->added_cats); i++) {
00114                         cat = (char *)apol_vector_get_element(l->added_cats, i);
00115                         if (apol_str_appendf(&s, &len, "\t+ %s\n", cat) < 0) {
00116                                 goto err;
00117                         }
00118                 }
00119                 for (i = 0; i < apol_vector_get_size(l->removed_cats); i++) {
00120                         cat = (char *)apol_vector_get_element(l->removed_cats, i);
00121                         if (apol_str_appendf(&s, &len, "\t- %s\n", cat) < 0) {
00122                                 goto err;
00123                         }
00124                 }
00125                 return s;
00126         }
00127         default:
00128         {
00129                 ERR(diff, "%s", strerror(ENOTSUP));
00130                 errno = ENOTSUP;
00131                 return NULL;
00132         }
00133         }
00134       err:
00135         /* if this is reached then an error occurred */
00136         free(s);
00137         ERR(diff, "%s", strerror(ENOMEM));
00138         errno = ENOMEM;
00139         return NULL;
00140 }

char* poldiff_level_to_string_brief const poldiff_t diff,
const poldiff_level_t level
 

Allocate and return a string rendering of a poldiff_level_t, suitable for embedding within some other component's to_string function (e.g., a user's default level).

Parameters:
diff Poldiff object, for error handling.
level Level diff object to render.
Returns:
String rendering of level, or NULL upon error. Caller must free() string afterwards.

Definition at line 142 of file level_diff.c.

References poldiff_level::added_cats, apol_str_append(), apol_str_appendf(), apol_vector_get_element(), apol_vector_get_size(), diff, ERR, poldiff_level::form, level, poldiff_level::name, POLDIFF_FORM_ADDED, POLDIFF_FORM_MODIFIED, POLDIFF_FORM_REMOVED, poldiff_level_t, poldiff_t, poldiff_level::removed_cats, and poldiff_level::unmodified_cats.

Referenced by poldiff_range_to_string_brief(), result_item_print_modified_range(), result_item_user_print_modified(), and user_to_modified_string().

00143 {
00144         char *s = NULL, t, *cat, *sep = "";
00145         int show_cat_sym = 0;
00146         size_t len = 0, i;
00147         switch (level->form) {
00148         case POLDIFF_FORM_ADDED:
00149                 t = '+';
00150                 break;
00151         case POLDIFF_FORM_REMOVED:
00152                 t = '-';
00153                 break;
00154         case POLDIFF_FORM_MODIFIED:
00155                 t = '*';
00156                 show_cat_sym = 1;
00157                 break;
00158         default:
00159                 /* don't show unmodified levels */
00160                 if ((s = strdup("")) == NULL) {
00161                         ERR(diff, "%s", strerror(errno));
00162                         return NULL;
00163                 }
00164                 return s;
00165         }
00166         if (apol_str_appendf(&s, &len, "%c %s", t, level->name) < 0) {
00167                 ERR(diff, "%s", strerror(errno));
00168                 return NULL;
00169         }
00170         if ((level->unmodified_cats != NULL && apol_vector_get_size(level->unmodified_cats) > 0) ||
00171             (level->added_cats != NULL && apol_vector_get_size(level->added_cats) > 0) ||
00172             (level->removed_cats != NULL && apol_vector_get_size(level->removed_cats) > 0)) {
00173                 if (apol_str_append(&s, &len, " : ") < 0) {
00174                         ERR(diff, "%s", strerror(errno));
00175                         return NULL;
00176                 }
00177                 for (i = 0; level->unmodified_cats != NULL && i < apol_vector_get_size(level->unmodified_cats); i++) {
00178                         cat = apol_vector_get_element(level->unmodified_cats, i);
00179                         if (apol_str_appendf(&s, &len, "%s%s", sep, cat) < 0) {
00180                                 ERR(diff, "%s", strerror(errno));
00181                                 return NULL;
00182                         }
00183                         sep = ",";
00184                 }
00185                 for (i = 0; level->added_cats != NULL && i < apol_vector_get_size(level->added_cats); i++) {
00186                         cat = apol_vector_get_element(level->added_cats, i);
00187                         if (apol_str_appendf(&s, &len, "%s%s%s", sep, (show_cat_sym ? "+" : ""), cat) < 0) {
00188                                 ERR(diff, "%s", strerror(errno));
00189                                 return NULL;
00190                         }
00191                         sep = ",";
00192                 }
00193                 for (i = 0; level->removed_cats != NULL && i < apol_vector_get_size(level->removed_cats); i++) {
00194                         cat = apol_vector_get_element(level->removed_cats, i);
00195                         if (apol_str_appendf(&s, &len, "%s%s%s", sep, (show_cat_sym ? "-" : ""), cat) < 0) {
00196                                 ERR(diff, "%s", strerror(errno));
00197                                 return NULL;
00198                         }
00199                         sep = ",";
00200                 }
00201         }
00202         if (apol_str_append(&s, &len, "\n") < 0) {
00203                 ERR(diff, "%s", strerror(errno));
00204                 return NULL;
00205         }
00206         return s;
00207 }

const char* poldiff_level_get_name const poldiff_level_t level  ) 
 

Get the name of the level (i.e., the sensitivity) from a level diff.

Parameters:
level The level from which to get the name.
Returns:
Name of the level on success and NULL on failure; if the call fails, errno will be set. The caller should not free the returned string.

Definition at line 209 of file level_diff.c.

References level, poldiff_level::name, and poldiff_level_t.

Referenced by level_to_string(), and modified_mls_range_to_string().

00210 {
00211         if (level == NULL) {
00212                 errno = EINVAL;
00213                 return NULL;
00214         }
00215 
00216         return level->name;
00217 }

poldiff_form_e poldiff_level_get_form const void *  level  ) 
 

Get the form of difference from a level diff.

Parameters:
level The level from which to get the difference form.
Returns:
The form of difference (one of POLDIFF_FORM_*) or POLDIFF_FORM_NONE on error. If the call fails, errno will be set.

Definition at line 219 of file level_diff.c.

References poldiff_level::form, level, poldiff_form_e, and poldiff_level_t.

Referenced by mls_user_to_string(), modified_mls_range_to_string(), result_item_print_modified_range(), and result_item_user_print_modified().

00220 {
00221         if (level == NULL) {
00222                 errno = EINVAL;
00223                 return POLDIFF_FORM_NONE;
00224         }
00225 
00226         return ((const poldiff_level_t *)level)->form;
00227 }

const apol_vector_t* poldiff_level_get_added_cats const poldiff_level_t level  ) 
 

Get a vector of categories added to the level.

These will be sorted in the same order as given by the modified policy. If the level was added by the modified policy then this vector will hold all of the categories.

Parameters:
level The level diff from which to get the categories.
Returns:
A vector of category names (type char *) that are assigned to the level in the modified policy. If no categories were added the size of the returned vector will be 0. The caller must not modify this vector. On error, errno will be set.

Definition at line 229 of file level_diff.c.

References poldiff_level::added_cats, apol_vector_t, level, and poldiff_level_t.

Referenced by level_to_string(), and modified_mls_range_to_string().

00230 {
00231         if (level == NULL) {
00232                 errno = EINVAL;
00233                 return NULL;
00234         }
00235         return level->added_cats;
00236 }

const apol_vector_t* poldiff_level_get_removed_cats const poldiff_level_t level  ) 
 

Get a vector of categories removed from the level.

These will be sorted in the same order as given by the original policy. If the level was removed by the modified policy then this vector will hold all of the categories.

Parameters:
level The level diff from which to get the category vector.
Returns:
A vector of category names (type char *) that are assigned to the level in the original policy. If no categories were removed the size of the returned vector will be 0. The caller must not destroy this vector. On error, errno will be set.

Definition at line 238 of file level_diff.c.

References apol_vector_t, level, poldiff_level_t, and poldiff_level::removed_cats.

Referenced by level_to_string(), and modified_mls_range_to_string().

00239 {
00240         if (level == NULL) {
00241                 errno = EINVAL;
00242                 return NULL;
00243         }
00244 
00245         return level->removed_cats;
00246 }

const apol_vector_t* poldiff_level_get_unmodified_cats const poldiff_level_t level  ) 
 

Get a vector of unmodified categories from the level.

These will be sorted in the same order as given by the original policy.

Parameters:
level The level diff from which to get the category vector.
Returns:
A vector of category names (type char *) that are assigned to the level in the original policy. If no categories were removed the size of the returned vector will be 0. The caller must not destroy this vector. On error, errno will be set.

Definition at line 248 of file level_diff.c.

References apol_vector_t, level, poldiff_level_t, and poldiff_level::unmodified_cats.

Referenced by modified_mls_range_to_string().

00249 {
00250         if (level == NULL) {
00251                 errno = EINVAL;
00252                 return NULL;
00253         }
00254 
00255         return level->unmodified_cats;
00256 }

poldiff_level_summary_t* level_create void   ) 
 

Allocate and return a new poldiff_level_summary_t object.

Returns:
A new level summary. The caller must call level_destroy() afterwards. On error, return NULL and set errno.

Definition at line 258 of file level_diff.c.

References apol_vector_create(), poldiff_level_summary::diffs, level_destroy(), level_free(), and poldiff_level_summary_t.

Referenced by level_reset(), and poldiff_create().

00259 {
00260         poldiff_level_summary_t *ls = calloc(1, sizeof(poldiff_level_summary_t));
00261         if (ls == NULL)
00262                 return NULL;
00263         if ((ls->diffs = apol_vector_create(level_free)) == NULL) {
00264                 level_destroy(&ls);
00265                 return NULL;
00266         }
00267         return ls;
00268 }

void level_destroy poldiff_level_summary_t **  ls  ) 
 

Deallocate all space associated with a poldiff_level_summary_t object, including the pointer itself.

If the pointer is already NULL then do nothing.

Parameters:
ls Reference to a level summary to destroy. The pointer will be set to NULL afterwards.

Definition at line 270 of file level_diff.c.

References apol_vector_destroy(), and poldiff_level_summary_t.

Referenced by level_create(), level_reset(), and poldiff_destroy().

00271 {
00272         if (ls == NULL || *ls == NULL)
00273                 return;
00274         apol_vector_destroy(&(*ls)->diffs);
00275         free(*ls);
00276         *ls = NULL;
00277 }

int level_reset poldiff_t diff  ) 
 

Reset the state of all level differences.

Parameters:
diff The policy difference structure containing the differences to reset.
Returns:
0 on success and < 0 on error; if the call fails, errno will be set and the user should call poldiff_destroy() on diff.

Definition at line 279 of file level_diff.c.

References diff, ERR, level_create(), level_destroy(), poldiff::level_diffs, and poldiff_t.

00280 {
00281         int error = 0;
00282 
00283         if (diff == NULL) {
00284                 ERR(diff, "%s", strerror(EINVAL));
00285                 errno = EINVAL;
00286                 return -1;
00287         }
00288 
00289         level_destroy(&diff->level_diffs);
00290         diff->level_diffs = level_create();
00291         if (diff->level_diffs == NULL) {
00292                 error = errno;
00293                 ERR(diff, "%s", strerror(error));
00294                 errno = error;
00295                 return -1;
00296         }
00297 
00298         return 0;
00299 }

int level_name_comp const void *  x,
const void *  y,
void *  arg
[static]
 

Comparison function for two levels from the same policy.

Definition at line 304 of file level_diff.c.

References apol_policy_get_qpol(), apol_policy_t, qpol_level_get_name(), qpol_level_t, and qpol_policy_t.

Referenced by level_get_items().

00305 {
00306         const qpol_level_t *s1 = x;
00307         const qpol_level_t *s2 = y;
00308         apol_policy_t *p = arg;
00309         qpol_policy_t *q = apol_policy_get_qpol(p);
00310         const char *name1, *name2;
00311 
00312         if (qpol_level_get_name(q, s1, &name1) < 0 || qpol_level_get_name(q, s2, &name2) < 0)
00313                 return 0;
00314         return strcmp(name1, name2);
00315 }

apol_vector_t* level_get_items poldiff_t diff,
const apol_policy_t policy
 

Get a vector of all levels from the given policy, sorted by name.

Parameters:
diff Policy diff error handler.
policy The policy from which to get the items.
Returns:
a newly allocated vector of all levels. The caller is responsible for calling apol_vector_destroy() afterwards. On error, return NULL and set errno.

Definition at line 317 of file level_diff.c.

References apol_policy_get_qpol(), apol_policy_t, apol_vector_create_from_iter(), apol_vector_sort(), apol_vector_t, diff, ERR, level_name_comp(), poldiff_t, qpol_iterator_destroy(), qpol_iterator_t, qpol_policy_get_level_iter(), and qpol_policy_t.

00318 {
00319         qpol_iterator_t *iter = NULL;
00320         apol_vector_t *v = NULL;
00321         qpol_policy_t *q = apol_policy_get_qpol(policy);
00322         int error = 0;
00323         if (qpol_policy_get_level_iter(q, &iter) < 0) {
00324                 return NULL;
00325         }
00326         v = apol_vector_create_from_iter(iter, NULL);
00327         if (v == NULL) {
00328                 error = errno;
00329                 ERR(diff, "%s", strerror(error));
00330                 qpol_iterator_destroy(&iter);
00331                 errno = error;
00332                 return NULL;
00333         }
00334         qpol_iterator_destroy(&iter);
00335         apol_vector_sort(v, level_name_comp, (void *)policy);
00336         return v;
00337 }

int level_comp const void *  x,
const void *  y,
const poldiff_t diff
 

Compare two qpol_level_t objects, determining if they have the same level name or not.

Parameters:
x The level from the original policy.
y The level from the modified policy.
diff The policy difference structure associated with both policies.
Returns:
< 0, 0, or > 0 if level x is respectively less than, equal to, or greater than level y.

Definition at line 339 of file level_diff.c.

References diff, poldiff::mod_qpol, poldiff::orig_qpol, poldiff_t, qpol_level_get_name(), and qpol_level_t.

00340 {
00341         const qpol_level_t *l1 = x;
00342         const qpol_level_t *l2 = y;
00343         const char *name1, *name2;
00344         if (qpol_level_get_name(diff->orig_qpol, l1, &name1) < 0 || qpol_level_get_name(diff->mod_qpol, l2, &name2) < 0) {
00345                 return 0;
00346         }
00347         return strcmp(name1, name2);
00348 }

poldiff_level_t* make_diff const poldiff_t diff,
poldiff_form_e  form,
const char *  name
[static]
 

Allocate and return a new level difference object.

Parameters:
diff Policy diff error handler.
form Form of the difference.
name Name of the level that is different.
Returns:
A newly allocated and initialized diff, or NULL upon error. The caller is responsible for calling level_free() upon the returned value.

Definition at line 361 of file level_diff.c.

References apol_vector_create(), diff, ERR, poldiff_user::form, level_free(), poldiff_level_t, and poldiff_t.

00362 {
00363         poldiff_level_t *pl;
00364         int error;
00365         if ((pl = calloc(1, sizeof(*pl))) == NULL || (pl->name = strdup(name)) == NULL ||
00366             (pl->added_cats = apol_vector_create(free)) == NULL ||
00367             (pl->removed_cats = apol_vector_create(free)) == NULL || (pl->unmodified_cats = apol_vector_create(free)) == NULL) {
00368                 error = errno;
00369                 level_free(pl);
00370                 ERR(diff, "%s", strerror(error));
00371                 errno = error;
00372                 return NULL;
00373         }
00374         pl->form = form;
00375         return pl;
00376 }

apol_vector_t* level_get_cats const poldiff_t diff,
const apol_policy_t p,
const qpol_level_t level
[static]
 

Given a level, return a vector of its allowed categories (in the form of strings).

These will be sorted in policy order.

Parameters:
diff Policy diff error handler.
p Policy from which the level came.
level Level whose categories to get.
Returns:
Vector of category strings for the level. The caller is responsible for calling apol_vector_destroy(). On error, return NULL.

Definition at line 390 of file level_diff.c.

References apol_policy_get_qpol(), apol_policy_t, apol_vector_append(), apol_vector_create(), apol_vector_destroy(), apol_vector_t, diff, ERR, level, poldiff_t, qpol_cat_get_name(), qpol_cat_t, qpol_iterator_destroy(), qpol_iterator_end(), qpol_iterator_get_item(), qpol_iterator_next(), qpol_iterator_t, qpol_level_get_cat_iter(), and qpol_policy_t.

Referenced by level_deep_diff(), and level_new_diff().

00391 {
00392         qpol_iterator_t *iter = NULL;
00393         const qpol_cat_t *cat;
00394         const char *cat_name;
00395         apol_vector_t *v = NULL;
00396         qpol_policy_t *q = apol_policy_get_qpol(p);
00397         int retval = -1, error = 0;
00398 
00399         if ((v = apol_vector_create(NULL)) == NULL) {
00400                 ERR(diff, "%s", strerror(errno));
00401                 goto cleanup;
00402         }
00403         if (qpol_level_get_cat_iter(q, level, &iter) < 0) {
00404                 goto cleanup;
00405         }
00406         for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
00407                 if (qpol_iterator_get_item(iter, (void **)&cat) < 0 || qpol_cat_get_name(q, cat, &cat_name)) {
00408                         error = errno;
00409                         goto cleanup;
00410                 }
00411                 if (apol_vector_append(v, (void *)cat_name) < 0) {
00412                         error = errno;
00413                         ERR(diff, "%s", strerror(error));
00414                         goto cleanup;
00415                 }
00416         }
00417 
00418         retval = 0;
00419       cleanup:
00420         qpol_iterator_destroy(&iter);
00421         if (retval < 0) {
00422                 apol_vector_destroy(&v);
00423                 errno = error;
00424                 return NULL;
00425         }
00426         return v;
00427 }

int level_new_diff poldiff_t diff,
poldiff_form_e  form,
const void *  item
 

Create, initialize, and insert a new semantic difference entry for a level.

Parameters:
diff The policy difference structure to which to add the entry.
form The form of the difference.
item Item for which the entry is being created.
Returns:
0 on success and < 0 on error; if the call fails, set errno and leave the policy difference structure unchanged.

Definition at line 429 of file level_diff.c.

References poldiff_level::added_cats, apol_policy_t, apol_str_strdup(), apol_vector_append(), apol_vector_create_from_vector(), apol_vector_destroy(), apol_vector_t, diff, poldiff_level_summary::diffs, ERR, poldiff::level_diffs, level_free(), level_get_cats(), make_diff(), poldiff::mod_pol, poldiff::mod_qpol, poldiff_level_summary::num_added, poldiff_level_summary::num_removed, poldiff::orig_pol, poldiff::orig_qpol, poldiff_level_t, poldiff_t, qpol_level_get_name(), qpol_level_t, qpol_policy_t, and poldiff_level::removed_cats.

00430 {
00431         const qpol_level_t *l = item;
00432         const char *name = NULL;
00433         poldiff_level_t *pl = NULL;
00434         apol_policy_t *p;
00435         qpol_policy_t *q;
00436         apol_vector_t *v = NULL;
00437         int error = 0, retval = -1;
00438         if (form == POLDIFF_FORM_ADDED) {
00439                 p = diff->mod_pol;
00440                 q = diff->mod_qpol;
00441         } else {
00442                 p = diff->orig_pol;
00443                 q = diff->orig_qpol;
00444         }
00445         if (qpol_level_get_name(q, l, &name) < 0 || (pl = make_diff(diff, form, name)) == NULL) {
00446                 error = errno;
00447                 goto cleanup;
00448         }
00449         if ((v = level_get_cats(diff, p, l)) == NULL) {
00450                 error = errno;
00451                 ERR(diff, "%s", strerror(error));
00452                 goto cleanup;
00453         }
00454         if (form == POLDIFF_FORM_ADDED) {
00455                 apol_vector_destroy(&pl->added_cats);
00456                 if ((pl->added_cats = apol_vector_create_from_vector(v, apol_str_strdup, NULL, free)) == NULL) {
00457                         error = errno;
00458                         ERR(diff, "%s", strerror(error));
00459                         goto cleanup;
00460                 }
00461         } else if (form == POLDIFF_FORM_REMOVED) {
00462                 apol_vector_destroy(&pl->removed_cats);
00463                 if ((pl->removed_cats = apol_vector_create_from_vector(v, apol_str_strdup, NULL, free)) == NULL) {
00464                         error = errno;
00465                         ERR(diff, "%s", strerror(error));
00466                         goto cleanup;
00467                 }
00468         }
00469         if (apol_vector_append(diff->level_diffs->diffs, pl) < 0) {
00470                 error = errno;
00471                 ERR(diff, "%s", strerror(error));
00472                 goto cleanup;
00473         }
00474         if (form == POLDIFF_FORM_ADDED) {
00475                 diff->level_diffs->num_added++;
00476         } else {
00477                 diff->level_diffs->num_removed++;
00478         }
00479         retval = 0;
00480       cleanup:
00481         apol_vector_destroy(&v);
00482         if (retval < 0) {
00483                 level_free(pl);
00484                 errno = error;
00485         }
00486         return retval;
00487 }

int level_cat_comp const void *  a,
const void *  b,
void *  data
[static]
 

Comparison function for two category names from the same policy.

Parameters:
a Name of a category.
b Name of another category.
data qpol policy from which the categories originate.
Returns:
Less than zero, zero, or greater than zero based upon the categories' order within the policy.

Definition at line 499 of file level_diff.c.

References qpol_cat_get_value(), qpol_cat_t, qpol_policy_get_cat_by_name(), and qpol_policy_t.

Referenced by level_deep_diff(), and level_deep_diff_apol_mls_levels().

00500 {
00501         const char *name1 = (const char *)a;
00502         const char *name2 = (const char *)b;
00503         qpol_policy_t *q = (qpol_policy_t *) data;
00504         const qpol_cat_t *cat1, *cat2;
00505         qpol_policy_get_cat_by_name(q, name1, &cat1);
00506         qpol_policy_get_cat_by_name(q, name2, &cat2);
00507         assert(cat1 != NULL && cat2 != NULL);
00508         uint32_t val1, val2;
00509         qpol_cat_get_value(q, cat1, &val1);
00510         qpol_cat_get_value(q, cat2, &val2);
00511         return val1 - val2;
00512 }

int level_deep_diff poldiff_t diff,
const void *  x,
const void *  y
 

Compute the semantic difference of two levels for which the compare callback returns 0.

If a difference is found then allocate, initialize, and insert a new semantic difference entry for that level.

Parameters:
diff The policy difference structure associated with both levels and to which to add an entry if needed.
x The level from the original policy.
y The level from the modified policy.
Returns:
0 on success and < 0 on error; if the call fails, set errno and leave the policy difference structure unchanged.

Definition at line 514 of file level_diff.c.

References poldiff_level::added_cats, apol_str_strcmp(), apol_str_strdup(), apol_vector_append(), apol_vector_create_from_vector(), apol_vector_destroy(), apol_vector_sort(), apol_vector_t, diff, poldiff_level_summary::diffs, ERR, level_cat_comp(), level_deep_diff_cats(), poldiff::level_diffs, level_free(), level_get_cats(), make_diff(), poldiff::mod_pol, poldiff::mod_qpol, poldiff_level_summary::num_modified, poldiff::orig_pol, poldiff::orig_qpol, POLDIFF_FORM_MODIFIED, poldiff_level_t, poldiff_t, qpol_level_get_name(), qpol_level_t, poldiff_level::removed_cats, and poldiff_level::unmodified_cats.

00515 {
00516         const qpol_level_t *l1 = x;
00517         const qpol_level_t *l2 = y;
00518         apol_vector_t *v1 = NULL, *v2 = NULL;
00519         apol_vector_t *added = NULL, *removed = NULL, *unmodified = NULL;
00520         const char *name;
00521         poldiff_level_t *l = NULL;
00522         int retval = -1, error = 0, compval;
00523 
00524         if (qpol_level_get_name(diff->orig_qpol, l1, &name) < 0 ||
00525             (v1 = level_get_cats(diff, diff->orig_pol, l1)) == NULL || (v2 = level_get_cats(diff, diff->mod_pol, l2)) == NULL) {
00526                 error = errno;
00527                 goto cleanup;
00528         }
00529         apol_vector_sort(v1, apol_str_strcmp, NULL);
00530         apol_vector_sort(v2, apol_str_strcmp, NULL);
00531         compval = level_deep_diff_cats(diff, v1, v2, &added, &removed, &unmodified);
00532         if (compval < 0) {
00533                 error = errno;
00534                 goto cleanup;
00535         } else if (compval > 0) {
00536                 if ((l = make_diff(diff, POLDIFF_FORM_MODIFIED, name)) == NULL) {
00537                         error = errno;
00538                         goto cleanup;
00539                 }
00540                 apol_vector_destroy(&l->added_cats);
00541                 apol_vector_destroy(&l->removed_cats);
00542                 apol_vector_destroy(&l->unmodified_cats);
00543                 if ((l->added_cats = apol_vector_create_from_vector(added, apol_str_strdup, NULL, free)) == NULL ||
00544                     (l->removed_cats = apol_vector_create_from_vector(removed, apol_str_strdup, NULL, free)) == NULL ||
00545                     (l->unmodified_cats = apol_vector_create_from_vector(unmodified, apol_str_strdup, NULL, free)) == NULL) {
00546                         error = errno;
00547                         ERR(diff, "%s", strerror(error));
00548                         goto cleanup;
00549                 }
00550                 apol_vector_sort(l->removed_cats, level_cat_comp, diff->orig_qpol);
00551                 apol_vector_sort(l->added_cats, level_cat_comp, diff->mod_qpol);
00552                 apol_vector_sort(l->unmodified_cats, level_cat_comp, diff->orig_qpol);
00553                 if (apol_vector_append(diff->level_diffs->diffs, l) < 0) {
00554                         error = errno;
00555                         ERR(diff, "%s", strerror(error));
00556                         goto cleanup;
00557                 }
00558                 diff->level_diffs->num_modified++;
00559         }
00560         retval = 0;
00561       cleanup:
00562         apol_vector_destroy(&v1);
00563         apol_vector_destroy(&v2);
00564         apol_vector_destroy(&added);
00565         apol_vector_destroy(&removed);
00566         apol_vector_destroy(&unmodified);
00567         if (retval != 0) {
00568                 level_free(l);
00569         }
00570         errno = error;
00571         return retval;
00572 }

poldiff_level_t* level_create_from_apol_mls_level const apol_mls_level_t level,
poldiff_form_e  form
 

Allocate and return a poldiff_level_t object.

If the form is added or removed, set that respective vector to be all of the categories from the given level.

Parameters:
level Level object to use as a template.
form Form of difference for the level.
Returns:
Initialized level, or NULL upon error. Caller must call level_free() upon the returned value.

Definition at line 574 of file level_diff.c.

References apol_mls_level_get_cats(), apol_mls_level_get_sens(), apol_mls_level_t, apol_str_strdup(), apol_vector_create_from_vector(), apol_vector_create_with_capacity(), apol_vector_t, level, level_free(), and poldiff_level_t.

Referenced by range_deep_diff(), and user_deep_diff_default_levels().

00575 {
00576         const char *sens = apol_mls_level_get_sens(level);
00577         const apol_vector_t *cats = apol_mls_level_get_cats(level);
00578         poldiff_level_t *pl = NULL;
00579         apol_vector_t **target;
00580         if ((pl = calloc(1, sizeof(*pl))) == NULL ||
00581             (pl->name = strdup(sens)) == NULL || (pl->unmodified_cats = apol_vector_create_with_capacity(1, free)) == NULL) {
00582                 level_free(pl);
00583                 return NULL;;
00584         }
00585         pl->form = form;
00586         if (form == POLDIFF_FORM_ADDED) {
00587                 if ((pl->removed_cats = apol_vector_create_with_capacity(1, free)) == NULL) {
00588                         level_free(pl);
00589                         return NULL;
00590                 }
00591                 target = &pl->added_cats;
00592         } else if (form == POLDIFF_FORM_REMOVED) {
00593                 if ((pl->added_cats = apol_vector_create_with_capacity(1, free)) == NULL) {
00594                         level_free(pl);
00595                         return NULL;
00596                 }
00597                 target = &pl->removed_cats;
00598         } else {
00599                 if ((pl->added_cats = apol_vector_create_with_capacity(1, free)) == NULL ||
00600                     (pl->removed_cats = apol_vector_create_with_capacity(1, free)) == NULL) {
00601                         level_free(pl);
00602                         return NULL;
00603                 }
00604                 return pl;
00605         }
00606         if ((*target = apol_vector_create_from_vector(cats, apol_str_strdup, NULL, free)) == NULL) {
00607                 level_free(pl);
00608                 return NULL;
00609         }
00610         return pl;
00611 }

void level_free void *  elem  ) 
 

Deallocate all space associated with a poldiff_level_t, including the pointer itself.

Parameters:
elem Pointer to a poldiff_level_t object. If NULL then do nothing.

Definition at line 613 of file level_diff.c.

References poldiff_level::added_cats, apol_vector_destroy(), poldiff_level::name, poldiff_level_t, poldiff_level::removed_cats, and poldiff_level::unmodified_cats.

Referenced by level_create(), level_create_from_apol_mls_level(), level_deep_diff(), level_deep_diff_apol_mls_levels(), level_new_diff(), make_diff(), range_create(), range_deep_diff(), user_deep_diff_default_levels(), and user_free().

00614 {
00615         poldiff_level_t *s = elem;
00616         if (!elem)
00617                 return;
00618         free(s->name);
00619         apol_vector_destroy(&s->added_cats);
00620         apol_vector_destroy(&s->removed_cats);
00621         apol_vector_destroy(&s->unmodified_cats);
00622         free(s);
00623 }

int level_deep_diff_apol_mls_levels poldiff_t diff,
const apol_mls_level_t level1,
const apol_mls_level_t level2,
poldiff_level_t **  orig_pl,
poldiff_level_t **  mod_pl
 

Perform a deep diff of two levels.

This will first compare the sensitivity names; if they match then it compares the vectors of category names. If the sensitivities do not match, then generate two poldiff_level_ts, one for the original level and one for modified level. If they do match then create just one poldiff_level_t and write it to orig_pl.

Parameters:
diff Poldiff object, used for error reporting and for sorting the categories to policy order.
level1 Original level.
level2 Modified level.
orig_pl Destination to where to write the poldiff_level_t, if the sensitivites do not match or if the categories do not match.
mod_pl Destination to where to write the poldiff_level_t, if the sensitivities do not match.
Returns:
0 on success, < 0 on error.

Definition at line 625 of file level_diff.c.

References apol_mls_level_get_cats(), apol_mls_level_get_sens(), apol_mls_level_t, apol_str_strdup(), apol_vector_create_from_vector(), apol_vector_destroy(), apol_vector_sort(), apol_vector_t, diff, ERR, poldiff_level::form, level_cat_comp(), level_deep_diff_cats(), level_free(), make_diff(), poldiff::mod_qpol, poldiff::orig_qpol, POLDIFF_FORM_ADDED, POLDIFF_FORM_REMOVED, poldiff_level_t, poldiff_t, and poldiff_level::removed_cats.

Referenced by range_deep_diff(), and user_deep_diff_default_levels().

00627 {
00628         poldiff_level_t *u1 = NULL, *u2 = NULL;
00629         apol_vector_t *added = NULL, *removed = NULL, *unmodified = NULL;
00630         const char *sens1 = apol_mls_level_get_sens(level1);
00631         const apol_vector_t *cats1 = apol_mls_level_get_cats(level1);
00632         const char *sens2 = apol_mls_level_get_sens(level2);
00633         const apol_vector_t *cats2 = apol_mls_level_get_cats(level2);
00634         int retval = -1, compval;
00635 
00636         *orig_pl = *mod_pl = NULL;
00637         if (strcmp(sens1, sens2) != 0) {
00638                 /* sensitivities do not match, so don't check categories */
00639                 if ((u1 = make_diff(diff, POLDIFF_FORM_REMOVED, sens1)) == NULL ||
00640                     (u2 = make_diff(diff, POLDIFF_FORM_ADDED, sens2)) == NULL) {
00641                         ERR(diff, "%s", strerror(errno));
00642                         level_free(u1);
00643                         level_free(u2);
00644                         return -1;
00645                 }
00646                 apol_vector_destroy(&u1->removed_cats);
00647                 apol_vector_destroy(&u2->added_cats);
00648                 if ((u1->removed_cats = apol_vector_create_from_vector(cats1, apol_str_strdup, NULL, free)) == NULL ||
00649                     (u2->added_cats = apol_vector_create_from_vector(cats2, apol_str_strdup, NULL, free)) == NULL) {
00650                         ERR(diff, "%s", strerror(errno));
00651                         level_free(u1);
00652                         level_free(u2);
00653                         return -1;
00654                 }
00655                 apol_vector_sort(u1->removed_cats, level_cat_comp, diff->orig_qpol);
00656                 apol_vector_sort(u2->added_cats, level_cat_comp, diff->mod_qpol);
00657                 *orig_pl = u1;
00658                 *mod_pl = u2;
00659                 return 0;
00660         }
00661 
00662         compval = level_deep_diff_cats(diff, cats1, cats2, &added, &removed, &unmodified);
00663         if (compval < 0) {
00664                 goto cleanup;
00665         } else if (compval > 0) {
00666                 if ((u1 = calloc(1, sizeof(*u1))) == NULL || (u1->name = strdup(sens1)) == NULL ||
00667                     (u1->added_cats = apol_vector_create_from_vector(added, apol_str_strdup, NULL, free)) == NULL ||
00668                     (u1->removed_cats = apol_vector_create_from_vector(removed, apol_str_strdup, NULL, free)) == NULL ||
00669                     (u1->unmodified_cats = apol_vector_create_from_vector(unmodified, apol_str_strdup, NULL, free)) == NULL) {
00670                         ERR(diff, "%s", strerror(errno));
00671                         level_free(u1);
00672                         goto cleanup;
00673                 }
00674                 apol_vector_sort(u1->added_cats, level_cat_comp, diff->mod_qpol);
00675                 apol_vector_sort(u1->removed_cats, level_cat_comp, diff->orig_qpol);
00676                 apol_vector_sort(u1->unmodified_cats, level_cat_comp, diff->orig_qpol);
00677                 u1->form = POLDIFF_FORM_MODIFIED;
00678                 *orig_pl = u1;
00679         }
00680         retval = 0;
00681       cleanup:
00682         apol_vector_destroy(&added);
00683         apol_vector_destroy(&removed);
00684         apol_vector_destroy(&unmodified);
00685         return retval;
00686 }

int level_deep_diff_cats poldiff_t diff,
const apol_vector_t v1,
const apol_vector_t v2,
apol_vector_t **  added,
apol_vector_t **  removed,
apol_vector_t **  unmodified
 

Calculate the differences between two sorted vectors of category names.

Allocate the vectors added, removed, and unmodified; fill them with appropriate category names. The returned vectors' categories will be sorted alphabetically.

Parameters:
diff Error handler.
v1 First vector of category names, sorted alphabetically.
v2 Other vector of category names, sorted alphabetically.
added Reference to where to store added categories. The caller is responsible for calling apol_vector_destroy() upon the value. If no differences are found then this will be set to NULL.
removed Reference to where to store removed categories. The caller is responsible for calling apol_vector_destroy() upon the value. If no differences are found then this will be set to NULL.
unmodified Reference to where to store unmodified categories. The caller is responsible for calling apol_vector_destroy() upon the value. If no differences are found then this will be set to NULL.
Returns:
Greater than zero if a difference was found, zero upon no differences, less than zero on error.

Definition at line 688 of file level_diff.c.

References apol_vector_append(), apol_vector_create(), apol_vector_destroy(), apol_vector_get_element(), apol_vector_get_size(), apol_vector_t, diff, ERR, and poldiff_t.

Referenced by level_deep_diff(), level_deep_diff_apol_mls_levels(), and range_deep_diff().

00690 {
00691         size_t i, j;
00692         char *cat1, *cat2;
00693         int compval, retval = -1, error = 0;
00694         *added = *removed = *unmodified = NULL;
00695         if ((*added = apol_vector_create(free)) == NULL ||
00696             (*removed = apol_vector_create(free)) == NULL || (*unmodified = apol_vector_create(free)) == NULL) {
00697                 error = errno;
00698                 ERR(diff, "%s", strerror(error));
00699                 goto cleanup;
00700         }
00701         for (i = j = 0; i < apol_vector_get_size(v1);) {
00702                 if (j >= apol_vector_get_size(v2)) {
00703                         break;
00704                 }
00705                 cat1 = (char *)apol_vector_get_element(v1, i);
00706                 cat2 = (char *)apol_vector_get_element(v2, j);
00707                 compval = strcmp(cat1, cat2);
00708                 if (compval < 0) {
00709                         if ((cat1 = strdup(cat1)) == NULL || apol_vector_append(*removed, cat1) < 0) {
00710                                 error = errno;
00711                                 ERR(diff, "%s", strerror(error));
00712                                 free(cat1);
00713                                 goto cleanup;
00714                         }
00715                         i++;
00716                 } else if (compval > 0) {
00717                         if ((cat2 = strdup(cat2)) == NULL || apol_vector_append(*added, cat2) < 0) {
00718                                 error = errno;
00719                                 ERR(diff, "%s", strerror(error));
00720                                 free(cat2);
00721                                 goto cleanup;
00722                         }
00723                         j++;
00724                 } else {
00725                         if ((cat1 = strdup(cat1)) == NULL || apol_vector_append(*unmodified, cat1) < 0) {
00726                                 error = errno;
00727                                 ERR(diff, "%s", strerror(error));
00728                                 free(cat1);
00729                                 goto cleanup;
00730                         }
00731                         i++;
00732                         j++;
00733                 }
00734         }
00735         for (; i < apol_vector_get_size(v1); i++) {
00736                 cat1 = (char *)apol_vector_get_element(v1, i);
00737                 if ((cat1 = strdup(cat1)) == NULL || apol_vector_append(*removed, cat1) < 0) {
00738                         error = errno;
00739                         ERR(diff, "%s", strerror(error));
00740                         free(cat1);
00741                         goto cleanup;
00742                 }
00743         }
00744         for (; j < apol_vector_get_size(v2); j++) {
00745                 cat2 = (char *)apol_vector_get_element(v2, j);
00746                 if ((cat2 = strdup(cat2)) == NULL || apol_vector_append(*added, cat2) < 0) {
00747                         error = errno;
00748                         ERR(diff, "%s", strerror(error));
00749                         free(cat2);
00750                         goto cleanup;
00751                 }
00752         }
00753         if (apol_vector_get_size(*added) > 0 || apol_vector_get_size(*removed) > 0) {
00754                 retval = 1;
00755         } else {
00756                 retval = 0;
00757         }
00758       cleanup:
00759         if (retval <= 0) {
00760                 /* if no differences found, then destroy all vectors */
00761                 apol_vector_destroy(added);
00762                 apol_vector_destroy(removed);
00763                 apol_vector_destroy(unmodified);
00764         }
00765         if (retval < 0) {
00766                 error = errno;
00767         }
00768         return retval;
00769 }