1 # Copyright (c) 2003-2016 CORE Security Technologies
3 # This software is provided under under a slightly modified version
4 # of the Apache Software License. See the accompanying LICENSE file
5 # for more information.
7 # Copyright (C) 2001 Michael Teo <michaelteo@bigfoot.com>
8 # smb.py - SMB/CIFS library
10 # This software is provided 'as-is', without any express or implied warranty.
11 # In no event will the author be held liable for any damages arising from the
12 # use of this software.
14 # Permission is granted to anyone to use this software for any purpose,
15 # including commercial applications, and to alter it and redistribute it
16 # freely, subject to the following restrictions:
18 # 1. The origin of this software must not be misrepresented; you must not
19 # claim that you wrote the original software. If you use this software
20 # in a product, an acknowledgment in the product documentation would be
21 # appreciated but is not required.
23 # 2. Altered source versions must be plainly marked as such, and must not be
24 # misrepresented as being the original software.
26 # 3. This notice cannot be removed or altered from any source distribution.
28 # Altered source done by Alberto Solino (@agsolino)
31 # [ ] Try [SMB]transport fragmentation using Transact requests
32 # [ ] Try other methods of doing write (write_raw, transact2, write, write_and_unlock, write_and_close, write_mpx)
33 # [-] Try replacements for SMB_COM_NT_CREATE_ANDX (CREATE, T_TRANSACT_CREATE, OPEN_ANDX works
34 # [x] Fix forceWriteAndx, which needs to send a RecvRequest, because recv() will not send it
35 # [x] Fix Recv() when using RecvAndx and the answer comes splet in several packets
36 # [ ] Try [SMB]transport fragmentation with overlaping segments
37 # [ ] Try [SMB]transport fragmentation with out of order segments
38 # [x] Do chained AndX requests
39 # [ ] Transform the rest of the calls to structure
40 # [X] Implement TRANS/TRANS2 reassembly for list_path
45 from binascii import a2b_hex
47 from struct import pack, unpack
48 from contextlib import contextmanager
50 from impacket import nmb, ntlm, nt_errors, LOG
51 from impacket.structure import Structure
52 from impacket.spnego import SPNEGO_NegTokenInit, TypesMech, SPNEGO_NegTokenResp
61 from cStringIO import StringIO
63 from StringIO import StringIO
66 SMB_DIALECT = 'NT LM 0.12'
70 SHARED_DISK_HIDDEN = 0x80000000
71 SHARED_PRINT_QUEUE = 0x01
75 # Extended attributes mask
77 ATTR_COMPRESSED = 0x800
81 ATTR_TEMPORARY = 0x100
82 ATTR_DIRECTORY = 0x010
87 SERVICE_PRINTER = 'LPT1:'
92 # Server Type (Can be used to mask with SMBMachine.get_type() or SMBDomain.get_type())
93 SV_TYPE_WORKSTATION = 0x00000001
94 SV_TYPE_SERVER = 0x00000002
95 SV_TYPE_SQLSERVER = 0x00000004
96 SV_TYPE_DOMAIN_CTRL = 0x00000008
97 SV_TYPE_DOMAIN_BAKCTRL = 0x00000010
98 SV_TYPE_TIME_SOURCE = 0x00000020
99 SV_TYPE_AFP = 0x00000040
100 SV_TYPE_NOVELL = 0x00000080
101 SV_TYPE_DOMAIN_MEMBER = 0x00000100
102 SV_TYPE_PRINTQ_SERVER = 0x00000200
103 SV_TYPE_DIALIN_SERVER = 0x00000400
104 SV_TYPE_XENIX_SERVER = 0x00000800
105 SV_TYPE_NT = 0x00001000
106 SV_TYPE_WFW = 0x00002000
107 SV_TYPE_SERVER_NT = 0x00004000
108 SV_TYPE_POTENTIAL_BROWSER = 0x00010000
109 SV_TYPE_BACKUP_BROWSER = 0x00020000
110 SV_TYPE_MASTER_BROWSER = 0x00040000
111 SV_TYPE_DOMAIN_MASTER = 0x00080000
112 SV_TYPE_LOCAL_LIST_ONLY = 0x40000000
113 SV_TYPE_DOMAIN_ENUM = 0x80000000
115 # Options values for SMB.stor_file and SMB.retr_file
116 SMB_O_CREAT = 0x10 # Create the file if file does not exists. Otherwise, operation fails.
117 SMB_O_EXCL = 0x00 # When used with SMB_O_CREAT, operation fails if file exists. Cannot be used with SMB_O_OPEN.
118 SMB_O_OPEN = 0x01 # Open the file if the file exists
119 SMB_O_TRUNC = 0x02 # Truncate the file if the file exists
122 SMB_SHARE_COMPAT = 0x00
123 SMB_SHARE_DENY_EXCL = 0x10
124 SMB_SHARE_DENY_WRITE = 0x20
125 SMB_SHARE_DENY_READEXEC = 0x30
126 SMB_SHARE_DENY_NONE = 0x40
127 SMB_ACCESS_READ = 0x00
128 SMB_ACCESS_WRITE = 0x01
129 SMB_ACCESS_READWRITE = 0x02
130 SMB_ACCESS_EXEC = 0x03
132 TRANS_DISCONNECT_TID = 1
133 TRANS_NO_RESPONSE = 2
135 STATUS_SUCCESS = 0x00000000
136 STATUS_LOGON_FAILURE = 0xC000006D
137 STATUS_LOGON_TYPE_NOT_GRANTED = 0xC000015B
138 MAX_TFRAG_SIZE = 5840
143 RPC_X_BAD_STUB_DATA = 0x6F7
145 # SMB_FILE_ATTRIBUTES
147 SMB_FILE_ATTRIBUTE_NORMAL = 0x0000
148 SMB_FILE_ATTRIBUTE_READONLY = 0x0001
149 SMB_FILE_ATTRIBUTE_HIDDEN = 0x0002
150 SMB_FILE_ATTRIBUTE_SYSTEM = 0x0004
151 SMB_FILE_ATTRIBUTE_VOLUME = 0x0008
152 SMB_FILE_ATTRIBUTE_DIRECTORY = 0x0010
153 SMB_FILE_ATTRIBUTE_ARCHIVE = 0x0020
154 SMB_SEARCH_ATTRIBUTE_READONLY = 0x0100
155 SMB_SEARCH_ATTRIBUTE_HIDDEN = 0x0200
156 SMB_SEARCH_ATTRIBUTE_SYSTEM = 0x0400
157 SMB_SEARCH_ATTRIBUTE_DIRECTORY = 0x1000
158 SMB_SEARCH_ATTRIBUTE_ARCHIVE = 0x2000
160 # Session SetupAndX Action flags
161 SMB_SETUP_GUEST = 0x01
162 SMB_SETUP_USE_LANMAN_KEY = 0x02
164 # QUERY_INFORMATION levels
165 SMB_INFO_ALLOCATION = 0x0001
166 SMB_INFO_VOLUME = 0x0002
167 FILE_FS_SIZE_INFORMATION = 0x0003
168 SMB_QUERY_FS_VOLUME_INFO = 0x0102
169 SMB_QUERY_FS_SIZE_INFO = 0x0103
170 SMB_QUERY_FILE_EA_INFO = 0x0103
171 SMB_QUERY_FS_DEVICE_INFO = 0x0104
172 SMB_QUERY_FS_ATTRIBUTE_INFO = 0x0105
173 SMB_QUERY_FILE_BASIC_INFO = 0x0101
174 SMB_QUERY_FILE_STANDARD_INFO = 0x0102
175 SMB_QUERY_FILE_ALL_INFO = 0x0107
176 FILE_FS_FULL_SIZE_INFORMATION = 0x03EF
178 # SET_INFORMATION levels
179 SMB_SET_FILE_DISPOSITION_INFO = 0x0102
180 SMB_SET_FILE_BASIC_INFO = 0x0101
181 SMB_SET_FILE_END_OF_FILE_INFO = 0x0104
184 # File System Attributes
185 FILE_CASE_SENSITIVE_SEARCH = 0x00000001
186 FILE_CASE_PRESERVED_NAMES = 0x00000002
187 FILE_UNICODE_ON_DISK = 0x00000004
188 FILE_PERSISTENT_ACLS = 0x00000008
189 FILE_FILE_COMPRESSION = 0x00000010
190 FILE_VOLUME_IS_COMPRESSED = 0x00008000
192 # FIND_FIRST2 flags and levels
193 SMB_FIND_CLOSE_AFTER_REQUEST = 0x0001
194 SMB_FIND_CLOSE_AT_EOS = 0x0002
195 SMB_FIND_RETURN_RESUME_KEYS = 0x0004
196 SMB_FIND_CONTINUE_FROM_LAST = 0x0008
197 SMB_FIND_WITH_BACKUP_INTENT = 0x0010
199 FILE_DIRECTORY_FILE = 0x00000001
200 FILE_DELETE_ON_CLOSE = 0x00001000
201 FILE_NON_DIRECTORY_FILE = 0x00000040
203 SMB_FIND_INFO_STANDARD = 0x0001
204 SMB_FIND_FILE_DIRECTORY_INFO = 0x0101
205 SMB_FIND_FILE_FULL_DIRECTORY_INFO= 0x0102
206 SMB_FIND_FILE_NAMES_INFO = 0x0103
207 SMB_FIND_FILE_BOTH_DIRECTORY_INFO= 0x0104
208 SMB_FIND_FILE_ID_FULL_DIRECTORY_INFO = 0x105
209 SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO = 0x106
212 # DesiredAccess flags
213 FILE_READ_DATA = 0x00000001
214 FILE_WRITE_DATA = 0x00000002
215 FILE_APPEND_DATA = 0x00000004
216 FILE_EXECUTE = 0x00000020
217 MAXIMUM_ALLOWED = 0x02000000
218 GENERIC_ALL = 0x10000000
219 GENERIC_EXECUTE = 0x20000000
220 GENERIC_WRITE = 0x40000000
221 GENERIC_READ = 0x80000000
224 FILE_SHARE_NONE = 0x00000000
225 FILE_SHARE_READ = 0x00000001
226 FILE_SHARE_WRITE = 0x00000002
227 FILE_SHARE_DELETE = 0x00000004
229 # CreateDisposition flags
230 FILE_SUPERSEDE = 0x00000000
231 FILE_OPEN = 0x00000001
232 FILE_CREATE = 0x00000002
233 FILE_OPEN_IF = 0x00000003
234 FILE_OVERWRITE = 0x00000004
235 FILE_OVERWRITE_IF = 0x00000005
237 def strerror(errclass, errcode):
239 return 'OS error', ERRDOS.get(errcode, 'Unknown error')
240 elif errclass == 0x02:
241 return 'Server error', ERRSRV.get(errcode, 'Unknown error')
242 elif errclass == 0x03:
243 return 'Hardware error', ERRHRD.get(errcode, 'Unknown error')
244 # This is not a standard error class for SMB
245 #elif errclass == 0x80:
246 # return 'Browse error', ERRBROWSE.get(errcode, 'Unknown error')
247 elif errclass == 0xff:
248 return 'Bad command', 'Bad command. Please file bug report'
250 return 'Unknown error', 'Unknown error'
252 # Raised when an error has occured during a session
253 class SessionError(Exception):
254 # SMB X/Open error codes for the ERRDOS error class
282 ERRinsufficientbuffer = 122
284 ERRunknownlevel = 124
290 ERRnotconnected = 233
293 ERRbaddirectory = 267
294 ERReasnotsupported = 282
295 ERRlogonfailure = 1326
296 ERRbuftoosmall = 2123
298 ERRnosuchprintjob = 2151
301 # here's a special one from observing NT
304 # These errors seem to be only returned by the NT printer driver system
305 ERRdriveralreadyinstalled = 1795
306 ERRunknownprinterport = 1796
307 ERRunknownprinterdriver = 1797
308 ERRunknownprintprocessor = 1798
309 ERRinvalidseparatorfile = 1799
310 ERRinvalidjobpriority = 1800
311 ERRinvalidprintername = 1801
312 ERRprinteralreadyexists = 1802
313 ERRinvalidprintercommand = 1803
314 ERRinvaliddatatype = 1804
315 ERRinvalidenvironment = 1805
317 ERRunknownprintmonitor = 3000
318 ERRprinterdriverinuse = 3001
319 ERRspoolfilenotfound = 3002
322 ERRprintprocessoralreadyinstalled = 3005
323 ERRprintmonitoralreadyinstalled = 3006
324 ERRinvalidprintmonitor = 3007
325 ERRprintmonitorinuse = 3008
326 ERRprinterhasjobsqueued = 3009
328 # Error codes for the ERRSRV class
362 # Error codes for the ERRHRD class
383 19: ("ERRnowrite", "Attempt to write on write-protected diskette."),
384 20: ("ERRbadunit", "Unknown unit."),
385 21: ("ERRnotready", "Drive not ready."),
386 22: ("ERRbadcmd", "Unknown command."),
387 23: ("ERRdata", "Data error (CRC)."),
388 24: ("ERRbadreq", "Bad request structure length."),
389 25: ("ERRseek", "Seek error."),
390 26: ("ERRbadmedia", "Unknown media type."),
391 27: ("ERRbadsector", "Sector not found."),
392 28: ("ERRnopaper", "Printer out of paper."),
393 29: ("ERRwrite", "Write fault."),
394 30: ("ERRread", "Read fault."),
395 31: ("ERRgeneral", "General failure."),
396 32: ("ERRbadshare", "An open conflicts with an existing open."),
397 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."),
398 34: ("ERRwrongdisk", "The wrong disk was found in a drive."),
399 35: ("ERRFCBUnavail", "No FCBs are available to process request."),
400 36: ("ERRsharebufexc", "A sharing buffer has been exceeded.")
404 ERRbadfunc: ("ERRbadfunc", "Invalid function."),
405 ERRbadfile: ("ERRbadfile", "File not found."),
406 ERRbadpath: ("ERRbadpath", "Directory invalid."),
407 ERRnofids: ("ERRnofids", "No file descriptors available"),
408 ERRnoaccess: ("ERRnoaccess", "Access denied."),
409 ERRbadfid: ("ERRbadfid", "Invalid file handle."),
410 ERRbadmcb: ("ERRbadmcb", "Memory control blocks destroyed."),
411 ERRnomem: ("ERRnomem", "Insufficient server memory to perform the requested function."),
412 ERRbadmem: ("ERRbadmem", "Invalid memory block address."),
413 ERRbadenv: ("ERRbadenv", "Invalid environment."),
414 11: ("ERRbadformat", "Invalid format."),
415 ERRbadaccess: ("ERRbadaccess", "Invalid open mode."),
416 ERRbaddata: ("ERRbaddata", "Invalid data."),
417 ERRres: ("ERRres", "reserved."),
418 ERRbaddrive: ("ERRbaddrive", "Invalid drive specified."),
419 ERRremcd: ("ERRremcd", "A Delete Directory request attempted to remove the server's current directory."),
420 ERRdiffdevice: ("ERRdiffdevice", "Not same device."),
421 ERRnofiles: ("ERRnofiles", "A File Search command can find no more files matching the specified criteria."),
422 ERRbadshare: ("ERRbadshare", "The sharing mode specified for an Open conflicts with existing FIDs on the file."),
423 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."),
424 ERRunsup: ("ERRunsup", "The operation is unsupported"),
425 ERRnosuchshare: ("ERRnosuchshare", "You specified an invalid share name"),
426 ERRfilexists: ("ERRfilexists", "The file named in a Create Directory, Make New File or Link request already exists."),
427 ERRinvalidname: ("ERRinvalidname", "Invalid name"),
428 ERRbadpipe: ("ERRbadpipe", "Pipe invalid."),
429 ERRpipebusy: ("ERRpipebusy", "All instances of the requested pipe are busy."),
430 ERRpipeclosing: ("ERRpipeclosing", "Pipe close in progress."),
431 ERRnotconnected: ("ERRnotconnected", "No process on other end of pipe."),
432 ERRmoredata: ("ERRmoredata", "There is more data to be returned."),
433 ERRinvgroup: ("ERRinvgroup", "Invalid workgroup (try the -W option)"),
434 ERRlogonfailure: ("ERRlogonfailure", "Logon failure"),
435 ERRdiskfull: ("ERRdiskfull", "Disk full"),
436 ERRgeneral: ("ERRgeneral", "General failure"),
437 ERRunknownlevel: ("ERRunknownlevel", "Unknown info level")
441 1: ("ERRerror", "Non-specific error code."),
442 2: ("ERRbadpw", "Bad password - name/password pair in a Tree Connect or Session Setup are invalid."),
443 3: ("ERRbadtype", "reserved."),
444 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."),
445 5: ("ERRinvnid", "The tree ID (TID) specified in a command was invalid."),
446 6: ("ERRinvnetname", "Invalid network name in tree connect."),
447 7: ("ERRinvdevice", "Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."),
448 49: ("ERRqfull", "Print queue full (files) -- returned by open print file."),
449 50: ("ERRqtoobig", "Print queue full -- no space."),
450 51: ("ERRqeof", "EOF on print queue dump."),
451 52: ("ERRinvpfid", "Invalid print file FID."),
452 64: ("ERRsmbcmd", "The server did not recognize the command received."),
453 65: ("ERRsrverror","The server encountered an internal error, e.g., system file unavailable."),
454 67: ("ERRfilespecs", "The file handle (FID) and pathname parameters contained an invalid combination of values."),
455 68: ("ERRreserved", "reserved."),
456 69: ("ERRbadpermits", "The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."),
457 70: ("ERRreserved", "reserved."),
458 71: ("ERRsetattrmode", "The attribute mode in the Set File Attribute request is invalid."),
459 81: ("ERRpaused", "Server is paused."),
460 82: ("ERRmsgoff", "Not receiving messages."),
461 83: ("ERRnoroom", "No room to buffer message."),
462 87: ("ERRrmuns", "Too many remote user names."),
463 88: ("ERRtimeout", "Operation timed out."),
464 89: ("ERRnoresource", "No resources currently available for request."),
465 90: ("ERRtoomanyuids", "Too many UIDs active on this session."),
466 91: ("ERRbaduid", "The UID is not known as a valid ID on this session."),
467 250: ("ERRusempx","Temp unable to support Raw, use MPX mode."),
468 251: ("ERRusestd","Temp unable to support Raw, use standard read/write."),
469 252: ("ERRcontmpx", "Continue in MPX mode."),
470 253: ("ERRreserved", "reserved."),
471 254: ("ERRreserved", "reserved."),
472 0xFFFF: ("ERRnosupport", "Function not supported.")
477 error_classes = { 0: ("SUCCESS", {}),
478 ERRDOS: ("ERRDOS", dos_msgs),
479 0x02: ("ERRSRV",server_msgs),
480 0x03: ("ERRHRD",hard_msgs),
481 0x04: ("ERRXOS", {} ),
482 0xE1: ("ERRRMX1", {} ),
483 0xE2: ("ERRRMX2", {} ),
484 0xE3: ("ERRRMX3", {} ),
485 0xFF: ("ERRCMD", {} ) }
489 def __init__( self, error_string, error_class, error_code, nt_status = 0):
490 Exception.__init__(self, error_string)
491 self.nt_status = nt_status
492 self._args = error_string
495 self.error_code = (error_code << 16) + error_class
497 self.error_class = error_class
498 self.error_code = error_code
501 def get_error_class( self ):
502 return self.error_class
504 def get_error_code( self ):
505 return self.error_code
508 error_class = SessionError.error_classes.get( self.error_class, None )
510 error_code_str = self.error_code
511 error_class_str = self.error_class
513 error_class_str = error_class[0]
514 error_code = error_class[1].get( self.error_code, None )
516 error_code_str = self.error_code
518 error_code_str = '%s(%s)' % error_code
521 return 'SMB SessionError: %s(%s)' % nt_errors.ERROR_MESSAGES[self.error_code]
523 # Fall back to the old format
524 return 'SMB SessionError: class: %s, code: %s' % (error_class_str, error_code_str)
527 # Raised when an supported feature is present/required in the protocol but is not
528 # currently supported by pysmb
529 class UnsupportedFeature(Exception): pass
531 # Contains information about a SMB shared device/service
533 def __init__(self, name, share_type, comment):
535 self.__type = share_type
536 self.__comment = comment
544 def get_comment(self):
545 return self.__comment
548 return '<SharedDevice instance: name=' + self.__name + ', type=' + str(self.__type) + ', comment="' + self.__comment + '">'
551 # Contains information about the shared file/directory
553 def __init__(self, ctime, atime, mtime, filesize, allocsize, attribs, shortname, longname):
557 self.__filesize = filesize
558 self.__allocsize = allocsize
559 self.__attribs = attribs
561 self.__shortname = shortname[:string.index(shortname, '\0')]
563 self.__shortname = shortname
565 self.__longname = longname[:string.index(longname, '\0')]
567 self.__longname = longname
572 def get_ctime_epoch(self):
573 return self.__convert_smbtime(self.__ctime)
578 def get_mtime_epoch(self):
579 return self.__convert_smbtime(self.__mtime)
584 def get_atime_epoch(self):
585 return self.__convert_smbtime(self.__atime)
587 def get_filesize(self):
588 return self.__filesize
590 def get_allocsize(self):
591 return self.__allocsize
593 def get_attributes(self):
594 return self.__attribs
596 def is_archive(self):
597 return self.__attribs & ATTR_ARCHIVE
599 def is_compressed(self):
600 return self.__attribs & ATTR_COMPRESSED
603 return self.__attribs & ATTR_NORMAL
606 return self.__attribs & ATTR_HIDDEN
608 def is_readonly(self):
609 return self.__attribs & ATTR_READONLY
611 def is_temporary(self):
612 return self.__attribs & ATTR_TEMPORARY
614 def is_directory(self):
615 return self.__attribs & ATTR_DIRECTORY
618 return self.__attribs & ATTR_SYSTEM
620 def get_shortname(self):
621 return self.__shortname
623 def get_longname(self):
624 return self.__longname
627 return '<SharedFile instance: shortname="' + self.__shortname + '", longname="' + self.__longname + '", filesize=' + str(self.__filesize) + '>'
630 def __convert_smbtime(t):
633 geo_cal_offset = 11644473600.0 # = 369.0 * 365.25 * 24 * 60 * 60 - (3.0 * 24 * 60 * 60 + 6.0 * 60 * 60)
634 return (x * 4.0 * (1 << 30) + (y & 0xfff00000L)) * 1.0e-7 - geo_cal_offset
637 # Contain information about a SMB machine
639 def __init__(self, nbname, nbt_type, comment):
640 self.__nbname = nbname
641 self.__type = nbt_type
642 self.__comment = comment
645 return '<SMBMachine instance: nbname="' + self.__nbname + '", type=' + hex(self.__type) + ', comment="' + self.__comment + '">'
648 def __init__(self, nbgroup, domain_type, master_browser):
649 self.__nbgroup = nbgroup
650 self.__type = domain_type
651 self.__master_browser = master_browser
654 return '<SMBDomain instance: nbgroup="' + self.__nbgroup + '", type=' + hex(self.__type) + ', master browser="' + self.__master_browser + '">'
656 # Represents a SMB Packet
657 class NewSMBPacket(Structure):
659 ('Signature', '"\xffSMB'),
661 ('ErrorClass','B=0'),
663 ('ErrorCode','<H=0'),
667 ('SecurityFeatures','8s=""'),
676 def __init__(self, **kargs):
677 Structure.__init__(self, **kargs)
679 if self.fields.has_key('Flags2') is False:
681 if self.fields.has_key('Flags1') is False:
684 if not kargs.has_key('data'):
687 def addCommand(self, command):
688 if len(self['Data']) == 0:
689 self['Command'] = command.command
691 self['Data'][-1]['Parameters']['AndXCommand'] = command.command
692 self['Data'][-1]['Parameters']['AndXOffset'] = len(self)
693 self['Data'].append(command)
695 def isMoreData(self):
696 return (self['Command'] in [SMB.SMB_COM_TRANSACTION, SMB.SMB_COM_READ_ANDX, SMB.SMB_COM_READ_RAW] and
697 self['ErrorClass'] == 1 and self['ErrorCode'] == SessionError.ERRmoredata)
699 def isMoreProcessingRequired(self):
700 return self['ErrorClass'] == 0x16 and self['ErrorCode'] == 0xc000
702 def isValidAnswer(self, cmd):
703 # this was inside a loop reading more from the net (with recv_packet(None))
704 if self['Command'] == cmd:
705 if (self['ErrorClass'] == 0x00 and
706 self['ErrorCode'] == 0x00):
708 elif self.isMoreData():
710 elif self.isMoreProcessingRequired():
712 raise SessionError, ("SMB Library Error", self['ErrorClass'] + (self['_reserved'] << 8), self['ErrorCode'], self['Flags2'] & SMB.FLAGS2_NT_STATUS)
714 raise UnsupportedFeature, ("Unexpected answer from server: Got %d, Expected %d" % (self['Command'], cmd))
717 class SMBCommand(Structure):
719 ('WordCount', 'B=len(Parameters)/2'),
720 ('_ParametersLength','_-Parameters','WordCount*2'),
721 ('Parameters',':'), # default set by constructor
722 ('ByteCount','<H-Data'),
723 ('Data',':'), # default set by constructor
726 def __init__(self, commandOrData = None, data = None, **kargs):
727 if type(commandOrData) == type(0):
728 self.command = commandOrData
730 data = data or commandOrData
732 Structure.__init__(self, data = data, **kargs)
735 self['Parameters'] = ''
738 class AsciiOrUnicodeStructure(Structure):
739 UnicodeStructure = ()
741 def __init__(self, flags = 0, **kargs):
742 if flags & SMB.FLAGS2_UNICODE:
743 self.structure = self.UnicodeStructure
745 self.structure = self.AsciiStructure
746 Structure.__init__(self, **kargs)
748 class SMBCommand_Parameters(Structure):
751 class SMBAndXCommand_Parameters(Structure):
753 ('AndXCommand','B=0xff'),
755 ('AndXOffset','<H=0'),
757 structure = ( # default structure, overriden by subclasses
761 ############# TRANSACTIONS RELATED
762 # TRANS2_QUERY_FS_INFORMATION
763 # QUERY_FS Information Levels
764 # SMB_QUERY_FS_ATTRIBUTE_INFO
765 class SMBQueryFsAttributeInfo(Structure):
767 ('FileSystemAttributes','<L'),
768 ('MaxFilenNameLengthInBytes','<L'),
769 ('LengthOfFileSystemName','<L-FileSystemName'),
770 ('FileSystemName',':'),
773 class SMBQueryFsInfoVolume(AsciiOrUnicodeStructure):
775 ('ulVolSerialNbr','<L=0xABCDEFAA'),
776 ('cCharCount','<B-VolumeLabel'),
785 # FILE_FS_SIZE_INFORMATION
786 class FileFsSizeInformation(Structure):
788 ('TotalAllocationUnits','<q=148529400'),
789 ('AvailableAllocationUnits','<q=14851044'),
790 ('SectorsPerAllocationUnit','<L=2'),
791 ('BytesPerSector','<L=512'),
794 # SMB_QUERY_FS_SIZE_INFO
795 class SMBQueryFsSizeInfo(Structure):
797 ('TotalAllocationUnits','<q=148529400'),
798 ('TotalFreeAllocationUnits','<q=14851044'),
799 ('SectorsPerAllocationUnit','<L=2'),
800 ('BytesPerSector','<L=512'),
802 # FILE_FS_FULL_SIZE_INFORMATION
803 class SMBFileFsFullSizeInformation(Structure):
805 ('TotalAllocationUnits','<q=148529400'),
806 ('CallerAvailableAllocationUnits','<q=148529400'),
807 ('ActualAvailableAllocationUnits','<q=148529400'),
808 ('SectorsPerAllocationUnit','<L=15'),
809 ('BytesPerSector','<L=512')
811 # SMB_QUERY_FS_VOLUME_INFO
812 class SMBQueryFsVolumeInfo(Structure):
814 ('VolumeCreationTime','<q'),
815 ('SerialNumber','<L=0xABCDEFAA'),
816 ('VolumeLabelSize','<L=len(VolumeLabel)'),
817 ('Reserved','<H=0x10'),
820 # SMB_FIND_FILE_BOTH_DIRECTORY_INFO level
821 class SMBFindFileBothDirectoryInfo(AsciiOrUnicodeStructure):
823 ('NextEntryOffset','<L=0'),
824 ('FileIndex','<L=0'),
825 ('CreationTime','<q'),
826 ('LastAccessTime','<q'),
827 ('LastWriteTime','<q'),
828 ('LastChangeTime','<q'),
829 ('EndOfFile','<q=0'),
830 ('AllocationSize','<q=0'),
831 ('ExtFileAttributes','<L=0'),
834 ('FileNameLength','<L-FileName','len(FileName)'),
836 ('ShortNameLength','<B=0'),
842 ('FileNameLength','<L-FileName','len(FileName)*2'),
844 ('ShortNameLength','<B=0'),
850 # SMB_FIND_FILE_ID_FULL_DIRECTORY_INFO level
851 class SMBFindFileIdFullDirectoryInfo(AsciiOrUnicodeStructure):
853 ('NextEntryOffset','<L=0'),
854 ('FileIndex','<L=0'),
855 ('CreationTime','<q'),
856 ('LastAccessTime','<q'),
857 ('LastWriteTime','<q'),
858 ('LastChangeTime','<q'),
859 ('EndOfFile','<q=0'),
860 ('AllocationSize','<q=0'),
861 ('ExtFileAttributes','<L=0'),
864 ('FileNameLength','<L-FileName','len(FileName)'),
870 ('FileNameLength','<L-FileName','len(FileName)*2'),
876 # SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO level
877 class SMBFindFileIdBothDirectoryInfo(AsciiOrUnicodeStructure):
879 ('NextEntryOffset','<L=0'),
880 ('FileIndex','<L=0'),
881 ('CreationTime','<q'),
882 ('LastAccessTime','<q'),
883 ('LastWriteTime','<q'),
884 ('LastChangeTime','<q'),
885 ('EndOfFile','<q=0'),
886 ('AllocationSize','<q=0'),
887 ('ExtFileAttributes','<L=0'),
890 ('FileNameLength','<L-FileName','len(FileName)'),
892 ('ShortNameLength','<B=0'),
900 ('FileNameLength','<L-FileName','len(FileName)*2'),
902 ('ShortNameLength','<B=0'),
910 # SMB_FIND_FILE_DIRECTORY_INFO level
911 class SMBFindFileDirectoryInfo(AsciiOrUnicodeStructure):
913 ('NextEntryOffset','<L=0'),
914 ('FileIndex','<L=0'),
915 ('CreationTime','<q'),
916 ('LastAccessTime','<q'),
917 ('LastWriteTime','<q'),
918 ('LastChangeTime','<q'),
919 ('EndOfFile','<q=0'),
920 ('AllocationSize','<q=1'),
921 ('ExtFileAttributes','<L=0'),
924 ('FileNameLength','<L-FileName','len(FileName)'),
928 ('FileNameLength','<L-FileName','len(FileName)*2'),
932 # SMB_FIND_FILE_NAMES_INFO level
933 class SMBFindFileNamesInfo(AsciiOrUnicodeStructure):
935 ('NextEntryOffset','<L=0'),
936 ('FileIndex','<L=0'),
939 ('FileNameLength','<L-FileName','len(FileName)'),
943 ('FileNameLength','<L-FileName','len(FileName)*2'),
947 # SMB_FIND_FILE_FULL_DIRECTORY_INFO level
948 class SMBFindFileFullDirectoryInfo(AsciiOrUnicodeStructure):
950 ('NextEntryOffset','<L=0'),
951 ('FileIndex','<L=0'),
952 ('CreationTime','<q'),
953 ('LastAccessTime','<q'),
954 ('LastWriteTime','<q'),
955 ('LastChangeTime','<q'),
956 ('EndOfFile','<q=0'),
957 ('AllocationSize','<q=1'),
958 ('ExtFileAttributes','<L=0'),
961 ('FileNameLength','<L-FileName','len(FileName)'),
966 ('FileNameLength','<L-FileName','len(FileName)*2'),
971 # SMB_FIND_INFO_STANDARD level
972 class SMBFindInfoStandard(AsciiOrUnicodeStructure):
974 ('ResumeKey','<L=0xff'),
975 ('CreationDate','<H=0'),
976 ('CreationTime','<H=0'),
977 ('LastAccessDate','<H=0'),
978 ('LastAccessTime','<H=0'),
979 ('LastWriteDate','<H=0'),
980 ('LastWriteTime','<H=0'),
982 ('AllocationSize','<L=1'),
983 ('ExtFileAttributes','<H=0'),
986 ('FileNameLength','<B-FileName','len(FileName)'),
990 ('FileNameLength','<B-FileName','len(FileName)*2'),
994 # SET_FILE_INFORMATION structures
995 # SMB_SET_FILE_DISPOSITION_INFO
996 class SMBSetFileDispositionInfo(Structure):
998 ('DeletePending','<B'),
1001 # SMB_SET_FILE_BASIC_INFO
1002 class SMBSetFileBasicInfo(Structure):
1004 ('CreationTime','<q'),
1005 ('LastAccessTime','<q'),
1006 ('LastWriteTime','<q'),
1007 ('ChangeTime','<q'),
1008 ('ExtFileAttributes','<H'),
1012 # FILE_STREAM_INFORMATION
1013 class SMBFileStreamInformation(Structure):
1015 ('NextEntryOffset','<L=0'),
1016 ('StreamNameLength','<L=0'),
1017 ('StreamSize','<q=0'),
1018 ('StreamAllocationSize','<q=0'),
1019 ('StreamName',':=""'),
1022 # FILE_NETWORK_OPEN_INFORMATION
1023 class SMBFileNetworkOpenInfo(Structure):
1025 ('CreationTime','<q=0'),
1026 ('LastAccessTime','<q=0'),
1027 ('LastWriteTime','<q=0'),
1028 ('ChangeTime','<q=0'),
1029 ('AllocationSize','<q=0'),
1030 ('EndOfFile','<q=0'),
1031 ('FileAttributes','<L=0'),
1032 ('Reserved','<L=0'),
1035 # SMB_SET_FILE_END_OF_FILE_INFO
1036 class SMBSetFileEndOfFileInfo(Structure):
1042 class SMBFindNext2_Parameters(AsciiOrUnicodeStructure):
1045 ('SearchCount','<H'),
1046 ('InformationLevel','<H'),
1053 UnicodeStructure = (
1057 class SMBFindNext2Response_Parameters(Structure):
1059 ('SearchCount','<H'),
1060 ('EndOfSearch','<H=1'),
1061 ('EaErrorOffset','<H=0'),
1062 ('LastNameOffset','<H=0'),
1065 class SMBFindNext2_Data(Structure):
1067 ('GetExtendedAttributesListLength','_-GetExtendedAttributesList', 'self["GetExtendedAttributesListLength"]'),
1068 ('GetExtendedAttributesList',':'),
1072 # TRANS2_FIND_FIRST2
1073 class SMBFindFirst2Response_Parameters(Structure):
1076 ('SearchCount','<H'),
1077 ('EndOfSearch','<H=1'),
1078 ('EaErrorOffset','<H=0'),
1079 ('LastNameOffset','<H=0'),
1082 class SMBFindFirst2_Parameters(AsciiOrUnicodeStructure):
1084 ('SearchAttributes','<H'),
1085 ('SearchCount','<H'),
1087 ('InformationLevel','<H'),
1088 ('SearchStorageType','<L'),
1093 UnicodeStructure = (
1097 class SMBFindFirst2_Data(Structure):
1099 ('GetExtendedAttributesListLength','_-GetExtendedAttributesList', 'self["GetExtendedAttributesListLength"]'),
1100 ('GetExtendedAttributesList',':'),
1103 # TRANS2_SET_PATH_INFORMATION
1104 class SMBSetPathInformation_Parameters(AsciiOrUnicodeStructure):
1106 ('InformationLevel','<H'),
1112 UnicodeStructure = (
1116 class SMBSetPathInformationResponse_Parameters(Structure):
1118 ('EaErrorOffset','<H=0'),
1121 # TRANS2_SET_FILE_INFORMATION
1122 class SMBSetFileInformation_Parameters(Structure):
1125 ('InformationLevel','<H'),
1129 class SMBSetFileInformationResponse_Parameters(Structure):
1131 ('EaErrorOffset','<H=0'),
1134 # TRANS2_QUERY_FILE_INFORMATION
1135 class SMBQueryFileInformation_Parameters(Structure):
1138 ('InformationLevel','<H'),
1141 class SMBQueryFileInformationResponse_Parameters(Structure):
1143 ('EaErrorOffset','<H=0'),
1146 class SMBQueryFileInformation_Data(Structure):
1148 ('GetExtendedAttributeList',':'),
1151 # TRANS2_QUERY_PATH_INFORMATION
1152 class SMBQueryPathInformationResponse_Parameters(Structure):
1154 ('EaErrorOffset','<H=0'),
1157 class SMBQueryPathInformation_Parameters(AsciiOrUnicodeStructure):
1159 ('InformationLevel','<H'),
1160 ('Reserved','<L=0'),
1165 UnicodeStructure = (
1169 class SMBQueryPathInformation_Data(Structure):
1171 ('GetExtendedAttributeList',':'),
1175 # SMB_QUERY_FILE_EA_INFO
1176 class SMBQueryFileEaInfo(Structure):
1181 # SMB_QUERY_FILE_BASIC_INFO
1182 class SMBQueryFileBasicInfo(Structure):
1184 ('CreationTime','<q'),
1185 ('LastAccessTime','<q'),
1186 ('LastWriteTime','<q'),
1187 ('LastChangeTime','<q'),
1188 ('ExtFileAttributes','<L'),
1189 #('Reserved','<L=0'),
1192 # SMB_QUERY_FILE_STANDARD_INFO
1193 class SMBQueryFileStandardInfo(Structure):
1195 ('AllocationSize','<q'),
1197 ('NumberOfLinks','<L=0'),
1198 ('DeletePending','<B=0'),
1202 # SMB_QUERY_FILE_ALL_INFO
1203 class SMBQueryFileAllInfo(Structure):
1205 ('CreationTime','<q'),
1206 ('LastAccessTime','<q'),
1207 ('LastWriteTime','<q'),
1208 ('LastChangeTime','<q'),
1209 ('ExtFileAttributes','<L'),
1210 ('Reserved','<L=0'),
1211 ('AllocationSize','<q'),
1213 ('NumberOfLinks','<L=0'),
1214 ('DeletePending','<B=0'),
1216 ('Reserved','<H=0'),
1218 ('FileNameLength','<L-FileName','len(FileName)'),
1222 # \PIPE\LANMAN NetShareEnum
1223 class SMBNetShareEnum(Structure):
1225 ('RAPOpcode','<H=0'),
1229 ('ReceiveBufferSize','<H'),
1232 class SMBNetShareEnumResponse(Structure):
1236 ('EntriesReturned','<H'),
1237 ('EntriesAvailable','<H'),
1240 class NetShareInfo1(Structure):
1242 ('NetworkName','13s'),
1245 ('RemarkOffsetLow','<H=0'),
1246 ('RemarkOffsetHigh','<H=0'),
1249 # \PIPE\LANMAN NetServerGetInfo
1250 class SMBNetServerGetInfoResponse(Structure):
1254 ('TotalBytesAvailable','<H'),
1257 class SMBNetServerInfo1(Structure):
1260 ('ServerName','16s'),
1261 ('MajorVersion','B=5'),
1262 ('MinorVersion','B=0'),
1263 ('ServerType','<L=3'),
1264 ('ServerCommentLow','<H=0'),
1265 ('ServerCommentHigh','<H=0'),
1268 # \PIPE\LANMAN NetShareGetInfo
1269 class SMBNetShareGetInfo(Structure):
1271 ('RAPOpcode','<H=0'),
1276 ('ReceiveBufferSize','<H'),
1279 class SMBNetShareGetInfoResponse(Structure):
1283 ('TotalBytesAvailable','<H'),
1286 ############# Security Features
1287 class SecurityFeatures(Structure):
1291 ('SequenceNumber','<H=0'),
1294 ############# SMB_COM_QUERY_INFORMATION2 (0x23)
1295 class SMBQueryInformation2_Parameters(Structure):
1300 class SMBQueryInformation2Response_Parameters(Structure):
1302 ('CreateDate','<H'),
1303 ('CreationTime','<H'),
1304 ('LastAccessDate','<H'),
1305 ('LastAccessTime','<H'),
1306 ('LastWriteDate','<H'),
1307 ('LastWriteTime','<H'),
1308 ('FileDataSize','<L'),
1309 ('FileAllocationSize','<L'),
1310 ('FileAttributes','<L'),
1315 ############# SMB_COM_SESSION_SETUP_ANDX (0x73)
1316 class SMBSessionSetupAndX_Parameters(SMBAndXCommand_Parameters):
1319 ('MaxMpxCount','<H'),
1321 ('SessionKey','<L'),
1322 ('AnsiPwdLength','<H'),
1323 ('UnicodePwdLength','<H'),
1324 ('_reserved','<L=0'),
1325 ('Capabilities','<L'),
1328 class SMBSessionSetupAndX_Extended_Parameters(SMBAndXCommand_Parameters):
1330 ('MaxBufferSize','<H'),
1331 ('MaxMpxCount','<H'),
1333 ('SessionKey','<L'),
1334 ('SecurityBlobLength','<H'),
1335 ('Reserved','<L=0'),
1336 ('Capabilities','<L'),
1339 class SMBSessionSetupAndX_Data(AsciiOrUnicodeStructure):
1341 ('AnsiPwdLength','_-AnsiPwd','self["AnsiPwdLength"]'),
1342 ('UnicodePwdLength','_-UnicodePwd','self["UnicodePwdLength"]'),
1344 ('UnicodePwd',':=""'),
1346 ('PrimaryDomain','z=""'),
1347 ('NativeOS','z=""'),
1348 ('NativeLanMan','z=""'),
1351 UnicodeStructure = (
1352 ('AnsiPwdLength','_-AnsiPwd','self["AnsiPwdLength"]'),
1353 ('UnicodePwdLength','_-UnicodePwd','self["UnicodePwdLength"]'),
1355 ('UnicodePwd',':=""'),
1357 ('PrimaryDomain','u=""'),
1358 ('NativeOS','u=""'),
1359 ('NativeLanMan','u=""'),
1362 class SMBSessionSetupAndX_Extended_Data(AsciiOrUnicodeStructure):
1364 ('SecurityBlobLength','_-SecurityBlob','self["SecurityBlobLength"]'),
1365 ('SecurityBlob',':'),
1366 ('NativeOS','z=""'),
1367 ('NativeLanMan','z=""'),
1370 UnicodeStructure = (
1371 ('SecurityBlobLength','_-SecurityBlob','self["SecurityBlobLength"]'),
1372 ('SecurityBlob',':'),
1373 ('NativeOS','u=""'),
1374 ('NativeLanMan','u=""'),
1377 class SMBSessionSetupAndXResponse_Parameters(SMBAndXCommand_Parameters):
1382 class SMBSessionSetupAndX_Extended_Response_Parameters(SMBAndXCommand_Parameters):
1385 ('SecurityBlobLength','<H'),
1388 class SMBSessionSetupAndXResponse_Data(AsciiOrUnicodeStructure):
1390 ('NativeOS','z=""'),
1391 ('NativeLanMan','z=""'),
1392 ('PrimaryDomain','z=""'),
1395 UnicodeStructure = (
1396 ('NativeOS','u=""'),
1397 ('NativeLanMan','u=""'),
1398 ('PrimaryDomain','u=""'),
1401 class SMBSessionSetupAndX_Extended_Response_Data(AsciiOrUnicodeStructure):
1403 ('SecurityBlobLength','_-SecurityBlob','self["SecurityBlobLength"]'),
1404 ('SecurityBlob',':'),
1405 ('NativeOS','z=""'),
1406 ('NativeLanMan','z=""'),
1409 UnicodeStructure = (
1410 ('SecurityBlobLength','_-SecurityBlob','self["SecurityBlobLength"]'),
1411 ('SecurityBlob',':'),
1412 ('NativeOS','u=""'),
1413 ('NativeLanMan','u=""'),
1416 ############# SMB_COM_TREE_CONNECT (0x70)
1417 class SMBTreeConnect_Parameters(SMBCommand_Parameters):
1421 class SMBTreeConnect_Data(SMBCommand_Parameters):
1423 ('PathFormat','"\x04'),
1425 ('PasswordFormat','"\x04'),
1427 ('ServiceFormat','"\x04'),
1431 ############# SMB_COM_TREE_CONNECT_ANDX (0x75)
1432 class SMBTreeConnectAndX_Parameters(SMBAndXCommand_Parameters):
1435 ('PasswordLength','<H'),
1438 class SMBTreeConnectAndXResponse_Parameters(SMBAndXCommand_Parameters):
1440 ('OptionalSupport','<H=0'),
1443 class SMBTreeConnectAndXExtendedResponse_Parameters(SMBAndXCommand_Parameters):
1445 ('OptionalSupport','<H=1'),
1446 ('MaximalShareAccessRights','<L=0x1fffff'),
1447 ('GuestMaximalShareAccessRights','<L=0x1fffff'),
1450 class SMBTreeConnectAndX_Data(AsciiOrUnicodeStructure):
1452 ('_PasswordLength','_-Password','self["_PasswordLength"]'),
1458 UnicodeStructure = (
1459 ('_PasswordLength','_-Password','self["_PasswordLength"] if self["_PasswordLength"] > 0 else 1'),
1465 class SMBTreeConnectAndXResponse_Data(AsciiOrUnicodeStructure):
1468 ('PadLen','_-Pad','self["PadLen"]'),
1470 ('NativeFileSystem','z'),
1472 UnicodeStructure = (
1474 ('PadLen','_-Pad','self["PadLen"]'),
1476 ('NativeFileSystem','u'),
1479 ############# SMB_COM_NT_CREATE_ANDX (0xA2)
1480 class SMBNtCreateAndX_Parameters(SMBAndXCommand_Parameters):
1482 ('_reserved', 'B=0'),
1483 ('FileNameLength','<H'), # NameLength
1484 ('CreateFlags','<L'), # Flags
1485 ('RootFid','<L=0'), # RootDirectoryFID
1486 ('AccessMask','<L'), # DesiredAccess
1487 ('AllocationSizeLo','<L=0'), # AllocationSize
1488 ('AllocationSizeHi','<L=0'),
1489 ('FileAttributes','<L=0'), # ExtFileAttributes
1490 ('ShareAccess','<L=3'), #
1491 ('Disposition','<L=1'), # CreateDisposition
1492 ('CreateOptions','<L'), # CreateOptions
1493 ('Impersonation','<L=2'),
1494 ('SecurityFlags','B=3'),
1497 class SMBNtCreateAndXResponse_Parameters(SMBAndXCommand_Parameters):
1498 # 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?
1500 ('OplockLevel', 'B=0'),
1502 ('CreateAction','<L'),
1503 ('CreateTime','<q=0'),
1504 ('LastAccessTime','<q=0'),
1505 ('LastWriteTime','<q=0'),
1506 ('LastChangeTime','<q=0'),
1507 ('FileAttributes','<L=0x80'),
1508 ('AllocationSize','<q=0'),
1509 ('EndOfFile','<q=0'),
1510 ('FileType','<H=0'),
1511 ('IPCState','<H=0'),
1512 ('IsDirectory','B'),
1515 class SMBNtCreateAndXExtendedResponse_Parameters(SMBAndXCommand_Parameters):
1516 # [MS-SMB] Extended response description
1518 ('OplockLevel', 'B=0'),
1520 ('CreateAction','<L'),
1521 ('CreateTime','<q=0'),
1522 ('LastAccessTime','<q=0'),
1523 ('LastWriteTime','<q=0'),
1524 ('LastChangeTime','<q=0'),
1525 ('FileAttributes','<L=0x80'),
1526 ('AllocationSize','<q=0'),
1527 ('EndOfFile','<q=0'),
1528 ('FileType','<H=0'),
1529 ('IPCState','<H=0'),
1530 ('IsDirectory','B'),
1531 ('VolumeGUID','16s'),
1532 ('FileIdLow','<L=0'),
1533 ('FileIdHigh','<L=0'),
1534 ('MaximalAccessRights','<L=0x12019b'),
1535 ('GuestMaximalAccessRights','<L=0x120089'),
1538 class SMBNtCreateAndX_Data(AsciiOrUnicodeStructure):
1542 UnicodeStructure = (
1547 ############# SMB_COM_OPEN_ANDX (0xD2)
1548 class SMBOpenAndX_Parameters(SMBAndXCommand_Parameters):
1551 ('DesiredAccess','<H=0'),
1552 ('SearchAttributes','<H=0'),
1553 ('FileAttributes','<H=0'),
1554 ('CreationTime','<L=0'),
1555 ('OpenMode','<H=1'), # SMB_O_OPEN = 1
1556 ('AllocationSize','<L=0'),
1557 ('Reserved','8s=""'),
1560 class SMBOpenAndX_Data(SMBNtCreateAndX_Data):
1563 class SMBOpenAndXResponse_Parameters(SMBAndXCommand_Parameters):
1566 ('FileAttributes','<H=0'),
1567 ('LastWriten','<L=0'),
1568 ('FileSize','<L=0'),
1569 ('GrantedAccess','<H=0'),
1570 ('FileType','<H=0'),
1571 ('IPCState','<H=0'),
1573 ('ServerFid','<L=0'),
1574 ('_reserved','<H=0'),
1577 ############# SMB_COM_WRITE (0x0B)
1578 class SMBWrite_Parameters(SMBCommand_Parameters):
1586 class SMBWriteResponse_Parameters(SMBCommand_Parameters):
1591 class SMBWrite_Data(Structure):
1593 ('BufferFormat','<B=1'),
1594 ('DataLength','<H-Data'),
1599 ############# SMB_COM_WRITE_ANDX (0x2F)
1600 class SMBWriteAndX_Parameters(SMBAndXCommand_Parameters):
1604 ('_reserved','<L=0xff'),
1605 ('WriteMode','<H=8'),
1606 ('Remaining','<H=0'),
1607 ('DataLength_Hi','<H=0'),
1608 ('DataLength','<H=0'),
1609 ('DataOffset','<H=0'),
1610 ('HighOffset','<L=0'),
1613 class SMBWriteAndX_Data_Short(Structure):
1615 ('_PadLen','_-Pad','self["DataOffset"] - 59'),
1618 ('DataLength','_-Data','self["DataLength"]'),
1622 class SMBWriteAndX_Data(Structure):
1624 ('_PadLen','_-Pad','self["DataOffset"] - 63'),
1627 ('DataLength','_-Data','self["DataLength"]'),
1632 class SMBWriteAndX_Parameters_Short(SMBAndXCommand_Parameters):
1636 ('_reserved','<L=0xff'),
1637 ('WriteMode','<H=8'),
1639 ('DataLength_Hi','<H=0'),
1640 ('DataLength','<H'),
1641 ('DataOffset','<H=0'),
1644 class SMBWriteAndXResponse_Parameters(SMBAndXCommand_Parameters):
1648 ('Reserved','<L=0'),
1651 ############# SMB_COM_WRITE_RAW (0x1D)
1652 class SMBWriteRaw_Parameters(SMBCommand_Parameters):
1656 ('_reserved','<H=0'),
1659 ('WriteMode','<H=0'),
1660 ('_reserved2','<L=0'),
1661 ('DataLength','<H'),
1662 ('DataOffset','<H=0'),
1665 ############# SMB_COM_READ (0x0A)
1666 class SMBRead_Parameters(SMBCommand_Parameters):
1671 ('Remaining','<H=Count'),
1674 class SMBReadResponse_Parameters(Structure):
1677 ('_reserved','8s=""'),
1680 class SMBReadResponse_Data(Structure):
1682 ('BufferFormat','<B=0x1'),
1683 ('DataLength','<H-Data'),
1687 ############# SMB_COM_READ_RAW (0x1A)
1688 class SMBReadRaw_Parameters(SMBCommand_Parameters):
1693 ('MinCount','<H=MaxCount'),
1695 ('_reserved','<H=0'),
1698 ############# SMB_COM_NT_TRANSACT (0xA0)
1699 class SMBNTTransaction_Parameters(SMBCommand_Parameters):
1701 ('MaxSetupCount','<B=0'),
1702 ('Reserved1','<H=0'),
1703 ('TotalParameterCount','<L'),
1704 ('TotalDataCount','<L'),
1705 ('MaxParameterCount','<L=1024'),
1706 ('MaxDataCount','<L=65504'),
1707 ('ParameterCount','<L'),
1708 ('ParameterOffset','<L'),
1710 ('DataOffset','<L'),
1711 ('SetupCount','<B=len(Setup)/2'),
1712 ('Function','<H=0'),
1713 ('SetupLength','_-Setup','SetupCount*2'),
1717 class SMBNTTransactionResponse_Parameters(SMBCommand_Parameters):
1719 ('Reserved1','3s=""'),
1720 ('TotalParameterCount','<L'),
1721 ('TotalDataCount','<L'),
1722 ('ParameterCount','<L'),
1723 ('ParameterOffset','<L'),
1724 ('ParameterDisplacement','<L=0'),
1726 ('DataOffset','<L'),
1727 ('DataDisplacement','<L=0'),
1728 ('SetupCount','<B=0'),
1729 ('SetupLength','_-Setup','SetupCount*2'),
1733 class SMBNTTransaction_Data(Structure):
1735 ('Pad1Length','_-Pad1','self["Pad1Length"]'),
1737 ('NT_Trans_ParametersLength','_-NT_Trans_Parameters','self["NT_Trans_ParametersLength"]'),
1738 ('NT_Trans_Parameters',':'),
1739 ('Pad2Length','_-Pad2','self["Pad2Length"]'),
1741 ('NT_Trans_DataLength','_-NT_Trans_Data','self["NT_Trans_DataLength"]'),
1742 ('NT_Trans_Data',':'),
1745 class SMBNTTransactionResponse_Data(Structure):
1747 ('Pad1Length','_-Pad1','self["Pad1Length"]'),
1749 ('Trans_ParametersLength','_-Trans_Parameters','self["Trans_ParametersLength"]'),
1750 ('Trans_Parameters',':'),
1751 ('Pad2Length','_-Pad2','self["Pad2Length"]'),
1753 ('Trans_DataLength','_-Trans_Data','self["Trans_DataLength"]'),
1758 ############# SMB_COM_TRANSACTION2_SECONDARY (0x33)
1759 class SMBTransaction2Secondary_Parameters(SMBCommand_Parameters):
1761 ('TotalParameterCount','<H'),
1762 ('TotalDataCount','<H'),
1763 ('ParameterCount','<H'),
1764 ('ParameterOffset','<H'),
1766 ('DataOffset','<H'),
1767 ('DataDisplacement','<H=0'),
1771 class SMBTransaction2Secondary_Data(Structure):
1773 ('Pad1Length','_-Pad1','self["Pad1Length"]'),
1775 ('Trans_ParametersLength','_-Trans_Parameters','self["Trans_ParametersLength"]'),
1776 ('Trans_Parameters',':'),
1777 ('Pad2Length','_-Pad2','self["Pad2Length"]'),
1779 ('Trans_DataLength','_-Trans_Data','self["Trans_DataLength"]'),
1784 ############# SMB_COM_TRANSACTION2 (0x32)
1786 class SMBTransaction2_Parameters(SMBCommand_Parameters):
1788 ('TotalParameterCount','<H'),
1789 ('TotalDataCount','<H'),
1790 ('MaxParameterCount','<H=1024'),
1791 ('MaxDataCount','<H=65504'),
1792 ('MaxSetupCount','<B=0'),
1793 ('Reserved1','<B=0'),
1796 ('Reserved2','<H=0'),
1797 ('ParameterCount','<H'),
1798 ('ParameterOffset','<H'),
1800 ('DataOffset','<H'),
1801 ('SetupCount','<B=len(Setup)/2'),
1802 ('Reserved3','<B=0'),
1803 ('SetupLength','_-Setup','SetupCount*2'),
1807 class SMBTransaction2Response_Parameters(SMBCommand_Parameters):
1809 ('TotalParameterCount','<H'),
1810 ('TotalDataCount','<H'),
1811 ('Reserved1','<H=0'),
1812 ('ParameterCount','<H'),
1813 ('ParameterOffset','<H'),
1814 ('ParameterDisplacement','<H=0'),
1816 ('DataOffset','<H'),
1817 ('DataDisplacement','<H=0'),
1818 ('SetupCount','<B=0'),
1819 ('Reserved2','<B=0'),
1820 ('SetupLength','_-Setup','SetupCount*2'),
1824 class SMBTransaction2_Data(Structure):
1826 # ('NameLength','_-Name','1'),
1828 ('Pad1Length','_-Pad1','self["Pad1Length"]'),
1830 ('Trans_ParametersLength','_-Trans_Parameters','self["Trans_ParametersLength"]'),
1831 ('Trans_Parameters',':'),
1832 ('Pad2Length','_-Pad2','self["Pad2Length"]'),
1834 ('Trans_DataLength','_-Trans_Data','self["Trans_DataLength"]'),
1838 class SMBTransaction2Response_Data(Structure):
1840 ('Pad1Length','_-Pad1','self["Pad1Length"]'),
1842 ('Trans_ParametersLength','_-Trans_Parameters','self["Trans_ParametersLength"]'),
1843 ('Trans_Parameters',':'),
1844 ('Pad2Length','_-Pad2','self["Pad2Length"]'),
1846 ('Trans_DataLength','_-Trans_Data','self["Trans_DataLength"]'),
1850 ############# SMB_COM_QUERY_INFORMATION (0x08)
1852 class SMBQueryInformation_Data(AsciiOrUnicodeStructure):
1854 ('BufferFormat','B=4'),
1857 UnicodeStructure = (
1858 ('BufferFormat','B=4'),
1863 class SMBQueryInformationResponse_Parameters(Structure):
1865 ('FileAttributes','<H'),
1866 ('LastWriteTime','<L'),
1868 ('Reserved','"0123456789'),
1871 ############# SMB_COM_TRANSACTION (0x25)
1872 class SMBTransaction_Parameters(SMBCommand_Parameters):
1874 ('TotalParameterCount','<H'),
1875 ('TotalDataCount','<H'),
1876 ('MaxParameterCount','<H=1024'),
1877 ('MaxDataCount','<H=65504'),
1878 ('MaxSetupCount','<B=0'),
1879 ('Reserved1','<B=0'),
1882 ('Reserved2','<H=0'),
1883 ('ParameterCount','<H'),
1884 ('ParameterOffset','<H'),
1886 ('DataOffset','<H'),
1887 ('SetupCount','<B=len(Setup)/2'),
1888 ('Reserved3','<B=0'),
1889 ('SetupLength','_-Setup','SetupCount*2'),
1893 class SMBTransactionResponse_Parameters(SMBCommand_Parameters):
1895 ('TotalParameterCount','<H'),
1896 ('TotalDataCount','<H'),
1897 ('Reserved1','<H=0'),
1898 ('ParameterCount','<H'),
1899 ('ParameterOffset','<H'),
1900 ('ParameterDisplacement','<H=0'),
1902 ('DataOffset','<H'),
1903 ('DataDisplacement','<H=0'),
1904 ('SetupCount','<B'),
1905 ('Reserved2','<B=0'),
1906 ('SetupLength','_-Setup','SetupCount*2'),
1910 # TODO: We should merge these both. But this will require fixing
1911 # the instances where this structure is used on the client side
1912 class SMBTransaction_SData(AsciiOrUnicodeStructure):
1915 ('Trans_ParametersLength','_-Trans_Parameters'),
1916 ('Trans_Parameters',':'),
1917 ('Trans_DataLength','_-Trans_Data'),
1920 UnicodeStructure = (
1923 ('Trans_ParametersLength','_-Trans_Parameters'),
1924 ('Trans_Parameters',':'),
1925 ('Trans_DataLength','_-Trans_Data'),
1929 class SMBTransaction_Data(Structure):
1931 ('NameLength','_-Name'),
1933 ('Trans_ParametersLength','_-Trans_Parameters'),
1934 ('Trans_Parameters',':'),
1935 ('Trans_DataLength','_-Trans_Data'),
1939 class SMBTransactionResponse_Data(Structure):
1941 ('Trans_ParametersLength','_-Trans_Parameters'),
1942 ('Trans_Parameters',':'),
1943 ('Trans_DataLength','_-Trans_Data'),
1947 ############# SMB_COM_READ_ANDX (0x2E)
1948 class SMBReadAndX_Parameters(SMBAndXCommand_Parameters):
1953 ('MinCount','<H=MaxCount'),
1954 ('_reserved','<L=0x0'),
1955 ('Remaining','<H=MaxCount'),
1956 ('HighOffset','<L=0'),
1959 class SMBReadAndX_Parameters2(SMBAndXCommand_Parameters):
1964 ('MinCount','<H=MaxCount'),
1965 ('_reserved','<L=0xffffffff'),
1966 ('Remaining','<H=MaxCount'),
1969 class SMBReadAndXResponse_Parameters(SMBAndXCommand_Parameters):
1971 ('Remaining','<H=0'),
1972 ('DataMode','<H=0'),
1973 ('_reserved','<H=0'),
1975 ('DataOffset','<H'),
1976 ('DataCount_Hi','<L'),
1977 ('_reserved2','6s=""'),
1980 ############# SMB_COM_ECHO (0x2B)
1981 class SMBEcho_Data(Structure):
1986 class SMBEcho_Parameters(Structure):
1991 class SMBEchoResponse_Data(Structure):
1996 class SMBEchoResponse_Parameters(Structure):
1998 ('SequenceNumber','<H=1'),
2001 ############# SMB_COM_QUERY_INFORMATION_DISK (0x80)
2002 class SMBQueryInformationDiskResponse_Parameters(Structure):
2004 ('TotalUnits','<H'),
2005 ('BlocksPerUnit','<H'),
2008 ('Reserved','<H=0'),
2012 ############# SMB_COM_LOGOFF_ANDX (0x74)
2013 class SMBLogOffAndX(SMBAndXCommand_Parameters):
2016 ############# SMB_COM_CLOSE (0x04)
2017 class SMBClose_Parameters(SMBCommand_Parameters):
2023 ############# SMB_COM_FLUSH (0x05)
2024 class SMBFlush_Parameters(SMBCommand_Parameters):
2029 ############# SMB_COM_CREATE_DIRECTORY (0x00)
2030 class SMBCreateDirectory_Data(AsciiOrUnicodeStructure):
2032 ('BufferFormat','<B=4'),
2033 ('DirectoryName','z'),
2035 UnicodeStructure = (
2036 ('BufferFormat','<B=4'),
2037 ('DirectoryName','u'),
2040 ############# SMB_COM_DELETE (0x06)
2041 class SMBDelete_Data(AsciiOrUnicodeStructure):
2043 ('BufferFormat','<B=4'),
2046 UnicodeStructure = (
2047 ('BufferFormat','<B=4'),
2051 class SMBDelete_Parameters(Structure):
2053 ('SearchAttributes','<H'),
2056 ############# SMB_COM_DELETE_DIRECTORY (0x01)
2057 class SMBDeleteDirectory_Data(AsciiOrUnicodeStructure):
2059 ('BufferFormat','<B=4'),
2060 ('DirectoryName','z'),
2062 UnicodeStructure = (
2063 ('BufferFormat','<B=4'),
2064 ('DirectoryName','u'),
2067 ############# SMB_COM_CHECK_DIRECTORY (0x10)
2068 class SMBCheckDirectory_Data(AsciiOrUnicodeStructure):
2070 ('BufferFormat','<B=4'),
2071 ('DirectoryName','z'),
2073 UnicodeStructure = (
2074 ('BufferFormat','<B=4'),
2075 ('DirectoryName','u'),
2078 ############# SMB_COM_RENAME (0x07)
2079 class SMBRename_Parameters(SMBCommand_Parameters):
2081 ('SearchAttributes','<H'),
2084 class SMBRename_Data(AsciiOrUnicodeStructure):
2086 ('BufferFormat1','<B=4'),
2087 ('OldFileName','z'),
2088 ('BufferFormat2','<B=4'),
2089 ('NewFileName','z'),
2091 UnicodeStructure = (
2092 ('BufferFormat1','<B=4'),
2093 ('OldFileName','u'),
2094 ('BufferFormat2','<B=4'),
2096 ('NewFileName','u'),
2100 ############# SMB_COM_OPEN (0x02)
2101 class SMBOpen_Parameters(SMBCommand_Parameters):
2103 ('DesiredAccess','<H=0'),
2104 ('SearchAttributes','<H=0'),
2107 class SMBOpen_Data(AsciiOrUnicodeStructure):
2109 ('FileNameFormat','"\x04'),
2112 UnicodeStructure = (
2113 ('FileNameFormat','"\x04'),
2117 class SMBOpenResponse_Parameters(SMBCommand_Parameters):
2120 ('FileAttributes','<H=0'),
2121 ('LastWriten','<L=0'),
2122 ('FileSize','<L=0'),
2123 ('GrantedAccess','<H=0'),
2126 ############# EXTENDED SECURITY CLASSES
2127 class SMBExtended_Security_Parameters(Structure):
2129 ('DialectIndex','<H'),
2130 ('SecurityMode','<B'),
2131 ('MaxMpxCount','<H'),
2132 ('MaxNumberVcs','<H'),
2133 ('MaxBufferSize','<L'),
2134 ('MaxRawSize','<L'),
2135 ('SessionKey','<L'),
2136 ('Capabilities','<L'),
2137 ('LowDateTime','<L'),
2138 ('HighDateTime','<L'),
2139 ('ServerTimeZone','<H'),
2140 ('ChallengeLength','<B'),
2143 class SMBExtended_Security_Data(Structure):
2145 ('ServerGUID','16s'),
2146 ('SecurityBlob',':'),
2149 class SMBNTLMDialect_Parameters(Structure):
2151 ('DialectIndex','<H'),
2152 ('SecurityMode','<B'),
2153 ('MaxMpxCount','<H'),
2154 ('MaxNumberVcs','<H'),
2155 ('MaxBufferSize','<L'),
2156 ('MaxRawSize','<L'),
2157 ('SessionKey','<L'),
2158 ('Capabilities','<L'),
2159 ('LowDateTime','<L'),
2160 ('HighDateTime','<L'),
2161 ('ServerTimeZone','<H'),
2162 ('ChallengeLength','<B'),
2165 class SMBNTLMDialect_Data(Structure):
2167 ('ChallengeLength','_-Challenge','self["ChallengeLength"]'),
2170 # 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.
2174 def __init__(self,data = None, alignment = 0):
2175 Structure.__init__(self,data,alignment)
2176 #self['ChallengeLength']=8
2178 def fromString(self,data):
2179 Structure.fromString(self,data)
2180 self['DomainName'] = ''
2181 self['ServerName'] = ''
2185 SMB_COM_CREATE_DIRECTORY = 0x00
2186 SMB_COM_DELETE_DIRECTORY = 0x01
2188 SMB_COM_CREATE = 0x03
2189 SMB_COM_CLOSE = 0x04
2190 SMB_COM_FLUSH = 0x05
2191 SMB_COM_DELETE = 0x06
2192 SMB_COM_RENAME = 0x07
2193 SMB_COM_QUERY_INFORMATION = 0x08
2194 SMB_COM_SET_INFORMATION = 0x09
2196 SMB_COM_WRITE = 0x0B
2197 SMB_COM_LOCK_BYTE_RANGE = 0x0C
2198 SMB_COM_UNLOCK_BYTE_RANGE = 0x0D
2199 SMB_COM_CREATE_TEMPORARY = 0x0E
2200 SMB_COM_CREATE_NEW = 0x0F
2201 SMB_COM_CHECK_DIRECTORY = 0x10
2202 SMB_COM_PROCESS_EXIT = 0x11
2204 SMB_COM_LOCK_AND_READ = 0x13
2205 SMB_COM_WRITE_AND_UNLOCK = 0x14
2206 SMB_COM_READ_RAW = 0x1A
2207 SMB_COM_READ_MPX = 0x1B
2208 SMB_COM_READ_MPX_SECONDARY = 0x1C
2209 SMB_COM_WRITE_RAW = 0x1D
2210 SMB_COM_WRITE_MPX = 0x1E
2211 SMB_COM_WRITE_MPX_SECONDARY = 0x1F
2212 SMB_COM_WRITE_COMPLETE = 0x20
2213 SMB_COM_QUERY_SERVER = 0x21
2214 SMB_COM_SET_INFORMATION2 = 0x22
2215 SMB_COM_QUERY_INFORMATION2 = 0x23
2216 SMB_COM_LOCKING_ANDX = 0x24
2217 SMB_COM_TRANSACTION = 0x25
2218 SMB_COM_TRANSACTION_SECONDARY = 0x26
2219 SMB_COM_IOCTL = 0x27
2220 SMB_COM_IOCTL_SECONDARY = 0x28
2224 SMB_COM_WRITE_AND_CLOSE = 0x2C
2225 SMB_COM_OPEN_ANDX = 0x2D
2226 SMB_COM_READ_ANDX = 0x2E
2227 SMB_COM_WRITE_ANDX = 0x2F
2228 SMB_COM_NEW_FILE_SIZE = 0x30
2229 SMB_COM_CLOSE_AND_TREE_DISC = 0x31
2230 SMB_COM_TRANSACTION2 = 0x32
2231 SMB_COM_TRANSACTION2_SECONDARY = 0x33
2232 SMB_COM_FIND_CLOSE2 = 0x34
2233 SMB_COM_FIND_NOTIFY_CLOSE = 0x35
2234 # Used by Xenix/Unix 0x60 - 0x6E
2235 SMB_COM_TREE_CONNECT = 0x70
2236 SMB_COM_TREE_DISCONNECT = 0x71
2237 SMB_COM_NEGOTIATE = 0x72
2238 SMB_COM_SESSION_SETUP_ANDX = 0x73
2239 SMB_COM_LOGOFF_ANDX = 0x74
2240 SMB_COM_TREE_CONNECT_ANDX = 0x75
2241 SMB_COM_QUERY_INFORMATION_DISK = 0x80
2242 SMB_COM_SEARCH = 0x81
2244 SMB_COM_FIND_UNIQUE = 0x83
2245 SMB_COM_FIND_CLOSE = 0x84
2246 SMB_COM_NT_TRANSACT = 0xA0
2247 SMB_COM_NT_TRANSACT_SECONDARY = 0xA1
2248 SMB_COM_NT_CREATE_ANDX = 0xA2
2249 SMB_COM_NT_CANCEL = 0xA4
2250 SMB_COM_NT_RENAME = 0xA5
2251 SMB_COM_OPEN_PRINT_FILE = 0xC0
2252 SMB_COM_WRITE_PRINT_FILE = 0xC1
2253 SMB_COM_CLOSE_PRINT_FILE = 0xC2
2254 SMB_COM_GET_PRINT_QUEUE = 0xC3
2255 SMB_COM_READ_BULK = 0xD8
2256 SMB_COM_WRITE_BULK = 0xD9
2257 SMB_COM_WRITE_BULK_DATA = 0xDA
2260 TRANS_TRANSACT_NMPIPE = 0x26
2263 TRANS2_FIND_FIRST2 = 0x0001
2264 TRANS2_FIND_NEXT2 = 0x0002
2265 TRANS2_QUERY_FS_INFORMATION = 0x0003
2266 TRANS2_QUERY_PATH_INFORMATION = 0x0005
2267 TRANS2_QUERY_FILE_INFORMATION = 0x0007
2268 TRANS2_SET_FILE_INFORMATION = 0x0008
2269 TRANS2_SET_PATH_INFORMATION = 0x0006
2271 # Security Share Mode (Used internally by SMB class)
2272 SECURITY_SHARE_MASK = 0x01
2273 SECURITY_SHARE_SHARE = 0x00
2274 SECURITY_SHARE_USER = 0x01
2275 SECURITY_SIGNATURES_ENABLED = 0X04
2276 SECURITY_SIGNATURES_REQUIRED = 0X08
2278 # Security Auth Mode (Used internally by SMB class)
2279 SECURITY_AUTH_MASK = 0x02
2280 SECURITY_AUTH_ENCRYPTED = 0x02
2281 SECURITY_AUTH_PLAINTEXT = 0x00
2283 # Raw Mode Mask (Used internally by SMB class. Good for dialect up to and including LANMAN2.1)
2284 RAW_READ_MASK = 0x01
2285 RAW_WRITE_MASK = 0x02
2287 # Capabilities Mask (Used internally by SMB class. Good for dialect NT LM 0.12)
2288 CAP_RAW_MODE = 0x00000001
2289 CAP_MPX_MODE = 0x0002
2290 CAP_UNICODE = 0x0004
2291 CAP_LARGE_FILES = 0x0008
2292 CAP_EXTENDED_SECURITY = 0x80000000
2293 CAP_USE_NT_ERRORS = 0x40
2295 CAP_LARGE_READX = 0x00004000
2296 CAP_LARGE_WRITEX = 0x00008000
2297 CAP_RPC_REMOTE_APIS = 0x20
2300 FLAGS1_LOCK_AND_READ_OK = 0x01
2301 FLAGS1_PATHCASELESS = 0x08
2302 FLAGS1_CANONICALIZED_PATHS = 0x10
2306 FLAGS2_LONG_NAMES = 0x0001
2308 FLAGS2_SMB_SECURITY_SIGNATURE = 0x0004
2309 FLAGS2_IS_LONG_NAME = 0x0040
2311 FLAGS2_PAGING_IO = 0x2000
2312 FLAGS2_NT_STATUS = 0x4000
2313 FLAGS2_UNICODE = 0x8000
2314 FLAGS2_COMPRESSED = 0x0008
2315 FLAGS2_SMB_SECURITY_SIGNATURE_REQUIRED = 0x0010
2316 FLAGS2_EXTENDED_SECURITY = 0x0800
2318 # Dialect's Security Mode flags
2319 NEGOTIATE_USER_SECURITY = 0x01
2320 NEGOTIATE_ENCRYPT_PASSWORDS = 0x02
2321 NEGOTIATE_SECURITY_SIGNATURE_ENABLE = 0x04
2322 NEGOTIATE_SECURITY_SIGNATURE_REQUIRED = 0x08
2324 # Tree Connect AndX Response optionalSuppor flags
2325 SMB_SUPPORT_SEARCH_BITS = 0x01
2326 SMB_SHARE_IS_IN_DFS = 0x02
2328 def __init__(self, remote_name, remote_host, my_name = None, host_type = nmb.TYPE_SERVER, sess_port = 445, timeout=None, UDP = 0, session = None, negPacket = None):
2329 # The uid attribute will be set when the client calls the login() method
2331 self.__server_name = ''
2332 self.__server_os = ''
2333 self.__server_os_major = None
2334 self.__server_os_minor = None
2335 self.__server_os_build = None
2336 self.__server_lanman = ''
2337 self.__server_domain = ''
2338 self.__server_dns_domain_name = ''
2339 self.__remote_name = string.upper(remote_name)
2340 self.__remote_host = remote_host
2341 self.__isNTLMv2 = True
2342 self._dialects_parameters = None
2343 self._dialects_data = None
2345 self.__userName = ''
2346 self.__password = ''
2355 # Negotiate Protocol Result, used everywhere
2356 # Could be extended or not, flags should be checked before
2357 self._dialect_data = 0
2358 self._dialect_parameters = 0
2361 self.encrypt_passwords = True
2366 self._SignSequenceNumber = 0
2367 self._SigningSessionKey = ''
2368 self._SigningChallengeResponse = ''
2369 self._SignatureEnabled = False
2370 self._SignatureVerificationEnabled = False
2371 self._SignatureRequired = False
2373 # Base flags (default flags, can be overriden using set_flags())
2374 self.__flags1 = SMB.FLAGS1_PATHCASELESS | SMB.FLAGS1_CANONICALIZED_PATHS
2375 self.__flags2 = SMB.FLAGS2_EXTENDED_SECURITY | SMB.FLAGS2_NT_STATUS | SMB.FLAGS2_LONG_NAMES
2380 self.__timeout = timeout
2382 # If port 445 and the name sent is *SMBSERVER we're setting the name to the IP.
2383 # This is to help some old applications still believing
2384 # *SMSBSERVER will work against modern OSes. If port is NETBIOS_SESSION_PORT the user better
2385 # know about *SMBSERVER's limitations
2386 if sess_port == 445 and remote_name == '*SMBSERVER':
2387 self.__remote_name = remote_host
2391 my_name = socket.gethostname()
2392 i = string.find(my_name, '.')
2394 my_name = my_name[:i]
2397 self._sess = nmb.NetBIOSUDPSession(my_name, remote_name, remote_host, host_type, sess_port, self.__timeout)
2399 self._sess = nmb.NetBIOSTCPSession(my_name, remote_name, remote_host, host_type, sess_port, self.__timeout)
2401 # Initialize session values (_dialect_data and _dialect_parameters)
2404 # Call login() without any authentication information to
2405 # setup a session if the remote server
2407 if (self._dialects_parameters['SecurityMode'] & SMB.SECURITY_SHARE_MASK) == SMB.SECURITY_SHARE_SHARE:
2410 self._sess = session
2411 self.neg_session(negPacket = negPacket)
2412 # Call login() without any authentication information to
2413 # setup a session if the remote server
2415 if (self._dialects_parameters['SecurityMode'] & SMB.SECURITY_SHARE_MASK) == SMB.SECURITY_SHARE_SHARE:
2419 def ntlm_supported():
2422 def get_remote_name(self):
2423 return self.__remote_name
2425 def get_remote_host(self):
2426 return self.__remote_host
2428 def get_flags(self):
2429 return self.__flags1, self.__flags2
2431 def set_flags(self, flags1=None, flags2=None):
2432 if flags1 is not None:
2433 self.__flags1 = flags1
2434 if flags2 is not None:
2435 self.__flags2 = flags2
2437 def set_timeout(self, timeout):
2438 prev_timeout = self.__timeout
2439 self.__timeout = timeout
2442 def get_timeout(self):
2443 return self.__timeout
2446 def use_timeout(self, timeout):
2447 prev_timeout = self.set_timeout(timeout)
2451 self.set_timeout(prev_timeout)
2453 def get_session(self):
2462 def isGuestSession(self):
2463 return self._action & SMB_SETUP_GUEST
2465 def doesSupportNTLMv2(self):
2466 return self.__isNTLMv2
2473 r = self._sess.recv_packet(self.__timeout)
2474 return NewSMBPacket(data = r.get_trailer())
2477 def __decode_trans(params, data):
2478 totparamcnt, totdatacnt, _, paramcnt, paramoffset, paramds, datacnt, dataoffset, datads, setupcnt = unpack('<HHHHHHHHHB', params[:19])
2479 if paramcnt + paramds < totparamcnt or datacnt + datads < totdatacnt:
2483 paramoffset = paramoffset - 55 - setupcnt * 2
2484 dataoffset = dataoffset - 55 - setupcnt * 2
2485 return has_more, params[20:20 + setupcnt * 2], data[paramoffset:paramoffset + paramcnt], data[dataoffset:dataoffset + datacnt]
2487 # TODO: Move this to NewSMBPacket, it belongs there
2488 def signSMB(self, packet, signingSessionKey, signingChallengeResponse):
2489 # This logic MUST be applied for messages sent in response to any of the higher-layer actions and in
2490 # compliance with the message sequencing rules.
2491 # * The client or server that sends the message MUST provide the 32-bit sequence number for this
2492 # message, as specified in sections 3.2.4.1 and 3.3.4.1.
2493 # * The SMB_FLAGS2_SMB_SECURITY_SIGNATURE flag in the header MUST be set.
2494 # * To generate the signature, a 32-bit sequence number is copied into the
2495 # least significant 32 bits of the SecuritySignature field and the remaining
2496 # 4 bytes are set to 0x00.
2497 # * The MD5 algorithm, as specified in [RFC1321], MUST be used to generate a hash of the SMB
2498 # message from the start of the SMB Header, which is defined as follows.
2499 # CALL MD5Init( md5context )
2500 # CALL MD5Update( md5context, Connection.SigningSessionKey )
2501 # CALL MD5Update( md5context, Connection.SigningChallengeResponse )
2502 # CALL MD5Update( md5context, SMB message )
2503 # CALL MD5Final( digest, md5context )
2504 # SET signature TO the first 8 bytes of the digest
2505 # The resulting 8-byte signature MUST be copied into the SecuritySignature field of the SMB Header,
2506 # after which the message can be transmitted.
2508 #print "seq(%d) signingSessionKey %r, signingChallengeResponse %r" % (self._SignSequenceNumber, signingSessionKey, signingChallengeResponse)
2509 packet['SecurityFeatures'] = pack('<q',self._SignSequenceNumber)
2510 # Sign with the sequence
2512 m.update( signingSessionKey )
2513 m.update( signingChallengeResponse )
2514 m.update( str(packet) )
2515 # Replace sequence with acual hash
2516 packet['SecurityFeatures'] = m.digest()[:8]
2517 if self._SignatureVerificationEnabled:
2518 self._SignSequenceNumber +=1
2520 self._SignSequenceNumber +=2
2522 def checkSignSMB(self, packet, signingSessionKey, signingChallengeResponse):
2524 signature = packet['SecurityFeatures']
2525 #print "Signature received: %r " % signature
2526 self.signSMB(packet, signingSessionKey, signingChallengeResponse)
2527 #print "Signature calculated: %r" % packet['SecurityFeatures']
2528 if self._SignatureVerificationEnabled is not True:
2529 self._SignSequenceNumber -= 1
2530 return packet['SecurityFeatures'] == signature
2532 def sendSMB(self,smb):
2533 smb['Uid'] = self._uid
2534 #At least on AIX, PIDs can exceed 16 bits, so we mask them out
2535 smb['Pid'] = (os.getpid() & 0xFFFF)
2537 smb['Flags1'] |= self.__flags1
2538 smb['Flags2'] |= self.__flags2
2539 if self._SignatureEnabled:
2540 smb['Flags2'] |= SMB.FLAGS2_SMB_SECURITY_SIGNATURE
2541 self.signSMB(smb, self._SigningSessionKey, self._SigningChallengeResponse)
2543 self._sess.send_packet(str(smb))
2546 def isValidAnswer(s, cmd):
2549 if s.get_command() == cmd:
2550 if s.get_error_class() == 0x00 and s.get_error_code() == 0x00:
2553 raise SessionError, ( "SMB Library Error", s.get_error_class()+ (s.get_reserved() << 8), s.get_error_code() , s.get_flags2() & SMB.FLAGS2_NT_STATUS )
2558 def neg_session(self, extended_security = True, negPacket = None):
2559 def parsePacket(smb):
2560 if smb.isValidAnswer(SMB.SMB_COM_NEGOTIATE):
2561 sessionResponse = SMBCommand(smb['Data'][0])
2562 self._dialects_parameters = SMBNTLMDialect_Parameters(sessionResponse['Parameters'])
2563 self._dialects_data = SMBNTLMDialect_Data()
2564 self._dialects_data['ChallengeLength'] = self._dialects_parameters['ChallengeLength']
2565 self._dialects_data.fromString(sessionResponse['Data'])
2566 if self._dialects_parameters['Capabilities'] & SMB.CAP_EXTENDED_SECURITY:
2567 # Whether we choose it or it is enforced by the server, we go for extended security
2568 self._dialects_parameters = SMBExtended_Security_Parameters(sessionResponse['Parameters'])
2569 self._dialects_data = SMBExtended_Security_Data(sessionResponse['Data'])
2570 # Let's setup some variable for later use
2571 if self._dialects_parameters['SecurityMode'] & SMB.SECURITY_SIGNATURES_REQUIRED:
2572 self._SignatureRequired = True
2574 # Interestingly, the security Blob might be missing sometimes.
2575 #spnego = SPNEGO_NegTokenInit(self._dialects_data['SecurityBlob'])
2576 #for i in spnego['MechTypes']:
2577 # print "Mech Found: %s" % MechTypes[i]
2580 # If not, let's try the old way
2582 if self._dialects_data['ServerName'] is not None:
2583 self.__server_name = self._dialects_data['ServerName']
2585 if self._dialects_parameters['DialectIndex'] == 0xffff:
2586 raise UnsupportedFeature,"Remote server does not know NT LM 0.12"
2591 if negPacket is None:
2592 smb = NewSMBPacket()
2593 negSession = SMBCommand(SMB.SMB_COM_NEGOTIATE)
2594 flags2 = self.get_flags()[1]
2595 if extended_security is True:
2596 self.set_flags(flags2=flags2|SMB.FLAGS2_EXTENDED_SECURITY)
2598 self.set_flags(flags2=flags2 & (~SMB.FLAGS2_EXTENDED_SECURITY))
2600 negSession['Data'] = '\x02NT LM 0.12\x00'
2601 smb.addCommand(negSession)
2605 smb = self.recvSMB()
2606 return parsePacket(smb)
2609 return parsePacket( NewSMBPacket( data = negPacket))
2611 def tree_connect(self, path, password = '', service = SERVICE_ANY):
2612 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")
2616 # Password is only encrypted if the server passed us an "encryption" during protocol dialect
2617 if self._dialects_parameters['ChallengeLength'] > 0:
2618 # this code is untested
2619 password = self.get_ntlmv1_response(ntlm.compute_lmhash(password))
2621 if not unicode_support:
2625 raise Exception('SMB: Can\t conver path from unicode!')
2627 smb = NewSMBPacket()
2628 treeConnect = SMBCommand(SMB.SMB_COM_TREE_CONNECT)
2629 treeConnect['Parameters'] = SMBTreeConnect_Parameters()
2630 treeConnect['Data'] = SMBTreeConnect_Data()
2631 treeConnect['Data']['Path'] = path.upper()
2632 treeConnect['Data']['Password'] = password
2633 treeConnect['Data']['Service'] = service
2634 smb.addCommand(treeConnect)
2638 smb = self.recvSMB()
2639 if smb.isValidAnswer(SMB.SMB_COM_TREE_CONNECT):
2640 # XXX Here we are ignoring the rest of the response
2647 def set_uid(self, uid):
2650 def tree_connect_andx(self, path, password = None, service = SERVICE_ANY, smb_packet=None):
2652 # Password is only encrypted if the server passed us an "encryption" during protocol dialect
2653 if self._dialects_parameters['ChallengeLength'] > 0:
2654 # this code is untested
2655 password = self.get_ntlmv1_response(ntlm.compute_lmhash(password))
2659 if not unicode_support:
2663 raise Exception('SMB: Can\t convert path from unicode!')
2665 if smb_packet is None:
2666 smb = NewSMBPacket()
2670 # Just in case this came with the full path ,let's just leave
2671 # the sharename, we'll take care of the rest
2673 share = path.split('\\')[-1]
2675 _, _, _, _, sockaddr = socket.getaddrinfo(self.get_remote_host(), 80, 0, 0, socket.IPPROTO_TCP)[0]
2676 remote_host = sockaddr[0]
2678 remote_host = self.get_remote_host()
2680 path = '\\\\' + remote_host + '\\' +share
2681 path = path.upper().encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else path
2683 treeConnect = SMBCommand(SMB.SMB_COM_TREE_CONNECT_ANDX)
2684 treeConnect['Parameters'] = SMBTreeConnectAndX_Parameters()
2685 treeConnect['Data'] = SMBTreeConnectAndX_Data(flags=self.__flags2)
2686 treeConnect['Parameters']['PasswordLength'] = len(password)
2687 treeConnect['Data']['Password'] = password
2688 treeConnect['Data']['Path'] = path
2689 treeConnect['Data']['Service'] = service
2691 if self.__flags2 & SMB.FLAGS2_UNICODE:
2692 treeConnect['Data']['Pad'] = 0x0
2694 smb.addCommand(treeConnect)
2696 # filename = "\PIPE\epmapper"
2698 # ntCreate = SMBCommand(SMB.SMB_COM_NT_CREATE_ANDX)
2699 # ntCreate['Parameters'] = SMBNtCreateAndX_Parameters()
2700 # ntCreate['Data'] = SMBNtCreateAndX_Data()
2701 # ntCreate['Parameters']['FileNameLength'] = len(filename)
2702 # ntCreate['Parameters']['CreateFlags'] = 0
2703 # ntCreate['Parameters']['AccessMask'] = 0x3
2704 # ntCreate['Parameters']['CreateOptions'] = 0x0
2705 # ntCreate['Data']['FileName'] = filename
2707 # smb.addCommand(ntCreate)
2711 smb = self.recvSMB()
2712 if smb.isValidAnswer(SMB.SMB_COM_TREE_CONNECT_ANDX):
2713 # XXX Here we are ignoring the rest of the response
2714 self.tid = smb['Tid']
2716 self.tid = smb['Tid']
2719 # backwars compatibility
2720 connect_tree = tree_connect_andx
2726 def get_server_name(self):
2727 #return self._dialects_data['ServerName']
2728 return self.__server_name
2730 def get_session_key(self):
2731 return self._SigningSessionKey
2733 def set_session_key(self, key):
2734 self._SigningSessionKey = key
2736 def get_encryption_key(self):
2737 if self._dialects_data.fields.has_key('Challenge'):
2738 return self._dialects_data['Challenge']
2742 def get_server_time(self):
2743 timestamp = self._dialects_parameters['HighDateTime']
2745 timestamp |= self._dialects_parameters['LowDateTime']
2746 timestamp -= 116444736000000000
2747 timestamp /= 10000000
2748 d = datetime.datetime.utcfromtimestamp(timestamp)
2749 return d.strftime("%a, %d %b %Y %H:%M:%S GMT")
2751 def disconnect_tree(self, tid):
2752 smb = NewSMBPacket()
2755 smb.addCommand(SMBCommand(SMB.SMB_COM_TREE_DISCONNECT))
2760 def open(self, tid, filename, open_mode, desired_access):
2761 filename = string.replace(filename,'/', '\\')
2762 filename = filename.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else filename
2764 smb = NewSMBPacket()
2767 openFile = SMBCommand(SMB.SMB_COM_OPEN)
2768 openFile['Parameters'] = SMBOpen_Parameters()
2769 openFile['Parameters']['DesiredAccess'] = desired_access
2770 openFile['Parameters']['OpenMode'] = open_mode
2771 openFile['Parameters']['SearchAttributes'] = ATTR_READONLY | ATTR_HIDDEN | ATTR_ARCHIVE
2772 openFile['Data'] = SMBOpen_Data(flags=self.__flags2)
2773 openFile['Data']['FileName'] = filename
2775 if self.__flags2 & SMB.FLAGS2_UNICODE:
2776 openFile['Data']['Pad'] = 0x0
2778 smb.addCommand(openFile)
2782 smb = self.recvSMB()
2783 if smb.isValidAnswer(SMB.SMB_COM_OPEN):
2784 # XXX Here we are ignoring the rest of the response
2785 openFileResponse = SMBCommand(smb['Data'][0])
2786 openFileParameters = SMBOpenResponse_Parameters(openFileResponse['Parameters'])
2789 openFileParameters['Fid'],
2790 openFileParameters['FileAttributes'],
2791 openFileParameters['LastWriten'],
2792 openFileParameters['FileSize'],
2793 openFileParameters['GrantedAccess'],
2796 def open_andx(self, tid, filename, open_mode, desired_access):
2797 filename = string.replace(filename,'/', '\\')
2798 filename = filename.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else filename
2800 smb = NewSMBPacket()
2803 openFile = SMBCommand(SMB.SMB_COM_OPEN_ANDX)
2804 openFile['Parameters'] = SMBOpenAndX_Parameters()
2805 openFile['Parameters']['DesiredAccess'] = desired_access
2806 openFile['Parameters']['OpenMode'] = open_mode
2807 openFile['Parameters']['SearchAttributes'] = ATTR_READONLY | ATTR_HIDDEN | ATTR_ARCHIVE
2808 openFile['Data'] = SMBOpenAndX_Data(flags=self.__flags2)
2809 openFile['Data']['FileName'] = filename
2811 if self.__flags2 & SMB.FLAGS2_UNICODE:
2812 openFile['Data']['Pad'] = 0x0
2814 smb.addCommand(openFile)
2818 smb = self.recvSMB()
2819 if smb.isValidAnswer(SMB.SMB_COM_OPEN_ANDX):
2820 # XXX Here we are ignoring the rest of the response
2821 openFileResponse = SMBCommand(smb['Data'][0])
2822 openFileParameters = SMBOpenAndXResponse_Parameters(openFileResponse['Parameters'])
2825 openFileParameters['Fid'],
2826 openFileParameters['FileAttributes'],
2827 openFileParameters['LastWriten'],
2828 openFileParameters['FileSize'],
2829 openFileParameters['GrantedAccess'],
2830 openFileParameters['FileType'],
2831 openFileParameters['IPCState'],
2832 openFileParameters['Action'],
2833 openFileParameters['ServerFid'],
2836 def close(self, tid, fid):
2837 smb = NewSMBPacket()
2840 closeFile = SMBCommand(SMB.SMB_COM_CLOSE)
2841 closeFile['Parameters'] = SMBClose_Parameters()
2842 closeFile['Parameters']['FID'] = fid
2843 smb.addCommand(closeFile)
2846 smb = self.recvSMB()
2847 if smb.isValidAnswer(SMB.SMB_COM_CLOSE):
2851 def send_trans(self, tid, setup, name, param, data, noAnswer = 0):
2852 smb = NewSMBPacket()
2855 transCommand = SMBCommand(SMB.SMB_COM_TRANSACTION)
2856 transCommand['Parameters'] = SMBTransaction_Parameters()
2857 transCommand['Data'] = SMBTransaction_Data()
2859 transCommand['Parameters']['Setup'] = setup
2860 transCommand['Parameters']['TotalParameterCount'] = len(param)
2861 transCommand['Parameters']['TotalDataCount'] = len(data)
2863 transCommand['Parameters']['ParameterCount'] = len(param)
2864 transCommand['Parameters']['ParameterOffset'] = 32+3+28+len(setup)+len(name)
2866 transCommand['Parameters']['DataCount'] = len(data)
2867 transCommand['Parameters']['DataOffset'] = transCommand['Parameters']['ParameterOffset'] + len(param)
2869 transCommand['Data']['Name'] = name
2870 transCommand['Data']['Trans_Parameters'] = param
2871 transCommand['Data']['Trans_Data'] = data
2874 transCommand['Parameters']['Flags'] = TRANS_NO_RESPONSE
2876 smb.addCommand(transCommand)
2880 def send_trans2(self, tid, setup, name, param, data):
2881 smb = NewSMBPacket()
2884 command = pack('<H', setup)
2886 transCommand = SMBCommand(SMB.SMB_COM_TRANSACTION2)
2887 transCommand['Parameters'] = SMBTransaction2_Parameters()
2888 transCommand['Parameters']['MaxDataCount'] = self._dialects_parameters['MaxBufferSize']
2889 transCommand['Data'] = SMBTransaction2_Data()
2891 transCommand['Parameters']['Setup'] = command
2892 transCommand['Parameters']['TotalParameterCount'] = len(param)
2893 transCommand['Parameters']['TotalDataCount'] = len(data)
2896 padLen = (4 - (32+2+28 + len(command)) % 4 ) % 4
2897 padBytes = '\xFF' * padLen
2898 transCommand['Data']['Pad1'] = padBytes
2900 transCommand['Data']['Pad1'] = ''
2903 transCommand['Parameters']['ParameterCount'] = len(param)
2904 transCommand['Parameters']['ParameterOffset'] = 32+2+28+len(command)+len(name) + padLen
2907 pad2Len = (4 - (32+2+28 + len(command) + padLen + len(param)) % 4) % 4
2908 transCommand['Data']['Pad2'] = '\xFF' * pad2Len
2910 transCommand['Data']['Pad2'] = ''
2913 transCommand['Parameters']['DataCount'] = len(data)
2914 transCommand['Parameters']['DataOffset'] = transCommand['Parameters']['ParameterOffset'] + len(param) + pad2Len
2916 transCommand['Data']['Name'] = name
2917 transCommand['Data']['Trans_Parameters'] = param
2918 transCommand['Data']['Trans_Data'] = data
2919 smb.addCommand(transCommand)
2923 def query_file_info(self, tid, fid, fileInfoClass = SMB_QUERY_FILE_STANDARD_INFO):
2924 self.send_trans2(tid, SMB.TRANS2_QUERY_FILE_INFORMATION, '\x00', pack('<HH', fid, fileInfoClass), '')
2926 resp = self.recvSMB()
2927 if resp.isValidAnswer(SMB.SMB_COM_TRANSACTION2):
2928 trans2Response = SMBCommand(resp['Data'][0])
2929 trans2Parameters = SMBTransaction2Response_Parameters(trans2Response['Parameters'])
2930 # Remove Potential Prefix Padding
2931 return trans2Response['Data'][-trans2Parameters['TotalDataCount']:]
2933 def __nonraw_retr_file(self, tid, fid, offset, datasize, callback):
2934 if (self._dialects_parameters['Capabilities'] & SMB.CAP_LARGE_READX) and self._SignatureEnabled is False:
2935 max_buf_size = 65000
2937 max_buf_size = self._dialects_parameters['MaxBufferSize'] & ~0x3ff # Read in multiple KB blocks
2939 read_offset = offset
2940 while read_offset < datasize:
2941 data = self.read_andx(tid, fid, read_offset, max_buf_size)
2944 read_offset += len(data)
2946 def __nonraw_stor_file(self, tid, fid, offset, datasize, callback):
2947 if (self._dialects_parameters['Capabilities'] & SMB.CAP_LARGE_WRITEX) and self._SignatureEnabled is False:
2948 max_buf_size = 65000
2950 max_buf_size = self._dialects_parameters['MaxBufferSize'] & ~0x3ff # Write in multiple KB blocks
2952 write_offset = offset
2954 data = callback(max_buf_size)
2958 smb = self.write_andx(tid,fid,data, write_offset)
2959 writeResponse = SMBCommand(smb['Data'][0])
2960 writeResponseParameters = SMBWriteAndXResponse_Parameters(writeResponse['Parameters'])
2961 write_offset += writeResponseParameters['Count']
2963 def get_server_domain(self):
2964 return self.__server_domain
2966 def get_server_dns_domain_name(self):
2967 return self.__server_dns_domain_name
2969 def get_server_os(self):
2970 return self.__server_os
2972 def get_server_os_major(self):
2973 return self.__server_os_major
2975 def get_server_os_minor(self):
2976 return self.__server_os_minor
2978 def get_server_os_build(self):
2979 return self.__server_os_build
2981 def set_server_os(self, os):
2982 self.__server_os = os
2984 def get_server_lanman(self):
2985 return self.__server_lanman
2987 def is_login_required(self):
2988 # Login is required if share mode is user.
2989 # Otherwise only public services or services in share mode
2991 return (self._dialects_parameters['SecurityMode'] & SMB.SECURITY_SHARE_MASK) == SMB.SECURITY_SHARE_USER
2993 def is_signing_required(self):
2994 return self._SignatureRequired
2996 def get_ntlmv1_response(self, key):
2997 challenge = self._dialects_data['Challenge']
2998 return ntlm.get_ntlmv1_response(key, challenge)
3000 def kerberos_login(self, user, password, domain = '', lmhash = '', nthash = '', aesKey = '', kdcHost = '', TGT=None, TGS=None):
3001 # Importing down here so pyasn1 is not required if kerberos is not used.
3002 from impacket.krb5.asn1 import AP_REQ, Authenticator, TGS_REP, seq_set
3003 from impacket.krb5.kerberosv5 import getKerberosTGT, getKerberosTGS
3004 from impacket.krb5 import constants
3005 from impacket.krb5.types import Principal, KerberosTime, Ticket
3006 from pyasn1.codec.der import decoder, encoder
3009 # login feature does not support unicode
3010 # disable it if enabled
3011 flags2 = self.__flags2
3012 if flags2 & SMB.FLAGS2_UNICODE:
3013 self.__flags2 = flags2 & (flags2 ^ SMB.FLAGS2_UNICODE)
3015 # If TGT or TGS are specified, they are in the form of:
3016 # TGS['KDC_REP'] = the response from the server
3017 # TGS['cipher'] = the cipher used
3018 # TGS['sessionKey'] = the sessionKey
3019 # If we have hashes, normalize them
3020 if lmhash != '' or nthash != '':
3021 if len(lmhash) % 2: lmhash = '0%s' % lmhash
3022 if len(nthash) % 2: nthash = '0%s' % nthash
3023 try: # just in case they were converted already
3024 lmhash = a2b_hex(lmhash)
3025 nthash = a2b_hex(nthash)
3029 self.__userName = user
3030 self.__password = password
3031 self.__domain = domain
3032 self.__lmhash = lmhash
3033 self.__nthash = nthash
3034 self.__aesKey = aesKey
3035 self.__kdc = kdcHost
3039 # First of all, we need to get a TGT for the user
3040 userName = Principal(user, type=constants.PrincipalNameType.NT_PRINCIPAL.value)
3043 tgt, cipher, oldSessionKey, sessionKey = getKerberosTGT(userName, password, domain, lmhash, nthash, aesKey, kdcHost)
3045 tgt = TGT['KDC_REP']
3046 cipher = TGT['cipher']
3047 sessionKey = TGT['sessionKey']
3049 # Now that we have the TGT, we should ask for a TGS for cifs
3052 serverName = Principal('cifs/%s' % self.__remote_name, type=constants.PrincipalNameType.NT_SRV_INST.value)
3053 tgs, cipher, oldSessionKey, sessionKey = getKerberosTGS(serverName, domain, kdcHost, tgt, cipher, sessionKey)
3055 tgs = TGS['KDC_REP']
3056 cipher = TGS['cipher']
3057 sessionKey = TGS['sessionKey']
3059 smb = NewSMBPacket()
3061 # Are we required to sign SMB? If so we do it, if not we skip it
3062 if self._SignatureRequired:
3063 smb['Flags2'] |= SMB.FLAGS2_SMB_SECURITY_SIGNATURE
3066 sessionSetup = SMBCommand(SMB.SMB_COM_SESSION_SETUP_ANDX)
3067 sessionSetup['Parameters'] = SMBSessionSetupAndX_Extended_Parameters()
3068 sessionSetup['Data'] = SMBSessionSetupAndX_Extended_Data()
3070 sessionSetup['Parameters']['MaxBufferSize'] = 61440
3071 sessionSetup['Parameters']['MaxMpxCount'] = 2
3072 sessionSetup['Parameters']['VcNumber'] = 1
3073 sessionSetup['Parameters']['SessionKey'] = 0
3074 sessionSetup['Parameters']['Capabilities'] = SMB.CAP_EXTENDED_SECURITY | SMB.CAP_USE_NT_ERRORS | SMB.CAP_UNICODE | SMB.CAP_LARGE_READX | SMB.CAP_LARGE_WRITEX
3077 # Let's build a NegTokenInit with the NTLMSSP
3078 # TODO: In the future we should be able to choose different providers
3080 blob = SPNEGO_NegTokenInit()
3083 blob['MechTypes'] = [TypesMech['MS KRB5 - Microsoft Kerberos 5']]
3085 # Let's extract the ticket from the TGS
3086 tgs = decoder.decode(tgs, asn1Spec = TGS_REP())[0]
3088 ticket.from_asn1(tgs['ticket'])
3090 # Now let's build the AP_REQ
3093 apReq['msg-type'] = int(constants.ApplicationTagNumbers.AP_REQ.value)
3096 apReq['ap-options'] = constants.encodeFlags(opts)
3097 seq_set(apReq,'ticket', ticket.to_asn1)
3099 authenticator = Authenticator()
3100 authenticator['authenticator-vno'] = 5
3101 authenticator['crealm'] = domain
3102 seq_set(authenticator, 'cname', userName.components_to_asn1)
3103 now = datetime.datetime.utcnow()
3105 authenticator['cusec'] = now.microsecond
3106 authenticator['ctime'] = KerberosTime.to_asn1(now)
3108 encodedAuthenticator = encoder.encode(authenticator)
3111 # AP-REQ Authenticator (includes application authenticator
3112 # subkey), encrypted with the application session key
3114 encryptedEncodedAuthenticator = cipher.encrypt(sessionKey, 11, encodedAuthenticator, None)
3116 apReq['authenticator'] = None
3117 apReq['authenticator']['etype'] = cipher.enctype
3118 apReq['authenticator']['cipher'] = encryptedEncodedAuthenticator
3120 blob['MechToken'] = encoder.encode(apReq)
3122 sessionSetup['Parameters']['SecurityBlobLength'] = len(blob)
3123 sessionSetup['Parameters'].getData()
3124 sessionSetup['Data']['SecurityBlob'] = blob.getData()
3126 # Fake Data here, don't want to get us fingerprinted
3127 sessionSetup['Data']['NativeOS'] = 'Unix'
3128 sessionSetup['Data']['NativeLanMan'] = 'Samba'
3130 smb.addCommand(sessionSetup)
3133 smb = self.recvSMB()
3134 if smb.isValidAnswer(SMB.SMB_COM_SESSION_SETUP_ANDX):
3135 # We will need to use this uid field for all future requests/responses
3136 self._uid = smb['Uid']
3138 # Now we have to extract the blob to continue the auth process
3139 sessionResponse = SMBCommand(smb['Data'][0])
3140 sessionParameters = SMBSessionSetupAndX_Extended_Response_Parameters(sessionResponse['Parameters'])
3141 sessionData = SMBSessionSetupAndX_Extended_Response_Data(flags = smb['Flags2'])
3142 sessionData['SecurityBlobLength'] = sessionParameters['SecurityBlobLength']
3143 sessionData.fromString(sessionResponse['Data'])
3145 self._action = sessionParameters['Action']
3146 # If smb sign required, let's enable it for the rest of the connection
3147 if self._dialects_parameters['SecurityMode'] & SMB.SECURITY_SIGNATURES_REQUIRED:
3148 self._SigningSessionKey = sessionKey.contents
3149 self._SignSequenceNumber = 2
3150 self._SignatureEnabled = True
3152 # restore unicode flag if needed
3153 if flags2 & SMB.FLAGS2_UNICODE:
3154 self.__flags2 |= SMB.FLAGS2_UNICODE
3158 raise Exception('Error: Could not login successfully')
3160 def login_extended(self, user, password, domain = '', lmhash = '', nthash = '', use_ntlmv2 = True ):
3162 # login feature does not support unicode
3163 # disable it if enabled
3164 flags2 = self.__flags2
3165 if flags2 & SMB.FLAGS2_UNICODE:
3166 self.__flags2 = flags2 & (flags2 ^ SMB.FLAGS2_UNICODE)
3168 # Once everything's working we should join login methods into a single one
3169 smb = NewSMBPacket()
3170 # Are we required to sign SMB? If so we do it, if not we skip it
3171 if self._SignatureRequired:
3172 smb['Flags2'] |= SMB.FLAGS2_SMB_SECURITY_SIGNATURE
3174 sessionSetup = SMBCommand(SMB.SMB_COM_SESSION_SETUP_ANDX)
3175 sessionSetup['Parameters'] = SMBSessionSetupAndX_Extended_Parameters()
3176 sessionSetup['Data'] = SMBSessionSetupAndX_Extended_Data()
3178 sessionSetup['Parameters']['MaxBufferSize'] = 61440
3179 sessionSetup['Parameters']['MaxMpxCount'] = 2
3180 sessionSetup['Parameters']['VcNumber'] = 1
3181 sessionSetup['Parameters']['SessionKey'] = 0
3182 sessionSetup['Parameters']['Capabilities'] = SMB.CAP_EXTENDED_SECURITY | SMB.CAP_USE_NT_ERRORS | SMB.CAP_UNICODE | SMB.CAP_LARGE_READX | SMB.CAP_LARGE_WRITEX
3185 # Let's build a NegTokenInit with the NTLMSSP
3186 # TODO: In the future we should be able to choose different providers
3188 blob = SPNEGO_NegTokenInit()
3191 blob['MechTypes'] = [TypesMech['NTLMSSP - Microsoft NTLM Security Support Provider']]
3192 auth = ntlm.getNTLMSSPType1('','',self._SignatureRequired, use_ntlmv2 = use_ntlmv2)
3193 blob['MechToken'] = str(auth)
3195 sessionSetup['Parameters']['SecurityBlobLength'] = len(blob)
3196 sessionSetup['Parameters'].getData()
3197 sessionSetup['Data']['SecurityBlob'] = blob.getData()
3199 # Fake Data here, don't want to get us fingerprinted
3200 sessionSetup['Data']['NativeOS'] = 'Unix'
3201 sessionSetup['Data']['NativeLanMan'] = 'Samba'
3203 smb.addCommand(sessionSetup)
3206 smb = self.recvSMB()
3207 if smb.isValidAnswer(SMB.SMB_COM_SESSION_SETUP_ANDX):
3208 # We will need to use this uid field for all future requests/responses
3209 self._uid = smb['Uid']
3211 # Now we have to extract the blob to continue the auth process
3212 sessionResponse = SMBCommand(smb['Data'][0])
3213 sessionParameters = SMBSessionSetupAndX_Extended_Response_Parameters(sessionResponse['Parameters'])
3214 sessionData = SMBSessionSetupAndX_Extended_Response_Data(flags = smb['Flags2'])
3215 sessionData['SecurityBlobLength'] = sessionParameters['SecurityBlobLength']
3216 sessionData.fromString(sessionResponse['Data'])
3217 respToken = SPNEGO_NegTokenResp(sessionData['SecurityBlob'])
3219 # Let's parse some data and keep it to ourselves in case it is asked
3220 ntlmChallenge = ntlm.NTLMAuthChallenge(respToken['ResponseToken'])
3221 if ntlmChallenge['TargetInfoFields_len'] > 0:
3222 av_pairs = ntlm.AV_PAIRS(ntlmChallenge['TargetInfoFields'][:ntlmChallenge['TargetInfoFields_len']])
3223 if av_pairs[ntlm.NTLMSSP_AV_HOSTNAME] is not None:
3225 self.__server_name = av_pairs[ntlm.NTLMSSP_AV_HOSTNAME][1].decode('utf-16le')
3227 # For some reason, we couldn't decode Unicode here.. silently discard the operation
3229 if av_pairs[ntlm.NTLMSSP_AV_DOMAINNAME] is not None:
3231 if self.__server_name != av_pairs[ntlm.NTLMSSP_AV_DOMAINNAME][1].decode('utf-16le'):
3232 self.__server_domain = av_pairs[ntlm.NTLMSSP_AV_DOMAINNAME][1].decode('utf-16le')
3234 # For some reason, we couldn't decode Unicode here.. silently discard the operation
3236 if av_pairs[ntlm.NTLMSSP_AV_DNS_DOMAINNAME] is not None:
3238 self.__server_dns_domain_name = av_pairs[ntlm.NTLMSSP_AV_DNS_DOMAINNAME][1].decode('utf-16le')
3240 # For some reason, we couldn't decode Unicode here.. silently discard the operation
3243 # Parse Version to know the target Operating system name. Not provided elsewhere anymore
3244 if ntlmChallenge.fields.has_key('Version'):
3245 version = ntlmChallenge['Version']
3247 if len(version) >= 4:
3248 self.__server_os_major, self.__server_os_minor, self.__server_os_build = unpack('<BBH',version[:4])
3250 type3, exportedSessionKey = ntlm.getNTLMSSPType3(auth, respToken['ResponseToken'], user, password, domain, lmhash, nthash, use_ntlmv2 = use_ntlmv2)
3252 if exportedSessionKey is not None:
3253 self._SigningSessionKey = exportedSessionKey
3255 smb = NewSMBPacket()
3257 # Are we required to sign SMB? If so we do it, if not we skip it
3258 if self._SignatureRequired:
3259 smb['Flags2'] |= SMB.FLAGS2_SMB_SECURITY_SIGNATURE
3261 respToken2 = SPNEGO_NegTokenResp()
3262 respToken2['ResponseToken'] = str(type3)
3264 # Reusing the previous structure
3265 sessionSetup['Parameters']['SecurityBlobLength'] = len(respToken2)
3266 sessionSetup['Data']['SecurityBlob'] = respToken2.getData()
3268 # Storing some info for later use
3269 self.__server_os = sessionData['NativeOS']
3270 self.__server_lanman = sessionData['NativeLanMan']
3272 smb.addCommand(sessionSetup)
3275 smb = self.recvSMB()
3277 if smb.isValidAnswer(SMB.SMB_COM_SESSION_SETUP_ANDX):
3278 self._uid = smb['Uid']
3279 sessionResponse = SMBCommand(smb['Data'][0])
3280 sessionParameters = SMBSessionSetupAndXResponse_Parameters(sessionResponse['Parameters'])
3282 self._action = sessionParameters['Action']
3283 # If smb sign required, let's enable it for the rest of the connection
3284 if self._dialects_parameters['SecurityMode'] & SMB.SECURITY_SIGNATURES_REQUIRED:
3285 self._SignSequenceNumber = 2
3286 self._SignatureEnabled = True
3288 # restore unicode flag if needed
3289 if flags2 & SMB.FLAGS2_UNICODE:
3290 self.__flags2 |= SMB.FLAGS2_UNICODE
3294 raise Exception('Error: Could not login successfully')
3296 def getCredentials(self):
3307 def getIOCapabilities(self):
3309 if (self._dialects_parameters['Capabilities'] & SMB.CAP_LARGE_READX) and self._SignatureEnabled is False:
3312 max_size = self._dialects_parameters['MaxBufferSize'] # Read in multiple KB blocks
3313 res['MaxReadSize'] = max_size
3314 res['MaxWriteSize'] = max_size
3317 def login(self, user, password, domain = '', lmhash = '', nthash = '', ntlm_fallback = True):
3319 # If we have hashes, normalize them
3320 if lmhash != '' or nthash != '':
3321 if len(lmhash) % 2: lmhash = '0%s' % lmhash
3322 if len(nthash) % 2: nthash = '0%s' % nthash
3323 try: # just in case they were converted already
3324 lmhash = a2b_hex(lmhash)
3325 nthash = a2b_hex(nthash)
3329 self.__userName = user
3330 self.__password = password
3331 self.__domain = domain
3332 self.__lmhash = lmhash
3333 self.__nthash = nthash
3338 if self._dialects_parameters['Capabilities'] & SMB.CAP_EXTENDED_SECURITY:
3340 self.login_extended(user, password, domain, lmhash, nthash, use_ntlmv2 = True)
3342 # If the target OS is Windows 5.0 or Samba, let's try using NTLMv1
3343 if ntlm_fallback and ((self.get_server_lanman().find('Windows 2000') != -1) or (self.get_server_lanman().find('Samba') != -1)):
3344 self.login_extended(user, password, domain, lmhash, nthash, use_ntlmv2 = False)
3345 self.__isNTLMv2 = False
3349 self.login_standard(user, password, domain, lmhash, nthash)
3350 self.__isNTLMv2 = False
3352 raise SessionError('Cannot authenticate against target, enable ntlm_fallback')
3354 def login_standard(self, user, password, domain = '', lmhash = '', nthash = ''):
3356 # login feature does not support unicode
3357 # disable it if enabled
3358 flags2 = self.__flags2
3359 if flags2 & SMB.FLAGS2_UNICODE:
3360 self.__flags2 = flags2 & (flags2 ^ SMB.FLAGS2_UNICODE)
3362 # Only supports NTLMv1
3363 # Password is only encrypted if the server passed us an "encryption key" during protocol dialect negotiation
3364 if self._dialects_parameters['ChallengeLength'] > 0:
3365 if lmhash != '' or nthash != '':
3366 pwd_ansi = self.get_ntlmv1_response(lmhash)
3367 pwd_unicode = self.get_ntlmv1_response(nthash)
3369 lmhash = ntlm.compute_lmhash(password)
3370 nthash = ntlm.compute_nthash(password)
3371 pwd_ansi = self.get_ntlmv1_response(lmhash)
3372 pwd_unicode = self.get_ntlmv1_response(nthash)
3373 else: # NULL SESSION
3380 smb = NewSMBPacket()
3382 sessionSetup = SMBCommand(SMB.SMB_COM_SESSION_SETUP_ANDX)
3383 sessionSetup['Parameters'] = SMBSessionSetupAndX_Parameters()
3384 sessionSetup['Data'] = SMBSessionSetupAndX_Data()
3386 sessionSetup['Parameters']['MaxBuffer'] = 61440
3387 sessionSetup['Parameters']['MaxMpxCount'] = 2
3388 sessionSetup['Parameters']['VCNumber'] = os.getpid()
3389 sessionSetup['Parameters']['SessionKey'] = self._dialects_parameters['SessionKey']
3390 sessionSetup['Parameters']['AnsiPwdLength'] = len(pwd_ansi)
3391 sessionSetup['Parameters']['UnicodePwdLength'] = len(pwd_unicode)
3392 sessionSetup['Parameters']['Capabilities'] = SMB.CAP_RAW_MODE | SMB.CAP_USE_NT_ERRORS | SMB.CAP_LARGE_READX | SMB.CAP_LARGE_WRITEX
3394 sessionSetup['Data']['AnsiPwd'] = pwd_ansi
3395 sessionSetup['Data']['UnicodePwd'] = pwd_unicode
3396 sessionSetup['Data']['Account'] = str(user)
3397 sessionSetup['Data']['PrimaryDomain'] = str(domain)
3398 sessionSetup['Data']['NativeOS'] = str(os.name)
3399 sessionSetup['Data']['NativeLanMan'] = 'pysmb'
3400 smb.addCommand(sessionSetup)
3404 smb = self.recvSMB()
3405 if smb.isValidAnswer(SMB.SMB_COM_SESSION_SETUP_ANDX):
3406 # We will need to use this uid field for all future requests/responses
3407 self._uid = smb['Uid']
3408 sessionResponse = SMBCommand(smb['Data'][0])
3409 sessionParameters = SMBSessionSetupAndXResponse_Parameters(sessionResponse['Parameters'])
3410 sessionData = SMBSessionSetupAndXResponse_Data(flags = smb['Flags2'], data = sessionResponse['Data'])
3412 self._action = sessionParameters['Action']
3414 # Still gotta figure out how to do this with no EXTENDED_SECURITY
3415 if sessionParameters['Action'] & SMB_SETUP_USE_LANMAN_KEY == 0:
3416 self._SigningChallengeResponse = sessionSetup['Data']['UnicodePwd']
3417 self._SigningSessionKey = nthash
3419 self._SigningChallengeResponse = sessionSetup['Data']['AnsiPwd']
3420 self._SigningSessionKey = lmhash
3422 #self._SignSequenceNumber = 1
3423 #self.checkSignSMB(smb, self._SigningSessionKey ,self._SigningChallengeResponse)
3424 #self._SignatureEnabled = True
3425 self.__server_os = sessionData['NativeOS']
3426 self.__server_lanman = sessionData['NativeLanMan']
3427 self.__server_domain = sessionData['PrimaryDomain']
3429 # restore unicode flag if needed
3430 if flags2 & SMB.FLAGS2_UNICODE:
3431 self.__flags2 |= SMB.FLAGS2_UNICODE
3434 else: raise Exception('Error: Could not login successfully')
3436 def waitNamedPipe(self, tid, pipe, timeout = 5, noAnswer = 0):
3437 smb = NewSMBPacket()
3440 transCommand = SMBCommand(SMB.SMB_COM_TRANSACTION)
3441 transCommand['Parameters'] = SMBTransaction_Parameters()
3442 transCommand['Data'] = SMBTransaction_Data()
3444 setup = '\x53\x00\x00\x00'
3445 name = '\\PIPE%s\x00' % pipe
3446 transCommand['Parameters']['Setup'] = setup
3447 transCommand['Parameters']['TotalParameterCount'] = 0
3448 transCommand['Parameters']['TotalDataCount'] = 0
3449 transCommand['Parameters']['MaxParameterCount'] = 0
3450 transCommand['Parameters']['MaxDataCount'] = 0
3451 transCommand['Parameters']['Timeout'] = timeout * 1000
3453 transCommand['Parameters']['ParameterCount'] = 0
3454 transCommand['Parameters']['ParameterOffset'] = 32+3+28+len(setup)+len(name)
3456 transCommand['Parameters']['DataCount'] = 0
3457 transCommand['Parameters']['DataOffset'] = 0
3459 transCommand['Data']['Name'] = name
3460 transCommand['Data']['Trans_Parameters'] = ''
3461 transCommand['Data']['Trans_Data'] = ''
3464 transCommand['Parameters']['Flags'] = TRANS_NO_RESPONSE
3466 smb.addCommand(transCommand)
3469 smb = self.recvSMB()
3470 if smb.isValidAnswer(SMB.SMB_COM_TRANSACTION):
3474 def read(self, tid, fid, offset=0, max_size = None, wait_answer=1):
3476 max_size = self._dialects_parameters['MaxBufferSize'] # Read in multiple KB blocks
3478 # max_size is not working, because although it would, the server returns an error (More data avail)
3480 smb = NewSMBPacket()
3483 read = SMBCommand(SMB.SMB_COM_READ)
3484 read['Parameters'] = SMBRead_Parameters()
3485 read['Parameters']['Fid'] = fid
3486 read['Parameters']['Offset'] = offset
3487 read['Parameters']['Count'] = max_size
3488 smb.addCommand(read)
3493 ans = self.recvSMB()
3495 if ans.isValidAnswer(SMB.SMB_COM_READ):
3496 readResponse = SMBCommand(ans['Data'][0])
3497 readData = SMBReadResponse_Data(readResponse['Data'])
3499 return readData['Data']
3503 def read_andx(self, tid, fid, offset=0, max_size = None, wait_answer=1, smb_packet=None):
3505 if (self._dialects_parameters['Capabilities'] & SMB.CAP_LARGE_READX) and self._SignatureEnabled is False:
3508 max_size = self._dialects_parameters['MaxBufferSize'] # Read in multiple KB blocks
3510 # max_size is not working, because although it would, the server returns an error (More data avail)
3512 if smb_packet is None:
3513 smb = NewSMBPacket()
3516 readAndX = SMBCommand(SMB.SMB_COM_READ_ANDX)
3517 readAndX['Parameters'] = SMBReadAndX_Parameters()
3518 readAndX['Parameters']['Fid'] = fid
3519 readAndX['Parameters']['Offset'] = offset
3520 readAndX['Parameters']['MaxCount'] = max_size
3521 smb.addCommand(readAndX)
3529 ans = self.recvSMB()
3531 if ans.isValidAnswer(SMB.SMB_COM_READ_ANDX):
3532 # XXX Here we are only using a few fields from the response
3533 readAndXResponse = SMBCommand(ans['Data'][0])
3534 readAndXParameters = SMBReadAndXResponse_Parameters(readAndXResponse['Parameters'])
3536 offset = readAndXParameters['DataOffset']
3537 count = readAndXParameters['DataCount']+0x10000*readAndXParameters['DataCount_Hi']
3538 answer += str(ans)[offset:offset+count]
3539 if not ans.isMoreData():
3541 max_size = min(max_size, readAndXParameters['Remaining'])
3542 readAndX['Parameters']['Offset'] += count # XXX Offset is not important (apparently)
3545 ans = self.recvSMB()
3548 if ans.isValidAnswer(SMB.SMB_COM_READ_ANDX):
3557 def read_raw(self, tid, fid, offset=0, max_size = None, wait_answer=1):
3559 max_size = self._dialects_parameters['MaxBufferSize'] # Read in multiple KB blocks
3561 # max_size is not working, because although it would, the server returns an error (More data avail)
3562 smb = NewSMBPacket()
3565 readRaw = SMBCommand(SMB.SMB_COM_READ_RAW)
3566 readRaw['Parameters'] = SMBReadRaw_Parameters()
3567 readRaw['Parameters']['Fid'] = fid
3568 readRaw['Parameters']['Offset'] = offset
3569 readRaw['Parameters']['MaxCount'] = max_size
3570 smb.addCommand(readRaw)
3574 data = self._sess.recv_packet(self.__timeout).get_trailer()
3576 # If there is no data it means there was an error
3577 data = self.read_andx(tid, fid, offset, max_size)
3582 def write(self,tid,fid,data, offset = 0, wait_answer=1):
3583 smb = NewSMBPacket()
3586 write = SMBCommand(SMB.SMB_COM_WRITE)
3587 write['Parameters'] = SMBWrite_Parameters()
3588 write['Data'] = SMBWrite_Data()
3589 write['Parameters']['Fid'] = fid
3590 write['Parameters']['Count'] = len(data)
3591 write['Parameters']['Offset'] = offset
3592 write['Parameters']['Remaining'] = len(data)
3593 write['Data']['Data'] = data
3594 smb.addCommand(write)
3599 smb = self.recvSMB()
3600 if smb.isValidAnswer(SMB.SMB_COM_WRITE):
3604 def write_andx(self,tid,fid,data, offset = 0, wait_answer=1, write_pipe_mode = False, smb_packet=None):
3605 if smb_packet is None:
3606 smb = NewSMBPacket()
3609 writeAndX = SMBCommand(SMB.SMB_COM_WRITE_ANDX)
3610 smb.addCommand(writeAndX)
3612 writeAndX['Parameters'] = SMBWriteAndX_Parameters()
3613 writeAndX['Parameters']['Fid'] = fid
3614 writeAndX['Parameters']['Offset'] = offset
3615 writeAndX['Parameters']['WriteMode'] = 8
3616 writeAndX['Parameters']['Remaining'] = len(data)
3617 writeAndX['Parameters']['DataLength'] = len(data)
3618 writeAndX['Parameters']['DataOffset'] = len(smb) # this length already includes the parameter
3619 writeAndX['Data'] = data
3621 if write_pipe_mode is True:
3622 # First of all we gotta know what the MaxBuffSize is
3623 maxBuffSize = self._dialects_parameters['MaxBufferSize']
3624 if len(data) > maxBuffSize:
3625 chunks_size = maxBuffSize - 60
3626 writeAndX['Parameters']['WriteMode'] = 0x0c
3627 sendData = '\xff\xff' + data
3628 totalLen = len(sendData)
3629 writeAndX['Parameters']['DataLength'] = chunks_size
3630 writeAndX['Parameters']['Remaining'] = totalLen-2
3631 writeAndX['Data'] = sendData[:chunks_size]
3635 smbResp = self.recvSMB()
3636 smbResp.isValidAnswer(SMB.SMB_COM_WRITE_ANDX)
3638 alreadySent = chunks_size
3639 sendData = sendData[chunks_size:]
3641 while alreadySent < totalLen:
3642 writeAndX['Parameters']['WriteMode'] = 0x04
3643 writeAndX['Parameters']['DataLength'] = len(sendData[:chunks_size])
3644 writeAndX['Data'] = sendData[:chunks_size]
3647 smbResp = self.recvSMB()
3648 smbResp.isValidAnswer(SMB.SMB_COM_WRITE_ANDX)
3649 alreadySent += writeAndX['Parameters']['DataLength']
3650 sendData = sendData[chunks_size:]
3660 smb = self.recvSMB()
3661 if smb.isValidAnswer(SMB.SMB_COM_WRITE_ANDX):
3665 def write_raw(self,tid,fid,data, offset = 0, wait_answer=1):
3666 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")
3667 smb = NewSMBPacket()
3670 writeRaw = SMBCommand(SMB.SMB_COM_WRITE_RAW)
3671 writeRaw['Parameters'] = SMBWriteRaw_Parameters()
3672 writeRaw['Parameters']['Fid'] = fid
3673 writeRaw['Parameters']['Offset'] = offset
3674 writeRaw['Parameters']['Count'] = len(data)
3675 writeRaw['Parameters']['DataLength'] = 0
3676 writeRaw['Parameters']['DataOffset'] = 0
3677 smb.addCommand(writeRaw)
3680 self._sess.send_packet(data)
3683 smb = self.recvSMB()
3684 if smb.isValidAnswer(SMB.SMB_COM_WRITE_RAW):
3688 def TransactNamedPipe(self, tid, fid, data = '', noAnswer = 0, waitAnswer = 1, offset = 0):
3689 self.send_trans(tid,pack('<HH', 0x26, fid),'\\PIPE\\\x00','',data, noAnswer = noAnswer)
3691 if noAnswer or not waitAnswer:
3693 smb = self.recvSMB()
3694 if smb.isValidAnswer(SMB.SMB_COM_TRANSACTION):
3695 transResponse = SMBCommand(smb['Data'][0])
3696 transParameters = SMBTransactionResponse_Parameters(transResponse['Parameters'])
3697 return transResponse['Data'][-transParameters['TotalDataCount']:] # Remove Potential Prefix Padding
3700 def TransactNamedPipeRecv(self):
3702 if s.isValidAnswer(SMB.SMB_COM_TRANSACTION):
3703 transResponse = SMBCommand(s['Data'][0])
3704 transParameters = SMBTransactionResponse_Parameters(transResponse['Parameters'])
3705 return transResponse['Data'][-transParameters['TotalDataCount']:] # Remove Potential Prefix Padding
3708 def nt_create_andx(self,tid,filename, smb_packet=None, cmd = None, shareAccessMode = FILE_SHARE_READ | FILE_SHARE_WRITE, disposition = FILE_OPEN, accessMask = 0x2019f):
3709 filename = filename.replace('/', '\\')
3710 filename = filename.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else filename
3712 if smb_packet is None:
3713 smb = NewSMBPacket()
3719 ntCreate = SMBCommand(SMB.SMB_COM_NT_CREATE_ANDX)
3720 ntCreate['Parameters'] = SMBNtCreateAndX_Parameters()
3721 ntCreate['Data'] = SMBNtCreateAndX_Data(flags=self.__flags2)
3722 ntCreate['Parameters']['FileNameLength'] = len(filename)
3723 ntCreate['Parameters']['CreateFlags'] = 0x16
3724 ntCreate['Parameters']['AccessMask'] = accessMask
3725 ntCreate['Parameters']['CreateOptions'] = 0x40
3726 ntCreate['Parameters']['ShareAccess'] = shareAccessMode
3727 ntCreate['Parameters']['Disposition'] = disposition
3728 ntCreate['Data']['FileName'] = filename
3730 if self.__flags2 & SMB.FLAGS2_UNICODE:
3731 ntCreate['Data']['Pad'] = 0x0
3735 smb.addCommand(ntCreate)
3740 smb = self.recvSMB()
3741 if smb.isValidAnswer(SMB.SMB_COM_NT_CREATE_ANDX):
3742 # XXX Here we are ignoring the rest of the response
3743 ntCreateResponse = SMBCommand(smb['Data'][0])
3744 ntCreateParameters = SMBNtCreateAndXResponse_Parameters(ntCreateResponse['Parameters'])
3746 self.fid = ntCreateParameters['Fid']
3747 return ntCreateParameters['Fid']
3750 smb = NewSMBPacket()
3752 logOff = SMBCommand(SMB.SMB_COM_LOGOFF_ANDX)
3753 logOff['Parameters'] = SMBLogOffAndX()
3754 smb.addCommand(logOff)
3758 # Let's clear some fields so you can login again under the same session
3761 def list_path(self, service, path = '*', password = None):
3762 path = path.replace('/', '\\')
3763 path = path.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else path
3765 tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
3767 findFirstParameter = SMBFindFirst2_Parameters()
3768 findFirstParameter['SearchAttributes'] = SMB_FILE_ATTRIBUTE_DIRECTORY | SMB_FILE_ATTRIBUTE_HIDDEN | \
3769 SMB_FILE_ATTRIBUTE_SYSTEM | SMB_FILE_ATTRIBUTE_READONLY | \
3770 SMB_FILE_ATTRIBUTE_ARCHIVE
3771 findFirstParameter['SearchCount'] = 512
3772 findFirstParameter['Flags'] = SMB_FIND_RETURN_RESUME_KEYS | SMB_FIND_CLOSE_AT_EOS
3773 findFirstParameter['InformationLevel'] = SMB_FIND_FILE_BOTH_DIRECTORY_INFO
3774 findFirstParameter['SearchStorageType'] = 0
3775 findFirstParameter['FileName'] = path + ('\x00\x00' if self.__flags2 & SMB.FLAGS2_UNICODE else '\x00')
3776 self.send_trans2(tid, SMB.TRANS2_FIND_FIRST2, '\x00', findFirstParameter, '')
3781 findFirst2ParameterBlock = ''
3782 while len(findData) < totalDataCount:
3783 resp = self.recvSMB()
3785 if resp.isValidAnswer(SMB.SMB_COM_TRANSACTION2):
3786 trans2Response = SMBCommand(resp['Data'][0])
3787 trans2Parameters = SMBTransaction2Response_Parameters(trans2Response['Parameters'])
3788 totalDataCount = trans2Parameters['TotalDataCount']
3789 findFirst2ParameterBlock += trans2Response['Data'][trans2Parameters['ParameterOffset']-55:][:trans2Parameters['ParameterCount']]
3790 findData += trans2Response['Data'][trans2Parameters['DataOffset']-55:]
3792 findParameterBlock = SMBFindFirst2Response_Parameters(findFirst2ParameterBlock)
3793 # Save the SID for resume operations
3794 sid = findParameterBlock['SID']
3797 record = SMBFindFileBothDirectoryInfo(data = findData)
3799 shortname = record['ShortName'].decode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else record['ShortName']
3800 filename = record['FileName'].decode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else record['FileName']
3802 fileRecord = SharedFile(record['CreationTime'], record['LastAccessTime'], record['LastChangeTime'],
3803 record['EndOfFile'], record['AllocationSize'], record['ExtFileAttributes'],
3804 shortname, filename)
3805 files.append(fileRecord)
3806 if record['NextEntryOffset'] > 0 and len(findData[record['NextEntryOffset']:]) > 0:
3807 findData = findData[record['NextEntryOffset']:]
3809 # More data to search?
3810 if findParameterBlock['EndOfSearch'] == 0:
3811 resume_filename = record['FileName']
3812 findNextParameter = SMBFindNext2_Parameters()
3813 findNextParameter['SID'] = sid
3814 findNextParameter['SearchCount'] = 1024
3815 findNextParameter['InformationLevel'] = SMB_FIND_FILE_BOTH_DIRECTORY_INFO
3816 findNextParameter['ResumeKey'] = 0
3817 findNextParameter['Flags'] = SMB_FIND_RETURN_RESUME_KEYS | SMB_FIND_CLOSE_AT_EOS
3818 findNextParameter['FileName'] = resume_filename + ('\x00\x00' if self.__flags2 & SMB.FLAGS2_UNICODE else '\x00')
3819 self.send_trans2(tid, SMB.TRANS2_FIND_NEXT2, '\x00', findNextParameter, '')
3821 findNext2ParameterBlock = ''
3823 while len(findData) < totalDataCount:
3824 resp = self.recvSMB()
3826 if resp.isValidAnswer(SMB.SMB_COM_TRANSACTION2):
3827 trans2Response = SMBCommand(resp['Data'][0])
3828 trans2Parameters = SMBTransaction2Response_Parameters(trans2Response['Parameters'])
3829 totalDataCount = trans2Parameters['TotalDataCount']
3830 findNext2ParameterBlock += trans2Response['Data'][trans2Parameters['ParameterOffset']-55:][:trans2Parameters['ParameterCount']]
3831 findData += trans2Response['Data'][trans2Parameters['DataOffset']-55:]
3832 findParameterBlock = SMBFindNext2Response_Parameters(findNext2ParameterBlock)
3836 self.disconnect_tree(tid)
3840 def retr_file(self, service, filename, callback, mode = FILE_OPEN, offset = 0, password = None, shareAccessMode = SMB_ACCESS_READ):
3841 filename = string.replace(filename, '/', '\\')
3844 tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
3846 fid = self.nt_create_andx(tid, filename, shareAccessMode = shareAccessMode, accessMask = 0x20089)
3848 res = self.query_file_info(tid, fid)
3849 datasize = SMBQueryFileStandardInfo(res)['EndOfFile']
3851 self.__nonraw_retr_file(tid, fid, offset, datasize, callback)
3854 self.close(tid, fid)
3855 self.disconnect_tree(tid)
3857 def stor_file(self, service, filename, callback, mode = FILE_OVERWRITE_IF, offset = 0, password = None, shareAccessMode = SMB_ACCESS_WRITE):
3858 filename = string.replace(filename, '/', '\\')
3861 tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
3863 fid = self.nt_create_andx(tid, filename, shareAccessMode = shareAccessMode, disposition = mode )
3865 self.__nonraw_stor_file(tid, fid, offset, 0, callback)
3868 self.close(tid, fid)
3869 self.disconnect_tree(tid)
3871 def stor_file_nonraw(self, service, filename, callback, mode = FILE_OVERWRITE_IF, offset = 0, password = None, shareAccessMode = SMB_ACCESS_WRITE ):
3872 filename = string.replace(filename, '/', '\\')
3875 tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
3877 fid = self.nt_create_andx(tid, filename, shareAccessMode = shareAccessMode, disposition = mode)
3878 self.__nonraw_stor_file(tid, fid, offset, 0, callback)
3881 self.close(tid, fid)
3882 self.disconnect_tree(tid)
3884 def check_dir(self, service, path, password = None):
3885 path = string.replace(path,'/', '\\')
3886 tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
3888 smb = NewSMBPacket()
3892 cmd = SMBCommand(SMB.SMB_COM_CHECK_DIRECTORY)
3893 cmd['Parameters'] = ''
3894 cmd['Data'] = SMBCheckDirectory_Data(flags = self.__flags2)
3895 cmd['Data']['DirectoryName'] = path.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else path
3902 if s.isValidAnswer(SMB.SMB_COM_CHECK_DIRECTORY):
3905 self.disconnect_tree(tid)
3907 def remove(self, service, path, password = None):
3908 path = string.replace(path,'/', '\\')
3909 # Perform a list to ensure the path exists
3910 self.list_path(service, path, password)
3912 tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
3914 smb = NewSMBPacket()
3918 cmd = SMBCommand(SMB.SMB_COM_DELETE)
3919 cmd['Parameters'] = SMBDelete_Parameters()
3920 cmd['Parameters']['SearchAttributes'] = ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE
3921 cmd['Data'] = SMBDelete_Data(flags = self.__flags2)
3922 cmd['Data']['FileName'] = (path + '\x00').encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else (path + '\x00')
3929 if s.isValidAnswer(SMB.SMB_COM_DELETE):
3932 self.disconnect_tree(tid)
3934 def rmdir(self, service, path, password = None):
3935 path = string.replace(path,'/', '\\')
3936 # Check that the directory exists
3937 self.check_dir(service, path, password)
3939 tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
3941 path = path.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else path
3943 smb = NewSMBPacket()
3945 createDir = SMBCommand(SMB.SMB_COM_DELETE_DIRECTORY)
3946 createDir['Data'] = SMBDeleteDirectory_Data(flags=self.__flags2)
3947 createDir['Data']['DirectoryName'] = path
3948 smb.addCommand(createDir)
3954 if s.isValidAnswer(SMB.SMB_COM_DELETE_DIRECTORY):
3957 self.disconnect_tree(tid)
3959 def mkdir(self, service, path, password = None):
3960 path = string.replace(path,'/', '\\')
3961 tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
3963 path = path.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else path
3965 smb = NewSMBPacket()
3969 createDir = SMBCommand(SMB.SMB_COM_CREATE_DIRECTORY)
3970 createDir['Data'] = SMBCreateDirectory_Data(flags=self.__flags2)
3971 createDir['Data']['DirectoryName'] = path
3972 smb.addCommand(createDir)
3976 smb = self.recvSMB()
3977 if smb.isValidAnswer(SMB.SMB_COM_CREATE_DIRECTORY):
3981 self.disconnect_tree(tid)
3983 def rename(self, service, old_path, new_path, password = None):
3984 old_path = string.replace(old_path,'/', '\\')
3985 new_path = string.replace(new_path,'/', '\\')
3986 tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
3988 smb = NewSMBPacket()
3992 renameCmd = SMBCommand(SMB.SMB_COM_RENAME)
3993 renameCmd['Parameters'] = SMBRename_Parameters()
3994 renameCmd['Parameters']['SearchAttributes'] = ATTR_SYSTEM | ATTR_HIDDEN | ATTR_DIRECTORY
3995 renameCmd['Data'] = SMBRename_Data(flags = self.__flags2)
3996 renameCmd['Data']['OldFileName'] = old_path.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else old_path
3997 renameCmd['Data']['NewFileName'] = new_path.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else new_path
3998 smb.addCommand(renameCmd)
4002 smb = self.recvSMB()
4003 if smb.isValidAnswer(SMB.SMB_COM_RENAME):
4007 self.disconnect_tree(tid)
4009 def writeFile(self, treeId, fileId, data, offset = 0):
4010 if (self._dialects_parameters['Capabilities'] & SMB.CAP_LARGE_WRITEX) and self._SignatureEnabled is False:
4011 max_buf_size = 65000
4013 max_buf_size = self._dialects_parameters['MaxBufferSize'] & ~0x3ff # Write in multiple KB blocks
4015 write_offset = offset
4019 writeData = data[:max_buf_size]
4020 data = data[max_buf_size:]
4022 smb = self.write_andx(treeId,fileId,writeData, write_offset)
4023 writeResponse = SMBCommand(smb['Data'][0])
4024 writeResponseParameters = SMBWriteAndXResponse_Parameters(writeResponse['Parameters'])
4025 write_offset += writeResponseParameters['Count']
4027 def get_socket(self):
4028 return self._sess.get_socket()
4030 ERRDOS = { 1: 'Invalid function',
4031 2: 'File not found',
4032 3: 'Invalid directory',
4033 4: 'Too many open files',
4035 6: 'Invalid file handle. Please file a bug report.',
4036 7: 'Memory control blocks destroyed',
4038 9: 'Invalid memory block address',
4039 10: 'Invalid environment',
4040 11: 'Invalid format',
4041 12: 'Invalid open mode',
4043 15: 'Invalid drive',
4044 16: 'Attempt to remove server\'s current directory',
4045 17: 'Not the same device',
4046 18: 'No files found',
4047 32: 'Sharing mode conflicts detected',
4048 33: 'Lock request conflicts detected',
4049 80: 'File already exists'
4052 ERRSRV = { 1: 'Non-specific error',
4055 5: 'Invalid tid. Please file a bug report.',
4056 6: 'Invalid network name',
4057 7: 'Invalid device',
4058 49: 'Print queue full',
4059 50: 'Print queue full',
4060 51: 'EOF on print queue dump',
4061 52: 'Invalid print file handle',
4062 64: 'Command not recognized. Please file a bug report.',
4063 65: 'Internal server error',
4065 69: 'Invalid access permissions',
4066 71: 'Invalid attribute mode',
4067 81: 'Server is paused',
4068 82: 'Not receiving messages',
4069 83: 'No room to buffer messages',
4070 87: 'Too many remote user names',
4071 88: 'Operation timeout',
4072 89: 'Out of resources',
4073 91: 'Invalid user handle. Please file a bug report.',
4074 250: 'Temporarily unable to support raw mode for transfer',
4075 251: 'Temporarily unable to support raw mode for transfer',
4076 252: 'Continue in MPX mode',
4077 65535: 'Unsupported function'
4080 ERRHRD = { 19: 'Media is write-protected',
4082 21: 'Drive not ready',
4083 22: 'Unknown command',
4087 26: 'Unknown media type',
4088 27: 'Sector not found',
4089 28: 'Printer out of paper',
4092 31: 'General failure',
4093 32: 'Open conflicts with an existing open',
4094 33: 'Invalid lock request',
4095 34: 'Wrong disk in drive',
4096 35: 'FCBs not available',
4097 36: 'Sharing buffer exceeded'