[pve-devel] r4888 - pve-access-control/trunk

svn-commits at proxmox.com svn-commits at proxmox.com
Wed Jul 14 07:50:43 CEST 2010


Author: dietmar
Date: 2010-07-14 05:50:39 +0000 (Wed, 14 Jul 2010)
New Revision: 4888

Modified:
   pve-access-control/trunk/AccessControl.pm
   pve-access-control/trunk/ChangeLog
   pve-access-control/trunk/README
Log:
	* AccessControl.pm: implemented Active Directory authentication


Modified: pve-access-control/trunk/AccessControl.pm
===================================================================
--- pve-access-control/trunk/AccessControl.pm	2010-07-12 08:14:30 UTC (rev 4887)
+++ pve-access-control/trunk/AccessControl.pm	2010-07-14 05:50:39 UTC (rev 4888)
@@ -12,6 +12,7 @@
 use Fcntl ':flock';
 use Digest::SHA;
 use Authen::PAM qw(:constants);
+use Net::LDAP;
 use Data::Dumper; # fixme: remove
 
 # $authdir must be writable by root only!
@@ -23,6 +24,7 @@
 my $shadowconfigfile = "shadow.cfg";
 my $shadowconfigpath = "$authdir/$shadowconfigfile";
 my $shadowconfiglock = "$authdir/.lock-$shadowconfigfile";
+my $domainconfigpath = "$authdir/domains.cfg";
 
 my $ticket_lifetime = 3600*2; # 2 hours
 
@@ -472,6 +474,48 @@
     $pamh = 0; # call destructor
 }
 
+sub authenticate_user_domain {
+
+    my ($username, $password) = @_;
+    my $ldap_resp;
+    my @domain_cfg = load_domains_config();
+    my (undef, $user, $domain) = verify_username($username);
+    foreach my $entry (@domain_cfg) {
+	foreach my $doms ($entry->{domains}) {
+	    foreach my $dom (@$doms) {
+		if ($dom eq $domain) {
+		    $ldap_resp = ldap_bind($entry->{server}, $entry->{type}, $username, $password);
+		    if ($ldap_resp =~ m/route/) {
+                        warn $ldap_resp . "\n";
+                        next;
+		    }
+		    return 1 if ($ldap_resp == 0);
+		    die "invalid credentials\n" if ($ldap_resp == 49);
+		}
+	    }
+	}
+    }
+    die "domain \'$domain\' not defined\n" if !$ldap_resp;
+    die "$ldap_resp\n";
+}
+
+sub ldap_bind {
+
+    my ($server, $type, $username, $password) = @_;
+    my $res;
+    my $ldap = Net::LDAP->new($server) or return $@;
+    if ($type eq "AD") {
+	$res = $ldap->bind( $username, password=>$password );
+    } else {
+	#fixme: Implement LDAP:my $res = $ldap->bind( $username, password=>$password );
+	die "LDAP Authentication not yet implemented.";
+    }
+    my $code = $res->code();
+    $ldap->unbind();
+    return $code;
+
+}
+
 sub user_enabled {
     my ($usercfg, $username) = @_;
 
@@ -510,7 +554,7 @@
 	} elsif ($domain eq 'localhost') {
 	    authenticate_user_pam($username, $password);
 	} else {
-	    die "unknown auth domain '$domain'\n";
+	    authenticate_user_domain($username, $password);
 	}
     };
 
@@ -1143,6 +1187,50 @@
     return $shadow;
 }
 
+sub parse_domains {
+    my ($filename, $fh) = @_;
+
+    my @connlist = ();
+    my $ad = {};
+
+    die "MODE: '$/'" if !$/;
+
+    if ($fh) {
+        while (defined (my $line = <$fh>)) {
+            chomp $line;
+
+            next if $line =~ m/^\s*$/; # skip empty lines
+            $line =~ s/^\s+//; # delete leading blanks
+            $line =~ s/\s+$//; # delete trailing blanks
+            if ($line =~ m/^\S+:\s*\S+$/) {
+                if ($ad->{domains}) {
+                    push(@connlist, $ad);
+                    $ad = {};
+                }
+                my($type,$domains) = split (/:/, $line);
+                $domains =~ s/^\s+//;
+                die "invalid domain type line $.\n" if (($type ne "AD") && ($type ne "LDAP"));
+                foreach my $domain (split_list($domains)) {
+                    die "invalid domain $domain at line $.\n" if ($domain !~ m/^\S+\.\S+$/);
+                    push @{$ad->{domains}}, ($domain);
+                }
+                $ad->{type} = $type;
+            }
+            elsif($line =~ /^\s*(.+?)\s(.+)\s*$/)
+            {
+                if ($1 eq "server") {
+                    $ad->{$1} = $2;
+                } else {
+                    warn "ignoring invalid parameter line $.\n";
+                }
+
+            }
+        }
+    }
+push(@connlist, $ad);
+return @connlist;
+}
+
 my $user_config_cache;
 sub load_user_config {
     my ($reload) = @_;
@@ -1177,6 +1265,23 @@
     return $shadow_config_cache;
 }
 
+my @domains_config_cache;
+sub load_domains_config {
+    my ($reload) = @_;
+
+    return @domains_config_cache if !$reload && @domains_config_cache;
+
+    my @cfg = {};
+
+    my $fh = IO::File->new ($domainconfigpath, 'r');
+    @cfg = parse_domains($domainconfigpath, $fh);
+    $fh->close() if $fh;
+
+    @domains_config_cache = @cfg;
+
+    return @domains_config_cache;
+}
+
 sub save_shadow_config {
     my ($cfg) = @_;
 

Modified: pve-access-control/trunk/ChangeLog
===================================================================
--- pve-access-control/trunk/ChangeLog	2010-07-12 08:14:30 UTC (rev 4887)
+++ pve-access-control/trunk/ChangeLog	2010-07-14 05:50:39 UTC (rev 4888)
@@ -1,3 +1,7 @@
+2010-07-14  Seth Lauzon <seth.lauzon at gmail.com>A
+
+	* AccessControl.pm: implemented Active Directory authentication
+
 2010-07-09  Seth Lauzon <seth.lauzon at gmail.com>
 
 	* AccessControl.pm (modify_acl): check if role exists

Modified: pve-access-control/trunk/README
===================================================================
--- pve-access-control/trunk/README	2010-07-12 08:14:30 UTC (rev 4887)
+++ pve-access-control/trunk/README	2010-07-14 05:50:39 UTC (rev 4888)
@@ -15,11 +15,11 @@
 Users are identified by there email address. The domain part of the
 email determines how a user gets authenticated. The file 
 
-/etc/pve/auth.cfg 
+/etc/pve/auth/domains.cfg
 
 associates domains with authentication servers.
 
-----example auth.cfg ---------------------
+----example domains.cfg ------------------
 
 AD: proxmox.com,maurer-it.com
 	server 10.10.10.1



More information about the pve-devel mailing list