]> git.proxmox.com Git - pve-access-control.git/blobdiff - PVE/API2/AccessControl.pm
remove_storage_access: cleanup of access permissions for removed storage
[pve-access-control.git] / PVE / API2 / AccessControl.pm
index 8daf10cf5f9763750af85cb70b7126d259bde296..f01180d138863ee50c21c25bf5f32b9868efb00b 100644 (file)
@@ -2,7 +2,6 @@ package PVE::API2::AccessControl;
 
 use strict;
 use warnings;
-use Time::HiRes qw(usleep gettimeofday tv_interval);
 
 use PVE::Exception qw(raise raise_perm_exc);
 use PVE::SafeSyslog;
@@ -89,7 +88,7 @@ __PACKAGE__->register_method ({
 
 
 my $verify_auth = sub {
-    my ($rpcenv, $username, $pw_or_ticket, $path, $privs) = @_;
+    my ($rpcenv, $username, $pw_or_ticket, $otp, $path, $privs) = @_;
 
     my $normpath = PVE::AccessControl::normalize_path($path);
 
@@ -100,7 +99,7 @@ my $verify_auth = sub {
     } elsif (PVE::AccessControl::verify_vnc_ticket($pw_or_ticket, $username, $normpath, 1)) {
        # valid vnc ticket
     } else {
-       $username = PVE::AccessControl::authenticate_user($username, $pw_or_ticket);
+       $username = PVE::AccessControl::authenticate_user($username, $pw_or_ticket, $otp);
     }
 
     my $privlist = [ PVE::Tools::split_list($privs) ];
@@ -112,14 +111,14 @@ my $verify_auth = sub {
 };
 
 my $create_ticket = sub {
-    my ($rpcenv, $username, $pw_or_ticket) = @_;
+    my ($rpcenv, $username, $pw_or_ticket, $otp) = @_;
 
     my $ticketuser;
     if (($ticketuser = PVE::AccessControl::verify_ticket($pw_or_ticket, 1)) &&
        ($ticketuser eq 'root@pam' || $ticketuser eq $username)) {
        # valid ticket. Note: root@pam can create tickets for other users
     } else {
-       $username = PVE::AccessControl::authenticate_user($username, $pw_or_ticket);
+       $username = PVE::AccessControl::authenticate_user($username, $pw_or_ticket, $otp);
     }
 
     my $ticket = PVE::AccessControl::assemble_ticket($username);
@@ -207,6 +206,18 @@ my $compute_api_permission = sub {
     return $res;
 };
 
+__PACKAGE__->register_method ({
+    name => 'get_ticket', 
+    path => 'ticket', 
+    method => 'GET',
+    permissions => { user => 'world' },
+    description => "Dummy. Useful for formaters which want to priovde a login page.",
+    parameters => {
+       additionalProperties => 0,
+    },
+    returns => { type => "null" },
+    code => sub { return undef; }});
+  
 __PACKAGE__->register_method ({
     name => 'create_ticket', 
     path => 'ticket', 
@@ -232,6 +243,11 @@ __PACKAGE__->register_method ({
                description => "The secret password. This can also be a valid ticket.",
                type => 'string',
            },
+           otp => {
+               description => "One-time password for Two-factor authentication.",
+               type => 'string',
+               optional => 1,
+           },
            path => {
                description => "Verify ticket, and check if user have access 'privs' on 'path'",
                type => 'string',
@@ -265,30 +281,22 @@ __PACKAGE__->register_method ({
        my $rpcenv = PVE::RPCEnvironment::get();
 
        my $res;
-
-       my $starttime = [gettimeofday];
-
        eval {
            # test if user exists and is enabled
            $rpcenv->check_user_enabled($username);
 
            if ($param->{path} && $param->{privs}) {
-               $res = &$verify_auth($rpcenv, $username, $param->{password},
+               $res = &$verify_auth($rpcenv, $username, $param->{password}, $param->{otp},
                                     $param->{path}, $param->{privs});
            } else {
-               $res = &$create_ticket($rpcenv, $username, $param->{password});
+               $res = &$create_ticket($rpcenv, $username, $param->{password}, $param->{otp});
            }
        };
        if (my $err = $@) {
            my $clientip = $rpcenv->get_client_ip() || '';
            syslog('err', "authentication failure; rhost=$clientip user=$username msg=$err");
            # do not return any info to prevent user enumeration attacks
-           # always try to delay exactly 3 seconds to prevent timing attacks
-           my $elapsed;
-           while (($elapsed = tv_interval($starttime)) < 3) {
-               usleep(int((3 - $elapsed)*1000000));
-           }
-           die "authentication failure\n"; 
+           die PVE::Exception->new("authentication failure\n", code => 401);
        }
 
        $res->{cap} = &$compute_api_permission($rpcenv, $username);