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