1df21f99a353071eadccee5c0c8b26f3689783f2
[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 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
39
40 def uint32(v):
41     return ctypes.c_uint32(v).value
42
43
44 def check_runtime_error(runtime, val):
45     if runtime is None:
46         return False
47
48     err32 = uint32(runtime[0])
49     if err32 == val:
50         return True
51
52     return False
53
54
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,
83 ]
84
85
86 def warning(message):
87     print "\033[37;41;1m" "Warning: %s" "\033[00m" % (message)
88
89 ###############################################################################
90 #
91 # Packet generation functions:
92 #
93 # All the packet generation functions have the following form:
94 #  packet_${protocol}_${opcode}(packet, conversation, context)
95 #
96 #  The functions return true, if statistics should be collected for the packet
97 #                      false, the packet has been ignored.
98 #
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.
103 #
104 #   packet contains data about the captured/generated packet
105 #          provides any extra data needed to generate the packet
106 #
107 #   conversation Details of the current client/server interaction
108 #
109 #   context state data for the current interaction
110 #
111 #
112 #
113 # The following protocols are not currently handled:
114 #     smb
115 #     smb2
116 #     browser
117 #     smb_netlogon
118 #
119 # The following drsuapi replication packets are currently ignored:
120 #     DsReplicaSync
121 #     DsGetNCChanges
122 #     DsReplicaUpdateRefs
123
124
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
130
131
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
140
141
142 packet_cldap_5 = null_packet
143 # searchResDone
144
145 packet_dcerpc_0  = null_packet
146 # Request
147 # Can be ignored, it's the continuation of an existing conversation
148
149 packet_dcerpc_2 = null_packet
150 # Request
151 # Server response, so should be ignored
152
153 packet_dcerpc_3 = null_packet
154
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
159
160
161 packet_dcerpc_12 = null_packet
162 # Bind_ack
163 # Server response, so should be ignored
164
165
166 packet_dcerpc_13 = null_packet
167 # Bind_nak
168 # Server response, so should be ignored
169
170
171 packet_dcerpc_14 = null_packet
172 # Alter_context
173 # Generated as part of the connect process
174
175
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
184
185
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
194
195
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
201
202
203 packet_dns_1 = null_packet
204 # response
205 # Server response, so should be ignored
206
207
208 def packet_drsuapi_0(packet, conversation, context):
209     # DsBind
210     context.get_drsuapi_connection_pair(True)
211     return True
212
213
214 NAME_FORMATS = [getattr(drsuapi, _x) for _x in dir(drsuapi)
215                 if 'NAME_FORMAT' in _x]
216
217
218 def packet_drsuapi_12(packet, conversation, context):
219     # DsCrackNames
220     drs, handle = context.get_drsuapi_connection_pair()
221
222     names = drsuapi.DsNameString()
223     names.str = context.server
224
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]
234
235     (result, ctr) = drs.DsCrackNames(handle, 1, req)
236     return True
237
238
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
246
247
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
254
255
256 packet_drsuapi_2 = null_packet
257 # DsReplicaSync
258 # This is between DCs, triggered on a DB change
259 # Ignoring for now
260
261
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
267
268
269 packet_drsuapi_4 = null_packet
270 # DsReplicaUpdateRefs
271 # Ignoring for now
272
273
274 packet_epm_3 = null_packet
275 # Map
276 # Will be generated by higher level protocol calls
277
278
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
289
290
291 packet_ldap_ = null_packet
292 # Unknown
293 # The ldap payload was probably encrypted so just ignore it.
294
295
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
305
306
307 packet_ldap_1 = null_packet
308 # bindResponse
309 # Server response ignored for traffic generation
310
311
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
317
318
319 def packet_ldap_3(packet, conversation, context):
320     # searchRequest
321
322     (scope, dn_sig, filter, attrs, extra, desc, oid) = packet.extra
323     if not scope:
324         scope = 0
325
326     samdb = context.get_ldap_connection()
327     dn = context.get_matching_dn(dn_sig)
328
329     samdb.search(dn, scope=int(scope), attrs=attrs.split(','))
330     return True
331
332
333 packet_ldap_4 = null_packet
334 # searchResEntry
335 # Server response ignored for traffic generation
336
337
338 packet_ldap_5 = null_packet
339 # Server response ignored for traffic generation
340
341 packet_ldap_6 = null_packet
342
343 packet_ldap_7 = null_packet
344
345 packet_ldap_8 = null_packet
346
347 packet_ldap_9 = null_packet
348
349 packet_ldap_16 = null_packet
350
351 packet_lsarpc_0 = null_packet
352 # lsarClose
353
354 packet_lsarpc_1 = null_packet
355 # lsarDelete
356
357 packet_lsarpc_2 = null_packet
358 # lsarEnumeratePrivileges
359
360 packet_lsarpc_3 = null_packet
361 # LsarQuerySecurityObject
362
363 packet_lsarpc_4 = null_packet
364 # LsarSetSecurityObject
365
366 packet_lsarpc_5 = null_packet
367 # LsarChangePassword
368
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.
373 #
374
375
376 def packet_lsarpc_14(packet, conversation, context):
377     # lsa_LookupNames
378     c = context.get_lsarpc_named_pipe_connection()
379
380     objectAttr = lsa.ObjectAttribute()
381     pol_handle = c.OpenPolicy2(u'', objectAttr,
382                                security.SEC_FLAG_MAXIMUM_ALLOWED)
383
384     sids  = lsa.TransSidArray()
385     names = [lsa.String("This Organization"),
386              lsa.String("Digest Authentication")]
387     level = 5
388     count = 0
389     c.LookupNames(pol_handle, names, sids, level, count)
390     return True
391
392
393 def packet_lsarpc_15(packet, conversation, context):
394     # lsa_LookupSids
395     c = context.get_lsarpc_named_pipe_connection()
396
397     objectAttr = lsa.ObjectAttribute()
398     pol_handle = c.OpenPolicy2(u'', objectAttr,
399                                security.SEC_FLAG_MAXIMUM_ALLOWED)
400
401     sids = lsa.SidArray()
402     sid = lsa.SidPtr()
403
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 = 5
410     count = 0
411
412     c.LookupSids(pol_handle, sids, names, level, count)
413     return True
414
415
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
419     #
420     c = context.get_lsarpc_named_pipe_connection()
421
422     objectAttr = lsa.ObjectAttribute()
423
424     pol_handle = c.OpenPolicy2(u'', objectAttr,
425                                security.SEC_FLAG_MAXIMUM_ALLOWED)
426
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
437
438
439 packet_lsarpc_40 = null_packet
440 # lsa_SetTrustedDomainInfo
441 # Not currently supported
442
443
444 packet_lsarpc_43 = null_packet
445 # LsaStorePrivateData
446
447
448 packet_lsarpc_44 = null_packet
449 # LsaRetrievePrivateData
450
451
452 packet_lsarpc_68 = null_packet
453 # LsarLookupNames3
454
455
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 = 5
468     count = 0
469     lookup_options = 0
470     client_revision = 2
471     c.LookupSids3(sids, names, level, count, lookup_options, client_revision)
472     return True
473
474
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 = 5
482     count = 0
483     lookup_options = 0
484     client_revision = 2
485     c.LookupNames4(names, sids, level, count, lookup_options, client_revision)
486     return True
487
488
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
497
498
499 packet_nbns_1 = null_packet
500 # response
501 # Server response, not generated by the client
502
503
504 packet_rpc_netlogon_0 = null_packet
505
506 packet_rpc_netlogon_1 = null_packet
507
508 packet_rpc_netlogon_4 = null_packet
509 # NetrServerReqChallenge
510 # generated by higher level protocol drivers
511 # ignored for traffic generation
512
513 packet_rpc_netlogon_14 = null_packet
514
515 packet_rpc_netlogon_15 = null_packet
516
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
521
522
523 packet_rpc_netlogon_26 = null_packet
524 # NetrServerAuthenticate3
525 # Triggered from schannel set up, no need for an explicit generator
526
527
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()
533
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
541
542
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
565
566
567 packet_rpc_netlogon_34 = null_packet
568
569
570 def packet_rpc_netlogon_39(packet, conversation, context):
571     # NetrLogonSamLogonEx [4331]
572     def connect(creds):
573         c = context.get_netlogon_connection()
574
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)
578
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)
591
592         creds.set_kerberos_state(old_state)
593
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
600
601
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
608
609     domainname = ntlmssp.AV_PAIR()
610     domainname.AvId = ntlmssp.MsvAvNbDomainName
611     domainname.Value = domain_name
612
613     eol = ntlmssp.AV_PAIR()
614     eol.AvId = ntlmssp.MsvAvEOL
615     target_info.pair = [domainname, computername, eol]
616
617     return ndr_pack(target_info)
618
619
620 def samlogon_logon_info(domain_name, computer_name, creds):
621
622     target_info_blob = samlogon_target(domain_name, computer_name)
623
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)
629
630     logon = netlogon.netr_NetworkInfo()
631
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()
637
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()
642
643     return logon
644
645
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
655
656
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()
662
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)
666
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)
681
682         creds.set_kerberos_state(old_state)
683
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
690
691
692 def packet_samr_0(packet, conversation, context):
693     # Open
694     c = context.get_samr_context()
695     c.get_handle()
696     return True
697
698
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
720
721
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
730
731
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
741
742
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
750
751
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)
759
760     c.domain_handle = s.OpenDomain(h,
761                                    security.SEC_FLAG_MAXIMUM_ALLOWED,
762                                    c.domain_sid)
763     return True
764
765
766 SAMR_QUERY_DOMAIN_INFO_LEVELS = [8, 12]
767
768
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
778
779
780 packet_samr_14 = null_packet
781 # CreateDomainAlias
782 # Ignore these for now.
783
784
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)
791
792     s.EnumDomainAliases(c.domain_handle, 100, 0)
793     return True
794
795
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)
802
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
809
810
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)
817
818     name = lsa.String(context.username)
819     c.rids = s.LookupNames(c.domain_handle, [name])
820     return True
821
822
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
835
836
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)
843
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
849
850
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
859
860
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
871
872
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
882
883
884 packet_samr_37 = null_packet
885
886
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
895
896
897 packet_samr_40 = null_packet
898
899 packet_samr_44 = null_packet
900
901
902 def packet_samr_57(packet, conversation, context):
903     # Connect2
904     c = context.get_samr_context()
905     c.get_handle()
906     return True
907
908
909 def packet_samr_64(packet, conversation, context):
910     # Connect5
911     c = context.get_samr_context()
912     c.get_handle()
913     return True
914
915
916 packet_samr_68 = null_packet
917
918
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
927
928
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