From 47be9ff57e72906660bb62a515222f482131e1fb Mon Sep 17 00:00:00 2001 From: Miroslav Grepl Date: Fri, 11 Apr 2014 09:37:53 +0200 Subject: Create setools-3.3.7 git repo --- apol/Makefile.am | 131 ++++ apol/analysis_tab.tcl | 326 +++++++++ apol/apol.gif | Bin 0 -> 1305 bytes apol/apol.png | Bin 0 -> 1408 bytes apol/apol.xcf | Bin 0 -> 9291 bytes apol/apol_help.txt | 482 +++++++++++++ apol/apol_tcl.cc | 142 ++++ apol/apol_tcl.i | 451 ++++++++++++ apol/classes_perms_tab.tcl | 484 +++++++++++++ apol/common_widgets.tcl | 688 ++++++++++++++++++ apol/cond_bools_tab.tcl | 266 +++++++ apol/cond_rules_tab.tcl | 281 ++++++++ apol/context_dialog.tcl | 340 +++++++++ apol/context_selector.tcl | 150 ++++ apol/directflow_module.tcl | 582 +++++++++++++++ apol/domaintrans_help.txt | 141 ++++ apol/domaintrans_module.tcl | 999 ++++++++++++++++++++++++++ apol/file_contexts_tab.tcl | 504 +++++++++++++ apol/file_relabel_help.txt | 68 ++ apol/find.tcl | 134 ++++ apol/foo_module.tcl | 143 ++++ apol/fscontexts_tab.tcl | 472 ++++++++++++ apol/goto.tcl | 78 ++ apol/head.tcl | 29 + apol/infoflow_help.txt | 321 +++++++++ apol/initial_sids_tab.tcl | 142 ++++ apol/level_dialog.tcl | 82 +++ apol/mls_tab.tcl | 332 +++++++++ apol/netcontexts_tab.tcl | 878 +++++++++++++++++++++++ apol/open_policy_dialog.tcl | 388 ++++++++++ apol/perm_maps/apol_perm_mapping_ver12 | 575 +++++++++++++++ apol/perm_maps/apol_perm_mapping_ver15 | 580 +++++++++++++++ apol/perm_maps/apol_perm_mapping_ver16 | 560 +++++++++++++++ apol/perm_maps/apol_perm_mapping_ver17 | 561 +++++++++++++++ apol/perm_maps/apol_perm_mapping_ver18 | 922 ++++++++++++++++++++++++ apol/perm_maps/apol_perm_mapping_ver19 | 952 +++++++++++++++++++++++++ apol/perm_maps/apol_perm_mapping_ver20 | 993 ++++++++++++++++++++++++++ apol/perm_maps/apol_perm_mapping_ver21 | 998 ++++++++++++++++++++++++++ apol/perm_maps/apol_perm_mapping_ver22 | 998 ++++++++++++++++++++++++++ apol/perm_maps/apol_perm_mapping_ver23 | 998 ++++++++++++++++++++++++++ apol/perm_maps/apol_perm_mapping_ver24 | 1227 +++++++++++++++++++++++++++++++ apol/perms_map.tcl | 410 +++++++++++ apol/policyconf.tcl | 102 +++ apol/progress_dialog.tcl | 74 ++ apol/range_dialog.tcl | 132 ++++ apol/range_selector.tcl | 156 ++++ apol/range_trans.tcl | 204 ++++++ apol/rbac_tab.tcl | 490 +++++++++++++ apol/relabel_module.tcl | 898 +++++++++++++++++++++++ apol/roles_tab.tcl | 196 +++++ apol/terules_tab.tcl | 1034 +++++++++++++++++++++++++++ apol/top.tcl | 1228 ++++++++++++++++++++++++++++++++ apol/transflow_module.tcl | 1156 ++++++++++++++++++++++++++++++ apol/types_relation_help.txt | 53 ++ apol/types_relation_module.tcl | 770 ++++++++++++++++++++ apol/types_tab.tcl | 411 +++++++++++ apol/users_tab.tcl | 313 ++++++++ apol/util.tcl | 312 ++++++++ 58 files changed, 26337 insertions(+) create mode 100644 apol/Makefile.am create mode 100644 apol/analysis_tab.tcl create mode 100644 apol/apol.gif create mode 100644 apol/apol.png create mode 100644 apol/apol.xcf create mode 100644 apol/apol_help.txt create mode 100644 apol/apol_tcl.cc create mode 100644 apol/apol_tcl.i create mode 100644 apol/classes_perms_tab.tcl create mode 100644 apol/common_widgets.tcl create mode 100644 apol/cond_bools_tab.tcl create mode 100644 apol/cond_rules_tab.tcl create mode 100644 apol/context_dialog.tcl create mode 100644 apol/context_selector.tcl create mode 100644 apol/directflow_module.tcl create mode 100644 apol/domaintrans_help.txt create mode 100644 apol/domaintrans_module.tcl create mode 100644 apol/file_contexts_tab.tcl create mode 100644 apol/file_relabel_help.txt create mode 100644 apol/find.tcl create mode 100644 apol/foo_module.tcl create mode 100644 apol/fscontexts_tab.tcl create mode 100644 apol/goto.tcl create mode 100644 apol/head.tcl create mode 100644 apol/infoflow_help.txt create mode 100644 apol/initial_sids_tab.tcl create mode 100644 apol/level_dialog.tcl create mode 100644 apol/mls_tab.tcl create mode 100644 apol/netcontexts_tab.tcl create mode 100644 apol/open_policy_dialog.tcl create mode 100644 apol/perm_maps/apol_perm_mapping_ver12 create mode 100644 apol/perm_maps/apol_perm_mapping_ver15 create mode 100644 apol/perm_maps/apol_perm_mapping_ver16 create mode 100644 apol/perm_maps/apol_perm_mapping_ver17 create mode 100644 apol/perm_maps/apol_perm_mapping_ver18 create mode 100644 apol/perm_maps/apol_perm_mapping_ver19 create mode 100644 apol/perm_maps/apol_perm_mapping_ver20 create mode 100644 apol/perm_maps/apol_perm_mapping_ver21 create mode 100644 apol/perm_maps/apol_perm_mapping_ver22 create mode 100644 apol/perm_maps/apol_perm_mapping_ver23 create mode 100644 apol/perm_maps/apol_perm_mapping_ver24 create mode 100644 apol/perms_map.tcl create mode 100644 apol/policyconf.tcl create mode 100644 apol/progress_dialog.tcl create mode 100644 apol/range_dialog.tcl create mode 100644 apol/range_selector.tcl create mode 100644 apol/range_trans.tcl create mode 100644 apol/rbac_tab.tcl create mode 100644 apol/relabel_module.tcl create mode 100644 apol/roles_tab.tcl create mode 100644 apol/terules_tab.tcl create mode 100644 apol/top.tcl create mode 100644 apol/transflow_module.tcl create mode 100644 apol/types_relation_help.txt create mode 100644 apol/types_relation_module.tcl create mode 100644 apol/types_tab.tcl create mode 100644 apol/users_tab.tcl create mode 100644 apol/util.tcl (limited to 'apol') 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 <> 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 Apol_Analysis::_switchTab + $widgets(results) bindtabs \ + [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 Binary files /dev/null and b/apol/apol.gif differ diff --git a/apol/apol.png b/apol/apol.png new file mode 100644 index 0000000..7029175 Binary files /dev/null and b/apol/apol.png differ diff --git a/apol/apol.xcf b/apol/apol.xcf new file mode 100644 index 0000000..ea6d26e Binary files /dev/null and b/apol/apol.xcf 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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/** 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 + +#include +#include +#include +#include +#include +#include +#include +#include +%} + +%{ +/* 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(a); + const qpol_avrule_t *r2 = static_cast(b); + apol_policy_t *p = static_cast(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(a); + const qpol_terule_t *r2 = static_cast(b); + apol_policy_t *p = static_cast(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(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(++(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 " \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 " \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 <> [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 [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 [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 [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 [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 [list Apol_Widget::_hyperlink $path %x %y] + $tb tag bind linenum [list $tb configure -cursor hand2] + $tb tag bind linenum [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 <> + } +} + +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: +#
    +#
  1. The (possibly partial) context, an apol_context_t. The caller +# must delete this afterwards. +#
  2. The MLS range search type, one of $::APOL_QUERY_EXACT or its like. +#
  3. If not an empty string, the attribute used to filter types. +#
+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 <> \ + [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 <> \ + [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 <> \ + [list Apol_Analysis_domaintrans::_selectClassListbox $l2 $classes_lb $perms_lb] + bind $perms_lb <> \ + [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-/) +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-. 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 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 <> \ + [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 +# +# 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 +# +# 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 +# +# 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 +# +# 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 +# +# 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 +# +# 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 +# +# 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 +# +# 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 +# +# 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 +# +# 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 +# +# 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 <> 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 [list Apol_Widget::_searchresults_popup %W %x %y] + pack $sw -expand yes -fill both + + bind $textbox <> 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 + # <> 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 <> + } + 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 Apol_TE::_switch_to_tab + $widgets(results) bindtabs \ + [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) <> \ + [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) <> \ + [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 [list ApolTop::_switch_tab $components $rules] + $components bindtabs [list ApolTop::_switch_tab $components $rules] + $rules bindtabs [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 . {focus %W} + bind . {focus %W} + bind . {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 <> \ + [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 [list Apol_Analysis_transflow::_findMore $res $tree] + $res.tb tag bind find_more [list $res.tb configure -cursor hand2] + $res.tb tag bind find_more [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) "" + } 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 +} -- cgit