includefile(../../release.yo)

htmlbodyopt(text)(#27408B)
htmlbodyopt(bgcolor)(#FFFAF0)

gagmacrowarning(stealth Stealth client)
mailto(f.b.brokken@rug.nl)

DEFINEMACRO(s)(0)(bf(stealth))
DEFINEMACRO(S)(0)(bf(Stealth))

manpage(stealth)(1)(_CurYrs_)(stealth__CurVers_)(Security Enhancement)

manpagename(stealth)(Stealthy File Integrity Scanner)

manpagesynopsis()
    `<uds>' represents the location of the used Unix Domain Socket.nl()

    s()  --daemon <uds> --dry-run --log <file-spec> --logmail+nl()
            --max-size <size>[BKMG] --no-mail --parse-policy-file+nl()
            --random-interval <seconds> --repeat <seconds>nl()
            --skip-files <file-spec> --syslog+nl()
            --syslog-facility <fac> --syslog-priority <pri> 
                                                    --syslog-tag <tag>nl()
            --verbosity <value> policy

    s()  --dry-run --log <file-spec> --logmail+nl()
            --max-size <size>[BKMG] --no-mail --parse-policy-file+nl()
            --random-interval <seconds> --repeat <seconds>nl()
            --run-command <nr> --skip-files <file-spec> --stdout --syslog+nl()
            --syslog-facility <fac> --syslog-priority <pri> 
                                                    --syslog-tag <tag>nl()
            --verbosity <value> policy

    s() {--ping,--reload,--rerun,--resume,--suspend,--terminate} <uds>

    s() --help --version


manpagedescription()

    The name of the s() program is an acronym of:
    quote(
    bf(SSH-based Trust Enforcement Acquired through a Locally Trusted Host.)
    )
    S() is based on an idea by em(Hans Gankema) and em(Kees Visser), both at
the Center for Information Technology of the University of Groningen. em(Hopko
Meijering) provided valuable suggestions for improvement.

    S()'s main task is to perform file integrity tests. However, the
testing itself will leave no sediments on the tested computer. Therefore,
s() has em(stealthy) characteristics. This is considered an
important feature, improving the security (integrity) of the software of
computers monitored by s().

    Please realize that s() intends to be just another security tool: other
security measures like firewalls, portscanners, intrusion detection systems,
dropping unencrypted protocols, etc. are usually required to improve the
security of a group of computers that are connected to the Internet. S() is a
file integrity scanner, and file integrity scanners offer no substitute for
those tools (and vv.).

    S() uses a policy file to determine the actions to perform. Each
policy file is uniquely associated with a host being monitored. This host
(called the em(client) below) trusts the computer on which s() runs, called
the em(monitor) (hence: a em(Locally Trusted Host)). The monitor
performs tasks (normally file integrity tests) that em(Enforce) the em(Trust)
we have in the client computer. Since almost all integrity tests can be run
on the client, one monitor can control many clients, even if the
monitor itself uses aged hard- and software components.

As the monitor and the client are (i.e., should be) different computers, the
monitor must communicate with the client in a secure fashion. This is realized
through SSH. So, there's another element of `local trust' involved here: the
client should permit the monitor to set up a secure SSH connection allowing
the monitor to access sensitive elements in the client's file system.

bf(It is important to ensure that public access to the monitor is
prevented. No incoming services should be allowed. The only access to the
monitor should be via its console and the monitor should be placed in a
physically secure location. Sensitive information of clients are stored in the
monitor's file system. To access the clients s() in daemon mode can use a
passphrase-protected ssh-key, allowing s() to perform its tasks
thereafter. This, too, makes it important to prevent the monitor from being
accessed by unauthorized persons.)

If, instead of running s() in daemon mode it is preferred to let s() perform
single, but automated integrity scans, then new bf(ssh)(1) connections may be
difficult to establish if the used ssh-key is passphrase-protected. To
implement this scenario (i.e., automated integrity scans using passphrase
protected ssh-keys) the program bf(ssh-cron)(1) can profitably be used. 

S()'s current way of connecting to clients uses a single bf(ssh)(1)
connection, which results in only a single  bf(sshd)(1)
entry in the client's logfiles, which lasts for the duration of s()'s
run. When using s() in daemon mode this too minimizes the `footprint' s() has
on the client hosts.

The monitor itself normally only requires two types of outgoing services:
bf(SSH) to reach its clients, and some mail transport agent (e.g.,
bf(sendmail)(1)) to forward its outgoing mail to some mail-hub.

    Here is what happens when s() running using the first synopsis:
    itemization(
    it() First, the em(policy) file is read. For each client a policy file is
defined, specifying the actions to be performed, and specifying the values of
several variables used by s().

    it() If the command-line option tt(--daemon <uds>) is specified, s()
runs as a daemon process, using the Unix Domain Socket (tt(<uds>)) for
communication with s() processes running in IPC mode.

If access to the Unix Domain Socket defined by Stealth running in daemon mode
should be restricted, it can be defined in a directory with is only accessible
to the user running Stealth (this will often be the root-user).

When running in daemon mode, tt(--repeat <seconds>) may be specified to rerun
the integrity scan every tt(<seconds>) seconds. If an integrity scan is being
performed when, according to the repeat interval the next integrity scan is
due, then the current scan is first completed. Once completed, the next
integrity scan will be performed after tt(seconds) seconds.

    it() Next, the monitor opens a command shell on the client using
bf(ssh)(1), and a command shell on the monitor computer itself using
bf(sh)(1).

    it() Once the command shells are available, commands defined in the policy
file are executed in their order of appearance. Examples are given
below. Normally, return values of the programs are tested. When return values
are to be tested s() terminates when a non-zero return value is sensed. If
this happens, a message stating the reason why s() terminated is written to
the report file (and into the mail sent by s()). In some cases (e.g., when the
report file could not be written), the message is written to the standard
error stream.

    it() Very often integrity tests can be controlled using bf(find)(1),
calling programs like bf(ls)(1), bf(sha256sum)(1) or its own tt(-printf)
method to produce file-integrity related statistics. Most of these programs
write file names at the end of generated lines. This characteristic is used by
one of s()'s internal routines to detect changes in the generated output. Such
changes could indicate some harmful intent, like an installed em(root-kit).

    it() When changes are detected, they are logged in a em(report file), to
which information is always appended. S() never reduces the report file's size
or rewrites its contents. When information is added to the report file (beyond
a plain time stamp) the newly added information is e-mailed to a configurable
e-mail address for further (human) processing. Usually the e-mail is sent to
the systems manager of the tested client. S() follows the `dark cockpit'
approach in the sense that no mail is sent when no changes were detected.

    it() Report and other log-files may safely be rotated between a pair of
tt(--suppress) and tt(--resume) commands (see below at the section `REPORT
FILE ROTATION').
    )

If s() should not be run as a daemon process the second synopsis can be
used. In this case s() performs one or more integrity scans (the latter when
the tt(--repreat) option was specified). When a single integrity scan is
requested s() terminates after the scan. When tt(--repeat) is specified s()
shows a prompt (i.e., `tt(? )') and terminates after pressing the
tt(Enter)-key. 

The third synopsis is used for communication with a s() daemon. In this case
the the Unix Domain Socket defined by the s() daemon process must be
specified after the option specifying the requested command.

manpagesection(OPTIONS)

    includefile(../manual/running/options.yo)

manpagesection(EXIT STATUS)

    When requesting an IPC command or when starting s() as a daemon 0 is
returned if the command was successfully completed. Otherwise a non-0 value is
returned.

manpagesection(OPEN SSH LINK TO CLIENTS)

    Once s() has started as a foreground or daemon process performing file
integrity scans bf(ssh)(1) is used to connect to the client(s) 
monitored by s(). While s() runs only one bf(ssh)(1) connection is opened to
each client. This connection remains active during s()'s lifetime to minimize
the number of bf(sshd) entries in the client's log files.

    nsect(THE POLICY FILE)

    The policy file consists of two sections, the second section is optional,
and starts at a line merely containing tt(%%).

    The policy file's first section consists of two sets of data: em(use
directives) (starting with the keyword bf(USE)) and em(commands). Blank lines
and information beyond hash-marks (#) are ignored, while lines following lines
terminating in backslashes (\) are concatenated (em(en passant) removing these
trailing backslashes). Leading white space on lines of the policy file is
ignored.

    The (optional) second section starts at a line merely containing
tt(%%). Following this separating line several long option specifications can
be entered (see below at section bf(OPTIONS)). Options specified on the
command-line take priority over options specified in the policy file. Although
the tt(--reload) option reloads the policy file, it will not change option
values originally specified as command-line options. This section may contain
specifications of the tt(skip-files) and tt(log) options.  Relative file
locations specified for these options are interpreted relative to the location
of the policy file. E.g., if the policy file argument is specified as
tt(/root/client/policy) then the specification tt(log: client.log) results in
s() writing its logs into the file tt(/root/client/client.log).


nsect(DEFINE DIRECTIVES)

    bf(DEFINE) directives are used to associate longer strings of text with
certain symbols. E.g., after
    tt(DEFINE FINDARGS -xdev -type f -exec /usr/bin/sha256sum {} \;)
    the specification tt(${FINDARGS}) may be used in bf(USE DIRECTIVES) and
bf(commands) (see below) to use the text associated with the bf(FINDARGS)
symbol.

    Note that bf(DEFINE) symbols may also be used in the definition of 
other bf(DEFINE) symbols as well. Direct or indirect circular definitions
should be avoided, as they are either not or incompletely expanded.

nsect(USE DIRECTIVES)

    The following bf(USE) directives may be specified (directives are written
in capitals, and should appear exactly as written below: letter casing is
preserved). Specifications in angular brackets (like tt(<this>)) represent
specifications to be provided  by s()'s users:
    itemization(
    it() bf(USE BASE) tt(<base-directory>)nl()
        bf(BASE) defines the directory from where s() operates. All subsequent
relative path specifications in the policy file (including relative path
specifications in the policy's second part) are interpreted relative to
bf(BASE). em(By default) this is the directory where s() was started. nl()
    bf(BASE) and other non-existing paths are created automatically by
s() if not yet existing.nl()
    Example:nl()
    tt(USE BASE /root/client)

    it() bf(USE DD) tt(<dd>)nl()
        The bf(DD) specification uses tt(/bin/dd) as default, and defines the
location of the bf(dd)(1) program, both on the server and on the client. The
bf(DD) program is used to copy files between the client and the monitor
over the existing ssh-connection. The program specified here is only used by
s() when executing tt(PUT) and tt(GET) commands (described below).nl()
    Example showing the default:nl()
    tt(USE DD /bin/dd)

    it() bf(USE DIFF) tt(<diff>)nl()
        The default bf(DIFF) specification uses tt(/usr/bin/diff),
and defines the location of the bf(diff)(1) program on the monitor. The
bf(diff)(1) program is used to compare a formerly created logfile of an
integrity check with a newly created logfile.nl()
    Example showing the default:nl()
    tt(USE DIFF /usr/bin/diff)

    it() bf(USE DIFFPREFIX) tt(<prefix>)nl()
        The bf(DIFFPREFIX) specification defines the size of the prefix added
by the tt(DIFF) command to lines produced by commands executed through s().

The default tt(/usr/bin/diff) program prefixes lines by either `tt(> )' or
`tt(< )'. The default value for tt(<prefix>) is therefore equal to 2.nl()
    Example showing the default:nl()
    tt(USE DIFFPREFIX 2)

    it() bf(USE EMAIL) tt(<address>)nl()
        The bf(EMAIL) specification defines the email-address to receive the
report of the integrity scan of the client. The `dark cockpit' philosophy is
followed here: mail is only sent when a modification is detected.nl()
    Example showing the default (apparently an email address on the
monitor):nl()
    tt(USE EMAIL root)

    it() bf(USE MAILER) tt(<mailer>)nl()
        The bf(MAILER) specification defines the program that to send
e-mail to the bf(EMAIL)-address. Contrary to bf(DIFF) and bf(DD) and (see
below) bf(SH) and bf(SSH), bf(MAILER) is run as a tt(/bin/sh) command, to
allow shell-scripts to process the mail too. By default bf(MAILER) is defined
as bf(/usr/bin/mail). bf(MAILER) is called with the following
arguments:nl()
    ----------------------------------------------------------nl()
    bf(MAILARGS), see below;nl()
    bf(EMAIL), the addressee of the mail.nl()
    ----------------------------------------------------------nl()
    Example showing the default:nl()
    tt(USE MAILER /usr/bin/mail)

    As an alternative, the script tt(stealthmail) is provided. It offers a
convenient filter sorting s()'s output and keeping only lines containing the
text tt(ADDED), tt(MODIFIED), tt(REMOVED) or tt(STEALTH). Usually these lines
are the ones system managers are interested in. The report and log files
can always be consulted to determine the actual nature of the changes.

    it() bf(USE MAILARGS) tt(<args>)nl()
        The bf(MAILARGS) specification defines the arguments that are passed
to tt(MAILER), followed by the tt(EMAIL) specification.nl()
    Example showing the default:nl()
    tt(USE MAILARGS -s "STEALTH scan report")nl()
    Note that blanks may be used in the subject specification: use double or
single quotes to define elements containing blanks. Use tt(\") to use a double
quote in a string that itself is delimted by double quotes; use tt(\') to use
a single quote in a string that itself is delimted by single quotes. 

    it() bf(USE REPORT) tt(<file-spec>)nl()
        bf(REPORT) defines the name of the reportfile. Information is always
appended to this file. At each s() integrity scan a em(time marker line) is
written to the report file. Only when (in addition to the marker line)
additional information is appended to the report file the added contents of
the report file are mailed to the mail address specified in the bf(USE EMAIL)
specification. When a relative file specification is used it is interpreted a
location relative to the tt(USE BASE) specification.nl()
    Example showing the default:nl()
    tt(USE REPORT report)

    it() bf(USE SH) tt(<sh>)nl()
        The bf(SH) specification uses tt(/bin/sh) as default, and defines the
command shell used by the monitor to execute commands on itself. This must be
an absolute path specification.nl()
    Example showing the default:nl()
    tt(USE SH /bin/sh)

    it() bf(USE SSH) tt(<user>)nl()
        bf(The SSH specification has no default), and em(must) be
specified. This must be an absolute path specification.  

    Assuming the client em(trusts) the monitor (which is after all what this
program is all about, so this should not be a very strong assumption),
preferably the public ssh key of the monitor should be placed in the
client's root tt(.ssh/authorized_keys) file, granting the monitor root access
to the client. Root access is normally needed to gain access to all
directories and files of the client's file system.

    In practice, connecting to an account using the bf(sh)(1) shell is
preferred. When another shell is already used by that account, one should make
sure that its shell doesn't define its own redirections for standard input
and standard output. One way to accomplish that is for force the execution of
tt(/bin/sh) in the bf(USE SSH) specification.
    Examples:
        verb(    # root's shell is /bin/sh:
        USE SSH root@client -T -q    
    # root uses another shell, but the use of /bin/bash is forced:
        USE SSH root@client -T -q exec /bin/bash    
    # an alternative:
        USE SSH root@client -T -q exec /bin/bash --noprofile)    
    )

    In some installations s() is used to inspect the monitor itself, even
though this is em(not) recommended, as it breaks one of the main reasons for
s()'s existence. But in those situations (so, where s() is used to monitor the
integrity of the tt(localhost)), tt(/bin/bash) could be specified at the
tt(USE SSH) directive. For example:
        verb(    # For stealth inspecting localhost:
        USE SSH /bin/bash --noprofile)

nsect(COMMANDS)

    Following the bf(USE) specifications, em(commands) can be specified. The
commands are executed in their order of appearance in the policy
file. Processing continues until the last command has been processed or until
a tested command (see below) returns a non-zero return value.

nsect(LABEL COMMANDS)
    
    The following bf(LABEL) commands are available:
    itemization(
    it() bf(LABEL) tt(<text>)nl()
        This defines a text-label which is written to the bf(REPORT) file,
in front of the output generated by the next bf(CHECK)-command. If the next
bf(CHECK)-command generates no output, the text-label is not written to the
bf(REPORT)-file. Once a bf(LABEL) has been defined, it is used until it is
redefined by the next bf(LABEL). Use an empty bf(LABEL) specification to
suppress the printing of labels.

    The text may contain tt(\n) characters (two characters) which are
transformed to a newline character.

    Example:nl()
    tt(LABEL Inspecting files in /etc\nIncluding subdirectories)nl()
    tt(LABEL) nl()
        (In this example the former bf(LABEL) specification is erased by the
        latter bf(LABEL) command).
    )

nsect(LOCAL COMMANDS)

    bf(LOCAL) commands are executed on the monitor itself:
    itemization(
    it() bf(LOCAL) tt(<command>)nl()
        Execute tt(command) on the monitor, using the bf(SH) command
shell. The command must succeed (i.e., must return a zero exit value). nl()
    Example:nl()
    tt(LOCAL scp rootsh@client:/usr/bin/sha256sum /tmp)nl()
    This command copies the client's bf(sha256sum)(1) program to the
monitor.

    it() bf(LOCAL NOTEST) tt(<command>)nl()
        Execute tt(command) on the monitor, using the bf(SH) command
shell. The command may or may not succeed.nl()
    Example:nl()
    tt(LOCAL NOTEST mkdir /tmp/subdir)nl()
    This command creates tt(/tmp/subdir) on the monitor. The command fails
if the directory cannot be created, but this does not terminate s().

    it() bf(LOCAL CHECK) [bf(LOG =)] tt(<file-spec> [pathOffset]
                                                            <command>)nl()
        Execute tt(command) on the monitor, using the bf(SH) command
shell. The command must succeed. The output of this command is compared to the
output of this command generated during the previous integrity check run by
s().

    The phrase bf(LOG =) is optional. When a relative file location is
specified at tt(<file-spec>) it is interpreted relatively to the tt(USE BASE)
path specification. 

    tt(PathOffset) is also optional. If specified it defines the (0-based)
offset where path-names of inspected files start in lines produced by
tt(<command>). By default s() assumes that the first occurrence of a forward
slash defines the first character of the path-names of inspected files.

    For example, if diff-output looks like this:
        verb(    01234567890123456789012345678901234567890 (column offsets)
    33c33
    < 90d8b506d249634c4ff80b9018644567  filename-specification
    ---
    > b88d0b77db74cc4a742d7bc26cdd2a1e  filename-specification)
    then the specification
        verb(    LOCAL CHECK logfile 36 command-to-be-executed)
    informs s() where to find the filename specifications in the
diff-output. Using the standard tt(/usr/bin/diff) command, this offset equals
2 + the offset of the tt(filename-specification) found in
tt(command-to-be-executed). 

Any differences between the previous and current output are written to
bf(REPORT). If differences were found, the existing tt(logfile) name is
renamed to tt(logfile.YYMMDD-HHMMSS), with tt(YYMMDD-HHMMSS) the
(UTC) datetime-stamp at the time s() was run.

    Note that eventually many tt(logfile.YYMMDD-HHMMSS) files could be
created: It is up to the monitor's systems manager to decide what to do
with old datetime-stamped logfiles.

    The tt(logfile) specifications may use relative and absolute paths. When
relative paths are used, these paths are relative to bf(BASE). When the
directories implied by the tt(logfile) specifications do not yet exist, they
are created first.

    Example:nl()
    tt(LOCAL CHECK LOG = local/sha256sum sha256sum /tmp/sha256sum)nl()
    This command checks the SHA256 sum of the tt(/tmp/sha256sum) program. The
resulting output is saved at bf(BASE)tt(/local/sha256sum). The program must
succeed (i.e., tt(sha256sum) must return a zero exit-value).

    it() bf(LOCAL NOTEST CHECK) tt(<logfile>  [pathOffset] <command>)nl()
        Execute tt(command) on the monitor, using the bf(SH) command
shell. The command may or may not succeed. Otherwise, the command performs
exactly like the bf(LOCAL CHECK ...) command, discussed above.

    Example:nl()
    tt(LOCAL NOTEST CHECK LOG=local/sha256sum sha256sum /tmp/sha256sum)nl()
    This command checks the SHA256 sum of the tt(/tmp/sha256sum) program. The
resulting output is saved at bf(BASE)tt(/local/sha256sum). The program must
succeed (i.e., tt(sha256sum) must return a zero exit-value).
    )

    Note that the bf(scp)(1) command can be used to copy files between the
client and the monitor, using a local command. This, however, is
discouraged, as a separate bf(ssh)(1)-connection is required for each separate
bf(scp)(1) command. This subtlety was brought to the author's attention by
Hopko Meijerink (tt(h.meijering@rug.nl)). 

    To copy files between the client and the monitor, the tt(GET) and
tt(PUT) commands (described below) should be used instead, as these commands
use the existing bf(ssh)(1) connection. In general, tt(LOCAL) commands should
not be used to establish additional bf(ssh)(1) connections to a client.

nsect(REMOTE COMMANDS)

    Remote commands are commands executed on the client using the bf(SSH)
shell. These commands are executed using the standard tt(PATH) set for the
bf(SSH) shell. However, it is advised to specify the full pathname to the
programs to be executed, to prevent ``trojan approaches'' where a trojan horse
is installed in an `earlier' directory of the tt(PATH)-specification than the
intended program.

    Two special remote commands are tt(GET) and tt(PUT), which can be used to
copy files between the client and the monitor.  Internally, tt(GET) and
tt(PUT) use the tt(DD) specification. If a non-default specification is
used, one should ensure that the alternate program accepts bf(dd)(1)'s tt(if=,
of=, bs=) and tt(count=) options. With tt(GET) the options tt(bs=, count=) and
tt(of=) are used, with tt(PUT) the options tt(bs=, count=) and tt(if=) are
used. Normally there should be no need to alter the default tt(DD)
specification.

    The tt(GET) command may be used as follows:
    itemization(    
    it() bf(GET) tt(<client-path> <local-path>)nl()
    Copy the file indicated by tt(client-path) at the client to tt(local-path)
at the monitor. Here, tt(client-path) must be the full path of an existing
file on the client, tt(local-path) may either be a local directory, in which
case the client's file name is used, or another file name may be specified, in
which case the client's file is copied to the specified local filename. If the
local file already exists, it is overwritten by the copy-procedure.

    Example:nl()
    tt(GET /usr/bin/sha256sum /tmp)nl()
    The program tt(/usr/bin/sha256sum), available at the client, is copied to the
monitor's tt(/tmp) directory. If, for whatever reason, copying fails, then
s() terminates.

    it() bf(GET NOTEST) tt(<client-path> <local-path>)nl()
    Copy the file indicated by tt(client-path) at the client to tt(local-path)
at the monitor. Again, tt(client-path) must be the full path of an existing
file on the client, tt(local-path) may either be a local directory, in which
case the client's file name is used, or another file name may be specified, in
which case the client's file is copied to the specified local filename. If the
local file already exists, it is overwritten by the copy-procedure.

    Example:nl()
    tt(GET NOTEST /usr/bin/sha256sum /tmp)nl()
    The program tt(/usr/bin/sha256sum), available at the client, is copied to the
monitor's tt(/tmp) directory. Remaining commands in the policy file are
executed, even if the copying process wasn't successful.
    )

    The tt(PUT) command may be used as follows:
    itemization(    
    it() bf(PUT) tt(<local-path> <remote-path>)nl()
    Copy the file indicated by tt(local-path) at the monitor to
tt(remote-path) at the client. The argument tt(local-path) must be the
full path of an existing file on the monitor. The argument tt(remote-path)
must be the full path to a file on the client. If the remote file already
exists, it is overwritten by tt(PUT).

    Example:nl()
    tt(PUT /tmp/sha256sum /usr/bin/sha256sum)nl()
    The program tt(/tmp/sha256sum), available at the monitor, is copied to the
client as tt(usr/bin/sha256sum). If the copying fails, bf(stealth) terminates.

    it() bf(PUT NOTEST) tt(<local-path> <remote-path>)nl()
    Copy the file indicated by tt(local-path) at the monitor to
tt(remote-path) at the client. The argument tt(local-path) must be the
full path of an existing file on the monitor. The argument tt(remote-path)
must be the full path to a file on the client. If the remote file already
exists, it is overwritten by tt(PUT).

    Example:nl()
    tt(PUT NOTEST /tmp/sha256sum /usr/bin/sha256sum)nl()
    Copy the file indicated by tt(local-path) at the monitor to
tt(remote-path) at the client. The argument tt(local-path) must be the full
path of an existing file on the monitor. The argument tt(remote-path) must
be the full path to a file on the client. If the remote file already exists,
it is overwritten by tt(PUT). Remaining commands in the policy file are
executed, even if the copying process wasn't successful.
    )

    Plain commands can be executed on the client computer by merely specifying
them. Of course, this implies that programs on the client which are named,
e.g., tt(LABEL), tt(LOCAL) or tt(USE), cannot be executed, since these names
are interpreted otherwise by s(). It's unlikely that this restriction presents
much of a problem....

    The following commands are available for execution on the client:
    itemization(
    it() tt(<command-path>)nl()
        Execute tt(command-path) on the client using the bf(SSH) command shell
(it is strongly advised to specify a full path to the command to execute). The
command must succeed (i.e., must return a zero exit value). However, any
output generated by the the command is ignored. nl()
    Example:nl()
    tt(/usr/bin/find /tmp -type f -exec /bin/rm {} \;)nl()
    This command removes all ordinary files in and below the client's
tt(/tmp) directory.

    it() bf(NOTEST) tt(<command-path>)nl()
        Execute tt(command-path) on the client, using the bf(SSH) command
shell. The command may or may not succeed.nl()
    Example:nl()
    tt(NOTEST /usr/bin/find /tmp -type f -exec /bin/rm {} \;)nl()
    Same as the previous command, but this time the exit value of
tt(/usr/bin/find) is not interpreted.

    it() bf(CHECK) [bf(LOG =)] tt(<file-spec>  [pathOffset] 
                                                        <command-path>)nl()
        Execute tt(command-path) on the client, using the bf(SSH) command
shell.

    The phrase bf(LOG =) is optional. When a relative file location is
specified at tt(<file-spec>) it is interpreted relatively to the tt(USE BASE)
path specification. 

tt(PathOffset) is also optional, and has the same meaning
as for the tt(LOCAL CHECK) command, described above. The command must
succeed. The output of this command is compared to the output of this command
generated during the previous run of s(). Any differences are written to
bf(REPORT). If differences were found, the existing tt(logfile) name is
renamed to tt(logfile.YYMMDD-HHMMSS), with tt(YYMMDD-HHMMSS) the
datetime-stamp at the time s() was run.

    Note that the command is executed on the client, but the logfile is kept
on the monitor. This command represents the core of the method implemented
by s(): there will be no residues of the actions performed by s() on
the client computers.

    Several examples (note the use of the backslash as line continuation
characters):

tt(CHECK LOG = remote/ls.root \)nl()
tt(    /usr/bin/find / \)nl()
tt(    -xdev -perm /6111 -type f -exec /bin/ls -l {} \;)

    All suid/gid/executable files on the same device as the root-directory (/)
on the client computer are listed with their permissions, owner and size
information. The resulting listing is written on the file
bf(BASE)tt(/remote/ls.root).


tt(CHECK remote/sha256.root \)nl()
tt(    /usr/bin/find / \)nl()
tt(    -xdev -perm /6111 -type f -exec /usr/bin/sha256sum {} \;)

    The SHA256 checksums of all suid/gid/executable files on the same device as
the root-directory (/) on the client computer are determined.  The resulting
listing is written on the file bf(BASE)tt(/remote/sha256.root).

    it() bf(NOTEST CHECK) [bf(LOG =)] tt(<file-spec> [pathOffset] 
                                                        <command-path>)nl()
        Execute tt(command-path) on the client, using the bf(SSH) command
shell. 

    The phrase bf(LOG =) is optional. When a relative file location is
specified at tt(<file-spec>) it is interpreted relatively to the tt(USE BASE)
path specification. 

tt(PathOffset) is also optional, and has the same meaning as for the tt(LOCAL
CHECK) command, described above. The command may or may not
succeed. Otherwise, the program acts identically as the bf(CHECK ...) command,
described above.

    Example:nl()
tt(NOTEST CHECK LOG = remote/sha256.root \)nl()
tt(    /usr/bin/find / \)nl()
tt(    -xdev -perm /6111 -type f -exec /usr/bin/sha256sum {} \;)


    The SHA256 checksums of all suid/gid/executable files on the same device as
the root-directory (/) on the client computer are determined.  The resulting
listing is written on the file bf(BASE)tt(/remote/sha256.root). s() does not
terminate if the tt(/usr/bin/find) program returns a non-zero exit value.
    )

    The maximum download size (using GET or CHECK) can be specified using the
tt(--max-size) option, see below. By default this size is set at 10M.


manpagesection(REPORT FILE ROTATION)
    Since s() only appends information to the report file, the report file's
size may eventually become prohibitively large, and log-rotation may be
desirable. It is of course possible to issue a tt(--terminate) command, rotate
the logfiles, and restart s(), but s() also offers a facility to temporarily
suspend integrity scans performed by a s() daemon process:
    itemization(
    it() Calling s() with the option tt(--suspend <uds>) suspends the
            daemon's integrity scans. If s() is
            actually performing a series of integrity scans when
            tt(--suspend) is issued, the currently executing command is first
            completed after which the tt(--suspend) command completes. Once
            the s() daemon has been suspended, automatic or explicit
            integrity scan requests are denied, and the daemon can only be
            instructed to resume its scanning tasks (s() --resume <uds>)
            or to terminate (s() --terminate <uds>).

    it() Once `s() tt(--suspend <uds>)' has returned, the report file
            may safely be rotated (using, e.g., bf(logrotate)(1)), and a new
            (empty) report file may optionally be created by the logrotation
            process.

    it() Once the log-rotation has been completed, the log-rotation process
            should issue the command `s() tt(--resume <uds>)'. This
            resumes the activities of a suspended s() daemon process,
            immediately performing the next integrity scan. Following this the
            s() daemon is back to its original integrity scanning mode.
    )
    Here is an example of bf(logrotate)(1) specification rotating s()
log-files:
        verb(
/root/stealth/clienthost/small/report /var/log/stealth/clienthost-small.log {
    daily
    rotate 4
    compress
    missingok
    copytruncate
    sharedscripts
    prerotate
        /usr/bin/stealth --suspend /root/stealth/client/small.uds
    endscript
    postrotate 
        /usr/bin/stealth --resume /root/stealth/client/small.uds
    endscript 
}
    )

manpagesection(RELOAD, RERUN AND TERMINATE)

    Here is what happens when s() is run using the third synopsis:

    itemization(
    it() When started as s() tt(--reload <uds>), the s() daemon process
        reloads its policy file and (if specified) tt(--skip-files)
        specification file. Next the s() daemon process performs a file
        integrity scan using the information in the re-read policy and
        skip-files files. S() can reload the (modified) contents of the
        originally specified policy- and skip-files names. If another policy
        and/or skip-files files must be used another s() process must be
        started, for which these new filenames are specified.

    it() When started as s() tt(--rerun <uds>), the s() daemon performs
        another scan (unless it has been suspended using s() tt(--suspend
        <uds>)).

    it() When started as s() tt(--terminate <uds>), the s() daemon is
        terminated.
    )

manpagesection(RSYSLOG FILTERING)

    includefile(../manual/running/rsyslog.yo)

manpagesection(DEPLOYMENT SUMMARY)
    The following summarizes the advised steps to perform when installing
    stealth. All these steps are elaborated upon in s()'s em(User Guide)
        (chapter em(Running `stealth')): 
    itemization(
    it() Install s() (e.g., use bf(dpkg)(1) to install the bf(.deb) file);
    it() Construct one or more policy files;
    it() Automate (re)starting s() using bf(cron)(1) or bf(ssh-cron)(1)
        (possibly calling bf(stealthcron));
    it() Set up automated log-file rotation, using, e.g., bf(stealthcleanup)
        and bf(logrotate)(1), defining one or more
        tt(/etc/logrotate.d/stealth...) configuration files.
    )

manpagefiles()

    tt(/usr/share/doc/stealth/);nl()
    the tt(policy) file;nl()
    files under the bf(BASE) directory as defined in the tt(policy) file;nl()
    the report file as defined by the policy's bf(USE REPORT) directive.

manpageseealso() 
   bf(cron)(1), bf(dd)(1), bf(diff)(1), bf(dpkg)(1), bf(find)(1),
    bf(logrotate)(1), bf(ls)(1), bf(mail)(1), bf(sha256sum)(1), bf(passwd)(5),
    bf(rsyslog)(1), bf(sendmail)(1), bf(sh)(1), bf(ssh)(1), bf(ssh-cron)(1)

manpagesection(DIAGNOSTICS)
       By default, executed commands are echoed to stderr. Use bf(-q) to
suppress this echoing.

manpagebugs()

    None reported

manpagesection(COPYRIGHT)
    This is free software, distributed under the terms of the `GNU General
Public License'. Copyright remains with the author. S() is found at
tt(https://fbb-git.gitlab.io/stealth/).

manpagesection(ORGANIZATION)
    University of Groningen.

manpageauthor()
    Frank B. Brokken (bf(f.b.brokken@rug.nl)).
