xref: /onnv-gate/usr/src/cmd/perl/contrib/Sun/Solaris/BSM/_BSMparse.pm (revision 9103:19aa7428269a)
10Sstevel@tonic-gate#
2*9103SJan.Friedel@Sun.COM# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
30Sstevel@tonic-gate# Use is subject to license terms.
40Sstevel@tonic-gate#
50Sstevel@tonic-gate# CDDL HEADER START
60Sstevel@tonic-gate#
70Sstevel@tonic-gate# The contents of this file are subject to the terms of the
82967Stz204579# Common Development and Distribution License (the "License").
92967Stz204579# You may not use this file except in compliance with the License.
100Sstevel@tonic-gate#
110Sstevel@tonic-gate# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
120Sstevel@tonic-gate# or http://www.opensolaris.org/os/licensing.
130Sstevel@tonic-gate# See the License for the specific language governing permissions
140Sstevel@tonic-gate# and limitations under the License.
150Sstevel@tonic-gate#
160Sstevel@tonic-gate# When distributing Covered Code, include this CDDL HEADER in each
170Sstevel@tonic-gate# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
180Sstevel@tonic-gate# If applicable, add the following below this CDDL HEADER, with the
190Sstevel@tonic-gate# fields enclosed by brackets "[]" replaced with your own identifying
200Sstevel@tonic-gate# information: Portions Copyright [yyyy] [name of copyright owner]
210Sstevel@tonic-gate#
220Sstevel@tonic-gate# CDDL HEADER END
230Sstevel@tonic-gate#
240Sstevel@tonic-gate
250Sstevel@tonic-gate# WARNING -- this package implements a Sun private interface; it may
260Sstevel@tonic-gate# change without notice.
270Sstevel@tonic-gate
280Sstevel@tonic-gatepackage Sun::Solaris::BSM::_BSMparse;
290Sstevel@tonic-gaterequire 5.005;
300Sstevel@tonic-gateuse strict;
310Sstevel@tonic-gateuse Exporter;
320Sstevel@tonic-gateuse Sun::Solaris::Utils qw(gettext);
330Sstevel@tonic-gate
340Sstevel@tonic-gateuse vars qw($VERSION $failedOpen
350Sstevel@tonic-gate    %EXPORT_TAGS @ISA @EXPORT_OK @EXPORT_FAIL);
360Sstevel@tonic-gate
370Sstevel@tonic-gate$VERSION = '1.01';
380Sstevel@tonic-gate
390Sstevel@tonic-gate@ISA = qw(Exporter);
400Sstevel@tonic-gatemy @constants = qw();
410Sstevel@tonic-gate@EXPORT_OK = qw(readAttr readEvent readClass filterLabel filterCallName
420Sstevel@tonic-gate		readControl getPathList readUser ckAttrEvent);
430Sstevel@tonic-gate@EXPORT_FAIL = qw($failedOpen);
440Sstevel@tonic-gate%EXPORT_TAGS = (ALL => \@EXPORT_OK);
450Sstevel@tonic-gate
460Sstevel@tonic-gate$failedOpen = gettext("failed to open %s: %s");
470Sstevel@tonic-gate
480Sstevel@tonic-gatesub new {
490Sstevel@tonic-gate	my $obj = shift;
500Sstevel@tonic-gate	my $debug = shift;	# bool
510Sstevel@tonic-gate	my $filters = shift;	# options for filtering
520Sstevel@tonic-gate
530Sstevel@tonic-gate	my $dir = '/etc/security';
543148Stz204579	my $attrDir = '/usr/lib/audit';
550Sstevel@tonic-gate        my $configDir = $dir;
560Sstevel@tonic-gate	$attrDir = shift if (@_);	# override for test
570Sstevel@tonic-gate	$configDir = shift if (@_);	# ditto
580Sstevel@tonic-gate
590Sstevel@tonic-gate	my $suffix = '';
600Sstevel@tonic-gate	$suffix = shift if (@_);	# test, again
610Sstevel@tonic-gate
620Sstevel@tonic-gate	$obj = ref($obj) || $obj;
630Sstevel@tonic-gate
640Sstevel@tonic-gate	my ($recordf, $classf, $controlf, $eventf, $userf) =
650Sstevel@tonic-gate	   ("$attrDir/audit_record_attr$suffix",
660Sstevel@tonic-gate	    "$configDir/audit_class$suffix",
670Sstevel@tonic-gate	    "$configDir/audit_control$suffix",
680Sstevel@tonic-gate	    "$configDir/audit_event$suffix",
690Sstevel@tonic-gate	    "$configDir/audit_user$suffix");
700Sstevel@tonic-gate
710Sstevel@tonic-gate	return (bless {
720Sstevel@tonic-gate		'attrFile'	=> $recordf,
730Sstevel@tonic-gate		'classFile'	=> $classf,
740Sstevel@tonic-gate		'classFilter'	=> $filters->{'classFilter'},
750Sstevel@tonic-gate		'controlFile'	=> $controlf,
760Sstevel@tonic-gate		'debug'		=> $debug,
770Sstevel@tonic-gate		'eventFile'	=> $eventf,
780Sstevel@tonic-gate		'eventFilter'	=> $filters->{'eventFilter'},
790Sstevel@tonic-gate		'idFilter'	=> $filters->{'idFilter'},
800Sstevel@tonic-gate		'havePath'	=> 0,
810Sstevel@tonic-gate		'kernelDefault'	=> '',
820Sstevel@tonic-gate		'userDefault'	=> '',
830Sstevel@tonic-gate		'userFile'	=> $userf}, $obj);
840Sstevel@tonic-gate}
850Sstevel@tonic-gate
860Sstevel@tonic-gate# readAttr
870Sstevel@tonic-gate# read the hand edited attrFile file
880Sstevel@tonic-gate#
890Sstevel@tonic-gate# return a hash reference
900Sstevel@tonic-gate
910Sstevel@tonic-gatesub readAttr {
920Sstevel@tonic-gate	my $obj = shift;
930Sstevel@tonic-gate
940Sstevel@tonic-gate	my $file = $obj->{'attrFile'};
950Sstevel@tonic-gate	my $fileHandle = do {local *FileHandle; *FileHandle};
960Sstevel@tonic-gate	open($fileHandle, $file) or die sprintf("$failedOpen\n", $file, $!);
970Sstevel@tonic-gate
980Sstevel@tonic-gate	my $count = 0;
99*9103SJan.Friedel@Sun.COM	my $lastAttr = '';
100*9103SJan.Friedel@Sun.COM	my $lastMacro = '';
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate	my $attrState = -1;
1030Sstevel@tonic-gate	my $caseState = 0;
1040Sstevel@tonic-gate	my $label;
1050Sstevel@tonic-gate	my $callName = '';
1060Sstevel@tonic-gate	my $skip = '';
1070Sstevel@tonic-gate	my $description = 'none';
1080Sstevel@tonic-gate	my $format = 'none';
1090Sstevel@tonic-gate	my $comment = '';
1100Sstevel@tonic-gate	my $title = 'none';
1110Sstevel@tonic-gate	my $note = '';
1120Sstevel@tonic-gate	my $case = '';
1130Sstevel@tonic-gate	my @case = ();
1140Sstevel@tonic-gate	my %skipClass;
1150Sstevel@tonic-gate	my %attr = ();
1160Sstevel@tonic-gate	my %token = ();
1170Sstevel@tonic-gate	my $classFilter = $obj->{'classFilter'};
1180Sstevel@tonic-gate	$classFilter = '' unless (defined ($classFilter));
1190Sstevel@tonic-gate
1200Sstevel@tonic-gate	my %noteAlias = ();
1210Sstevel@tonic-gate	while (<$fileHandle>) {
1220Sstevel@tonic-gate		chomp;
1230Sstevel@tonic-gate		s/#.*//;	 # remove comment
1240Sstevel@tonic-gate		next if (/^\s*$/);
1250Sstevel@tonic-gate
1260Sstevel@tonic-gate		if ($attrState < 0) {  # initial state:  header info
127*9103SJan.Friedel@Sun.COM			# continue assigning lines to multiline macros
128*9103SJan.Friedel@Sun.COM			# type: message
129*9103SJan.Friedel@Sun.COM			if ( $lastMacro ne '' ) {
130*9103SJan.Friedel@Sun.COM				my ($mcr, $attr) = split(/\s*:\s*/, $lastMacro);
131*9103SJan.Friedel@Sun.COM
132*9103SJan.Friedel@Sun.COM				if ($mcr eq "message") {
133*9103SJan.Friedel@Sun.COM					chomp($noteAlias{$attr});
134*9103SJan.Friedel@Sun.COM					chop($noteAlias{$attr});
135*9103SJan.Friedel@Sun.COM
136*9103SJan.Friedel@Sun.COM					$_ =~ /^\s*(.*)/i;
137*9103SJan.Friedel@Sun.COM					$noteAlias{$attr} .= $1;
138*9103SJan.Friedel@Sun.COM
139*9103SJan.Friedel@Sun.COM					$lastMacro = chkBslash($lastMacro, \$1);
140*9103SJan.Friedel@Sun.COM				}
141*9103SJan.Friedel@Sun.COM				next;
142*9103SJan.Friedel@Sun.COM			}
143*9103SJan.Friedel@Sun.COM
144*9103SJan.Friedel@Sun.COM			$lastMacro = '';
1450Sstevel@tonic-gate			if (/^\s*skipClass\s*=\s*(.*)/i) {
1460Sstevel@tonic-gate				my $class = $1;
1470Sstevel@tonic-gate				# don't skip what you're searching for
1482967Stz204579				next if (index(lc($classFilter),lc($class)) > -1);
1490Sstevel@tonic-gate				$skipClass{$1} = 1;
1500Sstevel@tonic-gate				next;
1510Sstevel@tonic-gate			}
1520Sstevel@tonic-gate			elsif (/^\s*token\s*=\s*(.*)/i) {
1530Sstevel@tonic-gate				my ($attr, $value) = split(/\s*:\s*/, $1);
1540Sstevel@tonic-gate				$token{$attr} = $value;
1550Sstevel@tonic-gate				next;
1560Sstevel@tonic-gate			}
1570Sstevel@tonic-gate			elsif (/^\s*message\s*=\s*(.*)/i) {
1580Sstevel@tonic-gate				my ($attr, $value) = split(/\s*:\s*/, $1);
1590Sstevel@tonic-gate				$noteAlias{$attr} = $value;
160*9103SJan.Friedel@Sun.COM				$lastMacro = chkBslash("message:$attr", \$1);
1610Sstevel@tonic-gate				next;
1620Sstevel@tonic-gate			}
1630Sstevel@tonic-gate			elsif (/^\s*kernel\s*=\s*(.*)/i) {
1640Sstevel@tonic-gate				my ($attr, $value) = split(/\s*:\s*/, $1);
1650Sstevel@tonic-gate				$obj->{'kernelDefault'} = $1;
1660Sstevel@tonic-gate				next;
1670Sstevel@tonic-gate			}
1680Sstevel@tonic-gate			elsif (/^\s*user\s*=\s*(.*)/i) {
1690Sstevel@tonic-gate				my ($attr, $value) = split(/\s*:\s*/, $1);
1700Sstevel@tonic-gate				$obj->{'userDefault'} = $1;
1710Sstevel@tonic-gate				next;
1720Sstevel@tonic-gate			}
1730Sstevel@tonic-gate		}
174*9103SJan.Friedel@Sun.COM
175*9103SJan.Friedel@Sun.COM		# continue assigning lines to multiline attributes
176*9103SJan.Friedel@Sun.COM		# type: case, comment, note, format
177*9103SJan.Friedel@Sun.COM		if ( $lastAttr ne '' ) {
178*9103SJan.Friedel@Sun.COM			my $curAttrVal = '';
179*9103SJan.Friedel@Sun.COM
180*9103SJan.Friedel@Sun.COM			eval "\$curAttrVal = \$$lastAttr";
181*9103SJan.Friedel@Sun.COM			chomp($curAttrVal);
182*9103SJan.Friedel@Sun.COM			chop($curAttrVal);
183*9103SJan.Friedel@Sun.COM
184*9103SJan.Friedel@Sun.COM			$_ =~ /^\s*(.*)/i;
185*9103SJan.Friedel@Sun.COM			$curAttrVal .= $1;
186*9103SJan.Friedel@Sun.COM
187*9103SJan.Friedel@Sun.COM			eval "\$$lastAttr = \$curAttrVal";
188*9103SJan.Friedel@Sun.COM
189*9103SJan.Friedel@Sun.COM			$lastAttr = chkBslash($lastAttr, \$1);
190*9103SJan.Friedel@Sun.COM			next;
191*9103SJan.Friedel@Sun.COM		}
192*9103SJan.Friedel@Sun.COM
193*9103SJan.Friedel@Sun.COM		$lastAttr = '';
1940Sstevel@tonic-gate		if (/^\s*label\s*=\s*(.*)/i) {
1950Sstevel@tonic-gate			$attrState = 0 if ($attrState < 0);
1960Sstevel@tonic-gate			my $newLabel = $1;
1970Sstevel@tonic-gate
1980Sstevel@tonic-gate			if ($obj->{'debug'}) {
1990Sstevel@tonic-gate				print STDERR qq{
2000Sstevel@tonic-gate$newLabel is duplicated in the attribute file (line $.)
2010Sstevel@tonic-gate				} if ($attr{$newLabel});
2020Sstevel@tonic-gate			}
2030Sstevel@tonic-gate			# if $attrState not zero, an unwritten record exists
2040Sstevel@tonic-gate			if ($attrState) {
2050Sstevel@tonic-gate				$callName = $obj->filterCallName($label,
2060Sstevel@tonic-gate				    $callName);
2070Sstevel@tonic-gate				push(@case, [$case, $format, $comment, $note]);
2080Sstevel@tonic-gate
2090Sstevel@tonic-gate				if ($obj->filterLabel($label)) {
2100Sstevel@tonic-gate					$attr{$label} =
2110Sstevel@tonic-gate					    [$callName, $description, $title,
2120Sstevel@tonic-gate					    $skip, @case];
2130Sstevel@tonic-gate					$count++;
2140Sstevel@tonic-gate				}
2150Sstevel@tonic-gate				$format = $description = $title = 'none';
2160Sstevel@tonic-gate				$case = $note = $comment = $skip = $callName
2170Sstevel@tonic-gate				    = '';
2180Sstevel@tonic-gate				@case = ();
2190Sstevel@tonic-gate				$caseState = 0;
2200Sstevel@tonic-gate			}
2210Sstevel@tonic-gate			$label = $newLabel;
2220Sstevel@tonic-gate			$attrState = 1;
2230Sstevel@tonic-gate		}
2240Sstevel@tonic-gate		elsif (/^\s*skip\s*=\s*(.*)/i) {
2250Sstevel@tonic-gate			$skip = $1;
2260Sstevel@tonic-gate		}
2270Sstevel@tonic-gate		elsif (/^\s*syscall\s*=\s*(.*)/i) {
2280Sstevel@tonic-gate			$callName = $1;
2290Sstevel@tonic-gate		}
2300Sstevel@tonic-gate		elsif (/^\s*program\s*=\s*(.*)/i) {
2310Sstevel@tonic-gate			$callName = $1;
2320Sstevel@tonic-gate		}
2330Sstevel@tonic-gate		elsif (/^\s*title\s*=\s*(.*)/i) {
2340Sstevel@tonic-gate			$title = $1;
2350Sstevel@tonic-gate		}
2360Sstevel@tonic-gate		elsif (/^\s*see\s*=\s*(.*)/i) {
2370Sstevel@tonic-gate			$description = $1;
2380Sstevel@tonic-gate		}
2390Sstevel@tonic-gate		elsif (/^\s*format\s*=\s*(.*)/i) {
2400Sstevel@tonic-gate			$format = $1;
241*9103SJan.Friedel@Sun.COM			$lastAttr = chkBslash("format", \$1);
2420Sstevel@tonic-gate		}
2430Sstevel@tonic-gate		elsif (/^\s*comment\s*=\s*(.*)/i) {
2440Sstevel@tonic-gate			$comment .= $1;
245*9103SJan.Friedel@Sun.COM			$lastAttr = chkBslash("comment", \$1);
2460Sstevel@tonic-gate		}
2470Sstevel@tonic-gate		elsif (/^\s*note\s*=\s*(.*)/i) {
2480Sstevel@tonic-gate			$note .= $1;
249*9103SJan.Friedel@Sun.COM			$lastAttr = chkBslash("note", \$1);
2500Sstevel@tonic-gate		}
2510Sstevel@tonic-gate		elsif (/^\s*case\s*=\s*(.*)/i) {
2520Sstevel@tonic-gate			if ($caseState) {
2530Sstevel@tonic-gate				push(@case, [$case, $format, $comment, $note]);
2540Sstevel@tonic-gate				$format = 'none';
2550Sstevel@tonic-gate				$comment = $note = '';
2560Sstevel@tonic-gate			}
2570Sstevel@tonic-gate			$case = $1;
258*9103SJan.Friedel@Sun.COM			$lastAttr = chkBslash("case", \$1);
2590Sstevel@tonic-gate			$caseState = 1;
2600Sstevel@tonic-gate		}
2610Sstevel@tonic-gate	}
2620Sstevel@tonic-gate	if ($attrState) {
2630Sstevel@tonic-gate		$callName = $obj->filterCallName($label, $callName);
2640Sstevel@tonic-gate		push(@case, [$case, $format, $comment, $note]);
2650Sstevel@tonic-gate		if ($obj->filterLabel($label)) {
2660Sstevel@tonic-gate			$attr{$label} = [$callName, $description, $title, $skip,
2670Sstevel@tonic-gate			    @case];
2680Sstevel@tonic-gate			$count++;
2690Sstevel@tonic-gate		}
2700Sstevel@tonic-gate	}
2710Sstevel@tonic-gate	close $fileHandle;
2720Sstevel@tonic-gate	print STDERR "found $count audit attribute entries\n" if ($obj->{'debug'});
2730Sstevel@tonic-gate
2740Sstevel@tonic-gate	return ($obj->{'attr'} = \%attr, \%token, \%skipClass, \%noteAlias);
2750Sstevel@tonic-gate}
2760Sstevel@tonic-gate
2770Sstevel@tonic-gate# readEvent
2780Sstevel@tonic-gate# read eventFile and extract audit event information, including
2790Sstevel@tonic-gate# which classes are associated with each event and what call is
2800Sstevel@tonic-gate# related.
2810Sstevel@tonic-gate
2820Sstevel@tonic-gatesub readEvent {
2830Sstevel@tonic-gate	my $obj = shift;
2840Sstevel@tonic-gate
2850Sstevel@tonic-gate	my %event = ();
2860Sstevel@tonic-gate	my $file = $obj->{'eventFile'};
2870Sstevel@tonic-gate
2880Sstevel@tonic-gate	my $fileHandle = do {local *FileHandle; *FileHandle};
2890Sstevel@tonic-gate	open($fileHandle, $file) or die sprintf("$failedOpen\n", $file, $!);
2900Sstevel@tonic-gate
2910Sstevel@tonic-gate	my $count = 0;
2920Sstevel@tonic-gate
2932967Stz204579	unless (defined $obj->{'class'} && (scalar keys %{$obj->{'class'}} > 1)) {
2942967Stz204579		$obj->readClass();
2952967Stz204579	}
2962967Stz204579
2972967Stz204579	my @classFilterMasks = ();
2980Sstevel@tonic-gate	my $classFilter = $obj->{'classFilter'};
2990Sstevel@tonic-gate	if ($classFilter) {
3002967Stz204579		foreach (split(',', $classFilter)) {
3012967Stz204579			push @classFilterMasks, $obj->{'class'}{$_};
3022967Stz204579		}
3030Sstevel@tonic-gate	}
3040Sstevel@tonic-gate	# ignore customer-supplied audit events (id > 32767)
3050Sstevel@tonic-gate
3060Sstevel@tonic-gate	while (<$fileHandle>) {
3070Sstevel@tonic-gate		chomp;
3080Sstevel@tonic-gate		s/#.*//;	# remove comment
3090Sstevel@tonic-gate		next if (/^\s*$/);
3100Sstevel@tonic-gate		if (/^\s*(\d+):(\w+):([^:]+):(.*)/) {
3110Sstevel@tonic-gate			my $id = $1;
3120Sstevel@tonic-gate			my $label = $2;
3130Sstevel@tonic-gate			my $description = $3;
3140Sstevel@tonic-gate			my $class = $4;
3150Sstevel@tonic-gate
3160Sstevel@tonic-gate			if ($id !~ /\d+/) {
3170Sstevel@tonic-gate				print STDERR "$id is not numeric (line $.)\n";
3180Sstevel@tonic-gate				next;
3190Sstevel@tonic-gate			}
3200Sstevel@tonic-gate			next if ($id > 32767);
3210Sstevel@tonic-gate
3220Sstevel@tonic-gate			$class =~ s/\s*$//;
3230Sstevel@tonic-gate
3240Sstevel@tonic-gate			if ($obj->{'debug'}) {
3250Sstevel@tonic-gate				print STDERR qq{
3260Sstevel@tonic-gate$label is duplicated in the event file (line $.)
3270Sstevel@tonic-gate				} if ($event{$label});
3280Sstevel@tonic-gate			}
3290Sstevel@tonic-gate			next unless ($obj->filterLabel($label));
3302967Stz204579			my $mask = 0;
3310Sstevel@tonic-gate			if ($classFilter) {
3322967Stz204579				foreach (split(/\s*,\s*/, $class)) {
3332967Stz204579					$mask |= $obj->{'class'}{$_};
3342967Stz204579				}
3352967Stz204579				my $skip = 0;
3362967Stz204579				foreach my $filterMask (@classFilterMasks) {
3372967Stz204579					unless ($mask & $filterMask) {
3382967Stz204579						$skip = 1;
3392967Stz204579						last;
3402967Stz204579					}
3412967Stz204579				}
3422967Stz204579				next if $skip;
3430Sstevel@tonic-gate			}
3440Sstevel@tonic-gate			if ($obj->{'idFilter'}) {
3450Sstevel@tonic-gate				next unless ($obj->{'idFilter'} == $id);
3460Sstevel@tonic-gate			}
3470Sstevel@tonic-gate			$event{$label} = [$id, $class, $description];
3480Sstevel@tonic-gate
3490Sstevel@tonic-gate			$count++;
3500Sstevel@tonic-gate		}
3510Sstevel@tonic-gate	}
3520Sstevel@tonic-gate	close $fileHandle;
3530Sstevel@tonic-gate	print STDERR "found $count audit events\n" if ($obj->{'debug'});
3540Sstevel@tonic-gate
3550Sstevel@tonic-gate	return ($obj->{'event'} = \%event);
3560Sstevel@tonic-gate}
3570Sstevel@tonic-gate
3580Sstevel@tonic-gate# readClass
3590Sstevel@tonic-gate# read classFile and extract audit class information
3600Sstevel@tonic-gate
3610Sstevel@tonic-gatesub readClass {
3620Sstevel@tonic-gate	my $obj = shift;
3630Sstevel@tonic-gate
3640Sstevel@tonic-gate	my %class = ();
3650Sstevel@tonic-gate	my $file = $obj->{'classFile'};
3660Sstevel@tonic-gate
3670Sstevel@tonic-gate	my $fileHandle = do {local *FileHandle; *FileHandle};
3680Sstevel@tonic-gate	open($fileHandle, $file) or die sprintf("$failedOpen\n", $file, $!);
3690Sstevel@tonic-gate
3700Sstevel@tonic-gate	my $count = 0;
3710Sstevel@tonic-gate
3720Sstevel@tonic-gate	while (<$fileHandle>) {
3730Sstevel@tonic-gate		chomp;
3740Sstevel@tonic-gate		s/#.*//;	# remove comment
3750Sstevel@tonic-gate		next if (/^\s*$/);
3760Sstevel@tonic-gate		my ($mask1, $class) = split(/:/);  # third field not used
3770Sstevel@tonic-gate		my $mask2 = hex($mask1);  # integer
3780Sstevel@tonic-gate		$class{$class} = $mask2;
3790Sstevel@tonic-gate		$count++;
3800Sstevel@tonic-gate	}
3810Sstevel@tonic-gate	close $fileHandle;
3820Sstevel@tonic-gate	print STDERR "found $count audit classes\n" if ($obj->{'debug'});
3830Sstevel@tonic-gate
3840Sstevel@tonic-gate	return ($obj->{'class'} = \%class);
3850Sstevel@tonic-gate}
3860Sstevel@tonic-gate
3870Sstevel@tonic-gatesub filterLabel {
3880Sstevel@tonic-gate	my $obj = shift;
3890Sstevel@tonic-gate	my $label = shift;
3900Sstevel@tonic-gate
3910Sstevel@tonic-gate	my $eventFilter = $obj->{'eventFilter'};
3920Sstevel@tonic-gate	my $keepIt = 1;
3930Sstevel@tonic-gate
3940Sstevel@tonic-gate	$keepIt = 0 if ($eventFilter && ($label !~ /$eventFilter/i));
3950Sstevel@tonic-gate
3960Sstevel@tonic-gate	return ($keepIt);
3970Sstevel@tonic-gate}
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate# Normally, the root of the event label is the system call.  The
4000Sstevel@tonic-gate# attrFile attribute syscall or program overrides this.
4010Sstevel@tonic-gate
4020Sstevel@tonic-gatesub filterCallName {
4030Sstevel@tonic-gate	my $obj = shift;
4040Sstevel@tonic-gate	my $label = shift;
4050Sstevel@tonic-gate	my $callName = shift;
4060Sstevel@tonic-gate
4070Sstevel@tonic-gate	return ($callName) if ($callName);
4080Sstevel@tonic-gate
4090Sstevel@tonic-gate	$label =~ /AUE_(.*)/;
4100Sstevel@tonic-gate
4110Sstevel@tonic-gate	my $name = $1;
4120Sstevel@tonic-gate
4130Sstevel@tonic-gate	return (lc ($name));
4140Sstevel@tonic-gate}
4150Sstevel@tonic-gate
4160Sstevel@tonic-gate# readControl
4170Sstevel@tonic-gate# read controlFile and extract flags and naflags information
4180Sstevel@tonic-gate# at present, minfree, maxfree and the audit partitions are not
4190Sstevel@tonic-gate# checked.
4200Sstevel@tonic-gate
4210Sstevel@tonic-gatesub readControl {
4220Sstevel@tonic-gate	my $obj = shift;
4230Sstevel@tonic-gate	my $failMode = shift;
4240Sstevel@tonic-gate
4250Sstevel@tonic-gate	my $cError = 0;
4260Sstevel@tonic-gate	my $errors = '';
4270Sstevel@tonic-gate	my $file = $obj->{'controlFile'};
4280Sstevel@tonic-gate	my $invalidClass = gettext('invalid class, %s, in audit_control: %s');
4290Sstevel@tonic-gate
4300Sstevel@tonic-gate	my $fileHandle = do {local *FileHandle; *FileHandle};
4310Sstevel@tonic-gate	unless (open($fileHandle, $file)) {
4320Sstevel@tonic-gate		die sprintf("$failedOpen\n", $file, $!)
4330Sstevel@tonic-gate			unless ($failMode eq 'ignore');
4340Sstevel@tonic-gate		return (0, '');
4350Sstevel@tonic-gate	}
4360Sstevel@tonic-gate	my %class = $obj->{'class'};
4370Sstevel@tonic-gate	my @paths = $obj->{'paths'};
4380Sstevel@tonic-gate	while (<$fileHandle>) {
4390Sstevel@tonic-gate		chomp;
4400Sstevel@tonic-gate		s/#.*//;	# remove comment
4410Sstevel@tonic-gate		next if (/^\s*$/);
4420Sstevel@tonic-gate		if ((/^\s*flags:/i) || (/^\s*naflags:/i)) {
4430Sstevel@tonic-gate			my ($class) = /flags:\s*(.*)/;
4440Sstevel@tonic-gate			my @class = split(/\s*,\s*/, $class);
4450Sstevel@tonic-gate
4460Sstevel@tonic-gate			foreach $class (@class) {
4472967Stz204579				$class =~ s/^[-+^]+//;
4480Sstevel@tonic-gate				unless (defined ($class{$class})) {
4490Sstevel@tonic-gate					$errors .=
4500Sstevel@tonic-gate					    sprintf("$invalidClass\n",
4510Sstevel@tonic-gate					    $class, $_);
4520Sstevel@tonic-gate					$cError++;
4530Sstevel@tonic-gate				}
4540Sstevel@tonic-gate			}
4550Sstevel@tonic-gate		}
4560Sstevel@tonic-gate		elsif (/^\s*dir:\s*(.*)/) {
4570Sstevel@tonic-gate			push (@paths, $1);
4580Sstevel@tonic-gate			$obj->{'havePath'} = 1;
4590Sstevel@tonic-gate		}
4600Sstevel@tonic-gate	}
4610Sstevel@tonic-gate	close $fileHandle;
4620Sstevel@tonic-gate	return ($cError, $errors);
4630Sstevel@tonic-gate}
4640Sstevel@tonic-gate
4650Sstevel@tonic-gatesub getPathList {
4660Sstevel@tonic-gate	my $obj = shift;
4670Sstevel@tonic-gate
4680Sstevel@tonic-gate	$obj->readControl() unless ($obj->{'havePath'});
4690Sstevel@tonic-gate
4700Sstevel@tonic-gate	return ($obj->{'paths'});
4710Sstevel@tonic-gate}
4720Sstevel@tonic-gate
4730Sstevel@tonic-gate# readUser
4740Sstevel@tonic-gate# read userFile and extract audit information for validation
4750Sstevel@tonic-gate
4760Sstevel@tonic-gatesub readUser {
4770Sstevel@tonic-gate	my $obj = shift;
4780Sstevel@tonic-gate	my $failMode = shift;
4790Sstevel@tonic-gate
4800Sstevel@tonic-gate	my $cError = 0;
4810Sstevel@tonic-gate	my $error = '';
4820Sstevel@tonic-gate	my $file = $obj->{'userFile'};
4830Sstevel@tonic-gate
4840Sstevel@tonic-gate	my $fileHandle = do {local *FileHandle; *FileHandle};
4850Sstevel@tonic-gate	unless (open($fileHandle, $file)) {
4860Sstevel@tonic-gate		die sprintf("$failedOpen\n", $file, $!)
4870Sstevel@tonic-gate			unless ($failMode eq 'ignore');
4880Sstevel@tonic-gate		return (0, '');
4890Sstevel@tonic-gate	}
4900Sstevel@tonic-gate	# these strings are defined here mostly to avoid indentation problems
4910Sstevel@tonic-gate	my $emptyErr   = gettext('empty audit mask in audit_user: %s');
4920Sstevel@tonic-gate	my $syntaxErr1 = gettext(
4930Sstevel@tonic-gate	    'incorrect syntax (exactly two colons req\'d) in audit_user: %s');
4940Sstevel@tonic-gate	my $syntaxErr2 = gettext('incorrect syntax in audit_user: %s');
4950Sstevel@tonic-gate	my $invalidErr = gettext('invalid class, %s, in audit_user: %s');
4960Sstevel@tonic-gate	my $undefined  = gettext('undefined user name in audit_user: %s');
4970Sstevel@tonic-gate
4980Sstevel@tonic-gate	my %class = $obj->{'class'};
4990Sstevel@tonic-gate	while (<$fileHandle>) {
5000Sstevel@tonic-gate		chomp;
5010Sstevel@tonic-gate		s/#.*//;        # remove comment
5020Sstevel@tonic-gate		next if (/^\s*$/);
5030Sstevel@tonic-gate		my $colonCount = tr/:/:/;
5040Sstevel@tonic-gate
5050Sstevel@tonic-gate		if ($colonCount != 2) {
5060Sstevel@tonic-gate			$error .= sprintf("$syntaxErr1\n", $_);
5070Sstevel@tonic-gate			$cError++;
5080Sstevel@tonic-gate		}
5090Sstevel@tonic-gate		my ($user, $always, $never) = split(/\s*:\s*/);
5100Sstevel@tonic-gate		unless (defined($user)) {
5110Sstevel@tonic-gate			$error .= sprintf("$syntaxErr2\n", $_);
5120Sstevel@tonic-gate			$cError++;
5130Sstevel@tonic-gate			next;
5140Sstevel@tonic-gate		}
5150Sstevel@tonic-gate		$error .= sprintf("$emptyErr\n", $_) unless ($always);
5160Sstevel@tonic-gate
5170Sstevel@tonic-gate		my ($name) = getpwnam($user);
5180Sstevel@tonic-gate		unless (defined($name)) {
5190Sstevel@tonic-gate			$error .= sprintf("$undefined\n", $user);
5200Sstevel@tonic-gate			$cError++;
5210Sstevel@tonic-gate		}
5220Sstevel@tonic-gate		unless (defined($always) && defined($never)) {
5230Sstevel@tonic-gate			$error .= sprintf("$emptyErr\n", $_);
5240Sstevel@tonic-gate			$cError++;
5250Sstevel@tonic-gate			next;
5260Sstevel@tonic-gate		}
5270Sstevel@tonic-gate		my $verify = $always . ',' . $never;
5280Sstevel@tonic-gate		my @class = split(/\s*,\s*/, $verify);
5290Sstevel@tonic-gate		my $thisClass;
5300Sstevel@tonic-gate
5310Sstevel@tonic-gate		foreach $thisClass (@class) {
5322967Stz204579			$thisClass =~ s/^[-+^]+//;
5330Sstevel@tonic-gate			unless (defined $class{$thisClass}) {
5340Sstevel@tonic-gate				$error .= sprintf("$invalidErr\n", $thisClass,
5350Sstevel@tonic-gate				    $_);
5360Sstevel@tonic-gate				$cError++;
5370Sstevel@tonic-gate			}
5380Sstevel@tonic-gate		}
5390Sstevel@tonic-gate	}
5400Sstevel@tonic-gate	close $fileHandle;
5410Sstevel@tonic-gate	return ($cError, $error);
5420Sstevel@tonic-gate}
5430Sstevel@tonic-gate
5440Sstevel@tonic-gate# ckAttrEvent complains if controlFile and attrFile don''t contain the
5450Sstevel@tonic-gate# same list of events.
5460Sstevel@tonic-gate
5470Sstevel@tonic-gatesub ckAttrEvent {
5480Sstevel@tonic-gate	my $obj = shift;
5490Sstevel@tonic-gate
5500Sstevel@tonic-gate	my $cError = 0;
5510Sstevel@tonic-gate	my $error = '';
5520Sstevel@tonic-gate	my $cAttr = 0;
5530Sstevel@tonic-gate	my $label;
5540Sstevel@tonic-gate	my $attrErr  = gettext(
5550Sstevel@tonic-gate	    '%s entry in attribute file but not in event file');
5560Sstevel@tonic-gate	my $eventErr = gettext(
5570Sstevel@tonic-gate	    '%s entry in event file but not in attribute file');
5580Sstevel@tonic-gate
5590Sstevel@tonic-gate	my %attr = %{$obj->{'attr'}};
5600Sstevel@tonic-gate	my %event = %{$obj->{'event'}};
5610Sstevel@tonic-gate	foreach $label (keys %attr) {
5620Sstevel@tonic-gate		$cAttr++;
5630Sstevel@tonic-gate		unless ($event{$label}) {
5640Sstevel@tonic-gate			$error .= sprintf("$attrErr\n", $label);
5650Sstevel@tonic-gate			$cError++;
5660Sstevel@tonic-gate		}
5670Sstevel@tonic-gate	}
5680Sstevel@tonic-gate	my $cEvent = 0;
5690Sstevel@tonic-gate	foreach $label (keys %event) {
5700Sstevel@tonic-gate		$cEvent++;
5710Sstevel@tonic-gate		unless ($attr{$label}) {
5720Sstevel@tonic-gate			$error .= sprintf("$eventErr\n", $label);
5730Sstevel@tonic-gate			$cError++;
5740Sstevel@tonic-gate		}
5750Sstevel@tonic-gate	}
5760Sstevel@tonic-gate	# debug only; not I18N'd
5770Sstevel@tonic-gate	print STDERR
5780Sstevel@tonic-gate	    "$cAttr audit_record_attr entries and $cEvent audit_event entries\n"
5790Sstevel@tonic-gate		if ($obj->{'debug'});
5800Sstevel@tonic-gate	return ($cError, $error);
5810Sstevel@tonic-gate}
5820Sstevel@tonic-gate
583*9103SJan.Friedel@Sun.COM# chkBslash (helper)
584*9103SJan.Friedel@Sun.COM# check the given string for backslash character at the end; if found
585*9103SJan.Friedel@Sun.COM# return the string sent as a first argument, otherwise return empty
586*9103SJan.Friedel@Sun.COM# string.
587*9103SJan.Friedel@Sun.COMsub chkBslash ($$) {
588*9103SJan.Friedel@Sun.COM	my $retStr = shift;
589*9103SJan.Friedel@Sun.COM	my $strPtr = shift;
590*9103SJan.Friedel@Sun.COM
591*9103SJan.Friedel@Sun.COM	if ( $$strPtr !~ /\\$/ ) {
592*9103SJan.Friedel@Sun.COM		 $retStr = '';
593*9103SJan.Friedel@Sun.COM	}
594*9103SJan.Friedel@Sun.COM
595*9103SJan.Friedel@Sun.COM	return $retStr;
596*9103SJan.Friedel@Sun.COM}
597*9103SJan.Friedel@Sun.COM
5980Sstevel@tonic-gate1;
599