Ejemplo n.º 1
0
    def join_finalise(ctx):
        '''finalise the join, mark us synchronised and setup secrets db'''

        print "Sending DsReplicateUpdateRefs for all the partitions"
        ctx.send_DsReplicaUpdateRefs(ctx.schema_dn)
        ctx.send_DsReplicaUpdateRefs(ctx.config_dn)
        ctx.send_DsReplicaUpdateRefs(ctx.base_dn)

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

        if ctx.subdomain:
            return

        secrets_ldb = Ldb(ctx.paths.secrets,
                          session_info=system_session(),
                          lp=ctx.lp)

        print "Setting up secrets database"
        secretsdb_self_join(secrets_ldb,
                            domain=ctx.domain_name,
                            realm=ctx.realm,
                            dnsdomain=ctx.dnsdomain,
                            netbiosname=ctx.myname,
                            domainsid=security.dom_sid(ctx.domsid),
                            machinepass=ctx.acct_pass,
                            secure_channel_type=ctx.secure_channel_type,
                            key_version_number=ctx.key_version_number)
Ejemplo n.º 2
0
    def join_finalise(ctx):
        """finalise the join, mark us synchronised and setup secrets db"""

        print "Sending DsReplicateUpdateRefs for all the partitions"
        ctx.send_DsReplicaUpdateRefs(ctx.schema_dn)
        ctx.send_DsReplicaUpdateRefs(ctx.config_dn)
        ctx.send_DsReplicaUpdateRefs(ctx.base_dn)

        print "Setting isSynchronized and dsServiceName"
        m = ldb.Message()
        m.dn = ldb.Dn(ctx.local_samdb, "@ROOTDSE")
        m["isSynchronized"] = ldb.MessageElement("TRUE", ldb.FLAG_MOD_REPLACE, "isSynchronized")
        m["dsServiceName"] = ldb.MessageElement("<GUID=%s>" % str(ctx.ntds_guid), ldb.FLAG_MOD_REPLACE, "dsServiceName")
        ctx.local_samdb.modify(m)

        if ctx.subdomain:
            return

        secrets_ldb = Ldb(ctx.paths.secrets, session_info=system_session(), lp=ctx.lp)

        print "Setting up secrets database"
        secretsdb_self_join(
            secrets_ldb,
            domain=ctx.domain_name,
            realm=ctx.realm,
            dnsdomain=ctx.dnsdomain,
            netbiosname=ctx.myname,
            domainsid=security.dom_sid(ctx.domsid),
            machinepass=ctx.acct_pass,
            secure_channel_type=ctx.secure_channel_type,
            key_version_number=ctx.key_version_number,
        )
Ejemplo n.º 3
0
def update_machine_account_password(samdb, secrets_ldb, names):
    """Update (change) the password of the current DC both in the SAM db and in
       secret one

    :param samdb: An LDB object related to the sam.ldb file of a given provision
    :param secrets_ldb: An LDB object related to the secrets.ldb file of a given
                        provision
    :param names: List of key provision parameters"""

    expression = "samAccountName=%s$" % names.netbiosname
    secrets_msg = secrets_ldb.search(expression=expression,
                                     attrs=["secureChannelType"])
    if int(secrets_msg[0]["secureChannelType"][0]) == SEC_CHAN_BDC:
        res = samdb.search(expression=expression, attrs=[])
        assert (len(res) == 1)

        msg = ldb.Message(res[0].dn)
        machinepass = samba.generate_random_machine_password(128, 255)
        mputf16 = machinepass.encode('utf-16-le')
        msg["clearTextPassword"] = ldb.MessageElement(mputf16,
                                                      ldb.FLAG_MOD_REPLACE,
                                                      "clearTextPassword")
        samdb.modify(msg)

        res = samdb.search(expression=("samAccountName=%s$" %
                                       names.netbiosname),
                           attrs=["msDs-keyVersionNumber"])
        assert (len(res) == 1)
        kvno = int(str(res[0]["msDs-keyVersionNumber"]))
        secChanType = int(secrets_msg[0]["secureChannelType"][0])

        secretsdb_self_join(secrets_ldb,
                            domain=names.domain,
                            realm=names.realm,
                            domainsid=names.domainsid,
                            dnsdomain=names.dnsdomain,
                            netbiosname=names.netbiosname,
                            machinepass=machinepass,
                            key_version_number=kvno,
                            secure_channel_type=secChanType)
    else:
        raise ProvisioningError("Unable to find a Secure Channel"
                                "of type SEC_CHAN_BDC")
Ejemplo n.º 4
0
    def join_finalise(ctx):
        '''finalise the join, mark us synchronised and setup secrets db'''

        print "Setting isSynchronized"
        m = ldb.Message()
        m.dn = ldb.Dn(ctx.samdb, '@ROOTDSE')
        m["isSynchronized"] = ldb.MessageElement("TRUE", ldb.FLAG_MOD_REPLACE, "isSynchronized")
        ctx.samdb.modify(m)

        secrets_ldb = Ldb(ctx.paths.secrets, session_info=system_session(), lp=ctx.lp)

        print "Setting up secrets database"
        secretsdb_self_join(secrets_ldb, domain=ctx.domain_name,
                            realm=ctx.realm,
                            dnsdomain=ctx.dnsdomain,
                            netbiosname=ctx.myname,
                            domainsid=security.dom_sid(ctx.domsid),
                            machinepass=ctx.acct_pass,
                            secure_channel_type=ctx.secure_channel_type,
                            key_version_number=ctx.key_version_number)
Ejemplo n.º 5
0
    def join_finalise(ctx):
        '''finalise the join, mark us synchronised and setup secrets db'''

        print "Setting isSynchronized"
        m = ldb.Message()
        m.dn = ldb.Dn(ctx.samdb, '@ROOTDSE')
        m["isSynchronized"] = ldb.MessageElement("TRUE", ldb.FLAG_MOD_REPLACE, "isSynchronized")
        ctx.samdb.modify(m)

        secrets_ldb = Ldb(ctx.paths.secrets, session_info=system_session(), lp=ctx.lp)

        print "Setting up secrets database"
        secretsdb_self_join(secrets_ldb, domain=ctx.domain_name,
                            realm=ctx.realm,
                            dnsdomain=ctx.dnsdomain,
                            netbiosname=ctx.myname,
                            domainsid=security.dom_sid(ctx.domsid),
                            machinepass=ctx.acct_pass,
                            secure_channel_type=ctx.secure_channel_type,
                            key_version_number=ctx.key_version_number)
Ejemplo n.º 6
0
def update_machine_account_password(samdb, secrets_ldb, names):
    """Update (change) the password of the current DC both in the SAM db and in
       secret one

    :param samdb: An LDB object related to the sam.ldb file of a given provision
    :param secrets_ldb: An LDB object related to the secrets.ldb file of a given
                        provision
    :param names: List of key provision parameters"""

    expression = "samAccountName=%s$" % names.netbiosname
    secrets_msg = secrets_ldb.search(expression=expression,
                                        attrs=["secureChannelType"])
    if int(secrets_msg[0]["secureChannelType"][0]) == SEC_CHAN_BDC:
        res = samdb.search(expression=expression, attrs=[])
        assert(len(res) == 1)

        msg = ldb.Message(res[0].dn)
        machinepass = samba.generate_random_password(128, 255)
        mputf16 = machinepass.encode('utf-16-le')
        msg["clearTextPassword"] = ldb.MessageElement(mputf16,
                                                ldb.FLAG_MOD_REPLACE,
                                                "clearTextPassword")
        samdb.modify(msg)

        res = samdb.search(expression=("samAccountName=%s$" % names.netbiosname),
                     attrs=["msDs-keyVersionNumber"])
        assert(len(res) == 1)
        kvno = int(str(res[0]["msDs-keyVersionNumber"]))
        secChanType = int(secrets_msg[0]["secureChannelType"][0])

        secretsdb_self_join(secrets_ldb, domain=names.domain,
                    realm=names.realm,
                    domainsid=names.domainsid,
                    dnsdomain=names.dnsdomain,
                    netbiosname=names.netbiosname,
                    machinepass=machinepass,
                    key_version_number=kvno,
                    secure_channel_type=secChanType)
    else:
        raise ProvisioningError("Unable to find a Secure Channel"
                                "of type SEC_CHAN_BDC")
Ejemplo n.º 7
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.")
Ejemplo n.º 8
0
    def join_finalise(ctx):
        """Finalise the join, mark us synchronised and setup secrets db."""

        logger = logging.getLogger("provision")
        logger.addHandler(logging.StreamHandler(sys.stdout))

        # FIXME we shouldn't do this in all cases
        # If for some reasons we joined in another site than the one of
        # DC we just replicated from then we don't need to send the updatereplicateref
        # as replication between sites is time based and on the initiative of the
        # requesting DC
        print "Sending DsReplicateUpdateRefs for all the replicated partitions"
        for nc in ctx.full_nc_list:
            ctx.send_DsReplicaUpdateRefs(nc)

        if ctx.RODC:
            print "Setting RODC invocationId"
            ctx.local_samdb.set_invocation_id(str(ctx.invocation_id))
            ctx.local_samdb.set_opaque_integer("domainFunctionality",
                                               ctx.behavior_version)
            m = ldb.Message()
            m.dn = ldb.Dn(ctx.local_samdb, "%s" % ctx.ntds_dn)
            m["invocationId"] = ldb.MessageElement(ndr_pack(ctx.invocation_id),
                                                   ldb.FLAG_MOD_REPLACE,
                                                   "invocationId")
            ctx.local_samdb.modify(m)

            # Note: as RODC the invocationId is only stored
            # on the RODC itself, the other DCs never see it.
            #
            # Thats is why we fix up the replPropertyMetaData stamp
            # for the 'invocationId' attribute, we need to change
            # the 'version' to '0', this is what windows 2008r2 does as RODC
            #
            # This means if the object on a RWDC ever gets a invocationId
            # attribute, it will have version '1' (or higher), which will
            # will overwrite the RODC local value.
            ctx.local_samdb.set_attribute_replmetadata_version(m.dn,
                                                               "invocationId",
                                                               0)

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

        if ctx.subdomain:
            return

        secrets_ldb = Ldb(ctx.paths.secrets, session_info=system_session(), lp=ctx.lp)

        print "Setting up secrets database"
        secretsdb_self_join(secrets_ldb, domain=ctx.domain_name,
                            realm=ctx.realm,
                            dnsdomain=ctx.dnsdomain,
                            netbiosname=ctx.myname,
                            domainsid=security.dom_sid(ctx.domsid),
                            machinepass=ctx.acct_pass,
                            secure_channel_type=ctx.secure_channel_type,
                            key_version_number=ctx.key_version_number)

        if ctx.dns_backend.startswith("BIND9_"):
            dnspass = samba.generate_random_password(128, 255)

            setup_bind9_dns(ctx.local_samdb, secrets_ldb, security.dom_sid(ctx.domsid),
                            ctx.names, ctx.paths, ctx.lp, logger,
                            dns_backend=ctx.dns_backend,
                            dnspass=dnspass, os_level=ctx.behavior_version,
                            targetdir=ctx.targetdir)