source: npl/fileserver/smb-ldap-tool/modified/smbldap_tools.pm @ 3187b26

perl-5.22
Last change on this file since 3187b26 was 3187b26, checked in by Edwin Eefting <edwin@datux.nl>, 7 years ago

flush nscd cache when modifying users

  • Property mode set to 100755
File size: 28.6 KB
RevLine 
[c5c522c]1#!/usr/bin/perl -w
2use strict;
3package smbldap_tools;
4use Net::LDAP;
5use Crypt::SmbHash;
6use Unicode::MapUTF8 qw(to_utf8 from_utf8);
7
8
9# $Id: smbldap_tools.pm 4204 2008-10-17 13:17:15Z edwin $
10#
11#  This code was developped by IDEALX (http://IDEALX.org/) and
12#  contributors (their names can be found in the CONTRIBUTORS file).
13#
14#                 Copyright (C) 2001-2002 IDEALX
15#
16#  This program is free software; you can redistribute it and/or
17#  modify it under the terms of the GNU General Public License
18#  as published by the Free Software Foundation; either version 2
19#  of the License, or (at your option) any later version.
20#
21#  This program is distributed in the hope that it will be useful,
22#  but WITHOUT ANY WARRANTY; without even the implied warranty of
23#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24#  GNU General Public License for more details.
25#
26#  You should have received a copy of the GNU General Public License
27#  along with this program; if not, write to the Free Software
28#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
29#  USA.
30
31
32# ugly funcs using global variables and spawning openldap clients
33
34my $smbldap_conf;
35if (-e "/etc/smbldap-tools/smbldap.conf") {
36        $smbldap_conf="/etc/smbldap-tools/smbldap.conf";
37} else {
38        $smbldap_conf="/etc/opt/IDEALX/smbldap-tools/smbldap.conf";
39}
40
41my $smbldap_bind_conf;
42if (-e "/etc/smbldap-tools/smbldap_bind.conf") {
43        $smbldap_bind_conf="/etc/smbldap-tools/smbldap_bind.conf";
44} else {
45        $smbldap_bind_conf="/etc/opt/IDEALX/smbldap-tools/smbldap_bind.conf";
46}
47my $samba_conf;
48if (-e "/etc/samba/smb.conf") {
49        $samba_conf="/etc/samba/smb.conf";
50} else {
51        $samba_conf="/usr/local/samba/lib/smb.conf";
52}
53
54use vars       qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
55use Exporter;
56$VERSION = 1.00;
57
58@ISA = qw(Exporter);
59use vars qw(%config $ldap);
60
61@EXPORT = qw(
62             get_user_dn
63             get_group_dn
64             is_group_member
65             is_samba_user
66             is_unix_user
67             is_nonldap_unix_user
68             is_user_valid
69             does_sid_exist
70             get_dn_from_line
71             add_posix_machine
72             add_samba_machine
73             add_samba_machine_smbpasswd
74             group_add_user
75             add_grouplist_user
76             disable_user
77             delete_user
78             group_add
79             group_del
80             get_homedir
81             read_user
82             read_user_entry
83             read_group
84             read_group_entry
85             read_group_entry_gid
86             find_groups_of
87             parse_group
88             group_remove_member
89             group_get_members
90             do_ldapadd
91             do_ldapmodify
92             get_user_dn2
93             connect_ldap_master
94             group_type_by_name
95             subst_configvar
96             read_config
97             read_parameter
98             subst_user
99             split_arg_comma
100             list_union
101             list_minus
102             get_next_id
103             print_banner
104             getDomainName
105             getLocalSID
106             utf8Encode
107             utf8Decode
108             %config
109            );
110
111sub print_banner
112  {
113       print STDERR "(c) Jerome Tournier - IDEALX 2004 (http://www.idealx.com)- Licensed under the GPL\n"
114         unless $config{no_banner};
115  }
116
117sub read_parameter
118  {
119        my $line=shift;
120        ## check for a param = value
121        if ($_=~/=/) {
122          my ($param,$val);
123          if ($_=~/\s*.*?\s*=\s*".*"/) {
124                ($param,$val) = /\s*(.*?)\s*=\s*"(.*)"/;
125          } elsif ($_=~/\s*.*?\s*=\s*'.*'/) {
126                ($param,$val) = /\s*(.*?)\s*=\s*'(.*)'/;
127          } else {
128                ($param,$val) = /\s*(.*?)\s*=\s*(.*)/;
129          }
130          return ($param,$val);
131        }
132  }
133
134sub subst_configvar
135  {
136        my $value = shift;
137        my $vars = shift;
138
139        $value =~ s/\$\{([^}]+)\}/$vars->{$1} ? $vars->{$1} : $1/eg;
140        return $value;
141  }
142
143sub read_conf
144  {
145        my %conf;
146        open (CONFIGFILE, "$smbldap_conf") || die "Unable to open $smbldap_conf for reading !\n";
147        while (<CONFIGFILE>) {
148          chomp($_);
149          ## throw away comments
150          next if ( /^\s*#/ || /^\s*$/ || /^\s*\;/);
151          ## check for a param = value
152          my ($parameter,$value)=read_parameter($_);
153          $value = &subst_configvar($value, \%conf);
154          $conf{$parameter}=$value;
155        }
156        close (CONFIGFILE);
157
158        if ($< == 0) {
159          open (CONFIGFILE, "$smbldap_bind_conf") || die "Unable to open $smbldap_bind_conf for reading !\n";
160          while (<CONFIGFILE>) {
161                chomp($_);
162                ## throw away comments
163                next if ( /^\s*#/ || /^\s*$/ || /^\s*\;/);
164                ## check for a param = value
165                my ($parameter,$value)=read_parameter($_);
166                $value = &subst_configvar($value, \%conf);
167                $conf{$parameter}=$value;
168          }
169          close (CONFIGFILE);
170        } else {
171          $conf{slaveDN}=$conf{slavePw}=$conf{masterDN}=$conf{masterPw}="";
172        }
173       # automatically find SID
174       if (not $conf{SID}) {
175         $conf{SID} = getLocalSID() ||
176           die "Unable to determine domain SID: please edit your smbldap.conf,
177  or start your samba server for a few minutes to allow for SID generation to proceed\n";
178       }
179        return(%conf);
180  }
181
182sub read_smbconf
183  {
184    my %conf;
185    my $smbconf="$samba_conf";
186    open (CONFIGFILE, "$smbconf") || die "Unable to open $smbconf for reading !\n";
187    my $global=0;
188    my $prevline="";
189    while (<CONFIGFILE>) {
190     chomp;
191     if (/^(.*)\\$/) {
192        $prevline.=$1;
193        next;
194     }
195     $_=$prevline.$_;
196     $prevline="";
197      if (/^\[global\]/) {
198        $global=1;
199      }
200      if ($global == 1) {
201        if (/^\[/ and !/\[global\]/) {
202          $global=0;
203        } else {
204          ## throw away comments
205          #next if ( ! /workgroup/i );
206          next if ( /^\s*#/ || /^\s*$/ || /^\s*\;/ || /\[/);
207          ## check for a param = value
208          my ($parameter,$value)=read_parameter($_);
209          $value = &subst_configvar($value, \%conf);
210          $conf{$parameter}=$value;
211        }
212      }
213    }
214    close (CONFIGFILE);
215    return(%conf);
216  }
217my %smbconf;
218#=read_smbconf();
219
220sub getLocalSID {
221  my $string = `LANG= PATH=/opt/IDEALX/bin:/usr/local/bin:/usr/bin:/bin net getlocalsid 2>/dev/null`;
222  my ($domain,$sid)=($string =~ m/^SID for domain (\S+) is: (\S+)$/ );
223
224  return $sid;
225}
226
227# let's read the configurations file...
228%config=read_conf();
229
230sub get_parameter {
231  # this function return the value for a parameter. The name of the parameter can be either this
232  # defined in smb.conf or smbldap.conf
233  my $parameter_smb=shift;
234  my $parameter_smbldap=shift;
235  if (defined $config{$parameter_smbldap} and $config{$parameter_smbldap} ne "") {
236        return $config{$parameter_smbldap};
237  } elsif (defined $smbconf{$parameter_smb} and $smbconf{$parameter_smb} ne "") {
238        return $smbconf{$parameter_smb};
239  } else {
240        #print "could not find parameter's value (parameter given: $parameter_smbldap or $parameter_smb) !!\n";
241        undef $smbconf{$parameter_smb};
242  }
[3187b26]243
[c5c522c]244}
245
246$config{sambaDomain}=get_parameter("workgroup","sambaDomain");
247$config{suffix}=get_parameter("ldap suffix","suffix");
248$config{usersdn}=get_parameter("ldap user suffix","usersdn");
249if ($config{usersdn} !~ m/,/ ) {$config{usersdn}=$config{usersdn}.",".$config{suffix};}
250$config{groupsdn}=get_parameter("ldap group suffix","groupsdn");
251if ($config{groupsdn} !~ m/,/ ) {$config{groupsdn}=$config{groupsdn}.",".$config{suffix};}
252$config{computersdn}=get_parameter("ldap machine suffix","computersdn");
253if ($config{computersdn} !~ m/,/ ) {$config{computersdn}=$config{computersdn}.",".$config{suffix};}
254$config{idmapdn}=get_parameter("ldap idmap suffix","idmapdn");
255if (defined $config{idmapdn}) {
256        if ($config{idmapdn} !~ m/,/ ) {$config{idmapdn}=$config{idmapdn}.",".$config{suffix};}
257}
258
259# next uidNumber and gidNumber available are stored in sambaDomainName object
260if (!defined $config{sambaUnixIdPooldn}) {
261        $config{sambaUnixIdPooldn}="sambaDomainName=$config{sambaDomain},$config{suffix}";
262}
263if (!defined $config{masterLDAP}) {
264        $config{masterLDAP}="127.0.0.1";
265}
266if (!defined $config{masterPort}) {
267        $config{masterPort}="389";
268}
269if (!defined $config{slaveLDAP}) {
270        $config{slaveLDAP}="127.0.0.1";
271}
272if (!defined $config{slavePort}) {
273        $config{slavePort}="389";
274}
275if (!defined $config{ldapTLS}) {
276        $config{ldapTLS}="0";
277}
278
279sub connect_ldap_master
280  {
281        # bind to a directory with dn and password
282        my $ldap_master = Net::LDAP->new(
283                                                                         "$config{masterLDAP}",
284                                                                         port => "$config{masterPort}",
285                                                                         version => 3,
286                                                                         timeout => 60,
287                                                                         # debug => 0xffff,
288                                                                        );
[3187b26]289
[c5c522c]290        if ($ldap_master)
291        {
292            if ($config{ldapTLS} == 1) {
293                  $ldap_master->start_tls(
294                                                          verify => "$config{verify}",
295                                                          clientcert => "$config{clientcert}",
296                                                          clientkey => "$config{clientkey}",
297                                                          cafile => "$config{cafile}"
298                                                         );
299            }
300                $ldap_master->bind ( "$config{masterDN}",
301                                                        password => "$config{masterPw}"
302                                                );
303                $ldap=$ldap_master;
304        }
305        else
306        {
307                print "Cant connect LDAP master...trying slave..\n";
308                my $ldap_slave = Net::LDAP->new(
309                                                                        "$config{slaveLDAP}",
310                                                                        port => "$config{slavePort}",
311                                                                        version => 3,
312                                                                        timeout => 60,
313                                                                        # debug => 0xffff,
314                                                                        );
315                if ($config{ldapTLS} == 1) {
316                        $ldap_slave->start_tls(
317                                                                verify => "$config{verify}",
318                                                                clientcert => "$config{clientcert}",
319                                                                clientkey => "$config{clientkey}",
320                                                                cafile => "$config{cafile}"
321                                                                );
322                }
323                $ldap_slave->bind ( "$config{slaveDN}",
324                                                        password => "$config{slavePw}"
325                                                        );
326                $ldap=$ldap_slave;
327        }
328        return ($ldap);
329}
330
331sub get_user_dn
332  {
333    my $user = shift;
334    my $dn='';
335    my  $mesg = $ldap->search (    base   => $config{suffix},
336                                                                                 scope => $config{scope},
337                                                                                 filter => "(&(objectclass=posixAccount)(uid=$user))"
338                                                                        );
339    $mesg->code && die $mesg->error;
340    foreach my $entry ($mesg->all_entries) {
341          $dn= $entry->dn;
342        }
343    chomp($dn);
344    if ($dn eq '') {
345          return undef;
346    }
347    $dn="dn: ".$dn;
348    return $dn;
349  }
350
351
352sub get_user_dn2
353  {
354    my $user = shift;
355    my $dn='';
356    my  $mesg = $ldap->search (    base   => $config{suffix},
357                                                                                 scope => $config{scope},
358                                                                                 filter => "(&(objectclass=posixAccount)(uid=$user))"
359                                                                        );
360    $mesg->code && warn "failed to perform search; ", $mesg->error;
361
362    foreach my $entry ($mesg->all_entries) {
363          $dn= $entry->dn;
364    }
365    chomp($dn);
366    if ($dn eq '') {
367          return (1,undef);
368    }
369    $dn="dn: ".$dn;
370    return (1,$dn);
371  }
372
373
374sub get_group_dn
375  {
376        my $group = shift;
377        my $dn='';
378        my $filter;
379        if ($group =~ /^\d+$/) {
380          $filter="(&(objectclass=posixGroup)(|(cn=$group)(gidNumber=$group)))";
381        } else {
382          $filter="(&(objectclass=posixGroup)(cn=$group))";
383        }
384        my  $mesg = $ldap->search (    base   => $config{groupsdn},
385                                                                                 scope => $config{scope},
386                                                                                 filter => $filter
387                                                                        );
388        $mesg->code && die $mesg->error;
389        foreach my $entry ($mesg->all_entries) {
390          $dn= $entry->dn;
391        }
392        chomp($dn);
393        if ($dn eq '') {
394          return undef;
395        }
396        $dn="dn: ".$dn;
397        return $dn;
398  }
399
400# return (success, dn)
401# bool = is_samba_user($username)
402sub is_samba_user
403  {
404        my $user = shift;
405        my $mesg = $ldap->search (    base   => $config{suffix},
406                                                                                scope => $config{scope},
407                                                                                filter => "(&(objectClass=sambaSamAccount)(uid=$user))"
408                                                                   );
409        $mesg->code && die $mesg->error;
410        return ($mesg->count ne 0);
411  }
412
413sub is_unix_user
414  {
415        my $user = shift;
416        my $mesg = $ldap->search (    base   => $config{suffix},
417                                                                                scope => $config{scope},
418                                                                                filter => "(&(objectClass=posixAccount)(uid=$user))"
419                                                                   );
420        $mesg->code && die $mesg->error;
421        return ($mesg->count ne 0);
422  }
423
424sub is_nonldap_unix_user
425  {
426        my $user = shift;
427        my $uid = getpwnam($user);
428
429        if ($uid) {
430                return 1;
431        } else {
432                return 0;
433        }
434}
435
436
437sub is_group_member
438  {
439        my $dn_group = shift;
440        my $user = shift;
441        my $mesg = $ldap->search (   base   => $dn_group,
442                                                                           scope => 'base',
443                                                                           filter => "(&(memberUid=$user))"
444                                                                   );
445        $mesg->code && die $mesg->error;
446        return ($mesg->count ne 0);
447  }
448
449# all entries = does_sid_exist($sid,$config{scope})
450sub does_sid_exist
451  {
452        my $sid = shift;
453        my $dn_group=shift;
454        my $mesg = $ldap->search (    base   => $dn_group,
455                                                                                scope => $config{scope},
456                                                                                filter => "(sambaSID=$sid)"
457                                                                                #filter => "(&(objectClass=sambaSAMAccount|objectClass=sambaGroupMapping)(sambaSID=$sid))"
458                                                                   );
459        $mesg->code && die $mesg->error;
460        return ($mesg);
461  }
462
463# try to bind with user dn and password to validate current password
464sub is_user_valid
465  {
466        my ($user, $dn, $pass) = @_;
467       my $userLdap = Net::LDAP->new(
468                                                                "$config{slaveLDAP}",
469                                                                port => "$config{slavePort}",
470                                                                version => 3,
471                                                                timeout => 60
472                                                                )
473         or warn "erreur LDAP: Can't contact slave ldap server ($@)\n=>trying to contact the master server\n";
474       if (!$userLdap) {
475         # connection to the slave failed: trying to contact the master ...
476         $userLdap = Net::LDAP->new(
477                                                                "$config{masterLDAP}",
478                                                                port => "$config{masterPort}",
479                                                                version => 3,
480                                                                timeout => 60
481                                                                )
482               or die "erreur LDAP: Can't contact master ldap server ($@)\n";
483       }
484       if ($userLdap) {
485         if ($config{ldapTLS} == 1) {
486               $userLdap->start_tls(
487                                                          verify => "$config{verify}",
488                                                          clientcert => "$config{clientcert}",
489                                                          clientkey => "$config{clientkey}",
490                                                          cafile => "$config{cafile}"
491                                                         );
492         }
493         my $mesg= $userLdap->bind (dn => $dn, password => $pass );
494         if ($mesg->code eq 0) {
495           $userLdap->unbind;
496           return 1;
497          } else {
498           if ($userLdap->bind()) {
499             $userLdap->unbind;
500             return 0;
501           } else {
502             print ("The LDAP directory is not available.\n Check the server, cables ...");
503             $userLdap->unbind;
504             return 0;
505           }
506           die "Problem : contact your administrator";
507          }
508        }
509  }
510
511
512# dn = get_dn_from_line ($dn_line)
513# helper to get "a=b,c=d" from "dn: a=b,c=d"
514sub get_dn_from_line
515  {
516        my $dn = shift;
517        $dn =~ s/^dn: //;
518        return $dn;
519  }
520
521
522# success = add_posix_machine($user, $uid, $gid)
523sub add_posix_machine
524  {
525        my ($user,$uid,$gid,$wait) = @_;
526        if (!defined $wait) {
527                $wait=0;
528        }
529        # bind to a directory with dn and password
530        my $add = $ldap->add ( "uid=$user,$config{computersdn}",
531                                                                  attr => [
532                                                                                   'objectclass' => ['top', 'person', 'organizationalPerson', 'inetOrgPerson', 'posixAccount'],
533                                                                                   'cn'   => "$user",
534                                                                                   'sn'   => "$user",
535                                                                                   'uid'   => "$user",
536                                                                                   'uidNumber'   => "$uid",
537                                                                                   'gidNumber'   => "$gid",
538                                                                                   'homeDirectory'   => '/dev/null',
539                                                                                   'loginShell'   => '/bin/false',
540                                                                                   'description'   => 'Computer',
541                                                                                  'gecos'   => 'Computer',
542                                                                                  ]
543                                                                );
[3187b26]544
[c5c522c]545        $add->code && warn "failed to add entry: ", $add->error ;
546        sleep($wait);
547        return 1;
548  }
549
550
551# success = add_samba_machine_smbpasswd($computername)
552sub add_samba_machine_smbpasswd
553  {
554    my $user = shift;
555    system "smbpasswd -a -m $user";
556    return 1;
557  }
558
559sub add_samba_machine
560  {
561        my ($user, $uid) = @_;
562        my $sambaSID = 2 * $uid + 1000;
563        my $name = $user;
564        $name =~ s/.$//s;
565
[3187b26]566        my ($lmpassword,$ntpassword) = ntlmgen $name;
[c5c522c]567        my $modify = $ldap->modify ( "uid=$user,$config{computersdn}",
568                                                                                changes => [
569                                                                                                        replace => [objectClass => ['inetOrgPerson', 'posixAccount', 'sambaSAMAccount']],
570                                                                                                        add => [sambaPwdLastSet => '0'],
571                                                                                                        add => [sambaLogonTime => '0'],
572                                                                                                        add => [sambaLogoffTime => '2147483647'],
573                                                                                                        add => [sambaKickoffTime => '2147483647'],
574                                                                                                        add => [sambaPwdCanChange => '0'],
575                                                                                                        add => [sambaPwdMustChange => '0'],
576                                                                                                        add => [sambaAcctFlags => '[W          ]'],
577                                                                                                        add => [sambaLMPassword => "$lmpassword"],
578                                                                                                        add => [sambaNTPassword => "$ntpassword"],
579                                                                                                        add => [sambaSID => "$config{SID}-$sambaSID"],
580                                                                                                        add => [sambaPrimaryGroupSID => "$config{SID}-0"]
581                                                                                                   ]
582                                                                          );
[3187b26]583
[c5c522c]584        $modify->code && die "failed to add entry: ", $modify->error ;
585
586        return 1;
587  }
588
589sub group_add_user
590  {
591        my ($group, $userid) = @_;
592        my $members='';
593        my $dn_line = get_group_dn($group);
594        if (!defined(get_group_dn($group))) {
595          print "$0: group \"$group\" doesn't exist\n";
[3187b26]596          exit (6);
[c5c522c]597        }
598        if (!defined($dn_line)) {
599          return 1;
600        }
601        my $dn = get_dn_from_line("$dn_line");
602        # on look if the user is already present in the group
603        my $is_member=is_group_member($dn,$userid);
604        if ($is_member == 1) {
605          print "User \"$userid\" already member of the group \"$group\".\n";
606        } else {
607          # bind to a directory with dn and password
608          # It does not matter if the user already exist, Net::LDAP will add the user
609          # if he does not exist, and ignore him if his already in the directory.
610          my $modify = $ldap->modify ( "$dn",
611                                                                                  changes => [
612                                                                                                          add => [memberUid => $userid]
613                                                                                                         ]
614                                                                                );
615          $modify->code && die "failed to modify entry: ", $modify->error ;
616        }
617  }
618
619sub ox_group_add
620{
621    my ($group, $userid) = @_;
622    my $members='';
623    my $dn_line = get_user_dn($userid);
624    if (!defined(get_user_dn($userid))) {
625    print "$0: user \"$userid\" doesn't exist\n";
626    exit (6);
627    }
628    if (!defined($dn_line)) {
629        return 1;
630    }
631    my $dn = get_dn_from_line("$dn_line");
632    my $modify = $ldap->modify ( $dn, add => [OXGroupID => $group]);
633    $modify->code && die "failed to modify entry: ", $modify->error ;
634}
635
636
637
638
639sub ox_group_del
640{
641    my ($userid) = shift;
642    my $dn_line = get_user_dn($userid);
643    if (!defined(get_user_dn($userid))) {
644    print "$0: user \"$userid\" doesn't exist\n";
645    exit (6);
646    }
647    if (!defined($dn_line)) {
648    return 1;
649    }
650    my $dn = get_dn_from_line("$dn_line");
651    # bind to a directory with dn and password
652    # It does not matter if the user already exist, Net::LDAP will add the user
653    # if he does not exist, and ignore him if his already in the directory.
654    my $modify = $ldap->modify ( $dn, delete  => ("OXGroupID"));
655    $modify->code
656
657}
658
659
660sub group_del
661  {
662        my $group_dn=shift;
663        # bind to a directory with dn and password
664        my $modify = $ldap->delete ($group_dn);
665        $modify->code && die "failed to delete group : ", $modify->error ;
666  }
667
[3187b26]668
[c5c522c]669sub add_grouplist_user
670{
671    my ($grouplist, $user) = @_;
672    ox_group_del("$user");
673    my @array = split(/,/, $grouplist);
674    foreach my $group (@array) {
675        group_add_user($group, $user);
676        ox_group_add($group, $user);
677    }
678}
679
680sub disable_user
681  {
682        my $user = shift;
683        my $dn_line;
684        my $dn = get_dn_from_line($dn_line);
[3187b26]685
[c5c522c]686        if (!defined($dn_line = get_user_dn($user))) {
687          print "$0: user $user doesn't exist\n";
688          exit (10);
689        }
690        my $modify = $ldap->modify ( "$dn",
691                                                                                changes => [
692                                                                                                        replace => [userPassword => '{crypt}!x']
693                                                                                                   ]
694                                                                          );
695        $modify->code && die "failed to modify entry: ", $modify->error ;
696
697        if (is_samba_user($user)) {
698          my $modify = $ldap->modify ( "$dn",
699                                                                                  changes => [
700                                                                                                          replace => [sambaAcctFlags => '[D       ]']
701                                                                                                         ]
702                                                                                );
703          $modify->code && die "failed to modify entry: ", $modify->error ;
704        }
705  }
706
707# delete_user($user)
708sub delete_user
709  {
710        my $user = shift;
711        my $dn_line;
712
713        if (!defined($dn_line = get_user_dn($user))) {
714          print "$0: user $user doesn't exist\n";
715          exit (10);
716        }
717
718        my $dn = get_dn_from_line($dn_line);
719        my $modify = $ldap->delete("ou=addr,".$dn);
720        $modify = $ldap->delete($dn);
721  }
722
723# $gid = group_add($groupname, $group_gid, $force_using_existing_gid)
724sub group_add
725  {
726        my ($gname, $gid, $force) = @_;
[3187b26]727        # my $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
728        # if ($nscd_status == 0) {
729        #   system "/etc/init.d/nscd stop > /dev/null 2>&1";
730        # }
[c5c522c]731        if (!defined($gid)) {
732          #while (defined(getgrgid($config{GID_START}))) {
733          #     $config{GID_START}++;
734          #}
735          #$gid = $config{GID_START};
736          $gid=get_next_id($config{groupsdn},"gidNumber");
737        } else {
738          if (!defined($force)) {
739                if (defined(getgrgid($gid))) {
740                  return undef;
741                }
742          }
743        }
[3187b26]744        # if ($nscd_status == 0) {
745          # system "/etc/init.d/nscd start > /dev/null 2>&1";
746          system "nscd -i passwd; nscd -i group";
747        # }
[c5c522c]748        my $modify = $ldap->add ( "cn=$gname,$config{groupsdn}",
749                                                                         attrs => [
750                                                                                           objectClass => [ 'top', 'posixGroup' ],
751                                                                                           cn => "$gname",
752                                                                                           gidNumber => "$gid"
753                                                                                          ]
754                                                                   );
[3187b26]755
[c5c522c]756        $modify->code && die "failed to add entry: ", $modify->error ;
757        return $gid;
758  }
759
760# $homedir = get_homedir ($user)
761sub get_homedir
762  {
763        my $user = shift;
764        my $homeDir='';
765        my $entry;
766        my  $mesg = $ldap->search (
767                                                                         base   =>$config{usersdn},
768                                                                         scope => $config{scope},
769                                                                         filter => "(&(objectclass=posixAccount)(uid=$user))"
770                                                                        );
771        $mesg->code && die $mesg->error;
772
773        my $nb=$mesg->count;
774        if ($nb > 1) {
775          print "Aborting: there are $nb existing user named $user\n";
776          foreach $entry ($mesg->all_entries) {
777                my $dn=$entry->dn;
778                print "  $dn\n";
779          }
780          exit (4);
781        } else {
782          $entry = $mesg->shift_entry();
783          $homeDir= $entry->get_value("homeDirectory");
784        }
785
786        chomp $homeDir;
787        if ($homeDir eq '') {
788          return undef;
789        }
790        return $homeDir;
791  }
792
793# search for an user
794sub read_user
795  {
796        my $user = shift;
797        my $lines ='';
798        my $mesg = $ldap->search ( # perform a search
799                                                                        base   => $config{suffix},
800                                                                        scope => $config{scope},
801                                                                        filter => "(&(objectclass=posixAccount)(uid=$user))"
802                                                                   );
803
804        $mesg->code && die $mesg->error;
805        foreach my $entry ($mesg->all_entries) {
806          $lines.= "dn: " . $entry->dn."\n";
807          foreach my $attr ($entry->attributes) {
808                {
809                  $lines.= $attr.": ".join(',', $entry->get_value($attr))."\n";
810                }
811          }
812        }
813        chomp $lines;
814        if ($lines eq '') {
815          return undef;
816        }
817        return $lines;
818  }
819
820# search for a user
821# return the attributes in an array
822sub read_user_entry
823  {
824        my $user = shift;
825        my  $mesg = $ldap->search ( # perform a search
826                                                                         base   => $config{suffix},
827                                                                         scope => $config{scope},
828                                                                         filter => "(&(objectclass=posixAccount)(uid=$user))"
829                                                                        );
830
831        $mesg->code && die $mesg->error;
832        my $entry = $mesg->entry();
833        return $entry;
834  }
835
836# search for a group
837sub read_group
838  {
839        my $user = shift;
840        my $lines ='';
841        my  $mesg = $ldap->search ( # perform a search
842                                                                         base   => $config{groupsdn},
843                                                                         scope => $config{scope},
844                                                                         filter => "(&(objectclass=posixGroup)(cn=$user))"
845                                                                        );
846
847        $mesg->code && die $mesg->error;
848        foreach my $entry ($mesg->all_entries) {
849          $lines.= "dn: " . $entry->dn."\n";
850          foreach my $attr ($entry->attributes) {
851                {
852                  $lines.= $attr.": ".join(',', $entry->get_value($attr))."\n";
853                }
854          }
855        }
856        chomp $lines;
857        if ($lines eq '') {
858          return undef;
859        }
860        return $lines;
861  }
862
863# find groups of a given user
864##### MODIFIE ########
865sub find_groups_of {
866  my $user = shift;
867  my @groups = ();
868  my $mesg = $ldap->search ( # perform a search
869                                  base   => $config{groupsdn},
870                                  scope => $config{scope},
871                                  filter => "(&(objectclass=posixGroup)(memberuid=$user))"
872                                 );
873  $mesg->code && die $mesg->error;
874
875  my $entry;
876  while ($entry = $mesg->shift_entry()) {
877    push(@groups, scalar($entry->get_value('cn')));
878  }
879  return (@groups);
880}
881
882sub read_group_entry {
883  my $group = shift;
884  my $entry;
885  my %res;
886  my  $mesg = $ldap->search ( # perform a search
887                                                                   base   => $config{groupsdn},
888                                                                   scope => $config{scope},
889                                                                   filter => "(&(objectclass=posixGroup)(cn=$group))"
890                                                                  );
891
892  $mesg->code && die $mesg->error;
893  my $nb=$mesg->count;
894  if ($nb > 1) {
895    print "Error: $nb groups exist \"cn=$group\"\n";
896    foreach $entry ($mesg->all_entries) {
897          my $dn=$entry->dn; print "  $dn\n";
898        }
899    exit 11;
900  } else {
901    $entry = $mesg->shift_entry();
902  }
903  return $entry;
904}
905
906sub read_group_entry_gid {
907  my $group = shift;
908  my %res;
909  my  $mesg = $ldap->search ( # perform a search
910                                                                   base   => $config{groupsdn},
911                                                                   scope => $config{scope},
912                                                                   filter => "(&(objectclass=posixGroup)(gidNumber=$group))"
913                                                                  );
914
915  $mesg->code && die $mesg->error;
916  my $entry = $mesg->shift_entry();
917  return $entry;
918}
919
920# return the gidnumber for a group given as name or gid
921# -1 : bad group name
922# -2 : bad gidnumber
923sub parse_group
924  {
925        my $userGidNumber = shift;
926        if ($userGidNumber =~ /[^\d]/ ) {
927          my $gname = $userGidNumber;
928          my $gidnum = getgrnam($gname);
929          if ($gidnum !~ /\d+/) {
930                return -1;
931          } else {
932                $userGidNumber = $gidnum;
933          }
934        } elsif (!defined(getgrgid($userGidNumber))) {
935          return -2;
936        }
937        return $userGidNumber;
938  }
939
940# remove $user from $group
941sub group_remove_member
942  {
943        my ($group, $user) = @_;
944        my $members='';
945        my $grp_line = get_group_dn($group);
946        if (!defined($grp_line)) {
947          return 0;
948        }
949        my $dn = get_dn_from_line($grp_line);
950        # we test if the user exist in the group
951        my $is_member=is_group_member($dn,$user);
952        if ($is_member == 1) {
953          # delete only the user from the group
954          my $modify = $ldap->modify ( "$dn",
955                                                                                  changes => [
956                                                                                                          delete => [memberUid => ["$user"]]
957                                                                                                         ]
958                                                                                );
959          $modify->code && die "failed to delete entry: ", $modify->error ;
960        }
961        return 1;
962  }
963
964sub group_get_members
965  {
966        my ($group) = @_;
967        my $members;
968        my @resultat;
969        my $grp_line = get_group_dn($group);
970        if (!defined($grp_line)) {
971          return 0;
972        }
973        my  $mesg = $ldap->search (
974                                                           base   => $config{groupsdn},
975                                                           scope => $config{scope},
976                                                           filter => "(&(objectclass=posixgroup)(cn=$group))"
977                                                          );
978        $mesg->code && die $mesg->error;
979        foreach my $entry ($mesg->all_entries) {
980          foreach my $attr ($entry->attributes) {
981                if ($attr=~/\bmemberUid\b/) {
982                  foreach my $ent ($entry->get_value($attr)) {
983                        push (@resultat,$ent);
984                  }
985                }
986          }
987        }
988        return @resultat;
989  }
990
991sub do_ldapmodify
992  {
993        my $ldif = shift;
994        my $FILE = "|$config{ldapmodify} -r >/dev/null";
995        open (FILE, $FILE) || die "$!\n";
996        print FILE <<EOF;
997$ldif
998EOF
999        ;
1000        close FILE;
1001        my $rc = $?;
1002        return $rc;
1003  }
1004
1005sub group_type_by_name {
1006  my $type_name = shift;
1007  my %groupmap = (
1008                                  'domain' => 2,
1009                                  'local' => 4,
1010                                  'builtin' => 5
1011                                 );
1012  return $groupmap{$type_name};
1013}
1014
1015sub subst_user
1016  {
1017        my ($str, $username) = @_;
1018        $str =~ s/%U/$username/ if ($str);
1019        return($str);
1020  }
1021
1022# all given mails are stored in a table (remove the comma separated)
1023sub split_arg_comma {
1024  my $arg = shift;
1025  my @args;
1026  if (defined($arg)) {
1027    if ($arg eq '-') {
1028      @args = ( );
1029    } else {
1030      @args = split(/\s*,\s*/, $arg);
1031    }
1032  }
1033  return (@args);
1034}
1035
1036sub list_union {
1037  my ($list1, $list2) = @_;
1038  my @res = @$list1;
1039  foreach my $e (@$list2) {
1040    if (! grep($_ eq $e, @$list1)) {
1041      push(@res, $e);
1042    }
1043  }
1044  return @res;
1045}
1046
1047sub list_minus {
1048  my ($list1, $list2) = @_;
1049  my @res = ();
1050  foreach my $e (@$list1) {
1051    if (! grep( $_ eq $e, @$list2 )) {
1052      push(@res, $e);
1053    }
1054  }
1055  return @res;
1056}
1057
1058sub get_next_id($$) {
1059  my $ldap_base_dn = shift;
1060  my $attribute = shift;
1061  my $tries = 0;
1062  my $found=0;
1063  my $next_uid_mesg;
1064  my $nextuid;
1065  if ($ldap_base_dn =~ m/$config{usersdn}/i) {
1066        # when adding a new user, we'll check if the uidNumber available is not
1067        # already used for a computer's account
1068        $ldap_base_dn=$config{suffix}
1069  }
1070  do {
1071        $next_uid_mesg = $ldap->search(
1072                                                                                  base => $config{sambaUnixIdPooldn},
1073                                                                                  filter => "(objectClass=sambaUnixIdPool)",
1074                                                                                  scope => "base"
1075                                                                                 );
1076        $next_uid_mesg->code && die "Error looking for next uid";
1077        if ($next_uid_mesg->count != 1) {
1078          die "Could not find base dn, to get next $attribute";
1079        }
1080        my $entry = $next_uid_mesg->entry(0);
[3187b26]1081
[c5c522c]1082        $nextuid = $entry->get_value($attribute);
1083        my $modify=$ldap->modify( "$config{sambaUnixIdPooldn}",
1084                                                                         changes => [
1085                                                                                                 replace => [ $attribute => $nextuid + 1 ]
1086                                                                                                ]
1087                                                                   );
1088        $modify->code && die "Error: ", $modify->error;
1089        # let's check if the id found is really free (in ou=Groups or ou=Users)...
1090        my $check_uid_mesg = $ldap->search(
1091                                                                                          base => $ldap_base_dn,
1092                                                                                          filter => "($attribute=$nextuid)",
1093                                                                                         );
1094        $check_uid_mesg->code && die "Cannot confirm $attribute $nextuid is free";
1095        if ($check_uid_mesg->count == 0) {
1096          $found=1;
1097          return $nextuid;
1098        }
1099        $tries++;
1100        print "Cannot confirm $attribute $nextuid is free: checking for the next one\n"
1101  } while ($found != 1);
1102  die "Could not allocate $attribute!";
1103}
1104
1105sub utf8Encode {
[3187b26]1106  my $arg = shift;
[c5c522c]1107
1108  return to_utf8(
1109                                 -string=> $arg,
1110                                 -charset => 'ISO-8859-1',
1111                                );
1112}
1113
1114sub utf8Decode {
1115  my $arg = shift;
1116
1117  return from_utf8(
1118                                   -string=> $arg,
1119                                   -charset => 'ISO-8859-1',
1120                                  );
[3187b26]1121}
[c5c522c]1122
11231;
Note: See TracBrowser for help on using the repository browser.