Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Changing email passwords using CGI

Status
Not open for further replies.
Feb 5, 2002
10
0
0
US
I am currently attempting to rewrite some CGI scripts which handle some of our email services such as changing passwords and setting forwards on a HP-UX system. I want to write them in Perl but I am unsure how to make it work. I want to (1) Authenticate users when they set a forward or change a password and (2) Change their password if necessary. I know it is possible, I just a nudge in the right direction.

Thanks

 
Here is a script the will help you

------------------------------------------------------------------------------


#!/usr/bin/perl

# manage.pl
#
# A program designed to allow teachers on a campus to handle adding
# and changing students to the system.
#
# At my school, all students have an ID number that happens to start
# with 135 - you'll need to come up with some unique identifier as well
# if you want to limit the person running this script to only modifying
# those users.
#
# Assumptions:
# All students are entered into a single group (this is not
# the default for RedHat, not sure about other distros).
#
# Changelog:
#
# Version 0.2
# -----------
# November 6, 2000 - Added rudimentary locking to prevent overlapping
# users - could be a bad thing :(
#
# Version 0.1
# -----------
# February 21, 2000 - First version
#
# License: GPL - Don't blame me if it breaks your system! :)
#
# Chris Hobbs <chobbs@silvervalley.k12.ca.us>

use Expect;
$| =1;

# Set up some useful tokens

$TRUE = (1 == 1);
$FALSE = (0 == 1);

# User definable variables

$student_group = &quot;502&quot;; # Group all students belong to
$samba = $TRUE; # Using samba?
$nis = $TRUE; # Using NIS?
$quota = $TRUE; # Using quotas?
$quota_prototype = 'ttest'; # Username to duplicate for edquota
$lockfile = '/tmp/manage.lock'; # Lockfile to prevent multiple users
$touch = '/bin/touch'; # Location of touch commmand

# That's all for user definable variables...

$check_locked = $FALSE;

main ();

sub main {

# Check for exisitence of lockfile - if it exists, exit, otherwise
# touch the lockfile and move on - we'll delete it later.

# *** It would be very easy for a user to block access
# *** to the program by creating their own $lockfile. That's
# *** why I've got this chmod'ed to prevent reading :)
# *** Security Through Obscurity at it's best!

unless ($check_locked) {
-e $lockfile?
die (&quot;$lockfile exists: try again in a few minutes.\n&quot;) :
`$touch $lockfile`;
$check_locked = $TRUE;
}
print &quot;\n&quot;;
$good_entry = ($FALSE);
until ($good_entry) {
print &quot;Please enter student ID number (0 to quit): &quot;;
$student_id = <STDIN>;
chomp $student_id;
if ($student_id =~ /^0$/) {
unlink $lockfile;
exit 0;
}
$good_entry = ($student_id =~ /^135\d{4}$/);
}
if (getpwnam $student_id) {
edit_student($student_id);
} else {
add_student($student_id);
}
}

sub edit_student {
$student_id = $_[0];
(undef, undef, undef, undef, undef, undef, $name, undef) = getpwnam $student_id;
print &quot;Modify $name? (y/n): &quot;;
$answer = <STDIN>;
chomp $answer;
main () unless ($answer eq &quot;y&quot;);

open SHADOW, &quot;/etc/shadow&quot;;
@shadow = <SHADOW>;
close SHADOW;

@lines = grep /^$student_id/, @shadow;
if (@lines > 1) {
print &quot;\n Uh-oh! There's a major problem. There are multiple\n&quot;;
print &quot; entries for $name in /etc/shadow. Exiting!\n\n&quot;;
unlink $lockfile;
exit (1);
}
(undef, $passwd, undef) = split (/:/, $lines[0]);

if ((substr $passwd, 0, 1) eq &quot;*&quot;) {
$enabled = $FALSE;
print &quot;\n 1) Enable this account.\n&quot;;
} else {
$enabled = $TRUE;
print &quot;\n 1) Disable this account.\n&quot;;
}
print &quot; 2) Change password.\n&quot;;
print &quot;\nEnter Choice (1/2): &quot;;
$choice = <STDIN>;
chomp $choice;
if ($choice eq &quot;1&quot;) {
toggle_active ($enabled, $student_id);
} elsif ($choice eq &quot;2&quot;) {
change_passwd ($student_id);
} else {
print &quot;\nSorry, your choice confused me! Exiting...\n\n&quot;;
unlink $lockfile;
exit (1);
}
}

sub toggle_active {
$enabled = $_[0];
$student_id = $_[1];
open SHADOW, &quot;/etc/shadow&quot;;
@shadow = <SHADOW>;
close SHADOW;

foreach $line (@shadow) {
unless ($line =~ /^$student_id/) {next};
($name, $passwd, $therest) = split (/:/, $line, 3);

if ($enabled) {
$passwd = &quot;*&quot; . $passwd;
print `/usr/bin/smbpasswd -d $student_id\n`;
print &quot;\n\n Student $student_id has been disabled.\n\n&quot;;
} else {
$passwd = substr $passwd, 1;
print `/usr/bin/smbpasswd -e $student_id\n`;
print &quot;\n\n Student $student_id has been enabled.\n\n&quot;;
}
$line = &quot;${name}:${passwd}:$therest&quot;;

last;
}

open SHADOW, &quot;>/etc/shadow&quot;;
print SHADOW @shadow;
close SHADOW;

if ($nis) { nis_remake () };

unlink $lockfile;
exit (0);
}

sub change_passwd {
$student_id = $_[0];
$newpass = gen_passwd ();

# Change Linux passwd...

$command = Expect->spawn(&quot;/usr/bin/passwd $student_id&quot;) or die &quot;Couldn't start program: $!\n&quot;;
$command->log_stdout(0);
unless ($command->expect(5, &quot;password:&quot;)) {};
print $command &quot;$newpass\r&quot;;
unless ($command->expect(5, &quot;password:&quot;)) {};
print $command &quot;$newpass\r&quot;;
$command->soft_close();

# Call Samba passwd if neccessary...

if ($samba) { change_samba ($student_id, $newpass) }

# Call nis_remake to update the maps...

if ($nis) { nis_remake() }

# OK, we're done...

print &quot;\n\n Complete: password changed for $student_id: $newpass\n\n&quot;;
unlink $lockfile;
exit (0);

}

sub change_samba {

$student_id = $_[0];
$newpass = $_[1];
open TEMP, &quot;>/root/temppass&quot;;
print TEMP &quot;$newpass\n$newpass&quot;;
close TEMP;
print `/usr/bin/smbpasswd -s $student_id < /root/temppass`;
unlink &quot;/root/temppass&quot;;
}

sub nis_remake {
$curdir = `pwd`;
chdir &quot;/var/yp&quot;;
`/usr/bin/make all\n`;
`cp /var/yp/*.* /var/yp/svhs/`;
chdir $curdir;
}

# This routine creates random passwords based on concatenating two short
# words with a symbol inbetween (DOG#puck or girl%PEN for example). Not as
# secure as truly random passwords, but much easier for a student to remember.
#
# @badwords is an array of words that I'm not using from he built-in dictionary,
# mainly to avoid getting sued by an irate parent!

sub gen_passwd {
@badwords = qw/put own list of bad words here/;

for (@badwords) {$is_badword{$_} = 1}

open DICT, &quot;/usr/dict/linux.words&quot;;
foreach (<DICT>) {
chomp;
if ((length($_) == 3) && ($is_badword{lc($_)} != 1)) {push @three, $_}
if ((length($_) == 4) && ($is_badword{lc($_)} != 1)) {push @four, $_}
}
close DICT;

@nums = qw/! @ # $ % ^ & * ( ) - _ + = \\ \/ : ; ' &quot; [ ] { }/;
$threeleft = int (rand() + 0.5);
$upperleft = int (rand() + 0.5);

if ($threeleft) {
if ($upperleft) {
$pass = uc ($three[rand(@three)]);
$pass .= $nums[rand(@nums)];
$pass .= lc ($four[rand(@four)]);
} else {
$pass = lc ($three[rand(@three)]);
$pass .= $nums[rand(@nums)];
$pass .= uc ($four[rand(@four)]);
}
} else {
if ($upperleft) {
$pass = uc ($four[rand(@four)]);
$pass .= $nums[rand(@nums)];
$pass .= lc ($three[rand(@three)]);
} else {
$pass = lc ($four[rand(@four)]);
$pass .= $nums[rand(@nums)];
$pass .= uc ($three[rand(@three)]);
}
}

return $pass;
}

sub add_student {
$student_id = $_[0];
$newpass = gen_passwd ();

print &quot; Enter Name of Student ($student_id): &quot;;
$desc = <STDIN>;
chomp $desc;

# Need to find the largest uid so we can go one above it...

open PASSWD, &quot;/etc/passwd&quot;;
@passwd = <PASSWD>;
close PASSWD;

$max_id = 0;

foreach (@passwd) {
(undef, undef, $uid, undef) = split (/:/);
if ($uid > $max_id) {
$max_id = $uid;
}
}

$num_id = $max_id + 1;

# Write the info to a temp file for newusers to input...

open TEMP_ONE, &quot;>temp_one&quot; || die &quot;Unable to open first output file: $!\n&quot;;

print TEMP_ONE &quot;${student_id}:${newpass}:${num_id}:student:${desc}:/home/${student_id}:/bin/bash\n&quot;;
close TEMP_ONE;

print `/usr/sbin/newusers temp_one\n`;
print `/usr/bin/chage -m 0 -M 99999 $student_id\n`;

unlink &quot;temp_one&quot;;

# Add to Samba if neccessary...

if ($samba) {
print `/usr/bin/smbpasswd -a -n $student_id\n`;
change_samba ($student_id, $newpass);
}

# Set user quota if neccessary

if ($quota) {
print `/usr/sbin/edquota -p $quota_prototype $student_id\n`;
}

# Enable account... (why is it it disabled????)

open PASSWD, &quot;/etc/passwd&quot;;
@passwd = <PASSWD>;
close PASSWD;

foreach (@passwd) {
if (/^${student_id}:!:/) {
$_ =~ s/^${student_id}:!:/${student_id}:x:/;
}
}

open PASSWD, &quot;>/etc/passwd&quot;;
print PASSWD @passwd;
close PASSWD;

# Remake NIS maps if neccessary...

if ($nis) { nis_remake() }


# Tell the user what we've done...

print &quot;\n\n New user $student_id ($desc) created. Password: $newpass\n\n&quot;;
unlink $lockfile;
exit (0);
}
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top