summaryrefslogtreecommitdiffstats
path: root/apol
diff options
context:
space:
mode:
authorMiroslav Grepl <mgrepl@redhat.com>2014-04-11 09:37:53 +0200
committerMiroslav Grepl <mgrepl@redhat.com>2014-04-11 09:37:53 +0200
commit47be9ff57e72906660bb62a515222f482131e1fb (patch)
tree2cb0ef0ba48d73b1df7cc0915754a17e19464bb6 /apol
downloadsetools-47be9ff57e72906660bb62a515222f482131e1fb.tar.gz
setools-47be9ff57e72906660bb62a515222f482131e1fb.tar.xz
setools-47be9ff57e72906660bb62a515222f482131e1fb.zip
Create setools-3.3.7 git repomaster
Diffstat (limited to 'apol')
-rw-r--r--apol/Makefile.am131
-rw-r--r--apol/analysis_tab.tcl326
-rw-r--r--apol/apol.gifbin0 -> 1305 bytes
-rw-r--r--apol/apol.pngbin0 -> 1408 bytes
-rw-r--r--apol/apol.xcfbin0 -> 9291 bytes
-rw-r--r--apol/apol_help.txt482
-rw-r--r--apol/apol_tcl.cc142
-rw-r--r--apol/apol_tcl.i451
-rw-r--r--apol/classes_perms_tab.tcl484
-rw-r--r--apol/common_widgets.tcl688
-rw-r--r--apol/cond_bools_tab.tcl266
-rw-r--r--apol/cond_rules_tab.tcl281
-rw-r--r--apol/context_dialog.tcl340
-rw-r--r--apol/context_selector.tcl150
-rw-r--r--apol/directflow_module.tcl582
-rw-r--r--apol/domaintrans_help.txt141
-rw-r--r--apol/domaintrans_module.tcl999
-rw-r--r--apol/file_contexts_tab.tcl504
-rw-r--r--apol/file_relabel_help.txt68
-rw-r--r--apol/find.tcl134
-rw-r--r--apol/foo_module.tcl143
-rw-r--r--apol/fscontexts_tab.tcl472
-rw-r--r--apol/goto.tcl78
-rw-r--r--apol/head.tcl29
-rw-r--r--apol/infoflow_help.txt321
-rw-r--r--apol/initial_sids_tab.tcl142
-rw-r--r--apol/level_dialog.tcl82
-rw-r--r--apol/mls_tab.tcl332
-rw-r--r--apol/netcontexts_tab.tcl878
-rw-r--r--apol/open_policy_dialog.tcl388
-rw-r--r--apol/perm_maps/apol_perm_mapping_ver12575
-rw-r--r--apol/perm_maps/apol_perm_mapping_ver15580
-rw-r--r--apol/perm_maps/apol_perm_mapping_ver16560
-rw-r--r--apol/perm_maps/apol_perm_mapping_ver17561
-rw-r--r--apol/perm_maps/apol_perm_mapping_ver18922
-rw-r--r--apol/perm_maps/apol_perm_mapping_ver19952
-rw-r--r--apol/perm_maps/apol_perm_mapping_ver20993
-rw-r--r--apol/perm_maps/apol_perm_mapping_ver21998
-rw-r--r--apol/perm_maps/apol_perm_mapping_ver22998
-rw-r--r--apol/perm_maps/apol_perm_mapping_ver23998
-rw-r--r--apol/perm_maps/apol_perm_mapping_ver241227
-rw-r--r--apol/perms_map.tcl410
-rw-r--r--apol/policyconf.tcl102
-rw-r--r--apol/progress_dialog.tcl74
-rw-r--r--apol/range_dialog.tcl132
-rw-r--r--apol/range_selector.tcl156
-rw-r--r--apol/range_trans.tcl204
-rw-r--r--apol/rbac_tab.tcl490
-rw-r--r--apol/relabel_module.tcl898
-rw-r--r--apol/roles_tab.tcl196
-rw-r--r--apol/terules_tab.tcl1034
-rw-r--r--apol/top.tcl1228
-rw-r--r--apol/transflow_module.tcl1156
-rw-r--r--apol/types_relation_help.txt53
-rw-r--r--apol/types_relation_module.tcl770
-rw-r--r--apol/types_tab.tcl411
-rw-r--r--apol/users_tab.tcl313
-rw-r--r--apol/util.tcl312
58 files changed, 26337 insertions, 0 deletions
diff --git a/apol/Makefile.am b/apol/Makefile.am
new file mode 100644
index 0000000..646d8b1
--- /dev/null
+++ b/apol/Makefile.am
@@ -0,0 +1,131 @@
+wrappedso_DATA = libapol_tcl.so.@libapol_version@
+wrappedso_SONAME = $(wrappedso_DATA)
+wrappedsodir = $(libdir)/setools/apol_tcl
+
+package_SCRIPTS = pkgIndex.tcl
+packagedir = $(wrappedsodir)
+
+bin_SCRIPTS = apol
+
+dist_noinst_DATA = apol_tcl.i apol_tcl.cc apol.png foo_module.tcl
+BUILT_SOURCES = apol_tcl_wrap.cc mkIndex.tcl init.tcl
+
+dist_setools_DATA = apol_help.txt domaintrans_help.txt file_relabel_help.txt \
+ infoflow_help.txt types_relation_help.txt \
+ perm_maps/apol_perm_mapping_ver12 \
+ perm_maps/apol_perm_mapping_ver15 \
+ perm_maps/apol_perm_mapping_ver16 \
+ perm_maps/apol_perm_mapping_ver17 \
+ perm_maps/apol_perm_mapping_ver18 \
+ perm_maps/apol_perm_mapping_ver19 \
+ perm_maps/apol_perm_mapping_ver20 \
+ perm_maps/apol_perm_mapping_ver21 \
+ perm_maps/apol_perm_mapping_ver22 \
+ perm_maps/apol_perm_mapping_ver23 \
+ perm_maps/apol_perm_mapping_ver24 \
+ apol.gif
+
+EXTRA_DIST = \
+ analysis_tab.tcl \
+ classes_perms_tab.tcl \
+ common_widgets.tcl \
+ cond_bools_tab.tcl \
+ cond_rules_tab.tcl \
+ context_dialog.tcl \
+ context_selector.tcl \
+ directflow_module.tcl \
+ domaintrans_module.tcl \
+ file_contexts_tab.tcl \
+ find.tcl \
+ fscontexts_tab.tcl \
+ goto.tcl \
+ head.tcl \
+ initial_sids_tab.tcl \
+ level_dialog.tcl \
+ mls_tab.tcl \
+ netcontexts_tab.tcl \
+ open_policy_dialog.tcl \
+ perms_map.tcl \
+ policyconf.tcl \
+ progress_dialog.tcl \
+ range_dialog.tcl \
+ range_selector.tcl \
+ range_trans.tcl \
+ rbac_tab.tcl \
+ relabel_module.tcl \
+ roles_tab.tcl \
+ terules_tab.tcl \
+ transflow_module.tcl \
+ types_relation_module.tcl \
+ types_tab.tcl \
+ users_tab.tcl \
+ util.tcl \
+ top.tcl
+# top.tcl must be last one written because it spawns the rest of the script
+
+TCL_STRIP_FILES = $(patsubst %,$(srcdir)/%,$(filter-out head.tcl,$(EXTRA_DIST)))
+DEPENDENCIES = $(top_builddir)/libqpol/src/libqpol.so \
+ $(top_builddir)/libapol/src/libapol.so \
+ $(top_builddir)/libsefs/src/libsefs.so \
+ $(top_builddir)/libqpol/swig/tcl/libtqpol.so \
+ $(top_builddir)/libapol/swig/tcl/libtapol.so \
+ $(top_builddir)/libsefs/swig/tcl/libtsefs.so \
+ $(top_builddir)/config.tcl
+
+AM_CXXFLAGS = @DEBUGCXXFLAGS@ @WARNCXXFLAGS@ @PROFILECFLAGS@ @SELINUX_CFLAGS@ \
+ @SEFS_CFLAGS@ @APOL_CFLAGS@ @QPOL_CFLAGS@ -I$(top_builddir) -fpic \
+ -I$(top_srcdir)/libapol/include
+AM_LDFLAGS = @DEBUGLDFLAGS@ @WARNLDFLAGS@ @PROFILELDFLAGS@ \
+ @SEFS_LIB_FLAG@ @APOL_LIB_FLAG@ @QPOL_LIB_FLAG@
+
+apol_tcl_wrap.cc: apol_tcl.i $(DEPENDENCIES)
+ $(SWIG) -c++ $(SWIG_TCL_OPT) -pkgversion @libapol_version@ -o $@ \
+ -I$(top_srcdir)/libsefs/include -I$(top_srcdir)/libsefs/swig \
+ -I$(top_srcdir)/libapol/include -I$(top_srcdir)/libapol/swig \
+ -I$(top_srcdir)/libqpol/swig $<
+
+$(wrappedso_DATA): apol_tcl.cc apol_tcl_wrap.cc
+ $(CXX) -shared -o $@ $^ $(AM_CXXFLAGS) $(CXXFLAGS) $(SWIG_TCL_CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -Wl,-soname,$(wrappedso_SONAME)
+
+$(package_SCRIPTS): $(wrappedso_DATA) mkIndex.tcl
+ cat mkIndex.tcl | LD_LIBRARY_PATH=$(top_builddir)/libqpol/src:$(top_builddir)/libapol/src:$(top_builddir)/libsefs/src $(TCLSH_PROG)
+ $(mkdir_p) apol_tcl
+ cp $< $@ apol_tcl
+
+mkIndex.tcl: $(wrappedso_DATA) Makefile
+ @echo "lappend auto_path $(top_builddir)/libapol/swig/tcl $(top_builddir)/libsefs/swig/tcl" > $@
+ @echo "package require apol" >> $@
+ @echo "package require sefs" >> $@
+ @echo "pkg_mkIndex . $<" >> $@
+
+TCL_AUTOPATH = @TCL_AUTOPATH@
+
+init.tcl: Makefile
+ @echo "proc tcl_config_init_libraries {} {" > $@
+ @echo " global auto_path" >> $@
+ @echo " lappend auto_path $(TCL_AUTOPATH)" >> $@
+ @echo " print_init \"Initializing libqpol... \"" >> $@
+ @echo " package require qpol @libqpol_version@" >> $@
+ @echo " print_init \"done.\nInitializing libapol... \"" >> $@
+ @echo " package require apol @libapol_version@" >> $@
+ @echo " print_init \"done.\nInitializing libsefs... \"" >> $@
+ @echo " package require sefs @libsefs_version@" >> $@
+ @echo " print_init \"done.\nInitializing libapol_tcl... \"" >> $@
+ @echo " package require apol_tcl @libapol_version@" >> $@
+ @echo " print_init \"done.\n\"" >> $@
+ @echo "}" >> $@
+ @echo "proc tcl_config_get_install_dir {} {" >> $@
+ @echo " return \"${setoolsdir}\"" >> $@
+ @echo "}" >> $@
+
+$(bin_SCRIPTS): $(package_SCRIPTS) head.tcl init.tcl $(top_builddir)/config.tcl $(TCL_STRIP_FILES)
+ cat $(srcdir)/head.tcl init.tcl $(top_builddir)/config.tcl > $@
+ cat $(TCL_STRIP_FILES) | perl -p -i -e 's/^\s*(\#[^!]*){0,1}$$//s' >> $@
+ chmod u+x $@
+
+%.tcl:
+# do nothing
+
+CLEANFILES = $(packages_SCRIPTS) $(bin_SCRIPTS) $(BUILT_SOURCES)
+
+MOSTLYCLEANFILES = $(wrappedso_DATA) $(package_SCRIPTS) apol_tcl/$(wrappedso_DATA) apol_tcl/$(package_SCRIPTS)
diff --git a/apol/analysis_tab.tcl b/apol/analysis_tab.tcl
new file mode 100644
index 0000000..99fb67c
--- /dev/null
+++ b/apol/analysis_tab.tcl
@@ -0,0 +1,326 @@
+# Copyright (C) 2003-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
+
+namespace eval Apol_Analysis {
+ variable vals
+ variable widgets
+ variable tabs
+}
+
+proc Apol_Analysis::create {tab_name nb} {
+ variable vals
+ variable widgets
+
+ set frame [$nb insert end $tab_name -text "Analysis"]
+ set pw [PanedWindow $frame.pw -side left -weights extra]
+ set topf [$pw add -weight 0]
+ set bottomf [$pw add -weight 1]
+ pack $pw -expand 1 -fill both
+
+ set top_leftf [TitleFrame $topf.left -text "Analysis Type"]
+ set opts_f [TitleFrame $topf.opts -text "Analysis Options"]
+ set buttons_f [frame $topf.buttons]
+ pack $top_leftf -side left -expand 0 -fill y -padx 2
+ pack $opts_f -side left -expand 1 -fill both -padx 2
+ pack $buttons_f -side right -expand 0 -anchor ne -padx 2
+ set results_f [TitleFrame $bottomf.r -text "Analysis Results"]
+ pack $results_f -expand 1 -fill both -padx 2
+
+ set widgets(modules) [Apol_Widget::makeScrolledListbox [$top_leftf getframe].m \
+ -height 8 -width 24 -listvar Apol_Analysis::vals(module_names) -exportselection 0]
+ $widgets(modules).lb selection set 0
+ bind $widgets(modules).lb <<ListboxSelect>> Apol_Analysis::_selectModule
+ pack $widgets(modules) -expand 1 -fill both
+
+ set widgets(search_opts) [PagesManager [$opts_f getframe].s]
+ foreach m $vals(modules) {
+ ${m}::create [$widgets(search_opts) add $m]
+ }
+ $widgets(search_opts) compute_size
+ $widgets(search_opts) raise [lindex $vals(modules) 0]
+ pack $widgets(search_opts) -expand 1 -fill both
+
+ set widgets(new) [button $buttons_f.new -text "New Analysis" -width 12 \
+ -command [list Apol_Analysis::_analyze new]]
+ set widgets(update) [button $buttons_f.update -text "Update Analysis" -width 12 -state disabled \
+ -command [list Apol_Analysis::_analyze update]]
+ set widgets(reset) [button $buttons_f.reset -text "Reset Criteria" -width 12 \
+ -command Apol_Analysis::_reset]
+ set widgets(info) [button $buttons_f.info -text "Info" -width 12 \
+ -command Apol_Analysis::_info]
+ pack $widgets(new) $widgets(update) $widgets(reset) $widgets(info) \
+ -side top -pady 5 -padx 5 -anchor ne
+
+ set popupTab_Menu [menu .popup_analysis -tearoff 0]
+ set tab_menu_callbacks \
+ [list {"Close Tab" Apol_Analysis::_deleteResults} \
+ {"Rename Tab" Apol_Analysis::_displayRenameTabDialog}]
+
+ set widgets(results) [NoteBook [$results_f getframe].results]
+ $widgets(results) bindtabs <Button-1> Apol_Analysis::_switchTab
+ $widgets(results) bindtabs <Button-3> \
+ [list ApolTop::popup \
+ %W %x %y $popupTab_Menu $tab_menu_callbacks]
+ set close [button [$results_f getframe].close -text "Close Tab" \
+ -command Apol_Analysis::_deleteCurrentResults]
+ pack $widgets(results) -expand 1 -fill both -padx 4
+ pack $close -expand 0 -fill x -padx 4 -pady 2
+
+ _reinitializeTabs
+ return $frame
+}
+
+proc Apol_Analysis::open {ppath} {
+ variable vals
+ foreach m $vals(modules) {
+ ${m}::open
+ }
+}
+
+proc Apol_Analysis::close {} {
+ variable vals
+ variable widgets
+ foreach m $vals(modules) {
+ ${m}::close
+ }
+ _reinitializeTabs
+}
+
+proc Apol_Analysis::getTextWidget {} {
+ variable widgets
+ variable tabs
+ set curid [$widgets(results) raise]
+ if {$curid != {}} {
+ return [$tabs($curid:module)::getTextWidget [$widgets(results) getframe $curid]]
+ }
+ return {}
+}
+
+proc Apol_Analysis::save_query_options {file_channel query_file} {
+ variable widgets
+ set m [$widgets(search_opts) raise]
+ puts $file_channel $m
+ ${m}::saveQuery $file_channel
+}
+
+proc Apol_Analysis::load_query_options {file_channel} {
+ variable vals
+ variable widgets
+
+ # Search for the module name
+ set line {}
+ while {[gets $file_channel line] >= 0} {
+ set line [string trim $line]
+ # Skip empty lines and comments
+ if {$line == {} || [string index $line 0] == "#"} {
+ continue
+ }
+ break
+ }
+ if {$line == {} || [set i [lsearch -exact $vals(modules) $line]] == -1} {
+ tk_messageBox -icon error -type ok -title "Open Apol Query" -message "The specified query is not a valid analysis module."
+ return
+ }
+ ${line}::loadQuery $file_channel
+ $widgets(modules).lb selection clear 0 end
+ set module [lindex $vals(modules) $i]
+ $widgets(search_opts) raise $module
+ $widgets(modules).lb selection set [lsearch $vals(module_names) $vals($module:name)]
+}
+
+#################### functions invoked by modules ####################
+
+proc Apol_Analysis::registerAnalysis {mod_proc mod_name} {
+ variable vals
+ lappend vals(modules) $mod_proc
+ lappend vals(module_names) $mod_name
+ set vals($mod_proc:name) $mod_name
+}
+
+proc Apol_Analysis::createResultTab {short_name criteria} {
+ variable widgets
+ variable tabs
+
+ set i $tabs(next_result_id)
+ incr tabs(next_result_id)
+ set m [$widgets(search_opts) raise]
+ set id "results$i"
+ set frame [$widgets(results) insert end $id -text "($i) $short_name"]
+ $widgets(results) raise $id
+
+ set tabs($id:module) $m
+ set tabs($id:vals) $criteria
+ return $frame
+}
+
+proc Apol_Analysis::setResultTabCriteria {criteria} {
+ variable widgets
+ variable tabs
+ set id [$widgets(results) raise]
+ if {$id != {}} {
+ set tabs($id:vals) $criteria
+ }
+}
+
+#################### private functions ####################
+
+proc Apol_Analysis::_selectModule {} {
+ variable vals
+ variable widgets
+ variable tabs
+
+ focus $widgets(modules).lb
+ if {[set selection [$widgets(modules).lb curselection]] == {}} {
+ return
+ }
+ set module [lindex $vals(modules) [lindex $selection 0]]
+ $widgets(search_opts) raise $module
+ set result_tab [$widgets(results) raise]
+ if {$result_tab != {} && $tabs($result_tab:module) == $module} {
+ $widgets(update) configure -state normal
+ } else {
+ $widgets(update) configure -state disabled
+ }
+}
+
+proc Apol_Analysis::_analyze {which_button} {
+ variable vals
+ variable widgets
+ variable tabs
+ $widgets(new) configure -state disabled
+ $widgets(update) configure -state disabled
+
+ set m [$widgets(search_opts) raise]
+ set retval [Apol_Progress_Dialog::wait "$vals($m:name) Analysis" \
+ "Performing $vals($m:name) Analysis..." \
+ {
+ if {$which_button == "new"} {
+ ${m}::newAnalysis
+ } else {
+ set f [$widgets(results) getframe [$widgets(results) raise]]
+ if {[set retval [${m}::updateAnalysis $f]] != {}} {
+ _deleteCurrentResults
+ }
+ set retval
+ }
+ }]
+ if {$retval != {}} {
+ tk_messageBox -icon error -type ok -title "$vals($m:name) Analysis" -message "Error while performing analysis:\n\n$retval"
+ }
+ if {[$widgets(results) raise] == {}} {
+ $widgets(update) configure -state disabled
+ } else {
+ $widgets(update) configure -state normal
+ }
+
+ $widgets(new) configure -state normal
+}
+
+proc Apol_Analysis::_reset {} {
+ variable vals
+ variable widgets
+ set m [$widgets(search_opts) raise]
+ ${m}::reset
+}
+
+proc Apol_Analysis::_info {} {
+ variable vals
+ variable widgets
+ set m [$widgets(search_opts) raise]
+ Apol_Widget::showPopupParagraph $vals(${m}:name) [${m}::getInfo]
+}
+
+proc Apol_Analysis::_reinitializeTabs {} {
+ variable widgets
+ variable tabs
+ array set tabs {
+ next_result_id 1
+ }
+ foreach p [$widgets(results) pages 0 end] {
+ _deleteResults $p
+ }
+}
+
+proc Apol_Analysis::_switchTab {pageID} {
+ variable vals
+ variable widgets
+ variable tabs
+
+ $widgets(update) configure -state normal
+ # check if switching to already visible tab
+ if {[$widgets(results) raise] == $pageID} {
+ return
+ }
+ $widgets(results) raise $pageID
+ set cur_search_opts [$widgets(search_opts) raise]
+
+ # restore the tab's search criteria
+ set m $tabs($pageID:module)
+ ${m}::switchTab $tabs($pageID:vals)
+
+ # update the analysis type selection
+ $widgets(modules).lb selection clear 0 end
+ $widgets(modules).lb selection set [lsearch $vals(module_names) $vals(${m}:name)]
+ $widgets(search_opts) raise $m
+}
+
+proc Apol_Analysis::_deleteResults {pageID} {
+ variable widgets
+ variable tabs
+
+ # Remove tab and its widgets
+ set curpos [$widgets(results) index $pageID]
+ $widgets(results) delete $pageID
+ array unset tabs $pageID:*
+ array unset tabs $pageID
+
+ # try to raise the next tab
+ if {[set next_id [$widgets(results) pages $curpos]] != {}} {
+ _switchTab $next_id
+ } elseif {$curpos > 0} {
+ # raise the previous page instead
+ _switchTab [$widgets(results) pages [expr {$curpos - 1}]]
+ } else {
+ # no tabs remaining
+ $widgets(update) configure -state disabled
+ }
+}
+
+proc Apol_Analysis::_deleteCurrentResults {} {
+ variable widgets
+ if {[set curid [$widgets(results) raise]] != {}} {
+ _deleteResults $curid
+ }
+}
+
+proc Apol_Analysis::_displayRenameTabDialog {pageID} {
+ variable widgets
+ variable tabs
+ set d [Dialog .apol_analysis_tab_rename -homogeneous 1 -spacing 2 -cancel 1 \
+ -default 0 -modal local -parent . -place center -separator 1 \
+ -side bottom -title "Rename Results Tab"]
+ $d add -text "OK" -command [list $d enddialog "ok"]
+ $d add -text "Cancel" -command [list $d enddialog "cancel"]
+ set f [$d getframe]
+ set l [label $f.l -text "Tab name:"]
+ set tabs(tab:new_name) [$widgets(results) itemcget $pageID -text]
+ set e [entry $f.e -textvariable Apol_Analysis::tabs(tab:new_name) -width 16 -bg white]
+ pack $l $e -side left -padx 2
+ set retval [$d draw]
+ destroy $d
+ if {$retval == "ok"} {
+ $widgets(results) itemconfigure $pageID -text $tabs(tab:new_name)
+ }
+}
diff --git a/apol/apol.gif b/apol/apol.gif
new file mode 100644
index 0000000..48d74d5
--- /dev/null
+++ b/apol/apol.gif
Binary files differ
diff --git a/apol/apol.png b/apol/apol.png
new file mode 100644
index 0000000..7029175
--- /dev/null
+++ b/apol/apol.png
Binary files differ
diff --git a/apol/apol.xcf b/apol/apol.xcf
new file mode 100644
index 0000000..ea6d26e
--- /dev/null
+++ b/apol/apol.xcf
Binary files differ
diff --git a/apol/apol_help.txt b/apol/apol_help.txt
new file mode 100644
index 0000000..aad309b
--- /dev/null
+++ b/apol/apol_help.txt
@@ -0,0 +1,482 @@
+SELinux Policy Analysis Tool Help File
+
+
+Overview
+--------
+This file contains basic help information for using apol, a graphical
+policy analysis tool for Security Enhanced (SELinux) policies. The
+tool provides the ability to:
+
+ + Examine, search, and relate policy components (types, type
+ attributes, object classes, object permissions, roles, users,
+ initials SIDs, MLS components, network and file system contexts,
+ and booleans), and policy rules (allow, neverallow, auditallow,
+ dontaudit, type_transition, type_change, role allow,
+ role_transition, and range_transition).
+
+ + Create and query an on-disk database that contains SELinux
+ context information about the filesystem.
+
+ + Perform some automated analysis of policies, including forward and
+ reverse domain transition analyses, direct information flow
+ analysis, as well as transitive (indirect) information flow
+ analysis, direct relabel analysis, and type relationship analysis.
+
+The tool supports source, monolithic binary, and modular binary
+policies. Certain apol features may be disabled if the underlying
+policy does not support the action. For example, rule searches will
+not report line numbers when searching monolithic binary polices.
+
+Apol provides compatibility with the current and previous policy
+syntax. It supports analysis of monolithic policy versions 12 to the
+current version 21 and modular policy versions 5 and 6.
+
+See setools/ChangeLog for a list of new features in this release. See
+setools/KNOWN_BUGS for a list of current bugs.
+
+
+Menus
+-----
+Use 'Open' from the File menu to open a valid policy. The policy may
+be monolithic or be composed of a base linked with multiple modules.
+Only one policy can be open at a time; opening a second policy will
+result in the first being closed.
+
+The Query menu allows the user to save or load a query for a TE Rules
+search or for an analysis module listed on the Analysis tab. Saving a
+query writes the appropriate parameters and settings to a '.qf' file:
+for TE Rules queries, the required query parameters are saved; for
+analysis queries, the required query parameters as well as the
+specified advanced settings are saved. When loading a query, apol
+parses the specified query (.qf) file, raises the correct tab and
+configures the query options with the specified query parameters and
+advanced settings. The Load Query menu item is enabled across all
+tabs, but the save query menu item is only enabled when the Analysis
+tab or the TE Rules tab (see the Policy Rules tab description below)
+is raised. Choose 'Policy Summary' from the Query menu to display
+statistics about the currently loaded policy. A shorthand version of
+these statistics is always displayed on the status bar when a policy
+is opened.
+
+Permission mappings are managed through the Tools menu. The mappings
+are used by apol's direct and transitive information flow analyses.
+Mappings may be viewed with the View Perm Map menu item. Although the
+ensuing dialog is not required to perform an information flow
+analysis, the user may fine tune those mappings. See the separate
+help file on information flow for more information about permission
+mappings and their management.
+
+
+Policy Components tabs
+----------------------
+The policy components tabs provide the means to examine, search, and
+relate the core components of an SELinux policy.
+
+ Types tab
+ ---------
+ Use the Types tab to search through types and attributes. Double
+ click or right click on any type or attribute in the list boxes to
+ see full details for that type or attribute. If a file index has
+ been loaded (see File Contexts tab description below), details will
+ include files labeled with that particular type or attribute.
+
+ Use the search options and hit the OK button to perform searches for
+ types. Alternately, use the "Search using regular expression" box
+ to search for types and/or attributes using a POSIX-style regular
+ expression.
+
+ Classes/Perms tab
+ -----------------
+ Use the Classes/Perms tab to view and search object classes, common
+ permissions, and permissions defined in a policy. Double clicking
+ on any name from the three list boxes gives a brief summary of the
+ class, permission, or common permission. Use the search options to
+ view more detailed aspects of classes and permissions.
+
+ For example, to display the objects that use the permission getattr,
+ select "Permissions", and the button "Object Classes" directly below
+ it. Then select "Search using regular expression" and type
+ "^getattr$" in the box. Press OK and a list of object classes that
+ use that permission displays (a * will mean that the class uses that
+ permission via a common permission).
+
+ Regular expressions can be used to constrain the search. For
+ example, to find all the permissions that start with the string
+ "set", use the regular expression "^set".
+
+ Roles tab
+ ----------
+ Use the Roles tab to search roles and their allowed types.
+ Functionality for this tab is essentially the same as the Types tab
+ (e.g., double click on a role for details about that role).
+
+ The primary search option provides the means to find all roles that
+ include a given type.
+
+ Users tab
+ ---------
+ Select the Users tab to search users defined in the policy and to
+ view the roles allowed for that user, the default MLS level and
+ allowed MLS range for users (if a MLS policy is loaded).
+
+ Booleans tab
+ ------------
+ Select the Booleans tab to search the boolean variables defined in
+ the policy, as well as to view the current state and/or policy
+ default state of the variable. This tab also provides the interface
+ to change the state of the boolean variable to TRUE or FALSE. This
+ boolean state change will be applied in memory and but will not
+ change the state within the actual policy.
+
+ MLS tab
+ -------
+ Select the MLS tab to search sensitivities and categories in the
+ policy, as well as to display the level statements for sensitivities
+ and which sensitivites can be associated with a category.
+
+ Initial SIDS tab
+ ----------------
+ Select the Initial SIDS tab to search initial sids defined in the
+ policy, as well as to view the context for each initial sid.
+
+ Net Contexts tab
+ ----------------
+ Select the Net Contexts tab to search network-based contexts
+ (portcon, netifcon, and nodecon statements) defined in the policy.
+
+ FS Contexts tab
+ ---------------
+ Select the FS Contexts tab to search filesystem-based contexts
+ (fs_use_ and genfscon statements) defined in the policy.
+
+
+Policy Rules tabs
+-----------------
+The Policy Rules tabs allow more advanced analysis of an SELinux
+policy. They provide the means to search and select from the many
+rules in a policy based on selected search criteria.
+
+ TE Rules tab
+ ------------
+ Select the TE Rules tab to search through the Type Enforcement
+ rules. This is the most extensively used tab, as well as the most
+ complicated.
+
+ Three different types of search criteria exist for TE Rules:
+
+ 1. RULE SELECTION: provides options to limit the scope of search;
+ only those rules selected will be included in the search. At
+ least one must be selected. NOTE: If no additional search
+ criteria is specified, apol will search for all of the selected
+ rules.
+
+ 2. TYPE/ATTRIBUTES SUBTAB: provides options to refine a search
+ based on types and/or type attributes used by a rule. There
+ are three general type search options: source, target, and
+ default. Default is useful only if one or more of type
+ transition/member/change rules are selected; other rules do not
+ use the default field. The source field also can be used as an
+ "any" field. In this case, the other two options will not be
+ available, and the search will look for the selected
+ type/attribute in any field of the selected rules.
+
+ Use drop down boxes to select a type or attribute. If the
+ "Search using regular expression" box is checked, enter a
+ regular expression in any type/attrib box. If regular
+ expressions are disabled, apol currently supports only one
+ type/attribute in each box. This type/attrib must be a
+ complete, valid type or attrib string. The Default field can
+ only be a type (not an attribute).
+
+ If the "Search only enabled rules" checkbox is selected, query
+ results will include all rules that meet the search criteria,
+ EXCLUDING any rules that have been disbled by a conditional
+ expression. If the checkbox is not selected, query results
+ will include all rules that meet the search criteria, INCLUDING
+ those rules that have been disabled by a conditional
+ expression.
+
+ Typically a search for a particular type also returns rules
+ that employ any of that type's attributes. Likewise, a search
+ for an attribute returns rules that use any of that attribute's
+ types. This "indirect" searching is enabled by default. The
+ "Only direct matches" checkbox alters the meaning of the search
+ field such that it performs literal searches upon the
+ identifier.
+
+ 3. CLASSES/PERMISSIONS SUBTAB: provides options to refine a search
+ using object classes and/or permissions. Only rules that
+ contain the selected object classes and selected permissions
+ will be returned. Each of these boxes allow multiple
+ selections. In the case of multiple select, apol treats them
+ using an "or" semantic (e.g., if two object classes, such as
+ 'dir' and 'file', are selected, rules that apply to file OR
+ directory object classes are selected).
+
+ This tab also includes a section for AV Rule Permissions, as a
+ means to prune the list of permissions based on the object
+ classes selected. However, if none of the AV rules have been
+ selected the permissions section will be disabled. If "All for
+ selected classes" is selected, only permissions related to
+ selected objects are shown. "Common to selected classes"
+ instead only shows permissions that all selected classes have.
+ Below is a checkbox that changes permission matching behavior.
+ If more than one permission is selected, the default behavior
+ is to return rules that contain any of those selections. When
+ the checkbox is enabled, returned rules instead will contain
+ all of them.
+
+ In the Results Tab for a given search, all rules that meet the
+ search criteria are displayed. In addition, if the policy that is
+ opened is capable of showing line numbers, a hyperlink for each rule
+ is shown. Clicking on this link will raise the Policy Source tab
+ and highlight the exact line in the source file where the rule was
+ found. This traces the rule back to the ultimate source code. If
+ the policy cannot show line numbers then there will be no
+ hyperlinks.
+
+ The TE Rules Tab also supports multiple results windows. Each
+ active window remembers the search options used for it, and will set
+ all the options accordingly when selected. Use the "Update Search"
+ button to change the results displayed for the current window based
+ on the current search option. "New Search" creates a new results
+ window based on the current search options. Use the "Close Tab" bar
+ at the bottom to destroy a results window. Also, the TE Rules tab
+ provides the means to save/load search criteria to a file (see Menus
+ section above).
+
+ Conditional Expressions tab
+ ---------------------------
+ Select the Conditional Expressions tab to search conditional
+ expressions within the policy, as well as to view the rules within
+ these conditional expressions. Note that conditional expressions
+ are displayed in Reverse Polish Notation.
+
+ By default, all conditionals are displayed; however they can be
+ limited to expressions that use particular boolean variables. The
+ current state of each rule is provided by means of a tag within the
+ results:
+
+ [Enabled] - indicates the rule is enabled
+ [Disabled] - indicates the rule is disabled
+
+ RBAC Rules tab
+ --------------
+ Select the RBAC Rules tab to search role-based access control rules.
+ It is similar in nature to the TE Rules tab, but somewhat simpler.
+ It supports searches of both role allow and role_transition rules.
+
+ As with TE Rules, the Source role can also be used in an "any"
+ search.
+
+ Range Transition Rules tab
+ --------------------------
+ Select the Range Transition Rules tab to search to search
+ range_transition rules by source and target types and by the MLS
+ range. There are three options when searching for ranges; find
+ exact matches to the entered range, find rules that have ranges
+ that contain the entered range, or find rules that have ranges
+ within the entered range.
+
+
+File Contexts tab
+-----------------
+The File Contexts tab is only available if apol has been built with
+libselinux support (see the setools INSTALL file for details on
+building apol with/without libselinux support). The tab provides the
+following features:
+
+ Creating/Loading an Index File
+ ------------------------------
+ An index file is an on-disk database that contains SELinux context
+ information about the filesystem, including SELinux users and types
+ associated with file paths and object classes. This tab provides
+ the option of creating an index file or loading an existing one. If
+ an index file is not loaded, all search items will be grayed out and
+ a red label indicating that an index file is not loaded is displayed
+ at the top. Buttons are presented for creating and loading an index
+ file. Selecting the 'Load' button displays a file selection dialog
+ for choosing saved index file to load. Selecting the 'Create and
+ Load' button will display a dialog to specify the save file and the
+ directory from which to start the indexing. Here, add multiple
+ directories from which to index by using the 'Add' button or simply
+ input a colon-delimited list of directory path strings within the
+ entrybox. Upon selecting the 'Create' button, an index file will be
+ created and then loaded into apol.
+
+ Searching an Index File
+ -----------------------
+ Searches on the index file can be done by specifying the user, type,
+ object class, or path search criteria to search for using the
+ widgets provided. Drop down lists and entryboxes are presented for
+ specifying the search criteria, of which the drop down lists contain
+ items from the index file. Regular expressions can be specified for
+ all fields except the object class field. To perform a search,
+ click the 'OK' button. Once the search is finished, list of files
+ that matched the criteria displays, along with the files' context
+ and/or object type, if specified.
+
+
+Analysis tab
+------------
+The Analysis tab provides automated analysis capabilities. The "Info"
+button provides a description for the selected analysis type. Also,
+this tab supports saving/loading any query criteria to a file (see
+Menus section above).
+
+ Domain Transition Analysis
+ --------------------------
+ Use the Domain Transition analysis module to specify a transition
+ direction for the analysis. The 2 directions provided are:
+
+ FORWARD: The Forward Domain Transition (FDT) analysis takes a
+ starting SOURCE domain and presents a tree of all the
+ resulting TARGET domains that can be transitioned into
+ from that starting domain. The tree can be walked to
+ follow the FDT tree to any depth. The only restriction
+ is that a subtree will not expand if its parent is the
+ same as the node. Each node in the FDT tree represents
+ a TARGET domain to which the parent domain can directly
+ transition.
+
+ The Forward Domain Transition (FDT) analysis also
+ provides the means to limit the query to find
+ transitions only to domains that are granted specific
+ object class permissions and/or are granted access to a
+ particular object type(s). Use the 'Access Filters'
+ dialog to select object types object classes, and
+ permissions in order to limit the query to this
+ constrained analysis. By default, all object types,
+ object classes and permissions are included in the
+ query. Selecting an object class from the listbox
+ widget will display all permissions for that object
+ class.
+
+ A specific example where this advanced feature would be
+ useful is when one is seeking to find transitions from
+ 'user_t' to domains with write access to files in the
+ 'shadow_t' domain. In this case:
+
+ - Specify 'user_t' as the source domain.
+ - Using the Access Filters dialog, select the
+ 'shadow_t' object type, 'file' object class, and
+ 'write' permission.
+
+ REVERSE: As its name implies, the Reverse Domain Transition
+ (RDT) analysis is the reverse of the FDT analysis. The
+ RDT takes a starting TARGET domain and presents a tree
+ of all the resulting SOURCE domains that can directly
+ transition to that TARGET domain. The tree can be
+ walked to follow the RDT tree to any depth. The only
+ restriction is that a subtree will not expand if its
+ parent is the same as the node. Each node in the RDT
+ tree represents a SOURCE domain that can transition to
+ its parent node. This analysis does not provide the
+ meands to constrain the query using the 'Access
+ Filters' dialog, as is possible in Forward Domain
+ Transition analysis.
+
+ Selecting a child node will show all the rules that permit the
+ transition to occur. In the case of a Forward Domain Transition
+ analysis, access granted to this target domain will also be appended
+ to the results.
+
+ See the separate help file for an overview of the criteria that
+ constitute a valid domain transition.
+
+ Direct Information Flow Analysis
+ --------------------------------
+ The Direct Information Flow (DIF) analysis takes a starting type and
+ an information flow direction (IN, OUT, EITHER, or BOTH), and
+ presents a tree with the starting type as the root node. The child
+ nodes represent other types in the policy where information flow can
+ occur DIRECTLY between its parent node and itself. If the flow
+ direction is IN, information in the child node types can flow to the
+ parent node type. If the flow direction is OUT, information in the
+ parent node can DIRECTLY flow to the child node. If the direction
+ is BOTH, information can flow from child to parent and from parent
+ to child. If EITHER is selected, flow direction will be IN, OUT, or
+ BOTH.
+
+ Selecting a child node will show all the rules that permit the
+ information flow to occur. Results are sorted by object class.
+
+ Results can be filtered by selecting one or more object classes.
+ This will ensure that only those flows that are allowed for the
+ selected object class will be shown (e.g., selecting file will
+ prevent flows allowed for sockets from being presented). Use a
+ regular expression to limit the results by end type. Only those end
+ types that match the provided regular expression will be presented.
+
+ See the separate help file on information flow for more information
+ about direct information flow.
+
+ Transitive Information Flow Analysis
+ ------------------------------------
+ Whereas the DIF analysis identifies information flows that are
+ directly allowed by one or more explicit rule, the Transitive
+ Information Flow (TIF) analysis attempts a much more extensive
+ analysis. Specifically the TIF identifies indirect paths between
+ two types. Since such paths can be circuitous or over many hops,
+ this analysis is quite difficult to achieve.
+
+ TIF takes a starting type and an information flow direction (To or
+ From) and presents a tree with the starting type as the root node.
+ The child nodes represent other types in the policy where
+ information flow can occur (directly or transitively) between the
+ parent node and itself. If the flow direction is To, the
+ information flow is to the parent node. If the flow direction is
+ From, the information flow is to the child node.
+
+ Selecting a child node shows each step in the flow chain between the
+ starting node and the child node, along with the rules that allow
+ that step to occur. Additionally, embedded in the text of the
+ results is a hyperlink for finding more flows between the starting
+ node and the selected child node. This link displays a dialog to
+ specify a time limit for the search and/or limit the number of flows
+ to find in the search.
+
+ As with the DIF analysis, results can be filtered using end type
+ regular expression.
+
+ Additionally, the TIF analysis provides the Advanced Filters dialog
+ for filtering results by object class permissions and/or types.
+ Selecting an object class in the Advanced Filters dialog will
+ display a list of permissions for that object class, whereby certain
+ permissions can be included or excluded. By default, all
+ permissions for an object class are included in the query, unless a
+ permission's 'Exclude' radiobutton is selected. Configuring all
+ permissions for an object class to be excluded will exclude the
+ object class itself from the query. When an object class becomes
+ excluded, its label will change to indicate that the object class is
+ to be excluded from the analysis query.
+
+ Additionally, the Advanced Filters dialog displays the weight value
+ of a permission, as specified in the loaded permission map. See the
+ separate help file on information flow for more information about
+ managing permission mappings. Specify a weight threshold in order
+ to exclude permissions from the results that have weights below a
+ certain threshold. Query results can also be filtered by including
+ or excluding intermediate types.
+
+ See the separate help file on information flow for more information
+ about transitive information flow.
+
+ Direct Relabel Analysis
+ -----------------------
+ See the separate help file on direct file relabel analysis, which can
+ be accessed from the help menu in apol.
+
+ Types Relationship Summary Analysis
+ -----------------------------------
+ See the separate help file on types relationship summary analysis,
+ which can be accessed from the help menu in apol.
+
+
+Policy Source tab
+-----------------
+The Policy Source tab provides a convenient display of the raw policy
+source file. If a modular policy was loaded, this tab shows only the
+base policy's source. Various search results will hyperlink to lines
+within this tab. If the loaded policy is not source then this tab
+will be disabled.
diff --git a/apol/apol_tcl.cc b/apol/apol_tcl.cc
new file mode 100644
index 0000000..0894b5c
--- /dev/null
+++ b/apol/apol_tcl.cc
@@ -0,0 +1,142 @@
+/**
+ * @file
+ *
+ * Support routines for the apol program that are faster/easier when
+ * written in C than in Tcl.
+ *
+ * @author Jeremy A. Mowery jmowery@tresys.com
+ * @author Jason Tang jtang@tresys.com
+ *
+ * Copyright (C) 2006-2007 Tresys Technology, LLC
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tcl.h>
+
+#include <apol/policy.h>
+#include <sefs/db.hh>
+#include <sefs/filesystem.hh>
+
+/** severity of most recent message */
+int msg_level = INT_MAX;
+
+/** pointer to most recent message string */
+char *message = NULL;
+
+/**
+ * Take the formated string, allocate space for it, and then write it
+ * the policy's msg_callback_arg. If there is already a string
+ * stored, then append to the string if the message level is equal to
+ * the previous one, overwrite the string if message level is less
+ * than previous, else ignore the message.
+ */
+static void apol_tcl_common_route(void *arg, int level, const char *fmt, va_list ap)
+{
+ char *s, *t;
+ Tcl_Interp *interp = static_cast < Tcl_Interp * >(arg);
+ if (level == APOL_MSG_INFO && msg_level >= APOL_MSG_INFO)
+ {
+ /* generate an info event */
+ free(message);
+ message = NULL;
+ if (vasprintf(&s, fmt, ap) < 0)
+ {
+ fprintf(stderr, "%s\n", strerror(errno));
+ return;
+ }
+ message = s;
+ msg_level = level;
+ Tcl_Eval(interp, "Apol_Progress_Dialog::_update_message");
+ while (Tcl_DoOneEvent(TCL_IDLE_EVENTS | TCL_DONT_WAIT)) ;
+ }
+ else if (message == NULL || level < msg_level)
+ {
+ /* overwrite the existing stored message string with a
+ * new, higher priority message */
+ free(message);
+ message = NULL;
+ if (vasprintf(&s, fmt, ap) < 0)
+ {
+ fprintf(stderr, "%s\n", strerror(errno));
+ return;
+ }
+ message = s;
+ msg_level = level;
+ }
+ else if (level == msg_level)
+ {
+ /* append to existing error message */
+ if (vasprintf(&s, fmt, ap) < 0)
+ {
+ fprintf(stderr, "%s\n", strerror(errno));
+ return;
+ }
+ if (asprintf(&t, "%s\n%s", message, s) < 0)
+ {
+ free(s);
+ fprintf(stderr, "%s\n", strerror(errno));
+ return;
+ }
+ free(s);
+ free(message);
+ message = t;
+ }
+}
+
+void apol_tcl_clear_info_string(void)
+{
+ if (message != NULL)
+ {
+ free(message);
+ message = NULL;
+ }
+ msg_level = INT_MAX;
+}
+
+void apol_tcl_route_apol_to_string(void *arg, const apol_policy_t * p
+ __attribute__ ((unused)), int level, const char *fmt, va_list ap)
+{
+ apol_tcl_common_route(arg, level, fmt, ap);
+}
+
+void apol_tcl_route_sefs_to_string(void *arg, const sefs_fclist * s
+ __attribute__ ((unused)), int level, const char *fmt, va_list ap)
+{
+ apol_tcl_common_route(arg, level, fmt, ap);
+}
+
+int apol_tcl_get_info_level(void)
+{
+ return msg_level;
+}
+
+char *apol_tcl_get_info_string(void)
+{
+ return message;
+}
+
+void apol_tcl_set_info_string(apol_policy_t * p, const char *s)
+{
+ INFO(p, "%s", s);
+}
diff --git a/apol/apol_tcl.i b/apol/apol_tcl.i
new file mode 100644
index 0000000..973c859
--- /dev/null
+++ b/apol/apol_tcl.i
@@ -0,0 +1,451 @@
+/**
+ * @file
+ *
+ * Support routines for the apol program that are faster/easier when
+ * written in C than in Tcl.
+ *
+ * @author Jeremy A. Mowery jmowery@tresys.com
+ * @author Jason Tang jtang@tresys.com
+ *
+ * Copyright (C) 2006-2007 Tresys Technology, LLC
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+%module apol_tcl
+%import sefs.i
+%import apol.i
+%import qpol.i
+
+%{
+#include <config.h>
+
+#include <apol/avrule-query.h>
+#include <apol/terule-query.h>
+#include <apol/policy.h>
+#include <apol/policy-path.h>
+#include <apol/util.h>
+#include <sefs/db.hh>
+#include <sefs/filesystem.hh>
+#include <sefs/fcfile.hh>
+%}
+
+%{
+/* Note that these must be placed in a different file rather than
+ * being inlined directly into this SWIG interface file. The reason
+ * is because they use some GNU functions that are only available when
+ * config.h is included prior to stdio.h. Unfortunately, SWIG will
+ * always place its own headers, which includes stdio.h, prior to any
+ * inlined headers when generating the wrapped C file. As a result,
+ * those GNU functions would not be available to the inlined
+ * functions.
+ */
+extern void apol_tcl_clear_info_string(void);
+extern int apol_tcl_get_info_level(void);
+extern char *apol_tcl_get_info_string(void);
+extern void apol_tcl_set_info_string(apol_policy_t *p, const char *s);
+extern void apol_tcl_route_apol_to_string(void *arg, const apol_policy_t * p, int level, const char *fmt, va_list ap);
+extern void apol_tcl_route_sefs_to_string(void *arg, const sefs_fclist * s, int level, const char *fmt, va_list ap);
+extern int msg_level;
+extern char *message;
+
+static void tcl_clear_error(void)
+{
+ apol_tcl_clear_info_string();
+}
+static void tcl_throw_error(const char *s)
+{
+ free(message);
+ message = strdup(s);
+}
+static char *tcl_get_error(void)
+{
+ if (msg_level != APOL_MSG_ERR) {
+ return NULL;
+ }
+ return apol_tcl_get_info_string();
+}
+#undef SWIG_exception
+#define SWIG_exception(code, msg) {tcl_throw_error(msg); goto fail;}
+%}
+
+/* Major hackery here to pass in the Tcl interpreter object as
+ * apol_policy_create_from_policy_path()'s callback argument. This is
+ * needed so that the callback can properly update apol's progress
+ * dialog without deadlocking itself.
+ */
+%newobject apol_tcl_open_policy(const apol_policy_path_t *, Tcl_Interp *);
+%typemap (in) (const apol_policy_path_t *ppath, Tcl_Interp *interp) {
+ int res = SWIG_ConvertPtr($input, SWIG_as_voidptrptr(&$1), $1_descriptor, 0);
+ if (res) {
+ SWIG_exception_fail(SWIG_ArgError(res), "in method '" "apol_tcl_open_policy" "', argument " "1"" of type '" "apol_policy_path_t const *""'");
+ }
+ $2 = interp;
+};
+%inline %{
+ /**
+ * Open a policy file, either source or binary, on disk. Note
+ * that this will not load neverallows; apol must rebuild
+ * neverallows (and call qpol_policy_build_syn_rule_table())
+ * when it needs to. If the file was opened successfully then
+ * allocate and return an apol_policy_t object. Otherwise
+ * throw an error and return a string that describes the
+ * error.
+ *
+ * @param ppath apol_policy_path object representing policy to
+ * open.
+ */
+ apol_policy_t *apol_tcl_open_policy(const apol_policy_path_t *ppath, Tcl_Interp *interp) {
+ apol_policy_t *p = apol_policy_create_from_policy_path(ppath, QPOL_POLICY_OPTION_NO_NEVERALLOWS,
+ apol_tcl_route_apol_to_string, interp);
+ if (p == NULL && message == NULL) { // Assume lower level has generated error message
+ if (errno != 0) { // otherwise take a guess at it
+ SWIG_exception(SWIG_RuntimeError, strerror(errno));
+ } else {
+ SWIG_exception(SWIG_RuntimeError, "The selected file does not appear to be a valid SELinux Policy.");
+ }
+ }
+ fail:
+ return p;
+ }
+
+ static int avrule_sort(const void *a, const void *b, void *arg) {
+ const qpol_avrule_t *r1 = static_cast<const qpol_avrule_t *>(a);
+ const qpol_avrule_t *r2 = static_cast<const qpol_avrule_t *>(b);
+ apol_policy_t *p = static_cast<apol_policy_t *>(arg);
+ qpol_policy_t *q = apol_policy_get_qpol(p);
+
+ uint32_t rule_type1, rule_type2;
+ const char *cs1, *cs2;
+ int compval;
+ if (qpol_avrule_get_rule_type(q, r1, &rule_type1) < 0 ||
+ qpol_avrule_get_rule_type(q, r2, &rule_type2) < 0) {
+ return 0;
+ }
+ if ((cs1 = apol_rule_type_to_str(rule_type1)) == NULL ||
+ (cs2 = apol_rule_type_to_str(rule_type2)) == NULL) {
+ return 0;
+ }
+ if ((compval = strcmp(cs1, cs2)) != 0) {
+ return compval;
+ }
+
+ const qpol_type_t *t1, *t2;
+ const char *s1, *s2;
+ if (qpol_avrule_get_source_type(q, r1, &t1) < 0 ||
+ qpol_avrule_get_source_type(q, r2, &t2) < 0) {
+ return 0;
+ }
+ if (qpol_type_get_name(q, t1, &s1) < 0 ||
+ qpol_type_get_name(q, t2, &s2) < 0) {
+ return 0;
+ }
+ if ((compval = strcmp(s1, s2)) != 0) {
+ return compval;
+ }
+
+ if (qpol_avrule_get_target_type(q, r1, &t1) < 0 ||
+ qpol_avrule_get_target_type(q, r2, &t2) < 0) {
+ return 0;
+ }
+ if (qpol_type_get_name(q, t1, &s1) < 0 ||
+ qpol_type_get_name(q, t2, &s2) < 0) {
+ return 0;
+ }
+ if ((compval = strcmp(s1, s2)) != 0) {
+ return compval;
+ }
+
+ const qpol_class_t *c1, *c2;
+ if (qpol_avrule_get_object_class(q, r1, &c1) < 0 ||
+ qpol_avrule_get_object_class(q, r2, &c2) < 0) {
+ return 0;
+ }
+ if (qpol_class_get_name(q, c1, &s1) < 0 ||
+ qpol_class_get_name(q, c2, &s2) < 0) {
+ return 0;
+ }
+ return strcmp(s1, s2);
+ }
+
+ /**
+ * Sort a vector of qpol_avrule_t, sorting by rule type, then
+ * source type, then target type, and then by object class.
+ */
+ void apol_tcl_avrule_sort(apol_policy_t *policy, apol_vector_t *v) {
+ if (policy != NULL && v != NULL) {
+ apol_vector_sort(v, avrule_sort, policy);
+ }
+ }
+
+ static int terule_sort(const void *a, const void *b, void *arg) {
+ const qpol_terule_t *r1 = static_cast<const qpol_terule_t *>(a);
+ const qpol_terule_t *r2 = static_cast<const qpol_terule_t *>(b);
+ apol_policy_t *p = static_cast<apol_policy_t *>(arg);
+ qpol_policy_t *q = apol_policy_get_qpol(p);
+
+ uint32_t rule_type1, rule_type2;
+ const char *cs1, *cs2;
+ int compval;
+ if (qpol_terule_get_rule_type(q, r1, &rule_type1) < 0 ||
+ qpol_terule_get_rule_type(q, r2, &rule_type2) < 0) {
+ return 0;
+ }
+ if ((cs1 = apol_rule_type_to_str(rule_type1)) == NULL ||
+ (cs2 = apol_rule_type_to_str(rule_type2)) == NULL) {
+ return 0;
+ }
+ if ((compval = strcmp(cs1, cs2)) != 0) {
+ return compval;
+ }
+
+ const qpol_type_t *t1, *t2;
+ const char *s1, *s2;
+ if (qpol_terule_get_source_type(q, r1, &t1) < 0 ||
+ qpol_terule_get_source_type(q, r2, &t2) < 0) {
+ return 0;
+ }
+ if (qpol_type_get_name(q, t1, &s1) < 0 ||
+ qpol_type_get_name(q, t2, &s2) < 0) {
+ return 0;
+ }
+ if ((compval = strcmp(s1, s2)) != 0) {
+ return compval;
+ }
+
+ if (qpol_terule_get_target_type(q, r1, &t1) < 0 ||
+ qpol_terule_get_target_type(q, r2, &t2) < 0) {
+ return 0;
+ }
+ if (qpol_type_get_name(q, t1, &s1) < 0 ||
+ qpol_type_get_name(q, t2, &s2) < 0) {
+ return 0;
+ }
+ if ((compval = strcmp(s1, s2)) != 0) {
+ return compval;
+ }
+
+ const qpol_class_t *c1, *c2;
+ if (qpol_terule_get_object_class(q, r1, &c1) < 0 ||
+ qpol_terule_get_object_class(q, r2, &c2) < 0) {
+ return 0;
+ }
+ if (qpol_class_get_name(q, c1, &s1) < 0 ||
+ qpol_class_get_name(q, c2, &s2) < 0) {
+ return 0;
+ }
+ return strcmp(s1, s2);
+ }
+
+ /**
+ * Sort a vector of qpol_terule_t, sorting by rule type, then
+ * source type, then target type, and then by object class.
+ */
+ void apol_tcl_terule_sort(apol_policy_t *policy, apol_vector_t *v) {
+ if (policy != NULL && v != NULL) {
+ apol_vector_sort(v, terule_sort, policy);
+ }
+ }
+
+ /**
+ * Returns the policy version number for the currently opened
+ * policy. If the policy is modular, return the maximum
+ * allowed policy as per libsepol.
+ */
+ unsigned int apol_tcl_get_policy_version(apol_policy_t *policy) {
+ if (policy == NULL) {
+ SWIG_exception(SWIG_RuntimeError, "No policy opened");
+ }
+ if (apol_policy_get_policy_type(policy) != QPOL_POLICY_MODULE_BINARY) {
+ unsigned int version;
+ if (qpol_policy_get_policy_version(apol_policy_get_qpol(policy), &version) < 0) {
+ SWIG_exception(SWIG_RuntimeError, "Could not get policy version");
+ }
+ return version;
+ } else {
+ return (unsigned int) SEPOL_POLICY_VERSION_MAX;
+ }
+ fail:
+ return 0;
+ }
+
+ char *apol_tcl_get_error_string(void) {
+ return tcl_get_error();
+ }
+%}
+
+%rename(apol_tcl_rule_render) apol_tcl_avrule_render;
+%rename(apol_tcl_rule_render) apol_tcl_terule_render;
+%rename(apol_tcl_rule_render) apol_tcl_syn_avrule_render;
+%rename(apol_tcl_rule_render) apol_tcl_syn_terule_render;
+
+/* Because this SWIG file will be written as C++, it expects all
+ * %newobject objects to be allocated via new and destructed with
+ * delete. However, the libapol render functions use malloc()/free()
+ * as that they come from C. Therefore, use an intermediate function
+ * to create a new string from the malloc() copy.
+ */
+%{
+ static char *apol_tcl_malloc_to_new(char *s) {
+ if (s == NULL) {
+ return new char[0];
+ }
+ char *t = new char[strlen(s) + 1];
+ strcpy(t, s);
+ free(s);
+ return t;
+ }
+ char *apol_tcl_avrule_render(apol_policy_t *policy, qpol_avrule_t *rule) {
+ return apol_tcl_malloc_to_new(apol_avrule_render(policy, rule));
+ }
+ char *apol_tcl_terule_render(apol_policy_t *policy, qpol_terule_t *rule) {
+ return apol_tcl_malloc_to_new(apol_terule_render(policy, rule));
+ }
+ char *apol_tcl_syn_avrule_render(apol_policy_t *policy, qpol_syn_avrule_t *rule) {
+ return apol_tcl_malloc_to_new(apol_syn_avrule_render(policy, rule));
+ }
+
+ char *apol_tcl_syn_terule_render(apol_policy_t *policy, qpol_syn_terule_t *rule) {
+ return apol_tcl_malloc_to_new(apol_syn_terule_render(policy, rule));
+ }
+%}
+%newobject apol_tcl_avrule_render(apol_policy_t *policy, qpol_avrule_t *rule);
+char *apol_tcl_avrule_render(apol_policy_t *policy, qpol_avrule_t *rule);
+%newobject apol_tcl_terule_render(apol_policy_t *policy, qpol_terule_t *rule);
+char *apol_tcl_terule_render(apol_policy_t *policy, qpol_terule_t *rule);
+%newobject apol_tcl_syn_avrule_render(apol_policy_t *policy, qpol_syn_avrule_t *rule);
+char *apol_tcl_syn_avrule_render(apol_policy_t *policy, qpol_syn_avrule_t *rule);
+%newobject apol_tcl_syn_terule_render(apol_policy_t *policy, qpol_syn_terule_t *rule);
+char *apol_tcl_syn_terule_render(apol_policy_t *policy, qpol_syn_terule_t *rule);
+
+
+void apol_tcl_avrule_sort(apol_policy_t *policy, apol_vector_t *v);
+void apol_tcl_terule_sort(apol_policy_t *policy, apol_vector_t *v);
+unsigned int apol_tcl_get_policy_version(apol_policy_t *policy);
+char *apol_tcl_get_error_string(void);
+
+%{
+ /**
+ * Open a sefs database from file.
+ *
+ * @param filename Database's filename.
+ */
+ sefs_db *apol_tcl_open_database(const char * filename, Tcl_Interp * interp)
+ {
+ try {
+ return new sefs_db(filename, apol_tcl_route_sefs_to_string, interp);
+ }
+ catch (...) {
+ return NULL;
+ }
+ }
+
+ /**
+ * Construct an in-memory database from part of a filesystem.
+ *
+ * @param filename Starting root directory.
+ */
+ sefs_db *apol_tcl_open_database_from_dir(const char * filename, Tcl_Interp * interp)
+ {
+ sefs_filesystem *fs = NULL;
+ sefs_db *db = NULL;
+ try {
+ fs = new sefs_filesystem(filename, apol_tcl_route_sefs_to_string, interp);
+ db = new sefs_db(fs, apol_tcl_route_sefs_to_string, interp);
+ }
+ catch (...) {
+ delete fs;
+ delete db;
+ return NULL;
+ }
+ delete fs;
+ return db;
+ }
+
+ struct apol_tcl_query_data {
+ Tcl_Interp *interp;
+ size_t matches;
+ };
+
+ static int apol_tcl_query_callback(sefs_fclist *fclist, const sefs_entry *entry, void *arg) {
+ struct apol_tcl_query_data *a = static_cast<struct apol_tcl_query_data *>(arg);
+ Tcl_Interp *interp = a->interp;
+ Tcl_Obj *cmd[2];
+ cmd[0] = Tcl_NewStringObj("Apol_File_Contexts::_search_callback", -1);
+ cmd[1] = SWIG_NewInstanceObj(SWIG_as_voidptr(entry), SWIGTYPE_p_sefs_entry, 0);
+ Tcl_EvalObjv(interp, 2, cmd, 0);
+ int retval = static_cast<int>(++(a->matches));
+ if (retval % 1000 == 0) {
+ SEFS_INFO(fclist, "Found %d results", retval);
+ }
+ return retval;
+ }
+
+ int apol_tcl_query_database(sefs_fclist *fclist, sefs_query *query, Tcl_Interp * interp)
+ {
+ struct apol_tcl_query_data a = {interp, 0};
+ int retval = fclist->runQueryMap(query, apol_tcl_query_callback, &a);
+ if (retval >= 0) {
+ tcl_clear_error();
+ }
+ return retval;
+ }
+
+ /**
+ * Include this function to force the generated SWIG wrapper
+ * to also include the code to convert from a Tcl object to a
+ * sefs_entry pointer; that code is used by
+ * apol_tcl_query_callback().
+ */
+ void apol_tcl_entry_do_nothing(sefs_entry *e) {
+ }
+%}
+
+
+/* Major hackery here to pass in the Tcl interpreter object as
+ * sefs_db's callback argument. This is needed so that the callback
+ * can properly update apol's progress dialog without deadlocking
+ * itself.
+ */
+%typemap (in) (const char * filename, Tcl_Interp *interp) {
+ $1 = Tcl_GetString($input);
+ $2 = interp;
+};
+/* More hackery to have a callback function for running queries
+ * against a sefs_db.
+ */
+%typemap (in) (sefs_query * query, Tcl_Interp *interp) {
+ int res = SWIG_ConvertPtr($input, SWIG_as_voidptrptr(&$1), $1_descriptor, 0);
+ if (res) {
+ SWIG_exception_fail(SWIG_ArgError(res), "in method '" "apol_tcl_query_database" "', argument " "1"" of type '" "sefs_query *""'");
+ }
+ $2 = interp;
+};
+sefs_db *apol_tcl_open_database(const char * filename, Tcl_Interp * interp);
+sefs_db *apol_tcl_open_database_from_dir(const char * filename, Tcl_Interp * interp);
+%newobject apol_tcl_open_database(const char*, Tcl_Interp*);
+%newobject apol_tcl_open_database_from_dir(const char*, Tcl_Interp*);
+int apol_tcl_query_database(sefs_fclist *fclist, sefs_query *query, Tcl_Interp * interp) throw (std::invalid_argument, std::runtime_error);
+void apol_tcl_entry_do_nothing(sefs_entry *e);
+
+// disable the exception handler, otherwise it will delete the error
+// message when this function gets called
+%exception;
+extern void apol_tcl_clear_info_string(void);
+extern int apol_tcl_get_info_level(void);
+extern char *apol_tcl_get_info_string(void);
+extern void apol_tcl_set_info_string(apol_policy_t *p, const char *s);
+
+// vim:ft=c noexpandtab
diff --git a/apol/classes_perms_tab.tcl b/apol/classes_perms_tab.tcl
new file mode 100644
index 0000000..ab9c4d7
--- /dev/null
+++ b/apol/classes_perms_tab.tcl
@@ -0,0 +1,484 @@
+# Copyright (C) 2001-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
+
+namespace eval Apol_Class_Perms {
+ variable class_list {}
+ variable common_list {}
+ variable perms_list {}
+ variable opts
+ variable widgets
+}
+
+proc Apol_Class_Perms::create {tab_name nb} {
+ variable opts
+ variable widgets
+
+ _initializeVars
+
+ set frame [$nb insert end $tab_name -text "Classes/Perms"]
+
+ set pw1 [PanedWindow $frame.pw -side top]
+ set left_pane [$pw1 add -weight 0]
+ set center_pane [$pw1 add -weight 1]
+ set class_pane [frame $left_pane.class]
+ set common_pane [frame $left_pane.common]
+ set perms_pane [frame $left_pane.perms]
+
+ set classes_box [TitleFrame $class_pane.tbox -text "Object Classes"]
+ set common_box [TitleFrame $common_pane.tbox -text "Common Permissions"]
+ set perms_box [TitleFrame $perms_pane.tbox -text "Permissions"]
+ set options_box [TitleFrame $center_pane.obox -text "Search Options"]
+ set results_box [TitleFrame $center_pane.rbox -text "Search Results"]
+ pack $classes_box -fill both -expand yes
+ pack $common_box -fill both -expand yes
+ pack $perms_box -fill both -expand yes
+ pack $options_box -padx 2 -fill both -expand 0
+ pack $results_box -padx 2 -fill both -expand yes
+ pack $pw1 -fill both -expand yes
+ pack $class_pane $common_pane -expand 0 -fill both
+ pack $perms_pane -expand 1 -fill both
+
+ # Object Classes listbox
+ set class_listbox [Apol_Widget::makeScrolledListbox [$classes_box getframe].lb -height 8 -width 20 -listvar Apol_Class_Perms::class_list]
+ Apol_Widget::setListboxCallbacks $class_listbox \
+ {{"Display Object Class Info" {Apol_Class_Perms::_popupInfo class}}}
+ pack $class_listbox -fill both -expand yes
+
+ # Common Permissions listbox
+ set common_listbox [Apol_Widget::makeScrolledListbox [$common_box getframe].lb -height 5 -width 20 -listvar Apol_Class_Perms::common_perms_list]
+ Apol_Widget::setListboxCallbacks $common_listbox \
+ {{"Display Common Permission Class Info" {Apol_Class_Perms::_popupInfo common}}}
+ pack $common_listbox -fill both -expand yes
+
+ # Permissions listbox
+ set perms_listbox [Apol_Widget::makeScrolledListbox [$perms_box getframe].lb -height 10 -width 20 -listvar Apol_Class_Perms::perms_list]
+ Apol_Widget::setListboxCallbacks $perms_listbox \
+ {{"Display Permission Info" {Apol_Class_Perms::_popupInfo perm}}}
+ pack $perms_listbox -fill both -expand yes
+
+ # Search options section
+ set ofm [$options_box getframe]
+ set classesfm [frame $ofm.classes]
+ set commonsfm [frame $ofm.commons]
+ set permsfm [frame $ofm.perms]
+ pack $classesfm $commonsfm $permsfm -side left -padx 4 -pady 2 -anchor ne
+
+ # First set of checkbuttons
+ set classes [checkbutton $classesfm.classes -text "Object classes" \
+ -variable Apol_Class_Perms::opts(classes:show)]
+ set perms [checkbutton $classesfm.perms -text "Include perms" \
+ -variable Apol_Class_Perms::opts(classes:perms)]
+ set commons [checkbutton $classesfm.commons -text "Expand common perms" \
+ -variable Apol_Class_Perms::opts(classes:commons)]
+ trace add variable Apol_Class_Perms::opts(classes:show) write \
+ [list Apol_Class_Perms::_toggleCheckbuttons $perms $commons]
+ trace add variable Apol_Class_Perms::opts(classes:perms) write \
+ [list Apol_Class_Perms::_toggleCheckbuttons $commons {}]
+ pack $classes -anchor w
+ pack $perms $commons -anchor w -padx 8
+
+ # Second set of checkbuttons
+ set commons [checkbutton $commonsfm.commons -text "Common permissions" \
+ -variable Apol_Class_Perms::opts(commons:show)]
+ set perms [checkbutton $commonsfm.perms2 -text "Include perms" \
+ -variable Apol_Class_Perms::opts(commons:perms) \
+ -state disabled]
+ set classes [checkbutton $commonsfm.classes -text "Object classes" \
+ -variable Apol_Class_Perms::opts(commons:classes) \
+ -state disabled]
+ trace add variable Apol_Class_Perms::opts(commons:show) write \
+ [list Apol_Class_Perms::_toggleCheckbuttons $perms $classes]
+ pack $commons -anchor w
+ pack $perms $classes -anchor w -padx 8
+
+ # Third set of checkbuttons
+ set perms [checkbutton $permsfm.prems -text "Permissions" \
+ -variable Apol_Class_Perms::opts(perms:show)]
+ set classes [checkbutton $permsfm.classes -text "Object classes" \
+ -variable Apol_Class_Perms::opts(perms:classes) \
+ -state disabled]
+ set commons [checkbutton $permsfm.commons -text "Common perms" \
+ -variable Apol_Class_Perms::opts(perms:commons) \
+ -state disabled]
+ trace add variable Apol_Class_Perms::opts(perms:show) write \
+ [list Apol_Class_Perms::_toggleCheckbuttons $classes $commons]
+ pack $perms -anchor w
+ pack $classes $commons -anchor w -padx 8
+
+ set widgets(regexp) [Apol_Widget::makeRegexpEntry $ofm.regexp]
+
+ pack $widgets(regexp) -side left -padx 2 -pady 2 -anchor ne
+
+ set ok [button $ofm.ok -text OK -width 6 \
+ -command Apol_Class_Perms::_search]
+ pack $ok -side right -pady 5 -padx 5 -anchor ne
+
+ set widgets(results) [Apol_Widget::makeSearchResults [$results_box getframe].results]
+ pack $widgets(results) -expand yes -fill both
+
+ return $frame
+}
+
+proc Apol_Class_Perms::open {ppath} {
+ set q [new_apol_class_query_t]
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ variable class_list [lsort [class_vector_to_list $v]]
+ $v -acquire
+ $v -delete
+
+ set q [new_apol_common_query_t]
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ variable common_perms_list [lsort [common_vector_to_list $v]]
+ $v -acquire
+ $v -delete
+
+ set q [new_apol_perm_query_t]
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ variable perms_list [lsort [str_vector_to_list $v]]
+ $v -acquire
+ $v -delete
+}
+
+proc Apol_Class_Perms::close {} {
+ variable class_list {}
+ variable common_perms_list {}
+ variable perms_list {}
+ variable widgets
+
+ _initializeVars
+ Apol_Widget::clearSearchResults $widgets(results)
+}
+
+proc Apol_Class_Perms::getTextWidget {} {
+ variable widgets
+ return $widgets(results).tb
+}
+
+proc Apol_Class_Perms::getClasses {} {
+ variable class_list
+ set class_list
+}
+
+# Return a sorted list of all permissions assigned to a class. If the
+# class has a common, include the common's permissions as well.
+proc Apol_Class_Perms::getPermsForClass {class_name} {
+ set qpol_class_datum [new_qpol_class_t $::ApolTop::qpolicy $class_name]
+ set i [$qpol_class_datum get_perm_iter $::ApolTop::qpolicy]
+ set perms [iter_to_str_list $i]
+ $i -acquire
+ $i -delete
+ if {[set qpol_common_datum [$qpol_class_datum get_common $::ApolTop::qpolicy]] != "NULL"} {
+ set i [$qpol_common_datum get_perm_iter $::ApolTop::qpolicy]
+ set perms [concat $perms [iter_to_str_list $i]]
+ $i -acquire
+ $i -delete
+ }
+ lsort -dictionary -unique $perms
+}
+
+# Given a permission name, return a 2-ple of lists. The first list
+# will contain all classes that directly declare the permission. The
+# second list is a list of classes that inherited from a common that
+# declared the permission. Both lists will be sorted and uniquified
+# when returned.
+proc Apol_Class_Perms::getClassesForPerm {perm_name} {
+ set classes_list {}
+ set i [$::ApolTop::qpolicy get_class_iter $perm_name]
+ while {![$i end]} {
+ set qpol_class_datum [qpol_class_from_void [$i get_item]]
+ lappend classes_list [$qpol_class_datum get_name $::ApolTop::qpolicy]
+ $i next
+ }
+ $i -acquire
+ $i -delete
+ set indirect_classes_list {}
+ set i [$::ApolTop::qpolicy get_common_iter $perm_name]
+ while {![$i end]} {
+ set qpol_common_datum [qpol_common_from_void [$i get_item]]
+ set q [new_apol_class_query_t]
+ $q set_common $::ApolTop::policy [$qpol_common_datum get_name $::ApolTop::qpolicy]
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set indirect_classes_list [concat $indirect_classes_list [class_vector_to_list $v]]
+ $v -acquire
+ $v -delete
+ $i next
+ }
+ $i -acquire
+ $i -delete
+ list [lsort $classes_list] [lsort -unique $indirect_classes_list]
+}
+
+#### private functions below ####
+
+proc Apol_Class_Perms::_initializeVars {} {
+ variable opts
+ array set opts {
+ classes:show 1 classes:perms 1 classes:commons 1
+ commons:show 0 commons:perms 1 commons:classes 1
+ perms:show 0 perms:classes 1 perms:commons 1
+ }
+}
+
+proc Apol_Class_Perms::_popupInfo {which name} {
+ if {$which == "class"} {
+ set text [_renderClass $name 1 0]
+ } elseif {$which == "common"} {
+ set text [_renderCommon $name 1 0]
+ } else {
+ set text [_renderPerm $name 1 1]
+ }
+ Apol_Widget::showPopupText $name $text
+}
+
+proc Apol_Class_Perms::_toggleCheckbuttons {cb1 cb2 name1 name2 op} {
+ variable opts
+ variable widgets
+ if {$opts($name2)} {
+ $cb1 configure -state normal
+ if {$name2 == "classes:show"} {
+ if {$opts(classes:perms)} {
+ $cb2 configure -state normal
+ } else {
+ $cb2 configure -state disabled
+ }
+ } elseif {$cb2 != {}} {
+ $cb2 configure -state normal
+ }
+ } else {
+ $cb1 configure -state disabled
+ if {$cb2 != {}} {
+ $cb2 configure -state disabled
+ }
+ }
+ if {!$opts(classes:show) && !$opts(commons:show) && !$opts(perms:show)} {
+ Apol_Widget::setRegexpEntryState $widgets(regexp) 0
+ } else {
+ Apol_Widget::setRegexpEntryState $widgets(regexp) 1
+ }
+}
+
+proc Apol_Class_Perms::_search {} {
+ variable opts
+ variable widgets
+
+ Apol_Widget::clearSearchResults $widgets(results)
+ if {![ApolTop::is_policy_open]} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No current policy file is opened."
+ return
+ }
+ if {!$opts(classes:show) && !$opts(commons:show) && !$opts(perms:show)} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No search options provided."
+ return
+ }
+ set use_regexp [Apol_Widget::getRegexpEntryState $widgets(regexp)]
+ set regexp [Apol_Widget::getRegexpEntryValue $widgets(regexp)]
+ if {$use_regexp} {
+ if {$regexp == {}} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No regular expression provided."
+ return
+ }
+ } else {
+ set regexp {}
+ }
+
+ set results {}
+
+ if {$opts(classes:show)} {
+ if {[set classes_perms $opts(classes:perms)]} {
+ set classes_commons $opts(classes:commons)
+ } else {
+ set classes_commons 0
+ }
+ set q [new_apol_class_query_t]
+ $q set_class $::ApolTop::policy $regexp
+ $q set_regex $::ApolTop::policy $use_regexp
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set classes_data [class_vector_to_list $v]
+ $v -acquire
+ $v -delete
+ append results "OBJECT CLASSES:\n"
+ if {$classes_data == {}} {
+ append results "Search returned no results.\n"
+ } else {
+ foreach c [lsort -index 0 $classes_data] {
+ append results [_renderClass $c $opts(classes:perms) $classes_commons]
+ }
+ }
+ }
+
+ if {$opts(commons:show)} {
+ set q [new_apol_common_query_t]
+ $q set_common $::ApolTop::policy $regexp
+ $q set_regex $::ApolTop::policy $use_regexp
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set commons_data [common_vector_to_list $v]
+ $v -acquire
+ $v -delete
+ append results "\nCOMMON PERMISSIONS: \n"
+ if {$commons_data == {}} {
+ append results "Search returned no results.\n"
+ } else {
+ foreach c [lsort -index 0 $commons_data] {
+ append results [_renderCommon $c $opts(commons:perms) $opts(commons:classes)]
+ }
+ }
+ }
+
+ if {$opts(perms:show)} {
+ set q [new_apol_perm_query_t]
+ $q set_perm $::ApolTop::policy $regexp
+ $q set_regex $::ApolTop::policy $use_regexp
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set perms_data [str_vector_to_list $v]
+ $v -acquire
+ $v -delete
+ append results "\nPERMISSIONS"
+ if {$opts(perms:classes)} {
+ append results " (* means class uses permission via a common permission)"
+ }
+ append results ":\n"
+ if {$perms_data == {}} {
+ append results "Search returned no results.\n"
+ } else {
+ foreach p [lsort -index 0 $perms_data] {
+ append results [_renderPerm $p $opts(perms:classes) $opts(perms:commons)]
+ }
+ }
+ }
+ Apol_Widget::appendSearchResultText $widgets(results) [string trim $results]
+}
+
+proc Apol_Class_Perms::_renderClass {class_name show_perms expand_common} {
+ set qpol_class_datum [new_qpol_class_t $::ApolTop::qpolicy $class_name]
+ if {[set qpol_common_datum [$qpol_class_datum get_common $::ApolTop::qpolicy]] == "NULL"} {
+ set common_name {}
+ } else {
+ set common_name [$qpol_common_datum get_name $::ApolTop::qpolicy]
+ }
+ set text "$class_name\n"
+ if {$show_perms} {
+ set i [$qpol_class_datum get_perm_iter $::ApolTop::qpolicy]
+ set perms_list [iter_to_str_list $i]
+ $i -acquire
+ $i -delete
+ foreach perm [lsort $perms_list] {
+ append text " $perm\n"
+ }
+ if {$common_name != {}} {
+ append text " $common_name (common perm)\n"
+ if {$expand_common} {
+ set i [$qpol_common_datum get_perm_iter $::ApolTop::qpolicy]
+ foreach perm [lsort [iter_to_str_list $i]] {
+ append text " $perm\n"
+ }
+ $i -acquire
+ $i -delete
+ }
+ }
+ append text \n
+ }
+ return $text
+}
+
+proc Apol_Class_Perms::_renderCommon {common_name show_perms show_classes} {
+ set qpol_common_datum [new_qpol_common_t $::ApolTop::qpolicy $common_name]
+ set text "$common_name\n"
+ if {$show_perms} {
+ set i [$qpol_common_datum get_perm_iter $::ApolTop::qpolicy]
+ foreach perm [lsort [iter_to_str_list $i]] {
+ append text " $perm\n"
+ }
+ $i -acquire
+ $i -delete
+ }
+ if {$show_classes} {
+ append text " Object classes that use this common permission:\n"
+ set i [$::ApolTop::qpolicy get_class_iter]
+ set classes_list {}
+ while {![$i end]} {
+ set qpol_class_t [qpol_class_from_void [$i get_item]]
+ set q [$qpol_class_t get_common $::ApolTop::qpolicy]
+ if {$q != "NULL" && [$q get_name $::ApolTop::qpolicy] == $common_name} {
+ lappend classes_list [$qpol_class_t get_name $::ApolTop::qpolicy]
+ }
+ $i next
+ }
+ $i -acquire
+ $i -delete
+ foreach class [lsort $classes_list] {
+ append text " $class\n"
+ }
+ }
+ if {$show_perms || $show_classes} {
+ append text "\n"
+ }
+ return $text
+}
+
+proc Apol_Class_Perms::_renderPerm {perm_name show_classes show_commons} {
+ set text "$perm_name\n"
+ if {$show_classes} {
+ append text " object classes:\n"
+ foreach {classes_list indirect_classes_list} [getClassesForPerm $perm_name] {break}
+ foreach c $indirect_classes_list {
+ lappend classes_list ${c}*
+ }
+ if {$classes_list == {}} {
+ append text " <none>\n"
+ } else {
+ foreach class [lsort -uniq $classes_list] {
+ append text " $class\n"
+ }
+ }
+ }
+ if {$show_commons} {
+ append text " common permissions:\n"
+ set commons_list {}
+ set i [$::ApolTop::qpolicy get_common_iter $perm_name]
+ while {![$i end]} {
+ set qpol_common_datum [qpol_common_from_void [$i get_item]]
+ lappend commons_list [$qpol_common_datum get_name $::ApolTop::qpolicy]
+ $i next
+ }
+ $i -acquire
+ $i -delete
+
+ if {$commons_list == {}} {
+ append text " <none>\n"
+ } else {
+ foreach common [lsort $commons_list] {
+ append text " $common\n"
+ }
+ }
+ }
+ if {$show_classes || $show_commons} {
+ append text "\n"
+ }
+ return $text
+}
diff --git a/apol/common_widgets.tcl b/apol/common_widgets.tcl
new file mode 100644
index 0000000..617cd70
--- /dev/null
+++ b/apol/common_widgets.tcl
@@ -0,0 +1,688 @@
+# Copyright (C) 2001-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
+
+namespace eval Apol_Widget {
+ variable menuPopup {}
+ variable infoPopup {}
+ variable infoPopup2 {}
+ variable vars
+}
+
+# Create a listbox contained within a scrolled window. Whenever the
+# listbox has focus, if the user hits an alphanum key then scroll to
+# the first entry beginning with that letter. That entry is then
+# selected, with all others being cleared. Repeatedly hitting the
+# same key causes the widget to select succesive entries, wrapping
+# back to the first when at the end of the list. (This behavior
+# assumes that the listbox has been alphabetized.)
+proc Apol_Widget::makeScrolledListbox {path args} {
+ set sw [ScrolledWindow $path -scrollbar both -auto both]
+ set lb [eval listbox $sw.lb $args -bg white -highlightthickness 0]
+ $sw setwidget $lb
+
+ update
+ grid propagate $sw 0
+ bind $lb <<ListboxSelect>> [list focus $lb]
+
+ # if the user hits a letter while the listbox has focus, jump to
+ # the first entry that begins with that letter
+ bind $lb <Key> [list Apol_Widget::_listbox_key $lb %K]
+ return $sw
+}
+
+# Add callback(s) to a listbox. The callback_list is a list of
+# 2-uple entries like so:
+#
+# menu_name {function ?args?}
+#
+# The first entry is executed upon double-clicks.
+proc Apol_Widget::setListboxCallbacks {path callback_list} {
+ set lb [getScrolledListbox $path]
+
+ # add double-click on an item to immediately do something
+ bind $lb <Double-Button-1> [eval list Apol_Widget::_listbox_double_click $lb [lindex $callback_list 0 1]]
+
+ # enable right-clicks on listbox to popup a menu; that menu lets
+ # the user see more info
+ set lb [getScrolledListbox $path]
+ bind $lb <Button-3> [list Apol_Widget::_listbox_popup %W %x %y $callback_list $lb]
+}
+
+proc Apol_Widget::getScrolledListbox {path} {
+ return $path.lb
+}
+
+proc Apol_Widget::setScrolledListboxState {path newState} {
+ if {$newState == 0 || $newState == "disabled"} {
+ $path.lb configure -state disabled
+ } else {
+ $path.lb configure -state normal
+ }
+}
+
+# Create combobox from which the user may choose a type. Then create
+# a combobox from which the user may select an attribute; this
+# attribute filters the allowable types.
+proc Apol_Widget::makeTypeCombobox {path args} {
+ variable vars
+ array unset vars $path:*
+ set vars($path:type) ""
+ set vars($path:attribenable) 0
+ set vars($path:attrib) ""
+
+ set f [frame $path]
+ set type_box [eval ComboBox $f.tb -helptext {{Type or select a type}} \
+ -textvariable Apol_Widget::vars($path:type) \
+ -entrybg white -width 20 -autopost 1 $args]
+ pack $type_box -side top -expand 1 -fill x
+
+ set attrib_width [expr {[$type_box cget -width] - 4}]
+ set attrib_enable [checkbutton $f.ae \
+ -anchor w -text "Filter by attribute"\
+ -variable Apol_Widget::vars($path:attribenable) \
+ -command [list Apol_Widget::_attrib_enabled $path]]
+ set attrib_box [ComboBox $f.ab -autopost 1 -entrybg white -width $attrib_width \
+ -textvariable Apol_Widget::vars($path:attrib)]
+ trace add variable Apol_Widget::vars($path:attrib) write [list Apol_Widget::_attrib_changed $path]
+ pack $attrib_enable -side top -expand 0 -fill x -anchor sw -padx 5 -pady 2
+ pack $attrib_box -side top -expand 1 -fill x -padx 9
+ _attrib_enabled $path
+ return $f
+}
+
+proc Apol_Widget::resetTypeComboboxToPolicy {path} {
+ $path.tb configure -values [Apol_Types::getTypes]
+ $path.ab configure -values [Apol_Types::getAttributes]
+}
+
+proc Apol_Widget::clearTypeCombobox {path} {
+ variable vars
+ set vars($path:attribenable) 0
+ set vars($path:attrib) ""
+ set vars($path:type) ""
+ $path.tb configure -values {}
+ $path.ab configure -values {}
+ _attrib_enabled $path
+}
+
+# Return the currently selected type. If an attribute is acting as a
+# filter, the return value will instead be a 2-ple list of the
+# selected type and the selected attribute.
+proc Apol_Widget::getTypeComboboxValueAndAttrib {path} {
+ variable vars
+ if {$vars($path:attribenable)} {
+ list [string trim $vars($path:type)] $vars($path:attrib)
+ } else {
+ string trim $vars($path:type)
+ }
+}
+
+# Set the type and possibly attribute for a type combobox. The first
+# element of $type is the type to set. If $type has more than one
+# element, then the second element is the attribute upon which to
+# filter.
+proc Apol_Widget::setTypeComboboxValue {path type} {
+ variable vars
+ if {[llength $type] <= 1} {
+ set vars($path:type) $type
+ set vars($path:attribenable) 0
+ set vars($path:attrib) ""
+ } else {
+ set vars($path:type) [lindex $type 0]
+ set vars($path:attribenable) 1
+ set vars($path:attrib) [lindex $type 1]
+ }
+ _attrib_enabled $path
+}
+
+proc Apol_Widget::setTypeComboboxState {path newState} {
+ variable vars
+ if {$newState == 0 || $newState == "disabled"} {
+ $path.tb configure -state disabled
+ $path.ae configure -state disabled
+ $path.ab configure -state disabled
+ } else {
+ $path.tb configure -state normal
+ $path.ae configure -state normal
+ if {$vars($path:attribenable)} {
+ $path.ab configure -state normal
+ }
+ }
+}
+
+
+# Create a mega-widget used to select a single MLS level (a
+# sensitivity + 0 or more categories).
+#
+# @param catSize Number of categories to show in the dropdown box.
+proc Apol_Widget::makeLevelSelector {path catSize args} {
+ variable vars
+ array unset vars $path:*
+ set vars($path:sens) {}
+ set vars($path:cats) {}
+
+ set f [frame $path]
+ set sens_box [eval ComboBox $f.sens $args \
+ -textvariable Apol_Widget::vars($path:sens) \
+ -entrybg white -width 16 -autopost 1]
+ trace add variable Apol_Widget::vars($path:sens) write [list Apol_Widget::_sens_changed $path]
+ pack $sens_box -side top -expand 0 -fill x
+
+ set cats_label [label $f.cl -text "Categories:"]
+ pack $cats_label -side top -anchor sw -pady 2 -expand 0
+
+ set cats [makeScrolledListbox $f.cats -width 16 -height $catSize \
+ -listvariable Apol_Widget::vars($path:cats) \
+ -selectmode extended -exportselection 0]
+ pack $cats -side top -expand 1 -fill both
+
+ set reset [button $f.reset -text "Clear Categories" \
+ -command [list [getScrolledListbox $cats] selection clear 0 end]]
+ pack $reset -side top -anchor center -pady 2
+ return $f
+}
+
+# Return an apol_mls_level_t object that represents the level
+# selected. The caller must delete it afterwards.
+proc Apol_Widget::getLevelSelectorLevel {path} {
+ variable vars
+ set apol_level [new_apol_mls_level_t]
+ # convert sensitivity aliases to its real name, if necessary
+ set l [Apol_MLS::isSensInPolicy $vars($path:sens)]
+ if {[ApolTop::is_policy_open]} {
+ set p $::ApolTop::policy
+ } else {
+ set p NULL
+ }
+ if {$l == {}} {
+ $apol_level set_sens $p $vars($path:sens)
+ } else {
+ $apol_level set_sens $p $l
+ }
+ set sl [getScrolledListbox $path.cats]
+ set cats {}
+ foreach idx [$sl curselection] {
+ $apol_level append_cats $p [$sl get $idx]
+ }
+ return $apol_level
+}
+
+# Given an apol_mls_level_t object, set the level selector's display
+# to match the level.
+proc Apol_Widget::setLevelSelectorLevel {path level} {
+ variable vars
+ if {$level == "NULL"} {
+ set sens {}
+ } else {
+ set sens [$level get_sens]
+ }
+ set sens_list [$path.sens cget -values]
+ if {$sens != {} && [lsearch -exact $sens_list $sens] != -1} {
+ set vars($path:sens) $sens
+ set cats_list $vars($path:cats)
+ set first_idx -1
+ set listbox [getScrolledListbox $path.cats]
+ set cats [str_vector_to_list [$level get_cats]]
+ foreach cat $cats {
+ if {[set idx [lsearch -exact $cats_list $cat]] != -1} {
+ $listbox selection set $idx
+ if {$first_idx == -1 || $idx < $first_idx} {
+ set first_idx $idx
+ }
+ }
+ }
+ # scroll the listbox so that the first one selected is visible
+ # near the top
+ incr first_idx -1
+ $listbox yview scroll $first_idx units
+ }
+}
+
+proc Apol_Widget::resetLevelSelectorToPolicy {path} {
+ variable vars
+ set vars($path:sens) {}
+
+ if {![ApolTop::is_policy_open]} {
+ $path.sens configure -values {}
+ } else {
+ set level_data {}
+ set i [$::ApolTop::qpolicy get_level_iter]
+ while {![$i end]} {
+ set qpol_level_datum [qpol_level_from_void [$i get_item]]
+ if {![$qpol_level_datum get_isalias $::ApolTop::qpolicy]} {
+ set level_name [$qpol_level_datum get_name $::ApolTop::qpolicy]
+ set level_value [$qpol_level_datum get_value $::ApolTop::qpolicy]
+ lappend level_data [list $level_name $level_value]
+ }
+ $i next
+ }
+ $i -acquire
+ $i -delete
+ set level_names {}
+ foreach l [lsort -integer -index 1 $level_data] {
+ lappend level_names [lindex $l 0]
+ }
+ $path.sens configure -values $level_names
+ }
+}
+
+proc Apol_Widget::clearLevelSelector {path} {
+ variable vars
+ set vars($path:sens) {}
+ $path.sens configure -values {}
+ # the category box will be cleared because of the trace on $path:sens
+}
+
+proc Apol_Widget::setLevelSelectorState {path newState} {
+ if {$newState == 0 || $newState == "disabled"} {
+ set newState disabled
+ } else {
+ set newState normal
+ }
+ $path.sens configure -state $newState
+ $path.cl configure -state $newState
+ $path.reset configure -state $newState
+ setScrolledListboxState $path.cats $newState
+}
+
+# Create a common "search using regular expression" checkbutton + entry.
+proc Apol_Widget::makeRegexpEntry {path args} {
+ variable vars
+ array unset vars $path:*
+ set vars($path:enable_regexp) 0
+
+ set f [frame $path]
+ set cb [checkbutton $f.cb -text "Search using regular expression" \
+ -variable Apol_Widget::vars($path:enable_regexp)]
+ set regexp [eval entry $f.entry $args \
+ -textvariable Apol_Widget::vars($path:regexp) \
+ -width 32 -state disabled -bg $ApolTop::default_bg_color]
+ trace add variable Apol_Widget::vars($path:enable_regexp) write \
+ [list Apol_Widget::_toggle_regexp_check_button $regexp]
+ pack $cb -side top -anchor nw
+ pack $regexp -side top -padx 4 -anchor nw -expand 0 -fill x
+ return $f
+}
+
+proc Apol_Widget::setRegexpEntryState {path newState} {
+ variable vars
+ if {$newState == 0 || $newState == "disabled"} {
+ set vars($path:enable_regexp) 0
+ $path.cb configure -state disabled
+ } else {
+ $path.cb configure -state normal
+ }
+}
+
+proc Apol_Widget::setRegexpEntryValue {path newState newValue} {
+ variable vars
+ set old_state [$path.cb cget -state]
+ set vars($path:enable_regexp) $newState
+ set vars($path:regexp) $newValue
+ $path.cb configure -state $old_state
+}
+
+proc Apol_Widget::getRegexpEntryState {path} {
+ return $Apol_Widget::vars($path:enable_regexp)
+}
+
+proc Apol_Widget::getRegexpEntryValue {path} {
+ return $Apol_Widget::vars($path:regexp)
+}
+
+# Create a scrolled non-editable text widget, from which search
+# results may be displayed.
+proc Apol_Widget::makeSearchResults {path args} {
+ variable vars
+ array unset vars $path:*
+ set sw [ScrolledWindow $path -scrollbar both -auto both]
+ set tb [eval text $sw.tb $args -bg white -wrap none -state disabled -font $ApolTop::text_font]
+ set vars($path:cursor) [$tb cget -cursor]
+ bind $tb <Button-3> [list Apol_Widget::_searchresults_popup %W %x %y]
+ $tb tag configure linenum -foreground blue -underline 1
+ $tb tag configure selected -foreground red -underline 1
+ $tb tag configure enabled -foreground green -underline 1
+ $tb tag configure disabled -foreground red -underline 1
+ $tb tag bind linenum <Button-1> [list Apol_Widget::_hyperlink $path %x %y]
+ $tb tag bind linenum <Enter> [list $tb configure -cursor hand2]
+ $tb tag bind linenum <Leave> [list $tb configure -cursor $Apol_Widget::vars($path:cursor)]
+ $sw setwidget $tb
+ return $sw
+}
+
+proc Apol_Widget::clearSearchResults {path} {
+ $path.tb configure -state normal
+ $path.tb delete 0.0 end
+ $path.tb configure -state disabled
+}
+
+proc Apol_Widget::copySearchResults {path} {
+ if {[$path tag ranges sel] != {}} {
+ set data [$path get sel.first sel.last]
+ clipboard clear
+ clipboard append -- $data
+ }
+}
+
+proc Apol_Widget::selectAllSearchResults {path} {
+ $path tag add sel 1.0 end
+}
+
+proc Apol_Widget::appendSearchResultHeader {path header} {
+ $path.tb configure -state normal
+ $path.tb insert 1.0 "$header\n"
+ $path.tb configure -state disabled
+}
+
+proc Apol_Widget::appendSearchResultText {path text} {
+ $path.tb configure -state normal
+ $path.tb insert end $text
+ $path.tb configure -state disabled
+}
+
+# Append a vector of qpol_avrule_t or qpol_terule_t to a search
+# results box. Sort the rules by string representation. Returns the
+# number of rules that were appended, number of enabled rules, and
+# number of disabled rules.
+#
+# @param cast SWIG casting function, one of "new_qpol_avrule_t" or
+# "new_qpol_terule_t"
+proc Apol_Widget::appendSearchResultRules {path indent rule_list cast} {
+ set curstate [$path.tb cget -state]
+ $path.tb configure -state normal
+
+ set num_enabled 0
+ set num_disabled 0
+
+ for {set i 0} {$i < [$rule_list get_size]} {incr i} {
+ set rule [$cast [$rule_list get_element $i]]
+ $path.tb insert end [string repeat " " $indent]
+ $path.tb insert end [apol_tcl_rule_render $::ApolTop::policy $rule]
+ if {[$rule get_cond $::ApolTop::qpolicy] != "NULL"} {
+ if {[$rule get_is_enabled $::ApolTop::qpolicy]} {
+ $path.tb insert end " \[" {} "Enabled" enabled "\]"
+ incr num_enabled
+ } else {
+ $path.tb insert end " \[" {} "Disabled" disabled "\]"
+ incr num_disabled
+ }
+ }
+ $path.tb insert end "\n"
+ }
+ $path.tb configure -state $curstate
+ list [$rule_list get_size] $num_enabled $num_disabled
+}
+
+# Append a vector of qpol_syn_avrule_t or qpol_syn_terule_t to a
+# search results box. Returns the number of rules that were appended,
+# number of enabled rules, and number of disabled rules.
+#
+# @param cast SWIG casting function, one of "new_qpol_syn_avrule_t" or
+# "new_qpol_syn_terule_t"
+proc Apol_Widget::appendSearchResultSynRules {path indent rule_list cast} {
+ set curstate [$path.tb cget -state]
+ $path.tb configure -state normal
+
+ set num_enabled 0
+ set num_disabled 0
+ if {[ApolTop::is_capable "line numbers"]} {
+ set do_linenums 1
+ } else {
+ set do_linenums 0
+ }
+
+ for {set i 0} {$i < [$rule_list get_size]} {incr i} {
+ set syn_rule [$cast [$rule_list get_element $i]]
+ $path.tb insert end [string repeat " " $indent]
+ if {$do_linenums} {
+ $path.tb insert end \
+ "\[" {} \
+ [$syn_rule get_lineno $::ApolTop::qpolicy] linenum \
+ "\] " {}
+ }
+ $path.tb insert end [apol_tcl_rule_render $::ApolTop::policy $syn_rule]
+ if {[$syn_rule get_cond $::ApolTop::qpolicy] != "NULL"} {
+ if {[$syn_rule get_is_enabled $::ApolTop::qpolicy]} {
+ $path.tb insert end " \[" {} "Enabled" enabled "\]"
+ incr num_enabled
+ } else {
+ $path.tb insert end " \[" {} "Disabled" disabled "\]"
+ incr num_disabled
+ }
+ }
+ $path.tb insert end "\n"
+ }
+ $path.tb configure -state $curstate
+ list [$rule_list get_size] $num_enabled $num_disabled
+}
+
+proc Apol_Widget::showPopupText {title info} {
+ variable infoPopup
+ if {![winfo exists $infoPopup]} {
+ set infoPopup [toplevel .apol_widget_info_popup]
+ wm withdraw $infoPopup
+ set sw [ScrolledWindow $infoPopup.sw -scrollbar both -auto horizontal]
+ set text [text [$sw getframe].text -font {helvetica 10} -wrap none -width 35 -height 10]
+ $sw setwidget $text
+ pack $sw -expand 1 -fill both
+ set b [button $infoPopup.close -text "Close" -command [list destroy $infoPopup]]
+ pack $b -side bottom -expand 0 -pady 5
+ wm geometry $infoPopup 250x200+50+50
+ update
+ grid propagate $sw 0
+ }
+ wm title $infoPopup $title
+ set text [$infoPopup.sw getframe].text
+ $text configure -state normal
+ $text delete 1.0 end
+ $text insert 0.0 $info
+ $text configure -state disabled
+ wm deiconify $infoPopup
+ raise $infoPopup
+}
+
+# Used to show pre-rendered paragraphs of text.
+proc Apol_Widget::showPopupParagraph {title info} {
+ variable infoPopup2
+ if {![winfo exists $infoPopup2]} {
+ set infoPopup2 [Dialog .apol_widget_info_popup2 -modal none -parent . \
+ -transient false -cancel 0 -default 0 -separator 1]
+ $infoPopup2 add -text "Close" -command [list destroy $infoPopup2]
+ set sw [ScrolledWindow [$infoPopup2 getframe].sw -auto both -scrollbar both]
+ $sw configure -relief sunken
+ set text [text [$sw getframe].text -font $ApolTop::text_font \
+ -wrap none -width 75 -height 25 -bg white]
+ $sw setwidget $text
+ update
+ grid propagate $sw 0
+ pack $sw -expand 1 -fill both -padx 4 -pady 4
+ $infoPopup2 draw
+ } else {
+ raise $infoPopup2
+ wm deiconify $infoPopup2
+ }
+ $infoPopup2 configure -title $title
+ set text [[$infoPopup2 getframe].sw getframe].text
+ $text configure -state normal
+ $text delete 1.0 end
+ $text insert 0.0 $info
+ $text configure -state disabled
+}
+
+########## private functions below ##########
+
+proc Apol_Widget::_listbox_key {listbox key} {
+ if {[string length $key] == 1} {
+ # only scroll with non-function keys
+ set values [set ::[$listbox cget -listvar]]
+ set x [lsearch $values $key*]
+ if {$x >= 0} {
+ # if the current value already begins with that letter,
+ # cycle to the next one, wrapping back to the first value
+ # as necessary
+ set curvalue [$listbox get active]
+ set curindex [$listbox curselection]
+ if {$curindex != "" && [string index $curvalue 0] == $key} {
+ set new_x [expr {$curindex + 1}]
+ if {[string index [lindex $values $new_x] 0] != $key} {
+ # wrap around
+ set new_x $x
+ }
+ } else {
+ set new_x $x
+ }
+
+ $listbox selection clear 0 end
+ $listbox selection set $new_x
+ $listbox activate $new_x
+ $listbox see $new_x
+ }
+ event generate $listbox <<ListboxSelect>>
+ }
+}
+
+proc Apol_Widget::_listbox_double_click {listbox callback_func args} {
+ eval $callback_func $args [$listbox get active]
+}
+
+proc Apol_Widget::_listbox_popup {w x y callbacks lb} {
+ focus $lb
+ set selected_item [$lb get active]
+ if {$selected_item == {}} {
+ return
+ }
+
+ # create a global popup menu widget if one does not already exist
+ variable menuPopup
+ if {![winfo exists $menuPopup]} {
+ set menuPopup [menu .apol_widget_menu_popup -tearoff 0]
+ }
+
+ ApolTop::popup $w $x $y $menuPopup $callbacks $selected_item
+}
+
+proc Apol_Widget::_attrib_enabled {path} {
+ variable vars
+ if {$vars($path:attribenable)} {
+ $path.ab configure -state normal
+ _filter_type_combobox $path $vars($path:attrib)
+ } else {
+ $path.ab configure -state disabled
+ _filter_type_combobox $path ""
+ }
+}
+
+proc Apol_Widget::_attrib_changed {path name1 name2 op} {
+ variable vars
+ if {$vars($path:attribenable)} {
+ _filter_type_combobox $path $vars($name2)
+ }
+}
+
+proc Apol_Widget::_attrib_validate {path} {
+ # check that the attribute given was valid
+}
+
+proc Apol_Widget::_filter_type_combobox {path attribvalue} {
+ variable vars
+ if {$attribvalue != {}} {
+ set typesList {}
+ if {[Apol_Types::isAttributeInPolicy $attribvalue]} {
+ set qpol_type_datum [new_qpol_type_t $::ApolTop::qpolicy $attribvalue]
+ set i [$qpol_type_datum get_type_iter $::ApolTop::qpolicy]
+ foreach t [iter_to_list $i] {
+ set t [qpol_type_from_void $t]
+ lappend typesList [$t get_name $::ApolTop::qpolicy]
+ }
+ $i -acquire
+ $i -delete
+ }
+ if {$typesList == {}} {
+ # unknown attribute, so don't change type combobox
+ return
+ }
+ } else {
+ set typesList [Apol_Types::getTypes]
+ # during policy load this list should already have been sorted
+ }
+ if {[lsearch -exact $typesList $vars($path:type)] == -1} {
+ set vars($path:type) {}
+ }
+ $path.tb configure -values [lsort $typesList]
+}
+
+proc Apol_Widget::_sens_changed {path name1 name2 op} {
+ variable vars
+ # get a list of categories associated with this sensitivity
+ [getScrolledListbox $path.cats] selection clear 0 end
+ set vars($path:cats) {}
+ set sens [Apol_MLS::isSensInPolicy $vars($path:sens)]
+ if {$sens != {}} {
+ # the given level exists within the given policy
+ set qpol_level_datum [new_qpol_level_t $::ApolTop::qpolicy $sens]
+ set i [$qpol_level_datum get_cat_iter $::ApolTop::qpolicy]
+ while {![$i end]} {
+ set qpol_cat_datum [qpol_cat_from_void [$i get_item]]
+ lappend vars($path:cats) [$qpol_cat_datum get_name $::ApolTop::qpolicy]
+ $i next
+ }
+ $i -acquire
+ $i -delete
+ }
+}
+
+proc Apol_Widget::_toggle_regexp_check_button {path name1 name2 op} {
+ if {$Apol_Widget::vars($name2)} {
+ $path configure -state normal -bg white
+ } else {
+ $path configure -state disabled -bg $ApolTop::default_bg_color
+ }
+}
+
+proc Apol_Widget::_searchresults_popup {path x y} {
+ if {[ApolTop::is_policy_open]} {
+ focus $path
+ # create a global popup menu widget if one does not already exist
+ variable menuPopup
+ if {![winfo exists $menuPopup]} {
+ set menuPopup [menu .apol_widget_menu_popup -tearoff 0]
+ }
+ set callbacks {
+ {"Copy" Apol_Widget::copySearchResults}
+ {"Select All" Apol_Widget::selectAllSearchResults}
+ }
+ ApolTop::popup $path $x $y $menuPopup $callbacks $path
+ }
+}
+
+proc Apol_Widget::_hyperlink {path x y} {
+ set tb $path.tb
+ set range [$tb tag prevrange linenum "@$x,$y + 1 char"]
+ $tb tag add selected [lindex $range 0] [lindex $range 1]
+ set line_num [$tb get [lindex $range 0] [lindex $range 1]]
+ ApolTop::showPolicySourceLineNumber $line_num
+}
+
+proc Apol_Widget::_render_typeset {typeset} {
+ if {[llength $typeset] > 1} {
+ if {[lindex $typeset 0] == "~"} {
+ set typeset "~\{[lrange $typeset 1 end]\}"
+ } else {
+ set typeset "\{$typeset\}"
+ }
+ } else {
+ set typeset
+ }
+}
diff --git a/apol/cond_bools_tab.tcl b/apol/cond_bools_tab.tcl
new file mode 100644
index 0000000..76356f1
--- /dev/null
+++ b/apol/cond_bools_tab.tcl
@@ -0,0 +1,266 @@
+# 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
+
+namespace eval Apol_Cond_Bools {
+ variable cond_bools_list {}
+ variable cond_bools_defaults
+ variable cond_bools_values
+ variable opts
+ variable widgets
+}
+
+proc Apol_Cond_Bools::create {tab_name nb} {
+ variable opts
+ variable widgets
+
+ _initializeVars
+
+ # Layout frames
+ set frame [$nb insert end $tab_name -text "Booleans"]
+ set pw [PanedWindow $frame.pw -side top]
+ set left_pane [$pw add -weight 0]
+ set right_pane [$pw add -weight 1]
+ pack $pw -expand 1 -fill both
+
+ # Title frames
+ set cond_bools_box [TitleFrame $left_pane.cond_bools_box -text "Booleans"]
+ set s_optionsbox [TitleFrame $right_pane.obox -text "Search Options"]
+ set rslts_frame [TitleFrame $right_pane.rbox -text "Search Results"]
+ pack $cond_bools_box -expand 1 -fill both
+ pack $s_optionsbox -padx 2 -fill x -expand 0
+ pack $rslts_frame -padx 2 -fill both -expand yes
+
+ # Booleans listbox widget
+ set left_frame [$cond_bools_box getframe]
+ set sw_b [ScrolledWindow $left_frame.sw -auto both]
+ set widgets(listbox) [ScrollableFrame $sw_b.listbox -bg white -width 200]
+ $sw_b setwidget $widgets(listbox)
+ set button_defaults [button $left_frame.button_defaults \
+ -text "Reset to Policy Defaults" \
+ -command Apol_Cond_Bools::_resetAll]
+ pack $sw_b -side top -expand 1 -fill both
+ pack $button_defaults -side bottom -pady 2 -expand 0 -fill x
+
+ # Search options subframes
+ set ofm [$s_optionsbox getframe]
+ set bool_frame [frame $ofm.bool]
+ set show_frame [frame $ofm.show]
+ pack $bool_frame $show_frame -side left -padx 4 -pady 2 -anchor nw
+
+ set enable [checkbutton $bool_frame.enable \
+ -variable Apol_Cond_Bools::opts(enable_bool) \
+ -text "Boolean"]
+ set widgets(combo_box) [ComboBox $bool_frame.combo_box \
+ -textvariable Apol_Cond_Bools::opts(name) \
+ -helptext "Type or select a boolean variable" \
+ -state disabled -entrybg white -autopost 1]
+ set widgets(regexp) [checkbutton $bool_frame.regexp \
+ -text "Search using regular expression" \
+ -state disabled \
+ -variable Apol_Cond_Bools::opts(use_regexp)]
+ trace add variable Apol_Cond_Bools::opts(enable_bool) write \
+ [list Apol_Cond_Bools::_toggleSearchBools]
+ pack $enable -anchor w
+ pack $widgets(combo_box) $widgets(regexp) -padx 4 -anchor nw -expand 0 -fill x
+
+ set show_default [checkbutton $show_frame.show_default \
+ -variable Apol_Cond_Bools::opts(show_default) \
+ -text "Show default state"]
+ set show_current [checkbutton $show_frame.show_current \
+ -variable Apol_Cond_Bools::opts(show_current) \
+ -text "Show current state"]
+ pack $show_default $show_current -anchor w
+
+ # Action Buttons
+ set ok_button [button $ofm.ok -text "OK" -width 6 \
+ -command Apol_Cond_Bools::_search]
+ pack $ok_button -side right -anchor ne -padx 5 -pady 5
+
+ set widgets(results) [Apol_Widget::makeSearchResults [$rslts_frame getframe].results]
+ pack $widgets(results) -expand yes -fill both
+
+ return $frame
+}
+
+proc Apol_Cond_Bools::open {ppath} {
+ set q [new_apol_bool_query_t]
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ variable cond_bools_list [lsort [bool_vector_to_list $v]]
+ $v -acquire
+ $v -delete
+
+ variable cond_bools_defaults
+ foreach bool $cond_bools_list {
+ set b [new_qpol_bool_t $::ApolTop::qpolicy $bool]
+ set cond_bools_defaults($bool) [$b get_state $::ApolTop::qpolicy]
+ _insert_listbox_item $bool $cond_bools_defaults($bool)
+ }
+
+ variable widgets
+ $widgets(listbox) xview moveto 0
+ $widgets(listbox) yview moveto 0
+ $widgets(listbox) configure -areaheight 0 -areawidth 0
+ $widgets(combo_box) configure -values $cond_bools_list
+}
+
+proc Apol_Cond_Bools::close {} {
+ variable widgets
+ variable cond_bools_list {}
+ variable cond_bools_defaults
+ variable cond_bools_values
+
+ _initializeVars
+ $widgets(combo_box) configure -values {}
+ # clean up bools listbox, then hide its scrollbars
+ foreach w [winfo children [$widgets(listbox) getframe]] {
+ destroy $w
+ }
+ [$widgets(listbox) getframe] configure -width 1 -height 1
+ Apol_Widget::clearSearchResults $widgets(results)
+ array unset cond_bools_defaults
+ array unset cond_bools_values
+}
+
+proc Apol_Cond_Bools::getTextWidget {} {
+ variable widgets
+ return $widgets(results).tb
+}
+
+# Return a list of names of all conditional booleans within the
+# policy. If no policy is opened then return an empty list.
+proc Apol_Cond_Bools::getBooleans {} {
+ variable cond_bools_list
+ set cond_bools_list
+}
+
+#### private functions below ####
+
+proc Apol_Cond_Bools::_initializeVars {} {
+ variable opts
+ array set opts {
+ enable_bool 0
+ name ""
+ use_regexp 0
+
+ show_default 1
+ show_current 1
+ }
+}
+
+proc Apol_Cond_Bools::_insert_listbox_item {bool initial_state} {
+ variable widgets
+ variable cond_bools_values
+
+ set cond_bools_values($bool) $initial_state
+ set subf [$widgets(listbox) getframe]
+ set rb_true [radiobutton $subf.t:$bool -bg white \
+ -variable Apol_Cond_Bools::cond_bools_values($bool) \
+ -value 1 -highlightthickness 0 -text "True"]
+ set rb_false [radiobutton $subf.f:$bool -bg white \
+ -variable Apol_Cond_Bools::cond_bools_values($bool) \
+ -value 0 -highlightthickness 0 -text "False"]
+ trace add variable Apol_Cond_Bools::cond_bools_values($bool) write \
+ [list Apol_Cond_Bools::_set_bool_value]
+ set rb_label [label $subf.l:$bool -bg white -text "- $bool"]
+ grid $rb_true $rb_false $rb_label -padx 2 -pady 5 -sticky w
+}
+
+proc Apol_Cond_Bools::_toggleSearchBools {name1 name2 op} {
+ variable opts
+ variable widgets
+ if {$opts(enable_bool)} {
+ $widgets(combo_box) configure -state normal
+ $widgets(regexp) configure -state normal
+ } else {
+ $widgets(combo_box) configure -state disabled
+ $widgets(regexp) configure -state disabled
+ }
+}
+
+proc Apol_Cond_Bools::_set_bool_value {name1 name2 op} {
+ variable cond_bools_values
+ set qpol_bool_datum [new_qpol_bool_t $::ApolTop::qpolicy $name2]
+ $qpol_bool_datum set_state $::ApolTop::qpolicy $cond_bools_values($name2)
+}
+
+proc Apol_Cond_Bools::_resetAll {} {
+ variable cond_bools_defaults
+ variable cond_bools_values
+
+ # hopefully each of the traces associated with each boolean
+ # triggers, causing the policy to be updated
+ array set cond_bools_values [array get cond_bools_defaults]
+}
+
+proc Apol_Cond_Bools::_search {} {
+ variable opts
+ variable widgets
+
+ Apol_Widget::clearSearchResults $widgets(results)
+ if {![ApolTop::is_policy_open]} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No current policy file is opened."
+ return
+ }
+ set name [string trim $opts(name)]
+ if {$opts(enable_bool) && $name == {}} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No boolean variable provided."
+ return
+ }
+
+ set q [new_apol_bool_query_t]
+ $q set_bool $::ApolTop::policy $name
+ $q set_regex $::ApolTop::policy $opts(use_regexp)
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set bools_data [bool_vector_to_list $v]
+ $v -acquire
+ $v -delete
+
+ set results {}
+ set results "BOOLEANS:\n"
+ if {[llength $bools_data] == 0} {
+ append results "Search returned no results."
+ } else {
+ foreach b [lsort $bools_data] {
+ append results "\n[_renderBool $b $opts(show_default) $opts(show_current)]"
+ }
+ }
+ Apol_Widget::appendSearchResultText $widgets(results) $results
+}
+
+proc Apol_Cond_Bools::_renderBool {bool_name show_default show_current} {
+ variable cond_bools_defaults
+ set qpol_bool_datum [new_qpol_bool_t $::ApolTop::qpolicy $bool_name]
+ set cur_state [$qpol_bool_datum get_state $::ApolTop::qpolicy]
+ set text [format "%-28s" $bool_name]
+ if {$show_default} {
+ if {$cond_bools_defaults($bool_name)} {
+ append text " Default State: True "
+ } else {
+ append text " Default State: False"
+ }
+ }
+ if {$show_current} {
+ if {$cur_state} {
+ append text " Current State: True "
+ } else {
+ append text " Current State: False"
+ }
+ }
+ return $text
+}
diff --git a/apol/cond_rules_tab.tcl b/apol/cond_rules_tab.tcl
new file mode 100644
index 0000000..f0ab23d
--- /dev/null
+++ b/apol/cond_rules_tab.tcl
@@ -0,0 +1,281 @@
+# 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
+
+namespace eval Apol_Cond_Rules {
+ variable vals
+ variable widgets
+}
+
+proc Apol_Cond_Rules::create {tab_name nb} {
+ variable vals
+ variable widgets
+
+ _initializeVars
+
+ set frame [$nb insert end $tab_name -text "Conditional Expressions"]
+ set topf [frame $frame.top]
+ set bottomf [frame $frame.bottom]
+ pack $topf -expand 0 -fill both -pady 2
+ pack $bottomf -expand 1 -fill both -pady 2
+
+ set rules_box [TitleFrame $topf.rules_box -text "Rule Selection"]
+ set obox [TitleFrame $topf.obox -text "Search Options"]
+ set dbox [TitleFrame $bottomf.dbox -text "Conditional Expressions Display"]
+ pack $rules_box -side left -expand 0 -fill both -padx 2
+ pack $obox -side left -expand 1 -fill both -padx 2
+ pack $dbox -expand 1 -fill both -padx 2
+
+ # Rule selection subframe
+ set fm_rules [$rules_box getframe]
+ set allow [checkbutton $fm_rules.allow -text "allow" \
+ -onvalue $::QPOL_RULE_ALLOW -offvalue 0 \
+ -variable Apol_Cond_Rules::vals(rs:avrule_allow)]
+ set auditallow [checkbutton $fm_rules.auditallow -text "auditallow" \
+ -onvalue $::QPOL_RULE_AUDITALLOW -offvalue 0 \
+ -variable Apol_Cond_Rules::vals(rs:avrule_auditallow)]
+ set dontaudit [checkbutton $fm_rules.dontaudit -text "dontaudit" \
+ -onvalue $::QPOL_RULE_DONTAUDIT -offvalue 0 \
+ -variable Apol_Cond_Rules::vals(rs:avrule_dontaudit)]
+ set type_transition [checkbutton $fm_rules.type_transition -text "type_trans" \
+ -onvalue $::QPOL_RULE_TYPE_TRANS -offvalue 0 \
+ -variable Apol_Cond_Rules::vals(rs:type_transition)]
+ set type_member [checkbutton $fm_rules.type_member -text "type_member" \
+ -onvalue $::QPOL_RULE_TYPE_MEMBER -offvalue 0 \
+ -variable Apol_Cond_Rules::vals(rs:type_member)]
+ set type_change [checkbutton $fm_rules.type_change -text "type_change" \
+ -onvalue $::QPOL_RULE_TYPE_CHANGE -offvalue 0 \
+ -variable Apol_Cond_Rules::vals(rs:type_change)]
+ grid $allow $type_transition -sticky w -padx 2
+ grid $auditallow $type_member -sticky w -padx 2
+ grid $dontaudit $type_change -sticky w -padx 2
+
+ # Search options subframes
+ set ofm [$obox getframe]
+ set bool_frame [frame $ofm.bool]
+ pack $bool_frame -side left -padx 4 -pady 2 -anchor nw
+ set enable [checkbutton $bool_frame.enable \
+ -variable Apol_Cond_Rules::vals(enable_bool) \
+ -text "Boolean"]
+ set widgets(combo_box) [ComboBox $bool_frame.combo_box \
+ -textvariable Apol_Cond_Rules::vals(name) \
+ -helptext "Type or select a boolean variable" \
+ -state disabled -entrybg white -autopost 1]
+ set widgets(regexp) [checkbutton $bool_frame.regexp \
+ -text "Search using regular expression" \
+ -state disabled \
+ -variable Apol_Cond_Rules::vals(use_regexp)]
+ trace add variable Apol_Cond_Rules::vals(enable_bool) write \
+ [list Apol_Cond_Rules::_toggleSearchBools]
+ pack $enable -anchor w
+ pack $widgets(combo_box) $widgets(regexp) -padx 4 -anchor nw -expand 0 -fill x
+
+ set ok_button [button $ofm.ok -text OK -width 6 \
+ -command Apol_Cond_Rules::_search]
+ pack $ok_button -side right -anchor ne -padx 5 -pady 5
+
+ set widgets(results) [Apol_Widget::makeSearchResults [$dbox getframe].results]
+ pack $widgets(results) -expand yes -fill both
+
+ return $frame
+}
+
+proc Apol_Cond_Rules::open {ppath} {
+ variable widgets
+ $widgets(combo_box) configure -values [Apol_Cond_Bools::getBooleans]
+}
+
+proc Apol_Cond_Rules::close {} {
+ variable widgets
+
+ _initializeVars
+ $widgets(combo_box) configure -values {}
+ Apol_Widget::clearSearchResults $widgets(results)
+}
+
+proc Apol_Cond_Rules::getTextWidget {} {
+ variable widgets
+ return $widgets(results).tb
+}
+
+#### private functions below ####
+
+proc Apol_Cond_Rules::_initializeVars {} {
+ variable vals
+ array set vals [list \
+ rs:avrule_allow $::QPOL_RULE_ALLOW \
+ rs:avrule_auditallow $::QPOL_RULE_AUDITALLOW \
+ rs:avrule_dontaudit $::QPOL_RULE_DONTAUDIT \
+ rs:type_transition $::QPOL_RULE_TYPE_TRANS \
+ rs:type_member $::QPOL_RULE_TYPE_MEMBER \
+ rs:type_change $::QPOL_RULE_TYPE_CHANGE \
+ enable_bool 0 \
+ name {} \
+ use_regexp 0]
+}
+
+proc Apol_Cond_Rules::_toggleSearchBools {name1 name2 op} {
+ variable vals
+ variable widgets
+ if {$vals(enable_bool)} {
+ $widgets(combo_box) configure -state normal
+ $widgets(regexp) configure -state normal
+ } else {
+ $widgets(combo_box) configure -state disabled
+ $widgets(regexp) configure -state disabled
+ }
+}
+
+proc Apol_Cond_Rules::_search {} {
+ variable vals
+ variable widgets
+ .mainframe.frame.nb.frules.nb.fApol_Cond_Rules.top.obox.f.ok configure -state disabled
+
+ Apol_Widget::clearSearchResults $widgets(results)
+ if {![ApolTop::is_policy_open]} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No current policy file is opened."
+ .mainframe.frame.nb.frules.nb.fApol_Cond_Rules.top.obox.f.ok configure -state normal
+ return
+ }
+
+ set avrule_selection 0
+ foreach {key value} [array get vals rs:avrule_*] {
+ set avrule_selection [expr {$avrule_selection | $value}]
+ }
+ set terule_selection 0
+ foreach {key value} [array get vals rs:type_*] {
+ set terule_selection [expr {$terule_selection | $value}]
+ }
+ if {$avrule_selection == 0 && $terule_selection == 0} {
+ tk_messageBox -icon error -type ok -title "Error" -message "At least one rule must be selected."
+ .mainframe.frame.nb.frules.nb.fApol_Cond_Rules.top.obox.f.ok configure -state normal
+ return
+ }
+
+ set bool_name {}
+ if {$vals(enable_bool)} {
+ if {[set bool_name $vals(name)] == {}} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No booleean selected."
+ .mainframe.frame.nb.frules.nb.fApol_Cond_Rules.top.obox.f.ok configure -state normal
+ return
+ }
+ }
+
+ set q [new_apol_cond_query_t]
+ $q set_bool $::ApolTop::policy $bool_name
+ if {$vals(use_regexp)} {
+ $q set_regex $::ApolTop::policy 1
+ }
+
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set results [cond_vector_to_list $v]
+ $v -acquire
+ $v -delete
+
+ if {[llength $results] == 0} {
+ set text "Search returned no results."
+ } else {
+ set text "[llength $results] conditional"
+ if {[llength $results] != 1} {
+ append text s
+ }
+ append text " match the search criteria. Expressions are in Reverse Polish Notation.\n\n"
+ }
+ Apol_Widget::appendSearchResultText $widgets(results) $text
+ if {![info exists apol_progress]} {
+ Apol_Progress_Dialog::wait "Conditional Expressions" "Rendering conditionals" \
+ {
+ if {[ApolTop::is_capable "syntactic rules"]} {
+ $::ApolTop::qpolicy build_syn_rule_table
+ }
+ set counter 1
+ set num_results [llength $results]
+ foreach r [lsort -index 0 $results] {
+ apol_tcl_set_info_string $::ApolTop::policy "Rendering $counter of $num_results"
+ set text [_renderConditional $r $avrule_selection $terule_selection $counter]
+ Apol_Widget::appendSearchResultText $widgets(results) "$text\n\n"
+ incr counter
+ }
+ }
+ }
+ .mainframe.frame.nb.frules.nb.fApol_Cond_Rules.top.obox.f.ok configure -state normal
+}
+
+proc Apol_Cond_Rules::_renderConditional {cond avrules terules cond_number} {
+ set cond_expr [apol_cond_expr_render $::ApolTop::policy $cond]
+ set i [$cond get_av_true_iter $::ApolTop::qpolicy $avrules]
+ set av_true_vector [new_apol_vector_t $i]
+ $i -acquire
+ $i -delete
+ set i [$cond get_av_false_iter $::ApolTop::qpolicy $avrules]
+ set av_false_vector [new_apol_vector_t $i]
+ $i -acquire
+ $i -delete
+ set i [$cond get_te_true_iter $::ApolTop::qpolicy $terules]
+ set te_true_vector [new_apol_vector_t $i]
+ $i -acquire
+ $i -delete
+ set i [$cond get_te_false_iter $::ApolTop::qpolicy $terules]
+ set te_false_vector [new_apol_vector_t $i]
+ $i -acquire
+ $i -delete
+
+ variable widgets
+ set text "conditional expression $cond_number: \[ [join $cond_expr] \]\n"
+
+ Apol_Widget::appendSearchResultText $widgets(results) "$text\nTRUE list:\n"
+ if {![ApolTop::is_capable "syntactic rules"]} {
+ apol_tcl_avrule_sort $::ApolTop::policy $av_true_vector
+ Apol_Widget::appendSearchResultRules $widgets(results) 4 $av_true_vector qpol_avrule_from_void
+ apol_tcl_terule_sort $::ApolTop::policy $te_true_vector
+ Apol_Widget::appendSearchResultRules $widgets(results) 4 $te_true_vector qpol_terule_from_void
+ } else {
+ set syn_avrules [apol_avrule_list_to_syn_avrules $::ApolTop::policy $av_true_vector NULL]
+ Apol_Widget::appendSearchResultSynRules $widgets(results) 4 $syn_avrules qpol_syn_avrule_from_void
+ set syn_terules [apol_terule_list_to_syn_terules $::ApolTop::policy $te_true_vector]
+ Apol_Widget::appendSearchResultSynRules $widgets(results) 4 $syn_terules qpol_syn_terule_from_void
+ $syn_avrules -acquire
+ $syn_avrules -delete
+ $syn_terules -acquire
+ $syn_terules -delete
+ }
+
+ Apol_Widget::appendSearchResultText $widgets(results) "\nFALSE list:\n"
+ if {![ApolTop::is_capable "syntactic rules"]} {
+ apol_tcl_avrule_sort $::ApolTop::policy $av_false_vector
+ Apol_Widget::appendSearchResultRules $widgets(results) 4 $av_false_vector qpol_avrule_from_void
+ apol_tcl_terule_sort $::ApolTop::policy $te_false_vector
+ Apol_Widget::appendSearchResultRules $widgets(results) 4 $te_false_vector qpol_terule_from_void
+ } else {
+ set syn_avrules [apol_avrule_list_to_syn_avrules $::ApolTop::policy $av_false_vector NULL]
+ Apol_Widget::appendSearchResultSynRules $widgets(results) 4 $syn_avrules qpol_syn_avrule_from_void
+ set syn_terules [apol_terule_list_to_syn_terules $::ApolTop::policy $te_false_vector]
+ Apol_Widget::appendSearchResultSynRules $widgets(results) 4 $syn_terules qpol_syn_terule_from_void
+ $syn_avrules -acquire
+ $syn_avrules -delete
+ $syn_terules -acquire
+ $syn_terules -delete
+ }
+
+ $av_true_vector -acquire
+ $av_true_vector -delete
+ $av_false_vector -acquire
+ $av_false_vector -delete
+ $te_true_vector -acquire
+ $te_true_vector -delete
+ $te_false_vector -acquire
+ $te_false_vector -delete
+}
diff --git a/apol/context_dialog.tcl b/apol/context_dialog.tcl
new file mode 100644
index 0000000..2bc63bc
--- /dev/null
+++ b/apol/context_dialog.tcl
@@ -0,0 +1,340 @@
+# Copyright (C) 2005-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
+
+namespace eval Apol_Context_Dialog {
+ variable dialog ""
+ variable vars
+}
+
+# Create a dialog box to allow the user to select a single context
+# (user + role + type + level [if MLS]). This will return a 2-ple
+# list. The first is an apol_context_t; the caller must delete this
+# afterwards. Note that the context may be partially filled. The
+# second element is the attribute used to filter types; it may be an
+# empty string to indicate no filtering. If the dialog is cancelled
+# then return an empty list.
+proc Apol_Context_Dialog::getContext {{defaultContext {}} {defaultAttribute {}} {parent .}} {
+ variable dialog
+ variable vars
+
+ if {![winfo exists $dialog]} {
+ _create_dialog $parent
+ }
+
+ set user {}
+ set role {}
+ set type {}
+ set low_level {}
+ set high_level {}
+
+ # initialize widget states
+ array set vars [list $dialog:low_enable 0 $dialog:high_enable 0]
+ if {$defaultContext != {}} {
+ set user [$defaultContext get_user] #line causing segfault. most likely the entire $defaultContext doesn't exist
+ set role [$defaultContext get_role]
+ set type [$defaultContext get_type]
+ if {$defaultAttribute != {}} {
+ lappend type $defaultAttribute
+ }
+ set range [$defaultContext get_range]
+ if {$range != "NULL"} {
+ set low_level [$range get_low]
+ set high_level [$range get_high]
+ }
+ }
+
+ $vars($dialog:user_box) configure -values [Apol_Users::getUsers]
+ set vars($dialog:user) $user
+ if {$user == {}} {
+ set vars($dialog:user_enable) 0
+ } else {
+ set vars($dialog:user_enable) 1
+ }
+
+
+
+ $vars($dialog:role_box) configure -values [Apol_Roles::getRoles]
+ set vars($dialog:role) $role
+ if {$role == {}} {
+ set vars($dialog:role_enable) 0
+ } else {
+ set vars($dialog:role_enable) 1
+ }
+
+ Apol_Widget::resetTypeComboboxToPolicy $vars($dialog:type_box)
+ Apol_Widget::setTypeComboboxValue $vars($dialog:type_box) $type
+ if {$type == {}} {
+ set vars($dialog:type_enable) 0
+ } else {
+ set vars($dialog:type_enable) 1
+ }
+
+ Apol_Widget::resetLevelSelectorToPolicy $vars($dialog:low_level)
+ Apol_Widget::resetLevelSelectorToPolicy $vars($dialog:high_level)
+ if {[ApolTop::is_policy_open] && [ApolTop::is_capable "mls"]} {
+ if {$low_level != {}} {
+ set vars($dialog:low_enable) 1
+ Apol_Widget::setLevelSelectorLevel $vars($dialog:low_level) $low_level
+ }
+ if {$high_level != {} && $high_level != "NULL"} {
+ set vars($dialog:low_enable) 1
+ set vars($dialog:high_enable) 1
+ Apol_Widget::setLevelSelectorLevel $vars($dialog:high_level) $high_level
+ }
+ $vars($dialog:low_cb) configure -state normal
+ } else {
+ set vars($dialog:low_enable) 0
+ set vars($dialog:high_enable) 0
+ $vars($dialog:low_cb) configure -state disabled
+ }
+
+ # force a recomputation of button sizes (bug in ButtonBox)
+ $dialog.bbox _redraw
+ set retval [$dialog draw]
+ if {$retval == -1 || $retval == 1} {
+ return {}
+ }
+ set context [_get_context $dialog]
+ set attribute [lindex [Apol_Widget::getTypeComboboxValueAndAttrib $vars($dialog:type_box)] 1]
+ list $context $attribute
+}
+
+
+########## private functions below ##########
+
+proc Apol_Context_Dialog::_create_dialog {parent} {
+ variable dialog
+ variable vars
+
+ set dialog [Dialog .context_dialog -modal local -parent $parent \
+ -separator 1 -homogeneous 1 -title "Select Context"]
+ array unset vars $dialog:*
+
+
+ set f [$dialog getframe]
+ set left_f [frame $f.left]
+
+ set user_f [frame $left_f.user]
+ set vars($dialog:user_cb) [checkbutton $user_f.enable -text "User" \
+ -variable Apol_Context_Dialog::vars($dialog:user_enable)]
+ set vars($dialog:user_box) [ComboBox $user_f.user -entrybg white \
+ -width 12 \
+ -textvariable Apol_Context_Dialog::vars($dialog:user) \
+ -autopost 1]
+ trace add variable Apol_Context_Dialog::vars($dialog:user_enable) write \
+ [list Apol_Context_Dialog::_user_changed $dialog]
+ pack $vars($dialog:user_cb) -anchor nw
+ pack $vars($dialog:user_box) -anchor nw -padx 4 -expand 0 -fill x
+
+ set role_f [frame $left_f.role]
+ set vars($dialog:role_cb) [checkbutton $role_f.enable -text "Role" \
+ -variable Apol_Context_Dialog::vars($dialog:role_enable)]
+ set vars($dialog:role_box) [ComboBox $role_f.role -entrybg white -width 12 \
+ -textvariable Apol_Context_Dialog::vars($dialog:role) -autopost 1]
+ trace add variable Apol_Context_Dialog::vars($dialog:role_enable) write \
+ [list Apol_Context_Dialog::_role_changed $dialog]
+ pack $vars($dialog:role_cb) -anchor nw
+ pack $vars($dialog:role_box) -anchor nw -padx 4 -expand 0 -fill x
+
+ set type_f [frame $left_f.type]
+ set vars($dialog:type_cb) [checkbutton $type_f.enable -text "Type" \
+ -variable Apol_Context_Dialog::vars($dialog:type_enable)]
+ set vars($dialog:type_box) [Apol_Widget::makeTypeCombobox $type_f.type]
+ pack $vars($dialog:type_cb) -anchor nw
+ pack $vars($dialog:type_box) -anchor nw -padx 4 -expand 0 -fill x
+ trace add variable Apol_Context_Dialog::vars($dialog:type_enable) write \
+ [list Apol_Context_Dialog::_type_changed $dialog]
+ pack $user_f $role_f $type_f -side top -expand 1 -fill x
+
+ set mlsbox [TitleFrame $f.mlsbox -text "MLS Range"]
+ set mls_f [$mlsbox getframe]
+ set vars($dialog:low_cb) [checkbutton $mls_f.low_cb -text "Single Level" \
+ -variable Apol_Context_Dialog::vars($dialog:low_enable)]
+ set vars($dialog:low_level) [Apol_Widget::makeLevelSelector $mls_f.low 8]
+ trace add variable Apol_Context_Dialog::vars($dialog:low_enable) write \
+ [list Apol_Context_Dialog::_low_changed $dialog]
+ set vars($dialog:high_cb) [checkbutton $mls_f.high_cb \
+ -text "High Level" \
+ -variable Apol_Context_Dialog::vars($dialog:high_enable)]
+ set vars($dialog:high_level) [Apol_Widget::makeLevelSelector $mls_f.high 8]
+ trace add variable Apol_Context_Dialog::vars($dialog:high_enable) write \
+ [list Apol_Context_Dialog::_high_changed $dialog]
+ grid $vars($dialog:low_cb) $vars($dialog:high_cb) -sticky w
+ grid $vars($dialog:low_level) $vars($dialog:high_level) -sticky nsew
+ grid columnconfigure $mls_f 0 -weight 1 -uniform 1 -pad 2
+ grid columnconfigure $mls_f 1 -weight 1 -uniform 1 -pad 2
+ grid rowconfigure $mls_f 1 -weight 1
+
+ pack $left_f $mlsbox -side left -expand 1 -fill both
+
+ $dialog add -text "OK" -command [list Apol_Context_Dialog::_okay $dialog]
+ $dialog add -text "Cancel"
+}
+
+# For all options that have been enabled, ensure that the user also
+# selected a value. With those values, ensure that they are
+# authorized (user has the role, etc). For the MLS range, also check
+# that the level is legal by constructing a 'range' with it (as both
+# the low and high level).
+proc Apol_Context_Dialog::_okay {dialog} {
+ variable vars
+ set context [new_apol_context_t]
+ if {[ApolTop::is_policy_open]} {
+ set p $::ApolTop::policy
+ } else {
+ set p NULL
+ }
+
+ if {$vars($dialog:user_enable)} {
+ if {[set user $vars($dialog:user)] == {}} {
+ tk_messageBox -icon error -type ok -title "Could Not Validate Context" \
+ -message "No user was selected."
+ return
+ }
+ $context set_user $p $user
+ }
+ if {$vars($dialog:role_enable)} {
+ if {[set role $vars($dialog:role)] == {}} {
+ tk_messageBox -icon error -type ok -title "Could Not Validate Context" \
+ -message "No role was selected."
+ return
+ }
+ $context set_role $p $role
+ }
+ if {$vars($dialog:type_enable)} {
+ set type [lindex [Apol_Widget::getTypeComboboxValueAndAttrib $vars($dialog:type_box)] 0]
+ if {$type == {}} {
+ tk_messageBox -icon error -type ok -title "Could Not Validate Context" \
+ -message "No type was selected."
+ return
+ }
+ $context set_type $p $type
+ }
+ if {$vars($dialog:low_enable)} {
+ set range [_get_range $dialog]
+ if {$range == {}} {
+ tk_messageBox -icon error -type ok -title "Could Not Validate Context" \
+ -message "No level was selected."
+ return
+ }
+ $context set_range $p $range
+ }
+ if {![ApolTop::is_policy_open] || [$context validate_partial $p] <= 0} {
+ tk_messageBox -icon error -type ok -title "Could Not Validate Context" \
+ -message "The selected context is not valid for the current policy."
+ return
+ } else {
+ $dialog enddialog 0
+ }
+ $context -acquire
+ $context -delete
+}
+
+proc Apol_Context_Dialog::_get_context {dialog} {
+ variable vars
+ set context [new_apol_context_t]
+ if {[ApolTop::is_policy_open]} {
+ set p $::ApolTop::policy
+ } else {
+ set p NULL
+ }
+ if {$vars($dialog:user_enable)} {
+ $context set_user $p $vars($dialog:user)
+ }
+ if {$vars($dialog:role_enable)} {
+ $context set_role $p $vars($dialog:role)
+ }
+ if {$vars($dialog:type_enable)} {
+ set type [lindex [Apol_Widget::getTypeComboboxValueAndAttrib $vars($dialog:type_box)] 0]
+ $context set_type $p $type
+ }
+ set range [_get_range $dialog]
+ if {$range != {}} {
+ $context set_range $p $range
+ }
+ return $context
+}
+
+proc Apol_Context_Dialog::_get_range {dialog} {
+ variable vars
+ if {!$vars($dialog:low_enable)} {
+ return {}
+ }
+ if {[ApolTop::is_policy_open]} {
+ set p $::ApolTop::policy
+ } else {
+ set p NULL
+ }
+ set range [new_apol_mls_range_t]
+ $range set_low $p [Apol_Widget::getLevelSelectorLevel $vars($dialog:low_level)]
+
+ if {$vars($dialog:high_enable)} {
+ $range set_high $p [Apol_Widget::getLevelSelectorLevel $vars($dialog:high_level)]
+ }
+ return $range
+}
+
+proc Apol_Context_Dialog::_user_changed {dialog name1 name2 op} {
+ variable vars
+ if {$vars($dialog:user_enable)} {
+ $vars($dialog:user_box) configure -state normal
+ } else {
+ $vars($dialog:user_box) configure -state disabled
+ }
+}
+
+proc Apol_Context_Dialog::_role_changed {dialog name1 name2 op} {
+ variable vars
+ if {$vars($dialog:role_enable)} {
+ $vars($dialog:role_box) configure -state normal
+ } else {
+ $vars($dialog:role_box) configure -state disabled
+ }
+}
+
+proc Apol_Context_Dialog::_type_changed {dialog name1 name2 op} {
+ variable vars
+ if {$vars($dialog:type_enable)} {
+ Apol_Widget::setTypeComboboxState $vars($dialog:type_box) 1
+ } else {
+ Apol_Widget::setTypeComboboxState $vars($dialog:type_box) 0
+ }
+}
+
+proc Apol_Context_Dialog::_low_changed {dialog name1 name2 op} {
+ variable vars
+ if {$vars($dialog:low_enable)} {
+ $vars($dialog:high_cb) configure -state normal
+ Apol_Widget::setLevelSelectorState $vars($dialog:low_level) 1
+ if {$vars($dialog:high_enable)} {
+ Apol_Widget::setLevelSelectorState $vars($dialog:high_level) 1
+ }
+ } else {
+ $vars($dialog:high_cb) configure -state disabled
+ Apol_Widget::setLevelSelectorState $vars($dialog:low_level) 0
+ Apol_Widget::setLevelSelectorState $vars($dialog:high_level) 0
+ }
+}
+
+proc Apol_Context_Dialog::_high_changed {dialog name1 name2 op} {
+ variable vars
+ if {$vars($dialog:high_enable)} {
+ $vars($dialog:low_cb) configure -text "Low Level"
+ Apol_Widget::setLevelSelectorState $vars($dialog:high_level) 1
+ } else {
+ $vars($dialog:low_cb) configure -text "Single Level"
+ Apol_Widget::setLevelSelectorState $vars($dialog:high_level) 0
+ }
+}
diff --git a/apol/context_selector.tcl b/apol/context_selector.tcl
new file mode 100644
index 0000000..d2b7e2a
--- /dev/null
+++ b/apol/context_selector.tcl
@@ -0,0 +1,150 @@
+# Copyright (C) 2001-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
+
+namespace eval Apol_Widget {
+ variable vars
+}
+
+# Creates a widget that lets the user select a context (user + role +
+# type + MLS range) and a range search type (exact, subset, superset).
+# If the second argument is not "" then add a checkbutton that
+# enables/disables the entire widget.
+proc Apol_Widget::makeContextSelector {path rangeMatchText {enableText "Context"} args} {
+ variable vars
+ array unset vars $path:*
+ set vars($path:context) {}
+ set vars($path:attribute) {}
+ set vars($path:context_rendered) {}
+ set vars($path:search_type) $::APOL_QUERY_EXACT
+
+ set f [frame $path]
+ set context_frame [frame $f.context]
+ set context2_frame [frame $f.context2]
+ pack $context_frame $context2_frame -side left -expand 0 -anchor nw
+
+ if {$enableText != {}} {
+ set vars($path:enable) 0
+ set context_cb [checkbutton $context_frame.enable -text $enableText \
+ -variable Apol_Widget::vars($path:enable)]
+ pack $context_cb -side top -expand 0 -anchor nw
+ trace add variable Apol_Widget::vars($path:enable) write [list Apol_Widget::_toggle_context_selector $path $context_cb]
+ }
+ set context_display [eval Entry $context_frame.display -textvariable Apol_Widget::vars($path:context_rendered) -width 26 -editable 0 $args]
+ set context_button [button $context_frame.button -text "Select Context..." -state disabled -command [list Apol_Widget::_show_context_dialog $path]]
+ trace add variable Apol_Widget::vars($path:context) write [list Apol_Widget::_update_context_display $path]
+ set vars($path:context) {} ;# this will invoke the display function
+ pack $context_display -side top -expand 1 -fill x -anchor nw
+ pack $context_button -side top -expand 0 -anchor ne
+ if {$enableText != {}} {
+ pack configure $context_display -padx 4
+ pack configure $context_button -padx 4
+ }
+
+ # range search type
+ set range_label [label $context2_frame.label -text "MLS range matching:" \
+ -state disabled]
+ set range_exact [radiobutton $context2_frame.exact -text "Exact matches" \
+ -state disabled -value $::APOL_QUERY_EXACT \
+ -variable Apol_Widget::vars($path:search_type)]
+ set range_subset [radiobutton $context2_frame.subset -text "$rangeMatchText containing range" \
+ -state disabled -value $::APOL_QUERY_SUB \
+ -variable Apol_Widget::vars($path:search_type)]
+ set range_superset [radiobutton $context2_frame.superset -text "$rangeMatchText within range" \
+ -state disabled -value $::APOL_QUERY_SUPER \
+ -variable Apol_Widget::vars($path:search_type)]
+ pack $range_label $range_exact $range_subset $range_superset \
+ -side top -expand 0 -anchor nw
+
+ return $f
+}
+
+proc Apol_Widget::setContextSelectorState {path newState} {
+ if {$newState == 0 || $newState == "disabled"} {
+ set new_state disabled
+ } else {
+ set new_state normal
+ }
+ foreach w {display button} {
+ $path.context.$w configure -state $new_state
+ }
+ if {![ApolTop::is_capable "mls"]} {
+ set new_state disabled
+ }
+ foreach w {label exact subset superset} {
+ $path.context2.$w configure -state $new_state
+ }
+}
+
+proc Apol_Widget::clearContextSelector {path} {
+ set Apol_Widget::vars($path:context) {}
+ set Apol_Widget::vars($path:attribute) {}
+ set Apol_Widget::vars($path:search_type) $::APOL_QUERY_EXACT
+ catch {set Apol_Widget::vars($path:enable) 0}
+}
+
+proc Apol_Widget::getContextSelectorState {path} {
+ return $Apol_Widget::vars($path:enable)
+}
+
+# Return the currently selected context and other stuff. This will be
+# a 3-ple list of:
+# <ol>
+# <li>The (possibly partial) context, an apol_context_t. The caller
+# must delete this afterwards.
+# <li>The MLS range search type, one of $::APOL_QUERY_EXACT or its like.
+# <li>If not an empty string, the attribute used to filter types.
+# </ol>
+proc Apol_Widget::getContextSelectorValue {path} {
+ variable vars
+ list $vars($path:context) $vars($path:search_type) $vars($path:attribute)
+}
+
+########## private functions below ##########
+
+proc Apol_Widget::_toggle_context_selector {path cb name1 name2 op} {
+ if {$Apol_Widget::vars($path:enable)} {
+ Apol_Widget::setContextSelectorState $path normal
+ } else {
+ Apol_Widget::setContextSelectorState $path disabled
+ }
+}
+
+proc Apol_Widget::_show_context_dialog {path} {
+ variable vars
+ $path.context.button configure -state disabled
+ set new_context [Apol_Context_Dialog::getContext $vars($path:context) $vars($path:attribute)]
+ if {$new_context != {}} {
+ set vars($path:context) [lindex $new_context 0]
+ set vars($path:attribute) [lindex $new_context 1]
+ }
+
+ $path.context.button configure -state normal
+ # the trace on this variable will trigger [_update_context_display] to execute
+}
+
+proc Apol_Widget::_update_context_display {path name1 name2 op} {
+ variable vars
+ set display $path.context.display
+ if {$vars($path:context) == {}} {
+ set context_str "*:*:*"
+ if {[ApolTop::is_policy_open] && [ApolTop::is_capable "mls"]} {
+ append context_str ":*"
+ }
+ } else {
+ set context_str [$vars($path:context) render $::ApolTop::policy]
+ }
+ set vars($path:context_rendered) $context_str
+ $display configure -helptext $vars($path:context_rendered)
+}
diff --git a/apol/directflow_module.tcl b/apol/directflow_module.tcl
new file mode 100644
index 0000000..61055ec
--- /dev/null
+++ b/apol/directflow_module.tcl
@@ -0,0 +1,582 @@
+# Copyright (C) 2003-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
+
+namespace eval Apol_Analysis_directflow {
+ variable vals
+ variable widgets
+ Apol_Analysis::registerAnalysis "Apol_Analysis_directflow" "Direct Information Flow"
+}
+
+proc Apol_Analysis_directflow::create {options_frame} {
+ variable vals
+ variable widgets
+
+ _reinitializeVals
+
+ set dir_tf [TitleFrame $options_frame.mode -text "Direction"]
+ pack $dir_tf -side left -padx 2 -pady 2 -expand 0 -fill y
+ set dir_in [radiobutton [$dir_tf getframe].in -text In \
+ -value $::APOL_INFOFLOW_IN \
+ -variable Apol_Analysis_directflow::vals(dir)]
+ set dir_out [radiobutton [$dir_tf getframe].out -text Out \
+ -value $::APOL_INFOFLOW_OUT \
+ -variable Apol_Analysis_directflow::vals(dir)]
+ set dir_either [radiobutton [$dir_tf getframe].either -text Either \
+ -value $::APOL_INFOFLOW_EITHER \
+ -variable Apol_Analysis_directflow::vals(dir)]
+ set dir_both [radiobutton [$dir_tf getframe].both -text Both \
+ -value $::APOL_INFOFLOW_BOTH \
+ -variable Apol_Analysis_directflow::vals(dir)]
+ pack $dir_in $dir_out $dir_either $dir_both -anchor w
+
+ set req_tf [TitleFrame $options_frame.req -text "Required Parameters"]
+ pack $req_tf -side left -padx 2 -pady 2 -expand 0 -fill y
+ set l [label [$req_tf getframe].l -text "Starting type"]
+ pack $l -anchor w
+ set widgets(type) [Apol_Widget::makeTypeCombobox [$req_tf getframe].type]
+ pack $widgets(type)
+
+ set filter_tf [TitleFrame $options_frame.filter -text "Optional Result Filters"]
+ pack $filter_tf -side left -padx 2 -pady 2 -expand 1 -fill both
+ set class_f [frame [$filter_tf getframe].class]
+ pack $class_f -side left -anchor nw
+ set class_enable [checkbutton $class_f.enable -text "Filter by object class" \
+ -variable Apol_Analysis_directflow::vals(classes:enable)]
+ pack $class_enable -anchor w
+ set widgets(classes) [Apol_Widget::makeScrolledListbox $class_f.classes \
+ -height 6 -width 24 \
+ -listvar Apol_Analysis_directflow::vals(classes:all_classes) \
+ -selectmode multiple -exportselection 0]
+ set classes_lb [Apol_Widget::getScrolledListbox $widgets(classes)]
+ bind $classes_lb <<ListboxSelect>> \
+ [list Apol_Analysis_directflow::_selectClassesListbox $classes_lb]
+ pack $widgets(classes) -padx 4 -expand 0 -fill both
+ trace add variable Apol_Analysis_directflow::vals(classes:enable) write \
+ Apol_Analysis_directflow::_toggleClasses
+ Apol_Widget::setScrolledListboxState $widgets(classes) disabled
+ set classes_bb [ButtonBox $class_f.bb -homogeneous 1 -spacing 4]
+ $classes_bb add -text "Include All" \
+ -command [list Apol_Analysis_directflow::_includeAll $classes_lb]
+ $classes_bb add -text "Exclude All" \
+ -command [list Apol_Analysis_directflow::_excludeAll $classes_lb]
+ pack $classes_bb -pady 4
+ set widgets(regexp) [Apol_Widget::makeRegexpEntry [$filter_tf getframe].end]
+ $widgets(regexp).cb configure -text "Filter result types using regular expression"
+ pack $widgets(regexp) -side left -anchor nw -padx 8
+}
+
+proc Apol_Analysis_directflow::open {} {
+ variable vals
+ variable widgets
+ Apol_Widget::resetTypeComboboxToPolicy $widgets(type)
+ set vals(classes:all_classes) [Apol_Class_Perms::getClasses]
+ set vals(classes:selected) $vals(classes:all_classes)
+ Apol_Widget::setScrolledListboxState $widgets(classes) normal
+ set classes_lb [Apol_Widget::getScrolledListbox $widgets(classes)]
+ $classes_lb selection set 0 end
+ _toggleClasses {} {} {}
+}
+
+proc Apol_Analysis_directflow::close {} {
+ variable widgets
+ _reinitializeVals
+ _reinitializeWidgets
+ Apol_Widget::clearTypeCombobox $widgets(type)
+}
+
+proc Apol_Analysis_directflow::getInfo {} {
+ return "This analysis generates the results of a Direct Information Flow
+analysis beginning from the starting type selected. The results of
+the analysis are presented in tree form with the root of the tree
+being the start point for the analysis.
+
+\nEach child node in the tree represents a type in the current policy
+for which there is a direct information flow to or from its parent
+node. If 'in' was selected then the information flow is from the
+child to the parent. If 'out' was selected then information flows
+from the parent to the child.
+
+\nThe results of the analysis may be optionally filtered by object class
+selection or an end type regular expression.
+
+\nNOTE: For any given generation, if the parent and the child are the
+same, the child cannot be opened. This avoids cyclic analyses.
+
+\nFor additional help on this topic select \"Information Flow Analysis\"
+from the help menu."
+}
+
+proc Apol_Analysis_directflow::newAnalysis {} {
+ if {[set rt [_checkParams]] != {}} {
+ return $rt
+ }
+ set results [_analyze]
+ set f [_createResultsDisplay]
+ _renderResults $f $results
+ $results -acquire
+ $results -delete
+ return {}
+}
+
+proc Apol_Analysis_directflow::updateAnalysis {f} {
+ if {[set rt [_checkParams]] != {}} {
+ return $rt
+ }
+ set results [_analyze]
+ _clearResultsDisplay $f
+ _renderResults $f $results
+ $results -acquire
+ $results -delete
+ return {}
+}
+
+proc Apol_Analysis_directflow::reset {} {
+ _reinitializeVals
+ _reinitializeWidgets
+}
+
+proc Apol_Analysis_directflow::switchTab {query_options} {
+ variable vals
+ variable widgets
+ array set vals $query_options
+ _reinitializeWidgets
+}
+
+proc Apol_Analysis_directflow::saveQuery {channel} {
+ variable vals
+ variable widgets
+ foreach {key value} [array get vals] {
+ puts $channel "$key $value"
+ }
+ set type [Apol_Widget::getTypeComboboxValueAndAttrib $widgets(type)]
+ puts $channel "type [lindex $type 0]"
+ puts $channel "type:attrib [lindex $type 1]"
+ set use_regexp [Apol_Widget::getRegexpEntryState $widgets(regexp)]
+ set regexp [Apol_Widget::getRegexpEntryValue $widgets(regexp)]
+ puts $channel "regexp:enable $use_regexp"
+ puts $channel "regexp $regexp"
+}
+
+proc Apol_Analysis_directflow::loadQuery {channel} {
+ variable vals
+
+ set classes {}
+ while {[gets $channel line] >= 0} {
+ set line [string trim $line]
+ # Skip empty lines and comments
+ if {$line == {} || [string index $line 0] == "#"} {
+ continue
+ }
+ set key {}
+ set value {}
+ regexp -line -- {^(\S+)( (.+))?} $line -> key --> value
+ switch -- $key {
+ classes:selected {
+ set classes $value
+ }
+ default {
+ set vals($key) $value
+ }
+ }
+ }
+
+ # fill in only classes found within the current policy
+ open
+
+ set vals(classes:selected) {}
+ foreach c $classes {
+ set i [lsearch [Apol_Class_Perms::getClasses] $c]
+ if {$i >= 0} {
+ lappend vals(classes:selected) $c
+ }
+ }
+ set vals(classes:selected) [lsort $vals(classes:selected)]
+ _reinitializeWidgets
+}
+
+proc Apol_Analysis_directflow::getTextWidget {tab} {
+ return [$tab.right getframe].res.tb
+}
+
+proc Apol_Analysis_directflow::appendResultsNodes {tree parent_node results} {
+ _createResultsNodes $tree $parent_node $results 0
+}
+
+#################### private functions below ####################
+
+proc Apol_Analysis_directflow::_reinitializeVals {} {
+ variable vals
+ set vals(dir) $::APOL_INFOFLOW_IN
+ array set vals {
+ type {} type:attrib {}
+
+ classes:enable 0
+ classes:selected {}
+
+ regexp:enable 0
+ regexp {}
+ }
+ set vals(classes:all_classes) [Apol_Class_Perms::getClasses]
+}
+
+proc Apol_Analysis_directflow::_reinitializeWidgets {} {
+ variable vals
+ variable widgets
+
+ if {$vals(type:attrib) != {}} {
+ Apol_Widget::setTypeComboboxValue $widgets(type) [list $vals(type) $vals(type:attrib)]
+ } else {
+ Apol_Widget::setTypeComboboxValue $widgets(type) $vals(type)
+ }
+ Apol_Widget::setRegexpEntryValue $widgets(regexp) $vals(regexp:enable) $vals(regexp)
+
+ Apol_Widget::setScrolledListboxState $widgets(classes) enabled
+ set classes_lb [Apol_Widget::getScrolledListbox $widgets(classes)]
+ $classes_lb selection clear 0 end
+ foreach c $vals(classes:selected) {
+ set i [lsearch $vals(classes:all_classes) $c]
+ $classes_lb selection set $i $i
+ }
+ _toggleClasses {} {} {}
+}
+
+proc Apol_Analysis_directflow::_toggleClasses {name1 name2 op} {
+ variable vals
+ variable widgets
+ if {$vals(classes:enable)} {
+ Apol_Widget::setScrolledListboxState $widgets(classes) enabled
+ } else {
+ Apol_Widget::setScrolledListboxState $widgets(classes) disabled
+ }
+}
+
+proc Apol_Analysis_directflow::_selectClassesListbox {lb} {
+ variable vals
+ for {set i 0} {$i < [$lb index end]} {incr i} {
+ set t [$lb get $i]
+ if {[$lb selection includes $i]} {
+ lappend vals(classes:selected) $t
+ } else {
+ if {[set j [lsearch $vals(classes:selected) $t]] >= 0} {
+ set vals(classes:selected) [lreplace $vals(classes:selected) $j $j]
+ }
+ }
+ }
+ set vals(classes:selected) [lsort -uniq $vals(classes:selected)]
+ focus $lb
+}
+
+proc Apol_Analysis_directflow::_includeAll {lb} {
+ variable vals
+ $lb selection set 0 end
+ set vals(classes:selected) $vals(classes:all_classes)
+}
+
+proc Apol_Analysis_directflow::_excludeAll {lb} {
+ variable vals
+ $lb selection clear 0 end
+ set vals(classes:selected) {}
+}
+
+#################### functions that do analyses ####################
+
+proc Apol_Analysis_directflow::_checkParams {} {
+ variable vals
+ variable widgets
+ if {![ApolTop::is_policy_open]} {
+ return "No current policy file is opened."
+ }
+ set type [Apol_Widget::getTypeComboboxValueAndAttrib $widgets(type)]
+ if {[lindex $type 0] == {}} {
+ return "No type was selected."
+ }
+ if {![Apol_Types::isTypeInPolicy [lindex $type 0]]} {
+ return "[lindex $type 0] is not a type within the policy."
+ }
+ set vals(type) [lindex $type 0]
+ set vals(type:attrib) [lindex $type 1]
+ set use_regexp [Apol_Widget::getRegexpEntryState $widgets(regexp)]
+ set regexp [Apol_Widget::getRegexpEntryValue $widgets(regexp)]
+ if {$use_regexp && $regexp == {}} {
+ return "No regular expression provided."
+ }
+ set vals(regexp:enable) $use_regexp
+ set vals(regexp) $regexp
+ if {$vals(classes:enable) && $vals(classes:selected) == {}} {
+ return "At least one object class must be included."
+ }
+
+ # if a permap is not loaded then load the default permap
+ if {![Apol_Perms_Map::is_pmap_loaded]} {
+ if {![ApolTop::openDefaultPermMap]} {
+ return "This analysis requires that a permission map is loaded."
+ }
+ apol_tcl_clear_info_string
+ }
+
+ return {} ;# all parameters passed, now ready to do search
+}
+
+proc Apol_Analysis_directflow::_analyze {} {
+ variable vals
+ set classes {}
+ if {$vals(classes:enable)} {
+ foreach c $vals(classes:selected) {
+ foreach p [Apol_Class_Perms::getPermsForClass $c] {
+ lappend classes $c $p
+ }
+ }
+ }
+ if {$vals(regexp:enable)} {
+ set regexp $vals(regexp)
+ } else {
+ set regexp {}
+ }
+
+ set q [new_apol_infoflow_analysis_t]
+ $q set_mode $::ApolTop::policy $::APOL_INFOFLOW_MODE_DIRECT
+ $q set_dir $::ApolTop::policy $vals(dir)
+ $q set_type $::ApolTop::policy $vals(type)
+ foreach {c p} $classes {
+ $q append_class_perm $::ApolTop::policy $c $p
+ }
+ $q set_result_regex $::ApolTop::policy $regexp
+ set results [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ return $results
+}
+
+proc Apol_Analysis_directflow::_analyzeMore {tree node} {
+ # disallow more analysis if this node is the same as its parent
+ set new_start [$tree itemcget $node -text]
+ if {[$tree itemcget [$tree parent $node] -text] == $new_start} {
+ return {}
+ }
+ set g [lindex [$tree itemcget top -data] 0]
+ $g do_more $::ApolTop::policy $new_start
+}
+
+################# functions that control analysis output #################
+
+proc Apol_Analysis_directflow::_createResultsDisplay {} {
+ variable vals
+
+ set f [Apol_Analysis::createResultTab "Direct Flow" [array get vals]]
+
+ set tree_tf [TitleFrame $f.left -text "Direct Information Flow Tree"]
+ pack $tree_tf -side left -expand 0 -fill y -padx 2 -pady 2
+ set sw [ScrolledWindow [$tree_tf getframe].sw -auto both]
+ set tree [Tree [$sw getframe].tree -width 24 -redraw 1 -borderwidth 0 \
+ -highlightthickness 0 -showlines 1 -padx 0 -bg white]
+ $sw setwidget $tree
+ pack $sw -expand 1 -fill both
+
+ set res_tf [TitleFrame $f.right -text "Direct Information Flow Results"]
+ pack $res_tf -side left -expand 1 -fill both -padx 2 -pady 2
+ set res [Apol_Widget::makeSearchResults [$res_tf getframe].res]
+ $res.tb tag configure title -font {Helvetica 14 bold}
+ $res.tb tag configure title_type -foreground blue -font {Helvetica 14 bold}
+ $res.tb tag configure subtitle -font {Helvetica 10 bold}
+ $res.tb tag configure subtitle_dir -foreground blue -font {Helvetica 10 bold}
+ pack $res -expand 1 -fill both
+
+ $tree configure -selectcommand [list Apol_Analysis_directflow::_treeSelect $res]
+ $tree configure -opencmd [list Apol_Analysis_directflow::_treeOpen $tree]
+ return $f
+}
+
+proc Apol_Analysis_directflow::_treeSelect {res tree node} {
+ if {$node != {}} {
+ $res.tb configure -state normal
+ $res.tb delete 0.0 end
+ set data [$tree itemcget $node -data]
+ if {[string index $node 0] == "x"} {
+ _renderResultsDirectFlow $res $tree $node [lindex $data 1]
+ } else {
+ # an informational node, whose data has already been rendered
+ eval $res.tb insert end [lindex $data 1]
+ }
+ $res.tb configure -state disabled
+ }
+}
+
+# perform additional direct infoflows if this node has not been
+# analyzed yet
+proc Apol_Analysis_directflow::_treeOpen {tree node} {
+ foreach {is_expanded results} [$tree itemcget $node -data] {break}
+ if {[string index $node 0] == "x" && !$is_expanded} {
+ Apol_Progress_Dialog::wait "Direct Information Flow Analysis" \
+ "Performing Direct Information Flow Analysis..." \
+ {
+ set new_results [_analyzeMore $tree $node]
+ # mark this node as having been expanded
+ $tree itemconfigure $node -data [list 1 $results]
+ if {$new_results != {}} {
+ _createResultsNodes $tree $node $new_results 1
+ $new_results -acquire
+ $new_results -delete
+ }
+ }
+ }
+}
+
+proc Apol_Analysis_directflow::_clearResultsDisplay {f} {
+ variable vals
+
+ set tree [[$f.left getframe].sw getframe].tree
+ set res [$f.right getframe].res
+ $tree delete [$tree nodes root]
+ Apol_Widget::clearSearchResults $res
+ Apol_Analysis::setResultTabCriteria [array get vals]
+}
+
+proc Apol_Analysis_directflow::_renderResults {f results} {
+ variable vals
+
+ set graph_handler [$results extract_graph]
+ $graph_handler -acquire ;# let Tcl's GC destroy graph when this tab closes
+ set results_list [$results extract_result_vector]
+
+ set tree [[$f.left getframe].sw getframe].tree
+ set res [$f.right getframe].res
+
+ $tree insert end root top -text $vals(type) -open 1 -drawcross auto
+ set top_text [_renderTopText]
+ $tree itemconfigure top -data [list $graph_handler $top_text]
+
+ _createResultsNodes $tree top $results_list 1
+ $tree selection set top
+ $tree opentree top 0
+ $tree see top
+
+ $results_list -acquire
+ $results_list -delete
+}
+
+proc Apol_Analysis_directflow::_renderTopText {} {
+ variable vals
+
+ set top_text [list "Direct Information Flow Analysis: Starting type: " title]
+ lappend top_text $vals(type) title_type \
+ "\n\n" title \
+ "This tab provides the results of a Direct Information Flow analysis
+beginning from the starting type selected above. The results of the
+analysis are presented in tree form with the root of the tree (this
+node) being the start point for the analysis.
+
+\nEach child node in the tree represents a type in the current policy
+for which there is a direct information flow to or from (depending on
+your selection above) its parent node.
+
+\nNOTE: For any given generation, if the parent and the child are the
+same, you cannot open the child. This avoids cyclic analyses."
+}
+
+# If do_expand is zero, then generate result nodes for only the first
+# target type of $results. This is needed by two types relationship
+# analysis.
+proc Apol_Analysis_directflow::_createResultsNodes {tree parent_node results do_expand} {
+ set all_targets {}
+ set info_list [infoflow_result_vector_to_list $results]
+ set results_processed 0
+ foreach r $info_list {
+ apol_tcl_set_info_string $::ApolTop::policy "Processing result $results_processed of [llength $info_list]"
+
+ if {$do_expand} {
+ set target [[$r get_end_type] get_name $::ApolTop::qpolicy]
+ } else {
+ set target [[[lindex $info_list 0] get_end_type] get_name $::ApolTop::qpolicy]
+ }
+ set flow_dir [$r get_dir]
+ set step0 [apol_infoflow_step_from_void [[$r get_steps] get_element 0]]
+ set rules [$step0 get_rules]
+
+ lappend all_targets $target
+ foreach r [avrule_vector_to_list $rules] {
+ set class [[$r get_object_class $::ApolTop::qpolicy] get_name $::ApolTop::qpolicy]
+ lappend classes($target) $class
+ lappend classes($target:$class) $r
+ }
+ set dir($target:$flow_dir) 1
+ incr results_processed
+ }
+
+ set all_targets [lsort -uniq $all_targets]
+ apol_tcl_set_info_string $::ApolTop::policy "Displaying [llength $all_targets] result(s)"
+ update idle
+
+ foreach t $all_targets {
+ if {[info exists dir(${t}:${::APOL_INFOFLOW_BOTH})] ||
+ ([info exists dir(${t}:${::APOL_INFOFLOW_IN})] &&
+ [info exists dir(${t}:${::APOL_INFOFLOW_OUT})])} {
+ set flow_dir "both"
+ } elseif {[info exists dir(${t}:${::APOL_INFOFLOW_IN})]} {
+ set flow_dir "in"
+ } else {
+ set flow_dir "out"
+ }
+ set rules {}
+ foreach c [lsort -uniq $classes($t)] {
+ lappend rules [list $c [lsort -uniq $classes($t:$c)]]
+ }
+ set data [list $flow_dir $rules]
+ $tree insert end $parent_node x\#auto -text $t -drawcross allways \
+ -data [list 0 $data]
+ }
+}
+
+proc Apol_Analysis_directflow::_renderResultsDirectFlow {res tree node data} {
+ set parent_name [$tree itemcget [$tree parent $node] -text]
+ set name [$tree itemcget $node -text]
+ foreach {flow_dir classes} $data {break}
+ switch -- $flow_dir {
+ both {
+ $res.tb insert end "Information flows both into and out of " title \
+ $parent_name title_type \
+ " from/to " title \
+ $name title_type
+ }
+ in {
+ $res.tb insert end "Information flows into " title \
+ $parent_name title_type \
+ " from " title \
+ $name title_type
+ }
+ out {
+ $res.tb insert end "Information flows out of " title \
+ $parent_name title_type \
+ " to " title \
+ $name title_type
+ }
+ }
+ $res.tb insert end "\n\n" title_type \
+ "Objects classes for " subtitle \
+ [string toupper $flow_dir] subtitle_dir \
+ " flows:\n" subtitle
+ foreach c $classes {
+ foreach {class_name rules} $c {break}
+ $res.tb insert end " " {} \
+ $class_name\n subtitle
+ set v [new_apol_vector_t]
+ foreach r $rules {
+ $v append $r
+ }
+ apol_tcl_avrule_sort $::ApolTop::policy $v
+ Apol_Widget::appendSearchResultRules $res 12 $v qpol_avrule_from_void
+ $v -acquire
+ $v -delete
+ }
+}
diff --git a/apol/domaintrans_help.txt b/apol/domaintrans_help.txt
new file mode 100644
index 0000000..5f0666a
--- /dev/null
+++ b/apol/domaintrans_help.txt
@@ -0,0 +1,141 @@
+An overview of domain transition analysis
+
+
+A key feature of Type Enforcement (TE) security is the ability to
+define domain types with which programs run, use that domain type to
+control access to objects (which are also typed), and strictly control
+the ability of a process to change its domain type. This last ability
+is known as domain transition.
+
+Apol supports analysis of an SELinux policy to understand the domain
+transitions it allows. As with all access in SELinux, the ability to
+transition from one domain to another is controlled by 'allow' rules
+in the policy. Below, we describe how apol performs a domain
+transition analysis.
+
+
+The three types of interest for domain transitions
+--------------------------------------------------
+When discussing domain transition access, there are three different
+types we must consider:
+
+ + SOURCE TYPE: This is the domain type associated with a process
+ that is trying to change (transition) its domain type to another
+ type.
+
+ + TARGET TYPE: This is the domain type to which the source type is
+ trying to transition.
+
+ + FILE TYPE (ENTRYPOINT TYPE): This is a type associated with an
+ executable file object that allows the target type to be entered
+ as part of an execve() system call.
+
+
+Forward vs. reverse domain transition analysis
+----------------------------------------------
+Apol supports both forward and reverse domain transition analysis. A
+forward analysis determines all the TARGET types to which the selected
+SOURCE types may transition. The results may be further filtered by
+selecting particular object classes, permissions, and object types to
+find transitions to domains that have those specific privileges or
+that have access to a particular object type(s). A reverse analysis
+is the opposite; select a TARGET type and determine all the SOURCE
+types that may transition to the target type.
+
+In each case, apol creates a tree structure to show the result. Drill
+down the tree to follow any given transition path.
+
+
+Criteria for identifying allow domain transitions
+-------------------------------------------------
+In SELinux, three types of access (and hence at least three rules)
+must be allowed by the policy for a domain transition to occur. These
+three access types form the criteria used by apol to determine allowed
+transitions.
+
+Given an understanding of the three types of interest in a domain
+transition, the criteria for an allowed domain transition are as
+follows. In the examples below, assume 'user_t' is the source type,
+'passwd_t' is the target type, and 'passwd_exec_t' is the file entry
+point type.
+
+ 1. A rule must exist that allows the SOURCE domain type 'transition'
+ access for 'process' object class for the TARGET domain type. For
+ example, the rule:
+
+ allow user_t passwd_t : process transition;
+
+ meets this criterion by allowing the source type (user_t) 'process
+ transition' permission to the target type (passwd_t).
+
+ 2. A rule must exist that allows the SOURCE domain type 'execute'
+ access to the FILE ENTRYPOINT type. For example, the rule:
+
+ allow user_t passwd_exec_t : file {read getattr execute};
+
+ meets the criterion by allowing the source type (user_t) 'execute'
+ access to the file entrypoint type (passwd_exec_t).
+
+ 3. A rule must exist that allows the TARGET domain type 'entrypoint'
+ access to the FILE ENTRYPOINT type for file objects. For
+ example, the rule:
+
+ allow passwd_t passwd_exec_t : file entrypoint;
+
+ meets this criterion by allowing the target type (passwd_t) 'file
+ entrypoint' access to the file entrypoint type (passwd_exec_t).
+
+ 4. There must be a way for the transition to be specified. Typically
+ this is accomplished in the policy with a TYPE TRANSITION statement.
+ For example, the statement:
+
+ type_transition user_t password_exec_t : process passwd_t;
+
+ meets this criterion by specifying that when user_t executes
+ a program with the passwd_exec_t type, the default type of the
+ new process is passwd_t. This is the most common specifier because
+ it does not require the programs to be SELinux-aware. Alternatively,
+ the program can be made SELinux-aware and the program itself may
+ specify the type of the new process. For example, the statement:
+
+ allow user_t self : process setexec;
+
+ allows the source type (user_t) to specify the type of new processes
+ when executing programs. In both the type transition and setexec
+ cases, the types that the source domain may transition to are
+ limited by the previous three criterion.
+
+In the analysis results for a reverse domain transition analysis, apol
+will list all the types that meet the above four criteria. On the
+other hand, results for a forward domain transition analysis will be
+limited to types that meet the above four criteria and that have the
+specified privileges or access to a particular object type(s). See
+'General Help' for the Forward DTA Advanced Search Options feature in
+apol.
+
+
+Filtering domain transition results in apol
+-------------------------------------------
+The domain transition analysis interface in apol provides the ability
+to further refine a domain transition query in order to find
+transitions to a specific domain and/or transitions to domains that
+are granted specific access to object types or classes. Filtering
+results types using regular expressions is enabled for both forward
+and reverse domain transition queries; however, the access filters are
+only enabled for a forward domain transition query.
+
+To enable and use the access filters, select the "Use access filters"
+checkbox and display the Access Filters dialog. This dialog presents
+listboxes for including object types, object classes, and permissions.
+An access filter may be particulary useful to a user searching for
+transitions to domains that have specific access to an object type
+and/or class. For example, one could determine whether the type
+user_t is allowed to transition to a domain that can write a file of
+type shadow_t. To run this query from apol, specify the starting type
+as user_t, go to the Access Filters dialog, select shadow_t in the
+included object types listbox, select 'file' from the object classes
+listbox and then select the 'write' permission. If multiple types,
+classes, or permissions are selected, the results will include all
+transitions to a domain with access to at least one of the selected
+types for at least one of the selected classes with at least one of
+the selected permissions.
diff --git a/apol/domaintrans_module.tcl b/apol/domaintrans_module.tcl
new file mode 100644
index 0000000..ea1d471
--- /dev/null
+++ b/apol/domaintrans_module.tcl
@@ -0,0 +1,999 @@
+# Copyright (C) 2003-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
+
+namespace eval Apol_Analysis_domaintrans {
+ variable vals
+ variable widgets
+ Apol_Analysis::registerAnalysis "Apol_Analysis_domaintrans" "Domain Transition"
+}
+
+proc Apol_Analysis_domaintrans::create {options_frame} {
+ variable vals
+ variable widgets
+
+ _reinitializeVals
+
+ set dir_tf [TitleFrame $options_frame.dir -text "Direction"]
+ pack $dir_tf -side left -padx 2 -pady 2 -expand 0 -fill y
+ set dir_forward [radiobutton [$dir_tf getframe].forward -text "Forward" \
+ -variable Apol_Analysis_domaintrans::vals(dir) \
+ -value $::APOL_DOMAIN_TRANS_DIRECTION_FORWARD]
+ set dir_reverse [radiobutton [$dir_tf getframe].reverse -text "Reverse" \
+ -variable Apol_Analysis_domaintrans::vals(dir) \
+ -value $::APOL_DOMAIN_TRANS_DIRECTION_REVERSE]
+ pack $dir_forward $dir_reverse -anchor w
+ trace add variable Apol_Analysis_domaintrans::vals(dir) write \
+ Apol_Analysis_domaintrans::_toggleDirection
+
+ set req_tf [TitleFrame $options_frame.req -text "Required Parameters"]
+ pack $req_tf -side left -padx 2 -pady 2 -expand 0 -fill y
+ set l [label [$req_tf getframe].l -textvariable Apol_Analysis_domaintrans::vals(type:label)]
+ pack $l -anchor w
+ set widgets(type) [Apol_Widget::makeTypeCombobox [$req_tf getframe].type]
+ pack $widgets(type)
+
+ set filter_tf [TitleFrame $options_frame.filter -text "Optional Result Filters"]
+ pack $filter_tf -side left -padx 2 -pady 2 -expand 1 -fill both
+ set access_f [frame [$filter_tf getframe].access]
+ pack $access_f -side left -anchor nw
+ set widgets(access_enable) [checkbutton $access_f.enable -text "Use access filters" \
+ -variable Apol_Analysis_domaintrans::vals(access:enable)]
+ pack $widgets(access_enable) -anchor w
+ set widgets(access) [button $access_f.b -text "Access Filters" \
+ -command Apol_Analysis_domaintrans::_createAccessDialog \
+ -state disabled]
+ pack $widgets(access) -anchor w -padx 4
+ trace add variable Apol_Analysis_domaintrans::vals(access:enable) write \
+ Apol_Analysis_domaintrans::_toggleAccessSelected
+ set widgets(regexp) [Apol_Widget::makeRegexpEntry [$filter_tf getframe].end]
+ $widgets(regexp).cb configure -text "Filter result types using regular expression"
+ pack $widgets(regexp) -side left -anchor nw -padx 8
+}
+
+proc Apol_Analysis_domaintrans::open {} {
+ variable vals
+ variable widgets
+ Apol_Widget::resetTypeComboboxToPolicy $widgets(type)
+ set vals(targets:inc) [Apol_Types::getTypes]
+ set vals(targets:inc_displayed) [Apol_Types::getTypes]
+ foreach c [Apol_Class_Perms::getClasses] {
+ set vals(classes:$c) [Apol_Class_Perms::getPermsForClass $c]
+ set vals(classes:$c:enable) 1
+ }
+}
+
+proc Apol_Analysis_domaintrans::close {} {
+ variable widgets
+ _reinitializeVals
+ _reinitializeWidgets
+ Apol_Widget::clearTypeCombobox $widgets(type)
+}
+
+proc Apol_Analysis_domaintrans::getInfo {} {
+ return "A forward domain transition analysis will determine all (target)
+domains to which a given (source) domain may transition. For a
+forward domain transition to be allowed, multiple forms of access must
+be granted:
+
+\n (1) source domain must have process transition permission for
+ target domain,
+ (2) source domain must have file execute permission for some
+ entrypoint type,
+ (3) target domain must have file entrypoint permission for the
+ same entrypoint type, and,
+ (4) for policies version 15 or later, either a type_transition
+ rule or a setexec permission for the source domain.
+
+\nA reverse domain transition analysis will determine all (source)
+domains that can transition to a given (target) domain. For a reverse
+domain transition to be allowed, three forms of access must be
+granted:
+
+\n (1) target domain must have process transition permission from the
+ source domain,
+ (2) target domain must have file entrypoint permission to some
+ entrypoint type, and
+ (3) source domain must have file execute permission to the same
+ entrypoint type.
+
+\nThe results are presented in tree form. Open target children domains
+to perform another domain transition analysis on that domain.
+
+\nFor additional help on this topic select \"Domain Transition Analysis\"
+from the Help menu."
+}
+
+proc Apol_Analysis_domaintrans::newAnalysis {} {
+ if {[set rt [_checkParams]] != {}} {
+ return $rt
+ }
+ set results [_analyze]
+ set f [_createResultsDisplay]
+ _renderResults $f $results
+ $results -acquire
+ $results -delete
+ return {}
+}
+
+proc Apol_Analysis_domaintrans::updateAnalysis {f} {
+ variable vals
+
+ if {[set rt [_checkParams]] != {}} {
+ return $rt
+ }
+
+ if {$vals(dir) == $::APOL_DOMAIN_TRANS_DIRECTION_FORWARD} {
+ $f.left configure -text "Forward Domain Transition"
+ } else {
+ $f.left configure -text "Reverse Domain Transition"
+ }
+
+ set results [_analyze]
+ _clearResultsDisplay $f
+ _renderResults $f $results
+ $results -acquire
+ $results -delete
+ return {}
+}
+
+proc Apol_Analysis_domaintrans::reset {} {
+ _reinitializeVals
+ _reinitializeWidgets
+}
+
+proc Apol_Analysis_domaintrans::switchTab {query_options} {
+ variable vals
+ variable widgets
+ array set vals $query_options
+ if {$vals(type:attrib) != {}} {
+ Apol_Widget::setTypeComboboxValue $widgets(type) [list $vals(type) $vals(type:attrib)]
+ } else {
+ Apol_Widget::setTypeComboboxValue $widgets(type) $vals(type)
+ }
+ Apol_Widget::setRegexpEntryValue $widgets(regexp) $vals(regexp:enable) $vals(regexp)
+}
+
+proc Apol_Analysis_domaintrans::saveQuery {channel} {
+ variable vals
+ variable widgets
+ foreach {key value} [array get vals] {
+ switch -- $key {
+ targets:inc_displayed -
+ classes:perms_displayed -
+ search:regexp -
+ search:object_types -
+ search:classperm_perms {
+ # don't save these variables
+ }
+ default {
+ puts $channel "$key $value"
+ }
+ }
+ }
+ set type [Apol_Widget::getTypeComboboxValueAndAttrib $widgets(type)]
+ puts $channel "type [lindex $type 0]"
+ puts $channel "type:attrib [lindex $type 1]"
+ set use_regexp [Apol_Widget::getRegexpEntryState $widgets(regexp)]
+ set regexp [Apol_Widget::getRegexpEntryValue $widgets(regexp)]
+ puts $channel "regexp:enable $use_regexp"
+ puts $channel "regexp $regexp"
+}
+
+proc Apol_Analysis_domaintrans::loadQuery {channel} {
+ variable vals
+ set targets_inc {}
+ while {[gets $channel line] >= 0} {
+ set line [string trim $line]
+ # Skip empty lines and comments
+ if {$line == {} || [string index $line 0] == "#"} {
+ continue
+ }
+ set key {}
+ set value {}
+ regexp -line -- {^(\S+)( (.+))?} $line -> key --> value
+ if {$key == "targets:inc"} {
+ lappend targets_inc $value
+ } elseif {[regexp -- {^classes:(.+)} $key -> class]} {
+ set c($class) $value
+ } else {
+ set vals($key) $value
+ }
+ }
+
+ # fill in the inclusion lists using only types/classes found
+ # within the current policy
+ open
+
+ set vals(targets:inc) {}
+ foreach s $targets_inc {
+ set i [lsearch [Apol_Types::getTypes] $s]
+ if {$i >= 0} {
+ lappend vals(targets:inc) $s
+ }
+ }
+
+ foreach class_key [array names c] {
+ if {[regexp -- {^([^:]+):enable} $class_key -> class]} {
+ if {[lsearch [Apol_Class_Perms::getClasses] $class] >= 0} {
+ set vals(classes:$class:enable) $c($class_key)
+ }
+ } else {
+ set class $class_key
+ set old_p $vals(classes:$class)
+ set new_p {}
+ foreach p $c($class) {
+ if {[lsearch $old_p $p] >= 0} {
+ lappend new_p $p
+ }
+ }
+ set vals(classes:$class) [lsort -uniq $new_p]
+ }
+ }
+ _reinitializeWidgets
+}
+
+proc Apol_Analysis_domaintrans::getTextWidget {tab} {
+ return [$tab.right getframe].res.tb
+}
+
+proc Apol_Analysis_domaintrans::appendResultsNodes {tree parent_node results} {
+ _createResultsNodes $tree $parent_node $results $::APOL_DOMAIN_TRANS_DIRECTION_FORWARD
+}
+
+#################### private functions below ####################
+
+proc Apol_Analysis_domaintrans::_reinitializeVals {} {
+ variable vals
+
+ set vals(dir) $::APOL_DOMAIN_TRANS_DIRECTION_FORWARD
+ array set vals {
+ type:label "Source domain"
+ type {} type:attrib {}
+
+ regexp:enable 0
+ regexp {}
+
+ access:enable 0
+ targets:inc {} targets:inc_displayed {}
+ targets:attribenable 0 targets:attrb {}
+ }
+ array unset vals classes:*
+ array unset vals search:*
+ foreach c [Apol_Class_Perms::getClasses] {
+ set vals(classes:$c) [Apol_Class_Perms::getPermsForClass $c]
+ set vals(classes:$c:enable) 1
+ }
+}
+
+proc Apol_Analysis_domaintrans::_reinitializeWidgets {} {
+ variable vals
+ variable widgets
+
+ if {$vals(type:attrib) != {}} {
+ Apol_Widget::setTypeComboboxValue $widgets(type) [list $vals(type) $vals(type:attrib)]
+ } else {
+ Apol_Widget::setTypeComboboxValue $widgets(type) $vals(type)
+ }
+ Apol_Widget::setRegexpEntryValue $widgets(regexp) $vals(regexp:enable) $vals(regexp)
+}
+
+proc Apol_Analysis_domaintrans::_toggleDirection {name1 name2 op} {
+ variable vals
+ if {$vals(dir) == $::APOL_DOMAIN_TRANS_DIRECTION_FORWARD} {
+ set vals(type:label) "Source domain"
+ } else {
+ set vals(type:label) "Target domain"
+ }
+ _maybeEnableAccess
+}
+
+proc Apol_Analysis_domaintrans::_toggleAccessSelected {name1 name2 op} {
+ _maybeEnableAccess
+}
+
+proc Apol_Analysis_domaintrans::_maybeEnableAccess {} {
+ variable vals
+ variable widgets
+ if {$vals(dir) == $::APOL_DOMAIN_TRANS_DIRECTION_FORWARD} {
+ $widgets(access_enable) configure -state normal
+ if {$vals(access:enable)} {
+ $widgets(access) configure -state normal
+ } else {
+ $widgets(access) configure -state disabled
+ }
+ } else {
+ $widgets(access_enable) configure -state disabled
+ $widgets(access) configure -state disabled
+ }
+}
+
+################# functions that do access filters #################
+
+proc Apol_Analysis_domaintrans::_createAccessDialog {} {
+ variable widgets
+ $widgets(access) configure -state disabled
+ destroy .domaintrans_adv
+ set d [Dialog .domaintrans_adv -modal local -separator 1 -title "Domain Transition Access Filter" -parent .]
+ $d add -text "Close"
+ _createAccessTargets [$d getframe]
+ _createAccessClasses [$d getframe]
+ $d draw
+ $widgets(access) configure -state normal
+}
+
+proc Apol_Analysis_domaintrans::_createAccessTargets {f} {
+ variable vals
+
+ set type_f [frame $f.targets]
+ pack $type_f -side left -expand 0 -fill both -padx 4 -pady 4
+ set l1 [label $type_f.l1 -text "Included Object Types"]
+ pack $l1 -anchor w
+
+ set targets [Apol_Widget::makeScrolledListbox $type_f.targets -height 10 -width 24 \
+ -listvar Apol_Analysis_domaintrans::vals(targets:inc_displayed) \
+ -selectmode extended -exportselection 0]
+ set targets_lb [Apol_Widget::getScrolledListbox $targets]
+ bind $targets_lb <<ListboxSelect>> \
+ [list Apol_Analysis_domaintrans::_selectTargetListbox $targets_lb]
+ pack $targets -expand 0 -fill both
+
+ set bb [ButtonBox $type_f.bb -homogeneous 1 -spacing 4]
+ $bb add -text "Include All" \
+ -command [list Apol_Analysis_domaintrans::_includeAllItems $targets_lb targets]
+ $bb add -text "Ignore All" \
+ -command [list Apol_Analysis_domaintrans::_ignoreAllItems $targets_lb targets]
+ pack $bb -pady 4
+
+ set attrib [frame $type_f.a]
+ pack $attrib
+ set attrib_enable [checkbutton $attrib.ae -anchor w \
+ -text "Filter by attribute" \
+ -variable Apol_Analysis_domaintrans::vals(targets:attribenable)]
+ set attrib_box [ComboBox $attrib.ab -autopost 1 -entrybg white -width 16 \
+ -values $Apol_Types::attriblist \
+ -textvariable Apol_Analysis_domaintrans::vals(targets:attrib)]
+ $attrib_enable configure -command \
+ [list Apol_Analysis_domaintrans::_attribEnabled $attrib_box $targets_lb]
+ # remove any old traces on the attribute
+ trace remove variable Apol_Analysis_domaintrans::vals(targets:attrib) write \
+ [list Apol_Analysis_domaintrans::_attribChanged $targets_lb]
+ trace add variable Apol_Analysis_domaintrans::vals(targets:attrib) write \
+ [list Apol_Analysis_domaintrans::_attribChanged $targets_lb]
+ pack $attrib_enable -side top -expand 0 -fill x -anchor sw -padx 5 -pady 2
+ pack $attrib_box -side top -expand 1 -fill x -padx 10
+ _attribEnabled $attrib_box $targets_lb
+ if {[set anchor [lindex [lsort [$targets_lb curselection]] 0]] != {}} {
+ $targets_lb selection anchor $anchor
+ $targets_lb see $anchor
+ }
+}
+
+proc Apol_Analysis_domaintrans::_selectTargetListbox {lb} {
+ variable vals
+ for {set i 0} {$i < [$lb index end]} {incr i} {
+ set t [$lb get $i]
+ if {[$lb selection includes $i]} {
+ lappend vals(targets:inc) $t
+ } else {
+ if {[set j [lsearch $vals(targets:inc) $t]] >= 0} {
+ set vals(targets:inc) [lreplace $vals(targets:inc) $j $j]
+ }
+ }
+ }
+ set vals(targets:inc) [lsort -uniq $vals(targets:inc)]
+ focus $lb
+}
+
+proc Apol_Analysis_domaintrans::_includeAllItems {lb varname} {
+ variable vals
+ $lb selection set 0 end
+ set displayed [$lb get 0 end]
+ set vals($varname:inc) [lsort -uniq [concat $vals($varname:inc) $displayed]]
+}
+
+proc Apol_Analysis_domaintrans::_ignoreAllItems {lb varname} {
+ variable vals
+ $lb selection clear 0 end
+ set displayed [$lb get 0 end]
+ set inc {}
+ foreach t $vals($varname:inc) {
+ if {[lsearch $displayed $t] == -1} {
+ lappend inc $t
+ }
+ }
+ set vals($varname:inc) $inc
+}
+
+proc Apol_Analysis_domaintrans::_attribEnabled {cb lb} {
+ variable vals
+ if {$vals(targets:attribenable)} {
+ $cb configure -state normal
+ _filterTypeLists $vals(targets:attrib) $lb
+ } else {
+ $cb configure -state disabled
+ _filterTypeLists "" $lb
+ }
+}
+
+proc Apol_Analysis_domaintrans::_attribChanged {lb name1 name2 op} {
+ variable vals
+ if {$vals(targets:attribenable)} {
+ _filterTypeLists $vals(targets:attrib) $lb
+ }
+}
+
+proc Apol_Analysis_domaintrans::_filterTypeLists {attrib lb} {
+ variable vals
+ $lb selection clear 0 end
+ if {$attrib != ""} {
+ set vals(targets:inc_displayed) {}
+ set qpol_type_datum [new_qpol_type_t $::ApolTop::qpolicy $attrib]
+ set i [$qpol_type_datum get_type_iter $::ApolTop::qpolicy]
+ while {![$i end]} {
+ set t [qpol_type_from_void [$i get_item]]
+ lappend vals(targets:inc_displayed) [$t get_name $::ApolTop::qpolicy]
+ $i next
+ }
+ $i -acquire
+ $i -delete
+ set vals(targets:inc_displayed) [lsort $vals(targets:inc_displayed)]
+ } else {
+ set vals(targets:inc_displayed) [Apol_Types::getTypes]
+ }
+ foreach t $vals(targets:inc) {
+ if {[set i [lsearch $vals(targets:inc_displayed) $t]] >= 0} {
+ $lb selection set $i $i
+ }
+ }
+}
+
+proc Apol_Analysis_domaintrans::_createAccessClasses {f} {
+ variable vals
+ variable widgets
+
+ set lf [frame $f.left]
+ pack $lf -side left -expand 0 -fill both -padx 4 -pady 4
+ set l1 [label $lf.l -text "Included Object Classes"]
+ pack $l1 -anchor w
+ set rf [frame $f.right]
+ pack $rf -side left -expand 0 -fill both -padx 4 -pady 4
+ set l2 [label $rf.l]
+ pack $l2 -anchor w
+
+ set vals(classes:all_classes) [Apol_Class_Perms::getClasses]
+ set classes [Apol_Widget::makeScrolledListbox $lf.classes -height 10 -width 24 \
+ -listvar Apol_Analysis_domaintrans::vals(classes:all_classes) \
+ -selectmode extended -exportselection 0]
+ set classes_lb [Apol_Widget::getScrolledListbox $classes]
+ pack $classes -expand 1 -fill both
+ set cbb [ButtonBox $lf.cbb -homogeneous 1 -spacing 4]
+ $cbb add -text "Include All" \
+ -command [list Apol_Analysis_domaintrans::_includeAllClasses $classes_lb]
+ $cbb add -text "Ignore All" \
+ -command [list Apol_Analysis_domaintrans::_ignoreAllClasses $classes_lb]
+ pack $cbb -pady 4 -expand 0
+
+ set perms [Apol_Widget::makeScrolledListbox $rf.perms -height 10 -width 24 \
+ -listvar Apol_Analysis_domaintrans::vals(classes:perms_displayed) \
+ -selectmode extended -exportselection 0]
+ set perms_lb [Apol_Widget::getScrolledListbox $perms]
+ pack $perms -expand 1 -fill both
+ set pbb [ButtonBox $rf.pbb -homogeneous 1 -spacing 4]
+ $pbb add -text "Include All" \
+ -command [list Apol_Analysis_domaintrans::_includeAllPerms $classes_lb $perms_lb]
+ $pbb add -text "Ignore All" \
+ -command [list Apol_Analysis_domaintrans::_ignoreAllPerms $classes_lb $perms_lb]
+ pack $pbb -pady 4 -expand 0
+
+ bind $classes_lb <<ListboxSelect>> \
+ [list Apol_Analysis_domaintrans::_selectClassListbox $l2 $classes_lb $perms_lb]
+ bind $perms_lb <<ListboxSelect>> \
+ [list Apol_Analysis_domaintrans::_selectPermListbox $classes_lb $perms_lb]
+
+ foreach class_key [array names vals classes:*:enable] {
+ if {$vals($class_key)} {
+ regexp -- {^classes:([^:]+):enable} $class_key -> class
+ set i [lsearch [Apol_Class_Perms::getClasses] $class]
+ $classes_lb selection set $i $i
+ }
+ }
+ if {[set anchor [lindex [lsort [$classes_lb curselection]] 0]] != {}} {
+ $classes_lb selection anchor $anchor
+ $classes_lb see $anchor
+ }
+ set vals(classes:perms_displayed) {}
+ _selectClassListbox $l2 $classes_lb $perms_lb
+}
+
+proc Apol_Analysis_domaintrans::_selectClassListbox {perm_label lb plb} {
+ variable vals
+ for {set i 0} {$i < [$lb index end]} {incr i} {
+ set c [$lb get $i]
+ set vals(classes:$c:enable) [$lb selection includes $i]
+ }
+ if {[set class [$lb get anchor]] == {}} {
+ $perm_label configure -text "Permissions"
+ return
+ }
+
+ $perm_label configure -text "Permissions for $class"
+ set vals(classes:perms_displayed) [Apol_Class_Perms::getPermsForClass $class]
+ $plb selection clear 0 end
+ foreach p $vals(classes:$class) {
+ set i [lsearch $vals(classes:perms_displayed) $p]
+ $plb selection set $i
+ }
+ if {[set anchor [lindex [lsort [$plb curselection]] 0]] != {}} {
+ $plb selection anchor $anchor
+ $plb see $anchor
+ }
+ focus $lb
+}
+
+proc Apol_Analysis_domaintrans::_includeAllClasses {lb} {
+ variable vals
+ $lb selection set 0 end
+ foreach c [Apol_Class_Perms::getClasses] {
+ set vals(classes:$c:enable) 1
+ }
+}
+
+proc Apol_Analysis_domaintrans::_ignoreAllClasses {lb} {
+ variable vals
+ $lb selection clear 0 end
+ foreach c [Apol_Class_Perms::getClasses] {
+ set vals(classes:$c:enable) 0
+ }
+}
+
+proc Apol_Analysis_domaintrans::_selectPermListbox {lb plb} {
+ variable vals
+ set class [$lb get anchor]
+ set p {}
+ foreach i [$plb curselection] {
+ lappend p [$plb get $i]
+ }
+ set vals(classes:$class) $p
+ focus $plb
+}
+
+proc Apol_Analysis_domaintrans::_includeAllPerms {lb plb} {
+ variable vals
+ set class [$lb get anchor]
+ $plb selection set 0 end
+ set vals(classes:$class) $vals(classes:perms_displayed)
+}
+
+proc Apol_Analysis_domaintrans::_ignoreAllPerms {lb plb} {
+ variable vals
+ set class [$lb get anchor]
+ $plb selection clear 0 end
+ set vals(classes:$class) {}
+}
+
+#################### functions that do analyses ####################
+
+proc Apol_Analysis_domaintrans::_checkParams {} {
+ variable vals
+ variable widgets
+ if {![ApolTop::is_policy_open]} {
+ return "No current policy file is opened."
+ }
+ set type [Apol_Widget::getTypeComboboxValueAndAttrib $widgets(type)]
+ if {[lindex $type 0] == {}} {
+ return "No type was selected."
+ }
+ if {![Apol_Types::isTypeInPolicy [lindex $type 0]]} {
+ return "[lindex $type 0] is not a type within the policy."
+ }
+ set vals(type) [lindex $type 0]
+ set vals(type:attrib) [lindex $type 1]
+ set use_regexp [Apol_Widget::getRegexpEntryState $widgets(regexp)]
+ set regexp [Apol_Widget::getRegexpEntryValue $widgets(regexp)]
+ if {$use_regexp && $regexp == {}} {
+ return "No regular expression provided."
+ }
+ set vals(regexp:enable) $use_regexp
+ set vals(regexp) $regexp
+ if {$vals(dir) == $::APOL_DOMAIN_TRANS_DIRECTION_FORWARD && $vals(access:enable)} {
+ set classperm_pairs {}
+ foreach class [Apol_Class_Perms::getClasses] {
+ if {$vals(classes:$class:enable) == 0} {
+ continue
+ }
+ if {$vals(classes:$class) == {}} {
+ return "No permissions were selected for class $class."
+ }
+ foreach perm $vals(classes:$class) {
+ lappend classperm_pairs [list $class $perm]
+ }
+ }
+ if {$vals(targets:inc) == {}} {
+ return "No object types were selected."
+ }
+ if {$classperm_pairs == {}} {
+ return "No object classes were selected."
+ }
+ set vals(search:object_types) $vals(targets:inc)
+ set vals(search:classperm_pairs) $classperm_pairs
+ } else {
+ set vals(search:object_types) {}
+ set vals(search:classperm_pairs) {}
+ }
+ if {$vals(regexp:enable)} {
+ set vals(search:regexp) $vals(regexp)
+ } else {
+ set vals(search:regexp) {}
+ }
+ return {} ;# all parameters passed, now ready to do search
+}
+
+proc Apol_Analysis_domaintrans::_analyze {} {
+ variable vals
+ $::ApolTop::policy reset_domain_trans_table
+ set q [new_apol_domain_trans_analysis_t]
+ $q set_direction $::ApolTop::policy $vals(dir)
+ $q set_start_type $::ApolTop::policy $vals(type)
+ $q set_result_regex $::ApolTop::policy $vals(search:regexp)
+ foreach o $vals(search:object_types) {
+ $q append_access_type $::ApolTop::policy $o
+ }
+ foreach {cp_pair} $vals(search:classperm_pairs) {
+ $q append_class $::ApolTop::policy [lindex $cp_pair 0]
+ $q append_perm $::ApolTop::policy [lindex $cp_pair 1]
+ }
+ apol_tcl_set_info_string $::ApolTop::policy "Building domain transition table..."
+ $::ApolTop::policy build_domain_trans_table
+ apol_tcl_set_info_string $::ApolTop::policy "Performing Domain Transition Analysis..."
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ return $v
+}
+
+proc Apol_Analysis_domaintrans::_analyzeMore {tree node analysis_args} {
+ # disallow more analysis if this node is the same as its parent
+ set new_start [$tree itemcget $node -text]
+ if {[$tree itemcget [$tree parent $node] -text] == $new_start} {
+ return {}
+ }
+ foreach {dir orig_type object_types classperm_pairs regexp} $analysis_args {break}
+ set q [new_apol_domain_trans_analysis_t]
+ $q set_direction $::ApolTop::policy $dir
+ $q set_start_type $::ApolTop::policy $new_start
+ $q set_result_regex $::ApolTop::policy $regexp
+ foreach o $object_types {
+ $q append_access_type $::ApolTop::policy $o
+ }
+ foreach {cp_pair} $classperm_pairs {
+ $q append_class $::ApolTop::policy [lindex $cp_pair 0]
+ $q append_perm $::ApolTop::policy [lindex $cp_pair 1]
+ }
+ $::ApolTop::policy reset_domain_trans_table
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ return $v
+}
+
+################# functions that control analysis output #################
+
+proc Apol_Analysis_domaintrans::_createResultsDisplay {} {
+ variable vals
+
+ set f [Apol_Analysis::createResultTab "Domain Trans" [array get vals]]
+ if {$vals(dir) == $::APOL_DOMAIN_TRANS_DIRECTION_FORWARD} {
+ set tree_title "Forward Domain Transition"
+ } else {
+ set tree_title "Reverse Domain Transition"
+ }
+ set tree_tf [TitleFrame $f.left -text $tree_title]
+ pack $tree_tf -side left -expand 0 -fill y -padx 2 -pady 2
+ set sw [ScrolledWindow [$tree_tf getframe].sw -auto both]
+ set tree [Tree [$sw getframe].tree -width 24 -redraw 1 -borderwidth 0 \
+ -highlightthickness 0 -showlines 1 -padx 0 -bg white]
+ $sw setwidget $tree
+ pack $sw -expand 1 -fill both
+
+ set res_tf [TitleFrame $f.right -text "Domain Transition Results"]
+ pack $res_tf -side left -expand 1 -fill both -padx 2 -pady 2
+ set res [Apol_Widget::makeSearchResults [$res_tf getframe].res]
+ $res.tb tag configure title -font {Helvetica 14 bold}
+ $res.tb tag configure title_type -foreground blue -font {Helvetica 14 bold}
+ $res.tb tag configure subtitle -font {Helvetica 10 bold}
+ $res.tb tag configure num -foreground blue -font {Helvetica 10 bold}
+ pack $res -expand 1 -fill both
+
+ $tree configure -selectcommand [list Apol_Analysis_domaintrans::_treeSelect $res]
+ $tree configure -opencmd [list Apol_Analysis_domaintrans::_treeOpen $tree]
+ return $f
+}
+
+proc Apol_Analysis_domaintrans::_treeSelect {res tree node} {
+ if {$node != {}} {
+ $res.tb configure -state normal
+ $res.tb delete 0.0 end
+ set data [$tree itemcget $node -data]
+ if {[string index $node 0] == "f" || [string index $node 0] == "r"} {
+ _renderResultsDTA $res $tree $node [lindex $data 1]
+ } else {
+ # an informational node, whose data has already been rendered
+ eval $res.tb insert end $data
+ }
+ $res.tb configure -state disabled
+ }
+}
+
+# perform additional domain transitions if this node has not been
+# analyzed yet
+proc Apol_Analysis_domaintrans::_treeOpen {tree node} {
+ foreach {search_crit results} [$tree itemcget $node -data] {break}
+ if {([string index $node 0] == "f" || [string index $node 0] == "r") && $search_crit != {}} {
+ set new_results [Apol_Progress_Dialog::wait "Domain Transition Analysis" \
+ "Performing Domain Transition Analysis..." \
+ { _analyzeMore $tree $node $search_crit }]
+ # mark this node as having been expanded
+ $tree itemconfigure $node -data [list {} $results]
+ if {$new_results != {}} {
+ _createResultsNodes $tree $node $new_results $search_crit
+ $new_results -acquire
+ $new_results -delete
+ }
+ }
+}
+
+proc Apol_Analysis_domaintrans::_clearResultsDisplay {f} {
+ variable vals
+ set tree [[$f.left getframe].sw getframe].tree
+ set res [$f.right getframe].res
+ $tree delete [$tree nodes root]
+ Apol_Widget::clearSearchResults $res
+ Apol_Analysis::setResultTabCriteria [array get vals]
+}
+
+proc Apol_Analysis_domaintrans::_renderResults {f results} {
+ variable vals
+
+ set tree [[$f.left getframe].sw getframe].tree
+ set res [$f.right getframe].res
+
+ $tree insert end root top -text $vals(type) -open 1 -drawcross auto
+ set top_text [_renderTopText]
+ $tree itemconfigure top -data $top_text
+
+ set search_crit [list $vals(dir) $vals(type) $vals(search:object_types) $vals(search:classperm_pairs) $vals(search:regexp)]
+ _createResultsNodes $tree top $results $search_crit
+ $tree selection set top
+ $tree opentree top 0
+ $tree see top
+}
+
+proc Apol_Analysis_domaintrans::_renderTopText {} {
+ variable vals
+
+ if {$vals(dir) == $::APOL_DOMAIN_TRANS_DIRECTION_FORWARD} {
+ set top_text [list "Forward Domain Transition Analysis: Starting Type: " title]
+ } else {
+ set top_text [list "Reverse Domain Transition Analysis: Starting Type: " title]
+ }
+ lappend top_text $vals(type) title_type \
+ "\n\n" title
+ if {$vals(dir) == $::APOL_DOMAIN_TRANS_DIRECTION_FORWARD} {
+ lappend top_text \
+"This tab provides the results of a forward domain transition analysis
+starting from the source domain type above. The results of this
+analysis are presented in tree form with the root of the tree (this
+node) being the start point for the analysis.
+
+\nEach child node in the tree represents a TARGET DOMAIN TYPE. A target
+domain type is a domain to which the source domain may transition.
+You can follow the domain transition tree by opening each subsequent
+generation of children in the tree.\n" {}
+ } else {
+ lappend top_text \
+"This tab provides the results of a reverse domain transition analysis
+given the target domain type above. The results of this analysis are
+presented in tree form with the root of the tree (this node) being the
+target point of the analysis.
+
+\nEach child node in the tree represents a source DOMAIN TYPE. A source
+domain type is a domain that can transition to the target domain. You
+can follow the domain transition tree by opening each subsequent
+generation of children in the tree.\n" {}
+ }
+ lappend top_text \
+"\nNOTE: For any given generation, if the parent and the child are the
+same, you cannot open the child. This avoids cyclic analyses.
+
+\nThe criteria that defines an allowed domain transition are:
+
+\n1) There must be at least one rule that allows TRANSITION access for
+ PROCESS objects between the SOURCE and TARGET domain types.
+
+\n2) There must be at least one FILE TYPE that allows the TARGET type
+ ENTRYPOINT access for FILE objects.
+
+\n3) There must be at least one FILE TYPE that meets criterion 2) above
+ and allows the SOURCE type EXECUTE access for FILE objects.
+
+\n4) For modular policies and monolithic policies greater than version
+ 15, there must also be at least one of the following:
+ a) A type_transition rule for class PROCESS from SOURCE to TARGET
+ for FILE TYPE, or
+ b) A rule that allows SETEXEC for SOURCE to itself.
+
+\nThe information window shows all the rules and file types that meet
+these criteria for each target domain type." {}
+}
+
+proc Apol_Analysis_domaintrans::_createResultsNodes {tree parent_node results search_crit} {
+ set dir [lindex $search_crit 0]
+ set dt_list [domain_trans_result_vector_to_list $results]
+ set results_processed 0
+ foreach r $dt_list {
+ apol_tcl_set_info_string $::ApolTop::policy "Processing result $results_processed of [llength $dt_list]"
+ set source [[$r get_start_type] get_name $::ApolTop::qpolicy]
+ set target [[$r get_end_type] get_name $::ApolTop::qpolicy]
+ set intermed [[$r get_entrypoint_type] get_name $::ApolTop::qpolicy]
+ set proctrans [avrule_vector_to_list [$r get_proc_trans_rules]]
+ set entrypoint [avrule_vector_to_list [$r get_entrypoint_rules]]
+ set execute [avrule_vector_to_list [$r get_exec_rules]]
+ set setexec [avrule_vector_to_list [$r get_setexec_rules]]
+ set type_trans [terule_vector_to_list [$r get_type_trans_rules]]
+ set access_list [avrule_vector_to_list [$r get_access_rules]]
+ if {$dir == $::APOL_DOMAIN_TRANS_DIRECTION_FORWARD} {
+ set key $target
+ set node f:\#auto
+ } else {
+ set key $source
+ set node r:\#auto
+ }
+ foreach p $proctrans {
+ lappend types($key) $p
+ }
+ if {[info exists types($key:setexec)]} {
+ set types($key:setexec) [concat $types($key:setexec) $setexec]
+ } else {
+ set types($key:setexec) $setexec
+ }
+ lappend types($key:inter) $intermed
+ foreach e $entrypoint {
+ lappend types($key:inter:$intermed:entry) $e
+ }
+ foreach e $execute {
+ lappend types($key:inter:$intermed:exec) $e
+ }
+ if {[info exists types($key:inter:$intermed:type_trans)]} {
+ set types($key:inter:$intermed:type_trans) [concat $types($key:inter:$intermed:type_trans) $type_trans]
+ } else {
+ set types($key:inter:$intermed:type_trans) $type_trans
+ }
+ if {[info exists types($key:access)]} {
+ set types($key:access) [concat $types($key:access) $access_list]
+ } else {
+ set types($key:access) $access_list
+ }
+ incr results_processed
+ }
+ foreach key [lsort [array names types]] {
+ if {[string first : $key] != -1} {
+ continue
+ }
+ set ep {}
+ set proctrans [lsort -uniq $types($key)]
+ set setexec [lsort -uniq $types($key:setexec)]
+ foreach intermed [lsort -uniq $types($key:inter)] {
+ lappend ep [list $intermed \
+ [lsort -uniq $types($key:inter:$intermed:entry)] \
+ [lsort -uniq $types($key:inter:$intermed:exec)] \
+ [lsort -uniq $types($key:inter:$intermed:type_trans)]]
+ }
+ set access_list [lsort -uniq $types($key:access)]
+ set data [list $proctrans $setexec $ep $access_list]
+ $tree insert end $parent_node $node -text $key -drawcross allways \
+ -data [list $search_crit $data]
+ }
+}
+
+proc Apol_Analysis_domaintrans::_renderResultsDTA {res tree node data} {
+ set parent_name [$tree itemcget [$tree parent $node] -text]
+ set name [$tree itemcget $node -text]
+ foreach {proctrans setexec ep access_list} $data {break}
+ # direction of domain transition is encoded encoded in the node's
+ # identifier
+ if {[string index $node 0] == "f"} {
+ set header [list "Domain transition from " title \
+ $parent_name title_type \
+ " to " title \
+ $name title_type]
+ } else {
+ set header [list "Domain transition from " title \
+ $name title_type \
+ " to " title \
+ $parent_name title_type]
+ }
+ eval $res.tb insert end $header
+ $res.tb insert end "\n\n" title_type
+
+ $res.tb insert end "Process Transition Rules: " subtitle \
+ [llength $proctrans] num \
+ "\n" subtitle
+ set v [list_to_vector $proctrans]
+ apol_tcl_avrule_sort $::ApolTop::policy $v
+ Apol_Widget::appendSearchResultRules $res 6 $v qpol_avrule_from_void
+ $v -acquire
+ $v -delete
+ if {[llength $setexec] > 0} {
+ $res.tb insert end "\n" {} \
+ "Setexec Rules: " subtitle \
+ [llength $setexec] num \
+ "\n" subtitle
+ set v [list_to_vector $setexec]
+ apol_tcl_avrule_sort $::ApolTop::policy $v
+ Apol_Widget::appendSearchResultRules $res 6 $v qpol_avrule_from_void
+ $v -acquire
+ $v -delete
+ }
+
+ $res.tb insert end "\nEntry Point File Types: " subtitle \
+ [llength $ep] num
+ foreach e [lsort -index 0 $ep] {
+ foreach {intermed entrypoint execute type_trans} $e {break}
+ $res.tb insert end "\n $intermed\n" {} \
+ " " {} \
+ "File Entrypoint Rules: " subtitle \
+ [llength $entrypoint] num \
+ "\n" subtitle
+ set v [list_to_vector $entrypoint]
+ apol_tcl_avrule_sort $::ApolTop::policy $v
+ Apol_Widget::appendSearchResultRules $res 12 $v qpol_avrule_from_void
+ $v -acquire
+ $v -delete
+ $res.tb insert end "\n" {} \
+ " " {} \
+ "File Execute Rules: " subtitle \
+ [llength $execute] num \
+ "\n" subtitle
+ set v [list_to_vector $execute]
+ apol_tcl_avrule_sort $::ApolTop::policy $v
+ Apol_Widget::appendSearchResultRules $res 12 $v qpol_avrule_from_void
+ $v -acquire
+ $v -delete
+ if {[llength $type_trans] > 0} {
+ $res.tb insert end "\n" {} \
+ " " {} \
+ "Type_transition Rules: " subtitle \
+ [llength $type_trans] num \
+ "\n" subtitle
+ set v [list_to_vector $type_trans]
+ apol_tcl_terule_sort $::ApolTop::policy $v
+ Apol_Widget::appendSearchResultRules $res 12 $v qpol_terule_from_void
+ $v -acquire
+ $v -delete
+ }
+ }
+
+ if {[llength $access_list] > 0} {
+ $res.tb insert end "\n" {} \
+ "The access filters you specified returned the following rules: " subtitle \
+ [llength $access_list] num \
+ "\n" subtitle
+ set v [list_to_vector $access_list]
+ apol_tcl_avrule_sort $::ApolTop::policy $v
+ Apol_Widget::appendSearchResultRules $res 6 $v qpol_avrule_from_void
+ $v -acquire
+ $v -delete
+ }
+}
diff --git a/apol/file_contexts_tab.tcl b/apol/file_contexts_tab.tcl
new file mode 100644
index 0000000..55b9d73
--- /dev/null
+++ b/apol/file_contexts_tab.tcl
@@ -0,0 +1,504 @@
+# Copyright (C) 2001-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
+
+namespace eval Apol_File_Contexts {
+ variable opts
+ variable widgets
+
+ variable info_button_text \
+ "This tab allows the user to create and open a file context index.
+The file context index is an on-disk database which contains the
+labeling information for an entire filesystem. Once an index has been
+created it can then be queried by user, type, MLS range (if it
+contains MLS information), object class, and/or path.\n
+
+The result of the context query is a list of matching files, ordered
+by path. The first field is the full SELinux context, assuming that
+'Show SELinux file context' is enabled. If 'Show object class' is
+enabled, then the next field is the type of file that matched; this
+will be one of 'file', 'dir', and so forth. The remaining field is
+the full path to the file."
+}
+
+proc Apol_File_Contexts::create {tab_name nb} {
+ variable opts
+ variable widgets
+
+ _initializeVars
+
+ set frame [$nb insert end $tab_name -text "File Contexts"]
+ set status [TitleFrame $frame.status -text "File Context Index"]
+ set options [TitleFrame $frame.opts -text "Search Options"]
+ set results [TitleFrame $frame.results -text "Matching Files"]
+ pack $status $options -expand 0 -fill x -pady 2
+ pack $results -expand 1 -fill both -pady 2
+
+ # File Context Index frame
+ set status_frame [$status getframe]
+ set status_buttons [ButtonBox $status_frame.bb -homogeneous 1 -padx 2]
+ $status_buttons add -text "Create and Open" -command {Apol_File_Contexts::_create_dialog}
+ $status_buttons add -text "Open" -command {Apol_File_Contexts::_open_database}
+ pack $status_buttons -side left -anchor nw -padx 2 -pady 4
+
+ set status_text [frame $status_frame.t]
+ pack $status_text -side left -anchor nw -padx 6 -pady 4
+ label $status_text.l -text "Opened Index:"
+ set status1 [label $status_text.t -textvariable Apol_File_Contexts::opts(statusText)]
+ set status2 [label $status_text.t2 -textvariable Apol_File_Contexts::opts(statusText2) -fg red]
+ trace add variable Apol_File_Contexts::opts(indexFilename) write \
+ [list Apol_File_Contexts::_changeStatusLabel $status1 $status2]
+ grid $status_text.l $status1 -sticky w
+ grid x $status2 -sticky w -pady 2
+ pack $status -side top -expand 0 -fill x -pady 2 -padx 2
+ # invoke trace to set initial label text
+ set opts(indexFilename) $opts(indexFilename)
+
+ # Search options subframes
+ set options_frame [$options getframe]
+ set show_frame [frame $options_frame.show]
+ set user_frame [frame $options_frame.user]
+ set role_frame [frame $options_frame.role]
+ set type_frame [frame $options_frame.type]
+ set range_frame [frame $options_frame.range]
+ set objclass_frame [frame $options_frame.objclass]
+ set path_frame [frame $options_frame.path]
+ grid $show_frame $user_frame $role_frame $type_frame $range_frame $objclass_frame $path_frame \
+ -padx 2 -sticky news
+ foreach idx {1 2 3 4 5} {
+ grid columnconfigure $options_frame $idx -uniform 1 -weight 0
+ }
+ grid columnconfigure $options_frame 0 -weight 0 -pad 8
+ grid columnconfigure $options_frame 6 -weight 0
+
+ set use_regexp [checkbutton $show_frame.regexp \
+ -variable Apol_File_Contexts::opts(useRegexp) \
+ -text "Search using regular expression"]
+ set show_context [checkbutton $show_frame.context \
+ -variable Apol_File_Contexts::opts(showContext) \
+ -text "Show SELinux file context"]
+ set show_objclass [checkbutton $show_frame.objclass \
+ -variable Apol_File_Contexts::opts(showObjclass) \
+ -text "Show object class"]
+ pack $use_regexp $show_context $show_objclass -side top -anchor nw
+
+ checkbutton $user_frame.enable -text "User" \
+ -variable Apol_File_Contexts::opts(useUser)
+ set widgets(user) [entry $user_frame.e -width 12 \
+ -textvariable Apol_File_Contexts::opts(user)]
+ trace add variable Apol_File_Contexts::opts(useUser) write \
+ [list Apol_File_Contexts::_toggleEnable $widgets(user)]
+ pack $user_frame.enable -side top -anchor nw
+ pack $widgets(user) -side top -anchor nw -padx 4 -expand 0 -fill x
+
+ checkbutton $role_frame.enable -text "Role" \
+ -variable Apol_File_Contexts::opts(useRole)
+ set widgets(role) [entry $role_frame.e -width 12 \
+ -textvariable Apol_File_Contexts::opts(role)]
+ trace add variable Apol_File_Contexts::opts(useRole) write \
+ [list Apol_File_Contexts::_toggleEnable $widgets(role)]
+ pack $role_frame.enable -side top -anchor nw
+ pack $widgets(role) -side top -anchor nw -padx 4 -expand 0 -fill x
+
+ checkbutton $type_frame.enable -text "Type" \
+ -variable Apol_File_Contexts::opts(useType)
+ set widgets(type) [entry $type_frame.e -width 12 \
+ -textvariable Apol_File_Contexts::opts(type)]
+ trace add variable Apol_File_Contexts::opts(useType) write \
+ [list Apol_File_Contexts::_toggleEnable $widgets(type)]
+ pack $type_frame.enable -side top -anchor nw
+ pack $widgets(type) -side top -anchor nw -padx 4 -expand 0 -fill x
+
+ checkbutton $objclass_frame.enable -text "Object class" \
+ -variable Apol_File_Contexts::opts(useObjclass)
+ set widgets(objclass) [entry $objclass_frame.e -width 12 \
+ -textvariable Apol_File_Contexts::opts(objclass)]
+ trace add variable Apol_File_Contexts::opts(useObjclass) write \
+ [list Apol_File_Contexts::_toggleEnable $widgets(objclass)]
+ pack $objclass_frame.enable -side top -anchor nw
+ pack $widgets(objclass) -side top -anchor nw -padx 4 -expand 0 -fill x
+
+ set range_cb [checkbutton $range_frame.enable \
+ -variable Apol_File_Contexts::opts(useRange) -text "MLS range"]
+ set range_entry [entry $range_frame.e -width 12 \
+ -textvariable Apol_File_Contexts::opts(range)]
+ trace add variable Apol_File_Contexts::opts(useRange) write \
+ [list Apol_File_Contexts::_toggleEnable $range_entry]
+ trace add variable Apol_File_Contexts::opts(fc_is_mls) write \
+ [list Apol_File_Contexts::_toggleRange $range_cb $range_entry]
+ pack $range_cb -side top -anchor nw
+ pack $range_entry -side top -anchor nw -padx 4 -expand 0 -fill x
+
+ checkbutton $path_frame.enable \
+ -variable Apol_File_Contexts::opts(usePath) -text "File path"
+ set path_entry [entry $path_frame.path -width 24 \
+ -textvariable Apol_File_Contexts::opts(path)]
+ trace add variable Apol_File_Contexts::opts(usePath) write \
+ [list Apol_File_Contexts::_toggleEnable $path_entry]
+ pack $path_frame.enable -side top -anchor nw
+ pack $path_entry -side top -anchor nw -padx 4 -expand 0 -fill x
+
+ set bb [ButtonBox $options_frame.bb -orient vertical -homogeneous 1 -pady 2]
+ $bb add -text OK -width 6 -command {Apol_File_Contexts::_search}
+ $bb add -text Info -width 6 -command {Apol_File_Contexts::_show_info}
+ grid $bb -row 0 -column 7 -padx 5 -pady 5 -sticky ne
+ grid columnconfigure $options_frame 7 -weight 1
+
+ set widgets(results) [Apol_Widget::makeSearchResults [$results getframe].results]
+ pack $widgets(results) -expand yes -fill both
+
+ return $frame
+}
+
+proc Apol_File_Contexts::open {ppath} {
+ if {[is_db_loaded]} {
+ variable opts
+ $opts(db) associatePolicy $::ApolTop::policy
+ }
+}
+
+proc Apol_File_Contexts::close {} {
+ _close_database
+}
+
+proc Apol_File_Contexts::getTextWidget {} {
+ variable widgets
+ return $widgets(results).tb
+}
+
+proc Apol_File_Contexts::is_db_loaded {} {
+ variable opts
+ if {$opts(db) != {}} {
+ return 1
+ }
+ return 0
+}
+
+proc Apol_File_Contexts::get_fc_files_for_ta {which ta} {
+ set q [new_sefs_query]
+ if {$which == "type"} {
+ $q type $ta 0
+ } else {
+ $q type $ta 1
+ }
+ variable opts
+ if {[catch {Apol_Progress_Dialog::wait "File Contexts" "Searching database for $ta" \
+ {
+ $opts(db) runQuery $q
+ }} results]} {
+ tk_messageBox -icon error -type ok -title "File Contexts" -message $results
+ delete_sefs_query $q
+ return {}
+ }
+ delete_sefs_query $q
+ return $results
+}
+
+#### private functions below ####
+
+proc Apol_File_Contexts::_initializeVars {} {
+ variable opts
+ variable widgets
+
+ array set opts {
+ useUser 0 user {}
+ useRole 0 role {}
+ useType 0 type {}
+ useObjclass 0 objclass {}
+ useRange 0 range {}
+ usePath 0 path {}
+
+ useRegexp 0 showContext 1 showObjclass 1
+ db {}
+ fc_is_mls 1
+ indexFilename {}
+ }
+}
+
+proc Apol_File_Contexts::_show_info {} {
+ .mainframe.frame.nb.fApol_File_Contexts.opts.f.bb.b1 configure -state disabled
+ Apol_Widget::showPopupParagraph "File Contexts Information" $Apol_File_Contexts::info_button_text
+ .mainframe.frame.nb.fApol_File_Contexts.opts.f.bb.b1 configure -state normal
+}
+
+proc Apol_File_Contexts::_changeStatusLabel {label1 label2 name1 name2 opt} {
+ variable opts
+ if {$opts(db) == {}} {
+ set opts(statusText) "No Index File Opened"
+ $label1 configure -fg red
+ set opts(statusText2) {}
+ } else {
+ set opts(statusText) $opts(indexFilename)
+ $label1 configure -fg black
+ if {$opts(fc_is_mls)} {
+ set opts(statusText2) "Database contexts include MLS ranges."
+ $label2 configure -fg black
+ } else {
+ set opts(statusText2) "Database contexts do not include MLS ranges."
+ $label2 configure -fg red
+ }
+ }
+}
+
+proc Apol_File_Contexts::_toggleEnable {entry name1 name2 op} {
+ variable opts
+ if {$opts($name2)} {
+ $entry configure -state normal -bg white
+ } else {
+ $entry configure -state disabled -bg $ApolTop::default_bg_color
+ }
+}
+
+proc Apol_File_Contexts::_toggleRange {cb entry name1 name2 op} {
+ variable opts
+ if {$opts(fc_is_mls)} {
+ $cb configure -state normal
+ if {$opts(useRange)} {
+ $entry configure -state normal -bg white
+ }
+ } else {
+ $cb configure -state disabled
+ $entry configure -state disabled -bg $ApolTop::default_bg_color
+ }
+}
+
+proc Apol_File_Contexts::_create_dialog {} {
+ variable opts
+
+ set opts(new_filename) $opts(indexFilename)
+ set opts(new_rootdir) "/"
+
+ set d [Dialog .filecontexts_create -title "Create Index File" \
+ -default 0 -cancel 1 -modal local -parent . -separator 1]
+ $d add -text "OK" -command [list Apol_File_Contexts::_create_database $d] \
+ -state disabled
+ $d add -text "Cancel"
+
+ set f [$d getframe]
+ set file_l [label $f.file_l -justify left -anchor w -text "Save index to:"]
+ set file_entry [entry $f.file_e -width 30 -bg white -takefocus 1\
+ -textvariable Apol_File_Contexts::opts(new_filename) \
+ -validate key \
+ -vcmd [list Apol_File_Contexts::_validateEntryKey %P $d new_rootdir]]
+ focus $file_entry
+ set file_browse [button $f.file_b -text "Browse" -width 8 -takefocus 1 \
+ -command [list Apol_File_Contexts::_browse_save]]
+
+ set root_l [label $f.root_l -justify left -anchor w -text "Directory to index:"]
+ set root_entry [entry $f.root_e -width 30 -bg white -takefocus 1 \
+ -textvariable Apol_File_Contexts::opts(new_rootdir) \
+ -validate key \
+ -vcmd [list Apol_File_Contexts::_validateEntryKey %P $d new_filename]]
+ set root_browse [button $f.root_b -text "Browse" -width 8 -takefocus 1 \
+ -command [list Apol_File_Contexts::_browse_root]]
+
+ grid $file_l $file_entry $file_browse -padx 4 -pady 2 -sticky ew
+ grid $root_l $root_entry $root_browse -padx 4 -pady 2 -sticky ew
+ grid columnconfigure $f 0 -weight 0
+ grid columnconfigure $f 1 -weight 1
+ grid columnconfigure $f 2 -weight 0
+
+ $d draw
+ destroy $d
+}
+
+proc Apol_File_Contexts::_browse_save {} {
+ variable opts
+ set f [tk_getSaveFile -initialfile $opts(new_filename) \
+ -parent .filecontexts_create -title "Save Index"]
+ if {$f != {}} {
+ set opts(new_filename) $f
+ }
+}
+
+proc Apol_File_Contexts::_browse_root {} {
+ variable opts
+ set f [tk_chooseDirectory -initialdir $opts(new_rootdir) \
+ -parent .filecontexts_create -title "Directory to Index"]
+ if {$f != {}} {
+ set opts(new_rootdir) $f
+ }
+}
+
+proc Apol_File_Contexts::_validateEntryKey {newvalue dialog othervar} {
+ variable opts
+ if {$newvalue == {} || $opts($othervar) == {}} {
+ $dialog itemconfigure 0 -state disabled
+ } else {
+ $dialog itemconfigure 0 -state normal
+ }
+ return 1
+}
+
+proc Apol_File_Contexts::_create_database {dialog} {
+ variable opts
+
+ if {[catch {Apol_Progress_Dialog::wait "Create Database" "Scanning $opts(new_rootdir)" \
+ {
+ set db [apol_tcl_open_database_from_dir $opts(new_rootdir)]
+ $db save $opts(new_filename)
+ set db
+ } \
+ } db] || $db == "NULL"} {
+ tk_messageBox -icon error -type ok -title "Create Database" \
+ -message [apol_tcl_get_info_string]
+ return
+ }
+ if {$opts(db) != {}} {
+ delete_sefs_fclist $opts(db)
+ }
+ _initializeVars
+ set opts(db) $db
+ set opts(fc_is_mls) [$db isMLS]
+ set opts(indexFilename) $opts(new_filename)
+ if {[ApolTop::is_policy_open]} {
+ $opts(db) associatePolicy $::ApolTop::policy
+ }
+ $dialog enddialog {}
+}
+
+proc Apol_File_Contexts::_open_database {} {
+ variable opts
+
+ set f [tk_getOpenFile -initialfile $opts(indexFilename) -parent . \
+ -title "Open Database"]
+ if {$f == {}} {
+ return
+ }
+ if {[catch {Apol_Progress_Dialog::wait "Open Database" "Opening $f" \
+ {apol_tcl_open_database $f} \
+ } db] || $db == "NULL"} {
+ tk_messageBox -icon error -type ok -title "Open Database" \
+ -message [apol_tcl_get_info_string]
+ return
+ }
+
+ if {$opts(db) != {}} {
+ delete_sefs_fclist $opts(db)
+ }
+ _initializeVars
+ set opts(db) $db
+ set opts(fc_is_mls) [$db isMLS]
+ set opts(indexFilename) $f
+ if {[ApolTop::is_policy_open]} {
+ $opts(db) associatePolicy $::ApolTop::policy
+ }
+}
+
+proc Apol_File_Contexts::_search {} {
+ variable opts
+ variable widgets
+
+ if {$opts(db) == {}} {
+ tk_messageBox -icon error -type ok -title "File Contexts" -message "No database opened."
+ return
+ }
+ Apol_Widget::clearSearchResults $widgets(results)
+ if {$opts(useUser)} {
+ if {[set user $opts(user)] == {}} {
+ tk_messageBox -icon error -type ok -title "File Contexts" -message "No user selected."
+ return
+ }
+ } else {
+ set user {}
+ }
+ if {$opts(useRole)} {
+ if {[set role $opts(role)] == {}} {
+ tk_messageBox -icon error -type ok -title "File Contexts" -message "No user selected."
+ return
+ }
+ } else {
+ set role {}
+ }
+ if {$opts(useType)} {
+ if {[set type $opts(type)] == {}} {
+ tk_messageBox -icon error -type ok -title "File Contexts" -message "No type selected."
+ return
+ }
+ } else {
+ set type {}
+ }
+ if {$opts(fc_is_mls) && $opts(useRange)} {
+ if {[set range $opts(range)] == {}} {
+ tk_messageBox -icon error -type ok -title "File Contexts" -message "No MLS range selected."
+ return
+ }
+ } else {
+ set range {}
+ }
+ if {$opts(useObjclass)} {
+ if {[set objclass $opts(objclass)] == {}} {
+ tk_messageBox -icon error -type ok -title "File Contexts" -message "No object class selected."
+ return
+ }
+ } else {
+ set objclass {}
+ }
+ if {$opts(usePath)} {
+ if {[set path $opts(path)] == {}} {
+ tk_messageBox -icon error -type ok -title "File Contexts" -message "No path selected."
+ return
+ }
+ } else {
+ set path {}
+ }
+
+ set q [new_sefs_query]
+ $q user $user
+ $q role $role
+ $q type $type 0
+ $q range $range 0
+ $q objectClass $objclass
+ $q path $path
+ $q regex $opts(useRegexp)
+
+ if {[catch {Apol_Progress_Dialog::wait "File Contexts" "Searching database" \
+ {
+ set num_results [apol_tcl_query_database $opts(db) $q]
+ if {$num_results == 0} {
+ Apol_Widget::appendSearchResultText $widgets(results) "Search returned no results."
+ } else {
+ Apol_Widget::appendSearchResultHeader $widgets(results) "FILES FOUND ($num_results):\n\n"
+ }
+ }} err]} {
+ tk_messageBox -icon error -type ok -title "File Contexts" -message $err
+ }
+ delete_sefs_query $q
+}
+
+proc Apol_File_Contexts::_search_callback {entry} {
+ variable opts
+ variable widgets
+ set text {}
+ if {$opts(showContext)} {
+ set context [[$entry context] render NULL]
+ append text [format "%-40s" $context]
+ }
+ if {$opts(showObjclass)} {
+ set class [apol_objclass_to_str [$entry objectClass]]
+ append text [format " %-12s" $class]
+ }
+ append text " [$entry path]\n"
+ Apol_Widget::appendSearchResultText $widgets(results) $text
+}
+
+proc Apol_File_Contexts::_close_database {} {
+ variable opts
+ variable widgets
+ if {$opts(db) != {}} {
+ delete_sefs_fclist $opts(db)
+ }
+ _initializeVars
+ Apol_Widget::clearSearchResults $widgets(results)
+}
diff --git a/apol/file_relabel_help.txt b/apol/file_relabel_help.txt
new file mode 100644
index 0000000..39f26c6
--- /dev/null
+++ b/apol/file_relabel_help.txt
@@ -0,0 +1,68 @@
+An overview of direct file relabel analysis
+
+
+Understanding file relabel analysis
+-----------------------------------
+The permission to relabel objects in a mandatory access control system
+is an important privilege. In SELinux, this privilege is controlled
+by the relabelto and relabelfrom permissions. Understanding the net
+effect of these policy rules is complex because it requires the
+examination of multiple rules potentially spanning dozens of files.
+To be able to successfully relabel an object, a subject must be able
+to:
+
+ - relabelfrom the starting type
+ - relabelto at least one other type
+
+For example, consider the following rules:
+
+ allow sysadm_t filea_t : file relabelfrom;
+ allow sysadm_t { fileb_t filec_t } : file relabelto;
+
+If these rules are the only relabel rules present in the policy,
+sysadm_t would be allowed to relabel files of type filea_t to fileb_t
+or filec_t. Both a relabelfrom and a relabelto rule for a single
+subject must be present for a relabel to be possible.
+
+Determining the potential ending types to which a starting type can be
+relabeled requires examining all subjects for relabel rules from the
+starting type to one or more ending types. Determining the relabel
+privileges of a subject type requires examining all of the relabel
+rules containing the subject type. The direct file relabel analysis
+in apol automates both of these analyses.
+
+
+Using direct file relabel analysis in apol
+------------------------------------------
+Direct file relabel analysis is designed to facilitate querying a
+policy for both potential changes to object labels and relabel
+privileges granted to a subject. These two modes are respectively
+called Object Mode and Subject Mode.
+
+
+Object Mode
+-----------
+In Object Mode, the user specifies a starting or ending type and
+either to, from or both. When To is selected, all types to which the
+starting type can be relabeled will be displayed. When From is
+selected, all types from which the ending type can be relabeled will
+be displayed. If both options are selected, the analysis performs
+both.
+
+
+Subject Mode
+------------
+In Subject Mode, the user specifies only a subject type. Two lists of
+types will be displayed corresponding to all of the types to which the
+subject can relabel and from which the subject can relabel.
+
+
+Optional result filters
+-----------------------
+Results may be filtered in several ways. The end types resulting from
+a query may be filtered by regular expression. Advanced Filters
+provide the option of selecting which object classes to include in the
+analysis and which types to include as subjects of relabeling
+operations. The subject types filter is disabled in subject mode
+because all types are excluded as subjects except the type specified as
+the required parameter.
diff --git a/apol/find.tcl b/apol/find.tcl
new file mode 100644
index 0000000..f3cf5f5
--- /dev/null
+++ b/apol/find.tcl
@@ -0,0 +1,134 @@
+# Copyright (C) 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
+
+namespace eval Apol_Find {
+ variable dialog .apol_find_dialog
+ variable search_string {}
+ variable case_sensitive 0
+ variable enable_regexp 0
+ variable direction "down"
+}
+
+proc Apol_Find::find {} {
+ variable dialog
+ if {![winfo exists $dialog]} {
+ _create_dialog
+ } else {
+ raise $dialog
+ variable entry
+ focus $entry
+ $entry selection range 0 end
+ }
+}
+
+
+########## private functions below ##########
+
+proc Apol_Find::_create_dialog {} {
+ variable dialog
+ Dialog $dialog -title "Find" -separator 0 -parent . \
+ -side right -default 0 -cancel 1 -modal none -homogeneous 1
+ set top_frame [frame [$dialog getframe].top]
+ set bottom_frame [frame [$dialog getframe].bottom]
+ pack $top_frame -expand 1 -fill both -padx 10 -pady 5
+ pack $bottom_frame -expand 0 -fill both -padx 10 -pady 5
+
+ set entry_label [label $top_frame.l -text "Find:" -anchor e]
+ variable entry [entry $top_frame.e -bg white \
+ -textvariable Apol_Find::search_string -width 16]
+ pack $entry_label -side left -expand 0 -padx 10
+ pack $entry -side left -expand 1 -fill x
+
+ set options_frame [frame $bottom_frame.opts]
+ pack $options_frame -side left -padx 5
+ set options_case [checkbutton $options_frame.case -text "Match case" \
+ -variable Apol_Find::case_sensitive]
+ set options_regex [checkbutton $options_frame.regex -text "Regular expression" \
+ -variable Apol_Find::enable_regexp]
+ pack $options_case -anchor w
+ pack $options_regex -anchor w
+
+ set dir_frame [TitleFrame $bottom_frame.dir -text Direction]
+ pack $dir_frame -side left
+ set dir_up [radiobutton [$dir_frame getframe].up -text Up \
+ -variable Apol_Find::direction -value up]
+ set dir_down [radiobutton [$dir_frame getframe].down -text Down \
+ -variable Apol_Find::direction -value down]
+ pack $dir_up $dir_down -side left
+
+ $dialog add -text "Find Next" -command Apol_Find::_do_find
+ $dialog add -text "Cancel" -command [list destroy $dialog]
+
+ focus $entry
+ $dialog draw
+ wm resizable $dialog 0 0
+}
+
+proc Apol_Find::_do_find {} {
+ set w [ApolTop::getCurrentTextWidget]
+ if {$w == {}} {
+ return
+ }
+
+ variable search_string
+ variable case_sensitive
+ variable enable_regexp
+ variable direction
+
+ if {$search_string == {}} {
+ return
+ }
+
+ set opts {}
+ if {!$case_sensitive} {
+ lappend opts "-nocase"
+ }
+ if {$enable_regexp} {
+ lappend opts "-regexp"
+ }
+ if {$direction == "down"} {
+ lappend opts "-forward"
+ set start_pos [$w index insert]
+ } else {
+ lappend opts "-backward"
+ set start_pos [lindex [$w tag ranges sel] 0]
+ }
+ if {$start_pos == {}} {
+ set start_pos "1.0"
+ }
+
+ $w tag remove sel 0.0 end
+
+ variable dialog
+ if {[catch {eval $w search -count count $opts -- [list $search_string] $start_pos} pos]} {
+ tk_messageBox -parent $dialog -icon warning -type ok -title "Find" -message \
+ "Invalid regular expression."
+ return
+ }
+
+ if {$pos == {}} {
+ tk_messageBox -parent $dialog -icon warning -type ok -title "Find" -message \
+ "String not found."
+ } else {
+ if {$direction == "down"} {
+ $w mark set insert "$pos + $count char"
+ $w see "$pos + $count char"
+ } else {
+ $w mark set insert "$pos"
+ $w see $pos
+ }
+ $w tag add sel $pos "$pos + $count char"
+ }
+}
diff --git a/apol/foo_module.tcl b/apol/foo_module.tcl
new file mode 100644
index 0000000..2728267
--- /dev/null
+++ b/apol/foo_module.tcl
@@ -0,0 +1,143 @@
+# Copyright (C) 2003-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
+
+
+## This module is not a real analysis, but an example that serves as a
+## guide to what one must do when creating a module via embedded
+## comments. This file also serves as a template for when new
+## analysis modules are created. To include this module in apol, add
+## the file name to apol_SOURCES variable in Makefile.am.
+##
+## All this module does is display an entry box and echo the contents
+## of that box.
+
+## The name space should following the convention of Apol_Analysis_XXX, where
+## XXX is a 3-4 letter name for the analysis.
+namespace eval Apol_Analysis_foo {
+ variable vals
+ variable widgets
+
+## Within the namespace command for the module, you must call
+## Apol_Analysis::registerAnalysis. The first argument is the
+## namespace name of the module, second is the descriptive display name
+## you want to be displayed in the GUI selection box.
+ Apol_Analysis::registerAnalysis "Apol_Analysis_foo" "Analysis Template Example"
+}
+
+# Called when the tool first starts up. It is given a blank frame to
+# which create its search widgets.
+proc Apol_Analysis_foo::create {options_frame} {
+ variable vals
+ set vals(entry_string) {}
+ set l [label $options_frame.l -text "Enter Text:"]
+ set e [entry $options_frame.e -textvariable Apol_Analysis_foo::vals(entry_string) -width 25 -background white]
+ pack $l $e -side left -anchor w
+}
+
+# Called when a policy is opened.
+proc Apol_Analysis_foo::open {} {
+}
+
+# Called when a policy is closed. Typically you should reset any
+# context or option variables you have.
+proc Apol_Analysis_foo::close {} {
+ variable vals
+ set vals(entry_string) {}
+}
+
+# Return a string that describes what the module does. Do not forget
+# that during compilation, blank lines are stripped; thus \n may be
+# needed within the text.
+proc Apol_Analysis_foo::getInfo {} {
+ return "This is an analysis template dialog that simply displays the content
+of the entry box. The purpose of this analysis is to provide a
+template for new analyses."
+}
+
+# Perform a new analysis. This function is responsible for obtaining
+# a new results tab if the analysis succeeds. If the analysis was
+# successful then return an empty string; otherwise return a string
+# describing the error, removing its tab if it had made one.
+proc Apol_Analysis_foo::newAnalysis {} {
+ variable vals
+ if {$vals(entry_string) == "" } {
+ return "You must enter text in the entry box."
+ }
+ set f [Apol_Analysis::createResultTab "Foo" [array get vals]]
+ set results_box [text $f.results -bg white]
+ pack $results_box -expand yes -fill both
+ $results_box insert 0.0 "new analysis: $vals(entry_string)"
+ return
+}
+
+# Update an existing analysis. The passed in frame will contain the
+# existing results; it is this function's responsibility to clear away
+# old data and to store the current search criteria onto the tab. If
+# the analysis was successful then return an empty string; otherwise
+# return a string describing the error. On error Apol_Analysis will
+# remove its tab.
+proc Apol_Analysis_foo::updateAnalysis {f} {
+ variable vals
+ if {$vals(entry_string) == "" } {
+ return "You must enter text in the entry box."
+ }
+ Apol_Analysis::setResultTabCriteria [array get vals]
+ $f.results delete 0.0 end
+ $f.results insert 0.0 "updated analysis: $vals(entry_string)"
+ return
+}
+
+# Called whenever the user hits the reset criteria button.
+proc Apol_Analysis_foo::reset {} {
+ variable vals
+ set vals(entry_string) {}
+}
+
+# Called when the user switches to this tab. The module should
+# restore its search criteria to the values that were stored within
+# the tab.
+proc Apol_Analysis_foo::switchTab {query_options} {
+ variable vals
+ array set vals $query_options
+}
+
+# Called to save the current criteria to a file channel.
+proc Apol_Analysis_foo::saveQuery {channel} {
+ variable vals
+ foreach {key value} [array get vals] {
+ puts $channel "$key $value"
+ }
+}
+
+# Called to load a query from a file channel. The module then updates
+# its display to match the criteria.
+proc Apol_Analysis_foo::loadQuery {channel} {
+ variable vals
+ while {[gets $channel line] >= 0} {
+ set line [string trim $line]
+ # Skip empty lines and comments
+ if {$line == {} || [string index $line 0] == "#"} {
+ continue
+ }
+ regexp -line -- {^(\S+)( (.+))?} $line -> key --> value
+ set vals($key) $value
+ }
+}
+
+# Get a text widget that contains this analysis's results. This is
+# then passed to the find dialog, goto line dialog, and so forth.
+proc Apol_Analysis_foo::getTextWidget {tab} {
+ return $tab.results
+}
diff --git a/apol/fscontexts_tab.tcl b/apol/fscontexts_tab.tcl
new file mode 100644
index 0000000..47522c2
--- /dev/null
+++ b/apol/fscontexts_tab.tcl
@@ -0,0 +1,472 @@
+# Copyright (C) 2001-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
+
+namespace eval Apol_FSContexts {
+ variable widgets
+ variable vals
+}
+
+proc Apol_FSContexts::create {tab_name nb} {
+ variable widgets
+ variable vals
+
+ _initializeVars
+
+ # Layout frames
+ set frame [$nb insert end $tab_name -text "FS Contexts"]
+ set pw [PanedWindow $frame.pw -side top -weights extra]
+ set leftf [$pw add -weight 0]
+ set rightf [$pw add -weight 1]
+ pack $pw -fill both -expand yes
+
+ # build the left column, where one selects a particular type of
+ # context; below it will be a scrolled listbox of keys for that
+ # context
+ set context_box [TitleFrame $leftf.context_f -text "Context Type"]
+ set context_f [$context_box getframe]
+ radiobutton $context_f.genfscon -text "genfscon" -value genfscon \
+ -variable Apol_FSContexts::vals(context_type)
+ radiobutton $context_f.fsuse -text "fs_use" -value fsuse \
+ -variable Apol_FSContexts::vals(context_type)
+ trace add variable Apol_FSContexts::vals(context_type) write \
+ {Apol_FSContexts::_contextTypeChanged}
+ pack $context_f.genfscon $context_f.fsuse \
+ -anchor w -expand 0 -padx 4 -pady 5
+ pack $context_box -expand 0 -fill x
+
+ set widgets(items_tf) [TitleFrame $leftf.items_f -text "GenFS Contexts"]
+ set widgets(items) [Apol_Widget::makeScrolledListbox [$widgets(items_tf) getframe].items \
+ -height 20 -width 20 -listvar Apol_FSContexts::vals(items)]
+ Apol_Widget::setListboxCallbacks $widgets(items) \
+ {{"Show Context Info" {Apol_FSContexts::_popupContextInfo}}}
+ pack $widgets(items) -expand 1 -fill both
+ pack $widgets(items_tf) -expand 1 -fill both
+
+ # build the search options
+ set optsbox [TitleFrame $rightf.optsbox -text "Search Options"]
+ pack $optsbox -side top -expand 0 -fill both -padx 2
+ set widgets(options_pm) [PagesManager [$optsbox getframe].pm]
+
+ _genfscon_create [$widgets(options_pm) add genfscon]
+ _fsuse_create [$widgets(options_pm) add fsuse]
+
+ $widgets(options_pm) compute_size
+ pack $widgets(options_pm) -expand 1 -fill both -side left
+ $widgets(options_pm) raise genfscon
+
+ set ok [button [$optsbox getframe].ok -text "OK" -width 6 \
+ -command Apol_FSContexts::_runSearch]
+ pack $ok -side right -pady 5 -padx 5 -anchor ne
+
+ # build the results box
+ set resultsbox [TitleFrame $rightf.resultsbox -text "Search Results"]
+ pack $resultsbox -expand yes -fill both -padx 2
+ set widgets(results) [Apol_Widget::makeSearchResults [$resultsbox getframe].results]
+ pack $widgets(results) -side top -expand yes -fill both
+
+ return $frame
+}
+
+proc Apol_FSContexts::open {ppath} {
+ variable vals
+
+ _genfscon_open
+ _fsuse_open
+
+ # force a flip to the genfscon page, via a trace on this variable
+ set vals(context_type) genfscon
+}
+
+proc Apol_FSContexts::close {} {
+ variable widgets
+
+ _initializeVars
+ Apol_Widget::clearSearchResults $widgets(results)
+ Apol_Widget::clearContextSelector $widgets(genfscon:context)
+ Apol_Widget::clearContextSelector $widgets(fsuse:context)
+ $widgets(genfscon:fs) configure -values {}
+ $widgets(fsuse:type) configure -values {}
+ $widgets(fsuse:fs) configure -values {}
+}
+
+proc Apol_FSContexts::getTextWidget {} {
+ variable widgets
+ return $widgets(results).tb
+}
+
+#### private functions below ####
+
+proc Apol_FSContexts::_initializeVars {} {
+ variable vals
+ array set vals {
+ genfscon:items {}
+ genfscon:fs_enable 0 genfscon:fs {}
+ genfscon:path_enable 0 genfscon:path {}
+
+ fsuse:items {}
+ fsuse:type_enable 0 fsuse:type {}
+ fsuse:fs_enable 0 fsuse:fs {}
+
+ items {}
+ context_type genfscon
+ }
+}
+
+proc Apol_FSContexts::_contextTypeChanged {name1 name2 op} {
+ variable vals
+ variable widgets
+ Apol_Widget::clearSearchResults $widgets(results)
+ if {$vals(context_type) == "genfscon"} {
+ _genfscon_show
+ } else {
+ _fsuse_show
+ }
+}
+
+proc Apol_FSContexts::_popupContextInfo {value} {
+ variable vals
+ if {$vals(context_type) == "genfscon"} {
+ _genfscon_popup $value
+ } else {
+ _fsuse_popup $value
+ }
+}
+
+proc Apol_FSContexts::_toggleCheckbutton {path name1 name2 op} {
+ variable vals
+ variable widgets
+ if {$vals($name2)} {
+ $path configure -state normal
+ } else {
+ $path configure -state disabled
+ }
+}
+
+proc Apol_FSContexts::_runSearch {} {
+ variable vals
+ variable widgets
+
+ Apol_Widget::clearSearchResults $widgets(results)
+ if {![ApolTop::is_policy_open]} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No current policy file is opened."
+ return
+ }
+ if {$vals(context_type) == "genfscon"} {
+ _genfscon_runSearch
+ } else {
+ _fsuse_runSearch
+ }
+}
+
+#### genfscon private functions below ####
+
+proc Apol_FSContexts::_genfscon_create {p_f} {
+ variable widgets
+ variable vals
+
+ set fs [frame $p_f.fs]
+ set fs_cb [checkbutton $fs.fs_enable -text "Filesystem" \
+ -variable Apol_FSContexts::vals(genfscon:fs_enable)]
+ set widgets(genfscon:fs) [ComboBox $fs.fs -entrybg white -width 12 -state disabled \
+ -textvariable Apol_FSContexts::vals(genfscon:fs) -autopost 1]
+ trace add variable Apol_FSContexts::vals(genfscon:fs_enable) write \
+ [list Apol_FSContexts::_toggleCheckbutton $widgets(genfscon:fs)]
+ pack $fs_cb -side top -anchor w
+ pack $widgets(genfscon:fs) -side top -expand 0 -fill x -padx 4
+
+ set p [frame $p_f.p]
+ set p_cb [checkbutton $p.p_enable -text "Path" \
+ -variable Apol_FSContexts::vals(genfscon:path_enable)]
+ set widgets(genfscon:path) [entry $p.path -bg white -width 24 \
+ -state disabled \
+ -textvariable Apol_FSContexts::vals(genfscon:path)]
+ trace add variable Apol_FSContexts::vals(genfscon:path_enable) write \
+ [list Apol_FSContexts::_toggleCheckbutton $widgets(genfscon:path)]
+ pack $p_cb -side top -anchor w
+ pack $widgets(genfscon:path) -side top -expand 0 -fill x -padx 4
+
+ frame $p_f.c
+ set widgets(genfscon:context) [Apol_Widget::makeContextSelector $p_f.c.context "Contexts"]
+ pack $widgets(genfscon:context)
+
+ pack $fs $p $p_f.c -side left -anchor n -padx 4 -pady 2
+}
+
+proc Apol_FSContexts::_genfscon_open {} {
+ variable vals
+
+ set q [new_apol_genfscon_query_t]
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set genfscons [genfscon_vector_to_list $v]
+ set vals(genfscon:items) {}
+ foreach g $genfscons {
+ lappend vals(genfscon:items) [$g get_name $::ApolTop::qpolicy]
+ }
+ set vals(genfscon:items) [lsort -unique $vals(genfscon:items)]
+
+ # because qpol_policy_get_genfscon_iter() returns allocated items,
+ # destroying the vector before using its items will segfault
+ $v -acquire
+ $v -delete
+
+ variable widgets
+ $widgets(genfscon:fs) configure -values $vals(genfscon:items)
+}
+
+proc Apol_FSContexts::_genfscon_show {} {
+ variable vals
+ variable widgets
+ $widgets(items_tf) configure -text "GenFS Contexts"
+ $widgets(options_pm) raise genfscon
+ set vals(items) $vals(genfscon:items)
+}
+
+proc Apol_FSContexts::_genfscon_popup {fstype} {
+ set q [new_apol_genfscon_query_t]
+ $q set_filesystem $::ApolTop::policy $fstype
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set genfscons [genfscon_vector_to_list $v]
+ set text "genfs filesystem $fstype ([llength $genfscons] context"
+ if {[llength $genfscons] != 1} {
+ append text s
+ }
+ append text ")"
+ foreach g [lsort -command _genfscon_sort $genfscons] {
+ append text "\n [_genfscon_render $g]"
+ }
+ Apol_Widget::showPopupText "filesystem $fstype" $text
+
+ # because qpol_policy_get_genfscon_iter() returns allocated items,
+ # destroying the vector before using its items will segfault
+ $v -acquire
+ $v -delete
+}
+
+proc Apol_FSContexts::_genfscon_runSearch {} {
+ variable vals
+ variable widgets
+
+ if {$vals(genfscon:fs_enable)} {
+ if {$vals(genfscon:fs) == {}} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No filesystem selected."
+ return
+ }
+ set fstype $vals(genfscon:fs_enable)
+ } else {
+ set fstype {}
+ }
+ if {$vals(genfscon:path_enable)} {
+ if {$vals(genfscon:path) == {}} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No path given."
+ return
+ }
+ set path $vals(genfscon:path)
+ } else {
+ set path {}
+ }
+
+ set q [new_apol_genfscon_query_t]
+ if {[Apol_Widget::getContextSelectorState $widgets(genfscon:context)]} {
+ foreach {context range_match attribute} [Apol_Widget::getContextSelectorValue $widgets(genfscon:context)] {break}
+ $q set_context $::ApolTop::policy $context $range_match
+ }
+ $q set_filesystem $::ApolTop::policy $fstype
+ $q set_path $::ApolTop::policy $path
+
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set genfscons [genfscon_vector_to_list $v]
+
+ set results "GENFSCONS:"
+ if {[llength $genfscons] == 0} {
+ append results "\nSearch returned no results."
+ } else {
+ foreach g [lsort -command _genfscon_sort $genfscons] {
+ append results "\n[_genfscon_render $g]"
+ }
+ }
+ Apol_Widget::appendSearchResultText $widgets(results) $results
+
+ # because qpol_policy_get_genfscon_iter() returns allocated items,
+ # destroying the vector before using its items will segfault
+ $v -acquire
+ $v -delete
+}
+
+proc Apol_FSContexts::_genfscon_render {qpol_genfscon_datum} {
+ apol_genfscon_render $::ApolTop::policy $qpol_genfscon_datum
+}
+
+proc Apol_FSContexts::_genfscon_sort {a b} {
+ set name_a [$a get_name $::ApolTop::qpolicy]
+ set name_b [$b get_name $::ApolTop::qpolicy]
+ if {[set z [string compare $name_a $name_b]] != 0} {
+ return $z
+ }
+ set path_a [$a get_path $::ApolTop::qpolicy]
+ set path_b [$b get_path $::ApolTop::qpolicy]
+ if {[set z [string compare $path_a $path_b]] != 0} {
+ return $z
+ }
+ return 0
+}
+
+#### fs_use private functions below ####
+
+proc Apol_FSContexts::_fsuse_create {p_f} {
+ variable widgets
+ variable vals
+
+ set t [frame $p_f.t]
+ set type_cb [checkbutton $t.type_enable -text "Statement type" \
+ -variable Apol_FSContexts::vals(fsuse:type_enable)]
+ set widgets(fsuse:type) [ComboBox $t.type -entrybg white -width 12 -state disabled \
+ -textvariable Apol_FSContexts::vals(fsuse:type) -autopost 1]
+ trace add variable Apol_FSContexts::vals(fsuse:type_enable) write \
+ [list Apol_FSContexts::_toggleCheckbutton $widgets(fsuse:type)]
+ pack $type_cb -side top -anchor w
+ pack $widgets(fsuse:type) -side top -expand 0 -fill x -padx 4
+
+ set fs [frame $p_f.fs]
+ set fs_cb [checkbutton $fs.fs_enable -text "Filesystem" \
+ -variable Apol_FSContexts::vals(fsuse:fs_enable)]
+ set widgets(fsuse:fs) [ComboBox $fs.fs -entrybg white -width 12 -state disabled \
+ -textvariable Apol_FSContexts::vals(fsuse:fs) -autopost 1]
+ trace add variable Apol_FSContexts::vals(fsuse:fs_enable) write \
+ [list Apol_FSContexts::_toggleCheckbutton $widgets(fsuse:fs)]
+ pack $fs_cb -side top -anchor w
+ pack $widgets(fsuse:fs) -side top -expand 0 -fill x -padx 4
+
+ frame $p_f.c
+ set widgets(fsuse:context) [Apol_Widget::makeContextSelector $p_f.c.context "Contexts"]
+ pack $widgets(fsuse:context)
+
+ pack $t $fs $p_f.c -side left -anchor n -padx 4 -pady 2
+}
+
+proc Apol_FSContexts::_fsuse_open {} {
+ variable vals
+
+ set q [new_apol_fs_use_query_t]
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set fs_uses [lsort -unique [fs_use_vector_to_list $v]]
+ $v -acquire
+ $v -delete
+
+ # get a list of all behaviors present in this policy
+ set vals(fsuse:items) {}
+ set behavs {}
+ foreach f $fs_uses {
+ lappend vals(fsuse:items) [$f get_name $::ApolTop::qpolicy]
+ lappend behavs [apol_fs_use_behavior_to_str [$f get_behavior $::ApolTop::qpolicy]]
+ }
+
+ variable widgets
+ set vals(fsuse:items) [lsort -unique $vals(fsuse:items)]
+ $widgets(fsuse:type) configure -values [lsort -unique $behavs]
+ $widgets(fsuse:fs) configure -values $vals(fsuse:items)
+}
+
+proc Apol_FSContexts::_fsuse_show {} {
+ variable vals
+ variable widgets
+ $widgets(items_tf) configure -text "fs_use Contexts"
+ $widgets(options_pm) raise fsuse
+ set vals(items) $vals(fsuse:items)
+}
+
+proc Apol_FSContexts::_fsuse_popup {fs} {
+ set qpol_fs_use_datum [new_qpol_fs_use_t $::ApolTop::qpolicy $fs]
+ set text "fs_use $fs\n [_fsuse_render $qpol_fs_use_datum]"
+ Apol_Widget::showPopupText $fs $text
+}
+
+proc Apol_FSContexts::_fsuse_runSearch {} {
+ variable vals
+ variable widgets
+
+ if {$vals(fsuse:type_enable)} {
+ if {$vals(fsuse:type) == {}} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No fs_use statement type selected."
+ return
+ }
+ set behavior [apol_str_to_fs_use_behavior $vals(fsuse:type)]
+ if {$behavior < 0} {
+ tk_messageBox -icon error -type ok -title "Error" -message "$vals(fsuse:type) is not a valid fs_use statement type."
+ return
+ }
+ } else {
+ set behavior -1
+ }
+ if {$vals(fsuse:fs_enable)} {
+ if {$vals(fsuse:fs) == {}} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No filesystem selected."
+ return
+ }
+ set fstype $vals(fsuse:fs)
+ } else {
+ set fstype {}
+ }
+
+ set q [new_apol_fs_use_query_t]
+ if {[Apol_Widget::getContextSelectorState $widgets(fsuse:context)]} {
+ foreach {context range_match attribute} [Apol_Widget::getContextSelectorValue $widgets(fsuse:context)] {break}
+ $q set_context $::ApolTop::policy $context $range_match
+ }
+ $q set_filesystem $::ApolTop::policy $fstype
+ $q set_behavior $::ApolTop::policy $behavior
+
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set fsuses [fs_use_vector_to_list $v]
+ $v -acquire
+ $v -delete
+
+ set results "FS_USES:"
+ if {[llength $fsuses] == 0} {
+ append results "\nSearch returned no results."
+ } else {
+ foreach u [lsort -command _fsuse_sort $fsuses] {
+ append results "\n[_fsuse_render $u]"
+ }
+ }
+ Apol_Widget::appendSearchResultText $widgets(results) $results
+}
+
+proc Apol_FSContexts::_fsuse_render {qpol_fs_use_datum} {
+ apol_fs_use_render $::ApolTop::policy $qpol_fs_use_datum
+}
+
+proc Apol_FSContexts::_fsuse_sort {a b} {
+ set behav_a [apol_fs_use_behavior_to_str [$a get_behavior $::ApolTop::qpolicy]]
+ set behav_b [apol_fs_use_behavior_to_str [$b get_behavior $::ApolTop::qpolicy]]
+ if {[set z [string compare $behav_a $behav_b]] != 0} {
+ return $z
+ }
+ set name_a [$a get_name $::ApolTop::qpolicy]
+ set name_b [$b get_name $::ApolTop::qpolicy]
+ if {[set z [string compare $name_a $name_b]] != 0} {
+ return $z
+ }
+ return 0
+}
diff --git a/apol/goto.tcl b/apol/goto.tcl
new file mode 100644
index 0000000..7988ebb
--- /dev/null
+++ b/apol/goto.tcl
@@ -0,0 +1,78 @@
+# Copyright (C) 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
+
+namespace eval Apol_Goto {
+ variable dialog .apol_goto_dialog
+ variable line_num
+}
+
+proc Apol_Goto::goto {} {
+ variable dialog
+ if {![winfo exists $dialog]} {
+ _create_dialog
+ } else {
+ raise $dialog
+ variable entry
+ focus $entry
+ $entry selection range 0 end
+ }
+}
+
+
+########## private functions below ##########
+
+proc Apol_Goto::_create_dialog {} {
+ variable dialog
+ Dialog $dialog -title "Goto Line" -separator 0 -parent . \
+ -default 0 -cancel 1 -modal none -homogeneous 1
+ set top_frame [$dialog getframe]
+ set entry_label [label $top_frame.l -text "Goto Line:" -anchor e]
+ variable entry [entry $top_frame.e -bg white \
+ -textvariable Apol_Goto::line_num -width 10]
+ pack $entry_label -side left -padx 5 -pady 5
+ pack $entry -side left -padx 5 -pady 5 -expand 1 -fill x
+
+ $dialog add -text "OK" -command [list Apol_Goto::_do_goto]
+ $dialog add -text "Cancel" -command [list destroy $dialog]
+
+ $entry selection range 0 end
+ focus $entry
+ $dialog draw
+ wm resizable $dialog 0 0
+}
+
+proc Apol_Goto::_do_goto {} {
+ set w [ApolTop::getCurrentTextWidget]
+ if {$w == {}} {
+ return
+ }
+
+ variable line_num
+ if {[string is integer -strict $line_num] != 1} {
+ tk_messageBox -icon error \
+ -type ok \
+ -title "Goto Line" \
+ -message "$line_num is not a valid line number."
+ } else {
+ $w tag remove sel 0.0 end
+ $w mark set insert ${line_num}.0
+ $w see ${line_num}.0
+ $w tag add sel $line_num.0 $line_num.end
+ focus $w
+ }
+
+ variable dialog
+ destroy $dialog
+}
diff --git a/apol/head.tcl b/apol/head.tcl
new file mode 100644
index 0000000..28dc44c
--- /dev/null
+++ b/apol/head.tcl
@@ -0,0 +1,29 @@
+#!/bin/sh
+# \
+exec tclsh "$0" ${1+"$@"}
+
+##############################################################
+#
+# apol: SELinux Policy Analysis Tools
+#
+# Copyright (C) 2002-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
+#
+# Question/comments to: setools@tresys.com
+#
+# This tool is designed to analyze SELinux policies. See the
+# assoicated help file for more information.
+#
+##############################################################
diff --git a/apol/infoflow_help.txt b/apol/infoflow_help.txt
new file mode 100644
index 0000000..fde6d42
--- /dev/null
+++ b/apol/infoflow_help.txt
@@ -0,0 +1,321 @@
+An overview of information flow analysis
+
+
+Apol supports the ability to automate the search for overt information
+flows between two types. The purpose of this analysis is to identify
+undesirable or unexpected flows of information allowed by a Type
+Enforcement (TE) policy. For example, imagine that the type shadow_t
+is assigned to the shadow password file /etc/shadow. To determine all
+the types to which information can flow from the shadow_t type (e.g,
+indicating possible paths for encrypted passwords to be
+unintentionally leaked), do a "flow from" analysis on the shadow_t
+type. Another example might be a firewall application where the
+intent is to understand all flows allowed between two network
+interfaces.
+
+Information flow analysis in SELinux is challenging for several
+reasons, including:
+
+ + The TE policy mechanism is extremely flexible, allowing for good
+ and bad flows to be easily specified, not necessarily by the
+ policy writer's intent.
+
+ + TE policies tend to be complex, with possibly tens of thousands of
+ rules and hundreds of types, making it difficult for a policy
+ writer to know all that is allowed.
+
+ + SELinux currently supports over 50 object classes and hundreds of
+ object permissions, each of which must be examined with their
+ ability to allow information flow from/to its associated object
+ class.
+
+The remainder of this file provides an overview on how apol performs
+information flow analysis.
+
+
+What Is Overt Information Flow In SELinux?
+------------------------------------------
+Information flow is defined in terms of access allowed (not
+necessarily whether that access is actually used). In SELinux, all
+objects and subjects have an associated type. Generally speaking,
+subjects can read or write objects, and thereby cause information to
+flow into and out of objects, and into and out of themselves. For
+example, given two types (say subject_t and object_t) and a subject
+(with subject_t type) able to read, but not write, an object (with
+object_t type), a rule that would allow this access might look like
+the following:
+
+ allow subject_t object_t : {file link_file} read;
+
+This case would have the following direct information flows for the
+types subject_t and object_t:
+
+ subject_t: FROM object_t
+
+ object_t: TO subject_t
+
+If this were the only rule relating to these two types, there would be
+no other direct information flows from or to either.
+
+An information flow can only occur when a subject is involved; a flow
+directly between two objects cannot exist since a subject is required
+to cause action. In SELinux, processes are generally the subject.
+There are currently 58 object classes (including processes, which are
+both subjects and objects).
+
+In apol, the subject is easy to recognize; any type that is used in
+the 'source' field of an allow rule is presumed to be associated with
+a subject, usually as the domain type of some process. The object
+type is the type used in the 'target' field of an allow rule.
+
+In the case of objects, the allow rule also explicitly identifies the
+object classes for which the rule applies. This fact results in a
+complication for analyzing information flows; specifically that flows
+between types are restricted by object classes. A flow between types
+is typically not allowed for all object classes, but for only those
+classes identified. So to be more precise, the direct information
+flows allowed by the object rules for object_t in the example above
+are:
+
+ object_t [file, link_file]: TO subject_t
+
+A perspective difference exists between source (subject) types and
+target (object) types. A read permission between a source type and a
+target type is a flow out of the target (which is being read) and flow
+into the source (which, being a process, is receiving the data being
+read into its memory).
+
+
+Object permission mappings
+--------------------------
+The above examples used 'read' permission, but described flows as 'in'
+or 'out' or 'from' and 'to'. In general, for information flow
+analysis, the only access between subjects and objects that are of
+interest, are read and write. Remembering the perspective difference
+mentioned above, read and write access results in the following flow
+for subjects (sources) and objects (targets):
+
+ SUBJECT: READ: IN flow
+ WRITE: OUT flow
+
+ OBJECT: READ: OUT flow
+ WRITE: IN flow
+
+ NOTE: A process can be either a subject or an object, so when the
+ process object class is specified in the allow rule, the target
+ type is associated with process object class and the object flow
+ rules apply.
+
+Although read and write access are the only access rights of interest
+for an information flow analysis, 'read' and 'write' permissions are
+not the only SELinux permissions of interest. The name of a
+permission does not necessarily imply whether it allows read or write
+access. Indeed, to perform an information flow analysis requires
+mapping all defined permissions for all object classes to read and
+write access.
+
+This mapping can be a difficult chore, and certainly requires
+extensive understanding of the access allowed by each of the hundreds
+of permissions currently defined. For example, the file object class
+has the 'getattr' permission defined that allows the ability to
+determine information about a file (such as date created and size).
+One could consider this a read access since the subject is reading
+information about the file. Then again this begins to feel like
+COVERT information flow analysis, where one is concerned about illicit
+signaling of information through non-traditional means (e.g.,
+signaling the critical data by varying the size of file is a covert
+flow, writing the data directly in the file so it can be read is an
+overt flow). This type of decision must be made for each defined
+object permission for each defined object class.
+
+The permission mapping mechanism in apol allows each permission to be
+mapped to read, write, both or none. In addition, the tool attempts
+to 'fix' a permission map to fit the needs of the currently opened
+policy. So, for example, if a permission map file does not map a set
+of permissions, or skips an entire object class, apol will label the
+missing permissions to "unmapped" and treat them as if they were
+mapped to 'none.' Likewise, if a map has permissions that are
+undefined in the current policy, it will ignore those mappings. In
+this way, apol continues its tradition of supporting old and new
+versions of policies (see below for more on managing permission maps).
+
+Apol provides mechanisms to manage and customize permission mappings
+that best suit the analyst's needs. Use the Tools menu (see below) to
+modify permission mappings.
+
+
+Permission weighting
+--------------------
+In addition to mapping each permission to read, write, both, or none,
+it is possible to assign the permission a weight between 1 and 10 (the
+default is 10). Apol uses this weight to rate the importance of the
+information flow this permission represents and allows the user to
+make fine-grained distinctions between high-bandwidth, overt
+information flows and low-bandwidth, or difficult to exploit, covert
+information flows. For example, the permissions "read" and "write" on
+the file object could be given a weight of 10 because they are very
+high-bandwidth information flows. Additionally, the "use" permission
+on the fd object (file descriptor) would probably be given a weight of
+1 as it is a very low-bandwidth covert flow at best. Note that a
+permission might be important for access control, like fd use, but be
+given a low weight for information flow because it cannot be used to
+pass large amounts of information.
+
+The default permission maps that are installed with apol have weights
+assigned for all of the permissions. The weights are in four general
+categories as follows:
+
+ 1 - 2 difficult to exploit covert flows (example: fd:use)
+ 3 - 5 less difficult to exploit covert flows
+ (example: process:signal)
+ 6 - 7 difficult to use, noisy, or low-bandwidth overt flows
+ (example: file:setattr)
+ 8 - 10 high-bandwidth overt flows (example: file:write)
+
+These categories are loosely defined and the placement of permissions
+into these categories is subjective. Additional work needs to be done
+to verify the accuracy of both the mappings of the permissions and the
+assigned weights.
+
+These weights are used in transitive information flow analysis to rank
+the results and to make certain that important paths between types are
+presented first. For example, consider a policy with the following
+information flows:
+
+ allow one_t two_t : file write;
+ allow three_t two_t : file read;
+ allow one_t three_t : fd use;
+
+If the permissions were mapped as described above and an analysis of
+the transitive flows from one_t to three_t were done, the analysis
+would return the path one_t->two_t->three_t first because the read and
+write permissions have a much higher weight. The direct flow between
+one_t and three_t would still be returned by the find more flows, but
+it would appear later in the list of flows.
+
+
+Types of information flow analysis
+----------------------------------
+The examples so far have only looked at 'direct' information flows.
+As its name implies, direct information flow analysis examines a
+policy for information flows that are directly permitted by one or
+more allow rules. In essence, every allow rule defines a direct
+information flow between the source and target types (for those
+allowed permissions that map to read, write, or both). The direct
+information flow analysis automates the search for these direct flows.
+
+Transitive information flow analysis attempts to link together a
+series of direct information flows to find an indirect path in which
+information can flow between two types. The results for a transitive
+closure will show one or more steps in the chain required for
+information to flow between the start and end types. Currently, the
+results will only show one such path for each end type; specifically
+the shortest path.
+
+For example, given the following rules:
+
+ allow one_t two_t : file write;
+ allow three_t two_t: file read;
+
+A direct flow analysis between one_t and three_t would not show any
+flows since no rule explicitly allows access between them. However, a
+two-step flow exists that would allow flow between these two types,
+namely one_t writing information into a file type (two_t) that three_t
+can read. These are the types of flows that the transitive analysis
+attempts to find.
+
+For both analyses, the results are presented in a less-than-desirable
+tree form (a more natural form might be a graph presentation;
+presently we are not prepared for that type of investment into the
+GUI). Each node in the tree represents a flow (in the direction
+selected) between the type of the parent node and the type of the
+node. The results window shows each step of the flow including the
+contributing access rule(s).
+
+
+Managing permission mappings
+----------------------------
+The ability to directly manage permission maps is important for the
+following reasons:
+
+ + Permission maps are central to analyzing information flows, and
+ the correctness of the map has a direct influence on the value of
+ the results.
+
+ + The mapping for individual permissions and object classes are
+ subjective, and changing permissions to alter the analysis might
+ be necessary (e.g., by unmapping certain object classes to remove
+ them from the analysis).
+
+ + The analyst may be working with several different policies each
+ with different definitions of object classes and permissions.
+
+
+Because of these reasons, apol was designed to provide great latitude
+in managing permission mappings using Tools menu. A user need not
+manage permission maps directly; apol is installed with default
+permission maps (typically in /usr/local/share/setools-<version>/)
+that will be loaded automatically when an information flow analysis is
+performed.
+
+Use the Tools menu to manually load a permission map from an arbitrary
+file. This capability allows the user to keep several versions of
+permission map files, loading the correct one for a given analysis.
+
+Although the user could view and modify mappings by editing a map file
+directly, an easier (and less error-prone) approach is apol's perm map
+viewer. Select View Perm Map from the Tools menu to display all
+object classes and permissions currently mapped (or unmapped) in the
+currently loaded policy. In addition, each permission's weight value
+is shown. These values tell apol the importance of each permission to
+the analysis. The user can configure these weight values according to
+the analysis goals. For example, the user may consider any read or
+write permissions of highest importance to the analysis, whereas
+permission to use a file descriptor may be of least importance. A
+permission will default to a weight of 10 if a weight value is not
+provided for the permission in the permission map.
+
+A user has access to the "default" permission file. If there exists a
+file named .apol_perm_mapping in his home directory (i.e.,
+$HOME/.apol_perm_mapping), then it is used when opening the default
+file. Otherwise the default file will be read from SETools's
+installed location, typically /usr/local/share/setools-<version>. The
+file .apol_perm_mapping is always used as the destination when saving
+to the default permission file.
+
+ NOTE: Only one permission map may be opened at a time, and only
+ when a policy is already opened. If apol has performed an
+ information flow analysis, the default permission map will be
+ loaded automatically unless a permission map was previously loaded.
+ Closing the policy will also close any existing permission mapping.
+ Unsaved changes will be lost.
+
+
+Finding more flows
+------------------
+For a transitive information flow, there might be many different
+information flows between two types. For example, given the
+following policy:
+
+ allow one_t two_t : file write;
+ allow three_t two_t: file read;
+ allow four_t two_t: file read;
+ allow four_t three_t: file write;
+
+In this policy, two ways exist that information can flow between one_t
+and three_t: through three_t and through three_t and four_t. In
+complicated policies, many information flows between two types can
+exist, but the initial transitive information flow analysis might not
+find all of them. For example, apol might only find the flow through
+three_t and four_t initially in the policy above. Apol provides the
+means to find more information flows between two types after the
+inital analysis is completed. In the results display for an end type,
+there is a link labeled "Find More Flows." Clicking on the link will
+bring up a dialog box that allows the user to set a maximum time
+duration and a maximum number of flows. Finding all of the paths
+between two types could take a significant amount of time for a
+complicated policy, so this dialog provides the means to set limits on
+the search. The search will stop when either of the limits are met.
+After the search completes, the additional paths will be displayed in
+the same results tab. Note that if a large number of flows are found
+it may take the display several seconds to render the text.
diff --git a/apol/initial_sids_tab.tcl b/apol/initial_sids_tab.tcl
new file mode 100644
index 0000000..ff81a32
--- /dev/null
+++ b/apol/initial_sids_tab.tcl
@@ -0,0 +1,142 @@
+# Copyright (C) 2001-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
+
+namespace eval Apol_Initial_SIDS {
+ variable widgets
+ variable vals
+}
+
+proc Apol_Initial_SIDS::create {tab_name nb} {
+ variable widgets
+ variable vals
+
+ array set vals {
+ items {}
+ }
+
+ set frame [$nb insert end $tab_name -text "Initial SIDs"]
+ set pw [PanedWindow $frame.pw -side top -weights extra]
+ set leftf [$pw add -weight 0]
+ set rightf [$pw add -weight 1]
+ pack $pw -fill both -expand yes
+
+ set sids_box [TitleFrame $leftf.sids_box -text "Initial SIDs"]
+ set s_optionsbox [TitleFrame $rightf.obox -text "Search Options"]
+ set rslts_frame [TitleFrame $rightf.rbox -text "Search Results"]
+ pack $sids_box -expand 1 -fill both
+ pack $s_optionsbox -side top -expand 0 -fill both -padx 2
+ pack $rslts_frame -side top -expand yes -fill both -padx 2
+
+ set widgets(items) [Apol_Widget::makeScrolledListbox [$sids_box getframe].lb -width 20 -listvar Apol_Initial_SIDS::vals(items)]
+ Apol_Widget::setListboxCallbacks $widgets(items) \
+ {{"Display Initial SID Context" {Apol_Initial_SIDS::_popupSIDInfo}}}
+ pack $widgets(items) -expand 1 -fill both
+
+ set f [frame [$s_optionsbox getframe].c]
+ set widgets(context) [Apol_Widget::makeContextSelector $f.context "Context"]
+ pack $widgets(context)
+ pack $f -side left -anchor n -padx 4 -pady 2
+
+ set ok [button [$s_optionsbox getframe].ok -text "OK" -width 6 \
+ -command Apol_Initial_SIDS::_search]
+ pack $ok -side right -pady 5 -padx 5 -anchor ne
+
+ set widgets(results) [Apol_Widget::makeSearchResults [$rslts_frame getframe].results]
+ pack $widgets(results) -side top -expand yes -fill both
+
+ return $frame
+}
+
+proc Apol_Initial_SIDS::open {ppath} {
+ variable vals
+ set q [new_apol_isid_query_t]
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set vals(items) [lsort [isid_vector_to_list $v]]
+ $v -acquire
+ $v -delete
+}
+
+proc Apol_Initial_SIDS::close {} {
+ variable vals
+ variable widgets
+ set vals(items) {}
+ Apol_Widget::clearSearchResults $widgets(results)
+ Apol_Widget::clearContextSelector $widgets(context)
+}
+
+proc Apol_Initial_SIDS::getTextWidget {} {
+ variable widgets
+ return $widgets(results).tb
+}
+
+#### private functions below ####
+
+proc Apol_Initial_SIDS::_popupSIDInfo {sid} {
+ set text "$sid:\n [_render_isid $sid 1]"
+ Apol_Widget::showPopupText "$sid Context" $text
+}
+
+proc Apol_Initial_SIDS::_search {} {
+ variable vals
+ variable widgets
+
+ set name {}
+ set context {}
+ set range_match 0
+ Apol_Widget::clearSearchResults $widgets(results)
+ if {![ApolTop::is_policy_open]} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No current policy file is opened."
+ return
+ }
+
+ set q [new_apol_isid_query_t]
+
+ if {[Apol_Widget::getContextSelectorState $widgets(context)]} {
+ foreach {context range_match attribute} [Apol_Widget::getContextSelectorValue $widgets(context)] {break}
+ $q set_context $::ApolTop::policy $context $range_match
+ }
+
+ set v [$q run $::ApolTop::policy] #line causing segfaulting
+
+ $q -acquire
+ $q -delete
+ set isids [isid_vector_to_list $v]
+ $v -acquire
+ $v -delete
+
+ set results "INITIAL SIDS:"
+ if {[llength $isids] == 0} {
+ append results "\nSearch returned no results."
+ } else {
+ foreach i [lsort -dictionary $isids] {
+ append results "\n[_render_isid $i]"
+ }
+ }
+
+ Apol_Widget::appendSearchResultText $widgets(results) $results
+}
+
+proc Apol_Initial_SIDS::_render_isid {isid_name {compact 0}} {
+ set qpol_isid_datum [new_qpol_isid_t $::ApolTop::qpolicy $isid_name]
+ set qpol_context [$qpol_isid_datum get_context $::ApolTop::qpolicy]
+ set context_str [apol_qpol_context_render $::ApolTop::policy $qpol_context]
+ if {$compact} {
+ format "sid %s %s" $isid_name $context_str
+ } else {
+ format "sid %-16s %s" $isid_name $context_str
+ }
+}
diff --git a/apol/level_dialog.tcl b/apol/level_dialog.tcl
new file mode 100644
index 0000000..181cc3c
--- /dev/null
+++ b/apol/level_dialog.tcl
@@ -0,0 +1,82 @@
+# Copyright (C) 2005-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
+
+namespace eval Apol_Level_Dialog {
+ variable dialog ""
+ variable vars
+}
+
+# Create a dialog box to allow the user to select a single MLS level.
+# Return an instance of an apol_mls_level. If no level is selected
+# then return an empty list; otherwise return the level. The caller
+# must delete it afterwards.
+proc Apol_Level_Dialog::getLevel {{defaultLevel {}} {parent .}} {
+ variable dialog
+ if {![winfo exists $dialog]} {
+ _create_dialog $parent
+ }
+ set f [$dialog getframe]
+ Apol_Widget::resetLevelSelectorToPolicy $f.level
+ if {$defaultLevel != {}} {
+ Apol_Widget::setLevelSelectorLevel $f.level $defaultLevel
+ }
+ # force a recomputation of button sizes (bug in ButtonBox)
+ $dialog.bbox _redraw
+ set retval [$dialog draw]
+ if {$retval == -1 || $retval == 1} {
+ return {}
+ }
+ _get_level $dialog
+}
+
+
+########## private functions below ##########
+
+proc Apol_Level_Dialog::_create_dialog {parent} {
+ variable dialog
+ variable vars
+
+ set dialog [Dialog .level_dialog -modal local -parent $parent \
+ -separator 1 -homogeneous 1 -title "Select Level"]
+ array unset vars $dialog:*
+
+ set f [$dialog getframe]
+ set label [label $f.ll -text "Level:"]
+ set level [Apol_Widget::makeLevelSelector $f.level 12]
+
+ pack $label -anchor w
+ pack $level -expand 1 -fill both
+
+ $dialog add -text "OK" -command [list Apol_Level_Dialog::_okay $dialog]
+ $dialog add -text "Cancel"
+}
+
+proc Apol_Level_Dialog::_get_level {dialog} {
+ return [Apol_Widget::getLevelSelectorLevel [$dialog getframe].level]
+}
+
+# Check that the level is legal by validating it against the current
+# policy.
+proc Apol_Level_Dialog::_okay {dialog} {
+ set level [_get_level $dialog]
+ if {![ApolTop::is_policy_open] || [$level validate $::ApolTop::policy] != 1} {
+ tk_messageBox -icon error -type ok -title "Invalid Level" \
+ -message "The selected level is not valid for the current policy."
+ } else {
+ $dialog enddialog 0
+ }
+ $level -acquire
+ $level -delete
+}
diff --git a/apol/mls_tab.tcl b/apol/mls_tab.tcl
new file mode 100644
index 0000000..e8e5a8e
--- /dev/null
+++ b/apol/mls_tab.tcl
@@ -0,0 +1,332 @@
+# Copyright (C) 2001-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
+
+namespace eval Apol_MLS {
+ variable widgets
+ variable vals
+}
+
+proc Apol_MLS::create {tab_name nb} {
+ variable widgets
+ variable vals
+
+ _initializeVars
+
+ # Layout frames
+ set frame [$nb insert end $tab_name -text "MLS"]
+ set pw [PanedWindow $frame.pw -side top -weights extra]
+ set leftf [$pw add -weight 0]
+ set rightf [$pw add -weight 1]
+ pack $pw -fill both -expand yes
+
+ # build the left column, where one may browse sensitivities and categories
+ set sensbox [TitleFrame $leftf.sensbox -text "Sensitivities"]
+ set catsbox [TitleFrame $leftf.catsbox -text "Categories"]
+ pack $sensbox -fill both -expand 0
+ pack $catsbox -fill both -expand yes
+
+ set sensbox [Apol_Widget::makeScrolledListbox [$sensbox getframe].sens \
+ -height 10 -width 20 -listvar Apol_MLS::vals(senslist)]
+ Apol_Widget::setListboxCallbacks $sensbox \
+ {{"Show Sensitivity Info" {Apol_MLS::_popupSensInfo}}}
+ pack $sensbox -expand 1 -fill both
+ set catsbox [Apol_Widget::makeScrolledListbox [$catsbox getframe].cats \
+ -height 16 -width 20 -listvar Apol_MLS::vals(catslist)]
+ Apol_Widget::setListboxCallbacks $catsbox \
+ {{"Show Category Info" {Apol_MLS::_popupCatsInfo}}}
+ pack $catsbox -expand 1 -fill both
+
+ # build the search options
+ set optsbox [TitleFrame $rightf.optsbox -text "Search Options"]
+ pack $optsbox -side top -expand 0 -fill both -padx 2
+ set sensf [frame [$optsbox getframe].sensf]
+ set catsf [frame [$optsbox getframe].catsf]
+ pack $sensf $catsf -side left -padx 4 -pady 2 -anchor nw
+
+ set enable_sens [checkbutton $sensf.enable -text "Sensitivities" \
+ -variable Apol_MLS::vals(enable_sens)]
+ set show_cats [checkbutton $sensf.cats -text "Show levels (categories)" \
+ -variable Apol_MLS::vals(show_cats_too)]
+ trace add variable Apol_MLS::vals(enable_sens) write \
+ [list Apol_MLS::_toggleCheckbutton $show_cats]
+ pack $enable_sens -side top -anchor nw
+ pack $show_cats -side top -anchor nw -padx 8
+
+ set enable_cats [checkbutton $catsf.enable -text "Categories" \
+ -variable Apol_MLS::vals(enable_cats)]
+ set show_sens [checkbutton $catsf.cats -text "Show sensitivities" \
+ -variable Apol_MLS::vals(show_sens_too) -state disabled]
+ trace add variable Apol_MLS::vals(enable_cats) write \
+ [list Apol_MLS::_toggleCheckbutton $show_sens]
+ pack $enable_cats -side top -anchor nw
+ pack $show_sens -side top -anchor nw -padx 8
+
+ set widgets(regexp) [Apol_Widget::makeRegexpEntry [$optsbox getframe].regexpf]
+ pack $widgets(regexp) -side left -padx 4 -pady 2 -anchor nw
+
+ set ok [button [$optsbox getframe].ok -text "OK" -width 6 \
+ -command Apol_MLS::_search]
+ pack $ok -side right -pady 5 -padx 5 -anchor ne
+
+ # build the results box
+ set resultsbox [TitleFrame $rightf.resultsbox -text "Search Results"]
+ pack $resultsbox -expand yes -fill both -padx 2
+ set widgets(results) [Apol_Widget::makeSearchResults [$resultsbox getframe].results]
+ pack $widgets(results) -side top -expand yes -fill both
+
+ return $frame
+}
+
+proc Apol_MLS::open {ppath} {
+ variable vals
+
+ set q [new_apol_level_query_t]
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set vals(senslist) [lsort [level_vector_to_list $v]]
+ $v -acquire
+ $v -delete
+
+ set q [new_apol_cat_query_t]
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set vals(catslist) [lsort [cat_vector_to_list $v]]
+ $v -acquire
+ $v -delete
+}
+
+proc Apol_MLS::close {} {
+ variable widgets
+
+ _initializeVars
+ Apol_Widget::clearSearchResults $widgets(results)
+}
+
+proc Apol_MLS::getTextWidget {} {
+ variable widgets
+ return $widgets(results).tb
+}
+
+# Given a sensitivity name, return a non-empty string if that
+# sensitivity is within the loaded policy. This string is the same as
+# the given parameter if the name is a sensitivity; it will be the
+# real sensitivity's name if the parameter is an alias. If no policy
+# has been loaded then return an empty string.
+proc Apol_MLS::isSensInPolicy {sens} {
+ variable vals
+ if {![ApolTop::is_policy_open]} {
+ return {}
+ }
+ if {[lsearch $vals(senslist) $sens] >= 0} {
+ return $sens
+ }
+ # try looking up aliases
+ foreach s $vals(senslist) {
+ set qpol_level_t [new_qpol_level_t $::ApolTop::qpolicy $s]
+ set i [$qpol_level_t get_alias_iter $::ApolTop::qpolicy]
+ set l [iter_to_str_list $i]
+ $i -acquire
+ $i -delete
+ if {[lsearch $l $sens] >= 0} {
+ return $s
+ }
+ }
+ return {}
+}
+
+#### private functions below ####
+
+proc Apol_MLS::_initializeVars {} {
+ variable vals
+ array set vals {
+ senslist {} catslist {}
+ enable_sens 1 show_cats_too 1
+ enable_cats 0 show_sens_too 1
+ }
+}
+
+proc Apol_MLS::_toggleCheckbutton {path name1 name2 op} {
+ variable vals
+ variable widgets
+ if {$vals($name2)} {
+ $path configure -state normal
+ } else {
+ $path configure -state disabled
+ }
+ if {$vals(enable_sens) == 0 && $vals(enable_cats) == 0} {
+ Apol_Widget::setRegexpEntryState $widgets(regexp) 0
+ } else {
+ Apol_Widget::setRegexpEntryState $widgets(regexp) 1
+ }
+}
+
+proc Apol_MLS::_popupSensInfo {sens} {
+ Apol_Widget::showPopupText $sens [_renderLevel $sens 1]
+}
+
+proc Apol_MLS::_popupCatsInfo {cats} {
+ Apol_Widget::showPopupText $cats [_renderCats $cats 1]
+}
+
+
+proc Apol_MLS::_renderLevel {level_name show_level} {
+ set qpol_level_datum [new_qpol_level_t $::ApolTop::qpolicy $level_name]
+ set i [$qpol_level_datum get_alias_iter $::ApolTop::qpolicy]
+ set aliases [iter_to_str_list $i]
+ $i -acquire
+ $i -delete
+
+ set text $level_name
+ if {[llength $aliases] > 0} {
+ append text " alias \{$aliases\}"
+ }
+ if {$show_level} {
+ set i [$qpol_level_datum get_cat_iter $::ApolTop::qpolicy]
+ set num_cats [$i get_size]
+ $i -acquire
+ $i -delete
+ append text " ($num_cats categor"
+ if {$num_cats == 1} {
+ append text "y)"
+ } else {
+ append text "ies)"
+ }
+ set level [new_apol_mls_level_t $::ApolTop::policy $qpol_level_datum]
+ append text "\n level [$level render $::ApolTop::policy]\n"
+ $level -acquire
+ $level -delete
+ }
+ return $text
+}
+
+proc Apol_MLS::_renderCats {cat_name show_sens} {
+ set qpol_cat_datum [new_qpol_cat_t $::ApolTop::qpolicy $cat_name]
+ set i [$qpol_cat_datum get_alias_iter $::ApolTop::qpolicy]
+ set aliases [iter_to_str_list $i]
+ $i -acquire
+ $i -delete
+
+ set text $cat_name
+ if {[llength $aliases] > 0} {
+ append text " alias \{$aliases\}"
+ }
+ if {$show_sens} {
+ append text "\n"
+ set q [new_apol_level_query_t]
+ $q set_cat $::ApolTop::policy $cat_name
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set sens_list {}
+ for {set i 0} {$i < [$v get_size]} {incr i} {
+ set qpol_level_datum [qpol_level_from_void [$v get_element $i]]
+ set level_name [$qpol_level_datum get_name $::ApolTop::qpolicy]
+ set level_value [$qpol_level_datum get_value $::ApolTop::qpolicy]
+ lappend sens_list [list $level_name $level_value]
+ }
+ $v -acquire
+ $v -delete
+ foreach s [lsort -integer -index 1 $sens_list] {
+ append text " [lindex $s 0]\n"
+ }
+ }
+ return $text
+}
+
+proc Apol_MLS::_search {} {
+ variable vals
+ variable widgets
+ Apol_Widget::clearSearchResults $widgets(results)
+ if {![ApolTop::is_policy_open]} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No current policy file is opened."
+ return
+ }
+ if {$vals(enable_sens) == 0 && $vals(enable_cats) == 0} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No search options provided."
+ return
+ }
+ set results ""
+ set use_regexp [Apol_Widget::getRegexpEntryState $widgets(regexp)]
+ if {$use_regexp} {
+ set regexp [Apol_Widget::getRegexpEntryValue $widgets(regexp)]
+ if {$regexp == {}} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No regular expression provided."
+ return
+ }
+ } else {
+ set regexp {}
+ }
+ if {$vals(enable_sens)} {
+ set q [new_apol_level_query_t]
+ $q set_sens $::ApolTop::policy $regexp
+ $q set_regex $::ApolTop::policy $use_regexp
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+
+ set level_data {}
+ for {set i 0} {$i < [$v get_size]} {incr i} {
+ set qpol_level_datum [qpol_level_from_void [$v get_element $i]]
+ set level_name [$qpol_level_datum get_name $::ApolTop::qpolicy]
+ set level_value [$qpol_level_datum get_value $::ApolTop::qpolicy]
+ lappend level_data [list $level_name $level_value]
+ }
+ $v -acquire
+ $v -delete
+
+ append results "SENSITIVITIES (ordered by dominance from low to high):"
+ if {[llength $level_data] == 0} {
+ append results "\nSearch returned no results."
+ } else {
+ foreach l [lsort -integer -index 1 $level_data] {
+ append results "\n[_renderLevel [lindex $l 0] $vals(show_cats_too)]"
+ }
+ }
+ }
+ if {$vals(enable_cats)} {
+ if {$vals(enable_sens)} {
+ append results "\n\n"
+ }
+
+ set q [new_apol_cat_query_t]
+ $q set_cat $::ApolTop::policy $regexp
+ $q set_regex $::ApolTop::policy $use_regexp
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+
+ set cats_data {}
+ for {set i 0} {$i < [$v get_size]} {incr i} {
+ set qpol_cat_datum [qpol_cat_from_void [$v get_element $i]]
+ set cat_name [$qpol_cat_datum get_name $::ApolTop::qpolicy]
+ set cat_value [$qpol_cat_datum get_value $::ApolTop::qpolicy]
+ lappend cats_data [list $cat_name $cat_value]
+ }
+ $v -acquire
+ $v -delete
+
+ append results "CATEGORIES (ordered by appearance within policy):"
+ if {[llength $cats_data] == 0} {
+ append results "\nSearch returned no results."
+ } else {
+ foreach c [lsort -integer -index 1 $cats_data] {
+ append results "\n[_renderCats [lindex $c 0] $vals(show_sens_too)]"
+ }
+ }
+ }
+ Apol_Widget::appendSearchResultText $widgets(results) $results
+}
diff --git a/apol/netcontexts_tab.tcl b/apol/netcontexts_tab.tcl
new file mode 100644
index 0000000..d59d19c
--- /dev/null
+++ b/apol/netcontexts_tab.tcl
@@ -0,0 +1,878 @@
+# Copyright (C) 2001-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
+
+namespace eval Apol_NetContexts {
+ variable widgets
+ variable vals
+}
+
+proc Apol_NetContexts::create {tab_name nb} {
+ variable widgets
+ variable vals
+
+ _initializeVars
+
+ # Layout frames
+ set frame [$nb insert end $tab_name -text "Net Contexts"]
+ set pw [PanedWindow $frame.pw -side top -weights extra]
+ set leftf [$pw add -weight 0]
+ set rightf [$pw add -weight 1]
+ pack $pw -fill both -expand yes
+
+ # build the left column, where one selects a particular type of
+ # context; below it will be a scrolled listbox of keys for that
+ # context
+ set context_box [TitleFrame $leftf.context_f -text "Context Type"]
+ set context_f [$context_box getframe]
+ radiobutton $context_f.portcon -text "portcon" -value portcon \
+ -variable Apol_NetContexts::vals(context_type)
+ radiobutton $context_f.netifcon -text "netifcon" -value netifcon \
+ -variable Apol_NetContexts::vals(context_type)
+ radiobutton $context_f.nodecon -text "nodecon" -value nodecon \
+ -variable Apol_NetContexts::vals(context_type)
+ trace add variable Apol_NetContexts::vals(context_type) write \
+ {Apol_NetContexts::_contextTypeChanged}
+ pack $context_f.portcon $context_f.netifcon $context_f.nodecon \
+ -anchor w -expand 0 -padx 4 -pady 5
+ pack $context_box -anchor nw -expand 0 -fill x
+
+ set widgets(items_tf) [TitleFrame $leftf.items_f -text "Port Contexts"]
+ set widgets(items) [Apol_Widget::makeScrolledListbox [$widgets(items_tf) getframe].items \
+ -height 20 -width 20 -listvar Apol_NetContexts::vals(items)]
+ Apol_Widget::setListboxCallbacks $widgets(items) \
+ {{"Show Context Info" {Apol_NetContexts::_popupContextInfo}}}
+ pack $widgets(items) -expand 1 -fill both
+ pack $widgets(items_tf) -expand 1 -fill both
+
+ # build the search options
+ set optsbox [TitleFrame $rightf.optsbox -text "Search Options"]
+ pack $optsbox -side top -expand 0 -fill both -padx 2
+ set widgets(options_pm) [PagesManager [$optsbox getframe].pm]
+
+ _portcon_create [$widgets(options_pm) add portcon]
+ _netifcon_create [$widgets(options_pm) add netifcon]
+ _nodecon_create [$widgets(options_pm) add nodecon]
+
+ $widgets(options_pm) compute_size
+ pack $widgets(options_pm) -expand 1 -fill both -side left
+ $widgets(options_pm) raise portcon
+
+ set ok [button [$optsbox getframe].ok -text "OK" -width 6 \
+ -command Apol_NetContexts::_runSearch]
+ pack $ok -side right -pady 5 -padx 5 -anchor ne
+
+ set resultsbox [TitleFrame $rightf.resultsbox -text "Search Results"]
+ pack $resultsbox -expand yes -fill both -padx 2
+ set widgets(results) [Apol_Widget::makeSearchResults [$resultsbox getframe].results]
+ pack $widgets(results) -side top -expand yes -fill both
+
+ return $frame
+}
+
+proc Apol_NetContexts::open {ppath} {
+ variable vals
+
+ _portcon_open
+ _netifcon_open
+ _nodecon_open
+
+ # force a flip to the portcon page
+ set vals(context_type) portcon
+}
+
+proc Apol_NetContexts::close {} {
+ variable widgets
+
+ _initializeVars
+ Apol_Widget::clearSearchResults $widgets(results)
+ Apol_Widget::clearContextSelector $widgets(portcon:context)
+ Apol_Widget::clearContextSelector $widgets(netifcon:ifcon)
+ Apol_Widget::clearContextSelector $widgets(netifcon:msgcon)
+ Apol_Widget::clearContextSelector $widgets(nodecon:context)
+ $widgets(portcon:proto) configure -values {}
+ $widgets(netifcon:dev) configure -values {}
+}
+
+proc Apol_NetContexts::getTextWidget {} {
+ variable widgets
+ return $widgets(results).tb
+}
+
+#### private functions below ####
+
+proc Apol_NetContexts::_initializeVars {} {
+ variable vals
+ array set vals {
+ portcon:items {}
+ portcon:proto_enable 0 portcon:proto {}
+ portcon:port_enable 0 portcon:port 0
+ portcon:hiport_enable 0 portcon:hiport 0
+
+ netifcon:items {}
+ netifcon:dev_enable 0 netifcon:dev {}
+
+ nodecon:items {}
+ nodecon:ip_type ipv4
+ nodecon:ipv4_addr_enable 0
+ nodecon:ipv4_addr0 0 nodecon:ipv4_addr1 0
+ nodecon:ipv4_addr2 0 nodecon:ipv4_addr3 0
+ nodecon:ipv4_mask_enable 0
+ nodecon:ipv4_mask0 255 nodecon:ipv4_mask1 255
+ nodecon:ipv4_mask2 255 nodecon:ipv4_mask3 255
+ nodecon:ipv6_addr_enable 0 nodecon:ipv6_addr ::
+ nodecon:ipv6_mask_enable 0 nodecon:ipv6_mask ::
+
+ items {}
+ context_type portcon
+ }
+}
+
+proc Apol_NetContexts::_contextTypeChanged {name1 name2 op} {
+ variable vals
+ variable widgets
+ Apol_Widget::clearSearchResults $widgets(results)
+ if {$vals(context_type) == "portcon"} {
+ _portcon_show
+ } elseif {$vals(context_type) == "netifcon"} {
+ _netifcon_show
+ } else {
+ _nodecon_show
+ }
+}
+
+proc Apol_NetContexts::_popupContextInfo {value} {
+ variable vals
+ if {$vals(context_type) == "portcon"} {
+ _portcon_popup $value
+ } elseif {$vals(context_type) == "netifcon"} {
+ _netifcon_popup $value
+ } else {
+ _nodecon_popup $value
+ }
+}
+
+proc Apol_NetContexts::_toggleCheckbutton {path name1 name2 op} {
+ variable vals
+ variable widgets
+ if {$vals($name2)} {
+ $path configure -state normal
+ } else {
+ $path configure -state disabled
+ }
+}
+
+proc Apol_NetContexts::_runSearch {} {
+ variable vals
+ variable widgets
+
+ Apol_Widget::clearSearchResults $widgets(results)
+ if {![ApolTop::is_policy_open]} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No current policy file is opened."
+ return
+ }
+ if {$vals(context_type) == "portcon"} {
+ _portcon_runSearch
+ } elseif {$vals(context_type) == "netifcon"} {
+ _netifcon_runSearch
+ } else {
+ _nodecon_runSearch
+ }
+}
+
+#### portcon private functions below ####
+
+# create the portcon-specific options widgets
+proc Apol_NetContexts::_portcon_create {p_f} {
+ variable widgets
+ variable vals
+
+ frame $p_f.proto
+ set proto_cb [checkbutton $p_f.proto.proto_enable -text "Protocol" \
+ -variable Apol_NetContexts::vals(portcon:proto_enable)]
+ set widgets(portcon:proto) [ComboBox $p_f.proto.proto -entrybg white -width 8 -state disabled \
+ -textvariable Apol_NetContexts::vals(portcon:proto) -autopost 1]
+ trace add variable Apol_NetContexts::vals(portcon:proto_enable) write \
+ [list Apol_NetContexts::_toggleCheckbutton $widgets(portcon:proto)]
+ pack $proto_cb -side top -anchor w
+ pack $widgets(portcon:proto) -side top -expand 0 -fill x -padx 4
+
+ frame $p_f.port
+ set low [frame $p_f.port.l]
+ set port_cb [checkbutton $low.port_enable -text "Single Port" \
+ -variable Apol_NetContexts::vals(portcon:port_enable)]
+ set widgets(portcon:port) [spinbox $low.port -bg white -width 8 \
+ -justify right -state disabled \
+ -from 0 -to 65535 \
+ -validate all -vcmd [list Apol_NetContexts::_portcon_limitPort %W %V %P port] \
+ -textvariable Apol_NetContexts::vals(portcon:port)]
+ set high [frame $p_f.port.h]
+ set hiport_cb [checkbutton $high.hiport_enable -text "High Port" \
+ -state disabled \
+ -variable Apol_NetContexts::vals(portcon:hiport_enable)]
+ set widgets(portcon:hiport) [spinbox $high.hiport -bg white -width 8 \
+ -justify right -state disabled \
+ -from 0 -to 65535 \
+ -validate all -vcmd [list Apol_NetContexts::_portcon_limitPort %W %V %P hiport] \
+ -textvariable Apol_NetContexts::vals(portcon:hiport)]
+ trace add variable Apol_NetContexts::vals(portcon:port_enable) write \
+ [list Apol_NetContexts::_portcon_toggleCheckbutton_lowport \
+ $widgets(portcon:port) $hiport_cb $widgets(portcon:hiport)]
+ trace add variable Apol_NetContexts::vals(portcon:hiport_enable) write \
+ [list Apol_NetContexts::_portcon_toggleCheckbutton_hiport $port_cb $widgets(portcon:hiport)]
+ pack $port_cb -side top -anchor w -expand 0
+ pack $widgets(portcon:port) -side top -expand 0 -fill x -padx 4
+ pack $hiport_cb -side top -anchor w -expand 0
+ pack $widgets(portcon:hiport) -side top -expand 0 -fill x -padx 4
+ pack $low $high -side left -expand 0 -fill both
+
+ frame $p_f.c
+ set widgets(portcon:context) [Apol_Widget::makeContextSelector $p_f.c.context "Contexts"]
+ pack $widgets(portcon:context)
+ pack $p_f.proto $p_f.port $p_f.c -side left -padx 4 -pady 2 -anchor nw
+}
+
+proc Apol_NetContexts::_portcon_open {} {
+ variable vals
+
+ set q [new_apol_portcon_query_t]
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set portcons [portcon_vector_to_list $v]
+ $v -acquire
+ $v -delete
+ set vals(portcon:items) {}
+ set protos {}
+ foreach p $portcons {
+ set low [$p get_low_port $::ApolTop::qpolicy]
+ set high [$p get_high_port $::ApolTop::qpolicy]
+ set proto [$p get_protocol $::ApolTop::qpolicy]
+ if {$low == $high} {
+ lappend vals(portcon:items) $low
+ } else {
+ lappend vals(portcon:items) "$low-$high"
+ }
+ lappend protos [apol_protocol_to_str $proto]
+ }
+
+ variable widgets
+ set vals(portcon:items) [lsort -unique -dictionary $vals(portcon:items)]
+ $widgets(portcon:proto) configure -values [lsort -unique -dictionary $protos]
+}
+
+proc Apol_NetContexts::_portcon_show {} {
+ variable vals
+ variable widgets
+ $widgets(items_tf) configure -text "Port Contexts"
+ $widgets(options_pm) raise portcon
+ set vals(items) $vals(portcon:items)
+}
+
+proc Apol_NetContexts::_portcon_popup {port} {
+ foreach {low high} [split $port "-"] {break}
+ if {$high == {}} {
+ set high $low
+ }
+
+ set q [new_apol_portcon_query_t]
+ $q set_low $::ApolTop::policy $low
+ $q set_high $::ApolTop::policy $high
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set portcons [portcon_vector_to_list $v]
+ $v -acquire
+ $v -delete
+
+ set text "port $port ([llength $portcons] context"
+ if {[llength $portcons] != 1} {
+ append text s
+ }
+ append text ")"
+ foreach p [lsort -command _portcon_sort $portcons] {
+ append text "\n [_portcon_render $p]"
+ }
+ Apol_Widget::showPopupText "port $port" $text
+}
+
+proc Apol_NetContexts::_portcon_limitPort {widget command new_port varname} {
+ variable vals
+ if {$command == "key"} {
+ if {$new_port != "" &&
+ (![string is integer $new_port] || $new_port < 0 || $new_port > 65535)} {
+ return 0
+ }
+ } elseif {$command == "focusout"} {
+ if {$new_port == ""} {
+ set vals(portcon:$varname) 0
+ } elseif {[string length $new_port] > 1} {
+ set vals(portcon:$varname) [string trimleft $new_port " 0"]
+ }
+
+ # re-enable the validation command (it could have been
+ # disabled because the variable changed)
+ $widget config -validate all
+ }
+ return 1
+}
+
+proc Apol_NetContexts::_portcon_toggleCheckbutton_lowport {low high_cb high name1 name2 op} {
+ variable vals
+ variable widgets
+ if {$vals($name2)} {
+ $low configure -state normal
+ $high_cb configure -state normal
+ if {$vals(portcon:hiport_enable)} {
+ $high configure -state normal
+ }
+ } else {
+ $low configure -state disabled
+ $high_cb configure -state disabled
+ $high configure -state disabled
+ }
+}
+
+proc Apol_NetContexts::_portcon_toggleCheckbutton_hiport {low high name1 name2 op} {
+ variable vals
+ variable widgets
+ if {$vals($name2)} {
+ $low configure -text "Low Port"
+ $high configure -state normal
+ } else {
+ $low configure -text "Single Port"
+ $high configure -state disabled
+ }
+}
+
+proc Apol_NetContexts::_portcon_runSearch {} {
+ variable vals
+ variable widgets
+
+ # explicitly validate the spinboxes (they could still have focus)
+ _portcon_limitPort $widgets(portcon:port) focusout $vals(portcon:port) port
+ _portcon_limitPort $widgets(portcon:hiport) focusout $vals(portcon:hiport) hiport
+
+ if {$vals(portcon:port_enable)} {
+ set low $vals(portcon:port)
+ set high $low
+ if {$vals(portcon:hiport_enable)} {
+ set high $vals(portcon:hiport)
+ if {$vals(portcon:port_enable) && $high < $low} {
+ tk_messageBox -icon error -type ok -title "Error" -message "The second port is not greater than the first."
+ return
+ }
+ }
+ } else {
+ set low -1
+ set high -1
+ }
+
+ set q [new_apol_portcon_query_t]
+ $q set_low $::ApolTop::policy $low
+ $q set_high $::ApolTop::policy $high
+ if {$vals(portcon:proto_enable)} {
+ if {[set proto $vals(portcon:proto)] == {}} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No protocol selected."
+ return
+ }
+ $q set_protocol $::ApolTop::policy [apol_str_to_protocol $proto]
+ }
+ if {[Apol_Widget::getContextSelectorState $widgets(portcon:context)]} {
+ foreach {context range_match attribute} [Apol_Widget::getContextSelectorValue $widgets(portcon:context)] {break}
+ $q set_context $::ApolTop::policy $context $range_match
+ }
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set portcons [portcon_vector_to_list $v]
+ $v -acquire
+ $v -delete
+
+ set results "PORTCONS:"
+ if {[llength $portcons] == 0} {
+ append results "\nSearch returned no results."
+ } else {
+ foreach p [lsort -command _portcon_sort $portcons] {
+ append results "\n[_portcon_render $p]"
+ }
+ }
+ Apol_Widget::appendSearchResultText $widgets(results) $results
+}
+
+proc Apol_NetContexts::_portcon_render {qpol_portcon_datum} {
+ set loport [$qpol_portcon_datum get_low_port $::ApolTop::qpolicy]
+ set hiport [$qpol_portcon_datum get_high_port $::ApolTop::qpolicy]
+ set proto [apol_protocol_to_str [$qpol_portcon_datum get_protocol $::ApolTop::qpolicy]]
+ set qpol_context [$qpol_portcon_datum get_context $::ApolTop::qpolicy]
+ if {$loport == $hiport} {
+ set line "portcon $proto $loport "
+ } else {
+ set line "portcon $proto ${loport}-${hiport} "
+ }
+ concat $line [apol_qpol_context_render $::ApolTop::policy $qpol_context]
+}
+
+proc Apol_NetContexts::_portcon_sort {a b} {
+ set loport1 [$a get_low_port $::ApolTop::qpolicy]
+ set hiport1 [$a get_high_port $::ApolTop::qpolicy]
+ set loport2 [$b get_low_port $::ApolTop::qpolicy]
+ set hiport2 [$b get_high_port $::ApolTop::qpolicy]
+ if {$loport1 == $hiport1} {
+ set singleport1 1
+ } else {
+ set singleport1 0
+ }
+ if {$loport2 == $hiport2} {
+ set singleport2 1
+ } else {
+ set singleport2 0
+ }
+ if {$singleport1 && !$singleport2} {
+ return -1
+ } elseif {!$singleport1 && $singleport2} {
+ return 1
+ }
+ if {$loport1 < $loport2} {
+ return -1
+ } elseif {$loport1 > $loport2} {
+ return 1
+ }
+ if {$hiport1 < $hiport2} {
+ return -1
+ } elseif {$hiport1 > $hiport2} {
+ return 1
+ }
+ set proto1 [apol_protocol_to_str [$a get_protocol $::ApolTop::qpolicy]]
+ set proto2 [apol_protocol_to_str [$b get_protocol $::ApolTop::qpolicy]]
+ string compare $proto1 $proto2
+}
+
+#### netifcon private functions below ####
+
+proc Apol_NetContexts::_netifcon_create {p_f} {
+ variable vals
+ variable widgets
+
+ frame $p_f.dev
+ set dev_cb [checkbutton $p_f.dev.dev_enable -text "Device" \
+ -variable Apol_NetContexts::vals(netifcon:dev_enable)]
+ set widgets(netifcon:dev) [ComboBox $p_f.dev.dev -entrybg white -width 8 -state disabled \
+ -textvariable Apol_NetContexts::vals(netifcon:dev) -autopost 1]
+ trace add variable Apol_NetContexts::vals(netifcon:dev_enable) write \
+ [list Apol_NetContexts::_toggleCheckbutton $widgets(netifcon:dev)]
+ pack $dev_cb -side top -anchor w
+ pack $widgets(netifcon:dev) -side top -expand 0 -fill x -padx 4
+
+ frame $p_f.ifcon
+ set widgets(netifcon:ifcon) [Apol_Widget::makeContextSelector $p_f.ifcon.context "Contexts" "Interface context" -width 18]
+ pack $widgets(netifcon:ifcon)
+
+ frame $p_f.msgcon
+ set widgets(netifcon:msgcon) [Apol_Widget::makeContextSelector $p_f.msgcon.context "Contexts" "Message context" -width 18]
+ pack $widgets(netifcon:msgcon)
+
+ pack $p_f.dev $p_f.ifcon $p_f.msgcon -side left -padx 4 -pady 2 -anchor nw
+}
+
+proc Apol_NetContexts::_netifcon_open {} {
+ variable vals
+
+ set q [new_apol_netifcon_query_t]
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set vals(netifcon:items) [lsort [netifcon_vector_to_list $v]]
+ $v -acquire
+ $v -delete
+
+ variable widgets
+ $widgets(netifcon:dev) configure -values $vals(netifcon:items)
+}
+
+proc Apol_NetContexts::_netifcon_show {} {
+ variable vals
+ variable widgets
+ $widgets(items_tf) configure -text "NetIF Contexts"
+ $widgets(options_pm) raise netifcon
+ set vals(items) $vals(netifcon:items)
+}
+
+proc Apol_NetContexts::_netifcon_popup {netif} {
+ set text "network interface $netif"
+ append text "\n [_netifcon_render $netif]"
+ Apol_Widget::showPopupText "interface $netif" $text
+}
+
+proc Apol_NetContexts::_netifcon_runSearch {} {
+ variable vals
+ variable widgets
+
+ if {$vals(netifcon:dev_enable)} {
+ if {$vals(netifcon:dev) == {}} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No device selected."
+ return
+ }
+ set dev $vals(netifcon:dev)
+ } else {
+ set dev {}
+ }
+
+ set q [new_apol_netifcon_query_t]
+ $q set_device $::ApolTop::policy $dev
+ if {[Apol_Widget::getContextSelectorState $widgets(netifcon:ifcon)]} {
+ foreach {context range_match attribute} [Apol_Widget::getContextSelectorValue $widgets(netifcon:ifcon)] {break}
+ $q set_if_context $::ApolTop::policy $context $range_match
+ }
+ if {[Apol_Widget::getContextSelectorState $widgets(netifcon:msgcon)]} {
+ foreach {context range_match attribute} [Apol_Widget::getContextSelectorValue $widgets(netifcon:msgcon)] {break}
+ $q set_msg_context $::ApolTop::policy $context $range_match
+ }
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set netifcons [netifcon_vector_to_list $v]
+ $v -acquire
+ $v -delete
+
+ set results "NETIFCONS:"
+ if {[llength $netifcons] == 0} {
+ append results "\nSearch returned no results."
+ } else {
+ foreach n [lsort $netifcons] {
+ append results "\n[_netifcon_render $n]"
+ }
+ }
+ Apol_Widget::appendSearchResultText $widgets(results) $results
+}
+
+proc Apol_NetContexts::_netifcon_render {netifcon} {
+ set qpol_netifcon_datum [new_qpol_netifcon_t $::ApolTop::qpolicy $netifcon]
+ apol_netifcon_render $::ApolTop::policy $qpol_netifcon_datum
+}
+
+#### nodecon private functions below ####
+
+proc Apol_NetContexts::_nodecon_create {p_f} {
+ variable vals
+ variable widgets
+
+ frame $p_f.ip_type
+ set ipv4_rb [radiobutton $p_f.ip_type.v4 -text "IPv4" -value ipv4 \
+ -variable Apol_NetContexts::vals(nodecon:ip_type)]
+ set ipv6_rb [radiobutton $p_f.ip_type.v6 -text "IPv6" -value ipv6 \
+ -variable Apol_NetContexts::vals(nodecon:ip_type)]
+ trace add variable Apol_NetContexts::vals(nodecon:ip_type) write \
+ [list Apol_NetContexts::_nodecon_pageChanged]
+ pack $ipv4_rb $ipv6_rb -side top -anchor nw -pady 5
+
+ frame $p_f.opts
+ set widgets(nodecon:ip_pm) [PagesManager $p_f.opts.pm]
+ _nodecon_ipv4Create [$widgets(nodecon:ip_pm) add ipv4]
+ _nodecon_ipv6Create [$widgets(nodecon:ip_pm) add ipv6]
+ $widgets(nodecon:ip_pm) compute_size
+ pack $widgets(nodecon:ip_pm)
+ $widgets(nodecon:ip_pm) raise ipv4
+
+ frame $p_f.con
+ set widgets(nodecon:context) [Apol_Widget::makeContextSelector $p_f.con.context "Contexts"]
+ pack $widgets(nodecon:context)
+
+ pack $p_f.ip_type $p_f.opts $p_f.con -side left -padx 4 -pady 2 -anchor nw
+}
+
+proc Apol_NetContexts::_nodecon_open {} {
+ set q [new_apol_nodecon_query_t]
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set nodecons [nodecon_vector_to_list $v]
+
+ variable vals
+ variable widgets
+ set vals(nodecon:items) {}
+ foreach n [lsort -command _nodecon_sort $nodecons] {
+ set proto [$n get_protocol $::ApolTop::qpolicy]
+ set addr [$n get_addr $::ApolTop::qpolicy]
+ if {$proto == $::QPOL_IPV4} {
+ set addr [apol_ipv4_addr_render $::ApolTop::policy $addr]
+ } elseif {$proto == $::QPOL_IPV6} {
+ set addr [apol_ipv6_addr_render $::ApolTop::policy $addr]
+ } else {
+ puts stderr "Unknown protocol $proto"
+ exit -1
+ }
+ lappend vals(nodecon:items) $addr
+ }
+ set vals(nodecon:items) [lsort -unique -dictionary $vals(nodecon:items)]
+
+ # because qpol_policy_get_nodecon_iter() returns allocated items,
+ # destroying the vector before using its items will segfault
+ $v -acquire
+ $v -delete
+}
+
+proc Apol_NetContexts::_nodecon_show {} {
+ variable vals
+ variable widgets
+ $widgets(items_tf) configure -text "Node Contexts"
+ $widgets(options_pm) raise nodecon
+ set vals(items) $vals(nodecon:items)
+}
+
+proc Apol_NetContexts::_nodecon_ipv4Create {fv4} {
+ variable widgets
+ set v4addrf [frame $fv4.addr]
+ set ipv4_addr_cb [checkbutton $v4addrf.enable -text "IP address" \
+ -variable Apol_NetContexts::vals(nodecon:ipv4_addr_enable)]
+ set widgets(nodecon:v4addrf2) [frame $v4addrf.a]
+ for {set i 0} {$i < 4} {incr i} {
+ set e [entry $widgets(nodecon:v4addrf2).e$i -bg white -justify center -width 4 \
+ -state disabled \
+ -validate all -vcmd [list Apol_NetContexts::_nodecon_limitAddr %W %V %P ipv4_addr$i] \
+ -textvariable Apol_NetContexts::vals(nodecon:ipv4_addr$i)]
+ pack $e -side left -padx 1 -anchor center
+ if {$i < 3} {
+ pack [label $widgets(nodecon:v4addrf2).l$i -text "."] -side left -expand 0 -anchor s
+ }
+ }
+ trace add variable Apol_NetContexts::vals(nodecon:ipv4_addr_enable) write \
+ [list Apol_NetContexts::_nodecon_toggleV4button $widgets(nodecon:v4addrf2).e]
+ pack $ipv4_addr_cb -anchor w
+ pack $widgets(nodecon:v4addrf2) -padx 3 -expand 0 -fill x
+
+ set v4maskf [frame $fv4.mask]
+ set ipv4_mask_cb [checkbutton $v4maskf.enable -text "Mask" \
+ -variable Apol_NetContexts::vals(nodecon:ipv4_mask_enable)]
+ set widgets(nodecon:v4maskf2) [frame $v4maskf.m]
+ for {set i 0} {$i < 4} {incr i} {
+ set e [entry $widgets(nodecon:v4maskf2).e$i -bg white -justify center -width 4 \
+ -state disabled \
+ -validate all -vcmd [list Apol_NetContexts::_nodecon_limitAddr %W %V %P ipv4_mask$i] \
+ -textvariable Apol_NetContexts::vals(nodecon:ipv4_mask$i)]
+ pack $e -side left -padx 1 -anchor center
+ if {$i < 3} {
+ pack [label $widgets(nodecon:v4maskf2).l$i -text "."] -side left -expand 0 -anchor s
+ }
+ }
+ trace add variable Apol_NetContexts::vals(nodecon:ipv4_mask_enable) write \
+ [list Apol_NetContexts::_nodecon_toggleV4button $widgets(nodecon:v4maskf2).e]
+ pack $ipv4_mask_cb -anchor w
+ pack $widgets(nodecon:v4maskf2) -padx 3 -expand 0 -fill x
+
+ pack $v4addrf $v4maskf -padx 4 -pady 2 -anchor nw
+}
+
+proc Apol_NetContexts::_nodecon_ipv6Create {fv6} {
+ set v6addrf [frame $fv6.addr]
+ set ipv4_addr_cb [checkbutton $v6addrf.enable -text "IP address" \
+ -variable Apol_NetContexts::vals(nodecon:ipv6_addr_enable)]
+ set e [entry $v6addrf.addr -bg white -width 28 -state disabled \
+ -textvariable Apol_NetContexts::vals(nodecon:ipv6_addr)]
+ trace add variable Apol_NetContexts::vals(nodecon:ipv6_addr_enable) write \
+ [list Apol_NetContexts::_toggleCheckbutton $e]
+ pack $ipv4_addr_cb -anchor w
+ pack $e -padx 4 -expand 0 -fill x
+
+ set v6maskf [frame $fv6.mask]
+ set ipv6_mask_cb [checkbutton $v6maskf.enable -text "Mask" \
+ -variable Apol_NetContexts::vals(nodecon:ipv6_mask_enable)]
+ set e [entry $v6maskf.addr -bg white -width 28 -state disabled \
+ -textvariable Apol_NetContexts::vals(nodecon:ipv6_mask)]
+ trace add variable Apol_NetContexts::vals(nodecon:ipv6_mask_enable) write \
+ [list Apol_NetContexts::_toggleCheckbutton $e]
+ pack $ipv6_mask_cb -anchor w
+ pack $e -padx 4 -expand 0 -fill x
+
+ pack $v6addrf $v6maskf -padx 4 -pady 2 -anchor w
+}
+
+proc Apol_NetContexts::_nodecon_pageChanged {name1 name2 op} {
+ variable vals
+ variable widgets
+ $widgets(nodecon:ip_pm) raise $vals(nodecon:ip_type)
+}
+
+proc Apol_NetContexts::_nodecon_limitAddr {widget command new_addr varname} {
+ variable vals
+ if {$command == "key"} {
+ if {$new_addr != "" &&
+ (![string is integer $new_addr] || $new_addr < 0 || $new_addr > 255)} {
+ return 0
+ }
+ } elseif {$command == "focusout"} {
+ if {$new_addr == ""} {
+ set vals(nodecon:$varname) 0
+ } elseif {[string length $new_addr] > 1} {
+ set vals(nodecon:$varname) [string trimleft $new_addr " 0"]
+ }
+
+ # re-enable the validation command (it could have been
+ # disabled because the variable changed)
+ after idle [list $widget config -validate all]
+ }
+ return 1
+}
+
+proc Apol_NetContexts::_nodecon_toggleV4button {path name1 name2 op} {
+ variable vals
+ if {$vals($name2)} {
+ for {set i 0} {$i < 4} {incr i} {
+ ${path}${i} configure -state normal
+ }
+ } else {
+ for {set i 0} {$i < 4} {incr i} {
+ ${path}${i} configure -state disabled
+ }
+ }
+}
+
+proc Apol_NetContexts::_nodecon_popup {nodecon_addr} {
+ set q [new_apol_nodecon_query_t]
+ set ip [apol_str_to_internal_ip $nodecon_addr]
+ $q set_addr $::ApolTop::policy $ip
+ $ip -acquire
+ $ip -delete
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set nodecons [nodecon_vector_to_list $v]
+
+ set text "nodecon $nodecon_addr ([llength $nodecons] context"
+ if {[llength $nodecons] != 1} {
+ append text s
+ }
+ append text ")"
+ foreach n [lsort -command _nodecon_sort $nodecons] {
+ append text "\n [_nodecon_render $n]"
+ }
+ Apol_Widget::showPopupText "address $nodecon_addr" $text
+
+ # because qpol_policy_get_nodecon_iter() returns allocated items,
+ # destroying the vector before using its items will segfault
+ $v -acquire
+ $v -delete
+}
+
+proc Apol_NetContexts::_nodecon_runSearch {} {
+ variable vals
+ variable widgets
+
+ set addr {}
+ set mask {}
+ if {$vals(nodecon:ip_type) == "ipv4"} {
+ # explicitly validate the entries (they could still have focus)
+ foreach i {0 1 2 3} {
+ _nodecon_limitAddr $widgets(nodecon:v4addrf2).e$i focusout $vals(nodecon:ipv4_addr$i) ipv4_addr$i
+ _nodecon_limitAddr $widgets(nodecon:v4maskf2).e$i focusout $vals(nodecon:ipv4_mask$i) ipv4_mask$i
+ }
+ if {$vals(nodecon:ipv4_addr_enable)} {
+ set addr [format "%d.%d.%d.%d" \
+ $vals(nodecon:ipv4_addr0) $vals(nodecon:ipv4_addr1) \
+ $vals(nodecon:ipv4_addr2) $vals(nodecon:ipv4_addr3)]
+ }
+ if {$vals(nodecon:ipv4_mask_enable)} {
+ set mask [format "%d.%d.%d.%d" \
+ $vals(nodecon:ipv4_mask0) $vals(nodecon:ipv4_mask1) \
+ $vals(nodecon:ipv4_mask2) $vals(nodecon:ipv4_mask3)]
+ }
+ set proto $::QPOL_IPV4
+ } else {
+ if {$vals(nodecon:ipv6_addr_enable)} {
+ if {[set addr $vals(nodecon:ipv6_addr)] == {}} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No IPV6 address provided."
+ return
+ }
+ }
+ if {$vals(nodecon:ipv6_mask_enable)} {
+ if {[set mask $vals(nodecon:ipv6_mask)] == {}} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No IPV6 address provided."
+ return
+ }
+ }
+ set proto $::QPOL_IPV6
+ }
+
+ set q [new_apol_nodecon_query_t]
+ $q set_protocol $::ApolTop::policy $proto
+ if {$addr != {}} {
+ if {[catch {apol_str_to_internal_ip $addr} u]} {
+ tk_messageBox -icon error -type ok -title "Error" -message $u
+ return
+ }
+ $q set_addr $::ApolTop::policy $u
+ }
+ if {$mask != {}} {
+ if {[catch {apol_str_to_internal_ip $mask} u]} {
+ tk_messageBox -icon error -type ok -title "Error" -message $u
+ return
+ }
+ $q set_mask $::ApolTop::policy $u
+ }
+ if {[Apol_Widget::getContextSelectorState $widgets(nodecon:context)]} {
+ foreach {context range_match attribute} [Apol_Widget::getContextSelectorValue $widgets(nodecon:context)] {break}
+ $q set_context $::ApolTop::policy $context $range_match
+ }
+
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set nodecons [nodecon_vector_to_list $v]
+
+ set results "NODECONS:"
+ if {[llength $nodecons] == 0} {
+ append results "\nSearch returned no results."
+ } else {
+ foreach n [lsort -command _nodecon_sort $nodecons] {
+ append results "\n[_nodecon_render $n]"
+ }
+ }
+ Apol_Widget::appendSearchResultText $widgets(results) $results
+
+ # because qpol_policy_get_nodecon_iter() returns allocated items,
+ # destroying the vector before using its items will segfault
+ $v -acquire
+ $v -delete
+}
+
+proc Apol_NetContexts::_nodecon_render {qpol_nodecon_datum} {
+ apol_nodecon_render $::ApolTop::policy $qpol_nodecon_datum
+}
+
+# Sort nodecons, grouping ipv4 before ipv6. Then sort by address and
+# then mask.
+proc Apol_NetContexts::_nodecon_sort {a b} {
+ set proto1 [$a get_protocol $::ApolTop::qpolicy]
+ set proto2 [$b get_protocol $::ApolTop::qpolicy]
+ if {$proto1 == $::QPOL_IPV4 && $proto2 == $::QPOL_IPV6} {
+ return -1
+ } elseif {$proto1 == $::QPOL_IPV6 && $proto1 == $::QPOL_IPV4} {
+ return 0
+ }
+
+ if {$proto1 == $::QPOL_IPV4} {
+ set render apol_ipv4_addr_render
+ } else {
+ set render apol_ipv6_addr_render
+ }
+ set addr1 [$render $::ApolTop::policy [$a get_addr $::ApolTop::qpolicy]]
+ set addr2 [$render $::ApolTop::policy [$b get_addr $::ApolTop::qpolicy]]
+ if {[set x [string compare $addr1 $addr2]] != 0} {
+ return $x
+ }
+
+ set mask1 [$render $::ApolTop::policy [$a get_mask $::ApolTop::qpolicy]]
+ set mask2 [$render $::ApolTop::policy [$b get_mask $::ApolTop::qpolicy]]
+ string compare $mask1 $mask2
+}
diff --git a/apol/open_policy_dialog.tcl b/apol/open_policy_dialog.tcl
new file mode 100644
index 0000000..217ca85
--- /dev/null
+++ b/apol/open_policy_dialog.tcl
@@ -0,0 +1,388 @@
+# Copyright (C) 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
+
+namespace eval Apol_Open_Policy_Dialog {
+ variable dialog {}
+ variable widgets
+ variable vars
+}
+
+# Create a dialog box to allow the user to select a policy path.
+proc Apol_Open_Policy_Dialog::getPolicyPath {defaultPath} {
+ variable dialog
+ variable vars
+
+ array unset vars
+ _create_dialog .
+
+ set vars(path_type) "monolithic"
+ set vars(primary_file) {}
+ set vars(last_module) {}
+ set vars(mod_names) {}
+ set vars(mod_vers) {}
+ set vars(mod_paths) {}
+
+ if {$defaultPath != {}} {
+ foreach {path_type primary modules} [policy_path_to_list $defaultPath] {break}
+ set vars(path_type) $path_type
+ if {[set vars(primary_file) $primary] != {}} {
+ $dialog itemconfigure 0 -state normal
+ }
+ set vars(last_module) $vars(primary_file)
+ foreach m $modules {
+ if {[catch {getModuleInfo $m} info]} {
+ tk_messageBox -icon error -type ok -title "Open Module" -message $info -detail "Module file $m" -parent [$dialog getframe]
+ } else {
+ foreach {name vers type} $info {break}
+ lappend vars(mod_names) $name
+ lappend vars(mod_vers) $vers
+ lappend vars(mod_paths) $m
+ set vars(last_module) $m
+ }
+ }
+ }
+ # force a recomputation of button sizes (bug in ButtonBox)
+ $dialog.bbox _redraw
+ $dialog draw
+ destroy $dialog
+}
+
+########## private functions below ##########
+
+proc Apol_Open_Policy_Dialog::_create_dialog {parent} {
+ variable dialog
+ variable widgets
+ variable vars
+
+ destroy $dialog
+ set dialog [Dialog .open_policy_dialog -modal local -parent $parent \
+ -cancel 1 \
+ -separator 1 -homogeneous 1 -title "Open Policy"]
+
+ set f [$dialog getframe]
+
+ set policy_type_f [frame $f.policy_type]
+ pack $policy_type_f -padx 4 -pady 4 -expand 0 -anchor w
+ set l [label $policy_type_f.l -text "Policy Type:"]
+ set mono_cb [radiobutton $policy_type_f.mono -text "Monolithic policy" \
+ -value monolithic \
+ -variable Apol_Open_Policy_Dialog::vars(path_type)]
+ set mod_cb [radiobutton $policy_type_f.mod -text "Modular policy" \
+ -value modular \
+ -variable Apol_Open_Policy_Dialog::vars(path_type)]
+ pack $l -anchor w
+ pack $mono_cb $mod_cb -anchor w -padx 8
+
+ set primary_f [frame $f.primary]
+ pack $primary_f -padx 4 -pady 8 -expand 0 -fill x
+ set widgets(main_label) [label $primary_f.l -text "Policy Filename:"]
+ pack $widgets(main_label) -anchor w
+ frame $primary_f.f
+ pack $primary_f.f -expand 1 -fill x
+ set e [entry $primary_f.f.e -width 32 -bg white \
+ -textvariable Apol_Open_Policy_Dialog::vars(primary_file) \
+ -validate key \
+ -vcmd [list Apol_Open_Policy_Dialog::_validateEntryKey %P]]
+ bind $e <Key-Return> Apol_Open_Policy_Dialog::tryOpenPolicy
+ set b [button $primary_f.f.b -text "Browse" \
+ -command Apol_Open_Policy_Dialog::browsePrimary]
+ pack $e -side left -expand 1 -fill x -padx 4
+ pack $b -side right -expand 0 -padx 4
+
+ set modules_f [frame $f.modules]
+ pack $modules_f -pady 4 -padx 4 -expand 1 -fill both
+ set mod_list_f [frame $modules_f.mods -relief sunken]
+ pack $mod_list_f -side left -expand 1 -fill both -padx 4
+ set mlabel [label $mod_list_f.ml -text "Module:"]
+ set vlabel [label $mod_list_f.vl -text "Version:"]
+ set plabel [label $mod_list_f.pl -text "Path:"]
+ grid $mlabel $vlabel $plabel x -sticky w
+ set dis_bg [$mlabel cget -bg]
+ set ml [listbox $mod_list_f.mods -height 6 -width 10 \
+ -listvariable Apol_Open_Policy_Dialog::vars(mod_names)]
+ set vl [listbox $mod_list_f.vers -height 6 -width 4 \
+ -listvariable Apol_Open_Policy_Dialog::vars(mod_vers)]
+ set pl [listbox $mod_list_f.paths -height 6 -width 24 \
+ -listvariable Apol_Open_Policy_Dialog::vars(mod_paths)]
+ set sb [scrollbar $mod_list_f.sb -orient vertical \
+ -command [list Apol_Open_Policy_Dialog::multiscroll yview]]
+ grid $ml $vl $pl $sb -sticky nsew
+ set widgets(bb) [ButtonBox $modules_f.bb -homogeneous 1 -orient vertical -pady 2]
+ $widgets(bb) add -text "Add" -command Apol_Open_Policy_Dialog::browseModule
+ $widgets(bb) add -text "Remove" -command Apol_Open_Policy_Dialog::removeModule -state disabled
+ $widgets(bb) add -text "Import" -command Apol_Open_Policy_Dialog::importList
+ $widgets(bb) add -text "Export" -command Apol_Open_Policy_Dialog::exportList -state disabled
+ pack $widgets(bb) -side right -expand 0 -anchor n -padx 4 -pady 10
+
+ set widgets(listboxes) [list $ml $vl $pl]
+ set widgets(scrollbar) $sb
+ foreach lb $widgets(listboxes) {
+ $lb configure -yscrollcommand Apol_Open_Policy_Dialog::multiyview \
+ -relief groove -bg white -exportselection 0
+ bind $lb <<ListboxSelect>> \
+ [list Apol_Open_Policy_Dialog::multiselect $lb]
+ }
+
+ trace add variable Apol_Open_Policy_Dialog::vars(path_type) write \
+ [list Apol_Open_Policy_Dialog::togglePathType \
+ [list $mlabel $vlabel $plabel] $dis_bg]
+ $dialog add -text "OK" -command Apol_Open_Policy_Dialog::tryOpenPolicy \
+ -state disabled
+ $dialog add -text "Cancel"
+}
+
+proc Apol_Open_Policy_Dialog::_validateEntryKey {newvalue} {
+ variable vars
+ variable dialog
+ variable widgets
+ if {$newvalue == {}} {
+ $dialog itemconfigure 0 -state disabled
+ $widgets(bb) itemconfigure 3 -state disabled
+ } else {
+ $dialog itemconfigure 0 -state normal
+ if {$vars(path_type) == "modular"} {
+ $widgets(bb) itemconfigure 3 -state normal
+ } else {
+ $widgets(bb) itemconfigure 3 -state disabled
+ }
+ }
+ return 1
+}
+
+proc Apol_Open_Policy_Dialog::togglePathType {labels disabled_bg name1 name2 op} {
+ variable vars
+ variable widgets
+ if {$vars(path_type) == "modular"} {
+ set state normal
+ set bg white
+ $widgets(main_label) configure -text "Base Filename:"
+ } else {
+ set state disabled
+ set bg $disabled_bg
+ $widgets(main_label) configure -text "Policy Filename:"
+ }
+ foreach w $labels {
+ $w configure -state $state
+ }
+ foreach w $widgets(listboxes) {
+ $w configure -state $state -bg $bg
+ }
+ $widgets(bb) configure -state $state
+ if {$state == "normal" && [[lindex $widgets(listboxes) 0] curselection] > 0} {
+ $widgets(bb) itemconfigure 1 -state normal
+ } else {
+ $widgets(bb) itemconfigure 1 -state disabled
+ }
+ if {$state == "normal" && $vars(primary_file) != {}} {
+ $widgets(bb) itemconfigure 3 -state normal
+ } else {
+ $widgets(bb) itemconfigure 3 -state disabled
+ }
+}
+
+proc Apol_Open_Policy_Dialog::browsePrimary {} {
+ variable vars
+ variable dialog
+ .open_policy_dialog.frame.primary.f.b configure -state disabled
+ if {$vars(path_type) == "monolithic"} {
+ set title "Open Monolithic Policy"
+ set initDirName {}
+ } else {
+ set title "Open Modular Policy"
+ if {$vars(primary_file) != {} } {
+ set initDirName [file dirname $vars(primary_file)]
+ } else {
+ set initDirName [file dirname $vars(last_module)]
+ }
+ }
+ set f [tk_getOpenFile -initialdir $initDirName \
+ -initialfile $vars(primary_file) -parent $dialog -title $title]
+ if {$f != {}} {
+ set vars(primary_file) $f
+ $dialog itemconfigure 0 -state normal
+ }
+ .open_policy_dialog.frame.primary.f.b configure -state normal
+}
+
+proc Apol_Open_Policy_Dialog::browseModule {} {
+ variable vars
+ variable dialog
+
+ if {$vars(last_module) != {} } {
+ set initDirName [file dirname $vars(last_module)]
+ } else {
+ set initDirName [file dirname $vars(primary_file)]
+ }
+ set paths [tk_getOpenFile -initialdir $initDirName \
+ -initialfile $vars(last_module) -parent $dialog \
+ -title "Open Module" -multiple 1]
+ if {$paths == {}} {
+ return
+ }
+ foreach f $paths {
+ # tk_getOpenFile returns "initialfile" as a selected file, so skip it.
+ if { $f != $vars(last_module) } {
+ addModule $f
+ }
+ }
+}
+
+proc Apol_Open_Policy_Dialog::addModule {f} {
+ variable vars
+ variable widgets
+ if {[lsearch $vars(mod_paths) $f] >= 0} {
+ tk_messageBox -icon error -type ok -title "Open Module" -message "Module $f was already added." -parent .open_policy_dialog
+ return
+ }
+ if {[catch {getModuleInfo $f} info]} {
+ tk_messageBox -icon error -type ok -title "Open Module" -message $info -detail "Module file $f" -parent .open_policy_dialog
+ } else {
+ foreach {name vers type} $info {break}
+ if {$type == 1} {
+ if {$vars(primary_file) != {}} {
+ if {$vars(primary_file) != $f} {
+ tk_messageBox -icon error -type ok -title "Open Module" -message "Base already set" -detail "Current $vars(primary_file)\n\nNew file $f\n\nIgnoring new file." -parent .open_policy_dialog
+ }
+ return
+ }
+ set vars(primary_file) $f
+ return
+ }
+ set vars(mod_names) [lsort [concat $vars(mod_names) $name]]
+ set i [lsearch $vars(mod_names) $name]
+ set vars(mod_vers) [linsert $vars(mod_vers) $i $vers]
+ set vars(mod_paths) [linsert $vars(mod_paths) $i $f]
+ foreach lb $widgets(listboxes) {
+ $lb selection clear 0 end
+ $lb selection set $i
+ }
+ [lindex $widgets(listboxes) 0] see $i
+ set vars(last_module) $f
+ $widgets(bb) itemconfigure 1 -state normal
+ }
+}
+
+proc Apol_Open_Policy_Dialog::removeModule {} {
+ variable widgets
+ set i [[lindex $widgets(listboxes) 0] curselection]
+ if {[llength $i] > 0} {
+ foreach lb $widgets(listboxes) {
+ $lb delete [lindex $i 0]
+ }
+ }
+ $widgets(bb) itemconfigure 1 -state disabled
+}
+
+proc Apol_Open_Policy_Dialog::importList {} {
+ variable vars
+ variable dialog
+ variable widgets
+ set f [tk_getOpenFile -initialdir [file dirname $vars(primary_file)] \
+ -parent $dialog -title "Import Policy List"]
+ if {$f == {}} {
+ return
+ }
+ if {[catch {new_apol_policy_path_t $f} ppath]} {
+ tk_messageBox -icon error -type ok -title "Import Policy List" \
+ -message "Error importing policy list $f: $ppath"
+ return
+ }
+ foreach lb $widgets(listboxes) {
+ $lb delete 0 end
+ }
+ foreach {path_type primary modules} [policy_path_to_list $ppath] {break}
+ set vars(path_type) $path_type
+ if {[set vars(primary_file) $primary] != {}} {
+ $dialog itemconfigure 0 -state normal
+ }
+ set vars(last_module) $f
+ foreach m $modules {
+ addModule $m
+ }
+ _validateEntryKey $vars(primary_file)
+ $ppath -acquire
+ $ppath -delete
+}
+
+proc Apol_Open_Policy_Dialog::exportList {} {
+ variable vars
+ variable dialog
+ set f [tk_getSaveFile -parent $dialog -title "Export Policy List"]
+ if {$f == {}} {
+ return
+ }
+ set ppath [list_to_policy_path $vars(path_type) $vars(primary_file) $vars(mod_paths)]
+ if {[catch {$ppath to_file $f} err]} {
+ tk_messageBox -icon error -type ok -title "Export Policy List" \
+ -message "Error exporting policy list $f: $err"
+ }
+}
+
+proc Apol_Open_Policy_Dialog::multiscroll {args} {
+ variable widgets
+ foreach lb $widgets(listboxes) {
+ eval $lb $args
+ }
+}
+
+proc Apol_Open_Policy_Dialog::multiselect {lb} {
+ variable widgets
+ set sellist [$lb curselection]
+ set enable_remove 0
+ foreach lb $widgets(listboxes) {
+ $lb selection clear 0 end
+ foreach item $sellist {
+ $lb selection set $item
+ set enable_remove 1
+ }
+ }
+ if {$enable_remove} {
+ $widgets(bb) itemconfigure 1 -state normal
+ }
+}
+
+proc Apol_Open_Policy_Dialog::multiyview {args} {
+ variable widgets
+ eval $widgets(scrollbar) set $args
+ multiscroll yview moveto [lindex $args 0]
+}
+
+
+# Generate a policy path and try to open the given policy. Upon
+# success end the dialog and return that path. Otherwise do not close
+# the dialog.
+proc Apol_Open_Policy_Dialog::tryOpenPolicy {} {
+ variable dialog
+ variable vars
+ .open_policy_dialog.bbox.b0 configure -state disabled
+ if {[string trim $vars(primary_file)] != {}} {
+ set ppath [list_to_policy_path $vars(path_type) $vars(primary_file) $vars(mod_paths)]
+ if {[ApolTop::openPolicyPath $ppath] == 0} {
+ $dialog enddialog {}
+ }
+ }
+ .open_policy_dialog.bbox.b0 configure -state normal
+}
+
+# Retrieve information about a policy module file, either source or
+# binary, from disk. This will be a 3-ple of module name, version and type.
+# The policy module will be closed afterwards.
+proc Apol_Open_Policy_Dialog::getModuleInfo {f} {
+ set mod [new_qpol_module_t $f]
+ set retval [list [$mod get_name] [$mod get_version] [$mod get_type]]
+ $mod -acquire
+ $mod -delete
+ return $retval
+}
diff --git a/apol/perm_maps/apol_perm_mapping_ver12 b/apol/perm_maps/apol_perm_mapping_ver12
new file mode 100644
index 0000000..7e3df06
--- /dev/null
+++ b/apol/perm_maps/apol_perm_mapping_ver12
@@ -0,0 +1,575 @@
+# This is a permission map file for use in policy analysis. This
+# file maps object permissions (read, getattr, setattr, ..., etc.)
+# for an object class, to exactly one of the following: read, write,
+# both, or none. This file may be edited as long as the specific
+# syntax rules are obeyed.
+#
+# For each object class, there is a set of object permissions that are
+# individually mapped to read, write, both, or none. If a new object
+# class is added, make sure that the current number of object classes
+# is increased.
+#
+# The syntax for an object class definition is:
+# class <class_name> <num_permissions>
+#
+# This is followed by each permission and its individual mapping to one
+# of the following:
+#
+# r = Read
+# w = Write
+# n = None
+# b = Both
+#
+# Additionally, you can choose to follow the mapping with an optional
+# permission weight value from 1 (less importance) to 10 (higher importance).
+# 10 is the default weight value if one is not provided.
+#
+# Look to the examples below for further clarification.
+#
+# Number of object classes.
+29
+
+
+class blk_file 17
+ getattr r 7
+ relabelto w 10
+ unlink w 1
+ ioctl n 1
+ execute r 0
+ append w 1
+ read r 10
+ setattr w 7
+ swapon b 0
+ write w 10
+ lock n 1
+ create w 1
+ rename w 5
+ mounton b 1
+ quotaon b 1
+ relabelfrom r 10
+ link w 1
+
+
+class file 19
+ setattr w 7
+ swapon b 0
+ write w 10
+ lock n 1
+ create w 1
+ rename w 5
+ mounton b 1
+ quotaon b 1
+ relabelfrom r 10
+ link w 1
+ entrypoint r 0
+ getattr r 7
+ relabelto w 10
+ unlink w 1
+ execute_no_trans r 0
+ ioctl n 1
+ execute r 0
+ append w 1
+ read r 10
+
+
+class udp_socket 22
+ listen r 1
+ setattr w 7
+ shutdown w 1
+ relabelto w 10
+ recv_msg r 10
+ accept r 1
+ name_bind n 1
+ append w 1
+ relabelfrom r 10
+ create w 1
+ read r 10
+ sendto w 10
+ connect w 1
+ recvfrom r 10
+ send_msg w 10
+ bind w 1
+ lock n 1
+ ioctl n 1
+ getattr r 7
+ write w 10
+ setopt w 1
+ getopt r 1
+
+
+class socket 22
+ append w 1
+ relabelfrom r 10
+ create w 1
+ read r 10
+ sendto w 10
+ connect w 1
+ recvfrom r 10
+ send_msg w 10
+ bind w 1
+ lock n 1
+ ioctl n 1
+ getattr r 7
+ write w 10
+ setopt w 1
+ getopt r 1
+ listen r 0
+ setattr w 7
+ shutdown w 1
+ relabelto w 10
+ recv_msg r 10
+ accept r 1
+ name_bind n 1
+
+
+class fifo_file 17
+ relabelto w 10
+ getattr r 7
+ lock n 1
+ execute r 0
+ unlink w 1
+ ioctl n 1
+ setattr w 7
+ append w 1
+ write w 10
+ swapon b 0
+ create w 1
+ link w 1
+ rename w 5
+ relabelfrom r 10
+ mounton b 1
+ quotaon b 1
+ read r 10
+
+
+class chr_file 17
+ append w 1
+ swapon b 0
+ mounton b 1
+ quotaon b 1
+ create w 1
+ rename w 5
+ ioctl n 1
+ getattr r 7
+ link w 1
+ write w 10
+ execute r 0
+ relabelto w 10
+ setattr w 7
+ relabelfrom r 10
+ read r 10
+ unlink w 1
+ lock n 1
+
+
+class netlink_socket 22
+ listen r 1
+ accept r 1
+ read r 10
+ setattr w 7
+ append w 1
+ bind w 1
+ lock n 1
+ shutdown w 1
+ recv_msg r 10
+ create w 1
+ sendto w 10
+ relabelto w 10
+ ioctl n 1
+ name_bind n 1
+ connect w 1
+ write w 10
+ recvfrom r 10
+ send_msg w 10
+ relabelfrom r 10
+ setopt w 1
+ getattr r 7
+ getopt r 1
+
+
+class unix_dgram_socket 22
+ connect w 1
+ getopt r 1
+ listen r 1
+ relabelto w 10
+ name_bind n 1
+ accept r 1
+ shutdown w 1
+ getattr r 7
+ recv_msg r 10
+ append w 1
+ read r 10
+ create w 1
+ sendto w 10
+ ioctl n 1
+ setattr w 7
+ bind w 1
+ lock n 1
+ recvfrom r 10
+ send_msg w 10
+ write w 10
+ relabelfrom r 10
+ setopt w 1
+
+
+class node 7
+ rawip_recv r 10
+ rawip_send w 10
+ tcp_recv r 10
+ tcp_send w 10
+ enforce_dest n 1
+ udp_recv r 10
+ udp_send w 10
+
+
+class netif 6
+ rawip_recv r 10
+ rawip_send w 10
+ tcp_recv r 10
+ tcp_send w 10
+ udp_recv r 10
+ udp_send w 10
+
+
+class unix_stream_socket 25
+ relabelto w 10
+ append w 1
+ name_bind n 1
+ setattr w 7
+ connectto w 1
+ newconn w 1
+ recvfrom r 10
+ create w 1
+ sendto w 10
+ send_msg w 10
+ read r 10
+ bind w 1
+ lock n 1
+ connect w 1
+ setopt w 1
+ acceptfrom r 1
+ getopt r 1
+ ioctl n 1
+ getattr r 7
+ shutdown w 1
+ recv_msg r 10
+ listen r 1
+ accept r 1
+ relabelfrom r 10
+ write w 10
+
+
+class tcp_socket 25
+ connectto w 1
+ newconn w 1
+ recvfrom r 10
+ create w 1
+ sendto w 10
+ send_msg w 10
+ read r 10
+ bind w 1
+ lock n 1
+ connect w 1
+ setopt w 1
+ acceptfrom r 1
+ getopt r 1
+ ioctl n 1
+ getattr r 7
+ shutdown w 1
+ recv_msg r 10
+ listen r 1
+ accept r 1
+ relabelfrom r 10
+ write w 10
+ relabelto w 10
+ append w 1
+ name_bind n 1
+ setattr w 7
+
+
+class dir 22
+ mounton b 1
+ search r 1
+ link w 1
+ quotaon b 1
+ append w 1
+ swapon b 0
+ rmdir b 1
+ create w 1
+ ioctl n 1
+ getattr r 7
+ remove_name w 1
+ rename w 5
+ read r 10
+ write w 10
+ relabelfrom r 10
+ execute r 0
+ relabelto w 10
+ lock n 1
+ setattr w 7
+ reparent w 1
+ add_name w 5
+ unlink w 1
+
+
+class shm 10
+ destroy w 1
+ write w 10
+ read r 10
+ getattr r 1
+ unix_write w 3
+ unix_read r 3
+ lock w 1
+ associate n 0
+ setattr w 1
+ create w 1
+
+
+class security 9
+ change_sid n 1
+ transition_sid n 1
+ sid_to_context n 1
+ member_sid n 1
+ get_user_sids n 1
+ compute_av n 1
+ load_policy n 1
+ get_sids n 1
+ context_to_sid n 1
+
+
+class packet_socket 22
+ setattr w 7
+ read r 10
+ relabelto w 10
+ shutdown w 1
+ name_bind n 1
+ recv_msg r 10
+ setopt w 1
+ bind w 1
+ lock n 1
+ ioctl n 1
+ getopt r 1
+ connect w 1
+ relabelfrom r 10
+ listen r 1
+ write w 10
+ accept r 1
+ append w 1
+ recvfrom r 10
+ send_msg w 10
+ getattr r 7
+ create w 1
+ sendto w 10
+
+
+class msgq 10
+ enqueue w 1
+ create w 1
+ destroy w 1
+ write w 10
+ read r 10
+ getattr r 1
+ unix_write w 3
+ unix_read r 3
+ associate n 0
+ setattr w 1
+
+
+class key_socket 22
+ connect w 1
+ setopt w 1
+ relabelto w 10
+ read r 10
+ name_bind n 1
+ getopt r 1
+ getattr r 7
+ recvfrom r 10
+ send_msg w 10
+ bind w 1
+ listen r 1
+ lock n 1
+ accept r 1
+ append w 1
+ setattr w 7
+ ioctl n 1
+ create w 1
+ sendto w 10
+ relabelfrom r 10
+ write w 10
+ shutdown w 1
+ recv_msg r 10
+
+
+class capability 29
+ net_bind_service n 1
+ sys_module n 0
+ sys_admin n 3
+ fowner n 1
+ net_raw n 1
+ setuid n 1
+ sys_chroot n 1
+ lease n 1
+ net_admin n 1
+ ipc_owner n 1
+ fsetid n 1
+ sys_resource n 1
+ sys_rawio n 1
+ sys_ptrace n 1
+ sys_nice n 1
+ setpcap n 3
+ kill n 1
+ sys_pacct n 1
+ sys_boot n 1
+ dac_override n 1
+ setgid n 3
+ net_broadcast n 1
+ chown n 3
+ sys_tty_config n 1
+ linux_immutable n 1
+ sys_time n 1
+ ipc_lock n 1
+ mknod n 1
+ dac_read_search n 1
+
+
+class fd 1
+ use b 1
+
+
+class rawip_socket 22
+ lock n 1
+ write w 10
+ getattr r 1
+ recvfrom r 10
+ send_msg w 10
+ setopt w 1
+ setattr w 1
+ getopt r 1
+ relabelto w 10
+ listen r 1
+ name_bind n 1
+ accept r 1
+ append w 1
+ shutdown w 1
+ recv_msg r 10
+ relabelfrom r 10
+ read r 10
+ ioctl n 1
+ connect w 1
+ create w 1
+ sendto w 10
+ bind w 1
+
+
+class ipc 9
+ write w 10
+ destroy w 1
+ unix_write w 3
+ getattr r 1
+ create w 1
+ read r 10
+ setattr w 1
+ unix_read r 3
+ associate n 1
+
+
+class lnk_file 17
+ relabelfrom r 10
+ append w 1
+ ioctl n 1
+ swapon b 0
+ create w 1
+ read r 10
+ write w 10
+ rename w 1
+ mounton b 1
+ quotaon b 1
+ lock n 1
+ relabelto w 10
+ getattr r 7
+ unlink w 1
+ execute r 0
+ link w 1
+ setattr w 7
+
+
+class system 8
+ ipc_info n 1
+ syslog_mod n 1
+ syslog_read n 1
+ syslog_console n 1
+ nfsd_control n 1
+ avc_toggle n 1
+ bdflush n 1
+ ichsid n 1
+
+
+class sem 9
+ unix_read r 3
+ associate n 1
+ create w 1
+ destroy w 1
+ getattr r 1
+ read r 10
+ setattr w 1
+ write w 10
+ unix_write w 3
+
+
+class filesystem 10
+ remount w 1
+ relabelfrom r 10
+ getattr r 1
+ relabelto w 10
+ mount w 1
+ transition w 1
+ quotaget r 1
+ quotamod w 1
+ unmount w 1
+ associate n 1
+
+
+class sock_file 17
+ setattr w 7
+ rename w 1
+ ioctl n 1
+ link w 1
+ write w 10
+ mounton b 1
+ relabelto w 10
+ quotaon b 1
+ read r 10
+ unlink w 1
+ append w 1
+ lock n 1
+ getattr r 7
+ swapon b 0
+ relabelfrom r 10
+ execute r 0
+ create w 1
+
+
+class process 16
+ getsched r 1
+ signull n 1
+ sigstop w 1
+ share b 1
+ getpgid r 1
+ signal w 5
+ setcap w 1
+ sigchld w 1
+ getcap r 3
+ getsession r 1
+ setsched w 1
+ fork n 1
+ ptrace b 10
+ sigkill w 1
+ setpgid w 5
+ transition w 1
+
+
+class msg 2
+ receive r 10
+ send w 10
+
+
diff --git a/apol/perm_maps/apol_perm_mapping_ver15 b/apol/perm_maps/apol_perm_mapping_ver15
new file mode 100644
index 0000000..689e91f
--- /dev/null
+++ b/apol/perm_maps/apol_perm_mapping_ver15
@@ -0,0 +1,580 @@
+# This is a permission map file for use in policy analysis. This
+# file maps object permissions (read, getattr, setattr, ..., etc.)
+# for an object class, to exactly one of the following: read, write,
+# both, or none. This file may be edited as long as the specific
+# syntax rules are obeyed.
+#
+# For each object class, there is a set of object permissions that are
+# individually mapped to read, write, both, or none. If a new object
+# class is added, make sure that the current number of object classes
+# is increased.
+#
+# The syntax for an object class definition is:
+# class <class_name> <num_permissions>
+#
+# This is followed by each permission and its individual mapping to one
+# of the following:
+#
+# r = Read
+# w = Write
+# n = None
+# b = Both
+#
+# Additionally, you can choose to follow the mapping with an optional
+# permission weight value from 1 (less importance) to 10 (higher importance).
+# 10 is the default weight value if one is not provided.
+#
+# Look to the examples below for further clarification.
+#
+# Number of object classes.
+30
+
+
+class blk_file 17
+ getattr r 7
+ relabelto w 10
+ unlink w 1
+ ioctl n 1
+ execute r 1
+ append w 1
+ read r 10
+ setattr w 7
+ swapon b 1
+ write w 10
+ lock n 1
+ create w 1
+ rename w 5
+ mounton b 1
+ quotaon b 1
+ relabelfrom r 10
+ link w 1
+
+
+class file 19
+ setattr w 7
+ swapon b 1
+ write w 10
+ lock n 1
+ create w 1
+ rename w 5
+ mounton b 1
+ quotaon b 1
+ relabelfrom r 10
+ link w 1
+ entrypoint r 1
+ getattr r 7
+ relabelto w 10
+ unlink w 1
+ execute_no_trans r 1
+ ioctl n 1
+ execute r 1
+ append w 1
+ read r 10
+
+
+class udp_socket 22
+ listen r 1
+ setattr w 7
+ shutdown w 1
+ relabelto w 10
+ recv_msg r 10
+ accept r 1
+ name_bind n 1
+ append w 1
+ relabelfrom r 10
+ create w 1
+ read r 10
+ sendto w 10
+ connect w 1
+ recvfrom r 10
+ send_msg w 10
+ bind w 1
+ lock n 1
+ ioctl n 1
+ getattr r 7
+ write w 10
+ setopt w 1
+ getopt r 1
+
+
+class socket 22
+ append w 1
+ relabelfrom r 10
+ create w 1
+ read r 10
+ sendto w 10
+ connect w 1
+ recvfrom r 10
+ send_msg w 10
+ bind w 1
+ lock n 1
+ ioctl n 1
+ getattr r 7
+ write w 10
+ setopt w 1
+ getopt r 1
+ listen r 1
+ setattr w 7
+ shutdown w 1
+ relabelto w 10
+ recv_msg r 10
+ accept r 1
+ name_bind n 1
+
+
+class passwd 3
+ passwd n 1
+ chfn w 5
+ chsh w 5
+
+
+class fifo_file 17
+ relabelto w 10
+ getattr r 7
+ lock n 1
+ execute r 1
+ unlink w 1
+ ioctl n 1
+ setattr w 7
+ append w 1
+ write w 10
+ swapon b 1
+ create w 1
+ link w 1
+ rename w 5
+ relabelfrom r 10
+ mounton b 1
+ quotaon b 1
+ read r 10
+
+
+class chr_file 17
+ append w 1
+ swapon b 1
+ mounton b 1
+ quotaon b 1
+ create w 1
+ rename w 5
+ ioctl n 1
+ getattr r 7
+ link w 1
+ write w 10
+ execute r 1
+ relabelto w 10
+ setattr w 7
+ relabelfrom r 10
+ read r 10
+ unlink w 1
+ lock n 1
+
+
+class netlink_socket 22
+ listen r 1
+ accept r 1
+ read r 10
+ setattr w 7
+ append w 1
+ bind w 1
+ lock n 1
+ shutdown w 1
+ recv_msg r 10
+ create w 1
+ sendto w 10
+ relabelto w 10
+ ioctl n 1
+ name_bind n 1
+ connect w 1
+ write w 10
+ recvfrom r 10
+ send_msg w 10
+ relabelfrom r 10
+ setopt w 1
+ getattr r 7
+ getopt r 1
+
+
+class unix_dgram_socket 22
+ connect w 1
+ getopt r 1
+ listen r 1
+ relabelto w 10
+ name_bind n 1
+ accept r 1
+ shutdown w 1
+ getattr r 7
+ recv_msg r 10
+ append w 1
+ read r 10
+ create w 1
+ sendto w 10
+ ioctl n 1
+ setattr w 7
+ bind w 1
+ lock n 1
+ recvfrom r 10
+ send_msg w 10
+ write w 10
+ relabelfrom r 10
+ setopt w 1
+
+
+class node 7
+ rawip_recv r 10
+ rawip_send w 10
+ tcp_recv r 10
+ tcp_send w 10
+ enforce_dest n 1
+ udp_recv r 10
+ udp_send w 10
+
+
+class netif 6
+ rawip_recv r 10
+ rawip_send w 10
+ tcp_recv r 10
+ tcp_send w 10
+ udp_recv r 10
+ udp_send w 10
+
+
+class unix_stream_socket 25
+ relabelto w 10
+ append w 1
+ name_bind n 1
+ setattr w 7
+ connectto w 1
+ newconn w 1
+ recvfrom r 10
+ create w 1
+ sendto w 10
+ send_msg w 10
+ read r 10
+ bind w 1
+ lock n 1
+ connect w 1
+ setopt w 1
+ acceptfrom r 1
+ getopt r 1
+ ioctl n 1
+ getattr r 7
+ shutdown w 1
+ recv_msg r 10
+ listen r 1
+ accept r 1
+ relabelfrom r 10
+ write w 10
+
+
+class tcp_socket 25
+ connectto w 1
+ newconn w 1
+ recvfrom r 10
+ create w 1
+ sendto w 10
+ send_msg w 10
+ read r 10
+ bind w 1
+ lock n 1
+ connect w 1
+ setopt w 1
+ acceptfrom r 1
+ getopt r 1
+ ioctl n 1
+ getattr r 7
+ shutdown w 1
+ recv_msg r 10
+ listen r 1
+ accept r 1
+ relabelfrom r 10
+ write w 10
+ relabelto w 10
+ append w 1
+ name_bind n 1
+ setattr w 7
+
+
+class dir 22
+ mounton b 1
+ search r 1
+ link w 1
+ quotaon b 1
+ append w 1
+ swapon b 1
+ rmdir b 1
+ create w 1
+ ioctl n 1
+ getattr r 7
+ remove_name w 1
+ rename w 5
+ read r 10
+ write w 10
+ relabelfrom r 10
+ execute r 1
+ relabelto w 10
+ lock n 1
+ setattr w 7
+ reparent w 1
+ add_name w 5
+ unlink w 1
+
+
+class shm 10
+ destroy w 1
+ write w 10
+ read r 10
+ getattr r 1
+ unix_write w 3
+ unix_read r 3
+ lock w 1
+ associate n 1
+ setattr w 1
+ create w 1
+
+
+class security 8
+ compute_user n 1
+ compute_relabel n 1
+ compute_create n 1
+ compute_av n 1
+ compute_member n 1
+ setenforce n 1
+ check_context n 1
+ load_policy n 1
+
+
+class packet_socket 22
+ setattr w 7
+ read r 10
+ relabelto w 10
+ shutdown w 1
+ name_bind n 1
+ recv_msg r 10
+ setopt w 1
+ bind w 1
+ lock n 1
+ ioctl n 1
+ getopt r 1
+ connect w 1
+ relabelfrom r 10
+ listen r 1
+ write w 10
+ accept r 1
+ append w 1
+ recvfrom r 10
+ send_msg w 10
+ getattr r 7
+ create w 1
+ sendto w 10
+
+
+class msgq 10
+ enqueue w 1
+ create w 1
+ destroy w 1
+ write w 10
+ read r 10
+ getattr r 1
+ unix_write w 3
+ unix_read r 3
+ associate n 1
+ setattr w 1
+
+
+class key_socket 22
+ connect w 1
+ setopt w 1
+ relabelto w 10
+ read r 10
+ name_bind n 1
+ getopt r 1
+ getattr r 7
+ recvfrom r 10
+ send_msg w 10
+ bind w 1
+ listen r 1
+ lock n 1
+ accept r 1
+ append w 1
+ setattr w 7
+ ioctl n 1
+ create w 1
+ sendto w 10
+ relabelfrom r 10
+ write w 10
+ shutdown w 1
+ recv_msg r 10
+
+
+class capability 29
+ net_bind_service n 1
+ sys_module n 1
+ sys_admin n 3
+ fowner n 1
+ net_raw n 1
+ setuid n 1
+ sys_chroot n 1
+ lease n 1
+ net_admin n 1
+ ipc_owner n 1
+ fsetid n 1
+ sys_resource n 1
+ sys_rawio n 1
+ sys_ptrace n 1
+ sys_nice n 1
+ setpcap n 3
+ kill n 1
+ sys_pacct n 1
+ sys_boot n 1
+ dac_override n 1
+ setgid n 3
+ net_broadcast n 1
+ chown n 3
+ sys_tty_config n 1
+ linux_immutable n 1
+ sys_time n 1
+ ipc_lock n 1
+ mknod n 1
+ dac_read_search n 1
+
+
+class fd 1
+ use b 1
+
+
+class rawip_socket 22
+ lock n 1
+ write w 10
+ getattr r 1
+ recvfrom r 10
+ send_msg w 10
+ setopt w 1
+ setattr w 1
+ getopt r 1
+ relabelto w 10
+ listen r 1
+ name_bind n 1
+ accept r 1
+ append w 1
+ shutdown w 1
+ recv_msg r 10
+ relabelfrom r 10
+ read r 10
+ ioctl n 1
+ connect w 1
+ create w 1
+ sendto w 10
+ bind w 1
+
+
+class ipc 9
+ write w 10
+ destroy w 1
+ unix_write w 3
+ getattr r 1
+ create w 1
+ read r 10
+ setattr w 1
+ unix_read r 3
+ associate n 1
+
+
+class lnk_file 17
+ relabelfrom r 10
+ append w 1
+ ioctl n 1
+ swapon b 1
+ create w 1
+ read r 10
+ write w 10
+ rename w 1
+ mounton b 1
+ quotaon b 1
+ lock n 1
+ relabelto w 10
+ getattr r 7
+ unlink w 1
+ execute r 1
+ link w 1
+ setattr w 7
+
+
+class system 4
+ ipc_info n 1
+ syslog_mod n 1
+ syslog_read n 1
+ syslog_console n 1
+
+
+class sem 9
+ unix_read r 3
+ associate n 1
+ create w 1
+ destroy w 1
+ getattr r 1
+ read r 10
+ setattr w 1
+ write w 10
+ unix_write w 3
+
+
+class filesystem 10
+ remount w 1
+ relabelfrom r 10
+ getattr r 1
+ relabelto w 10
+ mount w 1
+ transition w 1
+ quotaget r 1
+ quotamod w 1
+ unmount w 1
+ associate n 1
+
+
+class sock_file 17
+ setattr w 7
+ rename w 1
+ ioctl n 1
+ link w 1
+ write w 10
+ mounton b 1
+ relabelto w 10
+ quotaon b 1
+ read r 10
+ unlink w 1
+ append w 1
+ lock n 1
+ getattr r 7
+ swapon b 1
+ relabelfrom r 10
+ execute r 1
+ create w 1
+
+
+class process 20
+ noatsecure n 1
+ getsched r 1
+ signull n 1
+ sigstop w 1
+ getattr r 1
+ share b 1
+ getpgid r 1
+ signal w 5
+ setcap w 1
+ sigchld w 1
+ setexec w 1
+ getcap r 3
+ getsession r 1
+ setsched w 1
+ fork n 1
+ ptrace b 10
+ sigkill w 1
+ setpgid w 5
+ transition w 1
+ setfscreate w 1
+
+
+class msg 2
+ receive r 10
+ send w 10
+
+
diff --git a/apol/perm_maps/apol_perm_mapping_ver16 b/apol/perm_maps/apol_perm_mapping_ver16
new file mode 100644
index 0000000..a62fb77
--- /dev/null
+++ b/apol/perm_maps/apol_perm_mapping_ver16
@@ -0,0 +1,560 @@
+# This is a permission map file for use in policy analysis. This
+# file maps object permissions (read, getattr, setattr, ..., etc.)
+# for an object class, to exactly one of the following: read, write,
+# both, or none. This file may be edited as long as the specific
+# syntax rules are obeyed.
+#
+# For each object class, there is a set of object permissions that are
+# individually mapped to read, write, both, or none. If a new object
+# class is added, make sure that the current number of object classes
+# is increased.
+#
+# The syntax for an object class definition is:
+# class <class_name> <num_permissions>
+#
+# This is followed by each permission and its individual mapping to one
+# of the following:
+#
+# r = Read
+# w = Write
+# n = None
+# b = Both
+#
+# Additionally, you can choose to follow the mapping with an optional
+# permission weight value from 1 (less importance) to 10 (higher importance).
+# 10 is the default weight value if one is not provided.
+#
+# Look to the examples below for further clarification.
+#
+# Number of object classes.
+30
+
+class security 9
+ compute_av n 1
+ compute_create n 1
+ compute_member n 1
+ check_context n 1
+ load_policy n 1
+ compute_relabel n 1
+ compute_user n 1
+ setenforce n 1
+ setbool n 1
+
+class process 23
+ fork n 1
+ transition w 1
+ sigchld w 1
+ sigkill w 1
+ sigstop w 1
+ signull n 1
+ signal w 5
+ ptrace b 10
+ getsched r 1
+ setsched w 1
+ getsession r 1
+ getpgid r 1
+ setpgid w 5
+ getcap r 3
+ setcap w 1
+ share b 1
+ getattr r 1
+ setexec w 1
+ setfscreate w 1
+ noatsecure n 1
+ siginh n 1
+ setrlimit n 1
+ rlimitinh n 1
+
+
+class system 4
+ ipc_info n 1
+ syslog_read n 1
+ syslog_mod n 1
+ syslog_console n 1
+
+class capability 29
+ net_bind_service n 1
+ sys_module n 1
+ sys_admin n 3
+ fowner n 1
+ net_raw n 1
+ setuid n 1
+ sys_chroot n 1
+ lease n 1
+ net_admin n 1
+ ipc_owner n 1
+ fsetid n 1
+ sys_resource n 1
+ sys_rawio n 1
+ sys_ptrace n 1
+ sys_nice n 1
+ setpcap n 3
+ kill n 1
+ sys_pacct n 1
+ sys_boot n 1
+ dac_override n 1
+ setgid n 3
+ net_broadcast n 1
+ chown n 3
+ sys_tty_config n 1
+ linux_immutable n 1
+ sys_time n 1
+ ipc_lock n 1
+ mknod n 1
+ dac_read_search n 1
+
+class filesystem 10
+ remount w 1
+ relabelfrom r 10
+ getattr r 1
+ relabelto w 10
+ mount w 1
+ transition w 1
+ quotaget r 1
+ quotamod w 1
+ unmount w 1
+ associate n 1
+
+class file 19
+ setattr w 7
+ swapon b 1
+ write w 10
+ lock n 1
+ create w 1
+ rename w 5
+ mounton b 1
+ quotaon b 1
+ relabelfrom r 10
+ link w 1
+ entrypoint r 1
+ getattr r 7
+ relabelto w 10
+ unlink w 1
+ execute_no_trans r 1
+ ioctl n 1
+ execute r 1
+ append w 1
+ read r 10
+
+class dir 22
+ mounton b 1
+ search r 1
+ link w 1
+ quotaon b 1
+ append w 1
+ swapon b 1
+ rmdir b 1
+ create w 1
+ ioctl n 1
+ getattr r 7
+ remove_name w 1
+ rename w 5
+ read r 10
+ write w 10
+ relabelfrom r 10
+ execute r 1
+ relabelto w 10
+ lock n 1
+ setattr w 7
+ reparent w 1
+ add_name w 5
+ unlink w 1
+
+class fd 1
+ use b 1
+
+class lnk_file 17
+ relabelfrom r 10
+ append w 1
+ ioctl n 1
+ swapon b 1
+ create w 1
+ read r 10
+ write w 10
+ rename w 1
+ mounton b 1
+ quotaon b 1
+ lock n 1
+ relabelto w 10
+ getattr r 7
+ unlink w 1
+ execute r 1
+ link w 1
+ setattr w 7
+
+class chr_file 17
+ append w 1
+ swapon b 1
+ mounton b 1
+ quotaon b 1
+ create w 1
+ rename w 5
+ ioctl n 1
+ getattr r 7
+ link w 1
+ write w 10
+ execute r 1
+ relabelto w 10
+ setattr w 7
+ relabelfrom r 10
+ read r 10
+ unlink w 1
+ lock n 1
+
+class blk_file 17
+ getattr r 7
+ relabelto w 10
+ unlink w 1
+ ioctl n 1
+ execute r 1
+ append w 1
+ read r 10
+ setattr w 7
+ swapon b 1
+ write w 10
+ lock n 1
+ create w 1
+ rename w 5
+ mounton b 1
+ quotaon b 1
+ relabelfrom r 10
+ link w 1
+
+class sock_file 17
+ setattr w 7
+ rename w 1
+ ioctl n 1
+ link w 1
+ write w 10
+ mounton b 1
+ relabelto w 10
+ quotaon b 1
+ read r 10
+ unlink w 1
+ append w 1
+ lock n 1
+ getattr r 7
+ swapon b 1
+ relabelfrom r 10
+ execute r 1
+ create w 1
+
+class fifo_file 17
+ relabelto w 10
+ getattr r 7
+ lock n 1
+ execute r 1
+ unlink w 1
+ ioctl n 1
+ setattr w 7
+ append w 1
+ write w 10
+ swapon b 1
+ create w 1
+ link w 1
+ rename w 5
+ relabelfrom r 10
+ mounton b 1
+ quotaon b 1
+ read r 10
+
+class socket 22
+ append w 1
+ relabelfrom r 10
+ create w 1
+ read r 10
+ sendto w 10
+ connect w 1
+ recvfrom r 10
+ send_msg w 10
+ bind w 1
+ lock n 1
+ ioctl n 1
+ getattr r 7
+ write w 10
+ setopt w 1
+ getopt r 1
+ listen r 1
+ setattr w 7
+ shutdown w 1
+ relabelto w 10
+ recv_msg r 10
+ accept r 1
+ name_bind n 1
+
+class tcp_socket 26
+ connectto w 1
+ newconn w 1
+ acceptfrom r 1
+ node_bind n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+
+class udp_socket 23
+ node_bind n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+
+class rawip_socket 23
+ node_bind n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 1
+ setattr w 1
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+
+class node 7
+ rawip_recv r 10
+ rawip_send w 10
+ tcp_recv r 10
+ tcp_send w 10
+ enforce_dest n 1
+ udp_recv r 10
+ udp_send w 10
+
+class netif 6
+ rawip_recv r 10
+ rawip_send w 10
+ tcp_recv r 10
+ tcp_send w 10
+ udp_recv r 10
+ udp_send w 10
+
+class netlink_socket 22
+ listen r 1
+ accept r 1
+ read r 10
+ setattr w 7
+ append w 1
+ bind w 1
+ lock n 1
+ shutdown w 1
+ recv_msg r 10
+ create w 1
+ sendto w 10
+ relabelto w 10
+ ioctl n 1
+ name_bind n 1
+ connect w 1
+ write w 10
+ recvfrom r 10
+ send_msg w 10
+ relabelfrom r 10
+ setopt w 1
+ getattr r 7
+ getopt r 1
+
+class packet_socket 22
+ setattr w 7
+ read r 10
+ relabelto w 10
+ shutdown w 1
+ name_bind n 1
+ recv_msg r 10
+ setopt w 1
+ bind w 1
+ lock n 1
+ ioctl n 1
+ getopt r 1
+ connect w 1
+ relabelfrom r 10
+ listen r 1
+ write w 10
+ accept r 1
+ append w 1
+ recvfrom r 10
+ send_msg w 10
+ getattr r 7
+ create w 1
+ sendto w 10
+
+class key_socket 22
+ connect w 1
+ setopt w 1
+ relabelto w 10
+ read r 10
+ name_bind n 1
+ getopt r 1
+ getattr r 7
+ recvfrom r 10
+ send_msg w 10
+ bind w 1
+ listen r 1
+ lock n 1
+ accept r 1
+ append w 1
+ setattr w 7
+ ioctl n 1
+ create w 1
+ sendto w 10
+ relabelfrom r 10
+ write w 10
+ shutdown w 1
+ recv_msg r 10
+
+class unix_stream_socket 25
+ relabelto w 10
+ append w 1
+ name_bind n 1
+ setattr w 7
+ connectto w 1
+ newconn w 1
+ recvfrom r 10
+ create w 1
+ sendto w 10
+ send_msg w 10
+ read r 10
+ bind w 1
+ lock n 1
+ connect w 1
+ setopt w 1
+ acceptfrom r 1
+ getopt r 1
+ ioctl n 1
+ getattr r 7
+ shutdown w 1
+ recv_msg r 10
+ listen r 1
+ accept r 1
+ relabelfrom r 10
+ write w 10
+
+class unix_dgram_socket 22
+ connect w 1
+ getopt r 1
+ listen r 1
+ relabelto w 10
+ name_bind n 1
+ accept r 1
+ shutdown w 1
+ getattr r 7
+ recv_msg r 10
+ append w 1
+ read r 10
+ create w 1
+ sendto w 10
+ ioctl n 1
+ setattr w 7
+ bind w 1
+ lock n 1
+ recvfrom r 10
+ send_msg w 10
+ write w 10
+ relabelfrom r 10
+ setopt w 1
+
+class sem 9
+ unix_read r 3
+ associate n 1
+ create w 1
+ destroy w 1
+ getattr r 1
+ read r 10
+ setattr w 1
+ write w 10
+ unix_write w 3
+
+class msg 2
+ receive r 10
+ send w 10
+
+class msgq 10
+ enqueue w 1
+ create w 1
+ destroy w 1
+ write w 10
+ read r 10
+ getattr r 1
+ unix_write w 3
+ unix_read r 3
+ associate n 1
+ setattr w 1
+
+class shm 10
+ destroy w 1
+ write w 10
+ read r 10
+ getattr r 1
+ unix_write w 3
+ unix_read r 3
+ lock w 1
+ associate n 1
+ setattr w 1
+ create w 1
+
+class ipc 9
+ write w 10
+ destroy w 1
+ unix_write w 3
+ getattr r 1
+ create w 1
+ read r 10
+ setattr w 1
+ unix_read r 3
+ associate n 1
+
+class passwd 4
+ passwd w 1
+ chfn w 5
+ chsh w 5
+ rootok n 1
diff --git a/apol/perm_maps/apol_perm_mapping_ver17 b/apol/perm_maps/apol_perm_mapping_ver17
new file mode 100644
index 0000000..648b538
--- /dev/null
+++ b/apol/perm_maps/apol_perm_mapping_ver17
@@ -0,0 +1,561 @@
+# This is a permission map file for use in policy analysis. This
+# file maps object permissions (read, getattr, setattr, ..., etc.)
+# for an object class, to exactly one of the following: read, write,
+# both, or none. This file may be edited as long as the specific
+# syntax rules are obeyed.
+#
+# For each object class, there is a set of object permissions that are
+# individually mapped to read, write, both, or none. If a new object
+# class is added, make sure that the current number of object classes
+# is increased.
+#
+# The syntax for an object class definition is:
+# class <class_name> <num_permissions>
+#
+# This is followed by each permission and its individual mapping to one
+# of the following:
+#
+# r = Read
+# w = Write
+# n = None
+# b = Both
+#
+# Additionally, you can choose to follow the mapping with an optional
+# permission weight value from 1 (less importance) to 10 (higher importance).
+# 10 is the default weight value if one is not provided.
+#
+# Look to the examples below for further clarification.
+#
+# Number of object classes.
+41
+
+class security 9
+ compute_av n 1
+ compute_create n 1
+ compute_member n 1
+ check_context n 1
+ load_policy n 1
+ compute_relabel n 1
+ compute_user n 1
+ setenforce n 1
+ setbool n 1
+
+class process 23
+ fork n 1
+ transition w 1
+ sigchld w 1
+ sigkill w 1
+ sigstop w 1
+ signull n 1
+ signal w 5
+ ptrace b 10
+ getsched r 1
+ setsched w 1
+ getsession r 1
+ getpgid r 1
+ setpgid w 5
+ getcap r 3
+ setcap w 1
+ share b 1
+ getattr r 1
+ setexec w 1
+ setfscreate w 1
+ noatsecure n 1
+ siginh n 1
+ setrlimit n 1
+ rlimitinh n 1
+
+
+class system 4
+ ipc_info n 1
+ syslog_read n 1
+ syslog_mod n 1
+ syslog_console n 1
+
+class capability 29
+ net_bind_service n 1
+ sys_module n 1
+ sys_admin n 3
+ fowner n 1
+ net_raw n 1
+ setuid n 1
+ sys_chroot n 1
+ lease n 1
+ net_admin n 1
+ ipc_owner n 1
+ fsetid n 1
+ sys_resource n 1
+ sys_rawio n 1
+ sys_ptrace n 1
+ sys_nice n 1
+ setpcap n 3
+ kill n 1
+ sys_pacct n 1
+ sys_boot n 1
+ dac_override n 1
+ setgid n 3
+ net_broadcast n 1
+ chown n 3
+ sys_tty_config n 1
+ linux_immutable n 1
+ sys_time n 1
+ ipc_lock n 1
+ mknod n 1
+ dac_read_search n 1
+
+class filesystem 10
+ remount w 1
+ relabelfrom r 10
+ getattr r 1
+ relabelto w 10
+ mount w 1
+ transition w 1
+ quotaget r 1
+ quotamod w 1
+ unmount w 1
+ associate n 1
+
+class file 19
+ setattr w 7
+ swapon b 1
+ write w 10
+ lock n 1
+ create w 1
+ rename w 5
+ mounton b 1
+ quotaon b 1
+ relabelfrom r 10
+ link w 1
+ entrypoint r 1
+ getattr r 7
+ relabelto w 10
+ unlink w 1
+ execute_no_trans r 1
+ ioctl n 1
+ execute r 1
+ append w 1
+ read r 10
+
+class dir 22
+ mounton b 1
+ search r 1
+ link w 1
+ quotaon b 1
+ append w 1
+ swapon b 1
+ rmdir b 1
+ create w 1
+ ioctl n 1
+ getattr r 7
+ remove_name w 1
+ rename w 5
+ read r 10
+ write w 10
+ relabelfrom r 10
+ execute r 1
+ relabelto w 10
+ lock n 1
+ setattr w 7
+ reparent w 1
+ add_name w 5
+ unlink w 1
+
+class fd 1
+ use b 1
+
+class lnk_file 17
+ relabelfrom r 10
+ append w 1
+ ioctl n 1
+ swapon b 1
+ create w 1
+ read r 10
+ write w 10
+ rename w 1
+ mounton b 1
+ quotaon b 1
+ lock n 1
+ relabelto w 10
+ getattr r 7
+ unlink w 1
+ execute r 1
+ link w 1
+ setattr w 7
+
+class chr_file 17
+ append w 1
+ swapon b 1
+ mounton b 1
+ quotaon b 1
+ create w 1
+ rename w 5
+ ioctl n 1
+ getattr r 7
+ link w 1
+ write w 10
+ execute r 1
+ relabelto w 10
+ setattr w 7
+ relabelfrom r 10
+ read r 10
+ unlink w 1
+ lock n 1
+
+class blk_file 17
+ getattr r 7
+ relabelto w 10
+ unlink w 1
+ ioctl n 1
+ execute r 1
+ append w 1
+ read r 10
+ setattr w 7
+ swapon b 1
+ write w 10
+ lock n 1
+ create w 1
+ rename w 5
+ mounton b 1
+ quotaon b 1
+ relabelfrom r 10
+ link w 1
+
+class sock_file 17
+ setattr w 7
+ rename w 1
+ ioctl n 1
+ link w 1
+ write w 10
+ mounton b 1
+ relabelto w 10
+ quotaon b 1
+ read r 10
+ unlink w 1
+ append w 1
+ lock n 1
+ getattr r 7
+ swapon b 1
+ relabelfrom r 10
+ execute r 1
+ create w 1
+
+class fifo_file 17
+ relabelto w 10
+ getattr r 7
+ lock n 1
+ execute r 1
+ unlink w 1
+ ioctl n 1
+ setattr w 7
+ append w 1
+ write w 10
+ swapon b 1
+ create w 1
+ link w 1
+ rename w 5
+ relabelfrom r 10
+ mounton b 1
+ quotaon b 1
+ read r 10
+
+class socket 22
+ append w 1
+ relabelfrom r 10
+ create w 1
+ read r 10
+ sendto w 10
+ connect w 1
+ recvfrom r 10
+ send_msg w 10
+ bind w 1
+ lock n 1
+ ioctl n 1
+ getattr r 7
+ write w 10
+ setopt w 1
+ getopt r 1
+ listen r 1
+ setattr w 7
+ shutdown w 1
+ relabelto w 10
+ recv_msg r 10
+ accept r 1
+ name_bind n 1
+
+class tcp_socket 26
+ connectto w 1
+ newconn w 1
+ acceptfrom r 1
+ node_bind n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+
+class udp_socket 23
+ node_bind n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+
+class rawip_socket 23
+ node_bind n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 1
+ setattr w 1
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+
+class node 7
+ rawip_recv r 10
+ rawip_send w 10
+ tcp_recv r 10
+ tcp_send w 10
+ enforce_dest n 1
+ udp_recv r 10
+ udp_send w 10
+
+class netif 6
+ rawip_recv r 10
+ rawip_send w 10
+ tcp_recv r 10
+ tcp_send w 10
+ udp_recv r 10
+ udp_send w 10
+
+class netlink_socket 22
+ listen r 1
+ accept r 1
+ read r 10
+ setattr w 7
+ append w 1
+ bind w 1
+ lock n 1
+ shutdown w 1
+ recv_msg r 10
+ create w 1
+ sendto w 10
+ relabelto w 10
+ ioctl n 1
+ name_bind n 1
+ connect w 1
+ write w 10
+ recvfrom r 10
+ send_msg w 10
+ relabelfrom r 10
+ setopt w 1
+ getattr r 7
+ getopt r 1
+
+class packet_socket 22
+ setattr w 7
+ read r 10
+ relabelto w 10
+ shutdown w 1
+ name_bind n 1
+ recv_msg r 10
+ setopt w 1
+ bind w 1
+ lock n 1
+ ioctl n 1
+ getopt r 1
+ connect w 1
+ relabelfrom r 10
+ listen r 1
+ write w 10
+ accept r 1
+ append w 1
+ recvfrom r 10
+ send_msg w 10
+ getattr r 7
+ create w 1
+ sendto w 10
+
+class key_socket 22
+ connect w 1
+ setopt w 1
+ relabelto w 10
+ read r 10
+ name_bind n 1
+ getopt r 1
+ getattr r 7
+ recvfrom r 10
+ send_msg w 10
+ bind w 1
+ listen r 1
+ lock n 1
+ accept r 1
+ append w 1
+ setattr w 7
+ ioctl n 1
+ create w 1
+ sendto w 10
+ relabelfrom r 10
+ write w 10
+ shutdown w 1
+ recv_msg r 10
+
+class unix_stream_socket 25
+ relabelto w 10
+ append w 1
+ name_bind n 1
+ setattr w 7
+ connectto w 1
+ newconn w 1
+ recvfrom r 10
+ create w 1
+ sendto w 10
+ send_msg w 10
+ read r 10
+ bind w 1
+ lock n 1
+ connect w 1
+ setopt w 1
+ acceptfrom r 1
+ getopt r 1
+ ioctl n 1
+ getattr r 7
+ shutdown w 1
+ recv_msg r 10
+ listen r 1
+ accept r 1
+ relabelfrom r 10
+ write w 10
+
+class unix_dgram_socket 22
+ connect w 1
+ getopt r 1
+ listen r 1
+ relabelto w 10
+ name_bind n 1
+ accept r 1
+ shutdown w 1
+ getattr r 7
+ recv_msg r 10
+ append w 1
+ read r 10
+ create w 1
+ sendto w 10
+ ioctl n 1
+ setattr w 7
+ bind w 1
+ lock n 1
+ recvfrom r 10
+ send_msg w 10
+ write w 10
+ relabelfrom r 10
+ setopt w 1
+
+class sem 9
+ unix_read r 3
+ associate n 1
+ create w 1
+ destroy w 1
+ getattr r 1
+ read r 10
+ setattr w 1
+ write w 10
+ unix_write w 3
+
+class msg 2
+ receive r 10
+ send w 10
+
+class msgq 10
+ enqueue w 1
+ create w 1
+ destroy w 1
+ write w 10
+ read r 10
+ getattr r 1
+ unix_write w 3
+ unix_read r 3
+ associate n 1
+ setattr w 1
+
+class shm 10
+ destroy w 1
+ write w 10
+ read r 10
+ getattr r 1
+ unix_write w 3
+ unix_read r 3
+ lock w 1
+ associate n 1
+ setattr w 1
+ create w 1
+
+class ipc 9
+ write w 10
+ destroy w 1
+ unix_write w 3
+ getattr r 1
+ create w 1
+ read r 10
+ setattr w 1
+ unix_read r 3
+ associate n 1
+
+class passwd 4
+ passwd w 1
+ chfn w 5
+ chsh w 5
+ rootok n 1
+
diff --git a/apol/perm_maps/apol_perm_mapping_ver18 b/apol/perm_maps/apol_perm_mapping_ver18
new file mode 100644
index 0000000..b2f4403
--- /dev/null
+++ b/apol/perm_maps/apol_perm_mapping_ver18
@@ -0,0 +1,922 @@
+# This is a permission map file for use in policy analysis. This
+# file maps object permissions (read, getattr, setattr, ..., etc.)
+# for an object class, to exactly one of the following: read, write,
+# both, or none. This file may be edited as long as the specific
+# syntax rules are obeyed.
+#
+# For each object class, there is a set of object permissions that are
+# individually mapped to read, write, both, or none. If a new object
+# class is added, make sure that the current number of object classes
+# is increased.
+#
+# The syntax for an object class definition is:
+# class <class_name> <num_permissions>
+#
+# This is followed by each permission and its individual mapping to one
+# of the following:
+#
+# r = Read
+# w = Write
+# n = None
+# b = Both
+#
+# Additionally, you can choose to follow the mapping with an optional
+# permission weight value from 1 (less importance) to 10 (higher importance).
+# 10 is the default weight value if one is not provided.
+#
+# Look to the examples below for further clarification.
+#
+# Number of object classes.
+54
+
+class security 10
+ compute_av n 1
+ compute_create n 1
+ compute_member n 1
+ check_context n 1
+ load_policy n 1
+ compute_relabel n 1
+ compute_user n 1
+ setenforce n 1
+ setbool n 1
+ setsecparam n 1
+
+class process 26
+ fork n 1
+ transition w 5
+ sigchld w 1
+ sigkill w 1
+ sigstop w 1
+ signull n 1
+ signal w 5
+ ptrace b 10
+ getsched r 1
+ setsched w 1
+ getsession r 1
+ getpgid r 1
+ setpgid w 5
+ getcap r 3
+ setcap w 1
+ share b 1
+ getattr r 1
+ setexec w 1
+ setfscreate w 1
+ noatsecure n 1
+ siginh n 1
+ setrlimit n 1
+ rlimitinh n 1
+ dyntransition w 10
+ setcurrent w 1
+ execmem n 1
+
+class system 4
+ ipc_info n 1
+ syslog_read n 1
+ syslog_mod n 1
+ syslog_console n 1
+
+class capability 31
+ chown n 3
+ dac_override n 1
+ dac_read_search n 1
+ fowner n 1
+ fsetid n 1
+ kill n 1
+ setgid n 3
+ setuid n 1
+ setpcap n 3
+ linux_immutable n 1
+ net_bind_service n 1
+ net_broadcast n 1
+ net_admin n 1
+ net_raw n 1
+ ipc_lock n 1
+ ipc_owner n 1
+ sys_module n 1
+ sys_rawio n 1
+ sys_chroot n 1
+ sys_ptrace n 1
+ sys_pacct n 1
+ sys_admin n 3
+ sys_boot n 1
+ sys_nice n 1
+ sys_resource n 1
+ sys_time n 1
+ sys_tty_config n 1
+ mknod n 1
+ lease n 1
+ audit_write n 3
+ audit_control n 1
+
+class filesystem 10
+ mount w 1
+ remount w 1
+ unmount w 1
+ getattr r 1
+ relabelfrom r 10
+ relabelto w 10
+ transition w 1
+ associate n 1
+ quotamod w 1
+ quotaget r 1
+
+class file 20
+ execute_no_trans r 1
+ entrypoint r 1
+ execmod n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class dir 22
+ add_name w 5
+ remove_name w 1
+ reparent w 1
+ search r 1
+ rmdir b 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class fd 1
+ use b 1
+
+class lnk_file 17
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 1
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class chr_file 20
+ execute_no_trans r 1
+ entrypoint r 1
+ execmod n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class blk_file 17
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class sock_file 17
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 1
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class fifo_file 17
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class tcp_socket 26
+ connectto w 1
+ newconn w 1
+ acceptfrom r 1
+ node_bind n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class udp_socket 23
+ node_bind n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class rawip_socket 23
+ node_bind n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 1
+ setattr w 1
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class node 7
+ tcp_recv r 10
+ tcp_send w 10
+ udp_recv r 10
+ udp_send w 10
+ rawip_recv r 10
+ rawip_send w 10
+ enforce_dest n 1
+
+class netif 6
+ tcp_recv r 10
+ tcp_send w 10
+ udp_recv r 10
+ udp_send w 10
+ rawip_recv r 10
+ rawip_send w 10
+
+class netlink_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class packet_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class key_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class unix_stream_socket 25
+ connectto w 1
+ newconn w 1
+ acceptfrom r 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class unix_dgram_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class sem 9
+ create w 1
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ write w 10
+ associate n 1
+ unix_read r 3
+ unix_write w 3
+
+class msg 2
+ send w 10
+ receive r 10
+
+class msgq 10
+ enqueue w 1
+ create w 1
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ write w 10
+ associate n 1
+ unix_read r 3
+ unix_write w 3
+
+class shm 10
+ lock w 1
+ create w 1
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ write w 10
+ associate n 1
+ unix_read r 3
+ unix_write w 3
+
+class ipc 9
+ create w 1
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ write w 10
+ associate n 1
+ unix_read r 3
+ unix_write w 3
+
+class passwd 5
+ passwd w 1
+ chfn w 5
+ chsh w 5
+ rootok n 1
+ crontab w 5
+
+class drawable 5
+ create w 1
+ destroy w 1
+ draw w 10
+ copy r 10
+ getattr r 7
+
+class window 26
+ addchild w 1
+ create w 1
+ destroy w 1
+ map w 1
+ unmap w 1
+ chstack w 10
+ chproplist w 7
+ chprop w 10
+ listprop r 5
+ getattr r 5
+ setattr w 5
+ setfocus w 1
+ move w 10
+ chselection w 10
+ chparent w 5
+ ctrllife w 5
+ enumerate w 1
+ transparent w 1
+ mousemotion w 10
+ clientcomevent w 5
+ inputevent w 5
+ drawevent w 5
+ windowchangeevent w 5
+windowchangerequest w 5
+ serverchangeevent w 5
+ extensionevent w 5
+
+class gc 4
+ create w 1
+ free w 1
+ getattr r 5
+ setattr w 5
+
+class font 4
+ load r 1
+ free w 1
+ getattr r 5
+ use r 1
+
+class colormap 9
+ create w 1
+ free w 1
+ install w 10
+ uninstall w 1
+ list r 5
+ read r 10
+ store w 10
+ getattr r 5
+ setattr w 5
+
+class property 4
+ create w 1
+ free w 1
+ read r 10
+ write w 10
+
+class cursor 5
+ create w 1
+ createglyph w 10
+ free w 1
+ assign w 10
+ setattr w 5
+
+class xclient 1
+ kill w 1
+
+class xinput 11
+ lookup r 10
+ getattr r 5
+ setattr w 5
+ setfocus w 10
+ warppointer w 10
+ activegrab w 1
+ passivegrab w 1
+ ungrab w 1
+ bell w 3
+ mousemotion w 10
+ relabelinput b 3
+
+class xserver 8
+ screensaver w 10
+ gethostlist r 7
+ sethostlist w 7
+ getfontpath r 7
+ setfontpath w 7
+ getattr r 7
+ grab w 10
+ ungrab w 1
+
+class xextension 2
+ query r 10
+ use b 1
+
+class pax 6
+ pageexec n 1
+ emutramp n 1
+ mprotect n 1
+ randmmap n 1
+ randexec n 1
+ segmexec n 1
+
+class netlink_route_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_firewall_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_tcpdiag_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_nflog_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_xfrm_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_selinux_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_audit_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_ip6fw_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_dnrt_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class dbus 2
+ acquire_svc b 1
+ send_msg w 10
+
+class nscd 8
+ getpwd r 7
+ getgrp r 7
+ gethost r 7
+ getstat r 7
+ admin w 5
+ shmempwd r 7
+ shmemgrp r 7
+ shmemhost r 7
+
+class association 2
+ sendto w 10
+ recvfrom r 10
diff --git a/apol/perm_maps/apol_perm_mapping_ver19 b/apol/perm_maps/apol_perm_mapping_ver19
new file mode 100644
index 0000000..77e9a28
--- /dev/null
+++ b/apol/perm_maps/apol_perm_mapping_ver19
@@ -0,0 +1,952 @@
+# This is a permission map file for use in policy analysis. This
+# file maps object permissions (read, getattr, setattr, ..., etc.)
+# for an object class, to exactly one of the following: read, write,
+# both, or none. This file may be edited as long as the specific
+# syntax rules are obeyed.
+#
+# For each object class, there is a set of object permissions that are
+# individually mapped to read, write, both, or none. If a new object
+# class is added, make sure that the current number of object classes
+# is increased.
+#
+# The syntax for an object class definition is:
+# class <class_name> <num_permissions>
+#
+# This is followed by each permission and its individual mapping to one
+# of the following:
+#
+# r = Read
+# w = Write
+# n = None
+# b = Both
+#
+# Additionally, you can choose to follow the mapping with an optional
+# permission weight value from 1 (less importance) to 10 (higher importance).
+# 10 is the default weight value if one is not provided.
+#
+# Look to the examples below for further clarification.
+#
+# Number of object classes.
+55
+
+class security 11
+ compute_av n 1
+ compute_create n 1
+ compute_member n 1
+ check_context n 1
+ load_policy n 1
+ compute_relabel n 1
+ compute_user n 1
+ setenforce n 1
+ setbool n 1
+ setsecparam n 1
+ setcheckreqprot n 1
+
+class process 28
+ fork n 1
+ transition w 5
+ sigchld w 1
+ sigkill w 1
+ sigstop w 1
+ signull n 1
+ signal w 5
+ ptrace b 10
+ getsched r 1
+ setsched w 1
+ getsession r 1
+ getpgid r 1
+ setpgid w 5
+ getcap r 3
+ setcap w 1
+ share b 1
+ getattr r 1
+ setexec w 1
+ setfscreate w 1
+ noatsecure n 1
+ siginh n 1
+ setrlimit n 1
+ rlimitinh n 1
+ dyntransition w 10
+ setcurrent w 1
+ execmem n 1
+ execstack n 1
+ execheap n 1
+
+class system 4
+ ipc_info n 1
+ syslog_read n 1
+ syslog_mod n 1
+ syslog_console n 1
+
+class capability 31
+ chown n 3
+ dac_override n 1
+ dac_read_search n 1
+ fowner n 1
+ fsetid n 1
+ kill n 1
+ setgid n 3
+ setuid n 1
+ setpcap n 3
+ linux_immutable n 1
+ net_bind_service n 1
+ net_broadcast n 1
+ net_admin n 1
+ net_raw n 1
+ ipc_lock n 1
+ ipc_owner n 1
+ sys_module n 1
+ sys_rawio n 1
+ sys_chroot n 1
+ sys_ptrace n 1
+ sys_pacct n 1
+ sys_admin n 3
+ sys_boot n 1
+ sys_nice n 1
+ sys_resource n 1
+ sys_time n 1
+ sys_tty_config n 1
+ mknod n 1
+ lease n 1
+ audit_write n 3
+ audit_control n 1
+
+class filesystem 10
+ mount w 1
+ remount w 1
+ unmount w 1
+ getattr r 1
+ relabelfrom r 10
+ relabelto w 10
+ transition w 1
+ associate n 1
+ quotamod w 1
+ quotaget r 1
+
+class file 20
+ execute_no_trans r 1
+ entrypoint r 1
+ execmod n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class dir 22
+ add_name w 5
+ remove_name w 1
+ reparent w 1
+ search r 1
+ rmdir b 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class fd 1
+ use b 1
+
+class lnk_file 17
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 1
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class chr_file 20
+ execute_no_trans r 1
+ entrypoint r 1
+ execmod n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class blk_file 17
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class sock_file 17
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 1
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class fifo_file 17
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class tcp_socket 27
+ connectto w 1
+ newconn w 1
+ acceptfrom r 1
+ node_bind n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+ name_connect w 1
+
+class udp_socket 23
+ node_bind n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class rawip_socket 23
+ node_bind n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 1
+ setattr w 1
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class node 7
+ tcp_recv r 10
+ tcp_send w 10
+ udp_recv r 10
+ udp_send w 10
+ rawip_recv r 10
+ rawip_send w 10
+ enforce_dest n 1
+
+class netif 6
+ tcp_recv r 10
+ tcp_send w 10
+ udp_recv r 10
+ udp_send w 10
+ rawip_recv r 10
+ rawip_send w 10
+
+class netlink_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class packet_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class key_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class unix_stream_socket 25
+ connectto w 1
+ newconn w 1
+ acceptfrom r 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class unix_dgram_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class sem 9
+ create w 1
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ write w 10
+ associate n 1
+ unix_read r 3
+ unix_write w 3
+
+class msg 2
+ send w 10
+ receive r 10
+
+class msgq 10
+ enqueue w 1
+ create w 1
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ write w 10
+ associate n 1
+ unix_read r 3
+ unix_write w 3
+
+class shm 10
+ lock w 1
+ create w 1
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ write w 10
+ associate n 1
+ unix_read r 3
+ unix_write w 3
+
+class ipc 9
+ create w 1
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ write w 10
+ associate n 1
+ unix_read r 3
+ unix_write w 3
+
+class passwd 5
+ passwd w 1
+ chfn w 5
+ chsh w 5
+ rootok n 1
+ crontab w 5
+
+class drawable 5
+ create w 1
+ destroy w 1
+ draw w 10
+ copy r 10
+ getattr r 7
+
+class window 26
+ addchild w 1
+ create w 1
+ destroy w 1
+ map w 1
+ unmap w 1
+ chstack w 10
+ chproplist w 7
+ chprop w 10
+ listprop r 5
+ getattr r 5
+ setattr w 5
+ setfocus w 1
+ move w 10
+ chselection w 10
+ chparent w 5
+ ctrllife w 5
+ enumerate w 1
+ transparent w 1
+ mousemotion w 10
+ clientcomevent w 5
+ inputevent w 5
+ drawevent w 5
+ windowchangeevent w 5
+windowchangerequest w 5
+ serverchangeevent w 5
+ extensionevent w 5
+
+class gc 4
+ create w 1
+ free w 1
+ getattr r 5
+ setattr w 5
+
+class font 4
+ load r 1
+ free w 1
+ getattr r 5
+ use r 1
+
+class colormap 9
+ create w 1
+ free w 1
+ install w 10
+ uninstall w 1
+ list r 5
+ read r 10
+ store w 10
+ getattr r 5
+ setattr w 5
+
+class property 4
+ create w 1
+ free w 1
+ read r 10
+ write w 10
+
+class cursor 5
+ create w 1
+ createglyph w 10
+ free w 1
+ assign w 10
+ setattr w 5
+
+class xclient 1
+ kill w 1
+
+class xinput 11
+ lookup r 10
+ getattr r 5
+ setattr w 5
+ setfocus w 10
+ warppointer w 10
+ activegrab w 1
+ passivegrab w 1
+ ungrab w 1
+ bell w 3
+ mousemotion w 10
+ relabelinput b 3
+
+class xserver 8
+ screensaver w 10
+ gethostlist r 7
+ sethostlist w 7
+ getfontpath r 7
+ setfontpath w 7
+ getattr r 7
+ grab w 10
+ ungrab w 1
+
+class xextension 2
+ query r 10
+ use b 1
+
+class pax 6
+ pageexec n 1
+ emutramp n 1
+ mprotect n 1
+ randmmap n 1
+ randexec n 1
+ segmexec n 1
+
+class netlink_route_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_firewall_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_tcpdiag_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_nflog_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_xfrm_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_selinux_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_audit_socket 26
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+ nlmsg_relay w 10
+ nlmsg_readpriv r 10
+
+class netlink_ip6fw_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_dnrt_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_kobject_uevent_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class dbus 2
+ acquire_svc b 1
+ send_msg w 10
+
+class nscd 8
+ getpwd r 7
+ getgrp r 7
+ gethost r 7
+ getstat r 7
+ admin w 5
+ shmempwd r 7
+ shmemgrp r 7
+ shmemhost r 7
+
+class association 2
+ sendto w 10
+ recvfrom r 10
diff --git a/apol/perm_maps/apol_perm_mapping_ver20 b/apol/perm_maps/apol_perm_mapping_ver20
new file mode 100644
index 0000000..a7123ad
--- /dev/null
+++ b/apol/perm_maps/apol_perm_mapping_ver20
@@ -0,0 +1,993 @@
+# This is a permission map file for use in policy analysis. This
+# file maps object permissions (read, getattr, setattr, ..., etc.)
+# for an object class, to exactly one of the following: read, write,
+# both, or none. This file may be edited as long as the specific
+# syntax rules are obeyed.
+#
+# For each object class, there is a set of object permissions that are
+# individually mapped to read, write, both, or none. If a new object
+# class is added, make sure that the current number of object classes
+# is increased.
+#
+# The syntax for an object class definition is:
+# class <class_name> <num_permissions>
+#
+# This is followed by each permission and its individual mapping to one
+# of the following:
+#
+# r = Read
+# w = Write
+# n = None
+# b = Both
+#
+# Additionally, you can choose to follow the mapping with an optional
+# permission weight value from 1 (less importance) to 10 (higher importance).
+# 10 is the default weight value if one is not provided.
+#
+# Look to the examples below for further clarification.
+#
+# Number of object classes.
+58
+
+class security 11
+ compute_av n 1
+ compute_create n 1
+ compute_member n 1
+ check_context n 1
+ load_policy n 1
+ compute_relabel n 1
+ compute_user n 1
+ setenforce n 1
+ setbool n 1
+ setsecparam n 1
+ setcheckreqprot n 1
+
+class process 29
+ fork n 1
+ transition w 5
+ sigchld w 1
+ sigkill w 1
+ sigstop w 1
+ signull n 1
+ signal w 5
+ ptrace b 10
+ getsched r 1
+ setsched w 1
+ getsession r 1
+ getpgid r 1
+ setpgid w 5
+ getcap r 3
+ setcap w 1
+ share b 1
+ getattr r 1
+ setexec w 1
+ setfscreate w 1
+ noatsecure n 1
+ siginh n 1
+ setrlimit n 1
+ rlimitinh n 1
+ dyntransition w 10
+ setcurrent w 1
+ execmem n 1
+ execstack n 1
+ execheap n 1
+ setkeycreate w 1
+
+class system 4
+ ipc_info n 1
+ syslog_read n 1
+ syslog_mod n 1
+ syslog_console n 1
+
+class capability 31
+ chown n 3
+ dac_override n 1
+ dac_read_search n 1
+ fowner n 1
+ fsetid n 1
+ kill n 1
+ setgid n 3
+ setuid n 1
+ setpcap n 3
+ linux_immutable n 1
+ net_bind_service n 1
+ net_broadcast n 1
+ net_admin n 1
+ net_raw n 1
+ ipc_lock n 1
+ ipc_owner n 1
+ sys_module n 1
+ sys_rawio n 1
+ sys_chroot n 1
+ sys_ptrace n 1
+ sys_pacct n 1
+ sys_admin n 3
+ sys_boot n 1
+ sys_nice n 1
+ sys_resource n 1
+ sys_time n 1
+ sys_tty_config n 1
+ mknod n 1
+ lease n 1
+ audit_write n 3
+ audit_control n 1
+
+class filesystem 10
+ mount w 1
+ remount w 1
+ unmount w 1
+ getattr r 1
+ relabelfrom r 10
+ relabelto w 10
+ transition w 1
+ associate n 1
+ quotamod w 1
+ quotaget r 1
+
+class file 20
+ execute_no_trans r 1
+ entrypoint r 1
+ execmod n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class dir 22
+ add_name w 5
+ remove_name w 1
+ reparent w 1
+ search r 1
+ rmdir b 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class fd 1
+ use b 1
+
+class lnk_file 17
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 1
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class chr_file 20
+ execute_no_trans r 1
+ entrypoint r 1
+ execmod n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class blk_file 17
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class sock_file 17
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 1
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class fifo_file 17
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class tcp_socket 27
+ connectto w 1
+ newconn w 1
+ acceptfrom r 1
+ node_bind n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+ name_connect w 1
+
+class udp_socket 23
+ node_bind n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class rawip_socket 23
+ node_bind n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 1
+ setattr w 1
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class node 7
+ tcp_recv r 10
+ tcp_send w 10
+ udp_recv r 10
+ udp_send w 10
+ rawip_recv r 10
+ rawip_send w 10
+ enforce_dest n 1
+
+class netif 6
+ tcp_recv r 10
+ tcp_send w 10
+ udp_recv r 10
+ udp_send w 10
+ rawip_recv r 10
+ rawip_send w 10
+
+class netlink_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class packet_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class key_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class unix_stream_socket 25
+ connectto w 1
+ newconn w 1
+ acceptfrom r 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class unix_dgram_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class sem 9
+ create w 1
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ write w 10
+ associate n 1
+ unix_read r 3
+ unix_write w 3
+
+class msg 2
+ send w 10
+ receive r 10
+
+class msgq 10
+ enqueue w 1
+ create w 1
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ write w 10
+ associate n 1
+ unix_read r 3
+ unix_write w 3
+
+class shm 10
+ lock w 1
+ create w 1
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ write w 10
+ associate n 1
+ unix_read r 3
+ unix_write w 3
+
+class ipc 9
+ create w 1
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ write w 10
+ associate n 1
+ unix_read r 3
+ unix_write w 3
+
+class passwd 5
+ passwd w 1
+ chfn w 5
+ chsh w 5
+ rootok n 1
+ crontab w 5
+
+class drawable 5
+ create w 1
+ destroy w 1
+ draw w 10
+ copy r 10
+ getattr r 7
+
+class window 26
+ addchild w 1
+ create w 1
+ destroy w 1
+ map w 1
+ unmap w 1
+ chstack w 10
+ chproplist w 7
+ chprop w 10
+ listprop r 5
+ getattr r 5
+ setattr w 5
+ setfocus w 1
+ move w 10
+ chselection w 10
+ chparent w 5
+ ctrllife w 5
+ enumerate w 1
+ transparent w 1
+ mousemotion w 10
+ clientcomevent w 5
+ inputevent w 5
+ drawevent w 5
+ windowchangeevent w 5
+windowchangerequest w 5
+ serverchangeevent w 5
+ extensionevent w 5
+
+class gc 4
+ create w 1
+ free w 1
+ getattr r 5
+ setattr w 5
+
+class font 4
+ load r 1
+ free w 1
+ getattr r 5
+ use r 1
+
+class colormap 9
+ create w 1
+ free w 1
+ install w 10
+ uninstall w 1
+ list r 5
+ read r 10
+ store w 10
+ getattr r 5
+ setattr w 5
+
+class property 4
+ create w 1
+ free w 1
+ read r 10
+ write w 10
+
+class cursor 5
+ create w 1
+ createglyph w 10
+ free w 1
+ assign w 10
+ setattr w 5
+
+class xclient 1
+ kill w 1
+
+class xinput 11
+ lookup r 10
+ getattr r 5
+ setattr w 5
+ setfocus w 10
+ warppointer w 10
+ activegrab w 1
+ passivegrab w 1
+ ungrab w 1
+ bell w 3
+ mousemotion w 10
+ relabelinput b 3
+
+class xserver 8
+ screensaver w 10
+ gethostlist r 7
+ sethostlist w 7
+ getfontpath r 7
+ setfontpath w 7
+ getattr r 7
+ grab w 10
+ ungrab w 1
+
+class xextension 2
+ query r 10
+ use b 1
+
+class pax 6
+ pageexec n 1
+ emutramp n 1
+ mprotect n 1
+ randmmap n 1
+ randexec n 1
+ segmexec n 1
+
+class netlink_route_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_firewall_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_tcpdiag_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_nflog_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_xfrm_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_selinux_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_audit_socket 26
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+ nlmsg_relay w 10
+ nlmsg_readpriv r 10
+
+class netlink_ip6fw_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_dnrt_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_kobject_uevent_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class dbus 2
+ acquire_svc b 1
+ send_msg w 10
+
+class nscd 8
+ getpwd r 7
+ getgrp r 7
+ gethost r 7
+ getstat r 7
+ admin w 5
+ shmempwd r 7
+ shmemgrp r 7
+ shmemhost r 7
+
+class association 4
+ sendto w 10
+ recvfrom r 10
+ setcontext w 3
+ polmatch r 1
+
+class appletalk_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 1
+ setattr w 1
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class key 7
+ view r 7
+ read r 10
+ write w 10
+ search r 5
+ link w 7
+ setattr w 7
+ create w 10
+
+class packet 3
+ send w 10
+ recv r 10
+ relabelto w 3
diff --git a/apol/perm_maps/apol_perm_mapping_ver21 b/apol/perm_maps/apol_perm_mapping_ver21
new file mode 100644
index 0000000..e5b115f
--- /dev/null
+++ b/apol/perm_maps/apol_perm_mapping_ver21
@@ -0,0 +1,998 @@
+# This is a permission map file for use in policy analysis. This
+# file maps object permissions (read, getattr, setattr, ..., etc.)
+# for an object class, to exactly one of the following: read, write,
+# both, or none. This file may be edited as long as the specific
+# syntax rules are obeyed.
+#
+# For each object class, there is a set of object permissions that are
+# individually mapped to read, write, both, or none. If a new object
+# class is added, make sure that the current number of object classes
+# is increased.
+#
+# The syntax for an object class definition is:
+# class <class_name> <num_permissions>
+#
+# This is followed by each permission and its individual mapping to one
+# of the following:
+#
+# r = Read
+# w = Write
+# n = None
+# b = Both
+#
+# Additionally, you can choose to follow the mapping with an optional
+# permission weight value from 1 (less importance) to 10 (higher importance).
+# 10 is the default weight value if one is not provided.
+#
+# Look to the examples below for further clarification.
+#
+# Number of object classes.
+59
+
+class security 11
+ compute_av n 1
+ compute_create n 1
+ compute_member n 1
+ check_context n 1
+ load_policy n 1
+ compute_relabel n 1
+ compute_user n 1
+ setenforce n 1
+ setbool n 1
+ setsecparam n 1
+ setcheckreqprot n 1
+
+class process 30
+ fork n 1
+ transition w 5
+ sigchld w 1
+ sigkill w 1
+ sigstop w 1
+ signull n 1
+ signal w 5
+ ptrace b 10
+ getsched r 1
+ setsched w 1
+ getsession r 1
+ getpgid r 1
+ setpgid w 5
+ getcap r 3
+ setcap w 1
+ share b 1
+ getattr r 1
+ setexec w 1
+ setfscreate w 1
+ noatsecure n 1
+ siginh n 1
+ setrlimit n 1
+ rlimitinh n 1
+ dyntransition w 10
+ setcurrent w 1
+ execmem n 1
+ execstack n 1
+ execheap n 1
+ setkeycreate w 1
+ setsockcreate w 1
+
+class system 4
+ ipc_info n 1
+ syslog_read n 1
+ syslog_mod n 1
+ syslog_console n 1
+
+class capability 31
+ chown n 3
+ dac_override n 1
+ dac_read_search n 1
+ fowner n 1
+ fsetid n 1
+ kill n 1
+ setgid n 3
+ setuid n 1
+ setpcap n 3
+ linux_immutable n 1
+ net_bind_service n 1
+ net_broadcast n 1
+ net_admin n 1
+ net_raw n 1
+ ipc_lock n 1
+ ipc_owner n 1
+ sys_module n 1
+ sys_rawio n 1
+ sys_chroot n 1
+ sys_ptrace n 1
+ sys_pacct n 1
+ sys_admin n 3
+ sys_boot n 1
+ sys_nice n 1
+ sys_resource n 1
+ sys_time n 1
+ sys_tty_config n 1
+ mknod n 1
+ lease n 1
+ audit_write n 3
+ audit_control n 1
+
+class filesystem 10
+ mount w 1
+ remount w 1
+ unmount w 1
+ getattr r 1
+ relabelfrom r 10
+ relabelto w 10
+ transition w 1
+ associate n 1
+ quotamod w 1
+ quotaget r 1
+
+class file 20
+ execute_no_trans r 1
+ entrypoint r 1
+ execmod n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class dir 22
+ add_name w 5
+ remove_name w 1
+ reparent w 1
+ search r 1
+ rmdir b 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class fd 1
+ use b 1
+
+class lnk_file 17
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 1
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class chr_file 20
+ execute_no_trans r 1
+ entrypoint r 1
+ execmod n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class blk_file 17
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class sock_file 17
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 1
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class fifo_file 17
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class tcp_socket 27
+ connectto w 1
+ newconn w 1
+ acceptfrom r 1
+ node_bind n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+ name_connect w 1
+
+class udp_socket 23
+ node_bind n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class rawip_socket 23
+ node_bind n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 1
+ setattr w 1
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class node 7
+ tcp_recv r 10
+ tcp_send w 10
+ udp_recv r 10
+ udp_send w 10
+ rawip_recv r 10
+ rawip_send w 10
+ enforce_dest n 1
+
+class netif 6
+ tcp_recv r 10
+ tcp_send w 10
+ udp_recv r 10
+ udp_send w 10
+ rawip_recv r 10
+ rawip_send w 10
+
+class netlink_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class packet_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class key_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class unix_stream_socket 25
+ connectto w 1
+ newconn w 1
+ acceptfrom r 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class unix_dgram_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class sem 9
+ create w 1
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ write w 10
+ associate n 1
+ unix_read r 3
+ unix_write w 3
+
+class msg 2
+ send w 10
+ receive r 10
+
+class msgq 10
+ enqueue w 1
+ create w 1
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ write w 10
+ associate n 1
+ unix_read r 3
+ unix_write w 3
+
+class shm 10
+ lock w 1
+ create w 1
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ write w 10
+ associate n 1
+ unix_read r 3
+ unix_write w 3
+
+class ipc 9
+ create w 1
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ write w 10
+ associate n 1
+ unix_read r 3
+ unix_write w 3
+
+class passwd 5
+ passwd w 1
+ chfn w 5
+ chsh w 5
+ rootok n 1
+ crontab w 5
+
+class drawable 5
+ create w 1
+ destroy w 1
+ draw w 10
+ copy r 10
+ getattr r 7
+
+class window 26
+ addchild w 1
+ create w 1
+ destroy w 1
+ map w 1
+ unmap w 1
+ chstack w 10
+ chproplist w 7
+ chprop w 10
+ listprop r 5
+ getattr r 5
+ setattr w 5
+ setfocus w 1
+ move w 10
+ chselection w 10
+ chparent w 5
+ ctrllife w 5
+ enumerate w 1
+ transparent w 1
+ mousemotion w 10
+ clientcomevent w 5
+ inputevent w 5
+ drawevent w 5
+ windowchangeevent w 5
+windowchangerequest w 5
+ serverchangeevent w 5
+ extensionevent w 5
+
+class gc 4
+ create w 1
+ free w 1
+ getattr r 5
+ setattr w 5
+
+class font 4
+ load r 1
+ free w 1
+ getattr r 5
+ use r 1
+
+class colormap 9
+ create w 1
+ free w 1
+ install w 10
+ uninstall w 1
+ list r 5
+ read r 10
+ store w 10
+ getattr r 5
+ setattr w 5
+
+class property 4
+ create w 1
+ free w 1
+ read r 10
+ write w 10
+
+class cursor 5
+ create w 1
+ createglyph w 10
+ free w 1
+ assign w 10
+ setattr w 5
+
+class xclient 1
+ kill w 1
+
+class xinput 11
+ lookup r 10
+ getattr r 5
+ setattr w 5
+ setfocus w 10
+ warppointer w 10
+ activegrab w 1
+ passivegrab w 1
+ ungrab w 1
+ bell w 3
+ mousemotion w 10
+ relabelinput b 3
+
+class xserver 8
+ screensaver w 10
+ gethostlist r 7
+ sethostlist w 7
+ getfontpath r 7
+ setfontpath w 7
+ getattr r 7
+ grab w 10
+ ungrab w 1
+
+class xextension 2
+ query r 10
+ use b 1
+
+class pax 6
+ pageexec n 1
+ emutramp n 1
+ mprotect n 1
+ randmmap n 1
+ randexec n 1
+ segmexec n 1
+
+class netlink_route_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_firewall_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_tcpdiag_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_nflog_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_xfrm_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_selinux_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_audit_socket 26
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+ nlmsg_relay w 10
+ nlmsg_readpriv r 10
+
+class netlink_ip6fw_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_dnrt_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_kobject_uevent_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class dbus 2
+ acquire_svc b 1
+ send_msg w 10
+
+class nscd 8
+ getpwd r 7
+ getgrp r 7
+ gethost r 7
+ getstat r 7
+ admin w 5
+ shmempwd r 7
+ shmemgrp r 7
+ shmemhost r 7
+
+class association 4
+ sendto w 10
+ recvfrom r 10
+ setcontext w 3
+ polmatch r 1
+
+class appletalk_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 1
+ setattr w 1
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class key 7
+ view r 7
+ read r 10
+ write w 10
+ search r 5
+ link w 7
+ setattr w 7
+ create w 10
+
+class packet 3
+ send w 10
+ recv r 10
+ relabelto w 3
+
+class context 2
+ contains n 1
+ translate n 1
diff --git a/apol/perm_maps/apol_perm_mapping_ver22 b/apol/perm_maps/apol_perm_mapping_ver22
new file mode 100644
index 0000000..e5b115f
--- /dev/null
+++ b/apol/perm_maps/apol_perm_mapping_ver22
@@ -0,0 +1,998 @@
+# This is a permission map file for use in policy analysis. This
+# file maps object permissions (read, getattr, setattr, ..., etc.)
+# for an object class, to exactly one of the following: read, write,
+# both, or none. This file may be edited as long as the specific
+# syntax rules are obeyed.
+#
+# For each object class, there is a set of object permissions that are
+# individually mapped to read, write, both, or none. If a new object
+# class is added, make sure that the current number of object classes
+# is increased.
+#
+# The syntax for an object class definition is:
+# class <class_name> <num_permissions>
+#
+# This is followed by each permission and its individual mapping to one
+# of the following:
+#
+# r = Read
+# w = Write
+# n = None
+# b = Both
+#
+# Additionally, you can choose to follow the mapping with an optional
+# permission weight value from 1 (less importance) to 10 (higher importance).
+# 10 is the default weight value if one is not provided.
+#
+# Look to the examples below for further clarification.
+#
+# Number of object classes.
+59
+
+class security 11
+ compute_av n 1
+ compute_create n 1
+ compute_member n 1
+ check_context n 1
+ load_policy n 1
+ compute_relabel n 1
+ compute_user n 1
+ setenforce n 1
+ setbool n 1
+ setsecparam n 1
+ setcheckreqprot n 1
+
+class process 30
+ fork n 1
+ transition w 5
+ sigchld w 1
+ sigkill w 1
+ sigstop w 1
+ signull n 1
+ signal w 5
+ ptrace b 10
+ getsched r 1
+ setsched w 1
+ getsession r 1
+ getpgid r 1
+ setpgid w 5
+ getcap r 3
+ setcap w 1
+ share b 1
+ getattr r 1
+ setexec w 1
+ setfscreate w 1
+ noatsecure n 1
+ siginh n 1
+ setrlimit n 1
+ rlimitinh n 1
+ dyntransition w 10
+ setcurrent w 1
+ execmem n 1
+ execstack n 1
+ execheap n 1
+ setkeycreate w 1
+ setsockcreate w 1
+
+class system 4
+ ipc_info n 1
+ syslog_read n 1
+ syslog_mod n 1
+ syslog_console n 1
+
+class capability 31
+ chown n 3
+ dac_override n 1
+ dac_read_search n 1
+ fowner n 1
+ fsetid n 1
+ kill n 1
+ setgid n 3
+ setuid n 1
+ setpcap n 3
+ linux_immutable n 1
+ net_bind_service n 1
+ net_broadcast n 1
+ net_admin n 1
+ net_raw n 1
+ ipc_lock n 1
+ ipc_owner n 1
+ sys_module n 1
+ sys_rawio n 1
+ sys_chroot n 1
+ sys_ptrace n 1
+ sys_pacct n 1
+ sys_admin n 3
+ sys_boot n 1
+ sys_nice n 1
+ sys_resource n 1
+ sys_time n 1
+ sys_tty_config n 1
+ mknod n 1
+ lease n 1
+ audit_write n 3
+ audit_control n 1
+
+class filesystem 10
+ mount w 1
+ remount w 1
+ unmount w 1
+ getattr r 1
+ relabelfrom r 10
+ relabelto w 10
+ transition w 1
+ associate n 1
+ quotamod w 1
+ quotaget r 1
+
+class file 20
+ execute_no_trans r 1
+ entrypoint r 1
+ execmod n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class dir 22
+ add_name w 5
+ remove_name w 1
+ reparent w 1
+ search r 1
+ rmdir b 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class fd 1
+ use b 1
+
+class lnk_file 17
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 1
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class chr_file 20
+ execute_no_trans r 1
+ entrypoint r 1
+ execmod n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class blk_file 17
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class sock_file 17
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 1
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class fifo_file 17
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class tcp_socket 27
+ connectto w 1
+ newconn w 1
+ acceptfrom r 1
+ node_bind n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+ name_connect w 1
+
+class udp_socket 23
+ node_bind n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class rawip_socket 23
+ node_bind n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 1
+ setattr w 1
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class node 7
+ tcp_recv r 10
+ tcp_send w 10
+ udp_recv r 10
+ udp_send w 10
+ rawip_recv r 10
+ rawip_send w 10
+ enforce_dest n 1
+
+class netif 6
+ tcp_recv r 10
+ tcp_send w 10
+ udp_recv r 10
+ udp_send w 10
+ rawip_recv r 10
+ rawip_send w 10
+
+class netlink_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class packet_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class key_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class unix_stream_socket 25
+ connectto w 1
+ newconn w 1
+ acceptfrom r 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class unix_dgram_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class sem 9
+ create w 1
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ write w 10
+ associate n 1
+ unix_read r 3
+ unix_write w 3
+
+class msg 2
+ send w 10
+ receive r 10
+
+class msgq 10
+ enqueue w 1
+ create w 1
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ write w 10
+ associate n 1
+ unix_read r 3
+ unix_write w 3
+
+class shm 10
+ lock w 1
+ create w 1
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ write w 10
+ associate n 1
+ unix_read r 3
+ unix_write w 3
+
+class ipc 9
+ create w 1
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ write w 10
+ associate n 1
+ unix_read r 3
+ unix_write w 3
+
+class passwd 5
+ passwd w 1
+ chfn w 5
+ chsh w 5
+ rootok n 1
+ crontab w 5
+
+class drawable 5
+ create w 1
+ destroy w 1
+ draw w 10
+ copy r 10
+ getattr r 7
+
+class window 26
+ addchild w 1
+ create w 1
+ destroy w 1
+ map w 1
+ unmap w 1
+ chstack w 10
+ chproplist w 7
+ chprop w 10
+ listprop r 5
+ getattr r 5
+ setattr w 5
+ setfocus w 1
+ move w 10
+ chselection w 10
+ chparent w 5
+ ctrllife w 5
+ enumerate w 1
+ transparent w 1
+ mousemotion w 10
+ clientcomevent w 5
+ inputevent w 5
+ drawevent w 5
+ windowchangeevent w 5
+windowchangerequest w 5
+ serverchangeevent w 5
+ extensionevent w 5
+
+class gc 4
+ create w 1
+ free w 1
+ getattr r 5
+ setattr w 5
+
+class font 4
+ load r 1
+ free w 1
+ getattr r 5
+ use r 1
+
+class colormap 9
+ create w 1
+ free w 1
+ install w 10
+ uninstall w 1
+ list r 5
+ read r 10
+ store w 10
+ getattr r 5
+ setattr w 5
+
+class property 4
+ create w 1
+ free w 1
+ read r 10
+ write w 10
+
+class cursor 5
+ create w 1
+ createglyph w 10
+ free w 1
+ assign w 10
+ setattr w 5
+
+class xclient 1
+ kill w 1
+
+class xinput 11
+ lookup r 10
+ getattr r 5
+ setattr w 5
+ setfocus w 10
+ warppointer w 10
+ activegrab w 1
+ passivegrab w 1
+ ungrab w 1
+ bell w 3
+ mousemotion w 10
+ relabelinput b 3
+
+class xserver 8
+ screensaver w 10
+ gethostlist r 7
+ sethostlist w 7
+ getfontpath r 7
+ setfontpath w 7
+ getattr r 7
+ grab w 10
+ ungrab w 1
+
+class xextension 2
+ query r 10
+ use b 1
+
+class pax 6
+ pageexec n 1
+ emutramp n 1
+ mprotect n 1
+ randmmap n 1
+ randexec n 1
+ segmexec n 1
+
+class netlink_route_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_firewall_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_tcpdiag_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_nflog_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_xfrm_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_selinux_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_audit_socket 26
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+ nlmsg_relay w 10
+ nlmsg_readpriv r 10
+
+class netlink_ip6fw_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_dnrt_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_kobject_uevent_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class dbus 2
+ acquire_svc b 1
+ send_msg w 10
+
+class nscd 8
+ getpwd r 7
+ getgrp r 7
+ gethost r 7
+ getstat r 7
+ admin w 5
+ shmempwd r 7
+ shmemgrp r 7
+ shmemhost r 7
+
+class association 4
+ sendto w 10
+ recvfrom r 10
+ setcontext w 3
+ polmatch r 1
+
+class appletalk_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 1
+ setattr w 1
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class key 7
+ view r 7
+ read r 10
+ write w 10
+ search r 5
+ link w 7
+ setattr w 7
+ create w 10
+
+class packet 3
+ send w 10
+ recv r 10
+ relabelto w 3
+
+class context 2
+ contains n 1
+ translate n 1
diff --git a/apol/perm_maps/apol_perm_mapping_ver23 b/apol/perm_maps/apol_perm_mapping_ver23
new file mode 100644
index 0000000..e5b115f
--- /dev/null
+++ b/apol/perm_maps/apol_perm_mapping_ver23
@@ -0,0 +1,998 @@
+# This is a permission map file for use in policy analysis. This
+# file maps object permissions (read, getattr, setattr, ..., etc.)
+# for an object class, to exactly one of the following: read, write,
+# both, or none. This file may be edited as long as the specific
+# syntax rules are obeyed.
+#
+# For each object class, there is a set of object permissions that are
+# individually mapped to read, write, both, or none. If a new object
+# class is added, make sure that the current number of object classes
+# is increased.
+#
+# The syntax for an object class definition is:
+# class <class_name> <num_permissions>
+#
+# This is followed by each permission and its individual mapping to one
+# of the following:
+#
+# r = Read
+# w = Write
+# n = None
+# b = Both
+#
+# Additionally, you can choose to follow the mapping with an optional
+# permission weight value from 1 (less importance) to 10 (higher importance).
+# 10 is the default weight value if one is not provided.
+#
+# Look to the examples below for further clarification.
+#
+# Number of object classes.
+59
+
+class security 11
+ compute_av n 1
+ compute_create n 1
+ compute_member n 1
+ check_context n 1
+ load_policy n 1
+ compute_relabel n 1
+ compute_user n 1
+ setenforce n 1
+ setbool n 1
+ setsecparam n 1
+ setcheckreqprot n 1
+
+class process 30
+ fork n 1
+ transition w 5
+ sigchld w 1
+ sigkill w 1
+ sigstop w 1
+ signull n 1
+ signal w 5
+ ptrace b 10
+ getsched r 1
+ setsched w 1
+ getsession r 1
+ getpgid r 1
+ setpgid w 5
+ getcap r 3
+ setcap w 1
+ share b 1
+ getattr r 1
+ setexec w 1
+ setfscreate w 1
+ noatsecure n 1
+ siginh n 1
+ setrlimit n 1
+ rlimitinh n 1
+ dyntransition w 10
+ setcurrent w 1
+ execmem n 1
+ execstack n 1
+ execheap n 1
+ setkeycreate w 1
+ setsockcreate w 1
+
+class system 4
+ ipc_info n 1
+ syslog_read n 1
+ syslog_mod n 1
+ syslog_console n 1
+
+class capability 31
+ chown n 3
+ dac_override n 1
+ dac_read_search n 1
+ fowner n 1
+ fsetid n 1
+ kill n 1
+ setgid n 3
+ setuid n 1
+ setpcap n 3
+ linux_immutable n 1
+ net_bind_service n 1
+ net_broadcast n 1
+ net_admin n 1
+ net_raw n 1
+ ipc_lock n 1
+ ipc_owner n 1
+ sys_module n 1
+ sys_rawio n 1
+ sys_chroot n 1
+ sys_ptrace n 1
+ sys_pacct n 1
+ sys_admin n 3
+ sys_boot n 1
+ sys_nice n 1
+ sys_resource n 1
+ sys_time n 1
+ sys_tty_config n 1
+ mknod n 1
+ lease n 1
+ audit_write n 3
+ audit_control n 1
+
+class filesystem 10
+ mount w 1
+ remount w 1
+ unmount w 1
+ getattr r 1
+ relabelfrom r 10
+ relabelto w 10
+ transition w 1
+ associate n 1
+ quotamod w 1
+ quotaget r 1
+
+class file 20
+ execute_no_trans r 1
+ entrypoint r 1
+ execmod n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class dir 22
+ add_name w 5
+ remove_name w 1
+ reparent w 1
+ search r 1
+ rmdir b 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class fd 1
+ use b 1
+
+class lnk_file 17
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 1
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class chr_file 20
+ execute_no_trans r 1
+ entrypoint r 1
+ execmod n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class blk_file 17
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class sock_file 17
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 1
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class fifo_file 17
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ unlink w 1
+ link w 1
+ rename w 5
+ execute r 1
+ swapon b 1
+ quotaon b 1
+ mounton b 1
+
+class socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class tcp_socket 27
+ connectto w 1
+ newconn w 1
+ acceptfrom r 1
+ node_bind n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+ name_connect w 1
+
+class udp_socket 23
+ node_bind n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class rawip_socket 23
+ node_bind n 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 1
+ setattr w 1
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class node 7
+ tcp_recv r 10
+ tcp_send w 10
+ udp_recv r 10
+ udp_send w 10
+ rawip_recv r 10
+ rawip_send w 10
+ enforce_dest n 1
+
+class netif 6
+ tcp_recv r 10
+ tcp_send w 10
+ udp_recv r 10
+ udp_send w 10
+ rawip_recv r 10
+ rawip_send w 10
+
+class netlink_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class packet_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class key_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class unix_stream_socket 25
+ connectto w 1
+ newconn w 1
+ acceptfrom r 1
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class unix_dgram_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class sem 9
+ create w 1
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ write w 10
+ associate n 1
+ unix_read r 3
+ unix_write w 3
+
+class msg 2
+ send w 10
+ receive r 10
+
+class msgq 10
+ enqueue w 1
+ create w 1
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ write w 10
+ associate n 1
+ unix_read r 3
+ unix_write w 3
+
+class shm 10
+ lock w 1
+ create w 1
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ write w 10
+ associate n 1
+ unix_read r 3
+ unix_write w 3
+
+class ipc 9
+ create w 1
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ write w 10
+ associate n 1
+ unix_read r 3
+ unix_write w 3
+
+class passwd 5
+ passwd w 1
+ chfn w 5
+ chsh w 5
+ rootok n 1
+ crontab w 5
+
+class drawable 5
+ create w 1
+ destroy w 1
+ draw w 10
+ copy r 10
+ getattr r 7
+
+class window 26
+ addchild w 1
+ create w 1
+ destroy w 1
+ map w 1
+ unmap w 1
+ chstack w 10
+ chproplist w 7
+ chprop w 10
+ listprop r 5
+ getattr r 5
+ setattr w 5
+ setfocus w 1
+ move w 10
+ chselection w 10
+ chparent w 5
+ ctrllife w 5
+ enumerate w 1
+ transparent w 1
+ mousemotion w 10
+ clientcomevent w 5
+ inputevent w 5
+ drawevent w 5
+ windowchangeevent w 5
+windowchangerequest w 5
+ serverchangeevent w 5
+ extensionevent w 5
+
+class gc 4
+ create w 1
+ free w 1
+ getattr r 5
+ setattr w 5
+
+class font 4
+ load r 1
+ free w 1
+ getattr r 5
+ use r 1
+
+class colormap 9
+ create w 1
+ free w 1
+ install w 10
+ uninstall w 1
+ list r 5
+ read r 10
+ store w 10
+ getattr r 5
+ setattr w 5
+
+class property 4
+ create w 1
+ free w 1
+ read r 10
+ write w 10
+
+class cursor 5
+ create w 1
+ createglyph w 10
+ free w 1
+ assign w 10
+ setattr w 5
+
+class xclient 1
+ kill w 1
+
+class xinput 11
+ lookup r 10
+ getattr r 5
+ setattr w 5
+ setfocus w 10
+ warppointer w 10
+ activegrab w 1
+ passivegrab w 1
+ ungrab w 1
+ bell w 3
+ mousemotion w 10
+ relabelinput b 3
+
+class xserver 8
+ screensaver w 10
+ gethostlist r 7
+ sethostlist w 7
+ getfontpath r 7
+ setfontpath w 7
+ getattr r 7
+ grab w 10
+ ungrab w 1
+
+class xextension 2
+ query r 10
+ use b 1
+
+class pax 6
+ pageexec n 1
+ emutramp n 1
+ mprotect n 1
+ randmmap n 1
+ randexec n 1
+ segmexec n 1
+
+class netlink_route_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_firewall_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_tcpdiag_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_nflog_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_xfrm_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_selinux_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_audit_socket 26
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+ nlmsg_relay w 10
+ nlmsg_readpriv r 10
+
+class netlink_ip6fw_socket 24
+ nlmsg_read r 10
+ nlmsg_write w 10
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_dnrt_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class netlink_kobject_uevent_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 7
+ setattr w 7
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class dbus 2
+ acquire_svc b 1
+ send_msg w 10
+
+class nscd 8
+ getpwd r 7
+ getgrp r 7
+ gethost r 7
+ getstat r 7
+ admin w 5
+ shmempwd r 7
+ shmemgrp r 7
+ shmemhost r 7
+
+class association 4
+ sendto w 10
+ recvfrom r 10
+ setcontext w 3
+ polmatch r 1
+
+class appletalk_socket 22
+ ioctl n 1
+ read r 10
+ write w 10
+ create w 1
+ getattr r 1
+ setattr w 1
+ lock n 1
+ relabelfrom r 10
+ relabelto w 10
+ append w 1
+ bind w 1
+ connect w 1
+ listen r 1
+ accept r 1
+ getopt r 1
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ name_bind n 1
+
+class key 7
+ view r 7
+ read r 10
+ write w 10
+ search r 5
+ link w 7
+ setattr w 7
+ create w 10
+
+class packet 3
+ send w 10
+ recv r 10
+ relabelto w 3
+
+class context 2
+ contains n 1
+ translate n 1
diff --git a/apol/perm_maps/apol_perm_mapping_ver24 b/apol/perm_maps/apol_perm_mapping_ver24
new file mode 100644
index 0000000..102ce04
--- /dev/null
+++ b/apol/perm_maps/apol_perm_mapping_ver24
@@ -0,0 +1,1227 @@
+# This is a permission map file for use in policy analysis. This
+# file maps object permissions (read, getattr, setattr, ..., etc.)
+# for an object class, to exactly one of the following: read, write,
+# both, or none. This file may be edited as long as the specific
+# syntax rules are obeyed.
+#
+# For each object class, there is a set of object permissions that are
+# individually mapped to read, write, both, or none. If a new object
+# class is added, make sure that the current number of object classes
+# is increased.
+#
+# The syntax for an object class definition is:
+# class <class_name> <num_permissions>
+#
+# This is followed by each permission and its individual mapping to one
+# of the following:
+#
+# r = Read
+# w = Write
+# n = None
+# b = Both
+#
+# Additionally, you can choose to follow the mapping with an optional
+# permission weight value from 1 (less importance) to 10 (higher importance).
+# 10 is the default weight value if one is not provided.
+#
+# Look to the examples below for further clarification.
+#
+# Number of object classes.
+77
+
+class netlink_audit_socket 27
+ nlmsg_relay w 10
+ nlmsg_tty_audit w 10
+ nlmsg_readpriv r 10
+ nlmsg_write w 10
+ nlmsg_read r 10
+ append w 1
+ bind w 1
+ connect w 1
+ create w 1
+ write w 10
+ relabelfrom r 10
+ ioctl n 1
+ name_bind n 1
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ getattr r 7
+ setattr w 7
+ accept r 1
+ getopt r 1
+ read r 10
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ lock n 1
+ relabelto w 10
+ listen r 1
+
+class tcp_socket 27
+ acceptfrom r 1
+ connectto w 1
+ node_bind n 1
+ newconn w 1
+ name_connect w 1
+ append w 1
+ bind w 1
+ connect w 1
+ create w 1
+ write w 10
+ relabelfrom r 10
+ ioctl n 1
+ name_bind n 1
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ getattr r 7
+ setattr w 7
+ accept r 1
+ getopt r 1
+ read r 10
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ lock n 1
+ relabelto w 10
+ listen r 1
+
+class msgq 10
+ enqueue w 1
+ associate n 1
+ create w 1
+ write w 10
+ unix_read r 3
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ unix_write w 3
+
+class x_property 7
+ append w 10
+ create w 1
+ write w 10
+ destroy w 1
+ getattr r 7
+ setattr w 7
+ read r 10
+
+class db_procedure 9
+ execute r 1
+ install w 10
+ entrypoint r 1
+ drop w 1
+ create w 1
+ relabelfrom r 1
+ getattr r 7
+ setattr w 7
+ relabelto w 1
+
+class dir 23
+ rmdir b 1
+ remove_name w 1
+ add_name w 5
+ reparent w 1
+ search r 1
+ open n 1
+ append w 1
+ create w 1
+ execute r 1
+ write w 10
+ relabelfrom r 10
+ link w 1
+ unlink w 1
+ ioctl n 1
+ getattr r 7
+ setattr w 7
+ read r 10
+ rename w 5
+ lock n 1
+ relabelto w 10
+ mounton b 1
+ quotaon b 1
+ swapon b 1
+
+class peer 1
+ recv r 10
+
+class blk_file 18
+ open n 1
+ append w 1
+ create w 1
+ execute r 1
+ write w 10
+ relabelfrom r 10
+ link w 1
+ unlink w 1
+ ioctl n 1
+ getattr r 7
+ setattr w 7
+ read r 10
+ rename w 5
+ lock n 1
+ relabelto w 10
+ mounton b 1
+ quotaon b 1
+ swapon b 1
+
+class chr_file 21
+ entrypoint r 1
+ execmod n 1
+ execute_no_trans r 1
+ open n 1
+ append w 1
+ create w 1
+ execute r 1
+ write w 10
+ relabelfrom r 10
+ link w 1
+ unlink w 1
+ ioctl n 1
+ getattr r 7
+ setattr w 7
+ read r 10
+ rename w 5
+ lock n 1
+ relabelto w 10
+ mounton b 1
+ quotaon b 1
+ swapon b 1
+
+class db_table 12
+ select n 1
+ delete w 1
+ update w 10
+ insert w 10
+ use r 10
+ lock n 1
+ drop w 1
+ create w 1
+ relabelfrom r 1
+ getattr r 7
+ setattr w 7
+ relabelto w 1
+
+class db_tuple 7
+ select n 1
+ delete w 1
+ update w 10
+ relabelfrom r 1
+ insert w 10
+ use r 10
+ relabelto w 1
+
+class dbus 2
+ acquire_svc b 1
+ send_msg w 10
+
+class ipc 9
+ associate n 1
+ create w 1
+ write w 10
+ unix_read r 3
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ unix_write w 3
+
+class lnk_file 17
+ append w 1
+ create w 1
+ execute r 1
+ write w 10
+ relabelfrom r 10
+ link w 1
+ unlink w 1
+ ioctl n 1
+ getattr r 7
+ setattr w 7
+ read r 10
+ rename w 1
+ lock n 1
+ relabelto w 10
+ mounton b 1
+ quotaon b 1
+ swapon b 1
+
+class process 30
+ getcap r 3
+ setcap w 1
+ sigstop w 1
+ sigchld w 1
+ share b 1
+ execheap n 1
+ setcurrent w 1
+ setfscreate w 1
+ setkeycreate w 1
+ siginh n 1
+ dyntransition w 10
+ transition w 5
+ fork n 1
+ getsession r 1
+ noatsecure n 1
+ sigkill w 1
+ signull n 1
+ setrlimit n 1
+ getattr r 1
+ getsched r 1
+ setexec w 1
+ setsched w 1
+ getpgid r 1
+ setpgid w 5
+ ptrace b 10
+ execstack n 1
+ rlimitinh n 1
+ setsockcreate w 1
+ signal w 5
+ execmem n 1
+
+class capability2 2
+ mac_override n 1
+ mac_admin n 1
+
+class fd 1
+ use b 1
+
+class packet 7
+ forward_out w 10
+ flow_out w 10
+ send w 10
+ recv r 10
+ forward_in r 10
+ relabelto w 3
+ flow_in r 10
+
+class socket 22
+ append w 1
+ bind w 1
+ connect w 1
+ create w 1
+ write w 10
+ relabelfrom r 10
+ ioctl n 1
+ name_bind n 1
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ getattr r 7
+ setattr w 7
+ accept r 1
+ getopt r 1
+ read r 10
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ lock n 1
+ relabelto w 10
+ listen r 1
+
+class fifo_file 18
+ open n 1
+ append w 1
+ create w 1
+ execute r 1
+ write w 10
+ relabelfrom r 10
+ link w 1
+ unlink w 1
+ ioctl n 1
+ getattr r 7
+ setattr w 7
+ read r 10
+ rename w 5
+ lock n 1
+ relabelto w 10
+ mounton b 1
+ quotaon b 1
+ swapon b 1
+
+class file 21
+ entrypoint r 1
+ execmod n 1
+ execute_no_trans r 1
+ open n 1
+ append w 1
+ create w 1
+ execute r 1
+ write w 10
+ relabelfrom r 10
+ link w 1
+ unlink w 1
+ ioctl n 1
+ getattr r 7
+ setattr w 7
+ read r 10
+ rename w 5
+ lock n 1
+ relabelto w 10
+ mounton b 1
+ quotaon b 1
+ swapon b 1
+
+class node 11
+ rawip_recv r 10
+ tcp_recv r 10
+ udp_recv r 10
+ rawip_send w 10
+ tcp_send w 10
+ udp_send w 10
+ dccp_recv r 10
+ dccp_send w 10
+ enforce_dest n 1
+ sendto w 10
+ recvfrom r 10
+
+class x_cursor 7
+ create w 1
+ write w 10
+ destroy w 1
+ getattr r 7
+ setattr w 7
+ read r 10
+ use r 1
+
+class x_server 6
+ record r 10
+ getattr r 7
+ grab w 1
+ setattr w 7
+ manage w 10
+ debug b 10
+
+class netlink_nflog_socket 22
+ append w 1
+ bind w 1
+ connect w 1
+ create w 1
+ write w 10
+ relabelfrom r 10
+ ioctl n 1
+ name_bind n 1
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ getattr r 7
+ setattr w 7
+ accept r 1
+ getopt r 1
+ read r 10
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ lock n 1
+ relabelto w 10
+ listen r 1
+
+class key 7
+ create w 10
+ write w 10
+ view r 7
+ link w 7
+ setattr w 7
+ read r 10
+ search r 5
+
+class netlink_tcpdiag_socket 24
+ nlmsg_write w 10
+ nlmsg_read r 10
+ append w 1
+ bind w 1
+ connect w 1
+ create w 1
+ write w 10
+ relabelfrom r 10
+ ioctl n 1
+ name_bind n 1
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ getattr r 7
+ setattr w 7
+ accept r 1
+ getopt r 1
+ read r 10
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ lock n 1
+ relabelto w 10
+ listen r 1
+
+class unix_stream_socket 25
+ acceptfrom r 1
+ connectto w 1
+ newconn w 1
+ append w 1
+ bind w 1
+ connect w 1
+ create w 1
+ write w 10
+ relabelfrom r 10
+ ioctl n 1
+ name_bind n 1
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ getattr r 7
+ setattr w 7
+ accept r 1
+ getopt r 1
+ read r 10
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ lock n 1
+ relabelto w 10
+ listen r 1
+
+class x_synthetic_event 2
+ send w 10
+ receive r 10
+
+class db_database 11
+ access b 10
+ set_param w 7
+ load_module r 10
+ get_param r 7
+ install_module r 10
+ drop w 1
+ create w 1
+ relabelfrom r 1
+ getattr r 7
+ setattr w 7
+ relabelto w 1
+
+class kernel_service 2
+ create_files_as n 1
+ use_as_override n 1
+
+class netlink_route_socket 24
+ nlmsg_write w 10
+ nlmsg_read r 10
+ append w 1
+ bind w 1
+ connect w 1
+ create w 1
+ write w 10
+ relabelfrom r 10
+ ioctl n 1
+ name_bind n 1
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ getattr r 7
+ setattr w 7
+ accept r 1
+ getopt r 1
+ read r 10
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ lock n 1
+ relabelto w 10
+ listen r 1
+
+class x_extension 2
+ use r 1
+ query r 5
+
+class shm 10
+ lock w 1
+ associate n 1
+ create w 1
+ write w 10
+ unix_read r 3
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ unix_write w 3
+
+class x_resource 2
+ write w 10
+ read r 10
+
+class netlink_selinux_socket 22
+ append w 1
+ bind w 1
+ connect w 1
+ create w 1
+ write w 10
+ relabelfrom r 10
+ ioctl n 1
+ name_bind n 1
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ getattr r 7
+ setattr w 7
+ accept r 1
+ getopt r 1
+ read r 10
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ lock n 1
+ relabelto w 10
+ listen r 1
+
+class capability 32
+ setfcap n 1
+ setpcap n 3
+ fowner n 1
+ sys_boot n 1
+ sys_tty_config n 1
+ net_raw n 1
+ sys_admin n 3
+ sys_chroot n 1
+ sys_module n 1
+ sys_rawio n 1
+ dac_override n 1
+ ipc_owner n 1
+ kill n 1
+ dac_read_search n 1
+ sys_pacct n 1
+ net_broadcast n 1
+ net_bind_service n 1
+ sys_nice n 1
+ sys_time n 1
+ fsetid n 1
+ mknod n 1
+ setgid n 3
+ setuid n 1
+ lease n 1
+ net_admin n 1
+ audit_write n 3
+ linux_immutable n 1
+ sys_ptrace n 1
+ audit_control n 1
+ ipc_lock n 1
+ sys_resource n 1
+ chown n 3
+
+class netlink_ip6fw_socket 24
+ nlmsg_write w 10
+ nlmsg_read r 10
+ append w 1
+ bind w 1
+ connect w 1
+ create w 1
+ write w 10
+ relabelfrom r 10
+ ioctl n 1
+ name_bind n 1
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ getattr r 7
+ setattr w 7
+ accept r 1
+ getopt r 1
+ read r 10
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ lock n 1
+ relabelto w 10
+ listen r 1
+
+class dccp_socket 24
+ node_bind n 1
+ name_connect w 10
+ append w 1
+ bind w 1
+ connect w 1
+ create w 1
+ write w 10
+ relabelfrom r 10
+ ioctl n 1
+ name_bind n 1
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ getattr r 7
+ setattr w 7
+ accept r 1
+ getopt r 1
+ read r 10
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ lock n 1
+ relabelto w 10
+ listen r 1
+
+class netlink_firewall_socket 24
+ nlmsg_write w 10
+ nlmsg_read r 10
+ append w 1
+ bind w 1
+ connect w 1
+ create w 1
+ write w 10
+ relabelfrom r 10
+ ioctl n 1
+ name_bind n 1
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ getattr r 7
+ setattr w 7
+ accept r 1
+ getopt r 1
+ read r 10
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ lock n 1
+ relabelto w 10
+ listen r 1
+
+class sock_file 18
+ open n 1
+ append w 1
+ create w 1
+ execute r 1
+ write w 10
+ relabelfrom r 10
+ link w 1
+ unlink w 1
+ ioctl n 1
+ getattr r 7
+ setattr w 7
+ read r 10
+ rename w 1
+ lock n 1
+ relabelto w 10
+ mounton b 1
+ quotaon b 1
+ swapon b 1
+
+class unix_dgram_socket 22
+ append w 1
+ bind w 1
+ connect w 1
+ create w 1
+ write w 10
+ relabelfrom r 10
+ ioctl n 1
+ name_bind n 1
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ getattr r 7
+ setattr w 7
+ accept r 1
+ getopt r 1
+ read r 10
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ lock n 1
+ relabelto w 10
+ listen r 1
+
+class netlink_kobject_uevent_socket 22
+ append w 1
+ bind w 1
+ connect w 1
+ create w 1
+ write w 10
+ relabelfrom r 10
+ ioctl n 1
+ name_bind n 1
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ getattr r 7
+ setattr w 7
+ accept r 1
+ getopt r 1
+ read r 10
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ lock n 1
+ relabelto w 10
+ listen r 1
+
+class db_blob 10
+ write w 10
+ export r 10
+ import w 10
+ read r 10
+ drop w 1
+ create w 1
+ relabelfrom r 1
+ getattr r 7
+ setattr w 7
+ relabelto w 1
+
+class filesystem 10
+ associate n 1
+ quotaget r 1
+ relabelfrom r 10
+ transition w 1
+ getattr r 1
+ quotamod w 1
+ mount w 1
+ remount w 1
+ unmount w 1
+ relabelto w 10
+
+class netlink_xfrm_socket 24
+ nlmsg_write w 10
+ nlmsg_read r 10
+ append w 1
+ bind w 1
+ connect w 1
+ create w 1
+ write w 10
+ relabelfrom r 10
+ ioctl n 1
+ name_bind n 1
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ getattr r 7
+ setattr w 7
+ accept r 1
+ getopt r 1
+ read r 10
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ lock n 1
+ relabelto w 10
+ listen r 1
+
+class x_device 19
+ get_property r 7
+ list_property r 7
+ set_property w 7
+ add w 1
+ setfocus w 1
+ create w 1
+ freeze w 1
+ getfocus r 1
+ remove w 1
+ write w 10
+ force_cursor w 1
+ destroy w 1
+ bell w 1
+ getattr r 7
+ grab w 1
+ setattr w 7
+ read r 10
+ manage w 10
+ use r 1
+
+class netlink_dnrt_socket 22
+ append w 1
+ bind w 1
+ connect w 1
+ create w 1
+ write w 10
+ relabelfrom r 10
+ ioctl n 1
+ name_bind n 1
+ sendto r 10
+ recv_msg r 10
+ send_msg w 10
+ getattr r 7
+ setattr w 7
+ accept r 1
+ getopt r 1
+ read r 10
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ lock n 1
+ relabelto w 10
+ listen r 1
+
+class x_client 4
+ destroy w 1
+ getattr r 7
+ setattr w 7
+ manage w 10
+
+class x_gc 5
+ create w 1
+ destroy w 1
+ getattr r 7
+ setattr w 7
+ use r 1
+
+class context 2
+ contains n 1
+ translate n 1
+
+class nscd 10
+ shmemserv r 7
+ gethost r 7
+ getstat r 7
+ getgrp r 7
+ shmemhost r 7
+ shmempwd r 7
+ getpwd r 7
+ getserv r 7
+ shmemgrp r 7
+ admin w 5
+
+class passwd 5
+ chfn w 5
+ crontab w 5
+ passwd w 1
+ chsh w 5
+ rootok n 1
+
+class x_event 2
+ send w 10
+ receive r 10
+
+class x_font 6
+ create w 1
+ destroy w 1
+ add_glyph w 1
+ remove_glyph w 1
+ getattr r 7
+ use r 1
+
+class key_socket 22
+ append w 1
+ bind w 1
+ connect w 1
+ create w 1
+ write w 10
+ relabelfrom r 10
+ ioctl n 1
+ name_bind n 1
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ getattr r 7
+ setattr w 7
+ accept r 1
+ getopt r 1
+ read r 10
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ lock n 1
+ relabelto w 10
+ listen r 1
+
+class netif 10
+ rawip_recv r 10
+ tcp_recv r 10
+ udp_recv r 10
+ rawip_send w 10
+ egress w 10
+ ingress r 10
+ tcp_send w 10
+ udp_send w 10
+ dccp_recv r 10
+ dccp_send w 10
+
+class packet_socket 22
+ append w 1
+ bind w 1
+ connect w 1
+ create w 1
+ write w 10
+ relabelfrom r 10
+ ioctl n 1
+ name_bind n 1
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ getattr r 7
+ setattr w 7
+ accept r 1
+ getopt r 1
+ read r 10
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ lock n 1
+ relabelto w 10
+ listen r 1
+
+class memprotect 1
+ mmap_zero n 1
+
+class msg 2
+ send w 10
+ receive r 10
+
+class tun_socket 22
+ append w 1
+ bind w 1
+ connect w 1
+ create w 1
+ write w 10
+ relabelfrom r 10
+ ioctl n 1
+ name_bind n 1
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ getattr r 7
+ setattr w 7
+ accept r 1
+ getopt r 1
+ read r 10
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ lock n 1
+ relabelto w 10
+ listen r 1
+
+class udp_socket 23
+ node_bind n 1
+ append w 1
+ bind w 1
+ connect w 1
+ create w 1
+ write w 10
+ relabelfrom r 10
+ ioctl n 1
+ name_bind n 1
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ getattr r 7
+ setattr w 7
+ accept r 1
+ getopt r 1
+ read r 10
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ lock n 1
+ relabelto w 10
+ listen r 1
+
+class appletalk_socket 22
+ append w 1
+ bind w 1
+ connect w 1
+ create w 1
+ write w 10
+ relabelfrom r 10
+ ioctl n 1
+ name_bind n 1
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ getattr r 1
+ setattr w 1
+ accept r 1
+ getopt r 1
+ read r 10
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ lock n 1
+ relabelto w 10
+ listen r 1
+
+class x_colormap 10
+ add_color w 10
+ create w 1
+ write w 10
+ destroy w 1
+ install w 1
+ getattr r 7
+ read r 10
+ use r 1
+ remove_color w 10
+ uninstall w 1
+
+class x_screen 8
+ show_cursor w 1
+ hide_cursor w 1
+ saver_show w 1
+ getattr r 7
+ setattr w 7
+ saver_hide w 1
+ saver_getattr r 7
+ saver_setattr w 7
+
+class rawip_socket 23
+ node_bind n 1
+ append w 1
+ bind w 1
+ connect w 1
+ create w 1
+ write w 10
+ relabelfrom r 10
+ ioctl n 1
+ name_bind n 1
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ getattr r 1
+ setattr w 1
+ accept r 1
+ getopt r 1
+ read r 10
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ lock n 1
+ relabelto w 10
+ listen r 1
+
+class x_application_data 3
+ paste w 10
+paste_after_confirm w 10
+ copy r 10
+
+class association 4
+ setcontext w 3
+ sendto w 10
+ recvfrom r 10
+ polmatch r 1
+
+class x_selection 4
+ write w 10
+ getattr r 7
+ setattr w 7
+ read r 10
+
+class db_column 10
+ select r 10
+ update w 10
+ insert w 1
+ use r 10
+ drop w 1
+ create w 1
+ relabelfrom r 1
+ getattr r 7
+ setattr w 7
+ relabelto w 1
+
+class netlink_socket 22
+ append w 1
+ bind w 1
+ connect w 1
+ create w 1
+ write w 10
+ relabelfrom r 10
+ ioctl n 1
+ name_bind n 1
+ sendto w 10
+ recv_msg r 10
+ send_msg w 10
+ getattr r 7
+ setattr w 7
+ accept r 1
+ getopt r 1
+ read r 10
+ setopt w 1
+ shutdown w 1
+ recvfrom r 10
+ lock n 1
+ relabelto w 10
+ listen r 1
+
+class x_drawable 19
+ get_property r 7
+ list_property r 7
+ set_property w 7
+ add_child w 1
+ override n 1
+ blend w 1
+ send w 10
+ create w 1
+ hide w 1
+ receive r 10
+ write w 10
+ show w 1
+ destroy w 1
+ list_child r 7
+ getattr r 7
+ setattr w 7
+ read r 10
+ manage w 10
+ remove_child w 1
+
+class sem 9
+ associate n 1
+ create w 1
+ write w 10
+ unix_read r 3
+ destroy w 1
+ getattr r 1
+ setattr w 1
+ read r 10
+ unix_write w 3
+
+class system 5
+ module_request n 1
+ ipc_info n 1
+ syslog_read n 1
+ syslog_console n 1
+ syslog_mod n 1
+
+class x_keyboard 19
+ get_property r 7
+ list_property r 7
+ set_property w 7
+ add w 1
+ setfocus w 1
+ create w 1
+ freeze w 1
+ getfocus w 1
+ remove w 1
+ write w 10
+ force_cursor w 1
+ destroy w 1
+ bell w 1
+ getattr r 7
+ grab w 1
+ setattr w 7
+ read r 10
+ manage w 10
+ use r 1
+
+class security 11
+ compute_member n 1
+ compute_user n 1
+ compute_create n 1
+ setenforce n 1
+ check_context n 1
+ setcheckreqprot n 1
+ compute_relabel n 1
+ setbool n 1
+ load_policy n 1
+ setsecparam n 1
+ compute_av n 1
+
+class x_pointer 19
+ get_property r 7
+ list_property r 7
+ set_property w 7
+ add w 1
+ setfocus w 1
+ create w 1
+ freeze w 1
+ getfocus w 1
+ remove w 1
+ write w 10
+ force_cursor w 1
+ destroy w 1
+ bell w 1
+ getattr r 7
+ grab w 1
+ setattr w 7
+ read r 10
+ manage w 10
+ use r 1
diff --git a/apol/perms_map.tcl b/apol/perms_map.tcl
new file mode 100644
index 0000000..c1a1a75
--- /dev/null
+++ b/apol/perms_map.tcl
@@ -0,0 +1,410 @@
+# Copyright (C) 2003-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
+
+namespace eval Apol_Perms_Map {
+ variable dialog .apol_perms
+ variable user_default_pmap_name [file join $::env(HOME) .apol_perm_mapping]
+
+ variable opts ;# options for edit perm map dialog
+ variable widgets
+}
+
+proc Apol_Perms_Map::close {} {
+ variable opts
+
+ _close_dialog
+ set opts(filename) {}
+ set opts(is_saveable) 0
+ set opts(modified) 0
+}
+
+proc Apol_Perms_Map::showPermMappings {} {
+ variable dialog
+ if {[winfo exists $dialog]} {
+ raise $dialog
+ } else {
+ _createEditDialog
+ _refreshEditDialog
+ }
+}
+
+# Let the user select a permission map file to load. Returns 1 on
+# success, 0 on error.
+proc Apol_Perms_Map::openPermMapFromFile {} {
+ set pmap_name [tk_getOpenFile -title "Select Perm Map to Load" -parent .]
+ if {$pmap_name != {}} {
+ return [_loadPermMap $pmap_name [file tail $pmap_name] 1]
+ }
+ return 0
+}
+
+# Attempt to load the "default" permission map. If there exists
+# within the user's home directory a file called ".apol_perm_mapping"
+# then use that. Otherwise look for the file
+# "apol_perm_mapping_ver$ver", where $ver is the currently loaded
+# policy version number. If that fails then simply try
+# "apol_perm_mapping". If all of that fails, then display an error
+# message and abort the loading. Returns 1 on success, 0 on error.
+proc Apol_Perms_Map::openDefaultPermMap {} {
+ variable user_default_pmap_name
+ if {[file exists $user_default_pmap_name]} {
+ set pmap_name $user_default_pmap_name
+ set pmap_short "User Default Permission Map"
+ set pmap_editable 1
+ } else {
+ set pmap_editable 0
+ # try policy-specific file
+ set policy_version [apol_tcl_get_policy_version $::ApolTop::policy]
+ set pmap_name [apol_file_find_path "apol_perm_mapping_ver${policy_version}"]
+ if {$pmap_name == {}} {
+ # finally try fallback one
+ set pmap_name [apol_file_find_path apol_perm_mapping]
+ if {$pmap_name == {}} {
+ set message "Could not locate system default permission map. You must explicitly load a permission map from file."
+ if {[Apol_Progress_Dialog::is_waiting]} {
+ error $message
+ } else {
+ tk_messageBox -icon error -type ok -title "Permission Maps" \
+ -message $message
+ }
+ return 0
+ }
+ }
+ set pmap_short "System Default Permission Map (Read-Only)"
+ }
+ return [_loadPermMap $pmap_name $pmap_short $pmap_editable]
+}
+
+proc Apol_Perms_Map::savePermMap {} {
+ variable opts
+ if {!$opts(is_saveable)} {
+ savePermMapAs
+ } else {
+ _savePermMap $opts(filename) $opts(shortname)
+ }
+}
+
+proc Apol_Perms_Map::savePermMapAs {} {
+ set pmap_name [tk_getSaveFile -title "Save Perm Map" -parent .]
+ if {$pmap_name != {}} {
+ _savePermMap $pmap_name [file tail $pmap_name]
+ }
+}
+
+proc Apol_Perms_Map::saveDefaultPermMap {} {
+ variable user_default_pmap_name
+ variable opts
+ _savePermMap $user_default_pmap_name "User Default Permission Map"
+}
+
+proc Apol_Perms_Map::is_pmap_loaded {} {
+ variable opts
+ if {$opts(filename) == {}} {
+ return 0
+ }
+ return 1
+}
+
+#################### private functions below ####################
+
+
+proc Apol_Perms_Map::_loadPermMap {filename shortname saveable} {
+ if {[catch {$::ApolTop::policy open_permmap $filename} err]} {
+ if {[Apol_Progress_Dialog::is_waiting]} {
+ error $err
+ } else {
+ tk_messageBox -icon error -type ok -title "Permission Maps" -message $err
+ return 0
+ }
+ }
+ variable opts
+ set opts(filename) $filename
+ set opts(shortname) $shortname
+ set opts(is_saveable) $saveable
+ set opts(modified) 0
+ if {$err != {}} {
+ set len [llength [split $err "\n"]]
+ if {$len > 5} {
+ incr len -4
+ set err [lrange [split $err "\n"] 0 3]
+ lappend err "(plus $len more lines)"
+ set err [join $err "\n"]
+ }
+ if {![Apol_Progress_Dialog::is_waiting]} {
+ set message "There were warnings while opening the permission map:"
+ tk_messageBox -icon warning -type ok -title "Permission Maps" \
+ -message "$message\n\n$err"
+ }
+ } else {
+ if {![Apol_Progress_Dialog::is_waiting]} {
+ tk_messageBox -icon info -type ok -title "Permission Maps" \
+ -message "Permission map successfully loaded."
+ }
+ }
+ variable dialog
+ if {[winfo exists $dialog]} {
+ _refreshEditDialog
+ }
+ return 1
+}
+
+proc Apol_Perms_Map::_createEditDialog {} {
+ variable dialog
+ variable opts
+ variable widgets
+
+ set title "Permissions Mappings: $opts(shortname)"
+ Dialog $dialog -parent . -separator 1 -title $title -modal none \
+ -default 0 -cancel 2
+ set topf [frame [$dialog getframe].top]
+ pack $topf -side top -expand 1 -fill both
+
+ set classes_box [TitleFrame $topf.classes -text "Object Classes"]
+ pack $classes_box -side left -padx 2 -pady 2 -expand 0 -fill y
+ set widgets(classes) [Apol_Widget::makeScrolledListbox [$classes_box getframe].c \
+ -height 16 -width 24 -listvar Apol_Perms_Map::opts(classes)]
+ bind $widgets(classes).lb <<ListboxSelect>> Apol_Perms_Map::_refreshPermEdit
+ pack $widgets(classes) -expand 1 -fill both
+
+ set results_box [TitleFrame $topf.perms -text "Permission Mappings"]
+ pack $results_box -side right -padx 2 -pady 2 -expand 1 -fill both
+ set sw [ScrolledWindow [$results_box getframe].sw -auto both]
+ set widgets(perms) [ScrollableFrame $sw.perms -width 300]
+ $sw setwidget $widgets(perms)
+ pack $sw -expand 1 -fill both
+
+ set label_box [frame [$dialog getframe].l]
+ pack $label_box -side bottom -anchor center
+ set widgets(l1) [label $label_box.l1 -fg red -text ""]
+ set widgets(l2) [label $label_box.l2 -text ""]
+ pack $widgets(l1) $widgets(l2) -side left
+ # delay setting the labels' text until [_refresh_edit_dialog], to
+ # see if anything is unmapped
+
+ $dialog add -text "OK" -command Apol_Perms_Map::_okay
+ $dialog add -text "Apply" -command Apol_Perms_Map::_apply
+ $dialog add -text "Cancel" -command Apol_Perms_Map::_cancel
+
+ trace add variable Apol_Perms_Map::opts(modified) write \
+ Apol_Perms_Map::_toggleButtons
+
+ # forcibly invoke the button callback
+ set opts(modified) $opts(modified)
+ $dialog draw
+}
+
+proc Apol_Perms_Map::_refreshEditDialog {} {
+ variable opts
+ variable widgets
+
+ array set opts {
+ classes {}
+ }
+
+ set all_mapped 1
+ set class_index 0
+ foreach class [Apol_Class_Perms::getClasses] {
+ set suffix {}
+ set perm_list {}
+ foreach perm [Apol_Class_Perms::getPermsForClass $class] {
+ set direction [$::ApolTop::policy get_permmap_direction $class $perm]
+ set weight [$::ApolTop::policy get_permmap_weight $class $perm]
+ set opts(p:${class}:${perm}:map) $direction
+ set opts(p:${class}:${perm}:weight) $weight
+ if {$direction == $::APOL_PERMMAP_UNMAPPED} {
+ set suffix *
+ set all_mapped 0
+ }
+ lappend perm_list [list $perm $direction $weight]
+ }
+
+ # store original perm map values, needed if user cancels dialog
+ set opts(c:$class) $perm_list
+ lappend opts(classes) "$class$suffix"
+ if {$suffix != {}} {
+ $widgets(classes).lb itemconfigure $class_index -foreground red
+ }
+ incr class_index
+ }
+
+ # add the warning to the bottom if there exists any unmapped permissions
+ if {!$all_mapped} {
+ $widgets(l1) configure -text "*"
+ $widgets(l2) configure -text " - Undefined permission mapping(s)"
+ } else {
+ $widgets(l1) configure -text ""
+ $widgets(l2) configure -text ""
+ }
+}
+
+proc Apol_Perms_Map::_refreshPermEdit {} {
+ variable opts
+ variable widgets
+
+ focus $widgets(classes).lb
+
+ set perms [$widgets(perms) getframe]
+ foreach w [winfo children $perms] {
+ destroy $w
+ }
+
+ if {[set selection [$widgets(classes).lb curselection]] == {}} {
+ return
+ }
+ set class [lindex $opts(classes) [lindex $selection 0]]
+ set class [string trimright $class "*"]
+
+ foreach perm $opts(c:$class) {
+ foreach {perm map weight} $perm {break}
+ if {$map != $::APOL_PERMMAP_UNMAPPED} {
+ set l [label $perms.$perm:l -text $perm -anchor w]
+ } else {
+ set l [label $perms.$perm:l -text "${perm}*" -fg red -anchor w]
+ }
+ # tk_optionMenu does not have a -command flag, so implement an
+ # option menu via a menubutton
+ set menubutton [menubutton $perms.$perm:mb -bd 2 -relief raised \
+ -indicatoron 1 -width 8 \
+ -textvariable Apol_Perms_Map::opts(p:${class}:${perm}:map_label)]
+ set menu [menu $menubutton.m -type normal -tearoff 0]
+ $menubutton configure -menu $menu
+ $menu add radiobutton -label "Read" -value $::APOL_PERMMAP_READ \
+ -command [list Apol_Perms_Map::_togglePermMap $class $perm 1] \
+ -variable Apol_Perms_Map::opts(p:${class}:${perm}:map)
+ $menu add radiobutton -label "Write" -value $::APOL_PERMMAP_WRITE \
+ -command [list Apol_Perms_Map::_togglePermMap $class $perm 1] \
+ -variable Apol_Perms_Map::opts(p:${class}:${perm}:map)
+ $menu add radiobutton -label "Both" -value $::APOL_PERMMAP_BOTH \
+ -command [list Apol_Perms_Map::_togglePermMap $class $perm 1] \
+ -variable Apol_Perms_Map::opts(p:${class}:${perm}:map)
+ $menu add radiobutton -label "None" -value $::APOL_PERMMAP_NONE \
+ -command [list Apol_Perms_Map::_togglePermMap $class $perm 1] \
+ -variable Apol_Perms_Map::opts(p:${class}:${perm}:map)
+ set l2 [label $perms.$perm:l2 -text "Weight:" -anchor e]
+ set weight [spinbox $perms.$perm:weight -from 1 -to 10 -increment 1 \
+ -width 2 -bg white \
+ -command [list Apol_Perms_Map::_togglePermMap $class $perm 1] \
+ -textvariable Apol_Perms_Map::opts(p:${class}:${perm}:weight)]
+ grid $l $menubutton $l2 $weight -padx 2 -sticky w -pady 4
+ grid configure $l2 -ipadx 10
+ _togglePermMap $class $perm 0
+ }
+ grid columnconfigure $perms 0 -minsize 100 -weight 1
+ $widgets(perms) xview moveto 0
+ $widgets(perms) yview moveto 0
+}
+
+proc Apol_Perms_Map::_togglePermMap {class perm modification} {
+ variable opts
+ set map $opts(p:${class}:${perm}:map)
+ if {$map == $::APOL_PERMMAP_READ} {
+ set opts(p:${class}:${perm}:map_label) "Read"
+ } elseif {$map == $::APOL_PERMMAP_WRITE} {
+ set opts(p:${class}:${perm}:map_label) "Write"
+ } elseif {$map == $::APOL_PERMMAP_BOTH} {
+ set opts(p:${class}:${perm}:map_label) "Both"
+ } elseif {$map == $::APOL_PERMMAP_NONE} {
+ set opts(p:${class}:${perm}:map_label) "None"
+ } else {
+ set opts(p:${class}:${perm}:map_label) "Unmapped"
+ }
+ set opts(modified) $modification
+}
+
+proc Apol_Perms_Map::_toggleButtons {name1 name2 op} {
+ variable opts
+ variable dialog
+ if {$opts(modified)} {
+ $dialog itemconfigure 1 -state normal
+ } else {
+ $dialog itemconfigure 1 -state disabled
+ }
+}
+
+proc Apol_Perms_Map::_okay {} {
+ _apply
+ _close_dialog
+}
+
+proc Apol_Perms_Map::_apply {} {
+ variable dialog
+ variable opts
+
+ if {[winfo exists $dialog] && $opts(modified)} {
+ foreach class $opts(classes) {
+ set class [string trimright $class "*"]
+ set perm_list {}
+ foreach perm [Apol_Class_Perms::getPermsForClass $class] {
+ set map $opts(p:${class}:${perm}:map)
+ set weight $opts(p:${class}:${perm}:weight)
+ if {$map != $::APOL_PERMMAP_UNMAPPED} {
+ $::ApolTop::policy set_permmap $class $perm $map $weight
+ }
+ lappend perm_list [list $perm $map $weight]
+ }
+ # overwrite perm map values with applied values
+ set opts(c:$class) $perm_list
+ }
+ }
+ set opts(modified) 0
+}
+
+proc Apol_Perms_Map::_cancel {} {
+ variable opts
+
+ # revert the permission map to original values
+ if {$opts(modified)} {
+ foreach class $opts(classes) {
+ set class [string trimright $class "*"]
+ foreach perm $opts(c:$class) {
+ foreach {perm map weight} $perm {break}
+ $::ApolTop::policy set_permmap $class $perm $map $weight
+ }
+ }
+ }
+ _close_dialog
+}
+
+proc Apol_Perms_Map::_close_dialog {} {
+ variable opts
+ array unset opts c:*
+ array unset opts p:*
+ trace remove variable Apol_Perms_Map::opts(modified) write \
+ Apol_Perms_Map::_toggleButtons
+
+ variable dialog
+ destroy $dialog
+}
+
+proc Apol_Perms_Map::_savePermMap {filename shortname} {
+ variable opts
+ variable dialog
+
+ _apply
+ if {[catch {$::ApolTop::policy save_permmap $filename} err]} {
+ tk_messageBox -icon error -type ok -title "Permission Maps" -message "Error saving permission map: $err"
+ } else {
+ set opts(filename) $filename
+ set opts(shortname) $shortname
+ set opts(is_saveable) 1
+ set opts(modified) 0
+ set title "Permissions Mappings: $opts(shortname)"
+ if {[winfo exists $dialog]} {
+ $dialog configure -title $title
+ _refreshEditDialog
+ _refreshPermEdit
+ }
+ }
+}
diff --git a/apol/policyconf.tcl b/apol/policyconf.tcl
new file mode 100644
index 0000000..8f7e9c1
--- /dev/null
+++ b/apol/policyconf.tcl
@@ -0,0 +1,102 @@
+# Copyright (C) 2003-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
+
+namespace eval Apol_PolicyConf {
+ variable textbox
+}
+
+proc Apol_PolicyConf::create {tab_name nb} {
+ variable textbox
+
+ set frame [$nb insert end $tab_name -text "Policy Source"]
+ set sw [ScrolledWindow $frame.sw -auto none]
+ set textbox [text [$sw getframe].text -bg white -wrap none]
+ $sw setwidget $textbox
+ bind $textbox <Button-3> [list Apol_Widget::_searchresults_popup %W %x %y]
+ pack $sw -expand yes -fill both
+
+ bind $textbox <<Insertion>> Apol_PolicyConf::insertionMarkChanged
+
+ rename $textbox ::Apol_PolicyConf::_real_text
+
+ # Override the textbox's command to do two things:
+ #
+ # Deny normal insert and delete commands - but still show the
+ # insertion cursor. (Setting the state to disabled hides
+ # insertion cursor.) Use the 'fakeinsert' and 'fakedelete'
+ # commands to make changes.
+ #
+ # Unfortunately the Tk 8.4 text widget does not generate a virtual
+ # event whenever the insertion mark moves. Thus to simulate the
+ # behavior, override the mark command to generate the event
+ # <<Insertion>> after the mark changes.
+ proc ::$textbox {cmd args} {
+ switch -- $cmd {
+ insert -
+ delete { return }
+ fakeinsert { set cmd insert }
+ fakedelete { set cmd delete }
+ }
+ set retval [uplevel 1 ::Apol_PolicyConf::_real_text $cmd $args]
+ if {$cmd == "mark" && [string equal -length 10 $args "set insert"]} {
+ event generate $Apol_PolicyConf::textbox <<Insertion>>
+ }
+ return $retval
+ }
+}
+
+proc Apol_PolicyConf::open {ppath} {
+ variable textbox
+
+ $textbox fakedelete 0.0 end
+ if {![ApolTop::is_capable "source"]} {
+ $textbox fakeinsert end "The currently loaded policy is not a source policy."
+ } else {
+ set primary_file [$ppath get_primary]
+ if {[catch {::open $primary_file r} f]} {
+ $textbox fakeinsert end "$primary_file does not exist or could not be read by the user."
+ } else {
+ $textbox fakeinsert end [read $f]
+ ::close $f
+ }
+ }
+ $textbox see 0.0
+ $textbox mark set insert 1.0
+}
+
+proc Apol_PolicyConf::close {} {
+ variable textbox
+ $textbox fakedelete 0.0 end
+}
+
+proc Apol_PolicyConf::getTextWidget {} {
+ variable textbox
+ return $textbox
+}
+
+proc Apol_PolicyConf::insertionMarkChanged {} {
+ set lpos [$Apol_PolicyConf::textbox index insert]
+ foreach {line col} [split $lpos .] {break}
+ ApolTop::setPolicySourceLinenumber $line
+}
+
+proc Apol_PolicyConf::gotoLine {line} {
+ variable textbox
+ $textbox tag remove sel 0.0 end
+ $textbox mark set insert $line.0
+ $textbox see $line.0
+ $textbox tag add sel $line.0 $line.end
+ focus $textbox
+}
diff --git a/apol/progress_dialog.tcl b/apol/progress_dialog.tcl
new file mode 100644
index 0000000..2b44420
--- /dev/null
+++ b/apol/progress_dialog.tcl
@@ -0,0 +1,74 @@
+# Copyright (C) 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
+
+namespace eval Apol_Progress_Dialog {
+ variable text
+ variable prev_text
+ variable val
+ variable waiting 0
+}
+
+# Create a dialog to display messages while some library process is
+# running.
+proc Apol_Progress_Dialog::wait {title initialtext lambda} {
+ variable text "$title:\n $initialtext"
+ variable prev_text $initialtext
+ variable val -1
+
+ set title_width [string length $title]
+ set text_width [expr {[string length $initialtext] + 4}]
+ if {$text_width < $title_width} {
+ set text_width $title_width
+ }
+ if {$text_width < 32} {
+ set text_width 32
+ }
+
+ if {[info exists .apol_progress] == 0} {
+ ProgressDlg .apol_progress -title $title \
+ -type normal -stop {} -separator 1 -parent . -maximum 2 \
+ -width $text_width -textvariable Apol_Progress_Dialog::text \
+ -variable Apol_Progress_Dialog::val
+ }
+
+ set orig_cursor [. cget -cursor]
+ . configure -cursor watch
+ update idletasks
+
+ apol_tcl_clear_info_string
+ variable waiting 1
+ set catchval [catch {uplevel 1 $lambda} retval]
+ set waiting 0
+
+ . configure -cursor $orig_cursor
+ destroy .apol_progress
+ update idletasks
+ return -code $catchval $retval
+}
+
+proc Apol_Progress_Dialog::is_waiting {} {
+ variable waiting
+ set waiting
+}
+
+proc Apol_Progress_Dialog::_update_message {} {
+ variable text
+ variable prev_text
+ if {[set infoString [apol_tcl_get_info_string]] != $prev_text} {
+ set text "[lindex [split $text "\n"] 0]\n $infoString"
+ update idletasks
+ set prev_text $infoString
+ }
+}
diff --git a/apol/range_dialog.tcl b/apol/range_dialog.tcl
new file mode 100644
index 0000000..96457fb
--- /dev/null
+++ b/apol/range_dialog.tcl
@@ -0,0 +1,132 @@
+# Copyright (C) 2005-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
+
+namespace eval Apol_Range_Dialog {
+ variable dialog ""
+ variable vars
+}
+
+# Create a dialog box to allow the user to select an MLS range (either
+# a single level or two levels. Ensure that the selected range is
+# valid (i.e., high dominates low). If the range is invalid or if no
+# range is selected then return an empty list. Returns an instance of
+# an apol_mls_range_t; the caller must delete it afterwards.
+proc Apol_Range_Dialog::getRange {{defaultRange {}} {parent .}} {
+ variable dialog
+ variable vars
+ if {![winfo exists $dialog]} {
+ _create_dialog $parent
+ }
+ set f [$dialog getframe]
+ Apol_Widget::resetLevelSelectorToPolicy $f.low
+ Apol_Widget::resetLevelSelectorToPolicy $f.high
+ set vars($dialog:highenable) 0
+ if {$defaultRange != {}} {
+ set low_level [$defaultRange get_low]
+ set high_level [$defaultRange get_high]
+
+ Apol_Widget::setLevelSelectorLevel $f.low $low_level
+ if {[apol_mls_level_compare $::ApolTop::policy $low_level $high_level] != $::APOL_MLS_EQ} {
+ set vars($dialog:highenable) 1
+ Apol_Widget::setLevelSelectorLevel $f.high $high_level
+ }
+ }
+
+ _high_enabled $dialog
+ # force a recomputation of button sizes (bug in ButtonBox)
+ $dialog.bbox _redraw
+ set retval [$dialog draw]
+ if {$retval == -1 || $retval == 1} {
+ return {}
+ }
+ _get_range $dialog
+}
+
+
+########## private functions below ##########
+
+proc Apol_Range_Dialog::_create_dialog {parent} {
+ variable dialog
+ variable vars
+
+ set dialog [Dialog .range_dialog -modal local -parent $parent \
+ -separator 1 -homogeneous 1 -title "Select Range"]
+ array unset vars $dialog:*
+
+ set f [$dialog getframe]
+ set low_label [label $f.ll -text "Single level"]
+ set low_level [Apol_Widget::makeLevelSelector $f.low 12]
+
+ set high_cb [checkbutton $f.high_enable \
+ -text "High level" \
+ -variable Apol_Range_Dialog::vars($dialog:highenable) \
+ -command [list Apol_Range_Dialog::_high_enabled $dialog]]
+ set high_level [Apol_Widget::makeLevelSelector $f.high 12]
+ Apol_Widget::setLevelSelectorState $high_level 0
+
+ grid $low_label $high_cb -sticky w
+ grid $low_level $high_level -sticky ns
+ grid columnconfigure $f 0 -weight 1 -uniform 1 -pad 4
+ grid columnconfigure $f 1 -weight 1 -uniform 1 -pad 4
+
+ $dialog add -text "OK" -command [list Apol_Range_Dialog::_okay $dialog]
+ $dialog add -text "Cancel"
+}
+
+proc Apol_Range_Dialog::_get_range {dialog} {
+ variable vars
+ set f [$dialog getframe]
+ set range [new_apol_mls_range_t]
+
+ if {[ApolTop::is_policy_open]} {
+ set p $::ApolTop::policy
+ } else {
+ set p NULL
+ }
+
+ set low_level [Apol_Widget::getLevelSelectorLevel $f.low]
+ $range set_low $p $low_level
+
+ if {$vars($dialog:highenable)} {
+ set high_level [Apol_Widget::getLevelSelectorLevel $f.high]
+ $range set_high $p $high_level
+ }
+
+ return $range
+}
+
+proc Apol_Range_Dialog::_okay {dialog} {
+ set range [_get_range $dialog]
+ if {![ApolTop::is_policy_open] || [$range validate $::ApolTop::policy] != 1} {
+ tk_messageBox -icon error -type ok -title "Invalid Range" \
+ -message "The selected range is not valid. The high level does not dominate the low level."
+ } else {
+ $dialog enddialog 0
+ }
+ $range -acquire
+ $range -delete
+}
+
+proc Apol_Range_Dialog::_high_enabled {dialog} {
+ variable vars
+ set f [$dialog getframe]
+ if {$vars($dialog:highenable)} {
+ $f.ll configure -text "Low level"
+ Apol_Widget::setLevelSelectorState $f.high 1
+ } else {
+ $f.ll configure -text "Single level"
+ Apol_Widget::setLevelSelectorState $f.high 0
+ }
+}
diff --git a/apol/range_selector.tcl b/apol/range_selector.tcl
new file mode 100644
index 0000000..8234394
--- /dev/null
+++ b/apol/range_selector.tcl
@@ -0,0 +1,156 @@
+# Copyright (C) 2001-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
+
+namespace eval Apol_Widget {
+ variable vars
+}
+
+# Creates a widget that lets the user select an MLS range and a range
+# search type (exact, subset, superset). If the second argument is
+# not "" then add a checkbutton that enables/disables the entire
+# widget.
+proc Apol_Widget::makeRangeSelector {path rangeMatchText {enableText "MLS range"} args} {
+ variable vars
+ array unset vars $path:*
+ set vars($path:range) {}
+ set vars($path:range_rendered) {}
+ set vars($path:search_type) $::APOL_QUERY_EXACT
+
+ set f [frame $path]
+ set range_frame [frame $f.range]
+ set range2_frame [frame $f.range2]
+ pack $range_frame $range2_frame -side left -expand 0 -anchor nw
+
+ if {$enableText != {}} {
+ set vars($path:enable) 0
+ set range_cb [checkbutton $range_frame.enable -text $enableText \
+ -variable Apol_Widget::vars($path:enable)]
+ pack $range_cb -side top -expand 0 -anchor nw
+ trace add variable Apol_Widget::vars($path:enable) write [list Apol_Widget::_toggle_range_selector $path $range_cb]
+ }
+ set range_display [eval Entry $range_frame.display -textvariable Apol_Widget::vars($path:range_rendered) -width 20 -editable 0 $args]
+ set range_button [button $range_frame.button -text "Select Range..." -state disabled -command [list Apol_Widget::_show_mls_range_dialog $path]]
+ trace add variable Apol_Widget::vars($path:range) write [list Apol_Widget::_update_range_display $path]
+ pack $range_display -side top -expand 1 -fill x -anchor nw
+ pack $range_button -side top -expand 0 -anchor ne
+ if {$enableText != {}} {
+ pack configure $range_display -padx 4
+ pack configure $range_button -padx 4
+ }
+
+ # range search type
+ set range_label [label $range2_frame.label -text "Range matching:" \
+ -state disabled]
+ set range_exact [radiobutton $range2_frame.exact -text "Exact matches" \
+ -state disabled \
+ -value $::APOL_QUERY_EXACT \
+ -variable Apol_Widget::vars($path:search_type)]
+ set range_subset [radiobutton $range2_frame.subset -text "$rangeMatchText containing range" \
+ -state disabled \
+ -value $::APOL_QUERY_SUB \
+ -variable Apol_Widget::vars($path:search_type)]
+ set range_superset [radiobutton $range2_frame.superset -text "$rangeMatchText within range" \
+ -state disabled \
+ -value $::APOL_QUERY_SUPER \
+ -variable Apol_Widget::vars($path:search_type)]
+ pack $range_label $range_exact $range_subset $range_superset \
+ -side top -expand 0 -anchor nw
+
+ return $f
+}
+
+proc Apol_Widget::setRangeSelectorState {path newState} {
+ if {$newState == 0 || $newState == "disabled"} {
+ set new_state disabled
+ } else {
+ set new_state normal
+ }
+ foreach w {display button} {
+ $path.range.$w configure -state $new_state
+ }
+ foreach w {label exact subset superset} {
+ $path.range2.$w configure -state $new_state
+ }
+}
+
+proc Apol_Widget::setRangeSelectorCompleteState {path newState} {
+ if {$newState == 0 || $newState == "disabled"} {
+ set new_state disabled
+ } else {
+ set new_state normal
+ }
+ catch {$path.range.enable configure -state $new_state}
+}
+
+proc Apol_Widget::clearRangeSelector {path} {
+ set Apol_Widget::vars($path:range) {}
+ set Apol_Widget::vars($path:search_type) $::APOL_QUERY_EXACT
+ catch {set Apol_Widget::vars($path:enable) 0}
+}
+
+proc Apol_Widget::getRangeSelectorState {path} {
+ return $Apol_Widget::vars($path:enable)
+}
+
+# Return a 2-uple containing the range value (an instance of an
+# apol_mls_range_t) and the search type (one of APOL_QUERY_EXACT,
+# APOL_QUERY_SUB, or APOL_QUERY_SUPER). Caller must delete the range
+# afterwards. Note that the range could be an empty string if none is
+# set.
+proc Apol_Widget::getRangeSelectorValue {path} {
+ variable vars
+ if {$vars($path:range) != {}} {
+ set range [new_apol_mls_range_t $vars($path:range)]
+ } else {
+ set range {}
+ }
+ list $range $vars($path:search_type)
+}
+
+########## private functions below ##########
+
+proc Apol_Widget::_toggle_range_selector {path cb name1 name2 op} {
+ if {$Apol_Widget::vars($path:enable)} {
+ Apol_Widget::setRangeSelectorState $path normal
+ } else {
+ Apol_Widget::setRangeSelectorState $path disabled
+ }
+}
+
+proc Apol_Widget::_show_mls_range_dialog {path} {
+ $path.range.button configure -state disabled
+ set range [Apol_Range_Dialog::getRange $Apol_Widget::vars($path:range)]
+ if {$range != {}} {
+ set Apol_Widget::vars($path:range) $range
+ $range -acquire
+ }
+
+ $path.range.button configure -state normal
+ # the trace on this variable will trigger [_update_range_display]
+ # to execute
+}
+
+proc Apol_Widget::_update_range_display {path name1 name2 op} {
+ variable vars
+ set display $path.range.display
+ if {$vars($path:range) == {}} {
+ set vars($path:range_rendered) {}
+ $display configure -helptext {}
+ } else {
+ set s [$vars($path:range) render $::ApolTop::policy]
+ set vars($path:range_rendered) $s
+ $display configure -helptext $vars($path:range_rendered)
+ }
+}
diff --git a/apol/range_trans.tcl b/apol/range_trans.tcl
new file mode 100644
index 0000000..b35aca7
--- /dev/null
+++ b/apol/range_trans.tcl
@@ -0,0 +1,204 @@
+# Copyright (C) 2001-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
+
+namespace eval Apol_Range {
+ variable widgets
+ variable vals
+}
+
+proc Apol_Range::create {tab_name nb} {
+ variable widgets
+ variable vals
+
+ set frame [$nb insert end $tab_name -text "Range Transition Rules"]
+ set obox [TitleFrame $frame.obox -text "Search Options"]
+ set dbox [TitleFrame $frame.dbox -text "Range Transition Rules Display"]
+ pack $obox -fill x -expand 0 -padx 2 -pady 2
+ pack $dbox -fill both -expand yes -padx 2 -pady 2
+
+ set source_frame [frame [$obox getframe].source]
+ set target_frame [frame [$obox getframe].target]
+ set classes_frame [frame [$obox getframe].classes]
+ pack $source_frame $target_frame $classes_frame -side left -padx 4 -pady 2 -expand 0 -anchor nw
+
+ # source type
+ set vals(enable_source) 0
+ set source_cb [checkbutton $source_frame.cb -text "Source type" \
+ -variable Apol_Range::vals(enable_source)]
+ set widgets(source_type) [Apol_Widget::makeTypeCombobox $source_frame.tcb]
+ Apol_Widget::setTypeComboboxState $widgets(source_type) 0
+ trace add variable Apol_Range::vals(enable_source) write \
+ [list Apol_Range::_toggleTypeCombobox $widgets(source_type)]
+ pack $source_cb -side top -expand 0 -anchor nw
+ pack $widgets(source_type) -side top -expand 0 -anchor nw -padx 4
+
+ # target type
+ set vals(enable_target) 0
+ set target_cb [checkbutton $target_frame.cb -text "Target type" \
+ -variable Apol_Range::vals(enable_target)]
+ set widgets(target_type) [Apol_Widget::makeTypeCombobox $target_frame.tcb]
+ Apol_Widget::setTypeComboboxState $widgets(target_type) 0
+ trace add variable Apol_Range::vals(enable_target) write \
+ [list Apol_Range::_toggleTypeCombobox $widgets(target_type)]
+ pack $target_cb -side top -expand 0 -anchor nw
+ pack $widgets(target_type) -side top -expand 0 -anchor nw -padx 4
+
+ # object classes
+ set l [label $classes_frame.l -text "Target Classes"]
+ set sw [ScrolledWindow $classes_frame.sw -auto both]
+ set widgets(classes) [listbox [$sw getframe].lb -height 5 -width 24 \
+ -highlightthickness 0 -selectmode multiple \
+ -exportselection 0 -state disabled \
+ -bg $ApolTop::default_bg_color \
+ -listvar Apol_Range::vals(classes)]
+ $sw setwidget $widgets(classes)
+ update
+ grid propagate $sw 0
+ pack $l $sw -side top -expand 0 -anchor nw
+
+ set widgets(range) [Apol_Widget::makeRangeSelector [$obox getframe].range Rules]
+ pack $widgets(range) -side left -padx 4 -pady 2 -expand 0 -anchor nw
+
+ set ok [button [$obox getframe].ok -text "OK" -width 6 -command Apol_Range::_searchRanges]
+ pack $ok -side right -pady 5 -padx 5 -anchor ne
+
+ set widgets(results) [Apol_Widget::makeSearchResults [$dbox getframe].results]
+ pack $widgets(results) -expand yes -fill both
+
+ return $frame
+}
+
+proc Apol_Range::open {ppath} {
+ variable vals
+ variable widgets
+ Apol_Widget::resetTypeComboboxToPolicy $widgets(source_type)
+ Apol_Widget::resetTypeComboboxToPolicy $widgets(target_type)
+ set vals(classes) [Apol_Class_Perms::getClasses]
+ $widgets(classes) configure -bg white -state normal
+}
+
+proc Apol_Range::close {} {
+ variable vals
+ variable widgets
+ Apol_Widget::clearTypeCombobox $widgets(source_type)
+ Apol_Widget::clearTypeCombobox $widgets(target_type)
+ set vals(classes) {}
+ $widgets(classes) configure -bg $ApolTop::default_bg_color -state disabled
+ Apol_Widget::clearRangeSelector $widgets(range)
+ Apol_Widget::clearSearchResults $widgets(results)
+ set vals(enable_source) 0
+ set vals(enable_target) 0
+}
+
+proc Apol_Range::getTextWidget {} {
+ variable widgets
+ return $widgets(results).tb
+}
+
+#### private functions below ####
+
+proc Apol_Range::_toggleTypeCombobox {path name1 name2 op} {
+ Apol_Widget::setTypeComboboxState $path $Apol_Range::vals($name2)
+}
+
+proc Apol_Range::_searchRanges {} {
+ variable vals
+ variable widgets
+ Apol_Widget::clearSearchResults $widgets(results)
+ if {![ApolTop::is_policy_open]} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No current policy file is opened."
+ return
+ }
+
+ if {$vals(enable_source)} {
+ set source [lindex [Apol_Widget::getTypeComboboxValueAndAttrib $widgets(source_type)] 0]
+ if {$source == {}} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No source type provided."
+ return
+ }
+ } else {
+ set source {}
+ }
+ if {$vals(enable_target)} {
+ set target [lindex [Apol_Widget::getTypeComboboxValueAndAttrib $widgets(target_type)] 0]
+ if {$target == {}} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No target type provided."
+ return
+ }
+ } else {
+ set target {}
+ }
+ if {[Apol_Widget::getRangeSelectorState $widgets(range)]} {
+ foreach {range range_match} [Apol_Widget::getRangeSelectorValue $widgets(range)] break
+ if {$range == {}} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No range selected."
+ return
+ }
+ } else {
+ set range NULL
+ set range_match 0
+ }
+
+ set q [new_apol_range_trans_query_t]
+ $q set_source $::ApolTop::policy $source 0
+ $q set_target $::ApolTop::policy $target 0
+ foreach c [$widgets(classes) curselection] {
+ $q append_class $::ApolTop::policy [$widgets(classes) get $c]
+ }
+ $q set_range $::ApolTop::policy $range $range_match
+
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set results [range_trans_vector_to_list $v]
+ $v -acquire
+ $v -delete
+
+ if {[llength $results] == 0} {
+ set text "Search returned no results."
+ } else {
+ set text "[llength $results] rule"
+ if {[llength $results] != 1} {
+ append text s
+ }
+ append text " match the search criteria.\n\n"
+ }
+ foreach r [lsort -command _range_trans_sort $results] {
+ append text "[_renderRangeTrans $r]\n"
+ }
+ Apol_Widget::appendSearchResultText $widgets(results) $text
+}
+
+proc Apol_Range::_renderRangeTrans {rule} {
+ apol_range_trans_render $::ApolTop::policy $rule
+}
+
+proc Apol_Range::_range_trans_sort {a b} {
+ set t1 [[$a get_source_type $::ApolTop::qpolicy] get_name $::ApolTop::qpolicy]
+ set t2 [[$b get_source_type $::ApolTop::qpolicy] get_name $::ApolTop::qpolicy]
+ if {[set z [string compare $t1 $t2]] != 0} {
+ return $z
+ }
+
+ set t1 [[$a get_target_type $::ApolTop::qpolicy] get_name $::ApolTop::qpolicy]
+ set t2 [[$b get_target_type $::ApolTop::qpolicy] get_name $::ApolTop::qpolicy]
+ if {[set z [string compare $t1 $t2]] != 0} {
+ return $z
+ }
+
+ set c1 [[$a get_target_class $::ApolTop::qpolicy] get_name $::ApolTop::qpolicy]
+ set c2 [[$b get_target_class $::ApolTop::qpolicy] get_name $::ApolTop::qpolicy]
+ string compare $c1 $c2
+}
diff --git a/apol/rbac_tab.tcl b/apol/rbac_tab.tcl
new file mode 100644
index 0000000..2bc11c2
--- /dev/null
+++ b/apol/rbac_tab.tcl
@@ -0,0 +1,490 @@
+# Copyright (C) 2001-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
+
+namespace eval Apol_RBAC {
+ variable vals
+ variable widgets
+}
+
+proc Apol_RBAC::create {tab_name nb} {
+ variable vals
+ variable widgets
+
+ _initializeVars
+
+ set frame [$nb insert end $tab_name -text "RBAC Rules"]
+ set topf [frame $frame.top]
+ set bottomf [frame $frame.bottom]
+ pack $topf -expand 0 -fill both -pady 2
+ pack $bottomf -expand 1 -fill both -pady 2
+
+ set rsbox [TitleFrame $topf.rs -text "Rule Selection"]
+ set obox [TitleFrame $topf.opts -text "Search Options"]
+ set dbox [TitleFrame $bottomf.results -text "RBAC Rules Display"]
+ pack $rsbox -side left -expand 0 -fill both -padx 2
+ pack $obox -side left -expand 1 -fill both -padx 2
+ pack $dbox -expand 1 -fill both -padx 2
+
+ # Rule selection subframe
+ set rs [$rsbox getframe]
+ radiobutton $rs.allow -text allow -value allow \
+ -variable Apol_RBAC::vals(rule_selection)
+ radiobutton $rs.trans -text role_transition -value trans \
+ -variable Apol_RBAC::vals(rule_selection)
+ radiobutton $rs.both -text "allow and role_transition" -value both \
+ -variable Apol_RBAC::vals(rule_selection)
+ trace add variable Apol_RBAC::vals(rule_selection) write \
+ [list Apol_RBAC::_ruleChanged]
+ pack $rs.allow $rs.trans $rs.both -side top -anchor w
+
+ set widgets(options_pm) [PagesManager [$obox getframe].opts]
+
+ _allowCreate [$widgets(options_pm) add allow]
+ _transCreate [$widgets(options_pm) add trans]
+ _bothCreate [$widgets(options_pm) add both]
+ trace add variable Apol_RBAC::vals(source:which) write Apol_RBAC::_toggleRoleBox
+
+ $widgets(options_pm) compute_size
+ pack $widgets(options_pm) -expand 1 -fill both -side left
+ $widgets(options_pm) raise allow
+
+ set ok [button [$obox getframe].ok -text OK -width 6 -command Apol_RBAC::_searchRBACs]
+ pack $ok -side right -padx 5 -pady 5 -anchor ne
+
+ set widgets(results) [Apol_Widget::makeSearchResults [$dbox getframe].results]
+ pack $widgets(results) -expand yes -fill both
+
+ return $frame
+}
+
+proc Apol_RBAC::open {ppath} {
+ variable vals
+ variable widgets
+ $widgets(allow:source) configure -values $Apol_Roles::role_list
+ $widgets(allow:target) configure -values $Apol_Roles::role_list
+ $widgets(trans:source) configure -values $Apol_Roles::role_list
+ $widgets(trans:default) configure -values $Apol_Roles::role_list
+ $widgets(both:source) configure -values $Apol_Roles::role_list
+
+ # force a refresh of the types box for transitions
+ set vals(target_type:types) $vals(target_type:types)
+
+ # force a flip to the allow page
+ set vals(rule_selection) allow
+}
+
+proc Apol_RBAC::close {} {
+ variable widgets
+
+ _initializeVars
+ $widgets(allow:source) configure -values {}
+ $widgets(allow:target) configure -values {}
+ $widgets(trans:source) configure -values {}
+ $widgets(trans:target) configure -values {}
+ $widgets(trans:default) configure -values {}
+ $widgets(both:source) configure -values {}
+}
+
+proc Apol_RBAC::getTextWidget {} {
+ variable widgets
+ return $widgets(results).tb
+}
+
+#### private functions below ####
+
+proc Apol_RBAC::_initializeVars {} {
+ variable vals
+ array set vals {
+ rule_selection allow
+
+ source:use 0
+ source:sym {}
+ source:which source
+
+ target_role:use 0
+ target_role:sym {}
+ target_type:use 0
+ target_type:sym {}
+ target_type:types 1
+ target_type:attribs 0
+
+ default:use 0
+ default:sym {}
+ }
+}
+
+proc Apol_RBAC::_allowCreate {a_f} {
+ variable vals
+ variable widgets
+
+ set source [frame $a_f.source]
+ set source_cb [checkbutton $source.enable -text "Source role" \
+ -variable Apol_RBAC::vals(source:use)]
+ set widgets(allow:source) [ComboBox $source.cb -width 20 -state disabled \
+ -entrybg $ApolTop::default_bg_color \
+ -textvariable Apol_RBAC::vals(source:sym) \
+ -helptext "Type or select a role" -autopost 1]
+ set which_fm [frame $source.which]
+ set which_source [radiobutton $which_fm.source \
+ -text "As source" -state disabled \
+ -variable Apol_RBAC::vals(source:which) \
+ -value source]
+ set which_any [radiobutton $which_fm.any \
+ -text "As source or target" -state disabled \
+ -variable Apol_RBAC::vals(source:which) \
+ -value either]
+ trace add variable Apol_RBAC::vals(source:use) write \
+ [list Apol_RBAC::_toggleCheckbutton $widgets(allow:source) [list $which_source $which_any]]
+ pack $which_source $which_any -side top -anchor w
+ pack $source_cb -side top -anchor w
+ pack $widgets(allow:source) -side top -expand 0 -fill x -padx 4
+ pack $which_fm -anchor w -padx 8
+ pack $source -side left -padx 4 -pady 2 -expand 0 -anchor nw
+
+ set target [frame $a_f.target]
+ set widgets(allow:target_cb) [checkbutton $target.enable -text "Target role" \
+ -variable Apol_RBAC::vals(target_role:use)]
+ set widgets(allow:target) [ComboBox $target.cb -width 20 -state disabled \
+ -entrybg $ApolTop::default_bg_color \
+ -textvariable Apol_RBAC::vals(target_role:sym) \
+ -helptext "Type or select a role" -autopost 1]
+ trace add variable Apol_RBAC::vals(target_role:use) write \
+ [list Apol_RBAC::_toggleCheckbutton $widgets(allow:target) {}]
+ pack $widgets(allow:target_cb) -side top -anchor w
+ pack $widgets(allow:target) -side top -expand 0 -fill x -padx 4
+ pack $target -side left -padx 4 -pady 2 -expand 0 -fill y
+}
+
+proc Apol_RBAC::_transCreate {t_f} {
+ variable vals
+ variable widgets
+
+ set source [frame $t_f.source]
+ set source_cb [checkbutton $source.enable -text "Source role" \
+ -variable Apol_RBAC::vals(source:use)]
+ set widgets(trans:source) [ComboBox $source.cb -width 20 -state disabled \
+ -entrybg $ApolTop::default_bg_color \
+ -textvariable Apol_RBAC::vals(source:sym) \
+ -helptext "Type or select a role" -autopost 1]
+ set which_fm [frame $source.which]
+ set which_source [radiobutton $which_fm.source \
+ -text "As source" -state disabled \
+ -variable Apol_RBAC::vals(source:which) \
+ -value source]
+ set which_any [radiobutton $which_fm.any \
+ -text "As source or default" -state disabled \
+ -variable Apol_RBAC::vals(source:which) \
+ -value either]
+ trace add variable Apol_RBAC::vals(source:use) write \
+ [list Apol_RBAC::_toggleCheckbutton $widgets(trans:source) [list $which_source $which_any]]
+ pack $which_source $which_any -side top -anchor w
+ pack $source_cb -side top -anchor w
+ pack $widgets(trans:source) -side top -expand 0 -fill x -padx 4
+ pack $which_fm -anchor w -padx 8
+ pack $source -side left -padx 4 -pady 2 -expand 0 -anchor nw
+
+ set target [frame $t_f.target]
+ set target_cb [checkbutton $target.enable -text "Target type" \
+ -variable Apol_RBAC::vals(target_type:use)]
+ set widgets(trans:target) [ComboBox $target.cb -width 20 -state disabled \
+ -entrybg $ApolTop::default_bg_color \
+ -textvariable Apol_RBAC::vals(target_type:sym) \
+ -helptext "Type or select a type/attribute" -autopost 1]
+ set ta_frame [frame $target.ta]
+ set types [checkbutton $ta_frame.types -text "Types" -state disabled \
+ -variable Apol_RBAC::vals(target_type:types)]
+ set attribs [checkbutton $ta_frame.attribs -text "Attribs" -state disabled \
+ -variable Apol_RBAC::vals(target_type:attribs)]
+ $types configure -command [list Apol_RBAC::_toggleTAPushed $types]
+ $attribs configure -command [list Apol_RBAC::_toggleTAPushed $attribs]
+ trace add variable Apol_RBAC::vals(target_type:types) write \
+ [list Apol_RBAC::_toggleTASym]
+ trace add variable Apol_RBAC::vals(target_type:attribs) write \
+ [list Apol_RBAC::_toggleTASym]
+ pack $types $attribs -side left -padx 2
+ trace add variable Apol_RBAC::vals(target_type:use) write \
+ [list Apol_RBAC::_toggleCheckbutton $widgets(trans:target) [list $types $attribs]]
+ pack $target_cb -side top -anchor w
+ pack $widgets(trans:target) -side top -expand 0 -fill x -padx 4
+ pack $ta_frame -anchor center -pady 2
+ pack $target -side left -padx 4 -pady 2 -expand 0 -fill y
+
+ set default [frame $t_f.default]
+ set widgets(trans:default_cb) [checkbutton $default.enable -text "Default role" \
+ -variable Apol_RBAC::vals(default:use)]
+ set widgets(trans:default) [ComboBox $default.cb -width 20 -state disabled \
+ -entrybg $ApolTop::default_bg_color \
+ -textvariable Apol_RBAC::vals(default:sym) \
+ -helptext "Type or select a role" -autopost 1]
+ trace add variable Apol_RBAC::vals(default:use) write \
+ [list Apol_RBAC::_toggleCheckbutton $widgets(trans:default) {}]
+ pack $widgets(trans:default_cb) -side top -anchor w
+ pack $widgets(trans:default) -side top -expand 0 -fill x -padx 4
+ pack $default -side left -padx 4 -pady 2 -expand 0 -fill y
+}
+
+proc Apol_RBAC::_bothCreate {b_f} {
+ variable vals
+ variable widgets
+
+ set source [frame $b_f.source]
+ set source_cb [checkbutton $source.enable -text "Source role" \
+ -variable Apol_RBAC::vals(source:use)]
+ set widgets(both:source) [ComboBox $source.cb -width 20 -state disabled \
+ -entrybg $ApolTop::default_bg_color \
+ -textvariable Apol_RBAC::vals(source:sym) \
+ -helptext "Type or select a role" -autopost 1]
+ set which_fm [frame $source.which]
+ set which_source [radiobutton $which_fm.source \
+ -text "As source" -state disabled \
+ -variable Apol_RBAC::vals(source:which) \
+ -value source]
+ set which_any [radiobutton $which_fm.any \
+ -text "Any field" -state disabled \
+ -variable Apol_RBAC::vals(source:which) \
+ -value either]
+ trace add variable Apol_RBAC::vals(source:use) write \
+ [list Apol_RBAC::_toggleCheckbutton $widgets(both:source) [list $which_source $which_any]]
+ pack $which_source $which_any -side top -anchor w
+ pack $source_cb -side top -anchor w
+ pack $widgets(both:source) -side top -expand 0 -fill x -padx 4
+ pack $which_fm -anchor w -padx 8
+ pack $source -side left -padx 4 -pady 2 -expand 0 -anchor nw
+}
+
+proc Apol_RBAC::_toggleCheckbutton {cb w name1 name2 ops} {
+ variable vals
+
+ if {$vals($name2)} {
+ $cb configure -state normal -entrybg white
+ foreach x $w {
+ $x configure -state normal
+ }
+ } else {
+ $cb configure -state disabled -entrybg $ApolTop::default_bg_color
+ foreach x $w {
+ $x configure -state disabled
+ }
+ }
+
+ _maybeEnableTargetRole
+ _maybeEnableDefaultRole
+}
+
+# called whenever user selects 'as source'/'any' radio button
+proc Apol_RBAC::_toggleRoleBox {name1 name2 ops} {
+ _maybeEnableTargetRole
+ _maybeEnableDefaultRole
+}
+
+proc Apol_RBAC::_maybeEnableTargetRole {} {
+ variable vals
+ variable widgets
+ if {$vals(source:use) && $vals(source:which) == "either"} {
+ $widgets(allow:target_cb) configure -state disabled
+ $widgets(allow:target) configure -state disabled -entrybg $ApolTop::default_bg_color
+ } else {
+ $widgets(allow:target_cb) configure -state normal
+ # reset subwidgets' state
+ set vals(target_role:use) $vals(target_role:use)
+ }
+}
+
+proc Apol_RBAC::_maybeEnableDefaultRole {} {
+ variable vals
+ variable widgets
+ if {$vals(source:use) && $vals(source:which) == "either"} {
+ $widgets(trans:default_cb) configure -state disabled
+ $widgets(trans:default) configure -state disabled -entrybg $ApolTop::default_bg_color
+ } else {
+ $widgets(trans:default_cb) configure -state normal
+ # reset subwidgets' state
+ set vals(default:use) $vals(default:use)
+ }
+}
+
+proc Apol_RBAC::_toggleTASym {name1 name2 ops} {
+ variable vals
+ variable widgets
+
+ if {!$vals(target_type:types) && !$vals(target_type:attribs)} {
+ # don't change combobox if both types and attribs are deselected
+ return
+ }
+ if {$vals(target_type:types) && $vals(target_type:attribs)} {
+ set items [lsort [concat [Apol_Types::getTypes] [Apol_Types::getAttributes]]]
+ } elseif {$vals(target_type:types)} {
+ set items [Apol_Types::getTypes]
+ } else {
+ set items [Apol_Types::getAttributes]
+ }
+ $widgets(trans:target) configure -values $items
+}
+
+# disallow both types and attribs to be deselected
+proc Apol_RBAC::_toggleTAPushed {cb} {
+ variable vals
+ if {!$vals(target_type:types) && !$vals(target_type:attribs)} {
+ $cb select
+ }
+}
+
+# callback invoked when the user changes which RBAC rule to search
+proc Apol_RBAC::_ruleChanged {name1 name2 ops} {
+ variable vals
+ variable widgets
+ Apol_Widget::clearSearchResults $widgets(results)
+ $widgets(options_pm) raise $vals(rule_selection)
+}
+
+proc Apol_RBAC::_searchRBACs {} {
+ variable vals
+ variable widgets
+
+ Apol_Widget::clearSearchResults $widgets(results)
+ if {![ApolTop::is_policy_open]} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No current policy file is opened."
+ return
+ }
+
+ set raq {}
+ set rtq {}
+
+ if {$vals(rule_selection) == "allow" || $vals(rule_selection) == "both"} {
+ set raq [new_apol_role_allow_query_t]
+ }
+ if {$vals(rule_selection) == "trans" || $vals(rule_selection) == "both"} {
+ set rtq [new_apol_role_trans_query_t]
+ }
+
+ set source_sym {}
+ set is_any 0
+ if {$vals(source:use)} {
+ if {$vals(source:sym) == {}} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No source role selected."
+ return
+ }
+ if {$vals(source:which) == "either"} {
+ set is_any 1
+ }
+ set source_sym $vals(source:sym)
+ }
+
+ set target_role {}
+ set target_type {}
+ if {$vals(rule_selection) == "allow" && $vals(target_role:use) && \
+ (!$vals(source:use) || $vals(source:which) != "either")} {
+ if {$vals(target_role:sym) == {}} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No target role selected."
+ return
+ }
+ set target_role $vals(target_role:sym)
+ }
+ if {$vals(rule_selection) == "trans" && $vals(target_type:use)} {
+ if {$vals(target_type:sym) == {}} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No target type selected."
+ return
+ }
+ set target_type $vals(target_type:sym)
+ }
+
+ set default_role {}
+ if {$vals(rule_selection) == "trans" && $vals(default:use) && \
+ (!$vals(source:use) || $vals(source:which) != "either")} {
+ if {$vals(default:sym) == {}} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No default role selected."
+ return
+ }
+ set default_role $vals(default:sym)
+ }
+
+ set role_allows {}
+ if {$raq != {}} {
+ $raq set_source $::ApolTop::policy $source_sym
+ $raq set_source_any $::ApolTop::policy $is_any
+ $raq set_target $::ApolTop::policy $target_role
+ set v [$raq run $::ApolTop::policy]
+ $raq -acquire
+ $raq -delete
+ set role_allows [role_allow_vector_to_list $v]
+ $v -acquire
+ $v -delete
+ }
+
+ set role_trans {}
+ if {$rtq != {}} {
+ $rtq set_source $::ApolTop::policy $source_sym
+ $rtq set_source_any $::ApolTop::policy $is_any
+ $rtq set_target $::ApolTop::policy $target_type 0
+ $rtq set_default $::ApolTop::policy $default_role
+ set v [$rtq run $::ApolTop::policy]
+ $rtq -acquire
+ $rtq -delete
+ set role_trans [role_trans_vector_to_list $v]
+ $v -acquire
+ $v -delete
+ }
+
+ set num_results [expr {[llength $role_allows] + [llength $role_trans]}]
+ if {$num_results == 0} {
+ set text "Search returned no results."
+ } else {
+ set text "$num_results rule"
+ if {$num_results != 1} {
+ append text s
+ }
+ append text " match the search criteria.\n\n"
+ }
+
+ foreach r [lsort -command _role_allow_sort $role_allows] {
+ append text "[_render_role_allow $r]\n"
+ }
+ foreach r [lsort -command _role_trans_sort $role_trans] {
+ append text "[_render_role_trans $r]\n"
+ }
+ Apol_Widget::appendSearchResultText $widgets(results) $text
+}
+
+proc Apol_RBAC::_render_role_allow {qpol_role_allow_datum} {
+ apol_role_allow_render $::ApolTop::policy $qpol_role_allow_datum
+}
+
+proc Apol_RBAC::_render_role_trans {qpol_role_trans_datum} {
+ apol_role_trans_render $::ApolTop::policy $qpol_role_trans_datum
+}
+
+proc Apol_RBAC::_role_allow_sort {a b} {
+ set r1 [[$a get_source_role $::ApolTop::qpolicy] get_name $::ApolTop::qpolicy]
+ set r2 [[$b get_source_role $::ApolTop::qpolicy] get_name $::ApolTop::qpolicy]
+ if {[set z [string compare $r1 $r2]] != 0} {
+ return $z
+ }
+
+ set r1 [[$a get_target_role $::ApolTop::qpolicy] get_name $::ApolTop::qpolicy]
+ set r2 [[$b get_target_role $::ApolTop::qpolicy] get_name $::ApolTop::qpolicy]
+ string compare $r1 $r2
+}
+
+proc Apol_RBAC::_role_trans_sort {a b} {
+ set r1 [[$a get_source_role $::ApolTop::qpolicy] get_name $::ApolTop::qpolicy]
+ set r2 [[$b get_source_role $::ApolTop::qpolicy] get_name $::ApolTop::qpolicy]
+ if {[set z [string compare $r1 $r2]] != 0} {
+ return $z
+ }
+
+ set r1 [[$a get_target_type $::ApolTop::qpolicy] get_name $::ApolTop::qpolicy]
+ set r2 [[$b get_target_type $::ApolTop::qpolicy] get_name $::ApolTop::qpolicy]
+ string compare $r1 $r2
+}
diff --git a/apol/relabel_module.tcl b/apol/relabel_module.tcl
new file mode 100644
index 0000000..ddace64
--- /dev/null
+++ b/apol/relabel_module.tcl
@@ -0,0 +1,898 @@
+# Copyright (C) 2003-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
+
+namespace eval Apol_Analysis_relabel {
+ variable vals
+ variable widgets
+ Apol_Analysis::registerAnalysis "Apol_Analysis_relabel" "Direct Relabel"
+}
+
+proc Apol_Analysis_relabel::create {options_frame} {
+ variable vals
+ variable widgets
+
+ _reinitializeVals
+
+ set mode_tf [TitleFrame $options_frame.mode -text "Mode"]
+ pack $mode_tf -side left -padx 2 -pady 2 -expand 0 -fill y
+ set object_mode [radiobutton [$mode_tf getframe].object \
+ -text "Object" -value "object" \
+ -variable Apol_Analysis_relabel::vals(mode)]
+ pack $object_mode -anchor w
+ set widgets(mode:to) [checkbutton [$mode_tf getframe].to \
+ -text "To" \
+ -variable Apol_Analysis_relabel::vals(mode:to)]
+ $widgets(mode:to) configure -command \
+ [list Apol_Analysis_relabel::_toggleToFromPushed $widgets(mode:to)]
+ set widgets(mode:from) [checkbutton [$mode_tf getframe].from \
+ -text "From" \
+ -variable Apol_Analysis_relabel::vals(mode:from)]
+ $widgets(mode:from) configure -command \
+ [list Apol_Analysis_relabel::_toggleToFromPushed $widgets(mode:from)]
+ pack $widgets(mode:to) $widgets(mode:from) -anchor w -padx 8
+ set subject_mode [radiobutton [$mode_tf getframe].subject \
+ -text "Subject" -value "subject" \
+ -variable Apol_Analysis_relabel::vals(mode)]
+ pack $subject_mode -anchor w -pady 4
+ trace add variable Apol_Analysis_relabel::vals(mode) write \
+ Apol_Analysis_relabel::_toggleModeSelected
+
+ set req_tf [TitleFrame $options_frame.req -text "Required Parameters"]
+ pack $req_tf -side left -padx 2 -pady 2 -expand 0 -fill y
+ set l [label [$req_tf getframe].l -textvariable Apol_Analysis_relabel::vals(type:label)]
+ pack $l -anchor w
+ set widgets(type) [Apol_Widget::makeTypeCombobox [$req_tf getframe].type]
+ pack $widgets(type)
+
+ set filter_tf [TitleFrame $options_frame.filter -text "Optional Result Filters"]
+ pack $filter_tf -side left -padx 2 -pady 2 -expand 1 -fill both
+ set advanced_f [frame [$filter_tf getframe].advanced]
+ pack $advanced_f -side left -anchor nw
+ set access_enable [checkbutton $advanced_f.enable -text "Use advanced filters" \
+ -variable Apol_Analysis_relabel::vals(advanced_enable)]
+ pack $access_enable -anchor w
+ set widgets(advanced) [button $advanced_f.adv -text "Advanced Filters" \
+ -command Apol_Analysis_relabel::_createAdvancedDialog \
+ -state disabled]
+ pack $widgets(advanced) -anchor w -padx 4
+ trace add variable Apol_Analysis_relabel::vals(advanced_enable) write \
+ Apol_Analysis_relabel::_toggleAdvancedSelected
+ set widgets(regexp) [Apol_Widget::makeRegexpEntry [$filter_tf getframe].end]
+ $widgets(regexp).cb configure -text "Filter result types using regular expression"
+ pack $widgets(regexp) -side left -anchor nw -padx 8
+}
+
+proc Apol_Analysis_relabel::open {} {
+ variable vals
+ variable widgets
+ Apol_Widget::resetTypeComboboxToPolicy $widgets(type)
+ set vals(classes:inc) {}
+ foreach class [Apol_Class_Perms::getClasses] {
+ set perms [Apol_Class_Perms::getPermsForClass $class]
+ if {[lsearch $perms "relabelto"] >= 0 && [lsearch $perms "relabelfrom"] >= 0} {
+ lappend vals(classes:inc) $class
+ }
+ }
+ set vals(subjects:inc) [Apol_Types::getTypes]
+ set vals(subjects:inc_all) $vals(subjects:inc)
+}
+
+proc Apol_Analysis_relabel::close {} {
+ variable widgets
+ _reinitializeVals
+ _reinitializeWidgets
+ Apol_Widget::clearTypeCombobox $widgets(type)
+}
+
+proc Apol_Analysis_relabel::getInfo {} {
+ return "Direct relabel analysis is designed to facilitate querying a policy
+for both potential changes to object labels and relabel privileges
+granted to a subject. These two modes are respectively called Object
+Mode and Subject Mode.
+
+\nOBJECT MODE
+In object mode the user specifies a starting or ending type and either
+To, From, or Both. When To is selected all types to which the starting
+type can be relabeled will be displayed. When From is selected all
+types from which the ending type can be relabeled will be
+displayed. Both will, obviously, do both analyses.
+
+\nSUBJECT MODE
+In subject mode the user specifies only a subject type. Two lists of
+types will be displayed corresponding to all of the types To which the
+subject can relabel and From which the subject can relabel.
+
+\nOPTIONAL RESULT FILTERS
+Results may be filtered in several ways. The end types resulting from
+a query may be filtered by regular expression. The Advanced Filters
+provide the option of selecting which object classes to include in the
+analysis and which types to include as subjects of relabeling
+operations. Note, excluded subjects are ignored in subject mode
+because only the selected subject type is used as a subject."
+}
+
+proc Apol_Analysis_relabel::newAnalysis {} {
+ if {[set rt [_checkParams]] != {}} {
+ return $rt
+ }
+ set results [_analyze]
+ set f [_createResultsDisplay]
+ _renderResults $f $results
+ #results -acquire
+ $results -delete
+ return {}
+}
+
+proc Apol_Analysis_relabel::updateAnalysis {f} {
+ if {[set rt [_checkParams]] != {}} {
+ return $rt
+ }
+ set results [_analyze]
+ _clearResultsDisplay $f
+ _renderResults $f $results
+ $results -acquire
+ $results -delete
+ return {}
+}
+
+proc Apol_Analysis_relabel::reset {} {
+ _reinitializeVals
+ _reinitializeWidgets
+ open
+}
+
+proc Apol_Analysis_relabel::switchTab {query_options} {
+ variable vals
+ variable widgets
+ array set vals $query_options
+ _reinitializeWidgets
+}
+
+proc Apol_Analysis_relabel::saveQuery {channel} {
+ variable vals
+ variable widgets
+ foreach {key value} [array get vals] {
+ if {$key != "classes:inc" && \
+ $key != "subjects:inc_all" && $key != "subjects:inc" && \
+ $key != "subjects:exc"} {
+ puts $channel "$key $value"
+ }
+ }
+ set type [Apol_Widget::getTypeComboboxValueAndAttrib $widgets(type)]
+ puts $channel "type [lindex $type 0]"
+ puts $channel "type:attrib [lindex $type 1]"
+ set use_regexp [Apol_Widget::getRegexpEntryState $widgets(regexp)]
+ set regexp [Apol_Widget::getRegexpEntryValue $widgets(regexp)]
+ puts $channel "regexp:enable $use_regexp"
+ puts $channel "regexp $regexp"
+}
+
+proc Apol_Analysis_relabel::loadQuery {channel} {
+ variable vals
+
+ set classes_exc {}
+ set subjects_exc {}
+ while {[gets $channel line] >= 0} {
+ set line [string trim $line]
+ # Skip empty lines and comments
+ if {$line == {} || [string index $line 0] == "#"} {
+ continue
+ }
+ set key {}
+ set value {}
+ regexp -line -- {^(\S+)( (.+))?} $line -> key --> value
+ switch -- $key {
+ classes:exc {
+ set classes_exc $value
+ }
+ subjects:exc_all {
+ set subjects_exc $value
+ }
+ default {
+ set vals($key) $value
+ }
+ }
+ }
+
+ # fill in the exclusion lists using only classes/types found
+ # within the current policy
+ open
+
+ set vals(classes:exc) {}
+ foreach c $classes_exc {
+ set i [lsearch $vals(classes:inc) $c]
+ if {$i >= 0} {
+ lappend vals(classes:exc) $c
+ set vals(classes:inc) [lreplace $vals(classes:inc) $i $i]
+ }
+ }
+ set vals(classes:exc) [lsort $vals(classes:exc)]
+
+ set vals(subjects:exc_all) {}
+ set vals(subjects:exc) {}
+ foreach s $subjects_exc {
+ set i [lsearch $vals(subjects:inc_all) $s]
+ if {$i >= 0} {
+ lappend vals(subjects:exc_all) $s
+ lappend vals(subjects:exc) $s
+ set vals(subjects:inc_all) [lreplace $vals(subjects:inc_all) $i $i]
+ set i [lsearch $vals(subjects:inc) $s]
+ set vals(subjects:inc) [lreplace $vals(subjects:inc) $i $i]
+ }
+ }
+ set vals(subjects:exc_all) [lsort $vals(subjects:exc_all)]
+ set vals(subjects:exc) [lsort $vals(subjects:exc)]
+ _reinitializeWidgets
+}
+
+proc Apol_Analysis_relabel::getTextWidget {tab} {
+ return [$tab.right getframe].res.tb
+}
+
+#################### private functions below ####################
+
+proc Apol_Analysis_relabel::_reinitializeVals {} {
+ variable vals
+
+ array set vals {
+ mode object
+ mode:to 1
+ mode:from 0
+
+ type:label "Starting type"
+ type {} type:attrib {}
+
+ regexp:enable 0
+ regexp {}
+
+ advanced_enable 0
+ classes:inc {} classes:exc {}
+ subjects:inc {} subjects:inc_all {}
+ subjects:exc {} subjects:exc_all {}
+ subjects:attribenable 0 subjects:attrib {}
+ }
+}
+
+proc Apol_Analysis_relabel::_reinitializeWidgets {} {
+ variable vals
+ variable widgets
+
+ if {$vals(type:attrib) != {}} {
+ Apol_Widget::setTypeComboboxValue $widgets(type) [list $vals(type) $vals(type:attrib)]
+ } else {
+ Apol_Widget::setTypeComboboxValue $widgets(type) $vals(type)
+ }
+ Apol_Widget::setRegexpEntryValue $widgets(regexp) $vals(regexp:enable) $vals(regexp)
+ _updateTypeLabel
+}
+
+proc Apol_Analysis_relabel::_toggleModeSelected {name1 name2 op} {
+ variable vals
+ variable widgets
+ if {$vals(mode) == "object"} {
+ $widgets(mode:to) configure -state normal
+ $widgets(mode:from) configure -state normal
+ } else {
+ $widgets(mode:to) configure -state disabled
+ $widgets(mode:from) configure -state disabled
+ }
+ _updateTypeLabel
+}
+
+# disallow both to and from to be deselected
+proc Apol_Analysis_relabel::_toggleToFromPushed {cb} {
+ variable vals
+ if {!$vals(mode:to) && !$vals(mode:from)} {
+ $cb select
+ }
+ _updateTypeLabel
+}
+
+proc Apol_Analysis_relabel::_updateTypeLabel {} {
+ variable vals
+ if {$vals(mode) == "subject"} {
+ set vals(type:label) "Subject"
+ } elseif {$vals(mode:to) && $vals(mode:from)} {
+ set vals(type:label) "Starting/ending type"
+ } elseif {$vals(mode:from)} {
+ set vals(type:label) "Ending type"
+ } else {
+ set vals(type:label) "Starting type"
+ }
+}
+
+proc Apol_Analysis_relabel::_toggleAdvancedSelected {name1 name2 op} {
+ variable vals
+ variable widgets
+ if {$vals(advanced_enable)} {
+ $widgets(advanced) configure -state normal
+ } else {
+ $widgets(advanced) configure -state disabled
+ }
+}
+
+################# functions that do advanced filters #################
+
+proc Apol_Analysis_relabel::_createAdvancedDialog {} {
+ variable widgets
+ $widgets(advanced) configure -state disabled
+ destroy .relabel_analysis_adv
+ variable vals
+
+ set d [Dialog .relabel_analysis_adv -modal local -separator 1 -title "Direct Relabel Advanced Filters" -parent .]
+ $d add -text "Close"
+
+ set tf [TitleFrame [$d getframe].objs -text "Filter By Object Classes"]
+ pack $tf -side top -expand 1 -fill both -padx 2 -pady 4
+ _createAdvancedFilter [$tf getframe] "Object Classes" classes 0
+ set l [label [$tf getframe].l -text "Only showing object classes that have both 'relabelto' and 'relabelfrom' permissions."]
+ grid $l - - -padx 4 -pady 2
+
+ set tf [TitleFrame [$d getframe].types -text "Filter By Subject Types"]
+ pack $tf -side top -expand 1 -fill both -padx 2 -pady 4
+ if {$vals(mode) == "object"} {
+ _createAdvancedFilter [$tf getframe] "Subject Types" subjects 0
+ } else {
+ _createAdvancedFilter [$tf getframe] "Subject Types" subjects 1
+ }
+ set inc [$tf getframe].inc
+ set exc [$tf getframe].exc
+
+ set attrib [frame [$tf getframe].a]
+ grid $attrib - -
+ set attrib_enable [checkbutton $attrib.ae -anchor w \
+ -text "Filter by attribute" \
+ -variable Apol_Analysis_relabel::vals(subjects:attribenable)]
+ set attrib_box [ComboBox $attrib.ab -autopost 1 -entrybg white -width 16 \
+ -values $Apol_Types::attriblist \
+ -textvariable Apol_Analysis_relabel::vals(subjects:attrib)]
+ $attrib_enable configure -command \
+ [list Apol_Analysis_relabel::_attribEnabled $attrib_box]
+ # remove any old traces on the attribute
+ trace remove variable Apol_Analysis_relabel::vals(subjects:attrib) write \
+ [list Apol_Analysis_relabel::_attribChanged]
+ trace add variable Apol_Analysis_relabel::vals(subjects:attrib) write \
+ [list Apol_Analysis_relabel::_attribChanged]
+ pack $attrib_enable -side top -expand 0 -fill x -anchor sw -padx 5 -pady 2
+ pack $attrib_box -side top -expand 1 -fill x -padx 10
+ _attribEnabled $attrib_box
+ if {$vals(mode) == "subject"} {
+ $attrib_enable configure -state disabled
+ $attrib_box configure -state disabled
+ }
+
+ $d draw
+ $widgets(advanced) configure -state normal
+}
+
+proc Apol_Analysis_relabel::_createAdvancedFilter {f title varname disabled} {
+ set l1 [label $f.l1 -text "Included $title"]
+ set l2 [label $f.l2 -text "Excluded $title"]
+ grid $l1 x $l2 -sticky w
+
+ set inc [Apol_Widget::makeScrolledListbox $f.inc -height 10 -width 24 \
+ -listvar Apol_Analysis_relabel::vals($varname:inc) \
+ -selectmode extended -exportselection 0]
+ set exc [Apol_Widget::makeScrolledListbox $f.exc -height 10 -width 24 \
+ -listvar Apol_Analysis_relabel::vals($varname:exc) \
+ -selectmode extended -exportselection 0]
+ set inc_lb [Apol_Widget::getScrolledListbox $inc]
+ set exc_lb [Apol_Widget::getScrolledListbox $exc]
+ set bb [ButtonBox $f.bb -homogeneous 1 -orient vertical -spacing 4]
+ $bb add -text "-->" -width 10 -command [list Apol_Analysis_relabel::_moveToExclude $varname $inc_lb $exc_lb]
+ $bb add -text "<--" -width 10 -command [list Apol_Analysis_relabel::_moveToInclude $varname $inc_lb $exc_lb]
+ grid $inc $bb $exc -sticky nsew
+
+ set inc_bb [ButtonBox $f.inc_bb -homogeneous 1 -spacing 4]
+ $inc_bb add -text "Select All" -command [list $inc_lb selection set 0 end]
+ $inc_bb add -text "Unselect" -command [list $inc_lb selection clear 0 end]
+ set exc_bb [ButtonBox $f.exc_bb -homogeneous 1 -spacing 4]
+ $exc_bb add -text "Select All" -command [list $exc_lb selection set 0 end]
+ $exc_bb add -text "Unselect" -command [list $exc_lb selection clear 0 end]
+ grid $inc_bb x $exc_bb -pady 4
+
+ grid columnconfigure $f 0 -weight 1 -uniform 0 -pad 2
+ grid columnconfigure $f 1 -weight 0 -pad 8
+ grid columnconfigure $f 2 -weight 1 -uniform 0 -pad 2
+
+ if {$disabled} {
+ foreach w [list $l1 $l2 $bb $inc_bb $exc_bb] {
+ $w configure -state disabled
+ }
+ Apol_Widget::setScrolledListboxState $inc disabled
+ Apol_Widget::setScrolledListboxState $exc disabled
+ }
+}
+
+proc Apol_Analysis_relabel::_moveToExclude {varname inc exc} {
+ variable vals
+ if {[set selection [$inc curselection]] == {}} {
+ return
+ }
+ foreach i $selection {
+ lappend perms [$inc get $i]
+ }
+ set vals($varname:exc) [lsort [concat $vals($varname:exc) $perms]]
+ if {$varname == "subjects"} {
+ set vals(subjects:exc_all) [lsort [concat $vals(subjects:exc_all) $perms]]
+ }
+ foreach p $perms {
+ set i [lsearch $vals($varname:inc) $p]
+ set vals($varname:inc) [lreplace $vals($varname:inc) $i $i]
+ if {$varname == "subjects"} {
+ set i [lsearch $vals(subjects:inc_all) $p]
+ set vals(subjects:inc_all) [lreplace $vals(subjects:inc_all) $i $i]
+ }
+ }
+ $inc selection clear 0 end
+ $exc selection clear 0 end
+}
+
+proc Apol_Analysis_relabel::_moveToInclude {varname inc exc} {
+ variable vals
+ if {[set selection [$exc curselection]] == {}} {
+ return
+ }
+ foreach i $selection {
+ lappend perms [$exc get $i]
+ }
+ set vals($varname:inc) [lsort [concat $vals($varname:inc) $perms]]
+ if {$varname == "subjects"} {
+ set vals(subjects:inc_all) [lsort [concat $vals(subjects:inc_all) $perms]]
+ }
+ foreach p $perms {
+ set i [lsearch $vals($varname:exc) $p]
+ set vals($varname:exc) [lreplace $vals($varname:exc) $i $i]
+ if {$varname == "subjects"} {
+ set i [lsearch $vals(subjects:exc_all) $p]
+ set vals(subjects:exc_all) [lreplace $vals(subjects:exc_all) $i $i]
+ }
+ }
+ $inc selection clear 0 end
+ $exc selection clear 0 end
+}
+
+proc Apol_Analysis_relabel::_attribEnabled {cb} {
+ variable vals
+ if {$vals(subjects:attribenable)} {
+ $cb configure -state normal
+ _filterTypeLists $vals(subjects:attrib)
+ } else {
+ $cb configure -state disabled
+ _filterTypeLists ""
+ }
+}
+
+proc Apol_Analysis_relabel::_attribChanged {name1 name2 op} {
+ variable vals
+ if {$vals(subjects:attribenable)} {
+ _filterTypeLists $vals(subjects:attrib)
+ }
+}
+
+proc Apol_Analysis_relabel::_filterTypeLists {attrib} {
+ variable vals
+ if {$attrib != {}} {
+ set typesList {}
+ if {[Apol_Types::isAttributeInPolicy $attrib]} {
+ set qpol_type_datum [new_qpol_type_t $::ApolTop::qpolicy $attrib]
+ set i [$qpol_type_datum get_type_iter $::ApolTop::qpolicy]
+ foreach t [iter_to_list $i] {
+ set t [qpol_type_from_void $t]
+ lappend typesList [$t get_name $::ApolTop::qpolicy]
+ }
+ $i -acquire
+ $i -delete
+ }
+ if {$typesList == {}} {
+ # unknown attribute, so don't change listboxes
+ return
+ }
+ set vals(subjects:inc) {}
+ set vals(subjects:exc) {}
+ foreach t $typesList {
+ if {[lsearch $vals(subjects:inc_all) $t] >= 0} {
+ lappend vals(subjects:inc) $t
+ }
+ if {[lsearch $vals(subjects:exc_all) $t] >= 0} {
+ lappend vals(subjects:exc) $t
+ }
+ }
+ set vals(subjects:inc) [lsort $vals(subjects:inc)]
+ set vals(subjects:exc) [lsort $vals(subjects:exc)]
+ } else {
+ set vals(subjects:inc) $vals(subjects:inc_all)
+ set vals(subjects:exc) $vals(subjects:exc_all)
+ }
+}
+
+#################### functions that do analyses ####################
+
+proc Apol_Analysis_relabel::_checkParams {} {
+ variable vals
+ variable widgets
+ if {![ApolTop::is_policy_open]} {
+ return "No current policy file is opened."
+ }
+ set type [Apol_Widget::getTypeComboboxValueAndAttrib $widgets(type)]
+ if {[lindex $type 0] == {}} {
+ return "No type was selected."
+ }
+ if {![Apol_Types::isTypeInPolicy [lindex $type 0]]} {
+ return "[lindex $type 0] is not a type within the policy."
+ }
+ set vals(type) [lindex $type 0]
+ set vals(type:attrib) [lindex $type 1]
+ set use_regexp [Apol_Widget::getRegexpEntryState $widgets(regexp)]
+ set regexp [Apol_Widget::getRegexpEntryValue $widgets(regexp)]
+ if {$use_regexp && $regexp == {}} {
+ return "No regular expression provided."
+ }
+ set vals(regexp:enable) $use_regexp
+ set vals(regexp) $regexp
+ if {$vals(advanced_enable)} {
+ if {$vals(classes:inc) == {}} {
+ return "At least one object class must be included."
+ }
+ if {$vals(mode) == "object" && $vals(subjects:inc_all) == {}} {
+ return "At least one subject type must be included."
+ }
+ }
+ return {} ;# all parameters passed, now ready to do search
+}
+
+proc Apol_Analysis_relabel::_analyze {} {
+ variable vals
+ if {$vals(mode) == "object"} {
+ if {$vals(mode:to) && $vals(mode:from)} {
+ set mode $::APOL_RELABEL_DIR_BOTH
+ } elseif {$vals(mode:to)} {
+ set mode $::APOL_RELABEL_DIR_TO
+ } else {
+ set mode $::APOL_RELABEL_DIR_FROM
+ }
+ } else {
+ set mode $::APOL_RELABEL_DIR_SUBJECT
+ }
+ if {$vals(advanced_enable) && $vals(classes:exc) != {}} {
+ set classes $vals(classes:inc)
+ } else {
+ set classes {}
+ }
+ if {$vals(advanced_enable) && $vals(subjects:exc) != {}} {
+ set subjects $vals(subjects:inc)
+ } else {
+ set subjects {}
+ }
+ if {$vals(regexp:enable)} {
+ set regexp $vals(regexp)
+ } else {
+ set regexp {}
+ }
+
+ set q [new_apol_relabel_analysis_t]
+ $q set_dir $::ApolTop::policy $mode
+ $q set_type $::ApolTop::policy $vals(type)
+ foreach c $classes {
+ $q append_class $::ApolTop::policy $c
+ }
+ foreach s $subjects {
+ $q append_subject $::ApolTop::policy $s
+ }
+ $q set_result_regex $::ApolTop::policy $regexp
+ set results [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ return $results
+}
+
+################# functions that control analysis output #################
+
+proc Apol_Analysis_relabel::_createResultsDisplay {} {
+ variable vals
+
+ set f [Apol_Analysis::createResultTab "Relabel" [array get vals]]
+
+ if {$vals(mode) == "object"} {
+ if {$vals(mode:to) && $vals(mode:from)} {
+ set tree_title "Type $vals(type) relabels to/from"
+ } elseif {$vals(mode:to)} {
+ set tree_title "Type $vals(type) relabels to"
+ } else {
+ set tree_title "Type $vals(type) relabels from"
+ }
+ } else {
+ set tree_title "Subject $vals(type) relabels"
+ }
+ set tree_tf [TitleFrame $f.left -text $tree_title]
+ pack $tree_tf -side left -expand 0 -fill y -padx 2 -pady 2
+ set sw [ScrolledWindow [$tree_tf getframe].sw -auto both]
+ set tree [Tree [$sw getframe].tree -width 24 -redraw 1 -borderwidth 0 \
+ -highlightthickness 0 -showlines 1 -padx 0 -bg white]
+ $sw setwidget $tree
+ pack $sw -expand 1 -fill both
+
+ set res_tf [TitleFrame $f.right -text "Relabeling Results"]
+ pack $res_tf -side left -expand 1 -fill both -padx 2 -pady 2
+ set res [Apol_Widget::makeSearchResults [$res_tf getframe].res]
+ $res.tb tag configure title -font {Helvetica 14 bold}
+ $res.tb tag configure title_type -foreground blue -font {Helvetica 14 bold}
+ $res.tb tag configure num -font {Helvetica 12 bold}
+ $res.tb tag configure type_tag -foreground blue -font {Helvetica 12 bold}
+ pack $res -expand 1 -fill both
+
+ $tree configure -selectcommand [list Apol_Analysis_relabel::_treeSelect $res]
+ return $f
+}
+
+proc Apol_Analysis_relabel::_treeSelect {res tree node} {
+ if {$node != {}} {
+ $res.tb configure -state normal
+ $res.tb delete 0.0 end
+ set data [$tree itemcget $node -data]
+ if {[string index $node 0] == "o"} {
+ _renderResultsRuleObject $res $tree $node $data
+ } elseif {[string index $node 0] == "s"} {
+ _renderResultsRuleSubject $res $tree $node $data
+ } else {
+ # an informational node, whose data has already been rendered
+ eval $res.tb insert end $data
+ }
+ $res.tb configure -state disabled
+ }
+}
+
+proc Apol_Analysis_relabel::_clearResultsDisplay {f} {
+ variable vals
+
+ set tree [[$f.left getframe].sw getframe].tree
+ set res [$f.right getframe].res
+ $tree delete [$tree nodes root]
+ Apol_Widget::clearSearchResults $res
+ Apol_Analysis::setResultTabCriteria [array get vals]
+}
+
+proc Apol_Analysis_relabel::_renderResults {f results} {
+ variable vals
+
+ set tree [[$f.left getframe].sw getframe].tree
+ set res [$f.right getframe].res
+
+ $tree insert end root top -text $vals(type) -open 1 -drawcross auto
+ if {$vals(mode) == "object"} {
+ set top_text [_renderResultsObject $results $tree]
+ } else { ;# subject mode
+ set top_text [_renderResultsSubject $results $tree]
+ }
+ $tree itemconfigure top -data $top_text
+ $tree selection set top
+ $tree opentree top
+ $tree see top
+}
+
+proc Apol_Analysis_relabel::_result_type_sort {a b} {
+ set t1 [[$a get_result_type] get_name $::ApolTop::qpolicy]
+ set t2 [[$b get_result_type] get_name $::ApolTop::qpolicy]
+ string compare $t1 $t2
+}
+
+proc Apol_Analysis_relabel::_renderResultsObject {results tree} {
+ variable vals
+ if {$vals(mode:from) && $vals(mode:to)} {
+ set dir both
+ } elseif {$vals(mode:to)} {
+ set dir to
+ } else {
+ set dir from
+ }
+
+ foreach r [lsort -command _result_type_sort [relabel_result_vector_to_list $results]] {
+ set type [[$r get_result_type] get_name $::ApolTop::qpolicy]
+ set to [relabel_result_pair_vector_to_list [$r get_to]]
+ set from [relabel_result_pair_vector_to_list [$r get_from]]
+ set both [relabel_result_pair_vector_to_list [$r get_both]]
+ set pairs {}
+ foreach pair [concat $to $from $both] {
+ set intermed [[$pair get_intermediate_type] get_name $::ApolTop::qpolicy]
+ lappend pairs [list [$pair get_ruleA] [$pair get_ruleB] $intermed]
+ }
+ set pairs [lsort -unique $pairs]
+ $tree insert end top o:$dir:\#auto -text $type -data $pairs
+ }
+
+ set top_text [list "Direct Relabel Analysis: " title]
+ switch -- $dir {
+ both { lappend top_text "Starting/Ending Type: " title }
+ to { lappend top_text "Ending Type: " title }
+ from { lappend top_text "Starting Type: " title }
+ }
+ lappend top_text $vals(type) title_type \
+ "\n\n" title \
+ $vals(type) type_tag
+ if {[$results get_size]} {
+ switch -- $dir {
+ both { lappend top_text " can be relabeled to and from " {} }
+ to { lappend top_text " can be relabeled to " {} }
+ from { lappend top_text " can be relabeled from " {} }
+ }
+ lappend top_text [$results get_size] num \
+ " type(s).\n\n" {} \
+ "This tab provides the results of a Direct Relabel Analysis beginning\n" {}
+ switch -- $dir {
+ both { lappend top_text "with the starting/ending" {} }
+ to { lappend top_text "with the starting" {} }
+ from { lappend top_text "with the ending" {} }
+ }
+ lappend top_text " type above. The results of the analysis are\n" {} \
+ "presented in tree form with the root of the tree (this node) being the\n" {} \
+ "starting point for the analysis.\n\n" {} \
+ "Each child node in the tree represents a type in the current policy\n" {} \
+ "to/from which relabeling is allowed (depending on you selection\n" {} \
+ "above)." {}
+ } else {
+ switch -- $dir {
+ both { lappend top_text " cannot be relabeled to/from any type." {} }
+ to { lappend top_text " cannot be relabeled to any type." {} }
+ from { lappend top_text " cannot be relabeled from any type." {} }
+ }
+ }
+}
+
+proc Apol_Analysis_relabel::_renderResultsRuleObject {res tree node data} {
+ set header [list [$tree itemcget top -text] title_type]
+ lappend header " can be relabeled:\n" {}
+ eval $res.tb insert end $header
+
+ set dir [lindex [split $node :] 1]
+ set target_type [$tree itemcget $node -text]
+ foreach rule_pairs $data {
+ set class [[[lindex $rule_pairs 0] get_object_class $::ApolTop::qpolicy] get_name $::ApolTop::qpolicy]
+ lappend classes($class) $rule_pairs
+ }
+
+ foreach key [lsort [array names classes]] {
+ $res.tb configure -state normal
+ $res.tb insert end "\n$key:\n" title
+ foreach rule_pairs [lsort -index 2 $classes($key)] {
+ foreach {a_rule b_rule intermed} $rule_pairs {break}
+
+ # determine direction of relabelling
+ if {$dir == "to" || $dir == "from"} {
+ set dir_string $dir
+ } else {
+ set i [$a_rule get_perm_iter $::ApolTop::qpolicy]
+ set a_perms [iter_to_str_list $i]
+ $i -acquire
+ $i -delete
+ set i [$b_rule get_perm_iter $::ApolTop::qpolicy]
+ set b_perms [iter_to_str_list $i]
+ $i -acquire
+ $i -delete
+
+ if {[lsearch $a_perms "relabelto"] >= 0 && \
+ [lsearch $a_perms "relabelfrom"] >= 0 && \
+ [lsearch $b_perms "relabelto"] >= 0 && \
+ [lsearch $b_perms "relabelfrom"] >= 0} {
+ set dir_string "to and from"
+ } elseif {[lsearch $a_perms "relabelto"] >= 0 &&
+ [lsearch $b_perms "relabelfrom"] >= 0} {
+ set dir_string "to"
+ } else {
+ set dir_string "from"
+ }
+ }
+
+ $res.tb configure -state normal
+ $res.tb insert end "\n $dir_string " num \
+ $target_type type_tag \
+ " by " {} \
+ $intermed type_tag \
+ "\n" {}
+
+ set v [new_apol_vector_t]
+ $v append $a_rule
+ Apol_Widget::appendSearchResultRules $res 6 $v qpol_avrule_from_void
+ $v -acquire
+ $v -delete
+ if {$a_rule != $b_rule} {
+ set v [new_apol_vector_t]
+ $v append $b_rule
+ Apol_Widget::appendSearchResultRules $res 6 $v qpol_avrule_from_void
+ $v -acquire
+ $v -delete
+ }
+ }
+ }
+}
+
+proc Apol_Analysis_relabel::_renderResultsSubject {results tree} {
+ variable vals
+ set to_count 0
+ set from_count 0
+
+ foreach r [relabel_result_vector_to_list $results] {
+ set type [[$r get_result_type] get_name $::ApolTop::qpolicy]
+ set to [relabel_result_pair_vector_to_list [$r get_to]]
+ set from [relabel_result_pair_vector_to_list [$r get_from]]
+ set both [relabel_result_pair_vector_to_list [$r get_both]]
+
+ foreach pair [concat $to $both] {
+ lappend to_types($type) [$pair get_ruleA]
+ }
+ foreach pair [concat $from $both] {
+ lappend from_types($type) [$pair get_ruleA]
+ }
+
+ }
+
+ set to_count [llength [array names to_types]]
+ if {$to_count} {
+ set to_text [list $vals(type) title_type " can relabel to " {} ]
+ lappend to_text $to_count num \
+ " type(s). Open the subtree of this item to view the list of types." {}
+ $tree insert end top to -text "To" -data $to_text -drawcross auto
+ foreach type [lsort [array names to_types]] {
+ set rules [lsort -unique $to_types($type)]
+ $tree insert end to s\#auto -text $type -data [list to $rules]
+ }
+ }
+ set from_count [llength [array names from_types]]
+ if {$from_count} {
+ set from_text [list $vals(type) title_type " can relabel from " {} ]
+ lappend from_text $from_count num \
+ " type(s). Open the subtree of this item to view the list of types." {}
+ $tree insert end top from -text "From" -data $from_text -drawcross auto
+ foreach type [lsort [array names from_types]] {
+ set rules [lsort -unique $from_types($type)]
+ $tree insert end from s\#auto -text $type -data [list from $rules]
+ }
+ }
+
+ set top_text [list "Direct Relabel Analysis: Subject: " title]
+ lappend top_text $vals(type) title_type \
+ "\n\n" title \
+ $vals(type) type_tag
+ if {$to_count + $from_count} {
+ lappend top_text " can relabel to " {} \
+ $to_count num \
+ " type(s) and relabel from " {} \
+ $from_count num \
+ " type(s).\n\n" {} \
+ "This tab provides the results of a Direct Relabel Analysis for the\n" {} \
+ "subject above. The results of the analysis are presented in tree form\n" {} \
+ "with the root of the tree (this node) being the starting point for the\n" {} \
+ "analysis.\n\n" {} \
+ "Each child node in the To and From subtrees represents a type in the\n" {} \
+ "current policy which the chosen subject can relabel." {}
+ } else {
+ lappend top_text " does not relabel to or from any type as a subject." {}
+ }
+}
+
+proc Apol_Analysis_relabel::_renderResultsRuleSubject {res tree node data} {
+ foreach {dir rules} $data {break}
+ set header [list [$tree itemcget top -text] title_type]
+ lappend header " can relabel $dir " {} \
+ [$tree itemcget $node -text] title_type \
+ "\n\n" {}
+ eval $res.tb insert end $header
+ set v [new_apol_vector_t]
+ foreach r $rules {
+ $v append $r
+ }
+ Apol_Widget::appendSearchResultRules $res 0 $v qpol_avrule_from_void
+ $v -acquire
+ $v -delete
+}
diff --git a/apol/roles_tab.tcl b/apol/roles_tab.tcl
new file mode 100644
index 0000000..4d8339a
--- /dev/null
+++ b/apol/roles_tab.tcl
@@ -0,0 +1,196 @@
+# Copyright (C) 2001-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
+
+namespace eval Apol_Roles {
+ variable widgets
+ variable opts
+ variable role_list {}
+}
+
+proc Apol_Roles::create {tab_name nb} {
+ variable widgets
+ variable opts
+
+ _initializeVars
+
+ set frame [$nb insert end $tab_name -text "Roles"]
+ set pw [PanedWindow $frame.pw -side top]
+ set leftf [$pw add -weight 0]
+ set rightf [$pw add -weight 1]
+ pack $pw -fill both -expand yes
+
+ set rolebox [TitleFrame $leftf.rolebox -text "Roles"]
+ set s_optionsbox [TitleFrame $rightf.obox -text "Search Options"]
+ set resultsbox [TitleFrame $rightf.rbox -text "Search Results"]
+ pack $rolebox -fill both -expand yes
+ pack $s_optionsbox -padx 2 -fill both -expand 0
+ pack $resultsbox -padx 2 -fill both -expand yes
+
+ set rlistbox [Apol_Widget::makeScrolledListbox [$rolebox getframe].lb \
+ -width 20 -listvar Apol_Roles::role_list]
+ Apol_Widget::setListboxCallbacks $rlistbox \
+ {{"Display Role Info" {Apol_Roles::_popupRoleInfo role}}}
+ pack $rlistbox -fill both -expand yes
+
+ # Search options subframes
+ set ofm [$s_optionsbox getframe]
+ set lfm [frame $ofm.to]
+ set cfm [frame $ofm.co]
+ pack $lfm $cfm -side left -anchor nw -padx 4 -pady 2
+
+ radiobutton $lfm.all_info -text "All information" \
+ -variable Apol_Roles::opts(showSelection) -value all
+ radiobutton $lfm.names_only -text "Names only" \
+ -variable Apol_Roles::opts(showSelection) -value names
+ pack $lfm.all_info $lfm.names_only -anchor w -padx 5 -pady 4
+
+ set cb_type [checkbutton $cfm.cb -variable Apol_Roles::opts(useType) -text "Type"]
+ set widgets(combo_types) [Apol_Widget::makeTypeCombobox $cfm.combo_types]
+ Apol_Widget::setTypeComboboxState $widgets(combo_types) disabled
+ trace add variable Apol_Roles::opts(useType) write \
+ [list Apol_Roles::_toggleTypeCombobox $widgets(combo_types)]
+ pack $cb_type -anchor w
+ pack $widgets(combo_types) -anchor w -padx 4
+
+ button $ofm.ok -text OK -width 6 -command Apol_Roles::_searchRoles
+ pack $ofm.ok -side top -anchor e -pady 5 -padx 5
+
+ set widgets(results) [Apol_Widget::makeSearchResults [$resultsbox getframe].sw]
+ pack $widgets(results) -expand 1 -fill both
+
+ return $frame
+}
+
+proc Apol_Roles::open {ppath} {
+ set q [new_apol_role_query_t]
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ variable role_list [lsort [role_vector_to_list $v]]
+ $v -acquire
+ $v -delete
+
+ variable widgets
+ Apol_Widget::resetTypeComboboxToPolicy $widgets(combo_types)
+}
+
+proc Apol_Roles::close {} {
+ variable widgets
+ variable opts
+ variable role_list {}
+
+ _initializeVars
+ Apol_Widget::clearTypeCombobox $widgets(combo_types)
+ Apol_Widget::clearSearchResults $widgets(results)
+}
+
+proc Apol_Roles::getTextWidget {} {
+ variable widgets
+ return $widgets(results).tb
+}
+
+# Return a list of all role names in the current policy. If no policy
+# is loaded then return an empty list.
+proc Apol_Roles::getRoles {} {
+ variable role_list
+ set role_list
+}
+
+#### private functions below ####
+
+proc Apol_Roles::_initializeVars {} {
+ variable opts
+ array set opts {
+ useType 0
+ showSelection all
+ }
+}
+
+proc Apol_Roles::_toggleTypeCombobox {path name1 name2 op} {
+ Apol_Widget::setTypeComboboxState $path $Apol_Roles::opts(useType)
+}
+
+proc Apol_Roles::_popupRoleInfo {which role} {
+ Apol_Widget::showPopupText $role [_renderRole $role 1]
+}
+
+proc Apol_Roles::_searchRoles {} {
+ variable widgets
+ variable opts
+
+ Apol_Widget::clearSearchResults $widgets(results)
+ if {![ApolTop::is_policy_open]} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No current policy file is opened."
+ return
+ }
+ if {$opts(useType)} {
+ set type [lindex [Apol_Widget::getTypeComboboxValueAndAttrib $widgets(combo_types)] 0]
+ if {$type == {}} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No type selected."
+ return
+ }
+ } else {
+ set type {}
+ }
+ if {$opts(showSelection) == "names"} {
+ set show_all 0
+ } else {
+ set show_all 1
+ }
+
+ set q [new_apol_role_query_t]
+ $q set_type $::ApolTop::policy $type
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set roles_data [role_vector_to_list $v]
+ $v -acquire
+ $v -delete
+ set text "ROLES:\n"
+ if {[llength $roles_data] == 0} {
+ append text "Search returned no results."
+ } else {
+ foreach r [lsort $roles_data] {
+ append text "\n[_renderRole $r $show_all]"
+ }
+ }
+ Apol_Widget::appendSearchResultText $widgets(results) $text
+}
+
+proc Apol_Roles::_renderRole {role_name show_all} {
+ set qpol_role_datum [new_qpol_role_t $::ApolTop::qpolicy $role_name]
+ if {!$show_all} {
+ return $role_name
+ }
+ set i [$qpol_role_datum get_type_iter $::ApolTop::qpolicy]
+ set types {}
+ while {![$i end]} {
+ set qpol_type_datum [qpol_type_from_void [$i get_item]]
+ lappend types [$qpol_type_datum get_name $::ApolTop::qpolicy]
+ $i next
+ }
+ $i -acquire
+ $i -delete
+ set text "$role_name ([llength $types] type"
+ if {[llength $types] != 1} {
+ append text "s"
+ }
+ append text ")\n"
+ foreach t [lsort -dictionary $types] {
+ append text " $t\n"
+ }
+# append text " dominance: $dominates\n"
+ return $text
+}
diff --git a/apol/terules_tab.tcl b/apol/terules_tab.tcl
new file mode 100644
index 0000000..c5a490f
--- /dev/null
+++ b/apol/terules_tab.tcl
@@ -0,0 +1,1034 @@
+# Copyright (C) 2001-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
+
+namespace eval Apol_TE {
+ variable vals
+ variable widgets
+ variable tabs
+ variable enabled
+}
+
+proc Apol_TE::create {tab_name nb} {
+ variable vals
+ variable widgets
+
+ _initializeVars
+
+ set frame [$nb insert end $tab_name -text "TE Rules"]
+ set pw [PanedWindow $frame.pw -side left -weights extra]
+ set topf [$pw add -weight 0]
+ set bottomf [$pw add -weight 1]
+ pack $pw -expand 1 -fill both
+
+ # Major SubFrames:
+ # rsbox - rule selection
+ # oobox - other search options
+ # obox - holds search options widgets
+ # rbox - holds display window widgets
+ # abox - action buttons
+ set top_leftf [frame $topf.tl]
+ set widgets(search_opts) [NoteBook $topf.nb]
+ set abox [frame $topf.abox]
+ pack $top_leftf -side left -expand 0 -fill y
+ pack $widgets(search_opts) -side left -expand 1 -fill both -padx 10
+ pack $abox -side right -fill y -padx 5
+ set rsbox [TitleFrame $top_leftf.rsbox -text "Rule Selection"]
+ set oobox [TitleFrame $top_leftf.oobox -text "Search Options"]
+ set rbox [TitleFrame $bottomf.rbox -text "Type Enforcement Rules Display"]
+ pack $rsbox -side top -expand 0 -fill both
+ pack $oobox -side top -expand 1 -fill both -pady 2
+ pack $rbox -expand yes -fill both -padx 2
+
+ # Rule selection subframe
+ set fm_rules [$rsbox getframe]
+ set allow [checkbutton $fm_rules.allow -text "allow" \
+ -onvalue $::QPOL_RULE_ALLOW -offvalue 0 \
+ -variable Apol_TE::vals(rs:avrule_allow)]
+ set neverallow [checkbutton $fm_rules.neverallow -text "neverallow" \
+ -onvalue $::QPOL_RULE_NEVERALLOW -offvalue 0 \
+ -variable Apol_TE::vals(rs:avrule_neverallow)]
+ set auditallow [checkbutton $fm_rules.auditallow -text "auditallow" \
+ -onvalue $::QPOL_RULE_AUDITALLOW -offvalue 0 \
+ -variable Apol_TE::vals(rs:avrule_auditallow)]
+ set dontaudit [checkbutton $fm_rules.dontaudit -text "dontaudit" \
+ -onvalue $::QPOL_RULE_DONTAUDIT -offvalue 0 \
+ -variable Apol_TE::vals(rs:avrule_dontaudit)]
+ set type_transition [checkbutton $fm_rules.type_transition -text "type_trans" \
+ -onvalue $::QPOL_RULE_TYPE_TRANS -offvalue 0 \
+ -variable Apol_TE::vals(rs:type_transition)]
+ set type_member [checkbutton $fm_rules.type_member -text "type_member" \
+ -onvalue $::QPOL_RULE_TYPE_MEMBER -offvalue 0 \
+ -variable Apol_TE::vals(rs:type_member)]
+ set type_change [checkbutton $fm_rules.type_change -text "type_change" \
+ -onvalue $::QPOL_RULE_TYPE_CHANGE -offvalue 0 \
+ -variable Apol_TE::vals(rs:type_change)]
+ grid $allow $type_transition -sticky w -padx 2
+ grid $auditallow $type_member -sticky w -padx 2
+ grid $dontaudit $type_change -sticky w -padx 2
+ grid $neverallow x -sticky w -padx 2
+ foreach x {allow neverallow auditallow dontaudit type_transition type_member type_change} {
+ trace add variable Apol_TE::vals(rs:$x) write \
+ [list Apol_TE::_toggle_rule_selection]
+ }
+
+ # Other search options subframe
+ set fm_options [$oobox getframe]
+ set enabled [checkbutton $fm_options.enabled -text "Search only enabled rules" \
+ -variable Apol_TE::vals(oo:enabled)]
+ set regexp [checkbutton $fm_options.regex -text "Search using regular expression" \
+ -variable Apol_TE::vals(oo:regexp)]
+ pack $enabled $regexp -expand 0 -fill none -anchor w
+
+ _createTypesAttribsTab
+ _createClassesPermsTab
+
+ # Action buttons
+ set widgets(new) [button $abox.new -text "New Search" -width 12 \
+ -command [list Apol_TE::_search_terules new]]
+ set widgets(update) [button $abox.update -text "Update Search" -width 12 -state disabled \
+ -command [list Apol_TE::_search_terules update]]
+ set widgets(reset) [button $abox.reset -text "Reset Criteria" -width 12 \
+ -command Apol_TE::_reset]
+ pack $widgets(new) $widgets(update) $widgets(reset) \
+ -side top -pady 5 -padx 5 -anchor ne
+
+ $widgets(search_opts) compute_size
+
+ # Popup menu widget
+ set popupTab_Menu [menu .popup_terules -tearoff 0]
+ set tab_menu_callbacks \
+ [list {"Close Tab" Apol_TE::_delete_results} \
+ {"Rename Tab" Apol_TE::_display_rename_tab_dialog}]
+
+ # Notebook creation for results
+ set widgets(results) [NoteBook [$rbox getframe].results]
+ $widgets(results) bindtabs <Button-1> Apol_TE::_switch_to_tab
+ $widgets(results) bindtabs <Button-3> \
+ [list ApolTop::popup \
+ %W %x %y $popupTab_Menu $tab_menu_callbacks]
+ set close [button [$rbox getframe].close -text "Close Tab" \
+ -command Apol_TE::_delete_current_results]
+ pack $widgets(results) -expand 1 -fill both -padx 4
+ pack $close -expand 0 -fill x -padx 4 -pady 2
+
+ _initializeVars
+
+ return $frame
+}
+
+proc Apol_TE::open {ppath} {
+ _initializeVars
+ _initializeWidgets
+ _initializeTabs
+
+ variable vals
+ variable enabled
+ set vals(cp:classes) [Apol_Class_Perms::getClasses]
+ set enabled(cp:classes) 1
+ set enabled(cp:perms) 1
+}
+
+proc Apol_TE::close {} {
+ _initializeTabs
+ _initializeWidgets
+ _initializeVars
+ set enabled(cp:perms) 1
+}
+
+proc Apol_TE::getTextWidget {} {
+ variable widgets
+ variable tabs
+ if {[$widgets(results) pages] != {}} {
+ set raisedPage [$widgets(results) raise]
+ if {$raisedPage != {}} {
+ return $tabs($raisedPage).tb
+ }
+ }
+ return {}
+}
+
+proc Apol_TE::save_query_options {file_channel query_file} {
+ variable vals
+ foreach {key value} [array get vals] {
+ if {$key != "cp:classes" && $key != "cp:perms"} {
+ puts $file_channel "$key $value"
+ }
+ }
+}
+
+proc Apol_TE::load_query_options {file_channel} {
+ variable vals
+ variable widgets
+ variable enabled
+ _initializeVars
+
+ # load as many values as possible
+ set classes_selected {}
+ set perms_selected {}
+ while {[gets $file_channel line] >= 0} {
+ set line [string trim $line]
+ # Skip empty lines and comments
+ if {$line == {} || [string index $line 0] == "#"} {
+ continue
+ }
+ regexp -line -- {^(\S+)( (.+))?} $line -> key --> value
+ if {$key == "cp:classes_selected"} {
+ set classes_selected $value
+ } elseif {$key == "cp:perms_selected"} {
+ set perms_selected $value
+ } else {
+ set vals($key) $value
+ }
+ }
+
+ # update the display
+ _initializeWidgets
+ set vals(cp:classes) [Apol_Class_Perms::getClasses]
+ set enabled(cp:classes) 1
+ set enabled(cp:perms) 1
+ _toggle_perms_toshow -> -> reset
+
+ # then verify that selected object classes and permissions exist
+ # for this policy
+
+ set unknowns {}
+ set vals(cp:classes_selected) {}
+ foreach class $classes_selected {
+ if {[set i [lsearch $vals(cp:classes) $class]] >= 0} {
+ $widgets(cp:classes) selection set $i
+ lappend vals(cp:classes_selected) $class
+ } else {
+ lappend unknowns $class
+ }
+ }
+ if {[llength $unknowns] > 0} {
+ tk_messageBox -icon warning -type ok -title "Open Apol Query" \
+ -message "The following object classes do not exist in the currently loaded policy and were ignored:\n\n[join $unknowns ", "]" \
+ -parent .
+ }
+
+ _toggle_perms_toshow {} {} {}
+ set unknowns {}
+ set vals(cp:perms_selected) {}
+ foreach perm $perms_selected {
+ if {[set i [lsearch $vals(cp:perms) $perm]] >= 0} {
+ $widgets(cp:perms) selection set $i
+ lappend vals(cp:perms_selected) $perm
+ } else {
+ lappend unknowns $perm
+ }
+ }
+ if {[llength $unknowns] > 0} {
+ tk_messageBox -icon warning -type ok -title "Open Apol Query" \
+ -message "The following permissions do not exist in the currently loaded policy and were ignored:\n\n[join $unknowns ", "]" \
+ -parent $parentDlg
+ }
+}
+
+#### private functions below ####
+
+proc Apol_TE::_initializeVars {} {
+ variable vals
+ array set vals [list \
+ rs:avrule_allow $::QPOL_RULE_ALLOW \
+ rs:avrule_neverallow 0 \
+ rs:avrule_auditallow $::QPOL_RULE_AUDITALLOW \
+ rs:avrule_dontaudit $::QPOL_RULE_DONTAUDIT \
+ rs:type_transition $::QPOL_RULE_TYPE_TRANS \
+ rs:type_member $::QPOL_RULE_TYPE_MEMBER \
+ rs:type_change $::QPOL_RULE_TYPE_CHANGE \
+ ta:source_sym,types $::APOL_QUERY_SYMBOL_IS_TYPE \
+ ta:target_sym,types $::APOL_QUERY_SYMBOL_IS_TYPE \
+ ta:default_sym,types $::APOL_QUERY_SYMBOL_IS_TYPE \
+ ]
+
+ array set vals {
+ oo:enabled 0
+ oo:regexp 0
+
+ ta:use_source 0
+ ta:source_indirect 1
+ ta:source_which source
+ ta:source_sym,attribs 0
+ ta:source_sym {}
+
+ ta:use_target 0
+ ta:target_indirect 1
+ ta:target_sym,attribs 0
+ ta:target_sym {}
+
+ ta:use_default 0
+ ta:default_sym,attribs 0
+ ta:default_sym {}
+
+ cp:classes {}
+ cp:classes_selected {}
+ cp:perms {}
+ cp:perms_selected {}
+ cp:perms_toshow all
+ cp:perms_matchall 0
+ }
+
+ variable enabled
+ array set enabled {
+ ta:use_source 1
+ ta:use_target 1
+ ta:use_default 1
+
+ cp:classes 0
+ cp:perms 0
+ }
+}
+
+proc Apol_TE::_initializeTabs {} {
+ variable widgets
+ variable tabs
+ array set tabs {
+ next_result_id 1
+ }
+ foreach p [$widgets(results) pages 0 end] {
+ _delete_results $p
+ }
+}
+
+proc Apol_TE::_initializeWidgets {} {
+ variable widgets
+ $widgets(search_opts) raise typeattrib
+
+ $widgets(cp:classes) selection clear 0 end
+ $widgets(cp:perms) selection clear 0 end
+}
+
+proc Apol_TE::_createTypesAttribsTab {} {
+ variable vals
+ variable widgets
+ variable enabled
+
+ set ta_tab [$widgets(search_opts) insert end typeattrib -text "Types/Attributes"]
+ set fm_source [frame $ta_tab.source]
+ set fm_target [frame $ta_tab.target]
+ set fm_default [frame $ta_tab.default]
+ grid $fm_source $fm_target $fm_default -padx 4 -sticky ewns
+ foreach i {0 1 2} {
+ grid columnconfigure $ta_tab $i -weight 1 -uniform 1
+ }
+ grid rowconfigure $ta_tab 0 -weight 1
+
+ _create_ta_box source $fm_source "Source type/attribute" 1 1 1
+ _create_ta_box target $fm_target "Target type/attribute" 1 0 1
+ _create_ta_box default $fm_default "Default type" 0 0 0
+
+ $widgets(search_opts) raise typeattrib
+}
+
+proc Apol_TE::_create_ta_box {prefix f title has_indirect has_which has_attribs} {
+ variable vals
+ variable widgets
+
+ set widgets(ta:use_${prefix}) [checkbutton $f.use -text $title \
+ -variable Apol_TE::vals(ta:use_${prefix})]
+ pack $widgets(ta:use_${prefix}) -side top -anchor w
+ trace add variable Apol_TE::vals(ta:use_${prefix}) write \
+ [list Apol_TE::_toggle_ta_box $prefix]
+
+ set w {}
+
+ if {$has_attribs} {
+ set helptext "Type or select a type or attribute"
+ } else {
+ set helptext "Type or select a type"
+ }
+ set widgets(ta:${prefix}_sym) [ComboBox $f.sym \
+ -state disabled -entrybg $ApolTop::default_bg_color \
+ -textvariable Apol_TE::vals(ta:${prefix}_sym) \
+ -helptext $helptext -autopost 1]
+ pack $widgets(ta:${prefix}_sym) -expand 0 -fill x -padx 8
+ lappend w $widgets(ta:${prefix}_sym)
+
+ if {$has_attribs} {
+ set ta_frame [frame $f.ta]
+ pack $ta_frame -expand 0 -anchor center -pady 2
+ set types [checkbutton $ta_frame.types -text "Types" -state disabled \
+ -onvalue $::APOL_QUERY_SYMBOL_IS_TYPE -offvalue 0 \
+ -variable Apol_TE::vals(ta:${prefix}_sym,types)]
+ set attribs [checkbutton $ta_frame.attribs -text "Attribs" -state disabled \
+ -onvalue $::APOL_QUERY_SYMBOL_IS_ATTRIBUTE -offvalue 0 \
+ -variable Apol_TE::vals(ta:${prefix}_sym,attribs)]
+ $types configure -command [list Apol_TE::_toggle_ta_pushed $prefix $types]
+ $attribs configure -command [list Apol_TE::_toggle_ta_pushed $prefix $attribs]
+ trace add variable Apol_TE::vals(ta:${prefix}_sym,attribs) write \
+ [list Apol_TE::_toggle_ta_sym $prefix]
+ pack $types $attribs -side left -padx 2
+ lappend w $types $attribs
+ }
+
+ if {$has_indirect} {
+ set indirect [checkbutton $f.indirect -text "Only direct matches" \
+ -state disabled -variable Apol_TE::vals(ta:${prefix}_indirect) \
+ -onvalue 0 -offvalue 1]
+ pack $indirect -anchor w -padx 8
+ lappend w $indirect
+ }
+
+ if {$has_which} {
+ set which_fm [frame $f.which]
+ set which_source [radiobutton $which_fm.source \
+ -text "As source" -state disabled \
+ -variable Apol_TE::vals(ta:${prefix}_which) \
+ -value source]
+ set which_any [radiobutton $which_fm.any \
+ -text "Any" -state disabled \
+ -variable Apol_TE::vals(ta:${prefix}_which) \
+ -value either]
+ trace add variable Apol_TE::vals(ta:${prefix}_which) write \
+ [list Apol_TE::_toggle_which]
+ pack $which_source $which_any -side left -padx 2
+ pack $which_fm -anchor w -padx 6
+ lappend w $which_source $which_any
+ }
+
+ # update contents of the combobox whenever the 'Types' checkbutton
+ # is enabled; for default type, this is invoked by a call to
+ # reinitialize_default_search_options
+ trace add variable Apol_TE::vals(ta:${prefix}_sym,types) write \
+ [list Apol_TE::_toggle_ta_sym $prefix]
+
+ set widgets(ta:${prefix}_widgets) $w
+ trace add variable Apol_TE::enabled(ta:use_${prefix}) write \
+ [list Apol_TE::_toggle_enable_ta ${prefix}]
+}
+
+proc Apol_TE::_toggle_rule_selection {name1 name2 op} {
+ _maybe_enable_default_type
+ _maybe_enable_perms
+}
+
+
+## lots of obscure callbacks here to determine when to enable a ta box ##
+
+
+# called when there is a change in state to the top checkbutton within
+# a ta box
+proc Apol_TE::_toggle_ta_box {col name1 name2 op} {
+ variable vals
+ variable enabled
+ if {$col == "source"} {
+ _maybe_enable_target_type
+ _maybe_enable_default_type
+ }
+
+ # force a refresh of this box's state; this invokes
+ # _toggle_enable_ta callback
+ set enabled(ta:use_${col}) $enabled(ta:use_${col})
+}
+
+# disable target type/attrib and default type if source box is marked as "any"
+proc Apol_TE::_toggle_which {name1 name2 op} {
+ _maybe_enable_target_type
+ _maybe_enable_default_type
+}
+
+proc Apol_TE::_maybe_enable_target_type {} {
+ variable vals
+ variable enabled
+
+ set any_set 0
+ if {$enabled(ta:use_source) && $vals(ta:use_source) && $vals(ta:source_which) == "either"} {
+ set any_set 1
+ }
+ if {!$any_set} {
+ set enabled(ta:use_target) 1
+ } else {
+ set enabled(ta:use_target) 0
+ }
+}
+
+proc Apol_TE::_maybe_enable_default_type {} {
+ variable vals
+ variable enabled
+
+ set typerule_set 0
+ set any_set 0
+ foreach x {type_transition type_member type_change} {
+ if {$vals(rs:$x)} {
+ set typerule_set 1
+ break
+ }
+ }
+ if {$enabled(ta:use_source) && $vals(ta:use_source) && $vals(ta:source_which) == "either"} {
+ set any_set 1
+ }
+ if {$typerule_set && !$any_set} {
+ set enabled(ta:use_default) 1
+ } else {
+ set enabled(ta:use_default) 0
+ }
+}
+
+# called whenever a ta box is enabled or disabled
+proc Apol_TE::_toggle_enable_ta {col name1 name2 op} {
+ variable vals
+ variable widgets
+ variable enabled
+ if {$enabled(ta:use_${col})} {
+ $widgets(ta:use_${col}) configure -state normal
+ } else {
+ $widgets(ta:use_${col}) configure -state disabled
+ }
+ if {$enabled(ta:use_${col}) && $vals(ta:use_${col})} {
+ foreach w $widgets(ta:${col}_widgets) {
+ $w configure -state normal
+ }
+ $widgets(ta:${col}_sym) configure -entrybg white
+ } else {
+ foreach w $widgets(ta:${col}_widgets) {
+ $w configure -state disabled
+ }
+ $widgets(ta:${col}_sym) configure -entrybg $ApolTop::default_bg_color
+ }
+
+ # update this tab's name if one of the columns is enabled and used
+ if {($enabled(ta:use_source) && $vals(ta:use_source)) || \
+ ($enabled(ta:use_target) && $vals(ta:use_target)) || \
+ ($enabled(ta:use_default) && $vals(ta:use_default))} {
+ $widgets(search_opts) itemconfigure typeattrib -text "Types/Attributes *"
+ } else {
+ $widgets(search_opts) itemconfigure typeattrib -text "Types/Attributes"
+ }
+}
+
+proc Apol_TE::_toggle_ta_sym {col name1 name2 op} {
+ variable vals
+ variable widgets
+
+ if {!$vals(ta:${col}_sym,types) && !$vals(ta:${col}_sym,attribs)} {
+ # don't change combobox if both types and attribs are deselected
+ return
+ }
+ if {$vals(ta:${col}_sym,types) && $vals(ta:${col}_sym,attribs)} {
+ set items [lsort [concat [Apol_Types::getTypes] [Apol_Types::getAttributes]]]
+ } elseif {$vals(ta:${col}_sym,types)} {
+ set items [Apol_Types::getTypes]
+ } else {
+ set items [Apol_Types::getAttributes]
+ }
+ $widgets(ta:${col}_sym) configure -values $items
+}
+
+# disallow both types and attribs to be deselected within a ta box
+proc Apol_TE::_toggle_ta_pushed {col cb} {
+ variable vals
+ if {!$vals(ta:${col}_sym,types) && !$vals(ta:${col}_sym,attribs)} {
+ $cb select
+ }
+}
+
+# code to create and handle the classe/permissions subtab
+
+proc Apol_TE::_createClassesPermsTab {} {
+ variable vals
+ variable widgets
+ variable enabled
+
+ set objects_tab [$widgets(search_opts) insert end classperms -text "Classes/Permissions"]
+ set fm_objs [TitleFrame $objects_tab.objs -text "Object Classes"]
+ set fm_perms [TitleFrame $objects_tab.perms -text "AV Rule Permissions"]
+ pack $fm_objs -side left -expand 0 -fill both -padx 2 -pady 2
+ pack $fm_perms -side left -expand 1 -fill both -padx 2 -pady 2
+
+ # object classes subframe
+ set sw [ScrolledWindow [$fm_objs getframe].sw -auto both]
+ set widgets(cp:classes) [listbox [$sw getframe].lb -height 5 -width 24 \
+ -highlightthickness 0 -selectmode multiple \
+ -exportselection 0 -state disabled \
+ -bg $ApolTop::default_bg_color \
+ -listvar Apol_TE::vals(cp:classes)]
+ $sw setwidget $widgets(cp:classes)
+ update
+ grid propagate $sw 0
+ bind $widgets(cp:classes) <<ListboxSelect>> \
+ [list Apol_TE::_toggle_cp_select classes]
+ pack $sw -expand 1 -fill both
+ set clear [button [$fm_objs getframe].b -text "Clear" -width 6 -state disabled \
+ -command [list Apol_TE::_clear_cp_listbox $widgets(cp:classes) classes]]
+ pack $clear -expand 0 -pady 2
+ set widgets(cp:classes_widgets) [list $widgets(cp:classes) $clear]
+
+ # permissions subframe
+ set f [$fm_perms getframe]
+ set sw [ScrolledWindow $f.sw -auto both]
+ set widgets(cp:perms) [listbox [$sw getframe].lb -height 5 -width 24 \
+ -highlightthickness 0 -selectmode multiple \
+ -exportselection 0 -bg white \
+ -listvar Apol_TE::vals(cp:perms)]
+ $sw setwidget $widgets(cp:perms)
+ update
+ grid propagate $sw 0
+ bind $widgets(cp:perms) <<ListboxSelect>> \
+ [list Apol_TE::_toggle_cp_select perms]
+ set clear [button $f.clear -text "Clear" \
+ -command [list Apol_TE::_clear_cp_listbox $widgets(cp:perms) perms]]
+ set reverse [button $f.reverse -text "Reverse" \
+ -command [list Apol_TE::_reverse_cp_listbox $widgets(cp:perms)]]
+ set perm_opts_f [frame $f.perms]
+ set perm_rb_f [frame $perm_opts_f.rb]
+ set l [label $perm_rb_f.l -text "Permissions to show:" -state disabled]
+ set all [radiobutton $perm_rb_f.all -text "All" \
+ -variable Apol_TE::vals(cp:perms_toshow) -value all]
+ set union [radiobutton $perm_rb_f.union -text "All for selected classes" \
+ -variable Apol_TE::vals(cp:perms_toshow) -value union]
+ set intersect [radiobutton $perm_rb_f.inter -text "Common to selected classes" \
+ -variable Apol_TE::vals(cp:perms_toshow) -value intersect]
+ trace add variable Apol_TE::vals(cp:perms_toshow) write \
+ Apol_TE::_toggle_perms_toshow
+ pack $l $all $union $intersect -anchor w
+ set all_perms [checkbutton $perm_opts_f.all -text "AV rule must have all selected permissions" \
+ -variable Apol_TE::vals(cp:perms_matchall)]
+ pack $perm_rb_f $all_perms -anchor w -pady 4 -padx 4
+ grid $sw - $perm_opts_f -sticky nsw
+ grid $clear $reverse ^ -pady 2 -sticky ew
+ grid columnconfigure $f 0 -weight 0 -uniform 1 -pad 2
+ grid columnconfigure $f 1 -weight 0 -uniform 1 -pad 2
+ grid columnconfigure $f 2 -weight 1
+ grid rowconfigure $f 0 -weight 1
+ set widgets(cp:perms_widgets) \
+ [list $widgets(cp:perms) $clear $reverse $l $all $union $intersect $all_perms]
+
+ trace add variable Apol_TE::vals(cp:classes_selected) write \
+ [list Apol_TE::_update_cp_tabname]
+ trace add variable Apol_TE::vals(cp:perms_selected) write \
+ [list Apol_TE::_update_cp_tabname]
+ trace add variable Apol_TE::enabled(cp:classes) write \
+ [list Apol_TE::_toggle_enable_cp classes]
+ trace add variable Apol_TE::enabled(cp:perms) write \
+ [list Apol_TE::_toggle_enable_cp perms]
+}
+
+proc Apol_TE::_toggle_enable_cp {prefix name1 name2 op} {
+ variable vals
+ variable widgets
+ variable enabled
+ if {$enabled(cp:${prefix})} {
+ foreach w $widgets(cp:${prefix}_widgets) {
+ $w configure -state normal
+ }
+ $widgets(cp:${prefix}) configure -bg white
+ } else {
+ foreach w $widgets(cp:${prefix}_widgets) {
+ $w configure -state disabled
+ }
+ $widgets(cp:${prefix}) configure -bg $ApolTop::default_bg_color
+ }
+ # force a refresh of this tab's name
+ set vals(cp:${prefix}_selected) $vals(cp:${prefix}_selected)
+}
+
+proc Apol_TE::_maybe_enable_perms {} {
+ variable vals
+ variable enabled
+
+ set avrule_set 0
+ foreach x {avrule_allow avrule_neverallow avrule_auditallow avrule_dontaudit} {
+ if {$vals(rs:$x)} {
+ set avrule_set 1
+ break
+ }
+ }
+ if {$avrule_set} {
+ set enabled(cp:perms) 1
+ } else {
+ set enabled(cp:perms) 0
+ }
+}
+
+proc Apol_TE::_toggle_perms_toshow {name1 name2 op} {
+ variable vals
+ variable widgets
+ if {$vals(cp:perms_toshow) == "all"} {
+ # don't change the list of permissions if there was a new
+ # object class selection and the current radiobutton is all
+ if {$op != "update"} {
+ set vals(cp:perms) $Apol_Class_Perms::perms_list
+ set vals(cp:perms_selected) {}
+ }
+ } elseif {$vals(cp:perms_toshow) == "union"} {
+ set vals(cp:perms) {}
+ set vals(cp:perms_selected) {}
+ foreach class $vals(cp:classes_selected) {
+ set vals(cp:perms) [lsort -unique -dictionary [concat $vals(cp:perms) [Apol_Class_Perms::getPermsForClass $class]]]
+ }
+ } else { ;# intersection
+ set vals(cp:perms) {}
+ set vals(cp:perms_selected) {}
+ set classes {}
+ foreach i [$widgets(cp:classes) curselection] {
+ lappend classes [$widgets(cp:classes) get $i]
+ }
+ if {$classes == {}} {
+ return
+ }
+ set vals(cp:perms) [Apol_Class_Perms::getPermsForClass [lindex $classes 0]]
+ foreach class [lrange $classes 1 end] {
+ set this_perms [Apol_Class_Perms::getPermsForClass $class]
+ set new_perms {}
+ foreach p $vals(cp:perms) {
+ if {[lsearch -exact $this_perms $p] >= 0} {
+ lappend new_perms $p
+ }
+ }
+ set vals(cp:perms) $new_perms
+ }
+ }
+}
+
+# called whenever an item with a class/perm listbox is
+# selected/deselected
+proc Apol_TE::_toggle_cp_select {col} {
+ variable vals
+ variable widgets
+ set items {}
+ foreach i [$widgets(cp:${col}) curselection] {
+ lappend items [$widgets(cp:${col}) get $i]
+ }
+ set vals(cp:${col}_selected) $items
+ if {$col == "classes"} {
+ _toggle_perms_toshow {} {} update
+ }
+}
+
+proc Apol_TE::_clear_cp_listbox {lb prefix} {
+ variable vals
+ $lb selection clear 0 end
+ set vals(cp:${prefix}_selected) {}
+ if {$prefix == "classes"} {
+ _toggle_perms_toshow {} {} update
+ }
+}
+
+proc Apol_TE::_reverse_cp_listbox {lb} {
+ variable vals
+ set old_selection [$lb curselection]
+ set items {}
+ for {set i 0} {$i < [$lb index end]} {incr i} {
+ if {[lsearch $old_selection $i] >= 0} {
+ $lb selection clear $i
+ } else {
+ $lb selection set $i
+ lappend items [$lb get $i]
+ }
+ }
+ set vals(cp:perms_selected) $items
+}
+
+proc Apol_TE::_update_cp_tabname {name1 name2 op} {
+ variable vals
+ variable widgets
+ variable enabled
+ if {($enabled(cp:classes) && $vals(cp:classes_selected) > 0) || \
+ ($enabled(cp:perms) && $vals(cp:perms_selected) > 0)} {
+ $widgets(search_opts) itemconfigure classperms -text "Classes/Permissions *"
+ } else {
+ $widgets(search_opts) itemconfigure classperms -text "Classes/Permissions"
+ }
+}
+
+proc Apol_TE::_delete_results {pageID} {
+ variable widgets
+ variable tabs
+
+ # Remove tab and its widgets
+ set curpos [$widgets(results) index $pageID]
+ $widgets(results) delete $pageID
+ array unset tabs $pageID:*
+ array unset tabs $pageID
+
+ # try to raise the next tab
+ if {[set next_id [$widgets(results) pages $curpos]] != {}} {
+ _switch_to_tab $next_id
+ } elseif {$curpos > 0} {
+ # raise the previous page instead
+ _switch_to_tab [$widgets(results) pages [expr {$curpos - 1}]]
+ } else {
+ # no tabs remaining
+ $widgets(update) configure -state disabled
+ }
+}
+
+proc Apol_TE::_display_rename_tab_dialog {pageID} {
+ variable widgets
+ variable tabs
+ set d [Dialog .apol_te_tab_rename -homogeneous 1 -spacing 2 -cancel 1 \
+ -default 0 -modal local -parent . -place center -separator 1 \
+ -side bottom -title "Rename Results Tab"]
+ $d add -text "OK" -command [list $d enddialog "ok"]
+ $d add -text "Cancel" -command [list $d enddialog "cancel"]
+ set f [$d getframe]
+ set l [label $f.l -text "Tab name:"]
+ set tabs(tab:new_name) [$widgets(results) itemcget $pageID -text]
+ set e [entry $f.e -textvariable Apol_TE::tabs(tab:new_name) -width 16 -bg white]
+ pack $l $e -side left -padx 2
+ set retval [$d draw]
+ destroy $d
+ if {$retval == "ok"} {
+ $widgets(results) itemconfigure $pageID -text $tabs(tab:new_name)
+ }
+}
+
+proc Apol_TE::_delete_current_results {} {
+ variable widgets
+ if {[set curid [$widgets(results) raise]] != {}} {
+ _delete_results $curid
+ }
+}
+
+proc Apol_TE::_create_new_results_tab {} {
+ variable vals
+ variable widgets
+ variable tabs
+
+ set i $tabs(next_result_id)
+ incr tabs(next_result_id)
+ set id "results$i"
+ set frame [$widgets(results) insert end "$id" -text "Results $i"]
+ $widgets(results) raise $id
+ set tabs($id) [Apol_Widget::makeSearchResults $frame.results]
+ pack $tabs($id) -expand 1 -fill both
+
+ set tabs($id:vals) [array get vals]
+ return $tabs($id)
+}
+
+proc Apol_TE::_switch_to_tab {pageID} {
+ variable vals
+ variable widgets
+ variable tabs
+
+ # check if switching to already visible tab
+ if {[$Apol_TE::widgets(results) raise] == $pageID} {
+ return
+ }
+ $widgets(results) raise $pageID
+ set cur_search_opts [$widgets(search_opts) raise]
+
+ # restore the tab's search criteria
+ array set tmp_vals $tabs($pageID:vals)
+ set classes_selected $tmp_vals(cp:classes_selected)
+ set perms_selected $tmp_vals(cp:perms_selected)
+ array set vals $tabs($pageID:vals)
+ _initializeWidgets
+ set vals(cp:classes_selected) $classes_selected
+ set vals(cp:perms_selected) $perms_selected
+ foreach c $classes_selected {
+ $widgets(cp:classes) selection set [lsearch $vals(cp:classes) $c]
+ }
+ foreach p $perms_selected {
+ $widgets(cp:perms) selection set [lsearch $vals(cp:perms) $p]
+ }
+ $widgets(search_opts) raise $cur_search_opts
+}
+
+########################################################################
+
+proc Apol_TE::_reset {} {
+ variable enabled
+ set old_classes_enabled $enabled(cp:classes)
+ _initializeVars
+ _initializeWidgets
+ if {[set enabled(cp:classes) $old_classes_enabled]} {
+ variable vals
+ set vals(cp:classes) [Apol_Class_Perms::getClasses]
+ set enabled(cp:classes) 1
+ set enabled(cp:perms) 1
+ }
+}
+
+proc Apol_TE::_search_terules {whichButton} {
+ variable vals
+ variable widgets
+ variable enabled
+ variable tabs
+
+ if {![ApolTop::is_policy_open]} {
+ tk_messageBox -icon error -type ok -title "TE Rule Search" -message "No current policy file is opened."
+ return
+ }
+
+ # check search options
+ if {$enabled(ta:use_source) && $vals(ta:use_source) && $vals(ta:source_sym) == {}} {
+ tk_messageBox -icon error -type ok -title "TE Rule Search" -message "No source type/attribute was selected."
+ return
+ }
+ if {$enabled(ta:use_target) && $vals(ta:use_target) && $vals(ta:target_sym) == {}} {
+ tk_messageBox -icon error -type ok -title "TE Rule Search" -message "No target type/attribute was selected."
+ return
+ }
+ if {$enabled(ta:use_default) && $vals(ta:use_default) && $vals(ta:default_sym) == {}} {
+
+ tk_messageBox -icon error -type ok -title "TE Rule Search" -message "No default type selected."
+ return
+ }
+
+ set avrule_selection 0
+ foreach {key value} [array get vals rs:avrule_*] {
+ set avrule_selection [expr {$avrule_selection | $value}]
+ }
+ set terule_selection 0
+ foreach {key value} [array get vals rs:type_*] {
+ set terule_selection [expr {$terule_selection | $value}]
+ }
+ if {$avrule_selection == 0 && $terule_selection == 0} {
+ tk_messageBox -icon error -type ok -title "TE Rule Search" -message "At least one rule must be selected."
+ return
+ }
+
+ # start building queries
+ set avq [new_apol_avrule_query_t]
+ set teq [new_apol_terule_query_t]
+
+ if {$enabled(ta:use_source) && $vals(ta:use_source)} {
+ if {$vals(ta:source_which) == "either"} {
+ $avq set_source_any $::ApolTop::policy 1
+ }
+ $avq set_source $::ApolTop::policy $vals(ta:source_sym) $vals(ta:source_indirect)
+ $avq set_source_component $::ApolTop::policy [expr {$vals(ta:source_sym,types) | $vals(ta:source_sym,attribs)}]
+ $teq set_source $::ApolTop::policy $vals(ta:source_sym) $vals(ta:source_indirect)
+ $teq set_source_component $::ApolTop::policy [expr {$vals(ta:source_sym,types) | $vals(ta:source_sym,attribs)}]
+ }
+ if {$enabled(ta:use_target) && $vals(ta:use_target)} {
+ $avq set_target $::ApolTop::policy $vals(ta:target_sym) $vals(ta:target_indirect)
+ $avq set_target_component $::ApolTop::policy [expr {$vals(ta:target_sym,types) | $vals(ta:target_sym,attribs)}]
+ $teq set_target $::ApolTop::policy $vals(ta:target_sym) $vals(ta:target_indirect)
+ $teq set_target_component $::ApolTop::policy [expr {$vals(ta:target_sym,types) | $vals(ta:target_sym,attribs)}]
+ }
+ if {$enabled(ta:use_default) && $vals(ta:use_default)} {
+ $teq set_default $::ApolTop::policy $vals(ta:default_sym)
+ }
+
+ if {$enabled(cp:classes)} {
+ foreach c $vals(cp:classes_selected) {
+ $avq append_class $::ApolTop::policy $c
+ $teq append_class $::ApolTop::policy $c
+ }
+ }
+ if {$enabled(cp:perms)} {
+ foreach p $vals(cp:perms_selected) {
+ $avq append_perm $::ApolTop::policy $p
+ }
+ $avq set_all_perms $::ApolTop::policy $vals(cp:perms_matchall)
+ }
+
+ $avq set_rules $::ApolTop::policy $avrule_selection
+ $teq set_rules $::ApolTop::policy $terule_selection
+ $avq set_enabled $::ApolTop::policy $vals(oo:enabled)
+ $teq set_enabled $::ApolTop::policy $vals(oo:enabled)
+ $avq set_regex $::ApolTop::policy $vals(oo:regexp)
+ $teq set_regex $::ApolTop::policy $vals(oo:regexp)
+
+ foreach x {new update reset} {
+ $widgets($x) configure -state disabled
+ }
+
+ if {$vals(rs:avrule_neverallow)} {
+ ApolTop::loadNeverAllows
+ }
+ if {![ApolTop::is_capable "neverallow"]} {
+ set avrule_selection [expr {$avrule_selection & (~$::QPOL_RULE_NEVERALLOW)}]
+ $avq set_rules $::ApolTop::policy $avrule_selection
+ }
+
+ Apol_Progress_Dialog::wait "TE Rules" "Searching rules" \
+ {
+ set numTEs {0 0 0}
+ set numAVs {0 0 0}
+ set avresults NULL
+ set teresults NULL
+ set num_avresults 0
+ set num_teresults 0
+ if {![ApolTop::is_capable "syntactic rules"]} {
+ if {$avrule_selection != 0} {
+ set avresults [$avq run $::ApolTop::policy]
+ }
+ if {$terule_selection != 0} {
+ set teresults [$teq run $::ApolTop::policy]
+ }
+ } else {
+ $::ApolTop::qpolicy build_syn_rule_table
+ if {$avrule_selection != 0} {
+ set avresults [$avq run_syn $::ApolTop::policy]
+ }
+ if {$terule_selection != 0} {
+ set teresults [$teq run_syn $::ApolTop::policy]
+ }
+ }
+
+ $avq -acquire
+ $avq -delete
+ $teq -acquire
+ $teq -delete
+ if {$avresults != "NULL"} {
+ set num_avresults [$avresults get_size]
+ }
+ if {$teresults != "NULL"} {
+ set num_teresults [$teresults get_size]
+ }
+
+ if {$whichButton == "new"} {
+ set sr [_create_new_results_tab]
+ } else {
+ set id [$widgets(results) raise]
+ set tabs($id:vals) [array get vals]
+ set sr $tabs($id)
+ Apol_Widget::clearSearchResults $sr
+ }
+
+ if {![ApolTop::is_capable "syntactic rules"]} {
+ apol_tcl_set_info_string $::ApolTop::policy "Rendering $num_avresults AV rule results"
+ apol_tcl_terule_sort $::ApolTop::policy $teresults
+ if {$num_avresults > 0} {
+ set numAVs [Apol_Widget::appendSearchResultRules $sr 0 $avresults qpol_avrule_from_void]
+ }
+ apol_tcl_set_info_string $::ApolTop::policy "Rendering $num_teresults TE rule results"
+ apol_tcl_avrule_sort $::ApolTop::policy $avresults
+ if {$num_teresults > 0} {
+ set numTEs [Apol_Widget::appendSearchResultRules $sr 0 $teresults qpol_terule_from_void]
+ }
+ } else {
+ apol_tcl_set_info_string $::ApolTop::policy "Rendering $num_avresults AV rule results"
+ if {$num_avresults > 0} {
+ set numAVs [Apol_Widget::appendSearchResultSynRules $sr 0 $avresults qpol_syn_avrule_from_void]
+ }
+ apol_tcl_set_info_string $::ApolTop::policy "Rendering $num_teresults TE rule results"
+ if {$num_teresults > 0} {
+ set numTEs [Apol_Widget::appendSearchResultSynRules $sr 0 $teresults qpol_syn_terule_from_void]
+ }
+ }
+ set num_rules [expr {[lindex $numAVs 0] + [lindex $numTEs 0]}]
+ set num_enabled [expr {[lindex $numAVs 1] + [lindex $numTEs 1]}]
+ set num_disabled [expr {[lindex $numAVs 2] + [lindex $numTEs 2]}]
+ set header "$num_rules rule"
+ if {$num_rules != 1} {
+ append header s
+ }
+ append header " match the search criteria.\n"
+ append header "Number of enabled conditional rules: $num_enabled\n"
+ append header "Number of disabled conditional rules: $num_disabled\n"
+ Apol_Widget::appendSearchResultHeader $sr $header
+ }
+ $widgets(new) configure -state normal
+ $widgets(reset) configure -state normal
+ if {[$widgets(results) pages] != {} || $retval == 0} {
+ $widgets(update) configure -state normal
+ }
+}
diff --git a/apol/top.tcl b/apol/top.tcl
new file mode 100644
index 0000000..e0f87a3
--- /dev/null
+++ b/apol/top.tcl
@@ -0,0 +1,1228 @@
+# Copyright (C) 2001-2008 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
+
+set COPYRIGHT_INFO "Copyright (C) 2001-2008 Tresys Technology, LLC"
+
+namespace eval ApolTop {
+ variable policy {} ;# handle to an apol_policy, or {} if none opened
+ variable qpolicy {} ;# handle to policy's qpol_policy_t, or {} if none opened
+ # these three are shown on the status line of the toplevel window
+ variable policy_version_string {}
+ variable policy_source_linenum {}
+ variable policy_stats_summary {}
+ variable policy_stats ;# array of statistics for the current policy
+
+ # user's preferences
+ variable dot_apol_file [file join $::env(HOME) .apol]
+ variable recent_files {}
+ variable last_policy_path {}
+ variable max_recent_files 5
+ variable show_fake_attrib_warning 1 ;# warn if using fake attribute names
+
+ # store the default background color for use when diabling widgets
+ variable default_bg_color
+ variable text_font {}
+ variable title_font {}
+ variable dialog_font {}
+ variable general_font {}
+ variable query_file_ext ".qf"
+ # Main window dimension defaults
+ variable mainframe_width 1000
+ variable mainframe_height 700
+
+ # Other global widgets
+ variable mainframe
+ variable notebook
+ variable current_tab
+
+ # The following list describes the layout of apol. All tab names
+ # must be unique and shall not contain colons. For each tab, the
+ # first element gives the identifier; this corresponds with the
+ # namespace. The second element describes the path to get to the
+ # tab, starting from the topmost notebook. For tabs that are to
+ # be topmost, this is just an empty list. The third element is a
+ # list of tags for the tab. Valid tags are:
+ # tag_conditionals - show this only if the policy supports conditionals
+ # tag_mls - show this only if policy supports MLS
+ # tag_query_saveable - if this tab is shown, enable query saving
+ # tag_source - show this only if a source policy is loaded
+ variable tabs {
+ {Apol_Types components {}}
+ {Apol_Class_Perms components {}}
+ {Apol_Roles components {}}
+ {Apol_Users components {}}
+ {Apol_Cond_Bools components {tag_conditionals}}
+ {Apol_MLS components {tag_mls}}
+ {Apol_Initial_SIDS components {}}
+ {Apol_NetContexts components {}}
+ {Apol_FSContexts components {}}
+ {Apol_TE rules {tag_query_saveable}}
+ {Apol_Cond_Rules rules {tag_conditionals}}
+ {Apol_RBAC rules {}}
+ {Apol_Range rules {tag_mls}}
+ {Apol_File_Contexts {} {}}
+ {Apol_Analysis {} {tag_query_saveable}}
+ {Apol_PolicyConf {} {tag_source}}
+ }
+}
+
+#################### public functions ####################
+
+proc ApolTop::is_policy_open {} {
+ if {$::ApolTop::policy == {}} {
+ return 0
+ }
+ return 1
+}
+
+# If a policy is open and it has the given capability then return
+# non-zero. Valid capabilities are:
+# "attribute names"
+# "conditionals"
+# "line numbers"
+# "mls"
+# "neverallow"
+# "source"
+# "syntactic rules"
+proc ApolTop::is_capable {capability} {
+ if {![is_policy_open]} {
+ return 0;
+ }
+ switch -- $capability {
+ "attribute names" { set cap $::QPOL_CAP_ATTRIB_NAMES }
+ "conditionals" { set cap $::QPOL_CAP_CONDITIONALS }
+ "line numbers" { set cap $::QPOL_CAP_LINE_NUMBERS }
+ "mls" { set cap $::QPOL_CAP_MLS }
+ "neverallow" { set cap $::QPOL_CAP_NEVERALLOW }
+ "source" { set cap $::QPOL_CAP_SOURCE }
+ "syntactic rules" { set cap $::QPOL_CAP_SYN_RULES }
+ default { return 0 }
+ }
+ variable qpolicy
+ $qpolicy has_capability $cap
+}
+
+# Open the given policy path. Re-initialize all tabs and add the path
+# to the list of recently opened policies.
+#
+# @param ppath Policy path to open.
+proc ApolTop::openPolicyPath {ppath} {
+ _close_policy
+
+ set primary_file [$ppath get_primary]
+ if {[catch {Apol_Progress_Dialog::wait $primary_file "Opening policy." \
+ {
+ apol_tcl_open_policy $ppath
+ } \
+ } p] || $p == "NULL"} {
+ tk_messageBox -icon error -type ok -title "Open Policy" -parent . \
+ -message "[apol_tcl_get_error_string]"
+ return -1 ;# indicates failed to open policy
+ }
+
+ variable policy $p
+ variable qpolicy [$p get_qpol]
+
+ _toplevel_policy_open $ppath
+
+ _add_recent $ppath
+ variable last_policy_path $ppath
+
+ variable show_fake_attrib_warning
+ if {![is_capable "attribute names"] && \
+ [llength $::Apol_Types::attriblist] > 0 && \
+ $show_fake_attrib_warning} {
+ set d [Dialog .fake_attribute_dialog -modal local -parent . \
+ -title "Open Policy" -separator 1]
+ $d add -text "OK"
+ set f [$d getframe]
+ label $f.l -text "Warning: Apol has generated attribute names because\nthe original names were not preserved in the policy." -justify left
+ checkbutton $f.cb -text "Show this message again next time." \
+ -variable ApolTop::show_fake_attrib_warning
+ pack $f.l $f.cb -padx 10 -pady 10
+ $d draw
+ destroy $d
+ }
+
+ return 0 ;# indicates policy opened successfully
+}
+
+proc ApolTop::loadNeverAllows {} {
+ if {![is_capable "neverallow"]} {
+ Apol_Progress_Dialog::wait "Loading neverallow rules" "Rebuilding policy" \
+ {
+ $::ApolTop::qpolicy rebuild 0
+ _toplevel_update_stats
+ }
+ }
+}
+
+proc ApolTop::popup {parent x y menu callbacks callback_arg} {
+ # determine where to place the popup menu
+ set gx [winfo rootx $parent]
+ set gy [winfo rooty $parent]
+ set cmx [expr {$gx + $x}]
+ set cmy [expr {$gy + $y}]
+
+ $menu delete 0 end
+ foreach callback $callbacks {
+ $menu add command -label [lindex $callback 0] -command [concat [lindex $callback 1] $callback_arg]
+ }
+ tk_popup $menu $cmx $cmy
+}
+
+# Return the name of the currently shown tab. If the current tab is
+# nested, show the inner-most tab.
+proc ApolTop::getCurrentTab {} {
+ variable current_tab
+ set current_tab
+}
+
+proc ApolTop::getCurrentTextWidget {} {
+ [getCurrentTab]::getTextWidget
+}
+
+proc ApolTop::setCurrentTab {tab_name} {
+ variable tabs
+ # search through all tabs until one is found
+ foreach tab $tabs {
+ if {[lindex $tab 0] == $tab_name} {
+ variable notebook
+ set parent_nb $notebook
+ # raise all parent tabs as well
+ foreach nb [lindex $tab 1] {
+ $parent_nb raise $nb
+ set parent_nb [$parent_nb getframe $nb].nb
+ }
+ $parent_nb raise $tab_name
+ variable current_tab $tab_name
+ _toplevel_tab_switched
+ return
+ }
+ }
+ puts stderr "\[setCurrentTab\] tried to set the tab to $tab_name"
+ exit -1
+}
+
+proc ApolTop::setPolicySourceLinenumber {line} {
+ variable policy_source_linenum "Line $line"
+}
+
+proc ApolTop::showPolicySourceLineNumber {line} {
+ setCurrentTab Apol_PolicyConf
+ Apol_PolicyConf::gotoLine $line
+}
+
+############### functions for creating and maintaining toplevel ###############
+
+proc ApolTop::_create_toplevel {} {
+ set menus {
+ "&File" {} file 0 {
+ {command "&Open..." {} "Open a new policy" {Ctrl o} -command ApolTop::_open_policy}
+ {command "&Close" {tag_policy_open} "Close current polocy" {Ctrl w} -command ApolTop::_user_close_policy}
+ {separator}
+ {cascade "&Recent Files" {} recent 0 {}}
+ {separator}
+ {command "&Quit" {} "Quit policy analysis tool" {Ctrl q} -command ApolTop::_exit}
+ }
+ "&Edit" {} edit 0 {
+ {command "&Copy" {tag_policy_open} {} {Ctrl c} -command ApolTop::_copy}
+ {command "Select &All" {tag_policy_open} {} {Ctrl a} -command ApolTop::_select_all}
+ {separator}
+ {command "&Find..." {tag_policy_open} "Find text in current buffer" {Ctrl f} -command Apol_Find::find}
+ {command "&Goto Line..." {tag_policy_open} "Goto a line in current buffer" {Ctrl g} -command Apol_Goto::goto}
+ {separator}
+ }
+ "&Query" {} query 0 {
+ {command "&Open Query..." {tag_policy_open} "Open query criteria file" {} -command ApolTop::_open_query_file}
+ {command "&Save Query..." {tag_policy_open tag_query_saveable} "Save current query criteria to file" {} -command ApolTop::_save_query_file}
+ {separator}
+ {command "&Policy Summary" {tag_policy_open} "Display summary statistics" {} -command ApolTop::_show_policy_summary}
+ }
+ "&Tools" {} tools 0 {
+ {command "&Open Perm Map..." {tag_policy_open} "Open a permission map from file" {} -command ApolTop::_open_perm_map_from_file}
+ {command "Open &Default Perm Map" {tag_policy_open} "Open the default permission map" {} -command ApolTop::openDefaultPermMap}
+ {command "&Save Perm Map..." {tag_policy_open tag_perm_map_open} "Save the permission map to a file" {} -command ApolTop::_save_perm_map}
+ {command "Save Perm Map &As..." {tag_policy_open tag_perm_map_open} "Save the permission map to a file" {} -command ApolTop::_save_perm_map_as}
+ {command "Save Perm Map as D&efault" {tag_policy_open tag_perm_map_open} "Save the permission map to default file" {} -command ApolTop::_save_perm_map_default}
+ {command "&View Perm Map..." {tag_policy_open tag_perm_map_open} "Edit currently loaded permission map" {} -command Apol_Perms_Map::showPermMappings}
+ }
+ "&Help" {} helpmenu 0 {
+ {command "&General Help" {} "Show help on using apol" {} -command {ApolTop::_show_file Help apol_help.txt}}
+ {command "&Domain Transition Analysis" {} "Show help on domain transitions" {} -command {ApolTop::_show_file "Domain Transition Analysis Help" domaintrans_help.txt}}
+ {command "&Information Flow Analysis" {} "Show help on information flows" {} -command {ApolTop::_show_file "Information Flow Analysis Help" infoflow_help.txt}}
+ {command "Direct &Relabel Analysis" {} "Show help on file relabeling" {} -command {ApolTop::_show_file "Relabel Analysis Help" file_relabel_help.txt}}
+ {command "&Types Relationship Summary Analysis" {} "Show help on types relationships" {} -command {ApolTop::_show_file "Types Relationship Summary Analysis Help" types_relation_help.txt}}
+ {separator}
+ {command "&About apol" {} "Show copyright information" {} -command ApolTop::_about}
+ }
+ }
+ # Note that the name of the last menu is "helpmenu", not "help".
+ # This is because Tk handles menus named "help" differently in X
+ # Windows -- specifically, it is right justified on the menu bar.
+ # See the man page for [menu] for details. It was decided that
+ # the behavior is undesirable; the Help menu is intended to be
+ # left justified along with the other menus. Therefore the menu
+ # name is "helpmenu".
+
+ variable mainframe [MainFrame .mainframe -menu $menus -textvariable ApolTop::statu_line]
+ pack $mainframe -fill both -expand yes
+
+ $mainframe addindicator -textvariable ApolTop::policy_source_linenum -width 14
+ $mainframe addindicator -textvariable ApolTop::policy_stats_summary -width 88
+ $mainframe addindicator -textvariable ApolTop::policy_version_string -width 28
+
+ $mainframe setmenustate tag_policy_open disabled
+
+ variable notebook [NoteBook [$mainframe getframe].nb]
+ pack $notebook -fill both -expand yes -padx 4 -pady 4
+ set page [$notebook insert end components -text "Policy Components"]
+ set components [NoteBook $page.nb]
+ pack $components -fill both -expand yes -padx 4 -pady 4
+ set page [$notebook insert end rules -text "Policy Rules"]
+ set rules [NoteBook $page.nb]
+ pack $rules -fill both -expand yes -padx 4 -pady 4
+ $notebook bindtabs <Button-1> [list ApolTop::_switch_tab $components $rules]
+ $components bindtabs <Button-1> [list ApolTop::_switch_tab $components $rules]
+ $rules bindtabs <Button-1> [list ApolTop::_switch_tab $components $rules]
+
+ variable tabs
+ foreach tab $tabs {
+ set parent_nb $notebook
+ foreach nb [lindex $tab 1] {
+ # (intermediate notebooks were created just above here)
+ set parent_nb [set $nb]
+ }
+ [lindex $tab 0]::create [lindex $tab 0] $parent_nb
+ }
+
+ $components raise [$components page 0]
+ $rules raise [$rules page 0]
+ $notebook raise [$notebook page 0]
+
+ $notebook compute_size
+ setCurrentTab [$components page 0]
+}
+
+# Callback invoked whenever the user clicks on a (possibly different)
+# tab in the toplevel notebook(s).
+proc ApolTop::_switch_tab {components_nb rules_nb new_tab} {
+ if {$new_tab == "components"} {
+ set new_tab [$components_nb raise]
+ } elseif {$new_tab == "rules"} {
+ set new_tab [$rules_nb raise]
+ }
+ variable current_tab $new_tab
+ _toplevel_tab_switched
+}
+
+proc ApolTop::_toplevel_tab_switched {} {
+ variable tabs
+ variable current_tab
+ variable mainframe
+ foreach tab $tabs {
+ if {[lindex $tab 0] != $current_tab} {
+ continue
+ }
+ focus [getCurrentTextWidget]
+ if {[lsearch [lindex $tab 2] "tag_query_saveable"] >= 0} {
+ $mainframe setmenustate tag_query_saveable normal
+ } else {
+ $mainframe setmenustate tag_query_saveable disabled
+ }
+ if {[lsearch [lindex $tab 2] "tag_source"] >= 0} {
+ [lindex $tab 0]::insertionMarkChanged
+ } else {
+ variable policy_source_linenum {}
+ }
+ break
+ }
+}
+
+# Enable and disable various widgets in the toplevel window, based
+# upon the type of policy that was opened.
+proc ApolTop::_toplevel_policy_open {ppath} {
+ variable tabs
+ foreach tab $tabs {
+ [lindex $tab 0]::open $ppath
+ }
+
+ if {![is_capable "conditionals"]} {
+ _toplevel_enable_tabs tag_conditionals disabled
+ }
+ if {![is_capable "mls"]} {
+ _toplevel_enable_tabs tag_mls disabled
+ }
+ if {![is_capable "source"]} {
+ _toplevel_enable_tabs tag_source disabled
+ }
+ _toplevel_tab_switched
+
+ variable mainframe
+ $mainframe setmenustate tag_policy_open normal
+ $mainframe setmenustate tag_perm_map_open disabled
+
+ _toplevel_update_stats
+ variable policy_version_string [$::ApolTop::policy get_version_type_mls_str]
+
+ set primary_file [$ppath get_primary]
+ wm title . "SELinux Policy Analysis - $primary_file"
+}
+
+# Enable/disable tabs that contain the given tag. If the currently
+# raised page is one of those tabs then raise the first tab (which
+# hopefully does not have that tag).
+proc ApolTop::_toplevel_enable_tabs {tag new_state} {
+ variable tabs
+ variable notebook
+ foreach tab $tabs {
+ if {[lsearch [lindex $tab 2] $tag] >= 0} {
+ set parent_nb $notebook
+ foreach nb [lindex $tab 1] {
+ set parent_nb [$parent_nb getframe $nb].nb
+ }
+ $parent_nb itemconfigure [lindex $tab 0] -state $new_state
+ if {[$parent_nb raise] == {}} {
+ $parent_nb raise [$parent_nb pages 0]
+ setCurrentTab [lindex $tabs 0 0]
+ }
+ }
+ }
+}
+
+proc ApolTop::_build_recent_files_menu {} {
+ variable mainframe
+ variable recent_files
+ variable max_recent_files
+ set recent_menu [$mainframe getmenu recent]
+ $recent_menu delete 0 $max_recent_files
+ foreach r $recent_files {
+ foreach {path_type primary_file modules} [policy_path_to_list $r] {break}
+ if {$path_type == "monolithic"} {
+ set label $primary_file
+ } else {
+ set label "$primary_file + [llength $modules] module"
+ if {[llength $modules] != 1} {
+ append label "s"
+ }
+ }
+ $recent_menu add command -label $label \
+ -command [list ApolTop::openPolicyPath $r]
+ }
+}
+
+# Add a policy path to the recently opened list, trim the menu to
+# max_recent_files, and then regenerate the recent menu.
+proc ApolTop::_add_recent {ppath} {
+ variable recent_files
+ variable max_recent_files
+
+ # if ppath is already in recent files list, remove it from there
+ set new_recent $ppath
+ foreach r $recent_files {
+ if {[apol_policy_path_compare $r $ppath] != 0} {
+ lappend new_recent $r
+ }
+ }
+ set recent_files [lrange $new_recent 0 [expr {$max_recent_files - 1}]]
+ _build_recent_files_menu
+}
+
+proc ApolTop::_toplevel_update_stats {} {
+ variable policy_stats
+ variable policy_stats_summary
+
+ set iter_funcs {
+ "classes" get_class_iter
+ "commons" get_common_iter
+
+ "roles" get_role_iter
+ "role_allow" get_role_allow_iter
+ "role_trans" get_role_trans_iter
+
+ "users" get_user_iter
+ "bools" get_bool_iter
+ "sens" get_level_iter
+ "cats" get_cat_iter
+ "range_trans" get_range_trans_iter
+
+ "sids" get_isid_iter
+ "portcons" get_portcon_iter
+ "netifcons" get_netifcon_iter
+ "nodecons" get_nodecon_iter
+ "genfscons" get_genfscon_iter
+ "fs_uses" get_fs_use_iter
+ }
+ foreach {key func} $iter_funcs {
+ set i [$::ApolTop::qpolicy $func]
+ set policy_stats($key) [$i get_size]
+ $i -acquire
+ $i -delete
+ }
+
+ set query_funcs {
+ "perms" new_apol_perm_query_t
+ "types" new_apol_type_query_t
+ "attribs" new_apol_attr_query_t
+ }
+
+ foreach {key func} $query_funcs {
+ set q [$func]
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set policy_stats($key) [$v get_size]
+ $v -acquire
+ $v -delete
+ }
+
+ set avrule_bits [list \
+ avrule_allow $::QPOL_RULE_ALLOW \
+ avrule_auditallow $::QPOL_RULE_AUDITALLOW \
+ avrule_dontaudit $::QPOL_RULE_DONTAUDIT \
+ avrule_neverallow $::QPOL_RULE_NEVERALLOW \
+ ]
+ foreach {key bit} $avrule_bits {
+ if {$bit == $::QPOL_RULE_NEVERALLOW && ![is_capable "neverallow"]} {
+ # neverallow rules have not yet been loaded
+ set policy_stats($key) 0
+ } else {
+ set i [$::ApolTop::qpolicy get_avrule_iter $bit]
+ set policy_stats($key) [$i get_size]
+ $i -acquire
+ $i -delete
+ }
+ }
+
+ set terule_bits [list \
+ type_trans $::QPOL_RULE_TYPE_TRANS \
+ type_member $::QPOL_RULE_TYPE_CHANGE \
+ type_change $::QPOL_RULE_TYPE_MEMBER \
+ ]
+ foreach {key bit} $terule_bits {
+ set i [$::ApolTop::qpolicy get_avrule_iter $bit]
+ set policy_stats($key) [$i get_size]
+ $i -acquire
+ $i -delete
+ }
+
+ set policy_stats_summary ""
+ append policy_stats_summary "Classes: $policy_stats(classes) "
+ append policy_stats_summary "Perms: $policy_stats(perms) "
+ append policy_stats_summary "Types: $policy_stats(types) "
+ append policy_stats_summary "Attribs: $policy_stats(attribs) "
+ set num_te_rules [expr {$policy_stats(avrule_allow) + $policy_stats(avrule_auditallow) +
+ $policy_stats(avrule_dontaudit) + $policy_stats(avrule_neverallow) +
+ $policy_stats(type_trans) + $policy_stats(type_member) +
+ $policy_stats(type_change)}]
+ if {![is_capable "neverallow"]} {
+ append num_te_rules "+"
+ }
+ append policy_stats_summary "AV + TE rules: $num_te_rules "
+ append policy_stats_summary "Roles: $policy_stats(roles) "
+ append policy_stats_summary "Users: $policy_stats(users)"
+}
+
+############### callbacks for top-level menu items ###############
+
+proc ApolTop::_open_policy {} {
+ variable last_policy_path
+ Apol_Open_Policy_Dialog::getPolicyPath $last_policy_path
+}
+
+proc ApolTop::_user_close_policy {} {
+ variable last_policy_path
+
+ _close_policy
+ set last_policy_path {}
+}
+
+proc ApolTop::_close_policy {} {
+ variable policy_version_string {}
+ variable policy_stats_summary {}
+
+ wm title . "SELinux Policy Analysis"
+ set i 0
+ Apol_Progress_Dialog::wait "apol" "Closing policy." \
+ {
+ variable tabs
+ foreach tab $tabs {
+ if {[catch [lindex $tab 0]::close]} {
+ set i [expr $i+2]
+ }
+ }
+ Apol_Perms_Map::close
+ variable policy
+ if {$policy != {}} {
+ $policy -acquire
+ $policy -delete
+ set policy {}
+ variable qpolicy {}
+ }
+ }
+
+ variable mainframe
+ $mainframe setmenustate tag_policy_open disabled
+ $mainframe setmenustate tag_perm_map_open disabled
+
+ _toplevel_enable_tabs tag_conditionals normal
+ _toplevel_enable_tabs tag_mls normal
+ _toplevel_enable_tabs tag_source normal
+}
+
+proc ApolTop::_exit {} {
+ variable policy
+ if {$policy != {}} {
+ _close_policy
+ }
+
+ Apol_File_Contexts::close
+ _write_configuration_file
+ exit
+}
+
+proc ApolTop::_copy {} {
+ set w [getCurrentTextWidget]
+ if {$w != {} && [$w tag ranges sel] != {}} {
+ set data [$w get sel.first sel.last]
+ clipboard clear
+ clipboard append -- $data
+ }
+}
+
+proc ApolTop::_select_all {} {
+ set w [getCurrentTextWidget]
+ if {$w != {}} {
+ $w tag add sel 1.0 end
+ }
+}
+
+proc ApolTop::_find {} {
+ Apol_Find::find
+}
+
+proc ApolTop::_goto {} {
+ Apol_Goto::goto
+}
+
+proc ApolTop::_open_query_file {} {
+ set types {
+ {"Query files" {$ApolTop::query_file_ext}}
+ }
+ set query_file [tk_getOpenFile -filetypes $types -title "Open Apol Query" \
+ -defaultextension $ApolTop::query_file_ext -parent .]
+ if {$query_file != {}} {
+ if {[catch {::open $query_file r} f]} {
+ tk_messageBox -icon error -type ok -title "Open Apol Query" \
+ -message "Could not open $query_file: $f"
+ }
+ # Search for the analysis type line
+ while {[gets $f line] >= 0} {
+ set query_id [string trim $line]
+ # Skip empty lines and comments
+ if {$query_id == {} || [string index $query_id 0] == "#"} {
+ continue
+ }
+ break
+ }
+
+ variable tabs
+ foreach tab $tabs {
+ if {$query_id == [lindex $tab 0] && [lsearch [lindex $tab 2] "tag_query_saveable"] >= 0} {
+ if {[catch {${query_id}::load_query_options $f} err]} {
+ tk_messageBox -icon error -type ok -title "Open Apol Query" \
+ -message $err
+ } else {
+ setCurrentTab $query_id
+ }
+ return
+ }
+ }
+ tk_messageBox -icon error -type ok -title "Open Apol Query" \
+ -message "The query criteria file could not be read and may be corrupted."
+ close $f
+ }
+}
+
+proc ApolTop::_save_query_file {} {
+ set types {
+ {"Query files" {$ApolTop::query_file_ext}}
+ }
+ set query_file [tk_getSaveFile -title "Save Apol Query" \
+ -defaultextension $ApolTop::query_file_ext \
+ -filetypes $types -parent .]
+ if {$query_file != {}} {
+ if {[catch {::open $query_file w} f]} {
+ tk_messageBox -icon error -type ok -title "Save Apol Query" \
+ -message "Could not save $query_file: $f"
+ }
+ if {[catch {puts $f [getCurrentTab]} err]} {
+ tk_messageBox -icon error -type ok -title "Save Apol Query" \
+ -message $err
+ }
+ if {[catch {[getCurrentTab]::save_query_options $f $query_file} err]} {
+ tk_messageBox -icon error -type ok -title "Save Apol Query" \
+ -message $err
+ }
+ close $f
+ }
+}
+
+proc ApolTop::_show_policy_summary {} {
+ variable policy_version_string
+ variable policy_stats
+
+ if {![regexp -- {^([^\(]+) \(([^,]+), ([^\)]+)} $ApolTop::policy_version_string -> policy_version policy_type policy_mls_type]} {
+ set policy_version $ApolTop::policy_version_string
+ set policy_type "unknown"
+ set policy_mls_type "unknown"
+ }
+ set policy_version [string trim $policy_version]
+
+ destroy .policy_statsbox
+ set dialog [Dialog .policy_statsbox -separator 1 -title "Policy Summary" \
+ -modal none -parent .]
+ $dialog add -text Close -command [list destroy $dialog]
+
+ set w [$dialog getframe]
+
+ label $w.title -text "Policy Summary Statistics"
+ set f [frame $w.summary]
+ label $f.l -justify left -text " Policy Version:\n Policy Type:\n MLS Status:"
+ label $f.r -justify left -text "$policy_version\n$policy_type\n$policy_mls_type"
+ grid $f.l $f.r -sticky w
+ grid configure $f.r -padx 30
+ grid $w.title - -sticky w -padx 8
+ grid $f - -sticky w -padx 8
+ grid [Separator $w.sep] - -sticky ew -pady 5
+
+ set f [frame $w.left]
+ set i 0
+ foreach {title block} {
+ "Number of Classes and Permissions" {
+ "Object Classes" classes
+ "Common Permissions" commons
+ "Permissions" perms
+ }
+ "Number of Types and Attributes" {
+ "Types" types
+ "Attributes" attribs
+ }
+ "Number of Type Enforcement Rules" {
+ "allows" avrule_allow
+ "auditallows" avrule_auditallow
+ "dontaudits" avrule_dontaudit
+ "neverallows" avrule_neverallow
+ "type_transitions" type_trans
+ "type_members" type_member
+ "type_changes" type_change
+ }
+ "Number of Roles" {
+ "Roles" roles
+ }
+ "Number of RBAC Rules" {
+ "allows" role_allow
+ "role_transitions" role_trans
+ }
+ } {
+ set ltext "$title:"
+ set rtext {}
+ foreach {l r} $block {
+ append ltext "\n $l:"
+ if {$r != "avrule_neverallow" || [is_capable "neverallow"]} {
+ append rtext "\n$policy_stats($r)"
+ } else {
+ append rtext "\nN/A"
+ }
+ }
+ label $f.l$i -justify left -text $ltext
+ label $f.r$i -justify left -text $rtext
+ grid $f.l$i $f.r$i -sticky w -padx 4 -pady 2
+ incr i
+ }
+
+ set i 0
+ set g [frame $w.right]
+ foreach {title block} {
+ "Number of Users" {
+ "Users" users
+ }
+ "Number of Booleans" {
+ "Booleans" bools
+ }
+ "Number of MLS Components" {
+ "Sensitivities" sens
+ "Categories" cats
+ }
+ "Number of MLS Rules" {
+ "range_transitions" range_trans
+ }
+ "Number of Initial SIDs" {
+ "SIDs" sids
+ }
+ "Number of OContexts" {
+ "PortCons" portcons
+ "NetIfCons" netifcons
+ "NodeCons" nodecons
+ "GenFSCons" genfscons
+ "fs_use statements" fs_uses
+ }
+ } {
+ set ltext "$title:"
+ set rtext {}
+ foreach {l r} $block {
+ append ltext "\n $l:"
+ append rtext "\n$policy_stats($r)"
+ }
+ label $g.l$i -justify left -text $ltext
+ label $g.r$i -justify left -text $rtext
+ grid $g.l$i $g.r$i -sticky w -padx 4 -pady 2
+ incr i
+ }
+ grid $f $g -sticky nw -padx 4
+ $dialog draw
+}
+
+proc ApolTop::_open_perm_map_from_file {} {
+ if {[Apol_Perms_Map::openPermMapFromFile]} {
+ variable mainframe
+ $mainframe setmenustate tag_perm_map_open normal
+ }
+}
+
+# Return non-zero if a permission map was found and opened, zero if
+# not.
+proc ApolTop::openDefaultPermMap {} {
+ if {[Apol_Perms_Map::openDefaultPermMap]} {
+ variable mainframe
+ $mainframe setmenustate tag_perm_map_open normal
+ return 1
+ }
+ return 0
+}
+
+proc ApolTop::_save_perm_map {} {
+ Apol_Perms_Map::savePermMap
+}
+
+proc ApolTop::_save_perm_map_as {} {
+ Apol_Perms_Map::savePermMapAs
+}
+
+proc ApolTop::_save_perm_map_default {} {
+ Apol_Perms_Map::saveDefaultPermMap
+}
+
+proc ApolTop::_show_file {title file_name} {
+ set helpfile [file join [tcl_config_get_install_dir] $file_name]
+ if {[catch {::open $helpfile} f]} {
+ set info $f
+ } else {
+ set info [read $f]
+ close $f
+ }
+ Apol_Widget::showPopupParagraph $title $info
+}
+
+proc ApolTop::_about {} {
+ if {[winfo exists .apol_about]} {
+ raise .apol_about
+ } else {
+ variable apol_icon
+
+ Dialog .apol_about -cancel 0 -default 0 -image $apol_icon \
+ -modal none -parent . -separator 1 -title "About apol"
+ set f [.apol_about getframe]
+ set l1 [label $f.l1 -text "apol [tcl_config_get_version]" -height 2]
+ set label_font [$l1 cget -font]
+ # Tk 8.4 differs from 8.5 in how fonts are handled
+ if {[llength $label_font] > 1} {
+ foreach {name size} [$l1 cget -font] {break}
+ incr size 6
+ $l1 configure -font [list $name $size bold]
+ }
+ set l2 [label $f.l2 -text "Security Policy Analysis Tool for Security Enhanced Linux\n${::COPYRIGHT_INFO}\nhttp://oss.tresys.com/projects/setools"]
+ pack $l1 $l2
+ .apol_about add -text "Close" -command [list destroy .apol_about]
+ .apol_about draw
+ }
+}
+
+##### functions that load and write user's configuration file #####
+
+proc ApolTop::_load_fonts {} {
+ variable title_font
+ variable dialog_font
+ variable general_font
+ variable text_font
+
+ tk scaling -displayof . 1.0
+ # First set all fonts in general; then change specific fonts
+ if {$general_font == ""} {
+ set general_font "Helvetica 10"
+ }
+ option add *Font $general_font
+ if {$title_font == {}} {
+ set title_font "Helvetica 10 bold italic"
+ }
+ option add *TitleFrame.l.font $title_font
+ if {$dialog_font == {}} {
+ set dialog_font "Helvetica 10"
+ }
+ option add *Dialog*font $dialog_font
+ option add *Dialog*TitleFrame.l.font $title_font
+ if {$text_font == ""} {
+ set text_font "fixed"
+ }
+ option add *text*font $text_font
+}
+
+# Reads in user data from their $HOME/.apol file
+proc ApolTop::_read_configuration_file {} {
+ variable dot_apol_file
+ variable recent_files
+
+ # if it doesn't exist, it will be created later
+ if {![file exists $dot_apol_file]} {
+ return
+ }
+
+ if {[catch {::open $dot_apol_file r} f]} {
+ tk_messageBox -icon error -type ok -title "apol" \
+ -message "Could not open $dot_apol_file: $f"
+ return
+ }
+
+ while {![eof $f]} {
+ set option [string trim [gets $f]]
+ if {$option == {} || [string compare -length 1 $option "\#"] == 0} {
+ continue
+ }
+ set value [string trim [gets $f]]
+ if {[eof $f]} {
+ puts stderr "EOF reached while reading $option"
+ break
+ }
+ if {$value == {}} {
+ puts stderr "Empty value for option $option"
+ continue
+ }
+ switch -- $option {
+ "\[window_height\]" {
+ if {[string is integer -strict $value] != 1} {
+ puts stderr "window_height was not given as an integer and is ignored"
+ break
+ }
+ variable mainframe_height $value
+ }
+ "\[window_width\]" {
+ if {[string is integer -strict $value] != 1} {
+ puts stderr "window_width was not given as an integer and is ignored"
+ break
+ }
+ variable mainframe_width $value
+ }
+ "\[title_font\]" {
+ variable title_font $value
+ }
+ "\[dialog_font\]" {
+ variable dialog_font $value
+ }
+ "\[text_font\]" {
+ variable text_font $value
+ }
+ "\[general_font\]" {
+ variable general_font $value
+ }
+ "\[show_fake_attrib_warning\]" {
+ variable show_fake_attrib_warning $value
+ }
+
+ # The form of [max_recent_file] is a single line that
+ # follows containing an integer with the max number of
+ # recent files to keep. The default is 5 if this is not
+ # specified. The minimum is 2.
+ "\[max_recent_files\]" {
+ if {[string is integer -strict $value] != 1} {
+ puts stderr "max_recent_files was not given as an integer and is ignored"
+ } else {
+ if {$value < 2} {
+ variable max_recent_files 2
+ } else {
+ variable max_recent_files $value
+ }
+ }
+ }
+ # The form of this key in the .apol file is as such
+ #
+ # recent_files
+ # 5 (# indicating how many file names follow)
+ # policy_path_0
+ # policy_path_1
+ # ...
+ "recent_files" {
+ if {[string is integer -strict $value] != 1} {
+ puts stderr "Number of recent files was not given as an integer and was ignored."
+ continue
+ } elseif {$value < 0} {
+ puts stderr "Number of recent was less than 0 and was ignored."
+ continue
+ }
+ while {$value > 0} {
+ incr value -1
+ set line [gets $f]
+ if {[eof $f]} {
+ puts stderr "EOF reached trying to read recent files."
+ break
+ }
+ if {[llength $line] == 1} {
+ # reading older recent files, before advent of
+ # policy_path
+ set ppath [new_apol_policy_path_t $::APOL_POLICY_PATH_TYPE_MONOLITHIC $line NULL]
+ $ppath -acquire
+ } else {
+ foreach {path_type primary modules} $line {break}
+ if {[catch {list_to_policy_path $path_type $primary $modules} ppath]} {
+ puts stderr "Invalid policy path line: $line"
+ continue
+ }
+ }
+ lappend recent_files $ppath
+ }
+ }
+ }
+ }
+ close $f
+}
+
+# Saves user data in their $HOME/.apol file
+proc ApolTop::_write_configuration_file {} {
+ variable dot_apol_file
+ variable recent_files
+ variable text_font
+ variable title_font
+ variable dialog_font
+ variable general_font
+
+ if {[catch {::open $dot_apol_file w} f]} {
+ tk_messageBox -icon error -type ok -title "apol" \
+ -message "Could not open $dot_apol_file for writing: $f"
+ return
+ }
+ puts $f "recent_files"
+ puts $f [llength $recent_files]
+ foreach r $recent_files {
+ puts $f [policy_path_to_list $r]
+ }
+
+ puts $f "\n"
+ puts $f "# Font format: family ?size? ?style? ?style ...?"
+ puts $f "# Possible values for the style arguments are as follows:"
+ puts $f "# normal bold roman italic underline overstrike\n#\n#"
+ puts $f "# NOTE: When configuring fonts, remember to remove the following "
+ puts $f "# \[window height\] and \[window width\] entries before starting apol. "
+ puts $f "# Not doing this may cause widgets to be obscured when running apol."
+ puts $f "\[general_font\]"
+ if {$general_font == {}} {
+ puts $f "Helvetica 10"
+ } else {
+ puts $f "$general_font"
+ }
+ puts $f "\[title_font\]"
+ if {$title_font == {}} {
+ puts $f "Helvetica 10 bold italic"
+ } else {
+ puts $f "$title_font"
+ }
+ puts $f "\[dialog_font\]"
+ if {$dialog_font == {}} {
+ puts $f "Helvetica 10"
+ } else {
+ puts $f "$dialog_font"
+ }
+ puts $f "\[text_font\]"
+ if {$text_font == {}} {
+ puts $f "fixed"
+ } else {
+ puts $f "$text_font"
+ }
+ puts $f "\[window_height\]"
+ puts $f [winfo height .]
+ puts $f "\[window_width\]"
+ puts $f [winfo width .]
+ puts $f "\[show_fake_attrib_warning\]"
+ variable show_fake_attrib_warning
+ puts $f $show_fake_attrib_warning
+ puts $f "\[max_recent_files\]"
+ variable max_recent_files
+ puts $f $max_recent_files
+ close $f
+}
+
+#######################################################
+# Start script here
+
+proc ApolTop::main {} {
+ variable notebook
+
+ tcl_config_init
+
+ # Prevent the application from responding to incoming send
+ # requests and sending outgoing requests. This way any other
+ # applications that can connect to our X server cannot send
+ # harmful scripts to our application.
+ rename send {}
+
+ if {[catch {package require BWidget}]} {
+ tk_messageBox -icon error -type ok -title "Apol Startup" -message \
+ "The BWidget package could not be found. Ensure that BWidget is installed in a location that Tcl/Tk can read."
+ exit -1
+ }
+
+ wm withdraw .
+ wm title . "SELinux Policy Analysis"
+ wm protocol . WM_DELETE_WINDOW ApolTop::_exit
+ variable default_bg_color [. cget -background]
+
+ # Read apol's default settings file, gather all font information,
+ # create the gui and then load recent files into the menu.
+ catch {tcl_config_patch_bwidget}
+ _load_fonts
+ _read_configuration_file
+ _create_toplevel
+ bind . <Button-1> {focus %W}
+ bind . <Button-2> {focus %W}
+ bind . <Button-3> {focus %W}
+ _build_recent_files_menu
+
+ set icon_file [file join [tcl_config_get_install_dir] apol.gif]
+ if {![catch {image create photo -file $icon_file} icon]} {
+ catch {wm iconphoto . -default $icon}
+ }
+ variable apol_icon $icon
+
+ variable mainframe_width [$notebook cget -width]
+ variable mainframe_height [$notebook cget -height]
+ wm geom . ${mainframe_width}x${mainframe_height}
+
+ wm deiconify .
+ raise .
+ focus .
+}
+
+proc handle_args {argv0 argv} {
+ set argvp 0
+ while {$argvp < [llength $argv]} {
+ set arg [lindex $argv $argvp]
+ switch -- $arg {
+ "-h" - "--help" { print_help $argv0 verbose; exit }
+ "-V" - "--version" { print_version_info; exit }
+ "--" { incr argvp; break }
+ default {
+ if {[string index $arg 0] != "-"} {
+ break
+ } else {
+ puts stderr "$argv0: unrecognized option `$arg'"
+ print_help $argv0 brief
+ exit 1
+ }
+ }
+ }
+ incr argvp
+ }
+
+ set arglen [expr [llength $argv]-$argvp]
+ set ppath {}
+ if {$arglen <= 0} {
+ return {}
+ } elseif {$arglen == 1} {
+ set path_type $::APOL_POLICY_PATH_TYPE_MONOLITHIC
+ set policy_file [lindex $argv $argvp]
+ set mod_paths [list_to_str_vector {}]
+ if {[apol_file_is_policy_path_list $policy_file]} {
+ set ppath [new_apol_policy_path_t $policy_file]
+ }
+ } elseif {$arglen > 1} {
+ set path_type $::APOL_POLICY_PATH_TYPE_MODULAR
+ set policy_file {}
+ foreach f [lrange $argv $argvp end] {
+ if {[catch {Apol_Open_Policy_Dialog::getModuleInfo $f} modinfo]} {
+ tk_messageBox -icon error -type ok -title "Module access error" -message $modinfo
+ } else {
+ foreach {name vers type} $modinfo {break}
+ if {$type == 1} { ;# This file is a base 'module'
+ if {$policy_file != {} && $policy_file != $f} {
+ set rsp [tk_messageBox -icon error -type okcancel -title "Open Module" -message "Multiple base entries found." -detail "Current file: $policy_file\n\nNew file: $f\n\nClick OK to ignore new file, Cancel to exit"]
+ if {$rsp == "cancel"} { exit 1}
+ } else {
+ set policy_file $f
+ }
+ } else { ;# Append regular modules to the list.
+ lappend module_list $f
+ }
+ }
+ }
+ set mod_paths [list_to_str_vector $module_list]
+ }
+
+ if {$ppath == {}} {
+ set ppath [new_apol_policy_path_t $path_type $policy_file $mod_paths]
+ }
+ if {$ppath == {}} {
+ puts stderr "Error loading $policy_file."
+ } else {
+ $ppath -acquire
+ }
+ return $ppath
+}
+
+proc print_help {program_name verbose} {
+ puts "Usage: $program_name \[OPTIONS\] \[POLICY ...\]\n"
+ if {$verbose != "verbose"} {
+ puts "\tTry $program_name --help for more help.\n"
+ } else {
+ puts "Policy Analysis tool for Security Enhanced Linux.\n"
+ puts " -h, --help print this help text and exit"
+ puts " -V, --version print version information and exit\n"
+ }
+}
+
+proc print_version_info {} {
+ puts "apol [tcl_config_get_version]\n$::COPYRIGHT_INFO"
+}
+
+proc print_init {s} {
+ puts -nonewline $s
+ flush stdout
+}
+
+if {[catch {tcl_config_init_libraries}]} {
+ puts stderr "FAILED. The SETools libraries could not be found in any of these subdirectories:\n\t[join $auto_path "\n\t"]"
+ exit -1
+}
+
+print_init "Initializing Tk... "
+if {[catch {package require Tk}]} {
+ puts stderr "FAILED. This library could not be found in any of these subdirectories:\n\t[join $auto_path "\n\t"]"
+ puts stderr "This may indicate a problem with the tcl package's auto_path variable.\n"
+ exit -1
+}
+puts "done."
+
+set path [handle_args $argv0 $argv]
+ApolTop::main
+if {$path != {}} {
+ after idle [list ApolTop::openPolicyPath $path]
+}
diff --git a/apol/transflow_module.tcl b/apol/transflow_module.tcl
new file mode 100644
index 0000000..ff46f9b
--- /dev/null
+++ b/apol/transflow_module.tcl
@@ -0,0 +1,1156 @@
+# Copyright (C) 2003-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
+
+namespace eval Apol_Analysis_transflow {
+ variable vals
+ variable widgets
+ Apol_Analysis::registerAnalysis "Apol_Analysis_transflow" "Transitive Information Flow"
+}
+
+proc Apol_Analysis_transflow::create {options_frame} {
+ variable vals
+ variable widgets
+
+ _reinitializeVals
+
+ set dir_tf [TitleFrame $options_frame.dir -text "Direction"]
+ pack $dir_tf -side left -padx 2 -pady 2 -expand 0 -fill y
+ set dir_to [radiobutton [$dir_tf getframe].to -text "To" \
+ -value $::APOL_INFOFLOW_IN \
+ -variable Apol_Analysis_transflow::vals(dir)]
+ set dir_from [radiobutton [$dir_tf getframe].from -text "From" \
+ -value $::APOL_INFOFLOW_OUT \
+ -variable Apol_Analysis_transflow::vals(dir)]
+ pack $dir_to $dir_from -anchor w
+
+ set req_tf [TitleFrame $options_frame.req -text "Required Parameters"]
+ pack $req_tf -side left -padx 2 -pady 2 -expand 0 -fill y
+ set l [label [$req_tf getframe].l -text "Starting type"]
+ pack $l -anchor w
+ set widgets(type) [Apol_Widget::makeTypeCombobox [$req_tf getframe].type]
+ pack $widgets(type)
+
+ set filter_tf [TitleFrame $options_frame.filter -text "Optional Result Filters"]
+ pack $filter_tf -side left -padx 2 -pady 2 -expand 1 -fill both
+ set advanced_f [frame [$filter_tf getframe].advanced]
+ pack $advanced_f -side left -anchor nw
+ set widgets(advanced_enable) [checkbutton $advanced_f.enable -text "Use advanced filters" \
+ -variable Apol_Analysis_transflow::vals(advanced:enable)]
+ pack $widgets(advanced_enable) -anchor w
+ set widgets(advanced) [button $advanced_f.b -text "Advanced Filters" \
+ -command Apol_Analysis_transflow::_createAdvancedDialog \
+ -state disabled]
+ pack $widgets(advanced) -anchor w -padx 4
+ trace add variable Apol_Analysis_transflow::vals(advanced:enable) write \
+ Apol_Analysis_transflow::_toggleAdvancedSelected
+ set widgets(regexp) [Apol_Widget::makeRegexpEntry [$filter_tf getframe].end]
+ $widgets(regexp).cb configure -text "Filter result types using regular expression"
+ pack $widgets(regexp) -side left -anchor nw -padx 8
+}
+
+proc Apol_Analysis_transflow::open {} {
+ variable vals
+ variable widgets
+ Apol_Widget::resetTypeComboboxToPolicy $widgets(type)
+ set vals(intermed:inc) [Apol_Types::getTypes]
+ set vals(intermed:inc_all) $vals(intermed:inc)
+ set vals(classes:displayed) {}
+ foreach class [Apol_Class_Perms::getClasses] {
+ foreach perm [Apol_Class_Perms::getPermsForClass $class] {
+ set vals(perms:$class:$perm) 1
+ }
+ lappend vals(classes:displayed) $class
+ }
+}
+
+proc Apol_Analysis_transflow::close {} {
+ variable widgets
+ _reinitializeVals
+ _reinitializeWidgets
+ Apol_Widget::clearTypeCombobox $widgets(type)
+}
+
+proc Apol_Analysis_transflow::getInfo {} {
+ return "This analysis generates the results of a Transitive Information Flow
+analysis beginning from the starting type selected. The results of
+the analysis are presented in tree form with the root of the tree
+being the start point for the analysis.
+
+\nEach child node in the tree represents a type in the current policy
+for which there is a transitive information flow to or from its parent
+node. If flow 'To' is selected the information flows from the child
+to the parent. If flow 'From' is selected then information flows from
+the parent to the child.
+
+\nThe results of the analysis may be optionally filtered by object
+classes and/or permissions, intermediate types, or an end type regular
+expression.
+
+\nNOTE: For any given generation, if the parent and the child are the
+same, the child cannot be opened. This avoids cyclic analyses.
+
+\nFor additional help on this topic select \"Information Flow Analysis\"
+from the help menu."
+}
+
+proc Apol_Analysis_transflow::newAnalysis {} {
+ if {[set rt [_checkParams]] != {}} {
+ return $rt
+ }
+ set results [_analyze]
+ set f [_createResultsDisplay]
+ _renderResults $f $results
+ $results -acquire
+ $results -delete
+ return {}
+}
+
+proc Apol_Analysis_transflow::updateAnalysis {f} {
+ if {[set rt [_checkParams]] != {}} {
+ return $rt
+ }
+ set results [_analyze]
+ _clearResultsDisplay $f
+ _renderResults $f $results
+ $results -acquire
+ $results -delete
+ return {}
+}
+
+proc Apol_Analysis_transflow::reset {} {
+ _reinitializeVals
+ _reinitializeWidgets
+ open
+}
+
+proc Apol_Analysis_transflow::switchTab {query_options} {
+ variable vals
+ variable widgets
+ array set vals $query_options
+ _reinitializeWidgets
+}
+
+proc Apol_Analysis_transflow::saveQuery {channel} {
+ variable vals
+ variable widgets
+ foreach {key value} [array get vals] {
+ switch -glob -- $key {
+ find_more:* -
+ intermed:inc* -
+ intermed:exc -
+ classes:title {}
+ classes:displayed {}
+ perms:* {
+ # only write permissions that have been excluded
+ if {$value == 0} {
+ puts $channel "$key $value"
+ }
+ }
+ default {
+ puts $channel "$key $value"
+ }
+ }
+ }
+ set type [Apol_Widget::getTypeComboboxValueAndAttrib $widgets(type)]
+ puts $channel "type [lindex $type 0]"
+ puts $channel "type:attrib [lindex $type 1]"
+ set use_regexp [Apol_Widget::getRegexpEntryState $widgets(regexp)]
+ set regexp [Apol_Widget::getRegexpEntryValue $widgets(regexp)]
+ puts $channel "regexp:enable $use_regexp"
+ puts $channel "regexp $regexp"
+}
+
+proc Apol_Analysis_transflow::loadQuery {channel} {
+ variable vals
+ set intermed_exc {}
+ set perms_disabled {}
+ while {[gets $channel line] >= 0} {
+ set line [string trim $line]
+ # Skip empty lines and comments
+ if {$line == {} || [string index $line 0] == "#"} {
+ continue
+ }
+ set key {}
+ set value {}
+ regexp -line -- {^(\S+)( (.+))?} $line -> key --> value
+ switch -glob -- $key {
+ intermed:exc_all {
+ set intermed_exc $value
+ }
+ perms:* {
+ set perms_disabled [concat $perms_disabled $key $value]
+ }
+ default {
+ set vals($key) $value
+ }
+ }
+ }
+
+ # fill in only types and classes found within the current policy
+ open
+
+ set vals(intermed:exc_all) {}
+ set vals(intermed:exc) {}
+ foreach t $intermed_exc {
+ set i [lsearch $vals(intermed:inc_all) $t]
+ if {$i >= 0} {
+ lappend vals(intermed:exc_all) $t
+ lappend vals(intermed:exc) $t
+ set vals(intermed:inc_all) [lreplace $vals(intermed:inc_all) $i $i]
+ set i [lsearch $vals(intermed:inc) $t]
+ set vals(intermed:inc) [lreplace $vals(intermed:inc) $i $i]
+ }
+ }
+ set vals(intermed:exc_all) [lsort $vals(intermed:exc_all)]
+ set vals(intermed:exc) [lsort $vals(intermed:exc)]
+
+ foreach {key value} $perms_disabled {
+ if {[info exists vals($key)]} {
+ set vals($key) $value
+ }
+ }
+ set vals(classes:displayed) {}
+ foreach class [Apol_Class_Perms::getClasses] {
+ set all_disabled 1
+ foreach perm_key [array names vals perms:$class:*] {
+ if {$vals($perm_key)} {
+ set all_disabled 0
+ break
+ }
+ }
+ if {$all_disabled} {
+ lappend vals(classes:displayed) "$class (excluded)"
+ } else {
+ lappend vals(classes:displayed) $class
+ }
+ }
+ _reinitializeWidgets
+}
+
+proc Apol_Analysis_transflow::getTextWidget {tab} {
+ return [$tab.right getframe].res.tb
+}
+
+proc Apol_Analysis_transflow::appendResultsNodes {tree parent_node results} {
+ _createResultsNodes $tree $parent_node $results 0
+}
+
+proc Apol_Analysis_transflow::renderPath {res path_num path} {
+ _renderPath $res $path_num $path
+}
+
+#################### private functions below ####################
+
+proc Apol_Analysis_transflow::_reinitializeVals {} {
+ variable vals
+
+ set vals(dir) $::APOL_INFOFLOW_IN
+ array set vals {
+ type {} type:attrib {}
+
+ regexp:enable 0
+ regexp {}
+
+ advanced:enable 0
+
+ classes:title {}
+ classes:displayed {}
+ classes:threshold_enable 0
+ classes:threshold 1
+
+ intermed:inc {} intermed:inc_all {}
+ intermed:exc {} intermed:exc_all {}
+ intermed:attribenable 0 intermed:attrib {}
+
+ find_more:hours 0 find_more:minutes 0 find_more:seconds 30
+ find_more:limit 20
+ }
+ array unset vals perms:*
+ foreach class [Apol_Class_Perms::getClasses] {
+ foreach perm [Apol_Class_Perms::getPermsForClass $class] {
+ set vals(perms:$class:$perm) 1
+ }
+ }
+}
+
+proc Apol_Analysis_transflow::_reinitializeWidgets {} {
+ variable vals
+ variable widgets
+
+ if {$vals(type:attrib) != {}} {
+ Apol_Widget::setTypeComboboxValue $widgets(type) [list $vals(type) $vals(type:attrib)]
+ } else {
+ Apol_Widget::setTypeComboboxValue $widgets(type) $vals(type)
+ }
+ Apol_Widget::setRegexpEntryValue $widgets(regexp) $vals(regexp:enable) $vals(regexp)
+}
+
+proc Apol_Analysis_transflow::_toggleAdvancedSelected {name1 name2 op} {
+ variable vals
+ variable widgets
+ if {$vals(advanced:enable)} {
+ $widgets(advanced) configure -state normal
+ } else {
+ $widgets(advanced) configure -state disabled
+ }
+}
+
+################# functions that do advanced filters #################
+
+proc Apol_Analysis_transflow::_createAdvancedDialog {} {
+ variable widgets
+ $widgets(advanced) configure -state disabled
+ destroy .transflow_adv
+ variable vals
+
+ # if a permap is not loaded then load the default permap
+ if {[ApolTop::is_policy_open] && ![Apol_Perms_Map::is_pmap_loaded]} {
+ if {![ApolTop::openDefaultPermMap]} {
+ return "This analysis requires that a permission map is loaded."
+ }
+ }
+
+ set d [Dialog .transflow_adv -modal none -separator 1 -title "Transitive Information Flow Advanced Filters" -parent .]
+ $d add -text "Close" -command [list Apol_Analysis_transflow::_closeAdvancedDialog $d]
+
+ set tf [TitleFrame [$d getframe].classes -text "Filter By Object Class Permissions"]
+ pack $tf -side top -expand 1 -fill both -padx 2 -pady 4
+ _createClassFilter [$tf getframe]
+
+ set tf [TitleFrame [$d getframe].types -text "Filter By Intermediate Types"]
+ pack $tf -side top -expand 1 -fill both -padx 2 -pady 4
+ _createIntermedFilter [$tf getframe]
+ set inc [$tf getframe].inc
+ set exc [$tf getframe].exc
+
+ set attrib [frame [$tf getframe].a]
+ grid $attrib - -
+ set attrib_enable [checkbutton $attrib.ae -anchor w \
+ -text "Filter by attribute" \
+ -variable Apol_Analysis_transflow::vals(intermed:attribenable)]
+ set attrib_box [ComboBox $attrib.ab -autopost 1 -entrybg white -width 16 \
+ -values $Apol_Types::attriblist \
+ -textvariable Apol_Analysis_transflow::vals(intermed:attrib)]
+ $attrib_enable configure -command \
+ [list Apol_Analysis_transflow::_attribEnabled $attrib_box]
+ # remove any old traces on the attribute before adding new ones
+ trace remove variable Apol_Analysis_transflow::vals(intermed:attrib) write \
+ [list Apol_Analysis_transflow::_attribChanged]
+ trace add variable Apol_Analysis_transflow::vals(intermed:attrib) write \
+ [list Apol_Analysis_transflow::_attribChanged]
+ pack $attrib_enable -side top -expand 0 -fill x -anchor sw -padx 5 -pady 2
+ pack $attrib_box -side top -expand 1 -fill x -padx 10
+ _attribEnabled $attrib_box
+
+ $d draw
+ $widgets(advanced) configure -state normal
+}
+
+proc Apol_Analysis_transflow::_closeAdvancedDialog {d} {
+ $d withdraw
+}
+
+proc Apol_Analysis_transflow::_createClassFilter {f} {
+ variable vals
+
+ set l1 [label $f.l1 -text "Object Classes"]
+ set l [label $f.l]
+ set vals(classes:title) "Permissions"
+ set l2 [label $f.l2 -textvariable Apol_Analysis_transflow::vals(classes:title)]
+ grid $l1 $l $l2 -sticky w
+
+ set classes [Apol_Widget::makeScrolledListbox $f.c -selectmode extended \
+ -height 12 -width 24 -listvar Apol_Analysis_transflow::vals(classes:displayed)]
+ set sw [ScrolledWindow $f.sw -auto both -bd 2 -relief groove]
+ set perms [ScrollableFrame $sw.perms -height 150 -width 250]
+ $sw setwidget $perms
+ bind $classes.lb <<ListboxSelect>> \
+ [list Apol_Analysis_transflow::_refreshPerm $classes $perms]
+ grid $classes x $sw -sticky nsew
+ update
+ grid propagate $sw 0
+
+ set bb [ButtonBox $f.bb -homogeneous 1 -spacing 4]
+ $bb add -text "Include All Perms" -width 16 -command [list Apol_Analysis_transflow::_setAllPerms $classes $perms 1]
+ $bb add -text "Exclude All Perms" -width 16 -command [list Apol_Analysis_transflow::_setAllPerms $classes $perms 0]
+ grid ^ x $bb -pady 4
+
+ set f [frame $f.f]
+ grid ^ x $f
+ grid configure $f -sticky ew
+ set cb [checkbutton $f.cb -text "Exclude permissions with weights below:" \
+ -variable Apol_Analysis_transflow::vals(classes:threshold_enable)]
+
+ set weight [spinbox $f.threshold -from 1 -to 10 -increment 1 \
+ -width 2 -bg white -justify right \
+ -textvariable Apol_Analysis_transflow::vals(classes:threshold)]
+ # remove any old traces on the threshold checkbutton befored adding new one
+ trace remove variable Apol_Analysis_transflow::vals(classes:threshold_enable) write \
+ [list Apol_Analysis_transflow::_thresholdChanged $weight]
+ trace add variable Apol_Analysis_transflow::vals(classes:threshold_enable) write \
+ [list Apol_Analysis_transflow::_thresholdChanged $weight]
+ pack $cb $weight -side left
+ _thresholdChanged $weight {} {} {}
+
+ grid columnconfigure $f 0 -weight 0
+ grid columnconfigure $f 1 -weight 0 -pad 4
+ grid columnconfigure $f 2 -weight 1
+}
+
+proc Apol_Analysis_transflow::_refreshPerm {classes perms} {
+ variable vals
+ focus $classes.lb
+ if {[$classes.lb curselection] == {}} {
+ return
+ }
+ set pf [$perms getframe]
+ foreach w [winfo children $pf] {
+ destroy $w
+ }
+
+ foreach {class foo} [$classes.lb get anchor] {break}
+ set i [$classes.lb index anchor]
+ set vals(classes:title) "Permissions for $class"
+
+ foreach perm_key [lsort [array names vals perms:$class:*]] {
+ foreach {foo bar perm} [split $perm_key :] {break}
+ set weight [$::ApolTop::policy get_permmap_weight $class $perm]
+ set l [label $pf.$perm:l -text $perm -anchor w]
+ set inc [checkbutton $pf.$perm:i -text "Include" \
+ -command [list Apol_Analysis_transflow::_togglePerm $class $i] \
+ -variable Apol_Analysis_transflow::vals(perms:$class:$perm)]
+ set w [label $pf.$perm:w -text "Weight: $weight"]
+ grid $l $inc $w -padx 2 -sticky w -pady 4
+ grid configure $w -ipadx 10
+ }
+ grid columnconfigure $pf 0 -minsize 100 -weight 1
+ $perms xview moveto 0
+ $perms yview moveto 0
+}
+
+proc Apol_Analysis_transflow::_togglePerm {class i} {
+ variable vals
+ set all_disabled 1
+ foreach perm_key [array names vals perms:$class:*] {
+ if {$vals($perm_key)} {
+ set all_disabled 0
+ break
+ }
+ }
+ if {$all_disabled} {
+ set vals(classes:displayed) [lreplace $vals(classes:displayed) $i $i "$class (excluded)"]
+ } else {
+ set vals(classes:displayed) [lreplace $vals(classes:displayed) $i $i $class]
+ }
+}
+
+proc Apol_Analysis_transflow::_setAllPerms {classes perms newValue} {
+ variable vals
+ foreach i [$classes.lb curselection] {
+ foreach {class foo} [split [$classes.lb get $i]] {break}
+ foreach perm_key [array names vals perms:$class:*] {
+ set vals($perm_key) $newValue
+ }
+ if {$newValue == 1} {
+ set vals(classes:displayed) [lreplace $vals(classes:displayed) $i $i $class]
+ } else {
+ set vals(classes:displayed) [lreplace $vals(classes:displayed) $i $i "$class (excluded)"]
+ }
+ }
+}
+
+proc Apol_Analysis_transflow::_thresholdChanged {w name1 name2 op} {
+ variable vals
+ if {$vals(classes:threshold_enable)} {
+ $w configure -state normal
+ } else {
+ $w configure -state disabled
+ }
+}
+
+proc Apol_Analysis_transflow::_createIntermedFilter {f} {
+ set l1 [label $f.l1 -text "Included Intermediate Types"]
+ set l2 [label $f.l2 -text "Excluded Intermediate Types"]
+ grid $l1 x $l2 -sticky w
+
+ set inc [Apol_Widget::makeScrolledListbox $f.inc -height 10 -width 24 \
+ -listvar Apol_Analysis_transflow::vals(intermed:inc) \
+ -selectmode extended -exportselection 0]
+ set exc [Apol_Widget::makeScrolledListbox $f.exc -height 10 -width 24 \
+ -listvar Apol_Analysis_transflow::vals(intermed:exc) \
+ -selectmode extended -exportselection 0]
+ set inc_lb [Apol_Widget::getScrolledListbox $inc]
+ set exc_lb [Apol_Widget::getScrolledListbox $exc]
+ set bb [ButtonBox $f.bb -homogeneous 1 -orient vertical -spacing 4]
+ $bb add -text "-->" -width 10 -command [list Apol_Analysis_transflow::_moveToExclude $inc_lb $exc_lb]
+ $bb add -text "<--" -width 10 -command [list Apol_Analysis_transflow::_moveToInclude $inc_lb $exc_lb]
+ grid $inc $bb $exc -sticky nsew
+
+ set inc_bb [ButtonBox $f.inc_bb -homogeneous 1 -spacing 4]
+ $inc_bb add -text "Select All" -command [list $inc_lb selection set 0 end]
+ $inc_bb add -text "Unselect" -command [list $inc_lb selection clear 0 end]
+ set exc_bb [ButtonBox $f.exc_bb -homogeneous 1 -spacing 4]
+ $exc_bb add -text "Select All" -command [list $exc_lb selection set 0 end]
+ $exc_bb add -text "Unselect" -command [list $exc_lb selection clear 0 end]
+ grid $inc_bb x $exc_bb -pady 4
+
+ grid columnconfigure $f 0 -weight 1 -uniform 0 -pad 2
+ grid columnconfigure $f 1 -weight 0 -pad 8
+ grid columnconfigure $f 2 -weight 1 -uniform 0 -pad 2
+}
+
+proc Apol_Analysis_transflow::_moveToExclude {inc exc} {
+ variable vals
+ if {[set selection [$inc curselection]] == {}} {
+ return
+ }
+ foreach i $selection {
+ lappend types [$inc get $i]
+ }
+ set vals(intermed:exc) [lsort [concat $vals(intermed:exc) $types]]
+ set vals(intermed:exc_all) [lsort [concat $vals(intermed:exc_all) $types]]
+ foreach t $types {
+ set i [lsearch $vals(intermed:inc) $t]
+ set vals(intermed:inc) [lreplace $vals(intermed:inc) $i $i]
+ set i [lsearch $vals(intermed:inc_all) $t]
+ set vals(intermed:inc_all) [lreplace $vals(intermed:inc_all) $i $i]
+ }
+ $inc selection clear 0 end
+ $exc selection clear 0 end
+}
+
+proc Apol_Analysis_transflow::_moveToInclude {inc exc} {
+ variable vals
+ if {[set selection [$exc curselection]] == {}} {
+ return
+ }
+ foreach i $selection {
+ lappend types [$exc get $i]
+ }
+ set vals(intermed:inc) [lsort [concat $vals(intermed:inc) $types]]
+ set vals(intermed:inc_all) [lsort [concat $vals(intermed:inc_all) $types]]
+ foreach t $types {
+ set i [lsearch $vals(intermed:exc) $t]
+ set vals(intermed:exc) [lreplace $vals(intermed:exc) $i $i]
+ set i [lsearch $vals(intermed:exc_all) $t]
+ set vals(intermed:exc_all) [lreplace $vals(intermed:exc_all) $i $i]
+ }
+ $inc selection clear 0 end
+ $exc selection clear 0 end
+}
+
+proc Apol_Analysis_transflow::_attribEnabled {cb} {
+ variable vals
+ if {$vals(intermed:attribenable)} {
+ $cb configure -state normal
+ _filterTypeLists $vals(intermed:attrib)
+ } else {
+ $cb configure -state disabled
+ _filterTypeLists ""
+ }
+}
+
+proc Apol_Analysis_transflow::_attribChanged {name1 name2 op} {
+ variable vals
+ if {$vals(intermed:attribenable)} {
+ _filterTypeLists $vals(intermed:attrib)
+ }
+}
+
+proc Apol_Analysis_transflow::_filterTypeLists {attrib} {
+ variable vals
+ if {$attrib != {}} {
+ set typesList {}
+ if {[Apol_Types::isAttributeInPolicy $attrib]} {
+ set qpol_type_datum [new_qpol_type_t $::ApolTop::qpolicy $attrib]
+ set i [$qpol_type_datum get_type_iter $::ApolTop::qpolicy]
+ foreach t [iter_to_list $i] {
+ set t [qpol_type_from_void $t]
+ lappend typesList [$t get_name $::ApolTop::qpolicy]
+ }
+ $i -acquire
+ $i -delete
+ }
+ if {$typesList == {}} {
+ # unknown attribute, so don't change listboxes
+ return
+ }
+ set vals(intermed:inc) {}
+ set vals(intermed:exc) {}
+ foreach t $typesList {
+ if {[lsearch $vals(intermed:inc_all) $t] >= 0} {
+ lappend vals(intermed:inc) $t
+ }
+ if {[lsearch $vals(intermed:exc_all) $t] >= 0} {
+ lappend vals(intermed:exc) $t
+ }
+ }
+ set vals(intermed:inc) [lsort $vals(intermed:inc)]
+ set vals(intermed:exc) [lsort $vals(intermed:exc)]
+ } else {
+ set vals(intermed:inc) $vals(intermed:inc_all)
+ set vals(intermed:exc) $vals(intermed:exc_all)
+ }
+}
+
+#################### functions that do analyses ####################
+
+proc Apol_Analysis_transflow::_checkParams {} {
+ variable vals
+ variable widgets
+ if {![ApolTop::is_policy_open]} {
+ return "No current policy file is opened."
+ }
+ set type [Apol_Widget::getTypeComboboxValueAndAttrib $widgets(type)]
+ if {[lindex $type 0] == {}} {
+ return "No type was selected."
+ }
+ if {![Apol_Types::isTypeInPolicy [lindex $type 0]]} {
+ return "[lindex $type 0] is not a type within the policy."
+ }
+ set vals(type) [lindex $type 0]
+ set vals(type:attrib) [lindex $type 1]
+ set use_regexp [Apol_Widget::getRegexpEntryState $widgets(regexp)]
+ set regexp [Apol_Widget::getRegexpEntryValue $widgets(regexp)]
+ if {$use_regexp && $regexp == {}} {
+ return "No regular expression provided."
+ }
+ set vals(regexp:enable) $use_regexp
+ set vals(regexp) $regexp
+
+ # if a permap is not loaded then load the default permap
+ if {![Apol_Perms_Map::is_pmap_loaded]} {
+ if {![ApolTop::openDefaultPermMap]} {
+ return "This analysis requires that a permission map is loaded."
+ }
+ apol_tcl_clear_info_string
+ }
+
+ if {$vals(advanced:enable)} {
+ if {$vals(intermed:inc_all) == {}} {
+ return "At least one intermediate type must be selected."
+ }
+ if {[lsearch $vals(intermed:exc_all) $vals(type)] >= 0} {
+ return "The starting type is on the excluded intermediate types list"
+ }
+ set num_perms 0
+ foreach perm_key [array names vals perms:*] {
+ if {$vals($perm_key)} {
+ set num_perms 1
+ break
+ }
+ }
+ if {$num_perms == 0} {
+ return "At least one permissions must be enabled."
+ }
+ }
+ return {} ;# all parameters passed, now ready to do search
+}
+
+proc Apol_Analysis_transflow::_analyze {} {
+ variable vals
+ if {$vals(regexp:enable)} {
+ set regexp $vals(regexp)
+ } else {
+ set regexp {}
+ }
+ set threshold {}
+ if {$vals(advanced:enable)} {
+ set intermed $vals(intermed:inc_all)
+ set classperms {}
+ foreach perm_key [array names vals perms:*] {
+ if {$vals($perm_key)} {
+ foreach {foo class perm} [split $perm_key :] {break}
+ lappend classperms $class $perm
+ }
+ }
+ if {$vals(classes:threshold_enable)} {
+ set threshold $vals(classes:threshold)
+ }
+ } else {
+ set intermed {}
+ set classperms {}
+ }
+
+ set q [new_apol_infoflow_analysis_t]
+ $q set_mode $::ApolTop::policy $::APOL_INFOFLOW_MODE_TRANS
+ $q set_dir $::ApolTop::policy $vals(dir)
+ $q set_type $::ApolTop::policy $vals(type)
+ foreach i $intermed {
+ $q append_intermediate $::ApolTop::policy $i
+ }
+ foreach {c p} $classperms {
+ $q append_class_perm $::ApolTop::policy $c $p
+ }
+ if {$threshold != {}} {
+ $q set_min_weight $::ApolTop::policy $threshold
+ }
+ $q set_result_regex $::ApolTop::policy $regexp
+ set results [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ return $results
+}
+
+proc Apol_Analysis_transflow::_analyzeMore {tree node} {
+ # disallow more analysis if this node is the same as its parent
+ set new_start [$tree itemcget $node -text]
+ if {[$tree itemcget [$tree parent $node] -text] == $new_start} {
+ return {}
+ }
+ set g [lindex [$tree itemcget top -data] 0]
+ $g do_more $::ApolTop::policy $new_start
+}
+
+################# functions that control analysis output #################
+
+proc Apol_Analysis_transflow::_createResultsDisplay {} {
+ variable vals
+
+ set f [Apol_Analysis::createResultTab "Trans Flow" [array get vals]]
+
+ set tree_tf [TitleFrame $f.left -text "Transitive Information Flow Tree"]
+ pack $tree_tf -side left -expand 0 -fill y -padx 2 -pady 2
+ set sw [ScrolledWindow [$tree_tf getframe].sw -auto both]
+ set tree [Tree [$sw getframe].tree -width 24 -redraw 1 -borderwidth 0 \
+ -highlightthickness 0 -showlines 1 -padx 0 -bg white]
+ $sw setwidget $tree
+ pack $sw -expand 1 -fill both
+
+ set res_tf [TitleFrame $f.right -text "Transitive Information Flow Results"]
+ pack $res_tf -side left -expand 1 -fill both -padx 2 -pady 2
+ set res [Apol_Widget::makeSearchResults [$res_tf getframe].res]
+ $res.tb tag configure title -font {Helvetica 14 bold}
+ $res.tb tag configure title_type -foreground blue -font {Helvetica 14 bold}
+ $res.tb tag configure find_more -underline 1
+ $res.tb tag configure subtitle -font {Helvetica 10 bold}
+ $res.tb tag configure num -foreground blue -font {Helvetica 10 bold}
+ $res.tb tag bind find_more <Button-1> [list Apol_Analysis_transflow::_findMore $res $tree]
+ $res.tb tag bind find_more <Enter> [list $res.tb configure -cursor hand2]
+ $res.tb tag bind find_more <Leave> [list $res.tb configure -cursor {}]
+ pack $res -expand 1 -fill both
+
+ $tree configure -selectcommand [list Apol_Analysis_transflow::_treeSelect $res]
+ $tree configure -opencmd [list Apol_Analysis_transflow::_treeOpen $tree]
+ return $f
+}
+
+proc Apol_Analysis_transflow::_treeSelect {res tree node} {
+ if {$node != {}} {
+ $res.tb configure -state normal
+ $res.tb delete 0.0 end
+ set data [$tree itemcget $node -data]
+ if {[string index $node 0] == "y"} {
+ _renderResultsTransFlow $res $tree $node [lindex $data 1]
+ } else {
+ # an informational node, whose data has already been rendered
+ eval $res.tb insert end [lindex $data 1]
+ }
+ $res.tb configure -state disabled
+ }
+}
+
+proc Apol_Analysis_transflow::_treeOpen {tree node} {
+ foreach {is_expanded results} [$tree itemcget $node -data] {break}
+ if {[string index $node 0] == "y" && !$is_expanded} {
+ Apol_Progress_Dialog::wait "Transitive Information Flow Analysis" \
+ "Performing Transitive Information Flow Analysis..." \
+ {
+ set new_results [_analyzeMore $tree $node]
+ # mark this node as having been expanded
+ $tree itemconfigure $node -data [list 1 $results]
+ if {$new_results != {}} {
+ _createResultsNodes $tree $node $new_results 1
+ $new_results -acquire
+ $new_results -delete
+ }
+ }
+ }
+}
+
+proc Apol_Analysis_transflow::_clearResultsDisplay {f} {
+ variable vals
+
+ set tree [[$f.left getframe].sw getframe].tree
+ set res [$f.right getframe].res
+ $tree delete [$tree nodes root]
+ Apol_Widget::clearSearchResults $res
+ Apol_Analysis::setResultTabCriteria [array get vals]
+}
+
+
+proc Apol_Analysis_transflow::_renderResults {f results} {
+ variable vals
+
+ set graph_handler [$results extract_graph]
+ $graph_handler -acquire ;# let Tcl's GC destroy graph when this tab closes
+ set results_list [$results extract_result_vector]
+
+ set tree [[$f.left getframe].sw getframe].tree
+ set res [$f.right getframe].res
+
+ $tree insert end root top -text $vals(type) -open 1 -drawcross auto
+ set top_text [_renderTopText]
+ $tree itemconfigure top -data [list $graph_handler $top_text]
+
+ _createResultsNodes $tree top $results_list 1
+ $tree selection set top
+ $tree opentree top 0
+ $tree see top
+
+ $results_list -acquire
+ $results_list -delete
+}
+
+proc Apol_Analysis_transflow::_renderTopText {} {
+ variable vals
+
+ set top_text [list "Transitive Information Flow Analysis: Starting type: " title]
+ lappend top_text $vals(type) title_type \
+ "\n\n" title \
+ "This tab provides the results of a Transitive Information Flow
+analysis beginning from the starting type selected above. The results
+of the analysis are presented in tree form with the root of the tree
+(this node) being the start point for the analysis.
+
+\nEach child node in the tree represents a type in the current policy
+for which there is a transitive information flow to or from (depending
+on your selection above) its parent node.
+
+\nNOTE: For any given generation, if the parent and the child are the
+same, you cannot open the child. This avoids cyclic analyses." {}
+}
+
+# If do_expand is zero, then generate result nodes for only the first
+# target type of $results. This is needed by two types relationship
+# analysis.
+proc Apol_Analysis_transflow::_createResultsNodes {tree parent_node results do_expand} {
+ set all_targets {}
+ set info_list [infoflow_result_vector_to_list $results]
+ set results_processed 0
+ foreach r $info_list {
+ apol_tcl_set_info_string $::ApolTop::policy "Processing result $results_processed of [llength $info_list]"
+
+ if {$do_expand} {
+ set target [[$r get_end_type] get_name $::ApolTop::qpolicy]
+ } else {
+ set first_target [[lindex $info_list 0] get_end_type]
+ set target [$first_target get_name $::ApolTop::qpolicy]
+ }
+ set flow_dir [$r get_dir]
+ set length [$r get_length]
+ set steps_v [$r get_steps]
+
+ lappend all_targets $target
+ lappend paths($target) [list $length $steps_v]
+ incr results_processed
+ }
+
+ set all_targets [lsort -uniq $all_targets]
+ apol_tcl_set_info_string $::ApolTop::policy "Displaying [llength $all_targets] result(s)"
+ update idle
+
+ foreach t $all_targets {
+ set sorted_paths {}
+ foreach path [lsort -uniq [lsort -index 0 -integer $paths($t)]] {
+ set step_v [lindex $path 1]
+ set p {}
+ if {$flow_dir == $::APOL_INFOFLOW_IN} {
+ # flip the steps around
+ for {set i [expr {[$step_v get_size] - 1}]} {$i >= 0} {incr i -1} {
+ set r [apol_infoflow_step_from_void [$step_v get_element $i]]
+ lappend p [_infoflow_step_to_list $r]
+ }
+ } else {
+ for {set i 0} {$i < [$step_v get_size]} {incr i} {
+ set r [apol_infoflow_step_from_void [$step_v get_element $i]]
+ lappend p [_infoflow_step_to_list $r]
+ }
+ }
+ lappend sorted_paths $p
+ }
+ set data [list $flow_dir $sorted_paths]
+ $tree insert end $parent_node y\#auto -text $t -drawcross allways \
+ -data [list 0 $data]
+ }
+}
+
+proc Apol_Analysis_transflow::_infoflow_step_to_list {step} {
+ set start [[$step get_start_type] get_name $::ApolTop::qpolicy]
+ set end [[$step get_end_type] get_name $::ApolTop::qpolicy]
+ set weight [$step get_weight]
+ set rules [avrule_vector_to_list [$step get_rules]]
+ list $start $end $weight $rules
+}
+
+proc Apol_Analysis_transflow::_renderResultsTransFlow {res tree node data} {
+ set parent_name [$tree itemcget [$tree parent $node] -text]
+ set name [$tree itemcget $node -text]
+ foreach {flow_dir paths} $data {break}
+ switch -- $flow_dir [list \
+ $::APOL_INFOFLOW_IN {
+ $res.tb insert end "Information flows to " title \
+ $parent_name title_type \
+ " from " title \
+ $name title_type
+ } \
+ $::APOL_INFOFLOW_OUT {
+ $res.tb insert end "Information flows from " title \
+ $parent_name title_type \
+ " to " title \
+ $name title_type
+ } \
+ ]
+ $res.tb insert end " (" title \
+ "Find more flows" {title_type find_more} \
+ ")\n\n" title \
+ "Apol found the following number of information flows: " subtitle \
+ [llength $paths] num \
+ "\n" subtitle
+ set path_num 1
+ foreach path $paths {
+ $res.tb insert end "\n" {}
+ _renderPath $res $path_num $path
+ incr path_num
+ }
+}
+
+proc Apol_Analysis_transflow::_renderPath {res path_num path} {
+ $res.tb insert end "Flow " subtitle \
+ $path_num num \
+ " requires " subtitle \
+ [llength $path] num \
+ " steps(s).\n" subtitle \
+ " " {}
+ $res.tb insert end [lindex $path 0 0] subtitle \
+ " -> " {} \
+ [lindex $path 0 1] subtitle
+ foreach step [lrange $path 1 end] {
+ $res.tb insert end " -> " {} \
+ [lindex $step 1] subtitle
+ }
+ $res.tb insert end \n {}
+ foreach steps $path {
+ set rules [lindex $steps 3]
+ set v [new_apol_vector_t]
+ $v append [lindex $rules 0]
+ Apol_Widget::appendSearchResultRules $res 6 $v qpol_avrule_from_void
+ $v -acquire
+ $v -delete
+
+ set v [new_apol_vector_t]
+ foreach r [lrange $rules 1 end] {
+ $v append $r
+ }
+ apol_tcl_avrule_sort $::ApolTop::policy $v
+ Apol_Widget::appendSearchResultRules $res 10 $v qpol_avrule_from_void
+ $v -acquire
+ $v -delete
+ }
+}
+
+#################### procedures to find further flows ####################
+
+proc Apol_Analysis_transflow::_findMore {res tree} {
+ set node [$tree selection get]
+ set start [$tree itemcget [$tree parent $node] -text]
+ set end [$tree itemcget $node -text]
+
+ set d [Dialog .trans_more -cancel 1 -default 0 -modal local -parent . \
+ -separator 1 -title "Find More Flows"]
+ $d add -text Find -command [list Apol_Analysis_transflow::_verifyFindMore $d]
+ $d add -text Cancel
+
+ set f [$d getframe]
+ set l1 [label $f.l1 -text "Source: $start"]
+ set l2 [label $f.l2 -text "Target: $end"]
+ set time_f [frame $f.time]
+ set path_f [frame $f.path]
+ pack $l1 $l2 $time_f $path_f -anchor w -padx 8 -pady 4
+
+ set t1 [label $time_f.t1 -text "Time limit: "]
+ set e1 [entry $time_f.e1 -textvariable Apol_Analysis_transflow::vals(find_more:hours) -width 5 -justify right -bg white]
+ set t2 [label $time_f.t2 -text "Hour(s) "]
+ set e2 [entry $time_f.e2 -textvariable Apol_Analysis_transflow::vals(find_more:minutes) -width 5 -justify right -bg white]
+ set t3 [label $time_f.t3 -text "Minute(s) "]
+ set e3 [entry $time_f.e3 -textvariable Apol_Analysis_transflow::vals(find_more:seconds) -width 5 -justify right -bg white]
+ set t4 [label $time_f.t4 -text "Second(s) "]
+ pack $t1 $e1 $t2 $e2 $t3 $e3 $t4 -side left
+
+ set t1 [label $path_f.t1 -text "Limit by these number of flows: "]
+ set e1 [entry $path_f.e1 -textvariable Apol_Analysis_transflow::vals(find_more:limit) -width 5 -justify right -bg white]
+ pack $t1 $e1 -side left
+
+ set retval [$d draw]
+ destroy .trans_more
+ if {$retval == 0} {
+ set graph_handler [lindex [$tree itemcget top -data] 0]
+ $graph_handler trans_further_prepare $::ApolTop::policy $start $end
+ _doFindMore $res $tree $node
+ }
+}
+
+proc Apol_Analysis_transflow::_verifyFindMore {d} {
+ variable vals
+ set message {}
+ if {[set hours [string trim $vals(find_more:hours)]] == {}} {
+ set hours 0
+ }
+ if {[set minutes [string trim $vals(find_more:minutes)]] == {}} {
+ set minutes 0
+ }
+ if {[set seconds [string trim $vals(find_more:seconds)]] == {}} {
+ set seconds 0
+ }
+ set path_limit [string trim $vals(find_more:limit)]
+ if {![string is integer $hours] || $hours > 24 || $hours < 0} {
+ set message "Invalid hours limit input. Must be between 0-24 inclusive."
+ } elseif {![string is integer $minutes] || $minutes > 59 || $minutes < 0} {
+ set message "Invalid minutes limit input. Must be between 0-59 inclusive."
+ } elseif {![string is integer $seconds] || $seconds > 59 || $seconds < 0} {
+ set message "Invalid seconds limit input. Must be between 0-59 inclusive."
+ } elseif {$path_limit == {} && $hours == 0 && $minutes == 0 && $seconds == 0} {
+ set message "You must specify a time limit."
+ } elseif {$path_limit != {} && (![string is integer $path_limit] || $path_limit < 0)} {
+ set message "Number of flows cannot be less than 1."
+ }
+ if {$message != {}} {
+ tk_messageBox -icon error -type ok -title "Find More Flows" -message $message
+ } else {
+ $d enddialog 0
+ }
+}
+
+proc Apol_Analysis_transflow::_doFindMore {res tree node} {
+ variable vals
+ if {[set hours [string trim $vals(find_more:hours)]] == {}} {
+ set hours 0
+ }
+ if {[set minutes [string trim $vals(find_more:minutes)]] == {}} {
+ set minutes 0
+ }
+ if {[set seconds [string trim $vals(find_more:seconds)]] == {}} {
+ set seconds 0
+ }
+ set path_limit [string trim $vals(find_more:limit)]
+ if {$hours != 0 || $minutes != 0 || $seconds != 0} {
+ set time_limit [expr {$hours * 3600 + $minutes * 60 + $seconds}]
+ set time_limit_str [format " elapsed out of %02d:%02d:%02d" $hours $minutes $seconds]
+ } else {
+ set time_limit {}
+ set time_limit_str {}
+ }
+ if {$path_limit != {}} {
+ set path_limit_str " out of $path_limit"
+ } else {
+ set path_limit 0
+ set path_limit_str {}
+ }
+ set vals(find_more:abort) 0
+ set vals(find_more:searches_text) {}
+ set vals(find_more:searches_done) -1
+
+ set d [ProgressDlg .trans_domore -parent . -title "Find Results" \
+ -width 40 -height 5 \
+ -textvariable Apol_Analysis_transflow::vals(find_more:searches_text) \
+ -variable Apol_Analysis_transflow::vals(find_more:searches_done) \
+ -stop Stop \
+ -command [list set Apol_Analysis_transflow::vals(find_more:abort) 1]]
+ set graph_handler [lindex [$tree itemcget top -data] 0]
+ set start_time [clock seconds]
+ set elapsed_time 0
+ set path_found 0
+ set v NULL
+ while {1} {
+ set elapsed_time [expr {[clock seconds] - $start_time}]
+ set vals(find_more:searches_text) "Finding more flows:\n\n"
+ append vals(find_more:searches_text) " Time: [clock format $elapsed_time -format "%H:%M:%S" -gmt 1]$time_limit_str\n\n"
+ append vals(find_more:searches_text) " Flows: found $path_found$path_limit_str"
+ update
+ set v [$graph_handler trans_further_next $::ApolTop::policy $v]
+ set path_found [$v get_size]
+ if {($time_limit != {} && $elapsed_time >= $time_limit) || \
+ ($path_limit != 0 && $path_found > $path_limit) || \
+ $vals(find_more:abort)} {
+ break
+ }
+ }
+ set vals(find_more:searches_text) "Rendering $path_found flow(s)."
+ update idletasks
+
+ $res.tb configure -state normal
+ $res.tb delete 0.0 end
+ set parent_name [$tree itemcget [$tree parent $node] -text]
+ set name [$tree itemcget $node -text]
+ set flow_dir [lindex [$tree itemcget $node -data] 1 0]
+ switch -- $flow_dir [list \
+ $::APOL_INFOFLOW_IN {
+ $res.tb insert end "More information flows to " title \
+ $parent_name title_type \
+ " from " title \
+ $name title_type
+ } \
+ $::APOL_INFOFLOW_OUT {
+ $res.tb insert end "More information flows from " title \
+ $parent_name title_type \
+ " to " title \
+ $name title_type
+ } \
+ ]
+ $res.tb insert end " (" title \
+ "Find more flows" {title_type find_more} \
+ ")\n\n" title \
+ "Time: " subtitle \
+ [clock format $elapsed_time -format "%H:%M:%S" -gmt 1] subtitle \
+ [format " out of %02d:%02d:%02d" $hours $minutes $seconds] subtitle \
+ "\n\nApol found the following number of information flows: " subtitle \
+ $path_found num \
+ " out of " subtitle \
+ $path_limit num \
+ "\n" subtitle
+
+ set results {}
+ foreach r [infoflow_result_vector_to_list $v] {
+ set length [$r get_length]
+ set steps_v [$r get_steps]
+ lappend results [list $length $steps_v]
+ }
+
+ set path_num 1
+ foreach r [lsort -index 0 -integer $results] {
+ set steps_v [lindex $r 1]
+ set sorted_path {}
+ if {$flow_dir == $::APOL_INFOFLOW_IN} {
+ # flip the steps around
+ for {set i [expr {[$steps_v get_size] - 1}]} {$i >= 0} {incr i -1} {
+ set s [apol_infoflow_step_from_void [$steps_v get_element $i]]
+ lappend sorted_path [_infoflow_step_to_list $s]
+ }
+ } else {
+ for {set i 0} {$i < [$steps_v get_size]} {incr i} {
+ set s [apol_infoflow_step_from_void [$steps_v get_element $i]]
+ lappend sorted_path [_infoflow_step_to_list $s]
+ }
+ }
+ $res.tb insert end "\n" {}
+ _renderPath $res $path_num $sorted_path
+ incr path_num
+ }
+
+ $res.tb configure -state disabled
+ destroy $d
+ $v -acquire
+ $v -delete
+}
diff --git a/apol/types_relation_help.txt b/apol/types_relation_help.txt
new file mode 100644
index 0000000..3217702
--- /dev/null
+++ b/apol/types_relation_help.txt
@@ -0,0 +1,53 @@
+An overview of types relationship summary analysis
+
+
+Understanding types relationship summary analysis
+-------------------------------------------------
+The types relationship summary analysis in apol is a convenience
+mechanism to allow a user to quickly do several queries and analyses
+already in present in apol to understand the relationship between two
+types. It is meant to quickly display the relationship between two
+types and therefore does not include all of the options present in the
+standard queries and analyses. The analyses are grouped into two
+categories: Basic and Analysis.
+
+
+Basic
+-----
+The basic group includes several rule searches that can be performed
+using the Policy Rules tab.
+
+ Common Attributes: the attributes common to both types.
+
+ Common Roles: the roles to which both types are assigned.
+
+ Common Users: the users allowed associate with roles to which both
+ types are assigned.
+
+ Similar Access to Resources: object types to which both types have
+ some access.
+
+ Dissimilar Access to Resources: object types to which one type has
+ some access but the other type has none.
+
+ TE Allow Rules: rules that provide direct access between both types.
+
+ Type Transition / Change Rules: type_* rules that allow transitions
+ between both types.
+
+
+Analysis
+--------
+The analysis group includes several other analyses that can be
+performed using the Analysis tab.
+
+ Direct Flows Between A and B: direct information flow analysis between
+ the two types.
+
+ Transitive Flows A->B: transitive information flows from type A to B.
+
+ Transitive Flows B->A: transitive information flows from type B to A.
+
+ Domain Transitions A->B: domain transitions allowed from type A to B.
+
+ Domain Transitions B->A: domain transitions allowed from type B to A.
diff --git a/apol/types_relation_module.tcl b/apol/types_relation_module.tcl
new file mode 100644
index 0000000..32924c5
--- /dev/null
+++ b/apol/types_relation_module.tcl
@@ -0,0 +1,770 @@
+# 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
+
+# This module implements the two types relationship analysis interface.
+
+namespace eval Apol_Analysis_tra {
+ variable vals
+ variable widgets
+ Apol_Analysis::registerAnalysis "Apol_Analysis_tra" "Types Relationship Summary"
+}
+
+proc Apol_Analysis_tra::create {options_frame} {
+ variable vals
+ variable widgets
+
+ _reinitializeVals
+
+ set req_tf [TitleFrame $options_frame.req -text "Required Parameters"]
+ pack $req_tf -side left -padx 2 -pady 2 -expand 0 -fill y
+ set fA [frame [$req_tf getframe].fA]
+ pack $fA -side left -anchor nw -padx 2
+ set lA [label $fA.l -text "Type A"]
+ pack $lA -anchor w
+ set widgets(typeA) [Apol_Widget::makeTypeCombobox $fA.t -width 19]
+ pack $widgets(typeA)
+ set fB [frame [$req_tf getframe].fB]
+ pack $fB -side left -anchor nw -padx 2
+ set lB [label $fB.l -text "Type B"]
+ pack $lB -anchor w
+ set widgets(typeB) [Apol_Widget::makeTypeCombobox $fB.t -width 19]
+ pack $widgets(typeB)
+
+ set basic_tf [TitleFrame $options_frame.basic -text "Basic Relationships"]
+ pack $basic_tf -side left -padx 2 -pady 2 -expand 0 -fill y
+ foreach {t a v} [list \
+ "Common attributes" attribs $::APOL_TYPES_RELATION_COMMON_ATTRIBS \
+ "Common roles" roles $::APOL_TYPES_RELATION_COMMON_ROLES \
+ "Common users" users $::APOL_TYPES_RELATION_COMMON_USERS \
+ "Similar access to resources" similars $::APOL_TYPES_RELATION_SIMILAR_ACCESS \
+ "Dissimilar access to resources" dissimilars $::APOL_TYPES_RELATION_DISSIMILAR_ACCESS \
+ "TE allow rules" allows $::APOL_TYPES_RELATION_ALLOW_RULES \
+ "Type transition/change rules" typerules $::APOL_TYPES_RELATION_TYPE_RULES] {
+ set cb [checkbutton [$basic_tf getframe].$v -text $t \
+ -variable Apol_Analysis_tra::vals(run:$a) \
+ -onvalue $v -offvalue 0]
+ pack $cb -anchor w
+ }
+
+ set an_tf [TitleFrame $options_frame.an -text "Analysis Relationships"]
+ pack $an_tf -side left -padx 2 -pady 2 -expand 1 -fill both
+ foreach {t a v} [list \
+ "Direct flows between A and B" direct $::APOL_TYPES_RELATION_DIRECT_FLOW \
+ "Transitive flows A -> B" transAB $::APOL_TYPES_RELATION_TRANS_FLOW_AB \
+ "Transitive flows B -> A" transBA $::APOL_TYPES_RELATION_TRANS_FLOW_BA \
+ "Domain transitions A -> B" domainAB $::APOL_TYPES_RELATION_DOMAIN_TRANS_AB \
+ "Domain transitions B -> A" domainBA $::APOL_TYPES_RELATION_DOMAIN_TRANS_BA] {
+ set cb [checkbutton [$an_tf getframe].$v -text $t \
+ -variable Apol_Analysis_tra::vals(run:$a) \
+ -onvalue $v -offvalue 0]
+ pack $cb -anchor w
+ }
+}
+
+proc Apol_Analysis_tra::open {} {
+ variable widgets
+ Apol_Widget::resetTypeComboboxToPolicy $widgets(typeA)
+ Apol_Widget::resetTypeComboboxToPolicy $widgets(typeB)
+}
+
+proc Apol_Analysis_tra::close {} {
+ variable widgets
+ _reinitializeVals
+ _reinitializeWidgets
+ Apol_Widget::clearTypeCombobox $widgets(typeA)
+ Apol_Widget::clearTypeCombobox $widgets(typeB)
+}
+
+proc Apol_Analysis_tra::getInfo {} {
+ return "The types relationship summary analysis in Apol is a convenience
+mechanism to allow a user to quickly do several queries and analyses
+already in present in Apol to understand the relationship between two
+types. This is meant to quickly display the relationship between two
+types and therefore does not include all of the options present in the
+standard queries and analyses.
+
+\nFor additional help on this topic select \"Types Relationship Summary
+Analysis\" from the help menu."
+}
+
+proc Apol_Analysis_tra::newAnalysis {} {
+ if {[set rt [_checkParams]] != {}} {
+ return $rt
+ }
+ set results [_analyze]
+ set f [_createResultsDisplay]
+ _renderResults $f $results
+ $results -acquire
+ $results -delete
+ return {}
+}
+
+
+proc Apol_Analysis_tra::updateAnalysis {f} {
+ if {[set rt [_checkParams]] != {}} {
+ return $rt
+ }
+ set results [_analyze]
+ _clearResultsDisplay $f
+ _renderResults $f $results
+ $results -acquire
+ $results -delete
+ return {}
+}
+
+proc Apol_Analysis_tra::reset {} {
+ _reinitializeVals
+ _reinitializeWidgets
+}
+
+proc Apol_Analysis_tra::switchTab {query_options} {
+ variable vals
+ variable widgets
+ array set vals $query_options
+ _reinitializeWidgets
+}
+
+proc Apol_Analysis_tra::saveQuery {channel} {
+ variable vals
+ variable widgets
+ foreach {key value} [array get vals] {
+ puts $channel "$key $value"
+ }
+ set type [Apol_Widget::getTypeComboboxValueAndAttrib $widgets(typeA)]
+ puts $channel "typeA [lindex $type 0]"
+ puts $channel "typeA:attrib [lindex $type 1]"
+ set type [Apol_Widget::getTypeComboboxValueAndAttrib $widgets(typeB)]
+ puts $channel "typeB [lindex $type 0]"
+ puts $channel "typeB:attrib [lindex $type 1]"
+}
+
+proc Apol_Analysis_tra::loadQuery {channel} {
+ variable vals
+
+ set classes_exc {}
+ set subjects_exc {}
+ while {[gets $channel line] >= 0} {
+ set line [string trim $line]
+ # Skip empty lines and comments
+ if {$line == {} || [string index $line 0] == "#"} {
+ continue
+ }
+ set key {}
+ set value {}
+ regexp -line -- {^(\S+)( (.+))?} $line -> key --> value
+ set vals($key) $value
+ }
+ _reinitializeWidgets
+}
+
+proc Apol_Analysis_tra::getTextWidget {tab} {
+ return [$tab.right getframe].res.tb
+}
+
+
+#################### private functions below ####################
+
+proc Apol_Analysis_tra::_reinitializeVals {} {
+ variable vals
+
+ set vals(run:attribs) $::APOL_TYPES_RELATION_COMMON_ATTRIBS
+ set vals(run:roles) $::APOL_TYPES_RELATION_COMMON_ROLES
+ set vals(run:users) $::APOL_TYPES_RELATION_COMMON_USERS
+ array set vals {
+ typeA {} typeA:attrib {}
+ typeB {} typeB:attrib {}
+
+ run:similars 0
+ run:dissimilars 0
+ run:allows 0
+ run:typerules 0
+
+ run:direct 0
+ run:transAB 0
+ run:transBA 0
+ run:domainAB 0
+ run:domainBA 0
+ }
+}
+
+proc Apol_Analysis_tra::_reinitializeWidgets {} {
+ variable vals
+ variable widgets
+
+ if {$vals(typeA:attrib) != {}} {
+ Apol_Widget::setTypeComboboxValue $widgets(typeA) [list $vals(typeA) $vals(typeA:attrib)]
+ } else {
+ Apol_Widget::setTypeComboboxValue $widgets(typeA) $vals(typeA)
+ }
+ if {$vals(typeB:attrib) != {}} {
+ Apol_Widget::setTypeComboboxValue $widgets(typeB) [list $vals(typeB) $vals(typeB:attrib)]
+ } else {
+ Apol_Widget::setTypeComboboxValue $widgets(typeB) $vals(typeB)
+ }
+}
+
+#################### functions that do analyses ####################
+
+proc Apol_Analysis_tra::_checkParams {} {
+ variable vals
+ variable widgets
+ if {![ApolTop::is_policy_open]} {
+ return "No current policy file is opened."
+ }
+ set type [Apol_Widget::getTypeComboboxValueAndAttrib $widgets(typeA)]
+ if {[lindex $type 0] == {}} {
+ return "No type was selected for type A."
+ }
+ if {![Apol_Types::isTypeInPolicy [lindex $type 0]]} {
+ return "[lindex $type 0] is not a type within the policy."
+ }
+ set vals(typeA) [lindex $type 0]
+ set vals(typeA:attrib) [lindex $type 1]
+ set type [Apol_Widget::getTypeComboboxValueAndAttrib $widgets(typeB)]
+ if {[lindex $type 0] == {}} {
+ return "No type was selected for type B."
+ }
+ if {![Apol_Types::isTypeInPolicy [lindex $type 0]]} {
+ return "[lindex $type 0] is not a type within the policy."
+ }
+ set vals(typeB) [lindex $type 0]
+ set vals(typeB:attrib) [lindex $type 1]
+ set analysis_selected 0
+ foreach key [array names vals run:*] {
+ if {$vals($key)} {
+ # if a permap is not loaded then load the default permap
+ if {($key == "run:direct" || [string match run:trans* $key]) && \
+ ![Apol_Perms_Map::is_pmap_loaded]} {
+ if {![ApolTop::openDefaultPermMap]} {
+ return "This analysis requires that a permission map is loaded."
+ }
+ apol_tcl_clear_info_string
+ }
+ set analysis_selected 1
+ }
+ }
+ if {!$analysis_selected} {
+ return "At least one analysis must be selected."
+ }
+ return {} ;# all parameters passed, now ready to do search
+}
+
+proc Apol_Analysis_tra::_analyze {} {
+ variable vals
+ set q [new_apol_types_relation_analysis_t]
+ $q set_first_type $::ApolTop::policy $vals(typeA)
+ $q set_other_type $::ApolTop::policy $vals(typeB)
+ set analyses 0
+ foreach key [array names vals run:*] {
+ set analyses [expr {$analyses | $vals($key)}]
+ }
+ $q set_analyses $::ApolTop::policy $analyses
+
+ set results [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ return $results
+}
+
+################# functions that control analysis output #################
+
+proc Apol_Analysis_tra::_createResultsDisplay {} {
+ variable vals
+
+ set f [Apol_Analysis::createResultTab "Types Relationship" [array get vals]]
+
+ set tree_tf [TitleFrame $f.left -text "Types Relationship Results"]
+ pack $tree_tf -side left -expand 0 -fill y -padx 2 -pady 2
+ set sw [ScrolledWindow [$tree_tf getframe].sw -auto both]
+ set tree [Tree [$sw getframe].tree -width 24 -redraw 1 -borderwidth 0 \
+ -highlightthickness 0 -showlines 1 -padx 0 -bg white]
+ $sw setwidget $tree
+ pack $sw -expand 1 -fill both
+
+ set res_tf [TitleFrame $f.right -text "Types Relationship Information"]
+ pack $res_tf -side left -expand 1 -fill both -padx 2 -pady 2
+ set res [Apol_Widget::makeSearchResults [$res_tf getframe].res]
+ $res.tb tag configure title -font {Helvetica 14 bold}
+ $res.tb tag configure title_type -foreground blue -font {Helvetica 14 bold}
+ $res.tb tag configure subtitle -font {Helvetica 10 bold}
+ $res.tb tag configure subtitle_dir -foreground blue -font {Helvetica 10 bold}
+ $res.tb tag configure num -foreground blue -font {Helvetica 10 bold}
+ pack $res -expand 1 -fill both
+
+ update
+ grid propagate $sw 0
+ $tree configure -selectcommand [list Apol_Analysis_tra::_treeSelect $res]
+ return $f
+}
+
+proc Apol_Analysis_tra::_treeSelect {res tree node} {
+ if {$node != {}} {
+ $res.tb configure -state normal
+ $res.tb delete 0.0 end
+ set data [$tree itemcget $node -data]
+ set name [$tree itemcget $node -text]
+ if {[set parent [$tree parent $node]] != "root"} {
+ set parent_name [$tree itemcget $parent -text]
+ set parent_data [$tree itemcget $parent -data]
+ }
+ switch -glob -- $node {
+ pre:* {
+ # an informational node, whose data has already been rendered
+ eval $res.tb insert end $data
+ }
+ simtitle {
+ _showSimilarTitle $res $data
+ }
+ sim:* {
+ _showSimilar $res $name $parent_data $data
+ }
+ distitle {
+ _showDissimilarTitle $res $data
+ }
+ dissubtitle* {
+ _showDissimilarSubtitle $res $data
+ }
+ dis:* {
+ _showDissimilar $res $name $parent_name $data
+ }
+ allow {
+ _showAllows $res $data
+ }
+ typerules {
+ _showTypeRules $res $data
+ }
+ x* {
+ _showDirectFlow $res $data
+ }
+ y* {
+ _showTransFlow $res $data
+ }
+ f:* {
+ _showDTA $res $data
+ }
+ }
+ $res.tb configure -state disabled
+ }
+}
+
+proc Apol_Analysis_tra::_clearResultsDisplay {f} {
+ variable vals
+ set tree [[$f.left getframe].sw getframe].tree
+ set res [$f.right getframe].res
+ $tree delete [$tree nodes root]
+ Apol_Widget::clearSearchResults $res
+ Apol_Analysis::setResultTabCriteria [array get vals]
+}
+
+proc Apol_Analysis_tra::_renderResults {f results} {
+ variable vals
+
+ set tree [[$f.left getframe].sw getframe].tree
+ set res [$f.right getframe].res
+ if {$vals(run:attribs)} {
+ _renderCommon Attributes $tree $results get_attributes attr_vector_to_list
+ }
+ if {$vals(run:roles)} {
+ _renderCommon Roles $tree $results get_roles role_vector_to_list
+ }
+ if {$vals(run:users)} {
+ _renderCommon Users $tree $results get_users user_vector_to_list
+ }
+ if {$vals(run:similars)} {
+ _renderSimilars $tree $results
+ }
+ if {$vals(run:dissimilars)} {
+ _renderDissimilars $tree $results
+ }
+ if {$vals(run:allows)} {
+ _renderAllows $tree $results
+ }
+ if {$vals(run:typerules)} {
+ _renderTypeRules $tree $results
+ }
+ if {$vals(run:direct)} {
+ _renderDirectFlow $tree $results
+ }
+ if {$vals(run:transAB)} {
+ _renderTransFlow 0 $tree $results
+ }
+ if {$vals(run:transBA)} {
+ _renderTransFlow 1 $tree $results
+ }
+ if {$vals(run:domainAB)} {
+ _renderDTA 0 $tree $results
+ }
+ if {$vals(run:domainBA)} {
+ _renderDTA 1 $tree $results
+ }
+ set first_node [$tree nodes root 0]
+ $tree selection set $first_node
+ $tree see $first_node
+}
+
+proc Apol_Analysis_tra::_renderCommon {title tree results func convert_func} {
+ set names [$convert_func [$results $func]]
+ set text [list "Common $title ([llength $names]):\n\n" title]
+ foreach n [lsort $names] {
+ lappend text "$n\n" {}
+ }
+ $tree insert end root pre:$title -text "Common $title" -data $text
+}
+
+# Convert a vector of apol_types_relation_access_t pointers into a
+# list of access tuples. Each tuple is:
+#
+# type name
+# list of avrules
+proc Apol_Analysis_tra::_types_relation_access_vector_to_list {v} {
+ set l {}
+ for {set i 0} {$v != "NULL" && $i < [$v get_size]} {incr i} {
+ set a [apol_types_relation_access_from_void [$v get_element $i]]
+ set type [[$a get_type] get_name $::ApolTop::qpolicy]
+ set rules [avrule_vector_to_list [$a get_rules]]
+ lappend l [list $type $rules]
+ }
+ set l
+}
+
+proc Apol_Analysis_tra::_renderSimilars {tree results} {
+ variable vals
+ set simA [_types_relation_access_vector_to_list [$results get_similar_first]]
+ set simB [_types_relation_access_vector_to_list [$results get_similar_other]]
+ set data [list $vals(typeA) $vals(typeB) [llength $simA]]
+ $tree insert end root simtitle -text "Similar access to resources" -data $data -drawcross allways
+ foreach accessA [lsort -index 0 $simA] accessB [lsort -index 0 $simB] {
+ set type [lindex $accessA 0]
+ set rulesA [lindex $accessA 1]
+ set rulesB [lindex $accessB 1]
+ $tree insert end simtitle sim:$type -text $type -data [list $rulesA $rulesB]
+ }
+}
+
+proc Apol_Analysis_tra::_showSimilarTitle {res data} {
+ foreach {typeA typeB numTypes} $data {break}
+ $res.tb insert end $typeA title_type \
+ " and " title \
+ $typeB title_type \
+ " access $numTypes common type(s).\n\n" title \
+ "Open the subtree for this item to see the list of common types that
+can be accessed. You may then select a type from the subtree to see
+the allow rules which provide the access." {}
+}
+
+proc Apol_Analysis_tra::_showSimilar {res name parent_data data} {
+ foreach {typeA typeB} $parent_data {rulesA rulesB} $data {break}
+ $res.tb insert end $typeA title_type \
+ " accesses " title \
+ $name title_type \
+ ":\n\n" title
+ set v [new_apol_vector_t]
+ foreach r $rulesA {
+ $v append $r
+ }
+ apol_tcl_avrule_sort $::ApolTop::policy $v
+ Apol_Widget::appendSearchResultRules $res 2 $v qpol_avrule_from_void
+ $v -acquire
+ $v -delete
+
+ $res.tb insert end "\n" title \
+ $typeB title_type \
+ " accesses " title \
+ $name title_type \
+ ":\n\n" title
+ set v [new_apol_vector_t]
+ foreach r $rulesB {
+ $v append $r
+ }
+ apol_tcl_avrule_sort $::ApolTop::policy $v
+ Apol_Widget::appendSearchResultRules $res 2 $v qpol_avrule_from_void
+ $v -acquire
+ $v -delete
+}
+
+proc Apol_Analysis_tra::_renderDissimilars {tree results} {
+ variable vals
+ set disA [_types_relation_access_vector_to_list [$results get_dissimilar_first]]
+ set disB [_types_relation_access_vector_to_list [$results get_dissimilar_other]]
+ set data [list $vals(typeA) $vals(typeB)]
+ $tree insert end root distitle -text "Dissimilar access to resources" -data $data
+
+ set data [list $vals(typeA) $vals(typeB) [llength $disA]]
+ $tree insert end distitle dissubtitleA -text $vals(typeA) -data $data -drawcross allways
+ foreach access [lsort -index 0 $disA] {
+ set type [lindex $access 0]
+ set rules [lindex $access 1]
+ $tree insert end dissubtitleA dis:$type -text $type -data $rules
+ }
+ set data [list $vals(typeB) $vals(typeA) [llength $disB]]
+ $tree insert end distitle dissubtitleB -text $vals(typeB) -data $data -drawcross allways
+ foreach access [lsort -index 0 $disB] {
+ set type [lindex $access 0]
+ set rules [lindex $access 1]
+ $tree insert end dissubtitleB dis:$type -text $type -data $rules
+ }
+}
+
+proc Apol_Analysis_tra::_showDissimilarTitle {res data} {
+ foreach {typeA typeB} $data {break}
+ $res.tb insert end "Dissimilar access between " title \
+ $typeA title_type \
+ " and " title \
+ $typeB title_type \
+ ".\n\n" title \
+ "Open the subtree for this item to access individual subtrees of types
+which can be accessed by one type but not the other. You may then
+select a type from a subtree to see the allow rules which provide the
+access." {}
+}
+
+proc Apol_Analysis_tra::_showDissimilarSubtitle {res data} {
+ foreach {one_type other_type numTypes} $data {break}
+ $res.tb insert end $one_type title_type \
+ " accesss $numTypes type(s) to which " title \
+ $other_type title_type \
+ " does not have access.\n\n" title \
+ "Open the subtree for this item to see the list of types. You may then
+select a type from the subtree to see the allow rules which provide
+the access." {}
+}
+
+proc Apol_Analysis_tra::_showDissimilar {res name parent_name data} {
+ $res.tb insert end $parent_name title_type \
+ " accesses " title \
+ $name title_type \
+ ":\n\n" title
+ set v [new_apol_vector_t]
+ foreach r $data {
+ $v append $r
+ }
+ apol_tcl_avrule_sort $::ApolTop::policy $v
+ Apol_Widget::appendSearchResultRules $res 2 $v qpol_avrule_from_void
+ $v -acquire
+ $v -delete
+}
+
+proc Apol_Analysis_tra::_renderAllows {tree results} {
+ set rules [$results get_allowrules]
+ set rules_dup [new_apol_vector_t $rules]
+ $rules_dup -acquire
+ apol_tcl_avrule_sort $::ApolTop::policy $rules_dup
+ $tree insert end root allow -text "TE Allow Rules" -data $rules_dup
+}
+
+proc Apol_Analysis_tra::_showAllows {res data} {
+ $res.tb insert end "TE Allow Rules ([$data get_size]):\n\n" title
+ Apol_Widget::appendSearchResultRules $res 2 $data qpol_avrule_from_void
+}
+
+proc Apol_Analysis_tra::_renderTypeRules {tree results} {
+ set rules [$results get_typerules]
+ set rules_dup [new_apol_vector_t $rules]
+ apol_tcl_terule_sort $::ApolTop::policy $rules_dup
+ $rules_dup -acquire
+ $tree insert end root typerules -text "Type Transition/Change Rules" -data $rules_dup
+}
+
+proc Apol_Analysis_tra::_showTypeRules {res data} {
+ $res.tb insert end "Type transition/change rules ([$data get_size]):\n\n" title
+ Apol_Widget::appendSearchResultRules $res 2 $data qpol_terule_from_void
+}
+
+proc Apol_Analysis_tra::_renderDirectFlow {tree results} {
+ set v [$results get_directflows]
+ if {$v == "NULL" || [$v get_size] == 0} {
+ $tree insert end root pre:direct
+ set node [$tree nodes root end]
+ set data [list "No direct information flows found." title]
+ } else {
+ variable vals
+ Apol_Analysis_directflow::appendResultsNodes $tree root $v
+ set node [$tree nodes root end]
+ set data [list $vals(typeA) $vals(typeB) [$tree itemcget $node -data]]
+ }
+ $tree itemconfigure $node -text "Direct Flows Between A and B" -data $data -drawcross auto
+}
+
+proc Apol_Analysis_tra::_showDirectFlow {res data} {
+ foreach {parent_name name data} $data {break}
+ foreach {flow_dir classes} [lindex $data 1] {break}
+ $res.tb insert end "Information flows both into and out of " title \
+ $parent_name title_type \
+ " from/to " title \
+ $name title_type
+ $res.tb insert end "\n\n" title_type \
+ "Objects classes for " subtitle \
+ [string toupper $flow_dir] subtitle_dir \
+ " flows:\n" subtitle
+ foreach c $classes {
+ foreach {class_name rules} $c {break}
+ $res.tb insert end " " {} \
+ $class_name\n subtitle
+ set v [new_apol_vector_t]
+ foreach r $rules {
+ $v append $r
+ }
+ apol_tcl_avrule_sort $::ApolTop::policy $v
+ Apol_Widget::appendSearchResultRules $res 12 $v qpol_avrule_from_void
+ $v -acquire
+ $v -delete
+ }
+}
+
+proc Apol_Analysis_tra::_renderTransFlow {dir tree results} {
+ variable vals
+ if {$dir == 0} {
+ set title2 "A->B"
+ set v [$results get_transflowsAB]
+ set data [list $vals(typeB) $vals(typeA)]
+ } else {
+ set title2 "B->A"
+ set v [$results get_transflowsBA]
+ set data [list $vals(typeA) $vals(typeB)]
+ }
+ if {$v == "NULL" || [$v get_size] == 0} {
+ $tree insert end root pre:trans$dir
+ set node [$tree nodes root end]
+ set data [list "No transitive information flows found." title]
+ } else {
+ Apol_Analysis_transflow::appendResultsNodes $tree root $v
+ set node [$tree nodes root end]
+ lappend data [$tree itemcget $node -data]
+ }
+ $tree itemconfigure $node -text "Transitive Flows $title2" -data $data -drawcross auto
+}
+
+proc Apol_Analysis_tra::_showTransFlow {res data} {
+ foreach {parent_name name data} $data {break}
+ foreach {flow_dir paths} [lindex $data 1] {break}
+ $res.tb insert end "Information flows from " title \
+ $name title_type \
+ " to " title \
+ $parent_name title_type
+ $res.tb insert end "\n\n" title \
+ "Apol found the following number of information flows: " subtitle \
+ [llength $paths] num \
+ "\n" subtitle
+ set path_num 1
+ foreach path $paths {
+ $res.tb insert end "\n" {}
+ Apol_Analysis_transflow::renderPath $res $path_num $path
+ incr path_num
+ }
+}
+
+proc Apol_Analysis_tra::_renderDTA {dir tree results} {
+ variable vals
+ if {$dir == 0} {
+ set title2 "A->B"
+ set data [list $vals(typeA) $vals(typeB)]
+ set dta [$results get_domainsAB]
+ } else {
+ set title2 "B->A"
+ set data [list $vals(typeB) $vals(typeA)]
+ set dta [$results get_domainsBA]
+ }
+ if {$dta == "NULL" || [$dta get_size] == 0} {
+ $tree insert end root pre:dta$dir
+ set node [$tree nodes root end]
+ set data [list "No domain transitions found." title]
+ } else {
+ Apol_Analysis_domaintrans::appendResultsNodes $tree root $dta
+ set node [$tree nodes root end]
+ lappend data [$tree itemcget $node -data]
+ }
+ $tree itemconfigure $node -text "Domain Transitions $title2" -data $data -drawcross auto
+}
+
+proc Apol_Analysis_tra::_showDTA {res data} {
+ foreach {parent_name name data} $data {break}
+ foreach {proctrans setexec ep access_list} [lindex $data 1] {break}
+ set header [list "Domain transition from " title \
+ $parent_name title_type \
+ " to " title \
+ $name title_type]
+ eval $res.tb insert end $header
+ $res.tb insert end "\n\n" title_type
+
+ $res.tb insert end "Process Transition Rules: " subtitle \
+ [llength $proctrans] num \
+ "\n" subtitle
+ set v [list_to_vector $proctrans]
+ apol_tcl_avrule_sort $::ApolTop::policy $v
+ Apol_Widget::appendSearchResultRules $res 6 $v _qpol_avrule_from_void
+ $v -acquire
+ $v -delete
+ if {[llength $setexec] > 0} {
+ $res.tb insert end "\n" {} \
+ "Setexec Rules: " subtitle \
+ [llength $setexec] num \
+ "\n" subtitle
+ set v [list_to_vector $setexec]
+ apol_tcl_avrule_sort $::ApolTop::policy $v
+ Apol_Widget::appendSearchResultRules $res 6 $v qpol_avrule_from_void
+ $v -acquire
+ $v -delete
+ }
+
+ $res.tb insert end "\nEntry Point File Types: " subtitle \
+ [llength $ep] num
+ foreach e [lsort -index 0 $ep] {
+ foreach {intermed entrypoint execute type_trans} $e {break}
+ $res.tb insert end "\n $intermed\n" {} \
+ " " {} \
+ "File Entrypoint Rules: " subtitle \
+ [llength $entrypoint] num \
+ "\n" subtitle
+ set v [list_to_vector $entrypoint]
+ apol_tcl_avrule_sort $::ApolTop::policy $v
+ Apol_Widget::appendSearchResultRules $res 12 $v qpol_avrule_from_void
+ $v -acquire
+ $v -delete
+ $res.tb insert end "\n" {} \
+ " " {} \
+ "File Execute Rules: " subtitle \
+ [llength $execute] num \
+ "\n" subtitle
+ set v [list_to_vector $execute]
+ apol_tcl_avrule_sort $::ApolTop::policy $v
+ Apol_Widget::appendSearchResultRules $res 12 $v qpol_avrule_from_void
+ $v -acquire
+ $v -delete
+ if {[llength $type_trans] > 0} {
+ $res.tb insert end "\n" {} \
+ " " {} \
+ "Type_transition Rules: " subtitle \
+ [llength $type_trans] num \
+ "\n" subtitle
+ set v [list_to_vector $type_trans]
+ apol_tcl_terule_sort $::ApolTop::policy $v
+ Apol_Widget::appendSearchResultRules $res 12 $v qpol_terule_from_void
+ $v -acquire
+ $v -delete
+ }
+ }
+
+ if {[llength $access_list] > 0} {
+ $res.tb insert end "\n" {} \
+ "The access filters you specified returned the following rules: " subtitle \
+ [llength $access_list] num \
+ "\n" subtitle
+ set v [list_to_vector $access_list]
+ apol_tcl_avrule_sort $::ApolTop::policy $v
+ Apol_Widget::appendSearchResultRules $res 6 $v qpol_avrule_from_void
+ $v -acquire
+ $v -delete
+ }
+}
diff --git a/apol/types_tab.tcl b/apol/types_tab.tcl
new file mode 100644
index 0000000..26def34
--- /dev/null
+++ b/apol/types_tab.tcl
@@ -0,0 +1,411 @@
+# Copyright (C) 2001-2008 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
+
+namespace eval Apol_Types {
+ variable typelist {}
+ variable attriblist {}
+ variable opts
+ variable widgets
+}
+
+proc Apol_Types::create {tab_name nb} {
+ variable opts
+ variable widgets
+
+ _initializeVars
+
+ set frame [$nb insert end $tab_name -text "Types"]
+ set pw1 [PanedWindow $frame.pw -side top]
+ set left_pane [$pw1 add -weight 0]
+ set center_pane [$pw1 add -weight 1]
+ set tpane [frame $left_pane.t]
+ set apane [frame $left_pane.a]
+
+ set tbox [TitleFrame $tpane.tbox -text "Types"]
+ set abox [TitleFrame $apane.abox -text "Attributes"]
+ set obox [TitleFrame $center_pane.obox -text "Search Options"]
+ set rbox [TitleFrame $center_pane.rbox -text "Search Results"]
+
+ pack $obox -side top -expand 0 -fill both -padx 2
+ pack $rbox -expand yes -fill both -padx 2
+ pack $tbox -fill both -expand yes
+ pack $abox -fill both -expand yes
+ pack $pw1 -fill both -expand yes
+ pack $tpane -fill both -expand 1
+ pack $apane -fill both -expand 1
+
+ set tlistbox [Apol_Widget::makeScrolledListbox [$tbox getframe].types \
+ -height 10 -width 20 -listvar Apol_Types::typelist]
+ Apol_Widget::setListboxCallbacks $tlistbox \
+ {{"Show Type Info" {Apol_Types::_popupTypeInfo type}}}
+ pack $tlistbox -expand 1 -fill both
+
+ set alistbox [Apol_Widget::makeScrolledListbox [$abox getframe].attribs \
+ -height 5 -width 20 -listvar Apol_Types::attriblist]
+ Apol_Widget::setListboxCallbacks $alistbox {{"Show Attribute Info" {Apol_Types::_popupTypeInfo attrib}}}
+ pack $alistbox -expand 1 -fill both
+
+ set ofm [$obox getframe]
+ set fm_types_select [frame $ofm.to]
+ set fm_attribs_select [frame $ofm.ao]
+ pack $fm_types_select $fm_attribs_select -side left -padx 4 -pady 2 -anchor nw
+
+ set types_select [checkbutton $fm_types_select.type -text "Show types" -variable Apol_Types::opts(types)]
+ set typeattribs [checkbutton $fm_types_select.typeattribs -text "Include attributes" \
+ -variable Apol_Types::opts(types:show_attribs)]
+ pack $types_select -anchor w
+ pack $typeattribs -anchor w -padx 8
+ trace add variable Apol_Types::opts(types) write \
+ [list Apol_Types::_toggleCheckbuttons $typeattribs]
+
+ set attribs_select [checkbutton $fm_attribs_select.type -text "Show attributes" \
+ -variable Apol_Types::opts(attribs)]
+ set a_types [checkbutton $fm_attribs_select.types -text "Include types" \
+ -variable Apol_Types::opts(attribs:show_types) -state disabled]
+ set a_typeattribs [checkbutton $fm_attribs_select.typeattribs -text "Include types' attributes" \
+ -variable Apol_Types::opts(attribs:show_attribs) -state disabled]
+ pack $attribs_select -anchor w
+ pack $a_types $a_typeattribs -anchor w -padx 8
+ trace add variable Apol_Types::opts(attribs) write \
+ [list Apol_Types::_toggleCheckbuttons [list $a_typeattribs $a_types]]
+
+ set widgets(regexp) [Apol_Widget::makeRegexpEntry $ofm.regexpf]
+ Apol_Widget::setRegexpEntryState $widgets(regexp) 1
+
+ pack $widgets(regexp) -side left -padx 4 -pady 2 -anchor nw
+
+ set ok [button $ofm.ok -text OK -width 6 -command Apol_Types::_searchTypes]
+ pack $ok -side right -padx 5 -pady 5 -anchor ne
+
+ set widgets(results) [Apol_Widget::makeSearchResults [$rbox getframe].results]
+ pack $widgets(results) -expand yes -fill both
+
+ return $frame
+}
+
+proc Apol_Types::open {ppath} {
+ set q [new_apol_type_query_t]
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ variable typelist [lsort [type_vector_to_list $v]]
+ $v -acquire
+ $v -delete
+
+ set q [new_apol_attr_query_t]
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ variable attriblist [lsort [attr_vector_to_list $v]]
+ $v -acquire
+ $v -delete
+}
+
+proc Apol_Types::close {} {
+ variable widgets
+
+ _initializeVars
+ set Apol_Types::typelist {}
+ set Apol_Types::attriblist {}
+ Apol_Widget::clearSearchResults $widgets(results)
+}
+
+proc Apol_Types::getTextWidget {} {
+ variable widgets
+ return $widgets(results).tb
+}
+
+# Given a type or alias name, return non-zero if that type/alias is
+# within the policy. If no policy has been loaded then return zero.
+proc Apol_Types::isTypeInPolicy {type} {
+ if {![ApolTop::is_policy_open]} {
+ return 0
+ }
+ set q [new_apol_type_query_t]
+ $q set_type $::ApolTop::policy $type
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ if {$v == "NULL" || [$v get_size] == 0} {
+ set retval 0
+ } else {
+ set retval 1
+ }
+ $v -acquire
+ $v -delete
+ set retval
+}
+
+# Given an attribute name, return non-zero if that attribute is within
+# the loaded policy. If no policy has been loaded then return zero.
+proc Apol_Types::isAttributeInPolicy {attrib} {
+ variable attriblist
+ if {[ApolTop::is_policy_open] && [lsearch $attriblist $attrib] >= 0} {
+ return 1
+ }
+ return 0
+}
+
+# Return a sorted list of all type names (not attributes nor aliases)
+# within the current policy. If no policy is open then return an
+# empty list.
+proc Apol_Types::getTypes {} {
+ variable typelist
+ set typelist
+}
+
+# Return a list of all attribute names within the current policy. If
+# no policy is open then return an empty list.
+proc Apol_Types::getAttributes {} {
+ variable attriblist
+ set attriblist
+}
+
+#### private functions below ####
+
+proc Apol_Types::_initializeVars {} {
+ variable opts
+ array set opts {
+ types 1 types:show_attribs 1 types:show_aliases 1
+ attribs 0 attribs:show_types 1 attribs:show_attribs 1
+ }
+}
+
+proc Apol_Types::_toggleCheckbuttons {w name1 name2 op} {
+ variable opts
+ variable widgets
+ if {$opts($name2)} {
+ foreach x $w {
+ $x configure -state normal
+ }
+ } else {
+ foreach x $w {
+ $x configure -state disabled
+ }
+ }
+ if {!$opts(types) && !$opts(attribs)} {
+ Apol_Widget::setRegexpEntryState $widgets(regexp) 0
+ } else {
+ Apol_Widget::setRegexpEntryState $widgets(regexp) 1
+ }
+}
+
+proc Apol_Types::_popupTypeInfo {which ta} {
+ if {[Apol_File_Contexts::is_db_loaded]} {
+ set entry_vector [Apol_File_Contexts::get_fc_files_for_ta $which $ta]
+ set index_file_loaded 1
+ } else {
+ set entry_vector {}
+ set index_file_loaded 0
+ }
+
+ if {$which == "type"} {
+ set info_ta [_renderType $ta 1 1]
+ } else {
+ set info_ta [_renderAttrib $ta 1 0]
+ }
+
+ set w .ta_infobox
+ destroy $w
+
+ set w [Dialog .ta_infobox -cancel 0 -default 0 -modal none -parent . -separator 1 -title $ta]
+ $w add -text "Close" -command [list destroy $w]
+
+ set notebook [NoteBook [$w getframe].nb]
+ pack $notebook -expand 1 -fill both
+
+ set ta_info_tab [$notebook insert end ta_info_tab]
+ set fc_info_tab [$notebook insert end fc_info_tab -text "Files"]
+
+ if {$which == "type"} {
+ $notebook itemconfigure ta_info_tab -text "Attributes"
+ } else {
+ $notebook itemconfigure ta_info_tab -text "Types"
+ }
+ set sw [ScrolledWindow [$notebook getframe ta_info_tab].sw -scrollbar both -auto both]
+ set text [text [$sw getframe].text -wrap none -font {helvetica 10} -bg white]
+ $sw setwidget $text
+ pack $sw -expand 1 -fill both
+ $text insert 0.0 $info_ta
+ $text configure -state disabled
+
+ if {$which != "type"} {
+ set l [label [$notebook getframe fc_info_tab].l \
+ -text "Files labeled with types that are members of this attribute:" \
+ -justify left]
+ pack $l -anchor nw
+ }
+ set sw [ScrolledWindow [$notebook getframe fc_info_tab].sw -scrollbar both -auto both]
+ set fc_text [text [$sw getframe].text -wrap none -font {helvetica 10} -bg white]
+ $sw setwidget $fc_text
+ pack $sw -expand 1 -fill both
+
+ $notebook raise [$notebook page 0]
+
+ if {$index_file_loaded} {
+ if {$entry_vector != {}} {
+ set num [$entry_vector get_size]
+ $fc_text insert 1.0 "Number of files: $num\n\n"
+ for {set i 0} {$i < $num} {incr i} {
+ set entry [sefs_entry_from_void [$entry_vector get_element $i]]
+ $fc_text insert end "[$entry toString]\n"
+ }
+ $entry_vector -delete
+ } else {
+ $fc_text insert end "No files found."
+ }
+ } else {
+ $fc_text insert 0.0 "No index file is loaded. Load an index file through the File Contexts tab."
+ }
+ $fc_text configure -state disabled
+
+ $w draw {} 0 400x400
+}
+
+proc Apol_Types::_searchTypes {} {
+ variable widgets
+ variable opts
+
+ Apol_Widget::clearSearchResults $widgets(results)
+ if {![ApolTop::is_policy_open]} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No current policy file is opened."
+ return
+ }
+ if {$opts(types) == 0 && $opts(attribs) == 0} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No search options provided."
+ return
+ }
+ set use_regexp [Apol_Widget::getRegexpEntryState $widgets(regexp)]
+ set regexp [Apol_Widget::getRegexpEntryValue $widgets(regexp)]
+ if {$use_regexp} {
+ if {$regexp == {}} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No regular expression provided."
+ return
+ }
+ } else {
+ set regexp {}
+ }
+
+ set results {}
+ if {$opts(types)} {
+ set q [new_apol_type_query_t]
+ $q set_type $::ApolTop::policy $regexp
+ $q set_regex $::ApolTop::policy $use_regexp
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set types_data [type_vector_to_list $v]
+ $v -acquire
+ $v -delete
+ append results "TYPES ([llength $types_data]):\n\n"
+ foreach t [lsort $types_data] {
+ append results "[_renderType $t $opts(types:show_attribs) $opts(types:show_aliases)]\n"
+ }
+ }
+ if {$opts(attribs)} {
+ set q [new_apol_attr_query_t]
+ $q set_attr $::ApolTop::policy $regexp
+ $q set_regex $::ApolTop::policy $use_regexp
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set attribs_data [attr_vector_to_list $v]
+ $v -acquire
+ $v -delete
+ if {$opts(types)} {
+ append results "\n\n"
+ }
+ append results "ATTRIBUTES ([llength $attribs_data]):\n\n"
+ foreach a [lsort $attribs_data] {
+ append results "[_renderAttrib $a $opts(attribs:show_types) $opts(attribs:show_attribs)]\n"
+ }
+ }
+ Apol_Widget::appendSearchResultText $widgets(results) $results
+}
+
+proc Apol_Types::_renderType {type_name show_attribs show_aliases} {
+ set qpol_type_datum [new_qpol_type_t $::ApolTop::qpolicy $type_name]
+ set aliases {}
+ set attribs {}
+ set i [$qpol_type_datum get_alias_iter $::ApolTop::qpolicy]
+ set aliases [iter_to_str_list $i]
+ $i -acquire
+ $i -delete
+ set i [$qpol_type_datum get_attr_iter $::ApolTop::qpolicy]
+ foreach a [iter_to_list $i] {
+ set a [qpol_type_from_void $a]
+ lappend attribs [$a get_name $::ApolTop::qpolicy]
+ }
+ $i -acquire
+ $i -delete
+
+ set text "$type_name"
+ if {$show_aliases && [llength $aliases] > 0} {
+ append text " alias [list $aliases]"
+ }
+ if {$show_attribs} {
+ append text " ([llength $attribs] attribute"
+ if {[llength $attribs] != 1} {
+ append text s
+ }
+ append text ")\n"
+ foreach a [lsort $attribs] {
+ append text " $a\n"
+ }
+ }
+ return $text
+}
+
+proc Apol_Types::_renderAttrib {attrib_name show_types show_attribs} {
+ set qpol_type_datum [new_qpol_type_t $::ApolTop::qpolicy $attrib_name]
+
+ set text "$attrib_name"
+ if {$show_types} {
+ set types {}
+ set i [$qpol_type_datum get_type_iter $::ApolTop::qpolicy]
+ foreach t [iter_to_list $i] {
+ set t [qpol_type_from_void $t]
+ lappend types [$t get_name $::ApolTop::qpolicy]
+ }
+ $i -acquire
+ $i -delete
+ append text " ([llength $types] type"
+ if {[llength $types] != 1} {
+ append text s
+ }
+ append text ")\n"
+ foreach type_name [lsort $types] {
+ append text " $type_name"
+ if {$show_attribs} {
+ set t [new_qpol_type_t $::ApolTop::qpolicy $type_name]
+ set this_attribs {}
+ set i [$t get_attr_iter $::ApolTop::qpolicy]
+ foreach a [iter_to_list $i] {
+ set a [qpol_type_from_void $a]
+ lappend this_attribs [$a get_name $::ApolTop::qpolicy]
+ }
+ $i -acquire
+ $i -delete
+
+ set this_attribs [lsort $this_attribs]
+ # remove the entry that we know should be there
+ set idx [lsearch -sorted -exact $attrib_name $this_attribs]
+ append text " { [lreplace $this_attribs $idx $idx] }"
+ }
+ append text "\n"
+ }
+ }
+ return $text
+}
diff --git a/apol/users_tab.tcl b/apol/users_tab.tcl
new file mode 100644
index 0000000..ad581d3
--- /dev/null
+++ b/apol/users_tab.tcl
@@ -0,0 +1,313 @@
+# Copyright (C) 2001-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
+
+namespace eval Apol_Users {
+ variable opts
+ variable widgets
+ variable users_list {}
+}
+
+proc Apol_Users::create {tab_name nb} {
+ variable opts
+ variable widgets
+
+ _initializeVars
+
+ # Layout frames
+ set frame [$nb insert end $tab_name -text "Users"]
+ set pw1 [PanedWindow $frame.pw -side top]
+ set rpane [$pw1 add -weight 0]
+ set spane [$pw1 add -weight 1]
+
+ # Title frames
+ set userbox [TitleFrame $rpane.userbox -text "Users"]
+ set s_optionsbox [TitleFrame $spane.obox -text "Search Options"]
+ set resultsbox [TitleFrame $spane.rbox -text "Search Results"]
+ pack $pw1 -fill both -expand yes
+ pack $s_optionsbox -side top -expand 0 -fill both -padx 2
+ pack $userbox -fill both -expand yes
+ pack $resultsbox -expand yes -fill both -padx 2
+
+ # Users listbox widget
+ set users_listbox [Apol_Widget::makeScrolledListbox [$userbox getframe].lb -width 20 -listvar Apol_Users::users_list]
+ Apol_Widget::setListboxCallbacks $users_listbox \
+ {{"Display User Info" {Apol_Users::_popupUserInfo users}}}
+ pack $users_listbox -fill both -expand yes
+
+ # Search options subframes
+ set ofm [$s_optionsbox getframe]
+ set verboseFrame [frame $ofm.verbose]
+ set rolesFrame [frame $ofm.roles]
+ set defaultFrame [frame $ofm.default]
+ set rangeFrame [frame $ofm.range]
+ pack $verboseFrame $rolesFrame $defaultFrame $rangeFrame \
+ -side left -padx 4 -pady 2 -anchor nw -expand 0 -fill y
+
+ radiobutton $verboseFrame.all_info -text "All information" \
+ -variable Apol_Users::opts(showSelection) -value all
+ radiobutton $verboseFrame.names_only -text "Names only" \
+ -variable Apol_Users::opts(showSelection) -value names
+ pack $verboseFrame.all_info $verboseFrame.names_only -anchor w -padx 5 -pady 4
+
+ checkbutton $rolesFrame.cb -variable Apol_Users::opts(useRole) -text "Role"
+ set widgets(role) [ComboBox $rolesFrame.combo -width 12 -textvariable Apol_Users::opts(role) \
+ -helptext "Type or select a role" -state disabled \
+ -autopost 1]
+ trace add variable Apol_Users::opts(useRole) write \
+ [list Apol_Users::_toggleRolesCheckbutton $widgets(role)]
+ pack $rolesFrame.cb -anchor nw
+ pack $widgets(role) -padx 4
+
+ set widgets(defaultCB) [checkbutton $defaultFrame.cb -variable Apol_Users::opts(enable_default) -text "Default MLS level"]
+ set defaultDisplay [Entry $defaultFrame.display -textvariable Apol_Users::opts(default_level_display) -width 16 -editable 0]
+ set defaultButton [button $defaultFrame.button -text "Select Level..." -state disabled -command [list Apol_Users::_show_level_dialog]]
+ trace add variable Apol_Users::opts(enable_default) write \
+ [list Apol_Users::_toggleDefaultCheckbutton $widgets(defaultCB) $defaultDisplay $defaultButton]
+ trace add variable Apol_Users::opts(default_level) write \
+ [list Apol_Users::_updateDefaultDisplay $defaultDisplay]
+ pack $widgets(defaultCB) -side top -anchor nw -expand 0
+ pack $defaultDisplay -side top -expand 0 -fill x -padx 4
+ pack $defaultButton -side top -expand 1 -fill none -padx 4 -anchor ne
+
+ set widgets(range) [Apol_Widget::makeRangeSelector $rangeFrame.range Users]
+ pack $widgets(range) -expand 1 -fill x
+
+ # Action Buttons
+ button $ofm.ok -text OK -width 6 -command Apol_Users::_searchUsers
+ pack $ofm.ok -side right -pady 5 -padx 5 -anchor ne
+
+ set widgets(results) [Apol_Widget::makeSearchResults [$resultsbox getframe].results]
+ pack $widgets(results) -expand yes -fill both
+
+ return $frame
+}
+
+proc Apol_Users::open {ppath} {
+ set q [new_apol_user_query_t]
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ variable users_list [lsort [user_vector_to_list $v]]
+ $v -acquire
+ $v -delete
+
+ variable opts
+ variable widgets
+ $Apol_Users::widgets(role) configure -values [Apol_Roles::getRoles]
+ if {[ApolTop::is_capable "mls"]} {
+ Apol_Widget::setRangeSelectorCompleteState $widgets(range) normal
+ $widgets(defaultCB) configure -state normal
+ } else {
+ Apol_Widget::clearRangeSelector $widgets(range)
+ Apol_Widget::setRangeSelectorCompleteState $widgets(range) disabled
+ set opts(enable_default) 0
+ $widgets(defaultCB) configure -state disabled
+ }
+}
+
+proc Apol_Users::close {} {
+ variable widgets
+
+ _initializeVars
+ variable users_list {}
+ $widgets(role) configure -values ""
+ Apol_Widget::clearSearchResults $widgets(results)
+ Apol_Widget::clearRangeSelector $widgets(range)
+ Apol_Widget::setRangeSelectorCompleteState $widgets(range) normal
+ $widgets(defaultCB) configure -state normal
+}
+
+proc Apol_Users::getTextWidget {} {
+ variable widgets
+ return $widgets(results).tb
+}
+
+# Return a list of all user names within the current policy. If no
+# policy is loaded then return an empty list.
+proc Apol_Users::getUsers {} {
+ variable users_list
+ set users_list
+}
+
+#### private functions below ####
+
+proc Apol_Users::_initializeVars {} {
+ variable opts
+ array set opts {
+ showSelection all
+ useRole 0 role {}
+ enable_default 0 default_level {}
+ }
+}
+
+proc Apol_Users::_toggleRolesCheckbutton {path name1 name2 op} {
+ variable opts
+ if {$opts($name2)} {
+ $path configure -state normal -entrybg white
+ } else {
+ $path configure -state disabled -entrybg $ApolTop::default_bg_color
+ }
+}
+
+proc Apol_Users::_toggleDefaultCheckbutton {cb display button name1 name2 op} {
+ variable opts
+ if {$opts($name2)} {
+ $button configure -state normal
+ $display configure -state normal
+ } else {
+ $button configure -state disabled
+ $display configure -state disabled
+ }
+}
+
+proc Apol_Users::_show_level_dialog {} {
+ variable opts
+ .mainframe.frame.nb.fcomponents.nb.fApol_Users.pw.f1.frame.obox.f.default.button configure -state disabled
+ set new_level [Apol_Level_Dialog::getLevel $opts(default_level)]
+ if {$new_level != {}} {
+ set opts(default_level) $new_level
+ $opts(default_level) -acquire
+ }
+ .mainframe.frame.nb.fcomponents.nb.fApol_Users.pw.f1.frame.obox.f.default.button configure -state normal
+}
+
+proc Apol_Users::_updateDefaultDisplay {display name1 name2 op} {
+ variable opts
+ if {$opts(default_level) == {}} {
+ set opts(default_level_display) {}
+ $display configure -helptext {}
+ } else {
+ set level [$opts(default_level) render $::ApolTop::policy]
+ if {$level == {}} {
+ set opts(default_level_display) "<invalid MLS level>"
+ } else {
+ set opts(default_level_display) $level
+ }
+ $display configure -helptext $opts(default_level_display)
+ }
+}
+
+proc Apol_Users::_popupUserInfo {which user} {
+ Apol_Widget::showPopupText $user [_renderUser $user 1]
+}
+
+proc Apol_Users::_searchUsers {} {
+ variable opts
+ variable widgets
+ .mainframe.frame.nb.fcomponents.nb.fApol_Users.pw.f1.frame.obox.f.ok configure -state disabled
+
+ Apol_Widget::clearSearchResults $widgets(results)
+ if {![ApolTop::is_policy_open]} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No current policy file is opened."
+ .mainframe.frame.nb.fcomponents.nb.fApol_Users.pw.f1.frame.obox.f.ok configure -state normal
+ return
+ }
+ if {$opts(useRole)} {
+ if {$opts(role) == ""} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No role selected."
+ .mainframe.frame.nb.fcomponents.nb.fApol_Users.pw.f1.frame.obox.f.ok configure -state normal
+ return
+ }
+ set role $opts(role)
+ } else {
+ set role {}
+ }
+ if {$opts(enable_default)} {
+ if {$opts(default_level) == {}} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No default level selected."
+ .mainframe.frame.nb.fcomponents.nb.fApol_Users.pw.f1.frame.obox.f.ok configure -state normal
+ return
+ }
+ set default $opts(default_level)
+ # the user query will handle destroying the apol_mls_level object
+ } else {
+ set default NULL
+ }
+ set range_enabled [Apol_Widget::getRangeSelectorState $widgets(range)]
+ foreach {range range_type} [Apol_Widget::getRangeSelectorValue $widgets(range)] {break}
+ if {$range_enabled} {
+ if {$range == {}} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No range selected."
+ .mainframe.frame.nb.fcomponents.nb.fApol_Users.pw.f1.frame.obox.f.ok configure -state normal
+ return
+ }
+ # the user query will handle destroying the apol_mls_range object
+ } else {
+ set range NULL
+ }
+ if {$opts(showSelection) == "all"} {
+ set show_all 1
+ } else {
+ set show_all 0
+ }
+
+ set q [new_apol_user_query_t]
+ $q set_role $::ApolTop::policy $role
+ $q set_default_level $::ApolTop::policy $default
+ $q set_range $::ApolTop::policy $range $range_type
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set users_data [user_vector_to_list $v]
+ $v -acquire
+ $v -delete
+
+ set text "USERS:\n"
+ if {[llength $users_data] == 0} {
+ append text "Search returned no results."
+ } else {
+ foreach u [lsort -index 0 $users_data] {
+ append text "\n[_renderUser $u $show_all]"
+ }
+ }
+ Apol_Widget::appendSearchResultText $widgets(results) $text
+ .mainframe.frame.nb.fcomponents.nb.fApol_Users.pw.f1.frame.obox.f.ok configure -state normal
+}
+
+proc Apol_Users::_renderUser {user_name show_all} {
+ set text "$user_name"
+ if {!$show_all} {
+ return $text
+ }
+ set qpol_user_datum [new_qpol_user_t $::ApolTop::qpolicy $user_name]
+ if {[ApolTop::is_capable "mls"]} {
+ set default [$qpol_user_datum get_dfltlevel $::ApolTop::qpolicy]
+ set apol_default [new_apol_mls_level_t $::ApolTop::policy $default]
+ append text " level [$apol_default render $::ApolTop::policy]"
+ $apol_default -acquire
+ $apol_default -delete
+ set range [$qpol_user_datum get_range $::ApolTop::qpolicy]
+ set apol_range [new_apol_mls_range_t $::ApolTop::policy $range]
+ append text " range [$apol_range render $::ApolTop::policy]"
+ $apol_range -acquire
+ $apol_range -delete
+ }
+ set i [$qpol_user_datum get_role_iter $::ApolTop::qpolicy]
+ set roles {}
+ while {![$i end]} {
+ set qpol_role_datum [qpol_role_from_void [$i get_item]]
+ lappend roles [$qpol_role_datum get_name $::ApolTop::qpolicy]
+ $i next
+ }
+ append text " ([llength $roles] role"
+ if {[llength $roles] != 1} {
+ append text "s"
+ }
+ append text ")\n"
+ foreach r $roles {
+ append text " $r\n"
+ }
+ return $text
+}
diff --git a/apol/util.tcl b/apol/util.tcl
new file mode 100644
index 0000000..dbcdda6
--- /dev/null
+++ b/apol/util.tcl
@@ -0,0 +1,312 @@
+# Copyright (C) 2001-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
+
+# This file contains miscellaneous convenience routines to convert
+# between Tcl and libapol/libqpol.
+
+proc iter_to_list {iter} {
+ set list {}
+ while {![$iter end]} {
+ lappend list [$iter get_item]
+ $iter next
+ }
+ return $list
+}
+
+proc iter_to_str_list {iter} {
+ set list {}
+ while {![$iter end]} {
+ lappend list [to_str [$iter get_item]]
+ $iter next
+ }
+ return $list
+}
+
+proc list_to_vector {list} {
+ set v [new_apol_vector_t]
+ $v -acquire
+ foreach x $list {
+ $v append $x
+ }
+ return $v
+}
+
+proc list_to_str_vector {list} {
+ set v [new_apol_string_vector_t]
+ $v -acquire
+ foreach x $list {
+ $v append $x
+ }
+ return $v
+}
+
+proc str_vector_to_list {v} {
+ set list {}
+ for {set i 0} {$v != "NULL" && $i < [$v get_size]} {incr i} {
+ lappend list [$v get_element $i]
+ }
+ return $list
+}
+
+proc attr_vector_to_list {v} {
+ type_vector_to_list $v
+}
+
+proc avrule_vector_to_list {v} {
+ set list {}
+ for {set i 0} {$v != "NULL" && $i < [$v get_size]} {incr i} {
+ set q [qpol_avrule_from_void [$v get_element $i]]
+ lappend list $q
+ }
+ return $list
+}
+
+proc bool_vector_to_list {v} {
+ set list {}
+ for {set i 0} {$v != "NULL" && $i < [$v get_size]} {incr i} {
+ set q [qpol_bool_from_void [$v get_element $i]]
+ lappend list [$q get_name $::ApolTop::qpolicy]
+ }
+ return $list
+}
+
+proc cat_vector_to_list {v} {
+ set list {}
+ for {set i 0} {$v != "NULL" && $i < [$v get_size]} {incr i} {
+ set q [qpol_cat_from_void [$v get_element $i]]
+ lappend list [$q get_name $::ApolTop::qpolicy]
+ }
+ return $list
+}
+
+proc class_vector_to_list {v} {
+ set list {}
+ for {set i 0} {$v != "NULL" && $i < [$v get_size]} {incr i} {
+ set q [qpol_class_from_void [$v get_element $i]]
+ lappend list [$q get_name $::ApolTop::qpolicy]
+ }
+ return $list
+}
+
+proc common_vector_to_list {v} {
+ set list {}
+ for {set i 0} {$v != "NULL" && $i < [$v get_size]} {incr i} {
+ set q [qpol_common_from_void [$v get_element $i]]
+ lappend list [$q get_name $::ApolTop::qpolicy]
+ }
+ return $list
+}
+
+# Convert a vector a qpol_cond_t objects to a list of qpol_cond_t
+# objects.
+proc cond_vector_to_list {v} {
+ set list {}
+ for {set i 0} {$v != "NULL" && $i < [$v get_size]} {incr i} {
+ set q [qpol_cond_from_void [$v get_element $i]]
+ lappend list $q
+ }
+ return $list
+}
+
+proc domain_trans_result_vector_to_list {v} {
+ set list {}
+ for {set i 0} {$v != "NULL" && $i < [$v get_size]} {incr i} {
+ set a [apol_domain_trans_result_from_void [$v get_element $i]]
+ lappend list $a
+ }
+ return $list
+}
+
+# Convert a vector a qpol_fs_use_t objects to a list of qpol_fs_use_t
+# objects.
+proc fs_use_vector_to_list {v} {
+ set list {}
+ for {set i 0} {$v != "NULL" && $i < [$v get_size]} {incr i} {
+ set q [qpol_fs_use_from_void [$v get_element $i]]
+ lappend list $q
+ }
+ return $list
+}
+
+# Convert a vector of qpol_genfscon_t objects to a list of
+# qpol_genfscon_t objects.
+proc genfscon_vector_to_list {v} {
+ set list {}
+ for {set i 0} {$v != "NULL" && $i < [$v get_size]} {incr i} {
+ set q [qpol_genfscon_from_void [$v get_element $i]]
+ lappend list $q
+ }
+ return $list
+}
+
+proc infoflow_result_vector_to_list {v} {
+ set list {}
+ for {set i 0} {$v != "NULL" && $i < [$v get_size]} {incr i} {
+ set a [apol_infoflow_result_from_void [$v get_element $i]]
+ lappend list $a
+ }
+ return $list
+}
+
+proc isid_vector_to_list {v} {
+ set list {}
+ for {set i 0} {$v != "NULL" && $i < [$v get_size]} {incr i} {
+ set q [qpol_isid_from_void [$v get_element $i]]
+ lappend list [$q get_name $::ApolTop::qpolicy]
+ }
+ return $list
+}
+
+proc level_vector_to_list {v} {
+ set list {}
+ for {set i 0} {$v != "NULL" && $i < [$v get_size]} {incr i} {
+ set q [qpol_level_from_void [$v get_element $i]]
+ lappend list [$q get_name $::ApolTop::qpolicy]
+ }
+ return $list
+}
+
+proc netifcon_vector_to_list {v} {
+ set list {}
+ for {set i 0} {$v != "NULL" && $i < [$v get_size]} {incr i} {
+ set q [qpol_netifcon_from_void [$v get_element $i]]
+ lappend list [$q get_name $::ApolTop::qpolicy]
+ }
+ return $list
+}
+
+# Convert a vector of qpol_nodecon_t objects to a list of
+# qpol_nodecon_t objects.
+proc nodecon_vector_to_list {v} {
+ set list {}
+ for {set i 0} {$v != "NULL" && $i < [$v get_size]} {incr i} {
+ set q [qpol_nodecon_from_void [$v get_element $i]]
+ lappend list $q
+ }
+ return $list
+}
+
+# Convert a vector of qpol_portcon_t objects to a list of qpol_portcon_t.
+proc portcon_vector_to_list {v} {
+ set list {}
+ for {set i 0} {$v != "NULL" && $i < [$v get_size]} {incr i} {
+ lappend list [qpol_portcon_from_void [$v get_element $i]]
+ }
+ return $list
+}
+
+# Convert a vector of qpol_range_trans_t objects to a list of
+# qpol_role_trans_t.
+proc range_trans_vector_to_list {v} {
+ set list {}
+ for {set i 0} {$v != "NULL" && $i < [$v get_size]} {incr i} {
+ lappend list [qpol_range_trans_from_void [$v get_element $i]]
+ }
+ return $list
+}
+
+proc relabel_result_vector_to_list {v} {
+ set list {}
+ for {set i 0} {$v != "NULL" && $i < [$v get_size]} {incr i} {
+ lappend list [apol_relabel_result_from_void [$v get_element $i]]
+ }
+ return $list
+}
+
+proc relabel_result_pair_vector_to_list {v} {
+ set list {}
+ for {set i 0} {$v != "NULL" && $i < [$v get_size]} {incr i} {
+ lappend list [apol_relabel_result_pair_from_void [$v get_element $i]]
+ }
+ return $list
+}
+
+# Convert a vector of qpol_role_allow_t objects to a list of
+# qpol_role_allow_t.
+proc role_allow_vector_to_list {v} {
+ set list {}
+ for {set i 0} {$v != "NULL" && $i < [$v get_size]} {incr i} {
+ lappend list [qpol_role_allow_from_void [$v get_element $i]]
+ }
+ return $list
+}
+
+# Convert a vector of qpol_role_trans_t objects to a list of
+# qpol_role_trans_t.
+proc role_trans_vector_to_list {v} {
+ set list {}
+ for {set i 0} {$v != "NULL" && $i < [$v get_size]} {incr i} {
+ lappend list [qpol_role_trans_from_void [$v get_element $i]]
+ }
+ return $list
+}
+
+proc role_vector_to_list {v} {
+ set list {}
+ for {set i 0} {$v != "NULL" && $i < [$v get_size]} {incr i} {
+ set q [qpol_role_from_void [$v get_element $i]]
+ lappend list [$q get_name $::ApolTop::qpolicy]
+ }
+ return $list
+}
+
+proc terule_vector_to_list {v} {
+ set list {}
+ for {set i 0} {$v != "NULL" && $i < [$v get_size]} {incr i} {
+ set q [qpol_terule_from_void [$v get_element $i]]
+ lappend list $q
+ }
+ return $list
+}
+
+proc type_vector_to_list {v} {
+ set list {}
+ for {set i 0} {$v != "NULL" && $i < [$v get_size]} {incr i} {
+ set q [qpol_type_from_void [$v get_element $i]]
+ lappend list [$q get_name $::ApolTop::qpolicy]
+ }
+ return $list
+}
+
+proc user_vector_to_list {v} {
+ set list {}
+ for {set i 0} {$v != "NULL" && $i < [$v get_size]} {incr i} {
+ set q [qpol_user_from_void [$v get_element $i]]
+ lappend list [$q get_name $::ApolTop::qpolicy]
+ }
+ return $list
+}
+
+proc list_to_policy_path {path_type primary modules} {
+ if {$path_type == "monolithic"} {
+ set path_type $::APOL_POLICY_PATH_TYPE_MONOLITHIC
+ } else {
+ set path_type $::APOL_POLICY_PATH_TYPE_MODULAR
+ }
+ set ppath [new_apol_policy_path_t $path_type $primary [list_to_str_vector $modules]]
+ $ppath -acquire
+ return $ppath
+}
+
+proc policy_path_to_list {ppath} {
+ if {[$ppath get_type] == $::APOL_POLICY_PATH_TYPE_MONOLITHIC} {
+ set path_type "monolithic"
+ } else {
+ set path_type "modular"
+ }
+ set primary [$ppath get_primary]
+ set modules [str_vector_to_list [$ppath get_modules]]
+ list $path_type $primary $modules
+}