7 # This code was developped by IDEALX (http://IDEALX.org/) and
8 # contributors (their names can be found in the CONTRIBUTORS file).
10 # Copyright (C) 2001-2002 IDEALX
12 # This program is free software; you can redistribute it and/or
13 # modify it under the terms of the GNU General Public License
14 # as published by the Free Software Foundation; either version 2
15 # of the License, or (at your option) any later version.
17 # This program is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # GNU General Public License for more details.
22 # You should have received a copy of the GNU General Public License
23 # along with this program; if not, write to the Free Software
24 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
28 # ugly funcs using global variables and spawning openldap clients
30 use vars
qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
47 add_samba_machine_mkntpwd
72 sub connect_ldap_master
74 # bind to a directory with dn and password
75 my $ldap_master = Net
::LDAP
->new(
77 port
=> "$masterPort",
81 or die "erreur LDAP: Can't contact master ldap server ($@)";
83 $ldap_master->start_tls(
84 # verify => 'require',
85 # clientcert => 'mycert.pem',
86 # clientkey => 'mykey.pem',
87 # decryptkey => sub { 'secret'; },
88 # capath => '/usr/local/cacerts/'
91 $ldap_master->bind ( "$binddn",
92 password
=> "$masterPw"
97 sub connect_ldap_slave
99 # bind to a directory with dn and password
100 my $ldap_slave = Net
::LDAP
->new(
102 port
=> "$slavePort",
106 or die "erreur LDAP: Can't contact slave ldap server ($@)";
108 $ldap_slave->start_tls(
109 # verify => 'require',
110 # clientcert => 'mycert.pem',
111 # clientkey => 'mykey.pem',
112 # decryptkey => sub { 'secret'; },
113 # capath => '/usr/local/cacerts/'
116 $ldap_slave->bind ( "$binddn",
117 password
=> "$slavePw"
126 my $ldap_slave=connect_ldap_slave
();
127 my $mesg = $ldap_slave->search ( base
=> $suffix,
129 filter
=> "(&(objectclass=posixAccount)(uid=$user))"
131 $mesg->code && die $mesg->error;
132 foreach my $entry ($mesg->all_entries) {
149 my $ldap_slave=connect_ldap_slave
();
150 my $mesg = $ldap_slave->search ( base
=> $suffix,
152 filter
=> "(&(objectclass=posixAccount)(uid=$user))"
154 $mesg->code && warn "failed to perform search; ", $mesg->error;
156 foreach my $entry ($mesg->all_entries) {
173 my $ldap_slave=connect_ldap_slave
();
174 my $mesg = $ldap_slave->search ( base
=> $groupsdn,
176 filter
=> "(&(objectclass=posixGroup)(|(cn=$group)(gidNumber=$group)))"
178 $mesg->code && die $mesg->error;
179 foreach my $entry ($mesg->all_entries) {
191 # return (success, dn)
192 # bool = is_samba_user($username)
196 my $ldap_slave=connect_ldap_slave
();
197 my $mesg = $ldap_slave->search ( base
=> $suffix,
199 filter
=> "(&(objectClass=sambaSamAccount)(uid=$user))"
201 $mesg->code && die $mesg->error;
203 return ($mesg->count ne 0);
209 my $ldap_slave=connect_ldap_slave
();
210 my $mesg = $ldap_slave->search ( base
=> $suffix,
212 filter
=> "(&(objectClass=posixAccount)(uid=$user))"
214 $mesg->code && die $mesg->error;
216 return ($mesg->count ne 0);
221 my $dn_group = shift;
223 my $ldap_slave=connect_ldap_slave
();
224 my $mesg = $ldap_slave->search ( base
=> $dn_group,
226 filter
=> "(&(memberUid=$user))"
228 $mesg->code && die $mesg->error;
230 return ($mesg->count ne 0);
233 # all entries = does_sid_exist($sid,$scope)
238 my $ldap_slave=connect_ldap_slave
();
239 my $mesg = $ldap_slave->search ( base
=> $dn_group,
241 filter
=> "(sambaSID=$sid)"
242 #filter => "(&(objectClass=sambaSamAccount|objectClass=sambaGroupMapping)(sambaSID=$sid))"
244 $mesg->code && die $mesg->error;
249 # try to bind with user dn and password to validate current password
252 my ($user, $dn, $pass) = @_;
253 my $ldap = Net
::LDAP
->new($slaveLDAP) or die "erreur LDAP";
254 my $mesg= $ldap->bind (dn
=> $dn, password
=> $pass );
255 if ($mesg->code eq 0) {
263 print ("The LDAP directory is not available.\n Check the server, cables ...");
267 die "Problem : contact your administrator";
272 # dn = get_dn_from_line ($dn_line)
273 # helper to get "a=b,c=d" from "dn: a=b,c=d"
282 # success = add_posix_machine($user, $uid, $gid)
283 sub add_posix_machine
285 my ($user, $uid, $gid) = @_;
286 # bind to a directory with dn and password
287 my $ldap_master=connect_ldap_master
();
288 my $add = $ldap_master->add ( "uid=$user,$computersdn",
290 'objectclass' => ['top','inetOrgPerson', 'posixAccount'],
294 'uidNumber' => "$uid",
295 'gidNumber' => "$gid",
296 'homeDirectory' => '/dev/null',
297 'loginShell' => '/bin/false',
298 'description' => 'Computer',
302 $add->code && warn "failed to add entry: ", $add->error ;
303 # take down the session
304 $ldap_master->unbind;
309 # success = add_samba_machine($computername)
310 sub add_samba_machine
313 system "smbpasswd -a -m $user";
317 sub add_samba_machine_mkntpwd
319 my ($user, $uid) = @_;
320 my $sambaSID = 2 * $uid + 1000;
324 if ($mk_ntpasswd eq '') {
325 print "Either set \$with_smbpasswd = 1 or specify \$mk_ntpasswd\n";
329 my $ntpwd = `$mk_ntpasswd '$name'`;
330 chomp(my $lmpassword = substr($ntpwd, 0, index($ntpwd, ':')));
331 chomp(my $ntpassword = substr($ntpwd, index($ntpwd, ':')+1));
333 my $ldap_master=connect_ldap_master
();
334 my $modify = $ldap_master->modify ( "uid=$user,$computersdn",
336 replace
=> [objectClass
=> ['inetOrgPerson', 'posixAccount', 'sambaSamAccount']],
337 add
=> [sambaPwdLastSet
=> '0'],
338 add
=> [sambaLogonTime
=> '0'],
339 add
=> [sambaLogoffTime
=> '2147483647'],
340 add
=> [sambaKickoffTime
=> '2147483647'],
341 add
=> [sambaPwdCanChange
=> '0'],
342 add
=> [sambaPwdMustChange
=> '0'],
343 add
=> [sambaAcctFlags
=> '[W ]'],
344 add
=> [sambaLMPassword
=> "$lmpassword"],
345 add
=> [sambaNTPassword
=> "$ntpassword"],
346 add
=> [sambaSID
=> "$SID-$sambaSID"],
347 add
=> [sambaPrimaryGroupSID
=> "$SID-0"]
351 $modify->code && die "failed to add entry: ", $modify->error ;
354 # take down the session
355 $ldap_master->unbind;
362 my ($group, $userid) = @_;
364 my $dn_line = get_group_dn
($group);
365 if (!defined(get_group_dn
($group))) {
366 print "$0: group \"$group\" doesn't exist\n";
369 if (!defined($dn_line)) {
372 my $dn = get_dn_from_line
("$dn_line");
373 # on look if the user is already present in the group
374 my $is_member=is_group_member
($dn,$userid);
375 if ($is_member == 1) {
376 print "User \"$userid\" already member of the group \"$group\".\n";
378 # bind to a directory with dn and password
379 my $ldap_master=connect_ldap_master
();
380 # It does not matter if the user already exist, Net::LDAP will add the user
381 # if he does not exist, and ignore him if his already in the directory.
382 my $modify = $ldap_master->modify ( "$dn",
384 add
=> [memberUid
=> $userid]
387 $modify->code && die "failed to modify entry: ", $modify->error ;
389 $ldap_master->unbind;
396 # bind to a directory with dn and password
397 my $ldap_master=connect_ldap_master
();
398 my $modify = $ldap_master->delete ($group_dn);
399 $modify->code && die "failed to delete group : ", $modify->error ;
401 $ldap_master->unbind;
404 sub add_grouplist_user
406 my ($grouplist, $user) = @_;
407 my @array = split(/,/, $grouplist);
408 foreach my $group (@array) {
409 group_add_user
($group, $user);
417 my $dn = get_dn_from_line
($dn_line);
419 if (!defined($dn_line = get_user_dn
($user))) {
420 print "$0: user $user doesn't exist\n";
423 my $ldap_master=connect_ldap_master
();
424 my $modify = $ldap_master->modify ( "$dn",
426 replace
=> [userPassword
=> '{crypt}!x']
429 $modify->code && die "failed to modify entry: ", $modify->error ;
431 if (is_samba_user
($user)) {
432 my $modify = $ldap_master->modify ( "$dn",
434 replace
=> [sambaAcctFlags
=> '[D ]']
437 $modify->code && die "failed to modify entry: ", $modify->error ;
440 $ldap_master->unbind;
449 if (!defined($dn_line = get_user_dn
($user))) {
450 print "$0: user $user doesn't exist\n";
454 my $dn = get_dn_from_line
($dn_line);
455 my $ldap_master=connect_ldap_master
();
456 my $modify = $ldap_master->delete($dn);
457 $ldap_master->unbind;
460 # $gid = group_add($groupname, $group_gid, $force_using_existing_gid)
463 my ($gname, $gid, $force) = @_;
464 my $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
465 if ($nscd_status == 0) {
466 system "/etc/init.d/nscd stop > /dev/null 2>&1";
468 if (!defined($gid)) {
469 while (defined(getgrgid($GID_START))) {
474 if (!defined($force)) {
475 if (defined(getgrgid($gid))) {
480 if ($nscd_status == 0) {
481 system "/etc/init.d/nscd start > /dev/null 2>&1";
483 my $ldap_master=connect_ldap_master
();
484 my $modify = $ldap_master->add ( "cn=$gname,$groupsdn",
486 objectClass
=> 'posixGroup',
492 $modify->code && die "failed to add entry: ", $modify->error ;
494 $ldap_master->unbind;
498 # $homedir = get_homedir ($user)
503 my $ldap_slave=connect_ldap_slave
();
504 my $mesg = $ldap_slave->search (
507 filter
=> "(&(objectclass=posixAccount)(uid=$user))"
509 $mesg->code && die $mesg->error;
510 foreach my $entry ($mesg->all_entries) {
511 foreach my $attr ($entry->attributes) {
512 if ($attr=~/\bhomeDirectory\b/) {
513 foreach my $ent ($entry->get_value($attr)) {
514 $homeDir.= $attr.": ".$ent."\n";
521 if ($homeDir eq '') {
524 $homeDir =~ s/^homeDirectory: //;
533 my $ldap_slave=connect_ldap_slave
();
534 my $mesg = $ldap_slave->search ( # perform a search
537 filter
=> "(&(objectclass=posixAccount)(uid=$user))"
540 $mesg->code && die $mesg->error;
541 foreach my $entry ($mesg->all_entries) {
542 $lines.= "dn: " . $entry->dn."\n";
543 foreach my $attr ($entry->attributes) {
545 $lines.= $attr.": ".join(',', $entry->get_value($attr))."\n";
559 # return the attributes in an array
563 my $ldap_slave=connect_ldap_slave
();
564 my $mesg = $ldap_slave->search ( # perform a search
567 filter
=> "(&(objectclass=posixAccount)(uid=$user))"
570 $mesg->code && die $mesg->error;
571 my $entry = $mesg->entry();
581 my $ldap_slave=connect_ldap_slave
();
582 my $mesg = $ldap_slave->search ( # perform a search
585 filter
=> "(&(objectclass=posixGroup)(cn=$user))"
588 $mesg->code && die $mesg->error;
589 foreach my $entry ($mesg->all_entries) {
590 $lines.= "dn: " . $entry->dn."\n";
591 foreach my $attr ($entry->attributes) {
593 $lines.= $attr.": ".join(',', $entry->get_value($attr))."\n";
606 # find groups of a given user
607 ##### MODIFIE ########
612 my $ldap_slave=connect_ldap_slave
;
613 my $mesg = $ldap_slave->search ( # perform a search
616 filter
=> "(&(objectclass=posixGroup)(memberuid=$user))"
618 $mesg->code && die $mesg->error;
619 foreach my $entry ($mesg->all_entries) {
620 $lines.= "dn: ".$entry->dn."\n";
630 sub read_group_entry
{
634 my $ldap_slave=connect_ldap_slave
();
635 my $mesg = $ldap_slave->search ( # perform a search
638 filter
=> "(&(objectclass=posixGroup)(cn=$group))"
641 $mesg->code && die $mesg->error;
644 print "Error: $nb groups exist \"cn=$group\"\n";
645 foreach $entry ($mesg->all_entries) { my $dn=$entry->dn; print " $dn\n"; }
648 $entry = $mesg->shift_entry();
653 sub read_group_entry_gid
{
656 my $ldap_slave=connect_ldap_slave
();
657 my $mesg = $ldap_slave->search ( # perform a search
660 filter
=> "(&(objectclass=posixGroup)(gidNumber=$group))"
663 $mesg->code && die $mesg->error;
664 my $entry = $mesg->shift_entry();
668 # return the gidnumber for a group given as name or gid
669 # -1 : bad group name
673 my $userGidNumber = shift;
674 if ($userGidNumber =~ /[^\d]/ ) {
675 my $gname = $userGidNumber;
676 my $gidnum = getgrnam($gname);
677 if ($gidnum !~ /\d+/) {
680 $userGidNumber = $gidnum;
682 } elsif (!defined(getgrgid($userGidNumber))) {
685 return $userGidNumber;
688 # remove $user from $group
689 sub group_remove_member
691 my ($group, $user) = @_;
693 my $grp_line = get_group_dn
($group);
694 if (!defined($grp_line)) {
697 my $dn = get_dn_from_line
($grp_line);
698 # we test if the user exist in the group
699 my $is_member=is_group_member
($dn,$user);
700 if ($is_member == 1) {
701 my $ldap_master=connect_ldap_master
();
702 # delete only the user from the group
703 my $modify = $ldap_master->modify ( "$dn",
705 delete => [memberUid
=> ["$user"]]
708 $modify->code && die "failed to delete entry: ", $modify->error ;
709 $ldap_master->unbind;
714 sub group_get_members
719 my $grp_line = get_group_dn
($group);
720 if (!defined($grp_line)) {
724 my $ldap = Net
::LDAP
->new($slaveLDAP) or die "erreur LDAP";
726 my $mesg = $ldap->search (
729 filter
=> "(&(objectclass=posixgroup)(cn=$group))"
731 $mesg->code && die $mesg->error;
732 foreach my $entry ($mesg->all_entries) {
733 foreach my $attr ($entry->attributes) {
734 if ($attr=~/\bmemberUid\b/) {
735 foreach my $ent ($entry->get_value($attr)) {
736 push (@resultat,$ent);
747 my $FILE = "|$ldapmodify -r >/dev/null";
748 open (FILE
, $FILE) || die "$!\n";
758 sub group_type_by_name
{
759 my $type_name = shift;
765 return $groupmap{$type_name};