summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiroslav Grepl <mgrepl@redhat.com>2014-04-11 09:37:53 +0200
committerMiroslav Grepl <mgrepl@redhat.com>2014-04-11 09:37:53 +0200
commit47be9ff57e72906660bb62a515222f482131e1fb (patch)
tree2cb0ef0ba48d73b1df7cc0915754a17e19464bb6
downloadsetools-master.zip
setools-master.tar.gz
setools-master.tar.xz
Create setools-3.3.7 git repomaster
-rw-r--r--AUTHORS30
-rw-r--r--COPYING5
-rw-r--r--COPYING.GPL339
-rw-r--r--COPYING.LGPL504
-rw-r--r--ChangeLog1155
-rw-r--r--KNOWN-BUGS73
-rw-r--r--Makefile.am116
-rw-r--r--NEWS1018
-rw-r--r--README456
-rw-r--r--TODO29
-rw-r--r--VERSION.in1
-rw-r--r--apol/Makefile.am131
-rw-r--r--apol/analysis_tab.tcl326
-rw-r--r--apol/apol.gifbin0 -> 1305 bytes
-rw-r--r--apol/apol.pngbin0 -> 1408 bytes
-rw-r--r--apol/apol.xcfbin0 -> 9291 bytes
-rw-r--r--apol/apol_help.txt482
-rw-r--r--apol/apol_tcl.cc142
-rw-r--r--apol/apol_tcl.i451
-rw-r--r--apol/classes_perms_tab.tcl484
-rw-r--r--apol/common_widgets.tcl688
-rw-r--r--apol/cond_bools_tab.tcl266
-rw-r--r--apol/cond_rules_tab.tcl281
-rw-r--r--apol/context_dialog.tcl340
-rw-r--r--apol/context_selector.tcl150
-rw-r--r--apol/directflow_module.tcl582
-rw-r--r--apol/domaintrans_help.txt141
-rw-r--r--apol/domaintrans_module.tcl999
-rw-r--r--apol/file_contexts_tab.tcl504
-rw-r--r--apol/file_relabel_help.txt68
-rw-r--r--apol/find.tcl134
-rw-r--r--apol/foo_module.tcl143
-rw-r--r--apol/fscontexts_tab.tcl472
-rw-r--r--apol/goto.tcl78
-rw-r--r--apol/head.tcl29
-rw-r--r--apol/infoflow_help.txt321
-rw-r--r--apol/initial_sids_tab.tcl142
-rw-r--r--apol/level_dialog.tcl82
-rw-r--r--apol/mls_tab.tcl332
-rw-r--r--apol/netcontexts_tab.tcl878
-rw-r--r--apol/open_policy_dialog.tcl388
-rw-r--r--apol/perm_maps/apol_perm_mapping_ver12575
-rw-r--r--apol/perm_maps/apol_perm_mapping_ver15580
-rw-r--r--apol/perm_maps/apol_perm_mapping_ver16560
-rw-r--r--apol/perm_maps/apol_perm_mapping_ver17561
-rw-r--r--apol/perm_maps/apol_perm_mapping_ver18922
-rw-r--r--apol/perm_maps/apol_perm_mapping_ver19952
-rw-r--r--apol/perm_maps/apol_perm_mapping_ver20993
-rw-r--r--apol/perm_maps/apol_perm_mapping_ver21998
-rw-r--r--apol/perm_maps/apol_perm_mapping_ver22998
-rw-r--r--apol/perm_maps/apol_perm_mapping_ver23998
-rw-r--r--apol/perm_maps/apol_perm_mapping_ver241227
-rw-r--r--apol/perms_map.tcl410
-rw-r--r--apol/policyconf.tcl102
-rw-r--r--apol/progress_dialog.tcl74
-rw-r--r--apol/range_dialog.tcl132
-rw-r--r--apol/range_selector.tcl156
-rw-r--r--apol/range_trans.tcl204
-rw-r--r--apol/rbac_tab.tcl490
-rw-r--r--apol/relabel_module.tcl898
-rw-r--r--apol/roles_tab.tcl196
-rw-r--r--apol/terules_tab.tcl1034
-rw-r--r--apol/top.tcl1228
-rw-r--r--apol/transflow_module.tcl1156
-rw-r--r--apol/types_relation_help.txt53
-rw-r--r--apol/types_relation_module.tcl770
-rw-r--r--apol/types_tab.tcl411
-rw-r--r--apol/users_tab.tcl313
-rw-r--r--apol/util.tcl312
-rw-r--r--configure.ac896
-rw-r--r--debian/Makefile.am24
-rw-r--r--debian/changelog362
-rw-r--r--debian/compat1
-rw-r--r--debian/control183
-rw-r--r--debian/copyright48
-rw-r--r--debian/docs5
-rw-r--r--debian/libsetools-dev.install7
-rw-r--r--debian/libsetools-java.install2
-rw-r--r--debian/libsetools-jni.install1
-rw-r--r--debian/libsetools-jni.postinst41
-rw-r--r--debian/libsetools-jni.postrm39
-rw-r--r--debian/libsetools-python.install2
-rw-r--r--debian/libsetools-python.postinst41
-rw-r--r--debian/libsetools-tcl.install5
-rw-r--r--debian/libsetools.install5
-rw-r--r--debian/libsetools.postinst41
-rw-r--r--debian/libsetools.postrm39
-rwxr-xr-xdebian/rules25
-rw-r--r--debian/setools-console.install24
-rw-r--r--debian/setools.install19
-rw-r--r--debian/setools.menu6
-rw-r--r--debian/setools.postinst41
-rw-r--r--debian/setools.postrm39
-rw-r--r--debian/watch11
-rw-r--r--libapol/Makefile.am8
-rw-r--r--libapol/include/Makefile.am1
-rw-r--r--libapol/include/apol/Makefile.am35
-rw-r--r--libapol/include/apol/avrule-query.h373
-rw-r--r--libapol/include/apol/bool-query.h105
-rw-r--r--libapol/include/apol/bst.h178
-rw-r--r--libapol/include/apol/class-perm-query.h255
-rw-r--r--libapol/include/apol/condrule-query.h119
-rw-r--r--libapol/include/apol/constraint-query.h188
-rw-r--r--libapol/include/apol/context-query.h261
-rw-r--r--libapol/include/apol/domain-trans-analysis.h427
-rw-r--r--libapol/include/apol/fscon-query.h249
-rw-r--r--libapol/include/apol/infoflow-analysis.h387
-rw-r--r--libapol/include/apol/isid-query.h111
-rw-r--r--libapol/include/apol/mls-query.h228
-rw-r--r--libapol/include/apol/mls_level.h261
-rw-r--r--libapol/include/apol/mls_range.h270
-rw-r--r--libapol/include/apol/netcon-query.h364
-rw-r--r--libapol/include/apol/perm-map.h137
-rw-r--r--libapol/include/apol/permissive-query.h104
-rw-r--r--libapol/include/apol/polcap-query.h103
-rw-r--r--libapol/include/apol/policy-path.h194
-rw-r--r--libapol/include/apol/policy-query.h86
-rw-r--r--libapol/include/apol/policy.h166
-rw-r--r--libapol/include/apol/range_trans-query.h198
-rw-r--r--libapol/include/apol/rbacrule-query.h279
-rw-r--r--libapol/include/apol/relabel-analysis.h258
-rw-r--r--libapol/include/apol/render.h82
-rw-r--r--libapol/include/apol/role-query.h127
-rw-r--r--libapol/include/apol/terule-query.h321
-rw-r--r--libapol/include/apol/type-query.h172
-rw-r--r--libapol/include/apol/types-relation-analysis.h380
-rw-r--r--libapol/include/apol/user-query.h150
-rw-r--r--libapol/include/apol/util.h336
-rw-r--r--libapol/include/apol/vector.h335
-rw-r--r--libapol/src/Makefile.am75
-rw-r--r--libapol/src/avrule-query.c1209
-rw-r--r--libapol/src/bool-query.c111
-rw-r--r--libapol/src/bst.c352
-rw-r--r--libapol/src/class-perm-query.c327
-rw-r--r--libapol/src/condrule-query.c182
-rw-r--r--libapol/src/constraint-query.c217
-rw-r--r--libapol/src/context-query.c477
-rw-r--r--libapol/src/domain-trans-analysis-internal.h36
-rw-r--r--libapol/src/domain-trans-analysis.c2076
-rw-r--r--libapol/src/fscon-query.c437
-rw-r--r--libapol/src/infoflow-analysis-internal.h49
-rw-r--r--libapol/src/infoflow-analysis.c2245
-rw-r--r--libapol/src/isid-query.c123
-rw-r--r--libapol/src/libapol.map86
-rw-r--r--libapol/src/mls-query.c248
-rw-r--r--libapol/src/mls_level.c771
-rw-r--r--libapol/src/mls_range.c641
-rw-r--r--libapol/src/netcon-query.c592
-rw-r--r--libapol/src/perm-map.c697
-rw-r--r--libapol/src/permissive-query.c107
-rw-r--r--libapol/src/polcap-query.c107
-rw-r--r--libapol/src/policy-path.c409
-rw-r--r--libapol/src/policy-query-internal.h511
-rw-r--r--libapol/src/policy-query.c903
-rw-r--r--libapol/src/policy.c217
-rw-r--r--libapol/src/queue.c125
-rw-r--r--libapol/src/queue.h86
-rw-r--r--libapol/src/range_trans-query.c318
-rw-r--r--libapol/src/rbacrule-query.c417
-rw-r--r--libapol/src/relabel-analysis.c813
-rw-r--r--libapol/src/render.c158
-rw-r--r--libapol/src/role-query.c167
-rw-r--r--libapol/src/terule-query.c1049
-rw-r--r--libapol/src/type-query.c202
-rw-r--r--libapol/src/types-relation-analysis.c1143
-rw-r--r--libapol/src/user-query.c198
-rw-r--r--libapol/src/util.c659
-rw-r--r--libapol/src/vector-internal.h36
-rw-r--r--libapol/src/vector.c457
-rw-r--r--libapol/swig/Makefile.am15
-rw-r--r--libapol/swig/apol.i3220
-rw-r--r--libapol/swig/java/MANIFEST.MF.in12
-rw-r--r--libapol/swig/java/Makefile.am118
-rw-r--r--libapol/swig/python/Makefile.am36
-rw-r--r--libapol/swig/tcl/Makefile.am36
-rw-r--r--libapol/tests/Makefile.am23
-rw-r--r--libapol/tests/avrule-tests.c161
-rw-r--r--libapol/tests/avrule-tests.h35
-rw-r--r--libapol/tests/constrain-tests.c523
-rw-r--r--libapol/tests/constrain-tests.h33
-rw-r--r--libapol/tests/dta-tests.c529
-rw-r--r--libapol/tests/dta-tests.h35
-rw-r--r--libapol/tests/infoflow-tests.c127
-rw-r--r--libapol/tests/infoflow-tests.h36
-rw-r--r--libapol/tests/libapol-tests.c64
-rw-r--r--libapol/tests/policy-21-tests.c181
-rw-r--r--libapol/tests/policy-21-tests.h35
-rw-r--r--libapol/tests/role-tests.c154
-rw-r--r--libapol/tests/role-tests.h35
-rw-r--r--libapol/tests/terule-tests.c130
-rw-r--r--libapol/tests/terule-tests.h35
-rw-r--r--libapol/tests/user-tests.c159
-rw-r--r--libapol/tests/user-tests.h35
-rw-r--r--libpoldiff/Makefile.am8
-rw-r--r--libpoldiff/include/Makefile.am1
-rw-r--r--libpoldiff/include/poldiff/Makefile.am20
-rw-r--r--libpoldiff/include/poldiff/attrib_diff.h130
-rw-r--r--libpoldiff/include/poldiff/avrule_diff.h361
-rw-r--r--libpoldiff/include/poldiff/bool_diff.h146
-rw-r--r--libpoldiff/include/poldiff/cat_diff.h103
-rw-r--r--libpoldiff/include/poldiff/class_diff.h222
-rw-r--r--libpoldiff/include/poldiff/component_record.h159
-rw-r--r--libpoldiff/include/poldiff/level_diff.h159
-rw-r--r--libpoldiff/include/poldiff/poldiff.h218
-rw-r--r--libpoldiff/include/poldiff/range_diff.h129
-rw-r--r--libpoldiff/include/poldiff/range_trans_diff.h140
-rw-r--r--libpoldiff/include/poldiff/rbac_diff.h251
-rw-r--r--libpoldiff/include/poldiff/role_diff.h127
-rw-r--r--libpoldiff/include/poldiff/terule_diff.h262
-rw-r--r--libpoldiff/include/poldiff/type_diff.h132
-rw-r--r--libpoldiff/include/poldiff/type_map.h153
-rw-r--r--libpoldiff/include/poldiff/user_diff.h191
-rw-r--r--libpoldiff/include/poldiff/util.h45
-rw-r--r--libpoldiff/src/Makefile.am57
-rw-r--r--libpoldiff/src/attrib_diff.c544
-rw-r--r--libpoldiff/src/attrib_internal.h121
-rw-r--r--libpoldiff/src/avrule_diff.c1636
-rw-r--r--libpoldiff/src/avrule_internal.h296
-rw-r--r--libpoldiff/src/bool_diff.c333
-rw-r--r--libpoldiff/src/bool_internal.h122
-rw-r--r--libpoldiff/src/cat_diff.c289
-rw-r--r--libpoldiff/src/cat_internal.h120
-rw-r--r--libpoldiff/src/class_diff.c990
-rw-r--r--libpoldiff/src/class_internal.h212
-rw-r--r--libpoldiff/src/level_diff.c769
-rw-r--r--libpoldiff/src/level_internal.h208
-rw-r--r--libpoldiff/src/libpoldiff.map50
-rw-r--r--libpoldiff/src/poldiff.c814
-rw-r--r--libpoldiff/src/poldiff_internal.h239
-rw-r--r--libpoldiff/src/range_diff.c420
-rw-r--r--libpoldiff/src/range_internal.h80
-rw-r--r--libpoldiff/src/range_trans_diff.c520
-rw-r--r--libpoldiff/src/range_trans_internal.h124
-rw-r--r--libpoldiff/src/rbac_diff.c1052
-rw-r--r--libpoldiff/src/rbac_internal.h209
-rw-r--r--libpoldiff/src/role_diff.c543
-rw-r--r--libpoldiff/src/role_internal.h121
-rw-r--r--libpoldiff/src/terule_diff.c1329
-rw-r--r--libpoldiff/src/terule_internal.h244
-rw-r--r--libpoldiff/src/type_diff.c662
-rw-r--r--libpoldiff/src/type_internal.h125
-rw-r--r--libpoldiff/src/type_map.c985
-rw-r--r--libpoldiff/src/type_map_internal.h171
-rw-r--r--libpoldiff/src/user_diff.c789
-rw-r--r--libpoldiff/src/user_internal.h121
-rw-r--r--libpoldiff/src/util.c32
-rw-r--r--libpoldiff/src/writing-diffs-HOWTO351
-rw-r--r--libpoldiff/swig/Makefile.am15
-rw-r--r--libpoldiff/swig/java/MANIFEST.MF.in14
-rw-r--r--libpoldiff/swig/java/Makefile.am93
-rw-r--r--libpoldiff/swig/poldiff.i1335
-rw-r--r--libpoldiff/swig/python/Makefile.am39
-rw-r--r--libpoldiff/swig/tcl/Makefile.am37
-rw-r--r--libpoldiff/tests/Makefile.am19
-rw-r--r--libpoldiff/tests/components-tests.c544
-rw-r--r--libpoldiff/tests/components-tests.h49
-rw-r--r--libpoldiff/tests/libpoldiff-tests.c364
-rw-r--r--libpoldiff/tests/libpoldiff-tests.h85
-rw-r--r--libpoldiff/tests/mls-tests.c635
-rw-r--r--libpoldiff/tests/mls-tests.h39
-rw-r--r--libpoldiff/tests/nomls-tests.c139
-rw-r--r--libpoldiff/tests/nomls-tests.h33
-rw-r--r--libpoldiff/tests/policy-defs.h44
-rw-r--r--libpoldiff/tests/rules-tests.c914
-rw-r--r--libpoldiff/tests/rules-tests.h40
-rw-r--r--libqpol/Makefile.am8
-rw-r--r--libqpol/include/Makefile.am1
-rw-r--r--libqpol/include/qpol/Makefile.am30
-rw-r--r--libqpol/include/qpol/avrule_query.h167
-rw-r--r--libqpol/include/qpol/bool_query.h127
-rw-r--r--libqpol/include/qpol/class_perm_query.h209
-rw-r--r--libqpol/include/qpol/cond_query.h198
-rw-r--r--libqpol/include/qpol/constraint_query.h262
-rw-r--r--libqpol/include/qpol/context_query.h93
-rw-r--r--libqpol/include/qpol/fs_use_query.h115
-rw-r--r--libqpol/include/qpol/genfscon_query.h128
-rw-r--r--libqpol/include/qpol/isid_query.h91
-rw-r--r--libqpol/include/qpol/iterator.h95
-rw-r--r--libqpol/include/qpol/mls_query.h260
-rw-r--r--libqpol/include/qpol/mlsrule_query.h104
-rw-r--r--libqpol/include/qpol/module.h125
-rw-r--r--libqpol/include/qpol/netifcon_query.h104
-rw-r--r--libqpol/include/qpol/nodecon_query.h132
-rw-r--r--libqpol/include/qpol/permissive_query.h68
-rw-r--r--libqpol/include/qpol/polcap_query.h68
-rw-r--r--libqpol/include/qpol/policy.h261
-rw-r--r--libqpol/include/qpol/policy_extend.h86
-rw-r--r--libqpol/include/qpol/portcon_query.h118
-rw-r--r--libqpol/include/qpol/rbacrule_query.h130
-rw-r--r--libqpol/include/qpol/role_query.h119
-rw-r--r--libqpol/include/qpol/syn_rule_query.h314
-rw-r--r--libqpol/include/qpol/terule_query.h159
-rw-r--r--libqpol/include/qpol/type_query.h175
-rw-r--r--libqpol/include/qpol/user_query.h130
-rw-r--r--libqpol/include/qpol/util.h61
-rw-r--r--libqpol/src/Makefile.am89
-rw-r--r--libqpol/src/avrule_query.c288
-rw-r--r--libqpol/src/bool_query.c193
-rw-r--r--libqpol/src/class_perm_query.c653
-rw-r--r--libqpol/src/cond_query.c620
-rw-r--r--libqpol/src/constraint_query.c983
-rw-r--r--libqpol/src/context_query.c123
-rw-r--r--libqpol/src/expand.c190
-rw-r--r--libqpol/src/expand.h51
-rw-r--r--libqpol/src/fs_use_query.c167
-rw-r--r--libqpol/src/genfscon_query.c294
-rw-r--r--libqpol/src/isid_query.c139
-rw-r--r--libqpol/src/iterator.c797
-rw-r--r--libqpol/src/iterator_internal.h123
-rw-r--r--libqpol/src/libqpol.map73
-rw-r--r--libqpol/src/mls_query.c639
-rw-r--r--libqpol/src/mlsrule_query.c230
-rw-r--r--libqpol/src/module.c236
-rw-r--r--libqpol/src/module_compiler.c1440
-rw-r--r--libqpol/src/module_compiler.h115
-rw-r--r--libqpol/src/netifcon_query.c159
-rw-r--r--libqpol/src/nodecon_query.c329
-rw-r--r--libqpol/src/permissive_query.c95
-rw-r--r--libqpol/src/polcap_query.c92
-rw-r--r--libqpol/src/policy.c1563
-rw-r--r--libqpol/src/policy_define.c4319
-rw-r--r--libqpol/src/policy_define.h75
-rw-r--r--libqpol/src/policy_extend.c1397
-rw-r--r--libqpol/src/policy_parse.y834
-rw-r--r--libqpol/src/policy_scan.l320
-rw-r--r--libqpol/src/portcon_query.c183
-rw-r--r--libqpol/src/qpol_internal.h122
-rw-r--r--libqpol/src/queue.c183
-rw-r--r--libqpol/src/queue.h67
-rw-r--r--libqpol/src/rbacrule_query.c358
-rw-r--r--libqpol/src/role_query.c238
-rw-r--r--libqpol/src/syn_rule_internal.h47
-rw-r--r--libqpol/src/syn_rule_query.c782
-rw-r--r--libqpol/src/terule_query.c264
-rw-r--r--libqpol/src/type_query.c468
-rw-r--r--libqpol/src/user_query.c224
-rw-r--r--libqpol/src/util.c231
-rw-r--r--libqpol/swig/Makefile.am15
-rw-r--r--libqpol/swig/java/MANIFEST.MF.in9
-rw-r--r--libqpol/swig/java/Makefile.am97
-rw-r--r--libqpol/swig/python/Makefile.am34
-rw-r--r--libqpol/swig/python/__init__.py1
-rw-r--r--libqpol/swig/qpol.i2879
-rw-r--r--libqpol/swig/tcl/Makefile.am35
-rw-r--r--libqpol/tests/Makefile.am17
-rw-r--r--libqpol/tests/capabilities-tests.c542
-rw-r--r--libqpol/tests/capabilities-tests.h35
-rw-r--r--libqpol/tests/iterators-tests.c87
-rw-r--r--libqpol/tests/iterators-tests.h35
-rw-r--r--libqpol/tests/libqpol-tests.c57
-rw-r--r--libqpol/tests/policy-features-tests.c145
-rw-r--r--libqpol/tests/policy-features-tests.h35
-rw-r--r--libseaudit/Makefile.am8
-rw-r--r--libseaudit/include/Makefile.am1
-rw-r--r--libseaudit/include/seaudit/Makefile.am14
-rw-r--r--libseaudit/include/seaudit/avc_message.h374
-rw-r--r--libseaudit/include/seaudit/bool_message.h43
-rw-r--r--libseaudit/include/seaudit/filter.h1025
-rw-r--r--libseaudit/include/seaudit/load_message.h41
-rw-r--r--libseaudit/include/seaudit/log.h162
-rw-r--r--libseaudit/include/seaudit/message.h133
-rw-r--r--libseaudit/include/seaudit/model.h362
-rw-r--r--libseaudit/include/seaudit/parse.h72
-rw-r--r--libseaudit/include/seaudit/report.h140
-rw-r--r--libseaudit/include/seaudit/sort.h491
-rw-r--r--libseaudit/include/seaudit/util.h44
-rw-r--r--libseaudit/src/Makefile.am52
-rw-r--r--libseaudit/src/avc_message.c630
-rw-r--r--libseaudit/src/bool_message.c153
-rw-r--r--libseaudit/src/filter-internal.c1526
-rw-r--r--libseaudit/src/filter-internal.h109
-rw-r--r--libseaudit/src/filter.c1124
-rw-r--r--libseaudit/src/libseaudit.map88
-rw-r--r--libseaudit/src/load_message.c91
-rw-r--r--libseaudit/src/log.c253
-rw-r--r--libseaudit/src/message.c204
-rw-r--r--libseaudit/src/model.c808
-rw-r--r--libseaudit/src/parse.c1513
-rw-r--r--libseaudit/src/report.c1060
-rw-r--r--libseaudit/src/seaudit_internal.h664
-rw-r--r--libseaudit/src/sort.c744
-rw-r--r--libseaudit/src/util.c32
-rw-r--r--libseaudit/swig/Makefile.am15
-rw-r--r--libseaudit/swig/java/MANIFEST.MF.in14
-rw-r--r--libseaudit/swig/java/Makefile.am90
-rw-r--r--libseaudit/swig/python/Makefile.am39
-rw-r--r--libseaudit/swig/seaudit.i1373
-rw-r--r--libseaudit/swig/tcl/Makefile.am37
-rw-r--r--libseaudit/tests/Makefile.am16
-rw-r--r--libseaudit/tests/filters.c114
-rw-r--r--libseaudit/tests/filters.h35
-rw-r--r--libseaudit/tests/libseaudit-tests.c54
-rw-r--r--libseaudit/tests/parse_file.c113
-rw-r--r--libseaudit/tests/parse_file.h35
-rw-r--r--libsefs/Makefile.am8
-rw-r--r--libsefs/include/Makefile.am1
-rw-r--r--libsefs/include/sefs/Makefile.am10
-rw-r--r--libsefs/include/sefs/db.hh213
-rw-r--r--libsefs/include/sefs/entry.hh222
-rw-r--r--libsefs/include/sefs/fcfile.hh261
-rw-r--r--libsefs/include/sefs/fclist.hh323
-rw-r--r--libsefs/include/sefs/filesystem.hh181
-rw-r--r--libsefs/include/sefs/query.hh329
-rw-r--r--libsefs/include/sefs/util.h56
-rw-r--r--libsefs/src/Makefile.am52
-rw-r--r--libsefs/src/db.cc1304
-rw-r--r--libsefs/src/entry.cc213
-rw-r--r--libsefs/src/fcfile.cc691
-rw-r--r--libsefs/src/fclist.cc766
-rw-r--r--libsefs/src/filesystem.cc733
-rw-r--r--libsefs/src/libsefs.map29
-rw-r--r--libsefs/src/new_ftw.c749
-rw-r--r--libsefs/src/new_ftw.h183
-rw-r--r--libsefs/src/query.cc431
-rw-r--r--libsefs/src/sefs_internal.hh78
-rw-r--r--libsefs/src/util.c46
-rw-r--r--libsefs/swig/Makefile.am15
-rw-r--r--libsefs/swig/java/MANIFEST.MF.in14
-rw-r--r--libsefs/swig/java/Makefile.am85
-rw-r--r--libsefs/swig/python/Makefile.am39
-rw-r--r--libsefs/swig/sefs.i162
-rw-r--r--libsefs/swig/tcl/Makefile.am37
-rw-r--r--libsefs/tests/Makefile.am17
-rw-r--r--libsefs/tests/attic/fuse_non_mls.c195
-rwxr-xr-xlibsefs/tests/attic/launch-libsefs-tests.sh12
-rw-r--r--libsefs/tests/fcfile-tests.cc333
-rw-r--r--libsefs/tests/fcfile-tests.hh35
-rw-r--r--libsefs/tests/file_contexts.broken3
-rw-r--r--libsefs/tests/file_contexts.confed24
-rw-r--r--libsefs/tests/file_contexts.union16
-rw-r--r--libsefs/tests/libsefs-tests.cc52
-rw-r--r--m4/ac_check_classpath.m463
-rw-r--r--m4/ac_java_options.m446
-rw-r--r--m4/ac_pkg_swig.m4125
-rw-r--r--m4/ac_prog_jar.m452
-rw-r--r--m4/ac_prog_java.m4122
-rw-r--r--m4/ac_prog_java_works.m4137
-rw-r--r--m4/ac_prog_javac.m484
-rw-r--r--m4/ac_prog_javac_works.m475
-rw-r--r--m4/ac_python_devel.m4269
-rw-r--r--m4/c.m4265
-rw-r--r--m4/swig_python.m467
-rw-r--r--m4/tcl.m43960
-rw-r--r--man/Makefile.am19
-rw-r--r--man/apol.143
-rw-r--r--man/findcon.1119
-rw-r--r--man/indexcon.136
-rw-r--r--man/replcon.1102
-rw-r--r--man/seaudit-report.8.in38
-rw-r--r--man/seaudit.849
-rw-r--r--man/sechecker.1136
-rw-r--r--man/sediff.1118
-rw-r--r--man/sediffx.175
-rw-r--r--man/seinfo.1109
-rw-r--r--man/sesearch.1113
-rw-r--r--packages/BWidget-1.8.0.tar.bz2bin0 -> 164532 bytes
-rw-r--r--packages/Doxyfile1237
-rw-r--r--packages/Makefile.am38
-rw-r--r--packages/combobox.tcl764
-rw-r--r--packages/libapol.pc.in12
-rw-r--r--packages/libpoldiff.pc.in12
-rw-r--r--packages/libqpol.pc.in12
-rw-r--r--packages/libseaudit.pc.in12
-rw-r--r--packages/libsefs.pc.in12
-rw-r--r--packages/mainframe.tcl133
-rw-r--r--packages/notebook.tcl9
-rw-r--r--packages/rpm/Makefile.am11
-rw-r--r--packages/rpm/apol.desktop.in12
-rw-r--r--packages/rpm/fc9-compile.patch13
-rw-r--r--packages/rpm/seaudit.console.in3
-rw-r--r--packages/rpm/seaudit.desktop.in12
-rw-r--r--packages/rpm/seaudit.pam4
-rw-r--r--packages/rpm/sediffx.desktop.in12
-rw-r--r--packages/rpm/setools.spec661
-rw-r--r--seaudit/Makefile.am90
-rw-r--r--seaudit/dot_seaudit.in12
-rw-r--r--seaudit/filter_view.c1127
-rw-r--r--seaudit/filter_view.h42
-rw-r--r--seaudit/message_view.c1341
-rw-r--r--seaudit/message_view.h178
-rw-r--r--seaudit/modify_view.c327
-rw-r--r--seaudit/modify_view.h41
-rw-r--r--seaudit/open_policy_window.c469
-rw-r--r--seaudit/open_policy_window.h46
-rw-r--r--seaudit/policy_components_view.c373
-rw-r--r--seaudit/policy_components_view.h56
-rw-r--r--seaudit/policy_view.c573
-rw-r--r--seaudit/policy_view.h77
-rw-r--r--seaudit/preferences.c585
-rw-r--r--seaudit/preferences.h274
-rw-r--r--seaudit/preferences_view.c310
-rw-r--r--seaudit/preferences_view.h44
-rw-r--r--seaudit/progress.c200
-rw-r--r--seaudit/progress.h139
-rw-r--r--seaudit/report_window.c261
-rw-r--r--seaudit/report_window.h41
-rw-r--r--seaudit/seaudit-report-group.conf3
-rw-r--r--seaudit/seaudit-report-service.conf5
-rw-r--r--seaudit/seaudit-report-service.in24
-rw-r--r--seaudit/seaudit-report.c246
-rw-r--r--seaudit/seaudit-report.conf62
-rw-r--r--seaudit/seaudit-report.css178
-rw-r--r--seaudit/seaudit-small.pngbin0 -> 336 bytes
-rw-r--r--seaudit/seaudit.c418
-rw-r--r--seaudit/seaudit.glade7713
-rw-r--r--seaudit/seaudit.gladep7
-rw-r--r--seaudit/seaudit.h231
-rw-r--r--seaudit/seaudit.pngbin0 -> 992 bytes
-rw-r--r--seaudit/seaudit.xcfbin0 -> 7462 bytes
-rw-r--r--seaudit/seaudit_help.txt293
-rw-r--r--seaudit/toplevel.c1179
-rw-r--r--seaudit/toplevel.h263
-rw-r--r--seaudit/utilgui.c134
-rw-r--r--seaudit/utilgui.h106
-rw-r--r--sechecker/Makefile.am67
-rw-r--r--sechecker/modules/attribs_wo_rules.c520
-rw-r--r--sechecker/modules/attribs_wo_rules.h63
-rw-r--r--sechecker/modules/attribs_wo_types.c399
-rw-r--r--sechecker/modules/attribs_wo_types.h48
-rw-r--r--sechecker/modules/domain_and_file.c398
-rw-r--r--sechecker/modules/domain_and_file.h46
-rw-r--r--sechecker/modules/domains_wo_roles.c386
-rw-r--r--sechecker/modules/domains_wo_roles.h47
-rw-r--r--sechecker/modules/find_assoc_types.c407
-rw-r--r--sechecker/modules/find_assoc_types.h51
-rw-r--r--sechecker/modules/find_domains.c633
-rw-r--r--sechecker/modules/find_domains.h60
-rw-r--r--sechecker/modules/find_file_types.c636
-rw-r--r--sechecker/modules/find_file_types.h60
-rw-r--r--sechecker/modules/find_net_domains.c501
-rw-r--r--sechecker/modules/find_net_domains.h59
-rw-r--r--sechecker/modules/find_netif_types.c489
-rw-r--r--sechecker/modules/find_netif_types.h53
-rw-r--r--sechecker/modules/find_node_types.c479
-rw-r--r--sechecker/modules/find_node_types.h53
-rw-r--r--sechecker/modules/find_port_types.c513
-rw-r--r--sechecker/modules/find_port_types.h50
-rw-r--r--sechecker/modules/imp_range_trans.c513
-rw-r--r--sechecker/modules/imp_range_trans.h52
-rw-r--r--sechecker/modules/inc_dom_trans.c913
-rw-r--r--sechecker/modules/inc_dom_trans.h56
-rw-r--r--sechecker/modules/inc_mount.c520
-rw-r--r--sechecker/modules/inc_mount.h54
-rw-r--r--sechecker/modules/inc_net_access.c1852
-rw-r--r--sechecker/modules/inc_net_access.h51
-rw-r--r--sechecker/modules/roles_wo_allow.c387
-rw-r--r--sechecker/modules/roles_wo_allow.h49
-rw-r--r--sechecker/modules/roles_wo_types.c330
-rw-r--r--sechecker/modules/roles_wo_types.h47
-rw-r--r--sechecker/modules/roles_wo_users.c392
-rw-r--r--sechecker/modules/roles_wo_users.h53
-rw-r--r--sechecker/modules/spurious_audit.c778
-rw-r--r--sechecker/modules/spurious_audit.h53
-rw-r--r--sechecker/modules/template/profiles.readme142
-rw-r--r--sechecker/modules/template/template.howto13
-rw-r--r--sechecker/modules/template/xx.c393
-rw-r--r--sechecker/modules/template/xx.h72
-rw-r--r--sechecker/modules/types_wo_allow.c442
-rw-r--r--sechecker/modules/types_wo_allow.h49
-rw-r--r--sechecker/modules/unreachable_doms.c1053
-rw-r--r--sechecker/modules/unreachable_doms.h73
-rw-r--r--sechecker/modules/users_wo_roles.c321
-rw-r--r--sechecker/modules/users_wo_roles.h47
-rw-r--r--sechecker/profiles/all-checks-no-mls.sechecker98
-rw-r--r--sechecker/profiles/all-checks.sechecker102
-rw-r--r--sechecker/profiles/analysis-checks.sechecker78
-rw-r--r--sechecker/profiles/devel-checks.sechecker74
-rw-r--r--sechecker/profiles/sechecker.dtd19
-rw-r--r--sechecker/register_list.c102
-rw-r--r--sechecker/register_list.h64
-rw-r--r--sechecker/sechecker.c1230
-rw-r--r--sechecker/sechecker.h695
-rw-r--r--sechecker/sechecker_cli.c361
-rw-r--r--sechecker/sechecker_help.txt86
-rw-r--r--sechecker/sechk_parse.c285
-rw-r--r--sechecker/sechk_parse.h44
-rw-r--r--secmds/Makefile.am40
-rw-r--r--secmds/findcon.cc245
-rw-r--r--secmds/indexcon.cc121
-rw-r--r--secmds/replcon.cc358
-rw-r--r--secmds/seinfo.c2337
-rw-r--r--secmds/sesearch.c1173
-rw-r--r--sediff/Makefile.am54
-rw-r--r--sediff/find_dialog.c184
-rw-r--r--sediff/find_dialog.h63
-rw-r--r--sediff/open_policies_dialog.c527
-rw-r--r--sediff/open_policies_dialog.h45
-rw-r--r--sediff/policy_view.c391
-rw-r--r--sediff/policy_view.h84
-rw-r--r--sediff/progress.c202
-rw-r--r--sediff/progress.h139
-rw-r--r--sediff/remap_types_dialog.c564
-rw-r--r--sediff/remap_types_dialog.h56
-rw-r--r--sediff/result_item.c1361
-rw-r--r--sediff/result_item.h251
-rw-r--r--sediff/result_item_render.c421
-rw-r--r--sediff/result_item_render.h79
-rw-r--r--sediff/results.c708
-rw-r--r--sediff/results.h121
-rw-r--r--sediff/sediff.c653
-rw-r--r--sediff/sediff_help.txt259
-rw-r--r--sediff/sediffx-small.pngbin0 -> 281 bytes
-rw-r--r--sediff/sediffx-small.xcfbin0 -> 1639 bytes
-rw-r--r--sediff/sediffx.c317
-rw-r--r--sediff/sediffx.glade3619
-rw-r--r--sediff/sediffx.h108
-rw-r--r--sediff/sediffx.pngbin0 -> 607 bytes
-rw-r--r--sediff/sediffx.xcfbin0 -> 5882 bytes
-rw-r--r--sediff/select_diff_dialog.c134
-rw-r--r--sediff/select_diff_dialog.h42
-rw-r--r--sediff/toplevel.c728
-rw-r--r--sediff/toplevel.h202
-rw-r--r--sediff/utilgui.c168
-rw-r--r--sediff/utilgui.h125
614 files changed, 196158 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..9c5cb5e
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,30 @@
+SETools - Policy analysis tools for SELinux (C) 2001-2010
+Tresys Technology
+setools@tresys.com, http://oss.tresys.com/projects/setools
+
+Contributors:
+
+Alex Alberg
+James Athey
+Jeff Bankert
+Kevin Carr
+Alessandro Ferrucci
+Mark Goldman
+Ryan Jordan
+Karl MacMillan
+Frank Mayer
+Jeremy A. Mowery
+John Oliver
+Anand Patel
+Don Patterson
+Chris PeBenito
+Paul Rosenfeld
+Spencer Shimko
+Jeremy Solt
+David Sugar
+Jason Tang
+Karen Vance
+Brandon Whalen
+Meggan Whalen
+Randy Wicks
+David Windsor
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..25b8d0c
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,5 @@
+The SETools package contains files under two licences -
+the GNU General Public License and the GNU Lesser General Public License.
+See COPYING.GPL and COPYING.LGPL respectively for the full text of
+these licences. All files distributed with this package indicate the
+appropriate license to use with that file.
diff --git a/COPYING.GPL b/COPYING.GPL
new file mode 100644
index 0000000..d511905
--- /dev/null
+++ b/COPYING.GPL
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/COPYING.LGPL b/COPYING.LGPL
new file mode 100644
index 0000000..5ab7695
--- /dev/null
+++ b/COPYING.LGPL
@@ -0,0 +1,504 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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 Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..e492df4
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,1155 @@
+2010-05-07 Spencer Shimko <sshimko@tresys.com>
+
+ * SETools 3.3.7.
+
+2010-04-30 Spencer Shimko <sshimko@tresys.com>
+
+ * Update the spec file for release.
+ * Update versions for release.
+
+2010-04-28 John Oliver <joliver@tresys.com>
+
+ * Restore close button in transitive info flow.
+ * Wrapped new policy db components so we can build against
+ new and old SELinux userspace.
+
+2010-04-28 Spencer Shimko <sshimko@tresys.com>
+
+ * Switch to a non-modal advanced filtering window.
+
+2010-04-23 Spencer Shimko <sshimko@tresys.com>
+
+ * Rebase module loading code on upstream userspace.
+
+ * Automatically detect base module instead of asking
+ user to identify the base.
+
+ * Support for bzipped policy packages (.pp) found in
+ Fedora 12 and later.
+
+2010-04-20 Chris PeBenito <cpebenito@tresys.com>
+
+ * Fix seinfo to correctly handle cases where there are
+ no nodecon statements in the policy.
+
+2010-04-20 Spencer Shimko <sshimko@tresys.com>
+
+ * Fixes error conditions that prevent apol from exiting. If
+ window/tab was already destroyed on exit
+ then apol threw an error and refused to exit.
+
+2010-04-15 Spencer Shimko <sshimko@tresys.com>
+
+ * Add support for displaying constraints to seinfo.
+ * Add constraint CUnit tests.
+
+2010-03-12 John Oliver <joliver@tresys.com>
+
+ * Ensure architecture independent parts of python SWIG wrapper
+ get installed into the same directory as the architecture
+ dependent parts.
+
+2010-03-12 Chris PeBenito <cpebenito@tresys.com>
+
+ * Fix seaudit/libseaudit headers.
+
+2010-03-02 John Oliver <joliver@tresys.com>
+
+ * Fix error message when Tk can not be loaded by apol. Make it
+ clear that it is Tk, not an SETools library that connot be loaded.
+
+2010-03-01 John Oliver <joliver@tresys.com>
+
+ * Fix error in Apol which would disable new and updated search
+ buttons in rule search.
+
+2009-12-09 John Oliver <joliver@tresys.com>
+
+ * Fix seaudit-report to correctly handle -c and --config
+ options.
+
+2009-07-22 Chris PeBenito <cpebenito@tresys.com>
+
+ * SETools 3.3.6.
+
+2009-07-16 Chris PeBenito <cpebenito@tresys.com>
+
+ * Change default log for seaudit to /var/log/audit/audit.log.
+
+2009-07-16 Chris PeBenito <cpebenito@tresys.com>
+
+ * Change context parsing in libseaudit to use libselinux functions.
+
+2009-06-04 Jeremy Solt <jsolt@tresys.com>
+
+ * Add support for display of level and clearance of contexts to seaudit.
+ * Add support for filterting by level and clearance to seaudit.
+
+2009-05-26 Jeremy Solt <jsolt@tresys.com>
+
+ * Modified seaudit to show the raw audit message when doubleclicking
+ an entry.
+
+2009-05-19 Steve Lawrence <slawrence@tresys.com>
+
+ * Add libqpol and libapol support for policy capabilites and
+ permissive domains.
+ * Add policy capabilities and permissive domains querying to seinfo.
+
+2009-05-15 Jeremy Solt <jsolt@tresys.com>
+
+ * Add support for using attribute names available in version 24
+ binary policies.
+
+2008-09-11 J. Tang <jtang@tresys.com>
+
+ * Fixed error in qpol_policy_rebuild_opt() where a policy's
+ neverallow rules are expanded when the rebuild option is
+ QPOL_POLICY_OPTION_NO_RULES.
+
+2008-08-15 J. Tang <jtang@tresys.com>
+
+ * This is the official release of SETools 3.3.5.
+
+ * Fixed errors in libapol's AV and TE rule rendering functions
+ where errno was not being set properly.
+
+ * Fixed error in apol_syn_avrule_render() where braces were not
+ being added around the target set when there is exactly one target
+ type and the keyword 'self'. Thanks to Ryan Kagin for reporting
+ this error.
+
+2008-08-14 J. Tang <jtang@tresys.com>
+
+ * Synched libqpol to libsepol version 2.0.32, policy parser to
+ 2.0.16.
+
+ * Synched libqpol to libsepol version 2.0.26, policy parser to
+ 2.0.14.
+
+ * Added qpol_type_get_ispermissive(). SETools can now handle
+ version 23 policy; bumped libqpol to version 1.4.
+
+2008-03-07 J. Tang <jtang@tresys.com>
+
+ * This is the official release of SETools 3.3.4.
+
+ * debian/control: Added transitional packages for libapol1,
+ libseaudit1, libsefs1, and their associated development package.
+
+ * packages/rpm/fc9-compile.diff: Added a patch to allow building
+ of SETools on Fedora 9, due to possible buggy gcc/glibc-header
+ interaction in libseaudit/swig/python.
+
+2008-03-05 J. Tang <jtang@tresys.com>
+
+ * Fixes to libapol and libqpol to allow SETools to compile under
+ gcc/g++ 4.3.
+
+ * Added autodetection of Tk, needed for Tk 8.5.
+
+ * Synced libqpol to policy parser to 2.0.13.
+
+2008-02-29 J. Tang <jtang@tresys.com>
+
+ * Synced libqpol to libsepol version 2.0.23, policy parser to
+ 2.0.10.
+
+2008-02-21 J. Tang <jtang@tresys.com>
+
+ * This is the official release of SETools 3.3.3.
+
+ * Fixes to qpol_default_policy_find() to properly return policies
+ whose versions are greater than the currently running system.
+
+2008-02-19 J. Tang <jtang@tresys.com>
+
+ * Added QPOL_POLICY_OPTION_MATCH_SYSTEM as a policy load option to
+ qpol_policy_open_from_file(). The tools seinfo, sesearch, and
+ sechecker will now use this flag when loading the system's default
+ policy.
+
+ * Modified libqpol to understand version 22 policy. Added
+ QPOL_CAP_POLCAPS to qpol_capability enum.
+
+2008-02-15 J. Tang <jtang@tresys.com>
+
+ * Synced libqpol to libsepol version 2.0.20. The configure script
+ will check if dynamic avtabs exist (introduced in libsepol 2.0.20)
+ and will adjust policy loading as necessary.
+
+2008-01-09 J. Tang <jtang@tresys.com>
+
+ * Added initial attempt at Debian-izing SETools. The Debian
+ control files are only present in the SVN checkout of SETools, not
+ in the distributed tarball.
+
+2007-11-02 J. Tang <jtang@tresys.com>
+
+ * Ported bug fixes in branches/setools-devel to trunk. This is
+ the official release of SETools 3.3.2.
+
+ * Fixed error in libsefs/Java where the library has not been built
+ correctly since version 4 of libsefs.
+
+2007-10-31 J. Mowery <jmowery@tresys.com>
+
+ * Fix to libqpol when querying policies with no genfscon statements.
+
+ * Fix to SWIG wrappers to correctly report exceptions in multi-threaded
+ Java environments.
+
+2007-10-31 J. Tang <jtang@tresys.com>
+
+ * Modifed libqpol to explicitly ignore disabled aliases.
+
+ * Merged RedHat's spec file changes.
+
+2007-10-08 J. Tang <jtang@tresys.com>
+
+ * Fix to libqpol when qpol_type_get_alias_iter() could erroneously
+ be set to an initially wrong position for certain primary types.
+
+2007-10-02 J. Tang <jtang@tresys.com>
+
+ * Fix to libqpol to synthesize object_r. This was previously
+ (erroneously) handled in libapol.
+
+2007-09-26 J. Tang <jtang@tresys.com>
+
+ * Fix to apol where empty levels would throw an error during
+ validation.
+
+2007-09-04 J. Mowery <jmowery@tresys.com>
+
+ * Fixes to libsefs and apol if an invalid regular expression is
+ given.
+
+2007-08-30 J. Mowery <jmowery@tresys.com>
+
+ * Do not look for neverallow rules on default avrule query if not
+ available.
+
+2007-08-22 J. Tang <jtang@tresys.com>
+
+ * Ported bug fixes in branches/setools-devel to trunk. This is
+ the official release of SETools 3.3.1.
+
+2007-08-20 J. Tang <jtang@tresys.com>
+
+ * Fixed memory leak in libapol/infoflow analysis, where edges were
+ not being freed. Thanks to Ben Martin for spotting this error.
+
+2007-08-16 J. Tang <jtang@tresys.com>
+
+ * Fixed an error in libapol's infoflow. When performing a
+ transitive search, let there be an intermediate rule with source
+ A, an attribute. If a member of A, type T, is excluded by not
+ calling apol_infoflow_analysis_append_intermediate(), it was still
+ possible to return an infoflow result that uses T. This has been
+ fixed.
+
+2007-08-13 J. Tang <jtang@tresys.com>
+
+ * Fix error in libsefs when querying a filesystem or fcfile by
+ range, but the fclist is not MLS.
+
+2007-08-06 J. Tang <jtang@tresys.com>
+
+ * configure.ac: Tk is checked only if --enable-swig-tcl and
+ --enable-gui are given. Also, if tclconfig.sh is not found, then
+ abort configuration.
+
+ * apol/top.tcl: Fixed error where reading from an older .apol file
+ (from SETools < 3.2) would cause a startup problem.
+
+ * libapol/include/apol/domain-trans-analysis.h: Upon invalid
+ transition, empty vectors are returned rather than NULL pointers.
+
+2007-08-02 J. Tang <jtang@tresys.com>
+
+ * Official release of SETools 3.3.
+
+2007-08-02 J. Mowery <jmowery@tresys.com>
+
+ * Corrected sechecker module incomplete domain transitions
+ to once again return results for missing RBAC and user policy
+ for transitions that have sufficient type enforcement rules.
+
+2007-07-27 J. Tang <jtang@tresys.com>
+
+ * Library jar files are now installed in
+ $PREFIX/share/setools-<version>, with symlinks in
+ $PREFIX/share/java. They used to be placed in
+ $PREFIX/lib/setools.
+
+ * Added framework for CUnit tests for libseaudit.
+
+2007-07-26 J. Tang <jtang@tresys.com>
+
+ * Updated all linker map and SWIG interface files to match
+ exported library headers.
+
+ * libseaudit/src/filter.c (seaudit_filter_set_match): Added
+ ability to set strictness of libseaudit filters. Be default,
+ filters are not strict; this matches previous libseaudit behavior.
+ See seaudit_filter_set_match() for definition of "strictness".
+
+2007-07-26 M. Goldman <mgoldman@tresys.com>
+ * Added tooltip to glade interface noting that diffing never
+ allow rules could dramaticly increase run time
+
+ * Fixed names in sediffx to be more descriptive (the tree view
+ in the upper left hand corner). Names changed from
+ AVRules auditallow to Audit Allow Rules as an example.
+
+2007-07-24 J. Tang <jtang@tresys.com>
+
+ * Added framework for CUnit tests for libapol.
+
+2007-07-23 J. Tang <jtang@tresys.com>
+
+ * Added framework for CUnit tests for libpoldiff and libqpol.
+ configure now has the option --with-test-policies to specify where
+ the test policies reside.
+
+2007-07-20 J. Tang <jtang@tresys.com>
+
+ * Added seaudit_filter for PID.
+
+2007-07-19 J. Tang <jtang@tresys.com>
+
+ * Added many optimizations to qpol_policy_build_syn_rule_table()
+ and associated functions. With some code rewrites, a doubling of
+ the syntactic rule hash table size, and an improved hashing
+ function, it is at least three times faster to build the table.
+
+2007-07-18 J. Tang <jtang@tresys.com>
+
+ * Fixed error in libpoldiff where if an AV or a TE rule was within
+ a conditional that had multiple boolean variables, the diff
+ algorithm would generate an incorrect STC key for that rule.
+
+2007-07-17 J. Mowery <jmowery@tresys.com>
+
+ * Updated domain transition analysis to use the BST internally;
+ this should result in improved performance.
+
+2007-07-13 J. Tang <jtang@tresys.com>
+
+ * Java SWIG libraries now check if the libraries needs to be
+ loaded before doing such.
+
+ * Added more filtering options to libseaudit.
+
+2007-07-12 J. Tang <jtang@tresys.com>
+
+ * seaudit_filter_set_ipaddress() is renamed to
+ seaudit_filter_set_anyaddr(). seaudit_filter_set_port() is now
+ seaudit_filter_set_anyport(). Similar changes occurred to the
+ respective accessors.
+
+2007-07-11 M. Goldman <mgoldman@tresys.com>
+
+ * Split functions relating to item records out into their own
+ file. Added documentation for same.
+
+2007-07-09 J. Tang <jtang@tresys.com>
+
+ * Added additional sort constructors to libseaudit.
+
+2007-07-05 J. Tang <jtang@tresys.com>
+
+ * seaudit now has a button to clear all messages from a view.
+ This is useful when doing log monitoring, to show only new
+ messages.
+
+ * Added seaudit_model_hide_message(), to suppress display of
+ certain messages within a model.
+
+2007-06-28 J. Tang <jtang@tresys.com>
+
+ * Updated apol and sediffx to delay loading neverallow rules
+ unless the user requested analyzing them.
+
+2007-06-25 J. Tang <jtang@tresys.com>
+
+ * Updated apol(1) to use new libsefs
+
+ * Updated replcon(1) to use new libsefs.
+
+2007-06-19 J. Tang <jtang@tresys.com>
+
+ * Updated indexcon(1) to use new libsefs.
+
+ * Merged searchcon(1) functionality into findcon(1); man pages
+ updated. searchcon(1) has been removed from SETools.
+
+ * libsefs.so.4 is now wrapped by SWIG, for Python, Java, and
+ Tcl.
+
+ * Rewrite of libsefs to meet coding standards. libsefs.so.4 is an
+ object-oriented library that abstracts away filesystems,
+ file_contexts files, and databases into a unified object that can
+ be queried easily.
+
+2007-06-18 J. Tang <jtang@tresys.com>
+
+ * libpoldiff/include/poldiff/rbac_diff.h: Added
+ poldiff_role_allow_get_unmodified_roles(). The return values
+ poldiff_role_allow_get_added_roles() and
+ poldiff_role_allow_get_removed_roles() have been changed for forms
+ POLDIFF_FORM_ADDED and POLDIFF_FORM_REMOVED.
+
+2007-06-14 J. Tang <jtang@tresys.com>
+
+ * SETools can now compile against GTK+ 2.4. Nonetheless, GTK+ 2.8
+ is still the recommended toolkit.
+
+2007-06-13 J. Tang <jtang@tresys.com>
+
+ * libseaudit/src/log.c (seaudit_log_clear): Added ability to clear
+ a log of its messages.
+
+2007-06-12 J. Tang <jtang@tresys.com>
+
+ * SETools now requires libsqlite3, version 3.2.0 or greater. It
+ used to ship with its own copy of sqlite3; that is no longer the
+ case.
+
+2007-06-11 M. Goldman <mgoldman@tresys.com>
+ * Updated swig interface to properly expose av and te rule
+ vector accessor functions for libpoldiff.
+
+2007-06-08 J. Mowery <jmowery@tresys.com>
+
+ * Fixed an error in libpoldiff where
+ poldiff_terule_get_modified_default() was returning the
+ original default; it now correctly returns the modified
+ default type.
+
+2007-06-08 M. Goldman <mgoldman@tresys.com>
+
+ * updated sediffx diffs so that the subrules for avrules and
+ terules are broken out into allow, neverallow, auditallow,
+ dontaudit type_member, type_change, and type_transition rules
+
+2007-06-04 J. Tang <jtang@tresys.com>
+
+ * added convert functions to apol_context_t and
+ apol_mls_range_t; added constructors
+ apol_mls_range_create_from_string() and
+ apol_mls_range_create_from_literal().
+
+2007-05-31 J. Tang <jtang@tresys.com>
+
+ * libapol/src/util.c (apol_str_to_objclass): Added this function,
+ as the complement to apol_objclass_to_str().
+
+ * libapol/src/mls_level.c (apol_mls_level_is_literal),
+ libapol/src/mls_range.c (apol_mls_range_is_literal): Added
+ ability to query if level/range is literal. This is needed when
+ printing an apol_context_t containing a literal level.
+
+ * libapol: split mls-query.h into mls-query.h, mls_level.h, and
+ mls_range.h. This file was much too large.
+
+2007-05-30 J. Tang <jtang@tresys.com>
+
+ * libapol/src/mls-query.c (apol_mls_level_create_from_literal)
+ (apol_mls_level_convert): The apol_mls_level_t object can now be
+ created without relying upon a policy. Call
+ apol_mls_level_convert() to complete its category list.
+
+2007-05-30 J. Mowery <jmowery@tresys.com>
+
+ * The --regex flag in sesearch now also applies to --class.
+
+2007-05-29 J. Tang <jtang@tresys.com>
+
+ * ./configure no longer has --enable-sefs flag, for libselinux is
+ required to build SETools. (The kernel does need to have SELinux
+ running, though.) Therefore, libsefs is now always built.
+
+ * apol converted to use the SWIG interface for Tcl.
+
+ * libapol/src/types-relation-analysis.c
+ (apol_types_relation_domain): Domain transition table was not
+ correctly reset when intermixing calls between
+ apol_types_relation_analysis_do() and
+ apol_domain_trans_analysis_do().
+
+2007-05-22 J. Tang <jtang@tresys.com>
+
+ * Added infoflow defines to apol.i. Added apol_file_find_path()
+ to apol.i. They were inadvertently missing from the interface
+ file.
+
+2007-05-22 J. Mowery <jmowery@tresys.com>
+
+ * Renamed apol_permmap_*() to apol_policy_*_permmap() to
+ correctly reflect the fact that the policy owns the permmap.
+
+2007-05-21 J. Mowery <jmowery@tresys.com>
+
+ * Renamed apol_policy_domain_trans_table_build() and
+ apol_domain_trans_table_reset() to apol_policy_build_domain_trans_table()
+ and apol_polciy_reset_domain_trans_table() respectively. This change
+ reflects the correct namespace for these operations.
+
+2007-05-18 J. Mowery <jmowery@tresys.com>
+
+ * Deprecated qpol_policy_extend(); this function is called
+ automatically by qpol_policy_open* and qpol_policy_rebuild()
+ and therefore does not need to be called separately.
+
+2007-05-16 J. Tang <jtang@tresys.com>
+
+ * Right-clicking an apol results display now pops up a menu, that
+ allows the user to copy and to select all.
+
+ * libapol/swig/apol.i: Within the SWIG interfaces, there now
+ exists an object "apol_ip_t", that represents both an IP address
+ and a protocol. apol_str_to_internal_ip() returns an apol_ip_t,
+ which may then be used when setting an apol_nodecon_query_t. Note
+ that this only affects the SWIG generated libraries, not the
+ original libapol.
+
+ * SETools now requires a C99 compliant C compiler. The supplied
+ configure script will check for a working C99 compiler.
+
+2007-05-16 M. Goldman <mgoldman@tresys.com>
+ * modified libpoldiff to support partial diffing of avrules
+
+ * modified sediff to expose partial diffing of avrules functionality
+
+2007-05-15 J. Tang <jtang@tresys.com>
+
+ * libqpol/src/mls_query.c (qpol_level_get_alias_iter): Fixed
+ possible error when getting a level's alias iterator, where the
+ first element returned might be the original level instead of one
+ of its alias.
+
+ * libapol/include/apol/policy-path.h, libapol/include/apol/util.h:
+ Headers errantly included <config.h>.
+
+ * libapol/src/netcon-query.c (apol_nodecon_query_set_proto)
+ (apol_portcon_query_set_proto): These have been renamed to
+ apol_nodecon_query_set_protocol() and
+ apol_portcon_query_set_protocol() respectively.
+
+ * libapol/src/util.c (apol_str_to_protocol): Added this function,
+ to complement existing apol_protocol_to_str().
+
+ * libapol/src/mls-query.c (apol_mls_range_contain_subrange): Fixed
+ potential segfault if a range's high level is not yet set when
+ comparison occurs.
+
+2007-05-14 J. Mowery <jmowery@tresys.com>
+
+ * correctly marked libqpol defines for genfscon object classes
+ and fs_use behaviors as unsigned constants.
+
+2007-05-14 J. Tang <jtang@tresys.com>
+
+ * libapol/src/role-query.c (apol_role_get_by_query),
+ libapol/src/user-query.c (apol_user_get_by_query): Extra logic
+ added when "object_r" is given as the role. For user queries, all
+ users implicitly have object_r assigned to them. For role
+ queries, all types are assigned to object_r.
+
+ * libapol/swig/apol.i: apol_context_validate() and
+ apol_context_validate_partial() are now member functions of class
+ apol_context_t, rather than being a library function.
+
+ * libapol/include/mls-query.h (apol_mls_cat_name_compare): Removed
+ apol_mls_cat_name_compare() from the libapol public API. This
+ function should never have been made public.
+
+ * libapol/src/context-query.c: Fixed potential segfaults in
+ modifiers to apol_context_t object, if the same pointer returned
+ by its accessor is then passed back in the modifier modifier.
+
+ * libapol/src/context-query.c (apol_context_render): When
+ rendering a partial context, unset fields are now explicitly
+ represented by an asterisk, rather than by an empty string.
+
+2007-05-11 J. Mowery <jmowery@tresys.com>
+
+ * removed usage of typedef'ed bool_t and replaced with bool as
+ defined by stdbool.h; also replaced defined TRUE and FALSE
+ with true and false constants as defined by stdbool.h.
+
+2007-05-11 J. Tang <jtang@tresys.com>
+
+ * Fix potential segfaults in apol_mls_range functions if the high
+ level is not set.
+
+ * Added apol_mls_level_validate() to SWIG wrappers. Added
+ apol_mls_range_get_low() and apol_mls_range_get_high().
+ apol_mls_range_validate() is now a member function of class
+ apol_mls_range_t, rather than a library function.
+
+ * Within the SWIG wrappers, apol_mls_level_get_cats() returns a
+ vector. This should have been a string vector instead.
+
+ * Added function apol_mls_level_validate().
+
+2007-05-10 J. Tang <jtang@tresys.com>
+
+ * Added setools-libs-tcl target to setools.spec.
+
+ * Removed apol/apol.c; apol is now just a Tcl script that is
+ executed by tclsh, rather than a custom compiled Tcl interpreter.
+
+ * Removed the deprecated header apol/avl-util.h and its associated
+ source file.
+
+2007-05-08 M. Goldman <mgoldman@tresys.com>
+ * Added next and previous buttons to seaudit
+
+ * Added apol_bst_inorder_map()
+
+2007-05-07 J. Mowery <jmowery@tresys.com>
+
+ * Changed apol_ipv4_addr_render so that it now takes an array
+ of uint32_t's instead of a single uint32_t.
+
+ * Changed SWIG wrapping for apol_perm_query_t::run() to return
+ apol_string_vector_t instead of apol_vector_t.
+
+ * Added exported pointers to SWIG wrappers of each library
+ to allow changing of the message handler callback and its
+ void * argument.
+
+ * qpol_policy_rebuild() no longer requires a modular policy;
+ it can safely be called for any type of policy.
+
+2007-05-04 J. Tang <jtang@tresys.com>
+
+ * Fixed qpol_module function names in the libqpol SWIG wrappers.
+
+2007-05-04 J. Mowery <jmowery@tresys.com>
+
+ * Added SWIG wrappers for tcl to libpoldiff and libseaudit.
+
+2007-05-02 J. Mowery <jmowery@tresys.com>
+
+ * Versioned symbols in other libraries.
+
+2007-05-01 J. Mowery <jmowery@tresys.com>
+
+ * Versioned symbols in libqpol to allow conditional expansion
+ of neverallow rules from qpol_policy_open_from_*.
+
+2007-05-01 J. Tang <jtang@tresys.com>
+
+ * Added apol_avrule_query_set_all_perms(). This changes the
+ behavior when matching multiple permissions.
+
+2007-04-30 J. Tang <jtang@tresys.com>
+
+ * Added --enable-swig-tcl flag to configure script.
+
+2007-04-25 J. Tang <jtang@tresys.com>
+
+ * Official release of SETools-3.2.
+
+2007-04-20 J. Tang <jtang@tresys.com>
+
+ * Added seaudit_log_parse_buffer(), needed because
+ seaudit_log_parse() is not possible with the Java SWIG library.
+
+ * Build system updated to suppress warnings from automake
+ 1.10, and for parallel compilation (i.e., make -j).
+
+2007-04-18 J. Mowery <jmowery@tresys.com>
+
+ * The function apol_domain_trans_result_create_from_domain_trans_result()
+ is now publicly exported. Also added is apol_domain_trans_result_destroy()
+ to free memory used by duplicated results.
+
+2007-04-17 J. Tang <jtang@tresys.com>
+
+ * Fixed potential segfault in seaudit_filter_set_date() when
+ called using the same struct tm pointers that were returned by
+ seaudit_filter_get_date(). The old code would dereference
+ memory that was just free()d.
+
+2007-04-16 J. Tang <jtang@tresys.com>
+
+ * apol_mls_range_get_levels() fixed so that its returned levels
+ only include categories that are valid for the given policy.
+ Before it just copied the categories for the high level, even if a
+ lower level could not actually have one of those categories.
+
+ * apol_mls_level_get_cats() now always returns categories in
+ alphabetical order.
+
+2007-04-06 J. Tang <jtang@tresys.com>
+
+ * Added seaudit_avc_message_get_name() and
+ seaudit_sort_by_name(). seaudit now shows AVC messages' name
+ field; this column may be be hidden through the updated
+ preferences dialog.
+
+ * Updated libqpol to use libsepol >= 2.0.0 if available.
+ configure should be able to autodetect this.
+
+2007-04-05 J. Tang <jtang@tresys.com>
+
+ * sediffx now allows the user to select which components to diff,
+ rather than always diffing everything.
+
+ * fix to domain transition analysis, where setexec rules might not
+ be found correctly given certain policies.
+
+2007-04-04 J. Tang <jtang@tresys.com>
+
+ * New configure option --enable-swig-java to enable build of Java
+ SWIG wrappers.
+
+2007-04-03 J. Mowery <jmowery@tresys.com>
+
+ * Added apol_file_is_policy_path_list() to validate policy path
+ list files.
+
+ * Added ability to specify policy path list files from command
+ line for all tools taking a policy as an argument.
+
+2007-04-02 J. Mowery <jmowery@tresys.com>
+
+ * Removed the "all_files" symbol from libsefs; this symbol was
+ previously marked as deprecated.
+
+2007-03-29 J. Mowery <jmowery@tresys.com>
+
+ * Libpoldiff SWIG wrapper added; wrapper treats all structures as
+ classes in the target language.
+
+2007-03-28 J. Tang <jtang@tresys.com>
+
+ * Introduced 'policy list' in apol, seaudit, and sediffx. This is
+ a small text file that contains references to a base policy and
+ any number of modules.
+
+2007-03-27 J. Tang <jtang@tresys.com>
+
+ * added apol_policy_path_create_from_file() and
+ apol_policy_path_to_file().
+
+ * apol_str_trim() no longer has a return value; it also operates
+ directly on a string, rather than a reference to a string.
+
+ * apol_vector_t and apol_bst_t now require a destructor function
+ to be given during creation time, rather than being passed as a
+ second parameter respectively to apol_vector_destroy() and
+ apol_bst_destroy(). All of SETools has been updated to this
+ scheme.
+
+2007-03-26 J. Tang <jtang@tresys.com>
+
+ * apol_context_t is now an opaque structure. Accessors added to
+ the user, role, type, and range fields.
+
+2007-03-23 J. Tang <jtang@tresys.com>
+
+ * added apol_mls_level_get_sens() and apol_mls_level_get_cats().
+
+2007-03-23 J. Mowery <jmowery@tresys.com>
+
+ * Libseaudit SWIG wrapper added; wrapper treats all structures as
+ classes in the target language.
+
+2007-03-23 J. Tang <jtang@tresys.com>
+
+ * apol_mls_level_t and apol_mls_range_t are now opaque structures.
+
+ * fixed error in seaudit_model_create_from_model(), where the
+ duplicate's filters and sorts were being linked to the original
+ model, not the newly created one.
+
+ * fixed potential segfault in seaudit_filter_set_name() and
+ seaudit_filter_set_description() if the passed in pointer was the
+ same one obtained by the respecitve accessor function.
+
+2007-03-22 J. Mowery <jmowery@tresys.com>
+
+ * Libapol SWIG wrapper updated to treat all structures as classes
+ in the target language.
+
+2007-03-21 J. Tang <jtang@tresys.com>
+
+ * Added ability for user to specify type joins and splits in
+ sediffx. The libpoldiff library had always supported this
+ feature; it just was not available through the user interface.
+
+2007-03-20 J. Mowery <jmowery@tresys.com>
+
+ * Renamed apol_domain_trans_table_destroy to domain_trans_table_destroy
+ and moved to policy-query-internal.h; this function was not intended
+ for external use.
+
+2007-03-19 J. Tang <jtang@tresys.com>
+
+ * When viewing AV rule differences, click (either left or right) a
+ permission name. This will now popup a menu that gives line
+ numbers for rules that contributed just that permission, rather
+ than the entire AV rule. This is enabled when source policies are
+ used.
+
+2007-03-16 J. Tang <jtang@tresys.com>
+
+ * Added poldiff_avrule_get_orig_line_numbers_for_perm() and
+ poldiff_avrule_get_mod_line_numbers_for_perm().
+
+2007-03-15 J. Tang <jtang@tresys.com>
+
+ * Split libpoldiff/include/rule_diff.h into
+ libpoldiff/include/avrule_diff.h and
+ libpoldiff/include/terule_diff.h. None of the function names were
+ changed.
+
+ * Re-standardized all programs' command line options. -V always
+ shows the version, -c always deals with object classes, and so
+ forth. Man pages updated.
+
+ * Renamed libapol/include/rangetrans-query.h to
+ libapol/include/range_trans-query.h. Likewise renamed
+ libpoldiff's rangetrans_diff.h None of the function names were
+ changed.
+
+2007-03-13 J. Tang <jtang@tresys.com>
+
+ * fixed segfault in libseaudit when, while parsing an AVC
+ message's permissions list it does not encounter a closing brace.
+
+ * information flow graphs are now being constructed via a BST and
+ its O(log n), rather than via a vector and O(n). It should be
+ noticeably faster now.
+
+ * fixed error in information flow analysis, transitive mode. The
+ returned flows were mistakenly all set to be the same object
+ class. For example if a step was foo_t -> bar_t by way of class
+ baz_c, subsequent flows were accidentally being constrained to
+ also be of baz_c.
+
+ * fixed error in apol_bst_insert() and apol_bst_insert_and_get(),
+ where the return values of 0 and 1 were flipped. The comment was
+ correct, but the code was not.
+
+2007-03-12 J. Tang <jtang@tresys.com>
+
+ * fixed share libraries's soname, such that SETools's programs
+ depend upon the correct name. For example, seaudit's .dynamic
+ section should have as a dependency on libseaudit.so.4, not
+ libseaudit.so.4.1.
+
+ * sediffx now diffs and displays range transitions
+
+ * sediff -E now diffs range transitions
+
+ * range transition diff added libpoldiff
+
+2007-03-08 J. Tang <jtang@tresys.com>
+
+ * poldiff_user_get_added_roles() and
+ poldiff_user_get_removed_roles() now return all roles when the
+ form is POLDIFF_FORM_ADDED / POLDIFF_FORM_REMOVED.
+
+ * sediffx updated to show users' MLS differences
+
+2007-03-07 J. Tang <jtang@tresys.com>
+
+ * in libpoldiff, if either policy is MLS then when diffing users,
+ those users' default MLS level and assigned ranges are also
+ diffed.
+
+ * added poldiff_range_t object
+
+ * fixed segfault in libqpol when loading an invalid source policy
+
+ * error messages were not being shown correctly in apol's open
+ policy dialog; fixed.
+
+2007-03-06 J. Mowery <jmowery@tresys.com>
+
+ * added SWIG wrapper for libqpol. The wrapper treats all libqpol
+ structs as classes in the target language.
+
+2007-03-06 J. Tang <jtang@tresys.com>
+
+ * apol_mls_level_create() will now always return an allocated (and
+ empty) category vector as part of the level. Before it would
+ initialize the field as NULL.
+
+ * poldiff_avrule_get_unmodified_perms() no longer returns all
+ permissions whenever a rule is added or removed; it only returns
+ permissions when the form is POLDIFF_FORM_MODIFIED. The new
+ behavior matches the other policy components.
+
+2007-03-05 J. Tang <jtang@tresys.com>
+
+ * added apol_mls_level_free() and apol_mls_range_get_levels()
+
+2007-03-02 J. Tang <jtang@tresys.com>
+
+ * qpol_user_get_range() and qpol_user_get_dfltlevel() now return
+ NULL if the policy is not MLS. (It used to return a garbage
+ pointer.)
+
+2007-03-01 J. Tang <jtang@tresys.com>
+
+ * added additional accessors to the seaudit_avc_message_t object.
+
+2007-02-28 J. Tang <jtang@tresys.com>
+
+ * added apol_mls_level_create_from_mls_level() and
+ apol_mls_range_create_from_mls_range() copy constructors.
+
+ * Fixed segfault when libseaudit attempts to parse certain load
+ policy messages.
+
+2007-02-23 J. Tang <jtang@tresys.com>
+
+ * Implemented new sediffx results design. Results are implemented
+ as subclasses of an abstract result_item_t class. This will allow
+ easier future modifications of the sediffx interface.
+
+2007-02-21 J. Tang <jtang@tresys.com>
+
+ * fixed segfault when opening a policy with
+ APOL_POLICY_OPTION_NO_RULES when the policy has an unconditional
+ type_transition rule.
+
+2007-02-16 J. Mowery <jmowery@tresys.com>
+
+ * Moved libqpol/include/qpol/expand.h to libqpol/src/expand.h.
+ This header file was never supposed to be visible.
+
+ * added SWIG wrappers to libapol; build system updated. configure
+ must be passed --enable-swig-python to build the wrappers.
+
+2007-02-14 J. Tang <jtang@tresys.com>
+
+ * sesearch and apol now allow searching range transitions based
+ upon the target class. (Target classes were introduced in version
+ 21 policies.)
+
+ * added to apol_range_trans_query_append_class() to
+ libapol/include/apol/rangetrans-query.h
+
+2007-02-07 J. Mowery <jmowery@tresys.com>
+
+ * split --audit flag in sesearch to --auditallow and --dontaudit;
+ the --audit flag is now deprecated.
+
+2007-02-06 J. Tang <jtang@tresys.com>
+
+ * Official release of SETools-3.1.
+
+ * Compile fixes for 64-bit Linux.
+
+2007-02-02 J. Tang <jtang@tresys.com>
+
+ * added RPM spec files.
+
+2007-01-30 J. Tang <jtang@tresys.com>
+
+ * fixed error in apol when right-clicking an attribute when a file
+ contexts database is loaded.
+
+ * fixed error in SQLite configuration in which a pointer size was
+ defined as the size of an integer. this is a no longer valid
+ assumption on 64-bit architectures.
+
+ * if apol has a modular policy loaded, then its "policy version"
+ for purposes of permission maps is now set to the maximum policy
+ version as defined in libsepol. this mimics the linking behavior
+ of sepol.
+
+2007-01-25 J. Tang <jtang@tresys.com>
+
+ * fixed error where aliases within modules were not being detected
+ properly
+
+2007-01-19 J. Mowery <jmowery@tresys.com>
+
+ * all files now have correct copyright and license notices
+
+2007-01-19 J. Tang <jtang@tresys.com>
+
+ * updated all help documentation
+
+2007-01-17 J. Mowery <jmowery@tresys.com>
+
+ * updated all man pages
+
+2007-01-17 J. Tang <jtang@tresys.com>
+
+ * added poldiff_type_remap_entry_get_is_inferred()
+
+ * sediffx converted to use modular policies.
+
+2007-01-08 J. Tang <jtang@tresys.com>
+
+ * apol converted to use modular policies.
+
+2007-01-05 J. Mowery <jmowery@tresys.com>
+
+ * Added capability QPOL_CAP_SOURCE to detect ability to display
+ the policy source.
+
+ * Deprecated qpol_policy_is_mls_enabled() use
+ qpol_policy_has_capability() for QPOL_CAP_MLS instead.
+
+2007-01-04 J. Tang <jtang@tresys.com>
+
+ * seaudit converted to use modular policies.
+
+2007-01-03 J. Tang <jtang@tresys.com>
+
+ * Deprecated apol_policy_open() and apol_policy_open_no_rules();
+ use apol_policy_create_from_policy_path() instead.
+
+2006-12-14 J. Tang <jtang@tresys.com>
+
+ * Added apol_policy_path_t object. This is needed because policy
+ paths are not just a single string, but rather a base policy and
+ any number of modules.
+
+ * New functions apol_config_join_var() generalized to be
+ apol_str_join(). Same with apol_config_split_var() ->
+ apol_str_split().
+
+2006-12-12 J. Tang <jtang@tresys.com>
+
+ * Renamed qpol_find_default_policy_file() in qpol/policy.h to
+ qpol_default_policy_find() in qpol/util.h. Removed
+ qpol_find_default_policy_file_strerr(). These functions were
+ never supposed to be in these locations.
+
+ * Deprecated apol_policy_is_binary(); use qpol policy capabilities
+ instead.
+
+ * Deprecated qpol_open_policy_from_file(); it is now called
+ qpol_policy_open_from_file(). Similar change to
+ qpol_open_policy_from_file_no_rules() and
+ qpol_open_policy_from_memory().
+
+ * Merged qpol/policy_query.h into qpol/policy.h. Split module
+ related code into qpol/module.h.
+
+ * Rewrite of seaudit to utilize libseaudit.so.4; tweaked numerous
+ interface issues.
+
+ * Rewrite of libseaudit to meet coding standards. libseaudit.so.4
+ is now a shared object file with proper namespacing.
+
+2006-12-11 J. Mowery <jmowery@tresys.com>
+
+ * Added qpol_policy_has_capability() to qpol/policy_query.h
+ This function and the enumeration qpol_capability_e allows
+ a user of the library to check if a loaded policy is
+ capable of supporting various policy features.
+
+ * Support has been added to libqpol for loading policy modules.
+ See qpol/policy.h for details.
+
+2006-12-01 J. Tang <jtang@tresys.com>
+
+ * deprecated apol_config_get_varlist() and
+ apol_config_varlist_to_str(); added apol_file_find_path(),
+ apol_config_split_var(), and apol_config_join_var()
+
+2006-12-01 J. Tang <jtang@tresys.com>
+
+ * Official release of SETools 3.0.1.
+
+2006-11-29 J. Tang <jtang@tresys.com>
+
+ * synced source parser to libsepol 1.15.2.
+
+2006-11-27 J. Tang <jtang@tresys.com>
+
+ * added application icons to apol, seaudit, and sediffx
+
+2006-11-09 j. Mowery <jmowery@tresys.com>
+
+ * added __cplusplus guards to all external headers
+
+2006-11-08 J. Tang <jtang@tresys.com>
+
+ * apol_permmap_t is now a hidden declaration.
+ apol_permmap_destroy() has been removed. (It should never have
+ been publicly visible.)
+
+ * apol_policy_t is now an opaque structure. Added accessors such
+ as apol_policy_get_qpol() to retrieve some of those fields. This
+ also means that the apol callback function changed, so as to be
+ similar to qpol's callback.
+
+2006-11-07 J. Mowery <jmowery@tresys.com>
+
+ * renamed apol_get_*_by_query() to apol_*_get_by_query to match
+ naming conventions of other functions. Old versions were retained and
+ marked as deprecated.
+
+2006-11-02 J. Tang <jtang@tresys.com>
+
+ * added apol_str_strdup() (declared in apol/util.h)
+
+ * apol_vector_create_from_vector() takes two additional arguments,
+ so that it can act more like a copy constructor.
+
+
+2006-11-01 J. Mowery <jmowery@tresys.com>
+
+ * added ability for avrule and terule queries to search to only types or
+ only attributes for both source and target fields (separate option for
+ each field, default is to search both types and attributes).
+
+ * added apol_get_syn_avrule_by_query() and apol_get_syn_terule_by_query()
+
+2006-10-27 J. Tang <jtang@tresys.com>
+
+ * added apol_str_appendf() (declared in apol/util.h)
+
+2006-10-27 J. Mowery <jmowery@tresys.com>
+
+ * added make indent to standardize code indentation style
+
+ * indented all .c and .h files with make indent (except sqlite which it skips)
+
+2006-10-25 J. Tang <jtang@tresys.com>
+
+ * seaudit-report Logwatch script will look for
+ $(bindir)/seaudit-report, rather than the hard-coded
+ /usr/bin/seaudit-report
+
+2006-10-25 J. Mowery <jmowery@tresys.com>
+
+ * numbered steps for loading
+
+ * loading syntactic rule table is now off by default
+
+ * updated tools requiring line numbers to build syntactic table as needed
+
+2006-10-24 J. Tang <jtang@tresys.com>
+
+ * exclude the sqlite files from the Doxygen configuration
+
+2006-10-19 J. Tang <jtang@tresys.com>
+
+ * added lib<foo>_get_version() functions to libqpol, libpoldiff,
+ and libsefs
+
+2006-10-17 J. Tang <jtang@tresys.com>
+
+ * seaudit-report binary was mistakenly called "seaudit_report"
+
+ * Updated man pages to match programs' help files.
+
+2006-10-13 J. Tang <jtang@tresys.com>
+
+ * Official release of SETools 3.0.
diff --git a/KNOWN-BUGS b/KNOWN-BUGS
new file mode 100644
index 0000000..8e2acca
--- /dev/null
+++ b/KNOWN-BUGS
@@ -0,0 +1,73 @@
+SETools version 3.3
+Tresys Technology
+setools@tresys.com, http://oss.tresys.com/projects/setools
+
+
+August 15, 2008
+
+
+CURRENT BUGS AND ISSUES
+
+This file contains a description of the currently aware issues with
+SETools. There are undoubtedly more; please report any new problems
+to setools-bugs@tresys.com.
+
+SETOOLS
+
+1. There is a critical error in libsepol versions 1.16.2 and 2.0.2
+ that prevents SETools from opening source policies. The supplied
+ configure script will detect and abort if it finds this particular
+ version.
+
+APOL
+
+1. Double clicking on listbox items may not display popup windows in
+ certain window managers. Instead the user can right-click on the
+ item in order to display popup windows. This is due to Tk's event
+ buffer and is not fixable. (Ref: http://tinyurl.com/ltmuh)
+
+2. Apol will correctly load policies with aliases, but the alias names
+ will be lost (the root type name is used instead). Therefore,
+ aliases are not displayed and queries should not use them as
+ parameters.
+
+3. Certain older source policies will not load if complemented type
+ sets are used outside of neverallow rules. This is due to apol using
+ a similar parser to checkpolicy, which no longer accepts this use of
+ the complement operator (~).
+
+SEAUDIT
+
+1. Sorting by date will not work correctly if an audit log spans
+ through a new calendar year. For example, if the audit log
+ includes entries from December 2003 and January 2004, when sorted
+ by date January 2004 will come before the December 2003 entry. This
+ is because audit logs do not include a year; all messages are
+ assumed to have occurred on the same year.
+
+2. Audit messages that span multiple lines are not parsed correctly.
+ This will be addressed in a future revision of SETools.
+
+LIBPOLDIFF-SWIG-JAVA
+
+1. There is currently an issue with SWIG Java bindings that prevents
+ disowning an object, and there is an issue in libsepol that prevents the
+ duplication of a policy. Pending the availability of one of these features,
+ it will not be possible to safely use libpoldiff in Java. Future revisions
+ to the policy representation are expected to permit the duplication of
+ policies.
+
+TESTING INFORMATION
+
+Operating Systems:
+ Fedora Core 5 through 9, for both i386 and x86_64 architectures
+
+SELinux monolithic policy versions:
+ 12, 15 through 18
+ 19 through 23 (both with and without MLS support)
+
+SELinux modular policy versions:
+ 5 through 8
+
+Please report any new bugs or comments to setools-bugs@tresys.com.
+Thank you for using SETools!
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..5dc1b5d
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,116 @@
+ACLOCAL_AMFLAGS = -I m4
+AUTOMAKE_OPTIONS = dist-bzip2
+
+if BUILD_APOL
+ MAYBE_APOL = apol
+endif
+
+if BUILD_GUI
+ MAYBE_GUI = seaudit
+endif
+# sediffx is also built conditionally, from sediffx/Makefile.am
+
+SUBDIRS = libqpol libapol libsefs libpoldiff libseaudit secmds sechecker sediff man packages debian $(MAYBE_APOL) $(MAYBE_GUI)
+
+#old indent opts
+#INDENT_OPTS = -npro -nbad -bap -sob -ss -l132 -di1 -nbc -br -nbbb -c40 -cd40 -ncdb -ce -cli0 -cp40 -ncs -d0 -nfc1 -nfca -i8 -ts8 -ci8 -lp -ip0 -npcs -npsl -sc
+C_INDENT_OPTS = -npro -nbad -bap -nbbb -nbbo -nbc -br -bli0 -bls -c40 -cbi0 -cd40 -cdw -ce -ci8 -cli0 -cp40 -ncs -d0 -nbfda -di1 -nfc1 -nfca -i8 -ip0 -l132 -lp -nlps -npcs -pi0 -nprs -npsl -saf -sai -sbi0 -sob -ss -ts8 -ut
+CXX_INDENT_OPTS = -npro -nbad -bap -nbbb -nbbo -nbc -bl -bli0 -bls -c40 -cbi0 -cd40 -cdw -nce -ci8 -cli0 -cp40 -ncs -d0 -nbfda -di1 -nfc1 -nfca -i8 -ip0 -l132 -lp -nlps -npcs -pi0 -nprs -npsl -saf -sai -sbi0 -sob -ss -ts8 -ut
+
+EXTRA_DIST = VERSION KNOWN-BUGS COPYING.LGPL COPYING.GPL
+
+libqpol:
+ $(MAKE) -C $(top_srcdir)/libqpol
+
+libapol:
+ $(MAKE) -C $(top_srcdir)/libapol
+
+libpoldiff:
+ $(MAKE) -C $(top_srcdir)/libpoldiff
+
+libpolsearch:
+ $(MAKE) -C $(top_srcdir)/libpolsearch
+
+libsefs:
+ $(MAKE) -C $(top_srcdir)/libsefs
+
+libseaudit:
+ $(MAKE) -C $(top_srcdir)/libseaudit
+
+apol: libqpol libapol libsefs packages
+ $(MAKE) -C $(top_srcdir)/apol
+
+secmds: libqpol libapol libsefs
+ $(MAKE) -C $(top_srcdir)/secmds
+
+seaudit: libqpol libapol libseaudit
+ $(MAKE) -C $(top_srcdir)/seaudit
+
+sediff: libqpol libapol libpoldiff
+ $(MAKE) -C $(top_srcdir)/sediff sediff
+
+sediffx: libqpol libapol libpoldiff
+ $(MAKE) -C $(top_srcdir)/sediff sediffx
+
+sechecker: libqpol libapol libsefs
+ $(MAKE) -C $(top_srcdir)/sechecker
+
+help:
+ @echo "Make targets for SETools:"
+ @echo " all: build everything, but do not install"
+ @echo " install: install everything"
+ @echo " uninstall: remove SETools from your system"
+ @echo ""
+ @echo " apol: build policy analysis tool"
+ @echo " secmds: build command line tools"
+ @echo " seaudit: build audit log analysis tools"
+ @echo " sediff: build semantic policy diff command line tool"
+ @echo " sediffx: build semantic policy diff graphical tool"
+ @echo " sechecker: build policy checking tool"
+ @echo ""
+ @echo " install-logwatch: install LogWatch config files for seaudit-report"
+ @echo " (requires LogWatch and root privileges)"
+ @echo ""
+ @echo " clean: clean up interim files"
+ @echo " distclean: clean everything not in original distribution"
+
+install-logwatch:
+ $(MAKE) -C $(top_srcdir)/seaudit install-logwatch
+
+.PHONY: libqpol libapol libpoldiff libsefs libseaudit \
+ apol secmds seaudit sediff sediffx sechecker \
+ install-logwatch help \
+ seinfo sesearch indexcon findcon replcon searchcon \
+ packages
+
+seinfo: libqpol libapol
+ $(MAKE) -C $(top_srcdir)/secmds seinfo
+
+sesearch: libqpol libapol
+ $(MAKE) -C $(top_srcdir)/secmds sesearch
+
+indexcon: libqpol libapol libsefs
+ $(MAKE) -C $(top_srcdir)/secmds indexcon
+
+findcon: libqpol libapol libsefs
+ $(MAKE) -C $(top_srcdir)/secmds findcon
+
+replcon: libqpol libapol libsefs
+ $(MAKE) -C $(top_srcdir)/secmds replcon
+
+searchcon: libqpol libapol libsefs
+ $(MAKE) -C $(top_srcdir)/secmds searchcon
+
+packages:
+ $(MAKE) -C $(top_srcdir)/packages
+
+distclean-local:
+ -rm -r config.tcl
+
+indent:
+ find $(top_srcdir) \( -wholename '*/packages/*' -prune \) , \
+ \( -name '*.[ch]' -type f -exec indent $(C_INDENT_OPTS) '{}' \; \)
+ find $(top_srcdir) -regex '.*\.\(cc\|hh\)' -type f -exec indent $(CXX_INDENT_OPTS) '{}' \;
+ find $(top_srcdir) -regex '.*\.\(cc\|hh\)' -type f -exec sed -i 's/\*>>/* > >/g' '{}' \;
+ find $(top_srcdir) -name '*.cc' -type f -exec sed -i 's/const \?const/const/g' '{}' \;
+ find $(top_srcdir) -name '*.hh' -type f -exec sed -i 's/virtual ~ /virtual ~/g' '{}' \;
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..4f68561
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,1018 @@
+SETools 3.3.6:
+
+This release builds upon SETools 3.3.5:
+
+ * Update attribute handling to use attributes in version 24 policy.
+
+ * Fix bug where dontaudit rules were loaded when the "no rules" option is
+ enabled.
+
+seaudit:
+
+ * Add MLS fields to source and target contexts.
+
+ * Double clicking a message line will display the orignal log message.
+
+seinfo:
+
+ * Qdd query for permissive types.
+
+ * Add query for policy capabilities.
+
+==================================================
+
+SETools 3.3.5:
+
+This release builds upon SETools 3.3.4:
+
+ * Update to policy loader to match checkpolicy 2.0.16 and libsepol
+ 2.0.32.
+
+ * Changes to libqpol to allow compiling against libsepol >= 2.0.29.
+
+ * Support for reading policy version 23.
+
+==================================================
+
+SETools 3.3.4:
+
+This release builds upon SETools 3.3.3:
+
+ * Update to policy loader to match checkpolicy 2.0.13 and libsepol
+ 2.0.23.
+
+ * Fixes to apol for proper handling of Tk 8.5.
+
+ * Fixes to libapol, libqpol, and sechecker to build using GCC 4.3.
+
+==================================================
+
+SETools 3.3.3:
+
+This release builds upon SETools 3.3.2:
+
+ * Changes to libqpol to allow compiling against libsepol >= 2.0.20.
+
+ * Support for reading policy version 22.
+
+ * Clarification to default policy loading for seinfo, sesearch, and
+ sechecker.
+
+ * Build scripts for Debian and Ubuntu.
+
+==================================================
+
+SETools 3.3.2:
+
+This release corrects a number of issues present in SETools 3.3.1:
+
+ * Fix to libqpol for policies lacking genfscon statements; for
+ policies containing disabled aliases; for
+ qpol_type_get_alias_iter() given certain policies; for the special
+ role object_r.
+
+ * Fix to libapol when running a default avrule query on policies
+ that have not had their neverallow rules loaded.
+
+ * Fix to libsefs and apol for invalid regular expressions.
+
+ * Fix to apol when validating empty levels.
+
+ * Fix to all SWIG generated wrappers for Java.
+
+==================================================
+
+SETools 3.3.1:
+
+This release corrects a number of issues present in SETools 3.3:
+
+ * Fix to configure when Tcl is not found on build system; fix when
+ compiling with --disable-gui option.
+
+ * Fix to uninstall targets of Java wrappers.
+
+ * Fix to libapol where transitive flows could return results that
+ were supposed to be excluded; fixed memory leaks in infoflow graph
+ generation.
+
+ * Fix to libsefs when running MLS query on non-MLS fclists.
+
+ * Fix to apol when reading older .apol files; fix copy and select
+ all on certain tabs; fix to filter by attribute on some advanced
+ dialogs.
+
+==================================================
+
+SETools 3.3:
+
+SETools:
+
+ * SETools now has an external dependency upon libsqlite3 >= 3.2. The
+ supplied configure script will enforce this dependency.
+
+ * pkg-config scripts are installed with the SETools libraries.
+
+libsefs:
+
+ * Rewrite of library to have proper namespaces and much more usable
+ object-oriented design.
+
+ * SWIG wrappers generated for this library if the appropriate
+ configure flags are set.
+
+findcon, searchcon:
+
+ * Merge searchcon's functionality into findcon. The searchcon tool
+ has been removed from SETools.
+
+indexcon, replcon:
+
+ * Updated to use new libsefs design.
+
+apol:
+
+ * Updated to use new libsefs design.
+
+ * Modified to use the SWIG Tcl interface rather than a custom C
+ library. apol is now a combination of a Tcl script (simply called
+ 'apol') and associated packages that are required at runtime.
+
+ * Neverallow rules are only loaded and expanded when the user
+ performs a search for them. This will dramatically speed up
+ initial policy load time.
+
+awish:
+
+ * awish is no longer needed and thus has been removed from SETools.
+
+sediff, sediffx:
+
+ * Instead of differentiating "AV rules" or "TE rules", user now
+ specifies which particular rule to compare (allow, dontaudit,
+ type_transition, etc.).
+
+ * Neverallow rules are only loaded and expanded when the user
+ performs a diff upon them. This will dramatically speed up
+ initial policy load time.
+
+==================================================
+
+SETools 3.2:
+
+libapol, libqpol, libesaudit, libpoldiff:
+
+ * If --enable-swig-python is given during configure time, the build
+ system will create Python SWIG wrappers for these libraries.
+
+ * If --enable-swig-java is given during configure time, the build
+ system will create Java SWIG wrappers for these libraries.
+
+libpoldiff:
+
+ * Provides ability to diff levels, categories, and range_transition
+ statements. Provides ability to diff modifications to a user's
+ default level and permitted MLS range, assuming the policies are MLS.
+
+apol, seaudit, sediffx:
+
+ * Introduces 'policy list', a small text file that contains
+ references to a base policy and any number of modules. After
+ selecting the base policy and modules in a tool's open policy
+ dialog, click on 'Export' to write a policy list to disk. That
+ policy list then may be imported into the same tool or any other
+ graphical SETools application. This file also may be specified
+ on the command line for all tools that load a policy.
+
+sesearch, apol:
+
+ * Provides full support for version 21 policy (i.e., object classes for
+ range_transition statements).
+
+sediff:
+
+ * Shows MLS diffs.
+
+sediffx:
+
+ * Shows MLS diffs.
+
+ * Provides option to show line numbers that contributed just to a
+ specific AV rule's permission by clicking that AV rule's permissions.
+ This is in addition to existing sediffx behavior that showed all lines
+ associated with a particular rule difference.
+
+ * Provides support for type joins and splits within the type remap dialog.
+
+==================================================
+
+SETools 3.1:
+
+SETools:
+
+ * All tools that open a policy now support loadable policy modules.
+ Command line tools expect the first module to be a base module
+ followed optionally by any other modules. Graphical tools have
+ a new open policy dialog to select a base module and any number of
+ additional modules.
+
+ * Release of RPM packages that are compatible with Fedora Core 5 and
+ 6. The spec and support files are in packages/rpm.
+
+libapol:
+
+ * New class apol_policy_path_t to represent a base policy and any
+ number of modules. Use this whenever referring to the file or
+ files constituting a policy.
+
+libqpol:
+
+ * Policy features such as attribute names or MLS can now be queried
+ individally via qpol_policy_has_capability() rather than inferred
+ by policy type and version.
+
+ * New class qpol_module_t to represent a particular policy module
+ prior to it being linked into a base policy (qpol_policy_t).
+
+libseaudit:
+
+ * Rewrite of library to have proper namespaces. libseaudit is now
+ fully documented and suitable for third-party users.
+
+seaudit:
+
+ * Rewrite to use new libseaudit.
+
+ * Numerous tweaks to the interface to be more user friendly.
+
+seaudit-report:
+
+ * Rewrite to use new libseaudit.
+
+sediffx:
+
+ * Numerous tweaks to the interface to be more user friendly.
+
+==================================================
+
+SETools 3.0.1
+
+SETools:
+
+ * All code has been indented uniformly via the 'make indent' target.
+
+SETools libraries:
+
+ * All libraries now have a get_version() function.
+
+libqpol:
+
+ * Syntactic rule table is now off by default; it requires an
+ explicit call to qpol_policy_build_syn_rule_table() to create it.
+
+libapol:
+
+ * apol_policy_t is now an opaque structure. apol_permmap_t is no
+ longer a public declaration.
+
+ * avrule and terule queries now have full "syntactic" searching
+ features.
+
+apol & sesearch:
+
+ * If loaded policy is source, the new syntactic search algorithm is used.
+
+==================================================
+
+SETools 3.0
+
+SETools:
+
+ * Moved entire project to autoconf build system. This will detect
+ dependencies correctly and make it easier to integrate with Linux
+ distributions and their packaging systems.
+
+SETools libraries:
+
+ * Rewrite of back-end of SETools to use libsepol data structures.
+ Most things should run notably faster.
+
+ * All exported library functions have a standardized naming
+ convention and are fully documented. This will prove helpful for
+ third-party developers integrating SETools into their own
+ projects.
+
+ * For policies version 15 or greater, domain transition analysis now
+ takes into consideration setexec permission and/or type_transition
+ rules.
+
+apol:
+
+ * Rework Tk interface to fit on 1024x768 displays.
+
+ * Indirect matching of attributes now works with rule searches.
+
+sediff:
+
+ * New diffing algorithm yields significant speed improvements.
+
+ * Can now diff neverallow and role_transition statements.
+
+ * Streamlined results display - should be easier to read.
+
+sechecker:
+
+ * Updated module format and template for ease of extension.
+
+
+=======================================================
+May 1, 2006, Version 2.4
+
+apol:
+ File contexts tab now allows for MLS range searching if
+ the loaded database is from a MLS filesystem.
+ Policy statistics dialog now shows MLS and ocontexts
+ summaries.
+
+libapol:
+ Added support for loading base policies containing optionals.
+ Added support for searching range transitions containing
+ attributes.
+
+libseaudit:
+ Bugfix to support parsing FC5-style audit logs.
+
+seaudit:
+ Added date filters.
+
+secmds:
+ Added support to indexcon and searchcon for MLS filesytems.
+ Added support to findcon and replcon for MLS filesystems.
+
+sechecker:
+ Added incomplete network access (inc_net_access) module.
+ Added unreachable domains (unreachable_doms) module.
+ Added impossible range transitions (imp_range_trans) module.
+
+sesearch:
+ Allow user to search range transitions by attributes and
+ indirect matching.
+ Added RBAC searching.
+
+
+=======================================================
+January 23, 2006, Version 2.3
+
+apol:
+ added new MLS components tab for sensitivities,
+ levels, and categories.
+ changed users tab to support ranges and default
+ levels.
+ added range transition tab for searching range
+ transition rules.
+ added new tab for network context components.
+ added new tab for file system context components.
+libapol:
+ added binpol support for MLS, network contexts,
+ and file system contexts.
+seinfo:
+ added command line options for MLS components.
+ added command line options for network contexts
+ and file system contexts.
+sesearch:
+ added command line option for searching for rules
+ by conditional boolean name.
+seaudit:
+ added new column in the log view for the 'comm'
+ field found in auditd log files.
+ added filters for the 'comm' field and 'message'
+ field.
+manpages:
+ added manpages for all tools.
+
+=======================================================
+October 31, 2005, Version 2.2
+
+libapol:
+ replaced the original dta algorithm with a new one
+ to properly support complements in rules. added
+ new structures to support the separation of diff
+ elements. added support for parsing additional
+ policy components in source policies.
+sediff:
+ enhanced the GUI for display and separation of diff
+ elements. added the ability to rename types.
+sechecker:
+ added a new tool - a commandline modular and
+ extensible policy checker program
+seuser:
+ removed - deprecated
+sepcut:
+ removed - deprecated
+
+=======================================================
+October 12, 2005 Version 2.1.3
+
+libapol:
+ fixed a mls bug in the source parser.
+
+=======================================================
+August 24, 2005 Version 2.1.2
+
+apol:
+ created new permission maps for policy versions
+ 19 and 20. also some minor changes to support
+ version 20 binary format.
+libseaudit:
+ updated the parser to properly parse avc
+ messages from auditd logfiles
+libapol:
+ updated the binary policy parser to handle the
+ new version 20 avtab format. The parser
+ preserves attributes in av rules by generating
+ fake attribute names.
+
+=======================================================
+May 17, 2005, Version 2.1.1
+
+libseaudit:
+ updated code to compile with gcc-4.0.0
+ minor bug fixes
+
+sediff:
+ updated code to compile with gcc-4.0.0
+
+seaudit:
+ updated code to compile with gcc-4.0.0
+
+libsefs:
+ updated code to compile with gcc-4.0.0
+
+libapol:
+ updated code to compile with gcc-4.0.0
+ minor bug fixes
+
+seuser:
+ updated code to compile with gcc-4.0.0
+
+======================================================
+April 18, 2005, Version 2.1.0
+
+apol:
+ improved direct relabel analysis algorithm
+
+libapol:
+ added policy version 19 support
+
+sediff:
+ added role transitions, improved role allow
+ added conditional expression differences
+
+=======================================================
+February 16, 2005, Version 2.0
+
+setools:
+
+libsefs:
+ Converted to use an on-disk SQLite database backend and
+ re-designed API to provide the functionality to other
+ applications, such as apol.
+libapol:
+ Added support for analyzing direct file relabels.
+ Added support for analyzing relationship between two types.
+ Integrated use of hashtable structures for easily analyzing
+ differences between policies.
+ Minor bug fixes.
+
+libseuser:
+ Minor bug fixes.
+
+apol:
+ New analysis module for performing direct file relabel
+ analysis.
+ New analysis module for analyzing the relationship be-
+ tween two types.
+ New interface added for viewing file contexts from an
+ SELinux filesystem.
+ Improvements to domain transition analysis interface.
+ Minor bug fixes and GUI tweaks.
+
+secmds:
+ Updated indexcon/searchcon to use an on-disk SQLite database
+ in order to decrease memory use. These changes are not
+ backwards-compatible.
+
+seaudit:
+ Integrated reporting functionality into GUI.
+ Minor GUI tweaks.
+
+sediff:
+ New gtk GUI and command-line tools for analyzing the semantic
+ differences between two policies. The semantic difference
+ of a policy is different from the syntactic difference in
+ that it shows the cumulative effect of rules rather than
+ doing a line-by-line comparison.
+=======================================================
+November 4, 2004, Version 1.5.1
+
+apol:
+ Fixed compatibility with tcl 8.3.
+
+libsefs:
+ Fixed compile problem on PPC.
+
+secmds:
+ Fixed fatal error in replcon.
+
+setools:
+ Reverted to static linking and fixed various small bugs.
+
+========================================================
+October 27, 2004, Version 1.5
+
+apol:
+ Advanced options added to forward domain
+ transition analysis module for performing
+ more granular searching of transitions to
+ domains using specified classes, permissions
+ and target types.
+ Minor bug fixes and improvements.
+
+libapol:
+ Fixed to handle new libapol user structs.
+ Enhanced forward domain transition analysis to
+ perform more granular searching using specified
+ classes, permissions and target types.
+ Minor bug fixes.
+
+libseuser:
+ General clean up of the policy components.
+ Fixed handling of users to be consistent with rest.
+
+seaudit:
+ New tool (seaudit-report) for generating customized
+ reports on SE Linux audit messages using saved
+ seaudit view files. This tool is highly configurable
+ and can effectively integrate with the LogWatch
+ application for automating SE Linux audit log reporting.
+ Added feature for exporting audit messages to a
+ file, as well as viewing all components of an audit
+ message within a text view.
+
+libseaudit:
+ Updated library to store audit header information, such as
+ the system call timestamp and serial number.
+ Fixed parse errors for new logs.
+
+secmds:
+ New tool (indexcon) for creating a snapshot of security
+ contexts for SE Linux filesystem entities.
+ New tool (searchcon) for searching the SE Linux filesystem
+ database that was created using indexcon.
+
+=======================================================
+July 7, 2004, Version 1.4.1
+
+setools:
+ Added the install target install-dev to install the
+ setools headers and libraries for third party
+ developers (libapol, libseuser, libseaudit).
+
+libapol:
+ Added support for parsing policy version 18 (source
+ and binary).
+ Added a permission map for version 18 policies.
+
+libseaudit:
+ Fix timezone related bug that resulted in incorrect
+ dates displayed in seaudit.
+
+=======================================================
+June 2, 2004, Version 1.4
+
+setools:
+ Made policy installation and file labeling a separate
+ makefile target to better support non-default policies
+ like the 'targeted' policy included in Fedora Core 2.
+apol:
+ Added support for the user to change the name of
+ result tabs.
+ Added new Tool Options dialog for opening limited
+ portions of the selinux policy.
+ GUI changes to correctly support binary policies.
+ Enhanced display of conditional rules in TE rule
+ search results.
+libapol:
+ Added support for loading binary policy files (in
+ addition to source policy files).
+ Added utility functions for finding default policies
+ - both source and binary.
+ Various cleanups and bug fixes to source policy parsing.
+secmds:
+ Added conditional policy support to seinfo.
+ Changed to use libapol default policy logic.
+seaudit:
+ Changed to use libapol default policy logic.
+ Gui changes to correctly support binary policies.
+libseuser:
+ Changed to use libapol default policy logic.
+
+=======================================================
+May 5, 2004 Version 1.3.1
+
+apol:
+ Fixed to properly exclude object classes and/or
+ permissions in information flow analysis.
+libapol:
+ Fixed to properly exclude object classes and/or
+ permissions in information flow analysis.
+seuser:
+ Changed default policy.conf location in seuser.conf
+ to /etc/security/selinux/src/policy/policy.conf
+ Minor bug fixes.
+sepcut:
+ Minor bug fixes.
+libseuser:
+ Minor fixes to parsing of the seuser.conf file.
+
+=======================================================
+April 15, 2004 Version 1.3
+
+apol:
+ Added conditional policy support.
+ Added permission weighting for information flows.
+libapol:
+ Added full support for conditional policies.
+ Included support for policy version 17
+ Various fixes and updates
+seaudit:
+ Added support for audit messages from changing
+ booleans in a conditional policy.
+ Added multiple filters/views.
+libseaudit:
+ Updated to support new audit framework in the 2.6.5
+ kernel.
+seuser:
+ Added home directory labeling command as command
+ line option.
+libseuser:
+ Updated to support home directory labeling.
+secmds:
+ Added new context swap tool (replcon).
+ Added new context search tool (findcon).
+
+
+========================================================
+February 6, 2004 Version 1.2.1
+
+Libapol:
+ Fixed parse error when using attributes in role
+ declarations.
+
+========================================================
+February 4, 2004 Version 1.2
+
+Apol:
+ Added saving and loading queries from the TE rules tab.
+ Added a tab for referencing initial SIDs in the policy.
+ Fixed some memory usage problems in information flow.
+ Combined Forward and Reverse domain transitions into one
+ analysis module.
+
+Seuser:
+ Some minor changes to command line parsing for better use on
+ non selinux machines.
+
+Seaudit:
+ Added real-time log monitoring capability.
+ Added support for hostname recognition in logs.
+ Added ability to select from values that appear in the
+ policy or the log, for filtering. An open policy is no
+ longer needed to filter a log.
+
+
+Libapol:
+ Added support for new policy language features ('-' in
+ lists of types and typealias).
+ Enabled conditional policy (v16) support by default.
+ Added support for parsing and storing initial SIDs.
+
+========================================================
+December 30, 2003 Version 1.1.1
+
+libapol:
+ fixed memory leakage on information flow analysis
+
+seaudit:
+ fixed to properly compile with ISO C90 standards.
+
+libseaudit:
+ fixed to properly compile with ISO C90 standards.
+
+seuser:
+ fixed build process to properly build with no GUI.
+ fixed help for 'seuser -X'
+ removed default_context and cron_context in seuser.conf
+
+secmds:
+ fixed seinfo to display version information
+
+
+========================================================
+December 18, 2003 Version 1.1
+
+Apol:
+ Significantly improved transitive information flow analysis
+ by allowing for greater control over the types,
+ object classes, and permissions to use in an analysis;
+ as well as the ability to search for multiple paths
+ bounded by number of founds paths and time.
+ Additional work to complete a fully functional
+ transitive flow analysis is planned.
+ Updated to work with restructured libraries
+ Added support for saving and loading analysis queries
+ Additional work to make the fonts and window sizes work better
+
+Seuser:
+ Updated to work with restructured libraries.
+ Created separate seuser (no X) and seuserx (X) commands
+
+Secmds: NEW
+ Added new command line tools:
+ seinfo: displays information--including expanded
+ information--about the components of a
+ policy (classes, types, attributes, users,
+ roles), as well as policy stats
+ sesearch: searches and displays type enforcement
+ rules based on criteria such as source
+ and target type, object class, permissions,
+ and rule type
+
+seaudit: NEW
+ Added a new GUI-based audit log analysis tool. The tool allows
+ one to view and search SE Linux messages from a log file
+ and to analyze the policy for rules that relate to
+ a given audit message. This is a first generation tool,
+ and real-time monitoring of the audit messages is planned.
+
+libseaudit: NEW
+ Includes library to parse and store SE Linux audit messages.
+
+Libapol:
+ Added latent support to parse future conditional policy syntax
+ Restructured library to separate core functions from
+ TCL/TK/X support functions (to allow non-X commands).
+ There are now libapol and libapol-tcl libraries.
+ Removed "dead" code and various bug fixes and clean up
+ Improved transitive information flow analysis.
+
+Libseuser:
+ Restructured library to separate core functions from TCL/TK/X
+ support functions (to allow non-X commands). There are
+ now libseuser and libseuser-tcl libraries.
+
+
+========================================================
+October 30, 2003 SE Linux Tools, version 1.0.1
+
+Apol:
+ Update to default font configuration
+
+Sepcut:
+ Update to default font configuration
+
+Seuser:
+ Updated seuser .te file
+ Update seuser Makefile to use -Z option when installing seuser
+ Update to default font configuration
+
+Libapol:
+ Minor fix to support Tcl 8.4 interface
+
+========================================================
+September 22, 2003 SE Linux Tools, version 1.0
+
+Added BWidgets source under packages.
+Added support for rpm packages.
+
+Apol:
+ Added reverse domain transition analysis.
+ Added direct information flow analysis.
+ Added an experimental transitive information flow
+ analysis.
+ Added permap loading/editing/saving support (required by
+ information flow analyses).
+ Fixed various bugs.
+
+Sepcut:
+ Added 'Relabel Files' button in the test policy tab.
+ Fixed various bugs.
+
+Seuser:
+ Fixed forward and backward compatibility in the use of system
+ user administration utilities (i.e., old versions of
+ SELinux use suseradd, new versions use useradd).
+ Changed shell scripts to fix compatibility.
+
+Libapol:
+ Fixed type alias support.
+ Added support for policy version 15.
+ Added direct information flow analysis capabilities.
+ Added partial transitive information flow analysis
+ capabilities.
+ Added reverse domain transition analysis capabilities.
+ Added permap support.
+ Fixed various bugs.
+
+
+
+========================================================
+June 9, 2003 SE Linux Tools, Release 20030609
+
+Apol:
+ Simplified the user interface by consolidating tabs.
+ Various bug fixes and clean up
+
+Sepcut:
+ Added feature to track recently opened policy dirs
+ Added feature to allow one to save policy module configurations
+ so that one policy directory may be use for multiple
+ configurations.
+ Added feature to allow individual user ability to control
+ tool global settings
+ Enhanced tools ability to stay in sync with on disk view
+ Various minor fixes and code clean up
+
+Seuser:
+ Various bug fixes and general clean up
+
+Libapol:
+ Fixed various bugs.
+
+
+========================================================
+April 10, 2003 SE Linux Tools, Version 0.8
+
+Apol:
+ Added Analysis tab for new domain transition analysis capability.
+ Changed compile process to install just a single, compressed .tcl file
+ Fixed problems with fonts.
+
+Sepcut:
+ Added support for older policy directories (customize
+ tab will disable if domains/program doesn't exist)
+ Minor fixes
+
+Seuser:
+ Significantly changed command line options. Added rename, show, and load
+ commands. Added -X, -f, and -R flags. Made loading policy the
+ default and replaced -L with -N flag. Removed -g and -r flags.
+ Added seuseradd, seuserdel, and seusermod scripts as shell wrappers for
+ the s* equivalent wrappers that also call seuser as necessary
+ to provide single command-line interface to manage users
+ Completely replaced the graphical user interface (GUI) that supports
+ a single interface to manage both system and selinux
+ user issues
+ Removed support for old-style default context management.
+
+Libapol:
+ Added extensions to support new domain transition analysis
+ Fix various problems with handling '*' in TE rules
+ Remove the OBJ_CLASSES_PERMS compile flag and the associated
+ old dead code.
+ Added command to get types for a given attribute as a list
+ Began restructuring the rule rendering code.
+ Fixed some memory leaks
+ Various bug fixes, clean up, and restructuring
+
+Libseuser:
+ Added commands to get system groups
+ Modified command that returns system users to also identify
+ user type.
+ Added several new command support wrap functions to support new command
+ line interface.
+ Various bug fixes.
+
+
+
+========================================================
+February 27, 2003 SE Linux Tools, Version 0.7
+
+Enhanced SepCut:
+ Added text search feature
+ Added ability to include a policy directory path on command line
+ Added ability to view all unsaved, modified files in various
+ dialogs
+ Fixed various bugs
+
+Apol updates:
+ Added a policy.conf tab with search ability
+ Added hyperlinks between TE rules and policy conf allowing one to
+ look up where in policy.conf where a given rule came from
+ Added basic ability to recognize roles declared via dominance statement
+ (semantics of statement still to be done)
+ Fixed various bugs
+
+Libapol:
+ Updated to support apol hyperlinking.
+ Minor bugs
+
+Seuser:
+ Updated seuser .te file to fix policy dependencies
+
+
+========================================================
+January 09, 2002 SE Linux Tools, Version 0.6.1
+
+Updated install process to allow setools to be installed during
+ initial selinux system install
+
+Fixed various problems with seuser's policy .te and .fc files
+ (Wayne Salamon, wsalamon@tislabs.com)
+
+Fixed way sepcut handle temporary files to accommodate policy
+ fixes
+
+
+
+=========================================================
+
+December 18, 2002 SE Linux Tools, Version 0.6
+
+
+Created SePCuT: SE Linux Policy Customization Tool
+ a first generation GUI policy customization/editing/testing tool
+
+
+Update libapol:
+ Added regular expression searches to types/attribs, TE rules, objects
+ Cleaned up the policy version hints support
+ Tested with MLS enabled and added a compile option
+
+
+Updated apol:
+ Changes to accommodate regex searches
+ Made displays read only
+ Various minor GUI improvements and bug fixes
+
+Updated libseuser:
+ Added checks and support for new login context style (support both
+ old and new style)
+ Added buffer overflow checks
+
+Updates seuser:
+ Supports old and new login context styles
+ Better error checking for command line interface
+
+
+
+===============================================================
+
+September 21, 2002 SE Linux Tools, Version 0.5
+
+
+Updated libapol:
+ Added object classes and permissions to lib
+ Added avl-tree based sorting (~40% improvement in load time)
+ various minor bugs
+
+Updated apol:
+ Added object classes and permissions tab
+ Added object classes and permissions as TE rule search options
+ Added multiple results tabs for type enforcement rule searches
+ Added a recent files menu to the File menu
+ Various minor fixes
+
+Updated libseuser:
+ Added non-TCL/TK wrappers for C programs (to support command line seuser)
+
+Updated seuser:
+ Added command line version and options
+
+Misc:
+ General clean up
+ Improved string buffer overflow validation
+
+=================================================================
+
+
+August 1, 2002 SELinux Tools, Version 0.4.2
+
+Updated libapol:
+ Updated policy parsing to work with July 2002 policy syntax changes
+ Added backward compatibility with older policies
+ Added policy version checking
+ Replaced notify with dontaudit
+ Added new generalized filesystem syntax
+ Added latent structures for object classes and permissions
+
+Updated apol:
+ Updated GUI to reflect libapol changes
+ Added dontaudit rule selector
+ Made several font fixes
+ Added policy version indicators
+ Various minor GUI fixes
+
+Updated seuser:
+ Added a policy for seuser tool itself
+ Various GUI updates and bug fixes
+ Compatibility updates
diff --git a/README b/README
new file mode 100644
index 0000000..04b159b
--- /dev/null
+++ b/README
@@ -0,0 +1,456 @@
+SETools - Policy analysis tools for SELinux (C) 2001-2010
+Tresys Technology
+setools@tresys.com, http://oss.tresys.com/projects/setools
+
+
+TABLE OF CONTENTS
+-----------------
+
+1. Overview
+2. Installation
+ 2.1. compiling from official distribution
+ 2.2. compiling from SVN checkout
+ 2.3. configure flags
+ 2.4. using development version of SELinux
+ 2.5. Logwatch support
+ 2.6. doxygen support
+3. Features
+ 3.1. graphical tools
+ 3.2. command-line tools
+ 3.3. analysis libraries
+4. Obtaining SETools
+5. Reporting bugs
+6. Copyright license
+
+
+1. Overview
+-----------
+
+This file describes SETools, developed by Tresys Technology. SETools
+is a collection of graphical tools, command-line tools, and libraries
+designed to facilitate SELinux policy analysis. Although SETools is
+primarily targeted for Red Hat-based systems, it should also work for
+Gentoo and Debian distributions. See the file KNOWN-BUGS for testing
+information.
+
+SETools includes the following graphical tools, command-line tools,
+and libraries:
+
+ apol policy analysis tool
+ libapol policy analysis library
+ libpoldiff semantic policy difference library
+ libqpol library that abstracts policy internals
+ libseaudit parse and filter SELinux audit messages in log files
+ libsefs open and search SELinux file contexts
+ seaudit audit log analysis tools: seaudit and seaudit-report
+ sechecker SELinux policy checking tool
+ secmds command line tools: seinfo, sesearch, findcon,
+ replcon, and indexcon
+ sediff semantic policy difference tools: sediff and sediffx
+
+Each of these components is in a subdirectory under the top-level
+source directory, along with supporting pieces in the following
+directories:
+
+ man manual pages for SETools commands
+ packages miscellaneous support for external packages
+
+In addition the top-level source directory contains various pieces of
+documentation. Please consult the file KNOWN-BUGS in this directory
+prior to filing any bug reports.
+
+
+2. Installation
+---------------
+
+SETools uses the GNU build system to configure, compile, and install.
+As such it contains a configure script that will verify its
+dependencies. SETools requires the following development packages for
+compilation:
+ flex
+ bison
+ pkg-config 0.23 or greater
+ libselinux 2.0.87 or greater
+ libsepol 2.0.38 or greater
+ libsepol-static 2.0.38 or greater
+ libxml2
+ sqlite 3.6.20 or greater
+
+These packages are needed to build SETools's graphical tools:
+ swig 1.3.28 or greater
+ bwidget 1.8 or later
+ tcl-devel 8.4.9 or greater
+ tk-devel 8.4.9 or greater
+ glib2-devel
+ gtk2-devel 2.8 or greater
+ libglade2-devel
+
+To build additional SETools SWIG wrappers, these packages are
+required:
+ Java JDK 1.2 or greater
+ python-devel 2.3 or greater
+
+Apol requires BWidget 1.7 or greater to run. The BWidget toolkit is
+part of the tcllib package and is often not present in Linux
+distributions; the toolkit may be freely downloaded at
+http://tcllib.sourceforge.net. The supplied configure script attempts
+to detect the version of BWidget installed. If it is not found then
+SETools will use the prepackaged one found within the 'packages'
+subdirectory. In some situations the toolkit will not be
+automatically found; if you are sure that BWidget is present then
+specify --disable-bwidget-check to the configure script.
+
+
+2.1. compiling from official distribution
+-----------------------------------------
+
+The official, stable source distribution is available from
+http://oss.tresys.com/projects/setools/. Untar and uncompress the
+distribution, and perform the following.
+
+ $ cd setools-3.3.7
+ $ ./configure
+ $ make
+ $ make install
+
+This will put the binaries in /usr/local/bin, data files in
+/usr/local/share/setool-3.3, and libraries in /usr/local/lib.
+Assuming that /usr/local/bin is in your $PATH and /usr/local/lib in
+$LD_LIBRARY_PATH everything should now work.
+
+
+2.2. compiling from SVN checkout
+--------------------------------
+
+If you prefer the bleeding edge of SETools development, you could
+instead obtain the development version of SETools from the Subversion
+repository (see Section 4).
+
+ $ cd setools
+ $ autoreconf -i -s
+ $ ./configure
+ $ make
+ $ make install
+
+You will need a recent version of autoconf to create the configure
+script. SETools was written using autoconf-2.60, although
+autoconf-2.59 also seems to work correctly albeit with a build
+warning.
+
+As SETools uses the GNU build system, other make targets are
+available. `make install-strip' will strip unneeded symbols from
+installed binaries. `make uninstall' removes files written by an
+earlier install.
+
+
+2.3. configure flags
+--------------------
+
+You can customize your SETools build using the flags given to
+`configure'. Notable options include:
+
+ --enable-debug
+ All code will be compiled using static libraries and the gcc
+ flags '-g3 -gdwarf-2 -O0'. This flag is useful for tracking
+ down issues.
+
+ --disable-gui
+ Build only the command-line tools: seinfo, sesearch, findcon,
+ indexcon, replcon, sechecker, and sediff.
+
+ --disable-bwidget-check
+ Assume that BWidget 1.8 is installed on the system. The
+ configure script normally tries to launch a Tcl script that
+ loads BWidget, which requires a running X session. You will
+ need this flag if compiling in a non-X environment.
+
+ --disable-selinux-check
+ Disable the build-time check for SELinux. In rare
+ circumstances the build computer will not have SELinux
+ running, resulting in 'configure' producing a warning and
+ disable parts of SETools. By specifying this flag,
+ 'configure' will not disable parts of SETools.
+
+ --enable-swig-java
+ Build SWIG interfaces for Java. This permits third-party
+ developers who prefer Java to use the SETools libraries for
+ their own projects.
+
+ --enable-swig-python
+ Build SWIG interfaces for Python. This permits third-party
+ developers who prefer Python to use the SETools libraries for
+ their own projects.
+
+ --enable-swig-tcl
+ Build SWIG interfaces for Tcl. This is needed for the apol
+ tool. By default this flag is enabled.
+
+ --enable-sepol-src=PATH
+ Look for libsepol source files in PATH. Use this flag when
+ compiling against a development version of SELinux (see
+ Section 2.4). Note that if --enable-sepol-src and
+ --with-sepol-devel are both specified then this flag takes
+ precedence.
+
+ --with-tcl=PATH
+ Look for Tcl development files in PATH. Debian users will
+ need to specify this flag, as Tcl 8.4 is typically located at
+ /usr/lib/tcl8.4.
+
+ --with-tk=PATH
+ Look for Tk development files in PATH. Debian users will need
+ to specify this flag, as Tk 8.4 is typically located at
+ /usr/lib/tk8.4.
+
+ --with-sepol-devel=PATH
+ Look for libsepol header files in PATH/include and library in
+ PATH/lib64 and PATH/lib. Note that if --enable-sepol-src and
+ --with-sepol-devel are both specified then --enable-sepol-src
+ takes precedence.
+
+ --with-selinux-devel=PATH
+ Look for libselinux header files in PATH/include and library
+ in PATH/lib64 and PATH/lib.
+
+ --with-default-policy=PATH
+ Explicitly use PATH as the default SELinux policy source file,
+ instead of inferring its location based upon the return value
+ of selinux_policy_root().
+
+ --with-test-policies=PATH
+ Use the policies in PATH as input to the SETools tests; these
+ tests are invoked upon `make check'.
+
+Of course, `configure' accepts other usual flags such as --prefix.
+
+
+2.4. Using a development version of SELinux
+-----------------------------------------
+
+As SELinux is a rapidly evolving project, you may wish to use a
+version of libsepol.so that is newer than the one installed to
+/usr/lib. To support different versions of libsepol, SETools can be
+configured to compile against a specific version of libsepol using the
+--enable-sepol-src flag. For example, suppose you have a SELinux SVN
+checkout and compilation like the following:
+
+ $ cd /home/gburdell
+ $ svn co https://svn.sourceforge.net/svnroot/selinux/trunk selinux
+ $ cd selinux/libsepol
+ $ make
+
+You can compile SETools against this particular copy of libsepol:
+
+ $ cd /home/gburdell/setools
+ $ ./configure --enable-sepol-src=/home/gburdell/selinux/libsepol
+
+Note that --enable-sepol-src will override the flag
+--with-sepol-devel.
+
+
+2.5. Logwatch support
+---------------------
+
+Integrating SETools with Logwatch can provide an effective IDS
+solution by automating customized audit reports and having them
+emailed to a specific recipient(s) for further analysis. You can
+integrate SETools into Logwatch using the seaudit-report plugin by
+specifying the `make install-logwatch' target. This target installs
+the configuration necessary for having seaudit-report run as a
+Logwatch service. The configuration files are part of the SETools
+source distribution, located in the seaudit subdirectory, and include:
+
+ seaudit-report-group.conf:
+ logfile group configuration file
+
+ seaudit-report-service.conf:
+ service filter config file
+
+ seaudit-report-service:
+ service filter script
+
+Make sure the Logwatch program is installed before proceeding with
+using this install target.
+
+
+2.6. doxygen support
+--------------------
+
+All externally exported library functions include doxygen-style tags
+in the documentation. To produce your own HTML outputs when writing
+third-party tools, use the doxygen configuration file located in
+packages/Doxyfile; it directs generated output to /tmp/setools. From
+the top-level source directory do:
+
+ $ doxygen packages/Doxyfile
+
+
+3. Features
+-----------
+
+SETools encompasses a number of tools, both graphical and command
+line, and libraries. Many of the programs have help files accessible
+during runtime.
+
+
+3.1. graphical tools
+--------------------
+
+The main emphasis of SETools is the graphical analysis tools.
+
+ apol:
+ A Tcl/Tk graphical analysis tool. Use it to open a SELinux
+ policy, examine the policy's components and rules, and perform
+ various types of analyses.
+
+ seaudit:
+ A GTK+ graphical audit log analysis tool for SELinux. This
+ tool allows users to sort and filter the system's audit log,
+ query the policy based on audit messages, and export audit log
+ messages to a file. The tool can also create reports in HTML
+ or plaintext format using an entire audit log or an seaudit
+ view. Note that this program is installed in $(PREFIX)/sbin
+ because its main function is to analyze /var/log/audit/audit.log.
+
+ sediffx:
+ A GTK+ graphical tool to semantically compare two policies.
+ Use sediffx to open two SELinux policies, find differences
+ between them, and then show those results.
+
+
+3.2. command-line tools
+-----------------------
+
+Some tools in the SETools suite may be run in a non-windowing
+environment. The first six tools listed below are located in the
+secmds subdirectory; the rest are in their own directories.
+
+ seinfo:
+ A tool to quickly get a list of components from a SELinux
+ policy.
+
+ sesearch:
+ A tool to search rules (allow, type_transition, etc.) and constraints
+ within a SELinux policy.
+
+ findcon:
+ A tool to search files with a matching SELinux file context.
+ The tool can search a filesystem directly, a file_contexts file,
+ or a database as created by indexcon.
+
+ replcon:
+ A tool to search the filesystem, replacing a matched file's
+ context with a different one.
+
+ indexcon:
+ A tool to create a database that indexes the security contexts
+ of a SELinux filesystem.
+
+ sechecker:
+ A tool for performing modular checks on an SELinux policy.
+ Sechecker supports configuration profiles to specify multiple
+ modules and generates a report of potential issues within a
+ policy.
+
+ seaudit-report:
+ A tool for generating reports on SELinux audit messages in
+ plaintext or HTML format. Reports generated by this tool can
+ be configured to include standard report sections such as
+ policy load messages, enforcement toggles messages, policy
+ boolean messages, etc. A key feature of the tool is that
+ reports can be further customized through the use of saved
+ seaudit view files. The tool can effectively be used as a
+ plugin to other audit log analysis tools, such as the Logwatch
+ daemon.
+
+ sediff:
+ A tool to load two SELinux policies, find differences between
+ them, and then show those results. The tool provides a
+ command-line interface to libpoldiff.
+
+
+3.3. analysis libraries
+-----------------------
+
+The SETools support libraries (libapol, libpoldiff, libqpol,
+libseaudit, and libsefs) are available for use in third-party
+applications. Although they are not officially supported (and thus
+subject to change between SETools releases), we will do our best to
+maintain compatibility beginning with SETools version 3.0.
+
+ libqpol:
+ Abstract the internals of an SELinux policy behind a
+ consistent interface, such that changes to the policy
+ representation (as governed by libsepol) do not affect
+ analysis tools.
+
+ libapol:
+ Work with libqpol to perform higher-order analyses of a
+ policy. A typical sequence for an analysis tool is:
+ open a policy via apol_policy_open()
+ execute some query via apol/policy-query.h
+ obtain detailed results via qpol/policy_query.h
+ close the policy via apol_policy_destroy()
+
+ libseaudit:
+ Parse and store SELinux audit messages. Its chief users are
+ seaudit and seaudit-report.
+
+ libpoldiff:
+ Accept two SELinux policies and finds differences between
+ them. Its main users are sediff and sediffx.
+
+ libsefs:
+ Create a represention of file contexts, by reading contexts
+ directly from a filesystem, from a file_contexts file, or from a
+ specially formatted database. Queries can then be created and
+ executed against those file contexts
+
+These libraries have SWIG wrappers that are built if
+--enable-swig-java, --enable-swig-python, and/or --enable-swig-tcl are
+given during configuration time. The generated Java wrappers will be
+in placed $PREFIX/lib; symlinks to jar files will be in
+$PREFIX/share/java. Python wrappers will be installed to Python's
+site-packages directory. Tcl wrappers are built as Tcl packages
+(e.g., `package require apol') and placed in $PREFIX/lib/setools.
+
+
+4. Obtaining SETools
+--------------------
+
+Official releases of SETools may be freely downloaded from Tresys's
+Open Source Software website, http://oss.tresys.com/projects/setools.
+
+Tresys builds RPM packages of SETools. They may also be obtained from
+the website listed above.
+
+SETools source code is maintained within a Subversion repository.
+From the command line do:
+
+ $ svn co http://oss.tresys.com/repos/setools/trunk/ setools
+
+You may also browse the SVN repository at
+http://oss.tresys.com/projects/setools/browser.
+
+Other binary releases SETools are available for your favorite Linux
+packaging system from third-party sources. Gentoo users have an
+ebuild script for SETools. Debian maintains the dpkg "setools" in
+section admin, priority optional.
+
+
+5. Reporting bugs
+-----------------
+
+If you found a bug, have a suggestion, or otherwise would like to
+comment upon SETools, please email setools-bugs@tresys.com. We will
+respond to you as soon as possible.
+
+
+6. Copyright license
+--------------------
+
+The intent is to allow free use of this source code. All programs'
+source files are copyright protected and freely distributed under the
+GNU General Public License (see COPYING.GPL). All library source
+files are copyright under the GNU Lesser General Public License (see
+COPYING.LGPL). Absolutely no warranty is provided or implied.
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..c16f127
--- /dev/null
+++ b/TODO
@@ -0,0 +1,29 @@
+SETools TODO List
+=======================
+The following items are desirable features to be considered for future
+versions.
+
+Recent policies list - similar to that in seaudit - sediffx
+
+Improved type feedback - convert results to Tk table and permit
+right-click to pull up type info dialog - apol
+
+Module source loading - load .te and .if sources for modules - all
+tools
+
+Global semantic/syntactic option - allow semantic and syntactic search
+globally - apol
+
+Report generation - similar to saved queries export query results -
+apol
+
+Role dominance queries - query for role dominance relationships - apol
+& seinfo(display only)
+
+Constraint analysis - features to search and analyze constraints -
+apol
+
+Result filtering/sorting - allow rule diffs to be sorted or filtered
+by various fields - sediffx
+
+Duplicate TE warning - can we remove it - parser
diff --git a/VERSION.in b/VERSION.in
new file mode 100644
index 0000000..d78bda9
--- /dev/null
+++ b/VERSION.in
@@ -0,0 +1 @@
+@VERSION@
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 <<ListboxSelect>> 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 <Button-1> Apol_Analysis::_switchTab
+ $widgets(results) bindtabs <Button-3> \
+ [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
--- /dev/null
+++ b/apol/apol.gif
Binary files differ
diff --git a/apol/apol.png b/apol/apol.png
new file mode 100644
index 0000000..7029175
--- /dev/null
+++ b/apol/apol.png
Binary files differ
diff --git a/apol/apol.xcf b/apol/apol.xcf
new file mode 100644
index 0000000..ea6d26e
--- /dev/null
+++ b/apol/apol.xcf
Binary files 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 <config.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tcl.h>
+
+#include <apol/policy.h>
+#include <sefs/db.hh>
+#include <sefs/filesystem.hh>
+
+/** 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 <config.h>
+
+#include <apol/avrule-query.h>
+#include <apol/terule-query.h>
+#include <apol/policy.h>
+#include <apol/policy-path.h>
+#include <apol/util.h>
+#include <sefs/db.hh>
+#include <sefs/filesystem.hh>
+#include <sefs/fcfile.hh>
+%}
+
+%{
+/* 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<const qpol_avrule_t *>(a);
+ const qpol_avrule_t *r2 = static_cast<const qpol_avrule_t *>(b);
+ apol_policy_t *p = static_cast<apol_policy_t *>(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<const qpol_terule_t *>(a);
+ const qpol_terule_t *r2 = static_cast<const qpol_terule_t *>(b);
+ apol_policy_t *p = static_cast<apol_policy_t *>(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<struct apol_tcl_query_data *>(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<int>(++(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 " <none>\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 " <none>\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 <<ListboxSelect>> [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 <Key> [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 <Double-Button-1> [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 <Button-3> [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 <Button-3> [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 <Button-1> [list Apol_Widget::_hyperlink $path %x %y]
+ $tb tag bind linenum <Enter> [list $tb configure -cursor hand2]
+ $tb tag bind linenum <Leave> [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 <<ListboxSelect>>
+ }
+}
+
+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:
+# <ol>
+# <li>The (possibly partial) context, an apol_context_t. The caller
+# must delete this afterwards.
+# <li>The MLS range search type, one of $::APOL_QUERY_EXACT or its like.
+# <li>If not an empty string, the attribute used to filter types.
+# </ol>
+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 <<ListboxSelect>> \
+ [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 <<ListboxSelect>> \
+ [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 <<ListboxSelect>> \
+ [list Apol_Analysis_domaintrans::_selectClassListbox $l2 $classes_lb $perms_lb]
+ bind $perms_lb <<ListboxSelect>> \
+ [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-<version>/)
+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-<version>. 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 <Key-Return> 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 <<ListboxSelect>> \
+ [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 <class_name> <num_permissions>
+#
+# 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