filter-internal.c

Go to the documentation of this file.
00001 /**
00002  *  @file
00003  *  Implementation of seaudit filters private functions.
00004  *
00005  *  @author Jeremy A. Mowery jmowery@tresys.com
00006  *  @author Jason Tang jtang@tresys.com
00007  *
00008  *  Copyright (C) 2004-2007 Tresys Technology, LLC
00009  *
00010  *  This library is free software; you can redistribute it and/or
00011  *  modify it under the terms of the GNU Lesser General Public
00012  *  License as published by the Free Software Foundation; either
00013  *  version 2.1 of the License, or (at your option) any later version.
00014  *
00015  *  This library is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  *  Lesser General Public License for more details.
00019  *
00020  *  You should have received a copy of the GNU Lesser General Public
00021  *  License along with this library; if not, write to the Free Software
00022  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00023  */
00024 
00025 #include "seaudit_internal.h"
00026 #include "filter-internal.h"
00027 
00028 #include <apol/util.h>
00029 
00030 #include <errno.h>
00031 #include <fnmatch.h>
00032 #include <stdbool.h>
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <time.h>
00036 #include <libxml/uri.h>
00037 
00038 /******************** support functions ********************/
00039 
00040 static int filter_string_vector_read(apol_vector_t ** v, const xmlChar * ch)
00041 {
00042         char *s;
00043         if (*v == NULL && (*v = apol_vector_create_with_capacity(1, free)) == NULL) {
00044                 return -1;
00045         }
00046         if ((s = xmlURIUnescapeString((const char *)ch, 0, NULL)) == NULL || apol_vector_append(*v, s) < 0) {
00047                 free(s);
00048                 return -1;
00049         }
00050         return 0;
00051 }
00052 
00053 static int filter_string_read(char **dest, const xmlChar * ch)
00054 {
00055         free(*dest);
00056         *dest = NULL;
00057         if ((*dest = xmlURIUnescapeString((const char *)ch, 0, NULL)) == NULL) {
00058                 return -1;
00059         }
00060         return 0;
00061 }
00062 
00063 static int filter_ulong_read(unsigned long *dest, const xmlChar * ch)
00064 {
00065         char *s, *endptr;
00066         int retval = -1;
00067         if ((s = xmlURIUnescapeString((const char *)ch, 0, NULL)) == NULL) {
00068                 return -1;
00069         }
00070         *dest = strtoul(s, &endptr, 10);
00071         if (*s != '\0' && *endptr == '\0') {
00072                 retval = 0;
00073         }
00074         free(s);
00075         return retval;
00076 }
00077 
00078 static unsigned int filter_uint_read(unsigned int *dest, const xmlChar * ch)
00079 {
00080         char *s, *endptr;
00081         int retval = -1;
00082         if ((s = xmlURIUnescapeString((const char *)ch, 0, NULL)) == NULL) {
00083                 return -1;
00084         }
00085         *dest = (unsigned int)(strtoul(s, &endptr, 10));
00086         if (*s != '\0' && *endptr == '\0') {
00087                 retval = 0;
00088         }
00089         free(s);
00090         return retval;
00091 }
00092 
00093 static int filter_int_read(int *dest, const xmlChar * ch)
00094 {
00095         char *s, *endptr;
00096         int retval = -1;
00097         if ((s = xmlURIUnescapeString((const char *)ch, 0, NULL)) == NULL) {
00098                 return -1;
00099         }
00100         *dest = (int)(strtol(s, &endptr, 10));
00101         if (*s != '\0' && *endptr == '\0') {
00102                 retval = 0;
00103         }
00104         free(s);
00105         return retval;
00106 }
00107 
00108 static void filter_string_vector_print(const char *criteria_name, apol_vector_t * v, FILE * f, int tabs)
00109 {
00110         int i;
00111         size_t j;
00112         if (v == NULL) {
00113                 return;
00114         }
00115         for (i = 0; i < tabs; i++)
00116                 fprintf(f, "\t");
00117         fprintf(f, "<criteria type=\"%s\">\n", criteria_name);
00118         for (j = 0; j < apol_vector_get_size(v); j++) {
00119                 xmlChar *s = xmlCharStrdup(apol_vector_get_element(v, j));
00120                 xmlChar *escaped = xmlURIEscapeStr(s, NULL);
00121                 for (i = 0; i < tabs + 1; i++) {
00122                         fprintf(f, "\t");
00123                 }
00124                 fprintf(f, "<item>%s</item>\n", escaped);
00125                 free(escaped);
00126                 free(s);
00127         }
00128         for (i = 0; i < tabs; i++)
00129                 fprintf(f, "\t");
00130         fprintf(f, "</criteria>\n");
00131 }
00132 
00133 static void filter_string_print(const char *criteria_name, const char *s, FILE * f, int tabs)
00134 {
00135         int i;
00136         xmlChar *t, *escaped;
00137         if (s == NULL) {
00138                 return;
00139         }
00140         t = xmlCharStrdup(s);
00141         escaped = xmlURIEscapeStr(t, NULL);
00142         for (i = 0; i < tabs; i++)
00143                 fprintf(f, "\t");
00144         fprintf(f, "<criteria type=\"%s\">\n", criteria_name);
00145         for (i = 0; i < tabs + 1; i++) {
00146                 fprintf(f, "\t");
00147         }
00148         fprintf(f, "<item>%s</item>\n", escaped);
00149         for (i = 0; i < tabs; i++)
00150                 fprintf(f, "\t");
00151         fprintf(f, "</criteria>\n");
00152         free(escaped);
00153         free(t);
00154 }
00155 
00156 static void filter_ulong_print(const char *criteria_name, const unsigned long val, FILE * f, int tabs)
00157 {
00158         int i;
00159         for (i = 0; i < tabs; i++)
00160                 fprintf(f, "\t");
00161         fprintf(f, "<criteria type=\"%s\">\n", criteria_name);
00162         for (i = 0; i < tabs + 1; i++) {
00163                 fprintf(f, "\t");
00164         }
00165         fprintf(f, "<item>%lu</item>\n", val);
00166         for (i = 0; i < tabs; i++)
00167                 fprintf(f, "\t");
00168         fprintf(f, "</criteria>\n");
00169 }
00170 
00171 static void filter_uint_print(const char *criteria_name, const unsigned int val, FILE * f, int tabs)
00172 {
00173         int i;
00174         for (i = 0; i < tabs; i++)
00175                 fprintf(f, "\t");
00176         fprintf(f, "<criteria type=\"%s\">\n", criteria_name);
00177         for (i = 0; i < tabs + 1; i++) {
00178                 fprintf(f, "\t");
00179         }
00180         fprintf(f, "<item>%u</item>\n", val);
00181         for (i = 0; i < tabs; i++)
00182                 fprintf(f, "\t");
00183         fprintf(f, "</criteria>\n");
00184 }
00185 
00186 static void filter_int_print(const char *criteria_name, const int val, FILE * f, int tabs)
00187 {
00188         int i;
00189         for (i = 0; i < tabs; i++)
00190                 fprintf(f, "\t");
00191         fprintf(f, "<criteria type=\"%s\">\n", criteria_name);
00192         for (i = 0; i < tabs + 1; i++) {
00193                 fprintf(f, "\t");
00194         }
00195         fprintf(f, "<item>%d</item>\n", val);
00196         for (i = 0; i < tabs; i++)
00197                 fprintf(f, "\t");
00198         fprintf(f, "</criteria>\n");
00199 }
00200 
00201 /******************** filter private functions ********************/
00202 
00203 static bool filter_src_user_is_set(const seaudit_filter_t * filter)
00204 {
00205         return filter->src_users != NULL;
00206 }
00207 
00208 static int filter_src_user_support(const seaudit_message_t * msg)
00209 {
00210         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && msg->data.avc->suser != NULL;
00211 }
00212 
00213 static int filter_src_user_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00214 {
00215         size_t i;
00216         return apol_vector_get_index(filter->src_users, msg->data.avc->suser, apol_str_strcmp, NULL, &i) == 0;
00217 }
00218 
00219 static int filter_src_user_read(seaudit_filter_t * filter, const xmlChar * ch)
00220 {
00221         return filter_string_vector_read(&filter->src_users, ch);
00222 }
00223 
00224 static void filter_src_user_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00225 {
00226         filter_string_vector_print(name, filter->src_users, f, tabs);
00227 }
00228 
00229 static bool filter_src_role_is_set(const seaudit_filter_t * filter)
00230 {
00231         return filter->src_roles != NULL;
00232 }
00233 
00234 static int filter_src_role_support(const seaudit_message_t * msg)
00235 {
00236         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && msg->data.avc->srole != NULL;
00237 }
00238 
00239 static int filter_src_role_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00240 {
00241         size_t i;
00242         return apol_vector_get_index(filter->src_roles, msg->data.avc->srole, apol_str_strcmp, NULL, &i) == 0;
00243 }
00244 
00245 static int filter_src_role_read(seaudit_filter_t * filter, const xmlChar * ch)
00246 {
00247         return filter_string_vector_read(&filter->src_roles, ch);
00248 }
00249 
00250 static void filter_src_role_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00251 {
00252         filter_string_vector_print(name, filter->src_roles, f, tabs);
00253 }
00254 
00255 static bool filter_src_type_is_set(const seaudit_filter_t * filter)
00256 {
00257         return filter->src_types != NULL;
00258 }
00259 
00260 static int filter_src_type_support(const seaudit_message_t * msg)
00261 {
00262         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && msg->data.avc->stype != NULL;
00263 }
00264 
00265 static int filter_src_type_read(seaudit_filter_t * filter, const xmlChar * ch)
00266 {
00267         return filter_string_vector_read(&filter->src_types, ch);
00268 }
00269 
00270 static int filter_src_type_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00271 {
00272         size_t i;
00273         return apol_vector_get_index(filter->src_types, msg->data.avc->stype, apol_str_strcmp, NULL, &i) == 0;
00274 }
00275 
00276 static void filter_src_type_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00277 {
00278         filter_string_vector_print(name, filter->src_types, f, tabs);
00279 }
00280 
00281 static bool filter_tgt_user_is_set(const seaudit_filter_t * filter)
00282 {
00283         return filter->tgt_users != NULL;
00284 }
00285 
00286 static int filter_tgt_user_support(const seaudit_message_t * msg)
00287 {
00288         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && msg->data.avc->tuser != NULL;
00289 }
00290 
00291 static int filter_tgt_user_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00292 {
00293         size_t i;
00294         return apol_vector_get_index(filter->tgt_users, msg->data.avc->tuser, apol_str_strcmp, NULL, &i) == 0;
00295 }
00296 
00297 static int filter_tgt_user_read(seaudit_filter_t * filter, const xmlChar * ch)
00298 {
00299         return filter_string_vector_read(&filter->tgt_users, ch);
00300 }
00301 
00302 static void filter_tgt_user_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00303 {
00304         filter_string_vector_print(name, filter->tgt_users, f, tabs);
00305 }
00306 
00307 static bool filter_tgt_role_is_set(const seaudit_filter_t * filter)
00308 {
00309         return filter->tgt_roles != NULL;
00310 }
00311 
00312 static int filter_tgt_role_support(const seaudit_message_t * msg)
00313 {
00314         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && msg->data.avc->trole != NULL;
00315 }
00316 
00317 static int filter_tgt_role_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00318 {
00319         size_t i;
00320         return apol_vector_get_index(filter->tgt_roles, msg->data.avc->trole, apol_str_strcmp, NULL, &i) == 0;
00321 }
00322 
00323 static int filter_tgt_role_read(seaudit_filter_t * filter, const xmlChar * ch)
00324 {
00325         return filter_string_vector_read(&filter->tgt_roles, ch);
00326 }
00327 
00328 static void filter_tgt_role_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00329 {
00330         filter_string_vector_print(name, filter->tgt_roles, f, tabs);
00331 }
00332 
00333 static bool filter_tgt_type_is_set(const seaudit_filter_t * filter)
00334 {
00335         return filter->tgt_types != NULL;
00336 }
00337 
00338 static int filter_tgt_type_support(const seaudit_message_t * msg)
00339 {
00340         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && msg->data.avc->ttype != NULL;
00341 }
00342 
00343 static int filter_tgt_type_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00344 {
00345         size_t i;
00346         return apol_vector_get_index(filter->tgt_types, msg->data.avc->ttype, apol_str_strcmp, NULL, &i) == 0;
00347 }
00348 
00349 static int filter_tgt_type_read(seaudit_filter_t * filter, const xmlChar * ch)
00350 {
00351         return filter_string_vector_read(&filter->tgt_types, ch);
00352 }
00353 
00354 static void filter_tgt_type_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00355 {
00356         filter_string_vector_print(name, filter->tgt_types, f, tabs);
00357 }
00358 
00359 static bool filter_tgt_class_is_set(const seaudit_filter_t * filter)
00360 {
00361         return filter->tgt_classes != NULL;
00362 }
00363 
00364 static int filter_tgt_class_support(const seaudit_message_t * msg)
00365 {
00366         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && msg->data.avc->tclass != NULL;
00367 }
00368 
00369 static int filter_tgt_class_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00370 {
00371         size_t i;
00372         return apol_vector_get_index(filter->tgt_classes, msg->data.avc->tclass, apol_str_strcmp, NULL, &i) == 0;
00373 }
00374 
00375 static int filter_tgt_class_read(seaudit_filter_t * filter, const xmlChar * ch)
00376 {
00377         return filter_string_vector_read(&filter->tgt_classes, ch);
00378 }
00379 
00380 static void filter_tgt_class_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00381 {
00382         filter_string_vector_print(name, filter->tgt_classes, f, tabs);
00383 }
00384 
00385 static bool filter_perm_is_set(const seaudit_filter_t * filter)
00386 {
00387         return filter->perm != NULL;
00388 }
00389 
00390 static int filter_perm_support(const seaudit_message_t * msg)
00391 {
00392         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && msg->data.avc->perms != NULL &&
00393                 apol_vector_get_size(msg->data.avc->perms) >= 1;
00394 }
00395 
00396 static int filter_perm_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00397 {
00398         size_t i;
00399         for (i = 0; i < apol_vector_get_size(msg->data.avc->perms); i++) {
00400                 const char *p = apol_vector_get_element(msg->data.avc->perms, i);
00401                 if (fnmatch(filter->perm, p, 0) == 0) {
00402                         return 1;
00403                 }
00404         }
00405         return 0;
00406 }
00407 
00408 static int filter_perm_read(seaudit_filter_t * filter, const xmlChar * ch)
00409 {
00410         return filter_string_read(&filter->perm, ch);
00411 }
00412 
00413 static void filter_perm_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00414 {
00415         filter_string_print(name, filter->perm, f, tabs);
00416 }
00417 
00418 static bool filter_exe_is_set(const seaudit_filter_t * filter)
00419 {
00420         return filter->exe != NULL;
00421 }
00422 
00423 static int filter_exe_support(const seaudit_message_t * msg)
00424 {
00425         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && msg->data.avc->exe != NULL;
00426 }
00427 
00428 static int filter_exe_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00429 {
00430         return fnmatch(filter->exe, msg->data.avc->exe, 0) == 0;
00431 }
00432 
00433 static int filter_exe_read(seaudit_filter_t * filter, const xmlChar * ch)
00434 {
00435         return filter_string_read(&filter->exe, ch);
00436 }
00437 
00438 static void filter_exe_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00439 {
00440         filter_string_print(name, filter->exe, f, tabs);
00441 }
00442 
00443 static bool filter_host_is_set(const seaudit_filter_t * filter)
00444 {
00445         return filter->host != NULL;
00446 }
00447 
00448 static int filter_host_support(const seaudit_message_t * msg)
00449 {
00450         return msg->host != NULL;
00451 }
00452 
00453 static int filter_host_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00454 {
00455         return fnmatch(filter->host, msg->host, 0) == 0;
00456 }
00457 
00458 static int filter_host_read(seaudit_filter_t * filter, const xmlChar * ch)
00459 {
00460         return filter_string_read(&filter->host, ch);
00461 }
00462 
00463 static void filter_host_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00464 {
00465         filter_string_print(name, filter->host, f, tabs);
00466 }
00467 
00468 static bool filter_path_is_set(const seaudit_filter_t * filter)
00469 {
00470         return filter->path != NULL;
00471 }
00472 
00473 static int filter_path_support(const seaudit_message_t * msg)
00474 {
00475         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && msg->data.avc->path != NULL;
00476 }
00477 
00478 static int filter_path_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00479 {
00480         return fnmatch(filter->path, msg->data.avc->path, 0) == 0;
00481 }
00482 
00483 static int filter_path_read(seaudit_filter_t * filter, const xmlChar * ch)
00484 {
00485         return filter_string_read(&filter->path, ch);
00486 }
00487 
00488 static void filter_path_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00489 {
00490         filter_string_print(name, filter->path, f, tabs);
00491 }
00492 
00493 static bool filter_inode_is_set(const seaudit_filter_t * filter)
00494 {
00495         return filter->inode != 0;
00496 }
00497 
00498 static int filter_inode_support(const seaudit_message_t * msg)
00499 {
00500         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && msg->data.avc->is_inode;
00501 }
00502 
00503 static int filter_inode_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00504 {
00505         return filter->inode == msg->data.avc->inode;
00506 }
00507 
00508 static int filter_inode_read(seaudit_filter_t * filter, const xmlChar * ch)
00509 {
00510         return filter_ulong_read(&filter->inode, ch);
00511 }
00512 
00513 static void filter_inode_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00514 {
00515         filter_ulong_print(name, filter->inode, f, tabs);
00516 }
00517 
00518 static bool filter_pid_is_set(const seaudit_filter_t * filter)
00519 {
00520         return filter->pid != 0;
00521 }
00522 
00523 static int filter_pid_support(const seaudit_message_t * msg)
00524 {
00525         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && msg->data.avc->is_pid;
00526 }
00527 
00528 static int filter_pid_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00529 {
00530         return filter->pid == msg->data.avc->pid;
00531 }
00532 
00533 static int filter_pid_read(seaudit_filter_t * filter, const xmlChar * ch)
00534 {
00535         return filter_uint_read(&filter->pid, ch);
00536 }
00537 
00538 static void filter_pid_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00539 {
00540         filter_uint_print(name, filter->pid, f, tabs);
00541 }
00542 
00543 static bool filter_comm_is_set(const seaudit_filter_t * filter)
00544 {
00545         return filter->comm != NULL;
00546 }
00547 
00548 static int filter_comm_support(const seaudit_message_t * msg)
00549 {
00550         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && msg->data.avc->comm != NULL;
00551 }
00552 
00553 static int filter_comm_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00554 {
00555         return fnmatch(filter->comm, msg->data.avc->comm, 0) == 0;
00556 }
00557 
00558 static int filter_comm_read(seaudit_filter_t * filter, const xmlChar * ch)
00559 {
00560         return filter_string_read(&filter->comm, ch);
00561 }
00562 
00563 static void filter_comm_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00564 {
00565         filter_string_print(name, filter->comm, f, tabs);
00566 }
00567 
00568 static bool filter_anyaddr_is_set(const seaudit_filter_t * filter)
00569 {
00570         return filter->anyaddr != NULL;
00571 }
00572 
00573 static int filter_anyaddr_support(const seaudit_message_t * msg)
00574 {
00575         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && (msg->data.avc->saddr != NULL
00576                                                          || msg->data.avc->daddr != NULL
00577                                                          || msg->data.avc->faddr != NULL
00578                                                          || msg->data.avc->laddr != NULL || msg->data.avc->ipaddr != NULL);
00579 }
00580 
00581 static int filter_anyaddr_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00582 {
00583         if (msg->data.avc->saddr && fnmatch(filter->anyaddr, msg->data.avc->saddr, 0) == 0)
00584                 return 1;
00585         if (msg->data.avc->daddr && fnmatch(filter->anyaddr, msg->data.avc->daddr, 0) == 0)
00586                 return 1;
00587         if (msg->data.avc->faddr && fnmatch(filter->anyaddr, msg->data.avc->faddr, 0) == 0)
00588                 return 1;
00589         if (msg->data.avc->laddr && fnmatch(filter->anyaddr, msg->data.avc->laddr, 0) == 0)
00590                 return 1;
00591         if (msg->data.avc->ipaddr && fnmatch(filter->anyaddr, msg->data.avc->ipaddr, 0) == 0)
00592                 return 1;
00593         return 0;
00594 }
00595 
00596 static int filter_anyaddr_read(seaudit_filter_t * filter, const xmlChar * ch)
00597 {
00598         return filter_string_read(&filter->anyaddr, ch);
00599 }
00600 
00601 static void filter_anyaddr_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00602 {
00603         filter_string_print(name, filter->anyaddr, f, tabs);
00604 }
00605 
00606 static bool filter_anyport_is_set(const seaudit_filter_t * filter)
00607 {
00608         return filter->anyport != 0;
00609 }
00610 
00611 static int filter_anyport_support(const seaudit_message_t * msg)
00612 {
00613         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && (msg->data.avc->port != 0 ||
00614                                                          msg->data.avc->source != 0 ||
00615                                                          msg->data.avc->dest != 0 ||
00616                                                          msg->data.avc->fport != 0 || msg->data.avc->lport != 0);
00617 }
00618 
00619 static int filter_anyport_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00620 {
00621         if (msg->data.avc->port != 0 && filter->anyport == msg->data.avc->port) {
00622                 return 1;
00623         }
00624         if (msg->data.avc->source != 0 && filter->anyport == msg->data.avc->source) {
00625                 return 1;
00626         }
00627         if (msg->data.avc->dest != 0 && filter->anyport == msg->data.avc->dest) {
00628                 return 1;
00629         }
00630         if (msg->data.avc->fport != 0 && filter->anyport == msg->data.avc->fport) {
00631                 return 1;
00632         }
00633         if (msg->data.avc->lport != 0 && filter->anyport == msg->data.avc->lport) {
00634                 return 1;
00635         }
00636         return 0;
00637 }
00638 
00639 static int filter_anyport_read(seaudit_filter_t * filter, const xmlChar * ch)
00640 {
00641         return filter_int_read(&filter->anyport, ch);
00642 }
00643 
00644 static void filter_anyport_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00645 {
00646         filter_int_print(name, filter->anyport, f, tabs);
00647 }
00648 
00649 static bool filter_laddr_is_set(const seaudit_filter_t * filter)
00650 {
00651         return filter->laddr != NULL;
00652 }
00653 
00654 static int filter_laddr_support(const seaudit_message_t * msg)
00655 {
00656         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && msg->data.avc->laddr != NULL;
00657 }
00658 
00659 static int filter_laddr_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00660 {
00661         return fnmatch(filter->laddr, msg->data.avc->laddr, 0) == 0;
00662 }
00663 
00664 static int filter_laddr_read(seaudit_filter_t * filter, const xmlChar * ch)
00665 {
00666         return filter_string_read(&filter->laddr, ch);
00667 }
00668 
00669 static void filter_laddr_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00670 {
00671         filter_string_print(name, filter->laddr, f, tabs);
00672 }
00673 
00674 static bool filter_lport_is_set(const seaudit_filter_t * filter)
00675 {
00676         return filter->lport != 0;
00677 }
00678 
00679 static int filter_lport_support(const seaudit_message_t * msg)
00680 {
00681         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && msg->data.avc->lport != 0;
00682 }
00683 
00684 static int filter_lport_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00685 {
00686         return filter->lport == msg->data.avc->lport;
00687 }
00688 
00689 static int filter_lport_read(seaudit_filter_t * filter, const xmlChar * ch)
00690 {
00691         return filter_int_read(&filter->lport, ch);
00692 }
00693 
00694 static void filter_lport_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00695 {
00696         filter_int_print(name, filter->lport, f, tabs);
00697 }
00698 
00699 static bool filter_faddr_is_set(const seaudit_filter_t * filter)
00700 {
00701         return filter->faddr != NULL;
00702 }
00703 
00704 static int filter_faddr_support(const seaudit_message_t * msg)
00705 {
00706         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && msg->data.avc->faddr != NULL;
00707 }
00708 
00709 static int filter_faddr_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00710 {
00711         return fnmatch(filter->faddr, msg->data.avc->faddr, 0) == 0;
00712 }
00713 
00714 static int filter_faddr_read(seaudit_filter_t * filter, const xmlChar * ch)
00715 {
00716         return filter_string_read(&filter->faddr, ch);
00717 }
00718 
00719 static void filter_faddr_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00720 {
00721         filter_string_print(name, filter->faddr, f, tabs);
00722 }
00723 
00724 static bool filter_fport_is_set(const seaudit_filter_t * filter)
00725 {
00726         return filter->fport != 0;
00727 }
00728 
00729 static int filter_fport_support(const seaudit_message_t * msg)
00730 {
00731         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && msg->data.avc->fport != 0;
00732 }
00733 
00734 static int filter_fport_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00735 {
00736         return filter->fport == msg->data.avc->fport;
00737 }
00738 
00739 static int filter_fport_read(seaudit_filter_t * filter, const xmlChar * ch)
00740 {
00741         return filter_int_read(&filter->fport, ch);
00742 }
00743 
00744 static void filter_fport_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00745 {
00746         filter_int_print(name, filter->fport, f, tabs);
00747 }
00748 
00749 static bool filter_saddr_is_set(const seaudit_filter_t * filter)
00750 {
00751         return filter->saddr != NULL;
00752 }
00753 
00754 static int filter_saddr_support(const seaudit_message_t * msg)
00755 {
00756         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && msg->data.avc->saddr != NULL;
00757 }
00758 
00759 static int filter_saddr_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00760 {
00761         return fnmatch(filter->saddr, msg->data.avc->saddr, 0) == 0;
00762 }
00763 
00764 static int filter_saddr_read(seaudit_filter_t * filter, const xmlChar * ch)
00765 {
00766         return filter_string_read(&filter->saddr, ch);
00767 }
00768 
00769 static void filter_saddr_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00770 {
00771         filter_string_print(name, filter->saddr, f, tabs);
00772 }
00773 
00774 static bool filter_sport_is_set(const seaudit_filter_t * filter)
00775 {
00776         return filter->sport != 0;
00777 }
00778 
00779 static int filter_sport_support(const seaudit_message_t * msg)
00780 {
00781         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && msg->data.avc->source != 0;
00782 }
00783 
00784 static int filter_sport_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00785 {
00786         return filter->sport == msg->data.avc->source;
00787 }
00788 
00789 static int filter_sport_read(seaudit_filter_t * filter, const xmlChar * ch)
00790 {
00791         return filter_int_read(&filter->sport, ch);
00792 }
00793 
00794 static void filter_sport_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00795 {
00796         filter_int_print(name, filter->sport, f, tabs);
00797 }
00798 
00799 static bool filter_daddr_is_set(const seaudit_filter_t * filter)
00800 {
00801         return filter->daddr != NULL;
00802 }
00803 
00804 static int filter_daddr_support(const seaudit_message_t * msg)
00805 {
00806         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && msg->data.avc->daddr != NULL;
00807 }
00808 
00809 static int filter_daddr_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00810 {
00811         return fnmatch(filter->daddr, msg->data.avc->daddr, 0) == 0;
00812 }
00813 
00814 static int filter_daddr_read(seaudit_filter_t * filter, const xmlChar * ch)
00815 {
00816         return filter_string_read(&filter->daddr, ch);
00817 }
00818 
00819 static void filter_daddr_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00820 {
00821         filter_string_print(name, filter->daddr, f, tabs);
00822 }
00823 
00824 static bool filter_dport_is_set(const seaudit_filter_t * filter)
00825 {
00826         return filter->dport != 0;
00827 }
00828 
00829 static int filter_dport_support(const seaudit_message_t * msg)
00830 {
00831         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && msg->data.avc->dest != 0;
00832 }
00833 
00834 static int filter_dport_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00835 {
00836         return filter->dport == msg->data.avc->dest;
00837 }
00838 
00839 static int filter_dport_read(seaudit_filter_t * filter, const xmlChar * ch)
00840 {
00841         return filter_int_read(&filter->dport, ch);
00842 }
00843 
00844 static void filter_dport_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00845 {
00846         filter_int_print(name, filter->dport, f, tabs);
00847 }
00848 
00849 static bool filter_port_is_set(const seaudit_filter_t * filter)
00850 {
00851         return filter->port != 0;
00852 }
00853 
00854 static int filter_port_support(const seaudit_message_t * msg)
00855 {
00856         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && msg->data.avc->port != 0;
00857 }
00858 
00859 static int filter_port_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00860 {
00861         return filter->port == msg->data.avc->port;
00862 }
00863 
00864 static int filter_port_read(seaudit_filter_t * filter, const xmlChar * ch)
00865 {
00866         return filter_int_read(&filter->port, ch);
00867 }
00868 
00869 static void filter_port_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00870 {
00871         filter_int_print(name, filter->port, f, tabs);
00872 }
00873 
00874 static bool filter_netif_is_set(const seaudit_filter_t * filter)
00875 {
00876         return filter->netif != NULL;
00877 }
00878 
00879 static int filter_netif_support(const seaudit_message_t * msg)
00880 {
00881         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && msg->data.avc->netif != NULL;
00882 }
00883 
00884 static int filter_netif_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00885 {
00886         return strcmp(filter->netif, msg->data.avc->netif) == 0;
00887 }
00888 
00889 static int filter_netif_read(seaudit_filter_t * filter, const xmlChar * ch)
00890 {
00891         return filter_string_read(&filter->netif, ch);
00892 }
00893 
00894 static void filter_netif_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00895 {
00896         filter_string_print(name, filter->netif, f, tabs);
00897 }
00898 
00899 static bool filter_key_is_set(const seaudit_filter_t * filter)
00900 {
00901         return filter->key != 0;
00902 }
00903 
00904 static int filter_key_support(const seaudit_message_t * msg)
00905 {
00906         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && msg->data.avc->is_key;
00907 }
00908 
00909 static int filter_key_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00910 {
00911         return filter->key == msg->data.avc->key;
00912 }
00913 
00914 static int filter_key_read(seaudit_filter_t * filter, const xmlChar * ch)
00915 {
00916         return filter_int_read(&filter->key, ch);
00917 }
00918 
00919 static void filter_key_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00920 {
00921         filter_int_print(name, filter->key, f, tabs);
00922 }
00923 
00924 static bool filter_cap_is_set(const seaudit_filter_t * filter)
00925 {
00926         return filter->cap != 0;
00927 }
00928 
00929 static int filter_cap_support(const seaudit_message_t * msg)
00930 {
00931         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && msg->data.avc->is_capability;
00932 }
00933 
00934 static int filter_cap_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00935 {
00936         return filter->key == msg->data.avc->capability;
00937 }
00938 
00939 static int filter_cap_read(seaudit_filter_t * filter, const xmlChar * ch)
00940 {
00941         return filter_int_read(&filter->cap, ch);
00942 }
00943 
00944 static void filter_cap_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00945 {
00946         filter_int_print(name, filter->cap, f, tabs);
00947 }
00948 
00949 static bool filter_avc_msg_type_is_set(const seaudit_filter_t * filter)
00950 {
00951         return filter->avc_msg_type != SEAUDIT_AVC_UNKNOWN;
00952 }
00953 
00954 static int filter_avc_msg_type_support(const seaudit_message_t * msg __attribute__ ((unused)))
00955 {
00956         return 1;
00957 }
00958 
00959 static int filter_avc_msg_type_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
00960 {
00961         return msg->type == SEAUDIT_MESSAGE_TYPE_AVC && filter->avc_msg_type == msg->data.avc->msg;
00962 }
00963 
00964 static int filter_avc_msg_type_read(seaudit_filter_t * filter, const xmlChar * ch)
00965 {
00966         char *s;
00967         if ((s = xmlURIUnescapeString((const char *)ch, 0, NULL)) == NULL) {
00968                 return -1;
00969         }
00970         filter->avc_msg_type = atoi(s);
00971         free(s);
00972         return 0;
00973 }
00974 
00975 static void filter_avc_msg_type_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
00976 {
00977         int i;
00978         if (filter->avc_msg_type == SEAUDIT_AVC_UNKNOWN) {
00979                 return;
00980         }
00981         for (i = 0; i < tabs; i++)
00982                 fprintf(f, "\t");
00983         fprintf(f, "<criteria type=\"%s\">\n", name);
00984         for (i = 0; i < tabs + 1; i++) {
00985                 fprintf(f, "\t");
00986         }
00987         fprintf(f, "<item>%d</item>\n", filter->avc_msg_type);
00988         for (i = 0; i < tabs; i++)
00989                 fprintf(f, "\t");
00990         fprintf(f, "</criteria>\n");
00991 }
00992 
00993 static bool filter_date_is_set(const seaudit_filter_t * filter)
00994 {
00995         return filter->start != NULL;
00996 }
00997 
00998 static int filter_date_support(const seaudit_message_t * msg)
00999 {
01000         return msg->date_stamp != NULL;
01001 }
01002 
01003 /**
01004  * Given two dates compare them.  If both structs have years that are
01005  * not zeroes then also compare their years.
01006  */
01007 static int filter_date_comp(const struct tm *t1, const struct tm *t2)
01008 {
01009         /* tm has year, month, day, hour, min, sec */
01010         /* check if we should compare the years */
01011         int retval;
01012         if (t1->tm_year != 0 && t2->tm_year != 0 && (retval = t1->tm_year - t2->tm_year) != 0) {
01013                 return retval;
01014         }
01015         if ((retval = t1->tm_mon - t2->tm_mon) != 0) {
01016                 return retval;
01017         }
01018         if ((retval = t1->tm_mday - t2->tm_mday) != 0) {
01019                 return retval;
01020         }
01021         if ((retval = t1->tm_hour - t2->tm_hour) != 0) {
01022                 return retval;
01023         }
01024         if ((retval = t1->tm_min - t2->tm_min) != 0) {
01025                 return retval;
01026         }
01027         if ((retval = t1->tm_sec - t2->tm_sec) != 0) {
01028                 return retval;
01029         }
01030         return 0;
01031 }
01032 
01033 static int filter_date_accept(const seaudit_filter_t * filter, const seaudit_message_t * msg)
01034 {
01035         int compval = filter_date_comp(filter->start, msg->date_stamp);
01036         if (filter->date_match == SEAUDIT_FILTER_DATE_MATCH_BEFORE) {
01037                 return compval > 0;
01038         } else if (filter->date_match == SEAUDIT_FILTER_DATE_MATCH_AFTER) {
01039                 return compval < 0;
01040         } else {
01041                 if (compval > 0)
01042                         return 0;
01043                 compval = filter_date_comp(msg->date_stamp, filter->end);
01044                 return compval < 0;
01045         }
01046 }
01047 
01048 static int filter_date_read(seaudit_filter_t * filter, const xmlChar * ch)
01049 {
01050         char *s;
01051         if ((s = xmlURIUnescapeString((const char *)ch, 0, NULL)) == NULL) {
01052                 return -1;
01053         }
01054         if (filter->start == NULL) {
01055                 if ((filter->start = calloc(1, sizeof(*(filter->start)))) == NULL) {
01056                         free(s);
01057                         return -1;
01058                 }
01059                 strptime(s, "%a %b %d %T %Y", filter->start);
01060         } else if (filter->end == NULL) {
01061                 if ((filter->end = calloc(1, sizeof(*(filter->end)))) == NULL) {
01062                         free(s);
01063                         return -1;
01064                 }
01065                 strptime(s, "%a %b %d %T %Y", filter->end);
01066         } else {
01067                 filter->date_match = atoi(s);
01068         }
01069         free(s);
01070         return 0;
01071 }
01072 
01073 static void filter_date_print(const seaudit_filter_t * filter, const char *name, FILE * f, int tabs)
01074 {
01075         int i;
01076         xmlChar *s, *escaped;
01077         if (filter->start == NULL) {
01078                 return;
01079         }
01080         for (i = 0; i < tabs; i++)
01081                 fprintf(f, "\t");
01082         fprintf(f, "<criteria type=\"%s\">\n", name);
01083         s = xmlCharStrdup(asctime(filter->start));
01084         escaped = xmlURIEscapeStr(s, NULL);
01085         for (i = 0; i < tabs + 1; i++) {
01086                 fprintf(f, "\t");
01087         }
01088         fprintf(f, "<item>%s</item>\n", escaped);
01089         free(s);
01090         free(escaped);
01091         s = xmlCharStrdup(asctime(filter->end));
01092         escaped = xmlURIEscapeStr(s, NULL);
01093         for (i = 0; i < tabs + 1; i++)
01094                 fprintf(f, "\t");
01095         fprintf(f, "<item>%s</item>\n", escaped);
01096         free(s);
01097         free(escaped);
01098         for (i = 0; i < tabs + 1; i++)
01099                 fprintf(f, "\t");
01100         fprintf(f, "<item>%d</item>\n", filter->date_match);
01101         for (i = 0; i < tabs; i++)
01102                 fprintf(f, "\t");
01103         fprintf(f, "</criteria>\n");
01104 }
01105 
01106 typedef bool(filter_is_set_func) (const seaudit_filter_t * filter);
01107 typedef int (filter_support_func) (const seaudit_message_t * msg);
01108 typedef int (filter_accept_func) (const seaudit_filter_t * filter, const seaudit_message_t * msg);
01109 typedef void (filter_print_func) (const seaudit_filter_t * filter, const char *name, FILE * f, int tabs);
01110 
01111 struct filter_criteria_t
01112 {
01113         const char *name;
01114         filter_is_set_func *is_set;
01115         filter_support_func *support;
01116         filter_accept_func *accept;
01117         filter_read_func *read;
01118         filter_print_func *print;
01119 };
01120 
01121 /**
01122  * Filter criteria are actually implemented as entries within this
01123  * function pointer table.  During filter_is_accepted() each element
01124  * of this table is retrieved; if the support functions returns
01125  * non-zero then the accept function is called.  To add new filter
01126  * criteria, implement their support and accept functions and then
01127  * append new entries to this table.
01128  */
01129 static const struct filter_criteria_t filter_criteria[] = {
01130         {"src_user", filter_src_user_is_set, filter_src_user_support, filter_src_user_accept, filter_src_user_read,
01131          filter_src_user_print},
01132         {"src_role", filter_src_role_is_set, filter_src_role_support, filter_src_role_accept, filter_src_role_read,
01133          filter_src_role_print},
01134         {"src_type", filter_src_type_is_set, filter_src_type_support, filter_src_type_accept, filter_src_type_read,
01135          filter_src_type_print},
01136         {"tgt_user", filter_tgt_user_is_set, filter_tgt_user_support, filter_tgt_user_accept, filter_tgt_user_read,
01137          filter_tgt_user_print},
01138         {"tgt_role", filter_tgt_role_is_set, filter_tgt_role_support, filter_tgt_role_accept, filter_tgt_role_read,
01139          filter_tgt_role_print},
01140         {"tgt_type", filter_tgt_type_is_set, filter_tgt_type_support, filter_tgt_type_accept, filter_tgt_type_read,
01141          filter_tgt_type_print},
01142         {"obj_class", filter_tgt_class_is_set, filter_tgt_class_support, filter_tgt_class_accept, filter_tgt_class_read,
01143          filter_tgt_class_print},
01144         {"perm", filter_perm_is_set, filter_perm_support, filter_perm_accept, filter_perm_read, filter_perm_print},
01145         {"exe", filter_exe_is_set, filter_exe_support, filter_exe_accept, filter_exe_read, filter_exe_print},
01146         {"host", filter_host_is_set, filter_host_support, filter_host_accept, filter_host_read, filter_host_print},
01147         {"path", filter_path_is_set, filter_path_support, filter_path_accept, filter_path_read, filter_path_print},
01148         {"inode", filter_inode_is_set, filter_inode_support, filter_inode_accept, filter_inode_read, filter_inode_print},
01149         {"pid", filter_pid_is_set, filter_pid_support, filter_pid_accept, filter_pid_read, filter_pid_print},
01150         {"comm", filter_comm_is_set, filter_comm_support, filter_comm_accept, filter_comm_read, filter_comm_print},
01151         {"ipaddr", filter_anyaddr_is_set, filter_anyaddr_support, filter_anyaddr_accept, filter_anyaddr_read, filter_anyaddr_print},
01152         {"anyport", filter_anyport_is_set, filter_anyport_support, filter_anyport_accept, filter_anyport_read,
01153          filter_anyport_print},
01154         {"laddr", filter_laddr_is_set, filter_laddr_support, filter_laddr_accept, filter_laddr_read, filter_laddr_print},
01155         {"lport", filter_lport_is_set, filter_lport_support, filter_lport_accept, filter_lport_read, filter_lport_print},
01156         {"faddr", filter_faddr_is_set, filter_faddr_support, filter_faddr_accept, filter_faddr_read, filter_faddr_print},
01157         {"fport", filter_fport_is_set, filter_fport_support, filter_fport_accept, filter_fport_read, filter_fport_print},
01158         {"saddr", filter_saddr_is_set, filter_saddr_support, filter_saddr_accept, filter_saddr_read, filter_saddr_print},
01159         {"sport", filter_sport_is_set, filter_sport_support, filter_sport_accept, filter_sport_read, filter_sport_print},
01160         {"daddr", filter_daddr_is_set, filter_daddr_support, filter_daddr_accept, filter_daddr_read, filter_daddr_print},
01161         {"dport", filter_dport_is_set, filter_dport_support, filter_dport_accept, filter_dport_read, filter_dport_print},
01162         {"port", filter_port_is_set, filter_port_support, filter_port_accept, filter_port_read, filter_port_print},
01163         {"netif", filter_netif_is_set, filter_netif_support, filter_netif_accept, filter_netif_read, filter_netif_print},
01164         {"key", filter_key_is_set, filter_key_support, filter_key_accept, filter_key_read, filter_key_print},
01165         {"cap", filter_cap_is_set, filter_cap_support, filter_cap_accept, filter_cap_read, filter_cap_print},
01166         {"msg", filter_avc_msg_type_is_set, filter_avc_msg_type_support, filter_avc_msg_type_accept, filter_avc_msg_type_read,
01167          filter_avc_msg_type_print},
01168         {"date_time", filter_date_is_set, filter_date_support, filter_date_accept, filter_date_read, filter_date_print}
01169 };
01170 
01171 /******************** protected functions below ********************/
01172 
01173 int filter_is_accepted(const seaudit_filter_t * filter, const seaudit_message_t * msg)
01174 {
01175         bool tried_criterion = false;
01176         int acceptval;
01177         size_t i;
01178 
01179         for (i = 0; i < sizeof(filter_criteria) / sizeof(filter_criteria[0]); i++) {
01180                 if (filter_criteria[i].is_set(filter)) {
01181                         tried_criterion = true;
01182                         if (filter_criteria[i].support(msg)) {
01183                                 acceptval = filter_criteria[i].accept(filter, msg);
01184                         } else if (filter->strict) {
01185                                 /* if filter is strict, then an
01186                                    unsupported criterion is assumed to
01187                                    not match */
01188                                 acceptval = 0;
01189                         } else {
01190                                 /* for unstrict filters, unsupported
01191                                    criterion is assumed to be a don't
01192                                    care state */
01193                                 continue;
01194                         }
01195                         if (filter->match == SEAUDIT_FILTER_MATCH_ANY && acceptval == 1) {
01196                                 return 1;
01197                         }
01198                         if (filter->match == SEAUDIT_FILTER_MATCH_ALL && acceptval == 0) {
01199                                 return 0;
01200                         }
01201                 }
01202         }
01203         if (!tried_criterion) {
01204                 /* if got here, then the filter had no set criterion */
01205                 if (filter->strict) {
01206                         /* a strict empty filter matches nothing */
01207                         return 0;
01208                 }
01209                 return 1;
01210         }
01211         if (filter->match == SEAUDIT_FILTER_MATCH_ANY) {
01212                 /* if got here, then no criterion was met */
01213                 return 0;
01214         }
01215         /* if got here, then all criteria were met */
01216         return 1;
01217 }
01218 
01219 static bool filter_parse_is_valid_tag(const xmlChar * tag)
01220 {
01221         static const char *parse_valid_tags[] = { "item", "criteria", "view", "filter", "desc", NULL };
01222         size_t i;
01223         for (i = 0; parse_valid_tags[i] != NULL; i++) {
01224                 if (xmlStrcmp(tag, (xmlChar *) parse_valid_tags[i]) == 0) {
01225                         return 1;
01226                 }
01227         }
01228         return 0;
01229 }
01230 
01231 static filter_read_func *filter_get_read_func(const xmlChar * name)
01232 {
01233         size_t i;
01234         for (i = 0; i < sizeof(filter_criteria) / sizeof(filter_criteria[0]); i++) {
01235                 if (xmlStrcmp(name, (xmlChar *) filter_criteria[i].name) == 0) {
01236                         return filter_criteria[i].read;
01237                 }
01238         }
01239         return NULL;
01240 }
01241 
01242 static void filter_parse_start_element(void *user_data, const xmlChar * name, const xmlChar ** attrs)
01243 {
01244         struct filter_parse_state *state = user_data;
01245         size_t i;
01246         if (!filter_parse_is_valid_tag(name)) {
01247                 state->warnings = 1;
01248                 return;
01249         }
01250         if (xmlStrcmp(name, (xmlChar *) "view") == 0) {
01251                 for (i = 0; attrs[i] != NULL && attrs[i + 1] != NULL; i += 2) {
01252                         if (xmlStrcmp(attrs[i], (xmlChar *) "name") == 0) {
01253                                 free(state->view_name);
01254                                 state->view_name = xmlURIUnescapeString((const char *)attrs[i + 1], 0, NULL);
01255                         } else if (xmlStrcmp(attrs[i], (xmlChar *) "match") == 0) {
01256                                 if (xmlStrcmp(attrs[i + 1], (xmlChar *) "all") == 0) {
01257                                         state->view_match = SEAUDIT_FILTER_MATCH_ALL;
01258                                 } else if (xmlStrcmp(attrs[i + 1], (xmlChar *) "any") == 0) {
01259                                         state->view_match = SEAUDIT_FILTER_MATCH_ANY;
01260                                 }
01261                         } else if (xmlStrcmp(attrs[i], (xmlChar *) "show") == 0) {
01262                                 if (xmlStrcmp(attrs[i + 1], (xmlChar *) "true") == 0) {
01263                                         state->view_visible = SEAUDIT_FILTER_VISIBLE_SHOW;
01264                                 } else if (xmlStrcmp(attrs[i + 1], (xmlChar *) "hide") == 0) {
01265                                         state->view_visible = SEAUDIT_FILTER_VISIBLE_HIDE;
01266                                 }
01267                         }
01268                 }
01269         } else if (xmlStrcmp(name, (xmlChar *) "filter") == 0) {
01270                 /* create a new filter and set it to be the one that is currently being parsed */
01271                 char *filter_name = NULL;
01272                 seaudit_filter_match_e match = SEAUDIT_FILTER_MATCH_ALL;
01273                 bool strict = false;
01274                 for (i = 0; attrs[i] != NULL && attrs[i + 1] != NULL; i += 2) {
01275                         if (xmlStrcmp(attrs[i], (xmlChar *) "name") == 0) {
01276                                 free(filter_name);
01277                                 filter_name = xmlURIUnescapeString((const char *)attrs[i + 1], 0, NULL);
01278                         } else if (xmlStrcmp(attrs[i], (xmlChar *) "match") == 0) {
01279                                 if (xmlStrcmp(attrs[i + 1], (xmlChar *) "all") == 0) {
01280                                         match = SEAUDIT_FILTER_MATCH_ALL;
01281                                 } else if (xmlStrcmp(attrs[i + 1], (xmlChar *) "any") == 0) {
01282                                         match = SEAUDIT_FILTER_MATCH_ANY;
01283                                 }
01284                         } else if (xmlStrcmp(attrs[i], (xmlChar *) "strict") == 0) {
01285                                 if (xmlStrcmp(attrs[i + 1], (xmlChar *) "true") == 0) {
01286                                         strict = true;
01287                                 } else if (xmlStrcmp(attrs[i + 1], (xmlChar *) "false") == 0) {
01288                                         strict = false;
01289                                 }
01290                         }
01291                 }
01292                 if ((state->cur_filter = seaudit_filter_create(filter_name)) != NULL) {
01293                         if (apol_vector_append(state->filters, state->cur_filter) < 0) {
01294                                 seaudit_filter_destroy(&state->cur_filter);
01295                         } else {
01296                                 seaudit_filter_set_match(state->cur_filter, match);
01297                                 seaudit_filter_set_strict(state->cur_filter, strict);
01298                         }
01299                 }
01300                 free(filter_name);
01301         } else if (xmlStrcmp(name, (xmlChar *) "criteria") == 0) {
01302                 for (i = 0; attrs[i] != NULL && attrs[i + 1] != NULL; i += 2) {
01303                         if (xmlStrcmp(attrs[i], (xmlChar *) "type") == 0) {
01304                                 state->cur_filter_read = filter_get_read_func(attrs[i + 1]);
01305                         }
01306                 }
01307         }
01308         free(state->cur_string);
01309         state->cur_string = NULL;
01310 }
01311 
01312 static void filter_parse_end_element(void *user_data, const xmlChar * name)
01313 {
01314         struct filter_parse_state *state = user_data;
01315         char *s;
01316         if (!filter_parse_is_valid_tag(name)) {
01317                 state->warnings = 1;
01318                 return;
01319         }
01320         if (xmlStrcmp(name, (xmlChar *) "desc") == 0) {
01321                 if (state->cur_filter == NULL) {
01322                         state->warnings = 1;
01323                 } else {
01324                         s = xmlURIUnescapeString((const char *)state->cur_string, 0, NULL);
01325                         seaudit_filter_set_description(state->cur_filter, s);
01326                         free(s);
01327                 }
01328         } else if (xmlStrcmp(name, (xmlChar *) "item") == 0) {
01329                 if (state->cur_filter == NULL || state->cur_filter_read == NULL) {
01330                         state->warnings = 1;
01331                 } else {
01332                         state->cur_filter_read(state->cur_filter, state->cur_string);
01333                 }
01334         } else if (xmlStrcmp(name, (xmlChar *) "filter") == 0) {
01335                 state->cur_filter = NULL;
01336         } else if (xmlStrcmp(name, (xmlChar *) "criteria") == 0) {
01337                 state->cur_filter_read = NULL;
01338         }
01339         free(state->cur_string);
01340         state->cur_string = NULL;
01341 }
01342 
01343 static void filter_parse_characters(void *user_data, const xmlChar * ch, int len)
01344 {
01345         struct filter_parse_state *state = user_data;
01346         free(state->cur_string);
01347         state->cur_string = xmlStrndup(ch, len);
01348 }
01349 
01350 int filter_parse_xml(struct filter_parse_state *state, const char *filename)
01351 {
01352         xmlSAXHandler handler;
01353         int err;
01354 
01355         memset(&handler, 0, sizeof(xmlSAXHandler));
01356         handler.startElement = filter_parse_start_element;
01357         handler.endElement = filter_parse_end_element;
01358         handler.characters = filter_parse_characters;
01359         err = xmlSAXUserParseFile(&handler, state, filename);
01360         free(state->cur_string);
01361         state->cur_string = NULL;
01362         if (err) {
01363                 errno = EIO;
01364                 return -1;
01365         }
01366         if (state->warnings) {
01367                 return 1;
01368         }
01369         return 0;
01370 }
01371 
01372 void filter_append_to_file(const seaudit_filter_t * filter, FILE * file, int tabs)
01373 {
01374         xmlChar *escaped;
01375         xmlChar *str_xml;
01376         int i;
01377         size_t j;
01378 
01379         if (filter == NULL || file == NULL) {
01380                 errno = EINVAL;
01381                 return;
01382         }
01383 
01384         if (filter->name == NULL) {
01385                 str_xml = xmlCharStrdup("Unnamed");
01386         } else {
01387                 str_xml = xmlCharStrdup(filter->name);
01388         }
01389         escaped = xmlURIEscapeStr(str_xml, NULL);
01390         for (i = 0; i < tabs; i++)
01391                 fprintf(file, "\t");
01392         fprintf(file, "<filter name=\"%s\" match=\"%s\" strict=\"%s\">\n", escaped,
01393                 filter->match == SEAUDIT_FILTER_MATCH_ALL ? "all" : "any", filter->strict ? "true" : "false");
01394         free(escaped);
01395         free(str_xml);
01396 
01397         if (filter->desc != NULL) {
01398                 str_xml = xmlCharStrdup(filter->desc);
01399                 escaped = xmlURIEscapeStr(str_xml, NULL);
01400                 for (i = 0; i < tabs + 1; i++)
01401                         fprintf(file, "\t");
01402                 fprintf(file, "<desc>%s</desc>\n", escaped);
01403                 free(escaped);
01404                 free(str_xml);
01405         }
01406         for (j = 0; j < sizeof(filter_criteria) / sizeof(filter_criteria[0]); j++) {
01407                 filter_criteria[j].print(filter, filter_criteria[j].name, file, tabs + 1);
01408         }
01409         for (i = 0; i < tabs; i++)
01410                 fprintf(file, "\t");
01411         fprintf(file, "</filter>\n");
01412 }