File Coverage

blib/lib/Samba/LDAP/Group.pm
Criterion Covered Total %
statement 24 202 11.8
branch 0 58 0.0
condition n/a
subroutine 8 23 34.7
pod 12 12 100.0
total 44 295 14.9


line stmt bran cond sub pod time code
1             package Samba::LDAP::Group;
2              
3             # Returned by Perl::MinimumVersion 0.11
4             require 5.006;
5              
6 5     5   61345 use warnings;
  5         14  
  5         261  
7 5     5   226 use strict;
  5         10  
  5         200  
8 5     5   1482 use Regexp::DefaultFlags;
  5         6965  
  5         48  
9 5     5   2019 use Readonly;
  5         4252  
  5         337  
10 5     5   32 use Carp qw( croak carp );
  5         11  
  5         334  
11 5     5   37 use base qw(Samba::LDAP::Base);
  5         21  
  5         1156  
12 5     5   517 use Samba::LDAP;
  5         14  
  5         84  
13              
14             #use Samba::LDAP::User;
15 5     5   2021 use List::MoreUtils qw( any );
  5         2421  
  5         2055  
16              
17             our $VERSION = '0.05';
18              
19             #
20             # Add Log::Log4perl to all our classes!!!!
21             #
22              
23             # Our usage messages
24             Readonly my $ADD_TO_GROUPS_USAGE =>
25             'Usage: add_to_groups( $username | HoA, Aref | HoA);';
26              
27             #========================================================================
28             # -- PUBLIC METHODS --
29             #========================================================================
30              
31             #------------------------------------------------------------------------
32             # is_group_member( $dn,$userid )
33             #
34             # Check that the user is a member of the group already
35             #------------------------------------------------------------------------
36              
37             sub is_group_member {
38 0     0 1   my $self = shift;
39 0           my $dn_group = shift;
40 0           my $username = shift;
41              
42 0           my $ldap = Samba::LDAP->new();
43 0           $ldap = $ldap->connect_ldap_slave();
44              
45 0           my $mesg = $ldap->search(
46             base => $dn_group,
47             scope => 'sub',
48             filter => "(|(memberUid=$username)(member=uid=$username,$self->{usersDN}))"
49             );
50 0 0         $mesg->code && die $mesg->error;
51              
52 0           return ( $mesg->count ne 0 );
53             }
54              
55             #------------------------------------------------------------------------
56             # add_to_group( $group, $username)
57             #
58             # Add $username to LDAP group $group
59             #------------------------------------------------------------------------
60              
61             sub add_to_group {
62 0     0 1   my $self = shift;
63 0           my $group = shift;
64 0           my $username = shift;
65              
66 0           my $members = q{};
67 0           my $dn_line = $self->_get_group_dn($group);
68              
69 0 0         if ( !defined( $self->_get_group_dn($group) ) ) {
70 0           $self->error("group $group does not exist\n");
71 0           die $self->error();
72             }
73              
74 0 0         if ( !defined($dn_line) ) {
75 0           $self->error("Can not find group DN\n");
76 0           die $self->error();
77             }
78              
79 0           ( my $dn = $dn_line ) =~ s{\A dn:}{};
80              
81             # Should have been checked earlier, but check again anyway
82 0           my $user = Samba::LDAP::User->new();
83 0           my $valid_user = $user->is_unix_user($username);
84              
85             # Die if they are not
86 0 0         if ( $valid_user == 1 ) {
87 0           $self->error("User $username, is not even a user on this system\n");
88 0           die $self->error();
89             }
90              
91             # Now check if the user is already present in the group
92 0           my $is_member = $self->is_group_member( $dn, $username );
93 0 0         if ( $is_member == 1 ) {
94 0           $self->error("User $username already member of the group $group\n");
95 0           die $self->error();
96             }
97             else {
98              
99             # bind to a directory with dn and password
100             # It does not matter if the user already exist, Net::LDAP will add the
101             # user if he does not exist, and ignore him if his already in the
102             # directory.
103 0           my $ldap = Samba::LDAP->new();
104 0           $ldap = $ldap->connect_ldap_master();
105 0           my $modify =
106             $ldap->modify( "$dn",
107             changes => [ add => [ memberUid => $username ] ] );
108 0 0         $modify->code && die "failed to modify entry: ", $modify->error;
109 0           return 0;
110             }
111              
112 0           return 1;
113             }
114              
115             #------------------------------------------------------------------------
116             # add_to_groups( $groups_ref | HoA, Aref | HoA, $username )
117             #
118             # Pass in a list of groups for the user to be added to.
119             #------------------------------------------------------------------------
120              
121             sub add_to_groups {
122 0     0 1   my $self = shift;
123 0           my $groups = shift;
124 0           my $username = shift;
125              
126             # Required arguments
127 0           my @required_args = ($groups);
128              
129             # Allow HoA for adding lots of users to groups next.
130             #my $groups_ref = {
131             # admin => [ 'staff', 'directors', 'contractors', ],
132             # ghenry => [ 'web_team', 'finance', 'cleaners', ],
133             # };
134              
135             croak $ADD_TO_GROUPS_USAGE
136 0 0   0     if any { !defined $_ } @required_args;
  0            
137              
138             # Dereference the hashref passed to us by add_user in
139             # Samba::LDAP::User to get the Array, or take a Aref ;-)
140              
141 0           my @groups;
142 0 0         if ( ref($groups) eq 'HASH' ) {
    0          
143 0           for my $key ( keys %{$groups} ) {
  0            
144              
145             # Reminder: $key is our $username
146 0           $self->add_to_group( $key, ${$groups}{$key} );
  0            
147             }
148 0           return;
149             }
150              
151             elsif ( ref($groups) eq 'ARRAY' ) {
152 0           @groups = @{$groups};
  0            
153             }
154             else {
155 0           $self->error("Need a normal Array_Ref, $ADD_TO_GROUPS_USAGE");
156 0           croak $self->error();
157             }
158              
159 0           for my $group (@groups) {
160 0           $self->add_to_group( $group, $username );
161             }
162 0           return 1;
163             }
164              
165             #------------------------------------------------------------------------
166             # add_group()
167             #
168             # Description here
169             #------------------------------------------------------------------------
170              
171             sub add_group {
172 0     0 1   my $self = shift;
173             }
174              
175             #------------------------------------------------------------------------
176             # show_group( $group )
177             #
178             # Lists the entries for that group
179             #------------------------------------------------------------------------
180              
181             sub show_group {
182 0     0 1   my $self = shift;
183 0           my $group = shift;
184              
185 0 0         croak "No group specified!" if !$group;
186              
187 0           return $self->_read_group($group);
188             }
189              
190             #------------------------------------------------------------------------
191             # list_groups()
192             #
193             # Lists the entries for that group
194             #------------------------------------------------------------------------
195              
196             sub list_groups {
197 0     0 1   my $self = shift;
198             }
199              
200             #------------------------------------------------------------------------
201             # delete_group( $group_name )
202             #
203             # Deletes group name from LDAP tree
204             #------------------------------------------------------------------------
205              
206             sub delete_group {
207 0     0 1   my $self = shift;
208 0           my $group = shift;
209              
210 0           my $ldap = Samba::LDAP->new();
211 0           $ldap = $ldap->connect_ldap_slave();
212              
213 0           my $dn_line = $self->_get_group_dn($group);
214 0           ( my $dn = $dn_line ) =~ s{\A dn: [ ] }{};
215              
216 0 0         if ( !defined($dn_line) ) {
217 0           $self->error("$group doesn't exist\n");
218 0           return $self->error();
219             }
220              
221 0           my $modify = $ldap->delete($dn);
222 0 0         $modify->code && croak "Failed to delete group : ", $modify->error;
223              
224             # take down session
225 0           $ldap->unbind;
226              
227 0           return "$group group deleted\n.";
228             }
229              
230             #------------------------------------------------------------------------
231             # read_group_entry( $group )
232             #
233             # Return all posixGroup details
234             #------------------------------------------------------------------------
235              
236             sub read_group_entry {
237 0     0 1   my $self = shift;
238 0           my $group = shift;
239 0           my $entry;
240              
241 0           my $ldap = Samba::LDAP->new();
242 0           $ldap = $ldap->connect_ldap_slave();
243              
244 0           my $mesg = $ldap->search(
245             base => $self->{groupsdn},
246             scope => $self->{scope},
247             filter => "(&(objectclass=posixGroup)(cn=$group))"
248             );
249              
250 0 0         $mesg->code && die $mesg->error;
251 0           my $nb = $mesg->count;
252              
253 0 0         if ( $nb > 1 ) {
254 0           $self->error("Error: $nb groups exist \"cn=$group\"\n");
255              
256 0           foreach $entry ( $mesg->all_entries ) {
257 0           my $dn = $entry->dn;
258 0           return $dn;
259             }
260              
261 0           return $self->error();
262             }
263             else {
264 0           $entry = $mesg->shift_entry();
265             }
266 0           return $entry;
267             }
268              
269             #------------------------------------------------------------------------
270             # read_group_entry_gid( $group )
271             #
272             # Read the group number in the LDAP Directory
273             #------------------------------------------------------------------------
274              
275             sub read_group_entry_gid {
276 0     0 1   my $self = shift;
277 0           my $group = shift;
278              
279 0           my $ldap = Samba::LDAP->new();
280 0           $ldap = $ldap->connect_ldap_master();
281              
282 0           my $mesg = $ldap->search( # perform a search
283             base => $self->{groupsdn},
284             scope => $self->{scope},
285             filter => "(&(objectclass=posixGroup)(gidNumber=$group))"
286             );
287              
288 0 0         $mesg->code && die $mesg->error;
289 0           my $entry = $mesg->shift_entry();
290 0           return $entry;
291             }
292              
293             #------------------------------------------------------------------------
294             # find_groups( $username )
295             #
296             # Find the groups that $username belongs to
297             #------------------------------------------------------------------------
298              
299             sub find_groups {
300 0     0 1   my $self = shift;
301 0           my $user = shift;
302 0           my @groups = ();
303              
304 0           my $ldap = Samba::LDAP->new();
305 0           $ldap = $ldap->connect_ldap_master();
306              
307             # Everything apart from Open-xchange uses memberUid, OX uses
308             # member, so we do 2 searches
309 0           my $mesg = $ldap->search(
310             base => $self->{groupsdn},
311             scope => $self->{scope},
312             filter => "(&(objectclass=posixGroup)(memberUid=$user))"
313             );
314 0 0         $mesg->code && die $mesg->error;
315              
316 0           my $entry;
317 0           while ( $entry = $mesg->shift_entry() ) {
318 0           push( @groups, scalar( $entry->get_value('cn') ) );
319             }
320              
321             # OX Search
322 0           my $userdn = "uid=$user,$self->{usersdn}";
323 0           my $mesg2 = $ldap->search(
324             base => $self->{suffix},
325             scope => 'sub',
326             filter => "(&(objectclass=groupOfNames)(member=$userdn))"
327             );
328 0 0         $mesg2->code && die $mesg2->error;
329              
330 0           my $entry2;
331 0           while ( $entry2 = $mesg2->shift_entry() ) {
332 0           push( @groups, scalar( $entry2->get_value('cn') ) );
333             }
334              
335 0           return (@groups);
336             }
337              
338             #------------------------------------------------------------------------
339             # parse_group( $userGidNumber )
340             #
341             # Check the group is either a name or number
342             #------------------------------------------------------------------------
343              
344             sub parse_group {
345 0     0 1   my $self = shift;
346 0           my $userGidNumber = shift;
347              
348 0 0         if ( $userGidNumber =~ /[^\d]/ ) {
    0          
349 0           my $gname = $userGidNumber;
350 0           my $gidnum = getgrnam($gname);
351 0 0         if ( $gidnum !~ /\d+/ ) {
352 0           return -1;
353             }
354             else {
355 0           $userGidNumber = $gidnum;
356             }
357             }
358             elsif ( !defined( getgrgid($userGidNumber) ) ) {
359 0           return -2;
360             }
361 0           return $userGidNumber;
362             }
363              
364             #------------------------------------------------------------------------
365             # remove_from_group( $group, $username )
366             #
367             # Remove the user from $group
368             #------------------------------------------------------------------------
369              
370             sub remove_from_group {
371 0     0 1   my $self = shift;
372 0           my $group = shift;
373 0           my $user = shift;
374              
375 0           my $members = q{};
376              
377 0           my $grp_line = $self->_get_group_dn($group);
378 0 0         if ( !defined($grp_line) ) {
379 0           return 0;
380             }
381              
382 0           ( my $dn = $grp_line ) =~ s{\A dn: [ ] }{};
383              
384             # we test if the user exist in the group
385 0           my $is_member = $self->is_group_member( $dn, $user );
386              
387 0 0         if ( $is_member == 1 ) {
388              
389             # delete only the user from the group
390 0           my $ldap = Samba::LDAP->new();
391 0           $ldap = $ldap->connect_ldap_master();
392 0           my $modify = $ldap->modify(
393             "$dn",
394             changes => [
395             delete => [
396             memberUid => ["$user"],
397             member => ["uid=$user,$self->{usersdn}"],
398             ],
399             ]
400             );
401 0 0         $modify->code && die "failed to delete entry: ", $modify->error;
402             }
403 0           return 1;
404             }
405              
406             #========================================================================
407             # -- PRIVATE METHODS --
408             #========================================================================
409              
410             #------------------------------------------------------------------------
411             # _get_group_dn( $group )
412             #
413             # Searches for a groups distinguised name
414             #------------------------------------------------------------------------
415              
416             sub _get_group_dn {
417 0     0     my $self = shift;
418 0           my $group = shift;
419              
420 0           my $ldap = Samba::LDAP->new();
421 0           $ldap = $ldap->connect_ldap_master();
422              
423 0 0         if ( $group =~ /\A \d+ \z/ ) {
424 0           $self->{filter} =
425             "(&(objectclass=posixGroup)(|(cn=$group)(gidNumber=$group)))";
426             }
427             else {
428 0           $self->{filter} = "(&(objectclass=posixGroup)(cn=$group))";
429             }
430              
431 0           my $mesg = $ldap->search(
432             base => $self->{groupsdn},
433             scope => $self->{scope},
434             filter => $self->{filter},
435             );
436 0 0         $mesg->code && croak $mesg->error;
437              
438 0           for my $entry ( $mesg->all_entries ) {
439 0           $self->{dn} = $entry->dn;
440             }
441              
442             # For OX AddressAdmins search
443 0           my $mesg2 = $ldap->search(
444             base => $self->{suffix},
445             scope => $self->{scope},
446             filter => "(&(objectclass=groupOfNames)(cn=$group))"
447             );
448 0 0         $mesg2->code && die $mesg2->error;
449              
450 0           for my $entry ( $mesg2->all_entries ) {
451 0           $self->{dn} = $entry->dn;
452             }
453              
454 0 0         if ( !$self->{dn} ) {
455 0           croak "Can not find $group Group";
456             }
457              
458 0           my $dn = $self->{dn};
459 0           chomp($dn);
460              
461 0           $dn = "dn: " . $dn;
462              
463 0           return $dn;
464             }
465              
466             #------------------------------------------------------------------------
467             # _read_group( $group )
468             #
469             # Search for members of a group
470             #------------------------------------------------------------------------
471              
472             sub _read_group {
473 0     0     my $self = shift;
474 0           my $group = shift;
475              
476 0           my $ldap_slave = Samba::LDAP->new();
477 0           $ldap_slave = $ldap_slave->connect_ldap_slave();
478              
479 0           my $mesg = $ldap_slave->search(
480             base => $self->{groupsdn},
481             scope => $self->{scope},
482             filter => "(&(objectclass=posixGroup)(cn=$group))"
483             );
484 0 0         $mesg->code && croak $mesg->error;
485              
486 0           my $lines = '';
487 0           for my $entry ( $mesg->all_entries ) {
488 0           $lines .= "dn: " . $entry->dn . "\n";
489 0           for my $attr ( $entry->attributes ) {
490             {
491 0           $lines .=
  0            
492             $attr . ": " . join( ',', $entry->get_value($attr) ) . "\n";
493             }
494             }
495             }
496              
497             # take down session
498 0           $ldap_slave->unbind;
499              
500 0           chomp $lines;
501 0 0         if ( $lines eq '' ) {
502 0           return undef;
503             }
504              
505 0           return $lines;
506             }
507              
508             1; # Magic true value required at end of module
509              
510             __END__