mls_range.c File Reference


Detailed Description

Implementation of apol_mls_range class.

Author:
Jeremy A. Mowery jmowery@tresys.com

Jason Tang jtang@tresys.com

Copyright (C) 2006-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 mls_range.c.

#include <config.h>
#include <apol/mls_range.h>
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "policy-query-internal.h"
#include <qpol/iterator.h>
#include <apol/vector.h>

Go to the source code of this file.


Classes

struct  apol_mls_range

Functions

apol_mls_range_tapol_mls_range_create (void)
 Allocate and return a new MLS range structure.
apol_mls_range_tapol_mls_range_create_from_mls_range (const apol_mls_range_t *range)
 Allocate and return a new MLS range structure, initialized by an existing apol_mls_range_t.
apol_mls_range_tapol_mls_range_create_from_string (const apol_policy_t *p, const char *mls_range_string)
 Take a MLS range string (e.g., S0:C0.C10-S1:C0.C127) and parse it.
apol_mls_range_tapol_mls_range_create_from_literal (const char *mls_range_string)
 Take a literal MLS range string (e.g., S0:C0.C10-S1:C0.C127), fill in a newly allocated apol_mls_range_t and return it.
apol_mls_range_tapol_mls_range_create_from_qpol_mls_range (const apol_policy_t *p, const qpol_mls_range_t *qpol_range)
 Create a new apol_mls_range_t and initialize it with a qpol_mls_range_t.
void apol_mls_range_destroy (apol_mls_range_t **range)
 Deallocate all memory associated with a MLS range structure and then set it to NULL.
int apol_mls_range_set_low (const apol_policy_t *p, apol_mls_range_t *range, apol_mls_level_t *level)
 Set the low level component of a MLS range structure.
int apol_mls_range_set_high (const apol_policy_t *p, apol_mls_range_t *range, apol_mls_level_t *level)
 Set the high level component of a MLS range structure.
const apol_mls_level_tapol_mls_range_get_low (const apol_mls_range_t *range)
 Get the low level component of a MLS range structure.
const apol_mls_level_tapol_mls_range_get_high (const apol_mls_range_t *range)
 Get the high level component of a MLS range structure.
int apol_mls_range_compare (const apol_policy_t *p, const apol_mls_range_t *target, const apol_mls_range_t *search, unsigned int range_compare_type)
 Compare two ranges, determining if one matches the other.
int apol_mls_range_does_include_level (const apol_policy_t *p, const apol_mls_range_t *range, const apol_mls_level_t *level)
int apol_mls_range_contain_subrange (const apol_policy_t *p, const apol_mls_range_t *range, const apol_mls_range_t *subrange)
 Determine if a range completely contains a subrange given a certain policy.
int apol_mls_range_validate (const apol_policy_t *p, const apol_mls_range_t *range)
 Given a range, determine if it is legal according to the supplied policy.
int mls_range_comp (const void *a, const void *b, void *data)
int mls_level_name_to_cat_comp (const void *a, const void *b, void *data)
void mls_level_free (void *elem)
apol_vector_tapol_mls_range_get_levels (const apol_policy_t *p, const apol_mls_range_t *range)
 Given a range, return a vector of levels (type apol_mls_level_t *) that constitutes that range.
char * apol_mls_range_render (const apol_policy_t *p, const apol_mls_range_t *range)
 Creates a string containing the textual representation of a MLS range.
int apol_mls_range_convert (const apol_policy_t *p, apol_mls_range_t *range)
 Given a range, convert any literal MLS levels within it (as per apol_mls_level_convert()) to a complete level.
int apol_mls_range_is_literal (const apol_mls_range_t *range)
 Determine if the range contains any literal levels.

Function Documentation

apol_mls_range_t* apol_mls_range_create void   ) 
 

Allocate and return a new MLS range structure.

All fields are initialized to nothing. The caller must call apol_mls_range_destroy() upon the return value afterwards.

Returns:
An initialized MLS range structure, or NULL upon error.

Definition at line 44 of file mls_range.c.

References apol_mls_range_t.

Referenced by apol_mls_range_create_from_literal(), apol_mls_range_create_from_mls_range(), and apol_mls_range_create_from_string().

00045 {
00046         return calloc(1, sizeof(apol_mls_range_t));
00047 }

apol_mls_range_t* apol_mls_range_create_from_mls_range const apol_mls_range_t range  ) 
 

Allocate and return a new MLS range structure, initialized by an existing apol_mls_range_t.

The caller must call apol_mls_range_destroy() upon the return value afterwards.

Parameters:
range Range to copy. If NULL then the returned MLS range will be initialized to nothing.
Returns:
An initialized MLS range structure, or NULL upon error.

Definition at line 49 of file mls_range.c.

References apol_mls_level_create_from_mls_level(), apol_mls_range_create(), apol_mls_range_destroy(), apol_mls_range_t, apol_mls_range::high, and apol_mls_range::low.

00050 {
00051         apol_mls_range_t *r;
00052         if ((r = apol_mls_range_create()) == NULL) {
00053                 return NULL;
00054         }
00055         if (range != NULL &&
00056             ((r->low = apol_mls_level_create_from_mls_level(range->low)) == NULL ||
00057              (r->high = apol_mls_level_create_from_mls_level(range->high)) == NULL)) {
00058                 apol_mls_range_destroy(&r);
00059                 return NULL;
00060         }
00061         return r;
00062 }

apol_mls_range_t* apol_mls_range_create_from_string const apol_policy_t p,
const char *  mls_range_string
 

Take a MLS range string (e.g., S0:C0.C10-S1:C0.C127) and parse it.

Fill in a newly allocated apol_mls_range_t and return it. This function needs a policy to resolve dots within categories and to ensure that the high level dominates the low. If the string represents an illegal range then return NULL. The caller must call apol_mls_range_destroy() upon the returned value afterwards.

Parameters:
p Policy within which to validate mls_range_string.
mls_range_string Pointer to a string representing a valid MLS range.
Returns:
A filled in MLS range structure, or NULL upon error.

Definition at line 64 of file mls_range.c.

References apol_mls_level_create_from_string(), apol_mls_level_t, apol_mls_range_create(), apol_mls_range_destroy(), apol_mls_range_t, apol_mls_range_validate(), apol_policy_t, ERR, apol_mls_range::high, and apol_mls_range::low.

Referenced by db_range_compare(), sefs_filesystem::isQueryMatch(), sefs_filesystem::runQueryMap(), sefs_fcfile::runQueryMap(), and sefs_db::runQueryMap().

00065 {
00066         if (p == NULL || mls_range_string == NULL) {
00067                 ERR(p, "%s", strerror(EINVAL));
00068                 errno = EINVAL;
00069                 return NULL;
00070         }
00071 
00072         apol_mls_range_t *r = apol_mls_range_create();
00073         if (r == NULL) {
00074                 ERR(p, "%s", strerror(errno));
00075                 return NULL;
00076         }
00077         char *dash;
00078         if ((dash = strchr(mls_range_string, '-')) == NULL) {
00079                 // just a low level
00080                 apol_mls_level_t *l = apol_mls_level_create_from_string(p, mls_range_string);
00081                 if (l == NULL) {
00082                         ERR(p, "%s", strerror(errno));
00083                         apol_mls_range_destroy(&r);
00084                         return NULL;
00085                 }
00086                 r->low = l;
00087         } else {
00088                 // both a low and a high level
00089                 if (dash == mls_range_string) {
00090                         apol_mls_range_destroy(&r);
00091                         ERR(p, "%s", strerror(EINVAL));
00092                         errno = EINVAL;
00093                         return NULL;
00094                 }
00095                 char *s = strndup(mls_range_string, dash - mls_range_string);
00096                 if (s == NULL) {
00097                         ERR(p, "%s", strerror(errno));
00098                         apol_mls_range_destroy(&r);
00099                         return NULL;
00100                 }
00101                 apol_mls_level_t *l = apol_mls_level_create_from_string(p, s);
00102                 if (l == NULL) {
00103                         ERR(p, "%s", strerror(errno));
00104                         apol_mls_range_destroy(&r);
00105                         free(s);
00106                         return NULL;
00107                 }
00108                 r->low = l;
00109                 free(s);
00110                 l = NULL;
00111 
00112                 if ((l = apol_mls_level_create_from_string(p, dash + 1)) == NULL) {
00113                         ERR(p, "%s", strerror(errno));
00114                         apol_mls_range_destroy(&r);
00115                         return NULL;
00116                 }
00117                 r->high = l;
00118         }
00119 
00120         if (apol_mls_range_validate(p, r) <= 0) {
00121                 ERR(p, "%s", strerror(EINVAL));
00122                 errno = EINVAL;
00123                 apol_mls_range_destroy(&r);
00124                 return NULL;
00125         }
00126         return r;
00127 }

apol_mls_range_t* apol_mls_range_create_from_literal const char *  mls_range_string  ) 
 

Take a literal MLS range string (e.g., S0:C0.C10-S1:C0.C127), fill in a newly allocated apol_mls_range_t and return it.

The category portions of the levels will not be expanded (i.e., dots will not be resolved); likewise there is no check that the high level dominates the low. The caller must call apol_mls_range_destroy() upon the returned value afterwards.

Because this function creates a range without the benefit of a policy, its levels are "incomplete" and thus most operations will fail. Call apol_mls_range_convert() to make a literal MLS range complete, so that it can be used in all functions.

Parameters:
mls_range_string Pointer to a string representing a (possibly invalid) MLS range.
Returns:
A filled in MLS range structure, or NULL upon error.

Definition at line 129 of file mls_range.c.

References apol_mls_level_create_from_literal(), apol_mls_level_t, apol_mls_range_create(), apol_mls_range_destroy(), apol_mls_range_t, apol_mls_range::high, and apol_mls_range::low.

Referenced by apol_context_create_from_literal(), and sefs_fclist::getContext().

00130 {
00131         if (mls_range_string == NULL) {
00132                 errno = EINVAL;
00133                 return NULL;
00134         }
00135 
00136         apol_mls_range_t *r = apol_mls_range_create();
00137         if (r == NULL) {
00138                 return NULL;
00139         }
00140         char *dash;
00141         if ((dash = strchr(mls_range_string, '-')) == NULL) {
00142                 // just a low level
00143                 apol_mls_level_t *l = apol_mls_level_create_from_literal(mls_range_string);
00144                 if (l == NULL) {
00145                         apol_mls_range_destroy(&r);
00146                         return NULL;
00147                 }
00148                 r->low = l;
00149         } else {
00150                 // both a low and a high level
00151                 if (dash == mls_range_string) {
00152                         apol_mls_range_destroy(&r);
00153                         errno = EINVAL;
00154                         return NULL;
00155                 }
00156                 char *s = strndup(mls_range_string, dash - mls_range_string);
00157                 if (s == NULL) {
00158                         apol_mls_range_destroy(&r);
00159                         return NULL;
00160                 }
00161                 apol_mls_level_t *l = apol_mls_level_create_from_literal(s);
00162                 if (l == NULL) {
00163                         apol_mls_range_destroy(&r);
00164                         free(s);
00165                         return NULL;
00166                 }
00167                 r->low = l;
00168                 free(s);
00169                 l = NULL;
00170 
00171                 if ((l = apol_mls_level_create_from_literal(dash + 1)) == NULL) {
00172                         apol_mls_range_destroy(&r);
00173                         return NULL;
00174                 }
00175                 r->high = l;
00176         }
00177         return r;
00178 }

apol_mls_range_t* apol_mls_range_create_from_qpol_mls_range const apol_policy_t p,
const qpol_mls_range_t qpol_range
 

Create a new apol_mls_range_t and initialize it with a qpol_mls_range_t.

The caller must call apol_mls_range_destroy() upon the return value afterwards.

Parameters:
p Policy from which the qpol_mls_range_t was obtained.
qpol_range The libqpol range for which to create a new apol range. This range will not be altered by this call.
Returns:
A MLS range structure initialized to the value of qpol_range, or NULL upon error.

Definition at line 180 of file mls_range.c.

References apol_mls_level_create_from_qpol_mls_level(), apol_mls_level_destroy(), apol_mls_level_t, apol_mls_range_destroy(), apol_mls_range_set_high(), apol_mls_range_set_low(), apol_mls_range_t, apol_policy_t, ERR, apol_policy::p, qpol_mls_level_t, qpol_mls_range_get_high_level(), and qpol_mls_range_get_low_level().

Referenced by apol_context_create_from_qpol_context(), apol_context_validate_partial(), apol_range_trans_get_by_query(), apol_range_trans_render(), apol_user_get_by_query(), imp_range_trans_run(), print_user_roles(), and range_create().

00181 {
00182         apol_mls_range_t *apol_range = NULL;
00183         const qpol_mls_level_t *tmp = NULL;
00184         apol_mls_level_t *tmp_lvl = NULL;
00185         int error = 0;
00186 
00187         if (!p || !qpol_range) {
00188                 ERR(p, "%s", strerror(EINVAL));
00189                 errno = EINVAL;
00190                 return NULL;
00191         }
00192 
00193         apol_range = calloc(1, sizeof(apol_mls_range_t));
00194         if (!apol_range) {
00195                 ERR(p, "%s", strerror(ENOMEM));
00196                 return NULL;
00197         }
00198 
00199         /* low */
00200         if (qpol_mls_range_get_low_level(p->p, qpol_range, &tmp) ||
00201             !(tmp_lvl = apol_mls_level_create_from_qpol_mls_level(p, tmp)) || apol_mls_range_set_low(p, apol_range, tmp_lvl)) {
00202                 error = errno;
00203                 apol_mls_level_destroy(&tmp_lvl);
00204                 goto err;
00205         }
00206         tmp_lvl = NULL;
00207 
00208         /* high */
00209         if (qpol_mls_range_get_high_level(p->p, qpol_range, &tmp) ||
00210             !(tmp_lvl = apol_mls_level_create_from_qpol_mls_level(p, tmp)) || apol_mls_range_set_high(p, apol_range, tmp_lvl)) {
00211                 error = errno;
00212                 apol_mls_level_destroy(&tmp_lvl);
00213                 goto err;
00214         }
00215 
00216         return apol_range;
00217 
00218       err:
00219         apol_mls_range_destroy(&apol_range);
00220         errno = error;
00221         return NULL;
00222 }

void apol_mls_range_destroy apol_mls_range_t **  range  ) 
 

Deallocate all memory associated with a MLS range structure and then set it to NULL.

This function does nothing if the range is already NULL.

Parameters:
range Reference to a MLS range structure to destroy.

Definition at line 224 of file mls_range.c.

References apol_mls_level_destroy(), and apol_mls_range_t.

Referenced by apol_context_create_from_qpol_context(), apol_context_destroy(), apol_context_set_range(), apol_context_validate_partial(), apol_mls_range_create_from_literal(), apol_mls_range_create_from_mls_range(), apol_mls_range_create_from_qpol_mls_range(), apol_mls_range_create_from_string(), apol_range_trans_get_by_query(), apol_range_trans_query_destroy(), apol_range_trans_query_set_range(), apol_range_trans_render(), apol_user_get_by_query(), apol_user_query_destroy(), apol_user_query_set_range(), db_range_compare(), sefs_fclist::getContext(), sefs_filesystem::isQueryMatch(), print_user_roles(), range_destroy(), sefs_filesystem::runQueryMap(), sefs_fcfile::runQueryMap(), and sefs_db::runQueryMap().

00225 {
00226         if (!range || !(*range))
00227                 return;
00228 
00229         if ((*range)->low != (*range)->high) {
00230                 apol_mls_level_destroy(&((*range)->high));
00231         }
00232         apol_mls_level_destroy(&((*range)->low));
00233         free(*range);
00234         *range = NULL;
00235 }

int apol_mls_range_set_low const apol_policy_t p,
apol_mls_range_t range,
apol_mls_level_t level
 

Set the low level component of a MLS range structure.

This function takes ownership of the level, such that the caller must not modify nor destroy it afterwards. It is legal to pass in the same pointer for the range's low and high level.

Parameters:
p Error reporting handler, or NULL to use default handler.
range MLS range to modify.
level New low level for range, or NULL to unset this field.
Returns:
0 on success or < 0 on failure.

Definition at line 237 of file mls_range.c.

References apol_mls_level_destroy(), apol_mls_level_t, apol_mls_range_t, apol_policy_t, ERR, and apol_mls_range::low.

Referenced by apol_mls_range_create_from_qpol_mls_range().

00238 {
00239         if (!range) {
00240                 ERR(p, "%s", strerror(EINVAL));
00241                 errno = EINVAL;
00242                 return -1;
00243         }
00244         if (range->low != level) {
00245                 apol_mls_level_destroy(&(range->low));
00246                 range->low = level;
00247         }
00248         return 0;
00249 }

int apol_mls_range_set_high const apol_policy_t p,
apol_mls_range_t range,
apol_mls_level_t level
 

Set the high level component of a MLS range structure.

This function takes ownership of the level, such that the caller must not modify nor destroy it afterwards. It is legal to pass in the same pointer for the range's low and high level.

Parameters:
p Error reporting handler, or NULL to use default handler.
range MLS range to modify.
level New high level for range, or NULL to unset this field.
Returns:
0 on success or < 0 on failure.

Definition at line 251 of file mls_range.c.

References apol_mls_level_destroy(), apol_mls_level_t, apol_mls_range_t, apol_policy_t, ERR, apol_mls_range::high, and apol_mls_range::low.

Referenced by apol_mls_range_create_from_qpol_mls_range().

00252 {
00253         if (!range) {
00254                 ERR(p, "%s", strerror(EINVAL));
00255                 errno = EINVAL;
00256                 return -1;
00257         }
00258 
00259         if (range->high != level) {
00260                 if (range->low != range->high) {
00261                         apol_mls_level_destroy(&(range->high));
00262                 }
00263                 range->high = level;
00264         }
00265         return 0;
00266 }

const apol_mls_level_t* apol_mls_range_get_low const apol_mls_range_t range  ) 
 

Get the low level component of a MLS range structure.

Parameters:
range MLS range to query.
Returns:
Low level, or NULL upon error or if not yet set. Do not modify the return value.

Definition at line 268 of file mls_range.c.

References apol_mls_level_t, apol_mls_range_t, and apol_mls_range::low.

Referenced by range_deep_diff().

00269 {
00270         if (!range) {
00271                 errno = EINVAL;
00272                 return NULL;
00273         }
00274         return range->low;
00275 }

const apol_mls_level_t* apol_mls_range_get_high const apol_mls_range_t range  ) 
 

Get the high level component of a MLS range structure.

Parameters:
range MLS range to query.
Returns:
High level, or NULL upon error or if not yet set. Do not modify the return value.

Definition at line 277 of file mls_range.c.

References apol_mls_level_t, apol_mls_range_t, and apol_mls_range::high.

00278 {
00279         if (!range) {
00280                 errno = EINVAL;
00281                 return NULL;
00282         }
00283         return range->high;
00284 }

int apol_mls_range_compare const apol_policy_t p,
const apol_mls_range_t target,
const apol_mls_range_t search,
unsigned int  range_compare_type
 

Compare two ranges, determining if one matches the other.

The fifth parameter gives how to match the ranges. For APOL_QUERY_SUB, if search is a subset of target. For APOL_QUERY_SUPER, if search is a superset of target. Other valid compare types are APOL_QUERY_EXACT and APOL_QUERY_INTERSECT. If a range is not valid according to the policy then this function returns -1. If search is NULL then comparison always succeeds.

Parameters:
p Policy within which to look up MLS information.
target Target MLS range to compare.
search Source MLS range to compare.
range_compare_type Specifies how to compare the ranges.
Returns:
1 If comparison succeeds, 0 if not; -1 on error.

Definition at line 286 of file mls_range.c.

References apol_mls_range_contain_subrange(), apol_mls_range_t, apol_policy_t, ERR, and apol_mls_range::low.

Referenced by apol_context_compare(), apol_context_validate_partial(), apol_range_trans_get_by_query(), apol_user_get_by_query(), db_range_compare(), sefs_filesystem::isQueryMatch(), and sefs_fcfile::runQueryMap().

00288 {
00289         int ans1 = -1, ans2 = -1;
00290         if (search == NULL) {
00291                 return 1;
00292         }
00293         if (p == NULL || target == NULL || target->low == NULL || search->low == NULL) {
00294                 ERR(p, "%s", strerror(EINVAL));
00295                 errno = EINVAL;
00296                 return -1;
00297         }
00298         /* FIX ME:  intersect does not work */
00299         if ((range_compare_type & APOL_QUERY_SUB) || (range_compare_type & APOL_QUERY_INTERSECT)) {
00300                 ans1 = apol_mls_range_contain_subrange(p, target, search);
00301                 if (ans1 < 0) {
00302                         return -1;
00303                 }
00304         }
00305         if ((range_compare_type & APOL_QUERY_SUPER) || (range_compare_type & APOL_QUERY_INTERSECT)) {
00306                 ans2 = apol_mls_range_contain_subrange(p, search, target);
00307                 if (ans2 < 0) {
00308                         return -1;
00309                 }
00310         }
00311         /* EXACT has to come first because its bits are both SUB and SUPER */
00312         if ((range_compare_type & APOL_QUERY_EXACT) == APOL_QUERY_EXACT) {
00313                 return (ans1 && ans2);
00314         } else if (range_compare_type & APOL_QUERY_SUB) {
00315                 return ans1;
00316         } else if (range_compare_type & APOL_QUERY_SUPER) {
00317                 return ans2;
00318         } else if (range_compare_type & APOL_QUERY_INTERSECT) {
00319                 return (ans1 || ans2);
00320         }
00321         ERR(p, "%s", "Invalid range compare type argument.");
00322         errno = EINVAL;
00323         return -1;
00324 }

int apol_mls_range_does_include_level const apol_policy_t p,
const apol_mls_range_t range,
const apol_mls_level_t level
[static]
 

Definition at line 326 of file mls_range.c.

References APOL_MLS_EQ, apol_mls_level_compare(), apol_mls_level_get_sens(), apol_mls_level_t, apol_mls_range_t, apol_mls_sens_compare(), apol_policy_t, apol_mls_range::high, level, and apol_mls_range::low.

Referenced by apol_mls_range_contain_subrange().

00328 {
00329         int high_cmp = -1, low_cmp = -1;
00330 
00331         if (range->low != range->high) {
00332                 low_cmp = apol_mls_level_compare(p, range->low, level);
00333                 if (low_cmp < 0) {
00334                         return -1;
00335                 }
00336         }
00337         const apol_mls_level_t *high_level = (range->high != NULL ? range->high : range->low);
00338         high_cmp = apol_mls_level_compare(p, high_level, level);
00339         if (high_cmp < 0) {
00340                 return -1;
00341         }
00342 
00343         if (high_cmp == APOL_MLS_EQ || high_cmp == APOL_MLS_DOM) {
00344                 if ((low_cmp == APOL_MLS_EQ || low_cmp == APOL_MLS_DOMBY) && range->low != high_level) {
00345                         return 1;
00346                 } else if (range->low == high_level) {
00347                         return apol_mls_sens_compare(p, apol_mls_level_get_sens(range->low), apol_mls_level_get_sens(level));
00348                 }
00349         }
00350 
00351         return 0;
00352 }

int apol_mls_range_contain_subrange const apol_policy_t p,
const apol_mls_range_t range,
const apol_mls_range_t subrange
 

Determine if a range completely contains a subrange given a certain policy.

If a range is not valid according to the policy then this function returns -1.

Parameters:
p Policy within which to look up MLS information.
range Parent range to compare.
subrange Child range to which compare.
Returns:
1 If comparison succeeds, 0 if not; -1 on error.

Definition at line 354 of file mls_range.c.

References apol_mls_range_does_include_level(), apol_mls_range_t, apol_mls_range_validate(), apol_policy_t, ERR, apol_mls_range::high, and apol_mls_range::low.

Referenced by apol_mls_range_compare().

00355 {
00356         if (p == NULL || apol_mls_range_validate(p, subrange) != 1) {
00357                 ERR(p, "%s", strerror(EINVAL));
00358                 return -1;
00359         }
00360         /* parent range validity will be checked via
00361          * apol_mls_range_include_level() */
00362 
00363         if (apol_mls_range_does_include_level(p, range, subrange->low)) {
00364                 if (subrange->high == NULL || apol_mls_range_does_include_level(p, range, subrange->high)) {
00365                         return 1;
00366                 }
00367         }
00368         return 0;
00369 }

int apol_mls_range_validate const apol_policy_t p,
const apol_mls_range_t range
 

Given a range, determine if it is legal according to the supplied policy.

This function will convert from aliases to canonical forms as necessary.

Parameters:
p Policy within which to look up MLS information.
range Range to check.
Returns:
1 If range is legal, 0 if not; -1 on error.

Definition at line 371 of file mls_range.c.

References APOL_MLS_EQ, apol_mls_level_compare(), apol_mls_level_validate(), apol_mls_range_t, apol_policy_t, ERR, apol_mls_range::high, and apol_mls_range::low.

Referenced by apol_context_validate_partial(), apol_mls_range_contain_subrange(), and apol_mls_range_create_from_string().

00372 {
00373         int retv;
00374 
00375         if (p == NULL || range == NULL || range->low == NULL) {
00376                 ERR(p, "%s", strerror(EINVAL));
00377                 errno = EINVAL;
00378                 return -1;
00379         }
00380 
00381         if ((retv = apol_mls_level_validate(p, range->low)) != 1) {
00382                 return retv;
00383         }
00384 
00385         if (range->high == NULL) {
00386                 return retv;
00387         }
00388         if (range->high != range->low && (retv = apol_mls_level_validate(p, range->high)) != 1) {
00389                 return retv;
00390         }
00391 
00392         /* both low and high levels exist, so now check that high
00393          * dominates low */
00394         retv = apol_mls_level_compare(p, range->low, range->high);
00395         if (retv < 0) {
00396                 return -1;
00397         } else if (retv != APOL_MLS_EQ && retv != APOL_MLS_DOMBY) {
00398                 return 0;
00399         }
00400 
00401         return 1;
00402 }

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

Definition at line 404 of file mls_range.c.

References apol_mls_level_get_sens(), apol_mls_level_t, qpol_level_get_value(), qpol_level_t, qpol_policy_get_level_by_name(), and qpol_policy_t.

Referenced by apol_mls_range_get_levels().

00405 {
00406         const apol_mls_level_t *l1 = a;
00407         const apol_mls_level_t *l2 = b;
00408         qpol_policy_t *q = (qpol_policy_t *) data;
00409         const qpol_level_t *l;
00410         uint32_t low_value, high_value;
00411         qpol_policy_get_level_by_name(q, apol_mls_level_get_sens(l1), &l);
00412         qpol_level_get_value(q, l, &low_value);
00413         qpol_policy_get_level_by_name(q, apol_mls_level_get_sens(l2), &l);
00414         qpol_level_get_value(q, l, &high_value);
00415         assert(low_value != 0 && high_value != 0);
00416         return low_value - high_value;
00417 }

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

Definition at line 419 of file mls_range.c.

References qpol_cat_get_name(), qpol_cat_t, and qpol_policy_t.

Referenced by apol_mls_range_get_levels().

00420 {
00421         const qpol_cat_t *cat = a;
00422         const char *name = (const char *)b;
00423         qpol_policy_t *q = (qpol_policy_t *) data;
00424         const char *cat_name = "";
00425         qpol_cat_get_name(q, cat, &cat_name);
00426         return strcmp(name, cat_name);
00427 }

void mls_level_free void *  elem  )  [static]
 

Definition at line 429 of file mls_range.c.

References apol_mls_level_destroy(), apol_mls_level_t, and level.

Referenced by apol_mls_level_destroy(), and apol_mls_range_get_levels().

00430 {
00431         apol_mls_level_t *level = elem;
00432         apol_mls_level_destroy(&level);
00433 }

apol_vector_t* apol_mls_range_get_levels const apol_policy_t p,
const apol_mls_range_t range
 

Given a range, return a vector of levels (type apol_mls_level_t *) that constitutes that range.

The vector will be sorted in policy order.

Parameters:
p Policy from which the level and category definitions reside.
range Range to expand.
Returns:
Vector of levels, or NULL upon error. The caller is responsible for calling apol_vector_destroy() upon the returned value, passing apol_mls_level_free() as the second parameter.

Definition at line 435 of file mls_range.c.

References apol_mls_level_append_cats(), apol_mls_level_create(), apol_mls_level_destroy(), apol_mls_level_get_cats(), apol_mls_level_get_sens(), apol_mls_level_set_sens(), apol_mls_level_t, apol_mls_range_t, apol_policy_get_qpol(), apol_policy_t, apol_vector_append(), apol_vector_create(), apol_vector_create_from_iter(), apol_vector_destroy(), apol_vector_get_element(), apol_vector_get_index(), apol_vector_get_size(), apol_vector_sort(), apol_vector_t, ERR, apol_mls_range::high, apol_mls_range::low, mls_level_free(), mls_level_name_to_cat_comp(), mls_range_comp(), qpol_iterator_destroy(), qpol_iterator_end(), qpol_iterator_get_item(), qpol_iterator_next(), qpol_iterator_t, qpol_level_get_cat_iter(), qpol_level_get_name(), qpol_level_get_value(), qpol_level_t, qpol_policy_get_level_by_name(), qpol_policy_get_level_iter(), and qpol_policy_t.

Referenced by range_create(), and range_deep_diff().

00436 {
00437         qpol_policy_t *q = apol_policy_get_qpol(p);
00438         apol_vector_t *v = NULL, *catv = NULL;
00439         const qpol_level_t *l;
00440         uint32_t low_value, high_value, value;
00441         int error = 0;
00442         qpol_iterator_t *iter = NULL, *catiter = NULL;
00443 
00444         if (p == NULL || range == NULL || range->low == NULL) {
00445                 error = EINVAL;
00446                 ERR(p, "%s", strerror(error));
00447                 goto err;
00448         }
00449         apol_mls_level_t *low_level, *high_level;
00450         low_level = range->low;
00451         if (range->high == NULL) {
00452                 high_level = low_level;
00453         } else {
00454                 high_level = range->high;
00455         }
00456         if (qpol_policy_get_level_by_name(q, apol_mls_level_get_sens(low_level), &l) < 0 ||
00457             qpol_level_get_value(q, l, &low_value) < 0) {
00458                 error = errno;
00459                 goto err;
00460         }
00461         if (qpol_policy_get_level_by_name(q, apol_mls_level_get_sens(high_level), &l) < 0 ||
00462             qpol_level_get_value(q, l, &high_value) < 0) {
00463                 error = errno;
00464                 goto err;
00465         }
00466         assert(low_value <= high_value);
00467         if ((v = apol_vector_create(mls_level_free)) == NULL) {
00468                 error = errno;
00469                 ERR(p, "%s", strerror(error));
00470                 goto err;
00471         }
00472         if (qpol_policy_get_level_iter(q, &iter) < 0) {
00473                 error = errno;
00474                 goto err;
00475         }
00476         for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
00477                 const char *name;
00478                 apol_mls_level_t *ml;
00479                 if (qpol_iterator_get_item(iter, (void **)&l) < 0 ||
00480                     qpol_level_get_value(q, l, &value) < 0 || qpol_level_get_name(q, l, &name) < 0) {
00481                         error = errno;
00482                         goto err;
00483                 }
00484                 if (value < low_value || value > high_value) {
00485                         continue;
00486                 }
00487                 if ((ml = apol_mls_level_create()) == NULL || (apol_mls_level_set_sens(p, ml, name) < 0)) {
00488                         error = errno;
00489                         apol_mls_level_destroy(&ml);
00490                         ERR(p, "%s", strerror(error));
00491                         goto err;
00492                 }
00493 
00494                 if (qpol_level_get_cat_iter(q, l, &catiter) < 0 || (catv = apol_vector_create_from_iter(catiter, NULL)) == NULL) {
00495                         error = errno;
00496                         goto err;
00497                 }
00498 
00499                 const apol_vector_t *high_cats = apol_mls_level_get_cats(high_level);
00500                 for (size_t i = 0; i < apol_vector_get_size(high_cats); i++) {
00501                         char *cat_name = apol_vector_get_element(high_cats, i);
00502 
00503                         size_t j;
00504                         /* do not add categories that are not members of
00505                            the level */
00506                         if (apol_vector_get_index(catv, cat_name, mls_level_name_to_cat_comp, q, &j) < 0) {
00507                                 /* this category is not legal under the given policy */
00508                                 continue;
00509                         }
00510                         if (apol_mls_level_append_cats(p, ml, cat_name) < 0) {
00511                                 error = errno;
00512                                 apol_mls_level_destroy(&ml);
00513                                 ERR(p, "%s", strerror(error));
00514                                 goto err;
00515                         }
00516                 }
00517 
00518                 qpol_iterator_destroy(&catiter);
00519                 apol_vector_destroy(&catv);
00520 
00521                 if (apol_vector_append(v, ml) < 0) {
00522                         error = errno;
00523                         apol_mls_level_destroy(&ml);
00524                         ERR(p, "%s", strerror(error));
00525                         goto err;
00526                 }
00527         }
00528         apol_vector_sort(v, mls_range_comp, q);
00529         qpol_iterator_destroy(&iter);
00530         qpol_iterator_destroy(&catiter);
00531         apol_vector_destroy(&catv);
00532         return v;
00533       err:
00534         qpol_iterator_destroy(&iter);
00535         qpol_iterator_destroy(&catiter);
00536         apol_vector_destroy(&v);
00537         apol_vector_destroy(&catv);
00538         errno = error;
00539         return NULL;
00540 }

char* apol_mls_range_render const apol_policy_t p,
const apol_mls_range_t range
 

Creates a string containing the textual representation of a MLS range.

Parameters:
p Policy from which the MLS range is a member. If NULL, then attempt to treat the range's levels as incomplete levels (as per apol_mls_level_create_from_literal()).
range MLS range to render.
Returns:
A newly allocated string, or NULL upon error. The caller is responsible for calling free() upon the return value.

Definition at line 542 of file mls_range.c.

References APOL_MLS_DOM, apol_mls_level_compare(), apol_mls_level_render(), apol_mls_range_is_literal(), apol_mls_range_t, apol_policy_t, apol_str_append(), apol_str_appendf(), ERR, apol_mls_range::high, and apol_mls_range::low.

Referenced by apol_context_render(), apol_range_trans_render(), main(), poldiff_range_to_string_brief(), poldiff_range_trans_to_string(), print_user_roles(), rangetrans_to_string(), and replace_entry().

00543 {
00544         char *rt = NULL, *retval = NULL;
00545         char *sub_str = NULL;
00546         int retv;
00547         size_t sz = 0;
00548 
00549         if (!range || range->low == NULL) {
00550                 ERR(p, "%s", strerror(EINVAL));
00551                 errno = EINVAL;
00552                 goto cleanup;
00553         }
00554         if (p == NULL && apol_mls_range_is_literal(range) != 1) {
00555                 ERR(p, "%s", strerror(EINVAL));
00556                 errno = EINVAL;
00557                 goto cleanup;
00558         }
00559 
00560         if ((sub_str = apol_mls_level_render(p, range->low)) == NULL) {
00561                 goto cleanup;
00562         }
00563         if (apol_str_append(&rt, &sz, sub_str)) {
00564                 ERR(p, "%s", strerror(errno));
00565                 goto cleanup;
00566         }
00567         free(sub_str);
00568         sub_str = NULL;
00569         if (range->high == NULL) {
00570                 /* no high level set, so skip the rest of this render
00571                  * function */
00572                 retval = rt;
00573                 goto cleanup;
00574         }
00575         if (p == NULL) {
00576                 // no policy, so assume that high level dominates low level
00577                 retv = APOL_MLS_DOM;
00578         } else {
00579                 retv = apol_mls_level_compare(p, range->low, range->high);
00580                 if (retv < 0) {
00581                         goto cleanup;
00582                 }
00583         }
00584         /* if (high level != low level) */
00585         if ((retv == APOL_MLS_DOM || retv == APOL_MLS_DOMBY) && range->high != NULL) {
00586                 sub_str = apol_mls_level_render(p, range->high);
00587                 if (!sub_str)
00588                         goto cleanup;
00589                 if (apol_str_appendf(&rt, &sz, " - %s", sub_str)) {
00590                         ERR(p, "%s", strerror(errno));
00591                         goto cleanup;
00592                 }
00593         }
00594         retval = rt;
00595       cleanup:
00596         if (retval != rt) {
00597                 free(rt);
00598         }
00599         free(sub_str);
00600         return retval;
00601 }

int apol_mls_range_convert const apol_policy_t p,
apol_mls_range_t range
 

Given a range, convert any literal MLS levels within it (as per apol_mls_level_convert()) to a complete level.

If the range has no levels or has no literal levels then do nothing.

Parameters:
p Policy containing category information.
range Range to convert.
Returns:
0 on success, < 0 on error.

Definition at line 603 of file mls_range.c.

References apol_mls_level_convert(), apol_mls_level_t, apol_mls_range_t, apol_policy_t, ERR, apol_mls_range::high, and apol_mls_range::low.

Referenced by apol_context_convert().

00604 {
00605         if (p == NULL || range == NULL) {
00606                 ERR(p, "%s", strerror(EINVAL));
00607                 errno = EINVAL;
00608                 return -1;
00609         }
00610         apol_mls_level_t *low = range->low;
00611         apol_mls_level_t *high = range->high;
00612         int retval;
00613         if (low != NULL) {
00614                 retval = apol_mls_level_convert(p, low);
00615                 if (retval < 0) {
00616                         return retval;
00617                 }
00618         }
00619         if (high != NULL && high != low) {
00620                 retval = apol_mls_level_convert(p, high);
00621                 if (retval < 0) {
00622                         return retval;
00623                 }
00624         }
00625         return 0;
00626 }

int apol_mls_range_is_literal const apol_mls_range_t range  ) 
 

Determine if the range contains any literal levels.

(Levels that have been converted are still considered literal.)

Parameters:
range Range to query.
Returns:
> 0 value if the range has a literal level, 0 if not, < 0 if unknown or upon error.

Definition at line 628 of file mls_range.c.

References apol_mls_level_is_literal(), apol_mls_range_t, apol_mls_range::high, and apol_mls_range::low.

Referenced by apol_context_render(), and apol_mls_range_render().

00629 {
00630         if (range == NULL) {
00631                 return -1;
00632         }
00633         int ret;
00634         if ((ret = apol_mls_level_is_literal(range->low)) != 0) {
00635                 return ret;
00636         }
00637         if (range->high != NULL) {
00638                 ret = apol_mls_level_is_literal(range->high);
00639         }
00640         return ret;
00641 }