r8350: fixed the --root option to provision
[samba.git] / source4 / setup / provision
1 #!/usr/bin/env smbscript
2 /*
3         provision a Samba4 server
4         Copyright Andrew Tridgell 2005
5         Released under the GNU GPL v2 or later
6 */
7
8 options = new Object();
9 ok = GetOptions(ARGV, options, 
10                 "POPT_AUTOHELP",
11                 "POPT_COMMON_SAMBA",
12                 "POPT_COMMON_VERSION",
13                 'realm=s',
14                 'domain=s',
15                 'domain-guid=s',
16                 'domain-sid=s',
17                 'host-name=s',
18                 'host-ip=s',
19                 'host-guid=s',
20                 'invocationid=s',
21                 'adminpass=s',
22                 'krbtgtpass=s',
23                 'machinepass=s',
24                 'root=s',
25                 'nobody=s',
26                 'nogroup=s',
27                 'wheel=s',
28                 'users=s',
29                 'outputdir=s',
30                 'quiet');
31 if (ok == false) {
32    println("Failed to parse options: " + options.ERROR);
33    return -1;
34 }
35
36 libinclude("base.js");
37
38 /* used to generate sequence numbers for records */
39 next_usn = 1;
40
41 /*
42   print a message if quiet is not set
43 */
44 function message(s) 
45 {
46         if (options["quiet"] == undefined) {
47                 println(s);
48         }
49 }
50
51 /*
52   find a user or group from a list of possibilities
53 */
54 function findnss()
55 {
56         var i;
57         assert(arguments.length >= 2);
58         var nssfn = arguments[0];
59         var name = arguments[1];
60         if (options[name] != undefined) {
61                 return options[name];
62         }
63         for (i=2;i<arguments.length;i++) {
64                 if (nssfn(arguments[i]) != undefined) {
65                         return arguments[i];
66                 }
67         }
68         println("Unable to find user/group for " + name);
69         exit(1);
70 }
71
72 /*
73    add a foreign security principle
74  */
75 function add_foreign(str, sid, desc, unixname)
76 {
77         var add = "
78 dn: CN=${SID},CN=ForeignSecurityPrincipals,${BASEDN}
79 objectClass: top
80 objectClass: foreignSecurityPrincipal
81 cn: ${SID}
82 description: ${DESC}
83 instanceType: 4
84 whenCreated: ${LDAPTIME}
85 whenChanged: ${LDAPTIME}
86 uSNCreated: 1
87 uSNChanged: 1
88 showInAdvancedViewOnly: TRUE
89 name: ${SID}
90 objectGUID: ${NEWGUID}
91 objectSid: ${SID}
92 objectCategory: CN=Foreign-Security-Principal,CN=Schema,CN=Configuration,${BASEDN}
93 unixName: ${UNIXNAME}
94 ";
95         var sub = new Object();
96         sub.SID = sid;
97         sub.DESC = desc;
98         sub.UNIXNAME = unixname;
99         return str + substitute_var(add, sub);
100 }
101
102 /*
103   return current time as a nt time string
104 */
105 function nttime()
106 {
107         return "" + sys_nttime();
108 }
109
110 /*
111   return current time as a ldap time string
112 */
113 function ldaptime()
114 {
115         return sys_ldaptime(sys_nttime());
116 }
117
118 function datestring()
119 {
120         var t = sys_gmtime(sys_nttime());
121         return sprintf("%04u%02u%02u%02u",
122                        t.tm_year+1900, t.tm_mon+1, t.tm_mday, t.tm_hour);
123 }
124
125 /*
126   return current time as a ldap time string
127 */
128 function nextusn()
129 {
130         next_usn = next_usn+1;
131         return next_usn;
132 }
133
134 /*
135   return first part of hostname
136 */
137 function hostname()
138 {
139         var s = split(".", sys_hostname());
140         return s[0];
141 }
142
143
144 /*
145   setup a ldb in the private dir
146  */
147 function setup_ldb(ldif, dbname, subobj)
148 {
149         var extra = "";
150         if (arguments.length == 4) {
151                 extra = arguments[3];
152         }
153
154         var db = lpGet("private dir") + "/" + dbname;
155         var src = lpGet("setup directory") + "/" + ldif;
156
157         sys_unlink(db);
158
159         var data = sys_file_load(src);
160         data = data + extra;
161         data = substitute_var(data, subobj);
162
163         message("Creating " + db + "\n from " + src);
164         ok = ldbAdd(db, data);
165         assert(ok);
166 }
167
168 /*
169   setup a file in the private dir
170  */
171 function setup_file(template, fname, subobj)
172 {
173         var f = lpGet("private dir") + "/" + fname;
174         var src = lpGet("setup directory") + "/" + template;
175
176         sys_unlink(f);
177
178         var data = sys_file_load(src);
179         data = substitute_var(data, subobj);
180
181         message("Creating " + f + "\n from " + src);
182         ok = sys_file_save(f, data);
183         assert(ok);
184 }
185
186 /*
187  show some help
188 */
189 function ShowHelp()
190 {
191         print("
192 Samba4 provisioning
193
194 provision.pl [options]
195  --realm        REALM           set realm
196  --domain       DOMAIN          set domain
197  --domain-guid  GUID            set domainguid (otherwise random)
198  --domain-sid   SID             set domainsid (otherwise random)
199  --host-name    HOSTNAME        set hostname
200  --host-ip      IPADDRESS       set ipaddress
201  --host-guid    GUID            set hostguid (otherwise random)
202  --invocationid GUID            set invocationid (otherwise random)
203  --outputdir    OUTPUTDIR       set output directory
204  --adminpass    PASSWORD        choose admin password (otherwise random)
205  --krbtgtpass   PASSWORD        choose krbtgt password (otherwise random)
206  --machinepass  PASSWORD        choose machine password (otherwise random)
207  --root         USERNAME        choose 'root' unix username
208  --nobody       USERNAME        choose 'nobody' user
209  --nogroup      GROUPNAME       choose 'nogroup' group
210  --wheel        GROUPNAME       choose 'wheel' privileged group
211  --users        GROUPNAME       choose 'users' group
212  --quiet                        Be quiet
213
214 You must provide at least a realm and domain
215
216 ");
217         exit(1);
218 }
219
220 if (options['host-name'] == undefined) {
221         options['host-name'] = hostname();
222 }
223
224 /*
225    main program
226 */
227 if (options["realm"] == undefined ||
228     options["domain"] == undefined ||
229     options["host-name"] == undefined) {
230         ShowHelp();
231 }
232
233 options.realm        = strlower(options.realm);
234 options['host-name'] = strlower(options['host-name']);
235 options.domain       = strupper(options.domain);
236 options.netbiosname  = strupper(options['host-name']);
237
238 if (options.hostip == undefined) {
239         var list = sys_interfaces();
240         options.hostip = list[0];
241 }
242
243 message("Provisioning for " + options.domain + " in realm " + options.realm);
244
245 options.root    = findnss(getpwnam, "root", "root");
246 options.nobody  = findnss(getpwnam, "nobody", "nobody");
247 options.nogroup = findnss(getgrnam, "nogroup", "nogroup", "nobody");
248 options.wheel   = findnss(getgrnam, "wheel", "wheel", "root");
249 options.users   = findnss(getgrnam, "users", "users", "guest", "other");
250
251
252 options.dnsdomain = strlower(options.realm);
253 options.dnsname   = strlower(options['host-name']) + "." + options.dnsdomain;
254 options.basedn    = "DC=" + join(",DC=", split(".", options.realm));
255
256 /*
257   setup the substitution object
258 */
259 var subobj = new Object();
260 subobj.DOMAINGUID   = randguid();
261 subobj.DOMAINSID    = randsid();
262 subobj.HOSTGUID     = randguid();
263 subobj.INVOCATIONID = randguid();
264 subobj.KRBTGTPASS   = randpass(12);
265 subobj.MACHINEPASS  = randpass(12);
266 subobj.ADMINPASS    = randpass(12);
267 subobj.DEFAULTSITE  = "Default-First-Site-Name";
268 subobj.NEWGUID      = randguid;
269 subobj.NTTIME       = nttime;
270 subobj.LDAPTIME     = ldaptime;
271 subobj.DATESTRING   = datestring;
272 subobj.USN          = nextusn;
273 for (r in options) {
274         var key = strupper(join("", split("-", r)));
275         subobj[key] = options[r];
276 }
277
278
279 var extradata = "";
280 extradata = add_foreign(extradata, "S-1-5-7",  "Anonymous",           "${NOBODY}");
281 extradata = add_foreign(extradata, "S-1-1-0",  "World",               "${NOGROUP}");
282 extradata = add_foreign(extradata, "S-1-5-2",  "Network",             "${NOGROUP}");
283 extradata = add_foreign(extradata, "S-1-5-18", "System",              "${ROOT}");
284 extradata = add_foreign(extradata, "S-1-5-11", "Authenticated Users", "${USERS}");
285
286 message("Using administrator password: " + subobj.ADMINPASS);
287
288 setup_ldb("hklm.ldif", "hklm.ldb", subobj);
289 setup_ldb("provision.ldif", "sam.ldb", subobj, extradata);
290 setup_ldb("rootdse.ldif", "rootdse.ldb", subobj);
291 setup_ldb("secrets.ldif", "secrets.ldb", subobj);
292 setup_file("provision.zone", subobj.DNSDOMAIN + ".zone", subobj);
293
294 message("All OK");
295 return 0;