1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-12 09:18:10 +03:00
samba-mirror/source4/script/provision.pl
2007-10-10 13:02:22 -05:00

393 lines
8.0 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";
# 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 $hostguid = 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;
}
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 "DOMAINGUID") {
return $opt_domainguid;
}
if ($var eq "HOSTGUID") {
return $hostguid;
}
if ($var eq "DEFAULTSITE") {
return $defaultsite;
}
if ($var eq "ADMINPASS") {
return $opt_adminpass;
}
if ($var eq "RANDPASS") {
return randpass();
}
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;
}
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
distinguishedName: CN=$sid,CN=ForeignSecurityPrincipals,\${BASEDN}
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
--hostname HOSTNAME set hostname
--hostip IPADDRESS set ipaddress
--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,
'hostname=s' => \$opt_hostname,
'hostip=s' => \$opt_hostip,
'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";
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
Installation:
- Please move newsam.ldb to sam.ldb in the lib/private/ directory of your
Samba4 installation
- Please use $dnsdomain.zone to in BIND dns server
";