Example #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

        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)
Example #2
0
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)
Example #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

        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))
Example #4
0
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))
Example #5
0
    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
Example #6
0
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)
Example #7
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))
Example #8
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,
                                                  "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)
Example #9
0
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))
Example #10
0
    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)
Example #11
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.")
Example #12
0
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
Example #13
0
File: fsmo.py Project: sYnfo/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

    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
Example #14
0
	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)
Example #15
0
    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, "")