aa94dbbbc47a0630cae0ad7a276edc8f37573ea6
[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)
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 var 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 function upgrade_smbconf(samba3)
375 {
376         //FIXME
377 }
378
379 function save_smbconf(path,smbconf)
380 {
381         var data = "
382 # Generated by upgrade.js";
383
384         for (var i in smbconf.shares) {
385                 var s = smbconf.shares[i];
386                 data = data + "\n[" + s.name + "]\n";
387                 for (var j in s.parameters) {
388                         var p = s.parameters[j];
389                         data = data + "\t" + p.name + " = " + p + "\n";
390                 }
391         }
392         
393         sys.file_save(path,data);
394 }
395
396 function upgrade(subobj, samba3, message)
397 {
398         var ret = 0;
399         var samdb = ldb_init();
400         var ok = samdb.connect("sam.ldb");
401         assert(ok);
402
403         message("Importing account policies\n");
404         var ldif = upgrade_sam_policy(samba3,subobj.BASEDN);
405         ok = samdb.modify(ldif);
406         assert(ok);
407
408         var ldapurl = undefined;
409
410         // FIXME: figure out ldapurl
411
412         // Enable samba3sam module if original passdb backend was ldap
413         if (ldapurl != undefined) {
414                 var ldif = sprintf("
415 dn: @MAP=samba3sam
416 @MAP_URL: %s", ldapurl);
417                 samdb.add(ldif);
418
419                 samdb.modify("dn: @MODULES
420 @LIST: samldb,timestamps,objectguid,rdn_name");
421         }
422
423         message("Importing users\n");
424         for (var i in samba3.samaccounts) {
425                 message("... " + samba3.samaccounts[i].username);
426                 var ldif = upgrade_sam_account(samba3.samaccounts[i],subobj.BASEDN);
427                 ok = samdb.add(ldif);
428                 if (!ok) { 
429                         message("... error: " + samdb.errstring()); 
430                         ret = ret + 1; 
431                 }
432                 message("\n");
433         }
434
435         message("Importing groups\n");
436         for (var i in samba3.groupmappings) {
437                 message("... " + samba3.groupmappings[i].nt_name);
438                 var ldif = upgrade_sam_group(samba3.groupmappings[i],subobj.BASEDN);
439                 ok = samdb.add(ldif);
440                 if (!ok) { 
441                         message("... error: " + samdb.errstring()); 
442                         ret = ret + 1; 
443                 }
444                 message("\n");
445         }
446
447         message("Importing registry data\n");
448         var hives = new Array("hkcr","hkcu","hklm","hkpd","hku","hkpt"); 
449         for (var i in hives) {
450                 message("... " + hives[i] + "\n");
451                 var regdb = ldb_init();
452                 ok = regdb.connect(hives[i] + ".ldb");
453                 assert(ok);
454                 var ldif = upgrade_registry(samba3.registry, hives[i]);
455                 for (var j in ldif) {
456                         message("... ... " + j);
457                         ok = regdb.add(ldif[j]);
458                         if (!ok) { 
459                                 message("... error: " + regdb.errstring()); 
460                                 ret = ret + 1; 
461                         }
462                         message("\n");
463                 }
464         }
465
466         message("Importing WINS data\n");
467         var winsdb = ldb_init();
468         ok = winsdb.connect("wins.ldb");
469         assert(ok);
470         ldb_erase(winsdb);
471
472         var ldif = upgrade_wins(samba3);
473         ok = winsdb.add(ldif);
474         assert(ok);
475
476         return ret;
477 }