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