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))
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)
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.")