Initial import
[samba] / examples / LDAP / smbldap-tools-0.9.1 / smbldap-populate
1 #!/usr/bin/perl -w
2
3 # Populate a LDAP base for Samba-LDAP usage
4 #
5 # $Id: smbldap-populate,v 1.26 2005/05/27 14:21:00 jtournier Exp $
6
7 #  This code was developped by IDEALX (http://IDEALX.org/) and
8 #  contributors (their names can be found in the CONTRIBUTORS file).
9 #
10 #                 Copyright (C) 2001-2002 IDEALX
11 #
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.
16 #
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.
21 #
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,
25 #  USA.
26
27 #  Purpose :
28 #       . Create an initial LDAP database suitable for Samba 2.2
29 #       . For lazy people, replace ldapadd (with only an ldif parameter)
30
31 use strict;
32 use FindBin;
33 use FindBin qw($RealBin);
34 use lib "$RealBin/";
35 use smbldap_tools;
36 use Getopt::Std;
37 use Net::LDAP::LDIF;
38
39 use vars qw(%oc);
40
41 # objectclass of the suffix
42 %oc = (
43        "ou" => "organizationalUnit",
44        "o" => "organization",
45        "dc" => "dcObject",
46       );
47
48
49 my %Options;
50
51 my $ok = getopts('a:b:e:i:k:l:m:u:g:?', \%Options);
52 if ( (!$ok) || ($Options{'?'}) ) {
53   print_banner;
54   print "Usage: $0 [-abeiklug?] [ldif]\n";
55   print "  -u uidNumber first uidNumber to allocate (default: 1000)\n";
56   print "  -g gidNumber first uidNumber to allocate (default: 1000)\n";
57   print "  -a user      administrator login name (default: root)\n";
58   print "  -b user      guest login name (default: nobody)\n";
59   print "  -k uidNumber administrator's uidNumber (default: 0)\n";
60   print "  -l uidNumber guest's uidNumber (default: 999)\n";
61   print "  -m gidNumber administrator's gidNumber (default: 0)\n";
62   print "  -e file      export ldif file\n";
63   print "  -i file      import ldif file\n";
64   print "  -?           show this help message\n";
65
66   exit (1);
67 }
68
69 # sanity checks
70 my $domain = $config{sambaDomain};
71 if (! defined $domain) {
72   print STDERR "error: domain name not found !\n";
73   print STDERR "possible reasons are:\n";
74   print STDERR ". incorrect 'sambaDomain' parameter in smbldap.conf\n";
75   print STDERR ". incorrect 'samba_conf' definition in smbldap_tools.pm\n";
76   die;
77 }
78
79 #$config{sambaUnixIdPooldn}="sambaDomainName=$domain,$config{suffix}";
80
81 my $firstuidNumber=$Options{'u'};
82 if (!defined($firstuidNumber)) {
83   $firstuidNumber=1000;
84 }
85
86 my $firstgidNumber=$Options{'g'};
87 if (!defined($firstgidNumber)) {
88   $firstgidNumber=1000;
89 }
90
91 my $tmp_ldif_file=$Options{'e'};
92 if (!defined($tmp_ldif_file)) {
93   $tmp_ldif_file="/tmp/$$.ldif";
94 }
95
96 my $adminName = $Options{'a'};
97 if (!defined($adminName)) {
98   $adminName = "root";
99 }
100
101 my $guestName = $Options{'b'};
102 if (!defined($guestName)) {
103   $guestName = "nobody";
104 }
105
106 my $adminUidNumber=$Options{'k'};
107 my $adminrid;
108 if (!defined($adminUidNumber)) {
109   $adminUidNumber = "0";
110   $adminrid= "500";
111 } else {
112   $adminrid=(2*$adminUidNumber+ 1000)
113 }
114
115 my $guestUidNumber=$Options{'l'};
116 if (!defined($guestUidNumber)) {
117   $guestUidNumber = "999";
118 }
119
120 my $adminGidNumber=$Options{'m'};
121 if (!defined($adminGidNumber)) {
122   $adminGidNumber = "0";
123 }
124
125 my $_ldifName = $Options{'i'};
126
127 my $exportFile = $Options{'e'};
128 if (!defined($exportFile)) {
129   $exportFile = "base.ldif";
130 }
131
132 print "Populating LDAP directory for domain $domain ($config{SID})\n";
133 if (!defined($_ldifName)) {
134   my $attr;
135   my $val;
136   my $objcl;
137
138   print "(using builtin directory structure)\n\n";
139   if ($config{suffix} =~ m/([^=]+)=([^,]+)/) {
140     $attr = $1;
141     $val = $2;
142     $objcl = $oc{$attr} if (exists $oc{$attr});
143     if (!defined($objcl)) {
144       $objcl = "myhardcodedobjectclass";
145     }
146   } else {
147     die "can't extract first attr and value from suffix $config{suffix}";
148   }
149   #print "$attr=$val\n";
150   my ($type,$ou_users,$ou_groups,$ou_computers,$ou_idmap,$cnsambaUnixIdPool);
151   ($type,$ou_users)=($config{usersdn}=~/(.*)=(.*),$config{suffix}/);
152   ($type,$ou_groups)=($config{groupsdn}=~/(.*)=(.*),$config{suffix}/);
153   ($type,$ou_computers)=($config{computersdn}=~/(.*)=(.*),$config{suffix}/);
154   if (defined $config{idmapdn}) {
155         ($type,$ou_idmap)=($config{idmapdn}=~/(.*)=(.*),$config{suffix}/);
156   }
157   ($type,$cnsambaUnixIdPool)=($config{sambaUnixIdPooldn}=~/(.*)=(.*),$config{suffix}/);
158   my $org;
159   my ($organisation,$ext);
160   if ($config{suffix} =~ m/dc=([^=]+),dc=(.*)$/) {
161         ($organisation,$ext) = ($config{suffix} =~ m/dc=([^=]+),dc=(.*)$/);
162   } elsif ($config{suffix} =~ m/dc=(.*)$/) {
163         $organisation=$1;
164   }
165
166   if ($organisation ne '') {
167     $org = "\nobjectclass: organization\no: $organisation";
168   }
169   #my $FILE="|cat";
170
171   my $entries="dn: $config{suffix}
172 objectClass: $objcl$org
173 $attr: $val
174
175 dn: $config{usersdn}
176 objectClass: organizationalUnit
177 ou: $ou_users
178
179 dn: $config{groupsdn}
180 objectClass: organizationalUnit
181 ou: $ou_groups
182
183 dn: $config{computersdn}
184 objectClass: organizationalUnit
185 ou: $ou_computers\n";
186
187 if (defined $config{idmapdn}) {
188         $entries.="\ndn: $config{idmapdn}
189 objectClass: organizationalUnit
190 ou: $ou_idmap\n";
191 }
192
193 $entries.="\ndn: uid=$adminName,$config{usersdn}
194 cn: $adminName
195 sn: $adminName
196 objectClass: inetOrgPerson
197 objectClass: sambaSAMAccount
198 objectClass: posixAccount
199 objectClass: shadowAccount
200 gidNumber: $adminGidNumber
201 uid: $adminName
202 uidNumber: $adminUidNumber\n";
203   if (defined $config{userHome} and $config{userHome} ne "") {
204     my $userHome=$config{userHome};
205     $userHome=~s/\%U/$adminName/;
206     $entries.="homeDirectory: $userHome\n";
207   } else {
208     $entries.="homeDirectory: /dev/null\n";
209   }
210   $entries.="sambaPwdLastSet: 0
211 sambaLogonTime: 0
212 sambaLogoffTime: 2147483647
213 sambaKickoffTime: 2147483647
214 sambaPwdCanChange: 0
215 sambaPwdMustChange: 2147483647\n";
216   if (defined $config{userSmbHome} and $config{userSmbHome} ne "") {
217     my $userSmbHome=$config{userSmbHome};
218     $userSmbHome=~s/\%U/$adminName/;
219     $entries.="sambaHomePath: $userSmbHome\n";
220   }
221   if (defined $config{userHomeDrive} and $config{userHomeDrive} ne "") {
222     $entries.="sambaHomeDrive: $config{userHomeDrive}\n";
223   }
224   if (defined $config{userProfile} and $config{userProfile} ne "") {
225     my $userProfile=$config{userProfile};
226     $userProfile=~s/\%U/$adminName/;
227     $entries.="sambaProfilePath: $userProfile\n";       
228   }
229   $entries.="sambaPrimaryGroupSID: $config{SID}-512
230 sambaLMPassword: XXX
231 sambaNTPassword: XXX
232 sambaAcctFlags: [U          ]
233 sambaSID: $config{SID}-$adminrid
234 loginShell: /bin/false
235 gecos: Netbios Domain Administrator
236
237 dn: uid=$guestName,$config{usersdn}
238 cn: $guestName
239 sn: $guestName
240 objectClass: inetOrgPerson
241 objectClass: sambaSAMAccount
242 objectClass: posixAccount
243 objectClass: shadowAccount
244 gidNumber: 514
245 uid: $guestName
246 uidNumber: $guestUidNumber
247 homeDirectory: /dev/null
248 sambaPwdLastSet: 0
249 sambaLogonTime: 0
250 sambaLogoffTime: 2147483647
251 sambaKickoffTime: 2147483647
252 sambaPwdCanChange: 0
253 sambaPwdMustChange: 2147483647\n";
254   if (defined $config{userSmbHome} and $config{userSmbHome} ne "") {
255     my $userSmbHome=$config{userSmbHome};
256     $userSmbHome=~s/\%U/$guestName/;
257     $entries.="sambaHomePath: $userSmbHome\n";
258   }
259   if (defined $config{userHomeDrive} and $config{userHomeDrive} ne "") {
260     $entries.="sambaHomeDrive: $config{userHomeDrive}\n";
261   }
262   if (defined $config{userProfile} and $config{userProfile} ne "") {
263     my $userProfile=$config{userProfile};
264     $userProfile=~s/\%U/$guestName/;
265     $entries.="sambaProfilePath: $userProfile\n";
266   }
267   $entries.="sambaPrimaryGroupSID: $config{SID}-514
268 sambaLMPassword: NO PASSWORDXXXXXXXXXXXXXXXXXXXXX
269 sambaNTPassword: NO PASSWORDXXXXXXXXXXXXXXXXXXXXX
270 # account disabled by default
271 sambaAcctFlags: [NUD        ]
272 sambaSID: $config{SID}-2998
273 loginShell: /bin/false
274
275 dn: cn=Domain Admins,$config{groupsdn}
276 objectClass: posixGroup
277 objectClass: sambaGroupMapping
278 gidNumber: 512
279 cn: Domain Admins
280 memberUid: $adminName
281 description: Netbios Domain Administrators
282 sambaSID: $config{SID}-512
283 sambaGroupType: 2
284 displayName: Domain Admins
285
286 dn: cn=Domain Users,$config{groupsdn}
287 objectClass: posixGroup
288 objectClass: sambaGroupMapping
289 gidNumber: 513
290 cn: Domain Users
291 description: Netbios Domain Users
292 sambaSID: $config{SID}-513
293 sambaGroupType: 2
294 displayName: Domain Users
295
296 dn: cn=Domain Guests,$config{groupsdn}
297 objectClass: posixGroup
298 objectClass: sambaGroupMapping
299 gidNumber: 514
300 cn: Domain Guests
301 description: Netbios Domain Guests Users
302 sambaSID: $config{SID}-514
303 sambaGroupType: 2
304 displayName: Domain Guests
305
306 dn: cn=Domain Computers,$config{groupsdn}
307 objectClass: posixGroup
308 objectClass: sambaGroupMapping
309 gidNumber: 515
310 cn: Domain Computers
311 description: Netbios Domain Computers accounts
312 sambaSID: $config{SID}-515
313 sambaGroupType: 2
314 displayName: Domain Computers
315
316 dn: cn=Administrators,$config{groupsdn}
317 objectClass: posixGroup
318 objectClass: sambaGroupMapping
319 gidNumber: 544
320 cn: Administrators
321 description: Netbios Domain Members can fully administer the computer/sambaDomainName
322 sambaSID: S-1-5-32-544
323 sambaGroupType: 5
324 displayName: Administrators
325
326 #dn: cn=Users,$config{groupsdn}
327 #objectClass: posixGroup
328 #objectClass: sambaGroupMapping
329 #gidNumber: 545
330 #cn: Users
331 #description: Netbios Domain Ordinary users
332 #sambaSID: S-1-5-32-545
333 #sambaGroupType: 5
334 #displayName: users
335
336 #dn: cn=Guests,$config{groupsdn}
337 #objectClass: posixGroup
338 #objectClass: sambaGroupMapping
339 #gidNumber: 546
340 #cn: Guests
341 #memberUid: $guestName
342 #description: Netbios Domain Users granted guest access to the computer/sambaDomainName
343 #sambaSID: S-1-5-32-546
344 #sambaGroupType: 5
345 #displayName: Guests
346
347 #dn: cn=Power Users,$config{groupsdn}
348 #objectClass: posixGroup
349 #objectClass: sambaGroupMapping
350 #gidNumber: 547
351 #cn: Power Users
352 #description: Netbios Domain Members can share directories and printers
353 #sambaSID: S-1-5-32-547
354 #sambaGroupType: 5
355 #displayName: Power Users
356
357 dn: cn=Account Operators,$config{groupsdn}
358 objectClass: posixGroup
359 objectClass: sambaGroupMapping
360 gidNumber: 548
361 cn: Account Operators
362 description: Netbios Domain Users to manipulate users accounts
363 sambaSID: S-1-5-32-548
364 sambaGroupType: 5
365 displayName: Account Operators
366
367 #dn: cn=System Operators,$config{groupsdn}
368 #objectClass: posixGroup
369 #objectClass: sambaGroupMapping
370 #gidNumber: 549
371 #cn: System Operators
372 #description: Netbios Domain System Operators
373 #sambaSID: S-1-5-32-549
374 #sambaGroupType: 5
375 #displayName: System Operators
376
377 dn: cn=Print Operators,$config{groupsdn}
378 objectClass: posixGroup
379 objectClass: sambaGroupMapping
380 gidNumber: 550
381 cn: Print Operators
382 description: Netbios Domain Print Operators
383 sambaSID: S-1-5-32-550
384 sambaGroupType: 5
385 displayName: Print Operators
386
387 dn: cn=Backup Operators,$config{groupsdn}
388 objectClass: posixGroup
389 objectClass: sambaGroupMapping
390 gidNumber: 551
391 cn: Backup Operators
392 description: Netbios Domain Members can bypass file security to back up files
393 sambaSID: S-1-5-32-551
394 sambaGroupType: 5
395 displayName: Backup Operators
396
397 dn: cn=Replicators,$config{groupsdn}
398 objectClass: posixGroup
399 objectClass: sambaGroupMapping
400 gidNumber: 552
401 cn: Replicators
402 description: Netbios Domain Supports file replication in a sambaDomainName
403 sambaSID: S-1-5-32-552
404 sambaGroupType: 5
405 displayName: Replicators
406
407 ";
408   if ("sambaDomainName=$domain,$config{suffix}" eq $config{sambaUnixIdPooldn}) {
409     $entries.="dn: sambaDomainName=$domain,$config{suffix}
410 objectClass: sambaDomain
411 objectClass: sambaUnixIdPool
412 sambaDomainName: $domain
413 sambaSID: $config{SID}
414 uidNumber: $firstuidNumber
415 gidNumber: $firstgidNumber";
416   } else {
417     $entries.="dn: $config{sambaUnixIdPooldn}
418 objectClass: inetOrgPerson
419 objectClass: sambaUnixIdPool
420 uidNumber: $firstuidNumber
421 gidNumber: $firstgidNumber
422 cn: $cnsambaUnixIdPool
423 sn: $cnsambaUnixIdPool";
424   }
425   open (FILE, ">$tmp_ldif_file") || die "Can't open file $tmp_ldif_file: $!\n";
426
427   print FILE <<EOF;
428 $entries
429 EOF
430   close FILE;
431 } else {
432   $tmp_ldif_file=$_ldifName;
433 }
434
435 if (!defined $Options{'e'}) {
436   my $ldap_master=connect_ldap_master();
437   my $ldif = Net::LDAP::LDIF->new($tmp_ldif_file, "r", onerror => 'undef' );
438   while ( not $ldif->eof() ) {
439     my $entry = $ldif->read_entry();
440     if ( $ldif->error() ) {
441       print "Error msg: ",$ldif->error(),"\n";
442       print "Error lines:\n",$ldif->error_lines(),"\n";
443     } else {
444       my $dn = $entry->dn;
445       # we first check if the entry exist
446       my $mesg = $ldap_master->search (
447                                        base => "$dn",
448                                        scope => "base",
449                                        filter => "objectclass=*"
450                                       );
451       $mesg->code;
452       my $nb=$mesg->count;
453       if ($nb == 1 ) {
454         print "entry $dn already exist. ";
455         if ($dn eq $config{sambaUnixIdPooldn}) {
456           print "Updating it...\n";
457           my @mods;
458           foreach my $attr_tmp ($entry->attributes) {
459             push(@mods,$attr_tmp=>[$entry->get_value("$attr_tmp")]);
460           }
461           my $modify = $ldap_master->modify ( "$dn",
462                                               'replace' => { @mods },
463                                             );
464           $modify->code && warn "failed to modify entry: ", $modify->error ;
465         } else {
466           print "\n";
467         }
468       } else {
469         print "adding new entry: $dn\n";
470         my $result=$ldap_master->add($entry);
471         $result->code && warn "failed to add entry: ", $result->error ;
472       }
473     }
474   }
475   $ldap_master->unbind;
476   if (!defined $Options{'i'}) {
477     system "rm -f $tmp_ldif_file";
478   }
479
480   # secure the admin account
481   print "\nPlease provide a password for the domain $adminName: \n";
482   system("$RealBin/smbldap-passwd $adminName");
483
484
485
486 } else {
487   print "exported ldif file: $tmp_ldif_file\n";
488 }
489 exit(0);
490
491
492 ########################################
493
494 =head1 NAME
495
496 smbldap-populate - Populate your LDAP database
497
498 =head1 SYNOPSIS
499
500 smbldap-populate [ldif-file]
501
502 =head1 DESCRIPTION
503
504 The smbldap-populate command helps to populate an LDAP server by adding the necessary entries : base suffix (doesn't abort if already there), organizational units for users, groups and computers, builtin users : Administrator and guest, builtin groups (though posixAccount only, no SambaTNG support).
505
506 -a name
507  Your local administrator login name (default: Administrator)
508
509 -b name
510  Your local guest login name (default: nobody)
511
512 -e file
513  export an ldif file
514
515 -i file
516  import an ldif file (Options -a and -b will be ignored)
517
518 =head1 FILES
519
520        /etc/opt/IDEALX/smbldap-tools/smbldap.conf : main configuration
521        /etc/opt/IDEALX/smbldap-tools/smbldap_bind.conf : credentials for binding to the directory
522
523 =head1 SEE ALSO
524
525        smb.conf(5)
526
527 =cut
528
529 #'
530
531
532
533 # - The End