check in Idealx tools after talking with Olivier Lemaire at idealx dot org.
[Samba.git] / examples / LDAP / smbldap-tools / smbldap_tools.pm
blob1c090d0d5718ba7c54f1160e25e1cb8c74a68e15
1 #! /usr/bin/perl
2 use strict;
3 package smbldap_tools;
4 use smbldap_conf;
6 # $Id: smbldap_tools.pm,v 1.1.2.1 2002/06/04 22:25:39 jerry Exp $
8 # This code was developped by IDEALX (http://IDEALX.org/) and
9 # contributors (their names can be found in the CONTRIBUTORS file).
11 # Copyright (C) 2001-2002 IDEALX
13 # This program is free software; you can redistribute it and/or
14 # modify it under the terms of the GNU General Public License
15 # as published by the Free Software Foundation; either version 2
16 # of the License, or (at your option) any later version.
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
23 # You should have received a copy of the GNU General Public License
24 # along with this program; if not, write to the Free Software
25 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
26 # USA.
29 # ugly funcs using global variables and spawning openldap clients
31 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
32 use Exporter;
33 $VERSION = 1.00;
34 @ISA = qw(Exporter);
36 @EXPORT = qw(
37 get_user_dn
38 get_group_dn
39 is_samba_user
40 is_user_valid
41 get_dn_from_line
42 add_posix_machine
43 add_samba_machine
44 add_samba_machine_mkntpwd
45 group_add_user
46 add_grouplist_user
47 disable_user
48 delete_user
49 group_add
50 get_homedir
51 read_user
52 read_group
53 find_groups_of
54 parse_group
55 group_remove_member
56 group_get_members
57 do_ldapadd
58 do_ldapmodify
59 get_user_dn2
62 # dn_line = get_user_dn($username)
63 # where dn_line is like "dn: a=b,c=d"
64 sub get_user_dn
66 my $user = shift;
67 my $dn=`$ldapsearch -b '$suffix' -s '$scope' '(&(objectclass=posixAccount)(uid=$user))' | grep "^dn:"`;
68 chomp $dn;
69 if ($dn eq '') {
70 return undef;
73 return $dn;
76 # return (success, dn)
77 sub get_user_dn2
79 my $user = shift;
81 my $sr = `$ldapsearch -b '$suffix' -s '$scope' '(&(objectclass=posixAccount)(uid=$user))'`;
82 if ($sr eq "") {
83 print "get_user_dn2: error in ldapsearch :
84 $ldapsearch -b '$suffix' -s '$scope' '(&(objectclass=posixAccount)(uid=$user))'\n";
85 return (0, undef);
88 my @lines = split(/\n/, $sr);
90 my @matches = grep(/^dn:/, @lines);
92 my $dn = $matches[0];
93 chomp $dn;
94 if ($dn eq '') {
95 return (1, undef);
98 return (1, $dn);
101 # dn_line = get_group_dn($groupname)
102 # where dn_line is like "dn: a=b,c=d"
103 sub get_group_dn
105 my $group = shift;
106 my $dn=`$ldapsearch -b '$groupsdn' -s '$scope' '(&(objectclass=posixGroup)(|(cn=$group)(gidNumber=$group)))' | grep "^dn:"`;
107 chomp $dn;
108 if ($dn eq '') {
109 return undef;
112 return $dn;
115 # bool = is_samba_user($username)
116 sub is_samba_user
118 my $user = shift;
119 my $cmd = "$ldapsearch -b '$suffix' -s '$scope' '(&(objectClass=sambaAccount)(uid=$user))' | grep '^dn:\'";
120 my $res=`$cmd`;
121 chomp $res;
122 if ($res ne '') {
123 return 1;
125 return 0;
128 # bool = is_user_valid($username)
129 # try to bind with user dn and password to validate current password
130 sub is_user_valid
132 my ($user, $dn, $pass) = @_;
133 my $res=`$ldapsearchnobind -b '$usersdn' -s '$scope' -D '$dn' -w '$pass' '(&(objectclass=posixAccount)(uid=$user))' 2>/dev/null | grep "^dn:"`;
134 chomp $res;
135 if ($res eq '') {
136 return 0;
138 return 1;
141 # dn = get_dn_from_line ($dn_line)
142 # helper to get "a=b,c=d" from "dn: a=b,c=d"
143 sub get_dn_from_line
145 my $dn = shift;
146 $dn =~ s/^dn: //;
147 return $dn;
150 # success = add_posix_machine($user, $uid, $gid)
151 sub add_posix_machine
153 my ($user, $uid, $gid) = @_;
155 my $tmpldif =
156 "dn: uid=$user,$computersdn
157 objectclass: top
158 objectclass: posixAccount
159 cn: $user
160 uid: $user
161 uidNumber: $uid
162 gidNumber: $gid
163 homeDirectory: /dev/null
164 loginShell: /bin/false
165 description: Computer
169 die "$0: error while adding posix account to machine $user\n"
170 unless (do_ldapadd($tmpldif) == 0);
172 undef $tmpldif;
174 return 1;
177 # success = add_samba_machine($computername)
178 sub add_samba_machine
180 my $user = shift;
181 system "smbpasswd -a -m $user";
183 return 1;
186 sub add_samba_machine_mkntpwd
188 my ($user, $uid) = @_;
189 my $rid = 2 * $uid + 1000; # Samba 2.2.2 stuff
191 my $name = $user;
192 $name =~ s/.$//s;
194 if ($mk_ntpasswd eq '') {
195 print "Either set \$with_smbpasswd = 1 or specify \$mk_ntpasswd\n";
196 return 0;
199 my $ntpwd = `$mk_ntpasswd '$name'`;
200 chomp(my $lmpassword = substr($ntpwd, 0, index($ntpwd, ':')));
201 chomp(my $ntpassword = substr($ntpwd, index($ntpwd, ':')+1));
203 my $tmpldif =
204 "dn: uid=$user,$computersdn
205 changetype: modify
206 objectclass: top
207 objectclass: posixAccount
208 objectClass: sambaAccount
209 pwdLastSet: 0
210 logonTime: 0
211 logoffTime: 2147483647
212 kickoffTime: 2147483647
213 pwdCanChange: 0
214 pwdMustChange: 2147483647
215 acctFlags: [W ]
216 lmpassword: $lmpassword
217 ntpassword: $ntpassword
218 rid: $rid
219 primaryGroupID: 0
223 die "$0: error while adding samba account to $user\n"
224 unless (do_ldapmodify($tmpldif) == 0);
225 undef $tmpldif;
227 return 1;
232 sub group_add_user
234 my ($group, $userid) = @_;
235 my $dn_line;
237 if (!defined($dn_line = get_group_dn($group))) {
238 return 1;
240 my $dn = get_dn_from_line($dn_line);
241 my $members = `$ldapsearch -b '$dn' -s base | grep -i "^memberUid:"`;
242 chomp($members);
243 # user already member ?
244 if ($members =~ m/^memberUid: $userid/) {
245 return 2;
247 my $mods = "";
248 if ($members ne '') {
249 $mods="$dn_line
250 changetype: modify
251 replace: memberUid
252 $members
253 memberUid: $userid
255 } else {
256 $mods="$dn_line
257 changetype: modify
258 add: memberUid
259 memberUid: $userid
263 #print "$mods\n";
265 my $tmpldif =
266 "$mods
269 die "$0: error while modifying group $group\n"
270 unless (do_ldapmodify($tmpldif) == 0);
271 undef $tmpldif;
272 return 0;
275 sub add_grouplist_user
277 my ($grouplist, $user) = @_;
278 my @array = split(/,/, $grouplist);
279 foreach my $group (@array) {
280 group_add_user($group, $user);
284 # XXX FIXME : acctFlags |= D, and not acctFlags = D
285 sub disable_user
287 my $user = shift;
288 my $dn_line;
290 if (!defined($dn_line = get_user_dn($user))) {
291 print "$0: user $user doesn't exist\n";
292 exit (10);
295 my $tmpldif =
296 "dn: $dn_line
297 changetype: modify
298 replace: userPassword
299 userPassword: {crypt}!x
303 die "$0: error while modifying user $user\n"
304 unless (do_ldapmodify($tmpldif) == 0);
305 undef $tmpldif;
307 if (is_samba_user($user)) {
309 my $tmpldif =
310 "dn: $dn_line
311 changetype: modify
312 replace: acctFlags
313 acctFlags: [D ]
317 die "$0: error while modifying user $user\n"
318 unless (do_ldapmodify($tmpldif) == 0);
319 undef $tmpldif;
325 # delete_user($user)
326 sub delete_user
328 my $user = shift;
329 my $dn_line;
331 if (!defined($dn_line = get_user_dn($user))) {
332 print "$0: user $user doesn't exist\n";
333 exit (10);
336 my $dn = get_dn_from_line($dn_line);
337 system "$ldapdelete $dn >/dev/null";
340 # $success = group_add($groupname, $group_gid, $force_using_existing_gid)
341 sub group_add
343 my ($gname, $gid, $force) = @_;
345 my $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
347 if ($nscd_status == 0) {
348 system "/etc/init.d/nscd stop > /dev/null 2>&1";
351 if (!defined($gid)) {
352 while (defined(getgrgid($GID_START))) {
353 $GID_START++;
355 $gid = $GID_START;
356 } else {
357 if (!defined($force)) {
358 if (defined(getgrgid($gid))) {
359 return 0;
364 if ($nscd_status == 0) {
365 system "/etc/init.d/nscd start > /dev/null 2>&1";
368 my $tmpldif =
369 "dn: cn=$gname,$groupsdn
370 objectclass: posixGroup
371 cn: $gname
372 gidNumber: $gid
376 die "$0: error while adding posix group $gname\n"
377 unless (do_ldapadd($tmpldif) == 0);
379 undef $tmpldif;
381 return 1;
384 # $homedir = get_homedir ($user)
385 sub get_homedir
387 my $user = shift;
388 my $homeDir=`$ldapsearch -b '$suffix' -s '$scope' '(&(objectclass=posixAccount)(uid=$user))' | grep "^homeDirectory:"`;
389 chomp $homeDir;
390 if ($homeDir eq '') {
391 return undef;
393 $homeDir =~ s/^homeDirectory: //;
395 return $homeDir;
398 # search for an user
399 sub read_user
401 my $user = shift;
402 my $lines=`$ldapsearch -b '$suffix' -s '$scope' '(&(objectclass=posixAccount)(uid=$user))' -LLL`;
403 chomp $lines;
404 if ($lines eq '') {
405 return undef;
408 return $lines;
411 # search for a group
412 sub read_group
414 my $user = shift;
415 my $lines=`$ldapsearch -b '$groupsdn' -s '$scope' '(&(objectclass=posixGroup)(cn=$user))' -LLL`;
416 chomp $lines;
417 if ($lines eq '') {
418 return undef;
421 return $lines;
424 # find groups of a given user
425 sub find_groups_of
427 my $user = shift;
428 my $lines=`$ldapsearch -b '$groupsdn' -s '$scope' '(&(objectclass=posixGroup)(memberuid=$user))' -LLL | grep "^dn: "`;
429 chomp $lines;
430 if ($lines eq '') {
431 return undef;
434 return $lines;
437 # return the gidnumber for a group given as name or gid
438 # -1 : bad group name
439 # -2 : bad gidnumber
440 sub parse_group
442 my $userGidNumber = shift;
444 if ($userGidNumber =~ /[^\d]/ ) {
445 my $gname = $userGidNumber;
446 my $gidnum = getgrnam($gname);
447 if ($gidnum !~ /\d+/) {
448 return -1;
449 } else {
450 $userGidNumber = $gidnum;
452 } elsif (!defined(getgrgid($userGidNumber))) {
453 return -2;
455 return $userGidNumber;
458 # remove $user from $group
459 sub group_remove_member
461 my ($group, $user) = @_;
463 my $grp_line = get_group_dn($group);
464 if (!defined($grp_line)) {
465 return 0;
467 my $members = `$ldapsearch -b '$groupsdn' -s '$scope' '(&(objectclass=posixgroup)(cn=$group))' | grep -i "^memberUid:"`;
469 #print "avant ---\n$members\n";
470 $members =~ s/memberUid: $user\n//;
471 #print "----\n$members\n---\n";
473 chomp($members);
475 my $header;
476 if ($members eq '') {
477 $header = "changetype: modify\n";
478 $header .= "delete: memberUid";
479 } else {
480 $header = "changetype: modify\n";
481 $header .= "replace: memberUid";
484 my $tmpldif =
485 "$grp_line
486 $header
487 $members
489 die "$0: error while modifying group $group\n"
490 unless (do_ldapmodify($tmpldif) == 0);
491 undef $tmpldif;
493 return 1;
496 sub group_get_members
498 my ($group) = @_;
499 my @members;
501 my $grp_line = get_group_dn($group);
502 if (!defined($grp_line)) {
503 return 0;
505 my $members = `$ldapsearch -b '$groupsdn' -s '$scope' '(&(objectclass=posixgroup)(cn=$group))' memberUid | grep -i "^memberUid:"`;
507 my @lines = split (/\n/, $members);
508 foreach my $line (@lines) {
509 $line =~ s/^memberUid: //;
510 push(@members, $line);
513 return @members;
516 sub file_write {
517 my ($filename, $filecontent) = @_;
518 local *FILE;
519 open (FILE, "> $filename") ||
520 die "Cannot open «$filename» for writing: $!\n";
521 print FILE $filecontent;
522 close FILE;
525 # wrapper for ldapadd
526 sub do_ldapadd2
528 my $ldif = shift;
530 my $tempfile = "/tmp/smbldapadd.$$";
531 file_write($tempfile, $ldif);
533 my $rc = system "$ldapadd < $tempfile >/dev/null";
534 unlink($tempfile);
535 return $rc;
538 sub do_ldapadd
540 my $ldif = shift;
542 my $FILE = "|$ldapadd >/dev/null";
543 open (FILE, $FILE) || die "$!\n";
544 print FILE <<EOF;
545 $ldif
548 close FILE;
549 my $rc = $?;
550 return $rc;
553 # wrapper for ldapmodify
554 sub do_ldapmodify2
556 my $ldif = shift;
558 my $tempfile = "/tmp/smbldapmod.$$";
559 file_write($tempfile, $ldif);
561 my $rc = system "$ldapmodify -r < $tempfile >/dev/null";
562 unlink($tempfile);
563 return $rc;
566 sub do_ldapmodify
568 my $ldif = shift;
570 my $FILE = "|$ldapmodify -r >/dev/null";
571 open (FILE, $FILE) || die "$!\n";
572 print FILE <<EOF;
573 $ldif
576 close FILE;
577 my $rc = $?;
579 return $rc;