Files correlati : utilma verione di curl git-svn-id: svn://10.65.10.50/branches/R_10_00@24159 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			4100 lines
		
	
	
		
			148 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			4100 lines
		
	
	
		
			148 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # Copyright (c) 2003-2016 CORE Security Technologies
 | |
| #
 | |
| # This software is provided under under a slightly modified version
 | |
| # of the Apache Software License. See the accompanying LICENSE file
 | |
| # for more information.
 | |
| #
 | |
| # Copyright (C) 2001 Michael Teo <michaelteo@bigfoot.com>
 | |
| # smb.py - SMB/CIFS library
 | |
| #
 | |
| # This software is provided 'as-is', without any express or implied warranty. 
 | |
| # In no event will the author be held liable for any damages arising from the 
 | |
| # use of this software.
 | |
| #
 | |
| # Permission is granted to anyone to use this software for any purpose, 
 | |
| # including commercial applications, and to alter it and redistribute it 
 | |
| # freely, subject to the following restrictions:
 | |
| #
 | |
| # 1. The origin of this software must not be misrepresented; you must not 
 | |
| #    claim that you wrote the original software. If you use this software 
 | |
| #    in a product, an acknowledgment in the product documentation would be
 | |
| #    appreciated but is not required.
 | |
| #
 | |
| # 2. Altered source versions must be plainly marked as such, and must not be 
 | |
| #    misrepresented as being the original software.
 | |
| #
 | |
| # 3. This notice cannot be removed or altered from any source distribution.
 | |
| #
 | |
| # Altered source done by Alberto Solino (@agsolino)
 | |
| 
 | |
| # Todo:
 | |
| # [ ] Try [SMB]transport fragmentation using Transact requests
 | |
| # [ ] Try other methods of doing write (write_raw, transact2, write, write_and_unlock, write_and_close, write_mpx)
 | |
| # [-] Try replacements for SMB_COM_NT_CREATE_ANDX  (CREATE, T_TRANSACT_CREATE, OPEN_ANDX works
 | |
| # [x] Fix forceWriteAndx, which needs to send a RecvRequest, because recv() will not send it
 | |
| # [x] Fix Recv() when using RecvAndx and the answer comes splet in several packets
 | |
| # [ ] Try [SMB]transport fragmentation with overlaping segments
 | |
| # [ ] Try [SMB]transport fragmentation with out of order segments
 | |
| # [x] Do chained AndX requests
 | |
| # [ ] Transform the rest of the calls to structure
 | |
| # [X] Implement TRANS/TRANS2 reassembly for list_path
 | |
| 
 | |
| import os
 | |
| import socket
 | |
| import string
 | |
| from binascii import a2b_hex
 | |
| import datetime
 | |
| from struct import pack, unpack
 | |
| from contextlib import contextmanager
 | |
| 
 | |
| from impacket import nmb, ntlm, nt_errors, LOG
 | |
| from impacket.structure import Structure
 | |
| from impacket.spnego import SPNEGO_NegTokenInit, TypesMech, SPNEGO_NegTokenResp
 | |
| 
 | |
| # For signing
 | |
| import hashlib
 | |
| 
 | |
| unicode_support = 0
 | |
| unicode_convert = 1
 | |
| 
 | |
| try:
 | |
|     from cStringIO import StringIO
 | |
| except ImportError:
 | |
|     from StringIO import StringIO
 | |
| 
 | |
| # Dialect for SMB1
 | |
| SMB_DIALECT = 'NT LM 0.12'
 | |
| 
 | |
| # Shared Device Type
 | |
| SHARED_DISK                      = 0x00
 | |
| SHARED_DISK_HIDDEN               = 0x80000000
 | |
| SHARED_PRINT_QUEUE               = 0x01
 | |
| SHARED_DEVICE                    = 0x02
 | |
| SHARED_IPC                       = 0x03
 | |
| 
 | |
| # Extended attributes mask
 | |
| ATTR_ARCHIVE                     = 0x020
 | |
| ATTR_COMPRESSED                  = 0x800
 | |
| ATTR_NORMAL                      = 0x080
 | |
| ATTR_HIDDEN                      = 0x002
 | |
| ATTR_READONLY                    = 0x001
 | |
| ATTR_TEMPORARY                   = 0x100
 | |
| ATTR_DIRECTORY                   = 0x010
 | |
| ATTR_SYSTEM                      = 0x004
 | |
| 
 | |
| # Service Type
 | |
| SERVICE_DISK                     = 'A:'
 | |
| SERVICE_PRINTER                  = 'LPT1:'
 | |
| SERVICE_IPC                      = 'IPC'
 | |
| SERVICE_COMM                     = 'COMM'
 | |
| SERVICE_ANY                      = '?????'
 | |
| 
 | |
| # Server Type (Can be used to mask with SMBMachine.get_type() or SMBDomain.get_type())
 | |
| SV_TYPE_WORKSTATION              = 0x00000001
 | |
| SV_TYPE_SERVER                   = 0x00000002
 | |
| SV_TYPE_SQLSERVER                = 0x00000004
 | |
| SV_TYPE_DOMAIN_CTRL              = 0x00000008
 | |
| SV_TYPE_DOMAIN_BAKCTRL           = 0x00000010
 | |
| SV_TYPE_TIME_SOURCE              = 0x00000020
 | |
| SV_TYPE_AFP                      = 0x00000040
 | |
| SV_TYPE_NOVELL                   = 0x00000080
 | |
| SV_TYPE_DOMAIN_MEMBER            = 0x00000100
 | |
| SV_TYPE_PRINTQ_SERVER            = 0x00000200
 | |
| SV_TYPE_DIALIN_SERVER            = 0x00000400
 | |
| SV_TYPE_XENIX_SERVER             = 0x00000800
 | |
| SV_TYPE_NT                       = 0x00001000
 | |
| SV_TYPE_WFW                      = 0x00002000
 | |
| SV_TYPE_SERVER_NT                = 0x00004000
 | |
| SV_TYPE_POTENTIAL_BROWSER        = 0x00010000
 | |
| SV_TYPE_BACKUP_BROWSER           = 0x00020000
 | |
| SV_TYPE_MASTER_BROWSER           = 0x00040000
 | |
| SV_TYPE_DOMAIN_MASTER            = 0x00080000
 | |
| SV_TYPE_LOCAL_LIST_ONLY          = 0x40000000
 | |
| SV_TYPE_DOMAIN_ENUM              = 0x80000000
 | |
| 
 | |
| # Options values for SMB.stor_file and SMB.retr_file
 | |
| SMB_O_CREAT                      = 0x10   # Create the file if file does not exists. Otherwise, operation fails.
 | |
| SMB_O_EXCL                       = 0x00   # When used with SMB_O_CREAT, operation fails if file exists. Cannot be used with SMB_O_OPEN.
 | |
| SMB_O_OPEN                       = 0x01   # Open the file if the file exists
 | |
| SMB_O_TRUNC                      = 0x02   # Truncate the file if the file exists
 | |
| 
 | |
| # Share Access Mode
 | |
| SMB_SHARE_COMPAT                 = 0x00
 | |
| SMB_SHARE_DENY_EXCL              = 0x10
 | |
| SMB_SHARE_DENY_WRITE             = 0x20
 | |
| SMB_SHARE_DENY_READEXEC          = 0x30
 | |
| SMB_SHARE_DENY_NONE              = 0x40
 | |
| SMB_ACCESS_READ                  = 0x00
 | |
| SMB_ACCESS_WRITE                 = 0x01
 | |
| SMB_ACCESS_READWRITE             = 0x02
 | |
| SMB_ACCESS_EXEC                  = 0x03
 | |
| 
 | |
| TRANS_DISCONNECT_TID             = 1
 | |
| TRANS_NO_RESPONSE                = 2
 | |
| 
 | |
| STATUS_SUCCESS                   = 0x00000000
 | |
| STATUS_LOGON_FAILURE             = 0xC000006D
 | |
| STATUS_LOGON_TYPE_NOT_GRANTED    = 0xC000015B
 | |
| MAX_TFRAG_SIZE                   = 5840
 | |
| EVASION_NONE                     = 0
 | |
| EVASION_LOW                      = 1
 | |
| EVASION_HIGH                     = 2
 | |
| EVASION_MAX                      = 3
 | |
| RPC_X_BAD_STUB_DATA              = 0x6F7
 | |
| 
 | |
| # SMB_FILE_ATTRIBUTES
 | |
| 
 | |
| SMB_FILE_ATTRIBUTE_NORMAL        = 0x0000
 | |
| SMB_FILE_ATTRIBUTE_READONLY      = 0x0001
 | |
| SMB_FILE_ATTRIBUTE_HIDDEN        = 0x0002
 | |
| SMB_FILE_ATTRIBUTE_SYSTEM        = 0x0004
 | |
| SMB_FILE_ATTRIBUTE_VOLUME        = 0x0008
 | |
| SMB_FILE_ATTRIBUTE_DIRECTORY     = 0x0010
 | |
| SMB_FILE_ATTRIBUTE_ARCHIVE       = 0x0020
 | |
| SMB_SEARCH_ATTRIBUTE_READONLY    = 0x0100
 | |
| SMB_SEARCH_ATTRIBUTE_HIDDEN      = 0x0200
 | |
| SMB_SEARCH_ATTRIBUTE_SYSTEM      = 0x0400
 | |
| SMB_SEARCH_ATTRIBUTE_DIRECTORY   = 0x1000
 | |
| SMB_SEARCH_ATTRIBUTE_ARCHIVE     = 0x2000
 | |
| 
 | |
| # Session SetupAndX Action flags
 | |
| SMB_SETUP_GUEST                  = 0x01
 | |
| SMB_SETUP_USE_LANMAN_KEY         = 0x02
 | |
| 
 | |
| # QUERY_INFORMATION levels
 | |
| SMB_INFO_ALLOCATION              = 0x0001
 | |
| SMB_INFO_VOLUME                  = 0x0002
 | |
| FILE_FS_SIZE_INFORMATION         = 0x0003
 | |
| SMB_QUERY_FS_VOLUME_INFO         = 0x0102
 | |
| SMB_QUERY_FS_SIZE_INFO           = 0x0103
 | |
| SMB_QUERY_FILE_EA_INFO           = 0x0103
 | |
| SMB_QUERY_FS_DEVICE_INFO         = 0x0104
 | |
| SMB_QUERY_FS_ATTRIBUTE_INFO      = 0x0105
 | |
| SMB_QUERY_FILE_BASIC_INFO        = 0x0101
 | |
| SMB_QUERY_FILE_STANDARD_INFO     = 0x0102
 | |
| SMB_QUERY_FILE_ALL_INFO          = 0x0107
 | |
| FILE_FS_FULL_SIZE_INFORMATION    = 0x03EF
 | |
| 
 | |
| # SET_INFORMATION levels
 | |
| SMB_SET_FILE_DISPOSITION_INFO    = 0x0102
 | |
| SMB_SET_FILE_BASIC_INFO          = 0x0101
 | |
| SMB_SET_FILE_END_OF_FILE_INFO    = 0x0104
 | |
| 
 | |
| 
 | |
| # File System Attributes
 | |
| FILE_CASE_SENSITIVE_SEARCH       = 0x00000001
 | |
| FILE_CASE_PRESERVED_NAMES        = 0x00000002
 | |
| FILE_UNICODE_ON_DISK             = 0x00000004
 | |
| FILE_PERSISTENT_ACLS             = 0x00000008
 | |
| FILE_FILE_COMPRESSION            = 0x00000010
 | |
| FILE_VOLUME_IS_COMPRESSED        = 0x00008000
 | |
| 
 | |
| # FIND_FIRST2 flags and levels
 | |
| SMB_FIND_CLOSE_AFTER_REQUEST     = 0x0001
 | |
| SMB_FIND_CLOSE_AT_EOS            = 0x0002
 | |
| SMB_FIND_RETURN_RESUME_KEYS      = 0x0004
 | |
| SMB_FIND_CONTINUE_FROM_LAST      = 0x0008
 | |
| SMB_FIND_WITH_BACKUP_INTENT      = 0x0010
 | |
| 
 | |
| FILE_DIRECTORY_FILE              = 0x00000001
 | |
| FILE_DELETE_ON_CLOSE             = 0x00001000
 | |
| FILE_NON_DIRECTORY_FILE          = 0x00000040
 | |
| 
 | |
| SMB_FIND_INFO_STANDARD           = 0x0001
 | |
| SMB_FIND_FILE_DIRECTORY_INFO     = 0x0101
 | |
| SMB_FIND_FILE_FULL_DIRECTORY_INFO= 0x0102
 | |
| SMB_FIND_FILE_NAMES_INFO         = 0x0103
 | |
| SMB_FIND_FILE_BOTH_DIRECTORY_INFO= 0x0104
 | |
| SMB_FIND_FILE_ID_FULL_DIRECTORY_INFO = 0x105
 | |
| SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO = 0x106
 | |
| 
 | |
| 
 | |
| # DesiredAccess flags
 | |
| FILE_READ_DATA                   = 0x00000001
 | |
| FILE_WRITE_DATA                  = 0x00000002
 | |
| FILE_APPEND_DATA                 = 0x00000004
 | |
| FILE_EXECUTE                     = 0x00000020
 | |
| MAXIMUM_ALLOWED                  = 0x02000000
 | |
| GENERIC_ALL                      = 0x10000000
 | |
| GENERIC_EXECUTE                  = 0x20000000
 | |
| GENERIC_WRITE                    = 0x40000000
 | |
| GENERIC_READ                     = 0x80000000
 | |
| 
 | |
| # ShareAccess flags
 | |
| FILE_SHARE_NONE                  = 0x00000000
 | |
| FILE_SHARE_READ                  = 0x00000001
 | |
| FILE_SHARE_WRITE                 = 0x00000002
 | |
| FILE_SHARE_DELETE                = 0x00000004
 | |
| 
 | |
| # CreateDisposition flags
 | |
| FILE_SUPERSEDE                  = 0x00000000
 | |
| FILE_OPEN                       = 0x00000001
 | |
| FILE_CREATE                     = 0x00000002
 | |
| FILE_OPEN_IF                    = 0x00000003
 | |
| FILE_OVERWRITE                  = 0x00000004
 | |
| FILE_OVERWRITE_IF               = 0x00000005
 | |
| 
 | |
| def strerror(errclass, errcode):
 | |
|     if errclass == 0x01:
 | |
|         return 'OS error', ERRDOS.get(errcode, 'Unknown error')
 | |
|     elif errclass == 0x02:
 | |
|         return 'Server error', ERRSRV.get(errcode, 'Unknown error')
 | |
|     elif errclass == 0x03:
 | |
|         return 'Hardware error', ERRHRD.get(errcode, 'Unknown error')
 | |
|     # This is not a standard error class for SMB
 | |
|     #elif errclass == 0x80:
 | |
|     #    return 'Browse error', ERRBROWSE.get(errcode, 'Unknown error')
 | |
|     elif errclass == 0xff:
 | |
|         return 'Bad command', 'Bad command. Please file bug report'
 | |
|     else:
 | |
|         return 'Unknown error', 'Unknown error'
 | |
| 
 | |
| # Raised when an error has occured during a session
 | |
| class SessionError(Exception):
 | |
|     # SMB X/Open error codes for the ERRDOS error class
 | |
|     ERRsuccess                           = 0
 | |
|     ERRbadfunc                           = 1
 | |
|     ERRbadfile                           = 2
 | |
|     ERRbadpath                           = 3
 | |
|     ERRnofids                            = 4
 | |
|     ERRnoaccess                          = 5
 | |
|     ERRbadfid                            = 6
 | |
|     ERRbadmcb                            = 7
 | |
|     ERRnomem                             = 8
 | |
|     ERRbadmem                            = 9
 | |
|     ERRbadenv                            = 10
 | |
|     ERRbadaccess                         = 12
 | |
|     ERRbaddata                           = 13
 | |
|     ERRres                               = 14
 | |
|     ERRbaddrive                          = 15
 | |
|     ERRremcd                             = 16
 | |
|     ERRdiffdevice                        = 17
 | |
|     ERRnofiles                           = 18
 | |
|     ERRgeneral                           = 31
 | |
|     ERRbadshare                          = 32
 | |
|     ERRlock                              = 33
 | |
|     ERRunsup                             = 50
 | |
|     ERRnetnamedel                        = 64
 | |
|     ERRnosuchshare                       = 67
 | |
|     ERRfilexists                         = 80
 | |
|     ERRinvalidparam                      = 87
 | |
|     ERRcannotopen                        = 110
 | |
|     ERRinsufficientbuffer                = 122
 | |
|     ERRinvalidname                       = 123
 | |
|     ERRunknownlevel                      = 124
 | |
|     ERRnotlocked                         = 158
 | |
|     ERRrename                            = 183
 | |
|     ERRbadpipe                           = 230
 | |
|     ERRpipebusy                          = 231
 | |
|     ERRpipeclosing                       = 232
 | |
|     ERRnotconnected                      = 233
 | |
|     ERRmoredata                          = 234
 | |
|     ERRnomoreitems                       = 259
 | |
|     ERRbaddirectory                      = 267
 | |
|     ERReasnotsupported                   = 282
 | |
|     ERRlogonfailure                      = 1326
 | |
|     ERRbuftoosmall                       = 2123
 | |
|     ERRunknownipc                        = 2142
 | |
|     ERRnosuchprintjob                    = 2151
 | |
|     ERRinvgroup                          = 2455
 | |
| 
 | |
|     # here's a special one from observing NT
 | |
|     ERRnoipc                             = 66
 | |
| 
 | |
|     # These errors seem to be only returned by the NT printer driver system
 | |
|     ERRdriveralreadyinstalled            = 1795
 | |
|     ERRunknownprinterport                = 1796
 | |
|     ERRunknownprinterdriver              = 1797
 | |
|     ERRunknownprintprocessor             = 1798
 | |
|     ERRinvalidseparatorfile              = 1799
 | |
|     ERRinvalidjobpriority                = 1800
 | |
|     ERRinvalidprintername                = 1801
 | |
|     ERRprinteralreadyexists              = 1802
 | |
|     ERRinvalidprintercommand             = 1803
 | |
|     ERRinvaliddatatype                   = 1804
 | |
|     ERRinvalidenvironment                = 1805
 | |
| 
 | |
|     ERRunknownprintmonitor               = 3000
 | |
|     ERRprinterdriverinuse                = 3001
 | |
|     ERRspoolfilenotfound                 = 3002
 | |
|     ERRnostartdoc                        = 3003
 | |
|     ERRnoaddjob                          = 3004
 | |
|     ERRprintprocessoralreadyinstalled    = 3005
 | |
|     ERRprintmonitoralreadyinstalled      = 3006
 | |
|     ERRinvalidprintmonitor               = 3007
 | |
|     ERRprintmonitorinuse                 = 3008
 | |
|     ERRprinterhasjobsqueued              = 3009
 | |
| 
 | |
|     # Error codes for the ERRSRV class
 | |
| 
 | |
|     ERRerror                             = 1
 | |
|     ERRbadpw                             = 2
 | |
|     ERRbadtype                           = 3
 | |
|     ERRaccess                            = 4
 | |
|     ERRinvnid                            = 5
 | |
|     ERRinvnetname                        = 6
 | |
|     ERRinvdevice                         = 7
 | |
|     ERRqfull                             = 49
 | |
|     ERRqtoobig                           = 50
 | |
|     ERRinvpfid                           = 52
 | |
|     ERRsmbcmd                            = 64
 | |
|     ERRsrverror                          = 65
 | |
|     ERRfilespecs                         = 67
 | |
|     ERRbadlink                           = 68
 | |
|     ERRbadpermits                        = 69
 | |
|     ERRbadpid                            = 70
 | |
|     ERRsetattrmode                       = 71
 | |
|     ERRpaused                            = 81
 | |
|     ERRmsgoff                            = 82
 | |
|     ERRnoroom                            = 83
 | |
|     ERRrmuns                             = 87
 | |
|     ERRtimeout                           = 88
 | |
|     ERRnoresource                        = 89
 | |
|     ERRtoomanyuids                       = 90
 | |
|     ERRbaduid                            = 91
 | |
|     ERRuseMPX                            = 250
 | |
|     ERRuseSTD                            = 251
 | |
|     ERRcontMPX                           = 252
 | |
|     ERRbadPW                             = None
 | |
|     ERRnosupport                         = 0
 | |
|     ERRunknownsmb                        = 22
 | |
| 
 | |
|     # Error codes for the ERRHRD class
 | |
| 
 | |
|     ERRnowrite                           = 19
 | |
|     ERRbadunit                           = 20
 | |
|     ERRnotready                          = 21
 | |
|     ERRbadcmd                            = 22
 | |
|     ERRdata                              = 23
 | |
|     ERRbadreq                            = 24
 | |
|     ERRseek                              = 25
 | |
|     ERRbadmedia                          = 26
 | |
|     ERRbadsector                         = 27
 | |
|     ERRnopaper                           = 28
 | |
|     ERRwrite                             = 29
 | |
|     ERRread                              = 30
 | |
|     ERRwrongdisk                         = 34
 | |
|     ERRFCBunavail                        = 35
 | |
|     ERRsharebufexc                       = 36
 | |
|     ERRdiskfull                          = 39
 | |
| 
 | |
| 
 | |
|     hard_msgs = {
 | |
|       19: ("ERRnowrite", "Attempt to write on write-protected diskette."),
 | |
|       20: ("ERRbadunit", "Unknown unit."),
 | |
|       21: ("ERRnotready", "Drive not ready."),
 | |
|       22: ("ERRbadcmd", "Unknown command."),
 | |
|       23: ("ERRdata", "Data error (CRC)."),
 | |
|       24: ("ERRbadreq", "Bad request structure length."),
 | |
|       25: ("ERRseek", "Seek error."),
 | |
|       26: ("ERRbadmedia", "Unknown media type."),
 | |
|       27: ("ERRbadsector", "Sector not found."),
 | |
|       28: ("ERRnopaper", "Printer out of paper."),
 | |
|       29: ("ERRwrite", "Write fault."),
 | |
|       30: ("ERRread", "Read fault."),
 | |
|       31: ("ERRgeneral", "General failure."),
 | |
|       32: ("ERRbadshare", "An open conflicts with an existing open."),
 | |
|       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."),
 | |
|       34: ("ERRwrongdisk", "The wrong disk was found in a drive."),
 | |
|       35: ("ERRFCBUnavail", "No FCBs are available to process request."),
 | |
|       36: ("ERRsharebufexc", "A sharing buffer has been exceeded.")
 | |
|       }
 | |
| 
 | |
|     dos_msgs = {
 | |
|       ERRbadfunc: ("ERRbadfunc", "Invalid function."),
 | |
|       ERRbadfile: ("ERRbadfile", "File not found."),
 | |
|       ERRbadpath: ("ERRbadpath", "Directory invalid."),
 | |
|       ERRnofids: ("ERRnofids", "No file descriptors available"),
 | |
|       ERRnoaccess: ("ERRnoaccess", "Access denied."),
 | |
|       ERRbadfid: ("ERRbadfid", "Invalid file handle."),
 | |
|       ERRbadmcb: ("ERRbadmcb", "Memory control blocks destroyed."),
 | |
|       ERRnomem: ("ERRnomem", "Insufficient server memory to perform the requested function."),
 | |
|       ERRbadmem: ("ERRbadmem", "Invalid memory block address."),
 | |
|       ERRbadenv: ("ERRbadenv", "Invalid environment."),
 | |
|       11: ("ERRbadformat", "Invalid format."),
 | |
|       ERRbadaccess: ("ERRbadaccess", "Invalid open mode."),
 | |
|       ERRbaddata: ("ERRbaddata", "Invalid data."),
 | |
|       ERRres: ("ERRres", "reserved."),
 | |
|       ERRbaddrive: ("ERRbaddrive", "Invalid drive specified."),
 | |
|       ERRremcd: ("ERRremcd", "A Delete Directory request attempted  to  remove  the  server's  current directory."),
 | |
|       ERRdiffdevice: ("ERRdiffdevice", "Not same device."),
 | |
|       ERRnofiles: ("ERRnofiles", "A File Search command can find no more files matching the specified criteria."),
 | |
|       ERRbadshare: ("ERRbadshare", "The sharing mode specified for an Open conflicts with existing  FIDs  on the file."),
 | |
|       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."),
 | |
|       ERRunsup: ("ERRunsup",  "The operation is unsupported"),
 | |
|       ERRnosuchshare: ("ERRnosuchshare",  "You specified an invalid share name"),
 | |
|       ERRfilexists: ("ERRfilexists", "The file named in a Create Directory, Make  New  File  or  Link  request already exists."),
 | |
|       ERRinvalidname: ("ERRinvalidname",  "Invalid name"),
 | |
|       ERRbadpipe: ("ERRbadpipe", "Pipe invalid."),
 | |
|       ERRpipebusy: ("ERRpipebusy", "All instances of the requested pipe are busy."),
 | |
|       ERRpipeclosing: ("ERRpipeclosing", "Pipe close in progress."),
 | |
|       ERRnotconnected: ("ERRnotconnected", "No process on other end of pipe."),
 | |
|       ERRmoredata: ("ERRmoredata", "There is more data to be returned."),
 | |
|       ERRinvgroup: ("ERRinvgroup", "Invalid workgroup (try the -W option)"),
 | |
|       ERRlogonfailure: ("ERRlogonfailure", "Logon failure"),
 | |
|       ERRdiskfull: ("ERRdiskfull", "Disk full"),
 | |
|       ERRgeneral: ("ERRgeneral",  "General failure"),
 | |
|       ERRunknownlevel: ("ERRunknownlevel",  "Unknown info level")
 | |
|       }
 | |
| 
 | |
|     server_msgs = {
 | |
|       1: ("ERRerror", "Non-specific error code."),
 | |
|       2: ("ERRbadpw", "Bad password - name/password pair in a Tree Connect or Session Setup are invalid."),
 | |
|       3: ("ERRbadtype", "reserved."),
 | |
|       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."),
 | |
|       5: ("ERRinvnid", "The tree ID (TID) specified in a command was invalid."),
 | |
|       6: ("ERRinvnetname", "Invalid network name in tree connect."),
 | |
|       7: ("ERRinvdevice", "Invalid device - printer request made to non-printer connection or  non-printer request made to printer connection."),
 | |
|       49: ("ERRqfull", "Print queue full (files) -- returned by open print file."),
 | |
|       50: ("ERRqtoobig", "Print queue full -- no space."),
 | |
|       51: ("ERRqeof", "EOF on print queue dump."),
 | |
|       52: ("ERRinvpfid", "Invalid print file FID."),
 | |
|       64: ("ERRsmbcmd", "The server did not recognize the command received."),
 | |
|       65: ("ERRsrverror","The server encountered an internal error, e.g., system file unavailable."),
 | |
|       67: ("ERRfilespecs", "The file handle (FID) and pathname parameters contained an invalid  combination of values."),
 | |
|       68: ("ERRreserved", "reserved."),
 | |
|       69: ("ERRbadpermits", "The access permissions specified for a file or directory are not a valid combination.  The server cannot set the requested attribute."),
 | |
|       70: ("ERRreserved", "reserved."),
 | |
|       71: ("ERRsetattrmode", "The attribute mode in the Set File Attribute request is invalid."),
 | |
|       81: ("ERRpaused", "Server is paused."),
 | |
|       82: ("ERRmsgoff", "Not receiving messages."),
 | |
|       83: ("ERRnoroom", "No room to buffer message."),
 | |
|       87: ("ERRrmuns", "Too many remote user names."),
 | |
|       88: ("ERRtimeout", "Operation timed out."),
 | |
|       89: ("ERRnoresource", "No resources currently available for request."),
 | |
|       90: ("ERRtoomanyuids", "Too many UIDs active on this session."),
 | |
|       91: ("ERRbaduid", "The UID is not known as a valid ID on this session."),
 | |
|       250: ("ERRusempx","Temp unable to support Raw, use MPX mode."),
 | |
|       251: ("ERRusestd","Temp unable to support Raw, use standard read/write."),
 | |
|       252: ("ERRcontmpx", "Continue in MPX mode."),
 | |
|       253: ("ERRreserved", "reserved."),
 | |
|       254: ("ERRreserved", "reserved."),
 | |
|   0xFFFF: ("ERRnosupport", "Function not supported.")
 | |
|   }
 | |
|     # Error clases
 | |
| 
 | |
|     ERRDOS = 0x1
 | |
|     error_classes = { 0: ("SUCCESS", {}),
 | |
|                       ERRDOS: ("ERRDOS", dos_msgs),
 | |
|                       0x02: ("ERRSRV",server_msgs),
 | |
|                       0x03: ("ERRHRD",hard_msgs),
 | |
|                       0x04: ("ERRXOS", {} ),
 | |
|                       0xE1: ("ERRRMX1", {} ),
 | |
|                       0xE2: ("ERRRMX2", {} ),
 | |
|                       0xE3: ("ERRRMX3", {} ),
 | |
|                       0xFF: ("ERRCMD", {} ) }
 | |
| 
 | |
| 
 | |
| 
 | |
|     def __init__( self, error_string, error_class, error_code, nt_status = 0):
 | |
|         Exception.__init__(self, error_string)
 | |
|         self.nt_status = nt_status
 | |
|         self._args = error_string
 | |
|         if nt_status:
 | |
|            self.error_class = 0
 | |
|            self.error_code  = (error_code << 16) + error_class
 | |
|         else:
 | |
|            self.error_class = error_class
 | |
|            self.error_code = error_code
 | |
| 
 | |
| 
 | |
|     def get_error_class( self ):
 | |
|         return self.error_class
 | |
| 
 | |
|     def get_error_code( self ):
 | |
|         return self.error_code
 | |
| 
 | |
|     def __str__( self ):
 | |
|         error_class = SessionError.error_classes.get( self.error_class, None )
 | |
|         if not error_class:
 | |
|             error_code_str = self.error_code
 | |
|             error_class_str = self.error_class
 | |
|         else:
 | |
|             error_class_str = error_class[0]
 | |
|             error_code = error_class[1].get( self.error_code, None )
 | |
|             if not error_code:
 | |
|                 error_code_str = self.error_code
 | |
|             else:
 | |
|                 error_code_str = '%s(%s)' % error_code
 | |
| 
 | |
|         if self.nt_status:
 | |
|             return 'SMB SessionError: %s(%s)' % nt_errors.ERROR_MESSAGES[self.error_code]
 | |
|         else:
 | |
|             # Fall back to the old format
 | |
|             return 'SMB SessionError: class: %s, code: %s' % (error_class_str, error_code_str)
 | |
| 
 | |
| 
 | |
| # Raised when an supported feature is present/required in the protocol but is not
 | |
| # currently supported by pysmb
 | |
| class UnsupportedFeature(Exception): pass
 | |
| 
 | |
| # Contains information about a SMB shared device/service
 | |
| class SharedDevice:
 | |
|     def __init__(self, name, share_type, comment):
 | |
|         self.__name = name
 | |
|         self.__type = share_type
 | |
|         self.__comment = comment
 | |
| 
 | |
|     def get_name(self):
 | |
|         return self.__name
 | |
| 
 | |
|     def get_type(self):
 | |
|         return self.__type
 | |
| 
 | |
|     def get_comment(self):
 | |
|         return self.__comment
 | |
| 
 | |
|     def __repr__(self):
 | |
|         return '<SharedDevice instance: name=' + self.__name + ', type=' + str(self.__type) + ', comment="' + self.__comment + '">'
 | |
| 
 | |
| 
 | |
| # Contains information about the shared file/directory
 | |
| class SharedFile:
 | |
|     def __init__(self, ctime, atime, mtime, filesize, allocsize, attribs, shortname, longname):
 | |
|         self.__ctime = ctime
 | |
|         self.__atime = atime
 | |
|         self.__mtime = mtime
 | |
|         self.__filesize = filesize
 | |
|         self.__allocsize = allocsize
 | |
|         self.__attribs = attribs
 | |
|         try:
 | |
|             self.__shortname = shortname[:string.index(shortname, '\0')]
 | |
|         except ValueError:
 | |
|             self.__shortname = shortname
 | |
|         try:
 | |
|             self.__longname = longname[:string.index(longname, '\0')]
 | |
|         except ValueError:
 | |
|             self.__longname = longname
 | |
| 
 | |
|     def get_ctime(self):
 | |
|         return self.__ctime
 | |
| 
 | |
|     def get_ctime_epoch(self):
 | |
|         return self.__convert_smbtime(self.__ctime)
 | |
| 
 | |
|     def get_mtime(self):
 | |
|         return self.__mtime
 | |
| 
 | |
|     def get_mtime_epoch(self):
 | |
|         return self.__convert_smbtime(self.__mtime)
 | |
| 
 | |
|     def get_atime(self):
 | |
|         return self.__atime
 | |
| 
 | |
|     def get_atime_epoch(self):
 | |
|         return self.__convert_smbtime(self.__atime)
 | |
| 
 | |
|     def get_filesize(self):
 | |
|         return self.__filesize
 | |
| 
 | |
|     def get_allocsize(self):
 | |
|         return self.__allocsize
 | |
| 
 | |
|     def get_attributes(self):
 | |
|         return self.__attribs
 | |
| 
 | |
|     def is_archive(self):
 | |
|         return self.__attribs & ATTR_ARCHIVE
 | |
| 
 | |
|     def is_compressed(self):
 | |
|         return self.__attribs & ATTR_COMPRESSED
 | |
| 
 | |
|     def is_normal(self):
 | |
|         return self.__attribs & ATTR_NORMAL
 | |
| 
 | |
|     def is_hidden(self):
 | |
|         return self.__attribs & ATTR_HIDDEN
 | |
| 
 | |
|     def is_readonly(self):
 | |
|         return self.__attribs & ATTR_READONLY
 | |
| 
 | |
|     def is_temporary(self):
 | |
|         return self.__attribs & ATTR_TEMPORARY
 | |
| 
 | |
|     def is_directory(self):
 | |
|         return self.__attribs & ATTR_DIRECTORY
 | |
| 
 | |
|     def is_system(self):
 | |
|         return self.__attribs & ATTR_SYSTEM
 | |
| 
 | |
|     def get_shortname(self):
 | |
|         return self.__shortname
 | |
| 
 | |
|     def get_longname(self):
 | |
|         return self.__longname
 | |
| 
 | |
|     def __repr__(self):
 | |
|         return '<SharedFile instance: shortname="' + self.__shortname + '", longname="' + self.__longname + '", filesize=' + str(self.__filesize) + '>'
 | |
| 
 | |
|     @staticmethod
 | |
|     def __convert_smbtime(t):
 | |
|         x = t >> 32
 | |
|         y = t & 0xffffffffL
 | |
|         geo_cal_offset = 11644473600.0  # = 369.0 * 365.25 * 24 * 60 * 60 - (3.0 * 24 * 60 * 60 + 6.0 * 60 * 60)
 | |
|         return (x * 4.0 * (1 << 30) + (y & 0xfff00000L)) * 1.0e-7 - geo_cal_offset
 | |
| 
 | |
| 
 | |
| # Contain information about a SMB machine
 | |
| class SMBMachine:
 | |
|     def __init__(self, nbname, nbt_type, comment):
 | |
|         self.__nbname = nbname
 | |
|         self.__type = nbt_type
 | |
|         self.__comment = comment
 | |
| 
 | |
|     def __repr__(self):
 | |
|         return '<SMBMachine instance: nbname="' + self.__nbname + '", type=' + hex(self.__type) + ', comment="' + self.__comment + '">'
 | |
| 
 | |
| class SMBDomain:
 | |
|     def __init__(self, nbgroup, domain_type, master_browser):
 | |
|         self.__nbgroup = nbgroup
 | |
|         self.__type = domain_type
 | |
|         self.__master_browser = master_browser
 | |
| 
 | |
|     def __repr__(self):
 | |
|         return '<SMBDomain instance: nbgroup="' + self.__nbgroup + '", type=' + hex(self.__type) + ', master browser="' + self.__master_browser + '">'
 | |
| 
 | |
| # Represents a SMB Packet
 | |
| class NewSMBPacket(Structure):
 | |
|     structure = (
 | |
|         ('Signature', '"\xffSMB'),
 | |
|         ('Command','B=0'),
 | |
|         ('ErrorClass','B=0'),
 | |
|         ('_reserved','B=0'),
 | |
|         ('ErrorCode','<H=0'),
 | |
|         ('Flags1','B=0'),
 | |
|         ('Flags2','<H=0'),
 | |
|         ('PIDHigh','<H=0'),
 | |
|         ('SecurityFeatures','8s=""'),
 | |
|         ('Reserved','<H=0'),
 | |
|         ('Tid','<H=0xffff'),
 | |
|         ('Pid','<H=0'),
 | |
|         ('Uid','<H=0'),
 | |
|         ('Mid','<H=0'),
 | |
|         ('Data','*:'),
 | |
|     )
 | |
| 
 | |
|     def __init__(self, **kargs):
 | |
|         Structure.__init__(self, **kargs)
 | |
| 
 | |
|         if self.fields.has_key('Flags2') is False:
 | |
|              self['Flags2'] = 0
 | |
|         if self.fields.has_key('Flags1') is False:
 | |
|              self['Flags1'] = 0
 | |
| 
 | |
|         if not kargs.has_key('data'):
 | |
|             self['Data'] = []
 | |
| 
 | |
|     def addCommand(self, command):
 | |
|         if len(self['Data']) == 0:
 | |
|             self['Command'] = command.command
 | |
|         else:
 | |
|             self['Data'][-1]['Parameters']['AndXCommand'] = command.command
 | |
|             self['Data'][-1]['Parameters']['AndXOffset'] = len(self)
 | |
|         self['Data'].append(command)
 | |
| 
 | |
|     def isMoreData(self):
 | |
|         return (self['Command'] in [SMB.SMB_COM_TRANSACTION, SMB.SMB_COM_READ_ANDX, SMB.SMB_COM_READ_RAW] and
 | |
|                 self['ErrorClass'] == 1 and self['ErrorCode'] == SessionError.ERRmoredata)
 | |
| 
 | |
|     def isMoreProcessingRequired(self):
 | |
|         return self['ErrorClass'] == 0x16 and self['ErrorCode'] == 0xc000
 | |
| 
 | |
|     def isValidAnswer(self, cmd):
 | |
|         # this was inside a loop reading more from the net (with recv_packet(None))
 | |
|         if self['Command'] == cmd:
 | |
|             if (self['ErrorClass'] == 0x00 and
 | |
|                 self['ErrorCode']  == 0x00):
 | |
|                     return 1
 | |
|             elif self.isMoreData():
 | |
|                 return 1
 | |
|             elif self.isMoreProcessingRequired():
 | |
|                 return 1
 | |
|             raise SessionError, ("SMB Library Error", self['ErrorClass'] + (self['_reserved'] << 8), self['ErrorCode'], self['Flags2'] & SMB.FLAGS2_NT_STATUS)
 | |
|         else:
 | |
|             raise UnsupportedFeature, ("Unexpected answer from server: Got %d, Expected %d" % (self['Command'], cmd))
 | |
| 
 | |
| 
 | |
| class SMBCommand(Structure):
 | |
|     structure = (
 | |
|         ('WordCount', 'B=len(Parameters)/2'),
 | |
|         ('_ParametersLength','_-Parameters','WordCount*2'),
 | |
|         ('Parameters',':'),             # default set by constructor
 | |
|         ('ByteCount','<H-Data'),
 | |
|         ('Data',':'),                   # default set by constructor
 | |
|     )
 | |
| 
 | |
|     def __init__(self, commandOrData = None, data = None, **kargs):
 | |
|         if type(commandOrData) == type(0):
 | |
|             self.command = commandOrData
 | |
|         else:
 | |
|             data = data or commandOrData
 | |
| 
 | |
|         Structure.__init__(self, data = data, **kargs)
 | |
| 
 | |
|         if data is None:
 | |
|             self['Parameters'] = ''
 | |
|             self['Data']       = ''
 | |
| 
 | |
| class AsciiOrUnicodeStructure(Structure):
 | |
|     UnicodeStructure = ()
 | |
|     AsciiStructure   = ()
 | |
|     def __init__(self, flags = 0, **kargs):
 | |
|         if flags & SMB.FLAGS2_UNICODE:
 | |
|             self.structure = self.UnicodeStructure
 | |
|         else:
 | |
|             self.structure = self.AsciiStructure
 | |
|         Structure.__init__(self, **kargs)
 | |
| 
 | |
| class SMBCommand_Parameters(Structure):
 | |
|     pass
 | |
| 
 | |
| class SMBAndXCommand_Parameters(Structure):
 | |
|     commonHdr = (
 | |
|         ('AndXCommand','B=0xff'),
 | |
|         ('_reserved','B=0'),
 | |
|         ('AndXOffset','<H=0'),
 | |
|     )
 | |
|     structure = (       # default structure, overriden by subclasses
 | |
|         ('Data',':=""'),
 | |
|     )
 | |
| 
 | |
| ############# TRANSACTIONS RELATED
 | |
| # TRANS2_QUERY_FS_INFORMATION
 | |
| # QUERY_FS Information Levels
 | |
| # SMB_QUERY_FS_ATTRIBUTE_INFO
 | |
| class SMBQueryFsAttributeInfo(Structure):
 | |
|     structure = (
 | |
|         ('FileSystemAttributes','<L'),
 | |
|         ('MaxFilenNameLengthInBytes','<L'),
 | |
|         ('LengthOfFileSystemName','<L-FileSystemName'),
 | |
|         ('FileSystemName',':'),
 | |
|     )
 | |
| 
 | |
| class SMBQueryFsInfoVolume(AsciiOrUnicodeStructure):
 | |
|     commonHdr = (
 | |
|         ('ulVolSerialNbr','<L=0xABCDEFAA'),
 | |
|         ('cCharCount','<B-VolumeLabel'),
 | |
|     )
 | |
|     AsciiStructure = (
 | |
|         ('VolumeLabel','z'),
 | |
|     )
 | |
|     UnicodeStructure = (
 | |
|         ('VolumeLabel','u'),
 | |
|     )
 | |
| 
 | |
| # FILE_FS_SIZE_INFORMATION
 | |
| class FileFsSizeInformation(Structure):
 | |
|     structure = (
 | |
|         ('TotalAllocationUnits','<q=148529400'),
 | |
|         ('AvailableAllocationUnits','<q=14851044'),
 | |
|         ('SectorsPerAllocationUnit','<L=2'),
 | |
|         ('BytesPerSector','<L=512'),
 | |
|     )
 | |
| 
 | |
| # SMB_QUERY_FS_SIZE_INFO
 | |
| class SMBQueryFsSizeInfo(Structure):
 | |
|     structure = (
 | |
|         ('TotalAllocationUnits','<q=148529400'),
 | |
|         ('TotalFreeAllocationUnits','<q=14851044'),
 | |
|         ('SectorsPerAllocationUnit','<L=2'),
 | |
|         ('BytesPerSector','<L=512'),
 | |
|     )
 | |
| # FILE_FS_FULL_SIZE_INFORMATION
 | |
| class SMBFileFsFullSizeInformation(Structure):
 | |
|     structure = (
 | |
|         ('TotalAllocationUnits','<q=148529400'),
 | |
|         ('CallerAvailableAllocationUnits','<q=148529400'),
 | |
|         ('ActualAvailableAllocationUnits','<q=148529400'),
 | |
|         ('SectorsPerAllocationUnit','<L=15'),
 | |
|         ('BytesPerSector','<L=512')
 | |
|     )
 | |
| # SMB_QUERY_FS_VOLUME_INFO
 | |
| class SMBQueryFsVolumeInfo(Structure):
 | |
|     structure = (
 | |
|         ('VolumeCreationTime','<q'),
 | |
|         ('SerialNumber','<L=0xABCDEFAA'),
 | |
|         ('VolumeLabelSize','<L=len(VolumeLabel)'),
 | |
|         ('Reserved','<H=0x10'),
 | |
|         ('VolumeLabel',':')
 | |
|     )
 | |
| # SMB_FIND_FILE_BOTH_DIRECTORY_INFO level
 | |
| class SMBFindFileBothDirectoryInfo(AsciiOrUnicodeStructure):
 | |
|     commonHdr = (
 | |
|         ('NextEntryOffset','<L=0'),
 | |
|         ('FileIndex','<L=0'),
 | |
|         ('CreationTime','<q'),
 | |
|         ('LastAccessTime','<q'),
 | |
|         ('LastWriteTime','<q'),
 | |
|         ('LastChangeTime','<q'),
 | |
|         ('EndOfFile','<q=0'),
 | |
|         ('AllocationSize','<q=0'),
 | |
|         ('ExtFileAttributes','<L=0'),
 | |
|     )
 | |
|     AsciiStructure = (
 | |
|         ('FileNameLength','<L-FileName','len(FileName)'),
 | |
|         ('EaSize','<L=0'),
 | |
|         ('ShortNameLength','<B=0'),
 | |
|         ('Reserved','<B=0'),
 | |
|         ('ShortName','24s'),
 | |
|         ('FileName',':'),
 | |
|     )
 | |
|     UnicodeStructure = (
 | |
|         ('FileNameLength','<L-FileName','len(FileName)*2'),
 | |
|         ('EaSize','<L=0'),
 | |
|         ('ShortNameLength','<B=0'),
 | |
|         ('Reserved','<B=0'),
 | |
|         ('ShortName','24s'),
 | |
|         ('FileName',':'),
 | |
|     )
 | |
| 
 | |
| # SMB_FIND_FILE_ID_FULL_DIRECTORY_INFO level
 | |
| class SMBFindFileIdFullDirectoryInfo(AsciiOrUnicodeStructure):
 | |
|     commonHdr = (
 | |
|         ('NextEntryOffset','<L=0'),
 | |
|         ('FileIndex','<L=0'),
 | |
|         ('CreationTime','<q'),
 | |
|         ('LastAccessTime','<q'),
 | |
|         ('LastWriteTime','<q'),
 | |
|         ('LastChangeTime','<q'),
 | |
|         ('EndOfFile','<q=0'),
 | |
|         ('AllocationSize','<q=0'),
 | |
|         ('ExtFileAttributes','<L=0'),
 | |
|     )
 | |
|     AsciiStructure = (
 | |
|         ('FileNameLength','<L-FileName','len(FileName)'),
 | |
|         ('EaSize','<L=0'),
 | |
|         ('FileID','<q=0'),
 | |
|         ('FileName',':'),
 | |
|     )
 | |
|     UnicodeStructure = (
 | |
|         ('FileNameLength','<L-FileName','len(FileName)*2'),
 | |
|         ('EaSize','<L=0'),
 | |
|         ('FileID','<q=0'),
 | |
|         ('FileName',':'),
 | |
|     )
 | |
| 
 | |
| # SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO level
 | |
| class SMBFindFileIdBothDirectoryInfo(AsciiOrUnicodeStructure):
 | |
|     commonHdr = (
 | |
|         ('NextEntryOffset','<L=0'),
 | |
|         ('FileIndex','<L=0'),
 | |
|         ('CreationTime','<q'),
 | |
|         ('LastAccessTime','<q'),
 | |
|         ('LastWriteTime','<q'),
 | |
|         ('LastChangeTime','<q'),
 | |
|         ('EndOfFile','<q=0'),
 | |
|         ('AllocationSize','<q=0'),
 | |
|         ('ExtFileAttributes','<L=0'),
 | |
|     )
 | |
|     AsciiStructure = (
 | |
|         ('FileNameLength','<L-FileName','len(FileName)'),
 | |
|         ('EaSize','<L=0'),
 | |
|         ('ShortNameLength','<B=0'),
 | |
|         ('Reserved','<B=0'),
 | |
|         ('ShortName','24s'),
 | |
|         ('Reserved','<H=0'),
 | |
|         ('FileID','<q=0'),
 | |
|         ('FileName','z'),
 | |
|     )
 | |
|     UnicodeStructure = (
 | |
|         ('FileNameLength','<L-FileName','len(FileName)*2'),
 | |
|         ('EaSize','<L=0'),
 | |
|         ('ShortNameLength','<B=0'),
 | |
|         ('Reserved','<B=0'),
 | |
|         ('ShortName','24s'),
 | |
|         ('Reserved','<H=0'),
 | |
|         ('FileID','<q=0'),
 | |
|         ('FileName',':'),
 | |
|     )
 | |
| 
 | |
| # SMB_FIND_FILE_DIRECTORY_INFO level
 | |
| class SMBFindFileDirectoryInfo(AsciiOrUnicodeStructure):
 | |
|     commonHdr = (
 | |
|         ('NextEntryOffset','<L=0'),
 | |
|         ('FileIndex','<L=0'),
 | |
|         ('CreationTime','<q'),
 | |
|         ('LastAccessTime','<q'),
 | |
|         ('LastWriteTime','<q'),
 | |
|         ('LastChangeTime','<q'),
 | |
|         ('EndOfFile','<q=0'),
 | |
|         ('AllocationSize','<q=1'),
 | |
|         ('ExtFileAttributes','<L=0'),
 | |
|     )
 | |
|     AsciiStructure = (
 | |
|         ('FileNameLength','<L-FileName','len(FileName)'),
 | |
|         ('FileName','z'),
 | |
|     )
 | |
|     UnicodeStructure = (
 | |
|         ('FileNameLength','<L-FileName','len(FileName)*2'),
 | |
|         ('FileName',':'),
 | |
|     )
 | |
| 
 | |
| # SMB_FIND_FILE_NAMES_INFO level
 | |
| class SMBFindFileNamesInfo(AsciiOrUnicodeStructure):
 | |
|     commonHdr = (
 | |
|         ('NextEntryOffset','<L=0'),
 | |
|         ('FileIndex','<L=0'),
 | |
|     )
 | |
|     AsciiStructure = (
 | |
|         ('FileNameLength','<L-FileName','len(FileName)'),
 | |
|         ('FileName','z'),
 | |
|     )
 | |
|     UnicodeStructure = (
 | |
|         ('FileNameLength','<L-FileName','len(FileName)*2'),
 | |
|         ('FileName',':'),
 | |
|     )
 | |
| 
 | |
| # SMB_FIND_FILE_FULL_DIRECTORY_INFO level
 | |
| class SMBFindFileFullDirectoryInfo(AsciiOrUnicodeStructure):
 | |
|     commonHdr = (
 | |
|         ('NextEntryOffset','<L=0'),
 | |
|         ('FileIndex','<L=0'),
 | |
|         ('CreationTime','<q'),
 | |
|         ('LastAccessTime','<q'),
 | |
|         ('LastWriteTime','<q'),
 | |
|         ('LastChangeTime','<q'),
 | |
|         ('EndOfFile','<q=0'),
 | |
|         ('AllocationSize','<q=1'),
 | |
|         ('ExtFileAttributes','<L=0'),
 | |
|     )
 | |
|     AsciiStructure = (
 | |
|         ('FileNameLength','<L-FileName','len(FileName)'),
 | |
|         ('EaSize','<L'),
 | |
|         ('FileName','z'),
 | |
|     )
 | |
|     UnicodeStructure = (
 | |
|         ('FileNameLength','<L-FileName','len(FileName)*2'),
 | |
|         ('EaSize','<L'),
 | |
|         ('FileName',':'),
 | |
|     )
 | |
| 
 | |
| # SMB_FIND_INFO_STANDARD level
 | |
| class SMBFindInfoStandard(AsciiOrUnicodeStructure):
 | |
|     commonHdr = (
 | |
|         ('ResumeKey','<L=0xff'),
 | |
|         ('CreationDate','<H=0'),
 | |
|         ('CreationTime','<H=0'),
 | |
|         ('LastAccessDate','<H=0'),
 | |
|         ('LastAccessTime','<H=0'),
 | |
|         ('LastWriteDate','<H=0'),
 | |
|         ('LastWriteTime','<H=0'),
 | |
|         ('EaSize','<L'),
 | |
|         ('AllocationSize','<L=1'),
 | |
|         ('ExtFileAttributes','<H=0'),
 | |
|     )
 | |
|     AsciiStructure = (
 | |
|         ('FileNameLength','<B-FileName','len(FileName)'),
 | |
|         ('FileName','z'),
 | |
|     )
 | |
|     UnicodeStructure = (
 | |
|         ('FileNameLength','<B-FileName','len(FileName)*2'),
 | |
|         ('FileName',':'),
 | |
|     )
 | |
| 
 | |
| # SET_FILE_INFORMATION structures
 | |
| # SMB_SET_FILE_DISPOSITION_INFO
 | |
| class SMBSetFileDispositionInfo(Structure):
 | |
|     structure = (
 | |
|         ('DeletePending','<B'),
 | |
|     )
 | |
| 
 | |
| # SMB_SET_FILE_BASIC_INFO
 | |
| class SMBSetFileBasicInfo(Structure):
 | |
|     structure = (
 | |
|         ('CreationTime','<q'),
 | |
|         ('LastAccessTime','<q'),
 | |
|         ('LastWriteTime','<q'),
 | |
|         ('ChangeTime','<q'),
 | |
|         ('ExtFileAttributes','<H'),
 | |
|         ('Reserved','<L'),
 | |
|     )
 | |
| 
 | |
| # FILE_STREAM_INFORMATION
 | |
| class SMBFileStreamInformation(Structure):
 | |
|     commonHdr = (
 | |
|         ('NextEntryOffset','<L=0'),
 | |
|         ('StreamNameLength','<L=0'),
 | |
|         ('StreamSize','<q=0'),
 | |
|         ('StreamAllocationSize','<q=0'),
 | |
|         ('StreamName',':=""'),
 | |
|     )
 | |
| 
 | |
| # FILE_NETWORK_OPEN_INFORMATION
 | |
| class SMBFileNetworkOpenInfo(Structure):
 | |
|     structure = (
 | |
|         ('CreationTime','<q=0'),
 | |
|         ('LastAccessTime','<q=0'),
 | |
|         ('LastWriteTime','<q=0'),
 | |
|         ('ChangeTime','<q=0'),
 | |
|         ('AllocationSize','<q=0'),
 | |
|         ('EndOfFile','<q=0'),
 | |
|         ('FileAttributes','<L=0'),
 | |
|         ('Reserved','<L=0'),
 | |
|     )
 | |
| 
 | |
| # SMB_SET_FILE_END_OF_FILE_INFO
 | |
| class SMBSetFileEndOfFileInfo(Structure):
 | |
|     structure = (
 | |
|         ('EndOfFile','<q'),
 | |
|     )
 | |
| 
 | |
| # TRANS2_FIND_NEXT2
 | |
| class SMBFindNext2_Parameters(AsciiOrUnicodeStructure):
 | |
|      commonHdr = (
 | |
|          ('SID','<H'),
 | |
|          ('SearchCount','<H'),
 | |
|          ('InformationLevel','<H'),
 | |
|          ('ResumeKey','<L'),
 | |
|          ('Flags','<H'),
 | |
|      )
 | |
|      AsciiStructure = (
 | |
|          ('FileName','z'),
 | |
|      )
 | |
|      UnicodeStructure = (
 | |
|          ('FileName','u'),
 | |
|      )
 | |
| 
 | |
| class SMBFindNext2Response_Parameters(Structure):
 | |
|      structure = (
 | |
|          ('SearchCount','<H'),
 | |
|          ('EndOfSearch','<H=1'),
 | |
|          ('EaErrorOffset','<H=0'),
 | |
|          ('LastNameOffset','<H=0'),
 | |
|      )
 | |
| 
 | |
| class SMBFindNext2_Data(Structure):
 | |
|      structure = (
 | |
|          ('GetExtendedAttributesListLength','_-GetExtendedAttributesList', 'self["GetExtendedAttributesListLength"]'),
 | |
|          ('GetExtendedAttributesList',':'),
 | |
|      )
 | |
| 
 | |
| 
 | |
| # TRANS2_FIND_FIRST2 
 | |
| class SMBFindFirst2Response_Parameters(Structure):
 | |
|      structure = (
 | |
|          ('SID','<H'),
 | |
|          ('SearchCount','<H'),
 | |
|          ('EndOfSearch','<H=1'),
 | |
|          ('EaErrorOffset','<H=0'),
 | |
|          ('LastNameOffset','<H=0'),
 | |
|      )
 | |
| 
 | |
| class SMBFindFirst2_Parameters(AsciiOrUnicodeStructure):
 | |
|      commonHdr = (
 | |
|          ('SearchAttributes','<H'),
 | |
|          ('SearchCount','<H'),
 | |
|          ('Flags','<H'),
 | |
|          ('InformationLevel','<H'),
 | |
|          ('SearchStorageType','<L'),
 | |
|      )
 | |
|      AsciiStructure = (
 | |
|          ('FileName','z'),
 | |
|      )
 | |
|      UnicodeStructure = (
 | |
|          ('FileName','u'),
 | |
|      )
 | |
| 
 | |
| class SMBFindFirst2_Data(Structure):
 | |
|      structure = (
 | |
|          ('GetExtendedAttributesListLength','_-GetExtendedAttributesList', 'self["GetExtendedAttributesListLength"]'),
 | |
|          ('GetExtendedAttributesList',':'),
 | |
|      )
 | |
| 
 | |
| # TRANS2_SET_PATH_INFORMATION
 | |
| class SMBSetPathInformation_Parameters(AsciiOrUnicodeStructure):
 | |
|     commonHdr = (
 | |
|         ('InformationLevel','<H'),
 | |
|         ('Reserved','<L'),
 | |
|     )
 | |
|     AsciiStructure = (
 | |
|         ('FileName','z'),
 | |
|     )
 | |
|     UnicodeStructure = (
 | |
|         ('FileName','u'),
 | |
|     )
 | |
| 
 | |
| class SMBSetPathInformationResponse_Parameters(Structure):
 | |
|     structure = (
 | |
|         ('EaErrorOffset','<H=0'),
 | |
|     )
 | |
| 
 | |
| # TRANS2_SET_FILE_INFORMATION
 | |
| class SMBSetFileInformation_Parameters(Structure):
 | |
|     structure = (
 | |
|         ('FID','<H'),
 | |
|         ('InformationLevel','<H'),
 | |
|         ('Reserved','<H'),
 | |
|     )
 | |
| 
 | |
| class SMBSetFileInformationResponse_Parameters(Structure):
 | |
|     structure = (
 | |
|         ('EaErrorOffset','<H=0'),
 | |
|     )
 | |
| 
 | |
| # TRANS2_QUERY_FILE_INFORMATION
 | |
| class SMBQueryFileInformation_Parameters(Structure):
 | |
|     structure = (
 | |
|         ('FID','<H'),
 | |
|         ('InformationLevel','<H'),
 | |
|     )
 | |
| 
 | |
| class SMBQueryFileInformationResponse_Parameters(Structure):
 | |
|     structure = (
 | |
|         ('EaErrorOffset','<H=0'),
 | |
|     )
 | |
| 
 | |
| class SMBQueryFileInformation_Data(Structure):
 | |
|     structure = (
 | |
|         ('GetExtendedAttributeList',':'),
 | |
|     )
 | |
| 
 | |
| # TRANS2_QUERY_PATH_INFORMATION
 | |
| class SMBQueryPathInformationResponse_Parameters(Structure):
 | |
|     structure = (
 | |
|         ('EaErrorOffset','<H=0'),
 | |
|     )
 | |
| 
 | |
| class SMBQueryPathInformation_Parameters(AsciiOrUnicodeStructure):
 | |
|     commonHdr = (
 | |
|         ('InformationLevel','<H'),
 | |
|         ('Reserved','<L=0'),
 | |
|     )
 | |
|     AsciiStructure = (
 | |
|         ('FileName','z'),
 | |
|     )
 | |
|     UnicodeStructure = (
 | |
|         ('FileName','u'),
 | |
|     )
 | |
| 
 | |
| class SMBQueryPathInformation_Data(Structure):
 | |
|     structure = (
 | |
|         ('GetExtendedAttributeList',':'),
 | |
|     )
 | |
| 
 | |
| 
 | |
| # SMB_QUERY_FILE_EA_INFO
 | |
| class SMBQueryFileEaInfo(Structure):
 | |
|     structure = (
 | |
|         ('EaSize','<L=0'),
 | |
|     )
 | |
| 
 | |
| # SMB_QUERY_FILE_BASIC_INFO
 | |
| class SMBQueryFileBasicInfo(Structure):
 | |
|     structure = (
 | |
|         ('CreationTime','<q'),
 | |
|         ('LastAccessTime','<q'),
 | |
|         ('LastWriteTime','<q'),
 | |
|         ('LastChangeTime','<q'),
 | |
|         ('ExtFileAttributes','<L'),
 | |
|         #('Reserved','<L=0'),
 | |
|     )
 | |
| 
 | |
| # SMB_QUERY_FILE_STANDARD_INFO
 | |
| class SMBQueryFileStandardInfo(Structure):
 | |
|     structure = (
 | |
|         ('AllocationSize','<q'),
 | |
|         ('EndOfFile','<q'),
 | |
|         ('NumberOfLinks','<L=0'),
 | |
|         ('DeletePending','<B=0'),
 | |
|         ('Directory','<B'),
 | |
|     )
 | |
| 
 | |
| # SMB_QUERY_FILE_ALL_INFO
 | |
| class SMBQueryFileAllInfo(Structure):
 | |
|     structure = (
 | |
|         ('CreationTime','<q'),
 | |
|         ('LastAccessTime','<q'),
 | |
|         ('LastWriteTime','<q'),
 | |
|         ('LastChangeTime','<q'),
 | |
|         ('ExtFileAttributes','<L'),
 | |
|         ('Reserved','<L=0'),
 | |
|         ('AllocationSize','<q'),
 | |
|         ('EndOfFile','<q'),
 | |
|         ('NumberOfLinks','<L=0'),
 | |
|         ('DeletePending','<B=0'),
 | |
|         ('Directory','<B'),
 | |
|         ('Reserved','<H=0'),
 | |
|         ('EaSize','<L=0'),
 | |
|         ('FileNameLength','<L-FileName','len(FileName)'),
 | |
|         ('FileName',':'),
 | |
|     )
 | |
| 
 | |
| # \PIPE\LANMAN NetShareEnum
 | |
| class SMBNetShareEnum(Structure):
 | |
|     structure = (
 | |
|         ('RAPOpcode','<H=0'),
 | |
|         ('ParamDesc','z'),
 | |
|         ('DataDesc','z'),
 | |
|         ('InfoLevel','<H'),
 | |
|         ('ReceiveBufferSize','<H'),
 | |
|     )
 | |
| 
 | |
| class SMBNetShareEnumResponse(Structure):
 | |
|     structure = (
 | |
|         ('Status','<H=0'),
 | |
|         ('Convert','<H=0'),
 | |
|         ('EntriesReturned','<H'),
 | |
|         ('EntriesAvailable','<H'),
 | |
|     )
 | |
| 
 | |
| class NetShareInfo1(Structure):
 | |
|     structure = (
 | |
|         ('NetworkName','13s'),
 | |
|         ('Pad','<B=0'),
 | |
|         ('Type','<H=0'),
 | |
|         ('RemarkOffsetLow','<H=0'),
 | |
|         ('RemarkOffsetHigh','<H=0'),
 | |
|     )
 | |
| 
 | |
| # \PIPE\LANMAN NetServerGetInfo
 | |
| class SMBNetServerGetInfoResponse(Structure):
 | |
|     structure = (
 | |
|         ('Status','<H=0'),
 | |
|         ('Convert','<H=0'),
 | |
|         ('TotalBytesAvailable','<H'),
 | |
|     )
 | |
| 
 | |
| class SMBNetServerInfo1(Structure):
 | |
|     # Level 1 Response
 | |
|     structure = (
 | |
|         ('ServerName','16s'),
 | |
|         ('MajorVersion','B=5'),
 | |
|         ('MinorVersion','B=0'),
 | |
|         ('ServerType','<L=3'),
 | |
|         ('ServerCommentLow','<H=0'),
 | |
|         ('ServerCommentHigh','<H=0'),
 | |
|     )
 | |
| 
 | |
| # \PIPE\LANMAN NetShareGetInfo
 | |
| class SMBNetShareGetInfo(Structure):
 | |
|     structure = (
 | |
|         ('RAPOpcode','<H=0'),
 | |
|         ('ParamDesc','z'),
 | |
|         ('DataDesc','z'),
 | |
|         ('ShareName','z'),
 | |
|         ('InfoLevel','<H'),
 | |
|         ('ReceiveBufferSize','<H'),
 | |
|     )
 | |
| 
 | |
| class SMBNetShareGetInfoResponse(Structure):
 | |
|     structure = (
 | |
|         ('Status','<H=0'),
 | |
|         ('Convert','<H=0'),
 | |
|         ('TotalBytesAvailable','<H'),
 | |
|     )
 | |
| 
 | |
| ############# Security Features
 | |
| class SecurityFeatures(Structure):
 | |
|     structure = (
 | |
|         ('Key','<L=0'),
 | |
|         ('CID','<H=0'),
 | |
|         ('SequenceNumber','<H=0'),
 | |
|     )
 | |
| 
 | |
| ############# SMB_COM_QUERY_INFORMATION2 (0x23)
 | |
| class SMBQueryInformation2_Parameters(Structure):
 | |
|     structure = (
 | |
|         ('Fid','<H'),
 | |
|     )
 | |
| 
 | |
| class SMBQueryInformation2Response_Parameters(Structure):
 | |
|     structure = (
 | |
|         ('CreateDate','<H'),
 | |
|         ('CreationTime','<H'),
 | |
|         ('LastAccessDate','<H'),
 | |
|         ('LastAccessTime','<H'),
 | |
|         ('LastWriteDate','<H'),
 | |
|         ('LastWriteTime','<H'),
 | |
|         ('FileDataSize','<L'),
 | |
|         ('FileAllocationSize','<L'),
 | |
|         ('FileAttributes','<L'),
 | |
|     )
 | |
| 
 | |
| 
 | |
| 
 | |
| ############# SMB_COM_SESSION_SETUP_ANDX (0x73)
 | |
| class SMBSessionSetupAndX_Parameters(SMBAndXCommand_Parameters):
 | |
|     structure = (
 | |
|         ('MaxBuffer','<H'),
 | |
|         ('MaxMpxCount','<H'),
 | |
|         ('VCNumber','<H'),
 | |
|         ('SessionKey','<L'),
 | |
|         ('AnsiPwdLength','<H'),
 | |
|         ('UnicodePwdLength','<H'),
 | |
|         ('_reserved','<L=0'),
 | |
|         ('Capabilities','<L'),
 | |
|     )
 | |
| 
 | |
| class SMBSessionSetupAndX_Extended_Parameters(SMBAndXCommand_Parameters):
 | |
|     structure = (
 | |
|         ('MaxBufferSize','<H'),
 | |
|         ('MaxMpxCount','<H'),
 | |
|         ('VcNumber','<H'),
 | |
|         ('SessionKey','<L'),
 | |
|         ('SecurityBlobLength','<H'),
 | |
|         ('Reserved','<L=0'),
 | |
|         ('Capabilities','<L'),
 | |
|     )
 | |
| 
 | |
| class SMBSessionSetupAndX_Data(AsciiOrUnicodeStructure):
 | |
|     AsciiStructure = (
 | |
|         ('AnsiPwdLength','_-AnsiPwd','self["AnsiPwdLength"]'),
 | |
|         ('UnicodePwdLength','_-UnicodePwd','self["UnicodePwdLength"]'),
 | |
|         ('AnsiPwd',':=""'),
 | |
|         ('UnicodePwd',':=""'),
 | |
|         ('Account','z=""'),
 | |
|         ('PrimaryDomain','z=""'),
 | |
|         ('NativeOS','z=""'),
 | |
|         ('NativeLanMan','z=""'),
 | |
|     )
 | |
| 
 | |
|     UnicodeStructure = (
 | |
|         ('AnsiPwdLength','_-AnsiPwd','self["AnsiPwdLength"]'),
 | |
|         ('UnicodePwdLength','_-UnicodePwd','self["UnicodePwdLength"]'),
 | |
|         ('AnsiPwd',':=""'),
 | |
|         ('UnicodePwd',':=""'),
 | |
|         ('Account','u=""'),
 | |
|         ('PrimaryDomain','u=""'),
 | |
|         ('NativeOS','u=""'),
 | |
|         ('NativeLanMan','u=""'),
 | |
|     )
 | |
| 
 | |
| class SMBSessionSetupAndX_Extended_Data(AsciiOrUnicodeStructure):
 | |
|     AsciiStructure = (
 | |
|         ('SecurityBlobLength','_-SecurityBlob','self["SecurityBlobLength"]'),
 | |
|         ('SecurityBlob',':'),
 | |
|         ('NativeOS','z=""'),
 | |
|         ('NativeLanMan','z=""'),
 | |
|     )
 | |
| 
 | |
|     UnicodeStructure = (
 | |
|         ('SecurityBlobLength','_-SecurityBlob','self["SecurityBlobLength"]'),
 | |
|         ('SecurityBlob',':'),
 | |
|         ('NativeOS','u=""'),
 | |
|         ('NativeLanMan','u=""'),
 | |
|     )
 | |
| 
 | |
| class SMBSessionSetupAndXResponse_Parameters(SMBAndXCommand_Parameters):
 | |
|     structure = (
 | |
|         ('Action','<H'),
 | |
|     )
 | |
| 
 | |
| class SMBSessionSetupAndX_Extended_Response_Parameters(SMBAndXCommand_Parameters):
 | |
|     structure = (
 | |
|         ('Action','<H=0'),
 | |
|         ('SecurityBlobLength','<H'),
 | |
|     )
 | |
| 
 | |
| class SMBSessionSetupAndXResponse_Data(AsciiOrUnicodeStructure):
 | |
|     AsciiStructure = (
 | |
|         ('NativeOS','z=""'),
 | |
|         ('NativeLanMan','z=""'),
 | |
|         ('PrimaryDomain','z=""'),
 | |
|     )
 | |
| 
 | |
|     UnicodeStructure = (
 | |
|         ('NativeOS','u=""'),
 | |
|         ('NativeLanMan','u=""'),
 | |
|         ('PrimaryDomain','u=""'),
 | |
|     )
 | |
| 
 | |
| class SMBSessionSetupAndX_Extended_Response_Data(AsciiOrUnicodeStructure):
 | |
|     AsciiStructure = (
 | |
|         ('SecurityBlobLength','_-SecurityBlob','self["SecurityBlobLength"]'),
 | |
|         ('SecurityBlob',':'),
 | |
|         ('NativeOS','z=""'),
 | |
|         ('NativeLanMan','z=""'),
 | |
|     )
 | |
| 
 | |
|     UnicodeStructure = (
 | |
|         ('SecurityBlobLength','_-SecurityBlob','self["SecurityBlobLength"]'),
 | |
|         ('SecurityBlob',':'),
 | |
|         ('NativeOS','u=""'),
 | |
|         ('NativeLanMan','u=""'),
 | |
|     )
 | |
| 
 | |
| ############# SMB_COM_TREE_CONNECT (0x70)
 | |
| class SMBTreeConnect_Parameters(SMBCommand_Parameters):
 | |
|     structure = (
 | |
|     )
 | |
| 
 | |
| class SMBTreeConnect_Data(SMBCommand_Parameters):
 | |
|     structure = (
 | |
|         ('PathFormat','"\x04'),
 | |
|         ('Path','z'),
 | |
|         ('PasswordFormat','"\x04'),
 | |
|         ('Password','z'),
 | |
|         ('ServiceFormat','"\x04'),
 | |
|         ('Service','z'),
 | |
|     )
 | |
| 
 | |
| ############# SMB_COM_TREE_CONNECT_ANDX (0x75)
 | |
| class SMBTreeConnectAndX_Parameters(SMBAndXCommand_Parameters):
 | |
|     structure = (
 | |
|         ('Flags','<H=0'),
 | |
|         ('PasswordLength','<H'),
 | |
|     )
 | |
| 
 | |
| class SMBTreeConnectAndXResponse_Parameters(SMBAndXCommand_Parameters):
 | |
|     structure = (
 | |
|         ('OptionalSupport','<H=0'),
 | |
|     )
 | |
| 
 | |
| class SMBTreeConnectAndXExtendedResponse_Parameters(SMBAndXCommand_Parameters):
 | |
|     structure = (
 | |
|         ('OptionalSupport','<H=1'),
 | |
|         ('MaximalShareAccessRights','<L=0x1fffff'),
 | |
|         ('GuestMaximalShareAccessRights','<L=0x1fffff'),
 | |
|     )
 | |
| 
 | |
| class SMBTreeConnectAndX_Data(AsciiOrUnicodeStructure):
 | |
|     AsciiStructure = (
 | |
|         ('_PasswordLength','_-Password','self["_PasswordLength"]'),
 | |
|         ('Password',':'),
 | |
|         ('Path','z'),
 | |
|         ('Service','z'),
 | |
|     )
 | |
| 
 | |
|     UnicodeStructure = (
 | |
|         ('_PasswordLength','_-Password','self["_PasswordLength"] if self["_PasswordLength"] > 0 else 1'),
 | |
|         ('Password',':'),
 | |
|         ('Path','u'),
 | |
|         ('Service','z'),
 | |
|     )
 | |
| 
 | |
| class SMBTreeConnectAndXResponse_Data(AsciiOrUnicodeStructure):
 | |
|     AsciiStructure = (
 | |
|         ('Service','z'),
 | |
|         ('PadLen','_-Pad','self["PadLen"]'),
 | |
|         ('Pad',':=""'),
 | |
|         ('NativeFileSystem','z'),
 | |
|     )
 | |
|     UnicodeStructure = (
 | |
|         ('Service','z'),
 | |
|         ('PadLen','_-Pad','self["PadLen"]'),
 | |
|         ('Pad',':=""'),
 | |
|         ('NativeFileSystem','u'),
 | |
|     )
 | |
| 
 | |
| ############# SMB_COM_NT_CREATE_ANDX (0xA2)
 | |
| class SMBNtCreateAndX_Parameters(SMBAndXCommand_Parameters):
 | |
|     structure = (
 | |
|         ('_reserved', 'B=0'),
 | |
|         ('FileNameLength','<H'),     # NameLength
 | |
|         ('CreateFlags','<L'),        # Flags
 | |
|         ('RootFid','<L=0'),          # RootDirectoryFID
 | |
|         ('AccessMask','<L'),         # DesiredAccess
 | |
|         ('AllocationSizeLo','<L=0'), # AllocationSize
 | |
|         ('AllocationSizeHi','<L=0'),
 | |
|         ('FileAttributes','<L=0'),   # ExtFileAttributes
 | |
|         ('ShareAccess','<L=3'),      #
 | |
|         ('Disposition','<L=1'),      # CreateDisposition
 | |
|         ('CreateOptions','<L'),      # CreateOptions
 | |
|         ('Impersonation','<L=2'),
 | |
|         ('SecurityFlags','B=3'),
 | |
|     )
 | |
| 
 | |
| class SMBNtCreateAndXResponse_Parameters(SMBAndXCommand_Parameters):
 | |
|     # 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?
 | |
|     structure = (
 | |
|         ('OplockLevel', 'B=0'),
 | |
|         ('Fid','<H'),
 | |
|         ('CreateAction','<L'),
 | |
|         ('CreateTime','<q=0'),
 | |
|         ('LastAccessTime','<q=0'),
 | |
|         ('LastWriteTime','<q=0'),
 | |
|         ('LastChangeTime','<q=0'),
 | |
|         ('FileAttributes','<L=0x80'),
 | |
|         ('AllocationSize','<q=0'),
 | |
|         ('EndOfFile','<q=0'),
 | |
|         ('FileType','<H=0'),
 | |
|         ('IPCState','<H=0'),
 | |
|         ('IsDirectory','B'),
 | |
|     )
 | |
| 
 | |
| class SMBNtCreateAndXExtendedResponse_Parameters(SMBAndXCommand_Parameters):
 | |
|     # [MS-SMB] Extended response description
 | |
|     structure = (
 | |
|         ('OplockLevel', 'B=0'),
 | |
|         ('Fid','<H'),
 | |
|         ('CreateAction','<L'),
 | |
|         ('CreateTime','<q=0'),
 | |
|         ('LastAccessTime','<q=0'),
 | |
|         ('LastWriteTime','<q=0'),
 | |
|         ('LastChangeTime','<q=0'),
 | |
|         ('FileAttributes','<L=0x80'),
 | |
|         ('AllocationSize','<q=0'),
 | |
|         ('EndOfFile','<q=0'),
 | |
|         ('FileType','<H=0'),
 | |
|         ('IPCState','<H=0'),
 | |
|         ('IsDirectory','B'),
 | |
|         ('VolumeGUID','16s'),
 | |
|         ('FileIdLow','<L=0'),
 | |
|         ('FileIdHigh','<L=0'),
 | |
|         ('MaximalAccessRights','<L=0x12019b'),
 | |
|         ('GuestMaximalAccessRights','<L=0x120089'),
 | |
|     )
 | |
| 
 | |
| class SMBNtCreateAndX_Data(AsciiOrUnicodeStructure):
 | |
|     AsciiStructure = (
 | |
|         ('FileName','z'),
 | |
|     )
 | |
|     UnicodeStructure = (
 | |
|         ('Pad','B'),
 | |
|         ('FileName','u'),
 | |
|     )
 | |
| 
 | |
| ############# SMB_COM_OPEN_ANDX (0xD2)
 | |
| class SMBOpenAndX_Parameters(SMBAndXCommand_Parameters):
 | |
|     structure = (
 | |
|         ('Flags','<H=0'),
 | |
|         ('DesiredAccess','<H=0'),
 | |
|         ('SearchAttributes','<H=0'),
 | |
|         ('FileAttributes','<H=0'),
 | |
|         ('CreationTime','<L=0'),
 | |
|         ('OpenMode','<H=1'),        # SMB_O_OPEN = 1
 | |
|         ('AllocationSize','<L=0'),
 | |
|         ('Reserved','8s=""'),
 | |
|     )
 | |
| 
 | |
| class SMBOpenAndX_Data(SMBNtCreateAndX_Data):
 | |
|     pass
 | |
| 
 | |
| class SMBOpenAndXResponse_Parameters(SMBAndXCommand_Parameters):
 | |
|     structure = (
 | |
|         ('Fid','<H=0'),
 | |
|         ('FileAttributes','<H=0'),
 | |
|         ('LastWriten','<L=0'),
 | |
|         ('FileSize','<L=0'),
 | |
|         ('GrantedAccess','<H=0'),
 | |
|         ('FileType','<H=0'),
 | |
|         ('IPCState','<H=0'),
 | |
|         ('Action','<H=0'),
 | |
|         ('ServerFid','<L=0'),
 | |
|         ('_reserved','<H=0'),
 | |
|     )
 | |
| 
 | |
| ############# SMB_COM_WRITE (0x0B)
 | |
| class SMBWrite_Parameters(SMBCommand_Parameters):
 | |
|     structure = (
 | |
|         ('Fid','<H'),
 | |
|         ('Count','<H'),
 | |
|         ('Offset','<L'),
 | |
|         ('Remaining','<H'),
 | |
|     )
 | |
| 
 | |
| class SMBWriteResponse_Parameters(SMBCommand_Parameters):
 | |
|     structure = (
 | |
|         ('Count','<H'),
 | |
|     )
 | |
| 
 | |
| class SMBWrite_Data(Structure):
 | |
|     structure = (
 | |
|         ('BufferFormat','<B=1'),
 | |
|         ('DataLength','<H-Data'),
 | |
|         ('Data',':'),
 | |
|     )
 | |
| 
 | |
| 
 | |
| ############# SMB_COM_WRITE_ANDX (0x2F)
 | |
| class SMBWriteAndX_Parameters(SMBAndXCommand_Parameters):
 | |
|     structure = (
 | |
|         ('Fid','<H=0'),
 | |
|         ('Offset','<L=0'),
 | |
|         ('_reserved','<L=0xff'),
 | |
|         ('WriteMode','<H=8'),
 | |
|         ('Remaining','<H=0'),
 | |
|         ('DataLength_Hi','<H=0'),
 | |
|         ('DataLength','<H=0'),
 | |
|         ('DataOffset','<H=0'),
 | |
|         ('HighOffset','<L=0'),
 | |
|     )
 | |
| 
 | |
| class SMBWriteAndX_Data_Short(Structure):
 | |
|      structure = (
 | |
|          ('_PadLen','_-Pad','self["DataOffset"] - 59'),
 | |
|          ('Pad',':'),
 | |
|          #('Pad','<B=0'),
 | |
|          ('DataLength','_-Data','self["DataLength"]'),
 | |
|          ('Data',':'),
 | |
|      )
 | |
| 
 | |
| class SMBWriteAndX_Data(Structure):
 | |
|      structure = (
 | |
|          ('_PadLen','_-Pad','self["DataOffset"] - 63'),
 | |
|          ('Pad',':'),
 | |
|          #('Pad','<B=0'),
 | |
|          ('DataLength','_-Data','self["DataLength"]'),
 | |
|          ('Data',':'),
 | |
|      )
 | |
| 
 | |
| 
 | |
| class SMBWriteAndX_Parameters_Short(SMBAndXCommand_Parameters):
 | |
|     structure = (
 | |
|         ('Fid','<H'),
 | |
|         ('Offset','<L'),
 | |
|         ('_reserved','<L=0xff'),
 | |
|         ('WriteMode','<H=8'),
 | |
|         ('Remaining','<H'),
 | |
|         ('DataLength_Hi','<H=0'),
 | |
|         ('DataLength','<H'),
 | |
|         ('DataOffset','<H=0'),
 | |
|     )
 | |
| 
 | |
| class SMBWriteAndXResponse_Parameters(SMBAndXCommand_Parameters):
 | |
|     structure = (
 | |
|         ('Count','<H'),
 | |
|         ('Available','<H'),
 | |
|         ('Reserved','<L=0'),
 | |
|     )
 | |
| 
 | |
| ############# SMB_COM_WRITE_RAW (0x1D)
 | |
| class SMBWriteRaw_Parameters(SMBCommand_Parameters):
 | |
|     structure = (
 | |
|         ('Fid','<H'),
 | |
|         ('Count','<H'),
 | |
|         ('_reserved','<H=0'),
 | |
|         ('Offset','<L'),
 | |
|         ('Timeout','<L=0'),
 | |
|         ('WriteMode','<H=0'),
 | |
|         ('_reserved2','<L=0'),
 | |
|         ('DataLength','<H'),
 | |
|         ('DataOffset','<H=0'),
 | |
|     )
 | |
| 
 | |
| ############# SMB_COM_READ (0x0A)
 | |
| class SMBRead_Parameters(SMBCommand_Parameters):
 | |
|     structure = (
 | |
|         ('Fid','<H'),
 | |
|         ('Count','<H'),
 | |
|         ('Offset','<L'),
 | |
|         ('Remaining','<H=Count'),
 | |
|     )
 | |
| 
 | |
| class SMBReadResponse_Parameters(Structure):
 | |
|     structure = (
 | |
|         ('Count','<H=0'),
 | |
|         ('_reserved','8s=""'),
 | |
|     )
 | |
| 
 | |
| class SMBReadResponse_Data(Structure):
 | |
|     structure = (
 | |
|         ('BufferFormat','<B=0x1'),
 | |
|         ('DataLength','<H-Data'),
 | |
|         ('Data',':'),
 | |
|     )
 | |
| 
 | |
| ############# SMB_COM_READ_RAW (0x1A)
 | |
| class SMBReadRaw_Parameters(SMBCommand_Parameters):
 | |
|     structure = (
 | |
|         ('Fid','<H'),
 | |
|         ('Offset','<L'),
 | |
|         ('MaxCount','<H'),
 | |
|         ('MinCount','<H=MaxCount'),
 | |
|         ('Timeout','<L=0'),
 | |
|         ('_reserved','<H=0'),
 | |
|     )
 | |
| 
 | |
| ############# SMB_COM_NT_TRANSACT  (0xA0)
 | |
| class SMBNTTransaction_Parameters(SMBCommand_Parameters):
 | |
|     structure = (
 | |
|         ('MaxSetupCount','<B=0'),
 | |
|         ('Reserved1','<H=0'),
 | |
|         ('TotalParameterCount','<L'),
 | |
|         ('TotalDataCount','<L'),
 | |
|         ('MaxParameterCount','<L=1024'),
 | |
|         ('MaxDataCount','<L=65504'),
 | |
|         ('ParameterCount','<L'),
 | |
|         ('ParameterOffset','<L'),
 | |
|         ('DataCount','<L'),
 | |
|         ('DataOffset','<L'),
 | |
|         ('SetupCount','<B=len(Setup)/2'),
 | |
|         ('Function','<H=0'),
 | |
|         ('SetupLength','_-Setup','SetupCount*2'),
 | |
|         ('Setup',':'),
 | |
|     )
 | |
| 
 | |
| class SMBNTTransactionResponse_Parameters(SMBCommand_Parameters):
 | |
|     structure = (
 | |
|         ('Reserved1','3s=""'),
 | |
|         ('TotalParameterCount','<L'),
 | |
|         ('TotalDataCount','<L'),
 | |
|         ('ParameterCount','<L'),
 | |
|         ('ParameterOffset','<L'),
 | |
|         ('ParameterDisplacement','<L=0'),
 | |
|         ('DataCount','<L'),
 | |
|         ('DataOffset','<L'),
 | |
|         ('DataDisplacement','<L=0'),
 | |
|         ('SetupCount','<B=0'),
 | |
|         ('SetupLength','_-Setup','SetupCount*2'),
 | |
|         ('Setup',':'),
 | |
|     )
 | |
| 
 | |
| class SMBNTTransaction_Data(Structure):
 | |
|     structure = (
 | |
|         ('Pad1Length','_-Pad1','self["Pad1Length"]'),
 | |
|         ('Pad1',':'),
 | |
|         ('NT_Trans_ParametersLength','_-NT_Trans_Parameters','self["NT_Trans_ParametersLength"]'),
 | |
|         ('NT_Trans_Parameters',':'),
 | |
|         ('Pad2Length','_-Pad2','self["Pad2Length"]'),
 | |
|         ('Pad2',':'),
 | |
|         ('NT_Trans_DataLength','_-NT_Trans_Data','self["NT_Trans_DataLength"]'),
 | |
|         ('NT_Trans_Data',':'),
 | |
|     )
 | |
| 
 | |
| class SMBNTTransactionResponse_Data(Structure):
 | |
|     structure = (
 | |
|         ('Pad1Length','_-Pad1','self["Pad1Length"]'),
 | |
|         ('Pad1',':'),
 | |
|         ('Trans_ParametersLength','_-Trans_Parameters','self["Trans_ParametersLength"]'),
 | |
|         ('Trans_Parameters',':'),
 | |
|         ('Pad2Length','_-Pad2','self["Pad2Length"]'),
 | |
|         ('Pad2',':'),
 | |
|         ('Trans_DataLength','_-Trans_Data','self["Trans_DataLength"]'),
 | |
|         ('Trans_Data',':'),
 | |
|     )
 | |
| 
 | |
| 
 | |
| ############# SMB_COM_TRANSACTION2_SECONDARY (0x33)
 | |
| class SMBTransaction2Secondary_Parameters(SMBCommand_Parameters):
 | |
|     structure = (
 | |
|         ('TotalParameterCount','<H'),
 | |
|         ('TotalDataCount','<H'),
 | |
|         ('ParameterCount','<H'),
 | |
|         ('ParameterOffset','<H'),
 | |
|         ('DataCount','<H'),
 | |
|         ('DataOffset','<H'),
 | |
|         ('DataDisplacement','<H=0'),
 | |
|         ('FID','<H'),
 | |
|     )
 | |
| 
 | |
| class SMBTransaction2Secondary_Data(Structure):
 | |
|     structure = (
 | |
|         ('Pad1Length','_-Pad1','self["Pad1Length"]'),
 | |
|         ('Pad1',':'),
 | |
|         ('Trans_ParametersLength','_-Trans_Parameters','self["Trans_ParametersLength"]'),
 | |
|         ('Trans_Parameters',':'),
 | |
|         ('Pad2Length','_-Pad2','self["Pad2Length"]'),
 | |
|         ('Pad2',':'),
 | |
|         ('Trans_DataLength','_-Trans_Data','self["Trans_DataLength"]'),
 | |
|         ('Trans_Data',':'),
 | |
|     )
 | |
| 
 | |
| 
 | |
| ############# SMB_COM_TRANSACTION2 (0x32)
 | |
| 
 | |
| class SMBTransaction2_Parameters(SMBCommand_Parameters):
 | |
|     structure = (
 | |
|         ('TotalParameterCount','<H'),
 | |
|         ('TotalDataCount','<H'),
 | |
|         ('MaxParameterCount','<H=1024'),
 | |
|         ('MaxDataCount','<H=65504'),
 | |
|         ('MaxSetupCount','<B=0'),
 | |
|         ('Reserved1','<B=0'),
 | |
|         ('Flags','<H=0'),
 | |
|         ('Timeout','<L=0'),
 | |
|         ('Reserved2','<H=0'),
 | |
|         ('ParameterCount','<H'),
 | |
|         ('ParameterOffset','<H'),
 | |
|         ('DataCount','<H'),
 | |
|         ('DataOffset','<H'),
 | |
|         ('SetupCount','<B=len(Setup)/2'),
 | |
|         ('Reserved3','<B=0'),
 | |
|         ('SetupLength','_-Setup','SetupCount*2'),
 | |
|         ('Setup',':'),
 | |
|     )
 | |
| 
 | |
| class SMBTransaction2Response_Parameters(SMBCommand_Parameters):
 | |
|     structure = (
 | |
|         ('TotalParameterCount','<H'),
 | |
|         ('TotalDataCount','<H'),
 | |
|         ('Reserved1','<H=0'),
 | |
|         ('ParameterCount','<H'),
 | |
|         ('ParameterOffset','<H'),
 | |
|         ('ParameterDisplacement','<H=0'),
 | |
|         ('DataCount','<H'),
 | |
|         ('DataOffset','<H'),
 | |
|         ('DataDisplacement','<H=0'),
 | |
|         ('SetupCount','<B=0'),
 | |
|         ('Reserved2','<B=0'),
 | |
|         ('SetupLength','_-Setup','SetupCount*2'),
 | |
|         ('Setup',':'),
 | |
|     )
 | |
| 
 | |
| class SMBTransaction2_Data(Structure):
 | |
|     structure = (
 | |
| #        ('NameLength','_-Name','1'),
 | |
| #        ('Name',':'),
 | |
|         ('Pad1Length','_-Pad1','self["Pad1Length"]'),
 | |
|         ('Pad1',':'),
 | |
|         ('Trans_ParametersLength','_-Trans_Parameters','self["Trans_ParametersLength"]'),
 | |
|         ('Trans_Parameters',':'),
 | |
|         ('Pad2Length','_-Pad2','self["Pad2Length"]'),
 | |
|         ('Pad2',':'),
 | |
|         ('Trans_DataLength','_-Trans_Data','self["Trans_DataLength"]'),
 | |
|         ('Trans_Data',':'),
 | |
|     )
 | |
| 
 | |
| class SMBTransaction2Response_Data(Structure):
 | |
|     structure = (
 | |
|         ('Pad1Length','_-Pad1','self["Pad1Length"]'),
 | |
|         ('Pad1',':'),
 | |
|         ('Trans_ParametersLength','_-Trans_Parameters','self["Trans_ParametersLength"]'),
 | |
|         ('Trans_Parameters',':'),
 | |
|         ('Pad2Length','_-Pad2','self["Pad2Length"]'),
 | |
|         ('Pad2',':'),
 | |
|         ('Trans_DataLength','_-Trans_Data','self["Trans_DataLength"]'),
 | |
|         ('Trans_Data',':'),
 | |
|     )
 | |
| 
 | |
| ############# SMB_COM_QUERY_INFORMATION (0x08)
 | |
| 
 | |
| class SMBQueryInformation_Data(AsciiOrUnicodeStructure):
 | |
|     AsciiStructure = (
 | |
|         ('BufferFormat','B=4'),
 | |
|         ('FileName','z'),
 | |
|     )
 | |
|     UnicodeStructure = (
 | |
|         ('BufferFormat','B=4'),
 | |
|         ('FileName','u'),
 | |
|     )
 | |
| 
 | |
| 
 | |
| class SMBQueryInformationResponse_Parameters(Structure):
 | |
|     structure = (
 | |
|         ('FileAttributes','<H'),
 | |
|         ('LastWriteTime','<L'),
 | |
|         ('FileSize','<L'),
 | |
|         ('Reserved','"0123456789'),
 | |
|     )
 | |
| 
 | |
| ############# SMB_COM_TRANSACTION (0x25)
 | |
| class SMBTransaction_Parameters(SMBCommand_Parameters):
 | |
|     structure = (
 | |
|         ('TotalParameterCount','<H'),
 | |
|         ('TotalDataCount','<H'),
 | |
|         ('MaxParameterCount','<H=1024'),
 | |
|         ('MaxDataCount','<H=65504'),
 | |
|         ('MaxSetupCount','<B=0'),
 | |
|         ('Reserved1','<B=0'),
 | |
|         ('Flags','<H=0'),
 | |
|         ('Timeout','<L=0'),
 | |
|         ('Reserved2','<H=0'),
 | |
|         ('ParameterCount','<H'),
 | |
|         ('ParameterOffset','<H'),
 | |
|         ('DataCount','<H'),
 | |
|         ('DataOffset','<H'),
 | |
|         ('SetupCount','<B=len(Setup)/2'),
 | |
|         ('Reserved3','<B=0'),
 | |
|         ('SetupLength','_-Setup','SetupCount*2'),
 | |
|         ('Setup',':'),
 | |
|     )
 | |
| 
 | |
| class SMBTransactionResponse_Parameters(SMBCommand_Parameters):
 | |
|     structure = (
 | |
|         ('TotalParameterCount','<H'),
 | |
|         ('TotalDataCount','<H'),
 | |
|         ('Reserved1','<H=0'),
 | |
|         ('ParameterCount','<H'),
 | |
|         ('ParameterOffset','<H'),
 | |
|         ('ParameterDisplacement','<H=0'),
 | |
|         ('DataCount','<H'),
 | |
|         ('DataOffset','<H'),
 | |
|         ('DataDisplacement','<H=0'),
 | |
|         ('SetupCount','<B'),
 | |
|         ('Reserved2','<B=0'),
 | |
|         ('SetupLength','_-Setup','SetupCount*2'),
 | |
|         ('Setup',':'),
 | |
|     )
 | |
| 
 | |
| # TODO: We should merge these both. But this will require fixing
 | |
| # the instances where this structure is used on the client side
 | |
| class SMBTransaction_SData(AsciiOrUnicodeStructure):
 | |
|     AsciiStructure = (
 | |
|         ('Name','z'),
 | |
|         ('Trans_ParametersLength','_-Trans_Parameters'),
 | |
|         ('Trans_Parameters',':'),
 | |
|         ('Trans_DataLength','_-Trans_Data'),
 | |
|         ('Trans_Data',':'),
 | |
|     )
 | |
|     UnicodeStructure = (
 | |
|         ('Pad','B'),
 | |
|         ('Name','u'),
 | |
|         ('Trans_ParametersLength','_-Trans_Parameters'),
 | |
|         ('Trans_Parameters',':'),
 | |
|         ('Trans_DataLength','_-Trans_Data'),
 | |
|         ('Trans_Data',':'),
 | |
|     )
 | |
| 
 | |
| class SMBTransaction_Data(Structure):
 | |
|     structure = (
 | |
|         ('NameLength','_-Name'),
 | |
|         ('Name',':'),
 | |
|         ('Trans_ParametersLength','_-Trans_Parameters'),
 | |
|         ('Trans_Parameters',':'),
 | |
|         ('Trans_DataLength','_-Trans_Data'),
 | |
|         ('Trans_Data',':'),
 | |
|     )
 | |
| 
 | |
| class SMBTransactionResponse_Data(Structure):
 | |
|     structure = (
 | |
|         ('Trans_ParametersLength','_-Trans_Parameters'),
 | |
|         ('Trans_Parameters',':'),
 | |
|         ('Trans_DataLength','_-Trans_Data'),
 | |
|         ('Trans_Data',':'),
 | |
|     )
 | |
| 
 | |
| ############# SMB_COM_READ_ANDX (0x2E)
 | |
| class SMBReadAndX_Parameters(SMBAndXCommand_Parameters):
 | |
|     structure = (
 | |
|         ('Fid','<H'),
 | |
|         ('Offset','<L'),
 | |
|         ('MaxCount','<H'),
 | |
|         ('MinCount','<H=MaxCount'),
 | |
|         ('_reserved','<L=0x0'),
 | |
|         ('Remaining','<H=MaxCount'),
 | |
|         ('HighOffset','<L=0'),
 | |
|     )
 | |
| 
 | |
| class SMBReadAndX_Parameters2(SMBAndXCommand_Parameters):
 | |
|     structure = (
 | |
|         ('Fid','<H'),
 | |
|         ('Offset','<L'),
 | |
|         ('MaxCount','<H'),
 | |
|         ('MinCount','<H=MaxCount'),
 | |
|         ('_reserved','<L=0xffffffff'),
 | |
|         ('Remaining','<H=MaxCount'),
 | |
|     )
 | |
| 
 | |
| class SMBReadAndXResponse_Parameters(SMBAndXCommand_Parameters):
 | |
|     structure = (
 | |
|         ('Remaining','<H=0'),
 | |
|         ('DataMode','<H=0'),
 | |
|         ('_reserved','<H=0'),
 | |
|         ('DataCount','<H'),
 | |
|         ('DataOffset','<H'),
 | |
|         ('DataCount_Hi','<L'),
 | |
|         ('_reserved2','6s=""'),
 | |
|     )
 | |
| 
 | |
| ############# SMB_COM_ECHO (0x2B)
 | |
| class SMBEcho_Data(Structure):
 | |
|     structure = (
 | |
|         ('Data',':'),
 | |
|     )
 | |
| 
 | |
| class SMBEcho_Parameters(Structure):
 | |
|     structure = (
 | |
|         ('EchoCount','<H'),
 | |
|     )
 | |
| 
 | |
| class SMBEchoResponse_Data(Structure):
 | |
|     structure = (
 | |
|         ('Data',':'),
 | |
|     )
 | |
| 
 | |
| class SMBEchoResponse_Parameters(Structure):
 | |
|     structure = (
 | |
|         ('SequenceNumber','<H=1'),
 | |
|     )
 | |
| 
 | |
| ############# SMB_COM_QUERY_INFORMATION_DISK (0x80)
 | |
| class SMBQueryInformationDiskResponse_Parameters(Structure):
 | |
|     structure = (
 | |
|         ('TotalUnits','<H'),
 | |
|         ('BlocksPerUnit','<H'),
 | |
|         ('BlockSize','<H'),
 | |
|         ('FreeUnits','<H'),
 | |
|         ('Reserved','<H=0'),
 | |
|     )
 | |
| 
 | |
| 
 | |
| ############# SMB_COM_LOGOFF_ANDX (0x74)
 | |
| class SMBLogOffAndX(SMBAndXCommand_Parameters):
 | |
|     strucure = ()
 | |
| 
 | |
| ############# SMB_COM_CLOSE (0x04)
 | |
| class SMBClose_Parameters(SMBCommand_Parameters):
 | |
|    structure = (
 | |
|         ('FID','<H'),
 | |
|         ('Time','<L=0'),
 | |
|    )
 | |
| 
 | |
| ############# SMB_COM_FLUSH (0x05)
 | |
| class SMBFlush_Parameters(SMBCommand_Parameters):
 | |
|    structure = (
 | |
|         ('FID','<H'),
 | |
|    )
 | |
| 
 | |
| ############# SMB_COM_CREATE_DIRECTORY (0x00)
 | |
| class SMBCreateDirectory_Data(AsciiOrUnicodeStructure):
 | |
|     AsciiStructure = (
 | |
|         ('BufferFormat','<B=4'),
 | |
|         ('DirectoryName','z'),
 | |
|     )
 | |
|     UnicodeStructure = (
 | |
|         ('BufferFormat','<B=4'),
 | |
|         ('DirectoryName','u'),
 | |
|     )
 | |
| 
 | |
| ############# SMB_COM_DELETE (0x06)
 | |
| class SMBDelete_Data(AsciiOrUnicodeStructure):
 | |
|     AsciiStructure = (
 | |
|         ('BufferFormat','<B=4'),
 | |
|         ('FileName','z'),
 | |
|     )
 | |
|     UnicodeStructure = (
 | |
|         ('BufferFormat','<B=4'),
 | |
|         ('FileName','u'),
 | |
|     )
 | |
| 
 | |
| class SMBDelete_Parameters(Structure):
 | |
|     structure = (
 | |
|         ('SearchAttributes','<H'),
 | |
|     )
 | |
| 
 | |
| ############# SMB_COM_DELETE_DIRECTORY (0x01)
 | |
| class SMBDeleteDirectory_Data(AsciiOrUnicodeStructure):
 | |
|     AsciiStructure = (
 | |
|         ('BufferFormat','<B=4'),
 | |
|         ('DirectoryName','z'),
 | |
|     )
 | |
|     UnicodeStructure = (
 | |
|         ('BufferFormat','<B=4'),
 | |
|         ('DirectoryName','u'),
 | |
|     )
 | |
| 
 | |
| ############# SMB_COM_CHECK_DIRECTORY (0x10)
 | |
| class SMBCheckDirectory_Data(AsciiOrUnicodeStructure):
 | |
|     AsciiStructure = (
 | |
|         ('BufferFormat','<B=4'),
 | |
|         ('DirectoryName','z'),
 | |
|     )
 | |
|     UnicodeStructure = (
 | |
|         ('BufferFormat','<B=4'),
 | |
|         ('DirectoryName','u'),
 | |
|     )
 | |
| 
 | |
| ############# SMB_COM_RENAME (0x07)
 | |
| class SMBRename_Parameters(SMBCommand_Parameters):
 | |
|     structure = (
 | |
|         ('SearchAttributes','<H'),
 | |
|     )
 | |
| 
 | |
| class SMBRename_Data(AsciiOrUnicodeStructure):
 | |
|     AsciiStructure = (
 | |
|         ('BufferFormat1','<B=4'),
 | |
|         ('OldFileName','z'),
 | |
|         ('BufferFormat2','<B=4'),
 | |
|         ('NewFileName','z'),
 | |
|     )
 | |
|     UnicodeStructure = (
 | |
|         ('BufferFormat1','<B=4'),
 | |
|         ('OldFileName','u'),
 | |
|         ('BufferFormat2','<B=4'),
 | |
|         ('Pad','B=0'),
 | |
|         ('NewFileName','u'),
 | |
|     )
 | |
| 
 | |
| 
 | |
| ############# SMB_COM_OPEN (0x02)
 | |
| class SMBOpen_Parameters(SMBCommand_Parameters):
 | |
|     structure = (
 | |
|         ('DesiredAccess','<H=0'),
 | |
|         ('SearchAttributes','<H=0'),
 | |
|     )
 | |
| 
 | |
| class SMBOpen_Data(AsciiOrUnicodeStructure):
 | |
|     AsciiStructure = (
 | |
|         ('FileNameFormat','"\x04'),
 | |
|         ('FileName','z'),
 | |
|     )
 | |
|     UnicodeStructure = (
 | |
|         ('FileNameFormat','"\x04'),
 | |
|         ('FileName','z'),
 | |
|     )
 | |
| 
 | |
| class SMBOpenResponse_Parameters(SMBCommand_Parameters):
 | |
|     structure = (
 | |
|         ('Fid','<H=0'),
 | |
|         ('FileAttributes','<H=0'),
 | |
|         ('LastWriten','<L=0'),
 | |
|         ('FileSize','<L=0'),
 | |
|         ('GrantedAccess','<H=0'),
 | |
|     )
 | |
| 
 | |
| ############# EXTENDED SECURITY CLASSES
 | |
| class SMBExtended_Security_Parameters(Structure):
 | |
|     structure = (
 | |
|         ('DialectIndex','<H'),
 | |
|         ('SecurityMode','<B'),
 | |
|         ('MaxMpxCount','<H'),
 | |
|         ('MaxNumberVcs','<H'),
 | |
|         ('MaxBufferSize','<L'),
 | |
|         ('MaxRawSize','<L'),
 | |
|         ('SessionKey','<L'),
 | |
|         ('Capabilities','<L'),
 | |
|         ('LowDateTime','<L'),
 | |
|         ('HighDateTime','<L'),
 | |
|         ('ServerTimeZone','<H'),
 | |
|         ('ChallengeLength','<B'),
 | |
|     )
 | |
| 
 | |
| class SMBExtended_Security_Data(Structure):
 | |
|     structure = (
 | |
|         ('ServerGUID','16s'),
 | |
|         ('SecurityBlob',':'),
 | |
|     )
 | |
| 
 | |
| class SMBNTLMDialect_Parameters(Structure):
 | |
|     structure = (
 | |
|         ('DialectIndex','<H'),
 | |
|         ('SecurityMode','<B'),
 | |
|         ('MaxMpxCount','<H'),
 | |
|         ('MaxNumberVcs','<H'),
 | |
|         ('MaxBufferSize','<L'),
 | |
|         ('MaxRawSize','<L'),
 | |
|         ('SessionKey','<L'),
 | |
|         ('Capabilities','<L'),
 | |
|         ('LowDateTime','<L'),
 | |
|         ('HighDateTime','<L'),
 | |
|         ('ServerTimeZone','<H'),
 | |
|         ('ChallengeLength','<B'),
 | |
|     )
 | |
| 
 | |
| class SMBNTLMDialect_Data(Structure):
 | |
|     structure = (
 | |
|         ('ChallengeLength','_-Challenge','self["ChallengeLength"]'),
 | |
|         ('Challenge',':'),
 | |
|         ('Payload',':'),
 | |
| # 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.
 | |
|         ('DomainName','_'),
 | |
|         ('ServerName','_'),
 | |
|     )
 | |
|     def __init__(self,data = None, alignment = 0):
 | |
|          Structure.__init__(self,data,alignment)
 | |
|          #self['ChallengeLength']=8
 | |
| 
 | |
|     def fromString(self,data):
 | |
|         Structure.fromString(self,data)
 | |
|         self['DomainName'] = ''
 | |
|         self['ServerName'] = ''
 | |
| 
 | |
| class SMB:
 | |
|     # SMB Command Codes
 | |
|     SMB_COM_CREATE_DIRECTORY                = 0x00
 | |
|     SMB_COM_DELETE_DIRECTORY                = 0x01
 | |
|     SMB_COM_OPEN                            = 0x02
 | |
|     SMB_COM_CREATE                          = 0x03
 | |
|     SMB_COM_CLOSE                           = 0x04
 | |
|     SMB_COM_FLUSH                           = 0x05
 | |
|     SMB_COM_DELETE                          = 0x06
 | |
|     SMB_COM_RENAME                          = 0x07
 | |
|     SMB_COM_QUERY_INFORMATION               = 0x08
 | |
|     SMB_COM_SET_INFORMATION                 = 0x09
 | |
|     SMB_COM_READ                            = 0x0A
 | |
|     SMB_COM_WRITE                           = 0x0B
 | |
|     SMB_COM_LOCK_BYTE_RANGE                 = 0x0C
 | |
|     SMB_COM_UNLOCK_BYTE_RANGE               = 0x0D
 | |
|     SMB_COM_CREATE_TEMPORARY                = 0x0E
 | |
|     SMB_COM_CREATE_NEW                      = 0x0F
 | |
|     SMB_COM_CHECK_DIRECTORY                 = 0x10
 | |
|     SMB_COM_PROCESS_EXIT                    = 0x11
 | |
|     SMB_COM_SEEK                            = 0x12
 | |
|     SMB_COM_LOCK_AND_READ                   = 0x13
 | |
|     SMB_COM_WRITE_AND_UNLOCK                = 0x14
 | |
|     SMB_COM_READ_RAW                        = 0x1A
 | |
|     SMB_COM_READ_MPX                        = 0x1B
 | |
|     SMB_COM_READ_MPX_SECONDARY              = 0x1C
 | |
|     SMB_COM_WRITE_RAW                       = 0x1D
 | |
|     SMB_COM_WRITE_MPX                       = 0x1E
 | |
|     SMB_COM_WRITE_MPX_SECONDARY             = 0x1F
 | |
|     SMB_COM_WRITE_COMPLETE                  = 0x20
 | |
|     SMB_COM_QUERY_SERVER                    = 0x21
 | |
|     SMB_COM_SET_INFORMATION2                = 0x22
 | |
|     SMB_COM_QUERY_INFORMATION2              = 0x23
 | |
|     SMB_COM_LOCKING_ANDX                    = 0x24
 | |
|     SMB_COM_TRANSACTION                     = 0x25
 | |
|     SMB_COM_TRANSACTION_SECONDARY           = 0x26
 | |
|     SMB_COM_IOCTL                           = 0x27
 | |
|     SMB_COM_IOCTL_SECONDARY                 = 0x28
 | |
|     SMB_COM_COPY                            = 0x29
 | |
|     SMB_COM_MOVE                            = 0x2A
 | |
|     SMB_COM_ECHO                            = 0x2B
 | |
|     SMB_COM_WRITE_AND_CLOSE                 = 0x2C
 | |
|     SMB_COM_OPEN_ANDX                       = 0x2D
 | |
|     SMB_COM_READ_ANDX                       = 0x2E
 | |
|     SMB_COM_WRITE_ANDX                      = 0x2F
 | |
|     SMB_COM_NEW_FILE_SIZE                   = 0x30
 | |
|     SMB_COM_CLOSE_AND_TREE_DISC             = 0x31
 | |
|     SMB_COM_TRANSACTION2                    = 0x32
 | |
|     SMB_COM_TRANSACTION2_SECONDARY          = 0x33
 | |
|     SMB_COM_FIND_CLOSE2                     = 0x34
 | |
|     SMB_COM_FIND_NOTIFY_CLOSE               = 0x35
 | |
|     # Used by Xenix/Unix 0x60 - 0x6E 
 | |
|     SMB_COM_TREE_CONNECT                    = 0x70
 | |
|     SMB_COM_TREE_DISCONNECT                 = 0x71
 | |
|     SMB_COM_NEGOTIATE                       = 0x72
 | |
|     SMB_COM_SESSION_SETUP_ANDX              = 0x73
 | |
|     SMB_COM_LOGOFF_ANDX                     = 0x74
 | |
|     SMB_COM_TREE_CONNECT_ANDX               = 0x75
 | |
|     SMB_COM_QUERY_INFORMATION_DISK          = 0x80
 | |
|     SMB_COM_SEARCH                          = 0x81
 | |
|     SMB_COM_FIND                            = 0x82
 | |
|     SMB_COM_FIND_UNIQUE                     = 0x83
 | |
|     SMB_COM_FIND_CLOSE                      = 0x84
 | |
|     SMB_COM_NT_TRANSACT                     = 0xA0
 | |
|     SMB_COM_NT_TRANSACT_SECONDARY           = 0xA1
 | |
|     SMB_COM_NT_CREATE_ANDX                  = 0xA2
 | |
|     SMB_COM_NT_CANCEL                       = 0xA4
 | |
|     SMB_COM_NT_RENAME                       = 0xA5
 | |
|     SMB_COM_OPEN_PRINT_FILE                 = 0xC0
 | |
|     SMB_COM_WRITE_PRINT_FILE                = 0xC1
 | |
|     SMB_COM_CLOSE_PRINT_FILE                = 0xC2
 | |
|     SMB_COM_GET_PRINT_QUEUE                 = 0xC3
 | |
|     SMB_COM_READ_BULK                       = 0xD8
 | |
|     SMB_COM_WRITE_BULK                      = 0xD9
 | |
|     SMB_COM_WRITE_BULK_DATA                 = 0xDA
 | |
| 
 | |
|     # TRANSACT codes
 | |
|     TRANS_TRANSACT_NMPIPE                   = 0x26
 | |
| 
 | |
|     # TRANSACT2 codes
 | |
|     TRANS2_FIND_FIRST2                      = 0x0001
 | |
|     TRANS2_FIND_NEXT2                       = 0x0002
 | |
|     TRANS2_QUERY_FS_INFORMATION             = 0x0003
 | |
|     TRANS2_QUERY_PATH_INFORMATION           = 0x0005
 | |
|     TRANS2_QUERY_FILE_INFORMATION           = 0x0007
 | |
|     TRANS2_SET_FILE_INFORMATION             = 0x0008
 | |
|     TRANS2_SET_PATH_INFORMATION             = 0x0006
 | |
| 
 | |
|     # Security Share Mode (Used internally by SMB class)
 | |
|     SECURITY_SHARE_MASK                     = 0x01
 | |
|     SECURITY_SHARE_SHARE                    = 0x00
 | |
|     SECURITY_SHARE_USER                     = 0x01
 | |
|     SECURITY_SIGNATURES_ENABLED             = 0X04
 | |
|     SECURITY_SIGNATURES_REQUIRED            = 0X08
 | |
| 
 | |
|     # Security Auth Mode (Used internally by SMB class)
 | |
|     SECURITY_AUTH_MASK                      = 0x02
 | |
|     SECURITY_AUTH_ENCRYPTED                 = 0x02
 | |
|     SECURITY_AUTH_PLAINTEXT                 = 0x00
 | |
| 
 | |
|     # Raw Mode Mask (Used internally by SMB class. Good for dialect up to and including LANMAN2.1)
 | |
|     RAW_READ_MASK                           = 0x01
 | |
|     RAW_WRITE_MASK                          = 0x02
 | |
| 
 | |
|     # Capabilities Mask (Used internally by SMB class. Good for dialect NT LM 0.12)
 | |
|     CAP_RAW_MODE                            = 0x00000001
 | |
|     CAP_MPX_MODE                            = 0x0002
 | |
|     CAP_UNICODE                             = 0x0004
 | |
|     CAP_LARGE_FILES                         = 0x0008
 | |
|     CAP_EXTENDED_SECURITY                   = 0x80000000
 | |
|     CAP_USE_NT_ERRORS                       = 0x40
 | |
|     CAP_NT_SMBS                             = 0x10
 | |
|     CAP_LARGE_READX                         = 0x00004000
 | |
|     CAP_LARGE_WRITEX                        = 0x00008000
 | |
|     CAP_RPC_REMOTE_APIS                     = 0x20
 | |
| 
 | |
|     # Flags1 Mask
 | |
|     FLAGS1_LOCK_AND_READ_OK                 = 0x01
 | |
|     FLAGS1_PATHCASELESS                     = 0x08
 | |
|     FLAGS1_CANONICALIZED_PATHS              = 0x10
 | |
|     FLAGS1_REPLY                            = 0x80
 | |
| 
 | |
|     # Flags2 Mask
 | |
|     FLAGS2_LONG_NAMES                       = 0x0001
 | |
|     FLAGS2_EAS                              = 0x0002
 | |
|     FLAGS2_SMB_SECURITY_SIGNATURE           = 0x0004
 | |
|     FLAGS2_IS_LONG_NAME                     = 0x0040
 | |
|     FLAGS2_DFS                              = 0x1000
 | |
|     FLAGS2_PAGING_IO                        = 0x2000
 | |
|     FLAGS2_NT_STATUS                        = 0x4000
 | |
|     FLAGS2_UNICODE                          = 0x8000
 | |
|     FLAGS2_COMPRESSED                       = 0x0008
 | |
|     FLAGS2_SMB_SECURITY_SIGNATURE_REQUIRED  = 0x0010
 | |
|     FLAGS2_EXTENDED_SECURITY                = 0x0800
 | |
| 
 | |
|     # Dialect's Security Mode flags
 | |
|     NEGOTIATE_USER_SECURITY                 = 0x01
 | |
|     NEGOTIATE_ENCRYPT_PASSWORDS             = 0x02
 | |
|     NEGOTIATE_SECURITY_SIGNATURE_ENABLE     = 0x04
 | |
|     NEGOTIATE_SECURITY_SIGNATURE_REQUIRED   = 0x08
 | |
| 
 | |
|     # Tree Connect AndX Response optionalSuppor flags
 | |
|     SMB_SUPPORT_SEARCH_BITS                 = 0x01
 | |
|     SMB_SHARE_IS_IN_DFS                     = 0x02
 | |
| 
 | |
|     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):
 | |
|         # The uid attribute will be set when the client calls the login() method
 | |
|         self._uid = 0
 | |
|         self.__server_name = ''
 | |
|         self.__server_os = ''
 | |
|         self.__server_os_major = None
 | |
|         self.__server_os_minor = None
 | |
|         self.__server_os_build = None
 | |
|         self.__server_lanman = ''
 | |
|         self.__server_domain = ''
 | |
|         self.__server_dns_domain_name = ''
 | |
|         self.__remote_name = string.upper(remote_name)
 | |
|         self.__remote_host = remote_host
 | |
|         self.__isNTLMv2 = True
 | |
|         self._dialects_parameters = None
 | |
|         self._dialects_data = None
 | |
|         # Credentials
 | |
|         self.__userName = ''
 | |
|         self.__password = ''
 | |
|         self.__domain   = ''
 | |
|         self.__lmhash   = ''
 | |
|         self.__nthash   = ''
 | |
|         self.__aesKey   = ''
 | |
|         self.__kdc      = ''
 | |
|         self.__TGT      = None
 | |
|         self.__TGS      = None
 | |
| 
 | |
|         # Negotiate Protocol Result, used everywhere
 | |
|         # Could be extended or not, flags should be checked before 
 | |
|         self._dialect_data = 0
 | |
|         self._dialect_parameters = 0
 | |
|         self._action = 0
 | |
|         self._sess = None
 | |
|         self.encrypt_passwords = True
 | |
|         self.tid = 0
 | |
|         self.fid = 0
 | |
| 
 | |
|         # Signing stuff
 | |
|         self._SignSequenceNumber = 0
 | |
|         self._SigningSessionKey = ''
 | |
|         self._SigningChallengeResponse = ''
 | |
|         self._SignatureEnabled = False
 | |
|         self._SignatureVerificationEnabled = False
 | |
|         self._SignatureRequired = False
 | |
| 
 | |
|         # Base flags (default flags, can be overriden using set_flags())
 | |
|         self.__flags1 = SMB.FLAGS1_PATHCASELESS | SMB.FLAGS1_CANONICALIZED_PATHS
 | |
|         self.__flags2 = SMB.FLAGS2_EXTENDED_SECURITY | SMB.FLAGS2_NT_STATUS | SMB.FLAGS2_LONG_NAMES
 | |
| 
 | |
|         if timeout is None:
 | |
|             self.__timeout = 60
 | |
|         else:
 | |
|             self.__timeout = timeout
 | |
| 
 | |
|         # If port 445 and the name sent is *SMBSERVER we're setting the name to the IP. 
 | |
|         # This is to help some old applications still believing 
 | |
|         # *SMSBSERVER will work against modern OSes. If port is NETBIOS_SESSION_PORT the user better 
 | |
|         # know about *SMBSERVER's limitations
 | |
|         if sess_port == 445 and remote_name == '*SMBSERVER':
 | |
|            self.__remote_name = remote_host
 | |
| 
 | |
|         if session is None:
 | |
|             if not my_name:
 | |
|                 my_name = socket.gethostname()
 | |
|                 i = string.find(my_name, '.')
 | |
|                 if i > -1:
 | |
|                     my_name = my_name[:i]
 | |
| 
 | |
|             if UDP:
 | |
|                 self._sess = nmb.NetBIOSUDPSession(my_name, remote_name, remote_host, host_type, sess_port, self.__timeout)
 | |
|             else:
 | |
|                 self._sess = nmb.NetBIOSTCPSession(my_name, remote_name, remote_host, host_type, sess_port, self.__timeout)
 | |
| 
 | |
|                 # Initialize session values (_dialect_data and _dialect_parameters)
 | |
|                 self.neg_session()
 | |
| 
 | |
|                 # Call login() without any authentication information to 
 | |
|                 # setup a session if the remote server
 | |
|                 # is in share mode.
 | |
|                 if (self._dialects_parameters['SecurityMode'] & SMB.SECURITY_SHARE_MASK) == SMB.SECURITY_SHARE_SHARE:
 | |
|                     self.login('', '')
 | |
|         else:
 | |
|             self._sess = session
 | |
|             self.neg_session(negPacket = negPacket)
 | |
|             # Call login() without any authentication information to 
 | |
|             # setup a session if the remote server
 | |
|             # is in share mode.
 | |
|             if (self._dialects_parameters['SecurityMode'] & SMB.SECURITY_SHARE_MASK) == SMB.SECURITY_SHARE_SHARE:
 | |
|                 self.login('', '')
 | |
| 
 | |
|     @staticmethod
 | |
|     def ntlm_supported():
 | |
|         return False
 | |
| 
 | |
|     def get_remote_name(self):
 | |
|         return self.__remote_name
 | |
| 
 | |
|     def get_remote_host(self):
 | |
|         return self.__remote_host
 | |
| 
 | |
|     def get_flags(self):
 | |
|         return self.__flags1, self.__flags2
 | |
| 
 | |
|     def set_flags(self, flags1=None, flags2=None):
 | |
|         if flags1 is not None:
 | |
|            self.__flags1 = flags1
 | |
|         if flags2 is not None:
 | |
|            self.__flags2 = flags2
 | |
| 
 | |
|     def set_timeout(self, timeout):
 | |
|         prev_timeout = self.__timeout
 | |
|         self.__timeout = timeout
 | |
|         return prev_timeout
 | |
| 
 | |
|     def get_timeout(self):
 | |
|         return self.__timeout
 | |
| 
 | |
|     @contextmanager
 | |
|     def use_timeout(self, timeout):
 | |
|         prev_timeout = self.set_timeout(timeout)
 | |
|         try:
 | |
|             yield
 | |
|         finally:
 | |
|             self.set_timeout(prev_timeout)
 | |
| 
 | |
|     def get_session(self):
 | |
|         return self._sess
 | |
| 
 | |
|     def get_tid(self):
 | |
|         return self.tid
 | |
| 
 | |
|     def get_fid(self):
 | |
|         return self.fid
 | |
| 
 | |
|     def isGuestSession(self):
 | |
|         return self._action & SMB_SETUP_GUEST
 | |
| 
 | |
|     def doesSupportNTLMv2(self):
 | |
|         return self.__isNTLMv2
 | |
| 
 | |
|     def __del__(self):
 | |
|         if self._sess:
 | |
|             self._sess.close()
 | |
| 
 | |
|     def recvSMB(self):
 | |
|         r = self._sess.recv_packet(self.__timeout)
 | |
|         return NewSMBPacket(data = r.get_trailer())
 | |
| 
 | |
|     @staticmethod
 | |
|     def __decode_trans(params, data):
 | |
|         totparamcnt, totdatacnt, _, paramcnt, paramoffset, paramds, datacnt, dataoffset, datads, setupcnt = unpack('<HHHHHHHHHB', params[:19])
 | |
|         if paramcnt + paramds < totparamcnt or datacnt + datads < totdatacnt:
 | |
|             has_more = 1
 | |
|         else:
 | |
|             has_more = 0
 | |
|         paramoffset = paramoffset - 55 - setupcnt * 2
 | |
|         dataoffset = dataoffset - 55 - setupcnt * 2
 | |
|         return has_more, params[20:20 + setupcnt * 2], data[paramoffset:paramoffset + paramcnt], data[dataoffset:dataoffset + datacnt]
 | |
| 
 | |
|     # TODO: Move this to NewSMBPacket, it belongs there
 | |
|     def signSMB(self, packet, signingSessionKey, signingChallengeResponse):
 | |
|         # This logic MUST be applied for messages sent in response to any of the higher-layer actions and in
 | |
|         # compliance with the message sequencing rules.
 | |
|         #  * The client or server that sends the message MUST provide the 32-bit sequence number for this
 | |
|         #    message, as specified in sections 3.2.4.1 and 3.3.4.1.
 | |
|         #  * The SMB_FLAGS2_SMB_SECURITY_SIGNATURE flag in the header MUST be set.
 | |
|         #  * To generate the signature, a 32-bit sequence number is copied into the 
 | |
|         #    least significant 32 bits of the SecuritySignature field and the remaining 
 | |
|         #    4 bytes are set to 0x00.
 | |
|         #  * The MD5 algorithm, as specified in [RFC1321], MUST be used to generate a hash of the SMB
 | |
|         #    message from the start of the SMB Header, which is defined as follows.
 | |
|         #    CALL MD5Init( md5context )
 | |
|         #    CALL MD5Update( md5context, Connection.SigningSessionKey )
 | |
|         #    CALL MD5Update( md5context, Connection.SigningChallengeResponse )
 | |
|         #    CALL MD5Update( md5context, SMB message )
 | |
|         #    CALL MD5Final( digest, md5context )
 | |
|         #    SET signature TO the first 8 bytes of the digest
 | |
|         # The resulting 8-byte signature MUST be copied into the SecuritySignature field of the SMB Header,
 | |
|         # after which the message can be transmitted.
 | |
| 
 | |
|         #print "seq(%d) signingSessionKey %r, signingChallengeResponse %r" % (self._SignSequenceNumber, signingSessionKey, signingChallengeResponse)
 | |
|         packet['SecurityFeatures'] = pack('<q',self._SignSequenceNumber)
 | |
|         # Sign with the sequence
 | |
|         m = hashlib.md5()
 | |
|         m.update( signingSessionKey )
 | |
|         m.update( signingChallengeResponse )
 | |
|         m.update( str(packet) )
 | |
|         # Replace sequence with acual hash
 | |
|         packet['SecurityFeatures'] = m.digest()[:8]
 | |
|         if self._SignatureVerificationEnabled:
 | |
|            self._SignSequenceNumber +=1
 | |
|         else:
 | |
|            self._SignSequenceNumber +=2
 | |
| 
 | |
|     def checkSignSMB(self, packet, signingSessionKey, signingChallengeResponse):
 | |
|         # Let's check
 | |
|         signature = packet['SecurityFeatures']
 | |
|         #print "Signature received: %r " % signature
 | |
|         self.signSMB(packet, signingSessionKey, signingChallengeResponse)
 | |
|         #print "Signature calculated: %r" % packet['SecurityFeatures']
 | |
|         if self._SignatureVerificationEnabled is not True:
 | |
|            self._SignSequenceNumber -= 1
 | |
|         return packet['SecurityFeatures'] == signature
 | |
| 
 | |
|     def sendSMB(self,smb):
 | |
|         smb['Uid'] = self._uid
 | |
|         #At least on AIX, PIDs can exceed 16 bits, so we mask them out
 | |
|         smb['Pid'] = (os.getpid() & 0xFFFF)
 | |
|         # set flags
 | |
|         smb['Flags1'] |= self.__flags1
 | |
|         smb['Flags2'] |= self.__flags2
 | |
|         if self._SignatureEnabled:
 | |
|             smb['Flags2'] |= SMB.FLAGS2_SMB_SECURITY_SIGNATURE
 | |
|             self.signSMB(smb, self._SigningSessionKey, self._SigningChallengeResponse)
 | |
| 
 | |
|         self._sess.send_packet(str(smb))
 | |
| 
 | |
|     @staticmethod
 | |
|     def isValidAnswer(s, cmd):
 | |
|         while 1:
 | |
|             if s.rawData():
 | |
|                 if s.get_command() == cmd:
 | |
|                     if s.get_error_class() == 0x00 and s.get_error_code() == 0x00:
 | |
|                         return 1
 | |
|                     else:
 | |
|                         raise SessionError, ( "SMB Library Error", s.get_error_class()+ (s.get_reserved() << 8), s.get_error_code() , s.get_flags2() & SMB.FLAGS2_NT_STATUS )
 | |
|                 else:
 | |
|                     break
 | |
|         return 0
 | |
| 
 | |
|     def neg_session(self, extended_security = True, negPacket = None):
 | |
|         def parsePacket(smb):
 | |
|             if smb.isValidAnswer(SMB.SMB_COM_NEGOTIATE):
 | |
|                 sessionResponse = SMBCommand(smb['Data'][0])
 | |
|                 self._dialects_parameters = SMBNTLMDialect_Parameters(sessionResponse['Parameters'])
 | |
|                 self._dialects_data = SMBNTLMDialect_Data()
 | |
|                 self._dialects_data['ChallengeLength'] = self._dialects_parameters['ChallengeLength']
 | |
|                 self._dialects_data.fromString(sessionResponse['Data'])
 | |
|                 if self._dialects_parameters['Capabilities'] & SMB.CAP_EXTENDED_SECURITY:
 | |
|                     # Whether we choose it or it is enforced by the server, we go for extended security
 | |
|                     self._dialects_parameters = SMBExtended_Security_Parameters(sessionResponse['Parameters'])
 | |
|                     self._dialects_data = SMBExtended_Security_Data(sessionResponse['Data'])
 | |
|                     # Let's setup some variable for later use
 | |
|                     if self._dialects_parameters['SecurityMode'] & SMB.SECURITY_SIGNATURES_REQUIRED:
 | |
|                          self._SignatureRequired = True
 | |
| 
 | |
|                     # Interestingly, the security Blob might be missing sometimes.
 | |
|                     #spnego = SPNEGO_NegTokenInit(self._dialects_data['SecurityBlob'])
 | |
|                     #for i in spnego['MechTypes']:
 | |
|                     #      print "Mech Found: %s" % MechTypes[i]
 | |
|                     return 1
 | |
| 
 | |
|                 # If not, let's try the old way
 | |
|                 else:
 | |
|                     if self._dialects_data['ServerName'] is not None:
 | |
|                         self.__server_name = self._dialects_data['ServerName']
 | |
| 
 | |
|                     if self._dialects_parameters['DialectIndex'] == 0xffff:
 | |
|                         raise UnsupportedFeature,"Remote server does not know NT LM 0.12"
 | |
|                     return 1
 | |
|             else:
 | |
|                 return 0
 | |
| 
 | |
|         if negPacket is None:
 | |
|             smb = NewSMBPacket()
 | |
|             negSession = SMBCommand(SMB.SMB_COM_NEGOTIATE)
 | |
|             flags2 = self.get_flags()[1]
 | |
|             if extended_security is True:
 | |
|                 self.set_flags(flags2=flags2|SMB.FLAGS2_EXTENDED_SECURITY)
 | |
|             else:
 | |
|                 self.set_flags(flags2=flags2 & (~SMB.FLAGS2_EXTENDED_SECURITY))
 | |
| 
 | |
|             negSession['Data'] = '\x02NT LM 0.12\x00'
 | |
|             smb.addCommand(negSession)
 | |
|             self.sendSMB(smb)
 | |
| 
 | |
|             while 1:
 | |
|                 smb = self.recvSMB()
 | |
|                 return parsePacket(smb)
 | |
|         else:
 | |
| 
 | |
|             return parsePacket( NewSMBPacket( data = negPacket))
 | |
| 
 | |
|     def tree_connect(self, path, password = '', service = SERVICE_ANY):
 | |
|         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")
 | |
| 
 | |
|         # return 0x800
 | |
|         if password:
 | |
|             # Password is only encrypted if the server passed us an "encryption" during protocol dialect
 | |
|             if self._dialects_parameters['ChallengeLength'] > 0:
 | |
|                 # this code is untested
 | |
|                 password = self.get_ntlmv1_response(ntlm.compute_lmhash(password))
 | |
| 
 | |
|         if not unicode_support:
 | |
|             if unicode_convert:
 | |
|                 path = str(path)
 | |
|             else:
 | |
|                 raise Exception('SMB: Can\t conver path from unicode!')
 | |
| 
 | |
|         smb = NewSMBPacket()
 | |
|         treeConnect = SMBCommand(SMB.SMB_COM_TREE_CONNECT)
 | |
|         treeConnect['Parameters'] = SMBTreeConnect_Parameters()
 | |
|         treeConnect['Data']       = SMBTreeConnect_Data()
 | |
|         treeConnect['Data']['Path'] = path.upper()
 | |
|         treeConnect['Data']['Password'] = password
 | |
|         treeConnect['Data']['Service'] = service
 | |
|         smb.addCommand(treeConnect)
 | |
|         self.sendSMB(smb)
 | |
| 
 | |
|         while 1:
 | |
|             smb = self.recvSMB()
 | |
|             if smb.isValidAnswer(SMB.SMB_COM_TREE_CONNECT):
 | |
|                 # XXX Here we are ignoring the rest of the response
 | |
|                 return smb['Tid']
 | |
|             return smb['Tid']
 | |
| 
 | |
|     def get_uid(self):
 | |
|         return self._uid
 | |
| 
 | |
|     def set_uid(self, uid):
 | |
|         self._uid = uid
 | |
| 
 | |
|     def tree_connect_andx(self, path, password = None, service = SERVICE_ANY, smb_packet=None):
 | |
|         if password:
 | |
|             # Password is only encrypted if the server passed us an "encryption" during protocol dialect
 | |
|             if self._dialects_parameters['ChallengeLength'] > 0:
 | |
|                 # this code is untested
 | |
|                 password = self.get_ntlmv1_response(ntlm.compute_lmhash(password))
 | |
|         else:
 | |
|             password = '\x00'
 | |
| 
 | |
|         if not unicode_support:
 | |
|             if unicode_convert:
 | |
|                 path = str(path)
 | |
|             else:
 | |
|                 raise Exception('SMB: Can\t convert path from unicode!')
 | |
| 
 | |
|         if smb_packet is None:
 | |
|             smb = NewSMBPacket()
 | |
|         else:
 | |
|             smb = smb_packet
 | |
| 
 | |
|         # Just in case this came with the full path ,let's just leave 
 | |
|         # the sharename, we'll take care of the rest
 | |
| 
 | |
|         share = path.split('\\')[-1]
 | |
|         try:
 | |
|             _, _, _, _, sockaddr = socket.getaddrinfo(self.get_remote_host(), 80, 0, 0, socket.IPPROTO_TCP)[0]
 | |
|             remote_host = sockaddr[0]
 | |
|         except Exception:
 | |
|             remote_host =  self.get_remote_host()
 | |
| 
 | |
|         path = '\\\\' + remote_host + '\\' +share
 | |
|         path = path.upper().encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else path
 | |
| 
 | |
|         treeConnect = SMBCommand(SMB.SMB_COM_TREE_CONNECT_ANDX)
 | |
|         treeConnect['Parameters'] = SMBTreeConnectAndX_Parameters()
 | |
|         treeConnect['Data']       = SMBTreeConnectAndX_Data(flags=self.__flags2)
 | |
|         treeConnect['Parameters']['PasswordLength'] = len(password)
 | |
|         treeConnect['Data']['Password'] = password
 | |
|         treeConnect['Data']['Path'] = path
 | |
|         treeConnect['Data']['Service'] = service
 | |
| 
 | |
|         if self.__flags2 & SMB.FLAGS2_UNICODE:
 | |
|             treeConnect['Data']['Pad'] = 0x0
 | |
| 
 | |
|         smb.addCommand(treeConnect)
 | |
| 
 | |
|         # filename = "\PIPE\epmapper"
 | |
| 
 | |
|         # ntCreate = SMBCommand(SMB.SMB_COM_NT_CREATE_ANDX)
 | |
|         # ntCreate['Parameters'] = SMBNtCreateAndX_Parameters()
 | |
|         # ntCreate['Data']       = SMBNtCreateAndX_Data()
 | |
|         # ntCreate['Parameters']['FileNameLength'] = len(filename)
 | |
|         # ntCreate['Parameters']['CreateFlags'] = 0
 | |
|         # ntCreate['Parameters']['AccessMask'] = 0x3
 | |
|         # ntCreate['Parameters']['CreateOptions'] = 0x0
 | |
|         # ntCreate['Data']['FileName'] = filename
 | |
| 
 | |
|         # smb.addCommand(ntCreate)
 | |
|         self.sendSMB(smb)
 | |
| 
 | |
|         while 1:
 | |
|             smb = self.recvSMB()
 | |
|             if smb.isValidAnswer(SMB.SMB_COM_TREE_CONNECT_ANDX):
 | |
|                 # XXX Here we are ignoring the rest of the response
 | |
|                 self.tid = smb['Tid']
 | |
|                 return self.tid
 | |
|             self.tid = smb['Tid']
 | |
|             return self.tid
 | |
| 
 | |
|     # backwars compatibility
 | |
|     connect_tree = tree_connect_andx
 | |
| 
 | |
|     @staticmethod
 | |
|     def getDialect():
 | |
|         return SMB_DIALECT
 | |
| 
 | |
|     def get_server_name(self):
 | |
|         #return self._dialects_data['ServerName']
 | |
|         return self.__server_name
 | |
| 
 | |
|     def get_session_key(self):
 | |
|         return self._SigningSessionKey
 | |
| 
 | |
|     def set_session_key(self, key):
 | |
|         self._SigningSessionKey = key
 | |
| 
 | |
|     def get_encryption_key(self):
 | |
|         if self._dialects_data.fields.has_key('Challenge'):
 | |
|             return self._dialects_data['Challenge']
 | |
|         else:
 | |
|             return None
 | |
| 
 | |
|     def get_server_time(self):
 | |
|         timestamp = self._dialects_parameters['HighDateTime']
 | |
|         timestamp <<= 32
 | |
|         timestamp |= self._dialects_parameters['LowDateTime']
 | |
|         timestamp -= 116444736000000000
 | |
|         timestamp /= 10000000
 | |
|         d = datetime.datetime.utcfromtimestamp(timestamp)
 | |
|         return d.strftime("%a, %d %b %Y %H:%M:%S GMT")
 | |
| 
 | |
|     def disconnect_tree(self, tid):
 | |
|         smb = NewSMBPacket()
 | |
|         smb['Tid']  = tid
 | |
| 
 | |
|         smb.addCommand(SMBCommand(SMB.SMB_COM_TREE_DISCONNECT))
 | |
| 
 | |
|         self.sendSMB(smb)
 | |
|         self.recvSMB()
 | |
| 
 | |
|     def open(self, tid, filename, open_mode, desired_access):
 | |
|         filename = string.replace(filename,'/', '\\')
 | |
|         filename = filename.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else filename
 | |
| 
 | |
|         smb = NewSMBPacket()
 | |
|         smb['Tid']    = tid
 | |
| 
 | |
|         openFile = SMBCommand(SMB.SMB_COM_OPEN)
 | |
|         openFile['Parameters'] = SMBOpen_Parameters()
 | |
|         openFile['Parameters']['DesiredAccess']    = desired_access
 | |
|         openFile['Parameters']['OpenMode']         = open_mode
 | |
|         openFile['Parameters']['SearchAttributes'] = ATTR_READONLY | ATTR_HIDDEN | ATTR_ARCHIVE
 | |
|         openFile['Data']       = SMBOpen_Data(flags=self.__flags2)
 | |
|         openFile['Data']['FileName'] = filename
 | |
| 
 | |
|         if self.__flags2 & SMB.FLAGS2_UNICODE:
 | |
|             openFile['Data']['Pad'] = 0x0
 | |
| 
 | |
|         smb.addCommand(openFile)
 | |
| 
 | |
|         self.sendSMB(smb)
 | |
| 
 | |
|         smb = self.recvSMB()
 | |
|         if smb.isValidAnswer(SMB.SMB_COM_OPEN):
 | |
|             # XXX Here we are ignoring the rest of the response
 | |
|             openFileResponse   = SMBCommand(smb['Data'][0])
 | |
|             openFileParameters = SMBOpenResponse_Parameters(openFileResponse['Parameters'])
 | |
| 
 | |
|             return (
 | |
|                 openFileParameters['Fid'],
 | |
|                 openFileParameters['FileAttributes'],
 | |
|                 openFileParameters['LastWriten'],
 | |
|                 openFileParameters['FileSize'],
 | |
|                 openFileParameters['GrantedAccess'],
 | |
|             )
 | |
| 
 | |
|     def open_andx(self, tid, filename, open_mode, desired_access):
 | |
|         filename = string.replace(filename,'/', '\\')
 | |
|         filename = filename.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else filename
 | |
| 
 | |
|         smb = NewSMBPacket()
 | |
|         smb['Tid']    = tid
 | |
| 
 | |
|         openFile = SMBCommand(SMB.SMB_COM_OPEN_ANDX)
 | |
|         openFile['Parameters'] = SMBOpenAndX_Parameters()
 | |
|         openFile['Parameters']['DesiredAccess']    = desired_access
 | |
|         openFile['Parameters']['OpenMode']         = open_mode
 | |
|         openFile['Parameters']['SearchAttributes'] = ATTR_READONLY | ATTR_HIDDEN | ATTR_ARCHIVE
 | |
|         openFile['Data']       = SMBOpenAndX_Data(flags=self.__flags2)
 | |
|         openFile['Data']['FileName'] = filename
 | |
| 
 | |
|         if self.__flags2 & SMB.FLAGS2_UNICODE:
 | |
|             openFile['Data']['Pad'] = 0x0
 | |
| 
 | |
|         smb.addCommand(openFile)
 | |
| 
 | |
|         self.sendSMB(smb)
 | |
| 
 | |
|         smb = self.recvSMB()
 | |
|         if smb.isValidAnswer(SMB.SMB_COM_OPEN_ANDX):
 | |
|             # XXX Here we are ignoring the rest of the response
 | |
|             openFileResponse   = SMBCommand(smb['Data'][0])
 | |
|             openFileParameters = SMBOpenAndXResponse_Parameters(openFileResponse['Parameters'])
 | |
| 
 | |
|             return (
 | |
|                 openFileParameters['Fid'],
 | |
|                 openFileParameters['FileAttributes'],
 | |
|                 openFileParameters['LastWriten'],
 | |
|                 openFileParameters['FileSize'],
 | |
|                 openFileParameters['GrantedAccess'],
 | |
|                 openFileParameters['FileType'],
 | |
|                 openFileParameters['IPCState'],
 | |
|                 openFileParameters['Action'],
 | |
|                 openFileParameters['ServerFid'],
 | |
|             )
 | |
| 
 | |
|     def close(self, tid, fid):
 | |
|         smb = NewSMBPacket()
 | |
|         smb['Tid']    = tid
 | |
| 
 | |
|         closeFile = SMBCommand(SMB.SMB_COM_CLOSE)
 | |
|         closeFile['Parameters'] = SMBClose_Parameters()
 | |
|         closeFile['Parameters']['FID']    = fid
 | |
|         smb.addCommand(closeFile)
 | |
| 
 | |
|         self.sendSMB(smb)
 | |
|         smb = self.recvSMB()
 | |
|         if smb.isValidAnswer(SMB.SMB_COM_CLOSE):
 | |
|            return 1
 | |
|         return 0
 | |
| 
 | |
|     def send_trans(self, tid, setup, name, param, data, noAnswer = 0):
 | |
|         smb = NewSMBPacket()
 | |
|         smb['Tid']    = tid
 | |
| 
 | |
|         transCommand = SMBCommand(SMB.SMB_COM_TRANSACTION)
 | |
|         transCommand['Parameters'] = SMBTransaction_Parameters()
 | |
|         transCommand['Data'] = SMBTransaction_Data()
 | |
| 
 | |
|         transCommand['Parameters']['Setup'] = setup
 | |
|         transCommand['Parameters']['TotalParameterCount'] = len(param)
 | |
|         transCommand['Parameters']['TotalDataCount'] = len(data)
 | |
| 
 | |
|         transCommand['Parameters']['ParameterCount'] = len(param)
 | |
|         transCommand['Parameters']['ParameterOffset'] = 32+3+28+len(setup)+len(name)
 | |
| 
 | |
|         transCommand['Parameters']['DataCount'] = len(data)
 | |
|         transCommand['Parameters']['DataOffset'] = transCommand['Parameters']['ParameterOffset'] + len(param)
 | |
| 
 | |
|         transCommand['Data']['Name'] = name
 | |
|         transCommand['Data']['Trans_Parameters'] = param
 | |
|         transCommand['Data']['Trans_Data'] = data
 | |
| 
 | |
|         if noAnswer:
 | |
|            transCommand['Parameters']['Flags'] = TRANS_NO_RESPONSE
 | |
| 
 | |
|         smb.addCommand(transCommand)
 | |
| 
 | |
|         self.sendSMB(smb)
 | |
| 
 | |
|     def send_trans2(self, tid, setup, name, param, data):
 | |
|         smb = NewSMBPacket()
 | |
|         smb['Tid']    = tid
 | |
| 
 | |
|         command = pack('<H', setup)
 | |
| 
 | |
|         transCommand = SMBCommand(SMB.SMB_COM_TRANSACTION2)
 | |
|         transCommand['Parameters'] = SMBTransaction2_Parameters()
 | |
|         transCommand['Parameters']['MaxDataCount'] = self._dialects_parameters['MaxBufferSize']
 | |
|         transCommand['Data'] = SMBTransaction2_Data()
 | |
| 
 | |
|         transCommand['Parameters']['Setup'] = command
 | |
|         transCommand['Parameters']['TotalParameterCount'] = len(param)
 | |
|         transCommand['Parameters']['TotalDataCount'] = len(data)
 | |
| 
 | |
|         if len(param) > 0:
 | |
|             padLen = (4 - (32+2+28 + len(command)) % 4 ) % 4
 | |
|             padBytes = '\xFF' * padLen
 | |
|             transCommand['Data']['Pad1'] = padBytes
 | |
|         else:
 | |
|             transCommand['Data']['Pad1'] = ''
 | |
|             padLen = 0
 | |
| 
 | |
|         transCommand['Parameters']['ParameterCount'] = len(param)
 | |
|         transCommand['Parameters']['ParameterOffset'] = 32+2+28+len(command)+len(name) + padLen
 | |
| 
 | |
|         if len(data) > 0:
 | |
|             pad2Len = (4 - (32+2+28 + len(command) + padLen + len(param)) % 4) % 4
 | |
|             transCommand['Data']['Pad2'] = '\xFF' * pad2Len
 | |
|         else:
 | |
|             transCommand['Data']['Pad2'] = ''
 | |
|             pad2Len = 0
 | |
| 
 | |
|         transCommand['Parameters']['DataCount'] = len(data)
 | |
|         transCommand['Parameters']['DataOffset'] = transCommand['Parameters']['ParameterOffset'] + len(param) + pad2Len
 | |
| 
 | |
|         transCommand['Data']['Name'] = name
 | |
|         transCommand['Data']['Trans_Parameters'] = param
 | |
|         transCommand['Data']['Trans_Data'] = data
 | |
|         smb.addCommand(transCommand)
 | |
| 
 | |
|         self.sendSMB(smb)
 | |
| 
 | |
|     def query_file_info(self, tid, fid, fileInfoClass = SMB_QUERY_FILE_STANDARD_INFO):
 | |
|         self.send_trans2(tid, SMB.TRANS2_QUERY_FILE_INFORMATION, '\x00', pack('<HH', fid, fileInfoClass), '')
 | |
| 
 | |
|         resp = self.recvSMB()
 | |
|         if resp.isValidAnswer(SMB.SMB_COM_TRANSACTION2):
 | |
|             trans2Response = SMBCommand(resp['Data'][0])
 | |
|             trans2Parameters = SMBTransaction2Response_Parameters(trans2Response['Parameters'])
 | |
|             # Remove Potential Prefix Padding
 | |
|             return trans2Response['Data'][-trans2Parameters['TotalDataCount']:]
 | |
| 
 | |
|     def __nonraw_retr_file(self, tid, fid, offset, datasize, callback):
 | |
|         if (self._dialects_parameters['Capabilities'] & SMB.CAP_LARGE_READX) and self._SignatureEnabled is False:
 | |
|             max_buf_size = 65000
 | |
|         else:
 | |
|             max_buf_size = self._dialects_parameters['MaxBufferSize'] & ~0x3ff  # Read in multiple KB blocks
 | |
| 
 | |
|         read_offset = offset
 | |
|         while read_offset < datasize:
 | |
|             data = self.read_andx(tid, fid, read_offset, max_buf_size)
 | |
| 
 | |
|             callback(data)
 | |
|             read_offset += len(data)
 | |
| 
 | |
|     def __nonraw_stor_file(self, tid, fid, offset, datasize, callback):
 | |
|         if (self._dialects_parameters['Capabilities'] & SMB.CAP_LARGE_WRITEX) and self._SignatureEnabled is False:
 | |
|             max_buf_size = 65000
 | |
|         else:
 | |
|             max_buf_size = self._dialects_parameters['MaxBufferSize'] & ~0x3ff  # Write in multiple KB blocks
 | |
| 
 | |
|         write_offset = offset
 | |
|         while 1:
 | |
|             data = callback(max_buf_size)
 | |
|             if not data:
 | |
|                 break
 | |
| 
 | |
|             smb = self.write_andx(tid,fid,data, write_offset)
 | |
|             writeResponse   = SMBCommand(smb['Data'][0])
 | |
|             writeResponseParameters = SMBWriteAndXResponse_Parameters(writeResponse['Parameters'])
 | |
|             write_offset += writeResponseParameters['Count']
 | |
| 
 | |
|     def get_server_domain(self):
 | |
|         return self.__server_domain
 | |
| 
 | |
|     def get_server_dns_domain_name(self):
 | |
|         return self.__server_dns_domain_name
 | |
| 
 | |
|     def get_server_os(self):
 | |
|         return self.__server_os
 | |
| 
 | |
|     def get_server_os_major(self):
 | |
|         return self.__server_os_major
 | |
| 
 | |
|     def get_server_os_minor(self):
 | |
|         return self.__server_os_minor
 | |
| 
 | |
|     def get_server_os_build(self):
 | |
|         return self.__server_os_build
 | |
| 
 | |
|     def set_server_os(self, os):
 | |
|         self.__server_os = os
 | |
| 
 | |
|     def get_server_lanman(self):
 | |
|         return self.__server_lanman
 | |
| 
 | |
|     def is_login_required(self):
 | |
|         # Login is required if share mode is user. 
 | |
|         # Otherwise only public services or services in share mode
 | |
|         # are allowed.
 | |
|         return (self._dialects_parameters['SecurityMode'] & SMB.SECURITY_SHARE_MASK) == SMB.SECURITY_SHARE_USER
 | |
| 
 | |
|     def is_signing_required(self):
 | |
|         return self._SignatureRequired
 | |
| 
 | |
|     def get_ntlmv1_response(self, key):
 | |
|         challenge = self._dialects_data['Challenge']
 | |
|         return ntlm.get_ntlmv1_response(key, challenge)
 | |
| 
 | |
|     def kerberos_login(self, user, password, domain = '', lmhash = '', nthash = '', aesKey = '', kdcHost = '', TGT=None, TGS=None):
 | |
|         # Importing down here so pyasn1 is not required if kerberos is not used.
 | |
|         from impacket.krb5.asn1 import AP_REQ, Authenticator, TGS_REP, seq_set
 | |
|         from impacket.krb5.kerberosv5 import getKerberosTGT, getKerberosTGS
 | |
|         from impacket.krb5 import constants
 | |
|         from impacket.krb5.types import Principal, KerberosTime, Ticket
 | |
|         from pyasn1.codec.der import decoder, encoder
 | |
|         import datetime
 | |
| 
 | |
|         # login feature does not support unicode
 | |
|         # disable it if enabled
 | |
|         flags2 = self.__flags2
 | |
|         if flags2 & SMB.FLAGS2_UNICODE:
 | |
|             self.__flags2 = flags2 & (flags2 ^ SMB.FLAGS2_UNICODE)
 | |
| 
 | |
|         # If TGT or TGS are specified, they are in the form of:
 | |
|         # TGS['KDC_REP'] = the response from the server
 | |
|         # TGS['cipher'] = the cipher used
 | |
|         # TGS['sessionKey'] = the sessionKey
 | |
|         # If we have hashes, normalize them
 | |
|         if lmhash != '' or nthash != '':
 | |
|             if len(lmhash) % 2:     lmhash = '0%s' % lmhash
 | |
|             if len(nthash) % 2:     nthash = '0%s' % nthash
 | |
|             try: # just in case they were converted already
 | |
|                 lmhash = a2b_hex(lmhash)
 | |
|                 nthash = a2b_hex(nthash)
 | |
|             except:
 | |
|                 pass
 | |
| 
 | |
|         self.__userName = user
 | |
|         self.__password = password
 | |
|         self.__domain   = domain
 | |
|         self.__lmhash   = lmhash
 | |
|         self.__nthash   = nthash
 | |
|         self.__aesKey   = aesKey
 | |
|         self.__kdc      = kdcHost
 | |
|         self.__TGT      = TGT
 | |
|         self.__TGS      = TGS
 | |
| 
 | |
|         # First of all, we need to get a TGT for the user
 | |
|         userName = Principal(user, type=constants.PrincipalNameType.NT_PRINCIPAL.value)
 | |
|         if TGT is None:
 | |
|             if TGS is None:
 | |
|                 tgt, cipher, oldSessionKey, sessionKey = getKerberosTGT(userName, password, domain, lmhash, nthash, aesKey, kdcHost)
 | |
|         else:
 | |
|             tgt = TGT['KDC_REP']
 | |
|             cipher = TGT['cipher']
 | |
|             sessionKey = TGT['sessionKey']
 | |
| 
 | |
|         # Now that we have the TGT, we should ask for a TGS for cifs
 | |
| 
 | |
|         if TGS is None:
 | |
|             serverName = Principal('cifs/%s' % self.__remote_name, type=constants.PrincipalNameType.NT_SRV_INST.value)
 | |
|             tgs, cipher, oldSessionKey, sessionKey = getKerberosTGS(serverName, domain, kdcHost, tgt, cipher, sessionKey)
 | |
|         else:
 | |
|             tgs = TGS['KDC_REP']
 | |
|             cipher = TGS['cipher']
 | |
|             sessionKey = TGS['sessionKey']
 | |
| 
 | |
|         smb = NewSMBPacket()
 | |
| 
 | |
|         # Are we required to sign SMB? If so we do it, if not we skip it
 | |
|         if self._SignatureRequired:
 | |
|            smb['Flags2'] |= SMB.FLAGS2_SMB_SECURITY_SIGNATURE
 | |
| 
 | |
| 
 | |
|         sessionSetup = SMBCommand(SMB.SMB_COM_SESSION_SETUP_ANDX)
 | |
|         sessionSetup['Parameters'] = SMBSessionSetupAndX_Extended_Parameters()
 | |
|         sessionSetup['Data']       = SMBSessionSetupAndX_Extended_Data()
 | |
| 
 | |
|         sessionSetup['Parameters']['MaxBufferSize']        = 61440
 | |
|         sessionSetup['Parameters']['MaxMpxCount']          = 2
 | |
|         sessionSetup['Parameters']['VcNumber']             = 1
 | |
|         sessionSetup['Parameters']['SessionKey']           = 0
 | |
|         sessionSetup['Parameters']['Capabilities']         = SMB.CAP_EXTENDED_SECURITY | SMB.CAP_USE_NT_ERRORS | SMB.CAP_UNICODE | SMB.CAP_LARGE_READX | SMB.CAP_LARGE_WRITEX
 | |
| 
 | |
| 
 | |
|         # Let's build a NegTokenInit with the NTLMSSP
 | |
|         # TODO: In the future we should be able to choose different providers
 | |
| 
 | |
|         blob = SPNEGO_NegTokenInit()
 | |
| 
 | |
|         # Kerberos v5 mech
 | |
|         blob['MechTypes'] = [TypesMech['MS KRB5 - Microsoft Kerberos 5']]
 | |
| 
 | |
|         # Let's extract the ticket from the TGS
 | |
|         tgs = decoder.decode(tgs, asn1Spec = TGS_REP())[0]
 | |
|         ticket = Ticket()
 | |
|         ticket.from_asn1(tgs['ticket'])
 | |
| 
 | |
|         # Now let's build the AP_REQ
 | |
|         apReq = AP_REQ()
 | |
|         apReq['pvno'] = 5
 | |
|         apReq['msg-type'] = int(constants.ApplicationTagNumbers.AP_REQ.value)
 | |
| 
 | |
|         opts = list()
 | |
|         apReq['ap-options'] = constants.encodeFlags(opts)
 | |
|         seq_set(apReq,'ticket', ticket.to_asn1)
 | |
| 
 | |
|         authenticator = Authenticator()
 | |
|         authenticator['authenticator-vno'] = 5
 | |
|         authenticator['crealm'] = domain
 | |
|         seq_set(authenticator, 'cname', userName.components_to_asn1)
 | |
|         now = datetime.datetime.utcnow()
 | |
| 
 | |
|         authenticator['cusec'] = now.microsecond
 | |
|         authenticator['ctime'] = KerberosTime.to_asn1(now)
 | |
| 
 | |
|         encodedAuthenticator = encoder.encode(authenticator)
 | |
| 
 | |
|         # Key Usage 11
 | |
|         # AP-REQ Authenticator (includes application authenticator
 | |
|         # subkey), encrypted with the application session key
 | |
|         # (Section 5.5.1)
 | |
|         encryptedEncodedAuthenticator = cipher.encrypt(sessionKey, 11, encodedAuthenticator, None)
 | |
| 
 | |
|         apReq['authenticator'] = None
 | |
|         apReq['authenticator']['etype'] = cipher.enctype
 | |
|         apReq['authenticator']['cipher'] = encryptedEncodedAuthenticator
 | |
| 
 | |
|         blob['MechToken'] = encoder.encode(apReq)
 | |
| 
 | |
|         sessionSetup['Parameters']['SecurityBlobLength']  = len(blob)
 | |
|         sessionSetup['Parameters'].getData()
 | |
|         sessionSetup['Data']['SecurityBlob']       = blob.getData()
 | |
| 
 | |
|         # Fake Data here, don't want to get us fingerprinted
 | |
|         sessionSetup['Data']['NativeOS']      = 'Unix'
 | |
|         sessionSetup['Data']['NativeLanMan']  = 'Samba'
 | |
| 
 | |
|         smb.addCommand(sessionSetup)
 | |
|         self.sendSMB(smb)
 | |
| 
 | |
|         smb = self.recvSMB()
 | |
|         if smb.isValidAnswer(SMB.SMB_COM_SESSION_SETUP_ANDX):
 | |
|             # We will need to use this uid field for all future requests/responses
 | |
|             self._uid = smb['Uid']
 | |
| 
 | |
|             # Now we have to extract the blob to continue the auth process
 | |
|             sessionResponse   = SMBCommand(smb['Data'][0])
 | |
|             sessionParameters = SMBSessionSetupAndX_Extended_Response_Parameters(sessionResponse['Parameters'])
 | |
|             sessionData       = SMBSessionSetupAndX_Extended_Response_Data(flags = smb['Flags2'])
 | |
|             sessionData['SecurityBlobLength'] = sessionParameters['SecurityBlobLength']
 | |
|             sessionData.fromString(sessionResponse['Data'])
 | |
| 
 | |
|             self._action = sessionParameters['Action']
 | |
|             # If smb sign required, let's enable it for the rest of the connection
 | |
|             if self._dialects_parameters['SecurityMode'] & SMB.SECURITY_SIGNATURES_REQUIRED:
 | |
|                self._SigningSessionKey = sessionKey.contents
 | |
|                self._SignSequenceNumber = 2
 | |
|                self._SignatureEnabled = True
 | |
| 
 | |
|             # restore unicode flag if needed
 | |
|             if flags2 & SMB.FLAGS2_UNICODE:
 | |
|                 self.__flags2 |= SMB.FLAGS2_UNICODE
 | |
| 
 | |
|             return 1
 | |
|         else:
 | |
|             raise Exception('Error: Could not login successfully')
 | |
| 
 | |
|     def login_extended(self, user, password, domain = '', lmhash = '', nthash = '', use_ntlmv2 = True ):
 | |
| 
 | |
|         # login feature does not support unicode
 | |
|         # disable it if enabled
 | |
|         flags2 = self.__flags2
 | |
|         if flags2 & SMB.FLAGS2_UNICODE:
 | |
|             self.__flags2 = flags2 & (flags2 ^ SMB.FLAGS2_UNICODE)
 | |
| 
 | |
|         # Once everything's working we should join login methods into a single one
 | |
|         smb = NewSMBPacket()
 | |
|         # Are we required to sign SMB? If so we do it, if not we skip it
 | |
|         if self._SignatureRequired:
 | |
|            smb['Flags2'] |= SMB.FLAGS2_SMB_SECURITY_SIGNATURE
 | |
| 
 | |
|         sessionSetup = SMBCommand(SMB.SMB_COM_SESSION_SETUP_ANDX)
 | |
|         sessionSetup['Parameters'] = SMBSessionSetupAndX_Extended_Parameters()
 | |
|         sessionSetup['Data']       = SMBSessionSetupAndX_Extended_Data()
 | |
| 
 | |
|         sessionSetup['Parameters']['MaxBufferSize']        = 61440
 | |
|         sessionSetup['Parameters']['MaxMpxCount']          = 2
 | |
|         sessionSetup['Parameters']['VcNumber']             = 1
 | |
|         sessionSetup['Parameters']['SessionKey']           = 0
 | |
|         sessionSetup['Parameters']['Capabilities']         = SMB.CAP_EXTENDED_SECURITY | SMB.CAP_USE_NT_ERRORS | SMB.CAP_UNICODE | SMB.CAP_LARGE_READX | SMB.CAP_LARGE_WRITEX
 | |
| 
 | |
| 
 | |
|         # Let's build a NegTokenInit with the NTLMSSP
 | |
|         # TODO: In the future we should be able to choose different providers
 | |
| 
 | |
|         blob = SPNEGO_NegTokenInit()
 | |
| 
 | |
|         # NTLMSSP
 | |
|         blob['MechTypes'] = [TypesMech['NTLMSSP - Microsoft NTLM Security Support Provider']]
 | |
|         auth = ntlm.getNTLMSSPType1('','',self._SignatureRequired, use_ntlmv2 = use_ntlmv2)
 | |
|         blob['MechToken'] = str(auth)
 | |
| 
 | |
|         sessionSetup['Parameters']['SecurityBlobLength']  = len(blob)
 | |
|         sessionSetup['Parameters'].getData()
 | |
|         sessionSetup['Data']['SecurityBlob']       = blob.getData()
 | |
| 
 | |
|         # Fake Data here, don't want to get us fingerprinted
 | |
|         sessionSetup['Data']['NativeOS']      = 'Unix'
 | |
|         sessionSetup['Data']['NativeLanMan']  = 'Samba'
 | |
| 
 | |
|         smb.addCommand(sessionSetup)
 | |
|         self.sendSMB(smb)
 | |
| 
 | |
|         smb = self.recvSMB()
 | |
|         if smb.isValidAnswer(SMB.SMB_COM_SESSION_SETUP_ANDX):
 | |
|             # We will need to use this uid field for all future requests/responses
 | |
|             self._uid = smb['Uid']
 | |
| 
 | |
|             # Now we have to extract the blob to continue the auth process
 | |
|             sessionResponse   = SMBCommand(smb['Data'][0])
 | |
|             sessionParameters = SMBSessionSetupAndX_Extended_Response_Parameters(sessionResponse['Parameters'])
 | |
|             sessionData       = SMBSessionSetupAndX_Extended_Response_Data(flags = smb['Flags2'])
 | |
|             sessionData['SecurityBlobLength'] = sessionParameters['SecurityBlobLength']
 | |
|             sessionData.fromString(sessionResponse['Data'])
 | |
|             respToken = SPNEGO_NegTokenResp(sessionData['SecurityBlob'])
 | |
| 
 | |
|             # Let's parse some data and keep it to ourselves in case it is asked
 | |
|             ntlmChallenge = ntlm.NTLMAuthChallenge(respToken['ResponseToken'])
 | |
|             if ntlmChallenge['TargetInfoFields_len'] > 0:
 | |
|                 av_pairs = ntlm.AV_PAIRS(ntlmChallenge['TargetInfoFields'][:ntlmChallenge['TargetInfoFields_len']])
 | |
|                 if av_pairs[ntlm.NTLMSSP_AV_HOSTNAME] is not None:
 | |
|                    try:
 | |
|                        self.__server_name = av_pairs[ntlm.NTLMSSP_AV_HOSTNAME][1].decode('utf-16le')
 | |
|                    except:
 | |
|                        # For some reason, we couldn't decode Unicode here.. silently discard the operation
 | |
|                        pass
 | |
|                 if av_pairs[ntlm.NTLMSSP_AV_DOMAINNAME] is not None:
 | |
|                    try:
 | |
|                        if self.__server_name != av_pairs[ntlm.NTLMSSP_AV_DOMAINNAME][1].decode('utf-16le'):
 | |
|                            self.__server_domain = av_pairs[ntlm.NTLMSSP_AV_DOMAINNAME][1].decode('utf-16le')
 | |
|                    except:
 | |
|                        # For some reason, we couldn't decode Unicode here.. silently discard the operation
 | |
|                        pass
 | |
|                 if av_pairs[ntlm.NTLMSSP_AV_DNS_DOMAINNAME] is not None:
 | |
|                    try:
 | |
|                        self.__server_dns_domain_name = av_pairs[ntlm.NTLMSSP_AV_DNS_DOMAINNAME][1].decode('utf-16le')
 | |
|                    except:
 | |
|                        # For some reason, we couldn't decode Unicode here.. silently discard the operation
 | |
|                        pass
 | |
| 
 | |
|             # Parse Version to know the target Operating system name. Not provided elsewhere anymore
 | |
|             if ntlmChallenge.fields.has_key('Version'):
 | |
|                 version = ntlmChallenge['Version']
 | |
| 
 | |
|                 if len(version) >= 4:
 | |
|                    self.__server_os_major, self.__server_os_minor, self.__server_os_build = unpack('<BBH',version[:4])
 | |
| 
 | |
|             type3, exportedSessionKey = ntlm.getNTLMSSPType3(auth, respToken['ResponseToken'], user, password, domain, lmhash, nthash, use_ntlmv2 = use_ntlmv2)
 | |
| 
 | |
|             if exportedSessionKey is not None:
 | |
|                 self._SigningSessionKey = exportedSessionKey
 | |
| 
 | |
|             smb = NewSMBPacket()
 | |
| 
 | |
|             # Are we required to sign SMB? If so we do it, if not we skip it
 | |
|             if self._SignatureRequired:
 | |
|                smb['Flags2'] |= SMB.FLAGS2_SMB_SECURITY_SIGNATURE
 | |
| 
 | |
|             respToken2 = SPNEGO_NegTokenResp()
 | |
|             respToken2['ResponseToken'] = str(type3)
 | |
| 
 | |
|             # Reusing the previous structure
 | |
|             sessionSetup['Parameters']['SecurityBlobLength'] = len(respToken2)
 | |
|             sessionSetup['Data']['SecurityBlob'] = respToken2.getData()
 | |
| 
 | |
|             # Storing some info for later use
 | |
|             self.__server_os     = sessionData['NativeOS']
 | |
|             self.__server_lanman = sessionData['NativeLanMan']
 | |
| 
 | |
|             smb.addCommand(sessionSetup)
 | |
|             self.sendSMB(smb)
 | |
| 
 | |
|             smb = self.recvSMB()
 | |
|             self._uid = 0
 | |
|             if smb.isValidAnswer(SMB.SMB_COM_SESSION_SETUP_ANDX):
 | |
|                 self._uid = smb['Uid']
 | |
|                 sessionResponse   = SMBCommand(smb['Data'][0])
 | |
|                 sessionParameters = SMBSessionSetupAndXResponse_Parameters(sessionResponse['Parameters'])
 | |
| 
 | |
|                 self._action = sessionParameters['Action']
 | |
|                 # If smb sign required, let's enable it for the rest of the connection
 | |
|                 if self._dialects_parameters['SecurityMode'] & SMB.SECURITY_SIGNATURES_REQUIRED:
 | |
|                    self._SignSequenceNumber = 2
 | |
|                    self._SignatureEnabled = True
 | |
| 
 | |
|                 # restore unicode flag if needed
 | |
|                 if flags2 & SMB.FLAGS2_UNICODE:
 | |
|                     self.__flags2 |= SMB.FLAGS2_UNICODE
 | |
| 
 | |
|                 return 1
 | |
|         else:
 | |
|             raise Exception('Error: Could not login successfully')
 | |
| 
 | |
|     def getCredentials(self):
 | |
|         return (
 | |
|             self.__userName,
 | |
|             self.__password,
 | |
|             self.__domain,
 | |
|             self.__lmhash,
 | |
|             self.__nthash,
 | |
|             self.__aesKey,
 | |
|             self.__TGT,
 | |
|             self.__TGS)
 | |
| 
 | |
|     def getIOCapabilities(self):
 | |
|         res = dict()
 | |
|         if (self._dialects_parameters['Capabilities'] & SMB.CAP_LARGE_READX) and self._SignatureEnabled is False:
 | |
|             max_size = 65000
 | |
|         else:
 | |
|             max_size = self._dialects_parameters['MaxBufferSize'] # Read in multiple KB blocks
 | |
|         res['MaxReadSize'] = max_size
 | |
|         res['MaxWriteSize'] = max_size
 | |
|         return res
 | |
| 
 | |
|     def login(self, user, password, domain = '', lmhash = '', nthash = '', ntlm_fallback = True):
 | |
| 
 | |
|         # If we have hashes, normalize them
 | |
|         if lmhash != '' or nthash != '':
 | |
|             if len(lmhash) % 2:     lmhash = '0%s' % lmhash
 | |
|             if len(nthash) % 2:     nthash = '0%s' % nthash
 | |
|             try: # just in case they were converted already
 | |
|                 lmhash = a2b_hex(lmhash)
 | |
|                 nthash = a2b_hex(nthash)
 | |
|             except:
 | |
|                 pass
 | |
| 
 | |
|         self.__userName = user
 | |
|         self.__password = password
 | |
|         self.__domain   = domain
 | |
|         self.__lmhash   = lmhash
 | |
|         self.__nthash   = nthash
 | |
|         self.__aesKey   = ''
 | |
|         self.__TGT      = None
 | |
|         self.__TGS      = None
 | |
| 
 | |
|         if self._dialects_parameters['Capabilities'] & SMB.CAP_EXTENDED_SECURITY:
 | |
|             try:
 | |
|                 self.login_extended(user, password, domain, lmhash, nthash, use_ntlmv2 = True)
 | |
|             except:
 | |
|                 # If the target OS is Windows 5.0 or Samba, let's try using NTLMv1
 | |
|                 if ntlm_fallback and ((self.get_server_lanman().find('Windows 2000') != -1) or (self.get_server_lanman().find('Samba') != -1)):
 | |
|                     self.login_extended(user, password, domain, lmhash, nthash, use_ntlmv2 = False)
 | |
|                     self.__isNTLMv2 = False
 | |
|                 else:
 | |
|                     raise
 | |
|         elif ntlm_fallback:
 | |
|             self.login_standard(user, password, domain, lmhash, nthash)
 | |
|             self.__isNTLMv2 = False
 | |
|         else:
 | |
|             raise SessionError('Cannot authenticate against target, enable ntlm_fallback')
 | |
| 
 | |
|     def login_standard(self, user, password, domain = '', lmhash = '', nthash = ''):
 | |
| 
 | |
|         # login feature does not support unicode
 | |
|         # disable it if enabled
 | |
|         flags2 = self.__flags2
 | |
|         if flags2 & SMB.FLAGS2_UNICODE:
 | |
|             self.__flags2 = flags2 & (flags2 ^ SMB.FLAGS2_UNICODE)
 | |
| 
 | |
|         # Only supports NTLMv1
 | |
|         # Password is only encrypted if the server passed us an "encryption key" during protocol dialect negotiation
 | |
|         if self._dialects_parameters['ChallengeLength'] > 0:
 | |
|             if lmhash != '' or nthash != '':
 | |
|                pwd_ansi = self.get_ntlmv1_response(lmhash)
 | |
|                pwd_unicode = self.get_ntlmv1_response(nthash)
 | |
|             elif password:
 | |
|                lmhash = ntlm.compute_lmhash(password)
 | |
|                nthash = ntlm.compute_nthash(password)
 | |
|                pwd_ansi = self.get_ntlmv1_response(lmhash)
 | |
|                pwd_unicode = self.get_ntlmv1_response(nthash)
 | |
|             else: # NULL SESSION
 | |
|                pwd_ansi = ''
 | |
|                pwd_unicode = ''
 | |
|         else:
 | |
|             pwd_ansi = password
 | |
|             pwd_unicode = ''
 | |
| 
 | |
|         smb = NewSMBPacket()
 | |
| 
 | |
|         sessionSetup = SMBCommand(SMB.SMB_COM_SESSION_SETUP_ANDX)
 | |
|         sessionSetup['Parameters'] = SMBSessionSetupAndX_Parameters()
 | |
|         sessionSetup['Data']       = SMBSessionSetupAndX_Data()
 | |
| 
 | |
|         sessionSetup['Parameters']['MaxBuffer']        = 61440
 | |
|         sessionSetup['Parameters']['MaxMpxCount']      = 2
 | |
|         sessionSetup['Parameters']['VCNumber']         = os.getpid()
 | |
|         sessionSetup['Parameters']['SessionKey']       = self._dialects_parameters['SessionKey']
 | |
|         sessionSetup['Parameters']['AnsiPwdLength']    = len(pwd_ansi)
 | |
|         sessionSetup['Parameters']['UnicodePwdLength'] = len(pwd_unicode)
 | |
|         sessionSetup['Parameters']['Capabilities']     = SMB.CAP_RAW_MODE | SMB.CAP_USE_NT_ERRORS | SMB.CAP_LARGE_READX | SMB.CAP_LARGE_WRITEX
 | |
| 
 | |
|         sessionSetup['Data']['AnsiPwd']       = pwd_ansi
 | |
|         sessionSetup['Data']['UnicodePwd']    = pwd_unicode
 | |
|         sessionSetup['Data']['Account']       = str(user)
 | |
|         sessionSetup['Data']['PrimaryDomain'] = str(domain)
 | |
|         sessionSetup['Data']['NativeOS']      = str(os.name)
 | |
|         sessionSetup['Data']['NativeLanMan']  = 'pysmb'
 | |
|         smb.addCommand(sessionSetup)
 | |
| 
 | |
|         self.sendSMB(smb)
 | |
| 
 | |
|         smb = self.recvSMB()
 | |
|         if smb.isValidAnswer(SMB.SMB_COM_SESSION_SETUP_ANDX):
 | |
|             # We will need to use this uid field for all future requests/responses
 | |
|             self._uid = smb['Uid']
 | |
|             sessionResponse   = SMBCommand(smb['Data'][0])
 | |
|             sessionParameters = SMBSessionSetupAndXResponse_Parameters(sessionResponse['Parameters'])
 | |
|             sessionData       = SMBSessionSetupAndXResponse_Data(flags = smb['Flags2'], data = sessionResponse['Data'])
 | |
| 
 | |
|             self._action = sessionParameters['Action']
 | |
| 
 | |
|             # Still gotta figure out how to do this with no EXTENDED_SECURITY
 | |
|             if sessionParameters['Action'] & SMB_SETUP_USE_LANMAN_KEY == 0:
 | |
|                  self._SigningChallengeResponse = sessionSetup['Data']['UnicodePwd']
 | |
|                  self._SigningSessionKey = nthash
 | |
|             else:
 | |
|                  self._SigningChallengeResponse = sessionSetup['Data']['AnsiPwd']
 | |
|                  self._SigningSessionKey = lmhash
 | |
| 
 | |
|             #self._SignSequenceNumber = 1
 | |
|             #self.checkSignSMB(smb, self._SigningSessionKey ,self._SigningChallengeResponse)
 | |
|             #self._SignatureEnabled = True
 | |
|             self.__server_os     = sessionData['NativeOS']
 | |
|             self.__server_lanman = sessionData['NativeLanMan']
 | |
|             self.__server_domain = sessionData['PrimaryDomain']
 | |
| 
 | |
|             # restore unicode flag if needed
 | |
|             if flags2 & SMB.FLAGS2_UNICODE:
 | |
|                 self.__flags2 |= SMB.FLAGS2_UNICODE
 | |
| 
 | |
|             return 1
 | |
|         else: raise Exception('Error: Could not login successfully')
 | |
| 
 | |
|     def waitNamedPipe(self, tid, pipe, timeout = 5, noAnswer = 0):
 | |
|         smb = NewSMBPacket()
 | |
|         smb['Tid']    = tid
 | |
| 
 | |
|         transCommand = SMBCommand(SMB.SMB_COM_TRANSACTION)
 | |
|         transCommand['Parameters'] = SMBTransaction_Parameters()
 | |
|         transCommand['Data'] = SMBTransaction_Data()
 | |
| 
 | |
|         setup = '\x53\x00\x00\x00'
 | |
|         name = '\\PIPE%s\x00' % pipe
 | |
|         transCommand['Parameters']['Setup'] = setup
 | |
|         transCommand['Parameters']['TotalParameterCount'] = 0
 | |
|         transCommand['Parameters']['TotalDataCount'] = 0
 | |
|         transCommand['Parameters']['MaxParameterCount'] = 0
 | |
|         transCommand['Parameters']['MaxDataCount'] = 0
 | |
|         transCommand['Parameters']['Timeout'] = timeout * 1000
 | |
| 
 | |
|         transCommand['Parameters']['ParameterCount'] = 0
 | |
|         transCommand['Parameters']['ParameterOffset'] = 32+3+28+len(setup)+len(name)
 | |
| 
 | |
|         transCommand['Parameters']['DataCount'] = 0
 | |
|         transCommand['Parameters']['DataOffset'] = 0
 | |
| 
 | |
|         transCommand['Data']['Name'] = name
 | |
|         transCommand['Data']['Trans_Parameters'] = ''
 | |
|         transCommand['Data']['Trans_Data'] = ''
 | |
| 
 | |
|         if noAnswer:
 | |
|            transCommand['Parameters']['Flags'] = TRANS_NO_RESPONSE
 | |
| 
 | |
|         smb.addCommand(transCommand)
 | |
|         self.sendSMB(smb)
 | |
| 
 | |
|         smb = self.recvSMB()
 | |
|         if smb.isValidAnswer(SMB.SMB_COM_TRANSACTION):
 | |
|            return 1
 | |
|         return 0
 | |
| 
 | |
|     def read(self, tid, fid, offset=0, max_size = None, wait_answer=1):
 | |
|         if not max_size:
 | |
|             max_size = self._dialects_parameters['MaxBufferSize'] # Read in multiple KB blocks
 | |
| 
 | |
|         # max_size is not working, because although it would, the server returns an error (More data avail)
 | |
| 
 | |
|         smb = NewSMBPacket()
 | |
|         smb['Tid']    = tid
 | |
| 
 | |
|         read = SMBCommand(SMB.SMB_COM_READ)
 | |
|         read['Parameters'] = SMBRead_Parameters()
 | |
|         read['Parameters']['Fid'] = fid
 | |
|         read['Parameters']['Offset'] = offset
 | |
|         read['Parameters']['Count'] = max_size
 | |
|         smb.addCommand(read)
 | |
| 
 | |
|         if wait_answer:
 | |
|             while 1:
 | |
|                 self.sendSMB(smb)
 | |
|                 ans = self.recvSMB()
 | |
| 
 | |
|                 if ans.isValidAnswer(SMB.SMB_COM_READ):
 | |
|                     readResponse   = SMBCommand(ans['Data'][0])
 | |
|                     readData       = SMBReadResponse_Data(readResponse['Data'])
 | |
| 
 | |
|                     return readData['Data']
 | |
| 
 | |
|         return None
 | |
| 
 | |
|     def read_andx(self, tid, fid, offset=0, max_size = None, wait_answer=1, smb_packet=None):
 | |
|         if not max_size:
 | |
|             if (self._dialects_parameters['Capabilities'] & SMB.CAP_LARGE_READX) and self._SignatureEnabled is False:
 | |
|                 max_size = 65000
 | |
|             else:
 | |
|                 max_size = self._dialects_parameters['MaxBufferSize'] # Read in multiple KB blocks
 | |
| 
 | |
|         # max_size is not working, because although it would, the server returns an error (More data avail)
 | |
| 
 | |
|         if smb_packet is None:
 | |
|             smb = NewSMBPacket()
 | |
|             smb['Tid']    = tid
 | |
| 
 | |
|             readAndX = SMBCommand(SMB.SMB_COM_READ_ANDX)
 | |
|             readAndX['Parameters'] = SMBReadAndX_Parameters()
 | |
|             readAndX['Parameters']['Fid'] = fid
 | |
|             readAndX['Parameters']['Offset'] = offset
 | |
|             readAndX['Parameters']['MaxCount'] = max_size
 | |
|             smb.addCommand(readAndX)
 | |
|         else:
 | |
|             smb = smb_packet
 | |
| 
 | |
|         if wait_answer:
 | |
|             answer = ''
 | |
|             while 1:
 | |
|                 self.sendSMB(smb)
 | |
|                 ans = self.recvSMB()
 | |
| 
 | |
|                 if ans.isValidAnswer(SMB.SMB_COM_READ_ANDX):
 | |
|                     # XXX Here we are only using a few fields from the response
 | |
|                     readAndXResponse   = SMBCommand(ans['Data'][0])
 | |
|                     readAndXParameters = SMBReadAndXResponse_Parameters(readAndXResponse['Parameters'])
 | |
| 
 | |
|                     offset = readAndXParameters['DataOffset']
 | |
|                     count = readAndXParameters['DataCount']+0x10000*readAndXParameters['DataCount_Hi']
 | |
|                     answer += str(ans)[offset:offset+count]
 | |
|                     if not ans.isMoreData():
 | |
|                         return answer
 | |
|                     max_size = min(max_size, readAndXParameters['Remaining'])
 | |
|                     readAndX['Parameters']['Offset'] += count                      # XXX Offset is not important (apparently)
 | |
|         else:
 | |
|             self.sendSMB(smb)
 | |
|             ans = self.recvSMB()
 | |
| 
 | |
|             try:
 | |
|                 if ans.isValidAnswer(SMB.SMB_COM_READ_ANDX):
 | |
|                     return ans
 | |
|                 else:
 | |
|                     return None
 | |
|             except:
 | |
|                 return ans
 | |
| 
 | |
|         return None
 | |
| 
 | |
|     def read_raw(self, tid, fid, offset=0, max_size = None, wait_answer=1):
 | |
|         if not max_size:
 | |
|             max_size = self._dialects_parameters['MaxBufferSize'] # Read in multiple KB blocks
 | |
| 
 | |
|         # max_size is not working, because although it would, the server returns an error (More data avail)
 | |
|         smb = NewSMBPacket()
 | |
|         smb['Tid']    = tid
 | |
| 
 | |
|         readRaw = SMBCommand(SMB.SMB_COM_READ_RAW)
 | |
|         readRaw['Parameters'] = SMBReadRaw_Parameters()
 | |
|         readRaw['Parameters']['Fid'] = fid
 | |
|         readRaw['Parameters']['Offset'] = offset
 | |
|         readRaw['Parameters']['MaxCount'] = max_size
 | |
|         smb.addCommand(readRaw)
 | |
| 
 | |
|         self.sendSMB(smb)
 | |
|         if wait_answer:
 | |
|             data = self._sess.recv_packet(self.__timeout).get_trailer()
 | |
|             if not data:
 | |
|                 # If there is no data it means there was an error
 | |
|                 data = self.read_andx(tid, fid, offset, max_size)
 | |
|             return data
 | |
| 
 | |
|         return None
 | |
| 
 | |
|     def write(self,tid,fid,data, offset = 0, wait_answer=1):
 | |
|         smb = NewSMBPacket()
 | |
|         smb['Tid']    = tid
 | |
| 
 | |
|         write = SMBCommand(SMB.SMB_COM_WRITE)
 | |
|         write['Parameters'] = SMBWrite_Parameters()
 | |
|         write['Data'] = SMBWrite_Data()
 | |
|         write['Parameters']['Fid'] = fid
 | |
|         write['Parameters']['Count'] = len(data)
 | |
|         write['Parameters']['Offset'] = offset
 | |
|         write['Parameters']['Remaining'] = len(data)
 | |
|         write['Data']['Data'] = data
 | |
|         smb.addCommand(write)
 | |
| 
 | |
|         self.sendSMB(smb)
 | |
| 
 | |
|         if wait_answer:
 | |
|             smb = self.recvSMB()
 | |
|             if smb.isValidAnswer(SMB.SMB_COM_WRITE):
 | |
|                 return smb
 | |
|         return None
 | |
| 
 | |
|     def write_andx(self,tid,fid,data, offset = 0, wait_answer=1, write_pipe_mode = False, smb_packet=None):
 | |
|         if smb_packet is None:
 | |
|             smb = NewSMBPacket()
 | |
|             smb['Tid']    = tid
 | |
| 
 | |
|             writeAndX = SMBCommand(SMB.SMB_COM_WRITE_ANDX)
 | |
|             smb.addCommand(writeAndX)
 | |
| 
 | |
|             writeAndX['Parameters'] = SMBWriteAndX_Parameters()
 | |
|             writeAndX['Parameters']['Fid'] = fid
 | |
|             writeAndX['Parameters']['Offset'] = offset
 | |
|             writeAndX['Parameters']['WriteMode'] = 8
 | |
|             writeAndX['Parameters']['Remaining'] = len(data)
 | |
|             writeAndX['Parameters']['DataLength'] = len(data)
 | |
|             writeAndX['Parameters']['DataOffset'] = len(smb)    # this length already includes the parameter
 | |
|             writeAndX['Data'] = data
 | |
| 
 | |
|             if write_pipe_mode is True:
 | |
|                 # First of all we gotta know what the MaxBuffSize is
 | |
|                 maxBuffSize = self._dialects_parameters['MaxBufferSize']
 | |
|                 if len(data) > maxBuffSize:
 | |
|                     chunks_size = maxBuffSize - 60
 | |
|                     writeAndX['Parameters']['WriteMode'] = 0x0c
 | |
|                     sendData = '\xff\xff' + data
 | |
|                     totalLen = len(sendData)
 | |
|                     writeAndX['Parameters']['DataLength'] = chunks_size
 | |
|                     writeAndX['Parameters']['Remaining'] = totalLen-2
 | |
|                     writeAndX['Data'] = sendData[:chunks_size]
 | |
| 
 | |
|                     self.sendSMB(smb)
 | |
|                     if wait_answer:
 | |
|                         smbResp = self.recvSMB()
 | |
|                         smbResp.isValidAnswer(SMB.SMB_COM_WRITE_ANDX)
 | |
| 
 | |
|                     alreadySent = chunks_size
 | |
|                     sendData = sendData[chunks_size:]
 | |
| 
 | |
|                     while alreadySent < totalLen:
 | |
|                         writeAndX['Parameters']['WriteMode'] = 0x04
 | |
|                         writeAndX['Parameters']['DataLength'] = len(sendData[:chunks_size])
 | |
|                         writeAndX['Data'] = sendData[:chunks_size]
 | |
|                         self.sendSMB(smb)
 | |
|                         if wait_answer:
 | |
|                             smbResp = self.recvSMB()
 | |
|                             smbResp.isValidAnswer(SMB.SMB_COM_WRITE_ANDX)
 | |
|                         alreadySent += writeAndX['Parameters']['DataLength']
 | |
|                         sendData = sendData[chunks_size:]
 | |
| 
 | |
|                     return smbResp
 | |
| 
 | |
|         else:
 | |
|             smb = smb_packet
 | |
| 
 | |
|         self.sendSMB(smb)
 | |
| 
 | |
|         if wait_answer:
 | |
|             smb = self.recvSMB()
 | |
|             if smb.isValidAnswer(SMB.SMB_COM_WRITE_ANDX):
 | |
|                 return smb
 | |
|         return None
 | |
| 
 | |
|     def write_raw(self,tid,fid,data, offset = 0, wait_answer=1):
 | |
|         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")
 | |
|         smb = NewSMBPacket()
 | |
|         smb['Tid']    = tid
 | |
| 
 | |
|         writeRaw = SMBCommand(SMB.SMB_COM_WRITE_RAW)
 | |
|         writeRaw['Parameters'] = SMBWriteRaw_Parameters()
 | |
|         writeRaw['Parameters']['Fid'] = fid
 | |
|         writeRaw['Parameters']['Offset'] = offset
 | |
|         writeRaw['Parameters']['Count'] = len(data)
 | |
|         writeRaw['Parameters']['DataLength'] = 0
 | |
|         writeRaw['Parameters']['DataOffset'] = 0
 | |
|         smb.addCommand(writeRaw)
 | |
| 
 | |
|         self.sendSMB(smb)
 | |
|         self._sess.send_packet(data)
 | |
| 
 | |
|         if wait_answer:
 | |
|             smb = self.recvSMB()
 | |
|             if smb.isValidAnswer(SMB.SMB_COM_WRITE_RAW):
 | |
|                 return smb
 | |
|         return None
 | |
| 
 | |
|     def TransactNamedPipe(self, tid, fid, data = '', noAnswer = 0, waitAnswer = 1, offset = 0):
 | |
|         self.send_trans(tid,pack('<HH', 0x26, fid),'\\PIPE\\\x00','',data, noAnswer = noAnswer)
 | |
| 
 | |
|         if noAnswer or not waitAnswer:
 | |
|             return
 | |
|         smb = self.recvSMB()
 | |
|         if smb.isValidAnswer(SMB.SMB_COM_TRANSACTION):
 | |
|            transResponse = SMBCommand(smb['Data'][0])
 | |
|            transParameters = SMBTransactionResponse_Parameters(transResponse['Parameters'])
 | |
|            return transResponse['Data'][-transParameters['TotalDataCount']:] # Remove Potential Prefix Padding
 | |
|         return None
 | |
| 
 | |
|     def TransactNamedPipeRecv(self):
 | |
|         s = self.recvSMB()
 | |
|         if s.isValidAnswer(SMB.SMB_COM_TRANSACTION):
 | |
|            transResponse = SMBCommand(s['Data'][0])
 | |
|            transParameters = SMBTransactionResponse_Parameters(transResponse['Parameters'])
 | |
|            return transResponse['Data'][-transParameters['TotalDataCount']:] # Remove Potential Prefix Padding
 | |
|         return None
 | |
| 
 | |
|     def nt_create_andx(self,tid,filename, smb_packet=None, cmd = None, shareAccessMode = FILE_SHARE_READ | FILE_SHARE_WRITE, disposition = FILE_OPEN, accessMask = 0x2019f):
 | |
|         filename = filename.replace('/', '\\')
 | |
|         filename = filename.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else filename
 | |
| 
 | |
|         if smb_packet is None:
 | |
|             smb = NewSMBPacket()
 | |
|             smb['Tid']    = tid
 | |
|         else:
 | |
|             smb = smb_packet
 | |
| 
 | |
|         if cmd is None:
 | |
|             ntCreate = SMBCommand(SMB.SMB_COM_NT_CREATE_ANDX)
 | |
|             ntCreate['Parameters'] = SMBNtCreateAndX_Parameters()
 | |
|             ntCreate['Data']       = SMBNtCreateAndX_Data(flags=self.__flags2)
 | |
|             ntCreate['Parameters']['FileNameLength'] = len(filename)
 | |
|             ntCreate['Parameters']['CreateFlags'] = 0x16
 | |
|             ntCreate['Parameters']['AccessMask'] = accessMask
 | |
|             ntCreate['Parameters']['CreateOptions'] = 0x40
 | |
|             ntCreate['Parameters']['ShareAccess'] = shareAccessMode
 | |
|             ntCreate['Parameters']['Disposition'] = disposition
 | |
|             ntCreate['Data']['FileName'] = filename
 | |
| 
 | |
|             if self.__flags2 & SMB.FLAGS2_UNICODE:
 | |
|                 ntCreate['Data']['Pad'] = 0x0
 | |
|         else:
 | |
|             ntCreate = cmd
 | |
| 
 | |
|         smb.addCommand(ntCreate)
 | |
| 
 | |
|         self.sendSMB(smb)
 | |
| 
 | |
|         while 1:
 | |
|             smb = self.recvSMB()
 | |
|             if smb.isValidAnswer(SMB.SMB_COM_NT_CREATE_ANDX):
 | |
|                 # XXX Here we are ignoring the rest of the response
 | |
|                 ntCreateResponse   = SMBCommand(smb['Data'][0])
 | |
|                 ntCreateParameters = SMBNtCreateAndXResponse_Parameters(ntCreateResponse['Parameters'])
 | |
| 
 | |
|                 self.fid = ntCreateParameters['Fid']
 | |
|                 return ntCreateParameters['Fid']
 | |
| 
 | |
|     def logoff(self):
 | |
|         smb = NewSMBPacket()
 | |
| 
 | |
|         logOff = SMBCommand(SMB.SMB_COM_LOGOFF_ANDX)
 | |
|         logOff['Parameters'] = SMBLogOffAndX()
 | |
|         smb.addCommand(logOff)
 | |
| 
 | |
|         self.sendSMB(smb)
 | |
|         self.recvSMB()
 | |
|         # Let's clear some fields so you can login again under the same session
 | |
|         self._uid = 0
 | |
| 
 | |
|     def list_path(self, service, path = '*', password = None):
 | |
|         path = path.replace('/', '\\')
 | |
|         path = path.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else path
 | |
| 
 | |
|         tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
 | |
|         try:
 | |
|             findFirstParameter = SMBFindFirst2_Parameters()
 | |
|             findFirstParameter['SearchAttributes'] = SMB_FILE_ATTRIBUTE_DIRECTORY | SMB_FILE_ATTRIBUTE_HIDDEN | \
 | |
|                                                      SMB_FILE_ATTRIBUTE_SYSTEM | SMB_FILE_ATTRIBUTE_READONLY | \
 | |
|                                                      SMB_FILE_ATTRIBUTE_ARCHIVE
 | |
|             findFirstParameter['SearchCount'] = 512
 | |
|             findFirstParameter['Flags'] = SMB_FIND_RETURN_RESUME_KEYS | SMB_FIND_CLOSE_AT_EOS
 | |
|             findFirstParameter['InformationLevel'] = SMB_FIND_FILE_BOTH_DIRECTORY_INFO
 | |
|             findFirstParameter['SearchStorageType'] = 0
 | |
|             findFirstParameter['FileName'] = path + ('\x00\x00' if self.__flags2 & SMB.FLAGS2_UNICODE else '\x00')
 | |
|             self.send_trans2(tid, SMB.TRANS2_FIND_FIRST2, '\x00', findFirstParameter, '')
 | |
|             files = [ ]
 | |
| 
 | |
|             totalDataCount = 1
 | |
|             findData = ''
 | |
|             findFirst2ParameterBlock = ''
 | |
|             while len(findData) < totalDataCount:
 | |
|                 resp = self.recvSMB()
 | |
| 
 | |
|                 if resp.isValidAnswer(SMB.SMB_COM_TRANSACTION2):
 | |
|                     trans2Response = SMBCommand(resp['Data'][0])
 | |
|                     trans2Parameters = SMBTransaction2Response_Parameters(trans2Response['Parameters'])
 | |
|                     totalDataCount = trans2Parameters['TotalDataCount']
 | |
|                     findFirst2ParameterBlock += trans2Response['Data'][trans2Parameters['ParameterOffset']-55:][:trans2Parameters['ParameterCount']]
 | |
|                     findData += trans2Response['Data'][trans2Parameters['DataOffset']-55:]
 | |
| 
 | |
|             findParameterBlock = SMBFindFirst2Response_Parameters(findFirst2ParameterBlock)
 | |
|             # Save the SID for resume operations
 | |
|             sid = findParameterBlock['SID']
 | |
| 
 | |
|             while True:
 | |
|                 record = SMBFindFileBothDirectoryInfo(data = findData)
 | |
| 
 | |
|                 shortname = record['ShortName'].decode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else record['ShortName']
 | |
|                 filename = record['FileName'].decode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else record['FileName']
 | |
| 
 | |
|                 fileRecord = SharedFile(record['CreationTime'], record['LastAccessTime'], record['LastChangeTime'],
 | |
|                                   record['EndOfFile'], record['AllocationSize'], record['ExtFileAttributes'],
 | |
|                                   shortname, filename)
 | |
|                 files.append(fileRecord)
 | |
|                 if record['NextEntryOffset'] > 0 and len(findData[record['NextEntryOffset']:]) > 0:
 | |
|                     findData = findData[record['NextEntryOffset']:]
 | |
|                 else:
 | |
|                     # More data to search?
 | |
|                     if findParameterBlock['EndOfSearch'] == 0:
 | |
|                         resume_filename = record['FileName']
 | |
|                         findNextParameter = SMBFindNext2_Parameters()
 | |
|                         findNextParameter['SID'] = sid
 | |
|                         findNextParameter['SearchCount'] = 1024
 | |
|                         findNextParameter['InformationLevel'] = SMB_FIND_FILE_BOTH_DIRECTORY_INFO
 | |
|                         findNextParameter['ResumeKey'] = 0
 | |
|                         findNextParameter['Flags'] = SMB_FIND_RETURN_RESUME_KEYS | SMB_FIND_CLOSE_AT_EOS
 | |
|                         findNextParameter['FileName'] = resume_filename + ('\x00\x00' if self.__flags2 & SMB.FLAGS2_UNICODE else '\x00')
 | |
|                         self.send_trans2(tid, SMB.TRANS2_FIND_NEXT2, '\x00', findNextParameter, '')
 | |
|                         findData = ''
 | |
|                         findNext2ParameterBlock = ''
 | |
|                         totalDataCount = 1
 | |
|                         while len(findData) < totalDataCount:
 | |
|                             resp = self.recvSMB()
 | |
| 
 | |
|                             if resp.isValidAnswer(SMB.SMB_COM_TRANSACTION2):
 | |
|                                 trans2Response = SMBCommand(resp['Data'][0])
 | |
|                                 trans2Parameters = SMBTransaction2Response_Parameters(trans2Response['Parameters'])
 | |
|                                 totalDataCount = trans2Parameters['TotalDataCount']
 | |
|                                 findNext2ParameterBlock += trans2Response['Data'][trans2Parameters['ParameterOffset']-55:][:trans2Parameters['ParameterCount']]
 | |
|                                 findData += trans2Response['Data'][trans2Parameters['DataOffset']-55:]
 | |
|                                 findParameterBlock = SMBFindNext2Response_Parameters(findNext2ParameterBlock)
 | |
|                     else:
 | |
|                        break
 | |
|         finally:
 | |
|             self.disconnect_tree(tid)
 | |
| 
 | |
|         return files
 | |
| 
 | |
|     def retr_file(self, service, filename, callback, mode = FILE_OPEN, offset = 0, password = None, shareAccessMode = SMB_ACCESS_READ):
 | |
|         filename = string.replace(filename, '/', '\\')
 | |
| 
 | |
|         fid = -1
 | |
|         tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
 | |
|         try:
 | |
|             fid = self.nt_create_andx(tid, filename, shareAccessMode = shareAccessMode, accessMask = 0x20089)
 | |
| 
 | |
|             res = self.query_file_info(tid, fid)
 | |
|             datasize = SMBQueryFileStandardInfo(res)['EndOfFile']
 | |
| 
 | |
|             self.__nonraw_retr_file(tid, fid, offset, datasize, callback)
 | |
|         finally:
 | |
|             if fid >= 0:
 | |
|                 self.close(tid, fid)
 | |
|             self.disconnect_tree(tid)
 | |
| 
 | |
|     def stor_file(self, service, filename, callback, mode = FILE_OVERWRITE_IF, offset = 0, password = None, shareAccessMode = SMB_ACCESS_WRITE):
 | |
|         filename = string.replace(filename, '/', '\\')
 | |
| 
 | |
|         fid = -1
 | |
|         tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
 | |
|         try:
 | |
|             fid = self.nt_create_andx(tid, filename, shareAccessMode = shareAccessMode, disposition = mode )
 | |
| 
 | |
|             self.__nonraw_stor_file(tid, fid, offset, 0, callback)
 | |
|         finally:
 | |
|             if fid >= 0:
 | |
|                 self.close(tid, fid)
 | |
|             self.disconnect_tree(tid)
 | |
| 
 | |
|     def stor_file_nonraw(self, service, filename, callback, mode = FILE_OVERWRITE_IF, offset = 0, password = None, shareAccessMode = SMB_ACCESS_WRITE ):
 | |
|         filename = string.replace(filename, '/', '\\')
 | |
| 
 | |
|         fid = -1
 | |
|         tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
 | |
|         try:
 | |
|             fid = self.nt_create_andx(tid, filename, shareAccessMode = shareAccessMode, disposition = mode)
 | |
|             self.__nonraw_stor_file(tid, fid, offset, 0, callback)
 | |
|         finally:
 | |
|             if fid >= 0:
 | |
|                 self.close(tid, fid)
 | |
|             self.disconnect_tree(tid)
 | |
| 
 | |
|     def check_dir(self, service, path, password = None):
 | |
|         path = string.replace(path,'/', '\\')
 | |
|         tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
 | |
|         try:
 | |
|             smb = NewSMBPacket()
 | |
|             smb['Tid'] = tid
 | |
|             smb['Mid'] = 0
 | |
| 
 | |
|             cmd = SMBCommand(SMB.SMB_COM_CHECK_DIRECTORY)
 | |
|             cmd['Parameters'] = ''
 | |
|             cmd['Data'] = SMBCheckDirectory_Data(flags = self.__flags2)
 | |
|             cmd['Data']['DirectoryName'] = path.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else path
 | |
|             smb.addCommand(cmd)
 | |
| 
 | |
|             self.sendSMB(smb)
 | |
| 
 | |
|             while 1:
 | |
|                 s = self.recvSMB()
 | |
|                 if s.isValidAnswer(SMB.SMB_COM_CHECK_DIRECTORY):
 | |
|                     return
 | |
|         finally:
 | |
|             self.disconnect_tree(tid)
 | |
| 
 | |
|     def remove(self, service, path, password = None):
 | |
|         path = string.replace(path,'/', '\\')
 | |
|         # Perform a list to ensure the path exists
 | |
|         self.list_path(service, path, password)
 | |
| 
 | |
|         tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
 | |
|         try:
 | |
|             smb = NewSMBPacket()
 | |
|             smb['Tid'] = tid
 | |
|             smb['Mid'] = 0
 | |
| 
 | |
|             cmd = SMBCommand(SMB.SMB_COM_DELETE)
 | |
|             cmd['Parameters'] = SMBDelete_Parameters()
 | |
|             cmd['Parameters']['SearchAttributes'] = ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE
 | |
|             cmd['Data'] = SMBDelete_Data(flags = self.__flags2)
 | |
|             cmd['Data']['FileName'] = (path + '\x00').encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else (path + '\x00')
 | |
|             smb.addCommand(cmd)
 | |
| 
 | |
|             self.sendSMB(smb)
 | |
| 
 | |
|             while 1:
 | |
|                 s = self.recvSMB()
 | |
|                 if s.isValidAnswer(SMB.SMB_COM_DELETE):
 | |
|                     return
 | |
|         finally:
 | |
|             self.disconnect_tree(tid)
 | |
| 
 | |
|     def rmdir(self, service, path, password = None):
 | |
|         path = string.replace(path,'/', '\\')
 | |
|         # Check that the directory exists
 | |
|         self.check_dir(service, path, password)
 | |
| 
 | |
|         tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
 | |
|         try:
 | |
|             path = path.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else path
 | |
| 
 | |
|             smb = NewSMBPacket()
 | |
|             smb['Tid'] = tid
 | |
|             createDir = SMBCommand(SMB.SMB_COM_DELETE_DIRECTORY)
 | |
|             createDir['Data'] = SMBDeleteDirectory_Data(flags=self.__flags2)
 | |
|             createDir['Data']['DirectoryName'] = path
 | |
|             smb.addCommand(createDir)
 | |
| 
 | |
|             self.sendSMB(smb)
 | |
| 
 | |
|             while 1:
 | |
|                 s = self.recvSMB()
 | |
|                 if s.isValidAnswer(SMB.SMB_COM_DELETE_DIRECTORY):
 | |
|                     return
 | |
|         finally:
 | |
|             self.disconnect_tree(tid)
 | |
| 
 | |
|     def mkdir(self, service, path, password = None):
 | |
|         path = string.replace(path,'/', '\\')
 | |
|         tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
 | |
|         try:
 | |
|             path = path.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else path
 | |
| 
 | |
|             smb = NewSMBPacket()
 | |
|             smb['Tid'] = tid
 | |
|             smb['Mid'] = 0
 | |
| 
 | |
|             createDir = SMBCommand(SMB.SMB_COM_CREATE_DIRECTORY)
 | |
|             createDir['Data'] = SMBCreateDirectory_Data(flags=self.__flags2)
 | |
|             createDir['Data']['DirectoryName'] = path
 | |
|             smb.addCommand(createDir)
 | |
| 
 | |
|             self.sendSMB(smb)
 | |
| 
 | |
|             smb = self.recvSMB()
 | |
|             if smb.isValidAnswer(SMB.SMB_COM_CREATE_DIRECTORY):
 | |
|                 return 1
 | |
|             return 0
 | |
|         finally:
 | |
|             self.disconnect_tree(tid)
 | |
| 
 | |
|     def rename(self, service, old_path, new_path, password = None):
 | |
|         old_path = string.replace(old_path,'/', '\\')
 | |
|         new_path = string.replace(new_path,'/', '\\')
 | |
|         tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
 | |
|         try:
 | |
|             smb = NewSMBPacket()
 | |
|             smb['Tid'] = tid
 | |
|             smb['Mid'] = 0
 | |
| 
 | |
|             renameCmd = SMBCommand(SMB.SMB_COM_RENAME)
 | |
|             renameCmd['Parameters'] = SMBRename_Parameters()
 | |
|             renameCmd['Parameters']['SearchAttributes'] = ATTR_SYSTEM | ATTR_HIDDEN | ATTR_DIRECTORY
 | |
|             renameCmd['Data'] = SMBRename_Data(flags = self.__flags2)
 | |
|             renameCmd['Data']['OldFileName'] = old_path.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else old_path
 | |
|             renameCmd['Data']['NewFileName'] = new_path.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else new_path
 | |
|             smb.addCommand(renameCmd)
 | |
| 
 | |
|             self.sendSMB(smb)
 | |
| 
 | |
|             smb = self.recvSMB()
 | |
|             if smb.isValidAnswer(SMB.SMB_COM_RENAME):
 | |
|                return 1
 | |
|             return 0
 | |
|         finally:
 | |
|             self.disconnect_tree(tid)
 | |
| 
 | |
|     def writeFile(self, treeId, fileId, data, offset = 0):
 | |
|         if (self._dialects_parameters['Capabilities'] & SMB.CAP_LARGE_WRITEX) and self._SignatureEnabled is False:
 | |
|             max_buf_size = 65000
 | |
|         else:
 | |
|             max_buf_size = self._dialects_parameters['MaxBufferSize'] & ~0x3ff  # Write in multiple KB blocks
 | |
| 
 | |
|         write_offset = offset
 | |
|         while 1:
 | |
|             if len(data) == 0:
 | |
|                 break
 | |
|             writeData = data[:max_buf_size]
 | |
|             data = data[max_buf_size:]
 | |
| 
 | |
|             smb = self.write_andx(treeId,fileId,writeData, write_offset)
 | |
|             writeResponse   = SMBCommand(smb['Data'][0])
 | |
|             writeResponseParameters = SMBWriteAndXResponse_Parameters(writeResponse['Parameters'])
 | |
|             write_offset += writeResponseParameters['Count']
 | |
| 
 | |
|     def get_socket(self):
 | |
|         return self._sess.get_socket()
 | |
| 
 | |
| ERRDOS = { 1: 'Invalid function',
 | |
|            2: 'File not found',
 | |
|            3: 'Invalid directory',
 | |
|            4: 'Too many open files',
 | |
|            5: 'Access denied',
 | |
|            6: 'Invalid file handle. Please file a bug report.',
 | |
|            7: 'Memory control blocks destroyed',
 | |
|            8: 'Out of memory',
 | |
|            9: 'Invalid memory block address',
 | |
|            10: 'Invalid environment',
 | |
|            11: 'Invalid format',
 | |
|            12: 'Invalid open mode',
 | |
|            13: 'Invalid data',
 | |
|            15: 'Invalid drive',
 | |
|            16: 'Attempt to remove server\'s current directory',
 | |
|            17: 'Not the same device',
 | |
|            18: 'No files found',
 | |
|            32: 'Sharing mode conflicts detected',
 | |
|            33: 'Lock request conflicts detected',
 | |
|            80: 'File already exists'
 | |
|            }
 | |
| 
 | |
| ERRSRV = { 1: 'Non-specific error',
 | |
|            2: 'Bad password',
 | |
|            4: 'Access denied',
 | |
|            5: 'Invalid tid. Please file a bug report.',
 | |
|            6: 'Invalid network name',
 | |
|            7: 'Invalid device',
 | |
|            49: 'Print queue full',
 | |
|            50: 'Print queue full',
 | |
|            51: 'EOF on print queue dump',
 | |
|            52: 'Invalid print file handle',
 | |
|            64: 'Command not recognized. Please file a bug report.',
 | |
|            65: 'Internal server error',
 | |
|            67: 'Invalid path',
 | |
|            69: 'Invalid access permissions',
 | |
|            71: 'Invalid attribute mode',
 | |
|            81: 'Server is paused',
 | |
|            82: 'Not receiving messages',
 | |
|            83: 'No room to buffer messages',
 | |
|            87: 'Too many remote user names',
 | |
|            88: 'Operation timeout',
 | |
|            89: 'Out of resources',
 | |
|            91: 'Invalid user handle. Please file a bug report.',
 | |
|            250: 'Temporarily unable to support raw mode for transfer',
 | |
|            251: 'Temporarily unable to support raw mode for transfer',
 | |
|            252: 'Continue in MPX mode',
 | |
|            65535: 'Unsupported function'
 | |
|            }
 | |
| 
 | |
| ERRHRD = { 19: 'Media is write-protected',
 | |
|            20: 'Unknown unit',
 | |
|            21: 'Drive not ready',
 | |
|            22: 'Unknown command',
 | |
|            23: 'CRC error',
 | |
|            24: 'Bad request',
 | |
|            25: 'Seek error',
 | |
|            26: 'Unknown media type',
 | |
|            27: 'Sector not found',
 | |
|            28: 'Printer out of paper',
 | |
|            29: 'Write fault',
 | |
|            30: 'Read fault',
 | |
|            31: 'General failure',
 | |
|            32: 'Open conflicts with an existing open',
 | |
|            33: 'Invalid lock request',
 | |
|            34: 'Wrong disk in drive',
 | |
|            35: 'FCBs not available',
 | |
|            36: 'Sharing buffer exceeded'
 | |
|            }
 | |
| 
 |