2004-05-03 14:58:08 +00:00
#!/usr/bin/perl -w
use strict ;
2004-10-09 10:11:26 +00:00
use Socket ;
2004-10-03 10:02:41 +00:00
use Getopt::Long ;
2004-05-03 14:58:08 +00:00
2004-10-03 10:02:41 +00:00
my $ opt_hostname = `hostname` ;
chomp $ opt_hostname ;
2004-10-09 10:11:26 +00:00
my $ opt_hostip ;
2004-10-03 10:02:41 +00:00
my $ opt_realm ;
my $ opt_domain ;
my $ opt_adminpass ;
2004-10-03 11:27:31 +00:00
my $ opt_nobody ;
my $ opt_nogroup ;
my $ opt_wheel ;
my $ opt_users ;
2004-10-06 13:57:42 +00:00
my $ dnsdomain ;
2004-10-09 10:11:26 +00:00
my $ netbiosname ;
2004-10-03 10:02:41 +00:00
my $ dnsname ;
my $ basedn ;
2004-10-09 10:11:26 +00:00
my $ defaultsite = "Default-First-Site-Name" ;
2004-05-03 14:58:08 +00:00
# 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 ) ) ;
2004-05-27 06:27:21 +00:00
my $ r6 = int ( rand ( 2 ** 16 ) ) ;
return sprintf ( "%08x-%04x-%04x-%04x-%08x%04x" , $ r1 , $ r2 , $ r3 , $ r4 , $ r5 , $ r6 ) ;
2004-05-03 14:58:08 +00:00
}
2004-10-20 02:13:45 +00:00
my $ opt_domainguid = randguid ( ) ;
2004-10-09 10:11:26 +00:00
my $ hostguid = randguid ( ) ;
2004-07-25 15:09:48 +00:00
2004-05-03 14:58:08 +00:00
sub randsid ()
{
return sprintf ( "S-1-5-21-%d-%d-%d" ,
int ( rand ( 10 ** 8 ) ) , int ( rand ( 10 ** 8 ) ) , int ( rand ( 10 ** 8 ) ) ) ;
}
2004-10-20 02:13:45 +00:00
my $ opt_domainsid = randsid ( ) ;
2004-05-09 00:41:32 +00:00
2004-10-03 10:02:41 +00:00
# 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 ;
}
2004-05-09 00:41:32 +00:00
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 ;
}
2004-05-03 14:58:08 +00:00
#######################
# substitute a single variable
sub substitute ($)
{
my $ var = shift ;
if ( $ var eq "BASEDN" ) {
return $ basedn ;
}
if ( $ var eq "DOMAINSID" ) {
2004-10-20 02:13:45 +00:00
return $ opt_domainsid ;
2004-05-03 14:58:08 +00:00
}
if ( $ var eq "DOMAIN" ) {
2004-10-03 10:02:41 +00:00
return $ opt_domain ;
2004-05-03 14:58:08 +00:00
}
2004-05-27 06:27:21 +00:00
if ( $ var eq "REALM" ) {
2004-10-03 10:02:41 +00:00
return $ opt_realm ;
2004-05-27 06:27:21 +00:00
}
2004-10-06 13:57:42 +00:00
if ( $ var eq "DNSDOMAIN" ) {
return $ dnsdomain ;
}
2004-05-03 14:58:08 +00:00
if ( $ var eq "HOSTNAME" ) {
2004-10-03 10:02:41 +00:00
return $ opt_hostname ;
2004-05-03 14:58:08 +00:00
}
2004-10-09 10:11:26 +00:00
if ( $ var eq "NETBIOSNAME" ) {
return $ netbiosname ;
}
2004-05-03 14:58:08 +00:00
if ( $ var eq "DNSNAME" ) {
return $ dnsname ;
}
2004-10-09 10:11:26 +00:00
if ( $ var eq "HOSTIP" ) {
return $ opt_hostip ;
}
2004-05-03 14:58:08 +00:00
if ( $ var eq "LDAPTIME" ) {
2004-05-09 00:41:32 +00:00
return ldaptime ( ) ;
2004-05-03 14:58:08 +00:00
}
if ( $ var eq "NEWGUID" ) {
return randguid ( ) ;
}
2004-10-09 10:11:26 +00:00
if ( $ var eq "DOMAINGUID" ) {
2004-10-20 02:13:45 +00:00
return $ opt_domainguid ;
2004-10-09 10:11:26 +00:00
}
if ( $ var eq "HOSTGUID" ) {
return $ hostguid ;
}
if ( $ var eq "DEFAULTSITE" ) {
return $ defaultsite ;
}
2004-10-03 10:02:41 +00:00
if ( $ var eq "ADMINPASS" ) {
return $ opt_adminpass ;
}
2004-10-21 07:10:59 +00:00
if ( $ var eq "RANDPASS" ) {
return randpass ( ) ;
}
2004-05-03 14:58:08 +00:00
if ( $ var eq "NTTIME" ) {
return "" . nttime ( ) ;
}
2004-10-03 11:27:31 +00:00
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 ;
}
2004-05-03 14:58:08 +00:00
die "ERROR: Uknown substitution variable $var\n" ;
}
2004-10-03 10:02:41 +00:00
#####################################################################
# 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 ) ;
}
2004-05-03 14:58:08 +00:00
#####################################################################
# 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 ;
}
2004-10-03 10:02:41 +00:00
#######################################################################
# add a foreign security principle
2004-10-03 10:31:12 +00:00
sub add_foreign ($$$)
2004-10-03 10:02:41 +00:00
{
my $ sid = shift ;
my $ desc = shift ;
2004-10-03 10:31:12 +00:00
my $ unixname = shift ;
2004-10-03 10:02:41 +00:00
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 }
2004-10-03 10:31:12 +00:00
unixName: $ unixname
2004-10-03 10:02:41 +00:00
" ;
}
############################################
# show some help
sub ShowHelp ()
{
print "
Samba4 provisioning
provision . pl [ options ]
2004-10-03 11:27:31 +00:00
- - realm REALM set realm
- - domain DOMAIN set domain
- - hostname HOSTNAME set hostname
2004-10-09 10:11:26 +00:00
- - hostip IPADDRESS set ipaddress
2004-10-03 11:27:31 +00:00
- - 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
2004-10-03 10:02:41 +00:00
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 ,
2004-10-20 02:13:45 +00:00
'domain-guid=s' = > \ $ opt_domainguid ,
'domain-sid=s' = > \ $ opt_domainsid ,
2004-10-03 10:02:41 +00:00
'hostname=s' = > \ $ opt_hostname ,
2004-10-09 10:11:26 +00:00
'hostip=s' = > \ $ opt_hostip ,
2004-10-03 10:02:41 +00:00
'adminpass=s' = > \ $ opt_adminpass ,
2004-10-03 11:27:31 +00:00
'nobody=s' = > \ $ opt_nobody ,
'nogroup=s' = > \ $ opt_nogroup ,
'wheel=s' = > \ $ opt_wheel ,
'users=s' = > \ $ opt_users ,
2004-10-03 10:02:41 +00:00
) ;
if ( $ opt_help ||
! $ opt_realm ||
! $ opt_domain ||
! $ opt_hostname ) {
ShowHelp ( ) ;
}
2004-10-06 13:57:42 +00:00
$ opt_realm = uc ( $ opt_realm ) ;
$ opt_domain = uc ( $ opt_domain ) ;
2004-10-09 10:11:26 +00:00
$ 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>" ;
}
}
2004-10-06 13:57:42 +00:00
2004-10-09 10:11:26 +00:00
print "Provisioning host '$opt_hostname'[$opt_hostip] for domain '$opt_domain' in realm '$opt_realm'\n" ;
2004-10-03 10:02:41 +00:00
2004-10-03 11:27:31 +00:00
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" ;
2004-10-03 10:02:41 +00:00
print "generating ldif ...\n" ;
2004-10-06 13:57:42 +00:00
$ dnsdomain = lc ( $ opt_realm ) ;
$ dnsname = lc ( $ opt_hostname ) . "." . $ dnsdomain ;
2004-10-03 10:02:41 +00:00
$ basedn = "DC=" . join ( ",DC=" , split ( /\./ , $ opt_realm ) ) ;
2004-05-03 14:58:08 +00:00
my $ data = FileLoad ( "provision.ldif" ) || die "Unable to load provision.ldif\n" ;
2004-10-03 11:27:31 +00:00
$ data . = add_foreign ( "S-1-5-7" , "Anonymous" , "\${NOBODY}" ) ;
2004-10-12 11:30:48 +00:00
$ data . = add_foreign ( "S-1-1-0" , "World" , "\${NOGROUP}" ) ;
$ data . = add_foreign ( "S-1-5-2" , "Network" , "\${NOGROUP}" ) ;
2004-10-03 10:31:12 +00:00
$ data . = add_foreign ( "S-1-5-18" , "System" , "root" ) ;
2004-10-03 11:27:31 +00:00
$ data . = add_foreign ( "S-1-5-11" , "Authenticated Users" , "\${USERS}" ) ;
2004-10-03 10:02:41 +00:00
if ( ! $ opt_adminpass ) {
$ opt_adminpass = randpass ( ) ;
print "chose random Administrator password '$opt_adminpass'\n" ;
}
2004-05-03 14:58:08 +00:00
my $ res = "" ;
2004-10-03 10:02:41 +00:00
print "applying substitutions ...\n" ;
2004-05-03 14:58:08 +00:00
while ( $ data =~ /(.*?)\$\{(\w*)\}(.*)/s ) {
my $ sub = substitute ( $ 2 ) ;
$ res . = "$1$sub" ;
$ data = $ 3 ;
}
2004-10-03 10:02:41 +00:00
$ 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" ) ;
2004-10-09 10:11:26 +00:00
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 ) ;
2004-10-03 10:02:41 +00:00
print " done
2004-10-09 10:11:26 +00:00
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
2004-10-03 10:02:41 +00:00
" ;