2 backend code for upgrading from Samba3
3 Copyright Jelmer Vernooij 2005
4 Released under the GNU GPL v2 or later
9 function regkey_to_dn(name)
14 var as = split("/", name);
18 dn = sprintf("key=%s,", as[i]) + dn;
25 /* Where prefix is any of:
33 function upgrade_registry(regdb,prefix,ldb)
35 assert(regdb != undefined);
36 var prefix_up = strupper(prefix);
37 var ldif = new Array();
39 for (var i in regdb.keys) {
40 var rk = regdb.keys[i];
41 var pts = split("/", rk.name);
43 /* Only handle selected hive */
44 if (strupper(pts[0]) != prefix_up) {
48 var keydn = regkey_to_dn(rk.name);
50 var pts = split("/", rk.name);
52 /* Convert key name to dn */
53 ldif[rk.name] = sprintf("
59 for (var j in rk.values) {
60 var rv = rk.values[j];
62 ldif[rk.name + " (" + rv.name + ")"] = sprintf("
66 data:: %s", keydn, rv.name, rv.name, rv.type, ldb.encode(rv.data));
73 function upgrade_sam_policy(samba3,dn)
84 samba3ResetCountMinutes: %d
85 samba3UserMustLogonToChangePassword: %d
86 samba3BadLockoutMinutes: %d
87 samba3DisconnectTime: %d
88 samba3RefuseMachinePwdChange: %d
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
101 function upgrade_sam_account(ldb,acc,domaindn,domainsid)
103 if (acc.nt_username == undefined) {
104 acc.nt_username = acc.username;
107 if (acc.nt_username == "") {
108 acc.nt_username = acc.username;
111 if (acc.fullname == undefined) {
112 var pw = nss.getpwnam(acc.fullname);
113 acc.fullname = pw.pw_gecos;
116 var pts = split(',', acc.fullname);
117 acc.fullname = pts[0];
119 assert(acc.fullname != undefined);
120 assert(acc.nt_username != undefined);
140 samba3LogonScript: %s
141 samba3ProfilePath: %s
142 samba3Workstations: %s
143 samba3KickOffTime: %d
145 samba3PassLastSetTime: %d
146 samba3PassCanChangeTime: %d
147 samba3PassMustChangeTime: %d
152 ", acc.fullname, domaindn, acc.logon_time, acc.logoff_time, acc.username, acc.nt_username, acc.nt_username,
154 acc.fullname, acc.acct_desc, acc.group_rid, acc.bad_password_count, acc.logon_count,
155 acc.domain, acc.dir_drive, acc.munged_dial, acc.homedir, acc.logon_script,
156 acc.profile_path, acc.workstations, acc.kickoff_time, acc.bad_password_time,
157 acc.pass_last_set_time, acc.pass_can_change_time, acc.pass_must_change_time, domainsid, acc.user_rid,
158 ldb.encode(acc.lm_pw), ldb.encode(acc.nt_pw));
163 function upgrade_sam_group(grp,domaindn)
165 var nss = nss_init();
168 if (grp.sid_name_use == 5) { // Well-known group
172 if (grp.nt_name == "Domain Guests" ||
173 grp.nt_name == "Domain Users" ||
174 grp.nt_name == "Domain Admins") {
179 gr = nss.getgrnam(grp.nt_name);
181 gr = nss.getgrgid(grp.gid);
184 if (gr == undefined) {
185 grp.unixname = "UNKNOWN";
187 grp.unixname = gr.gr_name;
190 assert(grp.unixname != undefined);
201 ", grp.nt_name, domaindn,
202 grp.comment, grp.nt_name, grp.sid, grp.unixname, grp.sid_name_use);
207 function upgrade_winbind(samba3,domaindn)
215 ", samba3.idmap.user_hwm, samba3.idmap.group_hwm);
217 for (var i in samba3.idmap.mappings) {
218 var m = samba3.idmap.mappings[i];
219 ldif = ldif + sprintf("
223 unixID: %d", m.sid, domaindn, m.sid, m.type, m.unix_id);
230 function upgrade_wins(samba3)
233 for (i in samba3.winsentries) {
234 var e = samba3.winsentries[i];
236 ldif = ldif + sprintf("
242 ", e.type, e.name, e.name, e.type, e.nb_flags, sys.ldaptime(e.ttl));
244 for (var i in e.ips) {
245 ldif = ldif + sprintf("address: %s\n", e.ips[i]);
252 function upgrade_provision(samba3)
254 var subobj = new Object();
255 var nss = nss_init();
256 var lp = loadparm_init();
259 var domainname = samba3.configuration.get("workgroup");
261 if (domainname == undefined) {
262 domainname = samba3.secrets.domains[0].name;
263 println("No domain specified in smb.conf file, assuming '" + domainname + "'");
266 var domsec = samba3.find_domainsecrets(domainname);
267 var hostsec = samba3.find_domainsecrets(hostname());
268 var realm = samba3.configuration.get("realm");
270 if (realm == undefined) {
272 println("No realm specified in smb.conf file, assuming '" + realm + "'");
276 subobj.REALM = realm;
277 subobj.DOMAIN = domainname;
278 subobj.HOSTNAME = hostname();
280 assert(subobj.REALM);
281 assert(subobj.DOMAIN);
282 assert(subobj.HOSTNAME);
284 subobj.HOSTIP = hostip();
285 if (domsec != undefined) {
286 subobj.DOMAINGUID = domsec.guid;
287 subobj.DOMAINSID = domsec.sid;
289 println("Can't find domain secrets for '" + domainname + "'; using random SID and GUID");
290 subobj.DOMAINGUID = randguid();
291 subobj.DOMAINSID = randsid();
295 subobj.HOSTGUID = hostsec.guid;
297 subobj.HOSTGUID = randguid();
299 subobj.INVOCATIONID = randguid();
300 subobj.KRBTGTPASS = randpass(12);
301 subobj.MACHINEPASS = randpass(12);
302 subobj.ADMINPASS = randpass(12);
303 subobj.DEFAULTSITE = "Default-First-Site-Name";
304 subobj.NEWGUID = randguid;
305 subobj.NTTIME = nttime;
306 subobj.LDAPTIME = ldaptime;
307 subobj.DATESTRING = datestring;
308 subobj.USN = nextusn;
309 subobj.ROOT = findnss(nss.getpwnam, "root");
310 subobj.NOBODY = findnss(nss.getpwnam, "nobody");
311 subobj.NOGROUP = findnss(nss.getgrnam, "nogroup", "nobody");
312 subobj.WHEEL = findnss(nss.getgrnam, "wheel", "root");
313 subobj.USERS = findnss(nss.getgrnam, "users", "guest", "other");
314 subobj.DNSDOMAIN = strlower(subobj.REALM);
315 subobj.DNSNAME = sprintf("%s.%s",
316 strlower(subobj.HOSTNAME),
318 subobj.BASEDN = "DC=" + join(",DC=", split(".", subobj.REALM));
319 rdn_list = split(".", subobj.REALM);
323 smbconf_keep = new Array(
337 "bind interfaces only",
342 "obey pam restrictions",
350 "client NTLMv2 auth",
351 "client lanman auth",
352 "client plaintext auth",
372 "name resolve order",
381 "paranoid server security",
418 "winbind separator");
421 Remove configuration variables not present in Samba4
422 oldconf: Old configuration structure
423 mark: Whether removed configuration variables should be
424 kept in the new configuration as "samba3:<name>"
426 function upgrade_smbconf(oldconf,mark)
428 var data = oldconf.data();
429 var newconf = param_init();
431 for (var s in data) {
432 for (var p in data[s]) {
434 for (var k in smbconf_keep) {
435 if (smbconf_keep[k] == p) {
442 newconf.set(s, p, oldconf.get(s, p));
444 newconf.set(s, "samba3:"+p, oldconf.get(s,p));
452 function upgrade(subobj, samba3, message, paths)
455 var lp = loadparm_init();
456 var samdb = ldb_init();
457 var ok = samdb.connect(paths.samdb);
460 message("Writing configuration\n");
461 var newconf = upgrade_smbconf(samba3.configuration,true);
462 newconf.save(paths.smbconf);
464 message("Importing account policies\n");
465 var ldif = upgrade_sam_policy(samba3,subobj.BASEDN);
466 ok = samdb.modify(ldif);
469 message("Importing users\n");
470 for (var i in samba3.samaccounts) {
471 var msg = "... " + samba3.samaccounts[i].username;
472 var ldif = upgrade_sam_account(samdb,samba3.samaccounts[i],subobj.BASEDN,subobj.DOMAINSID);
473 ok = samdb.add(ldif);
474 if (!ok && samdb.errstring() != "Record exists") {
475 msg = msg + "... error: " + samdb.errstring();
481 message("Importing groups\n");
482 for (var i in samba3.groupmappings) {
483 var msg = "... " + samba3.groupmappings[i].nt_name;
484 var ldif = upgrade_sam_group(samba3.groupmappings[i],subobj.BASEDN);
485 if (ldif != undefined) {
486 ok = samdb.add(ldif);
487 if (!ok && samdb.errstring() != "Record exists") {
488 msg = msg + "... error: " + samdb.errstring();
495 message("Importing registry data\n");
496 var hives = new Array("hkcr","hkcu","hklm","hkpd","hku","hkpt");
497 for (var i in hives) {
499 message("... " + hn + "\n");
500 var regdb = ldb_init();
501 ok = regdb.connect(paths[hn]);
503 var ldif = upgrade_registry(samba3.registry, hn, regdb);
504 for (var j in ldif) {
505 var msg = "... ... " + j;
506 ok = regdb.add(ldif[j]);
507 if (!ok && regdb.errstring() != "Record exists") {
508 msg = msg + "... error: " + regdb.errstring();
515 message("Importing WINS data\n");
516 var winsdb = ldb_init();
517 ok = winsdb.connect(paths.winsdb);
521 var ldif = upgrade_wins(samba3);
522 ok = winsdb.add(ldif);
525 // figure out ldapurl, if applicable
526 var ldapurl = undefined;
527 var pdb = samba3.configuration.get_list("passdb backend");
528 if (pdb != undefined) {
530 if (substr(pdb[b], 0, 7) == "ldapsam") {
531 ldapurl = substr(pdb[b], 8);
536 // URL was not specified in passdb backend but ldap /is/ used
538 ldapurl = "ldap://" + samba3.configuration.get("ldap server");
541 // Enable samba3sam module if original passdb backend was ldap
542 if (ldapurl != undefined) {
543 message("Enabling Samba3 LDAP mappings for SAM database\n");
546 @MAP_URL: %s", ldapurl);
547 ok = samdb.add(ldif);
554 @LIST: samldb,timestamps,objectguid,rdn_name,samba3sam
557 message("Error enabling samba3sam module: " + samdb.errstring() + "\n");
565 function upgrade_verify(subobj, samba3,paths,message)
567 message("Verifying account policies\n");
568 var samldb = ldb_init();
571 var ok = samldb.connect(paths.samdb);
574 for (var i in samba3.samaccounts) {
575 var msg = samldb.search("(&(sAMAccountName=" + samba3.samaccounts[i].nt_username + ")(objectclass=user))");
576 assert(msg.length >= 1);