17c478bd9Sstevel@tonic-gate#
287e895dbStz# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate# Use is subject to license terms.
47c478bd9Sstevel@tonic-gate#
57c478bd9Sstevel@tonic-gate# CDDL HEADER START
67c478bd9Sstevel@tonic-gate#
77c478bd9Sstevel@tonic-gate# The contents of this file are subject to the terms of the
887e895dbStz# Common Development and Distribution License (the "License").
987e895dbStz# You may not use this file except in compliance with the License.
107c478bd9Sstevel@tonic-gate#
117c478bd9Sstevel@tonic-gate# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
127c478bd9Sstevel@tonic-gate# or http://www.opensolaris.org/os/licensing.
137c478bd9Sstevel@tonic-gate# See the License for the specific language governing permissions
147c478bd9Sstevel@tonic-gate# and limitations under the License.
157c478bd9Sstevel@tonic-gate#
167c478bd9Sstevel@tonic-gate# When distributing Covered Code, include this CDDL HEADER in each
177c478bd9Sstevel@tonic-gate# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
187c478bd9Sstevel@tonic-gate# If applicable, add the following below this CDDL HEADER, with the
197c478bd9Sstevel@tonic-gate# fields enclosed by brackets "[]" replaced with your own identifying
207c478bd9Sstevel@tonic-gate# information: Portions Copyright [yyyy] [name of copyright owner]
217c478bd9Sstevel@tonic-gate#
227c478bd9Sstevel@tonic-gate# CDDL HEADER END
237c478bd9Sstevel@tonic-gate#
247c478bd9Sstevel@tonic-gate# ident	"%Z%%M%	%I%	%E% SMI"
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate# WARNING -- this package implements a Sun private interface; it may
277c478bd9Sstevel@tonic-gate# change without notice.
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gatepackage Sun::Solaris::BSM::_BSMparse;
307c478bd9Sstevel@tonic-gaterequire 5.005;
317c478bd9Sstevel@tonic-gateuse strict;
327c478bd9Sstevel@tonic-gateuse Exporter;
337c478bd9Sstevel@tonic-gateuse Sun::Solaris::Utils qw(gettext);
347c478bd9Sstevel@tonic-gate
357c478bd9Sstevel@tonic-gateuse vars qw($VERSION $failedOpen
367c478bd9Sstevel@tonic-gate    %EXPORT_TAGS @ISA @EXPORT_OK @EXPORT_FAIL);
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate$VERSION = '1.01';
397c478bd9Sstevel@tonic-gate
407c478bd9Sstevel@tonic-gate@ISA = qw(Exporter);
417c478bd9Sstevel@tonic-gatemy @constants = qw();
427c478bd9Sstevel@tonic-gate@EXPORT_OK = qw(readAttr readEvent readClass filterLabel filterCallName
437c478bd9Sstevel@tonic-gate		readControl getPathList readUser ckAttrEvent);
447c478bd9Sstevel@tonic-gate@EXPORT_FAIL = qw($failedOpen);
457c478bd9Sstevel@tonic-gate%EXPORT_TAGS = (ALL => \@EXPORT_OK);
467c478bd9Sstevel@tonic-gate
477c478bd9Sstevel@tonic-gate$failedOpen = gettext("failed to open %s: %s");
487c478bd9Sstevel@tonic-gate
497c478bd9Sstevel@tonic-gatesub new {
507c478bd9Sstevel@tonic-gate	my $obj = shift;
517c478bd9Sstevel@tonic-gate	my $debug = shift;	# bool
527c478bd9Sstevel@tonic-gate	my $filters = shift;	# options for filtering
537c478bd9Sstevel@tonic-gate
547c478bd9Sstevel@tonic-gate	my $dir = '/etc/security';
55*1b5f7228Stz	my $attrDir = '/usr/lib/audit';
567c478bd9Sstevel@tonic-gate        my $configDir = $dir;
577c478bd9Sstevel@tonic-gate	$attrDir = shift if (@_);	# override for test
587c478bd9Sstevel@tonic-gate	$configDir = shift if (@_);	# ditto
597c478bd9Sstevel@tonic-gate
607c478bd9Sstevel@tonic-gate	my $suffix = '';
617c478bd9Sstevel@tonic-gate	$suffix = shift if (@_);	# test, again
627c478bd9Sstevel@tonic-gate
637c478bd9Sstevel@tonic-gate	$obj = ref($obj) || $obj;
647c478bd9Sstevel@tonic-gate
657c478bd9Sstevel@tonic-gate	my ($recordf, $classf, $controlf, $eventf, $userf) =
667c478bd9Sstevel@tonic-gate	   ("$attrDir/audit_record_attr$suffix",
677c478bd9Sstevel@tonic-gate	    "$configDir/audit_class$suffix",
687c478bd9Sstevel@tonic-gate	    "$configDir/audit_control$suffix",
697c478bd9Sstevel@tonic-gate	    "$configDir/audit_event$suffix",
707c478bd9Sstevel@tonic-gate	    "$configDir/audit_user$suffix");
717c478bd9Sstevel@tonic-gate
727c478bd9Sstevel@tonic-gate	return (bless {
737c478bd9Sstevel@tonic-gate		'attrFile'	=> $recordf,
747c478bd9Sstevel@tonic-gate		'classFile'	=> $classf,
757c478bd9Sstevel@tonic-gate		'classFilter'	=> $filters->{'classFilter'},
767c478bd9Sstevel@tonic-gate		'controlFile'	=> $controlf,
777c478bd9Sstevel@tonic-gate		'debug'		=> $debug,
787c478bd9Sstevel@tonic-gate		'eventFile'	=> $eventf,
797c478bd9Sstevel@tonic-gate		'eventFilter'	=> $filters->{'eventFilter'},
807c478bd9Sstevel@tonic-gate		'idFilter'	=> $filters->{'idFilter'},
817c478bd9Sstevel@tonic-gate		'havePath'	=> 0,
827c478bd9Sstevel@tonic-gate		'kernelDefault'	=> '',
837c478bd9Sstevel@tonic-gate		'userDefault'	=> '',
847c478bd9Sstevel@tonic-gate		'userFile'	=> $userf}, $obj);
857c478bd9Sstevel@tonic-gate}
867c478bd9Sstevel@tonic-gate
877c478bd9Sstevel@tonic-gate# readAttr
887c478bd9Sstevel@tonic-gate# read the hand edited attrFile file
897c478bd9Sstevel@tonic-gate#
907c478bd9Sstevel@tonic-gate# return a hash reference
917c478bd9Sstevel@tonic-gate
927c478bd9Sstevel@tonic-gatesub readAttr {
937c478bd9Sstevel@tonic-gate	my $obj = shift;
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate	my $file = $obj->{'attrFile'};
967c478bd9Sstevel@tonic-gate	my $fileHandle = do {local *FileHandle; *FileHandle};
977c478bd9Sstevel@tonic-gate	open($fileHandle, $file) or die sprintf("$failedOpen\n", $file, $!);
987c478bd9Sstevel@tonic-gate
997c478bd9Sstevel@tonic-gate	my $count = 0;
1007c478bd9Sstevel@tonic-gate
1017c478bd9Sstevel@tonic-gate	my $attrState = -1;
1027c478bd9Sstevel@tonic-gate	my $caseState = 0;
1037c478bd9Sstevel@tonic-gate	my $label;
1047c478bd9Sstevel@tonic-gate	my $callName = '';
1057c478bd9Sstevel@tonic-gate	my $skip = '';
1067c478bd9Sstevel@tonic-gate	my $description = 'none';
1077c478bd9Sstevel@tonic-gate	my $format = 'none';
1087c478bd9Sstevel@tonic-gate	my $comment = '';
1097c478bd9Sstevel@tonic-gate	my $title = 'none';
1107c478bd9Sstevel@tonic-gate	my $note = '';
1117c478bd9Sstevel@tonic-gate	my $case = '';
1127c478bd9Sstevel@tonic-gate	my @case = ();
1137c478bd9Sstevel@tonic-gate	my %skipClass;
1147c478bd9Sstevel@tonic-gate	my %attr = ();
1157c478bd9Sstevel@tonic-gate	my %token = ();
1167c478bd9Sstevel@tonic-gate	my $classFilter = $obj->{'classFilter'};
1177c478bd9Sstevel@tonic-gate	$classFilter = '' unless (defined ($classFilter));
1187c478bd9Sstevel@tonic-gate
1197c478bd9Sstevel@tonic-gate	my %noteAlias = ();
1207c478bd9Sstevel@tonic-gate	while (<$fileHandle>) {
1217c478bd9Sstevel@tonic-gate		chomp;
1227c478bd9Sstevel@tonic-gate		s/#.*//;	 # remove comment
1237c478bd9Sstevel@tonic-gate		next if (/^\s*$/);
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gate		if ($attrState < 0) {  # initial state:  header info
1267c478bd9Sstevel@tonic-gate			if (/^\s*skipClass\s*=\s*(.*)/i) {
1277c478bd9Sstevel@tonic-gate				my $class = $1;
1287c478bd9Sstevel@tonic-gate				# don't skip what you're searching for
12987e895dbStz				next if (index(lc($classFilter),lc($class)) > -1);
1307c478bd9Sstevel@tonic-gate				$skipClass{$1} = 1;
1317c478bd9Sstevel@tonic-gate				next;
1327c478bd9Sstevel@tonic-gate			}
1337c478bd9Sstevel@tonic-gate			elsif (/^\s*token\s*=\s*(.*)/i) {
1347c478bd9Sstevel@tonic-gate				my ($attr, $value) = split(/\s*:\s*/, $1);
1357c478bd9Sstevel@tonic-gate				$token{$attr} = $value;
1367c478bd9Sstevel@tonic-gate				next;
1377c478bd9Sstevel@tonic-gate			}
1387c478bd9Sstevel@tonic-gate			elsif (/^\s*message\s*=\s*(.*)/i) {
1397c478bd9Sstevel@tonic-gate				my ($attr, $value) = split(/\s*:\s*/, $1);
1407c478bd9Sstevel@tonic-gate				$noteAlias{$attr} = $value;
1417c478bd9Sstevel@tonic-gate				next;
1427c478bd9Sstevel@tonic-gate			}
1437c478bd9Sstevel@tonic-gate			elsif (/^\s*kernel\s*=\s*(.*)/i) {
1447c478bd9Sstevel@tonic-gate				my ($attr, $value) = split(/\s*:\s*/, $1);
1457c478bd9Sstevel@tonic-gate				$obj->{'kernelDefault'} = $1;
1467c478bd9Sstevel@tonic-gate				next;
1477c478bd9Sstevel@tonic-gate			}
1487c478bd9Sstevel@tonic-gate			elsif (/^\s*user\s*=\s*(.*)/i) {
1497c478bd9Sstevel@tonic-gate				my ($attr, $value) = split(/\s*:\s*/, $1);
1507c478bd9Sstevel@tonic-gate				$obj->{'userDefault'} = $1;
1517c478bd9Sstevel@tonic-gate				next;
1527c478bd9Sstevel@tonic-gate			}
1537c478bd9Sstevel@tonic-gate		}
1547c478bd9Sstevel@tonic-gate		if (/^\s*label\s*=\s*(.*)/i) {
1557c478bd9Sstevel@tonic-gate			$attrState = 0 if ($attrState < 0);
1567c478bd9Sstevel@tonic-gate			my $newLabel = $1;
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate			if ($obj->{'debug'}) {
1597c478bd9Sstevel@tonic-gate				print STDERR qq{
1607c478bd9Sstevel@tonic-gate$newLabel is duplicated in the attribute file (line $.)
1617c478bd9Sstevel@tonic-gate				} if ($attr{$newLabel});
1627c478bd9Sstevel@tonic-gate			}
1637c478bd9Sstevel@tonic-gate			# if $attrState not zero, an unwritten record exists
1647c478bd9Sstevel@tonic-gate			if ($attrState) {
1657c478bd9Sstevel@tonic-gate				$callName = $obj->filterCallName($label,
1667c478bd9Sstevel@tonic-gate				    $callName);
1677c478bd9Sstevel@tonic-gate				push(@case, [$case, $format, $comment, $note]);
1687c478bd9Sstevel@tonic-gate
1697c478bd9Sstevel@tonic-gate				if ($obj->filterLabel($label)) {
1707c478bd9Sstevel@tonic-gate					$attr{$label} =
1717c478bd9Sstevel@tonic-gate					    [$callName, $description, $title,
1727c478bd9Sstevel@tonic-gate					    $skip, @case];
1737c478bd9Sstevel@tonic-gate					$count++;
1747c478bd9Sstevel@tonic-gate				}
1757c478bd9Sstevel@tonic-gate				$format = $description = $title = 'none';
1767c478bd9Sstevel@tonic-gate				$case = $note = $comment = $skip = $callName
1777c478bd9Sstevel@tonic-gate				    = '';
1787c478bd9Sstevel@tonic-gate				@case = ();
1797c478bd9Sstevel@tonic-gate				$caseState = 0;
1807c478bd9Sstevel@tonic-gate			}
1817c478bd9Sstevel@tonic-gate			$label = $newLabel;
1827c478bd9Sstevel@tonic-gate			$attrState = 1;
1837c478bd9Sstevel@tonic-gate		}
1847c478bd9Sstevel@tonic-gate		elsif (/^\s*skip\s*=\s*(.*)/i) {
1857c478bd9Sstevel@tonic-gate			$skip = $1;
1867c478bd9Sstevel@tonic-gate		}
1877c478bd9Sstevel@tonic-gate		elsif (/^\s*syscall\s*=\s*(.*)/i) {
1887c478bd9Sstevel@tonic-gate			$callName = $1;
1897c478bd9Sstevel@tonic-gate		}
1907c478bd9Sstevel@tonic-gate		elsif (/^\s*program\s*=\s*(.*)/i) {
1917c478bd9Sstevel@tonic-gate			$callName = $1;
1927c478bd9Sstevel@tonic-gate		}
1937c478bd9Sstevel@tonic-gate		elsif (/^\s*title\s*=\s*(.*)/i) {
1947c478bd9Sstevel@tonic-gate			$title = $1;
1957c478bd9Sstevel@tonic-gate		}
1967c478bd9Sstevel@tonic-gate		elsif (/^\s*see\s*=\s*(.*)/i) {
1977c478bd9Sstevel@tonic-gate			$description = $1;
1987c478bd9Sstevel@tonic-gate		}
1997c478bd9Sstevel@tonic-gate		elsif (/^\s*format\s*=\s*(.*)/i) {
2007c478bd9Sstevel@tonic-gate			$format = $1;
2017c478bd9Sstevel@tonic-gate		}
2027c478bd9Sstevel@tonic-gate		elsif (/^\s*comment\s*=\s*(.*)/i) {
2037c478bd9Sstevel@tonic-gate			$comment .= $1;
2047c478bd9Sstevel@tonic-gate		}
2057c478bd9Sstevel@tonic-gate		elsif (/^\s*note\s*=\s*(.*)/i) {
2067c478bd9Sstevel@tonic-gate			$note .= $1;
2077c478bd9Sstevel@tonic-gate		}
2087c478bd9Sstevel@tonic-gate		elsif (/^\s*case\s*=\s*(.*)/i) {
2097c478bd9Sstevel@tonic-gate			if ($caseState) {
2107c478bd9Sstevel@tonic-gate				push(@case, [$case, $format, $comment, $note]);
2117c478bd9Sstevel@tonic-gate				$format = 'none';
2127c478bd9Sstevel@tonic-gate				$comment = $note = '';
2137c478bd9Sstevel@tonic-gate			}
2147c478bd9Sstevel@tonic-gate			$case = $1;
2157c478bd9Sstevel@tonic-gate			$caseState = 1;
2167c478bd9Sstevel@tonic-gate		}
2177c478bd9Sstevel@tonic-gate	}
2187c478bd9Sstevel@tonic-gate	if ($attrState) {
2197c478bd9Sstevel@tonic-gate		$callName = $obj->filterCallName($label, $callName);
2207c478bd9Sstevel@tonic-gate		push(@case, [$case, $format, $comment, $note]);
2217c478bd9Sstevel@tonic-gate		if ($obj->filterLabel($label)) {
2227c478bd9Sstevel@tonic-gate			$attr{$label} = [$callName, $description, $title, $skip,
2237c478bd9Sstevel@tonic-gate			    @case];
2247c478bd9Sstevel@tonic-gate			$count++;
2257c478bd9Sstevel@tonic-gate		}
2267c478bd9Sstevel@tonic-gate	}
2277c478bd9Sstevel@tonic-gate	close $fileHandle;
2287c478bd9Sstevel@tonic-gate	print STDERR "found $count audit attribute entries\n" if ($obj->{'debug'});
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate	return ($obj->{'attr'} = \%attr, \%token, \%skipClass, \%noteAlias);
2317c478bd9Sstevel@tonic-gate}
2327c478bd9Sstevel@tonic-gate
2337c478bd9Sstevel@tonic-gate# readEvent
2347c478bd9Sstevel@tonic-gate# read eventFile and extract audit event information, including
2357c478bd9Sstevel@tonic-gate# which classes are associated with each event and what call is
2367c478bd9Sstevel@tonic-gate# related.
2377c478bd9Sstevel@tonic-gate
2387c478bd9Sstevel@tonic-gatesub readEvent {
2397c478bd9Sstevel@tonic-gate	my $obj = shift;
2407c478bd9Sstevel@tonic-gate
2417c478bd9Sstevel@tonic-gate	my %event = ();
2427c478bd9Sstevel@tonic-gate	my $file = $obj->{'eventFile'};
2437c478bd9Sstevel@tonic-gate
2447c478bd9Sstevel@tonic-gate	my $fileHandle = do {local *FileHandle; *FileHandle};
2457c478bd9Sstevel@tonic-gate	open($fileHandle, $file) or die sprintf("$failedOpen\n", $file, $!);
2467c478bd9Sstevel@tonic-gate
2477c478bd9Sstevel@tonic-gate	my $count = 0;
2487c478bd9Sstevel@tonic-gate
24987e895dbStz	unless (defined $obj->{'class'} && (scalar keys %{$obj->{'class'}} > 1)) {
25087e895dbStz		$obj->readClass();
25187e895dbStz	}
25287e895dbStz
25387e895dbStz	my @classFilterMasks = ();
2547c478bd9Sstevel@tonic-gate	my $classFilter = $obj->{'classFilter'};
2557c478bd9Sstevel@tonic-gate	if ($classFilter) {
25687e895dbStz		foreach (split(',', $classFilter)) {
25787e895dbStz			push @classFilterMasks, $obj->{'class'}{$_};
25887e895dbStz		}
2597c478bd9Sstevel@tonic-gate	}
2607c478bd9Sstevel@tonic-gate	# ignore customer-supplied audit events (id > 32767)
2617c478bd9Sstevel@tonic-gate
2627c478bd9Sstevel@tonic-gate	while (<$fileHandle>) {
2637c478bd9Sstevel@tonic-gate		chomp;
2647c478bd9Sstevel@tonic-gate		s/#.*//;	# remove comment
2657c478bd9Sstevel@tonic-gate		next if (/^\s*$/);
2667c478bd9Sstevel@tonic-gate		if (/^\s*(\d+):(\w+):([^:]+):(.*)/) {
2677c478bd9Sstevel@tonic-gate			my $id = $1;
2687c478bd9Sstevel@tonic-gate			my $label = $2;
2697c478bd9Sstevel@tonic-gate			my $description = $3;
2707c478bd9Sstevel@tonic-gate			my $class = $4;
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate			if ($id !~ /\d+/) {
2737c478bd9Sstevel@tonic-gate				print STDERR "$id is not numeric (line $.)\n";
2747c478bd9Sstevel@tonic-gate				next;
2757c478bd9Sstevel@tonic-gate			}
2767c478bd9Sstevel@tonic-gate			next if ($id > 32767);
2777c478bd9Sstevel@tonic-gate
2787c478bd9Sstevel@tonic-gate			$class =~ s/\s*$//;
2797c478bd9Sstevel@tonic-gate
2807c478bd9Sstevel@tonic-gate			if ($obj->{'debug'}) {
2817c478bd9Sstevel@tonic-gate				print STDERR qq{
2827c478bd9Sstevel@tonic-gate$label is duplicated in the event file (line $.)
2837c478bd9Sstevel@tonic-gate				} if ($event{$label});
2847c478bd9Sstevel@tonic-gate			}
2857c478bd9Sstevel@tonic-gate			next unless ($obj->filterLabel($label));
28687e895dbStz			my $mask = 0;
2877c478bd9Sstevel@tonic-gate			if ($classFilter) {
28887e895dbStz				foreach (split(/\s*,\s*/, $class)) {
28987e895dbStz					$mask |= $obj->{'class'}{$_};
29087e895dbStz				}
29187e895dbStz				my $skip = 0;
29287e895dbStz				foreach my $filterMask (@classFilterMasks) {
29387e895dbStz					unless ($mask & $filterMask) {
29487e895dbStz						$skip = 1;
29587e895dbStz						last;
29687e895dbStz					}
29787e895dbStz				}
29887e895dbStz				next if $skip;
2997c478bd9Sstevel@tonic-gate			}
3007c478bd9Sstevel@tonic-gate			if ($obj->{'idFilter'}) {
3017c478bd9Sstevel@tonic-gate				next unless ($obj->{'idFilter'} == $id);
3027c478bd9Sstevel@tonic-gate			}
3037c478bd9Sstevel@tonic-gate			$event{$label} = [$id, $class, $description];
3047c478bd9Sstevel@tonic-gate
3057c478bd9Sstevel@tonic-gate			$count++;
3067c478bd9Sstevel@tonic-gate		}
3077c478bd9Sstevel@tonic-gate	}
3087c478bd9Sstevel@tonic-gate	close $fileHandle;
3097c478bd9Sstevel@tonic-gate	print STDERR "found $count audit events\n" if ($obj->{'debug'});
3107c478bd9Sstevel@tonic-gate
3117c478bd9Sstevel@tonic-gate	return ($obj->{'event'} = \%event);
3127c478bd9Sstevel@tonic-gate}
3137c478bd9Sstevel@tonic-gate
3147c478bd9Sstevel@tonic-gate# readClass
3157c478bd9Sstevel@tonic-gate# read classFile and extract audit class information
3167c478bd9Sstevel@tonic-gate
3177c478bd9Sstevel@tonic-gatesub readClass {
3187c478bd9Sstevel@tonic-gate	my $obj = shift;
3197c478bd9Sstevel@tonic-gate
3207c478bd9Sstevel@tonic-gate	my %class = ();
3217c478bd9Sstevel@tonic-gate	my $file = $obj->{'classFile'};
3227c478bd9Sstevel@tonic-gate
3237c478bd9Sstevel@tonic-gate	my $fileHandle = do {local *FileHandle; *FileHandle};
3247c478bd9Sstevel@tonic-gate	open($fileHandle, $file) or die sprintf("$failedOpen\n", $file, $!);
3257c478bd9Sstevel@tonic-gate
3267c478bd9Sstevel@tonic-gate	my $count = 0;
3277c478bd9Sstevel@tonic-gate
3287c478bd9Sstevel@tonic-gate	while (<$fileHandle>) {
3297c478bd9Sstevel@tonic-gate		chomp;
3307c478bd9Sstevel@tonic-gate		s/#.*//;	# remove comment
3317c478bd9Sstevel@tonic-gate		next if (/^\s*$/);
3327c478bd9Sstevel@tonic-gate		my ($mask1, $class) = split(/:/);  # third field not used
3337c478bd9Sstevel@tonic-gate		my $mask2 = hex($mask1);  # integer
3347c478bd9Sstevel@tonic-gate		$class{$class} = $mask2;
3357c478bd9Sstevel@tonic-gate		$count++;
3367c478bd9Sstevel@tonic-gate	}
3377c478bd9Sstevel@tonic-gate	close $fileHandle;
3387c478bd9Sstevel@tonic-gate	print STDERR "found $count audit classes\n" if ($obj->{'debug'});
3397c478bd9Sstevel@tonic-gate
3407c478bd9Sstevel@tonic-gate	return ($obj->{'class'} = \%class);
3417c478bd9Sstevel@tonic-gate}
3427c478bd9Sstevel@tonic-gate
3437c478bd9Sstevel@tonic-gatesub filterLabel {
3447c478bd9Sstevel@tonic-gate	my $obj = shift;
3457c478bd9Sstevel@tonic-gate	my $label = shift;
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate	my $eventFilter = $obj->{'eventFilter'};
3487c478bd9Sstevel@tonic-gate	my $keepIt = 1;
3497c478bd9Sstevel@tonic-gate
3507c478bd9Sstevel@tonic-gate	$keepIt = 0 if ($eventFilter && ($label !~ /$eventFilter/i));
3517c478bd9Sstevel@tonic-gate
3527c478bd9Sstevel@tonic-gate	return ($keepIt);
3537c478bd9Sstevel@tonic-gate}
3547c478bd9Sstevel@tonic-gate
3557c478bd9Sstevel@tonic-gate# Normally, the root of the event label is the system call.  The
3567c478bd9Sstevel@tonic-gate# attrFile attribute syscall or program overrides this.
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gatesub filterCallName {
3597c478bd9Sstevel@tonic-gate	my $obj = shift;
3607c478bd9Sstevel@tonic-gate	my $label = shift;
3617c478bd9Sstevel@tonic-gate	my $callName = shift;
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate	return ($callName) if ($callName);
3647c478bd9Sstevel@tonic-gate
3657c478bd9Sstevel@tonic-gate	$label =~ /AUE_(.*)/;
3667c478bd9Sstevel@tonic-gate
3677c478bd9Sstevel@tonic-gate	my $name = $1;
3687c478bd9Sstevel@tonic-gate
3697c478bd9Sstevel@tonic-gate	return (lc ($name));
3707c478bd9Sstevel@tonic-gate}
3717c478bd9Sstevel@tonic-gate
3727c478bd9Sstevel@tonic-gate# readControl
3737c478bd9Sstevel@tonic-gate# read controlFile and extract flags and naflags information
3747c478bd9Sstevel@tonic-gate# at present, minfree, maxfree and the audit partitions are not
3757c478bd9Sstevel@tonic-gate# checked.
3767c478bd9Sstevel@tonic-gate
3777c478bd9Sstevel@tonic-gatesub readControl {
3787c478bd9Sstevel@tonic-gate	my $obj = shift;
3797c478bd9Sstevel@tonic-gate	my $failMode = shift;
3807c478bd9Sstevel@tonic-gate
3817c478bd9Sstevel@tonic-gate	my $cError = 0;
3827c478bd9Sstevel@tonic-gate	my $errors = '';
3837c478bd9Sstevel@tonic-gate	my $file = $obj->{'controlFile'};
3847c478bd9Sstevel@tonic-gate	my $invalidClass = gettext('invalid class, %s, in audit_control: %s');
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate	my $fileHandle = do {local *FileHandle; *FileHandle};
3877c478bd9Sstevel@tonic-gate	unless (open($fileHandle, $file)) {
3887c478bd9Sstevel@tonic-gate		die sprintf("$failedOpen\n", $file, $!)
3897c478bd9Sstevel@tonic-gate			unless ($failMode eq 'ignore');
3907c478bd9Sstevel@tonic-gate		return (0, '');
3917c478bd9Sstevel@tonic-gate	}
3927c478bd9Sstevel@tonic-gate	my %class = $obj->{'class'};
3937c478bd9Sstevel@tonic-gate	my @paths = $obj->{'paths'};
3947c478bd9Sstevel@tonic-gate	while (<$fileHandle>) {
3957c478bd9Sstevel@tonic-gate		chomp;
3967c478bd9Sstevel@tonic-gate		s/#.*//;	# remove comment
3977c478bd9Sstevel@tonic-gate		next if (/^\s*$/);
3987c478bd9Sstevel@tonic-gate		if ((/^\s*flags:/i) || (/^\s*naflags:/i)) {
3997c478bd9Sstevel@tonic-gate			my ($class) = /flags:\s*(.*)/;
4007c478bd9Sstevel@tonic-gate			my @class = split(/\s*,\s*/, $class);
4017c478bd9Sstevel@tonic-gate
4027c478bd9Sstevel@tonic-gate			foreach $class (@class) {
40387e895dbStz				$class =~ s/^[-+^]+//;
4047c478bd9Sstevel@tonic-gate				unless (defined ($class{$class})) {
4057c478bd9Sstevel@tonic-gate					$errors .=
4067c478bd9Sstevel@tonic-gate					    sprintf("$invalidClass\n",
4077c478bd9Sstevel@tonic-gate					    $class, $_);
4087c478bd9Sstevel@tonic-gate					$cError++;
4097c478bd9Sstevel@tonic-gate				}
4107c478bd9Sstevel@tonic-gate			}
4117c478bd9Sstevel@tonic-gate		}
4127c478bd9Sstevel@tonic-gate		elsif (/^\s*dir:\s*(.*)/) {
4137c478bd9Sstevel@tonic-gate			push (@paths, $1);
4147c478bd9Sstevel@tonic-gate			$obj->{'havePath'} = 1;
4157c478bd9Sstevel@tonic-gate		}
4167c478bd9Sstevel@tonic-gate	}
4177c478bd9Sstevel@tonic-gate	close $fileHandle;
4187c478bd9Sstevel@tonic-gate	return ($cError, $errors);
4197c478bd9Sstevel@tonic-gate}
4207c478bd9Sstevel@tonic-gate
4217c478bd9Sstevel@tonic-gatesub getPathList {
4227c478bd9Sstevel@tonic-gate	my $obj = shift;
4237c478bd9Sstevel@tonic-gate
4247c478bd9Sstevel@tonic-gate	$obj->readControl() unless ($obj->{'havePath'});
4257c478bd9Sstevel@tonic-gate
4267c478bd9Sstevel@tonic-gate	return ($obj->{'paths'});
4277c478bd9Sstevel@tonic-gate}
4287c478bd9Sstevel@tonic-gate
4297c478bd9Sstevel@tonic-gate# readUser
4307c478bd9Sstevel@tonic-gate# read userFile and extract audit information for validation
4317c478bd9Sstevel@tonic-gate
4327c478bd9Sstevel@tonic-gatesub readUser {
4337c478bd9Sstevel@tonic-gate	my $obj = shift;
4347c478bd9Sstevel@tonic-gate	my $failMode = shift;
4357c478bd9Sstevel@tonic-gate
4367c478bd9Sstevel@tonic-gate	my $cError = 0;
4377c478bd9Sstevel@tonic-gate	my $error = '';
4387c478bd9Sstevel@tonic-gate	my $file = $obj->{'userFile'};
4397c478bd9Sstevel@tonic-gate
4407c478bd9Sstevel@tonic-gate	my $fileHandle = do {local *FileHandle; *FileHandle};
4417c478bd9Sstevel@tonic-gate	unless (open($fileHandle, $file)) {
4427c478bd9Sstevel@tonic-gate		die sprintf("$failedOpen\n", $file, $!)
4437c478bd9Sstevel@tonic-gate			unless ($failMode eq 'ignore');
4447c478bd9Sstevel@tonic-gate		return (0, '');
4457c478bd9Sstevel@tonic-gate	}
4467c478bd9Sstevel@tonic-gate	# these strings are defined here mostly to avoid indentation problems
4477c478bd9Sstevel@tonic-gate	my $emptyErr   = gettext('empty audit mask in audit_user: %s');
4487c478bd9Sstevel@tonic-gate	my $syntaxErr1 = gettext(
4497c478bd9Sstevel@tonic-gate	    'incorrect syntax (exactly two colons req\'d) in audit_user: %s');
4507c478bd9Sstevel@tonic-gate	my $syntaxErr2 = gettext('incorrect syntax in audit_user: %s');
4517c478bd9Sstevel@tonic-gate	my $invalidErr = gettext('invalid class, %s, in audit_user: %s');
4527c478bd9Sstevel@tonic-gate	my $undefined  = gettext('undefined user name in audit_user: %s');
4537c478bd9Sstevel@tonic-gate
4547c478bd9Sstevel@tonic-gate	my %class = $obj->{'class'};
4557c478bd9Sstevel@tonic-gate	while (<$fileHandle>) {
4567c478bd9Sstevel@tonic-gate		chomp;
4577c478bd9Sstevel@tonic-gate		s/#.*//;        # remove comment
4587c478bd9Sstevel@tonic-gate		next if (/^\s*$/);
4597c478bd9Sstevel@tonic-gate		my $colonCount = tr/:/:/;
4607c478bd9Sstevel@tonic-gate
4617c478bd9Sstevel@tonic-gate		if ($colonCount != 2) {
4627c478bd9Sstevel@tonic-gate			$error .= sprintf("$syntaxErr1\n", $_);
4637c478bd9Sstevel@tonic-gate			$cError++;
4647c478bd9Sstevel@tonic-gate		}
4657c478bd9Sstevel@tonic-gate		my ($user, $always, $never) = split(/\s*:\s*/);
4667c478bd9Sstevel@tonic-gate		unless (defined($user)) {
4677c478bd9Sstevel@tonic-gate			$error .= sprintf("$syntaxErr2\n", $_);
4687c478bd9Sstevel@tonic-gate			$cError++;
4697c478bd9Sstevel@tonic-gate			next;
4707c478bd9Sstevel@tonic-gate		}
4717c478bd9Sstevel@tonic-gate		$error .= sprintf("$emptyErr\n", $_) unless ($always);
4727c478bd9Sstevel@tonic-gate
4737c478bd9Sstevel@tonic-gate		my ($name) = getpwnam($user);
4747c478bd9Sstevel@tonic-gate		unless (defined($name)) {
4757c478bd9Sstevel@tonic-gate			$error .= sprintf("$undefined\n", $user);
4767c478bd9Sstevel@tonic-gate			$cError++;
4777c478bd9Sstevel@tonic-gate		}
4787c478bd9Sstevel@tonic-gate		unless (defined($always) && defined($never)) {
4797c478bd9Sstevel@tonic-gate			$error .= sprintf("$emptyErr\n", $_);
4807c478bd9Sstevel@tonic-gate			$cError++;
4817c478bd9Sstevel@tonic-gate			next;
4827c478bd9Sstevel@tonic-gate		}
4837c478bd9Sstevel@tonic-gate		my $verify = $always . ',' . $never;
4847c478bd9Sstevel@tonic-gate		my @class = split(/\s*,\s*/, $verify);
4857c478bd9Sstevel@tonic-gate		my $thisClass;
4867c478bd9Sstevel@tonic-gate
4877c478bd9Sstevel@tonic-gate		foreach $thisClass (@class) {
48887e895dbStz			$thisClass =~ s/^[-+^]+//;
4897c478bd9Sstevel@tonic-gate			unless (defined $class{$thisClass}) {
4907c478bd9Sstevel@tonic-gate				$error .= sprintf("$invalidErr\n", $thisClass,
4917c478bd9Sstevel@tonic-gate				    $_);
4927c478bd9Sstevel@tonic-gate				$cError++;
4937c478bd9Sstevel@tonic-gate			}
4947c478bd9Sstevel@tonic-gate		}
4957c478bd9Sstevel@tonic-gate	}
4967c478bd9Sstevel@tonic-gate	close $fileHandle;
4977c478bd9Sstevel@tonic-gate	return ($cError, $error);
4987c478bd9Sstevel@tonic-gate}
4997c478bd9Sstevel@tonic-gate
5007c478bd9Sstevel@tonic-gate# ckAttrEvent complains if controlFile and attrFile don''t contain the
5017c478bd9Sstevel@tonic-gate# same list of events.
5027c478bd9Sstevel@tonic-gate
5037c478bd9Sstevel@tonic-gatesub ckAttrEvent {
5047c478bd9Sstevel@tonic-gate	my $obj = shift;
5057c478bd9Sstevel@tonic-gate
5067c478bd9Sstevel@tonic-gate	my $cError = 0;
5077c478bd9Sstevel@tonic-gate	my $error = '';
5087c478bd9Sstevel@tonic-gate	my $cAttr = 0;
5097c478bd9Sstevel@tonic-gate	my $label;
5107c478bd9Sstevel@tonic-gate	my $attrErr  = gettext(
5117c478bd9Sstevel@tonic-gate	    '%s entry in attribute file but not in event file');
5127c478bd9Sstevel@tonic-gate	my $eventErr = gettext(
5137c478bd9Sstevel@tonic-gate	    '%s entry in event file but not in attribute file');
5147c478bd9Sstevel@tonic-gate
5157c478bd9Sstevel@tonic-gate	my %attr = %{$obj->{'attr'}};
5167c478bd9Sstevel@tonic-gate	my %event = %{$obj->{'event'}};
5177c478bd9Sstevel@tonic-gate	foreach $label (keys %attr) {
5187c478bd9Sstevel@tonic-gate		$cAttr++;
5197c478bd9Sstevel@tonic-gate		unless ($event{$label}) {
5207c478bd9Sstevel@tonic-gate			$error .= sprintf("$attrErr\n", $label);
5217c478bd9Sstevel@tonic-gate			$cError++;
5227c478bd9Sstevel@tonic-gate		}
5237c478bd9Sstevel@tonic-gate	}
5247c478bd9Sstevel@tonic-gate	my $cEvent = 0;
5257c478bd9Sstevel@tonic-gate	foreach $label (keys %event) {
5267c478bd9Sstevel@tonic-gate		$cEvent++;
5277c478bd9Sstevel@tonic-gate		unless ($attr{$label}) {
5287c478bd9Sstevel@tonic-gate			$error .= sprintf("$eventErr\n", $label);
5297c478bd9Sstevel@tonic-gate			$cError++;
5307c478bd9Sstevel@tonic-gate		}
5317c478bd9Sstevel@tonic-gate	}
5327c478bd9Sstevel@tonic-gate	# debug only; not I18N'd
5337c478bd9Sstevel@tonic-gate	print STDERR
5347c478bd9Sstevel@tonic-gate	    "$cAttr audit_record_attr entries and $cEvent audit_event entries\n"
5357c478bd9Sstevel@tonic-gate		if ($obj->{'debug'});
5367c478bd9Sstevel@tonic-gate	return ($cError, $error);
5377c478bd9Sstevel@tonic-gate}
5387c478bd9Sstevel@tonic-gate
5397c478bd9Sstevel@tonic-gate1;
540