#!/usr/bin/perl -wT

#----------------------------------------------------------------------
# e-smith manager functions: userpassword
# copyright (C) 1999, 2000, 2001 e-smith, inc.
# 		
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# 		
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 		
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
# 
# Technical support for this program is available from e-smith, inc.
# Please visit our web site www.e-smith.com for details.
#----------------------------------------------------------------------

package esmith;

use strict;
use CGI ':all';
use CGI::Carp qw(fatalsToBrowser);

use esmith::cgi;
use esmith::config;
use esmith::util;

sub performAndShowResult ($);

BEGIN
{
    # Clear PATH and related environment variables so that calls to
    # external programs do not cause results to be tainted. See
    # "perlsec" manual page for details.

    $ENV {'PATH'} = '';
    $ENV {'SHELL'} = '/bin/bash';
    delete $ENV {'ENV'};
}

esmith::util::setRealToEffective ();

$CGI::POST_MAX=1024 * 100;  # max 100K posts
$CGI::DISABLE_UPLOADS = 1;  # no uploads

my %conf;
tie %conf, 'esmith::config';

my %accounts;
tie %accounts, 'esmith::config', '/home/e-smith/accounts';

#------------------------------------------------------------
# examine state parameter and display the appropriate form
#------------------------------------------------------------

my $q = new CGI;

if (! grep (/^state$/, $q->param))
{
    esmith::cgi::genStateError ($q, \%conf);
}

elsif ($q->param ('state') eq "perform")
{
    performAndShowResult ($q);
}

else
{
    esmith::cgi::genStateError ($q, \%conf);
}

exit (0);

#------------------------------------------------------------
# subroutine to perform actions and display result
#------------------------------------------------------------

sub performAndShowResult ($)
{
    my ($q) = @_;

    #------------------------------------------------------------
    # Verify the arguments and untaint the variables (see Camel
    # book, "Detecting and laundering tainted data", pg. 358)
    #------------------------------------------------------------

    my $acct = $q->param ('acct');
    if ($acct =~ /^([a-z][\-\_\.a-z0-9]*)$/)
    {
	$acct = $1;
    }
    else
    {
        esmith::cgi::genHeaderNonCacheableNoPasswordCheck ($q, \%conf, "Error while changing password");
	esmith::cgi::genResult ($q, 'Bad account name.');
	return;
    }

    #------------------------------------------------------------
    # Account looks good so far. Get more information.
    #------------------------------------------------------------

    my $value = $accounts {$acct};
    my ($type, %properties) = split (/\|/, $value, -1);

    if ($type ne 'user')
    {
        esmith::cgi::genHeaderNonCacheableNoPasswordCheck ($q, \%conf, "Error while changing password");
	esmith::cgi::genResult ($q, 'Not a user account.');
	return;
    }

    #------------------------------------------------------------
    # Check password arguments.
    #------------------------------------------------------------

    my $oldPass = $q->param ('oldPass');
    if ($oldPass =~ /^(\S+)$/)
    {
	$oldPass = $1;
    }
    else
    {
        esmith::cgi::genHeaderNonCacheableNoPasswordCheck
	    ($q, \%conf, "Error while changing password");

	esmith::cgi::genResult
	    ($q, 'Password must not contain any whitespace characters.');
	return;
    }

    my $newPass = $q->param ('newPass');
    if ($newPass =~ /^([ -~]+)$/)
    {
	$newPass = $1;
    }
    else
    {
        esmith::cgi::genHeaderNonCacheableNoPasswordCheck
	    ($q, \%conf, "Error while changing password");

	esmith::cgi::genResult
	    ($q, 'Password must contain only letters and numbers.');

	return;
    }

    my $newPassVerify = $q->param ('newPassVerify');
    if ($newPassVerify =~ /^([ -~]+)$/)
    {
	$newPassVerify = $1;
    }
    else
    {
        esmith::cgi::genHeaderNonCacheableNoPasswordCheck
	    ($q, \%conf, "Error while changing password");

	esmith::cgi::genResult
	    ($q, 'Password must contain only letters and numbers.');

	return;
    }

    if ($newPass ne $newPassVerify)
    {
        esmith::cgi::genHeaderNonCacheableNoPasswordCheck
	    ($q, \%conf, "Error while changing password");

	esmith::cgi::genResult
	    ($q, 'The two passwords are not identical.');
	return;
    }

    #------------------------------------------------------------
    # Looks good; go ahead and change the password.
    #------------------------------------------------------------

    esmith::util::setUserPasswordRequirePrevious ($acct, $oldPass, $newPass);

    #------------------------------------------------------------
    # update the user's PasswordSet field in the accounts database
    #------------------------------------------------------------

    $properties {'PasswordSet'} = 'yes';

    my $key;
    my $val;
    $value = "user";
    while (($key,$val) = each %properties)
    {
	$value .= "|$key|$val";
    }

    $accounts {$acct} = $value;

	if($q->param('SyncPass') =~ m/no/i)
	{
		system ("/sbin/e-smith/db accounts setprop ${acct} StorePwd no") == 0
			or die ("Error occurred while modifying password for ${acct}.\n");
	}
	else
	{
		 system ("/sbin/e-smith/db accounts setprop ${acct} StorePwd yes") == 0
                        or die ("Error occurred while modifying password for ${acct}.\n");
	}

    system ("/sbin/e-smith/signal-event password-modify ${acct}") == 0
        or die ("Error occurred while modifying password for ${acct}.\n");

    esmith::cgi::genHeaderNonCacheable ($q, \%conf, "Password changed successfully");
    print $q->p ("Successfully changed password for user account $acct.");
    esmith::cgi::genFooter ($q);

    return;
}
