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

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

## 2132 statements

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)

29

30# Todo:

31# [ ] Try [SMB]transport fragmentation using Transact requests

32# [ ] Try other methods of doing write (write_raw, transact2, write, write_and_unlock, write_and_close, write_mpx)

33# [-] Try replacements for SMB_COM_NT_CREATE_ANDX (CREATE, T_TRANSACT_CREATE, OPEN_ANDX works

34# [x] Fix forceWriteAndx, which needs to send a RecvRequest, because recv() will not send it

35# [x] Fix Recv() when using RecvAndx and the answer comes splet in several packets

36# [ ] Try [SMB]transport fragmentation with 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

41 from __future__ import division

42 from __future__ import print_function

43 import os

44 import socket

45 from binascii import a2b_hex

46 import datetime

47 from struct import pack, unpack

48 from contextlib import contextmanager

49 from pyasn1.type.univ import noValue

50

51 from impacket import nmb, ntlm, nt_errors, LOG

52 from impacket.structure import Structure

53 from impacket.spnego import SPNEGO_NegTokenInit, TypesMech, SPNEGO_NegTokenResp, ASN1_OID, asn1encode, ASN1_AID

54 from impacket.krb5.gssapi import KRB5_AP_REQ

55

56# For signing

57 import hashlib

58

59 unicode_support = 0

60 unicode_convert = 1

61

62# Dialect for SMB1

63 SMB_DIALECT = 'NT LM 0.12'

64

65# Shared Device Type

66 SHARED_DISK = 0x00

67 SHARED_DISK_HIDDEN = 0x80000000

68 SHARED_PRINT_QUEUE = 0x01

69 SHARED_DEVICE = 0x02

70 SHARED_IPC = 0x03

71

72# Extended attributes mask

73 ATTR_ARCHIVE = 0x020

74 ATTR_COMPRESSED = 0x800

75 ATTR_NORMAL = 0x080

76 ATTR_HIDDEN = 0x002

77 ATTR_READONLY = 0x001

78 ATTR_TEMPORARY = 0x100

79 ATTR_DIRECTORY = 0x010

80 ATTR_SYSTEM = 0x004

81

82# Service Type

83 SERVICE_DISK = 'A:'

84 SERVICE_PRINTER = 'LPT1:'

85 SERVICE_IPC = 'IPC'

86 SERVICE_COMM = 'COMM'

87 SERVICE_ANY = '?????'

88

89# Server Type (Can be used to mask with SMBMachine.get_type() or SMBDomain.get_type())

90 SV_TYPE_WORKSTATION = 0x00000001

91 SV_TYPE_SERVER = 0x00000002

92 SV_TYPE_SQLSERVER = 0x00000004

93 SV_TYPE_DOMAIN_CTRL = 0x00000008

94 SV_TYPE_DOMAIN_BAKCTRL = 0x00000010

95 SV_TYPE_TIME_SOURCE = 0x00000020

96 SV_TYPE_AFP = 0x00000040

97 SV_TYPE_NOVELL = 0x00000080

98 SV_TYPE_DOMAIN_MEMBER = 0x00000100

99 SV_TYPE_PRINTQ_SERVER = 0x00000200

100 SV_TYPE_DIALIN_SERVER = 0x00000400

101 SV_TYPE_XENIX_SERVER = 0x00000800

102 SV_TYPE_NT = 0x00001000

103 SV_TYPE_WFW = 0x00002000

104 SV_TYPE_SERVER_NT = 0x00004000

105 SV_TYPE_POTENTIAL_BROWSER = 0x00010000

106 SV_TYPE_BACKUP_BROWSER = 0x00020000

107 SV_TYPE_MASTER_BROWSER = 0x00040000

108 SV_TYPE_DOMAIN_MASTER = 0x00080000

109 SV_TYPE_LOCAL_LIST_ONLY = 0x40000000

110 SV_TYPE_DOMAIN_ENUM = 0x80000000

111

112# Options values for SMB.stor_file and SMB.retr_file

113 SMB_O_CREAT = 0x10 # Create the file if file does not exists. Otherwise, operation fails.

114 SMB_O_EXCL = 0x00 # When used with SMB_O_CREAT, operation fails if file exists. Cannot be used with SMB_O_OPEN.

115 SMB_O_OPEN = 0x01 # Open the file if the file exists

116 SMB_O_TRUNC = 0x02 # Truncate the file if the file exists

117

118# Share Access Mode

119 SMB_SHARE_COMPAT = 0x00

120 SMB_SHARE_DENY_EXCL = 0x10

121 SMB_SHARE_DENY_WRITE = 0x20

122 SMB_SHARE_DENY_READEXEC = 0x30

123 SMB_SHARE_DENY_NONE = 0x40

124 SMB_ACCESS_READ = 0x00

125 SMB_ACCESS_WRITE = 0x01

126 SMB_ACCESS_READWRITE = 0x02

127 SMB_ACCESS_EXEC = 0x03

128

129 TRANS_DISCONNECT_TID = 1

130 TRANS_NO_RESPONSE = 2

131

132 STATUS_SUCCESS = 0x00000000

133 STATUS_LOGON_FAILURE = 0xC000006D

134 STATUS_LOGON_TYPE_NOT_GRANTED = 0xC000015B

135 MAX_TFRAG_SIZE = 5840

136 EVASION_NONE = 0

137 EVASION_LOW = 1

138 EVASION_HIGH = 2

139 EVASION_MAX = 3

140 RPC_X_BAD_STUB_DATA = 0x6F7

141

142# SMB_FILE_ATTRIBUTES

143

144 SMB_FILE_ATTRIBUTE_NORMAL = 0x0000

145 SMB_FILE_ATTRIBUTE_READONLY = 0x0001

146 SMB_FILE_ATTRIBUTE_HIDDEN = 0x0002

147 SMB_FILE_ATTRIBUTE_SYSTEM = 0x0004

148 SMB_FILE_ATTRIBUTE_VOLUME = 0x0008

149 SMB_FILE_ATTRIBUTE_DIRECTORY = 0x0010

150 SMB_FILE_ATTRIBUTE_ARCHIVE = 0x0020

151 SMB_SEARCH_ATTRIBUTE_READONLY = 0x0100

152 SMB_SEARCH_ATTRIBUTE_HIDDEN = 0x0200

153 SMB_SEARCH_ATTRIBUTE_SYSTEM = 0x0400

154 SMB_SEARCH_ATTRIBUTE_DIRECTORY = 0x1000

155 SMB_SEARCH_ATTRIBUTE_ARCHIVE = 0x2000

156

157# Session SetupAndX Action flags

158 SMB_SETUP_GUEST = 0x01

159 SMB_SETUP_USE_LANMAN_KEY = 0x02

160

161# QUERY_INFORMATION levels

162 SMB_INFO_ALLOCATION = 0x0001

163 SMB_INFO_VOLUME = 0x0002

164 FILE_FS_SIZE_INFORMATION = 0x0003

165 SMB_QUERY_FS_VOLUME_INFO = 0x0102

166 SMB_QUERY_FS_SIZE_INFO = 0x0103

167 SMB_QUERY_FILE_EA_INFO = 0x0103

168 SMB_QUERY_FS_DEVICE_INFO = 0x0104

169 SMB_QUERY_FS_ATTRIBUTE_INFO = 0x0105

170 SMB_QUERY_FILE_BASIC_INFO = 0x0101

171 SMB_QUERY_FILE_STANDARD_INFO = 0x0102

172 SMB_QUERY_FILE_ALL_INFO = 0x0107

173 FILE_FS_FULL_SIZE_INFORMATION = 0x03EF

174

175# SET_INFORMATION levels

176 SMB_SET_FILE_DISPOSITION_INFO = 0x0102

177 SMB_SET_FILE_BASIC_INFO = 0x0101

178 SMB_SET_FILE_END_OF_FILE_INFO = 0x0104

179

180

181# File System Attributes

182 FILE_CASE_SENSITIVE_SEARCH = 0x00000001

183 FILE_CASE_PRESERVED_NAMES = 0x00000002

184 FILE_UNICODE_ON_DISK = 0x00000004

185 FILE_PERSISTENT_ACLS = 0x00000008

186 FILE_FILE_COMPRESSION = 0x00000010

187 FILE_VOLUME_IS_COMPRESSED = 0x00008000

188

189# FIND_FIRST2 flags and levels

190 SMB_FIND_CLOSE_AFTER_REQUEST = 0x0001

191 SMB_FIND_CLOSE_AT_EOS = 0x0002

192 SMB_FIND_RETURN_RESUME_KEYS = 0x0004

193 SMB_FIND_CONTINUE_FROM_LAST = 0x0008

194 SMB_FIND_WITH_BACKUP_INTENT = 0x0010

195

196 FILE_DIRECTORY_FILE = 0x00000001

197 FILE_DELETE_ON_CLOSE = 0x00001000

198 FILE_NON_DIRECTORY_FILE = 0x00000040

199

200 SMB_FIND_INFO_STANDARD = 0x0001

201 SMB_FIND_FILE_DIRECTORY_INFO = 0x0101

202 SMB_FIND_FILE_FULL_DIRECTORY_INFO= 0x0102

203 SMB_FIND_FILE_NAMES_INFO = 0x0103

204 SMB_FIND_FILE_BOTH_DIRECTORY_INFO= 0x0104

205 SMB_FIND_FILE_ID_FULL_DIRECTORY_INFO = 0x105

206 SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO = 0x106

207

208

209# DesiredAccess flags

210 FILE_READ_DATA = 0x00000001

211 FILE_WRITE_DATA = 0x00000002

212 FILE_APPEND_DATA = 0x00000004

213 FILE_EXECUTE = 0x00000020

214 MAXIMUM_ALLOWED = 0x02000000

215 GENERIC_ALL = 0x10000000

216 GENERIC_EXECUTE = 0x20000000

217 GENERIC_WRITE = 0x40000000

218 GENERIC_READ = 0x80000000

219

220# ShareAccess flags

221 FILE_SHARE_NONE = 0x00000000

222 FILE_SHARE_READ = 0x00000001

223 FILE_SHARE_WRITE = 0x00000002

224 FILE_SHARE_DELETE = 0x00000004

225

226# CreateDisposition flags

227 FILE_SUPERSEDE = 0x00000000

228 FILE_OPEN = 0x00000001

229 FILE_CREATE = 0x00000002

230 FILE_OPEN_IF = 0x00000003

231 FILE_OVERWRITE = 0x00000004

232 FILE_OVERWRITE_IF = 0x00000005

233

234 def 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'

248

249# Raised when an error has occurred during a session

250 class 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

297

298 # here's a special one from observing NT

299 ERRnoipc = 66

300

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

313

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

324

325 # Error codes for the ERRSRV class

326

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

358

359 # Error codes for the ERRHRD class

360

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

377

378

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 }

399

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 }

436

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

472

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", {} ) }

483

484

485

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

497

498 def get_error_class( self ):

499 return self.error_class

500

501 def get_error_code( self ):

502 return self.error_code

503

504 def get_error_packet(self):

505 return self.packet

506

507 def __str__( self ):

508 error_class = SessionError.error_classes.get( self.error_class, None )

509 if not error_class:

510 error_code_str = self.error_code

511 error_class_str = self.error_class

512 else:

513 error_class_str = error_class[0]

514 error_code = error_class[1].get( self.error_code, None )

515 if not error_code:

516 error_code_str = self.error_code

517 else:

518 error_code_str = '%s(%s)' % error_code

519

520 if self.nt_status:

521 return 'SMB SessionError: %s(%s)' % nt_errors.ERROR_MESSAGES[self.error_code]

522 else:

523 # Fall back to the old format

524 return 'SMB SessionError: class: %s, code: %s' % (error_class_str, error_code_str)

525

526

527# Raised when an supported feature is present/required in the protocol but is not

528# currently supported by pysmb

529 class UnsupportedFeature(Exception):

530 pass

531

532# Contains information about a SMB shared device/service

533 class SharedDevice:

534 def __init__(self, name, share_type, comment):

535 self.__name = name

536 self.__type = share_type

537 self.__comment = comment

538

539 def get_name(self):

540 return self.__name

541

542 def get_type(self):

543 return self.__type

544

545 def get_comment(self):

546 return self.__comment

547

548 def __repr__(self):

549 return '<SharedDevice instance: name=' + self.__name + ', type=' + str(self.__type) + ', comment="' + self.__comment + '">'

550

551

552# Contains information about the shared file/directory

553 class 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

575

576 def get_ctime(self):

577 return self.__ctime

578

579 def get_ctime_epoch(self):

580 return self.__convert_smbtime(self.__ctime)

581

582 def get_mtime(self):

583 return self.__mtime

584

585 def get_mtime_epoch(self):

586 return self.__convert_smbtime(self.__mtime)

587

588 def get_atime(self):

589 return self.__atime

590

591 def get_atime_epoch(self):

592 return self.__convert_smbtime(self.__atime)

593

594 def get_filesize(self):

595 return self.__filesize

596

597 def get_allocsize(self):

598 return self.__allocsize

599

600 def get_attributes(self):

601 return self.__attribs

602

603 def is_archive(self):

604 return self.__attribs & ATTR_ARCHIVE

605

606 def is_compressed(self):

607 return self.__attribs & ATTR_COMPRESSED

608

609 def is_normal(self):

610 return self.__attribs & ATTR_NORMAL

611

612 def is_hidden(self):

613 return self.__attribs & ATTR_HIDDEN

614

615 def is_readonly(self):

616 return self.__attribs & ATTR_READONLY

617

618 def is_temporary(self):

619 return self.__attribs & ATTR_TEMPORARY

620

621 def is_directory(self):

622 return self.__attribs & ATTR_DIRECTORY

623

624 def is_system(self):

625 return self.__attribs & ATTR_SYSTEM

626

627 def get_shortname(self):

628 return self.__shortname

629

630 def get_longname(self):

631 return self.__longname

632

633 def __repr__(self):

634 return '<SharedFile instance: shortname="' + self.__shortname + '", longname="' + self.__longname + '", filesize=' + str(self.__filesize) + '>'

635

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

642

643

644# Contain information about a SMB machine

645 class SMBMachine:

646 def __init__(self, nbname, nbt_type, comment):

647 self.__nbname = nbname

648 self.__type = nbt_type

649 self.__comment = comment

650

651 def __repr__(self):

652 return '<SMBMachine instance: nbname="' + self.__nbname + '", type=' + hex(self.__type) + ', comment="' + self.__comment + '">'

653

654 class 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

659

660 def __repr__(self):

661 return '<SMBDomain instance: nbgroup="' + self.__nbgroup + '", type=' + hex(self.__type) + ', master browser="' + self.__master_browser + '">'

662

663# Represents a SMB Packet

664 class 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 )

682

683 def __init__(self, **kargs):

684 Structure.__init__(self, **kargs)

685

686 if ('Flags2' in self.fields) is False:

687 self['Flags2'] = 0

688 if ('Flags1' in self.fields) is False:

689 self['Flags1'] = 0

690

691 if 'data' not in kargs:

692 self['Data'] = []

693

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)

701

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)

705

706 def isMoreProcessingRequired(self):

707 return self['ErrorClass'] == 0x16 and self['ErrorCode'] == 0xc000

708

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))

721

722

723 class 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 )

731

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

737

738 Structure.__init__(self, data = data, **kargs)

739

740 if data is None:

741 self['Parameters'] = ''

742 self['Data'] = ''

743

744 class 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)

753

754 class SMBCommand_Parameters(Structure):

755 pass

756

757 class 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 )

766

767############# TRANSACTIONS RELATED

768# TRANS2_QUERY_FS_INFORMATION

769# QUERY_FS Information Levels

770# SMB_QUERY_FS_ATTRIBUTE_INFO

771 class SMBQueryFsAttributeInfo(Structure):

772 structure = (

773 ('FileSystemAttributes','<L'),

774 ('MaxFilenNameLengthInBytes','<L'),

775 ('LengthOfFileSystemName','<L-FileSystemName'),

776 ('FileSystemName',':'),

777 )

778

779 class 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 )

790

791# FILE_FS_SIZE_INFORMATION

792 class FileFsSizeInformation(Structure):

793 structure = (

794 ('TotalAllocationUnits','<q=148529400'),

795 ('AvailableAllocationUnits','<q=14851044'),

796 ('SectorsPerAllocationUnit','<L=2'),

797 ('BytesPerSector','<L=512'),

798 )

799

800# SMB_QUERY_FS_SIZE_INFO

801 class 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

809 class 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

818 class 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

827 class 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 )

855

856# SMB_FIND_FILE_ID_FULL_DIRECTORY_INFO level

857 class 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 )

881

882# SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO level

883 class 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 )

915

916# SMB_FIND_FILE_DIRECTORY_INFO level

917 class 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 )

937

938# SMB_FIND_FILE_NAMES_INFO level

939 class 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 )

952

953# SMB_FIND_FILE_FULL_DIRECTORY_INFO level

954 class 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 )

976

977# SMB_FIND_INFO_STANDARD level

978 class 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 )

999

1000# SET_FILE_INFORMATION structures

1001# SMB_SET_FILE_DISPOSITION_INFO

1002 class SMBSetFileDispositionInfo(Structure):

1003 structure = (

1004 ('DeletePending','<B'),

1005 )

1006

1007# SMB_SET_FILE_BASIC_INFO

1008 class SMBSetFileBasicInfo(Structure):

1009 structure = (

1010 ('CreationTime','<q'),

1011 ('LastAccessTime','<q'),

1012 ('LastWriteTime','<q'),

1013 ('ChangeTime','<q'),

1014 ('ExtFileAttributes','<H'),

1015 ('Reserved','<L'),

1016 )

1017

1018# FILE_STREAM_INFORMATION

1019 class SMBFileStreamInformation(Structure):

1020 commonHdr = (

1021 ('NextEntryOffset','<L=0'),

1022 ('StreamNameLength','<L=0'),

1023 ('StreamSize','<q=0'),

1024 ('StreamAllocationSize','<q=0'),

1025 ('StreamName',':=""'),

1026 )

1027

1028# FILE_NETWORK_OPEN_INFORMATION

1029 class 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 )

1040

1041# SMB_SET_FILE_END_OF_FILE_INFO

1042 class SMBSetFileEndOfFileInfo(Structure):

1043 structure = (

1044 ('EndOfFile','<q'),

1045 )

1046

1047# TRANS2_FIND_NEXT2

1048 class 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 )

1062

1063 class SMBFindNext2Response_Parameters(Structure):

1064 structure = (

1065 ('SearchCount','<H'),

1066 ('EndOfSearch','<H=1'),

1067 ('EaErrorOffset','<H=0'),

1068 ('LastNameOffset','<H=0'),

1069 )

1070

1071 class SMBFindNext2_Data(Structure):

1072 structure = (

1073 ('GetExtendedAttributesListLength','_-GetExtendedAttributesList', 'self["GetExtendedAttributesListLength"]'),

1074 ('GetExtendedAttributesList',':'),

1075 )

1076

1077

1078# TRANS2_FIND_FIRST2

1079 class SMBFindFirst2Response_Parameters(Structure):

1080 structure = (

1081 ('SID','<H'),

1082 ('SearchCount','<H'),

1083 ('EndOfSearch','<H=1'),

1084 ('EaErrorOffset','<H=0'),

1085 ('LastNameOffset','<H=0'),

1086 )

1087

1088 class 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 )

1102

1103 class SMBFindFirst2_Data(Structure):

1104 structure = (

1105 ('GetExtendedAttributesListLength','_-GetExtendedAttributesList', 'self["GetExtendedAttributesListLength"]'),

1106 ('GetExtendedAttributesList',':'),

1107 )

1108

1109# TRANS2_SET_PATH_INFORMATION

1110 class SMBSetPathInformation_Parameters(AsciiOrUnicodeStructure):

1111 commonHdr = (

1112 ('InformationLevel','<H'),

1113 ('Reserved','<L'),

1114 )

1115 AsciiStructure = (

1116 ('FileName','z'),

1117 )

1118 UnicodeStructure = (

1119 ('FileName','u'),

1120 )

1121

1122 class SMBSetPathInformationResponse_Parameters(Structure):

1123 structure = (

1124 ('EaErrorOffset','<H=0'),

1125 )

1126

1127# TRANS2_SET_FILE_INFORMATION

1128 class SMBSetFileInformation_Parameters(Structure):

1129 structure = (

1130 ('FID','<H'),

1131 ('InformationLevel','<H'),

1132 ('Reserved','<H'),

1133 )

1134

1135 class SMBSetFileInformationResponse_Parameters(Structure):

1136 structure = (

1137 ('EaErrorOffset','<H=0'),

1138 )

1139

1140# TRANS2_QUERY_FILE_INFORMATION

1141 class SMBQueryFileInformation_Parameters(Structure):

1142 structure = (

1143 ('FID','<H'),

1144 ('InformationLevel','<H'),

1145 )

1146

1147 class SMBQueryFileInformationResponse_Parameters(Structure):

1148 structure = (

1149 ('EaErrorOffset','<H=0'),

1150 )

1151

1152 class SMBQueryFileInformation_Data(Structure):

1153 structure = (

1154 ('GetExtendedAttributeList',':'),

1155 )

1156

1157# TRANS2_QUERY_PATH_INFORMATION

1158 class SMBQueryPathInformationResponse_Parameters(Structure):

1159 structure = (

1160 ('EaErrorOffset','<H=0'),

1161 )

1162

1163 class 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 )

1174

1175 class SMBQueryPathInformation_Data(Structure):

1176 structure = (

1177 ('GetExtendedAttributeList',':'),

1178 )

1179

1180

1181# SMB_QUERY_FILE_EA_INFO

1182 class SMBQueryFileEaInfo(Structure):

1183 structure = (

1184 ('EaSize','<L=0'),

1185 )

1186

1187# SMB_QUERY_FILE_BASIC_INFO

1188 class SMBQueryFileBasicInfo(Structure):

1189 structure = (

1190 ('CreationTime','<q'),

1191 ('LastAccessTime','<q'),

1192 ('LastWriteTime','<q'),

1193 ('LastChangeTime','<q'),

1194 ('ExtFileAttributes','<L'),

1195 #('Reserved','<L=0'),

1196 )

1197

1198# SMB_QUERY_FILE_STANDARD_INFO

1199 class SMBQueryFileStandardInfo(Structure):

1200 structure = (

1201 ('AllocationSize','<q'),

1202 ('EndOfFile','<q'),

1203 ('NumberOfLinks','<L=0'),

1204 ('DeletePending','<B=0'),

1205 ('Directory','<B'),

1206 )

1207

1208# SMB_QUERY_FILE_ALL_INFO

1209 class 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 )

1227

1228# \PIPE\LANMAN NetShareEnum

1229 class SMBNetShareEnum(Structure):

1230 structure = (

1231 ('RAPOpcode','<H=0'),

1232 ('ParamDesc','z'),

1233 ('DataDesc','z'),

1234 ('InfoLevel','<H'),

1235 ('ReceiveBufferSize','<H'),

1236 )

1237

1238 class SMBNetShareEnumResponse(Structure):

1239 structure = (

1240 ('Status','<H=0'),

1241 ('Convert','<H=0'),

1242 ('EntriesReturned','<H'),

1243 ('EntriesAvailable','<H'),

1244 )

1245

1246 class NetShareInfo1(Structure):

1247 structure = (

1248 ('NetworkName','13s'),

1249 ('Pad','<B=0'),

1250 ('Type','<H=0'),

1251 ('RemarkOffsetLow','<H=0'),

1252 ('RemarkOffsetHigh','<H=0'),

1253 )

1254

1255# \PIPE\LANMAN NetServerGetInfo

1256 class SMBNetServerGetInfoResponse(Structure):

1257 structure = (

1258 ('Status','<H=0'),

1259 ('Convert','<H=0'),

1260 ('TotalBytesAvailable','<H'),

1261 )

1262

1263 class 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 )

1273

1274# \PIPE\LANMAN NetShareGetInfo

1275 class SMBNetShareGetInfo(Structure):

1276 structure = (

1277 ('RAPOpcode','<H=0'),

1278 ('ParamDesc','z'),

1279 ('DataDesc','z'),

1280 ('ShareName','z'),

1281 ('InfoLevel','<H'),

1282 ('ReceiveBufferSize','<H'),

1283 )

1284

1285 class SMBNetShareGetInfoResponse(Structure):

1286 structure = (

1287 ('Status','<H=0'),

1288 ('Convert','<H=0'),

1289 ('TotalBytesAvailable','<H'),

1290 )

1291

1292############# Security Features

1293 class SecurityFeatures(Structure):

1294 structure = (

1295 ('Key','<L=0'),

1296 ('CID','<H=0'),

1297 ('SequenceNumber','<H=0'),

1298 )

1299

1300############# SMB_COM_QUERY_INFORMATION2 (0x23)

1301 class SMBQueryInformation2_Parameters(Structure):

1302 structure = (

1303 ('Fid','<H'),

1304 )

1305

1306 class 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 )

1318

1319

1320

1321############# SMB_COM_SESSION_SETUP_ANDX (0x73)

1322 class 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 )

1333

1334 class 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 )

1344

1345 class 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 )

1356

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 )

1367

1368 class SMBSessionSetupAndX_Extended_Data(AsciiOrUnicodeStructure):

1369 AsciiStructure = (

1370 ('SecurityBlobLength','_-SecurityBlob','self["SecurityBlobLength"]'),

1371 ('SecurityBlob',':'),

1372 ('NativeOS','z=""'),

1373 ('NativeLanMan','z=""'),

1374 )

1375

1376 UnicodeStructure = (

1377 ('SecurityBlobLength','_-SecurityBlob','self["SecurityBlobLength"]'),

1378 ('SecurityBlob',':'),

1379 ('NativeOS','u=""'),

1380 ('NativeLanMan','u=""'),

1381 )

1382

1383 class SMBSessionSetupAndXResponse_Parameters(SMBAndXCommand_Parameters):

1384 structure = (

1385 ('Action','<H'),

1386 )

1387

1388 class SMBSessionSetupAndX_Extended_Response_Parameters(SMBAndXCommand_Parameters):

1389 structure = (

1390 ('Action','<H=0'),

1391 ('SecurityBlobLength','<H'),

1392 )

1393

1394 class SMBSessionSetupAndXResponse_Data(AsciiOrUnicodeStructure):

1395 AsciiStructure = (

1396 ('NativeOS','z=""'),

1397 ('NativeLanMan','z=""'),

1398 ('PrimaryDomain','z=""'),

1399 )

1400

1401 UnicodeStructure = (

1402 ('NativeOS','u=""'),

1403 ('NativeLanMan','u=""'),

1404 ('PrimaryDomain','u=""'),

1405 )

1406

1407 class SMBSessionSetupAndX_Extended_Response_Data(AsciiOrUnicodeStructure):

1408 AsciiStructure = (

1409 ('SecurityBlobLength','_-SecurityBlob','self["SecurityBlobLength"]'),

1410 ('SecurityBlob',':'),

1411 ('NativeOS','z=""'),

1412 ('NativeLanMan','z=""'),

1413 )

1414

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)

1428

1429############# SMB_COM_TREE_CONNECT (0x70)

1430 class SMBTreeConnect_Parameters(SMBCommand_Parameters):

1431 structure = (

1432 )

1433

1434 class 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 )

1443

1444############# SMB_COM_TREE_CONNECT_ANDX (0x75)

1445 class SMBTreeConnectAndX_Parameters(SMBAndXCommand_Parameters):

1446 structure = (

1447 ('Flags','<H=0'),

1448 ('PasswordLength','<H'),

1449 )

1450

1451 class SMBTreeConnectAndXResponse_Parameters(SMBAndXCommand_Parameters):

1452 structure = (

1453 ('OptionalSupport','<H=0'),

1454 )

1455

1456 class SMBTreeConnectAndXExtendedResponse_Parameters(SMBAndXCommand_Parameters):

1457 structure = (

1458 ('OptionalSupport','<H=1'),

1459 ('MaximalShareAccessRights','<L=0x1fffff'),

1460 ('GuestMaximalShareAccessRights','<L=0x1fffff'),

1461 )

1462

1463 class SMBTreeConnectAndX_Data(AsciiOrUnicodeStructure):

1464 AsciiStructure = (

1465 ('_PasswordLength','_-Password','self["_PasswordLength"]'),

1466 ('Password',':'),

1467 ('Path','z'),

1468 ('Service','z'),

1469 )

1470

1471 UnicodeStructure = (

1472 ('_PasswordLength','_-Password','self["_PasswordLength"] if self["_PasswordLength"] > 0 else 1'),

1473 ('Password',':'),

1474 ('Path','u'),

1475 ('Service','z'),

1476 )

1477

1478 class 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 )

1491

1492############# SMB_COM_NT_CREATE_ANDX (0xA2)

1493 class 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 )

1509

1510 class 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 )

1527

1528 class 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 )

1550

1551 class SMBNtCreateAndX_Data(AsciiOrUnicodeStructure):

1552 AsciiStructure = (

1553 ('FileName','z'),

1554 )

1555 UnicodeStructure = (

1556 ('Pad','B'),

1557 ('FileName','u'),

1558 )

1559

1560############# SMB_COM_OPEN_ANDX (0xD2)

1561 class 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 )

1572

1573 class SMBOpenAndX_Data(SMBNtCreateAndX_Data):

1574 pass

1575

1576 class 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 )

1589

1590############# SMB_COM_WRITE (0x0B)

1591 class SMBWrite_Parameters(SMBCommand_Parameters):

1592 structure = (

1593 ('Fid','<H'),

1594 ('Count','<H'),

1595 ('Offset','<L'),

1596 ('Remaining','<H'),

1597 )

1598

1599 class SMBWriteResponse_Parameters(SMBCommand_Parameters):

1600 structure = (

1601 ('Count','<H'),

1602 )

1603

1604 class SMBWrite_Data(Structure):

1605 structure = (

1606 ('BufferFormat','<B=1'),

1607 ('DataLength','<H-Data'),

1608 ('Data',':'),

1609 )

1610

1611

1612############# SMB_COM_WRITE_ANDX (0x2F)

1613 class 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 )

1625

1626 class 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 )

1634

1635 class 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 )

1643

1644

1645 class 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 )

1656

1657 class SMBWriteAndXResponse_Parameters(SMBAndXCommand_Parameters):

1658 structure = (

1659 ('Count','<H'),

1660 ('Available','<H'),

1661 ('Reserved','<L=0'),

1662 )

1663

1664############# SMB_COM_WRITE_RAW (0x1D)

1665 class 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 )

1677

1678############# SMB_COM_READ (0x0A)

1679 class SMBRead_Parameters(SMBCommand_Parameters):

1680 structure = (

1681 ('Fid','<H'),

1682 ('Count','<H'),

1683 ('Offset','<L'),

1684 ('Remaining','<H=Count'),

1685 )

1686

1687 class SMBReadResponse_Parameters(Structure):

1688 structure = (

1689 ('Count','<H=0'),

1690 ('_reserved','8s=""'),

1691 )

1692

1693 class SMBReadResponse_Data(Structure):

1694 structure = (

1695 ('BufferFormat','<B=0x1'),

1696 ('DataLength','<H-Data'),

1697 ('Data',':'),

1698 )

1699

1700############# SMB_COM_READ_RAW (0x1A)

1701 class 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 )

1710

1711############# SMB_COM_NT_TRANSACT (0xA0)

1712 class 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 )

1729

1730 class 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 )

1745

1746 class 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 )

1757

1758 class 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 )

1769

1770

1771############# SMB_COM_TRANSACTION2_SECONDARY (0x33)

1772 class 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 )

1784

1785 class 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 )

1796

1797

1798############# SMB_COM_TRANSACTION2 (0x32)

1799

1800 class 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 )

1820

1821 class 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 )

1837

1838 class 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 )

1851

1852 class 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 )

1863

1864############# SMB_COM_QUERY_INFORMATION (0x08)

1865

1866 class SMBQueryInformation_Data(AsciiOrUnicodeStructure):

1867 AsciiStructure = (

1868 ('BufferFormat','B=4'),

1869 ('FileName','z'),

1870 )

1871 UnicodeStructure = (

1872 ('BufferFormat','B=4'),

1873 ('FileName','u'),

1874 )

1875

1876

1877 class SMBQueryInformationResponse_Parameters(Structure):

1878 structure = (

1879 ('FileAttributes','<H'),

1880 ('LastWriteTime','<L'),

1881 ('FileSize','<L'),

1882 ('Reserved','"0123456789'),

1883 )

1884

1885############# SMB_COM_TRANSACTION (0x25)

1886 class 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 )

1906

1907 class 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 )

1923

1924# TODO: We should merge these both. But this will require fixing

1925# the instances where this structure is used on the client side

1926 class 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 )

1942

1943 class 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 )

1952

1953 class SMBTransactionResponse_Data(Structure):

1954 structure = (

1955 ('Trans_ParametersLength','_-Trans_Parameters'),

1956 ('Trans_Parameters',':'),

1957 ('Trans_DataLength','_-Trans_Data'),

1958 ('Trans_Data',':'),

1959 )

1960

1961############# SMB_COM_READ_ANDX (0x2E)

1962 class 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 )

1972

1973 class 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 )

1982

1983 class 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 )

1993

1994############# SMB_COM_ECHO (0x2B)

1995 class SMBEcho_Data(Structure):

1996 structure = (

1997 ('Data',':'),

1998 )

1999

2000 class SMBEcho_Parameters(Structure):

2001 structure = (

2002 ('EchoCount','<H'),

2003 )

2004

2005 class SMBEchoResponse_Data(Structure):

2006 structure = (

2007 ('Data',':'),

2008 )

2009

2010 class SMBEchoResponse_Parameters(Structure):

2011 structure = (

2012 ('SequenceNumber','<H=1'),

2013 )

2014

2015############# SMB_COM_QUERY_INFORMATION_DISK (0x80)

2016 class SMBQueryInformationDiskResponse_Parameters(Structure):

2017 structure = (

2018 ('TotalUnits','<H'),

2019 ('BlocksPerUnit','<H'),

2020 ('BlockSize','<H'),

2021 ('FreeUnits','<H'),

2022 ('Reserved','<H=0'),

2023 )

2024

2025

2026############# SMB_COM_LOGOFF_ANDX (0x74)

2027 class SMBLogOffAndX(SMBAndXCommand_Parameters):

2028 strucure = ()

2029

2030############# SMB_COM_CLOSE (0x04)

2031 class SMBClose_Parameters(SMBCommand_Parameters):

2032 structure = (

2033 ('FID','<H'),

2034 ('Time','<L=0'),

2035 )

2036

2037############# SMB_COM_FLUSH (0x05)

2038 class SMBFlush_Parameters(SMBCommand_Parameters):

2039 structure = (

2040 ('FID','<H'),

2041 )

2042

2043############# SMB_COM_CREATE_DIRECTORY (0x00)

2044 class SMBCreateDirectory_Data(AsciiOrUnicodeStructure):

2045 AsciiStructure = (

2046 ('BufferFormat','<B=4'),

2047 ('DirectoryName','z'),

2048 )

2049 UnicodeStructure = (

2050 ('BufferFormat','<B=4'),

2051 ('DirectoryName','u'),

2052 )

2053

2054############# SMB_COM_DELETE (0x06)

2055 class SMBDelete_Data(AsciiOrUnicodeStructure):

2056 AsciiStructure = (

2057 ('BufferFormat','<B=4'),

2058 ('FileName','z'),

2059 )

2060 UnicodeStructure = (

2061 ('BufferFormat','<B=4'),

2062 ('FileName','u'),

2063 )

2064

2065 class SMBDelete_Parameters(Structure):

2066 structure = (

2067 ('SearchAttributes','<H'),

2068 )

2069

2070############# SMB_COM_DELETE_DIRECTORY (0x01)

2071 class SMBDeleteDirectory_Data(AsciiOrUnicodeStructure):

2072 AsciiStructure = (

2073 ('BufferFormat','<B=4'),

2074 ('DirectoryName','z'),

2075 )

2076 UnicodeStructure = (

2077 ('BufferFormat','<B=4'),

2078 ('DirectoryName','u'),

2079 )

2080

2081############# SMB_COM_CHECK_DIRECTORY (0x10)

2082 class SMBCheckDirectory_Data(AsciiOrUnicodeStructure):

2083 AsciiStructure = (

2084 ('BufferFormat','<B=4'),

2085 ('DirectoryName','z'),

2086 )

2087 UnicodeStructure = (

2088 ('BufferFormat','<B=4'),

2089 ('DirectoryName','u'),

2090 )

2091

2092############# SMB_COM_RENAME (0x07)

2093 class SMBRename_Parameters(SMBCommand_Parameters):

2094 structure = (

2095 ('SearchAttributes','<H'),

2096 )

2097

2098 class 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 )

2112

2113

2114############# SMB_COM_OPEN (0x02)

2115 class SMBOpen_Parameters(SMBCommand_Parameters):

2116 structure = (

2117 ('DesiredAccess','<H=0'),

2118 ('SearchAttributes','<H=0'),

2119 )

2120

2121 class SMBOpen_Data(AsciiOrUnicodeStructure):

2122 AsciiStructure = (

2123 ('FileNameFormat','"\x04'),

2124 ('FileName','z'),

2125 )

2126 UnicodeStructure = (

2127 ('FileNameFormat','"\x04'),

2128 ('FileName','u'),

2129 )

2130

2131 class 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 )

2139

2140############# EXTENDED SECURITY CLASSES

2141 class 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 )

2156

2157 class SMBExtended_Security_Data(Structure):

2158 structure = (

2159 ('ServerGUID','16s'),

2160 ('SecurityBlob',':'),

2161 )

2162

2163 class 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 )

2178

2179 class 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

2191

2192 def fromString(self,data):

2193 Structure.fromString(self,data)

2194 self['DomainName'] = ''

2195 self['ServerName'] = ''

2196

2197 class SMB(object):

2198

2199 class HostnameValidationException(Exception):

2200 pass

2201

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

2276

2277 # TRANSACT codes

2278 TRANS_TRANSACT_NMPIPE = 0x26

2279

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

2288

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

2295

2296 # Security Auth Mode (Used internally by SMB class)

2297 SECURITY_AUTH_MASK = 0x02

2298 SECURITY_AUTH_ENCRYPTED = 0x02

2299 SECURITY_AUTH_PLAINTEXT = 0x00

2300

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

2304

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

2316

2317 # Flags1 Mask

2318 FLAGS1_LOCK_AND_READ_OK = 0x01

2319 FLAGS1_PATHCASELESS = 0x08

2320 FLAGS1_CANONICALIZED_PATHS = 0x10

2321 FLAGS1_REPLY = 0x80

2322

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

2335

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

2341

2342 # Tree Connect AndX Response optionalSuppor flags

2343 SMB_SUPPORT_SEARCH_BITS = 0x01

2344 SMB_SHARE_IS_IN_DFS = 0x02

2345

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

2366

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

2377

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

2387

2388 # Strict host validation - off by default

2389 self._strict_hostname_validation = False

2390 self._validation_allow_absent = True

2391 self._accepted_hostname = ''

2392

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

2400

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

2404

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

2409

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

2416

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

2422

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]

2430

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)

2435

2436 # Initialize session values (_dialect_data and _dialect_parameters)

2437 self.neg_session()

2438

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('', '')

2452

2453 @staticmethod

2454 def ntlm_supported():

2455 return False

2456

2457 def getKerberos(self):

2458 return self._doKerberos

2459

2460 def get_remote_name(self):

2461 return self.__remote_name

2462

2463 def set_remote_name(self, name):

2464 self.__remote_name = name

2465 return True

2466

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

2471

2472 def get_remote_host(self):

2473 return self.__remote_host

2474

2475 def get_flags(self):

2476 return self.__flags1, self.__flags2

2477

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

2483

2484 def set_timeout(self, timeout):

2485 prev_timeout = self.__timeout

2486 self.__timeout = timeout

2487 return prev_timeout

2488

2489 def get_timeout(self):

2490 return self.__timeout

2491

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)

2499

2500 def get_session(self):

2501 return self._sess

2502

2503 def get_tid(self):

2504 return self.tid

2505

2506 def get_fid(self):

2507 return self.fid

2508

2509 def isGuestSession(self):

2510 return self._action & SMB_SETUP_GUEST

2511

2512 def doesSupportNTLMv2(self):

2513 return self.__isNTLMv2

2514

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

2519

2520 def recvSMB(self):

2521 r = self._sess.recv_packet(self.__timeout)

2522 return NewSMBPacket(data = r.get_trailer())

2523

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]

2534

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.

2555

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

2569

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

2579

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)

2590

2591 self._sess.send_packet(smb.getData())

2592

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

2605

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

2611

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

2625

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

2631

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']

2636

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

2642

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))

2651

2652 negSession['Data'] = b'\x02NT LM 0.12\x00'

2653 smb.addCommand(negSession)

2654 self.sendSMB(smb)

2655

2656 while 1:

2657 smb = self.recvSMB()

2658 return parsePacket(smb)

2659 else:

2660

2661 return parsePacket( NewSMBPacket( data = negPacket))

2662

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")

2665

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))

2672

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!')

2678

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)

2688

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']

2695

2696 def get_uid(self):

2697 return self._uid

2698

2699 def set_uid(self, uid):

2700 self._uid = uid

2701

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'

2710

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!')

2716

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

2721

2722 # Just in case this came with the full path ,let's just leave

2723 # the sharename, we'll take care of the rest

2724

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()

2731

2732 path = '\\\\' + remote_host + '\\' +share

2733 path = path.upper().encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else path

2734

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

2742

2743 if self.__flags2 & SMB.FLAGS2_UNICODE:

2744 treeConnect['Data']['Pad'] = 0x0

2745

2746 smb.addCommand(treeConnect)

2747

2748 # filename = "\PIPE\epmapper"

2749

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

2758

2759 # smb.addCommand(ntCreate)

2760 self.sendSMB(smb)

2761

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

2770

2771 # backwars compatibility

2772 connect_tree = tree_connect_andx

2773

2774 @staticmethod

2775 def getDialect():

2776 return SMB_DIALECT

2777

2778 def get_server_name(self):

2779 #return self._dialects_data['ServerName']

2780 return self.__server_name

2781

2782 def get_client_name(self):

2783 return self.__client_name

2784

2785 def get_session_key(self):

2786 return self._SigningSessionKey

2787

2788 def set_session_key(self, key):

2789 self._SignatureEnabled = True

2790 self._SignSequenceNumber = 2

2791 self._SigningSessionKey = key

2792

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

2798

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")

2807

2808 def disconnect_tree(self, tid):

2809 smb = NewSMBPacket()

2810 smb['Tid'] = tid

2811

2812 smb.addCommand(SMBCommand(SMB.SMB_COM_TREE_DISCONNECT))

2813

2814 self.sendSMB(smb)

2815 self.recvSMB()

2816

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

2820

2821 smb = NewSMBPacket()

2822 smb['Tid'] = tid

2823

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

2831

2832 smb.addCommand(openFile)

2833

2834 self.sendSMB(smb)

2835

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'])

2841

2842 return (

2843 openFileParameters['Fid'],

2844 openFileParameters['FileAttributes'],

2845 openFileParameters['LastWriten'],

2846 openFileParameters['FileSize'],

2847 openFileParameters['GrantedAccess'],

2848 )

2849

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

2853

2854 smb = NewSMBPacket()

2855 smb['Tid'] = tid

2856

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

2864

2865 if self.__flags2 & SMB.FLAGS2_UNICODE:

2866 openFile['Data']['Pad'] = 0x0

2867

2868 smb.addCommand(openFile)

2869

2870 self.sendSMB(smb)

2871

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'])

2877

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 )

2889

2890 def close(self, tid, fid):

2891 smb = NewSMBPacket()

2892 smb['Tid'] = tid

2893

2894 closeFile = SMBCommand(SMB.SMB_COM_CLOSE)

2895 closeFile['Parameters'] = SMBClose_Parameters()

2896 closeFile['Parameters']['FID'] = fid

2897 smb.addCommand(closeFile)

2898

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

2904

2905 def send_trans(self, tid, setup, name, param, data, noAnswer = 0):

2906 smb = NewSMBPacket()

2907 smb['Tid'] = tid

2908

2909 transCommand = SMBCommand(SMB.SMB_COM_TRANSACTION)

2910 transCommand['Parameters'] = SMBTransaction_Parameters()

2911 transCommand['Data'] = SMBTransaction_Data()

2912

2913 transCommand['Parameters']['Setup'] = setup

2914 transCommand['Parameters']['TotalParameterCount'] = len(param)

2915 transCommand['Parameters']['TotalDataCount'] = len(data)

2916

2917 transCommand['Parameters']['ParameterCount'] = len(param)

2918 transCommand['Parameters']['ParameterOffset'] = 32+3+28+len(setup)+len(name)

2919

2920 transCommand['Parameters']['DataCount'] = len(data)

2921 transCommand['Parameters']['DataOffset'] = transCommand['Parameters']['ParameterOffset'] + len(param)

2922

2923 transCommand['Data']['Name'] = name

2924 transCommand['Data']['Trans_Parameters'] = param

2925 transCommand['Data']['Trans_Data'] = data

2926

2927 if noAnswer:

2928 transCommand['Parameters']['Flags'] = TRANS_NO_RESPONSE

2929

2930 smb.addCommand(transCommand)

2931

2932 self.sendSMB(smb)

2933

2934 def send_trans2(self, tid, setup, name, param, data):

2935 smb = NewSMBPacket()

2936 smb['Tid'] = tid

2937

2938 command = pack('<H', setup)

2939

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()

2944

2945 transCommand['Parameters']['Setup'] = command

2946 transCommand['Parameters']['TotalParameterCount'] = len(param)

2947 transCommand['Parameters']['TotalDataCount'] = len(data)

2948

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

2956

2957 transCommand['Parameters']['ParameterCount'] = len(param)

2958 transCommand['Parameters']['ParameterOffset'] = 32+2+28+len(command)+len(name) + padLen

2959

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

2966

2967 transCommand['Parameters']['DataCount'] = len(data)

2968 transCommand['Parameters']['DataOffset'] = transCommand['Parameters']['ParameterOffset'] + len(param) + pad2Len

2969

2970 transCommand['Data']['Name'] = name

2971 transCommand['Data']['Trans_Parameters'] = param

2972 transCommand['Data']['Trans_Data'] = data

2973 smb.addCommand(transCommand)

2974

2975 self.sendSMB(smb)

2976

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), '')

2979

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']:]

2986

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

2992

2993 read_offset = offset

2994 while read_offset < datasize:

2995 data = self.read_andx(tid, fid, read_offset, max_buf_size)

2996

2997 callback(data)

2998 read_offset += len(data)

2999

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

3005

3006 write_offset = offset

3007 while 1:

3008 data = callback(max_buf_size)

3009 if not data:

3010 break

3011

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']

3016

3017 def get_server_domain(self):

3018 return self.__server_domain

3019

3020 def get_server_dns_domain_name(self):

3021 return self.__server_dns_domain_name

3022

3023 def get_server_dns_host_name(self):

3024 return self.__server_dns_host_name

3025

3026 def get_server_os(self):

3027 return self.__server_os

3028

3029 def get_server_os_major(self):

3030 return self.__server_os_major

3031

3032 def get_server_os_minor(self):

3033 return self.__server_os_minor

3034

3035 def get_server_os_build(self):

3036 return self.__server_os_build

3037

3038 def set_server_os(self, os):

3039 self.__server_os = os

3040

3041 def get_server_lanman(self):

3042 return self.__server_lanman

3043

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

3049

3050 def is_signing_required(self):

3051 return self._SignatureRequired

3052

3053 def get_ntlmv1_response(self, key):

3054 challenge = self._dialects_data['Challenge']

3055 return ntlm.get_ntlmv1_response(key, challenge)

3056

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()))

3065

3066

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

3075

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)

3081

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

3097

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

3108

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']

3118

3119 # Now that we have the TGT, we should ask for a TGS for cifs

3120

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']

3128

3129 smb = NewSMBPacket()

3130

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

3134

3135

3136 sessionSetup = SMBCommand(SMB.SMB_COM_SESSION_SETUP_ANDX)

3137 sessionSetup['Parameters'] = SMBSessionSetupAndX_Extended_Parameters()

3138 sessionSetup['Data'] = SMBSessionSetupAndX_Extended_Data()

3139

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

3145

3146

3147 # Let's build a NegTokenInit with the NTLMSSP

3148 # TODO: In the future we should be able to choose different providers

3149

3150 blob = SPNEGO_NegTokenInit()

3151

3152 # Kerberos v5 mech

3153 blob['MechTypes'] = [TypesMech['MS KRB5 - Microsoft Kerberos 5']]

3154

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'])

3159

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)

3164

3165 opts = list()

3166 apReq['ap-options'] = constants.encodeFlags(opts)

3167 seq_set(apReq,'ticket', ticket.to_asn1)

3168

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()

3174

3175 authenticator['cusec'] = now.microsecond

3176 authenticator['ctime'] = KerberosTime.to_asn1(now)

3177

3178 encodedAuthenticator = encoder.encode(authenticator)

3179

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)

3185

3186 apReq['authenticator'] = noValue

3187 apReq['authenticator']['etype'] = cipher.enctype

3188 apReq['authenticator']['cipher'] = encryptedEncodedAuthenticator

3189

3190 blob['MechToken'] = pack('B', ASN1_AID) + asn1encode(pack('B', ASN1_OID) + asn1encode(

3191 TypesMech['KRB5 - Kerberos 5']) + KRB5_AP_REQ + encoder.encode(apReq))

3192

3193 sessionSetup['Parameters']['SecurityBlobLength'] = len(blob)

3194 sessionSetup['Parameters'].getData()

3195 sessionSetup['Data']['SecurityBlob'] = blob.getData()

3196

3197 # Fake Data here, don't want to get us fingerprinted

3198 sessionSetup['Data']['NativeOS'] = 'Unix'

3199 sessionSetup['Data']['NativeLanMan'] = 'Samba'

3200

3201 smb.addCommand(sessionSetup)

3202 self.sendSMB(smb)

3203

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']

3208

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'])

3215

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

3222

3223 # restore unicode flag if needed

3224 if flags2 & SMB.FLAGS2_UNICODE:

3225 self.__flags2 |= SMB.FLAGS2_UNICODE

3226

3227 return 1

3228 else:

3229 raise Exception('Error: Could not login successfully')

3230

3231 def login_extended(self, user, password, domain = '', lmhash = '', nthash = '', use_ntlmv2 = True ):

3232

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)

3238

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

3244

3245 sessionSetup = SMBCommand(SMB.SMB_COM_SESSION_SETUP_ANDX)

3246 sessionSetup['Parameters'] = SMBSessionSetupAndX_Extended_Parameters()

3247 sessionSetup['Data'] = SMBSessionSetupAndX_Extended_Data()

3248

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

3254

3255

3256 # Let's build a NegTokenInit with the NTLMSSP

3257 # TODO: In the future we should be able to choose different providers

3258

3259 blob = SPNEGO_NegTokenInit()

3260

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()

3265

3266 sessionSetup['Parameters']['SecurityBlobLength'] = len(blob)

3267 sessionSetup['Parameters'].getData()

3268 sessionSetup['Data']['SecurityBlob'] = blob.getData()

3269

3270 # Fake Data here, don't want to get us fingerprinted

3271 sessionSetup['Data']['NativeOS'] = 'Unix'

3272 sessionSetup['Data']['NativeLanMan'] = 'Samba'

3273

3274 smb.addCommand(sessionSetup)

3275 self.sendSMB(smb)

3276

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']

3281

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'])

3289

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

3313

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

3320

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()

3323

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']

3327

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])

3330

3331 type3, exportedSessionKey = ntlm.getNTLMSSPType3(auth, respToken['ResponseToken'], user, password, domain, lmhash, nthash, use_ntlmv2 = use_ntlmv2)

3332

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

3335

3336 smb = NewSMBPacket()

3337

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

3341

3342 respToken2 = SPNEGO_NegTokenResp()

3343 respToken2['ResponseToken'] = type3.getData()

3344

3345 # Reusing the previous structure

3346 sessionSetup['Parameters']['SecurityBlobLength'] = len(respToken2)

3347 sessionSetup['Data']['SecurityBlob'] = respToken2.getData()

3348

3349 # Storing some info for later use

3350 self.__server_os = sessionData['NativeOS']

3351 self.__server_lanman = sessionData['NativeLanMan']

3352

3353 smb.addCommand(sessionSetup)

3354 self.sendSMB(smb)

3355

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'])

3362

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

3368

3369 # restore unicode flag if needed

3370 if flags2 & SMB.FLAGS2_UNICODE:

3371 self.__flags2 |= SMB.FLAGS2_UNICODE

3372

3373 return 1

3374 else:

3375 raise Exception('Error: Could not login successfully')

3376

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)

3387

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

3397

3398 def login(self, user, password, domain = '', lmhash = '', nthash = '', ntlm_fallback = True):

3399

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

3411

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

3420

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')

3436

3437 def login_standard(self, user, password, domain = '', lmhash = '', nthash = ''):

3438

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)

3444

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 = ''

3462

3463 smb = NewSMBPacket()

3464

3465 sessionSetup = SMBCommand(SMB.SMB_COM_SESSION_SETUP_ANDX)

3466 sessionSetup['Parameters'] = SMBSessionSetupAndX_Parameters()

3467 sessionSetup['Data'] = SMBSessionSetupAndX_Data()

3468

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

3476

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)

3484

3485 self.sendSMB(smb)

3486

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'])

3494

3495 self._action = sessionParameters['Action']

3496

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

3504

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']

3511

3512 # restore unicode flag if needed

3513 if flags2 & SMB.FLAGS2_UNICODE:

3514 self.__flags2 |= SMB.FLAGS2_UNICODE

3515

3516 return 1

3517 else:

3518 raise Exception('Error: Could not login successfully')

3519

3520 def waitNamedPipe(self, tid, pipe, timeout = 5, noAnswer = 0):

3521 smb = NewSMBPacket()

3522 smb['Tid'] = tid

3523

3524 transCommand = SMBCommand(SMB.SMB_COM_TRANSACTION)

3525 transCommand['Parameters'] = SMBTransaction_Parameters()

3526 transCommand['Data'] = SMBTransaction_Data()

3527

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

3536

3537 transCommand['Parameters']['ParameterCount'] = 0

3538 transCommand['Parameters']['ParameterOffset'] = 32+3+28+len(setup)+len(name)

3539

3540 transCommand['Parameters']['DataCount'] = 0

3541 transCommand['Parameters']['DataOffset'] = 0

3542

3543 transCommand['Data']['Name'] = name

3544 transCommand['Data']['Trans_Parameters'] = ''

3545 transCommand['Data']['Trans_Data'] = ''

3546

3547 if noAnswer:

3548 transCommand['Parameters']['Flags'] = TRANS_NO_RESPONSE

3549

3550 smb.addCommand(transCommand)

3551 self.sendSMB(smb)

3552

3553 smb = self.recvSMB()

3554 if smb.isValidAnswer(SMB.SMB_COM_TRANSACTION):

3555 return 1

3556 return 0

3557

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

3561

3562 # max_size is not working, because although it would, the server returns an error (More data avail)

3563

3564 smb = NewSMBPacket()

3565 smb['Tid'] = tid

3566

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)

3573

3574 if wait_answer:

3575 while 1:

3576 self.sendSMB(smb)

3577 ans = self.recvSMB()

3578

3579 if ans.isValidAnswer(SMB.SMB_COM_READ):

3580 readResponse = SMBCommand(ans['Data'][0])

3581 readData = SMBReadResponse_Data(readResponse['Data'])

3582

3583 return readData['Data']

3584

3585 return None

3586

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

3593

3594 # max_size is not working, because although it would, the server returns an error (More data avail)

3595

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

3599

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

3608

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()

3614

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'])

3619

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()

3630

3631 try:

3632 if ans.isValidAnswer(SMB.SMB_COM_READ_ANDX):

3633 return ans

3634 else:

3635 return None

3636 except:

3637 return ans

3638

3639 return None

3640

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

3644

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

3648

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)

3655

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

3663

3664 return None

3665

3666 def write(self,tid,fid,data, offset = 0, wait_answer=1):

3667 smb = NewSMBPacket()

3668 smb['Tid'] = tid

3669

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)

3679

3680 self.sendSMB(smb)

3681

3682 if wait_answer:

3683 smb = self.recvSMB()

3684 if smb.isValidAnswer(SMB.SMB_COM_WRITE):

3685 return smb

3686 return None

3687

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

3692

3693 writeAndX = SMBCommand(SMB.SMB_COM_WRITE_ANDX)

3694 smb.addCommand(writeAndX)

3695

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

3704

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]

3716

3717 self.sendSMB(smb)

3718 if wait_answer:

3719 smbResp = self.recvSMB()

3720 smbResp.isValidAnswer(SMB.SMB_COM_WRITE_ANDX)

3721

3722 alreadySent = chunks_size

3723 sendData = sendData[chunks_size:]

3724

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:]

3735

3736 return smbResp

3737

3738 else:

3739 smb = smb_packet

3740

3741 self.sendSMB(smb)

3742

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

3748

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

3753

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)

3762

3763 self.sendSMB(smb)

3764 self._sess.send_packet(data)

3765

3766 if wait_answer:

3767 smb = self.recvSMB()

3768 if smb.isValidAnswer(SMB.SMB_COM_WRITE_RAW):

3769 return smb

3770 return None

3771

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)

3774

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

3783

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

3791

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

3795

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

3801

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

3813

3814 if self.__flags2 & SMB.FLAGS2_UNICODE:

3815 ntCreate['Data']['Pad'] = 0x0

3816 else:

3817 ntCreate = cmd

3818

3819 smb.addCommand(ntCreate)

3820

3821 self.sendSMB(smb)

3822

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'])

3829

3830 self.fid = ntCreateParameters['Fid']

3831 return ntCreateParameters['Fid']

3832

3833 def logoff(self):

3834 smb = NewSMBPacket()

3835

3836 logOff = SMBCommand(SMB.SMB_COM_LOGOFF_ANDX)

3837 logOff['Parameters'] = SMBLogOffAndX()

3838 smb.addCommand(logOff)

3839

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

3844

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

3848

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 = [ ]

3865

3866 totalDataCount = 1

3867 findData = b''

3868 findFirst2ParameterBlock = b''

3869 while len(findData) < totalDataCount:

3870 resp = self.recvSMB()

3871

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:]

3878

3879 findParameterBlock = SMBFindFirst2Response_Parameters(findFirst2ParameterBlock)

3880 # Save the SID for resume operations

3881 sid = findParameterBlock['SID']

3882

3883 while True:

3884 record = SMBFindFileBothDirectoryInfo(data = findData)

3885

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')

3890

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()

3917

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)

3929

3930 return files

3931

3932 def retr_file(self, service, filename, callback, mode = FILE_OPEN, offset = 0, password = None, shareAccessMode = SMB_ACCESS_READ):

3933 filename = filename.replace('/', '\\')

3934

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)

3939

3940 res = self.query_file_info(tid, fid)

3941 datasize = SMBQueryFileStandardInfo(res)['EndOfFile']

3942

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)

3948

3949 def stor_file(self, service, filename, callback, mode = FILE_OVERWRITE_IF, offset = 0, password = None, shareAccessMode = SMB_ACCESS_WRITE):

3950 filename = filename.replace('/', '\\')

3951

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 )

3956

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)

3962

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('/', '\\')

3965

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)

3975

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

3983

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)

3989

3990 self.sendSMB(smb)

3991

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)

3998

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)

4003

4004 tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)

4005 try:

4006 smb = NewSMBPacket()

4007 smb['Tid'] = tid

4008 smb['Mid'] = 0

4009

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)

4016

4017 self.sendSMB(smb)

4018

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)

4025

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)

4030

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

4034

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)

4041

4042 self.sendSMB(smb)

4043

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)

4050

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

4056

4057 smb = NewSMBPacket()

4058 smb['Tid'] = tid

4059 smb['Mid'] = 0

4060

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)

4065

4066 self.sendSMB(smb)

4067

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

4074

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

4083

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)

4091

4092 self.sendSMB(smb)

4093

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

4100

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

4106

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:]

4113

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']

4118

4119 def get_socket(self):

4120 return self._sess.get_socket()

4121

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 ''

4137

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

4147

4148 transCommand['Data'] = SMBNTTransaction_Data()

4149

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

4156

4157 if len(param) > 0:

4158 transCommand['Parameters']['ParameterOffset'] = offset

4159 else:

4160 transCommand['Parameters']['ParameterOffset'] = 0

4161

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)

4167

4168 if len(data) > 0:

4169 transCommand['Parameters']['DataOffset'] = offset

4170 else:

4171 transCommand['Parameters']['DataOffset'] = 0

4172

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)

4178

4179 self.sendSMB(smb_packet)

4180

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']:]

4198

4199 def echo(self, text = '', count = 1):

4200

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)

4208

4209 self.sendSMB(smb)

4210

4211 for i in range(count):

4212 resp = self.recvSMB()

4213 resp.isValidAnswer(SMB.SMB_COM_ECHO)

4214 return True

4215

4216 ERRDOS = { 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 }

4237

4238 ERRSRV = { 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 }

4265

4266 ERRHRD = { 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 }