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