def __init__(ctx, server=None, creds=None, lp=None, site=None, netbios_name=None, targetdir=None, domain=None): ctx.creds = creds ctx.lp = lp ctx.site = site ctx.netbios_name = netbios_name ctx.targetdir = targetdir ctx.creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL) ctx.net = Net(creds=ctx.creds, lp=ctx.lp) if server is not None: ctx.server = server else: print("Finding a writeable DC for domain '%s'" % domain) ctx.server = ctx.find_dc(domain) print("Found DC %s" % ctx.server) ctx.samdb = SamDB(url="ldap://%s" % ctx.server, session_info=system_session(), credentials=ctx.creds, lp=ctx.lp) try: ctx.samdb.search(scope=ldb.SCOPE_ONELEVEL, attrs=["dn"]) except ldb.LdbError, (enum, estr): raise DCJoinException(estr)
def netcmd_get_domain_infos_via_cldap(lp, creds, address=None): '''Return domain information (CLDAP record) of the ldap-capable DC with the specified address''' net = Net(creds=creds, lp=lp) cldap_ret = net.finddc(address=address, flags=nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS) return cldap_ret
def test_net_change_password(self): dn = "CN=" + USER_NAME + ",CN=Users," + self.base_dn self.discardSetupMessages(dn) creds = self.insta_creds(template=self.get_credentials()) lp = self.get_loadparm() net = Net(creds, lp, server=self.server) password = "******" net.change_password(newpassword=password, username=USER_NAME, oldpassword=USER_PASS) messages = self.waitForMessages(1, net, dn) print("Received %d messages" % len(messages)) self.assertEqual(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["passwordChange"] self.assertEqual(EVT_ID_PASSWORD_CHANGE, audit["eventId"]) self.assertEqual("Change", audit["action"]) self.assertEqual(dn, audit["dn"]) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) session_id = self.get_session() self.assertEqual(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEqual(service_description, "DCE/RPC") self.assertTrue(self.is_guid(audit["transactionId"]))
def test_net_join_no_spnego(self): self.lp.set("client ipc max protocol", "NT1") self.lp.set("client use spnego", "no") netbios_name = "NetJoinNoSpnego" machinepass = "******" creds = self.insta_creds(template=self.get_credentials(), kerberos_state=DONT_USE_KERBEROS) net = Net(creds, self.lp, server=self.server) try: (join_password, sid, domain_name) = net.join_member(self.domain, netbios_name, LIBNET_JOIN_AUTOMATIC, machinepass=machinepass) except NTSTATUSError as e: code = ctypes.c_uint32(e.args[0]).value if code == ntstatus.NT_STATUS_CONNECTION_DISCONNECTED: self.fail("Connection failure") elif code == ntstatus.NT_STATUS_ACCESS_DENIED: return else: raise self.fail("Shoud have rejected NTLMv2 without SPNEGO")
def __init__(self, binding_string, lp, creds, samdb): self.drs = drsuapi.drsuapi(binding_string, lp, creds) (self.drs_handle, self.supported_extensions) = drs_DsBind(self.drs) self.net = Net(creds=creds, lp=lp) self.samdb = samdb self.replication_state = self.net.replicate_init( self.samdb, lp, self.drs)
def test_admin_change_password_new_password_fails_restriction(self): def isLastExpectedMessage(msg): return ((msg["type"] == "Authentication") and (msg["Authentication"]["status"] == "NT_STATUS_PASSWORD_RESTRICTION") and (msg["Authentication"]["serviceDescription"] == "SAMR Password Change") and (msg["Authentication"]["authDescription"] == "samr_ChangePasswordUser3")) creds = self.insta_creds(template=self.get_credentials()) lp = self.get_loadparm() net = Net(creds, lp, server=self.server_ip) password = "******" exception_thrown = False try: net.change_password(newpassword=password.encode('utf-8'), oldpassword=USER_PASS, username=USER_NAME) except Exception: exception_thrown = True self.assertEquals(True, exception_thrown, "Expected exception not thrown") messages = self.waitForMessages(isLastExpectedMessage) self.assertEquals(8, len(messages), "Did not receive the expected number of messages")
def test_admin_change_password_bad_original_password(self): def isLastExpectedMessage(msg): return ( (msg["type"] == "Authentication") and (msg["Authentication"]["status"] == "NT_STATUS_WRONG_PASSWORD") and (msg["Authentication"]["serviceDescription"] == "SAMR Password Change") and (msg["Authentication"]["authDescription"] == "samr_ChangePasswordUser3") and (msg["Authentication"]["eventId"] == EVT_ID_UNSUCCESSFUL_LOGON) and (msg["Authentication"]["logonType"] == EVT_LOGON_NETWORK)) creds = self.insta_creds(template=self.get_credentials()) lp = self.get_loadparm() net = Net(creds, lp, server=self.server_ip) password = "******" exception_thrown = False try: net.change_password(newpassword=password, oldpassword="******", username=USER_NAME) except Exception: exception_thrown = True self.assertEquals(True, exception_thrown, "Expected exception not thrown") messages = self.waitForMessages(isLastExpectedMessage) self.assertEquals(8, len(messages), "Did not receive the expected number of messages")
def test_admin_change_password(self): def isLastExpectedMessage(msg): return ((msg["type"] == "Authentication") and (msg["Authentication"]["status"] == "NT_STATUS_OK") and (msg["Authentication"]["serviceDescription"] == "SAMR Password Change") and (msg["Authentication"]["authDescription"] == "samr_ChangePasswordUser3") and (msg["Authentication"]["eventId"] == EVT_ID_SUCCESSFUL_LOGON) and (msg["Authentication"]["logonType"] == EVT_LOGON_NETWORK)) creds = self.insta_creds(template=self.get_credentials()) lp = self.get_loadparm() net = Net(creds, lp, server=self.server_ip) password = "******" net.change_password(newpassword=password, username=USER_NAME, oldpassword=USER_PASS) messages = self.waitForMessages(isLastExpectedMessage) print("Received %d messages" % len(messages)) self.assertEquals(8, len(messages), "Did not receive the expected number of messages")
def test_net_join_no_spnego_ntlmv1(self): self.lp.set("client ipc max protocol", "NT1") self.lp.set("client use spnego", "no") self.lp.set("client ntlmv2 auth", "no") netbios_name = "NetJoinNoSpnego" machinepass = "******" creds = self.insta_creds(template=self.get_credentials(), kerberos_state=DONT_USE_KERBEROS) net = Net(creds, self.lp, server=self.server) # NOTE WELL: We must not run more than one successful # net.join_member per file (process), as the shared # secrets.ldb handle will be kept between runs. try: (join_password, sid, domain_name) = net.join_member(self.domain, netbios_name, LIBNET_JOIN_AUTOMATIC, machinepass=machinepass) except NTSTATUSError as e: code = ctypes.c_uint32(e.args[0]).value if code == ntstatus.NT_STATUS_CONNECTION_DISCONNECTED: self.fail("Connection failure") raise os.unlink(os.path.join(self.tempdir, "secrets.ldb")) pass
def run(self, credopts=None, sambaopts=None, versionopts=None, newpassword=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) # get old password now, to get the password prompts in the right order old_password = creds.get_password() net = Net(creds, lp, server=credopts.ipaddress) password = newpassword while True: if password is not None and password is not '': break password = getpass("New Password: "******"Retype Password: "******"Sorry, passwords do not match.\n") try: net.change_password(password) except Exception, msg: # FIXME: catch more specific exception raise CommandError("Failed to change password : %s" % msg)
def test_admin_change_password(self): def isLastExpectedMessage(msg): return (msg["type"] == "Authentication" and msg["Authentication"]["status"] == "NT_STATUS_OK" and msg["Authentication"]["serviceDescription"] == "SAMR Password Change" and msg["Authentication"]["authDescription"] == "samr_ChangePasswordUser3") creds = self.insta_creds(template = self.get_credentials()) lp = self.get_loadparm() net = Net(creds, lp, server=self.server_ip) password = "******" net.change_password(newpassword=password.encode('utf-8'), username=USER_NAME, oldpassword=USER_PASS) messages = self.waitForMessages(isLastExpectedMessage) print "Received %d messages" % len(messages) self.assertEquals(8, len(messages), "Did not receive the expected number of messages")
def packet_cldap_3(packet, conversation, context): # searchRequest net = Net(creds=context.creds, lp=context.lp) net.finddc(domain=context.lp.get('realm'), flags=(nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS | nbt.NBT_SERVER_WRITABLE)) return True
def test_admin_change_password_unknown_user(self): def isLastExpectedMessage(msg): return (msg["type"] == "Authentication" and msg["Authentication"]["status"] == "NT_STATUS_NO_SUCH_USER" and msg["Authentication"]["serviceDescription"] == "SAMR Password Change" and msg["Authentication"]["authDescription"] == "samr_ChangePasswordUser3") creds = self.insta_creds(template=self.get_credentials()) lp = self.get_loadparm() net = Net(creds, lp, server=self.server_ip) password = "******" exception_thrown = False try: net.change_password(newpassword=password.encode('utf-8'), oldpassword=USER_PASS, username="******") except Exception as msg: exception_thrown = True self.assertEquals(True, exception_thrown, "Expected exception not thrown") messages = self.waitForMessages(isLastExpectedMessage) self.assertEquals(8, len(messages), "Did not receive the expected number of messages")
def test_admin_change_password_new_password_fails_restriction(self): def isLastExpectedMessage(msg): return ((msg["type"] == "Authentication") and (msg["Authentication"]["status"] == "NT_STATUS_PASSWORD_RESTRICTION") and (msg["Authentication"]["serviceDescription"] == "SAMR Password Change") and (msg["Authentication"]["authDescription"] == "samr_ChangePasswordUser3") and (msg["Authentication"]["eventId"] == EVT_ID_UNSUCCESSFUL_LOGON) and (msg["Authentication"]["logonType"] == EVT_LOGON_NETWORK)) creds = self.insta_creds(template=self.get_credentials()) lp = self.get_loadparm() net = Net(creds, lp, server=self.server_ip) password = "******" exception_thrown = False try: net.change_password(newpassword=password, oldpassword=USER_PASS, username=USER_NAME) except Exception: exception_thrown = True self.assertEqual(True, exception_thrown, "Expected exception not thrown") self.assertTrue(self.waitForMessages(isLastExpectedMessage), "Did not receive the expected message")
def test_net_set_password_user_without_permission(self): self.ldb.newuser(SECOND_USER_NAME, SECOND_USER_PASS) creds = self.insta_creds(template=self.get_credentials(), username=SECOND_USER_NAME, userpass=SECOND_USER_PASS, kerberos_state=None) lp = self.get_loadparm() net = Net(creds, lp, server=self.server) password = "******" domain = lp.get("workgroup") # # This operation should fail and trigger a transaction roll back. # try: net.set_password(newpassword=password.encode('utf-8'), account_name=USER_NAME, domain_name=domain) self.fail("Expected exception not thrown") except Exception: pass message = self.waitForTransaction(net) audit = message["dsdbTransaction"] self.assertEquals("rollback", audit["action"]) self.assertTrue(self.is_guid(audit["transactionId"]))
def test_net_set_password(self): dn = "CN=" + USER_NAME + ",CN=Users," + self.base_dn self.discardSetupMessages(dn) creds = self.insta_creds(template=self.get_credentials()) lp = self.get_loadparm() net = Net(creds, lp, server=self.server) password = "******" domain = lp.get("workgroup") net.set_password(newpassword=password.encode('utf-8'), account_name=USER_NAME, domain_name=domain) dn = "CN=" + USER_NAME + ",CN=Users," + self.base_dn messages = self.waitForMessages(1, net, dn) print("Received %d messages" % len(messages)) self.assertEquals(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["passwordChange"] self.assertEquals("Reset", audit["action"]) self.assertEquals(dn, audit["dn"]) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "DCE/RPC") session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) self.assertTrue(self.is_guid(audit["transactionId"]))
def run(self, server_name=None, credopts=None, sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp, fallback_machine=True) net = Net(creds, lp, server=credopts.ipaddress) if server_name is None: server_name = common.netcmd_dnsname(lp) self.outf.write(net.time(server_name) + "\n")
def run(self, name, credopts=None, sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp, fallback_machine=True) net = Net(creds, lp, server=credopts.ipaddress) try: net.delete_user(name) except RuntimeError, msg: raise CommandError("Failed to delete user %s: %s" % (name, msg))
def run(self, domain, target_dir=None, credopts=None, sambaopts=None, versionopts=None, force=False): if not force: raise CommandError("samba-tool vampire is deprecated, please use samba-tool join. Use --force to override") lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) net = Net(creds, lp, server=credopts.ipaddress) (domain_name, domain_sid) = net.vampire(domain=domain, target_dir=target_dir) self.outf.write("Vampired domain %s (%s)\n" % (domain_name, domain_sid))
def run(self, keytab, credopts=None, sambaopts=None, versionopts=None, principal=None): lp = sambaopts.get_loadparm() net = Net(None, lp) net.export_keytab(keytab=keytab, principal=principal)
def get_ldb_url(lp, creds, names): if names.serverrole == "member server": net = Net(creds, lp) dc = net.finddc(domain=names.dnsdomain, flags=nbt.NBT_SERVER_LDAP) url = "ldap://" + dc.pdc_dns_name else: url = lp.samdb_url() return url
def __init__(self, binding_string, lp, creds, samdb, invocation_id): self.drs = drsuapi.drsuapi(binding_string, lp, creds) (self.drs_handle, self.supported_extensions) = drs_DsBind(self.drs) self.net = Net(creds=creds, lp=lp) self.samdb = samdb if not isinstance(invocation_id, misc.GUID): raise RuntimeError("Must supply GUID for invocation_id") if invocation_id == misc.GUID("00000000-0000-0000-0000-000000000000"): raise RuntimeError("Must not set GUID 00000000-0000-0000-0000-000000000000 as invocation_id") self.replication_state = self.net.replicate_init(self.samdb, lp, self.drs, invocation_id)
def finddc(self, realm=None, flags=None): if not realm: realm = self.realm if not flags: flags = nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS | nbt.NBT_SERVER_WRITABLE net = Net(creds=self.creds, lp=self.lp) ret = net.finddc(domain=realm, flags=flags) return ret.pdc_dns_name
def netcmd_finddc(lp, creds, realm=None): '''Return domain-name of a writable/ldap-capable DC for the default domain (parameter "realm" in smb.conf) unless another realm has been specified as argument''' net = Net(creds=creds, lp=lp) if realm is None: realm = lp.get('realm') cldap_ret = net.finddc(domain=realm, flags=nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS | nbt.NBT_SERVER_WRITABLE) return cldap_ret.pdc_dns_name
def __init__(self, lp, creds): self.lp = lp self.creds = creds self.realm = lp.get('realm') net = Net(creds=creds, lp=lp) cldap_ret = net.finddc(domain=self.realm, flags=(nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS)) self.l = ldap.initialize('ldap://%s' % cldap_ret.pdc_dns_name) if self.__kinit_for_gssapi(): auth_tokens = ldap.sasl.gssapi('') self.l.sasl_interactive_bind_s('', auth_tokens) else: self.l.bind_s('%s@%s' % (creds.get_username(), self.realm) if not self.realm in creds.get_username() else creds.get_username(), creds.get_password())
def run(self, name, password=None, credopts=None, sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) net = Net(creds, lp, server=credopts.ipaddress) net.create_user(name) if password is not None: net.set_password(name, creds.get_domain(), password, creds)
def __domain_name(server): global cldap_ret, cldap_server if not cldap_ret or not strcasecmp(server, cldap_server): try: net = Net(Credentials()) cldap_ret = net.finddc(address=server, flags=(nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS)) cldap_server = server except NTSTATUSError as e: ycpbuiltins.y2error(str(e)) return cldap_ret.dns_domain if cldap_ret else server
def test_export_keytab(self): net = Net(None, self.lp) net.export_keytab(keytab=self.ktfile, principal=self.principal) assert os.path.exists(self.ktfile), 'keytab was not created' with open_bytes(self.ktfile) as bytes_kt: result = '' for c in bytes_kt.read(): if c in string.printable: result += c principal_parts = self.principal.split('@') assert principal_parts[0] in result and \ principal_parts[1] in result, \ 'Principal not found in generated keytab'
def run(self, domain, role=None, sambaopts=None, credopts=None, versionopts=None, server=None, site=None, targetdir=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) net = Net(creds, lp, server=credopts.ipaddress) if site is None: site = "Default-First-Site-Name" netbios_name = lp.get("netbios name") if not role is None: role = role.upper() if role is None or role == "MEMBER": (join_password, sid, domain_name) = net.join_member(domain, netbios_name, LIBNET_JOIN_AUTOMATIC) self.outf.write("Joined domain %s (%s)\n" % (domain_name, sid)) return elif role == "DC": join_DC(server=server, creds=creds, lp=lp, domain=domain, site=site, netbios_name=netbios_name, targetdir=targetdir) return elif role == "RODC": join_RODC(server=server, creds=creds, lp=lp, domain=domain, site=site, netbios_name=netbios_name, targetdir=targetdir) return else: raise CommandError( "Invalid role %s (possible values: MEMBER, BDC, RODC)" % role)
def test_net_change_password(self): dn = "CN=" + USER_NAME + ",CN=Users," + self.base_dn self.discardSetupMessages(dn) creds = self.insta_creds(template=self.get_credentials()) lp = self.get_loadparm() net = Net(creds, lp, server=self.server) password = "******" net.change_password(newpassword=password, username=USER_NAME, oldpassword=USER_PASS) messages = self.waitForMessages(1, net, dn=dn) print("Received %d messages" % len(messages)) self.assertEquals(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["dsdbChange"] self.assertEquals("Modify", audit["operation"]) self.assertFalse(audit["performedAsSystem"]) self.assertTrue(dn.lower(), audit["dn"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) # We skip the check for self.get_service_description() as this # is subject to a race between smbd and the s4 rpc_server code # as to which will set the description as it is DCE/RPC over SMB self.assertTrue(self.is_guid(audit["transactionId"])) attributes = audit["attributes"] self.assertEquals(1, len(attributes)) actions = attributes["clearTextPassword"]["actions"] self.assertEquals(1, len(actions)) self.assertTrue(actions[0]["redacted"]) self.assertEquals("replace", actions[0]["action"])