#!/usr/pubsw/bin/perl

&parse_args;

if ($user) {
   $telnet_opt .= " -l $user";
   $kftgt_opt .= "-l $user";
}

unless ($o_forward) {
   $cmd = "$kftgt $kftgt_opt $host";
   print "$cmd\n" if $o_verbose;
   system $cmd;
   die "$kftgt_opt failed on remote host $host\n" if $?>>8;

  $cmd = "$rsh $host $telnet_opt ";
  if ($o_verbose) {print STDOUT "$cmd", "'/usr/pubsw/bin/aklog; ",
      join(' ',@ARGV), "; /usr/pubsw/bin/kdestroy; /usr/pubsw/bin/unlog'\n";}
  system $cmd . "'/usr/pubsw/bin/aklog; " . join(' ',@ARGV)
      . "; /usr/pubsw/bin/kdestroy; /usr/pubsw/bin/unlog'";
  $rval = $?>>8;
  exit($rval);
}

   $cmd = "$rsh $host $telnet_opt ";
   if ($o_verbose) {print STDOUT "$cmd", "'", join(' ',@ARGV), "'\n";} 
   system $cmd . "' " . join(' ',@ARGV). "'";
   $rval = $?>>8;
   exit($rval);

sub parse_args {
  $0 =~ s%.*/%%;
  $kftgt  = $ENV{"KLOGIN_KFTGT_PROGRAM"} || "/usr/pubsw/bin/kftgt";
  $rsh = $ENV{"KLOGIN_RSH_PROGRAM"} || "/usr/pubsw/bin/rsh";
  &usage if $ARGV[0] =~ /^(-h|--help)$/;
  $host = &get_fqdn(shift @ARGV);
  while ($_ = shift @ARGV) {
    if (!/^-/) {
	unshift (@ARGV, $_),
	last;
    }
    last if $_ eq '--';
    foreach $_ (split(//,substr($_,1))) {
      if (/h/) {  &usage;      }
      elsif (/f/) {  $o_forward = !$o_forward; }
      elsif (/v/) { print STDERR "$0 version 1.0\n"; exit(0); }
      elsif (/l/) { $user = shift @ARGV || &usage; }
      elsif (/V/) { $o_verbose = !$o_verbose; }
      else        {  &usage;}
     }
    }

  if ($_  = $ENV{"KLOGIN_OPTS"}) {
    $o_verbose = !$o_verbose if /V/;
    $o_forward = !$o_forward if /f/;
  }
}

sub get_fqdn {
  local($host) = @_;
  local($name,$aliases,$addrtype,$length,@addrs) = gethostbyname($host);

  die "$0: unknown host: $host\n" if ($name eq '');

  $name = (gethostbyaddr($addrs[0],$addrtype))[0];

  return $host if ($name eq '');
  return $name;
}

sub usage {

print<<USAGE;

usage: $0 hostname [options] remote-command

  -f             don't forward tickets with kftgt
  -h             display this help
  -l user        remote user
  -v             display version
  -V             display commands before executing them

USAGE

 exit(1);
}

=head1 NAME

krsh - Kerberos rsh with v4 ticket forwarding

=head1 SYNOPSIS

krsh [B<-fhvV>] [B<-l> I<username>] I<host> I<command> ...

=head1 DESCRIPTION

B<krsh> forwards your Kerberos ticket-granting ticket to the machine I<host>
using kftgt(1) and then executes I<command> on that system using Kerberos
rlogin.  It assumes that the remote system has aklog(1), kdestroy(1), and
unlog(1) installed in /usr/pubsw/bin (and therefore is generally not
suitable for use in a non-Stanford environment).

Normally it's not necessary to forward one's ticket to execute commands
remotely with rsh.  The reason for the existence of this wrapper is to
facilitate running programs that need to write to disk on a remote system
that uses AFS.  The commands given to B<krsh> will be wrapped by an
execution of /usr/pubsw/bin/aklog before the command to obtain an AFS token
from the forwarded ticket and /usr/pubsw/bin/kdestroy and
/usr/pubsw/bin/unlog after the command to destroy the forwarded ticket and
obtained token.

The host given to B<krsh> is put through a forward and then reverse DNS
lookup before being used, to resolve any CNAMEs to their canonical hosts and
to handle load-balanced hosts or hosts with multiple A records.

=head1 OPTIONS

=over 4

=item B<-f>

Don't forward tickets to the remote host.  This tells B<krsh> not to run
kftgt(1).  aklog, kdestroy, and unlog are still run.  This option is
generally only useful if your tickets have already been forwarded to the
remote host via other means.

=item B<--help>, B<-h>

Print a summary of options and exit.

=item B<--login>=I<username>, B<-l> I<username>

Set the username on the remote system to I<username>.  This is the user to
log in as as well as user to which to forward tickets.  If this option is
not given, the default will be the username on the local host.  This option
will often be necessary if the local username differs from the Kerberos
principal name, since B<kftgt> and B<rsh> differ on the default otherwise.

=item B<--verbose>, B<-V>

Print out each command and the arguments used before it's executed.

=item B<--version>, B<-v>

Print the version number of B<klogin> and exit.

=back

=head1 BUGS

Due to hard-coded paths, this script is not suitable for use in a
non-Stanford environment or on machines that don't mount Stanford's pubsw
software tree.

Regular rsh options are not accepted and passed to rsh.

=head1 SEE ALSO

aklog(1), kdestroy(1), kftgt(1), klogin(1), rsh(1), unlog(1)

=head1 AUTHORS

B<krsh> was originally written by Larry Schwimmer <opusl@stanford.edu>.

Questions and bug reports may be sent to kerberos-help@stanford.edu, but
please be aware that we only support Stanford affiliates and may not be able
to help with problems at other sites.

=head1 LICENSE

Copyright 1996, 2001, 2002 Board of Trustees, Leland Stanford Jr. University
  
All rights reserved.
  
Export of this software from the United States of America may require a
specific license from the United States Government.  It is the
responsibility of any person or organization contemplating export to obtain
such a license before exporting.

WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute this
software and its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all copies and
that both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Stanford University not be
used in advertising or publicity pertaining to distribution of the software
without specific, written prior permission.  Stanford University makes no
representations about the suitability of this software for any purpose.  It
is provided "as is" without express or implied warranty.

THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

=cut
