python/samba/emulate: PY3 port of samba.tests.emulate.traffic_packet
[samba.git] / python / samba / emulate / traffic_packets.py
1 # Dispatch for various request types.
2 #
3 # Copyright (C) Catalyst IT Ltd. 2017
4 #
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.
9 #
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.
14 #
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/>.
17 #
18 import os
19 import ctypes
20 import random
21
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
32 )
33 from samba import NTSTATUSError
34 from samba.ntstatus import (
35     NT_STATUS_OBJECT_NAME_NOT_FOUND,
36     NT_STATUS_NO_SUCH_DOMAIN
37 )
38 import samba
39 samba.ensure_third_party_module("dns", "dnspython")
40 import dns.resolver
41
42
43 def uint32(v):
44     return ctypes.c_uint32(v).value
45
46
47 def check_runtime_error(runtime, val):
48     if runtime is None:
49         return False
50
51     err32 = uint32(runtime.args[0])
52     if err32 == val:
53         return True
54
55     return False
56
57
58 name_formats = [
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,
86 ]
87
88
89 def warning(message):
90     print("\033[37;41;1m" "Warning: %s" "\033[00m" % (message))
91
92 ###############################################################################
93 #
94 # Packet generation functions:
95 #
96 # All the packet generation functions have the following form:
97 #  packet_${protocol}_${opcode}(packet, conversation, context)
98 #
99 #  The functions return true, if statistics should be collected for the packet
100 #                      false, the packet has been ignored.
101 #
102 # Where:
103 #   protocol is the protocol, i.e. cldap, dcerpc, ...
104 #   opcode   is the protocol op code i.e. type of the packet to be
105 #            generated.
106 #
107 #   packet contains data about the captured/generated packet
108 #          provides any extra data needed to generate the packet
109 #
110 #   conversation Details of the current client/server interaction
111 #
112 #   context state data for the current interaction
113 #
114 #
115 #
116 # The following protocols are not currently handled:
117 #     smb
118 #     smb2
119 #     browser
120 #     smb_netlogon
121 #
122 # The following drsuapi replication packets are currently ignored:
123 #     DsReplicaSync
124 #     DsGetNCChanges
125 #     DsReplicaUpdateRefs
126
127
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):
132     return False
133
134
135 def packet_cldap_3(packet, conversation, context):
136     # searchRequest
137     net = Net(creds=context.creds, lp=context.lp)
138     net.finddc(domain=context.lp.get('realm'),
139                flags=(nbt.NBT_SERVER_LDAP |
140                       nbt.NBT_SERVER_DS |
141                       nbt.NBT_SERVER_WRITABLE))
142     return True
143
144
145 packet_cldap_5 = null_packet
146 # searchResDone
147
148 packet_dcerpc_0  = null_packet
149 # Request
150 # Can be ignored, it's the continuation of an existing conversation
151
152 packet_dcerpc_2 = null_packet
153 # Request
154 # Server response, so should be ignored
155
156 packet_dcerpc_3 = null_packet
157
158 packet_dcerpc_11 = null_packet
159 # Bind
160 # creation of the rpc dcerpc connection is managed by the higher level
161 # protocol drivers. So we ignore it when generating traffic
162
163
164 packet_dcerpc_12 = null_packet
165 # Bind_ack
166 # Server response, so should be ignored
167
168
169 packet_dcerpc_13 = null_packet
170 # Bind_nak
171 # Server response, so should be ignored
172
173
174 packet_dcerpc_14 = null_packet
175 # Alter_context
176 # Generated as part of the connect process
177
178
179 def packet_dcerpc_15(packet, conversation, context):
180     # Alter_context_resp
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")
186     return False
187
188
189 def packet_dcerpc_16(packet, conversation, context):
190     # AUTH3
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")
196     return False
197
198
199 def packet_dns_0(packet, conversation, context):
200     # query
201     name, rtype = context.guess_a_dns_lookup()
202     dns.resolver.query(name, rtype)
203     return True
204
205
206 packet_dns_1 = null_packet
207 # response
208 # Server response, so should be ignored
209
210
211 def packet_drsuapi_0(packet, conversation, context):
212     # DsBind
213     context.get_drsuapi_connection_pair(True)
214     return True
215
216
217 NAME_FORMATS = [getattr(drsuapi, _x) for _x in dir(drsuapi)
218                 if 'NAME_FORMAT' in _x]
219
220
221 def packet_drsuapi_12(packet, conversation, context):
222     # DsCrackNames
223     drs, handle = context.get_drsuapi_connection_pair()
224
225     names = drsuapi.DsNameString()
226     names.str = context.server
227
228     req = drsuapi.DsNameRequest1()
229     req.format_flags = 0
230     req.format_offered = 7
231     req.format_desired = random.choice(name_formats)
232     req.codepage = 1252
233     req.language = 1033  # German, I think
234     req.format_flags = 0
235     req.count = 1
236     req.names = [names]
237
238     (result, ctr) = drs.DsCrackNames(handle, 1, req)
239     return True
240
241
242 def packet_drsuapi_13(packet, conversation, context):
243     # DsWriteAccountSpn
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)
254     return True
255
256
257 def packet_drsuapi_1(packet, conversation, context):
258     # DsUnbind
259     (drs, handle) = context.get_drsuapi_connection_pair()
260     drs.DsUnbind(handle)
261     del context.drsuapi_connections[-1]
262     return True
263
264
265 packet_drsuapi_2 = null_packet
266 # DsReplicaSync
267 # This is between DCs, triggered on a DB change
268 # Ignoring for now
269
270
271 packet_drsuapi_3 = null_packet
272 # DsGetNCChanges
273 # This is between DCs, trigger with DB operation,
274 # or DsReplicaSync between DCs.
275 # Ignoring for now
276
277
278 packet_drsuapi_4 = null_packet
279 # DsReplicaUpdateRefs
280 # Ignoring for now
281
282
283 packet_epm_3 = null_packet
284 # Map
285 # Will be generated by higher level protocol calls
286
287
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)
297     return False
298
299
300 packet_ldap_ = null_packet
301 # Unknown
302 # The ldap payload was probably encrypted so just ignore it.
303
304
305 def packet_ldap_0(packet, conversation, context):
306     # bindRequest
307     if packet.extra[5] == "simple":
308         # Perform a simple bind.
309         context.get_ldap_connection(new=True, simple=True)
310     else:
311         # Perform a sasl bind.
312         context.get_ldap_connection(new=True, simple=False)
313     return True
314
315
316 packet_ldap_1 = null_packet
317 # bindResponse
318 # Server response ignored for traffic generation
319
320
321 def packet_ldap_2(packet, conversation, context):
322     # unbindRequest
323     # pop the last one off -- most likely we're in a bind/unbind ping.
324     del context.ldap_connections[-1:]
325     return False
326
327
328 def packet_ldap_3(packet, conversation, context):
329     # searchRequest
330
331     (scope, dn_sig, filter, attrs, extra, desc, oid) = packet.extra
332     if not scope:
333         scope = 0
334
335     samdb = context.get_ldap_connection()
336     dn = context.get_matching_dn(dn_sig)
337
338     samdb.search(dn,
339                  scope=int(scope),
340                  attrs=attrs.split(','),
341                  controls=["paged_results:1:1000"])
342     return True
343
344
345 packet_ldap_4 = null_packet
346 # searchResEntry
347 # Server response ignored for traffic generation
348
349
350 packet_ldap_5 = null_packet
351 # Server response ignored for traffic generation
352
353 packet_ldap_6 = null_packet
354
355 packet_ldap_7 = null_packet
356
357 packet_ldap_8 = null_packet
358
359 packet_ldap_9 = null_packet
360
361 packet_ldap_16 = null_packet
362
363 packet_lsarpc_0 = null_packet
364 # lsarClose
365
366 packet_lsarpc_1 = null_packet
367 # lsarDelete
368
369 packet_lsarpc_2 = null_packet
370 # lsarEnumeratePrivileges
371
372 packet_lsarpc_3 = null_packet
373 # LsarQuerySecurityObject
374
375 packet_lsarpc_4 = null_packet
376 # LsarSetSecurityObject
377
378 packet_lsarpc_5 = null_packet
379 # LsarChangePassword
380
381 packet_lsarpc_6 = null_packet
382 # lsa_OpenPolicy
383 # We ignore this, but take it as a hint that the lsarpc handle should
384 # be over a named pipe.
385 #
386
387
388 def packet_lsarpc_14(packet, conversation, context):
389     # lsa_LookupNames
390     c = context.get_lsarpc_named_pipe_connection()
391
392     objectAttr = lsa.ObjectAttribute()
393     pol_handle = c.OpenPolicy2(u'', objectAttr,
394                                security.SEC_FLAG_MAXIMUM_ALLOWED)
395
396     sids  = lsa.TransSidArray()
397     names = [lsa.String("This Organization"),
398              lsa.String("Digest Authentication")]
399     level = lsa.LSA_LOOKUP_NAMES_ALL
400     count = 0
401     c.LookupNames(pol_handle, names, sids, level, count)
402     return True
403
404
405 def packet_lsarpc_15(packet, conversation, context):
406     # lsa_LookupSids
407     c = context.get_lsarpc_named_pipe_connection()
408
409     objectAttr = lsa.ObjectAttribute()
410     pol_handle = c.OpenPolicy2(u'', objectAttr,
411                                security.SEC_FLAG_MAXIMUM_ALLOWED)
412
413     sids = lsa.SidArray()
414     sid = lsa.SidPtr()
415
416     x = dom_sid("S-1-5-7")
417     sid.sid = x
418     sids.sids = [sid]
419     sids.num_sids = 1
420     names = lsa.TransNameArray()
421     level = lsa.LSA_LOOKUP_NAMES_ALL
422     count = 0
423
424     c.LookupSids(pol_handle, sids, names, level, count)
425     return True
426
427
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
431     #
432     c = context.get_lsarpc_named_pipe_connection()
433
434     objectAttr = lsa.ObjectAttribute()
435
436     pol_handle = c.OpenPolicy2(u'', objectAttr,
437                                security.SEC_FLAG_MAXIMUM_ALLOWED)
438
439     domsid = security.dom_sid(context.domain_sid)
440     level = 1
441     try:
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):
449             raise
450     return True
451
452
453 packet_lsarpc_40 = null_packet
454 # lsa_SetTrustedDomainInfo
455 # Not currently supported
456
457
458 packet_lsarpc_43 = null_packet
459 # LsaStorePrivateData
460
461
462 packet_lsarpc_44 = null_packet
463 # LsaRetrievePrivateData
464
465
466 packet_lsarpc_68 = null_packet
467 # LsarLookupNames3
468
469
470 def packet_lsarpc_76(packet, conversation, context):
471     # lsa_LookupSids3
472     c = context.get_lsarpc_connection()
473     sids = lsa.SidArray()
474     sid = lsa.SidPtr()
475     # Need a set
476     x = dom_sid("S-1-5-7")
477     sid.sid = x
478     sids.sids = [sid]
479     sids.num_sids = 1
480     names = lsa.TransNameArray2()
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.LookupSids3(sids, names, level, count, lookup_options, client_revision)
486     return True
487
488
489 def packet_lsarpc_77(packet, conversation, context):
490     # lsa_LookupNames4
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
496     count = 0
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)
500     return True
501
502
503 def packet_nbns_0(packet, conversation, context):
504     # query
505     n = Node()
506     try:
507         n.query_name("ANAME", context.server, timeout=4, broadcast=False)
508     except:
509         pass
510     return True
511
512
513 packet_nbns_1 = null_packet
514 # response
515 # Server response, not generated by the client
516
517
518 packet_rpc_netlogon_0 = null_packet
519
520 packet_rpc_netlogon_1 = null_packet
521
522 packet_rpc_netlogon_4 = null_packet
523 # NetrServerReqChallenge
524 # generated by higher level protocol drivers
525 # ignored for traffic generation
526
527 packet_rpc_netlogon_14 = null_packet
528
529 packet_rpc_netlogon_15 = null_packet
530
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
535
536
537 packet_rpc_netlogon_26 = null_packet
538 # NetrServerAuthenticate3
539 # Triggered from schannel set up, no need for an explicit generator
540
541
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()
547
548     c.netr_LogonGetDomainInfo(context.server,
549                               context.netbios_name,
550                               auth,
551                               succ,
552                               2,      # TODO are there other values?
553                               query)
554     return True
555
556
557 def packet_rpc_netlogon_30(packet, conversation, context):
558     # NetrServerPasswordSet2
559     c = context.get_netlogon_connection()
560     (auth, succ) = context.get_authenticator()
561     DATA_LEN = 512
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
564     # subsequent runs
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()
569     pwd.length = pwd_len
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,
578                               auth,
579                               pwd)
580     return True
581
582
583 packet_rpc_netlogon_34 = null_packet
584
585
586 def packet_rpc_netlogon_39(packet, conversation, context):
587     # NetrLogonSamLogonEx [4331]
588     def connect(creds):
589         c = context.get_netlogon_connection()
590
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)
594
595         logon = samlogon_logon_info(context.domain,
596                                     context.netbios_name,
597                                     creds)
598         logon_level = netlogon.NetlogonNetworkTransitiveInformation
599         validation_level = netlogon.NetlogonValidationSamInfo4
600         netr_flags = 0
601         c.netr_LogonSamLogonEx(context.server,
602                                context.machine_creds.get_workstation(),
603                                logon_level,
604                                logon,
605                                validation_level,
606                                netr_flags)
607
608         creds.set_kerberos_state(old_state)
609
610     context.last_samlogon_bad =\
611         context.with_random_bad_credentials(connect,
612                                             context.user_creds,
613                                             context.user_creds_bad,
614                                             context.last_samlogon_bad)
615     return True
616
617
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
624
625     domainname = ntlmssp.AV_PAIR()
626     domainname.AvId = ntlmssp.MsvAvNbDomainName
627     domainname.Value = domain_name
628
629     eol = ntlmssp.AV_PAIR()
630     eol.AvId = ntlmssp.MsvAvEOL
631     target_info.pair = [domainname, computername, eol]
632
633     return ndr_pack(target_info)
634
635
636 def samlogon_logon_info(domain_name, computer_name, creds):
637
638     target_info_blob = samlogon_target(domain_name, computer_name)
639
640     challenge = b"abcdefgh"
641     # User account under test
642     response = creds.get_ntlm_response(flags=CLI_CRED_NTLMv2_AUTH,
643                                        challenge=challenge,
644                                        target_info=target_info_blob)
645
646     logon = netlogon.netr_NetworkInfo()
647
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"]]
652
653     logon.identity_info = netlogon.netr_IdentityInfo()
654
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()
659
660     return logon
661
662
663 def packet_rpc_netlogon_40(packet, conversation, context):
664     # DsrEnumerateDomainTrusts
665     c = context.get_netlogon_connection()
666     c.netr_DsrEnumerateDomainTrusts(
667         context.server,
668         netlogon.NETR_TRUST_FLAG_IN_FOREST |
669         netlogon.NETR_TRUST_FLAG_OUTBOUND  |
670         netlogon.NETR_TRUST_FLAG_INBOUND)
671     return True
672
673
674 def packet_rpc_netlogon_45(packet, conversation, context):
675     # NetrLogonSamLogonWithFlags [7]
676     def connect(creds):
677         c = context.get_netlogon_connection()
678         (auth, succ) = context.get_authenticator()
679
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)
683
684         logon = samlogon_logon_info(context.domain,
685                                     context.netbios_name,
686                                     creds)
687         logon_level = netlogon.NetlogonNetworkTransitiveInformation
688         validation_level = netlogon.NetlogonValidationSamInfo4
689         netr_flags = 0
690         c.netr_LogonSamLogonWithFlags(context.server,
691                                       context.machine_creds.get_workstation(),
692                                       auth,
693                                       succ,
694                                       logon_level,
695                                       logon,
696                                       validation_level,
697                                       netr_flags)
698
699         creds.set_kerberos_state(old_state)
700
701     context.last_samlogon_bad =\
702         context.with_random_bad_credentials(connect,
703                                             context.user_creds,
704                                             context.user_creds_bad,
705                                             context.last_samlogon_bad)
706     return True
707
708
709 def packet_samr_0(packet, conversation, context):
710     # Open
711     c = context.get_samr_context()
712     c.get_handle()
713     return True
714
715
716 def packet_samr_1(packet, conversation, context):
717     # Close
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)
724         c.user_handle = None
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
731         c.rids          = None
732     elif c.handle is not None:
733         s.Close(c.handle)
734         c.handle     = None
735         c.domain_sid = None
736     return True
737
738
739 def packet_samr_3(packet, conversation, context):
740     # QuerySecurity
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)
746     return True
747
748
749 def packet_samr_5(packet, conversation, context):
750     # LookupDomain
751     c = context.get_samr_context()
752     s = c.get_connection()
753     h = c.get_handle()
754     d = lsa.String()
755     d.string = context.domain
756     c.domain_sid = s.LookupDomain(h, d)
757     return True
758
759
760 def packet_samr_6(packet, conversation, context):
761     # EnumDomains
762     c = context.get_samr_context()
763     s = c.get_connection()
764     h = c.get_handle()
765     s.EnumDomains(h, 0, 0)
766     return True
767
768
769 def packet_samr_7(packet, conversation, context):
770     # OpenDomain
771     c = context.get_samr_context()
772     s = c.get_connection()
773     h = c.get_handle()
774     if c.domain_sid is None:
775         packet_samr_5(packet, conversation, context)
776
777     c.domain_handle = s.OpenDomain(h,
778                                    security.SEC_FLAG_MAXIMUM_ALLOWED,
779                                    c.domain_sid)
780     return True
781
782
783 SAMR_QUERY_DOMAIN_INFO_LEVELS = [8, 12]
784
785
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)
794     return True
795
796
797 packet_samr_14 = null_packet
798 # CreateDomainAlias
799 # Ignore these for now.
800
801
802 def packet_samr_15(packet, conversation, context):
803     # EnumDomainAliases
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)
808
809     s.EnumDomainAliases(c.domain_handle, 100, 0)
810     return True
811
812
813 def packet_samr_16(packet, conversation, context):
814     # GetAliasMembership
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)
819
820     sids = lsa.SidArray()
821     sid  = lsa.SidPtr()
822     sid.sid = c.domain_sid
823     sids.sids = [sid]
824     s.GetAliasMembership(c.domain_handle, sids)
825     return True
826
827
828 def packet_samr_17(packet, conversation, context):
829     # LookupNames
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)
834
835     name = lsa.String(context.username)
836     c.rids = s.LookupNames(c.domain_handle, [name])
837     return True
838
839
840 def packet_samr_18(packet, conversation, context):
841     # LookupRids
842     c = context.get_samr_context()
843     s = c.get_connection()
844     if c.rids is None:
845         packet_samr_17(packet, conversation, context)
846     rids = []
847     for r in c.rids:
848         for i in r.ids:
849             rids.append(i)
850     s.LookupRids(c.domain_handle, rids)
851     return True
852
853
854 def packet_samr_19(packet, conversation, context):
855     # OpenGroup
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)
860
861     rid = 0x202  # Users I think.
862     c.group_handle = s.OpenGroup(c.domain_handle,
863                                  security.SEC_FLAG_MAXIMUM_ALLOWED,
864                                  rid)
865     return True
866
867
868 def packet_samr_25(packet, conversation, context):
869     # QueryGroupMember
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)
875     return True
876
877
878 def packet_samr_34(packet, conversation, context):
879     # OpenUser
880     c = context.get_samr_context()
881     s = c.get_connection()
882     if c.rids is None:
883         packet_samr_17(packet, conversation, context)
884     c.user_handle = s.OpenUser(c.domain_handle,
885                                security.SEC_FLAG_MAXIMUM_ALLOWED,
886                                c.rids[0].ids[0])
887     return True
888
889
890 def packet_samr_36(packet, conversation, context):
891     # QueryUserInfo
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)
896     level = 1
897     s.QueryUserInfo(c.user_handle, level)
898     return True
899
900
901 packet_samr_37 = null_packet
902
903
904 def packet_samr_39(packet, conversation, context):
905     # GetGroupsForUser
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)
911     return True
912
913
914 packet_samr_40 = null_packet
915
916 packet_samr_44 = null_packet
917
918
919 def packet_samr_57(packet, conversation, context):
920     # Connect2
921     c = context.get_samr_context()
922     c.get_handle()
923     return True
924
925
926 def packet_samr_64(packet, conversation, context):
927     # Connect5
928     c = context.get_samr_context()
929     c.get_handle()
930     return True
931
932
933 packet_samr_68 = null_packet
934
935
936 def packet_srvsvc_16(packet, conversation, context):
937     # NetShareGetInfo
938     s = context.get_srvsvc_connection()
939     server_unc = "\\\\" + context.server
940     share_name = "IPC$"
941     level = 1
942     s.NetShareGetInfo(server_unc, share_name, level)
943     return True
944
945
946 def packet_srvsvc_21(packet, conversation, context):
947     """NetSrvGetInfo
948
949     FIXME: Level changed from 102 to 101 here, to bypass Windows error.
950
951     Level 102 will cause WERR_ACCESS_DENIED error against Windows, because:
952
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.
956
957     It passed against Samba since this check is not implemented by Samba yet.
958
959     refer to:
960
961         https://msdn.microsoft.com/en-us/library/cc247297.aspx#Appendix_A_80
962
963     """
964     srvsvc = context.get_srvsvc_connection()
965     server_unc = "\\\\" + context.server
966     level = 101
967     srvsvc.NetSrvGetInfo(server_unc, level)
968     return True