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