]>
git.proxmox.com Git - pve-common.git/blob - src/PVE/LDAP.pm
8 use Net
::LDAP
::Control
::Paged
;
9 use Net
::LDAP
::Constant
qw(LDAP_CONTROL_PAGED);
12 my ($servers, $scheme, $port, $opts) = @_;
16 if ($scheme eq 'ldap+starttls') {
28 for my $host (@$servers) {
29 if (Net
::IP
::ip_is_ipv6
($host)) {
30 push @$hosts, "[$host]";
36 for my $opt (qw(clientcert clientkey capath cafile sslversion verify)) {
37 $ldap_opts{$opt} = $opts->{$opt} if $opts->{$opt};
40 my $ldap = Net
::LDAP-
>new($hosts, %ldap_opts) || die "$@\n";
43 my $res = $ldap->start_tls(%$opts);
44 die $res->error . "\n" if $res->code;
51 my ($ldap, $dn, $pw) = @_;
54 if (defined($dn) && defined($pw)) {
55 $res = $ldap->bind($dn, password
=> $pw);
56 } else { # anonymous bind
60 my $code = $res->code;
61 my $err = $res->error;
63 die "ldap bind failed: $err\n" if $code;
67 my ($ldap, $name, $attr, $base_dn) = @_;
70 my $result = $ldap->search(
71 base
=> $base_dn // "",
73 filter
=> "$attr=$name",
76 die $result->error . "\n" if $result->code;
77 return undef if !$result->entries;
78 my @entries = $result->entries;
79 return $entries[0]->dn;
83 my ($ldap, $dn, $pw, $noerr) = @_;
86 return undef if $noerr;
87 die "user dn is empty\n";
90 my $res = $ldap->bind($dn, password
=> $pw);
92 my $code = $res->code;
93 my $err = $res->error;
96 return undef if $noerr;
104 my ($ldap, $filter, $attributes, $base_dn, $classes) = @_;
106 # build filter from given filter and attribute list
108 foreach my $att (@$attributes) {
115 for my $class (@$classes) {
116 $tmp .= "(objectclass=$class)";
122 $filter = "($filter)" if $filter !~ m/^\(.*\)$/;
123 $filter = "(&${filter}${tmp})"
128 my $page = Net
::LDAP
::Control
::Paged-
>new(size
=> 900);
131 base
=> $base_dn // "",
134 control
=> [ $page ],
135 attrs
=> [ @$attributes, 'memberOf'],
144 my $mesg = $ldap->search(@args);
148 $err = "ldap user search error: " . $mesg->error;
152 #foreach my $entry ($mesg->entries) { $entry->dump; }
153 foreach my $entry ($mesg->entries) {
157 groups
=> [$entry->get_value('memberOf')],
160 foreach my $attr (@$attributes) {
161 my $vals = [$entry->get_value($attr)];
162 if (scalar(@$vals)) {
163 $user->{attributes
}->{$attr} = $vals;
170 # Get cookie from paged control
171 my ($resp) = $mesg->control(LDAP_CONTROL_PAGED
) or last;
172 $cookie = $resp->cookie;
174 last if (!defined($cookie) || !length($cookie));
176 # Set cookie in paged control
177 $page->cookie($cookie);
180 if (defined($cookie) && length($cookie)) {
181 # We had an abnormal exit, so let the server know we do not want any more
182 $page->cookie($cookie);
184 $ldap->search(@args);
185 $err = "LDAP user query unsuccessful" if !$err;
188 die "$err\n" if $err;
194 my ($ldap, $base_dn, $classes, $filter, $group_name_attr) = @_;
197 for my $class (@$classes) {
198 $tmp .= "(objectclass=$class)";
203 $filter = "($filter)" if $filter !~ m/^\(.*\)$/;
204 $filter = "(&${filter}${tmp})"
209 my $page = Net
::LDAP
::Control
::Paged-
>new(size
=> 100);
211 my $attrs = [ 'member', 'uniqueMember' ];
212 push @$attrs, $group_name_attr if $group_name_attr;
217 control
=> [ $page ],
227 my $mesg = $ldap->search(@args);
231 $err = "ldap group search error: " . $mesg->error;
235 foreach my $entry ( $mesg->entries ) {
240 my $members = [$entry->get_value('member')];
241 if (!scalar(@$members)) {
242 $members = [$entry->get_value('uniqueMember')];
244 $group->{members
} = $members;
245 if ($group_name_attr && (my $name = $entry->get_value($group_name_attr))) {
246 $group->{name
} = $name;
248 push @$groups, $group;
251 # Get cookie from paged control
252 my ($resp) = $mesg->control(LDAP_CONTROL_PAGED
) or last;
253 $cookie = $resp->cookie;
255 last if (!defined($cookie) || !length($cookie));
257 # Set cookie in paged control
258 $page->cookie($cookie);
262 # We had an abnormal exit, so let the server know we do not want any more
263 $page->cookie($cookie);
265 $ldap->search(@args);
266 $err = "LDAP group query unsuccessful" if !$err;
269 die "$err\n" if $err;