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:        CheckRhosts
# Agent description: Check permissions on .rhosts files
# Author:            Diego Zamboni
#
# History of modifications:
# 
# Known bugs:
# 
# Things to do:
# 
# Future work:
# 
# Suggestions made by people:
# 
# Generated automatically by ../bin/makeagent.pl on Tue Sep  7 23:55:45 1999.
# 
###### AUTOMATICALLY GENERATED FILE --- DO NOT EDIT ##########
#

# 11 "CheckRhosts.aas"
package CheckRhosts;

# Version number
# 14 "CheckRhosts.aas"
$VERSION=eval {do { my @r = (q$Revision: 1.11 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r };}; $VERSION=$VERSION;

# Agent parameters
%PARAMETERS=(
             Description        => "Check permissions on .rhosts files",
             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 CheckRhosts


Agent that detects incorrect permissions on user F<.rhosts> files. In
this case, we will define "incorrect permissions" as "having any
permission at all for anybody else than the owner". Under this
definition, permissions 400, 200, 100 or any combination of them is
acceptable, but any others (in particular, any permission on the
"group" and "other" fields) are not.

The following criteria is used to compute the status:

=over 4

=item *

If nobody has incorrect permissions of any kind, the status is 0 (zero).

=item *

For each user that has group or world read permission in his
F<.rhosts> file, we will add 0.5 to the status, rounding up (so that a
minimum status of 1 will be generated if one user has read permissions
in the file).

=item *

For each user that has group or world write permission in his F<.rhosts>
file, we will add 3 to the status.

If the user name happens to be "root", the status will immediately
jump to 10.

=item *

If the home directory of the user is not readable (and thus we cannot
check permissions on the F<.rhosts> file) or the F<.rhosts> file does
not exist, that user is considered safe.

=item *

If the sum goes over 10, it is set to 10.

=back 4

The message will be a string with the following format:

  Read:user,...:Write:user,...

where every user that has wrong read permissions will be listed in the
"Read" field, and every user that has wrong write permissions will be
listed in the "Write" field. Thus, a user may appear on both of them.

=head2 Interface

The essential functionality that we will need to control and monitor
this agent is the capability to specify which users we want to monitor,
and to request the list of users that are currently being monitored.
Thus, we will define three new commands:

=over 4

=item C<ADDUSERS Users =E<gt> 'user1[,user2,...]'>

Adds the users listed in the C<Users> parameter to the list of users
to be monitored.


=item C<DELUSERS Users =E<gt> 'user1[,user2,...]'>

Takes the named users off the monitoring list.


=item C<LISTUSERS>

Returns a field called "Users" that contains the list of users currently
being monitored.

=back 4

=cut

# Preamble code


# Provide an Init function.
sub Init {
  my $self=checkref(shift);
# 70 "CheckRhosts.aas"
  $Params{MyUsers}={};
  return $self;
}

# The Check function.
sub Check {
  my $self=checkref(shift);
# 73 "CheckRhosts.aas"
  my @users=keys(%{$Params{MyUsers}});
  my @readusers=();
  my @writeusers=();
  my $readstatus=0;
  my $writestatus=0;
  my $status;
  my $message;
  my $u;
  $self->Log("debug", "Entering Check routine.\n");
  foreach $u (@users) {
    $self->Log("debug", "Checking user $u.\n");
    my $home=(getpwnam $u)[7];
    if (!$home) {
      $self->Log("errors", "Null home directory for user $u.\n");
      next;
    }
    # If the stat fails (because no permission, or file doesn't exit)
    # we default the mode to zero.
    my $mode=(stat "$home/.rhosts")[2] || 0;
    my $omode=sprintf("%o", $mode);
    if (($mode & oct('022'))>0) { # Write permission.
      $self->Log("debug", "$u has incorrect write permissions $omode.\n");
      $writestatus+=3;
      push @writeusers, $u;
      $writestatus=10 if $u eq 'root';
    }
    if (($mode & oct('044'))>0) { # Read permission.
      $self->Log("debug", "$u has incorrect read permissions $omode.\n");
      $readstatus+=0.5;
      push @readusers, $u;
    }
  }
  # Round $readstatus up, but only if it has something.
  $readstatus=int($readstatus+0.5) if $readstatus>0;
  $status=$writestatus+$readstatus;
  $status=10 if $status>10;
  $message="Read:".join(",", @readusers).":Write:".join(",", @writeusers);
  $self->Log("debug", "Returning ($status, '$message')\n");
  return ($status, $message);
}
# Agent commands

sub command_ADDUSERS {
  my $self=checkref(shift);
  my ($message, %p)=@_;
  if (exists($p{Users}) && 1) {
    my $Users = $p{Users};
# 130 "CheckRhosts.aas"
  my @users=splitList($Users);
  my $usersref=$Params{MyUsers};
  my $u;
  $self->Log("debug", "Adding to list of monitored users: @users.\n");
  foreach $u (@users) {
    $usersref->{$u}=1;
  }
  return undef;
    # By default, return undef
    return undef;
  }
}

sub command_LISTUSERS {
  my $self=checkref(shift);
  my ($message, %p)=@_;
  if (1) {
    
# 165 "CheckRhosts.aas"
  $self->Log("debug", "Reporting current list of users.\n");
  return {Users => join(",", keys %{$Params{MyUsers}})};
    # By default, return undef
    return undef;
  }
}

sub command_DELUSERS {
  my $self=checkref(shift);
  my ($message, %p)=@_;
  if (exists($p{Users}) && 1) {
    my $Users = $p{Users};
# 146 "CheckRhosts.aas"
  my @users=splitList($Users);
  my $usersref=$Params{MyUsers};
  my $u;
  $self->Log("debug", "Removing from list of monitored users: @users.\n");
  foreach $u (@users) {
    delete $usersref->{$u};
  }
  return undef;
    # By default, return undef
    return undef;
  }
}

# End of entity marker
_EndOfEntity;
