r9842: More error checks in the ldb_map modules, extend testsuite
[kai/samba.git] / source / 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         message("Importing users\n");
422         for (var i in samba3.samaccounts) {
423                 var msg = "... " + samba3.samaccounts[i].username;
424                 var ldif = upgrade_sam_account(samba3.samaccounts[i],subobj.BASEDN);
425                 ok = samdb.add(ldif);
426                 if (!ok) { 
427                         msg = msg + "... error: " + samdb.errstring();
428                         ret = ret + 1; 
429                 }
430                 message(msg + "\n");
431         }
432
433         message("Importing groups\n");
434         for (var i in samba3.groupmappings) {
435                 var msg = "... " + samba3.groupmappings[i].nt_name;
436                 var ldif = upgrade_sam_group(samba3.groupmappings[i],subobj.BASEDN);
437                 ok = samdb.add(ldif);
438                 if (!ok) { 
439                         msg = msg + "... error: " + samdb.errstring();
440                         ret = ret + 1; 
441                 }
442                 message(msg + "\n");
443         }
444
445         message("Importing registry data\n");
446         var hives = new Array("hkcr","hkcu","hklm","hkpd","hku","hkpt"); 
447         for (var i in hives) {
448                 var hn = hives[i];
449                 message("... " + hn + "\n");
450                 var regdb = ldb_init();
451                 ok = regdb.connect(paths[hn]);
452                 assert(ok);
453                 var ldif = upgrade_registry(samba3.registry, hn, regdb);
454                 for (var j in ldif) {
455                         var msg = "... ... " + j;
456                         ok = regdb.add(ldif[j]);
457                         if (!ok) { 
458                                 msg = msg + "... error: " + regdb.errstring();
459                                 ret = ret + 1; 
460                         }
461                         message(msg + "\n");
462                 }
463         }
464
465         message("Importing WINS data\n");
466         var winsdb = ldb_init();
467         ok = winsdb.connect(paths.winsdb);
468         assert(ok);
469         ldb_erase(winsdb);
470
471         var ldif = upgrade_wins(samba3);
472         ok = winsdb.add(ldif);
473         assert(ok);
474
475         // figure out ldapurl, if applicable
476         var ldapurl = undefined;
477         var pdb = samba3.configuration.get_list("passdb backend");
478         if (pdb != undefined) {
479                 for (var b in pdb) {
480                         if (substr(pdb[b], 0, 7) == "ldapsam") {
481                                 ldapurl = substr(pdb[b], 8);
482                         }
483                 }
484         }
485
486         // URL was not specified in passdb backend but ldap /is/ used
487         if (ldapurl == "") {
488                 ldapurl = "ldap://" + samba3.configuration.get("ldap server");
489         }
490
491         // Enable samba3sam module if original passdb backend was ldap
492         if (ldapurl != undefined) {
493                 message("Enabling Samba3 LDAP mappings for SAM database\n");
494                 var ldif = sprintf("
495 dn: @MAP=samba3sam
496 @MAP_URL: %s", ldapurl);
497                 ok = samdb.add(ldif);
498                 assert(ok);
499
500                 ok = samdb.modify("dn: @MODULES
501 replace: @LIST
502 @LIST: samldb,timestamps,objectguid,rdn_name,samba3sam");
503                 assert(ok);
504         }
505
506         return ret;
507 }
508
509 function upgrade_verify(subobj, samba3,paths,message)
510 {
511         message("Verifying account policies\n");
512         var samldb = ldb_init();
513         var ne = 0;
514
515         var ok = samldb.connect(paths.samdb);
516         assert(ok);
517         
518         // FIXME
519 }