traffic_packets.py: let Lookup{Sids,Names}() work against a sane server
[Samba.git] / python / samba / emulate / traffic_packets.py
blob688c935cdc09baf07af00ce0cbd0a6f465b9bd13
1 # Dispatch for various request types.
3 # Copyright (C) Catalyst IT Ltd. 2017
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 import os
19 import ctypes
20 import random
22 from samba.net import Net
23 from samba.dcerpc import security, drsuapi, nbt, lsa, netlogon, ntlmssp
24 from samba.dcerpc.netlogon import netr_WorkstationInformation
25 from samba.dcerpc.security import dom_sid
26 from samba.netbios import Node
27 from samba.ndr import ndr_pack
28 from samba.credentials import (
29 CLI_CRED_NTLMv2_AUTH,
30 MUST_USE_KERBEROS,
31 DONT_USE_KERBEROS
33 from samba import NTSTATUSError
34 from samba.ntstatus import NT_STATUS_OBJECT_NAME_NOT_FOUND
35 from samba.dcerpc.misc import SEC_CHAN_WKSTA
36 import samba
37 samba.ensure_third_party_module("dns", "dnspython")
38 import dns.resolver
40 def uint32(v):
41 return ctypes.c_uint32(v).value
44 def check_runtime_error(runtime, val):
45 if runtime is None:
46 return False
48 err32 = uint32(runtime[0])
49 if err32 == val:
50 return True
52 return False
55 name_formats = [
56 drsuapi.DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
57 drsuapi.DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
58 drsuapi.DRSUAPI_DS_NAME_FORMAT_DISPLAY,
59 drsuapi.DRSUAPI_DS_NAME_FORMAT_GUID,
60 drsuapi.DRSUAPI_DS_NAME_FORMAT_CANONICAL,
61 drsuapi.DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
62 drsuapi.DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX,
63 drsuapi.DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
64 drsuapi.DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
65 drsuapi.DRSUAPI_DS_NAME_FORMAT_DNS_DOMAIN,
66 drsuapi.DRSUAPI_DS_NAME_FORMAT_UPN_AND_ALTSECID,
67 drsuapi.DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT_NAME_SANS_DOMAIN_EX,
68 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_GLOBAL_CATALOG_SERVERS,
69 drsuapi.DRSUAPI_DS_NAME_FORMAT_UPN_FOR_LOGON,
70 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_WITH_DCS_IN_SITE,
71 drsuapi.DRSUAPI_DS_NAME_FORMAT_STRING_SID_NAME,
72 drsuapi.DRSUAPI_DS_NAME_FORMAT_ALT_SECURITY_IDENTITIES_NAME,
73 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_NCS,
74 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_DOMAINS,
75 drsuapi.DRSUAPI_DS_NAME_FORMAT_MAP_SCHEMA_GUID,
76 drsuapi.DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT_NAME_SANS_DOMAIN,
77 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_ROLES,
78 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_INFO_FOR_SERVER,
79 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_FOR_DOMAIN_IN_SITE,
80 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_DOMAINS_IN_SITE,
81 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_IN_SITE,
82 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_SITES,
86 def warning(message):
87 print("\033[37;41;1m" "Warning: %s" "\033[00m" % (message))
89 ###############################################################################
91 # Packet generation functions:
93 # All the packet generation functions have the following form:
94 # packet_${protocol}_${opcode}(packet, conversation, context)
96 # The functions return true, if statistics should be collected for the packet
97 # false, the packet has been ignored.
99 # Where:
100 # protocol is the protocol, i.e. cldap, dcerpc, ...
101 # opcode is the protocol op code i.e. type of the packet to be
102 # generated.
104 # packet contains data about the captured/generated packet
105 # provides any extra data needed to generate the packet
107 # conversation Details of the current client/server interaction
109 # context state data for the current interaction
113 # The following protocols are not currently handled:
114 # smb
115 # smb2
116 # browser
117 # smb_netlogon
119 # The following drsuapi replication packets are currently ignored:
120 # DsReplicaSync
121 # DsGetNCChanges
122 # DsReplicaUpdateRefs
125 # Packet generators that do NOTHING are assigned to the null_packet
126 # function which allows the conversation generators to notice this and
127 # avoid a whole lot of pointless work.
128 def null_packet(packet, conversation, context):
129 return False
132 def packet_cldap_3(packet, conversation, context):
133 # searchRequest
134 net = Net(creds=context.creds, lp=context.lp)
135 net.finddc(domain=context.lp.get('realm'),
136 flags=(nbt.NBT_SERVER_LDAP |
137 nbt.NBT_SERVER_DS |
138 nbt.NBT_SERVER_WRITABLE))
139 return True
142 packet_cldap_5 = null_packet
143 # searchResDone
145 packet_dcerpc_0 = null_packet
146 # Request
147 # Can be ignored, it's the continuation of an existing conversation
149 packet_dcerpc_2 = null_packet
150 # Request
151 # Server response, so should be ignored
153 packet_dcerpc_3 = null_packet
155 packet_dcerpc_11 = null_packet
156 # Bind
157 # creation of the rpc dcerpc connection is managed by the higher level
158 # protocol drivers. So we ignore it when generating traffic
161 packet_dcerpc_12 = null_packet
162 # Bind_ack
163 # Server response, so should be ignored
166 packet_dcerpc_13 = null_packet
167 # Bind_nak
168 # Server response, so should be ignored
171 packet_dcerpc_14 = null_packet
172 # Alter_context
173 # Generated as part of the connect process
176 def packet_dcerpc_15(packet, conversation, context):
177 # Alter_context_resp
178 # This means it was GSSAPI/krb5 (probably)
179 # Check the kerberos_state and issue a diagnostic if kerberos not enabled
180 if context.user_creds.get_kerberos_state() == DONT_USE_KERBEROS:
181 warning("Kerberos disabled but have dcerpc Alter_context_resp "
182 "indicating Kerberos was used")
183 return False
186 def packet_dcerpc_16(packet, conversation, context):
187 # AUTH3
188 # This means it was NTLMSSP
189 # Check the kerberos_state and issue a diagnostic if kerberos enabled
190 if context.user_creds.get_kerberos_state() == MUST_USE_KERBEROS:
191 warning("Kerberos enabled but have dcerpc AUTH3 "
192 "indicating NTLMSSP was used")
193 return False
196 def packet_dns_0(packet, conversation, context):
197 # query
198 name, rtype = context.guess_a_dns_lookup()
199 dns.resolver.query(name, rtype)
200 return True
203 packet_dns_1 = null_packet
204 # response
205 # Server response, so should be ignored
208 def packet_drsuapi_0(packet, conversation, context):
209 # DsBind
210 context.get_drsuapi_connection_pair(True)
211 return True
214 NAME_FORMATS = [getattr(drsuapi, _x) for _x in dir(drsuapi)
215 if 'NAME_FORMAT' in _x]
218 def packet_drsuapi_12(packet, conversation, context):
219 # DsCrackNames
220 drs, handle = context.get_drsuapi_connection_pair()
222 names = drsuapi.DsNameString()
223 names.str = context.server
225 req = drsuapi.DsNameRequest1()
226 req.format_flags = 0
227 req.format_offered = 7
228 req.format_desired = random.choice(name_formats)
229 req.codepage = 1252
230 req.language = 1033 # German, I think
231 req.format_flags = 0
232 req.count = 1
233 req.names = [names]
235 (result, ctr) = drs.DsCrackNames(handle, 1, req)
236 return True
239 def packet_drsuapi_13(packet, conversation, context):
240 # DsWriteAccountSpn
241 req = drsuapi.DsWriteAccountSpnRequest1()
242 req.operation = drsuapi.DRSUAPI_DS_SPN_OPERATION_ADD
243 (drs, handle) = context.get_drsuapi_connection_pair()
244 (level, res) = drs.DsWriteAccountSpn(handle, 1, req)
245 return True
248 def packet_drsuapi_1(packet, conversation, context):
249 # DsUnbind
250 (drs, handle) = context.get_drsuapi_connection_pair()
251 drs.DsUnbind(handle)
252 del context.drsuapi_connections[-1]
253 return True
256 packet_drsuapi_2 = null_packet
257 # DsReplicaSync
258 # This is between DCs, triggered on a DB change
259 # Ignoring for now
262 packet_drsuapi_3 = null_packet
263 # DsGetNCChanges
264 # This is between DCs, trigger with DB operation,
265 # or DsReplicaSync between DCs.
266 # Ignoring for now
269 packet_drsuapi_4 = null_packet
270 # DsReplicaUpdateRefs
271 # Ignoring for now
274 packet_epm_3 = null_packet
275 # Map
276 # Will be generated by higher level protocol calls
279 def packet_kerberos_(packet, conversation, context):
280 # Use the presence of kerberos packets as a hint to enable kerberos
281 # for the rest of the conversation.
282 # i.e. kerberos packets are not explicitly generated.
283 context.user_creds.set_kerberos_state(MUST_USE_KERBEROS)
284 context.user_creds_bad.set_kerberos_state(MUST_USE_KERBEROS)
285 context.machine_creds.set_kerberos_state(MUST_USE_KERBEROS)
286 context.machine_creds_bad.set_kerberos_state(MUST_USE_KERBEROS)
287 context.creds.set_kerberos_state(MUST_USE_KERBEROS)
288 return False
291 packet_ldap_ = null_packet
292 # Unknown
293 # The ldap payload was probably encrypted so just ignore it.
296 def packet_ldap_0(packet, conversation, context):
297 # bindRequest
298 if packet.extra[5] == "simple":
299 # Perform a simple bind.
300 context.get_ldap_connection(new=True, simple=True)
301 else:
302 # Perform a sasl bind.
303 context.get_ldap_connection(new=True, simple=False)
304 return True
307 packet_ldap_1 = null_packet
308 # bindResponse
309 # Server response ignored for traffic generation
312 def packet_ldap_2(packet, conversation, context):
313 # unbindRequest
314 # pop the last one off -- most likely we're in a bind/unbind ping.
315 del context.ldap_connections[-1:]
316 return False
319 def packet_ldap_3(packet, conversation, context):
320 # searchRequest
322 (scope, dn_sig, filter, attrs, extra, desc, oid) = packet.extra
323 if not scope:
324 scope = 0
326 samdb = context.get_ldap_connection()
327 dn = context.get_matching_dn(dn_sig)
329 samdb.search(dn, scope=int(scope), attrs=attrs.split(','))
330 return True
333 packet_ldap_4 = null_packet
334 # searchResEntry
335 # Server response ignored for traffic generation
338 packet_ldap_5 = null_packet
339 # Server response ignored for traffic generation
341 packet_ldap_6 = null_packet
343 packet_ldap_7 = null_packet
345 packet_ldap_8 = null_packet
347 packet_ldap_9 = null_packet
349 packet_ldap_16 = null_packet
351 packet_lsarpc_0 = null_packet
352 # lsarClose
354 packet_lsarpc_1 = null_packet
355 # lsarDelete
357 packet_lsarpc_2 = null_packet
358 # lsarEnumeratePrivileges
360 packet_lsarpc_3 = null_packet
361 # LsarQuerySecurityObject
363 packet_lsarpc_4 = null_packet
364 # LsarSetSecurityObject
366 packet_lsarpc_5 = null_packet
367 # LsarChangePassword
369 packet_lsarpc_6 = null_packet
370 # lsa_OpenPolicy
371 # We ignore this, but take it as a hint that the lsarpc handle should
372 # be over a named pipe.
376 def packet_lsarpc_14(packet, conversation, context):
377 # lsa_LookupNames
378 c = context.get_lsarpc_named_pipe_connection()
380 objectAttr = lsa.ObjectAttribute()
381 pol_handle = c.OpenPolicy2(u'', objectAttr,
382 security.SEC_FLAG_MAXIMUM_ALLOWED)
384 sids = lsa.TransSidArray()
385 names = [lsa.String("This Organization"),
386 lsa.String("Digest Authentication")]
387 level = lsa.LSA_LOOKUP_NAMES_ALL
388 count = 0
389 c.LookupNames(pol_handle, names, sids, level, count)
390 return True
393 def packet_lsarpc_15(packet, conversation, context):
394 # lsa_LookupSids
395 c = context.get_lsarpc_named_pipe_connection()
397 objectAttr = lsa.ObjectAttribute()
398 pol_handle = c.OpenPolicy2(u'', objectAttr,
399 security.SEC_FLAG_MAXIMUM_ALLOWED)
401 sids = lsa.SidArray()
402 sid = lsa.SidPtr()
404 x = dom_sid("S-1-5-7")
405 sid.sid = x
406 sids.sids = [sid]
407 sids.num_sids = 1
408 names = lsa.TransNameArray()
409 level = lsa.LSA_LOOKUP_NAMES_ALL
410 count = 0
412 c.LookupSids(pol_handle, sids, names, level, count)
413 return True
416 def packet_lsarpc_39(packet, conversation, context):
417 # lsa_QueryTrustedDomainInfoBySid
418 # Samba does not support trusted domains, so this call is expected to fail
420 c = context.get_lsarpc_named_pipe_connection()
422 objectAttr = lsa.ObjectAttribute()
424 pol_handle = c.OpenPolicy2(u'', objectAttr,
425 security.SEC_FLAG_MAXIMUM_ALLOWED)
427 domsid = security.dom_sid(context.domain_sid)
428 level = 1
429 try:
430 c.QueryTrustedDomainInfoBySid(pol_handle, domsid, level)
431 except NTSTATUSError as error:
432 # Object Not found is the expected result, anything else is a
433 # failure.
434 if not check_runtime_error(error, NT_STATUS_OBJECT_NAME_NOT_FOUND):
435 raise
436 return True
439 packet_lsarpc_40 = null_packet
440 # lsa_SetTrustedDomainInfo
441 # Not currently supported
444 packet_lsarpc_43 = null_packet
445 # LsaStorePrivateData
448 packet_lsarpc_44 = null_packet
449 # LsaRetrievePrivateData
452 packet_lsarpc_68 = null_packet
453 # LsarLookupNames3
456 def packet_lsarpc_76(packet, conversation, context):
457 # lsa_LookupSids3
458 c = context.get_lsarpc_connection()
459 sids = lsa.SidArray()
460 sid = lsa.SidPtr()
461 # Need a set
462 x = dom_sid("S-1-5-7")
463 sid.sid = x
464 sids.sids = [sid]
465 sids.num_sids = 1
466 names = lsa.TransNameArray2()
467 level = lsa.LSA_LOOKUP_NAMES_ALL
468 count = 0
469 lookup_options = lsa.LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES
470 client_revision = lsa.LSA_CLIENT_REVISION_2
471 c.LookupSids3(sids, names, level, count, lookup_options, client_revision)
472 return True
475 def packet_lsarpc_77(packet, conversation, context):
476 # lsa_LookupNames4
477 c = context.get_lsarpc_connection()
478 sids = lsa.TransSidArray3()
479 names = [lsa.String("This Organization"),
480 lsa.String("Digest Authentication")]
481 level = lsa.LSA_LOOKUP_NAMES_ALL
482 count = 0
483 lookup_options = lsa.LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES
484 client_revision = lsa.LSA_CLIENT_REVISION_2
485 c.LookupNames4(names, sids, level, count, lookup_options, client_revision)
486 return True
489 def packet_nbns_0(packet, conversation, context):
490 # query
491 n = Node()
492 try:
493 n.query_name("ANAME", context.server, timeout=4, broadcast=False)
494 except:
495 pass
496 return True
499 packet_nbns_1 = null_packet
500 # response
501 # Server response, not generated by the client
504 packet_rpc_netlogon_0 = null_packet
506 packet_rpc_netlogon_1 = null_packet
508 packet_rpc_netlogon_4 = null_packet
509 # NetrServerReqChallenge
510 # generated by higher level protocol drivers
511 # ignored for traffic generation
513 packet_rpc_netlogon_14 = null_packet
515 packet_rpc_netlogon_15 = null_packet
517 packet_rpc_netlogon_21 = null_packet
518 # NetrLogonDummyRoutine1
519 # Used to determine security settings. Triggered from schannel setup
520 # So no need for an explicit generator
523 packet_rpc_netlogon_26 = null_packet
524 # NetrServerAuthenticate3
525 # Triggered from schannel set up, no need for an explicit generator
528 def packet_rpc_netlogon_29(packet, conversation, context):
529 # NetrLogonGetDomainInfo [531]
530 c = context.get_netlogon_connection()
531 (auth, succ) = context.get_authenticator()
532 query = netr_WorkstationInformation()
534 c.netr_LogonGetDomainInfo(context.server,
535 context.netbios_name,
536 auth,
537 succ,
538 2, # TODO are there other values?
539 query)
540 return True
543 def packet_rpc_netlogon_30(packet, conversation, context):
544 # NetrServerPasswordSet2
545 c = context.get_netlogon_connection()
546 (auth, succ) = context.get_authenticator()
547 DATA_LEN = 512
548 # Set the new password to the existing password, this generates the same
549 # work load as a new value, and leaves the account password intact for
550 # subsequent runs
551 newpass = context.machine_creds.get_password().encode('utf-16-le')
552 pwd_len = len(newpass)
553 filler = [ord(x) for x in os.urandom(DATA_LEN - pwd_len)]
554 pwd = netlogon.netr_CryptPassword()
555 pwd.length = pwd_len
556 pwd.data = filler + [ord(x) for x in newpass]
557 context.machine_creds.encrypt_netr_crypt_password(pwd)
558 c.netr_ServerPasswordSet2(context.server,
559 context.machine_creds.get_workstation(),
560 SEC_CHAN_WKSTA,
561 context.netbios_name,
562 auth,
563 pwd)
564 return True
567 packet_rpc_netlogon_34 = null_packet
570 def packet_rpc_netlogon_39(packet, conversation, context):
571 # NetrLogonSamLogonEx [4331]
572 def connect(creds):
573 c = context.get_netlogon_connection()
575 # Disable Kerberos in cli creds to extract NTLM response
576 old_state = creds.get_kerberos_state()
577 creds.set_kerberos_state(DONT_USE_KERBEROS)
579 logon = samlogon_logon_info(context.domain,
580 context.netbios_name,
581 creds)
582 logon_level = netlogon.NetlogonNetworkTransitiveInformation
583 validation_level = netlogon.NetlogonValidationSamInfo4
584 netr_flags = 0
585 c.netr_LogonSamLogonEx(context.server,
586 context.machine_creds.get_workstation(),
587 logon_level,
588 logon,
589 validation_level,
590 netr_flags)
592 creds.set_kerberos_state(old_state)
594 context.last_samlogon_bad =\
595 context.with_random_bad_credentials(connect,
596 context.user_creds,
597 context.user_creds_bad,
598 context.last_samlogon_bad)
599 return True
602 def samlogon_target(domain_name, computer_name):
603 target_info = ntlmssp.AV_PAIR_LIST()
604 target_info.count = 3
605 computername = ntlmssp.AV_PAIR()
606 computername.AvId = ntlmssp.MsvAvNbComputerName
607 computername.Value = computer_name
609 domainname = ntlmssp.AV_PAIR()
610 domainname.AvId = ntlmssp.MsvAvNbDomainName
611 domainname.Value = domain_name
613 eol = ntlmssp.AV_PAIR()
614 eol.AvId = ntlmssp.MsvAvEOL
615 target_info.pair = [domainname, computername, eol]
617 return ndr_pack(target_info)
620 def samlogon_logon_info(domain_name, computer_name, creds):
622 target_info_blob = samlogon_target(domain_name, computer_name)
624 challenge = b"abcdefgh"
625 # User account under test
626 response = creds.get_ntlm_response(flags=CLI_CRED_NTLMv2_AUTH,
627 challenge=challenge,
628 target_info=target_info_blob)
630 logon = netlogon.netr_NetworkInfo()
632 logon.challenge = [ord(x) for x in challenge]
633 logon.nt = netlogon.netr_ChallengeResponse()
634 logon.nt.length = len(response["nt_response"])
635 logon.nt.data = [ord(x) for x in response["nt_response"]]
636 logon.identity_info = netlogon.netr_IdentityInfo()
638 (username, domain) = creds.get_ntlm_username_domain()
639 logon.identity_info.domain_name.string = domain
640 logon.identity_info.account_name.string = username
641 logon.identity_info.workstation.string = creds.get_workstation()
643 return logon
646 def packet_rpc_netlogon_40(packet, conversation, context):
647 # DsrEnumerateDomainTrusts
648 c = context.get_netlogon_connection()
649 c.netr_DsrEnumerateDomainTrusts(
650 context.server,
651 netlogon.NETR_TRUST_FLAG_IN_FOREST |
652 netlogon.NETR_TRUST_FLAG_OUTBOUND |
653 netlogon.NETR_TRUST_FLAG_INBOUND)
654 return True
657 def packet_rpc_netlogon_45(packet, conversation, context):
658 # NetrLogonSamLogonWithFlags [7]
659 def connect(creds):
660 c = context.get_netlogon_connection()
661 (auth, succ) = context.get_authenticator()
663 # Disable Kerberos in cli creds to extract NTLM response
664 old_state = creds.get_kerberos_state()
665 creds.set_kerberos_state(DONT_USE_KERBEROS)
667 logon = samlogon_logon_info(context.domain,
668 context.netbios_name,
669 creds)
670 logon_level = netlogon.NetlogonNetworkTransitiveInformation
671 validation_level = netlogon.NetlogonValidationSamInfo4
672 netr_flags = 0
673 c.netr_LogonSamLogonWithFlags(context.server,
674 context.machine_creds.get_workstation(),
675 auth,
676 succ,
677 logon_level,
678 logon,
679 validation_level,
680 netr_flags)
682 creds.set_kerberos_state(old_state)
684 context.last_samlogon_bad =\
685 context.with_random_bad_credentials(connect,
686 context.user_creds,
687 context.user_creds_bad,
688 context.last_samlogon_bad)
689 return True
692 def packet_samr_0(packet, conversation, context):
693 # Open
694 c = context.get_samr_context()
695 c.get_handle()
696 return True
699 def packet_samr_1(packet, conversation, context):
700 # Close
701 c = context.get_samr_context()
702 s = c.get_connection()
703 # close the last opened handle, may not always be accurate
704 # but will do for load simulation
705 if c.user_handle is not None:
706 s.Close(c.user_handle)
707 c.user_handle = None
708 elif c.group_handle is not None:
709 s.Close(c.group_handle)
710 c.group_handle = None
711 elif c.domain_handle is not None:
712 s.Close(c.domain_handle)
713 c.domain_handle = None
714 c.rids = None
715 elif c.handle is not None:
716 s.Close(c.handle)
717 c.handle = None
718 c.domain_sid = None
719 return True
722 def packet_samr_3(packet, conversation, context):
723 # QuerySecurity
724 c = context.get_samr_context()
725 s = c.get_connection()
726 if c.user_handle is None:
727 packet_samr_34(packet, conversation, context)
728 s.QuerySecurity(c.user_handle, 1)
729 return True
732 def packet_samr_5(packet, conversation, context):
733 # LookupDomain
734 c = context.get_samr_context()
735 s = c.get_connection()
736 h = c.get_handle()
737 d = lsa.String()
738 d.string = context.domain
739 c.domain_sid = s.LookupDomain(h, d)
740 return True
743 def packet_samr_6(packet, conversation, context):
744 # EnumDomains
745 c = context.get_samr_context()
746 s = c.get_connection()
747 h = c.get_handle()
748 s.EnumDomains(h, 0, 0)
749 return True
752 def packet_samr_7(packet, conversation, context):
753 # OpenDomain
754 c = context.get_samr_context()
755 s = c.get_connection()
756 h = c.get_handle()
757 if c.domain_sid is None:
758 packet_samr_5(packet, conversation, context)
760 c.domain_handle = s.OpenDomain(h,
761 security.SEC_FLAG_MAXIMUM_ALLOWED,
762 c.domain_sid)
763 return True
766 SAMR_QUERY_DOMAIN_INFO_LEVELS = [8, 12]
769 def packet_samr_8(packet, conversation, context):
770 # QueryDomainInfo [228]
771 c = context.get_samr_context()
772 s = c.get_connection()
773 if c.domain_handle is None:
774 packet_samr_7(packet, conversation, context)
775 level = random.choice(SAMR_QUERY_DOMAIN_INFO_LEVELS)
776 s.QueryDomainInfo(c.domain_handle, level)
777 return True
780 packet_samr_14 = null_packet
781 # CreateDomainAlias
782 # Ignore these for now.
785 def packet_samr_15(packet, conversation, context):
786 # EnumDomainAliases
787 c = context.get_samr_context()
788 s = c.get_connection()
789 if c.domain_handle is None:
790 packet_samr_7(packet, conversation, context)
792 s.EnumDomainAliases(c.domain_handle, 100, 0)
793 return True
796 def packet_samr_16(packet, conversation, context):
797 # GetAliasMembership
798 c = context.get_samr_context()
799 s = c.get_connection()
800 if c.domain_handle is None:
801 packet_samr_7(packet, conversation, context)
803 sids = lsa.SidArray()
804 sid = lsa.SidPtr()
805 sid.sid = c.domain_sid
806 sids.sids = [sid]
807 s.GetAliasMembership(c.domain_handle, sids)
808 return True
811 def packet_samr_17(packet, conversation, context):
812 # LookupNames
813 c = context.get_samr_context()
814 s = c.get_connection()
815 if c.domain_handle is None:
816 packet_samr_7(packet, conversation, context)
818 name = lsa.String(context.username)
819 c.rids = s.LookupNames(c.domain_handle, [name])
820 return True
823 def packet_samr_18(packet, conversation, context):
824 # LookupRids
825 c = context.get_samr_context()
826 s = c.get_connection()
827 if c.rids is None:
828 packet_samr_17(packet, conversation, context)
829 rids = []
830 for r in c.rids:
831 for i in r.ids:
832 rids.append(i)
833 s.LookupRids(c.domain_handle, rids)
834 return True
837 def packet_samr_19(packet, conversation, context):
838 # OpenGroup
839 c = context.get_samr_context()
840 s = c.get_connection()
841 if c.domain_handle is None:
842 packet_samr_7(packet, conversation, context)
844 rid = 0x202 # Users I think.
845 c.group_handle = s.OpenGroup(c.domain_handle,
846 security.SEC_FLAG_MAXIMUM_ALLOWED,
847 rid)
848 return True
851 def packet_samr_25(packet, conversation, context):
852 # QueryGroupMember
853 c = context.get_samr_context()
854 s = c.get_connection()
855 if c.group_handle is None:
856 packet_samr_19(packet, conversation, context)
857 s.QueryGroupMember(c.group_handle)
858 return True
861 def packet_samr_34(packet, conversation, context):
862 # OpenUser
863 c = context.get_samr_context()
864 s = c.get_connection()
865 if c.rids is None:
866 packet_samr_17(packet, conversation, context)
867 c.user_handle = s.OpenUser(c.domain_handle,
868 security.SEC_FLAG_MAXIMUM_ALLOWED,
869 c.rids[0].ids[0])
870 return True
873 def packet_samr_36(packet, conversation, context):
874 # QueryUserInfo
875 c = context.get_samr_context()
876 s = c.get_connection()
877 if c.user_handle is None:
878 packet_samr_34(packet, conversation, context)
879 level = 1
880 s.QueryUserInfo(c.user_handle, level)
881 return True
884 packet_samr_37 = null_packet
887 def packet_samr_39(packet, conversation, context):
888 # GetGroupsForUser
889 c = context.get_samr_context()
890 s = c.get_connection()
891 if c.user_handle is None:
892 packet_samr_34(packet, conversation, context)
893 s.GetGroupsForUser(c.user_handle)
894 return True
897 packet_samr_40 = null_packet
899 packet_samr_44 = null_packet
902 def packet_samr_57(packet, conversation, context):
903 # Connect2
904 c = context.get_samr_context()
905 c.get_handle()
906 return True
909 def packet_samr_64(packet, conversation, context):
910 # Connect5
911 c = context.get_samr_context()
912 c.get_handle()
913 return True
916 packet_samr_68 = null_packet
919 def packet_srvsvc_16(packet, conversation, context):
920 # NetShareGetInfo
921 s = context.get_srvsvc_connection()
922 server_unc = "\\\\" + context.server
923 share_name = "netlogon"
924 level = 1
925 s.NetShareGetInfo(server_unc, share_name, level)
926 return True
929 def packet_srvsvc_21(packet, conversation, context):
930 # NetSrvGetInfo
931 srvsvc = context.get_srvsvc_connection()
932 server_unc = "\\\\" + context.server
933 level = 102
934 srvsvc.NetSrvGetInfo(server_unc, level)
935 return True