eval 'exec perl -x $0 ${1+"$@"}' # -*-perl-*-
  if 0;
#!perl -w
#
# ======================================================================
# This file is Copyright 1998,1999 by the Purdue Research Foundation and
# may only be used under license.  For terms of the license, see the
# file named COPYRIGHT included with this software release.
# AAFID is a trademark of the Purdue Research Foundation.
# All rights reserved.
# ======================================================================
#
# AAFID2 system
# Agent name:        FTP
# Agent description: Checks the anonymous ftp configuration
# Author:            Penka Vassileva Markova
#
# History of modifications:
#  Modifications by Diego Zamboni (zamboni@cs.purdue.edu)
#  $Log: FTP.pm,v $
#  Revision 1.8  1999/09/08 04:57:13  zamboni
#  Regenerated from AAS files.
#
#  Revision 1.4  1999/09/07 00:49:25  zamboni
#  Updated copyright notice.
# 
#  Revision 1.3  1998/08/11 00:48:26  zamboni
#  Made some corrections, added comments, etc.
# 
# Known bugs:
# 
# Things to do:
# 
# Future work:
# 
# Suggestions made by people:
# 
# Generated automatically by ../bin/makeagent.pl on Tue Sep  7 23:55:49 1999.
# 
###### AUTOMATICALLY GENERATED FILE --- DO NOT EDIT ##########
#

# 10 "FTP.aas"
package FTP;

# Version number
# 12 "FTP.aas"
$VERSION=eval {1.0}; $VERSION=$VERSION;

# Agent parameters
%PARAMETERS=(
             Description        => "Checks the anonymous ftp configuration",
             CheckPeriod        => eval {10},

             FiltersNeeded => {  }
            );

# Package loading
use AAFID::Agent;
use AAFID::Log;
use AAFID::Common;


use vars qw (
             @ISA
             $VERSION
             %PARAMETERS
            );

# Define the superclass.
 @ISA=qw(AAFID::Agent);

=head1 FTP



=cut

# Preamble code


# Provide an Init function.
sub Init {
  my $self=checkref(shift);
# 26 "FTP.aas"
  $self->Log_activate("debug");
  $max_status = 10 ;
  $min_status =  0 ;
  $default = 'Default';
  $in_ftpusers = 'Default_ftpusers' ; # if not in the file /etc/ftpusers

  $Params{MyFiles}={};
  $Params{MyFiles}{$default}{$default} = 0 ;
  $Params{MyFiles}{$default}{$in_ftpusers} = 0 ;

  $Params{MyData} = {} ;
  $Params{MyData} = { passwd_file => "/etc/passwd",
                      group_file  => "/etc/group" ,
                      ftp_user => "ftp",
		      ftpusers_file => "/etc/ftpusers",
                     };

  $Params{MyWeights}={} ;
  $Params{MyWeights}={ bad_root => 8, 
		       same_passwd_files => 3,
		       same_group_files => 3,
		       ftpusers_not_opened=>5
                    ,
                   } ;
  return $self;
}

# The Check function.
sub Check {
  my $self=checkref(shift);
# 52 "FTP.aas"
  my $message = ""; my $owner_message=""; my $ftpuser_message="";
  my $status = 0 ;

  if ( $Params{MyData}{ftp_user} =~ /^\s*$/) { 
	$status = $max_status ; 
	$message = "Empty ftp user name; no further checks are done; "; 
	goto END_OF_CHECK ; 
  }

  my $root = ( getpwnam $Params{MyData}{ftp_user} )[7] ;

  # If user does not exist, it's ok.
  if (!defined($root)) {
    $status = 0;
    $message = "FTP user '$Params{MyData}{ftp_user} does not exist; no further checks done; ";
    goto END_OF_CHECK;
  }

  # If user exists but its home directory not, it's not ok.
  if (! -d $root) { 
	$status = $max_status ; 
	$message = "Home directory '$root' for user '$Params{MyData}{ftp_user}' does not exist; no further checks done; "; 
	goto END_OF_CHECK ; 
  }

  # If ftp user home directory is root, it's not ok.
  elsif ( $root eq "/"){
	$status += $Params{MyWeights}{bad_root};
        $message = "Ftp Root is '/'; "
  }

  $Params{MyData}{ftp_passwd_file} ||= "< $root/etc/passwd";
  $Params{MyData}{ftp_group_file} ||= "< $root/etc/group";

  # passwd_file is the global password file, 
  # ftp_passwd_file is the ftp password file.
  
  if ( # Both password files exist. 
      ( ( -e $Params{MyData}{passwd_file} ) &&
	( -e $Params{MyData}{ftp_passwd_file})
      ) 
      && # The file names are different
      ( $Params{MyData}{passwd_file} ne $Params{MyData}{ftp_passwd_file} )
      && # Their contents is equal, which is indicated by cmp not 
         # producing any output
      !( `cmp $Params{MyData}{passwd_file} $Params{MyData}{ftp_passwd_file}`)
     )
  {
    $status += $Params{MyWeights}{same_passwd_files}; 
    $message .= "The password file and the ftp password file are the same; ";
  }

  # group_file is the global (system) group file,
  # ftp_group_file is the ftp group file.

  if ( # Both group files exist 
      ( ( -e $Params{MyData}{group_file} ) &&
	( -e $Params{MyData}{ftp_group_file})
      ) 
      && # The file names are different
      ( $Params{MyData}{group_file} ne $Params{MyData}{ftp_group_file} )
      && # Their contents is equal
      !( `cmp $Params{MyData}{group_file} $Params{MyData}{ftp_group_file} `)
     )
  {
    $status += $Params{MyWeights}{same_group_files};
    $message .= "The group file and the ftp group file are the same; ";
  }

  # Read the ftpusers file into %ftp_users_scalar
  my %ftp_users_scalar;
  my $FTP_USERS_FILE = $Params{MyData}{ftpusers};

  if ( ( defined($FTP_USERS_FILE) ) &&
       ( open FTP_USERS_FILE) )
  {
        while ($line=<FTP_USERS_FILE>) { 
	  chomp($line); $ftp_users_scalar{$line} = 1 ;
	}
  }
  else {
    $status += $Params{MyWeights}{ftpusers_not_opened}; 
    $message .="Can't open '$Params{MyData}{ftpusers}' file; ";
  }
	
  my $owner;
  my $status_change ;
  my $current_file;

  foreach $current_file ( reverse sort keys %{$Params{MyFiles}}){
    next if ($current_file eq $default) ;
    $owner = scalar getpwuid ( (stat "$root.$current_file" )[4]);
    $status_change = $Params{MyFiles}{$current_file}{$owner} 
               || $Params{MyFiles}{$current_file}{$default}
	       || $Params{MyFiles}{$default}{$default} ;
    $owner_message.= "$current_file, " if ( $status_change > 0 );
    $status += $status_change ;

    if ( ! defined $ftp_users_scalar{$current_file} ) {
    	$status_change = $Params{MyFiles}{$current_file}{$in_ftpusers}
	       || $Params{MyFiles}{$default}{$in_ftpusers} ;
    	$ftpuser_message.= "$current_file, " if ( $status_change > 0 );   }

  }

END_OF_CHECK:
  if ( $status > $max_status ) 
      { $status = $max_status; } 

  if ($owner_message ne "") { 
    chop $owner_message;
    chop $owner_message;
    $message.= "Files with ownership problem: $owner_message; " ;
  }

  if ($ftpuser_message ne "") {
    chop $ftpuser_message;
    chop $ftpuser_message;
    $message .= " Files which are not in /etc/ftpuser: $ftpuser_message; "
  }

  if ( $message eq "" ) {
    $message = "OK";
  }
  else {
    chop $message;
    chop $message;
    $message.=".";
  }

  return ( $status, $message );

#=============================================================================
###
#	MyFiles
###
}
# Agent commands

sub command_ADD_FILE {
  my $self=checkref(shift);
  my ($message, %p)=@_;
  if (exists($p{Info}) && 1) {
    my $Info = $p{Info};
# 189 "FTP.aas"
###
## adds the data for a file; if the file have existed, all previous data
#    about it would be lost.
## $default is an exception, and for it ADD_FILE is same as CHANGE_FILE
## the input is expected to be a list with content: file name, ( file owner or 
#    $in_ftpusers(now 'in_ftpusers') for the case of not being in /etc/ftpusers , 
#    value to be recorded )* as many times as needed
#####
    my @list = splitList($Info);
    my $file_name = shift (@list ) ;

  if ( $file_name ne $default ) 
	{$Params{MyFiles}{$file_name} = {};}

   while ( scalar @list > 0 ) {
	$value = pop @list ;
	$owner = pop @list ;
	$Params{MyFiles}{$file_name}{$owner} = $value ;
    }
  $self->Log('debug', "Adding values for $file_name\n");
    # By default, return undef
    return undef;
  }
}

sub command_LIST_WEIGHT_FIELDS {
  my $self=checkref(shift);
  my ($message, %p)=@_;
  if (1) {
    
# 332 "FTP.aas"
  my $list = "";
  foreach $file (  keys %{$Params{MyWeights}}) 
		{ $list.= ":: $file => $Params{MyWeights}{$file} "; }
  $self->Log('debug', "Listing the ftpusers files\n"); 
  return {WEIGHT_FIELDS => $list } ;
    # By default, return undef
    return undef;
  }
}

sub command_LIST_FTPUSERS_SPECIAL_FILES {
  my $self=checkref(shift);
  my ($message, %p)=@_;
  if (1) {
    
# 293 "FTP.aas"
##
# returns in a list the names of all monitored files , separated by ', '
##
  my $list ;
  my @list ;
  foreach $file (  keys %{$Params{MyFtpusersFiles}}) 
	{if (( ( defined $Params{MyFiles}{$default}{$in_ftpusers}) 
		&& ($Params{MyFiles}{$default}{$in_ftpusers} > 0) )
	   || ( defined $Params{MyFiles}{$file}{$in_ftpusers}) 
		&& ($Params{MyFiles}{$file}{$in_ftpusers} > 0) )

		{ push @list, $file;} }
  $list = join ( ",", @list ) ;
  $list =~ s/$default(, *)*// ;
  $self->Log('debug', "Listing the ftpusers files\n"); 
  return {FTPUSERS_Files => $list } ;
    # By default, return undef
    return undef;
  }
}

sub command_FILES_RECORD {
  my $self=checkref(shift);
  my ($message, %p)=@_;
  if (exists($p{Info}) && 1) {
    my $Info = $p{Info};
# 239 "FTP.aas"
##
# returns a all the records for the given files, in a specific form
## 

  my @Name= splitList($Info) ;
  my $result ;

  foreach $name(@Name)
  {
    if ( defined ($Params{MyFiles}{$name}))
	{
	    $result.= "File name => :: $name;  Owners= > ";
	    foreach $weigh ( sort keys %{$Params{MyFiles}{$name}})
	        { if ( $weigh ne $in_ftpusers) {$result.=":: $weigh : $Params{MyFiles}{$name}{$weigh} ";}}
	    $result.="; In ftpusers file => ";
	    if ( defined $Params{MyFiles}{$name}{$in_ftpusers}) 
	        { $result.=":: yes : $Params{MyFiles}{$name}{$in_ftpusers}) ";}
	    $result.=";";
	}
    else
    {
	$result.= "File name => :: $name; Owners= > :: ; In ftpusers file => :: ;";
    }
  }  
  $self->Log('debug', "Showing data fields for files\n"); 
  return { Files_Records => $result };
    # By default, return undef
    return undef;
  }
}

sub command_CHANGE_WEIGHT_FIELDS {
  my $self=checkref(shift);
  my ($message, %p)=@_;
  if (exists($p{Info}) && 1) {
    my $Info = $p{Info};
# 325 "FTP.aas"
  my @list = splitList($Info);
  my $data_name = shift (@list ) ;
	$value = pop @list ;
	$Params{MyWeights}{$data_name} = shift (@list) ;
  $self->Log('debug', "Changing the values for $file_name\n");
    # By default, return undef
    return undef;
  }
}

sub command_LIST_DATA_FIELDS {
  my $self=checkref(shift);
  my ($message, %p)=@_;
  if (1) {
    
# 318 "FTP.aas"
  my $list = "";
  foreach $file (  keys %{$Params{MyData}}) 
		{ $list.= ":: $file => $Params{MyData}{$file} "; }
  $self->Log('debug', "Listing the ftpusers files\n"); 
  return {FTPUSERS_Files => $list } ;
    # By default, return undef
    return undef;
  }
}

sub command_DELETE_ALL {
  my $self=checkref(shift);
  my ($message, %p)=@_;
  if (1) {
    
# 281 "FTP.aas"
###
## deletes all files with special treatment ( 'Default' remains )
###
  foreach $current( keys %{$Params{MyFiles}})
	{
	  delete $Params{MyFiles}{$current} if ( $current ne $default);
	}
  $self->Log('debug', "Removing ALL files from nondefault treatment\n"); 

#=========================================================================
    # By default, return undef
    return undef;
  }
}

sub command_CHANGE_DATA_FIELDS {
  my $self=checkref(shift);
  my ($message, %p)=@_;
  if (exists($p{Info}) && 1) {
    my $Info = $p{Info};
# 311 "FTP.aas"
  my @list = splitList($Info);
  my $data_name = shift (@list ) ;
	$value = pop @list ;
	$Params{MyData}{$data_name} = shift (@list) ;
  $self->Log('debug', "Changing the values for $file_name\n");
    # By default, return undef
    return undef;
  }
}

sub command_DELETE_FILES {
  my $self=checkref(shift);
  my ($message, %p)=@_;
  if (exists($p{Info}) && 1) {
    my $Info = $p{Info};
# 269 "FTP.aas"
###
## deletes the entries of files in the list
###
  my @list = splitList($Info);

  foreach $list( @list )
  {
	if ( $list ne $default) { delete $Params{MyFiles}{$list} ;}
  }
  $self->Log('debug', "Removing files from nondefault treatment\n");
    # By default, return undef
    return undef;
  }
}

sub command_CHANGE_FILE {
  my $self=checkref(shift);
  my ($message, %p)=@_;
  if (exists($p{Info}) && 1) {
    my $Info = $p{Info};
# 211 "FTP.aas"
##
# same as ADD_FILE, however any data for the given filesystem already exists, it
#   will not be changed except if specifically stated ; 
# use $in_ftpusers = 'in_ftpusers' for entering points for the case of not being in the
#   /etc/ftpusers file
##
  my @list = splitList($Info);
  my $file_name = shift (@list ) ;

   while ( scalar @list > 0 ) {
	$value = pop @list ;
	$owner = pop @list ;
	$Params{MyFiles}{$file_name}{$owner} = $value ;
    }
  $self->Log('debug', "Changing the values for $file_name\n");
    # By default, return undef
    return undef;
  }
}

sub command_LIST_SPECIAL_FILES {
  my $self=checkref(shift);
  my ($message, %p)=@_;
  if (1) {
    
# 228 "FTP.aas"
##
# returns in a list the names of all monitored files , separated by ', '
##
  my $list ;
  $list = join ( ",", keys %{$Params{MyFiles}}) ;
  $list =~ s/$default(, *)*// ;
  $self->Log('debug', "Listing the files with nondefault values\n"); 
  return {Special_Files => $list } ;
    # By default, return undef
    return undef;
  }
}

# End of entity marker
_EndOfEntity;
