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

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

## 2186 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 ↛ 3971, 3970 ↛ 39972 missed branches: 1) line 3970 didn't jump to line 3971, because the condition on line 3970 was never true, 2) line 3970 didn't jump to line 3997, because the condition on line 3970 was never false

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) 4144 ↛ 4142line 4144 didn't jump to line 4142, because the return on line 4142 wasn't executed

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) 4170 ↛ 4168line 4170 didn't jump to line 4168, because the return on line 4168 wasn't executed

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 }