]> git.proxmox.com Git - pmg-api.git/blobdiff - PMG/LDAPCache.pm
show all errors when we get an ldap connection error
[pmg-api.git] / PMG / LDAPCache.pm
index b361eee3f19ef840418e97c60ebb1a9111fe6518..0d3601915acb281d2462a764e98cb7297c4a57ad 100755 (executable)
@@ -11,8 +11,10 @@ use Net::LDAP::Constant qw (LDAP_CONTROL_PAGED);
 use DB_File;
 
 use PVE::SafeSyslog;
+use PVE::Tools qw(split_list);
 
 use PMG::Utils;
+use PMG::LDAPConfig;
 
 $DB_HASH->{'cachesize'} = 10000;
 $DB_RECNO->{'cachesize'} = 10000;
@@ -51,20 +53,20 @@ sub new {
        $self->{id} = $id;
     }
 
-    if (!$args{mailattr}) {
-       $args{mailattr} = "mail, userPrincipalName, proxyAddresses, othermailbox";
-    }
-    $args{mailattr} =~ s/[\,\;]/ /g;
-    $args{mailattr} =~ s/\s+/,/g;
+    my $config_properties = PMG::LDAPConfig::properties();
 
-    if ($args{mode} && ($args{mode} eq 'ldap' ||  $args{mode} eq 'ldaps')) {
-       $self->{mode} = $args{mode};
-    } else {
-       $self->{mode} = 'ldap';
+    # set defaults for the fields that have one
+    foreach my $property (keys %$config_properties) {
+       my $d = $config_properties->{$property};
+       next if !defined($d->{default});
+       $self->{$property} = $args{$property} || $d->{default};
     }
 
-    $self->{accountattr} = $args{accountattr} || 'sAMAccountName';
-    @{$self->{mailattr}} = split(/,/, $args{mailattr});
+    # split list returns an array not a reference
+    $self->{accountattr} = [split_list($self->{accountattr})];
+    $self->{mailattr} = [split_list($self->{mailattr})];
+    $self->{groupclass} = [split_list($self->{groupclass})];
+
     $self->{server1} = $args{server1};
     $self->{server2} = $args{server2};
     $self->{binddn} = $args{binddn};
@@ -156,7 +158,7 @@ sub queryusers {
        scope    => "subtree",
        filter   => $filter,
        control  => [ $page ],
-       attrs  => [ @{$self->{mailattr}}, $self->{accountattr}, 'memberOf' ]
+       attrs  => [ @{$self->{mailattr}}, @{$self->{accountattr}}, 'memberOf' ]
        );
 
     my $cookie;
@@ -207,12 +209,14 @@ sub queryusers {
                $self->{dbstat}->{dnames}->{dbh}->put($dn, $cuid);
            }
 
-           my $account = $entry->get_value($self->{accountattr});
-           if ($account && ($account =~ m/^\S+$/s)) {
-               $account = lc($account);
-               $self->{dbstat}->{accounts}->{dbh}->put($account, $cuid);
-               my $data = pack('n/a* n/a* n/a*', $pmail, $account, $dn);
-               $self->{dbstat}->{users}->{dbh}->put($cuid, $data);
+           foreach my $attr (@{$self->{accountattr}}) {
+               my $account = $entry->get_value($attr);
+               if ($account && ($account =~ m/^\S+$/s)) {
+                   $account = lc($account);
+                   $self->{dbstat}->{accounts}->{dbh}->put($account, $cuid);
+                   my $data = pack('n/a* n/a* n/a*', $pmail, $account, $dn);
+                   $self->{dbstat}->{users}->{dbh}->put($cuid, $data);
+               }
            }
 
            foreach my $mail (@$addresses) {
@@ -235,14 +239,16 @@ sub queryusers {
 
        # Get cookie from paged control
        my ($resp) = $mesg->control(LDAP_CONTROL_PAGED) or last;
-       $cookie = $resp->cookie or last;
+       $cookie = $resp->cookie;
+
+       last if (!defined($cookie) || !length($cookie));
 
        # Set cookie in paged control
        $page->cookie($cookie);
     }
 
 
-    if ($cookie) {
+    if (defined($cookie) && length($cookie)) {
        # We had an abnormal exit, so let the server know we do not want any more
        $page->cookie($cookie);
        $page->size(0);
@@ -258,7 +264,13 @@ sub querygroups {
 
     return undef if !$self->{groupbasedn};
 
-    my $filter = "(|(objectclass=group)(objectclass=univentionGroup))";
+    my $filter = "(|";
+
+    for my $class (@{$self->{groupclass}}) {
+       $filter .= "(objectclass=$class)";
+    }
+
+    $filter .= ")";
 
     my $page = Net::LDAP::Control::Paged->new(size => 100);
 
@@ -346,7 +358,7 @@ sub ldap_connect_and_bind {
      my ($self) = @_;
 
      my $ldap = $self->ldap_connect() ||
-        die "Can't bind to ldap server '$self->{id}': $!\n";
+        die "Can't bind to ldap server '$self->{id}': $! $@\n";
 
      my $mesg;
 
@@ -550,10 +562,10 @@ sub loaddata {
     }
 }
 
-sub list_groups {
+sub get_groups {
     my ($self) = @_;
 
-    my $res = [];
+    my $res = {};
 
     my $dbh = $self->{dbstat}->{groups}->{dbh};
 
@@ -562,22 +574,19 @@ sub list_groups {
     my $key = 0 ;
     my $value = "" ;
     my $status = $dbh->seq($key, $value, R_FIRST());
-    my $keys;
 
     while ($status == 0) {
-       push @$res, {
-           dn => $key,
-       };
+       $res->{$value} = $key;
         $status = $dbh->seq($key, $value, R_NEXT());
     }
 
     return $res;
 }
 
-sub list_users {
+sub get_users {
     my ($self) = @_;
 
-    my $res = [];
+    my $res = {};
 
     my $dbh = $self->{dbstat}->{users}->{dbh};
 
@@ -590,7 +599,7 @@ sub list_users {
 
     while ($status == 0) {
        my ($pmail, $account, $dn) = unpack('n/a* n/a* n/a*', $value);
-       push @$res, {
+       $res->{$key} = {
            pmail => $pmail,
            account => $account,
            dn => $dn,
@@ -601,6 +610,68 @@ sub list_users {
     return $res;
 }
 
+sub get_gid_uid_map {
+    my ($self) = @_;
+
+    my $dbh = $self->{dbstat}->{memberof}->{dbh};
+
+    return [] if !$dbh;
+
+    my $key = 0 ;
+    my $value = "" ;
+
+    my $map = {};
+
+    if($dbh->seq($key, $value, R_FIRST()) == 0) {
+       do {
+           push @{$map->{$value}}, $key;
+       } while($dbh->seq($key, $value, R_NEXT()) == 0);
+    }
+
+    return $map;
+}
+
+sub list_groups {
+    my ($self) = @_;
+
+    my $res = [];
+
+    my $groups = $self->get_groups();
+
+    for my $gid (sort keys %$groups) {
+       push @$res, {
+           dn => $groups->{$gid},
+           gid => $gid,
+       };
+    }
+
+    return $res;
+}
+
+sub list_users {
+    my ($self, $gid) = @_;
+
+    my $res = [];
+
+    my $users = $self->get_users();
+
+    if (!defined($gid)) {
+       $res = [values %$users];
+    } else {
+       my $gid_uid_map = $self->get_gid_uid_map();
+       my $groups = $self->get_groups();
+       die "No such Group ID\n"
+           if !defined($groups->{$gid});
+       my $memberuids = $gid_uid_map->{$gid};
+       for my $uid (@$memberuids) {
+           next if !defined($users->{$uid});
+           push @$res, $users->{$uid};
+       }
+    }
+
+    return $res;
+}
+
 sub list_addresses {
     my ($self, $mail) = @_;