summaryrefslogtreecommitdiffstats
path: root/apol/fscontexts_tab.tcl
blob: 47522c2b20f764de0ad61e72f72bf677dfef7166 (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
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
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
}