7 my $opt_hostname = `hostname`;
21 my $defaultsite = "Default-First-Site-Name";
22 my $joinpass = randpass();
25 # return the current NTTIME as an integer
29 $t += (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60));
31 return sprintf("%lld", $t);
34 # generate a random guid. Not a good algorithm.
37 my $r1 = int(rand(2**32));
38 my $r2 = int(rand(2**16));
39 my $r3 = int(rand(2**16));
40 my $r4 = int(rand(2**16));
41 my $r5 = int(rand(2**32));
42 my $r6 = int(rand(2**16));
43 return sprintf("%08x-%04x-%04x-%04x-%08x%04x", $r1, $r2, $r3, $r4, $r5, $r6);
46 my $opt_domainguid = randguid();
47 my $hostguid = randguid();
51 return sprintf("S-1-5-21-%d-%d-%d",
52 int(rand(10**8)), int(rand(10**8)), int(rand(10**8)));
55 my $opt_domainsid = randsid();
57 # generate a random password. Poor algorithm :(
61 my $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ%\$!~";
62 for (my $i=0;$i<8;$i++) {
63 my $c = int(rand(length($chars)));
64 $pass .= substr($chars, $c, 1);
71 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = gmtime(time);
72 return sprintf "%04u%02u%02u%02u%02u%02u.0Z",
73 $year+1900, $mon+1, $mday, $hour, $min, $sec;
76 #######################
77 # substitute a single variable
82 if ($var eq "BASEDN") {
86 if ($var eq "DOMAINSID") {
87 return $opt_domainsid;
90 if ($var eq "DOMAIN") {
94 if ($var eq "REALM") {
98 if ($var eq "DNSDOMAIN") {
102 if ($var eq "HOSTNAME") {
103 return $opt_hostname;
106 if ($var eq "NETBIOSNAME") {
110 if ($var eq "DNSNAME") {
114 if ($var eq "HOSTIP") {
118 if ($var eq "LDAPTIME") {
122 if ($var eq "NEWGUID") {
126 if ($var eq "NEWSCHEMAGUID") {
130 if ($var eq "DOMAINGUID") {
131 return $opt_domainguid;
134 if ($var eq "HOSTGUID") {
138 if ($var eq "DEFAULTSITE") {
142 if ($var eq "ADMINPASS") {
143 return $opt_adminpass;
146 if ($var eq "RANDPASS") {
150 if ($var eq "JOINPASS") {
154 if ($var eq "NTTIME") {
155 return "" . nttime();
158 if ($var eq "WHEEL") {
162 if ($var eq "NOBODY") {
166 if ($var eq "NOGROUP") {
170 if ($var eq "USERS") {
180 die "ERROR: Uknown substitution variable $var\n";
183 #####################################################################
184 # write a string into a file
187 my($filename) = shift;
190 open(FILE, ">$filename") || die "can't open $filename";
195 #####################################################################
196 # read a file into a string
199 my($filename) = shift;
201 open(INPUTFILE, $filename) || return undef;
202 my($saved_delim) = $/;
204 my($data) = <INPUTFILE>;
210 #######################################################################
211 # add a foreign security principle
216 my $unixname = shift;
218 dn: CN=$sid,CN=ForeignSecurityPrincipals,\${BASEDN}
220 objectClass: foreignSecurityPrincipal
224 whenCreated: \${LDAPTIME}
225 whenChanged: \${LDAPTIME}
228 showInAdvancedViewOnly: TRUE
230 objectGUID: \${NEWGUID}
232 objectCategory: CN=Foreign-Security-Principal,CN=Schema,CN=Configuration,\${BASEDN}
238 ############################################
245 provision.pl [options]
246 --realm REALM set realm
247 --domain DOMAIN set domain
248 --hostname HOSTNAME set hostname
249 --hostip IPADDRESS set ipaddress
250 --adminpass PASSWORD choose admin password (otherwise random)
251 --nobody USERNAME choose 'nobody' user
252 --nogroup GROUPNAME choose 'nogroup' group
253 --wheel GROUPNAME choose 'wheel' privileged group
254 --users GROUPNAME choose 'users' group
256 You must provide at least a realm and domain
265 'help|h|?' => \$opt_help,
266 'realm=s' => \$opt_realm,
267 'domain=s' => \$opt_domain,
268 'domain-guid=s' => \$opt_domainguid,
269 'domain-sid=s' => \$opt_domainsid,
270 'hostname=s' => \$opt_hostname,
271 'hostip=s' => \$opt_hostip,
272 'adminpass=s' => \$opt_adminpass,
273 'nobody=s' => \$opt_nobody,
274 'nogroup=s' => \$opt_nogroup,
275 'wheel=s' => \$opt_wheel,
276 'users=s' => \$opt_users,
286 $opt_realm=uc($opt_realm);
287 $opt_domain=uc($opt_domain);
288 $opt_hostname=lc($opt_hostname);
289 $netbiosname=uc($opt_hostname);
292 my $hip = gethostbyname($opt_hostname);
294 $opt_hostip = inet_ntoa($hip);
296 $opt_hostip = "<0.0.0.0>";
300 print "Provisioning host '$opt_hostname'[$opt_hostip] for domain '$opt_domain' in realm '$opt_realm'\n";
303 if (defined getpwnam("nobody")) {
304 $opt_nobody = "nobody";
309 if (defined getgrnam("nogroup")) {
310 $opt_nogroup = "nogroup";
311 } elsif (defined getgrnam("nobody")) {
312 $opt_nogroup = "nobody";
317 if (defined getgrnam("wheel")) {
318 $opt_wheel = "wheel";
319 } elsif (defined getgrnam("root")) {
325 if (defined getgrnam("users")) {
326 $opt_users = "users";
330 $opt_nobody || die "Unable to determine a user for 'nobody'\n";
331 $opt_nogroup || die "Unable to determine a group for 'nogroup'\n";
332 $opt_users || die "Unable to determine a group for 'user'\n";
333 $opt_wheel || die "Unable to determine a group for 'wheel'\n";
335 print "Using nobody='$opt_nobody' nogroup='$opt_nogroup' wheel='$opt_wheel' users='$opt_users'\n";
337 print "generating ldif ...\n";
339 $dnsdomain = lc($opt_realm);
340 $dnsname = lc($opt_hostname).".".$dnsdomain;
341 $basedn = "DC=" . join(",DC=", split(/\./, $opt_realm));
343 my $data = FileLoad("provision.ldif") || die "Unable to load provision.ldif\n";
345 $data .= add_foreign("S-1-5-7", "Anonymous", "\${NOBODY}");
346 $data .= add_foreign("S-1-1-0", "World", "\${NOGROUP}");
347 $data .= add_foreign("S-1-5-2", "Network", "\${NOGROUP}");
348 $data .= add_foreign("S-1-5-18", "System", "root");
349 $data .= add_foreign("S-1-5-11", "Authenticated Users", "\${USERS}");
351 if (!$opt_adminpass) {
352 $opt_adminpass = randpass();
353 print "chose random Administrator password '$opt_adminpass'\n";
358 print "applying substitutions ...\n";
360 while ($data =~ /(.*?)\$\{(\w*)\}(.*)/s) {
361 my $sub = substitute($2);
367 print "saving ldif to newsam.ldif ...\n";
369 FileSave("newsam.ldif", $res);
371 unlink("newsam.ldb");
373 print "creating newsam.ldb ...\n";
375 # allow provisioning to be run from the source directory
376 $ENV{"PATH"} .= ":bin";
378 system("ldbadd -H newsam.ldb newsam.ldif");
382 $data = FileLoad("rootdse.ldif") || die "Unable to load rootdse.ldif\n";
386 print "applying substitutions ...\n";
388 while ($data =~ /(.*?)\$\{(\w*)\}(.*)/s) {
389 my $sub = substitute($2);
395 print "saving ldif to newrootdse.ldif ...\n";
397 FileSave("newrootdse.ldif", $res);
399 unlink("newrootdse.ldb");
401 print "creating newrootdse.ldb ...\n";
403 system("ldbadd -H newrootdse.ldb newrootdse.ldif");
407 $data = FileLoad("secrets.ldif") || die "Unable to load secrets.ldif\n";
411 print "applying substitutions ...\n";
413 while ($data =~ /(.*?)\$\{(\w*)\}(.*)/s) {
414 my $sub = substitute($2);
420 print "saving ldif to newsecrets.ldif ...\n";
422 FileSave("newsecrets.ldif", $res);
424 unlink("newsecrets.ldb");
426 print "creating newsecrets.ldb ...\n";
428 system("ldbadd -H newsecrets.ldb newsecrets.ldif");
432 print "generating dns zone file ...\n";
434 $data = FileLoad("provision.zone") || die "Unable to load provision.zone\n";
438 print "applying substitutions ...\n";
440 while ($data =~ /(.*?)\$\{(\w*)\}(.*)/s) {
441 my $sub = substitute($2);
447 print "saving dns zone to newdns.zone ...\n";
449 FileSave("$dnsdomain.zone", $res);
453 unlink("newhklm.ldb");
455 print "creating newhklm.ldb ... \n";
457 system("ldbadd -H newhklm.ldb hklm.ldif");
464 - Please move newsam.ldb to sam.ldb in the private/ directory of your
466 - Please move newrootdse.ldb to rootdse.ldb in the private/ directory
467 of your Samba4 installation
468 - Please move newsecrets.ldb to secrets.ldb in the private/ directory
469 of your Samba4 installation
470 - Please move newhklm.ldb to hklm.ldb in the private/ directory
471 of your Samba4 installation
472 - Please use $dnsdomain.zone to in BIND dns server