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