rbacrule-query.c

Go to the documentation of this file.
00001 /**
00002  * @file
00003  *
00004  * Provides a way for setools to make queries about type enforcement
00005  * rules within a policy.  The caller obtains a query object, fills in
00006  * its parameters, and then runs the query; it obtains a vector of
00007  * results.  Searches are conjunctive -- all fields of the search
00008  * query must match for a datum to be added to the results query.
00009  *
00010  * @author Jeremy A. Mowery jmowery@tresys.com
00011  * @author Jason Tang  jtang@tresys.com
00012  *
00013  * Copyright (C) 2006-2007 Tresys Technology, LLC
00014  *
00015  *  This library is free software; you can redistribute it and/or
00016  *  modify it under the terms of the GNU Lesser General Public
00017  *  License as published by the Free Software Foundation; either
00018  *  version 2.1 of the License, or (at your option) any later version.
00019  *
00020  *  This library is distributed in the hope that it will be useful,
00021  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00023  *  Lesser General Public License for more details.
00024  *
00025  *  You should have received a copy of the GNU Lesser General Public
00026  *  License along with this library; if not, write to the Free Software
00027  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00028  */
00029 
00030 #include "policy-query-internal.h"
00031 
00032 #include <errno.h>
00033 #include <string.h>
00034 
00035 struct apol_role_allow_query
00036 {
00037         char *source, *target;
00038         unsigned int flags;
00039 };
00040 
00041 struct apol_role_trans_query
00042 {
00043         char *source, *target, *default_role;
00044         unsigned int flags;
00045 };
00046 
00047 /******************** (role) allow queries ********************/
00048 
00049 int apol_role_allow_get_by_query(const apol_policy_t * p, const apol_role_allow_query_t * r, apol_vector_t ** v)
00050 {
00051         qpol_iterator_t *iter = NULL;
00052         apol_vector_t *source_list = NULL, *target_list = NULL;
00053         int retval = -1, source_as_any = 0;
00054         *v = NULL;
00055 
00056         if (r != NULL) {
00057                 if (r->source != NULL &&
00058                     (source_list = apol_query_create_candidate_role_list(p, r->source, r->flags & APOL_QUERY_REGEX)) == NULL) {
00059                         goto cleanup;
00060                 }
00061                 if ((r->flags & APOL_QUERY_SOURCE_AS_ANY) && r->source != NULL) {
00062                         target_list = source_list;
00063                         source_as_any = 1;
00064                 } else if (r->target != NULL &&
00065                            (target_list = apol_query_create_candidate_role_list(p, r->target, r->flags & APOL_QUERY_REGEX)) == NULL)
00066                 {
00067                         goto cleanup;
00068                 }
00069         }
00070         if (qpol_policy_get_role_allow_iter(p->p, &iter) < 0) {
00071                 goto cleanup;
00072         }
00073         if ((*v = apol_vector_create(NULL)) == NULL) {
00074                 ERR(p, "%s", strerror(errno));
00075                 goto cleanup;
00076         }
00077         for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
00078                 qpol_role_allow_t *rule;
00079                 int match_source = 0, match_target = 0;
00080                 size_t i;
00081                 if (qpol_iterator_get_item(iter, (void **)&rule) < 0) {
00082                         goto cleanup;
00083                 }
00084 
00085                 if (source_list == NULL) {
00086                         match_source = 1;
00087                 } else {
00088                         const qpol_role_t *source_role;
00089                         if (qpol_role_allow_get_source_role(p->p, rule, &source_role) < 0) {
00090                                 goto cleanup;
00091                         }
00092                         if (apol_vector_get_index(source_list, source_role, NULL, NULL, &i) == 0) {
00093                                 match_source = 1;
00094                         }
00095                 }
00096 
00097                 /* if source did not match, but treating source symbol
00098                  * as any field, then delay rejecting this rule until
00099                  * the target has been checked */
00100                 if (!source_as_any && !match_source) {
00101                         continue;
00102                 }
00103 
00104                 if (target_list == NULL || (source_as_any && match_source)) {
00105                         match_target = 1;
00106                 } else {
00107                         const qpol_role_t *target_role;
00108                         if (qpol_role_allow_get_target_role(p->p, rule, &target_role) < 0) {
00109                                 goto cleanup;
00110                         }
00111                         if (apol_vector_get_index(target_list, target_role, NULL, NULL, &i) == 0) {
00112                                 match_target = 1;
00113                         }
00114                 }
00115                 if (!match_target) {
00116                         continue;
00117                 }
00118 
00119                 if (apol_vector_append(*v, rule)) {
00120                         ERR(p, "%s", strerror(ENOMEM));
00121                         goto cleanup;
00122                 }
00123         }
00124 
00125         retval = 0;
00126       cleanup:
00127         if (retval != 0) {
00128                 apol_vector_destroy(v);
00129         }
00130         apol_vector_destroy(&source_list);
00131         if (!source_as_any) {
00132                 apol_vector_destroy(&target_list);
00133         }
00134         qpol_iterator_destroy(&iter);
00135         return retval;
00136 }
00137 
00138 apol_role_allow_query_t *apol_role_allow_query_create(void)
00139 {
00140         return calloc(1, sizeof(apol_role_allow_query_t));
00141 }
00142 
00143 void apol_role_allow_query_destroy(apol_role_allow_query_t ** r)
00144 {
00145         if (r != NULL && *r != NULL) {
00146                 free((*r)->source);
00147                 free((*r)->target);
00148                 free(*r);
00149                 *r = NULL;
00150         }
00151 }
00152 
00153 int apol_role_allow_query_set_source(const apol_policy_t * p, apol_role_allow_query_t * r, const char *role)
00154 {
00155         return apol_query_set(p, &r->source, NULL, role);
00156 }
00157 
00158 int apol_role_allow_query_set_target(const apol_policy_t * p, apol_role_allow_query_t * r, const char *role)
00159 {
00160         return apol_query_set(p, &r->target, NULL, role);
00161 }
00162 
00163 int apol_role_allow_query_set_source_any(const apol_policy_t * p, apol_role_allow_query_t * r, int is_any)
00164 {
00165         return apol_query_set_flag(p, &r->flags, is_any, APOL_QUERY_SOURCE_AS_ANY);
00166 }
00167 
00168 int apol_role_allow_query_set_regex(const apol_policy_t * p, apol_role_allow_query_t * r, int is_regex)
00169 {
00170         return apol_query_set_regex(p, &r->flags, is_regex);
00171 }
00172 
00173 char *apol_role_allow_render(const apol_policy_t * policy, const qpol_role_allow_t * rule)
00174 {
00175         char *tmp = NULL;
00176         const char *source_name = NULL, *target_name = NULL;
00177         const qpol_role_t *role = NULL;
00178 
00179         if (!policy || !rule) {
00180                 ERR(policy, "%s", strerror(EINVAL));
00181                 errno = EINVAL;
00182                 return NULL;
00183         }
00184 
00185         /* source role */
00186         if (qpol_role_allow_get_source_role(policy->p, rule, &role)) {
00187                 ERR(policy, "%s", strerror(errno));
00188                 return NULL;
00189         }
00190         if (qpol_role_get_name(policy->p, role, &source_name)) {
00191                 ERR(policy, "%s", strerror(errno));
00192                 return NULL;
00193         }
00194 
00195         /* target role */
00196         if (qpol_role_allow_get_target_role(policy->p, rule, &role)) {
00197                 ERR(policy, "%s", strerror(errno));
00198                 return NULL;
00199         }
00200         if (qpol_role_get_name(policy->p, role, &target_name)) {
00201                 ERR(policy, "%s", strerror(errno));
00202                 return NULL;
00203         }
00204 
00205         if (asprintf(&tmp, "allow %s %s;", source_name, target_name) < 0) {
00206                 ERR(policy, "%s", strerror(errno));
00207                 return NULL;
00208         }
00209 
00210         return tmp;
00211 }
00212 
00213 /******************** role_transition queries ********************/
00214 
00215 int apol_role_trans_get_by_query(const apol_policy_t * p, const apol_role_trans_query_t * r, apol_vector_t ** v)
00216 {
00217         qpol_iterator_t *iter = NULL;
00218         apol_vector_t *source_list = NULL, *target_list = NULL, *default_list = NULL;
00219         int retval = -1, source_as_any = 0;
00220         *v = NULL;
00221 
00222         if (r != NULL) {
00223                 if (r->source != NULL &&
00224                     (source_list = apol_query_create_candidate_role_list(p, r->source, r->flags & APOL_QUERY_REGEX)) == NULL) {
00225                         goto cleanup;
00226                 }
00227                 if (r->target != NULL &&
00228                     (target_list =
00229                      apol_query_create_candidate_type_list(p, r->target, r->flags & APOL_QUERY_REGEX,
00230                                                            r->flags & APOL_QUERY_TARGET_INDIRECT,
00231                                                            APOL_QUERY_SYMBOL_IS_BOTH)) == NULL) {
00232                         goto cleanup;
00233                 }
00234                 if ((r->flags & APOL_QUERY_SOURCE_AS_ANY) && r->source != NULL) {
00235                         default_list = source_list;
00236                         source_as_any = 1;
00237                 } else if (r->default_role != NULL &&
00238                            (default_list =
00239                             apol_query_create_candidate_role_list(p, r->default_role, r->flags & APOL_QUERY_REGEX)) == NULL) {
00240                         goto cleanup;
00241                 }
00242         }
00243         if (qpol_policy_get_role_trans_iter(p->p, &iter) < 0) {
00244                 goto cleanup;
00245         }
00246         if ((*v = apol_vector_create(NULL)) == NULL) {
00247                 ERR(p, "%s", strerror(errno));
00248                 goto cleanup;
00249         }
00250         for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
00251                 qpol_role_trans_t *rule;
00252                 int match_source = 0, match_target = 0, match_default = 0;
00253                 size_t i;
00254                 if (qpol_iterator_get_item(iter, (void **)&rule) < 0) {
00255                         goto cleanup;
00256                 }
00257 
00258                 if (source_list == NULL) {
00259                         match_source = 1;
00260                 } else {
00261                         const qpol_role_t *source_role;
00262                         if (qpol_role_trans_get_source_role(p->p, rule, &source_role) < 0) {
00263                                 goto cleanup;
00264                         }
00265                         if (apol_vector_get_index(source_list, source_role, NULL, NULL, &i) == 0) {
00266                                 match_source = 1;
00267                         }
00268                 }
00269 
00270                 /* if source did not match, but treating source symbol
00271                  * as any field, then delay rejecting this rule until
00272                  * the target and default have been checked */
00273                 if (!source_as_any && !match_source) {
00274                         continue;
00275                 }
00276 
00277                 if (target_list == NULL) {
00278                         match_target = 1;
00279                 } else {
00280                         const qpol_type_t *target_type;
00281                         if (qpol_role_trans_get_target_type(p->p, rule, &target_type) < 0) {
00282                                 goto cleanup;
00283                         }
00284                         if (apol_vector_get_index(target_list, target_type, NULL, NULL, &i) == 0) {
00285                                 match_target = 1;
00286                         }
00287                 }
00288                 if (!match_target) {
00289                         continue;
00290                 }
00291 
00292                 if (default_list == NULL || (source_as_any && match_source)) {
00293                         match_default = 1;
00294                 } else {
00295                         const qpol_role_t *default_role;
00296                         if (qpol_role_trans_get_default_role(p->p, rule, &default_role) < 0) {
00297                                 goto cleanup;
00298                         }
00299                         if (apol_vector_get_index(default_list, default_role, NULL, NULL, &i) == 0) {
00300                                 match_default = 1;
00301                         }
00302                 }
00303                 if (!match_default) {
00304                         continue;
00305                 }
00306 
00307                 if (apol_vector_append(*v, rule)) {
00308                         ERR(p, "%s", strerror(ENOMEM));
00309                         goto cleanup;
00310                 }
00311         }
00312 
00313         retval = 0;
00314       cleanup:
00315         if (retval != 0) {
00316                 apol_vector_destroy(v);
00317         }
00318         apol_vector_destroy(&source_list);
00319         apol_vector_destroy(&target_list);
00320         if (!source_as_any) {
00321                 apol_vector_destroy(&default_list);
00322         }
00323         qpol_iterator_destroy(&iter);
00324         return retval;
00325 }
00326 
00327 apol_role_trans_query_t *apol_role_trans_query_create(void)
00328 {
00329         return calloc(1, sizeof(apol_role_trans_query_t));
00330 }
00331 
00332 void apol_role_trans_query_destroy(apol_role_trans_query_t ** r)
00333 {
00334         if (r != NULL && *r != NULL) {
00335                 free((*r)->source);
00336                 free((*r)->target);
00337                 free((*r)->default_role);
00338                 free(*r);
00339                 *r = NULL;
00340         }
00341 }
00342 
00343 int apol_role_trans_query_set_source(const apol_policy_t * p, apol_role_trans_query_t * r, const char *role)
00344 {
00345         return apol_query_set(p, &r->source, NULL, role);
00346 }
00347 
00348 int apol_role_trans_query_set_target(const apol_policy_t * p, apol_role_trans_query_t * r, const char *type, int is_indirect)
00349 {
00350         apol_query_set_flag(p, &r->flags, is_indirect, APOL_QUERY_TARGET_INDIRECT);
00351         return apol_query_set(p, &r->target, NULL, type);
00352 }
00353 
00354 int apol_role_trans_query_set_default(const apol_policy_t * p, apol_role_trans_query_t * r, const char *role)
00355 {
00356         return apol_query_set(p, &r->default_role, NULL, role);
00357 }
00358 
00359 int apol_role_trans_query_set_source_any(const apol_policy_t * p, apol_role_trans_query_t * r, int is_any)
00360 {
00361         return apol_query_set_flag(p, &r->flags, is_any, APOL_QUERY_SOURCE_AS_ANY);
00362 }
00363 
00364 int apol_role_trans_query_set_regex(const apol_policy_t * p, apol_role_trans_query_t * r, int is_regex)
00365 {
00366         return apol_query_set_regex(p, &r->flags, is_regex);
00367 }
00368 
00369 char *apol_role_trans_render(const apol_policy_t * policy, const qpol_role_trans_t * rule)
00370 {
00371         char *tmp = NULL;
00372         const char *source_name = NULL, *target_name = NULL, *default_name = NULL;
00373         const qpol_role_t *role = NULL;
00374         const qpol_type_t *type = NULL;
00375 
00376         if (!policy || !rule) {
00377                 ERR(policy, "%s", strerror(EINVAL));
00378                 errno = EINVAL;
00379                 return NULL;
00380         }
00381 
00382         /* source role */
00383         if (qpol_role_trans_get_source_role(policy->p, rule, &role)) {
00384                 ERR(policy, "%s", strerror(errno));
00385                 return NULL;
00386         }
00387         if (qpol_role_get_name(policy->p, role, &source_name)) {
00388                 ERR(policy, "%s", strerror(errno));
00389                 return NULL;
00390         }
00391 
00392         /* target type */
00393         if (qpol_role_trans_get_target_type(policy->p, rule, &type)) {
00394                 ERR(policy, "%s", strerror(errno));
00395                 return NULL;
00396         }
00397         if (qpol_type_get_name(policy->p, type, &target_name)) {
00398                 ERR(policy, "%s", strerror(errno));
00399                 return NULL;
00400         }
00401 
00402         /* default role */
00403         if (qpol_role_trans_get_default_role(policy->p, rule, &role)) {
00404                 ERR(policy, "%s", strerror(errno));
00405                 return NULL;
00406         }
00407         if (qpol_role_get_name(policy->p, role, &default_name)) {
00408                 ERR(policy, "%s", strerror(errno));
00409                 return NULL;
00410         }
00411 
00412         if (asprintf(&tmp, "role_transition %s %s %s;", source_name, target_name, default_name) < 0) {
00413                 ERR(policy, "%s", strerror(errno));
00414                 return NULL;
00415         }
00416         return tmp;
00417 }