#! /usr/bin/perl -T
# $Id: poppasswd,v 1.1.2.4 2000/09/07 06:53:35 david Exp $
# Add, delete, or modify a rot13 passwd in /etc/cram-md5.pwd file.
# Usage: apoppasswd [-d] [loginid]

use strict;
use Fcntl ':flock'; # import LOCK_* constants;

$ENV{"PATH"} = "/bin:/usr/bin";
$ENV{"BASH_ENV"} = "";

# Configuration
my $rot13 = 1; # Set to 1 to rot13 passwords.
my $pfile = "/etc/cram-md5.pwd"; # Matches with UW-IMAP in /etc directory.
my $delete = 0; # Default is to not delete entry.

# Local variables.
my $loginid;
my ($ploginid, $ppasswd);
my $found = 0; # Have we found the loginid line yet?
my $newpasswd;

$SIG{INT} = \&catch_zap; # Delete temp file and restore terminal parms.

$delete = 1, shift if ( $ARGV[0] eq "-d" );

$loginid = shift;

if ( $< == 0 )
   {
   doit();
   }
 else
  {
  if ( $loginid )
     {
     usage();
     }
   else
    {
    doit();
    }
  }

exit 0;

sub doit
{
if ( !$loginid )
   {
   $loginid = (getpwuid( $< ))[0];
   }

#print "Debug: User = $loginid\n";

open( PFILE, "<$pfile" ) || die "Can't open $pfile.\n";
flock( PFILE, LOCK_EX ); # Lock the file until it is closed.
open( OFILE, ">$pfile.$$.tmp" ) || die "Can't open $pfile.$$.tmp.\n";

chmod 0600, "$pfile.$$.tmp";

while ( <PFILE> )
   {
   $ploginid = $ppasswd = "";
   chomp;
   ($ploginid = $1, $ppasswd = $2) if ( /^(.*)\t(.*)$/ );
   # print "Debug: $ploginid, $ppasswd\n";
   $found = $ploginid eq $loginid if ( ! $found );
   if ( ! $delete && $ploginid eq $loginid  )
      {
      $ppasswd = ($newpasswd = changepwd( $ppasswd )) ? $newpasswd : $ppasswd;
      }
   print OFILE "$ploginid\t$ppasswd\n" unless ( $delete && $ploginid eq $loginid );
   }

# Add passwd if we are not deleting and it hasn't been found yet.
if ( ! $delete && ! $found )
   {
   $ploginid = $loginid;
   if ( ($ppasswd = makepwd()) )
      {
      print OFILE "$ploginid\t$ppasswd\n";
      }
   }

close( PFILE );
close( OFILE );

rename "$pfile", "$pfile.bak";
rename "$pfile.$$.tmp", "$pfile";

unlink "$pfile.$$.tmp";

exit 0;
}

sub rot13
{
my $p = shift;
my $i;
my $c;

for ( $i = 0; $i < length( $p ); $i++ )
   {
   $c = substr( $p, $i, 1 );
   if ( (($c ge 'a') && ($c le 'm')) || (($c ge 'A') && ($c le 'M')) )
      {
      $c = chr( ord($c) + 13 );
      }
    else
      {
      if ( (($c ge 'n') && ($c le 'z')) || (($c ge 'N') && ($c le 'Z')) )
         {
         $c = chr( ord($c) - 13 );
         }
      }
   substr( $p, $i, 1 ) = $c;
   }

return $p;
}

sub changepwd()
{
my $old_passwd = shift;
my $check_passwd;

print "Enter old password: ";
system "stty -echo";
$check_passwd = <>;
system "stty echo";
print "\n";
chomp $check_passwd;
$check_passwd = rot13( $check_passwd ) if ( $rot13 );

if ( $check_passwd ne $old_passwd )
   {
   print "Passwords do NOT match.\n";
   return "";
   }

print "Changing password.\n";
return ($check_passwd = makepwd()) ? $check_passwd : "";
}

sub makepwd
{
my $p;
my $check;

print "New password: ";
system "stty -echo";
$p = <>;
system "stty echo";
print "\n";
chomp $p;
$p = rot13( $p ) if ( $rot13 );

print "Verify password: ";
system "stty -echo";
$check = <>;
system "stty echo";
print "\n";
chomp $check;
$check = rot13( $check ) if ( $rot13 );

if ( $check ne $p )
   {
   print "Passwords do not match.\n";
   return "";
   }

return $p;
}

sub catch_zap
{
unlink "$pfile.$$.tmp";
system "stty echo";
exit 1;
}

sub usage
{
die "Only root can specify a user\nUsage: poppasswd [-d] [loginid]\n";
}
