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

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