def test_binary_encode(self): encoded = ldb.binary_encode(b"test\\x") decoded = ldb.binary_decode(encoded) self.assertEqual(decoded, b"test\\x") encoded2 = ldb.binary_encode("test\\x") self.assertEqual(encoded2, encoded)
def get_gpo_info(samdb, gpo=None, displayname=None, dn=None): '''Get GPO information using gpo, displayname or dn''' policies_dn = samdb.get_default_basedn() policies_dn.add_child(ldb.Dn(samdb, "CN=Policies,CN=System")) base_dn = policies_dn search_expr = "(objectClass=groupPolicyContainer)" search_scope = ldb.SCOPE_ONELEVEL if gpo is not None: search_expr = "(&(objectClass=groupPolicyContainer)(name=%s))" % ldb.binary_encode(gpo) if displayname is not None: search_expr = "(&(objectClass=groupPolicyContainer)(displayname=%s))" % ldb.binary_encode(displayname) if dn is not None: base_dn = dn search_scope = ldb.SCOPE_BASE try: msg = samdb.search(base=base_dn, scope=search_scope, expression=search_expr, attrs=['nTSecurityDescriptor', 'versionNumber', 'flags', 'name', 'displayName', 'gPCFileSysPath']) except Exception, e: if gpo is not None: mesg = "Cannot get information for GPO %s" % gpo else: mesg = "Cannot get information for GPOs" raise CommandError(mesg, e)
def test_binary_encode(self): encoded = ldb.binary_encode(b'test\\x') decoded = ldb.binary_decode(encoded) self.assertEqual(decoded, b'test\\x') encoded2 = ldb.binary_encode('test\\x') self.assertEqual(encoded2, encoded)
def add_remove_group_members(self, groupname, listofmembers, add_members_operation=True): """Adds or removes group members :param groupname: Name of the target group :param listofmembers: Comma-separated list of group members :param add_members_operation: Defines if its an add or remove operation """ groupfilter = "(&(sAMAccountName=%s)(objectCategory=%s,%s))" % ( ldb.binary_encode(groupname), "CN=Group,CN=Schema,CN=Configuration", self.domain_dn()) groupmembers = listofmembers.split(',') self.transaction_start() try: targetgroup = self.search(base=self.domain_dn(), scope=ldb.SCOPE_SUBTREE, expression=groupfilter, attrs=['member']) if len(targetgroup) == 0: raise Exception('Unable to find group "%s"' % groupname) assert(len(targetgroup) == 1) modified = False addtargettogroup = """ dn: %s changetype: modify """ % (str(targetgroup[0].dn)) for member in groupmembers: targetmember = self.search(base=self.domain_dn(), scope=ldb.SCOPE_SUBTREE, expression="(|(sAMAccountName=%s)(CN=%s))" % ( ldb.binary_encode(member), ldb.binary_encode(member)), attrs=[]) if len(targetmember) != 1: continue if add_members_operation is True and (targetgroup[0].get('member') is None or str(targetmember[0].dn) not in targetgroup[0]['member']): modified = True addtargettogroup += """add: member member: %s """ % (str(targetmember[0].dn)) elif add_members_operation is False and (targetgroup[0].get('member') is not None and str(targetmember[0].dn) in targetgroup[0]['member']): modified = True addtargettogroup += """delete: member member: %s """ % (str(targetmember[0].dn)) if modified is True: self.modify_ldif(addtargettogroup) except: self.transaction_cancel() raise else: self.transaction_commit()
def run(self, username, H=None, sambaopts=None, credopts=None, versionopts=None): self.lp = sambaopts.get_loadparm() self.creds = credopts.get_credentials(self.lp, fallback_machine=True) self.url = dc_url(self.lp, self.creds, H) samdb_connect(self) try: msg = self.samdb.search(expression='(&(|(samAccountName=%s)(samAccountName=%s$))(objectClass=User))' % (ldb.binary_encode(username),ldb.binary_encode(username))) user_dn = msg[0].dn except Exception, e: raise CommandError("Failed to find account %s" % username, e)
def run(self, computername, credopts=None, sambaopts=None, versionopts=None, H=None, computer_attrs=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) attrs = None if computer_attrs: attrs = computer_attrs.split(",") samaccountname = computername if not computername.endswith('$'): samaccountname = "%s$" % computername filter = ("(&(sAMAccountType=%d)(sAMAccountName=%s))" % (dsdb.ATYPE_WORKSTATION_TRUST, ldb.binary_encode(samaccountname))) domaindn = samdb.domain_dn() try: res = samdb.search(base=domaindn, expression=filter, scope=ldb.SCOPE_SUBTREE, attrs=attrs) computer_dn = res[0].dn except IndexError: raise CommandError('Unable to find computer "%s"' % samaccountname) for msg in res: computer_ldif = samdb.write_ldif(msg, ldb.CHANGETYPE_NONE) self.outf.write(computer_ldif)
def run(self, groupname, credopts=None, sambaopts=None, versionopts=None, H=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) filter = ("(&(sAMAccountName=%s)(objectClass=group))" % ldb.binary_encode(groupname)) try: res = samdb.search(base=samdb.domain_dn(), scope=ldb.SCOPE_SUBTREE, expression=filter, attrs=["dn"]) group_dn = res[0].dn except IndexError: raise CommandError('Unable to find group "%s"' % (groupname)) try: samdb.delete(group_dn) except Exception as e: # FIXME: catch more specific exception raise CommandError('Failed to remove group "%s"' % groupname, e) self.outf.write("Deleted group %s\n" % groupname)
def rename_domain_partition(self, logger, samdb, new_netbios_name): '''Renames the domain parition object and updates its nETBIOSName''' # lookup the crossRef object that holds the nETBIOSName (nCName has # already been updated by this point, but the netBIOS hasn't) base_dn = samdb.get_default_basedn() nc_name = ldb.binary_encode(str(base_dn)) partitions_dn = samdb.get_partitions_dn() res = samdb.search(base=partitions_dn, scope=ldb.SCOPE_ONELEVEL, attrs=["nETBIOSName"], expression='ncName=%s' % nc_name) logger.info("Changing backup domain's NetBIOS name to %s" % new_netbios_name) m = ldb.Message() m.dn = res[0].dn m["nETBIOSName"] = ldb.MessageElement(new_netbios_name, ldb.FLAG_MOD_REPLACE, "nETBIOSName") samdb.modify(m) # renames the object itself to reflect the change in domain new_dn = "CN=%s,%s" % (new_netbios_name, partitions_dn) logger.info("Renaming %s --> %s" % (res[0].dn, new_dn)) samdb.rename(res[0].dn, new_dn, controls=['relax:0'])
def run(self, user, credopts=None, sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) paths = provision.provision_paths_from_lp(lp, lp.get("realm")) sam = SamDB(paths.samdb, session_info=system_session(), credentials=creds, lp=lp) # TODO once I understand how, use the domain info to naildown # to the correct domain (cleaneduser, realm, domain) = _get_user_realm_domain(user) self.outf.write(cleaneduser + "\n") res = sam.search( expression="samaccountname=%s" % ldb.binary_encode(cleaneduser), scope=ldb.SCOPE_SUBTREE, attrs=["servicePrincipalName"]) if len(res) > 0: spns = res[0].get("servicePrincipalName") if spns is not None: self.outf.write( "User %s has the following servicePrincipalName: \n" % res[0].dn) for e in spns: self.outf.write("\t %s\n" % e) else: self.outf.write("User %s has no servicePrincipalName\n" % res[0].dn) else: raise CommandError("User %s not found" % user)
def run(self, groupname, new_parent_dn, credopts=None, sambaopts=None, versionopts=None, H=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 = ldb.Dn(samdb, samdb.domain_dn()) filter = ("(&(sAMAccountName=%s)(objectClass=group))" % ldb.binary_encode(groupname)) try: res = samdb.search(base=domain_dn, expression=filter, scope=ldb.SCOPE_SUBTREE) group_dn = res[0].dn except IndexError: raise CommandError('Unable to find group "%s"' % (groupname)) try: full_new_parent_dn = samdb.normalize_dn_in_domain(new_parent_dn) except Exception as e: raise CommandError('Invalid new_parent_dn "%s": %s' % (new_parent_dn, e.message)) full_new_group_dn = ldb.Dn(samdb, str(group_dn)) full_new_group_dn.remove_base_components(len(group_dn) - 1) full_new_group_dn.add_base(full_new_parent_dn) try: samdb.rename(group_dn, full_new_group_dn) except Exception as e: raise CommandError('Failed to move group "%s"' % groupname, e) self.outf.write('Moved group "%s" into "%s"\n' % (groupname, full_new_parent_dn))
def remove_dc(samdb, logger, dc_name): # TODO: Check if this is the last server (covered mostly by # refusing to remove our own name) samdb.transaction_start() server_dn = None # Allow the name to be a the nTDS-DSA GUID try: ntds_guid = uuid.UUID(hex=dc_name) ntds_dn = "<GUID=%s>" % ntds_guid except ValueError: try: server_msgs = samdb.search(base=samdb.get_config_basedn(), attrs=[], expression="(&(objectClass=server)" "(cn=%s))" % ldb.binary_encode(dc_name)) except LdbError as (enum, estr): raise DemoteException( "Failure checking if %s is an server " "object in %s: " % (dc_name, samdb.domain_dns_name()), estr) if (len(server_msgs) == 0): raise DemoteException("%s is not an AD DC in %s" % (dc_name, samdb.domain_dns_name())) server_dn = server_msgs[0].dn ntds_dn = ldb.Dn(samdb, "CN=NTDS Settings") ntds_dn.add_base(server_dn) pass
def run(self, computername, new_ou_dn, credopts=None, sambaopts=None, versionopts=None, H=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 = ldb.Dn(samdb, samdb.domain_dn()) samaccountname = computername if not computername.endswith('$'): samaccountname = "%s$" % computername filter = ("(&(sAMAccountName=%s)(sAMAccountType=%u))" % (ldb.binary_encode(samaccountname), dsdb.ATYPE_WORKSTATION_TRUST)) try: res = samdb.search(base=domain_dn, expression=filter, scope=ldb.SCOPE_SUBTREE) computer_dn = res[0].dn except IndexError: raise CommandError('Unable to find computer "%s"' % (computername)) full_new_ou_dn = ldb.Dn(samdb, new_ou_dn) if not full_new_ou_dn.is_child_of(domain_dn): full_new_ou_dn.add_base(domain_dn) new_computer_dn = ldb.Dn(samdb, str(computer_dn)) new_computer_dn.remove_base_components(len(computer_dn) -1) new_computer_dn.add_base(full_new_ou_dn) try: samdb.rename(computer_dn, new_computer_dn) except Exception as e: raise CommandError('Failed to move computer "%s"' % computername, e) self.outf.write('Moved computer "%s" to "%s"\n' % (computername, new_ou_dn))
def run(self, computername, credopts=None, sambaopts=None, versionopts=None, H=None, computer_attrs=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) attrs = None if computer_attrs: attrs = computer_attrs.split(",") samaccountname = computername if not computername.endswith('$'): samaccountname = "%s$" % computername filter = ("(&(sAMAccountType=%d)(sAMAccountName=%s))" % (dsdb.ATYPE_WORKSTATION_TRUST, ldb.binary_encode(samaccountname))) domaindn = samdb.domain_dn() try: res = samdb.search(base=domaindn, expression=filter, scope=ldb.SCOPE_SUBTREE, attrs=attrs) computer_dn = res[0].dn except IndexError: raise CommandError('Unable to find computer "%s"' % samaccountname) for msg in res: computer_ldif = common.get_ldif_for_editor(samdb, msg) self.outf.write(computer_ldif)
def run(self, username=None, sambaopts=None, credopts=None, versionopts=None, H=None, filter=None, days=None, noexpiry=None): if username is None and filter is None: raise CommandError( "Either the username or '--filter' must be specified!") if filter is None: filter = "(&(objectClass=user)(sAMAccountName=%s))" % ( ldb.binary_encode(username)) lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) samdb = SamDB(url=H, session_info=system_session(), credentials=creds, lp=lp) try: samdb.setexpiry(filter, days * 24 * 3600, no_expiry_req=noexpiry) except Exception, msg: # FIXME: Catch more specific exception raise CommandError("Failed to set expiry for user '%s': %s" % (username or filter, msg))
def run(self, computername, new_ou_dn, credopts=None, sambaopts=None, versionopts=None, H=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 = ldb.Dn(samdb, samdb.domain_dn()) samaccountname = computername if not computername.endswith('$'): samaccountname = "%s$" % computername filter = ("(&(sAMAccountName=%s)(sAMAccountType=%u))" % (ldb.binary_encode(samaccountname), dsdb.ATYPE_WORKSTATION_TRUST)) try: res = samdb.search(base=domain_dn, expression=filter, scope=ldb.SCOPE_SUBTREE) computer_dn = res[0].dn except IndexError: raise CommandError('Unable to find computer "%s"' % (computername)) full_new_ou_dn = ldb.Dn(samdb, new_ou_dn) if not full_new_ou_dn.is_child_of(domain_dn): full_new_ou_dn.add_base(domain_dn) new_computer_dn = ldb.Dn(samdb, str(computer_dn)) new_computer_dn.remove_base_components(len(computer_dn)-1) new_computer_dn.add_base(full_new_ou_dn) try: samdb.rename(computer_dn, new_computer_dn) except Exception as e: raise CommandError('Failed to move computer "%s"' % computername, e) self.outf.write('Moved computer "%s" to "%s"\n' % (computername, new_ou_dn))
def run(self, groupname, credopts=None, sambaopts=None, versionopts=None, H=None, group_attrs=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) attrs = None if group_attrs: attrs = group_attrs.split(",") filter = ("(&(objectCategory=group)(sAMAccountName=%s))" % ldb.binary_encode(groupname)) domaindn = samdb.domain_dn() try: res = samdb.search(base=domaindn, expression=filter, scope=ldb.SCOPE_SUBTREE, attrs=attrs) user_dn = res[0].dn except IndexError: raise CommandError('Unable to find group "%s"' % (groupname)) for msg in res: group_ldif = common.get_ldif_for_editor(samdb, msg) self.outf.write(group_ldif)
def run(self, username=None, sambaopts=None, credopts=None, versionopts=None, filter=None, H=None): if username is None and filter is None: raise CommandError( "Either the username or '--filter' must be specified!") if filter is None: filter = "(&(objectClass=user)(sAMAccountName=%s))" % ( ldb.binary_encode(username)) lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp, fallback_machine=True) samdb = SamDB(url=H, session_info=system_session(), credentials=creds, lp=lp) try: samdb.enable_account(filter) except Exception, msg: raise CommandError("Failed to enable user '%s': %s" % (username or filter, msg))
def remove_dc(samdb, logger, dc_name): # TODO: Check if this is the last server (covered mostly by # refusing to remove our own name) samdb.transaction_start() server_dn = None # Allow the name to be a the nTDS-DSA GUID try: ntds_guid = uuid.UUID(hex=dc_name) ntds_dn = "<GUID=%s>" % ntds_guid except ValueError: try: server_msgs = samdb.search(base=samdb.get_config_basedn(), attrs=[], expression="(&(objectClass=server)" "(cn=%s))" % ldb.binary_encode(dc_name)) except LdbError as (enum, estr): raise DemoteException("Failure checking if %s is an server " "object in %s: " % (dc_name, samdb.domain_dns_name()), estr) if (len(server_msgs) == 0): raise DemoteException("%s is not an AD DC in %s" % (dc_name, samdb.domain_dns_name())) server_dn = server_msgs[0].dn ntds_dn = ldb.Dn(samdb, "CN=NTDS Settings") ntds_dn.add_base(server_dn) pass
def run(self, username=None, sambaopts=None, credopts=None, versionopts=None, H=None, filter=None, days=None, noexpiry=None): if username is None and filter is None: raise CommandError("Either the username or '--filter' must be specified!") if filter is None: filter = "(&(objectClass=user)(sAMAccountName=%s))" % (ldb.binary_encode(username)) lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) samdb = SamDB(url=H, session_info=system_session(), credentials=creds, lp=lp) try: samdb.setexpiry(filter, days*24*3600, no_expiry_req=noexpiry) except Exception as msg: # FIXME: Catch more specific exception raise CommandError("Failed to set expiry for user '%s': %s" % ( username or filter, msg)) if noexpiry: self.outf.write("Expiry for user '%s' disabled.\n" % ( username or filter)) else: self.outf.write("Expiry for user '%s' set to %u days.\n" % ( username or filter, days))
def run(self, accountname, principal, H=None, credopts=None, sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) paths = provision.provision_paths_from_lp(lp, lp.get("realm")) if H == None: path = paths.samdb else: path = H sam = SamDB(path, session_info=system_session(), credentials=creds, lp=lp) # TODO once I understand how, use the domain info to naildown # to the correct domain (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname) res = sam.search(expression="sAMAccountName=%s" % ldb.binary_encode(cleanedaccount), scope=ldb.SCOPE_SUBTREE, attrs=["msDS-AllowedToDelegateTo"]) if len(res) == 0: raise CommandError("Unable to find account name '%s'" % accountname) assert(len(res) == 1) msg = ldb.Message() msg.dn = res[0].dn msg["msDS-AllowedToDelegateTo"] = ldb.MessageElement([principal], ldb.FLAG_MOD_DELETE, "msDS-AllowedToDelegateTo") try: sam.modify(msg) except Exception as err: raise CommandError(err)
def run(self, groupname, credopts=None, sambaopts=None, versionopts=None, H=None, group_attrs=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) attrs = None if group_attrs: attrs = group_attrs.split(",") filter = ("(&(sAMAccountType=%d)(sAMAccountName=%s))" % ( ATYPE_SECURITY_GLOBAL_GROUP, ldb.binary_encode(groupname))) domaindn = samdb.domain_dn() try: res = samdb.search(base=domaindn, expression=filter, scope=ldb.SCOPE_SUBTREE, attrs=attrs) user_dn = res[0].dn except IndexError: raise CommandError('Unable to find group "%s"' % (groupname)) for msg in res: user_ldif = samdb.write_ldif(msg, ldb.CHANGETYPE_NONE) self.outf.write(user_ldif)
def run(self, username=None, filter=None, credopts=None, sambaopts=None, versionopts=None, H=None, newpassword=None, must_change_at_next_login=False, random_password=False, smartcard_required=False, clear_smartcard_required=False): if filter is None and username is None: raise CommandError("Either the username or '--filter' must be specified!") password = newpassword if smartcard_required: if password is not None and password is not '': raise CommandError('It is not allowed to specifiy ' '--newpassword ' 'together with --smartcard-required.') if must_change_at_next_login: raise CommandError('It is not allowed to specifiy ' '--must-change-at-next-login ' 'together with --smartcard-required.') if clear_smartcard_required: raise CommandError('It is not allowed to specifiy ' '--clear-smartcard-required ' 'together with --smartcard-required.') if random_password and not smartcard_required: password = generate_random_password(128, 255) while True: if smartcard_required: break if password is not None and password is not '': break password = getpass("New Password: "******"Retype Password: "******"Sorry, passwords do not match.\n") if filter is None: filter = "(&(objectClass=user)(sAMAccountName=%s))" % (ldb.binary_encode(username)) lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL) samdb = SamDB(url=H, session_info=system_session(), credentials=creds, lp=lp) if smartcard_required: command = "" try: command = "Failed to set UF_SMARTCARD_REQUIRED for user '%s'" % (username or filter) flags = dsdb.UF_SMARTCARD_REQUIRED samdb.toggle_userAccountFlags(filter, flags, on=True) command = "Failed to enable account for user '%s'" % (username or filter) samdb.enable_account(filter) except Exception, msg: # FIXME: catch more specific exception raise CommandError("%s: %s" % (command, msg)) self.outf.write("Added UF_SMARTCARD_REQUIRED OK\n")
def run(self, username=None, filter=None, credopts=None, sambaopts=None, versionopts=None, H=None, newpassword=None, must_change_at_next_login=False, random_password=False): if filter is None and username is None: raise CommandError("Either the username or '--filter' must be specified!") if random_password: password = generate_random_password(128, 255) else: password = newpassword while 1: if password is not None and password is not '': break password = getpass("New Password: "******"(&(objectClass=user)(sAMAccountName={0!s}))".format((ldb.binary_encode(username))) lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL) samdb = SamDB(url=H, session_info=system_session(), credentials=creds, lp=lp) try: samdb.setpassword(filter, password, force_change_at_next_login=must_change_at_next_login, username=username) except Exception, msg: # FIXME: catch more specific exception raise CommandError("Failed to set password for user '{0!s}': {1!s}".format(username or filter, msg))
def run(self, accountname, onoff, credopts=None, sambaopts=None, versionopts=None): on = False if onoff == "on": on = True elif onoff == "off": on = False else: raise CommandError("Invalid argument [%s]" % onoff) lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) paths = provision.provision_paths_from_lp(lp, lp.get("realm")) sam = SamDB(paths.samdb, session_info=system_session(), credentials=creds, lp=lp) # TODO once I understand how, use the domain info to naildown # to the correct domain (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname) search_filter = "sAMAccountName=%s" % ldb.binary_encode(cleanedaccount) flag = dsdb.UF_TRUSTED_FOR_DELEGATION try: sam.toggle_userAccountFlags(search_filter, flag, on=on, strict=True) except Exception, err: raise CommandError(err)
def run(self, accountname, credopts=None, sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) paths = provision.provision_paths_from_lp(lp, lp.get("realm")) sam = SamDB(paths.samdb, session_info=system_session(), credentials=creds, lp=lp) # TODO once I understand how, use the domain info to naildown # to the correct domain (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname) print "Searching for: %s" % (cleanedaccount) res = sam.search(expression="sAMAccountName=%s" % ldb.binary_encode(cleanedaccount), scope=ldb.SCOPE_SUBTREE, attrs=["userAccountControl", "msDS-AllowedToDelegateTo"]) if len(res) != 1: raise CommandError("Account %s found %d times" % (accountname, len(res))) uac = int(res[0].get("userAccountControl")[0]) allowed = res[0].get("msDS-AllowedToDelegateTo") print "Account-DN: %s" % str(res[0].dn) if uac & dsdb.UF_TRUSTED_FOR_DELEGATION: print "UF_TRUSTED_FOR_DELEGATION: 1" else: print "UF_TRUSTED_FOR_DELEGATION: 0" if uac & dsdb.UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION: print "UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION: 1" else: print "UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION: 0" if allowed != None: for a in allowed: print "msDS-AllowedToDelegateTo: %s" % (str(a))
def invalid_user(self, username): ret = self.samdb.search( base=self.samdb.domain_dn(), scope=ldb.SCOPE_SUBTREE, expression="(sAMAccountName=%s)" % ldb.binary_encode(username), ) return len(ret) != 1
def run(self, accountname, credopts=None, sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) paths = provision.provision_paths_from_lp(lp, lp.get("realm")) sam = SamDB(paths.samdb, session_info=system_session(), credentials=creds, lp=lp) # TODO once I understand how, use the domain info to naildown # to the correct domain (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname) res = sam.search(expression="sAMAccountName=%s" % ldb.binary_encode(cleanedaccount), scope=ldb.SCOPE_SUBTREE, attrs=["userAccountControl", "msDS-AllowedToDelegateTo"]) if len(res) == 0: raise CommandError("Unable to find account name '%s'" % accountname) assert(len(res) == 1) uac = int(res[0].get("userAccountControl")[0]) allowed = res[0].get("msDS-AllowedToDelegateTo") self.outf.write("Account-DN: %s\n" % str(res[0].dn)) self.outf.write("UF_TRUSTED_FOR_DELEGATION: %s\n" % bool(uac & dsdb.UF_TRUSTED_FOR_DELEGATION)) self.outf.write("UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION: %s\n" % bool(uac & dsdb.UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION)) if allowed is not None: for a in allowed: self.outf.write("msDS-AllowedToDelegateTo: %s\n" % a)
def run(self, user, credopts=None, sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) paths = provision.provision_paths_from_lp(lp, lp.get("realm")) sam = SamDB(paths.samdb, session_info=system_session(), credentials=creds, lp=lp) # TODO once I understand how, use the domain info to naildown # to the correct domain (cleaneduser, realm, domain) = _get_user_realm_domain(user) self.outf.write(cleaneduser+"\n") res = sam.search(expression="samaccountname=%s" % ldb.binary_encode(cleaneduser), scope=ldb.SCOPE_SUBTREE, attrs=["servicePrincipalName"]) if len(res) >0: spns = res[0].get("servicePrincipalName") found = False flag = ldb.FLAG_MOD_ADD if spns != None: self.outf.write( "User %s has the following servicePrincipalName: \n" % res[0].dn) for e in spns: self.outf.write("\t %s\n" % e) else: self.outf.write("User %s has no servicePrincipalName" % res[0].dn) else: raise CommandError("User %s not found" % user)
def run(self, accountname, onoff, H=None, credopts=None, sambaopts=None, versionopts=None): on = False if onoff == "on": on = True elif onoff == "off": on = False else: raise CommandError("invalid argument: '%s' (choose from 'on', 'off')" % onoff) lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp, fallback_machine=True) paths = provision.provision_paths_from_lp(lp, lp.get("realm")) if H == None: path = paths.samdb else: path = H sam = SamDB(path, session_info=system_session(), credentials=creds, lp=lp) # TODO once I understand how, use the domain info to naildown # to the correct domain (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname) search_filter = "sAMAccountName=%s" % ldb.binary_encode(cleanedaccount) flag = dsdb.UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION try: sam.toggle_userAccountFlags(search_filter, flag, flags_str="Trusted-to-Authenticate-for-Delegation", on=on, strict=True) except Exception as err: raise CommandError(err)
def run(self, groupname, gidnumber, credopts=None, sambaopts=None, versionopts=None, H=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) samdb = SamDB(url=H, session_info=system_session(), credentials=creds, lp=lp) domaindn = samdb.domain_dn() # Check group exists and doesn't have a gidNumber filter = "(samaccountname={})".format(ldb.binary_encode(groupname)) res = samdb.search(domaindn, scope=ldb.SCOPE_SUBTREE, expression=filter) if (len(res) == 0): raise CommandError("Unable to find group '{}'".format(groupname)) group_dn = res[0].dn if "gidNumber" in res[0]: raise CommandError("Group {} is a Unix group.".format(groupname)) # Check if supplied gidnumber isn't already being used filter = "(&(objectClass=group)(gidNumber={}))".format(gidnumber) res = samdb.search(domaindn, scope=ldb.SCOPE_SUBTREE, expression=filter) if (len(res) != 0): raise CommandError('gidNumber {} already used.'.format(gidnumber)) if not lp.get("idmap_ldb:use rfc2307"): self.outf.write("You are setting a Unix/RFC2307 GID. " "You may want to set 'idmap_ldb:use rfc2307 = Yes'" " in smb.conf to use the attributes for " "XID/SID-mapping.\n") group_mod = """ dn: {0} changetype: modify add: gidNumber gidNumber: {1} """.format(group_dn, gidnumber) try: samdb.modify_ldif(group_mod) except ldb.LdbError as e: raise CommandError("Failed to modify group '{0}': {1}".format( groupname, e)) self.outf.write("Modified Group '{}' successfully\n".format(groupname))
def newcomputer(self, computername, computerou=None, description=None, prepare_oldjoin=False, ip_address_list=None, service_principal_name_list=None): """Adds a new user with additional parameters :param computername: Name of the new computer :param computerou: Object container for new computer :param description: Description of the new computer :param prepare_oldjoin: Preset computer password for oldjoin mechanism :param ip_address_list: ip address list for DNS A or AAAA record :param service_principal_name_list: string list of servicePincipalName """ cn = re.sub(r"\$$", "", computername) if cn.count('$'): raise Exception('Illegal computername "%s"' % computername) samaccountname = "%s$" % cn computercontainer_dn = "CN=Computers,%s" % self.domain_dn() if computerou: computercontainer_dn = self.normalize_dn_in_domain(computerou) computer_dn = "CN=%s,%s" % (cn, computercontainer_dn) ldbmessage = {"dn": computer_dn, "sAMAccountName": samaccountname, "objectClass": "computer", } if description is not None: ldbmessage["description"] = description if service_principal_name_list: ldbmessage["servicePrincipalName"] = service_principal_name_list accountcontrol = str(dsdb.UF_WORKSTATION_TRUST_ACCOUNT | dsdb.UF_ACCOUNTDISABLE) if prepare_oldjoin: accountcontrol = str(dsdb.UF_WORKSTATION_TRUST_ACCOUNT) ldbmessage["userAccountControl"] = accountcontrol if ip_address_list: ldbmessage['dNSHostName'] = '{}.{}'.format( cn, self.domain_dns_name()) self.transaction_start() try: self.add(ldbmessage) if prepare_oldjoin: password = cn.lower() self.setpassword(("(distinguishedName=%s)" % ldb.binary_encode(computer_dn)), password, False) except: self.transaction_cancel() raise else: self.transaction_commit()
def find_email_of(self, username): ret = self.samdb.search( base=self.samdb.domain_dn(), scope=ldb.SCOPE_SUBTREE, attrs=["mail"], expression="(sAMAccountName=%s)" % ldb.binary_encode(username), ) return ret[0]["mail"][0]
def _find_user(self, name): search_filter = "(&(sAMAccountName=%s)(objectCategory=%s,%s))" % (ldb.binary_encode(name), "CN=Person,CN=Schema,CN=Configuration", self.samdb.domain_dn()) userlist = self.samdb.search(base=self.samdb.domain_dn(), scope=ldb.SCOPE_SUBTREE, expression=search_filter, attrs=[]) if userlist: return userlist[0] else: return None
def _find_user(self, name): search_filter = "(&(sAMAccountName=%s)(objectCategory=%s,%s))" % (ldb.binary_encode(name), "CN=Person,CN=Schema,CN=Configuration", self.samdb.domain_dn()) userlist = self.samdb.search(base=self.samdb.domain_dn(), scope=ldb.SCOPE_SUBTREE, expression=search_filter) if userlist: return userlist[0] else: return None
def delete(self, **kwargs): try: con = self.connection_service.connection() except Exception as e: return ResponseStatus(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Invalid server details "%s": ' % (e), None) samaccountname = kwargs['computer_name'] + "$" print(samaccountname) exp = ( "(&(sAMAccountType=%d)(sAMAccountName=%s))" % (dsdb.ATYPE_WORKSTATION_TRUST, ldb.binary_encode(samaccountname))) domain_dn = con.domain_dn() try: res = con.search(base=domain_dn, scope=ldb.SCOPE_SUBTREE, expression=exp, attrs=[]) print(str(res)) if len(res) == 0: return ResponseStatus( status.HTTP_404_NOT_FOUND, 'Unable to find computer "%s"\n' % computer_name, None) computer_dn = res[0].dn print("comp_dn: " + str(computer_dn)) computer_ac = int(res[0]["userAccountControl"][0]) if "dNSHostName" in res[0]: computer_dns_host_name = str(res[0]["dNSHostName"][0]) else: computer_dns_host_name = None except Exception as e: return ResponseStatus( status.HTTP_404_NOT_FOUND, 'Unable to find computer "%s"\n' % samaccountname, None) computer_is_workstation = (computer_ac & dsdb.UF_WORKSTATION_TRUST_ACCOUNT) if not computer_is_workstation: print("Computer is not a workstation") return ResponseStatus( status.HTTP_409_CONFLICT, 'Failed to remove computer "%s": ' % samaccountname) try: con.delete(computer_dn) if computer_dns_host_name: remove_dns_references(con, self.get_logger(), computer_dns_host_name, ignore_no_name=True) except Exception as e: return ResponseStatus( status.HTTP_409_CONFLICT, 'Failed to delete computer "%s": %s' % (samaccountname, e), None) return ResponseStatus(status.HTTP_204_NO_CONTENT, None, None)
def cleanup_old_join(ctx): '''remove any DNs from a previous join''' try: # find the krbtgt link print("checking samaccountname") if ctx.subdomain: res = None else: res = ctx.samdb.search(base=ctx.samdb.get_default_basedn(), expression='samAccountName=%s' % ldb.binary_encode(ctx.samname), attrs=["msDS-krbTgtLink"]) if res: ctx.del_noerror(res[0].dn, recursive=True) if ctx.connection_dn is not None: ctx.del_noerror(ctx.connection_dn) if ctx.krbtgt_dn is not None: ctx.del_noerror(ctx.krbtgt_dn) ctx.del_noerror(ctx.ntds_dn) ctx.del_noerror(ctx.server_dn, recursive=True) if ctx.topology_dn: ctx.del_noerror(ctx.topology_dn) if ctx.partition_dn: ctx.del_noerror(ctx.partition_dn) if res: ctx.new_krbtgt_dn = res[0]["msDS-Krbtgtlink"][0] ctx.del_noerror(ctx.new_krbtgt_dn) if ctx.subdomain: binding_options = "sign" lsaconn = lsa.lsarpc( "ncacn_ip_tcp:%s[%s]" % (ctx.server, binding_options), ctx.lp, ctx.creds) objectAttr = lsa.ObjectAttribute() objectAttr.sec_qos = lsa.QosInfo() pol_handle = lsaconn.OpenPolicy2( ''.decode('utf-8'), objectAttr, security.SEC_FLAG_MAXIMUM_ALLOWED) name = lsa.String() name.string = ctx.realm info = lsaconn.QueryTrustedDomainInfoByName( pol_handle, name, lsa.LSA_TRUSTED_DOMAIN_INFO_FULL_INFO) lsaconn.DeleteTrustedDomain(pol_handle, info.info_ex.sid) name = lsa.String() name.string = ctx.forest_domain_name info = lsaconn.QueryTrustedDomainInfoByName( pol_handle, name, lsa.LSA_TRUSTED_DOMAIN_INFO_FULL_INFO) lsaconn.DeleteTrustedDomain(pol_handle, info.info_ex.sid) except Exception: pass
def get_gpo_info(samdb, gpo=None, displayname=None, dn=None, sd_flags=security.SECINFO_OWNER | security.SECINFO_GROUP | security.SECINFO_DACL | security.SECINFO_SACL): '''Get GPO information using gpo, displayname or dn''' policies_dn = samdb.get_default_basedn() policies_dn.add_child(ldb.Dn(samdb, "CN=Policies,CN=System")) base_dn = policies_dn search_expr = "(objectClass=groupPolicyContainer)" search_scope = ldb.SCOPE_ONELEVEL if gpo is not None: search_expr = "(&(objectClass=groupPolicyContainer)(name=%s))" % ldb.binary_encode( gpo) if displayname is not None: search_expr = "(&(objectClass=groupPolicyContainer)(displayname=%s))" % ldb.binary_encode( displayname) if dn is not None: base_dn = dn search_scope = ldb.SCOPE_BASE try: msg = samdb.search(base=base_dn, scope=search_scope, expression=search_expr, attrs=[ 'nTSecurityDescriptor', 'versionNumber', 'flags', 'name', 'displayName', 'gPCFileSysPath' ], controls=['sd_flags:1:%d' % sd_flags]) except Exception as e: if gpo is not None: mesg = "Cannot get information for GPO %s" % gpo else: mesg = "Cannot get information for GPOs" raise CommandError(mesg, e) return msg
def set_password(self, **kwargs): try: con = self.connection_service.connection() except Exception as e: return ResponseStatus(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Invalid server details "%s": ' % (e), None) request = kwargs['request'] username = request['username'] password = request['password'] random_password = request['random_password'] must_change_at_next_login = False if random_password == True: password = generate_random_password(128, 255) must_change_at_next_login = True print(must_change_at_next_login) filter = "(&(objectClass=user)(sAMAccountName=%s))" % ( ldb.binary_encode(username)) exp = ("(&(sAMAccountName=%s)(sAMAccountType=805306368))" % ldb.binary_encode(username)) domain_dn = con.domain_dn() try: res = con.search(base=domain_dn, scope=ldb.SCOPE_SUBTREE, expression=exp, attrs=["dn"]) if (len(res) == 0): return ResponseStatus(status.HTTP_404_NOT_FOUND, 'no user "%s"' % username, None) except Exception as e: return ResponseStatus( status.HTTP_400_BAD_REQUEST, 'unable to find user "%s": %s' % (username, e), None) try: con.setpassword( filter, password, force_change_at_next_login=must_change_at_next_login, username=username) except Exception as e: return ResponseStatus(status.HTTP_409_CONFLICT, None, None) return ResponseStatus(status.HTTP_200_OK, None, None)
def run(self, groupname, credopts=None, sambaopts=None, versionopts=None, H=None, editor=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) filter = ("(&(sAMAccountName=%s)(objectClass=group))" % ldb.binary_encode(groupname)) domaindn = samdb.domain_dn() try: res = samdb.search(base=domaindn, expression=filter, scope=ldb.SCOPE_SUBTREE) group_dn = res[0].dn except IndexError: raise CommandError('Unable to find group "%s"' % (groupname)) if len(res) != 1: raise CommandError('Invalid number of results: for "%s": %d' % ((groupname), len(res))) msg = res[0] result_ldif = common.get_ldif_for_editor(samdb, msg) if editor is None: editor = os.environ.get('EDITOR') if editor is None: editor = 'vi' with tempfile.NamedTemporaryFile(suffix=".tmp") as t_file: t_file.write(get_bytes(result_ldif)) t_file.flush() try: check_call([editor, t_file.name]) except CalledProcessError as e: raise CalledProcessError("ERROR: ", e) with open(t_file.name) as edited_file: edited_message = edited_file.read() msgs_edited = samdb.parse_ldif(edited_message) msg_edited = next(msgs_edited)[1] res_msg_diff = samdb.msg_diff(msg, msg_edited) if len(res_msg_diff) == 0: self.outf.write("Nothing to do\n") return try: samdb.modify(res_msg_diff) except Exception as e: raise CommandError("Failed to modify group '%s': " % groupname, e) self.outf.write("Modified group '%s' successfully\n" % groupname)
def run(self, name, user, H=None, credopts=None, sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) sam = SamDB(H, session_info=system_session(), credentials=creds, lp=lp) res = sam.search( expression="servicePrincipalName=%s" % ldb.binary_encode(name), scope=ldb.SCOPE_SUBTREE) if len(res) != 0: raise CommandError("Service principal %s already" " affected to another user" % name) (cleaneduser, realm, domain) = _get_user_realm_domain(user) res = sam.search( expression="samaccountname=%s" % ldb.binary_encode(cleaneduser), scope=ldb.SCOPE_SUBTREE, attrs=["servicePrincipalName"]) if len(res) > 0: res[0].dn msg = ldb.Message() spns = res[0].get("servicePrincipalName") tab = [] found = False flag = ldb.FLAG_MOD_ADD if spns is not None: for e in spns: if str(e) == name: found = True tab.append(str(e)) flag = ldb.FLAG_MOD_REPLACE tab.append(name) msg.dn = res[0].dn msg["servicePrincipalName"] = ldb.MessageElement(tab, flag, "servicePrincipalName") if not found: sam.modify(msg) else: raise CommandError("Service principal %s already" " affected to %s" % (name, user)) else: raise CommandError("User %s not found" % user)
def run(self, name, user, force=False, credopts=None, sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) paths = provision.provision_paths_from_lp(lp, lp.get("realm")) sam = SamDB(paths.samdb, session_info=system_session(), credentials=creds, lp=lp) res = sam.search( expression="servicePrincipalName=%s" % ldb.binary_encode(name), scope=ldb.SCOPE_SUBTREE) if len(res) != 0 and not force: raise CommandError("Service principal %s already" " affected to another user" % name) (cleaneduser, realm, domain) = _get_user_realm_domain(user) res = sam.search( expression="samaccountname=%s" % ldb.binary_encode(cleaneduser), scope=ldb.SCOPE_SUBTREE, attrs=["servicePrincipalName"]) if len(res) >0: res[0].dn msg = ldb.Message() spns = res[0].get("servicePrincipalName") tab = [] found = False flag = ldb.FLAG_MOD_ADD if spns is not None: for e in spns: if str(e) == name: found = True tab.append(str(e)) flag = ldb.FLAG_MOD_REPLACE tab.append(name) msg.dn = res[0].dn msg["servicePrincipalName"] = ldb.MessageElement(tab, flag, "servicePrincipalName") if not found: sam.modify(msg) else: raise CommandError("Service principal %s already" " affected to %s" % (name, user)) else: raise CommandError("User %s not found" % user)
def set_admin_password(logger, samdb, username): """Sets a randomly generated password for the backup DB's admin user""" adminpass = samba.generate_random_password(12, 32) logger.info("Setting %s password in backup to: %s" % (username, adminpass)) logger.info("Run 'samba-tool user setpassword %s' after restoring DB" % username) samdb.setpassword("(&(objectClass=user)(sAMAccountName=%s))" % ldb.binary_encode(username), adminpass, force_change_at_next_login=False, username=username)
def run(self, groupname, credopts=None, sambaopts=None, versionopts=None, H=None, full_dn=False): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp, fallback_machine=True) try: samdb = SamDB(url=H, session_info=system_session(), credentials=creds, lp=lp) search_filter = ("(&(objectClass=group)(sAMAccountName=%s))" % ldb.binary_encode(groupname)) try: res = samdb.search(samdb.domain_dn(), scope=ldb.SCOPE_SUBTREE, expression=(search_filter), attrs=["objectSid"]) group_sid_binary = res[0].get('objectSid', idx=0) except IndexError: raise CommandError('Unable to find group "%s"' % (groupname)) group_sid = ndr_unpack(security.dom_sid, group_sid_binary) (group_dom_sid, rid) = group_sid.split() group_sid_dn = "<SID=%s>" % (group_sid) search_filter = ("(|(primaryGroupID=%s)(memberOf=%s))" % (rid, group_sid_dn)) res = samdb.search(samdb.domain_dn(), scope=ldb.SCOPE_SUBTREE, expression=(search_filter), attrs=["samAccountName", "cn"]) if (len(res) == 0): return for msg in res: if full_dn: self.outf.write("%s\n" % msg.get("dn")) continue member_name = msg.get("samAccountName", idx=0) if member_name is None: member_name = msg.get("cn", idx=0) self.outf.write("%s\n" % member_name) except Exception as e: raise CommandError('Failed to list members of "%s" group - %s' % (groupname, e))
def _find_ou(self, name): search_filter = ("(&(name=%s)(objectCategory=%s,%s))" % (ldb.binary_encode(name), "CN=Organizational-Unit,CN=Schema,CN=Configuration", self.samdb.domain_dn())) oulist = self.samdb.search(base=self.samdb.domain_dn(), scope=ldb.SCOPE_SUBTREE, expression=search_filter) if oulist: return oulist[0] else: return None
def create_subnet(samdb, configDn, subnet_name, site_name): """Create a subnet and associate it with a site. :param samdb: A samdb connection :param configDn: The DN of the configuration partition :param subnet_name: name of the subnet to create (a CIDR range) :return: None :raise SubnetAlreadyExists: if the subnet to be created already exists. :raise SiteNotFound: if the site does not exist. """ ret = samdb.search(base=configDn, scope=ldb.SCOPE_SUBTREE, expression='(&(objectclass=Site)(cn=%s))' % ldb.binary_encode(site_name)) if len(ret) != 1: raise SiteNotFound('A site with the name %s does not exist' % site_name) dn_site = ret[0].dn if not isinstance(subnet_name, str): raise SubnetInvalid("%s is not a valid subnet (not a string)" % subnet_name) dnsubnet = ldb.Dn(samdb, "CN=Subnets,CN=Sites") if dnsubnet.add_base(configDn) == False: raise SubnetException("dnsubnet.add_base() failed") if dnsubnet.add_child("CN=X") == False: raise SubnetException("dnsubnet.add_child() failed") dnsubnet.set_component(0, "CN", subnet_name) try: m = ldb.Message() m.dn = dnsubnet m["objectclass"] = ldb.MessageElement("subnet", FLAG_MOD_ADD, "objectclass") m["siteObject"] = ldb.MessageElement(str(dn_site), FLAG_MOD_ADD, "siteObject") samdb.add(m) except ldb.LdbError as e: (enum, estr) = e.args if enum == ldb.ERR_INVALID_DN_SYNTAX: raise SubnetInvalid("%s is not a valid subnet: %s" % (subnet_name, estr)) elif enum == ldb.ERR_ENTRY_ALREADY_EXISTS: # Subnet collisions are checked by exact match only, not # overlapping range. This won't stop you creating # 10.1.1.0/24 when there is already 10.1.0.0/16, or # prevent you from having numerous IPv6 subnets that refer # to the same range (e.g 5::0/16, 5::/16, 5:0:0::/16). raise SubnetAlreadyExists( 'A subnet with the CIDR %s already exists' % subnet_name) else: raise
def run(self, name, user=None, credopts=None, sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) paths = provision.provision_paths_from_lp(lp, lp.get("realm")) sam = SamDB(paths.samdb, session_info=system_session(), credentials=creds, lp=lp) res = sam.search(expression="servicePrincipalName=%s" % ldb.binary_encode(name), scope=ldb.SCOPE_SUBTREE, attrs=["servicePrincipalName", "samAccountName"]) if len(res) > 0: result = None if user is not None: (cleaneduser, realm, domain) = _get_user_realm_domain(user) for elem in res: if str(elem["samAccountName"]).lower() == cleaneduser: result = elem if result is None: raise CommandError("Unable to find user %s with" " spn %s" % (user, name)) else: if len(res) != 1: listUser = "" for r in res: listUser = "******" % (listUser, str(r.dn)) raise CommandError( "More than one user has the spn %s " "and no specific user was specified, list of users" " with this spn:%s" % (name, listUser)) else: result = res[0] msg = ldb.Message() spns = result.get("servicePrincipalName") tab = [] if spns is not None: for e in spns: if str(e) != name: tab.append(str(e)) flag = ldb.FLAG_MOD_REPLACE msg.dn = result.dn msg["servicePrincipalName"] = ldb.MessageElement( tab, flag, "servicePrincipalName") sam.modify(msg) else: raise CommandError("Service principal %s not affected" % name)
def run(self, computername, credopts=None, sambaopts=None, versionopts=None, H=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) samaccountname = computername if not computername.endswith('$'): samaccountname = "%s$" % computername filter = ( "(&(sAMAccountName=%s)(sAMAccountType=%u))" % (ldb.binary_encode(samaccountname), dsdb.ATYPE_WORKSTATION_TRUST)) try: res = samdb.search(base=samdb.domain_dn(), scope=ldb.SCOPE_SUBTREE, expression=filter, attrs=["userAccountControl", "dNSHostName"]) computer_dn = res[0].dn computer_ac = int(res[0]["userAccountControl"][0]) if "dNSHostName" in res[0]: computer_dns_host_name = res[0]["dNSHostName"][0] else: computer_dns_host_name = None except IndexError: raise CommandError('Unable to find computer "%s"' % computername) computer_is_workstation = (computer_ac & dsdb.UF_WORKSTATION_TRUST_ACCOUNT) if not computer_is_workstation: raise CommandError( 'Failed to remove computer "%s": ' 'Computer is not a workstation - removal denied' % computername) try: samdb.delete(computer_dn) if computer_dns_host_name: remove_dns_references(samdb, self.get_logger(), computer_dns_host_name, ignore_no_name=True) except Exception as e: raise CommandError( 'Failed to remove computer "%s"' % samaccountname, e) self.outf.write("Deleted computer %s\n" % computername)
def run(self, contactname, sambaopts=None, credopts=None, versionopts=None, H=None, contact_attrs=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) base_dn = samdb.domain_dn() scope = ldb.SCOPE_SUBTREE attrs = None if contact_attrs: attrs = contact_attrs.split(",") filter = ("(&(objectClass=contact)(name=%s))" % ldb.binary_encode(contactname)) if contactname.upper().startswith("CN="): # contact is specified by DN filter = "(objectClass=contact)" scope = ldb.SCOPE_BASE try: base_dn = samdb.normalize_dn_in_domain(contactname) except Exception as e: raise CommandError('Invalid dn "%s": %s' % (contactname, e)) try: res = samdb.search(base=base_dn, expression=filter, scope=scope, attrs=attrs) contact_dn = res[0].dn except IndexError: raise CommandError('Unable to find contact "%s"' % (contactname)) if len(res) > 1: for msg in sorted(res, key=attrgetter('dn')): self.outf.write("found: %s\n" % msg.dn) raise CommandError("Multiple results for contact '%s'\n" "Please specify the contact's DN" % contactname) for msg in res: contact_ldif = common.get_ldif_for_editor(samdb, msg) self.outf.write(contact_ldif)
def _find_contact(self, name): contactname = name search_filter = ("(&(objectClass=contact)(name=%s))" % ldb.binary_encode(contactname)) contactlist = self.samdb.search(base=self.samdb.domain_dn(), scope=ldb.SCOPE_SUBTREE, expression=search_filter, attrs=[]) if contactlist: return contactlist[0] else: return None
def cleanup_old_join(ctx): """remove any DNs from a previous join""" try: # find the krbtgt link print ("checking sAMAccountName") if ctx.subdomain: res = None else: res = ctx.samdb.search( base=ctx.samdb.get_default_basedn(), expression="sAMAccountName=%s" % ldb.binary_encode(ctx.samname), attrs=["msDS-krbTgtLink"], ) if res: ctx.del_noerror(res[0].dn, recursive=True) if ctx.connection_dn is not None: ctx.del_noerror(ctx.connection_dn) if ctx.krbtgt_dn is not None: ctx.del_noerror(ctx.krbtgt_dn) ctx.del_noerror(ctx.ntds_dn) ctx.del_noerror(ctx.server_dn, recursive=True) if ctx.topology_dn: ctx.del_noerror(ctx.topology_dn) if ctx.partition_dn: ctx.del_noerror(ctx.partition_dn) if res: ctx.new_krbtgt_dn = res[0]["msDS-Krbtgtlink"][0] ctx.del_noerror(ctx.new_krbtgt_dn) if ctx.subdomain: binding_options = "sign" lsaconn = lsa.lsarpc("ncacn_ip_tcp:%s[%s]" % (ctx.server, binding_options), ctx.lp, ctx.creds) objectAttr = lsa.ObjectAttribute() objectAttr.sec_qos = lsa.QosInfo() pol_handle = lsaconn.OpenPolicy2("".decode("utf-8"), objectAttr, security.SEC_FLAG_MAXIMUM_ALLOWED) name = lsa.String() name.string = ctx.realm info = lsaconn.QueryTrustedDomainInfoByName(pol_handle, name, lsa.LSA_TRUSTED_DOMAIN_INFO_FULL_INFO) lsaconn.DeleteTrustedDomain(pol_handle, info.info_ex.sid) name = lsa.String() name.string = ctx.forest_domain_name info = lsaconn.QueryTrustedDomainInfoByName(pol_handle, name, lsa.LSA_TRUSTED_DOMAIN_INFO_FULL_INFO) lsaconn.DeleteTrustedDomain(pol_handle, info.info_ex.sid) except Exception: pass
def _find_group(self, name): search_filter = ( "(&(sAMAccountName=%s)(objectCategory=%s,%s))" % (ldb.binary_encode(name), "CN=Group,CN=Schema,CN=Configuration", self.samdb.domain_dn())) grouplist = self.samdb.search(base=self.samdb.domain_dn(), scope=ldb.SCOPE_SUBTREE, expression=search_filter, attrs=[]) if grouplist: return grouplist[0] else: return None
def _find_ou(self, name): search_filter = ("(&(name=%s)(objectCategory=%s,%s))" % (ldb.binary_encode(name), "CN=Organizational-Unit,CN=Schema,CN=Configuration", self.samdb.domain_dn())) oulist = self.samdb.search(base=self.samdb.domain_dn(), scope=ldb.SCOPE_SUBTREE, expression=search_filter, attrs=[]) if oulist: return oulist[0] else: return None
def run(self, username, H=None, sambaopts=None, credopts=None, versionopts=None): self.lp = sambaopts.get_loadparm() self.creds = credopts.get_credentials(self.lp, fallback_machine=True) self.url = dc_url(self.lp, self.creds, H) samdb_connect(self) try: msg = self.samdb.search( expression= '(&(|(samAccountName=%s)(samAccountName=%s$))(objectClass=User))' % (ldb.binary_encode(username), ldb.binary_encode(username))) user_dn = msg[0].dn except Exception, e: raise CommandError("Failed to find account %s" % username, e)
def create_subnet(samdb, configDn, subnet_name, site_name): """Create a subnet and associate it with a site. :param samdb: A samdb connection :param configDn: The DN of the configuration partition :param subnet_name: name of the subnet to create (a CIDR range) :return: None :raise SubnetAlreadyExists: if the subnet to be created already exists. :raise SiteNotFound: if the site does not exist. """ ret = samdb.search(base=configDn, scope=ldb.SCOPE_SUBTREE, expression='(&(objectclass=Site)(cn=%s))' % ldb.binary_encode(site_name)) if len(ret) != 1: raise SiteNotFound('A site with the name %s does not exist' % site_name) dn_site = ret[0].dn if not isinstance(subnet_name, str): raise SubnetInvalid("%s is not a valid subnet (not a string)" % subnet_name) dnsubnet = ldb.Dn(samdb, "CN=Subnets,CN=Sites") if dnsubnet.add_base(configDn) == False: raise SubnetException("dnsubnet.add_base() failed") if dnsubnet.add_child("CN=X") == False: raise SubnetException("dnsubnet.add_child() failed") dnsubnet.set_component(0, "CN", subnet_name) try: m = ldb.Message() m.dn = dnsubnet m["objectclass"] = ldb.MessageElement("subnet", FLAG_MOD_ADD, "objectclass") m["siteObject"] = ldb.MessageElement(str(dn_site), FLAG_MOD_ADD, "siteObject") samdb.add(m) except ldb.LdbError as e: (enum, estr) = e.args if enum == ldb.ERR_INVALID_DN_SYNTAX: raise SubnetInvalid("%s is not a valid subnet: %s" % (subnet_name, estr)) elif enum == ldb.ERR_ENTRY_ALREADY_EXISTS: # Subnet collisions are checked by exact match only, not # overlapping range. This won't stop you creating # 10.1.1.0/24 when there is already 10.1.0.0/16, or # prevent you from having numerous IPv6 subnets that refer # to the same range (e.g 5::0/16, 5::/16, 5:0:0::/16). raise SubnetAlreadyExists('A subnet with the CIDR %s already exists' % subnet_name) else: raise
def run(self, username=None, filter=None, credopts=None, sambaopts=None, versionopts=None, H=None, newpassword=None, must_change_at_next_login=False, random_password=False): if filter is None and username is None: raise CommandError( "Either the username or '--filter' must be specified!") if random_password: password = generate_random_password(128, 255) else: password = newpassword while 1: if password is not None and password is not '': break password = getpass("New Password: "******"(&(objectClass=user)(sAMAccountName=%s))" % ( ldb.binary_encode(username)) lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL) samdb = SamDB(url=H, session_info=system_session(), credentials=creds, lp=lp) try: samdb.setpassword( filter, password, force_change_at_next_login=must_change_at_next_login, username=username) except Exception, msg: # FIXME: catch more specific exception raise CommandError("Failed to set password for user '%s': %s" % (username or filter, msg))
def _find_computer(self, name): samaccountname = name if not name.endswith('$'): samaccountname = "%s$" % name search_filter = ("(&(sAMAccountName=%s)(objectCategory=%s,%s))" % (ldb.binary_encode(samaccountname), "CN=Computer,CN=Schema,CN=Configuration", self.samdb.domain_dn())) computerlist = self.samdb.search(base=self.samdb.domain_dn(), scope=ldb.SCOPE_SUBTREE, expression=search_filter, attrs=[]) if computerlist: return computerlist[0] else: return None
def run(self, name, user=None, credopts=None, sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) paths = provision.provision_paths_from_lp(lp, lp.get("realm")) sam = SamDB(paths.samdb, session_info=system_session(), credentials=creds, lp=lp) res = sam.search( expression="servicePrincipalName=%s" % ldb.binary_encode(name), scope=ldb.SCOPE_SUBTREE, attrs=["servicePrincipalName", "samAccountName"]) if len(res) >0: result = None if user is not None: (cleaneduser, realm, domain) = _get_user_realm_domain(user) for elem in res: if str(elem["samAccountName"]).lower() == cleaneduser: result = elem if result is None: raise CommandError("Unable to find user %s with" " spn %s" % (user, name)) else: if len(res) != 1: listUser = "" for r in res: listUser = "******" % (listUser, str(r.dn)) raise CommandError("More than one user has the spn %s " "and no specific user was specified, list of users" " with this spn:%s" % (name, listUser)) else: result=res[0] msg = ldb.Message() spns = result.get("servicePrincipalName") tab = [] if spns is not None: for e in spns: if str(e) != name: tab.append(str(e)) flag = ldb.FLAG_MOD_REPLACE msg.dn = result.dn msg["servicePrincipalName"] = ldb.MessageElement(tab, flag, "servicePrincipalName") sam.modify(msg) else: raise CommandError("Service principal %s not affected" % name)
def _find_service_principal_name(self, name, expected_service_principal_names): """Find all servicePrincipalName values and compare with expected_service_principal_names""" samaccountname = name.strip('$') + '$' search_filter = ("(&(sAMAccountName=%s)(objectCategory=%s,%s))" % (ldb.binary_encode(samaccountname), "CN=Computer,CN=Schema,CN=Configuration", self.samdb.domain_dn())) computer_list = self.samdb.search( base=self.samdb.domain_dn(), scope=ldb.SCOPE_SUBTREE, expression=search_filter, attrs=['servicePrincipalName']) names = set() for computer in computer_list: for name in computer.get('servicePrincipalName', []): names.add(name) return names == set(expected_service_principal_names)
def run(self, username=None, sambaopts=None, credopts=None, versionopts=None, filter=None, H=None): if username is None and filter is None: raise CommandError("Either the username or '--filter' must be specified!") if filter is None: filter = "(&(objectClass=user)(sAMAccountName={0!s}))".format((ldb.binary_encode(username))) lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp, fallback_machine=True) samdb = SamDB(url=H, session_info=system_session(), credentials=creds, lp=lp) try: samdb.disable_account(filter) except Exception, msg: raise CommandError("Failed to disable user '{0!s}': {1!s}".format(username or filter, msg))
def promote_possible(ctx): """confirm that the account is just a bare NT4 BDC or a member server, so can be safely promoted""" if ctx.subdomain: # This shouldn't happen raise Exception("Can not promote into a subdomain") res = ctx.samdb.search(base=ctx.samdb.get_default_basedn(), expression='sAMAccountName=%s' % ldb.binary_encode(ctx.samname), attrs=["msDS-krbTgtLink", "userAccountControl", "serverReferenceBL", "rIDSetReferences"]) if len(res) == 0: raise Exception("Could not find domain member account '%s' to promote to a DC, use 'samba-tool domain join' instead'" % ctx.samname) if "msDS-krbTgtLink" in res[0] or "serverReferenceBL" in res[0] or "rIDSetReferences" in res[0]: raise Exception("Account '%s' appears to be an active DC, use 'samba-tool domain join' if you must re-create this account" % ctx.samname) if (int(res[0]["userAccountControl"][0]) & (samba.dsdb.UF_WORKSTATION_TRUST_ACCOUNT|samba.dsdb.UF_SERVER_TRUST_ACCOUNT) == 0): raise Exception("Account %s is not a domain member or a bare NT4 BDC, use 'samba-tool domain join' instead'" % ctx.samname) ctx.promote_from_dn = res[0].dn