Codebase list stealth / ebeedda
Imported Upstream version 4.00.00 tony mancill 9 years ago
249 changed file(s) with 3357 addition(s) and 2838 deletion(s). Raw diff Collapse all Expand all
0 syslogstruct
1
02 msg
13
2 wait11 msg
4 util
35
4 util
56 stealthenums
67
7 options stealthenums msg util
8 options stealthenums syslogstruct msg util
89
9 policyfile options
10 runmode options
11 stealthlog options
10 policyfile options
1211
13 integrityscanner options policyfile stealthlog runmode
12 runmode stealthenums
1413
15 ipc options wait11
14 report policyfile
1615
17 stealth integrityscanner ipc stealthlog
16 integrityscanner policyfile runmode
17
18 logunit options
19
20 stealth logunit integrityscanner report
21
1822
1923
2024
00 // Specify the name of the project:
11 #define PROJECT "stealth"
22
3 // When defined, these overrule COMPILER and COMPILER_OPTIONS
4 // COMPILER and COMPILER_OPTIONS are now obsolete
5 // Instead of CXX and CXXFLAGS, CC and CFLAGS can be used.
6 // Their #define values are overruled by identically named environment
7 // variables.
3 // Compiler to use:
4 #define CXX "g++"
5 //#define CXX "g++-5"
86
9 #define CXX "g++"
10 // the compiler to use.
7 // The compiler options to use:
8 #define CXXFLAGS "--std=c++14 -Wall -O2 -pthread"
119
12 #define CXXFLAGS "--std=c++11 -Wall -O2 -pthread -g"
13 // the compiler options to use.
10 // Flags passed to the linker:
11 #define LDFLAGS "-lpthread"
1412
15 #define LDFLAGS "-lpthread"
16 // flags passed to the linker
13 // The following locations can be overruled by `build install' arguments
1714
18 // =========================================================================
19 // The following locations are overruled by `build install' arguments
15 // the full path of the final program
16 #define BINARY "/usr/bin/"${PROJECT}
2017
21 #define BINARY "/usr/bin/"${PROJECT}
22 // the full path of the final program
18 // the directory whre the manual page is stored
19 #define MAN "/usr/share/man/man1"
2320
24 #define MAN "/usr/share/man/man1"
2521 // the directory whre the manual page is stored
22 #define MANUAL "/usr/share/doc/"${PROJECT}"-doc/manual"
2623
27 #define MANUAL "/usr/share/doc/"${PROJECT}"-doc/manual"
28 // the directory whre the manual page is stored
24 // the directory where the standard documentation is stored
25 #define STD "/usr/share/doc/"${PROJECT}
2926
30 #define STD "/usr/share/doc/"${PROJECT}
31 // the directory where the standard documentation is stored
32
27 // the directory where the extra documentation is stored
3328 #define EXTRA "/usr/share/doc/"${PROJECT}"-doc"
34 // the directory where the extra documentation is stored
3529
3630
3731
0 With Stealth 4.00.00 existing policy files used with Stealth 3.00.00 can
1 remain as-is, although a run- or pid-file is no longer used. Instead, a Unix
2 Domain Socket is used for communication between a Stealth daemon and Stealth
3 running in IPC mode.
4
5 For cosmetic reasons consider using xxx.uds instead of xxx.run or xxx.pid.
6
7 Logrotate.d scripts should use the 'copytruncate' and 'sharedscripts' options
8 (see the man-page for an example). These options should have been used with
9 earlier Stealth versions too, but were overlooked until now (sorry about
10 that).
11
12 If access to the Unix Domain Socket defined by Stealth running in daemon mode
13 should be restricted, it can be defined in a directory with is only accessible
14 to the user running Stealth (this will often be the root-user).
0 Stealth: handles the integrity scan or handles the communication with a
1 running stealth daemon.
0 SyslogStruct: merely a struct containing the values of --syslog* options. It
1 is filled by Options and used by LogUnit
22
3 Options: singleton, prepares all options received either on the command
4 line or found in the policy file. Ends the program if incompatible
5 options were specified. Initialized by Stealth::Stealth()
3 Msg: m1..m3 insert messages, depending on verbosity level, into imsg,
4 mp writes to cout is used for messages related to parsing the
5 policy file. M1..m3 are global objects, inserting into imsg.
6 The Mstream objects imsg, wmsg and fmsg can also be used, the
7 latter two inserting into cout.
8
9 Util: Utility class offering members for making directories and
10 determining absolute file names from relative file specifications
11
12 StealthEnums: an otherwise empty struct, defining the enum Mode and the `Mode |
13 Mode' operator.
614
715 PolicyFile: analyzes and stores the information found in the first section of
8 the policy file (through its member 'reload').
16 the policy file (through its member 'reload'). The second section
17 (option specifications) are read by Options::loadPolicyOptions
918
10 Wait11: implements C++11 (timed) waiting for events, like receiving
11 signals, and sending notifications when they are received. The
12 actual signal handling is handled by the class Stealth itself.
13
14 IPC: handles the runfile (pid file): requests are written to the
15 runfile followed by signaling the daemon. All actual
16 waiting/notification steps are left to Wait11. signaling the
17 daemon is handled by its member 'signalDaemon'
19 Options: singleton, determines and validates all options received either on
20 the command line or found in the policy file. Ends the program if
21 incompatible options were specified. Initialized by Stealth's
22 constructor.
1823
1924 RunMode: keeps track of the currently active Stealth mode. A mode may also
2025 be queried, and the name of a mode can be requested. When a mode
21 is changed, setMode is used to update RunMode's mode.
26 is changed, setMode is used to update RunMode's mode. RunMode
27 objects are defined in Stealth, defining d_task for the currently
28 active mode, and d_pending for a requested (next) mode.
2229
23 StealthLog: Handles all logs. d_stealthLog in the Stealth object is a stream
24 into which log messages can be inserted.
30 Report: ostream responsible for inserting information into the REPORT
31 file. The object d_stealthReport is defined by the Stealth object.
2532
26 Msg: m1..m3 insert messages depending on verbosity level. mp is used
27 for messages related to parsing the policy file. These are global
28 objects. Other than the m-objects imsg, wmsg and fmsg can also be
29 used.
33 IntegrityScanner: performs the actual integrity scans. Called from
34 Stealth::integrityScan. Main public interface member: run().
3035
31 StealthEnums: struct StealthEnums is empty, defining the enum Mode and the
32 Mode | Mode operator.
36 LogUnit: handles all logged messages. Redefinable singleton, with no public
37 members other than LogUnit::init. See REAME.messages for
38 information about the way it operates.
3339
40 Stealth: handles the integrity scan or handles the communication with a
41 running stealth daemon.
42
43
44
0 Initially the running mode is INTEGRITY_SCAN. Options may change the
1 initial mode.
2
3 If the --daemon option was not requested, stealth runs as a forgeground
4 process. Unless --repeat is specified there is just one integrity scan after
5 which Stealth::processRequests terminates
6
7 Flow control is handled through IPC signals, in combination with information
8 written to the pid-file.
9
10 The first line of the PID file contains the pid of the daemon process.
11 A second line may be written by a stealth process requesting an action of the
12 daemon, followed by the pid of the process issuing the request. Requests are:
0 Stealth may run in one of three modes:
1
2 1. Foreground, where stealth performs one integrity scan and terminates;
3
4 2. Background, where stealth, after performing its initial integrity scan
5 waits for additional commands and/or performs additional integrity scans
6 after (possibly random) time intervals.
7
8 3. IPC, where stealth sends commands to a stealth daemon process.
9
10 Communication between stealth processes running in modes 2 and 3 is realized
11 through a unix domain socket, which is created by the stealth daemon process.
12
13 Figure documentation/images/communication.jpg shows the organization:
14
15 * Stealth --daemon starts the daemon process, its childprocess
16 (stealth/childprocess) starting the ipcInterface thread (separate
17 threads are shown in light green), implemented by the
18 stealth/ipcinterface function.
19
20 * ChildProcess is the main thread of the running stealth daemon. It
21 performs all the tasks (through stealth/doTasks).
22
23 DoChores performs some bookkeeping tasks, eventually passing control
24 to stealth/processrequests.
25
26 JobsHandler runs the current task, which may be an integrity
27 scan.
28
29 * IpcInterface is a separate thread preparing the next task for
30 jobsHandler. It creates the Unix domain server socket, and waits for
31 incoming request. Incoming requests are verified, and if OK they are
32 forwarded to jobsHandler. IpcInterface's mode of operation is
33 described in more detail below.
34
35 * Stealth-ipc processes handle ipc requests. These processes connect to
36 the stealth daemon's unix domain socket, passing it the received
37 request. It then waits for a reply from the daemon. If the daemon
38 reports an error the error message is shown, and stealth running in
39 ipc mode terminates with exit value 1. Otherwise exit value 0 is
40 returned and no additional output is shown.
41
42 Figure documentation/images/ipcinterface.jpg shows the inner workings of
43 the ipcInterface function.
44
45 * Each cycle of ipcInterface's main loop handles one incoming
46 connection. If a TERMINATE request is received, the ipcInterface
47 thread ends. A TERMINATE request also ends the main (jobsHandler)
48 thread. Once both threads have terminated the stealth daemon ends.
49
50 * Incoming requests are validated (by Stealth::incomingRequest), and (if
51 valid) initially stored in the local Runmode incoming, processing may
52 be suspended until processRequests is ready to accept the next command
53 (see below at nextTask's description).
54
55 * Incoming requests are validated. For each possible request a matching
56 ...request function handles the valiadation. If a request cannot be
57 granted (i.e., is invalid), an error message is sent to the
58 stealth-ipc process and another cycle starts.
59
60 Given a current task (mode of operation) the following requests are
61 valid:
62
63 ----------------------------------------------------------
64 Actual Job: Valid Incoming Request:
65 ----------------------------------------------------------
66 INTEGRITY_SCAN RELOAD, RERUN, SUSPEND, TERMINATE
67 RELOAD TERMINATE
68 SUSPEND RELOAD, RESUME, SUSPEND, TERMINATE
69 ----------------------------------------------------------
70
71 Requesting SUSPEND while in SUSPEND mode has no effect (validation
72 returns `nop'): in this case the stealth-ipc process is informed that
73 there is no error but processRequests doesn't actually receive a new
74 command to process
75
76 * If a request is valid, the incoming request is stored in
77 d_pending. Ongoing jobs may inspect d_pending to see whether they
78 should prematurely stop (e.g., when a TERMINATE request arrives while
79 an integrity scan is being executed, the scan will end after
80 completing the command currently being processed)
81
82 * Next, ipcInterface waits until jobsHandler is ready for the next task.
83 When ready, notifyTask sets the next task in d_task, and d_pending is
84 reset, after which jobsHandler is notified that it has another task to
85 handle.
86
87 * The next task may be TERMINATE. If so, ipcInterface ands (and
88 jobsHandler will also end).
89
90
91
92 The Stealth::jobsHandler function handles incoming requests. This function
93 loops until (at the end of the loop) the d_task has been set to TERMINATE. At
94 the top of the loop the next job is determined. Once determined, the
95 requested task starts.
96
97 Figure documentation/images/nextjob.jpg shows the inner workings of
98 Stealth::nextJob.
99
100 When returning from nextJob the d_job binary Semaphore has decayed to zero. It
101 is incremented again by ipcInterface once a command is requested by an
102 ipc-stealth process and by some of the task-handling functions (reload,
103 resume, rerun).
104
105 Since ipcInterface and some of the task-handling functions may set the next
106 command to process, the permission to set the next command is set by the d_ipc
107 semaphore. Once ipcInterface returns from d_ipc.wait() d_ipc blocks until it
108 is incremented by d_ipc.notify(). Initially d_ipc blocks, but it is
109 incremented by startScan and suspend.
110
111 When nextJob returns the next task has been set. This is realized as follows:
112
113 * If at daemon startup --repeat was not specified then nextJob simply
114 waits for a command which is received from an ipc-stealth process through
115 ipcInterface (alternatively, the command may be set by the mentioned
116 request-processing functions).
117
118 * time-limited wait: otherwise, nextJobs waits until either a command was
119 set (as with the plain wait), or until a (random) delay has passed.
120
121 * If no timeout occurred, then a command was specified and nextJob
122 returns with the next command.
123
124 * Otherwise, in suspend mode or while an integrity scan is still active,
125 nextJob loops back to the time-limited wait step.
126
127 * Otherwise, --repeat was specified, and the waiting time has passed, so
128 the next task automatically becomes INTEGRITY_SCAN (and nextJob
129 returns)
130
131
132 Integrity scans are performed by Stealth::integrityScan.
133
134
135
136
137
138 Flow control is handled by communicating through a Unix Domain Socket, which
139 uses the run-file. Requests are:
13140
14141 suspend,
15142 resume,
19146 and perform another integrity scan.
20147 terminate
21148
22 A request is written to the PID file, followed by sending the daemon a SIGUSR1
23 signal. When the daemon has completed the request it sends the requesting
24 process a SIGUSR1 signal;
149 Requests are received through the Unix domain socket defined by the run-file
150 the daemon performs the request and replies with an answer indicating
151 success or failure. Success is inferred when an empty line is received.
152 Failure information contains an indication of the nature of the failure.
153
154 Requests are passed to the daemon from the function Stealth::contactPeer.
155
156 | - the pid file is locked
157 | - the request is written to the pid-file
158 | - the pid file is unlocked.
159 |
160 | A request is written to the PID file, followed by sending the daemon a SIGUSR1
161 | signal. When the daemon has completed the request it sends the requesting
162 | process a SIGUSR1 signal;
25163
26164
27165 Stealth uses a RunMode object to keep track of its current mode of operation
28 and an IPC object to handle the inter process communication.
166 | now OBS? and an IPC object to handle the inter process communication.
167
168 The member Stealth::policyMode handles the actual commands.
169
170 policyMode:
171 ==============
172 policyMode forks if a Stealth should run as a daemon, in which case the
173 fork's child process performs the daemon's tasks, and the parent process
174 immediately finishes.
175
176 When a daemon starts its childProcess prepares the daemon (using
177 Fork::prepareDaemon), and the communication thread starts, defining the
178 unix domain server socket. Hereafter 'doTasks' starts.
179
180 communicator:
181 =============
182
183 The communicator creates the LocalServerSocket, and loops while d_run.mode()
184 is unequal TERMINATE. When a request arrives, the matching function is
185 called. These functions should return an empty string indicating that the
186 request can be handled. Otherwise the returned string contains an error
187 message which is returned to the requestor.
188
189 If the request can be handled d_chore is notified, and the communicator waits
190 for d_communicate to return, indicating that the request has been
191 handled. When d_communicate.wait() returns the contents of d_result is
192 returned to the requestor. Again: an empty string indicates that the request
193 was successfully processed.
194
195 doTasks:
196 =========
197
198 With foreground runs 'doTasks' is directly started.
29199
30200 The flow of control handling requests is defined in processRequests,
31 called from doChores. ProcessRequests defines a loop basically processing a
201 called from doTasks. ProcessRequests defines a loop basically processing a
32202 request and waiting for the next request ((waitForRequest)
33203
34204 The file integrity scan itself is handled by an IntegrityScanner object.
35205
36
37 Communications with the daemon use the run-file and signals SIGUSR1 (and
38 SIGTERM). The run-file by default contains the pid of the daemon process. The
39 signalling stealth process adds a request to the
40 file. The daemon reads the request and honors it if possible.
206 |
207 | Communications with the daemon use the run-file and signals SIGUSR1 (and
208 | SIGTERM). The run-file by default contains the pid of the daemon process. The
209 | signalling stealth process adds a request to the
210 | file. The daemon reads the request and honors it if possible.
211
212
213 processRequests:
214 ================
215
216 Stealth (when performing integrity scans) starts up with an initial mode
217 INTEGRITY_SCAN. At processRequests netTask() returns the next mode, which is
218 then processed by 'process'.
219
220 NextTask() inspects the current mode. If it's WAIT wait() is called, which
221
222
223
224 Possible task requests:
225 =======================
226 rerun: OK in mode WAIT
227 suspend: OK in mode SCAN, WAIT, SUSPEND
228 resume: OK in mode SUSPEND
229 reload: OK in mode SCAN, WAIT, SUSPEND
230 terminate: always OK.
231
232
0 Messages sent to m1, m2, and m3 (see ../msg) are sent to imsg.
1
2 LogUnit::setupLogs() creates an FBB::Log and FBB::SyslogSteam if requested so
3 by options.
4
5 It adds these files to an FBB::MultiStreambuf, and (if requested by --stdout)
6 also adds cout.
7
8 If any streams are stored, the MultiStreambuf is installed in imsg. Following
9 this, all messages inserted into imsg are sent to the requested log streams.
10
11 Fatal messages, sent to fmsg, are handled similarly:
12
13 A MultiStreambuf receives imsg, and optionally (when calling setupLogs(ostream
14 &report)) into the ostream which inserts messages into the Report object.
15
16 The stream received by setupLogs is itself a wrapper around the actual Report
17 object, and its streambuf is defined in stealth/stealth.ih: all text inserted
18 into fmsg is also sent to this wrapper ostream, which forwards its characters
19 to its streambuffer's overflow member. This member sends all its characters to
20 Stealth's d_report object. When the wrapper stream is flushed, it calls
21 d_report.mail(), to process d_report's info by mail.
22
23 LogUnit:
24 ========
25
26 SyslogStream --+
27 |
28 Log --+--> MultiStreambuf
29 | |
30 cout (with --stdout) --+ |
31 |
32 |
33 v
34 imsg.reset(...)
35 |
36 +----------+----------+
37 m1 m2 m3
38
39
40 imsg ----+
41 |
42 +--> MultiStreambuf
43 | |
44 report ----+ |
45 |
46 v
47 fmsg.reset(...)
48
49
50
51
00 #define AUTHOR "Frank B. Brokken (f.b.brokken@rug.nl)";
1 #define VERSION "3.00.00"
2 #define YEARS "2005-2014"
1 #define VERSION "4.00.00"
2 #define YEARS "2005-2015"
0 #!/usr/bin/icmake -qt/tmp/bisonc++
0 #!/usr/bin/icmake -qt/tmp/stealth
11
22 #include "icmconf"
33
5050 if (argv[2] == "strip")
5151 strip = "strip";
5252
53 if (option == "p")
54 {
55 system("tput clear");
56 system("icmbuild program strip");
57 exit(0);
58 }
59
5360 if (option == "program")
5461 {
5562 system("icmbuild program " + strip);
6370 exit(0);
6471 }
6572
66 printf("Usage: build [-p] what\n"
73 printf("Usage: build what\n"
6774 "Where `what' is one of:\n"
6875 " clean - clean up remnants of previous "
6976 "compilations\n"
7178 " library - build " PROJECT "'s library\n"
7279 " man - build the man-page (requires Yodl)\n"
7380 " manual - build the manual (requires Yodl)\n"
81 " p - build " PROJECT " after `tput clear' and\n"
82 " strip the executable)\n"
7483 " program [strip] - build " PROJECT " (optionally strip the\n"
7584 " executable)\n"
7685 " oxref [strip] - same a `program', also builds xref file\n"
0 stealth (4.00.00)
1
2 * Stealth 4.00.00 uses Unix Domain Sockets instead of signals to
3 communicatie with the stealth monitor running as a daemon.
4
5 * Previously required absolute file paths are no longer required. When
6 relative file paths are used with the Stealth daemon or with Stealth doing
7 an integrity scan as foreground process they are interpreted relatively to
8 the current working directory, or (when specified in the policy file)
9 relative to the USE BASE location. With Stealth running in IPC mode
10 relative file paths are interpreted relative to the directory in which
11 Stealth running in IPC mode was started.
12
13 * A README.flow file is provided with several separately provided
14 illustrative images in the directory documentation/images. Similarly:
15 README.messages describes the organization of log/mail message handling.
16
17 * Specifications for the logrotate specifications should use 'copytruncate'
18 and 'sharedscripts' (see the man-page for an example).
19
20 * share/usr/bin/stealthcron now specifies a Unix Domain Socket (usage not
21 changed).
22
23 * Fixed compilation errors that emerged with g++-5, reported by Matthias
24 Klose.
25
26 -- Frank B. Brokken <f.b.brokken@rug.nl> Sat, 07 Feb 2015 21:14:30 +0100
27
028 stealth (3.00.00)
129
230 * Version 3.00.00 completely reorganizes and refactors Stealth's
1313 manpagename(stealth)(Stealthy File Integrity Scanner)
1414
1515 manpagesynopsis()
16 s() --daemon pidfile --dry-run --log <path> --logmail+nl()
16 `<uds>' represents the location of the used Unix Domain Socket.nl()
17
18 s() --daemon <uds> --dry-run --log <file-spec> --logmail+nl()
1719 --max-size <size>[BKMG] --no-mail --parse-policy-file+nl()
1820 --random-interval <seconds> --repeat <seconds>nl()
19 --run-command <nr> --skip-files <path> --stdout --syslog+nl()
21 --skip-files <file-spec> --syslog+nl()
2022 --syslog-facility <fac> --syslog-priority <pri>
2123 --syslog-tag <tag>nl()
2224 --verbosity <value> policy
2325
24 s() {--reload,--rerun,--resume,--suspend,--terminate} pidfile
26 s() --dry-run --log <file-spec> --logmail+nl()
27 --max-size <size>[BKMG] --no-mail --parse-policy-file+nl()
28 --random-interval <seconds> --repeat <seconds>nl()
29 --run-command <nr> --skip-files <file-spec> --stdout --syslog+nl()
30 --syslog-facility <fac> --syslog-priority <pri>
31 --syslog-tag <tag>nl()
32 --verbosity <value> policy
33
34 s() {--reload,--rerun,--resume,--suspend,--terminate} <uds>
2535
2636 s() --help --version
2737
3242 quote(
3343 bf(SSH-based Trust Enforcement Acquired through a Locally Trusted Host.)
3444 )
35 s() is based on an idea by em(Hans Gankema) and em(Kees Visser), both at
45 S() is based on an idea by em(Hans Gankema) and em(Kees Visser), both at
3646 the Center for Information Technology of the University of Groningen. em(Hopko
3747 Meijering) provided valuable suggestions for improvement.
3848
39 s()'s main task is to perform file integrity tests. However, the
49 S()'s main task is to perform file integrity tests. However, the
4050 testing itself will leave no sediments on the tested computer. Therefore,
4151 s() has em(stealthy) characteristics. This is considered an
4252 important feature, improving the security (integrity) of the software of
4353 computers monitored by s().
4454
45 On the other hand, one should realize that s() intends to be just another
46 security tool: other security measures like firewalls, portscanners, intrusion
47 detection systems, dropping unencrypted protocols, etc. are usually required
48 to improve or promote the security of a group of computers that are connected
49 to the Internet.
50
51 s() uses a policy file to determine the actions to perform. Each
52 policy file is uniquely associated with a host to be tested. This host
55 Please realize that s() intends to be just another security tool: other
56 security measures like firewalls, portscanners, intrusion detection systems,
57 dropping unencrypted protocols, etc. are usually required to improve the
58 security of a group of computers that are connected to the Internet. S() is a
59 file integrity scanner, and file integrity scanners offer no substitute for
60 those tools (and vv.).
61
62 S() uses a policy file to determine the actions to perform. Each
63 policy file is uniquely associated with a host being monitored. This host
5364 (called the em(client) below) trusts the computer on which s() runs, called
54 the em(controller) (hence: a em(Locally Trusted Host)). The controller
65 the em(monitor) (hence: a em(Locally Trusted Host)). The monitor
5566 performs tasks (normally file integrity tests) that em(Enforce) the em(Trust)
5667 we have in the client computer. Since almost all integrity tests can be run
57 on the client, one controller can control many clients, even if the
58 controller itself uses aged hard- and software components.
59
60 As the controller and the client normally are different computers, the
61 controller must communicate with the client in a secure fashion. This is
62 realized using SSH. So, there's another element of `local trust' involved
63 here: the client should permit the controller to set up a secure SSH
64 connection allowing the controller to access sensitive files and private parts
65 of the client's file system.
66
67 bf(It is important to ensure that there is no public access to the
68 controller. All inbound services should be denied. The only access to
69 the controller should be via its console and the controller should be placed
70 in a physically secure location. Sensitive information of clients are stored
71 in the controller, and passwordless access to clients can be obtained from the
72 controller by anyone who gains (root)-access).
73
74 The controller itself normally only uses two kinds of outgoing services:
68 on the client, one monitor can control many clients, even if the
69 monitor itself uses aged hard- and software components.
70
71 As the monitor and the client are (i.e., should be) different computers, the
72 monitor must communicate with the client in a secure fashion. This is realized
73 through SSH. So, there's another element of `local trust' involved here: the
74 client should permit the monitor to set up a secure SSH connection allowing
75 the monitor to access sensitive elements in the client's file system.
76
77 bf(It is important to ensure that public access to the monitor is
78 prevented. No incoming services should be allowed. The only access to the
79 monitor should be via its console and the monitor should be placed in a
80 physically secure location. Sensitive information of clients are stored in the
81 monitor's file system. To access the clients s() in daemon mode can use a
82 passphrase-protected ssh-key, allowing s() to perform its tasks
83 thereafter. This, too, makes it important to prevent the monitor from being
84 accessed by unauthorized persons.)
85
86 If, instead of running s() in deamon mode it is preferred to let s() perform
87 single, but automated integrity scans, then new bf(ssh)(1) connections may be
88 difficult to establish if the used ssh-key is passphrase-protected. To
89 implement this scenario (i.e., automated integrity scans using passphrase
90 protected ssh-keys) the program bf(ssh-cron)(1) can profitably be used.
91
92 S()'s current way of connecting to clients uses a single bf(ssh)(1)
93 connection, which results in only a single bf(sshd)(1)
94 entry in the client's logfiles, which lasts for the duration of s()'s
95 run. When using s() in daemon mode this too minimizes the `footprint' s() has
96 on the client hosts.
97
98 The monitor itself normally only requires two types of outgoing services:
7599 bf(SSH) to reach its clients, and some mail transport agent (e.g.,
76100 bf(sendmail)(1)) to forward its outgoing mail to some mail-hub.
77101
78 Here is what happens when s() is run using the first synopsis:
102 Here is what happens when s() running using the first synopsis:
79103 itemization(
80 it() First, the em(policy) file is read. This determines the actions to be
81 performed, and the values of several variables that are used by s().
82
83 it() If the command-line option tt(--daemon pidfile) is specified, s()
84 runs as a backgrond process, writing its process id in the file tt(pifile).
85
86 With tt(--repeat <seconds>) the scan is rerun every tt(<seconds>) seconds. The
87 number of seconds until the next rerun is restricted by s() to a value of at
88 least 60. However, using the tt(--rerun pidfile) option a daemon s() another
89 integrity scan can be requested after a shorter interval.
90
91 When tt(--daemon) is specified the scan is performed just once, whereafter
92 s() waits until another integrity scan is requested using the
93 s() tt(--rerun pidfile) invokation
94
95 it() Next, the controller opens a command shell on the client using
96 bf(ssh)(1), and a command shell on itself using bf(sh)(1).
104 it() First, the em(policy) file is read. For each client a policy file is
105 defined, specifying the actions to be performed, and specifying the values of
106 several variables used by s().
107
108 it() If the command-line option tt(--daemon <uds>) is specified, s()
109 runs as a daemon process, using the Unix Domain Socket (tt(<uds>)) for
110 communication with s() processes running in IPC mode.
111
112 If access to the Unix Domain Socket defined by Stealth running in daemon mode
113 should be restricted, it can be defined in a directory with is only accessible
114 to the user running Stealth (this will often be the root-user).
115
116 When running in daemon mode, tt(--repeat <seconds>) may be specified to rerun
117 the integrity scan every tt(<seconds>) seconds. If an integrity scan is being
118 performed when, according to the repeat interval the next integrity scan is
119 due, then the current scan is first completed. Once completed, the next
120 integrity scan will be performed after tt(seconds) seconds.
121
122 it() Next, the monitor opens a command shell on the client using
123 bf(ssh)(1), and a command shell on the monitor computer itself using
124 bf(sh)(1).
97125
98126 it() Once the command shells are available, commands defined in the policy
99127 file are executed in their order of appearance. Examples are given
100128 below. Normally, return values of the programs are tested. When return values
101 are tested s() terminates when a non-zero return
102 value is received. If this happens, a message stating the
103 reason why s() terminated is written to the report file (and into the mail
104 message sent by s()). In some cases (e.g., when the report file could not be
105 written), the message is written to the standard error stream.
106
107 it() In most cases, integrity tests can be controlled using the
108 bf(find)(1) program, calling programs like bf(ls)(1), bf(sha1sum)(1) or its
109 own tt(-printf) method to produce file-integrity related statistics. Most of
110 these programs write file names at the end of generated lines. This
111 characteristic is used by an internal routine of s() to detect changes in the
112 generated output, which could indicate some harmful intent, like an installed
113 em(root-kit).
129 are to be tested s() terminates when a non-zero return value is sensed. If
130 this happens, a message stating the reason why s() terminated is written to
131 the report file (and into the mail sent by s()). In some cases (e.g., when the
132 report file could not be written), the message is written to the standard
133 error stream.
134
135 it() Very often integrity tests can be controlled using bf(find)(1),
136 calling programs like bf(ls)(1), bf(sha256sum)(1) or its own tt(-printf)
137 method to produce file-integrity related statistics. Most of these programs
138 write file names at the end of generated lines. This characteristic is used by
139 one of s()'s internal routines to detect changes in the generated output. Such
140 changes could indicate some harmful intent, like an installed em(root-kit).
114141
115142 it() When changes are detected, they are logged in a em(report file), to
116143 which information is always appended. S() never reduces the report file's size
117 or rewrites its contents. Whenever information is added to the report file
118 (exceeding a plain time stamp) the appended information is e-mailed to a
119 configurable e-mail address for further (human) processing. Usually the e-mail
120 is sent to the systems manager of the tested client. S() follows the `dark
121 cockpit' approach in the sense that no mail is sent when no changes were
122 detected.
123
124 it() When the tt(--repeat) or tt(--rerun) options are issued, the report
125 file should not be rotated by, e.g., a log-rotating process, but the report
126 file may safely be rotated between a pair of tt(--suppress) and tt(--resume)
127 commands.
128 )
129
130 manpagesection(REPORT FILE ROTATION)
131 Since s() only appends information to the report file, the report file's
132 size may eventually become prohibitively large, and log-rotation may be
133 desirable. It is of course possible to issue a tt(--terminate) command, rotate
134 the logfiles, and restart s(), but s() also offers a facility to temporarily
135 suspend integrity scans performed by a s() daemon process:
136 itemization(
137 it() Calling s() with the option tt(--suspend <pidfile>) suspends the
138 daemon's integrity scans. If s() is
139 actually performing a series of integrity scans when
140 tt(--suspend) is issued, the currently executing command is first
141 completed after which the tt(--suspend) command completes. Once
142 the s() daemon has been suspended, automatic or explicit
143 integrity scan requests are denied, and the daemon can only be
144 instructed to resume its scanning tasks (s() --resume <pidfile>)
145 or to terminate (s() --terminate <pidfile>).
146
147 it() Once `s() tt(--suspend <pidfile>)' has returned, the report file
148 may safely be rotated (using, e.g., bf(logrotate)(1)), and a new
149 (empty) report file may optionally be created by the logrotation
150 process.
151
152 it() Once the log-rotation has been completed, the log-rotation process
153 should issue the command `s() tt(--resume <pidfile>)'. This
154 resumes the activities of a suspended s() daemon process,
155 immediately performing the next integrity scan. Following this the
156 s() daemon is back to its original integrity scanning mode.
157 )
158 Here is an example of bf(logrotate)(1) specification rotating s()
159 log-files:
160 verb(/root/stealth/host/report {
161 weekly
162 rotate 12
163 compress
164 missingok
165 prerotate
166 /usr/bin/stealth --suppress /run/stealth.host
167 endscript
168 postrotate
169 /usr/bin/stealth --resume /run/stealth.host
170 endscript
171 })
172
173 manpagesection(RELOAD, RERUN AND TERMINATE)
174
175 Here is what happens when s() is run using the second synopsis:
176 itemization(
177 it() When started as s() tt(--reload <pidfile>), the s() daemon process
178 reloads its policy file and (if specified) tt(--skip-files)
179 specification file. Next the s() daemon process performs a file
180 integrity scan using the information in the re-read policy and
181 skip-files files. S() can reload the (modified) contents of the
182 originally specified policy- and skip-files names. If another policy
183 and/or skip-files files must be used another s() process must be
184 started, for which these new filenames are specified.
185
186 it() When started as s() tt(--rerun <pidfile>), the s() daemon performs
187 another scan (unless it has been suspended using s() tt(--suspend
188 <pidfile>)).
189
190 it() When started as s() tt(--terminate pidfile), the s() daemon is
191 terminated.
192 )
193
194 manpagesection(OPEN SSH LINK TO CLIENTS)
195
196 Once s() is started as a foreground or daemon process performing file
197 integrity scans one one bf(ssh)(1) connection is opened to the client. This
198 connection remains active during s()'s lifetime to minimize the number of
199 bf(sshd) entries caused by s() in the client's log files.
144 or rewrites its contents. When information is added to the report file (beyond
145 a plain time stamp) the newly added information is e-mailed to a configurable
146 e-mail address for further (human) processing. Usually the e-mail is sent to
147 the systems manager of the tested client. S() follows the `dark cockpit'
148 approach in the sense that no mail is sent when no changes were detected.
149
150 it() Report and other log-files may safely be rotated between a pair of
151 tt(--suppress) and tt(--resume) commands (see below at the section `REPORT
152 FILE ROTATION').
153 )
154
155 If s() should not be run as a daemon process the second synopsis can be
156 used. In this case s() performs one or more integrity scans (the latter when
157 the tt(--repreat) option was specified). When a single integrity scan is
158 requested s() terminates after the scan. When tt(--repeat) is specified s()
159 shows a prompt (i.e., `tt(? )') and terminates after pressing the
160 tt(Enter)-key.
161
162 The third synopsys is used for communication with a s() daemon. In this case
163 the the Unix Domain Socket defined by the s() daemon process must be
164 specified after the option specifying the requested command.
165
166 manpagesection(OPTIONS)
167
168 includefile(../manual/running/options.yo)
169
170 manpagesection(OPEN SSH LINK TO CLIENTS)
171
172 Once s() has started as a foreground or daemon process performing file
173 integrity scans bf(ssh)(1) is used to connect to the client(s)
174 monitored by s(). While s() runs only one bf(ssh)(1) connection is opened to
175 each client. This connection remains active during s()'s lifetime to minimize
176 the number of bf(sshd) entries in the client's log files.
200177
201178 nsect(THE POLICY FILE)
202179
207184 directives) (starting with the keyword bf(USE)) and em(commands). Blank lines
208185 and information beyond hash-marks (#) are ignored, while lines following lines
209186 terminating in backslashes (\) are concatenated (em(en passant) removing these
210 trailing backslashes). Initial white space on lines of the policy file is
187 trailing backslashes). Leading white space on lines of the policy file is
211188 ignored.
212189
213190 The (optional) second section starts at a line merely containing
214 tt(%%). Following this separating line long option specifications can be
215 entered (see below at section bf(OPTIONS)).
191 tt(%%). Following this separating line several long option specifications can
192 be entered (see below at section bf(OPTIONS)). Options specified on the
193 command-line take priority over options specified in the policy file. Although
194 the tt(--reload) option reloads the policy file, it will not change option
195 values originally specified as command-line options. This section may contain
196 specifications of the tt(skip-files) and tt(log) options. Relative file
197 locations specified for these options are interpreted relative to the location
198 of the policy file. E.g., if the policy file argument is specified as
199 tt(/root/client/policy) then the specification tt(log: client.log) results in
200 s() writing its logs into the file tt(/root/client/client.log).
201
216202
217203 nsect(DEFINE DIRECTIVES)
218204
219205 bf(DEFINE) directives are used to associate longer strings of text with
220206 certain symbols. E.g., after
221 tt(DEFINE FINDARGS -xdev -type f -exec /usr/bin/sha1sum {} \;)
207 tt(DEFINE FINDARGS -xdev -type f -exec /usr/bin/sha256sum {} \;)
222208 the specification tt(${FINDARGS}) may be used in bf(USE DIRECTIVES) and
223209 bf(commands) (see below) to use the text associated with the bf(FINDARGS)
224210 symbol.
234220 preserved). Specifications in angular brackets (like tt(<this>)) represent
235221 specifications to be provided by s()'s users:
236222 itemization(
237 it() bf(USE BASE) tt(<base-irectory>)nl()
223 it() bf(USE BASE) tt(<base-directory>)nl()
238224 bf(BASE) defines the directory from where s() operates. All subsequent
239 relative path specifications are interpreted relative to bf(BASE). em(By
240 default) this is the directory where s() was started. nl()
225 relative path specifications in the policy file (including relative path
226 specifications in the policy's second part) are interpreted relative to
227 bf(BASE). em(By default) this is the directory where s() was started. nl()
241228 bf(BASE) and other non-existing paths are created automatically by
242229 s() if not yet existing.nl()
243230 Example:nl()
246233 it() bf(USE DD) tt(<dd>)nl()
247234 The bf(DD) specification uses tt(/bin/dd) as default, and defines the
248235 location of the bf(dd)(1) program, both on the server and on the client. The
249 bf(DD) program is used to copy files between the client and the controller
236 bf(DD) program is used to copy files between the client and the monitor
250237 over the existing ssh-connection. The program specified here is only used by
251238 s() when executing tt(PUT) and tt(GET) commands (described below).nl()
252239 Example showing the default:nl()
254241
255242 it() bf(USE DIFF) tt(<diff>)nl()
256243 The default bf(DIFF) specification uses tt(/usr/bin/diff),
257 and defines the location of the bf(diff)(1) program on the controller. The
244 and defines the location of the bf(diff)(1) program on the monitor. The
258245 bf(diff)(1) program is used to compare a formerly created logfile of an
259246 integrity check with a newly created logfile.nl()
260247 Example showing the default:nl()
274261 report of the integrity scan of the client. The `dark cockpit' philosophy is
275262 followed here: mail is only sent when a modification is detected.nl()
276263 Example showing the default (apparently an email address on the
277 controller):nl()
264 monitor):nl()
278265 tt(USE EMAIL root)
279266
280267 it() bf(USE MAILER) tt(<mailer>)nl()
307294 quote in a string that itself is delimted by double quotes; use tt(\') to use
308295 a single quote in a string that itself is delimted by single quotes.
309296
310 it() bf(USE REPORT) tt(<reportfile>)nl()
297 it() bf(USE REPORT) tt(<file-spec>)nl()
311298 bf(REPORT) defines the name of the reportfile. Information is always
312299 appended to this file. At each s() integrity scan a em(time marker line) is
313300 written to the report file. Only when (in addition to the marker line)
314301 additional information is appended to the report file the added contents of
315302 the report file are mailed to the mail address specified in the bf(USE EMAIL)
316 specification.nl()
303 specification. When a relative file specification is used it is interpreted a
304 location relative to the tt(USE BASE) specification.nl()
317305 Example showing the default:nl()
318306 tt(USE REPORT report)
319307
320308 it() bf(USE SH) tt(<sh>)nl()
321309 The bf(SH) specification uses tt(/bin/sh) as default, and defines the
322 command shell used by the controller to execute commands on itself.nl()
310 command shell used by the monitor to execute commands on itself. This must be
311 an absolute path specification.nl()
323312 Example showing the default:nl()
324313 tt(USE SH /bin/sh)
325314
326315 it() bf(USE SSH) tt(<user>)nl()
327316 bf(The SSH specification has no default), and em(must) be
328 specified. Assuming the client em(trusts) the controller (which is, after all,
329 what this program is all about; so this should not be a very strong
330 assumption), preferably the public ssh-identity key of the controller should
331 be placed in the client's root tt(.ssh/authorized_keys) file, granting the
332 controller root access to the client. Root access is normally needed to gain
333 access to all directories and files of the client's file system.
334
335 In practice, connecting to a account using the bf(sh)(1) shell is
317 specified. This must be an absolute path specification.
318
319 Assuming the client em(trusts) the monitor (which is after all what this
320 program is all about, so this should not be a very strong assumption),
321 preferably the public ssh key of the monitor should be placed in the
322 client's root tt(.ssh/authorized_keys) file, granting the monitor root access
323 to the client. Root access is normally needed to gain access to all
324 directories and files of the client's file system.
325
326 In practice, connecting to an account using the bf(sh)(1) shell is
336327 preferred. When another shell is already used by that account, one should make
337 sure that that shell doesn't define its own redirections for standard input
328 sure that its shell doesn't define its own redirections for standard input
338329 and standard output. One way to accomplish that is for force the execution of
339330 tt(/bin/sh) in the bf(USE SSH) specification.
340331 Examples:
341332 verb( # root's shell is /bin/sh:
342333 USE SSH root@client -T -q
343 # root uses another shell
334 # root uses another shell, but the use of /bin/bash is forced:
344335 USE SSH root@client -T -q exec /bin/bash
345336 # an alternative:
346337 USE SSH root@client -T -q exec /bin/bash --noprofile)
347338 )
348339
349 In some installations s() is used to inspect the computer itself, even
350 though this is em(not) recommended, as it breaks one of the main reasons
351 for s()'s existence. In situations where s() is used to monitor the integrity
352 of the tt(localhost), tt(/bin/bash) could be specified with the tt(USE SSH)
353 directive. For example:
340 In some installations s() is used to inspect the monitor itself, even
341 though this is em(not) recommended, as it breaks one of the main reasons for
342 s()'s existence. But in those situations (so, where s() is used to monitor the
343 integrity of the tt(localhost)), tt(/bin/bash) could be specified at the
344 tt(USE SSH) directive. For example:
354345 verb( # For stealth inspecting localhost:
355346 USE SSH /bin/bash --noprofile)
356347
379370 Example:nl()
380371 tt(LABEL Inspecting files in /etc\nIncluding subdirectories)nl()
381372 tt(LABEL) nl()
382 (In this example the latter bf(LABEL) specification erases the former
383 label text).
373 (In this example the former bf(LABEL) specification is erased by the
374 latter bf(LABEL) command).
384375 )
385376
386377 nsect(LOCAL COMMANDS)
387378
388 bf(LOCAL) commands are executed on the controller itself:
379 bf(LOCAL) commands are executed on the monitor itself:
389380 itemization(
390381 it() bf(LOCAL) tt(<command>)nl()
391 Execute tt(command) on the controller, using the bf(SH) command
382 Execute tt(command) on the monitor, using the bf(SH) command
392383 shell. The command must succeed (i.e., must return a zero exit value). nl()
393384 Example:nl()
394 tt(LOCAL scp rootsh@client:/usr/bin/sha1sum /tmp)nl()
395 This command copies the client's bf(sha1sum)(1) program to the
396 controller.
385 tt(LOCAL scp rootsh@client:/usr/bin/sha256sum /tmp)nl()
386 This command copies the client's bf(sha256sum)(1) program to the
387 monitor.
397388
398389 it() bf(LOCAL NOTEST) tt(<command>)nl()
399 Execute tt(command) on the controller, using the bf(SH) command
390 Execute tt(command) on the monitor, using the bf(SH) command
400391 shell. The command may or may not succeed.nl()
401392 Example:nl()
402393 tt(LOCAL NOTEST mkdir /tmp/subdir)nl()
403 This command creates tt(/tmp/subdir) on the controller. The command fails
394 This command creates tt(/tmp/subdir) on the monitor. The command fails
404395 if the directory cannot be created, but this does not terminate s().
405396
406 it() bf(LOCAL CHECK) [bf(LOG =)] tt(<logfile> [pathOffset] <command>)nl()
407 Execute tt(command) on the controller, using the bf(SH) command
397 it() bf(LOCAL CHECK) [bf(LOG =)] tt(<file-spec> [pathOffset]
398 <command>)nl()
399 Execute tt(command) on the monitor, using the bf(SH) command
408400 shell. The command must succeed. The output of this command is compared to the
409401 output of this command generated during the previous integrity check run by
410 s().
411
412 The phrase bf(LOG =) is optional. tt(PathOffset) is also
413 optional. If specified it defines the (0-based) offset where path-names of
414 inspected files start in lines produced by tt(<command>). By default s()
415 assumes that the first occurrence of a forward slash defines the first
416 character of the path-names of inspected files.
402 s().
403
404 The phrase bf(LOG =) is optional. When a relative file location is
405 specified at tt(<file-spec>) it is interpreted relatively to the tt(USE BASE)
406 path specification.
407
408 tt(PathOffset) is also optional. If specified it defines the (0-based)
409 offset where path-names of inspected files start in lines produced by
410 tt(<command>). By default s() assumes that the first occurrence of a forward
411 slash defines the first character of the path-names of inspected files.
417412
418413 For example, if diff-output looks like this:
419414 verb( 01234567890123456789012345678901234567890 (column offsets)
434429 (UTC) datetime-stamp at the time s() was run.
435430
436431 Note that eventually many tt(logfile.YYMMDD-HHMMSS) files could be
437 created: It is up to the controller's systems manager to decide what to do
432 created: It is up to the monitor's systems manager to decide what to do
438433 with old datetime-stamped logfiles.
439434
440435 The tt(logfile) specifications may use relative and absolute paths. When
443438 are created first.
444439
445440 Example:nl()
446 tt(LOCAL CHECK LOG = local/sha1sum sha1sum /tmp/sha1sum)nl()
447 This command checks the SHA1 sum of the tt(/tmp/sha1sum) program. The
448 resulting output is saved at bf(BASE)tt(/local/sha1sum). The program must
449 succeed (i.e., tt(sha1sum) must return a zero exit-value).
441 tt(LOCAL CHECK LOG = local/sha256sum sha256sum /tmp/sha256sum)nl()
442 This command checks the SHA256 sum of the tt(/tmp/sha256sum) program. The
443 resulting output is saved at bf(BASE)tt(/local/sha256sum). The program must
444 succeed (i.e., tt(sha256sum) must return a zero exit-value).
450445
451446 it() bf(LOCAL NOTEST CHECK) tt(<logfile> [pathOffset] <command>)nl()
452 Execute tt(command) on the controller, using the bf(SH) command
447 Execute tt(command) on the monitor, using the bf(SH) command
453448 shell. The command may or may not succeed. Otherwise, the command performs
454449 exactly like the bf(LOCAL CHECK ...) command, discussed above.
455450
456451 Example:nl()
457 tt(LOCAL NOTEST CHECK LOG=local/sha1sum sha1sum /tmp/sha1sum)nl()
458 This command checks the SHA1 sum of the tt(/tmp/sha1sum) program. The
459 resulting output is saved at bf(BASE)tt(/local/sha1sum). The program must
460 succeed (i.e., tt(sha1sum) must return a zero exit-value).
452 tt(LOCAL NOTEST CHECK LOG=local/sha256sum sha256sum /tmp/sha256sum)nl()
453 This command checks the SHA256 sum of the tt(/tmp/sha256sum) program. The
454 resulting output is saved at bf(BASE)tt(/local/sha256sum). The program must
455 succeed (i.e., tt(sha256sum) must return a zero exit-value).
461456 )
462457
463458 Note that the bf(scp)(1) command can be used to copy files between the
464 client and the controller, using a local command. This, however, is
459 client and the monitor, using a local command. This, however, is
465460 discouraged, as a separate bf(ssh)(1)-connection is required for each separate
466461 bf(scp)(1) command. This subtlety was brought to the author's attention by
467462 Hopko Meijerink (tt(h.meijering@rug.nl)).
468463
469 New bf(ssh)(1) connections may be difficult to establish if the used
470 ssh-key is passphrase-protected (but it is not impossible to do so, see e.g.,
471 bf(ssh-cron)(1)), and using an ssh-key without a passphrase is discouraged as
472 client computers are immediagely compromised too, once the controller is
473 compromised. Furthermore, using bf(scp)(1) results in several additional
474 entries showing bf(sshd)(1) connections in the client's logfiles, which in
475 turn may disclose information that the client is intensively monitored.
476
477 To copy files between the client and the controller, the tt(GET) and
464 To copy files between the client and the monitor, the tt(GET) and
478465 tt(PUT) commands (described below) should be used instead, as these commands
479466 use the existing bf(ssh)(1) connection. In general, tt(LOCAL) commands should
480467 not be used to establish additional bf(ssh)(1) connections to a client.
489476 intended program.
490477
491478 Two special remote commands are tt(GET) and tt(PUT), which can be used to
492 copy files between the client and the controller. Internally, tt(GET) and
479 copy files between the client and the monitor. Internally, tt(GET) and
493480 tt(PUT) use the tt(DD) specification. If a non-default specification is
494481 used, one should ensure that the alternate program accepts bf(dd)(1)'s tt(if=,
495482 of=, bs=) and tt(count=) options. With tt(GET) the options tt(bs=, count=) and
501488 itemization(
502489 it() bf(GET) tt(<client-path> <local-path>)nl()
503490 Copy the file indicated by tt(client-path) at the client to tt(local-path)
504 at the controller. tt(client-path) must be the full path of an existing file
505 on the client, tt(local-path) may either be a local directory, in which case
506 the client's file name is used, or another file name may be specified, in
491 at the monitor. Here, tt(client-path) must be the full path of an existing
492 file on the client, tt(local-path) may either be a local directory, in which
493 case the client's file name is used, or another file name may be specified, in
507494 which case the client's file is copied to the specified local filename. If the
508495 local file already exists, it is overwritten by the copy-procedure.
509496
510497 Example:nl()
511 tt(GET /usr/bin/sha1sum /tmp)nl()
512 The program tt(/usr/bin/sha1sum), available at the client, is copied to the
513 controller's tt(/tmp) directory. If, for whatever reason, copying fails, then
498 tt(GET /usr/bin/sha256sum /tmp)nl()
499 The program tt(/usr/bin/sha256sum), available at the client, is copied to the
500 monitor's tt(/tmp) directory. If, for whatever reason, copying fails, then
514501 s() terminates.
515502
516503 it() bf(GET NOTEST) tt(<client-path> <local-path>)nl()
517504 Copy the file indicated by tt(client-path) at the client to tt(local-path)
518 at the controller. tt(client-path) must be the full path of an existing file
519 on the client, tt(local-path) may either be a local directory, in which case
520 the client's file name is used, or another file name may be specified, in
505 at the monitor. Again, tt(client-path) must be the full path of an existing
506 file on the client, tt(local-path) may either be a local directory, in which
507 case the client's file name is used, or another file name may be specified, in
521508 which case the client's file is copied to the specified local filename. If the
522509 local file already exists, it is overwritten by the copy-procedure.
523510
524511 Example:nl()
525 tt(GET NOTEST /usr/bin/sha1sum /tmp)nl()
526 The program tt(/usr/bin/sha1sum), available at the client, is copied to the
527 controller's tt(/tmp) directory. Remaining commands in the policy file are
512 tt(GET NOTEST /usr/bin/sha256sum /tmp)nl()
513 The program tt(/usr/bin/sha256sum), available at the client, is copied to the
514 monitor's tt(/tmp) directory. Remaining commands in the policy file are
528515 executed, even if the copying process wasn't successful.
529516 )
530517
531518 The tt(PUT) command may be used as follows:
532519 itemization(
533520 it() bf(PUT) tt(<local-path> <remote-path>)nl()
534 Copy the file indicated by tt(local-path) at the controller to
521 Copy the file indicated by tt(local-path) at the monitor to
535522 tt(remote-path) at the client. The argument tt(local-path) must be the
536 full path of an existing file on the controller. The argument tt(remote-path)
523 full path of an existing file on the monitor. The argument tt(remote-path)
537524 must be the full path to a file on the client. If the remote file already
538525 exists, it is overwritten by tt(PUT).
539526
540527 Example:nl()
541 tt(PUT /tmp/sha1sum /usr/bin/sha1sum)nl()
542 The program tt(/tmp/sha1sum), available at the controller, is copied to the
543 client as tt(usr/bin/sha1sum). If the copying fails, bf(stealth) terminates.
528 tt(PUT /tmp/sha256sum /usr/bin/sha256sum)nl()
529 The program tt(/tmp/sha256sum), available at the monitor, is copied to the
530 client as tt(usr/bin/sha256sum). If the copying fails, bf(stealth) terminates.
544531
545532 it() bf(PUT NOTEST) tt(<local-path> <remote-path>)nl()
546 Copy the file indicated by tt(local-path) at the controller to
533 Copy the file indicated by tt(local-path) at the monitor to
547534 tt(remote-path) at the client. The argument tt(local-path) must be the
548 full path of an existing file on the controller. The argument tt(remote-path)
535 full path of an existing file on the monitor. The argument tt(remote-path)
549536 must be the full path to a file on the client. If the remote file already
550537 exists, it is overwritten by tt(PUT).
551538
552539 Example:nl()
553 tt(PUT NOTEST /tmp/sha1sum /usr/bin/sha1sum)nl()
554 Copy the file indicated by tt(local-path) at the controller to
540 tt(PUT NOTEST /tmp/sha256sum /usr/bin/sha256sum)nl()
541 Copy the file indicated by tt(local-path) at the monitor to
555542 tt(remote-path) at the client. The argument tt(local-path) must be the full
556 path of an existing file on the controller. The argument tt(remote-path) must
543 path of an existing file on the monitor. The argument tt(remote-path) must
557544 be the full path to a file on the client. If the remote file already exists,
558545 it is overwritten by tt(PUT). Remaining commands in the policy file are
559546 executed, even if the copying process wasn't successful.
567554
568555 The following commands are available for execution on the client:
569556 itemization(
570 it() tt(<command>)nl()
571 Execute tt(command) on the client, using the bf(SSH) command
572 shell. The command must succeed (i.e., must return a zero exit
573 value). However, any output generated by the the command is ignored. nl()
557 it() tt(<command-path>)nl()
558 Execute tt(command-path) on the client using the bf(SSH) command shell
559 (it is strongly advised to specify a full path to the command to execute). The
560 command must succeed (i.e., must return a zero exit value). However, any
561 output generated by the the command is ignored. nl()
574562 Example:nl()
575563 tt(/usr/bin/find /tmp -type f -exec /bin/rm {} \;)nl()
576 This command will remove all ordinary files in and below the client's
564 This command removes all ordinary files in and below the client's
577565 tt(/tmp) directory.
578566
579 it() bf(NOTEST) tt(<command>)nl()
580 Execute tt(command) on the client, using the bf(SSH) command
567 it() bf(NOTEST) tt(<command-path>)nl()
568 Execute tt(command-path) on the client, using the bf(SSH) command
581569 shell. The command may or may not succeed.nl()
582570 Example:nl()
583571 tt(NOTEST /usr/bin/find /tmp -type f -exec /bin/rm {} \;)nl()
584572 Same as the previous command, but this time the exit value of
585573 tt(/usr/bin/find) is not interpreted.
586574
587 it() bf(CHECK) [bf(LOG =)] tt(<logfile> [pathOffset] <command>)nl()
588 Execute tt(command) on the client, using the bf(SSH) command
589 shell. The phrase bf(LOG = ) is optional. The tt([pathOffset]) specification
590 is also optional, and has the same meaning as for the tt(LOCAL CHECK) command,
591 described above. The command must succeed. The output of this command is
592 compared to the output of this command generated during the previous run of
593 s(). Any differences are written to bf(REPORT). If differences were found, the
594 existing tt(logfile) name is renamed to tt(logfile.YYMMDD-HHMMSS), with
595 tt(YYMMDD-HHMMSS) the datetime-stamp at the time s() was run.
575 it() bf(CHECK) [bf(LOG =)] tt(<file-spec> [pathOffset]
576 <command-path>)nl()
577 Execute tt(command-path) on the client, using the bf(SSH) command
578 shell.
579
580 The phrase bf(LOG =) is optional. When a relative file location is
581 specified at tt(<file-spec>) it is interpreted relatively to the tt(USE BASE)
582 path specification.
583
584 tt(PathOffset) is also optional, and has the same meaning
585 as for the tt(LOCAL CHECK) command, described above. The command must
586 succeed. The output of this command is compared to the output of this command
587 generated during the previous run of s(). Any differences are written to
588 bf(REPORT). If differences were found, the existing tt(logfile) name is
589 renamed to tt(logfile.YYMMDD-HHMMSS), with tt(YYMMDD-HHMMSS) the
590 datetime-stamp at the time s() was run.
596591
597592 Note that the command is executed on the client, but the logfile is kept
598 on the controller. This command represents the core of the method implemented
593 on the monitor. This command represents the core of the method implemented
599594 by s(): there will be no residues of the actions performed by s() on
600595 the client computers.
601596
612607 bf(BASE)tt(/remote/ls.root).
613608
614609
615 tt(CHECK remote/sha1.root \)nl()
610 tt(CHECK remote/sha256.root \)nl()
616611 tt( /usr/bin/find / \)nl()
617 tt( -xdev -perm /6111 -type f -exec /usr/bin/sha1sum {} \;)
618
619 The SHA1 checksums of all suid/gid/executable files on the same device as
612 tt( -xdev -perm /6111 -type f -exec /usr/bin/sha256sum {} \;)
613
614 The SHA256 checksums of all suid/gid/executable files on the same device as
620615 the root-directory (/) on the client computer are determined. The resulting
621 listing is written on the file bf(BASE)tt(/remote/sha1.root).
622
623 it() bf(NOTEST CHECK) [bf(LOG =)] tt(<logfile> [pathOffset] <command>)nl()
624 Execute tt(command) on the client, using the bf(SSH) command
625 shell. The phrase bf(LOG =) is optional. The tt([pathOffset]) is also
626 optional, and has the same meaning as for the tt(LOCAL CHECK) command,
627 described above. The command may or may not succeed. Otherwise, the program
628 acts identically as the bf(CHECK ...) command, described above.
629
630 Example:nl()
631 tt(NOTEST CHECK LOG = remote/sha1.root \)nl()
616 listing is written on the file bf(BASE)tt(/remote/sha256.root).
617
618 it() bf(NOTEST CHECK) [bf(LOG =)] tt(<file-spec> [pathOffset]
619 <command-path>)nl()
620 Execute tt(command-path) on the client, using the bf(SSH) command
621 shell.
622
623 The phrase bf(LOG =) is optional. When a relative file location is
624 specified at tt(<file-spec>) it is interpreted relatively to the tt(USE BASE)
625 path specification.
626
627 tt(PathOffset) is also optional, and has the same meaning as for the tt(LOCAL
628 CHECK) command, described above. The command may or may not
629 succeed. Otherwise, the program acts identically as the bf(CHECK ...) command,
630 described above.
631
632 Example:nl()
633 tt(NOTEST CHECK LOG = remote/sha256.root \)nl()
632634 tt( /usr/bin/find / \)nl()
633 tt( -xdev -perm /6111 -type f -exec /usr/bin/sha1sum {} \;)
634
635
636 The SHA1 checksums of all suid/gid/executable files on the same device as
635 tt( -xdev -perm /6111 -type f -exec /usr/bin/sha256sum {} \;)
636
637
638 The SHA256 checksums of all suid/gid/executable files on the same device as
637639 the root-directory (/) on the client computer are determined. The resulting
638 listing is written on the file bf(BASE)tt(/remote/sha1.root). s() does not
640 listing is written on the file bf(BASE)tt(/remote/sha256.root). s() does not
639641 terminate if the tt(/usr/bin/find) program returns a non-zero exit value.
640642 )
641643
643645 tt(--max-size) option, see below. By default this size is set at 10M.
644646
645647
646 manpagesection(OPTIONS)
647
648 includefile(../manual/running/options.yo)
648 manpagesection(REPORT FILE ROTATION)
649 Since s() only appends information to the report file, the report file's
650 size may eventually become prohibitively large, and log-rotation may be
651 desirable. It is of course possible to issue a tt(--terminate) command, rotate
652 the logfiles, and restart s(), but s() also offers a facility to temporarily
653 suspend integrity scans performed by a s() daemon process:
654 itemization(
655 it() Calling s() with the option tt(--suspend <uds>) suspends the
656 daemon's integrity scans. If s() is
657 actually performing a series of integrity scans when
658 tt(--suspend) is issued, the currently executing command is first
659 completed after which the tt(--suspend) command completes. Once
660 the s() daemon has been suspended, automatic or explicit
661 integrity scan requests are denied, and the daemon can only be
662 instructed to resume its scanning tasks (s() --resume <uds>)
663 or to terminate (s() --terminate <uds>).
664
665 it() Once `s() tt(--suspend <uds>)' has returned, the report file
666 may safely be rotated (using, e.g., bf(logrotate)(1)), and a new
667 (empty) report file may optionally be created by the logrotation
668 process.
669
670 it() Once the log-rotation has been completed, the log-rotation process
671 should issue the command `s() tt(--resume <uds>)'. This
672 resumes the activities of a suspended s() daemon process,
673 immediately performing the next integrity scan. Following this the
674 s() daemon is back to its original integrity scanning mode.
675 )
676 Here is an example of bf(logrotate)(1) specification rotating s()
677 log-files:
678 verb(
679 /root/stealth/clienthost/small/report /var/log/stealth/clienthost-small.log {
680 daily
681 rotate 4
682 compress
683 missingok
684 copytruncate
685 sharedscripts
686 prerotate
687 /usr/bin/stealth --suspend /root/stealth/client/small.uds
688 endscript
689 postrotate
690 /usr/bin/stealth --resume /root/stealth/client/small.uds
691 endscript
692 }
693 )
694
695 manpagesection(RELOAD, RERUN AND TERMINATE)
696
697 Here is what happens when s() is run using the third synopsis:
698
699 itemization(
700 it() When started as s() tt(--reload <uds>), the s() daemon process
701 reloads its policy file and (if specified) tt(--skip-files)
702 specification file. Next the s() daemon process performs a file
703 integrity scan using the information in the re-read policy and
704 skip-files files. S() can reload the (modified) contents of the
705 originally specified policy- and skip-files names. If another policy
706 and/or skip-files files must be used another s() process must be
707 started, for which these new filenames are specified.
708
709 it() When started as s() tt(--rerun <uds>), the s() daemon performs
710 another scan (unless it has been suspended using s() tt(--suspend
711 <uds>)).
712
713 it() When started as s() tt(--terminate <uds>), the s() daemon is
714 terminated.
715 )
649716
650717 manpagesection(RSYSLOG FILTERING)
651718
658725 itemization(
659726 it() Install s() (e.g., use bf(dpkg)(1) to install the bf(.deb) file);
660727 it() Construct one or more policy files;
661 it() Automate running s() using bf(cron)(1) (possibly calling
662 bf(stealthcron));
728 it() Automate (re)starting s() using bf(cron)(1) or bf(ssh-cron)(1)
729 (possibly calling bf(stealthcron));
663730 it() Set up automated log-file rotation, using, e.g., bf(stealthcleanup)
664731 and bf(logrotate)(1), defining one or more
665732 tt(/etc/logrotate.d/stealth...) configuration files.
674741
675742 manpageseealso()
676743 bf(cron)(1), bf(dd)(1), bf(diff)(1), bf(dpkg)(1), bf(find)(1),
677 bf(logrotate)(1), bf(ls)(1), bf(mail)(1), bf(sha1sum)(1), bf(passwd)(5),
744 bf(logrotate)(1), bf(ls)(1), bf(mail)(1), bf(sha256sum)(1), bf(passwd)(5),
678745 bf(rsyslog)(1), bf(sendmail)(1), bf(sh)(1), bf(ssh)(1), bf(ssh-cron)(1)
679746
680747 manpagesection(DIAGNOSTICS)
0
10 Next, at the client's account where s()'s tt(ssh) command connects to (see
2 also the tt(USE SSH) specification in section ref(USE) ssh-access must be
3 granted to the controller's user. To do so, the controller user's file
1 also the tt(USE SSH) specification in section ref(USE)) ssh-access must be
2 granted to the monitor's user. To do so, the monitor user's file
43 tt(~/.ssh/id_rsa.pub) is added to the client account user's file
54 tt(~/.ssh/authorized_keys):
6 verb( # transfer user@controller's file id_rsa.pub to the client's /tmp
5 verb( # transfer user@monitor's file id_rsa.pub to the client's /tmp
76 # directory. Then do:
87
98 cat /tmp/id_rsa.pub >> /home/account/.ssh/authorized_keys)
109
11 This allows the user at the controller to login at the account at the
10 This allows the user at the monitor to login at the account at the
1211 client without specifying the client account's password (of course, if the
1312 ssh-key is passphrase protected that passphrase must still be provided at the
14 controller once s() is started).
13 monitor when starting s()).
1514
+0
-18
documentation/manual/access/controller.yo less more
0 The controller's user calling s() to scan the client must first generate
1 an tt(ssh-keypair):
2 verb( ssh-keygen -t rsh)
3 This generates a public/private ssh key pair in tt(.ssh) in the user's
4 home directory. The program asks for a em(passphrase). A passphrase can be
5 defined (in which case it must be proviced when s() is started) or, if the
6 security if the controller is sufficiently guaranteed, it can remain empty. To
7 generate an ssh-key without passphrase simply press tt(Enter) in response to
8 the question
9 verb( Enter passphrase (empty for no passphrase):)
10 (a confirmation is required: just press tt(Enter) again).
11
12 tt(Ssh-keygen) then returns a key fingerprint, e.g.,
13 verb( 03:96:49:63:8a:64:33:45:79:ab:ca:de:c8:c8:4f:e9 user@controller)
14 which may be saved for future reference.
15
16 In the user's tt(.ssh) directory the files tt(id_rsa) and tt(id_rsa.pub)
17 are now created, which completes the preparations at the controller.
0 Access to clients (remote hosts) must be granted using the tt(ssh) protocol.
0 Access to clients should be granted using the tt(ssh) protocol.
11
2 Clients must allow the controller to connect using tt(ssh). S() connects to
3 its clients using ssh certificates, after the controler's public
4 key has been transferred to its clients.
2 Clients must allow the monitor to connect using tt(ssh). S() connects to its
3 clients using ssh certificates, after the monitor's public SSH-key has been
4 transferred to the clients.
0 When user@controller now issues, for the first time, the command
1 verb( ssh account@controller)
0 When user@monitor now issues, for the first time, the command
1 verb( ssh account@monitor)
22 tt(Ssh) responds like this:
3 verb( The authenticity of host 'controller (xxx.yyy.aaa.bbb)' can't be
3 verb( The authenticity of host 'monitor (xxx.yyy.aaa.bbb)' can't be
44 established.
55 RSA key fingerprint is c4:52:d6:a3:d4:65:0d:5e:2e:66:d8:ab:de:ad:12:be.
66 Are you sure you want to continue connecting (yes/no)?)
77 Answering tt(yes) results in the message:
8 verb( Warning: Permanently added 'controller,xxx.yyy.aaa.bbb' (RSA) to the
8 verb( Warning: Permanently added 'monitor,xxx.yyy.aaa.bbb' (RSA) to the
99 list of known hosts.)
1010
11 The next time a login is attempted, the authenticity question isn't asked
11 The next time a login is attempted, the authenticity question is not asked
1212 anyore. However, the proper value of the host's RSA key fingerprint (i.e., the
1313 key fingerprint of the em(client) computer) should em(always) be verified to
1414 prevent em(man in the middle) attacks. The proper value may be obtained at the
15 client computer by issuing (at the client) the command
15 client by issuing there the command
1616 verb( ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key.pub)
1717 This should show the same value of the fingerprint as shown when the
1818 first tt(ssh) connection was established. E.g.,
19 verb( 1024 c4:52:d6:a3:d4:65:0d:5e:2e:66:d8:ab:de:ad:12:be ssh_host_rsa_key.pub)
19 verb(
20 1024 c4:52:d6:a3:d4:65:0d:5e:2e:66:d8:ab:de:ad:12:be ssh_host_rsa_key.pub)
0 The monitor's user calling s() to scan the client must first generate
1 an tt(ssh-keypair):
2 verb( ssh-keygen -t rsa)
3 By default this generates a public/private ssh key-pair in the directory
4 tt(.ssh) in the user's home directory. The program asks for a
5 em(passphrase). A passphrase can be defined (in which case it must be proviced
6 when s() is started) or, if the security if the monitor is sufficiently
7 guaranteed, it can remain empty. To generate an ssh-key without passphrase
8 simply press tt(Enter) in response to the question
9 verb( Enter passphrase (empty for no passphrase):)
10 (a confirmation is required: just press tt(Enter) again).
11
12 tt(Ssh-keygen) then returns a key fingerprint, e.g.,
13 verb( 03:96:49:63:8a:64:33:45:79:ab:ca:de:c8:c8:4f:e9 user@monitor)
14 which may be saved for future reference.
15
16 In the user's tt(.ssh) directory the files tt(id_rsa) and tt(id_rsa.pub)
17 are now created, which completes the preparations at the monitor.
18
19 If, instead of running s() in deamon mode it is preferred to let s() perform
20 single, but automated integrity scans, then new bf(ssh)(1) connections may be
21 difficult to establish if the used ssh-key is passphrase-protected. To
22 implement this scenario (i.e., automated integrity scans using passphrase
23 protected ssh-keys) the program bf(ssh-cron)(1) can profitably be used.
24
0 On order to minimize the amount of clutter and possible complications when
0 On order to minimize the amount of clutter and possibly complications when
11 only a simple command-shell is required for executing commands, it is
22 suggested to use a bf(bash)(1) shell when logging into tt(account@client)'s
33 account.
0 COMMENT(
1 tt(/bin/sh: no output from /usr/bin/diff ...)
2 quote(the actual program names appearing here could change due to your
3 local configuration. The defaults are shown. This indicates that the
4 tt(/usr/bin/diff) program could not be activated on the controller. Check the
5 correctness of both the shell program (tt(/bin/sh)) and the diff program
6 (tt(/usr/bin/diff)): Do they exist? Have their paths been specfied well?
7 Note that filenames passed to tt(diff) might not exist anymore when the
8 program terminates. This should not be the cause of the error.
9 )
10 END)
11
120 tt(Can't chdir to `path')
131 quote(the directory tt(path) could not be
142 created/used. This may be a permission problem. Check the permissions of
2311 write it.
2412 )
2513
14 tt(Corrupt line in policy file: ...)
15 quote(The apparently corrupted line is shown. The line is corrupted if
16 the line could not be split into an initial word and its remainder. Normally
17 this should not happen. As the line is mentioned, the message itself should
18 assist you in your repairs.
19 )
20
2621 tt(could not open <logname>)
2722 quote(This message is generated when the mentioned log-file cannot be
2823 written to. Check the permissions of the file, and check if the path to the
3025 last element of the path or in the file itself.
3126 )
3227
33 tt(Can't read `<run-file>')
34 quote(The daemon's run-file could not be read. Check if there is indeed a
35 s() daemon process using this run-filefile exists; if the run-file actually
36 exists (typo in its specification?), and if you have read permissions for it.
37 )
38
39 tt(Can't send signal <signal-name> to process `<pid>')
40 quote(The indicated signal (either tt(SIGTERM) or tt(SIGUSR1)) could not
41 be sent to the daemon process. Check if a s() daemon process having process ID
42 tt(<pid>) really exist.)
43
44 tt(Corrupt line in policy file: ...)
45 quote(The apparently corrupted line is shown. The line is corrupted if
46 the line could not be split into an initial word and its remainder. Normally
47 this should not happen. As the line is mentioned, the message itself should
48 assist you in your repairs.
49 )
50
51 tt(could not write <run-file name>)
52 quote(The specified run-file could not be written to. Check its
53 permissions and whether it actually exists.)
54
55 tt(--daemon: missing run-file or policy file)
56 quote(The tt(--daemon) option requires an absolute filename to a run-file,
57 and the call also requires a policy file. Most likely the path to the run-file
58 was not specified, thus confusing the policy file with the run-file. The
59 run-file is often created in the tt(/run) directory.
60 )
61
62 tt(--daemon <run-file>: must use an absolute file name)
63 quote(The tt(--daemon) option requires a full (absolute) path to the
64 run-file name. Most likely the name of the run-file was not specified, thus
65 confusing the policy file with the skip-file. The run-file is often created in
66 the tt(/run) directory.
28 tt(--daemon: missing uds-file or policy file)
29 quote(The tt(--daemon) option requires the location for its Unix Domain
30 Socket, and in addition a policy file must be specified. Most likely the
31 location of the Unix Domain File was omitted, thus confusing the policy file
32 with the Unix Domain File
33 )
34
35
36 tt(incompatible options: ...)
37 quote(Two or more incompatible options are shown. E.g., tt(--daemon) is
38 incompatible with IPC options, which themselves are mutually
39 incompatible. Omit all but one of the mentioned options and restart s()
6740 )
6841
6942 tt(Inserting command `...' failed.)
7750 negative) argument.
7851 )
7952
80 tt(incompatible options: ....)
81 quote(Only one option related to a s() daemon process can be specified at
82 a time. E.g., you cannot specify tt(--daemon --rerun --suspend) in one
83 command. If incompatible options are specified s() terminates after reporting
84 which (incompatible) options were received.)
53 tt(invalid --<option> specified)
54 quote(The specified option value (e.g., tt(--max-size) was specified, but
55 its option value is not a valid integral number) is not supported
56 )
57
58 tt(LocalClientSocket::connect(): ...)
59 quote(When running in IPC-mode s() could not connect to the unix domain
60 socket specified for the IPC-mode. Check whether the matching s() daemon
61 exists, and whether the location of the uds-file was correctly specified
62 )
63
64 tt(LocalServerSocket::accept(): ...)
65 quote(When running in daemon mode incoming connections could not be
66 accepted. This may have many causes, and a probably cause is mentioned with
67 the error message
68 )
69
70 tt(LocalServerSocket::listen(): ...)
71 quote(When running in daemon mode the unix domain socket failed to
72 listen for incoming connections. This may have many causes, and a probably
73 cause is mentioned with the error message
74 )
75
76 tt(LocalServerSocket::open(<uds>): ...)
77 quote(When running in daemon mode the unix domain socket could not be
78 opened. A possible reason is that an entry in the file system having the same
79 name already exists. The error message will mention a probably cause of the
80 failure
81 )
8582
8683 tt(--max-size incompatible with IPC calls)
8784 quote(The tt(--max-size) option can can only be used when s() is also
9996 terminates.
10097 )
10198
102 tt(--<option name> is only valid for a stealth foreground process)
103 quote(The specified option is incompatible with the tt(--daemon)
104 option. Either do not specify tt(--daemon) or omit the offending option.)
99 tt(--<option> is only valid for a s() foreground process)
100 quote(The indicated option cannot be specified in combination with a
101 tt(--daemon) or IPC-option (like tt(--suspend))
102 )
105103
106104 tt(--random-interval requires --repeat)
107105 quote(The tt(--random-interval) option can only be used when the
108106 tt(--repeat) option has also been specified.
107 )
108
109 tt(--repeat not available in IPC modes)
110 quote(The tt(--repeat) option cannot be specified in combination with an
111 IPC-option (like tt(--suspend))
109112 )
110113
111114 tt(--run-command 0: not a valid (natural) command number)
120123 )
121124
122125 tt(--skip-files incompatible with IPC calls)
123 quote(The tt(--skip-files) option can only be used when s() is also
124 receiving a policy file. It cannot be used in combination with the Inter
125 Process Communication (IPC) options tt(--reload, --rerun, --resume, --suspend)
126 or tt(--terminate).
126 quote(The tt(--skip-files) option can only be used when s() is also given
127 a policy file. It cannot be used in combination with IPC options (tt(--reload,
128 --rerun, --resume, --suspend) or tt(--terminate)).
127129 )
128130
129131 tt(--skip-files: missing skip-file or policy file)
130 quote(The tt(--skip-files) option requires a skip-files absolute filename,
131 and the call also requires a policy file. Most likely the name of the
132 skip-file was not specified, thus confusing the policy file with the
133 skip-file.
134 )
135
136 tt(--skip-files <filename>: must use an absolute file name)
137 quote(The tt(--skip-files) option requires a full (absolute) path to the
138 skip-file name. Most likely the name of the skip-file was not specified, thus
139 confusing the policy file with the skip-file.
140 )
141
142 tt(Stealth V _CurVers_ terminated)
143 quote(Some pre-3.00.00 options were discontinued starting at s() version
144 3.00.00. Two of these options are tt(--suppress) and tt(--keep-alive). If
145 these options are used, their use is reported and s() terminates with the
146 above message.
132 quote(The tt(--skip-files) option requires a file name and the s() command
133 also requires a policy file. Most likely the name of the skip-file was not
134 provided, thus confusing the policy file with the skip-file.
147135 )
148136
149137 tt(--stdout incompatible with --daemon)
157145 tt(LOCAL7) and tt(USER). See, e.g., the bf(syslog)(3) man-page for an overview
158146 of their definitions.)
159147
148
160149 tt(--syslog* options incompatible with IPC calls)
161150 quote(tt(--syslog*) options can can only be used when s() is also
162151 receiving a policy file. It cannot be used in combination with the Inter
163152 Process Communication (IPC) options tt(--reload, --rerun, --resume, --suspend)
164153 or tt(--terminate).
165154 )
166
167155
168156 tt(syslog priority <priority> not supported)
169157 quote(The option tt(--syslog-priority) requires the name of a standard
174162 WARNING) rather than tt(--syslog-priority LOG-WARNING))
175163 )
176164
177
178165 tt(terminated: non-zero exit value for `...')
179166 quote(A local command (not using the tt(CHECK) keyword), returned with a
180167 non-zero exit. This will terminate further processing of the policy
190177 itself.
191178 )
192179
180 tt(Unix Domain Socket `<uds>': already in use, remove it first)
181 quote(The intended Unix Domain Socket name (tt(<uds>)) is already in
182 use. It could be a file that is or has been used by another process. Either
183 use another name for the unix domain socket, or remove the existing
184 file-system entry)
185
193186 tt(USE SSH ... entry missing in the policy file)
194187 quote(there is no default for the tt(USE SSH) specification in the policy
195188 file. The specification could not be found. Provide a specification like:
196189 verb(USE SSH ssh -q root@localhost)
197190 )
191
192
193
194
195
196
197
198
199
200
201
22 is a version number. Below, tt(_CurVers_) should be altered into the version
33 of the archive that is actually used.
44
5 Required, non-standard software, for compiling s() is summarized in the file
6 tt(required), which is included in the source file distribution. Currently,
7 its contents are:
8
9 verbinclude(../../../required)
10
511 itemization(
612 it() S() compilation is controlled by bf(icmake)(1). The program
713 maintenance utility bf(icmake)(1) can be obtained at
814 lurl(http://icmake.sourceforge.net/), and it is also available in several
9 Linux distributions (e.g., Debian, Ubuntu). It is assumed below
10 that you have an install a recent tt(icmake) version;
15 Linux distributions (e.g., Debian, Ubuntu);
1116
12 it() Determine a directory under which the archive's file should be
13 stored. E.g., if the files in the archive should be stored under tt(/tmp), and
14 the archive itself is stored in tt(/tmp) as well, do:
17 it() Determine a directory where the files in s()'s archive ashould be
18 stored. E.g., if the files in the archive should be stored under tt(/tmp)
19 (and assuming the archive itself is stored in tt(/tmp) as well) then do:
1520 verb(
1621 cd /tmp
1722 tar xzf stealth-_CurVers_.tar.gz
1823 )
1924 This creates a subdirectory tt(stealth) containing s()'s sources;
2025
21 it() Next, tt(chdir) to that directory:
26 it() Change-dir to that directory:
2227 verb(
2328 chdir stealth
2429 )
2530
2631 it() Check the contents of the files tt(INSTALL.im) and tt(icmconf), and
2732 verify that all tt(#defines) match your computer's file system and
28 software. Also note, in tt(icmconf), the entry
29 verb(
30 #define ADD_LIBRARIES "bobcat"
31 )
33 software.
3234
33 When compiling and s(), the
35 When compiling s(), the
3436 url(bobcat)(http://bobcat.sourceforge.net/) header files must be
3537 available. When s() is run it is dynamically linked against the bobcat
36 library. If you haven't installed bf(bobcat) yet, download it from
37 lurl(http://sourceforge.net/projects/bobcat/), and follow its installation
38 instructions (alternatively, bobcat may be available in your distribution,
39 like Debian or Ubuntu). Make sure to install both the run-time
38 library. bf(Bobcat) can be downloaded from
39 lurl(http://sourceforge.net/projects/bobcat/) (and follow its installation
40 instructions). Alternatively, bobcat may be available in your distribution,
41 (e.g., Debian or Ubuntu). Make sure to install both the run-time
4042 (bf(bobcat_...)) and the development (bf(bobcat-dev_...)) versions.
4143
4244 it() Execute the command
6264 `/usr/share/doc/stealth-doc')
6365 )
6466 )
65
66
67
68
69
70
71
72
73
74
75
99 itemization(
1010 it() tt(SSH-based): The file integrity scan is (usually) performed over an
1111 ssh-connection. Usually the computer being scanned (called the em(client)) and
12 the computer initiating the scan (called the tt(controller)) are different
12 the computer initiating the scan (called the tt(monitor)) are different
1313 computers.
14 it() The client should accept incoming ssh-connections
15 from the initiating computer. The controller doesn't have to (and shouldn't,
16 probably).
14 it() The client should accept incoming ssh-connections from the
15 monitor. The monitor doesn't have to (and shouldn't, probably).
1716 it() tt(Trust Enforcement): following the scan, `trust' is enforced in the
1817 client, due to the integrity of its files.
19 it() tt(Locally Trusted Host): the client apparently trusts the controller
18 it() tt(Locally Trusted Host): the client apparently trusts the monitor
2019 to use an ssh-connection to perform commands on it. The client therefore
21 em(locally trusts) the controller. Hence, em(locally trusted host).
20 em(locally trusts) the monitor. Hence, em(locally trusted host).
2221 )
2322
2423 s() is based on an idea by em(Hans Gankema) and em(Kees Visser),
2928 s() has em(stealthy) characteristics. I consider this an important
3029 security improving feature of s().
3130
32 The controller itself only needs two kinds of outgoing services:
31 The monitor itself only needs two kinds of outgoing services:
3332 bf(ssh)(1) to reach its clients, and some mail transport agent (e.g.,
3433 bf(sendmail)(1)) to forward its outgoing mail to some mail-hub.
3534
3635 Here is what happens when s() is run:
3736 itemization(
38 it() First, a em(policy) file is read. This determines actions to be
39 performed, as well as the values of several variables used by s().
40 it() If the command-line option tt(--daemon) is given, s() runs as a
41 backgrond (daemon) process, writing its process ID in a separate file. Using
42 tt(--repeat <seconds>) the scan is rerun every tt(<seconds>) seconds after
43 completing the previous integrity scan. When merely tt(--daemon) is
44 specified the scan is performed only once, whereafter s() waits until it is
45 reactivated through the s() tt(--rerun <pid>) command.
46 it() Then, the controller opens a command shell on the client using
47 bf(ssh)(1), and a command shell on the controller itself using bf(sh)(1).
48 it() Next, commands defined in the policy file are executed in their order
49 of appearance. Examples are given below. Normally, return values of the
50 programs are tested. Non-zero return values terminate s().
51 it() In most cases, integrity tests can be controlled by the bf(find)(1)
52 program, calling programs like bf(ls)(1), bf(sha1sum)(1) or its own tt(-printf)
53 method to produce file-integrity related statistics. Most of these programs
54 write file names at the end of generated lines. This characteristic is used by
55 an internal routine of s() to detect changes in the generated output,
56 which could indicate some malignant software, like an installed em(root-kit).
57 it() When changes are detected, they are logged on a em(report file), to
58 which information is always appended. s() never reduces or rewrites
59 the report file. When information is added to the report file the newly
60 written information is emailed to a configurable email address for further
61 (human) processing. Usually the e-mail is sent to the systems manager of the
62 tested client. s() follows the `dark cockpit' approach in that no mail
63 is sent when no changes were detected.
37 it() First, the em(policy) file is read. For each client a policy file is
38 defined, specifying the actions to be performed, and specifying the values of
39 several variables used by s().
40
41 it() If the command-line option tt(--daemon <uds>) is specified, s()
42 runs as a daemon process, using the Unix Domain Socket (tt(<uds>)) for
43 communication with s() processes running in IPC mode.
44
45 If access to the Unix Domain Socket defined by Stealth running in daemon mode
46 should be restricted, it can be defined in a directory with is only accessible
47 to the user running Stealth (this will often be the root-user).
48
49 When running in daemon mode, tt(--repeat <seconds>) may be specified to rerun
50 the integrity scan every tt(<seconds>) seconds. If an integrity scan is being
51 performed when, according to the repeat interval the next integrity scan is
52 due, then the current scan is first completed. Once completed, the next
53 integrity scan will be performed after tt(seconds) seconds.
54
55 it() Next, the monitor opens a command shell on the client using
56 bf(ssh)(1), and a command shell on the monitor computer itself using
57 bf(sh)(1).
58
59 it() Once the command shells are available, commands defined in the policy
60 file are executed in their order of appearance. Examples are given
61 below. Normally, return values of the programs are tested. When return values
62 are to be tested s() terminates when a non-zero return value is sensed. If
63 this happens, a message stating the reason why s() terminated is written to
64 the report file (and into the mail sent by s()). In some cases (e.g., when the
65 report file could not be written), the message is written to the standard
66 error stream.
67
68 it() Very often integrity tests can be controlled using bf(find)(1),
69 calling programs like bf(ls)(1), bf(sha1sum)(1) or its own tt(-printf) method
70 to produce file-integrity related statistics. Most of these programs write
71 file names at the end of generated lines. This characteristic is used by one
72 of s()'s internal routines to detect changes in the generated output. Such
73 changes could indicate some harmful intent, like an installed em(root-kit).
74
75 it() When changes are detected, they are logged in a em(report file), to
76 which information is always appended. S() never reduces the report file's size
77 or rewrites its contents. When information is added to the report file (beyond
78 a plain time stamp) the newly added information is e-mailed to a configurable
79 e-mail address for further (human) processing. Usually the e-mail is sent to
80 the systems manager of the tested client. S() follows the `dark cockpit'
81 approach in the sense that no mail is sent when no changes were detected.
82
83 it() Report and other log-files may safely be rotated between a pair of
84 tt(--suspend) and tt(--resume) commands (see below at the section
85 ref(ROTATE)).
6486 )
6587
66 Alternatively, the command-line options tt(--reload, --rerun, --suspend,
67 --resume) and tt(--terminate) may be provided to communicate with an existing
68 s() daemon. These options require but one argument: the pathname to a pid-file
69 of a running s().
88 Instead of running in daemon mode, s() may also run in `foreground' mode.
89 In foreground mode the option tt(--daemon) is not specified. When running in
90 foreground mode s() either performs one integrity scan (and terminates) or, if
91 the tt(--repeat) option has been specified, it repeatedly performs integrity
92 scans, at intervals determined by the tt(--repeat) and tt(--random-interval)
93 options. When tt(--repeat) is specified with s() running in foreground mode a
94 prompt is shown (i.e., `tt(? )') with s() terminating after pressing the
95 tt(Enter)-key.
96
97 Alternatively, s() may run in `inter process communication' mode (IPC
98 mode). IPC mode is characterized by using one of the command-line options
99 tt(--reload, --rerun, --suspend, --resume) or tt(--terminate). In IPC-mode s()
100 communicates with an existing s() daemon, using the Unix Domain Socket defined
101 by the s() daemon. These options require but one argument: the location of the
102 Unix Domain Socket defined by a running s() daemon.
70103 itemization(
71 it() When started using the tt(--reload <pidfile>) command-line option,
72 the stealth daemon corresponding to tt(pidfile) reloads its policy and skip
73 files, immediately followed by another integrity scan;
74 it() When started using the tt(--rerun <pidfile>) command-line option, the
75 stealth daemon corresponding to tt(pidfile) performs another integrity scan;
76 it() When started using the tt(--terminate <pid>) command-line option, the
77 stealth daemon corresponding to tt(pidfile) terminates. The daemon is also
78 terminated if it receives a tt(SIGTERM) or tt(SIGINT) signal.
104 it() When started using the tt(--reload <uds>) command-line option, the
105 stealth daemon that created the Unix Domain Socket reloads its policy file
106 (and skip-file), immediately followed by another integrity scan;
107 it() When started using the tt(--rerun <uds>) command-line option, the
108 stealth daemon that created the Unix Domain Socket performs another integrity
109 scan;
110 it() When started using the tt(--terminate <usd>) command-line option, the
111 stealth daemon that created the Unix Domain Socket terminates.
79112 )
80113
81 The options tt(--suspend) and tt(--rerun) (see section ref(ROTATE)) were
82 implemented to allow safe rotations of s()'s report file.
83
84 COMMENT(
85
86 This second was removed since the distributions are responsible for
87 archive integrity
88
89 subsect(The integrity of the stealth distribution)
90
91 The integrity of the archive tt(stealth-_CurVers_.tar.gz) can be verified as
92 follows:
93 itemization(
94 it() At the location where you found this archive, you should also find a
95 file named tt(stealth-_CurVers_.dsc). This file contains a PGP signed
96 bf(sha1sum)(1) signature of the tt(tar.gz) archive. The PGP signature was
97 provided by me using bf(gpg)(1) (bf(pgp)(1)).
98 it() Compute the SHA1 checksum of the tt(stealth-_CurVers_.tar.gz)
99 archive. Its value should match the SHA1 checksum that is mentioned in the
100 tt(stealth-_CurVers_.dsc) file. If not, the tt(stealth-_CurVers_.tar.gz)
101 archive has been compromised, and should em(not) be used.
102 it() In order to verify the validity of the electronic signature, do as
103 follows:
104 itemization(
105 it() Obtain my public key from a public PGP keyserver, e.g.
106 verb( http://pgp.surfnet.nl:11371/)
107 it() Make sure you have the right key. Its fingerprint is
108 verb( DF32 13DE B156 7732 E65E 3B4D 7DB2 A8BE EAE4 D8AA)
109 and it has been electronically signed by, e.g., the University of
110 Groningen's PGP-certificate authority. If in doubt, contact me to verify you
111 have the right key.
112 it() Once you're sufficiently satisfied that you indeed have obtained
113 my public PGP key, verify the validity of the signature used for signing
114 tt(stealth-_CurVers_.dsc). With bf(gpg)(1) this can be done by the command
115 verb( gpg --verify stealth-_CurVers_.dsc)
116 )
117 )
118 This should produce output comparable to:
119 verb(gpg: Signature made Fri Jun 1 10:57:41 2012 CEST using DSA key ID EAE4D8AA
120 gpg: Good signature from "Frank B. Brokken <f.b.brokken@rug.nl>")
121
122 END COMMENT)
114 The options tt(--suspend) and tt(--resume) (see section ref(ROTATE)) were
115 implemented to allow safe rotations of s()'s log-files.
123116
124117
125118
130123
131124
132125
126
99 it() Inspect, and where necessary modify the values of the variables in
1010 the files tt(INSTALL.cf) and tt(icmconf);
1111 it() Install a recent Gnu tt(g++) compiler;
12 it() Install the bobcat library
12 it() Install the bobcat library (both the binary and development version)
1313 (lurl(http://bobcat.sourceforge.net));
1414 it() Install the tt(icmake) program
1515 (lurl(http://icmake.sourceforge.net));
00 S() uses a policy file consisting of two sections, the second
1 section is optional.
1 section is optional, and starts at a line merely containing tt(%%).
2
3 Each policy file is uniquely associated with a host to be tested. Each host
4 may have multiple policy files, though. In that case, each policy file defines
5 its own set of checks to be performed.
26
37 itemization(
4 it() The policy file's first section defines the actions that s() must
5 perform. Each policy file is uniquely associated with a host to be
6 tested. Each host may have multiple policy files, though. In that case, each
7 policy file defines its own set of checks to be performed.
8 it() The policy file's first section consists of two sets of data: em(use
9 directives) (starting with the keyword bf(USE)) and em(commands).
810
9 it() The policy file's optional second section starts with a line merely
10 containing tt(%%), which may then be followed by certain long option
11 specifications. See section ref(OPTIONS) for an overview.
11 it() The (optional) second section starts at a line merely containing
12 tt(%%). Following this separating line several long option specifications can
13 be entered (cf. section ref(OPTIONS)). Options
14 specified on the command-line take priority over options specified
15 in the policy file. Although the tt(--reload) option reloads the policy file,
16 it will not change option values originally specified as command-line options.
17
18 This section may contain specifications of the tt(skip-files) and tt(log)
19 options. Relative file locations specified for these options are interpreted
20 relative to the location of the policy file. E.g., if the policy file argument
21 is specified as tt(/root/client/policy) then the specification tt(log:
22 client.log) results in s() writing its logs into the file
23 tt(/root/client/client.log).
1224 )
1325
14 In this chapter the term em(controller) is used for the computer running
15 s(), while the term em(client) is used for the computer that is scanned by
16 s(). The controller and the client could be the same computer, but
17 normally they are different.
1826
1927 The policy file's first section consists of three sets of data: em(define
2028 directives) (starting with the keyword bf(DEFINE)), em(use directives)
2129 (starting with the keyword bf(USE)) and em(commands).
2230
2331 Directives are written in capitals, and should appear exactly as written
24 below; letter casing is preserved.
32 below.
2533
2634 Blank lines and information beyond hash-marks (#) are ignored, while lines
2735 following lines terminating in backslashes (\ ) will be concatenated (em(en
28 passant) removing these backslashes). Initial white space on lines of the
36 passant) removing these backslashes). Leading white space on lines of the
2937 policy file is ignored.
3038
39
1616 )
1717
1818 Examples:
19 verb( LABEL Inspecting files in /etc\nIncluding subdirectories
19 verb(
20 LABEL Inspecting files in /etc\nIncluding subdirectories
2021 LABEL)
21 The second bf(LABEL) command clears the first label.
22 The latter bf(LABEL) command clears the text of the former bf(LABEL)
23 command.
00 bf(LOCAL) commands can be used to specify commands that are
1 executed on the controller itself. The following bf(LOCAL) commands are
1 executed on the monitor itself. The following bf(LOCAL) commands are
22 available:
33 itemization(
44 it() bf(LOCAL) tt(command)
55
6 Execute tt(command) on the controller, using the bf(SH) command
6 Execute tt(command) on the monitor, using the bf(SH) command
77 shell. The command must succeed (i.e., must return a zero exit value).
88 Example:
99 verb( LOCAL mkdir /tmp/client)
10 This command creates the directory tt(/tmp/client) on the controller.
10 This command creates the directory tt(/tmp/client) on the monitor.
1111
1212 it() bf(LOCAL NOTEST) tt(command)
1313
14 Execute tt(command) on the controller, using the bf(SH) command
14 Execute tt(command) on the monitor, using the bf(SH) command
1515 shell. The command may or may not succeed.
1616 Example:
1717 verb( LOCAL NOTEST mkdir /tmp/subdir)
18 This command creates tt(/tmp/subdir) on the controller. The command
18 This command creates tt(/tmp/subdir) on the monitor. The command
1919 fails if the directory cannot be created, but this does not terminate
2020 s().
2121
2222 it() bf(LOCAL CHECK) [bf(LOG =)] tt(logfile [pathOffset] command)
2323
24 Execute tt(command) on the controller, using the bf(SH) command shell.
25 The phrase `bf(LOG =)' is optional.
24 Execute tt(command) on the monitor, using the bf(SH) command
25 shell. The command must succeed. The output of this command is compared to the
26 output of this command generated during the previous integrity check run by
27 s().
2628
27 The tt([pathOffset]) is also optional. If specified it defines the (0-based)
28 offset where path-names of inspected files start in lines produced by the
29 diff-command, comparing the previous report and the output generated by
30 tt(<command>). By default s() assumes that the first occurrence of a
31 forward slash defines the first character of the path-names of inspected
32 files.
29 The phrase bf(LOG =) is optional. When a relative file location is
30 specified at tt(<file-spec>) it is interpreted relatively to the tt(USE BASE)
31 path specification.
32
33 tt(PathOffset) is also optional. If specified it defines the (0-based)
34 offset where path-names of inspected files start in lines produced by
35 tt(<command>). By default s() assumes that the first occurrence of a forward
36 slash defines the first character of the path-names of inspected files.
3337
3438 For example, if diff-output looks like this:
35 verb( 01234567890123456789012345678901234567890 (column offsets, not part of
39 verb(
40 01234567890123456789012345678901234567890 (column offsets, not part of
3641 the diff-output)
3742
3843 33c33
5156 forged:
5257 verb( *** BE CAREFUL *** REMAINING RESULTS MAY BE FORGED)
5358 This situation may occur, e.g., if an essential program (like tt(sha1sum))
54 was transferred to the controller, and it was apparently modified since the
59 was transferred to the monitor, and it was apparently modified since the
5560 previous check. Processing continues, but remaining checks performed at the
5661 client computer should be interpreted with em(extreme) caution.
5762
6469 the time s() was run.
6570
6671 Over time, many tt(logfile.YYMMDD-HHMMSS) files could be accumulated.
67 It is up to the controller's systems manager to decide what to do
72 It is up to the monitor's systems manager to decide what to do
6873 with old datetime-stamped logfiles. For instance, the following script
6974 removes all s() reports below the current directory that are
7075 older than 30 days:
8893
8994 it() bf(LOCAL NOTEST CHECK) [bf(LOG =)] tt(logfile [pathOffset] command)
9095
91 Execute tt(command) on the controller, using the bf(SH) command
92 shell. The phrase `bf(LOG =)' is optional. The command may or may not
93 succeed. Otherwise, the program performs exactly like the bf(LOCAL CHECK ...)
94 command, discussed above.
96 Execute tt(command) on the monitor, using the bf(SH) command
97 shell.
98
99 The phrase bf(LOG =) is optional. When a relative file location is
100 specified at tt(<file-spec>) it is interpreted relatively to the tt(USE BASE)
101 path specification.
102
103 The command may or may not succeed. Otherwise, the program performs exactly
104 like the bf(LOCAL CHECK ...) command, discussed above.
95105
96106 Example:
97107 verb( LOCAL NOTEST CHECK LOG=local/sha1sum sha1sum /tmp/sha1sum)
0 Either by malicious intent or by accident (as happened to me) the controller
1 may be a victim of a Denial of Service (DOS) attack. This DOS attack may occur
2 when the client (apparently) sends a never ending stream of bytes in response
3 to a tt(GET) or tt(REMOTE) command. Once one of my controllers fell victim to
4 this attack when a client's power went down and the controller kept on trying
5 to read bytes from that client filling up the controller's disk....
0 Either by malicious intent or by accident (as happened to me) the monitor may
1 be a victim of a (self-inflicted) Denial of Service (DOS) attack. This DOS
2 attack may occur when the client (apparently) sends a never ending stream of
3 bytes in response to a tt(GET) or tt(REMOTE) command. Once one of my monitors
4 fell victim to this attack when a client's power went down and the monitor
5 kept on trying to read bytes from that client filling up the monitor's
6 disk....
67
78 This problem was of course caused by a programming error: while reading
89 information from a client s() failed to check whether the reading had actually
1314 ending stream of bytes to be written to its `report' file, thus causing its
1415 disk to fill up.
1516
16 To prevent this from happening s() offers the tt(--max-size)
17 To prevent this from happening s() now offers the tt(--max-size)
1718 command line option allowing the specification of the maximum size of a stream
1819 of bytes received by s() (e.g., a report or downloaded file). The
1920 maximum is used for each individual download and can be specified in bytes
2425 If a file or report received from the client exceeds its maximum allowed size
2526 then s() terminates after writing the following message to the report
2627 file (which is sent to the configured mail address):
27 verb( STEALTH - CAN'T CONTINUE: `<name of offending file>' EXCEEDS MAX.
28 verb(
29 STEALTH - CAN'T CONTINUE: `<name of offending file>' EXCEEDS MAX.
2830 DOWNLOAD SIZE (<size shown>)
2931 STEALTH - THIS COULD SIGNAL A SERIOUS PROBLEM WITH THE CLIENT
3032 STEALTH - ONE OR MORE LOG FILES MAY BE INVALID AS A RESULT
1212 intended program.
1313
1414 Two special remote commands are tt(GET) and tt(PUT), which can be used to
15 copy files between the client and the controller. Internally, tt(GET) and
15 copy files between the client and the monitor. Internally, tt(GET) and
1616 tt(PUT) use the tt(DD) use-specification. If a non-default specification is
1717 used, one should ensure that the alternate program accepts bf(dd)(1)'s tt(if=,
1818 of=, bs=) and tt(count=) options. With tt(GET) the options tt(bs=, count=) and
2424 startit()
2525 it() bf(GET) tt(<client-path> <local-path>)nl()
2626 Copy the file indicated by tt(client-path) at the client to tt(local-path)
27 at the controller. tt(client-path) must be the full path of an existing file
27 at the monitor. tt(client-path) must be the full path of an existing file
2828 on the client, tt(local-path) may either be a local directory, in which case
2929 the client's file name is used, or another file name may be specified, in
3030 which case the client's file is copied to the specified local filename. If the
3333 Example:
3434 verb( GET /usr/bin/sha1sum /tmp)
3535 The program tt(/usr/bin/sha1sum), available at the client, is copied to
36 the controller's tt(/tmp) directory. If copying fails for some reason, any
36 the monitor's tt(/tmp) directory. If copying fails for some reason, any
3737 subsequent commands are skipped, and s() terminates.
3838
3939 it() bf(GET NOTEST) tt(<client-path> <local-path>)nl()
4040 Copy the file indicated by tt(client-path) at the client to tt(local-path)
41 at the controller. tt(client-path) must be the full path of an existing file
41 at the monitor. tt(client-path) must be the full path of an existing file
4242 on the client, tt(local-path) may either be a local directory, in which case
4343 the client's file name is used, or another file name may be specified, in
4444 which case the client's file is copied to the specified local filename. If the
4747 Example:
4848 verb( GET NOTEST /usr/bin/sha1sum /tmp)
4949 The program tt(/usr/bin/sha1sum), available at the client, is copied to the
50 controller's tt(/tmp) directory. Remaining commands in the policy file are
50 monitor's tt(/tmp) directory. Remaining commands in the policy file are
5151 executed, even if the copying process wasn't successful.
5252 endit()
5353
5454 The tt(PUT) command may be used as follows:
5555 startit()
5656 it() bf(PUT) tt(<local-path> <remote-path>)nl()
57 Copy the file indicated by tt(local-path) at the controller to
57 Copy the file indicated by tt(local-path) at the monitor to
5858 tt(remote-path) at the client. The argument tt(local-path) must be the
59 full path of an existing file on the controller. The argument tt(remote-path)
59 full path of an existing file on the monitor. The argument tt(remote-path)
6060 must be the full path to a file on the client. If the remote file already
6161 exists, it is overwritten by tt(PUT).
6262
6363 Example:
6464 verb( PUT /tmp/sha1sum /usr/bin/sha1sum)
65 The program tt(/tmp/sha1sum), available at the controller, is copied to the
65 The program tt(/tmp/sha1sum), available at the monitor, is copied to the
6666 client as tt(usr/bin/sha1sum). If the copying fails for some reason,
6767 any subsequent commands are skipped, and s() terminates.
6868
6969 it() bf(PUT NOTEST) tt(<local-path> <remote-path>)nl()
70 Copy the file indicated by tt(local-path) at the controller to
70 Copy the file indicated by tt(local-path) at the monitor to
7171 tt(remote-path) at the client. The argument tt(local-path) must be the
72 full path of an existing file on the controller. The argument tt(remote-path)
72 full path of an existing file on the monitor. The argument tt(remote-path)
7373 must be the full path to a file on the client. If the remote file already
7474 exists, it is overwritten by tt(PUT).
7575
7676 Example:
7777 verb( PUT NOTEST /tmp/sha1sum /usr/bin/sha1sum)
78 Copy the file indicated by tt(local-path) at the controller to
78 Copy the file indicated by tt(local-path) at the monitor to
7979 tt(remote-path) at the client. The argument tt(local-path) must be the full
80 path of an existing file on the controller. The argument tt(remote-path) must
80 path of an existing file on the monitor. The argument tt(remote-path) must
8181 be the full path to a file on the client. If the remote file already exists,
8282 it is overwritten by tt(PUT). Remaining commands in the policy file are
8383 executed, even if the copying process wasn't successful.
109109 it() bf(CHECK) [bf(LOG =)] tt(logfile [pathOffset] command)
110110
111111 Execute tt(command) on the client, using the bf(SSH) command
112 shell. The phrase `bf(LOG =)' is optional. The tt([pathOffset]) specification
113 is also optional, and has the same meaning as for the tt(LOCAL CHECK) command,
114 described above.
112 shell.
113
114 The phrase bf(LOG =) is optional. When a relative file location is
115 specified at tt(<file-spec>) it is interpreted relatively to the tt(USE BASE)
116 path specification.
117
118 tt(PathOffset) is also optional, and has the same meaning as for the tt(LOCAL
119 CHECK) command, described above.
115120
116121 The command must succeed. The output of this command is compared to the
117122 output of this command generated during the previous run of s(). Any
120125 tt(YYYYMMDD-HHMMSS) being the datetime-stamp at the time s() was run.
121126
122127 Note that the command is executed on the client, but the logfile is kept
123 at the controller. This command represents the core of the method implemented
128 at the monitor. This command represents the core of the method implemented
124129 by s(): there will be no residues of the actions performed by s() on client
125130 computers.
126131
148153 it() bf(NOTEST CHECK) [bf(LOG =)] tt(logfile [pathOffset] command)
149154
150155 Execute tt(command) on the client, using the bf(SSH) command
151 shell. The phrase `bf(LOG =)' is optional. The tt([pathOffset]) is also
152 optional, and has the same meaning as for the tt(LOCAL CHECK) command,
153 described above. The command may or may not succeed. Otherwise, the program
154 acts identically as the bf(CHECK ...) command, described above.
156 shell.
157
158 The phrase bf(LOG =) is optional. When a relative file location is
159 specified at tt(<file-spec>) it is interpreted relatively to the tt(USE BASE)
160 path specification.
161
162 tt(PathOffset) is also optional, and has the same meaning as for the tt(LOCAL
163 CHECK) command, described above. The command may or may not
164 succeed. Otherwise, the program acts identically as the bf(CHECK ...) command,
165 described above.
155166 Example (using the same tt(${SHA1SUM}))definition:
156167 verb( NOTEST CHECK LOG = remote/sha1.root /usr/bin/find / ${SHA1SUM})
157168 The SHA1 checksums of all suid/gid/executable files on the same device as
33 itemization(
44 it() bf(USE BASE) tt(basedirectory)
55
6 bf(BASE) defines the directory from where s() operates. All
7 relative path specifications are interpreted relative to bf(BASE). em(By
8 default) this is the directory where s() was started.
6 bf(BASE) defines the directory from where s() operates. All relative
7 path specifications in this section of the policy file are interpreted
8 relative to bf(BASE). em(By default) this is the directory where s() was
9 started.
910
1011 If necessary, s() creates all bf(BASE) and other directories below
1112 tt(BASE).
1819 it() bf(USE DD) tt(<dd>)nl()
1920 The bf(DD) specification uses tt(/bin/dd) as default, and defines the
2021 location of the bf(dd)(1) program, both on the server and on the client. The
21 bf(DD) program is used to copy files between the client and the controller
22 bf(DD) program is used to copy files between the client and the monitor
2223 without creating separate ssh-connections. The bf(DD) program is only
2324 used by s() for the tt(PUT) and tt(GET) commands, described below.
2425
8990 taken as a string, and the information beyond the first string is thereupon
9091 interpreted.
9192
92 it() bf(USE REPORT) tt(reportfile)
93 it() bf(USE REPORT) tt(<file-spec>)nl()
94 bf(REPORT) defines the name of the reportfile. Information is always
95 appended to this file. At each s() integrity scan a em(time marker line) is
96 written to the report file. Only when (in addition to the marker line)
97 additional information is appended to the report file the added contents of
98 the report file are mailed to the mail address specified in the bf(USE EMAIL)
99 specification. When a relative file specification is used it is interpreted a
100 location relative to the tt(USE BASE) specification.nl()
101 Example showing the default:nl()
102 tt(USE REPORT report)
93103
94 bf(REPORT) defines the name of the reportfile. Information is always
95 appended to this file. For each s() run a em(time marker line) is
96 written to the report file. Such a marker line looks like this:
97 verb( STEALTH (1.11) started at Mon Jun 16 12:57:26 2003)
98 Only when (in addition to the marker line)
99 additional information was appended to the report file, the added contents of
100 the report file are mailed to the mail address specified in the bf(USE EMAIL)
101 specification.
104 it() bf(USE SH) tt(<sh>)nl()
105 The bf(SH) specification uses tt(/bin/sh) as default, and defines the
106 command shell used by the monitor to execute commands on itself. This must be
107 an absolute path specification.nl()
108 Example showing the default:nl()
109 tt(USE SH /bin/sh)
102110
103 Example showing the default:
104 verb( USE REPORT report)
111 it() bf(USE SSH) tt(<user>)nl()
112 bf(The SSH specification has no default), and em(must) be
113 specified. This must be an absolute path specification.
105114
106 it() bf(USE SH) tt(sh-specification)
115 Assuming the client em(trusts) the monitor (which is after all what this
116 program is all about, so this should not be a very strong assumption),
117 preferably the public ssh key of the monitor should be placed in the
118 client's root tt(.ssh/authorized_keys) file, granting the monitor root access
119 to the client. Root access is normally needed to gain access to all
120 directories and files of the client's file system.
107121
108 The bf(SH) specification uses tt(/bin/sh) as default, and defines the
109 command shell used by the controller to execute local commands.
110
111 Example showing the default:
112 verb( USE SH /bin/sh)
113
114 it() bf(USE SSH) tt(ssh-specification)
115
116 bf(The SSH specification has no default), and em(must) be
117 specified. Assuming the client em(trusts) the controller (which is, after all,
118 what this program is all about; so this should not be a very strong
119 assumption), preferably the public ssh-identity key of the controller should
120 be placed in the client's root tt(.ssh/authorized_keys) file, granting the
121 controller root access to the client. Root access is normally needed to gain
122 access to all directories and files of the client's file system.
123
124 In practice, connecting to a account using the bf(sh)(1) shell is
122 In practice, connecting to an account using the bf(sh)(1) shell is
125123 preferred. When another shell is already used by that account, one should make
126 sure that that shell doesn't setup its own redirections for standard input and
127 standard output. One way to accomplish that is for force the execution of
128 tt(/bin/sh) in the bf(USE SSH) specification.
124 sure that its shell doesn't define its own redirections for standard input
125 and standard output. One way to accomplish that is for force the execution of
126 tt(/bin/sh) in the bf(USE SSH) specification.
129127
130128 An example of an tt(SSH) specification to scan a localhost is:
131 verb( USE SSH root@localhost -T -q # root's shell is /bin/sh)
129 verb(
130 USE SSH root@localhost -T -q # root's shell is /bin/sh)
132131
133132 The same, now explicitly using tt(/bin/bash):
134 verb( USE SSH root@localhost -T -q exec /bin/bash # root uses another shell)
133 verb(
134 USE SSH root@localhost -T -q exec /bin/bash # root uses another shell)
135135
136136 Alternatively, tt(--noprofile) can be specified to prevent any
137137 profile-initialization:
138 verb( USE SSH root@localhost -T -q exec /bin/bash --noprofile)
138 verb(
139 USE SSH root@localhost -T -q exec /bin/bash --noprofile)
139140 )
140 Using tt(stealth) to inspect tt(localhost) is em(not)
141 recommended, as it counters one of the main reasons for tt(stealth)'s
142 existence.
143141
144 itemization(
145 it() Yet another alternative, applicable only to tt(localhost). tt(Ssh)
146 could completely be avoided, specifying tt(/bin/bash) or a comparable shell
147 with the tt(USE SSH) directive. For example:
142 In some installations s() is used to inspect the monitor itself, even
143 though this is em(not) recommended, as it breaks one of the main reasons for
144 s()'s existence. But in those situations (so, where s() is used to monitor the
145 integrity of the tt(localhost)), tt(/bin/bash) could be specified at the
146 tt(USE SSH) directive. For example:
148147 verb( # For stealth inspecting localhost:
149148 USE SSH /bin/bash --noprofile)
150 )
0 Next, we check the received tt(sha1sum) program, using our own:
0 Next, we check the integrity of the received tt(sha1sum) program. For this, we
1 use the monitor's tt(sha1sum) program:
12 verb(
23 LABEL \nCheck the client's sha1sum program
34 LOCAL CHECK LOG = local/sha1 /usr/bin/sha1sum /root/tmp/sha1sum
910 client. The report is written on the file
1011 tt(/root/stealth/client/local/sha1). If this fails, s() terminates, alerting
1112 tt(admin@elsewhere) that the check failed. This is a serious event, as it
12 indicates that either the controller's tt(sha1sum) is behaving unexpectedly or
13 indicates that either the monitor's tt(sha1sum) is behaving unexpectedly or
1314 that the client's tt(sha1sum) program has unexpectedly changed.
1415
1516 The tt(sha1sum) program em(may) have changed due to a normal upgrade. If
44 know that the client's tt(sha1sum) program is OK, we can use it to check the
55 client's tt(/usr/bin/find) program.
66
7 Note that the controller itself will not suffer any processing load here: only
8 the client itself is taxed for checking the intergrity of its own files:
9 verb( LABEL \nchecking the client's /usr/bin/find program
7 Note that the monitor itself no longer needs to invest any significant
8 processing load: only the client itself is taxed for checking the integrity
9 of its own files:
10 verb(
11 LABEL \nchecking the client's /usr/bin/find program
1012 CHECK LOG = remote/binfind /usr/bin/sha1sum /usr/bin/find)
1113
22 client. For this we activate the tt(sha1sum) program on the client. In
33 order to check the setuid/setgid files, the following command is added to the
44 policy file:
5 verb( LABEL \nsuid/sgid/executable files uid or gid root on the / partition
5 verb(
6 LABEL \nsuid/sgid/executable files uid or gid root on the / partition
67 CHECK LOG = remote/setuidgid /usr/bin/find / ${EXECSHA1})
78
0 First, we copy the client's tt(sha1sum) program to the controller. In
0 The following commands are now defined:
1 itemization(
2 it() first, we copy the client's tt(sha1sum) program to the monitor. In
13 practice, this should also include the shared object libraries that are used
2 by tt(sha1sum), as they might have become corrupted as well.
4 by tt(sha1sum), as they might have become corrupted as well;
5 it() Once tt(sha1sum) is locally available its integrity is verified;
6 it() Once the integrity of the client's tt(sha1sum) has been verified, it
7 is used to verify the integrity of the client's tt(/usr/bin/find) program;
8 it() Following this, all setuid and setgid root files are located and
9 checked for integrity;
10 it() Finally, the integrity of the client configuration files under
11 tt(/etc) is verified;
12 )
313
14 In this manual the bf(sha1sum)(1) program is frequently used when checking
15 hash values. Stronger hash functions (like bf(sha256sum)(1) might be preferred
16 in practice. tt(sha256sum's) hash values are remarkably longer than
17 tt(sha1sum's) hash values. When using these longer hash values in the manual
18 it often clobbers the layout of examples. Therefore in this manual
19 bf(sha1sum)(1) is continued to be used.
20
21 Realize, however, that when updating existing policy files to use
22 bf(sha256sum)(1) instead of bf(sha1sum)(1), that previously generated log
23 files (that used bf(sha1sum)(1)) are incompatible with log files obtained when
24 using bf(sha256sum)(1). In practice this means that new log files need to be
25 generated, and any previously geneerated log files must be disregarded.
26
11 tt(/etc/cron.d/stealth) could be created, containing a line like
22 verb(
33 2,17,32,47 * * * * root test -x /usr/bin/stealth && \
4 /usr/bin/stealth -q /root/stealth/client.pol
4 /usr/bin/stealth /root/stealth/client.pol
55 )
66 This starts s() 2 minutes after every hour. In this example the ssh-key
77 must not require a passphrase, as bf(crontab)(1) cannot provide passphrases of
1717 option. For example, the s() daemon started by the following command
1818 repeatedly performs integrity scans between two and five minutes after the
1919 last integrity scan completed:
20 verb( stealth -d /var/run/client.pid -r 2m -i 3m /root/stealth/client.pol)
20 verb(
21 stealth --daemon /root/stealth/client.uds \
22 --repeat 2m --random-interval 3m /root/stealth/client.pol)
23 Once this program has started its bf(ssh)(1) connection to the client host
24 persists, and a possibly required ssh-passphrase is no longer
25 required. Additional (intermediate) integrity scans can always be requested
26 (also without requiring ssh-passphrase specifications) using the command
27 verb(
28 stealth --rerun /root/stealth/client.uds)
29
00 First we write some tt(DEFINE) directives simplifying complex command
11 specifications:
2 verb( DEFINE SSHCMD /usr/bin/ssh root@client -T -q exec /bin/bash --noprofile
2 verb(
3 DEFINE SSHCMD /usr/bin/ssh root@client -T -q exec /bin/bash --noprofile
34 DEFINE EXECSHA1 -xdev -perm +u+s,g+s \( -user root -or -group root \) \
45 -type f -exec /usr/bin/sha1sum {} \;)
56 The first tt(DEFINE) defines the tt(ssh) command to use: an ssh-connection
11 has developed. In that case, further actions by s() would be suspect, as their
22 results might easily be currupted. Additional checks em(will) be performed,
33 but a warning is generated on the tt(report) file (and in the mail sent to
4 tt(admin@elsewhere):
5 verb( STEALTH (3.00.00) started at Wed, 20 Aug 2014 11:13:38 +0000
4 tt(admin@elsewhere)):
5 verb(
6 STEALTH (4.00.00) started at Sat, 07 Feb 2015 22:27:15 +0100
67
78 Check the client's sha1sum program
89 MODIFIED: /root/tmp/sha1sum
4747
4848 it() The file tt(/root/client/report) bf(New lines are always appended to
4949 the tt(/root/client/report) file. It will never shorten, unless shorten by
50 the systems administrator at `controller').
50 the systems administrator at `monitor').
5151
5252 This file contains the following:
5353 verb( STEALTH (3.00.00) started at Wed, 20 Aug 2014 11:06:50 +0000
00 As s() is mainly a system administrator's tool, it could be
1 installed in tt(/usr/bin). In that case, do (as em(root)) from the
1 installed in tt(/usr/bin). In that case, do (as em(root)) in the
22 directory where s() was compiled/unpacked:
33 verb( ./build install program)
44 Alternatively, another default location may be specified in the
66 verb( ./build install program /usr/local/bin/stealth)
77 installing the binary program as tt(/usr/local/bin/stealth).
88
9 The provided tt(icmake build) script can be started without arguments for an
10 overview of possible commands.
11
12
55 bf(logrotate)(1). Logrotate (on Debian systems) keeps its configuration files
66 in tt(/etc/logrotate.d), and assuming there is a host tt(target), whose report
77 file is tt(/var/stealth/target/report), the required bf(logrotate)(1)
8 specification file (e.g., tt(/etc/logrotate.d/target) could be:
8 specification file (e.g., tt(/etc/logrotate.d/target)) could be:
99 verbinclude(../../../share/etc/logrotate.d/target)
1010 Using this specification file, bf(logrotate)(1) will
1111 itemization(
1212 it() perform weekly rotations of the report file;
1313 it() keep up to 12 rotated files, compressing them using bf(gzip)(1);
1414 it() suspend the s() daemon, before rotating its report file;
15 suppressed;
15 suspended;
1616 it() following the rotation, s()'s actions are resumed.
1717 )
1818 Note thet tt(stealth --resume xxx) always initiates another file integrity
00 The tt(/root/bin/stealthmail) script is called with the following arguments:
1 verb( "Client STEALTH report" admin@elswhere)
1 verb(
2 "Client STEALTH report" admin@elswhere)
23
34 The mailed report contains information comparable to this:
4 verb( STEALTH (3.00.00) started at Wed, 20 Aug 2014 11:06:50 +0000
5 verb(
6 STEALTH (4.00.00) started at Sat, 07 Feb 2015 22:10:56 +0100
57
68 Check the client's sha1sum program
79 Initialized report on local/sha1
11 store information about the host tt(client) under the subdirectory
22 tt(/root/stealth/client).
33
4 Stealth reports should be sent to the user tt(admin@elsewhere), who is only
5 interested in a short notice of changes, as the full report can always be read
6 elsewhere. For this a support-script was developed filtering the report
7 generated by s() down to its essentials.
4 Furthermore, we assume that reports of s() integrity-scans should be sent to
5 the user tt(admin@elsewhere), who is only interested in receiving a short
6 summary of changes, as the full report can always be read at the monitor
7 itself. To accomplish this a small support-script was developed, filtering the
8 report generated by s() down to its essentials.
89
910 As the tt(sha1sum) program on the client may be compromised, it is a good idea
10 to transfer the client's tt(sha1sum) program to the controller first,
11 verifying the integrity of that program at the controller, before trusting it
12 to compute the sha1sums of the client's files. The same holds true for any
13 libraries and support programs (like tt(find)) that are used intensively
14 during integrity scans.
11 to start the integrity scan by transferring the client's tt(sha1sum) program
12 to the monitor first, to verify the integrity of that program locally (i.e.,
13 at the monitor), before trusting it to compute sha1sums of the client's
14 files. The same holds true for any libraries and support programs (like
15 tt(find)) that are used intensively during integrity scans.
1516
1617 Sha1sum checks should be performed on all setuid and setgid files on the
1718 tt(client), and in order to be able reach all files on tt(client),
18 tt(root@controller) is allowed to login to the tt(root@client) account using
19 tt(root@monitor) is allowed to login to the tt(root@client) account using
1920 an tt(ssh) connection.
2021
2122 Furthermore, sha1sum checks should be performed on all configuration files,
22 living under tt(/etc) and on the file tt(/usr/bin/find) which is used
23 intensively to perform the checks.
23 living under tt(/etc) and on the file tt(/usr/bin/find) (which is used
24 intensively when performing the integrity checks).
2425
26 Next, the construction of the required tt(policy) file, implementing the
27 abovementioned requirements, is described in the following subsections.
2528
26 The required tt(policy) file is now constructed according to the
27 abovementioned requirements.
28
11 tt(root/stealth/client). If nothing has changed, the log-files remain
22 unaltered. Subsequent runs will, however, add some new info to the file
33 tt(/root/client/report):
4 verb( STEALTH (3.00.00) started at Wed, 20 Aug 2014 11:06:50 +0000
4 verb(
5 STEALTH (4.00.00) started at Sat, 07 Feb 2015 22:10:56 +0100
56
67 Check the client's sha1sum program
78 Initialized report on local/sha1
1516 configuration files under /etc
1617 Initialized report on remote/etcfiles
1718
18 STEALTH (3.00.00) started at Wed, 20 Aug 2014 11:13:38 +0000)
19 STEALTH (4.00.00) started at Sat, 07 Feb 2015 22:22:15 +0100)
1920 Note that just one extra line was added: a timestamp showing the date/time
2021 of the last run. The systems administrator may rotate the report file every
2122 once in a while to reclaim some disk space.
0 First, the tt(sha1sum) program is copied to a local directory:
1 verb( GET /usr/bin/sha1sum /root/tmp)
0 To copy the client's tt(sha1sum) program to a local directory we specify:
1 verb(
2 GET /usr/bin/sha1sum /root/tmp)
23 This command must succeed.
34
00 Short options are provided between parentheses, immediately following
1 their long option equivalents. Option descriptions starting with (C) can only
2 be used on the command-line, and are ignored when specified in the second
3 section of the policy file.
1 their long option equivalents.
2
3 Option descriptions showing (C) can only be used on the command-line, and
4 are ignored when specified in the second section of the policy file.
5
6 In the overview of options `tt(<uds>)' represents the name of the
7 em(Unix Domain Socket) to use, and `tt(<file-spec>)' refers to a (relative or
8 absolute) specification of a file location.
9
10 With the first and second synopses relative locations (of the Unix Domain
11 Socket and of other file-specifications) are interpreted relative to the
12 current working directory.
13
14 Command-line options overrule options defined in the policy-file.
415
516 itemization(
6 it() tt(--daemon (-d) <path>): (C) run as background (daemon)
7 process. tt<path> specifies the absolute filename of the pid-file used
8 for communication with the daemon process;
17 it() tt(--daemon (-d) <uds>): (C) run as background (daemon)
18 process. When the Stealth daemon process is started, the Unix Domain
19 Socket (tt<uds>) may not already exist.
920 it() tt(--dry-run): (C) no integrity scans or reloads are performed, but
1021 are assumed OK. Remaining tasks are normally performed;
1122 it() tt(--help (-h)): (C) Display help information and exit;
12 it() tt(--log (-L) <path>): log messages are appended to `path'. If path
13 does not exist, it is first created;
23 it() tt(--log (-L) <file-spec>): log messages are appended to
24 `file-spec'. If file-spec does not exist, it is first created;
1425 it() tt(--logmail): mail sent by s() is logged (requires tt(--log) or
1526 tt(--syslog));
1627 it() tt(--max-size <size>[BKMG]): files retrieved by tt(GET) commands may
2839 interval of <interval> seconds (or minutes if an `m' is appended (no
2940 blanks) to <interval>) following the delay specified at tt(--repeat)
3041 (see below). This option requires specification of the tt(--repeat)
31 option;
32 it() tt(--reload <pid-file>): (C) reloads the configuration and skip-files
33 and restarts the scan of the s() daemon process.
42 and tt(--daemon) options;
43 it() tt(--reload <uds>): (C) reloads the configuration and skip-files
44 and restarts the scan of the s() daemon process. Options defined in
45 the policy file are also reloaded. However, command-line options
46 always take priority over options defined in the policy file, so when
47 command-line options were used when starting s() in daemon mode, they
48 cannot be modified by reloading the policy file.
3449 it() tt(--repeat <seconds>): wake up and perform an integrity scan at
3550 interrupts or after tt(<seconds>) seconds (or minutes if an `m' is
3651 appended (no blanks) to <seconds>) after completing the previous
3752 integrity scan. The option tt(--random-interval) can be used to add a
3853 random delay to tt(<seconds>) until the next integrity scan is
39 performed.
40 it() tt(--rerun <pid-file>): start executing the integrity scan commands
41 that are specifed in the s() daemon process's policy file;
42 it() tt(--resume <pid-file>): (C) resume a suspended s() process, implies
54 performed. This option requires specification of the and tt(--daemon)
55 option;
56 it() tt(--rerun <uds>): (C) start executing the integrity scan
57 commands that are specifed in the s() daemon process's policy file;
58 it() tt(--resume <uds>): (C) resume a suspended s() process, implies
4359 tt(--rerun);
4460 it() tt(--run-command (-r) <nr>): (C) Only execute command number <nr>
4561 (natural number). Command numbers are shown by s()
46 tt(---parse-policy-file);
47 it() tt(--skip-files (-s) <skippath>): all entries in tt(skippath)
48 (specified using an em(absolute path)) are skipped. Their integrity is
49 not monitored. If an entry is already present in a log file then s()
50 once generates an tt(IGNORING) message in the mail sent to the address
51 specified at tt(EMAIL) in the policy file. Each entry mentioned in
52 tt(filepath) must be on a line of its own and must be specified using
53 absolute paths. Entries ending in a slash are assumed to be
54 directories whose full contents must be skipped. Other entries are
55 interpreted as the path names of files to skip. Initial and trailing
56 blanks, empty lines and lines having a tt(#) as their 1st non blank
57 character are ignored.
62 tt(---parse-policy-file). This option can only be specified using the
63 second synopsis;
64 it() tt(--skip-files (-s) <file-spec>): all entries in tt(<file-spec>) are
65 skipped. Their integrity is not monitored. If an entry is already
66 present in a log file then s() once generates an tt(IGNORING) message
67 in the mail sent to the address specified at tt(EMAIL) in the policy
68 file. Each entry mentioned in tt(file-spec) must be on a line of
69 its own and must be specified using absolute file paths. Entries
70 ending in a slash are assumed to be directories whose full contents
71 must be skipped. Other entries are interpreted as the names
72 of files to skip. Initial and trailing blanks, empty lines and lines
73 having a tt(#) as their 1st non blank character are ignored. Here are
74 some examples:
75 verb(
76 # skip all files in user's Mail directory
77 /home/user/Mail/
78 # skip user's .history file
79 /home/user/.history
80 )
5881 it() tt(--stdout (-o)): messages are (also) written to the std. output
59 stream (not available when for option tt(--daemon));
60 it() tt(--suspend <pid-file>): (C) suspends a currently active s()
61 process. Use tt(--resume) to re-activate an s() daemon or
62 tt(--terminate) to end an s() daemon;
82 stream (only available with the second synopsis);
83 it() tt(--suspend <uds>): (C) suspends a currently active s()
84 process. Following tt(--suspend) use tt(--resume) to re-activate an
85 s() daemon or tt(--terminate) to end an s() daemon;
6386 it() tt(--syslog): write syslog messages;
6487 it() tt(--syslog-facility <facility>): syslog facility to use. By
6588 default facility DAEMON is used;
6891 it() tt(--syslog-tag <tag>): tt(<tag>) specifies the identifier that is
6992 prefixed to syslog messages. By default the tag `STEALTH' is used, see
7093 also the next section;
71 it() tt(--terminate <pid-file>): (C) terminate a currently active s()
94 it() tt(--terminate <uds>): (C) terminate a currently active s()
7295 process;
7396 it() tt(--time-stamp (-t) <type>): the time-stamps to use. By default
7497 UTC. To use the local time specify tt(--time-stamp
79102 information. Requires options tt(--log) or tt(--syslog). Possible
80103 values are:nl()
81104 0: nothing is logged+nl()
82 1: mode reports and policy commands+nl()
105 1: (default) mode reports and policy commands+nl()
83106 2: also: ipc commands and actions+nl()
84107 3: also: integrity scan informative messages
85108 it() tt(--version (-v)): (C) Display s()'s version information and
87110 )
88111
89112 itemization(
90 it() tt(<pid-file>): absolute filename of a file that is used for
91 communication with a s() daemon process;
92 it() tt(policy): path to the policy file;
113 it() tt(policy): file specification of the policy file. If a relative
114 location is specified then this location is interpreted relative to
115 the current working directory. S() converts this relative
116 specification to an absolute file location, and an option like
117 tt(--reload) will reload the policy file from the thus determined
118 absolute file path.
93119 )
94120
95 Only one of the options tt(--daemon, --reload, --rerun, --resume,
96 --suspend,) and tt(--terminate) can be specified. The options tt(--reload,
121 Only one of the options tt(--daemon, --reload, --resume,
122 --suspend) or tt(--terminate) can be specified. The options tt(--reload,
97123 --rerun, --resume, --suspend,) and tt(--terminate) ignore any other options.
98124
99125 The following options are still recognized for backward compatibility with s()
100 pre-3.00 versions and will be removed in future versions. They generate error
101 messages suggesting alternatives:
126 pre-3.00 versions and will be removed in a future s() version. They generate
127 error messages suggesting alternatives:
102128
103129 itemization(
104130 it() tt(--echo-commands (-e)):
109135 tt(--stdout) instead.
110136 it() tt(--quiet (-q)): suppresses progress messages written to stderr; use
111137 tt(--verbosity 0) instead.
112 it() tt(--suppress <pid-file>): suppresses a currently active s()
138 it() tt(--suppress <uds>): suppresses a currently active s()
113139 process; use tt(--suspend) instead.
114140 )
115141
116 The following options were discontinued starting with s() version 3.00.00:
142 The following options were discontinued starting since s() version 3.00.00:
117143 itemization(
118144 it() tt(--debug) (option tt(--verbosity) or tt(--dry-run) could be used
119145 instead);
121147 it() tt(--parse-config-file).
122148 )
123149
124 When specifying long options in policy files the initial hyphens should be
150 When specifying long options in policy files initial hyphens should be
125151 omitted. Here are some examples:
126152 verb( %%
127153 log /tmp/stealth.log
88
99 For example, if a s() process was once started using the command
1010 COMMENT(KEEP A BLANK FOLLOWING THE BACKSLASH)
11 verb( stealth --daemon /var/run/small.pid --repeat 900 \
12 /var/stealth/policies/small.pol)
11 verb(
12 stealth --daemon /root/stealth/small.uds --repeat 900 \
13 /root/stealth/small.pol)
1314 then the tt(--suspend) and tt(--resume) commands for this process should
1415 be called as:
15 verb( stealth --suspend /var/run/small.pid
16 stealth --resume /var/run/small.pid)
16 verb( stealth --suspend /root/stealth/small.uds
17 stealth --resume /root/stealth/small.uds)
1718 The s() process identified in the files provided as arguments to
1819 the tt(--suspend) and tt(--resume) options is called the em(daemon stealth
1920 process) below.
2627 except for tt(--resume) (see below) and tt(--terminate).
2728 it() Any scheduled integrity scans following the tt(--suspend) command
2829 are ignored by the daemon s() process;
29 it() The daemon s() process writes a message that it is
30 being suspended to the report file and then processes the report file as
31 usual.
30 it() The daemon s() process writes a message that it is being suspended to
31 the report file and then processes the report file as usual.
3232 )
33 Now that the report file will no longer be affected by the daemon
33 Now that the report file is no longer modified by the daemon
3434 s() process, log-rotation may take place. E.g., a program like
3535 bf(logrotate)(1) allows its users to specify a command or script just before
36 log-rotation takes place, and `s() tt(--suspend pidfile)' could be
36 log-rotation takes place, and `s() tt(--suspend udsfile)' could be
3737 specified nicely in such a pre-rotation section.
3838
3939 The tt(--resume) option has the following effect:
5353 itemization(
5454 it() Wait for the daemon s() process to complete an ongoing series of
5555 integrity scan commands;
56 it() Issue the `s() tt(--terminate pidfile)' command.
56 it() Issue the `s() tt(--terminate udsfile)' command.
5757 )
33 the absolute paths of entries to be skipped. Each entry should appear on a
44 line of its own without any additional information.
55
6 S() can be informed about this file using the tt(--skip-files skippath)
7 option. The file holding the paths of the entries to be skipped should be
8 specified using absolute paths, using one entry per line. Initial and trailing
9 blanks, empty lines and lines having a tt(#) as their first non blank
10 character are ignored.
6 S() can be informed about this file using the tt(--skip-files <file-spec>)
7 option. When a relative file specification is used with tt(--skip-files) it is
8 interpreted a location relative to the current working directory. The
9 skip-files file itself must contain the paths of the entries to be skipped
10 during file integrity scans. If an entry is already present in a log file then
11 s() once generates an tt(IGNORING) message in the mail sent to the address
12 specified at tt(EMAIL) in the policy file. Each entry in a skip-file must be
13 on a line of its own and must be specified using absolute file paths. Entries
14 ending in a slash are assumed to be directories whose full contents must be
15 skipped. Other entries are interpreted as the names of files to skip. Initial
16 and trailing blanks, empty lines and lines having a tt(#) as their 1st non
17 blank character are ignored.
1118
1219 Here is an example:
13 verb( stealth -e --skip-files /root/stealth/remote/skipping remote.pol)
20 verb(
21 stealth -e --skip-files /root/stealth/remote/skipping remote.pol)
1422
1523 If an entry tt(/etc/skipme) appears in the current logs which is thereafter
1624 added to the tt(skippath) file then the mail generated by s()
2727 tt(/etc/stealth/cleanup.rc) and the tt(stealthcleanup) script itself in
2828 tt(/usr/bin/stealthcleanup), the tt(stealthcleanup) script could be called
2929 as follows:
30 verb( /usr/bin/stealthcleanup /etc/stealth/cleanup.rc)
30 verb(
31 /usr/bin/stealthcleanup /etc/stealth/cleanup.rc)
3132 Note that tt(stealthcleanup) may be called whether or not there are active
32 s() processes, as s() does not use status files anymore once
33 they have been written.
33 s() processes.
34
35
36
37
0 Next we specify some tt(USE) directives, to fit our specific, local,
1 situation:
2 verb( USE BASE /root/stealth/client
0 Next some tt(USE) directives, matching our specific, local,
1 situation, are defined:
2 verb(
3 USE BASE /root/stealth/client
34 USE EMAIL admin@elswhere
45 USE MAILER /root/bin/stealthmail
56 USE MAILARGS "Client STEALTH report"
67 USE SSH ${SSHCMD})
8
79 itemization(
810 it() All output is written under the tt(/root/stealth/client) directory;
911 it() Mail is sent to the user tt(admin@elsewhere);
5252 chapter(Granting access)
5353 includefile(access/intro)
5454
55 subsect(The controller's user: creating an ssh-key)
56 includefile(access/controller)
55 subsect(The monitor's user: creating an ssh-key)
56 includefile(access/monitor)
5757
58 subsect(The client's account: accepting ssh from the controller's user)
58 subsect(The client's account: accepting ssh from the monitor's user)
5959 includefile(access/client)
6060
6161 subsect(Logging into the account@client account)
124124 subsubsect(Checking the client's setuid/setgid files)
125125 includefile(running/checkingsetuid)
126126
127 subsubsect(Checking the configuration files in the client's /etc/ directory)
127 subsubsect(Checking the configuration files in the
128 client's /etc/ directory)
128129 includefile(running/checkingconfig)
129130
130131 subsect(The complete `policy' file)
0 With 4.00.00:
1
2 itemization(
3 it() Version 3.00.00 was only short-lived. The inter-process communication
4 using signals never ran smoothly. Version 4.00.00 re-implements s()'s
5 inter-process communication using Unix Domain Sockets.
6 it() Previously required absolute file paths are no longer required. When
7 relative file paths are used with the s() daemon or with s()
8 performing an integrity scan as foreground process they are
9 interpreted relatively to the current working directory. Relative
10 file locations for options specified in the second section of the
11 policy file are interpreted relative to the location of the policy
12 file, and relative path specifications used in the first section of
13 the policy file are interpreted relative to the policy file's tt(USE
14 BASE).
15 it() The README.flow file is provided with several separately provided
16 illustrative images in the distribution-provided directory
17 tt(documentation/images).
18 it() Specifications for the logrotate specifications should use
19 'tt(copytruncate)' and 'tt(sharedscripts)' (see section ref(ROTATE)
20 for an example)
21 it() Examples in the manual still use tt(sha1sum) when checking hash
22 values. Stronger hash functions (like tt(sha256sum)) might be
23 preferred in practice. When updating existing policy files to use
24 tt(sha256sum) rather than tt(sha1sum) realize that tt(sha256sum's)
25 hash values are longer than tt(sha1sum's) hash values, and that
26 therefore log files obtained when tt(sha1sum) was used are
27 incompatible with log files obtained when tt(sha256sum) was used. In
28 practice this means that new log files need to be generated,
29 disregarding any previously geneerated log files.
30 )
31
32
033 COMMENT(
134 With 3.00.00:
2 )
35
336 itemization(
437 it() Internally the flow control handling, in particular with s() running
538 as a daemon, has completely been redesigned.
4679 (some) long option specifications. See section ref(OPTIONS) for
4780 details.
4881 )
82 )
4983
5084 COMMENT(
5185 With 2.02.00:
117151
118152 Two new options were added to facilitate report-file rotations:
119153 itemization(
120 it() tt(--resume pidfile): resume a suppressed s()
154 it() tt(--resume pidfile): resume a suspended s()
121155 process (implying tt(--rerun));
122 it() tt(--suppress pidfile): suppress a currently active s()
123 process. All scheduled scans following tt(--suppress) are skipped,
156 it() tt(--suspend pidfile): suspend a currently active s()
157 process. All scheduled scans following tt(--suspend) are skipped,
124158 tt(--rerun) is ignored, but tt(--resume) and tt(--terminate)
125159 can be issued;
126160 )
127161 The report file should not be modified while integrity scans take
128162 place. The new options were added to make sure this requirement is met when
129163 the report file must be rotated. The bf(ssh) connections to clients remain
130 open between pairs of tt(--suppress) and tt(--resume) commands. See section
164 open between pairs of tt(--suspend) and tt(--resume) commands. See section
131165 ref(ROTATE) for details about these two options.
132166
133 Issues related to suppressing s() runs are:
167 Issues related to suspending s() runs are:
134168 itemization(
135169 it() cleaning up obsolete status files (section ref(STATUS));
136170 it() automating report- and status file rotation using external
00 #include "INSTALL.im"
11
22 #undef CXXFLAGS
3 #define CXXFLAGS "--std=c++11 -Wall -O2 -pthread"
3 #define CXXFLAGS "--std=c++14 -Wall -O2 -pthread"
44
55 #define MAIN "main.cc"
66 #define ADD_LIBRARIES "bobcat"
1010 #define REFRESH
1111 #define LIBRARY "modules"
1212 #define SHAREDREQ ""
13 #define CLS
1413 #define USE_ALL "a"
1514 #define SOURCES "*.cc"
1615 #define SCANGEN ""
0 // This icmconf file is used for compiling class-specific libraries in
1 // sub-directories.
2
03 #define USE_ECHO ON
14 #define CLS
25
47 #define THREAD ""
58 #endif
69
7 #define CXX "g++"
8 #define CXXFLAGS "--std=c++11 " ${THREAD} " -Wall -O2"
10 //#define CXX "g++"
11 #define CXX "g++-5"
12
13 #define CXXFLAGS "--std=c++14 " ${THREAD} " -Wall -O2"
914 #define SOURCES "*.cc"
1015 #define TMP_DIR "tmp"
1116 #define OBJ_EXT ".o"
22 void IntegrityScanner::checkSize(std::string const &fname, off_t length)
33 {
44 if (length > d_maxSize)
5 d_stealthLog <<
5 fmsg <<
66 "STEALTH - CAN'T CONTINUE: `" << fname << "' EXCEEDS MAX. "
77 "DOWNLOAD SIZE (" << d_options.maxSizeStr() << ")\n"
88 "STEALTH - THIS COULD POINT TO A SERIOUS SITUATION EXISTING AT "
99 "THE CLIENT\n"
1010 "STEALTH - THIS CONDITION MAY HAVE INVALIDATED THE CLIENT'S LOG "
1111 "FILES\n"
12 "STEALTH - *** INVESTIGATE ***" << StealthEnums::leave;
12 "STEALTH - *** INVESTIGATE ***" << noidl;
1313 }
1414
1515
66 ofstream currentReport(fname.c_str());
77
88 if (!currentReport)
9 d_stealthLog << "Can't open `" << fname << "' to write" <<
10 StealthEnums::leave;
9 fmsg << "Can't open `" << fname << "' to write" << noidl;
1110
1211 m3 << "copy: about to read child input" << endl;
1312
33 void IntegrityScanner::execute(string const &cmd)
44 {
55 if (!(s_firstWord << cmd)) // determine first word and the rest
6 d_stealthLog << "Corrupt line in policy file: " << cmd <<
7 StealthEnums::leave;
6 fmsg << "Corrupt line in policy file: " << cmd << noidl;
87 else
98 m1 << cmd << endl;
109
1616 string source = s_firstWord[1]; // get the (remote) source
1717
1818 if (!source.length())
19 d_stealthLog << "GET command requires source and destination" <<
20 StealthEnums::leave;
19 fmsg << "GET command requires source and destination" << noidl;
2120
2221 s_firstWord.match(s_firstWord[3]); // strip off source
2322 string destination = s_firstWord[1]; // get the local dest.
2423
2524 if (!destination.length())
26 d_stealthLog <<
27 "GET " << source << " <destination>': destination missing" <<
28 StealthEnums::leave;
25 fmsg << "GET " << source <<
26 " <destination>': destination missing" << noidl;
2927
3028 if (Stat(destination).isType(Stat::DIRECTORY)) // is the dest. a dir. ?
3129 destination += "/" + fileName(source);
99 #include <bobcat/process>
1010 #include <bobcat/pattern>
1111
12 #include "../stealthenums/stealthenums.h"
13
1214 class PolicyFile;
1315 class RunMode;
1416 class Options;
1517
16 class IntegrityScanner
18 class IntegrityScanner: public StealthEnums
1719 {
1820 typedef std::vector<std::string> StringVector;
1921 typedef StringVector::const_iterator const_iterator;
2022
2123 Options &d_options;
22 RunMode &d_run;
24 RunMode const &d_pending;
2325 PolicyFile &d_policyFile;
24 std::ostream &d_stealthLog;
26 std::ostream &d_report;
27
2528 FBB::Pattern d_firstWord;
2629 FBB::Process d_sshFork;
2730 FBB::Process d_shFork;
2932 std::string d_label;
3033 const_iterator d_cmdIterator;
3134 bool d_testExitValue;
35 bool d_active = false;
3236 size_t d_nScans;
3337 off_t d_maxSize;
3438 StringVector d_skipFiles;
35 std::string d_skipFilePath;
39 std::string d_skipFile;
3640 size_t d_diffPrefix;
3741 size_t d_pathOffset; // begin of the abs path if not
3842 // at the first / on a line
4751 static FBB::Pattern s_exitValue;
4852
4953 public:
50 IntegrityScanner(RunMode &run, PolicyFile &sorter,
51 std::ostream &stealthlog);
54 IntegrityScanner(RunMode const &pending, Options &options,
55 PolicyFile &policyFile, std::ostream &stealthlog);
5256
5357 size_t nScans() const
5458 {
5862 void loadSkipFiles();
5963 void nScansReset();
6064 // run one series of tests
61 void run();
65 void run();
6266
6367 void killChildren();
64
68
69 bool active() const;
70
6571 private:
6672
6773 void foreground(size_t cmdNr); // run 1 command
175181 d_nScans = 0;
176182 }
177183
184 inline bool IntegrityScanner::active() const
185 {
186 return d_active;
187 }
188
178189 #endif
00 #include "integrityscanner.h"
1
2 #include <sstream>
13
24 #include <bobcat/mstream>
35 #include <bobcat/stat>
46 #include <bobcat/datetime>
57 #include <bobcat/stringline>
6 #include <bobcat/exception>
78 #include <bobcat/ranger>
89
910 #include "../util/util.h"
1011 #include "../policyfile/policyfile.h"
11 #include "../stealthlog/stealthlog.h"
1212 #include "../runmode/runmode.h"
1313 #include "../options/options.h"
1414 #include "../msg/msg.h"
00 #include "integrityscanner.ih"
11
22 /*
3 Since the IntegrityScanner's destruction is also the termination of the program, no
4 explicit destruction of the newly created objects is necessary. A pointer is
5 used to prevent the construction of a constant object. As the constructor
6 itself would create a constant object, the construction *new...
3 Since the IntegrityScanner's destruction is also the termination of the
4 program, no explicit destruction of the newly created objects is necessary. A
5 pointer is used to prevent the construction of a constant object. As the
6 constructor itself would create a constant object, the construction *new...
77 is used.
88
99 */
1010
11 IntegrityScanner::IntegrityScanner(RunMode &run, PolicyFile &policyFile,
12 ostream &stealthLog)
11 IntegrityScanner::IntegrityScanner(RunMode const &pending, Options &options,
12 PolicyFile &policyFile, ostream &report)
1313 :
14 d_options(Options::instance()),
15 d_run(run),
14 d_options(options),
15 d_pending(pending),
1616 d_policyFile(policyFile),
17 d_stealthLog(stealthLog),
17 d_report(report),
1818 d_firstWord("(\\S+)(\\s+(.*))?"), // firstword ([1]) and the
1919 // rest ([3]) of a text
2020 d_sshFork
3737 d_pathOffset(numeric_limits<size_t>::max())
3838 {
3939 setSentinel();
40
4140 loadSkipFiles();
42
43 m2 << "(re)constructed the Integrity Scanner" << endl;
44 m3 << "max. download size: " << d_options.maxSizeStr() << endl;
4541 }
46
47
48
49
50
51
52
53
11
22 void IntegrityScanner::loadSkipFiles()
33 {
4 d_skipFilePath = d_options.skipFilePath();
4 d_skipFile = d_options.skipFile();
55
6 if (d_skipFilePath.length()) // skip files
6 if (d_skipFile.length()) // skip files
77 setSkip();
88 else // or don't skip
99 d_skip = &IntegrityScanner::dontSkip;
2121 if (removeFirstWord("CHECK")) // ... CHECK ...
2222 {
2323 if (!doCHECKcommand(d_shFork)) // so, do the command
24 d_stealthLog << "\n" // and check the result
24 d_report << "\n" // and check the result
2525 "*** BE CAREFUL *** REMAINING RESULTS MAY BE FORGED\n" <<
2626 endl;
2727 }
1010 "/bin/echo \"" << d_sentinel << " $?\"" << endl;
1111
1212 if (!out)
13 d_stealthLog << "Inserting command `" << s_firstWord[0] <<
14 "' failed." << StealthEnums::leave;
13 fmsg << "Inserting command `" << s_firstWord[0] << "' failed." <<
14 noidl;
1515 }
4545 // of the pair.
4646 //
4747 // At the end, if the hashtable has any elements, the table is inserted
48 // into the d_stealthLog and `false' is returned. If the hashtable contains
48 // into the d_report and `false' is returned. If the hashtable contains
4949 // no elements, 'true' is returned.
5050
5151 string line;
100100 }
101101
102102 if (d_label.length())
103 d_stealthLog << d_label << endl;
103 d_report << d_label << endl;
104104
105105 for
106106 (
110110 begin++
111111 )
112112 {
113 d_stealthLog << begin->second.first << ": " << begin->first << endl;
113 d_report << begin->second.first << ": " << begin->first << endl;
114114
115115 for
116116 (
120120 sbegin != send;
121121 sbegin++
122122 )
123 d_stealthLog << " " << *sbegin << endl;
123 d_report << " " << *sbegin << endl;
124124 }
125125
126126 string logFilename = logfile + "." + datetime();
1616
1717 string source = s_firstWord[1]; // get the (remote) source
1818 if (!source.length())
19 d_stealthLog << "PUT command requires source and destination" <<
20 StealthEnums::leave;
19 fmsg << "PUT command requires source and destination" << noidl;
2120
2221 s_firstWord.match(s_firstWord[3]); // strip off source
2322
2423 string destination = s_firstWord[1]; // get the local dest.
2524 if (!destination.length())
26 d_stealthLog << "At `PUT " << source <<
25 fmsg << "At `PUT " << source <<
2726 " <destination>': destination missing" <<
28 StealthEnums::leave;
27 noidl;
2928
3029 if (Stat(destination).isType(Stat::DIRECTORY)) // is the dest. a dir. ?
3130 destination += "/" + fileName(source); // then append sourcename
55 struct stat statbuf;
66
77 if (stat(source.c_str(), &statbuf))
8 d_stealthLog << "PUT " << source << ": can't stat it" << StealthEnums::leave;
8 fmsg << "PUT " << source << ": can't stat it" << noidl;
99
1010 ostringstream command;
1111
66 ofstream target(fname.c_str());
77
88 if (!target)
9 d_stealthLog << "Can't open `" << fname << "' to write" <<
10 StealthEnums::leave;
9 fmsg << "can't write `" << fname << '\'' << noidl;
1110
1211 char c;
1312 string partialSentinel;
1716
1817 while (true)
1918 {
20 if (!src.read(&c, 1)) // read char by char
21 {
22 d_run.setMode(RunMode::TERMINATE);
23 d_stealthLog << "Incomplete read from `" << fname << "'" <<
24 StealthEnums::leave;
25 return;
26 }
19 if (not src.read(&c, 1)) // read char by char
20 fmsg << "Incomplete read from `" << fname << "'" << noidl;
2721
2822 checkSize(fname, ++size); // throws if not OK
2923
11
22 void IntegrityScanner::run()
33 {
4 d_active = true;
5
46 ++d_nScans;
57
68 setSentinel(); // determine d_sentinel
1820
1921 for (auto &cmd: ranger(d_cmdIterator, beyond))
2022 {
21 if (d_run.interrupted()) // terminate, suspend, reload
23 if (d_pending.hasMode(SUSPEND | RELOAD | TERMINATE))
2224 {
2325 m1 << "integrity scan interrupted by " <<
24 d_run.modeName() << " request" << endl;
25 return;
26 d_pending << " request" << endl;
27 d_active = false;
2628 }
27
2829 execute(cmd);
2930 }
3031 }
3132
3233 m3 << "policy file processed" << endl;
34 d_active = false;
3335 }
34
35
36
37
38
44 string current = logfile + ".cur"; // create current logfile
55
66 if (!Util::mkdir(current)) // make sure directory exists
7 d_stealthLog << "Unable to create the logfile `" << current << "'" <<
8 StealthEnums::leave;
7 fmsg << "unable to create the logfile `" << current << '\'' << noidl;
98
109 m3 << "logs to " << current << endl;
1110
1211 copy(extractor, current); // copy the info in extractor
1312 // to the current logfile
1413
15 if (access(logfile.c_str(), R_OK)) // no old report yet
14 if (access(logfile.c_str(), R_OK) != 0) // no old report yet
1615 {
1716 m3 << "writing new report: " << logfile << '\n';
1817
1918 rename(current.c_str(), logfile.c_str()); // install `logfile'
2019
2120 if (d_label.length())
22 d_stealthLog << d_label << endl;
21 d_report << d_label << endl;
2322
24 d_stealthLog << "Initialized report on " << logfile << endl;
23 d_report << "Initialized report on " << logfile << endl;
2524
2625 m3 << "initialized report on " << logfile << endl;
2726 return true;
11
22 void IntegrityScanner::setSkip()
33 {
4 ifstream in;
5 Exception::open(in, d_skipFilePath);
4 ifstream in(d_skipFile);
5 if (not in)
6 fmsg << "cannot read skip-file `" << d_skipFile << '\'' << noidl;
67
78 for_each(
89 istream_iterator<StringLine>(in), istream_iterator<StringLine>(),
1920
2021
2122
23
33 std::string const &exitStr)
44 {
55 if (not (s_exitValue << exitStr))
6 d_stealthLog << "No exit value for\n" <<
6 fmsg << "No exit value for\n" <<
77 cmd << "\n"
8 "NOTE: this is the literal text of the executed command. "
9 "Maybe a typo?" << RunMode::leave;
8 "ADVICE: this is the literal text of the executed command. "
9 "Maybe a typo?" << noidl;
1010
1111 if (d_testExitValue && stoul(s_exitValue[1]) != 0)
12 d_stealthLog <<
13 d_options.basename() <<
12 fmsg << d_options.basename() <<
1413 " terminated: non-zero exit value for\n" <<
15 *d_cmdIterator << " (" << exitStr << ")" << RunMode::leave;
14 *d_cmdIterator << " (" << exitStr << ")" << noidl;
1615 }
1716
1817
66 ifstream source(fname.c_str());
77
88 if (!source)
9 d_stealthLog << "Can't open `" << fname << "' to read." <<
10 StealthEnums::leave;
9 fmsg << "can't read `" << fname << '\'' << noidl;
1110
1211 m3 << "about to read local `" << fname << '\'' << endl;
1312
2221 break;
2322
2423 if (!d_sshFork.write(buffer, nRead))
25 d_stealthLog << "PUT failed." << StealthEnums::leave;
24 fmsg << "PUT failed." << noidl;
2625 }
2726
2827 d_sshFork.flush();
+0
-10
ipc/data.cc less more
0 #include "ipc.ih"
1
2 LinearMap<std::string, StealthEnums::Mode> const IPC::s_request =
3 {
4 {"suspend", SUSPEND},
5 {"resume", RESUME},
6 {"rerun", RERUN},
7 {"reload", RELOAD},
8 {"terminate", TERMINATE},
9 };
+0
-5
ipc/frame less more
0 #include "ipc.ih"
1
2 IPC::
3 {
4 }
+0
-3
ipc/icmconf less more
0 #define LIBRARY "ipc"
1
2 #include "../icmconf2"
+0
-91
ipc/ipc.h less more
0 #ifndef INCLUDED_IPC_
1 #define INCLUDED_IPC_
2
3 #include <string>
4
5 //#include <bobcat/selector>
6
7
8 #include <bobcat/linearmap>
9
10 #include "../stealthenums/stealthenums.h"
11 #include "../wait11/wait11.h"
12
13 class Options;
14
15 class IPC: public StealthEnums
16 {
17 Options &d_options;
18
19 Wait11 d_wait11;
20
21 std::string d_requestText;
22 size_t d_requestorPid = 0;
23 size_t d_daemonPid;
24
25 static FBB::LinearMap<std::string, Mode> const s_request;
26
27 public:
28 IPC();
29 // always returns true, or
30 bool signalDaemon(); // throws exception on failure
31
32 StealthEnums::Mode request(); // retrieve the request/msg and
33 // requestor's pid
34 std::string const &requestText() const;
35
36 void sendRequestor(std::string const &msg);
37
38 void signaled(); // call after receiving a signal
39
40 void wait(bool doM2 = true); // wait until signaled
41
42 void timedWait(); // wait until signaled or wait
43 // until --repeat time has passed
44
45 void timedWait(size_t seconds); // wait until signaled or wait
46 // until seconds has passed
47 // (no m2 messages), called from
48 // the ipc-modes
49
50 bool timeout() const; // true if timedWait's waiting
51 // time has expired
52
53 void writeRunFile(pid_t pid);
54
55 void write(std::string const &msg) const; // write msg and own pid
56 // to the runfile
57 size_t daemonPid() const;
58
59 private:
60 void readDaemonPid();
61 void sendRequest(char const *request, pid_t pid);
62 };
63
64 inline void IPC::timedWait(size_t seconds)
65 {
66 d_wait11.waitFor(seconds, false);
67 }
68
69 inline void IPC::signaled()
70 {
71 d_wait11.notify();
72 }
73
74 inline bool IPC::timeout() const
75 {
76 return not d_wait11.signaled();
77 }
78
79 inline std::string const &IPC::requestText() const
80 {
81 return d_requestText;
82 }
83
84 inline size_t IPC::daemonPid() const
85 {
86 return d_daemonPid;
87 }
88
89 #endif
90
+0
-16
ipc/ipc.ih less more
0 #include "ipc.h"
1
2 #include <fstream>
3 #include <limits>
4 #include <csignal>
5
6 #include <bobcat/mstream>
7 #include <bobcat/exception>
8
9 // #include "../lock/lock.h"
10 #include "../options/options.ih"
11 #include "../msg/msg.h"
12
13 using namespace std;
14 using namespace FBB;
15
+0
-6
ipc/ipc1.cc less more
0 #include "ipc.ih"
1
2 IPC::IPC()
3 :
4 d_options(Options::instance())
5 {}
+0
-27
ipc/readdaemonpid.cc less more
0 #include "ipc.ih"
1
2 // daemonPid() obtains the process-id from an existing run-file. The file must
3 // exist and the pid stored in the lock-file must be the process-id of an
4 // existing Stealth program.
5
6 void IPC::readDaemonPid()
7 {
8 ifstream in;
9
10 string const &runFile = d_options.runFile();
11
12 Exception::open(in, runFile);
13
14 pid_t pid;
15
16 if (not (in >> pid))
17 fmsg << "daemonPid: Can't read `" << runFile << '\'' << endl;
18
19 d_daemonPid = pid;
20 }
21
22
23
24
25
26
+0
-15
ipc/request.cc less more
0 #include "ipc.ih"
1
2 StealthEnums::Mode IPC::request()
3 {
4 ifstream runFile;
5 Exception::open(runFile, d_options.runFile());
6
7 runFile.ignore(numeric_limits<int>::max(), '\n');
8
9 getline(runFile, d_requestText) >> d_requestorPid;
10
11 auto iter = s_request.find(d_requestText);
12
13 return iter == s_request.end() ? Mode::UNKNOWN : iter->second;
14 }
+0
-17
ipc/sendrequest.cc less more
0 #include "ipc.ih"
1
2 void IPC::sendRequest(char const *request, pid_t pid)
3 {
4 if (kill(pid, SIGUSR1) != 0)
5 {
6 unlink(d_options.runFile().c_str());
7
8 fmsg << "Can't send signal SIGUSR1 to process `" << pid << "',\n"
9 "removed stale run-file `" << d_options.runFile() << '.' <<
10 endl;
11 }
12
13 m2 << "stealth command line process sent request " << request <<
14 " to stealth daemon " << pid << endl;
15 }
16
+0
-19
ipc/sendrequestor.cc less more
0 #include "ipc.ih"
1
2 void IPC::sendRequestor(string const &msg)
3 {
4 if (d_requestorPid == 0)
5 {
6 m2 << "no requestor PID. Would have sent `" << msg << '\'' << endl;
7 return;
8 }
9
10 write(msg);
11
12 if (kill(d_requestorPid, SIGUSR1) == 0)
13 m2 << "to pid " << d_requestorPid << ": " << msg << endl;
14 else
15 m2 << "could not signal requestor " << d_requestorPid <<
16 " (" << msg << ')' << endl;
17
18 }
+0
-18
ipc/signaldaemon.cc less more
0 #include "ipc.ih"
1
2 bool IPC::signalDaemon()
3 {
4 readDaemonPid(); // get the pid of the daemon to signal
5
6 char const *request = d_options.modeRequest();
7
8 write(request);
9
10 m2 << "Sending signal SIGUSR1 to process " << d_daemonPid << endl;
11
12 sendRequest(request, d_daemonPid);
13
14 return true;
15 }
16
17
+0
-8
ipc/sleep2.cc less more
0 //#include "ipc.ih"
1 //
2 //void IPC::sleep(size_t seconds)
3 //{
4 // d_selector.setAlarm(seconds);
5 // wait();
6 //}
7 //
+0
-17
ipc/timedwait.cc less more
0 #include "ipc.ih"
1
2 void IPC::timedWait()
3 {
4 if (not d_options.repeat())
5 d_wait11.waitSignal();
6 else
7 {
8 size_t waitSeconds = d_options.repeatInterval() +
9 d_options.randomAddition();
10
11 m2 << "waiting for " << waitSeconds << " seconds or for a signal" <<
12 endl;
13
14 d_wait11.waitFor(waitSeconds);
15 }
16 }
+0
-9
ipc/wait.cc less more
0 #include "ipc.ih"
1
2 void IPC::wait(bool doM2)
3 {
4 d_wait11.waitSignal(doM2);
5
6 if (doM2)
7 m2 << "continuing after wait" << endl;
8 }
+0
-12
ipc/write.cc less more
0 #include "ipc.ih"
1
2 void IPC::write(string const &msg) const
3 {
4 fstream runFile(d_options.runFile(), ios::in | ios::out);
5
6 runFile.ignore(numeric_limits<int>::max(), '\n'); // skip one line
7 runFile.seekp(0, ios::cur); // prepare for writing
8 runFile << msg << '\n' << // write the msg
9 getpid() << '\n'; // write our own pid
10 runFile.close(); // done.
11 }
+0
-17
ipc/writerunfile.cc less more
0 #include "ipc.ih"
1
2 // runs in the foreground
3 void IPC::writeRunFile(pid_t pid)
4 {
5 string const &runFileName = d_options.runFile();
6
7 ofstream runFile(runFileName);
8
9 m2 << "run file: " << runFileName << '\n';
10
11 if (not (runFile << pid << endl))
12 {
13 kill(SIGTERM, pid);
14 fmsg << "could not write " << runFileName << endl;
15 }
16 }
+0
-5
lock/data.cc less more
0 #include "lock.ih"
1
2 FILE *Lock::s_runFILE = 0;
3 string Lock::s_runFilename;
4
+0
-5
lock/frame less more
0 #include "lock.ih"
1
2 Lock::
3 {
4 }
+0
-55
lock/lock.h less more
0 #ifndef INCLUDED_LOCK_
1 #define INCLUDED_LOCK_
2
3 #include <iosfwd>
4 #include <string>
5 #include <unistd.h>
6
7 class Lock
8 {
9 static FILE *s_runFILE; // pointer used for locking
10 static std::string s_runFilename;
11
12 static size_t const s_maxBlockAttempts = 10; // # seconds & tries
13 // recompile lockrunfile.cc when
14 // modifying this value
15 public:
16 enum LockType
17 {
18 NONBLOCKING,
19 BLOCKING,
20 };
21
22 static void unlockRunFile();
23 static bool lockRunFile(LockType type);
24 static void unlinkRunFile();
25 static void setRunFilename(std::string const &newName);
26
27 static std::string const &runFilename();
28
29 };
30
31 inline void Lock::setRunFilename(std::string const &newName)
32 {
33 s_runFilename = newName;
34 }
35
36 inline std::string const &Lock::runFilename()
37 {
38 return s_runFilename;
39 }
40
41 inline void Lock::unlinkRunFile()
42 {
43 unlink(s_runFilename.c_str()); // s_runFilename may be empty
44 }
45
46 #endif
47
48
49
50
51
52
53
54
+0
-10
lock/lock.ih less more
0 #include "lock.h"
1
2 #include <cstdio>
3 #include <sys/file.h>
4
5 #include <bobcat/mstream>
6
7 using namespace std;
8 using namespace FBB;
9
+0
-59
lock/lockrunfile.cc less more
0 #include "lock.ih"
1
2 // In time: make a CFIle object allowing us to open a file, determine its
3 // file descriptor, and have it closed by its destructor.
4
5 bool Lock::lockRunFile(LockType type)
6 try
7 {
8 // if (s_runFILE)
9 // fmsg << "Internal error: runfile already locked" << endl;
10 //
11 // if (s_runFilename.empty()) // no runfilename, no lock.
12 // {
13 // imsg << "No need to lock a run file" << endl;
14 // return true;
15 // }
16
17 imsg << "opening `" << s_runFilename << "' for reading" << endl;
18
19 s_runFILE = fopen(s_runFilename.c_str(), "r");
20
21 if (s_runFILE == 0)
22 fmsg << "Can't open run-file `" << s_runFilename.c_str() << '\'' <<
23 endl;
24
25 if (type == BLOCKING)
26 {
27 // imsg << "attempting blocking mode lock" << endl;
28 // if (flock(fileno(s_runFILE), LOCK_EX) == 0)
29 throw true;
30 // imsg << "blocking mode lock FAILED" << endl;
31 }
32 else
33 {
34 imsg << "attempting non-blocking mode lock on FD " <<
35 fileno(s_runFILE) << endl;
36 // for (size_t idx = 0; idx < s_maxBlockAttempts; ++idx)
37 // {
38 // if (flock(fileno(s_runFILE), LOCK_EX | LOCK_NB) == 0)
39 throw true;
40 // imsg << '.';
41 // ::sleep(1);
42 // imsg << "\nNon-blocking mode lock FAILED" << endl;
43 // }
44 }
45 throw false;
46 }
47 catch (bool ret)
48 {
49 imsg << "locked (and return): " << ret << endl;
50
51 // if (!ret)
52 // fmsg << "Failed to lock run-file `" << s_runFilename << '\'' << endl;
53
54 return true;
55 }
56
57
58
+0
-11
lock/unlockrunfile.cc less more
0 #include "lock.ih"
1
2 void Lock::unlockRunFile()
3 {
4 // if (s_runFILE)
5 // {
6 // flock(fileno(s_runFILE), LOCK_UN);
7 // fclose(s_runFILE); // closing removes the lock
8 // }
9 // s_runFILE = 0;
10 }
0 #include "logunit.ih"
1
2 LogUnit::
3 {
4 }
0 #define LIBRARY "logunit"
1
2 #include "../icmconf2"
0 #ifndef INCLUDED_LOGUNIT_
1 #define INCLUDED_LOGUNIT_
2
3 #include <memory>
4 #include <ostream>
5
6 #include <bobcat/multistreambuf>
7
8 class Options;
9
10 namespace FBB
11 {
12 class LogBuffer;
13 class Syslogbuf;
14 }
15
16 class LogUnit
17 {
18 Options &d_options;
19
20 std::unique_ptr<std::ostream> d_log;
21 std::unique_ptr<std::ostream> d_syslog;
22
23 std::unique_ptr<FBB::MultiStreambuf> d_imsgbuf;
24 std::unique_ptr<FBB::MultiStreambuf> d_fmsgbuf;
25
26 public:
27 LogUnit(Options &options);
28
29 void setupLogs();
30 void setupLogs(std::ostream &report);
31
32 std::ostream *newSyslogStream();
33 std::ostream *newLog();
34 };
35
36 #endif
37
38
39
40
0 #include "logunit.h"
1
2 #include <iostream>
3
4 #include <bobcat/logbuffer>
5 #include <bobcat/syslogbuf>
6 #include <bobcat/mstream>
7
8 #include "../options/options.h"
9
10 using namespace std;
11 using namespace FBB;
12
13
14
0 #include "logunit.ih"
1
2 LogUnit::LogUnit(Options &options)
3 :
4 d_options(options)
5 {}
0 #include "logunit.ih"
1
2 ostream *LogUnit::newLog()
3 try
4 {
5 string const &name = d_options.logName();
6
7 return name.empty() ? 0 : new Log(name);
8 }
9 catch (exception const &exc)
10 {
11 fmsg << "cannot write log file `" << d_options.logName() << '\'' << noidl;
12 return 0; // to make the compiler happy
13 }
0 #include "logunit.ih"
1
2 ostream *LogUnit::newSyslogStream()
3 try
4 {
5 SyslogStruct const &info = d_options.syslogStruct();
6
7 return info.requested ?
8 new SyslogStream(info.tag, info.priority, info.facility)
9 :
10 0;
11 }
12 catch (exception const &exc)
13 {
14 fmsg << "cannot write syslog messages" << noidl;
15 return 0; // to make the compiler happy
16 }
0 #include "logunit.ih"
1
2 // If --log was requested, define the logbuffer.
3 // If --syslog was requested define the syslogbuf
4 // If either fails, send fmsg.
5 //
6 // If both succeed messages inserted into imsg (and so: into m1..m3) are sent
7 // to all logfiles; if --stdout has also been specified then imsg also inserts
8 // into cout.
9 //
10 // fmsg, after setuplogs also inserts into the mail, and pending mail is
11 // delivered when the mail object is destroyed.
12
13 void LogUnit::setupLogs()
14 {
15 unique_ptr<ostream> log(newLog());
16
17 unique_ptr<ostream> syslog(newSyslogStream());
18
19 unique_ptr<MultiStreambuf> imsgbuf(new MultiStreambuf);
20
21 if (log.get() != 0)
22 {
23 d_log.swap(log); // install the new Log
24 imsgbuf->insert(*d_log);
25 }
26
27 if (syslog.get() != 0)
28 {
29 d_syslog.swap(syslog); // install the new syslogbuf
30 imsgbuf->insert(*d_syslog);
31 }
32
33 if (d_options.stdout())
34 imsgbuf->insert(cout);
35
36 if (imsgbuf->begin() != imsgbuf->end())
37 {
38 d_imsgbuf.swap(imsgbuf);
39 imsg.reset(d_imsgbuf.get());
40 }
41
42 unique_ptr<MultiStreambuf> fmsgbuf(new MultiStreambuf);
43 fmsgbuf->insert(imsg);
44 d_fmsgbuf.swap(fmsgbuf);
45
46 fmsg.reset(d_fmsgbuf.get());
47 }
0 #include "logunit.ih"
1
2 void LogUnit::setupLogs(ostream &report)
3 {
4 setupLogs();
5 d_fmsgbuf->insert(report);
6 }
7070 longOption, endLongOption,
7171 argc, argv);
7272
73 arg.versionHelp(Options::usage, Icmbuild::version, 0);
73 arg.versionHelp(Options::usage, Icmbuild::version, 1);
7474
7575 Stealth stealth;
7676
77 if (not stealth.contactPeer())
78 stealth.processPolicy(); // do all policy-file related tasks
77 if (stealth.ipcMode())
78 return 0;
79
80 stealth.policyMode(); // do all policy-file related tasks
7981 }
8082 catch (exception const &err)
8183 {
82 if (err.what() != to_string(fmsg.id()))
83 cout << err.what() << '\n';
84 cout << err.what() << endl;
8485 return 1;
8586 }
8687 catch (int ret)
8990 }
9091 catch (...)
9192 {
92 cerr << "\n"
93 cout << "\n"
9394 "Stealth terminated with an UNEXPECTED EXCEPTION.\n" <<
9495 "This should not have happened, please report this error and the "
9596 "circumstances\n"
00 #include <iostream>
11
2 #include <bobcat/arg>
2 #include <bobcat/argconfig>
33 #include <bobcat/mstream>
44
55 #include "options/options.h"
88 Msg(); // msgs are inserted if verbosity <=
99 // the configured verbosity level
1010 // E.g., configured: 3 inserts m1, m2 and m3
11 Msg(std::ostream &out);
11
12 Msg(std::ostream &out); // Used by mp, writing to cout
1213
1314 static void setVerbosity(size_t verbosity);
1415 };
1616 }
1717 catch (...)
1818 {
19 fmsg << "Invalid --" << option << " specified" << endl;
19 fmsg << "Invalid --" << option << " specified" << noidl;
2020 return 0;
2121 }
2222
2525 if (d_terminate)
2626 fmsg << " --terminate";
2727
28 fmsg << endl;
28 fmsg << noidl;
2929 }
3030 }
3131
00 #include "options.ih"
11
22 Options *Options::s_options = 0;
3
4 char const Options::s_configFileBase[] = ".stealth"; // in $HOME
53
64 char const Options::s_defaultSyslogIdent[] = "STEALTH";
75 Facility Options::s_defaultSyslogFacility = Facility::DAEMON;
33 {
44 if (not d_foreground)
55 fmsg << "--" << optionName << " is only valid for a " <<
6 basename() << " foreground process" << endl;
6 basename() << " foreground process" << noidl;
77 }
0 #include "options.ih"
1
2 string Options::getCwd()
3 {
4 char buffer[PATH_MAX];
5 string base(getcwd(buffer, PATH_MAX));
6 base += '/';
7
8 return base;
9 }
+0
-9
options/instance.cc less more
0 #include "options.ih"
1
2 Options &Options::instance()
3 {
4 if (s_options == 0)
5 s_options = new Options();
6
7 return *s_options;
8 }
+0
-29
options/loadpolicyoptions.cc less more
0 #include "options.ih"
1
2 void Options::loadPolicyOptions()
3 {
4 if (d_ipc)
5 return;
6
7 d_policyFilePath = Util::realPath(d_arg[0]);
8
9 ifstream policy;
10 Exception::open(policy, d_policyFilePath);
11
12 string line;
13 while (getline(policy, line) && line != "%%") // find the %% separator
14 ;
15
16 if (line != "%%") // no separator?
17 return; // then done here
18
19 TempStream tmpStream(User().homedir() + s_configFileBase);
20
21 tmpStream << policy.rdbuf(); // copy the long options
22 // into the temp. stream
23
24 tmpStream.close();
25
26 d_arg.open(tmpStream.fileName()); // read the config file
27 }
28
6161
6262 if (usedKeepAlive or usedSuppress)
6363 fmsg << basename() << " V. " << Icmbuild::version <<
64 " terminated" << endl;
64 " terminated" << noidl;
6565 else
6666 wmsg << flush;
6767 }
00 #ifndef INCLUDED_OPTIONS_
11 #define INCLUDED_OPTIONS_
22
3 #include <memory>
3 #include <string>
44
55 #include <bobcat/argconfig>
66 #include <bobcat/linearmap>
7
78 #include <bobcat/log>
8 #include <bobcat/multistreambuf>
9 #include <bobcat/syslogstream>
109
1110 #include "../stealthenums/stealthenums.h"
12
13 struct Options: public StealthEnums
14 {
11 #include "../syslogstruct/syslogstruct.h"
12
13 class Options: public StealthEnums
14 {
15 enum FileArgs
16 {
17 LOG = 1 << 0,
18 SKIP_FILE = 1 << 1
19 };
20
1521 FBB::ArgConfig &d_arg;
1622
17 std::shared_ptr<FBB::SyslogStream> d_syslog;
18 FBB::Log d_log;
19
20 FBB::MultiStreambuf d_multiStreambuf;
21 std::ostream d_msg; // d_msg handles all messages to
22 // syslog and/or d_log
23
23 std::string d_policyPath;
24
2425 Mode d_mode = INTEGRITY_SCAN;
2526
26 std::string d_policyFilePath;
27 std::string d_skipFilePath;
28 std::string d_runFile;
27 std::string d_base;
28
29 std::string d_skipFile;
30 std::string d_logName;
31 int d_cmdLineOption = 0;
32
33 std::string d_unixDomainSocket;
2934 std::string d_maxSizeStr;
3035
3136 bool d_reload;
3641 bool d_daemon;
3742 bool d_randomDelay;
3843 bool d_sendMail = true;
39 bool d_logMail = false;
40 bool d_stdout = false;
44 bool d_logMail = false;
45 bool d_stdout = false;
4146 bool d_repeat;
4247 bool d_foreground;
4348 bool d_ipc;
4449 bool d_dryrun;
4550 size_t d_repeatInterval;
46 size_t d_delayInterval = 0;
47 size_t d_commandNr = 0;
48 size_t d_parsePolicy = 0;
51 size_t d_delayInterval = 0;
52 size_t d_commandNr = 0;
53 size_t d_parsePolicy = 0;
4954 size_t d_verbosity;
55
56 SyslogStruct d_syslogStruct;
57
5058
5159 std::streamsize d_maxDownloadSize = 10 * 1024 * 1024; // 10 MB
5260
5967
6068 static Options *s_options;
6169
62 static char const s_configFileBase[];
6370 static FBB::Facility s_defaultSyslogFacility;
6471 static FBB::Priority s_defaultSyslogPriority;
6572 static char const s_defaultSyslogIdent[];
7481 static FBB::LinearMap<Mode, char const *> const s_modeName;
7582
7683 public:
77 static Options &instance();
84 Options();
7885
7986 Options(Options const &other) = delete;
8087
8188 void oldOptions() const;
8289
83 size_t parsePolicyFile() const;
8490 bool verbose() const;
8591 bool ipc() const;
8692 bool reload() const;
9197 bool daemon() const;
9298 bool repeat() const;
9399 bool sendMail() const;
100
94101 bool logMail() const;
102 void setLogMail();
103
95104 bool stdout() const;
96105 bool dryrun() const;
97106
99108 char const *modeRequest() const;
100109
101110 size_t commandNr() const;
102 size_t randomAddition() const;
103 size_t repeatInterval() const;
111 size_t nextIntegrityScan() const;
112
113 size_t parsePolicy() const;
104114 size_t verbosity() const;
105115
106116 std::streamsize maxDownloadSize() const;
107117
108118 std::string const &basename() const;
109119 std::string const &maxSizeStr() const;
120 std::string const &unixDomainSocket() const;
121 std::string const &skipFile() const;
122 std::string const &logName() const;
110123 std::string const &policyFilePath() const;
111 std::string const &runFile() const;
112 std::string const &skipFilePath() const;
113124
114125 std::string rfc2822() const;
115126
127 SyslogStruct const &syslogStruct() const;
128
129 FBB::TimeStamps timestamp() const;
130
131 void setConfigOptions(); // set options which may be (re)defined by
132 // config-files (e.g. the 2nd part of
133 // policy files
134
135
116136 static void usage(std::string const &progname);
117137
118138 private:
119 Options();
139 static std::string getCwd();
120140
121141 void requireSomeArgument();
122142
123143 void setMode();
124144 void checkMode() const;
125145
126 void setTimestamp();
127146 void setCommandNr();
128147 void setParsePolicy();
148
129149 void setStdout();
130 std::string setLog();
150
151 int setLog(); // initially using cmd-line options
152 int setSkipFile(); // when set in the policy file use the
153 // policy file's base
154
155 void setTimestamp();
131156
132157 void setRepeat();
133158 void setRandomDelay();
134159 size_t checkM(std::string const &spec, char const *option) const;
135160
161 size_t randomAddition() const;
162 size_t repeatInterval() const;
163
136164 void setMail();
137 void setSkipFilePath();
138165 void setDownloadSize();
139 void setVerbosity(bool useSyslog, std::string const &logName);
140
141 bool setSyslog();
142
143 std::string syslogTag() const;
144 FBB::Priority syslogPriority() const;
145 FBB::Facility syslogFacility() const;
146
147
148 void loadPolicyOptions();
166
167 void setVerbosity();
168
169 void setSyslog();
170 void setSyslogPriority();
171 void setSyslogFacility();
172
173 void setPolicyPath();
149174
150175 void foregroundOnly(char const *optionName) const;
151176 };
152177
178 inline FBB::TimeStamps Options::timestamp() const
179 {
180 return d_timestamp;
181 }
182
183 inline SyslogStruct const &Options::syslogStruct() const
184 {
185 return d_syslogStruct;
186 }
187
153188 inline size_t Options::verbosity() const
154189 {
155190 return d_verbosity;
156191 }
157192
193 inline size_t Options::parsePolicy() const
194 {
195 return d_parsePolicy;
196 }
197
158198 inline Options::Mode Options::mode() const
159199 {
160200 return d_mode;
175215 return d_logMail;
176216 }
177217
218 inline void Options::setLogMail()
219 {
220 d_logMail = true;
221 }
222
178223 inline bool Options::reload() const
179224 {
180225 return d_reload;
185230 return d_arg.option('V');
186231 }
187232
188 inline size_t Options::parsePolicyFile() const
189 {
190 return d_parsePolicy;
191 }
192
193233 inline bool Options::rerun() const
194234 {
195235 return d_rerun;
237277
238278 inline std::string const &Options::policyFilePath() const
239279 {
240 return d_policyFilePath;
241 }
242
243 inline std::string const &Options::skipFilePath() const
244 {
245 return d_skipFilePath;
246 }
247
248 inline std::string const &Options::runFile() const
249 {
250 return d_runFile;
280 return d_policyPath;
281 }
282
283 inline std::string const &Options::skipFile() const
284 {
285 return d_skipFile;
286 }
287
288 inline std::string const &Options::logName() const
289 {
290 return d_logName;
291 }
292
293 inline std::string const &Options::unixDomainSocket() const
294 {
295 return d_unixDomainSocket;
251296 }
252297
253298 inline std::string const &Options::basename() const
260305 return d_repeatInterval;
261306 }
262307
308 inline size_t Options::nextIntegrityScan() const
309 {
310 return repeatInterval() + randomAddition();
311 }
312
263313 inline size_t Options::commandNr() const
264314 {
265315 return d_commandNr;
11
22 #include <iostream>
33 #include <sstream>
4 #include <string>
5 #include <cstdlib>
6 #include <unistd.h>
7 #include <csignal>
84
9 #include <bobcat/user>
105 #include <bobcat/mstream>
11 #include <bobcat/tempstream>
12 #include <bobcat/exception>
136 #include <bobcat/datetime>
147
158 #include "../msg/msg.h"
00 #include "options.ih"
1
2 // No log-files are available yet. But since Options is constructed while
3 // stealth runs in the foreground, error messages can be sent to cerr.
14
25 Options::Options()
36 :
47 d_arg(ArgConfig::instance()),
5 d_msg(&d_multiStreambuf),
8 d_base(getCwd()),
69 d_maxSizeStr("10M"),
710 d_repeatInterval(numeric_limits<int>::max())
811 {
12
913 requireSomeArgument(); // no args/options, then usage and ends.
1014
1115 oldOptions(); // ends if --keep-alive or --suppress was
1721
1822 d_dryrun = d_arg.option(0, "dry-run");
1923
24 // preset file name options when defined as
25 // command-line options, using base = cwd
26 d_cmdLineOption = setLog() | setSkipFile();
27
2028 setCommandNr(); // sets run-command, (requires foreground).
2129 setParsePolicy(); // sets the policy file (requires foreground)
22
23 loadPolicyOptions(); // load any configuration options from the
24 // policy file into ArgConfig
2530
26 setMail(); // sets log-mail and no-mail
27 setSkipFilePath();
31 setPolicyPath();
2832
29 setTimestamp();
33 if (d_daemon)
34 {
35 Util::absPath(d_base, d_unixDomainSocket);
3036
31 setVerbosity( setSyslog(), setLog() );
37 if (access(d_unixDomainSocket.c_str(), F_OK) == 0)
38 fmsg << "Unix Domain Socket `" << d_unixDomainSocket <<
39 "': already in use, remove it first" << noidl;
40 }
3241
33 setStdout();
34 setRepeat();
35 setRandomDelay();
36 setDownloadSize();
42 setConfigOptions();
3743
38 if (not d_ipc)
39 m1 << "timestamps use " <<
40 (d_timestamp == TIMESTAMPS ? "local time" : "UTC") << endl;
44 if
45 (
46 not d_skipFile.empty()
47 and
48 access(d_skipFile.c_str(), R_OK) != 0
49 )
50 fmsg << "Can't read skip-file `" << d_skipFile << '\'' << noidl;
51
52
4153 }
4254
4355
1212 d_commandNr = stoul(value);
1313 if (d_commandNr == 0)
1414 fmsg << "--run-command 0: not a valid (natural) command number" <<
15 endl;
15 noidl;
1616 if (not d_stdout)
17 {
1817 d_stdout = true;
19 d_multiStreambuf.insert(cout);
20 }
2118 }
2219 catch (...)
2320 {
2421 d_commandNr = 0;
2522 fmsg << "--run-command " << value << ": invalid command number" <<
26 endl;
23 noidl;
2724 }
2825 }
2926
0 #include "options.ih"
1
2 void Options::setConfigOptions()
3 {
4 setMail(); // sets log-mail and no-mail
5 setSkipFile();
6
7 setLog();
8 setTimestamp();
9
10 setSyslog();
11
12 setVerbosity();
13 setStdout();
14
15 setRepeat();
16 setRandomDelay();
17 setDownloadSize();
18 }
55 return;
66
77 if (d_ipc)
8 fmsg << "--max-size incompatible with IPC calls" << endl;
8 fmsg << "--max-size incompatible with IPC calls" << noidl;
99
1010 size_t pos;
1111 try
3535 catch (...)
3636 {}
3737
38 fmsg << "--max-size " << d_maxSizeStr << ": invalid option value" << endl;
38 fmsg << "--max-size " << d_maxSizeStr << ": invalid option value" <<
39 noidl;
3940 }
4041
4142
00 #include "options.ih"
11
2 string Options::setLog()
2 int Options::setLog()
33 {
4 string logName;
5 if (d_arg.option(&logName, 'L'))
6 {
7 d_log.open(logName);
8 if (not d_log)
9 fmsg << "could not open " << logName << endl;
4 if
5 (
6 (d_cmdLineOption & LOG) // already a command line option
7 or
8 not d_arg.option(&d_logName, 'L')
9 )
10 return 0;
1011
11 d_log.setTimestamp(d_timestamp);
12
13 d_multiStreambuf.insert(d_log);
14 }
15 return logName;
12 Util::absPath(d_base, d_logName);
13 return LOG;
1614 }
1616 if ((d_resume = d_arg.option(0, "resume")))
1717 d_mode = RESUME;
1818
19 if
20 (
21 (d_daemon = d_arg.option(&d_runFile, 'd'))
22 and
23 d_runFile[0] != '/'
19 if (
20 (d_daemon = d_arg.option(&d_unixDomainSocket, 'd'))
21 &&
22 (d_arg.nArgs() == 0)
2423 )
25 {
26 if (d_arg.nArgs() == 0)
27 fmsg << "--daemon: missing run-file or policy file" << endl;
28 else
29 fmsg << "--daemon: " << d_runFile <<
30 ": must use an absolute file name" << endl;
31 }
32
33 if (d_mode & (RELOAD | RERUN | TERMINATE | SUSPEND | RESUME))
34 d_runFile = d_arg[0];
24 fmsg << "--daemon: missing Unix Domain File or policy file" << noidl;
3525
3626 d_ipc = d_reload || d_rerun || d_terminate || d_suspend || d_resume;
3727
28 if (d_ipc)
29 d_unixDomainSocket = d_arg[0];
30
3831 d_foreground = not d_ipc and not d_daemon;
3932 }
0 #include "options.ih"
1
2 void Options::setPolicyPath()
3 {
4 if (d_ipc)
5 return;
6
7 d_policyPath = d_arg[0];
8
9 Util::absPath(d_base, d_policyPath);
10 }
88 return;
99
1010 if (not d_repeat)
11 fmsg << "--random-interval requires --repeat" << endl;
11 fmsg << "--random-interval requires --repeat" << noidl;
1212
1313 d_delayInterval = checkM(delay, "random-interval");
1414
77 return;
88
99 if (d_ipc)
10 fmsg << "--repeat not available in IPC modes" << endl;
10 fmsg << "--repeat not available in IPC modes" << noidl;
1111
1212 d_repeatInterval = checkM(value, "repeat");
1313
0 #include "options.ih"
1
2 int Options::setSkipFile()
3 {
4 if ((d_cmdLineOption & SKIP_FILE) or not d_arg.option(&d_skipFile, 's'))
5 return 0;
6
7 if (d_arg.nArgs() == 0)
8 fmsg << "--skip-files: missing skip-file or policy file" << noidl;
9
10 if (d_ipc)
11 fmsg << "--skip-files incompatible with IPC calls" << noidl;
12
13 Util::absPath(d_base, d_skipFile);
14
15 return SKIP_FILE;
16 }
+0
-17
options/setskipfilepath.cc less more
0 #include "options.ih"
1
2 void Options::setSkipFilePath()
3 {
4 if (not d_arg.option(&d_skipFilePath, 's'))
5 return;
6
7 if (d_arg.nArgs() == 0)
8 fmsg << "--skip-files: missing skip-file or policy file" << endl;
9
10 if (d_skipFilePath[0] != '/')
11 fmsg << "--skip-files " << d_skipFilePath <<
12 ": must specify an absolute file name" << endl;
13
14 if (d_ipc)
15 fmsg << "--skip-files incompatible with IPC calls" << endl;
16 }
44 if (d_arg.option('o') or d_ipc)
55 {
66 if (d_daemon)
7 fmsg << "--stdout incompatible with --daemon" << endl;
7 fmsg << "--stdout incompatible with --daemon" << noidl;
88
99 d_stdout = true;
10 d_multiStreambuf.insert(cout);
1110 }
1211 }
00 #include "options.ih"
11
2 bool Options::setSyslog()
2 void Options::setSyslog()
33 {
4 if (not d_arg.option(0, "syslog"))
5 return false;
4 d_syslogStruct.requested = d_arg.option(0, "syslog");
5
6 if (not d_syslogStruct.requested)
7 return;
68
79 if (d_ipc)
8 fmsg << "--syslog* options incompatible with IPC calls" << endl;
10 fmsg << "--syslog* options incompatible with IPC calls" << noidl;
911
10 d_syslog = make_shared<SyslogStream>(syslogTag(), syslogPriority(),
11 syslogFacility());
1212
13 d_multiStreambuf.insert(*d_syslog);
14 return true;
13 if (not d_arg.option(&d_syslogStruct.tag, "syslog-tag"))
14 d_syslogStruct.tag = s_defaultSyslogIdent;
15
16 setSyslogPriority();
17 setSyslogFacility();
1518 }
0 #include "options.ih"
1
2 void Options::setSyslogFacility()
3 {
4 string option;
5 if (not d_arg.option(&option, "syslog-facility"))
6 d_syslogStruct.facility = s_defaultSyslogFacility;
7 else
8 {
9 LinearMap<string, Facility>::const_iterator
10 iter = s_syslogFacilities.find(option);
11
12 if (iter == s_syslogFacilities.end())
13 fmsg << "syslog facility " << option << " not supported" << noidl;
14
15 d_syslogStruct.facility = iter->second;
16 }
17 }
18
0 #include "options.ih"
1
2 void Options::setSyslogPriority()
3 {
4 string option;
5 if (not d_arg.option(&option, "syslog-priority"))
6 d_syslogStruct.priority = s_defaultSyslogPriority;
7 else
8 {
9 LinearMap<std::string, Priority>::const_iterator
10 iter = s_syslogPriorities.find(option);
11
12 if (iter == s_syslogPriorities.end())
13 fmsg << "syslog priority " << option << " not supported" << noidl;
14
15 d_syslogStruct.priority = iter->second;
16 }
17 }
18
77
88 if (value == "LT")
99 d_timestamp = TIMESTAMPS;
10 else if (value == "UTC")
11 d_timestamp = UTCTIMESTAMPS;
1012 else if (value != "UTC")
1113 wmsg << "--time-stamp " << value << " not supported. Using UTC" <<
1214 endl;
00 #include "options.ih"
11
2 void Options::setVerbosity(bool useSyslog, string const &logName)
2 void Options::setVerbosity()
33 {
44 string verbosity;
5 bool verb;
6 d_verbosity = (verb = d_arg.option(&verbosity, 'V')) ?
5
6 d_verbosity = (d_arg.option(&verbosity, 'V')) ?
77 stoul(verbosity)
88 :
99 s_defaultVerbosity;
10
11 if (useSyslog || logName.length() != 0)
12 imsg.reset(d_msg);
1310
1411 Msg::setVerbosity(d_verbosity);
1512 }
+0
-23
options/syslogfacility.cc less more
0 #include "options.ih"
1
2 Facility Options::syslogFacility() const
3 {
4 Facility facility;
5
6 string option;
7 if (not d_arg.option(&option, "syslog-facility"))
8 facility = s_defaultSyslogFacility;
9 else
10 {
11 LinearMap<string, Facility>::const_iterator
12 iter = s_syslogFacilities.find(option);
13
14 if (iter == s_syslogFacilities.end())
15 fmsg << "syslog facility " << option << " not supported" << endl;
16
17 facility = iter->second;
18 }
19
20 return facility;
21 }
22
+0
-23
options/syslogpriority.cc less more
0 #include "options.ih"
1
2 Priority Options::syslogPriority() const
3 {
4 Priority priority;
5
6 string option;
7 if (not d_arg.option(&option, "syslog-priority"))
8 priority = s_defaultSyslogPriority;
9 else
10 {
11 LinearMap<std::string, Priority>::const_iterator
12 iter = s_syslogPriorities.find(option);
13
14 if (iter == s_syslogPriorities.end())
15 fmsg << "syslog priority " << option << " not supported" << endl;
16
17 priority = iter->second;
18 }
19
20 return priority;
21 }
22
+0
-9
options/syslogtag.cc less more
0 #include "options.ih"
1
2 string Options::syslogTag() const
3 {
4 string tag;
5 if (not d_arg.option(&tag, "syslog-tag"))
6 tag = s_defaultSyslogIdent;
7 return tag;
8 }
1616 "the\n"
1717 " policy file).\n"
1818
19 " --daemon (-d) <path>: (C) run as a background (daemon) process.\n"
20 " <path> is the absolute filename of a pid-file used for\n"
21 " communication with the stealth daemon process\n"
19 " --daemon (-d) <uds>: (C) run as a background (daemon) process.\n"
20 " <uds> is the location of the Unix Domain Socket that is\n"
21 " used for communication with the stealth daemon process\n"
2222
2323 " --dry-run: (C) no integrity scans or reloads are performed, but\n"
2424 " are assumed OK. Remaining tasks are normally performed\n"
2525
26 " --log (-L) path: log messages are appended to `path'. If path\n"
27 " does not exist, it is first created \n"
26 " --log (-L) <file-spec>: log messages are appended to "
27 "`<file-spec>'.\n"
28 " If <file-spec> does not exist, it is first created \n"
2829
29 " --logmail: mail is loggeed (requires --log or --syslog)\n"
30 " --logmail: mail is logged (requires --log or --syslog)\n"
3031
3132 " --max-size value[BKMG]: files retrieved by GET may at most\n"
32 " have `value' bytes (B), Kbytes (K), Mbytes (M), "
33 " have `value' bytes (B), Kbytes (K), Mbytes (M), "
3334 "Gbytes (G).\n"
34 " By default: 10M; The default unit is `B'\n"
35 " By default: 10M; The default unit is `B'\n"
3536
3637 " --no-mail: mail is not sent. By default mail is sent as "
3738 "configured\n"
38 " in the policy-file (--logmail can be specified "
39 " in the policy-file (--logmail can be specified "
3940 "independently\n"
40 " from --no-mail)\n"
41 " from --no-mail)\n"
4142
4243 " --parse-policy-file (-p): (C) parse the policy file, no further "
4344 "actions.\n"
44 " Specify once to see the numbered commands,\n"
45 " twice to see the policy file parsing steps as well.\n"
46 " Results to std output.\n"
45 " Specify once to see the numbered commands,\n"
46 " twice to see the policy file parsing steps as well.\n"
47 " Results to std output.\n"
4748
4849 " --random-interval (-i) value: start integrity scans within\n"
49 " a random interval of `value' seconds (minutes\n"
50 " if an `m' is appended to the specified value).\n"
51 " Requires --repeat.\n"
50 " a random interval of `value' seconds (minutes if an `m'\n"
51 " is appended to the specified value).\n"
52 " Requires --repeat.\n"
5253
5354 " --repeat value: start an integrity scan every `value' seconds\n"
54 " (minutes if an `m' is appended to the specified "
55 "value).\n"
55 " (minutes if an `m' is appended to the specified value).\n"
5656
5757 " --run-command (-r) value: (C) only execute command #`value'\n"
58 " (not available in combination with --daemon)\n"
5859
59 " --skip-files (-s) path: skip the integrity checks of the\n"
60 " files having their absolute path names listed in "
61 "`path'\n"
60 " --skip-files (-s) <file-spec>: skip the integrity checks of the\n"
61 " files having their absolute path names listed in "
62 "`<file-spec>'\n"
6263
63 " --stdout (-o): messages are (also) written to stdout "
64 "(incompatible\n"
65 " with the --daemon option)\n"
64 " --stdout (-o): messages are (also) written to stdout\n"
65 " (not available in combination with --daemon)\n"
6666
6767 " --syslog: write syslog messages\n"
6868
6969 " --syslog-facility fac: syslog facility to use. By default "
70 "DAEMON\n"
70 "DAEMON\n"
7171
7272 " --syslog-priority pri: syslog priority to use. By default "
73 "NOTICE\n"
73 "NOTICE\n"
7474
7575 " --syslog-tag tag: identifier prefixed to syslog messages. By\n"
76 " default `" << s_defaultSyslogIdent << "')\n"
76 " default `" << s_defaultSyslogIdent << "')\n"
7777
7878 " --time-stamp <type>: the time-stamps to use. By default UTC.\n"
79 " (does not apply to syslog-timestamps)\n"
79 " (does not apply to syslog-timestamps)\n"
8080
8181 " --verbosity (-V) value: determines the amount of logged "
8282 "information.\n"
83 " Requires --log or --syslog:\n"
84 " 0: nothing is logged\n"
85 " 1: mode reports and policy commands\n"
86 " 2: also: ipc commands and actions\n"
87 " 3: also: integrity scan informative messages\n"
83 " Requires --log or --syslog:\n"
84 " 0: nothing is logged\n"
85 " 1: mode reports and policy commands\n"
86 " 2: also: ipc commands and actions\n"
87 " 3: also: integrity scan informative messages\n"
8888
89 " policy: path to the policy file\n"
89 " policy: location of the policy file\n"
9090 "\n"
9191
9292 "Usage 2 (IPC modes, all options are command-line only):\n"
9393 " " << progname <<
94 " {--reload,--rerun,--resume,--suspend,--terminate} pid-file\n"
94 " {--reload,--rerun,--resume,--suspend,--terminate} <uds>\n"
9595 "Where:\n"
9696 " --reload: reload a " << progname << " process's policy and "
97 "skip-files\n"
97 "skip-file\n"
9898 " files\n"
9999 " --rerun: start an integrity scan\n"
100100 " --resume: resume " << progname << " after --suspend\n"
101101 " --suspend: suspend " << progname << "'s activities\n"
102102 " to continue: --resume; to end: --terminate\n"
103103 " --terminate: terminate the " << progname << " daemon\n"
104 " pidfile: file containing the pid of the stealth daemon process.\n"
104 " <uds>: location of the Unix Domain Socket to connect to.\n"
105105 "\n"
106106 "Usage 3 (support mode, all options are command-line only)\n"
107107 " " << progname << " {--help,--version}\n"
0 #include "policyfile.ih"
1
2 void PolicyFile::chdirBase() const
3 {
4 char const *base = d_use.find("BASE")->second.c_str();
5
6 if (chdir(base) != 0)
7 fmsg << "Can't chdir to `" << base << '\'' << noidl;
8 }
9
00 #include "policyfile.ih"
1
2 char const PolicyFile::s_configFileBase[] = ".stealth"; // in $HOME
13
24 pair<string, string> const
35 PolicyFile::s_defaultKeyword[] =
2224 // [0]: all text,
2325 // [1]: all ${NAME} text
2426 // [2]: NAME itself
27 Pattern PolicyFile::s_log(
28 "^\\s*"
29 "(LOCAL\\s+)?" // 1
30 "(NOTEST\\s+)?" // 2
31 "CHECK\\s+(LOG\\s*=\\s*)?" // 3
32 "(\\S+)"); // 4: name of the logfile
2533
00 #include "policyfile.ih"
11
22 void PolicyFile::directivesAndCommands()
3 try
34 {
4 for (int idx = 0, size = d_configfile.size(); idx != size; ++idx)
5 ConfigFile configfile(d_options.policyFilePath());
6
7 for (size_t idx = 0, size = configfile.size(); idx != size; ++idx)
58 {
6 string line = d_configfile[idx];
9 string line = configfile[idx];
710
8 if (line == "%%") // stop at section 2
11 if (line == "%%")
912 {
10 mp << "Policy file processing ends at section 2, line " <<
11 (idx + 1) << endl;
13 loadOptions(configfile, idx + 1);
1214 return;
1315 }
1416
3032 }
3133 }
3234 }
33
35 catch (exception const &exc)
36 {
37 fmsg << exc.what() << noidl;
38 }
44 void PolicyFile::fetchCommands()
55 {
66 directivesAndCommands();
7
8 string &base = d_use["BASE"];
9
10 if (base.back() != '/')
11 base += '/';
712
813 bool ok = d_use.count("SSH");
914
1621 for(auto &entry: d_command)
1722 replaceDefines(entry);
1823
19 if (size_t parse = Options::instance().parsePolicyFile())
24 fixRelativeLocations();
25
26 if (size_t parseOnly = d_options.parsePolicy())
2027 {
21 if (parse > 1)
28 if (parseOnly > 1)
29 {
2230 for(auto &value: d_use)
2331 mp << "USE " << value.first << ": " << value.second << endl;
32 }
2433
2534 mp.clear();
35
36 mp << "REPORT: " << d_use["REPORT"] << endl;
37
2638 for (size_t idx = 0; idx != d_command.size(); ++idx)
2739 mp << (idx + 1) << ": " << d_command[idx] << endl;
2840
3042 }
3143
3244 if (!ok)
33 fmsg << "USE SSH ... entry missing in the policy file" << endl;
45 fmsg << "USE SSH ... entry missing in the policy file" << noidl;
3446 }
3547
48
49
50
51
52
0 #include "policyfile.ih"
1
2 void PolicyFile::fixRelativeLocations()
3 {
4 string const &base = d_use["BASE"];
5
6 Util::absPath(base, d_use["REPORT"]);
7
8 for (auto &line: d_command)
9 {
10 // [LOCAL] CHECK [LOG =] <logfile> [pathOffset] <command>
11 // [LOCAL] NOTEST CHECK <logfile> [pathOffset] <command>
12 // NOTEST CHECK [LOG =] <logfile> [pathOffset] <command>
13
14 if (s_log << line)
15 {
16 string logName = s_log[4];
17 Pattern::Position pos = s_log.position(4);
18
19 Util::absPath(base, logName);
20
21 line.replace(pos.first, pos.second - pos.first, logName);
22 }
23 }
24 }
25
26
27
28
29
0 #include "policyfile.ih"
1
2 void PolicyFile::load()
3 {
4 d_use = LinearMap(
5 &s_defaultKeyword[0], &s_defaultKeyword[s_nDefaultKeywords]
6 );
7
8 d_define.clear();
9 d_command.clear();
10
11 fetchCommands();
12
13 string &base = d_use["BASE"];
14
15 base += '.'; // the . is required by mkdir
16 char const *cp = base.c_str();
17 Util::mkdir(cp);
18 base.pop_back(); // cut off the . again
19
20 chdirBase(); // change to the base directory
21 }
22
23
24
25
26
27
28
0 #include "policyfile.ih"
1
2 void PolicyFile::loadOptions(ConfigFile &configFile, size_t from)
3 {
4 TempStream tmpStream(User().homedir() + s_configFileBase);
5
6 for
7 (
8 auto begin = configFile.begin() + from, end = configFile.end();
9 begin != end;
10 ++begin
11 )
12 tmpStream << *begin << '\n'; // copy the long options
13 // into the temp. stream
14
15 tmpStream.close();
16
17 // read the config file's options
18 ArgConfig::instance().open(tmpStream.fileName());
19
20 d_options.setConfigOptions();
21 }
22
33 #include <string>
44 #include <vector>
55 #include <bobcat/linearmap>
6 #include <bobcat/configfile>
6
7 class Options;
78
89 namespace FBB
910 {
1011 class Pattern;
12 class ConfigFile;
1113 }
1214
1315 class PolicyFile
1416 {
15 typedef FBB::LinearMap<std::string, std::string> LinearMap;
17 typedef FBB::LinearMap<std::string, std::string> LinearMap;
1618
17 std::string d_policyPath;
18 FBB::ConfigFile d_configfile;
19 std::vector<std::string> d_command;
19 Options &d_options;
2020
21 LinearMap d_use;
22 LinearMap d_define;
23
24 static std::pair<std::string, std::string> const s_defaultKeyword[];
25 static size_t s_nDefaultKeywords;
26 static FBB::Pattern s_firstWord;
27 static FBB::Pattern s_comment;
28 static FBB::Pattern s_define; // [0]: all text,
29 // [1]: all ${NAME} text
30 // [2]: NAME itself
21 std::vector<std::string> d_command;
22
23 LinearMap d_use;
24 LinearMap d_define;
25
26 static char const s_configFileBase[];
27
28 static std::pair<std::string, std::string> const s_defaultKeyword[];
29 static size_t s_nDefaultKeywords;
30
31 static FBB::Pattern s_firstWord;
32 static FBB::Pattern s_comment;
33 static FBB::Pattern s_define; // [0]: all text,
34 // [1]: all ${NAME} text
35 // [2]: NAME itself
36 static FBB::Pattern s_log; // [4]: name of the logfile
37
3138 public:
32 PolicyFile(std::string const &policyPath);
33
34 void reload();
39 PolicyFile(Options &options);
3540
3641 size_t size() const;
3742 std::vector<std::string>::const_iterator firstCmd() const;
3843 std::vector<std::string>::const_iterator beyondCmd() const;
44
3945 std::string const &operator[](std::string const &key) const;
40
46
47 void chdirBase() const;
48
4149 private:
50 void load();
51 void loadOptions(FBB::ConfigFile &configFile, size_t from);
52
4253 std::string const &getDEFINE(std::string const &key) const;
4354 bool hasDEFINE(std::string const &key) const;
4455
4960 // replaces the DEFINE's in text
5061 void replaceDefines(std::string &text);
5162 void insert(LinearMap &linMap, std::string const &line);
63
64 void fixRelativeLocations();
5265 };
5366
5467 inline size_t PolicyFile::size() const
11
22 #include <bobcat/pattern>
33 #include <bobcat/mstream>
4
4 #include <bobcat/argconfig>
5 #include <bobcat/tempstream>
6 #include <bobcat/user>
7
58 #include "../util/util.h"
9 #include "../msg/msg.h"
610 #include "../options/options.h"
7 #include "../msg/msg.h"
811
912 using namespace std;
1013 using namespace FBB;
00 #include "policyfile.ih"
11
2 PolicyFile::PolicyFile(string const &policyPath)
2 PolicyFile::PolicyFile(Options &options)
33 :
4 d_policyPath(policyPath)
4 d_options(options)
55 {
6 reload();
6 load();
77 }
88
99
+0
-35
policyfile/reload.cc less more
0 #include "policyfile.ih"
1
2 void PolicyFile::reload()
3 {
4 d_configfile.open(d_policyPath);
5
6 d_use = LinearMap(
7 &s_defaultKeyword[0], &s_defaultKeyword[s_nDefaultKeywords]
8 );
9
10 d_define.clear();
11 d_command.clear();
12
13 fetchCommands();
14
15 string &base = d_use["BASE"];
16
17 base += "/."; // the . is required by mkdir
18
19 char const *cp = base.c_str();
20
21 if (!Util::mkdir(cp) || chdir(cp))
22 fmsg << "Can't chdir to `" << cp << '\'' << endl;
23
24 base.resize(base.length() - 1); // cut off the . again
25
26 m2 << "(re)loaded the policy file `" << d_policyPath << '\'' << endl;
27 }
28
29
30
31
32
33
34
0 /*
1 demo.cc
2
3 g++ demo.cc -L../.. -lstealth | & less
4 */
5
6 #include "demo.h"
7
8 int main(int argc, char **argv, char **envp)
9 {
10 try
11 {
12 Reporter rep("report");
13
14 rep << Util::date << ": Hello world\n";
15
16 rep.reset();
17
18 string s;
19
20 cout << "========= 0 ===========\n";
21
22 while (getline(rep, s))
23 cout << "Added: " << s << "\n";
24
25 cout << "========= 1 ===========\n";
26
27 sleep(5);
28
29 rep.reinit(); // make sure we can add new info
30 // as a new run
31
32 // insert info
33 rep << Util::date << ": Hello world (2nd time)\n";
34
35 rep.reset(); // reset the stream to read it again
36
37 while (getline(rep, s))
38 cout << "Added: " << s << "\n";
39
40 cout << "========= 2 ===========\n";
41
42 return 0;
43 }
44 catch(exception const &e)
45 {
46 cerr << "Exception " << e.what() << "\n";
47 return 1;
48 }
49 }
0 #include <iostream>
1 #include <string>
2
3 #include "../stealthreport.h"
4 #include "../../util/util.h"
5
6 using namespace std;
0 #include "report.ih"
1
2 Report::~Report()
3 {
4 if (hasMail())
5 processMail();
6 }
0 #include "report.ih"
1
2 void Report::
3 {
4 }
0 #include "report.ih"
1
2 bool Report::hasMail()
3 {
4 return d_beginMail < endpos();
5 }
6
0 #define LIBRARY "report"
1
2 #include "../icmconf2"
0 #include "report.ih"
1
2 void Report::mail()
3 {
4 if (hasMail())
5 processMail();
6 else
7 m3 << "No new logs to mail" << endl;
8 }
0 #include "report.ih"
1
2 void Report::processMail()
3 {
4 if (d_options.logMail())
5 {
6 rewind();
7
8 string line;
9 while (std::getline(*this, line))
10 imsg << "Mail: " << line << endl;
11 }
12
13 if (d_options.sendMail())
14 sendMail();
15
16 refresh();
17 }
0 #include "report.ih"
1
2 void Report::refresh()
3 {
4 clear();
5
6 d_startSize = endpos();
7
8 d_beginMail = d_startSize;
9 }
10
11
12
13
14
15
16
0 #ifndef REPORT_H_
1 #define REPORT_H_
2
3 #include <string>
4 #include <fstream>
5
6 class Options;
7 class PolicyFile;
8
9 class Report: public std::fstream
10 {
11 std::string d_name;
12
13 Options &d_options;
14 PolicyFile const &d_policyFile;
15
16 std::ios::pos_type d_startSize;
17 std::ios::pos_type d_beginMail;
18
19 std::string d_headerLine;
20
21 public:
22 Report(Options &options, PolicyFile const &policyFile);
23 ~Report();
24
25 Report(Report const &other) = delete;
26 Report &operator=(Report const &other) = delete;
27
28 void timestamp(char const *label, size_t nScans);
29 void mail();
30 void scanHeader(); // writes the integrity scan header,
31 // initializes d_beginMail
32 private:
33 void rewind(); // prepare for reading
34 void processMail();
35 void sendMail();
36 void refresh(); // set d_beginMail to the log's EOF pos.
37 bool hasMail(); // true if there is info beyond
38 // d_beginMail
39
40 std::ios::pos_type endpos();
41 };
42
43 #endif
44
0 #include "report.h"
1
2 #include <iostream>
3 #include <sstream>
4
5 #include <bobcat/exception>
6 #include <bobcat/mstream>
7 #include <bobcat/process>
8
9 #include "../options/options.h"
10 #include "../msg/msg.h"
11 #include "../policyfile/policyfile.h"
12
13 namespace Icmbuild
14 {
15 extern char const version[];
16 }
17
18 using namespace FBB;
19 using namespace std;
20
21 inline ios::pos_type Report::endpos()
22 {
23 return seekp(0, ios::end).tellp();
24 }
0 #include "report.ih"
1
2 Report::Report(Options &options, PolicyFile const &policyFile)
3 :
4 fstream(policyFile["REPORT"], ios::out | ios::ate | ios::in),
5 d_name(policyFile["REPORT"]),
6 d_options(options),
7 d_policyFile(policyFile)
8 {
9 if (not good())
10 {
11 clear();
12 open(d_name, ios::out | ios::in | ios::trunc);
13 }
14
15 if (not good())
16 fmsg << "cannot write report file `" << d_name << '\'' << noidl;
17
18 ostringstream headerTxt;
19 headerTxt << "\n"
20 "STEALTH (" << Icmbuild::version << ") started at " <<
21 d_options.rfc2822() << '\n';
22
23 d_headerLine = headerTxt.str();
24
25 *this << d_headerLine << endl;
26
27 refresh();
28 }
29
30
31
32
33
0 #include "report.ih"
1
2 void Report::rewind()
3 {
4 clear();
5 seekg(d_startSize).tellg();
6 }
7
0 #include "report.ih"
1
2 void Report::scanHeader()
3 {
4 d_startSize = endpos();
5
6 *this << "STEALTH integrity scan at " << d_options.rfc2822() << endl;
7
8 d_beginMail = tellp();
9 }
10
11
12
13
14
15
16
0 #include "report.ih"
1
2 void Report::sendMail()
3 {
4 m3 << "Mailing new logs using: " <<
5 d_policyFile["MAILER"] << ' ' <<
6 d_policyFile["MAILARGS"] << " " <<
7 d_policyFile["EMAIL"] << endl;
8
9 // mailcommand subject and email are called as separate arguments
10 // If subject contains blanks, they will be interpreted as separate
11 // arguments by the `mail' IOFork. Usually d_policyFile["MAILER"] will
12 // call a script.
13
14 Process mail(
15 Process::CIN | Process::IGNORE_COUT | Process::IGNORE_CERR,
16 d_policyFile["MAILER"] + ' ' +
17 d_policyFile["MAILARGS"] + ' ' +
18 d_policyFile["EMAIL"]
19 );
20
21 mail.start();
22
23 mail << d_headerLine << '\n';
24
25 rewind();
26
27 string line;
28 while (std::getline(*this, line))
29 mail << line << '\n';
30
31 mail.close();
32 mail.waitForChild();
33 }
0 #include "report.ih"
1
2 void Report::timestamp(char const *label, size_t nScans)
3 {
4 static char plural[] = "s";
5
6 plural[0] = nScans != 1 ? 's' : 0;
7
8 *this << "STEALTH " << label << " after " << nScans << " scan" <<
9 plural << " at " << d_options.rfc2822() << endl;
10 mail();
11 }
0 This file lists non-standard software only. Thus, standard utilities like cp,
1 mv, sed, etc, etc, are not explicitly mentioned. Neither is the gcc compiler
2 explicitly mentioned, but a fairly recent one is assumed.
3
4 Required software for building Stealth 4.00.00
5 ----------------------------------------------
6
7 libbobcat-dev (>= 3.25.01),
8
9
10 To use the provided build-script:
11
12 icmake (>= 7.22.00)
13
14 To construct the manual and map-page:
15
16 yodl (>= 3.05.0)
17
18 To construct the manual:
19
20 texlive-latex-base,
21 texlive-generic-recommended,
22 texlive-latex-recommended,
23 texlive-fonts-recommended,
24 cm-super-minimal,
25 ghostscript
26
27
00 #include "runmode.ih"
11
2 LinearMap<volatile RunMode::Mode, char const *> const RunMode::s_modeName =
2 LinearMap<RunMode::Mode, char const *> const RunMode::s_modeName =
33 {
44 {INTEGRITY_SCAN, "INTEGRITY_SCAN"},
5 {WAIT, "WAIT"},
65 {RERUN, "RERUN"},
76 {SUSPEND, "SUSPEND"},
87 {RESUME, "RESUME"},
98 {RELOAD, "RELOAD"},
109 {TERMINATE, "TERMINATE"},
1110 };
12
13 LinearMap<volatile RunMode::Mode, int> const RunMode::s_mode2signal =
14 {
15 {RERUN, SIGHUP},
16 {RELOAD, SIGPIPE},
17 {RESUME, SIGUSR2},
18 {SUSPEND, SIGUSR1},
19 {TERMINATE, SIGTERM},
20 };
2111
2212
2313
00 #ifndef INCLUDED_RUNMODE_
11 #define INCLUDED_RUNMODE_
22
3 #include <iostream>
34 #include <bobcat/linearmap>
45
56 #include "../stealthenums/stealthenums.h"
67
78 struct RunMode: public StealthEnums
89 {
10 friend std::ostream &operator<<(std::ostream &out, RunMode const &mode);
11
912 private:
10 static FBB::LinearMap<volatile Mode, char const *> const s_modeName;
11 static FBB::LinearMap<volatile Mode, int> const s_mode2signal;
13 static FBB::LinearMap<Mode, char const *> const s_modeName;
1214
1315 volatile Mode d_mode = INTEGRITY_SCAN;
1416
1517 public:
16 bool mode(Mode query) const;
18 bool hasMode(Mode query) const;
1719 Mode mode() const;
18 char const *modeName() const;
1920
2021 void setMode(Mode mode);
21 bool interrupted() const; // a running integrity scan was interrupted
22
23 static Mode validate(int mode);
2224 };
2325
24 inline char const *RunMode::modeName() const
26 inline RunMode::Mode RunMode::validate(int mode)
2527 {
26 return s_modeName.find(d_mode)->second;
28 return
29 ((mode - 1) & mode) == 0
30 &&
31 mode <= UNKNOWN ?
32 static_cast<Mode>(mode)
33 :
34 UNKNOWN;
2735 }
2836
2937 inline RunMode::Mode RunMode::mode() const
3139 return d_mode;
3240 }
3341
34 inline bool RunMode::mode(Mode mode) const
42 inline bool RunMode::hasMode(Mode mode) const
3543 {
3644 return d_mode & mode;
3745 }
38
39 inline bool RunMode::interrupted() const
46
47 inline std::ostream &operator<<(std::ostream &out, RunMode const &mode)
4048 {
41 return mode(SUSPEND | TERMINATE | RELOAD);
49 return out << RunMode::s_modeName.find(mode.mode())->second;
4250 }
4351
4452 #endif
00 #include "runmode.h"
1
2 #include <unistd.h>
3 #include <csignal>
4
5 //#include "../lock/lock.h"
6 #include "../options/options.h"
71
82 using namespace std;
93 using namespace FBB;
11
22 void RunMode::setMode(Mode mode)
33 {
4 if ((d_mode = mode) == LEAVE)
5 unlink(Options::instance().runFile().c_str());
4 d_mode = mode;
65 }
76
0 /var/stealth/target/report {
0 /root/stealth/report /var/log/stealth/client-small.log {
11 weekly
22 rotate 12
33 compress
44 missingok
5 copytruncate
6 sharedscripts
57 prerotate
6 /usr/bin/stealth --suppress /var/run/stealth.target
8 /usr/bin/stealth --suspend /root/stealth/small.uds
79 endscript
8 postrotate
9 /usr/bin/stealth --resume /var/run/stealth.target
10 postrotate
11 /usr/bin/stealth --resume /root/stealth/small.uds
1012 endscript
1113 }
2929 (*)
3030 echo "
3131 $PROG by Frank B. Brokken (f.b.brokken@rug.nl)
32 Usage: $PROG pidfile configfile [skipfile]
32 Usage: $PROG uds policyfile [skipfile]
3333 where:
34 pidfile: absolute path to pidfile to be used by ${STEALTH}
35 configfile: absolute path to configuration file to be used by ${STEALTH}
36 skipfile: absolute path to file holding files to skip (optional)
34 uds: absolute path to the Unix Domain Socket to be used
35 policyfile: absolute path to the policyfile to be used
36 skipfile: absolute path to the skipfile to be used (optional)
3737
38 calls $STEALTH} --rerun pidfile.
38 calls $STEALTH} --rerun uds.
3939 If that fails,
40 ${STEALTH} --daemon pidfile -q configfile
40 ${STEALTH} --daemon uds policyfile
4141 or (if skipfile was specified)
42 ${STEALTH} --daemon pidfile -s skipfile -q configfile
42 ${STEALTH} --daemon uds policyfile -s skipfile policyfile
4343 is started.
4444 "
4545 exit 1
11
22 grep 'STEALTH\|MODIFIED\|ADDED\|REMOVED\|SKIPPING' | sort | uniq |
33 /usr/bin/mail -s "$2" $3
4
5
6 # echo "$0 started with arguments:
7 # =============================================" > /tmp/stealth.mail
8 #
9 # while [ "$1" != "" ]
10 # do
11 # echo "$1" >> /tmp/stealth.mail
12 # shift
13 # done
14 #
15 # echo "== contents begin ===========================" >> /tmp/stealth.mail
16 #
17 # cat >> /tmp/stealth.mail
18 #
19 # echo "== contents end =============================" >> /tmp/stealth.mail
00 #include "stealth.ih"
11
2 void Stealth::acceptMode(Mode mode)
2 string Stealth::acceptMode(Mode mode)
33 {
4 d_run.setMode(mode);
5 d_ipc.sendRequestor("OK");
4 d_task.setMode(mode);
5 return "";
66 }
0 #include "stealth.ih"
1
2 // automatically switch to an integrity scan after reload, rerun and resume.
3
4 void Stealth::autoScan(char const *label)
5 {
6 m2 << "automatically starting an INTEGRITY_SCAN following --" << label
7 << endl;
8 d_task.setMode(INTEGRITY_SCAN);
9 d_autoJob = true;
10 d_job.notify();
11 }
11
22 void Stealth::childProcess()
33 {
4 // prepareDaemon("/tmp/serr", "/tmp/serr"); // by Fork.
45 prepareDaemon(); // by Fork.
56
6 doChores();
7 // start the ipc interface thread
8 thread(startThread, &Stealth::ipcInterface, this).detach();
9
10 doTasks();
711
812 m1 << d_options.basename() << " (process " << getpid() <<
913 ") terminates" << endl;
+0
-28
stealth/contactpeer.cc less more
0 #include "stealth.ih"
1
2 bool Stealth::contactPeer()
3 {
4 if (not d_options.ipc())
5 return false;
6
7 Signal &signal = Signal::instance();
8 signal.add(SIGUSR1, *this);
9
10 if (d_ipc.signalDaemon())
11 {
12 d_ipc.timedWait(s_contactPeerWaitSeconds);
13
14 if (d_ipc.timeout())
15 cout << "No reply from daemon (pid " << d_ipc.daemonPid() <<
16 ')' << endl;
17 else if (d_ipc.requestText() != "OK")
18 cout << d_ipc.requestText() << endl;
19
20 return true;
21 }
22
23 return false;
24 }
25
26
27
00 #include "stealth.ih"
11
2 FBB::LinearMap<Stealth::Mode, Stealth::Action> Stealth::s_task =
2 FBB::LinearMap<Stealth::Mode, Stealth::Task> Stealth::s_task =
33 {
4 {RELOAD, &Stealth::reload},
5 {TERMINATE, &Stealth::terminate},
4 {RELOAD, &Stealth::reload}, // autoscan
5 {TERMINATE, &Stealth::terminate}, // terminates
66 {INTEGRITY_SCAN, &Stealth::integrityScan},
77 {SUSPEND, &Stealth::suspend},
8 {RESUME, &Stealth::resume},
8 {RESUME, &Stealth::resume}, // autoscan
9 {RERUN, &Stealth::rerun}, // autoscan
910 };
1011
12 // possible incoming requests at the ipcInterface
1113 FBB::LinearMap<Stealth::Mode, Stealth::Action> Stealth::s_request =
1214 {
15 {INTEGRITY_SCAN, &Stealth::unknownRequest},
16
17 {RERUN, &Stealth::rerunRequest},
18 {SUSPEND, &Stealth::suspendRequest},
19 {RESUME, &Stealth::resumeRequest},
1320 {RELOAD, &Stealth::reloadRequest},
14 {RERUN, &Stealth::rerunRequest},
15 {RESUME, &Stealth::resumeRequest},
16 {SUSPEND, &Stealth::suspendRequest},
1721 {TERMINATE, &Stealth::terminateRequest},
22
1823 {UNKNOWN, &Stealth::unknownRequest},
1924 };
2025
+0
-11
stealth/definesupportedsignals.cc less more
0 #include "stealth.ih"
1
2 void Stealth::defineSupportedSignals()
3 {
4 Signal &signal = Signal::instance();
5
6 signal.add(SIGTERM, *this); // ends the running Stealth program.
7 signal.add(SIGINT, *this);
8
9 signal.add(SIGUSR1, *this);
10 }
00 #include "stealth.ih"
11
2 void Stealth::deniedMode(char const *request)
2 std::string Stealth::deniedMode(char const *request)
33 {
44 ostringstream ostr;
55
6 ostr << "Stealth deamon " << getpid() << " in mode " <<
7 d_run.modeName() << " cannot do " << request;
6 ostr << "Stealth deamon (pid = " << getpid() << "): `" << request <<
7 "' not available in mode " << d_task;
88
99
10 d_ipc.sendRequestor(ostr.str());
10 m2 << "ignored --rerun in mode " << d_task << endl;
1111
12 m2 << "ignored --rerun in mode " << d_run.modeName() << endl;
12 return ostr.str();
1313 }
00 #include "stealth.ih"
11
22 Stealth::~Stealth()
3 {}
3 {
4 if (d_options.daemon())
5 unlink(d_options.unixDomainSocket().c_str());
6
7 delete d_logReportbuf;
8 }
49
510
611
+0
-28
stealth/dochores.cc less more
0 #include "stealth.ih"
1
2 // called by processPolicy and childProcess
3
4 void Stealth::doChores()
5 {
6 policyDepDataMembers();
7
8 defineSupportedSignals();
9
10 if (d_options.dryrun())
11 d_stealthLog << "--dry-run: SH/SSH connections not established" <<
12 endl;
13 else
14 d_integrityScanner->startCommandShells();
15
16 processRequests(); // Stealth terminates once this function
17 // ends
18 }
19
20
21
22
23
24
25
26
27
0 #include "stealth.ih"
1
2 void Stealth::doTasks()
3 {
4 if (not d_options.ipc())
5 {
6 m1 << "timestamps use " <<
7 (d_options.timestamp() == TIMESTAMPS ?
8 "local time"
9 :
10 "UTC"
11 ) << endl;
12 }
13
14 d_policyFile->chdirBase();
15
16 if (d_options.dryrun())
17 *d_report << "--dry-run: SH/SSH connections not established" << endl;
18 else
19 d_integrityScanner->startCommandShells();
20
21 jobsHandler();
22 }
23
24
25
26
27
28
29
30
31
0 #include "stealth.ih"
1
2 bool Stealth::incomingRequest(istream &in, ostream &out)
3 {
4 int request; // read te request
5 if (not (in >> request).ignore(numeric_limits<int>::max(), '\n'))
6 request = UNKNOWN;
7
8 RunMode incoming;
9 incoming.setMode(RunMode::validate(request));
10
11 string answer = (this->*s_request.find(incoming.mode())->second)();
12
13 if (not answer.empty()) // error or no operation (nop)
14 {
15 if (answer == "nop")
16 answer.clear();
17
18 out << answer << endl;
19 return false; // no-action or error request:
20 // read the next request
21 }
22
23 d_pending = incoming;
24 return true;
25 }
11
22 void Stealth::integrityScan()
33 {
4 d_stealthLog.scanHeader();
4 d_report->scanHeader();
55
66 if (d_options.dryrun())
7 d_stealthLog << "--dry-run: integrity scan suppressed" << endl;
8 else
9 d_integrityScanner->run();
7 {
8 *d_report << "--dry-run: would have performed an integrity scan" <<
9 endl;
10 return;
11 }
1012
11 if (d_run.interrupted())
12 return;
13
14 d_run.setMode(d_options.daemon() or d_options.repeat() ? WAIT : LEAVE);
13 d_integrityScanner->run();
14 m2 << "Integrity scan completed" << endl;
1515 }
1616
1717
0 #include "stealth.ih"
1
2 // see also documentation/images/ipcinterface.jpg
3
4 void Stealth::ipcInterface()
5 try
6 {
7 string const &udsName = d_options.unixDomainSocket();
8
9 m2 << "Unix Domain Socket: " << udsName << endl;
10
11 LocalServerSocket uds(udsName);
12
13 uds.listen();
14
15 do
16 {
17 int socket = uds.accept(); // accept a request
18
19 IFdStream in(socket); // stream to read the request from
20 OFdStream out(socket); // stream to write answers to the
21 // ipc-stealth process to.
22 if (incomingRequest(in, out))
23 {
24 d_ipc.wait(); // wait until an IPC command can be
25 // accepted
26
27 out << endl; // all commands succeed: empty return
28 // texts indicates so.
29 notifyTask();
30 }
31 }
32 while (not d_task.hasMode(TERMINATE));
33 }
34 catch (exception const &exc)
35 {
36 ostringstream msg;
37 msg << '\n' << exc.what() << "\n"
38 " TERMINATING: exception in ipcInterface:\n";
39
40 imsg << msg.str() << endl;
41 *d_report << msg.str() << endl;
42 d_report->mail();
43
44 d_pending.setMode(TERMINATE);
45 d_ipc.wait();
46 notifyTask();
47 }
0 #include "stealth.ih"
1
2 bool Stealth::ipcMode()
3 {
4 if (not d_options.ipc())
5 return false;
6
7 int fd;
8 LocalClientSocket uds;
9
10 try
11 {
12 uds.open(d_options.unixDomainSocket());
13 fd = uds.connect();
14 }
15 catch (...)
16 {
17 throw Exception() << "can't connect to `" <<
18 d_options.unixDomainSocket() << '\'';
19 }
20
21 OFdStream out(fd);
22 out << d_options.mode() << endl; // send the requested mode
23
24 IFdStream in(fd);
25 string answer; // wait for the answer
26 getline(in, answer);
27
28 if (not answer.empty()) // show the answer if something
29 throw Exception() << answer; // went wrong.
30
31 return true;
32 }
33
34
0 #include "stealth.ih"
1
2 void Stealth::jobsHandler()
3 {
4 bool prompt = not d_options.daemon() && d_options.repeat();
5 bool runOnce = not d_options.daemon() && not d_options.repeat();
6
7 if (prompt)
8 {
9 thread(startThread, &Stealth::waitForKey, this).detach();
10 cout << "? " << flush;
11 }
12
13 while (true)
14 {
15 nextJob();
16
17 m1 << d_task << " next." << endl;
18
19 // process the current request
20 (this->*(s_task.find(d_task.mode())->second))();
21
22 d_report->mail();
23
24 if (runOnce)
25 break;
26
27 if (d_task.hasMode(TERMINATE))
28 {
29 d_ipc.notify();
30 break;
31 }
32
33 if (d_autoJob)
34 {
35 d_autoJob = false;
36 continue;
37 }
38 d_ipc.notify();
39 }
40 }
+0
-8
stealth/logmsg.cc less more
0 #include "stealth.ih"
1
2 void Stealth::logMsg(char const *label)
3 {
4 d_stealthLog << "STEALTH " << label << " after " <<
5 d_integrityScanner->nScans() << " scans at " <<
6 d_options.rfc2822() << endl;
7 }
0 #include "stealth.ih"
1
2 LogReportbuf::LogReportbuf(Report &report)
3 :
4 d_report(report)
5 {}
+0
-15
stealth/maillogs.cc less more
0 #include "stealth.ih"
1
2 // Called from performTask()
3
4 void Stealth::mailLogs()
5 {
6 if (not d_stealthLog.hasMail())
7 {
8 m3 << "No new logs to mail" << endl;
9 return;
10 }
11
12 processMail();
13 }
14
0 #include "stealth.ih"
1
2 void Stealth::nextJob()
3 {
4 if (not d_options.repeat()) // if the scan is not automatically
5 d_job.wait(); // restarted, then wait for the next job
6 else
7 {
8 size_t nSeconds = d_options.nextIntegrityScan();
9
10 m2 << "waiting for " << nSeconds << " seconds or for a command" <<
11 endl;
12
13 while (true)
14 {
15 auto cvStatus = d_job.wait_for(chrono::seconds(nSeconds));
16
17 m2 << "wait ends" << endl;
18
19 if (cvStatus != cv_status::timeout)
20 break;
21
22 m2 << "timeout" << endl;
23
24 if
25 (
26 d_task.hasMode(SUSPEND) // At timeout during
27 || // suspend, or
28 d_integrityScanner->active() // still busy scanning
29 )
30 {
31 m2 << "SUSPEND or actively scanning: wait some more" << endl;
32 continue; // then wait some more
33 }
34
35 d_task.setMode(INTEGRITY_SCAN);
36 d_autoJob = true;
37 break;
38 }
39 }
40 }
0 #include "stealth.ih"
1
2 void Stealth::notifyTask()
3 {
4 d_task = d_pending; // set the next request
5 d_pending.setMode(UNKNOWN); // clear the pending request
6
7 d_job.notify(); // notify processRequests (i.e.,
8 }
0 #include "stealth.ih"
1
2 int LogReportbuf::overflow(int ch)
3 {
4 if (ch != EOF)
5 d_report.put(ch);
6 return ch;
7 }
00 #include "stealth.ih"
11
22 void Stealth::parentProcess()
3 {
4 d_ipc.writeRunFile(pid());
5 }
3 {}
64
+0
-14
stealth/policydepdatamembers.cc less more
0 #include "stealth.ih"
1
2 void Stealth::policyDepDataMembers()
3 {
4 d_policyFile = make_shared<PolicyFile>(d_options.policyFilePath());
5
6 d_stealthLog.open((*d_policyFile)["REPORT"]);
7
8 d_integrityScanner = make_shared<IntegrityScanner>(
9 d_run, *d_policyFile, d_stealthLog
10 );
11 }
12
13
0 #include "stealth.ih"
1
2 // Called by main() once all preliminary actions have been completed.
3
4 void Stealth::policyMode()
5 {
6 d_logUnit.setupLogs();
7 setUniquePtrs();
8
9 if (d_options.daemon())
10 fork(); // creates the daemon. Its childProcess
11 else // does the tasks.
12 doTasks();
13 }
+0
-11
stealth/process.cc less more
0 #include "stealth.ih"
1
2 void Stealth::process(Mode request)
3 try
4 {
5 (this->*(s_task.find(request)->second))();
6 }
7 catch (Mode)
8 {
9 terminate();
10 }
+0
-21
stealth/processmail.cc less more
0 #include "stealth.ih"
1
2 void Stealth::processMail()
3 {
4 if (d_options.logMail())
5 {
6 d_stealthLog.rewind();
7
8 string line;
9 while (getline(d_stealthLog.in(), line))
10 imsg << "Mail: " << line << endl;
11 }
12
13 if (d_options.sendMail())
14 sendMail();
15 }
16
17
18
19
20
+0
-14
stealth/processpolicy.cc less more
0 #include "stealth.ih"
1
2 // Called by main() once all preliminary actions have been completed.
3
4 // Signals are sent by sendSignal. Signals are caught by handleProcessSignals
5 // contactOtherStealth sends the signals depending on command-line options
6
7 void Stealth::processPolicy()
8 {
9 if (d_options.daemon())
10 fork(); // creates the daemon. Its childProcess
11 else // does the chores.
12 doChores();
13 }
+0
-26
stealth/processrequests.cc less more
0 #include "stealth.ih"
1
2 // requests are received through interrupts (SIGUSR1, SIGTERM, SIGINT). For
3 // SIGUSR1 requests the type of request is written in line 2 of the run file.
4 // When a SIGUSR1 signal is received, the request
5
6 void Stealth::processRequests()
7 {
8 while (true)
9 {
10 Mode request = d_run.mode();
11
12 if (request == LEAVE)
13 break;
14
15 m1 << "MODE: " << d_run.modeName() << endl;
16
17 d_stealthLog.refresh();
18
19 process(request); // process the current request
20
21 mailLogs();
22
23 waitForRequest();
24 }
25 }
11
22 void Stealth::reload()
33 {
4 logMsg("reloads its policy file");
5
6 mailLogs();
7
8 d_stealthLog.close();
4 timestamp("reloads its policy file");
95
106 if (d_options.dryrun())
11 d_stealthLog << "--dry-run: reload suppressed" << endl;
7 *d_report << "--dry-run: would have reloaded the policy file" << endl;
128 else
139 {
14 d_policyFile->reload();
15
16 d_stealthLog.open((*d_policyFile)["REPORT"]);
17
18 d_integrityScanner = make_shared<IntegrityScanner>(
19 d_run, *d_policyFile, d_stealthLog
20 );
10 PolicyFile *policyFilePtr = new PolicyFile(d_options);
11
12 Report *reportPtr = new Report(d_options, *policyFilePtr);
13
14 d_integrityScanner.reset(
15 new IntegrityScanner(d_pending, d_options,
16 *policyFilePtr, *reportPtr)
17 );
2118
2219 d_integrityScanner->startCommandShells();
20
21 setupFatalReport();
22
23 d_logUnit.setupLogs(d_logReport);
24
25 d_report.reset(reportPtr);
26 d_policyFile.reset(policyFilePtr);
27
28 m2 << "reloaded policy file `" << d_options.policyFilePath() << "'\n"
29 "reconstructed the Integrity Scanner" << endl;
30 m3 << "max. download size: " << d_options.maxSizeStr() << endl;
2331 }
24
25 d_run.setMode(INTEGRITY_SCAN);
32 autoScan("reload");
2633 }
2734
2835
36
37
00 #include "stealth.ih"
11
2 void Stealth::reloadRequest()
2 string Stealth::reloadRequest()
33 {
4 if (d_run.mode(INTEGRITY_SCAN | WAIT | SUSPEND))
5 acceptMode(RELOAD);
6 else
7 deniedMode("--reload");
4 string ret = d_task.hasMode(INTEGRITY_SCAN) ?
5 acceptMode(RELOAD)
6 :
7 deniedMode("--reload");
8 return ret;
89 }
910
1011
0 #include "stealth.ih"
1
2 void Stealth::rerun()
3 {
4 *d_report << "STEALTH explicit integrity scan rerun at " <<
5 d_options.rfc2822() << endl;
6 autoScan("rerun");
7 }
00 #include "stealth.ih"
11
2 void Stealth::rerunRequest()
2 string Stealth::rerunRequest()
33 {
4 if (d_run.mode(WAIT))
5 acceptMode(INTEGRITY_SCAN);
6 else
7 deniedMode("--rerun");
4 string ret = d_task.hasMode(INTEGRITY_SCAN) ?
5 acceptMode(RERUN)
6 :
7 deniedMode("--rerun");
8
9 return ret;
810 }
11
22 void Stealth::resume()
33 {
4 d_stealthLog << "STEALTH resumes its tasks at " << d_options.rfc2822() <<
4 *d_report << "STEALTH resumes its tasks at " << d_options.rfc2822() <<
55 endl;
6 d_run.setMode(INTEGRITY_SCAN);
7
8 m2 << "resuming tasks: INTEGRITY_SCAN next" << endl;
6 autoScan("resume");
97 }
00 #include "stealth.ih"
11
2 void Stealth::resumeRequest()
2 std::string Stealth::resumeRequest()
33 {
4 if (d_run.mode(SUSPEND))
5 acceptMode(RESUME);
6 else
7 deniedMode("--resume");
4 string ret = d_task.hasMode(SUSPEND) ?
5 acceptMode(RESUME)
6 :
7 deniedMode("--resume");
8
9 return ret;
810 }
+0
-34
stealth/sendmail.cc less more
0 #include "stealth.ih"
1
2 void Stealth::sendMail()
3 {
4 d_stealthLog.rewind();
5
6 m3 << "Mailing new logs using: " <<
7 (*d_policyFile)["MAILER"] << ' ' <<
8 (*d_policyFile)["MAILARGS"] << " " <<
9 (*d_policyFile)["EMAIL"] << endl;
10
11 // mailcommand subject and email are called as separate arguments
12 // If subject contains blanks, they will be interpreted as separate
13 // arguments by the `mail' IOFork. Ususally d_policyFile["MAILER"] will
14 // call a script.
15
16 Process mail(
17 Process::CIN | Process::IGNORE_COUT | Process::IGNORE_CERR,
18 (*d_policyFile)["MAILER"] + ' ' +
19 (*d_policyFile)["MAILARGS"] + ' ' +
20 (*d_policyFile)["EMAIL"]
21 );
22
23 mail.start();
24
25 mail << d_stealthLog.headerLine() << '\n';
26
27 string line;
28 while (getline(d_stealthLog.in(), line))
29 mail << line << '\n';
30
31 mail.close();
32 mail.waitForChild();
33 }
0 #include "stealth.ih"
1
2 void Stealth::setUniquePtrs()
3 {
4 d_policyFile.reset(new PolicyFile(d_options)); // the PolicyFile may
5 // redefine some options
6
7 d_report.reset(new Report(d_options, *d_policyFile));
8
9 d_integrityScanner.reset(
10 new IntegrityScanner(d_pending, d_options, *d_policyFile, *d_report)
11 );
12
13 setupFatalReport();
14
15 d_logUnit.setupLogs(d_logReport); // possibly redefine the log files
16
17 m2 << "constructed the Integrity Scanner" << endl;
18 m3 << "max. download size: " << d_options.maxSizeStr() << endl;
19 }
0 #include "stealth.ih"
1
2 void Stealth::setupFatalReport()
3 {
4 delete d_logReportbuf;
5
6 d_logReportbuf = new LogReportbuf(*d_report);
7 d_logReport.rdbuf(d_logReportbuf);
8 d_logReport.clear();
9 }
+0
-24
stealth/signalhandler.cc less more
0 #include "stealth.ih"
1
2 void Stealth::signalHandler(size_t signal)
3 {
4 d_ipc.signaled();
5
6 if (d_options.ipc())
7 {
8 d_ipc.request(); // retrieve the return message
9 return;
10 }
11
12 d_request = true; // set to false by unknownRequest.
13
14 // SIGUSR1 signals are retrieved from
15 // the runfile. Other signals
16 // (TERM, INT) terminate the daemon.
17 (this->*s_request.find(
18 signal == SIGUSR1 ? d_ipc.request() : TERMINATE
19 )->second)();
20 }
21
22
23
00 #ifndef _INCLUDED_STEALTH_H_
11 #define _INCLUDED_STEALTH_H_
22
3 #include <iosfwd>
34 #include <string>
45 #include <memory>
6 #include <thread>
57
6 #include <bobcat/signal>
78 #include <bobcat/fork>
9 #include <bobcat/semaphore>
810
9 #include "../runmode/runmode.h" // declares LinearMap
10 #include "../ipc/ipc.h"
11 #include "../stealthlog/stealthlog.h"
11 #include "../runmode/runmode.h" // includes LinearMap, StealthEnums
12 #include "../options/options.h"
13 #include "../logunit/logunit.h"
1214
1315 class PolicyFile;
1416 class IntegrityScanner;
15 class Options;
17 class Report;
1618
17 class Stealth: public StealthEnums, public FBB::Fork, public FBB::SignalHandler
19 class LogReportbuf;
20
21 class Stealth: public StealthEnums, public FBB::Fork
1822 {
19 static size_t const s_contactPeerWaitSeconds = 3;
23 Options d_options;
24 LogUnit d_logUnit;
2025
21 Options &d_options;
22 IPC d_ipc;
26 RunMode d_task; // the current run-mode.
27 RunMode d_pending; // a pending run-mode.
2328
24 RunMode d_run;
25 volatile bool d_request;
29 FBB::Semaphore d_ipc; // Folowing wait Stealth is available
30 // for the next ipc-command
2631
27 StealthLog d_stealthLog;
28 std::shared_ptr<PolicyFile> d_policyFile;
29 std::shared_ptr<IntegrityScanner> d_integrityScanner;
32 FBB::Semaphore d_job; // Semaphore for the next command
33
34 bool d_autoJob = false;
3035
31 typedef void (Stealth::*Action)();
36 std::unique_ptr<PolicyFile> d_policyFile;
37 std::unique_ptr<IntegrityScanner> d_integrityScanner;
38 std::unique_ptr<Report> d_report; // and sends mail
3239
33 static FBB::LinearMap<Mode, Action> s_task;
40 std::ostream d_logReport; // configured into LogUnit
41 LogReportbuf *d_logReportbuf = 0;
42
43 typedef std::string (Stealth::*Action)();
44 typedef void (Stealth::*Task)();
45
46 static FBB::LinearMap<Mode, Task> s_task;
3447 static FBB::LinearMap<Mode, Action> s_request;
3548
3649 public:
3750 Stealth();
3851 ~Stealth() override;
3952
40 bool contactPeer(); // contact a stealth daemon
41 void processPolicy(); // do all policy-file related tasks
53 bool ipcMode(); // contact a stealth daemon
54 void policyMode(); // do all policy-file related tasks
4255
4356 private:
57 void parentProcess() override; // no actions here
4458 void childProcess() override;
45 void parentProcess() override;
46 void signalHandler(size_t signum) override;
47 void rerunRequest();
48 void suspendRequest();
49 void resumeRequest();
50 void reloadRequest();
51 void terminateRequest();
52 void unknownRequest();
53 void acceptMode(Mode mode);
54 void deniedMode(char const *request);
5559
56 void logMsg(char const *label);
60 std::string rerunRequest();
61 std::string suspendRequest();
62 std::string resumeRequest();
63 std::string reloadRequest();
64 std::string terminateRequest();
65 std::string unknownRequest();
66 std::string acceptMode(Mode mode);
67 std::string deniedMode(char const *request);
5768
58 void mailLogs(); // mail the logs or write them to cout
59 void processMail();
60 void sendMail();
69 void doTasks(); // run all scanning (related) tasks
70 void setUniquePtrs(); // initialize the unique_ptrs
71 void setupFatalReport(); // fmsg also inserts into the report and
72 // into the mail
6173
62 void doChores(); // run all scanning (related) tasks
63 void policyDepDataMembers();
64 void defineSupportedSignals();
74 void timestamp(char const *label);
6575
66 void processRequests();
67 void process(Mode request); // process one single request
68 void waitForRequest();
76 void jobsHandler();
77 void nextJob();
78 void reload(); // reload the configuration files.
79 void terminate();
80 void suspend();
81 void resume();
82 void rerun();
83 void integrityScan();
6984
70 void integrityScan();
85 void autoScan(char const *label);
7186
87 void ipcInterface(); // thread
88 bool incomingRequest(std::istream &in, std::ostream &out);
89 void notifyTask();
7290
73 void reload(); // reload the configuration files.
74 void terminate();
75 void suspend();
76 void resume();
91 void waitForKey(); // thread
7792
93 static void startThread(void (Stealth::*member)(), Stealth *obj);
7894 };
7995
8096 #endif
81
82
83
84
85
86
87
88
00 #include "stealth.h"
11
2 #include <iostream>
2 #include <unistd.h>
3 #include <sstream>
4 #include <thread>
5 #include <chrono>
36
47 #include <bobcat/mstream>
58 #include <bobcat/exception>
69 #include <bobcat/linearmap>
710 #include <bobcat/process>
11 #include <bobcat/ifdstream>
12 #include <bobcat/ofdstream>
13 #include <bobcat/localclientsocket>
14 #include <bobcat/localserversocket>
815
916 #include "../policyfile/policyfile.h"
1017 #include "../integrityscanner/integrityscanner.h"
11 #include "../options/options.h"
18 #include "../report/report.h"
1219 #include "../msg/msg.h"
20 #include "../util/util.h"
21
22
23 inline void Stealth::timestamp(char const *label)
24 {
25 d_report->timestamp(label, d_integrityScanner->nScans());
26 }
27
28 inline void Stealth::startThread(void (Stealth::*member)(), Stealth *obj)
29 {
30 (obj->*member)();
31 }
1332
1433 using namespace std;
1534 using namespace FBB;
35
36 class LogReportbuf: public streambuf
37 {
38 Report &d_report;
39
40 public:
41 LogReportbuf(Report &report);
42
43 private:
44 int overflow(int ch) override;
45 int sync() override;
46 };
11
22 Stealth::Stealth()
33 :
4 d_options(Options::instance()) // determine all options / runmode
4 d_logUnit(d_options),
5 d_ipc(0), // Semaphores
6 d_job(1),
7 d_logReport(0)
58 {
6 d_run.setMode(d_options.mode());
9 d_task.setMode(d_options.mode());
10 d_pending.setMode(UNKNOWN);
711 }
812
913
11
22 void Stealth::suspend()
33 {
4 logMsg("is suspended");
4 m2 << "received SUSPEND request" << endl;
55
6 mailLogs();
7 d_stealthLog.refresh();
8
9 while (true)
10 {
11 d_ipc.wait();
12 if (d_run.mode(RESUME | TERMINATE))
13 break;
14 m2 << "ignoring wake up signal in SUSPEND mode" << endl;
15 }
16 m2 << "received SUSPEND signal" << endl;
6 timestamp("is suspended");
177 }
00 #include "stealth.ih"
11
2 void Stealth::suspendRequest()
2 string Stealth::suspendRequest()
33 {
4 if (d_run.mode(INTEGRITY_SCAN | WAIT | SUSPEND))
5 acceptMode(SUSPEND);
6 else
7 deniedMode("--suspend");
4 string ret;
5
6 switch (d_task.mode())
7 {
8 case INTEGRITY_SCAN:
9 ret = acceptMode(SUSPEND);
10 break;
11
12 case SUSPEND:
13 ret = "nop";
14 break;
15
16 default:
17 ret = deniedMode("--suspend");
18 break;
19 }
20
21 return ret;
822 }
0 #include "stealth.ih"
1
2 int LogReportbuf::sync()
3 {
4 d_report.flush();
5 d_report.mail();
6 return 0;
7 }
11
22 void Stealth::terminate()
33 {
4 logMsg("terminates");
5 d_run.setMode(LEAVE);
4 timestamp("terminates");
65 }
00 #include "stealth.ih"
11
2 void Stealth::terminateRequest()
2 string Stealth::terminateRequest()
33 {
4 acceptMode(TERMINATE);
4 return acceptMode(TERMINATE);
55 }
00 #include "stealth.ih"
11
2 void Stealth::unknownRequest()
2 string Stealth::unknownRequest()
33 {
44 ostringstream msg;
5 msg << "received undefined request `" << d_ipc.requestText() << '\'';
65
7 m2 << msg << endl;
8 d_stealthLog << msg << endl;
6 string ret("unknown request");
7 msg << "received " << ret;
98
10 d_request = false;
9 m2 << msg.str() << endl;
10 *d_report << msg.str() << endl;
11
12 return ret;
1113 }
1214
1315
0 #include "stealth.ih"
1
2 void Stealth::waitForKey()
3 {
4 cin.ignore(numeric_limits<int>::max(), '\n');
5 imsg << "STEALTH (foreground) TERMINATED by user-request" << endl;
6 d_task.setMode(TERMINATE);
7 d_job.notify();
8 }
9
+0
-19
stealth/waitforrequest.cc less more
0 #include "stealth.ih"
1
2 void Stealth::waitForRequest()
3 {
4 if (d_run.mode(WAIT))
5 {
6 m1 << "MODE: WAIT" << endl;
7
8 while (true)
9 {
10 d_ipc.timedWait();
11 if (d_ipc.timeout() || d_request) // wait for the next request
12 break; // or timeout
13 }
14
15 if (d_run.mode(WAIT))
16 d_run.setMode(INTEGRITY_SCAN);
17 }
18 }
00 oxref by Frank B. Brokken (f.b.brokken@rug.nl)
1 oxref V1.00.01 2012-2013
2
3 CREATED Fri, 29 Aug 2014 09:48:55 +0000
1 oxref V1.00.02 2012-2015
2
3 CREATED Sat, 14 Feb 2015 15:43:45 +0000
44 CROSS REFERENCE FOR: -fxs tmp/libmodules.a
55 ----------------------------------------------------------------------
6
7 absPath(std::string const&, std::string&)
8 Full name: Util::absPath(std::string const&, std::string&)
9 Source: abspath.cc
10 Used By:
11 options1.cc: Options::Options()
12 setlog.cc: Options::setLog()
13 setpolicypath.cc: Options::setPolicyPath()
14 setskipfile.cc: Options::setSkipFile()
15 fixrelativelocations.cc: PolicyFile::fixRelativeLocations()
616
717 acceptMode(StealthEnums::Mode)
818 Full name: Stealth::acceptMode(StealthEnums::Mode)
2030 Used By:
2131 setskip.cc: IntegrityScanner::setSkip()
2232
33 autoScan(char const*)
34 Full name: Stealth::autoScan(char const*)
35 Source: autoscan.cc
36 Used By:
37 reload.cc: Stealth::reload()
38 rerun.cc: Stealth::rerun()
39 resume.cc: Stealth::resume()
40
41 chdirBase() const
42 Full name: PolicyFile::chdirBase() const
43 Source: chdirbase.cc
44 Used By:
45 load.cc: PolicyFile::load()
46
2347 checkM(std::string const&, char const*) const
2448 Full name: Options::checkM(std::string const&, char const*) const
2549 Source: checkm.cc
5781 Source: datetime.cc
5882 Used By:
5983 nodifferences.cc: IntegrityScanner::noDifferences(std::string const&, std::string const&)
60
61 defineSupportedSignals()
62 Full name: Stealth::defineSupportedSignals()
63 Source: definesupportedsignals.cc
64 Used By:
65 dochores.cc: Stealth::doChores()
6684
6785 deniedMode(char const*)
6886 Full name: Stealth::deniedMode(char const*)
86104 local.cc: IntegrityScanner::local(std::string const&)
87105 remote.cc: IntegrityScanner::remote(std::string const&)
88106
89 doChores()
90 Full name: Stealth::doChores()
91 Source: dochores.cc
92 Used By:
93 childprocess.cc: Stealth::childProcess()
94 processpolicy.cc: Stealth::processPolicy()
95
96107 doPlainCommand(FBB::Process&)
97108 Full name: IntegrityScanner::doPlainCommand(FBB::Process&)
98109 Source: doplaincommand.cc
100111 local.cc: IntegrityScanner::local(std::string const&)
101112 remote.cc: IntegrityScanner::remote(std::string const&)
102113
114 doTasks()
115 Full name: Stealth::doTasks()
116 Source: dotasks.cc
117 Used By:
118 childprocess.cc: Stealth::childProcess()
119 policymode.cc: Stealth::policyMode()
120
103121 execute(std::string const&)
104122 Full name: IntegrityScanner::execute(std::string const&)
105123 Source: execute.cc
111129 Full name: PolicyFile::fetchCommands()
112130 Source: fetchcommands.cc
113131 Used By:
114 reload.cc: PolicyFile::reload()
132 load.cc: PolicyFile::load()
115133
116134 fileName(std::string const&)
117135 Full name: IntegrityScanner::fileName(std::string const&)
120138 get.cc: IntegrityScanner::get(std::string const&)
121139 put.cc: IntegrityScanner::put(std::string const&)
122140
141 fixRelativeLocations()
142 Full name: PolicyFile::fixRelativeLocations()
143 Source: fixrelativelocations.cc
144 Used By:
145 fetchcommands.cc: PolicyFile::fetchCommands()
146
123147 foreground(unsigned int)
124148 Full name: IntegrityScanner::foreground(unsigned int)
125149 Source: foreground.cc
139163 Used By:
140164 execute.cc: IntegrityScanner::execute(std::string const&)
141165
166 getCwd()
167 Full name: Options::getCwd()
168 Source: getcwd.cc
169 Used By:
170 options1.cc: Options::Options()
171
142172 getPath(std::string const&) const
143173 Full name: IntegrityScanner::getPath(std::string const&) const
144174 Source: getpath.cc
147177 nodifferences.cc: IntegrityScanner::noDifferences(std::string const&, std::string const&)
148178
149179 hasMail()
150 Full name: StealthLog::hasMail()
180 Full name: Report::hasMail()
151181 Source: hasmail.cc
152182 Used By:
153 maillogs.cc: Stealth::mailLogs()
154
155 headerLine() const
156 Full name: StealthLog::headerLine() const
157 Source: headerline.cc
158 Used By:
159 sendmail.cc: Stealth::sendMail()
183 destructor.cc: Report::~Report()
184 mail.cc: Report::mail()
185
186 incomingRequest(std::istream&, std::ostream&)
187 Full name: Stealth::incomingRequest(std::istream&, std::ostream&)
188 Source: incomingrequest.cc
189 Used By:
190 ipcinterface.cc: Stealth::ipcInterface()
160191
161192 insert(FBB::LinearMap<std::string, std::string, std::allocator<std::pair<std::string const, std::string> > >&, std::string const&)
162193 Full name: PolicyFile::insert(FBB::LinearMap<std::string, std::string, std::allocator<std::pair<std::string const, std::string> > >&, std::string const&)
164195 Used By:
165196 directivesandcommands.cc: PolicyFile::directivesAndCommands()
166197
167 instance()
168 Full name: Options::instance()
169 Source: instance.cc
170 Used By:
171 ipc1.cc: IPC::IPC()
172 stealth1.cc: Stealth::Stealth()
173 fetchcommands.cc: PolicyFile::fetchCommands()
174 setmode.cc: RunMode::setMode(StealthEnums::Mode)
175 open.cc: StealthLog::open(std::string const&)
176 scanheader.cc: StealthLog::scanHeader()
177 integrityscanner1.cc: IntegrityScanner::IntegrityScanner(RunMode&, PolicyFile&, std::ostream&)
178
179198 integrityScan()
180199 Full name: Stealth::integrityScan()
181200 Source: integrityscan.cc
182201 Used By:
183202 data.cc: GLOBALS data.cc 11data.o
184203
185 IntegrityScanner(RunMode&, PolicyFile&, std::ostream&)
186 Full name: IntegrityScanner::IntegrityScanner(RunMode&, PolicyFile&, std::ostream&)
204 IntegrityScanner(RunMode const&, Options&, PolicyFile&, std::ostream&)
205 Full name: IntegrityScanner::IntegrityScanner(RunMode const&, Options&, PolicyFile&, std::ostream&)
187206 Source: integrityscanner1.cc
188207 Used By:
189 policydepdatamembers.cc: Stealth::policyDepDataMembers()
190208 reload.cc: Stealth::reload()
191
192 IPC()
193 Full name: IPC::IPC()
194 Source: ipc1.cc
195 Used By:
196 stealth1.cc: Stealth::Stealth()
197
198 leave(std::ostream&)
199 Full name: StealthEnums::leave(std::ostream&)
200 Source: leave.cc
201 Used By:
202 checksize.cc: IntegrityScanner::checkSize(std::string const&, long)
203 copy.cc: IntegrityScanner::copy(FBB::Process&, std::string const&)
204 execute.cc: IntegrityScanner::execute(std::string const&)
205 get.cc: IntegrityScanner::get(std::string const&)
206 nextcommand.cc: IntegrityScanner::nextCommand(std::ostream&, std::string const&)
207 put.cc: IntegrityScanner::put(std::string const&)
208 putcommand.cc: IntegrityScanner::putCommand(std::string const&, std::string const&) const
209 read.cc: IntegrityScanner::read(FBB::Process&, std::string const&)
210 sameoutput.cc: IntegrityScanner::sameOutput(std::string const&, FBB::Process&)
211 testexitvalue.cc: IntegrityScanner::testExitValue(std::string const&, std::string const&)
212 write.cc: IntegrityScanner::write(std::string const&)
213
214 loadPolicyOptions()
215 Full name: Options::loadPolicyOptions()
216 Source: loadpolicyoptions.cc
217 Used By:
218 options1.cc: Options::Options()
209 setuniqueptrs.cc: Stealth::setUniquePtrs()
210
211 ipcInterface()
212 Full name: Stealth::ipcInterface()
213 Source: ipcinterface.cc
214 Used By:
215 childprocess.cc: Stealth::childProcess()
216
217 jobsHandler()
218 Full name: Stealth::jobsHandler()
219 Source: jobshandler.cc
220 Used By:
221 dotasks.cc: Stealth::doTasks()
222
223 load()
224 Full name: PolicyFile::load()
225 Source: load.cc
226 Used By:
227 policyfile1.cc: PolicyFile::PolicyFile(Options&)
228
229 loadOptions(FBB::ConfigFile&, unsigned int)
230 Full name: PolicyFile::loadOptions(FBB::ConfigFile&, unsigned int)
231 Source: loadoptions.cc
232 Used By:
233 directivesandcommands.cc: PolicyFile::directivesAndCommands()
219234
220235 loadSkipFiles()
221236 Full name: IntegrityScanner::loadSkipFiles()
222237 Source: loadskipfiles.cc
223238 Used By:
224 integrityscanner1.cc: IntegrityScanner::IntegrityScanner(RunMode&, PolicyFile&, std::ostream&)
239 integrityscanner1.cc: IntegrityScanner::IntegrityScanner(RunMode const&, Options&, PolicyFile&, std::ostream&)
225240
226241 local(std::string const&)
227242 Full name: IntegrityScanner::local(std::string const&)
229244 Used By:
230245 execute.cc: IntegrityScanner::execute(std::string const&)
231246
232 logMsg(char const*)
233 Full name: Stealth::logMsg(char const*)
234 Source: logmsg.cc
235 Used By:
236 reload.cc: Stealth::reload()
237 suspend.cc: Stealth::suspend()
238 terminate.cc: Stealth::terminate()
247 LogReportbuf(Report&)
248 Full name: LogReportbuf::LogReportbuf(Report&)
249 Source: logreportbuf1.cc
250 Used By:
251 setupfatalreport.cc: Stealth::setupFatalReport()
252
253 LogUnit(Options&)
254 Full name: LogUnit::LogUnit(Options&)
255 Source: logunit1.cc
256 Used By:
257 stealth1.cc: Stealth::Stealth()
239258
240259 m1
241260 Full name: m1
242261 Source: data.cc
243262 Used By:
244263 childprocess.cc: Stealth::childProcess()
245 processrequests.cc: Stealth::processRequests()
246 waitforrequest.cc: Stealth::waitForRequest()
264 dotasks.cc: Stealth::doTasks()
265 jobshandler.cc: Stealth::jobsHandler()
247266 setverbosity.cc: Msg::setVerbosity(unsigned int)
248 options1.cc: Options::Options()
249267 execute.cc: IntegrityScanner::execute(std::string const&)
250268 nodifferences.cc: IntegrityScanner::noDifferences(std::string const&, std::string const&)
251269 run.cc: IntegrityScanner::run()
254272 Full name: m2
255273 Source: data.cc
256274 Used By:
257 sendrequest.cc: IPC::sendRequest(char const*, int)
258 sendrequestor.cc: IPC::sendRequestor(std::string const&)
259 signaldaemon.cc: IPC::signalDaemon()
260 timedwait.cc: IPC::timedWait()
261 wait.cc: IPC::wait(bool)
262 writerunfile.cc: IPC::writeRunFile(int)
275 autoscan.cc: Stealth::autoScan(char const*)
263276 deniedmode.cc: Stealth::deniedMode(char const*)
264 resume.cc: Stealth::resume()
277 integrityscan.cc: Stealth::integrityScan()
278 ipcinterface.cc: Stealth::ipcInterface()
279 nextjob.cc: Stealth::nextJob()
280 reload.cc: Stealth::reload()
281 setuniqueptrs.cc: Stealth::setUniquePtrs()
265282 suspend.cc: Stealth::suspend()
266283 unknownrequest.cc: Stealth::unknownRequest()
267284 setverbosity.cc: Msg::setVerbosity(unsigned int)
268 waitfor.cc: Wait11::waitFor(unsigned int, bool)
269 waitsignal.cc: Wait11::waitSignal(bool)
270 reload.cc: PolicyFile::reload()
271 integrityscanner1.cc: IntegrityScanner::IntegrityScanner(RunMode&, PolicyFile&, std::ostream&)
272285 startcommandshells.cc: IntegrityScanner::startCommandShells()
273286
274287 m3
275288 Full name: m3
276289 Source: data.cc
277290 Used By:
278 maillogs.cc: Stealth::mailLogs()
279 sendmail.cc: Stealth::sendMail()
291 reload.cc: Stealth::reload()
292 setuniqueptrs.cc: Stealth::setUniquePtrs()
280293 setverbosity.cc: Msg::setVerbosity(unsigned int)
294 mail.cc: Report::mail()
295 sendmail.cc: Report::sendMail()
281296 copy.cc: IntegrityScanner::copy(FBB::Process&, std::string const&)
282 integrityscanner1.cc: IntegrityScanner::IntegrityScanner(RunMode&, PolicyFile&, std::ostream&)
283297 loadskipfiles.cc: IntegrityScanner::loadSkipFiles()
284298 nextcommand.cc: IntegrityScanner::nextCommand(std::ostream&, std::string const&)
285299 nodifferences.cc: IntegrityScanner::noDifferences(std::string const&, std::string const&)
291305 waitforsentinel.cc: IntegrityScanner::waitForSentinel(FBB::Process&)
292306 write.cc: IntegrityScanner::write(std::string const&)
293307
294 mailLogs()
295 Full name: Stealth::mailLogs()
296 Source: maillogs.cc
297 Used By:
298 processrequests.cc: Stealth::processRequests()
299 reload.cc: Stealth::reload()
300 suspend.cc: Stealth::suspend()
308 mail()
309 Full name: Report::mail()
310 Source: mail.cc
311 Used By:
312 ipcinterface.cc: Stealth::ipcInterface()
313 jobshandler.cc: Stealth::jobsHandler()
314 timestamp.cc: Report::timestamp(char const*, unsigned int)
315 sync.cc: LogReportbuf::sync()
301316
302317 mkdir(std::string const&)
303318 Full name: Util::mkdir(std::string const&)
304319 Source: mkdir.cc
305320 Used By:
306 reload.cc: PolicyFile::reload()
321 load.cc: PolicyFile::load()
307322 sameoutput.cc: IntegrityScanner::sameOutput(std::string const&, FBB::Process&)
308323
309324 mp
320335 Full name: Msg::Msg()
321336 Source: msg1.cc
322337 Used By:
323 data.cc: GLOBALS data.cc 1data.o
338 data.cc: GLOBALS data.cc 2data.o
324339
325340 Msg(std::ostream&)
326341 Full name: Msg::Msg(std::ostream&)
327342 Source: msg2.cc
328343 Used By:
329 data.cc: GLOBALS data.cc 1data.o
344 data.cc: GLOBALS data.cc 2data.o
345
346 newLog()
347 Full name: LogUnit::newLog()
348 Source: newlog.cc
349 Used By:
350 setuplogs.cc: LogUnit::setupLogs()
351
352 newSyslogStream()
353 Full name: LogUnit::newSyslogStream()
354 Source: newsyslogstream.cc
355 Used By:
356 setuplogs.cc: LogUnit::setupLogs()
330357
331358 nextCommand(std::ostream&, std::string const&)
332359 Full name: IntegrityScanner::nextCommand(std::ostream&, std::string const&)
336363 doplaincommand.cc: IntegrityScanner::doPlainCommand(FBB::Process&)
337364 get.cc: IntegrityScanner::get(std::string const&)
338365
366 nextJob()
367 Full name: Stealth::nextJob()
368 Source: nextjob.cc
369 Used By:
370 jobshandler.cc: Stealth::jobsHandler()
371
339372 noDifferences(std::string const&, std::string const&)
340373 Full name: IntegrityScanner::noDifferences(std::string const&, std::string const&)
341374 Source: nodifferences.cc
342375 Used By:
343376 sameoutput.cc: IntegrityScanner::sameOutput(std::string const&, FBB::Process&)
344377
345 notify()
346 Full name: Wait11::notify()
347 Source: notify.cc
348 Used By:
349 signalhandler.cc: Stealth::signalHandler(unsigned int)
378 notifyTask()
379 Full name: Stealth::notifyTask()
380 Source: notifytask.cc
381 Used By:
382 ipcinterface.cc: Stealth::ipcInterface()
350383
351384 oldOptions() const
352385 Full name: Options::oldOptions() const
354387 Used By:
355388 options1.cc: Options::Options()
356389
357 open(std::string const&)
358 Full name: StealthLog::open(std::string const&)
359 Source: open.cc
360 Used By:
361 policydepdatamembers.cc: Stealth::policyDepDataMembers()
362 reload.cc: Stealth::reload()
363
364390 Options()
365391 Full name: Options::Options()
366392 Source: options1.cc
367393 Used By:
368 instance.cc: Options::instance()
394 stealth1.cc: Stealth::Stealth()
369395
370396 parentProcess()
371397 Full name: Stealth::parentProcess()
373399 Used By:
374400 destructor.cc: Stealth::~Stealth()
375401
376 policyDepDataMembers()
377 Full name: Stealth::policyDepDataMembers()
378 Source: policydepdatamembers.cc
379 Used By:
380 dochores.cc: Stealth::doChores()
381
382 PolicyFile(std::string const&)
383 Full name: PolicyFile::PolicyFile(std::string const&)
402 PolicyFile(Options&)
403 Full name: PolicyFile::PolicyFile(Options&)
384404 Source: policyfile1.cc
385405 Used By:
386 policydepdatamembers.cc: Stealth::policyDepDataMembers()
387
388 process(StealthEnums::Mode)
389 Full name: Stealth::process(StealthEnums::Mode)
390 Source: process.cc
391 Used By:
392 processrequests.cc: Stealth::processRequests()
406 reload.cc: Stealth::reload()
407 setuniqueptrs.cc: Stealth::setUniquePtrs()
393408
394409 processMail()
395 Full name: Stealth::processMail()
410 Full name: Report::processMail()
396411 Source: processmail.cc
397412 Used By:
398 maillogs.cc: Stealth::mailLogs()
399
400 processRequests()
401 Full name: Stealth::processRequests()
402 Source: processrequests.cc
403 Used By:
404 dochores.cc: Stealth::doChores()
413 destructor.cc: Report::~Report()
414 mail.cc: Report::mail()
405415
406416 put(std::string const&)
407417 Full name: IntegrityScanner::put(std::string const&)
419429 Full name: Options::randomAddition() const
420430 Source: randomaddition.cc
421431 Used By:
422 timedwait.cc: IPC::timedWait()
432 nextjob.cc: Stealth::nextJob()
423433
424434 read(FBB::Process&, std::string const&)
425435 Full name: IntegrityScanner::read(FBB::Process&, std::string const&)
427437 Used By:
428438 get.cc: IntegrityScanner::get(std::string const&)
429439
430 readDaemonPid()
431 Full name: IPC::readDaemonPid()
432 Source: readdaemonpid.cc
433 Used By:
434 signaldaemon.cc: IPC::signalDaemon()
435
436440 realPath(std::string const&)
437441 Full name: Util::realPath(std::string const&)
438442 Source: realpath.cc
439443 Used By:
440 loadpolicyoptions.cc: Options::loadPolicyOptions()
444 abspath.cc: Util::absPath(std::string const&, std::string&)
441445
442446 refresh()
443 Full name: StealthLog::refresh()
447 Full name: Report::refresh()
444448 Source: refresh.cc
445449 Used By:
446 processrequests.cc: Stealth::processRequests()
447 suspend.cc: Stealth::suspend()
448
449 reload()
450 Full name: PolicyFile::reload()
451 Source: reload.cc
452 Used By:
453 reload.cc: Stealth::reload()
454 policyfile1.cc: PolicyFile::PolicyFile(std::string const&)
450 processmail.cc: Report::processMail()
451 report1.cc: Report::Report(Options&, PolicyFile const&)
455452
456453 reload()
457454 Full name: Stealth::reload()
498495 Used By:
499496 fetchcommands.cc: PolicyFile::fetchCommands()
500497
501 request()
502 Full name: IPC::request()
503 Source: request.cc
504 Used By:
505 signalhandler.cc: Stealth::signalHandler(unsigned int)
498 Report(Options&, PolicyFile const&)
499 Full name: Report::Report(Options&, PolicyFile const&)
500 Source: report1.cc
501 Used By:
502 reload.cc: Stealth::reload()
503 setuniqueptrs.cc: Stealth::setUniquePtrs()
506504
507505 requireSomeArgument()
508506 Full name: Options::requireSomeArgument()
510508 Used By:
511509 options1.cc: Options::Options()
512510
511 rerun()
512 Full name: Stealth::rerun()
513 Source: rerun.cc
514 Used By:
515 data.cc: GLOBALS data.cc 11data.o
516
513517 rerunRequest()
514518 Full name: Stealth::rerunRequest()
515519 Source: rerunrequest.cc
529533 data.cc: GLOBALS data.cc 11data.o
530534
531535 rewind()
532 Full name: StealthLog::rewind()
536 Full name: Report::rewind()
533537 Source: rewind.cc
534538 Used By:
535 processmail.cc: Stealth::processMail()
536 sendmail.cc: Stealth::sendMail()
539 processmail.cc: Report::processMail()
540 sendmail.cc: Report::sendMail()
537541
538542 rfc2822() const
539543 Full name: Options::rfc2822() const
540544 Source: rfc2822.cc
541545 Used By:
542 logmsg.cc: Stealth::logMsg(char const*)
546 rerun.cc: Stealth::rerun()
543547 resume.cc: Stealth::resume()
544 open.cc: StealthLog::open(std::string const&)
545 scanheader.cc: StealthLog::scanHeader()
548 report1.cc: Report::Report(Options&, PolicyFile const&)
549 scanheader.cc: Report::scanHeader()
550 timestamp.cc: Report::timestamp(char const*, unsigned int)
546551
547552 run()
548553 Full name: IntegrityScanner::run()
557562 directivesandcommands.cc: PolicyFile::directivesAndCommands()
558563
559564 s_configFileBase
560 Full name: Options::s_configFileBase
561 Source: data.cc
562 Used By:
563 loadpolicyoptions.cc: Options::loadPolicyOptions()
565 Full name: PolicyFile::s_configFileBase
566 Source: data.cc
567 Used By:
568 loadoptions.cc: PolicyFile::loadOptions(FBB::ConfigFile&, unsigned int)
564569
565570 s_defaultKeyword
566571 Full name: PolicyFile::s_defaultKeyword
567572 Source: data.cc
568573 Used By:
569 reload.cc: PolicyFile::reload()
574 load.cc: PolicyFile::load()
570575
571576 s_defaultSyslogFacility
572577 Full name: Options::s_defaultSyslogFacility
573578 Source: data.cc
574579 Used By:
575 syslogfacility.cc: Options::syslogFacility() const
580 setsyslogfacility.cc: Options::setSyslogFacility()
576581
577582 s_defaultSyslogIdent
578583 Full name: Options::s_defaultSyslogIdent
579584 Source: data.cc
580585 Used By:
581 syslogtag.cc: Options::syslogTag() const
586 setsyslog.cc: Options::setSyslog()
582587 usage.cc: Options::usage(std::string const&)
583588
584589 s_defaultSyslogPriority
585590 Full name: Options::s_defaultSyslogPriority
586591 Source: data.cc
587592 Used By:
588 syslogpriority.cc: Options::syslogPriority() const
593 setsyslogpriority.cc: Options::setSyslogPriority()
589594
590595 s_defaultVerbosity
591596 Full name: Options::s_defaultVerbosity
592597 Source: data.cc
593598 Used By:
594 setverbosity.cc: Options::setVerbosity(bool, std::string const&)
599 setverbosity.cc: Options::setVerbosity()
595600
596601 s_define
597602 Full name: PolicyFile::s_define
604609 Source: data.cc
605610 Used By:
606611 testexitvalue.cc: IntegrityScanner::testExitValue(std::string const&, std::string const&)
612
613 s_firstWord
614 Full name: PolicyFile::s_firstWord
615 Source: data.cc
616 Used By:
617 directivesandcommands.cc: PolicyFile::directivesAndCommands()
618 insert.cc: PolicyFile::insert(FBB::LinearMap<std::string, std::string, std::allocator<std::pair<std::string const, std::string> > >&, std::string const&)
607619
608620 s_firstWord
609621 Full name: IntegrityScanner::s_firstWord
619631 removefirstword.cc: IntegrityScanner::removeFirstWord(char const*)
620632 removelog.cc: IntegrityScanner::removeLOG()
621633
622 s_firstWord
623 Full name: PolicyFile::s_firstWord
624 Source: data.cc
625 Used By:
626 directivesandcommands.cc: PolicyFile::directivesAndCommands()
627 insert.cc: PolicyFile::insert(FBB::LinearMap<std::string, std::string, std::allocator<std::pair<std::string const, std::string> > >&, std::string const&)
634 s_log
635 Full name: PolicyFile::s_log
636 Source: data.cc
637 Used By:
638 fixrelativelocations.cc: PolicyFile::fixRelativeLocations()
628639
629640 s_modeName
630641 Full name: RunMode::s_modeName
631642 Source: data.cc
632643 Used By:
633644 deniedmode.cc: Stealth::deniedMode(char const*)
634 processrequests.cc: Stealth::processRequests()
645 jobshandler.cc: Stealth::jobsHandler()
635646 run.cc: IntegrityScanner::run()
636
637 s_modeName
638 Full name: Options::s_modeName
639 Source: data.cc
640 Used By:
641 signaldaemon.cc: IPC::signalDaemon()
642647
643648 s_nDefaultKeywords
644649 Full name: PolicyFile::s_nDefaultKeywords
645650 Source: data.cc
646651 Used By:
647 reload.cc: PolicyFile::reload()
648
649 s_options
650 Full name: Options::s_options
651 Source: data.cc
652 Used By:
653 instance.cc: Options::instance()
654
655 s_request
656 Full name: IPC::s_request
657 Source: data.cc
658 Used By:
659 request.cc: IPC::request()
652 load.cc: PolicyFile::load()
660653
661654 s_request
662655 Full name: Stealth::s_request
663656 Source: data.cc
664657 Used By:
665 signalhandler.cc: Stealth::signalHandler(unsigned int)
658 incomingrequest.cc: Stealth::incomingRequest(std::istream&, std::ostream&)
666659
667660 s_syslogFacilities
668661 Full name: Options::s_syslogFacilities
669662 Source: data.cc
670663 Used By:
671 syslogfacility.cc: Options::syslogFacility() const
664 setsyslogfacility.cc: Options::setSyslogFacility()
672665
673666 s_syslogPriorities
674667 Full name: Options::s_syslogPriorities
675668 Source: data.cc
676669 Used By:
677 syslogpriority.cc: Options::syslogPriority() const
670 setsyslogpriority.cc: Options::setSyslogPriority()
678671
679672 s_task
680673 Full name: Stealth::s_task
681674 Source: data.cc
682675 Used By:
683 process.cc: Stealth::process(StealthEnums::Mode)
676 jobshandler.cc: Stealth::jobsHandler()
684677
685678 sameOutput(std::string const&, FBB::Process&)
686679 Full name: IntegrityScanner::sameOutput(std::string const&, FBB::Process&)
689682 docheckcommand.cc: IntegrityScanner::doCHECKcommand(FBB::Process&)
690683
691684 scanHeader()
692 Full name: StealthLog::scanHeader()
685 Full name: Report::scanHeader()
693686 Source: scanheader.cc
694687 Used By:
695688 integrityscan.cc: Stealth::integrityScan()
696689
697690 sendMail()
698 Full name: Stealth::sendMail()
691 Full name: Report::sendMail()
699692 Source: sendmail.cc
700693 Used By:
701 processmail.cc: Stealth::processMail()
702
703 sendRequest(char const*, int)
704 Full name: IPC::sendRequest(char const*, int)
705 Source: sendrequest.cc
706 Used By:
707 signaldaemon.cc: IPC::signalDaemon()
708
709 sendRequestor(std::string const&)
710 Full name: IPC::sendRequestor(std::string const&)
711 Source: sendrequestor.cc
712 Used By:
713 acceptmode.cc: Stealth::acceptMode(StealthEnums::Mode)
714 deniedmode.cc: Stealth::deniedMode(char const*)
694 processmail.cc: Report::processMail()
715695
716696 setCommandNr()
717697 Full name: Options::setCommandNr()
719699 Used By:
720700 options1.cc: Options::Options()
721701
702 setConfigOptions()
703 Full name: Options::setConfigOptions()
704 Source: setconfigoptions.cc
705 Used By:
706 options1.cc: Options::Options()
707 loadoptions.cc: PolicyFile::loadOptions(FBB::ConfigFile&, unsigned int)
708
722709 setDownloadSize()
723710 Full name: Options::setDownloadSize()
724711 Source: setdownloadsize.cc
725712 Used By:
726 options1.cc: Options::Options()
713 setconfigoptions.cc: Options::setConfigOptions()
727714
728715 setLog()
729716 Full name: Options::setLog()
730717 Source: setlog.cc
731718 Used By:
732719 options1.cc: Options::Options()
720 setconfigoptions.cc: Options::setConfigOptions()
733721
734722 setMail()
735723 Full name: Options::setMail()
736724 Source: setmail.cc
737725 Used By:
738 options1.cc: Options::Options()
726 setconfigoptions.cc: Options::setConfigOptions()
739727
740728 setMode()
741729 Full name: Options::setMode()
748736 Source: setmode.cc
749737 Used By:
750738 acceptmode.cc: Stealth::acceptMode(StealthEnums::Mode)
751 integrityscan.cc: Stealth::integrityScan()
752 reload.cc: Stealth::reload()
753 resume.cc: Stealth::resume()
739 autoscan.cc: Stealth::autoScan(char const*)
740 incomingrequest.cc: Stealth::incomingRequest(std::istream&, std::ostream&)
741 ipcinterface.cc: Stealth::ipcInterface()
742 nextjob.cc: Stealth::nextJob()
743 notifytask.cc: Stealth::notifyTask()
754744 stealth1.cc: Stealth::Stealth()
755 terminate.cc: Stealth::terminate()
756 waitforrequest.cc: Stealth::waitForRequest()
757 read.cc: IntegrityScanner::read(FBB::Process&, std::string const&)
745 waitforkey.cc: Stealth::waitForKey()
758746
759747 setParsePolicy()
760748 Full name: Options::setParsePolicy()
762750 Used By:
763751 options1.cc: Options::Options()
764752
753 setPolicyPath()
754 Full name: Options::setPolicyPath()
755 Source: setpolicypath.cc
756 Used By:
757 options1.cc: Options::Options()
758
765759 setRandomDelay()
766760 Full name: Options::setRandomDelay()
767761 Source: setrandomdelay.cc
768762 Used By:
769 options1.cc: Options::Options()
763 setconfigoptions.cc: Options::setConfigOptions()
770764
771765 setRepeat()
772766 Full name: Options::setRepeat()
773767 Source: setrepeat.cc
774768 Used By:
775 options1.cc: Options::Options()
769 setconfigoptions.cc: Options::setConfigOptions()
776770
777771 setSentinel()
778772 Full name: IntegrityScanner::setSentinel()
779773 Source: setsentinel.cc
780774 Used By:
781 integrityscanner1.cc: IntegrityScanner::IntegrityScanner(RunMode&, PolicyFile&, std::ostream&)
775 integrityscanner1.cc: IntegrityScanner::IntegrityScanner(RunMode const&, Options&, PolicyFile&, std::ostream&)
782776 run.cc: IntegrityScanner::run()
783777
784778 setSkip()
787781 Used By:
788782 loadskipfiles.cc: IntegrityScanner::loadSkipFiles()
789783
790 setSkipFilePath()
791 Full name: Options::setSkipFilePath()
792 Source: setskipfilepath.cc
793 Used By:
794 options1.cc: Options::Options()
784 setSkipFile()
785 Full name: Options::setSkipFile()
786 Source: setskipfile.cc
787 Used By:
788 options1.cc: Options::Options()
789 setconfigoptions.cc: Options::setConfigOptions()
795790
796791 setStdout()
797792 Full name: Options::setStdout()
798793 Source: setstdout.cc
799794 Used By:
800 options1.cc: Options::Options()
795 setconfigoptions.cc: Options::setConfigOptions()
801796
802797 setSyslog()
803798 Full name: Options::setSyslog()
804799 Source: setsyslog.cc
805800 Used By:
806 options1.cc: Options::Options()
801 setconfigoptions.cc: Options::setConfigOptions()
802
803 setSyslogFacility()
804 Full name: Options::setSyslogFacility()
805 Source: setsyslogfacility.cc
806 Used By:
807 setsyslog.cc: Options::setSyslog()
808
809 setSyslogPriority()
810 Full name: Options::setSyslogPriority()
811 Source: setsyslogpriority.cc
812 Used By:
813 setsyslog.cc: Options::setSyslog()
807814
808815 setTimestamp()
809816 Full name: Options::setTimestamp()
810817 Source: settimestamp.cc
811818 Used By:
812 options1.cc: Options::Options()
813
814 setVerbosity(bool, std::string const&)
815 Full name: Options::setVerbosity(bool, std::string const&)
819 setconfigoptions.cc: Options::setConfigOptions()
820
821 setUniquePtrs()
822 Full name: Stealth::setUniquePtrs()
823 Source: setuniqueptrs.cc
824 Used By:
825 policymode.cc: Stealth::policyMode()
826
827 setupFatalReport()
828 Full name: Stealth::setupFatalReport()
829 Source: setupfatalreport.cc
830 Used By:
831 reload.cc: Stealth::reload()
832 setuniqueptrs.cc: Stealth::setUniquePtrs()
833
834 setupLogs()
835 Full name: LogUnit::setupLogs()
836 Source: setuplogs.cc
837 Used By:
838 setuplogs2.cc: LogUnit::setupLogs(std::ostream&)
839 policymode.cc: Stealth::policyMode()
840
841 setupLogs(std::ostream&)
842 Full name: LogUnit::setupLogs(std::ostream&)
843 Source: setuplogs2.cc
844 Used By:
845 reload.cc: Stealth::reload()
846 setuniqueptrs.cc: Stealth::setUniquePtrs()
847
848 setVerbosity()
849 Full name: Options::setVerbosity()
816850 Source: setverbosity.cc
817851 Used By:
818 options1.cc: Options::Options()
852 setconfigoptions.cc: Options::setConfigOptions()
819853
820854 setVerbosity(unsigned int)
821855 Full name: Msg::setVerbosity(unsigned int)
822856 Source: setverbosity.cc
823857 Used By:
824 setverbosity.cc: Options::setVerbosity(bool, std::string const&)
825
826 signalDaemon()
827 Full name: IPC::signalDaemon()
828 Source: signaldaemon.cc
829 Used By:
830 contactpeer.cc: Stealth::contactPeer()
831
832 signalHandler(unsigned int)
833 Full name: Stealth::signalHandler(unsigned int)
834 Source: signalhandler.cc
835 Used By:
836 destructor.cc: Stealth::~Stealth()
858 setverbosity.cc: Options::setVerbosity()
837859
838860 skip(std::string&)
839861 Full name: IntegrityScanner::skip(std::string&)
851873 Full name: IntegrityScanner::startCommandShells()
852874 Source: startcommandshells.cc
853875 Used By:
854 dochores.cc: Stealth::doChores()
876 dotasks.cc: Stealth::doTasks()
855877 reload.cc: Stealth::reload()
856878
857879 suspend()
866888 Used By:
867889 data.cc: GLOBALS data.cc 11data.o
868890
869 syslogFacility() const
870 Full name: Options::syslogFacility() const
871 Source: syslogfacility.cc
872 Used By:
873 setsyslog.cc: Options::setSyslog()
874
875 syslogPriority() const
876 Full name: Options::syslogPriority() const
877 Source: syslogpriority.cc
878 Used By:
879 setsyslog.cc: Options::setSyslog()
880
881 syslogTag() const
882 Full name: Options::syslogTag() const
883 Source: syslogtag.cc
884 Used By:
885 setsyslog.cc: Options::setSyslog()
891 sync()
892 Full name: LogReportbuf::sync()
893 Source: sync.cc
894 Used By:
895 overflow.cc: LogReportbuf::overflow(int)
886896
887897 terminate()
888898 Full name: Stealth::terminate()
889899 Source: terminate.cc
890900 Used By:
891901 data.cc: GLOBALS data.cc 11data.o
892 process.cc: Stealth::process(StealthEnums::Mode)
893902
894903 terminateRequest()
895904 Full name: Stealth::terminateRequest()
905914 read.cc: IntegrityScanner::read(FBB::Process&, std::string const&)
906915 waitforsentinel.cc: IntegrityScanner::waitForSentinel(FBB::Process&)
907916
908 timedWait()
909 Full name: IPC::timedWait()
910 Source: timedwait.cc
911 Used By:
912 waitforrequest.cc: Stealth::waitForRequest()
917 timestamp(char const*, unsigned int)
918 Full name: Report::timestamp(char const*, unsigned int)
919 Source: timestamp.cc
920 Used By:
921 reload.cc: Stealth::reload()
922 suspend.cc: Stealth::suspend()
923 terminate.cc: Stealth::terminate()
913924
914925 unknownRequest()
915926 Full name: Stealth::unknownRequest()
929940 Used By:
930941 oldoptions.cc: Options::oldOptions() const
931942 usage.cc: Options::usage(std::string const&)
932 open.cc: StealthLog::open(std::string const&)
933
934 wait(bool)
935 Full name: IPC::wait(bool)
936 Source: wait.cc
937 Used By:
938 suspend.cc: Stealth::suspend()
939
940 waitFor(unsigned int, bool)
941 Full name: Wait11::waitFor(unsigned int, bool)
942 Source: waitfor.cc
943 Used By:
944 timedwait.cc: IPC::timedWait()
945 contactpeer.cc: Stealth::contactPeer()
946
947 waitForRequest()
948 Full name: Stealth::waitForRequest()
949 Source: waitforrequest.cc
950 Used By:
951 processrequests.cc: Stealth::processRequests()
943 report1.cc: Report::Report(Options&, PolicyFile const&)
944
945 waitForKey()
946 Full name: Stealth::waitForKey()
947 Source: waitforkey.cc
948 Used By:
949 jobshandler.cc: Stealth::jobsHandler()
952950
953951 waitForSentinel(FBB::Process&)
954952 Full name: IntegrityScanner::waitForSentinel(FBB::Process&)
958956 put.cc: IntegrityScanner::put(std::string const&)
959957 startcommandshells.cc: IntegrityScanner::startCommandShells()
960958
961 waitSignal(bool)
962 Full name: Wait11::waitSignal(bool)
963 Source: waitsignal.cc
964 Used By:
965 timedwait.cc: IPC::timedWait()
966 wait.cc: IPC::wait(bool)
967
968959 write(std::string const&)
969960 Full name: IntegrityScanner::write(std::string const&)
970961 Source: write.cc
971962 Used By:
972963 put.cc: IntegrityScanner::put(std::string const&)
973964
974 write(std::string const&) const
975 Full name: IPC::write(std::string const&) const
976 Source: write.cc
977 Used By:
978 sendrequestor.cc: IPC::sendRequestor(std::string const&)
979 signaldaemon.cc: IPC::signalDaemon()
980
981 writeRunFile(int)
982 Full name: IPC::writeRunFile(int)
983 Source: writerunfile.cc
984 Used By:
985 parentprocess.cc: Stealth::parentProcess()
986
987965 years
988966 Full name: Icmbuild::years
989967 Source: version.cc
0 #define LIBRARY "stealthenums"
1
2 #include "../icmconf2"
+0
-7
stealthenums/leave.cc less more
0 #include "stealthenums.ih"
1
2 ostream &StealthEnums::leave(ostream &out)
3 {
4 out << endl;
5 throw LEAVE;
6 }
66 {
77 enum Mode // uses bit-flags values
88 {
9 LEAVE = 1 << 0,
10
119 INTEGRITY_SCAN = 1 << 1, // perform an integrity scan
12
13 WAIT = 1 << 3, // waiting for another signal/tine
1410
1511 RERUN = 1 << 4, // rerun on request at WAITING
1612
2016
2117 RELOAD = 1 << 6, // reload the config files
2218
23 TERMINATE = 1 << 7, // terminate a Stealth run (-> SIGTERM,
24 // SIGINT)
19 TERMINATE = 1 << 7, // terminate a Stealth run
2520
2621 UNKNOWN = 1 << 8,
2722 };
28
29 static std::ostream &leave(std::ostream &out);
3023 };
3124
3225 inline constexpr StealthEnums::Mode operator|(
3730 );
3831 }
3932
40
4133 #endif
+0
-50
stealthlog/demo/demo.cc less more
0 /*
1 demo.cc
2
3 g++ demo.cc -L../.. -lstealth | & less
4 */
5
6 #include "demo.h"
7
8 int main(int argc, char **argv, char **envp)
9 {
10 try
11 {
12 Reporter rep("report");
13
14 rep << Util::date << ": Hello world\n";
15
16 rep.reset();
17
18 string s;
19
20 cout << "========= 0 ===========\n";
21
22 while (getline(rep, s))
23 cout << "Added: " << s << "\n";
24
25 cout << "========= 1 ===========\n";
26
27 sleep(5);
28
29 rep.reinit(); // make sure we can add new info
30 // as a new run
31
32 // insert info
33 rep << Util::date << ": Hello world (2nd time)\n";
34
35 rep.reset(); // reset the stream to read it again
36
37 while (getline(rep, s))
38 cout << "Added: " << s << "\n";
39
40 cout << "========= 2 ===========\n";
41
42 return 0;
43 }
44 catch(exception const &e)
45 {
46 cerr << "Exception " << e.what() << "\n";
47 return 1;
48 }
49 }
+0
-32
stealthlog/demo/demo.h less more
0 // demo.h
1
2 #ifndef _H_demo_
3 #define _H_demo_
4
5 /*
6 $Id$
7
8 $Log$
9 Revision 1.3 2003/11/30 14:21:29 frank
10 Adding facilities to reuse the Reporter: reinit() re-initializes the reporter
11 but note that reset() must still be used. See demo/demo.cc for an example
12
13 Revision 1.2 2003/06/20 18:58:14 frank
14 Changes are recorded in stealth/debian/changelog
15
16 */
17
18 //#include <iosfwd>
19 #include <iostream>
20 //#include <fstream>
21 #include <string>
22 //#include <sstream>
23
24 #include "../reporter.h"
25 #include "../../util/util.h"
26 #include "../../errno/errno.h"
27
28 using namespace FBB;
29 using namespace std;
30
31 #endif
+0
-5
stealthlog/frame less more
0 #include "stealthlog.ih"
1
2 void StealthLog::
3 {
4 }
+0
-7
stealthlog/hasmail.cc less more
0 #include "stealthlog.ih"
1
2 bool StealthLog::hasMail()
3 {
4 return d_stealthlog.seekp(0, ios::end).tellp() > d_beginMail;
5 }
6
+0
-6
stealthlog/headerline.cc less more
0 #include "stealthlog.ih"
1
2 string const &StealthLog::headerLine() const
3 {
4 return d_headerLine;
5 }
+0
-24
stealthlog/open.cc less more
0 #include "stealthlog.ih"
1
2 void StealthLog::open(string const &name)
3 {
4 d_name = name;
5 d_stealthlog.open(name, ios::out | ios::ate | ios::in);
6
7 if (not d_stealthlog)
8 {
9 d_stealthlog.clear();
10 Exception::open(d_stealthlog, name, ios::out | ios::in | ios::trunc);
11 }
12
13 ostringstream headerTxt;
14 headerTxt << "\n"
15 "STEALTH (" << Icmbuild::version << ") started at " <<
16 Options::instance().rfc2822() << '\n';
17
18 d_headerLine = headerTxt.str();
19
20 d_stealthlog << d_headerLine << endl;
21
22 rdbuf(d_stealthlog.rdbuf());
23 }
+0
-17
stealthlog/refresh.cc less more
0 #include "stealthlog.ih"
1
2 void StealthLog::refresh()
3 {
4 d_stealthlog.clear();
5
6 d_startSize = d_stealthlog.seekp(0, ios::end).tellp();
7
8 d_beginMail = d_startSize;
9 }
10
11
12
13
14
15
16
+0
-7
stealthlog/rewind.cc less more
0 #include "stealthlog.ih"
1
2 void StealthLog::rewind()
3 {
4 d_stealthlog.seekg(d_startSize).tellg();
5 }
6
+0
-18
stealthlog/scanheader.cc less more
0 #include "stealthlog.ih"
1
2 void StealthLog::scanHeader()
3 {
4 d_startSize = d_stealthlog.seekp(0, ios::end).tellp();
5
6 *this << "STEALTH integrity scan at " <<
7 Options::instance().rfc2822() << endl;
8
9 d_beginMail = d_stealthlog.tellp();
10 }
11
12
13
14
15
16
17
+0
-48
stealthlog/stealthlog.h less more
0 #ifndef STEALTHLOG_H_
1 #define STEALTHLOG_H_
2
3 #include <string>
4 #include <fstream>
5
6 class StealthLog: public std::ostream
7 {
8 std::ios::pos_type d_startSize = 0;
9 std::ios::pos_type d_beginMail = 0;
10
11 std::fstream d_stealthlog;
12 std::string d_name;
13 std::string d_headerLine;
14
15 public:
16 StealthLog() = default;
17
18 StealthLog(StealthLog const &other) = delete;
19 StealthLog &operator=(StealthLog const &other) = delete;
20
21 void refresh(); // set d_beginMail to the log's EOF pos.
22 void scanHeader(); // writes the integrity scan header,
23 // initializes d_beginMail
24
25 std::string const &headerLine() const; // returns info about the
26 // starting date/time of this stealth run
27
28 std::istream &in();
29 bool hasMail(); // true if there is info beyond d_beginMail
30
31 void open(std::string const &name);
32 void close();
33
34 void rewind(); // prepare for reading
35 };
36
37 inline std::istream &StealthLog::in()
38 {
39 return d_stealthlog;
40 }
41
42 inline void StealthLog::close()
43 {
44 d_stealthlog.close();
45 }
46
47 #endif
+0
-17
stealthlog/stealthlog.ih less more
0 #include "stealthlog.h"
1
2 #include <iostream>
3 #include <sstream>
4
5 #include <bobcat/exception>
6 #include <bobcat/mstream>
7
8 #include "../options/options.h"
9
10 namespace Icmbuild
11 {
12 extern char const version[];
13 }
14
15 using namespace FBB;
16 using namespace std;
+0
-6
stealthlog/sync.cc less more
0 //#include "stealthlog.ih"
1 //
2 //int StealthLog::sync()
3 //{
4 // return MultiStreambuf::pSync();
5 //}
0 #ifndef INCLUDED_SYSLOGSTRUCT_
1 #define INCLUDED_SYSLOGSTRUCT_
2
3 #include <string>
4 #include <bobcat/syslogstream>
5
6 struct SyslogStruct
7 {
8 bool requested;
9 FBB::Priority priority;
10 FBB::Facility facility;
11 std::string tag;
12
13 SyslogStruct();
14 };
15
16 inline SyslogStruct::SyslogStruct()
17 :
18 requested(false)
19 {}
20
21 #endif
0 #include "util.ih"
1
2 void Util::absPath(string const &base, string &fileName)
3 {
4 if (fileName.front() != '/')
5 fileName = realPath(base + fileName);
6 }
0 #define LIBRARY "util"
1
2 #include "../icmconf2"
+0
-13
util/makeabspath.cc less more
0 //#include "util.ih"
1 //
2 //string Util::makeAbsPath(string const &path)
3 //{
4 // string ret;
5 //
6 // if (path[0] == '/')
7 // ret = path;
8 // else
9 // ret = Stat(".").path() + '/' + path;
10 //
11 // return ret;
12 //}
11
22 string Util::realPath(string const &path)
33 {
4 char *cp = ::realpath(path.c_str(), 0);
5 string ret = cp;
6 free(cp);
4 String::Type type;
5 vector<string> component = String::split(&type, path, "/");
6
7 if (type != String::NORMAL)
8 throw Exception() << "Filename `" << path << "': not supported";
9
10 component.resize(
11 remove(component.begin(), component.end(), ".")
12 -
13 component.begin()
14 );
15
16 while (true)
17 {
18 size_t from = find(component.begin(), component.end(), "..")
19 - component.begin();
20
21 if (from == component.size()) // at the last entry: done
22 break;
23
24 size_t to = find_if(component.begin() + from + 1, component.end(),
25 [&](string const &element)
26 {
27 return element != "..";
28 }
29 ) - component.begin();
30
31
32 size_t count = to - from; // # ".." entries
33
34 size_t firstErase = from >= count ? // first to erase
35 from - count
36 :
37 0;
38
39 component.erase(component.begin() + firstErase,
40 component.begin() + to);
41 }
42
43 string ret(1, '/');
44
45 for(auto &str: component)
46 ret += str + '/';
47
48 ret.pop_back();
49
750 return ret;
851 }
88 static bool mkdir(std::string const &path); // pathname to a file
99 // find full path name
1010 static std::string realPath(std::string const &path);
11 static void absPath(std::string const &path, std::string &fileName);
1112 };
1213
1314 #endif
00 #include "util.h"
11
2 #include <ostream>
32 #include <string>
4 #include <climits>
5 #include <cstdlib>
3 #include <algorithm>
4
5 // ::mkdir
66 #include <libgen.h>
7 #include <sys/stat.h>
78
8 #include <sys/stat.h>
9 #include <sys/types.h>
9 #include <bobcat/string>
10 #include <bobcat/exception>
1011
1112 using namespace std;
13 using namespace FBB;
+0
-5
wait11/frame less more
0 #include "wait11.ih"
1
2 Wait11::
3 {
4 }
+0
-8
wait11/notify.cc less more
0 #include "wait11.ih"
1
2 void Wait11::notify()
3 {
4 lock_guard<mutex> lock(d_mutex);
5 d_signaled = true;
6 d_condition.notify_one();
7 }
+0
-29
wait11/wait11.h less more
0 #ifndef INCLUDED_WAIT11_
1 #define INCLUDED_WAIT11_
2
3 #include <mutex>
4 #include <condition_variable>
5
6 class Wait11
7 {
8 bool d_signaled = false;
9 std::mutex d_mutex;
10 std::condition_variable d_condition;
11
12 public:
13 void waitSignal(bool doM2 = true); // wait for a signal to arrive
14 void waitFor(size_t seconds, bool doM2 = true);
15
16 void notify();
17
18 bool signaled() const;
19
20 private:
21 };
22
23 inline bool Wait11::signaled() const
24 {
25 return d_signaled;
26 }
27
28 #endif
+0
-6
wait11/wait11.ih less more
0 #include "wait11.h"
1
2 #include "../msg/msg.h"
3
4 using namespace std;
5
+0
-26
wait11/waitfor.cc less more
0 #include "wait11.ih"
1
2 void Wait11::waitFor(size_t seconds, bool doM2)
3 {
4 d_signaled = false;
5
6 while (true)
7 {
8 unique_lock<mutex> lock(d_mutex); // get the lock
9
10 if (d_condition.wait_for(lock, chrono::seconds(seconds)) ==
11 std::cv_status::timeout)
12 {
13 if (doM2)
14 m2 << "timeout after " << seconds << " seconds" << endl;
15 return;
16 }
17
18 if (d_signaled)
19 {
20 if (doM2)
21 m2 << "received signal: done waiting" << endl;
22 return;
23 }
24 }
25 }
+0
-14
wait11/waitsignal.cc less more
0 #include "wait11.ih"
1
2 void Wait11::waitSignal(bool doM2)
3 {
4 unique_lock<mutex> lock(d_mutex); // get the lock
5
6 d_signaled = false;
7
8 if (doM2)
9 m2 << "waiting..." << endl;
10
11 while (not d_signaled)
12 d_condition.wait(lock);
13 }