# 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 }