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 join_subdomain(server=None, creds=None, lp=None, site=None, netbios_name=None, targetdir=None, parent_domain=None, dnsdomain=None, netbios_domain=None): """join as a DC""" ctx = dc_join(server, creds, lp, site, netbios_name, targetdir, parent_domain) ctx.subdomain = True ctx.parent_domain_name = ctx.domain_name ctx.domain_name = netbios_domain ctx.realm = dnsdomain ctx.parent_dnsdomain = ctx.dnsdomain ctx.parent_partition_dn = ctx.get_parent_partition_dn() ctx.dnsdomain = dnsdomain ctx.partition_dn = "CN=%s,CN=Partitions,%s" % (ctx.domain_name, ctx.config_dn) ctx.base_dn = samba.dn_from_dns_name(dnsdomain) ctx.domsid = str(security.random_sid()) ctx.acct_dn = None ctx.dnshostname = "%s.%s" % (ctx.myname, ctx.dnsdomain) ctx.trustdom_pass = samba.generate_random_password(128, 128) ctx.userAccountControl = samba.dsdb.UF_SERVER_TRUST_ACCOUNT | samba.dsdb.UF_TRUSTED_FOR_DELEGATION ctx.SPNs.append('E3514235-4B06-11D1-AB04-00C04FC2DCD2/$NTDSGUID/%s' % ctx.dnsdomain) ctx.secure_channel_type = misc.SEC_CHAN_BDC ctx.replica_flags = (drsuapi.DRSUAPI_DRS_WRIT_REP | drsuapi.DRSUAPI_DRS_INIT_SYNC | drsuapi.DRSUAPI_DRS_PER_SYNC | drsuapi.DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS | drsuapi.DRSUAPI_DRS_NEVER_SYNCED) ctx.domain_replica_flags = ctx.replica_flags ctx.do_join() print "Created domain %s (SID %s) as a DC" % (ctx.domain_name, ctx.domsid)
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 transfer_dns_role(outf, sambaopts, credopts, role, samdb): """Transfer dns FSMO role. """ if role == "domaindns": domain_dn = samdb.domain_dn() role_object = "CN=Infrastructure,DC=DomainDnsZones," + domain_dn elif role == "forestdns": forest_dn = samba.dn_from_dns_name(samdb.forest_dns_name()) role_object = "CN=Infrastructure,DC=ForestDnsZones," + forest_dn try: res = samdb.search(role_object, attrs=["fSMORoleOwner"], scope=ldb.SCOPE_BASE, controls=["extended_dn:1:1"]) if 'fSMORoleOwner' in res[0]: try: master_guid = str(misc.GUID(ldb.Dn(samdb, res[0]['fSMORoleOwner'][0]) .get_extended_component('GUID'))) master_owner = str(ldb.Dn(samdb, res[0]['fSMORoleOwner'][0])) except LdbError, (num, msg): raise CommandError("GUID not found in partition naming master DN %s : %s \n" % (res[0]['fSMORoleOwner'][0], msg)) except LdbError, (num, msg): raise CommandError("DNS partion %s not found : %s" % (role, msg))
def seize_dns_role(self, role, samdb, credopts, sambaopts, versionopts, force): """Seize DNS FSMO role. """ serviceName = samdb.get_dsServiceName() domain_dn = samdb.domain_dn() forest_dn = samba.dn_from_dns_name(samdb.forest_dns_name()) self.domaindns_dn = "CN=Infrastructure,DC=DomainDnsZones," + domain_dn self.forestdns_dn = "CN=Infrastructure,DC=ForestDnsZones," + forest_dn m = ldb.Message() if role == "domaindns": m.dn = ldb.Dn(samdb, self.domaindns_dn) elif role == "forestdns": m.dn = ldb.Dn(samdb, self.forestdns_dn) else: raise CommandError("Invalid FSMO role.") #first try to transfer to avoid problem if the owner is still active seize = False master_owner = get_fsmo_roleowner(samdb, m.dn, role) if master_owner is not None: # if there is a different owner if master_owner != serviceName: # if --force isn't given, attempt transfer if force is None: self.message("Attempting transfer...") try: transfer_dns_role(self.outf, sambaopts, credopts, role, samdb) except: #transfer failed, use the big axe... seize = True self.message("Transfer unsuccessful, seizing...") else: self.message("Transfer successful, not seizing role\n") return True else: self.outf.write("This DC already has the '%s' FSMO role\n" % role) return False else: seize = True if force is not None or seize == True: self.message("Seizing %s FSMO role..." % role) m["fSMORoleOwner"]= ldb.MessageElement( serviceName, ldb.FLAG_MOD_REPLACE, "fSMORoleOwner") try: samdb.modify(m) except LdbError, (num, msg): raise CommandError("Failed to seize '%s' role: %s" % (role, msg)) self.outf.write("FSMO seize of '%s' role successful\n" % role) return True
def join_subdomain(server=None, creds=None, lp=None, site=None, netbios_name=None, targetdir=None, parent_domain=None, dnsdomain=None, netbios_domain=None, machinepass=None, use_ntvfs=False, dns_backend=None): """Join as a DC.""" ctx = dc_join(server, creds, lp, site, netbios_name, targetdir, parent_domain, machinepass, use_ntvfs, dns_backend) ctx.subdomain = True ctx.parent_domain_name = ctx.domain_name ctx.domain_name = netbios_domain ctx.realm = dnsdomain ctx.parent_dnsdomain = ctx.dnsdomain ctx.parent_partition_dn = ctx.get_parent_partition_dn() ctx.dnsdomain = dnsdomain ctx.partition_dn = "CN=%s,CN=Partitions,%s" % (ctx.domain_name, ctx.config_dn) ctx.naming_master = ctx.get_naming_master() if ctx.naming_master != ctx.server: print("Reconnecting to naming master %s" % ctx.naming_master) ctx.server = ctx.naming_master ctx.samdb = SamDB(url="ldap://%s" % ctx.server, session_info=system_session(), credentials=ctx.creds, lp=ctx.lp) ctx.base_dn = samba.dn_from_dns_name(dnsdomain) ctx.domsid = str(security.random_sid()) ctx.acct_dn = None ctx.dnshostname = "%s.%s" % (ctx.myname, ctx.dnsdomain) ctx.trustdom_pass = samba.generate_random_password(128, 128) ctx.userAccountControl = samba.dsdb.UF_SERVER_TRUST_ACCOUNT | samba.dsdb.UF_TRUSTED_FOR_DELEGATION ctx.SPNs.append('E3514235-4B06-11D1-AB04-00C04FC2DCD2/$NTDSGUID/%s' % ctx.dnsdomain) ctx.secure_channel_type = misc.SEC_CHAN_BDC ctx.replica_flags = (drsuapi.DRSUAPI_DRS_WRIT_REP | drsuapi.DRSUAPI_DRS_INIT_SYNC | drsuapi.DRSUAPI_DRS_PER_SYNC | drsuapi.DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS | drsuapi.DRSUAPI_DRS_NEVER_SYNCED) ctx.domain_replica_flags = ctx.replica_flags ctx.do_join() print "Created domain %s (SID %s) as a DC" % (ctx.domain_name, ctx.domsid)
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, "infrastructure") pdcEmulator = get_fsmo_roleowner(samdb, domain_dn, "pdc") namingMaster = get_fsmo_roleowner(samdb, naming_dn, "naming") schemaMaster = get_fsmo_roleowner(samdb, schema_dn, "schema") ridMaster = get_fsmo_roleowner(samdb, rid_dn, "rid") domaindnszonesMaster = get_fsmo_roleowner(samdb, domaindns_dn, "domaindns") forestdnszonesMaster = get_fsmo_roleowner(samdb, forestdns_dn, "forestdns") 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 transfer_dns_role(outf, sambaopts, credopts, role, samdb): """Transfer dns FSMO role. """ if role == "domaindns": domain_dn = samdb.domain_dn() role_object = "CN=Infrastructure,DC=DomainDnsZones," + domain_dn elif role == "forestdns": forest_dn = samba.dn_from_dns_name(samdb.forest_dns_name()) role_object = "CN=Infrastructure,DC=ForestDnsZones," + forest_dn res = samdb.search(role_object, attrs=["fSMORoleOwner"], scope=ldb.SCOPE_BASE, controls=["extended_dn:1:1"]) if 'fSMORoleOwner' in res[0]: try: master_guid = str(misc.GUID(ldb.Dn(samdb, res[0]['fSMORoleOwner'][0]) .get_extended_component('GUID'))) master_owner = str(ldb.Dn(samdb, res[0]['fSMORoleOwner'][0])) except LdbError, (num, msg): raise CommandError("No GUID found in naming master DN %s : %s \n" % (res[0]['fSMORoleOwner'][0], msg))
def run(self, new_domain_name, new_dns_realm, sambaopts=None, credopts=None, server=None, targetdir=None, keep_dns_realm=False, no_secrets=False): logger = self.get_logger() logger.setLevel(logging.INFO) # Make sure we have all the required args. check_online_backup_args(logger, credopts, server, targetdir) delete_old_dns = not keep_dns_realm new_dns_realm = new_dns_realm.lower() new_domain_name = new_domain_name.upper() new_base_dn = samba.dn_from_dns_name(new_dns_realm) logger.info("New realm for backed up domain: %s" % new_dns_realm) logger.info("New base DN for backed up domain: %s" % new_base_dn) logger.info("New domain NetBIOS name: %s" % new_domain_name) tmpdir = tempfile.mkdtemp(dir=targetdir) # setup a join-context for cloning the remote server lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) include_secrets = not no_secrets ctx = DCCloneAndRenameContext(new_base_dn, new_domain_name, new_dns_realm, logger=logger, creds=creds, lp=lp, include_secrets=include_secrets, dns_backend='SAMBA_INTERNAL', server=server, targetdir=tmpdir) # sanity-check we're not "renaming" the domain to the same values old_domain = ctx.domain_name if old_domain == new_domain_name: shutil.rmtree(tmpdir) raise CommandError("Cannot use the current domain NetBIOS name.") old_realm = ctx.realm if old_realm == new_dns_realm: shutil.rmtree(tmpdir) raise CommandError("Cannot use the current domain DNS realm.") # do the clone/rename ctx.do_join() # get the paths used for the clone, then drop the old samdb connection del ctx.local_samdb paths = ctx.paths # get a free RID to use as the new DC's SID (when it gets restored) remote_sam = SamDB(url='ldap://' + server, credentials=creds, session_info=system_session(), lp=lp) new_sid = get_sid_for_restore(remote_sam) # Grab the remote DC's sysvol files and bundle them into a tar file. # Note we end up with 2 sysvol dirs - the original domain's files (that # use the old realm) backed here, as well as default files generated # for the new realm as part of the clone/join. sysvol_tar = os.path.join(tmpdir, 'sysvol.tar.gz') smb_conn = smb.SMB(server, "sysvol", lp=lp, creds=creds) backup_online(smb_conn, sysvol_tar, remote_sam.get_domain_sid()) # connect to the local DB (making sure we use the new/renamed config) lp.load(paths.smbconf) samdb = SamDB(url=paths.samdb, session_info=system_session(), lp=lp) # Edit the cloned sam.ldb to mark it as a backup time_str = get_timestamp() add_backup_marker(samdb, "backupDate", time_str) add_backup_marker(samdb, "sidForRestore", new_sid) add_backup_marker(samdb, "backupRename", old_realm) # fix up the DNS objects that are using the old dnsRoot value self.update_dns_root(logger, samdb, old_realm, delete_old_dns) # update the netBIOS name and the Partition object for the domain self.rename_domain_partition(logger, samdb, new_domain_name) if delete_old_dns: self.delete_old_dns_zones(logger, samdb, old_realm) logger.info("Fixing DN attributes after rename...") self.fix_old_dn_attributes(samdb) # ensure the admin user always has a password set (same as provision) if no_secrets: set_admin_password(logger, samdb, creds.get_username()) # Add everything in the tmpdir to the backup tar file backup_file = backup_filepath(targetdir, new_dns_realm, time_str) create_log_file( tmpdir, lp, "rename", server, include_secrets, "Original domain %s (NetBIOS), %s (DNS realm)" % (old_domain, old_realm)) create_backup_tar(logger, tmpdir, backup_file) shutil.rmtree(tmpdir)
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.")
def transfer_dns_role(outf, sambaopts, credopts, role, samdb): """Transfer dns FSMO role. """ if role == "domaindns": domain_dn = samdb.domain_dn() role_object = "CN=Infrastructure,DC=DomainDnsZones," + domain_dn elif role == "forestdns": forest_dn = samba.dn_from_dns_name(samdb.forest_dns_name()) role_object = "CN=Infrastructure,DC=ForestDnsZones," + forest_dn res = samdb.search(role_object, attrs=["fSMORoleOwner"], scope=ldb.SCOPE_BASE, controls=["extended_dn:1:1"]) if 'fSMORoleOwner' in res[0]: try: master_guid = str( misc.GUID( ldb.Dn(samdb, res[0]['fSMORoleOwner'] [0]).get_extended_component('GUID'))) master_owner = str(ldb.Dn(samdb, res[0]['fSMORoleOwner'][0])) except LdbError as e3: (num, msg) = e3.args raise CommandError("No GUID found in naming master DN %s : %s \n" % (res[0]['fSMORoleOwner'][0], msg)) else: outf.write("* The '%s' role does not have an FSMO roleowner\n" % role) return False if role == "domaindns": master_dns_name = '%s._msdcs.%s' % (master_guid, samdb.domain_dns_name()) new_dns_name = '%s._msdcs.%s' % (samdb.get_ntds_GUID(), samdb.domain_dns_name()) elif role == "forestdns": master_dns_name = '%s._msdcs.%s' % (master_guid, samdb.forest_dns_name()) new_dns_name = '%s._msdcs.%s' % (samdb.get_ntds_GUID(), samdb.forest_dns_name()) new_owner = samdb.get_dsServiceName() if master_dns_name != new_dns_name: lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp, fallback_machine=True) samdb = SamDB(url="ldap://%s" % (master_dns_name), session_info=system_session(), credentials=creds, lp=lp) m = ldb.Message() m.dn = ldb.Dn(samdb, role_object) m["fSMORoleOwner"] = ldb.MessageElement(master_owner, ldb.FLAG_MOD_DELETE, "fSMORoleOwner") try: samdb.modify(m) except LdbError as e4: (num, msg) = e4.args raise CommandError("Failed to delete role '%s': %s" % (role, msg)) m = ldb.Message() m.dn = ldb.Dn(samdb, role_object) m["fSMORoleOwner"] = ldb.MessageElement(new_owner, ldb.FLAG_MOD_ADD, "fSMORoleOwner") try: samdb.modify(m) except LdbError as e5: (num, msg) = e5.args raise CommandError("Failed to add role '%s': %s" % (role, msg)) try: connection = samba.drs_utils.drsuapi_connect( samdb.host_dns_name(), lp, creds) except samba.drs_utils.drsException as e: raise CommandError("Drsuapi Connect failed", e) try: drsuapi_connection = connection[0] drsuapi_handle = connection[1] req_options = drsuapi.DRSUAPI_DRS_WRIT_REP NC = role_object[18:] samba.drs_utils.sendDsReplicaSync(drsuapi_connection, drsuapi_handle, master_guid, NC, req_options) except samba.drs_utils.drsException as estr: raise CommandError("Replication failed", estr) outf.write("FSMO transfer of '%s' role successful\n" % role) return True else: outf.write("This DC already has the '%s' FSMO role\n" % role) return False
def transfer_dns_role(outf, sambaopts, credopts, role, samdb): """Transfer dns FSMO role. """ if role == "domaindns": domain_dn = samdb.domain_dn() role_object = "CN=Infrastructure,DC=DomainDnsZones," + domain_dn elif role == "forestdns": forest_dn = samba.dn_from_dns_name(samdb.forest_dns_name()) role_object = "CN=Infrastructure,DC=ForestDnsZones," + forest_dn try: res = samdb.search(role_object, attrs=["fSMORoleOwner"], scope=ldb.SCOPE_BASE, controls=["extended_dn:1:1"]) if 'fSMORoleOwner' in res[0]: try: master_guid = str(misc.GUID(ldb.Dn(samdb, res[0]['fSMORoleOwner'][0]) .get_extended_component('GUID'))) master_owner = str(ldb.Dn(samdb, res[0]['fSMORoleOwner'][0])) except LdbError as e: (num, msg) = e.args raise CommandError("GUID not found in partition naming master DN %s : %s \n" % (res[0]['fSMORoleOwner'][0], msg)) except LdbError as e: (num, msg) = e.args raise CommandError("DNS partion %s not found : %s" % (role, msg)) if role == "domaindns": master_dns_name = '%s._msdcs.%s' % (master_guid, samdb.domain_dns_name()) new_dns_name = '%s._msdcs.%s' % (samdb.get_ntds_GUID(), samdb.domain_dns_name()) elif role == "forestdns": master_dns_name = '%s._msdcs.%s' % (master_guid, samdb.forest_dns_name()) new_dns_name = '%s._msdcs.%s' % (samdb.get_ntds_GUID(), samdb.forest_dns_name()) new_owner = samdb.get_dsServiceName() if master_dns_name != new_dns_name: lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp, fallback_machine=True) samdb = SamDB(url="ldap://%s" % (master_dns_name), session_info=system_session(), credentials=creds, lp=lp) m = ldb.Message() m.dn = ldb.Dn(samdb, role_object) m["fSMORoleOwner"] = ldb.MessageElement(master_owner, ldb.FLAG_MOD_DELETE, "fSMORoleOwner") try: samdb.modify(m) except LdbError as e: (num, msg) = e.args raise CommandError("Failed to delete role '%s': %s" % (role, msg)) m = ldb.Message() m.dn = ldb.Dn(samdb, role_object) m["fSMORoleOwner"]= ldb.MessageElement(new_owner, ldb.FLAG_MOD_ADD, "fSMORoleOwner") try: samdb.modify(m) except LdbError as e: (num, msg) = e.args raise CommandError("Failed to add role '%s': %s" % (role, msg)) try: connection = samba.drs_utils.drsuapi_connect(samdb.host_dns_name(), lp, creds) except samba.drs_utils.drsException as e: raise CommandError("Drsuapi Connect failed", e) try: drsuapi_connection = connection[0] drsuapi_handle = connection[1] req_options = drsuapi.DRSUAPI_DRS_WRIT_REP NC = role_object[18:] samba.drs_utils.sendDsReplicaSync(drsuapi_connection, drsuapi_handle, master_guid, NC, req_options) except samba.drs_utils.drsException as estr: raise CommandError("Replication failed", estr) outf.write("FSMO transfer of '%s' role successful\n" % role) return True else: outf.write("This DC already has the '%s' FSMO role\n" % role) return False
lp = LoadParm() lp.load('/etc/samba/smb.conf') samdb = SamDB('/var/lib/samba/private/sam.ldb', session_info=system_session(lp), lp=lp) secretsdb = samba.Ldb('/var/lib/samba/private/secrets.ldb', session_info=system_session(lp), lp=lp) paths = ProvisionPaths() paths.private_dir = lp.get("private dir") names = ProvisionNames() # NT domain, kerberos realm, root dn, domain dn, domain dns name names.realm = lp.get("realm").upper() names.domain = lp.get("workgroup").upper() names.domaindn = samdb.domain_dn() names.dnsdomain = samba.ldb.Dn(samdb, names.domaindn).canonical_str().replace("/", "") basedn = samba.dn_from_dns_name(names.dnsdomain) # Get the netbiosname first (could be obtained from smb.conf in theory) res = secretsdb.search(expression="(flatname=%s)" % names.domain,base="CN=Primary Domains", scope=samba.ldb.SCOPE_SUBTREE, attrs=["sAMAccountName"]) names.netbiosname = str(res[0]["sAMAccountName"]).replace("$","") # dns hostname and server dn res4 = samdb.search(expression="(CN=%s)" % names.netbiosname, base="OU=Domain Controllers,%s" % basedn, scope=samba.ldb.SCOPE_ONELEVEL, attrs=["dNSHostName"]) names.hostname = str(res4[0]["dNSHostName"]).replace("." + names.dnsdomain,"") names.hostname = names.hostname.lower() dnspass = samba.generate_random_password(128, 255)
secretsdb = samba.Ldb('/var/lib/samba/private/secrets.ldb', session_info=system_session(lp), lp=lp) paths = ProvisionPaths() paths.private_dir = lp.get("private dir") names = ProvisionNames() # NT domain, kerberos realm, root dn, domain dn, domain dns name names.realm = lp.get("realm").upper() names.domain = lp.get("workgroup").upper() names.domaindn = samdb.domain_dn() names.dnsdomain = samba.ldb.Dn(samdb, names.domaindn).canonical_str().replace( "/", "") basedn = samba.dn_from_dns_name(names.dnsdomain) # Get the netbiosname first (could be obtained from smb.conf in theory) res = secretsdb.search(expression="(flatname=%s)" % names.domain, base="CN=Primary Domains", scope=samba.ldb.SCOPE_SUBTREE, attrs=["sAMAccountName"]) names.netbiosname = str(res[0]["sAMAccountName"]).replace("$", "") # dns hostname and server dn res4 = samdb.search(expression="(CN=%s)" % names.netbiosname, base="OU=Domain Controllers,%s" % basedn, scope=samba.ldb.SCOPE_ONELEVEL, attrs=["dNSHostName"]) names.hostname = str(res4[0]["dNSHostName"]).replace( "." + names.dnsdomain, "")