summaryrefslogtreecommitdiffstats
path: root/apol/users_tab.tcl
blob: ad581d308cfbaee9f87f751aefc61b503c2b866d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
# Copyright (C) 2001-2007 Tresys Technology, LLC
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

namespace eval Apol_Users {
    variable opts
    variable widgets
    variable users_list {}
}

proc Apol_Users::create {tab_name nb} {
    variable opts
    variable widgets

    _initializeVars

    # Layout frames
    set frame [$nb insert end $tab_name -text "Users"]
    set pw1   [PanedWindow $frame.pw -side top]
    set rpane [$pw1 add -weight 0]
    set spane [$pw1 add -weight 1]

    # Title frames
    set userbox [TitleFrame $rpane.userbox -text "Users"]
    set s_optionsbox [TitleFrame $spane.obox -text "Search Options"]
    set resultsbox [TitleFrame $spane.rbox -text "Search Results"]
    pack $pw1 -fill both -expand yes
    pack $s_optionsbox -side top -expand 0 -fill both -padx 2
    pack $userbox -fill both -expand yes
    pack $resultsbox -expand yes -fill both -padx 2

    # Users listbox widget
    set users_listbox [Apol_Widget::makeScrolledListbox [$userbox getframe].lb -width 20 -listvar Apol_Users::users_list]
    Apol_Widget::setListboxCallbacks $users_listbox \
        {{"Display User Info" {Apol_Users::_popupUserInfo users}}}
    pack $users_listbox -fill both -expand yes

    # Search options subframes
    set ofm [$s_optionsbox getframe]
    set verboseFrame [frame $ofm.verbose]
    set rolesFrame [frame $ofm.roles]
    set defaultFrame [frame $ofm.default]
    set rangeFrame [frame $ofm.range]
    pack $verboseFrame $rolesFrame $defaultFrame $rangeFrame \
        -side left -padx 4 -pady 2 -anchor nw -expand 0 -fill y

    radiobutton $verboseFrame.all_info -text "All information" \
        -variable Apol_Users::opts(showSelection) -value all
    radiobutton $verboseFrame.names_only -text "Names only" \
        -variable Apol_Users::opts(showSelection) -value names
    pack $verboseFrame.all_info $verboseFrame.names_only -anchor w -padx 5 -pady 4

    checkbutton $rolesFrame.cb -variable Apol_Users::opts(useRole) -text "Role"
    set widgets(role) [ComboBox $rolesFrame.combo -width 12 -textvariable Apol_Users::opts(role) \
                           -helptext "Type or select a role" -state disabled \
                           -autopost 1]
    trace add variable Apol_Users::opts(useRole) write \
        [list Apol_Users::_toggleRolesCheckbutton $widgets(role)]
    pack $rolesFrame.cb -anchor nw
    pack $widgets(role) -padx 4

    set widgets(defaultCB) [checkbutton $defaultFrame.cb -variable Apol_Users::opts(enable_default) -text "Default MLS level"]
    set defaultDisplay [Entry $defaultFrame.display -textvariable Apol_Users::opts(default_level_display) -width 16 -editable 0]
    set defaultButton [button $defaultFrame.button -text "Select Level..." -state disabled -command [list Apol_Users::_show_level_dialog]]
    trace add variable Apol_Users::opts(enable_default) write \
        [list Apol_Users::_toggleDefaultCheckbutton $widgets(defaultCB) $defaultDisplay $defaultButton]
    trace add variable Apol_Users::opts(default_level) write \
        [list Apol_Users::_updateDefaultDisplay $defaultDisplay]
    pack $widgets(defaultCB) -side top -anchor nw -expand 0
    pack $defaultDisplay -side top -expand 0 -fill x -padx 4
    pack $defaultButton -side top -expand 1 -fill none -padx 4 -anchor ne

    set widgets(range) [Apol_Widget::makeRangeSelector $rangeFrame.range Users]
    pack $widgets(range) -expand 1 -fill x

    # Action Buttons
    button $ofm.ok -text OK -width 6 -command Apol_Users::_searchUsers
    pack $ofm.ok -side right -pady 5 -padx 5 -anchor ne

    set widgets(results) [Apol_Widget::makeSearchResults [$resultsbox getframe].results]
    pack $widgets(results) -expand yes -fill both

    return $frame
}

proc Apol_Users::open {ppath} {
    set q [new_apol_user_query_t]
    set v [$q run $::ApolTop::policy]
    $q -acquire
    $q -delete
    variable users_list [lsort [user_vector_to_list $v]]
    $v -acquire
    $v -delete

    variable opts
    variable widgets
    $Apol_Users::widgets(role) configure -values [Apol_Roles::getRoles]
    if {[ApolTop::is_capable "mls"]} {
        Apol_Widget::setRangeSelectorCompleteState $widgets(range) normal
        $widgets(defaultCB) configure -state normal
    } else {
        Apol_Widget::clearRangeSelector $widgets(range)
        Apol_Widget::setRangeSelectorCompleteState $widgets(range) disabled
        set opts(enable_default) 0
        $widgets(defaultCB) configure -state disabled
    }
}

proc Apol_Users::close {} {
    variable widgets

    _initializeVars
    variable users_list {}
    $widgets(role) configure -values ""
    Apol_Widget::clearSearchResults $widgets(results)
    Apol_Widget::clearRangeSelector $widgets(range)
    Apol_Widget::setRangeSelectorCompleteState $widgets(range) normal
    $widgets(defaultCB) configure -state normal
}

proc Apol_Users::getTextWidget {} {
    variable widgets
    return $widgets(results).tb
}

# Return a list of all user names within the current policy.  If no
# policy is loaded then return an empty list.
proc Apol_Users::getUsers {} {
    variable users_list
    set users_list
}

#### private functions below ####

proc Apol_Users::_initializeVars {} {
    variable opts
    array set opts {
        showSelection all
        useRole 0         role {}
        enable_default 0  default_level {}
    }
}

proc Apol_Users::_toggleRolesCheckbutton {path name1 name2 op} {
    variable opts
    if {$opts($name2)} {
    $path configure -state normal -entrybg white
    } else {
        $path configure -state disabled -entrybg $ApolTop::default_bg_color
    }
}

proc Apol_Users::_toggleDefaultCheckbutton {cb display button name1 name2 op} {
    variable opts
    if {$opts($name2)} {
        $button configure -state normal
        $display configure -state normal
    } else {
        $button configure -state disabled
        $display configure -state disabled
    }
}

proc Apol_Users::_show_level_dialog {} {
    variable opts
    .mainframe.frame.nb.fcomponents.nb.fApol_Users.pw.f1.frame.obox.f.default.button configure -state disabled
    set new_level [Apol_Level_Dialog::getLevel $opts(default_level)]
    if {$new_level != {}} {
        set opts(default_level) $new_level
        $opts(default_level) -acquire
    }
    .mainframe.frame.nb.fcomponents.nb.fApol_Users.pw.f1.frame.obox.f.default.button configure -state normal
}

proc Apol_Users::_updateDefaultDisplay {display name1 name2 op} {
    variable opts
    if {$opts(default_level) == {}} {
        set opts(default_level_display) {}
        $display configure -helptext {}
    } else {
        set level [$opts(default_level) render $::ApolTop::policy]
        if {$level == {}} {
            set opts(default_level_display) "<invalid MLS level>"
        } else {
            set opts(default_level_display) $level
        }
        $display configure -helptext $opts(default_level_display)
    }
}

proc Apol_Users::_popupUserInfo {which user} {
    Apol_Widget::showPopupText $user [_renderUser $user 1]
}

proc Apol_Users::_searchUsers {} {
    variable opts
    variable widgets
    .mainframe.frame.nb.fcomponents.nb.fApol_Users.pw.f1.frame.obox.f.ok configure -state disabled

    Apol_Widget::clearSearchResults $widgets(results)
    if {![ApolTop::is_policy_open]} {
        tk_messageBox -icon error -type ok -title "Error" -message "No current policy file is opened."
        .mainframe.frame.nb.fcomponents.nb.fApol_Users.pw.f1.frame.obox.f.ok configure -state normal
        return
    }
    if {$opts(useRole)} {
        if {$opts(role) == ""} {
            tk_messageBox -icon error -type ok -title "Error" -message "No role selected."
            .mainframe.frame.nb.fcomponents.nb.fApol_Users.pw.f1.frame.obox.f.ok configure -state normal
            return
        }
        set role $opts(role)
    } else {
        set role {}
    }
    if {$opts(enable_default)} {
        if {$opts(default_level) == {}} {
            tk_messageBox -icon error -type ok -title "Error" -message "No default level selected."
            .mainframe.frame.nb.fcomponents.nb.fApol_Users.pw.f1.frame.obox.f.ok configure -state normal
            return
        }
        set default $opts(default_level)
        # the user query will handle destroying the apol_mls_level object
    } else {
        set default NULL
    }
    set range_enabled [Apol_Widget::getRangeSelectorState $widgets(range)]
    foreach {range range_type} [Apol_Widget::getRangeSelectorValue $widgets(range)] {break}
    if {$range_enabled} {
        if {$range == {}} {
            tk_messageBox -icon error -type ok -title "Error" -message "No range selected."
            .mainframe.frame.nb.fcomponents.nb.fApol_Users.pw.f1.frame.obox.f.ok configure -state normal
            return
        }
        # the user query will handle destroying the apol_mls_range object
    } else {
        set range NULL
    }
    if {$opts(showSelection) == "all"} {
        set show_all 1
    } else {
        set show_all 0
    }

    set q [new_apol_user_query_t]
    $q set_role $::ApolTop::policy $role
    $q set_default_level $::ApolTop::policy $default
    $q set_range $::ApolTop::policy $range $range_type
    set v [$q run $::ApolTop::policy]
    $q -acquire
    $q -delete
    set users_data [user_vector_to_list $v]
    $v -acquire
    $v -delete

    set text "USERS:\n"
    if {[llength $users_data] == 0} {
        append text "Search returned no results."
    } else {
        foreach u [lsort -index 0 $users_data] {
            append text "\n[_renderUser $u $show_all]"
        }
    }
    Apol_Widget::appendSearchResultText $widgets(results) $text
    .mainframe.frame.nb.fcomponents.nb.fApol_Users.pw.f1.frame.obox.f.ok configure -state normal
}

proc Apol_Users::_renderUser {user_name show_all} {
    set text "$user_name"
    if {!$show_all} {
        return $text
    }
    set qpol_user_datum [new_qpol_user_t $::ApolTop::qpolicy $user_name]
    if {[ApolTop::is_capable "mls"]} {
        set default [$qpol_user_datum get_dfltlevel $::ApolTop::qpolicy]
        set apol_default [new_apol_mls_level_t $::ApolTop::policy $default]
        append text " level [$apol_default render $::ApolTop::policy]"
        $apol_default -acquire
        $apol_default -delete
        set range [$qpol_user_datum get_range $::ApolTop::qpolicy]
        set apol_range [new_apol_mls_range_t $::ApolTop::policy $range]
        append text " range [$apol_range render $::ApolTop::policy]"
        $apol_range -acquire
        $apol_range -delete
    }
    set i [$qpol_user_datum get_role_iter $::ApolTop::qpolicy]
    set roles {}
    while {![$i end]} {
        set qpol_role_datum [qpol_role_from_void [$i get_item]]
        lappend roles [$qpol_role_datum get_name $::ApolTop::qpolicy]
        $i next
    }
    append text " ([llength $roles] role"
    if {[llength $roles] != 1} {
        append text "s"
    }
    append text ")\n"
    foreach r $roles {
        append text "    $r\n"
    }
    return $text
}