mirror of
https://github.com/webmin/webmin.git
synced 2026-07-24 18:30:38 +01:00
Fix to clarify Unix authentication mapping behavior
https://github.com/webmin/webmin/issues/2791
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
#!/usr/local/bin/perl
|
||||
# edit_unix.cgi
|
||||
# Choose a user whose permissions will be used for logins that don't
|
||||
# match any webmin user, but have unix accounts
|
||||
# Map Unix users that do not have Webmin accounts to a Webmin user whose
|
||||
# access rights and authentication method will be used for their logins.
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
@@ -20,7 +20,7 @@ my %miniserv;
|
||||
print &ui_form_start("save_unix.cgi", "post");
|
||||
print &ui_table_start($text{'unix_header'}, undef, 2);
|
||||
|
||||
# Enable Unix auth
|
||||
# Configure Unix login mappings
|
||||
my @unixauth = &get_unixauth(\%miniserv);
|
||||
my $utable = "";
|
||||
$utable .= &ui_radio("unix_def", @unixauth ? 0 : 1,
|
||||
@@ -28,8 +28,13 @@ $utable .= &ui_radio("unix_def", @unixauth ? 0 : 1,
|
||||
$utable .= &ui_columns_start([ $text{'unix_mode'}, $text{'unix_who'},
|
||||
$text{'unix_to'} ]);
|
||||
my $i = 0;
|
||||
my @webmins = map { [ $_->{'name'} ] }
|
||||
sort { $a->{'name'} cmp $b->{'name'} } &list_users();
|
||||
my @webmins = map {
|
||||
my $auth = $_->{'pass'} eq 'x' ? $text{'edit_unix'} :
|
||||
$_->{'pass'} eq 'e' ? $text{'edit_extauth'} :
|
||||
$_->{'pass'} eq '*LK*' || $_->{'pass'} =~ /^!/ ?
|
||||
$text{'edit_lock'} : $text{'unix_webminpass'};
|
||||
[ $_->{'name'}, "$_->{'name'} ($auth)" ]
|
||||
} sort { $a->{'name'} cmp $b->{'name'} } &list_users();
|
||||
foreach my $ua (@unixauth, [ ], [ ]) {
|
||||
$utable .= &ui_columns_row([
|
||||
&ui_select("mode_$i", !defined($ua->[0]) ? 0 :
|
||||
@@ -47,6 +52,7 @@ foreach my $ua (@unixauth, [ ], [ ]) {
|
||||
$i++;
|
||||
}
|
||||
$utable .= &ui_columns_end();
|
||||
$utable .= "<p>".&ui_note($text{'unix_mapdesc'}, 0)."</p>\n";
|
||||
print &ui_table_row($text{'unix_utable'}, $utable);
|
||||
|
||||
# Allow users who can sudo to root?
|
||||
@@ -88,4 +94,3 @@ print &ui_table_end();
|
||||
print &ui_form_end([ [ undef, $text{'save'} ] ]);
|
||||
|
||||
&ui_print_footer("", $text{'index_return'});
|
||||
|
||||
|
||||
16
acl/lang/en
16
acl/lang/en
@@ -316,15 +316,17 @@ sync_ecannot=You are not allowed to configure user synchronization.
|
||||
|
||||
unix_title=Unix User Authentication
|
||||
unix_err=Failed to save Unix authentication
|
||||
unix_desc=This page allows you to configure Webmin to validate login attempts against the system user list and PAM. This can be useful if you have a large number of existing Unix users who you want to give access to Webmin.
|
||||
unix_def=Only allow Webmin users to login
|
||||
unix_sel=Allow Unix users listed below to login ..
|
||||
unix_desc=This page allows Unix and directory-backed users, as well as PAM-only users, to log in without creating a separate Webmin account for each user. Each login receives the access rights and uses the authentication method of the mapped Webmin user.
|
||||
unix_def=Only allow Webmin users to log in
|
||||
unix_sel=Allow the users and groups mapped below to log in
|
||||
unix_mode=Allow
|
||||
unix_mall=All users
|
||||
unix_group=Members of group..
|
||||
unix_user=Unix user ..
|
||||
unix_group=Members of group
|
||||
unix_user=Unix user
|
||||
unix_who=User or Group
|
||||
unix_to=As Webmin user
|
||||
unix_to=Webmin user access and authentication
|
||||
unix_mapdesc=The selected Webmin user supplies both access rights and the authentication method. To authenticate the original username through PAM, SSSD, or the system password database, select a Webmin user configured for <b>Unix authentication</b>. If the selected user has a Webmin password, every matching login uses that shared password instead.
|
||||
unix_webminpass=Webmin password
|
||||
unix_ecannot=You are not allowed to configure Unix user authentication
|
||||
unix_epam=Unix authentication is not available as the <tt>Authen::PAM</tt> Perl module is not installed or not working properly.
|
||||
unix_all=Allow all Unix users
|
||||
@@ -345,7 +347,7 @@ unix_pamany=Treat logins that only pass PAM validation as $1
|
||||
unix_esudo=The $1 command is not installed
|
||||
unix_esudomod=The Perl module $1 needed for <tt>sudo</tt> authentication is not installed
|
||||
unix_header=Unix user authentication settings
|
||||
unix_utable=Allowed Unix users
|
||||
unix_utable=Login mappings
|
||||
|
||||
sessions_title=Current Login Sessions
|
||||
sessions_id=Session ID
|
||||
|
||||
@@ -1179,6 +1179,34 @@ is(group_line({ name => 'empty' }),
|
||||
# writing <confdir>/acl/<user>.acl, seeds whatever miniserv-user state the CGI
|
||||
# needs, runs the CGI as a subprocess, and asserts on what the caller sees.
|
||||
|
||||
# edit_unix.cgi should make the authentication method inherited from each
|
||||
# mapped Webmin user visible without changing the submitted username value.
|
||||
subtest 'edit_unix.cgi authentication labels' => sub {
|
||||
_reset_fixture();
|
||||
_seed_user_acl('admin', { unix => 1, create => 1, delete => 1 });
|
||||
create_user({ name => 'external-user', pass => 'e', modules => ['acl'] });
|
||||
create_user({ name => 'locked-user', pass => '*LK*', modules => ['acl'] });
|
||||
create_user({ name => 'pam-user', pass => 'x', modules => ['acl'] });
|
||||
create_user({ name => 'webmin-user', pass => 'fixed', modules => ['acl'] });
|
||||
|
||||
my $r = run_cgi('edit_unix.cgi', {});
|
||||
is($r->{status}, 0, 'mapping page renders successfully');
|
||||
like($r->{out},
|
||||
qr/value="pam-user"[^>]*>pam-user \(Unix authentication\)/,
|
||||
'Unix authentication target is labeled');
|
||||
like($r->{out},
|
||||
qr/value="external-user"[^>]*>external-user \(External authentication program\)/,
|
||||
'external authentication target is labeled');
|
||||
like($r->{out},
|
||||
qr/value="locked-user"[^>]*>locked-user \(No password accepted\)/,
|
||||
'locked target is labeled');
|
||||
like($r->{out},
|
||||
qr/value="webmin-user"[^>]*>webmin-user \(Webmin password\)/,
|
||||
'fixed Webmin password target is labeled');
|
||||
like($r->{out}, qr/every matching login uses that shared password/,
|
||||
'mapping authentication behavior is explained');
|
||||
};
|
||||
|
||||
# Harness sanity: a CGI with no privileges should reject any action and
|
||||
# print an HTML error (not a redirect). switch.cgi is the smallest victim.
|
||||
subtest 'CGI harness smoke' => sub {
|
||||
|
||||
@@ -2581,7 +2581,8 @@ elsif ($canmode == 0) {
|
||||
return ( $canuser, 0, 0, $webminuser );
|
||||
}
|
||||
elsif ($canmode == 1) {
|
||||
# Attempt Webmin authentication
|
||||
# Attempt Webmin authentication. For a unixauth mapping, this checks
|
||||
# the fixed password of the mapped Webmin user.
|
||||
my $uinfo = &get_user_details($webminuser, $canuser);
|
||||
if ($uinfo &&
|
||||
&password_crypt($pass, $uinfo->{'pass'}) eq $uinfo->{'pass'}) {
|
||||
@@ -2774,14 +2775,17 @@ return $resp =~ /^OK/i ? 1 : 0;
|
||||
# Second is 0 if cannot login, 1 if using Webmin pass, 2 if PAM, 3 if password
|
||||
# file, 4 if external.
|
||||
# Third is 1 if the user does not exist at all, 0 if he does.
|
||||
# Fourth is the Webmin username whose permissions apply, based on unixauth.
|
||||
# Fourth is the Webmin username whose permissions apply. For a unixauth
|
||||
# mapping, its password setting also selects the authentication method.
|
||||
# Fifth is a flag indicating if a sudo check is needed.
|
||||
sub can_user_login
|
||||
{
|
||||
local $uinfo = &get_user_details($_[0]);
|
||||
if (!$uinfo) {
|
||||
# See if this user exists in Unix and can be validated by the same
|
||||
# method as the unixauth webmin user
|
||||
# See if this user exists in Unix and can use the authentication method
|
||||
# configured for the mapped Webmin user. The original username is passed
|
||||
# to PAM, the password file, or the external authentication program; the
|
||||
# mapped Webmin user supplies the access rights.
|
||||
local $realuser = $unixauth{$_[0]};
|
||||
local @uinfo;
|
||||
local $sudo = 0;
|
||||
@@ -2821,6 +2825,8 @@ if (!$uinfo) {
|
||||
return (undef, 0, 1, undef) if (!$realuser);
|
||||
local $uinfo = &get_user_details($realuser);
|
||||
return (undef, 0, 1, undef) if (!$uinfo);
|
||||
# The mapped user's password setting selects how the original username
|
||||
# will be authenticated.
|
||||
local $up = $uinfo->{'pass'};
|
||||
|
||||
# Work out possible domain names from the hostname
|
||||
@@ -2920,17 +2926,17 @@ if (!$uinfo) {
|
||||
}
|
||||
|
||||
if ($up eq 'x') {
|
||||
# PAM or passwd file authentication
|
||||
# Authenticate the original username through PAM or the password file
|
||||
print DEBUG "can_user_login: Validate with PAM\n";
|
||||
return ( $_[0], $use_pam ? 2 : 3, 0, $realuser, $sudo );
|
||||
}
|
||||
elsif ($up eq 'e') {
|
||||
# External authentication
|
||||
# Authenticate the original username externally
|
||||
print DEBUG "can_user_login: Validate externally\n";
|
||||
return ( $_[0], 4, 0, $realuser, $sudo );
|
||||
}
|
||||
else {
|
||||
# Fixed Webmin password
|
||||
# Authenticate against the fixed password of the mapped Webmin user
|
||||
print DEBUG "can_user_login: Validate by Webmin\n";
|
||||
return ( $_[0], 1, 0, $realuser, $sudo );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user