[1] | 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
|
---|
[161] | 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.
|
---|
[1] | 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
|
---|
[161] | 685 | start with a character different from '/'). To retrieve data, you can use
|
---|
[1] | 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>
|
---|