[pve-devel] r5558 - in pve-access-control/trunk: . PVE PVE/API2

svn-commits at proxmox.com svn-commits at proxmox.com
Thu Feb 17 12:06:19 CET 2011


Author: dietmar
Date: 2011-02-17 12:06:18 +0100 (Thu, 17 Feb 2011)
New Revision: 5558

Modified:
   pve-access-control/trunk/ChangeLog
   pve-access-control/trunk/PVE/API2/User.pm
   pve-access-control/trunk/PVE/AccessControl.pm
   pve-access-control/trunk/README
   pve-access-control/trunk/control.in
Log:
	* PVE/AccessControl.pm (authenticate_user_domain): added a 'domid'
	attribute to users. This references an entry in the domain
	config. This is simpler than the previous domain search
	algorithm.

	* PVE/API2/User.pm: save domid, name, comment and expire time for
	user entries.

	* PVE/AccessControl.pm (authenticate_user): check for expired
	accounts

	* control.in (Depends): depend on liburi-perl (we use URI::Escape
	to encode text in our config files).

	* PVE/AccessControl.pm (enable_user, disable_user): removed
	clumsy methods, not needed.



Modified: pve-access-control/trunk/ChangeLog
===================================================================
--- pve-access-control/trunk/ChangeLog	2011-02-17 06:04:47 UTC (rev 5557)
+++ pve-access-control/trunk/ChangeLog	2011-02-17 11:06:18 UTC (rev 5558)
@@ -1,3 +1,22 @@
+2011-02-17  Proxmox Support Team  <support at proxmox.com>
+
+	* PVE/AccessControl.pm (authenticate_user_domain): added a 'domid'
+	attribute to users. This references an entry in the domain
+	config. This is simpler than the previous domain search
+	algorithm.
+
+	* PVE/API2/User.pm: save domid, name, comment and expire time for
+	user entries.
+
+	* PVE/AccessControl.pm (authenticate_user): check for expired
+	accounts
+
+	* control.in (Depends): depend on liburi-perl (we use URI::Escape
+	to encode text in our config files).
+
+	* PVE/AccessControl.pm (enable_user, disable_user): removed
+	clumsy methods, not needed.
+
 2011-02-16  Proxmox Support Team  <support at proxmox.com>
 
 	* README (privileges): Changes set of privileges. We try to be as

Modified: pve-access-control/trunk/PVE/API2/User.pm
===================================================================
--- pve-access-control/trunk/PVE/API2/User.pm	2011-02-17 06:04:47 UTC (rev 5557)
+++ pve-access-control/trunk/PVE/API2/User.pm	2011-02-17 11:06:18 UTC (rev 5558)
@@ -15,6 +15,24 @@
 
 use base qw(PVE::RESTHandler);
 
+my $extract_user_data = sub {
+    my ($data) = @_;
+
+    my $res;
+
+    foreach my $prop (qw(domid enabled expire name comment)) {
+	$res->{$prop} = $data->{$prop} if defined($data->{$prop});
+    }
+
+    if ($data->{groups}) {
+	if (my @ga = keys %{$data->{groups}}) {
+	    $res->{groups} = join(',', @ga);
+	}
+    }
+
+    return $res;
+};
+
 # fixme: index should return more/all attributes?
 __PACKAGE__->register_method ({
     name => 'index', 
@@ -45,7 +63,9 @@
 	foreach my $user (keys %{$usercfg->{users}}) {
 	    next if $user eq 'root';
 
-	    push @$res, { id => $user };
+	    my $entry = &$extract_user_data($usercfg->{users}->{$user});
+	    $entry->{id} = $user;
+	    push @$res, $entry;
 	}
 
 	return $res;
@@ -83,8 +103,17 @@
    	additionalProperties => 0,
 	properties => {
 	    userid => get_standard_option('userid'),
+	    domid =>  get_standard_option('domid', { optional => 1 }),
 	    password => { type => 'string', optional => 1 },
 	    groups => { type => 'string', optional => 1, format => 'pve-groupid-list'},
+	    name => { type => 'string', optional => 1 },
+	    comment => { type => 'string', optional => 1 },
+	    expire => { 
+		description => "Account expiration date (seconds since epoch). '0' means no expiration date.",
+		type => 'integer', 
+		minimum => 0,
+		optional => 1 
+	    },
 	},
     },
     returns => { type => 'null' },
@@ -94,24 +123,22 @@
 	PVE::AccessControl::lock_user_config(
 	    sub {
 			
-		my ($username, undef, $domain) = 
-		    PVE::AccessControl::verify_username($param->{userid});
+		my $username = PVE::AccessControl::verify_username($param->{userid});
 	
 		my $usercfg = cfs_read_file("user.cfg");
 
 		die "user '$username' already exists\n" 
 		    if $usercfg->{users}->{$username};
-			 		
-		if ($param->{password}) {
-		    if ($domain) {
-			die "can't set password on auth domain '$domain'\n";
-		    } else {
-			PVE::AccessControl::store_shadow_password($username, $param->{password});
-		    }
-		}
+			 
+		my $domid = $param->{domid};
 
-		PVE::AccessControl::enable_user($username, $usercfg);
+		PVE::AccessControl::domain_set_password($domid, $username, $param->{password})
+		    if $param->{password};
 
+		$usercfg->{users}->{$username} = { enabled => 1 };
+		$usercfg->{users}->{$username}->{domid} = $domid if $domid;
+		$usercfg->{users}->{$username}->{expire} = $param->{expire} if $param->{expire};
+
 		if ($param->{groups}) {
 		    foreach my $group (split_list($param->{groups})) {
 			if ($usercfg->{groups}->{$group}) {
@@ -122,6 +149,9 @@
 		    }
 		}
 
+		$usercfg->{users}->{$username}->{name} = $param->{name} if $param->{name};
+		$usercfg->{users}->{$username}->{comment} = $param->{comment} if $param->{comment};
+
 		cfs_write_file("user.cfg", $usercfg);
 	    }, "create user failed");
 
@@ -139,7 +169,17 @@
 	    userid => get_standard_option('userid'),
 	},
     },
-    returns => {},
+    returns => {
+   	additionalProperties => 0,
+	properties => {
+	    domid => get_standard_option('domid'),
+	    enabled => { type => 'boolean' },
+	    expire => { type => 'integer' },
+	    name => { type => 'string', optional => 1 },
+	    comment => { type => 'string', optional => 1 },    
+	    groups => { type => 'string', optional => 1, format => 'pve-groupid-list'},
+	}
+    },
     code => sub {
 	my ($param) = @_;
 
@@ -152,7 +192,7 @@
 
 	die "user '$username' does not exist\n" if !$data;
 
-	return $data;
+	return &$extract_user_data($data);
     }});
 
 __PACKAGE__->register_method ({
@@ -165,6 +205,7 @@
    	additionalProperties => 0,
 	properties => {
 	    userid => get_standard_option('userid'),
+	    domid =>  get_standard_option('domid', { optional => 1 }),
 	    password => { type => 'string', optional => 1 },
 	    groups => { type => 'string', optional => 1,  format => 'pve-groupid-list'  },
 	    append => { 
@@ -176,6 +217,12 @@
 	    unlock => { type => 'boolean', optional => 1 },
 	    name => { type => 'string', optional => 1 },
 	    comment => { type => 'string', optional => 1 },
+	    expire => { 
+		description => "Account expiration date (seconds since epoch). '0' means no expiration date.",
+		type => 'integer', 
+		minimum => 0,
+		optional => 1 
+	    },
 	},
     },
     returns => { type => 'null' },
@@ -196,18 +243,19 @@
 		die "user '$username' does not exist\n" 
 		    if !$usercfg->{users}->{$username};
 
-		if ($param->{password}) {
-		    if ($domain) {
-			die "can't set password on auth domain '$domain'\n";
-		    } else {
-			PVE::AccessControl::store_shadow_password($username, $param->{password});
-		    }
-		}
+		my $domid = $param->{domid};
 
-		PVE::AccessControl::enable_user($username, $usercfg) if $param->{unlock};
+		PVE::AccessControl::domain_set_password($domid, $username, $param->{password})
+		    if $param->{password};
 
-		PVE::AccessControl::disable_user($username, $usercfg) if $param->{lock};
+		$usercfg->{users}->{$username}->{enabled} = 1 if $param->{unlock};
 
+		$usercfg->{users}->{$username}->{enabled} = 0 if $param->{lock};
+
+		$usercfg->{users}->{$username}->{domid} = $domid if $domid;
+
+		$usercfg->{users}->{$username}->{expire} = $param->{expire} if $param->{expire};
+
 		PVE::AccessControl::delete_user_group($username, $usercfg) 
 		    if (!$param->{append} && $param->{groups});
 
@@ -221,10 +269,9 @@
 		    }
 		}
 
-		PVE::AccessControl::name_user($username, $usercfg) if $param->{name};
+		$usercfg->{users}->{$username}->{name} = $param->{name} if $param->{name};
+		$usercfg->{users}->{$username}->{comment} = $param->{comment} if $param->{comment};
 
-		PVE::AccessControl::comment_user($username, $usercfg) if $param->{comment};
-
 		cfs_write_file("user.cfg", $usercfg);
 	    }, "update user failed");
 	

Modified: pve-access-control/trunk/PVE/AccessControl.pm
===================================================================
--- pve-access-control/trunk/PVE/AccessControl.pm	2011-02-17 06:04:47 UTC (rev 5557)
+++ pve-access-control/trunk/PVE/AccessControl.pm	2011-02-17 11:06:18 UTC (rev 5558)
@@ -11,6 +11,8 @@
 use PVE::Tools qw(run_command lock_file file_get_contents split_list safe_print);
 use PVE::Cluster qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
 use PVE::JSONSchema;
+use Encode;
+use URI::Escape;
 
 use Data::Dumper; # fixme: remove
 
@@ -198,13 +200,13 @@
 
 sub authenticate_user_ldap {
 
-    my ($entry, $username, $password) = @_;
+    my ($entry, $server, $username, $password) = @_;
 
     my (undef, $user, $domain) = verify_username($username);
     my $default_port = ($entry->{type} eq 'ldap') ? 389 : 636;
     my $port = $entry->{port} ? $entry->{port} : $default_port;
     my $conn_string = $entry->{type} . "://" if ($entry->{type} ne 'ldap');
-    $conn_string .= $entry->{server} . ":" . $port;
+    $conn_string .= $server . ":" . $port;
     my $ldap = Net::LDAP->new($conn_string, verify => 'none') || die "$@\n";
     my $search = $entry->{user_attr} . "=" . $user;
     my $result = $ldap->search( base    => "$entry->{base_dn}",
@@ -225,74 +227,46 @@
 }
 
 sub authenticate_user_domain {
-
-    my ($username, $password) = @_;
+    my ($domid, $username, $password) = @_;
  
     my $domain_cfg = cfs_read_file($domainconfigfile);
 
-    my (undef, $user, $domain) = verify_username($username);
+    die "no auth domain specified" if !$domid;
 
-    my $shadow = {
-	type => "shadow",
-	domains => [ '' ], # names without domain part
-    };
+    if ($domid eq 'pam') {
+	authenticate_user_pam($username, $password);
+	return;
+    } 
 
-    my $pam = {
-	type => "PAM",
-	domains => [ 'localhost' ],
-    };
+    eval {
+	if ($domid eq 'pve') {
+	    authenticate_user_shadow($username, $password);
+	} else { 
 
-    my @entries = @$domain_cfg;
-    # add 'PAM' if not configured if domain.cfg
-    push @entries, $pam if !grep {$_->{type} eq 'PAM'} @entries;
-    # add 'shadow' if not configured if domain.cfg
-    push @entries, $shadow if !grep {$_->{type} eq 'shadow'} @entries;
-
-    my $found;
-
-    my $errmsg = '';
-
-    foreach my $entry (@$domain_cfg, $pam, $shadow) {
-	foreach my $doms ($entry->{domains}) {    
-	    foreach my $dom (@$doms) {
-		if ((!$domain && ($dom eq '')) || 
-		    ($domain && ($domain =~ m/^${dom}$/))) {
-
-		    $found = 1;
-
-		    eval {
-			if ($entry->{type} eq 'shadow') {
-			    authenticate_user_shadow($username, $password);
-			} elsif ($entry->{type} eq 'PAM') {
-			    authenticate_user_pam($user, $password);
-			} elsif ($entry->{type} eq 'ad') {
-			    authenticate_user_ad($entry->{server}, $username, $password);
-			} elsif (($entry->{type} eq 'ldap') || ($entry->{type} eq 'ldaps')) {
-			    authenticate_user_ldap($entry, $username, $password);
-			} else {
-			    die "unknown auth type '$entry->{type}'\n";
-			}
-		    };
-		    my $err = $@;
-
-		    if ($err) {
-			chomp($err);
-			$errmsg .= "$entry->{type}: $err\n";
-			#warn "$entry->{type} auth failed: $err\n";
-			next;
-		    }
-		    
-		    # no exceptions, so auth was successful
-		    return 1;
-		}
+	    my $cfg = $domain_cfg->{$domid};
+	    die "auth domain '$domid' does not exists\n" if !$cfg;
+    
+	    if ($cfg->{type} eq 'ad') {
+		eval { authenticate_user_ad($cfg->{server1}, $username, $password); };
+		my $err = $@;
+		return if !$err;
+		die $err if !$cfg->{server2};
+		authenticate_user_ad($cfg->{server2}, $username, $password); 
+	    } elsif (($cfg->{type} eq 'ldap') || ($cfg->{type} eq 'ldaps')) {
+		eval { authenticate_user_ldap($cfg, $cfg->{server1}, $username, $password); };
+		my $err = $@;
+		return if !$err;
+		die $err if !$cfg->{server2};
+		authenticate_user_ldap($cfg, $cfg->{server2}, $username, $password); 
+	    } else {
+		die "unknown auth type '$cfg->{type}'\n";
 	    }
 	}
+    };
+    if (my $err = $@) {
+	sleep(2); # timeout after failed auth
+	die $err;
     }
-
-    sleep(2); # timeout after failed auth
-
-    die "domain \'$domain\' not defined\n" if !$found;
-    die $errmsg || "internal error";
 }
 
 sub user_enabled {
@@ -317,18 +291,28 @@
 
 	die "no username specified\n" if !$username;
  
-	my ($user, $domain);
-
-	($username, $user, $domain) = verify_username($username);
+	$username = verify_username($username);
  
 	my $usercfg = cfs_read_file('user.cfg');
 
-	die "no such user ('$username')\n" if !user_enabled($usercfg, $username);
+	if (!user_enabled($usercfg, $username)) {
+	    sleep(2);
+	    die "no such user ('$username')\n"
+	}
 
+	my $ctime = time();
+	my $expire = $usercfg->{users}->{$username}->{expire};
+	my $domid = $usercfg->{users}->{$username}->{domid};
+
+	if ($expire && ($expire < $ctime)) {
+	    sleep(2);
+	    die "account expired\n"
+	}
+
 	if ($username eq 'root') { # always use PAM for root
 	    authenticate_user_pam($username, $password);
 	} else {
-	    authenticate_user_domain($username, $password);
+	    authenticate_user_domain($domid, $username, $password);
 	}
     };
 
@@ -338,8 +322,8 @@
 }
 
 sub delete_shadow_password {
-
     my ($username) = @_;
+ 
     lock_shadow_config(sub {
 	my $shadow_cfg = cfs_read_file($shadowconfigfile);
 	delete ($shadow_cfg->{users}->{$username})
@@ -349,8 +333,8 @@
 }
 
 sub store_shadow_password {
-
-    my ($username,$password) = @_;
+    my ($username, $password) = @_;
+  
     lock_shadow_config(sub {
 	my $shadow_cfg = cfs_read_file($shadowconfigfile);
 	$shadow_cfg->{users}->{$username}->{shadow} = encrypt_pw($password);
@@ -365,6 +349,35 @@
     return crypt (encode("utf8", $pw), "\$5\$$time\$");
 }
 
+sub store_pam_password {
+    my ($username, $password) = @_;
+
+    my $cmd = ['/usr/sbin/usermod'];
+
+    my $epw = encrypt_pw($password);
+    push @$cmd, '-p', $epw;
+
+    push @$cmd, $username;
+
+    run_command($cmd);
+}
+
+sub domain_set_password {
+    my ($domid, $username, $password) = @_;
+
+    if ($username eq 'root') {
+	store_pam_password($username, $password);
+    } elsif ($domid) {
+	if ($domid eq 'pam') {
+	    store_pam_password($username, $password);
+	} else {
+	    die "can't set password on auth domain '$domid'\n";
+	}
+    } else {
+	store_shadow_password($username, $password);
+    }
+}
+
 sub add_user_group {
 
     my ($username, $usercfg, $group) = @_;
@@ -406,34 +419,20 @@
 
 }
 
-sub disable_user {
+sub encode_text {
+    my ($text) = @_;
 
-    my ($username, $usercfg) = @_;
-
-    $usercfg->{users}->{$username} = { enabled => 0 };
-
+    # all control and hi-bit characters, and ':'
+    my $unsafe = "^\x20-\x39\x3b-\x7e";
+    return uri_escape(Encode::encode("utf8", $text), $unsafe);
 }
 
-sub enable_user {
+sub decode_text {
+    my ($data) = @_;
 
-    my ($username, $usercfg) = @_;
-
-    $usercfg->{users}->{$username} = { enabled => 1 };
-
+    return Encode::decode("utf8", uri_unescape($data));
 }
 
-sub name_user {
-
-    warn "change name not implemented\n";
-
-}
-
-sub comment_user {
-
-    warn "change comment not implemented\n";
-
-}
-
 my $valid_privs = {
     'VM.Audit' => 1,
     'VM.Modify' => 1,
@@ -467,7 +466,8 @@
 };
 
 my $valid_attributes = {
-    server => '[\w\d]+(.[\w\d]+)*',
+    server1 => '[\w\d]+(.[\w\d]+)*',
+    server2 => '[\w\d]+(.[\w\d]+)*',
     base_dn => '\w+=[\w\s]+(,\s*\w+=[\w\s]+)*',
     user_attr => '\S{2,}',
     port => '\d*',
@@ -518,8 +518,6 @@
 	return undef;
     }
 
-    $username =~ s/root\@localhost/root/;
-
     # we only allow a limited set of characters (colon is not allowed,
     # because we store usernames in colon separated lists)!
     if ($username =~ m/^([A-Za-z0-9\.\-_]+)(\@([A-Za-z0-9\.\-_]+))?$/) {
@@ -535,6 +533,10 @@
     type => 'string', format => 'pve-userid',
 });
 
+PVE::JSONSchema::register_standard_option('domid', {
+    description => "Authentication domain ID",
+    type => 'string', format => 'pve-configid',
+});
 
 PVE::JSONSchema::register_format('pve-groupid', \&verify_groupname);
 sub verify_groupname {
@@ -614,15 +616,28 @@
 	my $et = shift @data;
 
 	if ($et eq 'user') {
-	    my ($user, $enabled) = @data;
+	    my ($user, $enabled, $expire, $domid, $name, $comment) = @data;
 
 	    if (!verify_username($user, 1)) {
 		warn "user config - ignore user '$user' - invalid characters in user name\n";
 		next;
 	    }
-	    
+
+	    if ($domid && !PVE::JSONSchema::pve_verify_configid($domid, 1)) {
+		warn "user config - ignore user '$user' - (illegal characters in domain '$domid')\n";
+		next;
+	    }
+
 	    $enabled = $enabled ? 1 : 0;
 
+	    $expire = 0 if !$expire;
+
+	    if ($expire !~ m/^\d+$/) {
+		warn "user config - ignore user '$user' - (illegal characters in expire '$expire')\n";
+		next;
+	    }
+	    $expire = int($expire);
+
 	    #if (!verify_groupname ($group, 1)) {
 	    #    warn "user config - ignore user '$user' - invalid characters in group name\n";
 	    #    next;
@@ -632,6 +647,10 @@
 		enabled => $enabled,
 		# group => $group,
 	    };
+	    $cfg->{users}->{$user}->{domid} = $domid ? $domid : 'pve';
+	    $cfg->{users}->{$user}->{name} = decode_text($name) if $name;
+	    $cfg->{users}->{$user}->{comment} = decode_text($comment) if $comment;
+	    $cfg->{users}->{$user}->{expire} = $expire;
 
 	    #$cfg->{users}->{$user}->{groups}->{$group} = 1;
 	    #$cfg->{groups}->{$group}->{$user} = 1;
@@ -751,8 +770,7 @@
 sub parse_domains {
     my ($filename, $raw) = @_;
 
-    my $connlist = [];
-    my $ad;
+    my $cfg = {};
 
     $raw = "" if !defined($raw);
 
@@ -762,24 +780,21 @@
 	next if $line =~ m/^\#/; # skip comment lines
 	next if $line =~ m/^\s*$/; # skip empty lines
 
-	if ($line =~ m/^(\S+):\s*(.+)\s*$/) {
+	if ($line =~ m/^(\S+):\s*(\S+)\s*$/) {
+	    my $domid = $2;
 	    my $type = lc($1);
-	    my $domains = $2;
+
 	    my $ignore = 0;
+	    my $entry;
 
-	    if (($type ne "ad") && ($type ne "ldap") && ($type ne "ldaps")) {
+	    if (!PVE::JSONSchema::pve_verify_configid($domid, 1)) {
 		$ignore = 1;
-		warn "ignoring domains '$domains' - (unsupported authentication type '$type')\n";
+		warn "ignoring domain '$domid' - (illegal characters)\n";
+	    } elsif (($type ne "ad") && ($type ne "ldap") && ($type ne "ldaps")) {
+		$ignore = 1;
+		warn "ignoring domain '$domid' - (unsupported authentication type '$type')\n";
 	    } else {
-		$ad = { type => $type, domains => [] };
-
-		foreach my $domain (split_list($domains)) {
-		    if (!parse_domain_name ($domain, 1)) {
-			warn "ignoring domain '$domain' - (invalid form)\n";
-		    } else {
-			push @{$ad->{domains}}, $domain;
-		    }
-		}
+		$entry = { type => $type };
 	    }
 
 	    while ($raw =~ s/^(.*)\n//) {
@@ -794,8 +809,8 @@
 		    my ($k, $v) = (lc($1), $3);
 		    if ($valid_attributes->{$k}) {
 			if ($v =~ m/^$valid_attributes->{$k}$/) {
-			    if (!defined($ad->{$k})) {
-				$ad->{$k} = $v;
+			    if (!defined($entry->{$k})) {
+				$entry->{$k} = $v;
 			    } else {
 				warn "ignoring duplicate attribute '$k $v'\n";
 			    }
@@ -809,24 +824,32 @@
 		    warn "ignore config line: $line\n";
 		}
 	    }
-	    if (!$ad->{server}) {
-		warn "ignoring domain '$domains' - missing server attribute\n";
-	    } elsif ((($ad->{type} eq "ldap") || ($ad->{type} eq "ldaps")) && (!$ad->{user_attr})) {
-		warn "ignoring domain '$domains' - missing user attribute\n";
-	    } elsif ((($ad->{type} eq "ldap") || ($ad->{type} eq "ldaps")) && (!$ad->{base_dn})) {
-		warn "ignoring domain '$domains' - missing base_dn attribute\n";
+
+	    if ($entry->{server2} && !$entry->{server1}) {
+		$entry->{server1} = $entry->{server2};
+		delete $entry->{server2};
+	    }
+
+	    if ($ignore) {
+		# do nothing
+	    } elsif (!$entry->{server1}) {
+		warn "ignoring domain '$domid' - missing server attribute\n";
+	    } elsif ((($entry->{type} eq "ldap") || ($entry->{type} eq "ldaps")) && 
+		     (!$entry->{user_attr})) {
+		warn "ignoring domain '$domid' - missing user attribute\n";
+	    } elsif ((($entry->{type} eq "ldap") || ($entry->{type} eq "ldaps")) && 
+		     (!$entry->{base_dn})) {
+		warn "ignoring domain '$domid' - missing base_dn attribute\n";
 	    } else {
-	    push(@$connlist, $ad) if !$ignore;
+		$cfg->{$domid} = $entry;
 	    }
-	    $ad = undef
      
 	} else {
 	    warn "ignore config line: $line\n";
-
 	}
     }
 
-    return $connlist;
+    return $cfg;
 }
 
 sub parse_domain_name {
@@ -859,7 +882,12 @@
 	next if $user eq 'root';
 
 	my $d = $cfg->{users}->{$user};
-	$data .= "user:$user:$d->{enabled}:\n";
+	my $domid = $d->{domid} || 'pve';
+	my $name = $d->{name} ? encode_text($d->{name}) : '';
+	my $comment = $d->{comment} ? encode_text($d->{comment}) : '';
+	my $expire = int($d->{expire}) || 0;
+	my $enabled = $d->{enabled} ? 1 : 0;
+	$data .= "user:$user:$enabled:$expire:$domid:$name:$comment:\n";
     }
 
     $data .= "\n";

Modified: pve-access-control/trunk/README
===================================================================
--- pve-access-control/trunk/README	2011-02-17 06:04:47 UTC (rev 5557)
+++ pve-access-control/trunk/README	2011-02-17 11:06:18 UTC (rev 5558)
@@ -12,30 +12,34 @@
 User Authentication
 ===================
 
-Users are identified by there email address. The domain part of the
-email determines how a user gets authenticated. The file 
+User names need to be unique (else logging gets complicated). So we
+suggest to use email addresses. Each user has an associated
+authentication domain, which references an entry in the file
+'/etc/pve/priv/domain.cfg'. The file associates domain IDs with
+authentication servers.
 
-/etc/pve/auth/domains.cfg
-
-associates domains with authentication servers.
-
 ----example domains.cfg ------------------
 
-AD: proxmox.com,maurer-it.com
-	server 10.10.10.1
+# an active directory server
+AD: mycompany
+	server1 10.10.10.1
+	server2 10.10.10.2
 	...
 
+# an LDAP server
 LDAP: example.com
-	server 10.10.10.2
+	server1 10.10.10.2
       	....
 
 ------------------------------------------
 
-Users without domains get authenticated using our own password file.
+There are 2 special authentication domains name 'pve' and 'pam':
 
-User with 'localhost' as domain ("<user>@localhost") use PAM for authentication.
+ * pve: stores paswords to "/etc/pve/priv/shadow.cfg" (SHA256 crypt); 
 
+ * pam: use unix 'pam'
 
+
 Proposed user database fields:
 ==============================
 
@@ -43,20 +47,18 @@
 
 	login_name: email address (user at domain)
 	enabled: 1 = TRUE, 0 = FALSE
+	expire: <integer> (account expiration date)
+	domid: reference to authentication domain
+	name: full user name
+	comment: arbitrary comment
 
-	# account type: pam, ldap, shadow, ident (how to verify password)
-	# group: primary group name 
-	# real_name: full user name
-	# comment: arbitrary comment
 
 	special user root: The root user has full administrative privileges
 
-	encrypted passwords (SHA256 crypt) are stored in separate shadow file: /etc/pve/auth/shadow.cfg
-
 group:
 
 	group_name: the name of the group
-	description: a more verbose description
+	comment: a more verbose description
 	user_list: list of login names
 
 	special group root: group root has full administrative privileges

Modified: pve-access-control/trunk/control.in
===================================================================
--- pve-access-control/trunk/control.in	2011-02-17 06:04:47 UTC (rev 5557)
+++ pve-access-control/trunk/control.in	2011-02-17 11:06:18 UTC (rev 5558)
@@ -3,7 +3,7 @@
 Section: perl
 Priority: optional
 Architecture: @@ARCH@@
-Depends: libc6 (>= 2.3), perl (>= 5.6.0-16), libcrypt-openssl-rsa-perl, libcrypt-openssl-random-perl, libjson-xs-perl, libjson-perl, libterm-readline-gnu-perl,libnet-ldap-perl, libpve-common-perl, pve-cluster
+Depends: libc6 (>= 2.3), perl (>= 5.6.0-16), libcrypt-openssl-rsa-perl, libcrypt-openssl-random-perl, libjson-xs-perl, libjson-perl, libterm-readline-gnu-perl,libnet-ldap-perl, libpve-common-perl, pve-cluster, liburi-perl
 Maintainer: Proxmox Support Team <support at proxmox.com>
 Description: Proxmox VE access control library
  This package contains the role based user management and access



More information about the pve-devel mailing list