this adds the subs which actually query the LDAP for users/groups and returns the value in format which makes it easy to insert in our parsed user.cfg
when we find a user/groupname which cannot be in our config, we warn the verification error for groups, we append "-$realm" to the groupname, to lower the chance of accidental overwriting of existing groups (this will be documented in the api call since it technically does not prevent overwriting, just makes it more unlikely) Signed-off-by: Dominik Csapak <d.csa...@proxmox.com> --- PVE/Auth/LDAP.pm | 135 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) diff --git a/PVE/Auth/LDAP.pm b/PVE/Auth/LDAP.pm index 6047dfb..45e4299 100755 --- a/PVE/Auth/LDAP.pm +++ b/PVE/Auth/LDAP.pm @@ -189,6 +189,141 @@ sub connect_and_bind { return $ldap; } +# returns: +# { +# 'username@realm' => { +# 'attr1' => 'value1', +# 'attr2' => 'value2', +# ... +# }, +# ... +# } +# +# or in list context: +# ( +# { +# 'username@realm' => { +# 'attr1' => 'value1', +# 'attr2' => 'value2', +# ... +# }, +# ... +# }, +# { +# 'uid=username,dc=....' => 'username@realm', +# ... +# } +# ) +# the map of dn->username is needed for group membership sync +sub get_users { + my ($class, $config, $realm) = @_; + + my $ldap = $class->connect_and_bind($config, $realm); + + my $user_attr = $config->{user_attr} // 'uid'; + my $attrs = { + $user_attr => 'username', + enable => 'enable', + expire => 'expire', + firstname => 'firstname', + lastname => 'lastname', + email => 'email', + comment => 'comment', + keys => 'keys', + }; + + foreach my $attr (PVE::Tools::split_list($config->{sync_attributes})) { + my ($ours, $ldap) = ($attr =~ m/^\s*(\w+)=(.*)\s*$/); + $attrs->{$ldap} = $ours; + } + + my $filter = $config->{filter}; + my $basedn = $config->{base_dn}; + + $config->{user_classes} //= 'inetorgperson, posixaccount, person, user'; + my $classes = [PVE::Tools::split_list($config->{user_classes})]; + + my $users = PVE::LDAP::query_users($ldap, $filter, [keys %$attrs], $basedn, $classes); + + my $ret = {}; + my $dnmap = {}; + + foreach my $user (@$users) { + my $user_attrs = $user->{attributes}; + my $userid = $user_attrs->{$user_attr}->[0]; + my $username = "$userid\@$realm"; + + # we cannot sync usernames that do not meet our criteria + eval { PVE::Auth::Plugin::verify_username($username) }; + if (my $err = $@) { + warn "$err"; + next; + } + + $ret->{$username} = { + enable => 1, + expire => 0, + }; + + foreach my $attr (keys %$user_attrs) { + if (my $key = $attrs->{$attr}) { + $ret->{$username}->{$key} = $user_attrs->{$attr}->[0]; + } + } + + if (!wantarray) { + my $dn = $user->{dn}; + $dnmap->{$dn} = $username; + } + } + + return wantarray ? ($ret, $dnmap) : $ret; +} + +# needs a map for dn -> username, we get this from the get_users call +# otherwise we cannot determine the group membership +sub get_groups { + my ($class, $config, $realm, $dnmap) = @_; + + my $filter = $config->{group_filter}; + my $basedn = $config->{group_dn} // $config->{base_dn}; + my $attr = $config->{group_attr}; + $config->{group_classes} //= 'groupOfNames, group, univentionGroup, ipausergroup'; + my $classes = [PVE::Tools::split_list($config->{group_classes})]; + + my $ldap = $class->connect_and_bind($config, $realm); + + my $groups = PVE::LDAP::query_groups($ldap, $basedn, $classes, $filter, $attr); + + my $ret = {}; + + foreach my $group (@$groups) { + my $name = $group->{name}; + if (!$name && $group->{dn} =~ m/^[^=]+=([^,]+),/){ + $name = PVE::Tools::trim($1); + } + if ($name) { + $name .= "-$realm"; + + # we cannot sync groups that do not meet our criteria + eval { PVE::AccessControl::verify_groupname($name) }; + if (my $err = $@) { + warn "$err"; + next; + } + + $ret->{$name} = { users => {} }; + foreach my $member (@{$group->{members}}) { + if (my $user = $dnmap->{$member}) { + $ret->{$name}->{users}->{$user} = 1; + } + } + } + } + + return $ret; +} + sub authenticate_user { my ($class, $config, $realm, $username, $password) = @_; -- 2.20.1 _______________________________________________ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel