terule-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 #include <apol/bst.h>
00032 #include <qpol/policy_extend.h>
00033 #include <errno.h>
00034 #include <string.h>
00035 
00036 struct apol_terule_query
00037 {
00038         char *source, *target, *default_type, *bool_name;
00039         apol_vector_t *classes;
00040         unsigned int rules;
00041         unsigned int flags;
00042 };
00043 
00044 /**
00045  *  Common semantic rule selection routine used in get*rule_by_query.
00046  *  @param p Policy to search.
00047  *  @param v Vector of rules to populate (of type qpol_terule_t).
00048  *  @param rule_type Mask of rules to search.
00049  *  @param flags Query options as specified by the apol_terule_query.
00050  *  @param source_list If non-NULL, list of types to use as source.
00051  *  If NULL, accept all types.
00052  *  @param target_list If non-NULL, list of types to use as target.
00053  *  If NULL, accept all types.
00054  *  @param class_list If non-NULL, list of classes to use.
00055  *  If NULL, accept all classes.
00056  *  @param default_list If non-NULL, list of types to use as default.
00057  *  If NULL, accept all types.
00058  *  @param bool_name If non-NULL, find conditional rules affected by this boolean.
00059  *  If NULL, all rules will be considered (including unconditional rules).
00060  *  @return 0 on success and < 0 on failure.
00061  */
00062 static int rule_select(const apol_policy_t * p, apol_vector_t * v, uint32_t rule_type, unsigned int flags,
00063                        const apol_vector_t * source_list, const apol_vector_t * target_list, const apol_vector_t * class_list,
00064                        const apol_vector_t * default_list, const char *bool_name)
00065 {
00066         qpol_iterator_t *iter = NULL;
00067         int only_enabled = flags & APOL_QUERY_ONLY_ENABLED;
00068         int is_regex = flags & APOL_QUERY_REGEX;
00069         int source_as_any = flags & APOL_QUERY_SOURCE_AS_ANY;
00070         int retv = -1;
00071         regex_t *bool_regex = NULL;
00072 
00073         if (qpol_policy_get_terule_iter(p->p, rule_type, &iter) < 0) {
00074                 goto cleanup;
00075         }
00076 
00077         for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
00078                 qpol_terule_t *rule;
00079                 uint32_t is_enabled;
00080                 const qpol_cond_t *cond = NULL;
00081                 int match_source = 0, match_target = 0, match_default = 0, match_bool = 0;
00082                 size_t i;
00083                 if (qpol_iterator_get_item(iter, (void **)&rule) < 0) {
00084                         goto cleanup;
00085                 }
00086 
00087                 if (qpol_terule_get_is_enabled(p->p, rule, &is_enabled) < 0) {
00088                         goto cleanup;
00089                 }
00090                 if (!is_enabled && only_enabled) {
00091                         continue;
00092                 }
00093 
00094                 if (bool_name != NULL) {
00095                         if (qpol_terule_get_cond(p->p, rule, &cond) < 0) {
00096                                 goto cleanup;
00097                         }
00098                         if (cond == NULL) {
00099                                 continue;       /* skip unconditional rule */
00100                         }
00101                         match_bool = apol_compare_cond_expr(p, cond, bool_name, is_regex, &bool_regex);
00102                         if (match_bool < 0) {
00103                                 goto cleanup;
00104                         } else if (match_bool == 0) {
00105                                 continue;
00106                         }
00107                 }
00108 
00109                 if (source_list == NULL) {
00110                         match_source = 1;
00111                 } else {
00112                         const qpol_type_t *source_type;
00113                         if (qpol_terule_get_source_type(p->p, rule, &source_type) < 0) {
00114                                 goto cleanup;
00115                         }
00116                         if (apol_vector_get_index(source_list, source_type, NULL, NULL, &i) == 0) {
00117                                 match_source = 1;
00118                         }
00119                 }
00120 
00121                 /* if source did not match, but treating source symbol
00122                  * as any field, then delay rejecting this rule until
00123                  * the target and default have been checked */
00124                 if (!source_as_any && !match_source) {
00125                         continue;
00126                 }
00127 
00128                 if (target_list == NULL || (source_as_any && match_source)) {
00129                         match_target = 1;
00130                 } else {
00131                         const qpol_type_t *target_type;
00132                         if (qpol_terule_get_target_type(p->p, rule, &target_type) < 0) {
00133                                 goto cleanup;
00134                         }
00135                         if (apol_vector_get_index(target_list, target_type, NULL, NULL, &i) == 0) {
00136                                 match_target = 1;
00137                         }
00138                 }
00139 
00140                 if (!source_as_any && !match_target) {
00141                         continue;
00142                 }
00143 
00144                 if (default_list == NULL || (source_as_any && match_source) || (source_as_any && match_target)) {
00145                         match_default = 1;
00146                 } else {
00147                         const qpol_type_t *default_type;
00148                         if (qpol_terule_get_default_type(p->p, rule, &default_type) < 0) {
00149                                 goto cleanup;
00150                         }
00151                         if (apol_vector_get_index(default_list, default_type, NULL, NULL, &i) == 0) {
00152                                 match_default = 1;
00153                         }
00154                 }
00155 
00156                 if (!source_as_any && !match_default) {
00157                         continue;
00158                 }
00159                 /* at least one thing must match if source_as_any was given */
00160                 if (source_as_any && (!match_source && !match_target && !match_default)) {
00161                         continue;
00162                 }
00163 
00164                 if (class_list != NULL) {
00165                         const qpol_class_t *obj_class;
00166                         if (qpol_terule_get_object_class(p->p, rule, &obj_class) < 0) {
00167                                 goto cleanup;
00168                         }
00169                         if (apol_vector_get_index(class_list, obj_class, NULL, NULL, &i) < 0) {
00170                                 continue;
00171                         }
00172                 }
00173 
00174                 if (apol_vector_append(v, rule)) {
00175                         ERR(p, "%s", strerror(ENOMEM));
00176                         goto cleanup;
00177                 }
00178         }
00179 
00180         retv = 0;
00181 
00182       cleanup:
00183         apol_regex_destroy(&bool_regex);
00184         qpol_iterator_destroy(&iter);
00185         return retv;
00186 }
00187 
00188 int apol_terule_get_by_query(const apol_policy_t * p, const apol_terule_query_t * t, apol_vector_t ** v)
00189 {
00190         apol_vector_t *source_list = NULL, *target_list = NULL, *class_list = NULL, *default_list = NULL;
00191         int retval = -1, source_as_any = 0, is_regex = 0;
00192         char *bool_name = NULL;
00193         *v = NULL;
00194         unsigned int flags = 0;
00195 
00196         uint32_t rule_type = QPOL_RULE_TYPE_TRANS | QPOL_RULE_TYPE_MEMBER | QPOL_RULE_TYPE_CHANGE;
00197         if (t != NULL) {
00198                 if (t->rules != 0) {
00199                         rule_type &= t->rules;
00200                 }
00201                 flags = t->flags;
00202                 is_regex = t->flags & APOL_QUERY_REGEX;
00203                 bool_name = t->bool_name;
00204                 if (t->source != NULL &&
00205                     (source_list =
00206                      apol_query_create_candidate_type_list(p, t->source, is_regex,
00207                                                            t->flags & APOL_QUERY_SOURCE_INDIRECT,
00208                                                            ((t->flags & (APOL_QUERY_SOURCE_TYPE | APOL_QUERY_SOURCE_ATTRIBUTE)) /
00209                                                             APOL_QUERY_SOURCE_TYPE))) == NULL) {
00210                         goto cleanup;
00211                 }
00212                 if ((t->flags & APOL_QUERY_SOURCE_AS_ANY) && t->source != NULL) {
00213                         default_list = target_list = source_list;
00214                         source_as_any = 1;
00215                 } else {
00216                         if (t->target != NULL &&
00217                             (target_list =
00218                              apol_query_create_candidate_type_list(p, t->target, is_regex,
00219                                                                    t->flags & APOL_QUERY_TARGET_INDIRECT,
00220                                                                    ((t->
00221                                                                      flags & (APOL_QUERY_TARGET_TYPE | APOL_QUERY_TARGET_ATTRIBUTE))
00222                                                                     / APOL_QUERY_TARGET_TYPE))) == NULL) {
00223                                 goto cleanup;
00224                         }
00225                         if (t->default_type != NULL &&
00226                             (default_list =
00227                              apol_query_create_candidate_type_list(p, t->default_type, is_regex, 0,
00228                                                                    APOL_QUERY_SYMBOL_IS_TYPE)) == NULL) {
00229                                 goto cleanup;
00230                         }
00231                 }
00232                 if (t->classes != NULL &&
00233                     apol_vector_get_size(t->classes) > 0 &&
00234                     (class_list = apol_query_create_candidate_class_list(p, t->classes)) == NULL) {
00235                         goto cleanup;
00236                 }
00237         }
00238 
00239         if ((*v = apol_vector_create(NULL)) == NULL) {
00240                 ERR(p, "%s", strerror(errno));
00241                 goto cleanup;
00242         }
00243 
00244         if (rule_select(p, *v, rule_type, flags, source_list, target_list, class_list, default_list, bool_name)) {
00245                 goto cleanup;
00246         }
00247 
00248         retval = 0;
00249       cleanup:
00250         if (retval != 0) {
00251                 apol_vector_destroy(v);
00252         }
00253         apol_vector_destroy(&source_list);
00254         if (!source_as_any) {
00255                 apol_vector_destroy(&target_list);
00256                 apol_vector_destroy(&default_list);
00257         }
00258         apol_vector_destroy(&class_list);
00259         return retval;
00260 }
00261 
00262 int apol_syn_terule_get_by_query(const apol_policy_t * p, const apol_terule_query_t * t, apol_vector_t ** v)
00263 {
00264         apol_vector_t *source_list = NULL, *target_list = NULL, *class_list = NULL, *default_list = NULL, *syn_v = NULL;
00265         int retval = -1, source_as_any = 0, is_regex = 0;
00266         char *bool_name = NULL;
00267         *v = NULL;
00268         size_t i;
00269         unsigned int flags = 0;
00270 
00271         if (!p || !qpol_policy_has_capability(apol_policy_get_qpol(p), QPOL_CAP_SYN_RULES)) {
00272                 ERR(p, "%s", strerror(EINVAL));
00273                 goto cleanup;
00274         }
00275 
00276         uint32_t rule_type = QPOL_RULE_TYPE_TRANS | QPOL_RULE_TYPE_MEMBER | QPOL_RULE_TYPE_CHANGE;
00277         if (t != NULL) {
00278                 if (t->rules != 0) {
00279                         rule_type &= t->rules;
00280                 }
00281                 flags = t->flags;
00282                 is_regex = t->flags & APOL_QUERY_REGEX;
00283                 bool_name = t->bool_name;
00284                 if (t->source != NULL &&
00285                     (source_list =
00286                      apol_query_create_candidate_syn_type_list(p, t->source, is_regex,
00287                                                                t->flags & APOL_QUERY_SOURCE_INDIRECT,
00288                                                                ((t->flags & (APOL_QUERY_SOURCE_TYPE |
00289                                                                              APOL_QUERY_SOURCE_ATTRIBUTE)) /
00290                                                                 APOL_QUERY_SOURCE_TYPE))) == NULL) {
00291                         goto cleanup;
00292                 }
00293                 if ((t->flags & APOL_QUERY_SOURCE_AS_ANY) && t->source != NULL) {
00294                         default_list = target_list = source_list;
00295                         source_as_any = 1;
00296                 } else {
00297                         if (t->target != NULL &&
00298                             (target_list =
00299                              apol_query_create_candidate_syn_type_list(p, t->target, is_regex,
00300                                                                        t->flags & APOL_QUERY_TARGET_INDIRECT,
00301                                                                        ((t->flags & (APOL_QUERY_TARGET_TYPE |
00302                                                                                      APOL_QUERY_TARGET_ATTRIBUTE))
00303                                                                         / APOL_QUERY_TARGET_TYPE))) == NULL) {
00304                                 goto cleanup;
00305                         }
00306                         if (t->default_type != NULL &&
00307                             (default_list =
00308                              apol_query_create_candidate_type_list(p, t->default_type, is_regex, 0,
00309                                                                    APOL_QUERY_SYMBOL_IS_TYPE)) == NULL) {
00310                                 goto cleanup;
00311                         }
00312                 }
00313                 if (t->classes != NULL &&
00314                     apol_vector_get_size(t->classes) > 0 &&
00315                     (class_list = apol_query_create_candidate_class_list(p, t->classes)) == NULL) {
00316                         goto cleanup;
00317                 }
00318         }
00319 
00320         if ((*v = apol_vector_create(NULL)) == NULL) {
00321                 ERR(p, "%s", strerror(errno));
00322                 goto cleanup;
00323         }
00324 
00325         if (rule_select(p, *v, rule_type, flags, source_list, target_list, class_list, default_list, bool_name)) {
00326                 goto cleanup;
00327         }
00328 
00329         syn_v = apol_terule_list_to_syn_terules(p, *v);
00330         if (!syn_v) {
00331                 goto cleanup;
00332         }
00333         apol_vector_destroy(v);
00334         *v = syn_v;
00335         syn_v = NULL;
00336 
00337         /* if source and target are indirect skip post filtering type sets */
00338         if ((t->flags & APOL_QUERY_SOURCE_INDIRECT) && (t->flags & (APOL_QUERY_TARGET_INDIRECT | APOL_QUERY_SOURCE_AS_ANY))) {
00339                 retval = 0;
00340                 goto cleanup;
00341         }
00342         /* if not searching by source, target, or default we are done */
00343         if (!source_list && !target_list && !default_list) {
00344                 retval = 0;
00345                 goto cleanup;
00346         }
00347 
00348         if (source_list && !(t->flags & APOL_QUERY_SOURCE_INDIRECT)) {
00349                 apol_vector_destroy(&source_list);
00350                 source_list =
00351                         apol_query_create_candidate_type_list(p, t->source, is_regex, 0,
00352                                                               ((t->flags & (APOL_QUERY_SOURCE_TYPE | APOL_QUERY_SOURCE_ATTRIBUTE)) /
00353                                                                APOL_QUERY_SOURCE_TYPE));
00354                 if (!source_list)
00355                         goto cleanup;
00356         }
00357         if (target_list && (source_as_any || !(t->flags & APOL_QUERY_TARGET_INDIRECT))) {
00358                 if (source_as_any) {
00359                         target_list = source_list;
00360                 } else {
00361                         apol_vector_destroy(&target_list);
00362                         target_list =
00363                                 apol_query_create_candidate_type_list(p, t->target, is_regex, 0,
00364                                                                       ((t->flags & (APOL_QUERY_SOURCE_TYPE |
00365                                                                                     APOL_QUERY_SOURCE_ATTRIBUTE)) /
00366                                                                        APOL_QUERY_SOURCE_TYPE));
00367                         if (!target_list)
00368                                 goto cleanup;
00369                 }
00370         }
00371         if (source_as_any) {
00372                 default_list = source_list;
00373         }
00374 
00375         for (i = 0; i < apol_vector_get_size(*v); i++) {
00376                 qpol_syn_terule_t *srule = apol_vector_get_element(*v, i);
00377                 const qpol_type_set_t *stypes = NULL, *ttypes = NULL;
00378                 const qpol_type_t *dflt = NULL;
00379                 size_t j;
00380                 int uses_source = 0, uses_target = 0, uses_default = 0;
00381                 qpol_syn_terule_get_source_type_set(p->p, srule, &stypes);
00382                 qpol_syn_terule_get_target_type_set(p->p, srule, &ttypes);
00383                 if (source_list && !(t->flags & APOL_QUERY_SOURCE_INDIRECT)) {
00384                         uses_source = apol_query_type_set_uses_types_directly(p, stypes, source_list);
00385                         if (uses_source < 0)
00386                                 goto cleanup;
00387                 } else if (source_list && (t->flags & APOL_QUERY_SOURCE_INDIRECT)) {
00388                         uses_source = 1;
00389                 } else if (!source_list) {
00390                         uses_source = 1;
00391                 }
00392 
00393                 if (target_list
00394                     && !(t->flags & APOL_QUERY_TARGET_INDIRECT || (source_as_any && t->flags & APOL_QUERY_SOURCE_INDIRECT))) {
00395                         uses_target = apol_query_type_set_uses_types_directly(p, ttypes, target_list);
00396                         if (uses_target < 0)
00397                                 goto cleanup;
00398                 } else if (target_list
00399                            && (t->flags & APOL_QUERY_TARGET_INDIRECT || (source_as_any && t->flags & APOL_QUERY_SOURCE_INDIRECT))) {
00400                         uses_target = 1;
00401                 } else if (!target_list) {
00402                         uses_target = 1;
00403                 }
00404 
00405                 if (default_list) {
00406                         qpol_syn_terule_get_default_type(p->p, srule, &dflt);
00407                         if (!apol_vector_get_index(default_list, (void *)dflt, NULL, NULL, &j))
00408                                 uses_default = 1;
00409                 } else if (!default_list) {
00410                         uses_default = 1;
00411                 }
00412 
00413                 if (!((uses_source && uses_target && uses_default)
00414                       || (source_as_any && (uses_source || uses_target || uses_default)))) {
00415                         apol_vector_remove(*v, i);
00416                         i--;
00417                 }
00418         }
00419 
00420         retval = 0;
00421       cleanup:
00422         if (retval != 0) {
00423                 apol_vector_destroy(v);
00424         }
00425         apol_vector_destroy(&syn_v);
00426         apol_vector_destroy(&source_list);
00427         if (!source_as_any) {
00428                 apol_vector_destroy(&target_list);
00429                 apol_vector_destroy(&default_list);
00430         }
00431         apol_vector_destroy(&class_list);
00432         return retval;
00433 }
00434 
00435 apol_terule_query_t *apol_terule_query_create(void)
00436 {
00437         apol_terule_query_t *t = calloc(1, sizeof(apol_terule_query_t));
00438         if (t != NULL) {
00439                 t->rules = ~0U;
00440                 t->flags =
00441                         (APOL_QUERY_SOURCE_TYPE | APOL_QUERY_SOURCE_ATTRIBUTE | APOL_QUERY_TARGET_TYPE |
00442                          APOL_QUERY_TARGET_ATTRIBUTE);
00443         }
00444         return t;
00445 }
00446 
00447 void apol_terule_query_destroy(apol_terule_query_t ** t)
00448 {
00449         if (*t != NULL) {
00450                 free((*t)->source);
00451                 free((*t)->target);
00452                 free((*t)->default_type);
00453                 free((*t)->bool_name);
00454                 apol_vector_destroy(&(*t)->classes);
00455                 free(*t);
00456                 *t = NULL;
00457         }
00458 }
00459 
00460 int apol_terule_query_set_rules(const apol_policy_t * p __attribute__ ((unused)), apol_terule_query_t * t, unsigned int rules)
00461 {
00462         if (rules != 0) {
00463                 t->rules = rules;
00464         } else {
00465                 t->rules = ~0U;
00466         }
00467         return 0;
00468 }
00469 
00470 int apol_terule_query_set_source(const apol_policy_t * p, apol_terule_query_t * t, const char *symbol, int is_indirect)
00471 {
00472         apol_query_set_flag(p, &t->flags, is_indirect, APOL_QUERY_SOURCE_INDIRECT);
00473         return apol_query_set(p, &t->source, NULL, symbol);
00474 }
00475 
00476 int apol_terule_query_set_source_component(const apol_policy_t * p, apol_terule_query_t * t, unsigned int component)
00477 {
00478         if (!t || !(component & APOL_QUERY_SYMBOL_IS_BOTH)) {
00479                 ERR(p, "%s", strerror(EINVAL));
00480                 errno = EINVAL;
00481                 return -1;
00482         }
00483         apol_query_set_flag(p, &t->flags, component & APOL_QUERY_SYMBOL_IS_TYPE, APOL_QUERY_SOURCE_TYPE);
00484         apol_query_set_flag(p, &t->flags, component & APOL_QUERY_SYMBOL_IS_ATTRIBUTE, APOL_QUERY_SOURCE_ATTRIBUTE);
00485         return 0;
00486 }
00487 
00488 int apol_terule_query_set_target(const apol_policy_t * p, apol_terule_query_t * t, const char *symbol, int is_indirect)
00489 {
00490         apol_query_set_flag(p, &t->flags, is_indirect, APOL_QUERY_TARGET_INDIRECT);
00491         return apol_query_set(p, &t->target, NULL, symbol);
00492 }
00493 
00494 int apol_terule_query_set_target_component(const apol_policy_t * p, apol_terule_query_t * t, unsigned int component)
00495 {
00496         if (!t || !(component & APOL_QUERY_SYMBOL_IS_BOTH)) {
00497                 ERR(p, "%s", strerror(EINVAL));
00498                 errno = EINVAL;
00499                 return -1;
00500         }
00501         apol_query_set_flag(p, &t->flags, component & APOL_QUERY_SYMBOL_IS_TYPE, APOL_QUERY_TARGET_TYPE);
00502         apol_query_set_flag(p, &t->flags, component & APOL_QUERY_SYMBOL_IS_ATTRIBUTE, APOL_QUERY_TARGET_ATTRIBUTE);
00503         return 0;
00504 }
00505 
00506 int apol_terule_query_set_default(const apol_policy_t * p, apol_terule_query_t * t, const char *symbol)
00507 {
00508         return apol_query_set(p, &t->default_type, NULL, symbol);
00509 }
00510 
00511 int apol_terule_query_append_class(const apol_policy_t * p, apol_terule_query_t * t, const char *obj_class)
00512 {
00513         char *s = NULL;
00514         if (obj_class == NULL) {
00515                 apol_vector_destroy(&t->classes);
00516         } else if ((s = strdup(obj_class)) == NULL || (t->classes == NULL && (t->classes = apol_vector_create(free)) == NULL)
00517                    || apol_vector_append(t->classes, s) < 0) {
00518                 ERR(p, "%s", strerror(errno));
00519                 free(s);
00520                 return -1;
00521         }
00522         return 0;
00523 }
00524 
00525 int apol_terule_query_set_bool(const apol_policy_t * p, apol_terule_query_t * t, const char *bool_name)
00526 {
00527         return apol_query_set(p, &t->bool_name, NULL, bool_name);
00528 }
00529 
00530 int apol_terule_query_set_enabled(const apol_policy_t * p, apol_terule_query_t * t, int is_enabled)
00531 {
00532         return apol_query_set_flag(p, &t->flags, is_enabled, APOL_QUERY_ONLY_ENABLED);
00533 }
00534 
00535 int apol_terule_query_set_source_any(const apol_policy_t * p, apol_terule_query_t * t, int is_any)
00536 {
00537         return apol_query_set_flag(p, &t->flags, is_any, APOL_QUERY_SOURCE_AS_ANY);
00538 }
00539 
00540 int apol_terule_query_set_regex(const apol_policy_t * p, apol_terule_query_t * t, int is_regex)
00541 {
00542         return apol_query_set_regex(p, &t->flags, is_regex);
00543 }
00544 
00545 /**
00546  * Comparison function for two syntactic terules.  Will return -1 if
00547  * a's line number is before b's, 1 if b is greater.
00548  */
00549 static int apol_syn_terule_comp(const void *a, const void *b, void *data)
00550 {
00551         qpol_syn_terule_t *r1 = (qpol_syn_terule_t *) a;
00552         qpol_syn_terule_t *r2 = (qpol_syn_terule_t *) b;
00553         apol_policy_t *p = (apol_policy_t *) data;
00554         unsigned long num1, num2;
00555         if (qpol_syn_terule_get_lineno(p->p, r1, &num1) < 0 || qpol_syn_terule_get_lineno(p->p, r2, &num2) < 0) {
00556                 return 0;
00557         }
00558         if (num1 != num2) {
00559                 return (int)num1 - (int)num2;
00560         }
00561         return (int)((char *)r1 - (char *)r2);
00562 }
00563 
00564 apol_vector_t *apol_terule_to_syn_terules(const apol_policy_t * p, const qpol_terule_t * rule)
00565 {
00566         apol_vector_t *v = NULL;
00567         qpol_iterator_t *iter = NULL;
00568         qpol_syn_terule_t *syn_terule;
00569         int retval = -1, error = 0;
00570         if (qpol_terule_get_syn_terule_iter(p->p, rule, &iter) < 0) {
00571                 error = errno;
00572                 goto cleanup;
00573         }
00574         if ((v = apol_vector_create(NULL)) == NULL) {
00575                 error = errno;
00576                 ERR(p, "%s", strerror(error));
00577                 goto cleanup;
00578         }
00579         for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
00580                 if (qpol_iterator_get_item(iter, (void **)&syn_terule) < 0) {
00581                         error = errno;
00582                         ERR(p, "%s", strerror(error));
00583                         goto cleanup;
00584                 }
00585                 if (apol_vector_append(v, syn_terule) < 0) {
00586                         error = errno;
00587                         ERR(p, "%s", strerror(error));
00588                         goto cleanup;
00589                 }
00590         }
00591         apol_vector_sort_uniquify(v, apol_syn_terule_comp, (void *)p);
00592         retval = 0;
00593       cleanup:
00594         qpol_iterator_destroy(&iter);
00595         if (retval != 0) {
00596                 apol_vector_destroy(&v);
00597                 errno = error;
00598                 return NULL;
00599         }
00600         return v;
00601 }
00602 
00603 apol_vector_t *apol_terule_list_to_syn_terules(const apol_policy_t * p, const apol_vector_t * rules)
00604 {
00605         apol_bst_t *b = NULL;
00606         qpol_terule_t *rule;
00607         qpol_iterator_t *iter = NULL;
00608         qpol_syn_terule_t *syn_terule;
00609         apol_vector_t *v = NULL;
00610         size_t i;
00611         int retval = -1, error = 0;
00612 
00613         if ((b = apol_bst_create(apol_syn_terule_comp, NULL)) == NULL) {
00614                 error = errno;
00615                 ERR(p, "%s", strerror(error));
00616                 goto cleanup;
00617         }
00618         for (i = 0; i < apol_vector_get_size(rules); i++) {
00619                 rule = apol_vector_get_element(rules, i);
00620                 if (qpol_terule_get_syn_terule_iter(p->p, rule, &iter) < 0) {
00621                         error = errno;
00622                         goto cleanup;
00623                 }
00624                 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
00625                         if (qpol_iterator_get_item(iter, (void **)&syn_terule) < 0) {
00626                                 error = errno;
00627                                 ERR(p, "%s", strerror(error));
00628                                 goto cleanup;
00629                         }
00630                         if (apol_bst_insert(b, syn_terule, (void *)p) < 0) {
00631                                 error = errno;
00632                                 ERR(p, "%s", strerror(error));
00633                                 goto cleanup;
00634                         }
00635                 }
00636                 qpol_iterator_destroy(&iter);
00637         }
00638         if ((v = apol_bst_get_vector(b, 1)) == NULL) {
00639                 error = errno;
00640                 ERR(p, "%s", strerror(error));
00641                 goto cleanup;
00642         }
00643         retval = 0;
00644       cleanup:
00645         apol_bst_destroy(&b);
00646         qpol_iterator_destroy(&iter);
00647         if (retval != 0) {
00648                 errno = error;
00649                 return NULL;
00650         }
00651         return v;
00652 }
00653 
00654 char *apol_terule_render(const apol_policy_t * policy, const qpol_terule_t * rule)
00655 {
00656         char *tmp = NULL;
00657         const char *tmp_name = NULL;
00658         const char *rule_type_str;
00659         int error = 0;
00660         size_t tmp_sz = 0;
00661         uint32_t rule_type = 0;
00662         const qpol_type_t *type = NULL;
00663         const qpol_class_t *obj_class = NULL;
00664 
00665         if (!policy || !rule) {
00666                 ERR(policy, "%s", strerror(EINVAL));
00667                 errno = EINVAL;
00668                 return NULL;
00669         }
00670 
00671         /* rule type */
00672         if (qpol_terule_get_rule_type(policy->p, rule, &rule_type)) {
00673                 error = errno;
00674                 errno = error;
00675                 return NULL;
00676         }
00677         if (!(rule_type &= (QPOL_RULE_TYPE_TRANS | QPOL_RULE_TYPE_CHANGE | QPOL_RULE_TYPE_MEMBER))) {
00678                 ERR(policy, "%s", "Invalid type rule type");
00679                 errno = EINVAL;
00680                 return NULL;
00681         }
00682         if (!(rule_type_str = apol_rule_type_to_str(rule_type))) {
00683                 ERR(policy, "%s", "Type rule has multiple rule types?");
00684                 errno = EINVAL;
00685                 return NULL;
00686         }
00687         if (apol_str_append(&tmp, &tmp_sz, rule_type_str) || apol_str_append(&tmp, &tmp_sz, " ")) {
00688                 error = error;
00689                 ERR(policy, "%s", strerror(error));
00690                 goto err;
00691         }
00692 
00693         /* source type */
00694         if (qpol_terule_get_source_type(policy->p, rule, &type)) {
00695                 error = errno;
00696                 goto err;
00697         }
00698         if (qpol_type_get_name(policy->p, type, &tmp_name)) {
00699                 error = errno;
00700                 goto err;
00701         }
00702         if (apol_str_append(&tmp, &tmp_sz, tmp_name) || apol_str_append(&tmp, &tmp_sz, " ")) {
00703                 error = error;
00704                 ERR(policy, "%s", strerror(error));
00705                 goto err;
00706         }
00707 
00708         /* target type */
00709         if (qpol_terule_get_target_type(policy->p, rule, &type)) {
00710                 error = errno;
00711                 goto err;
00712         }
00713         if (qpol_type_get_name(policy->p, type, &tmp_name)) {
00714                 error = errno;
00715                 goto err;
00716         }
00717         if (apol_str_append(&tmp, &tmp_sz, tmp_name) || apol_str_append(&tmp, &tmp_sz, " : ")) {
00718                 error = error;
00719                 ERR(policy, "%s", strerror(error));
00720                 goto err;
00721         }
00722 
00723         /* object class */
00724         if (qpol_terule_get_object_class(policy->p, rule, &obj_class)) {
00725                 error = errno;
00726                 goto err;
00727         }
00728         if (qpol_class_get_name(policy->p, obj_class, &tmp_name)) {
00729                 error = errno;
00730                 goto err;
00731         }
00732         if (apol_str_append(&tmp, &tmp_sz, tmp_name) || apol_str_append(&tmp, &tmp_sz, " ")) {
00733                 error = error;
00734                 ERR(policy, "%s", strerror(error));
00735                 goto err;
00736         }
00737 
00738         /* default type */
00739         if (qpol_terule_get_default_type(policy->p, rule, &type)) {
00740                 error = errno;
00741                 goto err;
00742         }
00743         if (qpol_type_get_name(policy->p, type, &tmp_name)) {
00744                 error = errno;
00745                 goto err;
00746         }
00747         if (apol_str_append(&tmp, &tmp_sz, tmp_name) || apol_str_append(&tmp, &tmp_sz, ";")) {
00748                 error = error;
00749                 ERR(policy, "%s", strerror(error));
00750                 goto err;
00751         }
00752 
00753         return tmp;
00754 
00755       err:
00756         free(tmp);
00757         errno = error;
00758         return NULL;
00759 }
00760 
00761 char *apol_syn_terule_render(const apol_policy_t * policy, const qpol_syn_terule_t * rule)
00762 {
00763         char *tmp = NULL;
00764         const char *tmp_name = NULL;
00765         const char *rule_type_str;
00766         int error = 0;
00767         uint32_t rule_type = 0, star = 0, comp = 0;
00768         const qpol_type_t *type = NULL;
00769         const qpol_class_t *obj_class = NULL;
00770         qpol_iterator_t *iter = NULL, *iter2 = NULL;
00771         size_t tmp_sz = 0, iter_sz = 0, iter2_sz = 0;
00772         const qpol_type_set_t *set = NULL;
00773 
00774         if (!policy || !rule) {
00775                 ERR(policy, "%s", strerror(EINVAL));
00776                 errno = EINVAL;
00777                 return NULL;
00778         }
00779 
00780         /* rule type */
00781         if (qpol_syn_terule_get_rule_type(policy->p, rule, &rule_type)) {
00782                 error = errno;
00783                 return NULL;
00784         }
00785         if (!(rule_type &= (QPOL_RULE_TYPE_TRANS | QPOL_RULE_TYPE_CHANGE | QPOL_RULE_TYPE_MEMBER))) {
00786                 ERR(policy, "%s", "Invalid te rule type");
00787                 errno = EINVAL;
00788                 return NULL;
00789         }
00790         if (!(rule_type_str = apol_rule_type_to_str(rule_type))) {
00791                 ERR(policy, "%s", "Te rule has multiple rule types?");
00792                 errno = EINVAL;
00793                 return NULL;
00794         }
00795         if (apol_str_append(&tmp, &tmp_sz, rule_type_str) || apol_str_append(&tmp, &tmp_sz, " ")) {
00796                 error = error;
00797                 ERR(policy, "%s", strerror(error));
00798                 goto err;
00799         }
00800 
00801         /* source type set */
00802         if (qpol_syn_terule_get_source_type_set(policy->p, rule, &set)) {
00803                 error = errno;
00804                 goto err;
00805         }
00806         if (qpol_type_set_get_is_star(policy->p, set, &star)) {
00807                 error = errno;
00808                 goto err;
00809         }
00810         if (star) {
00811                 if (apol_str_append(&tmp, &tmp_sz, "* ")) {
00812                         error = error;
00813                         ERR(policy, "%s", strerror(error));
00814                         goto err;
00815                 }
00816         } else {
00817                 if (qpol_type_set_get_is_comp(policy->p, set, &comp)) {
00818                         error = errno;
00819                         goto err;
00820                 }
00821                 if (comp) {
00822                         if (apol_str_append(&tmp, &tmp_sz, "~")) {
00823                                 error = error;
00824                                 ERR(policy, "%s", strerror(error));
00825                                 goto err;
00826                         }
00827                 }
00828                 if (qpol_type_set_get_included_types_iter(policy->p, set, &iter)) {
00829                         error = errno;
00830                         goto err;
00831                 }
00832                 if (qpol_type_set_get_subtracted_types_iter(policy->p, set, &iter2)) {
00833                         error = errno;
00834                         goto err;
00835                 }
00836                 if (qpol_iterator_get_size(iter, &iter_sz) || qpol_iterator_get_size(iter2, &iter2_sz)) {
00837                         error = errno;
00838                         ERR(policy, "%s", strerror(error));
00839                         goto err;
00840                 }
00841                 if (iter_sz + iter2_sz > 1) {
00842                         if (apol_str_append(&tmp, &tmp_sz, "{ ")) {
00843                                 error = error;
00844                                 ERR(policy, "%s", strerror(error));
00845                                 goto err;
00846                         }
00847                 }
00848                 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
00849                         if (qpol_iterator_get_item(iter, (void **)&type)) {
00850                                 error = errno;
00851                                 ERR(policy, "%s", strerror(error));
00852                                 goto err;
00853                         }
00854                         if (qpol_type_get_name(policy->p, type, &tmp_name)) {
00855                                 error = errno;
00856                                 goto err;
00857                         }
00858                         if (apol_str_append(&tmp, &tmp_sz, tmp_name) || apol_str_append(&tmp, &tmp_sz, " ")) {
00859                                 error = error;
00860                                 ERR(policy, "%s", strerror(error));
00861                                 goto err;
00862                         }
00863                 }
00864                 for (; !qpol_iterator_end(iter2); qpol_iterator_next(iter2)) {
00865                         if (qpol_iterator_get_item(iter2, (void **)&type)) {
00866                                 error = errno;
00867                                 ERR(policy, "%s", strerror(error));
00868                                 goto err;
00869                         }
00870                         if (qpol_type_get_name(policy->p, type, &tmp_name)) {
00871                                 error = errno;
00872                                 goto err;
00873                         }
00874                         if (apol_str_append(&tmp, &tmp_sz, "-") ||
00875                             apol_str_append(&tmp, &tmp_sz, tmp_name) || apol_str_append(&tmp, &tmp_sz, " ")) {
00876                                 error = error;
00877                                 ERR(policy, "%s", strerror(error));
00878                                 goto err;
00879                         }
00880                 }
00881                 qpol_iterator_destroy(&iter);
00882                 qpol_iterator_destroy(&iter2);
00883                 if (iter_sz + iter2_sz > 1) {
00884                         if (apol_str_append(&tmp, &tmp_sz, "} ")) {
00885                                 error = error;
00886                                 ERR(policy, "%s", strerror(error));
00887                                 goto err;
00888                         }
00889                 }
00890         }
00891 
00892         /* target type set */
00893         if (qpol_syn_terule_get_target_type_set(policy->p, rule, &set)) {
00894                 error = errno;
00895                 goto err;
00896         }
00897         if (qpol_type_set_get_is_star(policy->p, set, &star)) {
00898                 error = errno;
00899                 goto err;
00900         }
00901         if (star) {
00902                 if (apol_str_append(&tmp, &tmp_sz, "* ")) {
00903                         error = error;
00904                         ERR(policy, "%s", strerror(error));
00905                         goto err;
00906                 }
00907         } else {
00908                 if (qpol_type_set_get_is_comp(policy->p, set, &comp)) {
00909                         error = errno;
00910                         goto err;
00911                 }
00912                 if (comp) {
00913                         if (apol_str_append(&tmp, &tmp_sz, "~")) {
00914                                 error = error;
00915                                 ERR(policy, "%s", strerror(error));
00916                                 goto err;
00917                         }
00918                 }
00919                 if (qpol_type_set_get_included_types_iter(policy->p, set, &iter)) {
00920                         error = errno;
00921                         goto err;
00922                 }
00923                 if (qpol_type_set_get_subtracted_types_iter(policy->p, set, &iter2)) {
00924                         error = errno;
00925                         goto err;
00926                 }
00927                 if (qpol_iterator_get_size(iter, &iter_sz) || qpol_iterator_get_size(iter2, &iter2_sz)) {
00928                         error = errno;
00929                         ERR(policy, "%s", strerror(error));
00930                         goto err;
00931                 }
00932                 if (iter_sz + iter2_sz > 1) {
00933                         if (apol_str_append(&tmp, &tmp_sz, "{ ")) {
00934                                 error = error;
00935                                 ERR(policy, "%s", strerror(error));
00936                                 goto err;
00937                         }
00938                 }
00939                 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
00940                         if (qpol_iterator_get_item(iter, (void **)&type)) {
00941                                 error = errno;
00942                                 ERR(policy, "%s", strerror(error));
00943                                 goto err;
00944                         }
00945                         if (qpol_type_get_name(policy->p, type, &tmp_name)) {
00946                                 error = errno;
00947                                 goto err;
00948                         }
00949                         if (apol_str_append(&tmp, &tmp_sz, tmp_name) || apol_str_append(&tmp, &tmp_sz, " ")) {
00950                                 error = error;
00951                                 ERR(policy, "%s", strerror(error));
00952                                 goto err;
00953                         }
00954                 }
00955                 for (; !qpol_iterator_end(iter2); qpol_iterator_next(iter2)) {
00956                         if (qpol_iterator_get_item(iter2, (void **)&type)) {
00957                                 error = errno;
00958                                 ERR(policy, "%s", strerror(error));
00959                                 goto err;
00960                         }
00961                         if (qpol_type_get_name(policy->p, type, &tmp_name)) {
00962                                 error = errno;
00963                                 goto err;
00964                         }
00965                         if (apol_str_append(&tmp, &tmp_sz, "-") ||
00966                             apol_str_append(&tmp, &tmp_sz, tmp_name) || apol_str_append(&tmp, &tmp_sz, " ")) {
00967                                 error = error;
00968                                 ERR(policy, "%s", strerror(error));
00969                                 goto err;
00970                         }
00971                 }
00972                 qpol_iterator_destroy(&iter);
00973                 qpol_iterator_destroy(&iter2);
00974                 if (iter_sz + iter2_sz > 1) {
00975                         if (apol_str_append(&tmp, &tmp_sz, "} ")) {
00976                                 error = error;
00977                                 ERR(policy, "%s", strerror(error));
00978                                 goto err;
00979                         }
00980                 }
00981         }
00982 
00983         if (apol_str_append(&tmp, &tmp_sz, ": ")) {
00984                 error = error;
00985                 ERR(policy, "%s", strerror(error));
00986                 goto err;
00987         }
00988 
00989         /* object classes */
00990         if (qpol_syn_terule_get_class_iter(policy->p, rule, &iter)) {
00991                 error = errno;
00992                 goto err;
00993         }
00994         if (qpol_iterator_get_size(iter, &iter_sz)) {
00995                 error = errno;
00996                 ERR(policy, "%s", strerror(error));
00997                 goto err;
00998         }
00999         if (iter_sz > 1) {
01000                 if (apol_str_append(&tmp, &tmp_sz, "{ ")) {
01001                         error = errno;
01002                         ERR(policy, "%s", strerror(error));
01003                         goto err;
01004                 }
01005         }
01006         for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
01007                 if (qpol_iterator_get_item(iter, (void **)&obj_class)) {
01008                         error = errno;
01009                         ERR(policy, "%s", strerror(error));
01010                         goto err;
01011                 }
01012                 if (qpol_class_get_name(policy->p, obj_class, &tmp_name)) {
01013                         error = errno;
01014                         goto err;
01015                 }
01016                 if (apol_str_append(&tmp, &tmp_sz, tmp_name) || apol_str_append(&tmp, &tmp_sz, " ")) {
01017                         error = errno;
01018                         ERR(policy, "%s", strerror(error));
01019                         goto err;
01020                 }
01021         }
01022         qpol_iterator_destroy(&iter);
01023         if (iter_sz > 1) {
01024                 if (apol_str_append(&tmp, &tmp_sz, "} ")) {
01025                         error = errno;
01026                         ERR(policy, "%s", strerror(error));
01027                         goto err;
01028                 }
01029         }
01030 
01031         /* default type */
01032         if (qpol_syn_terule_get_default_type(policy->p, rule, &type)) {
01033                 error = errno;
01034                 goto err;
01035         }
01036         if (qpol_type_get_name(policy->p, type, &tmp_name)) {
01037                 error = errno;
01038                 goto err;
01039         }
01040         if (apol_str_append(&tmp, &tmp_sz, tmp_name) || apol_str_append(&tmp, &tmp_sz, ";")) {
01041                 error = errno;
01042                 ERR(policy, "%s", strerror(error));
01043                 goto err;
01044         }
01045 
01046         return tmp;
01047 
01048       err:
01049         free(tmp);
01050         qpol_iterator_destroy(&iter);
01051         qpol_iterator_destroy(&iter2);
01052         errno = error;
01053         return NULL;
01054 }