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);
46 add_samba_machine_mkntpwd
68 sub connect_ldap_master
70 # bind to a directory with dn and password
71 my $ldap_master = Net::LDAP->new(
73 port => "$masterPort",
77 or die "erreur LDAP: Can't contact master ldap server ($@)";
79 $ldap_master->start_tls(
80 # verify => 'require',
81 # clientcert => 'mycert.pem',
82 # clientkey => 'mykey.pem',
83 # decryptkey => sub { 'secret'; },
84 # capath => '/usr/local/cacerts/'
87 $ldap_master->bind ( "$binddn",
88 password => "$masterPw"
93 sub connect_ldap_slave
95 # bind to a directory with dn and password
96 my $ldap_slave = Net::LDAP->new(
102 or die "erreur LDAP: Can't contact slave ldap server ($@)";
104 $ldap_slave->start_tls(
105 # verify => 'require',
106 # clientcert => 'mycert.pem',
107 # clientkey => 'mykey.pem',
108 # decryptkey => sub { 'secret'; },
109 # capath => '/usr/local/cacerts/'
112 $ldap_slave->bind ( "$binddn",
113 password => "$slavePw"
122 my $ldap_slave=connect_ldap_slave();
123 my $mesg = $ldap_slave->search ( base => $suffix,
125 filter => "(&(objectclass=posixAccount)(uid=$user))"
127 $mesg->code && die $mesg->error;
128 foreach my $entry ($mesg->all_entries) {
145 my $ldap_slave=connect_ldap_slave();
146 my $mesg = $ldap_slave->search ( base => $suffix,
148 filter => "(&(objectclass=posixAccount)(uid=$user))"
150 $mesg->code && warn "failed to perform search; ", $mesg->error;
152 foreach my $entry ($mesg->all_entries) {
169 my $ldap_slave=connect_ldap_slave();
170 my $mesg = $ldap_slave->search ( base => $groupsdn,
172 filter => "(&(objectclass=posixGroup)(|(cn=$group)(gidNumber=$group)))"
174 $mesg->code && die $mesg->error;
175 foreach my $entry ($mesg->all_entries) {
187 # return (success, dn)
188 # bool = is_samba_user($username)
192 my $ldap_slave=connect_ldap_slave();
193 my $mesg = $ldap_slave->search ( base => $suffix,
195 filter => "(&(objectClass=sambaSamAccount)(uid=$user))"
197 $mesg->code && die $mesg->error;
199 return ($mesg->count ne 0);
205 my $ldap_slave=connect_ldap_slave();
206 my $mesg = $ldap_slave->search ( base => $suffix,
208 filter => "(&(objectClass=posixAccount)(uid=$user))"
210 $mesg->code && die $mesg->error;
212 return ($mesg->count ne 0);
217 my $dn_group = shift;
219 my $ldap_slave=connect_ldap_slave();
220 my $mesg = $ldap_slave->search (
223 filter => "(&(memberUid=$user))"
225 $mesg->code && die $mesg->error;
227 return ($mesg->count ne 0);
231 # try to bind with user dn and password to validate current password
234 my ($user, $dn, $pass) = @_;
235 my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP";
236 my $mesg= $ldap->bind (dn => $dn, password => $pass );
237 if ($mesg->code eq 0) {
245 print ("The LDAP directory is not available.\n Check the server, cables ...");
249 die "Problem : contact your administrator";
253 # dn = get_dn_from_line ($dn_line)
254 # helper to get "a=b,c=d" from "dn: a=b,c=d"
262 # success = add_posix_machine($user, $uid, $gid)
263 sub add_posix_machine
265 my ($user, $uid, $gid) = @_;
266 # bind to a directory with dn and password
267 my $ldap_master=connect_ldap_master();
268 my $add = $ldap_master->add ( "uid=$user,$computersdn",
270 'objectclass' => ['top','inetOrgPerson', 'posixAccount'],
274 'uidNumber' => "$uid",
275 'gidNumber' => "$gid",
276 'homeDirectory' => '/dev/null',
277 'loginShell' => '/bin/false',
278 'description' => 'Computer',
282 $add->code && warn "failed to add entry: ", $add->error ;
283 # take down the session
284 $ldap_master->unbind;
289 # success = add_samba_machine($computername)
290 sub add_samba_machine
293 system "smbpasswd -a -m $user";
297 sub add_samba_machine_mkntpwd
299 my ($user, $uid) = @_;
300 my $sambaSID = 2 * $uid + 1000;
304 if ($mk_ntpasswd eq '') {
305 print "Either set \$with_smbpasswd = 1 or specify \$mk_ntpasswd\n";
309 my $ntpwd = `$mk_ntpasswd '$name'`;
310 chomp(my $lmpassword = substr($ntpwd, 0, index($ntpwd, ':')));
311 chomp(my $ntpassword = substr($ntpwd, index($ntpwd, ':')+1));
313 my $ldap_master=connect_ldap_master();
314 my $modify = $ldap_master->modify ( "uid=$user,$computersdn",
316 replace => [objectClass => ['inetOrgPerson', 'posixAccount', 'sambaSAMAccount']],
317 add => [sambaPwdLastSet => '0'],
318 add => [sambaLogonTime => '0'],
319 add => [sambaLogoffTime => '2147483647'],
320 add => [sambaKickoffTime => '2147483647'],
321 add => [sambaPwdCanChange => '0'],
322 add => [sambaPwdMustChange => '0'],
323 add => [sambaAcctFlags => '[W ]'],
324 add => [sambaLMPassword => "$lmpassword"],
325 add => [sambaNTPassword => "$ntpassword"],
326 add => [sambaSID => "$SID-$sambaSID"],
327 add => [sambaPrimaryGroupSID => "$SID-0"]
331 $modify->code && die "failed to add entry: ", $modify->error ;
334 # take down the session
335 $ldap_master->unbind;
342 my ($group, $userid) = @_;
344 my $dn_line = get_group_dn($group);
345 if (!defined(get_group_dn($group))) {
346 print "$0: group \"$group\" doesn't exist\n";
349 if (!defined($dn_line)) {
352 my $dn = get_dn_from_line("$dn_line");
353 # on look if the user is already present in the group
354 my $is_member=is_group_member($dn,$userid);
355 if ($is_member == 1) {
356 print "User \"$userid\" already member of the group \"$group\".\n";
358 # bind to a directory with dn and password
359 my $ldap_master=connect_ldap_master();
360 # It does not matter if the user already exist, Net::LDAP will add the user
361 # if he does not exist, and ignore him if his already in the directory.
362 my $modify = $ldap_master->modify ( "$dn",
364 add => [memberUid => $userid]
367 $modify->code && die "failed to modify entry: ", $modify->error ;
369 $ldap_master->unbind;
376 # bind to a directory with dn and password
377 my $ldap_master=connect_ldap_master();
378 my $modify = $ldap_master->delete ($group_dn);
379 $modify->code && die "failed to delete group : ", $modify->error ;
381 $ldap_master->unbind;
384 sub add_grouplist_user
386 my ($grouplist, $user) = @_;
387 my @array = split(/,/, $grouplist);
388 foreach my $group (@array) {
389 group_add_user($group, $user);
397 my $dn = get_dn_from_line($dn_line);
399 if (!defined($dn_line = get_user_dn($user))) {
400 print "$0: user $user doesn't exist\n";
403 my $ldap_master=connect_ldap_master();
404 my $modify = $ldap_master->modify ( "$dn",
406 replace => [userPassword => '{crypt}!x']
409 $modify->code && die "failed to modify entry: ", $modify->error ;
411 if (is_samba_user($user)) {
412 my $modify = $ldap_master->modify ( "$dn",
414 replace => [sambaAcctFlags => '[D ]']
417 $modify->code && die "failed to modify entry: ", $modify->error ;
420 $ldap_master->unbind;
429 if (!defined($dn_line = get_user_dn($user))) {
430 print "$0: user $user doesn't exist\n";
434 my $dn = get_dn_from_line($dn_line);
435 my $ldap_master=connect_ldap_master();
436 my $modify = $ldap_master->delete($dn);
437 $ldap_master->unbind;
440 # $success = group_add($groupname, $group_gid, $force_using_existing_gid)
443 my ($gname, $gid, $force) = @_;
444 my $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
445 if ($nscd_status == 0) {
446 system "/etc/init.d/nscd stop > /dev/null 2>&1";
448 if (!defined($gid)) {
449 while (defined(getgrgid($GID_START))) {
454 if (!defined($force)) {
455 if (defined(getgrgid($gid))) {
460 if ($nscd_status == 0) {
461 system "/etc/init.d/nscd start > /dev/null 2>&1";
463 my $ldap_master=connect_ldap_master();
464 my $modify = $ldap_master->add ( "cn=$gname,$groupsdn",
466 objectClass => 'posixGroup',
472 $modify->code && die "failed to add entry: ", $modify->error ;
474 $ldap_master->unbind;
478 # $homedir = get_homedir ($user)
483 my $ldap_slave=connect_ldap_slave();
484 my $mesg = $ldap_slave->search (
487 filter => "(&(objectclass=posixAccount)(uid=$user))"
489 $mesg->code && die $mesg->error;
490 foreach my $entry ($mesg->all_entries){
491 foreach my $attr ($entry->attributes) {
492 if ($attr=~/\bhomeDirectory\b/){
493 foreach my $ent($entry->get_value($attr)) {
494 $homeDir.= $attr.": ".$ent."\n";
501 if ($homeDir eq '') {
504 $homeDir =~ s/^homeDirectory: //;
513 my $ldap_slave=connect_ldap_slave();
514 my $mesg = $ldap_slave->search ( # perform a search
517 filter => "(&(objectclass=posixAccount)(uid=$user))"
520 $mesg->code && die $mesg->error;
521 foreach my $entry ($mesg->all_entries) {
522 $lines.= "dn: " . $entry->dn."\n";
523 foreach my $attr ($entry->attributes) {
525 $lines.= $attr.": ".join(',', $entry->get_value($attr))."\n";
539 # return the attributes in an array
543 my $ldap_slave=connect_ldap_slave();
544 my $mesg = $ldap_slave->search ( # perform a search
547 filter => "(&(objectclass=posixAccount)(uid=$user))"
550 $mesg->code && die $mesg->error;
551 my $entry = $mesg->entry();
561 my $ldap_slave=connect_ldap_slave();
562 my $mesg = $ldap_slave->search ( # perform a search
565 filter => "(&(objectclass=posixGroup)(cn=$user))"
568 $mesg->code && die $mesg->error;
569 foreach my $entry ($mesg->all_entries) {
570 $lines.= "dn: " . $entry->dn."\n";
571 foreach my $attr ($entry->attributes) {
573 $lines.= $attr.": ".join(',', $entry->get_value($attr))."\n";
586 # find groups of a given user
587 ##### MODIFIE ########
592 my $ldap_slave=connect_ldap_slave;
593 my $mesg = $ldap_slave->search ( # perform a search
596 filter => "(&(objectclass=posixGroup)(memberuid=$user))"
598 $mesg->code && die $mesg->error;
599 foreach my $entry ($mesg->all_entries) {
600 $lines.= "dn: ".$entry->dn."\n";
610 # return the gidnumber for a group given as name or gid
611 # -1 : bad group name
615 my $userGidNumber = shift;
616 if ($userGidNumber =~ /[^\d]/ ) {
617 my $gname = $userGidNumber;
618 my $gidnum = getgrnam($gname);
619 if ($gidnum !~ /\d+/) {
622 $userGidNumber = $gidnum;
624 } elsif (!defined(getgrgid($userGidNumber))) {
627 return $userGidNumber;
630 # remove $user from $group
631 sub group_remove_member
633 my ($group, $user) = @_;
635 my $grp_line = get_group_dn($group);
636 if (!defined($grp_line)) {
639 my $dn = get_dn_from_line($grp_line);
640 # we test if the user exist in the group
641 my $is_member=is_group_member($dn,$user);
642 if ($is_member == 1) {
643 my $ldap_master=connect_ldap_master();
644 # delete only the user from the group
645 my $modify = $ldap_master->modify ( "$dn",
647 delete => [memberUid => ["$user"]]
650 $modify->code && die "failed to delete entry: ", $modify->error ;
651 $ldap_master->unbind;
656 sub group_get_members
661 my $grp_line = get_group_dn($group);
662 if (!defined($grp_line)) {
666 my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP";
668 my $mesg = $ldap->search (
671 filter => "(&(objectclass=posixgroup)(cn=$group))"
673 $mesg->code && die $mesg->error;
674 foreach my $entry ($mesg->all_entries){
675 foreach my $attr ($entry->attributes){
676 if ($attr=~/\bmemberUid\b/){
677 foreach my $ent ($entry->get_value($attr)) {
678 push (@resultat,$ent);
689 my $FILE = "|$ldapmodify -r >/dev/null";
690 open (FILE, $FILE) || die "$!\n";