예제 #1
0
    def run(self, H=None, credopts=None, sambaopts=None, versionopts=None):
        lp = sambaopts.get_loadparm()
        creds = credopts.get_credentials(lp, fallback_machine=True)

        samdb = SamDB(url=H, session_info=system_session(),
            credentials=creds, lp=lp)

        domain_dn = samdb.domain_dn()
        forest_dn = samba.dn_from_dns_name(samdb.forest_dns_name())
        infrastructure_dn = "CN=Infrastructure," + domain_dn
        naming_dn = "CN=Partitions,%s" % samdb.get_config_basedn()
        schema_dn = samdb.get_schema_basedn()
        rid_dn = "CN=RID Manager$,CN=System," + domain_dn
        domaindns_dn = "CN=Infrastructure,DC=DomainDnsZones," + domain_dn
        forestdns_dn = "CN=Infrastructure,DC=ForestDnsZones," + forest_dn

        masters = [(schema_dn, "schema", "SchemaMasterRole"),
                   (infrastructure_dn, "infrastructure", "InfrastructureMasterRole"),
                   (rid_dn, "rid", "RidAllocationMasterRole"),
                   (domain_dn, "pdc", "PdcEmulationMasterRole"),
                   (naming_dn, "naming", "DomainNamingMasterRole"),
                   (domaindns_dn, "domaindns", "DomainDnsZonesMasterRole"),
                   (forestdns_dn, "forestdns", "ForestDnsZonesMasterRole"),
        ]

        for master in masters:
            (dn, short_name, long_name) = master
            try:
                master = get_fsmo_roleowner(samdb, dn, short_name)
                if master is not None:
                    self.message("%s owner: %s" % (long_name, str(master)))
                else:
                    self.message("%s has no current owner" % (long_name))
            except CommandError, e:
                self.message("%s: * %s" % (long_name, e.message))
예제 #2
0
    def run(self, H=None, credopts=None, sambaopts=None, versionopts=None):
        lp = sambaopts.get_loadparm()
        creds = credopts.get_credentials(lp, fallback_machine=True)

        samdb = SamDB(url=H,
                      session_info=system_session(),
                      credentials=creds,
                      lp=lp)

        domain_dn = samdb.domain_dn()
        forest_dn = samba.dn_from_dns_name(samdb.forest_dns_name())
        infrastructure_dn = "CN=Infrastructure," + domain_dn
        naming_dn = "CN=Partitions,%s" % samdb.get_config_basedn()
        schema_dn = samdb.get_schema_basedn()
        rid_dn = "CN=RID Manager$,CN=System," + domain_dn
        domaindns_dn = "CN=Infrastructure,DC=DomainDnsZones," + domain_dn
        forestdns_dn = "CN=Infrastructure,DC=ForestDnsZones," + forest_dn

        infrastructureMaster = get_fsmo_roleowner(samdb, infrastructure_dn)
        pdcEmulator = get_fsmo_roleowner(samdb, domain_dn)
        namingMaster = get_fsmo_roleowner(samdb, naming_dn)
        schemaMaster = get_fsmo_roleowner(samdb, schema_dn)
        ridMaster = get_fsmo_roleowner(samdb, rid_dn)
        domaindnszonesMaster = get_fsmo_roleowner(samdb, domaindns_dn)
        forestdnszonesMaster = get_fsmo_roleowner(samdb, forestdns_dn)

        self.message("SchemaMasterRole owner: " + schemaMaster)
        self.message("InfrastructureMasterRole owner: " + infrastructureMaster)
        self.message("RidAllocationMasterRole owner: " + ridMaster)
        self.message("PdcEmulationMasterRole owner: " + pdcEmulator)
        self.message("DomainNamingMasterRole owner: " + namingMaster)
        self.message("DomainDnsZonesMasterRole owner: " + domaindnszonesMaster)
        self.message("ForestDnsZonesMasterRole owner: " + forestdnszonesMaster)
예제 #3
0
    def run(self, H=None, credopts=None, sambaopts=None, versionopts=None):
        lp = sambaopts.get_loadparm()
        creds = credopts.get_credentials(lp, fallback_machine=True)

        samdb = SamDB(url=H, session_info=system_session(),
            credentials=creds, lp=lp)

        domain_dn = samdb.domain_dn()
        forest_dn = samba.dn_from_dns_name(samdb.forest_dns_name())
        infrastructure_dn = "CN=Infrastructure," + domain_dn
        naming_dn = "CN=Partitions,%s" % samdb.get_config_basedn()
        schema_dn = samdb.get_schema_basedn()
        rid_dn = "CN=RID Manager$,CN=System," + domain_dn
        domaindns_dn = "CN=Infrastructure,DC=DomainDnsZones," + domain_dn
        forestdns_dn = "CN=Infrastructure,DC=ForestDnsZones," + forest_dn

        infrastructureMaster = get_fsmo_roleowner(samdb, infrastructure_dn)
        pdcEmulator = get_fsmo_roleowner(samdb, domain_dn)
        namingMaster = get_fsmo_roleowner(samdb, naming_dn)
        schemaMaster = get_fsmo_roleowner(samdb, schema_dn)
        ridMaster = get_fsmo_roleowner(samdb, rid_dn)
        domaindnszonesMaster = get_fsmo_roleowner(samdb, domaindns_dn)
        forestdnszonesMaster = get_fsmo_roleowner(samdb, forestdns_dn)

        self.message("SchemaMasterRole owner: " + schemaMaster)
        self.message("InfrastructureMasterRole owner: " + infrastructureMaster)
        self.message("RidAllocationMasterRole owner: " + ridMaster)
        self.message("PdcEmulationMasterRole owner: " + pdcEmulator)
        self.message("DomainNamingMasterRole owner: " + namingMaster)
        self.message("DomainDnsZonesMasterRole owner: " + domaindnszonesMaster)
        self.message("ForestDnsZonesMasterRole owner: " + forestdnszonesMaster)
예제 #4
0
    def run(self,
            sambaopts=None,
            credopts=None,
            backup_file=None,
            targetdir=None,
            newservername=None,
            host_ip=None,
            host_ip6=None):
        if not (backup_file and os.path.exists(backup_file)):
            raise CommandError('Backup file not found.')
        if targetdir is None:
            raise CommandError('Please specify a target directory')
        # allow restoredc to install into a directory prepopulated by selftest
        if (os.path.exists(targetdir) and os.listdir(targetdir)
                and os.environ.get('SAMBA_SELFTEST') != '1'):
            raise CommandError('Target directory is not empty')
        if not newservername:
            raise CommandError('Server name required')

        logger = logging.getLogger()
        logger.setLevel(logging.DEBUG)
        logger.addHandler(logging.StreamHandler(sys.stdout))

        # ldapcmp prefers the server's netBIOS name in upper-case
        newservername = newservername.upper()

        # extract the backup .tar to a temp directory
        targetdir = os.path.abspath(targetdir)
        tf = tarfile.open(backup_file)
        tf.extractall(targetdir)
        tf.close()

        # use the smb.conf that got backed up, by default (save what was
        # actually backed up, before we mess with it)
        smbconf = os.path.join(targetdir, 'etc', 'smb.conf')
        shutil.copyfile(smbconf, smbconf + ".orig")

        # if a smb.conf was specified on the cmd line, then use that instead
        cli_smbconf = sambaopts.get_loadparm_path()
        if cli_smbconf:
            logger.info("Using %s as restored domain's smb.conf" % cli_smbconf)
            shutil.copyfile(cli_smbconf, smbconf)

        lp = samba.param.LoadParm()
        lp.load(smbconf)

        # open a DB connection to the restored DB
        private_dir = os.path.join(targetdir, 'private')
        samdb_path = os.path.join(private_dir, 'sam.ldb')
        samdb = SamDB(url=samdb_path, session_info=system_session(), lp=lp)

        # Create account using the join_add_objects function in the join object
        # We need namingContexts, account control flags, and the sid saved by
        # the backup process.
        res = samdb.search(base="",
                           scope=ldb.SCOPE_BASE,
                           attrs=['namingContexts'])
        ncs = [str(r) for r in res[0].get('namingContexts')]

        creds = credopts.get_credentials(lp)
        ctx = DCJoinContext(logger,
                            creds=creds,
                            lp=lp,
                            forced_local_samdb=samdb,
                            netbios_name=newservername)
        ctx.nc_list = ncs
        ctx.full_nc_list = ncs
        ctx.userAccountControl = (samba.dsdb.UF_SERVER_TRUST_ACCOUNT
                                  | samba.dsdb.UF_TRUSTED_FOR_DELEGATION)

        # rewrite the smb.conf to make sure it uses the new targetdir settings.
        # (This doesn't update all filepaths in a customized config, but it
        # corrects the same paths that get set by a new provision)
        logger.info('Updating basic smb.conf settings...')
        make_smbconf(smbconf,
                     newservername,
                     ctx.domain_name,
                     ctx.realm,
                     targetdir,
                     lp=lp,
                     serverrole="active directory domain controller")

        # Get the SID saved by the backup process and create account
        res = samdb.search(base=ldb.Dn(samdb, "@SAMBA_DSDB"),
                           scope=ldb.SCOPE_BASE,
                           attrs=['sidForRestore', 'backupRename'])
        is_rename = True if 'backupRename' in res[0] else False
        sid = res[0].get('sidForRestore')[0]
        logger.info('Creating account with SID: ' + str(sid))
        ctx.join_add_objects(specified_sid=dom_sid(sid))

        m = ldb.Message()
        m.dn = ldb.Dn(samdb, '@ROOTDSE')
        ntds_guid = str(ctx.ntds_guid)
        m["dsServiceName"] = ldb.MessageElement("<GUID=%s>" % ntds_guid,
                                                ldb.FLAG_MOD_REPLACE,
                                                "dsServiceName")
        samdb.modify(m)

        # if we renamed the backed-up domain, then we need to add the DNS
        # objects for the new realm (we do this in the restore, now that we
        # know the new DC's IP address)
        if is_rename:
            self.register_dns_zone(logger, samdb, lp, ctx.ntds_guid, host_ip,
                                   host_ip6)

        secrets_path = os.path.join(private_dir, 'secrets.ldb')
        secrets_ldb = Ldb(secrets_path, session_info=system_session(), lp=lp)
        secretsdb_self_join(secrets_ldb,
                            domain=ctx.domain_name,
                            realm=ctx.realm,
                            dnsdomain=ctx.dnsdomain,
                            netbiosname=ctx.myname,
                            domainsid=ctx.domsid,
                            machinepass=ctx.acct_pass,
                            key_version_number=ctx.key_version_number,
                            secure_channel_type=misc.SEC_CHAN_BDC)

        # Seize DNS roles
        domain_dn = samdb.domain_dn()
        forest_dn = samba.dn_from_dns_name(samdb.forest_dns_name())
        domaindns_dn = ("CN=Infrastructure,DC=DomainDnsZones,", domain_dn)
        forestdns_dn = ("CN=Infrastructure,DC=ForestDnsZones,", forest_dn)
        for dn_prefix, dns_dn in [forestdns_dn, domaindns_dn]:
            if dns_dn not in ncs:
                continue
            full_dn = dn_prefix + dns_dn
            m = ldb.Message()
            m.dn = ldb.Dn(samdb, full_dn)
            m["fSMORoleOwner"] = ldb.MessageElement(samdb.get_dsServiceName(),
                                                    ldb.FLAG_MOD_REPLACE,
                                                    "fSMORoleOwner")
            samdb.modify(m)

        # Seize other roles
        for role in ['rid', 'pdc', 'naming', 'infrastructure', 'schema']:
            self.seize_role(role, samdb, force=True)

        # Get all DCs and remove them (this ensures these DCs cannot
        # replicate because they will not have a password)
        search_expr = "(&(objectClass=Server)(serverReference=*))"
        res = samdb.search(samdb.get_config_basedn(),
                           scope=ldb.SCOPE_SUBTREE,
                           expression=search_expr)
        for m in res:
            cn = m.get('cn')[0]
            if cn != newservername:
                remove_dc(samdb, logger, cn)

        # Remove the repsFrom and repsTo from each NC to ensure we do
        # not try (and fail) to talk to the old DCs
        for nc in ncs:
            msg = ldb.Message()
            msg.dn = ldb.Dn(samdb, nc)

            msg["repsFrom"] = ldb.MessageElement([], ldb.FLAG_MOD_REPLACE,
                                                 "repsFrom")
            msg["repsTo"] = ldb.MessageElement([], ldb.FLAG_MOD_REPLACE,
                                               "repsTo")
            samdb.modify(msg)

        # Update the krbtgt passwords twice, ensuring no tickets from
        # the old domain are valid
        update_krbtgt_account_password(samdb)
        update_krbtgt_account_password(samdb)

        # restore the sysvol directory from the backup tar file, including the
        # original NTACLs. Note that the backup_restore() will fail if not root
        sysvol_tar = os.path.join(targetdir, 'sysvol.tar.gz')
        dest_sysvol_dir = lp.get('path', 'sysvol')
        if not os.path.exists(dest_sysvol_dir):
            os.makedirs(dest_sysvol_dir)
        backup_restore(sysvol_tar, dest_sysvol_dir, samdb, smbconf)
        os.remove(sysvol_tar)

        # fix up any stale links to the old DCs we just removed
        logger.info("Fixing up any remaining references to the old DCs...")
        self.fix_old_dc_references(samdb)

        # Remove DB markers added by the backup process
        m = ldb.Message()
        m.dn = ldb.Dn(samdb, "@SAMBA_DSDB")
        m["backupDate"] = ldb.MessageElement([], ldb.FLAG_MOD_DELETE,
                                             "backupDate")
        m["sidForRestore"] = ldb.MessageElement([], ldb.FLAG_MOD_DELETE,
                                                "sidForRestore")
        if is_rename:
            m["backupRename"] = ldb.MessageElement([], ldb.FLAG_MOD_DELETE,
                                                   "backupRename")
        samdb.modify(m)

        logger.info("Backup file successfully restored to %s" % targetdir)
        logger.info("Please check the smb.conf settings are correct before "
                    "starting samba.")