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