r9827: Convert 'passdb backend' rather then 'passdb backends'
[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 backend");
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                 message("Enabling Samba3 LDAP mappings for SAM database\n");
442                 var ldif = sprintf("
443 dn: @MAP=samba3sam
444 @MAP_URL: %s", ldapurl);
445                 samdb.add(ldif);
446
447                 samdb.modify("dn: @MODULES
448 @LIST: samldb,timestamps,objectguid,rdn_name,samba3sam");
449         }
450
451         message("Importing users\n");
452         for (var i in samba3.samaccounts) {
453                 message("... " + samba3.samaccounts[i].username);
454                 var ldif = upgrade_sam_account(samba3.samaccounts[i],subobj.BASEDN);
455                 ok = samdb.add(ldif);
456                 if (!ok) { 
457                         message("... error: " + samdb.errstring()); 
458                         ret = ret + 1; 
459                 }
460                 message("\n");
461         }
462
463         message("Importing groups\n");
464         for (var i in samba3.groupmappings) {
465                 message("... " + samba3.groupmappings[i].nt_name);
466                 var ldif = upgrade_sam_group(samba3.groupmappings[i],subobj.BASEDN);
467                 ok = samdb.add(ldif);
468                 if (!ok) { 
469                         message("... error: " + samdb.errstring()); 
470                         ret = ret + 1; 
471                 }
472                 message("\n");
473         }
474
475         message("Importing registry data\n");
476         var hives = new Array("hkcr","hkcu","hklm","hkpd","hku","hkpt"); 
477         for (var i in hives) {
478                 var hn = hives[i];
479                 message("... " + hn + "\n");
480                 var regdb = ldb_init();
481                 ok = regdb.connect(paths[hn]);
482                 assert(ok);
483                 var ldif = upgrade_registry(samba3.registry, hn);
484                 for (var j in ldif) {
485                         message("... ... " + j);
486                         ok = regdb.add(ldif[j]);
487                         if (!ok) { 
488                                 message("... error: " + regdb.errstring()); 
489                                 ret = ret + 1; 
490                         }
491                         message("\n");
492                 }
493         }
494
495         message("Importing WINS data\n");
496         var winsdb = ldb_init();
497         ok = winsdb.connect(paths.winsdb);
498         assert(ok);
499         ldb_erase(winsdb);
500
501         var ldif = upgrade_wins(samba3);
502         ok = winsdb.add(ldif);
503         assert(ok);
504
505         return ret;
506 }