#!/usr/bin/perl

require "/Admin/apache/config/d0world/cgi-bin/cgi-lib.pl" ;

print &PrintHeader;
print &HtmlTop("Password change page");

$FAILMESSAGE = "<P>Your login or password was incorrect. Please hit the back button and try again.<P>";
$ADMINPASSWORDFILE = "/Admin/wsrvd0/auth/passwd.admin";
$PASSWORDFILE = "/Admin/wsrvd0/auth/passwd";

# (FF) the following should be modified to point to the actual executables
$CHECKPASSWORD =  "/Admin/wsrvd0/auth/apache/htcheck";
$MODIFYPASSWORD = "/Admin/wsrvd0/auth/apache/htpasswd";

if (&ReadParse(*input)) {
        if ( $input{'adminpassform'} ) {
                &admin_passwd_form;
        } elsif ( $input{'adminchgpass'} ) {
                &admin_change_password;
        } else {
                &process_new_passwd;
        }
} else {
        &display_form;
}

print &HtmlBot;

### End of script

sub display_form {
        print ("Enter your current login id and password below and then your desired new passwd twice.<P>\n");
#       print ("<form action=\"/cgi-bin/d0-admin/passwdadmin/webpasswd.pl\"
        print ("<form action=\"/cgi-bin/webpasswd.pl\"
                method=\"POST\"><center>
                Login id:<BR>
                <input type=text name=\"loginid\" size=20>
                <P>Current password:<BR>
                <input type=password name=\"passwd\" size=20><P>
                <P>New password:<BR>
                <input type=password name=\"newpass1\" size=8>
                <P>Please retype your new password:<BR>
                <input type=password name=\"newpass2\" size=8>
                <P><input type=submit value=\"Submit\">
                <input type=reset value=\"Clear\">
                </center></form><p>\n");
#       print ("If you are an admin you can <a href=\"/cgi-bin/d0-admin/passwdadmin/webpasswd.pl?adminpassform=y\">change a user password</a><P>\n");
        print ("If you are an admin you can <a href=\"/cgi-bin/webpasswd.pl?adminpassform=y\">change a user password</a><P>\n");
}

sub process_new_passwd {


        if ((! $input{'passwd'}) || (! $input{'loginid'})) {
                $BAILMESSAGE = "You must enter a login id and password";
                &bail;
        }
        
        if ( "$input{'newpass1'}" ne "$input{'newpass2'}" ) {
                $BAILMESSAGE = "The two new passwords did not match";
                &bail;
        }

        if ( "$input{'newpass1'}" eq "$input{'passwd'}" ) {
                $BAILMESSAGE = "The old passwd can not match the new password.";
                &bail;
        }

        if ( length $input{'newpass1'} > 8 || length $input{'newpass1'} < 4 ) {
                $BAILMESSAGE = "Passwd must be from 4 to 8 characters in size. Hit back and try again";
                &bail;
        }

        unless (open (PASS, "< $PASSWORDFILE")) {
                $BAILMESSAGE = "Can not open password file";
                &bail;
        }
        close (PASS);

        # Here we do not go to extremes to ensure proper security. After all, we are only dealing
        # with the Web password file rather than the system file.
        $match = system("$CHECKPASSWORD $PASSWORDFILE $input{'loginid'} $input{'passwd'}");
        if ($match == 0) {
                # The $input{'loginid'} parameter which the user entered could be
                # an attempt to hack the machine. It is used below so that the
                # shell doesn't do interpretation on it.  The whole entered string
                # is passed as a single param to ypmatch and the "Programming Perl"
                # book says this should be secure.  In my tests it appears to be.
                # Using (system "/bin/ypmatch $input{'loginid'} passwd") is 
                # REALLY REALLY bad.
                open YPPASS, "-|" or exec "/bin/ypmatch", $input{'loginid'}, "passwd" ;
                $line = <YPPASS> ;
                close (YPPASS);
                ($skipit, $CASpass) = split (":", $line);
                if (crypt($input{'newpass2'}, $CASpass) ne $CASpass) {
                        # Make sure to use the (platform independent but Apache specific) MD5 encryption.
                        # Again we are not too much worried here about the security issues.
                        $update = system("$MODIFYPASSWORD -b -m $PASSWORDFILE $input{'loginid'} $input{'newpass2'}");
                        if ($update == 0) {
                            print ("Password successfully updated<BR>\n");
                        } else {
                            print ("Error updating password file<BR>\n");
                        }
                } else {
                        print ("<blink>Your web passwd must not be your Central Server passwd</blink><BR>\n");
                }
        } else {
                print $FAILMESSAGE ;
        }
}

sub bail {
        print ("<P><blink>$BAILMESSAGE</blink><P>");
        print &HtmlBot;
        exit;
}

sub admin_passwd_form {
        print ("<P>This page is used by a web administrator to change a users password.<P>\n");
#       print ("<form action=\"/cgi-bin/d0-admin/passwdadmin/webpasswd.pl\"
        print ("<form action=\"/cgi-bin/webpasswd.pl\"
                method=\"POST\"><center>
                Admin login id:<BR>
                <input type=text name=\"adminloginid\" size=20>
                <P>Admin login password:<BR>
                <input type=password name=\"adminpasswd\" size=20><P>
                <P>User login id:<BR>
                <input type=text name=\"userloginid\" size=20><P>
                <P>New user password:<BR>
                <input type=password name=\"usernewpass1\" size=8>
                <P>Please retype the new password:<BR>
                <input type=password name=\"usernewpass2\" size=8>
                <input type=hidden name=\"adminchgpass\" value=\"y\">
                <P><input type=submit value=\"Submit\">
                <input type=reset value=\"Clear\">
                </center></form><p>\n");
}

sub admin_change_password {

        if ( "$input{'usernewpass1'}" ne "$input{'usernewpass2'}" ) {
                $BAILMESSAGE = "The two new passwords did not match";
                &bail;
        }

        unless (open (ADMINPASS, "+< $ADMINPASSWORDFILE")) {
                $BAILMESSAGE = "Can not open admin password file";
                &bail;
        }

        while (<ADMINPASS>) {
                chomp;
                ($login, $password) = split (":");
                $adminpasswords{$login} = $password;
        }

        if ( $adminpasswords{$input{'adminloginid'}} ) {
#amj                if (crypt($input{'adminpasswd'}, $adminpasswords{$input{'adminloginid'}}) eq $adminpasswords{$input{'adminloginid'}}) {
        $match = system("$CHECKPASSWORD $ADMINPASSWORDFILE $input{'adminloginid'} $input{'adminpasswd'}");
        if ($match == 0) {
                        unless (open (PASS, "< $PASSWORDFILE")) {
                                $BAILMESSAGE = "Can not open password file";
                                &bail;
                        }
        
                        $valid = 0;
                        while (<PASS>) {
                                chomp;
                                ($login, $password) = split (":");
                                if ($login eq $input{'userloginid'} ) {
                                        $valid = 1;
                                }
                        }
                        close (PASS);
                        
                        if ($valid) {
                                $update = system("$MODIFYPASSWORD -b -m $PASSWORDFILE $input{'userloginid'} $input{'usernewpass2'}");
                                if ($update == 0) {
                                    print ("Password successfully updated<BR>\n");
                                } else {
                                    print ("Error updating password file<BR>\n");
                                }
                        } else {
                                print ("User id not valid<BR>\n");
                        }
                } else {
                        print $FAILMESSAGE;
                }
        } else {
                print $FAILMESSAGE;
        }               
        
}