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 retrieve(self, remote_host): self.__init_lsa_pipe(remote_host) objectAttribute = lsa.ObjectAttribute() objectAttribute.sec_qos = lsa.QosInfo() try: self._policy_handle = self._pipe.OpenPolicy2( u"", objectAttribute, security.SEC_FLAG_MAXIMUM_ALLOWED) result = self._pipe.QueryInfoPolicy2(self._policy_handle, lsa.LSA_POLICY_INFO_DNS) except RuntimeError, (num, message): raise assess_dcerpc_exception(num=num, message=message)
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 test_smb3_dcerpc_encryption(self): creds = self.get_user_creds() creds.set_smb_encryption(SMB_ENCRYPTION_REQUIRED) lp = self.get_loadparm() lp.set('client ipc max protocol', 'SMB3') lp.set('client ipc min protocol', 'SMB3') binding_string = ("ncacn_np:%s" % (samba.tests.env_get_var_value('SERVER'))) lsa_conn = lsa.lsarpc(binding_string, lp, creds) objectAttr = lsa.ObjectAttribute() objectAttr.sec_qos = lsa.QosInfo() pol_handle = lsa_conn.OpenPolicy2('', objectAttr, security.SEC_FLAG_MAXIMUM_ALLOWED) self.assertIsNotNone(pol_handle)
def packet_lsarpc_39(packet, conversation, context): # lsa_QueryTrustedDomainInfoBySid # Samba does not support trusted domains, so this call is expected to fail # c = context.get_lsarpc_named_pipe_connection() objectAttr = lsa.ObjectAttribute() pol_handle = c.OpenPolicy2(u'', objectAttr, security.SEC_FLAG_MAXIMUM_ALLOWED) domsid = security.dom_sid(context.domain_sid) level = 1 try: c.QueryTrustedDomainInfoBySid(pol_handle, domsid, level) except NTSTATUSError as error: # Object Not found is the expected result, anything else is a # failure. if not check_runtime_error(error, NT_STATUS_OBJECT_NAME_NOT_FOUND): raise return True
def packet_lsarpc_15(packet, conversation, context): # lsa_LookupSids c = context.get_lsarpc_named_pipe_connection() objectAttr = lsa.ObjectAttribute() pol_handle = c.OpenPolicy2(u'', objectAttr, security.SEC_FLAG_MAXIMUM_ALLOWED) sids = lsa.SidArray() sid = lsa.SidPtr() x = dom_sid("S-1-5-7") sid.sid = x sids.sids = [sid] sids.num_sids = 1 names = lsa.TransNameArray() level = 5 count = 0 c.LookupSids(pol_handle, sids, names, level, count) return True
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"])
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)
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)