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