source: branches/samhain-2_2-branch/src/sh_getopt.c

Last change on this file was 42, checked in by rainer, 18 years ago

Bugfix for regression that makes local updates impossible for clients

File size: 17.1 KB
Line 
1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 1999, 2000 Rainer Wichmann */
3/* */
4/* This program is free software; you can redistribute it */
5/* and/or modify */
6/* it under the terms of the GNU General Public License as */
7/* published by */
8/* the Free Software Foundation; either version 2 of the License, or */
9/* (at your option) any later version. */
10/* */
11/* This program is distributed in the hope that it will be useful, */
12/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14/* GNU General Public License for more details. */
15/* */
16/* You should have received a copy of the GNU General Public License */
17/* along with this program; if not, write to the Free Software */
18/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#include "config_xor.h"
21
22#include <stdlib.h>
23#include <stdio.h>
24#include <string.h>
25#include <limits.h>
26#include <errno.h>
27
28
29#include "samhain.h"
30#include "sh_error.h"
31#include "sh_getopt.h"
32#include "sh_files.h"
33#include "sh_utils.h"
34#include "sh_mail.h"
35#include "sh_forward.h"
36#include "sh_hash.h"
37
38#if defined(WITH_EXTERNAL)
39#include "sh_extern.h"
40#endif
41
42extern int sh_calls_set_bind_addr (const char *);
43
44#undef FIL__
45#define FIL__ _("sh_getopt.c")
46
47#define HAS_ARG_NO 0
48#define HAS_ARG_YES 1
49#define DROP_PRIV_NO 0
50#define DROP_PRIV_YES 1
51
52
53typedef struct options {
54 char * longopt;
55 const char shortopt;
56 char * usage;
57 int hasArg;
58 int (*func)(const char * opt);
59} opttable_t;
60
61/*@noreturn@*/
62static int sh_getopt_usage (const char * dummy);
63#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
64static int sh_getopt_forever (const char * dummy);
65#endif
66static int sh_getopt_copyright (const char * dummy);
67
68static opttable_t op_table[] = {
69
70#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
71 { N_("set-checksum-test"),
72 't',
73 N_("Set checksum testing to 'init', 'update', or 'check'"),
74 HAS_ARG_YES,
75 sh_util_setchecksum },
76 { N_("interactive"),
77 'i',
78 N_("Run update in interactive mode"),
79 HAS_ARG_NO,
80 sh_util_set_interactive },
81#endif
82#if defined(SH_WITH_SERVER) || defined(SH_WITH_CLIENT)
83 { N_("server-port"),
84 '-',
85 N_("Set the server port to connect to"),
86 HAS_ARG_YES,
87 sh_forward_server_port },
88#endif
89#ifdef SH_WITH_SERVER
90 { N_("server"),
91 'S',
92 N_("Run as log server (obsolete)"),
93 HAS_ARG_NO,
94 sh_util_setserver },
95 { N_("qualified"),
96 'q',
97 N_("Log fully qualified name of client host"),
98 HAS_ARG_NO,
99 sh_forward_set_strip },
100 { N_("chroot"),
101 '-',
102 N_("Chroot to specified directory"),
103 HAS_ARG_YES,
104 sh_unix_set_chroot },
105#endif
106 { N_("daemon"),
107 'D',
108 N_("Run as daemon"),
109 HAS_ARG_NO,
110 sh_unix_setdeamon },
111 { N_("foreground"),
112 '-',
113 N_("Stay in the foreground"),
114 HAS_ARG_NO,
115 sh_unix_setnodeamon },
116 { N_("bind-address"),
117 '-',
118 N_("Bind to this address (interface) for outgoing connections"),
119 HAS_ARG_YES,
120 sh_calls_set_bind_addr },
121#if defined(SH_WITH_SERVER) || defined(SH_WITH_CLIENT)
122 { N_("set-export-severity"),
123 'e',
124 N_("Set severity threshold for export to remote log server"),
125 HAS_ARG_YES,
126 sh_error_setexport },
127#endif
128 { N_("set-syslog-severity"),
129 's',
130 N_("Set severity threshold for syslog"),
131 HAS_ARG_YES,
132 sh_error_set_syslog },
133#ifdef WITH_EXTERNAL
134 { N_("set-extern-severity"),
135 'x',
136 N_("Set severity threshold for logging by external program(s)"),
137 HAS_ARG_YES,
138 sh_error_set_external },
139#endif
140#ifdef HAVE_LIBPRELUDE
141 { N_("set-prelude-severity"),
142 '-',
143 N_("Set severity threshold for logging to prelude"),
144 HAS_ARG_YES,
145 sh_error_set_prelude },
146#endif
147#if defined(WITH_DATABASE)
148 { N_("set-database-severity"),
149 '-',
150 N_("Set severity threshold for logging to RDBMS"),
151 HAS_ARG_YES,
152 sh_error_set_database },
153#endif
154 { N_("set-log-severity"),
155 'l',
156 N_("Set severity threshold for logfile"),
157 HAS_ARG_YES,
158 sh_error_setlog },
159#if defined(SH_WITH_MAIL)
160 { N_("set-mail-severity"),
161 'm',
162 N_("Set severitythreshold for e-mail"),
163 HAS_ARG_YES,
164 sh_error_setseverity },
165#endif
166 { N_("set-print-severity"),
167 'p',
168 N_("Set the severity threshold for terminal/console log"),
169 HAS_ARG_YES,
170 sh_error_setprint },
171#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
172 { N_("recursion"),
173 'r',
174 N_("Set recursion level for directories"),
175 HAS_ARG_YES,
176 sh_files_setrecursion },
177#endif
178 { N_("verify-log"),
179 'L',
180 N_("Verify the audit trail"),
181 HAS_ARG_YES,
182 sh_error_logverify },
183 { N_("just-list"),
184 'j',
185 N_("Modify -L to just list the audit trail"),
186 HAS_ARG_NO,
187 sh_error_logverify_mod },
188#if defined(SH_WITH_MAIL)
189 { N_("verify-mail"),
190 'M',
191 N_("Verify the mailbox"),
192 HAS_ARG_YES,
193 sh_mail_sigverify
194 },
195#endif
196 { N_("add-key"),
197 'V',
198 N_("Add key for the mail/log signature"),
199 HAS_ARG_YES,
200 sh_util_set_newkey
201 },
202 { N_("hash-string"),
203 'H',
204 N_("Print the hash of a string"),
205 HAS_ARG_YES,
206 sh_error_verify },
207#if defined (SH_WITH_SERVER)
208 { N_("password"),
209 'P',
210 N_("Compute a client registry entry for password"),
211 HAS_ARG_YES,
212 sh_forward_make_client },
213 { N_("gen-password"),
214 'G',
215 N_("Generate a random password"),
216 HAS_ARG_NO,
217 sh_forward_create_password },
218#endif
219
220#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
221 { N_("forever"),
222 'f',
223 N_("Loop forever, even if not daemon"),
224 HAS_ARG_NO,
225 sh_getopt_forever},
226 { N_("full-detail"),
227 'a',
228 N_("Modify -d to list full details"),
229 HAS_ARG_NO,
230 set_full_detail},
231 { N_("delimited"),
232 '-',
233 N_("Modify -d to list full details, comma delimited"),
234 HAS_ARG_NO,
235 set_list_delimited},
236 { N_("list-database"),
237 'd',
238 N_("List database content (like ls -l)"),
239 HAS_ARG_YES,
240 sh_hash_list_db},
241 { N_("init2stdout"),
242 '-',
243 N_("Write database to stdout on init"),
244 HAS_ARG_NO,
245 sh_hash_pushdata_stdout},
246#endif
247 { N_("trace-logfile"),
248 '-',
249 N_("Logfile for trace"),
250 HAS_ARG_YES,
251 sl_trace_file },
252 { N_("trace-enable"),
253 '-',
254 N_("Enable tracing"),
255 HAS_ARG_NO,
256 sl_trace_use },
257 { N_("copyright"),
258 'c',
259 N_("Print copyright information"),
260 HAS_ARG_NO,
261 sh_getopt_copyright },
262 { N_("help"),
263 'h',
264 N_("Print usage information"),
265 HAS_ARG_NO,
266 sh_getopt_usage },
267#if defined(HAVE_LIBPRELUDE) && defined(HAVE_LIBPRELUDE_9)
268 /* need to skip over these */
269 { N_("prelude"),
270 '-',
271 N_("Prelude generic options"),
272 HAS_ARG_NO,
273 NULL },
274 { N_("profile"),
275 '-',
276 N_("Profile to use for this analyzer"),
277 HAS_ARG_YES,
278 NULL },
279 { N_("heartbeat-interval"),
280 '-',
281 N_("Number of seconds between two heartbeats"),
282 HAS_ARG_YES,
283 NULL },
284 { N_("server-addr"),
285 '-',
286 N_("Address where this sensor should report to"),
287 HAS_ARG_YES,
288 NULL },
289 { N_("analyzer-name"),
290 '-',
291 N_("Name for this analyzer"),
292 HAS_ARG_YES,
293 NULL },
294#endif
295 /* last entry -- required !! -- */
296 { NULL,
297 '\0',
298 NULL,
299 HAS_ARG_NO,
300 NULL }
301};
302
303static int sh_getopt_copyright (const char * dummy)
304{
305 fprintf (stdout,
306 _("Copyright (C) 1999-2005 Rainer Wichmann"\
307 " (http://la-samhna.de).\n\n"));
308
309 fprintf (stdout,
310 _("This program is free software; "\
311 "you can redistribute it and/or modify\n"));
312 fprintf (stdout, _("it under the terms of the GNU General "\
313 "Public License as published by\n"));
314 fprintf (stdout, _("the Free Software Foundation; either version 2 "\
315 "of the License, or\n"));
316 fprintf (stdout, _("(at your option) any later version.\n\n"));
317
318 fprintf (stdout, _("This program is distributed in the hope "\
319 "that it will be useful,\n"));
320 fprintf (stdout, _("but WITHOUT ANY WARRANTY; "\
321 "without even the implied warranty of\n"));
322 fprintf (stdout, _("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."\
323 " See the\n"));
324 fprintf (stdout, _("GNU General Public License for more details.\n\n"));
325
326 fprintf (stdout, _("You should have received a copy of the "\
327 "GNU General Public License\n"));
328 fprintf (stdout, _("along with this program; "\
329 "if not, write to the Free Software\n"));
330 fprintf (stdout, _("Foundation, Inc., 59 Temple Place - Suite 330, "\
331 "Boston, MA 02111-1307, USA.\n\n"));
332
333 fprintf (stdout, _("This product makes use of the reference implementation "\
334 "of the TIGER message\n"));
335 fprintf (stdout, _("digest algorithm. This code is copyright Eli Biham "\
336 "(biham@cs.technion.ac.il)\n"));
337 fprintf (stdout, _("and Ross Anderson (rja14@cl.cam.ac.uk). It can be used "\
338 "freely without any\n"));
339 fprintf (stdout, _("restrictions.\n"));
340#if defined(USE_SRP_PROTOCOL) && !defined(SH_STANDALONE)
341#if (!defined(HAVE_LIBGMP) || !defined(HAVE_GMP_H))
342 fprintf (stdout, _("This product makes use of the 'bignum' library by "\
343 "Henrik Johansson\n"));
344 fprintf (stdout, _("(Henrik.Johansson@Nexus.Comm.SE). If you are including "\
345 "this library in a\n"));
346 fprintf (stdout, _("commercial product, be sure to distribute ALL of"\
347 " it with the product.\n"));
348#endif
349 fprintf (stdout, _("This product uses the 'Secure Remote Password' "\
350 "cryptographic\n"));
351 fprintf (stdout, _("authentication system developed by Tom Wu "\
352 "(tjw@CS.Stanford.EDU).\n"));
353#endif
354 fprintf (stdout, _("\nPlease refer to the file COPYING in the source "\
355 "distribution for a"));
356 fprintf (stdout, _("\nfull list of incorporated code and associated "\
357 "licenses.\n"));
358
359 if (dummy)
360 _exit (EXIT_SUCCESS);
361 else
362 _exit (EXIT_SUCCESS);
363 /*@notreached@*/
364 return 0; /* make compilers happy */
365}
366
367/*@noreturn@*/
368static int sh_getopt_usage (const char * dummy)
369{
370 int i;
371 char fmt[64];
372
373 char opts[64];
374
375 for (i = 0; i < 64; ++i) /* splint does not grok char opts[64] = { '\0' }; */
376 opts[i] = '\0';
377
378 fprintf (stdout,
379 _("This is samhain (%s), "\
380 "(c) 1999-2005 Rainer Wichmann (http://la-samhna.de).\n"),
381 VERSION);
382 fprintf (stdout, _("This software comes with ABSOLUTELY NO WARRANTY. "));
383 fprintf (stdout, _("Use at own risk.\n"));
384
385 fprintf (stdout, _("Usage:\n\n"));
386
387 for (i = 0; op_table[i].longopt != NULL; ++i) {
388
389 if (i == 63)
390 break;
391
392 if (op_table[i].shortopt != '-' &&
393 strchr(opts, op_table[i].shortopt) != NULL)
394 fprintf (stdout, _("Short option char collision !\n"));
395 opts[i] = op_table[i].shortopt;
396
397
398 if (op_table[i].hasArg == HAS_ARG_NO) {
399 if (sl_strlen(op_table[i].longopt) < 10)
400 sl_strlcpy(fmt,_("%c%c%c --%-s,\t\t\t %s\n"), sizeof(fmt));
401 else if (sl_strlen(op_table[i].longopt) < 17)
402 sl_strlcpy(fmt, _("%c%c%c --%-s,\t\t %s\n"), sizeof(fmt));
403 else
404 sl_strlcpy(fmt, _("%c%c%c --%-s,\t %s\n"), sizeof(fmt));
405 /* flawfinder: ignore */
406 fprintf (stdout, fmt,
407 (op_table[i].shortopt == '-') ? ' ' : '-',
408 (op_table[i].shortopt == '-') ? ' ' : op_table[i].shortopt,
409 (op_table[i].shortopt == '-') ? ' ' : ',',
410 _(op_table[i].longopt),
411 _(op_table[i].usage));
412 } else {
413 if (sl_strlen(op_table[i].longopt) < 12)
414 sl_strlcpy(fmt, _("%c%c %s --%-s=<arg>,\t\t %s\n"), sizeof(fmt));
415 else
416 sl_strlcpy(fmt, _("%c%c %s --%-s=<arg>,\t %s\n"), sizeof(fmt));
417 /* flawfinder: ignore */
418 fprintf (stdout, fmt,
419 (op_table[i].shortopt == '-') ? ' ' : '-',
420 (op_table[i].shortopt == '-') ? ' ' : op_table[i].shortopt,
421 (op_table[i].shortopt == '-') ? _(" ") : _("<arg>,"),
422 _(op_table[i].longopt),
423 _(op_table[i].usage));
424 }
425 }
426
427 fprintf (stdout,
428 _("\nPlease report bugs to support@la-samhna.de.\n"));
429
430 (void) fflush(stdout);
431
432 if ( dummy != NULL)
433 {
434 if (sl_strcmp( dummy, _("fail")) == 0 )
435 _exit (EXIT_FAILURE);
436 }
437
438 _exit (EXIT_SUCCESS);
439 /*@notreached@*/
440 return 0; /* make compilers happy */
441}
442
443#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
444static int sh_getopt_forever (const char * dummy)
445{
446 dummy = (void *) dummy;
447 SL_ENTER(_("sh_getopt_forever"));
448 sh.flag.loop = S_TRUE;
449 SL_RETURN(0, _("sh_getopt_forever"));
450}
451#endif
452
453int sh_getopt_get (int argc, char * argv[])
454{
455 int count = 0;
456 size_t len = 0;
457 int foundit = 0;
458 int i;
459 size_t k;
460 char * theequal;
461
462 SL_ENTER(_("sh_getopt_get"));
463
464 /* -- Return if no args. --
465 */
466 if (argc < 2)
467 SL_RETURN(0, _("sh_getopt_get"));
468
469 while (argc > 1 && argv[1][0] == '-')
470 {
471
472 /* Initialize
473 */
474 foundit = 0;
475 len = sl_strlen (argv[1]);
476
477 /* a '-' with no argument: error
478 */
479 if (len == 1)
480 (void) sh_getopt_usage(_("fail"));
481
482 /* a '--' with no argument: stop argument processing
483 */
484 if (len == 2 && argv[1][1] == '-')
485 SL_RETURN( count, _("sh_getopt_get"));
486
487 /* a short option: process it
488 */
489 if (len >= 2 && argv[1][1] != '-')
490 {
491 for (k = 1; k < len; ++k)
492 {
493 for (i = 0; op_table[i].shortopt != '\0'; ++i)
494 {
495
496 if ( op_table[i].shortopt == argv[1][k] )
497 {
498 foundit = 1;
499 if ( op_table[i].hasArg == HAS_ARG_YES )
500 {
501 if (k != (len - 1))
502 {
503 /* not last option
504 */
505 fprintf (stderr,
506 _("Error: short option with argument is not last in option string\n"));
507 (void) sh_getopt_usage(_("fail"));
508 }
509 if (argc < 3)
510 {
511 /* argument required, but no avail
512 */
513 fprintf (stderr, _("Error: missing argument\n"));
514 (void) sh_getopt_usage(_("fail"));
515 }
516 else
517 {
518 /* call function with argument */
519 --argc; ++argv;
520 if (NULL != op_table[i].func &&
521 0 != (* op_table[i].func )(argv[1]))
522 fprintf (stderr,
523 _("Error processing option -%c\n"),
524 op_table[i].shortopt);
525 break;
526 }
527 }
528 else
529 {
530 if (NULL != op_table[i].func &&
531 0 != (* op_table[i].func )(NULL))
532 fprintf (stderr,
533 _("Error processing option -%c\n"),
534 op_table[i].shortopt);
535 break;
536 }
537 }
538 }
539 }
540
541 /* 'break' should get here
542 */
543 if (foundit == 1)
544 {
545 --argc; ++argv;
546 continue;
547 }
548 else
549 {
550 /* unrecognized short option */
551 fprintf (stderr, _("Error: unrecognized short option\n"));
552 (void) sh_getopt_usage(_("fail"));
553 }
554 }
555
556 /* a long option: process it
557 */
558 if (len > 2)
559 {
560
561 for (i = 0; op_table[i].longopt != NULL; ++i)
562 {
563
564 if (sl_strncmp(_(op_table[i].longopt),
565 &argv[1][2],
566 sl_strlen(op_table[i].longopt)) == 0 )
567 {
568 foundit = 1;
569 if ( op_table[i].hasArg == HAS_ARG_YES )
570 {
571 theequal = strchr(argv[1], '=');
572 if (theequal == NULL)
573 {
574 if (argc < 3)
575 {
576 /* argument required, but no avail
577 */
578 fprintf (stderr, _("Error: missing argument\n"));
579 (void) sh_getopt_usage(_("fail"));
580 }
581 else
582 {
583 /* call function with argument */
584 --argc; ++argv;
585 if (NULL != op_table[i].func &&
586 0 != (* op_table[i].func )(argv[1]))
587 fprintf (stderr,
588 _("Error processing option -%s\n"),
589 op_table[i].longopt);
590 break;
591 }
592 }
593 else
594 {
595 if (sl_strlen (theequal) > 1)
596 {
597 ++theequal;
598 /* call function with argument */
599 if (NULL != op_table[i].func &&
600 0 != (* op_table[i].func )(theequal))
601 fprintf (stderr,
602 _("Error processing option -%s\n"),
603 op_table[i].longopt);
604 break;
605 }
606 else
607 {
608 fprintf (stderr, _("Error: invalid argument\n"));
609 /* argument required, but no avail */
610 (void) sh_getopt_usage(_("fail"));
611 }
612 }
613 }
614 else
615 {
616 if (NULL != op_table[i].func &&
617 0 != (* op_table[i].func )(NULL))
618 fprintf (stderr,
619 _("Error processing option -%s\n"),
620 op_table[i].longopt);
621 break;
622 }
623 }
624 }
625
626 /* 'break' should get here */
627 if (foundit == 1)
628 {
629 ++count;
630 --argc;
631 ++argv;
632 continue;
633 }
634 else
635 {
636 /* unrecognized long option */
637 fprintf (stderr, _("Error: unrecognized long option\n"));
638 (void) sh_getopt_usage(_("fail"));
639 }
640 }
641 }
642
643 SL_RETURN( count, _("sh_getopt_get"));
644}
Note: See TracBrowser for help on using the repository browser.