mirror of
https://github.com/webmin/webmin.git
synced 2025-07-21 23:40:34 +00:00
More work on forgotten password support
This commit is contained in:
69
forgot.cgi
Normal file
69
forgot.cgi
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#!/usr/local/bin/perl
|
||||||
|
# Linked to from the forgotten password email
|
||||||
|
|
||||||
|
BEGIN { push(@INC, "."); };
|
||||||
|
use WebminCore;
|
||||||
|
$no_acl_check++;
|
||||||
|
&init_config();
|
||||||
|
&ReadParse();
|
||||||
|
$gconfig{'forgot_pass'} || &error($text{'forgot_ecannot'});
|
||||||
|
my $forgot_password_link_dir = "$config_directory/forgot-password";
|
||||||
|
my $forgot_timeout = 10;
|
||||||
|
&error_setup($text{'forgot_err'});
|
||||||
|
|
||||||
|
# Check that the random ID is valid
|
||||||
|
$in{'id'} =~ /^[a-f0-9]+$/i || &error($text{'forgot_eid'});
|
||||||
|
my %link;
|
||||||
|
&read_file("$forgot_password_link_dir/$link{'id'}", \%link) ||
|
||||||
|
&error($text{'forgot_eid2'});
|
||||||
|
time() - $link{'time'} > 60*$forgot_timeout &&
|
||||||
|
&error(&text('forgot_etime', $forgot_timeout));
|
||||||
|
|
||||||
|
# Get the Webmin user
|
||||||
|
&foreign_require("acl");
|
||||||
|
my ($wuser) = grep { $_->{'name'} eq $link{'user'} } &acl::list_users();
|
||||||
|
$wuser || &error(&text('forgot_euser2',
|
||||||
|
"<tt>".&html_escape($link{'user'})."</tt>"));
|
||||||
|
|
||||||
|
&ui_print_header(undef, $text{'forgot_title'}, "", undef, undef, 1, 1);
|
||||||
|
|
||||||
|
print "<center>\n";
|
||||||
|
if (defined($in{'newpass'})) {
|
||||||
|
# Validate the password
|
||||||
|
$in{'newpass'} =~ /\S/ || &error($text{'forgot_enewpass'});
|
||||||
|
my $perr = &acl::check_password_restrictions(
|
||||||
|
$wuser->{'name'}, $in{'newpass'});
|
||||||
|
$perr && &error(&text('forgot_equality', $perr));
|
||||||
|
|
||||||
|
# Actually update the password
|
||||||
|
if (&foreign_check("virtual-server")) {
|
||||||
|
# Is this a Virtualmin domain owner?
|
||||||
|
&foreign_require("virtual-server");
|
||||||
|
$d = &virtual_server::get_domain_by("user", $link{'user'},
|
||||||
|
"parent", "");
|
||||||
|
}
|
||||||
|
if ($d) {
|
||||||
|
# Update in Virtualmin
|
||||||
|
}
|
||||||
|
elsif ($wuser->{'pass'} eq 'x') {
|
||||||
|
# Update in Users and Groups
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# Update in Webmin
|
||||||
|
$wuser->{'pass'} = &encrypt_password($in{'newpass'});
|
||||||
|
&modify_user($wuser->{'name'}, $wuser);
|
||||||
|
&reload_miniserv();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# Show password selection form
|
||||||
|
print &ui_form_start("forgot.cgi", "post");
|
||||||
|
print &ui_hidden("id", $in{'id'});
|
||||||
|
print "<b>",&text('forgot_newpass',
|
||||||
|
"<tt>".&html_escape($link{'user'})."</tt>"),"</b>\n",
|
||||||
|
&ui_textbox("newpass", undef, 30),"<p>\n";
|
||||||
|
print &ui_form_end([ [ undef, $text{'forgot_passok'} ] ]);
|
||||||
|
}
|
||||||
|
print "</center>\n";
|
||||||
|
|
||||||
|
&ui_print_footer();
|
@ -12,7 +12,7 @@ $gconfig{'forgot_pass'} || &error($text{'forgot_ecannot'});
|
|||||||
|
|
||||||
print "<center>\n";
|
print "<center>\n";
|
||||||
print $text{'forgot_desc'},"<p>\n";
|
print $text{'forgot_desc'},"<p>\n";
|
||||||
print &ui_form_start("forgot.cgi", "post");
|
print &ui_form_start("forgot_send.cgi", "post");
|
||||||
print "<b>$text{'forgot_user'}</b>\n",
|
print "<b>$text{'forgot_user'}</b>\n",
|
||||||
&ui_textbox("forgot", $in{'failed'}, 40),"<br>\n";
|
&ui_textbox("forgot", $in{'failed'}, 40),"<br>\n";
|
||||||
print &ui_form_end([ [ undef, $text{'forgot_ok'} ] ]);
|
print &ui_form_end([ [ undef, $text{'forgot_ok'} ] ]);
|
||||||
|
69
forgot_send.cgi
Normal file
69
forgot_send.cgi
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#!/usr/local/bin/perl
|
||||||
|
# Send a forgotten password reset email
|
||||||
|
|
||||||
|
BEGIN { push(@INC, "."); };
|
||||||
|
use WebminCore;
|
||||||
|
$no_acl_check++;
|
||||||
|
&init_config();
|
||||||
|
&ReadParse();
|
||||||
|
$gconfig{'forgot_pass'} || &error($text{'forgot_ecannot'});
|
||||||
|
$forgot_password_link_dir = "$config_directory/forgot-password";
|
||||||
|
|
||||||
|
# Lookup the Webmin user
|
||||||
|
&foreign_require("acl");
|
||||||
|
my ($wuser) = grep { lc($_->{'name'}) eq lc($in{'forgot'}) } &acl::list_users();
|
||||||
|
$wuser && $wuser->{'email'} || &error($text{'forgot_euser'});
|
||||||
|
($wuser->{'sync'} || $wuser->{'pass'} eq 'e') && &error($text{'forgot_esync'});
|
||||||
|
$wuser->{'pass'} eq '*LK*' && &error($text{'forgot_elock'});
|
||||||
|
my $email = $wuser->{'email'};
|
||||||
|
|
||||||
|
# Generate a random ID for this password reset
|
||||||
|
my %link = ( 'id' => &generate_random_id(),
|
||||||
|
'remote' => $ENV{'REMOTE_ADDR'},
|
||||||
|
'time' => time(),
|
||||||
|
'user' => $wuser->{'user'} );
|
||||||
|
$link{'id'} || &error($text{'forgot_erandom'});
|
||||||
|
&make_dir($forgot_password_link_dir, 0700);
|
||||||
|
&write_file("$forgot_password_link_dir/$link{'id'}", \%link);
|
||||||
|
my $baseurl = &get_webmin_email_url();
|
||||||
|
my $url = $baseurl.'/forgot.cgi?id='.&urlize($link{'id'});
|
||||||
|
|
||||||
|
&ui_print_header(undef, $text{'forgot_title'}, "", undef, undef, 1, 1);
|
||||||
|
|
||||||
|
# Send email with a link to generate the reset form
|
||||||
|
&foreign_require("mailboxes");
|
||||||
|
my $msg = &text('forgot_msg', $wuser->{'name'}, $url, $ENV{'REMOTE_HOST'},
|
||||||
|
$baseurl);
|
||||||
|
$msg =~ s/\\n/\n/g;
|
||||||
|
$msg = join("\n", &mailboxes::wrap_lines($msg, 75))."\n";
|
||||||
|
my $subject = $text{'forgot_subject'};
|
||||||
|
&mailboxes::send_text_mail(&mailboxes::get_from_address(),
|
||||||
|
$email,
|
||||||
|
undef,
|
||||||
|
$subject,
|
||||||
|
$msg);
|
||||||
|
|
||||||
|
# Tell the user
|
||||||
|
print "<center>\n";
|
||||||
|
print &text('forgot_sent', "<tt>".&html_escape($email)."</tt>",
|
||||||
|
"<tt>".&html_escape($wuser->{'name'})."</tt>"),"<p>\n";
|
||||||
|
print "</center>\n";
|
||||||
|
|
||||||
|
&ui_print_footer();
|
||||||
|
|
||||||
|
# generate_random_id()
|
||||||
|
# Generate an ID string that can be used for a password reset link
|
||||||
|
sub generate_random_id
|
||||||
|
{
|
||||||
|
if (open(my $RANDOM, "</dev/urandom")) {
|
||||||
|
my $sid;
|
||||||
|
my $tmpsid;
|
||||||
|
if (read($RANDOM, $tmpsid, 16) == 16) {
|
||||||
|
$sid = lc(unpack('h*',$tmpsid));
|
||||||
|
}
|
||||||
|
close($RANDOM);
|
||||||
|
return $sid;
|
||||||
|
}
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
16
lang/en
16
lang/en
@ -151,6 +151,22 @@ forgot_user=Webmin username:
|
|||||||
forgot_desc=If your Webmin login has a recovery email address associated with it, you can use this page to send a link that can be used to reset the password.
|
forgot_desc=If your Webmin login has a recovery email address associated with it, you can use this page to send a link that can be used to reset the password.
|
||||||
forgot_ok=Send Password Reset Link
|
forgot_ok=Send Password Reset Link
|
||||||
forgot_ecannot=Forgotten password recovery is not enabled!
|
forgot_ecannot=Forgotten password recovery is not enabled!
|
||||||
|
forgot_euser=The username either does not exist or does not have a recovery email configured.
|
||||||
|
forgot_msg=You are receiving this email due to a request for password recovery from the Webmin system at $4 from $3, for the login $1.\n\nIf you would like to proceed with resetting the password, follow this link :\n$2
|
||||||
|
forgot_subject=Webmin password reset
|
||||||
|
forgot_sent=A link to reset your Webmin password for login $2 has been sent to the recovery email address $1.
|
||||||
|
forgot_erandom=Failed to generate random ID!
|
||||||
|
forgot_eid=Missing or invalid-looking reset ID!
|
||||||
|
forgot_eid2=Reset ID is not valid!
|
||||||
|
forgot_etime=Password reset email is more than $1 minutes old.
|
||||||
|
forgot_newpass=Enter a new password for Webmin user $1 :
|
||||||
|
forgot_passok=Change Password
|
||||||
|
forgot_euser2=Webmin user $1 does not exist!
|
||||||
|
forgot_esync=The password cannot be changed for this user
|
||||||
|
forgot_elock=The password for this user is locked
|
||||||
|
forgot_err=Failed to change password
|
||||||
|
forgot_enewpass=No new password entered!
|
||||||
|
forgot_equality=Password requirements were not met : $1
|
||||||
|
|
||||||
pam_header=Login to Webmin
|
pam_header=Login to Webmin
|
||||||
pam_mesg=You must respond to the question below to login to Webmin server on $1.
|
pam_mesg=You must respond to the question below to login to Webmin server on $1.
|
||||||
|
@ -4918,7 +4918,7 @@ my %vital = ("port", 80,
|
|||||||
"pam", "webmin",
|
"pam", "webmin",
|
||||||
"sidname", "sid",
|
"sidname", "sid",
|
||||||
"unauth", "^/unauthenticated/ ^/robots.txt\$ ^[A-Za-z0-9\\-/_]+\\.jar\$ ^[A-Za-z0-9\\-/_]+\\.class\$ ^[A-Za-z0-9\\-/_]+\\.gif\$ ^[A-Za-z0-9\\-/_]+\\.png\$ ^[A-Za-z0-9\\-/_]+\\.conf\$ ^[A-Za-z0-9\\-/_]+\\.ico\$ ^/robots.txt\$ ^/service-worker.js\$",
|
"unauth", "^/unauthenticated/ ^/robots.txt\$ ^[A-Za-z0-9\\-/_]+\\.jar\$ ^[A-Za-z0-9\\-/_]+\\.class\$ ^[A-Za-z0-9\\-/_]+\\.gif\$ ^[A-Za-z0-9\\-/_]+\\.png\$ ^[A-Za-z0-9\\-/_]+\\.conf\$ ^[A-Za-z0-9\\-/_]+\\.ico\$ ^/robots.txt\$ ^/service-worker.js\$",
|
||||||
"unauthcgi", "^/forgot_form.cgi\$ ^/forgot.cgi\$",
|
"unauthcgi", "^/forgot_form.cgi\$ ^/forgot_send.cgi\$ ^/forgot.cgi\$",
|
||||||
"max_post", 10000,
|
"max_post", 10000,
|
||||||
"expires", 7*24*60*60,
|
"expires", 7*24*60*60,
|
||||||
"pam_test_user", "root",
|
"pam_test_user", "root",
|
||||||
|
Reference in New Issue
Block a user