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 packet_lsarpc_77(packet, conversation, context): # lsa_LookupNames4 c = context.get_lsarpc_connection() sids = lsa.TransSidArray3() names = [lsa.String("This Organization"), lsa.String("Digest Authentication")] level = lsa.LSA_LOOKUP_NAMES_ALL count = 0 lookup_options = lsa.LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES client_revision = lsa.LSA_CLIENT_REVISION_2 c.LookupNames4(names, sids, level, count, lookup_options, client_revision) return True
def packet_lsarpc_77(packet, conversation, context): # lsa_LookupNames4 c = context.get_lsarpc_connection() sids = lsa.TransSidArray3() names = [ lsa.String("This Organization"), lsa.String("Digest Authentication") ] level = 5 count = 0 lookup_options = 0 client_revision = 2 c.LookupNames4(names, sids, level, count, lookup_options, client_revision) return True
def packet_lsarpc_14(packet, conversation, context): # lsa_LookupNames c = context.get_lsarpc_named_pipe_connection() objectAttr = lsa.ObjectAttribute() pol_handle = c.OpenPolicy2(u'', objectAttr, security.SEC_FLAG_MAXIMUM_ALLOWED) sids = lsa.TransSidArray() names = [lsa.String("This Organization"), lsa.String("Digest Authentication")] level = lsa.LSA_LOOKUP_NAMES_ALL count = 0 c.LookupNames(pol_handle, names, sids, level, count) return True
def set_lsa_string(str): lsa_string = lsa.String() lsa_string.string = unicode(str) lsa_string.length = len(str) lsa_string.size = len(str) return lsa_string
def establish_trust(self, another_domain, trustdom_secret): """ Establishes trust between our and another domain Input: another_domain -- instance of TrustDomainInstance, initialized with #retrieve call trustdom_secret -- shared secred used for the trust """ self.generate_auth(trustdom_secret) info = lsa.TrustDomainInfoInfoEx() info.domain_name.string = another_domain.info['dns_domain'] info.netbios_name.string = another_domain.info['name'] info.sid = security.dom_sid(another_domain.info['sid']) info.trust_direction = lsa.LSA_TRUST_DIRECTION_INBOUND | lsa.LSA_TRUST_DIRECTION_OUTBOUND info.trust_type = lsa.LSA_TRUST_TYPE_UPLEVEL info.trust_attributes = lsa.LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE try: dname = lsa.String() dname.string = another_domain.info['dns_domain'] res = self._pipe.QueryTrustedDomainInfoByName( self._policy_handle, dname, lsa.LSA_TRUSTED_DOMAIN_INFO_FULL_INFO) self._pipe.DeleteTrustedDomain(self._policy_handle, res.info_ex.sid) except RuntimeError, e: pass
def open_user_handle(self): name = lsa.String(self.user_name) rids = self.conn.LookupNames(self.domain_handle, [name]) self.user_handle = self.conn.OpenUser(self.domain_handle, security.SEC_FLAG_MAXIMUM_ALLOWED, rids[0].ids[0])
def test_string_constructor(self): CONTENT = "The content string" s = lsa.String(CONTENT) self.assertEqual(CONTENT, s.string) # These should be zero, are set by ndr_pack and ndr_unpack self.assertEqual(0, s.size) self.assertEqual(0, s.length)
def packet_samr_5(packet, conversation, context): # LookupDomain c = context.get_samr_context() s = c.get_connection() h = c.get_handle() d = lsa.String() d.string = context.domain c.domain_sid = s.LookupDomain(h, d) return True
def open_domain_handle(self): self.handle = self.conn.Connect2( None, security.SEC_FLAG_MAXIMUM_ALLOWED) self.domain_sid = self.conn.LookupDomain( self.handle, lsa.String(self.domain)) self.domain_handle = self.conn.OpenDomain( self.handle, security.SEC_FLAG_MAXIMUM_ALLOWED, self.domain_sid)
def packet_samr_17(packet, conversation, context): # LookupNames c = context.get_samr_context() s = c.get_connection() if c.domain_handle is None: packet_samr_7(packet, conversation, context) name = lsa.String(context.username) c.rids = s.LookupNames(c.domain_handle, [name]) return True
def test_samr_change_password(self): self.creds.set_kerberos_state(MUST_USE_KERBEROS) conn = samr.samr("ncacn_np:%s[krb5,seal,smb2]" % os.getenv("SERVER")) # we want to check whether this gets rejected outright because NTLM is # disabled, so we don't actually need to encrypt a valid password here server = lsa.String() server.string = self.server username = lsa.String() username.string = os.getenv("USERNAME") try: conn.ChangePasswordUser2(server, username, None, None, True, None, None) except NTSTATUSError as e: # changing passwords should be rejected when NTLM is disabled enum = ctypes.c_uint32(e[0]).value if enum == ntstatus.NT_STATUS_NTLM_BLOCKED: self.fail("NTLM is disabled on this server") elif enum == ntstatus.NT_STATUS_WRONG_PASSWORD: # expected error case when NTLM is enabled pass else: raise
def test_string_constructor(self): CONTENT = "The content string" s = lsa.String(CONTENT) self.assertEqual(CONTENT, s.string) # These should be zero self.assertEqual(0, s.size) self.assertEqual(0, s.length) packed = ndr_pack(s) unpacked = ndr_unpack(lsa.String, packed) # Original object should be unchanged self.assertEqual(0, s.size) self.assertEqual(0, s.length) # But they should be correct in the unpacked object self.assertEqual(36, unpacked.size) self.assertEqual(36, unpacked.length)
def set_password_in_ad(connector, samaccountname, pwd, reconnect=False): _d = ud.function('ldap.ad.set_password_in_ad') # noqa: F841 # print "Static Session Key: %s" % (samr.session_key,) if reconnect: if connector.dom_handle: connector.samr.Close(connector.dom_handle) connector.samr = None if not connector.samr: connector.open_samr() user_handle = None info = None try: sam_accountname = lsa.String() sam_accountname.string = samaccountname (rids, types) = connector.samr.LookupNames(connector.dom_handle, [ sam_accountname, ]) rid = rids.ids[0] user_handle = connector.samr.OpenUser( connector.dom_handle, security.SEC_FLAG_MAXIMUM_ALLOWED, rid) userinfo18 = samba.dcerpc.samr.UserInfo18() bin_hash = binascii.a2b_hex(pwd) enc_hash = mySamEncryptNTLMHash(bin_hash, connector.samr.session_key) samr_Password = samba.dcerpc.samr.Password() samr_Password.hash = map(ord, enc_hash) userinfo18.nt_pwd = samr_Password userinfo18.nt_pwd_active = 1 userinfo18.password_expired = 0 info = connector.samr.SetUserInfo(user_handle, 18, userinfo18) finally: if user_handle: connector.samr.Close(user_handle) return info
def test_default_constructor(self): s = lsa.String() self.assertEqual(None, s.string) self.assertEqual(0, s.size) self.assertEqual(0, s.length)
def join_setup_trusts(ctx): '''provision the local SAM''' def arcfour_encrypt(key, data): from Crypto.Cipher import ARC4 c = ARC4.new(key) return c.encrypt(data) def string_to_array(string): blob = [0] * len(string) for i in range(len(string)): blob[i] = ord(string[i]) return blob print "Setup domain trusts with server %s" % ctx.server binding_options = "" # why doesn't signing work here? w2k8r2 claims no session key lsaconn = lsa.lsarpc("ncacn_np:%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) info = lsa.TrustDomainInfoInfoEx() info.domain_name.string = ctx.dnsdomain info.netbios_name.string = ctx.domain_name info.sid = security.dom_sid(ctx.domsid) info.trust_direction = lsa.LSA_TRUST_DIRECTION_INBOUND | lsa.LSA_TRUST_DIRECTION_OUTBOUND info.trust_type = lsa.LSA_TRUST_TYPE_UPLEVEL info.trust_attributes = lsa.LSA_TRUST_ATTRIBUTE_WITHIN_FOREST try: oldname = lsa.String() oldname.string = ctx.dnsdomain oldinfo = lsaconn.QueryTrustedDomainInfoByName( pol_handle, oldname, lsa.LSA_TRUSTED_DOMAIN_INFO_FULL_INFO) print("Removing old trust record for %s (SID %s)" % (ctx.dnsdomain, oldinfo.info_ex.sid)) lsaconn.DeleteTrustedDomain(pol_handle, oldinfo.info_ex.sid) except RuntimeError: pass password_blob = string_to_array(ctx.trustdom_pass.encode('utf-16-le')) clear_value = drsblobs.AuthInfoClear() clear_value.size = len(password_blob) clear_value.password = password_blob clear_authentication_information = drsblobs.AuthenticationInformation() clear_authentication_information.LastUpdateTime = samba.unix2nttime( int(time.time())) clear_authentication_information.AuthType = lsa.TRUST_AUTH_TYPE_CLEAR clear_authentication_information.AuthInfo = clear_value authentication_information_array = drsblobs.AuthenticationInformationArray( ) authentication_information_array.count = 1 authentication_information_array.array = [ clear_authentication_information ] outgoing = drsblobs.trustAuthInOutBlob() outgoing.count = 1 outgoing.current = authentication_information_array trustpass = drsblobs.trustDomainPasswords() confounder = [3] * 512 for i in range(512): confounder[i] = random.randint(0, 255) trustpass.confounder = confounder trustpass.outgoing = outgoing trustpass.incoming = outgoing trustpass_blob = ndr_pack(trustpass) encrypted_trustpass = arcfour_encrypt(lsaconn.session_key, trustpass_blob) auth_blob = lsa.DATA_BUF2() auth_blob.size = len(encrypted_trustpass) auth_blob.data = string_to_array(encrypted_trustpass) auth_info = lsa.TrustDomainInfoAuthInfoInternal() auth_info.auth_blob = auth_blob trustdom_handle = lsaconn.CreateTrustedDomainEx2( pol_handle, info, auth_info, security.SEC_STD_DELETE) rec = { "dn": "cn=%s,cn=system,%s" % (ctx.dnsforest, ctx.base_dn), "objectclass": "trustedDomain", "trustType": str(info.trust_type), "trustAttributes": str(info.trust_attributes), "trustDirection": str(info.trust_direction), "flatname": ctx.forest_domain_name, "trustPartner": ctx.dnsforest, "trustAuthIncoming": ndr_pack(outgoing), "trustAuthOutgoing": ndr_pack(outgoing) } ctx.local_samdb.add(rec) rec = { "dn": "cn=%s$,cn=users,%s" % (ctx.forest_domain_name, ctx.base_dn), "objectclass": "user", "userAccountControl": str(samba.dsdb.UF_INTERDOMAIN_TRUST_ACCOUNT), "clearTextPassword": ctx.trustdom_pass.encode('utf-16-le') } ctx.local_samdb.add(rec)
def _create_trust_relax(self, smbencrypt=True): creds = self.get_user_creds() if smbencrypt: creds.set_smb_encryption(SMB_ENCRYPTION_REQUIRED) else: creds.set_smb_encryption(SMB_ENCRYPTION_OFF) lp = self.get_loadparm() binding_string = ("ncacn_np:%s" % (samba.tests.env_get_var_value('SERVER'))) lsa_conn = lsa.lsarpc(binding_string, lp, creds) if smbencrypt: self.assertTrue(lsa_conn.transport_encrypted()) else: self.assertFalse(lsa_conn.transport_encrypted()) objectAttr = lsa.ObjectAttribute() objectAttr.sec_qos = lsa.QosInfo() pol_handle = lsa_conn.OpenPolicy2('', objectAttr, security.SEC_FLAG_MAXIMUM_ALLOWED) self.assertIsNotNone(pol_handle) name = lsa.String() name.string = "tests.samba.example.com" try: info = lsa_conn.QueryTrustedDomainInfoByName( pol_handle, name, lsa.LSA_TRUSTED_DOMAIN_INFO_FULL_INFO) lsa_conn.DeleteTrustedDomain(pol_handle, info.info_ex.sid) except RuntimeError: pass info = lsa.TrustDomainInfoInfoEx() info.domain_name.string = name.string info.netbios_name.string = "createtrustrelax" info.sid = security.dom_sid("S-1-5-21-538490383-3740119673-95748416") info.trust_direction = lsa.LSA_TRUST_DIRECTION_INBOUND | lsa.LSA_TRUST_DIRECTION_OUTBOUND info.trust_type = lsa.LSA_TRUST_TYPE_UPLEVEL info.trust_attributes = lsa.LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE password_blob = samba.string_to_byte_array( "password".encode('utf-16-le')) clear_value = drsblobs.AuthInfoClear() clear_value.size = len(password_blob) clear_value.password = password_blob clear_authentication_information = drsblobs.AuthenticationInformation() clear_authentication_information.LastUpdateTime = 0 clear_authentication_information.AuthType = lsa.TRUST_AUTH_TYPE_CLEAR clear_authentication_information.AuthInfo = clear_value authentication_information_array = drsblobs.AuthenticationInformationArray( ) authentication_information_array.count = 1 authentication_information_array.array = [ clear_authentication_information ] outgoing = drsblobs.trustAuthInOutBlob() outgoing.count = 1 outgoing.current = authentication_information_array trustdom_handle = None try: trustdom_handle = CreateTrustedDomainRelax(lsa_conn, pol_handle, info, security.SEC_STD_DELETE, outgoing, outgoing) except samba.NTSTATUSError as nt: raise AssertionError(nt) except OSError as e: if smbencrypt: raise AssertionError(e) if smbencrypt: self.assertIsNotNone(trustdom_handle) lsa_conn.DeleteTrustedDomain(pol_handle, info.sid) else: self.assertIsNone(trustdom_handle)
net = Net(creds) cldap_ret = net.finddc(domain=realm, flags=(nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS | nbt.NBT_SERVER_WRITABLE)) host = cldap_ret.pdc_dns_name ldb = samdb.SamDB(url='ldap://%s' % host, lp=lp, credentials=creds, session_info=system_session()) domain_sid = security.dom_sid(ldb.get_domain_sid()) s = samr.samr("ncacn_ip_tcp:%s[seal]" % host, lp, creds) samr_handle = s.Connect2(None, security.SEC_FLAG_MAXIMUM_ALLOWED) samr_domain = s.OpenDomain(samr_handle, security.SEC_FLAG_MAXIMUM_ALLOWED, domain_sid) try: (rids, _) = s.LookupNames(samr_domain, [lsa.String(opts.name)]) except NTSTATUSError: print('%s not found!' % opts.name) exit(1) samr_user = s.OpenUser(samr_domain, security.SEC_FLAG_MAXIMUM_ALLOWED, rids.ids[0]) flags = samr.UserInfo16() flags.acct_flags = samr.ACB_PWNOEXP | samr.ACB_WSTRUST s.SetUserInfo2(samr_user, 16, flags) s.Close(samr_user)
def test_to_string(self): # test an empty string self.assertEqual("", str(lsa.String())) # and one with contents self.assertEqual("Hello world", str(lsa.String("Hello world")))
def test_repr(self): # test an empty string self.assertEqual("lsaString(None)", repr(lsa.String())) # and one with contents self.assertEqual("lsaString('Hello world')", repr(lsa.String("Hello world")))
def test_create_and_delete_secret_over_lsa(self): dn = "cn=Test Secret,CN=System," + self.base_dn self.discardSetupMessages(dn) creds = self.insta_creds(template=self.get_credentials()) lsa_conn = lsa.lsarpc("ncacn_np:%s" % self.server, self.get_loadparm(), creds) lsa_handle = lsa_conn.OpenPolicy2( system_name="\\", attr=lsa.ObjectAttribute(), access_mask=security.SEC_FLAG_MAXIMUM_ALLOWED) secret_name = lsa.String() secret_name.string = "G$Test" lsa_conn.CreateSecret(handle=lsa_handle, name=secret_name, access_mask=security.SEC_FLAG_MAXIMUM_ALLOWED) messages = self.waitForMessages(1, 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("Add", audit["operation"]) self.assertTrue(audit["performedAsSystem"]) self.assertTrue(dn.lower(), audit["dn"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) 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 attributes = audit["attributes"] self.assertEquals(2, len(attributes)) object_class = attributes["objectClass"] self.assertEquals(1, len(object_class["actions"])) action = object_class["actions"][0] self.assertEquals("add", action["action"]) values = action["values"] self.assertEquals(1, len(values)) self.assertEquals("secret", values[0]["value"]) cn = attributes["cn"] self.assertEquals(1, len(cn["actions"])) action = cn["actions"][0] self.assertEquals("add", action["action"]) values = action["values"] self.assertEquals(1, len(values)) self.assertEquals("Test Secret", values[0]["value"]) # # Now delete the secret. self.discardMessages() h = lsa_conn.OpenSecret(handle=lsa_handle, name=secret_name, access_mask=security.SEC_FLAG_MAXIMUM_ALLOWED) lsa_conn.DeleteObject(h) messages = self.waitForMessages(1, dn=dn) print("Received %d messages" % len(messages)) self.assertEquals(1, len(messages), "Did not receive the expected number of messages") dn = "cn=Test Secret,CN=System," + self.base_dn audit = messages[0]["dsdbChange"] self.assertEquals("Delete", audit["operation"]) self.assertTrue(audit["performedAsSystem"]) self.assertTrue(dn.lower(), audit["dn"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"])
import samba.dcerpc.lsa as lsa import samba.dcerpc.samr as samr import samba.dcerpc.winreg as winreg domname = lsa.String() domname.string = u'DOMAIN' con = samr.samr('ncalrpc:', 'samba/etc/smb.conf') h = con.Connect(0, 0xFFFFFFF) sid = con.LookupDomain(h, domname) print sid con.Close(h) from samba.tests import RpcInterfaceTestCase class WinregTests(RpcInterfaceTestCase): def setUp(self): self.conn = winreg.winreg('ncalrpc:', self.get_loadparm(), self.get_credentials()) def testhklm(self): handle = self.conn.OpenHKLM( None, winreg.KEY_QUERY_VALUE | winreg.KEY_ENUMERATE_SUB_KEYS) self.conn.CloseKey(handle)