Imported Upstream version 2.4.3
[platform/upstream/audit.git] / src / ausearch-options.c
1 /* ausearch-options.c - parse commandline options and configure ausearch
2  * Copyright 2005-08,2010-11,2014 Red Hat Inc., Durham, North Carolina.
3  * Copyright (c) 2011 IBM Corp.
4  * All Rights Reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * Authors:
21  *     Debora Velarde <dvelarde@us.ibm.com>
22  *     Steve Grubb <sgrubb@redhat.com>
23  *     Marcelo Henrique Cerri <mhcerri@br.ibm.com>
24  */
25
26 #include "config.h"
27 #include <string.h>
28 #include <ctype.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <errno.h>
32 #include <pwd.h>
33 #include <grp.h>
34 #include "ausearch-options.h"
35 #include "ausearch-time.h"
36 #include "ausearch-int.h"
37 #include "libaudit.h"
38
39
40 /* Global vars that will be accessed by the main program */
41 char *user_file = NULL;
42 int force_logs = 0;
43
44 /* Global vars that will be accessed by the match model */
45 unsigned int event_id = -1;
46 gid_t event_gid = -1, event_egid = -1;
47 ilist *event_type = NULL;
48 pid_t event_pid = -1, event_ppid = -1;
49 success_t event_success = S_UNSET;
50 int event_exact_match = 0;
51 uid_t event_uid = -1, event_euid = -1, event_loginuid = -2;
52 int event_syscall = -1, event_machine = -1;
53 int event_ua = 0, event_ga = 0, event_se = 0;
54 int just_one = 0;
55 uint32_t event_session_id = -2;
56 long long event_exit = 0;
57 int event_exit_is_set = 0;
58 int line_buffered = 0;
59 int event_debug = 0;
60 int checkpt_timeonly = 0;
61 const char *event_key = NULL;
62 const char *event_filename = NULL;
63 const char *event_exe = NULL;
64 const char *event_comm = NULL;
65 const char *event_hostname = NULL;
66 const char *event_terminal = NULL;
67 const char *event_subject = NULL;
68 const char *event_object = NULL;
69 const char *event_uuid = NULL;
70 const char *event_vmname = NULL;
71 const char *checkpt_filename = NULL;    /* checkpoint filename if present */
72 report_t report_format = RPT_DEFAULT;
73 ilist *event_type;
74
75 slist *event_node_list = NULL;
76
77 struct nv_pair {
78     int        value;
79     const char *name;
80 };
81
82
83 enum { S_EVENT, S_COMM, S_FILENAME, S_ALL_GID, S_EFF_GID, S_GID, S_HELP,
84 S_HOSTNAME, S_INTERP, S_INFILE, S_MESSAGE_TYPE, S_PID, S_SYSCALL, S_OSUCCESS,
85 S_TIME_END, S_TIME_START, S_TERMINAL, S_ALL_UID, S_EFF_UID, S_UID, S_LOGINID,
86 S_VERSION, S_EXACT_MATCH, S_EXECUTABLE, S_CONTEXT, S_SUBJECT, S_OBJECT,
87 S_PPID, S_KEY, S_RAW, S_NODE, S_IN_LOGS, S_JUST_ONE, S_SESSION, S_EXIT,
88 S_LINEBUFFERED, S_UUID, S_VMNAME, S_DEBUG, S_CHECKPOINT, S_ARCH };
89
90 static struct nv_pair optiontab[] = {
91         { S_EVENT, "-a" },
92         { S_ARCH, "--arch" },
93         { S_EVENT, "--event" },
94         { S_COMM, "-c" },
95         { S_COMM, "--comm" },
96         { S_CHECKPOINT, "--checkpoint" },
97         { S_DEBUG, "--debug" },
98         { S_EXIT, "-e" },
99         { S_EXIT, "--exit" },
100         { S_FILENAME, "-f" },
101         { S_FILENAME, "--file" },
102         { S_ALL_GID, "-ga" },
103         { S_ALL_GID, "--gid-all" },
104         { S_EFF_GID, "-ge" },
105         { S_EFF_GID, "--gid-effective" },
106         { S_GID, "-gi" },
107         { S_GID, "--gid" },
108         { S_HELP, "-h" },
109         { S_HELP, "--help" },
110         { S_HOSTNAME, "-hn" },
111         { S_HOSTNAME, "--host" },
112         { S_INTERP, "-i" },
113         { S_INTERP, "--interpret" },
114         { S_INFILE, "-if" },
115         { S_INFILE, "--input" },
116         { S_IN_LOGS, "--input-logs" },
117         { S_JUST_ONE, "--just-one" },
118         { S_KEY, "-k" },
119         { S_KEY, "--key" },
120         { S_LINEBUFFERED, "-l" },
121         { S_LINEBUFFERED, "--line-buffered" },
122         { S_MESSAGE_TYPE, "-m" },
123         { S_MESSAGE_TYPE, "--message" },
124         { S_NODE, "-n" },
125         { S_NODE, "--node" },
126         { S_OBJECT, "-o" },
127         { S_OBJECT, "--object" },
128         { S_PID, "-p" },
129         { S_PID, "--pid" },
130         { S_PPID, "-pp" },
131         { S_PPID, "--ppid" },
132         { S_RAW, "-r" },
133         { S_RAW, "--raw" },
134         { S_SYSCALL, "-sc" },
135         { S_SYSCALL, "--syscall" },
136         { S_CONTEXT, "-se" },
137         { S_CONTEXT, "--context" },
138         { S_SESSION, "--session" },
139         { S_SUBJECT, "-su" },
140         { S_SUBJECT, "--subject" },
141         { S_OSUCCESS, "-sv" },
142         { S_OSUCCESS, "--success" },
143         { S_TIME_END, "-te"},
144         { S_TIME_END, "--end"},
145         { S_TIME_START, "-ts" },
146         { S_TIME_START, "--start" },
147         { S_TERMINAL, "-tm" },
148         { S_TERMINAL, "--terminal" },
149         { S_ALL_UID, "-ua" },
150         { S_ALL_UID, "--uid-all" },
151         { S_EFF_UID, "-ue" },
152         { S_EFF_UID, "--uid-effective" },
153         { S_UID, "-ui" },
154         { S_UID, "--uid" },
155         { S_UUID, "-uu" },
156         { S_UUID, "--uuid" },
157         { S_LOGINID, "-ul" },
158         { S_LOGINID, "--loginuid" },
159         { S_VERSION, "-v" },
160         { S_VERSION, "--version" },
161         { S_VMNAME, "-vm" },
162         { S_VMNAME, "--vm-name" },
163         { S_EXACT_MATCH, "-w" },
164         { S_EXACT_MATCH, "--word" },
165         { S_EXECUTABLE, "-x" },
166         { S_EXECUTABLE, "--executable" }
167 };
168 #define OPTION_NAMES (sizeof(optiontab)/sizeof(optiontab[0]))
169
170
171 static int audit_lookup_option(const char *name)
172 {
173         int i;
174
175         for (i = 0; i < OPTION_NAMES; i++)
176                 if (!strcmp(optiontab[i].name, name))
177                         return optiontab[i].value;
178         return -1;
179 }
180
181 static void usage(void)
182 {
183         printf("usage: ausearch [options]\n"
184         "\t-a,--event <Audit event id>\tsearch based on audit event id\n"
185         "\t--arch <CPU>\t\t\tsearch based on the CPU architecture\n"
186         "\t-c,--comm  <Comm name>\t\tsearch based on command line name\n"
187         "\t--checkpoint <checkpoint file>\tsearch from last complete event\n"
188         "\t--debug\t\t\tWrite malformed events that are skipped to stderr\n"
189         "\t-e,--exit  <Exit code or errno>\tsearch based on syscall exit code\n"
190         "\t-f,--file  <File name>\t\tsearch based on file name\n"
191         "\t-ga,--gid-all <all Group id>\tsearch based on All group ids\n"
192         "\t-ge,--gid-effective <effective Group id>  search based on Effective\n\t\t\t\t\tgroup id\n"
193         "\t-gi,--gid <Group Id>\t\tsearch based on group id\n"
194         "\t-h,--help\t\t\thelp\n"
195         "\t-hn,--host <Host Name>\t\tsearch based on remote host name\n"
196         "\t-i,--interpret\t\t\tInterpret results to be human readable\n"
197         "\t-if,--input <Input File name>\tuse this file instead of current logs\n"
198         "\t--input-logs\t\t\tUse the logs even if stdin is a pipe\n"
199         "\t--just-one\t\t\tEmit just one event\n"
200         "\t-k,--key  <key string>\t\tsearch based on key field\n"
201         "\t-l, --line-buffered\t\tFlush output on every line\n"
202         "\t-m,--message  <Message type>\tsearch based on message type\n"
203         "\t-n,--node  <Node name>\t\tsearch based on machine's name\n"
204         "\t-o,--object  <SE Linux Object context> search based on context of object\n"
205         "\t-p,--pid  <Process id>\t\tsearch based on process id\n"
206         "\t-pp,--ppid <Parent Process id>\tsearch based on parent process id\n"
207         "\t-r,--raw\t\t\toutput is completely unformatted\n"
208         "\t-sc,--syscall <SysCall name>\tsearch based on syscall name or number\n"
209         "\t-se,--context <SE Linux context> search based on either subject or\n\t\t\t\t\t object\n"
210         "\t--session <login session id>\tsearch based on login session id\n"
211         "\t-su,--subject <SE Linux context> search based on context of the Subject\n"
212         "\t-sv,--success <Success Value>\tsearch based on syscall or event\n\t\t\t\t\tsuccess value\n"
213         "\t-te,--end [end date] [end time]\tending date & time for search\n"
214         "\t-ts,--start [start date] [start time]\tstarting data & time for search\n"
215         "\t-tm,--terminal <TerMinal>\tsearch based on terminal\n"
216         "\t-ua,--uid-all <all User id>\tsearch based on All user id's\n"
217         "\t-ue,--uid-effective <effective User id>  search based on Effective\n\t\t\t\t\tuser id\n"
218         "\t-ui,--uid <User Id>\t\tsearch based on user id\n"
219         "\t-ul,--loginuid <login id>\tsearch based on the User's Login id\n"
220         "\t-uu,--uuid <guest UUID>\t\tsearch for events related to the virtual\n"
221         "\t\t\t\t\tmachine with the given UUID.\n"
222         "\t-v,--version\t\t\tversion\n"
223         "\t-vm,--vm-name <guest name>\tsearch for events related to the virtual\n"
224         "\t\t\t\t\tmachine with the name.\n"
225         "\t-w,--word\t\t\tstring matches are whole word\n"
226         "\t-x,--executable <executable name>  search based on executable name\n"
227         );
228 }
229
230 static int convert_str_to_msg(const char *optarg)
231 {
232         int tmp, retval = 0;
233
234         if (isdigit(optarg[0])) {
235                 errno = 0;
236                 tmp = strtoul(optarg, NULL, 10);
237                 if (errno) {
238                         fprintf(stderr, 
239                         "Numeric message type conversion error (%s) for %s\n",
240                                 strerror(errno), optarg);
241                         retval = -1;
242                 }
243         } else {
244                 tmp = audit_name_to_msg_type(optarg);
245                 if (tmp < 0) 
246                         retval = -1;
247         }
248         if (retval == 0) {
249                 if (event_type == NULL) {
250                         event_type = malloc(sizeof(ilist));
251                         if (event_type == NULL)
252                                 return -1;
253                         ilist_create(event_type);
254                 }
255                 ilist_append(event_type, tmp, 1, 0);
256         }
257         return retval;
258 }
259
260 static int parse_msg(const char *optarg)
261 {
262         int retval = 0;
263         char *saved = NULL;
264
265         if (strchr(optarg, ',')) {
266                 char *ptr, *tmp = strdup(optarg);
267                 if (tmp == NULL)
268                         return -1;
269                 ptr = strtok_r(tmp, ",", &saved);
270                 while (ptr) {
271                         retval = convert_str_to_msg(ptr);
272                         if (retval != 0)
273                                 break;
274                         ptr = strtok_r(NULL, ",", &saved);
275                 }
276                 free(tmp);
277                 return retval;
278         }
279
280         return convert_str_to_msg(optarg);
281 }
282
283 /*
284  * This function examines the commandline parameters and sets various
285  * search options. It returns a 0 on success and < 0 on failure
286  */
287 int check_params(int count, char *vars[])
288 {
289         int c = 1;
290         int retval = 0;
291         const char *optarg;
292
293         if (count < 2) {
294                 usage();
295                 return -1;
296         }
297         while (c < count && retval == 0) {
298                 // Go ahead and point to the next argument
299                 if (c+1 < count) {
300                         if (vars[c+1][0] != '-')
301                                 optarg = vars[c+1];
302                         else
303                                 optarg = NULL;
304                 } else
305                         optarg = NULL;
306
307                 switch (audit_lookup_option(vars[c])) {
308                 case S_EVENT:
309                         if (!optarg) {
310                                 fprintf(stderr, 
311                                         "Argument is required for %s\n",
312                                         vars[c]);
313                                 retval = -1;
314                                 break;
315                         }
316                         if (isdigit(optarg[0])) {
317                                 errno = 0;
318                                 event_id = strtoul(optarg, NULL, 10);
319                                 if (errno) {
320                                         fprintf(stderr,
321                                         "Illegal value for audit event ID");
322                                         retval = -1;
323                                 }
324                                 c++;
325                         } else {
326                                 fprintf(stderr, 
327                         "Audit event id must be a numeric value, was %s\n",
328                                         optarg);
329                                 retval = -1;
330                         }
331                         break;
332                 case S_COMM:
333                         if (!optarg) {
334                                 fprintf(stderr, 
335                                         "Argument is required for %s\n",
336                                         vars[c]);
337                                 retval = -1;
338                                 break;
339                         } else {
340                                 event_comm = strdup(optarg);
341                                 if (event_comm == NULL)
342                                         retval = -1;
343                                 c++;
344                         }
345                         break;
346                 case S_FILENAME:
347                         if (!optarg) {
348                                 fprintf(stderr, 
349                                         "Argument is required for %s\n",
350                                         vars[c]);
351                                 retval = -1;
352                         } else {
353                                 event_filename = strdup(optarg);
354                                 if (event_filename == NULL)
355                                         retval = -1;
356                                 c++;
357                         }
358                         break;
359                 case S_KEY:
360                         if (!optarg) {
361                                 fprintf(stderr, 
362                                         "Argument is required for %s\n",
363                                         vars[c]);
364                                 retval = -1;
365                         } else {
366                                 event_key = strdup(optarg);
367                                 if (event_key == NULL)
368                                         retval = -1;
369                                 c++;
370                         }
371                         break;
372                 case S_ALL_GID:
373                         if (!optarg) {
374                                 fprintf(stderr, 
375                                         "Argument is required for %s\n",
376                                         vars[c]);
377                                 retval = -1;
378                                 break;
379                         }
380                         if (isdigit(optarg[0])) {
381                                 errno = 0;
382                                 event_gid = strtoul(optarg,NULL,10);
383                                 if (errno) {
384                                         fprintf(stderr, 
385                         "Numeric group ID conversion error (%s) for %s\n",
386                                                 strerror(errno), optarg);
387                                         retval = -1;
388                                 }
389                         } else {
390                                 struct group *gr ;
391
392                                 gr = getgrnam(optarg) ;
393                                 if (gr == NULL) {
394                                         fprintf(stderr, 
395                                 "Group ID is non-numeric and unknown (%s)\n",
396                                                 optarg);
397                                         retval = -1;
398                                         break;
399                                 }
400                                 event_gid = gr->gr_gid;
401                         }
402                         event_egid = event_gid;
403                         event_ga = 1;
404                         c++;
405                         break;
406                 case S_EFF_GID:
407                         if (!optarg) {
408                                 fprintf(stderr, 
409                                         "Argument is required for %s\n",
410                                         vars[c]);
411                                 retval = -1;
412                                 break;
413                         }
414                         if (isdigit(optarg[0])) {
415                                 errno = 0;
416                                 event_egid = strtoul(optarg,NULL,10);
417                                 if (errno) {
418                                         fprintf(stderr, 
419                         "Numeric group ID conversion error (%s) for %s\n",
420                                                 strerror(errno), optarg);
421                                         retval = -1;
422                                 }
423                         } else {
424                                 struct group *gr ;
425
426                                 gr = getgrnam(optarg) ;
427                                 if (gr == NULL) {
428                                         fprintf(stderr, 
429                         "Effective group ID is non-numeric and unknown (%s)\n",
430                                                 optarg);
431                                         retval = -1;
432                                         break;
433                                 }
434                                 event_egid = gr->gr_gid;
435                         }
436                         c++;
437                         break;
438                 case S_GID:
439                         if (!optarg) {
440                                 fprintf(stderr, 
441                                         "Argument is required for %s\n",
442                                         vars[c]);
443                                 retval = -1;
444                                 break;
445                         }
446                         if (isdigit(optarg[0])) {
447                                 errno = 0;
448                                 event_gid = strtoul(optarg,NULL,10);
449                                 if (errno) {
450                                         fprintf(stderr, 
451                         "Numeric group ID conversion error (%s) for %s\n",
452                                                 strerror(errno), optarg);
453                                         retval = -1;
454                                 }
455                         } else {
456                                 struct group *gr ;
457
458                                 gr = getgrnam(optarg) ;
459                                 if (gr == NULL) {
460                                         fprintf(stderr, 
461                                 "Group ID is non-numeric and unknown (%s)\n",
462                                                 optarg);
463                                         retval = -1;
464                                         break;
465                                 }
466                                 event_gid = gr->gr_gid;
467                         }
468                         c++;
469                         break;
470                 case S_HELP:
471                         usage();
472                         exit(0);
473                         break;
474                 case S_HOSTNAME:
475                         if (!optarg) {
476                                 fprintf(stderr, 
477                                         "Argument is required for %s\n",
478                                         vars[c]);
479                                 retval = -1;
480                         } else {
481                                 event_hostname = strdup(optarg);
482                                 if (event_hostname == NULL)
483                                         retval = -1;
484                                 c++;
485                         }
486                         break;
487                 case S_INTERP:
488                         if (report_format == RPT_DEFAULT)
489                                 report_format = RPT_INTERP;
490                         else {
491                                 fprintf(stderr, 
492                                         "Conflicting output format %s\n",
493                                         vars[c]);
494                                 retval = -1;
495                         }
496                         if (optarg) {
497                                 fprintf(stderr, 
498                                         "Argument is NOT required for %s\n",
499                                         vars[c]);
500                                 retval = -1;
501                         }
502                         break;
503                 case S_INFILE:
504                         if (!optarg) {
505                                 fprintf(stderr, 
506                                         "Argument is required for %s\n",
507                                         vars[c]);
508                                 retval = -1;
509                         } else {
510                                 user_file = strdup(optarg);
511                                 if (user_file == NULL)
512                                         retval = -1;
513                                 c++;
514                         }
515                         break;
516                 case S_MESSAGE_TYPE:
517                         if (!optarg) {
518                                 fprintf(stderr, 
519                                         "Argument is required for %s\n",
520                                         vars[c]);
521                                 retval = -1;
522                         } else {
523                                 if (strcasecmp(optarg, "ALL") != 0) {
524                                         retval = parse_msg(optarg);
525                                 }
526                                 c++;
527                         }
528                         if (retval < 0) {
529                                 int i;
530                                 fprintf(stderr, 
531                                         "Valid message types are: ALL ");
532                                 for (i=AUDIT_USER;i<=AUDIT_LAST_VIRT_MSG;i++){
533                                         const char *name;
534                                         if (i == AUDIT_WATCH_INS) // Skip a few
535                                                 i = AUDIT_FIRST_USER_MSG;
536                                         name = audit_msg_type_to_name(i);
537                                         if (name)
538                                                 fprintf(stderr, "%s ", name);
539                                 }
540                                 fprintf(stderr, "\n");
541                         }
542                         break;
543                 case S_OBJECT:
544                         if (!optarg) {
545                                 fprintf(stderr, 
546                                         "Argument is required for %s\n",
547                                         vars[c]);
548                                 retval = -1;
549                                 break;
550                         } else {
551                                 event_object = strdup(optarg);
552                                 if (event_object == NULL)
553                                         retval = -1;
554                                 c++;
555                         }
556                         break;
557                 case S_PPID:
558                         if (!optarg) {
559                                 fprintf(stderr, 
560                                         "Argument is required for %s\n",
561                                         vars[c]);
562                                 retval = -1;
563                                 break;
564                         }
565                         if (isdigit(optarg[0])) {
566                                 errno = 0;
567                                 event_ppid = strtol(optarg,NULL,10);
568                                 if (errno)
569                                         retval = -1;
570                                 c++;
571                         } else {
572                                 fprintf(stderr, 
573                         "Parent process id must be a numeric value, was %s\n",
574                                         optarg);
575                                 retval = -1;
576                         }
577                         break;
578                 case S_PID:
579                         if (!optarg) {
580                                 fprintf(stderr, 
581                                         "Argument is required for %s\n",
582                                         vars[c]);
583                                 retval = -1;
584                                 break;
585                         }
586                         if (isdigit(optarg[0])) {
587                                 errno = 0;
588                                 event_pid = strtol(optarg,NULL,10);
589                                 if (errno)
590                                         retval = -1;
591                                 c++;
592                         } else {
593                                 fprintf(stderr, 
594                                 "Process id must be a numeric value, was %s\n",
595                                         optarg);
596                                 retval = -1;
597                         }
598                         break;
599                 case S_RAW:
600                         if (report_format == RPT_DEFAULT)
601                                 report_format = RPT_RAW;
602                         else {
603                                 fprintf(stderr, 
604                                         "Conflicting output format --raw\n");
605                                 retval = -1;
606                         }
607                         if (optarg) {
608                                 fprintf(stderr, 
609                                         "Argument is NOT required for --raw\n");
610                                 retval = -1;
611                         }
612                         break;
613                 case S_NODE:
614                         if (!optarg) {
615                                 fprintf(stderr, 
616                                         "Argument is required for %s\n",
617                                         vars[c]);
618                                 retval = -1;
619                         } else {
620                                 snode sn;
621                                 c++;
622
623                                 if (!event_node_list) {
624                                         event_node_list = malloc(sizeof (slist));
625                                         if (!event_node_list) {
626                                                 retval = -1;
627                                                 break;
628                                         }
629                                         slist_create(event_node_list);
630                                 }
631                                 
632                                 sn.str = strdup(optarg);
633                                 sn.key = NULL;
634                                 sn.hits=0;
635                                 slist_append(event_node_list, &sn);
636                         }
637                         break;
638                 case S_SYSCALL:
639                         if (!optarg) {
640                                 fprintf(stderr, 
641                                         "Argument is required for %s\n",
642                                         vars[c]);
643                                 retval = -1;
644                                 break;
645                         }
646                         if (isdigit(optarg[0])) {
647                                 errno = 0;
648                                 event_syscall = (int)strtoul(optarg, NULL, 10);
649                                 if (errno) {
650                                         fprintf(stderr, 
651                         "Syscall numeric conversion error (%s) for %s\n",
652                                                 strerror(errno), optarg);
653                                         retval = -1;
654                                 }
655                         } else {
656                                 if (event_machine == -1) {
657                                         int machine;
658                                         machine = audit_detect_machine();
659                                         if (machine < 0) {
660                                                 fprintf(stderr,
661                                             "Error detecting machine type");
662                                                 retval = -1;
663                                                 break;
664                                         }
665                                         event_machine = machine;
666                                 }
667                                 event_syscall = audit_name_to_syscall(optarg, 
668                                         event_machine);
669                                 if (event_syscall == -1) {
670                                         fprintf(stderr, 
671                                                 "Syscall %s not found\n",
672                                                 optarg);
673                                         retval = -1;
674                                 }
675                         }
676                         c++;
677                         break;
678                 case S_CONTEXT:
679                         if (!optarg) {
680                                 fprintf(stderr, 
681                                         "Argument is required for %s\n",
682                                         vars[c]);
683                                 retval = -1;
684                                 break;
685                         } else {
686                                 event_subject = strdup(optarg);
687                                 if (event_subject == NULL)
688                                         retval = -1;
689                                 event_object = strdup(optarg);
690                                 if (event_object == NULL)
691                                         retval = -1;
692                                 event_se = 1;
693                                 c++;
694                         }
695                         break;
696                 case S_SUBJECT:
697                         if (!optarg) {
698                                 fprintf(stderr, 
699                                         "Argument is required for %s\n",
700                                         vars[c]);
701                                 retval = -1;
702                                 break;
703                         } else {
704                                 event_subject = strdup(optarg);
705                                 if (event_subject == NULL)
706                                         retval = -1;
707                                 c++;
708                         }
709                         break;
710                 case S_OSUCCESS:
711                         if (!optarg) {
712                                 fprintf(stderr, 
713                                         "Argument is required for %s\n",
714                                         vars[c]);
715                                 retval = -1;
716                                 break;
717                         }
718                         if ( (strstr(optarg, "yes")!=NULL) || 
719                                         (strstr(optarg, "no")!=NULL) ) {
720                                 if (strcmp(optarg, "yes") == 0)
721                                         event_success = S_SUCCESS;
722                                 else
723                                         event_success = S_FAILED;
724                         } else {
725                                 fprintf(stderr, 
726                                         "Success must be 'yes' or 'no'.\n");
727                                 retval = -1;
728                         }
729                         c++;
730                         break;
731                 case S_SESSION:
732                         if (!optarg) {
733                                 if ((c+1 < count) && vars[c+1])
734                                         optarg = vars[c+1];
735                                 else {
736                                         fprintf(stderr,
737                                                 "Argument is required for %s\n",
738                                                 vars[c]);
739                                         retval = -1;
740                                         break;
741                                 }
742                         }
743                         { 
744                         size_t len = strlen(optarg);
745                         if (isdigit(optarg[0])) {
746                                 errno = 0;
747                                 event_session_id = strtoul(optarg,NULL,10);
748                                 if (errno)
749                                         retval = -1;
750                                 c++;
751                         } else if (len >= 2 && *(optarg)=='-' &&
752                                                 (isdigit(optarg[1]))) {
753                                 errno = 0;
754                                 event_session_id = strtoul(optarg, NULL, 0);
755                                 if (errno) {
756                                         retval = -1;
757                                         fprintf(stderr, "Error converting %s\n",
758                                                 optarg);
759                                 }
760                                 c++;
761                         } else {
762                                 fprintf(stderr, 
763                                 "Session id must be a numeric value, was %s\n",
764                                         optarg);
765                                 retval = -1;
766                         }
767                         }
768                         break;
769                 case S_EXIT:
770                         if (!optarg) {
771                                 if ((c+1 < count) && vars[c+1])
772                                         optarg = vars[c+1];
773                                 else {
774                                         fprintf(stderr,
775                                                 "Argument is required for %s\n",
776                                                 vars[c]);
777                                         retval = -1;
778                                         break;
779                                 }
780                         } 
781                         {
782                         size_t len = strlen(optarg);
783                         if (isdigit(optarg[0])) {
784                                 errno = 0;
785                                 event_exit = strtoll(optarg, NULL, 0);
786                                 if (errno) {
787                                         retval = -1;
788                                         fprintf(stderr, "Error converting %s\n",
789                                                 optarg);
790                                 }
791                         } else if (len >= 2 && *(optarg)=='-' &&
792                                                 (isdigit(optarg[1]))) {
793                                 errno = 0;
794                                 event_exit = strtoll(optarg, NULL, 0);
795                                 if (errno) {
796                                         retval = -1;
797                                         fprintf(stderr, "Error converting %s\n",
798                                                 optarg);
799                                 }
800                         } else {
801                                 event_exit = audit_name_to_errno(optarg);
802                                 if (event_exit == 0) {
803                                         retval = -1;
804                                         fprintf(stderr, 
805                                                 "Unknown errno, was %s\n",
806                                                 optarg);
807                                 }
808                         }
809                         c++;
810                         if (retval != -1)
811                                 event_exit_is_set = 1;
812                         }
813                         break;
814                 case S_TIME_END:
815                         if (optarg) {
816                                 if ( (c+2 < count) && vars[c+2] && 
817                                         (vars[c+2][0] != '-') ) {
818                                 /* Have both date and time - check order*/
819                                         if (strchr(optarg, ':')) {
820                                                 if (ausearch_time_end(vars[c+2],
821                                                                  optarg) != 0) 
822                                                         retval = -1;
823                                         } else {
824                                                 if (ausearch_time_end(optarg, 
825                                                                 vars[c+2]) != 0)
826                                                         retval = -1;
827                                         }
828                                         c++;                    
829                                 } else {
830                                         // Check against recognized words
831                                         int t = lookup_time(optarg);
832                                         if (t >= 0) {
833                                                 if (ausearch_time_end(optarg,
834                                                                 NULL) != 0)
835                                                         retval = -1;
836                                         } else if ( (strchr(optarg, ':')) == NULL) {
837                                                 /* Only have date */
838                                                 if (ausearch_time_end(optarg,
839                                                                 NULL) != 0)
840                                                         retval = -1;
841                                         } else {
842                                                 /* Only have time */
843                                                 if (ausearch_time_end(NULL,
844                                                                 optarg) != 0)
845                                                         retval = -1;
846                                         }
847                                 }
848                                 c++;                    
849                                 break;
850                         } 
851                         fprintf(stderr, 
852                                 "%s requires either date and/or time\n",
853                                 vars[c]);
854                         retval = -1;
855                         break;
856                 case S_TIME_START:
857                         if (optarg) {
858                                 if ( (c+2 < count) && vars[c+2] && 
859                                         (vars[c+2][0] != '-') ) {
860                                 /* Have both date and time - check order */
861                                         if (strchr(optarg, ':')) {
862                                                 if (ausearch_time_start(
863                                                         vars[c+2], optarg) != 0)
864                                                         retval = -1;
865                                         } else {
866                                                 if (ausearch_time_start(optarg, 
867                                                                 vars[c+2]) != 0)
868                                                         retval = -1;
869                                         }
870                                         c++;
871                                 } else {
872                                         // Check against recognized words
873                                         int t = lookup_time(optarg);
874                                         if (t >= 0) {
875                                                 if (ausearch_time_start(optarg,
876                                                         "00:00:00") != 0)
877                                                         retval = -1;
878                                         } else if (strcmp(optarg,
879                                                         "checkpoint") == 0) {
880                                         // Only use the timestamp from within
881                                         // the checkpoint file
882                                                 checkpt_timeonly++;
883                                         } else if (strchr(optarg, ':') == NULL){
884                                                 /* Only have date */
885                                                 if (ausearch_time_start(optarg,
886                                                         "00:00:00") != 0)
887                                                         retval = -1;
888                                         } else {
889                                                 /* Only have time */
890                                                 if (ausearch_time_start(NULL,
891                                                                 optarg) != 0)
892                                                         retval = -1;
893                                         }
894                                 }
895                                 c++;
896                                 break;
897                         }
898                         fprintf(stderr, 
899                                 "%s requires either date and/or time\n",
900                                 vars[c]);
901                         retval = -1;
902                         break;
903                 case S_TERMINAL:
904                         if (!optarg) {
905                                 fprintf(stderr, 
906                                         "Argument is required for %s\n",
907                                         vars[c]);
908                                 retval = -1;
909                         } else { 
910                                 event_terminal = strdup(optarg);
911                                 if (event_terminal == NULL)
912                                         retval = -1;
913                                 c++;
914                         }
915                         break;
916                 case S_UID:
917                         if (!optarg) {
918                                 fprintf(stderr, 
919                                         "Argument is required for %s\n",
920                                         vars[c]);
921                                 retval = -1;
922                                 break;
923                         }
924                         if (isdigit(optarg[0])) {
925                                 errno = 0;
926                                 event_uid = strtoul(optarg,NULL,10);
927                                 if (errno) {
928                                         fprintf(stderr, 
929                         "Numeric user ID conversion error (%s) for %s\n",
930                                                 strerror(errno), optarg);
931                                         retval = -1;
932                                 }
933                         } else {
934                                 struct passwd *pw;
935
936                                 pw = getpwnam(optarg);
937                                 if (pw == NULL) {
938                                         fprintf(stderr, 
939                         "Effective user ID is non-numeric and unknown (%s)\n",
940                                                 optarg);
941                                         retval = -1;
942                                         break;
943                                 }
944                                 event_uid = pw->pw_uid;
945                         }
946                         c++;
947                         break;
948                 case S_EFF_UID:
949                         if (!optarg) {
950                                 fprintf(stderr, 
951                                         "Argument is required for %s\n",
952                                         vars[c]);
953                                 retval = -1;
954                                 break;
955                         }
956                         if (isdigit(optarg[0])) {
957                                 errno = 0;
958                                 event_euid = strtoul(optarg,NULL,10);
959                                 if (errno) {
960                                         fprintf(stderr, 
961                         "Numeric user ID conversion error (%s) for %s\n",
962                                                 strerror(errno), optarg);
963                                         retval = -1;
964                                 }
965                         } else {
966                                 struct passwd *pw ;
967
968                                 pw = getpwnam(optarg) ;
969                                 if (pw == NULL) {
970                                         fprintf(stderr, 
971                                 "User ID is non-numeric and unknown (%s)\n",
972                                                 optarg);
973                                         retval = -1;
974                                         break;
975                                 }
976                                 event_euid = pw->pw_uid;
977                         }
978                         c++;
979                         break;
980                 case S_ALL_UID:
981                         if (!optarg) {
982                                 fprintf(stderr, 
983                                         "Argument is required for %s\n",
984                                         vars[c]);
985                                 retval = -1;
986                                 break;
987                         }
988                         if (isdigit(optarg[0])) {
989                                 errno = 0;
990                                 event_uid = strtoul(optarg,NULL,10);
991                                 if (errno) {
992                                         fprintf(stderr, 
993                         "Numeric user ID conversion error (%s) for %s\n",
994                                                 strerror(errno), optarg);
995                                         retval = -1;
996                                 }
997                         } else {
998                                 struct passwd *pw ;
999
1000                                 pw = getpwnam(optarg) ;
1001                                 if (pw == NULL) {
1002                                         fprintf(stderr, 
1003                                 "User ID is non-numeric and unknown (%s)\n",
1004                                                 optarg);
1005                                         retval = -1;
1006                                         break;
1007                                 }
1008                                 event_uid = pw->pw_uid;
1009                         }
1010                         event_ua = 1;
1011                         event_euid = event_uid;
1012                         event_loginuid = event_uid;
1013                         c++;
1014                         break;
1015                 case S_LOGINID:
1016                         if (!optarg) {
1017                                 if ((c+1 < count) && vars[c+1])
1018                                         optarg = vars[c+1];
1019                                 else {
1020                                         fprintf(stderr,
1021                                                 "Argument is required for %s\n",
1022                                                 vars[c]);
1023                                         retval = -1;
1024                                         break;
1025                                 }
1026                         }
1027                         {
1028                         size_t len = strlen(optarg);
1029                         if (isdigit(optarg[0])) {
1030                                 errno = 0;
1031                                 event_loginuid = strtoul(optarg,NULL,10);
1032                                 if (errno) {
1033                                         fprintf(stderr, 
1034                         "Numeric user ID conversion error (%s) for %s\n",
1035                                                 strerror(errno), optarg);
1036                                         retval = -1;
1037                                 }
1038                         } else if (len >= 2 && *(optarg)=='-' &&
1039                                                 (isdigit(optarg[1]))) {
1040                                 errno = 0;
1041                                 event_loginuid = strtol(optarg, NULL, 0);
1042                                 if (errno) {
1043                                         retval = -1;
1044                                         fprintf(stderr, "Error converting %s\n",
1045                                                 optarg);
1046                                 }
1047                         } else {
1048                                 struct passwd *pw ;
1049
1050                                 pw = getpwnam(optarg) ;
1051                                 if (pw == NULL) {
1052                                         fprintf(stderr, 
1053                         "Login user ID is non-numeric and unknown (%s)\n",
1054                                                 optarg);
1055                                         retval = -1;
1056                                         break;
1057                                 }
1058                                 event_loginuid = pw->pw_uid;
1059                         }
1060                         }
1061                         c++;
1062                         break;
1063                 case S_UUID:
1064                         if (!optarg) {
1065                                 fprintf(stderr,
1066                                         "Argument is required for %s\n",
1067                                         vars[c]);
1068                                 retval = -1;
1069                         } else {
1070                                 event_uuid = strdup(optarg);
1071                                 if (event_uuid == NULL) {
1072                                         retval = -1;
1073                                 }
1074                                 c++;
1075                         }
1076                         break;
1077                 case S_VMNAME:
1078                         if (!optarg) {
1079                                 fprintf(stderr,
1080                                         "Argument is required for %s\n",
1081                                         vars[c]);
1082                                 retval = -1;
1083                         } else {
1084                                 event_vmname= strdup(optarg);
1085                                 if (event_vmname == NULL) {
1086                                         retval = -1;
1087                                 }
1088                                 c++;
1089                         }
1090                         break;
1091                 case S_VERSION:
1092                         printf("ausearch version %s\n", VERSION);
1093                         exit(0);
1094                         break;
1095                 case S_EXACT_MATCH:
1096                         event_exact_match=1;
1097                         break;
1098                 case S_IN_LOGS:
1099                         force_logs = 1;
1100                         break;
1101                 case S_JUST_ONE:
1102                         just_one = 1;
1103                         break;
1104                 case S_EXECUTABLE:
1105                         if (!optarg) {
1106                                 fprintf(stderr, 
1107                                         "Argument is required for %s\n",
1108                                         vars[c]);
1109                                 retval = -1;
1110                         } else { 
1111                                 event_exe = strdup(optarg);
1112                                 if (event_exe == NULL)
1113                                         retval = -1;
1114                                 c++;
1115                         }
1116                         break;
1117                 case S_LINEBUFFERED:
1118                         line_buffered = 1;
1119                         break;
1120                 case S_DEBUG:
1121                         event_debug = 1;
1122                         break;
1123                 case S_CHECKPOINT:
1124                         if (!optarg) {
1125                                 fprintf(stderr, 
1126                                         "Argument is required for %s\n",
1127                                         vars[c]);
1128                                 retval = -1;
1129                         } else {
1130                                 checkpt_filename = strdup(optarg);
1131                                 if (checkpt_filename == NULL)
1132                                         retval = -1;
1133                                 c++;
1134                         }
1135                         break;
1136                 case S_ARCH:
1137                         if (!optarg) {
1138                                 fprintf(stderr, 
1139                                         "Argument is required for %s\n",
1140                                         vars[c]);
1141                                 retval = -1;
1142                                 break;
1143                         }
1144                         if (event_machine != -1) {
1145                                 if (event_syscall != -1)
1146                                         fprintf(stderr, 
1147                         "Arch needs to be defined before the syscall\n");
1148                                 else
1149                                         fprintf(stderr, 
1150                                                 "Arch is already defined\n");
1151                                 retval = -1;
1152                                 break;
1153                         } else {
1154                                 int machine = audit_determine_machine(optarg);
1155                                 if (machine < 0) {
1156                                         fprintf(stderr, "Unknown arch %s\n",
1157                                                 optarg);
1158                                         retval = -1;
1159                                 }
1160                                 event_machine = machine;
1161                         }
1162                         c++;
1163                         break;
1164                 default:
1165                         fprintf(stderr, "%s is an unsupported option\n", 
1166                                 vars[c]);
1167                         retval = -1;
1168                         break;
1169                 }
1170                 c++;
1171         }
1172
1173         return retval;
1174 }
1175