
#!/usr/local/bin/perl
# 
# $Header: umaskSetting.pl 05-dec-2005.14:57:05 dsukhwal Exp $
#
# umaskSetting.pl
# 
# Copyright (c) 2004, 2005, Oracle. All rights reserved.  
#
#    NAME
#      umaskSetting.pl - <one-line expansion of the name>
#
#    DESCRIPTION
#      <short description of component this file declares/defines>
#
#    NOTES
#      <other useful comments, qualifications, etc.>
#
#    MODIFIED   (MM/DD/YY)
#    dsukhwal    11/24/05 - more restrictive umask is ok 
#    dkjain      07/04/05 - Added exit(0) 
#    dsukhwal    05/11/05 - limit number of rows pushed 
#    dkjain      04/17/05 - 
#    dsukhwal    02/16/05 - 3 digits in octal file permissions 
#    dkjain      12/27/04 - Validate Umask value
#    dkjain      12/10/04 - Fixed Bug-4046011 
#    dkjain      11/26/04 - fix Bug-4031854 
#    dkjain      10/31/04 - fix Bug-3977629
#    dkjain      10/08/04 - dkjain_esa_impl_init
#    dkjain      10/08/04 - Creation
# 
#Since it has to be checked against linux OS

if(!($^O =~ "linux"))
{
  print "em_error=Metric is defined for Unix Systems.\n" ;
  exit(0) ;
}
 use Cwd ;
#################################
 require "$ENV{EMDROOT}/sysman/admin/scripts/db/esaUtils.pl";
##################################

 my $maxRows = $ENV{'UMASKMAX'};
 my $okUmask = "18"; #18 in decimal is same as 22 in octal
 my $rownum = 0;
 my $property="umask_setting";
 my $dbOracleHome = $ENV{EM_TARGET_ORACLE_HOME};
 my $euidAgentProcess = $> ;
 my $uidOracleHomeOwner = file_owner_uid($dbOracleHome) ;

 if($uidOracleHomeOwner == -1){
   print "em_error=File $dbOracleHome Does not Exists.\n" ;
   exit(0);
 }
 #unit_test();
 my $homedir ;
 my $envUmask;
 if(match_oraclehome()||($euidAgentProcess == $uidOracleHomeOwner)){
   $envUmask = umask(); #here, $envUmask is in decimal system
   if( compareNegInf($rownum, $maxRows) && unsafeUmask($envUmask) ) {#unsafeUmask is based on the global $okUmask
    printf "em_result=$property|%03o|Environment\n",$envUmask;
    $rownum++;
   }
 }
 elsif($uidOracleHomeOwner != -1) {
   $homedir=(getpwuid($uidOracleHomeOwner))[7] ;
   umask_test("$homedir/.cshrc");
   umask_test("$homedir/.bashrc");
   umask_test("$homedir/.profile");
 }


 sub match_oraclehome {
  my $pwdAgent = getcwd(); 
  if($pwdAgent =~ $dbOracleHome){
   return 1 ; 
  }
  else{
   return 0 ; 
  }
 } 

 sub umask_test {
  my $files = shift ;
  unless (open ( FILE, $files))
  {
      return ;
  }

  my @info = <FILE> ;
  my $line ;
  my $tmpLastValidUmask ;
  my $lastValidUmask ;
  foreach $line (@info){
     if(($line =~ /^\s*umask\s+(.*)/)){
       $tmpLastValidUmask = validate_umask($1);
       if($tmpLastValidUmask ne ""){
         $lastValidUmask = $tmpLastValidUmask;
       }
     }
   }

  if(($lastValidUmask ne "022")&&($lastValidUmask ne "")){
    $files = check_512char($files);
    if( (compareNegInf($rownum,$maxRows)) && 
        unsafeUmask(oct($lastValidUmask)) #oct will convert from octal to decimal
      ){
       print "em_result=$property|$lastValidUmask|$files\n";
       $rownum++;
    }
  }
 }



 sub validate_umask {
  my $line = shift ;
  my @words = split(/ /,$line);
  my $numOfWords = @words ;
  if($numOfWords > 1){
   #Too Many Arguments Certainly this setting will
   #not be in effect thus nothing is to be return ;
   return ;
  }

  my $len = length($words[0]);
  if($len < 3){
    $words[0] = sprintf("%03d",$words[0]); #pad left with zeroes
    $len = 3;
  }
  my $umask = substr($words[0],($len - 3)) ;
  if($umask =~ m/[^0-7]/){
   #If any of the last three digits is other than 0..7,
   #Bad arguments so nothing is to be return ;
   #print "$umask \n ";
   return ;
  }
  my $rest = substr($words[0],0,($len-3)) ;
  if($rest =~ m/[^0]/){
    #if the block of last three digits is prepended by a
    #substring containing non-zero digit will also
    #leads to bad umask,thus  nothing is to be return
    #print "Rest $rest \n ";
    return ;
  }
  return $umask ;
 }		

sub unsafeUmask{
#first argument is the umask(decimal) that is to be checked
#Returns 1 if the umask is more or equally restrictive than the global $okUmask
    my $umask = shift;
    return compareRestrictions($umask, ,$okUmask)?0:1;
}

sub compareRestrictions{
#compare umasks $um1 and $um2(both in decimal). Returns 1 if $um1 is more or equally restrictive than $um2. 
#Otherwise returns 0. Note that $um1 is not more restrictive than $um2 does not mean $um2 is more 
#restrictive than $um1
    my $um1 = shift;
    my $um2 = shift;
    if( ($um1 & $um2) == $um2){
        return 1;
    }
    else{
        return 0;
    }
}

##################################################
sub unit_test{
my $line = "0000234" ;
my $umask = validate_umask($line);
print "em_result=A test for last three digits are valid and rest of the digits are zero\n" ;
print "em_result=LINE TEXT =====> $line\n" ;
print "em_result=Umask returned Value(from $line) ====> $umask\n" ;
print "em_result=umask  is valid umask\n" ;

$line = "0000284" ;
$umask = validate_umask($line);
print "em_result=A test for whether any of last three digits is/are invalid(8..9)\n" ;
print "em_result=LINE TEXT =====> $line\n" ;
print "em_result=Umask returned Value(from $line) ====> $umask\n" ;
print "em_result=null is returned since one of last three digits of $line is not a valid digit\n" ;

$line = "0001234" ;
$umask = validate_umask($line);
print "em_result=A test for atleast one digits  being nonzero except the last three digits\n" ;
print "em_result=LINE TEXT =====> $line\n" ;
print "em_result=Umask returned Value(from $line) ====> $umask\n" ;
print "em_result=null is returned since $line is not a valid umask(last four non zero digits)\n" ;

$line = "0000234 111"; 
$umask = validate_umask($line);
print "em_result=A test for more than once words in umask line\n" ;
print "em_result=LINE TEXT =====> $line\n" ;
print "em_result=Umask returned Value(from $line) ====> $umask\n" ;
print "em_result=null is returned since $line has more than one space separated words\n" ;


$line = "023u"; 
$umask = validate_umask($line);
print "em_result=A test for whether any of last three digits is/are invalid(alph)\n" ;
print "em_result=LINE TEXT =====> $line\n" ;
print "em_result=Umask returned Value(from $line) ====> $umask\n" ;
print "em_result=null is returned since one of last three digits of $line is not a valid digit\n" ;

#################################################
#UNIT test compareRestrictions
$umask = "022";
my $ok = "23";
my $valid = compareRestrictions(oct($umask), oct($ok));
print "em_result=umask $umask|compared with $ok|gives $valid\n";
print "em_result=$umask is not more or equally restrictive than $ok\n";
if($valid != 0){
    print "em_result=**********TEST FAILED*****************\n";
}

$umask = "011";
my $ok = "10";
my $valid = compareRestrictions(oct($umask), oct($ok));
print "em_result=umask $umask|compared with $ok|gives $valid\n";
print "em_result=$umask is more or equally restrictive than $ok\n";
if($valid != 1){
    print "em_result=**********TEST FAILED*****************\n";
}

$umask = "111";
my $ok = "7";
my $valid = compareRestrictions(oct($umask), oct($ok));
print "em_result=umask $umask|compared with $ok|gives $valid\n";
print "em_result=$umask is not more or equally restrictive than $ok\n";
if($valid != 0){
    print "em_result=**********TEST FAILED*****************\n";
}
    
}    



