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/>.
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 (
33 from samba import NTSTATUSError
34 from samba.ntstatus import (
35 NT_STATUS_OBJECT_NAME_NOT_FOUND,
36 NT_STATUS_NO_SUCH_DOMAIN
39 samba.ensure_third_party_module("dns", "dnspython")
44 return ctypes.c_uint32(v).value
47 def check_runtime_error(runtime, val):
51 err32 = uint32(runtime.args[0])
59 drsuapi.DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
60 drsuapi.DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
61 drsuapi.DRSUAPI_DS_NAME_FORMAT_DISPLAY,
62 drsuapi.DRSUAPI_DS_NAME_FORMAT_GUID,
63 drsuapi.DRSUAPI_DS_NAME_FORMAT_CANONICAL,
64 drsuapi.DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
65 drsuapi.DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX,
66 drsuapi.DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
67 drsuapi.DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
68 drsuapi.DRSUAPI_DS_NAME_FORMAT_DNS_DOMAIN,
69 drsuapi.DRSUAPI_DS_NAME_FORMAT_UPN_AND_ALTSECID,
70 drsuapi.DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT_NAME_SANS_DOMAIN_EX,
71 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_GLOBAL_CATALOG_SERVERS,
72 drsuapi.DRSUAPI_DS_NAME_FORMAT_UPN_FOR_LOGON,
73 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_WITH_DCS_IN_SITE,
74 drsuapi.DRSUAPI_DS_NAME_FORMAT_STRING_SID_NAME,
75 drsuapi.DRSUAPI_DS_NAME_FORMAT_ALT_SECURITY_IDENTITIES_NAME,
76 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_NCS,
77 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_DOMAINS,
78 drsuapi.DRSUAPI_DS_NAME_FORMAT_MAP_SCHEMA_GUID,
79 drsuapi.DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT_NAME_SANS_DOMAIN,
80 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_ROLES,
81 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_INFO_FOR_SERVER,
82 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_FOR_DOMAIN_IN_SITE,
83 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_DOMAINS_IN_SITE,
84 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_IN_SITE,
85 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_SITES,
90 print("\033[37;41;1m" "Warning: %s" "\033[00m" % (message))
92 ###############################################################################
94 # Packet generation functions:
96 # All the packet generation functions have the following form:
97 # packet_${protocol}_${opcode}(packet, conversation, context)
99 # The functions return true, if statistics should be collected for the packet
100 # false, the packet has been ignored.
103 # protocol is the protocol, i.e. cldap, dcerpc, ...
104 # opcode is the protocol op code i.e. type of the packet to be
107 # packet contains data about the captured/generated packet
108 # provides any extra data needed to generate the packet
110 # conversation Details of the current client/server interaction
112 # context state data for the current interaction
116 # The following protocols are not currently handled:
122 # The following drsuapi replication packets are currently ignored:
125 # DsReplicaUpdateRefs
128 # Packet generators that do NOTHING are assigned to the null_packet
129 # function which allows the conversation generators to notice this and
130 # avoid a whole lot of pointless work.
131 def null_packet(packet, conversation, context):
135 def packet_cldap_3(packet, conversation, context):
137 net = Net(creds=context.creds, lp=context.lp)
138 net.finddc(domain=context.lp.get('realm'),
139 flags=(nbt.NBT_SERVER_LDAP |
141 nbt.NBT_SERVER_WRITABLE))
145 packet_cldap_5 = null_packet
148 packet_dcerpc_0 = null_packet
150 # Can be ignored, it's the continuation of an existing conversation
152 packet_dcerpc_2 = null_packet
154 # Server response, so should be ignored
156 packet_dcerpc_3 = null_packet
158 packet_dcerpc_11 = null_packet
160 # creation of the rpc dcerpc connection is managed by the higher level
161 # protocol drivers. So we ignore it when generating traffic
164 packet_dcerpc_12 = null_packet
166 # Server response, so should be ignored
169 packet_dcerpc_13 = null_packet
171 # Server response, so should be ignored
174 packet_dcerpc_14 = null_packet
176 # Generated as part of the connect process
179 def packet_dcerpc_15(packet, conversation, context):
181 # This means it was GSSAPI/krb5 (probably)
182 # Check the kerberos_state and issue a diagnostic if kerberos not enabled
183 if context.user_creds.get_kerberos_state() == DONT_USE_KERBEROS:
184 warning("Kerberos disabled but have dcerpc Alter_context_resp "
185 "indicating Kerberos was used")
189 def packet_dcerpc_16(packet, conversation, context):
191 # This means it was NTLMSSP
192 # Check the kerberos_state and issue a diagnostic if kerberos enabled
193 if context.user_creds.get_kerberos_state() == MUST_USE_KERBEROS:
194 warning("Kerberos enabled but have dcerpc AUTH3 "
195 "indicating NTLMSSP was used")
199 def packet_dns_0(packet, conversation, context):
201 name, rtype = context.guess_a_dns_lookup()
202 dns.resolver.query(name, rtype)
206 packet_dns_1 = null_packet
208 # Server response, so should be ignored
211 def packet_drsuapi_0(packet, conversation, context):
213 context.get_drsuapi_connection_pair(True)
217 NAME_FORMATS = [getattr(drsuapi, _x) for _x in dir(drsuapi)
218 if 'NAME_FORMAT' in _x]
221 def packet_drsuapi_12(packet, conversation, context):
223 drs, handle = context.get_drsuapi_connection_pair()
225 names = drsuapi.DsNameString()
226 names.str = context.server
228 req = drsuapi.DsNameRequest1()
230 req.format_offered = 7
231 req.format_desired = random.choice(name_formats)
233 req.language = 1033 # German, I think
238 (result, ctr) = drs.DsCrackNames(handle, 1, req)
242 def packet_drsuapi_13(packet, conversation, context):
244 req = drsuapi.DsWriteAccountSpnRequest1()
245 req.operation = drsuapi.DRSUAPI_DS_SPN_OPERATION_REPLACE
246 req.unknown1 = 0 # Unused, must be 0
247 req.object_dn = context.user_dn
248 req.count = 1 # only 1 name
249 spn_name = drsuapi.DsNameString()
250 spn_name.str = 'foo/{}'.format(context.username)
251 req.spn_names = [spn_name]
252 (drs, handle) = context.get_drsuapi_connection_pair()
253 (level, res) = drs.DsWriteAccountSpn(handle, 1, req)
257 def packet_drsuapi_1(packet, conversation, context):
259 (drs, handle) = context.get_drsuapi_connection_pair()
261 del context.drsuapi_connections[-1]
265 packet_drsuapi_2 = null_packet
267 # This is between DCs, triggered on a DB change
271 packet_drsuapi_3 = null_packet
273 # This is between DCs, trigger with DB operation,
274 # or DsReplicaSync between DCs.
278 packet_drsuapi_4 = null_packet
279 # DsReplicaUpdateRefs
283 packet_epm_3 = null_packet
285 # Will be generated by higher level protocol calls
288 def packet_kerberos_(packet, conversation, context):
289 # Use the presence of kerberos packets as a hint to enable kerberos
290 # for the rest of the conversation.
291 # i.e. kerberos packets are not explicitly generated.
292 context.user_creds.set_kerberos_state(MUST_USE_KERBEROS)
293 context.user_creds_bad.set_kerberos_state(MUST_USE_KERBEROS)
294 context.machine_creds.set_kerberos_state(MUST_USE_KERBEROS)
295 context.machine_creds_bad.set_kerberos_state(MUST_USE_KERBEROS)
296 context.creds.set_kerberos_state(MUST_USE_KERBEROS)
300 packet_ldap_ = null_packet
302 # The ldap payload was probably encrypted so just ignore it.
305 def packet_ldap_0(packet, conversation, context):
307 if packet.extra[5] == "simple":
308 # Perform a simple bind.
309 context.get_ldap_connection(new=True, simple=True)
311 # Perform a sasl bind.
312 context.get_ldap_connection(new=True, simple=False)
316 packet_ldap_1 = null_packet
318 # Server response ignored for traffic generation
321 def packet_ldap_2(packet, conversation, context):
323 # pop the last one off -- most likely we're in a bind/unbind ping.
324 del context.ldap_connections[-1:]
328 def packet_ldap_3(packet, conversation, context):
331 (scope, dn_sig, filter, attrs, extra, desc, oid) = packet.extra
335 samdb = context.get_ldap_connection()
336 dn = context.get_matching_dn(dn_sig)
340 attrs=attrs.split(','),
341 controls=["paged_results:1:1000"])
345 packet_ldap_4 = null_packet
347 # Server response ignored for traffic generation
350 packet_ldap_5 = null_packet
351 # Server response ignored for traffic generation
353 packet_ldap_6 = null_packet
355 packet_ldap_7 = null_packet
357 packet_ldap_8 = null_packet
359 packet_ldap_9 = null_packet
361 packet_ldap_16 = null_packet
363 packet_lsarpc_0 = null_packet
366 packet_lsarpc_1 = null_packet
369 packet_lsarpc_2 = null_packet
370 # lsarEnumeratePrivileges
372 packet_lsarpc_3 = null_packet
373 # LsarQuerySecurityObject
375 packet_lsarpc_4 = null_packet
376 # LsarSetSecurityObject
378 packet_lsarpc_5 = null_packet
381 packet_lsarpc_6 = null_packet
383 # We ignore this, but take it as a hint that the lsarpc handle should
384 # be over a named pipe.
388 def packet_lsarpc_14(packet, conversation, context):
390 c = context.get_lsarpc_named_pipe_connection()
392 objectAttr = lsa.ObjectAttribute()
393 pol_handle = c.OpenPolicy2(u'', objectAttr,
394 security.SEC_FLAG_MAXIMUM_ALLOWED)
396 sids = lsa.TransSidArray()
397 names = [lsa.String("This Organization"),
398 lsa.String("Digest Authentication")]
399 level = lsa.LSA_LOOKUP_NAMES_ALL
401 c.LookupNames(pol_handle, names, sids, level, count)
405 def packet_lsarpc_15(packet, conversation, context):
407 c = context.get_lsarpc_named_pipe_connection()
409 objectAttr = lsa.ObjectAttribute()
410 pol_handle = c.OpenPolicy2(u'', objectAttr,
411 security.SEC_FLAG_MAXIMUM_ALLOWED)
413 sids = lsa.SidArray()
416 x = dom_sid("S-1-5-7")
420 names = lsa.TransNameArray()
421 level = lsa.LSA_LOOKUP_NAMES_ALL
424 c.LookupSids(pol_handle, sids, names, level, count)
428 def packet_lsarpc_39(packet, conversation, context):
429 # lsa_QueryTrustedDomainInfoBySid
430 # Samba does not support trusted domains, so this call is expected to fail
432 c = context.get_lsarpc_named_pipe_connection()
434 objectAttr = lsa.ObjectAttribute()
436 pol_handle = c.OpenPolicy2(u'', objectAttr,
437 security.SEC_FLAG_MAXIMUM_ALLOWED)
439 domsid = security.dom_sid(context.domain_sid)
442 c.QueryTrustedDomainInfoBySid(pol_handle, domsid, level)
443 except NTSTATUSError as error:
444 # Object Not found is the expected result from samba,
445 # while No Such Domain is the expected result from windows,
446 # anything else is a failure.
447 if not check_runtime_error(error, NT_STATUS_OBJECT_NAME_NOT_FOUND) \
448 and not check_runtime_error(error, NT_STATUS_NO_SUCH_DOMAIN):
453 packet_lsarpc_40 = null_packet
454 # lsa_SetTrustedDomainInfo
455 # Not currently supported
458 packet_lsarpc_43 = null_packet
459 # LsaStorePrivateData
462 packet_lsarpc_44 = null_packet
463 # LsaRetrievePrivateData
466 packet_lsarpc_68 = null_packet
470 def packet_lsarpc_76(packet, conversation, context):
472 c = context.get_lsarpc_connection()
473 sids = lsa.SidArray()
476 x = dom_sid("S-1-5-7")
480 names = lsa.TransNameArray2()
481 level = lsa.LSA_LOOKUP_NAMES_ALL
483 lookup_options = lsa.LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES
484 client_revision = lsa.LSA_CLIENT_REVISION_2
485 c.LookupSids3(sids, names, level, count, lookup_options, client_revision)
489 def packet_lsarpc_77(packet, conversation, context):
491 c = context.get_lsarpc_connection()
492 sids = lsa.TransSidArray3()
493 names = [lsa.String("This Organization"),
494 lsa.String("Digest Authentication")]
495 level = lsa.LSA_LOOKUP_NAMES_ALL
497 lookup_options = lsa.LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES
498 client_revision = lsa.LSA_CLIENT_REVISION_2
499 c.LookupNames4(names, sids, level, count, lookup_options, client_revision)
503 def packet_nbns_0(packet, conversation, context):
507 n.query_name("ANAME", context.server, timeout=4, broadcast=False)
513 packet_nbns_1 = null_packet
515 # Server response, not generated by the client
518 packet_rpc_netlogon_0 = null_packet
520 packet_rpc_netlogon_1 = null_packet
522 packet_rpc_netlogon_4 = null_packet
523 # NetrServerReqChallenge
524 # generated by higher level protocol drivers
525 # ignored for traffic generation
527 packet_rpc_netlogon_14 = null_packet
529 packet_rpc_netlogon_15 = null_packet
531 packet_rpc_netlogon_21 = null_packet
532 # NetrLogonDummyRoutine1
533 # Used to determine security settings. Triggered from schannel setup
534 # So no need for an explicit generator
537 packet_rpc_netlogon_26 = null_packet
538 # NetrServerAuthenticate3
539 # Triggered from schannel set up, no need for an explicit generator
542 def packet_rpc_netlogon_29(packet, conversation, context):
543 # NetrLogonGetDomainInfo [531]
544 c = context.get_netlogon_connection()
545 (auth, succ) = context.get_authenticator()
546 query = netr_WorkstationInformation()
548 c.netr_LogonGetDomainInfo(context.server,
549 context.netbios_name,
552 2, # TODO are there other values?
557 def packet_rpc_netlogon_30(packet, conversation, context):
558 # NetrServerPasswordSet2
559 c = context.get_netlogon_connection()
560 (auth, succ) = context.get_authenticator()
562 # Set the new password to the existing password, this generates the same
563 # work load as a new value, and leaves the account password intact for
565 newpass = context.machine_creds.get_password().encode('utf-16-le')
566 pwd_len = len(newpass)
567 filler = [x if isinstance(x, int) else ord(x) for x in os.urandom(DATA_LEN - pwd_len)]
568 pwd = netlogon.netr_CryptPassword()
570 pwd.data = filler + [x if isinstance(x, int) else ord(x) for x in newpass]
571 context.machine_creds.encrypt_netr_crypt_password(pwd)
572 c.netr_ServerPasswordSet2(context.server,
573 # must ends with $, so use get_username instead
574 # of get_workstation here
575 context.machine_creds.get_username(),
576 context.machine_creds.get_secure_channel_type(),
577 context.netbios_name,
583 packet_rpc_netlogon_34 = null_packet
586 def packet_rpc_netlogon_39(packet, conversation, context):
587 # NetrLogonSamLogonEx [4331]
589 c = context.get_netlogon_connection()
591 # Disable Kerberos in cli creds to extract NTLM response
592 old_state = creds.get_kerberos_state()
593 creds.set_kerberos_state(DONT_USE_KERBEROS)
595 logon = samlogon_logon_info(context.domain,
596 context.netbios_name,
598 logon_level = netlogon.NetlogonNetworkTransitiveInformation
599 validation_level = netlogon.NetlogonValidationSamInfo4
601 c.netr_LogonSamLogonEx(context.server,
602 context.machine_creds.get_workstation(),
608 creds.set_kerberos_state(old_state)
610 context.last_samlogon_bad =\
611 context.with_random_bad_credentials(connect,
613 context.user_creds_bad,
614 context.last_samlogon_bad)
618 def samlogon_target(domain_name, computer_name):
619 target_info = ntlmssp.AV_PAIR_LIST()
620 target_info.count = 3
621 computername = ntlmssp.AV_PAIR()
622 computername.AvId = ntlmssp.MsvAvNbComputerName
623 computername.Value = computer_name
625 domainname = ntlmssp.AV_PAIR()
626 domainname.AvId = ntlmssp.MsvAvNbDomainName
627 domainname.Value = domain_name
629 eol = ntlmssp.AV_PAIR()
630 eol.AvId = ntlmssp.MsvAvEOL
631 target_info.pair = [domainname, computername, eol]
633 return ndr_pack(target_info)
636 def samlogon_logon_info(domain_name, computer_name, creds):
638 target_info_blob = samlogon_target(domain_name, computer_name)
640 challenge = b"abcdefgh"
641 # User account under test
642 response = creds.get_ntlm_response(flags=CLI_CRED_NTLMv2_AUTH,
644 target_info=target_info_blob)
646 logon = netlogon.netr_NetworkInfo()
648 logon.challenge = [x if isinstance(x, int) else ord(x) for x in challenge]
649 logon.nt = netlogon.netr_ChallengeResponse()
650 logon.nt.length = len(response["nt_response"])
651 logon.nt.data = [x if isinstance(x, int) else ord(x) for x in response["nt_response"]]
653 logon.identity_info = netlogon.netr_IdentityInfo()
655 (username, domain) = creds.get_ntlm_username_domain()
656 logon.identity_info.domain_name.string = domain
657 logon.identity_info.account_name.string = username
658 logon.identity_info.workstation.string = creds.get_workstation()
663 def packet_rpc_netlogon_40(packet, conversation, context):
664 # DsrEnumerateDomainTrusts
665 c = context.get_netlogon_connection()
666 c.netr_DsrEnumerateDomainTrusts(
668 netlogon.NETR_TRUST_FLAG_IN_FOREST |
669 netlogon.NETR_TRUST_FLAG_OUTBOUND |
670 netlogon.NETR_TRUST_FLAG_INBOUND)
674 def packet_rpc_netlogon_45(packet, conversation, context):
675 # NetrLogonSamLogonWithFlags [7]
677 c = context.get_netlogon_connection()
678 (auth, succ) = context.get_authenticator()
680 # Disable Kerberos in cli creds to extract NTLM response
681 old_state = creds.get_kerberos_state()
682 creds.set_kerberos_state(DONT_USE_KERBEROS)
684 logon = samlogon_logon_info(context.domain,
685 context.netbios_name,
687 logon_level = netlogon.NetlogonNetworkTransitiveInformation
688 validation_level = netlogon.NetlogonValidationSamInfo4
690 c.netr_LogonSamLogonWithFlags(context.server,
691 context.machine_creds.get_workstation(),
699 creds.set_kerberos_state(old_state)
701 context.last_samlogon_bad =\
702 context.with_random_bad_credentials(connect,
704 context.user_creds_bad,
705 context.last_samlogon_bad)
709 def packet_samr_0(packet, conversation, context):
711 c = context.get_samr_context()
716 def packet_samr_1(packet, conversation, context):
718 c = context.get_samr_context()
719 s = c.get_connection()
720 # close the last opened handle, may not always be accurate
721 # but will do for load simulation
722 if c.user_handle is not None:
723 s.Close(c.user_handle)
725 elif c.group_handle is not None:
726 s.Close(c.group_handle)
727 c.group_handle = None
728 elif c.domain_handle is not None:
729 s.Close(c.domain_handle)
730 c.domain_handle = None
732 elif c.handle is not None:
739 def packet_samr_3(packet, conversation, context):
741 c = context.get_samr_context()
742 s = c.get_connection()
743 if c.user_handle is None:
744 packet_samr_34(packet, conversation, context)
745 s.QuerySecurity(c.user_handle, 1)
749 def packet_samr_5(packet, conversation, context):
751 c = context.get_samr_context()
752 s = c.get_connection()
755 d.string = context.domain
756 c.domain_sid = s.LookupDomain(h, d)
760 def packet_samr_6(packet, conversation, context):
762 c = context.get_samr_context()
763 s = c.get_connection()
765 s.EnumDomains(h, 0, 0)
769 def packet_samr_7(packet, conversation, context):
771 c = context.get_samr_context()
772 s = c.get_connection()
774 if c.domain_sid is None:
775 packet_samr_5(packet, conversation, context)
777 c.domain_handle = s.OpenDomain(h,
778 security.SEC_FLAG_MAXIMUM_ALLOWED,
783 SAMR_QUERY_DOMAIN_INFO_LEVELS = [8, 12]
786 def packet_samr_8(packet, conversation, context):
787 # QueryDomainInfo [228]
788 c = context.get_samr_context()
789 s = c.get_connection()
790 if c.domain_handle is None:
791 packet_samr_7(packet, conversation, context)
792 level = random.choice(SAMR_QUERY_DOMAIN_INFO_LEVELS)
793 s.QueryDomainInfo(c.domain_handle, level)
797 packet_samr_14 = null_packet
799 # Ignore these for now.
802 def packet_samr_15(packet, conversation, context):
804 c = context.get_samr_context()
805 s = c.get_connection()
806 if c.domain_handle is None:
807 packet_samr_7(packet, conversation, context)
809 s.EnumDomainAliases(c.domain_handle, 100, 0)
813 def packet_samr_16(packet, conversation, context):
815 c = context.get_samr_context()
816 s = c.get_connection()
817 if c.domain_handle is None:
818 packet_samr_7(packet, conversation, context)
820 sids = lsa.SidArray()
822 sid.sid = c.domain_sid
824 s.GetAliasMembership(c.domain_handle, sids)
828 def packet_samr_17(packet, conversation, context):
830 c = context.get_samr_context()
831 s = c.get_connection()
832 if c.domain_handle is None:
833 packet_samr_7(packet, conversation, context)
835 name = lsa.String(context.username)
836 c.rids = s.LookupNames(c.domain_handle, [name])
840 def packet_samr_18(packet, conversation, context):
842 c = context.get_samr_context()
843 s = c.get_connection()
845 packet_samr_17(packet, conversation, context)
850 s.LookupRids(c.domain_handle, rids)
854 def packet_samr_19(packet, conversation, context):
856 c = context.get_samr_context()
857 s = c.get_connection()
858 if c.domain_handle is None:
859 packet_samr_7(packet, conversation, context)
861 rid = 0x202 # Users I think.
862 c.group_handle = s.OpenGroup(c.domain_handle,
863 security.SEC_FLAG_MAXIMUM_ALLOWED,
868 def packet_samr_25(packet, conversation, context):
870 c = context.get_samr_context()
871 s = c.get_connection()
872 if c.group_handle is None:
873 packet_samr_19(packet, conversation, context)
874 s.QueryGroupMember(c.group_handle)
878 def packet_samr_34(packet, conversation, context):
880 c = context.get_samr_context()
881 s = c.get_connection()
883 packet_samr_17(packet, conversation, context)
884 c.user_handle = s.OpenUser(c.domain_handle,
885 security.SEC_FLAG_MAXIMUM_ALLOWED,
890 def packet_samr_36(packet, conversation, context):
892 c = context.get_samr_context()
893 s = c.get_connection()
894 if c.user_handle is None:
895 packet_samr_34(packet, conversation, context)
897 s.QueryUserInfo(c.user_handle, level)
901 packet_samr_37 = null_packet
904 def packet_samr_39(packet, conversation, context):
906 c = context.get_samr_context()
907 s = c.get_connection()
908 if c.user_handle is None:
909 packet_samr_34(packet, conversation, context)
910 s.GetGroupsForUser(c.user_handle)
914 packet_samr_40 = null_packet
916 packet_samr_44 = null_packet
919 def packet_samr_57(packet, conversation, context):
921 c = context.get_samr_context()
926 def packet_samr_64(packet, conversation, context):
928 c = context.get_samr_context()
933 packet_samr_68 = null_packet
936 def packet_srvsvc_16(packet, conversation, context):
938 s = context.get_srvsvc_connection()
939 server_unc = "\\\\" + context.server
942 s.NetShareGetInfo(server_unc, share_name, level)
946 def packet_srvsvc_21(packet, conversation, context):
949 FIXME: Level changed from 102 to 101 here, to bypass Windows error.
951 Level 102 will cause WERR_ACCESS_DENIED error against Windows, because:
953 > If the level is 102 or 502, the Windows implementation checks whether
954 > the caller is a member of one of the groups previously mentioned or
955 > is a member of the Power Users local group.
957 It passed against Samba since this check is not implemented by Samba yet.
961 https://msdn.microsoft.com/en-us/library/cc247297.aspx#Appendix_A_80
964 srvsvc = context.get_srvsvc_connection()
965 server_unc = "\\\\" + context.server
967 srvsvc.NetSrvGetInfo(server_unc, level)