[pve-devel] r5591 - in pve-manager/pve2: . lib/PVE www/manager/window
svn-commits at proxmox.com
svn-commits at proxmox.com
Wed Feb 23 09:59:02 CET 2011
Author: dietmar
Date: 2011-02-23 09:59:02 +0100 (Wed, 23 Feb 2011)
New Revision: 5591
Modified:
pve-manager/pve2/ChangeLog
pve-manager/pve2/lib/PVE/APIDaemon.pm
pve-manager/pve2/lib/PVE/REST.pm
pve-manager/pve2/www/manager/window/LoginWindow.js
Log:
2011-02-23 Proxmox Support Team <support at proxmox.com>
* lib/PVE/REST.pm (rest_handler): use standard framework to create
tickets.
* www/manager/window/LoginWindow.js: use new URIs (/access/ticket)
* lib/PVE/REST.pm (proxy_handler): set 'PVEClientIP' header - that
way we can log auth failures with client IP (can be use by
fail2ban)
Modified: pve-manager/pve2/ChangeLog
===================================================================
--- pve-manager/pve2/ChangeLog 2011-02-23 08:30:06 UTC (rev 5590)
+++ pve-manager/pve2/ChangeLog 2011-02-23 08:59:02 UTC (rev 5591)
@@ -1,3 +1,14 @@
+2011-02-23 Proxmox Support Team <support at proxmox.com>
+
+ * lib/PVE/REST.pm (rest_handler): use standard framework to create
+ tickets.
+
+ * www/manager/window/LoginWindow.js: use new URIs (/access/ticket)
+
+ * lib/PVE/REST.pm (proxy_handler): set 'PVEClientIP' header - that
+ way we can log auth failures with client IP (can be use by
+ fail2ban)
+
2011-02-16 Proxmox Support Team <support at proxmox.com>
* lib/PVE/REST.pm (rest_handler): use new PVE::RPCEnvironment
Modified: pve-manager/pve2/lib/PVE/APIDaemon.pm
===================================================================
--- pve-manager/pve2/lib/PVE/APIDaemon.pm 2011-02-23 08:30:06 UTC (rev 5590)
+++ pve-manager/pve2/lib/PVE/APIDaemon.pm 2011-02-23 08:59:02 UTC (rev 5591)
@@ -267,8 +267,10 @@
my $parser = HTTP::Request::Params->new({req => $r});
my $params = $parser->params;
- my $res = PVE::REST::rest_handler($method, $uri, $rel_uri, $ticket, $params);
+ my $clientip = $headers->header('PVEClientIP');
+ my $res = PVE::REST::rest_handler($clientip, $method, $uri, $rel_uri, $ticket, $params);
+
if ($res->{proxy}) {
$res->{status} = 500;
Modified: pve-manager/pve2/lib/PVE/REST.pm
===================================================================
--- pve-manager/pve2/lib/PVE/REST.pm 2011-02-23 08:30:06 UTC (rev 5590)
+++ pve-manager/pve2/lib/PVE/REST.pm 2011-02-23 08:59:02 UTC (rev 5591)
@@ -35,34 +35,6 @@
return $cookie;
}
-sub create_ticket {
- my ($user, $pw) = @_;
-
- # NOTE: $pw is allowed to be a ticket
-
- my $euid = $>;
-
- my $ticket;
- eval {
- my $tmp;
- if (($tmp = PVE::AccessControl::verify_ticket($pw, 1)) &&
- ($tmp eq $user)) {
- # got valid ticket
- } else {
- $user = PVE::AccessControl::authenticate_user($user, $pw);
- }
- $ticket = PVE::AccessControl::assemble_ticket($user);
- };
- my $err = $@;
-
- if ($err) {
- syslog('err', $err);
- return undef;
- }
-
- return $ticket;
-}
-
sub extract_auth_cookie {
my ($cookie) = @_;
@@ -195,7 +167,7 @@
}
sub proxy_handler {
- my($r, $host, $method, $abs_uri, $ticket, $params) = @_;
+ my($r, $clientip, $host, $method, $abs_uri, $ticket, $params) = @_;
syslog('info', "proxy start $method $host:$abs_uri");
@@ -207,6 +179,7 @@
$ua->default_header('cookie' => "${cookie_name}=$ticket") if $ticket;
$ua->default_header('PVEDisableProxy' => 'true');
+ $ua->default_header('PVEClientIP' => $clientip);
my $uri = URI->new();
@@ -266,6 +239,8 @@
my $check_permissions = sub {
my ($rpcenv, $perm, $username, $param) = @_;
+ return 1 if !$username && $perm->{user} eq 'world';
+
return 1 if $username eq 'root at pam';
die "permission check failed (user != root)\n" if !$perm;
@@ -288,7 +263,7 @@
};
sub rest_handler {
- my ($method, $abs_uri, $rel_uri, $ticket, $params) = @_;
+ my ($clientip, $method, $abs_uri, $rel_uri, $ticket, $params) = @_;
my $rpcenv = PVE::RPCEnvironment::get();
@@ -299,60 +274,31 @@
}
my $euid = $>;
-
- if ($rel_uri eq '/realms' && $method eq 'GET') {
- return { status => HTTP_OK,
- data => $rpcenv->realm_list() };
+ my $require_auth = 1;
- } elsif ($rel_uri eq '/ticket') {
- my $user = $params->{username} || '';
- my $pw = $params->{password} || '';
+ # explicitly allow some calls without auth
+ if (($rel_uri eq '/access/domains' && $method eq 'GET') ||
+ ($rel_uri eq '/access/ticket' && $method eq 'POST')) {
+ $require_auth = 0;
+ }
- $user .= "\@$params->{realm}" if $params->{realm};
+ my ($username, $age);
- if (!$rpcenv->user_enabled($user)) {
- return {
- status => HTTP_FORBIDDEN,
- message => "No such user (user not enabled).",
- };
- }
+ if ($require_auth) {
- return { proxy => 'localhost' } if ($euid != 0);
+ return {
+ status => HTTP_UNAUTHORIZED,
+ message => "No ticket",
+ } if !$ticket;
- #syslog('info', "ticket auth $user $pw");
+ ($username, $age) = PVE::AccessControl::verify_ticket($ticket, 1);
- if (!($ticket = create_ticket($user, $pw))) {
- return {
- status => HTTP_FORBIDDEN,
- message => "Unable to verify credentials.",
- };
- }
-
- if (defined($params->{path}) || defined($params->{permissions})) {
- my @privs = PVE::Tools::split_list($params->{permissions});
- my $path = PVE::AccessControl::normalize_path($params->{path});
- if (!($path && scalar(@privs) && $rpcenv->check($user, $path, \@privs))) {
- my $msg = "permission check failed ($params->{path}, $params->{permissions})";
- syslog('info', $msg);
- return {
- status => HTTP_FORBIDDEN,
- message => $msg,
- };
- }
- }
-
- PVE::Cluster::log_msg('info', 'root at pam', "successful auth for user '$user'");
- return { status => HTTP_OK, ticket => $ticket,
- data => { ticket => $ticket }};
+ return {
+ status => HTTP_UNAUTHORIZED,
+ message => "Ticket verify failed",
+ } if !$username;
}
-
- my ($username, $age);
- ($username, $age) = PVE::AccessControl::verify_ticket($ticket, 1) if $ticket;
-
- return { status => HTTP_UNAUTHORIZED } if !($ticket && $username);
-
- #syslog ('info', "GOT $method $abs_uri VALID TICKET $ticket");
my $uri_param = {};
my ($handler, $info) = PVE::API2->find_handler($method, $rel_uri, $uri_param);
@@ -412,6 +358,7 @@
# set environment variables
$rpcenv->set_language('C'); # fixme:
$rpcenv->set_user($username);
+ $rpcenv->set_client_ip($clientip);
my $resp = {
info => $info, # useful to format output
@@ -433,6 +380,12 @@
}
}
+ $rpcenv->set_user(undef);
+
+ if ($rel_uri eq '/access/ticket') {
+ $resp->{ticket} = $resp->{data}->{ticket};
+ }
+
# fixme: update ticket if too old
# $resp->{ticket} = update_ticket($ticket);
@@ -461,6 +414,7 @@
#syslog('info', "perl handler called");
my $method = $r->method;
+ my $clientip = $r->connection->remote_ip();
return HTTP_NOT_IMPLEMENTED
if !$known_methods->{$method};
@@ -479,7 +433,7 @@
my ($rel_uri, $format) = split_abs_uri($abs_uri);
return HTTP_NOT_IMPLEMENTED if !$format;
- my $res = rest_handler($method, $abs_uri, $rel_uri, $ticket, $params);
+ my $res = rest_handler($clientip, $method, $abs_uri, $rel_uri, $ticket, $params);
if ($res->{proxy}) {
if ($r->headers_in->{'PVEDisableProxy'}) {
@@ -488,7 +442,8 @@
$r->status_line("$code proxy loop detected - aborted");
return $res->{status};
}
- return proxy_handler($r, $res->{proxy}, $method, $abs_uri, $ticket, $params);
+ return proxy_handler($r, $clientip, $res->{proxy}, $method,
+ $abs_uri, $ticket, $params);
}
prepare_response_data($format, $res);
Modified: pve-manager/pve2/www/manager/window/LoginWindow.js
===================================================================
--- pve-manager/pve2/www/manager/window/LoginWindow.js 2011-02-23 08:30:06 UTC (rev 5590)
+++ pve-manager/pve2/www/manager/window/LoginWindow.js 2011-02-23 08:59:02 UTC (rev 5591)
@@ -32,7 +32,7 @@
var self = this;
var realmstore = new Ext.data.JsonStore({
- url: "/api2/json/realms",
+ url: "/api2/json/access/domains",
autoDestory: true,
root: 'data',
restful: true, // use GET, not POST
@@ -85,7 +85,7 @@
items: [{
xtype: 'form',
frame: true,
- url: '/api2/extjs/ticket',
+ url: '/api2/extjs/access/ticket',
labelWidth: 70,
labelAlign : 'right',
More information about the pve-devel
mailing list