Coverage for /root/GitHubProjects/impacket/impacket/smb.py : 68%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# Impacket - Collection of Python classes for working with network protocols.
2#
3# SECUREAUTH LABS. Copyright (C) 2020 SecureAuth Corporation. All rights reserved.
4#
5# This software is provided under a slightly modified version
6# of the Apache Software License. See the accompanying LICENSE file
7# for more information.
8#
9# Author:
10# Altered source done by Alberto Solino (@agsolino)
11#
12# Copyright and license note from Pysmb:
13#
14# Copyright (C) 2001 Michael Teo <michaelteo@bigfoot.com>
15# smb.py - SMB/CIFS library
16#
17# This software is provided 'as-is', without any express or implied warranty.
18# In no event will the author be held liable for any damages arising from the
19# use of this software.
20#
21# Permission is granted to anyone to use this software for any purpose,
22# including commercial applications, and to alter it and redistribute it
23# freely, subject to the following restrictions:
24#
25# 1. The origin of this software must not be misrepresented; you must not
26# claim that you wrote the original software. If you use this software
27# in a product, an acknowledgment in the product documentation would be
28# appreciated but is not required.
29#
30# 2. Altered source versions must be plainly marked as such, and must not be
31# misrepresented as being the original software.
32#
33# 3. This notice cannot be removed or altered from any source distribution.
34#
35# Todo:
36# [ ] Try [SMB]transport fragmentation using Transact requests
37# [ ] Try other methods of doing write (write_raw, transact2, write, write_and_unlock, write_and_close, write_mpx)
38# [-] Try replacements for SMB_COM_NT_CREATE_ANDX (CREATE, T_TRANSACT_CREATE, OPEN_ANDX works
39# [x] Fix forceWriteAndx, which needs to send a RecvRequest, because recv() will not send it
40# [x] Fix Recv() when using RecvAndx and the answer comes splet in several packets
41# [ ] Try [SMB]transport fragmentation with overlapping segments
42# [ ] Try [SMB]transport fragmentation with out of order segments
43# [x] Do chained AndX requests
44# [ ] Transform the rest of the calls to structure
45# [X] Implement TRANS/TRANS2 reassembly for list_path
46#
47from __future__ import division
48from __future__ import print_function
49import os
50import socket
51from binascii import a2b_hex
52import datetime
53from struct import pack, unpack
54from contextlib import contextmanager
55from pyasn1.type.univ import noValue
57from impacket import nmb, ntlm, nt_errors, LOG
58from impacket.structure import Structure
59from impacket.spnego import SPNEGO_NegTokenInit, TypesMech, SPNEGO_NegTokenResp, ASN1_OID, asn1encode, ASN1_AID
60from impacket.krb5.gssapi import KRB5_AP_REQ
62# For signing
63import hashlib
65unicode_support = 0
66unicode_convert = 1
68# Dialect for SMB1
69SMB_DIALECT = 'NT LM 0.12'
71# Shared Device Type
72SHARED_DISK = 0x00
73SHARED_DISK_HIDDEN = 0x80000000
74SHARED_PRINT_QUEUE = 0x01
75SHARED_DEVICE = 0x02
76SHARED_IPC = 0x03
78# Extended attributes mask
79ATTR_ARCHIVE = 0x020
80ATTR_COMPRESSED = 0x800
81ATTR_NORMAL = 0x080
82ATTR_HIDDEN = 0x002
83ATTR_READONLY = 0x001
84ATTR_TEMPORARY = 0x100
85ATTR_DIRECTORY = 0x010
86ATTR_SYSTEM = 0x004
88# Service Type
89SERVICE_DISK = 'A:'
90SERVICE_PRINTER = 'LPT1:'
91SERVICE_IPC = 'IPC'
92SERVICE_COMM = 'COMM'
93SERVICE_ANY = '?????'
95# Server Type (Can be used to mask with SMBMachine.get_type() or SMBDomain.get_type())
96SV_TYPE_WORKSTATION = 0x00000001
97SV_TYPE_SERVER = 0x00000002
98SV_TYPE_SQLSERVER = 0x00000004
99SV_TYPE_DOMAIN_CTRL = 0x00000008
100SV_TYPE_DOMAIN_BAKCTRL = 0x00000010
101SV_TYPE_TIME_SOURCE = 0x00000020
102SV_TYPE_AFP = 0x00000040
103SV_TYPE_NOVELL = 0x00000080
104SV_TYPE_DOMAIN_MEMBER = 0x00000100
105SV_TYPE_PRINTQ_SERVER = 0x00000200
106SV_TYPE_DIALIN_SERVER = 0x00000400
107SV_TYPE_XENIX_SERVER = 0x00000800
108SV_TYPE_NT = 0x00001000
109SV_TYPE_WFW = 0x00002000
110SV_TYPE_SERVER_NT = 0x00004000
111SV_TYPE_POTENTIAL_BROWSER = 0x00010000
112SV_TYPE_BACKUP_BROWSER = 0x00020000
113SV_TYPE_MASTER_BROWSER = 0x00040000
114SV_TYPE_DOMAIN_MASTER = 0x00080000
115SV_TYPE_LOCAL_LIST_ONLY = 0x40000000
116SV_TYPE_DOMAIN_ENUM = 0x80000000
118# Options values for SMB.stor_file and SMB.retr_file
119SMB_O_CREAT = 0x10 # Create the file if file does not exists. Otherwise, operation fails.
120SMB_O_EXCL = 0x00 # When used with SMB_O_CREAT, operation fails if file exists. Cannot be used with SMB_O_OPEN.
121SMB_O_OPEN = 0x01 # Open the file if the file exists
122SMB_O_TRUNC = 0x02 # Truncate the file if the file exists
124# Share Access Mode
125SMB_SHARE_COMPAT = 0x00
126SMB_SHARE_DENY_EXCL = 0x10
127SMB_SHARE_DENY_WRITE = 0x20
128SMB_SHARE_DENY_READEXEC = 0x30
129SMB_SHARE_DENY_NONE = 0x40
130SMB_ACCESS_READ = 0x00
131SMB_ACCESS_WRITE = 0x01
132SMB_ACCESS_READWRITE = 0x02
133SMB_ACCESS_EXEC = 0x03
135TRANS_DISCONNECT_TID = 1
136TRANS_NO_RESPONSE = 2
138STATUS_SUCCESS = 0x00000000
139STATUS_LOGON_FAILURE = 0xC000006D
140STATUS_LOGON_TYPE_NOT_GRANTED = 0xC000015B
141MAX_TFRAG_SIZE = 5840
142EVASION_NONE = 0
143EVASION_LOW = 1
144EVASION_HIGH = 2
145EVASION_MAX = 3
146RPC_X_BAD_STUB_DATA = 0x6F7
148# SMB_FILE_ATTRIBUTES
150SMB_FILE_ATTRIBUTE_NORMAL = 0x0000
151SMB_FILE_ATTRIBUTE_READONLY = 0x0001
152SMB_FILE_ATTRIBUTE_HIDDEN = 0x0002
153SMB_FILE_ATTRIBUTE_SYSTEM = 0x0004
154SMB_FILE_ATTRIBUTE_VOLUME = 0x0008
155SMB_FILE_ATTRIBUTE_DIRECTORY = 0x0010
156SMB_FILE_ATTRIBUTE_ARCHIVE = 0x0020
157SMB_SEARCH_ATTRIBUTE_READONLY = 0x0100
158SMB_SEARCH_ATTRIBUTE_HIDDEN = 0x0200
159SMB_SEARCH_ATTRIBUTE_SYSTEM = 0x0400
160SMB_SEARCH_ATTRIBUTE_DIRECTORY = 0x1000
161SMB_SEARCH_ATTRIBUTE_ARCHIVE = 0x2000
163# Session SetupAndX Action flags
164SMB_SETUP_GUEST = 0x01
165SMB_SETUP_USE_LANMAN_KEY = 0x02
167# QUERY_INFORMATION levels
168SMB_INFO_ALLOCATION = 0x0001
169SMB_INFO_VOLUME = 0x0002
170FILE_FS_SIZE_INFORMATION = 0x0003
171SMB_QUERY_FS_VOLUME_INFO = 0x0102
172SMB_QUERY_FS_SIZE_INFO = 0x0103
173SMB_QUERY_FILE_EA_INFO = 0x0103
174SMB_QUERY_FS_DEVICE_INFO = 0x0104
175SMB_QUERY_FS_ATTRIBUTE_INFO = 0x0105
176SMB_QUERY_FILE_BASIC_INFO = 0x0101
177SMB_QUERY_FILE_STANDARD_INFO = 0x0102
178SMB_QUERY_FILE_ALL_INFO = 0x0107
179FILE_FS_FULL_SIZE_INFORMATION = 0x03EF
181# SET_INFORMATION levels
182SMB_SET_FILE_DISPOSITION_INFO = 0x0102
183SMB_SET_FILE_BASIC_INFO = 0x0101
184SMB_SET_FILE_END_OF_FILE_INFO = 0x0104
186# Device Type [MS-CIFS] 2.2.8.2.5
187FILE_DEVICE_BEEP = 0x0001
188FILE_DEVICE_CD_ROM = 0x0002
189FILE_DEVICE_CD_ROM_FILE_SYSTEM = 0x0003
190FILE_DEVICE_CONTROLLER = 0x0004
191FILE_DEVICE_DATALINK = 0x0005
192FILE_DEVICE_DFS = 0x0006
193FILE_DEVICE_DISK = 0x0007
194FILE_DEVICE_DISK_FILE_SYSTEM = 0x0008
195FILE_DEVICE_FILE_SYSTEM = 0x0009
196FILE_DEVICE_INPORT_PORT = 0x000a
197FILE_DEVICE_KEYBOARD = 0x000b
198FILE_DEVICE_MAILSLOT = 0x000c
199FILE_DEVICE_MIDI_IN = 0x000d
200FILE_DEVICE_MIDI_OUT = 0x000e
201FILE_DEVICE_MOUSE = 0x000f
202FILE_DEVICE_MULTI_UNC_PROVIDER = 0x0010
203FILE_DEVICE_NAMED_PIPE = 0x0011
204FILE_DEVICE_NETWORK = 0x0012
205FILE_DEVICE_NETWORK_BROWSER = 0x0013
206FILE_DEVICE_NETWORK_FILE_SYSTEM = 0x0014
207FILE_DEVICE_NULL = 0x0015
208FILE_DEVICE_PARALLEL_PORT = 0x0016
209FILE_DEVICE_PHYSICAL_NETCARD = 0x0017
210FILE_DEVICE_PRINTER = 0x0018
211FILE_DEVICE_SCANNER = 0x0019
212FILE_DEVICE_SERIAL_MOUSE_PORT = 0x001a
213FILE_DEVICE_SERIAL_PORT = 0x001b
214FILE_DEVICE_SCREEN = 0x001c
215FILE_DEVICE_SOUND = 0x001d
216FILE_DEVICE_STREAMS = 0x001e
217FILE_DEVICE_TAPE = 0x001f
218FILE_DEVICE_TAPE_FILE_SYSTEM = 0x0020
219FILE_DEVICE_TRANSPORT = 0x0021
220FILE_DEVICE_UNKNOWN = 0x0022
221FILE_DEVICE_VIDEO = 0x0023
222FILE_DEVICE_VIRTUAL_DISK = 0x0024
223FILE_DEVICE_WAVE_IN = 0x0025
224FILE_DEVICE_WAVE_OUT = 0x0026
225FILE_DEVICE_8042_PORT = 0x0027
226FILE_DEVICE_NETWORK_REDIRECTOR = 0x0028
227FILE_DEVICE_BATTERY = 0x0029
228FILE_DEVICE_BUS_EXTENDER = 0x002a
229FILE_DEVICE_MODEM = 0x002b
230FILE_DEVICE_VDM = 0x002c
232# Device Characteristics [MS-CIFS] 2.2.8.2.5
233FILE_REMOVABLE_MEDIA = 0x0001
234FILE_READ_ONLY_DEVICE = 0x0002
235FILE_FLOPPY_DISKETTE = 0x0004
236FILE_WRITE_ONCE_MEDIA = 0x0008
237FILE_REMOTE_DEVICE = 0x0010
238FILE_DEVICE_IS_MOUNTED = 0x0020
239FILE_VIRTUAL_VOLUME = 0x0040
241# File System Attributes
242FILE_CASE_SENSITIVE_SEARCH = 0x00000001
243FILE_CASE_PRESERVED_NAMES = 0x00000002
244FILE_UNICODE_ON_DISK = 0x00000004
245FILE_PERSISTENT_ACLS = 0x00000008
246FILE_FILE_COMPRESSION = 0x00000010
247FILE_VOLUME_IS_COMPRESSED = 0x00008000
249# FIND_FIRST2 flags and levels
250SMB_FIND_CLOSE_AFTER_REQUEST = 0x0001
251SMB_FIND_CLOSE_AT_EOS = 0x0002
252SMB_FIND_RETURN_RESUME_KEYS = 0x0004
253SMB_FIND_CONTINUE_FROM_LAST = 0x0008
254SMB_FIND_WITH_BACKUP_INTENT = 0x0010
256FILE_DIRECTORY_FILE = 0x00000001
257FILE_DELETE_ON_CLOSE = 0x00001000
258FILE_NON_DIRECTORY_FILE = 0x00000040
260SMB_FIND_INFO_STANDARD = 0x0001
261SMB_FIND_FILE_DIRECTORY_INFO = 0x0101
262SMB_FIND_FILE_FULL_DIRECTORY_INFO= 0x0102
263SMB_FIND_FILE_NAMES_INFO = 0x0103
264SMB_FIND_FILE_BOTH_DIRECTORY_INFO= 0x0104
265SMB_FIND_FILE_ID_FULL_DIRECTORY_INFO = 0x105
266SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO = 0x106
269# DesiredAccess flags
270FILE_READ_DATA = 0x00000001
271FILE_WRITE_DATA = 0x00000002
272FILE_APPEND_DATA = 0x00000004
273FILE_EXECUTE = 0x00000020
274MAXIMUM_ALLOWED = 0x02000000
275GENERIC_ALL = 0x10000000
276GENERIC_EXECUTE = 0x20000000
277GENERIC_WRITE = 0x40000000
278GENERIC_READ = 0x80000000
280# ShareAccess flags
281FILE_SHARE_NONE = 0x00000000
282FILE_SHARE_READ = 0x00000001
283FILE_SHARE_WRITE = 0x00000002
284FILE_SHARE_DELETE = 0x00000004
286# CreateDisposition flags
287FILE_SUPERSEDE = 0x00000000
288FILE_OPEN = 0x00000001
289FILE_CREATE = 0x00000002
290FILE_OPEN_IF = 0x00000003
291FILE_OVERWRITE = 0x00000004
292FILE_OVERWRITE_IF = 0x00000005
294def strerror(errclass, errcode):
295 if errclass == 0x01:
296 return 'OS error', ERRDOS.get(errcode, 'Unknown error')
297 elif errclass == 0x02:
298 return 'Server error', ERRSRV.get(errcode, 'Unknown error')
299 elif errclass == 0x03:
300 return 'Hardware error', ERRHRD.get(errcode, 'Unknown error')
301 # This is not a standard error class for SMB
302 #elif errclass == 0x80:
303 # return 'Browse error', ERRBROWSE.get(errcode, 'Unknown error')
304 elif errclass == 0xff:
305 return 'Bad command', 'Bad command. Please file bug report'
306 else:
307 return 'Unknown error', 'Unknown error'
309# Raised when an error has occurred during a session
310class SessionError(Exception):
311 # SMB X/Open error codes for the ERRDOS error class
312 ERRsuccess = 0
313 ERRbadfunc = 1
314 ERRbadfile = 2
315 ERRbadpath = 3
316 ERRnofids = 4
317 ERRnoaccess = 5
318 ERRbadfid = 6
319 ERRbadmcb = 7
320 ERRnomem = 8
321 ERRbadmem = 9
322 ERRbadenv = 10
323 ERRbadaccess = 12
324 ERRbaddata = 13
325 ERRres = 14
326 ERRbaddrive = 15
327 ERRremcd = 16
328 ERRdiffdevice = 17
329 ERRnofiles = 18
330 ERRgeneral = 31
331 ERRbadshare = 32
332 ERRlock = 33
333 ERRunsup = 50
334 ERRnetnamedel = 64
335 ERRnosuchshare = 67
336 ERRfilexists = 80
337 ERRinvalidparam = 87
338 ERRcannotopen = 110
339 ERRinsufficientbuffer = 122
340 ERRinvalidname = 123
341 ERRunknownlevel = 124
342 ERRnotlocked = 158
343 ERRrename = 183
344 ERRbadpipe = 230
345 ERRpipebusy = 231
346 ERRpipeclosing = 232
347 ERRnotconnected = 233
348 ERRmoredata = 234
349 ERRnomoreitems = 259
350 ERRbaddirectory = 267
351 ERReasnotsupported = 282
352 ERRlogonfailure = 1326
353 ERRbuftoosmall = 2123
354 ERRunknownipc = 2142
355 ERRnosuchprintjob = 2151
356 ERRinvgroup = 2455
358 # here's a special one from observing NT
359 ERRnoipc = 66
361 # These errors seem to be only returned by the NT printer driver system
362 ERRdriveralreadyinstalled = 1795
363 ERRunknownprinterport = 1796
364 ERRunknownprinterdriver = 1797
365 ERRunknownprintprocessor = 1798
366 ERRinvalidseparatorfile = 1799
367 ERRinvalidjobpriority = 1800
368 ERRinvalidprintername = 1801
369 ERRprinteralreadyexists = 1802
370 ERRinvalidprintercommand = 1803
371 ERRinvaliddatatype = 1804
372 ERRinvalidenvironment = 1805
374 ERRunknownprintmonitor = 3000
375 ERRprinterdriverinuse = 3001
376 ERRspoolfilenotfound = 3002
377 ERRnostartdoc = 3003
378 ERRnoaddjob = 3004
379 ERRprintprocessoralreadyinstalled = 3005
380 ERRprintmonitoralreadyinstalled = 3006
381 ERRinvalidprintmonitor = 3007
382 ERRprintmonitorinuse = 3008
383 ERRprinterhasjobsqueued = 3009
385 # Error codes for the ERRSRV class
387 ERRerror = 1
388 ERRbadpw = 2
389 ERRbadtype = 3
390 ERRaccess = 4
391 ERRinvnid = 5
392 ERRinvnetname = 6
393 ERRinvdevice = 7
394 ERRqfull = 49
395 ERRqtoobig = 50
396 ERRinvpfid = 52
397 ERRsmbcmd = 64
398 ERRsrverror = 65
399 ERRfilespecs = 67
400 ERRbadlink = 68
401 ERRbadpermits = 69
402 ERRbadpid = 70
403 ERRsetattrmode = 71
404 ERRpaused = 81
405 ERRmsgoff = 82
406 ERRnoroom = 83
407 ERRrmuns = 87
408 ERRtimeout = 88
409 ERRnoresource = 89
410 ERRtoomanyuids = 90
411 ERRbaduid = 91
412 ERRuseMPX = 250
413 ERRuseSTD = 251
414 ERRcontMPX = 252
415 ERRbadPW = None
416 ERRnosupport = 0
417 ERRunknownsmb = 22
419 # Error codes for the ERRHRD class
421 ERRnowrite = 19
422 ERRbadunit = 20
423 ERRnotready = 21
424 ERRbadcmd = 22
425 ERRdata = 23
426 ERRbadreq = 24
427 ERRseek = 25
428 ERRbadmedia = 26
429 ERRbadsector = 27
430 ERRnopaper = 28
431 ERRwrite = 29
432 ERRread = 30
433 ERRwrongdisk = 34
434 ERRFCBunavail = 35
435 ERRsharebufexc = 36
436 ERRdiskfull = 39
439 hard_msgs = {
440 19: ("ERRnowrite", "Attempt to write on write-protected diskette."),
441 20: ("ERRbadunit", "Unknown unit."),
442 21: ("ERRnotready", "Drive not ready."),
443 22: ("ERRbadcmd", "Unknown command."),
444 23: ("ERRdata", "Data error (CRC)."),
445 24: ("ERRbadreq", "Bad request structure length."),
446 25: ("ERRseek", "Seek error."),
447 26: ("ERRbadmedia", "Unknown media type."),
448 27: ("ERRbadsector", "Sector not found."),
449 28: ("ERRnopaper", "Printer out of paper."),
450 29: ("ERRwrite", "Write fault."),
451 30: ("ERRread", "Read fault."),
452 31: ("ERRgeneral", "General failure."),
453 32: ("ERRbadshare", "An open conflicts with an existing open."),
454 33: ("ERRlock", "A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."),
455 34: ("ERRwrongdisk", "The wrong disk was found in a drive."),
456 35: ("ERRFCBUnavail", "No FCBs are available to process request."),
457 36: ("ERRsharebufexc", "A sharing buffer has been exceeded.")
458 }
460 dos_msgs = {
461 ERRbadfunc: ("ERRbadfunc", "Invalid function."),
462 ERRbadfile: ("ERRbadfile", "File not found."),
463 ERRbadpath: ("ERRbadpath", "Directory invalid."),
464 ERRnofids: ("ERRnofids", "No file descriptors available"),
465 ERRnoaccess: ("ERRnoaccess", "Access denied."),
466 ERRbadfid: ("ERRbadfid", "Invalid file handle."),
467 ERRbadmcb: ("ERRbadmcb", "Memory control blocks destroyed."),
468 ERRnomem: ("ERRnomem", "Insufficient server memory to perform the requested function."),
469 ERRbadmem: ("ERRbadmem", "Invalid memory block address."),
470 ERRbadenv: ("ERRbadenv", "Invalid environment."),
471 11: ("ERRbadformat", "Invalid format."),
472 ERRbadaccess: ("ERRbadaccess", "Invalid open mode."),
473 ERRbaddata: ("ERRbaddata", "Invalid data."),
474 ERRres: ("ERRres", "reserved."),
475 ERRbaddrive: ("ERRbaddrive", "Invalid drive specified."),
476 ERRremcd: ("ERRremcd", "A Delete Directory request attempted to remove the server's current directory."),
477 ERRdiffdevice: ("ERRdiffdevice", "Not same device."),
478 ERRnofiles: ("ERRnofiles", "A File Search command can find no more files matching the specified criteria."),
479 ERRbadshare: ("ERRbadshare", "The sharing mode specified for an Open conflicts with existing FIDs on the file."),
480 ERRlock: ("ERRlock", "A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."),
481 ERRunsup: ("ERRunsup", "The operation is unsupported"),
482 ERRnosuchshare: ("ERRnosuchshare", "You specified an invalid share name"),
483 ERRfilexists: ("ERRfilexists", "The file named in a Create Directory, Make New File or Link request already exists."),
484 ERRinvalidname: ("ERRinvalidname", "Invalid name"),
485 ERRbadpipe: ("ERRbadpipe", "Pipe invalid."),
486 ERRpipebusy: ("ERRpipebusy", "All instances of the requested pipe are busy."),
487 ERRpipeclosing: ("ERRpipeclosing", "Pipe close in progress."),
488 ERRnotconnected: ("ERRnotconnected", "No process on other end of pipe."),
489 ERRmoredata: ("ERRmoredata", "There is more data to be returned."),
490 ERRinvgroup: ("ERRinvgroup", "Invalid workgroup (try the -W option)"),
491 ERRlogonfailure: ("ERRlogonfailure", "Logon failure"),
492 ERRdiskfull: ("ERRdiskfull", "Disk full"),
493 ERRgeneral: ("ERRgeneral", "General failure"),
494 ERRunknownlevel: ("ERRunknownlevel", "Unknown info level")
495 }
497 server_msgs = {
498 1: ("ERRerror", "Non-specific error code."),
499 2: ("ERRbadpw", "Bad password - name/password pair in a Tree Connect or Session Setup are invalid."),
500 3: ("ERRbadtype", "reserved."),
501 4: ("ERRaccess", "The requester does not have the necessary access rights within the specified context for the requested function. The context is defined by the TID or the UID."),
502 5: ("ERRinvnid", "The tree ID (TID) specified in a command was invalid."),
503 6: ("ERRinvnetname", "Invalid network name in tree connect."),
504 7: ("ERRinvdevice", "Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."),
505 49: ("ERRqfull", "Print queue full (files) -- returned by open print file."),
506 50: ("ERRqtoobig", "Print queue full -- no space."),
507 51: ("ERRqeof", "EOF on print queue dump."),
508 52: ("ERRinvpfid", "Invalid print file FID."),
509 64: ("ERRsmbcmd", "The server did not recognize the command received."),
510 65: ("ERRsrverror","The server encountered an internal error, e.g., system file unavailable."),
511 67: ("ERRfilespecs", "The file handle (FID) and pathname parameters contained an invalid combination of values."),
512 68: ("ERRreserved", "reserved."),
513 69: ("ERRbadpermits", "The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."),
514 70: ("ERRreserved", "reserved."),
515 71: ("ERRsetattrmode", "The attribute mode in the Set File Attribute request is invalid."),
516 81: ("ERRpaused", "Server is paused."),
517 82: ("ERRmsgoff", "Not receiving messages."),
518 83: ("ERRnoroom", "No room to buffer message."),
519 87: ("ERRrmuns", "Too many remote user names."),
520 88: ("ERRtimeout", "Operation timed out."),
521 89: ("ERRnoresource", "No resources currently available for request."),
522 90: ("ERRtoomanyuids", "Too many UIDs active on this session."),
523 91: ("ERRbaduid", "The UID is not known as a valid ID on this session."),
524 250: ("ERRusempx","Temp unable to support Raw, use MPX mode."),
525 251: ("ERRusestd","Temp unable to support Raw, use standard read/write."),
526 252: ("ERRcontmpx", "Continue in MPX mode."),
527 253: ("ERRreserved", "reserved."),
528 254: ("ERRreserved", "reserved."),
529 0xFFFF: ("ERRnosupport", "Function not supported.")
530 }
531 # Error clases
533 ERRDOS = 0x1
534 error_classes = { 0: ("SUCCESS", {}),
535 ERRDOS: ("ERRDOS", dos_msgs),
536 0x02: ("ERRSRV",server_msgs),
537 0x03: ("ERRHRD",hard_msgs),
538 0x04: ("ERRXOS", {} ),
539 0xE1: ("ERRRMX1", {} ),
540 0xE2: ("ERRRMX2", {} ),
541 0xE3: ("ERRRMX3", {} ),
542 0xFF: ("ERRCMD", {} ) }
546 def __init__( self, error_string, error_class, error_code, nt_status = 0, packet=0):
547 Exception.__init__(self, error_string)
548 self.nt_status = nt_status
549 self._args = error_string
550 if nt_status: 550 ↛ 554line 550 didn't jump to line 554, because the condition on line 550 was never false
551 self.error_class = 0
552 self.error_code = (error_code << 16) + error_class
553 else:
554 self.error_class = error_class
555 self.error_code = error_code
556 self.packet = packet
558 def get_error_class( self ):
559 return self.error_class
561 def get_error_code( self ):
562 return self.error_code
564 def get_error_packet(self):
565 return self.packet
567 def __str__( self ):
568 error_class = SessionError.error_classes.get( self.error_class, None )
569 if not error_class:
570 error_code_str = self.error_code
571 error_class_str = self.error_class
572 else:
573 error_class_str = error_class[0]
574 error_code = error_class[1].get( self.error_code, None )
575 if not error_code:
576 error_code_str = self.error_code
577 else:
578 error_code_str = '%s(%s)' % error_code
580 if self.nt_status:
581 return 'SMB SessionError: %s(%s)' % nt_errors.ERROR_MESSAGES[self.error_code]
582 else:
583 # Fall back to the old format
584 return 'SMB SessionError: class: %s, code: %s' % (error_class_str, error_code_str)
587# Raised when an supported feature is present/required in the protocol but is not
588# currently supported by pysmb
589class UnsupportedFeature(Exception):
590 pass
592# Contains information about a SMB shared device/service
593class SharedDevice:
594 def __init__(self, name, share_type, comment):
595 self.__name = name
596 self.__type = share_type
597 self.__comment = comment
599 def get_name(self):
600 return self.__name
602 def get_type(self):
603 return self.__type
605 def get_comment(self):
606 return self.__comment
608 def __repr__(self):
609 return '<SharedDevice instance: name=' + self.__name + ', type=' + str(self.__type) + ', comment="' + self.__comment + '">'
612# Contains information about the shared file/directory
613class SharedFile:
614 def __init__(self, ctime, atime, mtime, filesize, allocsize, attribs, shortname, longname):
615 self.__ctime = ctime
616 self.__atime = atime
617 self.__mtime = mtime
618 self.__filesize = filesize
619 self.__allocsize = allocsize
620 self.__attribs = attribs
621 try:
622 if isinstance(shortname,bytes): 622 ↛ 623line 622 didn't jump to line 623, because the condition on line 622 was never true
623 self.__shortname = shortname[:shortname.index(b'\0')]
624 else:
625 self.__shortname = shortname[:shortname.index('\0')]
626 except (ValueError, TypeError):
627 self.__shortname = shortname
628 try:
629 if isinstance(shortname,bytes): 629 ↛ 630line 629 didn't jump to line 630, because the condition on line 629 was never true
630 self.__longname = longname[:longname.index(b'\0')]
631 else:
632 self.__longname = longname[:longname.index('\0')]
633 except (ValueError, TypeError):
634 self.__longname = longname
636 def get_ctime(self):
637 return self.__ctime
639 def get_ctime_epoch(self):
640 return self.__convert_smbtime(self.__ctime)
642 def get_mtime(self):
643 return self.__mtime
645 def get_mtime_epoch(self):
646 return self.__convert_smbtime(self.__mtime)
648 def get_atime(self):
649 return self.__atime
651 def get_atime_epoch(self):
652 return self.__convert_smbtime(self.__atime)
654 def get_filesize(self):
655 return self.__filesize
657 def get_allocsize(self):
658 return self.__allocsize
660 def get_attributes(self):
661 return self.__attribs
663 def is_archive(self):
664 return self.__attribs & ATTR_ARCHIVE
666 def is_compressed(self):
667 return self.__attribs & ATTR_COMPRESSED
669 def is_normal(self):
670 return self.__attribs & ATTR_NORMAL
672 def is_hidden(self):
673 return self.__attribs & ATTR_HIDDEN
675 def is_readonly(self):
676 return self.__attribs & ATTR_READONLY
678 def is_temporary(self):
679 return self.__attribs & ATTR_TEMPORARY
681 def is_directory(self):
682 return self.__attribs & ATTR_DIRECTORY
684 def is_system(self):
685 return self.__attribs & ATTR_SYSTEM
687 def get_shortname(self):
688 return self.__shortname
690 def get_longname(self):
691 return self.__longname
693 def __repr__(self):
694 return '<SharedFile instance: shortname="' + self.__shortname + '", longname="' + self.__longname + '", filesize=' + str(self.__filesize) + '>'
696 @staticmethod
697 def __convert_smbtime(t):
698 x = t >> 32
699 y = t & 0xffffffff
700 geo_cal_offset = 11644473600.0 # = 369.0 * 365.25 * 24 * 60 * 60 - (3.0 * 24 * 60 * 60 + 6.0 * 60 * 60)
701 return (x * 4.0 * (1 << 30) + (y & 0xfff00000)) * 1.0e-7 - geo_cal_offset
704# Contain information about a SMB machine
705class SMBMachine:
706 def __init__(self, nbname, nbt_type, comment):
707 self.__nbname = nbname
708 self.__type = nbt_type
709 self.__comment = comment
711 def __repr__(self):
712 return '<SMBMachine instance: nbname="' + self.__nbname + '", type=' + hex(self.__type) + ', comment="' + self.__comment + '">'
714class SMBDomain:
715 def __init__(self, nbgroup, domain_type, master_browser):
716 self.__nbgroup = nbgroup
717 self.__type = domain_type
718 self.__master_browser = master_browser
720 def __repr__(self):
721 return '<SMBDomain instance: nbgroup="' + self.__nbgroup + '", type=' + hex(self.__type) + ', master browser="' + self.__master_browser + '">'
723# Represents a SMB Packet
724class NewSMBPacket(Structure):
725 structure = (
726 ('Signature', '"\xffSMB'),
727 ('Command','B=0'),
728 ('ErrorClass','B=0'),
729 ('_reserved','B=0'),
730 ('ErrorCode','<H=0'),
731 ('Flags1','B=0'),
732 ('Flags2','<H=0'),
733 ('PIDHigh','<H=0'),
734 ('SecurityFeatures','8s=""'),
735 ('Reserved','<H=0'),
736 ('Tid','<H=0xffff'),
737 ('Pid','<H=0'),
738 ('Uid','<H=0'),
739 ('Mid','<H=0'),
740 ('Data','*:'),
741 )
743 def __init__(self, **kargs):
744 Structure.__init__(self, **kargs)
746 if ('Flags2' in self.fields) is False:
747 self['Flags2'] = 0
748 if ('Flags1' in self.fields) is False:
749 self['Flags1'] = 0
751 if 'data' not in kargs:
752 self['Data'] = []
754 def addCommand(self, command):
755 if len(self['Data']) == 0: 755 ↛ 758line 755 didn't jump to line 758, because the condition on line 755 was never false
756 self['Command'] = command.command
757 else:
758 self['Data'][-1]['Parameters']['AndXCommand'] = command.command
759 self['Data'][-1]['Parameters']['AndXOffset'] = len(self)
760 self['Data'].append(command)
762 def isMoreData(self):
763 return (self['Command'] in [SMB.SMB_COM_TRANSACTION, SMB.SMB_COM_READ_ANDX, SMB.SMB_COM_READ_RAW] and
764 self['ErrorClass'] == 1 and self['ErrorCode'] == SessionError.ERRmoredata)
766 def isMoreProcessingRequired(self):
767 return self['ErrorClass'] == 0x16 and self['ErrorCode'] == 0xc000
769 def isValidAnswer(self, cmd):
770 # this was inside a loop reading more from the net (with recv_packet(None))
771 if self['Command'] == cmd: 771 ↛ 780line 771 didn't jump to line 780, because the condition on line 771 was never false
772 if (self['ErrorClass'] == 0x00 and self['ErrorCode'] == 0x00):
773 return 1
774 elif self.isMoreData(): 774 ↛ 775line 774 didn't jump to line 775, because the condition on line 774 was never true
775 return 1
776 elif self.isMoreProcessingRequired():
777 return 1
778 raise SessionError("SMB Library Error", self['ErrorClass'] + (self['_reserved'] << 8), self['ErrorCode'], self['Flags2'] & SMB.FLAGS2_NT_STATUS, self)
779 else:
780 raise UnsupportedFeature("Unexpected answer from server: Got %d, Expected %d" % (self['Command'], cmd))
783class SMBCommand(Structure):
784 structure = (
785 ('WordCount', 'B=len(Parameters)//2'),
786 ('_ParametersLength','_-Parameters','WordCount*2'),
787 ('Parameters',':'), # default set by constructor
788 ('ByteCount','<H-Data'),
789 ('Data',':'), # default set by constructor
790 )
792 def __init__(self, commandOrData = None, data = None, **kargs):
793 if type(commandOrData) == type(0):
794 self.command = commandOrData
795 else:
796 data = data or commandOrData
798 Structure.__init__(self, data = data, **kargs)
800 if data is None:
801 self['Parameters'] = ''
802 self['Data'] = ''
804class AsciiOrUnicodeStructure(Structure):
805 UnicodeStructure = ()
806 AsciiStructure = ()
807 def __init__(self, flags = 0, **kargs):
808 if flags & SMB.FLAGS2_UNICODE:
809 self.structure = self.UnicodeStructure
810 else:
811 self.structure = self.AsciiStructure
812 Structure.__init__(self, **kargs)
814class SMBCommand_Parameters(Structure):
815 pass
817class SMBAndXCommand_Parameters(Structure):
818 commonHdr = (
819 ('AndXCommand','B=0xff'),
820 ('_reserved','B=0'),
821 ('AndXOffset','<H=0'),
822 )
823 structure = ( # default structure, overridden by subclasses
824 ('Data',':=""'),
825 )
827############# TRANSACTIONS RELATED
828# TRANS2_QUERY_FS_INFORMATION
829# QUERY_FS Information Levels
830# SMB_QUERY_FS_ATTRIBUTE_INFO
831class SMBQueryFsAttributeInfo(Structure):
832 structure = (
833 ('FileSystemAttributes','<L'),
834 ('MaxFilenNameLengthInBytes','<L'),
835 ('LengthOfFileSystemName','<L-FileSystemName'),
836 ('FileSystemName',':'),
837 )
839class SMBQueryFsInfoVolume(AsciiOrUnicodeStructure):
840 commonHdr = (
841 ('ulVolSerialNbr','<L=0xABCDEFAA'),
842 ('cCharCount','<B-VolumeLabel'),
843 )
844 AsciiStructure = (
845 ('VolumeLabel','z'),
846 )
847 UnicodeStructure = (
848 ('VolumeLabel','u'),
849 )
851# FILE_FS_SIZE_INFORMATION
852class FileFsSizeInformation(Structure):
853 structure = (
854 ('TotalAllocationUnits','<q=148529400'),
855 ('AvailableAllocationUnits','<q=14851044'),
856 ('SectorsPerAllocationUnit','<L=2'),
857 ('BytesPerSector','<L=512'),
858 )
860# SMB_QUERY_FS_SIZE_INFO
861class SMBQueryFsSizeInfo(Structure):
862 structure = (
863 ('TotalAllocationUnits','<q=148529400'),
864 ('TotalFreeAllocationUnits','<q=14851044'),
865 ('SectorsPerAllocationUnit','<L=2'),
866 ('BytesPerSector','<L=512'),
867 )
868# FILE_FS_FULL_SIZE_INFORMATION
869class SMBFileFsFullSizeInformation(Structure):
870 structure = (
871 ('TotalAllocationUnits','<q=148529400'),
872 ('CallerAvailableAllocationUnits','<q=148529400'),
873 ('ActualAvailableAllocationUnits','<q=148529400'),
874 ('SectorsPerAllocationUnit','<L=15'),
875 ('BytesPerSector','<L=512')
876 )
877# SMB_QUERY_FS_VOLUME_INFO
878class SMBQueryFsVolumeInfo(Structure):
879 structure = (
880 ('VolumeCreationTime','<q'),
881 ('SerialNumber','<L=0xABCDEFAA'),
882 ('VolumeLabelSize','<L=len(VolumeLabel)'),
883 ('Reserved','<H=0x10'),
884 ('VolumeLabel',':')
885 )
887# SMB_QUERY_FS_DEVICE_INFO
888class SMBQueryFsDeviceInfo(Structure):
889 structure = (
890 ('DeviceType', '<L=0'),
891 ('DeviceCharacteristics', '<L=0')
892 )
895# SMB_FIND_FILE_BOTH_DIRECTORY_INFO level
896class SMBFindFileBothDirectoryInfo(AsciiOrUnicodeStructure):
897 commonHdr = (
898 ('NextEntryOffset','<L=0'),
899 ('FileIndex','<L=0'),
900 ('CreationTime','<q'),
901 ('LastAccessTime','<q'),
902 ('LastWriteTime','<q'),
903 ('LastChangeTime','<q'),
904 ('EndOfFile','<q=0'),
905 ('AllocationSize','<q=0'),
906 ('ExtFileAttributes','<L=0'),
907 )
908 AsciiStructure = (
909 ('FileNameLength','<L-FileName','len(FileName)'),
910 ('EaSize','<L=0'),
911 ('ShortNameLength','<B=0'),
912 ('Reserved','<B=0'),
913 ('ShortName','24s'),
914 ('FileName',':'),
915 )
916 UnicodeStructure = (
917 ('FileNameLength','<L-FileName','len(FileName)*2'),
918 ('EaSize','<L=0'),
919 ('ShortNameLength','<B=0'),
920 ('Reserved','<B=0'),
921 ('ShortName','24s'),
922 ('FileName',':'),
923 )
925# SMB_FIND_FILE_ID_FULL_DIRECTORY_INFO level
926class SMBFindFileIdFullDirectoryInfo(AsciiOrUnicodeStructure):
927 commonHdr = (
928 ('NextEntryOffset','<L=0'),
929 ('FileIndex','<L=0'),
930 ('CreationTime','<q'),
931 ('LastAccessTime','<q'),
932 ('LastWriteTime','<q'),
933 ('LastChangeTime','<q'),
934 ('EndOfFile','<q=0'),
935 ('AllocationSize','<q=0'),
936 ('ExtFileAttributes','<L=0'),
937 )
938 AsciiStructure = (
939 ('FileNameLength','<L-FileName','len(FileName)'),
940 ('EaSize','<L=0'),
941 ('Reserved', '<L=0'),
942 ('FileID','<q=0'),
943 ('FileName','z'),
944 )
945 UnicodeStructure = (
946 ('FileNameLength','<L-FileName','len(FileName)*2'),
947 ('EaSize','<L=0'),
948 ('Reserved','<L=0'),
949 ('FileID','<q=0'),
950 ('FileName',':'),
951 )
953# SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO level
954class SMBFindFileIdBothDirectoryInfo(AsciiOrUnicodeStructure):
955 commonHdr = (
956 ('NextEntryOffset','<L=0'),
957 ('FileIndex','<L=0'),
958 ('CreationTime','<q'),
959 ('LastAccessTime','<q'),
960 ('LastWriteTime','<q'),
961 ('LastChangeTime','<q'),
962 ('EndOfFile','<q=0'),
963 ('AllocationSize','<q=0'),
964 ('ExtFileAttributes','<L=0'),
965 )
966 AsciiStructure = (
967 ('FileNameLength','<L-FileName','len(FileName)'),
968 ('EaSize','<L=0'),
969 ('ShortNameLength','<B=0'),
970 ('Reserved','<B=0'),
971 ('ShortName','24s'),
972 ('Reserved','<H=0'),
973 ('FileID','<q=0'),
974 ('FileName','z'),
975 )
976 UnicodeStructure = (
977 ('FileNameLength','<L-FileName','len(FileName)*2'),
978 ('EaSize','<L=0'),
979 ('ShortNameLength','<B=0'),
980 ('Reserved','<B=0'),
981 ('ShortName','24s'),
982 ('Reserved','<H=0'),
983 ('FileID','<q=0'),
984 ('FileName',':'),
985 )
987# SMB_FIND_FILE_DIRECTORY_INFO level
988class SMBFindFileDirectoryInfo(AsciiOrUnicodeStructure):
989 commonHdr = (
990 ('NextEntryOffset','<L=0'),
991 ('FileIndex','<L=0'),
992 ('CreationTime','<q'),
993 ('LastAccessTime','<q'),
994 ('LastWriteTime','<q'),
995 ('LastChangeTime','<q'),
996 ('EndOfFile','<q=0'),
997 ('AllocationSize','<q=1'),
998 ('ExtFileAttributes','<L=0'),
999 )
1000 AsciiStructure = (
1001 ('FileNameLength','<L-FileName','len(FileName)'),
1002 ('FileName','z'),
1003 )
1004 UnicodeStructure = (
1005 ('FileNameLength','<L-FileName','len(FileName)*2'),
1006 ('FileName',':'),
1007 )
1009# SMB_FIND_FILE_NAMES_INFO level
1010class SMBFindFileNamesInfo(AsciiOrUnicodeStructure):
1011 commonHdr = (
1012 ('NextEntryOffset','<L=0'),
1013 ('FileIndex','<L=0'),
1014 )
1015 AsciiStructure = (
1016 ('FileNameLength','<L-FileName','len(FileName)'),
1017 ('FileName','z'),
1018 )
1019 UnicodeStructure = (
1020 ('FileNameLength','<L-FileName','len(FileName)*2'),
1021 ('FileName',':'),
1022 )
1024# SMB_FIND_FILE_FULL_DIRECTORY_INFO level
1025class SMBFindFileFullDirectoryInfo(AsciiOrUnicodeStructure):
1026 commonHdr = (
1027 ('NextEntryOffset','<L=0'),
1028 ('FileIndex','<L=0'),
1029 ('CreationTime','<q'),
1030 ('LastAccessTime','<q'),
1031 ('LastWriteTime','<q'),
1032 ('LastChangeTime','<q'),
1033 ('EndOfFile','<q=0'),
1034 ('AllocationSize','<q=1'),
1035 ('ExtFileAttributes','<L=0'),
1036 )
1037 AsciiStructure = (
1038 ('FileNameLength','<L-FileName','len(FileName)'),
1039 ('EaSize','<L'),
1040 ('FileName','z'),
1041 )
1042 UnicodeStructure = (
1043 ('FileNameLength','<L-FileName','len(FileName)*2'),
1044 ('EaSize','<L'),
1045 ('FileName',':'),
1046 )
1048# SMB_FIND_INFO_STANDARD level
1049class SMBFindInfoStandard(AsciiOrUnicodeStructure):
1050 commonHdr = (
1051 ('ResumeKey','<L=0xff'),
1052 ('CreationDate','<H=0'),
1053 ('CreationTime','<H=0'),
1054 ('LastAccessDate','<H=0'),
1055 ('LastAccessTime','<H=0'),
1056 ('LastWriteDate','<H=0'),
1057 ('LastWriteTime','<H=0'),
1058 ('EaSize','<L'),
1059 ('AllocationSize','<L=1'),
1060 ('ExtFileAttributes','<H=0'),
1061 )
1062 AsciiStructure = (
1063 ('FileNameLength','<B-FileName','len(FileName)'),
1064 ('FileName','z'),
1065 )
1066 UnicodeStructure = (
1067 ('FileNameLength','<B-FileName','len(FileName)*2'),
1068 ('FileName',':'),
1069 )
1071# SET_FILE_INFORMATION structures
1072# SMB_SET_FILE_DISPOSITION_INFO
1073class SMBSetFileDispositionInfo(Structure):
1074 structure = (
1075 ('DeletePending','<B'),
1076 )
1078# SMB_SET_FILE_BASIC_INFO
1079class SMBSetFileBasicInfo(Structure):
1080 structure = (
1081 ('CreationTime','<q'),
1082 ('LastAccessTime','<q'),
1083 ('LastWriteTime','<q'),
1084 ('ChangeTime','<q'),
1085 ('ExtFileAttributes','<H'),
1086 ('Reserved','<L'),
1087 )
1089# FILE_STREAM_INFORMATION
1090class SMBFileStreamInformation(Structure):
1091 commonHdr = (
1092 ('NextEntryOffset','<L=0'),
1093 ('StreamNameLength','<L=0'),
1094 ('StreamSize','<q=0'),
1095 ('StreamAllocationSize','<q=0'),
1096 ('StreamName',':=""'),
1097 )
1099# FILE_NETWORK_OPEN_INFORMATION
1100class SMBFileNetworkOpenInfo(Structure):
1101 structure = (
1102 ('CreationTime','<q=0'),
1103 ('LastAccessTime','<q=0'),
1104 ('LastWriteTime','<q=0'),
1105 ('ChangeTime','<q=0'),
1106 ('AllocationSize','<q=0'),
1107 ('EndOfFile','<q=0'),
1108 ('FileAttributes','<L=0'),
1109 ('Reserved','<L=0'),
1110 )
1112# SMB_SET_FILE_END_OF_FILE_INFO
1113class SMBSetFileEndOfFileInfo(Structure):
1114 structure = (
1115 ('EndOfFile','<q'),
1116 )
1118# TRANS2_FIND_NEXT2
1119class SMBFindNext2_Parameters(AsciiOrUnicodeStructure):
1120 commonHdr = (
1121 ('SID','<H'),
1122 ('SearchCount','<H'),
1123 ('InformationLevel','<H'),
1124 ('ResumeKey','<L'),
1125 ('Flags','<H'),
1126 )
1127 AsciiStructure = (
1128 ('FileName','z'),
1129 )
1130 UnicodeStructure = (
1131 ('FileName','u'),
1132 )
1134class SMBFindNext2Response_Parameters(Structure):
1135 structure = (
1136 ('SearchCount','<H'),
1137 ('EndOfSearch','<H=1'),
1138 ('EaErrorOffset','<H=0'),
1139 ('LastNameOffset','<H=0'),
1140 )
1142class SMBFindNext2_Data(Structure):
1143 structure = (
1144 ('GetExtendedAttributesListLength','_-GetExtendedAttributesList', 'self["GetExtendedAttributesListLength"]'),
1145 ('GetExtendedAttributesList',':'),
1146 )
1149# TRANS2_FIND_FIRST2
1150class SMBFindFirst2Response_Parameters(Structure):
1151 structure = (
1152 ('SID','<H'),
1153 ('SearchCount','<H'),
1154 ('EndOfSearch','<H=1'),
1155 ('EaErrorOffset','<H=0'),
1156 ('LastNameOffset','<H=0'),
1157 )
1159class SMBFindFirst2_Parameters(AsciiOrUnicodeStructure):
1160 commonHdr = (
1161 ('SearchAttributes','<H'),
1162 ('SearchCount','<H'),
1163 ('Flags','<H'),
1164 ('InformationLevel','<H'),
1165 ('SearchStorageType','<L'),
1166 )
1167 AsciiStructure = (
1168 ('FileName','z'),
1169 )
1170 UnicodeStructure = (
1171 ('FileName','u'),
1172 )
1174class SMBFindFirst2_Data(Structure):
1175 structure = (
1176 ('GetExtendedAttributesListLength','_-GetExtendedAttributesList', 'self["GetExtendedAttributesListLength"]'),
1177 ('GetExtendedAttributesList',':'),
1178 )
1180# TRANS2_SET_PATH_INFORMATION
1181class SMBSetPathInformation_Parameters(AsciiOrUnicodeStructure):
1182 commonHdr = (
1183 ('InformationLevel','<H'),
1184 ('Reserved','<L'),
1185 )
1186 AsciiStructure = (
1187 ('FileName','z'),
1188 )
1189 UnicodeStructure = (
1190 ('FileName','u'),
1191 )
1193class SMBSetPathInformationResponse_Parameters(Structure):
1194 structure = (
1195 ('EaErrorOffset','<H=0'),
1196 )
1198# TRANS2_SET_FILE_INFORMATION
1199class SMBSetFileInformation_Parameters(Structure):
1200 structure = (
1201 ('FID','<H'),
1202 ('InformationLevel','<H'),
1203 ('Reserved','<H'),
1204 )
1206class SMBSetFileInformationResponse_Parameters(Structure):
1207 structure = (
1208 ('EaErrorOffset','<H=0'),
1209 )
1211# TRANS2_QUERY_FILE_INFORMATION
1212class SMBQueryFileInformation_Parameters(Structure):
1213 structure = (
1214 ('FID','<H'),
1215 ('InformationLevel','<H'),
1216 )
1218class SMBQueryFileInformationResponse_Parameters(Structure):
1219 structure = (
1220 ('EaErrorOffset','<H=0'),
1221 )
1223class SMBQueryFileInformation_Data(Structure):
1224 structure = (
1225 ('GetExtendedAttributeList',':'),
1226 )
1228# TRANS2_QUERY_PATH_INFORMATION
1229class SMBQueryPathInformationResponse_Parameters(Structure):
1230 structure = (
1231 ('EaErrorOffset','<H=0'),
1232 )
1234class SMBQueryPathInformation_Parameters(AsciiOrUnicodeStructure):
1235 commonHdr = (
1236 ('InformationLevel','<H'),
1237 ('Reserved','<L=0'),
1238 )
1239 AsciiStructure = (
1240 ('FileName','z'),
1241 )
1242 UnicodeStructure = (
1243 ('FileName','u'),
1244 )
1246class SMBQueryPathInformation_Data(Structure):
1247 structure = (
1248 ('GetExtendedAttributeList',':'),
1249 )
1252# SMB_QUERY_FILE_EA_INFO
1253class SMBQueryFileEaInfo(Structure):
1254 structure = (
1255 ('EaSize','<L=0'),
1256 )
1258# SMB_QUERY_FILE_BASIC_INFO
1259class SMBQueryFileBasicInfo(Structure):
1260 structure = (
1261 ('CreationTime','<q'),
1262 ('LastAccessTime','<q'),
1263 ('LastWriteTime','<q'),
1264 ('LastChangeTime','<q'),
1265 ('ExtFileAttributes','<L'),
1266 #('Reserved','<L=0'),
1267 )
1269# SMB_QUERY_FILE_STANDARD_INFO
1270class SMBQueryFileStandardInfo(Structure):
1271 structure = (
1272 ('AllocationSize','<q'),
1273 ('EndOfFile','<q'),
1274 ('NumberOfLinks','<L=0'),
1275 ('DeletePending','<B=0'),
1276 ('Directory','<B'),
1277 )
1279# SMB_QUERY_FILE_ALL_INFO
1280class SMBQueryFileAllInfo(Structure):
1281 structure = (
1282 ('CreationTime','<q'),
1283 ('LastAccessTime','<q'),
1284 ('LastWriteTime','<q'),
1285 ('LastChangeTime','<q'),
1286 ('ExtFileAttributes','<L'),
1287 ('Reserved','<L=0'),
1288 ('AllocationSize','<q'),
1289 ('EndOfFile','<q'),
1290 ('NumberOfLinks','<L=0'),
1291 ('DeletePending','<B=0'),
1292 ('Directory','<B'),
1293 ('Reserved','<H=0'),
1294 ('EaSize','<L=0'),
1295 ('FileNameLength','<L-FileName','len(FileName)'),
1296 ('FileName',':'),
1297 )
1299# \PIPE\LANMAN NetShareEnum
1300class SMBNetShareEnum(Structure):
1301 structure = (
1302 ('RAPOpcode','<H=0'),
1303 ('ParamDesc','z'),
1304 ('DataDesc','z'),
1305 ('InfoLevel','<H'),
1306 ('ReceiveBufferSize','<H'),
1307 )
1309class SMBNetShareEnumResponse(Structure):
1310 structure = (
1311 ('Status','<H=0'),
1312 ('Convert','<H=0'),
1313 ('EntriesReturned','<H'),
1314 ('EntriesAvailable','<H'),
1315 )
1317class NetShareInfo1(Structure):
1318 structure = (
1319 ('NetworkName','13s'),
1320 ('Pad','<B=0'),
1321 ('Type','<H=0'),
1322 ('RemarkOffsetLow','<H=0'),
1323 ('RemarkOffsetHigh','<H=0'),
1324 )
1326# \PIPE\LANMAN NetServerGetInfo
1327class SMBNetServerGetInfoResponse(Structure):
1328 structure = (
1329 ('Status','<H=0'),
1330 ('Convert','<H=0'),
1331 ('TotalBytesAvailable','<H'),
1332 )
1334class SMBNetServerInfo1(Structure):
1335 # Level 1 Response
1336 structure = (
1337 ('ServerName','16s'),
1338 ('MajorVersion','B=5'),
1339 ('MinorVersion','B=0'),
1340 ('ServerType','<L=3'),
1341 ('ServerCommentLow','<H=0'),
1342 ('ServerCommentHigh','<H=0'),
1343 )
1345# \PIPE\LANMAN NetShareGetInfo
1346class SMBNetShareGetInfo(Structure):
1347 structure = (
1348 ('RAPOpcode','<H=0'),
1349 ('ParamDesc','z'),
1350 ('DataDesc','z'),
1351 ('ShareName','z'),
1352 ('InfoLevel','<H'),
1353 ('ReceiveBufferSize','<H'),
1354 )
1356class SMBNetShareGetInfoResponse(Structure):
1357 structure = (
1358 ('Status','<H=0'),
1359 ('Convert','<H=0'),
1360 ('TotalBytesAvailable','<H'),
1361 )
1363############# Security Features
1364class SecurityFeatures(Structure):
1365 structure = (
1366 ('Key','<L=0'),
1367 ('CID','<H=0'),
1368 ('SequenceNumber','<H=0'),
1369 )
1371############# SMB_COM_QUERY_INFORMATION2 (0x23)
1372class SMBQueryInformation2_Parameters(Structure):
1373 structure = (
1374 ('Fid','<H'),
1375 )
1377class SMBQueryInformation2Response_Parameters(Structure):
1378 structure = (
1379 ('CreateDate','<H'),
1380 ('CreationTime','<H'),
1381 ('LastAccessDate','<H'),
1382 ('LastAccessTime','<H'),
1383 ('LastWriteDate','<H'),
1384 ('LastWriteTime','<H'),
1385 ('FileDataSize','<L'),
1386 ('FileAllocationSize','<L'),
1387 ('FileAttributes','<L'),
1388 )
1392############# SMB_COM_SESSION_SETUP_ANDX (0x73)
1393class SMBSessionSetupAndX_Parameters(SMBAndXCommand_Parameters):
1394 structure = (
1395 ('MaxBuffer','<H'),
1396 ('MaxMpxCount','<H'),
1397 ('VCNumber','<H'),
1398 ('SessionKey','<L'),
1399 ('AnsiPwdLength','<H'),
1400 ('UnicodePwdLength','<H'),
1401 ('_reserved','<L=0'),
1402 ('Capabilities','<L'),
1403 )
1405class SMBSessionSetupAndX_Extended_Parameters(SMBAndXCommand_Parameters):
1406 structure = (
1407 ('MaxBufferSize','<H'),
1408 ('MaxMpxCount','<H'),
1409 ('VcNumber','<H'),
1410 ('SessionKey','<L'),
1411 ('SecurityBlobLength','<H'),
1412 ('Reserved','<L=0'),
1413 ('Capabilities','<L'),
1414 )
1416class SMBSessionSetupAndX_Data(AsciiOrUnicodeStructure):
1417 AsciiStructure = (
1418 ('AnsiPwdLength','_-AnsiPwd','self["AnsiPwdLength"]'),
1419 ('UnicodePwdLength','_-UnicodePwd','self["UnicodePwdLength"]'),
1420 ('AnsiPwd',':=""'),
1421 ('UnicodePwd',':=""'),
1422 ('Account','z=""'),
1423 ('PrimaryDomain','z=""'),
1424 ('NativeOS','z=""'),
1425 ('NativeLanMan','z=""'),
1426 )
1428 UnicodeStructure = (
1429 ('AnsiPwdLength','_-AnsiPwd','self["AnsiPwdLength"]'),
1430 ('UnicodePwdLength','_-UnicodePwd','self["UnicodePwdLength"]'),
1431 ('AnsiPwd',':=""'),
1432 ('UnicodePwd',':=""'),
1433 ('Account','u=""'),
1434 ('PrimaryDomain','u=""'),
1435 ('NativeOS','u=""'),
1436 ('NativeLanMan','u=""'),
1437 )
1439class SMBSessionSetupAndX_Extended_Data(AsciiOrUnicodeStructure):
1440 AsciiStructure = (
1441 ('SecurityBlobLength','_-SecurityBlob','self["SecurityBlobLength"]'),
1442 ('SecurityBlob',':'),
1443 ('NativeOS','z=""'),
1444 ('NativeLanMan','z=""'),
1445 )
1447 UnicodeStructure = (
1448 ('SecurityBlobLength','_-SecurityBlob','self["SecurityBlobLength"]'),
1449 ('SecurityBlob',':'),
1450 ('NativeOS','u=""'),
1451 ('NativeLanMan','u=""'),
1452 )
1454class SMBSessionSetupAndXResponse_Parameters(SMBAndXCommand_Parameters):
1455 structure = (
1456 ('Action','<H'),
1457 )
1459class SMBSessionSetupAndX_Extended_Response_Parameters(SMBAndXCommand_Parameters):
1460 structure = (
1461 ('Action','<H=0'),
1462 ('SecurityBlobLength','<H'),
1463 )
1465class SMBSessionSetupAndXResponse_Data(AsciiOrUnicodeStructure):
1466 AsciiStructure = (
1467 ('NativeOS','z=""'),
1468 ('NativeLanMan','z=""'),
1469 ('PrimaryDomain','z=""'),
1470 )
1472 UnicodeStructure = (
1473 ('NativeOS','u=""'),
1474 ('NativeLanMan','u=""'),
1475 ('PrimaryDomain','u=""'),
1476 )
1478class SMBSessionSetupAndX_Extended_Response_Data(AsciiOrUnicodeStructure):
1479 AsciiStructure = (
1480 ('SecurityBlobLength','_-SecurityBlob','self["SecurityBlobLength"]'),
1481 ('SecurityBlob',':'),
1482 ('NativeOS','z=""'),
1483 ('NativeLanMan','z=""'),
1484 )
1486 UnicodeStructure = (
1487 ('SecurityBlobLength','_-SecurityBlob','self["SecurityBlobLength"]'),
1488 ('SecurityBlob',':'),
1489 ('PadLen','_-Pad','1 if (len(self["SecurityBlob"]) % 2 == 0) else 0'),
1490 ('Pad',':=""'),
1491 ('NativeOS','u=""'),
1492 ('NativeLanMan','u=""'),
1493 )
1494 def getData(self):
1495 if self.structure == self.UnicodeStructure:
1496 if len(str(self['SecurityBlob'])) % 2 == 0:
1497 self['Pad'] = '\x00'
1498 return AsciiOrUnicodeStructure.getData(self)
1500############# SMB_COM_TREE_CONNECT (0x70)
1501class SMBTreeConnect_Parameters(SMBCommand_Parameters):
1502 structure = (
1503 )
1505class SMBTreeConnect_Data(SMBCommand_Parameters):
1506 structure = (
1507 ('PathFormat','"\x04'),
1508 ('Path','z'),
1509 ('PasswordFormat','"\x04'),
1510 ('Password','z'),
1511 ('ServiceFormat','"\x04'),
1512 ('Service','z'),
1513 )
1515############# SMB_COM_TREE_CONNECT_ANDX (0x75)
1516class SMBTreeConnectAndX_Parameters(SMBAndXCommand_Parameters):
1517 structure = (
1518 ('Flags','<H=0'),
1519 ('PasswordLength','<H'),
1520 )
1522class SMBTreeConnectAndXResponse_Parameters(SMBAndXCommand_Parameters):
1523 structure = (
1524 ('OptionalSupport','<H=0'),
1525 )
1527class SMBTreeConnectAndXExtendedResponse_Parameters(SMBAndXCommand_Parameters):
1528 structure = (
1529 ('OptionalSupport','<H=1'),
1530 ('MaximalShareAccessRights','<L=0x1fffff'),
1531 ('GuestMaximalShareAccessRights','<L=0x1fffff'),
1532 )
1534class SMBTreeConnectAndX_Data(AsciiOrUnicodeStructure):
1535 AsciiStructure = (
1536 ('_PasswordLength','_-Password','self["_PasswordLength"]'),
1537 ('Password',':'),
1538 ('Path','z'),
1539 ('Service','z'),
1540 )
1542 UnicodeStructure = (
1543 ('_PasswordLength','_-Password','self["_PasswordLength"] if self["_PasswordLength"] > 0 else 1'),
1544 ('Password',':'),
1545 ('Path','u'),
1546 ('Service','z'),
1547 )
1549class SMBTreeConnectAndXResponse_Data(AsciiOrUnicodeStructure):
1550 AsciiStructure = (
1551 ('Service','z'),
1552 ('PadLen','_-Pad','self["PadLen"]'),
1553 ('Pad',':=""'),
1554 ('NativeFileSystem','z'),
1555 )
1556 UnicodeStructure = (
1557 ('Service','z'),
1558 ('PadLen','_-Pad','self["PadLen"]'),
1559 ('Pad',':=""'),
1560 ('NativeFileSystem','u'),
1561 )
1563############# SMB_COM_NT_CREATE_ANDX (0xA2)
1564class SMBNtCreateAndX_Parameters(SMBAndXCommand_Parameters):
1565 structure = (
1566 ('_reserved', 'B=0'),
1567 ('FileNameLength','<H'), # NameLength
1568 ('CreateFlags','<L'), # Flags
1569 ('RootFid','<L=0'), # RootDirectoryFID
1570 ('AccessMask','<L'), # DesiredAccess
1571 ('AllocationSizeLo','<L=0'), # AllocationSize
1572 ('AllocationSizeHi','<L=0'),
1573 ('FileAttributes','<L=0'), # ExtFileAttributes
1574 ('ShareAccess','<L=3'), #
1575 ('Disposition','<L=1'), # CreateDisposition
1576 ('CreateOptions','<L'), # CreateOptions
1577 ('Impersonation','<L=2'),
1578 ('SecurityFlags','B=3'),
1579 )
1581class SMBNtCreateAndXResponse_Parameters(SMBAndXCommand_Parameters):
1582 # XXX Is there a memory leak in the response for NTCreate (where the Data section would be) in Win 2000, Win XP, and Win 2003?
1583 structure = (
1584 ('OplockLevel', 'B=0'),
1585 ('Fid','<H'),
1586 ('CreateAction','<L'),
1587 ('CreateTime','<q=0'),
1588 ('LastAccessTime','<q=0'),
1589 ('LastWriteTime','<q=0'),
1590 ('LastChangeTime','<q=0'),
1591 ('FileAttributes','<L=0x80'),
1592 ('AllocationSize','<q=0'),
1593 ('EndOfFile','<q=0'),
1594 ('FileType','<H=0'),
1595 ('IPCState','<H=0'),
1596 ('IsDirectory','B'),
1597 )
1599class SMBNtCreateAndXExtendedResponse_Parameters(SMBAndXCommand_Parameters):
1600 # [MS-SMB] Extended response description
1601 structure = (
1602 ('OplockLevel', 'B=0'),
1603 ('Fid','<H'),
1604 ('CreateAction','<L'),
1605 ('CreateTime','<q=0'),
1606 ('LastAccessTime','<q=0'),
1607 ('LastWriteTime','<q=0'),
1608 ('LastChangeTime','<q=0'),
1609 ('FileAttributes','<L=0x80'),
1610 ('AllocationSize','<q=0'),
1611 ('EndOfFile','<q=0'),
1612 ('FileType','<H=0'),
1613 ('IPCState','<H=0'),
1614 ('IsDirectory','B'),
1615 ('VolumeGUID','16s'),
1616 ('FileIdLow','<L=0'),
1617 ('FileIdHigh','<L=0'),
1618 ('MaximalAccessRights','<L=0x12019b'),
1619 ('GuestMaximalAccessRights','<L=0x120089'),
1620 )
1622class SMBNtCreateAndX_Data(AsciiOrUnicodeStructure):
1623 AsciiStructure = (
1624 ('FileName','z'),
1625 )
1626 UnicodeStructure = (
1627 ('Pad','B'),
1628 ('FileName','u'),
1629 )
1631############# SMB_COM_OPEN_ANDX (0xD2)
1632class SMBOpenAndX_Parameters(SMBAndXCommand_Parameters):
1633 structure = (
1634 ('Flags','<H=0'),
1635 ('DesiredAccess','<H=0'),
1636 ('SearchAttributes','<H=0'),
1637 ('FileAttributes','<H=0'),
1638 ('CreationTime','<L=0'),
1639 ('OpenMode','<H=1'), # SMB_O_OPEN = 1
1640 ('AllocationSize','<L=0'),
1641 ('Reserved','8s=""'),
1642 )
1644class SMBOpenAndX_Data(SMBNtCreateAndX_Data):
1645 pass
1647class SMBOpenAndXResponse_Parameters(SMBAndXCommand_Parameters):
1648 structure = (
1649 ('Fid','<H=0'),
1650 ('FileAttributes','<H=0'),
1651 ('LastWriten','<L=0'),
1652 ('FileSize','<L=0'),
1653 ('GrantedAccess','<H=0'),
1654 ('FileType','<H=0'),
1655 ('IPCState','<H=0'),
1656 ('Action','<H=0'),
1657 ('ServerFid','<L=0'),
1658 ('_reserved','<H=0'),
1659 )
1661############# SMB_COM_WRITE (0x0B)
1662class SMBWrite_Parameters(SMBCommand_Parameters):
1663 structure = (
1664 ('Fid','<H'),
1665 ('Count','<H'),
1666 ('Offset','<L'),
1667 ('Remaining','<H'),
1668 )
1670class SMBWriteResponse_Parameters(SMBCommand_Parameters):
1671 structure = (
1672 ('Count','<H'),
1673 )
1675class SMBWrite_Data(Structure):
1676 structure = (
1677 ('BufferFormat','<B=1'),
1678 ('DataLength','<H-Data'),
1679 ('Data',':'),
1680 )
1683############# SMB_COM_WRITE_ANDX (0x2F)
1684class SMBWriteAndX_Parameters(SMBAndXCommand_Parameters):
1685 structure = (
1686 ('Fid','<H=0'),
1687 ('Offset','<L=0'),
1688 ('_reserved','<L=0xff'),
1689 ('WriteMode','<H=8'),
1690 ('Remaining','<H=0'),
1691 ('DataLength_Hi','<H=0'),
1692 ('DataLength','<H=0'),
1693 ('DataOffset','<H=0'),
1694 ('HighOffset','<L=0'),
1695 )
1697class SMBWriteAndX_Data_Short(Structure):
1698 structure = (
1699 ('_PadLen','_-Pad','self["DataOffset"] - 59'),
1700 ('Pad',':'),
1701 #('Pad','<B=0'),
1702 ('DataLength','_-Data','self["DataLength"]'),
1703 ('Data',':'),
1704 )
1706class SMBWriteAndX_Data(Structure):
1707 structure = (
1708 ('_PadLen','_-Pad','self["DataOffset"] - 63'),
1709 ('Pad',':'),
1710 #('Pad','<B=0'),
1711 ('DataLength','_-Data','self["DataLength"]'),
1712 ('Data',':'),
1713 )
1716class SMBWriteAndX_Parameters_Short(SMBAndXCommand_Parameters):
1717 structure = (
1718 ('Fid','<H'),
1719 ('Offset','<L'),
1720 ('_reserved','<L=0xff'),
1721 ('WriteMode','<H=8'),
1722 ('Remaining','<H'),
1723 ('DataLength_Hi','<H=0'),
1724 ('DataLength','<H'),
1725 ('DataOffset','<H=0'),
1726 )
1728class SMBWriteAndXResponse_Parameters(SMBAndXCommand_Parameters):
1729 structure = (
1730 ('Count','<H'),
1731 ('Available','<H'),
1732 ('Reserved','<L=0'),
1733 )
1735############# SMB_COM_WRITE_RAW (0x1D)
1736class SMBWriteRaw_Parameters(SMBCommand_Parameters):
1737 structure = (
1738 ('Fid','<H'),
1739 ('Count','<H'),
1740 ('_reserved','<H=0'),
1741 ('Offset','<L'),
1742 ('Timeout','<L=0'),
1743 ('WriteMode','<H=0'),
1744 ('_reserved2','<L=0'),
1745 ('DataLength','<H'),
1746 ('DataOffset','<H=0'),
1747 )
1749############# SMB_COM_READ (0x0A)
1750class SMBRead_Parameters(SMBCommand_Parameters):
1751 structure = (
1752 ('Fid','<H'),
1753 ('Count','<H'),
1754 ('Offset','<L'),
1755 ('Remaining','<H=Count'),
1756 )
1758class SMBReadResponse_Parameters(Structure):
1759 structure = (
1760 ('Count','<H=0'),
1761 ('_reserved','8s=""'),
1762 )
1764class SMBReadResponse_Data(Structure):
1765 structure = (
1766 ('BufferFormat','<B=0x1'),
1767 ('DataLength','<H-Data'),
1768 ('Data',':'),
1769 )
1771############# SMB_COM_READ_RAW (0x1A)
1772class SMBReadRaw_Parameters(SMBCommand_Parameters):
1773 structure = (
1774 ('Fid','<H'),
1775 ('Offset','<L'),
1776 ('MaxCount','<H'),
1777 ('MinCount','<H=MaxCount'),
1778 ('Timeout','<L=0'),
1779 ('_reserved','<H=0'),
1780 )
1782############# SMB_COM_NT_TRANSACT (0xA0)
1783class SMBNTTransaction_Parameters(SMBCommand_Parameters):
1784 structure = (
1785 ('MaxSetupCount','<B=0'),
1786 ('Reserved1','<H=0'),
1787 ('TotalParameterCount','<L'),
1788 ('TotalDataCount','<L'),
1789 ('MaxParameterCount','<L=1024'),
1790 ('MaxDataCount','<L=65504'),
1791 ('ParameterCount','<L'),
1792 ('ParameterOffset','<L'),
1793 ('DataCount','<L'),
1794 ('DataOffset','<L'),
1795 ('SetupCount','<B=len(Setup)//2'),
1796 ('Function','<H=0'),
1797 ('SetupLength','_-Setup','SetupCount*2'),
1798 ('Setup',':'),
1799 )
1801class SMBNTTransactionResponse_Parameters(SMBCommand_Parameters):
1802 structure = (
1803 ('Reserved1','3s=""'),
1804 ('TotalParameterCount','<L'),
1805 ('TotalDataCount','<L'),
1806 ('ParameterCount','<L'),
1807 ('ParameterOffset','<L'),
1808 ('ParameterDisplacement','<L=0'),
1809 ('DataCount','<L'),
1810 ('DataOffset','<L'),
1811 ('DataDisplacement','<L=0'),
1812 ('SetupCount','<B=0'),
1813 ('SetupLength','_-Setup','SetupCount*2'),
1814 ('Setup',':'),
1815 )
1817class SMBNTTransaction_Data(Structure):
1818 structure = (
1819 ('Pad1Length','_-Pad1','self["Pad1Length"]'),
1820 ('Pad1',':'),
1821 ('NT_Trans_ParametersLength','_-NT_Trans_Parameters','self["NT_Trans_ParametersLength"]'),
1822 ('NT_Trans_Parameters',':'),
1823 ('Pad2Length','_-Pad2','self["Pad2Length"]'),
1824 ('Pad2',':'),
1825 ('NT_Trans_DataLength','_-NT_Trans_Data','self["NT_Trans_DataLength"]'),
1826 ('NT_Trans_Data',':'),
1827 )
1829class SMBNTTransactionResponse_Data(Structure):
1830 structure = (
1831 ('Pad1Length','_-Pad1','self["Pad1Length"]'),
1832 ('Pad1',':'),
1833 ('Trans_ParametersLength','_-Trans_Parameters','self["Trans_ParametersLength"]'),
1834 ('Trans_Parameters',':'),
1835 ('Pad2Length','_-Pad2','self["Pad2Length"]'),
1836 ('Pad2',':'),
1837 ('Trans_DataLength','_-Trans_Data','self["Trans_DataLength"]'),
1838 ('Trans_Data',':'),
1839 )
1842############# SMB_COM_TRANSACTION2_SECONDARY (0x33)
1843class SMBTransaction2Secondary_Parameters(SMBCommand_Parameters):
1844 structure = (
1845 ('TotalParameterCount','<H'),
1846 ('TotalDataCount','<H'),
1847 ('ParameterCount','<H'),
1848 ('ParameterOffset','<H'),
1849 ('ParameterDisplacement','<H'),
1850 ('DataCount','<H'),
1851 ('DataOffset','<H'),
1852 ('DataDisplacement','<H=0'),
1853 ('FID','<H'),
1854 )
1856class SMBTransaction2Secondary_Data(Structure):
1857 structure = (
1858 ('Pad1Length','_-Pad1','self["Pad1Length"]'),
1859 ('Pad1',':'),
1860 ('Trans_ParametersLength','_-Trans_Parameters','self["Trans_ParametersLength"]'),
1861 ('Trans_Parameters',':'),
1862 ('Pad2Length','_-Pad2','self["Pad2Length"]'),
1863 ('Pad2',':'),
1864 ('Trans_DataLength','_-Trans_Data','self["Trans_DataLength"]'),
1865 ('Trans_Data',':'),
1866 )
1869############# SMB_COM_TRANSACTION2 (0x32)
1871class SMBTransaction2_Parameters(SMBCommand_Parameters):
1872 structure = (
1873 ('TotalParameterCount','<H'),
1874 ('TotalDataCount','<H'),
1875 ('MaxParameterCount','<H=1024'),
1876 ('MaxDataCount','<H=65504'),
1877 ('MaxSetupCount','<B=0'),
1878 ('Reserved1','<B=0'),
1879 ('Flags','<H=0'),
1880 ('Timeout','<L=0'),
1881 ('Reserved2','<H=0'),
1882 ('ParameterCount','<H'),
1883 ('ParameterOffset','<H'),
1884 ('DataCount','<H'),
1885 ('DataOffset','<H'),
1886 ('SetupCount','<B=len(Setup)//2'),
1887 ('Reserved3','<B=0'),
1888 ('SetupLength','_-Setup','SetupCount*2'),
1889 ('Setup',':'),
1890 )
1892class SMBTransaction2Response_Parameters(SMBCommand_Parameters):
1893 structure = (
1894 ('TotalParameterCount','<H'),
1895 ('TotalDataCount','<H'),
1896 ('Reserved1','<H=0'),
1897 ('ParameterCount','<H'),
1898 ('ParameterOffset','<H'),
1899 ('ParameterDisplacement','<H=0'),
1900 ('DataCount','<H'),
1901 ('DataOffset','<H'),
1902 ('DataDisplacement','<H=0'),
1903 ('SetupCount','<B=0'),
1904 ('Reserved2','<B=0'),
1905 ('SetupLength','_-Setup','SetupCount*2'),
1906 ('Setup',':'),
1907 )
1909class SMBTransaction2_Data(Structure):
1910 structure = (
1911# ('NameLength','_-Name','1'),
1912# ('Name',':'),
1913 ('Pad1Length','_-Pad1','self["Pad1Length"]'),
1914 ('Pad1',':'),
1915 ('Trans_ParametersLength','_-Trans_Parameters','self["Trans_ParametersLength"]'),
1916 ('Trans_Parameters',':'),
1917 ('Pad2Length','_-Pad2','self["Pad2Length"]'),
1918 ('Pad2',':'),
1919 ('Trans_DataLength','_-Trans_Data','self["Trans_DataLength"]'),
1920 ('Trans_Data',':'),
1921 )
1923class SMBTransaction2Response_Data(Structure):
1924 structure = (
1925 ('Pad1Length','_-Pad1','self["Pad1Length"]'),
1926 ('Pad1',':'),
1927 ('Trans_ParametersLength','_-Trans_Parameters','self["Trans_ParametersLength"]'),
1928 ('Trans_Parameters',':'),
1929 ('Pad2Length','_-Pad2','self["Pad2Length"]'),
1930 ('Pad2',':'),
1931 ('Trans_DataLength','_-Trans_Data','self["Trans_DataLength"]'),
1932 ('Trans_Data',':'),
1933 )
1935############# SMB_COM_QUERY_INFORMATION (0x08)
1937class SMBQueryInformation_Data(AsciiOrUnicodeStructure):
1938 AsciiStructure = (
1939 ('BufferFormat','B=4'),
1940 ('FileName','z'),
1941 )
1942 UnicodeStructure = (
1943 ('BufferFormat','B=4'),
1944 ('FileName','u'),
1945 )
1948class SMBQueryInformationResponse_Parameters(Structure):
1949 structure = (
1950 ('FileAttributes','<H'),
1951 ('LastWriteTime','<L'),
1952 ('FileSize','<L'),
1953 ('Reserved','"0123456789'),
1954 )
1956############# SMB_COM_TRANSACTION (0x25)
1957class SMBTransaction_Parameters(SMBCommand_Parameters):
1958 structure = (
1959 ('TotalParameterCount','<H'),
1960 ('TotalDataCount','<H'),
1961 ('MaxParameterCount','<H=1024'),
1962 ('MaxDataCount','<H=65504'),
1963 ('MaxSetupCount','<B=0'),
1964 ('Reserved1','<B=0'),
1965 ('Flags','<H=0'),
1966 ('Timeout','<L=0'),
1967 ('Reserved2','<H=0'),
1968 ('ParameterCount','<H'),
1969 ('ParameterOffset','<H'),
1970 ('DataCount','<H'),
1971 ('DataOffset','<H'),
1972 ('SetupCount','<B=len(Setup)//2'),
1973 ('Reserved3','<B=0'),
1974 ('SetupLength','_-Setup','SetupCount*2'),
1975 ('Setup',':'),
1976 )
1978class SMBTransactionResponse_Parameters(SMBCommand_Parameters):
1979 structure = (
1980 ('TotalParameterCount','<H'),
1981 ('TotalDataCount','<H'),
1982 ('Reserved1','<H=0'),
1983 ('ParameterCount','<H'),
1984 ('ParameterOffset','<H'),
1985 ('ParameterDisplacement','<H=0'),
1986 ('DataCount','<H'),
1987 ('DataOffset','<H'),
1988 ('DataDisplacement','<H=0'),
1989 ('SetupCount','<B'),
1990 ('Reserved2','<B=0'),
1991 ('SetupLength','_-Setup','SetupCount*2'),
1992 ('Setup',':'),
1993 )
1995# TODO: We should merge these both. But this will require fixing
1996# the instances where this structure is used on the client side
1997class SMBTransaction_SData(AsciiOrUnicodeStructure):
1998 AsciiStructure = (
1999 ('Name','z'),
2000 ('Trans_ParametersLength','_-Trans_Parameters'),
2001 ('Trans_Parameters',':'),
2002 ('Trans_DataLength','_-Trans_Data'),
2003 ('Trans_Data',':'),
2004 )
2005 UnicodeStructure = (
2006 ('Pad','B'),
2007 ('Name','u'),
2008 ('Trans_ParametersLength','_-Trans_Parameters'),
2009 ('Trans_Parameters',':'),
2010 ('Trans_DataLength','_-Trans_Data'),
2011 ('Trans_Data',':'),
2012 )
2014class SMBTransaction_Data(Structure):
2015 structure = (
2016 ('NameLength','_-Name'),
2017 ('Name',':'),
2018 ('Trans_ParametersLength','_-Trans_Parameters'),
2019 ('Trans_Parameters',':'),
2020 ('Trans_DataLength','_-Trans_Data'),
2021 ('Trans_Data',':'),
2022 )
2024class SMBTransactionResponse_Data(Structure):
2025 structure = (
2026 ('Trans_ParametersLength','_-Trans_Parameters'),
2027 ('Trans_Parameters',':'),
2028 ('Trans_DataLength','_-Trans_Data'),
2029 ('Trans_Data',':'),
2030 )
2032############# SMB_COM_READ_ANDX (0x2E)
2033class SMBReadAndX_Parameters(SMBAndXCommand_Parameters):
2034 structure = (
2035 ('Fid','<H'),
2036 ('Offset','<L'),
2037 ('MaxCount','<H'),
2038 ('MinCount','<H=MaxCount'),
2039 ('_reserved','<L=0x0'),
2040 ('Remaining','<H=MaxCount'),
2041 ('HighOffset','<L=0'),
2042 )
2044class SMBReadAndX_Parameters2(SMBAndXCommand_Parameters):
2045 structure = (
2046 ('Fid','<H'),
2047 ('Offset','<L'),
2048 ('MaxCount','<H'),
2049 ('MinCount','<H=MaxCount'),
2050 ('_reserved','<L=0xffffffff'),
2051 ('Remaining','<H=MaxCount'),
2052 )
2054class SMBReadAndXResponse_Parameters(SMBAndXCommand_Parameters):
2055 structure = (
2056 ('Remaining','<H=0'),
2057 ('DataMode','<H=0'),
2058 ('_reserved','<H=0'),
2059 ('DataCount','<H'),
2060 ('DataOffset','<H'),
2061 ('DataCount_Hi','<L'),
2062 ('_reserved2','6s=""'),
2063 )
2065############# SMB_COM_ECHO (0x2B)
2066class SMBEcho_Data(Structure):
2067 structure = (
2068 ('Data',':'),
2069 )
2071class SMBEcho_Parameters(Structure):
2072 structure = (
2073 ('EchoCount','<H'),
2074 )
2076class SMBEchoResponse_Data(Structure):
2077 structure = (
2078 ('Data',':'),
2079 )
2081class SMBEchoResponse_Parameters(Structure):
2082 structure = (
2083 ('SequenceNumber','<H=1'),
2084 )
2086############# SMB_COM_QUERY_INFORMATION_DISK (0x80)
2087class SMBQueryInformationDiskResponse_Parameters(Structure):
2088 structure = (
2089 ('TotalUnits','<H'),
2090 ('BlocksPerUnit','<H'),
2091 ('BlockSize','<H'),
2092 ('FreeUnits','<H'),
2093 ('Reserved','<H=0'),
2094 )
2097############# SMB_COM_LOGOFF_ANDX (0x74)
2098class SMBLogOffAndX(SMBAndXCommand_Parameters):
2099 strucure = ()
2101############# SMB_COM_CLOSE (0x04)
2102class SMBClose_Parameters(SMBCommand_Parameters):
2103 structure = (
2104 ('FID','<H'),
2105 ('Time','<L=0'),
2106 )
2108############# SMB_COM_FLUSH (0x05)
2109class SMBFlush_Parameters(SMBCommand_Parameters):
2110 structure = (
2111 ('FID','<H'),
2112 )
2114############# SMB_COM_CREATE_DIRECTORY (0x00)
2115class SMBCreateDirectory_Data(AsciiOrUnicodeStructure):
2116 AsciiStructure = (
2117 ('BufferFormat','<B=4'),
2118 ('DirectoryName','z'),
2119 )
2120 UnicodeStructure = (
2121 ('BufferFormat','<B=4'),
2122 ('DirectoryName','u'),
2123 )
2125############# SMB_COM_DELETE (0x06)
2126class SMBDelete_Data(AsciiOrUnicodeStructure):
2127 AsciiStructure = (
2128 ('BufferFormat','<B=4'),
2129 ('FileName','z'),
2130 )
2131 UnicodeStructure = (
2132 ('BufferFormat','<B=4'),
2133 ('FileName','u'),
2134 )
2136class SMBDelete_Parameters(Structure):
2137 structure = (
2138 ('SearchAttributes','<H'),
2139 )
2141############# SMB_COM_DELETE_DIRECTORY (0x01)
2142class SMBDeleteDirectory_Data(AsciiOrUnicodeStructure):
2143 AsciiStructure = (
2144 ('BufferFormat','<B=4'),
2145 ('DirectoryName','z'),
2146 )
2147 UnicodeStructure = (
2148 ('BufferFormat','<B=4'),
2149 ('DirectoryName','u'),
2150 )
2152############# SMB_COM_CHECK_DIRECTORY (0x10)
2153class SMBCheckDirectory_Data(AsciiOrUnicodeStructure):
2154 AsciiStructure = (
2155 ('BufferFormat','<B=4'),
2156 ('DirectoryName','z'),
2157 )
2158 UnicodeStructure = (
2159 ('BufferFormat','<B=4'),
2160 ('DirectoryName','u'),
2161 )
2163############# SMB_COM_RENAME (0x07)
2164class SMBRename_Parameters(SMBCommand_Parameters):
2165 structure = (
2166 ('SearchAttributes','<H'),
2167 )
2169class SMBRename_Data(AsciiOrUnicodeStructure):
2170 AsciiStructure = (
2171 ('BufferFormat1','<B=4'),
2172 ('OldFileName','z'),
2173 ('BufferFormat2','<B=4'),
2174 ('NewFileName','z'),
2175 )
2176 UnicodeStructure = (
2177 ('BufferFormat1','<B=4'),
2178 ('OldFileName','u'),
2179 ('BufferFormat2','<B=4'),
2180 ('Pad','B=0'),
2181 ('NewFileName','u'),
2182 )
2185############# SMB_COM_OPEN (0x02)
2186class SMBOpen_Parameters(SMBCommand_Parameters):
2187 structure = (
2188 ('DesiredAccess','<H=0'),
2189 ('SearchAttributes','<H=0'),
2190 )
2192class SMBOpen_Data(AsciiOrUnicodeStructure):
2193 AsciiStructure = (
2194 ('FileNameFormat','"\x04'),
2195 ('FileName','z'),
2196 )
2197 UnicodeStructure = (
2198 ('FileNameFormat','"\x04'),
2199 ('FileName','u'),
2200 )
2202class SMBOpenResponse_Parameters(SMBCommand_Parameters):
2203 structure = (
2204 ('Fid','<H=0'),
2205 ('FileAttributes','<H=0'),
2206 ('LastWriten','<L=0'),
2207 ('FileSize','<L=0'),
2208 ('GrantedAccess','<H=0'),
2209 )
2211############# EXTENDED SECURITY CLASSES
2212class SMBExtended_Security_Parameters(Structure):
2213 structure = (
2214 ('DialectIndex','<H'),
2215 ('SecurityMode','<B'),
2216 ('MaxMpxCount','<H'),
2217 ('MaxNumberVcs','<H'),
2218 ('MaxBufferSize','<L'),
2219 ('MaxRawSize','<L'),
2220 ('SessionKey','<L'),
2221 ('Capabilities','<L'),
2222 ('LowDateTime','<L'),
2223 ('HighDateTime','<L'),
2224 ('ServerTimeZone','<H'),
2225 ('ChallengeLength','<B'),
2226 )
2228class SMBExtended_Security_Data(Structure):
2229 structure = (
2230 ('ServerGUID','16s'),
2231 ('SecurityBlob',':'),
2232 )
2234class SMBNTLMDialect_Parameters(Structure):
2235 structure = (
2236 ('DialectIndex','<H'),
2237 ('SecurityMode','<B'),
2238 ('MaxMpxCount','<H'),
2239 ('MaxNumberVcs','<H'),
2240 ('MaxBufferSize','<L'),
2241 ('MaxRawSize','<L'),
2242 ('SessionKey','<L'),
2243 ('Capabilities','<L'),
2244 ('LowDateTime','<L'),
2245 ('HighDateTime','<L'),
2246 ('ServerTimeZone','<H'),
2247 ('ChallengeLength','<B'),
2248 )
2250class SMBNTLMDialect_Data(Structure):
2251 structure = (
2252 ('ChallengeLength','_-Challenge','self["ChallengeLength"]'),
2253 ('Challenge',':'),
2254 ('Payload',':'),
2255# For some reason on an old Linux this field is not present, we have to check this out. There must be a flag stating this.
2256 ('DomainName','_'),
2257 ('ServerName','_'),
2258 )
2259 def __init__(self,data = None, alignment = 0):
2260 Structure.__init__(self,data,alignment)
2261 #self['ChallengeLength']=8
2263 def fromString(self,data):
2264 Structure.fromString(self,data)
2265 self['DomainName'] = ''
2266 self['ServerName'] = ''
2268class SMB(object):
2270 class HostnameValidationException(Exception):
2271 pass
2273 # SMB Command Codes
2274 SMB_COM_CREATE_DIRECTORY = 0x00
2275 SMB_COM_DELETE_DIRECTORY = 0x01
2276 SMB_COM_OPEN = 0x02
2277 SMB_COM_CREATE = 0x03
2278 SMB_COM_CLOSE = 0x04
2279 SMB_COM_FLUSH = 0x05
2280 SMB_COM_DELETE = 0x06
2281 SMB_COM_RENAME = 0x07
2282 SMB_COM_QUERY_INFORMATION = 0x08
2283 SMB_COM_SET_INFORMATION = 0x09
2284 SMB_COM_READ = 0x0A
2285 SMB_COM_WRITE = 0x0B
2286 SMB_COM_LOCK_BYTE_RANGE = 0x0C
2287 SMB_COM_UNLOCK_BYTE_RANGE = 0x0D
2288 SMB_COM_CREATE_TEMPORARY = 0x0E
2289 SMB_COM_CREATE_NEW = 0x0F
2290 SMB_COM_CHECK_DIRECTORY = 0x10
2291 SMB_COM_PROCESS_EXIT = 0x11
2292 SMB_COM_SEEK = 0x12
2293 SMB_COM_LOCK_AND_READ = 0x13
2294 SMB_COM_WRITE_AND_UNLOCK = 0x14
2295 SMB_COM_READ_RAW = 0x1A
2296 SMB_COM_READ_MPX = 0x1B
2297 SMB_COM_READ_MPX_SECONDARY = 0x1C
2298 SMB_COM_WRITE_RAW = 0x1D
2299 SMB_COM_WRITE_MPX = 0x1E
2300 SMB_COM_WRITE_MPX_SECONDARY = 0x1F
2301 SMB_COM_WRITE_COMPLETE = 0x20
2302 SMB_COM_QUERY_SERVER = 0x21
2303 SMB_COM_SET_INFORMATION2 = 0x22
2304 SMB_COM_QUERY_INFORMATION2 = 0x23
2305 SMB_COM_LOCKING_ANDX = 0x24
2306 SMB_COM_TRANSACTION = 0x25
2307 SMB_COM_TRANSACTION_SECONDARY = 0x26
2308 SMB_COM_IOCTL = 0x27
2309 SMB_COM_IOCTL_SECONDARY = 0x28
2310 SMB_COM_COPY = 0x29
2311 SMB_COM_MOVE = 0x2A
2312 SMB_COM_ECHO = 0x2B
2313 SMB_COM_WRITE_AND_CLOSE = 0x2C
2314 SMB_COM_OPEN_ANDX = 0x2D
2315 SMB_COM_READ_ANDX = 0x2E
2316 SMB_COM_WRITE_ANDX = 0x2F
2317 SMB_COM_NEW_FILE_SIZE = 0x30
2318 SMB_COM_CLOSE_AND_TREE_DISC = 0x31
2319 SMB_COM_TRANSACTION2 = 0x32
2320 SMB_COM_TRANSACTION2_SECONDARY = 0x33
2321 SMB_COM_FIND_CLOSE2 = 0x34
2322 SMB_COM_FIND_NOTIFY_CLOSE = 0x35
2323 # Used by Xenix/Unix 0x60 - 0x6E
2324 SMB_COM_TREE_CONNECT = 0x70
2325 SMB_COM_TREE_DISCONNECT = 0x71
2326 SMB_COM_NEGOTIATE = 0x72
2327 SMB_COM_SESSION_SETUP_ANDX = 0x73
2328 SMB_COM_LOGOFF_ANDX = 0x74
2329 SMB_COM_TREE_CONNECT_ANDX = 0x75
2330 SMB_COM_QUERY_INFORMATION_DISK = 0x80
2331 SMB_COM_SEARCH = 0x81
2332 SMB_COM_FIND = 0x82
2333 SMB_COM_FIND_UNIQUE = 0x83
2334 SMB_COM_FIND_CLOSE = 0x84
2335 SMB_COM_NT_TRANSACT = 0xA0
2336 SMB_COM_NT_TRANSACT_SECONDARY = 0xA1
2337 SMB_COM_NT_CREATE_ANDX = 0xA2
2338 SMB_COM_NT_CANCEL = 0xA4
2339 SMB_COM_NT_RENAME = 0xA5
2340 SMB_COM_OPEN_PRINT_FILE = 0xC0
2341 SMB_COM_WRITE_PRINT_FILE = 0xC1
2342 SMB_COM_CLOSE_PRINT_FILE = 0xC2
2343 SMB_COM_GET_PRINT_QUEUE = 0xC3
2344 SMB_COM_READ_BULK = 0xD8
2345 SMB_COM_WRITE_BULK = 0xD9
2346 SMB_COM_WRITE_BULK_DATA = 0xDA
2348 # TRANSACT codes
2349 TRANS_TRANSACT_NMPIPE = 0x26
2351 # TRANSACT2 codes
2352 TRANS2_FIND_FIRST2 = 0x0001
2353 TRANS2_FIND_NEXT2 = 0x0002
2354 TRANS2_QUERY_FS_INFORMATION = 0x0003
2355 TRANS2_QUERY_PATH_INFORMATION = 0x0005
2356 TRANS2_QUERY_FILE_INFORMATION = 0x0007
2357 TRANS2_SET_FILE_INFORMATION = 0x0008
2358 TRANS2_SET_PATH_INFORMATION = 0x0006
2360 # Security Share Mode (Used internally by SMB class)
2361 SECURITY_SHARE_MASK = 0x01
2362 SECURITY_SHARE_SHARE = 0x00
2363 SECURITY_SHARE_USER = 0x01
2364 SECURITY_SIGNATURES_ENABLED = 0X04
2365 SECURITY_SIGNATURES_REQUIRED = 0X08
2367 # Security Auth Mode (Used internally by SMB class)
2368 SECURITY_AUTH_MASK = 0x02
2369 SECURITY_AUTH_ENCRYPTED = 0x02
2370 SECURITY_AUTH_PLAINTEXT = 0x00
2372 # Raw Mode Mask (Used internally by SMB class. Good for dialect up to and including LANMAN2.1)
2373 RAW_READ_MASK = 0x01
2374 RAW_WRITE_MASK = 0x02
2376 # Capabilities Mask (Used internally by SMB class. Good for dialect NT LM 0.12)
2377 CAP_RAW_MODE = 0x00000001
2378 CAP_MPX_MODE = 0x0002
2379 CAP_UNICODE = 0x0004
2380 CAP_LARGE_FILES = 0x0008
2381 CAP_EXTENDED_SECURITY = 0x80000000
2382 CAP_USE_NT_ERRORS = 0x40
2383 CAP_NT_SMBS = 0x10
2384 CAP_LARGE_READX = 0x00004000
2385 CAP_LARGE_WRITEX = 0x00008000
2386 CAP_RPC_REMOTE_APIS = 0x20
2388 # Flags1 Mask
2389 FLAGS1_LOCK_AND_READ_OK = 0x01
2390 FLAGS1_PATHCASELESS = 0x08
2391 FLAGS1_CANONICALIZED_PATHS = 0x10
2392 FLAGS1_REPLY = 0x80
2394 # Flags2 Mask
2395 FLAGS2_LONG_NAMES = 0x0001
2396 FLAGS2_EAS = 0x0002
2397 FLAGS2_SMB_SECURITY_SIGNATURE = 0x0004
2398 FLAGS2_IS_LONG_NAME = 0x0040
2399 FLAGS2_DFS = 0x1000
2400 FLAGS2_PAGING_IO = 0x2000
2401 FLAGS2_NT_STATUS = 0x4000
2402 FLAGS2_UNICODE = 0x8000
2403 FLAGS2_COMPRESSED = 0x0008
2404 FLAGS2_SMB_SECURITY_SIGNATURE_REQUIRED = 0x0010
2405 FLAGS2_EXTENDED_SECURITY = 0x0800
2407 # Dialect's Security Mode flags
2408 NEGOTIATE_USER_SECURITY = 0x01
2409 NEGOTIATE_ENCRYPT_PASSWORDS = 0x02
2410 NEGOTIATE_SECURITY_SIGNATURE_ENABLE = 0x04
2411 NEGOTIATE_SECURITY_SIGNATURE_REQUIRED = 0x08
2413 # Tree Connect AndX Response optionalSuppor flags
2414 SMB_SUPPORT_SEARCH_BITS = 0x01
2415 SMB_SHARE_IS_IN_DFS = 0x02
2417 def __init__(self, remote_name, remote_host, my_name=None, host_type=nmb.TYPE_SERVER, sess_port=445, timeout=None,
2418 UDP=0, session=None, negPacket=None):
2419 # The uid attribute will be set when the client calls the login() method
2420 self._uid = 0
2421 self.__server_name = ''
2422 self.__client_name = ''
2423 self.__server_os = ''
2424 self.__server_os_major = None
2425 self.__server_os_minor = None
2426 self.__server_os_build = None
2427 self.__server_lanman = ''
2428 self.__server_domain = ''
2429 self.__server_dns_domain_name = ''
2430 self.__server_dns_host_name = ''
2431 self.__remote_name = remote_name.upper()
2432 self.__remote_host = remote_host
2433 self.__isNTLMv2 = True
2434 self._dialects_parameters = None
2435 self._dialects_data = None
2436 self._doKerberos = False
2438 # Credentials
2439 self.__userName = b''
2440 self.__password = b''
2441 self.__domain = b''
2442 self.__lmhash = b''
2443 self.__nthash = b''
2444 self.__aesKey = b''
2445 self.__kdc = b''
2446 self.__TGT = None
2447 self.__TGS = None
2449 # Negotiate Protocol Result, used everywhere
2450 # Could be extended or not, flags should be checked before
2451 self._dialect_data = 0
2452 self._dialect_parameters = 0
2453 self._action = 0
2454 self._sess = None
2455 self.encrypt_passwords = True
2456 self.tid = 0
2457 self.fid = 0
2459 # Strict host validation - off by default
2460 self._strict_hostname_validation = False
2461 self._validation_allow_absent = True
2462 self._accepted_hostname = ''
2464 # Signing stuff
2465 self._SignSequenceNumber = 0
2466 self._SigningSessionKey = b''
2467 self._SigningChallengeResponse = b''
2468 self._SignatureEnabled = False
2469 self._SignatureVerificationEnabled = False
2470 self._SignatureRequired = False
2472 # Base flags (default flags, can be overridden using set_flags())
2473 self.__flags1 = SMB.FLAGS1_PATHCASELESS | SMB.FLAGS1_CANONICALIZED_PATHS
2474 self.__flags2 = SMB.FLAGS2_EXTENDED_SECURITY | SMB.FLAGS2_NT_STATUS | SMB.FLAGS2_LONG_NAMES
2476 if timeout is None: 2476 ↛ 2477line 2476 didn't jump to line 2477, because the condition on line 2476 was never true
2477 self.__timeout = 60
2478 else:
2479 self.__timeout = timeout
2481 # If port 445 and the name sent is *SMBSERVER we're setting the name to the IP.
2482 # This is to help some old applications still believing
2483 # *SMSBSERVER will work against modern OSes. If port is NETBIOS_SESSION_PORT the user better
2484 # know about *SMBSERVER's limitations
2485 if sess_port == 445 and remote_name == '*SMBSERVER': 2485 ↛ 2486line 2485 didn't jump to line 2486, because the condition on line 2485 was never true
2486 self.__remote_name = remote_host
2488 # This is on purpose. I'm still not convinced to do a socket.gethostname() if not specified
2489 if my_name is None: 2489 ↛ 2492line 2489 didn't jump to line 2492, because the condition on line 2489 was never false
2490 self.__client_name = b''
2491 else:
2492 self.__client_name = my_name
2494 if session is None: 2494 ↛ 2516line 2494 didn't jump to line 2516, because the condition on line 2494 was never false
2495 if not my_name: 2495 ↛ 2502line 2495 didn't jump to line 2502, because the condition on line 2495 was never false
2496 # If destination port is 139 yes, there's some client disclosure
2497 my_name = socket.gethostname()
2498 i = my_name.find('.')
2499 if i > -1: 2499 ↛ 2500line 2499 didn't jump to line 2500, because the condition on line 2499 was never true
2500 my_name = my_name[:i]
2502 if UDP: 2502 ↛ 2503line 2502 didn't jump to line 2503, because the condition on line 2502 was never true
2503 self._sess = nmb.NetBIOSUDPSession(my_name, remote_name, remote_host, host_type, sess_port, self.__timeout)
2504 else:
2505 self._sess = nmb.NetBIOSTCPSession(my_name, remote_name, remote_host, host_type, sess_port, self.__timeout)
2507 # Initialize session values (_dialect_data and _dialect_parameters)
2508 self.neg_session()
2510 # Call login() without any authentication information to
2511 # setup a session if the remote server
2512 # is in share mode.
2513 if (self._dialects_parameters['SecurityMode'] & SMB.SECURITY_SHARE_MASK) == SMB.SECURITY_SHARE_SHARE: 2513 ↛ 2514line 2513 didn't jump to line 2514, because the condition on line 2513 was never true
2514 self.login('', '')
2515 else:
2516 self._sess = session
2517 self.neg_session(negPacket = negPacket)
2518 # Call login() without any authentication information to
2519 # setup a session if the remote server
2520 # is in share mode.
2521 if (self._dialects_parameters['SecurityMode'] & SMB.SECURITY_SHARE_MASK) == SMB.SECURITY_SHARE_SHARE:
2522 self.login('', '')
2524 @staticmethod
2525 def ntlm_supported():
2526 return False
2528 def getKerberos(self):
2529 return self._doKerberos
2531 def get_remote_name(self):
2532 return self.__remote_name
2534 def set_remote_name(self, name):
2535 self.__remote_name = name
2536 return True
2538 def set_hostname_validation(self, validate, accept_empty, hostname):
2539 self._strict_hostname_validation = validate
2540 self._validation_allow_absent = accept_empty
2541 self._accepted_hostname = hostname
2543 def get_remote_host(self):
2544 return self.__remote_host
2546 def get_flags(self):
2547 return self.__flags1, self.__flags2
2549 def set_flags(self, flags1=None, flags2=None):
2550 if flags1 is not None:
2551 self.__flags1 = flags1
2552 if flags2 is not None: 2552 ↛ exitline 2552 didn't return from function 'set_flags', because the condition on line 2552 was never false
2553 self.__flags2 = flags2
2555 def set_timeout(self, timeout):
2556 prev_timeout = self.__timeout
2557 self.__timeout = timeout
2558 return prev_timeout
2560 def get_timeout(self):
2561 return self.__timeout
2563 @contextmanager
2564 def use_timeout(self, timeout):
2565 prev_timeout = self.set_timeout(timeout)
2566 try:
2567 yield
2568 finally:
2569 self.set_timeout(prev_timeout)
2571 def get_session(self):
2572 return self._sess
2574 def get_tid(self):
2575 return self.tid
2577 def get_fid(self):
2578 return self.fid
2580 def isGuestSession(self):
2581 return self._action & SMB_SETUP_GUEST
2583 def doesSupportNTLMv2(self):
2584 return self.__isNTLMv2
2586 def close_session(self):
2587 if self._sess: 2587 ↛ exitline 2587 didn't return from function 'close_session', because the condition on line 2587 was never false
2588 self._sess.close()
2589 self._sess = None
2591 def recvSMB(self):
2592 r = self._sess.recv_packet(self.__timeout)
2593 return NewSMBPacket(data = r.get_trailer())
2595 @staticmethod
2596 def __decode_trans(params, data):
2597 totparamcnt, totdatacnt, _, paramcnt, paramoffset, paramds, datacnt, dataoffset, datads, setupcnt = unpack('<HHHHHHHHHB', params[:19])
2598 if paramcnt + paramds < totparamcnt or datacnt + datads < totdatacnt:
2599 has_more = 1
2600 else:
2601 has_more = 0
2602 paramoffset = paramoffset - 55 - setupcnt * 2
2603 dataoffset = dataoffset - 55 - setupcnt * 2
2604 return has_more, params[20:20 + setupcnt * 2], data[paramoffset:paramoffset + paramcnt], data[dataoffset:dataoffset + datacnt]
2606 # TODO: Move this to NewSMBPacket, it belongs there
2607 def signSMB(self, packet, signingSessionKey, signingChallengeResponse):
2608 # This logic MUST be applied for messages sent in response to any of the higher-layer actions and in
2609 # compliance with the message sequencing rules.
2610 # * The client or server that sends the message MUST provide the 32-bit sequence number for this
2611 # message, as specified in sections 3.2.4.1 and 3.3.4.1.
2612 # * The SMB_FLAGS2_SMB_SECURITY_SIGNATURE flag in the header MUST be set.
2613 # * To generate the signature, a 32-bit sequence number is copied into the
2614 # least significant 32 bits of the SecuritySignature field and the remaining
2615 # 4 bytes are set to 0x00.
2616 # * The MD5 algorithm, as specified in [RFC1321], MUST be used to generate a hash of the SMB
2617 # message from the start of the SMB Header, which is defined as follows.
2618 # CALL MD5Init( md5context )
2619 # CALL MD5Update( md5context, Connection.SigningSessionKey )
2620 # CALL MD5Update( md5context, Connection.SigningChallengeResponse )
2621 # CALL MD5Update( md5context, SMB message )
2622 # CALL MD5Final( digest, md5context )
2623 # SET signature TO the first 8 bytes of the digest
2624 # The resulting 8-byte signature MUST be copied into the SecuritySignature field of the SMB Header,
2625 # after which the message can be transmitted.
2627 #print "seq(%d) signingSessionKey %r, signingChallengeResponse %r" % (self._SignSequenceNumber, signingSessionKey, signingChallengeResponse)
2628 packet['SecurityFeatures'] = pack('<q',self._SignSequenceNumber)
2629 # Sign with the sequence
2630 m = hashlib.md5()
2631 m.update( signingSessionKey )
2632 m.update( signingChallengeResponse )
2633 m.update( packet.getData() )
2634 # Replace sequence with acual hash
2635 packet['SecurityFeatures'] = m.digest()[:8]
2636 if self._SignatureVerificationEnabled: 2636 ↛ 2637line 2636 didn't jump to line 2637, because the condition on line 2636 was never true
2637 self._SignSequenceNumber +=1
2638 else:
2639 self._SignSequenceNumber +=2
2641 def checkSignSMB(self, packet, signingSessionKey, signingChallengeResponse):
2642 # Let's check
2643 signature = packet['SecurityFeatures']
2644 #print "Signature received: %r " % signature
2645 self.signSMB(packet, signingSessionKey, signingChallengeResponse)
2646 #print "Signature calculated: %r" % packet['SecurityFeatures']
2647 if self._SignatureVerificationEnabled is not True:
2648 self._SignSequenceNumber -= 1
2649 return packet['SecurityFeatures'] == signature
2651 def sendSMB(self,smb):
2652 smb['Uid'] = self._uid
2653 #At least on AIX, PIDs can exceed 16 bits, so we mask them out
2654 smb['Pid'] = (os.getpid() & 0xFFFF)
2655 # set flags
2656 smb['Flags1'] |= self.__flags1
2657 smb['Flags2'] |= self.__flags2
2658 if self._SignatureEnabled:
2659 smb['Flags2'] |= SMB.FLAGS2_SMB_SECURITY_SIGNATURE
2660 self.signSMB(smb, self._SigningSessionKey, self._SigningChallengeResponse)
2662 self._sess.send_packet(smb.getData())
2664 @staticmethod
2665 def isValidAnswer(s, cmd):
2666 while 1:
2667 if s.rawData():
2668 if s.get_command() == cmd:
2669 if s.get_error_class() == 0x00 and s.get_error_code() == 0x00:
2670 return 1
2671 else:
2672 raise SessionError( "SMB Library Error", s.get_error_class()+ (s.get_reserved() << 8), s.get_error_code() , s.get_flags2() & SMB.FLAGS2_NT_STATUS)
2673 else:
2674 break
2675 return 0
2677 def neg_session(self, extended_security = True, negPacket = None):
2678 def parsePacket(smb):
2679 # If server speaks Unicode, let's set that flag from now on
2680 if smb['Flags2'] & SMB.FLAGS2_UNICODE: 2680 ↛ 2681line 2680 didn't jump to line 2681, because the condition on line 2680 was never true
2681 self.__flags2 |= SMB.FLAGS2_UNICODE
2683 if smb.isValidAnswer(SMB.SMB_COM_NEGOTIATE): 2683 ↛ 2712line 2683 didn't jump to line 2712, because the condition on line 2683 was never false
2684 sessionResponse = SMBCommand(smb['Data'][0])
2685 self._dialects_parameters = SMBNTLMDialect_Parameters(sessionResponse['Parameters'])
2686 self._dialects_data = SMBNTLMDialect_Data()
2687 self._dialects_data['ChallengeLength'] = self._dialects_parameters['ChallengeLength']
2688 self._dialects_data.fromString(sessionResponse['Data'])
2689 if self._dialects_parameters['Capabilities'] & SMB.CAP_EXTENDED_SECURITY: 2689 ↛ 2705line 2689 didn't jump to line 2705, because the condition on line 2689 was never false
2690 # Whether we choose it or it is enforced by the server, we go for extended security
2691 self._dialects_parameters = SMBExtended_Security_Parameters(sessionResponse['Parameters'])
2692 self._dialects_data = SMBExtended_Security_Data(sessionResponse['Data'])
2693 # Let's setup some variable for later use
2694 if self._dialects_parameters['SecurityMode'] & SMB.SECURITY_SIGNATURES_REQUIRED: 2694 ↛ 2701line 2694 didn't jump to line 2701, because the condition on line 2694 was never false
2695 self._SignatureRequired = True
2697 # Interestingly, the security Blob might be missing sometimes.
2698 #spnego = SPNEGO_NegTokenInit(self._dialects_data['SecurityBlob'])
2699 #for i in spnego['MechTypes']:
2700 # print "Mech Found: %s" % MechTypes[i]
2701 return 1
2703 # If not, let's try the old way
2704 else:
2705 if self._dialects_data['ServerName'] is not None:
2706 self.__server_name = self._dialects_data['ServerName']
2708 if self._dialects_parameters['DialectIndex'] == 0xffff:
2709 raise UnsupportedFeature("Remote server does not know NT LM 0.12")
2710 return 1
2711 else:
2712 return 0
2714 if negPacket is None: 2714 ↛ 2732line 2714 didn't jump to line 2732, because the condition on line 2714 was never false
2715 smb = NewSMBPacket()
2716 negSession = SMBCommand(SMB.SMB_COM_NEGOTIATE)
2717 flags2 = self.get_flags()[1]
2718 if extended_security is True: 2718 ↛ 2721line 2718 didn't jump to line 2721, because the condition on line 2718 was never false
2719 self.set_flags(flags2=flags2|SMB.FLAGS2_EXTENDED_SECURITY)
2720 else:
2721 self.set_flags(flags2=flags2 & (~SMB.FLAGS2_EXTENDED_SECURITY))
2723 negSession['Data'] = b'\x02NT LM 0.12\x00'
2724 smb.addCommand(negSession)
2725 self.sendSMB(smb)
2727 while 1:
2728 smb = self.recvSMB()
2729 return parsePacket(smb)
2730 else:
2732 return parsePacket( NewSMBPacket( data = negPacket))
2734 def tree_connect(self, path, password = '', service = SERVICE_ANY):
2735 LOG.warning("[MS-CIFS] This is an original Core Protocol command.This command has been deprecated.Client Implementations SHOULD use SMB_COM_TREE_CONNECT_ANDX")
2737 # return 0x800
2738 if password:
2739 # Password is only encrypted if the server passed us an "encryption" during protocol dialect
2740 if self._dialects_parameters['ChallengeLength'] > 0:
2741 # this code is untested
2742 password = self.get_ntlmv1_response(ntlm.compute_lmhash(password))
2744 if not unicode_support:
2745 if unicode_convert:
2746 path = str(path)
2747 else:
2748 raise Exception('SMB: Can\t conver path from unicode!')
2750 smb = NewSMBPacket()
2751 treeConnect = SMBCommand(SMB.SMB_COM_TREE_CONNECT)
2752 treeConnect['Parameters'] = SMBTreeConnect_Parameters()
2753 treeConnect['Data'] = SMBTreeConnect_Data()
2754 treeConnect['Data']['Path'] = path.upper()
2755 treeConnect['Data']['Password'] = password
2756 treeConnect['Data']['Service'] = service
2757 smb.addCommand(treeConnect)
2758 self.sendSMB(smb)
2760 while 1:
2761 smb = self.recvSMB()
2762 if smb.isValidAnswer(SMB.SMB_COM_TREE_CONNECT):
2763 # XXX Here we are ignoring the rest of the response
2764 return smb['Tid']
2765 return smb['Tid']
2767 def get_uid(self):
2768 return self._uid
2770 def set_uid(self, uid):
2771 self._uid = uid
2773 def tree_connect_andx(self, path, password = None, service = SERVICE_ANY, smb_packet=None):
2774 if password: 2774 ↛ 2776line 2774 didn't jump to line 2776, because the condition on line 2774 was never true
2775 # Password is only encrypted if the server passed us an "encryption" during protocol dialect
2776 if self._dialects_parameters['ChallengeLength'] > 0:
2777 # this code is untested
2778 password = self.get_ntlmv1_response(ntlm.compute_lmhash(password))
2779 else:
2780 password = '\x00'
2782 if not unicode_support: 2782 ↛ 2788line 2782 didn't jump to line 2788, because the condition on line 2782 was never false
2783 if unicode_convert: 2783 ↛ 2786line 2783 didn't jump to line 2786, because the condition on line 2783 was never false
2784 path = str(path)
2785 else:
2786 raise Exception('SMB: Can\t convert path from unicode!')
2788 if smb_packet is None: 2788 ↛ 2791line 2788 didn't jump to line 2791, because the condition on line 2788 was never false
2789 smb = NewSMBPacket()
2790 else:
2791 smb = smb_packet
2793 # Just in case this came with the full path ,let's just leave
2794 # the sharename, we'll take care of the rest
2796 share = path.split('\\')[-1]
2797 try:
2798 _, _, _, _, sockaddr = socket.getaddrinfo(self.get_remote_host(), 80, 0, 0, socket.IPPROTO_TCP)[0]
2799 remote_host = sockaddr[0]
2800 except Exception:
2801 remote_host = self.get_remote_host()
2803 path = '\\\\' + remote_host + '\\' +share
2804 path = path.upper().encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else path
2806 treeConnect = SMBCommand(SMB.SMB_COM_TREE_CONNECT_ANDX)
2807 treeConnect['Parameters'] = SMBTreeConnectAndX_Parameters()
2808 treeConnect['Data'] = SMBTreeConnectAndX_Data(flags=self.__flags2)
2809 treeConnect['Parameters']['PasswordLength'] = len(password)
2810 treeConnect['Data']['Password'] = password
2811 treeConnect['Data']['Path'] = path
2812 treeConnect['Data']['Service'] = service
2814 if self.__flags2 & SMB.FLAGS2_UNICODE:
2815 treeConnect['Data']['Pad'] = 0x0
2817 smb.addCommand(treeConnect)
2819 # filename = "\PIPE\epmapper"
2821 # ntCreate = SMBCommand(SMB.SMB_COM_NT_CREATE_ANDX)
2822 # ntCreate['Parameters'] = SMBNtCreateAndX_Parameters()
2823 # ntCreate['Data'] = SMBNtCreateAndX_Data()
2824 # ntCreate['Parameters']['FileNameLength'] = len(filename)
2825 # ntCreate['Parameters']['CreateFlags'] = 0
2826 # ntCreate['Parameters']['AccessMask'] = 0x3
2827 # ntCreate['Parameters']['CreateOptions'] = 0x0
2828 # ntCreate['Data']['FileName'] = filename
2830 # smb.addCommand(ntCreate)
2831 self.sendSMB(smb)
2833 while 1:
2834 smb = self.recvSMB()
2835 if smb.isValidAnswer(SMB.SMB_COM_TREE_CONNECT_ANDX): 2835 ↛ 2839line 2835 didn't jump to line 2839, because the condition on line 2835 was never false
2836 # XXX Here we are ignoring the rest of the response
2837 self.tid = smb['Tid']
2838 return self.tid
2839 self.tid = smb['Tid']
2840 return self.tid
2842 # backwars compatibility
2843 connect_tree = tree_connect_andx
2845 @staticmethod
2846 def getDialect():
2847 return SMB_DIALECT
2849 def get_server_name(self):
2850 #return self._dialects_data['ServerName']
2851 return self.__server_name
2853 def get_client_name(self):
2854 return self.__client_name
2856 def get_session_key(self):
2857 return self._SigningSessionKey
2859 def set_session_key(self, key):
2860 self._SignatureEnabled = True
2861 self._SignSequenceNumber = 2
2862 self._SigningSessionKey = key
2864 def get_encryption_key(self):
2865 if 'Challenge' in self._dialects_data.fields:
2866 return self._dialects_data['Challenge']
2867 else:
2868 return None
2870 def get_server_time(self):
2871 timestamp = self._dialects_parameters['HighDateTime']
2872 timestamp <<= 32
2873 timestamp |= self._dialects_parameters['LowDateTime']
2874 timestamp -= 116444736000000000
2875 timestamp //= 10000000
2876 d = datetime.datetime.utcfromtimestamp(timestamp)
2877 return d.strftime("%a, %d %b %Y %H:%M:%S GMT")
2879 def disconnect_tree(self, tid):
2880 smb = NewSMBPacket()
2881 smb['Tid'] = tid
2883 smb.addCommand(SMBCommand(SMB.SMB_COM_TREE_DISCONNECT))
2885 self.sendSMB(smb)
2886 self.recvSMB()
2888 def open(self, tid, filename, open_mode, desired_access):
2889 filename = filename.replace('/', '\\')
2890 filename = filename.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else filename
2892 smb = NewSMBPacket()
2893 smb['Tid'] = tid
2895 openFile = SMBCommand(SMB.SMB_COM_OPEN)
2896 openFile['Parameters'] = SMBOpen_Parameters()
2897 openFile['Parameters']['DesiredAccess'] = desired_access
2898 openFile['Parameters']['OpenMode'] = open_mode
2899 openFile['Parameters']['SearchAttributes'] = ATTR_READONLY | ATTR_HIDDEN | ATTR_ARCHIVE
2900 openFile['Data'] = SMBOpen_Data(flags=self.__flags2)
2901 openFile['Data']['FileName'] = filename
2903 smb.addCommand(openFile)
2905 self.sendSMB(smb)
2907 smb = self.recvSMB()
2908 if smb.isValidAnswer(SMB.SMB_COM_OPEN):
2909 # XXX Here we are ignoring the rest of the response
2910 openFileResponse = SMBCommand(smb['Data'][0])
2911 openFileParameters = SMBOpenResponse_Parameters(openFileResponse['Parameters'])
2913 return (
2914 openFileParameters['Fid'],
2915 openFileParameters['FileAttributes'],
2916 openFileParameters['LastWriten'],
2917 openFileParameters['FileSize'],
2918 openFileParameters['GrantedAccess'],
2919 )
2921 def open_andx(self, tid, filename, open_mode, desired_access):
2922 filename = filename.replace('/', '\\')
2923 filename = filename.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else filename
2925 smb = NewSMBPacket()
2926 smb['Tid'] = tid
2928 openFile = SMBCommand(SMB.SMB_COM_OPEN_ANDX)
2929 openFile['Parameters'] = SMBOpenAndX_Parameters()
2930 openFile['Parameters']['DesiredAccess'] = desired_access
2931 openFile['Parameters']['OpenMode'] = open_mode
2932 openFile['Parameters']['SearchAttributes'] = ATTR_READONLY | ATTR_HIDDEN | ATTR_ARCHIVE
2933 openFile['Data'] = SMBOpenAndX_Data(flags=self.__flags2)
2934 openFile['Data']['FileName'] = filename
2936 if self.__flags2 & SMB.FLAGS2_UNICODE:
2937 openFile['Data']['Pad'] = 0x0
2939 smb.addCommand(openFile)
2941 self.sendSMB(smb)
2943 smb = self.recvSMB()
2944 if smb.isValidAnswer(SMB.SMB_COM_OPEN_ANDX):
2945 # XXX Here we are ignoring the rest of the response
2946 openFileResponse = SMBCommand(smb['Data'][0])
2947 openFileParameters = SMBOpenAndXResponse_Parameters(openFileResponse['Parameters'])
2949 return (
2950 openFileParameters['Fid'],
2951 openFileParameters['FileAttributes'],
2952 openFileParameters['LastWriten'],
2953 openFileParameters['FileSize'],
2954 openFileParameters['GrantedAccess'],
2955 openFileParameters['FileType'],
2956 openFileParameters['IPCState'],
2957 openFileParameters['Action'],
2958 openFileParameters['ServerFid'],
2959 )
2961 def close(self, tid, fid):
2962 smb = NewSMBPacket()
2963 smb['Tid'] = tid
2965 closeFile = SMBCommand(SMB.SMB_COM_CLOSE)
2966 closeFile['Parameters'] = SMBClose_Parameters()
2967 closeFile['Parameters']['FID'] = fid
2968 smb.addCommand(closeFile)
2970 self.sendSMB(smb)
2971 smb = self.recvSMB()
2972 if smb.isValidAnswer(SMB.SMB_COM_CLOSE): 2972 ↛ 2974line 2972 didn't jump to line 2974, because the condition on line 2972 was never false
2973 return 1
2974 return 0
2976 def send_trans(self, tid, setup, name, param, data, noAnswer = 0):
2977 smb = NewSMBPacket()
2978 smb['Tid'] = tid
2980 transCommand = SMBCommand(SMB.SMB_COM_TRANSACTION)
2981 transCommand['Parameters'] = SMBTransaction_Parameters()
2982 transCommand['Data'] = SMBTransaction_Data()
2984 transCommand['Parameters']['Setup'] = setup
2985 transCommand['Parameters']['TotalParameterCount'] = len(param)
2986 transCommand['Parameters']['TotalDataCount'] = len(data)
2988 transCommand['Parameters']['ParameterCount'] = len(param)
2989 transCommand['Parameters']['ParameterOffset'] = 32+3+28+len(setup)+len(name)
2991 transCommand['Parameters']['DataCount'] = len(data)
2992 transCommand['Parameters']['DataOffset'] = transCommand['Parameters']['ParameterOffset'] + len(param)
2994 transCommand['Data']['Name'] = name
2995 transCommand['Data']['Trans_Parameters'] = param
2996 transCommand['Data']['Trans_Data'] = data
2998 if noAnswer:
2999 transCommand['Parameters']['Flags'] = TRANS_NO_RESPONSE
3001 smb.addCommand(transCommand)
3003 self.sendSMB(smb)
3005 def send_trans2(self, tid, setup, name, param, data):
3006 smb = NewSMBPacket()
3007 smb['Tid'] = tid
3009 command = pack('<H', setup)
3011 transCommand = SMBCommand(SMB.SMB_COM_TRANSACTION2)
3012 transCommand['Parameters'] = SMBTransaction2_Parameters()
3013 transCommand['Parameters']['MaxDataCount'] = self._dialects_parameters['MaxBufferSize']
3014 transCommand['Data'] = SMBTransaction2_Data()
3016 transCommand['Parameters']['Setup'] = command
3017 transCommand['Parameters']['TotalParameterCount'] = len(param)
3018 transCommand['Parameters']['TotalDataCount'] = len(data)
3020 if len(param) > 0: 3020 ↛ 3025line 3020 didn't jump to line 3025, because the condition on line 3020 was never false
3021 padLen = (4 - (32+2+28 + len(command)) % 4 ) % 4
3022 padBytes = '\xFF' * padLen
3023 transCommand['Data']['Pad1'] = padBytes
3024 else:
3025 transCommand['Data']['Pad1'] = ''
3026 padLen = 0
3028 transCommand['Parameters']['ParameterCount'] = len(param)
3029 transCommand['Parameters']['ParameterOffset'] = 32+2+28+len(command)+len(name) + padLen
3031 if len(data) > 0: 3031 ↛ 3032line 3031 didn't jump to line 3032, because the condition on line 3031 was never true
3032 pad2Len = (4 - (32+2+28 + len(command) + padLen + len(param)) % 4) % 4
3033 transCommand['Data']['Pad2'] = '\xFF' * pad2Len
3034 else:
3035 transCommand['Data']['Pad2'] = ''
3036 pad2Len = 0
3038 transCommand['Parameters']['DataCount'] = len(data)
3039 transCommand['Parameters']['DataOffset'] = transCommand['Parameters']['ParameterOffset'] + len(param) + pad2Len
3041 transCommand['Data']['Name'] = name
3042 transCommand['Data']['Trans_Parameters'] = param
3043 transCommand['Data']['Trans_Data'] = data
3044 smb.addCommand(transCommand)
3046 self.sendSMB(smb)
3048 def query_file_info(self, tid, fid, fileInfoClass = SMB_QUERY_FILE_STANDARD_INFO):
3049 self.send_trans2(tid, SMB.TRANS2_QUERY_FILE_INFORMATION, '\x00', pack('<HH', fid, fileInfoClass), '')
3051 resp = self.recvSMB()
3052 if resp.isValidAnswer(SMB.SMB_COM_TRANSACTION2): 3052 ↛ exitline 3052 didn't return from function 'query_file_info', because the condition on line 3052 was never false
3053 trans2Response = SMBCommand(resp['Data'][0])
3054 trans2Parameters = SMBTransaction2Response_Parameters(trans2Response['Parameters'])
3055 # Remove Potential Prefix Padding
3056 return trans2Response['Data'][-trans2Parameters['TotalDataCount']:]
3058 def __nonraw_retr_file(self, tid, fid, offset, datasize, callback):
3059 if (self._dialects_parameters['Capabilities'] & SMB.CAP_LARGE_READX) and self._SignatureEnabled is False: 3059 ↛ 3060line 3059 didn't jump to line 3060, because the condition on line 3059 was never true
3060 max_buf_size = 65000
3061 else:
3062 max_buf_size = self._dialects_parameters['MaxBufferSize'] & ~0x3ff # Read in multiple KB blocks
3064 read_offset = offset
3065 while read_offset < datasize:
3066 data = self.read_andx(tid, fid, read_offset, max_buf_size)
3068 callback(data)
3069 read_offset += len(data)
3071 def __nonraw_stor_file(self, tid, fid, offset, datasize, callback):
3072 if (self._dialects_parameters['Capabilities'] & SMB.CAP_LARGE_WRITEX) and self._SignatureEnabled is False: 3072 ↛ 3073line 3072 didn't jump to line 3073, because the condition on line 3072 was never true
3073 max_buf_size = 65000
3074 else:
3075 max_buf_size = self._dialects_parameters['MaxBufferSize'] & ~0x3ff # Write in multiple KB blocks
3077 write_offset = offset
3078 while 1:
3079 data = callback(max_buf_size)
3080 if not data:
3081 break
3083 smb = self.write_andx(tid,fid,data, write_offset)
3084 writeResponse = SMBCommand(smb['Data'][0])
3085 writeResponseParameters = SMBWriteAndXResponse_Parameters(writeResponse['Parameters'])
3086 write_offset += writeResponseParameters['Count']
3088 def get_server_domain(self):
3089 return self.__server_domain
3091 def get_server_dns_domain_name(self):
3092 return self.__server_dns_domain_name
3094 def get_server_dns_host_name(self):
3095 return self.__server_dns_host_name
3097 def get_server_os(self):
3098 return self.__server_os
3100 def get_server_os_major(self):
3101 return self.__server_os_major
3103 def get_server_os_minor(self):
3104 return self.__server_os_minor
3106 def get_server_os_build(self):
3107 return self.__server_os_build
3109 def set_server_os(self, os):
3110 self.__server_os = os
3112 def get_server_lanman(self):
3113 return self.__server_lanman
3115 def is_login_required(self):
3116 # Login is required if share mode is user.
3117 # Otherwise only public services or services in share mode
3118 # are allowed.
3119 return (self._dialects_parameters['SecurityMode'] & SMB.SECURITY_SHARE_MASK) == SMB.SECURITY_SHARE_USER
3121 def is_signing_required(self):
3122 return self._SignatureRequired
3124 def get_ntlmv1_response(self, key):
3125 challenge = self._dialects_data['Challenge']
3126 return ntlm.get_ntlmv1_response(key, challenge)
3128 def perform_hostname_validation(self):
3129 if self.__server_name == '':
3130 if not self._validation_allow_absent:
3131 raise self.HostnameValidationException('Hostname was not supplied by target host and absent validation is disallowed')
3132 return
3133 if self.__server_name.lower() != self._accepted_hostname.lower() and self.__server_dns_host_name.lower() != self._accepted_hostname.lower():
3134 raise self.HostnameValidationException('Supplied hostname %s does not match reported hostnames %s or %s' %
3135 (self._accepted_hostname.lower(), self.__server_name.lower(), self.__server_dns_host_name.lower()))
3138 def kerberos_login(self, user, password, domain = '', lmhash = '', nthash = '', aesKey = '', kdcHost = '', TGT=None, TGS=None):
3139 # Importing down here so pyasn1 is not required if kerberos is not used.
3140 from impacket.krb5.asn1 import AP_REQ, Authenticator, TGS_REP, seq_set
3141 from impacket.krb5.kerberosv5 import getKerberosTGT, getKerberosTGS
3142 from impacket.krb5 import constants
3143 from impacket.krb5.types import Principal, KerberosTime, Ticket
3144 from pyasn1.codec.der import decoder, encoder
3145 import datetime
3147 # login feature does not support unicode
3148 # disable it if enabled
3149 flags2 = self.__flags2
3150 if flags2 & SMB.FLAGS2_UNICODE:
3151 self.__flags2 = flags2 & (flags2 ^ SMB.FLAGS2_UNICODE)
3153 # If TGT or TGS are specified, they are in the form of:
3154 # TGS['KDC_REP'] = the response from the server
3155 # TGS['cipher'] = the cipher used
3156 # TGS['sessionKey'] = the sessionKey
3157 # If we have hashes, normalize them
3158 if lmhash != '' or nthash != '':
3159 if len(lmhash) % 2: 3159 ↛ 3160line 3159 didn't jump to line 3160, because the condition on line 3159 was never true
3160 lmhash = '0%s' % lmhash
3161 if len(nthash) % 2: 3161 ↛ 3162line 3161 didn't jump to line 3162, because the condition on line 3161 was never true
3162 nthash = '0%s' % nthash
3163 try: # just in case they were converted already
3164 lmhash = a2b_hex(lmhash)
3165 nthash = a2b_hex(nthash)
3166 except:
3167 pass
3169 self.__userName = user
3170 self.__password = password
3171 self.__domain = domain
3172 self.__lmhash = lmhash
3173 self.__nthash = nthash
3174 self.__aesKey = aesKey
3175 self.__kdc = kdcHost
3176 self.__TGT = TGT
3177 self.__TGS = TGS
3178 self._doKerberos= True
3180 # First of all, we need to get a TGT for the user
3181 userName = Principal(user, type=constants.PrincipalNameType.NT_PRINCIPAL.value)
3182 if TGT is None: 3182 ↛ 3186line 3182 didn't jump to line 3186, because the condition on line 3182 was never false
3183 if TGS is None: 3183 ↛ 3192line 3183 didn't jump to line 3192, because the condition on line 3183 was never false
3184 tgt, cipher, oldSessionKey, sessionKey = getKerberosTGT(userName, password, domain, lmhash, nthash, aesKey, kdcHost)
3185 else:
3186 tgt = TGT['KDC_REP']
3187 cipher = TGT['cipher']
3188 sessionKey = TGT['sessionKey']
3190 # Now that we have the TGT, we should ask for a TGS for cifs
3192 if TGS is None: 3192 ↛ 3196line 3192 didn't jump to line 3196, because the condition on line 3192 was never false
3193 serverName = Principal('cifs/%s' % self.__remote_name, type=constants.PrincipalNameType.NT_SRV_INST.value)
3194 tgs, cipher, oldSessionKey, sessionKey = getKerberosTGS(serverName, domain, kdcHost, tgt, cipher, sessionKey)
3195 else:
3196 tgs = TGS['KDC_REP']
3197 cipher = TGS['cipher']
3198 sessionKey = TGS['sessionKey']
3200 smb = NewSMBPacket()
3202 # Are we required to sign SMB? If so we do it, if not we skip it
3203 if self._SignatureRequired: 3203 ↛ 3207line 3203 didn't jump to line 3207, because the condition on line 3203 was never false
3204 smb['Flags2'] |= SMB.FLAGS2_SMB_SECURITY_SIGNATURE
3207 sessionSetup = SMBCommand(SMB.SMB_COM_SESSION_SETUP_ANDX)
3208 sessionSetup['Parameters'] = SMBSessionSetupAndX_Extended_Parameters()
3209 sessionSetup['Data'] = SMBSessionSetupAndX_Extended_Data()
3211 sessionSetup['Parameters']['MaxBufferSize'] = 61440
3212 sessionSetup['Parameters']['MaxMpxCount'] = 2
3213 sessionSetup['Parameters']['VcNumber'] = 1
3214 sessionSetup['Parameters']['SessionKey'] = 0
3215 sessionSetup['Parameters']['Capabilities'] = SMB.CAP_EXTENDED_SECURITY | SMB.CAP_USE_NT_ERRORS | SMB.CAP_UNICODE | SMB.CAP_LARGE_READX | SMB.CAP_LARGE_WRITEX
3218 # Let's build a NegTokenInit with the NTLMSSP
3219 # TODO: In the future we should be able to choose different providers
3221 blob = SPNEGO_NegTokenInit()
3223 # Kerberos v5 mech
3224 blob['MechTypes'] = [TypesMech['MS KRB5 - Microsoft Kerberos 5']]
3226 # Let's extract the ticket from the TGS
3227 tgs = decoder.decode(tgs, asn1Spec = TGS_REP())[0]
3228 ticket = Ticket()
3229 ticket.from_asn1(tgs['ticket'])
3231 # Now let's build the AP_REQ
3232 apReq = AP_REQ()
3233 apReq['pvno'] = 5
3234 apReq['msg-type'] = int(constants.ApplicationTagNumbers.AP_REQ.value)
3236 opts = list()
3237 apReq['ap-options'] = constants.encodeFlags(opts)
3238 seq_set(apReq,'ticket', ticket.to_asn1)
3240 authenticator = Authenticator()
3241 authenticator['authenticator-vno'] = 5
3242 authenticator['crealm'] = domain
3243 seq_set(authenticator, 'cname', userName.components_to_asn1)
3244 now = datetime.datetime.utcnow()
3246 authenticator['cusec'] = now.microsecond
3247 authenticator['ctime'] = KerberosTime.to_asn1(now)
3249 encodedAuthenticator = encoder.encode(authenticator)
3251 # Key Usage 11
3252 # AP-REQ Authenticator (includes application authenticator
3253 # subkey), encrypted with the application session key
3254 # (Section 5.5.1)
3255 encryptedEncodedAuthenticator = cipher.encrypt(sessionKey, 11, encodedAuthenticator, None)
3257 apReq['authenticator'] = noValue
3258 apReq['authenticator']['etype'] = cipher.enctype
3259 apReq['authenticator']['cipher'] = encryptedEncodedAuthenticator
3261 blob['MechToken'] = pack('B', ASN1_AID) + asn1encode(pack('B', ASN1_OID) + asn1encode(
3262 TypesMech['KRB5 - Kerberos 5']) + KRB5_AP_REQ + encoder.encode(apReq))
3264 sessionSetup['Parameters']['SecurityBlobLength'] = len(blob)
3265 sessionSetup['Parameters'].getData()
3266 sessionSetup['Data']['SecurityBlob'] = blob.getData()
3268 # Fake Data here, don't want to get us fingerprinted
3269 sessionSetup['Data']['NativeOS'] = 'Unix'
3270 sessionSetup['Data']['NativeLanMan'] = 'Samba'
3272 smb.addCommand(sessionSetup)
3273 self.sendSMB(smb)
3275 smb = self.recvSMB()
3276 if smb.isValidAnswer(SMB.SMB_COM_SESSION_SETUP_ANDX): 3276 ↛ 3300line 3276 didn't jump to line 3300, because the condition on line 3276 was never false
3277 # We will need to use this uid field for all future requests/responses
3278 self._uid = smb['Uid']
3280 # Now we have to extract the blob to continue the auth process
3281 sessionResponse = SMBCommand(smb['Data'][0])
3282 sessionParameters = SMBSessionSetupAndX_Extended_Response_Parameters(sessionResponse['Parameters'])
3283 sessionData = SMBSessionSetupAndX_Extended_Response_Data(flags = smb['Flags2'])
3284 sessionData['SecurityBlobLength'] = sessionParameters['SecurityBlobLength']
3285 sessionData.fromString(sessionResponse['Data'])
3287 self._action = sessionParameters['Action']
3288 # If smb sign required, let's enable it for the rest of the connection
3289 if self._dialects_parameters['SecurityMode'] & SMB.SECURITY_SIGNATURES_REQUIRED: 3289 ↛ 3295line 3289 didn't jump to line 3295, because the condition on line 3289 was never false
3290 self._SigningSessionKey = sessionKey.contents
3291 self._SignSequenceNumber = 2
3292 self._SignatureEnabled = True
3294 # restore unicode flag if needed
3295 if flags2 & SMB.FLAGS2_UNICODE:
3296 self.__flags2 |= SMB.FLAGS2_UNICODE
3298 return 1
3299 else:
3300 raise Exception('Error: Could not login successfully')
3302 def login_extended(self, user, password, domain = '', lmhash = '', nthash = '', use_ntlmv2 = True ):
3304 # login feature does not support unicode
3305 # disable it if enabled
3306 flags2 = self.__flags2
3307 if flags2 & SMB.FLAGS2_UNICODE:
3308 self.__flags2 = flags2 & (flags2 ^ SMB.FLAGS2_UNICODE)
3310 # Once everything's working we should join login methods into a single one
3311 smb = NewSMBPacket()
3312 # Are we required to sign SMB? If so we do it, if not we skip it
3313 if self._SignatureRequired: 3313 ↛ 3316line 3313 didn't jump to line 3316, because the condition on line 3313 was never false
3314 smb['Flags2'] |= SMB.FLAGS2_SMB_SECURITY_SIGNATURE
3316 sessionSetup = SMBCommand(SMB.SMB_COM_SESSION_SETUP_ANDX)
3317 sessionSetup['Parameters'] = SMBSessionSetupAndX_Extended_Parameters()
3318 sessionSetup['Data'] = SMBSessionSetupAndX_Extended_Data()
3320 sessionSetup['Parameters']['MaxBufferSize'] = 61440
3321 sessionSetup['Parameters']['MaxMpxCount'] = 2
3322 sessionSetup['Parameters']['VcNumber'] = 1
3323 sessionSetup['Parameters']['SessionKey'] = 0
3324 sessionSetup['Parameters']['Capabilities'] = SMB.CAP_EXTENDED_SECURITY | SMB.CAP_USE_NT_ERRORS | SMB.CAP_UNICODE | SMB.CAP_LARGE_READX | SMB.CAP_LARGE_WRITEX
3327 # Let's build a NegTokenInit with the NTLMSSP
3328 # TODO: In the future we should be able to choose different providers
3330 blob = SPNEGO_NegTokenInit()
3332 # NTLMSSP
3333 blob['MechTypes'] = [TypesMech['NTLMSSP - Microsoft NTLM Security Support Provider']]
3334 auth = ntlm.getNTLMSSPType1(self.get_client_name(),domain,self._SignatureRequired, use_ntlmv2 = use_ntlmv2)
3335 blob['MechToken'] = auth.getData()
3337 sessionSetup['Parameters']['SecurityBlobLength'] = len(blob)
3338 sessionSetup['Parameters'].getData()
3339 sessionSetup['Data']['SecurityBlob'] = blob.getData()
3341 # Fake Data here, don't want to get us fingerprinted
3342 sessionSetup['Data']['NativeOS'] = 'Unix'
3343 sessionSetup['Data']['NativeLanMan'] = 'Samba'
3345 smb.addCommand(sessionSetup)
3346 self.sendSMB(smb)
3348 smb = self.recvSMB()
3349 if smb.isValidAnswer(SMB.SMB_COM_SESSION_SETUP_ANDX): 3349 ↛ 3446line 3349 didn't jump to line 3446, because the condition on line 3349 was never false
3350 # We will need to use this uid field for all future requests/responses
3351 self._uid = smb['Uid']
3353 # Now we have to extract the blob to continue the auth process
3354 sessionResponse = SMBCommand(smb['Data'][0])
3355 sessionParameters = SMBSessionSetupAndX_Extended_Response_Parameters(sessionResponse['Parameters'])
3356 sessionData = SMBSessionSetupAndX_Extended_Response_Data(flags = smb['Flags2'])
3357 sessionData['SecurityBlobLength'] = sessionParameters['SecurityBlobLength']
3358 sessionData.fromString(sessionResponse['Data'])
3359 respToken = SPNEGO_NegTokenResp(sessionData['SecurityBlob'])
3361 # Let's parse some data and keep it to ourselves in case it is asked
3362 ntlmChallenge = ntlm.NTLMAuthChallenge(respToken['ResponseToken'])
3363 if ntlmChallenge['TargetInfoFields_len'] > 0: 3363 ↛ 3392line 3363 didn't jump to line 3392, because the condition on line 3363 was never false
3364 av_pairs = ntlm.AV_PAIRS(ntlmChallenge['TargetInfoFields'][:ntlmChallenge['TargetInfoFields_len']])
3365 if av_pairs[ntlm.NTLMSSP_AV_HOSTNAME] is not None: 3365 ↛ 3371line 3365 didn't jump to line 3371, because the condition on line 3365 was never false
3366 try:
3367 self.__server_name = av_pairs[ntlm.NTLMSSP_AV_HOSTNAME][1].decode('utf-16le')
3368 except UnicodeDecodeError:
3369 # For some reason, we couldn't decode Unicode here.. silently discard the operation
3370 pass
3371 if av_pairs[ntlm.NTLMSSP_AV_DOMAINNAME] is not None: 3371 ↛ 3378line 3371 didn't jump to line 3378, because the condition on line 3371 was never false
3372 try:
3373 if self.__server_name != av_pairs[ntlm.NTLMSSP_AV_DOMAINNAME][1].decode('utf-16le'): 3373 ↛ 3378line 3373 didn't jump to line 3378, because the condition on line 3373 was never false
3374 self.__server_domain = av_pairs[ntlm.NTLMSSP_AV_DOMAINNAME][1].decode('utf-16le')
3375 except UnicodeDecodeError:
3376 # For some reason, we couldn't decode Unicode here.. silently discard the operation
3377 pass
3378 if av_pairs[ntlm.NTLMSSP_AV_DNS_DOMAINNAME] is not None: 3378 ↛ 3385line 3378 didn't jump to line 3385, because the condition on line 3378 was never false
3379 try:
3380 self.__server_dns_domain_name = av_pairs[ntlm.NTLMSSP_AV_DNS_DOMAINNAME][1].decode('utf-16le')
3381 except UnicodeDecodeError:
3382 # For some reason, we couldn't decode Unicode here.. silently discard the operation
3383 pass
3385 if av_pairs[ntlm.NTLMSSP_AV_DNS_HOSTNAME] is not None: 3385 ↛ 3392line 3385 didn't jump to line 3392, because the condition on line 3385 was never false
3386 try:
3387 self.__server_dns_host_name = av_pairs[ntlm.NTLMSSP_AV_DNS_HOSTNAME][1].decode('utf-16le')
3388 except UnicodeDecodeError:
3389 # For some reason, we couldn't decode Unicode here.. silently discard the operation
3390 pass
3392 if self._strict_hostname_validation: 3392 ↛ 3393line 3392 didn't jump to line 3393, because the condition on line 3392 was never true
3393 self.perform_hostname_validation()
3395 # Parse Version to know the target Operating system name. Not provided elsewhere anymore
3396 if 'Version' in ntlmChallenge.fields: 3396 ↛ 3402line 3396 didn't jump to line 3402, because the condition on line 3396 was never false
3397 version = ntlmChallenge['Version']
3399 if len(version) >= 4: 3399 ↛ 3402line 3399 didn't jump to line 3402, because the condition on line 3399 was never false
3400 self.__server_os_major, self.__server_os_minor, self.__server_os_build = unpack('<BBH',version[:4])
3402 type3, exportedSessionKey = ntlm.getNTLMSSPType3(auth, respToken['ResponseToken'], user, password, domain, lmhash, nthash, use_ntlmv2 = use_ntlmv2)
3404 if exportedSessionKey is not None: 3404 ↛ 3407line 3404 didn't jump to line 3407, because the condition on line 3404 was never false
3405 self._SigningSessionKey = exportedSessionKey
3407 smb = NewSMBPacket()
3409 # Are we required to sign SMB? If so we do it, if not we skip it
3410 if self._SignatureRequired: 3410 ↛ 3413line 3410 didn't jump to line 3413, because the condition on line 3410 was never false
3411 smb['Flags2'] |= SMB.FLAGS2_SMB_SECURITY_SIGNATURE
3413 respToken2 = SPNEGO_NegTokenResp()
3414 respToken2['ResponseToken'] = type3.getData()
3416 # Reusing the previous structure
3417 sessionSetup['Parameters']['SecurityBlobLength'] = len(respToken2)
3418 sessionSetup['Data']['SecurityBlob'] = respToken2.getData()
3420 # Storing some info for later use
3421 self.__server_os = sessionData['NativeOS']
3422 self.__server_lanman = sessionData['NativeLanMan']
3424 smb.addCommand(sessionSetup)
3425 self.sendSMB(smb)
3427 smb = self.recvSMB()
3428 self._uid = 0
3429 if smb.isValidAnswer(SMB.SMB_COM_SESSION_SETUP_ANDX): 3429 ↛ exitline 3429 didn't return from function 'login_extended', because the condition on line 3429 was never false
3430 self._uid = smb['Uid']
3431 sessionResponse = SMBCommand(smb['Data'][0])
3432 sessionParameters = SMBSessionSetupAndXResponse_Parameters(sessionResponse['Parameters'])
3434 self._action = sessionParameters['Action']
3435 # If smb sign required, let's enable it for the rest of the connection
3436 if self._dialects_parameters['SecurityMode'] & SMB.SECURITY_SIGNATURES_REQUIRED: 3436 ↛ 3441line 3436 didn't jump to line 3441, because the condition on line 3436 was never false
3437 self._SignSequenceNumber = 2
3438 self._SignatureEnabled = True
3440 # restore unicode flag if needed
3441 if flags2 & SMB.FLAGS2_UNICODE:
3442 self.__flags2 |= SMB.FLAGS2_UNICODE
3444 return 1
3445 else:
3446 raise Exception('Error: Could not login successfully')
3448 def getCredentials(self):
3449 return (
3450 self.__userName,
3451 self.__password,
3452 self.__domain,
3453 self.__lmhash,
3454 self.__nthash,
3455 self.__aesKey,
3456 self.__TGT,
3457 self.__TGS)
3459 def getIOCapabilities(self):
3460 res = dict()
3461 if (self._dialects_parameters['Capabilities'] & SMB.CAP_LARGE_READX) and self._SignatureEnabled is False: 3461 ↛ 3462line 3461 didn't jump to line 3462, because the condition on line 3461 was never true
3462 max_size = 65000
3463 else:
3464 max_size = self._dialects_parameters['MaxBufferSize'] # Read in multiple KB blocks
3465 res['MaxReadSize'] = max_size
3466 res['MaxWriteSize'] = max_size
3467 return res
3469 def login(self, user, password, domain = '', lmhash = '', nthash = '', ntlm_fallback = True):
3471 # If we have hashes, normalize them
3472 if lmhash != '' or nthash != '':
3473 if len(lmhash) % 2: 3473 ↛ 3474line 3473 didn't jump to line 3474, because the condition on line 3473 was never true
3474 lmhash = '0%s' % lmhash
3475 if len(nthash) % 2: 3475 ↛ 3476line 3475 didn't jump to line 3476, because the condition on line 3475 was never true
3476 nthash = '0%s' % nthash
3477 try: # just in case they were converted already
3478 lmhash = a2b_hex(lmhash)
3479 nthash = a2b_hex(nthash)
3480 except:
3481 pass
3483 self.__userName = user
3484 self.__password = password
3485 self.__domain = domain
3486 self.__lmhash = lmhash
3487 self.__nthash = nthash
3488 self.__aesKey = ''
3489 self.__TGT = None
3490 self.__TGS = None
3492 if self._dialects_parameters['Capabilities'] & SMB.CAP_EXTENDED_SECURITY: 3492 ↛ 3502line 3492 didn't jump to line 3502, because the condition on line 3492 was never false
3493 try:
3494 self.login_extended(user, password, domain, lmhash, nthash, use_ntlmv2 = True)
3495 except:
3496 # If the target OS is Windows 5.0 or Samba, let's try using NTLMv1
3497 if ntlm_fallback and ((self.get_server_lanman().find('Windows 2000') != -1) or (self.get_server_lanman().find('Samba') != -1)):
3498 self.login_extended(user, password, domain, lmhash, nthash, use_ntlmv2 = False)
3499 self.__isNTLMv2 = False
3500 else:
3501 raise
3502 elif ntlm_fallback:
3503 self.login_standard(user, password, domain, lmhash, nthash)
3504 self.__isNTLMv2 = False
3505 else:
3506 raise SessionError('Cannot authenticate against target, enable ntlm_fallback')
3508 def login_standard(self, user, password, domain = '', lmhash = '', nthash = ''):
3510 # login feature does not support unicode
3511 # disable it if enabled
3512 flags2 = self.__flags2
3513 if flags2 & SMB.FLAGS2_UNICODE:
3514 self.__flags2 = flags2 & (flags2 ^ SMB.FLAGS2_UNICODE)
3516 # Only supports NTLMv1
3517 # Password is only encrypted if the server passed us an "encryption key" during protocol dialect negotiation
3518 if self._dialects_parameters['ChallengeLength'] > 0:
3519 if lmhash != '' or nthash != '':
3520 pwd_ansi = self.get_ntlmv1_response(lmhash)
3521 pwd_unicode = self.get_ntlmv1_response(nthash)
3522 elif password:
3523 lmhash = ntlm.compute_lmhash(password)
3524 nthash = ntlm.compute_nthash(password)
3525 pwd_ansi = self.get_ntlmv1_response(lmhash)
3526 pwd_unicode = self.get_ntlmv1_response(nthash)
3527 else: # NULL SESSION
3528 pwd_ansi = ''
3529 pwd_unicode = ''
3530 else:
3531 pwd_ansi = password
3532 pwd_unicode = ''
3534 smb = NewSMBPacket()
3536 sessionSetup = SMBCommand(SMB.SMB_COM_SESSION_SETUP_ANDX)
3537 sessionSetup['Parameters'] = SMBSessionSetupAndX_Parameters()
3538 sessionSetup['Data'] = SMBSessionSetupAndX_Data()
3540 sessionSetup['Parameters']['MaxBuffer'] = 61440
3541 sessionSetup['Parameters']['MaxMpxCount'] = 2
3542 sessionSetup['Parameters']['VCNumber'] = os.getpid() & 0xFFFF # Value has to be expressed in 2 bytes
3543 sessionSetup['Parameters']['SessionKey'] = self._dialects_parameters['SessionKey']
3544 sessionSetup['Parameters']['AnsiPwdLength'] = len(pwd_ansi)
3545 sessionSetup['Parameters']['UnicodePwdLength'] = len(pwd_unicode)
3546 sessionSetup['Parameters']['Capabilities'] = SMB.CAP_RAW_MODE | SMB.CAP_USE_NT_ERRORS | SMB.CAP_LARGE_READX | SMB.CAP_LARGE_WRITEX
3548 sessionSetup['Data']['AnsiPwd'] = pwd_ansi
3549 sessionSetup['Data']['UnicodePwd'] = pwd_unicode
3550 sessionSetup['Data']['Account'] = str(user)
3551 sessionSetup['Data']['PrimaryDomain'] = str(domain)
3552 sessionSetup['Data']['NativeOS'] = str(os.name)
3553 sessionSetup['Data']['NativeLanMan'] = 'pysmb'
3554 smb.addCommand(sessionSetup)
3556 self.sendSMB(smb)
3558 smb = self.recvSMB()
3559 if smb.isValidAnswer(SMB.SMB_COM_SESSION_SETUP_ANDX):
3560 # We will need to use this uid field for all future requests/responses
3561 self._uid = smb['Uid']
3562 sessionResponse = SMBCommand(smb['Data'][0])
3563 sessionParameters = SMBSessionSetupAndXResponse_Parameters(sessionResponse['Parameters'])
3564 sessionData = SMBSessionSetupAndXResponse_Data(flags = smb['Flags2'], data = sessionResponse['Data'])
3566 self._action = sessionParameters['Action']
3568 # Still gotta figure out how to do this with no EXTENDED_SECURITY
3569 if sessionParameters['Action'] & SMB_SETUP_USE_LANMAN_KEY == 0:
3570 self._SigningChallengeResponse = sessionSetup['Data']['UnicodePwd']
3571 self._SigningSessionKey = nthash
3572 else:
3573 self._SigningChallengeResponse = sessionSetup['Data']['AnsiPwd']
3574 self._SigningSessionKey = lmhash
3576 #self._SignSequenceNumber = 1
3577 #self.checkSignSMB(smb, self._SigningSessionKey ,self._SigningChallengeResponse)
3578 #self._SignatureEnabled = True
3579 self.__server_os = sessionData['NativeOS']
3580 self.__server_lanman = sessionData['NativeLanMan']
3581 self.__server_domain = sessionData['PrimaryDomain']
3583 # restore unicode flag if needed
3584 if flags2 & SMB.FLAGS2_UNICODE:
3585 self.__flags2 |= SMB.FLAGS2_UNICODE
3587 return 1
3588 else:
3589 raise Exception('Error: Could not login successfully')
3591 def waitNamedPipe(self, tid, pipe, timeout = 5, noAnswer = 0):
3592 smb = NewSMBPacket()
3593 smb['Tid'] = tid
3595 transCommand = SMBCommand(SMB.SMB_COM_TRANSACTION)
3596 transCommand['Parameters'] = SMBTransaction_Parameters()
3597 transCommand['Data'] = SMBTransaction_Data()
3599 setup = '\x53\x00\x00\x00'
3600 name = '\\PIPE%s\x00' % pipe
3601 transCommand['Parameters']['Setup'] = setup
3602 transCommand['Parameters']['TotalParameterCount'] = 0
3603 transCommand['Parameters']['TotalDataCount'] = 0
3604 transCommand['Parameters']['MaxParameterCount'] = 0
3605 transCommand['Parameters']['MaxDataCount'] = 0
3606 transCommand['Parameters']['Timeout'] = timeout * 1000
3608 transCommand['Parameters']['ParameterCount'] = 0
3609 transCommand['Parameters']['ParameterOffset'] = 32+3+28+len(setup)+len(name)
3611 transCommand['Parameters']['DataCount'] = 0
3612 transCommand['Parameters']['DataOffset'] = 0
3614 transCommand['Data']['Name'] = name
3615 transCommand['Data']['Trans_Parameters'] = ''
3616 transCommand['Data']['Trans_Data'] = ''
3618 if noAnswer:
3619 transCommand['Parameters']['Flags'] = TRANS_NO_RESPONSE
3621 smb.addCommand(transCommand)
3622 self.sendSMB(smb)
3624 smb = self.recvSMB()
3625 if smb.isValidAnswer(SMB.SMB_COM_TRANSACTION):
3626 return 1
3627 return 0
3629 def read(self, tid, fid, offset=0, max_size = None, wait_answer=1):
3630 if not max_size:
3631 max_size = self._dialects_parameters['MaxBufferSize'] # Read in multiple KB blocks
3633 # max_size is not working, because although it would, the server returns an error (More data avail)
3635 smb = NewSMBPacket()
3636 smb['Tid'] = tid
3638 read = SMBCommand(SMB.SMB_COM_READ)
3639 read['Parameters'] = SMBRead_Parameters()
3640 read['Parameters']['Fid'] = fid
3641 read['Parameters']['Offset'] = offset
3642 read['Parameters']['Count'] = max_size
3643 smb.addCommand(read)
3645 if wait_answer:
3646 while 1:
3647 self.sendSMB(smb)
3648 ans = self.recvSMB()
3650 if ans.isValidAnswer(SMB.SMB_COM_READ):
3651 readResponse = SMBCommand(ans['Data'][0])
3652 readData = SMBReadResponse_Data(readResponse['Data'])
3654 return readData['Data']
3656 return None
3658 def read_andx(self, tid, fid, offset=0, max_size = None, wait_answer=1, smb_packet=None):
3659 if not max_size: 3659 ↛ 3660line 3659 didn't jump to line 3660, because the condition on line 3659 was never true
3660 if (self._dialects_parameters['Capabilities'] & SMB.CAP_LARGE_READX) and self._SignatureEnabled is False:
3661 max_size = 65000
3662 else:
3663 max_size = self._dialects_parameters['MaxBufferSize'] # Read in multiple KB blocks
3665 # max_size is not working, because although it would, the server returns an error (More data avail)
3667 if smb_packet is None: 3667 ↛ 3678line 3667 didn't jump to line 3678, because the condition on line 3667 was never false
3668 smb = NewSMBPacket()
3669 smb['Tid'] = tid
3671 readAndX = SMBCommand(SMB.SMB_COM_READ_ANDX)
3672 readAndX['Parameters'] = SMBReadAndX_Parameters()
3673 readAndX['Parameters']['Fid'] = fid
3674 readAndX['Parameters']['Offset'] = offset
3675 readAndX['Parameters']['MaxCount'] = max_size
3676 smb.addCommand(readAndX)
3677 else:
3678 smb = smb_packet
3680 if wait_answer: 3680 ↛ 3699line 3680 didn't jump to line 3699, because the condition on line 3680 was never false
3681 answer = b''
3682 while 1:
3683 self.sendSMB(smb)
3684 ans = self.recvSMB()
3686 if ans.isValidAnswer(SMB.SMB_COM_READ_ANDX): 3686 ↛ 3683line 3686 didn't jump to line 3683, because the condition on line 3686 was never false
3687 # XXX Here we are only using a few fields from the response
3688 readAndXResponse = SMBCommand(ans['Data'][0])
3689 readAndXParameters = SMBReadAndXResponse_Parameters(readAndXResponse['Parameters'])
3691 offset = readAndXParameters['DataOffset']
3692 count = readAndXParameters['DataCount']+0x10000*readAndXParameters['DataCount_Hi']
3693 answer += ans.getData()[offset:offset+count]
3694 if not ans.isMoreData(): 3694 ↛ 3696line 3694 didn't jump to line 3696, because the condition on line 3694 was never false
3695 return answer
3696 max_size = min(max_size, readAndXParameters['Remaining'])
3697 readAndX['Parameters']['Offset'] += count # XXX Offset is not important (apparently)
3698 else:
3699 self.sendSMB(smb)
3700 ans = self.recvSMB()
3702 try:
3703 if ans.isValidAnswer(SMB.SMB_COM_READ_ANDX):
3704 return ans
3705 else:
3706 return None
3707 except:
3708 return ans
3710 return None
3712 def read_raw(self, tid, fid, offset=0, max_size = None, wait_answer=1):
3713 if not max_size:
3714 max_size = self._dialects_parameters['MaxBufferSize'] # Read in multiple KB blocks
3716 # max_size is not working, because although it would, the server returns an error (More data avail)
3717 smb = NewSMBPacket()
3718 smb['Tid'] = tid
3720 readRaw = SMBCommand(SMB.SMB_COM_READ_RAW)
3721 readRaw['Parameters'] = SMBReadRaw_Parameters()
3722 readRaw['Parameters']['Fid'] = fid
3723 readRaw['Parameters']['Offset'] = offset
3724 readRaw['Parameters']['MaxCount'] = max_size
3725 smb.addCommand(readRaw)
3727 self.sendSMB(smb)
3728 if wait_answer:
3729 data = self._sess.recv_packet(self.__timeout).get_trailer()
3730 if not data:
3731 # If there is no data it means there was an error
3732 data = self.read_andx(tid, fid, offset, max_size)
3733 return data
3735 return None
3737 def write(self,tid,fid,data, offset = 0, wait_answer=1):
3738 smb = NewSMBPacket()
3739 smb['Tid'] = tid
3741 write = SMBCommand(SMB.SMB_COM_WRITE)
3742 write['Parameters'] = SMBWrite_Parameters()
3743 write['Data'] = SMBWrite_Data()
3744 write['Parameters']['Fid'] = fid
3745 write['Parameters']['Count'] = len(data)
3746 write['Parameters']['Offset'] = offset
3747 write['Parameters']['Remaining'] = len(data)
3748 write['Data']['Data'] = data
3749 smb.addCommand(write)
3751 self.sendSMB(smb)
3753 if wait_answer:
3754 smb = self.recvSMB()
3755 if smb.isValidAnswer(SMB.SMB_COM_WRITE):
3756 return smb
3757 return None
3759 def write_andx(self,tid,fid,data, offset = 0, wait_answer=1, write_pipe_mode = False, smb_packet=None):
3760 if smb_packet is None: 3760 ↛ 3810line 3760 didn't jump to line 3810, because the condition on line 3760 was never false
3761 smb = NewSMBPacket()
3762 smb['Tid'] = tid
3764 writeAndX = SMBCommand(SMB.SMB_COM_WRITE_ANDX)
3765 smb.addCommand(writeAndX)
3767 writeAndX['Parameters'] = SMBWriteAndX_Parameters()
3768 writeAndX['Parameters']['Fid'] = fid
3769 writeAndX['Parameters']['Offset'] = offset
3770 writeAndX['Parameters']['WriteMode'] = 8
3771 writeAndX['Parameters']['Remaining'] = len(data)
3772 writeAndX['Parameters']['DataLength'] = len(data)
3773 writeAndX['Parameters']['DataOffset'] = len(smb) # this length already includes the parameter
3774 writeAndX['Data'] = data
3776 if write_pipe_mode is True: 3776 ↛ 3778line 3776 didn't jump to line 3778, because the condition on line 3776 was never true
3777 # First of all we gotta know what the MaxBuffSize is
3778 maxBuffSize = self._dialects_parameters['MaxBufferSize']
3779 if len(data) > maxBuffSize:
3780 chunks_size = maxBuffSize - 60
3781 writeAndX['Parameters']['WriteMode'] = 0x0c
3782 sendData = b'\xff\xff' + data
3783 totalLen = len(sendData)
3784 writeAndX['Parameters']['DataLength'] = chunks_size
3785 writeAndX['Parameters']['Remaining'] = totalLen-2
3786 writeAndX['Data'] = sendData[:chunks_size]
3788 self.sendSMB(smb)
3789 if wait_answer:
3790 smbResp = self.recvSMB()
3791 smbResp.isValidAnswer(SMB.SMB_COM_WRITE_ANDX)
3793 alreadySent = chunks_size
3794 sendData = sendData[chunks_size:]
3796 while alreadySent < totalLen:
3797 writeAndX['Parameters']['WriteMode'] = 0x04
3798 writeAndX['Parameters']['DataLength'] = len(sendData[:chunks_size])
3799 writeAndX['Data'] = sendData[:chunks_size]
3800 self.sendSMB(smb)
3801 if wait_answer:
3802 smbResp = self.recvSMB()
3803 smbResp.isValidAnswer(SMB.SMB_COM_WRITE_ANDX)
3804 alreadySent += writeAndX['Parameters']['DataLength']
3805 sendData = sendData[chunks_size:]
3807 return smbResp
3809 else:
3810 smb = smb_packet
3812 self.sendSMB(smb)
3814 if wait_answer: 3814 ↛ 3818line 3814 didn't jump to line 3818, because the condition on line 3814 was never false
3815 smb = self.recvSMB()
3816 if smb.isValidAnswer(SMB.SMB_COM_WRITE_ANDX): 3816 ↛ 3818line 3816 didn't jump to line 3818, because the condition on line 3816 was never false
3817 return smb
3818 return None
3820 def write_raw(self,tid,fid,data, offset = 0, wait_answer=1):
3821 LOG.warning("[MS-CIFS] This command was introduced in the CorePlus dialect, but is often listed as part of the LAN Manager 1.0 dialect.This command has been deprecated.Clients SHOULD use SMB_COM_WRITE_ANDX")
3822 smb = NewSMBPacket()
3823 smb['Tid'] = tid
3825 writeRaw = SMBCommand(SMB.SMB_COM_WRITE_RAW)
3826 writeRaw['Parameters'] = SMBWriteRaw_Parameters()
3827 writeRaw['Parameters']['Fid'] = fid
3828 writeRaw['Parameters']['Offset'] = offset
3829 writeRaw['Parameters']['Count'] = len(data)
3830 writeRaw['Parameters']['DataLength'] = 0
3831 writeRaw['Parameters']['DataOffset'] = 0
3832 smb.addCommand(writeRaw)
3834 self.sendSMB(smb)
3835 self._sess.send_packet(data)
3837 if wait_answer:
3838 smb = self.recvSMB()
3839 if smb.isValidAnswer(SMB.SMB_COM_WRITE_RAW):
3840 return smb
3841 return None
3843 def TransactNamedPipe(self, tid, fid, data = '', noAnswer = 0, waitAnswer = 1, offset = 0):
3844 self.send_trans(tid,pack('<HH', 0x26, fid),'\\PIPE\\\x00','',data, noAnswer = noAnswer)
3846 if noAnswer or not waitAnswer:
3847 return
3848 smb = self.recvSMB()
3849 if smb.isValidAnswer(SMB.SMB_COM_TRANSACTION):
3850 transResponse = SMBCommand(smb['Data'][0])
3851 transParameters = SMBTransactionResponse_Parameters(transResponse['Parameters'])
3852 return transResponse['Data'][-transParameters['TotalDataCount']:] # Remove Potential Prefix Padding
3853 return None
3855 def TransactNamedPipeRecv(self):
3856 s = self.recvSMB()
3857 if s.isValidAnswer(SMB.SMB_COM_TRANSACTION):
3858 transResponse = SMBCommand(s['Data'][0])
3859 transParameters = SMBTransactionResponse_Parameters(transResponse['Parameters'])
3860 return transResponse['Data'][-transParameters['TotalDataCount']:] # Remove Potential Prefix Padding
3861 return None
3863 def nt_create_andx(self,tid,filename, smb_packet=None, cmd = None, shareAccessMode = FILE_SHARE_READ | FILE_SHARE_WRITE, disposition = FILE_OPEN, accessMask = 0x2019f):
3864 filename = filename.replace('/', '\\')
3865 filename = filename.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else filename
3867 if smb_packet is None: 3867 ↛ 3871line 3867 didn't jump to line 3871, because the condition on line 3867 was never false
3868 smb = NewSMBPacket()
3869 smb['Tid'] = tid
3870 else:
3871 smb = smb_packet
3873 if cmd is None:
3874 ntCreate = SMBCommand(SMB.SMB_COM_NT_CREATE_ANDX)
3875 ntCreate['Parameters'] = SMBNtCreateAndX_Parameters()
3876 ntCreate['Data'] = SMBNtCreateAndX_Data(flags=self.__flags2)
3877 ntCreate['Parameters']['FileNameLength'] = len(filename)
3878 ntCreate['Parameters']['CreateFlags'] = 0x16
3879 ntCreate['Parameters']['AccessMask'] = accessMask
3880 ntCreate['Parameters']['CreateOptions'] = 0x40
3881 ntCreate['Parameters']['ShareAccess'] = shareAccessMode
3882 ntCreate['Parameters']['Disposition'] = disposition
3883 ntCreate['Data']['FileName'] = filename
3885 if self.__flags2 & SMB.FLAGS2_UNICODE:
3886 ntCreate['Data']['Pad'] = 0x0
3887 else:
3888 ntCreate = cmd
3890 smb.addCommand(ntCreate)
3892 self.sendSMB(smb)
3894 while 1:
3895 smb = self.recvSMB()
3896 if smb.isValidAnswer(SMB.SMB_COM_NT_CREATE_ANDX): 3896 ↛ 3895line 3896 didn't jump to line 3895, because the condition on line 3896 was never false
3897 # XXX Here we are ignoring the rest of the response
3898 ntCreateResponse = SMBCommand(smb['Data'][0])
3899 ntCreateParameters = SMBNtCreateAndXResponse_Parameters(ntCreateResponse['Parameters'])
3901 self.fid = ntCreateParameters['Fid']
3902 return ntCreateParameters['Fid']
3904 def logoff(self):
3905 smb = NewSMBPacket()
3907 logOff = SMBCommand(SMB.SMB_COM_LOGOFF_ANDX)
3908 logOff['Parameters'] = SMBLogOffAndX()
3909 smb.addCommand(logOff)
3911 self.sendSMB(smb)
3912 self.recvSMB()
3913 # Let's clear some fields so you can login again under the same session
3914 self._uid = 0
3916 def list_path(self, service, path = '*', password = None):
3917 path = path.replace('/', '\\')
3918 path = path.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else path
3920 tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
3921 try:
3922 findFirstParameter = SMBFindFirst2_Parameters(self.__flags2)
3923 findFirstParameter['SearchAttributes'] = SMB_FILE_ATTRIBUTE_DIRECTORY | SMB_FILE_ATTRIBUTE_HIDDEN | \
3924 SMB_FILE_ATTRIBUTE_SYSTEM | SMB_FILE_ATTRIBUTE_READONLY | \
3925 SMB_FILE_ATTRIBUTE_ARCHIVE
3926 findFirstParameter['SearchCount'] = 512
3927 findFirstParameter['Flags'] = SMB_FIND_RETURN_RESUME_KEYS | SMB_FIND_CLOSE_AT_EOS
3928 findFirstParameter['InformationLevel'] = SMB_FIND_FILE_BOTH_DIRECTORY_INFO
3929 findFirstParameter['SearchStorageType'] = 0
3930 if self.__flags2 & SMB.FLAGS2_UNICODE:
3931 findFirstParameter['FileName'] = path + b'\x00\x00'
3932 else:
3933 findFirstParameter['FileName'] = path + '\x00'
3934 self.send_trans2(tid, SMB.TRANS2_FIND_FIRST2, '\x00', findFirstParameter, '')
3935 files = [ ]
3937 totalDataCount = 1
3938 findData = b''
3939 findFirst2ParameterBlock = b''
3940 while len(findData) < totalDataCount:
3941 resp = self.recvSMB()
3943 if resp.isValidAnswer(SMB.SMB_COM_TRANSACTION2): 3943 ↛ 3940line 3943 didn't jump to line 3940, because the condition on line 3943 was never false
3944 trans2Response = SMBCommand(resp['Data'][0])
3945 trans2Parameters = SMBTransaction2Response_Parameters(trans2Response['Parameters'])
3946 totalDataCount = trans2Parameters['TotalDataCount']
3947 findFirst2ParameterBlock += trans2Response['Data'][trans2Parameters['ParameterOffset']-55:][:trans2Parameters['ParameterCount']]
3948 findData += trans2Response['Data'][trans2Parameters['DataOffset']-55:]
3950 findParameterBlock = SMBFindFirst2Response_Parameters(findFirst2ParameterBlock)
3951 # Save the SID for resume operations
3952 sid = findParameterBlock['SID']
3954 while findParameterBlock['SearchCount'] > 0: 3954 ↛ 3999line 3954 didn't jump to line 3999, because the condition on line 3954 was never false
3955 record = SMBFindFileBothDirectoryInfo(data = findData)
3957 shortname = record['ShortName'].decode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else \
3958 record['ShortName'].decode('cp437')
3959 filename = record['FileName'].decode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else \
3960 record['FileName'].decode('cp437')
3962 fileRecord = SharedFile(record['CreationTime'], record['LastAccessTime'], record['LastChangeTime'],
3963 record['EndOfFile'], record['AllocationSize'], record['ExtFileAttributes'],
3964 shortname, filename)
3965 files.append(fileRecord)
3966 if record['NextEntryOffset'] > 0 and len(findData[record['NextEntryOffset']:]) > 0:
3967 findData = findData[record['NextEntryOffset']:]
3968 else:
3969 # More data to search?
3970 if findParameterBlock['EndOfSearch'] == 0: 3970 ↛ 3971, 3970 ↛ 39972 missed branches: 1) line 3970 didn't jump to line 3971, because the condition on line 3970 was never true, 2) line 3970 didn't jump to line 3997, because the condition on line 3970 was never false
3971 resume_filename = record['FileName']
3972 findNextParameter = SMBFindNext2_Parameters()
3973 findNextParameter['SID'] = sid
3974 findNextParameter['SearchCount'] = 1024
3975 findNextParameter['InformationLevel'] = SMB_FIND_FILE_BOTH_DIRECTORY_INFO
3976 findNextParameter['ResumeKey'] = 0
3977 findNextParameter['Flags'] = SMB_FIND_RETURN_RESUME_KEYS | SMB_FIND_CLOSE_AT_EOS
3978 if self.__flags2 & SMB.FLAGS2_UNICODE:
3979 findNextParameter['FileName'] = resume_filename + b'\x00\x00'
3980 else:
3981 findNextParameter['FileName'] = resume_filename + b'\x00'
3982 self.send_trans2(tid, SMB.TRANS2_FIND_NEXT2, '\x00', findNextParameter, '')
3983 findData = b''
3984 findNext2ParameterBlock = b''
3985 totalDataCount = 1
3986 while len(findData) < totalDataCount:
3987 resp = self.recvSMB()
3989 if resp.isValidAnswer(SMB.SMB_COM_TRANSACTION2):
3990 trans2Response = SMBCommand(resp['Data'][0])
3991 trans2Parameters = SMBTransaction2Response_Parameters(trans2Response['Parameters'])
3992 totalDataCount = trans2Parameters['TotalDataCount']
3993 findNext2ParameterBlock += trans2Response['Data'][trans2Parameters['ParameterOffset']-55:][:trans2Parameters['ParameterCount']]
3994 findData += trans2Response['Data'][trans2Parameters['DataOffset']-55:]
3995 findParameterBlock = SMBFindNext2Response_Parameters(findNext2ParameterBlock)
3996 else:
3997 break
3998 finally:
3999 self.disconnect_tree(tid)
4001 return files
4003 def retr_file(self, service, filename, callback, mode = FILE_OPEN, offset = 0, password = None, shareAccessMode = SMB_ACCESS_READ):
4004 filename = filename.replace('/', '\\')
4006 fid = -1
4007 tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
4008 try:
4009 fid = self.nt_create_andx(tid, filename, shareAccessMode = shareAccessMode, accessMask = 0x20089)
4011 res = self.query_file_info(tid, fid)
4012 datasize = SMBQueryFileStandardInfo(res)['EndOfFile']
4014 self.__nonraw_retr_file(tid, fid, offset, datasize, callback)
4015 finally:
4016 if fid >= 0: 4016 ↛ 4018line 4016 didn't jump to line 4018, because the condition on line 4016 was never false
4017 self.close(tid, fid)
4018 self.disconnect_tree(tid)
4020 def stor_file(self, service, filename, callback, mode = FILE_OVERWRITE_IF, offset = 0, password = None, shareAccessMode = SMB_ACCESS_WRITE):
4021 filename = filename.replace('/', '\\')
4023 fid = -1
4024 tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
4025 try:
4026 fid = self.nt_create_andx(tid, filename, shareAccessMode = shareAccessMode, disposition = mode )
4028 self.__nonraw_stor_file(tid, fid, offset, 0, callback)
4029 finally:
4030 if fid >= 0: 4030 ↛ 4032line 4030 didn't jump to line 4032, because the condition on line 4030 was never false
4031 self.close(tid, fid)
4032 self.disconnect_tree(tid)
4034 def stor_file_nonraw(self, service, filename, callback, mode = FILE_OVERWRITE_IF, offset = 0, password = None, shareAccessMode = SMB_ACCESS_WRITE ):
4035 filename = filename.replace('/', '\\')
4037 fid = -1
4038 tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
4039 try:
4040 fid = self.nt_create_andx(tid, filename, shareAccessMode = shareAccessMode, disposition = mode)
4041 self.__nonraw_stor_file(tid, fid, offset, 0, callback)
4042 finally:
4043 if fid >= 0:
4044 self.close(tid, fid)
4045 self.disconnect_tree(tid)
4047 def check_dir(self, service, path, password = None):
4048 path = path.replace('/', '\\')
4049 tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
4050 try:
4051 smb = NewSMBPacket()
4052 smb['Tid'] = tid
4053 smb['Mid'] = 0
4055 cmd = SMBCommand(SMB.SMB_COM_CHECK_DIRECTORY)
4056 cmd['Parameters'] = ''
4057 cmd['Data'] = SMBCheckDirectory_Data(flags = self.__flags2)
4058 cmd['Data']['DirectoryName'] = path.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else path
4059 smb.addCommand(cmd)
4061 self.sendSMB(smb)
4063 while 1:
4064 s = self.recvSMB()
4065 if s.isValidAnswer(SMB.SMB_COM_CHECK_DIRECTORY): 4065 ↛ 4064line 4065 didn't jump to line 4064, because the condition on line 4065 was never false
4066 return
4067 finally:
4068 self.disconnect_tree(tid)
4070 def remove(self, service, path, password = None):
4071 path = path.replace('/', '\\')
4072 # Perform a list to ensure the path exists
4073 self.list_path(service, path, password)
4075 tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
4076 try:
4077 smb = NewSMBPacket()
4078 smb['Tid'] = tid
4079 smb['Mid'] = 0
4081 cmd = SMBCommand(SMB.SMB_COM_DELETE)
4082 cmd['Parameters'] = SMBDelete_Parameters()
4083 cmd['Parameters']['SearchAttributes'] = ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE
4084 cmd['Data'] = SMBDelete_Data(flags = self.__flags2)
4085 cmd['Data']['FileName'] = (path + '\x00').encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else (path + '\x00')
4086 smb.addCommand(cmd)
4088 self.sendSMB(smb)
4090 while 1:
4091 s = self.recvSMB()
4092 if s.isValidAnswer(SMB.SMB_COM_DELETE): 4092 ↛ 4091line 4092 didn't jump to line 4091, because the condition on line 4092 was never false
4093 return
4094 finally:
4095 self.disconnect_tree(tid)
4097 def rmdir(self, service, path, password = None):
4098 path = path.replace('/', '\\')
4099 # Check that the directory exists
4100 self.check_dir(service, path, password)
4102 tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
4103 try:
4104 path = path.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else path
4106 smb = NewSMBPacket()
4107 smb['Tid'] = tid
4108 createDir = SMBCommand(SMB.SMB_COM_DELETE_DIRECTORY)
4109 createDir['Data'] = SMBDeleteDirectory_Data(flags=self.__flags2)
4110 createDir['Data']['DirectoryName'] = path
4111 smb.addCommand(createDir)
4113 self.sendSMB(smb)
4115 while 1:
4116 s = self.recvSMB()
4117 if s.isValidAnswer(SMB.SMB_COM_DELETE_DIRECTORY): 4117 ↛ 4116line 4117 didn't jump to line 4116, because the condition on line 4117 was never false
4118 return
4119 finally:
4120 self.disconnect_tree(tid)
4122 def mkdir(self, service, path, password = None):
4123 path = path.replace('/', '\\')
4124 tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
4125 try:
4126 path = path.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else path
4128 smb = NewSMBPacket()
4129 smb['Tid'] = tid
4130 smb['Mid'] = 0
4132 createDir = SMBCommand(SMB.SMB_COM_CREATE_DIRECTORY)
4133 createDir['Data'] = SMBCreateDirectory_Data(flags=self.__flags2)
4134 createDir['Data']['DirectoryName'] = path
4135 smb.addCommand(createDir)
4137 self.sendSMB(smb)
4139 smb = self.recvSMB()
4140 if smb.isValidAnswer(SMB.SMB_COM_CREATE_DIRECTORY): 4140 ↛ 4142line 4140 didn't jump to line 4142, because the condition on line 4140 was never false
4141 return 1
4142 return 0
4143 finally:
4144 self.disconnect_tree(tid) 4144 ↛ 4142line 4144 didn't jump to line 4142, because the return on line 4142 wasn't executed
4146 def rename(self, service, old_path, new_path, password = None):
4147 old_path = old_path.replace('/', '\\')
4148 new_path = new_path.replace('/', '\\')
4149 tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
4150 try:
4151 smb = NewSMBPacket()
4152 smb['Tid'] = tid
4153 smb['Mid'] = 0
4155 renameCmd = SMBCommand(SMB.SMB_COM_RENAME)
4156 renameCmd['Parameters'] = SMBRename_Parameters()
4157 renameCmd['Parameters']['SearchAttributes'] = ATTR_SYSTEM | ATTR_HIDDEN | ATTR_DIRECTORY
4158 renameCmd['Data'] = SMBRename_Data(flags = self.__flags2)
4159 renameCmd['Data']['OldFileName'] = old_path.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else old_path
4160 renameCmd['Data']['NewFileName'] = new_path.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else new_path
4161 smb.addCommand(renameCmd)
4163 self.sendSMB(smb)
4165 smb = self.recvSMB()
4166 if smb.isValidAnswer(SMB.SMB_COM_RENAME): 4166 ↛ 4168line 4166 didn't jump to line 4168, because the condition on line 4166 was never false
4167 return 1
4168 return 0
4169 finally:
4170 self.disconnect_tree(tid) 4170 ↛ 4168line 4170 didn't jump to line 4168, because the return on line 4168 wasn't executed
4172 def writeFile(self, treeId, fileId, data, offset = 0):
4173 if (self._dialects_parameters['Capabilities'] & SMB.CAP_LARGE_WRITEX) and self._SignatureEnabled is False: 4173 ↛ 4174line 4173 didn't jump to line 4174, because the condition on line 4173 was never true
4174 max_buf_size = 65000
4175 else:
4176 max_buf_size = self._dialects_parameters['MaxBufferSize'] & ~0x3ff # Write in multiple KB blocks
4178 write_offset = offset
4179 while 1:
4180 if len(data) == 0:
4181 break
4182 writeData = data[:max_buf_size]
4183 data = data[max_buf_size:]
4185 smb = self.write_andx(treeId,fileId,writeData, write_offset)
4186 writeResponse = SMBCommand(smb['Data'][0])
4187 writeResponseParameters = SMBWriteAndXResponse_Parameters(writeResponse['Parameters'])
4188 write_offset += writeResponseParameters['Count']
4190 def get_socket(self):
4191 return self._sess.get_socket()
4193 def send_nt_trans(self, tid, subcommand, max_param_count, setup='', param='', data=''):
4194 """
4195 [MS-CIFS]: 2.2.4.62.1 SMB_COM_NT_TRANSACT request.
4196 :param tid:
4197 :param subcommand: The transaction subcommand code
4198 :param max_param_count: This field MUST be set as specified in the subsections of Transaction subcommands.
4199 :param setup: Transaction context to the server, depends on transaction subcommand.
4200 :param param: Subcommand parameter bytes if any, depends on transaction subcommand.
4201 :param data: Subcommand data bytes if any, depends on transaction subcommand.
4202 :return: Buffer relative to requested subcommand.
4203 """
4204 smb_packet = NewSMBPacket()
4205 smb_packet['Tid'] = tid
4206 # setup depends on NT_TRANSACT subcommands so it may be 0.
4207 setup_bytes = pack('<H', setup) if setup != '' else ''
4209 transCommand = SMBCommand(SMB.SMB_COM_NT_TRANSACT)
4210 transCommand['Parameters'] = SMBNTTransaction_Parameters()
4211 transCommand['Parameters']['MaxDataCount'] = self._dialects_parameters['MaxBufferSize']
4212 transCommand['Parameters']['Setup'] = setup_bytes
4213 transCommand['Parameters']['Function'] = subcommand
4214 transCommand['Parameters']['TotalParameterCount'] = len(param)
4215 transCommand['Parameters']['TotalDataCount'] = len(data)
4216 transCommand['Parameters']['MaxParameterCount'] = max_param_count
4217 transCommand['Parameters']['MaxSetupCount'] = 0
4219 transCommand['Data'] = SMBNTTransaction_Data()
4221 # SMB header size + SMB_COM_NT_TRANSACT parameters size + length of setup bytes.
4222 offset = 32 + 3 + 38 + len(setup_bytes)
4223 transCommand['Data']['Pad1'] = ''
4224 if offset % 4 != 0:
4225 transCommand['Data']['Pad1'] = '\0' * (4 - offset % 4)
4226 offset += (4 - offset % 4) # pad1 length
4228 if len(param) > 0:
4229 transCommand['Parameters']['ParameterOffset'] = offset
4230 else:
4231 transCommand['Parameters']['ParameterOffset'] = 0
4233 offset += len(param)
4234 transCommand['Data']['Pad2'] = ''
4235 if offset % 4 != 0:
4236 transCommand['Data']['Pad2'] = '\0' * (4 - offset % 4)
4237 offset += (4 - offset % 4)
4239 if len(data) > 0:
4240 transCommand['Parameters']['DataOffset'] = offset
4241 else:
4242 transCommand['Parameters']['DataOffset'] = 0
4244 transCommand['Parameters']['DataCount'] = len(data)
4245 transCommand['Parameters']['ParameterCount'] = len(param)
4246 transCommand['Data']['NT_Trans_Parameters'] = param
4247 transCommand['Data']['NT_Trans_Data'] = data
4248 smb_packet.addCommand(transCommand)
4250 self.sendSMB(smb_packet)
4252 def query_sec_info(self, tid, fid, additional_information=7):
4253 """
4254 [MS-CIFS]: 2.2.7.6.1
4255 NT_TRANSACT_QUERY_SECURITY_DESC 0x0006
4256 :param tid: valid tree id.
4257 :param fid: valid file handle.
4258 :param additional_information: SecurityInfoFields. default = owner + group + dacl ie. 7
4259 :return: security descriptor buffer
4260 """
4261 self.send_nt_trans(tid, subcommand=0x0006, max_param_count=4,
4262 param=pack('<HHL', fid, 0x0000, additional_information))
4263 resp = self.recvSMB()
4264 if resp.isValidAnswer(SMB.SMB_COM_NT_TRANSACT):
4265 nt_trans_response = SMBCommand(resp['Data'][0])
4266 nt_trans_parameters = SMBNTTransactionResponse_Parameters(nt_trans_response['Parameters'])
4267 # Remove Potential Prefix Padding
4268 return nt_trans_response['Data'][-nt_trans_parameters['TotalDataCount']:]
4270 def echo(self, text = '', count = 1):
4272 smb = NewSMBPacket()
4273 comEcho = SMBCommand(SMB.SMB_COM_ECHO)
4274 comEcho['Parameters'] = SMBEcho_Parameters()
4275 comEcho['Data'] = SMBEcho_Data()
4276 comEcho['Parameters']['EchoCount'] = count
4277 comEcho['Data']['Data'] = text
4278 smb.addCommand(comEcho)
4280 self.sendSMB(smb)
4282 for i in range(count):
4283 resp = self.recvSMB()
4284 resp.isValidAnswer(SMB.SMB_COM_ECHO)
4285 return True
4287ERRDOS = { 1: 'Invalid function',
4288 2: 'File not found',
4289 3: 'Invalid directory',
4290 4: 'Too many open files',
4291 5: 'Access denied',
4292 6: 'Invalid file handle. Please file a bug report.',
4293 7: 'Memory control blocks destroyed',
4294 8: 'Out of memory',
4295 9: 'Invalid memory block address',
4296 10: 'Invalid environment',
4297 11: 'Invalid format',
4298 12: 'Invalid open mode',
4299 13: 'Invalid data',
4300 15: 'Invalid drive',
4301 16: 'Attempt to remove server\'s current directory',
4302 17: 'Not the same device',
4303 18: 'No files found',
4304 32: 'Sharing mode conflicts detected',
4305 33: 'Lock request conflicts detected',
4306 80: 'File already exists'
4307 }
4309ERRSRV = { 1: 'Non-specific error',
4310 2: 'Bad password',
4311 4: 'Access denied',
4312 5: 'Invalid tid. Please file a bug report.',
4313 6: 'Invalid network name',
4314 7: 'Invalid device',
4315 49: 'Print queue full',
4316 50: 'Print queue full',
4317 51: 'EOF on print queue dump',
4318 52: 'Invalid print file handle',
4319 64: 'Command not recognized. Please file a bug report.',
4320 65: 'Internal server error',
4321 67: 'Invalid path',
4322 69: 'Invalid access permissions',
4323 71: 'Invalid attribute mode',
4324 81: 'Server is paused',
4325 82: 'Not receiving messages',
4326 83: 'No room to buffer messages',
4327 87: 'Too many remote user names',
4328 88: 'Operation timeout',
4329 89: 'Out of resources',
4330 91: 'Invalid user handle. Please file a bug report.',
4331 250: 'Temporarily unable to support raw mode for transfer',
4332 251: 'Temporarily unable to support raw mode for transfer',
4333 252: 'Continue in MPX mode',
4334 65535: 'Unsupported function'
4335 }
4337ERRHRD = { 19: 'Media is write-protected',
4338 20: 'Unknown unit',
4339 21: 'Drive not ready',
4340 22: 'Unknown command',
4341 23: 'CRC error',
4342 24: 'Bad request',
4343 25: 'Seek error',
4344 26: 'Unknown media type',
4345 27: 'Sector not found',
4346 28: 'Printer out of paper',
4347 29: 'Write fault',
4348 30: 'Read fault',
4349 31: 'General failure',
4350 32: 'Open conflicts with an existing open',
4351 33: 'Invalid lock request',
4352 34: 'Wrong disk in drive',
4353 35: 'FCBs not available',
4354 36: 'Sharing buffer exceeded'
4355 }