1 | <html>
|
---|
2 | <head>
|
---|
3 | <title>HOWTO Write Samhain Modules</title>
|
---|
4 | <style type="text/css">
|
---|
5 | <!--
|
---|
6 |
|
---|
7 | html { background: #eee; color: #000; }
|
---|
8 |
|
---|
9 | body { background: #eee; color: #000; margin: 0; padding: 0;}
|
---|
10 |
|
---|
11 | div.body {
|
---|
12 | background: #fff; color: #000;
|
---|
13 | margin: 0 1em 0 1em; padding: 1em;
|
---|
14 | font-family: serif;
|
---|
15 | font-size: 1em; line-height: 1.2em;
|
---|
16 | border-width: 0 1px 0 1px;
|
---|
17 | border-style: solid;
|
---|
18 | border-color: #aaa;
|
---|
19 | }
|
---|
20 |
|
---|
21 | div.block {
|
---|
22 | background: #b6c5f2; color: #000;
|
---|
23 | margin: 1em; padding: 0 1em 0 1em;
|
---|
24 | border-width: 1px;
|
---|
25 | border-style: solid;
|
---|
26 | border-color: #2d4488;
|
---|
27 | }
|
---|
28 |
|
---|
29 | div.warnblock {
|
---|
30 | background: #b6c5f2; color: #000;
|
---|
31 | margin: 1em; padding: 0 1em 0 1em;
|
---|
32 | border-width: 1px;
|
---|
33 | border-style: solid;
|
---|
34 | border-color: #FF9900;
|
---|
35 | }
|
---|
36 |
|
---|
37 | table {
|
---|
38 | background: #F8F8F8; color: #000;
|
---|
39 | margin: 1em;
|
---|
40 | border-width: 0 0 0 1px;
|
---|
41 | border-style: solid;
|
---|
42 | border-color: #C0C0C0;
|
---|
43 | }
|
---|
44 |
|
---|
45 | td {
|
---|
46 | border-width: 0 1px 1px 0;
|
---|
47 | border-style: solid;
|
---|
48 | border-color: #C0C0C0;
|
---|
49 | }
|
---|
50 |
|
---|
51 | th {
|
---|
52 | background: #F8F8FF;
|
---|
53 | border-width: 1px 1px 2px 0;
|
---|
54 | border-style: solid;
|
---|
55 | border-color: #C0C0C0;
|
---|
56 | }
|
---|
57 |
|
---|
58 |
|
---|
59 | /* body text, headings, and rules */
|
---|
60 |
|
---|
61 | p { margin: 0; text-indent: 0em; margin: 0 0 0.5em 0 }
|
---|
62 |
|
---|
63 | h1, h2, h3, h4, h5, h6 {
|
---|
64 | color: #206020; background: transparent;
|
---|
65 | font-family: Optima, Arial, Helvetica, sans-serif;
|
---|
66 | font-weight: normal;
|
---|
67 | }
|
---|
68 |
|
---|
69 | h1 { font-size: 1.69em; margin: 1.4em 0 0.4em 0; }
|
---|
70 | h2 { font-size: 1.44em; margin: 1.4em 0 0.4em 0; }
|
---|
71 | h3 { font-size: 1.21em; margin: 1.4em 0 0.4em 0; }
|
---|
72 | h4 { font-size: 1.00em; margin: 1.4em 0 0.4em 0; }
|
---|
73 | h5 { font-size: 0.81em; margin: 1.4em 0 0.4em 0; }
|
---|
74 | h6 { font-size: 0.64em; margin: 1.4em 0 0.4em 0; }
|
---|
75 |
|
---|
76 | hr {
|
---|
77 | color: transparent; background: transparent;
|
---|
78 | height: 0px; margin: 0.6em 0;
|
---|
79 | border-width: 1px ;
|
---|
80 | border-style: solid;
|
---|
81 | border-color: #999;
|
---|
82 | }
|
---|
83 |
|
---|
84 | /* bulleted lists and definition lists */
|
---|
85 |
|
---|
86 | ul { margin: 0 1em 0.6em 2em; padding: 0; }
|
---|
87 | li { margin: 0.4em 0 0 0; }
|
---|
88 |
|
---|
89 | dl { margin: 0.6em 1em 0.6em 2em; }
|
---|
90 | dt { color: #285577; }
|
---|
91 |
|
---|
92 | tt { color: #602020; }
|
---|
93 |
|
---|
94 | /* links */
|
---|
95 |
|
---|
96 | a.link {
|
---|
97 | color: #33c; background: transparent;
|
---|
98 | text-decoration: none;
|
---|
99 | }
|
---|
100 |
|
---|
101 | a:hover {
|
---|
102 | color: #000; background: transparent;
|
---|
103 | }
|
---|
104 |
|
---|
105 | body > a {
|
---|
106 | font-family: Optima, Arial, Helvetica, sans-serif;
|
---|
107 | font-size: 0.81em;
|
---|
108 | }
|
---|
109 |
|
---|
110 | h1, h2, h3, h4, h5, h6 {
|
---|
111 | color: #2d5588; background: transparent;
|
---|
112 | font-family: Optima, Arial, Helvetica, sans-serif;
|
---|
113 | font-weight: normal;
|
---|
114 | }
|
---|
115 |
|
---|
116 | -->
|
---|
117 | </style></head>
|
---|
118 |
|
---|
119 | <body>
|
---|
120 | <div class="body">
|
---|
121 | <p style="text-align: center; background: #ccc; border: 1px solid #2d5588;"><a
|
---|
122 | style="text-decoration: none;"
|
---|
123 | href="http://www.la-samhna.de/samhain/">samhain file integrity
|
---|
124 | scanner</a> | <a style="text-decoration: none;"
|
---|
125 | href="http://www.la-samhna.de/samhain/s_documentation.html">online
|
---|
126 | documentation</a></p>
|
---|
127 | <br><center>
|
---|
128 | <h1>Writing modules for samhain</h1>
|
---|
129 | </center>
|
---|
130 | <br>
|
---|
131 | <hr>
|
---|
132 | <p>
|
---|
133 | This document should help anyone who is sitting down to write a module
|
---|
134 | for the samhain host intrusion detection system. We give an overview
|
---|
135 | of samhain's structure from the point of view of the module author,
|
---|
136 | and describe some of the samhain utility and interface functions
|
---|
137 | available. Lastly, we explain how to integrate your module into the
|
---|
138 | samhain autoconf build tools.
|
---|
139 | </p>
|
---|
140 | <h2>Introduction</h2>
|
---|
141 | <p>
|
---|
142 | Samhain is a rather useful file integrity and host intrusion detection
|
---|
143 | system. It is written entirely in C, and much care has been given to
|
---|
144 | making it robust and secure. Additionally, it has been written with
|
---|
145 | extensibility in mind, and so interfaces for adding user-contributed
|
---|
146 | modules have been provided. A module author can easily extend the
|
---|
147 | configuration file syntax and have his checking code run on a regular
|
---|
148 | basis as one of samhain's internal checks.
|
---|
149 | </p>
|
---|
150 |
|
---|
151 | <h2>Prerequisites</h2>
|
---|
152 | <p>
|
---|
153 | You'll need to know how to read and write C. You'll need the latest
|
---|
154 | source for samhain. You'll need to have read all of samhain's other
|
---|
155 | documentation. Finally, if you want to make your module build as part
|
---|
156 | of the samhain tree (you do), you'll need GNU's autoconf package.
|
---|
157 | </p>
|
---|
158 | <h2>An overview of samhain's execution</h2>
|
---|
159 | <p>
|
---|
160 | Here's what happens when samhain starts:
|
---|
161 | <ul>
|
---|
162 | <li>
|
---|
163 | Check if samhain has been called with one of the "init.d" type
|
---|
164 | commands - start, stop, reload, status. If so, these are handled
|
---|
165 | as you might expect. Nice feature.
|
---|
166 | </li>
|
---|
167 | <li>
|
---|
168 | Initialise all global structures and parse command-line options.
|
---|
169 | </li>
|
---|
170 | <li>
|
---|
171 | Read the configuration file. This is handled in sh_readconf_read().
|
---|
172 | This includes attempting to download the file if samhain has been
|
---|
173 | compiled to do so.
|
---|
174 | </li>
|
---|
175 | <li>
|
---|
176 | Drop privileges if server.
|
---|
177 | </li>
|
---|
178 | <li>
|
---|
179 | Test the checksum on the database if client or standalone.
|
---|
180 | </li>
|
---|
181 | <li>
|
---|
182 | Now test if samhain has been compiled as a client or a server.
|
---|
183 | <ul>
|
---|
184 | <li>
|
---|
185 | If server, enter server main loop sh_receive() in
|
---|
186 | sh_forward.c. This is simple enough; apart from checks for
|
---|
187 | signals received, the server just accepts incoming
|
---|
188 | connections, verifies that they are from an authorised
|
---|
189 | client, and logs the message received.
|
---|
190 | </li>
|
---|
191 | <li>
|
---|
192 | If client or standalone, we run the rest of main() in
|
---|
193 | samhain.c, which follows:
|
---|
194 | </li>
|
---|
195 | </ul>
|
---|
196 | </li>
|
---|
197 | <li>
|
---|
198 | Initialise modules - that is, call the mod_init() function on each
|
---|
199 | module. Note that if the module intialisation routine returns a
|
---|
200 | nonzero value, you should also have it free anything that's been
|
---|
201 | allocated by the configuration file reading functions, since this
|
---|
202 | method is always called after an sh_readconf_read(), i.e. when the
|
---|
203 | configuration file is re-read after a SIGHUP.
|
---|
204 | </li>
|
---|
205 | <li>
|
---|
206 | Test the setup that's been read from the configuration - for example,
|
---|
207 | check if any files or directories have been defined twice.
|
---|
208 | </li>
|
---|
209 | <li>
|
---|
210 | Enter the main loop (which runs just once if samhain is not
|
---|
211 | configured as a daemon). Test if any signals have been received,
|
---|
212 | and handle them appropriately:
|
---|
213 | <ul>
|
---|
214 | <li>
|
---|
215 | On reconfiguration (SIGHUP), clear internal file lists etc.
|
---|
216 | and call the mod_reconf() function on each module. This should
|
---|
217 | clean up anything internal to the module before the
|
---|
218 | configuration file is re-read. Then read the configuration
|
---|
219 | file again and set things up as before, including a new call
|
---|
220 | to mod_init().
|
---|
221 | </li>
|
---|
222 | <li>
|
---|
223 | On SIGIOT (SIGABRT), shut down the log-file for a moment
|
---|
224 | to allow for rotation.
|
---|
225 | </li>
|
---|
226 | <li>
|
---|
227 | On SIGQUIT, terminate. Note that any call to exit() will
|
---|
228 | invoke the exit_handler() defined in samhain.c; the first
|
---|
229 | thing this does is to call mod_cleanup() on all modules.
|
---|
230 | Then it cleans up everything else in samhain and exits.
|
---|
231 | </li>
|
---|
232 | <li>
|
---|
233 | On SIGUSR1 turn toggle debugging on/off.
|
---|
234 | </li>
|
---|
235 | <li>
|
---|
236 | On SIGUSR2 suspend the daemon an notify the server to
|
---|
237 | allow a second instance of samhain downloading its
|
---|
238 | configuration file without triggering an alert (restart
|
---|
239 | without exit) on the server.
|
---|
240 | </li>
|
---|
241 | </ul>
|
---|
242 | </li>
|
---|
243 | <li>
|
---|
244 | If it's time to check files, check directories and then files, and
|
---|
245 | then flush the mail queue.
|
---|
246 | </li>
|
---|
247 | <li>
|
---|
248 | Execute modules. For each module, if mod_timer(tcurrent) returns a
|
---|
249 | nonzero value, then execute mod_check().
|
---|
250 | </li>
|
---|
251 | <li>
|
---|
252 | Do various maintenance operations such as logging a timestamp/sending
|
---|
253 | some mail if it's time, seeding/re-seeding the PRNG, etc.
|
---|
254 | </li>
|
---|
255 | </ul>
|
---|
256 | You'll note that in the text above I refer to a couple of module
|
---|
257 | functions - mod_init(), mod_check(), etc. These are function pointers
|
---|
258 | that act as hooks for attaching modules to samhain. Next we'll
|
---|
259 | describe how they are used.
|
---|
260 | </p>
|
---|
261 |
|
---|
262 | <h2>Samhain's module interface</h2>
|
---|
263 | <p>
|
---|
264 | Here we'll describe the interface samhain provides to module authors.
|
---|
265 | </p>
|
---|
266 |
|
---|
267 | <h3>The module list</h3>
|
---|
268 | <p>
|
---|
269 | In sh_modules.h, the following structure is defined:
|
---|
270 | </p>
|
---|
271 | <pre>
|
---|
272 |
|
---|
273 | typedef struct mod_type
|
---|
274 | {
|
---|
275 | /* The name of the module */
|
---|
276 | char * name;
|
---|
277 |
|
---|
278 | /* Set by samhain to 1 on successful initialization, else 0 */
|
---|
279 | int initval;
|
---|
280 |
|
---|
281 | /* The initialization function. Return 0 on success. */
|
---|
282 | int (* mod_init) (void);
|
---|
283 |
|
---|
284 | /* The timer function. Return 0 if NOT time to check. */
|
---|
285 | int (* mod_timer) (unsigned long tcurrent);
|
---|
286 |
|
---|
287 | /* The check function. Return 0 on success. */
|
---|
288 | int (* mod_check) (void);
|
---|
289 |
|
---|
290 | /* The cleanup function. Return 0 on success. */
|
---|
291 | int (* mod_cleanup) (void);
|
---|
292 |
|
---|
293 | /* The preparation for reconfiguration. Return 0 on success. */
|
---|
294 | int (* mod_reconf) (void);
|
---|
295 |
|
---|
296 | /* Section header in config file */
|
---|
297 | char * conf_section;
|
---|
298 |
|
---|
299 | /* A table of key/handler_function for config file entries */
|
---|
300 | sh_rconf * conf_table;
|
---|
301 |
|
---|
302 | } sh_mtype;
|
---|
303 | </pre>
|
---|
304 |
|
---|
305 | <p>
|
---|
306 | This is the structure used to hook modules into samhain. There is a
|
---|
307 | list of these structures (modList), defined in sh_modules.c,
|
---|
308 | containing pointers to the functions to be used for each module
|
---|
309 | compiled into samhain. For example,
|
---|
310 | </p>
|
---|
311 |
|
---|
312 | <pre>
|
---|
313 |
|
---|
314 | sh_mtype modList[] = {
|
---|
315 | #ifdef SH_USE_UTMP
|
---|
316 | {
|
---|
317 | N_("UTMP"),
|
---|
318 | 0,
|
---|
319 | sh_utmp_init,
|
---|
320 | sh_utmp_timer,
|
---|
321 | sh_utmp_check,
|
---|
322 | sh_utmp_end,
|
---|
323 | sh_utmp_null,
|
---|
324 |
|
---|
325 | N_("[Utmp]"),
|
---|
326 | sh_utmp_table,
|
---|
327 | },
|
---|
328 | #endif
|
---|
329 | </pre>
|
---|
330 | <p>
|
---|
331 | is the beginning of that table. The author of the sh_utmp module has
|
---|
332 | initialised the structure with the name of the module (note that N_()
|
---|
333 | is just a macro used to delimit strings here), a 0 to signify that the
|
---|
334 | module has not yet been initialised, and then pointers to _init(),
|
---|
335 | _timer(), _check(), _cleanup() and _reconf() functions for the
|
---|
336 | module. Finally, the last two structure elements are for configuration
|
---|
337 | file parsing: the first is the section heading in the configuration
|
---|
338 | file for this module, and the second is a table of type
|
---|
339 | </p>
|
---|
340 |
|
---|
341 | <pre>
|
---|
342 |
|
---|
343 | typedef struct rconf
|
---|
344 | {
|
---|
345 | char * the_opt;
|
---|
346 | int (*func)(char * opt);
|
---|
347 | } sh_rconf;
|
---|
348 | </pre>
|
---|
349 |
|
---|
350 | <p>
|
---|
351 | (also defined in sh_modules.h). This structure is for storing options
|
---|
352 | for this module to be found in the configuration file, as well as the
|
---|
353 | functions that will be used to parse them when found. In the sh_utmp
|
---|
354 | example above, we can see that this table has been set to
|
---|
355 | sh_utmp_table - this is a reference to a list of the Utmp module's
|
---|
356 | configuration options declared in sh_utmp.h. It should be clear now
|
---|
357 | that one of the changes you will need to make to samhain's source
|
---|
358 | files is to include your header file in sh_modules.c and add a modList
|
---|
359 | entry like the above.
|
---|
360 | </p>
|
---|
361 |
|
---|
362 | <p>
|
---|
363 | For a description of when during samhain's execution these various
|
---|
364 | module hooks are called, see the overview above. It would likely be
|
---|
365 | helpful to you now to read through the source for one of the modules
|
---|
366 | provided with samhain and see the above actually implemented. You
|
---|
367 | should also be able to use one of these modules as a template for your
|
---|
368 | own.
|
---|
369 | </p>
|
---|
370 |
|
---|
371 | <h3>The message catalogue</h3>
|
---|
372 |
|
---|
373 | <p>
|
---|
374 | Most module authors will want to log messages in their own specified
|
---|
375 | format; samhain stores all of its message formats in a "messages
|
---|
376 | catalogue" found in sh_cat.h and sh_cat.c. For example, for the
|
---|
377 | sh_suidchk module we find the following entries in sh_cat.h, as part
|
---|
378 | of an enum:
|
---|
379 | </p>
|
---|
380 |
|
---|
381 | <pre>
|
---|
382 |
|
---|
383 | #ifdef SH_USE_SUIDCHK
|
---|
384 | MSG_SUID_POLICY,
|
---|
385 | MSG_SUID_FOUND,
|
---|
386 | MSG_SUID_STAT,
|
---|
387 | MSG_SUID_SUMMARY,
|
---|
388 | #endif
|
---|
389 | </pre>
|
---|
390 |
|
---|
391 | <p>
|
---|
392 | Correspondingly in sh_cat.c we find
|
---|
393 | </p>
|
---|
394 |
|
---|
395 | <pre>
|
---|
396 |
|
---|
397 | #ifdef SH_USE_SUIDCHK
|
---|
398 | { MSG_SUID_POLICY, SH_ERR_SEVERE, RUN, N_("msg=\"POLICY SUIDCHK %s\" path=\"%s\"") },
|
---|
399 | { MSG_SUID_FOUND, SH_ERR_INFO, RUN, N_("msg=\"Found suid/sgid file\" path=\"%s\"") },
|
---|
400 | { MSG_SUID_STAT, SH_ERR_ERR, ERR, N_("msg=\"stat: %s\" path=\"%s\"") },
|
---|
401 | { MSG_SUID_SUMMARY,SH_ERR_INFO, RUN, N_("msg=\"Checked for SUID programs: %ld files, %ld seconds\"") },
|
---|
402 | #endif
|
---|
403 | </pre>
|
---|
404 | <p>
|
---|
405 | as part of the table msg_cat[] of type cat_entry:
|
---|
406 | </p>
|
---|
407 | <pre>
|
---|
408 |
|
---|
409 | typedef struct foo_cat_entry {
|
---|
410 | unsigned long id;
|
---|
411 | unsigned long priority;
|
---|
412 | unsigned long class;
|
---|
413 | char * format;
|
---|
414 | } cat_entry;
|
---|
415 | </pre>
|
---|
416 | <p>
|
---|
417 | The first member of this structure is the message type's ID, as
|
---|
418 | defined in the enum in sh_cat.h. The second is the default priority of
|
---|
419 | such messages, defined as in the samhain documentation. The third is
|
---|
420 | the class of the message, again defined as in the samhain
|
---|
421 | documentation. Finally we have the message format itself, which is a
|
---|
422 | printf() style format string.
|
---|
423 | </p>
|
---|
424 | <p>
|
---|
425 | This catalogue is used by the logging functions in samhain; you will
|
---|
426 | need to add your own message types and formats to sh_cat.h and
|
---|
427 | sh_cat.c. Note that because samhain can be compiled for XML style
|
---|
428 | logging, you will actually need to make two entries in sh_cat.c for
|
---|
429 | each message; see the file itself for details.
|
---|
430 | </p>
|
---|
431 | <p>
|
---|
432 | Note that there is a generic message format with the ID 'MSG_E_SUBGEN'
|
---|
433 | and the default priority 'SH_ERR_ERR'. If you are using this message
|
---|
434 | format, then you can log (a) a string, and (b) the name of the subroutine.
|
---|
435 | </p>
|
---|
436 | <p>
|
---|
437 | This completes our description of samhain's module interface.
|
---|
438 | </p>
|
---|
439 |
|
---|
440 | <h2>Samhain's utility functions</h2>
|
---|
441 | <p>
|
---|
442 | Here we'll describe the main utility functions available to samhain module
|
---|
443 | authors.
|
---|
444 | </p>
|
---|
445 |
|
---|
446 | <h3>String wrapping macros</h3>
|
---|
447 |
|
---|
448 | <p>
|
---|
449 | Constant strings should be wrapped in the _(string) macro. Initialisation
|
---|
450 | strings that cannot be replaced with a function should be wrapped
|
---|
451 | in a N_(string) macro, and the variable thus initialized should be
|
---|
452 | wrapped in a _(var) macro whereever used. This is important for the
|
---|
453 | 'stealth' functionality of samhain.
|
---|
454 | </p>
|
---|
455 |
|
---|
456 | <h3>Logging messages</h3>
|
---|
457 |
|
---|
458 | <pre>
|
---|
459 | #include "sh_error.h"
|
---|
460 |
|
---|
461 | void sh_error_handle(int severity, char * file, long line, long status,
|
---|
462 | unsigned long msg_id, ...)
|
---|
463 | </pre>
|
---|
464 | <p>
|
---|
465 | This is samhain's logging/reporting function, so the name is a little
|
---|
466 | misleading - errors are not the only thing we should handle with
|
---|
467 | this. The first four arguments are simple enough: severity is the
|
---|
468 | logging severity, defined in the enum ShErrLevel from sh_error.h; file
|
---|
469 | and line are the current file and line - usually you'll be using FIL__
|
---|
470 | and __LINE__ for these; status is not very important - for module
|
---|
471 | authors it'll do to always pass 0 to this. The final named argument is
|
---|
472 | msg_id, which should be one of the message IDs defined in sh_cat.h;
|
---|
473 | these correspond to message format strings in printf() format, which
|
---|
474 | will be interpolated with the following arguments to form the log
|
---|
475 | message.
|
---|
476 | </p>
|
---|
477 | <p>
|
---|
478 | The '__LINE__' macro is provided by the C preprocessor. The FIL__ macro
|
---|
479 | should be #defined to '_("sourcefile_name")' (see 'String wrapping macros'
|
---|
480 | above).
|
---|
481 | <p>
|
---|
482 | Example of use:
|
---|
483 | </p>
|
---|
484 | <pre>
|
---|
485 | #undef
|
---|
486 | #define FIL__ _("sh_mounts.c")
|
---|
487 |
|
---|
488 | sh_error_handle(ShMountsSevMnt, FIL__, __LINE__, 0, MSG_MNT_MNTMISS,
|
---|
489 | cfgmnt->path);
|
---|
490 | </pre>
|
---|
491 | <p>
|
---|
492 | See cat.c for the definition of MSG_MNT_MNTMISS:
|
---|
493 | </p>
|
---|
494 | <pre>
|
---|
495 |
|
---|
496 | { MSG_MNT_MNTMISS, SH_ERR_WARN, RUN, N_("msg=\"Mount missing\" path=\"%s\"")},
|
---|
497 | </pre>
|
---|
498 | <p>
|
---|
499 | So we print this out at severity ShMountsSevMnt, which in this case is
|
---|
500 | a configured value read from the samhain configuration file (see
|
---|
501 | sh_mounts.c). If we wanted to print it at the default severity
|
---|
502 | (SH_ERR_WARN), we could pass -1 as the severity.
|
---|
503 | </p>
|
---|
504 |
|
---|
505 | <h3>Checking files for modification</h3>
|
---|
506 |
|
---|
507 | <pre>
|
---|
508 | #include "sh_files.h"
|
---|
509 |
|
---|
510 | int sh_files_pushdir_?? (char * dirName);
|
---|
511 | int sh_files_pushfile_?? (char * fileName);
|
---|
512 | </pre>
|
---|
513 | <p>
|
---|
514 | These functions push directories and files onto the stack of those to check
|
---|
515 | for the specified policy (see the samhain documentation for further
|
---|
516 | information):
|
---|
517 | <table>
|
---|
518 | <tr><td> sh_files_pushdir_user0 </td><td>pushes the directory at USER0 </td></tr>
|
---|
519 | <tr><td align=right> ... _user1</td><td align=right>USER1</td></tr>
|
---|
520 | <tr><td align=right> ... _attr</td><td align=right>ATTR</td></tr>
|
---|
521 | <tr><td align=right> ... _ro</td><td align=right>READONLY</td></tr>
|
---|
522 | <tr><td align=right> ... _log</td><td align=right>LOGFILE</td></tr>
|
---|
523 | <tr><td align=right> ... _glog</td><td align=right>GROWING LOGFILE</td></tr>
|
---|
524 | <tr><td align=right> ... _noig</td><td align=right>IGNORE NONE</td></tr>
|
---|
525 | <tr><td align=right> ... _allig</td><td align=right>IGNORE ALL</td></tr>
|
---|
526 | </table>
|
---|
527 | So if you're writing a module that adds particular files to check, like the
|
---|
528 | sh_userfiles module for example, these are the functions to use.
|
---|
529 | </p>
|
---|
530 |
|
---|
531 | <h3>Managing memory</h3>
|
---|
532 |
|
---|
533 | <pre>
|
---|
534 | #include "sh_mem.h"
|
---|
535 |
|
---|
536 | #define SH_FREE(a) ...
|
---|
537 | #define SH_ALLOC(a) ...
|
---|
538 | </pre>
|
---|
539 | <p>
|
---|
540 | These are the macros to use when you're allocating/freeing memory in
|
---|
541 | samhain. They do all the error checking/reporting you need, so when
|
---|
542 | you get memory from SH_ALLOC you can just get to using it right away.
|
---|
543 | </p>
|
---|
544 |
|
---|
545 | <h3>Parsing strings</h3>
|
---|
546 |
|
---|
547 | <pre>
|
---|
548 | #include "sh_utils.h"
|
---|
549 |
|
---|
550 | char * sh_util_strdup (const char * str);
|
---|
551 | char * sh_util_strsep (char **str, const char *delim);
|
---|
552 | char * sh_util_strconcat (const char * arg1, ...);
|
---|
553 |
|
---|
554 | int sh_util_flagval(char * c, int * fval);
|
---|
555 | int sh_util_isnum (char *str);
|
---|
556 |
|
---|
557 | #include "slib.h"
|
---|
558 |
|
---|
559 | int sl_strlcpy (char * dst, const char * src, size_t siz);
|
---|
560 | int sl_strlcat (char * dst, const char * src, size_t siz);
|
---|
561 | int sl_snprintf(char *str, size_t n, const char *format, ... );
|
---|
562 | </pre>
|
---|
563 | <p>
|
---|
564 | These functions are the samhain internal functions for string
|
---|
565 | handling. The first three act like their C library counterparts,
|
---|
566 | except using samhain's memory management functions and error
|
---|
567 | checking. sh_util_flagval converts the passed string into a truth
|
---|
568 | value - the value is stored in <b>fval</b> as 1 or 0 - and returns 0
|
---|
569 | on success, -1 on failure. sh_util_isnum just checks if the passed
|
---|
570 | string is all numeric.
|
---|
571 | </p>
|
---|
572 | <p>
|
---|
573 | The functions sl_strlcpy and sl_strlcat work similar to the C library
|
---|
574 | strncpy/strncat functions, except that the destination string is always
|
---|
575 | null terminated, and the third argument must be the full length of the
|
---|
576 | destination buffer, <i>not</i> the remaining space. On success, the
|
---|
577 | return value is 0.
|
---|
578 | </p>
|
---|
579 | <p>
|
---|
580 | The function sl_snprintf provides either the system snprintf, or a replacement,
|
---|
581 | if the system has no or a buggy snprintf.
|
---|
582 | </p>
|
---|
583 |
|
---|
584 | <h3>Tracing execution</h3>
|
---|
585 |
|
---|
586 | <pre>
|
---|
587 | #include "slib.h"
|
---|
588 |
|
---|
589 | #define SL_ENTER(s) ...
|
---|
590 | #define SL_RETURN(retval, s) ...
|
---|
591 | </pre>
|
---|
592 | <p>
|
---|
593 | These macros are for tracing execution through samhain functions. You
|
---|
594 | should use SL_ENTER with the name of the function for each function
|
---|
595 | entered, and SL_RETURN with the return value and the name of the
|
---|
596 | function for each exit if you want to maintain compatibility with the
|
---|
597 | rest of samhain.
|
---|
598 | </p>
|
---|
599 |
|
---|
600 | <h3>Executing external programs (popen)</h3>
|
---|
601 |
|
---|
602 | <pre>
|
---|
603 | #include "sh_extern.h"
|
---|
604 |
|
---|
605 |
|
---|
606 | sh_tas_t task;
|
---|
607 | /* Prepare task */
|
---|
608 | sh_ext_tas_init(&task);
|
---|
609 | sh_ext_tas_command(&task, char * command);
|
---|
610 | sh_ext_tas_add_argv(&task, char * val);
|
---|
611 | sh_ext_tas_add_envv (&task, char * environment_variable, char * value);
|
---|
612 |
|
---|
613 | int sh_ext_popen(&task);
|
---|
614 | int sh_ext_pclose(&task);
|
---|
615 | </pre>
|
---|
616 | <p>
|
---|
617 | To prepare a task to run, use 'sh_ext_tas_init' to initialise the task
|
---|
618 | structure. With 'sh_ext_tas_command' the command (absolute path) is set,
|
---|
619 | with 'sh_ext_tas_add_argv' command line options are added. Environment
|
---|
620 | variables can be set with 'sh_ext_tas_add_envv'.
|
---|
621 | </p>
|
---|
622 | <p>
|
---|
623 | To open for read, set "task.rw = 'r';", to open for write
|
---|
624 | use "task.rw = 'w';".
|
---|
625 | </p>
|
---|
626 | <p>
|
---|
627 | To run the task with privileges dropped to another UID, set
|
---|
628 | "task.privileged = 0;" and task.run_user_uid, task.run_user_gid
|
---|
629 | to the desired UID/GID.
|
---|
630 | </p>
|
---|
631 | <p>
|
---|
632 | To verify the checksum of the called executable, set
|
---|
633 | task.checksum[KEY_LEN+1] to the TIGER192 checksum of the executable.
|
---|
634 | </p>
|
---|
635 | <p>
|
---|
636 | After successful execution of sh_ext_popen (return status 0),
|
---|
637 | task.pipe is the stream opened for read or write, and task.pipeFD
|
---|
638 | its associated file descriptor.
|
---|
639 | </p>
|
---|
640 |
|
---|
641 | <h3>Inserting arbitrary data into the baseline database</h3>
|
---|
642 | <pre>
|
---|
643 |
|
---|
644 | #include "sh_hash.c"
|
---|
645 |
|
---|
646 | void sh_hash_push2db (char * key, unsigned long val1,
|
---|
647 | unsigned long val2, unsigned long val3,
|
---|
648 | unsigned char * str, int size);
|
---|
649 |
|
---|
650 | char * sh_hash_db2pop (char * key, unsigned long * val1,
|
---|
651 | unsigned long * val2, unsigned long * val3,
|
---|
652 | int * size);
|
---|
653 | </pre>
|
---|
654 | <p>
|
---|
655 | The baseline database has a fixed record format. To enter data, these need
|
---|
656 | to be prepared in the required format. To retrieve the data, the
|
---|
657 | 'filepath' is used as key (if your data is not a file, you would provide
|
---|
658 | a dummy pathname as key). For convenience, the two functions noted below
|
---|
659 | are provided.
|
---|
660 | </p>
|
---|
661 | <p>
|
---|
662 | When checking files, samhain will walk the database to find files that
|
---|
663 | are in the database, but have been deleted from the disk. If you enter
|
---|
664 | data, you need to mark it as such by using a key that
|
---|
665 | starts with something else but '/', otherwise samhain will complain
|
---|
666 | if it has not been checked during the file check.
|
---|
667 | </p>
|
---|
668 | <pre>
|
---|
669 |
|
---|
670 | #include "sh_hash.c"
|
---|
671 |
|
---|
672 | void sh_hash_push2db (char * key, unsigned long val1,
|
---|
673 | unsigned long val2, unsigned long val3,
|
---|
674 | unsigned char * str, int size);
|
---|
675 |
|
---|
676 | char * sh_hash_db2pop (char * key, unsigned long * val1,
|
---|
677 | unsigned long * val2, unsigned long * val3,
|
---|
678 | int * size);
|
---|
679 | </pre>
|
---|
680 | <p>
|
---|
681 | To insert data, use 'sh_hash_push2db'. You can insert up to three long
|
---|
682 | integers (val1, val2, val3) and/or a binary string of length size
|
---|
683 | (max. (PATH_MAX-1)/2). As noted
|
---|
684 | above, you need to supply a key (stored as the 'filepath', which should
|
---|
685 | start with a character different from '/'). To retrieve data, you can use
|
---|
686 | 'sh_hash_db2pop'. The return value is either NULL (if no string was
|
---|
687 | stored under this key), or the stored string (length returned in 'size').
|
---|
688 | </p>
|
---|
689 | <p>
|
---|
690 | A string to store may consist of any characters, including NULLs, and
|
---|
691 | need not be NULL terminated. The returned string is
|
---|
692 | always NULL terminated (the terminating NULL is not included in 'size'),
|
---|
693 | and should be freed with SH_FREE() if not required anymore.
|
---|
694 | </p>
|
---|
695 | <p>
|
---|
696 | If the key is not found in the database, <b>size</b> is set to -1.
|
---|
697 | </p>
|
---|
698 |
|
---|
699 | <h2>Incorporating modules into the samhain build</h2>
|
---|
700 | <p>
|
---|
701 | This is a somewhat secondary but important part of writing a module
|
---|
702 | for samhain:
|
---|
703 | how to incorporate it into the samhain configuration and build process.
|
---|
704 | This just involves hacking the autoconf and makefile setup to include your
|
---|
705 | module. We'll present this file-by-file.
|
---|
706 | </p>
|
---|
707 | <h3>Makefile.in</h3>
|
---|
708 | <p>
|
---|
709 | You need to add a few bits to this file. First, add your header,
|
---|
710 | source and object filenames to the HEADERS, SOURCES and OBJECTS
|
---|
711 | variables. Then add your header to the dependencies for sh_modules.o
|
---|
712 | and ./sh_modules.o. Finally add dependency lines for your module
|
---|
713 | object file sh_whatever.o and ./sh_whatever.o, modelling them on the
|
---|
714 | other module object dependency lines.
|
---|
715 | </p>
|
---|
716 | <h3>acconfig.h</h3>
|
---|
717 | <p>
|
---|
718 | The config.h.in will be generated from this file by 'autoheader'.
|
---|
719 | You just need to add a line like
|
---|
720 | <pre>
|
---|
721 | #undef SH_USE_MOUNTS
|
---|
722 | </pre>
|
---|
723 | that will be defined by the ./configure code if the user specifies
|
---|
724 | the module as enabled.
|
---|
725 | </p>
|
---|
726 | <h3>aclocal.m4</h3>
|
---|
727 | <p>
|
---|
728 | This file is used by 'autoconf' to help generate ./configure. You need to add
|
---|
729 | your module's ./configure option to the SH_ENABLE_OPTS variable; for example,
|
---|
730 | to add the option --enable-mounts-check, we added the string 'mounts-check' to
|
---|
731 | this variable.
|
---|
732 | </p>
|
---|
733 | <h3>configure.ac</h3>
|
---|
734 | This is the other file used by 'autoconf' to generate ./configure. You need to
|
---|
735 | add an AC_ARG_ENABLE call to this file, along the lines of those for other
|
---|
736 | modules. For example, we added
|
---|
737 | <pre>
|
---|
738 | AC_ARG_ENABLE(mounts-check,
|
---|
739 | [ --enable-mounts-check check mount options on filesystems [[no]
|
---|
740 | ]],
|
---|
741 | [
|
---|
742 | if test "x${enable_mounts_check}" = xyes; then
|
---|
743 | AC_DEFINE(SH_USE_MOUNTS)
|
---|
744 | fi
|
---|
745 | ]
|
---|
746 | )
|
---|
747 | </pre>
|
---|
748 | for the sh_mounts module. This causes the #undef from acconfig.h above
|
---|
749 | to be defined when ./configure is run with the --enable-mounts-check argument.
|
---|
750 | </p>
|
---|
751 | This is all that you need. Once you've done the above, you'll need to
|
---|
752 | run 'autoheader' and 'autoconfig' to generate config.h.in and the
|
---|
753 | ./configure script. Then your module will build as part of the samhain
|
---|
754 | source.
|
---|
755 | </p>
|
---|
756 |
|
---|
757 | <h2>Conclusion</h2>
|
---|
758 | <p>
|
---|
759 | Armed with the above information, any proficient C programmer should
|
---|
760 | be able to adapt and extend samhain to do whatever it is they need. We
|
---|
761 | hope that this document has been reasonably clear, easy to follow and
|
---|
762 | useful; please feel free to update it for clarity, accuracy and
|
---|
763 | completeness and resubmit it to the samhain project.
|
---|
764 | </p>
|
---|
765 | <p>
|
---|
766 | This document was written by the eircom.net Computer Incident Response Team.
|
---|
767 | Updated with CSS by Rainer Wichmann.
|
---|
768 | </p>
|
---|
769 | </div>
|
---|
770 | </body>
|
---|
771 | </html>
|
---|