7 my $opt_hostname = `hostname`;
24 my $defaultsite = "Default-First-Site-Name";
27 # return the current NTTIME as an integer
31 $t += (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60));
33 return sprintf("%lld", $t);
36 # generate a random guid. Not a good algorithm.
39 my $r1 = int(rand(2**32));
40 my $r2 = int(rand(2**16));
41 my $r3 = int(rand(2**16));
42 my $r4 = int(rand(2**16));
43 my $r5 = int(rand(2**32));
44 my $r6 = int(rand(2**16));
45 return sprintf("%08x-%04x-%04x-%04x-%08x%04x", $r1, $r2, $r3, $r4, $r5, $r6);
48 my $opt_domainguid = randguid();
49 my $opt_hostguid = randguid();
50 my $opt_invocationid = randguid();
54 return sprintf("S-1-5-21-%d-%d-%d",
55 int(rand(10**8)), int(rand(10**8)), int(rand(10**8)));
58 my $opt_domainsid = randsid();
60 # generate a random password. Poor algorithm :(
64 my $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ%\$!~";
65 for (my $i=0;$i<8;$i++) {
66 my $c = int(rand(length($chars)));
67 $pass .= substr($chars, $c, 1);
72 my $joinpass = randpass();
76 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = gmtime(time);
77 return sprintf "%04u%02u%02u%02u%02u%02u.0Z",
78 $year+1900, $mon+1, $mday, $hour, $min, $sec;
81 #######################
82 # substitute a single variable
87 if ($var eq "BASEDN") {
91 if ($var eq "DOMAINSID") {
92 return $opt_domainsid;
95 if ($var eq "DOMAIN") {
99 if ($var eq "REALM") {
103 if ($var eq "DNSDOMAIN") {
107 if ($var eq "HOSTNAME") {
108 return $opt_hostname;
111 if ($var eq "NETBIOSNAME") {
115 if ($var eq "DNSNAME") {
119 if ($var eq "HOSTIP") {
123 if ($var eq "LDAPTIME") {
127 if ($var eq "NEWGUID") {
131 if ($var eq "NEWSCHEMAGUID") {
135 if ($var eq "DOMAINGUID") {
136 return $opt_domainguid;
139 if ($var eq "HOSTGUID") {
140 return $opt_hostguid;
143 if ($var eq "INVOCATIONID") {
144 return $opt_invocationid;
147 if ($var eq "DEFAULTSITE") {
151 if ($var eq "ADMINPASS") {
152 return $opt_adminpass;
155 if ($var eq "RANDPASS") {
159 if ($var eq "JOINPASS") {
163 if ($var eq "NTTIME") {
164 return "" . nttime();
167 if ($var eq "WHEEL") {
171 if ($var eq "NOBODY") {
175 if ($var eq "ROOT") {
179 if ($var eq "NOGROUP") {
183 if ($var eq "USERS") {
193 die "ERROR: Uknown substitution variable $var\n";
197 ####################################################################
198 # substitute all variables in a string
199 sub apply_substitutions($)
203 while ($data =~ /(.*?)\$\{(\w*)\}(.*)/s) {
204 my $sub = substitute($2);
213 #####################################################################
214 # write a string into a file
217 my($filename) = shift;
220 open(FILE, ">$filename") || die "can't open $filename";
225 #####################################################################
226 # read a file into a string
229 my($filename) = shift;
231 open(INPUTFILE, $filename) || return undef;
232 my($saved_delim) = $/;
234 my($data) = <INPUTFILE>;
240 #######################################################################
241 # add a foreign security principle
246 my $unixname = shift;
248 dn: CN=$sid,CN=ForeignSecurityPrincipals,\${BASEDN}
250 objectClass: foreignSecurityPrincipal
254 whenCreated: \${LDAPTIME}
255 whenChanged: \${LDAPTIME}
258 showInAdvancedViewOnly: TRUE
260 objectGUID: \${NEWGUID}
262 objectCategory: CN=Foreign-Security-Principal,CN=Schema,CN=Configuration,\${BASEDN}
268 ############################################
275 provision.pl [options]
276 --realm REALM set realm
277 --domain DOMAIN set domain
278 --domain-guid GUID set domainguid (otherwise random)
279 --domain-sid SID set domainsid (otherwise random)
280 --host-name HOSTNAME set hostname
281 --host-ip IPADDRESS set ipaddress
282 --host-guid GUID set hostguid (otherwise random)
283 --invocationid GUID set invocationid (otherwise random)
284 --outputdir OUTPUTDIR set output directory
285 --adminpass PASSWORD choose admin password (otherwise random)
286 --root USERNAME choose 'root' unix username
287 --nobody USERNAME choose 'nobody' user
288 --nogroup GROUPNAME choose 'nogroup' group
289 --wheel GROUPNAME choose 'wheel' privileged group
290 --users GROUPNAME choose 'users' group
293 You must provide at least a realm and domain
302 'help|h|?' => \$opt_help,
303 'realm=s' => \$opt_realm,
304 'domain=s' => \$opt_domain,
305 'domain-guid=s' => \$opt_domainguid,
306 'domain-sid=s' => \$opt_domainsid,
307 'host-name=s' => \$opt_hostname,
308 'host-ip=s' => \$opt_hostip,
309 'host-guid=s' => \$opt_hostguid,
310 'invocationid=s' => \$opt_invocationid,
311 'adminpass=s' => \$opt_adminpass,
312 'root=s' => \$opt_root,
313 'nobody=s' => \$opt_nobody,
314 'nogroup=s' => \$opt_nogroup,
315 'wheel=s' => \$opt_wheel,
316 'users=s' => \$opt_users,
317 'outputdir=s' => \$opt_outputdir,
318 'quiet' => \$opt_quiet
328 $opt_realm=uc($opt_realm);
329 $opt_domain=uc($opt_domain);
330 $opt_hostname=lc($opt_hostname);
331 $netbiosname=uc($opt_hostname);
334 my $hip = gethostbyname($opt_hostname);
336 $opt_hostip = inet_ntoa($hip);
338 $opt_hostip = "<0.0.0.0>";
342 $opt_quiet or print "Provisioning host '$opt_hostname'[$opt_hostip] for domain '$opt_domain' in realm '$opt_realm'\n";
349 if (defined getpwnam("nobody")) {
350 $opt_nobody = "nobody";
355 if (defined getgrnam("nogroup")) {
356 $opt_nogroup = "nogroup";
357 } elsif (defined getgrnam("nobody")) {
358 $opt_nogroup = "nobody";
363 if (defined getgrnam("wheel")) {
364 $opt_wheel = "wheel";
365 } elsif (defined getgrnam("root")) {
371 if (defined getgrnam("users")) {
372 $opt_users = "users";
376 $opt_nobody || die "Unable to determine a user for 'nobody'\n";
377 $opt_nogroup || die "Unable to determine a group for 'nogroup'\n";
378 $opt_users || die "Unable to determine a group for 'users'\n";
379 $opt_wheel || die "Unable to determine a group for 'wheel'\n";
381 $opt_quiet or print "Using nobody='$opt_nobody' nogroup='$opt_nogroup' wheel='$opt_wheel' users='$opt_users'\n";
383 $opt_quiet or print "generating ldif ...\n";
385 $dnsdomain = lc($opt_realm);
386 $dnsname = lc($opt_hostname).".".$dnsdomain;
387 $basedn = "DC=" . join(",DC=", split(/\./, $opt_realm));
389 my $data = FileLoad("setup/provision.ldif") || die "Unable to load provision.ldif\n";
391 $data .= add_foreign("S-1-5-7", "Anonymous", "\${NOBODY}");
392 $data .= add_foreign("S-1-1-0", "World", "\${NOGROUP}");
393 $data .= add_foreign("S-1-5-2", "Network", "\${NOGROUP}");
394 $data .= add_foreign("S-1-5-18", "System", "\${ROOT}");
395 $data .= add_foreign("S-1-5-11", "Authenticated Users", "\${USERS}");
397 if (!$opt_adminpass) {
398 $opt_adminpass = randpass();
399 print "chose random Administrator password '$opt_adminpass'\n";
402 # allow provisioning to be run from the source directory
403 $ENV{"PATH"} .= ":bin:../bin";
406 my $res = apply_substitutions($data);
408 my $newdb = $opt_outputdir;
411 $newdb = "newdb." . int(rand(1000));
414 $opt_quiet or print "Putting new database files in $newdb\n";
416 unless ($opt_outputdir) {
417 mkdir($newdb, 0755) || die "Unable to create temporary directory $newdb\n";
420 FileSave("$newdb/sam.ldif", $res);
422 $opt_quiet or print "creating $newdb/sam.ldb ...\n";
424 system("ldbadd -H $newdb/sam.ldb $newdb/sam.ldif") == 0 || die "Failed to create sam.ldb\n";
426 $data = FileLoad("setup/rootdse.ldif") || die "Unable to load rootdse.ldif\n";
428 $res = apply_substitutions($data);
430 FileSave("$newdb/rootdse.ldif", $res);
432 $opt_quiet or print "creating $newdb/rootdse.ldb ...\n";
434 system("ldbadd -H $newdb/rootdse.ldb $newdb/rootdse.ldif") == 0 || die "Failed to create rootdse.ldb\n";
436 $data = FileLoad("setup/secrets.ldif") || die "Unable to load secrets.ldif\n";
438 $res = apply_substitutions($data);
440 FileSave("$newdb/secrets.ldif", $res);
442 $opt_quiet or print "creating $newdb/secrets.ldb ...\n";
444 system("ldbadd -H $newdb/secrets.ldb $newdb/secrets.ldif") == 0 || die "Failed to create secrets.ldb\n";
446 $data = FileLoad("setup/provision.zone") || die "Unable to load provision.zone\n";
448 $res = apply_substitutions($data);
450 $opt_quiet or print "saving dns zone to $newdb/$dnsdomain.zone ...\n";
452 FileSave("$newdb/$dnsdomain.zone", $res);
454 $data = FileLoad("setup/provision.smb.conf") || die "Unable to load provision.smb.conf\n";
456 $res = apply_substitutions($data);
458 $opt_quiet or print "saving smb.conf to $newdb/smb.conf ...\n";
460 FileSave("$newdb/smb.conf", $res);
462 $opt_quiet or print "creating $newdb/hklm.ldb ... \n";
464 system("ldbadd -H $newdb/hklm.ldb setup/hklm.ldif") == 0 || die "Failed to create hklm.ldb\n";
466 $opt_quiet or print "
469 - Please move $newdb/*.ldb to the private/ directory of your
471 - Please move $newdb/smb.conf to the lib/ directory of your
473 - Please use $newdb/$dnsdomain.zone in BIND on your dns server