def get_ldbs(paths, creds, session, lp): """Return LDB object mapped on most important databases :param paths: An object holding the different importants paths for provision object :param creds: Credential used for openning LDB files :param session: Session to use for openning LDB files :param lp: A loadparam object :return: A ProvisionLDB object that contains LDB object for the different LDB files of the provision""" ldbs = ProvisionLDB() ldbs.sam = SamDB(paths.samdb, session_info=session, credentials=creds, lp=lp, options=["modules:samba_dsdb"], flags=0) ldbs.secrets = Ldb(paths.secrets, session_info=session, credentials=creds, lp=lp) ldbs.idmap = Ldb(paths.idmapdb, session_info=session, credentials=creds, lp=lp) ldbs.privilege = Ldb(paths.privilege, session_info=session, credentials=creds, lp=lp) # ldbs.hkcr = Ldb(paths.hkcr, session_info=session, credentials=creds, lp=lp) # ldbs.hkcu = Ldb(paths.hkcu, session_info=session, credentials=creds, lp=lp) # ldbs.hku = Ldb(paths.hku, session_info=session, credentials=creds, lp=lp) # ldbs.hklm = Ldb(paths.hklm, session_info=session, credentials=creds, lp=lp) return ldbs
def setUp(self): super(MapTestCase, self).setUp() ldb = Ldb(self.ldburl, lp=cmdline_loadparm) ldif = read_datafile("provision_samba3sam.ldif") ldb.add_ldif(self.samba4.subst(ldif)) self.setup_modules(ldb, self.samba3, self.samba4) del ldb self.ldb = Ldb(self.ldburl, lp=cmdline_loadparm)
def setUp(self): super(MapTestCase, self).setUp() ldb = Ldb(self.ldburl, lp=self.lp, session_info=system_session()) ldb.set_opaque("skip_allocate_sids", "true") ldif = read_datafile("provision_samba3sam.ldif") ldb.add_ldif(self.samba4.subst(ldif)) self.setup_modules(ldb, self.samba3, self.samba4) del ldb self.ldb = Ldb(self.ldburl, lp=self.lp, session_info=system_session()) self.ldb.set_opaque("skip_allocate_sids", "true")
def delta_update_basesamdb(refsampath, sampath, creds, session, lp, message): """Update the provision container db: sam.ldb This function is aimed for alpha9 and newer; :param refsampath: Path to the samdb in the reference provision :param sampath: Path to the samdb in the upgraded provision :param creds: Credential used for openning LDB files :param session: Session to use for openning LDB files :param lp: A loadparam object :return: A msg_diff object with the difference between the @ATTRIBUTES of the current provision and the reference provision """ message(SIMPLE, "Update base samdb by searching difference with reference one") refsam = Ldb(refsampath, session_info=session, credentials=creds, lp=lp, options=["modules:"]) sam = Ldb(sampath, session_info=session, credentials=creds, lp=lp, options=["modules:"]) empty = ldb.Message() deltaattr = None reference = refsam.search(expression="") for refentry in reference: entry = sam.search(expression="distinguishedName=%s" % refentry["dn"], scope=SCOPE_SUBTREE) if not len(entry): delta = sam.msg_diff(empty, refentry) message(CHANGE, "Adding %s to sam db" % str(refentry.dn)) if str(refentry.dn) == "@PROVISION" and\ delta.get(samba.provision.LAST_PROVISION_USN_ATTRIBUTE): delta.remove(samba.provision.LAST_PROVISION_USN_ATTRIBUTE) delta.dn = refentry.dn sam.add(delta) else: delta = sam.msg_diff(entry[0], refentry) if str(refentry.dn) == "@ATTRIBUTES": deltaattr = sam.msg_diff(refentry, entry[0]) if str(refentry.dn) == "@PROVISION" and\ delta.get(samba.provision.LAST_PROVISION_USN_ATTRIBUTE): delta.remove(samba.provision.LAST_PROVISION_USN_ATTRIBUTE) if len(delta.items()) > 1: delta.dn = refentry.dn sam.modify(delta) return deltaattr
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)
def get_prim_dom(secrets_path, lp): secrets_ldb = Ldb(secrets_path, session_info=system_session(), lp=lp) return secrets_ldb.search(base="CN=Primary Domains", attrs=['objectClass', 'samAccountName', 'secret', 'msDS-KeyVersionNumber'], scope=ldb.SCOPE_SUBTREE, expression="(objectClass=kerberosSecret)")
def __init__(self, file, basedn, dn): self.file = os.path.join(tempdir, file) self.url = "tdb://" + self.file self.basedn = basedn self.substvars = {"BASEDN": self.basedn} self.db = Ldb(lp=cmdline_loadparm) self._dn = dn
def join_provision_own_domain(ctx): """Provision the local SAM.""" # we now operate exclusively on the local database, which # we need to reopen in order to get the newly created schema print("Reconnecting to local samdb") ctx.samdb = SamDB(url=ctx.local_samdb.url, session_info=system_session(), lp=ctx.local_samdb.lp, global_schema=False) ctx.samdb.set_invocation_id(str(ctx.invocation_id)) ctx.local_samdb = ctx.samdb print("Finding domain GUID from ncName") res = ctx.local_samdb.search(base=ctx.partition_dn, scope=ldb.SCOPE_BASE, attrs=['ncName'], controls=["extended_dn:1:1"]) domguid = str(misc.GUID(ldb.Dn(ctx.samdb, res[0]['ncName'][0]).get_extended_component('GUID'))) print("Got domain GUID %s" % domguid) print("Calling own domain provision") logger = logging.getLogger("provision") logger.addHandler(logging.StreamHandler(sys.stdout)) secrets_ldb = Ldb(ctx.paths.secrets, session_info=system_session(), lp=ctx.lp) presult = provision_fill(ctx.local_samdb, secrets_ldb, logger, ctx.names, ctx.paths, domainsid=security.dom_sid(ctx.domsid), domainguid=domguid, targetdir=ctx.targetdir, samdb_fill=FILL_SUBDOMAIN, machinepass=ctx.acct_pass, serverrole="domain controller", lp=ctx.lp, hostip=ctx.names.hostip, hostip6=ctx.names.hostip6, dns_backend=ctx.dns_backend) print("Provision OK for domain %s" % ctx.names.dnsdomain)
def accountcontrol(lp, creds, username=None, value=0): """enable/disable an OpenChange user account. :param lp: Loadparm context :param creds: Credentials context :param username: Name of user to disable :param value: the control value """ names = guess_names_from_smbconf(lp, None, None) db = Ldb(url=get_ldb_url(lp, creds, names), session_info=system_session(), credentials=creds, lp=lp) user_dn = get_user_dn(db, names.domaindn, username) extended_user = """ dn: %s changetype: modify replace: msExchUserAccountControl msExchUserAccountControl: %d """ % (user_dn, value) db.modify_ldif(extended_user) if value == 2: print "[+] Account %s disabled" % username else: print "[+] Account %s enabled" % username
def rsop(self, gpo): output = {} pol_file = 'MACHINE/Registry.pol' section = 'Software\Policies\Microsoft\Cryptography\AutoEnrollment' if gpo.file_sys_path: path = os.path.join(gpo.file_sys_path, pol_file) pol_conf = self.parse(path) if not pol_conf: return output for e in pol_conf.entries: if e.keyname == section and e.valuename == 'AEPolicy': enroll = e.data & 0x1 == 1 if e.data == 0x8000 or not enroll: continue output['Auto Enrollment Policy'] = {} url = 'ldap://%s' % get_dc_hostname(self.creds, self.lp) ldb = Ldb(url=url, session_info=system_session(), lp=self.lp, credentials=self.creds) cas = fetch_certification_authorities(ldb) for ca in cas: policy = 'Auto Enrollment Policy' cn = ca['cn'][0] output[policy][cn] = {} output[policy][cn]['CA Certificate'] = \ format_root_cert(ca['cACertificate'][0]).decode() output[policy][cn]['Auto Enrollment Server'] = \ ca['dNSHostName'][0] supported_templates = \ get_supported_templates(ca['dNSHostName'][0], self.logger) output[policy][cn]['Templates'] = \ [t.decode() for t in supported_templates] return output
def backup_smb_dbs(self, private_dir, samdb, lp, logger): # First, determine if DB backend is MDB. Assume not unless there is a # 'backendStore' attribute on @PARTITION containing the text 'mdb' store_label = "backendStore" res = samdb.search(base="@PARTITION", scope=ldb.SCOPE_BASE, attrs=[store_label]) mdb_backend = store_label in res[0] and res[0][store_label][0] == 'mdb' sam_ldb_path = os.path.join(private_dir, 'sam.ldb') copy_function = None if mdb_backend: logger.info('MDB backend detected. Using mdb backup function.') copy_function = self.offline_mdb_copy else: logger.info('Starting transaction on ' + sam_ldb_path) copy_function = self.offline_tdb_copy sam_obj = Ldb(sam_ldb_path, lp=lp) sam_obj.transaction_start() logger.info(' backing up ' + sam_ldb_path) self.offline_tdb_copy(sam_ldb_path) sam_ldb_d = sam_ldb_path + '.d' for sam_file in os.listdir(sam_ldb_d): sam_file = os.path.join(sam_ldb_d, sam_file) if sam_file.endswith('.ldb'): logger.info(' backing up locked/related file ' + sam_file) copy_function(sam_file) else: logger.info(' copying locked/related file ' + sam_file) shutil.copyfile(sam_file, sam_file + self.backup_ext) if not mdb_backend: sam_obj.transaction_cancel()
def process_group_policy(self, deleted_gpo_list, changed_gpo_list, trust_dir=None, private_dir=None): if trust_dir is None: trust_dir = self.lp.cache_path('certs') if private_dir is None: private_dir = self.lp.private_path('certs') if not os.path.exists(trust_dir): os.mkdir(trust_dir, mode=0o755) if not os.path.exists(private_dir): os.mkdir(private_dir, mode=0o700) for guid, settings in deleted_gpo_list: self.gp_db.set_guid(guid) if str(self) in settings: for ca_cn_enc, data in settings[str(self)].items(): ca_cn = base64.b64decode(ca_cn_enc) data = json.loads(data) getcert = which('getcert') if getcert is not None: Popen([getcert, 'remove-ca', '-c', ca_cn]).wait() for nickname in data['templates']: Popen([getcert, 'stop-tracking', '-i', nickname]).wait() for f in data['files']: if os.path.exists(f): os.unlink(f) self.gp_db.delete(str(self), ca_cn_enc) self.gp_db.commit() for gpo in changed_gpo_list: if gpo.file_sys_path: section = 'Software\Policies\Microsoft\Cryptography\AutoEnrollment' self.gp_db.set_guid(gpo.name) pol_file = 'MACHINE/Registry.pol' path = os.path.join(gpo.file_sys_path, pol_file) pol_conf = self.parse(path) if not pol_conf: continue for e in pol_conf.entries: if e.keyname == section and e.valuename == 'AEPolicy': # This policy applies as specified in [MS-CAESO] 4.4.5.1 if e.data == 0x8000: continue # The policy is disabled enroll = e.data & 0x1 == 1 manage = e.data & 0x2 == 1 retrive_pending = e.data & 0x4 == 1 if enroll: url = 'ldap://%s' % get_dc_hostname(self.creds, self.lp) ldb = Ldb(url=url, session_info=system_session(), lp=self.lp, credentials=self.creds) cas = fetch_certification_authorities(ldb) for ca in cas: data = cert_enroll(ca, trust_dir, private_dir, self.logger) self.gp_db.store(str(self), base64.b64encode(ca['cn'][0]).decode(), data) self.gp_db.commit()
def newuser(names, lp, creds, username=None): """extend user record with OpenChange settings. :param lp: Loadparm context :param creds: Credentials context :param names: provision names object. :param username: Name of user to extend """ db = Ldb(url=get_ldb_url(lp, creds, names), session_info=system_session(), credentials=creds, lp=lp) user_dn = get_user_dn(db, "CN=Users,%s" % names.domaindn, username) if user_dn: extended_user = """ dn: %(user_dn)s changetype: modify add: mailNickName mailNickname: %(username)s add: homeMDB homeMDB: CN=Mailbox Store (%(netbiosname)s),CN=First Storage Group,CN=InformationStore,CN=%(netbiosname)s,CN=Servers,CN=%(firstou)s,CN=Administrative Groups,CN=%(firstorg)s,CN=Microsoft Exchange,CN=Services,CN=Configuration,%(domaindn)s add: homeMTA homeMTA: CN=Mailbox Store (%(netbiosname)s),CN=First Storage Group,CN=InformationStore,CN=%(netbiosname)s,CN=Servers,CN=%(firstou)s,CN=Administrative Groups,CN=%(firstorg)s,CN=Microsoft Exchange,CN=Services,CN=Configuration,%(domaindn)s add: legacyExchangeDN legacyExchangeDN: /o=%(firstorg)s/ou=%(firstou)s/cn=Recipients/cn=%(username)s add: proxyAddresses proxyAddresses: =EX:/o=%(firstorg)s/ou=%(firstou)s/cn=Recipients/cn=%(username)s proxyAddresses: smtp:postmaster@%(dnsdomain)s proxyAddresses: X400:c=US;a= ;p=First Organizati;o=Exchange;s=%(username)s proxyAddresses: SMTP:%(username)s@%(dnsdomain)s replace: msExchUserAccountControl msExchUserAccountControl: 0 """ ldif_value = extended_user % {"user_dn": user_dn, "username": username, "netbiosname": names.netbiosname, "firstorg": names.firstorg, "firstou": names.firstou, "domaindn": names.domaindn, "dnsdomain": names.dnsdomain} db.modify_ldif(ldif_value) res = db.search(base=user_dn, scope=SCOPE_BASE, attrs=["*"]) if len(res) == 1: record = res[0] else: raise Exception("this should never happen as we just modified the record...") record_keys = map(lambda x: x.lower(), record.keys()) if "displayname" not in record_keys: extended_user = "******" % (user_dn, username) db.modify_ldif(extended_user) if "mail" not in record_keys: extended_user = "******" % (user_dn, username, names.dnsdomain) db.modify_ldif(extended_user) print "[+] User %s extended and enabled" % username else: print "[!] User '%s' not found" % username
def __init__(self, host, creds, lp, two=False, quiet=False, descriptor=False, sort_aces=False, verbose=False, view="section", base="", scope="SUB"): ldb_options = [] samdb_url = host if not "://" in host: if os.path.isfile(host): samdb_url = "tdb://%s" % host else: samdb_url = "ldap://%s" % host # use 'paged_search' module when connecting remotely if samdb_url.lower().startswith("ldap://"): ldb_options = ["modules:paged_searches"] self.ldb = Ldb(url=samdb_url, credentials=creds, lp=lp, options=ldb_options) self.search_base = base self.search_scope = scope self.two_domains = two self.quiet = quiet self.descriptor = descriptor self.sort_aces = sort_aces self.view = view self.verbose = verbose self.host = host self.base_dn = str(self.ldb.get_default_basedn()) self.root_dn = str(self.ldb.get_root_basedn()) self.config_dn = str(self.ldb.get_config_basedn()) self.schema_dn = str(self.ldb.get_schema_basedn()) self.domain_netbios = self.find_netbios() self.server_names = self.find_servers() self.domain_name = re.sub("[Dd][Cc]=", "", self.base_dn).replace(",", ".") self.domain_sid = self.find_domain_sid() self.get_guid_map() self.get_sid_map() # # Log some domain controller specific place-holers that are being used # when compare content of two DCs. Uncomment for DEBUG purposes. if self.two_domains and not self.quiet: self.outf.write("\n* Place-holders for %s:\n" % self.host) self.outf.write(4 * " " + "${DOMAIN_DN} => %s\n" % self.base_dn) self.outf.write(4 * " " + "${DOMAIN_NETBIOS} => %s\n" % self.domain_netbios) self.outf.write(4 * " " + "${SERVER_NAME} => %s\n" % self.server_names) self.outf.write(4 * " " + "${DOMAIN_NAME} => %s\n" % self.domain_name)
def backup_secrets(self, private_dir, lp, logger): secrets_path = os.path.join(private_dir, 'secrets') secrets_obj = Ldb(secrets_path + '.ldb', lp=lp) logger.info('Starting transaction on ' + secrets_path) secrets_obj.transaction_start() self.offline_tdb_copy(secrets_path + '.ldb') self.offline_tdb_copy(secrets_path + '.tdb') secrets_obj.transaction_cancel()
def init(self): # Check to see that this 'existing' LDAP backend in fact exists ldapi_db = Ldb(self.ldapi_uri) ldapi_db.search(base="", scope=SCOPE_BASE, expression="(objectClass=OpenLDAProotDSE)") # For now, assume existing backends at least emulate OpenLDAP self.ldap_backend_type = "openldap"
def __init__(self, basedn, dn, lp): self.db = Ldb(lp=lp, session_info=system_session()) self.db.set_opaque("skip_allocate_sids", "true") self.basedn = basedn self.basedn_casefold = ldb.Dn(self.db, basedn).get_casefold() self.substvars = {"BASEDN": self.basedn} self.file = os.path.join(tempdir, "%s.ldb" % self.basedn_casefold) self.url = "tdb://" + self.file self._dn = dn
def __init__(self, basedn, dn): self.db = Ldb(lp=cmdline_loadparm) self.basedn = basedn self.basedn_casefold = ldb.Dn(self.db, basedn).get_casefold() self.substvars = {"BASEDN": self.basedn} self.file = os.path.join(tempdir, "%s.ldb" % self.basedn_casefold) self.url = "tdb://" + self.file self._dn = dn
def init(self): from samba.provision import ProvisioningError # we will shortly start slapd with ldapi for final provisioning. first # check with ldapsearch -> rootDSE via self.ldap_uri if another # instance of slapd is already running try: ldapi_db = Ldb(self.ldap_uri) ldapi_db.search(base="", scope=SCOPE_BASE, expression="(objectClass=OpenLDAProotDSE)") try: f = open(self.slapd_pid, "r") except IOError as err: if err != errno.ENOENT: raise else: try: p = f.read() finally: f.close() self.logger.info("Check for slapd process with PID: %s and terminate it manually." % p) raise SlapdAlreadyRunning(self.ldap_uri) except LdbError: # XXX: We should never be catching all Ldb errors pass # Try to print helpful messages when the user has not specified the # path to slapd if self.slapd_path is None: raise ProvisioningError("Warning: LDAP-Backend must be setup with path to slapd, e.g. --slapd-path=\"/usr/local/libexec/slapd\"!") if not os.path.exists(self.slapd_path): self.logger.warning("Path (%s) to slapd does not exist!", self.slapd_path) if not os.path.isdir(self.ldapdir): os.makedirs(self.ldapdir, 0o700) # Put the LDIF of the schema into a database so we can search on # it to generate schema-dependent configurations in Fedora DS and # OpenLDAP schemadb_path = os.path.join(self.ldapdir, "schema-tmp.ldb") try: os.unlink(schemadb_path) except OSError: pass self.schema.write_to_tmp_ldb(schemadb_path) self.credentials = Credentials() self.credentials.guess(self.lp) # Kerberos to an ldapi:// backend makes no sense (we also force EXTERNAL) self.credentials.set_kerberos_state(DONT_USE_KERBEROS) self.credentials.set_username("samba-admin") self.credentials.set_password(self.ldapadminpass) self.credentials.set_forced_sasl_mech("EXTERNAL") self.provision()
def __init__(self, setup_path, domain_sid, schemadn=None, serverdn=None, files=None, prefixmap=None): """Load schema for the SamDB from the AD schema files and samba4_schema.ldif :param samdb: Load a schema into a SamDB. :param setup_path: Setup path function. :param schemadn: DN of the schema :param serverdn: DN of the server Returns the schema data loaded, to avoid double-parsing when then needing to add it to the db """ self.schemadn = schemadn self.ldb = Ldb() self.schema_data = read_ms_schema( setup_path('ad-schema/MS-AD_Schema_2K8_Attributes.txt'), setup_path('ad-schema/MS-AD_Schema_2K8_Classes.txt')) if files is not None: for file in files: self.schema_data += open(file, 'r').read() self.schema_data = substitute_var(self.schema_data, {"SCHEMADN": schemadn}) check_all_substituted(self.schema_data) self.schema_dn_modify = read_and_sub_file( setup_path("provision_schema_basedn_modify.ldif"), { "SCHEMADN": schemadn, "SERVERDN": serverdn, }) descr = b64encode(get_schema_descriptor(domain_sid)) self.schema_dn_add = read_and_sub_file( setup_path("provision_schema_basedn.ldif"), { "SCHEMADN": schemadn, "DESCRIPTOR": descr }) self.prefixmap_data = open(setup_path("prefixMap.txt"), 'r').read() if prefixmap is not None: for map in prefixmap: self.prefixmap_data += "%s\n" % map self.prefixmap_data = b64encode(self.prefixmap_data) # We don't actually add this ldif, just parse it prefixmap_ldif = "dn: cn=schema\nprefixMap:: %s\n\n" % self.prefixmap_data self.ldb.set_schema_from_ldif(prefixmap_ldif, self.schema_data)
def init(self): #Check to see that this 'existing' LDAP backend in fact exists ldapi_db = Ldb(self.ldapi_uri, credentials=self.credentials) search_ol_rootdse = ldapi_db.search(base="", scope=SCOPE_BASE, expression="(objectClass=OpenLDAProotDSE)") # If we have got here, then we must have a valid connection to the LDAP server, with valid credentials supplied # This caused them to be set into the long-term database later in the script. self.secrets_credentials = self.credentials self.ldap_backend_type = "openldap" #For now, assume existing backends at least emulate OpenLDAP
def run(self, acl, file, quiet=False,xattr_backend=None,eadb_file=None, credopts=None, sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) path = os.path.join(lp.get("private dir"), lp.get("secrets database") or "secrets.ldb") creds = credopts.get_credentials(lp) creds.set_kerberos_state(DONT_USE_KERBEROS) try: ldb = Ldb(path, session_info=system_session(), credentials=creds, lp=lp) except Exception, e: raise CommandError("Unable to read domain SID from configuration files", e)
def ldif_to_samdb(dburl, lp, ldif_file, forced_local_dsa=None): """Routine to import all objects and attributes that are relevent to the KCC algorithms from a previously exported LDIF file. The point of this function is to allow a programmer/debugger to import an LDIF file with non-security relevent information that was previously extracted from a DC database. The LDIF file is used to create a temporary abbreviated database. The KCC algorithm can then run against this abbreviated database for debug or test verification that the topology generated is computationally the same between different OSes and algorithms. :param dburl: path to the temporary abbreviated db to create :param ldif_file: path to the ldif file to import """ if os.path.exists(dburl): raise LdifError("Specify a database (%s) that doesn't already exist." % dburl) # Use ["modules:"] as we are attempting to build a sam # database as opposed to start it here. tmpdb = Ldb(url=dburl, session_info=system_session(), lp=lp, options=["modules:"]) tmpdb.transaction_start() try: data = read_and_sub_file(ldif_file, None) tmpdb.add_ldif(data, None) if forced_local_dsa: tmpdb.modify_ldif("""dn: @ROOTDSE changetype: modify replace: dsServiceName dsServiceName: CN=NTDS Settings,%s """ % forced_local_dsa) tmpdb.add_ldif("""dn: @MODULES @LIST: rootdse,extended_dn_in,extended_dn_out_ldb,objectguid - """) except Exception as estr: tmpdb.transaction_cancel() raise LdifError("Failed to import %s: %s" % (ldif_file, estr)) tmpdb.transaction_commit() # We have an abbreviated list of options here because we have built # an abbreviated database. We use the rootdse and extended-dn # modules only during this re-open samdb = SamDB(url=dburl, session_info=system_session(), lp=lp) return samdb
def start(self): from samba.provision import ProvisioningError self.slapd_command_escaped = "\'" + "\' \'".join( self.slapd_command) + "\'" ldap_backend_script = os.path.join(self.ldapdir, "ldap_backend_startup.sh") f = open(ldap_backend_script, 'w') try: f.write("#!/bin/sh\n" + self.slapd_command_escaped + " $@\n") finally: f.close() os.chmod(ldap_backend_script, 0o755) # Now start the slapd, so we can provision onto it. We keep the # subprocess context around, to kill this off at the successful # end of the script self.slapd = subprocess.Popen(self.slapd_provision_command, close_fds=True, shell=False) count = 0 while self.slapd.poll() is None: # Wait until the socket appears try: time.sleep(1) ldapi_db = Ldb(self.ldap_uri, lp=self.lp, credentials=self.credentials) ldapi_db.search(base="", scope=SCOPE_BASE, expression="(objectClass=OpenLDAProotDSE)") # If we have got here, then we must have a valid connection to # the LDAP server! return except LdbError: count = count + 1 if count > 15: self.logger.error( "Could not connect to slapd started with: %s" % "\'" + "\' \'".join(self.slapd_provision_command) + "\'") raise ProvisioningError( "slapd never accepted a connection within 15 seconds of starting" ) self.logger.error("Could not start slapd with: %s" % "\'" + "\' \'".join(self.slapd_provision_command) + "\'") raise ProvisioningError( "slapd died before we could make a connection to it")
def run(self, secret, sambaopts=None, credopts=None, versionopts=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp, fallback_machine=True) url = lp.get("secrets database") secretsdb = Ldb(url=url, session_info=system_session(), credentials=creds, lp=lp) result = secretsdb.search(attrs=["secret"], expression="(&(objectclass=primaryDomain)(samaccountname=%s))" % secret) if len(result) != 1: raise CommandError("search returned %d records, expected 1" % len(result)) self.outf.write("%s\n" % result[0]["secret"])
def test_tdb_copy(self): src_ldb_file = os.path.join(self.tempdir, "source.ldb") dst_ldb_file = os.path.join(self.tempdir, "destination.ldb") # Create LDB source file with some content src_ldb = Ldb(src_ldb_file) src_ldb.add({"dn": "f=dc", "b": "bla"}) # Copy source file to destination file and check return status self.assertIsNone(tdb_copy(src_ldb_file, dst_ldb_file)) # Load copied file as LDB object dst_ldb = Ldb(dst_ldb_file) # Copmare contents of files self.assertEqual( src_ldb.searchone(basedn=ldb.Dn(src_ldb, "f=dc"), attribute="b"), dst_ldb.searchone(basedn=ldb.Dn(dst_ldb, "f=dc"), attribute="b")) # Clean up del src_ldb del dst_ldb os.unlink(src_ldb_file) os.unlink(dst_ldb_file)
def post_setup(self): ldapi_db = Ldb(self.ldap_uri, credentials=self.credentials) # configure in-directory access control on Fedora DS via the aci # attribute (over a direct ldapi:// socket) aci = """(targetattr = "*") (version 3.0;acl "full access to all by samba-admin";allow (all)(userdn = "ldap:///CN=samba-admin,%s");)""" % self.sambadn m = ldb.Message() m["aci"] = ldb.MessageElement([aci], ldb.FLAG_MOD_REPLACE, "aci") for dnstring in (self.names.domaindn, self.names.configdn, self.names.schemadn): m.dn = ldb.Dn(ldapi_db, dnstring) ldapi_db.modify(m) return LDAPBackendResult(self.credentials, self.slapd_command_escaped, self.ldapdir)
def init(self): # we will shortly start slapd with ldapi for final provisioning. first check with ldapsearch -> rootDSE via self.ldapi_uri # if another instance of slapd is already running try: ldapi_db = Ldb(self.ldapi_uri) search_ol_rootdse = ldapi_db.search(base="", scope=SCOPE_BASE, expression="(objectClass=OpenLDAProotDSE)"); try: f = open(self.paths.slapdpid, "r") p = f.read() f.close() self.message("Check for slapd Process with PID: " + str(p) + " and terminate it manually.") except: pass raise ProvisioningError("Warning: Another slapd Instance seems already running on this host, listening to " + self.ldapi_uri + ". Please shut it down before you continue. ") except LdbError, e: pass
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)
def start(self): self.slapd_command_escaped = "\'" + "\' \'".join(self.slapd_command) + "\'" open(self.paths.ldapdir + "/ldap_backend_startup.sh", 'w').write("#!/bin/sh\n" + self.slapd_command_escaped + "\n") # Now start the slapd, so we can provision onto it. We keep the # subprocess context around, to kill this off at the successful # end of the script self.slapd = subprocess.Popen(self.slapd_provision_command, close_fds=True, shell=False) while self.slapd.poll() is None: # Wait until the socket appears try: ldapi_db = Ldb(self.ldapi_uri, lp=self.lp, credentials=self.credentials) search_ol_rootdse = ldapi_db.search(base="", scope=SCOPE_BASE, expression="(objectClass=OpenLDAProotDSE)") # If we have got here, then we must have a valid connection to the LDAP server! return except LdbError, e: time.sleep(1) pass