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@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
42import os
43import socket
44import string
45from binascii import a2b_hex
46import datetime
47from struct import pack, unpack
48from contextlib import contextmanager
49
50from impacket import nmb, ntlm, nt_errors, LOG
51from impacket.structure import Structure
52from impacket.spnego import SPNEGO_NegTokenInit, TypesMech, SPNEGO_NegTokenResp
53
54# For signing
55import hashlib
56
57unicode_support = 0
58unicode_convert = 1
59
60try:
61    from cStringIO import StringIO
62except ImportError:
63    from StringIO import StringIO
64
65# Dialect for SMB1
66SMB_DIALECT = 'NT LM 0.12'
67
68# Shared Device Type
69SHARED_DISK                      = 0x00
70SHARED_DISK_HIDDEN               = 0x80000000
71SHARED_PRINT_QUEUE               = 0x01
72SHARED_DEVICE                    = 0x02
73SHARED_IPC                       = 0x03
74
75# Extended attributes mask
76ATTR_ARCHIVE                     = 0x020
77ATTR_COMPRESSED                  = 0x800
78ATTR_NORMAL                      = 0x080
79ATTR_HIDDEN                      = 0x002
80ATTR_READONLY                    = 0x001
81ATTR_TEMPORARY                   = 0x100
82ATTR_DIRECTORY                   = 0x010
83ATTR_SYSTEM                      = 0x004
84
85# Service Type
86SERVICE_DISK                     = 'A:'
87SERVICE_PRINTER                  = 'LPT1:'
88SERVICE_IPC                      = 'IPC'
89SERVICE_COMM                     = 'COMM'
90SERVICE_ANY                      = '?????'
91
92# Server Type (Can be used to mask with SMBMachine.get_type() or SMBDomain.get_type())
93SV_TYPE_WORKSTATION              = 0x00000001
94SV_TYPE_SERVER                   = 0x00000002
95SV_TYPE_SQLSERVER                = 0x00000004
96SV_TYPE_DOMAIN_CTRL              = 0x00000008
97SV_TYPE_DOMAIN_BAKCTRL           = 0x00000010
98SV_TYPE_TIME_SOURCE              = 0x00000020
99SV_TYPE_AFP                      = 0x00000040
100SV_TYPE_NOVELL                   = 0x00000080
101SV_TYPE_DOMAIN_MEMBER            = 0x00000100
102SV_TYPE_PRINTQ_SERVER            = 0x00000200
103SV_TYPE_DIALIN_SERVER            = 0x00000400
104SV_TYPE_XENIX_SERVER             = 0x00000800
105SV_TYPE_NT                       = 0x00001000
106SV_TYPE_WFW                      = 0x00002000
107SV_TYPE_SERVER_NT                = 0x00004000
108SV_TYPE_POTENTIAL_BROWSER        = 0x00010000
109SV_TYPE_BACKUP_BROWSER           = 0x00020000
110SV_TYPE_MASTER_BROWSER           = 0x00040000
111SV_TYPE_DOMAIN_MASTER            = 0x00080000
112SV_TYPE_LOCAL_LIST_ONLY          = 0x40000000
113SV_TYPE_DOMAIN_ENUM              = 0x80000000
114
115# Options values for SMB.stor_file and SMB.retr_file
116SMB_O_CREAT                      = 0x10   # Create the file if file does not exists. Otherwise, operation fails.
117SMB_O_EXCL                       = 0x00   # When used with SMB_O_CREAT, operation fails if file exists. Cannot be used with SMB_O_OPEN.
118SMB_O_OPEN                       = 0x01   # Open the file if the file exists
119SMB_O_TRUNC                      = 0x02   # Truncate the file if the file exists
120
121# Share Access Mode
122SMB_SHARE_COMPAT                 = 0x00
123SMB_SHARE_DENY_EXCL              = 0x10
124SMB_SHARE_DENY_WRITE             = 0x20
125SMB_SHARE_DENY_READEXEC          = 0x30
126SMB_SHARE_DENY_NONE              = 0x40
127SMB_ACCESS_READ                  = 0x00
128SMB_ACCESS_WRITE                 = 0x01
129SMB_ACCESS_READWRITE             = 0x02
130SMB_ACCESS_EXEC                  = 0x03
131
132TRANS_DISCONNECT_TID             = 1
133TRANS_NO_RESPONSE                = 2
134
135STATUS_SUCCESS                   = 0x00000000
136STATUS_LOGON_FAILURE             = 0xC000006D
137STATUS_LOGON_TYPE_NOT_GRANTED    = 0xC000015B
138MAX_TFRAG_SIZE                   = 5840
139EVASION_NONE                     = 0
140EVASION_LOW                      = 1
141EVASION_HIGH                     = 2
142EVASION_MAX                      = 3
143RPC_X_BAD_STUB_DATA              = 0x6F7
144
145# SMB_FILE_ATTRIBUTES
146
147SMB_FILE_ATTRIBUTE_NORMAL        = 0x0000
148SMB_FILE_ATTRIBUTE_READONLY      = 0x0001
149SMB_FILE_ATTRIBUTE_HIDDEN        = 0x0002
150SMB_FILE_ATTRIBUTE_SYSTEM        = 0x0004
151SMB_FILE_ATTRIBUTE_VOLUME        = 0x0008
152SMB_FILE_ATTRIBUTE_DIRECTORY     = 0x0010
153SMB_FILE_ATTRIBUTE_ARCHIVE       = 0x0020
154SMB_SEARCH_ATTRIBUTE_READONLY    = 0x0100
155SMB_SEARCH_ATTRIBUTE_HIDDEN      = 0x0200
156SMB_SEARCH_ATTRIBUTE_SYSTEM      = 0x0400
157SMB_SEARCH_ATTRIBUTE_DIRECTORY   = 0x1000
158SMB_SEARCH_ATTRIBUTE_ARCHIVE     = 0x2000
159
160# Session SetupAndX Action flags
161SMB_SETUP_GUEST                  = 0x01
162SMB_SETUP_USE_LANMAN_KEY         = 0x02
163
164# QUERY_INFORMATION levels
165SMB_INFO_ALLOCATION              = 0x0001
166SMB_INFO_VOLUME                  = 0x0002
167FILE_FS_SIZE_INFORMATION         = 0x0003
168SMB_QUERY_FS_VOLUME_INFO         = 0x0102
169SMB_QUERY_FS_SIZE_INFO           = 0x0103
170SMB_QUERY_FILE_EA_INFO           = 0x0103
171SMB_QUERY_FS_DEVICE_INFO         = 0x0104
172SMB_QUERY_FS_ATTRIBUTE_INFO      = 0x0105
173SMB_QUERY_FILE_BASIC_INFO        = 0x0101
174SMB_QUERY_FILE_STANDARD_INFO     = 0x0102
175SMB_QUERY_FILE_ALL_INFO          = 0x0107
176FILE_FS_FULL_SIZE_INFORMATION    = 0x03EF
177
178# SET_INFORMATION levels
179SMB_SET_FILE_DISPOSITION_INFO    = 0x0102
180SMB_SET_FILE_BASIC_INFO          = 0x0101
181SMB_SET_FILE_END_OF_FILE_INFO    = 0x0104
182
183
184# File System Attributes
185FILE_CASE_SENSITIVE_SEARCH       = 0x00000001
186FILE_CASE_PRESERVED_NAMES        = 0x00000002
187FILE_UNICODE_ON_DISK             = 0x00000004
188FILE_PERSISTENT_ACLS             = 0x00000008
189FILE_FILE_COMPRESSION            = 0x00000010
190FILE_VOLUME_IS_COMPRESSED        = 0x00008000
191
192# FIND_FIRST2 flags and levels
193SMB_FIND_CLOSE_AFTER_REQUEST     = 0x0001
194SMB_FIND_CLOSE_AT_EOS            = 0x0002
195SMB_FIND_RETURN_RESUME_KEYS      = 0x0004
196SMB_FIND_CONTINUE_FROM_LAST      = 0x0008
197SMB_FIND_WITH_BACKUP_INTENT      = 0x0010
198
199FILE_DIRECTORY_FILE              = 0x00000001
200FILE_DELETE_ON_CLOSE             = 0x00001000
201FILE_NON_DIRECTORY_FILE          = 0x00000040
202
203SMB_FIND_INFO_STANDARD           = 0x0001
204SMB_FIND_FILE_DIRECTORY_INFO     = 0x0101
205SMB_FIND_FILE_FULL_DIRECTORY_INFO= 0x0102
206SMB_FIND_FILE_NAMES_INFO         = 0x0103
207SMB_FIND_FILE_BOTH_DIRECTORY_INFO= 0x0104
208SMB_FIND_FILE_ID_FULL_DIRECTORY_INFO = 0x105
209SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO = 0x106
210
211
212# DesiredAccess flags
213FILE_READ_DATA                   = 0x00000001
214FILE_WRITE_DATA                  = 0x00000002
215FILE_APPEND_DATA                 = 0x00000004
216FILE_EXECUTE                     = 0x00000020
217MAXIMUM_ALLOWED                  = 0x02000000
218GENERIC_ALL                      = 0x10000000
219GENERIC_EXECUTE                  = 0x20000000
220GENERIC_WRITE                    = 0x40000000
221GENERIC_READ                     = 0x80000000
222
223# ShareAccess flags
224FILE_SHARE_NONE                  = 0x00000000
225FILE_SHARE_READ                  = 0x00000001
226FILE_SHARE_WRITE                 = 0x00000002
227FILE_SHARE_DELETE                = 0x00000004
228
229# CreateDisposition flags
230FILE_SUPERSEDE                  = 0x00000000
231FILE_OPEN                       = 0x00000001
232FILE_CREATE                     = 0x00000002
233FILE_OPEN_IF                    = 0x00000003
234FILE_OVERWRITE                  = 0x00000004
235FILE_OVERWRITE_IF               = 0x00000005
236
237def 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
253class 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
529class UnsupportedFeature(Exception): pass
530
531# Contains information about a SMB shared device/service
532class 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
552class 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 & 0xffffffff
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 & 0xfff00000)) * 1.0e-7 - geo_cal_offset
635
636
637# Contain information about a SMB machine
638class 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
647class 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
657class 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 ('Flags2' in self.fields) is False:
680             self['Flags2'] = 0
681        if ('Flags1' in self.fields) is False:
682             self['Flags1'] = 0
683
684        if 'data' not in kargs:
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
717class 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
738class 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
748class SMBCommand_Parameters(Structure):
749    pass
750
751class 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
765class SMBQueryFsAttributeInfo(Structure):
766    structure = (
767        ('FileSystemAttributes','<L'),
768        ('MaxFilenNameLengthInBytes','<L'),
769        ('LengthOfFileSystemName','<L-FileSystemName'),
770        ('FileSystemName',':'),
771    )
772
773class 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
786class 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
795class 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
803class 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
812class 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
821class 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
851class 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
877class 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
911class 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
933class 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
948class 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
972class 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
996class SMBSetFileDispositionInfo(Structure):
997    structure = (
998        ('DeletePending','<B'),
999    )
1000
1001# SMB_SET_FILE_BASIC_INFO
1002class 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
1013class 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
1023class 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
1036class SMBSetFileEndOfFileInfo(Structure):
1037    structure = (
1038        ('EndOfFile','<q'),
1039    )
1040
1041# TRANS2_FIND_NEXT2
1042class 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
1057class SMBFindNext2Response_Parameters(Structure):
1058     structure = (
1059         ('SearchCount','<H'),
1060         ('EndOfSearch','<H=1'),
1061         ('EaErrorOffset','<H=0'),
1062         ('LastNameOffset','<H=0'),
1063     )
1064
1065class SMBFindNext2_Data(Structure):
1066     structure = (
1067         ('GetExtendedAttributesListLength','_-GetExtendedAttributesList', 'self["GetExtendedAttributesListLength"]'),
1068         ('GetExtendedAttributesList',':'),
1069     )
1070
1071
1072# TRANS2_FIND_FIRST2
1073class 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
1082class 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
1097class SMBFindFirst2_Data(Structure):
1098     structure = (
1099         ('GetExtendedAttributesListLength','_-GetExtendedAttributesList', 'self["GetExtendedAttributesListLength"]'),
1100         ('GetExtendedAttributesList',':'),
1101     )
1102
1103# TRANS2_SET_PATH_INFORMATION
1104class 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
1116class SMBSetPathInformationResponse_Parameters(Structure):
1117    structure = (
1118        ('EaErrorOffset','<H=0'),
1119    )
1120
1121# TRANS2_SET_FILE_INFORMATION
1122class SMBSetFileInformation_Parameters(Structure):
1123    structure = (
1124        ('FID','<H'),
1125        ('InformationLevel','<H'),
1126        ('Reserved','<H'),
1127    )
1128
1129class SMBSetFileInformationResponse_Parameters(Structure):
1130    structure = (
1131        ('EaErrorOffset','<H=0'),
1132    )
1133
1134# TRANS2_QUERY_FILE_INFORMATION
1135class SMBQueryFileInformation_Parameters(Structure):
1136    structure = (
1137        ('FID','<H'),
1138        ('InformationLevel','<H'),
1139    )
1140
1141class SMBQueryFileInformationResponse_Parameters(Structure):
1142    structure = (
1143        ('EaErrorOffset','<H=0'),
1144    )
1145
1146class SMBQueryFileInformation_Data(Structure):
1147    structure = (
1148        ('GetExtendedAttributeList',':'),
1149    )
1150
1151# TRANS2_QUERY_PATH_INFORMATION
1152class SMBQueryPathInformationResponse_Parameters(Structure):
1153    structure = (
1154        ('EaErrorOffset','<H=0'),
1155    )
1156
1157class 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
1169class SMBQueryPathInformation_Data(Structure):
1170    structure = (
1171        ('GetExtendedAttributeList',':'),
1172    )
1173
1174
1175# SMB_QUERY_FILE_EA_INFO
1176class SMBQueryFileEaInfo(Structure):
1177    structure = (
1178        ('EaSize','<L=0'),
1179    )
1180
1181# SMB_QUERY_FILE_BASIC_INFO
1182class 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
1193class 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
1203class 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
1223class SMBNetShareEnum(Structure):
1224    structure = (
1225        ('RAPOpcode','<H=0'),
1226        ('ParamDesc','z'),
1227        ('DataDesc','z'),
1228        ('InfoLevel','<H'),
1229        ('ReceiveBufferSize','<H'),
1230    )
1231
1232class SMBNetShareEnumResponse(Structure):
1233    structure = (
1234        ('Status','<H=0'),
1235        ('Convert','<H=0'),
1236        ('EntriesReturned','<H'),
1237        ('EntriesAvailable','<H'),
1238    )
1239
1240class 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
1250class SMBNetServerGetInfoResponse(Structure):
1251    structure = (
1252        ('Status','<H=0'),
1253        ('Convert','<H=0'),
1254        ('TotalBytesAvailable','<H'),
1255    )
1256
1257class 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
1269class 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
1279class SMBNetShareGetInfoResponse(Structure):
1280    structure = (
1281        ('Status','<H=0'),
1282        ('Convert','<H=0'),
1283        ('TotalBytesAvailable','<H'),
1284    )
1285
1286############# Security Features
1287class SecurityFeatures(Structure):
1288    structure = (
1289        ('Key','<L=0'),
1290        ('CID','<H=0'),
1291        ('SequenceNumber','<H=0'),
1292    )
1293
1294############# SMB_COM_QUERY_INFORMATION2 (0x23)
1295class SMBQueryInformation2_Parameters(Structure):
1296    structure = (
1297        ('Fid','<H'),
1298    )
1299
1300class 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)
1316class 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
1328class 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
1339class 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
1362class 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
1377class SMBSessionSetupAndXResponse_Parameters(SMBAndXCommand_Parameters):
1378    structure = (
1379        ('Action','<H'),
1380    )
1381
1382class SMBSessionSetupAndX_Extended_Response_Parameters(SMBAndXCommand_Parameters):
1383    structure = (
1384        ('Action','<H=0'),
1385        ('SecurityBlobLength','<H'),
1386    )
1387
1388class 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
1401class 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)
1417class SMBTreeConnect_Parameters(SMBCommand_Parameters):
1418    structure = (
1419    )
1420
1421class 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)
1432class SMBTreeConnectAndX_Parameters(SMBAndXCommand_Parameters):
1433    structure = (
1434        ('Flags','<H=0'),
1435        ('PasswordLength','<H'),
1436    )
1437
1438class SMBTreeConnectAndXResponse_Parameters(SMBAndXCommand_Parameters):
1439    structure = (
1440        ('OptionalSupport','<H=0'),
1441    )
1442
1443class SMBTreeConnectAndXExtendedResponse_Parameters(SMBAndXCommand_Parameters):
1444    structure = (
1445        ('OptionalSupport','<H=1'),
1446        ('MaximalShareAccessRights','<L=0x1fffff'),
1447        ('GuestMaximalShareAccessRights','<L=0x1fffff'),
1448    )
1449
1450class 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
1465class 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)
1480class 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
1497class 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
1515class 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
1538class 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)
1548class 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
1560class SMBOpenAndX_Data(SMBNtCreateAndX_Data):
1561    pass
1562
1563class 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)
1578class SMBWrite_Parameters(SMBCommand_Parameters):
1579    structure = (
1580        ('Fid','<H'),
1581        ('Count','<H'),
1582        ('Offset','<L'),
1583        ('Remaining','<H'),
1584    )
1585
1586class SMBWriteResponse_Parameters(SMBCommand_Parameters):
1587    structure = (
1588        ('Count','<H'),
1589    )
1590
1591class SMBWrite_Data(Structure):
1592    structure = (
1593        ('BufferFormat','<B=1'),
1594        ('DataLength','<H-Data'),
1595        ('Data',':'),
1596    )
1597
1598
1599############# SMB_COM_WRITE_ANDX (0x2F)
1600class 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
1613class 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
1622class 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
1632class 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
1644class SMBWriteAndXResponse_Parameters(SMBAndXCommand_Parameters):
1645    structure = (
1646        ('Count','<H'),
1647        ('Available','<H'),
1648        ('Reserved','<L=0'),
1649    )
1650
1651############# SMB_COM_WRITE_RAW (0x1D)
1652class 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)
1666class SMBRead_Parameters(SMBCommand_Parameters):
1667    structure = (
1668        ('Fid','<H'),
1669        ('Count','<H'),
1670        ('Offset','<L'),
1671        ('Remaining','<H=Count'),
1672    )
1673
1674class SMBReadResponse_Parameters(Structure):
1675    structure = (
1676        ('Count','<H=0'),
1677        ('_reserved','8s=""'),
1678    )
1679
1680class SMBReadResponse_Data(Structure):
1681    structure = (
1682        ('BufferFormat','<B=0x1'),
1683        ('DataLength','<H-Data'),
1684        ('Data',':'),
1685    )
1686
1687############# SMB_COM_READ_RAW (0x1A)
1688class 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)
1699class 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
1717class 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
1733class 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
1745class 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)
1759class 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
1771class 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
1786class 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
1807class 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
1824class 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
1838class 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
1852class 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
1863class SMBQueryInformationResponse_Parameters(Structure):
1864    structure = (
1865        ('FileAttributes','<H'),
1866        ('LastWriteTime','<L'),
1867        ('FileSize','<L'),
1868        ('Reserved','"0123456789'),
1869    )
1870
1871############# SMB_COM_TRANSACTION (0x25)
1872class 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
1893class 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
1912class 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
1929class 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
1939class 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)
1948class 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
1959class 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
1969class 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)
1981class SMBEcho_Data(Structure):
1982    structure = (
1983        ('Data',':'),
1984    )
1985
1986class SMBEcho_Parameters(Structure):
1987    structure = (
1988        ('EchoCount','<H'),
1989    )
1990
1991class SMBEchoResponse_Data(Structure):
1992    structure = (
1993        ('Data',':'),
1994    )
1995
1996class SMBEchoResponse_Parameters(Structure):
1997    structure = (
1998        ('SequenceNumber','<H=1'),
1999    )
2000
2001############# SMB_COM_QUERY_INFORMATION_DISK (0x80)
2002class 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)
2013class SMBLogOffAndX(SMBAndXCommand_Parameters):
2014    strucure = ()
2015
2016############# SMB_COM_CLOSE (0x04)
2017class SMBClose_Parameters(SMBCommand_Parameters):
2018   structure = (
2019        ('FID','<H'),
2020        ('Time','<L=0'),
2021   )
2022
2023############# SMB_COM_FLUSH (0x05)
2024class SMBFlush_Parameters(SMBCommand_Parameters):
2025   structure = (
2026        ('FID','<H'),
2027   )
2028
2029############# SMB_COM_CREATE_DIRECTORY (0x00)
2030class 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)
2041class SMBDelete_Data(AsciiOrUnicodeStructure):
2042    AsciiStructure = (
2043        ('BufferFormat','<B=4'),
2044        ('FileName','z'),
2045    )
2046    UnicodeStructure = (
2047        ('BufferFormat','<B=4'),
2048        ('FileName','u'),
2049    )
2050
2051class SMBDelete_Parameters(Structure):
2052    structure = (
2053        ('SearchAttributes','<H'),
2054    )
2055
2056############# SMB_COM_DELETE_DIRECTORY (0x01)
2057class 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)
2068class 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)
2079class SMBRename_Parameters(SMBCommand_Parameters):
2080    structure = (
2081        ('SearchAttributes','<H'),
2082    )
2083
2084class 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)
2101class SMBOpen_Parameters(SMBCommand_Parameters):
2102    structure = (
2103        ('DesiredAccess','<H=0'),
2104        ('SearchAttributes','<H=0'),
2105    )
2106
2107class SMBOpen_Data(AsciiOrUnicodeStructure):
2108    AsciiStructure = (
2109        ('FileNameFormat','"\x04'),
2110        ('FileName','z'),
2111    )
2112    UnicodeStructure = (
2113        ('FileNameFormat','"\x04'),
2114        ('FileName','z'),
2115    )
2116
2117class 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
2127class 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
2143class SMBExtended_Security_Data(Structure):
2144    structure = (
2145        ('ServerGUID','16s'),
2146        ('SecurityBlob',':'),
2147    )
2148
2149class 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
2165class 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
2183class 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 'Challenge' in self._dialects_data.fields:
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 'Version' in ntlmChallenge.fields:
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
4030ERRDOS = { 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
4052ERRSRV = { 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
4080ERRHRD = { 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