r9834: More tests for the upgrade from Samba3
[ira/wip.git] / source4 / scripting / libjs / upgrade.js
1 /*
2         backend code for upgrading from Samba3
3         Copyright Jelmer Vernooij 2005
4         Released under the GNU GPL v2 or later
5 */
6
7 libinclude("base.js");
8
9 function regkey_to_dn(name)
10 {
11         var dn = "hive=NONE";
12         var i = 0;
13
14         var as = split("/", name);
15
16         for (i in as) {
17                 if (i > 0) {
18                         dn = sprintf("key=%s,", as[i]) + dn;
19                 }
20         }
21
22         return dn;
23 }
24
25 /* Where prefix is any of:
26  * - HKLM
27  *   HKU
28  *   HKCR
29  *   HKPD
30  *   HKPT
31  */
32
33 function upgrade_registry(regdb,prefix,ldb)
34 {
35         assert(regdb != undefined);
36         var prefix_up = strupper(prefix);
37         var ldif = new Array();
38
39         for (var i in regdb.keys) {
40                 var rk = regdb.keys[i];
41                 var pts = split("/", rk.name);
42
43                 /* Only handle selected hive */
44                 if (strupper(pts[0]) != prefix_up) {
45                         continue;
46                 }
47
48                 var keydn = regkey_to_dn(rk.name);
49
50                 var pts = split("/", rk.name);
51
52                 /* Convert key name to dn */
53                 ldif[rk.name] = sprintf("
54 dn: %s
55 name: %s
56
57 ", keydn, pts[0]);
58                 
59                 for (var j in rk.values) {
60                         var rv = rk.values[j];
61
62                         ldif[rk.name + " (" + rv.name + ")"] = sprintf("
63 dn: %s,value=%s
64 value: %s
65 type: %d
66 data:: %s", keydn, rv.name, rv.name, rv.type, ldb.encode(rv.data));
67                 }
68         }
69
70         return ldif;
71 }
72
73 function upgrade_sam_policy(samba3,dn)
74 {
75         var ldif = sprintf("
76 dn: %s
77 changetype: modify
78 replace: minPwdLength
79 minPwdLength: %d
80 pwdHistoryLength: %d
81 minPwdAge: %d
82 maxPwdAge: %d
83 lockoutDuration: %d
84 samba3ResetCountMinutes: %d
85 samba3UserMustLogonToChangePassword: %d
86 samba3BadLockoutMinutes: %d
87 samba3DisconnectTime: %d
88 samba3RefuseMachinePwdChange: %d
89
90 ", dn, samba3.policy.min_password_length, 
91         samba3.policy.password_history, samba3.policy.minimum_password_age,
92         samba3.policy.maximum_password_age, samba3.policy.lockout_duration,
93         samba3.policy.reset_count_minutes, samba3.policy.user_must_logon_to_change_password,
94         samba3.policy.bad_lockout_minutes, samba3.policy.disconnect_time, 
95         samba3.policy.refuse_machine_password_change
96 );
97
98         return ldif;
99 }
100
101 function upgrade_sam_account(acc,domaindn)
102 {
103         var ldb = ldb_init();
104         var ldif = sprintf(
105 "dn: cn=%s,%s
106 objectClass: user
107 lastLogon: %d
108 lastLogoff: %d
109 unixName: %s
110 name: %s
111 cn: %s
112 description: %s
113 primaryGroupID: %d
114 badPwdcount: %d
115 logonCount: %d
116 samba3Domain: %s
117 samba3DirDrive: %s
118 samba3MungedDial: %s
119 samba3Homedir: %s
120 samba3LogonScript: %s
121 samba3ProfilePath: %s
122 samba3Workstations: %s
123 samba3KickOffTime: %d
124 samba3BadPwdTime: %d
125 samba3PassLastSetTime: %d
126 samba3PassCanChangeTime: %d
127 samba3PassMustChangeTime: %d
128 samba3Rid: %d
129 ntPwdHash:: %s
130 lmPwdHash:: %s
131
132 ", acc.fullname, domaindn, acc.logon_time, acc.logoff_time, acc.username, acc.nt_username, 
133 acc.fullname, acc.acct_desc, acc.group_rid, acc.bad_password_count, acc.logon_count,
134 acc.domain, acc.dir_drive, acc.munged_dial, acc.homedir, acc.logon_script, 
135 acc.profile_path, acc.workstations, acc.kickoff_time, acc.bad_password_time, 
136 acc.pass_last_set_time, acc.pass_can_change_time, acc.pass_must_change_time, acc.user_rid,
137         ldb.encode(acc.lm_pw), ldb.encode(acc.nt_pw)); 
138
139         return ldif;
140 }
141
142 function upgrade_sam_group(grp,domaindn)
143 {
144         var ldif = sprintf(
145 "dn: cn=%s,%s
146 objectClass: top
147 objectClass: group
148 description: %s
149 cn: %s
150 objectSid: %s
151 unixName: FIXME
152 samba3SidNameUse: %d
153 ", grp.nt_name, domaindn, 
154 grp.comment, grp.nt_name, grp.sid, grp.sid_name_use);
155
156         return ldif;
157 }
158
159 function upgrade_winbind(samba3,domaindn)
160 {
161         var ldif = sprintf("
162                 
163 dn: dc=none
164 userHwm: %d
165 groupHwm: %d
166
167 ", samba3.idmap.user_hwm, samba3.idmap.group_hwm);
168
169         for (var i in samba3.idmap.mappings) {
170                 var m = samba3.idmap.mappings[i];
171                 ldif = ldif + sprintf("
172 dn: SID=%s,%s
173 SID: %s
174 type: %d
175 unixID: %d", m.sid, domaindn, m.sid, m.type, m.unix_id);
176         }
177         
178         return ldif;
179 }
180 */
181
182 function upgrade_wins(samba3)
183 {
184         var ldif = "";
185         for (i in samba3.winsentries) {
186                 var e = samba3.winsentries[i];
187                 
188                 ldif = ldif + sprintf("
189 dn: type=%d,name=%s
190 name: %s
191 objectClass: wins
192 nbFlags: %x
193 expires: %s
194 ", e.type, e.name, e.name, e.type, e.nb_flags, sys.ldaptime(e.ttl));
195
196                 for (var i in e.ips) {
197                         ldif = ldif + sprintf("address: %s\n", e.ips[i]);
198                 }
199         }
200
201         return ldif;
202 }
203
204 function upgrade_provision(samba3)
205 {
206         var subobj = new Object();
207         var nss = nss_init();
208         var lp = loadparm_init();
209         var rdn_list;
210
211         var domainname = samba3.configuration.get("workgroup");
212         
213         if (domainname == undefined) {
214                 domainname = samba3.secrets.domains[0].name;
215                 println("No domain specified in smb.conf file, assuming '" + domainname + "'");
216         }
217         
218         var domsec = samba3.find_domainsecrets(domainname);
219         var hostsec = samba3.find_domainsecrets(hostname());
220         var realm = samba3.configuration.get("realm");
221
222         if (realm == undefined) {
223                 realm = domainname;
224                 println("No realm specified in smb.conf file, assuming '" + realm + "'");
225         }
226         random_init(local);
227
228         subobj.REALM        = realm;
229         subobj.DOMAIN       = domainname;
230         subobj.HOSTNAME     = hostname();
231
232         assert(subobj.REALM);
233         assert(subobj.DOMAIN);
234         assert(subobj.HOSTNAME);
235
236         subobj.HOSTIP       = hostip();
237         if (domsec != undefined) {
238                 subobj.DOMAINGUID   = domsec.guid;
239                 subobj.DOMAINSID    = domsec.sid;
240         } else {
241                 println("Can't find domain secrets for '" + domainname + "'; using random SID and GUID");
242                 subobj.DOMAINGUID = randguid();
243                 subobj.DOMAINSID = randsid();
244         }
245         
246         if (hostsec) {
247                 subobj.HOSTGUID     = hostsec.guid;
248         } else {
249                 subobj.HOSTGUID = randguid();
250         }
251         subobj.INVOCATIONID = randguid();
252         subobj.KRBTGTPASS   = randpass(12);
253         subobj.MACHINEPASS  = randpass(12);
254         subobj.ADMINPASS    = randpass(12);
255         subobj.DEFAULTSITE  = "Default-First-Site-Name";
256         subobj.NEWGUID      = randguid;
257         subobj.NTTIME       = nttime;
258         subobj.LDAPTIME     = ldaptime;
259         subobj.DATESTRING   = datestring;
260         subobj.USN          = nextusn;
261         subobj.ROOT         = findnss(nss.getpwnam, "root");
262         subobj.NOBODY       = findnss(nss.getpwnam, "nobody");
263         subobj.NOGROUP      = findnss(nss.getgrnam, "nogroup", "nobody");
264         subobj.WHEEL        = findnss(nss.getgrnam, "wheel", "root");
265         subobj.USERS        = findnss(nss.getgrnam, "users", "guest", "other");
266         subobj.DNSDOMAIN    = strlower(subobj.REALM);
267         subobj.DNSNAME      = sprintf("%s.%s", 
268                                       strlower(subobj.HOSTNAME), 
269                                       subobj.DNSDOMAIN);
270         subobj.BASEDN       = "DC=" + join(",DC=", split(".", subobj.REALM));
271         rdn_list = split(".", subobj.REALM);
272         return subobj;
273 }
274
275 smbconf_keep = new Array(
276         "dos charset", 
277         "unix charset",
278         "display charset",
279         "comment",
280         "path",
281         "directory",
282         "workgroup",
283         "realm",
284         "netbios name",
285         "netbios aliases",
286         "netbios scope",
287         "server string",
288         "interfaces",
289         "bind interfaces only",
290         "security",
291         "auth methods",
292         "encrypt passwords",
293         "null passwords",
294         "obey pam restrictions",
295         "password server",
296         "smb passwd file",
297         "private dir",
298         "passwd chat",
299         "password level",
300         "lanman auth",
301         "ntlm auth",
302         "client NTLMv2 auth",
303         "client lanman auth",
304         "client plaintext auth",
305         "read only",
306         "hosts allow",
307         "hosts deny",
308         "log level",
309         "debuglevel",
310         "log file",
311         "smb ports",
312         "large readwrite",
313         "max protocol",
314         "min protocol",
315         "unicode",
316         "read raw",
317         "write raw",
318         "disable netbios",
319         "nt status support",
320         "announce version",
321         "announce as",
322         "max mux",
323         "max xmit",
324         "name resolve order",
325         "max wins ttl",
326         "min wins ttl",
327         "time server",
328         "unix extensions",
329         "use spnego",
330         "server signing",
331         "client signing",
332         "max connections",
333         "paranoid server security",
334         "socket options",
335         "strict sync",
336         "max print jobs",
337         "printable",
338         "print ok",
339         "printer name",
340         "printer",
341         "map system",
342         "map hidden",
343         "map archive",
344         "domain logons",
345         "preferred master",
346         "prefered master",
347         "local master",
348         "domain master",
349         "browseable",
350         "browsable",
351         "wins server",
352         "wins support",
353         "csc policy",
354         "strict locking",
355         "config file",
356         "preload",
357         "auto services",
358         "lock dir",
359         "lock directory",
360         "pid directory",
361         "socket address",
362         "copy",
363         "include",
364         "available",
365         "volume",
366         "fstype",
367         "panic action",
368         "msdfs root",
369         "host msdfs",
370         "winbind separator");
371
372 /*
373    Remove configuration variables not present in Samba4
374         oldconf: Old configuration structure
375         mark: Whether removed configuration variables should be 
376                 kept in the new configuration as "samba3:<name>"
377  */
378 function upgrade_smbconf(oldconf,mark)
379 {
380         var data = oldconf.data();
381         var newconf = param_init();
382
383         for (var s in data) {
384                 for (var p in data[s]) {
385                         var keep = false;
386                         for (var k in smbconf_keep) { 
387                                 if (smbconf_keep[k] == p) {
388                                         keep = true;
389                                         break;
390                                 }
391                         }
392
393                         if (keep) {
394                                 newconf.set(s, p, oldconf.get(s, p));
395                         } else if (mark) {
396                                 newconf.set(s, "samba3:"+p, oldconf.get(s,p));
397                         }
398                 }
399         }
400
401         return newconf;
402 }
403
404 function upgrade(subobj, samba3, message, paths)
405 {
406         var ret = 0;
407         var lp = loadparm_init();
408         var samdb = ldb_init();
409         var ok = samdb.connect(paths.samdb);
410         assert(ok);
411
412         message("Writing configuration\n");
413         var newconf = upgrade_smbconf(samba3.configuration,true);
414         newconf.save(paths.smbconf);
415
416         message("Importing account policies\n");
417         var ldif = upgrade_sam_policy(samba3,subobj.BASEDN);
418         ok = samdb.modify(ldif);
419         assert(ok);
420
421         // figure out ldapurl, if applicable
422         var ldapurl = undefined;
423         var pdb = samba3.configuration.get_list("passdb backend");
424         if (pdb != undefined) {
425                 for (var b in pdb) {
426                         if (substr(pdb[b], 0, 7) == "ldapsam") {
427                                 ldapurl = substr(pdb[b], 8);
428                         }
429                 }
430         }
431
432         // URL was not specified in passdb backend but ldap /is/ used
433         if (ldapurl == "") {
434                 ldapurl = "ldap://" + samba3.configuration.get("ldap server");
435         }
436
437         // Enable samba3sam module if original passdb backend was ldap
438         if (ldapurl != undefined) {
439                 message("Enabling Samba3 LDAP mappings for SAM database\n");
440                 var ldif = sprintf("
441 dn: @MAP=samba3sam
442 @MAP_URL: %s", ldapurl);
443                 samdb.add(ldif);
444
445                 samdb.modify("dn: @MODULES
446 @LIST: samldb,timestamps,objectguid,rdn_name,samba3sam");
447         }
448
449         message("Importing users\n");
450         for (var i in samba3.samaccounts) {
451                 var msg = "... " + samba3.samaccounts[i].username;
452                 var ldif = upgrade_sam_account(samba3.samaccounts[i],subobj.BASEDN);
453                 ok = samdb.add(ldif);
454                 if (!ok) { 
455                         msg = msg + "... error: " + samdb.errstring();
456                         ret = ret + 1; 
457                 }
458                 message(msg + "\n");
459         }
460
461         message("Importing groups\n");
462         for (var i in samba3.groupmappings) {
463                 var msg = "... " + samba3.groupmappings[i].nt_name;
464                 var ldif = upgrade_sam_group(samba3.groupmappings[i],subobj.BASEDN);
465                 ok = samdb.add(ldif);
466                 if (!ok) { 
467                         msg = msg + "... error: " + samdb.errstring();
468                         ret = ret + 1; 
469                 }
470                 message(msg + "\n");
471         }
472
473         message("Importing registry data\n");
474         var hives = new Array("hkcr","hkcu","hklm","hkpd","hku","hkpt"); 
475         for (var i in hives) {
476                 var hn = hives[i];
477                 message("... " + hn + "\n");
478                 var regdb = ldb_init();
479                 ok = regdb.connect(paths[hn]);
480                 assert(ok);
481                 var ldif = upgrade_registry(samba3.registry, hn, regdb);
482                 for (var j in ldif) {
483                         var msg = "... ... " + j;
484                         ok = regdb.add(ldif[j]);
485                         if (!ok) { 
486                                 msg = msg + "... error: " + regdb.errstring();
487                                 ret = ret + 1; 
488                         }
489                         message(msg + "\n");
490                 }
491         }
492
493         message("Importing WINS data\n");
494         var winsdb = ldb_init();
495         ok = winsdb.connect(paths.winsdb);
496         assert(ok);
497         ldb_erase(winsdb);
498
499         var ldif = upgrade_wins(samba3);
500         ok = winsdb.add(ldif);
501         assert(ok);
502
503         return ret;
504 }
505
506 function upgrade_verify(subobj, samba3,paths,message)
507 {
508         message("Verifying account policies\n");
509         var samldb = ldb_init();
510         var ne = 0;
511
512         var ok = samldb.connect(paths.samdb);
513         assert(ok);
514         
515         // FIXME
516 }