Print this page
NEX-13644 File access audit logging
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/auditreduce/proc.c
+++ new/usr/src/cmd/auditreduce/proc.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 + *
25 + * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
24 26 */
25 27
26 28 /*
27 29 * Main processor for auditreduce.
28 30 * Mproc() is the entry point for this module. It is the only visible
29 31 * function in this module.
30 32 */
31 33
32 34 #include <sys/types.h>
33 35 #include <locale.h>
34 36 #include <bsm/libbsm.h>
35 37 #include <bsm/audit.h>
36 38 #include "auditr.h"
37 39
38 40 extern int write_header();
39 41 extern int token_processing();
40 42
41 43 static void asort();
42 44 static audit_pcb_t *aget();
43 45 static int get_file();
44 46 static int write_recs();
45 47 static int get_recs();
46 48 static int check_rec();
47 49 static void check_order();
48 50 static int check_header();
49 51 static int get_record();
50 52
51 53 static char empty_file_token[] = {
52 54 #ifdef _LP64
53 55 AUT_OTHER_FILE64, /* token id */
54 56 0, 0, 0, 0, 0, 0, 0, 0, /* seconds of time */
55 57 0, 0, 0, 0, 0, 0, 0, 0, /* microseconds of time */
56 58 #else
57 59 AUT_OTHER_FILE32, /* token id */
58 60 0, 0, 0, 0, /* seconds of time */
59 61 0, 0, 0, 0, /* microseconds of time */
60 62 #endif
61 63 0, 0, /* length of path name */
62 64 };
63 65
64 66
65 67 /*
66 68 * .func mproc - main processor.
67 69 * .desc Mproc controls a single process's actions.
68 70 * First one record is retreived from each pcb. As they are retreived
69 71 * they are placed into a linked list sorted with oldest first. Then
70 72 * the first one from the list is written out and another record
71 73 * read in to replace it. The new record is placed into the list.
72 74 * This continues until the list is empty.
73 75 * .call ret = mproc(pcbr).
74 76 * .arg pcbr - ptr to pcb for this process.
75 77 * .ret 0 - no errors in processing.
76 78 * .ret -1 - errors in processing (message already printed).
77 79 */
78 80 int
79 81 mproc(pcbr)
80 82 register audit_pcb_t *pcbr;
81 83 {
82 84 int i, ret, junk;
83 85 int nrecs = 0; /* number of records read from stream */
84 86 int nprecs = 0; /* number of records put to stream */
85 87 register audit_pcb_t *pcb;
86 88 audit_pcb_t *aget();
87 89 void asort();
88 90
89 91 #if AUDIT_PROC_TRACE
90 92 (void) fprintf(stderr, "mproc: count %d lo %d hi %d\n",
91 93 pcbr->pcb_count, pcbr->pcb_lo, pcbr->pcb_hi);
92 94 #endif
93 95
94 96 /*
95 97 * First load up a record from each input group.
96 98 */
97 99 for (i = pcbr->pcb_lo; i <= pcbr->pcb_hi; i++) {
98 100 pcb = &(pcbr->pcb_below[i]); /* get next PCB */
99 101 while (pcb->pcb_time < 0) { /* while no active record ... */
100 102 if ((ret = get_file(pcb)) == -1)
101 103 break; /* no files - finished PCB */
102 104 if (ret == -2)
103 105 return (-1); /* quit processing - failed */
104 106 if (get_recs(pcb, &nrecs) == 0)
105 107 asort(pcb); /* got a rec - put in list */
106 108 }
107 109 }
108 110 /*
109 111 * Now process all of the records.
110 112 */
111 113 while ((pcb = aget()) != NULL) { /* get oldest record */
112 114 if (write_recs(pcbr, pcb, &nprecs))
113 115 return (-1);
114 116 while (pcb->pcb_time < 0) { /* while we don't have a rec */
115 117 if (pcb->pcb_fpr == NULL) { /* no active file ... */
116 118 if ((ret = get_file(pcb)) == -1)
117 119 break; /* no files - finished pcb */
118 120 else if (ret == -2)
119 121 return (-1); /* quit - failed */
120 122 }
121 123 if (get_recs(pcb, &nrecs) == 0)
122 124 asort(pcb); /* put record in list */
123 125 }
124 126 }
125 127 /*
126 128 * For root: write outfile header if no records were encountered.
127 129 * For non-root: write trailer to pipe and close pipe.
128 130 */
129 131 if (pcbr->pcb_flags & PF_ROOT) {
130 132 if (nprecs == 0) {
131 133 if (write_header()) /* write header if no records */
132 134 return (-1);
133 135 }
134 136 } else {
135 137 pcb = &(pcbr->pcb_below[0]); /* any old PCB will do */
136 138 pcb->pcb_rec = empty_file_token;
137 139 if (write_recs(pcbr, pcb, &junk))
138 140 return (-1);
139 141 if (fclose(pcbr->pcb_fpw) == EOF) {
140 142 if (!f_quiet)
141 143 (void) fprintf(stderr,
142 144 gettext("%s couldn't close pipe.\n"), ar);
143 145 }
144 146 }
145 147 /*
146 148 * For root process tell how many records were written.
147 149 */
148 150 if (f_verbose && (pcbr->pcb_flags & PF_ROOT)) {
149 151 (void) fprintf(stderr,
150 152 gettext("%s %d record(s) total were written out.\n"),
151 153 ar, nprecs);
152 154 }
153 155 return (0);
154 156 }
155 157
156 158
157 159 /*
158 160 * Head of linked-list of pcbs - sorted by time - oldest first.
159 161 */
160 162 static audit_pcb_t *pcbls = NULL;
161 163
162 164 /*
163 165 * .func asort - audit sort.
164 166 * .desc Place a pcb in the list sorted by time - oldest first.
165 167 * .call asort(pcb);
166 168 * .arg pcb - ptr to pcb to install in list.
167 169 * .ret void.
168 170 */
169 171 static void
170 172 asort(pcb)
171 173 register audit_pcb_t *pcb;
172 174 {
173 175 register audit_pcb_t *pcbc, *pcbp;
174 176 extern audit_pcb_t *pcbls; /* ptr to start of list */
175 177
176 178 pcb->pcb_next = NULL;
177 179 if (pcbls == NULL) {
178 180 pcbls = pcb; /* empty list */
179 181 return;
180 182 }
181 183 pcbc = pcbls; /* current pcb */
182 184 pcbp = pcbls; /* previous pcb */
183 185 while (pcbc != NULL) {
184 186 if (pcb->pcb_time < pcbc->pcb_time) {
185 187 if (pcbp == pcbc) {
186 188 pcb->pcb_next = pcbls; /* new -> 1st in list */
187 189 pcbls = pcb;
188 190 return;
189 191 }
190 192 pcbp->pcb_next = pcb;
191 193 pcb->pcb_next = pcbc; /* new in the inside */
192 194 return;
193 195 }
194 196 pcbp = pcbc;
195 197 pcbc = pcbc->pcb_next;
196 198 }
197 199 pcbp->pcb_next = pcb; /* new -> last */
198 200 }
199 201
200 202
201 203 /*
202 204 * .func aget - audit get.
203 205 * .desc Get the first pcb from the list. Pcb is removed from list, too.
204 206 * .call pcb = aget().
205 207 * .arg none.
206 208 * .ret pcb - ptr to pcb that was the first.
207 209 */
208 210 static audit_pcb_t *
209 211 aget()
210 212 {
211 213 audit_pcb_t *pcbret;
212 214 extern audit_pcb_t *pcbls; /* ptr to start of list */
213 215
214 216 if (pcbls == NULL)
215 217 return (pcbls); /* empty list */
216 218 pcbret = pcbls;
217 219 pcbls = pcbls->pcb_next; /* 2nd becomes 1st */
218 220 return (pcbret);
219 221 }
220 222
221 223
222 224 /*
223 225 * .func get_file - get a new file.
224 226 * .desc Get the next file from the pcb's list. Check the header to see
225 227 * if the file really is an audit file. If there are no more then
226 228 * quit. If a file open (fopen) fails because the system file table
227 229 * is full or the process file table is full then quit processing
228 230 * altogether.
229 231 * .call ret = get_file(pcb).
230 232 * .arg pcb - pcb holding the fcb's (files).
231 233 * .ret 0 - new file opened for processing.
232 234 * .ret -1 - no more files - pcb finished.
233 235 * .ret -2 - fatal error - quit processing.
234 236 */
235 237 static int
236 238 get_file(pcb)
237 239 register audit_pcb_t *pcb;
238 240 {
239 241 FILE *fp;
240 242 audit_fcb_t *fcb;
241 243
242 244 /*
243 245 * Process file list until a good one if found or empty.
244 246 */
245 247 while (pcb->pcb_fpr == NULL) {
246 248 if ((fcb = pcb->pcb_first) == NULL) {
247 249 pcb->pcb_time = -1;
248 250 return (-1); /* pcb is all done */
249 251 } else {
250 252 /*
251 253 * If we are reading from files then open the next one.
252 254 */
253 255 if (!f_stdin) {
254 256 if ((fp = fopen(fcb->fcb_file, "r")) == NULL) {
255 257 if (!f_quiet) {
256 258 (void) sprintf(errbuf, gettext(
257 259 "%s couldn't open:\n %s"),
258 260 ar, fcb->fcb_file);
259 261 perror(errbuf);
260 262 }
261 263 /*
262 264 * See if file space is depleted.
263 265 * If it is then we quit.
264 266 */
265 267 if (errno == ENFILE || errno == EMFILE)
266 268 {
267 269 return (-2);
268 270 }
269 271 pcb->pcb_first = fcb->fcb_next;
270 272 continue; /* try another file */
271 273 }
272 274 } else {
273 275 /*
274 276 * Read from standard input.
275 277 */
276 278 fp = stdin;
277 279 }
278 280 /*
279 281 * Check header of audit file.
280 282 */
281 283 if (check_header(fp, fcb->fcb_name)) {
282 284 if (!f_quiet) {
283 285 (void) fprintf(stderr,
284 286 "%s %s:\n %s.\n",
285 287 ar, error_str, fcb->fcb_file);
286 288 }
287 289 if (fclose(fp) == EOF) {
288 290 if (!f_quiet) {
289 291 (void) fprintf(stderr, gettext(
290 292 "%s couldn't close %s.\n"),
291 293 ar, fcb->fcb_file);
292 294 }
293 295 }
294 296 pcb->pcb_first = fcb->fcb_next;
295 297 continue; /* try another file */
296 298 }
297 299 /*
298 300 * Found a good audit file.
299 301 * Initalize pcb for processing.
300 302 */
301 303 pcb->pcb_first = fcb->fcb_next;
302 304 pcb->pcb_cur = fcb;
303 305 pcb->pcb_fpr = fp;
304 306 pcb->pcb_nrecs = 0;
305 307 pcb->pcb_nprecs = 0;
306 308 pcb->pcb_otime = -1;
307 309 }
308 310 }
309 311 return (0);
310 312 }
311 313
312 314
313 315 /*
314 316 * .func write_recs - write records.
315 317 * .desc Write record from a buffer to output stream. Keep an eye out
316 318 * for the first and last records of the root's output stream.
317 319 * .call ret = write_recs(pcbr, pcb, nprecs).
318 320 * .arg pcbr - ptr to node pcb.
319 321 * .arg pcb - ptr to pcb holding the stream.
320 322 * .arg nprecs - ptr to the number of put records. Updated here.
321 323 * .ret 0 - no errors detected.
322 324 * .ret -1 - error in writing. Quit processing.
323 325 */
324 326 static int
325 327 write_recs(pcbr, pcb, nprecs)
326 328 register audit_pcb_t *pcbr, *pcb;
327 329 int *nprecs;
328 330 {
329 331 adr_t adr;
330 332 char id;
331 333 int32_t size;
332 334
333 335 adrm_start(&adr, pcb->pcb_rec);
334 336 (void) adrm_char(&adr, &id, 1);
335 337 (void) adrm_int32(&adr, &size, 1);
336 338
337 339 /*
338 340 * Scan for first record to be written to outfile.
339 341 * When we find it then write the header and
340 342 * save the time for the outfile name.
341 343 */
342 344 if ((*nprecs)++ == 0) {
343 345 if (pcbr->pcb_flags & PF_ROOT) {
344 346 f_start = pcb->pcb_time; /* save start time */
345 347 if (write_header())
346 348 return (-1);
347 349 }
348 350 }
349 351 f_end = pcb->pcb_time; /* find last record's time */
350 352 pcb->pcb_time = -1; /* disable just written rec */
351 353
352 354 if ((fwrite(pcb->pcb_rec, sizeof (char), size, pcbr->pcb_fpw)) !=
353 355 size) {
354 356 if (pcbr->pcb_flags & PF_ROOT) {
355 357 (void) sprintf(errbuf, gettext(
356 358 "%s write failed to %s"),
357 359 ar, f_outfile ? f_outfile : gettext("stdout"));
358 360 perror(errbuf);
359 361 } else {
360 362 perror(gettext("auditreduce: write failed to pipe"));
361 363 }
362 364 return (-1);
363 365 }
364 366 free(pcb->pcb_rec);
365 367 return (0);
366 368 }
367 369
368 370 /*
369 371 * .func get_recs - get records.
370 372 * .desc Get records from a stream until one passing the current selection
371 373 * criteria is found or the stream is emptied.
372 374 * .call ret = get_recs(pcb, nr).
373 375 * .arg pcb - ptr to pcb that holds this stream.
374 376 * .arg nr - ptr to number of records read. Updated by this routine.
375 377 * .ret 0 - got a record.
376 378 * .ret -1 - stream is finished.
377 379 */
378 380 static int
379 381 get_recs(pcb, nr)
380 382 register audit_pcb_t *pcb;
381 383 int *nr;
382 384 {
383 385 adr_t adr;
384 386 time_t secs;
385 387 int tmp;
386 388 int ret, ret2;
387 389 int nrecs = 0; /* count how many records read this call */
388 390 int getrec = TRUE;
389 391 int alldone = FALSE;
390 392 char header_type;
391 393 short e;
392 394 char *str;
393 395 #if AUDIT_FILE
394 396 static void get_trace();
395 397 #endif
396 398
397 399 while (getrec) {
398 400 ret = get_record(pcb->pcb_fpr, &pcb->pcb_rec,
399 401 pcb->pcb_cur->fcb_name);
400 402 if (ret > 0) {
401 403 adrm_start(&adr, pcb->pcb_rec);
402 404
403 405 /* get token id */
404 406 (void) adrm_char(&adr, (char *)&header_type, 1);
405 407 /* skip over byte count */
406 408 (void) adrm_int32(&adr, (int32_t *)&tmp, 1);
407 409 /* skip over version # */
408 410 (void) adrm_char(&adr, (char *)&tmp, 1);
409 411 /* skip over event id */
410 412 (void) adrm_short(&adr, (short *)&e, 1);
411 413 /* skip over event id modifier */
412 414 (void) adrm_short(&adr, (short *)&tmp, 1);
413 415
414 416 if (header_type == AUT_HEADER32) {
415 417 int32_t s, m;
416 418
417 419 /* get seconds */
418 420 (void) adrm_int32(&adr, (int32_t *)&s, 1);
419 421 /* get microseconds */
420 422 (void) adrm_int32(&adr, (int32_t *)&m, 1);
421 423 secs = (time_t)s;
422 424 } else if (header_type == AUT_HEADER32_EX) {
423 425 int32_t s, m;
424 426 int32_t t, junk[4]; /* at_type + at_addr[4] */
425 427
426 428 /* skip type and ip address field */
427 429 (void) adrm_int32(&adr, (int32_t *)&t, 1);
428 430 (void) adrm_int32(&adr, (int32_t *)&junk[0], t/4);
429 431
430 432 /* get seconds */
431 433 (void) adrm_int32(&adr, (int32_t *)&s, 1);
432 434 /* get microseconds */
433 435 (void) adrm_int32(&adr, (int32_t *)&m, 1);
434 436 secs = (time_t)s;
435 437 } else if (header_type == AUT_HEADER64) {
436 438 int64_t s, m;
437 439
438 440 /* get seconds */
439 441 (void) adrm_int64(&adr, (int64_t *)&s, 1);
440 442 /* get microseconds */
441 443 (void) adrm_int64(&adr, (int64_t *)&m, 1);
442 444 #if ((!defined(_LP64)) || defined(_SYSCALL32))
443 445 if (s < (time_t)INT32_MIN ||
444 446 s > (time_t)INT32_MAX)
445 447 secs = 0;
446 448 else
447 449 secs = (time_t)s;
448 450 #else
449 451 secs = (time_t)s;
450 452 #endif
451 453 } else if (header_type == AUT_HEADER64_EX) {
452 454 int64_t s, m;
453 455 int32_t t, junk[4];
454 456
455 457 /* skip type and ip address field */
456 458 (void) adrm_int32(&adr, (int32_t *)&t, 1);
457 459 (void) adrm_int32(&adr, (int32_t *)&junk[0], t/4);
458 460
459 461 /* get seconds */
460 462 (void) adrm_int64(&adr, (int64_t *)&s, 1);
461 463 /* get microseconds */
462 464 (void) adrm_int64(&adr, (int64_t *)&m, 1);
463 465 #if ((!defined(_LP64)) || defined(_SYSCALL32))
464 466 if (s < (time_t)INT32_MIN ||
465 467 s > (time_t)INT32_MAX)
466 468 secs = 0;
467 469 else
468 470 secs = (time_t)s;
469 471 #else
470 472 secs = (time_t)s;
471 473 #endif
472 474 }
473 475 }
474 476
475 477 #if AUDIT_REC
476 478 (void) fprintf(stderr, "get_recs: %d ret %d recno %d\n",
477 479 pcb->pcb_procno, ret, pcb->pcb_nrecs + 1);
478 480 #endif
479 481 /*
480 482 * See if entire file is after the time window specified.
481 483 * Must be check here because the start time of the file name
482 484 * may be after the first record(s).
483 485 */
484 486 if (pcb->pcb_nrecs == 0 && (pcb->pcb_flags & PF_USEFILE)) {
485 487 /*
486 488 * If the first record read failed then use the time
487 489 * that was in the filename to judge.
488 490 */
489 491 if (ret > 0)
490 492 (pcb->pcb_cur)->fcb_start = secs;
491 493 if (!f_all && (m_before <= (pcb->pcb_cur)->fcb_start)) {
492 494 (void) fclose(pcb->pcb_fpr); /* ignore file */
493 495 pcb->pcb_fpr = NULL;
494 496 pcb->pcb_time = -1;
495 497 return (-1);
496 498 } else {
497 499 /* Give belated announcement of file opening. */
498 500 if (f_verbose) {
499 501 (void) fprintf(stderr,
500 502 gettext("%s opened:\n %s.\n"),
501 503 ar, (pcb->pcb_cur)->fcb_file);
502 504 }
503 505 }
504 506 }
505 507 /* Succesful acquisition of a record. */
506 508 if (ret > 0) {
507 509 pcb->pcb_time = secs; /* time of record */
508 510 pcb->pcb_nrecs++; /* # of read recs from stream */
509 511 nrecs++; /* # of recs read this call */
510 512 /* Only check record if at bottom of process tree. */
511 513 if (pcb->pcb_flags & PF_USEFILE) {
512 514 check_order(pcb); /* check time sequence */
513 515 if ((ret2 = check_rec(pcb)) == 0) {
514 516 pcb->pcb_nprecs++;
515 517 getrec = FALSE;
516 518 } else if (ret2 == -2) {
517 519 /* error */
518 520 getrec = FALSE; /* get no more recs */
519 521 alldone = TRUE; /* quit this file */
520 522 free(pcb->pcb_rec);
521 523 } else {
522 524 /* -1: record not interesting */
523 525 free(pcb->pcb_rec);
524 526 }
525 527 } else {
526 528 pcb->pcb_nprecs++;
527 529 getrec = FALSE;
528 530 }
529 531 } else {
530 532 /* Error with record read or all done with stream. */
531 533 getrec = FALSE;
532 534 alldone = TRUE;
533 535 }
534 536 }
535 537 if (alldone == TRUE) {
536 538 #if AUDIT_FILE
537 539 get_trace(pcb);
538 540 #endif
539 541 /* Error in record read. Display messages. */
540 542 if (ret < 0 || ret2 == -2) {
541 543 pcb->pcb_nrecs++; /* # of read records */
542 544 if (!f_quiet) {
543 545 if (pcb->pcb_flags & PF_USEFILE) {
544 546 /* Ignore if this is not_terminated. */
545 547 if (!strstr((pcb->pcb_cur)->fcb_file,
546 548 "not_terminated")) {
547 549 (void) fprintf(stderr, gettext("%s read error in %s at record %d.\n"), ar,
548 550 (pcb->pcb_cur)->fcb_file, pcb->pcb_nrecs);
549 551 }
550 552 } else {
551 553 (void) fprintf(stderr, gettext("%s read error in pipe at record %d.\n"), ar,
552 554 pcb->pcb_nrecs);
553 555 }
554 556 }
555 557 } else {
556 558 /*
557 559 * Only mark infile for deleting if we have succesfully
558 560 * processed all of it.
559 561 */
560 562 if (pcb->pcb_flags & PF_USEFILE)
561 563 (pcb->pcb_cur)->fcb_flags |= FF_DELETE;
562 564 }
563 565 if (fclose(pcb->pcb_fpr) == EOF) {
564 566 if (!f_quiet) {
565 567 if (pcb->pcb_flags & PF_USEFILE) {
566 568 str = (pcb->pcb_cur)->fcb_file;
567 569 } else {
568 570 str = "pipe";
569 571 }
570 572 (void) fprintf(stderr,
571 573 gettext("%s couldn't close %s.\n"),
572 574 ar, str);
573 575 }
574 576 }
575 577 pcb->pcb_fpr = NULL;
576 578 pcb->pcb_time = -1;
577 579 *nr += nrecs;
578 580 return (-1);
579 581 }
580 582 *nr += nrecs;
581 583 return (0);
582 584 }
583 585
584 586
585 587 #if AUDIT_FILE
586 588 /*
587 589 * .func get_trace - get trace.
588 590 * .desc If we are tracing file action (AUDIT_FILE is on) then print out
589 591 * a message when the file is closed regarding how many records
590 592 * were handled.
591 593 * .call get_trace(pcb).
592 594 * .arg pcb - ptr to pcb holding file/pipe.
593 595 * .ret void.
594 596 */
595 597 static void
596 598 get_trace(pcb)
597 599 audit_pcb_t *pcb;
598 600 {
599 601 /*
600 602 * For file give filename, too.
601 603 */
602 604 if (pcb->pcb_flags & PF_USEFILE) {
603 605 (void) fprintf(stderr, "%s closed %s: %d records read recs: \
604 606 %d record written.\n", ar, (pcb->pcb_cur)->fcb_file,
605 607 pcb->pcb_nrecs, pcb->pcb_nprecs);
606 608 } else {
607 609 (void) fprintf(stderr, "%s closed pipe: %d records read: \
608 610 %d records written .\n", ar, pcb->pcb_nrecs,
609 611 pcb->pcb_nprecs);
610 612 }
611 613 }
612 614
613 615 #endif
614 616
615 617 /*
616 618 * .func check_rec - check a record.
617 619 * .desc Check a record against the user's selection criteria.
618 620 * .call ret = check_rec(pcb).
619 621 * .arg pcb - ptr to pcb holding the record.
620 622 * .ret 0 - record accepted.
621 623 * .ret -1 - record rejected - continue processing file.
622 624 * .ret -2 - record rejected - quit processing file.
623 625 */
624 626 static int
625 627 check_rec(pcb)
626 628 register audit_pcb_t *pcb;
627 629 {
628 630 adr_t adr;
629 631 struct timeval tv;
630 632 uint_t bytes;
631 633 au_emod_t id_modifier;
632 634 char version;
633 635 au_event_t event_type;
634 636 char tokenid;
635 637 int rc; /* return code */
636 638
637 639 adrm_start(&adr, pcb->pcb_rec);
638 640 (void) adrm_char(&adr, &tokenid, 1);
639 641
640 642 /*
641 643 * checkflags will be my data structure for determining if
642 644 * a record has met ALL the selection criteria. Once
643 645 * checkflags == flags, we have seen all we need to of the
644 646 * record, and can go to the next one. If when we finish
645 647 * processing the record we still have stuff to see,
646 648 * checkflags != flags, and thus we should return a -1
647 649 * from this function meaning reject this record.
648 650 */
649 651
650 652 checkflags = 0;
651 653
652 654 /* must be header token -- sanity check */
653 655 if (tokenid != AUT_HEADER32 && tokenid != AUT_HEADER64 &&
654 656 tokenid != AUT_HEADER32_EX && tokenid != AUT_HEADER64_EX) {
655 657 #if AUDIT_REC
656 658 (void) fprintf(stderr,
657 659 "check_rec: %d recno %d no header %d found\n",
658 660 pcb->pcb_procno, pcb->pcb_nrecs, tokenid);
659 661 #endif
660 662 return (-2);
661 663 }
662 664
663 665 /*
664 666 * The header token is:
665 667 * attribute id: char
666 668 * byte count: int
667 669 * version #: char
668 670 * event ID: short
669 671 * ID modifier: short
670 672 * seconds (date): int
671 673 * time (microsecs): int
672 674 */
673 675 (void) adrm_u_int32(&adr, (uint32_t *)&bytes, 1);
674 676 (void) adrm_char(&adr, &version, 1);
675 677 (void) adrm_u_short(&adr, &event_type, 1);
676 678
677 679 /*
678 680 * Used by s5_IPC_token to set the ipc_type so
679 681 * s5_IPC_perm_token can test.
680 682 */
681 683 ipc_type = (char)0;
682 684
683 685 if (flags & M_TYPE) {
684 686 checkflags |= M_TYPE;
685 687 if (m_type != event_type)
686 688 return (-1);
687 689 }
688 690 if (flags & M_CLASS) {
689 691 au_event_ent_t *ev = NULL;
690 692
691 693 checkflags |= M_CLASS;
692 694 if (cacheauevent(&ev, event_type) <= 0) {
693 695 (void) fprintf(stderr, gettext(
694 696 "Warning: invalid event no %d in audit trail."),
695 697 event_type);
696 698 return (-1);
697 699 }
698 700 global_class = ev->ae_class;
699 701 if (!(flags & M_SORF) && !(mask.am_success & global_class))
700 702 return (-1);
701 703 }
702 704
703 705 (void) adrm_u_short(&adr, &id_modifier, 1);
704 706
705 707 /*
706 708 * Check record against time criteria.
707 709 * If the 'A' option was used then no time checking is done.
708 710 * The 'a' parameter is inclusive and the 'b' exclusive.
709 711 */
710 712 if (tokenid == AUT_HEADER32) {
711 713 int32_t secs, msecs;
712 714 (void) adrm_int32(&adr, (int32_t *)&secs, 1);
713 715 (void) adrm_int32(&adr, (int32_t *)&msecs, 1);
714 716 tv.tv_sec = (time_t)secs;
715 717 tv.tv_usec = (suseconds_t)msecs;
716 718 } else if (tokenid == AUT_HEADER32_EX) {
717 719 int32_t secs, msecs;
718 720 int32_t t, junk[5]; /* at_type + at_addr[4] */
719 721 /* skip type and ip address field */
720 722 (void) adrm_int32(&adr, (int32_t *)&t, 1);
721 723 (void) adrm_int32(&adr, (int32_t *)&junk[0], t/4);
722 724 /* get time */
723 725 (void) adrm_int32(&adr, (int32_t *)&secs, 1);
724 726 (void) adrm_int32(&adr, (int32_t *)&msecs, 1);
725 727 tv.tv_sec = (time_t)secs;
726 728 tv.tv_usec = (suseconds_t)msecs;
727 729 } else if (tokenid == AUT_HEADER64) {
728 730 int64_t secs, msecs;
729 731 (void) adrm_int64(&adr, (int64_t *)&secs, 1);
730 732 (void) adrm_int64(&adr, (int64_t *)&msecs, 1);
731 733 #if ((!defined(_LP64)) || defined(_SYSCALL32))
732 734 if (secs < (time_t)INT32_MIN ||
733 735 secs > (time_t)INT32_MAX)
734 736 tv.tv_sec = 0;
735 737 else
736 738 tv.tv_sec = (time_t)secs;
737 739 if (msecs < (suseconds_t)INT32_MIN ||
738 740 msecs > (suseconds_t)INT32_MAX)
739 741 tv.tv_usec = 0;
740 742 else
741 743 tv.tv_usec = (suseconds_t)msecs;
742 744 #else
743 745 tv.tv_sec = (time_t)secs;
744 746 tv.tv_usec = (suseconds_t)msecs;
745 747 #endif
746 748 } else if (tokenid == AUT_HEADER64_EX) {
747 749 int64_t secs, msecs;
748 750 int32_t t, junk[4]; /* at_type + at_addr[4] */
749 751 /* skip type and ip address field */
750 752 (void) adrm_int32(&adr, (int32_t *)&t, 1);
751 753 (void) adrm_int32(&adr, (int32_t *)&junk[0], t/4);
752 754 /* get time */
753 755 (void) adrm_int64(&adr, (int64_t *)&secs, 1);
754 756 (void) adrm_int64(&adr, (int64_t *)&msecs, 1);
755 757 #if ((!defined(_LP64)) || defined(_SYSCALL32))
756 758 if (secs < (time_t)INT32_MIN ||
757 759 secs > (time_t)INT32_MAX)
758 760 tv.tv_sec = 0;
759 761 else
760 762 tv.tv_sec = (time_t)secs;
761 763 if (msecs < (suseconds_t)INT32_MIN ||
762 764 msecs > (suseconds_t)INT32_MAX)
763 765 tv.tv_usec = 0;
764 766 else
765 767 tv.tv_usec = (suseconds_t)msecs;
766 768 #else
767 769 tv.tv_sec = (time_t)secs;
768 770 tv.tv_usec = (suseconds_t)msecs;
769 771 #endif
770 772 }
771 773 pcb->pcb_otime = pcb->pcb_time;
772 774 if (!f_all) {
773 775 if (m_after > tv.tv_sec)
774 776 return (-1);
775 777 if (m_before <= tv.tv_sec)
776 778 return (-1);
777 779 }
778 780
779 781 /* if no selection flags were passed, select everything */
780 782 if (!flags)
781 783 return (0);
782 784
783 785 /*
784 786 * If all information can be found in header,
785 787 * there is no need to continue processing the tokens.
786 788 */
787 789 if (flags == checkflags)
788 790 return (0);
789 791
790 792 /*
791 793 * Process tokens until we hit the end of the record
792 794 */
793 795 while ((uint_t)(adr.adr_now - adr.adr_stream) < bytes) {
794 796 adrm_char(&adr, &tokenid, 1);
795 797 rc = token_processing(&adr, tokenid);
796 798
797 799 /* Any Problems? */
798 800 if (rc == -2) {
799 801 (void) fprintf(stderr,
|
↓ open down ↓ |
766 lines elided |
↑ open up ↑ |
800 802 gettext("auditreduce: bad token %u, terminating "
801 803 "file %s\n"), tokenid, (pcb->pcb_cur)->fcb_file);
802 804 return (-2);
803 805 }
804 806
805 807 /* Are we finished? */
806 808 if (flags == checkflags)
807 809 return (0);
808 810 }
809 811
812 + /* let PAD_FAILURE satisfy success/failure selection */
813 + if ((flags & M_SORF) != 0 && (checkflags & M_SORF) == 0 &&
814 + (((global_class & mask.am_success) != 0 &&
815 + (id_modifier & PAD_FAILURE) == 0) ||
816 + ((global_class & mask.am_failure) != 0 &&
817 + (id_modifier & PAD_FAILURE) != 0))) {
818 + checkflags |= M_SORF;
819 + }
820 +
821 +
810 822 /*
811 - * So, we haven't seen all that we need to see. Reject record.
823 + * If we haven't seen all that we need to see, reject the record.
812 824 */
813 825
814 - return (-1);
826 + return ((checkflags == flags) ? 0 : -1);
815 827 }
816 828
817 829
818 830 /*
819 831 * .func check_order - Check temporal sequence.
820 832 * .call check_order(pcb).
821 833 * .arg pcb - ptr to audit_pcb_t.
822 834 * .desc Check to see if the records are out of temporal sequence, ie,
823 835 * a record has a time stamp older than its predecessor.
824 836 * Also check to see if the current record is within the bounds of
825 837 * the file itself.
826 838 * This routine prints a diagnostic message, unless the QUIET
827 839 * option was selected.
828 840 * .call check_order(pcb).
829 841 * .arg pcb - ptr to pcb holding the records.
830 842 * .ret void.
831 843 */
832 844 static void
833 845 check_order(pcb)
834 846 register audit_pcb_t *pcb;
835 847 {
836 848 char cptr1[28], cptr2[28]; /* for error reporting */
837 849
838 850 /*
839 851 * If the record-past is not the oldest then say so.
840 852 */
841 853 if (pcb->pcb_otime > pcb->pcb_time) {
842 854 if (!f_quiet) {
843 855 (void) memcpy((void *)cptr1,
844 856 (void *)ctime(&pcb->pcb_otime), 26);
845 857 cptr1[24] = ' ';
846 858 (void) memcpy((void *)cptr2,
847 859 (void *)ctime(&pcb->pcb_time), 26);
848 860 cptr2[24] = ' ';
849 861 (void) fprintf(stderr,
850 862 gettext("%s %s had records out of order: %s was followed by %s.\n"),
851 863 ar, (pcb->pcb_cur)->fcb_file, cptr1, cptr2);
852 864 }
853 865 }
854 866 }
855 867
856 868
857 869 /*
858 870 * .func check_header.
859 871 * .desc Read in and check the header for an audit file.
860 872 * The header must read-in properly and have the magic #.
861 873 * .call err = check_header(fp).
862 874 * .arg fp - file stream.
863 875 * .ret 0 no problems.
864 876 * .ret -1 problems.
865 877 */
866 878 static int
867 879 check_header(fp, fn)
868 880 FILE *fp;
869 881 char *fn;
870 882 {
871 883 char id;
872 884 char *fname;
873 885 short pathlength;
874 886 adr_t adr;
875 887 adrf_t adrf;
876 888
877 889 adrf_start(&adrf, &adr, fp);
878 890
879 891 if (adrf_char(&adrf, &id, 1)) {
880 892 (void) sprintf(errbuf, gettext("%s is empty"), fn);
881 893 error_str = errbuf;
882 894 return (-1);
883 895 }
884 896 if (!(id == AUT_OTHER_FILE32 || id == AUT_OTHER_FILE64)) {
885 897 (void) sprintf(errbuf, gettext("%s not an audit file "), fn);
886 898 error_str = errbuf;
887 899 return (-1);
888 900 }
889 901
890 902 if (id == AUT_OTHER_FILE32) {
891 903 int32_t secs, msecs;
892 904 (void) adrf_int32(&adrf, (int32_t *)&secs, 1);
893 905 (void) adrf_int32(&adrf, (int32_t *)&msecs, 1);
894 906 } else {
895 907 int64_t secs, msecs;
896 908 (void) adrf_int64(&adrf, (int64_t *)&secs, 1);
897 909 (void) adrf_int64(&adrf, (int64_t *)&msecs, 1);
898 910 #if ((!defined(_LP64)) || defined(_SYSCALL32))
899 911 if (secs < (time_t)INT32_MIN ||
900 912 secs > (time_t)INT32_MAX) {
901 913 error_str = gettext("bad time stamp in file header");
902 914 return (-1);
903 915 }
904 916 if (msecs < (suseconds_t)INT32_MIN ||
905 917 msecs > (suseconds_t)INT32_MAX) {
906 918 error_str = gettext("bad time stamp in file header");
907 919 return (-1);
908 920 }
909 921 #endif
910 922 }
911 923
912 924 if (adrf_short(&adrf, &pathlength, 1)) {
913 925 error_str = gettext("incomplete file header");
914 926 return (-1);
915 927 }
916 928
917 929 if (pathlength != 0) {
918 930 fname = (char *)a_calloc(1, (size_t)pathlength);
919 931 if ((fread(fname, sizeof (char), pathlength, fp)) !=
920 932 pathlength) {
921 933 (void) sprintf(errbuf,
922 934 gettext("error in header/filename read in %s"),
923 935 fn);
924 936 error_str = errbuf;
925 937 return (-1);
926 938 }
927 939 free(fname);
928 940 }
929 941 return (0);
930 942 }
931 943
932 944
933 945 /*
934 946 * .func get_record - get a single record.
935 947 * .desc Read a single record from stream fp. If the record to be read
936 948 * is larger than the buffer given to hold it (as determined by
937 949 * cur_size) then free that buffer and allocate a new and bigger
938 950 * one, making sure to store its size.
939 951 * .call ret = get_record(fp, buf, cur_size, flags).
940 952 * .arg fp - stream to read from.
941 953 * .arg buf - ptr to ptr to buffer to place record in.
942 954 * .arg cur_size- ptr to the size of the buffer that *buf points to.
943 955 * .arg flags - flags from fcb (to get FF_NOTTERM).
944 956 * .ret +number - number of chars in the record.
945 957 * .ret 0 - trailer seen - file done.
946 958 * .ret -1 - read error (error_str know what type).
947 959 */
948 960 static int
949 961 get_record(fp, buf, fn)
950 962 FILE *fp;
951 963 char **buf;
952 964 char *fn;
953 965 {
954 966 adr_t adr;
955 967 adrf_t adrf;
956 968 int leadin;
957 969 char id;
958 970 int lsize;
959 971 short ssize;
960 972
961 973 /*
962 974 * Get the token type. It will be either a header or a file
963 975 * token.
964 976 */
965 977 (void) adrf_start(&adrf, &adr, fp);
966 978 if (adrf_char(&adrf, &id, 1)) {
967 979 (void) sprintf(errbuf, gettext(
968 980 "record expected but not found in %s"),
969 981 fn);
970 982 error_str = errbuf;
971 983 return (-1);
972 984 }
973 985 switch (id) {
974 986 case AUT_HEADER32:
975 987 case AUT_HEADER32_EX:
976 988 case AUT_HEADER64:
977 989 case AUT_HEADER64_EX:
978 990 /*
979 991 * The header token is:
980 992 * attribute id: char
981 993 * byte count: int
982 994 * version #: char
983 995 * event ID: short
984 996 * ID modifier: short
985 997 * IP address type int (_EX only)
986 998 * IP address 1/4*int (_EX only)
987 999 * seconds (date): long
988 1000 * time (microsecs): long
989 1001 */
990 1002 leadin = sizeof (int32_t) + sizeof (char);
991 1003 (void) adrf_int32(&adrf, &lsize, 1);
992 1004 *buf = (char *)a_calloc(1, (size_t)(lsize + leadin));
993 1005 adr_start(&adr, *buf);
994 1006 adr_char(&adr, &id, 1);
995 1007 adr_int32(&adr, (int32_t *)&lsize, 1);
996 1008 if (fread(*buf + leadin, sizeof (char), lsize - leadin, fp) !=
997 1009 lsize - leadin) {
998 1010 (void) sprintf(errbuf,
999 1011 gettext("header token read failure in %s"), fn);
1000 1012 error_str = errbuf;
1001 1013 return (-1);
1002 1014 }
1003 1015 return (lsize + leadin);
1004 1016 case AUT_OTHER_FILE32: {
1005 1017 int32_t secs, msecs;
1006 1018 leadin = 2 * sizeof (int32_t) +
1007 1019 sizeof (short) + sizeof (char);
1008 1020 (void) adrf_int32(&adrf, (int32_t *)&secs, 1);
1009 1021 (void) adrf_int32(&adrf, (int32_t *)&msecs, 1);
1010 1022 (void) adrf_short(&adrf, &ssize, 1);
1011 1023 *buf = (char *)a_calloc(1, (size_t)(ssize + leadin));
1012 1024 adr_start(&adr, *buf);
1013 1025 adr_char(&adr, &id, 1);
1014 1026 adr_int32(&adr, (int32_t *)&secs, 1);
1015 1027 adr_int32(&adr, (int32_t *)&msecs, 1);
1016 1028 adr_short(&adr, &ssize, 1);
1017 1029 if (fread(*buf + leadin, sizeof (char), ssize, fp) != ssize) {
1018 1030 error_str = gettext("file token read failure");
1019 1031 return (-1);
1020 1032 }
1021 1033 return (0); /* done! */
1022 1034 }
1023 1035 case AUT_OTHER_FILE64: {
1024 1036 int64_t secs, msecs;
1025 1037 leadin = 2 * sizeof (int64_t) +
1026 1038 sizeof (short) + sizeof (char);
1027 1039 (void) adrf_int64(&adrf, (int64_t *)&secs, 1);
1028 1040 (void) adrf_int64(&adrf, (int64_t *)&msecs, 1);
1029 1041 (void) adrf_short(&adrf, &ssize, 1);
1030 1042 *buf = (char *)a_calloc(1, (size_t)(ssize + leadin));
1031 1043 adr_start(&adr, *buf);
1032 1044 adr_char(&adr, &id, 1);
1033 1045 adr_int64(&adr, (int64_t *)&secs, 1);
1034 1046 adr_int64(&adr, (int64_t *)&msecs, 1);
1035 1047 adr_short(&adr, &ssize, 1);
1036 1048 if (fread(*buf + leadin, sizeof (char), ssize, fp) != ssize) {
1037 1049 error_str = gettext("file token read failure");
1038 1050 return (-1);
1039 1051 }
1040 1052 return (0); /* done! */
1041 1053 }
1042 1054 default:
1043 1055 break;
1044 1056 }
1045 1057 error_str = gettext("record begins without proper token");
1046 1058 return (-1);
1047 1059 }
|
↓ open down ↓ |
223 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX