summaryrefslogtreecommitdiffstats
path: root/seaudit/filter_view.c
diff options
context:
space:
mode:
Diffstat (limited to 'seaudit/filter_view.c')
-rw-r--r--seaudit/filter_view.c1127
1 files changed, 1127 insertions, 0 deletions
diff --git a/seaudit/filter_view.c b/seaudit/filter_view.c
new file mode 100644
index 0000000..e0d8745
--- /dev/null
+++ b/seaudit/filter_view.c
@@ -0,0 +1,1127 @@
+/**
+ * @file
+ * Run the dialog to modify a particular filter.
+ *
+ * @author Jeremy A. Mowery jmowery@tresys.com
+ * @author Jason Tang jtang@tresys.com
+ * @author Jeremy Solt jsolt@tresys.com
+ *
+ * Copyright (C) 2004-2007 Tresys Technology, LLC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <config.h>
+
+#include "filter_view.h"
+#include "policy_components_view.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <apol/policy-query.h>
+#include <apol/mls-query.h>
+#include <apol/util.h>
+#include <glade/glade.h>
+
+struct context_item
+{
+ GtkButton *button;
+ GtkEntry *entry;
+ apol_vector_t *items;
+};
+
+struct date_item
+{
+ GtkComboBox *month;
+ GtkSpinButton *day, *hour, *minute, *second;
+ GtkFrame *frame;
+};
+
+struct filter_view
+{
+ toplevel_t *top;
+ seaudit_filter_t *filter;
+ GladeXML *xml;
+
+ GtkDialog *dialog;
+
+ GtkEntry *name_entry;
+ GtkComboBox *match_combo;
+
+ struct context_item suser, srole, stype, smls_lvl, smls_clr, tuser, trole, ttype, tmls_lvl, tmls_clr, obj_class;
+ GtkButton *context_clear_button;
+
+ GtkEntry *ipaddr_entry, *port_entry, *netif_entry, *exe_entry, *path_entry, *host_entry, *comm_entry;
+ GtkComboBox *message_combo;
+ GtkButton *other_clear_button;
+
+ GtkRadioButton *date_none_radio, *date_before_radio, *date_after_radio, *date_between_radio;
+ struct date_item dates[2];
+ GtkTextBuffer *description_buffer;
+};
+
+/**
+ * Initialize pointers to widgets on the context tab.
+ */
+static void filter_view_init_widgets_context(struct filter_view *fv)
+{
+ fv->suser.button = GTK_BUTTON(glade_xml_get_widget(fv->xml, "FilterViewSUserButton"));
+ fv->srole.button = GTK_BUTTON(glade_xml_get_widget(fv->xml, "FilterViewSRoleButton"));
+ fv->stype.button = GTK_BUTTON(glade_xml_get_widget(fv->xml, "FilterViewSTypeButton"));
+ fv->smls_lvl.button = GTK_BUTTON(glade_xml_get_widget(fv->xml, "FilterViewSMLSLVLButton"));
+ fv->smls_clr.button = GTK_BUTTON(glade_xml_get_widget(fv->xml, "FilterViewSMLSCLRButton"));
+ fv->tuser.button = GTK_BUTTON(glade_xml_get_widget(fv->xml, "FilterViewTUserButton"));
+ fv->trole.button = GTK_BUTTON(glade_xml_get_widget(fv->xml, "FilterViewTRoleButton"));
+ fv->ttype.button = GTK_BUTTON(glade_xml_get_widget(fv->xml, "FilterViewTTypeButton"));
+ fv->tmls_lvl.button = GTK_BUTTON(glade_xml_get_widget(fv->xml, "FilterViewTMLSLVLButton"));
+ fv->tmls_clr.button = GTK_BUTTON(glade_xml_get_widget(fv->xml, "FilterViewTMLSCLRButton"));
+ fv->obj_class.button = GTK_BUTTON(glade_xml_get_widget(fv->xml, "FilterViewClassButton"));
+ assert(fv->suser.button != NULL && fv->srole.button != NULL && fv->stype.button != NULL && fv->smls_lvl.button != NULL && fv->smls_clr.button != NULL &&
+ fv->tuser.button != NULL && fv->trole.button != NULL && fv->ttype.button != NULL && fv->tmls_lvl.button != NULL && fv->tmls_clr.button != NULL && fv->obj_class.button != NULL);
+
+ fv->suser.entry = GTK_ENTRY(glade_xml_get_widget(fv->xml, "FilterViewSUserEntry"));
+ fv->srole.entry = GTK_ENTRY(glade_xml_get_widget(fv->xml, "FilterViewSRoleEntry"));
+ fv->stype.entry = GTK_ENTRY(glade_xml_get_widget(fv->xml, "FilterViewSTypeEntry"));
+ fv->smls_lvl.entry = GTK_ENTRY(glade_xml_get_widget(fv->xml, "FilterViewSMLSLVLEntry"));
+ fv->smls_clr.entry = GTK_ENTRY(glade_xml_get_widget(fv->xml, "FilterViewSMLSCLREntry"));
+ fv->tuser.entry = GTK_ENTRY(glade_xml_get_widget(fv->xml, "FilterViewTUserEntry"));
+ fv->trole.entry = GTK_ENTRY(glade_xml_get_widget(fv->xml, "FilterViewTRoleEntry"));
+ fv->ttype.entry = GTK_ENTRY(glade_xml_get_widget(fv->xml, "FilterViewTTypeEntry"));
+ fv->tmls_lvl.entry = GTK_ENTRY(glade_xml_get_widget(fv->xml, "FilterViewTMLSLVLEntry"));
+ fv->tmls_clr.entry = GTK_ENTRY(glade_xml_get_widget(fv->xml, "FilterViewTMLSCLREntry"));
+ fv->obj_class.entry = GTK_ENTRY(glade_xml_get_widget(fv->xml, "FilterViewClassEntry"));
+ assert(fv->suser.entry != NULL && fv->srole.entry != NULL && fv->stype.entry != NULL && fv->smls_lvl.entry != NULL && fv->smls_clr.entry != NULL &&
+ fv->tuser.entry != NULL && fv->trole.entry != NULL && fv->ttype.entry != NULL && fv->tmls_lvl.entry != NULL && fv->tmls_clr.entry != NULL && fv->obj_class.entry != NULL);
+ g_object_set_data(G_OBJECT(fv->suser.entry), "data", &fv->suser);
+ g_object_set_data(G_OBJECT(fv->srole.entry), "data", &fv->srole);
+ g_object_set_data(G_OBJECT(fv->stype.entry), "data", &fv->stype);
+ g_object_set_data(G_OBJECT(fv->smls_lvl.entry), "data", &fv->smls_lvl);
+ g_object_set_data(G_OBJECT(fv->smls_clr.entry), "data", &fv->smls_clr);
+ g_object_set_data(G_OBJECT(fv->tuser.entry), "data", &fv->tuser);
+ g_object_set_data(G_OBJECT(fv->trole.entry), "data", &fv->trole);
+ g_object_set_data(G_OBJECT(fv->ttype.entry), "data", &fv->ttype);
+ g_object_set_data(G_OBJECT(fv->tmls_lvl.entry), "data", &fv->tmls_lvl);
+ g_object_set_data(G_OBJECT(fv->tmls_clr.entry), "data", &fv->tmls_clr);
+ g_object_set_data(G_OBJECT(fv->obj_class.entry), "data", &fv->obj_class);
+
+ fv->context_clear_button = GTK_BUTTON(glade_xml_get_widget(fv->xml, "FilterViewContextClearButton"));
+ assert(fv->context_clear_button != NULL);
+}
+
+/**
+ * Initialize pointers to widgets on the other tab.
+ */
+static void filter_view_init_widgets_other(struct filter_view *fv)
+{
+ fv->ipaddr_entry = GTK_ENTRY(glade_xml_get_widget(fv->xml, "FilterViewIPAddrEntry"));
+ fv->port_entry = GTK_ENTRY(glade_xml_get_widget(fv->xml, "FilterViewPortEntry"));
+ fv->netif_entry = GTK_ENTRY(glade_xml_get_widget(fv->xml, "FilterViewNetIfEntry"));
+ assert(fv->ipaddr_entry != NULL && fv->port_entry != NULL && fv->netif_entry != NULL);
+
+ fv->exe_entry = GTK_ENTRY(glade_xml_get_widget(fv->xml, "FilterViewExeEntry"));
+ fv->path_entry = GTK_ENTRY(glade_xml_get_widget(fv->xml, "FilterViewPathEntry"));
+ fv->host_entry = GTK_ENTRY(glade_xml_get_widget(fv->xml, "FilterViewHostEntry"));
+ fv->comm_entry = GTK_ENTRY(glade_xml_get_widget(fv->xml, "FilterViewCommEntry"));
+ assert(fv->exe_entry != NULL && fv->path_entry != NULL && fv->host_entry != NULL && fv->comm_entry != NULL);
+
+ fv->message_combo = GTK_COMBO_BOX(glade_xml_get_widget(fv->xml, "FilterViewMessageCombo"));
+ assert(fv->message_combo != NULL);
+
+ fv->other_clear_button = GTK_BUTTON(glade_xml_get_widget(fv->xml, "FilterViewOtherClearButton"));
+ assert(fv->other_clear_button != NULL);
+}
+
+/**
+ * Initialize pointers to widgets on the date tab.
+ */
+static void filter_view_init_widgets_date(struct filter_view *fv)
+{
+ static const char *widgets[2][6] = {
+ {"FilterViewDateStartFrame", "FilterViewDateStartMonthCombo", "FilterViewDateStartDaySpin",
+ "FilterViewDateStartHourSpin", "FilterViewDateStartMinuteSpin", "FilterViewDateStartSecondSpin"},
+ {"FilterViewDateEndFrame", "FilterViewDateEndMonthCombo", "FilterViewDateEndDaySpin",
+ "FilterViewDateEndHourSpin", "FilterViewDateEndMinuteSpin", "FilterViewDateEndSecondSpin"}
+ };
+ size_t i;
+ fv->date_none_radio = GTK_RADIO_BUTTON(glade_xml_get_widget(fv->xml, "FilterViewDateNoneRadio"));
+ fv->date_before_radio = GTK_RADIO_BUTTON(glade_xml_get_widget(fv->xml, "FilterViewDateBeforeRadio"));
+ fv->date_after_radio = GTK_RADIO_BUTTON(glade_xml_get_widget(fv->xml, "FilterViewDateAfterRadio"));
+ fv->date_between_radio = GTK_RADIO_BUTTON(glade_xml_get_widget(fv->xml, "FilterViewDateBetweenRadio"));
+ assert(fv->date_none_radio != NULL && fv->date_before_radio != NULL && fv->date_after_radio != NULL
+ && fv->date_between_radio != NULL);
+
+ for (i = 0; i < 2; i++) {
+ fv->dates[i].frame = GTK_FRAME(glade_xml_get_widget(fv->xml, widgets[i][0]));
+ fv->dates[i].month = GTK_COMBO_BOX(glade_xml_get_widget(fv->xml, widgets[i][1]));
+ fv->dates[i].day = GTK_SPIN_BUTTON(glade_xml_get_widget(fv->xml, widgets[i][2]));
+ fv->dates[i].hour = GTK_SPIN_BUTTON(glade_xml_get_widget(fv->xml, widgets[i][3]));
+ fv->dates[i].minute = GTK_SPIN_BUTTON(glade_xml_get_widget(fv->xml, widgets[i][4]));
+ fv->dates[i].second = GTK_SPIN_BUTTON(glade_xml_get_widget(fv->xml, widgets[i][5]));
+ assert(fv->dates[i].frame != NULL && fv->dates[i].month != NULL && fv->dates[i].day != NULL &&
+ fv->dates[i].hour != NULL && fv->dates[i].minute != NULL && fv->dates[i].second != NULL);
+ }
+}
+
+static void filter_view_init_widgets(struct filter_view *fv, GtkWindow * parent)
+{
+ GtkTextView *description_view;
+
+ fv->dialog = GTK_DIALOG(glade_xml_get_widget(fv->xml, "FilterWindow"));
+ assert(fv->dialog != NULL);
+ gtk_window_set_transient_for(GTK_WINDOW(fv->dialog), parent);
+
+ fv->name_entry = GTK_ENTRY(glade_xml_get_widget(fv->xml, "FilterViewNameEntry"));
+ fv->match_combo = GTK_COMBO_BOX(glade_xml_get_widget(fv->xml, "FilterViewMatchCombo"));
+ assert(fv->name_entry != NULL && fv->match_combo);
+
+ filter_view_init_widgets_context(fv);
+ filter_view_init_widgets_other(fv);
+ filter_view_init_widgets_date(fv);
+
+ fv->description_buffer = gtk_text_buffer_new(NULL);
+#ifdef GTK_2_8
+ g_object_ref_sink(fv->description_buffer);
+#endif
+ description_view = GTK_TEXT_VIEW(glade_xml_get_widget(fv->xml, "FilterViewDescView"));
+ assert(description_view != NULL);
+ gtk_text_view_set_buffer(description_view, fv->description_buffer);
+}
+
+/********** functions that copies filter object values to widget **********/
+
+/**
+ * Get the vector of strings from the accessor function. If the
+ * vector is NULL then clear the entry's contents; otherwies set the
+ * entry to the vector of strings, comma delimited.
+ */
+static void filter_view_context_item_to_entry(struct filter_view *fv, struct context_item *item)
+{
+ if (item->items == NULL) {
+ gtk_entry_set_text(item->entry, "");
+ } else {
+ GString *s = g_string_new("");
+ size_t i;
+ for (i = 0; i < apol_vector_get_size(item->items); i++) {
+ char *t = apol_vector_get_element(item->items, i);
+ if (i > 0) {
+ g_string_append(s, ", ");
+ }
+ g_string_append(s, t);
+ }
+ gtk_entry_set_text(item->entry, s->str);
+ g_string_free(s, TRUE);
+ }
+}
+
+static void filter_view_context_items_to_entries(struct filter_view *fv)
+{
+ filter_view_context_item_to_entry(fv, &fv->suser);
+ filter_view_context_item_to_entry(fv, &fv->srole);
+ filter_view_context_item_to_entry(fv, &fv->stype);
+ filter_view_context_item_to_entry(fv, &fv->smls_lvl);
+ filter_view_context_item_to_entry(fv, &fv->smls_clr);
+ filter_view_context_item_to_entry(fv, &fv->tuser);
+ filter_view_context_item_to_entry(fv, &fv->trole);
+ filter_view_context_item_to_entry(fv, &fv->ttype);
+ filter_view_context_item_to_entry(fv, &fv->tmls_lvl);
+ filter_view_context_item_to_entry(fv, &fv->tmls_clr);
+ filter_view_context_item_to_entry(fv, &fv->obj_class);
+}
+
+static void filter_view_init_context(struct filter_view *fv)
+{
+ const apol_vector_t *v;
+ v = seaudit_filter_get_source_user(fv->filter);
+ if (v != NULL && (fv->suser.items = apol_vector_create_from_vector(v, apol_str_strdup, NULL, free)) == NULL) {
+ toplevel_ERR(fv->top, "Error initializing context tab: %s", strerror(errno));
+ return;
+ }
+ v = seaudit_filter_get_source_role(fv->filter);
+ if (v != NULL && (fv->srole.items = apol_vector_create_from_vector(v, apol_str_strdup, NULL, free)) == NULL) {
+ toplevel_ERR(fv->top, "Error initializing context tab: %s", strerror(errno));
+ return;
+ }
+ v = seaudit_filter_get_source_type(fv->filter);
+ if (v != NULL && (fv->stype.items = apol_vector_create_from_vector(v, apol_str_strdup, NULL, free)) == NULL) {
+ toplevel_ERR(fv->top, "Error initializing context tab: %s", strerror(errno));
+ return;
+ }
+ v = seaudit_filter_get_source_mls_lvl(fv->filter);
+ if (v != NULL && (fv->smls_lvl.items = apol_vector_create_from_vector(v, apol_str_strdup, NULL, free)) == NULL) {
+ toplevel_ERR(fv->top, "Error initializing context tab: %s", strerror(errno));
+ return;
+ }
+ v = seaudit_filter_get_source_mls_clr(fv->filter);
+ if (v != NULL && (fv->smls_clr.items = apol_vector_create_from_vector(v, apol_str_strdup, NULL, free)) == NULL) {
+ toplevel_ERR(fv->top, "Error initializing context tab: %s", strerror(errno));
+ return;
+ }
+
+ v = seaudit_filter_get_target_user(fv->filter);
+ if (v != NULL && (fv->tuser.items = apol_vector_create_from_vector(v, apol_str_strdup, NULL, free)) == NULL) {
+ toplevel_ERR(fv->top, "Error initializing context tab: %s", strerror(errno));
+ return;
+ }
+ v = seaudit_filter_get_target_role(fv->filter);
+ if (v != NULL && (fv->trole.items = apol_vector_create_from_vector(v, apol_str_strdup, NULL, free)) == NULL) {
+ toplevel_ERR(fv->top, "Error initializing context tab: %s", strerror(errno));
+ return;
+ }
+ v = seaudit_filter_get_target_type(fv->filter);
+ if (v != NULL && (fv->ttype.items = apol_vector_create_from_vector(v, apol_str_strdup, NULL, free)) == NULL) {
+ toplevel_ERR(fv->top, "Error initializing context tab: %s", strerror(errno));
+ return;
+ }
+ v = seaudit_filter_get_target_mls_lvl(fv->filter);
+ if (v != NULL && (fv->tmls_lvl.items = apol_vector_create_from_vector(v, apol_str_strdup, NULL, free)) == NULL) {
+ toplevel_ERR(fv->top, "Error initializing context tab: %s", strerror(errno));
+ return;
+ }
+ v = seaudit_filter_get_target_mls_clr(fv->filter);
+ if (v != NULL && (fv->tmls_clr.items = apol_vector_create_from_vector(v, apol_str_strdup, NULL, free)) == NULL) {
+ toplevel_ERR(fv->top, "Error initializing context tab: %s", strerror(errno));
+ return;
+ }
+
+ v = seaudit_filter_get_target_class(fv->filter);
+ if (v != NULL && (fv->obj_class.items = apol_vector_create_from_vector(v, apol_str_strdup, NULL, free)) == NULL) {
+ toplevel_ERR(fv->top, "Error initializing context tab: %s", strerror(errno));
+ return;
+ }
+ filter_view_context_items_to_entries(fv);
+}
+
+/**
+ * Get the string from the accessor function. If the returned string
+ * is NULL then clear the entry's contents; otherwise set the entry to
+ * the returned string.
+ */
+static void filter_view_init_entry(struct filter_view *fv, const char *(*accessor) (const seaudit_filter_t *), GtkEntry * entry)
+{
+ const char *s = accessor(fv->filter);
+ if (s == NULL) {
+ s = "";
+ }
+ gtk_entry_set_text(entry, s);
+}
+
+static void filter_view_init_other(struct filter_view *fv)
+{
+ char s[32];
+ filter_view_init_entry(fv, seaudit_filter_get_anyaddr, fv->ipaddr_entry);
+ if (seaudit_filter_get_anyport(fv->filter) <= 0) {
+ s[0] = '\0';
+ } else {
+ snprintf(s, 32, "%d", seaudit_filter_get_anyport(fv->filter));
+ }
+ gtk_entry_set_text(fv->port_entry, s);
+ filter_view_init_entry(fv, seaudit_filter_get_netif, fv->netif_entry);
+ filter_view_init_entry(fv, seaudit_filter_get_executable, fv->exe_entry);
+ filter_view_init_entry(fv, seaudit_filter_get_path, fv->path_entry);
+ filter_view_init_entry(fv, seaudit_filter_get_host, fv->host_entry);
+ filter_view_init_entry(fv, seaudit_filter_get_command, fv->comm_entry);
+ switch (seaudit_filter_get_message_type(fv->filter)) {
+ case SEAUDIT_AVC_DENIED:
+ gtk_combo_box_set_active(fv->message_combo, 1);
+ break;
+ case SEAUDIT_AVC_GRANTED:
+ gtk_combo_box_set_active(fv->message_combo, 2);
+ break;
+ default:
+ gtk_combo_box_set_active(fv->message_combo, 0);
+ }
+}
+
+static void filter_view_init_date(struct filter_view *fv)
+{
+ const struct tm *start, *end;
+ struct tm values[2];
+ int has_value[2] = { 0, 0 };
+ seaudit_filter_date_match_e match;
+ size_t i;
+
+ seaudit_filter_get_date(fv->filter, &start, &end, &match);
+ if (start == NULL && end == NULL) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fv->date_none_radio), TRUE);
+ } else {
+ if (match == SEAUDIT_FILTER_DATE_MATCH_BEFORE) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fv->date_before_radio), TRUE);
+ } else if (match == SEAUDIT_FILTER_DATE_MATCH_AFTER) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fv->date_after_radio), TRUE);
+ }
+ memcpy(values + 0, start, sizeof(values[0]));
+ has_value[0] = 1;
+ }
+ if (match == SEAUDIT_FILTER_DATE_MATCH_BETWEEN) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fv->date_between_radio), TRUE);
+ memcpy(values + 1, end, sizeof(values[1]));
+ has_value[1] = 1;
+ }
+ for (i = 0; i < 2; i++) {
+ if (has_value[i]) {
+ gtk_combo_box_set_active(fv->dates[i].month, values[i].tm_mon);
+ gtk_spin_button_set_value(fv->dates[i].day, values[i].tm_mday);
+ gtk_spin_button_set_value(fv->dates[i].hour, values[i].tm_hour);
+ gtk_spin_button_set_value(fv->dates[i].minute, values[i].tm_min);
+ gtk_spin_button_set_value(fv->dates[i].second, values[i].tm_sec);
+ } else {
+ gtk_combo_box_set_active(fv->dates[i].month, 0);
+ }
+ }
+}
+
+/**
+ * Copy values from seaudit filter object to GTK+ widgets.
+ */
+static void filter_view_init_dialog(struct filter_view *fv)
+{
+ const char *name = seaudit_filter_get_name(fv->filter);
+ const char *desc = seaudit_filter_get_description(fv->filter);;
+ if (name == NULL) {
+ name = "Untitled";
+ }
+ gtk_entry_set_text(fv->name_entry, name);
+ gtk_combo_box_set_active(fv->match_combo, seaudit_filter_get_match(fv->filter));
+
+ filter_view_init_context(fv);
+ filter_view_init_other(fv);
+ filter_view_init_date(fv);
+
+ if (desc == NULL) {
+ desc = "";
+ }
+ gtk_text_buffer_set_text(fv->description_buffer, desc, -1);
+}
+
+/********** functions that copies widget values to filter object **********/
+
+static void filter_view_apply_context(struct filter_view *fv)
+{
+ if (seaudit_filter_set_source_user(fv->filter, fv->suser.items) < 0 ||
+ seaudit_filter_set_source_role(fv->filter, fv->srole.items) < 0 ||
+ seaudit_filter_set_source_type(fv->filter, fv->stype.items) < 0 ||
+ seaudit_filter_set_source_mls_lvl(fv->filter, fv->smls_lvl.items) < 0 ||
+ seaudit_filter_set_source_mls_clr(fv->filter, fv->smls_clr.items) < 0 ||
+ seaudit_filter_set_target_user(fv->filter, fv->tuser.items) < 0 ||
+ seaudit_filter_set_target_role(fv->filter, fv->trole.items) < 0 ||
+ seaudit_filter_set_target_type(fv->filter, fv->ttype.items) < 0 ||
+ seaudit_filter_set_target_mls_lvl(fv->filter, fv->tmls_lvl.items) < 0 ||
+ seaudit_filter_set_target_mls_clr(fv->filter, fv->tmls_clr.items) < 0 ||
+ seaudit_filter_set_target_class(fv->filter, fv->obj_class.items) < 0) {
+ toplevel_ERR(fv->top, "Error applying context: %s", strerror(errno));
+ }
+}
+
+/**
+ * If the entry is empty, then call the modifier function passing NULL
+ * as the second parameter. Else call the function with the entry's
+ * contents.
+ */
+static void filter_view_apply_entry(struct filter_view *fv, GtkEntry * entry, int (*modifier) (seaudit_filter_t *, const char *))
+{
+ const char *s = gtk_entry_get_text(entry);
+ if (strcmp(s, "") == 0) {
+ s = NULL;
+ }
+ if (modifier(fv->filter, s) < 0) {
+ toplevel_ERR(fv->top, "Error apply settings: %s", strerror(errno));
+ }
+}
+
+/**
+ * Copy values from the other tab to filter object.
+ */
+static void filter_view_apply_other(struct filter_view *fv)
+{
+ const char *s;
+ int port = 0;
+ seaudit_avc_message_type_e message_type;
+
+ filter_view_apply_entry(fv, fv->ipaddr_entry, seaudit_filter_set_anyaddr);
+ s = gtk_entry_get_text(fv->port_entry);
+ if (strcmp(s, "") != 0) {
+ port = atoi(s);
+ }
+ if (seaudit_filter_set_anyport(fv->filter, port) < 0) {
+ toplevel_ERR(fv->top, "Error setting filter: %s", strerror(errno));
+ return;
+ }
+ filter_view_apply_entry(fv, fv->netif_entry, seaudit_filter_set_netif);
+ filter_view_apply_entry(fv, fv->exe_entry, seaudit_filter_set_executable);
+ filter_view_apply_entry(fv, fv->path_entry, seaudit_filter_set_path);
+ filter_view_apply_entry(fv, fv->host_entry, seaudit_filter_set_host);
+ filter_view_apply_entry(fv, fv->comm_entry, seaudit_filter_set_command);
+ switch (gtk_combo_box_get_active(fv->message_combo)) {
+ case 1:
+ message_type = SEAUDIT_AVC_DENIED;
+ break;
+ case 2:
+ message_type = SEAUDIT_AVC_GRANTED;
+ break;
+ default:
+ message_type = SEAUDIT_AVC_UNKNOWN;
+ }
+ if (seaudit_filter_set_message_type(fv->filter, message_type) < 0) {
+ toplevel_ERR(fv->top, "Error setting filter: %s", strerror(errno));
+ return;
+ }
+}
+
+/**
+ * Returns which date radio button is active:
+ *
+ * -1 if date_none_radio,
+ * else something that can be casted to seaudit_filter_date_match
+ */
+static int filter_view_get_date_match(struct filter_view *fv)
+{
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fv->date_before_radio))) {
+ return SEAUDIT_FILTER_DATE_MATCH_BEFORE;
+ }
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fv->date_after_radio))) {
+ return SEAUDIT_FILTER_DATE_MATCH_AFTER;
+ }
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fv->date_between_radio))) {
+ return SEAUDIT_FILTER_DATE_MATCH_BETWEEN;
+ }
+ return -1;
+}
+
+/**
+ * Copy values from date tab to the seaudit filter object.
+ */
+static void filter_view_apply_date(struct filter_view *fv)
+{
+ struct tm tm[2];
+ size_t i;
+ int date_match = filter_view_get_date_match(fv);
+ memset(&tm, 0, sizeof(tm));
+ for (i = 0; i < 2; i++) {
+ tm[i].tm_mon = gtk_combo_box_get_active(fv->dates[i].month);
+ tm[i].tm_mday = gtk_spin_button_get_value_as_int(fv->dates[i].day);
+ tm[i].tm_year = 0;
+ tm[i].tm_hour = gtk_spin_button_get_value_as_int(fv->dates[i].hour);
+ tm[i].tm_min = gtk_spin_button_get_value_as_int(fv->dates[i].minute);
+ tm[i].tm_sec = gtk_spin_button_get_value_as_int(fv->dates[i].second);
+ }
+ if (date_match < 0) {
+ seaudit_filter_set_date(fv->filter, NULL, NULL, 0);
+ } else {
+ seaudit_filter_set_date(fv->filter, tm + 0, tm + 1, (seaudit_filter_date_match_e) date_match);
+ }
+}
+
+/**
+ * Copy values from GTK+ widgets to the seaudit filter object.
+ */
+static void filter_view_apply(struct filter_view *fv)
+{
+ GtkTextIter start, end;
+ char *s;
+ seaudit_filter_match_e match = SEAUDIT_FILTER_MATCH_ALL;
+
+ filter_view_apply_entry(fv, fv->name_entry, seaudit_filter_set_name);
+ if (gtk_combo_box_get_active(fv->match_combo) == 1) {
+ match = SEAUDIT_FILTER_MATCH_ANY;
+ }
+ if (seaudit_filter_set_match(fv->filter, match) < 0) {
+ toplevel_ERR(fv->top, "Error setting filter: %s", strerror(errno));
+ }
+
+ filter_view_apply_context(fv);
+ filter_view_apply_other(fv);
+ filter_view_apply_date(fv);
+
+ gtk_text_buffer_get_bounds(fv->description_buffer, &start, &end);
+ s = gtk_text_buffer_get_text(fv->description_buffer, &start, &end, FALSE);
+ if (strcmp(s, "") == 0) {
+ free(s);
+ s = NULL;
+ }
+ if (seaudit_filter_set_description(fv->filter, s) < 0) {
+ toplevel_ERR(fv->top, "Error setting filter: %s", strerror(errno));
+ }
+ free(s);
+}
+
+/******************** signal handlers for dialog ********************/
+
+/**
+ * Return a list of users within the currently loaded policy, sorted
+ * alphabetically. If there is no policy loaded then return NULL.
+ */
+static apol_vector_t *filter_view_get_policy_users(struct filter_view *fv)
+{
+ apol_vector_t *policy_items = NULL, *v = NULL;
+ apol_policy_t *p = toplevel_get_policy(fv->top);
+ size_t i;
+ if (p == NULL) {
+ return NULL;
+ }
+ if (apol_user_get_by_query(p, NULL, &v) < 0 || (policy_items = apol_vector_create(NULL)) == NULL) {
+ toplevel_ERR(fv->top, "Error getting a list of policy users: %s", strerror(errno));
+ apol_vector_destroy(&policy_items);
+ return NULL;
+ }
+ for (i = 0; i < apol_vector_get_size(v); i++) {
+ const qpol_user_t *e = apol_vector_get_element(v, i);
+ const char *name;
+ qpol_user_get_name(apol_policy_get_qpol(p), e, &name);
+ if (apol_vector_append(policy_items, (void *)name) < 0) {
+ toplevel_ERR(fv->top, "Error getting a list of policy users: %s", strerror(errno));
+ apol_vector_destroy(&v);
+ apol_vector_destroy(&policy_items);
+ }
+ }
+ apol_vector_destroy(&v);
+ apol_vector_sort(policy_items, apol_str_strcmp, NULL);
+ return policy_items;
+}
+
+/**
+ * Return a list of roles within the currently loaded policy, sorted
+ * alphabetically. If there is no policy loaded then return NULL.
+ */
+static apol_vector_t *filter_view_get_policy_roles(struct filter_view *fv)
+{
+ apol_vector_t *policy_items = NULL, *v = NULL;
+ apol_policy_t *p = toplevel_get_policy(fv->top);
+ size_t i;
+ if (p == NULL) {
+ return NULL;
+ }
+ if (apol_role_get_by_query(p, NULL, &v) < 0 || (policy_items = apol_vector_create(NULL)) == NULL) {
+ toplevel_ERR(fv->top, "Error getting a list of policy roles: %s", strerror(errno));
+ apol_vector_destroy(&policy_items);
+ return NULL;
+ }
+ for (i = 0; i < apol_vector_get_size(v); i++) {
+ const qpol_role_t *e = apol_vector_get_element(v, i);
+ const char *name;
+ qpol_role_get_name(apol_policy_get_qpol(p), e, &name);
+ if (apol_vector_append(policy_items, (void *)name) < 0) {
+ toplevel_ERR(fv->top, "Error getting a list of policy roles: %s", strerror(errno));
+ apol_vector_destroy(&v);
+ apol_vector_destroy(&policy_items);
+ }
+ }
+ apol_vector_destroy(&v);
+ apol_vector_sort(policy_items, apol_str_strcmp, NULL);
+ return policy_items;
+}
+
+/**
+ * Return a list of types (not attributes nor aliases) within the
+ * currently loaded policy, sorted alphabetically. If there is no
+ * policy loaded then return NULL.
+ */
+static apol_vector_t *filter_view_get_policy_types(struct filter_view *fv)
+{
+ apol_vector_t *policy_items = NULL, *v = NULL;
+ apol_policy_t *p = toplevel_get_policy(fv->top);
+ size_t i;
+ if (p == NULL) {
+ return NULL;
+ }
+ if (apol_type_get_by_query(p, NULL, &v) < 0 || (policy_items = apol_vector_create(NULL)) == NULL) {
+ toplevel_ERR(fv->top, "Error getting a list of policy types: %s", strerror(errno));
+ apol_vector_destroy(&policy_items);
+ return NULL;
+ }
+ for (i = 0; i < apol_vector_get_size(v); i++) {
+ const qpol_type_t *e = apol_vector_get_element(v, i);
+ const char *name;
+ qpol_type_get_name(apol_policy_get_qpol(p), e, &name);
+ if (apol_vector_append(policy_items, (void *)name) < 0) {
+ toplevel_ERR(fv->top, "Error getting a list of policy types: %s", strerror(errno));
+ apol_vector_destroy(&v);
+ apol_vector_destroy(&policy_items);
+ }
+ }
+ apol_vector_destroy(&v);
+ apol_vector_sort(policy_items, apol_str_strcmp, NULL);
+ return policy_items;
+}
+
+/**
+ * Return a list of mls levels/clearance (not aliases) within the
+ * currently loaded policy, sorted alphabetically. If there is no
+ * policy loaded then return NULL.
+ */
+static apol_vector_t *filter_view_get_policy_mls_lvl(struct filter_view *fv)
+{
+ apol_vector_t *policy_items = NULL, *v = NULL;
+ apol_policy_t *p = toplevel_get_policy(fv->top);
+ const qpol_iterator_t **cats = NULL;
+
+ size_t i;
+
+ if (p == NULL) {
+ return NULL;
+ }
+
+ if (apol_level_get_by_query(p, NULL, &v) < 0 || (policy_items = apol_vector_create(&free)) == NULL) {
+ toplevel_ERR(fv->top, "Error getting a list of policy mls levels: %s", strerror(errno));
+ apol_vector_destroy(&policy_items);
+ return NULL;
+ }
+
+ for (i = 0; i < apol_vector_get_size(v); i++)
+ {
+ const char *name = NULL;
+ const char *mls = malloc(100*sizeof(mls));
+
+ const char *cat_name1 = NULL, *cat_name2 = NULL;
+ uint32_t *cat_val1, *cat_val2;
+ const char *cat_low = NULL;
+ const char *cat_high = NULL;
+ bool isrange = false, isrange_end = false, isempty = true;
+ size_t k;
+ qpol_cat_t *c = NULL;
+ const qpol_level_t *e = apol_vector_get_element(v, i);
+
+ qpol_level_get_name(apol_policy_get_qpol(p), e, &name);
+ strcpy(mls, name);
+ if (qpol_level_get_cat_iter(apol_policy_get_qpol(p), e, &cats) < 0){
+ toplevel_ERR(fv->top, "Error getting categories for level: %s", strerror(errno));
+ qpol_iterator_destroy(&cats);
+ }
+ qpol_iterator_get_size(cats, &k);
+
+ if (k > 0){
+ strcat(mls, ":");
+ isempty = true;
+ }
+ if (qpol_iterator_get_item(cats, &c) < 0){
+ toplevel_ERR(fv->top, "Error getting category: %s", strerror(errno));
+ qpol_iterator_destroy(&cats);
+ }
+ qpol_cat_get_value(apol_policy_get_qpol(p), c, &cat_val1);
+ qpol_cat_get_name(apol_policy_get_qpol(p), c, &cat_name1);
+ isrange = false;
+ isrange_end = false;
+
+ for (; !qpol_iterator_end(cats); qpol_iterator_next(cats))
+ {
+ if (qpol_iterator_get_item(cats, &c) < 0){
+ toplevel_ERR(fv->top, "Error getting category: %s", strerror(errno));
+ qpol_iterator_destroy(&cats);
+ }
+ qpol_cat_get_value(apol_policy_get_qpol(p), c, &cat_val2);
+ qpol_cat_get_name(apol_policy_get_qpol(p), c, &cat_name2);
+ if (((int)cat_val2 == ((int)cat_val1 + 1)) && (isrange == false))
+ {
+ cat_low = cat_name1;
+ strcat(mls, cat_low);
+ strcat(mls, ".");
+ isrange = true;
+ isempty = false;
+ }
+ if ((isrange == true) && ((int)cat_val2 == ((int)cat_val1 + 1)))
+ {
+ cat_high = cat_name2;
+ }
+ else if ((isrange == true) && ((int)cat_val2 != ((int)cat_val1 + 1)))
+ {
+ cat_high = cat_name1;
+ isrange_end = true;
+ strcat(mls, cat_high);
+ isempty=false;
+ }
+ if ((isrange == false) && (isempty == false) && ((int)cat_val2 != ((int)cat_val1 + 1)))
+ {
+ strcat(mls, ",");
+ strcat(mls, cat_name2);
+ }
+ cat_val1 = cat_val2;
+ cat_name1 = cat_name2;
+
+ }
+ if ((isrange == true) && (isrange_end == false))
+ {
+ strcat(mls, cat_high);
+ }
+ if (apol_vector_append(policy_items, (void *)mls) < 0) {
+ toplevel_ERR(fv->top, "Error getting a list of policy mls levels: %s", strerror(errno));
+ apol_vector_destroy(&v);
+ apol_vector_destroy(&policy_items);
+ }
+ }
+
+ apol_vector_destroy(&v);
+ qpol_iterator_destroy(&cats);
+ apol_vector_sort(policy_items, apol_str_strcmp, NULL);
+ return policy_items;
+}
+
+/**
+ * Return a list of object classeswithin the currently loaded policy,
+ * sorted alphabetically. If there is no policy loaded then return
+ * NULL.
+ */
+static apol_vector_t *filter_view_get_policy_classes(struct filter_view *fv)
+{
+ apol_vector_t *policy_items = NULL, *v = NULL;
+ apol_policy_t *p = toplevel_get_policy(fv->top);
+ size_t i;
+ if (p == NULL) {
+ return NULL;
+ }
+ if (apol_class_get_by_query(p, NULL, &v) < 0 || (policy_items = apol_vector_create(NULL)) == NULL) {
+ toplevel_ERR(fv->top, "Error getting a list of policy classes: %s", strerror(errno));
+ apol_vector_destroy(&policy_items);
+ return NULL;
+ }
+ for (i = 0; i < apol_vector_get_size(v); i++) {
+ const qpol_class_t *e = apol_vector_get_element(v, i);
+ const char *name;
+ qpol_class_get_name(apol_policy_get_qpol(p), e, &name);
+ if (apol_vector_append(policy_items, (void *)name) < 0) {
+ toplevel_ERR(fv->top, "Error getting a list of policy classes: %s", strerror(errno));
+ apol_vector_destroy(&v);
+ apol_vector_destroy(&policy_items);
+ }
+ }
+ apol_vector_destroy(&v);
+ apol_vector_sort(policy_items, apol_str_strcmp, NULL);
+ return policy_items;
+}
+
+static void filter_view_on_suser_context_click(GtkButton * widget __attribute__ ((unused)), gpointer user_data)
+{
+ struct filter_view *fv = (struct filter_view *)user_data;
+ apol_vector_t *log_items = toplevel_get_log_users(fv->top);
+ apol_vector_t *policy_items = filter_view_get_policy_users(fv);
+ fv->suser.items =
+ policy_components_view_run(fv->top, GTK_WINDOW(fv->dialog), "Source User Items", log_items, policy_items,
+ fv->suser.items);
+ apol_vector_destroy(&log_items);
+ apol_vector_destroy(&policy_items);
+ filter_view_context_item_to_entry(fv, &fv->suser);
+}
+
+static void filter_view_on_srole_context_click(GtkButton * widget __attribute__ ((unused)), gpointer user_data)
+{
+ struct filter_view *fv = (struct filter_view *)user_data;
+ apol_vector_t *log_items = toplevel_get_log_roles(fv->top);
+ apol_vector_t *policy_items = filter_view_get_policy_roles(fv);
+ fv->srole.items =
+ policy_components_view_run(fv->top, GTK_WINDOW(fv->dialog), "Source Role Items", log_items, policy_items,
+ fv->srole.items);
+ apol_vector_destroy(&log_items);
+ apol_vector_destroy(&policy_items);
+ filter_view_context_item_to_entry(fv, &fv->srole);
+}
+
+static void filter_view_on_stype_context_click(GtkButton * widget __attribute__ ((unused)), gpointer user_data)
+{
+ struct filter_view *fv = (struct filter_view *)user_data;
+ apol_vector_t *log_items = toplevel_get_log_types(fv->top);
+ apol_vector_t *policy_items = filter_view_get_policy_types(fv);
+ fv->stype.items =
+ policy_components_view_run(fv->top, GTK_WINDOW(fv->dialog), "Source Type Items", log_items, policy_items,
+ fv->stype.items);
+ apol_vector_destroy(&log_items);
+ apol_vector_destroy(&policy_items);
+ filter_view_context_item_to_entry(fv, &fv->stype);
+}
+
+static void filter_view_on_smls_lvl_context_click(GtkButton * widget __attribute__ ((unused)), gpointer user_data)
+{
+ struct filter_view *fv = (struct filter_view *)user_data;
+
+ apol_vector_t *log_items = toplevel_get_log_mls_lvl(fv->top);
+ apol_vector_t *policy_items = filter_view_get_policy_mls_lvl(fv);
+ fv->smls_lvl.items =
+ policy_components_view_run(fv->top, GTK_WINDOW(fv->dialog), "Source MLS Level Items", log_items, policy_items,
+ fv->smls_lvl.items);
+ apol_vector_destroy(&log_items);
+ apol_vector_destroy(&policy_items);
+ filter_view_context_item_to_entry(fv, &fv->smls_lvl);
+}
+
+static void filter_view_on_smls_clr_context_click(GtkButton * widget __attribute__ ((unused)), gpointer user_data)
+{
+ struct filter_view *fv = (struct filter_view *)user_data;
+ apol_vector_t *log_items = toplevel_get_log_mls_clr(fv->top);
+ apol_vector_t *policy_items = filter_view_get_policy_mls_lvl(fv);
+ fv->smls_clr.items =
+ policy_components_view_run(fv->top, GTK_WINDOW(fv->dialog), "Source MLS Clearance Items", log_items, policy_items,
+ fv->smls_clr.items);
+ apol_vector_destroy(&log_items);
+ apol_vector_destroy(&policy_items);
+ filter_view_context_item_to_entry(fv, &fv->smls_clr);
+}
+
+static void filter_view_on_tuser_context_click(GtkButton * widget __attribute__ ((unused)), gpointer user_data)
+{
+ struct filter_view *fv = (struct filter_view *)user_data;
+ apol_vector_t *log_items = toplevel_get_log_users(fv->top);
+ apol_vector_t *policy_items = filter_view_get_policy_users(fv);
+ fv->tuser.items =
+ policy_components_view_run(fv->top, GTK_WINDOW(fv->dialog), "Target User Items", log_items, policy_items,
+ fv->tuser.items);
+ apol_vector_destroy(&log_items);
+ apol_vector_destroy(&policy_items);
+ filter_view_context_item_to_entry(fv, &fv->tuser);
+}
+
+static void filter_view_on_trole_context_click(GtkButton * widget __attribute__ ((unused)), gpointer user_data)
+{
+ struct filter_view *fv = (struct filter_view *)user_data;
+ apol_vector_t *log_items = toplevel_get_log_roles(fv->top);
+ apol_vector_t *policy_items = filter_view_get_policy_roles(fv);
+ fv->trole.items =
+ policy_components_view_run(fv->top, GTK_WINDOW(fv->dialog), "Target Role Items", log_items, policy_items,
+ fv->trole.items);
+ apol_vector_destroy(&log_items);
+ apol_vector_destroy(&policy_items);
+ filter_view_context_item_to_entry(fv, &fv->trole);
+}
+
+static void filter_view_on_ttype_context_click(GtkButton * widget __attribute__ ((unused)), gpointer user_data)
+{
+ struct filter_view *fv = (struct filter_view *)user_data;
+ apol_vector_t *log_items = toplevel_get_log_types(fv->top);
+ apol_vector_t *policy_items = filter_view_get_policy_types(fv);
+ fv->ttype.items =
+ policy_components_view_run(fv->top, GTK_WINDOW(fv->dialog), "Target Type Items", log_items, policy_items,
+ fv->ttype.items);
+ apol_vector_destroy(&log_items);
+ apol_vector_destroy(&policy_items);
+ filter_view_context_item_to_entry(fv, &fv->ttype);
+}
+
+static void filter_view_on_tmls_lvl_context_click(GtkButton * widget __attribute__ ((unused)), gpointer user_data)
+{
+ struct filter_view *fv = (struct filter_view *)user_data;
+ apol_vector_t *log_items = toplevel_get_log_mls_lvl(fv->top);
+ apol_vector_t *policy_items = filter_view_get_policy_mls_lvl(fv);
+ fv->tmls_lvl.items =
+ policy_components_view_run(fv->top, GTK_WINDOW(fv->dialog), "Target MLS Level Items", log_items, policy_items,
+ fv->tmls_lvl.items);
+ apol_vector_destroy(&log_items);
+ apol_vector_destroy(&policy_items);
+ filter_view_context_item_to_entry(fv, &fv->tmls_lvl);
+}
+
+static void filter_view_on_tmls_clr_context_click(GtkButton * widget __attribute__ ((unused)), gpointer user_data)
+{
+ struct filter_view *fv = (struct filter_view *)user_data;
+ apol_vector_t *log_items = toplevel_get_log_mls_clr(fv->top);
+ apol_vector_t *policy_items = filter_view_get_policy_mls_lvl(fv);
+ fv->tmls_clr.items =
+ policy_components_view_run(fv->top, GTK_WINDOW(fv->dialog), "Target MLS Clearance Items", log_items, policy_items,
+ fv->tmls_clr.items);
+ apol_vector_destroy(&log_items);
+ apol_vector_destroy(&policy_items);
+ filter_view_context_item_to_entry(fv, &fv->tmls_clr);
+}
+
+static void filter_view_on_class_context_click(GtkButton * widget __attribute__ ((unused)), gpointer user_data)
+{
+ struct filter_view *fv = (struct filter_view *)user_data;
+ apol_vector_t *log_items = toplevel_get_log_classes(fv->top);
+ apol_vector_t *policy_items = filter_view_get_policy_classes(fv);
+ fv->obj_class.items =
+ policy_components_view_run(fv->top, GTK_WINDOW(fv->dialog), "Object Class Items", log_items, policy_items,
+ fv->obj_class.items);
+ apol_vector_destroy(&log_items);
+ apol_vector_destroy(&policy_items);
+ filter_view_context_item_to_entry(fv, &fv->obj_class);
+}
+
+/**
+ * Whenever the user finished manually editing a context entry,
+ * convert the entry's string into the underlying vector.
+ */
+static gboolean filter_view_on_entry_focus_out(GtkWidget * widget, GdkEventFocus * event
+ __attribute__ ((unused)), gpointer user_data)
+{
+ struct context_item *item = g_object_get_data(G_OBJECT(widget), "data");
+ struct filter_view *fv = (struct filter_view *)user_data;
+ gchar **strs = g_strsplit(gtk_entry_get_text(GTK_ENTRY(widget)), ",", -1);
+ gchar *s;
+ size_t i = 0;
+ char *t;
+ apol_vector_t *new_v = NULL;
+ while (1) {
+ s = strs[i++];
+ if (s == NULL) {
+ break;
+ }
+ if (new_v == NULL && (new_v = apol_vector_create(free)) == NULL) {
+ toplevel_ERR(fv->top, "Could not interpret entry contents: %s", strerror(errno));
+ break;
+ }
+ if ((t = strdup(s)) == NULL) {
+ toplevel_ERR(fv->top, "Could not interpret entry contents: %s", strerror(errno));
+ free(t);
+ break;
+ }
+ apol_str_trim(t);
+ if (apol_vector_append(new_v, t) < 0) {
+ toplevel_ERR(fv->top, "Could not interpret entry contents: %s", strerror(errno));
+ free(t);
+ break;
+ }
+ }
+ g_strfreev(strs);
+ apol_vector_destroy(&item->items);
+ item->items = new_v;
+ filter_view_context_item_to_entry(fv, item);
+ return FALSE;
+}
+
+static void filter_view_destroy_context_vectors(struct filter_view *fv)
+{
+ apol_vector_destroy(&fv->suser.items);
+ apol_vector_destroy(&fv->srole.items);
+ apol_vector_destroy(&fv->stype.items);
+ apol_vector_destroy(&fv->smls_lvl.items);
+ apol_vector_destroy(&fv->smls_clr.items);
+ apol_vector_destroy(&fv->tuser.items);
+ apol_vector_destroy(&fv->trole.items);
+ apol_vector_destroy(&fv->ttype.items);
+ apol_vector_destroy(&fv->tmls_lvl.items);
+ apol_vector_destroy(&fv->tmls_clr.items);
+ apol_vector_destroy(&fv->obj_class.items);
+}
+
+static void filter_view_on_context_clear_click(GtkButton * widget __attribute__ ((unused)), gpointer user_data)
+{
+ struct filter_view *fv = (struct filter_view *)user_data;
+ filter_view_destroy_context_vectors(fv);
+ filter_view_context_items_to_entries(fv);
+}
+
+static void filter_view_init_context_signals(struct filter_view *fv)
+{
+ g_signal_connect(fv->suser.button, "clicked", G_CALLBACK(filter_view_on_suser_context_click), fv);
+ g_signal_connect(fv->suser.entry, "focus_out_event", G_CALLBACK(filter_view_on_entry_focus_out), fv);
+ g_signal_connect(fv->srole.button, "clicked", G_CALLBACK(filter_view_on_srole_context_click), fv);
+ g_signal_connect(fv->srole.entry, "focus_out_event", G_CALLBACK(filter_view_on_entry_focus_out), fv);
+ g_signal_connect(fv->stype.button, "clicked", G_CALLBACK(filter_view_on_stype_context_click), fv);
+ g_signal_connect(fv->stype.entry, "focus_out_event", G_CALLBACK(filter_view_on_entry_focus_out), fv);
+ g_signal_connect(fv->smls_lvl.button, "clicked", G_CALLBACK(filter_view_on_smls_lvl_context_click), fv);
+ g_signal_connect(fv->smls_lvl.entry, "focus_out_event", G_CALLBACK(filter_view_on_entry_focus_out), fv);
+ g_signal_connect(fv->smls_clr.button, "clicked", G_CALLBACK(filter_view_on_smls_clr_context_click), fv);
+ g_signal_connect(fv->smls_clr.entry, "focus_out_event", G_CALLBACK(filter_view_on_entry_focus_out), fv);
+ g_signal_connect(fv->tuser.button, "clicked", G_CALLBACK(filter_view_on_tuser_context_click), fv);
+ g_signal_connect(fv->tuser.entry, "focus_out_event", G_CALLBACK(filter_view_on_entry_focus_out), fv);
+ g_signal_connect(fv->trole.button, "clicked", G_CALLBACK(filter_view_on_trole_context_click), fv);
+ g_signal_connect(fv->trole.entry, "focus_out_event", G_CALLBACK(filter_view_on_entry_focus_out), fv);
+ g_signal_connect(fv->ttype.button, "clicked", G_CALLBACK(filter_view_on_ttype_context_click), fv);
+ g_signal_connect(fv->ttype.entry, "focus_out_event", G_CALLBACK(filter_view_on_entry_focus_out), fv);
+ g_signal_connect(fv->tmls_lvl.button, "clicked", G_CALLBACK(filter_view_on_tmls_lvl_context_click), fv);
+ g_signal_connect(fv->tmls_lvl.entry, "focus_out_event", G_CALLBACK(filter_view_on_entry_focus_out), fv);
+ g_signal_connect(fv->tmls_clr.button, "clicked", G_CALLBACK(filter_view_on_tmls_clr_context_click), fv);
+ g_signal_connect(fv->tmls_clr.entry, "focus_out_event", G_CALLBACK(filter_view_on_entry_focus_out), fv);
+ g_signal_connect(fv->obj_class.button, "clicked", G_CALLBACK(filter_view_on_class_context_click), fv);
+ g_signal_connect(fv->obj_class.entry, "focus_out_event", G_CALLBACK(filter_view_on_entry_focus_out), fv);
+ g_signal_connect(fv->context_clear_button, "clicked", G_CALLBACK(filter_view_on_context_clear_click), fv);
+}
+
+static void filter_view_on_other_clear_click(GtkButton * widget __attribute__ ((unused)), gpointer user_data)
+{
+ struct filter_view *fv = (struct filter_view *)user_data;
+ gtk_entry_set_text(fv->ipaddr_entry, "");
+ gtk_entry_set_text(fv->port_entry, "");
+ gtk_entry_set_text(fv->netif_entry, "");
+ gtk_entry_set_text(fv->exe_entry, "");
+ gtk_entry_set_text(fv->path_entry, "");
+ gtk_entry_set_text(fv->host_entry, "");
+ gtk_entry_set_text(fv->comm_entry, "");
+ gtk_combo_box_set_active(fv->message_combo, 0);
+}
+
+static void filter_view_on_date_toggle(GtkToggleButton * widget, gpointer user_data)
+{
+ struct filter_view *fv = (struct filter_view *)user_data;
+ int match;
+ /* clicking on the radio buttons emit two toggle signals, one for
+ * the original button and one for the new one. thus only need to
+ * handle half of all signals */
+ if (!gtk_toggle_button_get_active(widget)) {
+ return;
+ }
+ match = filter_view_get_date_match(fv);
+ gtk_widget_set_sensitive(GTK_WIDGET(fv->dates[0].frame), (match != -1));
+ gtk_widget_set_sensitive(GTK_WIDGET(fv->dates[1].frame), (match == SEAUDIT_FILTER_DATE_MATCH_BETWEEN));
+}
+
+/* Given the year and the month set the spin button to have the
+ correct number of days for that month */
+static void filter_view_date_set_number_days(int month, GtkSpinButton * button)
+{
+ static const int days[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+ int cur_day;
+ /* get the current day because set_range moves the current day
+ * by the difference minus 1 day. e.g., going from jan 20 to
+ * february the day would automatically become 18 */
+ cur_day = gtk_spin_button_get_value_as_int(button);
+ gtk_spin_button_set_range(button, 1, days[month]);
+ /* return to current day, or to the max value allowed in range */
+ gtk_spin_button_set_value(button, cur_day);
+}
+
+static void filter_view_on_month0_change(GtkComboBox * widget, gpointer user_data)
+{
+ struct filter_view *fv = (struct filter_view *)user_data;
+ filter_view_date_set_number_days(gtk_combo_box_get_active(widget), fv->dates[0].day);
+}
+
+static void filter_view_on_month1_change(GtkComboBox * widget, gpointer user_data)
+{
+ struct filter_view *fv = (struct filter_view *)user_data;
+ filter_view_date_set_number_days(gtk_combo_box_get_active(widget), fv->dates[1].day);
+}
+
+static void filter_view_init_signals(struct filter_view *fv)
+{
+ filter_view_init_context_signals(fv);
+ g_signal_connect(fv->other_clear_button, "clicked", G_CALLBACK(filter_view_on_other_clear_click), fv);
+ g_signal_connect(fv->date_none_radio, "toggled", G_CALLBACK(filter_view_on_date_toggle), fv);
+ g_signal_connect(fv->date_before_radio, "toggled", G_CALLBACK(filter_view_on_date_toggle), fv);
+ g_signal_connect(fv->date_after_radio, "toggled", G_CALLBACK(filter_view_on_date_toggle), fv);
+ g_signal_connect(fv->date_between_radio, "toggled", G_CALLBACK(filter_view_on_date_toggle), fv);
+ g_signal_connect(fv->dates[0].month, "changed", G_CALLBACK(filter_view_on_month0_change), fv);
+ g_signal_connect(fv->dates[1].month, "changed", G_CALLBACK(filter_view_on_month1_change), fv);
+}
+
+/******************** public function below ********************/
+
+void filter_view_run(seaudit_filter_t * filter, toplevel_t * top, GtkWindow * parent)
+{
+ struct filter_view fv;
+ gint response;
+
+ memset(&fv, 0, sizeof(fv));
+ fv.top = top;
+ fv.filter = filter;
+ fv.xml = glade_xml_new(toplevel_get_glade_xml(top), "FilterWindow", NULL);
+ filter_view_init_widgets(&fv, parent);
+ filter_view_init_signals(&fv);
+ filter_view_init_dialog(&fv);
+ do {
+ response = gtk_dialog_run(fv.dialog);
+ } while (response != GTK_RESPONSE_CLOSE);
+
+ filter_view_apply(&fv);
+ g_object_unref(fv.description_buffer);
+ gtk_widget_destroy(GTK_WIDGET(fv.dialog));
+ filter_view_destroy_context_vectors(&fv);
+}