Coverage for /root/GitHubProjects/impacket/impacket/smb.py : 68%

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