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
40 from ldb import SCOPE_BASE
43 return ctypes.c_uint32(v).value
46 def check_runtime_error(runtime, val):
50 err32 = uint32(runtime.args[0])
58 drsuapi.DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
59 drsuapi.DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
60 drsuapi.DRSUAPI_DS_NAME_FORMAT_DISPLAY,
61 drsuapi.DRSUAPI_DS_NAME_FORMAT_GUID,
62 drsuapi.DRSUAPI_DS_NAME_FORMAT_CANONICAL,
63 drsuapi.DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
64 drsuapi.DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX,
65 drsuapi.DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
66 drsuapi.DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
67 drsuapi.DRSUAPI_DS_NAME_FORMAT_DNS_DOMAIN,
68 drsuapi.DRSUAPI_DS_NAME_FORMAT_UPN_AND_ALTSECID,
69 drsuapi.DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT_NAME_SANS_DOMAIN_EX,
70 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_GLOBAL_CATALOG_SERVERS,
71 drsuapi.DRSUAPI_DS_NAME_FORMAT_UPN_FOR_LOGON,
72 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_WITH_DCS_IN_SITE,
73 drsuapi.DRSUAPI_DS_NAME_FORMAT_STRING_SID_NAME,
74 drsuapi.DRSUAPI_DS_NAME_FORMAT_ALT_SECURITY_IDENTITIES_NAME,
75 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_NCS,
76 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_DOMAINS,
77 drsuapi.DRSUAPI_DS_NAME_FORMAT_MAP_SCHEMA_GUID,
78 drsuapi.DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT_NAME_SANS_DOMAIN,
79 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_ROLES,
80 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_INFO_FOR_SERVER,
81 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_FOR_DOMAIN_IN_SITE,
82 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_DOMAINS_IN_SITE,
83 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_IN_SITE,
84 drsuapi.DRSUAPI_DS_NAME_FORMAT_LIST_SITES,
89 print("\033[37;41;1m" "Warning: %s" "\033[00m" % (message))
91 ###############################################################################
93 # Packet generation functions:
95 # All the packet generation functions have the following form:
96 # packet_${protocol}_${opcode}(packet, conversation, context)
98 # The functions return true, if statistics should be collected for the packet
99 # false, the packet has been ignored.
102 # protocol is the protocol, i.e. cldap, dcerpc, ...
103 # opcode is the protocol op code i.e. type of the packet to be
106 # packet contains data about the captured/generated packet
107 # provides any extra data needed to generate the packet
109 # conversation Details of the current client/server interaction
111 # context state data for the current interaction
115 # The following protocols are not currently handled:
121 # The following drsuapi replication packets are currently ignored:
124 # DsReplicaUpdateRefs
127 # Packet generators that do NOTHING are assigned to the null_packet
128 # function which allows the conversation generators to notice this and
129 # avoid a whole lot of pointless work.
130 def null_packet(packet, conversation, context):
134 def packet_cldap_3(packet, conversation, context):
136 net = Net(creds=context.creds, lp=context.lp)
137 net.finddc(domain=context.lp.get('realm'),
138 flags=(nbt.NBT_SERVER_LDAP |
140 nbt.NBT_SERVER_WRITABLE))
144 packet_cldap_5 = null_packet
147 packet_dcerpc_0 = null_packet
149 # Can be ignored, it's the continuation of an existing conversation
151 packet_dcerpc_2 = null_packet
153 # Server response, so should be ignored
155 packet_dcerpc_3 = null_packet
157 packet_dcerpc_11 = null_packet
159 # creation of the rpc dcerpc connection is managed by the higher level
160 # protocol drivers. So we ignore it when generating traffic
163 packet_dcerpc_12 = null_packet
165 # Server response, so should be ignored
168 packet_dcerpc_13 = null_packet
170 # Server response, so should be ignored
173 packet_dcerpc_14 = null_packet
175 # Generated as part of the connect process
178 def packet_dcerpc_15(packet, conversation, context):
180 # This means it was GSSAPI/krb5 (probably)
181 # Check the kerberos_state and issue a diagnostic if kerberos not enabled
182 if context.user_creds.get_kerberos_state() == DONT_USE_KERBEROS:
183 warning("Kerberos disabled but have dcerpc Alter_context_resp "
184 "indicating Kerberos was used")
188 def packet_dcerpc_16(packet, conversation, context):
190 # This means it was NTLMSSP
191 # Check the kerberos_state and issue a diagnostic if kerberos enabled
192 if context.user_creds.get_kerberos_state() == MUST_USE_KERBEROS:
193 warning("Kerberos enabled but have dcerpc AUTH3 "
194 "indicating NTLMSSP was used")
198 def packet_dns_0(packet, conversation, context):
200 name, rtype = context.guess_a_dns_lookup()
201 dns.resolver.query(name, rtype)
205 packet_dns_1 = null_packet
207 # Server response, so should be ignored
210 def packet_drsuapi_0(packet, conversation, context):
212 context.get_drsuapi_connection_pair(True)
216 NAME_FORMATS = [getattr(drsuapi, _x) for _x in dir(drsuapi)
217 if 'NAME_FORMAT' in _x]
220 def packet_drsuapi_12(packet, conversation, context):
222 drs, handle = context.get_drsuapi_connection_pair()
224 names = drsuapi.DsNameString()
225 names.str = context.server
227 req = drsuapi.DsNameRequest1()
229 req.format_offered = 7
230 req.format_desired = random.choice(name_formats)
232 req.language = 1033 # German, I think
237 (result, ctr) = drs.DsCrackNames(handle, 1, req)
241 def packet_drsuapi_13(packet, conversation, context):
243 req = drsuapi.DsWriteAccountSpnRequest1()
244 req.operation = drsuapi.DRSUAPI_DS_SPN_OPERATION_REPLACE
245 req.unknown1 = 0 # Unused, must be 0
246 req.object_dn = context.user_dn
247 req.count = 1 # only 1 name
248 spn_name = drsuapi.DsNameString()
249 spn_name.str = 'foo/{}'.format(context.username)
250 req.spn_names = [spn_name]
251 (drs, handle) = context.get_drsuapi_connection_pair()
252 (level, res) = drs.DsWriteAccountSpn(handle, 1, req)
256 def packet_drsuapi_1(packet, conversation, context):
258 (drs, handle) = context.get_drsuapi_connection_pair()
260 del context.drsuapi_connections[-1]
264 packet_drsuapi_2 = null_packet
266 # This is between DCs, triggered on a DB change
270 packet_drsuapi_3 = null_packet
272 # This is between DCs, trigger with DB operation,
273 # or DsReplicaSync between DCs.
277 packet_drsuapi_4 = null_packet
278 # DsReplicaUpdateRefs
282 packet_epm_3 = null_packet
284 # Will be generated by higher level protocol calls
287 def packet_kerberos_(packet, conversation, context):
288 # Use the presence of kerberos packets as a hint to enable kerberos
289 # for the rest of the conversation.
290 # i.e. kerberos packets are not explicitly generated.
291 context.user_creds.set_kerberos_state(MUST_USE_KERBEROS)
292 context.user_creds_bad.set_kerberos_state(MUST_USE_KERBEROS)
293 context.machine_creds.set_kerberos_state(MUST_USE_KERBEROS)
294 context.machine_creds_bad.set_kerberos_state(MUST_USE_KERBEROS)
295 context.creds.set_kerberos_state(MUST_USE_KERBEROS)
299 packet_ldap_ = null_packet
301 # The ldap payload was probably encrypted so just ignore it.
304 def packet_ldap_0(packet, conversation, context):
306 if packet.extra[5] == "simple":
307 # Perform a simple bind.
308 context.get_ldap_connection(new=True, simple=True)
310 # Perform a sasl bind.
311 context.get_ldap_connection(new=True, simple=False)
315 packet_ldap_1 = null_packet
317 # Server response ignored for traffic generation
320 def packet_ldap_2(packet, conversation, context):
322 # pop the last one off -- most likely we're in a bind/unbind ping.
323 del context.ldap_connections[-1:]
327 def packet_ldap_3(packet, conversation, context):
330 (scope, dn_sig, filter, attrs, extra, desc, oid) = packet.extra
334 samdb = context.get_ldap_connection()
335 dn = context.get_matching_dn(dn_sig)
337 # try to guess the search expression (don't bother for base searches, as
338 # they're only looking up a single object)
339 if (filter is None or filter == '') and scope != SCOPE_BASE:
340 filter = context.guess_search_filter(attrs, dn_sig, dn)
345 attrs=attrs.split(','),
346 controls=["paged_results:1:1000"])
350 packet_ldap_4 = null_packet
352 # Server response ignored for traffic generation
355 packet_ldap_5 = null_packet
356 # Server response ignored for traffic generation
358 packet_ldap_6 = null_packet
360 packet_ldap_7 = null_packet
362 packet_ldap_8 = null_packet
364 packet_ldap_9 = null_packet
366 packet_ldap_16 = null_packet
368 packet_lsarpc_0 = null_packet
371 packet_lsarpc_1 = null_packet
374 packet_lsarpc_2 = null_packet
375 # lsarEnumeratePrivileges
377 packet_lsarpc_3 = null_packet
378 # LsarQuerySecurityObject
380 packet_lsarpc_4 = null_packet
381 # LsarSetSecurityObject
383 packet_lsarpc_5 = null_packet
386 packet_lsarpc_6 = null_packet
388 # We ignore this, but take it as a hint that the lsarpc handle should
389 # be over a named pipe.
393 def packet_lsarpc_14(packet, conversation, context):
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.TransSidArray()
402 names = [lsa.String("This Organization"),
403 lsa.String("Digest Authentication")]
404 level = lsa.LSA_LOOKUP_NAMES_ALL
406 c.LookupNames(pol_handle, names, sids, level, count)
410 def packet_lsarpc_15(packet, conversation, context):
412 c = context.get_lsarpc_named_pipe_connection()
414 objectAttr = lsa.ObjectAttribute()
415 pol_handle = c.OpenPolicy2(u'', objectAttr,
416 security.SEC_FLAG_MAXIMUM_ALLOWED)
418 sids = lsa.SidArray()
421 x = dom_sid("S-1-5-7")
425 names = lsa.TransNameArray()
426 level = lsa.LSA_LOOKUP_NAMES_ALL
429 c.LookupSids(pol_handle, sids, names, level, count)
433 def packet_lsarpc_39(packet, conversation, context):
434 # lsa_QueryTrustedDomainInfoBySid
435 # Samba does not support trusted domains, so this call is expected to fail
437 c = context.get_lsarpc_named_pipe_connection()
439 objectAttr = lsa.ObjectAttribute()
441 pol_handle = c.OpenPolicy2(u'', objectAttr,
442 security.SEC_FLAG_MAXIMUM_ALLOWED)
444 domsid = security.dom_sid(context.domain_sid)
447 c.QueryTrustedDomainInfoBySid(pol_handle, domsid, level)
448 except NTSTATUSError as error:
449 # Object Not found is the expected result from samba,
450 # while No Such Domain is the expected result from windows,
451 # anything else is a failure.
452 if not check_runtime_error(error, NT_STATUS_OBJECT_NAME_NOT_FOUND) \
453 and not check_runtime_error(error, NT_STATUS_NO_SUCH_DOMAIN):
458 packet_lsarpc_40 = null_packet
459 # lsa_SetTrustedDomainInfo
460 # Not currently supported
463 packet_lsarpc_43 = null_packet
464 # LsaStorePrivateData
467 packet_lsarpc_44 = null_packet
468 # LsaRetrievePrivateData
471 packet_lsarpc_68 = null_packet
475 def packet_lsarpc_76(packet, conversation, context):
477 c = context.get_lsarpc_connection()
478 sids = lsa.SidArray()
481 x = dom_sid("S-1-5-7")
485 names = lsa.TransNameArray2()
486 level = lsa.LSA_LOOKUP_NAMES_ALL
488 lookup_options = lsa.LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES
489 client_revision = lsa.LSA_CLIENT_REVISION_2
490 c.LookupSids3(sids, names, level, count, lookup_options, client_revision)
494 def packet_lsarpc_77(packet, conversation, context):
496 c = context.get_lsarpc_connection()
497 sids = lsa.TransSidArray3()
498 names = [lsa.String("This Organization"),
499 lsa.String("Digest Authentication")]
500 level = lsa.LSA_LOOKUP_NAMES_ALL
502 lookup_options = lsa.LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES
503 client_revision = lsa.LSA_CLIENT_REVISION_2
504 c.LookupNames4(names, sids, level, count, lookup_options, client_revision)
508 def packet_nbns_0(packet, conversation, context):
512 n.query_name("ANAME", context.server, timeout=4, broadcast=False)
518 packet_nbns_1 = null_packet
520 # Server response, not generated by the client
523 packet_rpc_netlogon_0 = null_packet
525 packet_rpc_netlogon_1 = null_packet
527 packet_rpc_netlogon_4 = null_packet
528 # NetrServerReqChallenge
529 # generated by higher level protocol drivers
530 # ignored for traffic generation
532 packet_rpc_netlogon_14 = null_packet
534 packet_rpc_netlogon_15 = null_packet
536 packet_rpc_netlogon_21 = null_packet
537 # NetrLogonDummyRoutine1
538 # Used to determine security settings. Triggered from schannel setup
539 # So no need for an explicit generator
542 packet_rpc_netlogon_26 = null_packet
543 # NetrServerAuthenticate3
544 # Triggered from schannel set up, no need for an explicit generator
547 def packet_rpc_netlogon_29(packet, conversation, context):
548 # NetrLogonGetDomainInfo [531]
549 c = context.get_netlogon_connection()
550 (auth, succ) = context.get_authenticator()
551 query = netr_WorkstationInformation()
553 c.netr_LogonGetDomainInfo(context.server,
554 context.netbios_name,
557 2, # TODO are there other values?
562 def packet_rpc_netlogon_30(packet, conversation, context):
563 # NetrServerPasswordSet2
564 c = context.get_netlogon_connection()
565 (auth, succ) = context.get_authenticator()
567 # Set the new password to the existing password, this generates the same
568 # work load as a new value, and leaves the account password intact for
570 newpass = context.machine_creds.get_password().encode('utf-16-le')
571 pwd_len = len(newpass)
572 filler = list(os.urandom(DATA_LEN - pwd_len))
573 pwd = netlogon.netr_CryptPassword()
575 pwd.data = filler + list(newpass)
576 context.machine_creds.encrypt_netr_crypt_password(pwd)
577 c.netr_ServerPasswordSet2(context.server,
578 # must ends with $, so use get_username instead
579 # of get_workstation here
580 context.machine_creds.get_username(),
581 context.machine_creds.get_secure_channel_type(),
582 context.netbios_name,
588 packet_rpc_netlogon_34 = null_packet
591 def packet_rpc_netlogon_39(packet, conversation, context):
592 # NetrLogonSamLogonEx [4331]
594 c = context.get_netlogon_connection()
596 # Disable Kerberos in cli creds to extract NTLM response
597 old_state = creds.get_kerberos_state()
598 creds.set_kerberos_state(DONT_USE_KERBEROS)
600 logon = samlogon_logon_info(context.domain,
601 context.netbios_name,
603 logon_level = netlogon.NetlogonNetworkTransitiveInformation
604 validation_level = netlogon.NetlogonValidationSamInfo4
606 c.netr_LogonSamLogonEx(context.server,
607 context.machine_creds.get_workstation(),
613 creds.set_kerberos_state(old_state)
615 context.last_samlogon_bad =\
616 context.with_random_bad_credentials(connect,
618 context.user_creds_bad,
619 context.last_samlogon_bad)
623 def samlogon_target(domain_name, computer_name):
624 target_info = ntlmssp.AV_PAIR_LIST()
625 target_info.count = 3
626 computername = ntlmssp.AV_PAIR()
627 computername.AvId = ntlmssp.MsvAvNbComputerName
628 computername.Value = computer_name
630 domainname = ntlmssp.AV_PAIR()
631 domainname.AvId = ntlmssp.MsvAvNbDomainName
632 domainname.Value = domain_name
634 eol = ntlmssp.AV_PAIR()
635 eol.AvId = ntlmssp.MsvAvEOL
636 target_info.pair = [domainname, computername, eol]
638 return ndr_pack(target_info)
641 def samlogon_logon_info(domain_name, computer_name, creds):
643 target_info_blob = samlogon_target(domain_name, computer_name)
645 challenge = b"abcdefgh"
646 # User account under test
647 response = creds.get_ntlm_response(flags=CLI_CRED_NTLMv2_AUTH,
649 target_info=target_info_blob)
651 logon = netlogon.netr_NetworkInfo()
653 logon.challenge = list(challenge)
654 logon.nt = netlogon.netr_ChallengeResponse()
655 logon.nt.length = len(response["nt_response"])
656 logon.nt.data = list(response["nt_response"])
658 logon.identity_info = netlogon.netr_IdentityInfo()
660 (username, domain) = creds.get_ntlm_username_domain()
661 logon.identity_info.domain_name.string = domain
662 logon.identity_info.account_name.string = username
663 logon.identity_info.workstation.string = creds.get_workstation()
668 def packet_rpc_netlogon_40(packet, conversation, context):
669 # DsrEnumerateDomainTrusts
670 c = context.get_netlogon_connection()
671 c.netr_DsrEnumerateDomainTrusts(
673 netlogon.NETR_TRUST_FLAG_IN_FOREST |
674 netlogon.NETR_TRUST_FLAG_OUTBOUND |
675 netlogon.NETR_TRUST_FLAG_INBOUND)
679 def packet_rpc_netlogon_45(packet, conversation, context):
680 # NetrLogonSamLogonWithFlags [7]
682 c = context.get_netlogon_connection()
683 (auth, succ) = context.get_authenticator()
685 # Disable Kerberos in cli creds to extract NTLM response
686 old_state = creds.get_kerberos_state()
687 creds.set_kerberos_state(DONT_USE_KERBEROS)
689 logon = samlogon_logon_info(context.domain,
690 context.netbios_name,
692 logon_level = netlogon.NetlogonNetworkTransitiveInformation
693 validation_level = netlogon.NetlogonValidationSamInfo4
695 c.netr_LogonSamLogonWithFlags(context.server,
696 context.machine_creds.get_workstation(),
704 creds.set_kerberos_state(old_state)
706 context.last_samlogon_bad =\
707 context.with_random_bad_credentials(connect,
709 context.user_creds_bad,
710 context.last_samlogon_bad)
714 def packet_samr_0(packet, conversation, context):
716 c = context.get_samr_context()
721 def packet_samr_1(packet, conversation, context):
723 c = context.get_samr_context()
724 s = c.get_connection()
725 # close the last opened handle, may not always be accurate
726 # but will do for load simulation
727 if c.user_handle is not None:
728 s.Close(c.user_handle)
730 elif c.group_handle is not None:
731 s.Close(c.group_handle)
732 c.group_handle = None
733 elif c.domain_handle is not None:
734 s.Close(c.domain_handle)
735 c.domain_handle = None
737 elif c.handle is not None:
744 def packet_samr_3(packet, conversation, context):
746 c = context.get_samr_context()
747 s = c.get_connection()
748 if c.user_handle is None:
749 packet_samr_34(packet, conversation, context)
750 s.QuerySecurity(c.user_handle, 1)
754 def packet_samr_5(packet, conversation, context):
756 c = context.get_samr_context()
757 s = c.get_connection()
760 d.string = context.domain
761 c.domain_sid = s.LookupDomain(h, d)
765 def packet_samr_6(packet, conversation, context):
767 c = context.get_samr_context()
768 s = c.get_connection()
770 s.EnumDomains(h, 0, 0)
774 def packet_samr_7(packet, conversation, context):
776 c = context.get_samr_context()
777 s = c.get_connection()
779 if c.domain_sid is None:
780 packet_samr_5(packet, conversation, context)
782 c.domain_handle = s.OpenDomain(h,
783 security.SEC_FLAG_MAXIMUM_ALLOWED,
788 SAMR_QUERY_DOMAIN_INFO_LEVELS = [8, 12]
791 def packet_samr_8(packet, conversation, context):
792 # QueryDomainInfo [228]
793 c = context.get_samr_context()
794 s = c.get_connection()
795 if c.domain_handle is None:
796 packet_samr_7(packet, conversation, context)
797 level = random.choice(SAMR_QUERY_DOMAIN_INFO_LEVELS)
798 s.QueryDomainInfo(c.domain_handle, level)
802 packet_samr_14 = null_packet
804 # Ignore these for now.
807 def packet_samr_15(packet, conversation, context):
809 c = context.get_samr_context()
810 s = c.get_connection()
811 if c.domain_handle is None:
812 packet_samr_7(packet, conversation, context)
814 s.EnumDomainAliases(c.domain_handle, 100, 0)
818 def packet_samr_16(packet, conversation, context):
820 c = context.get_samr_context()
821 s = c.get_connection()
822 if c.domain_handle is None:
823 packet_samr_7(packet, conversation, context)
825 sids = lsa.SidArray()
827 sid.sid = c.domain_sid
829 s.GetAliasMembership(c.domain_handle, sids)
833 def packet_samr_17(packet, conversation, context):
835 c = context.get_samr_context()
836 s = c.get_connection()
837 if c.domain_handle is None:
838 packet_samr_7(packet, conversation, context)
840 name = lsa.String(context.username)
841 c.rids = s.LookupNames(c.domain_handle, [name])
845 def packet_samr_18(packet, conversation, context):
847 c = context.get_samr_context()
848 s = c.get_connection()
850 packet_samr_17(packet, conversation, context)
855 s.LookupRids(c.domain_handle, rids)
859 def packet_samr_19(packet, conversation, context):
861 c = context.get_samr_context()
862 s = c.get_connection()
863 if c.domain_handle is None:
864 packet_samr_7(packet, conversation, context)
866 rid = 0x202 # Users I think.
867 c.group_handle = s.OpenGroup(c.domain_handle,
868 security.SEC_FLAG_MAXIMUM_ALLOWED,
873 def packet_samr_25(packet, conversation, context):
875 c = context.get_samr_context()
876 s = c.get_connection()
877 if c.group_handle is None:
878 packet_samr_19(packet, conversation, context)
879 s.QueryGroupMember(c.group_handle)
883 def packet_samr_34(packet, conversation, context):
885 c = context.get_samr_context()
886 s = c.get_connection()
888 packet_samr_17(packet, conversation, context)
889 c.user_handle = s.OpenUser(c.domain_handle,
890 security.SEC_FLAG_MAXIMUM_ALLOWED,
895 def packet_samr_36(packet, conversation, context):
897 c = context.get_samr_context()
898 s = c.get_connection()
899 if c.user_handle is None:
900 packet_samr_34(packet, conversation, context)
902 s.QueryUserInfo(c.user_handle, level)
906 packet_samr_37 = null_packet
909 def packet_samr_39(packet, conversation, context):
911 c = context.get_samr_context()
912 s = c.get_connection()
913 if c.user_handle is None:
914 packet_samr_34(packet, conversation, context)
915 s.GetGroupsForUser(c.user_handle)
919 packet_samr_40 = null_packet
921 packet_samr_44 = null_packet
924 def packet_samr_57(packet, conversation, context):
926 c = context.get_samr_context()
931 def packet_samr_64(packet, conversation, context):
933 c = context.get_samr_context()
938 packet_samr_68 = null_packet
941 def packet_srvsvc_16(packet, conversation, context):
943 s = context.get_srvsvc_connection()
944 server_unc = "\\\\" + context.server
947 s.NetShareGetInfo(server_unc, share_name, level)
951 def packet_srvsvc_21(packet, conversation, context):
954 FIXME: Level changed from 102 to 101 here, to bypass Windows error.
956 Level 102 will cause WERR_ACCESS_DENIED error against Windows, because:
958 > If the level is 102 or 502, the Windows implementation checks whether
959 > the caller is a member of one of the groups previously mentioned or
960 > is a member of the Power Users local group.
962 It passed against Samba since this check is not implemented by Samba yet.
966 https://msdn.microsoft.com/en-us/library/cc247297.aspx#Appendix_A_80
969 srvsvc = context.get_srvsvc_connection()
970 server_unc = "\\\\" + context.server
972 srvsvc.NetSrvGetInfo(server_unc, level)