diff options
Diffstat (limited to 'apol/perms_map.tcl')
-rw-r--r-- | apol/perms_map.tcl | 410 |
1 files changed, 410 insertions, 0 deletions
diff --git a/apol/perms_map.tcl b/apol/perms_map.tcl new file mode 100644 index 0000000..c1a1a75 --- /dev/null +++ b/apol/perms_map.tcl @@ -0,0 +1,410 @@ +# Copyright (C) 2003-2007 Tresys Technology, LLC +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +namespace eval Apol_Perms_Map { + variable dialog .apol_perms + variable user_default_pmap_name [file join $::env(HOME) .apol_perm_mapping] + + variable opts ;# options for edit perm map dialog + variable widgets +} + +proc Apol_Perms_Map::close {} { + variable opts + + _close_dialog + set opts(filename) {} + set opts(is_saveable) 0 + set opts(modified) 0 +} + +proc Apol_Perms_Map::showPermMappings {} { + variable dialog + if {[winfo exists $dialog]} { + raise $dialog + } else { + _createEditDialog + _refreshEditDialog + } +} + +# Let the user select a permission map file to load. Returns 1 on +# success, 0 on error. +proc Apol_Perms_Map::openPermMapFromFile {} { + set pmap_name [tk_getOpenFile -title "Select Perm Map to Load" -parent .] + if {$pmap_name != {}} { + return [_loadPermMap $pmap_name [file tail $pmap_name] 1] + } + return 0 +} + +# Attempt to load the "default" permission map. If there exists +# within the user's home directory a file called ".apol_perm_mapping" +# then use that. Otherwise look for the file +# "apol_perm_mapping_ver$ver", where $ver is the currently loaded +# policy version number. If that fails then simply try +# "apol_perm_mapping". If all of that fails, then display an error +# message and abort the loading. Returns 1 on success, 0 on error. +proc Apol_Perms_Map::openDefaultPermMap {} { + variable user_default_pmap_name + if {[file exists $user_default_pmap_name]} { + set pmap_name $user_default_pmap_name + set pmap_short "User Default Permission Map" + set pmap_editable 1 + } else { + set pmap_editable 0 + # try policy-specific file + set policy_version [apol_tcl_get_policy_version $::ApolTop::policy] + set pmap_name [apol_file_find_path "apol_perm_mapping_ver${policy_version}"] + if {$pmap_name == {}} { + # finally try fallback one + set pmap_name [apol_file_find_path apol_perm_mapping] + if {$pmap_name == {}} { + set message "Could not locate system default permission map. You must explicitly load a permission map from file." + if {[Apol_Progress_Dialog::is_waiting]} { + error $message + } else { + tk_messageBox -icon error -type ok -title "Permission Maps" \ + -message $message + } + return 0 + } + } + set pmap_short "System Default Permission Map (Read-Only)" + } + return [_loadPermMap $pmap_name $pmap_short $pmap_editable] +} + +proc Apol_Perms_Map::savePermMap {} { + variable opts + if {!$opts(is_saveable)} { + savePermMapAs + } else { + _savePermMap $opts(filename) $opts(shortname) + } +} + +proc Apol_Perms_Map::savePermMapAs {} { + set pmap_name [tk_getSaveFile -title "Save Perm Map" -parent .] + if {$pmap_name != {}} { + _savePermMap $pmap_name [file tail $pmap_name] + } +} + +proc Apol_Perms_Map::saveDefaultPermMap {} { + variable user_default_pmap_name + variable opts + _savePermMap $user_default_pmap_name "User Default Permission Map" +} + +proc Apol_Perms_Map::is_pmap_loaded {} { + variable opts + if {$opts(filename) == {}} { + return 0 + } + return 1 +} + +#################### private functions below #################### + + +proc Apol_Perms_Map::_loadPermMap {filename shortname saveable} { + if {[catch {$::ApolTop::policy open_permmap $filename} err]} { + if {[Apol_Progress_Dialog::is_waiting]} { + error $err + } else { + tk_messageBox -icon error -type ok -title "Permission Maps" -message $err + return 0 + } + } + variable opts + set opts(filename) $filename + set opts(shortname) $shortname + set opts(is_saveable) $saveable + set opts(modified) 0 + if {$err != {}} { + set len [llength [split $err "\n"]] + if {$len > 5} { + incr len -4 + set err [lrange [split $err "\n"] 0 3] + lappend err "(plus $len more lines)" + set err [join $err "\n"] + } + if {![Apol_Progress_Dialog::is_waiting]} { + set message "There were warnings while opening the permission map:" + tk_messageBox -icon warning -type ok -title "Permission Maps" \ + -message "$message\n\n$err" + } + } else { + if {![Apol_Progress_Dialog::is_waiting]} { + tk_messageBox -icon info -type ok -title "Permission Maps" \ + -message "Permission map successfully loaded." + } + } + variable dialog + if {[winfo exists $dialog]} { + _refreshEditDialog + } + return 1 +} + +proc Apol_Perms_Map::_createEditDialog {} { + variable dialog + variable opts + variable widgets + + set title "Permissions Mappings: $opts(shortname)" + Dialog $dialog -parent . -separator 1 -title $title -modal none \ + -default 0 -cancel 2 + set topf [frame [$dialog getframe].top] + pack $topf -side top -expand 1 -fill both + + set classes_box [TitleFrame $topf.classes -text "Object Classes"] + pack $classes_box -side left -padx 2 -pady 2 -expand 0 -fill y + set widgets(classes) [Apol_Widget::makeScrolledListbox [$classes_box getframe].c \ + -height 16 -width 24 -listvar Apol_Perms_Map::opts(classes)] + bind $widgets(classes).lb <<ListboxSelect>> Apol_Perms_Map::_refreshPermEdit + pack $widgets(classes) -expand 1 -fill both + + set results_box [TitleFrame $topf.perms -text "Permission Mappings"] + pack $results_box -side right -padx 2 -pady 2 -expand 1 -fill both + set sw [ScrolledWindow [$results_box getframe].sw -auto both] + set widgets(perms) [ScrollableFrame $sw.perms -width 300] + $sw setwidget $widgets(perms) + pack $sw -expand 1 -fill both + + set label_box [frame [$dialog getframe].l] + pack $label_box -side bottom -anchor center + set widgets(l1) [label $label_box.l1 -fg red -text ""] + set widgets(l2) [label $label_box.l2 -text ""] + pack $widgets(l1) $widgets(l2) -side left + # delay setting the labels' text until [_refresh_edit_dialog], to + # see if anything is unmapped + + $dialog add -text "OK" -command Apol_Perms_Map::_okay + $dialog add -text "Apply" -command Apol_Perms_Map::_apply + $dialog add -text "Cancel" -command Apol_Perms_Map::_cancel + + trace add variable Apol_Perms_Map::opts(modified) write \ + Apol_Perms_Map::_toggleButtons + + # forcibly invoke the button callback + set opts(modified) $opts(modified) + $dialog draw +} + +proc Apol_Perms_Map::_refreshEditDialog {} { + variable opts + variable widgets + + array set opts { + classes {} + } + + set all_mapped 1 + set class_index 0 + foreach class [Apol_Class_Perms::getClasses] { + set suffix {} + set perm_list {} + foreach perm [Apol_Class_Perms::getPermsForClass $class] { + set direction [$::ApolTop::policy get_permmap_direction $class $perm] + set weight [$::ApolTop::policy get_permmap_weight $class $perm] + set opts(p:${class}:${perm}:map) $direction + set opts(p:${class}:${perm}:weight) $weight + if {$direction == $::APOL_PERMMAP_UNMAPPED} { + set suffix * + set all_mapped 0 + } + lappend perm_list [list $perm $direction $weight] + } + + # store original perm map values, needed if user cancels dialog + set opts(c:$class) $perm_list + lappend opts(classes) "$class$suffix" + if {$suffix != {}} { + $widgets(classes).lb itemconfigure $class_index -foreground red + } + incr class_index + } + + # add the warning to the bottom if there exists any unmapped permissions + if {!$all_mapped} { + $widgets(l1) configure -text "*" + $widgets(l2) configure -text " - Undefined permission mapping(s)" + } else { + $widgets(l1) configure -text "" + $widgets(l2) configure -text "" + } +} + +proc Apol_Perms_Map::_refreshPermEdit {} { + variable opts + variable widgets + + focus $widgets(classes).lb + + set perms [$widgets(perms) getframe] + foreach w [winfo children $perms] { + destroy $w + } + + if {[set selection [$widgets(classes).lb curselection]] == {}} { + return + } + set class [lindex $opts(classes) [lindex $selection 0]] + set class [string trimright $class "*"] + + foreach perm $opts(c:$class) { + foreach {perm map weight} $perm {break} + if {$map != $::APOL_PERMMAP_UNMAPPED} { + set l [label $perms.$perm:l -text $perm -anchor w] + } else { + set l [label $perms.$perm:l -text "${perm}*" -fg red -anchor w] + } + # tk_optionMenu does not have a -command flag, so implement an + # option menu via a menubutton + set menubutton [menubutton $perms.$perm:mb -bd 2 -relief raised \ + -indicatoron 1 -width 8 \ + -textvariable Apol_Perms_Map::opts(p:${class}:${perm}:map_label)] + set menu [menu $menubutton.m -type normal -tearoff 0] + $menubutton configure -menu $menu + $menu add radiobutton -label "Read" -value $::APOL_PERMMAP_READ \ + -command [list Apol_Perms_Map::_togglePermMap $class $perm 1] \ + -variable Apol_Perms_Map::opts(p:${class}:${perm}:map) + $menu add radiobutton -label "Write" -value $::APOL_PERMMAP_WRITE \ + -command [list Apol_Perms_Map::_togglePermMap $class $perm 1] \ + -variable Apol_Perms_Map::opts(p:${class}:${perm}:map) + $menu add radiobutton -label "Both" -value $::APOL_PERMMAP_BOTH \ + -command [list Apol_Perms_Map::_togglePermMap $class $perm 1] \ + -variable Apol_Perms_Map::opts(p:${class}:${perm}:map) + $menu add radiobutton -label "None" -value $::APOL_PERMMAP_NONE \ + -command [list Apol_Perms_Map::_togglePermMap $class $perm 1] \ + -variable Apol_Perms_Map::opts(p:${class}:${perm}:map) + set l2 [label $perms.$perm:l2 -text "Weight:" -anchor e] + set weight [spinbox $perms.$perm:weight -from 1 -to 10 -increment 1 \ + -width 2 -bg white \ + -command [list Apol_Perms_Map::_togglePermMap $class $perm 1] \ + -textvariable Apol_Perms_Map::opts(p:${class}:${perm}:weight)] + grid $l $menubutton $l2 $weight -padx 2 -sticky w -pady 4 + grid configure $l2 -ipadx 10 + _togglePermMap $class $perm 0 + } + grid columnconfigure $perms 0 -minsize 100 -weight 1 + $widgets(perms) xview moveto 0 + $widgets(perms) yview moveto 0 +} + +proc Apol_Perms_Map::_togglePermMap {class perm modification} { + variable opts + set map $opts(p:${class}:${perm}:map) + if {$map == $::APOL_PERMMAP_READ} { + set opts(p:${class}:${perm}:map_label) "Read" + } elseif {$map == $::APOL_PERMMAP_WRITE} { + set opts(p:${class}:${perm}:map_label) "Write" + } elseif {$map == $::APOL_PERMMAP_BOTH} { + set opts(p:${class}:${perm}:map_label) "Both" + } elseif {$map == $::APOL_PERMMAP_NONE} { + set opts(p:${class}:${perm}:map_label) "None" + } else { + set opts(p:${class}:${perm}:map_label) "Unmapped" + } + set opts(modified) $modification +} + +proc Apol_Perms_Map::_toggleButtons {name1 name2 op} { + variable opts + variable dialog + if {$opts(modified)} { + $dialog itemconfigure 1 -state normal + } else { + $dialog itemconfigure 1 -state disabled + } +} + +proc Apol_Perms_Map::_okay {} { + _apply + _close_dialog +} + +proc Apol_Perms_Map::_apply {} { + variable dialog + variable opts + + if {[winfo exists $dialog] && $opts(modified)} { + foreach class $opts(classes) { + set class [string trimright $class "*"] + set perm_list {} + foreach perm [Apol_Class_Perms::getPermsForClass $class] { + set map $opts(p:${class}:${perm}:map) + set weight $opts(p:${class}:${perm}:weight) + if {$map != $::APOL_PERMMAP_UNMAPPED} { + $::ApolTop::policy set_permmap $class $perm $map $weight + } + lappend perm_list [list $perm $map $weight] + } + # overwrite perm map values with applied values + set opts(c:$class) $perm_list + } + } + set opts(modified) 0 +} + +proc Apol_Perms_Map::_cancel {} { + variable opts + + # revert the permission map to original values + if {$opts(modified)} { + foreach class $opts(classes) { + set class [string trimright $class "*"] + foreach perm $opts(c:$class) { + foreach {perm map weight} $perm {break} + $::ApolTop::policy set_permmap $class $perm $map $weight + } + } + } + _close_dialog +} + +proc Apol_Perms_Map::_close_dialog {} { + variable opts + array unset opts c:* + array unset opts p:* + trace remove variable Apol_Perms_Map::opts(modified) write \ + Apol_Perms_Map::_toggleButtons + + variable dialog + destroy $dialog +} + +proc Apol_Perms_Map::_savePermMap {filename shortname} { + variable opts + variable dialog + + _apply + if {[catch {$::ApolTop::policy save_permmap $filename} err]} { + tk_messageBox -icon error -type ok -title "Permission Maps" -message "Error saving permission map: $err" + } else { + set opts(filename) $filename + set opts(shortname) $shortname + set opts(is_saveable) 1 + set opts(modified) 0 + set title "Permissions Mappings: $opts(shortname)" + if {[winfo exists $dialog]} { + $dialog configure -title $title + _refreshEditDialog + _refreshPermEdit + } + } +} |