mirror of
https://git.proxmox.com/git/pve-access-control
synced 2025-08-26 23:11:53 +00:00
drop support for old login API
The new-format parameter for the ticket call is now ignored and assumed 1. Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
cb64967379
commit
cfd8636b5e
@ -111,8 +111,8 @@ __PACKAGE__->register_method ({
|
|||||||
}});
|
}});
|
||||||
|
|
||||||
|
|
||||||
my sub verify_auth : prototype($$$$$$$) {
|
my sub verify_auth : prototype($$$$$$) {
|
||||||
my ($rpcenv, $username, $pw_or_ticket, $otp, $path, $privs, $new_format) = @_;
|
my ($rpcenv, $username, $pw_or_ticket, $otp, $path, $privs) = @_;
|
||||||
|
|
||||||
my $normpath = PVE::AccessControl::normalize_path($path);
|
my $normpath = PVE::AccessControl::normalize_path($path);
|
||||||
die "invalid path - $path\n" if defined($path) && !defined($normpath);
|
die "invalid path - $path\n" if defined($path) && !defined($normpath);
|
||||||
@ -128,7 +128,6 @@ my sub verify_auth : prototype($$$$$$$) {
|
|||||||
$username,
|
$username,
|
||||||
$pw_or_ticket,
|
$pw_or_ticket,
|
||||||
$otp,
|
$otp,
|
||||||
$new_format,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,8 +139,8 @@ my sub verify_auth : prototype($$$$$$$) {
|
|||||||
return { username => $username };
|
return { username => $username };
|
||||||
};
|
};
|
||||||
|
|
||||||
my sub create_ticket_do : prototype($$$$$$) {
|
my sub create_ticket_do : prototype($$$$$) {
|
||||||
my ($rpcenv, $username, $pw_or_ticket, $otp, $new_format, $tfa_challenge) = @_;
|
my ($rpcenv, $username, $pw_or_ticket, $otp, $tfa_challenge) = @_;
|
||||||
|
|
||||||
die "TFA response should be in 'password', not 'otp' when 'tfa-challenge' is set\n"
|
die "TFA response should be in 'password', not 'otp' when 'tfa-challenge' is set\n"
|
||||||
if defined($otp) && defined($tfa_challenge);
|
if defined($otp) && defined($tfa_challenge);
|
||||||
@ -164,7 +163,6 @@ my sub create_ticket_do : prototype($$$$$$) {
|
|||||||
$username,
|
$username,
|
||||||
$pw_or_ticket,
|
$pw_or_ticket,
|
||||||
$otp,
|
$otp,
|
||||||
$new_format,
|
|
||||||
$tfa_challenge,
|
$tfa_challenge,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -172,27 +170,11 @@ my sub create_ticket_do : prototype($$$$$$) {
|
|||||||
my %extra;
|
my %extra;
|
||||||
my $ticket_data = $username;
|
my $ticket_data = $username;
|
||||||
my $aad;
|
my $aad;
|
||||||
if ($new_format) {
|
|
||||||
if (defined($tfa_info)) {
|
if (defined($tfa_info)) {
|
||||||
$extra{NeedTFA} = 1;
|
$extra{NeedTFA} = 1;
|
||||||
$ticket_data = "!tfa!$tfa_info";
|
$ticket_data = "!tfa!$tfa_info";
|
||||||
$aad = $username;
|
$aad = $username;
|
||||||
}
|
}
|
||||||
} elsif (defined($tfa_info)) {
|
|
||||||
$extra{NeedTFA} = 1;
|
|
||||||
if ($tfa_info->{type} eq 'u2f') {
|
|
||||||
my $u2finfo = $tfa_info->{data};
|
|
||||||
my $u2f = get_u2f_instance($rpcenv, $u2finfo->@{qw(publicKey keyHandle)});
|
|
||||||
my $challenge = $u2f->auth_challenge()
|
|
||||||
or die "failed to get u2f challenge\n";
|
|
||||||
$challenge = decode_json($challenge);
|
|
||||||
$extra{U2FChallenge} = $challenge;
|
|
||||||
$ticket_data = "u2f!$username!$challenge->{challenge}";
|
|
||||||
} else {
|
|
||||||
# General half-login / 'missing 2nd factor' ticket:
|
|
||||||
$ticket_data = "tfa!$username";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
my $ticket = PVE::AccessControl::assemble_ticket($ticket_data, $aad);
|
my $ticket = PVE::AccessControl::assemble_ticket($ticket_data, $aad);
|
||||||
my $csrftoken = PVE::AccessControl::assemble_csrf_prevention_token($username);
|
my $csrftoken = PVE::AccessControl::assemble_csrf_prevention_token($username);
|
||||||
@ -267,12 +249,9 @@ __PACKAGE__->register_method ({
|
|||||||
},
|
},
|
||||||
'new-format' => {
|
'new-format' => {
|
||||||
type => 'boolean',
|
type => 'boolean',
|
||||||
description =>
|
description => 'This parameter is now ignored and assumed to be 1.',
|
||||||
'With webauthn the format of half-authenticated tickts changed.'
|
|
||||||
.' New clients should pass 1 here and not worry about the old format.'
|
|
||||||
.' The old format is deprecated and will be retired with PVE-8.0',
|
|
||||||
optional => 1,
|
optional => 1,
|
||||||
default => 0,
|
default => 1,
|
||||||
},
|
},
|
||||||
'tfa-challenge' => {
|
'tfa-challenge' => {
|
||||||
type => 'string',
|
type => 'string',
|
||||||
@ -307,14 +286,13 @@ __PACKAGE__->register_method ({
|
|||||||
|
|
||||||
if ($param->{path} && $param->{privs}) {
|
if ($param->{path} && $param->{privs}) {
|
||||||
$res = verify_auth($rpcenv, $username, $param->{password}, $param->{otp},
|
$res = verify_auth($rpcenv, $username, $param->{password}, $param->{otp},
|
||||||
$param->{path}, $param->{privs}, $param->{'new-format'});
|
$param->{path}, $param->{privs});
|
||||||
} else {
|
} else {
|
||||||
$res = create_ticket_do(
|
$res = create_ticket_do(
|
||||||
$rpcenv,
|
$rpcenv,
|
||||||
$username,
|
$username,
|
||||||
$param->{password},
|
$param->{password},
|
||||||
$param->{otp},
|
$param->{otp},
|
||||||
$param->{'new-format'},
|
|
||||||
$param->{'tfa-challenge'},
|
$param->{'tfa-challenge'},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -717,8 +717,8 @@ sub verify_one_time_pw {
|
|||||||
|
|
||||||
# password should be utf8 encoded
|
# password should be utf8 encoded
|
||||||
# Note: some plugins delay/sleep if auth fails
|
# Note: some plugins delay/sleep if auth fails
|
||||||
sub authenticate_user : prototype($$$$;$) {
|
sub authenticate_user : prototype($$$;$) {
|
||||||
my ($username, $password, $otp, $new_format, $tfa_challenge) = @_;
|
my ($username, $password, $otp, $tfa_challenge) = @_;
|
||||||
|
|
||||||
die "no username specified\n" if !$username;
|
die "no username specified\n" if !$username;
|
||||||
|
|
||||||
@ -744,51 +744,14 @@ sub authenticate_user : prototype($$$$;$) {
|
|||||||
|
|
||||||
$plugin->authenticate_user($cfg, $realm, $ruid, $password);
|
$plugin->authenticate_user($cfg, $realm, $ruid, $password);
|
||||||
|
|
||||||
if ($new_format) {
|
|
||||||
# This is the first factor with an optional immediate 2nd factor for TOTP:
|
# This is the first factor with an optional immediate 2nd factor for TOTP:
|
||||||
my $tfa_challenge = authenticate_2nd_new($username, $realm, $otp, undef);
|
$tfa_challenge = authenticate_2nd_new($username, $realm, $otp, undef);
|
||||||
return wantarray ? ($username, $tfa_challenge) : $username;
|
return wantarray ? ($username, $tfa_challenge) : $username;
|
||||||
} else {
|
|
||||||
return authenticate_2nd_old($username, $realm, $otp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub authenticate_2nd_old : prototype($$$) {
|
|
||||||
my ($username, $realm, $otp) = @_;
|
|
||||||
|
|
||||||
my ($type, $tfa_data) = user_get_tfa($username, $realm, 0);
|
|
||||||
if ($type) {
|
|
||||||
if ($type eq 'incompatible') {
|
|
||||||
die "old login api disabled, user has incompatible TFA entries\n";
|
|
||||||
} elsif ($type eq 'u2f') {
|
|
||||||
# Note that if the user did not manage to complete the initial u2f registration
|
|
||||||
# challenge we have a hash containing a 'challenge' entry in the user's tfa.cfg entry:
|
|
||||||
$tfa_data = undef if exists $tfa_data->{challenge};
|
|
||||||
} elsif (!defined($otp)) {
|
|
||||||
# The user requires a 2nd factor but has not provided one. Return success but
|
|
||||||
# don't clear $tfa_data.
|
|
||||||
} else {
|
|
||||||
my $keys = $tfa_data->{keys};
|
|
||||||
my $tfa_cfg = $tfa_data->{config};
|
|
||||||
verify_one_time_pw($type, $username, $keys, $tfa_cfg, $otp);
|
|
||||||
$tfa_data = undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Return the type along with the rest:
|
|
||||||
if ($tfa_data) {
|
|
||||||
$tfa_data = {
|
|
||||||
type => $type,
|
|
||||||
data => $tfa_data,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return wantarray ? ($username, $tfa_data) : $username;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub authenticate_2nd_new_do : prototype($$$$) {
|
sub authenticate_2nd_new_do : prototype($$$$) {
|
||||||
my ($username, $realm, $tfa_response, $tfa_challenge) = @_;
|
my ($username, $realm, $tfa_response, $tfa_challenge) = @_;
|
||||||
my ($tfa_cfg, $realm_tfa) = user_get_tfa($username, $realm, 1);
|
my ($tfa_cfg, $realm_tfa) = user_get_tfa($username, $realm);
|
||||||
|
|
||||||
if (!defined($tfa_cfg)) {
|
if (!defined($tfa_cfg)) {
|
||||||
return undef;
|
return undef;
|
||||||
@ -2032,7 +1995,7 @@ sub add_old_keys_to_realm_tfa : prototype($$$$) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub user_get_tfa : prototype($$$) {
|
sub user_get_tfa : prototype($$$) {
|
||||||
my ($username, $realm, $new_format) = @_;
|
my ($username, $realm) = @_;
|
||||||
|
|
||||||
my $user_cfg = cfs_read_file('user.cfg');
|
my $user_cfg = cfs_read_file('user.cfg');
|
||||||
my $user = $user_cfg->{users}->{$username}
|
my $user = $user_cfg->{users}->{$username}
|
||||||
@ -2053,35 +2016,11 @@ sub user_get_tfa : prototype($$$) {
|
|||||||
die "missing required 2nd keys\n";
|
die "missing required 2nd keys\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($new_format) {
|
|
||||||
my $tfa_cfg = cfs_read_file('priv/tfa.cfg');
|
my $tfa_cfg = cfs_read_file('priv/tfa.cfg');
|
||||||
if (defined($keys) && $keys !~ /^x(?:!.*)$/) {
|
if (defined($keys) && $keys !~ /^x(?:!.*)$/) {
|
||||||
add_old_keys_to_realm_tfa($username, $tfa_cfg, $realm_tfa, $keys);
|
add_old_keys_to_realm_tfa($username, $tfa_cfg, $realm_tfa, $keys);
|
||||||
}
|
}
|
||||||
return ($tfa_cfg, $realm_tfa);
|
return ($tfa_cfg, $realm_tfa);
|
||||||
}
|
|
||||||
|
|
||||||
# new style config starts with an 'x' and optionally contains a !<type> suffix
|
|
||||||
if ($keys !~ /^x(?:!.*)?$/) {
|
|
||||||
# old style config, find the type via the realm
|
|
||||||
return if !$realm_tfa;
|
|
||||||
return ($realm_tfa->{type}, {
|
|
||||||
keys => $keys,
|
|
||||||
config => $realm_tfa,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
my $tfa_cfg = cfs_read_file('priv/tfa.cfg');
|
|
||||||
my $tfa = $tfa_cfg->{users}->{$username};
|
|
||||||
return if !$tfa; # should not happen (user.cfg wasn't cleaned up?)
|
|
||||||
|
|
||||||
if ($realm_tfa) {
|
|
||||||
# if the realm has a tfa setting we need to verify the type:
|
|
||||||
die "auth domain '$realm' and user have mismatching TFA settings\n"
|
|
||||||
if $realm_tfa && $realm_tfa->{type} ne $tfa->{type};
|
|
||||||
}
|
|
||||||
|
|
||||||
return ($tfa->{type}, $tfa->{data});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# bash completion helpers
|
# bash completion helpers
|
||||||
|
Loading…
Reference in New Issue
Block a user