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

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

## 2192 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# Impacket - Collection of Python classes for working with network protocols.

2#

3# SECUREAUTH LABS. Copyright (C) 2020 SecureAuth Corporation. All rights reserved.

4#

5# This software is provided under a slightly modified version

6# of the Apache Software License. See the accompanying LICENSE file

7# for more information.

8#

9# Author:

10# Altered source done by Alberto Solino (@agsolino)

11#

12# Copyright and license note from Pysmb:

13#

14# Copyright (C) 2001 Michael Teo <michaelteo@bigfoot.com>

15# smb.py - SMB/CIFS library

16#

17# This software is provided 'as-is', without any express or implied warranty.

18# In no event will the author be held liable for any damages arising from the

19# use of this software.

20#

21# Permission is granted to anyone to use this software for any purpose,

22# including commercial applications, and to alter it and redistribute it

23# freely, subject to the following restrictions:

24#

25# 1. The origin of this software must not be misrepresented; you must not

26# claim that you wrote the original software. If you use this software

27# in a product, an acknowledgment in the product documentation would be

28# appreciated but is not required.

29#

30# 2. Altered source versions must be plainly marked as such, and must not be

31# misrepresented as being the original software.

32#

33# 3. This notice cannot be removed or altered from any source distribution.

34#

35# Todo:

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

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

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

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

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

41# [ ] Try [SMB]transport fragmentation with overlapping segments

42# [ ] Try [SMB]transport fragmentation with out of order segments

43# [x] Do chained AndX requests

44# [ ] Transform the rest of the calls to structure

45# [X] Implement TRANS/TRANS2 reassembly for list_path

46#

47 from __future__ import division

48 from __future__ import print_function

49 import os

50 import socket

51 from binascii import a2b_hex

52 import datetime

53 from struct import pack, unpack

54 from contextlib import contextmanager

55 from pyasn1.type.univ import noValue

56

57 from impacket import nmb, ntlm, nt_errors, LOG

58 from impacket.structure import Structure

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

60 from impacket.krb5.gssapi import KRB5_AP_REQ

61

62# For signing

63 import hashlib

64

65 unicode_support = 0

66 unicode_convert = 1

67

68# Dialect for SMB1

69 SMB_DIALECT = 'NT LM 0.12'

70

71# Shared Device Type

72 SHARED_DISK = 0x00

73 SHARED_DISK_HIDDEN = 0x80000000

74 SHARED_PRINT_QUEUE = 0x01

75 SHARED_DEVICE = 0x02

76 SHARED_IPC = 0x03

77

78# Extended attributes mask

79 ATTR_ARCHIVE = 0x020

80 ATTR_COMPRESSED = 0x800

81 ATTR_NORMAL = 0x080

82 ATTR_HIDDEN = 0x002

83 ATTR_READONLY = 0x001

84 ATTR_TEMPORARY = 0x100

85 ATTR_DIRECTORY = 0x010

86 ATTR_SYSTEM = 0x004

87

88# Service Type

89 SERVICE_DISK = 'A:'

90 SERVICE_PRINTER = 'LPT1:'

91 SERVICE_IPC = 'IPC'

92 SERVICE_COMM = 'COMM'

93 SERVICE_ANY = '?????'

94

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

96 SV_TYPE_WORKSTATION = 0x00000001

97 SV_TYPE_SERVER = 0x00000002

98 SV_TYPE_SQLSERVER = 0x00000004

99 SV_TYPE_DOMAIN_CTRL = 0x00000008

100 SV_TYPE_DOMAIN_BAKCTRL = 0x00000010

101 SV_TYPE_TIME_SOURCE = 0x00000020

102 SV_TYPE_AFP = 0x00000040

103 SV_TYPE_NOVELL = 0x00000080

104 SV_TYPE_DOMAIN_MEMBER = 0x00000100

105 SV_TYPE_PRINTQ_SERVER = 0x00000200

106 SV_TYPE_DIALIN_SERVER = 0x00000400

107 SV_TYPE_XENIX_SERVER = 0x00000800

108 SV_TYPE_NT = 0x00001000

109 SV_TYPE_WFW = 0x00002000

110 SV_TYPE_SERVER_NT = 0x00004000

111 SV_TYPE_POTENTIAL_BROWSER = 0x00010000

112 SV_TYPE_BACKUP_BROWSER = 0x00020000

113 SV_TYPE_MASTER_BROWSER = 0x00040000

114 SV_TYPE_DOMAIN_MASTER = 0x00080000

115 SV_TYPE_LOCAL_LIST_ONLY = 0x40000000

116 SV_TYPE_DOMAIN_ENUM = 0x80000000

117

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

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

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

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

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

123

124# Share Access Mode

125 SMB_SHARE_COMPAT = 0x00

126 SMB_SHARE_DENY_EXCL = 0x10

127 SMB_SHARE_DENY_WRITE = 0x20

128 SMB_SHARE_DENY_READEXEC = 0x30

129 SMB_SHARE_DENY_NONE = 0x40

130 SMB_ACCESS_READ = 0x00

131 SMB_ACCESS_WRITE = 0x01

132 SMB_ACCESS_READWRITE = 0x02

133 SMB_ACCESS_EXEC = 0x03

134

135 TRANS_DISCONNECT_TID = 1

136 TRANS_NO_RESPONSE = 2

137

138 STATUS_SUCCESS = 0x00000000

139 STATUS_LOGON_FAILURE = 0xC000006D

140 STATUS_LOGON_TYPE_NOT_GRANTED = 0xC000015B

141 MAX_TFRAG_SIZE = 5840

142 EVASION_NONE = 0

143 EVASION_LOW = 1

144 EVASION_HIGH = 2

145 EVASION_MAX = 3

146 RPC_X_BAD_STUB_DATA = 0x6F7

147

148# SMB_FILE_ATTRIBUTES

149

150 SMB_FILE_ATTRIBUTE_NORMAL = 0x0000

151 SMB_FILE_ATTRIBUTE_READONLY = 0x0001

152 SMB_FILE_ATTRIBUTE_HIDDEN = 0x0002

153 SMB_FILE_ATTRIBUTE_SYSTEM = 0x0004

154 SMB_FILE_ATTRIBUTE_VOLUME = 0x0008

155 SMB_FILE_ATTRIBUTE_DIRECTORY = 0x0010

156 SMB_FILE_ATTRIBUTE_ARCHIVE = 0x0020

157 SMB_SEARCH_ATTRIBUTE_READONLY = 0x0100

158 SMB_SEARCH_ATTRIBUTE_HIDDEN = 0x0200

159 SMB_SEARCH_ATTRIBUTE_SYSTEM = 0x0400

160 SMB_SEARCH_ATTRIBUTE_DIRECTORY = 0x1000

161 SMB_SEARCH_ATTRIBUTE_ARCHIVE = 0x2000

162

163# Session SetupAndX Action flags

164 SMB_SETUP_GUEST = 0x01

165 SMB_SETUP_USE_LANMAN_KEY = 0x02

166

167# QUERY_INFORMATION levels

168 SMB_INFO_ALLOCATION = 0x0001

169 SMB_INFO_VOLUME = 0x0002

170 FILE_FS_SIZE_INFORMATION = 0x0003

171 SMB_QUERY_FS_VOLUME_INFO = 0x0102

172 SMB_QUERY_FS_SIZE_INFO = 0x0103

173 SMB_QUERY_FILE_EA_INFO = 0x0103

174 SMB_QUERY_FS_DEVICE_INFO = 0x0104

175 SMB_QUERY_FS_ATTRIBUTE_INFO = 0x0105

176 SMB_QUERY_FILE_BASIC_INFO = 0x0101

177 SMB_QUERY_FILE_STANDARD_INFO = 0x0102

178 SMB_QUERY_FILE_ALL_INFO = 0x0107

179 FILE_FS_FULL_SIZE_INFORMATION = 0x03EF

180

181# SET_INFORMATION levels

182 SMB_SET_FILE_DISPOSITION_INFO = 0x0102

183 SMB_SET_FILE_BASIC_INFO = 0x0101

184 SMB_SET_FILE_END_OF_FILE_INFO = 0x0104

185

186# Device Type [MS-CIFS] 2.2.8.2.5

187 FILE_DEVICE_BEEP = 0x0001

188 FILE_DEVICE_CD_ROM = 0x0002

189 FILE_DEVICE_CD_ROM_FILE_SYSTEM = 0x0003

190 FILE_DEVICE_CONTROLLER = 0x0004

191 FILE_DEVICE_DATALINK = 0x0005

192 FILE_DEVICE_DFS = 0x0006

193 FILE_DEVICE_DISK = 0x0007

194 FILE_DEVICE_DISK_FILE_SYSTEM = 0x0008

195 FILE_DEVICE_FILE_SYSTEM = 0x0009

196 FILE_DEVICE_INPORT_PORT = 0x000a

197 FILE_DEVICE_KEYBOARD = 0x000b

198 FILE_DEVICE_MAILSLOT = 0x000c

199 FILE_DEVICE_MIDI_IN = 0x000d

200 FILE_DEVICE_MIDI_OUT = 0x000e

201 FILE_DEVICE_MOUSE = 0x000f

202 FILE_DEVICE_MULTI_UNC_PROVIDER = 0x0010

203 FILE_DEVICE_NAMED_PIPE = 0x0011

204 FILE_DEVICE_NETWORK = 0x0012

205 FILE_DEVICE_NETWORK_BROWSER = 0x0013

206 FILE_DEVICE_NETWORK_FILE_SYSTEM = 0x0014

207 FILE_DEVICE_NULL = 0x0015

208 FILE_DEVICE_PARALLEL_PORT = 0x0016

209 FILE_DEVICE_PHYSICAL_NETCARD = 0x0017

210 FILE_DEVICE_PRINTER = 0x0018

211 FILE_DEVICE_SCANNER = 0x0019

212 FILE_DEVICE_SERIAL_MOUSE_PORT = 0x001a

213 FILE_DEVICE_SERIAL_PORT = 0x001b

214 FILE_DEVICE_SCREEN = 0x001c

215 FILE_DEVICE_SOUND = 0x001d

216 FILE_DEVICE_STREAMS = 0x001e

217 FILE_DEVICE_TAPE = 0x001f

218 FILE_DEVICE_TAPE_FILE_SYSTEM = 0x0020

219 FILE_DEVICE_TRANSPORT = 0x0021

220 FILE_DEVICE_UNKNOWN = 0x0022

221 FILE_DEVICE_VIDEO = 0x0023

222 FILE_DEVICE_VIRTUAL_DISK = 0x0024

223 FILE_DEVICE_WAVE_IN = 0x0025

224 FILE_DEVICE_WAVE_OUT = 0x0026

225 FILE_DEVICE_8042_PORT = 0x0027

226 FILE_DEVICE_NETWORK_REDIRECTOR = 0x0028

227 FILE_DEVICE_BATTERY = 0x0029

228 FILE_DEVICE_BUS_EXTENDER = 0x002a

229 FILE_DEVICE_MODEM = 0x002b

230 FILE_DEVICE_VDM = 0x002c

231

232# Device Characteristics [MS-CIFS] 2.2.8.2.5

233 FILE_REMOVABLE_MEDIA = 0x0001

234 FILE_READ_ONLY_DEVICE = 0x0002

235 FILE_FLOPPY_DISKETTE = 0x0004

236 FILE_WRITE_ONCE_MEDIA = 0x0008

237 FILE_REMOTE_DEVICE = 0x0010

238 FILE_DEVICE_IS_MOUNTED = 0x0020

239 FILE_VIRTUAL_VOLUME = 0x0040

240

241# File System Attributes

242 FILE_CASE_SENSITIVE_SEARCH = 0x00000001

243 FILE_CASE_PRESERVED_NAMES = 0x00000002

244 FILE_UNICODE_ON_DISK = 0x00000004

245 FILE_PERSISTENT_ACLS = 0x00000008

246 FILE_FILE_COMPRESSION = 0x00000010

247 FILE_VOLUME_IS_COMPRESSED = 0x00008000

248

249# FIND_FIRST2 flags and levels

250 SMB_FIND_CLOSE_AFTER_REQUEST = 0x0001

251 SMB_FIND_CLOSE_AT_EOS = 0x0002

252 SMB_FIND_RETURN_RESUME_KEYS = 0x0004

253 SMB_FIND_CONTINUE_FROM_LAST = 0x0008

254 SMB_FIND_WITH_BACKUP_INTENT = 0x0010

255

256 FILE_DIRECTORY_FILE = 0x00000001

257 FILE_DELETE_ON_CLOSE = 0x00001000

258 FILE_NON_DIRECTORY_FILE = 0x00000040

259

260 SMB_FIND_INFO_STANDARD = 0x0001

261 SMB_FIND_FILE_DIRECTORY_INFO = 0x0101

262 SMB_FIND_FILE_FULL_DIRECTORY_INFO= 0x0102

263 SMB_FIND_FILE_NAMES_INFO = 0x0103

264 SMB_FIND_FILE_BOTH_DIRECTORY_INFO= 0x0104

265 SMB_FIND_FILE_ID_FULL_DIRECTORY_INFO = 0x105

266 SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO = 0x106

267

268

269# DesiredAccess flags

270 FILE_READ_DATA = 0x00000001

271 FILE_WRITE_DATA = 0x00000002

272 FILE_APPEND_DATA = 0x00000004

273 FILE_EXECUTE = 0x00000020

274 MAXIMUM_ALLOWED = 0x02000000

275 GENERIC_ALL = 0x10000000

276 GENERIC_EXECUTE = 0x20000000

277 GENERIC_WRITE = 0x40000000

278 GENERIC_READ = 0x80000000

279

280# ShareAccess flags

281 FILE_SHARE_NONE = 0x00000000

282 FILE_SHARE_READ = 0x00000001

283 FILE_SHARE_WRITE = 0x00000002

284 FILE_SHARE_DELETE = 0x00000004

285

286# CreateDisposition flags

287 FILE_SUPERSEDE = 0x00000000

288 FILE_OPEN = 0x00000001

289 FILE_CREATE = 0x00000002

290 FILE_OPEN_IF = 0x00000003

291 FILE_OVERWRITE = 0x00000004

292 FILE_OVERWRITE_IF = 0x00000005

293

294 def strerror(errclass, errcode):

295 if errclass == 0x01:

296 return 'OS error', ERRDOS.get(errcode, 'Unknown error')

297 elif errclass == 0x02:

298 return 'Server error', ERRSRV.get(errcode, 'Unknown error')

299 elif errclass == 0x03:

300 return 'Hardware error', ERRHRD.get(errcode, 'Unknown error')

301 # This is not a standard error class for SMB

302 #elif errclass == 0x80:

303 # return 'Browse error', ERRBROWSE.get(errcode, 'Unknown error')

304 elif errclass == 0xff:

305 return 'Bad command', 'Bad command. Please file bug report'

306 else:

307 return 'Unknown error', 'Unknown error'

308

309# Raised when an error has occurred during a session

310 class SessionError(Exception):

311 # SMB X/Open error codes for the ERRDOS error class

312 ERRsuccess = 0

313 ERRbadfunc = 1

314 ERRbadfile = 2

315 ERRbadpath = 3

316 ERRnofids = 4

317 ERRnoaccess = 5

318 ERRbadfid = 6

319 ERRbadmcb = 7

320 ERRnomem = 8

321 ERRbadmem = 9

322 ERRbadenv = 10

323 ERRbadaccess = 12

324 ERRbaddata = 13

325 ERRres = 14

326 ERRbaddrive = 15

327 ERRremcd = 16

328 ERRdiffdevice = 17

329 ERRnofiles = 18

330 ERRgeneral = 31

331 ERRbadshare = 32

332 ERRlock = 33

333 ERRunsup = 50

334 ERRnetnamedel = 64

335 ERRnosuchshare = 67

336 ERRfilexists = 80

337 ERRinvalidparam = 87

338 ERRcannotopen = 110

339 ERRinsufficientbuffer = 122

340 ERRinvalidname = 123

341 ERRunknownlevel = 124

342 ERRnotlocked = 158

343 ERRrename = 183

344 ERRbadpipe = 230

345 ERRpipebusy = 231

346 ERRpipeclosing = 232

347 ERRnotconnected = 233

348 ERRmoredata = 234

349 ERRnomoreitems = 259

350 ERRbaddirectory = 267

351 ERReasnotsupported = 282

352 ERRlogonfailure = 1326

353 ERRbuftoosmall = 2123

354 ERRunknownipc = 2142

355 ERRnosuchprintjob = 2151

356 ERRinvgroup = 2455

357

358 # here's a special one from observing NT

359 ERRnoipc = 66

360

361 # These errors seem to be only returned by the NT printer driver system

362 ERRdriveralreadyinstalled = 1795

363 ERRunknownprinterport = 1796

364 ERRunknownprinterdriver = 1797

365 ERRunknownprintprocessor = 1798

366 ERRinvalidseparatorfile = 1799

367 ERRinvalidjobpriority = 1800

368 ERRinvalidprintername = 1801

369 ERRprinteralreadyexists = 1802

370 ERRinvalidprintercommand = 1803

371 ERRinvaliddatatype = 1804

372 ERRinvalidenvironment = 1805

373

374 ERRunknownprintmonitor = 3000

375 ERRprinterdriverinuse = 3001

376 ERRspoolfilenotfound = 3002

377 ERRnostartdoc = 3003

378 ERRnoaddjob = 3004

379 ERRprintprocessoralreadyinstalled = 3005

380 ERRprintmonitoralreadyinstalled = 3006

381 ERRinvalidprintmonitor = 3007

382 ERRprintmonitorinuse = 3008

383 ERRprinterhasjobsqueued = 3009

384

385 # Error codes for the ERRSRV class

386

387 ERRerror = 1

388 ERRbadpw = 2

389 ERRbadtype = 3

390 ERRaccess = 4

391 ERRinvnid = 5

392 ERRinvnetname = 6

393 ERRinvdevice = 7

394 ERRqfull = 49

395 ERRqtoobig = 50

396 ERRinvpfid = 52

397 ERRsmbcmd = 64

398 ERRsrverror = 65

399 ERRfilespecs = 67

400 ERRbadlink = 68

401 ERRbadpermits = 69

402 ERRbadpid = 70

403 ERRsetattrmode = 71

404 ERRpaused = 81

405 ERRmsgoff = 82

406 ERRnoroom = 83

407 ERRrmuns = 87

408 ERRtimeout = 88

409 ERRnoresource = 89

410 ERRtoomanyuids = 90

411 ERRbaduid = 91

412 ERRuseMPX = 250

413 ERRuseSTD = 251

414 ERRcontMPX = 252

415 ERRbadPW = None

416 ERRnosupport = 0

417 ERRunknownsmb = 22

418

419 # Error codes for the ERRHRD class

420

421 ERRnowrite = 19

422 ERRbadunit = 20

423 ERRnotready = 21

424 ERRbadcmd = 22

425 ERRdata = 23

426 ERRbadreq = 24

427 ERRseek = 25

428 ERRbadmedia = 26

429 ERRbadsector = 27

430 ERRnopaper = 28

431 ERRwrite = 29

432 ERRread = 30

433 ERRwrongdisk = 34

434 ERRFCBunavail = 35

435 ERRsharebufexc = 36

436 ERRdiskfull = 39

437

438

439 hard_msgs = {

440 19: ("ERRnowrite", "Attempt to write on write-protected diskette."),

441 20: ("ERRbadunit", "Unknown unit."),

442 21: ("ERRnotready", "Drive not ready."),

443 22: ("ERRbadcmd", "Unknown command."),

444 23: ("ERRdata", "Data error (CRC)."),

445 24: ("ERRbadreq", "Bad request structure length."),

446 25: ("ERRseek", "Seek error."),

447 26: ("ERRbadmedia", "Unknown media type."),

448 27: ("ERRbadsector", "Sector not found."),

449 28: ("ERRnopaper", "Printer out of paper."),

450 29: ("ERRwrite", "Write fault."),

451 30: ("ERRread", "Read fault."),

452 31: ("ERRgeneral", "General failure."),

453 32: ("ERRbadshare", "An open conflicts with an existing open."),

454 33: ("ERRlock", "A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."),

455 34: ("ERRwrongdisk", "The wrong disk was found in a drive."),

456 35: ("ERRFCBUnavail", "No FCBs are available to process request."),

457 36: ("ERRsharebufexc", "A sharing buffer has been exceeded.")

458 }

459

460 dos_msgs = {

461 ERRbadfunc: ("ERRbadfunc", "Invalid function."),

462 ERRbadfile: ("ERRbadfile", "File not found."),

463 ERRbadpath: ("ERRbadpath", "Directory invalid."),

464 ERRnofids: ("ERRnofids", "No file descriptors available"),

465 ERRnoaccess: ("ERRnoaccess", "Access denied."),

466 ERRbadfid: ("ERRbadfid", "Invalid file handle."),

467 ERRbadmcb: ("ERRbadmcb", "Memory control blocks destroyed."),

468 ERRnomem: ("ERRnomem", "Insufficient server memory to perform the requested function."),

469 ERRbadmem: ("ERRbadmem", "Invalid memory block address."),

470 ERRbadenv: ("ERRbadenv", "Invalid environment."),

471 11: ("ERRbadformat", "Invalid format."),

472 ERRbadaccess: ("ERRbadaccess", "Invalid open mode."),

473 ERRbaddata: ("ERRbaddata", "Invalid data."),

474 ERRres: ("ERRres", "reserved."),

475 ERRbaddrive: ("ERRbaddrive", "Invalid drive specified."),

476 ERRremcd: ("ERRremcd", "A Delete Directory request attempted to remove the server's current directory."),

477 ERRdiffdevice: ("ERRdiffdevice", "Not same device."),

478 ERRnofiles: ("ERRnofiles", "A File Search command can find no more files matching the specified criteria."),

479 ERRbadshare: ("ERRbadshare", "The sharing mode specified for an Open conflicts with existing FIDs on the file."),

480 ERRlock: ("ERRlock", "A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."),

481 ERRunsup: ("ERRunsup", "The operation is unsupported"),

482 ERRnosuchshare: ("ERRnosuchshare", "You specified an invalid share name"),

483 ERRfilexists: ("ERRfilexists", "The file named in a Create Directory, Make New File or Link request already exists."),

484 ERRinvalidname: ("ERRinvalidname", "Invalid name"),

485 ERRbadpipe: ("ERRbadpipe", "Pipe invalid."),

486 ERRpipebusy: ("ERRpipebusy", "All instances of the requested pipe are busy."),

487 ERRpipeclosing: ("ERRpipeclosing", "Pipe close in progress."),

488 ERRnotconnected: ("ERRnotconnected", "No process on other end of pipe."),

489 ERRmoredata: ("ERRmoredata", "There is more data to be returned."),

490 ERRinvgroup: ("ERRinvgroup", "Invalid workgroup (try the -W option)"),

491 ERRlogonfailure: ("ERRlogonfailure", "Logon failure"),

492 ERRdiskfull: ("ERRdiskfull", "Disk full"),

493 ERRgeneral: ("ERRgeneral", "General failure"),

494 ERRunknownlevel: ("ERRunknownlevel", "Unknown info level")

495 }

496

497 server_msgs = {

498 1: ("ERRerror", "Non-specific error code."),

499 2: ("ERRbadpw", "Bad password - name/password pair in a Tree Connect or Session Setup are invalid."),

500 3: ("ERRbadtype", "reserved."),

501 4: ("ERRaccess", "The requester does not have the necessary access rights within the specified context for the requested function. The context is defined by the TID or the UID."),

502 5: ("ERRinvnid", "The tree ID (TID) specified in a command was invalid."),

503 6: ("ERRinvnetname", "Invalid network name in tree connect."),

504 7: ("ERRinvdevice", "Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."),

505 49: ("ERRqfull", "Print queue full (files) -- returned by open print file."),

506 50: ("ERRqtoobig", "Print queue full -- no space."),

507 51: ("ERRqeof", "EOF on print queue dump."),

508 52: ("ERRinvpfid", "Invalid print file FID."),

509 64: ("ERRsmbcmd", "The server did not recognize the command received."),

510 65: ("ERRsrverror","The server encountered an internal error, e.g., system file unavailable."),

511 67: ("ERRfilespecs", "The file handle (FID) and pathname parameters contained an invalid combination of values."),

512 68: ("ERRreserved", "reserved."),

513 69: ("ERRbadpermits", "The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."),

514 70: ("ERRreserved", "reserved."),

515 71: ("ERRsetattrmode", "The attribute mode in the Set File Attribute request is invalid."),

516 81: ("ERRpaused", "Server is paused."),

517 82: ("ERRmsgoff", "Not receiving messages."),

518 83: ("ERRnoroom", "No room to buffer message."),

519 87: ("ERRrmuns", "Too many remote user names."),

520 88: ("ERRtimeout", "Operation timed out."),

521 89: ("ERRnoresource", "No resources currently available for request."),

522 90: ("ERRtoomanyuids", "Too many UIDs active on this session."),

523 91: ("ERRbaduid", "The UID is not known as a valid ID on this session."),

524 250: ("ERRusempx","Temp unable to support Raw, use MPX mode."),

525 251: ("ERRusestd","Temp unable to support Raw, use standard read/write."),

526 252: ("ERRcontmpx", "Continue in MPX mode."),

527 253: ("ERRreserved", "reserved."),

528 254: ("ERRreserved", "reserved."),

529 0xFFFF: ("ERRnosupport", "Function not supported.")

530 }

531 # Error clases

532

533 ERRDOS = 0x1

534 error_classes = { 0: ("SUCCESS", {}),

535 ERRDOS: ("ERRDOS", dos_msgs),

536 0x02: ("ERRSRV",server_msgs),

537 0x03: ("ERRHRD",hard_msgs),

538 0x04: ("ERRXOS", {} ),

539 0xE1: ("ERRRMX1", {} ),

540 0xE2: ("ERRRMX2", {} ),

541 0xE3: ("ERRRMX3", {} ),

542 0xFF: ("ERRCMD", {} ) }

543

544

545

546 def __init__( self, error_string, error_class, error_code, nt_status = 0, packet=0):

547 Exception.__init__(self, error_string)

548 self.nt_status = nt_status

549 self._args = error_string

550 if nt_status: 550 ↛ 554line 550 didn't jump to line 554, because the condition on line 550 was never false

551 self.error_class = 0

552 self.error_code = (error_code << 16) + error_class

553 else:

554 self.error_class = error_class

555 self.error_code = error_code

556 self.packet = packet

557

558 def get_error_class( self ):

559 return self.error_class

560

561 def get_error_code( self ):

562 return self.error_code

563

564 def get_error_packet(self):

565 return self.packet

566

567 def __str__( self ):

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

569 if not error_class:

570 error_code_str = self.error_code

571 error_class_str = self.error_class

572 else:

573 error_class_str = error_class[0]

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

575 if not error_code:

576 error_code_str = self.error_code

577 else:

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

579

580 if self.nt_status:

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

582 else:

583 # Fall back to the old format

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

585

586

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

588# currently supported by pysmb

589 class UnsupportedFeature(Exception):

590 pass

591

592# Contains information about a SMB shared device/service

593 class SharedDevice:

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

595 self.__name = name

596 self.__type = share_type

597 self.__comment = comment

598

599 def get_name(self):

600 return self.__name

601

602 def get_type(self):

603 return self.__type

604

605 def get_comment(self):

606 return self.__comment

607

608 def __repr__(self):

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

610

611

612# Contains information about the shared file/directory

613 class SharedFile:

614 def __init__(self, ctime, atime, mtime, filesize, allocsize, attribs, shortname, longname):

615 self.__ctime = ctime

616 self.__atime = atime

617 self.__mtime = mtime

618 self.__filesize = filesize

619 self.__allocsize = allocsize

620 self.__attribs = attribs

621 try:

622 if isinstance(shortname,bytes): 622 ↛ 623line 622 didn't jump to line 623, because the condition on line 622 was never true

623 self.__shortname = shortname[:shortname.index(b'\0')]

624 else:

625 self.__shortname = shortname[:shortname.index('\0')]

626 except (ValueError, TypeError):

627 self.__shortname = shortname

628 try:

629 if isinstance(shortname,bytes): 629 ↛ 630line 629 didn't jump to line 630, because the condition on line 629 was never true

630 self.__longname = longname[:longname.index(b'\0')]

631 else:

632 self.__longname = longname[:longname.index('\0')]

633 except (ValueError, TypeError):

634 self.__longname = longname

635

636 def get_ctime(self):

637 return self.__ctime

638

639 def get_ctime_epoch(self):

640 return self.__convert_smbtime(self.__ctime)

641

642 def get_mtime(self):

643 return self.__mtime

644

645 def get_mtime_epoch(self):

646 return self.__convert_smbtime(self.__mtime)

647

648 def get_atime(self):

649 return self.__atime

650

651 def get_atime_epoch(self):

652 return self.__convert_smbtime(self.__atime)

653

654 def get_filesize(self):

655 return self.__filesize

656

657 def get_allocsize(self):

658 return self.__allocsize

659

660 def get_attributes(self):

661 return self.__attribs

662

663 def is_archive(self):

664 return self.__attribs & ATTR_ARCHIVE

665

666 def is_compressed(self):

667 return self.__attribs & ATTR_COMPRESSED

668

669 def is_normal(self):

670 return self.__attribs & ATTR_NORMAL

671

672 def is_hidden(self):

673 return self.__attribs & ATTR_HIDDEN

674

675 def is_readonly(self):

676 return self.__attribs & ATTR_READONLY

677

678 def is_temporary(self):

679 return self.__attribs & ATTR_TEMPORARY

680

681 def is_directory(self):

682 return self.__attribs & ATTR_DIRECTORY

683

684 def is_system(self):

685 return self.__attribs & ATTR_SYSTEM

686

687 def get_shortname(self):

688 return self.__shortname

689

690 def get_longname(self):

691 return self.__longname

692

693 def __repr__(self):

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

695

696 @staticmethod

697 def __convert_smbtime(t):

698 x = t >> 32

699 y = t & 0xffffffff

700 geo_cal_offset = 11644473600.0 # = 369.0 * 365.25 * 24 * 60 * 60 - (3.0 * 24 * 60 * 60 + 6.0 * 60 * 60)

701 return (x * 4.0 * (1 << 30) + (y & 0xfff00000)) * 1.0e-7 - geo_cal_offset

702

703

704# Contain information about a SMB machine

705 class SMBMachine:

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

707 self.__nbname = nbname

708 self.__type = nbt_type

709 self.__comment = comment

710

711 def __repr__(self):

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

713

714 class SMBDomain:

715 def __init__(self, nbgroup, domain_type, master_browser):

716 self.__nbgroup = nbgroup

717 self.__type = domain_type

718 self.__master_browser = master_browser

719

720 def __repr__(self):

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

722

723# Represents a SMB Packet

724 class NewSMBPacket(Structure):

725 structure = (

726 ('Signature', '"\xffSMB'),

727 ('Command','B=0'),

728 ('ErrorClass','B=0'),

729 ('_reserved','B=0'),

730 ('ErrorCode','<H=0'),

731 ('Flags1','B=0'),

732 ('Flags2','<H=0'),

733 ('PIDHigh','<H=0'),

734 ('SecurityFeatures','8s=""'),

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

736 ('Tid','<H=0xffff'),

737 ('Pid','<H=0'),

738 ('Uid','<H=0'),

739 ('Mid','<H=0'),

740 ('Data','*:'),

741 )

742

743 def __init__(self, **kargs):

744 Structure.__init__(self, **kargs)

745

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

747 self['Flags2'] = 0

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

749 self['Flags1'] = 0

750

751 if 'data' not in kargs:

752 self['Data'] = []

753

754 def addCommand(self, command):

755 if len(self['Data']) == 0: 755 ↛ 758line 755 didn't jump to line 758, because the condition on line 755 was never false

756 self['Command'] = command.command

757 else:

758 self['Data'][-1]['Parameters']['AndXCommand'] = command.command

759 self['Data'][-1]['Parameters']['AndXOffset'] = len(self)

760 self['Data'].append(command)

761

762 def isMoreData(self):

763 return (self['Command'] in [SMB.SMB_COM_TRANSACTION, SMB.SMB_COM_READ_ANDX, SMB.SMB_COM_READ_RAW] and

764 self['ErrorClass'] == 1 and self['ErrorCode'] == SessionError.ERRmoredata)

765

766 def isMoreProcessingRequired(self):

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

768

769 def isValidAnswer(self, cmd):

770 # this was inside a loop reading more from the net (with recv_packet(None))

771 if self['Command'] == cmd: 771 ↛ 780line 771 didn't jump to line 780, because the condition on line 771 was never false

772 if (self['ErrorClass'] == 0x00 and self['ErrorCode'] == 0x00):

773 return 1

774 elif self.isMoreData(): 774 ↛ 775line 774 didn't jump to line 775, because the condition on line 774 was never true

775 return 1

776 elif self.isMoreProcessingRequired():

777 return 1

778 raise SessionError("SMB Library Error", self['ErrorClass'] + (self['_reserved'] << 8), self['ErrorCode'], self['Flags2'] & SMB.FLAGS2_NT_STATUS, self)

779 else:

780 raise UnsupportedFeature("Unexpected answer from server: Got %d, Expected %d" % (self['Command'], cmd))

781

782

783 class SMBCommand(Structure):

784 structure = (

785 ('WordCount', 'B=len(Parameters)//2'),

786 ('_ParametersLength','_-Parameters','WordCount*2'),

787 ('Parameters',':'), # default set by constructor

788 ('ByteCount','<H-Data'),

789 ('Data',':'), # default set by constructor

790 )

791

792 def __init__(self, commandOrData = None, data = None, **kargs):

793 if type(commandOrData) == type(0):

794 self.command = commandOrData

795 else:

796 data = data or commandOrData

797

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

799

800 if data is None:

801 self['Parameters'] = ''

802 self['Data'] = ''

803

804 class AsciiOrUnicodeStructure(Structure):

805 UnicodeStructure = ()

806 AsciiStructure = ()

807 def __init__(self, flags = 0, **kargs):

808 if flags & SMB.FLAGS2_UNICODE:

809 self.structure = self.UnicodeStructure

810 else:

811 self.structure = self.AsciiStructure

812 Structure.__init__(self, **kargs)

813

814 class SMBCommand_Parameters(Structure):

815 pass

816

817 class SMBAndXCommand_Parameters(Structure):

818 commonHdr = (

819 ('AndXCommand','B=0xff'),

820 ('_reserved','B=0'),

821 ('AndXOffset','<H=0'),

822 )

823 structure = ( # default structure, overridden by subclasses

824 ('Data',':=""'),

825 )

826

827############# TRANSACTIONS RELATED

828# TRANS2_QUERY_FS_INFORMATION

829# QUERY_FS Information Levels

830# SMB_QUERY_FS_ATTRIBUTE_INFO

831 class SMBQueryFsAttributeInfo(Structure):

832 structure = (

833 ('FileSystemAttributes','<L'),

834 ('MaxFilenNameLengthInBytes','<L'),

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

836 ('FileSystemName',':'),

837 )

838

839 class SMBQueryFsInfoVolume(AsciiOrUnicodeStructure):

840 commonHdr = (

841 ('ulVolSerialNbr','<L=0xABCDEFAA'),

842 ('cCharCount','<B-VolumeLabel'),

843 )

844 AsciiStructure = (

845 ('VolumeLabel','z'),

846 )

847 UnicodeStructure = (

848 ('VolumeLabel','u'),

849 )

850

851# FILE_FS_SIZE_INFORMATION

852 class FileFsSizeInformation(Structure):

853 structure = (

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

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

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

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

858 )

859

860# SMB_QUERY_FS_SIZE_INFO

861 class SMBQueryFsSizeInfo(Structure):

862 structure = (

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

864 ('TotalFreeAllocationUnits','<q=14851044'),

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

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

867 )

868# FILE_FS_FULL_SIZE_INFORMATION

869 class SMBFileFsFullSizeInformation(Structure):

870 structure = (

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

872 ('CallerAvailableAllocationUnits','<q=148529400'),

873 ('ActualAvailableAllocationUnits','<q=148529400'),

874 ('SectorsPerAllocationUnit','<L=15'),

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

876 )

877# SMB_QUERY_FS_VOLUME_INFO

878 class SMBQueryFsVolumeInfo(Structure):

879 structure = (

880 ('VolumeCreationTime','<q'),

881 ('SerialNumber','<L=0xABCDEFAA'),

882 ('VolumeLabelSize','<L=len(VolumeLabel)'),

883 ('Reserved','<H=0x10'),

884 ('VolumeLabel',':')

885 )

886

887# SMB_QUERY_FS_DEVICE_INFO

888 class SMBQueryFsDeviceInfo(Structure):

889 structure = (

890 ('DeviceType', '<L=0'),

891 ('DeviceCharacteristics', '<L=0')

892 )

893

894

895# SMB_FIND_FILE_BOTH_DIRECTORY_INFO level

896 class SMBFindFileBothDirectoryInfo(AsciiOrUnicodeStructure):

897 commonHdr = (

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

899 ('FileIndex','<L=0'),

900 ('CreationTime','<q'),

901 ('LastAccessTime','<q'),

902 ('LastWriteTime','<q'),

903 ('LastChangeTime','<q'),

904 ('EndOfFile','<q=0'),

905 ('AllocationSize','<q=0'),

906 ('ExtFileAttributes','<L=0'),

907 )

908 AsciiStructure = (

909 ('FileNameLength','<L-FileName','len(FileName)'),

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

911 ('ShortNameLength','<B=0'),

912 ('Reserved','<B=0'),

913 ('ShortName','24s'),

914 ('FileName',':'),

915 )

916 UnicodeStructure = (

917 ('FileNameLength','<L-FileName','len(FileName)*2'),

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

919 ('ShortNameLength','<B=0'),

920 ('Reserved','<B=0'),

921 ('ShortName','24s'),

922 ('FileName',':'),

923 )

924

925# SMB_FIND_FILE_ID_FULL_DIRECTORY_INFO level

926 class SMBFindFileIdFullDirectoryInfo(AsciiOrUnicodeStructure):

927 commonHdr = (

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

929 ('FileIndex','<L=0'),

930 ('CreationTime','<q'),

931 ('LastAccessTime','<q'),

932 ('LastWriteTime','<q'),

933 ('LastChangeTime','<q'),

934 ('EndOfFile','<q=0'),

935 ('AllocationSize','<q=0'),

936 ('ExtFileAttributes','<L=0'),

937 )

938 AsciiStructure = (

939 ('FileNameLength','<L-FileName','len(FileName)'),

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

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

942 ('FileID','<q=0'),

943 ('FileName','z'),

944 )

945 UnicodeStructure = (

946 ('FileNameLength','<L-FileName','len(FileName)*2'),

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

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

949 ('FileID','<q=0'),

950 ('FileName',':'),

951 )

952

953# SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO level

954 class SMBFindFileIdBothDirectoryInfo(AsciiOrUnicodeStructure):

955 commonHdr = (

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

957 ('FileIndex','<L=0'),

958 ('CreationTime','<q'),

959 ('LastAccessTime','<q'),

960 ('LastWriteTime','<q'),

961 ('LastChangeTime','<q'),

962 ('EndOfFile','<q=0'),

963 ('AllocationSize','<q=0'),

964 ('ExtFileAttributes','<L=0'),

965 )

966 AsciiStructure = (

967 ('FileNameLength','<L-FileName','len(FileName)'),

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

969 ('ShortNameLength','<B=0'),

970 ('Reserved','<B=0'),

971 ('ShortName','24s'),

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

973 ('FileID','<q=0'),

974 ('FileName','z'),

975 )

976 UnicodeStructure = (

977 ('FileNameLength','<L-FileName','len(FileName)*2'),

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

979 ('ShortNameLength','<B=0'),

980 ('Reserved','<B=0'),

981 ('ShortName','24s'),

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

983 ('FileID','<q=0'),

984 ('FileName',':'),

985 )

986

987# SMB_FIND_FILE_DIRECTORY_INFO level

988 class SMBFindFileDirectoryInfo(AsciiOrUnicodeStructure):

989 commonHdr = (

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

991 ('FileIndex','<L=0'),

992 ('CreationTime','<q'),

993 ('LastAccessTime','<q'),

994 ('LastWriteTime','<q'),

995 ('LastChangeTime','<q'),

996 ('EndOfFile','<q=0'),

997 ('AllocationSize','<q=1'),

998 ('ExtFileAttributes','<L=0'),

999 )

1000 AsciiStructure = (

1001 ('FileNameLength','<L-FileName','len(FileName)'),

1002 ('FileName','z'),

1003 )

1004 UnicodeStructure = (

1005 ('FileNameLength','<L-FileName','len(FileName)*2'),

1006 ('FileName',':'),

1007 )

1008

1009# SMB_FIND_FILE_NAMES_INFO level

1010 class SMBFindFileNamesInfo(AsciiOrUnicodeStructure):

1011 commonHdr = (

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

1013 ('FileIndex','<L=0'),

1014 )

1015 AsciiStructure = (

1016 ('FileNameLength','<L-FileName','len(FileName)'),

1017 ('FileName','z'),

1018 )

1019 UnicodeStructure = (

1020 ('FileNameLength','<L-FileName','len(FileName)*2'),

1021 ('FileName',':'),

1022 )

1023

1024# SMB_FIND_FILE_FULL_DIRECTORY_INFO level

1025 class SMBFindFileFullDirectoryInfo(AsciiOrUnicodeStructure):

1026 commonHdr = (

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

1028 ('FileIndex','<L=0'),

1029 ('CreationTime','<q'),

1030 ('LastAccessTime','<q'),

1031 ('LastWriteTime','<q'),

1032 ('LastChangeTime','<q'),

1033 ('EndOfFile','<q=0'),

1034 ('AllocationSize','<q=1'),

1035 ('ExtFileAttributes','<L=0'),

1036 )

1037 AsciiStructure = (

1038 ('FileNameLength','<L-FileName','len(FileName)'),

1039 ('EaSize','<L'),

1040 ('FileName','z'),

1041 )

1042 UnicodeStructure = (

1043 ('FileNameLength','<L-FileName','len(FileName)*2'),

1044 ('EaSize','<L'),

1045 ('FileName',':'),

1046 )

1047

1048# SMB_FIND_INFO_STANDARD level

1049 class SMBFindInfoStandard(AsciiOrUnicodeStructure):

1050 commonHdr = (

1051 ('ResumeKey','<L=0xff'),

1052 ('CreationDate','<H=0'),

1053 ('CreationTime','<H=0'),

1054 ('LastAccessDate','<H=0'),

1055 ('LastAccessTime','<H=0'),

1056 ('LastWriteDate','<H=0'),

1057 ('LastWriteTime','<H=0'),

1058 ('EaSize','<L'),

1059 ('AllocationSize','<L=1'),

1060 ('ExtFileAttributes','<H=0'),

1061 )

1062 AsciiStructure = (

1063 ('FileNameLength','<B-FileName','len(FileName)'),

1064 ('FileName','z'),

1065 )

1066 UnicodeStructure = (

1067 ('FileNameLength','<B-FileName','len(FileName)*2'),

1068 ('FileName',':'),

1069 )

1070

1071# SET_FILE_INFORMATION structures

1072# SMB_SET_FILE_DISPOSITION_INFO

1073 class SMBSetFileDispositionInfo(Structure):

1074 structure = (

1075 ('DeletePending','<B'),

1076 )

1077

1078# SMB_SET_FILE_BASIC_INFO

1079 class SMBSetFileBasicInfo(Structure):

1080 structure = (

1081 ('CreationTime','<q'),

1082 ('LastAccessTime','<q'),

1083 ('LastWriteTime','<q'),

1084 ('ChangeTime','<q'),

1085 ('ExtFileAttributes','<H'),

1086 ('Reserved','<L'),

1087 )

1088

1089# FILE_STREAM_INFORMATION

1090 class SMBFileStreamInformation(Structure):

1091 commonHdr = (

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

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

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

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

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

1097 )

1098

1099# FILE_NETWORK_OPEN_INFORMATION

1100 class SMBFileNetworkOpenInfo(Structure):

1101 structure = (

1102 ('CreationTime','<q=0'),

1103 ('LastAccessTime','<q=0'),

1104 ('LastWriteTime','<q=0'),

1105 ('ChangeTime','<q=0'),

1106 ('AllocationSize','<q=0'),

1107 ('EndOfFile','<q=0'),

1108 ('FileAttributes','<L=0'),

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

1110 )

1111

1112# SMB_SET_FILE_END_OF_FILE_INFO

1113 class SMBSetFileEndOfFileInfo(Structure):

1114 structure = (

1115 ('EndOfFile','<q'),

1116 )

1117

1118# TRANS2_FIND_NEXT2

1119 class SMBFindNext2_Parameters(AsciiOrUnicodeStructure):

1120 commonHdr = (

1121 ('SID','<H'),

1122 ('SearchCount','<H'),

1123 ('InformationLevel','<H'),

1124 ('ResumeKey','<L'),

1125 ('Flags','<H'),

1126 )

1127 AsciiStructure = (

1128 ('FileName','z'),

1129 )

1130 UnicodeStructure = (

1131 ('FileName','u'),

1132 )

1133

1134 class SMBFindNext2Response_Parameters(Structure):

1135 structure = (

1136 ('SearchCount','<H'),

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

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

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

1140 )

1141

1142 class SMBFindNext2_Data(Structure):

1143 structure = (

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

1145 ('GetExtendedAttributesList',':'),

1146 )

1147

1148

1149# TRANS2_FIND_FIRST2

1150 class SMBFindFirst2Response_Parameters(Structure):

1151 structure = (

1152 ('SID','<H'),

1153 ('SearchCount','<H'),

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

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

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

1157 )

1158

1159 class SMBFindFirst2_Parameters(AsciiOrUnicodeStructure):

1160 commonHdr = (

1161 ('SearchAttributes','<H'),

1162 ('SearchCount','<H'),

1163 ('Flags','<H'),

1164 ('InformationLevel','<H'),

1165 ('SearchStorageType','<L'),

1166 )

1167 AsciiStructure = (

1168 ('FileName','z'),

1169 )

1170 UnicodeStructure = (

1171 ('FileName','u'),

1172 )

1173

1174 class SMBFindFirst2_Data(Structure):

1175 structure = (

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

1177 ('GetExtendedAttributesList',':'),

1178 )

1179

1180# TRANS2_SET_PATH_INFORMATION

1181 class SMBSetPathInformation_Parameters(AsciiOrUnicodeStructure):

1182 commonHdr = (

1183 ('InformationLevel','<H'),

1184 ('Reserved','<L'),

1185 )

1186 AsciiStructure = (

1187 ('FileName','z'),

1188 )

1189 UnicodeStructure = (

1190 ('FileName','u'),

1191 )

1192

1193 class SMBSetPathInformationResponse_Parameters(Structure):

1194 structure = (

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

1196 )

1197

1198# TRANS2_SET_FILE_INFORMATION

1199 class SMBSetFileInformation_Parameters(Structure):

1200 structure = (

1201 ('FID','<H'),

1202 ('InformationLevel','<H'),

1203 ('Reserved','<H'),

1204 )

1205

1206 class SMBSetFileInformationResponse_Parameters(Structure):

1207 structure = (

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

1209 )

1210

1211# TRANS2_QUERY_FILE_INFORMATION

1212 class SMBQueryFileInformation_Parameters(Structure):

1213 structure = (

1214 ('FID','<H'),

1215 ('InformationLevel','<H'),

1216 )

1217

1218 class SMBQueryFileInformationResponse_Parameters(Structure):

1219 structure = (

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

1221 )

1222

1223 class SMBQueryFileInformation_Data(Structure):

1224 structure = (

1225 ('GetExtendedAttributeList',':'),

1226 )

1227

1228# TRANS2_QUERY_PATH_INFORMATION

1229 class SMBQueryPathInformationResponse_Parameters(Structure):

1230 structure = (

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

1232 )

1233

1234 class SMBQueryPathInformation_Parameters(AsciiOrUnicodeStructure):

1235 commonHdr = (

1236 ('InformationLevel','<H'),

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

1238 )

1239 AsciiStructure = (

1240 ('FileName','z'),

1241 )

1242 UnicodeStructure = (

1243 ('FileName','u'),

1244 )

1245

1246 class SMBQueryPathInformation_Data(Structure):

1247 structure = (

1248 ('GetExtendedAttributeList',':'),

1249 )

1250

1251

1252# SMB_QUERY_FILE_EA_INFO

1253 class SMBQueryFileEaInfo(Structure):

1254 structure = (

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

1256 )

1257

1258# SMB_QUERY_FILE_BASIC_INFO

1259 class SMBQueryFileBasicInfo(Structure):

1260 structure = (

1261 ('CreationTime','<q'),

1262 ('LastAccessTime','<q'),

1263 ('LastWriteTime','<q'),

1264 ('LastChangeTime','<q'),

1265 ('ExtFileAttributes','<L'),

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

1267 )

1268

1269# SMB_QUERY_FILE_STANDARD_INFO

1270 class SMBQueryFileStandardInfo(Structure):

1271 structure = (

1272 ('AllocationSize','<q'),

1273 ('EndOfFile','<q'),

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

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

1276 ('Directory','<B'),

1277 )

1278

1279# SMB_QUERY_FILE_ALL_INFO

1280 class SMBQueryFileAllInfo(Structure):

1281 structure = (

1282 ('CreationTime','<q'),

1283 ('LastAccessTime','<q'),

1284 ('LastWriteTime','<q'),

1285 ('LastChangeTime','<q'),

1286 ('ExtFileAttributes','<L'),

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

1288 ('AllocationSize','<q'),

1289 ('EndOfFile','<q'),

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

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

1292 ('Directory','<B'),

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

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

1295 ('FileNameLength','<L-FileName','len(FileName)'),

1296 ('FileName',':'),

1297 )

1298

1299# \PIPE\LANMAN NetShareEnum

1300 class SMBNetShareEnum(Structure):

1301 structure = (

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

1303 ('ParamDesc','z'),

1304 ('DataDesc','z'),

1305 ('InfoLevel','<H'),

1306 ('ReceiveBufferSize','<H'),

1307 )

1308

1309 class SMBNetShareEnumResponse(Structure):

1310 structure = (

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

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

1313 ('EntriesReturned','<H'),

1314 ('EntriesAvailable','<H'),

1315 )

1316

1317 class NetShareInfo1(Structure):

1318 structure = (

1319 ('NetworkName','13s'),

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

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

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

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

1324 )

1325

1326# \PIPE\LANMAN NetServerGetInfo

1327 class SMBNetServerGetInfoResponse(Structure):

1328 structure = (

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

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

1331 ('TotalBytesAvailable','<H'),

1332 )

1333

1334 class SMBNetServerInfo1(Structure):

1335 # Level 1 Response

1336 structure = (

1337 ('ServerName','16s'),

1338 ('MajorVersion','B=5'),

1339 ('MinorVersion','B=0'),

1340 ('ServerType','<L=3'),

1341 ('ServerCommentLow','<H=0'),

1342 ('ServerCommentHigh','<H=0'),

1343 )

1344

1345# \PIPE\LANMAN NetShareGetInfo

1346 class SMBNetShareGetInfo(Structure):

1347 structure = (

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

1349 ('ParamDesc','z'),

1350 ('DataDesc','z'),

1351 ('ShareName','z'),

1352 ('InfoLevel','<H'),

1353 ('ReceiveBufferSize','<H'),

1354 )

1355

1356 class SMBNetShareGetInfoResponse(Structure):

1357 structure = (

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

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

1360 ('TotalBytesAvailable','<H'),

1361 )

1362

1363############# Security Features

1364 class SecurityFeatures(Structure):

1365 structure = (

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

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

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

1369 )

1370

1371############# SMB_COM_QUERY_INFORMATION2 (0x23)

1372 class SMBQueryInformation2_Parameters(Structure):

1373 structure = (

1374 ('Fid','<H'),

1375 )

1376

1377 class SMBQueryInformation2Response_Parameters(Structure):

1378 structure = (

1379 ('CreateDate','<H'),

1380 ('CreationTime','<H'),

1381 ('LastAccessDate','<H'),

1382 ('LastAccessTime','<H'),

1383 ('LastWriteDate','<H'),

1384 ('LastWriteTime','<H'),

1385 ('FileDataSize','<L'),

1386 ('FileAllocationSize','<L'),

1387 ('FileAttributes','<L'),

1388 )

1389

1390

1391

1392############# SMB_COM_SESSION_SETUP_ANDX (0x73)

1393 class SMBSessionSetupAndX_Parameters(SMBAndXCommand_Parameters):

1394 structure = (

1395 ('MaxBuffer','<H'),

1396 ('MaxMpxCount','<H'),

1397 ('VCNumber','<H'),

1398 ('SessionKey','<L'),

1399 ('AnsiPwdLength','<H'),

1400 ('UnicodePwdLength','<H'),

1401 ('_reserved','<L=0'),

1402 ('Capabilities','<L'),

1403 )

1404

1405 class SMBSessionSetupAndX_Extended_Parameters(SMBAndXCommand_Parameters):

1406 structure = (

1407 ('MaxBufferSize','<H'),

1408 ('MaxMpxCount','<H'),

1409 ('VcNumber','<H'),

1410 ('SessionKey','<L'),

1411 ('SecurityBlobLength','<H'),

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

1413 ('Capabilities','<L'),

1414 )

1415

1416 class SMBSessionSetupAndX_Data(AsciiOrUnicodeStructure):

1417 AsciiStructure = (

1418 ('AnsiPwdLength','_-AnsiPwd','self["AnsiPwdLength"]'),

1419 ('UnicodePwdLength','_-UnicodePwd','self["UnicodePwdLength"]'),

1420 ('AnsiPwd',':=""'),

1421 ('UnicodePwd',':=""'),

1422 ('Account','z=""'),

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

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

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

1426 )

1427

1428 UnicodeStructure = (

1429 ('AnsiPwdLength','_-AnsiPwd','self["AnsiPwdLength"]'),

1430 ('UnicodePwdLength','_-UnicodePwd','self["UnicodePwdLength"]'),

1431 ('AnsiPwd',':=""'),

1432 ('UnicodePwd',':=""'),

1433 ('Account','u=""'),

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

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

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

1437 )

1438

1439 class SMBSessionSetupAndX_Extended_Data(AsciiOrUnicodeStructure):

1440 AsciiStructure = (

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

1442 ('SecurityBlob',':'),

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

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

1445 )

1446

1447 UnicodeStructure = (

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

1449 ('SecurityBlob',':'),

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

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

1452 )

1453

1454 class SMBSessionSetupAndXResponse_Parameters(SMBAndXCommand_Parameters):

1455 structure = (

1456 ('Action','<H'),

1457 )

1458

1459 class SMBSessionSetupAndX_Extended_Response_Parameters(SMBAndXCommand_Parameters):

1460 structure = (

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

1462 ('SecurityBlobLength','<H'),

1463 )

1464

1465 class SMBSessionSetupAndXResponse_Data(AsciiOrUnicodeStructure):

1466 AsciiStructure = (

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

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

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

1470 )

1471

1472 UnicodeStructure = (

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

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

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

1476 )

1477

1478 class SMBSessionSetupAndX_Extended_Response_Data(AsciiOrUnicodeStructure):

1479 AsciiStructure = (

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

1481 ('SecurityBlob',':'),

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

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

1484 )

1485

1486 UnicodeStructure = (

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

1488 ('SecurityBlob',':'),

1489 ('PadLen','_-Pad','1 if (len(self["SecurityBlob"]) % 2 == 0) else 0'),

1490 ('Pad',':=""'),

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

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

1493 )

1494 def getData(self):

1495 if self.structure == self.UnicodeStructure:

1496 if len(str(self['SecurityBlob'])) % 2 == 0:

1497 self['Pad'] = '\x00'

1498 return AsciiOrUnicodeStructure.getData(self)

1499

1500############# SMB_COM_TREE_CONNECT (0x70)

1501 class SMBTreeConnect_Parameters(SMBCommand_Parameters):

1502 structure = (

1503 )

1504

1505 class SMBTreeConnect_Data(SMBCommand_Parameters):

1506 structure = (

1507 ('PathFormat','"\x04'),

1508 ('Path','z'),

1509 ('PasswordFormat','"\x04'),

1510 ('Password','z'),

1511 ('ServiceFormat','"\x04'),

1512 ('Service','z'),

1513 )

1514

1515############# SMB_COM_TREE_CONNECT_ANDX (0x75)

1516 class SMBTreeConnectAndX_Parameters(SMBAndXCommand_Parameters):

1517 structure = (

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

1519 ('PasswordLength','<H'),

1520 )

1521

1522 class SMBTreeConnectAndXResponse_Parameters(SMBAndXCommand_Parameters):

1523 structure = (

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

1525 )

1526

1527 class SMBTreeConnectAndXExtendedResponse_Parameters(SMBAndXCommand_Parameters):

1528 structure = (

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

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

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

1532 )

1533

1534 class SMBTreeConnectAndX_Data(AsciiOrUnicodeStructure):

1535 AsciiStructure = (

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

1537 ('Password',':'),

1538 ('Path','z'),

1539 ('Service','z'),

1540 )

1541

1542 UnicodeStructure = (

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

1544 ('Password',':'),

1545 ('Path','u'),

1546 ('Service','z'),

1547 )

1548

1549 class SMBTreeConnectAndXResponse_Data(AsciiOrUnicodeStructure):

1550 AsciiStructure = (

1551 ('Service','z'),

1552 ('PadLen','_-Pad','self["PadLen"]'),

1553 ('Pad',':=""'),

1554 ('NativeFileSystem','z'),

1555 )

1556 UnicodeStructure = (

1557 ('Service','z'),

1558 ('PadLen','_-Pad','self["PadLen"]'),

1559 ('Pad',':=""'),

1560 ('NativeFileSystem','u'),

1561 )

1562

1563############# SMB_COM_NT_CREATE_ANDX (0xA2)

1564 class SMBNtCreateAndX_Parameters(SMBAndXCommand_Parameters):

1565 structure = (

1566 ('_reserved', 'B=0'),

1567 ('FileNameLength','<H'), # NameLength

1568 ('CreateFlags','<L'), # Flags

1569 ('RootFid','<L=0'), # RootDirectoryFID

1570 ('AccessMask','<L'), # DesiredAccess

1571 ('AllocationSizeLo','<L=0'), # AllocationSize

1572 ('AllocationSizeHi','<L=0'),

1573 ('FileAttributes','<L=0'), # ExtFileAttributes

1574 ('ShareAccess','<L=3'), #

1575 ('Disposition','<L=1'), # CreateDisposition

1576 ('CreateOptions','<L'), # CreateOptions

1577 ('Impersonation','<L=2'),

1578 ('SecurityFlags','B=3'),

1579 )

1580

1581 class SMBNtCreateAndXResponse_Parameters(SMBAndXCommand_Parameters):

1582 # XXX Is there a memory leak in the response for NTCreate (where the Data section would be) in Win 2000, Win XP, and Win 2003?

1583 structure = (

1584 ('OplockLevel', 'B=0'),

1585 ('Fid','<H'),

1586 ('CreateAction','<L'),

1587 ('CreateTime','<q=0'),

1588 ('LastAccessTime','<q=0'),

1589 ('LastWriteTime','<q=0'),

1590 ('LastChangeTime','<q=0'),

1591 ('FileAttributes','<L=0x80'),

1592 ('AllocationSize','<q=0'),

1593 ('EndOfFile','<q=0'),

1594 ('FileType','<H=0'),

1595 ('IPCState','<H=0'),

1596 ('IsDirectory','B'),

1597 )

1598

1599 class SMBNtCreateAndXExtendedResponse_Parameters(SMBAndXCommand_Parameters):

1600 # [MS-SMB] Extended response description

1601 structure = (

1602 ('OplockLevel', 'B=0'),

1603 ('Fid','<H'),

1604 ('CreateAction','<L'),

1605 ('CreateTime','<q=0'),

1606 ('LastAccessTime','<q=0'),

1607 ('LastWriteTime','<q=0'),

1608 ('LastChangeTime','<q=0'),

1609 ('FileAttributes','<L=0x80'),

1610 ('AllocationSize','<q=0'),

1611 ('EndOfFile','<q=0'),

1612 ('FileType','<H=0'),

1613 ('IPCState','<H=0'),

1614 ('IsDirectory','B'),

1615 ('VolumeGUID','16s'),

1616 ('FileIdLow','<L=0'),

1617 ('FileIdHigh','<L=0'),

1618 ('MaximalAccessRights','<L=0x12019b'),

1619 ('GuestMaximalAccessRights','<L=0x120089'),

1620 )

1621

1622 class SMBNtCreateAndX_Data(AsciiOrUnicodeStructure):

1623 AsciiStructure = (

1624 ('FileName','z'),

1625 )

1626 UnicodeStructure = (

1627 ('Pad','B'),

1628 ('FileName','u'),

1629 )

1630

1631############# SMB_COM_OPEN_ANDX (0xD2)

1632 class SMBOpenAndX_Parameters(SMBAndXCommand_Parameters):

1633 structure = (

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

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

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

1637 ('FileAttributes','<H=0'),

1638 ('CreationTime','<L=0'),

1639 ('OpenMode','<H=1'), # SMB_O_OPEN = 1

1640 ('AllocationSize','<L=0'),

1641 ('Reserved','8s=""'),

1642 )

1643

1644 class SMBOpenAndX_Data(SMBNtCreateAndX_Data):

1645 pass

1646

1647 class SMBOpenAndXResponse_Parameters(SMBAndXCommand_Parameters):

1648 structure = (

1649 ('Fid','<H=0'),

1650 ('FileAttributes','<H=0'),

1651 ('LastWriten','<L=0'),

1652 ('FileSize','<L=0'),

1653 ('GrantedAccess','<H=0'),

1654 ('FileType','<H=0'),

1655 ('IPCState','<H=0'),

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

1657 ('ServerFid','<L=0'),

1658 ('_reserved','<H=0'),

1659 )

1660

1661############# SMB_COM_WRITE (0x0B)

1662 class SMBWrite_Parameters(SMBCommand_Parameters):

1663 structure = (

1664 ('Fid','<H'),

1665 ('Count','<H'),

1666 ('Offset','<L'),

1667 ('Remaining','<H'),

1668 )

1669

1670 class SMBWriteResponse_Parameters(SMBCommand_Parameters):

1671 structure = (

1672 ('Count','<H'),

1673 )

1674

1675 class SMBWrite_Data(Structure):

1676 structure = (

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

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

1679 ('Data',':'),

1680 )

1681

1682

1683############# SMB_COM_WRITE_ANDX (0x2F)

1684 class SMBWriteAndX_Parameters(SMBAndXCommand_Parameters):

1685 structure = (

1686 ('Fid','<H=0'),

1687 ('Offset','<L=0'),

1688 ('_reserved','<L=0xff'),

1689 ('WriteMode','<H=8'),

1690 ('Remaining','<H=0'),

1691 ('DataLength_Hi','<H=0'),

1692 ('DataLength','<H=0'),

1693 ('DataOffset','<H=0'),

1694 ('HighOffset','<L=0'),

1695 )

1696

1697 class SMBWriteAndX_Data_Short(Structure):

1698 structure = (

1699 ('_PadLen','_-Pad','self["DataOffset"] - 59'),

1700 ('Pad',':'),

1701 #('Pad','<B=0'),

1702 ('DataLength','_-Data','self["DataLength"]'),

1703 ('Data',':'),

1704 )

1705

1706 class SMBWriteAndX_Data(Structure):

1707 structure = (

1708 ('_PadLen','_-Pad','self["DataOffset"] - 63'),

1709 ('Pad',':'),

1710 #('Pad','<B=0'),

1711 ('DataLength','_-Data','self["DataLength"]'),

1712 ('Data',':'),

1713 )

1714

1715

1716 class SMBWriteAndX_Parameters_Short(SMBAndXCommand_Parameters):

1717 structure = (

1718 ('Fid','<H'),

1719 ('Offset','<L'),

1720 ('_reserved','<L=0xff'),

1721 ('WriteMode','<H=8'),

1722 ('Remaining','<H'),

1723 ('DataLength_Hi','<H=0'),

1724 ('DataLength','<H'),

1725 ('DataOffset','<H=0'),

1726 )

1727

1728 class SMBWriteAndXResponse_Parameters(SMBAndXCommand_Parameters):

1729 structure = (

1730 ('Count','<H'),

1731 ('Available','<H'),

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

1733 )

1734

1735############# SMB_COM_WRITE_RAW (0x1D)

1736 class SMBWriteRaw_Parameters(SMBCommand_Parameters):

1737 structure = (

1738 ('Fid','<H'),

1739 ('Count','<H'),

1740 ('_reserved','<H=0'),

1741 ('Offset','<L'),

1742 ('Timeout','<L=0'),

1743 ('WriteMode','<H=0'),

1744 ('_reserved2','<L=0'),

1745 ('DataLength','<H'),

1746 ('DataOffset','<H=0'),

1747 )

1748

1749############# SMB_COM_READ (0x0A)

1750 class SMBRead_Parameters(SMBCommand_Parameters):

1751 structure = (

1752 ('Fid','<H'),

1753 ('Count','<H'),

1754 ('Offset','<L'),

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

1756 )

1757

1758 class SMBReadResponse_Parameters(Structure):

1759 structure = (

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

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

1762 )

1763

1764 class SMBReadResponse_Data(Structure):

1765 structure = (

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

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

1768 ('Data',':'),

1769 )

1770

1771############# SMB_COM_READ_RAW (0x1A)

1772 class SMBReadRaw_Parameters(SMBCommand_Parameters):

1773 structure = (

1774 ('Fid','<H'),

1775 ('Offset','<L'),

1776 ('MaxCount','<H'),

1777 ('MinCount','<H=MaxCount'),

1778 ('Timeout','<L=0'),

1779 ('_reserved','<H=0'),

1780 )

1781

1782############# SMB_COM_NT_TRANSACT (0xA0)

1783 class SMBNTTransaction_Parameters(SMBCommand_Parameters):

1784 structure = (

1785 ('MaxSetupCount','<B=0'),

1786 ('Reserved1','<H=0'),

1787 ('TotalParameterCount','<L'),

1788 ('TotalDataCount','<L'),

1789 ('MaxParameterCount','<L=1024'),

1790 ('MaxDataCount','<L=65504'),

1791 ('ParameterCount','<L'),

1792 ('ParameterOffset','<L'),

1793 ('DataCount','<L'),

1794 ('DataOffset','<L'),

1795 ('SetupCount','<B=len(Setup)//2'),

1796 ('Function','<H=0'),

1797 ('SetupLength','_-Setup','SetupCount*2'),

1798 ('Setup',':'),

1799 )

1800

1801 class SMBNTTransactionResponse_Parameters(SMBCommand_Parameters):

1802 structure = (

1803 ('Reserved1','3s=""'),

1804 ('TotalParameterCount','<L'),

1805 ('TotalDataCount','<L'),

1806 ('ParameterCount','<L'),

1807 ('ParameterOffset','<L'),

1808 ('ParameterDisplacement','<L=0'),

1809 ('DataCount','<L'),

1810 ('DataOffset','<L'),

1811 ('DataDisplacement','<L=0'),

1812 ('SetupCount','<B=0'),

1813 ('SetupLength','_-Setup','SetupCount*2'),

1814 ('Setup',':'),

1815 )

1816

1817 class SMBNTTransaction_Data(Structure):

1818 structure = (

1819 ('Pad1Length','_-Pad1','self["Pad1Length"]'),

1820 ('Pad1',':'),

1821 ('NT_Trans_ParametersLength','_-NT_Trans_Parameters','self["NT_Trans_ParametersLength"]'),

1822 ('NT_Trans_Parameters',':'),

1823 ('Pad2Length','_-Pad2','self["Pad2Length"]'),

1824 ('Pad2',':'),

1825 ('NT_Trans_DataLength','_-NT_Trans_Data','self["NT_Trans_DataLength"]'),

1826 ('NT_Trans_Data',':'),

1827 )

1828

1829 class SMBNTTransactionResponse_Data(Structure):

1830 structure = (

1831 ('Pad1Length','_-Pad1','self["Pad1Length"]'),

1832 ('Pad1',':'),

1833 ('Trans_ParametersLength','_-Trans_Parameters','self["Trans_ParametersLength"]'),

1834 ('Trans_Parameters',':'),

1835 ('Pad2Length','_-Pad2','self["Pad2Length"]'),

1836 ('Pad2',':'),

1837 ('Trans_DataLength','_-Trans_Data','self["Trans_DataLength"]'),

1838 ('Trans_Data',':'),

1839 )

1840

1841

1842############# SMB_COM_TRANSACTION2_SECONDARY (0x33)

1843 class SMBTransaction2Secondary_Parameters(SMBCommand_Parameters):

1844 structure = (

1845 ('TotalParameterCount','<H'),

1846 ('TotalDataCount','<H'),

1847 ('ParameterCount','<H'),

1848 ('ParameterOffset','<H'),

1849 ('ParameterDisplacement','<H'),

1850 ('DataCount','<H'),

1851 ('DataOffset','<H'),

1852 ('DataDisplacement','<H=0'),

1853 ('FID','<H'),

1854 )

1855

1856 class SMBTransaction2Secondary_Data(Structure):

1857 structure = (

1858 ('Pad1Length','_-Pad1','self["Pad1Length"]'),

1859 ('Pad1',':'),

1860 ('Trans_ParametersLength','_-Trans_Parameters','self["Trans_ParametersLength"]'),

1861 ('Trans_Parameters',':'),

1862 ('Pad2Length','_-Pad2','self["Pad2Length"]'),

1863 ('Pad2',':'),

1864 ('Trans_DataLength','_-Trans_Data','self["Trans_DataLength"]'),

1865 ('Trans_Data',':'),

1866 )

1867

1868

1869############# SMB_COM_TRANSACTION2 (0x32)

1870

1871 class SMBTransaction2_Parameters(SMBCommand_Parameters):

1872 structure = (

1873 ('TotalParameterCount','<H'),

1874 ('TotalDataCount','<H'),

1875 ('MaxParameterCount','<H=1024'),

1876 ('MaxDataCount','<H=65504'),

1877 ('MaxSetupCount','<B=0'),

1878 ('Reserved1','<B=0'),

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

1880 ('Timeout','<L=0'),

1881 ('Reserved2','<H=0'),

1882 ('ParameterCount','<H'),

1883 ('ParameterOffset','<H'),

1884 ('DataCount','<H'),

1885 ('DataOffset','<H'),

1886 ('SetupCount','<B=len(Setup)//2'),

1887 ('Reserved3','<B=0'),

1888 ('SetupLength','_-Setup','SetupCount*2'),

1889 ('Setup',':'),

1890 )

1891

1892 class SMBTransaction2Response_Parameters(SMBCommand_Parameters):

1893 structure = (

1894 ('TotalParameterCount','<H'),

1895 ('TotalDataCount','<H'),

1896 ('Reserved1','<H=0'),

1897 ('ParameterCount','<H'),

1898 ('ParameterOffset','<H'),

1899 ('ParameterDisplacement','<H=0'),

1900 ('DataCount','<H'),

1901 ('DataOffset','<H'),

1902 ('DataDisplacement','<H=0'),

1903 ('SetupCount','<B=0'),

1904 ('Reserved2','<B=0'),

1905 ('SetupLength','_-Setup','SetupCount*2'),

1906 ('Setup',':'),

1907 )

1908

1909 class SMBTransaction2_Data(Structure):

1910 structure = (

1911# ('NameLength','_-Name','1'),

1912# ('Name',':'),

1913 ('Pad1Length','_-Pad1','self["Pad1Length"]'),

1914 ('Pad1',':'),

1915 ('Trans_ParametersLength','_-Trans_Parameters','self["Trans_ParametersLength"]'),

1916 ('Trans_Parameters',':'),

1917 ('Pad2Length','_-Pad2','self["Pad2Length"]'),

1918 ('Pad2',':'),

1919 ('Trans_DataLength','_-Trans_Data','self["Trans_DataLength"]'),

1920 ('Trans_Data',':'),

1921 )

1922

1923 class SMBTransaction2Response_Data(Structure):

1924 structure = (

1925 ('Pad1Length','_-Pad1','self["Pad1Length"]'),

1926 ('Pad1',':'),

1927 ('Trans_ParametersLength','_-Trans_Parameters','self["Trans_ParametersLength"]'),

1928 ('Trans_Parameters',':'),

1929 ('Pad2Length','_-Pad2','self["Pad2Length"]'),

1930 ('Pad2',':'),

1931 ('Trans_DataLength','_-Trans_Data','self["Trans_DataLength"]'),

1932 ('Trans_Data',':'),

1933 )

1934

1935############# SMB_COM_QUERY_INFORMATION (0x08)

1936

1937 class SMBQueryInformation_Data(AsciiOrUnicodeStructure):

1938 AsciiStructure = (

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

1940 ('FileName','z'),

1941 )

1942 UnicodeStructure = (

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

1944 ('FileName','u'),

1945 )

1946

1947

1948 class SMBQueryInformationResponse_Parameters(Structure):

1949 structure = (

1950 ('FileAttributes','<H'),

1951 ('LastWriteTime','<L'),

1952 ('FileSize','<L'),

1953 ('Reserved','"0123456789'),

1954 )

1955

1956############# SMB_COM_TRANSACTION (0x25)

1957 class SMBTransaction_Parameters(SMBCommand_Parameters):

1958 structure = (

1959 ('TotalParameterCount','<H'),

1960 ('TotalDataCount','<H'),

1961 ('MaxParameterCount','<H=1024'),

1962 ('MaxDataCount','<H=65504'),

1963 ('MaxSetupCount','<B=0'),

1964 ('Reserved1','<B=0'),

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

1966 ('Timeout','<L=0'),

1967 ('Reserved2','<H=0'),

1968 ('ParameterCount','<H'),

1969 ('ParameterOffset','<H'),

1970 ('DataCount','<H'),

1971 ('DataOffset','<H'),

1972 ('SetupCount','<B=len(Setup)//2'),

1973 ('Reserved3','<B=0'),

1974 ('SetupLength','_-Setup','SetupCount*2'),

1975 ('Setup',':'),

1976 )

1977

1978 class SMBTransactionResponse_Parameters(SMBCommand_Parameters):

1979 structure = (

1980 ('TotalParameterCount','<H'),

1981 ('TotalDataCount','<H'),

1982 ('Reserved1','<H=0'),

1983 ('ParameterCount','<H'),

1984 ('ParameterOffset','<H'),

1985 ('ParameterDisplacement','<H=0'),

1986 ('DataCount','<H'),

1987 ('DataOffset','<H'),

1988 ('DataDisplacement','<H=0'),

1989 ('SetupCount','<B'),

1990 ('Reserved2','<B=0'),

1991 ('SetupLength','_-Setup','SetupCount*2'),

1992 ('Setup',':'),

1993 )

1994

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

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

1997 class SMBTransaction_SData(AsciiOrUnicodeStructure):

1998 AsciiStructure = (

1999 ('Name','z'),

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

2001 ('Trans_Parameters',':'),

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

2003 ('Trans_Data',':'),

2004 )

2005 UnicodeStructure = (

2006 ('Pad','B'),

2007 ('Name','u'),

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

2009 ('Trans_Parameters',':'),

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

2011 ('Trans_Data',':'),

2012 )

2013

2014 class SMBTransaction_Data(Structure):

2015 structure = (

2016 ('NameLength','_-Name'),

2017 ('Name',':'),

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

2019 ('Trans_Parameters',':'),

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

2021 ('Trans_Data',':'),

2022 )

2023

2024 class SMBTransactionResponse_Data(Structure):

2025 structure = (

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

2027 ('Trans_Parameters',':'),

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

2029 ('Trans_Data',':'),

2030 )

2031

2032############# SMB_COM_READ_ANDX (0x2E)

2033 class SMBReadAndX_Parameters(SMBAndXCommand_Parameters):

2034 structure = (

2035 ('Fid','<H'),

2036 ('Offset','<L'),

2037 ('MaxCount','<H'),

2038 ('MinCount','<H=MaxCount'),

2039 ('_reserved','<L=0x0'),

2040 ('Remaining','<H=MaxCount'),

2041 ('HighOffset','<L=0'),

2042 )

2043

2044 class SMBReadAndX_Parameters2(SMBAndXCommand_Parameters):

2045 structure = (

2046 ('Fid','<H'),

2047 ('Offset','<L'),

2048 ('MaxCount','<H'),

2049 ('MinCount','<H=MaxCount'),

2050 ('_reserved','<L=0xffffffff'),

2051 ('Remaining','<H=MaxCount'),

2052 )

2053

2054 class SMBReadAndXResponse_Parameters(SMBAndXCommand_Parameters):

2055 structure = (

2056 ('Remaining','<H=0'),

2057 ('DataMode','<H=0'),

2058 ('_reserved','<H=0'),

2059 ('DataCount','<H'),

2060 ('DataOffset','<H'),

2061 ('DataCount_Hi','<L'),

2062 ('_reserved2','6s=""'),

2063 )

2064

2065############# SMB_COM_ECHO (0x2B)

2066 class SMBEcho_Data(Structure):

2067 structure = (

2068 ('Data',':'),

2069 )

2070

2071 class SMBEcho_Parameters(Structure):

2072 structure = (

2073 ('EchoCount','<H'),

2074 )

2075

2076 class SMBEchoResponse_Data(Structure):

2077 structure = (

2078 ('Data',':'),

2079 )

2080

2081 class SMBEchoResponse_Parameters(Structure):

2082 structure = (

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

2084 )

2085

2086############# SMB_COM_QUERY_INFORMATION_DISK (0x80)

2087 class SMBQueryInformationDiskResponse_Parameters(Structure):

2088 structure = (

2089 ('TotalUnits','<H'),

2090 ('BlocksPerUnit','<H'),

2091 ('BlockSize','<H'),

2092 ('FreeUnits','<H'),

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

2094 )

2095

2096

2097############# SMB_COM_LOGOFF_ANDX (0x74)

2098 class SMBLogOffAndX(SMBAndXCommand_Parameters):

2099 strucure = ()

2100

2101############# SMB_COM_CLOSE (0x04)

2102 class SMBClose_Parameters(SMBCommand_Parameters):

2103 structure = (

2104 ('FID','<H'),

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

2106 )

2107

2108############# SMB_COM_FLUSH (0x05)

2109 class SMBFlush_Parameters(SMBCommand_Parameters):

2110 structure = (

2111 ('FID','<H'),

2112 )

2113

2114############# SMB_COM_CREATE_DIRECTORY (0x00)

2115 class SMBCreateDirectory_Data(AsciiOrUnicodeStructure):

2116 AsciiStructure = (

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

2118 ('DirectoryName','z'),

2119 )

2120 UnicodeStructure = (

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

2122 ('DirectoryName','u'),

2123 )

2124

2125############# SMB_COM_DELETE (0x06)

2126 class SMBDelete_Data(AsciiOrUnicodeStructure):

2127 AsciiStructure = (

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

2129 ('FileName','z'),

2130 )

2131 UnicodeStructure = (

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

2133 ('FileName','u'),

2134 )

2135

2136 class SMBDelete_Parameters(Structure):

2137 structure = (

2138 ('SearchAttributes','<H'),

2139 )

2140

2141############# SMB_COM_DELETE_DIRECTORY (0x01)

2142 class SMBDeleteDirectory_Data(AsciiOrUnicodeStructure):

2143 AsciiStructure = (

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

2145 ('DirectoryName','z'),

2146 )

2147 UnicodeStructure = (

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

2149 ('DirectoryName','u'),

2150 )

2151

2152############# SMB_COM_CHECK_DIRECTORY (0x10)

2153 class SMBCheckDirectory_Data(AsciiOrUnicodeStructure):

2154 AsciiStructure = (

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

2156 ('DirectoryName','z'),

2157 )

2158 UnicodeStructure = (

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

2160 ('DirectoryName','u'),

2161 )

2162

2163############# SMB_COM_RENAME (0x07)

2164 class SMBRename_Parameters(SMBCommand_Parameters):

2165 structure = (

2166 ('SearchAttributes','<H'),

2167 )

2168

2169 class SMBRename_Data(AsciiOrUnicodeStructure):

2170 AsciiStructure = (

2171 ('BufferFormat1','<B=4'),

2172 ('OldFileName','z'),

2173 ('BufferFormat2','<B=4'),

2174 ('NewFileName','z'),

2175 )

2176 UnicodeStructure = (

2177 ('BufferFormat1','<B=4'),

2178 ('OldFileName','u'),

2179 ('BufferFormat2','<B=4'),

2180 ('Pad','B=0'),

2181 ('NewFileName','u'),

2182 )

2183

2184

2185############# SMB_COM_OPEN (0x02)

2186 class SMBOpen_Parameters(SMBCommand_Parameters):

2187 structure = (

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

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

2190 )

2191

2192 class SMBOpen_Data(AsciiOrUnicodeStructure):

2193 AsciiStructure = (

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

2195 ('FileName','z'),

2196 )

2197 UnicodeStructure = (

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

2199 ('FileName','u'),

2200 )

2201

2202 class SMBOpenResponse_Parameters(SMBCommand_Parameters):

2203 structure = (

2204 ('Fid','<H=0'),

2205 ('FileAttributes','<H=0'),

2206 ('LastWriten','<L=0'),

2207 ('FileSize','<L=0'),

2208 ('GrantedAccess','<H=0'),

2209 )

2210

2211############# EXTENDED SECURITY CLASSES

2212 class SMBExtended_Security_Parameters(Structure):

2213 structure = (

2214 ('DialectIndex','<H'),

2215 ('SecurityMode','<B'),

2216 ('MaxMpxCount','<H'),

2217 ('MaxNumberVcs','<H'),

2218 ('MaxBufferSize','<L'),

2219 ('MaxRawSize','<L'),

2220 ('SessionKey','<L'),

2221 ('Capabilities','<L'),

2222 ('LowDateTime','<L'),

2223 ('HighDateTime','<L'),

2224 ('ServerTimeZone','<H'),

2225 ('ChallengeLength','<B'),

2226 )

2227

2228 class SMBExtended_Security_Data(Structure):

2229 structure = (

2230 ('ServerGUID','16s'),

2231 ('SecurityBlob',':'),

2232 )

2233

2234 class SMBNTLMDialect_Parameters(Structure):

2235 structure = (

2236 ('DialectIndex','<H'),

2237 ('SecurityMode','<B'),

2238 ('MaxMpxCount','<H'),

2239 ('MaxNumberVcs','<H'),

2240 ('MaxBufferSize','<L'),

2241 ('MaxRawSize','<L'),

2242 ('SessionKey','<L'),

2243 ('Capabilities','<L'),

2244 ('LowDateTime','<L'),

2245 ('HighDateTime','<L'),

2246 ('ServerTimeZone','<H'),

2247 ('ChallengeLength','<B'),

2248 )

2249

2250 class SMBNTLMDialect_Data(Structure):

2251 structure = (

2252 ('ChallengeLength','_-Challenge','self["ChallengeLength"]'),

2253 ('Challenge',':'),

2254 ('Payload',':'),

2255# For some reason on an old Linux this field is not present, we have to check this out. There must be a flag stating this.

2256 ('DomainName','_'),

2257 ('ServerName','_'),

2258 )

2259 def __init__(self,data = None, alignment = 0):

2260 Structure.__init__(self,data,alignment)

2261 #self['ChallengeLength']=8

2262

2263 def fromString(self,data):

2264 Structure.fromString(self,data)

2265 self['DomainName'] = ''

2266 self['ServerName'] = ''

2267

2268 class SMB(object):

2269

2270 class HostnameValidationException(Exception):

2271 pass

2272

2273 # SMB Command Codes

2274 SMB_COM_CREATE_DIRECTORY = 0x00

2275 SMB_COM_DELETE_DIRECTORY = 0x01

2276 SMB_COM_OPEN = 0x02

2277 SMB_COM_CREATE = 0x03

2278 SMB_COM_CLOSE = 0x04

2279 SMB_COM_FLUSH = 0x05

2280 SMB_COM_DELETE = 0x06

2281 SMB_COM_RENAME = 0x07

2282 SMB_COM_QUERY_INFORMATION = 0x08

2283 SMB_COM_SET_INFORMATION = 0x09

2284 SMB_COM_READ = 0x0A

2285 SMB_COM_WRITE = 0x0B

2286 SMB_COM_LOCK_BYTE_RANGE = 0x0C

2287 SMB_COM_UNLOCK_BYTE_RANGE = 0x0D

2288 SMB_COM_CREATE_TEMPORARY = 0x0E

2289 SMB_COM_CREATE_NEW = 0x0F

2290 SMB_COM_CHECK_DIRECTORY = 0x10

2291 SMB_COM_PROCESS_EXIT = 0x11

2292 SMB_COM_SEEK = 0x12

2293 SMB_COM_LOCK_AND_READ = 0x13

2294 SMB_COM_WRITE_AND_UNLOCK = 0x14

2295 SMB_COM_READ_RAW = 0x1A

2296 SMB_COM_READ_MPX = 0x1B

2297 SMB_COM_READ_MPX_SECONDARY = 0x1C

2298 SMB_COM_WRITE_RAW = 0x1D

2299 SMB_COM_WRITE_MPX = 0x1E

2300 SMB_COM_WRITE_MPX_SECONDARY = 0x1F

2301 SMB_COM_WRITE_COMPLETE = 0x20

2302 SMB_COM_QUERY_SERVER = 0x21

2303 SMB_COM_SET_INFORMATION2 = 0x22

2304 SMB_COM_QUERY_INFORMATION2 = 0x23

2305 SMB_COM_LOCKING_ANDX = 0x24

2306 SMB_COM_TRANSACTION = 0x25

2307 SMB_COM_TRANSACTION_SECONDARY = 0x26

2308 SMB_COM_IOCTL = 0x27

2309 SMB_COM_IOCTL_SECONDARY = 0x28

2310 SMB_COM_COPY = 0x29

2311 SMB_COM_MOVE = 0x2A

2312 SMB_COM_ECHO = 0x2B

2313 SMB_COM_WRITE_AND_CLOSE = 0x2C

2314 SMB_COM_OPEN_ANDX = 0x2D

2315 SMB_COM_READ_ANDX = 0x2E

2316 SMB_COM_WRITE_ANDX = 0x2F

2317 SMB_COM_NEW_FILE_SIZE = 0x30

2318 SMB_COM_CLOSE_AND_TREE_DISC = 0x31

2319 SMB_COM_TRANSACTION2 = 0x32

2320 SMB_COM_TRANSACTION2_SECONDARY = 0x33

2321 SMB_COM_FIND_CLOSE2 = 0x34

2322 SMB_COM_FIND_NOTIFY_CLOSE = 0x35

2323 # Used by Xenix/Unix 0x60 - 0x6E

2324 SMB_COM_TREE_CONNECT = 0x70

2325 SMB_COM_TREE_DISCONNECT = 0x71

2326 SMB_COM_NEGOTIATE = 0x72

2327 SMB_COM_SESSION_SETUP_ANDX = 0x73

2328 SMB_COM_LOGOFF_ANDX = 0x74

2329 SMB_COM_TREE_CONNECT_ANDX = 0x75

2330 SMB_COM_QUERY_INFORMATION_DISK = 0x80

2331 SMB_COM_SEARCH = 0x81

2332 SMB_COM_FIND = 0x82

2333 SMB_COM_FIND_UNIQUE = 0x83

2334 SMB_COM_FIND_CLOSE = 0x84

2335 SMB_COM_NT_TRANSACT = 0xA0

2336 SMB_COM_NT_TRANSACT_SECONDARY = 0xA1

2337 SMB_COM_NT_CREATE_ANDX = 0xA2

2338 SMB_COM_NT_CANCEL = 0xA4

2339 SMB_COM_NT_RENAME = 0xA5

2340 SMB_COM_OPEN_PRINT_FILE = 0xC0

2341 SMB_COM_WRITE_PRINT_FILE = 0xC1

2342 SMB_COM_CLOSE_PRINT_FILE = 0xC2

2343 SMB_COM_GET_PRINT_QUEUE = 0xC3

2344 SMB_COM_READ_BULK = 0xD8

2345 SMB_COM_WRITE_BULK = 0xD9

2346 SMB_COM_WRITE_BULK_DATA = 0xDA

2347

2348 # TRANSACT codes

2349 TRANS_TRANSACT_NMPIPE = 0x26

2350

2351 # TRANSACT2 codes

2352 TRANS2_FIND_FIRST2 = 0x0001

2353 TRANS2_FIND_NEXT2 = 0x0002

2354 TRANS2_QUERY_FS_INFORMATION = 0x0003

2355 TRANS2_QUERY_PATH_INFORMATION = 0x0005

2356 TRANS2_QUERY_FILE_INFORMATION = 0x0007

2357 TRANS2_SET_FILE_INFORMATION = 0x0008

2358 TRANS2_SET_PATH_INFORMATION = 0x0006

2359

2360 # Security Share Mode (Used internally by SMB class)

2361 SECURITY_SHARE_MASK = 0x01

2362 SECURITY_SHARE_SHARE = 0x00

2363 SECURITY_SHARE_USER = 0x01

2364 SECURITY_SIGNATURES_ENABLED = 0X04

2365 SECURITY_SIGNATURES_REQUIRED = 0X08

2366

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

2368 SECURITY_AUTH_MASK = 0x02

2369 SECURITY_AUTH_ENCRYPTED = 0x02

2370 SECURITY_AUTH_PLAINTEXT = 0x00

2371

2372 # Raw Mode Mask (Used internally by SMB class. Good for dialect up to and including LANMAN2.1)

2373 RAW_READ_MASK = 0x01

2374 RAW_WRITE_MASK = 0x02

2375

2376 # Capabilities Mask (Used internally by SMB class. Good for dialect NT LM 0.12)

2377 CAP_RAW_MODE = 0x00000001

2378 CAP_MPX_MODE = 0x0002

2379 CAP_UNICODE = 0x0004

2380 CAP_LARGE_FILES = 0x0008

2381 CAP_EXTENDED_SECURITY = 0x80000000

2382 CAP_USE_NT_ERRORS = 0x40

2383 CAP_NT_SMBS = 0x10

2384 CAP_LARGE_READX = 0x00004000

2385 CAP_LARGE_WRITEX = 0x00008000

2386 CAP_RPC_REMOTE_APIS = 0x20

2387

2388 # Flags1 Mask

2389 FLAGS1_LOCK_AND_READ_OK = 0x01

2390 FLAGS1_PATHCASELESS = 0x08

2391 FLAGS1_CANONICALIZED_PATHS = 0x10

2392 FLAGS1_REPLY = 0x80

2393

2394 # Flags2 Mask

2395 FLAGS2_LONG_NAMES = 0x0001

2396 FLAGS2_EAS = 0x0002

2397 FLAGS2_SMB_SECURITY_SIGNATURE = 0x0004

2398 FLAGS2_IS_LONG_NAME = 0x0040

2399 FLAGS2_DFS = 0x1000

2400 FLAGS2_PAGING_IO = 0x2000

2401 FLAGS2_NT_STATUS = 0x4000

2402 FLAGS2_UNICODE = 0x8000

2403 FLAGS2_COMPRESSED = 0x0008

2404 FLAGS2_SMB_SECURITY_SIGNATURE_REQUIRED = 0x0010

2405 FLAGS2_EXTENDED_SECURITY = 0x0800

2406

2407 # Dialect's Security Mode flags

2408 NEGOTIATE_USER_SECURITY = 0x01

2409 NEGOTIATE_ENCRYPT_PASSWORDS = 0x02

2410 NEGOTIATE_SECURITY_SIGNATURE_ENABLE = 0x04

2411 NEGOTIATE_SECURITY_SIGNATURE_REQUIRED = 0x08

2412

2413 # Tree Connect AndX Response optionalSuppor flags

2414 SMB_SUPPORT_SEARCH_BITS = 0x01

2415 SMB_SHARE_IS_IN_DFS = 0x02

2416

2417 def __init__(self, remote_name, remote_host, my_name=None, host_type=nmb.TYPE_SERVER, sess_port=445, timeout=None,

2418 UDP=0, session=None, negPacket=None):

2419 # The uid attribute will be set when the client calls the login() method

2420 self._uid = 0

2421 self.__server_name = ''

2422 self.__client_name = ''

2423 self.__server_os = ''

2424 self.__server_os_major = None

2425 self.__server_os_minor = None

2426 self.__server_os_build = None

2427 self.__server_lanman = ''

2428 self.__server_domain = ''

2429 self.__server_dns_domain_name = ''

2430 self.__server_dns_host_name = ''

2431 self.__remote_name = remote_name.upper()

2432 self.__remote_host = remote_host

2433 self.__isNTLMv2 = True

2434 self._dialects_parameters = None

2435 self._dialects_data = None

2436 self._doKerberos = False

2437

2438 # Credentials

2439 self.__userName = b''

2440 self.__password = b''

2441 self.__domain = b''

2442 self.__lmhash = b''

2443 self.__nthash = b''

2444 self.__aesKey = b''

2445 self.__kdc = b''

2446 self.__TGT = None

2447 self.__TGS = None

2448

2449 # Negotiate Protocol Result, used everywhere

2450 # Could be extended or not, flags should be checked before

2451 self._dialect_data = 0

2452 self._dialect_parameters = 0

2453 self._action = 0

2454 self._sess = None

2455 self.encrypt_passwords = True

2456 self.tid = 0

2457 self.fid = 0

2458

2459 # Strict host validation - off by default

2460 self._strict_hostname_validation = False

2461 self._validation_allow_absent = True

2462 self._accepted_hostname = ''

2463

2464 # Signing stuff

2465 self._SignSequenceNumber = 0

2466 self._SigningSessionKey = b''

2467 self._SigningChallengeResponse = b''

2468 self._SignatureEnabled = False

2469 self._SignatureVerificationEnabled = False

2470 self._SignatureRequired = False

2471

2472 # Base flags (default flags, can be overridden using set_flags())

2473 self.__flags1 = SMB.FLAGS1_PATHCASELESS | SMB.FLAGS1_CANONICALIZED_PATHS

2474 self.__flags2 = SMB.FLAGS2_EXTENDED_SECURITY | SMB.FLAGS2_NT_STATUS | SMB.FLAGS2_LONG_NAMES

2475

2476 if timeout is None: 2476 ↛ 2477line 2476 didn't jump to line 2477, because the condition on line 2476 was never true

2477 self.__timeout = 60

2478 else:

2479 self.__timeout = timeout

2480

2481 # If port 445 and the name sent is *SMBSERVER we're setting the name to the IP.

2482 # This is to help some old applications still believing

2483 # *SMSBSERVER will work against modern OSes. If port is NETBIOS_SESSION_PORT the user better

2484 # know about *SMBSERVER's limitations

2485 if sess_port == 445 and remote_name == '*SMBSERVER': 2485 ↛ 2486line 2485 didn't jump to line 2486, because the condition on line 2485 was never true

2486 self.__remote_name = remote_host

2487

2488 # This is on purpose. I'm still not convinced to do a socket.gethostname() if not specified

2489 if my_name is None: 2489 ↛ 2492line 2489 didn't jump to line 2492, because the condition on line 2489 was never false

2490 self.__client_name = b''

2491 else:

2492 self.__client_name = my_name

2493

2494 if session is None: 2494 ↛ 2516line 2494 didn't jump to line 2516, because the condition on line 2494 was never false

2495 if not my_name: 2495 ↛ 2502line 2495 didn't jump to line 2502, because the condition on line 2495 was never false

2496 # If destination port is 139 yes, there's some client disclosure

2497 my_name = socket.gethostname()

2498 i = my_name.find('.')

2499 if i > -1: 2499 ↛ 2500line 2499 didn't jump to line 2500, because the condition on line 2499 was never true

2500 my_name = my_name[:i]

2501

2502 if UDP: 2502 ↛ 2503line 2502 didn't jump to line 2503, because the condition on line 2502 was never true

2503 self._sess = nmb.NetBIOSUDPSession(my_name, remote_name, remote_host, host_type, sess_port, self.__timeout)

2504 else:

2505 self._sess = nmb.NetBIOSTCPSession(my_name, remote_name, remote_host, host_type, sess_port, self.__timeout)

2506

2507 # Initialize session values (_dialect_data and _dialect_parameters)

2508 self.neg_session()

2509

2510 # Call login() without any authentication information to

2511 # setup a session if the remote server

2512 # is in share mode.

2513 if (self._dialects_parameters['SecurityMode'] & SMB.SECURITY_SHARE_MASK) == SMB.SECURITY_SHARE_SHARE: 2513 ↛ 2514line 2513 didn't jump to line 2514, because the condition on line 2513 was never true

2514 self.login('', '')

2515 else:

2516 self._sess = session

2517 self.neg_session(negPacket = negPacket)

2518 # Call login() without any authentication information to

2519 # setup a session if the remote server

2520 # is in share mode.

2521 if (self._dialects_parameters['SecurityMode'] & SMB.SECURITY_SHARE_MASK) == SMB.SECURITY_SHARE_SHARE:

2522 self.login('', '')

2523

2524 @staticmethod

2525 def ntlm_supported():

2526 return False

2527

2528 def getKerberos(self):

2529 return self._doKerberos

2530

2531 def get_remote_name(self):

2532 return self.__remote_name

2533

2534 def set_remote_name(self, name):

2535 self.__remote_name = name

2536 return True

2537

2538 def set_hostname_validation(self, validate, accept_empty, hostname):

2539 self._strict_hostname_validation = validate

2540 self._validation_allow_absent = accept_empty

2541 self._accepted_hostname = hostname

2542

2543 def get_remote_host(self):

2544 return self.__remote_host

2545

2546 def get_flags(self):

2547 return self.__flags1, self.__flags2

2548

2549 def set_flags(self, flags1=None, flags2=None):

2550 if flags1 is not None:

2551 self.__flags1 = flags1

2552 if flags2 is not None: 2552 ↛ exitline 2552 didn't return from function 'set_flags', because the condition on line 2552 was never false

2553 self.__flags2 = flags2

2554

2555 def set_timeout(self, timeout):

2556 prev_timeout = self.__timeout

2557 self.__timeout = timeout

2558 return prev_timeout

2559

2560 def get_timeout(self):

2561 return self.__timeout

2562

2563 @contextmanager

2564 def use_timeout(self, timeout):

2565 prev_timeout = self.set_timeout(timeout)

2566 try:

2567 yield

2568 finally:

2569 self.set_timeout(prev_timeout)

2570

2571 def get_session(self):

2572 return self._sess

2573

2574 def get_tid(self):

2575 return self.tid

2576

2577 def get_fid(self):

2578 return self.fid

2579

2580 def isGuestSession(self):

2581 return self._action & SMB_SETUP_GUEST

2582

2583 def doesSupportNTLMv2(self):

2584 return self.__isNTLMv2

2585

2586 def close_session(self):

2587 if self._sess: 2587 ↛ exitline 2587 didn't return from function 'close_session', because the condition on line 2587 was never false

2588 self._sess.close()

2589 self._sess = None

2590

2591 def recvSMB(self):

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

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

2594

2595 @staticmethod

2596 def __decode_trans(params, data):

2597 totparamcnt, totdatacnt, _, paramcnt, paramoffset, paramds, datacnt, dataoffset, datads, setupcnt = unpack('<HHHHHHHHHB', params[:19])

2598 if paramcnt + paramds < totparamcnt or datacnt + datads < totdatacnt:

2599 has_more = 1

2600 else:

2601 has_more = 0

2602 paramoffset = paramoffset - 55 - setupcnt * 2

2603 dataoffset = dataoffset - 55 - setupcnt * 2

2604 return has_more, params[20:20 + setupcnt * 2], data[paramoffset: paramoffset + paramcnt], data[dataoffset: dataoffset + datacnt]

2605

2606 # TODO: Move this to NewSMBPacket, it belongs there

2607 def signSMB(self, packet, signingSessionKey, signingChallengeResponse):

2608 # This logic MUST be applied for messages sent in response to any of the higher-layer actions and in

2609 # compliance with the message sequencing rules.

2610 # * The client or server that sends the message MUST provide the 32-bit sequence number for this

2611 # message, as specified in sections 3.2.4.1 and 3.3.4.1.

2612 # * The SMB_FLAGS2_SMB_SECURITY_SIGNATURE flag in the header MUST be set.

2613 # * To generate the signature, a 32-bit sequence number is copied into the

2614 # least significant 32 bits of the SecuritySignature field and the remaining

2615 # 4 bytes are set to 0x00.

2616 # * The MD5 algorithm, as specified in [RFC1321], MUST be used to generate a hash of the SMB

2617 # message from the start of the SMB Header, which is defined as follows.

2618 # CALL MD5Init( md5context )

2619 # CALL MD5Update( md5context, Connection.SigningSessionKey )

2620 # CALL MD5Update( md5context, Connection.SigningChallengeResponse )

2621 # CALL MD5Update( md5context, SMB message )

2622 # CALL MD5Final( digest, md5context )

2623 # SET signature TO the first 8 bytes of the digest

2624 # The resulting 8-byte signature MUST be copied into the SecuritySignature field of the SMB Header,

2625 # after which the message can be transmitted.

2626

2627 #print "seq(%d) signingSessionKey %r, signingChallengeResponse %r" % (self._SignSequenceNumber, signingSessionKey, signingChallengeResponse)

2628 packet['SecurityFeatures'] = pack('<q',self._SignSequenceNumber)

2629 # Sign with the sequence

2630 m = hashlib.md5()

2631 m.update( signingSessionKey )

2632 m.update( signingChallengeResponse )

2633 m.update( packet.getData() )

2634 # Replace sequence with acual hash

2635 packet['SecurityFeatures'] = m.digest()[:8]

2636 if self._SignatureVerificationEnabled: 2636 ↛ 2637line 2636 didn't jump to line 2637, because the condition on line 2636 was never true

2637 self._SignSequenceNumber +=1

2638 else:

2639 self._SignSequenceNumber +=2

2640

2641 def checkSignSMB(self, packet, signingSessionKey, signingChallengeResponse):

2642 # Let's check

2643 signature = packet['SecurityFeatures']

2644 #print "Signature received: %r " % signature

2645 self.signSMB(packet, signingSessionKey, signingChallengeResponse)

2646 #print "Signature calculated: %r" % packet['SecurityFeatures']

2647 if self._SignatureVerificationEnabled is not True:

2648 self._SignSequenceNumber -= 1

2649 return packet['SecurityFeatures'] == signature

2650

2651 def sendSMB(self,smb):

2652 smb['Uid'] = self._uid

2653 #At least on AIX, PIDs can exceed 16 bits, so we mask them out

2654 smb['Pid'] = (os.getpid() & 0xFFFF)

2655 # set flags

2656 smb['Flags1'] |= self.__flags1

2657 smb['Flags2'] |= self.__flags2

2658 if self._SignatureEnabled:

2659 smb['Flags2'] |= SMB.FLAGS2_SMB_SECURITY_SIGNATURE

2660 self.signSMB(smb, self._SigningSessionKey, self._SigningChallengeResponse)

2661

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

2663

2664 @staticmethod

2665 def isValidAnswer(s, cmd):

2666 while 1:

2667 if s.rawData():

2668 if s.get_command() == cmd:

2669 if s.get_error_class() == 0x00 and s.get_error_code() == 0x00:

2670 return 1

2671 else:

2672 raise SessionError( "SMB Library Error", s.get_error_class()+ (s.get_reserved() << 8), s.get_error_code() , s.get_flags2() & SMB.FLAGS2_NT_STATUS)

2673 else:

2674 break

2675 return 0

2676

2677 def neg_session(self, extended_security = True, negPacket = None):

2678 def parsePacket(smb):

2679 # If server speaks Unicode, let's set that flag from now on

2680 if smb['Flags2'] & SMB.FLAGS2_UNICODE: 2680 ↛ 2681line 2680 didn't jump to line 2681, because the condition on line 2680 was never true

2681 self.__flags2 |= SMB.FLAGS2_UNICODE

2682

2683 if smb.isValidAnswer(SMB.SMB_COM_NEGOTIATE): 2683 ↛ 2712line 2683 didn't jump to line 2712, because the condition on line 2683 was never false

2684 sessionResponse = SMBCommand(smb['Data'][0])

2685 self._dialects_parameters = SMBNTLMDialect_Parameters(sessionResponse['Parameters'])

2686 self._dialects_data = SMBNTLMDialect_Data()

2687 self._dialects_data['ChallengeLength'] = self._dialects_parameters['ChallengeLength']

2688 self._dialects_data.fromString(sessionResponse['Data'])

2689 if self._dialects_parameters['Capabilities'] & SMB.CAP_EXTENDED_SECURITY: 2689 ↛ 2705line 2689 didn't jump to line 2705, because the condition on line 2689 was never false

2690 # Whether we choose it or it is enforced by the server, we go for extended security

2691 self._dialects_parameters = SMBExtended_Security_Parameters(sessionResponse['Parameters'])

2692 self._dialects_data = SMBExtended_Security_Data(sessionResponse['Data'])

2693 # Let's setup some variable for later use

2694 if self._dialects_parameters['SecurityMode'] & SMB.SECURITY_SIGNATURES_REQUIRED: 2694 ↛ 2701line 2694 didn't jump to line 2701, because the condition on line 2694 was never false

2695 self._SignatureRequired = True

2696

2697 # Interestingly, the security Blob might be missing sometimes.

2698 #spnego = SPNEGO_NegTokenInit(self._dialects_data['SecurityBlob'])

2699 #for i in spnego['MechTypes']:

2700 # print "Mech Found: %s" % MechTypes[i]

2701 return 1

2702

2703 # If not, let's try the old way

2704 else:

2705 if self._dialects_data['ServerName'] is not None:

2706 self.__server_name = self._dialects_data['ServerName']

2707

2708 if self._dialects_parameters['DialectIndex'] == 0xffff:

2709 raise UnsupportedFeature("Remote server does not know NT LM 0.12")

2710 return 1

2711 else:

2712 return 0

2713

2714 if negPacket is None: 2714 ↛ 2732line 2714 didn't jump to line 2732, because the condition on line 2714 was never false

2715 smb = NewSMBPacket()

2716 negSession = SMBCommand(SMB.SMB_COM_NEGOTIATE)

2717 flags2 = self.get_flags()[1]

2718 if extended_security is True: 2718 ↛ 2721line 2718 didn't jump to line 2721, because the condition on line 2718 was never false

2719 self.set_flags(flags2=flags2|SMB.FLAGS2_EXTENDED_SECURITY)

2720 else:

2721 self.set_flags(flags2=flags2 & (~SMB.FLAGS2_EXTENDED_SECURITY))

2722

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

2724 smb.addCommand(negSession)

2725 self.sendSMB(smb)

2726

2727 while 1:

2728 smb = self.recvSMB()

2729 return parsePacket(smb)

2730 else:

2731

2732 return parsePacket( NewSMBPacket( data = negPacket))

2733

2734 def tree_connect(self, path, password = '', service = SERVICE_ANY):

2735 LOG.warning("[MS-CIFS] This is an original Core Protocol command.This command has been deprecated.Client Implementations SHOULD use SMB_COM_TREE_CONNECT_ANDX")

2736

2737 # return 0x800

2738 if password:

2739 # Password is only encrypted if the server passed us an "encryption" during protocol dialect

2740 if self._dialects_parameters['ChallengeLength'] > 0:

2741 # this code is untested

2742 password = self.get_ntlmv1_response(ntlm.compute_lmhash(password))

2743

2744 if not unicode_support:

2745 if unicode_convert:

2746 path = str(path)

2747 else:

2748 raise Exception('SMB: Can\t conver path from unicode!')

2749

2750 smb = NewSMBPacket()

2751 treeConnect = SMBCommand(SMB.SMB_COM_TREE_CONNECT)

2752 treeConnect['Parameters'] = SMBTreeConnect_Parameters()

2753 treeConnect['Data'] = SMBTreeConnect_Data()

2754 treeConnect['Data']['Path'] = path.upper()

2755 treeConnect['Data']['Password'] = password

2756 treeConnect['Data']['Service'] = service

2757 smb.addCommand(treeConnect)

2758 self.sendSMB(smb)

2759

2760 while 1:

2761 smb = self.recvSMB()

2762 if smb.isValidAnswer(SMB.SMB_COM_TREE_CONNECT):

2763 # XXX Here we are ignoring the rest of the response

2764 return smb['Tid']

2765 return smb['Tid']

2766

2767 def get_uid(self):

2768 return self._uid

2769

2770 def set_uid(self, uid):

2771 self._uid = uid

2772

2773 def tree_connect_andx(self, path, password = None, service = SERVICE_ANY, smb_packet=None):

2774 if password: 2774 ↛ 2776line 2774 didn't jump to line 2776, because the condition on line 2774 was never true

2775 # Password is only encrypted if the server passed us an "encryption" during protocol dialect

2776 if self._dialects_parameters['ChallengeLength'] > 0:

2777 # this code is untested

2778 password = self.get_ntlmv1_response(ntlm.compute_lmhash(password))

2779 else:

2780 password = '\x00'

2781

2782 if not unicode_support: 2782 ↛ 2788line 2782 didn't jump to line 2788, because the condition on line 2782 was never false

2783 if unicode_convert: 2783 ↛ 2786line 2783 didn't jump to line 2786, because the condition on line 2783 was never false

2784 path = str(path)

2785 else:

2786 raise Exception('SMB: Can\t convert path from unicode!')

2787

2788 if smb_packet is None: 2788 ↛ 2791line 2788 didn't jump to line 2791, because the condition on line 2788 was never false

2789 smb = NewSMBPacket()

2790 else:

2791 smb = smb_packet

2792

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

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

2795

2796 share = path.split('\\')[-1]

2797 try:

2798 _, _, _, _, sockaddr = socket.getaddrinfo(self.get_remote_host(), 80, 0, 0, socket.IPPROTO_TCP)[0]

2799 remote_host = sockaddr[0]

2800 except Exception:

2801 remote_host = self.get_remote_host()

2802

2803 path = '\\\\' + remote_host + '\\' +share

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

2805

2806 treeConnect = SMBCommand(SMB.SMB_COM_TREE_CONNECT_ANDX)

2807 treeConnect['Parameters'] = SMBTreeConnectAndX_Parameters()

2808 treeConnect['Data'] = SMBTreeConnectAndX_Data(flags=self.__flags2)

2809 treeConnect['Parameters']['PasswordLength'] = len(password)

2810 treeConnect['Data']['Password'] = password

2811 treeConnect['Data']['Path'] = path

2812 treeConnect['Data']['Service'] = service

2813

2814 if self.__flags2 & SMB.FLAGS2_UNICODE:

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

2816

2817 smb.addCommand(treeConnect)

2818

2819 # filename = "\PIPE\epmapper"

2820

2821 # ntCreate = SMBCommand(SMB.SMB_COM_NT_CREATE_ANDX)

2822 # ntCreate['Parameters'] = SMBNtCreateAndX_Parameters()

2823 # ntCreate['Data'] = SMBNtCreateAndX_Data()

2824 # ntCreate['Parameters']['FileNameLength'] = len(filename)

2825 # ntCreate['Parameters']['CreateFlags'] = 0

2826 # ntCreate['Parameters']['AccessMask'] = 0x3

2827 # ntCreate['Parameters']['CreateOptions'] = 0x0

2828 # ntCreate['Data']['FileName'] = filename

2829

2830 # smb.addCommand(ntCreate)

2831 self.sendSMB(smb)

2832

2833 while 1:

2834 smb = self.recvSMB()

2835 if smb.isValidAnswer(SMB.SMB_COM_TREE_CONNECT_ANDX): 2835 ↛ 2839line 2835 didn't jump to line 2839, because the condition on line 2835 was never false

2836 # XXX Here we are ignoring the rest of the response

2837 self.tid = smb['Tid']

2838 return self.tid

2839 self.tid = smb['Tid']

2840 return self.tid

2841

2842 # backwars compatibility

2843 connect_tree = tree_connect_andx

2844

2845 @staticmethod

2846 def getDialect():

2847 return SMB_DIALECT

2848

2849 def get_server_name(self):

2850 #return self._dialects_data['ServerName']

2851 return self.__server_name

2852

2853 def get_client_name(self):

2854 return self.__client_name

2855

2856 def get_session_key(self):

2857 return self._SigningSessionKey

2858

2859 def set_session_key(self, key):

2860 self._SignatureEnabled = True

2861 self._SignSequenceNumber = 2

2862 self._SigningSessionKey = key

2863

2864 def get_encryption_key(self):

2865 if 'Challenge' in self._dialects_data.fields:

2866 return self._dialects_data['Challenge']

2867 else:

2868 return None

2869

2870 def get_server_time(self):

2871 timestamp = self._dialects_parameters['HighDateTime']

2872 timestamp <<= 32

2873 timestamp |= self._dialects_parameters['LowDateTime']

2874 timestamp -= 116444736000000000

2875 timestamp //= 10000000

2876 d = datetime.datetime.utcfromtimestamp(timestamp)

2877 return d.strftime("%a, %d %b %Y %H:%M:%S GMT")

2878

2879 def disconnect_tree(self, tid):

2880 smb = NewSMBPacket()

2881 smb['Tid'] = tid

2882

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

2884

2885 self.sendSMB(smb)

2886 self.recvSMB()

2887

2888 def open(self, tid, filename, open_mode, desired_access):

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

2890 filename = filename.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else filename

2891

2892 smb = NewSMBPacket()

2893 smb['Tid'] = tid

2894

2895 openFile = SMBCommand(SMB.SMB_COM_OPEN)

2896 openFile['Parameters'] = SMBOpen_Parameters()

2897 openFile['Parameters']['DesiredAccess'] = desired_access

2898 openFile['Parameters']['OpenMode'] = open_mode

2899 openFile['Parameters']['SearchAttributes'] = ATTR_READONLY | ATTR_HIDDEN | ATTR_ARCHIVE

2900 openFile['Data'] = SMBOpen_Data(flags=self.__flags2)

2901 openFile['Data']['FileName'] = filename

2902

2903 smb.addCommand(openFile)

2904

2905 self.sendSMB(smb)

2906

2907 smb = self.recvSMB()

2908 if smb.isValidAnswer(SMB.SMB_COM_OPEN):

2909 # XXX Here we are ignoring the rest of the response

2910 openFileResponse = SMBCommand(smb['Data'][0])

2911 openFileParameters = SMBOpenResponse_Parameters(openFileResponse['Parameters'])

2912

2913 return (

2914 openFileParameters['Fid'],

2915 openFileParameters['FileAttributes'],

2916 openFileParameters['LastWriten'],

2917 openFileParameters['FileSize'],

2918 openFileParameters['GrantedAccess'],

2919 )

2920

2921 def open_andx(self, tid, filename, open_mode, desired_access):

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

2923 filename = filename.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else filename

2924

2925 smb = NewSMBPacket()

2926 smb['Tid'] = tid

2927

2928 openFile = SMBCommand(SMB.SMB_COM_OPEN_ANDX)

2929 openFile['Parameters'] = SMBOpenAndX_Parameters()

2930 openFile['Parameters']['DesiredAccess'] = desired_access

2931 openFile['Parameters']['OpenMode'] = open_mode

2932 openFile['Parameters']['SearchAttributes'] = ATTR_READONLY | ATTR_HIDDEN | ATTR_ARCHIVE

2933 openFile['Data'] = SMBOpenAndX_Data(flags=self.__flags2)

2934 openFile['Data']['FileName'] = filename

2935

2936 if self.__flags2 & SMB.FLAGS2_UNICODE:

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

2938

2939 smb.addCommand(openFile)

2940

2941 self.sendSMB(smb)

2942

2943 smb = self.recvSMB()

2944 if smb.isValidAnswer(SMB.SMB_COM_OPEN_ANDX):

2945 # XXX Here we are ignoring the rest of the response

2946 openFileResponse = SMBCommand(smb['Data'][0])

2947 openFileParameters = SMBOpenAndXResponse_Parameters(openFileResponse['Parameters'])

2948

2949 return (

2950 openFileParameters['Fid'],

2951 openFileParameters['FileAttributes'],

2952 openFileParameters['LastWriten'],

2953 openFileParameters['FileSize'],

2954 openFileParameters['GrantedAccess'],

2955 openFileParameters['FileType'],

2956 openFileParameters['IPCState'],

2957 openFileParameters['Action'],

2958 openFileParameters['ServerFid'],

2959 )

2960

2961 def close(self, tid, fid):

2962 smb = NewSMBPacket()

2963 smb['Tid'] = tid

2964

2965 closeFile = SMBCommand(SMB.SMB_COM_CLOSE)

2966 closeFile['Parameters'] = SMBClose_Parameters()

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

2968 smb.addCommand(closeFile)

2969

2970 self.sendSMB(smb)

2971 smb = self.recvSMB()

2972 if smb.isValidAnswer(SMB.SMB_COM_CLOSE): 2972 ↛ 2974line 2972 didn't jump to line 2974, because the condition on line 2972 was never false

2973 return 1

2974 return 0

2975

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

2977 smb = NewSMBPacket()

2978 smb['Tid'] = tid

2979

2980 transCommand = SMBCommand(SMB.SMB_COM_TRANSACTION)

2981 transCommand['Parameters'] = SMBTransaction_Parameters()

2982 transCommand['Data'] = SMBTransaction_Data()

2983

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

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

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

2987

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

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

2990

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

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

2993

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

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

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

2997

2998 if noAnswer:

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

3000

3001 smb.addCommand(transCommand)

3002

3003 self.sendSMB(smb)

3004

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

3006 smb = NewSMBPacket()

3007 smb['Tid'] = tid

3008

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

3010

3011 transCommand = SMBCommand(SMB.SMB_COM_TRANSACTION2)

3012 transCommand['Parameters'] = SMBTransaction2_Parameters()

3013 transCommand['Parameters']['MaxDataCount'] = self._dialects_parameters['MaxBufferSize']

3014 transCommand['Data'] = SMBTransaction2_Data()

3015

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

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

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

3019

3020 if len(param) > 0: 3020 ↛ 3025line 3020 didn't jump to line 3025, because the condition on line 3020 was never false

3021 padLen = (4 - (32+2+28 + len(command)) % 4 ) % 4

3022 padBytes = '\xFF' * padLen

3023 transCommand['Data']['Pad1'] = padBytes

3024 else:

3025 transCommand['Data']['Pad1'] = ''

3026 padLen = 0

3027

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

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

3030

3031 if len(data) > 0: 3031 ↛ 3032line 3031 didn't jump to line 3032, because the condition on line 3031 was never true

3032 pad2Len = (4 - (32+2+28 + len(command) + padLen + len(param)) % 4) % 4

3033 transCommand['Data']['Pad2'] = '\xFF' * pad2Len

3034 else:

3035 transCommand['Data']['Pad2'] = ''

3036 pad2Len = 0

3037

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

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

3040

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

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

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

3044 smb.addCommand(transCommand)

3045

3046 self.sendSMB(smb)

3047

3048 def query_file_info(self, tid, fid, fileInfoClass = SMB_QUERY_FILE_STANDARD_INFO):

3049 self.send_trans2(tid, SMB.TRANS2_QUERY_FILE_INFORMATION, '\x00', pack('<HH', fid, fileInfoClass), '')

3050

3051 resp = self.recvSMB()

3052 if resp.isValidAnswer(SMB.SMB_COM_TRANSACTION2): 3052 ↛ exitline 3052 didn't return from function 'query_file_info', because the condition on line 3052 was never false

3053 trans2Response = SMBCommand(resp['Data'][0])

3054 trans2Parameters = SMBTransaction2Response_Parameters(trans2Response['Parameters'])

3055 # Remove Potential Prefix Padding

3056 return trans2Response['Data'][-trans2Parameters['TotalDataCount']:]

3057

3058 def __nonraw_retr_file(self, tid, fid, offset, datasize, callback):

3059 if (self._dialects_parameters['Capabilities'] & SMB.CAP_LARGE_READX) and self._SignatureEnabled is False: 3059 ↛ 3060line 3059 didn't jump to line 3060, because the condition on line 3059 was never true

3060 max_buf_size = 65000

3061 else:

3062 max_buf_size = self._dialects_parameters['MaxBufferSize'] & ~0x3ff # Read in multiple KB blocks

3063

3064 read_offset = offset

3065 while read_offset < datasize:

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

3067

3068 callback(data)

3069 read_offset += len(data)

3070

3071 def __nonraw_stor_file(self, tid, fid, offset, datasize, callback):

3072 if (self._dialects_parameters['Capabilities'] & SMB.CAP_LARGE_WRITEX) and self._SignatureEnabled is False: 3072 ↛ 3073line 3072 didn't jump to line 3073, because the condition on line 3072 was never true

3073 max_buf_size = 65000

3074 else:

3075 max_buf_size = self._dialects_parameters['MaxBufferSize'] & ~0x3ff # Write in multiple KB blocks

3076

3077 write_offset = offset

3078 while 1:

3079 data = callback(max_buf_size)

3080 if not data:

3081 break

3082

3083 smb = self.write_andx(tid,fid,data, write_offset)

3084 writeResponse = SMBCommand(smb['Data'][0])

3085 writeResponseParameters = SMBWriteAndXResponse_Parameters(writeResponse['Parameters'])

3086 write_offset += writeResponseParameters['Count']

3087

3088 def get_server_domain(self):

3089 return self.__server_domain

3090

3091 def get_server_dns_domain_name(self):

3092 return self.__server_dns_domain_name

3093

3094 def get_server_dns_host_name(self):

3095 return self.__server_dns_host_name

3096

3097 def get_server_os(self):

3098 return self.__server_os

3099

3100 def get_server_os_major(self):

3101 return self.__server_os_major

3102

3103 def get_server_os_minor(self):

3104 return self.__server_os_minor

3105

3106 def get_server_os_build(self):

3107 return self.__server_os_build

3108

3109 def set_server_os(self, os):

3110 self.__server_os = os

3111

3112 def get_server_lanman(self):

3113 return self.__server_lanman

3114

3115 def is_login_required(self):

3116 # Login is required if share mode is user.

3117 # Otherwise only public services or services in share mode

3118 # are allowed.

3119 return (self._dialects_parameters['SecurityMode'] & SMB.SECURITY_SHARE_MASK) == SMB.SECURITY_SHARE_USER

3120

3121 def is_signing_required(self):

3122 return self._SignatureRequired

3123

3124 def get_ntlmv1_response(self, key):

3125 challenge = self._dialects_data['Challenge']

3126 return ntlm.get_ntlmv1_response(key, challenge)

3127

3128 def perform_hostname_validation(self):

3129 if self.__server_name == '':

3130 if not self._validation_allow_absent:

3131 raise self.HostnameValidationException('Hostname was not supplied by target host and absent validation is disallowed')

3132 return

3133 if self.__server_name.lower() != self._accepted_hostname.lower() and self.__server_dns_host_name.lower() != self._accepted_hostname.lower():

3134 raise self.HostnameValidationException('Supplied hostname %s does not match reported hostnames %s or %s' %

3135 (self._accepted_hostname.lower(), self.__server_name.lower(), self.__server_dns_host_name.lower()))

3136

3137

3138 def kerberos_login(self, user, password, domain = '', lmhash = '', nthash = '', aesKey = '', kdcHost = '', TGT=None, TGS=None):

3139 # Importing down here so pyasn1 is not required if kerberos is not used.

3140 from impacket.krb5.asn1 import AP_REQ, Authenticator, TGS_REP, seq_set

3141 from impacket.krb5.kerberosv5 import getKerberosTGT, getKerberosTGS

3142 from impacket.krb5 import constants

3143 from impacket.krb5.types import Principal, KerberosTime, Ticket

3144 from pyasn1.codec.der import decoder, encoder

3145 import datetime

3146

3147 # login feature does not support unicode

3148 # disable it if enabled

3149 flags2 = self.__flags2

3150 if flags2 & SMB.FLAGS2_UNICODE:

3151 self.__flags2 = flags2 & (flags2 ^ SMB.FLAGS2_UNICODE)

3152

3153 # If TGT or TGS are specified, they are in the form of:

3154 # TGS['KDC_REP'] = the response from the server

3155 # TGS['cipher'] = the cipher used

3156 # TGS['sessionKey'] = the sessionKey

3157 # If we have hashes, normalize them

3158 if lmhash != '' or nthash != '':

3159 if len(lmhash) % 2: 3159 ↛ 3160line 3159 didn't jump to line 3160, because the condition on line 3159 was never true

3160 lmhash = '0%s' % lmhash

3161 if len(nthash) % 2: 3161 ↛ 3162line 3161 didn't jump to line 3162, because the condition on line 3161 was never true

3162 nthash = '0%s' % nthash

3163 try: # just in case they were converted already

3164 lmhash = a2b_hex(lmhash)

3165 nthash = a2b_hex(nthash)

3166 except:

3167 pass

3168

3169 self.__userName = user

3170 self.__password = password

3171 self.__domain = domain

3172 self.__lmhash = lmhash

3173 self.__nthash = nthash

3174 self.__aesKey = aesKey

3175 self.__kdc = kdcHost

3176 self.__TGT = TGT

3177 self.__TGS = TGS

3178 self._doKerberos= True

3179

3180 # First of all, we need to get a TGT for the user

3181 userName = Principal(user, type=constants.PrincipalNameType.NT_PRINCIPAL.value)

3182 if TGT is None: 3182 ↛ 3186line 3182 didn't jump to line 3186, because the condition on line 3182 was never false

3183 if TGS is None: 3183 ↛ 3192line 3183 didn't jump to line 3192, because the condition on line 3183 was never false

3184 tgt, cipher, oldSessionKey, sessionKey = getKerberosTGT(userName, password, domain, lmhash, nthash, aesKey, kdcHost)

3185 else:

3186 tgt = TGT['KDC_REP']

3187 cipher = TGT['cipher']

3188 sessionKey = TGT['sessionKey']

3189

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

3191

3192 if TGS is None: 3192 ↛ 3196line 3192 didn't jump to line 3196, because the condition on line 3192 was never false

3193 serverName = Principal('cifs/%s' % self.__remote_name, type=constants.PrincipalNameType.NT_SRV_INST.value)

3194 tgs, cipher, oldSessionKey, sessionKey = getKerberosTGS(serverName, domain, kdcHost, tgt, cipher, sessionKey)

3195 else:

3196 tgs = TGS['KDC_REP']

3197 cipher = TGS['cipher']

3198 sessionKey = TGS['sessionKey']

3199

3200 smb = NewSMBPacket()

3201

3202 # Are we required to sign SMB? If so we do it, if not we skip it

3203 if self._SignatureRequired: 3203 ↛ 3207line 3203 didn't jump to line 3207, because the condition on line 3203 was never false

3204 smb['Flags2'] |= SMB.FLAGS2_SMB_SECURITY_SIGNATURE

3205

3206

3207 sessionSetup = SMBCommand(SMB.SMB_COM_SESSION_SETUP_ANDX)

3208 sessionSetup['Parameters'] = SMBSessionSetupAndX_Extended_Parameters()

3209 sessionSetup['Data'] = SMBSessionSetupAndX_Extended_Data()

3210

3211 sessionSetup['Parameters']['MaxBufferSize'] = 61440

3212 sessionSetup['Parameters']['MaxMpxCount'] = 2

3213 sessionSetup['Parameters']['VcNumber'] = 1

3214 sessionSetup['Parameters']['SessionKey'] = 0

3215 sessionSetup['Parameters']['Capabilities'] = SMB.CAP_EXTENDED_SECURITY | SMB.CAP_USE_NT_ERRORS | SMB.CAP_UNICODE | SMB.CAP_LARGE_READX | SMB.CAP_LARGE_WRITEX

3216

3217

3218 # Let's build a NegTokenInit with the NTLMSSP

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

3220

3221 blob = SPNEGO_NegTokenInit()

3222

3223 # Kerberos v5 mech

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

3225

3226 # Let's extract the ticket from the TGS

3227 tgs = decoder.decode(tgs, asn1Spec = TGS_REP())[0]

3228 ticket = Ticket()

3229 ticket.from_asn1(tgs['ticket'])

3230

3231 # Now let's build the AP_REQ

3232 apReq = AP_REQ()

3233 apReq['pvno'] = 5

3234 apReq['msg-type'] = int(constants.ApplicationTagNumbers.AP_REQ.value)

3235

3236 opts = list()

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

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

3239

3240 authenticator = Authenticator()

3241 authenticator['authenticator-vno'] = 5

3242 authenticator['crealm'] = domain

3243 seq_set(authenticator, 'cname', userName.components_to_asn1)

3244 now = datetime.datetime.utcnow()

3245

3246 authenticator['cusec'] = now.microsecond

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

3248

3249 encodedAuthenticator = encoder.encode(authenticator)

3250

3251 # Key Usage 11

3252 # AP-REQ Authenticator (includes application authenticator

3253 # subkey), encrypted with the application session key

3254 # (Section 5.5.1)

3255 encryptedEncodedAuthenticator = cipher.encrypt(sessionKey, 11, encodedAuthenticator, None)

3256

3257 apReq['authenticator'] = noValue

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

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

3260

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

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

3263

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

3265 sessionSetup['Parameters'].getData()

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

3267

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

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

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

3271

3272 smb.addCommand(sessionSetup)

3273 self.sendSMB(smb)

3274

3275 smb = self.recvSMB()

3276 if smb.isValidAnswer(SMB.SMB_COM_SESSION_SETUP_ANDX): 3276 ↛ 3300line 3276 didn't jump to line 3300, because the condition on line 3276 was never false

3277 # We will need to use this uid field for all future requests/responses

3278 self._uid = smb['Uid']

3279

3280 # Now we have to extract the blob to continue the auth process

3281 sessionResponse = SMBCommand(smb['Data'][0])

3282 sessionParameters = SMBSessionSetupAndX_Extended_Response_Parameters(sessionResponse['Parameters'])

3283 sessionData = SMBSessionSetupAndX_Extended_Response_Data(flags = smb['Flags2'])

3284 sessionData['SecurityBlobLength'] = sessionParameters['SecurityBlobLength']

3285 sessionData.fromString(sessionResponse['Data'])

3286

3287 self._action = sessionParameters['Action']

3288 # If smb sign required, let's enable it for the rest of the connection

3289 if self._dialects_parameters['SecurityMode'] & SMB.SECURITY_SIGNATURES_REQUIRED: 3289 ↛ 3295line 3289 didn't jump to line 3295, because the condition on line 3289 was never false

3290 self._SigningSessionKey = sessionKey.contents

3291 self._SignSequenceNumber = 2

3292 self._SignatureEnabled = True

3293

3294 # restore unicode flag if needed

3295 if flags2 & SMB.FLAGS2_UNICODE:

3296 self.__flags2 |= SMB.FLAGS2_UNICODE

3297

3298 return 1

3299 else:

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

3301

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

3303

3304 # login feature does not support unicode

3305 # disable it if enabled

3306 flags2 = self.__flags2

3307 if flags2 & SMB.FLAGS2_UNICODE:

3308 self.__flags2 = flags2 & (flags2 ^ SMB.FLAGS2_UNICODE)

3309

3310 # Once everything's working we should join login methods into a single one

3311 smb = NewSMBPacket()

3312 # Are we required to sign SMB? If so we do it, if not we skip it

3313 if self._SignatureRequired: 3313 ↛ 3316line 3313 didn't jump to line 3316, because the condition on line 3313 was never false

3314 smb['Flags2'] |= SMB.FLAGS2_SMB_SECURITY_SIGNATURE

3315

3316 sessionSetup = SMBCommand(SMB.SMB_COM_SESSION_SETUP_ANDX)

3317 sessionSetup['Parameters'] = SMBSessionSetupAndX_Extended_Parameters()

3318 sessionSetup['Data'] = SMBSessionSetupAndX_Extended_Data()

3319

3320 sessionSetup['Parameters']['MaxBufferSize'] = 61440

3321 sessionSetup['Parameters']['MaxMpxCount'] = 2

3322 sessionSetup['Parameters']['VcNumber'] = 1

3323 sessionSetup['Parameters']['SessionKey'] = 0

3324 sessionSetup['Parameters']['Capabilities'] = SMB.CAP_EXTENDED_SECURITY | SMB.CAP_USE_NT_ERRORS | SMB.CAP_UNICODE | SMB.CAP_LARGE_READX | SMB.CAP_LARGE_WRITEX

3325

3326

3327 # Let's build a NegTokenInit with the NTLMSSP

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

3329

3330 blob = SPNEGO_NegTokenInit()

3331

3332 # NTLMSSP

3333 blob['MechTypes'] = [TypesMech['NTLMSSP - Microsoft NTLM Security Support Provider']]

3334 auth = ntlm.getNTLMSSPType1(self.get_client_name(),domain,self._SignatureRequired, use_ntlmv2 = use_ntlmv2)

3335 blob['MechToken'] = auth.getData()

3336

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

3338 sessionSetup['Parameters'].getData()

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

3340

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

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

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

3344

3345 smb.addCommand(sessionSetup)

3346 self.sendSMB(smb)

3347

3348 smb = self.recvSMB()

3349 if smb.isValidAnswer(SMB.SMB_COM_SESSION_SETUP_ANDX): 3349 ↛ 3446line 3349 didn't jump to line 3446, because the condition on line 3349 was never false

3350 # We will need to use this uid field for all future requests/responses

3351 self._uid = smb['Uid']

3352

3353 # Now we have to extract the blob to continue the auth process

3354 sessionResponse = SMBCommand(smb['Data'][0])

3355 sessionParameters = SMBSessionSetupAndX_Extended_Response_Parameters(sessionResponse['Parameters'])

3356 sessionData = SMBSessionSetupAndX_Extended_Response_Data(flags = smb['Flags2'])

3357 sessionData['SecurityBlobLength'] = sessionParameters['SecurityBlobLength']

3358 sessionData.fromString(sessionResponse['Data'])

3359 respToken = SPNEGO_NegTokenResp(sessionData['SecurityBlob'])

3360

3361 # Let's parse some data and keep it to ourselves in case it is asked

3362 ntlmChallenge = ntlm.NTLMAuthChallenge(respToken['ResponseToken'])

3363 if ntlmChallenge['TargetInfoFields_len'] > 0: 3363 ↛ 3392line 3363 didn't jump to line 3392, because the condition on line 3363 was never false

3364 av_pairs = ntlm.AV_PAIRS(ntlmChallenge['TargetInfoFields'][:ntlmChallenge['TargetInfoFields_len']])

3365 if av_pairs[ntlm.NTLMSSP_AV_HOSTNAME] is not None: 3365 ↛ 3371line 3365 didn't jump to line 3371, because the condition on line 3365 was never false

3366 try:

3367 self.__server_name = av_pairs[ntlm.NTLMSSP_AV_HOSTNAME][1].decode('utf-16le')

3368 except UnicodeDecodeError:

3369 # For some reason, we couldn't decode Unicode here.. silently discard the operation

3370 pass

3371 if av_pairs[ntlm.NTLMSSP_AV_DOMAINNAME] is not None: 3371 ↛ 3378line 3371 didn't jump to line 3378, because the condition on line 3371 was never false

3372 try:

3373 if self.__server_name != av_pairs[ntlm.NTLMSSP_AV_DOMAINNAME][1].decode('utf-16le'): 3373 ↛ 3378line 3373 didn't jump to line 3378, because the condition on line 3373 was never false

3374 self.__server_domain = av_pairs[ntlm.NTLMSSP_AV_DOMAINNAME][1].decode('utf-16le')

3375 except UnicodeDecodeError:

3376 # For some reason, we couldn't decode Unicode here.. silently discard the operation

3377 pass

3378 if av_pairs[ntlm.NTLMSSP_AV_DNS_DOMAINNAME] is not None: 3378 ↛ 3385line 3378 didn't jump to line 3385, because the condition on line 3378 was never false

3379 try:

3380 self.__server_dns_domain_name = av_pairs[ntlm.NTLMSSP_AV_DNS_DOMAINNAME][1].decode('utf-16le')

3381 except UnicodeDecodeError:

3382 # For some reason, we couldn't decode Unicode here.. silently discard the operation

3383 pass

3384

3385 if av_pairs[ntlm.NTLMSSP_AV_DNS_HOSTNAME] is not None: 3385 ↛ 3392line 3385 didn't jump to line 3392, because the condition on line 3385 was never false

3386 try:

3387 self.__server_dns_host_name = av_pairs[ntlm.NTLMSSP_AV_DNS_HOSTNAME][1].decode('utf-16le')

3388 except UnicodeDecodeError:

3389 # For some reason, we couldn't decode Unicode here.. silently discard the operation

3390 pass

3391

3392 if self._strict_hostname_validation: 3392 ↛ 3393line 3392 didn't jump to line 3393, because the condition on line 3392 was never true

3393 self.perform_hostname_validation()

3394

3395 # Parse Version to know the target Operating system name. Not provided elsewhere anymore

3396 if 'Version' in ntlmChallenge.fields: 3396 ↛ 3402line 3396 didn't jump to line 3402, because the condition on line 3396 was never false

3397 version = ntlmChallenge['Version']

3398

3399 if len(version) >= 4: 3399 ↛ 3402line 3399 didn't jump to line 3402, because the condition on line 3399 was never false

3400 self.__server_os_major, self.__server_os_minor, self.__server_os_build = unpack('<BBH',version[:4])

3401

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

3403

3404 if exportedSessionKey is not None: 3404 ↛ 3407line 3404 didn't jump to line 3407, because the condition on line 3404 was never false

3405 self._SigningSessionKey = exportedSessionKey

3406

3407 smb = NewSMBPacket()

3408

3409 # Are we required to sign SMB? If so we do it, if not we skip it

3410 if self._SignatureRequired: 3410 ↛ 3413line 3410 didn't jump to line 3413, because the condition on line 3410 was never false

3411 smb['Flags2'] |= SMB.FLAGS2_SMB_SECURITY_SIGNATURE

3412

3413 respToken2 = SPNEGO_NegTokenResp()

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

3415

3416 # Reusing the previous structure

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

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

3419

3420 # Storing some info for later use

3421 self.__server_os = sessionData['NativeOS']

3422 self.__server_lanman = sessionData['NativeLanMan']

3423

3424 smb.addCommand(sessionSetup)

3425 self.sendSMB(smb)

3426

3427 smb = self.recvSMB()

3428 self._uid = 0

3429 if smb.isValidAnswer(SMB.SMB_COM_SESSION_SETUP_ANDX): 3429 ↛ exitline 3429 didn't return from function 'login_extended', because the condition on line 3429 was never false

3430 self._uid = smb['Uid']

3431 sessionResponse = SMBCommand(smb['Data'][0])

3432 sessionParameters = SMBSessionSetupAndXResponse_Parameters(sessionResponse['Parameters'])

3433

3434 self._action = sessionParameters['Action']

3435 # If smb sign required, let's enable it for the rest of the connection

3436 if self._dialects_parameters['SecurityMode'] & SMB.SECURITY_SIGNATURES_REQUIRED: 3436 ↛ 3441line 3436 didn't jump to line 3441, because the condition on line 3436 was never false

3437 self._SignSequenceNumber = 2

3438 self._SignatureEnabled = True

3439

3440 # restore unicode flag if needed

3441 if flags2 & SMB.FLAGS2_UNICODE:

3442 self.__flags2 |= SMB.FLAGS2_UNICODE

3443

3444 return 1

3445 else:

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

3447

3448 def getCredentials(self):

3449 return (

3450 self.__userName,

3451 self.__password,

3452 self.__domain,

3453 self.__lmhash,

3454 self.__nthash,

3455 self.__aesKey,

3456 self.__TGT,

3457 self.__TGS)

3458

3459 def getIOCapabilities(self):

3460 res = dict()

3461 if (self._dialects_parameters['Capabilities'] & SMB.CAP_LARGE_READX) and self._SignatureEnabled is False: 3461 ↛ 3462line 3461 didn't jump to line 3462, because the condition on line 3461 was never true

3462 max_size = 65000

3463 else:

3464 max_size = self._dialects_parameters['MaxBufferSize'] # Read in multiple KB blocks

3465 res['MaxReadSize'] = max_size

3466 res['MaxWriteSize'] = max_size

3467 return res

3468

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

3470

3471 # If we have hashes, normalize them

3472 if lmhash != '' or nthash != '':

3473 if len(lmhash) % 2: 3473 ↛ 3474line 3473 didn't jump to line 3474, because the condition on line 3473 was never true

3474 lmhash = '0%s' % lmhash

3475 if len(nthash) % 2: 3475 ↛ 3476line 3475 didn't jump to line 3476, because the condition on line 3475 was never true

3476 nthash = '0%s' % nthash

3477 try: # just in case they were converted already

3478 lmhash = a2b_hex(lmhash)

3479 nthash = a2b_hex(nthash)

3480 except:

3481 pass

3482

3483 self.__userName = user

3484 self.__password = password

3485 self.__domain = domain

3486 self.__lmhash = lmhash

3487 self.__nthash = nthash

3488 self.__aesKey = ''

3489 self.__TGT = None

3490 self.__TGS = None

3491

3492 if self._dialects_parameters['Capabilities'] & SMB.CAP_EXTENDED_SECURITY: 3492 ↛ 3502line 3492 didn't jump to line 3502, because the condition on line 3492 was never false

3493 try:

3494 self.login_extended(user, password, domain, lmhash, nthash, use_ntlmv2 = True)

3495 except:

3496 # If the target OS is Windows 5.0 or Samba, let's try using NTLMv1

3497 if ntlm_fallback and ((self.get_server_lanman().find('Windows 2000') != -1) or (self.get_server_lanman().find('Samba') != -1)):

3498 self.login_extended(user, password, domain, lmhash, nthash, use_ntlmv2 = False)

3499 self.__isNTLMv2 = False

3500 else:

3501 raise

3502 elif ntlm_fallback:

3503 self.login_standard(user, password, domain, lmhash, nthash)

3504 self.__isNTLMv2 = False

3505 else:

3506 raise SessionError('Cannot authenticate against target, enable ntlm_fallback')

3507

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

3509

3510 # login feature does not support unicode

3511 # disable it if enabled

3512 flags2 = self.__flags2

3513 if flags2 & SMB.FLAGS2_UNICODE:

3514 self.__flags2 = flags2 & (flags2 ^ SMB.FLAGS2_UNICODE)

3515

3516 # Only supports NTLMv1

3517 # Password is only encrypted if the server passed us an "encryption key" during protocol dialect negotiation

3518 if self._dialects_parameters['ChallengeLength'] > 0:

3519 if lmhash != '' or nthash != '':

3520 pwd_ansi = self.get_ntlmv1_response(lmhash)

3521 pwd_unicode = self.get_ntlmv1_response(nthash)

3522 elif password:

3523 lmhash = ntlm.compute_lmhash(password)

3524 nthash = ntlm.compute_nthash(password)

3525 pwd_ansi = self.get_ntlmv1_response(lmhash)

3526 pwd_unicode = self.get_ntlmv1_response(nthash)

3527 else: # NULL SESSION

3528 pwd_ansi = ''

3529 pwd_unicode = ''

3530 else:

3531 pwd_ansi = password

3532 pwd_unicode = ''

3533

3534 smb = NewSMBPacket()

3535

3536 sessionSetup = SMBCommand(SMB.SMB_COM_SESSION_SETUP_ANDX)

3537 sessionSetup['Parameters'] = SMBSessionSetupAndX_Parameters()

3538 sessionSetup['Data'] = SMBSessionSetupAndX_Data()

3539

3540 sessionSetup['Parameters']['MaxBuffer'] = 61440

3541 sessionSetup['Parameters']['MaxMpxCount'] = 2

3542 sessionSetup['Parameters']['VCNumber'] = os.getpid() & 0xFFFF # Value has to be expressed in 2 bytes

3543 sessionSetup['Parameters']['SessionKey'] = self._dialects_parameters['SessionKey']

3544 sessionSetup['Parameters']['AnsiPwdLength'] = len(pwd_ansi)

3545 sessionSetup['Parameters']['UnicodePwdLength'] = len(pwd_unicode)

3546 sessionSetup['Parameters']['Capabilities'] = SMB.CAP_RAW_MODE | SMB.CAP_USE_NT_ERRORS | SMB.CAP_LARGE_READX | SMB.CAP_LARGE_WRITEX

3547

3548 sessionSetup['Data']['AnsiPwd'] = pwd_ansi

3549 sessionSetup['Data']['UnicodePwd'] = pwd_unicode

3550 sessionSetup['Data']['Account'] = str(user)

3551 sessionSetup['Data']['PrimaryDomain'] = str(domain)

3552 sessionSetup['Data']['NativeOS'] = str(os.name)

3553 sessionSetup['Data']['NativeLanMan'] = 'pysmb'

3554 smb.addCommand(sessionSetup)

3555

3556 self.sendSMB(smb)

3557

3558 smb = self.recvSMB()

3559 if smb.isValidAnswer(SMB.SMB_COM_SESSION_SETUP_ANDX):

3560 # We will need to use this uid field for all future requests/responses

3561 self._uid = smb['Uid']

3562 sessionResponse = SMBCommand(smb['Data'][0])

3563 sessionParameters = SMBSessionSetupAndXResponse_Parameters(sessionResponse['Parameters'])

3564 sessionData = SMBSessionSetupAndXResponse_Data(flags = smb['Flags2'], data = sessionResponse['Data'])

3565

3566 self._action = sessionParameters['Action']

3567

3568 # Still gotta figure out how to do this with no EXTENDED_SECURITY

3569 if sessionParameters['Action'] & SMB_SETUP_USE_LANMAN_KEY == 0:

3570 self._SigningChallengeResponse = sessionSetup['Data']['UnicodePwd']

3571 self._SigningSessionKey = nthash

3572 else:

3573 self._SigningChallengeResponse = sessionSetup['Data']['AnsiPwd']

3574 self._SigningSessionKey = lmhash

3575

3576 #self._SignSequenceNumber = 1

3577 #self.checkSignSMB(smb, self._SigningSessionKey ,self._SigningChallengeResponse)

3578 #self._SignatureEnabled = True

3579 self.__server_os = sessionData['NativeOS']

3580 self.__server_lanman = sessionData['NativeLanMan']

3581 self.__server_domain = sessionData['PrimaryDomain']

3582

3583 # restore unicode flag if needed

3584 if flags2 & SMB.FLAGS2_UNICODE:

3585 self.__flags2 |= SMB.FLAGS2_UNICODE

3586

3587 return 1

3588 else:

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

3590

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

3592 smb = NewSMBPacket()

3593 smb['Tid'] = tid

3594

3595 transCommand = SMBCommand(SMB.SMB_COM_TRANSACTION)

3596 transCommand['Parameters'] = SMBTransaction_Parameters()

3597 transCommand['Data'] = SMBTransaction_Data()

3598

3599 setup = '\x53\x00\x00\x00'

3600 name = '\\PIPE%s\x00' % pipe

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

3602 transCommand['Parameters']['TotalParameterCount'] = 0

3603 transCommand['Parameters']['TotalDataCount'] = 0

3604 transCommand['Parameters']['MaxParameterCount'] = 0

3605 transCommand['Parameters']['MaxDataCount'] = 0

3606 transCommand['Parameters']['Timeout'] = timeout * 1000

3607

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

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

3610

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

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

3613

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

3615 transCommand['Data']['Trans_Parameters'] = ''

3616 transCommand['Data']['Trans_Data'] = ''

3617

3618 if noAnswer:

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

3620

3621 smb.addCommand(transCommand)

3622 self.sendSMB(smb)

3623

3624 smb = self.recvSMB()

3625 if smb.isValidAnswer(SMB.SMB_COM_TRANSACTION):

3626 return 1

3627 return 0

3628

3629 def read(self, tid, fid, offset=0, max_size = None, wait_answer=1):

3630 if not max_size:

3631 max_size = self._dialects_parameters['MaxBufferSize'] # Read in multiple KB blocks

3632

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

3634

3635 smb = NewSMBPacket()

3636 smb['Tid'] = tid

3637

3638 read = SMBCommand(SMB.SMB_COM_READ)

3639 read['Parameters'] = SMBRead_Parameters()

3640 read['Parameters']['Fid'] = fid

3641 read['Parameters']['Offset'] = offset

3642 read['Parameters']['Count'] = max_size

3643 smb.addCommand(read)

3644

3645 if wait_answer:

3646 while 1:

3647 self.sendSMB(smb)

3648 ans = self.recvSMB()

3649

3650 if ans.isValidAnswer(SMB.SMB_COM_READ):

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

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

3653

3654 return readData['Data']

3655

3656 return None

3657

3658 def read_andx(self, tid, fid, offset=0, max_size = None, wait_answer=1, smb_packet=None):

3659 if not max_size: 3659 ↛ 3660line 3659 didn't jump to line 3660, because the condition on line 3659 was never true

3660 if (self._dialects_parameters['Capabilities'] & SMB.CAP_LARGE_READX) and self._SignatureEnabled is False:

3661 max_size = 65000

3662 else:

3663 max_size = self._dialects_parameters['MaxBufferSize'] # Read in multiple KB blocks

3664

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

3666

3667 if smb_packet is None: 3667 ↛ 3678line 3667 didn't jump to line 3678, because the condition on line 3667 was never false

3668 smb = NewSMBPacket()

3669 smb['Tid'] = tid

3670

3671 readAndX = SMBCommand(SMB.SMB_COM_READ_ANDX)

3672 readAndX['Parameters'] = SMBReadAndX_Parameters()

3673 readAndX['Parameters']['Fid'] = fid

3674 readAndX['Parameters']['Offset'] = offset

3675 readAndX['Parameters']['MaxCount'] = max_size

3676 smb.addCommand(readAndX)

3677 else:

3678 smb = smb_packet

3679

3680 if wait_answer: 3680 ↛ 3699line 3680 didn't jump to line 3699, because the condition on line 3680 was never false

3681 answer = b''

3682 while 1:

3683 self.sendSMB(smb)

3684 ans = self.recvSMB()

3685

3686 if ans.isValidAnswer(SMB.SMB_COM_READ_ANDX): 3686 ↛ 3683line 3686 didn't jump to line 3683, because the condition on line 3686 was never false

3687 # XXX Here we are only using a few fields from the response

3688 readAndXResponse = SMBCommand(ans['Data'][0])

3689 readAndXParameters = SMBReadAndXResponse_Parameters(readAndXResponse['Parameters'])

3690

3691 offset = readAndXParameters['DataOffset']

3692 count = readAndXParameters['DataCount']+0x10000*readAndXParameters['DataCount_Hi']

3693 answer += ans.getData()[offset: offset+count]

3694 if not ans.isMoreData(): 3694 ↛ 3696line 3694 didn't jump to line 3696, because the condition on line 3694 was never false

3695 return answer

3696 max_size = min(max_size, readAndXParameters['Remaining'])

3697 readAndX['Parameters']['Offset'] += count # XXX Offset is not important (apparently)

3698 else:

3699 self.sendSMB(smb)

3700 ans = self.recvSMB()

3701

3702 try:

3703 if ans.isValidAnswer(SMB.SMB_COM_READ_ANDX):

3704 return ans

3705 else:

3706 return None

3707 except:

3708 return ans

3709

3710 return None

3711

3712 def read_raw(self, tid, fid, offset=0, max_size = None, wait_answer=1):

3713 if not max_size:

3714 max_size = self._dialects_parameters['MaxBufferSize'] # Read in multiple KB blocks

3715

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

3717 smb = NewSMBPacket()

3718 smb['Tid'] = tid

3719

3720 readRaw = SMBCommand(SMB.SMB_COM_READ_RAW)

3721 readRaw['Parameters'] = SMBReadRaw_Parameters()

3722 readRaw['Parameters']['Fid'] = fid

3723 readRaw['Parameters']['Offset'] = offset

3724 readRaw['Parameters']['MaxCount'] = max_size

3725 smb.addCommand(readRaw)

3726

3727 self.sendSMB(smb)

3728 if wait_answer:

3729 data = self._sess.recv_packet(self.__timeout).get_trailer()

3730 if not data:

3731 # If there is no data it means there was an error

3732 data = self.read_andx(tid, fid, offset, max_size)

3733 return data

3734

3735 return None

3736

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

3738 smb = NewSMBPacket()

3739 smb['Tid'] = tid

3740

3741 write = SMBCommand(SMB.SMB_COM_WRITE)

3742 write['Parameters'] = SMBWrite_Parameters()

3743 write['Data'] = SMBWrite_Data()

3744 write['Parameters']['Fid'] = fid

3745 write['Parameters']['Count'] = len(data)

3746 write['Parameters']['Offset'] = offset

3747 write['Parameters']['Remaining'] = len(data)

3748 write['Data']['Data'] = data

3749 smb.addCommand(write)

3750

3751 self.sendSMB(smb)

3752

3753 if wait_answer:

3754 smb = self.recvSMB()

3755 if smb.isValidAnswer(SMB.SMB_COM_WRITE):

3756 return smb

3757 return None

3758

3759 def write_andx(self,tid,fid,data, offset = 0, wait_answer=1, write_pipe_mode = False, smb_packet=None):

3760 if smb_packet is None: 3760 ↛ 3810line 3760 didn't jump to line 3810, because the condition on line 3760 was never false

3761 smb = NewSMBPacket()

3762 smb['Tid'] = tid

3763

3764 writeAndX = SMBCommand(SMB.SMB_COM_WRITE_ANDX)

3765 smb.addCommand(writeAndX)

3766

3767 writeAndX['Parameters'] = SMBWriteAndX_Parameters()

3768 writeAndX['Parameters']['Fid'] = fid

3769 writeAndX['Parameters']['Offset'] = offset

3770 writeAndX['Parameters']['WriteMode'] = 8

3771 writeAndX['Parameters']['Remaining'] = len(data)

3772 writeAndX['Parameters']['DataLength'] = len(data)

3773 writeAndX['Parameters']['DataOffset'] = len(smb) # this length already includes the parameter

3774 writeAndX['Data'] = data

3775

3776 if write_pipe_mode is True: 3776 ↛ 3778line 3776 didn't jump to line 3778, because the condition on line 3776 was never true

3777 # First of all we gotta know what the MaxBuffSize is

3778 maxBuffSize = self._dialects_parameters['MaxBufferSize']

3779 if len(data) > maxBuffSize:

3780 chunks_size = maxBuffSize - 60

3781 writeAndX['Parameters']['WriteMode'] = 0x0c

3782 sendData = b'\xff\xff' + data

3783 totalLen = len(sendData)

3784 writeAndX['Parameters']['DataLength'] = chunks_size

3785 writeAndX['Parameters']['Remaining'] = totalLen-2

3786 writeAndX['Data'] = sendData[:chunks_size]

3787

3788 self.sendSMB(smb)

3789 if wait_answer:

3790 smbResp = self.recvSMB()

3791 smbResp.isValidAnswer(SMB.SMB_COM_WRITE_ANDX)

3792

3793 alreadySent = chunks_size

3794 sendData = sendData[chunks_size:]

3795

3796 while alreadySent < totalLen:

3797 writeAndX['Parameters']['WriteMode'] = 0x04

3798 writeAndX['Parameters']['DataLength'] = len(sendData[:chunks_size])

3799 writeAndX['Data'] = sendData[:chunks_size]

3800 self.sendSMB(smb)

3801 if wait_answer:

3802 smbResp = self.recvSMB()

3803 smbResp.isValidAnswer(SMB.SMB_COM_WRITE_ANDX)

3804 alreadySent += writeAndX['Parameters']['DataLength']

3805 sendData = sendData[chunks_size:]

3806

3807 return smbResp

3808

3809 else:

3810 smb = smb_packet

3811

3812 self.sendSMB(smb)

3813

3814 if wait_answer: 3814 ↛ 3818line 3814 didn't jump to line 3818, because the condition on line 3814 was never false

3815 smb = self.recvSMB()

3816 if smb.isValidAnswer(SMB.SMB_COM_WRITE_ANDX): 3816 ↛ 3818line 3816 didn't jump to line 3818, because the condition on line 3816 was never false

3817 return smb

3818 return None

3819

3820 def write_raw(self,tid,fid,data, offset = 0, wait_answer=1):

3821 LOG.warning("[MS-CIFS] This command was introduced in the CorePlus dialect, but is often listed as part of the LAN Manager 1.0 dialect.This command has been deprecated.Clients SHOULD use SMB_COM_WRITE_ANDX")

3822 smb = NewSMBPacket()

3823 smb['Tid'] = tid

3824

3825 writeRaw = SMBCommand(SMB.SMB_COM_WRITE_RAW)

3826 writeRaw['Parameters'] = SMBWriteRaw_Parameters()

3827 writeRaw['Parameters']['Fid'] = fid

3828 writeRaw['Parameters']['Offset'] = offset

3829 writeRaw['Parameters']['Count'] = len(data)

3830 writeRaw['Parameters']['DataLength'] = 0

3831 writeRaw['Parameters']['DataOffset'] = 0

3832 smb.addCommand(writeRaw)

3833

3834 self.sendSMB(smb)

3835 self._sess.send_packet(data)

3836

3837 if wait_answer:

3838 smb = self.recvSMB()

3839 if smb.isValidAnswer(SMB.SMB_COM_WRITE_RAW):

3840 return smb

3841 return None

3842

3843 def TransactNamedPipe(self, tid, fid, data = '', noAnswer = 0, waitAnswer = 1, offset = 0):

3844 self.send_trans(tid,pack('<HH', 0x26, fid),'\\PIPE\\\x00','',data, noAnswer = noAnswer)

3845

3846 if noAnswer or not waitAnswer:

3847 return

3848 smb = self.recvSMB()

3849 if smb.isValidAnswer(SMB.SMB_COM_TRANSACTION):

3850 transResponse = SMBCommand(smb['Data'][0])

3851 transParameters = SMBTransactionResponse_Parameters(transResponse['Parameters'])

3852 return transResponse['Data'][-transParameters['TotalDataCount']:] # Remove Potential Prefix Padding

3853 return None

3854

3855 def TransactNamedPipeRecv(self):

3856 s = self.recvSMB()

3857 if s.isValidAnswer(SMB.SMB_COM_TRANSACTION):

3858 transResponse = SMBCommand(s['Data'][0])

3859 transParameters = SMBTransactionResponse_Parameters(transResponse['Parameters'])

3860 return transResponse['Data'][-transParameters['TotalDataCount']:] # Remove Potential Prefix Padding

3861 return None

3862

3863 def nt_create_andx(self,tid,filename, smb_packet=None, cmd = None, shareAccessMode = FILE_SHARE_READ | FILE_SHARE_WRITE, disposition = FILE_OPEN, accessMask = 0x2019f):

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

3865 filename = filename.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else filename

3866

3867 if smb_packet is None: 3867 ↛ 3871line 3867 didn't jump to line 3871, because the condition on line 3867 was never false

3868 smb = NewSMBPacket()

3869 smb['Tid'] = tid

3870 else:

3871 smb = smb_packet

3872

3873 if cmd is None:

3874 ntCreate = SMBCommand(SMB.SMB_COM_NT_CREATE_ANDX)

3875 ntCreate['Parameters'] = SMBNtCreateAndX_Parameters()

3876 ntCreate['Data'] = SMBNtCreateAndX_Data(flags=self.__flags2)

3877 ntCreate['Parameters']['FileNameLength'] = len(filename)

3878 ntCreate['Parameters']['CreateFlags'] = 0x16

3879 ntCreate['Parameters']['AccessMask'] = accessMask

3880 ntCreate['Parameters']['CreateOptions'] = 0x40

3881 ntCreate['Parameters']['ShareAccess'] = shareAccessMode

3882 ntCreate['Parameters']['Disposition'] = disposition

3883 ntCreate['Data']['FileName'] = filename

3884

3885 if self.__flags2 & SMB.FLAGS2_UNICODE:

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

3887 else:

3888 ntCreate = cmd

3889

3890 smb.addCommand(ntCreate)

3891

3892 self.sendSMB(smb)

3893

3894 while 1:

3895 smb = self.recvSMB()

3896 if smb.isValidAnswer(SMB.SMB_COM_NT_CREATE_ANDX): 3896 ↛ 3895line 3896 didn't jump to line 3895, because the condition on line 3896 was never false

3897 # XXX Here we are ignoring the rest of the response

3898 ntCreateResponse = SMBCommand(smb['Data'][0])

3899 ntCreateParameters = SMBNtCreateAndXResponse_Parameters(ntCreateResponse['Parameters'])

3900

3901 self.fid = ntCreateParameters['Fid']

3902 return ntCreateParameters['Fid']

3903

3904 def logoff(self):

3905 smb = NewSMBPacket()

3906

3907 logOff = SMBCommand(SMB.SMB_COM_LOGOFF_ANDX)

3908 logOff['Parameters'] = SMBLogOffAndX()

3909 smb.addCommand(logOff)

3910

3911 self.sendSMB(smb)

3912 self.recvSMB()

3913 # Let's clear some fields so you can login again under the same session

3914 self._uid = 0

3915

3916 def list_path(self, service, path = '*', password = None):

3917 path = path.replace('/', '\\')

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

3919

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

3921 try:

3922 findFirstParameter = SMBFindFirst2_Parameters(self.__flags2)

3923 findFirstParameter['SearchAttributes'] = SMB_FILE_ATTRIBUTE_DIRECTORY | SMB_FILE_ATTRIBUTE_HIDDEN | \

3924 SMB_FILE_ATTRIBUTE_SYSTEM | SMB_FILE_ATTRIBUTE_READONLY | \

3925 SMB_FILE_ATTRIBUTE_ARCHIVE

3926 findFirstParameter['SearchCount'] = 512

3927 findFirstParameter['Flags'] = SMB_FIND_RETURN_RESUME_KEYS | SMB_FIND_CLOSE_AT_EOS

3928 findFirstParameter['InformationLevel'] = SMB_FIND_FILE_BOTH_DIRECTORY_INFO

3929 findFirstParameter['SearchStorageType'] = 0

3930 if self.__flags2 & SMB.FLAGS2_UNICODE:

3931 findFirstParameter['FileName'] = path + b'\x00\x00'

3932 else:

3933 findFirstParameter['FileName'] = path + '\x00'

3934 self.send_trans2(tid, SMB.TRANS2_FIND_FIRST2, '\x00', findFirstParameter, '')

3935 files = [ ]

3936

3937 totalDataCount = 1

3938 findData = b''

3939 findFirst2ParameterBlock = b''

3940 while len(findData) < totalDataCount:

3941 resp = self.recvSMB()

3942

3943 if resp.isValidAnswer(SMB.SMB_COM_TRANSACTION2): 3943 ↛ 3940line 3943 didn't jump to line 3940, because the condition on line 3943 was never false

3944 trans2Response = SMBCommand(resp['Data'][0])

3945 trans2Parameters = SMBTransaction2Response_Parameters(trans2Response['Parameters'])

3946 totalDataCount = trans2Parameters['TotalDataCount']

3947 findFirst2ParameterBlock += trans2Response['Data'][trans2Parameters['ParameterOffset']-55:][:trans2Parameters['ParameterCount']]

3948 findData += trans2Response['Data'][trans2Parameters['DataOffset']-55:]

3949

3950 findParameterBlock = SMBFindFirst2Response_Parameters(findFirst2ParameterBlock)

3951 # Save the SID for resume operations

3952 sid = findParameterBlock['SID']

3953

3954 while findParameterBlock['SearchCount'] > 0: 3954 ↛ 3999line 3954 didn't jump to line 3999, because the condition on line 3954 was never false

3955 record = SMBFindFileBothDirectoryInfo(data = findData)

3956

3957 shortname = record['ShortName'].decode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else \

3958 record['ShortName'].decode('cp437')

3959 filename = record['FileName'].decode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else \

3960 record['FileName'].decode('cp437')

3961

3962 fileRecord = SharedFile(record['CreationTime'], record['LastAccessTime'], record['LastChangeTime'],

3963 record['EndOfFile'], record['AllocationSize'], record['ExtFileAttributes'],

3964 shortname, filename)

3965 files.append(fileRecord)

3966 if record['NextEntryOffset'] > 0 and len(findData[record['NextEntryOffset']:]) > 0:

3967 findData = findData[record['NextEntryOffset']:]

3968 else:

3969 # More data to search?

3970 if findParameterBlock['EndOfSearch'] == 0: 3970 ↛ 3971line 3970 didn't jump to line 3971, because the condition on line 3970 was never true

3971 resume_filename = record['FileName']

3972 findNextParameter = SMBFindNext2_Parameters()

3973 findNextParameter['SID'] = sid

3974 findNextParameter['SearchCount'] = 1024

3975 findNextParameter['InformationLevel'] = SMB_FIND_FILE_BOTH_DIRECTORY_INFO

3976 findNextParameter['ResumeKey'] = 0

3977 findNextParameter['Flags'] = SMB_FIND_RETURN_RESUME_KEYS | SMB_FIND_CLOSE_AT_EOS

3978 if self.__flags2 & SMB.FLAGS2_UNICODE:

3979 findNextParameter['FileName'] = resume_filename + b'\x00\x00'

3980 else:

3981 findNextParameter['FileName'] = resume_filename + b'\x00'

3982 self.send_trans2(tid, SMB.TRANS2_FIND_NEXT2, '\x00', findNextParameter, '')

3983 findData = b''

3984 findNext2ParameterBlock = b''

3985 totalDataCount = 1

3986 while len(findData) < totalDataCount:

3987 resp = self.recvSMB()

3988

3989 if resp.isValidAnswer(SMB.SMB_COM_TRANSACTION2):

3990 trans2Response = SMBCommand(resp['Data'][0])

3991 trans2Parameters = SMBTransaction2Response_Parameters(trans2Response['Parameters'])

3992 totalDataCount = trans2Parameters['TotalDataCount']

3993 findNext2ParameterBlock += trans2Response['Data'][trans2Parameters['ParameterOffset']-55:][:trans2Parameters['ParameterCount']]

3994 findData += trans2Response['Data'][trans2Parameters['DataOffset']-55:]

3995 findParameterBlock = SMBFindNext2Response_Parameters(findNext2ParameterBlock)

3996 else:

3997 break

3998 finally:

3999 self.disconnect_tree(tid)

4000

4001 return files

4002

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

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

4005

4006 fid = -1

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

4008 try:

4009 fid = self.nt_create_andx(tid, filename, shareAccessMode = shareAccessMode, accessMask = 0x20089)

4010

4011 res = self.query_file_info(tid, fid)

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

4013

4014 self.__nonraw_retr_file(tid, fid, offset, datasize, callback)

4015 finally:

4016 if fid >= 0: 4016 ↛ 4018line 4016 didn't jump to line 4018, because the condition on line 4016 was never false

4017 self.close(tid, fid)

4018 self.disconnect_tree(tid)

4019

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

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

4022

4023 fid = -1

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

4025 try:

4026 fid = self.nt_create_andx(tid, filename, shareAccessMode = shareAccessMode, disposition = mode )

4027

4028 self.__nonraw_stor_file(tid, fid, offset, 0, callback)

4029 finally:

4030 if fid >= 0: 4030 ↛ 4032line 4030 didn't jump to line 4032, because the condition on line 4030 was never false

4031 self.close(tid, fid)

4032 self.disconnect_tree(tid)

4033

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

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

4036

4037 fid = -1

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

4039 try:

4040 fid = self.nt_create_andx(tid, filename, shareAccessMode = shareAccessMode, disposition = mode)

4041 self.__nonraw_stor_file(tid, fid, offset, 0, callback)

4042 finally:

4043 if fid >= 0:

4044 self.close(tid, fid)

4045 self.disconnect_tree(tid)

4046

4047 def check_dir(self, service, path, password = None):

4048 path = path.replace('/', '\\')

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

4050 try:

4051 smb = NewSMBPacket()

4052 smb['Tid'] = tid

4053 smb['Mid'] = 0

4054

4055 cmd = SMBCommand(SMB.SMB_COM_CHECK_DIRECTORY)

4056 cmd['Parameters'] = ''

4057 cmd['Data'] = SMBCheckDirectory_Data(flags = self.__flags2)

4058 cmd['Data']['DirectoryName'] = path.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else path

4059 smb.addCommand(cmd)

4060

4061 self.sendSMB(smb)

4062

4063 while 1:

4064 s = self.recvSMB()

4065 if s.isValidAnswer(SMB.SMB_COM_CHECK_DIRECTORY): 4065 ↛ 4064line 4065 didn't jump to line 4064, because the condition on line 4065 was never false

4066 return

4067 finally:

4068 self.disconnect_tree(tid)

4069

4070 def remove(self, service, path, password = None):

4071 path = path.replace('/', '\\')

4072 # Perform a list to ensure the path exists

4073 self.list_path(service, path, password)

4074

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

4076 try:

4077 smb = NewSMBPacket()

4078 smb['Tid'] = tid

4079 smb['Mid'] = 0

4080

4081 cmd = SMBCommand(SMB.SMB_COM_DELETE)

4082 cmd['Parameters'] = SMBDelete_Parameters()

4083 cmd['Parameters']['SearchAttributes'] = ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE

4084 cmd['Data'] = SMBDelete_Data(flags = self.__flags2)

4085 cmd['Data']['FileName'] = (path + '\x00').encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else (path + '\x00')

4086 smb.addCommand(cmd)

4087

4088 self.sendSMB(smb)

4089

4090 while 1:

4091 s = self.recvSMB()

4092 if s.isValidAnswer(SMB.SMB_COM_DELETE): 4092 ↛ 4091line 4092 didn't jump to line 4091, because the condition on line 4092 was never false

4093 return

4094 finally:

4095 self.disconnect_tree(tid)

4096

4097 def rmdir(self, service, path, password = None):

4098 path = path.replace('/', '\\')

4099 # Check that the directory exists

4100 self.check_dir(service, path, password)

4101

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

4103 try:

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

4105

4106 smb = NewSMBPacket()

4107 smb['Tid'] = tid

4108 createDir = SMBCommand(SMB.SMB_COM_DELETE_DIRECTORY)

4109 createDir['Data'] = SMBDeleteDirectory_Data(flags=self.__flags2)

4110 createDir['Data']['DirectoryName'] = path

4111 smb.addCommand(createDir)

4112

4113 self.sendSMB(smb)

4114

4115 while 1:

4116 s = self.recvSMB()

4117 if s.isValidAnswer(SMB.SMB_COM_DELETE_DIRECTORY): 4117 ↛ 4116line 4117 didn't jump to line 4116, because the condition on line 4117 was never false

4118 return

4119 finally:

4120 self.disconnect_tree(tid)

4121

4122 def mkdir(self, service, path, password = None):

4123 path = path.replace('/', '\\')

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

4125 try:

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

4127

4128 smb = NewSMBPacket()

4129 smb['Tid'] = tid

4130 smb['Mid'] = 0

4131

4132 createDir = SMBCommand(SMB.SMB_COM_CREATE_DIRECTORY)

4133 createDir['Data'] = SMBCreateDirectory_Data(flags=self.__flags2)

4134 createDir['Data']['DirectoryName'] = path

4135 smb.addCommand(createDir)

4136

4137 self.sendSMB(smb)

4138

4139 smb = self.recvSMB()

4140 if smb.isValidAnswer(SMB.SMB_COM_CREATE_DIRECTORY): 4140 ↛ 4142line 4140 didn't jump to line 4142, because the condition on line 4140 was never false

4141 return 1

4142 return 0

4143 finally:

4144 self.disconnect_tree(tid)

4145

4146 def rename(self, service, old_path, new_path, password = None):

4147 old_path = old_path.replace('/', '\\')

4148 new_path = new_path.replace('/', '\\')

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

4150 try:

4151 smb = NewSMBPacket()

4152 smb['Tid'] = tid

4153 smb['Mid'] = 0

4154

4155 renameCmd = SMBCommand(SMB.SMB_COM_RENAME)

4156 renameCmd['Parameters'] = SMBRename_Parameters()

4157 renameCmd['Parameters']['SearchAttributes'] = ATTR_SYSTEM | ATTR_HIDDEN | ATTR_DIRECTORY

4158 renameCmd['Data'] = SMBRename_Data(flags = self.__flags2)

4159 renameCmd['Data']['OldFileName'] = old_path.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else old_path

4160 renameCmd['Data']['NewFileName'] = new_path.encode('utf-16le') if self.__flags2 & SMB.FLAGS2_UNICODE else new_path

4161 smb.addCommand(renameCmd)

4162

4163 self.sendSMB(smb)

4164

4165 smb = self.recvSMB()

4166 if smb.isValidAnswer(SMB.SMB_COM_RENAME): 4166 ↛ 4168line 4166 didn't jump to line 4168, because the condition on line 4166 was never false

4167 return 1

4168 return 0

4169 finally:

4170 self.disconnect_tree(tid)

4171

4172 def writeFile(self, treeId, fileId, data, offset = 0):

4173 if (self._dialects_parameters['Capabilities'] & SMB.CAP_LARGE_WRITEX) and self._SignatureEnabled is False: 4173 ↛ 4174line 4173 didn't jump to line 4174, because the condition on line 4173 was never true

4174 max_buf_size = 65000

4175 else:

4176 max_buf_size = self._dialects_parameters['MaxBufferSize'] & ~0x3ff # Write in multiple KB blocks

4177

4178 write_offset = offset

4179 while 1:

4180 if len(data) == 0:

4181 break

4182 writeData = data[:max_buf_size]

4183 data = data[max_buf_size:]

4184

4185 smb = self.write_andx(treeId,fileId,writeData, write_offset)

4186 writeResponse = SMBCommand(smb['Data'][0])

4187 writeResponseParameters = SMBWriteAndXResponse_Parameters(writeResponse['Parameters'])

4188 write_offset += writeResponseParameters['Count']

4189

4190 def get_socket(self):

4191 return self._sess.get_socket()

4192

4193 def send_nt_trans(self, tid, subcommand, max_param_count, setup='', param='', data=''):

4194 """

4195 [MS-CIFS]: 2.2.4.62.1 SMB_COM_NT_TRANSACT request.

4196 :param tid:

4197 :param subcommand: The transaction subcommand code

4198 :param max_param_count: This field MUST be set as specified in the subsections of Transaction subcommands.

4199 :param setup: Transaction context to the server, depends on transaction subcommand.

4200 :param param: Subcommand parameter bytes if any, depends on transaction subcommand.

4201 :param data: Subcommand data bytes if any, depends on transaction subcommand.

4202 :return: Buffer relative to requested subcommand.

4203 """

4204 smb_packet = NewSMBPacket()

4205 smb_packet['Tid'] = tid

4206 # setup depends on NT_TRANSACT subcommands so it may be 0.

4207 setup_bytes = pack('<H', setup) if setup != '' else ''

4208

4209 transCommand = SMBCommand(SMB.SMB_COM_NT_TRANSACT)

4210 transCommand['Parameters'] = SMBNTTransaction_Parameters()

4211 transCommand['Parameters']['MaxDataCount'] = self._dialects_parameters['MaxBufferSize']

4212 transCommand['Parameters']['Setup'] = setup_bytes

4213 transCommand['Parameters']['Function'] = subcommand

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

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

4216 transCommand['Parameters']['MaxParameterCount'] = max_param_count

4217 transCommand['Parameters']['MaxSetupCount'] = 0

4218

4219 transCommand['Data'] = SMBNTTransaction_Data()

4220

4221 # SMB header size + SMB_COM_NT_TRANSACT parameters size + length of setup bytes.

4222 offset = 32 + 3 + 38 + len(setup_bytes)

4223 transCommand['Data']['Pad1'] = ''

4224 if offset % 4 != 0:

4225 transCommand['Data']['Pad1'] = '\0' * (4 - offset % 4)

4226 offset += (4 - offset % 4) # pad1 length

4227

4228 if len(param) > 0:

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

4230 else:

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

4232

4233 offset += len(param)

4234 transCommand['Data']['Pad2'] = ''

4235 if offset % 4 != 0:

4236 transCommand['Data']['Pad2'] = '\0' * (4 - offset % 4)

4237 offset += (4 - offset % 4)

4238

4239 if len(data) > 0:

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

4241 else:

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

4243

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

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

4246 transCommand['Data']['NT_Trans_Parameters'] = param

4247 transCommand['Data']['NT_Trans_Data'] = data

4248 smb_packet.addCommand(transCommand)

4249

4250 self.sendSMB(smb_packet)

4251

4252 def query_sec_info(self, tid, fid, additional_information=7):

4253 """

4254 [MS-CIFS]: 2.2.7.6.1

4255 NT_TRANSACT_QUERY_SECURITY_DESC 0x0006

4256 :param tid: valid tree id.

4257 :param fid: valid file handle.

4258 :param additional_information: SecurityInfoFields. default = owner + group + dacl ie. 7

4259 :return: security descriptor buffer

4260 """

4261 self.send_nt_trans(tid, subcommand=0x0006, max_param_count=4,

4262 param=pack('<HHL', fid, 0x0000, additional_information))

4263 resp = self.recvSMB()

4264 if resp.isValidAnswer(SMB.SMB_COM_NT_TRANSACT):

4265 nt_trans_response = SMBCommand(resp['Data'][0])

4266 nt_trans_parameters = SMBNTTransactionResponse_Parameters(nt_trans_response['Parameters'])

4267 # Remove Potential Prefix Padding

4268 return nt_trans_response['Data'][-nt_trans_parameters['TotalDataCount']:]

4269

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

4271

4272 smb = NewSMBPacket()

4273 comEcho = SMBCommand(SMB.SMB_COM_ECHO)

4274 comEcho['Parameters'] = SMBEcho_Parameters()

4275 comEcho['Data'] = SMBEcho_Data()

4276 comEcho['Parameters']['EchoCount'] = count

4277 comEcho['Data']['Data'] = text

4278 smb.addCommand(comEcho)

4279

4280 self.sendSMB(smb)

4281

4282 for i in range(count):

4283 resp = self.recvSMB()

4284 resp.isValidAnswer(SMB.SMB_COM_ECHO)

4285 return True

4286

4287 ERRDOS = { 1: 'Invalid function',

4288 2: 'File not found',

4289 3: 'Invalid directory',

4290 4: 'Too many open files',

4291 5: 'Access denied',

4292 6: 'Invalid file handle. Please file a bug report.',

4293 7: 'Memory control blocks destroyed',

4294 8: 'Out of memory',

4295 9: 'Invalid memory block address',

4296 10: 'Invalid environment',

4297 11: 'Invalid format',

4298 12: 'Invalid open mode',

4299 13: 'Invalid data',

4300 15: 'Invalid drive',

4301 16: 'Attempt to remove server\'s current directory',

4302 17: 'Not the same device',

4303 18: 'No files found',

4304 32: 'Sharing mode conflicts detected',

4305 33: 'Lock request conflicts detected',

4306 80: 'File already exists'

4307 }

4308

4309 ERRSRV = { 1: 'Non-specific error',

4310 2: 'Bad password',

4311 4: 'Access denied',

4312 5: 'Invalid tid. Please file a bug report.',

4313 6: 'Invalid network name',

4314 7: 'Invalid device',

4315 49: 'Print queue full',

4316 50: 'Print queue full',

4317 51: 'EOF on print queue dump',

4318 52: 'Invalid print file handle',

4319 64: 'Command not recognized. Please file a bug report.',

4320 65: 'Internal server error',

4321 67: 'Invalid path',

4322 69: 'Invalid access permissions',

4323 71: 'Invalid attribute mode',

4324 81: 'Server is paused',

4325 82: 'Not receiving messages',

4326 83: 'No room to buffer messages',

4327 87: 'Too many remote user names',

4328 88: 'Operation timeout',

4329 89: 'Out of resources',

4330 91: 'Invalid user handle. Please file a bug report.',

4331 250: 'Temporarily unable to support raw mode for transfer',

4332 251: 'Temporarily unable to support raw mode for transfer',

4333 252: 'Continue in MPX mode',

4334 65535: 'Unsupported function'

4335 }

4336

4337 ERRHRD = { 19: 'Media is write-protected',

4338 20: 'Unknown unit',

4339 21: 'Drive not ready',

4340 22: 'Unknown command',

4341 23: 'CRC error',

4342 24: 'Bad request',

4343 25: 'Seek error',

4344 26: 'Unknown media type',

4345 27: 'Sector not found',

4346 28: 'Printer out of paper',

4347 29: 'Write fault',

4348 30: 'Read fault',

4349 31: 'General failure',

4350 32: 'Open conflicts with an existing open',

4351 33: 'Invalid lock request',

4352 34: 'Wrong disk in drive',

4353 35: 'FCBs not available',

4354 36: 'Sharing buffer exceeded'

4355 }