r26608: More improvements to the upgrade code.
authorJelmer Vernooij <jelmer@samba.org>
Thu, 27 Dec 2007 09:09:49 +0000 (03:09 -0600)
committerStefan Metzmacher <metze@samba.org>
Thu, 27 Dec 2007 03:18:02 +0000 (21:18 -0600)
(This used to be commit 7ea06d91f602f770f55a1171174f11b922fed8e7)

source4/scripting/python/samba/provision.py
source4/scripting/python/samba/samba3.py
source4/scripting/python/samba/tests/samba3.py
source4/scripting/python/samba/tests/upgrade.py
source4/scripting/python/samba/upgrade.py

index c4a3bb7fd60f7ad11e00ec1a8f23b6ee1912b6a7..53eb1d618f60067af74f8ccce0fd41dc678ff76c 100644 (file)
@@ -745,6 +745,8 @@ def provision(lp, setup_dir, message, blank, paths, session_info,
                       domainguid=domainguid, hostguid=hostguid)
         message("Please install the zone located in %s into your DNS server" % paths.dns)
 
+    return domaindn
+
 def create_phplpapdadmin_config(path, setup_path, s4_ldapi_path):
     setup_file(setup_path("phpldapadmin-config.php"), 
                path, {"S4_LDAPI_URI": "ldapi://%s" % s4_ldapi_path.replace("/", "%2F")})
index df94f3503c1cdead8ea197a353193350b2225775..c9153d85cf451810dcf2255a9464fe805f3ace09 100644 (file)
@@ -118,6 +118,15 @@ class GroupMappingDatabase:
             if k.startswith(GROUP_PREFIX):
                 yield k[len(GROUP_PREFIX):].rstrip("\0")
 
+    def get_group(self, sid):
+        data = self.tdb.get("%s%s\0" % (GROUP_PREFIX, sid))
+        if data is None:
+            return data
+        import struct
+        (gid, sid_name_use) = struct.unpack("<lL", data[0:8])
+        (nt_name, comment, _) = data[8:].split("\0")
+        return (gid, sid_name_use, nt_name, comment)
+
     def aliases(self):
         for k in self.tdb.keys():
             if k.startswith(MEMBEROF_PREFIX):
@@ -288,15 +297,15 @@ ACB_NO_AUTH_DATA_REQD = 0x00080000
 acb_info_mapping = {
         'N': ACB_PWNOTREQ,  # 'N'o password. 
         'D': ACB_DISABLED,  # 'D'isabled.
-               'H': ACB_HOMDIRREQ, # 'H'omedir required.
-               'T': ACB_TEMPDUP,   # 'T'emp account.
-               'U': ACB_NORMAL,    # 'U'ser account (normal).
-               'M': ACB_MNS,       # 'M'NS logon user account. What is this ?
-               'W': ACB_WSTRUST,   # 'W'orkstation account.
-               'S': ACB_SVRTRUST,  # 'S'erver account. 
-               'L': ACB_AUTOLOCK,  # 'L'ocked account.
-               'X': ACB_PWNOEXP,   # No 'X'piry on password
-               'I': ACB_DOMTRUST,  # 'I'nterdomain trust account.
+        'H': ACB_HOMDIRREQ, # 'H'omedir required.
+        'T': ACB_TEMPDUP,   # 'T'emp account.
+        'U': ACB_NORMAL,    # 'U'ser account (normal).
+        'M': ACB_MNS,       # 'M'NS logon user account. What is this ?
+        'W': ACB_WSTRUST,   # 'W'orkstation account.
+        'S': ACB_SVRTRUST,  # 'S'erver account. 
+        'L': ACB_AUTOLOCK,  # 'L'ocked account.
+        'X': ACB_PWNOEXP,   # No 'X'piry on password
+        'I': ACB_DOMTRUST,  # 'I'nterdomain trust account.
         ' ': 0
         }
 
@@ -308,6 +317,72 @@ def decode_acb(text):
     return ret
 
 
+class SAMUser:
+    def __init__(self, name, uid=None, lm_password=None, nt_password=None, acct_ctrl=None, 
+                 last_change_time=None, nt_username=None, fullname=None, logon_time=None, logoff_time=None,
+                 acct_desc=None, group_rid=None, bad_password_count=None, logon_count=None,
+                 domain=None, dir_drive=None, munged_dial=None, homedir=None, logon_script=None,
+                 profile_path=None, workstations=None, kickoff_time=None, bad_password_time=None,
+                 pass_last_set_time=None, pass_can_change_time=None, pass_must_change_time=None,
+                 user_rid=None):
+        self.username = name
+        self.uid = uid
+        self.lm_password = lm_password
+        self.nt_password = nt_password
+        self.acct_ctrl = acct_ctrl
+        self.pass_last_set_time = last_change_time
+        self.nt_username = nt_username
+        self.fullname = fullname
+        self.logon_time = logon_time
+        self.logoff_time = logoff_time
+        self.acct_desc = acct_desc
+        self.group_rid = group_rid
+        self.bad_password_count = bad_password_count
+        self.logon_count = logon_count
+        self.domain = domain
+        self.dir_drive = dir_drive
+        self.munged_dial = munged_dial
+        self.homedir = homedir
+        self.logon_script = logon_script
+        self.profile_path = profile_path
+        self.workstations = workstations
+        self.kickoff_time = kickoff_time
+        self.bad_password_time = bad_password_time
+        self.pass_can_change_time = pass_can_change_time
+        self.pass_must_change_time = pass_must_change_time
+        self.user_rid = user_rid
+
+    def __eq__(self, other): 
+        if not isinstance(other, SAMUser):
+            return False
+        return (self.username == other.username and 
+                self.uid == other.uid and 
+                self.lm_password == other.lm_password and 
+                self.nt_password == other.nt_password and 
+                self.acct_ctrl == other.acct_ctrl and 
+                self.pass_last_set_time == other.pass_last_set_time and 
+                self.nt_username == other.nt_username and 
+                self.fullname == other.fullname and 
+                self.logon_time == other.logon_time and 
+                self.logoff_time == other.logoff_time and 
+                self.acct_desc == other.acct_desc and 
+                self.group_rid == other.group_rid and 
+                self.bad_password_count == other.bad_password_count and 
+                self.logon_count == other.logon_count and 
+                self.domain == other.domain and 
+                self.dir_drive == other.dir_drive and 
+                self.munged_dial == other.munged_dial and 
+                self.homedir == other.homedir and 
+                self.logon_script == other.logon_script and 
+                self.profile_path == other.profile_path and 
+                self.workstations == other.workstations and 
+                self.kickoff_time == other.kickoff_time and 
+                self.bad_password_time == other.bad_password_time and 
+                self.pass_can_change_time == other.pass_can_change_time and 
+                self.pass_must_change_time == other.pass_must_change_time and 
+                self.user_rid == other.user_rid)
+
+
 class SmbpasswdFile:
     def __init__(self, file):
         self.users = {}
@@ -345,7 +420,7 @@ class SmbpasswdFile:
                     acct_ctrl &= ~ACB_NORMAL
                     acct_ctrl |= ACB_WSTRUST
 
-            self.users[username] = (uid, lm_password, nt_password, acct_ctrl, last_change_time)
+            self.users[username] = SAMUser(username, uid, lm_password, nt_password, acct_ctrl, last_change_time)
 
         f.close()
 
@@ -368,6 +443,11 @@ TDBSAM_FORMAT_STRING_V2 = "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
 TDBSAM_USER_PREFIX = "USER_"
 
 
+class LdapSam:
+    def __init__(self, url):
+        self.ldap_url = ldap_url
+
+
 class TdbSam:
     def __init__(self, file):
         self.tdb = tdb.Tdb(file, flags=os.O_RDONLY)
@@ -380,6 +460,45 @@ class TdbSam:
                 yield k[len(TDBSAM_USER_PREFIX):].rstrip("\0")
 
     __iter__ = usernames
+    
+    def __getitem__(self, name):
+        data = self.tdb["%s%s\0" % (TDBSAM_USER_PREFIX, name)]
+        import struct
+        (logon_time, logoff_time, kickoff_time, pass_last_set_time, pass_can_change_time, \
+                pass_must_change_time) = struct.unpack("<llllll", data[:6*4])
+        user = SAMUser(name)
+        user.logon_time = logon_time
+        user.logoff_time = logoff_time
+        user.kickoff_time = kickoff_time
+        user.pass_last_set_time = pass_last_set_time
+        user.pass_can_change_time = pass_can_change_time
+
+#      &username_len, &sampass->username,                      /* B */
+#              &domain_len, &sampass->domain,                          /* B */
+#              &nt_username_len, &sampass->nt_username,                /* B */
+#              &fullname_len, &sampass->fullname,                      /* B */
+#              &homedir_len, &sampass->homedir,                        /* B */
+#              &dir_drive_len, &sampass->dir_drive,                    /* B */
+#              &logon_script_len, &sampass->logon_script,              /* B */
+#              &profile_path_len, &sampass->profile_path,              /* B */
+#              &acct_desc_len, &sampass->acct_desc,                    /* B */
+#              &workstations_len, &sampass->workstations,              /* B */
+#              &unknown_str_len, &sampass->unknown_str,                /* B */
+#              &munged_dial_len, &sampass->munged_dial,                /* B */
+#              &sampass->user_rid,                                     /* d */
+#              &sampass->group_rid,                                    /* d */
+#              &lm_pw_len, sampass->lm_pw.hash,                        /* B */
+#              &nt_pw_len, sampass->nt_pw.hash,                        /* B */
+#              &sampass->acct_ctrl,                                    /* w */
+#              &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */
+#              &sampass->logon_divs,                                   /* w */
+#              &sampass->hours_len,                                    /* d */
+#              &hourslen, &sampass->hours,                             /* B */
+#              &sampass->bad_password_count,                           /* w */
+#              &sampass->logon_count,                                  /* w */
+#              &sampass->unknown_6);                                   /* d */
+#              
+        return user
 
     def close(self):
         self.tdb.close()
@@ -423,7 +542,7 @@ class WinsDatabase:
             while "." in entries[i]:
                 ips.append(entries[i])
                 i+=1
-            nb_flags = entries[i]
+            nb_flags = int(entries[i][:-1], 16)
             assert not name in self.entries, "Name %s exists twice" % name
             self.entries[name] = (ttl, ips, nb_flags)
         f.close()
@@ -437,6 +556,9 @@ class WinsDatabase:
     def __iter__(self):
         return iter(self.entries)
 
+    def items(self):
+        return self.entries.items()
+
     def close(self): # for consistency
         pass
 
@@ -459,14 +581,19 @@ class Samba3:
     def get_sam_db(self):
         lp = self.get_conf()
         backends = str(lp.get("passdb backend")).split(" ")
-        if backends[0].startswith("smbpasswd"):
-            if ":" in backends[0]:
-                return SmbpasswdFile(self.libdir_path(backends[0][len("smbpasswd:"):]))
-            return SmbpasswdFile(self.libdir_path("smbpasswd"))
-        elif backends[0].startswith("tdbsam"):
-            if ":" in backends[0]:
-                return TdbSam(self.libdir_path(backends[0][len("tdbsam:"):]))
-            return TdbSam(self.libdir_path("passdb.tdb"))
+        if ":" in backends[0]:
+            (name, location) = backends[0].split(":", 2)
+        else:
+            name = backends[0]
+            location = None
+        if name == "smbpasswd":
+            return SmbpasswdFile(self.libdir_path(location or "smbpasswd"))
+        elif name == "tdbsam":
+            return TdbSam(self.libdir_path(location or "passdb.tdb"))
+        elif name == "ldapsam":
+            if location is not None:
+                return LdapSam("ldap:%s" % location)
+            return LdapSam(lp.get("ldap server"))
         else:
             raise NotImplementedError("unsupported passdb backend %s" % backends[0])
 
index e25562929a73c433093e96ac992234f3a30f7df0..22b21ba1b496196d68ece2fef3682952501c5508 100644 (file)
@@ -19,7 +19,7 @@
 
 import unittest
 from samba.samba3 import (GroupMappingDatabase, Registry, PolicyDatabase, SecretsDatabase, TdbSam,
-                          WinsDatabase, SmbpasswdFile, ACB_NORMAL, IdmapDatabase)
+                          WinsDatabase, SmbpasswdFile, ACB_NORMAL, IdmapDatabase, SAMUser)
 import os
 
 DATADIR=os.path.join(os.path.dirname(__file__), "../../../../../testdata/samba3")
@@ -74,6 +74,9 @@ class GroupsTestCase(unittest.TestCase):
     def test_group_length(self):
         self.assertEquals(13, len(list(self.groupdb.groupsids())))
 
+    def test_get_group(self):
+        self.assertEquals((-1, 5L, 'Administrators', ''), self.groupdb.get_group("S-1-5-32-544"))
+
     def test_groupsids(self):
         sids = list(self.groupdb.groupsids())
         self.assertTrue("S-1-5-32-544" in sids)
@@ -103,6 +106,11 @@ class TdbSamTestCase(unittest.TestCase):
     def test_usernames(self):
         self.assertEquals(3, len(list(self.samdb.usernames())))
 
+    def test_getuser(self):
+        return
+        user = SAMUser("root")
+        self.assertEquals(user, self.samdb["root"])
+
 
 class WinsDatabaseTestCase(unittest.TestCase):
     def setUp(self):
@@ -112,7 +120,7 @@ class WinsDatabaseTestCase(unittest.TestCase):
         self.assertEquals(22, len(self.winsdb))
 
     def test_first_entry(self):
-        self.assertEqual((1124185120, ["192.168.1.5"], "64R"), self.winsdb["ADMINISTRATOR#03"])
+        self.assertEqual((1124185120, ["192.168.1.5"], 0x64), self.winsdb["ADMINISTRATOR#03"])
 
     def tearDown(self):
         self.winsdb.close()
@@ -125,7 +133,13 @@ class SmbpasswdTestCase(unittest.TestCase):
         self.assertEquals(3, len(self.samdb))
 
     def test_get_user(self):
-        self.assertEquals((0, "552902031BEDE9EFAAD3B435B51404EE", "878D8014606CDA29677A44EFA1353FC7", ACB_NORMAL, int(1125418267)), self.samdb["rootpw"])
+        user = SAMUser("rootpw")
+        user.lm_password = "552902031BEDE9EFAAD3B435B51404EE"
+        user.nt_password = "878D8014606CDA29677A44EFA1353FC7"
+        user.acct_ctrl = ACB_NORMAL
+        user.pass_last_set_time = int(1125418267)
+        user.uid = 0
+        self.assertEquals(user, self.samdb["rootpw"])
 
     def tearDown(self):
         self.samdb.close()
index a25743425bb3495c87083f058b29afbc7d72bc74..ddafa00691b79a380bf66adda49f69387b6dd0a6 100644 (file)
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
-from samba.upgrade import regkey_to_dn
+import samba.upgrade
 from unittest import TestCase
 
-class RegkeyDnTests(TestCase):
-    def test_empty(self):
-        self.assertEquals("hive=NONE", regkey_to_dn(""))
-
-    def test_nested(self):
-        self.assertEquals("key=bar,key=foo,hive=NONE", regkey_to_dn("foo/bar"))
index a6bd07df58dd29189910fc72a5fc42388ef813f0..3ecfe872f9ec354e11e4f5171ef6476f0afe16bc 100644 (file)
@@ -9,20 +9,15 @@
 
 from provision import findnss, provision
 import grp
+import ldb
 import pwd
 import uuid
 import registry
+from samba import Ldb
+from samba.samdb import SamDB
 
-# Where prefix is any of:
-# - HKLM
-#   HKU
-#   HKCR
-#   HKPD
-#   HKPT
-#
-
-def upgrade_sam_policy(policy,dn):
-    ldif = """
+def import_sam_policy(samldb, samba3_policy, domaindn):
+    samldb.modify_ldif("""
 dn: %s
 changetype: modify
 replace: minPwdLength
@@ -40,19 +35,24 @@ samba3DisconnectTime: %d
     policy.password_history, policy.minimum_password_age,
     policy.maximum_password_age, policy.lockout_duration,
     policy.reset_count_minutes, policy.user_must_logon_to_change_password,
-    policy.bad_lockout_minutes, policy.disconnect_time)
-    
-    return ldif
+    policy.bad_lockout_minutes, policy.disconnect_time))
+
 
-def upgrade_sam_account(ldb,acc,domaindn,domainsid):
-    """Upgrade a SAM account."""
+def import_sam_account(samldb,acc,domaindn,domainsid):
+    """Import a Samba 3 SAM account.
+    
+    :param samldb: Samba 4 SAM Database handle
+    :param acc: Samba 3 account
+    :param domaindn: Domain DN
+    :param domainsid: Domain SID."""
     if acc.nt_username is None or acc.nt_username == "":
         acc.nt_username = acc.username
 
     if acc.fullname is None:
-        acc.fullname = pwd.getpwnam(acc.fullname)[4]
-
-    acc.fullname = acc.fullname.split(",")[0]
+        try:
+            acc.fullname = pwd.getpwnam(acc.username)[4].split(",")[0]
+        except KeyError:
+            pass
 
     if acc.fullname is None:
         acc.fullname = acc.username
@@ -60,105 +60,113 @@ def upgrade_sam_account(ldb,acc,domaindn,domainsid):
     assert acc.fullname is not None
     assert acc.nt_username is not None
 
-    ldif = """dn: cn=%s,%s
-objectClass: top
-objectClass: user
-lastLogon: %d
-lastLogoff: %d
-unixName: %s
-sAMAccountName: %s
-cn: %s
-description: %s
-primaryGroupID: %d
-badPwdcount: %d
-logonCount: %d
-samba3Domain: %s
-samba3DirDrive: %s
-samba3MungedDial: %s
-samba3Homedir: %s
-samba3LogonScript: %s
-samba3ProfilePath: %s
-samba3Workstations: %s
-samba3KickOffTime: %d
-samba3BadPwdTime: %d
-samba3PassLastSetTime: %d
-samba3PassCanChangeTime: %d
-samba3PassMustChangeTime: %d
-objectSid: %s-%d
-lmPwdHash:: %s
-ntPwdHash:: %s
-
-""" % (ldb.dn_escape(acc.fullname), domaindn, acc.logon_time, acc.logoff_time, acc.username, acc.nt_username, acc.nt_username, 
-acc.acct_desc, acc.group_rid, acc.bad_password_count, acc.logon_count,
-acc.domain, acc.dir_drive, acc.munged_dial, acc.homedir, acc.logon_script, 
-acc.profile_path, acc.workstations, acc.kickoff_time, acc.bad_password_time, 
-acc.pass_last_set_time, acc.pass_can_change_time, acc.pass_must_change_time, domainsid, acc.user_rid,
-    ldb.encode(acc.lm_pw), ldb.encode(acc.nt_pw))
-
-    return ldif
-
-def upgrade_sam_group(group,domaindn):
-    """Upgrade a SAM group."""
-    if group.sid_name_use == 5: # Well-known group
+    samldb.add({
+        "dn": "cn=%s,%s" % (acc.fullname, domaindn),
+        "objectClass": ["top", "user"],
+        "lastLogon": str(acc.logon_time),
+        "lastLogoff": str(acc.logoff_time),
+        "unixName": acc.username,
+        "sAMAccountName": acc.nt_username,
+        "cn": acc.nt_username,
+        "description": acc.acct_desc,
+        "primaryGroupID": str(acc.group_rid),
+        "badPwdcount": str(acc.bad_password_count),
+        "logonCount": str(acc.logon_count),
+        "samba3Domain": acc.domain,
+        "samba3DirDrive": acc.dir_drive,
+        "samba3MungedDial": acc.munged_dial,
+        "samba3Homedir": acc.homedir, 
+        "samba3LogonScript": acc.logon_script, 
+        "samba3ProfilePath": acc.profile_path,
+        "samba3Workstations": acc.workstations,
+        "samba3KickOffTime": str(acc.kickoff_time),
+        "samba3BadPwdTime": str(acc.bad_password_time),
+        "samba3PassLastSetTime": str(acc.pass_last_set_time),
+        "samba3PassCanChangeTime": str(acc.pass_can_change_time),
+        "samba3PassMustChangeTime": str(acc.pass_must_change_time),
+        "objectSid": "%s-%d" % (domainsid, acc.user_rid),
+        "lmPwdHash:": acc.lm_password,
+        "ntPwdHash:": acc.nt_password,
+        })
+
+
+def import_sam_group(samldb, sid, gid, sid_name_use, nt_name, comment, domaindn):
+    """Upgrade a SAM group.
+    
+    :param samldb: SAM database.
+    :param gid: Group GID
+    :param sid_name_use: SID name use
+    :param nt_name: NT Group Name
+    :param comment: NT Group Comment
+    :param domaindn: Domain DN
+    """
+
+    if sid_name_use == 5: # Well-known group
         return None
 
-    if group.nt_name in ("Domain Guests", "Domain Users", "Domain Admins"):
+    if nt_name in ("Domain Guests", "Domain Users", "Domain Admins"):
         return None
     
-    if group.gid == -1:
-        gr = grp.getgrnam(grp.nt_name)
+    if gid == -1:
+        gr = grp.getgrnam(nt_name)
     else:
-        gr = grp.getgrgid(grp.gid)
+        gr = grp.getgrgid(gid)
 
     if gr is None:
-        group.unixname = "UNKNOWN"
+        unixname = "UNKNOWN"
     else:
-        group.unixname = gr.gr_name
+        unixname = gr.gr_name
 
-    assert group.unixname is not None
+    assert unixname is not None
     
-    ldif = """dn: cn=%s,%s
-objectClass: top
-objectClass: group
-description: %s
-cn: %s
-objectSid: %s
-unixName: %s
-samba3SidNameUse: %d
-""" % (group.nt_name, domaindn, 
-group.comment, group.nt_name, group.sid, group.unixname, group.sid_name_use)
-
-    return ldif
-
-def import_idmap(samba4_idmap,samba3_idmap,domaindn):
-    samba4_idmap.add({
+    samldb.add({
+        "dn": "cn=%s,%s" % (nt_name, domaindn),
+        "objectClass": ["top", "group"],
+        "description": comment,
+        "cn": nt_name, 
+        "objectSid": sid,
+        "unixName": unixname,
+        "samba3SidNameUse": str(sid_name_use)
+        })
+
+
+def import_idmap(samdb,samba3_idmap,domaindn):
+    """Import idmap data.
+
+    :param samdb: SamDB handle.
+    :param samba3_idmap: Samba 3 IDMAP database to import from
+    :param domaindn: Domain DN.
+    """
+    samdb.add({
         "dn": domaindn,
         "userHwm": str(samba3_idmap.get_user_hwm()),
         "groupHwm": str(samba3_idmap.get_group_hwm())})
 
     for uid in samba3_idmap.uids():
-        samba4_idmap.add({"dn": "SID=%s,%s" % (samba3_idmap.get_user_sid(uid), domaindn),
+        samdb.add({"dn": "SID=%s,%s" % (samba3_idmap.get_user_sid(uid), domaindn),
                           "SID": samba3_idmap.get_user_sid(uid),
                           "type": "user",
                           "unixID": str(uid)})
 
     for gid in samba3_idmap.uids():
-        samba4_idmap.add({"dn": "SID=%s,%s" % (samba3_idmap.get_group_sid(gid), domaindn),
+        samdb.add({"dn": "SID=%s,%s" % (samba3_idmap.get_group_sid(gid), domaindn),
                           "SID": samba3_idmap.get_group_sid(gid),
                           "type": "group",
                           "unixID": str(gid)})
 
 
 def import_wins(samba4_winsdb, samba3_winsdb):
-    """Import settings from a Samba3 WINS database."""
+    """Import settings from a Samba3 WINS database.
+    
+    :param samba4_winsdb: WINS database to import to
+    :param samba3_winsdb: WINS database to import from
+    """
     version_id = 0
     import time
 
     for (name, (ttl, ips, nb_flags)) in samba3_winsdb.items():
         version_id+=1
 
-        numIPs = len(e.ips)
-
         type = int(name.split("#", 1)[1], 16)
 
         if type == 0x1C:
@@ -181,14 +189,14 @@ def import_wins(samba4_winsdb, samba3_winsdb):
 
         nType = ((nb_flags & 0x60)>>5)
 
-        samba4_winsdb.add({"dn": "name=%s,type=0x%s" % name.split("#"),
+        samba4_winsdb.add({"dn": "name=%s,type=0x%s" % tuple(name.split("#")),
                            "type": name.split("#")[1],
                            "name": name.split("#")[0],
                            "objectClass": "winsRecord",
                            "recordType": str(rType),
                            "recordState": str(rState),
                            "nodeType": str(nType),
-                           "expireTime": ldb.ldaptime(ttl),
+                           "expireTime": ldb.timestring(ttl),
                            "isStatic": "0",
                            "versionID": str(version_id),
                            "address": ips})
@@ -237,9 +245,52 @@ def upgrade_provision(samba3, setup_dir, message, credentials, session_info, lp,
     else:
         machinepass = None
     
-    provision(lp=lp, setup_dir=setup_dir, message=message, blank=True, ldapbackend=None, paths=paths, session_info=session_info, 
-              credentials=credentials, realm=realm, domain=domainname, 
-              domainsid=domainsid, domainguid=domainguid, machinepass=machinepass, serverrole=serverrole)
+    domaindn = provision(lp=lp, setup_dir=setup_dir, message=message, blank=True, ldapbackend=None, 
+                         paths=paths, session_info=session_info, credentials=credentials, realm=realm, 
+                         domain=domainname, domainsid=domainsid, domainguid=domainguid, 
+                         machinepass=machinepass, serverrole=serverrole)
+
+    samdb = SamDB(paths.samdb, credentials=credentials, lp=lp, session_info=session_info)
+
+    import_wins(Ldb(paths.winsdb), samba3.get_wins_db())
+
+    # FIXME: import_registry(registry.Registry(), samba3.get_registry())
+
+    # FIXME: import_idmap(samdb,samba3.get_idmap_db(),domaindn)
+    
+    groupdb = samba3.get_groupmapping_db()
+    for sid in groupdb.groupsids():
+        (gid, sid_name_use, nt_name, comment) = groupdb.get_group(sid)
+        # FIXME: import_sam_group(samdb, sid, gid, sid_name_use, nt_name, comment, domaindn)
+
+    # FIXME: Aliases
+
+    passdb = samba3.get_sam_db()
+    for name in passdb:
+        user = passdb[name]
+        #FIXME: import_sam_account(samdb, user, domaindn, domainsid)
+
+    if hasattr(passdb, 'ldap_url'):
+        message("Enabling Samba3 LDAP mappings for SAM database")
+
+        enable_samba3sam(samdb, passdb.ldap_url)
+
+
+def enable_samba3sam(samdb, ldapurl):
+    """Enable Samba 3 LDAP URL database.
+
+    :param samdb: SAM Database.
+    :param ldapurl: Samba 3 LDAP URL
+    """
+    samdb.modify_ldif("""
+dn: @MODULES
+changetype: modify
+replace: @LIST
+@LIST: samldb,operational,objectguid,rdn_name,samba3sam
+""")
+
+    samdb.add({"dn": "@MAP=samba3sam", "@MAP_URL": ldapurl})
+
 
 smbconf_keep = [
     "dos charset", 
@@ -436,33 +487,4 @@ data: %d
     ldif = upgrade_wins(samba3)
     winsdb.add(ldif)
 
-    # figure out ldapurl, if applicable
-    ldapurl = None
-    pdb = samba3.configuration.get_list("passdb backend")
-    if pdb is not None:
-        for backend in pdb:
-            if len(backend) >= 7 and backend[0:7] == "ldapsam":
-                ldapurl = backend[7:]
-
-    # URL was not specified in passdb backend but ldap /is/ used
-    if ldapurl == "":
-        ldapurl = "ldap://%s" % samba3.configuration.get("ldap server")
 
-    # Enable samba3sam module if original passdb backend was ldap
-    if ldapurl is not None:
-        message("Enabling Samba3 LDAP mappings for SAM database")
-
-        enable_samba3sam(samdb)
-
-    return ret
-
-
-def enable_samba3sam(samdb):
-    samdb.modify("""
-dn: @MODULES
-changetype: modify
-replace: @LIST
-@LIST: samldb,operational,objectguid,rdn_name,samba3sam
-""")
-
-    samdb.add({"dn": "@MAP=samba3sam", "@MAP_URL": ldapurl})