apol: Implement help menu

Populate with some help text from setools3.

Related to #114
This commit is contained in:
Chris PeBenito 2016-04-19 15:59:56 -04:00
parent edde585e5f
commit 2828db4a64
14 changed files with 649 additions and 4 deletions

4
.gitignore vendored
View File

@ -10,6 +10,10 @@ setools/policyrep/qpol_wrap.c
setools/policyrep/qpol.py
*.so
# Qt Generated Help files
help/apol.qch
#help/apol.qhc
# Generated by tox
/.tox

View File

@ -7,6 +7,7 @@ include libqpol/*.y
include libqpol/libqpol.map
include libqpol/include/qpol/*.h
include man/*
include qhc/*
include tests/*.conf
include tests/*.py
include tests/perm_map

View File

@ -76,6 +76,8 @@
<property name="title">
<string>&amp;Help</string>
</property>
<addaction name="apol_help_action"/>
<addaction name="separator"/>
<addaction name="about_apol_action"/>
</widget>
<widget class="QMenu" name="menu_Edit">
@ -225,6 +227,11 @@
<string>Save Permission Map</string>
</property>
</action>
<action name="apol_help_action">
<property name="text">
<string>Apol Help</string>
</property>
</action>
</widget>
<resources/>
<connections>

7
qhc/analyses.html Normal file
View File

@ -0,0 +1,7 @@
<!-- Copyright (c) 2016 Tresys Technology, LLC. All rights reserved. -->
<h1>Analyses</h1>
<p>Apol supports the following analyses:</p>
<ul>
<li><a href="infoflow.html">Information Flow Analysis</a></li>
<li><a href="dta.html">Domain Transition Analysis</a></li>
</ul>

19
qhc/apol.qhcp Normal file
View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright (c) 2016 Tresys Technology, LLC. All rights reserved. -->
<QHelpCollectionProject version="1.0">
<assistant>
<title>Apol Help</title>
<startPage>qthelp://com.github.tresystechnology.setools/doc/index.html</startPage>
</assistant>
<docFiles>
<generate>
<file>
<input>apol.qhp</input>
<output>apol.qch</output>
</file>
</generate>
<register>
<file>apol.qch</file>
</register>
</docFiles>
</QHelpCollectionProject>

34
qhc/apol.qhp Normal file
View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright (c) 2016 Tresys Technology, LLC. All rights reserved. -->
<QtHelpProject version="1.0">
<namespace>com.github.tresystechnology.setools</namespace>
<virtualFolder>doc</virtualFolder>
<customFilter name="Apol">
<filterAttribute>apol</filterAttribute>
</customFilter>
<filterSection>
<filterAttribute>apol</filterAttribute>
<toc>
<section title="Apol" ref="index.html">
<section title="Analyses" ref="analyses.html">
<section title="Information Flow Analysis" ref="infoflow.html"/>
<section title="Domain Transition Analysis" ref="dta.html"/>
</section>
<section title="Components" ref="components.html"/>
<section title="Rules" ref="rules.html"/>
<section title="Labeling" ref="labeling.html"/>
</section>
</toc>
<keywords>
<keyword name="DTA" ref="dta.html"/>
<keyword name="Domain Transition Analysis" ref="dta.html"/>
<keyword name="infoflow" ref="infoflow.html"/>
<keyword name="Information Flow" ref="infoflow.html"/>
<keyword name="Permission Map" ref="infoflow.html#permmap"/>
</keywords>
<files>
<file>*.html</file>
<file>../data/icons/*.png</file>
</files>
</filterSection>
</QtHelpProject>

17
qhc/components.html Normal file
View File

@ -0,0 +1,17 @@
<!-- Copyright (c) 2016 Tresys Technology, LLC. All rights reserved. -->
<h1>Components</h1>
<p>The policy components tabs provide the means to examine, search, and
relate the core components of an SELinux policy.</p>
<p>Apol supports querying the following policy components:</p>
<ul>
<li>Booleans</li>
<li>Categories</li>
<li>Commons</li>
<li>Roles</li>
<li>Object Classes</li>
<li>Sensitivities</li>
<li>Types</li>
<li>Type Attributes</li>
<li>Users</li>
</ul>

143
qhc/dta.html Normal file
View File

@ -0,0 +1,143 @@
<!-- Copyright (c) 2016 Tresys Technology, LLC. All rights reserved. -->
<h1>Domain Transition Analysis</h1>
<p>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.</p>
<p>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.</p>
<h2>Types Used in Domain Transitions</h2>
<p>When discussing domain transition access, there are three different
types we must consider:</p>
<ul>
<li>SOURCE TYPE: This is the domain type associated with a process
that is trying to change (transition) its domain type to another
type.</li>
<li>TARGET TYPE: This is the domain type to which the source type is
trying to transition.</li>
<li>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 exec() system call.</li>
</ul>
<h2>Domain Transition Criteria</h2>
<p>In SELinux, there are two ways for a domain transition to occur,
on <code>exec()</code>, and on <code>setcon()</code>.
The common case is for a domain transition to occur on <code>exec()</code>.</p>
<h3>Transitions on Exec()</h3>
<p>In SELinux, four types of access (and hence at four rules)
must be allowed by the policy for a domain transition to occur. These
access types form the criteria used by apol to determine allowed
transitions.</p>
<p>The criteria for an allowed domain transition are as
follows. In the examples below, assume <code>user_t</code> is the source type,
<code>passwd_t</code> is the target type, and <code>passwd_exec_t</code> is the file entry
point type.</p>
<ol>
<li>A rule must exist that allows the SOURCE domain type <code>transition</code>
access for <code>process</code> object class for the TARGET domain type. For
example, the rule:<pre>
allow user_t passwd_t : process transition;
</pre>meets this criterion by allowing the source type (<code>user_t</code>) <code>process:
transition</code> permission to the target type (<code>passwd_t</code>).</li>
<li>A rule must exist that allows the SOURCE domain type <code>execute</code>
access to the FILE ENTRYPOINT type. For example, the rule:<pre>
allow user_t passwd_exec_t : file { read getattr execute };
</pre>meets the criterion by allowing the source type (<code>user_t</code>) <code>execute</code>
access to the file entrypoint type (<code>passwd_exec_t</code>).</li>
<li>A rule must exist that allows the TARGET domain type <code>entrypoint</code>
access to the FILE ENTRYPOINT type for file objects. For
example, the rule:<pre>
allow passwd_t passwd_exec_t : file entrypoint;
</pre>meets this criterion by allowing the target type (<code>passwd_t</code>) <code>file:
entrypoint</code> access to the file entrypoint type (<code>passwd_exec_t</code>).</li>
<li>There must be a way for the transition to be triggered. Typically
this is accomplished in the policy with a TYPE TRANSITION statement.
For example, the statement:<pre>
type_transition user_t password_exec_t : process passwd_t;
</pre>meets this criterion by specifying that when <code>user_t</code> executes
a program with the <code>passwd_exec_t</code> type, the default type of the
new process is <code>passwd_t</code>. 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:<pre>
allow user_t self : process setexec;
</pre>allows the source type (<code>user_t</code>) 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.</li>
</ol>
<p>In the analysis results, apol will list all the types that meet the above four criteria.</p>
<h3>Transitions on Setcon()</h3>
<p>SELinux also supports domain transitions that are requested by SELinux-aware
programs (also known as a dynamic domain transition),
using the <code>setcon()</code> libselinux function. Two types of access
must be allowed by the policy for a dynamic domain
transition to occur. These access types form the criteria used by apol
to determine allowed transitions.</p>
<p>The criteria for an allowed dynamic domain transition are as
follows. In the examples below, assume <code>souce_t</code> is the source type
and, <code>target_t</code> is the target type.</p>
<ol>
<li>A rule must exist that allows the SOURCE domain type <code>dyntransition</code>
access for <code>process</code> object class for the TARGET domain type. For
example, the rule:<pre>
allow source_t target_t : process transition;
</pre>meets this criterion by allowing the source type (<code>source_t</code>) <code>process:
dyntransition</code> permission to the target type (<code>target_t</code>).</li>
<li>A rule must exist that allows the SOURCE domain type <code>setcurrent</code>
access so it can set its current SELinux context. For example, the rule:<pre>
allow source_t source_t : process setcurrent;
</pre>meets the criterion by allowing the source type (<code>source_t</code>) <code>setcurrent</code>
access on itself.</li>
</ol>
<p>In the analysis results, apol will list all the types that meet the above two criteria.</p>
<h2>Reverse Transitions</h2>
<p>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 (find child domains/processes).
A reverse analysis is the opposite; select a TARGET type and determine all the SOURCE
types that may transition to the target type (find parent domains/processes).</p>

45
qhc/index.html Normal file
View File

@ -0,0 +1,45 @@
<!-- Copyright (c) 2016 Tresys Technology, LLC. All rights reserved. -->
<h1>Apol SELinux Policy Analysis</h1>
<h2>Overview</h2>
<p>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:</p>
<ol>
<li>
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.</li>
<li>Perform some automated analysis of policies, including forward and
reverse domain transition analyses, and information flow analysis.</li>
</ol>
<p>Apol supports source, and 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.
<p>Apol provides compatibility with the current and previous policy
syntax. It supports analysis of policy versions 15 and up.</p>
<h2>Menus</h2>
<p>Use <b>Open</b> from the <b>File</b> menu to open a valid policy.
Only one policy can be open at a time; opening a second policy will
result in the first being closed.</p>
<p>The <b>Permission Map</b> menu allows for opening, editing,
and saving <a href="infoflow.html#permmap">permission mappings</a>.
These are used by apol's <a href="infoflow.html">information flow analysis</a>.</p>
<h2>Starting an Analysis</h2>
<p>To begin analyzing a policy, click the <img src="data/icons/Add.png" alt="green '+'" align="middle">
icon. A menu of available analysis tools will be presented. Select one, and
a new analysis tab will open. Any analysis can be started multiple
times, and each will operate independently, so multiple concurrent
analyses can be performed. To help manage multiple tabs, the tabs can be
renamed by double-click the tab.</p>

280
qhc/infoflow.html Normal file
View File

@ -0,0 +1,280 @@
<!-- Copyright (c) 2016 Tresys Technology, LLC. All rights reserved. -->
<h1>Information Flow Analysis</h1>
<p>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.</p>
<p>Information flow analysis in SELinux is challenging for several
reasons, including:
</p>
<ul>
<li>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.</li>
<li>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.</li>
<li>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.</li>
</ul>
<p>The remainder of this file provides an overview on how apol performs
information flow analysis.</p>
<h2>What Is Overt Information Flow In SELinux?</h2>
<p>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:</p>
<pre>allow subject_t object_t : {file link_file} read;</pre>
<p>This case would have the following direct information flows for the
types subject_t and object_t:</p>
<pre>
subject_t: FROM object_t
object_t: TO subject_t
</pre>
<p>If this were the only rule relating to these two types, there would be
no other direct information flows from or to either.</p>
<p>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 dozens of object classes (including processes, which are
both subjects and objects).</p>
<p>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.</p>
<p>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:</p>
<pre>
object_t [file, link_file]: TO subject_t
</pre>
<p>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).</p>
<a name="permmap"><h2>Object permission mappings</h2></a>
<p>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):</p>
<pre>
SUBJECT: READ: IN flow
WRITE: OUT flow
OBJECT: READ: OUT flow
WRITE: IN flow
</pre>
<p><b>NOTE:</b> 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.</p>
<p>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.</p>
<p>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 <code>getattr</code> 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.</p>
<p>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.</p>
<p>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.</p>
<h2>Permission Weighting</h2>
<p>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.
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 <code>read</code> and <code>write</code> on
the file object could be given a weight of 10 because they are very
high-bandwidth information flows. Additionally, the <code>use</code> permission
on the <code>fd</code> 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 <code>fd: use</code>, but be
given a low weight for information flow because it cannot be used to
pass large amounts of information.</p>
<p>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:</p>
<ul>
<li>1 - 2 difficult to exploit covert flows (example: fd:use)</li>
<li>3 - 5 less difficult to exploit covert flows
(example: process:signal) </li>
<li>6 - 7 difficult to use, noisy, or low-bandwidth overt flows
(example: file:setattr)</li>
<li>8 - 10 high-bandwidth overt flows (example: file:write)</li>
</ul>
<p>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.</p>
<h2>Types of information flow analysis</h2>
<p>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.</p>
<p>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.</p>
<p>For example, given the following rules:</p>
<pre>
allow one_t two_t : file write;
allow three_t two_t: file read;
</pre>
<p>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.</p>
<p>For direct analyses, the results are presented in
tree form in the browser tab. 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).</p>
<h2>Managing Permission Mappings</h2>
<p>The ability to directly manage permission maps is important for the
following reasons:</p>
<ul>
<li>Permission maps are central to analyzing information flows, and
the correctness of the map has a direct influence on the value of
he results.</li>
<li>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).</li>
<li>The analyst may be working with several different policies each
with different definitions of object classes and permissions.</li>
</ul>
<p>Because of these reasons, apol was designed to provide great latitude
in managing permission mappings using <strong>Permission Map</strong> menu. A user need not
manage permission maps directly; apol is installed with default
permission maps (typically in <code>/usr/share/setools/perm_map</code>)
that will be loaded automatically when an information flow analysis is
performed.</p>
<p>Use the <strong>Permission Map</strong> 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.</p>
<p>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 <strong>Edit Permission Map</strong>from the <strong>Permission Map</strong> 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 1 if a weight value is not
provided for the permission in the permission map.</p>
<h2>Finding more flows</h2>
<p>For a transitive information flow, there might be many different
information flows between two types. For example, given the
following policy:</p>
<pre>
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;
</pre>
<p>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. The analysis algorithm can find all information flows, but
this would be time prohibitive on large policies. Apol provides two
ways of constraining the analysis time. Two analysis algorithms are provided:</p>
<ol>
<li>Shortest Paths: The shortest path between the source and target type will
be found. If there are multiple shortest paths, all with be found.</li>
<li>All Paths: All paths between the source and target type will be found.
To constrain this, an upper limit of path length must be specified. For typical
policies, a path length more than 4 or 5 may be very expensive.</li>
</ol>
<p>Additionally, the analysis can be constrained by number of results. The
<strong>Limit Results</strong> option will stop the analysis if the specified
number of results is reached. There is no idication if there are more results</p>

11
qhc/labeling.html Normal file
View File

@ -0,0 +1,11 @@
<!-- Copyright (c) 2016 Tresys Technology, LLC. All rights reserved. -->
<h1>Labeling</h1>
<p>Apol supports querying the following labeling statements:</p>
<ul>
<li>Fs_use_* Statements</li>
<li>Genfscon Statements</li>
<li>Initial SID Statements</li>
<li>Netifcon Statements</li>
<li>Nodecon Statements</li>
<li>Portcon Statements</li>
</ul>

9
qhc/rules.html Normal file
View File

@ -0,0 +1,9 @@
<!-- Copyright (c) 2016 Tresys Technology, LLC. All rights reserved. -->
<h1>Rules</h1>
<p>Apol supports querying the following rule types:</p>
<ul>
<li>Constraints</li>
<li>Multi-level Security (MLS)</li>
<li>Role-based Access Control (RBAC)</li>
<li>Type Enforcement (TE)</li>
</ul>

View File

@ -16,10 +16,13 @@
# License along with SETools. If not, see
# <http://www.gnu.org/licenses/>.
#
import os
import sys
import stat
import logging
from errno import ENOENT
from PyQt5.QtCore import Qt
from PyQt5.QtCore import pyqtSlot, Qt, QProcess
from PyQt5.QtWidgets import QApplication, QFileDialog, QLineEdit, QMainWindow, QMessageBox
from setools import __version__, PermissionMap, SELinuxPolicy
@ -80,6 +83,9 @@ class ApolMainWindow(SEToolsWidget, QMainWindow):
logging.getLogger("setools").addHandler(handler)
logging.getLogger("setoolsgui").addHandler(handler)
# set up help browser process
self.help_process = QProcess()
# connect signals
self.open_policy.triggered.connect(self.select_policy)
self.close_policy_action.triggered.connect(self.close_policy)
@ -96,6 +102,7 @@ class ApolMainWindow(SEToolsWidget, QMainWindow):
self.edit_permmap_action.triggered.connect(self.edit_permmap)
self.save_permmap_action.triggered.connect(self.save_permmap)
self.about_apol_action.triggered.connect(self.about_apol)
self.apol_help_action.triggered.connect(self.apol_help)
self.show()
@ -305,3 +312,42 @@ class ApolMainWindow(SEToolsWidget, QMainWindow):
"<a href=\"https://github.com/TresysTechnology/setools/wiki\">"
"SETools</a>.<p>"
"Copyright (C) 2015-2016, Tresys Technology.".format(__version__))
def apol_help(self):
"""Open the main help window."""
if self.help_process.state() != QProcess.NotRunning:
return
for path in ["qhc", sys.prefix + "/share/setools"]:
helpfile = "{0}/apol.qhc".format(path)
try:
if stat.S_ISREG(os.stat(helpfile).st_mode):
break
except (IOError, OSError) as err:
if err.errno != ENOENT:
raise
else:
self.log.critical("Unable to find apol help data (apol.qhc).")
self.log.debug("Starting assistant with help file {0}".format(helpfile))
self.help_process.start("assistant",
["-collectionFile", helpfile, "-showUrl",
"qthelp://com.github.tresystechnology.setools/doc/index.html",
"-show", "contents", "-enableRemoteControl"])
@pyqtSlot(str)
def set_help(self, location):
"""Set the help window to the specified document."""
if self.help_process.state() == QProcess.NotStarted:
self.apol_help()
if not self.help_process.waitForStarted():
self.log.warning("Timed out waiting for Qt assistant to start.")
return
elif self.help_process.state() == QProcess.Starting:
if not self.help_process.waitForStarted():
self.log.warning("Timed out waiting for Qt assistant to start.")
return
self.help_process.write("setSource qthelp://com.github.tresystechnology.setools/doc/{0}\n".
format(location))

View File

@ -13,6 +13,26 @@ import os
from os.path import join
class QtHelpCommand(Command):
description = "Build Qt help files."
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
command = ['qcollectiongenerator', 'apol.qhcp', '-o', 'apol.qhc']
self.announce("Building Qt help files", level=log.INFO)
self.announce(' '.join(command), level=log.INFO)
pwd = os.getcwd()
os.chdir("./qhc")
subprocess.check_call(command)
os.chdir(pwd)
class YaccCommand(Command):
description = "Build yacc parsers."
user_options = []
@ -140,11 +160,13 @@ setup(name='setools',
url='https://github.com/TresysTechnology/setools',
cmdclass={'build_yacc': YaccCommand,
'build_lex': LexCommand,
'build_ext': BuildExtCommand},
'build_ext': BuildExtCommand,
'build_help': QtHelpCommand},
packages=['setools', 'setools.diff', 'setools.policyrep', 'setoolsgui', 'setoolsgui.apol'],
scripts=['apol', 'sediff', 'seinfo', 'seinfoflow', 'sesearch', 'sedta'],
data_files=[(join(sys.prefix, 'share/man/man1'), glob.glob("man/*.1") ),
(join(sys.prefix, 'share/setools'), glob.glob("data/*.ui") + ["data/perm_map"] ),
(join(sys.prefix, 'share/setools'), glob.glob("data/*.ui") +
["data/perm_map", "qhc/apol.qhc"] ),
(join(sys.prefix, 'share/setools/icons'), glob.glob("data/icons/*.png"))],
ext_modules=ext_py_mods,
test_suite='tests',