cond_query.c

Go to the documentation of this file.
00001 /**
00002  * @file
00003  * Implememtation for the public interface for searching and iterating
00004  * conditionals
00005  *
00006  * @author Kevin Carr kcarr@tresys.com
00007  * @author Jeremy A. Mowery jmowery@tresys.com
00008  * @author Jason Tang jtang@tresys.com
00009  *
00010  * Copyright (C) 2006-2007 Tresys Technology, LLC
00011  *
00012  *  This library is free software; you can redistribute it and/or
00013  *  modify it under the terms of the GNU Lesser General Public
00014  *  License as published by the Free Software Foundation; either
00015  *  version 2.1 of the License, or (at your option) any later version.
00016  *
00017  *  This library is distributed in the hope that it will be useful,
00018  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020  *  Lesser General Public License for more details.
00021  *
00022  *  You should have received a copy of the GNU Lesser General Public
00023  *  License along with this library; if not, write to the Free Software
00024  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00025  */
00026 
00027 #include <qpol/policy.h>
00028 #include <qpol/cond_query.h>
00029 #include <qpol/bool_query.h>
00030 #include <qpol/avrule_query.h>
00031 #include <qpol/terule_query.h>
00032 #include <qpol/iterator.h>
00033 #include "iterator_internal.h"
00034 #include "qpol_internal.h"
00035 
00036 #include <sepol/policydb/conditional.h>
00037 
00038 #include <stdlib.h>
00039 #include <errno.h>
00040 
00041 typedef struct cond_state
00042 {
00043         cond_node_t *head;
00044         cond_node_t *cur;
00045 } cond_state_t;
00046 
00047 static int cond_state_end(const qpol_iterator_t * iter)
00048 {
00049         cond_state_t *cs = NULL;
00050 
00051         if (!iter || !(cs = (cond_state_t *) qpol_iterator_state(iter))) {
00052                 errno = EINVAL;
00053                 return STATUS_ERR;
00054         }
00055 
00056         return cs->cur ? 0 : 1;
00057 }
00058 
00059 static void *cond_state_get_cur(const qpol_iterator_t * iter)
00060 {
00061         cond_state_t *cs = NULL;
00062 
00063         if (!iter || !(cs = (cond_state_t *) qpol_iterator_state(iter)) || qpol_iterator_end(iter)) {
00064                 errno = EINVAL;
00065                 return NULL;
00066         }
00067 
00068         return cs->cur;
00069 }
00070 
00071 static int cond_state_next(qpol_iterator_t * iter)
00072 {
00073         cond_state_t *cs = NULL;
00074 
00075         if (!iter || !(cs = (cond_state_t *) qpol_iterator_state(iter))) {
00076                 errno = EINVAL;
00077                 return STATUS_ERR;
00078         }
00079 
00080         if (qpol_iterator_end(iter)) {
00081                 errno = ERANGE;
00082                 return STATUS_ERR;
00083         }
00084 
00085         cs->cur = cs->cur->next;
00086 
00087         return STATUS_SUCCESS;
00088 }
00089 
00090 static size_t cond_state_size(const qpol_iterator_t * iter)
00091 {
00092         cond_state_t *cs = NULL;
00093         cond_node_t *tmp = NULL;
00094         size_t count = 0;
00095 
00096         if (!iter || !(cs = (cond_state_t *) qpol_iterator_state(iter))) {
00097                 errno = EINVAL;
00098                 return 0;
00099         }
00100 
00101         for (tmp = cs->head; tmp; tmp = tmp->next)
00102                 count++;
00103 
00104         return count;
00105 }
00106 
00107 int qpol_policy_get_cond_iter(const qpol_policy_t * policy, qpol_iterator_t ** iter)
00108 {
00109         int error = 0;
00110         cond_state_t *cs = NULL;
00111         policydb_t *db = NULL;
00112 
00113         if (iter)
00114                 *iter = NULL;
00115 
00116         if (!policy || !iter) {
00117                 ERR(policy, "%s", strerror(EINVAL));
00118                 errno = EINVAL;
00119                 return STATUS_ERR;
00120         }
00121 
00122         if (!qpol_policy_has_capability(policy, QPOL_CAP_RULES_LOADED)) {
00123                 ERR(policy, "%s", "Cannot get conditionals: Rules not loaded");
00124                 errno = ENOTSUP;
00125                 return STATUS_ERR;
00126         }
00127 
00128         db = &policy->p->p;
00129 
00130         if (!(cs = calloc(1, sizeof(cond_state_t)))) {
00131                 error = errno;
00132                 ERR(policy, "%s", strerror(error));
00133                 goto err;
00134         }
00135         cs->head = cs->cur = db->cond_list;
00136 
00137         if (qpol_iterator_create(policy, (void *)cs,
00138                                  cond_state_get_cur, cond_state_next, cond_state_end, cond_state_size, free, iter)) {
00139                 error = errno;
00140                 goto err;
00141         }
00142 
00143         return STATUS_SUCCESS;
00144 
00145       err:
00146         free(cs);
00147         errno = error;
00148         return STATUS_ERR;
00149 }
00150 
00151 typedef struct cond_expr_state
00152 {
00153         cond_expr_t *head;
00154         cond_expr_t *cur;
00155 } cond_expr_state_t;
00156 
00157 static int cond_expr_state_end(const qpol_iterator_t * iter)
00158 {
00159         cond_expr_state_t *ces = NULL;
00160 
00161         if (!iter || !(ces = (cond_expr_state_t *) qpol_iterator_state(iter))) {
00162                 errno = EINVAL;
00163                 return STATUS_ERR;
00164         }
00165 
00166         return ces->cur ? 0 : 1;
00167 }
00168 
00169 static void *cond_expr_state_get_cur(const qpol_iterator_t * iter)
00170 {
00171         cond_expr_state_t *ces = NULL;
00172 
00173         if (!iter || !(ces = (cond_expr_state_t *) qpol_iterator_state(iter)) || qpol_iterator_end(iter)) {
00174                 errno = EINVAL;
00175                 return NULL;
00176         }
00177 
00178         return ces->cur;
00179 }
00180 
00181 static int cond_expr_state_next(qpol_iterator_t * iter)
00182 {
00183         cond_expr_state_t *ces = NULL;
00184 
00185         if (!iter || !(ces = (cond_expr_state_t *) qpol_iterator_state(iter))) {
00186                 errno = EINVAL;
00187                 return STATUS_ERR;
00188         }
00189 
00190         if (qpol_iterator_end(iter)) {
00191                 errno = ERANGE;
00192                 return STATUS_ERR;
00193         }
00194 
00195         ces->cur = ces->cur->next;
00196 
00197         return STATUS_SUCCESS;
00198 }
00199 
00200 static size_t cond_expr_state_size(const qpol_iterator_t * iter)
00201 {
00202         cond_expr_state_t *ces = NULL;
00203         cond_expr_t *tmp = NULL;
00204         size_t count = 0;
00205 
00206         if (!iter || !(ces = (cond_expr_state_t *) qpol_iterator_state(iter))) {
00207                 errno = EINVAL;
00208                 return 0;
00209         }
00210 
00211         for (tmp = ces->head; tmp; tmp = tmp->next)
00212                 count++;
00213 
00214         return count;
00215 }
00216 
00217 int qpol_cond_get_expr_node_iter(const qpol_policy_t * policy, const qpol_cond_t * cond, qpol_iterator_t ** iter)
00218 {
00219         int error = 0;
00220         cond_expr_state_t *ces = NULL;
00221         cond_node_t *internal_cond = NULL;
00222         policydb_t *db = NULL;
00223 
00224         if (iter)
00225                 *iter = NULL;
00226 
00227         if (!policy || !cond || !iter) {
00228                 ERR(policy, "%s", strerror(EINVAL));
00229                 errno = EINVAL;
00230                 return STATUS_ERR;
00231         }
00232 
00233         db = &policy->p->p;
00234         internal_cond = (cond_node_t *) cond;
00235 
00236         if (!(ces = calloc(1, sizeof(cond_expr_state_t)))) {
00237                 error = errno;
00238                 ERR(policy, "%s", strerror(error));
00239                 goto err;
00240         }
00241         ces->head = ces->cur = internal_cond->expr;
00242 
00243         if (qpol_iterator_create(policy, (void *)ces,
00244                                  cond_expr_state_get_cur, cond_expr_state_next, cond_expr_state_end,
00245                                  cond_expr_state_size, free, iter)) {
00246                 error = errno;
00247                 goto err;
00248         }
00249 
00250         return STATUS_SUCCESS;
00251 
00252       err:
00253         free(ces);
00254         errno = error;
00255         return STATUS_ERR;
00256 }
00257 
00258 typedef struct cond_rule_state
00259 {
00260         cond_av_list_t *head;
00261         cond_av_list_t *cur;
00262         uint32_t rule_type_mask;
00263 } cond_rule_state_t;
00264 
00265 static int cond_rule_state_end(const qpol_iterator_t * iter)
00266 {
00267         cond_rule_state_t *crs = NULL;
00268 
00269         if (!iter || !(crs = (cond_rule_state_t *) qpol_iterator_state(iter))) {
00270                 errno = EINVAL;
00271                 return STATUS_ERR;
00272         }
00273 
00274         return crs->cur ? 0 : 1;
00275 }
00276 
00277 static void *cond_rule_state_get_cur(const qpol_iterator_t * iter)
00278 {
00279         cond_rule_state_t *crs = NULL;
00280 
00281         if (!iter || !(crs = (cond_rule_state_t *) qpol_iterator_state(iter)) || qpol_iterator_end(iter)) {
00282                 errno = EINVAL;
00283                 return NULL;
00284         }
00285 
00286         return crs->cur->node;
00287 }
00288 
00289 static int cond_rule_state_next(qpol_iterator_t * iter)
00290 {
00291         cond_rule_state_t *crs = NULL;
00292 
00293         if (!iter || !(crs = (cond_rule_state_t *) qpol_iterator_state(iter))) {
00294                 errno = EINVAL;
00295                 return STATUS_ERR;
00296         }
00297 
00298         if (qpol_iterator_end(iter)) {
00299                 errno = ERANGE;
00300                 return STATUS_ERR;
00301         }
00302 
00303         do {
00304                 crs->cur = crs->cur->next;
00305         } while (crs->cur && !(crs->cur->node->key.specified & crs->rule_type_mask));
00306 
00307         return STATUS_SUCCESS;
00308 }
00309 
00310 static size_t cond_rule_state_size(const qpol_iterator_t * iter)
00311 {
00312         cond_rule_state_t *crs = NULL;
00313         cond_av_list_t *tmp = NULL;
00314         size_t count = 0;
00315 
00316         if (!iter || !(crs = (cond_rule_state_t *) qpol_iterator_state(iter))) {
00317                 errno = EINVAL;
00318                 return 0;
00319         }
00320 
00321         for (tmp = crs->head; tmp; tmp = tmp->next) {
00322                 if (tmp->node->key.specified & crs->rule_type_mask)
00323                         count++;
00324         }
00325 
00326         return count;
00327 }
00328 
00329 int qpol_cond_get_av_true_iter(const qpol_policy_t * policy, const qpol_cond_t * cond, uint32_t rule_type_mask,
00330                                qpol_iterator_t ** iter)
00331 {
00332         int error = 0;
00333         cond_rule_state_t *crs = NULL;
00334         cond_node_t *internal_cond = NULL;
00335         policydb_t *db = NULL;
00336 
00337         if (iter)
00338                 *iter = NULL;
00339 
00340         if (!policy || !cond || !iter) {
00341                 ERR(policy, "%s", strerror(EINVAL));
00342                 errno = EINVAL;
00343                 return STATUS_ERR;
00344         }
00345 
00346         if (rule_type_mask & ~(QPOL_RULE_ALLOW | QPOL_RULE_NEVERALLOW | QPOL_RULE_AUDITALLOW | QPOL_RULE_DONTAUDIT)) {
00347                 ERR(policy, "%s", strerror(EINVAL));
00348                 errno = EINVAL;
00349                 return STATUS_ERR;
00350         }
00351 
00352         db = &policy->p->p;
00353         internal_cond = (cond_node_t *) cond;
00354 
00355         if (!(crs = calloc(1, sizeof(cond_rule_state_t)))) {
00356                 error = errno;
00357                 ERR(policy, "%s", strerror(error));
00358                 goto err;
00359         }
00360         crs->head = crs->cur = internal_cond->true_list;
00361         crs->rule_type_mask = rule_type_mask;
00362 
00363         if (qpol_iterator_create(policy, (void *)crs,
00364                                  cond_rule_state_get_cur, cond_rule_state_next, cond_rule_state_end,
00365                                  cond_rule_state_size, free, iter)) {
00366                 error = errno;
00367                 goto err;
00368         }
00369 
00370         if (crs->cur && !(crs->cur->node->key.specified & crs->rule_type_mask))
00371                 qpol_iterator_next(*iter);
00372 
00373         return STATUS_SUCCESS;
00374 
00375       err:
00376         free(crs);
00377         errno = error;
00378         return STATUS_ERR;
00379 }
00380 
00381 int qpol_cond_get_te_true_iter(const qpol_policy_t * policy, const qpol_cond_t * cond, uint32_t rule_type_mask,
00382                                qpol_iterator_t ** iter)
00383 {
00384         int error = 0;
00385         cond_rule_state_t *crs = NULL;
00386         cond_node_t *internal_cond = NULL;
00387         policydb_t *db = NULL;
00388 
00389         if (iter)
00390                 *iter = NULL;
00391 
00392         if (!policy || !cond || !iter) {
00393                 ERR(policy, "%s", strerror(EINVAL));
00394                 errno = EINVAL;
00395                 return STATUS_ERR;
00396         }
00397 
00398         if (rule_type_mask & ~(QPOL_RULE_TYPE_TRANS | QPOL_RULE_TYPE_CHANGE | QPOL_RULE_TYPE_MEMBER)) {
00399                 ERR(policy, "%s", strerror(EINVAL));
00400                 errno = EINVAL;
00401                 return STATUS_ERR;
00402         }
00403 
00404         db = &policy->p->p;
00405         internal_cond = (cond_node_t *) cond;
00406 
00407         if (!(crs = calloc(1, sizeof(cond_rule_state_t)))) {
00408                 error = errno;
00409                 ERR(policy, "%s", strerror(error));
00410                 goto err;
00411         }
00412         crs->head = crs->cur = internal_cond->true_list;
00413         crs->rule_type_mask = rule_type_mask;
00414 
00415         if (qpol_iterator_create(policy, (void *)crs,
00416                                  cond_rule_state_get_cur, cond_rule_state_next, cond_rule_state_end,
00417                                  cond_rule_state_size, free, iter)) {
00418                 error = errno;
00419                 goto err;
00420         }
00421 
00422         if (crs->cur && !(crs->cur->node->key.specified & crs->rule_type_mask))
00423                 qpol_iterator_next(*iter);
00424 
00425         return STATUS_SUCCESS;
00426 
00427       err:
00428         free(crs);
00429         errno = error;
00430         return STATUS_ERR;
00431 }
00432 
00433 int qpol_cond_get_av_false_iter(const qpol_policy_t * policy, const qpol_cond_t * cond, uint32_t rule_type_mask,
00434                                 qpol_iterator_t ** iter)
00435 {
00436         int error = 0;
00437         cond_rule_state_t *crs = NULL;
00438         cond_node_t *internal_cond = NULL;
00439         policydb_t *db = NULL;
00440 
00441         if (iter)
00442                 *iter = NULL;
00443 
00444         if (!policy || !cond || !iter) {
00445                 ERR(policy, "%s", strerror(EINVAL));
00446                 errno = EINVAL;
00447                 return STATUS_ERR;
00448         }
00449 
00450         if (rule_type_mask & ~(QPOL_RULE_ALLOW | QPOL_RULE_NEVERALLOW | QPOL_RULE_AUDITALLOW | QPOL_RULE_DONTAUDIT)) {
00451                 ERR(policy, "%s", strerror(EINVAL));
00452                 errno = EINVAL;
00453                 return STATUS_ERR;
00454         }
00455 
00456         db = &policy->p->p;
00457         internal_cond = (cond_node_t *) cond;
00458 
00459         if (!(crs = calloc(1, sizeof(cond_rule_state_t)))) {
00460                 error = errno;
00461                 ERR(policy, "%s", strerror(error));
00462                 goto err;
00463         }
00464         crs->head = crs->cur = internal_cond->false_list;
00465         crs->rule_type_mask = rule_type_mask;
00466 
00467         if (qpol_iterator_create(policy, (void *)crs,
00468                                  cond_rule_state_get_cur, cond_rule_state_next, cond_rule_state_end,
00469                                  cond_rule_state_size, free, iter)) {
00470                 error = errno;
00471                 goto err;
00472         }
00473 
00474         if (crs->cur && !(crs->cur->node->key.specified & crs->rule_type_mask))
00475                 qpol_iterator_next(*iter);
00476 
00477         return STATUS_SUCCESS;
00478 
00479       err:
00480         free(crs);
00481         errno = error;
00482         return STATUS_ERR;
00483 }
00484 
00485 int qpol_cond_get_te_false_iter(const qpol_policy_t * policy, const qpol_cond_t * cond, uint32_t rule_type_mask,
00486                                 qpol_iterator_t ** iter)
00487 {
00488         int error = 0;
00489         cond_rule_state_t *crs = NULL;
00490         cond_node_t *internal_cond = NULL;
00491         policydb_t *db = NULL;
00492 
00493         if (iter)
00494                 *iter = NULL;
00495 
00496         if (!policy || !cond || !iter) {
00497                 ERR(policy, "%s", strerror(EINVAL));
00498                 errno = EINVAL;
00499                 return STATUS_ERR;
00500         }
00501 
00502         if (rule_type_mask & ~(QPOL_RULE_TYPE_TRANS | QPOL_RULE_TYPE_CHANGE | QPOL_RULE_TYPE_MEMBER)) {
00503                 ERR(policy, "%s", strerror(EINVAL));
00504                 errno = EINVAL;
00505                 return STATUS_ERR;
00506         }
00507 
00508         db = &policy->p->p;
00509         internal_cond = (cond_node_t *) cond;
00510 
00511         if (!(crs = calloc(1, sizeof(cond_rule_state_t)))) {
00512                 error = errno;
00513                 ERR(policy, "%s", strerror(error));
00514                 goto err;
00515         }
00516         crs->head = crs->cur = internal_cond->false_list;
00517         crs->rule_type_mask = rule_type_mask;
00518 
00519         if (qpol_iterator_create(policy, (void *)crs,
00520                                  cond_rule_state_get_cur, cond_rule_state_next, cond_rule_state_end,
00521                                  cond_rule_state_size, free, iter)) {
00522                 error = errno;
00523                 goto err;
00524         }
00525 
00526         if (crs->cur && !(crs->cur->node->key.specified & crs->rule_type_mask))
00527                 qpol_iterator_next(*iter);
00528 
00529         return STATUS_SUCCESS;
00530 
00531       err:
00532         free(crs);
00533         errno = error;
00534         return STATUS_ERR;
00535 }
00536 
00537 int qpol_cond_eval(const qpol_policy_t * policy, const qpol_cond_t * cond, uint32_t * is_true)
00538 {
00539         int error = 0;
00540         cond_node_t *internal_cond = NULL;
00541 
00542         if (is_true)
00543                 *is_true = 0;
00544 
00545         if (!policy || !cond || !is_true) {
00546                 ERR(policy, "%s", strerror(EINVAL));
00547                 errno = EINVAL;
00548                 return STATUS_ERR;
00549         }
00550 
00551         internal_cond = (cond_node_t *) cond;
00552 
00553         if ((*is_true = (uint32_t) cond_evaluate_expr(&policy->p->p, internal_cond->expr)) > 1) {
00554                 error = ERANGE;
00555                 goto err;
00556         }
00557 
00558         return STATUS_SUCCESS;
00559 
00560       err:
00561         ERR(policy, "%s", strerror(error));
00562         errno = error;
00563         return STATUS_ERR;
00564 }
00565 
00566 int qpol_cond_expr_node_get_expr_type(const qpol_policy_t * policy, const qpol_cond_expr_node_t * node, uint32_t * expr_type)
00567 {
00568         cond_expr_t *internal_cond = NULL;
00569 
00570         if (expr_type)
00571                 *expr_type = 0;
00572 
00573         if (!policy || !node || !expr_type) {
00574                 ERR(policy, "%s", strerror(EINVAL));
00575                 errno = EINVAL;
00576                 return STATUS_ERR;
00577         }
00578 
00579         internal_cond = (cond_expr_t *) node;
00580 
00581         *expr_type = internal_cond->expr_type;
00582 
00583         return STATUS_SUCCESS;
00584 }
00585 
00586 int qpol_cond_expr_node_get_bool(const qpol_policy_t * policy, const qpol_cond_expr_node_t * node, qpol_bool_t ** cond_bool)
00587 {
00588         int error = 0;
00589         cond_expr_t *internal_cond = NULL;
00590         policydb_t *db = NULL;
00591 
00592         if (cond_bool)
00593                 *cond_bool = NULL;
00594 
00595         if (!policy || !node || !cond_bool) {
00596                 ERR(policy, "%s", strerror(EINVAL));
00597                 errno = EINVAL;
00598                 return STATUS_ERR;
00599         }
00600 
00601         db = &policy->p->p;
00602         internal_cond = (cond_expr_t *) node;
00603 
00604         if (internal_cond->expr_type != QPOL_COND_EXPR_BOOL) {
00605                 error = EINVAL;
00606                 goto err;
00607         }
00608 
00609         if (!(*cond_bool = (qpol_bool_t *) db->bool_val_to_struct[internal_cond->bool - 1])) {
00610                 error = EINVAL;
00611                 goto err;
00612         }
00613 
00614         return STATUS_SUCCESS;
00615 
00616       err:
00617         ERR(policy, "%s", strerror(error));
00618         errno = error;
00619         return STATUS_ERR;
00620 }