From: Jos Backus <jos@oce.nl>
To: djb-qmailbeta@koobera.math.uic.edu
Subject: mkpoppass/chkpoppass
Date: Mon, 05 Aug 1996 09:58:13 +0200


	Hi Dan, all,

Not sure whether this is useful to anybody, but I thought I'd make a
contribution of sorts. chkpoppass can be used instead of checkpassword.

#!/usr/local/bin/perl
# mkpoppass -- pop passwd file maintenance hack
# 30 july 1996
# jos@oce.nl

$mailhome = "/var/qmail/mailhome";
$passwdfile = "$mailhome/poppasswd";

sub makenewpasswd {
  my $passwd = shift;
  srand(time ^ $$);
  @saltchars=('a'..'z','A'..'Z',0..9,'.','/');
  $salt =$saltchars[int(rand($#saltchars+1))];
  $salt.=$saltchars[int(rand($#saltchars+1))];
  $cpw=crypt($passwd,$salt);
  $cpw=crypt($passwd,$cpw);
}

{
last unless $ARGV[0] =~ /^-/;
$_ = shift;
$check++, redo if /-c/;
$delete++, redo if /-d/;
$quiet++, redo if /-q/;
$edit++, redo if /-e/;
$passwdfile = shift, redo if /-f/;
die "bad flag: $_";
}

$view = @ARGV == 0;

$new_user = shift;
$new_passwd = shift;

if ($edit) {
  $editcmd = $ENV{"EDITOR"} || "vi";
  $editcmd .= " -c /$new_user" if $new_user;
  $editcmd .= " $passwdfile";
  system $editcmd;
  exit $?;
}

if (!$view&&!$check) {
  if (!$new_passwd) {
    print "Password for $new_user: ";
    chop($new_passwd=<STDIN>);
  }
}

$found = 0;
open PASSWD,$passwdfile or die;
while (<PASSWD>) {
  if (/\s*#/ or /^\s*$/) { # keep comments/empty lines
    push @lines, $_;
    next;
  }
  chomp;
  ($user,$passwd) = split /\s*:\s*/;
  if ($user eq $new_user) {
    $found = 1;
    if ($delete) {
      $writefile = 1;
      next;
    }
    if ($check) {
      last;
    } else {
      $writefile = 1;
      $passwd = makenewpasswd $new_passwd;
    }
  }
  push @lines,"$user:$passwd\n";
}
close PASSWD;

if ($view) {
  for (@lines) { print; }
  exit 0;
}

if ($check) {
  if ($found) {
    $c = crypt($new_passwd,$passwd);
    #print "$user: old '$passwd', new '$c'\n" if !$quiet;
    $ok = ($passwd eq $c);
    print $ok ? "ok" : "error","\n";
    exit !$ok;
  } else {
    die "user $new_user not in passwd file!\n";
  }
}

if (!$found) { # new user
  $user = $new_user;
  $passwd = makenewpasswd $new_passwd;
  push @lines,"$user:$passwd\n";
  $writefile = 1;
}

if ($writefile) {
  rename $passwdfile,"$passwdfile.bak" if -f $passwdfile;
  open PASSWD,">$passwdfile" or die "Can't write $passwdfile: $!\n";
  for (@lines) { print PASSWD; }
  close PASSWD;
  print "Wrote ",scalar @lines," lines to $passwdfile\n" if !$quiet;
}

#!/usr/local/bin/perl
# chkpoppass -- check pop password, setup and call qmail-pop3d if OK
# 30 july 1996
# jos@oce.nl

$mailhome = "/var/qmail/mailhome";
$poppasswdfile = "$mailhome/poppasswd";

$shell = '/bin/sh';

$user_program = shift || die "need a program to run!\n";

open X,"<&=3" or exit 111;
$_ = <X>;
($user,$passwd) = /^(.*)\0(.*)\0/;
close X;
$found=$user&&$passwd;

sub poppasswd {
  my ($sent_user,$sent_passwd) = @_;
  local($user,$passwd);
  $found = 0;
  open PASSWD,$poppasswdfile or exit 111;
  while (<PASSWD>) {
    next if /\s*#/ or /^\s*$/;
    chomp;
    ($user,$passwd) = split /\s*:\s*/;
    next if $user ne $sent_user;
    if ($passwd eq crypt($sent_passwd,$passwd)) { $found = 1; last; }
  }
  close PASSWD;
  return $found;
}

sub etcpasswd {
  my ($sent_user,$sent_passwd) = (@_);
  local($user,$passwd);
  ($user,$passwd,$uid,$gid,$quota,$comment,$gecos,$dir,$shell) =
    getpwnam($sent_user);
  $found = ($user and $passwd eq crypt($sent_passwd,$passwd));
  return $found;
}

if ($found) {
  if (poppasswd $user,$passwd) { $home="$mailhome/$user"; $found=1; }
  elsif (etcpasswd $user,$passwd) { $home="$dir"; $found=1;}
}

if ($found) {
  $ENV{"SHELL"} = $shell;
  $ENV{"USER"} = $user;
  $ENV{"HOME"} = $home;
  chdir $ENV{"HOME"} or exit 111;
  exec $user_program, @ARGV; 
}

exit 2;

Groetjes,
Jos
--
Jos Backus           _/  _/_/_/                                 R-IS/SNB
                    _/  _/   _/                       Oce-Nederland B.V.
                   _/  _/_/_/                     Venlo, The Netherlands
             _/   _/  _/    _/
jos@oce.nl    _/_/   _/_/_/                  #include <std/disclaimer.h>
