Home | pfodApps/pfodDevices | WebStringTemplates | Java/J2EE | Unix | Torches | Superannuation | | About Us
 

Forward Logo (image)      

Freebees - Changing User passwords from a Webpage
Perl CGI file to process input from webpage

This perl file is called from the webpage to allow users to change their password. After checking the new password and the retry password are the same, it uses the webpasswd program to actually change the uses password via the system passwd program. It returns any messages to the user via an output webpage.

The perl file is actually run from a small C file which suid's to root. The perl system I am running on Solaris would not let me suid to root directly from the the perl program. The C file is show at the bottom of the page as is the sendmail program.

There may be a security hole in the sendmail program if it is accessiable to the general users as it runs as root and lets you send mail as any user. If in doubt do not install it. If you find a hole and how to fix it let me know. The permissions specified below only allow root and users in the other group to use the program.

The program checks the user's input and then calls webpasswd to actually change the user's password.

Any errors email an error message to the apporpiate person and displays an error message on the resulting webpage.

Make whatever are the appropiate changes to the variables at the top of this file to suit your system.

File change_passwd.pl

This file is placed in the /usr/local/etc/system.perl directory with the following permissions
-rwx--x--- 1 root other 7250 Sep 30 22:49 change_passwd.pl

#!/usr/bin/perl -w
#
#  Copyright (c)1997 Forward Computing and Control Pty. Ltd.
#  All rights reserved       ACN 003 669 994 NSW Australia.
#  written by Matthew Ford
#
#  Changes user's passwd given userid and password and new passwd
#
# Need this info
#  UserID and password new passwd and retry passwd
#
# Return 
#  Messages from password changing program
#
#  Process:
# needs USER.ID USER.PASSWD NEW.PASSWD RETRY.PASSWD  fields

$ENV{'IFS'} = '' if $ENV{'IFS'} ;
#  $ENV{'SHELL'} = '/sbin/sh' if $ENV{'SHELL'} ne '';
$ENV{'SHELL'} = '/sbin/sh';
$ENV{'PATH'} = '/usr/sbin:/usr/bin:/usr/local/bin';
$mailto = "SomeAdminUser\@your.domain.name"; # all mail to ?
$mailprog = ' /cww/test/cgi-bin/sendmail ';
$passwordprg = " /usr/local/etc/system.perl/webpasswd ";

$< = $>;  # make effective uid the real uid

# Retrieve Date
&get_date;

if ($ENV{'REQUEST_METHOD'} eq "GET") {
        $FORM_DATA = $ENV{'QUERY_STRING'};
} else {
        $LENGTH = $ENV{'CONTENT_LENGTH'};
                # $LENGTH = 14;  # for testing only
        while ($LENGTH) {
                $FORM_DATA .= getc(STDIN);
                $LENGTH--;
        }
}

foreach (split(/&/, $FORM_DATA)) {
        ($NAME, $VALUE) = split(/=/, $_);
        $NAME =~ s/\+/ /g;
        $NAME =~ s/%([0-9|A-F]{2})/pack(C,hex($1))/eg;
        $VALUE =~ s/\+/ /g;
        $VALUE =~ s/%([0-9|A-F]{2})/pack(C,hex($1))/eg;
        $MYDATA{$NAME} = $VALUE;
}
print "Content-type: text/html\n\n";
print "<HTML>\n";
print "<HEAD>\n";
print "<TITLE>Central West Web - Results of User Password Change</TITLE>\n";
print "</HEAD>\n";
print "<BODY>\n";
print "<H1><A HREF=\"../welcome.html\"><IMG SRC=\"/gifs/images/cwwsmall.gif\"";
print " ALIGN=\"BOTTOM\" ALT=\"[Image] Central West Web\"></A>";
print "The Results of Changing Your Password</H1>";


#       print " User's ID :\n     ";
#       chop($userid = <STDIN>); 
        $userid = $MYDATA{'USER.ID'};
        $userid =~ s/(^\s+)|(\s+$)//g;  # strip leading trailing blanks
        if (!$userid) {   # just Enter pressed
            print " <P><H3>The User ID is missing<P>";
            print " Click on the browser's <B>Back</B> button to return to the form<BR> and fill in the User ID.</H3>\n";
                print "</BODY>\n</HTML>\n";
              exit 1;
        }


#      print " User's Password:\n     ";
#       chop($userpasswd = <STDIN>);
        $userpasswd = $MYDATA{'USER.PASSWD'};
        $userpasswd =~ s/(^\s+)|(\s+$)//g;  # strip leading trailing blanks
        if (!$userpasswd) {   # just Enter pressed
            print " <P><H3>The Password is missing<P>";
            print "Click on the browser's";
            print " <B>Back</B> button to return to the form<BR> and fill";
            print " in the Password.</H3>\n";
                print "</BODY>\n</HTML>\n";
              exit 1;
        }


        $newpasswd = $MYDATA{'NEW.PASSWD'};
        $newpasswd =~ s/(^\s+)|(\s+$)//g;  # strip leading trailing blanks
        if (!$newpasswd) {   # just Enter pressed
            print " <P><H3>The New Password is missing<P>";
            print "Click on the browser's";
            print " <B>Back</B> button to return to the form<BR> and fill";
            print " in the New Password.</H3>\n";
                print "</BODY>\n</HTML>\n";
              exit 1;
        }

        $retrypasswd = $MYDATA{'RETRY.PASSWD'};
        $retrypasswd =~ s/(^\s+)|(\s+$)//g;  # strip leading trailing blanks
        if (!$retrypasswd) {   # just Enter pressed
            print " <P><H3>The New Password Again is missing<P>";
            print "Click on the browser's";
            print " <B>Back</B> button to return to the form<BR> and fill";
            print " in the New Password Again.</H3>\n";
                print "</BODY>\n</HTML>\n";
              exit 1;
        }

        if ($retrypasswd ne $newpasswd) {   # just Enter pressed
            print " <P><H3>The New Passwords do not match<P>";
            print "Click on the browser's";
            print " <B>Back</B> button to return to the form<BR> and fill";
            print " in both the new Passwords again.</H3>\n";
                print "</BODY>\n</HTML>\n";
              exit 1;
        }
print "\n";

  if (! defined( open(PASSWORD, $passwordprg . $userid ." " . $userpasswd . " " . $newpasswd . " | ")) ) {
     &mailerr("could not run '" . $passwordprg . "'\n");
        print "<P><H3> Internal Error<BR> Please report this to the ";
        print "<A HREF=\"mailto:webmaster\@cww.octec.org.au\">";
        print "webmaster\@cww.octec.org.au</A></H3><P>";
                print "</BODY>\n</HTML>\n";
              exit 1;
  }
  $_ = <PASSWORD>;  # get return line from passwrd prg
  close(PASSWORD);
  s/\n//g;   # remove all /r /n 
  s/\r//g;
       print "<H3>";
       print ;
       print "</H3>\n<P>";
       if (! /^Password changed/i ) {
            print "<H3>Click on the browser's";
            print " <B>Back</B> button to return to the form";
            print "</H3>\n";
                print "</BODY>\n</HTML>\n";
            exit 1;
       }

print "<HR>";

print "<P><A HREF=\"../welcome.html\"><IMG SRC=\"/gifs/images/cwwsmall.gif\"\n";
print " ALIGN=\"BOTTOM\" ALT=\"[Image] Central West Web\"></A>\n";
print "<A HREF=\"../welcome.html\">Central West Web, NSW, Australia</A>\n";
print "<HR><P>Copyright&#169; 1997 Forward Computing and Control Pty. Ltd.\n";
print "<BR>ACN 003 669 994, All rights reserved. (Email forward.com.au)\n";
# print $username, "\n";
print "</BODY>\n</HTML>\n";

exit;

#============================================================
sub calc_time {
   local($sec) = pop(@_);
   local($hrs,$mins,$minutes,$timestr,$timearray);

   # calc hours 
   $mins = ($sec / 60) - (($sec % 60) / 60);
   if ($sec % 60) { # add one 
      $mins = $mins + 1;
   }
   if ($mins < 1) {
      $mins = $mins + 1;
   }
   $minutes = $mins;

   $hrs = ($mins / 60) - (($mins % 60)/60);
   $mins = $mins - ($hrs * 60);

   $mins =sprintf("%0.0d",$mins);
   if (length($mins) < 2) {
       $mins = " " . $mins;
   }
   $hrs = sprintf("%0.0d",$hrs);
   if (length($hrs) < 1) {
       $hrs = "0";
   }
   if (length($hrs) < 2) {
       $hrs = " " . $hrs;
   }


   $timestr = $hrs . " hrs  " . $mins . " mins";
   @timearray = ($timestr, $minutes);
   @timearray;
}

sub get_date {

   @days = ('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday',
            'Saturday');
   @months = ('January','February','March','April','May','June','July',
              'August','September','October','November','December');

   ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
   if ($hour < 10) { $hour = "0$hour"; }
   if ($min < 10) { $min = "0$min"; }
   if ($sec < 10) { $sec = "0$sec"; }

   $date = "$days[$wday], $months[$mon] $mday, 19$year at $hour\:$min\:$sec";
   $shortdate = "$months[$mon] $mday, 19$year";
   $shortdate = $shortdate;
   $date = $date;
   $isdst = $isdst;
   $yday = $yday;
}

sub mailerr {
  local($errmsg) = pop(@_);
  open(MAIL,"|".$mailprog) || die "Can't open mail program :$!\n";
  print MAIL "To: ". $mailto . "\n";
  print MAIL "From: webmaster\@cww.octec.org.au\n";
  print MAIL "Subject: Error Trying to Change User's Password via Web page";
  print MAIL " for $userid\n";
  print MAIL "\n";
  print MAIL " While trying to change the user's password at\n ";
  print MAIL "    " . $date . "\n";
  print MAIL $errmsg . "\n\n";
  close(MAIL);
}

File change_passwd.c

This file is compiled with
cc change_passwd.c -o change_passwd
cp change_passwd /cww/test/cgi-bin
chmod to
---s--x--x 1 root other 5360 Sep 30 22:17 change_passwd
Note since this runs as root we depend on the webpasswd program changing to the user before trying to change the password.

/* user-acc.c */
main(argc,argv)
int argc;
char **argv;
{
    setuid(0);  /* user root */
    setgid(1);  /* group other */
    execv("/usr/local/etc/system.perl/change_passwd.pl",argv);
}

File sendmail.pl

This file is placed in the /usr/local/etc/system.perl directory with the following permissions
-rwx--x--- 1 root other 20624 Nov 8 13:10 sendmail.pl
This is called from the sendmail executiable shown further down
#!/usr/local/bin/perl -w
#  Copyright (c)1997 Forward Computing and Control Pty. Ltd.
#  All rights reserved       ACN 003 669 994 NSW Australia.
#  written by Matthew Ford
#
#  sendmail.pl
# this programs sends mail after su to root
#
$mailprog = '/usr/local/lib/sendmail -t';
# take to from from input
#
$ENV{'IFS'} = '' if $ENV{'IFS'} ;
#  $ENV{'SHELL'} = '/sbin/sh' if $ENV{'SHELL'} ne '';
$ENV{'SHELL'} = '/sbin/sh';
$ENV{'PATH'} = '/usr/sbin:/usr/bin:/usr/local/bin';

$< = $>;  # make effective uid the real uid

open(MAIL,"| $mailprog");
while(<STDIN>) {
        print MAIL ;
}
close(MAIL);

File sendmail.c

This file is compiled with 
cc sendmail.c -o sendmail
and is placed in a suitable directory with the following permissions
---s--s--- 1 root other 5340 Sep 22 22:36 sendmail
/* sendmail.c */
main(argc,argv)
int argc;
char **argv;
{
    setuid(0);  /* user root */
    setgid(1);  /* group other */
    execv("/usr/local/bin/sendmail.pl", argv);
}

Refer to Conditions of Use


Forward home page link (image)

Contact Forward Computing and Control by
©Copyright 1996-2012 Forward Computing and Control Pty. Ltd. ACN 003 669 994