2005-07-12 15:46:34 +04:00
/ *
backend code for provisioning a Samba4 server
Copyright Andrew Tridgell 2005
Released under the GNU GPL v2 or later
* /
/* used to generate sequence numbers for records */
provision _next _usn = 1 ;
2005-07-15 11:45:40 +04:00
sys = sys _init ( ) ;
2005-07-12 15:46:34 +04:00
/ *
find a user or group from a list of possibilities
* /
function findnss ( )
{
var i ;
assert ( arguments . length >= 2 ) ;
var nssfn = arguments [ 0 ] ;
for ( i = 1 ; i < arguments . length ; i ++ ) {
if ( nssfn ( arguments [ i ] ) != undefined ) {
return arguments [ i ] ;
}
}
printf ( "Unable to find user/group for %s\n" , arguments [ 1 ] ) ;
assert ( i < arguments . length ) ;
}
/ *
add a foreign security principle
* /
function add _foreign ( str , sid , desc , unixname )
{
var add = "
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 }
" ;
var sub = new Object ( ) ;
sub . SID = sid ;
sub . DESC = desc ;
sub . UNIXNAME = unixname ;
return str + substitute _var ( add , sub ) ;
}
/ *
return current time as a nt time string
* /
function nttime ( )
{
2005-07-15 11:45:40 +04:00
return "" + sys . nttime ( ) ;
2005-07-12 15:46:34 +04:00
}
/ *
return current time as a ldap time string
* /
function ldaptime ( )
{
2005-07-15 11:45:40 +04:00
return sys . ldaptime ( sys . nttime ( ) ) ;
2005-07-12 15:46:34 +04:00
}
/ *
return a date string suitable for a dns zone serial number
* /
function datestring ( )
{
2005-07-15 11:45:40 +04:00
var t = sys . gmtime ( sys . nttime ( ) ) ;
2005-07-12 15:46:34 +04:00
return sprintf ( "%04u%02u%02u%02u" ,
t . tm _year + 1900 , t . tm _mon + 1 , t . tm _mday , t . tm _hour ) ;
}
/ *
return first host IP
* /
function hostip ( )
{
2005-07-15 11:45:40 +04:00
var list = sys . interfaces ( ) ;
2005-07-12 15:46:34 +04:00
return list [ 0 ] ;
}
/ *
return current time as a ldap time string
* /
function nextusn ( )
{
provision _next _usn = provision _next _usn + 1 ;
return provision _next _usn ;
}
/ *
return first part of hostname
* /
function hostname ( )
{
2005-07-15 11:45:40 +04:00
var s = split ( "." , sys . hostname ( ) ) ;
2005-07-12 15:46:34 +04:00
return s [ 0 ] ;
}
/ *
setup a ldb in the private dir
* /
function setup _ldb ( ldif , dbname , subobj )
{
var extra = "" ;
2005-07-15 09:40:34 +04:00
var ldb = ldb _init ( ) ;
2005-07-12 15:46:34 +04:00
if ( arguments . length == 4 ) {
extra = arguments [ 3 ] ;
}
2005-07-15 13:23:23 +04:00
var dbfile = lpGet ( "private dir" ) + "/" + dbname ;
2005-07-12 15:46:34 +04:00
var src = lpGet ( "setup directory" ) + "/" + ldif ;
2005-07-15 13:23:23 +04:00
sys . unlink ( dbfile ) ;
2005-07-12 15:46:34 +04:00
2005-07-15 11:45:40 +04:00
var data = sys . file _load ( src ) ;
2005-07-12 15:46:34 +04:00
data = data + extra ;
data = substitute _var ( data , subobj ) ;
2005-07-15 15:10:38 +04:00
var ok = ldb . connect ( dbfile ) ;
assert ( ok ) ;
2005-07-15 13:23:23 +04:00
2005-07-15 15:10:38 +04:00
ok = ldb . add ( data ) ;
2005-07-12 15:46:34 +04:00
assert ( ok ) ;
}
/ *
setup a file in the private dir
* /
function setup _file ( template , fname , subobj )
{
var f = lpGet ( "private dir" ) + "/" + fname ;
var src = lpGet ( "setup directory" ) + "/" + template ;
2005-07-15 11:45:40 +04:00
sys . unlink ( f ) ;
2005-07-12 15:46:34 +04:00
2005-07-15 11:45:40 +04:00
var data = sys . file _load ( src ) ;
2005-07-12 15:46:34 +04:00
data = substitute _var ( data , subobj ) ;
2005-07-15 11:45:40 +04:00
ok = sys . file _save ( f , data ) ;
2005-07-12 15:46:34 +04:00
assert ( ok ) ;
}
/ *
provision samba4 - caution , this wipes all existing data !
* /
function provision ( subobj , message )
{
var data = "" ;
/ *
some options need to be upper / lower case
* /
subobj . REALM = strlower ( subobj . REALM ) ;
subobj . HOSTNAME = strlower ( subobj . HOSTNAME ) ;
subobj . DOMAIN = strupper ( subobj . DOMAIN ) ;
subobj . NETBIOSNAME = strupper ( subobj . HOSTNAME ) ;
data = add _foreign ( data , "S-1-5-7" , "Anonymous" , "${NOBODY}" ) ;
data = add _foreign ( data , "S-1-1-0" , "World" , "${NOGROUP}" ) ;
data = add _foreign ( data , "S-1-5-2" , "Network" , "${NOGROUP}" ) ;
data = add _foreign ( data , "S-1-5-18" , "System" , "${ROOT}" ) ;
data = add _foreign ( data , "S-1-5-11" , "Authenticated Users" , "${USERS}" ) ;
provision _next _usn = 1 ;
message ( "Setting up hklm.ldb\n" ) ;
setup _ldb ( "hklm.ldif" , "hklm.ldb" , subobj ) ;
message ( "Setting up sam.ldb\n" ) ;
setup _ldb ( "provision.ldif" , "sam.ldb" , subobj , data ) ;
message ( "Setting up rootdse.ldb\n" ) ;
setup _ldb ( "rootdse.ldif" , "rootdse.ldb" , subobj ) ;
message ( "Setting up secrets.ldb\n" ) ;
setup _ldb ( "secrets.ldif" , "secrets.ldb" , subobj ) ;
message ( "Setting up DNS zone file\n" ) ;
setup _file ( "provision.zone" , subobj . DNSDOMAIN + ".zone" , subobj ) ;
}
/ *
guess reasonably default options for provisioning
* /
function provision _guess ( )
{
var subobj = new Object ( ) ;
subobj . REALM = lpGet ( "realm" ) ;
subobj . DOMAIN = lpGet ( "workgroup" ) ;
subobj . HOSTNAME = hostname ( ) ;
subobj . HOSTIP = hostip ( ) ;
subobj . DOMAINGUID = randguid ( ) ;
subobj . DOMAINSID = randsid ( ) ;
subobj . HOSTGUID = randguid ( ) ;
subobj . INVOCATIONID = randguid ( ) ;
subobj . KRBTGTPASS = randpass ( 12 ) ;
subobj . MACHINEPASS = randpass ( 12 ) ;
subobj . ADMINPASS = randpass ( 12 ) ;
subobj . DEFAULTSITE = "Default-First-Site-Name" ;
subobj . NEWGUID = randguid ;
subobj . NTTIME = nttime ;
subobj . LDAPTIME = ldaptime ;
subobj . DATESTRING = datestring ;
subobj . USN = nextusn ;
subobj . ROOT = findnss ( getpwnam , "root" ) ;
subobj . NOBODY = findnss ( getpwnam , "nobody" ) ;
2005-07-14 07:10:17 +04:00
subobj . NOGROUP = findnss ( getgrnam , "nogroup" , "nobody" ) ;
2005-07-12 15:46:34 +04:00
subobj . WHEEL = findnss ( getgrnam , "wheel" , "root" ) ;
subobj . USERS = findnss ( getgrnam , "users" , "guest" , "other" ) ;
subobj . DNSDOMAIN = strlower ( subobj . REALM ) ;
subobj . DNSNAME = sprintf ( "%s.%s" ,
strlower ( subobj . HOSTNAME ) ,
subobj . DNSDOMAIN ) ;
subobj . BASEDN = "DC=" + join ( ",DC=" , split ( "." , subobj . REALM ) ) ;
return subobj ;
}
2005-07-19 03:58:18 +04:00
/ *
search for one attribute as a string
* /
function searchone ( ldb , expression , attribute )
{
var attrs = new Array ( attribute ) ;
res = ldb . search ( expression , attrs ) ;
if ( res . length != 1 ||
res [ 0 ] [ attribute ] == undefined ) {
return undefined ;
}
return res [ 0 ] [ attribute ] ;
}
/ *
add a new user record
* /
function newuser ( username , unixname , password , message )
{
var samdb = lpGet ( "sam database" ) ;
var ldb = ldb _init ( ) ;
/* connect to the sam */
var ok = ldb . connect ( samdb ) ;
assert ( ok ) ;
/* find the DNs for the domain and the domain users group */
var domain _dn = searchone ( ldb , "objectClass=domainDNS" , "dn" ) ;
assert ( domain _dn != undefined ) ;
var dom _users = searchone ( ldb , "name=Domain Users" , "dn" ) ;
assert ( dom _users != undefined ) ;
var user _dn = sprintf ( "CN=%s,CN=Users,%s" , username , domain _dn ) ;
/ *
the new user record . note the reliance on the samdb module to fill
in a sid , guid etc
* /
var ldif = sprintf ( "
dn : % s
sAMAccountName : % s
name : % s
memberOf : % s
unixName : % s
objectGUID : % s
unicodePwd : % s
objectClass : user
" ,
user _dn , username , username , dom _users ,
unixname , randguid ( ) , password ) ;
/ *
add the user to the users group as well
* /
var modgroup = sprintf ( "
dn : % s
changetype : modify
add : member
member : % s
" ,
dom _users , user _dn ) ;
/ *
now the real work
* /
message ( "Adding user %s\n" , user _dn ) ;
ok = ldb . add ( ldif ) ;
if ( ok != true ) {
message ( "Failed to add %s - %s\n" , user _dn , ldb . errstring ( ) ) ;
return false ;
}
message ( "Modifying group %s\n" , dom _users ) ;
ok = ldb . modify ( modgroup ) ;
if ( ok != true ) {
message ( "Failed to modify %s - %s\n" , dom _users , ldb . errstring ( ) ) ;
return false ;
}
return true ;
}
2005-07-12 15:46:34 +04:00
return 0 ;