mirror of
https://github.com/samba-team/samba.git
synced 2025-03-10 12:58:35 +03:00
- add some stuff to make w2k3 dc join to get the correct values metze (This used to be commit d1490635622023f5c672eea70260265960ac48b6)
488 lines
9.8 KiB
Perl
Executable File
488 lines
9.8 KiB
Perl
Executable File
#!/usr/bin/perl -w
|
|
|
|
use strict;
|
|
use Socket;
|
|
use Getopt::Long;
|
|
|
|
my $opt_hostname = `hostname`;
|
|
chomp $opt_hostname;
|
|
my $opt_hostip;
|
|
my $opt_realm;
|
|
my $opt_domain;
|
|
my $opt_adminpass;
|
|
my $opt_nobody;
|
|
my $opt_nogroup;
|
|
my $opt_wheel;
|
|
my $opt_users;
|
|
my $dnsdomain;
|
|
my $netbiosname;
|
|
my $dnsname;
|
|
my $basedn;
|
|
my $defaultsite = "Default-First-Site-Name";
|
|
my $usn = 1;
|
|
|
|
# return the current NTTIME as an integer
|
|
sub nttime()
|
|
{
|
|
my $t = time();
|
|
$t += (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60));
|
|
$t *= 1.0e7;
|
|
return sprintf("%lld", $t);
|
|
}
|
|
|
|
# generate a random guid. Not a good algorithm.
|
|
sub randguid()
|
|
{
|
|
my $r1 = int(rand(2**32));
|
|
my $r2 = int(rand(2**16));
|
|
my $r3 = int(rand(2**16));
|
|
my $r4 = int(rand(2**16));
|
|
my $r5 = int(rand(2**32));
|
|
my $r6 = int(rand(2**16));
|
|
return sprintf("%08x-%04x-%04x-%04x-%08x%04x", $r1, $r2, $r3, $r4, $r5, $r6);
|
|
}
|
|
|
|
my $opt_domainguid = randguid();
|
|
my $opt_hostguid = randguid();
|
|
my $opt_invocationid = randguid();
|
|
|
|
sub randsid()
|
|
{
|
|
return sprintf("S-1-5-21-%d-%d-%d",
|
|
int(rand(10**8)), int(rand(10**8)), int(rand(10**8)));
|
|
}
|
|
|
|
my $opt_domainsid = randsid();
|
|
|
|
# generate a random password. Poor algorithm :(
|
|
sub randpass()
|
|
{
|
|
my $pass = "";
|
|
my $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ%\$!~";
|
|
for (my $i=0;$i<8;$i++) {
|
|
my $c = int(rand(length($chars)));
|
|
$pass .= substr($chars, $c, 1);
|
|
}
|
|
return $pass;
|
|
}
|
|
|
|
my $joinpass = randpass();
|
|
|
|
sub ldaptime()
|
|
{
|
|
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = gmtime(time);
|
|
return sprintf "%04u%02u%02u%02u%02u%02u.0Z",
|
|
$year+1900, $mon+1, $mday, $hour, $min, $sec;
|
|
}
|
|
|
|
#######################
|
|
# substitute a single variable
|
|
sub substitute($)
|
|
{
|
|
my $var = shift;
|
|
|
|
if ($var eq "BASEDN") {
|
|
return $basedn;
|
|
}
|
|
|
|
if ($var eq "DOMAINSID") {
|
|
return $opt_domainsid;
|
|
}
|
|
|
|
if ($var eq "DOMAIN") {
|
|
return $opt_domain;
|
|
}
|
|
|
|
if ($var eq "REALM") {
|
|
return $opt_realm;
|
|
}
|
|
|
|
if ($var eq "DNSDOMAIN") {
|
|
return $dnsdomain;
|
|
}
|
|
|
|
if ($var eq "HOSTNAME") {
|
|
return $opt_hostname;
|
|
}
|
|
|
|
if ($var eq "NETBIOSNAME") {
|
|
return $netbiosname;
|
|
}
|
|
|
|
if ($var eq "DNSNAME") {
|
|
return $dnsname;
|
|
}
|
|
|
|
if ($var eq "HOSTIP") {
|
|
return $opt_hostip;
|
|
}
|
|
|
|
if ($var eq "LDAPTIME") {
|
|
return ldaptime();
|
|
}
|
|
|
|
if ($var eq "NEWGUID") {
|
|
return randguid();
|
|
}
|
|
|
|
if ($var eq "NEWSCHEMAGUID") {
|
|
return randguid();
|
|
}
|
|
|
|
if ($var eq "DOMAINGUID") {
|
|
return $opt_domainguid;
|
|
}
|
|
|
|
if ($var eq "HOSTGUID") {
|
|
return $opt_hostguid;
|
|
}
|
|
|
|
if ($var eq "INVOCATIONID") {
|
|
return $opt_invocationid;
|
|
}
|
|
|
|
if ($var eq "DEFAULTSITE") {
|
|
return $defaultsite;
|
|
}
|
|
|
|
if ($var eq "ADMINPASS") {
|
|
return $opt_adminpass;
|
|
}
|
|
|
|
if ($var eq "RANDPASS") {
|
|
return randpass();
|
|
}
|
|
|
|
if ($var eq "JOINPASS") {
|
|
return $joinpass;
|
|
}
|
|
|
|
if ($var eq "NTTIME") {
|
|
return "" . nttime();
|
|
}
|
|
|
|
if ($var eq "WHEEL") {
|
|
return $opt_wheel;
|
|
}
|
|
|
|
if ($var eq "NOBODY") {
|
|
return $opt_nobody;
|
|
}
|
|
|
|
if ($var eq "NOGROUP") {
|
|
return $opt_nogroup;
|
|
}
|
|
|
|
if ($var eq "USERS") {
|
|
return $opt_users;
|
|
}
|
|
|
|
if ($var eq "USN") {
|
|
my $ret = $usn;
|
|
$usn = $ret + 1;
|
|
return $ret;
|
|
}
|
|
|
|
die "ERROR: Uknown substitution variable $var\n";
|
|
}
|
|
|
|
#####################################################################
|
|
# write a string into a file
|
|
sub FileSave($$)
|
|
{
|
|
my($filename) = shift;
|
|
my($v) = shift;
|
|
local(*FILE);
|
|
open(FILE, ">$filename") || die "can't open $filename";
|
|
print FILE $v;
|
|
close(FILE);
|
|
}
|
|
|
|
#####################################################################
|
|
# read a file into a string
|
|
sub FileLoad($)
|
|
{
|
|
my($filename) = shift;
|
|
local(*INPUTFILE);
|
|
open(INPUTFILE, $filename) || return undef;
|
|
my($saved_delim) = $/;
|
|
undef $/;
|
|
my($data) = <INPUTFILE>;
|
|
close(INPUTFILE);
|
|
$/ = $saved_delim;
|
|
return $data;
|
|
}
|
|
|
|
#######################################################################
|
|
# add a foreign security principle
|
|
sub add_foreign($$$)
|
|
{
|
|
my $sid = shift;
|
|
my $desc = shift;
|
|
my $unixname = shift;
|
|
return "
|
|
dn: CN=$sid,CN=ForeignSecurityPrincipals,\${BASEDN}
|
|
objectClass: top
|
|
objectClass: foreignSecurityPrincipal
|
|
cn: $sid
|
|
description: $desc
|
|
instanceType: 4
|
|
whenCreated: \${LDAPTIME}
|
|
whenChanged: \${LDAPTIME}
|
|
uSNCreated: 1
|
|
uSNChanged: 1
|
|
showInAdvancedViewOnly: TRUE
|
|
name: $sid
|
|
objectGUID: \${NEWGUID}
|
|
objectSid: $sid
|
|
objectCategory: CN=Foreign-Security-Principal,CN=Schema,CN=Configuration,\${BASEDN}
|
|
unixName: $unixname
|
|
|
|
";
|
|
}
|
|
|
|
############################################
|
|
# show some help
|
|
sub ShowHelp()
|
|
{
|
|
print "
|
|
Samba4 provisioning
|
|
|
|
provision.pl [options]
|
|
--realm REALM set realm
|
|
--domain DOMAIN set domain
|
|
--domain-guid GUID set domainguid (otherwise random)
|
|
--domain-sid SID set domainsid (otherwise random)
|
|
--host-name HOSTNAME set hostname
|
|
--host-ip IPADDRESS set ipaddress
|
|
--host-guid GUID set hostguid (otherwise random)
|
|
--invocationid GUID set invocationid (otherwise random)
|
|
--adminpass PASSWORD choose admin password (otherwise random)
|
|
--nobody USERNAME choose 'nobody' user
|
|
--nogroup GROUPNAME choose 'nogroup' group
|
|
--wheel GROUPNAME choose 'wheel' privileged group
|
|
--users GROUPNAME choose 'users' group
|
|
|
|
You must provide at least a realm and domain
|
|
|
|
";
|
|
exit(1);
|
|
}
|
|
|
|
my $opt_help;
|
|
|
|
GetOptions(
|
|
'help|h|?' => \$opt_help,
|
|
'realm=s' => \$opt_realm,
|
|
'domain=s' => \$opt_domain,
|
|
'domain-guid=s' => \$opt_domainguid,
|
|
'domain-sid=s' => \$opt_domainsid,
|
|
'host-name=s' => \$opt_hostname,
|
|
'host-ip=s' => \$opt_hostip,
|
|
'host-guid=s' => \$opt_hostguid,
|
|
'invocationid=s' => \$opt_invocationid,
|
|
'adminpass=s' => \$opt_adminpass,
|
|
'nobody=s' => \$opt_nobody,
|
|
'nogroup=s' => \$opt_nogroup,
|
|
'wheel=s' => \$opt_wheel,
|
|
'users=s' => \$opt_users,
|
|
);
|
|
|
|
if ($opt_help ||
|
|
!$opt_realm ||
|
|
!$opt_domain ||
|
|
!$opt_hostname) {
|
|
ShowHelp();
|
|
}
|
|
|
|
$opt_realm=uc($opt_realm);
|
|
$opt_domain=uc($opt_domain);
|
|
$opt_hostname=lc($opt_hostname);
|
|
$netbiosname=uc($opt_hostname);
|
|
|
|
if (!$opt_hostip) {
|
|
my $hip = gethostbyname($opt_hostname);
|
|
if (defined $hip) {
|
|
$opt_hostip = inet_ntoa($hip);
|
|
} else {
|
|
$opt_hostip = "<0.0.0.0>";
|
|
}
|
|
}
|
|
|
|
print "Provisioning host '$opt_hostname'[$opt_hostip] for domain '$opt_domain' in realm '$opt_realm'\n";
|
|
|
|
if (!$opt_nobody) {
|
|
if (defined getpwnam("nobody")) {
|
|
$opt_nobody = "nobody";
|
|
}
|
|
}
|
|
|
|
if (!$opt_nogroup) {
|
|
if (defined getgrnam("nogroup")) {
|
|
$opt_nogroup = "nogroup";
|
|
} elsif (defined getgrnam("nobody")) {
|
|
$opt_nogroup = "nobody";
|
|
}
|
|
}
|
|
|
|
if (!$opt_wheel) {
|
|
if (defined getgrnam("wheel")) {
|
|
$opt_wheel = "wheel";
|
|
} elsif (defined getgrnam("root")) {
|
|
$opt_wheel = "root";
|
|
}
|
|
}
|
|
|
|
if (!$opt_users) {
|
|
if (defined getgrnam("users")) {
|
|
$opt_users = "users";
|
|
}
|
|
}
|
|
|
|
$opt_nobody || die "Unable to determine a user for 'nobody'\n";
|
|
$opt_nogroup || die "Unable to determine a group for 'nogroup'\n";
|
|
$opt_users || die "Unable to determine a group for 'user'\n";
|
|
$opt_wheel || die "Unable to determine a group for 'wheel'\n";
|
|
|
|
print "Using nobody='$opt_nobody' nogroup='$opt_nogroup' wheel='$opt_wheel' users='$opt_users'\n";
|
|
|
|
print "generating ldif ...\n";
|
|
|
|
$dnsdomain = lc($opt_realm);
|
|
$dnsname = lc($opt_hostname).".".$dnsdomain;
|
|
$basedn = "DC=" . join(",DC=", split(/\./, $opt_realm));
|
|
|
|
my $data = FileLoad("provision.ldif") || die "Unable to load provision.ldif\n";
|
|
|
|
$data .= add_foreign("S-1-5-7", "Anonymous", "\${NOBODY}");
|
|
$data .= add_foreign("S-1-1-0", "World", "\${NOGROUP}");
|
|
$data .= add_foreign("S-1-5-2", "Network", "\${NOGROUP}");
|
|
$data .= add_foreign("S-1-5-18", "System", "root");
|
|
$data .= add_foreign("S-1-5-11", "Authenticated Users", "\${USERS}");
|
|
|
|
if (!$opt_adminpass) {
|
|
$opt_adminpass = randpass();
|
|
print "chose random Administrator password '$opt_adminpass'\n";
|
|
}
|
|
|
|
my $res = "";
|
|
|
|
print "applying substitutions ...\n";
|
|
|
|
while ($data =~ /(.*?)\$\{(\w*)\}(.*)/s) {
|
|
my $sub = substitute($2);
|
|
$res .= "$1$sub";
|
|
$data = $3;
|
|
}
|
|
$res .= $data;
|
|
|
|
print "saving ldif to newsam.ldif ...\n";
|
|
|
|
FileSave("newsam.ldif", $res);
|
|
|
|
unlink("newsam.ldb");
|
|
|
|
print "creating newsam.ldb ...\n";
|
|
|
|
# allow provisioning to be run from the source directory
|
|
$ENV{"PATH"} .= ":bin";
|
|
|
|
system("ldbadd -H newsam.ldb newsam.ldif");
|
|
|
|
print "done\n";
|
|
|
|
$data = FileLoad("rootdse.ldif") || die "Unable to load rootdse.ldif\n";
|
|
|
|
$res = "";
|
|
|
|
print "applying substitutions ...\n";
|
|
|
|
while ($data =~ /(.*?)\$\{(\w*)\}(.*)/s) {
|
|
my $sub = substitute($2);
|
|
$res .= "$1$sub";
|
|
$data = $3;
|
|
}
|
|
$res .= $data;
|
|
|
|
print "saving ldif to newrootdse.ldif ...\n";
|
|
|
|
FileSave("newrootdse.ldif", $res);
|
|
|
|
unlink("newrootdse.ldb");
|
|
|
|
print "creating newrootdse.ldb ...\n";
|
|
|
|
system("ldbadd -H newrootdse.ldb newrootdse.ldif");
|
|
|
|
print "done\n";
|
|
|
|
$data = FileLoad("secrets.ldif") || die "Unable to load secrets.ldif\n";
|
|
|
|
$res = "";
|
|
|
|
print "applying substitutions ...\n";
|
|
|
|
while ($data =~ /(.*?)\$\{(\w*)\}(.*)/s) {
|
|
my $sub = substitute($2);
|
|
$res .= "$1$sub";
|
|
$data = $3;
|
|
}
|
|
$res .= $data;
|
|
|
|
print "saving ldif to newsecrets.ldif ...\n";
|
|
|
|
FileSave("newsecrets.ldif", $res);
|
|
|
|
unlink("newsecrets.ldb");
|
|
|
|
print "creating newsecrets.ldb ...\n";
|
|
|
|
system("ldbadd -H newsecrets.ldb newsecrets.ldif");
|
|
|
|
print "done\n";
|
|
|
|
print "generating dns zone file ...\n";
|
|
|
|
$data = FileLoad("provision.zone") || die "Unable to load provision.zone\n";
|
|
|
|
$res = "";
|
|
|
|
print "applying substitutions ...\n";
|
|
|
|
while ($data =~ /(.*?)\$\{(\w*)\}(.*)/s) {
|
|
my $sub = substitute($2);
|
|
$res .= "$1$sub";
|
|
$data = $3;
|
|
}
|
|
$res .= $data;
|
|
|
|
print "saving dns zone to newdns.zone ...\n";
|
|
|
|
FileSave("$dnsdomain.zone", $res);
|
|
|
|
print "done\n";
|
|
|
|
unlink("newhklm.ldb");
|
|
|
|
print "creating newhklm.ldb ... \n";
|
|
|
|
system("ldbadd -H newhklm.ldb hklm.ldif");
|
|
|
|
print "done\n";
|
|
|
|
print "
|
|
|
|
Installation:
|
|
- Please move newsam.ldb to sam.ldb in the private/ directory of your
|
|
Samba4 installation
|
|
- Please move newrootdse.ldb to rootdse.ldb in the private/ directory
|
|
of your Samba4 installation
|
|
- Please move newsecrets.ldb to secrets.ldb in the private/ directory
|
|
of your Samba4 installation
|
|
- Please move newhklm.ldb to hklm.ldb in the private/ directory
|
|
of your Samba4 installation
|
|
- Please use $dnsdomain.zone to in BIND dns server
|
|
";
|
|
|
|
|