Package pike :: Module smb2
[hide private]
[frames] | no frames]

Source Code for Module pike.smb2

   1  # 
   2  # Copyright (c) 2013, EMC Corporation 
   3  # All rights reserved. 
   4  # 
   5  # Redistribution and use in source and binary forms, with or without 
   6  # modification, are permitted provided that the following conditions are met: 
   7  # 
   8  # 1. Redistributions of source code must retain the above copyright notice, 
   9  # this list of conditions and the following disclaimer. 
  10  # 2. Redistributions in binary form must reproduce the above copyright notice, 
  11  # this list of conditions and the following disclaimer in the documentation 
  12  # and/or other materials provided with the distribution. 
  13  # 
  14  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
  15  # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  16  # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
  17  # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
  18  # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
  19  # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
  20  # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
  21  # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
  22  # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  23  # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  24  # POSSIBILITY OF SUCH DAMAGE. 
  25  # 
  26  # Module Name: 
  27  # 
  28  #        smb2.py 
  29  # 
  30  # Abstract: 
  31  # 
  32  #        SMB2 support 
  33  # 
  34  # Authors: Brian Koropoff (brian.koropoff@emc.com) 
  35  # 
  36   
  37  """ 
  38  SMB2 packet definitions 
  39   
  40  This module contains definitions of SMB2 packet frames and 
  41  associated constants and data types. 
  42   
  43  Packet field names are derived by taking the name from MS-SMB2 and 
  44  making it PEP-8 compliant. For example, FooBarBaz becomes foo_bar_baz. 
  45  This makes it simple to correlate the code with the spec while 
  46  maintaining a clear visual distinction between values and types. 
  47  """ 
  48   
  49  import array 
  50  import core 
  51  import nttime 
  52  import re 
  53  import ntstatus 
54 55 # Dialects constants 56 -class Dialect(core.ValueEnum):
57 DIALECT_SMB2_WILDCARD = 0x02FF 58 DIALECT_SMB2_002 = 0x0202 59 DIALECT_SMB2_1 = 0x0210 60 DIALECT_SMB3_0 = 0x0300 61 DIALECT_SMB3_0_2 = 0x0302 62 DIALECT_SMB3_1_1 = 0x0311
63 64 Dialect.import_items(globals())
65 66 # Flag constants 67 -class Flags(core.FlagEnum):
68 SMB2_FLAGS_NONE = 0x00000000 69 SMB2_FLAGS_SERVER_TO_REDIR = 0x00000001 70 SMB2_FLAGS_ASYNC_COMMAND = 0x00000002 71 SMB2_FLAGS_RELATED_OPERATIONS = 0x00000004 72 SMB2_FLAGS_SIGNED = 0x00000008 73 SMB2_FLAGS_DFS_OPERATIONS = 0x10000000 74 SMB2_FLAGS_REPLAY_OPERATION = 0x20000000
75 76 Flags.import_items(globals())
77 78 # Command constants 79 -class CommandId(core.ValueEnum):
80 SMB2_NEGOTIATE = 0x0000 81 SMB2_SESSION_SETUP = 0x0001 82 SMB2_LOGOFF = 0x0002 83 SMB2_TREE_CONNECT = 0x0003 84 SMB2_TREE_DISCONNECT = 0x0004 85 SMB2_CREATE = 0x0005 86 SMB2_CLOSE = 0x0006 87 SMB2_FLUSH = 0x0007 88 SMB2_READ = 0x0008 89 SMB2_WRITE = 0x0009 90 SMB2_LOCK = 0x000a 91 SMB2_IOCTL = 0x000b 92 SMB2_CANCEL = 0x000c 93 SMB2_ECHO = 0x000d 94 SMB2_QUERY_DIRECTORY = 0x000e 95 SMB2_CHANGE_NOTIFY = 0x000f 96 SMB2_QUERY_INFO = 0x0010 97 SMB2_SET_INFO = 0x0011 98 SMB2_OPLOCK_BREAK = 0x0012
99 100 CommandId.import_items(globals())
101 102 # Share Capabilities 103 -class ShareCaps(core.FlagEnum):
104 SMB2_SHARE_CAP_DFS = 0x00000008 105 SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY = 0x00000010 106 SMB2_SHARE_CAP_SCALEOUT = 0x00000020 107 SMB2_SHARE_CAP_CLUSTER = 0x00000040
108 109 ShareCaps.import_items(globals())
110 111 # Share flags 112 -class ShareFlags(core.FlagEnum):
113 SMB2_SHAREFLAG_MANUAL_CACHING = 0x00000000 114 SMB2_SHAREFLAG_AUTO_CACHING = 0x00000010 115 SMB2_SHAREFLAG_VDO_CACHING = 0x00000020 116 SMB2_SHAREFLAG_NO_CACHING = 0x00000030 117 SMB2_SHAREFLAG_DFS = 0x00000001 118 SMB2_SHAREFLAG_DFS_ROOT = 0x00000002 119 SMB2_SHAREFLAG_RESTRICT_EXCLUSIVE_OPENS = 0x00000100 120 SMB2_SHAREFLAG_FORCE_SHARED_DELETE = 0x00000200 121 SMB2_SHAREFLAG_ALLOW_NAMESPACE_CACHING = 0x00000400 122 SMB2_SHAREFLAG_ACCESS_BASED_DIRECTORY_ENUM = 0x00000800 123 SMB2_SHAREFLAG_FORCE_LEVELII_OPLOCK = 0x00001000 124 SMB2_SHAREFLAG_ENABLE_HASH_V1 = 0x00002000 125 SMB2_SHAREFLAG_ENABLE_HASH_V2 = 0x00004000 126 SMB2_SHAREFLAG_ENCRYPT_DATA = 0x00008000
127 128 ShareFlags.import_items(globals()) 129 130 # Misc 131 RELATED_FID = (2**64-1,2**64-1) 132 UNSOLICITED_MESSAGE_ID = (2**64-1)
133 134 -class Smb2(core.Frame):
135 _request_table = {} 136 _response_table = {} 137 _notification_table = {} 138 # Decorators to register class as request/response/notification payload 139 request = core.Register(_request_table, 'command_id', 'structure_size') 140 response = core.Register(_response_table, 'command_id', 'structure_size') 141 notification = core.Register(_notification_table, 'command_id', 'structure_size') 142
143 - def __init__(self, parent, context=None):
144 core.Frame.__init__(self, parent, context) 145 self.credit_charge = None 146 self.channel_sequence = 0 147 self.status = None 148 self.command = None 149 self.credit_request = None 150 self.credit_response = None 151 self.flags = SMB2_FLAGS_NONE 152 self.next_command = 0 153 self.message_id = None 154 self.async_id = None 155 self.session_id = 0 156 self.tree_id = 0 157 self._command = None 158 if parent is not None: 159 parent.append(self)
160
161 - def _children(self):
162 return [self._command] if self._command is not None else []
163
164 - def _encode(self, cur):
165 cur.encode_bytes('\xfeSMB') 166 cur.encode_uint16le(64) 167 cur.encode_uint16le(self.credit_charge) 168 if self.flags & SMB2_FLAGS_SERVER_TO_REDIR: 169 cur.encode_uint32le(self.status) 170 else: 171 cur.encode_uint16le(self.channel_sequence) 172 cur.encode_uint16le(0) 173 174 if self.command is None: 175 self.command = self._command.command_id 176 cur.encode_uint16le(self.command) 177 178 if self.flags & SMB2_FLAGS_SERVER_TO_REDIR: 179 cur.encode_uint16le(self.credit_response) 180 else: 181 cur.encode_uint16le(self.credit_request) 182 cur.encode_uint32le(self.flags) 183 # Set NextCommand to 0 for now 184 next_command_hole = cur.hole.encode_uint32le(0) 185 cur.encode_uint64le(self.message_id) 186 if self.flags & SMB2_FLAGS_ASYNC_COMMAND: 187 cur.encode_uint64le(self.async_id) 188 else: 189 cur.encode_uint32le(0xfeff) # default process id 190 cur.encode_uint32le(self.tree_id) 191 cur.encode_uint64le(self.session_id) 192 # Set Signature to 0 for now 193 signature_hole = cur.hole.encode_bytes([0]*16) 194 195 # Encode command body 196 self._command.encode(cur) 197 198 # If we are not last command in chain 199 if not self.is_last_child(): 200 # Add padding 201 cur.align(self.start, 8) 202 cur.trunc() 203 204 # Calculate next_command 205 self.next_command = cur - self.start 206 else: 207 self.next_command = 0 208 209 next_command_hole(self.next_command) 210 211 # Calculate and backpatch signature 212 if not hasattr(self, "signature"): 213 if self.flags & SMB2_FLAGS_SIGNED: 214 digest = self.context.signing_digest() 215 key = self.context.signing_key(self.session_id) 216 self.signature = digest(key, self.start[:cur])[:16] 217 else: 218 self.signature = array.array('B',[0]*16) 219 220 signature_hole(self.signature)
221
222 - def _decode(self, cur):
223 if (cur.decode_bytes(4).tostring() != '\xfeSMB'): 224 raise core.BadPacket() 225 if (cur.decode_uint16le() != 64): 226 raise core.BadPacket() 227 self.credit_charge = cur.decode_uint16le() 228 # Look ahead and decode flags first 229 self.flags = Flags((cur + 8).decode_uint32le()) 230 if self.flags & SMB2_FLAGS_SERVER_TO_REDIR: 231 self.status = ntstatus.Status(cur.decode_uint32le()) 232 self.channel_sequence = None 233 else: 234 self.channel_sequence = cur.decode_uint16le() 235 # Ignore reserved 236 cur.decode_uint16le() 237 self.status = None 238 self.command = CommandId(cur.decode_uint16le()) 239 if self.flags & SMB2_FLAGS_SERVER_TO_REDIR: 240 self.credit_response = cur.decode_uint16le() 241 self.credit_request = None 242 else: 243 self.credit_request = cur.decode_uint16le() 244 self.credit_response = None 245 # Skip over flags 246 cur += 4 247 self.next_command = cur.decode_uint32le() 248 self.message_id = cur.decode_uint64le() 249 if self.flags & SMB2_FLAGS_ASYNC_COMMAND: 250 self.async_id = cur.decode_uint64le() 251 self.tree_id = None 252 else: 253 # Ignore reserved 254 cur.decode_uint32le() 255 self.tree_id = cur.decode_uint32le() 256 self.async_id = None 257 self.session_id = cur.decode_uint64le() 258 self.signature = cur.decode_bytes(16) 259 260 # Peek ahead at structure_size 261 structure_size = (cur+0).decode_uint16le() 262 263 key = (self.command, structure_size) 264 265 if self.flags & SMB2_FLAGS_SERVER_TO_REDIR: 266 # Distinguish unsoliticed response, error response, normal response 267 if self.message_id == UNSOLICITED_MESSAGE_ID: 268 if key in Smb2._notification_table: 269 cls = Smb2._notification_table[key] 270 else: 271 raise core.BadPacket() 272 elif key in Smb2._response_table: 273 cls = Smb2._response_table[key] 274 if self.status not in cls.allowed_status and \ 275 structure_size == ErrorResponse.structure_size: 276 cls = ErrorResponse 277 else: 278 cls = ErrorResponse 279 else: 280 cls = Smb2._request_table[key] 281 282 # Figure out limit of command data 283 if self.next_command: 284 end = self.start + self.next_command 285 else: 286 end = cur.upperbound 287 288 self._command = cls(self) 289 with cur.bounded(cur, end): 290 self._command.decode(cur) 291 292 # Advance to next frame or end of data 293 cur.advanceto(end)
294
295 - def verify(self, digest, key):
296 if self.flags & SMB2_FLAGS_SIGNED: 297 message = self.start[:self.end] 298 # Zero out signature in message 299 message[12*4:12*4+16] = array.array('B',[0]*16) 300 # Calculate signature 301 signature = digest(key, message)[:16] 302 # Check that signatures match 303 if signature != self.signature: 304 raise core.BadPacket()
305
306 -class Command(core.Frame):
307 - def __init__(self, parent):
308 core.Frame.__init__(self, parent) 309 parent._command = self
310
311 - def _encode_pre(self, cur):
312 core.Frame._encode_pre(self, cur) 313 cur.encode_uint16le(self.structure_size)
314
315 - def _decode_pre(self, cur):
316 core.Frame._decode_pre(self, cur) 317 if cur.decode_uint16le() != self.structure_size: 318 raise core.BadPacket()
319 320 321 @Smb2.request
322 -class Request(Command):
323 pass
324
325 @Smb2.response 326 -class Response(Command):
327 allowed_status = [ntstatus.STATUS_SUCCESS]
328
329 @Smb2.notification 330 -class Notification(Command):
331 pass
332
333 -class ErrorResponse(Command):
334 structure_size = 9 335 336 _context_table = {} 337 error_context = core.Register(_context_table, 'error_id', 'parent_status') 338 special_statuses = [ntstatus.STATUS_STOPPED_ON_SYMLINK, 339 ntstatus.STATUS_BUFFER_TOO_SMALL] 340
341 - def __init__(self, parent):
342 super(ErrorResponse,self).__init__(parent) 343 parent._command = self 344 self.byte_count = None 345 self.error_context_count = 0 346 self.error_data = None 347 self._error_contexts = []
348
349 - def _children(self):
350 return self._error_contexts
351
352 - def append(self, e):
353 self._error_contexts.append(e)
354
355 - def _decode(self, cur):
356 self.error_context_count = cur.decode_uint8le() 357 # Ignore Reserved 358 cur.decode_uint8le() 359 self.byte_count = cur.decode_uint32le() 360 end = cur + self.byte_count 361 362 # SMB 3.1.1+ Error context handling 363 if self.error_context_count > 0: 364 for ix in xrange(self.error_context_count): 365 cur.align(self.parent.start, 8) 366 data_length = cur.decode_uint32le() 367 error_id = cur.decode_uint32le() 368 parent_status = self.parent.status 369 if parent_status not in self.special_statuses: 370 parent_status = None 371 key = (error_id, parent_status) 372 ctx = self._context_table[key] 373 with cur.bounded(cur, end): 374 ctx(self, data_length).decode(cur) 375 elif self.byte_count > 0: 376 # compatability shim for older dialects 377 error_id = 0 378 parent_status = self.parent.status 379 if parent_status not in self.special_statuses: 380 parent_status = None 381 key = (error_id, parent_status) 382 ctx = self._context_table[key] 383 with cur.bounded(cur, end): 384 self.error_data = ctx(self, self.byte_count) 385 self.error_data.decode(cur) 386 else: 387 # Ignore ErrorData 388 cur += self.byte_count if self.byte_count else 1
389
390 -class ErrorId(core.ValueEnum):
391 SMB2_ERROR_ID_DEFAULT = 0x0
392 393 ErrorId.import_items(globals())
394 395 @ErrorResponse.error_context 396 -class ErrorResponseContext(core.Frame):
397 - def __init__(self, parent, data_length):
398 core.Frame.__init__(self, parent) 399 self.data_length = data_length 400 self.error_data = None 401 if parent is not None: 402 parent.append(self)
403
404 -class ErrorResponseDefault(ErrorResponseContext):
405 error_id = SMB2_ERROR_ID_DEFAULT 406 parent_status = None
407 - def _decode(self, cur):
408 self.error_data = cur.decode_bytes(self.data_length)
409
410 -class ErrorResponseDefaultBufferSize(ErrorResponseContext):
411 error_id = SMB2_ERROR_ID_DEFAULT 412 parent_status = ntstatus.STATUS_BUFFER_TOO_SMALL
413 - def _decode(self, cur):
414 self.error_data = cur.decode_uint32le() 415 self.minimum_buffer_length = self.error_data
416
417 -class SymbolicLinkErrorResponse(ErrorResponseContext):
418 error_id = SMB2_ERROR_ID_DEFAULT 419 parent_status = ntstatus.STATUS_STOPPED_ON_SYMLINK
420 - def _decode(self, cur):
421 end = cur + self.data_length 422 self.sym_link_length = cur.decode_uint32le() 423 self.sym_link_error_tag = cur.decode_uint32le() 424 self.reparse_tag = cur.decode_uint32le() 425 if self.sym_link_error_tag != 0x4C4D5953: 426 raise core.BadPacket() 427 reparse_data = GetReparsePointResponse._reparse_tag_map[self.reparse_tag] 428 with cur.bounded(cur, end): 429 self.error_data = reparse_data(self) 430 self.error_data.decode(cur)
431
432 -class Cancel(Request):
433 command_id = SMB2_CANCEL 434 structure_size = 4 435
436 - def _encode(self, cur):
437 # Reserved 438 cur.encode_uint16le(0)
439
440 # Negotiate constants 441 -class SecurityMode(core.FlagEnum):
442 SMB2_NEGOTIATE_NONE = 0x0000 443 SMB2_NEGOTIATE_SIGNING_ENABLED = 0x0001 444 SMB2_NEGOTIATE_SIGNING_REQUIRED = 0x0002
445 446 SecurityMode.import_items(globals())
447 448 -class GlobalCaps(core.FlagEnum):
449 SMB2_GLOBAL_CAP_DFS = 0x00000001 450 SMB2_GLOBAL_CAP_LEASING = 0x00000002 451 SMB2_GLOBAL_CAP_LARGE_MTU = 0x00000004 452 SMB2_GLOBAL_CAP_MULTI_CHANNEL = 0x00000008 453 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES = 0x00000010 454 SMB2_GLOBAL_CAP_DIRECTORY_LEASING = 0x00000020 455 SMB2_GLOBAL_CAP_ENCRYPTION = 0x00000040
456 457 GlobalCaps.import_items(globals())
458 459 -class NegotiateContextType(core.ValueEnum):
460 SMB2_PREAUTH_INTEGRITY_CAPABILITIES = 0x0001 461 SMB2_ENCRYPTION_CAPABILITIES = 0x0002
462 463 NegotiateContextType.import_items(globals())
464 465 -class HashAlgorithms(core.ValueEnum):
466 SMB2_SHA_512 = 0x0001
467 468 HashAlgorithms.import_items(globals())
469 470 -class NegotiateRequest(Request):
471 command_id = SMB2_NEGOTIATE 472 structure_size = 36 473
474 - def __init__(self, parent):
475 Request.__init__(self, parent) 476 self.security_mode = 0 477 self.capabilities = 0 478 self.client_guid = [0]*16 479 self.dialects = [] 480 self.negotiate_contexts_count = None 481 self.negotiate_contexts_offset = None 482 self.negotiate_contexts_alignment_skew = 0 483 self.negotiate_contexts = []
484
485 - def _children(self):
486 return self.negotiate_contexts
487
488 - def _has_negotiate_contexts(self):
489 return (self.negotiate_contexts or 490 self.negotiate_contexts_offset is not None or 491 self.negotiate_contexts_count is not None)
492
493 - def _encode(self, cur):
494 cur.encode_uint16le(len(self.dialects)) 495 cur.encode_uint16le(self.security_mode) 496 cur.encode_uint16le(0) 497 cur.encode_uint32le(self.capabilities) 498 cur.encode_bytes(self.client_guid) 499 if self._has_negotiate_contexts(): 500 negotiate_contexts_offset_hole = cur.hole.encode_uint32le(0) 501 if self.negotiate_contexts_count is None: 502 self.negotiate_contexts_count = len(self.negotiate_contexts) 503 cur.encode_uint16le(self.negotiate_contexts_count) 504 cur.encode_uint16le(0) #reserved 505 else: 506 cur.encode_uint64le(0) 507 for dialect in self.dialects: 508 cur.encode_uint16le(dialect) 509 510 if self._has_negotiate_contexts(): 511 cur.align(self.parent.start, 8) 512 cur.seekto(cur + self.negotiate_contexts_alignment_skew) 513 if self.negotiate_contexts_offset is not None: 514 negotiate_contexts_offset_hole( 515 self.negotiate_contexts_offset) 516 else: 517 negotiate_contexts_offset_hole(cur - self.parent.start) 518 519 for ctx in self.negotiate_contexts: 520 cur.align(self.parent.start, 8) 521 cur.encode_uint16le(ctx.context_type) 522 data_length_hole = cur.hole.encode_uint16le(0) 523 cur.encode_uint32le(0) # reserved 524 data_start = cur.copy() 525 ctx.encode(cur) 526 if ctx.data_length is None: 527 ctx.data_length = cur - data_start 528 data_length_hole(ctx.data_length)
529
530 - def append(self, e):
531 self.negotiate_contexts.append(e)
532
533 -class NegotiateResponse(Response):
534 command_id = SMB2_NEGOTIATE 535 structure_size = 65 536 537 _context_table = {} 538 negotiate_context = core.Register(_context_table, 'context_type') 539
540 - def __init__(self, parent):
541 Response.__init__(self, parent) 542 self.security_mode = 0 543 self.dialect_revision = 0 544 self.server_guid = [0]*16 545 self.capabilities = 0 546 self.max_transact_size = 0 547 self.max_read_size = 0 548 self.max_write_size = 0 549 self.system_time = 0 550 self.server_start_time = 0 551 self.security_buffer = None 552 self.negotiate_contexts_count = None 553 self.negotiate_contexts_offset = None 554 self.negotiate_contexts = []
555
556 - def _children(self):
557 return self.negotiate_contexts
558
559 - def _decode(self, cur):
560 self.security_mode = SecurityMode(cur.decode_uint16le()) 561 self.dialect_revision = Dialect(cur.decode_uint16le()) 562 self.negotiate_contexts_count = cur.decode_uint16le() 563 self.server_guid = cur.decode_bytes(16) 564 self.capabilities = GlobalCaps(cur.decode_uint32le()) 565 self.max_transact_size = cur.decode_uint32le() 566 self.max_read_size = cur.decode_uint32le() 567 self.max_write_size = cur.decode_uint32le() 568 self.system_time = nttime.NtTime(cur.decode_uint64le()) 569 self.server_start_time = nttime.NtTime(cur.decode_uint64le()) 570 571 offset = cur.decode_uint16le() 572 length = cur.decode_uint16le() 573 574 self.negotiate_contexts_offset = cur.decode_uint32le() 575 576 # Advance to security buffer 577 cur.advanceto(self.parent.start + offset) 578 self.security_buffer = cur.decode_bytes(length) 579 if self.negotiate_contexts_count > 0: 580 cur.seekto(self.parent.start + self.negotiate_contexts_offset) 581 for ix in xrange(self.negotiate_contexts_count): 582 cur.align(self.parent.start, 8) 583 context_type = cur.decode_uint16le() 584 data_length = cur.decode_uint16le() 585 cur.decode_uint32le() # reserved 586 ctx = self._context_table[context_type] 587 ctx(self).decode(cur)
588
589 - def append(self, e):
590 self.negotiate_contexts.append(e)
591
592 -class NegotiateRequestContext(core.Frame):
593 - def __init__(self, parent):
594 core.Frame.__init__(self, parent) 595 if parent is not None: 596 parent.append(self) 597 self.data_length = None
598
599 @NegotiateResponse.negotiate_context 600 -class NegotiateResponseContext(core.Frame):
601 - def __init__(self, parent):
602 core.Frame.__init__(self, parent) 603 if parent is not None: 604 parent.append(self)
605
606 -class PreauthIntegrityCapabilities(core.Frame):
607 context_type = SMB2_PREAUTH_INTEGRITY_CAPABILITIES
608 - def __init__(self):
609 self.hash_algorithms = [] 610 self.hash_algorithms_count = None 611 self.salt = "" 612 self.salt_length = None
613 - def _encode(self, cur):
614 if self.hash_algorithms_count is None: 615 self.hash_algorithms_count = len(self.hash_algorithms) 616 cur.encode_uint16le(self.hash_algorithms_count) 617 if self.salt_length is None: 618 self.salt_length = len(self.salt) 619 cur.encode_uint16le(self.salt_length) 620 for h in self.hash_algorithms: 621 cur.encode_uint16le(h) 622 cur.encode_bytes(self.salt)
623 - def _decode(self, cur):
624 self.hash_algorithm_count = cur.decode_uint16le() 625 self.salt_length = cur.decode_uint16le() 626 for ix in xrange(self.hash_algorithm_count): 627 self.hash_algorithms.append(HashAlgorithms(cur.decode_uint16le())) 628 self.salt = cur.decode_bytes(self.salt_length)
629
630 -class PreauthIntegrityCapabilitiesRequest(NegotiateRequestContext, 631 PreauthIntegrityCapabilities):
632 - def __init__(self, parent):
635
636 -class PreauthIntegrityCapabilitiesResponse(NegotiateResponseContext, 637 PreauthIntegrityCapabilities):
638 - def __init__(self, parent):
641
642 # Session setup constants 643 -class SessionFlags(core.FlagEnum):
644 SMB2_SESSION_FLAG_NONE = 0x00 645 SMB2_SESSION_FLAG_BINDING = 0x01 646 SMB2_SESSION_FLAG_ENCRYPT_DATA = 0x04
647 648 SessionFlags.import_items(globals())
649 650 # SMB2_ECHO_REQUEST definition 651 -class EchoRequest(Request):
652 command_id = SMB2_ECHO 653 structure_size = 4 654
655 - def __init__(self, parent):
656 Request.__init__(self, parent) 657 self.reserved = 0
658
659 - def _encode(self, cur):
660 # Reserved 661 cur.encode_uint16le(self.reserved)
662
663 # SMB2_ECHO_RESPONSE definition 664 -class EchoResponse(Response):
665 # Expect response whenever SMB2_ECHO_REQUEST sent 666 command_id = SMB2_ECHO 667 structure_size = 4 668
669 - def __init__(self, parent):
670 Response.__init__(self, parent)
671
672 - def _decode(self, cur):
673 # Reserved 674 cur.decode_uint16le()
675
676 # SMB2_FLUSH_REQUEST definition 677 -class FlushRequest(Request):
678 command_id = SMB2_FLUSH 679 structure_size = 24 680
681 - def __init__(self, parent):
682 Request.__init__(self, parent) 683 self.reserved1 = 0 684 self.reserved2 = 0 685 self.file_id = None
686
687 - def _encode(self, cur):
688 # Reserved1 689 cur.encode_uint16le(self.reserved1) 690 # Reserved2 691 cur.encode_uint32le(self.reserved2) 692 cur.encode_uint64le(self.file_id[0]) 693 cur.encode_uint64le(self.file_id[1])
694
695 # SMB2_FLUSH_RESPONSE definition 696 -class FlushResponse(Response):
697 # Expect response whenever SMB2_FLUSH_REQUEST sent 698 command_id = SMB2_FLUSH 699 structure_size = 4 700
701 - def __init__(self, parent):
702 Response.__init__(self, parent)
703
704 - def _decode(self, cur):
705 self.reserved = cur.decode_uint16le()
706
707 -class SessionSetupRequest(Request):
708 command_id = SMB2_SESSION_SETUP 709 structure_size = 25 710
711 - def __init__(self, parent):
712 Request.__init__(self, parent) 713 self.flags = 0 714 self.security_mode = 0 715 self.capabilities = 0 716 self.channel = 0 # must not be used 717 self.previous_session_id = 0 718 self.security_buffer = None 719 self.security_buffer_offset = None 720 self.security_buffer_length = None
721
722 - def _encode(self, cur):
723 cur.encode_uint8le(self.flags) 724 cur.encode_uint8le(self.security_mode) 725 cur.encode_uint32le(self.capabilities) 726 cur.encode_uint32le(self.channel) 727 # Encode 0 for security buffer offset for now 728 sec_buf_ofs = cur.hole.encode_uint16le(0) 729 if self.security_buffer_length is None: 730 self.security_buffer_length = len(self.security_buffer) 731 cur.encode_uint16le(self.security_buffer_length) 732 cur.encode_uint64le(self.previous_session_id) 733 # Go back and set security buffer offset 734 if self.security_buffer_offset is None: 735 self.security_buffer_offset = cur - self.parent.start 736 sec_buf_ofs(self.security_buffer_offset) 737 cur.encode_bytes(self.security_buffer)
738
739 -class SessionSetupResponse(Response):
740 command_id = SMB2_SESSION_SETUP 741 allowed_status = [ntstatus.STATUS_SUCCESS, ntstatus.STATUS_MORE_PROCESSING_REQUIRED] 742 structure_size = 9 743
744 - def __init__(self, parent):
745 Response.__init__(self, parent) 746 self.session_flags = 0 747 self.security_buffer = None
748
749 - def _decode(self, cur):
750 self.session_flags = SessionFlags(cur.decode_uint16le()) 751 offset = cur.decode_uint16le() 752 length = cur.decode_uint16le() 753 754 # Advance to sec buffer 755 cur.advanceto(self.parent.start + offset) 756 self.security_buffer = cur.decode_bytes(length)
757
758 -class TreeConnectRequest(Request):
759 command_id = SMB2_TREE_CONNECT 760 structure_size = 9 761
762 - def __init__(self, parent):
763 Request.__init__(self, parent) 764 self.flags = 0 765 self.path_offset = None 766 self.path_length = None 767 self.path = None
768
769 - def _encode(self, cur):
770 # Reserved/Flags (SMB 3.1.1) 771 cur.encode_uint16le(self.flags) 772 # Path Offset 773 path_offset_hole = cur.hole.encode_uint16le(0) 774 # Path Length 775 path_lenght_hole = cur.hole.encode_uint16le(0) 776 777 if self.path_offset is None: 778 self.path_offset = cur - self.parent.start 779 path_offset_hole(self.path_offset) 780 781 path_start = cur.copy() 782 # Path 783 cur.encode_utf16le(self.path) 784 785 if self.path_length is None: 786 self.path_length = cur - path_start 787 path_lenght_hole(self.path_length)
788
789 790 -class TreeConnectResponse(Response):
791 command_id = SMB2_TREE_CONNECT 792 structure_size = 16 793
794 - def __init__(self, parent):
795 Response.__init__(self, parent) 796 self.share_type = 0 797 self.share_flags = 0 798 self.capabilities = 0 799 self.maximal_access = 0
800
801 - def _decode(self, cur):
802 self.share_type = cur.decode_uint8le() 803 # Ignore reserved 804 cur.decode_uint8le() 805 self.share_flags = cur.decode_uint32le() 806 self.capabilities = cur.decode_uint32le() 807 self.maximal_access = Access(cur.decode_uint32le())
808
809 -class TreeDisconnectRequest(Request):
810 command_id = SMB2_TREE_DISCONNECT 811 structure_size = 4 812
813 - def __init__(self, parent):
814 Request.__init__(self, parent)
815
816 - def _encode(self, cur):
817 # Reserved 818 cur.encode_uint16le(0)
819
820 -class TreeDisconnectResponse(Response):
821 command_id = SMB2_TREE_DISCONNECT 822 structure_size = 4 823
824 - def __init__(self, parent):
825 Response.__init__(self, parent)
826
827 - def _decode(self, cur):
828 # Ignore reserved 829 cur.decode_uint16le()
830
831 -class LogoffRequest(Request):
832 command_id = SMB2_LOGOFF 833 structure_size = 4 834
835 - def __init__(self, parent):
836 Request.__init__(self, parent)
837
838 - def _encode(self, cur):
839 # Reserved 840 cur.encode_uint16le(0)
841
842 -class LogoffResponse(Response):
843 command_id = SMB2_LOGOFF 844 structure_size = 4 845
846 - def __init__(self, parent):
847 Response.__init__(self, parent)
848
849 - def _decode(self, cur):
850 # Ignore reserved 851 cur.decode_uint16le()
852
853 # Oplock levels 854 -class OplockLevel(core.ValueEnum):
855 SMB2_OPLOCK_LEVEL_NONE = 0x00 856 SMB2_OPLOCK_LEVEL_II = 0x01 857 SMB2_OPLOCK_LEVEL_EXCLUSIVE = 0x08 858 SMB2_OPLOCK_LEVEL_BATCH = 0x09 859 SMB2_OPLOCK_LEVEL_LEASE = 0xFF
860 861 OplockLevel.import_items(globals())
862 863 # Share access 864 -class ShareAccess(core.FlagEnum):
865 FILE_SHARE_READ = 0x00000001 866 FILE_SHARE_WRITE = 0x00000002 867 FILE_SHARE_DELETE = 0x00000004
868 869 ShareAccess.import_items(globals())
870 871 # Create dispositions 872 -class CreateDisposition(core.ValueEnum):
873 FILE_SUPERSEDE = 0x00000000 874 FILE_OPEN = 0x00000001 875 FILE_CREATE = 0x00000002 876 FILE_OPEN_IF = 0x00000003 877 FILE_OVERWRITE = 0x00000004 878 FILE_OVERWRITE_IF = 0x00000005
879 880 CreateDisposition.import_items(globals())
881 882 # Create options 883 -class CreateOptions(core.FlagEnum):
884 FILE_DIRECTORY_FILE = 0x00000001 885 FILE_WRITE_THROUGH = 0x00000002 886 FILE_SEQUENTIAL_ONLY = 0x00000004 887 FILE_NO_INTERMEDIATE_BUFFERING = 0x00000008 888 FILE_SYNCHRONOUS_IO_ALERT = 0x00000010 889 FILE_SYNCRHONOUS_IO_NONALERT = 0x00000020 890 FILE_NON_DIRECTORY_FILE = 0x00000040 891 FILE_COMPLETE_IF_OPLOCKED = 0x00000100 892 FILE_NO_EA_KNOWLEDGE = 0x00000200 893 FILE_RANDOM_ACCESS = 0x00000800 894 FILE_DELETE_ON_CLOSE = 0x00001000 895 FILE_OPEN_BY_FILE_ID = 0x00002000 896 FILE_OPEN_FOR_BACKUP_INTENT = 0x00004000 897 FILE_NO_COMPRESSION = 0x00008000 898 FILE_RESERVE_OPFILTER = 0x00100000 899 FILE_OPEN_REPARSE_POINT = 0x00200000 900 FILE_OPEN_NO_RECALL = 0x00400000 901 FILE_OPEN_FOR_FREE_SPACE_QUERY = 0x00800000
902 903 CreateOptions.import_items(globals())
904 905 # Access masks 906 -class Access(core.FlagEnum):
907 FILE_READ_DATA = 0x00000001 908 FILE_WRITE_DATA = 0x00000002 909 FILE_APPEND_DATA = 0x00000004 910 FILE_READ_EA = 0x00000008 911 FILE_WRITE_EA = 0x00000010 912 FILE_EXECUTE = 0x00000020 913 FILE_READ_ATTRIBUTES = 0x00000080 914 FILE_WRITE_ATTRIBUTES = 0x00000100 915 DELETE = 0x00010000 916 READ_CONTROL = 0x00020000 917 WRITE_DAC = 0x00040000 918 WRITE_OWNER = 0x00080000 919 SYNCHRONIZE = 0x00100000 920 ACCESS_SYSTEM_SECURITY = 0x01000000 921 MAXIMUM_ALLOWED = 0x02000000 922 GENERIC_ALL = 0x10000000 923 GENERIC_EXECUTE = 0x20000000 924 GENERIC_WRITE = 0x40000000 925 GENERIC_READ = 0x80000000 926 FILE_LIST_DIRECTORY = 0x00000001 927 FILE_ADD_FILE = 0x00000002 928 FILE_ADD_SUBDIRECTORY = 0x00000004 929 FILE_TRAVERSE = 0x00000020 930 FILE_DELETE_CHILD = 0x00000040
931 932 Access.import_items(globals())
933 934 # File attributes 935 -class FileAttributes(core.FlagEnum):
936 FILE_ATTRIBUTE_READONLY = 0x00000001 937 FILE_ATTRIBUTE_HIDDEN = 0x00000002 938 FILE_ATTRIBUTE_SYSTEM = 0x00000004 939 FILE_ATTRIBUTE_DIRECTORY = 0x00000010 940 FILE_ATTRIBUTE_ARCHIVE = 0x00000020 941 FILE_ATTRIBUTE_DEVICE = 0x00000040 942 FILE_ATTRIBUTE_NORMAL = 0x00000080 943 FILE_ATTRIBUTE_TEMPORARY = 0x00000100 944 FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200 945 FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400 946 FILE_ATTRIBUTE_COMPRESSED = 0x00000800 947 FILE_ATTRIBUTE_OFFLINE = 0x00001000 948 FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000 949 FILE_ATTRIBUTE_ENCRYPTED = 0x00004000
950 951 FileAttributes.import_items(globals())
952 953 -class CreateRequest(Request):
954 command_id = SMB2_CREATE 955 structure_size = 57 956
957 - def __init__(self, parent):
958 Request.__init__(self, parent) 959 self.security_flags = 0 960 self.requested_oplock_level = SMB2_OPLOCK_LEVEL_NONE 961 self.impersonation_level = 0 962 self.smb_create_flags = 0 963 self.reserved = 0 964 self.desired_access = 0 965 self.file_attributes = 0 966 self.share_access = 0 967 self.create_disposition = 0 968 self.create_options = 0 969 self.name = None 970 self.name_offset = None 971 self.name_length = None 972 self.create_contexts_offset = 0 973 self.create_contexts_length = 0 974 self._create_contexts = []
975
976 - def _children(self):
977 return self._create_contexts
978
979 - def _encode(self, cur):
980 # SecurityFlags, must be 0 981 cur.encode_uint8le(self.security_flags) 982 cur.encode_uint8le(self.requested_oplock_level) 983 cur.encode_uint32le(self.impersonation_level) 984 # SmbCreateFlags, must be 0 985 cur.encode_uint64le(self.smb_create_flags) 986 # Reserved 987 cur.encode_uint64le(self.reserved) 988 cur.encode_uint32le(self.desired_access) 989 cur.encode_uint32le(self.file_attributes) 990 cur.encode_uint32le(self.share_access) 991 cur.encode_uint32le(self.create_disposition) 992 cur.encode_uint32le(self.create_options) 993 994 name_offset_hole = cur.hole.encode_uint16le(0) 995 name_length_hole = cur.hole.encode_uint16le(0) 996 997 create_contexts_offset_hole = cur.hole.encode_uint32le(0) 998 create_contexts_length_hole = cur.hole.encode_uint32le(0) 999 1000 cur.align(self.parent.start, 2) 1001 1002 buffer_start = cur.copy() 1003 1004 1005 if self.name_offset is None: 1006 self.name_offset = cur - self.parent.start 1007 name_offset_hole(self.name_offset) 1008 1009 name_start = cur.copy() 1010 cur.encode_utf16le(self.name) 1011 1012 if self.name_length is None: 1013 self.name_length = cur - name_start 1014 name_length_hole(self.name_length) 1015 1016 if len(self._create_contexts) != 0: 1017 # Next field of previous context to fill in 1018 next_hole = None 1019 # Pointer to start of previous context 1020 con_start = None 1021 cur.align(self.parent.start, 8) 1022 create_contexts_start = cur.copy() 1023 create_contexts_offset_hole(cur - self.parent.start) 1024 1025 for con in self._create_contexts: 1026 cur.align(self.parent.start, 8) 1027 if next_hole: 1028 next_hole(cur - con_start) 1029 con_start = cur.copy() 1030 next_hole = cur.hole.encode_uint32le(0) 1031 1032 name_offset_hole = cur.hole.encode_uint16le(0) 1033 cur.encode_uint16le(len(con.name)) 1034 # Reserved 1035 cur.encode_uint16le(0) 1036 data_offset_hole = cur.hole.encode_uint16le(0) 1037 data_length_hole = cur.hole.encode_uint32le(0) 1038 1039 # Name 1040 cur.align(self.parent.start, 8) 1041 name_offset_hole(cur - con_start) 1042 cur.encode_bytes(con.name) 1043 name_end = cur.copy() 1044 1045 # Data 1046 cur.align(self.parent.start, 8) 1047 data_start = cur.copy() 1048 con.encode(cur) 1049 data_length = cur - data_start 1050 if data_length: 1051 data_offset_hole(data_start - con_start) 1052 data_length_hole(cur - data_start) 1053 else: 1054 # Undo align 1055 cur.reverseto(name_end) 1056 1057 create_contexts_length_hole(cur - create_contexts_start) 1058 1059 if cur == buffer_start: 1060 # Buffer must be at least 1 byte 1061 cur.encode_uint8le(0)
1062
1063 - def append(self, e):
1064 self._create_contexts.append(e)
1065
1066 -class CreateResponse(Response):
1067 command_id = SMB2_CREATE 1068 structure_size = 89 1069 1070 _context_table = {} 1071 create_context = core.Register(_context_table, 'name') 1072
1073 - def __init__(self, parent):
1074 Response.__init__(self, parent) 1075 self.oplock_level = 0 1076 self.flags = 0 1077 self.create_action = 0 1078 self.creation_time = 0 1079 self.last_access_time = 0 1080 self.last_write_time = 0 1081 self.change_time = 0 1082 self.allocation_size = 0 1083 self.end_of_file = 0 1084 self.file_attributes = 0 1085 self.reserved2 = 0 1086 self.file_id = (0,0) 1087 self.create_contexts_offset = 0 1088 self.create_contexts_length = 0 1089 self._create_contexts = []
1090
1091 - def _children(self):
1092 return self._create_contexts
1093
1094 - def _decode(self, cur):
1095 self.oplock_level = OplockLevel(cur.decode_uint8le()) 1096 self.flags = cur.decode_uint8le() 1097 self.create_action = cur.decode_uint32le() 1098 self.creation_time = nttime.NtTime(cur.decode_uint64le()) 1099 self.last_access_time = nttime.NtTime(cur.decode_uint64le()) 1100 self.last_write_time = nttime.NtTime(cur.decode_uint64le()) 1101 self.change_time = nttime.NtTime(cur.decode_uint64le()) 1102 self.allocation_size = cur.decode_uint64le() 1103 self.end_of_file = cur.decode_uint64le() 1104 self.file_attributes = FileAttributes(cur.decode_uint32le()) 1105 # Ignore Reserved2 1106 self.reserved2 = cur.decode_uint32le() 1107 self.file_id = (cur.decode_uint64le(),cur.decode_uint64le()) 1108 self.create_contexts_offset = cur.decode_uint32le() 1109 self.create_contexts_length = cur.decode_uint32le() 1110 1111 if self.create_contexts_length > 0: 1112 create_contexts_start = self.parent.start + self.create_contexts_offset 1113 create_contexts_end = create_contexts_start + self.create_contexts_length 1114 next_cur = create_contexts_start 1115 1116 with cur.bounded(create_contexts_start, create_contexts_end): 1117 while next_cur: 1118 cur.seekto(next_cur) 1119 con_start = cur.copy() 1120 next_offset = cur.decode_uint32le() 1121 name_offset = cur.decode_uint16le() 1122 name_length = cur.decode_uint16le() 1123 # Ignore Reserved 1124 cur.decode_uint16le() 1125 data_offset = cur.decode_uint16le() 1126 data_length = cur.decode_uint32le() 1127 1128 name = (con_start + name_offset).decode_bytes(name_length).tostring() 1129 1130 cur.seekto(con_start + data_offset) 1131 with cur.bounded(cur, cur + data_length): 1132 self._context_table[name](self).decode(cur) 1133 1134 next_cur = con_start + next_offset if next_offset != 0 else None 1135 1136 # Make sure we end up at the end regardless of how much we jumped around 1137 cur.advanceto(create_contexts_end)
1138
1139 - def append(self, e):
1140 self._create_contexts.append(e)
1141
1142 -class CreateRequestContext(core.Frame):
1143 - def __init__(self, parent):
1144 core.Frame.__init__(self, parent) 1145 if parent is not None: 1146 parent.append(self)
1147
1148 @CreateResponse.create_context 1149 -class CreateResponseContext(core.Frame):
1150 - def __init__(self, parent):
1151 core.Frame.__init__(self, parent) 1152 if parent is not None: 1153 parent.append(self)
1154
1155 -class MaximalAccessRequest(CreateRequestContext):
1156 name = 'MxAc' 1157
1158 - def __init__(self, parent):
1159 CreateRequestContext.__init__(self, parent) 1160 self.timestamp = None
1161
1162 - def _encode(self, cur):
1163 if self.timestamp is not None: 1164 cur.encode_uint64le(self.timestamp)
1165
1166 -class MaximalAccessResponse(CreateResponseContext):
1167 name = 'MxAc' 1168
1169 - def __init__(self, parent):
1170 CreateResponseContext.__init__(self, parent) 1171 self.query_status = 0 1172 self.maximal_access = 0
1173
1174 - def _decode(self, cur):
1175 self.query_status = ntstatus.Status(cur.decode_uint32le()) 1176 self.maximal_access = Access(cur.decode_uint32le())
1177
1178 -class AllocationSizeRequest(CreateRequestContext):
1179 name = 'AlSi' 1180
1181 - def __init__(self, parent):
1182 CreateRequestContext.__init__(self, parent) 1183 self.allocation_size = 0
1184
1185 - def _encode(self, cur):
1186 cur.encode_uint64le(self.allocation_size)
1187
1188 1189 -class ExtendedAttributeRequest(CreateRequestContext):
1190 name = 'ExtA' 1191
1192 - def __init__(self,parent):
1193 CreateRequestContext.__init__(self,parent) 1194 self.next_entry_offset = 0 1195 self.flags = 0x00000000 1196 self.ea_name_length = 0 1197 self.ea_value_length = 0 1198 self.ea_name = None 1199 self.ea_value = None
1200
1201 - def _encode(self,cur):
1202 cur.encode_uint32le(self.next_entry_offset) 1203 cur.encode_uint8le(self.flags) 1204 if self.ea_name is not None: 1205 self.ea_name = array.array('B',self.ea_name) 1206 self.ea_name.append(00) 1207 self.ea_value = array.array('B',self.ea_value) 1208 cur.encode_uint8le(self.ea_name_length) 1209 cur.encode_uint16le(self.ea_value_length) 1210 cur.encode_bytes(self.ea_name) 1211 cur.encode_bytes(self.ea_value)
1212
1213 -class LeaseState(core.FlagEnum):
1214 SMB2_LEASE_NONE = 0x00 1215 SMB2_LEASE_READ_CACHING = 0x01 1216 SMB2_LEASE_HANDLE_CACHING = 0x02 1217 SMB2_LEASE_WRITE_CACHING = 0x04
1218 1219 LeaseState.import_items(globals())
1220 1221 -class LeaseFlags(core.FlagEnum):
1222 SMB2_LEASE_FLAG_NONE = 0x00 1223 SMB2_LEASE_FLAG_BREAK_IN_PROGRESS = 0x02
1224 1225 LeaseFlags.import_items(globals())
1226 1227 -class AceType(core.ValueEnum):
1228 ACCESS_ALLOWED_ACE_TYPE = 0x00 1229 ACCESS_DENIED_ACE_TYPE = 0x01 1230 SYSTEM_AUDIT_ACE_TYPE = 0x02 1231 SYSTEM_ALARM_ACE_TYPE = 0x03 1232 ACCESS_ALLOWED_COMPOUND_ACE_TYPE = 0x04 1233 ACCESS_ALLOWED_OBJECT_ACE_TYPE = 0x05 1234 ACCESS_DENIED_OBJECT_ACE_TYPE = 0x06 1235 SYSTEM_AUDIT_OBJECT_ACE_TYPE = 0x07 1236 SYSTEM_ALARM_OBJECT_ACE_TYPE = 0x08 1237 ACCESS_ALLOWED_CALLBACK_ACE_TYPE = 0x09 1238 ACCESS_DENIED_CALLBACK_ACE_TYPE = 0x0A 1239 ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE = 0x0B 1240 ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE = 0x0C 1241 SYSTEM_AUDIT_CALLBACK_ACE_TYPE = 0x0D 1242 SYSTEM_ALARM_CALLBACK_ACE_TYPE = 0x0E 1243 SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE = 0x0F 1244 SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE = 0x10 1245 SYSTEM_MANDATORY_LABEL_ACE_TYPE = 0x11 1246 SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE = 0x12 1247 SYSTEM_SCOPED_POLICY_ID_ACE_TYPE = 0x13
1248 1249 AceType.import_items(globals())
1250 1251 -class AceFlags(core.FlagEnum):
1252 OBJECT_INHERIT_ACE = 0x01 1253 CONTAINER_INHERIT_ACE = 0x02 1254 NO_PROPAGATE_INHERIT_ACE = 0x04 1255 INHERIT_ONLY_ACE = 0x08 1256 INHERITED_ACE = 0x10 1257 SUCCESSFUL_ACCESS_ACE_FLAG = 0x40 1258 FAILED_ACCESS_ACE_FLAG = 0x80
1259 1260 AceFlags.import_items(globals())
1261 1262 -class AclRevision(core.ValueEnum):
1263 ACL_REVISION = 0x02 1264 ACL_REVISION_DS = 0x04
1265 1266 AclRevision.import_items(globals())
1267 1268 -class SecurityDescriptorRequest(CreateRequestContext):
1269 name = 'SecD' 1270
1271 - def __init__(self,parent):
1272 CreateRequestContext.__init__(self,parent) 1273 self.revision = 1 1274 self.sbz1 = 0 1275 self.control = None 1276 self.owner_sid = None 1277 self.group_sid = None 1278 self.sacl = None 1279 self.dacl = None 1280 self.sacl_aces = None 1281 self.dacl_aces = None
1282
1283 - def _encode(self,cur):
1284 self.offset_owner,self.offset_group,self.offset_sacl,self.offset_dacl=\ 1285 self._get_offset(owner_sid = self.owner_sid ,group_sid=\ 1286 self.group_sid ,sacl = self.sacl_aces ,dacl = self.dacl_aces) 1287 cur.encode_uint8le(self.revision) 1288 cur.encode_uint8le(self.sbz1) 1289 cur.encode_uint16le(self.control) 1290 cur.encode_uint32le(self.offset_owner) 1291 cur.encode_uint32le(self.offset_group) 1292 cur.encode_uint32le(self.offset_sacl) 1293 cur.encode_uint32le(self.offset_dacl) 1294 1295 if self.offset_owner != 0: 1296 id_auth, sub_auth = self._get_sid(self.owner_sid) 1297 self._encode_sid(cur,id_auth,sub_auth) 1298 1299 if self.offset_group != 0: 1300 id_auth, sub_auth = self._get_sid(self.group_sid) 1301 self._encode_sid(cur,id_auth,sub_auth) 1302 1303 if self.offset_sacl!= 0: 1304 # Acl Revision 1305 cur.encode_uint8le(self.sacl) 1306 # sbz1 1307 cur.encode_uint8le(0) 1308 # Acl Size 1309 sid_size,ace_size,acl_size = self._get_size(acl=self.sacl_aces) 1310 cur.encode_uint16le(acl_size) 1311 # Ace Count 1312 cur.encode_uint16le(len(self.sacl_aces)) 1313 # sbz2 1314 cur.encode_uint16le(0) 1315 for ace in self.sacl_aces: 1316 # Ace Type 1317 cur.encode_uint8le(ace[0]) 1318 # Ace flags 1319 cur.encode_uint8le(ace[1]) 1320 # Ace Size 1321 sid_size,ace_size,acl_size = self._get_size(ace_val=ace) 1322 cur.encode_uint16le(ace_size) 1323 # Ace Mask 1324 cur.encode_uint32le(ace[2]) 1325 id_auth, sub_auth = self._get_sid(ace[3]) 1326 self._encode_sid(cur,id_auth,sub_auth) 1327 if self.offset_dacl!= 0: 1328 # Acl Revision 1329 cur.encode_uint8le(self.dacl) 1330 # sbz1 1331 cur.encode_uint8le(0) 1332 # Acl Size 1333 sid_size,ace_size,acl_size = self._get_size(acl=self.dacl_aces) 1334 cur.encode_uint16le(acl_size) 1335 # Ace Count 1336 cur.encode_uint16le(len(self.dacl_aces)) 1337 # sbz2 1338 cur.encode_uint16le(0) 1339 for ace in self.dacl_aces: 1340 # Ace Type 1341 cur.encode_uint8le(ace[0]) 1342 # Ace flags 1343 cur.encode_uint8le(ace[1]) 1344 # Ace Size 1345 sid_size,ace_size,acl_size = self._get_size(ace_val=ace) 1346 cur.encode_uint16le(ace_size) 1347 # Ace Mask 1348 cur.encode_uint32le(ace[2]) 1349 id_auth, sub_auth = self._get_sid(ace[3]) 1350 self._encode_sid(cur,id_auth,sub_auth)
1351
1352 - def _encode_sid(self,cur,id_auth,sub_auth):
1353 sub_auth = [int(i) for i in sub_auth] 1354 # Revision 1355 cur.encode_uint8le(0x01) 1356 # Sub Authrty Count 1357 cur.encode_uint8le(len(sub_auth)) 1358 # Identifier Authority 1359 tmp_id_auth = array.array('B',[0x00,0x00,0x00,0x00,0x00]) 1360 tmp_id_auth.append(int(id_auth)) 1361 for tmp in tmp_id_auth : 1362 cur.encode_uint8le(tmp) 1363 # Sub Authority 1364 for tmp_sub_auth in sub_auth: 1365 cur.encode_uint32le(tmp_sub_auth)
1366
1367 - def _get_sid(self,sid):
1368 pat = r'S-1-(\d)-(.*)' 1369 match = re.search(pat,sid) 1370 id_auth= match.group(1) 1371 sub_auth = (match.group(2)).split('-') 1372 return id_auth,sub_auth
1373
1374 - def _get_size(self,sid = None,ace_val = None,acl = None):
1375 sid_size=0 1376 ace_size=0 1377 acl_size=0 1378 # All Sizes are in Bytes 1379 sbz1 = 1 1380 sbz2 = 2 1381 revision_size = 1 1382 ace_type_size = 1 1383 ace_flags_size = 1 1384 ace_size_param = 2 1385 ace_mask_size = 4 1386 acl_revision_size = 1 1387 acl_size_param = 2 1388 ace_count_size = 2 1389 sub_auth_count_size = 1 1390 identifier_auth_size = 6 1391 sub_auth_size = 0 1392 if sid != None: 1393 id_auth, sub_auth = self._get_sid(sid) 1394 sub_auth_size+= len(sub_auth) * 4 1395 sid_size =revision_size + sub_auth_count_size+\ 1396 identifier_auth_size + sub_auth_size 1397 elif ace_val != None: 1398 sub_auth_size = 0 1399 id_auth, sub_auth = self._get_sid(ace_val[3]) 1400 sub_auth_size+= len(sub_auth) * 4 1401 sid_size = revision_size + sub_auth_count_size+\ 1402 identifier_auth_size + sub_auth_size 1403 ace_size = ace_type_size + ace_flags_size +\ 1404 ace_size_param + ace_mask_size + sid_size 1405 elif acl != None: 1406 tmp_acl_size=0 1407 for aces in acl: 1408 sub_auth_size = 0 1409 id_auth, sub_auth = self._get_sid(aces[3]) 1410 sub_auth_size+= len(sub_auth) * 4 1411 sid_size = revision_size + sub_auth_count_size +\ 1412 identifier_auth_size + sub_auth_size 1413 ace_size = ace_type_size + ace_flags_size + \ 1414 ace_size_param + ace_mask_size + sid_size 1415 tmp_acl_size += ace_size 1416 acl_size = acl_revision_size + sbz1 + acl_size_param + \ 1417 ace_count_size + sbz2 + tmp_acl_size 1418 return sid_size,ace_size,acl_size
1419
1420 - def _get_offset(self,owner_sid=None,group_sid=None,sacl=None,dacl=None):
1421 default_offset = 20 1422 owner_sid_size = self._get_size(sid = owner_sid) 1423 off_owner = 0 if owner_sid_size[0] == 0 else default_offset 1424 group_sid_size = self._get_size(sid = group_sid) 1425 off_group = 0 if group_sid_size[0] == 0 else default_offset +\ 1426 owner_sid_size[0] 1427 sacl_size = self._get_size(acl = sacl) 1428 off_sacl = 0 if sacl_size[2] == 0 else default_offset +\ 1429 owner_sid_size[0] + group_sid_size[0] 1430 dacl_size = self._get_size(acl = dacl) 1431 off_dacl = 0 if dacl_size[2] == 0 else default_offset +\ 1432 owner_sid_size[0] + group_sid_size[0] + sacl_size[2] 1433 return off_owner,off_group,off_sacl,off_dacl
1434
1435 -class LeaseRequest(CreateRequestContext):
1436 name = 'RqLs' 1437 # This class handles V2 requests as well. Set 1438 # the lease_flags field to a non-None value 1439 # to enable the extended fields
1440 - def __init__(self, parent):
1441 CreateRequestContext.__init__(self, parent) 1442 self.lease_key = array.array('B', [0]*16) 1443 self.lease_state = 0 1444 # V2 fields 1445 self.lease_flags = None 1446 self.parent_lease_key = None 1447 self.epoch = None
1448
1449 - def _encode(self, cur):
1450 cur.encode_bytes(self.lease_key) 1451 cur.encode_uint32le(self.lease_state) 1452 if (self.lease_flags is not None): 1453 # V2 variant 1454 cur.encode_uint32le(self.lease_flags) 1455 # LeaseDuration is reserved 1456 cur.encode_uint64le(0) 1457 cur.encode_bytes(self.parent_lease_key) 1458 cur.encode_uint16le(self.epoch) 1459 # Reserved 1460 cur.encode_uint16le(0) 1461 else: 1462 # Regular variant 1463 # LeaseFlags is reserved 1464 cur.encode_uint32le(0) 1465 # LeaseDuration is reserved 1466 cur.encode_uint64le(0)
1467
1468 -class LeaseResponse(CreateResponseContext):
1469 name = 'RqLs' 1470 v1_size = 32 1471 v2_size = 52 1472 # This class handles V2 responses as well. 1473 # The extended fields will be set to None 1474 # if the response was not V2 1475
1476 - def __init__(self, parent):
1477 CreateResponseContext.__init__(self, parent) 1478 self.lease_key = array.array('B', [0]*16) 1479 self.lease_state = 0 1480 self.lease_flags = 0 1481 self.parent_lease_key = None 1482 self.epoch = None
1483
1484 - def _decode(self, cur):
1485 size = cur.upperbound - cur 1486 if size != self.v1_size and size != self.v2_size: 1487 raise core.BadPacket() 1488 self.lease_key = cur.decode_bytes(16) 1489 self.lease_state = LeaseState(cur.decode_uint32le()) 1490 self.lease_flags = LeaseFlags(cur.decode_uint32le()) 1491 # LeaseDuration is reserved 1492 cur.decode_uint64le() 1493 1494 if size == self.v2_size: 1495 self.parent_lease_key = cur.decode_bytes(16) 1496 self.epoch = cur.decode_uint16le() 1497 # Ignore Reserved 1498 cur.decode_uint16le() 1499 else: 1500 self.parent_lease_key = None 1501 self.epoch = None
1502
1503 -class DurableFlags(core.FlagEnum):
1504 SMB2_DHANDLE_FLAG_PERSISTENT = 0x02
1505 1506 DurableFlags.import_items(globals())
1507 1508 -class DurableHandleRequest(CreateRequestContext):
1509 name = 'DHnQ' 1510
1511 - def __init__(self, parent):
1512 CreateRequestContext.__init__(self, parent)
1513
1514 - def _encode(self, cur):
1515 # Reserved 1516 cur.encode_uint64le(0) 1517 cur.encode_uint64le(0)
1518
1519 -class DurableHandleResponse(CreateResponseContext):
1520 name = 'DHnQ' 1521
1522 - def __init__(self, parent):
1523 CreateResponseContext.__init__(self, parent)
1524
1525 - def _decode(self, cur):
1526 # Ignore reserved 1527 cur.decode_uint64le()
1528
1529 -class DurableHandleReconnectRequest(CreateRequestContext):
1530 name = 'DHnC' 1531
1532 - def __init__(self, parent):
1533 CreateRequestContext.__init__(self, parent) 1534 self.file_id = None
1535
1536 - def _encode(self, cur):
1537 cur.encode_uint64le(self.file_id[0]) 1538 cur.encode_uint64le(self.file_id[1])
1539
1540 -class DurableHandleV2Request(CreateRequestContext):
1541 name = 'DH2Q' 1542
1543 - def __init__(self, parent):
1544 CreateRequestContext.__init__(self, parent) 1545 self.timeout = 0 1546 self.flags = 0 1547 self.create_guid = None
1548
1549 - def _encode(self, cur):
1550 cur.encode_uint32le(self.timeout) 1551 cur.encode_uint32le(self.flags) 1552 # Reserved 1553 cur.encode_uint64le(0) 1554 cur.encode_bytes(self.create_guid)
1555
1556 -class DurableHandleV2Response(CreateResponseContext):
1557 name = 'DH2Q' 1558
1559 - def __init__(self, parent):
1560 CreateResponseContext.__init__(self, parent) 1561 self.timeout = 0 1562 self.flags = 0
1563
1564 - def _decode(self, cur):
1565 self.timeout = cur.decode_uint32le() 1566 self.flags = DurableFlags(cur.decode_uint32le())
1567
1568 -class DurableHandleReconnectV2Request(CreateRequestContext):
1569 name = 'DH2C' 1570
1571 - def __init__(self, parent):
1572 CreateRequestContext.__init__(self, parent) 1573 self.fileid = None 1574 self.create_guid = None 1575 self.flags = 0
1576
1577 - def _encode(self, cur):
1578 cur.encode_uint64le(self.file_id[0]) 1579 cur.encode_uint64le(self.file_id[1]) 1580 cur.encode_bytes(self.create_guid) 1581 cur.encode_uint32le(self.flags)
1582
1583 -class AppInstanceIdRequest(CreateRequestContext):
1584 name = '\x45\xBC\xA6\x6A\xEF\xA7\xF7\x4A\x90\x08\xFA\x46\x2E\x14\x4D\x74' 1585
1586 - def __init__(self, parent):
1587 CreateRequestContext.__init__(self, parent) 1588 self.structure_size = 20 1589 self.app_instance_id = array.array('B', [0]*16)
1590
1591 - def _encode(self, cur):
1592 cur.encode_uint16le(self.structure_size) 1593 # Reserved 1594 cur.encode_uint16le(0) 1595 cur.encode_bytes(self.app_instance_id)
1596
1597 -class QueryOnDiskIDRequest(CreateRequestContext):
1598 name = 'QFid' 1599
1600 - def __init__(self, parent):
1601 CreateRequestContext.__init__(self, parent)
1602
1603 - def _encode(self, cur):
1604 pass # client sends no data to server
1605
1606 -class QueryOnDiskIDResponse(CreateResponseContext):
1607 name = 'QFid' 1608
1609 - def __init__(self, parent):
1610 CreateResponseContext.__init__(self, parent) 1611 self.file_id = array.array('B', [0]*32)
1612
1613 - def _decode(self, cur):
1614 self.file_id = cur.decode_bytes(32)
1615
1616 -class TimewarpTokenRequest(CreateRequestContext):
1617 name = 'TWrp' 1618
1619 - def __init__(self, parent):
1620 super(TimewarpTokenRequest, self).__init__(parent) 1621 self.timestamp = 0
1622
1623 - def _encode(self, cur):
1624 cur.encode_uint64le(self.timestamp)
1625
1626 -class CloseRequest(Request):
1627 command_id = SMB2_CLOSE 1628 structure_size = 24 1629
1630 - def __init__(self, parent):
1631 Request.__init__(self, parent) 1632 self.flags = 0 1633 self.file_id = None
1634
1635 - def _encode(self, cur):
1636 cur.encode_uint16le(self.flags) 1637 # Reserved 1638 cur.encode_uint32le(0) 1639 cur.encode_uint64le(self.file_id[0]) 1640 cur.encode_uint64le(self.file_id[1])
1641
1642 -class CloseFlags(core.FlagEnum):
1643 SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB = 0x0001
1644 1645 CloseFlags.import_items(globals())
1646 1647 -class CloseResponse(Response):
1648 command_id = SMB2_CLOSE 1649 structure_size = 60 1650
1651 - def __init__(self, parent):
1652 Response.__init__(self, parent) 1653 self.flags = 0 1654 self.creation_time = 0 1655 self.last_access_time = 0 1656 self.last_write_time = 0 1657 self.change_time = 0 1658 self.allocation_size = 0 1659 self.end_of_file = 0 1660 self.file_attributes = 0
1661
1662 - def _decode(self, cur):
1663 self.flags = CloseFlags(cur.decode_uint16le()) 1664 self.reserved = cur.decode_uint32le() 1665 self.creation_time = nttime.NtTime(cur.decode_uint64le()) 1666 self.last_access_time = nttime.NtTime(cur.decode_uint64le()) 1667 self.last_write_time = nttime.NtTime(cur.decode_uint64le()) 1668 self.change_time = nttime.NtTime(cur.decode_uint64le()) 1669 self.allocation_size = cur.decode_uint64le() 1670 self.end_of_file = cur.decode_uint64le() 1671 self.file_attributes = FileAttributes(cur.decode_uint32le())
1672
1673 -class FileInformationClass(core.ValueEnum):
1674 FILE_DIRECTORY_INFORMATION = 1 1675 FILE_FULL_DIRECTORY_INFORMATION = 2 1676 FILE_BASIC_INFORMATION = 4 1677 FILE_STANDARD_INFORMATION = 5 1678 FILE_INTERNAL_INFORMATION = 6 1679 FILE_EA_INFORMATION = 7 1680 FILE_ACCESS_INFORMATION = 8 1681 FILE_NAME_INFORMATION = 9 1682 FILE_RENAME_INFORMATION = 10 1683 FILE_NAMES_INFORMATION = 12 1684 FILE_DISPOSITION_INFORMATION = 13 1685 FILE_POSITION_INFORMATION = 14 1686 FILE_MODE_INFORMATION = 16 1687 FILE_ALIGNMENT_INFORMATION = 17 1688 FILE_ALL_INFORMATION = 18 1689 FILE_ALLOCATION_INFORMATION = 19 1690 FILE_END_OF_FILE_INFORMATION = 20 1691 FILE_STREAM_INFORMATION = 22 1692 FILE_COMPRESSION_INFORMATION = 28 1693 FILE_NETWORK_OPEN_INFORMATION = 34 1694 FILE_ATTRIBUTE_TAG_INFORMATION = 35 1695 FILE_ID_BOTH_DIR_INFORMATION = 37 1696 FILE_ID_FULL_DIR_INFORMATION = 38 1697 FILE_VALID_DATA_LENGTH_INFORMATION = 39
1698 1699 FileInformationClass.import_items(globals())
1700 1701 1702 -class FileSystemInformationClass(core.ValueEnum):
1703 FILE_FS_VOLUME_INFORMATION = 1 1704 FILE_FS_SIZE_INFORMATION = 3 1705 FILE_FS_DEVICE_INFORMATION = 4 1706 FILE_FS_ATTRIBUTE_INFORMATION = 5 1707 FILE_FS_CONTROL_INFORMATION = 6 1708 FILE_FS_FULL_SIZE_INFORMATION = 7 1709 FILE_FS_OBJECTID_INFORMATION = 8 1710 FILE_FS_SECTOR_SIZE_INFORMATION = 11
1711 1712 FileSystemInformationClass.import_items(globals())
1713 1714 1715 -class QueryDirectoryRequest(Request):
1716 command_id = SMB2_QUERY_DIRECTORY 1717 structure_size = 33 1718
1719 - def __init__(self, parent):
1720 Request.__init__(self, parent) 1721 self.file_information_class = 0 1722 self.flags = 0 1723 self.file_index = 0 1724 self.file_id = None 1725 self.file_name = None 1726 self.output_buffer_length = 0
1727
1728 - def _encode(self, cur):
1729 cur.encode_uint8le(self.file_information_class) 1730 cur.encode_uint8le(self.flags) 1731 cur.encode_uint32le(self.file_index) 1732 cur.encode_uint64le(self.file_id[0]) 1733 cur.encode_uint64le(self.file_id[1]) 1734 1735 file_name_offset_hole = cur.hole.encode_uint16le(0) 1736 file_name_length_hole = cur.hole.encode_uint16le(0) 1737 1738 cur.encode_uint32le(self.output_buffer_length) 1739 1740 file_name_start = cur.copy() 1741 file_name_offset_hole(file_name_start - self.parent.start) 1742 cur.encode_utf16le(self.file_name) 1743 file_name_length_hole(cur - file_name_start)
1744
1745 -class QueryDirectoryResponse(Response):
1746 command_id = SMB2_QUERY_DIRECTORY 1747 structure_size = 9 1748 1749 _file_info_map = {} 1750 file_information = core.Register(_file_info_map, 'file_information_class') 1751
1752 - def __init__(self, parent):
1753 Response.__init__(self, parent) 1754 self._file_information_class = None 1755 1756 # Try to figure out file information class by looking up 1757 # associated request in context 1758 context = self.context 1759 1760 if context: 1761 request = context.get_request(parent.message_id) 1762 1763 if request and request.children: 1764 self._file_information_class = request[0].file_information_class 1765 1766 self._entries = []
1767
1768 - def _children(self):
1769 return self._entries
1770
1771 - def append(self, e):
1772 self._entries.append(e)
1773
1774 - def _decode(self, cur):
1775 output_buffer_offset = cur.decode_uint16le() 1776 output_buffer_length = cur.decode_uint32le() 1777 1778 cur.advanceto(self.parent.start + output_buffer_offset) 1779 1780 end = cur + output_buffer_length 1781 1782 if self._file_information_class is not None: 1783 cls = self._file_info_map[self._file_information_class] 1784 1785 with cur.bounded(cur, end): 1786 while cur < end: 1787 cls(self).decode(cur) 1788 else: 1789 Information(self, end).decode(cur)
1790
1791 -class InfoType(core.ValueEnum):
1792 SMB2_0_INFO_FILE = 0x01 1793 SMB2_0_INFO_FILESYSTEM = 0x02 1794 SMB2_0_INFO_SECURITY = 0x03 1795 SMB2_0_INFO_QUOTA = 0x04
1796 1797 InfoType.import_items(globals())
1798 1799 -class SecurityInformation(core.FlagEnum):
1800 OWNER_SECURITY_INFORMATION = 0x00000001 1801 GROUP_SECURITY_INFORMATION = 0x00000002 1802 DACL_SECURITY_INFORMATION = 0x00000004 1803 SACL_SECURITY_INFORMATION = 0x00000008
1804 1805 SecurityInformation.import_items(globals())
1806 1807 -class ScanFlags(core.FlagEnum):
1808 SL_RESTART_SCAN = 0x00000001 1809 SL_RETURN_SINGLE_ENTRY = 0x00000002 1810 SL_INDEX_SPECIFIED = 0x00000004
1811 1812 ScanFlags.import_items(globals())
1813 1814 -class QueryInfoRequest(Request):
1815 command_id = SMB2_QUERY_INFO 1816 structure_size = 41 1817
1818 - def __init__(self, parent):
1819 Request.__init__(self, parent) 1820 self.info_type = None 1821 self.file_information_class = 0 1822 self.additional_information = 0 1823 self.flags = 0 1824 self.file_id = None 1825 self.output_buffer_length = 4096
1826
1827 - def _encode(self, cur):
1828 cur.encode_uint8le(self.info_type) 1829 cur.encode_uint8le(self.file_information_class) 1830 cur.encode_uint32le(self.output_buffer_length) 1831 1832 # We're not implementing the input buffer support right now 1833 cur.encode_uint16le(0) 1834 cur.encode_uint16le(0) # Reserved 1835 1836 # We're not implementing the input buffer support right now 1837 cur.encode_uint32le(0) 1838 1839 cur.encode_uint32le(self.additional_information) 1840 cur.encode_uint32le(self.flags) 1841 cur.encode_uint64le(self.file_id[0]) 1842 cur.encode_uint64le(self.file_id[1])
1843
1844 1845 -class QueryInfoResponse(Response):
1846 command_id = SMB2_QUERY_INFO 1847 structure_size = 9 1848 allowed_status = [ntstatus.STATUS_SUCCESS, ntstatus.STATUS_BUFFER_OVERFLOW] 1849 1850 _info_map = {} 1851 information = core.Register(_info_map, "info_type", "file_information_class") 1852
1853 - def __init__(self, parent):
1854 Response.__init__(self, parent) 1855 self._info_type = None 1856 self._file_information_class = None 1857 1858 context = self.context 1859 if context: 1860 request = context.get_request(parent.message_id) 1861 1862 if request and request.children: 1863 self._info_type = request[0].info_type 1864 self._file_information_class = request[0].file_information_class 1865 1866 self._entries = []
1867
1868 - def _children(self):
1869 return self._entries
1870
1871 - def append(self, e):
1872 self._entries.append(e)
1873
1874 - def _decode(self, cur):
1875 output_buffer_offset = cur.decode_uint16le() 1876 output_buffer_length = cur.decode_uint32le() 1877 1878 cur.advanceto(self.parent.start + output_buffer_offset) 1879 end = cur + output_buffer_length 1880 1881 key = (self._info_type, self._file_information_class) 1882 if key in self._info_map: 1883 cls = self._info_map[key] 1884 with cur.bounded(cur, end): 1885 cls(self).decode(cur) 1886 else: 1887 Information(self, end).decode(cur)
1888
1889 1890 -class SetInfoRequest(Request):
1891 command_id = SMB2_SET_INFO 1892 structure_size = 33 1893
1894 - def __init__(self, parent):
1895 Request.__init__(self, parent) 1896 self.info_type = 0 1897 self.file_information_class = 0 1898 self.input_buffer_length = 0 1899 self.input_buffer_offset = 0 1900 self.additional_information = 0 1901 self.file_id = None 1902 1903 self._entries = []
1904
1905 - def _children(self):
1906 return self._entries
1907
1908 - def append(self, e):
1909 self._entries.append(e)
1910
1911 - def _encode(self, cur):
1912 if not self.info_type: 1913 self.info_type = self[0].info_type 1914 1915 if not self.file_information_class: 1916 # Determine it from child object 1917 self.file_information_class = self[0].file_information_class 1918 1919 cur.encode_uint8le(self.info_type) 1920 cur.encode_uint8le(self.file_information_class) 1921 1922 buffer_length_hole = cur.hole.encode_uint32le(0) 1923 buffer_offset_hole = cur.hole.encode_uint16le(0) 1924 cur.encode_uint16le(0) # Reserved 1925 1926 cur.encode_uint32le(self.additional_information) 1927 cur.encode_uint64le(self.file_id[0]) 1928 cur.encode_uint64le(self.file_id[1]) 1929 1930 buffer_start = cur.copy() 1931 buffer_offset_hole(buffer_start - self.parent.start) 1932 1933 for info in self._entries: 1934 info.encode(cur) 1935 1936 buffer_length_hole(cur - buffer_start)
1937
1938 1939 -class SetInfoResponse(Response):
1940 command_id = SMB2_SET_INFO 1941 structure_size = 2 1942
1943 - def __init__(self, parent):
1944 Response.__init__(self, parent)
1945
1946 - def _decode(self, cur):
1947 #The response is only the structure size 1948 pass
1949
1950 1951 -class Information(core.Frame):
1952 """ 1953 Base class for all info frames. Holds the raw data if no specific decoder 1954 has been registered for the given info type 1955 """ 1956 info_type = 0 1957 file_information_class = 0 1958
1959 - def __init__(self, parent = None, end = None):
1960 super(Information, self).__init__(parent) 1961 if parent is not None: 1962 parent.append(self) 1963 self.end = end 1964 self.raw_data = ''
1965
1966 - def _decode(self, cur):
1967 """ 1968 decode the raw data to the specified end of buffer 1969 """ 1970 if self.end is not None: 1971 self.raw_data = cur.decode_bytes(self.end - cur)
1972
1973 - def _encode(self, cur):
1974 """ 1975 encode the raw data 1976 """ 1977 cur.encode_bytes(self.raw_data)
1978
1979 1980 @QueryDirectoryResponse.file_information 1981 @QueryInfoResponse.information 1982 -class FileInformation(Information):
1983 info_type = SMB2_0_INFO_FILE
1984
1985 @QueryInfoResponse.information 1986 -class FileSystemInformation(Information):
1987 info_type = SMB2_0_INFO_FILESYSTEM
1988
1989 -class FileAccessInformation(FileInformation):
1990 file_information_class = FILE_ACCESS_INFORMATION 1991
1992 - def __init__(self, parent = None):
1993 FileInformation.__init__(self, parent) 1994 self.access_flags = 0
1995
1996 - def _decode(self, cur):
1997 self.access_flags = Access(cur.decode_uint32le())
1998
1999 # Alignment Requirement flags 2000 -class Alignment(core.ValueEnum):
2001 FILE_BYTE_ALIGNMENT = 0x00000000 2002 FILE_WORD_ALIGNMENT = 0x00000001 2003 FILE_LONG_ALIGNMENT = 0x00000003 2004 FILE_QUAD_ALIGNMENT = 0x00000007 2005 FILE_OCTA_ALIGNMENT = 0x0000000f 2006 FILE_32_BYTE_ALIGNMENT = 0x0000001f 2007 FILE_64_BYTE_ALIGNMENT = 0x0000003f 2008 FILE_128_BYTE_ALIGNMENT = 0x0000007f 2009 FILE_256_BYTE_ALIGNMENT = 0x000000ff 2010 FILE_512_BYTE_ALIGNMENT = 0x000001ff
2011 2012 Alignment.import_items(globals())
2013 2014 -class FileAlignmentInformation(FileInformation):
2015 file_information_class = FILE_ALIGNMENT_INFORMATION 2016
2017 - def __init__(self, parent = None):
2018 FileInformation.__init__(self, parent) 2019 self.alignment_requirement = 0
2020
2021 - def _decode(self, cur):
2022 self.alignment_requirement = Alignment(cur.decode_uint32le())
2023
2024 -class FileAllInformation(FileInformation):
2025 file_information_class = FILE_ALL_INFORMATION 2026
2027 - def __init__(self, parent = None):
2028 FileInformation.__init__(self, parent) 2029 2030 self.basic_information = FileBasicInformation() 2031 self.standard_information = FileStandardInformation() 2032 self.internal_information = FileInternalInformation() 2033 self.ea_information = FileEaInformation() 2034 self.access_information = FileAccessInformation() 2035 self.position_information = FilePositionInformation() 2036 self.mode_information = FileModeInformation() 2037 self.alignment_information = FileAlignmentInformation() 2038 self.name_information = FileNameInformation()
2039
2040 - def _decode(self, cur):
2041 for field in self.fields: 2042 frame = getattr(self, field) 2043 if isinstance(frame, core.Frame): 2044 frame.decode(cur)
2045
2046 -class FileDirectoryInformation(FileInformation):
2047 file_information_class = FILE_DIRECTORY_INFORMATION 2048
2049 - def __init__(self, parent = None):
2050 FileInformation.__init__(self, parent) 2051 self.file_index = 0 2052 self.creation_time = 0 2053 self.last_access_time = 0 2054 self.last_write_time = 0 2055 self.change_time = 0 2056 self.end_of_file = 0 2057 self.allocation_size = 0 2058 self.file_attributes = 0 2059 self.file_name = None
2060
2061 - def _decode(self, cur):
2062 next_offset = cur.decode_uint32le() 2063 self.file_index = cur.decode_uint32le() 2064 self.creation_time = nttime.NtTime(cur.decode_uint64le()) 2065 self.last_access_time = nttime.NtTime(cur.decode_uint64le()) 2066 self.last_write_time = nttime.NtTime(cur.decode_uint64le()) 2067 self.change_time = nttime.NtTime(cur.decode_uint64le()) 2068 self.end_of_file = cur.decode_uint64le() 2069 self.allocation_size = cur.decode_uint64le() 2070 self.file_attributes = FileAttributes(cur.decode_uint32le()) 2071 2072 file_name_length = cur.decode_uint32le() 2073 self.file_name = cur.decode_utf16le(file_name_length) 2074 2075 if next_offset: 2076 cur.advanceto(self.start + next_offset) 2077 else: 2078 cur.advanceto(cur.upperbound)
2079
2080 2081 -class FileFullDirectoryInformation(FileInformation):
2082 file_information_class = FILE_FULL_DIRECTORY_INFORMATION 2083
2084 - def __init__(self, parent = None):
2085 FileInformation.__init__(self, parent) 2086 self.file_index = 0 2087 self.creation_time = 0 2088 self.last_access_time = 0 2089 self.last_write_time = 0 2090 self.change_time = 0 2091 self.end_of_file = 0 2092 self.allocation_size = 0 2093 self.file_attributes = 0 2094 self.ea_size = 0 2095 self.file_name = None
2096
2097 - def _decode(self, cur):
2098 next_offset = cur.decode_uint32le() 2099 self.file_index = cur.decode_uint32le() 2100 self.creation_time = nttime.NtTime(cur.decode_uint64le()) 2101 self.last_access_time = nttime.NtTime(cur.decode_uint64le()) 2102 self.last_write_time = nttime.NtTime(cur.decode_uint64le()) 2103 self.change_time = nttime.NtTime(cur.decode_uint64le()) 2104 self.end_of_file = cur.decode_uint64le() 2105 self.allocation_size = cur.decode_uint64le() 2106 self.file_attributes = FileAttributes(cur.decode_uint32le()) 2107 file_name_length = cur.decode_uint32le() 2108 self.ea_size = cur.decode_uint32le() 2109 2110 self.file_name = cur.decode_utf16le(file_name_length) 2111 if next_offset: 2112 cur.advanceto(self.start + next_offset) 2113 else: 2114 cur.advanceto(cur.upperbound)
2115
2116 -class FileIdFullDirectoryInformation(FileInformation):
2117 file_information_class = FILE_ID_FULL_DIR_INFORMATION 2118
2119 - def __init__(self, parent = None):
2120 FileInformation.__init__(self, parent) 2121 self.file_index = 0 2122 self.creation_time = 0 2123 self.last_access_time = 0 2124 self.last_write_time = 0 2125 self.change_time = 0 2126 self.end_of_file = 0 2127 self.allocation_size = 0 2128 self.file_attributes = 0 2129 self.ea_size = 0 2130 self.reserved = 0 2131 self.file_id = 0 2132 self.file_name = None
2133
2134 - def _decode(self, cur):
2135 next_offset = cur.decode_uint32le() 2136 self.file_index = cur.decode_uint32le() 2137 self.creation_time = nttime.NtTime(cur.decode_uint64le()) 2138 self.last_access_time = nttime.NtTime(cur.decode_uint64le()) 2139 self.last_write_time = nttime.NtTime(cur.decode_uint64le()) 2140 self.change_time = nttime.NtTime(cur.decode_uint64le()) 2141 self.end_of_file = cur.decode_uint64le() 2142 self.allocation_size = cur.decode_uint64le() 2143 self.file_attributes = FileAttributes(cur.decode_uint32le()) 2144 file_name_length = cur.decode_uint32le() 2145 self.ea_size = cur.decode_uint32le() 2146 self.reserved = cur.decode_uint32le() 2147 self.file_id = cur.decode_uint64le() 2148 2149 self.file_name = cur.decode_utf16le(file_name_length) 2150 if next_offset: 2151 cur.advanceto(self.start + next_offset) 2152 else: 2153 cur.advanceto(cur.upperbound)
2154
2155 2156 -class FileIdBothDirectoryInformation(FileInformation):
2157 file_information_class = FILE_ID_BOTH_DIR_INFORMATION 2158
2159 - def __init__(self, parent = None):
2160 FileInformation.__init__(self, parent) 2161 self.file_index = 0 2162 self.creation_time = 0 2163 self.last_access_time = 0 2164 self.last_write_time = 0 2165 self.change_time = 0 2166 self.end_of_file = 0 2167 self.allocation_size = 0 2168 self.file_attributes = 0 2169 self.ea_size = 0 2170 self.file_id = 0 2171 self.short_name = None 2172 self.file_name = None
2173
2174 - def _decode(self, cur):
2175 next_offset = cur.decode_uint32le() 2176 self.file_index = cur.decode_uint32le() 2177 self.creation_time = nttime.NtTime(cur.decode_uint64le()) 2178 self.last_access_time = nttime.NtTime(cur.decode_uint64le()) 2179 self.last_write_time = nttime.NtTime(cur.decode_uint64le()) 2180 self.change_time = nttime.NtTime(cur.decode_uint64le()) 2181 self.end_of_file = cur.decode_uint64le() 2182 self.allocation_size = cur.decode_uint64le() 2183 self.file_attributes = FileAttributes(cur.decode_uint32le()) 2184 2185 self.file_name_length = cur.decode_uint32le() 2186 self.ea_size = cur.decode_uint32le() 2187 self.short_name_length = cur.decode_uint8le() 2188 reserved = cur.decode_uint8le() 2189 self.short_name = cur.decode_bytes(24) 2190 reserved = cur.decode_uint16le() 2191 self.file_id = cur.decode_uint64le() 2192 self.file_name = cur.decode_utf16le(self.file_name_length) 2193 2194 if next_offset: 2195 cur.advanceto(self.start + next_offset) 2196 else: 2197 cur.advanceto(cur.upperbound)
2198
2199 2200 -class FileBasicInformation(FileInformation):
2201 file_information_class = FILE_BASIC_INFORMATION 2202
2203 - def __init__(self, parent = None):
2204 FileInformation.__init__(self, parent) 2205 self.creation_time = 0 2206 self.last_access_time = 0 2207 self.last_write_time = 0 2208 self.change_time = 0 2209 self.file_attributes = 0
2210
2211 - def _decode(self, cur):
2212 self.creation_time = nttime.NtTime(cur.decode_uint64le()) 2213 self.last_access_time = nttime.NtTime(cur.decode_uint64le()) 2214 self.last_write_time = nttime.NtTime(cur.decode_uint64le()) 2215 self.change_time = nttime.NtTime(cur.decode_uint64le()) 2216 self.file_attributes = FileAttributes(cur.decode_uint32le()) 2217 # Ignore the 4-byte reserved field 2218 cur.decode_uint32le()
2219
2220 - def _encode(self, cur):
2221 cur.encode_uint64le(self.creation_time) 2222 cur.encode_uint64le(self.last_access_time) 2223 cur.encode_uint64le(self.last_write_time) 2224 cur.encode_uint64le(self.change_time) 2225 cur.encode_uint32le(self.file_attributes) 2226 # Ignore the 4-byte reserved field 2227 cur.encode_uint32le(0)
2228
2229 2230 -class FileNetworkOpenInformation(FileInformation):
2231 file_information_class = FILE_NETWORK_OPEN_INFORMATION 2232
2233 - def __init__(self, parent = None):
2234 FileInformation.__init__(self, parent) 2235 self.creation_time = 0 2236 self.last_access_time = 0 2237 self.last_write_time = 0 2238 self.change_time = 0 2239 self.allocation_size = 0 2240 self.end_of_file = 0 2241 self.file_attributes = 0
2242
2243 - def _decode(self, cur):
2244 self.creation_time = nttime.NtTime(cur.decode_uint64le()) 2245 self.last_access_time = nttime.NtTime(cur.decode_uint64le()) 2246 self.last_write_time = nttime.NtTime(cur.decode_uint64le()) 2247 self.change_time = nttime.NtTime(cur.decode_uint64le()) 2248 self.allocation_size = cur.decode_int64le() 2249 self.end_of_file = cur.decode_int64le() 2250 self.file_attributes = FileAttributes(cur.decode_uint32le()) 2251 # Ignore the 4-byte reserved field 2252 cur.decode_uint32le()
2253
2254 2255 -class FileAttributeTagInformation(FileInformation):
2256 file_information_class = FILE_ATTRIBUTE_TAG_INFORMATION 2257
2258 - def __init__(self, parent = None):
2259 FileInformation.__init__(self, parent) 2260 self.file_attributes = 0 2261 self.reparse_tag = 0
2262
2263 - def _decode(self, cur):
2264 self.file_attributes = FileAttributes(cur.decode_uint32le()) 2265 self.reparse_tag = cur.decode_uint32le()
2266
2267 2268 -class FileStreamInformation(FileInformation):
2269 file_information_class = FILE_STREAM_INFORMATION 2270
2271 - def __init__(self, parent = None):
2272 FileInformation.__init__(self, parent) 2273 self.next_entry_offset = 0 2274 self.stream_name_length = 0 2275 self.stream_size = 0 2276 self.stream_allocation_size = 0 2277 self.stream_name = None
2278
2279 - def _decode(self, cur):
2280 self.next_entry_offset = cur.decode_uint32le() 2281 self.stream_name_length = cur.decode_uint32le() 2282 self.stream_size = cur.decode_int64le() 2283 self.stream_allocation_size = cur.decode_int64le() 2284 self.stream_name = cur.decode_utf16le(self.stream_name_length)
2285
2286 2287 # Compression Format 2288 -class CompressionFormat(core.ValueEnum):
2289 COMPRESSION_FORMAT_NONE = 0x0000 2290 COMPRESSION_FORMAT_LZNT1 = 0x0002
2291 2292 CompressionFormat.import_items(globals())
2293 2294 2295 -class FileCompressionInformation(FileInformation):
2296 file_information_class = FILE_COMPRESSION_INFORMATION 2297
2298 - def __init__(self, parent = None):
2299 FileInformation.__init__(self, parent) 2300 self.compressed_file_size = 0 2301 self.compression_format = 0 2302 self.compression_unit_shift = 0 2303 self.chunk_shift = 0 2304 self.cluster_shift = None 2305 self.reserved = 0
2306
2307 - def _decode(self, cur):
2308 self.compressed_file_size = cur.decode_int64le() 2309 self.compression_format = CompressionFormat(cur.decode_uint16le()) 2310 self.compression_unit_shift = cur.decode_uint8le() 2311 self.chunk_shift = cur.decode_uint8le() 2312 self.cluster_shift = cur.decode_uint8le() 2313 2314 # This is a single reserved field of 3 bytes. 2315 self.reserved = cur.decode_uint8le() | (cur.decode_uint8le() << 8) | (cur.decode_uint8le() << 16)
2316
2317 -class FileInternalInformation(FileInformation):
2318 file_information_class = FILE_INTERNAL_INFORMATION 2319
2320 - def __init__(self, parent = None):
2321 FileInformation.__init__(self, parent) 2322 self.index_number = 0
2323
2324 - def _decode(self, cur):
2325 self.index_number = cur.decode_uint64le()
2326
2327 -class FileModeInformation(FileInformation):
2328 file_information_class = FILE_MODE_INFORMATION 2329
2330 - def __init__(self, parent = None):
2331 FileInformation.__init__(self, parent) 2332 # See Create options (e.g. FILE_DELETE_ON_CLOSE) for available flags 2333 self.mode = 0
2334
2335 - def _decode(self, cur):
2336 self.mode = CreateOptions(cur.decode_uint32le())
2337
2338 - def _encode(self, cur):
2339 cur.encode_uint32le(self.mode)
2340
2341 -class FileNameInformation(FileInformation):
2342 file_information_class = FILE_NAME_INFORMATION 2343
2344 - def __init__(self, parent = None):
2345 FileInformation.__init__(self, parent) 2346 self.file_name = None
2347
2348 - def _decode(self, cur):
2349 file_name_length = cur.decode_uint32le() 2350 self.file_name = cur.decode_utf16le(file_name_length)
2351
2352 -class FileRenameInformation(FileInformation):
2353 file_information_class = FILE_RENAME_INFORMATION 2354
2355 - def __init__(self, parent = None):
2356 FileInformation.__init__(self, parent) 2357 self.replace_if_exists = 0 2358 self.root_directory = (0,0) 2359 self.file_name = None
2360
2361 - def _encode(self, cur):
2362 cur.encode_uint8le(self.replace_if_exists) 2363 cur.encode_uint8le(0) # reserved 2364 cur.encode_uint16le(0) # reserved 2365 cur.encode_uint32le(0) # reserved 2366 cur.encode_uint32le(self.root_directory[0]) 2367 cur.encode_uint32le(self.root_directory[1]) 2368 file_name_length_hole = cur.hole.encode_uint32le(0) 2369 file_name_start = cur.copy() 2370 cur.encode_utf16le(self.file_name) 2371 file_name_length_hole(cur - file_name_start)
2372
2373 -class FileAllocationInformation(FileInformation):
2374 file_information_class = FILE_ALLOCATION_INFORMATION 2375
2376 - def __init__(self, parent = None):
2377 FileInformation.__init__(self,parent) 2378 self.allocation_size = 0
2379
2380 - def _encode(self, cur):
2381 cur.encode_int64le(self.allocation_size)
2382
2383 2384 -class FileDispositionInformation(FileInformation):
2385 file_information_class = FILE_DISPOSITION_INFORMATION 2386
2387 - def __init__(self, parent = None):
2388 FileInformation.__init__(self,parent) 2389 self.delete_pending = 0
2390
2391 - def _encode(self, cur):
2392 cur.encode_uint8le(self.delete_pending)
2393
2394 2395 -class FileEndOfFileInformation(FileInformation):
2396 file_information_class = FILE_END_OF_FILE_INFORMATION 2397
2398 - def __init__(self, parent = None):
2399 FileInformation.__init__(self, parent) 2400 self.endoffile = 0
2401
2402 - def _encode(self, cur):
2403 cur.encode_int64le(self.endoffile)
2404
2405 2406 -class FileValidDataLengthInformation(FileInformation):
2407 file_information_class = FILE_VALID_DATA_LENGTH_INFORMATION 2408
2409 - def __init__(self, parent = None):
2410 FileInformation.__init__(self, parent) 2411 self.valid_data_length = 0
2412
2413 - def _encode(self, cur):
2414 cur.encode_int64le(self.valid_data_length)
2415
2416 -class FileNamesInformation(FileInformation):
2417 file_information_class = FILE_NAMES_INFORMATION 2418
2419 - def __init__(self, parent = None):
2420 FileInformation.__init__(self, parent) 2421 self.file_index = 0 2422 self.file_name = None
2423
2424 - def _decode(self, cur):
2425 next_entry_offset = cur.decode_uint32le() 2426 self.file_index = cur.decode_uint32le() 2427 2428 file_name_length = cur.decode_uint32le() 2429 self.file_name = cur.decode_utf16le(file_name_length) 2430 2431 if next_entry_offset: 2432 cur.advanceto(self.start + next_entry_offset) 2433 else: 2434 cur.advanceto(cur.upperbound)
2435
2436 -class FilePositionInformation(FileInformation):
2437 file_information_class = FILE_POSITION_INFORMATION 2438
2439 - def __init__(self, parent = None):
2440 FileInformation.__init__(self, parent) 2441 self.current_byte_offset = 0
2442
2443 - def _decode(self, cur):
2444 self.current_byte_offset = cur.decode_uint64le()
2445
2446 - def _encode(self, cur):
2447 cur.encode_uint64le(self.current_byte_offset)
2448
2449 -class FileStandardInformation(FileInformation):
2450 file_information_class = FILE_STANDARD_INFORMATION 2451
2452 - def __init__(self, parent = None):
2453 FileInformation.__init__(self, parent) 2454 self.allocation_size = 0 2455 self.end_of_file = 0 2456 self.number_of_links = 0 2457 self.delete_pending = 0 2458 self.directory = 0
2459
2460 - def _decode(self, cur):
2461 self.allocation_size = cur.decode_uint64le() 2462 self.end_of_file = cur.decode_uint64le() 2463 self.number_of_links = cur.decode_uint32le() 2464 self.delete_pending = cur.decode_uint8le() 2465 self.directory = cur.decode_uint8le() 2466 # Ignore 2-bytes Reserved field 2467 cur.decode_uint16le()
2468
2469 - def _encode(self, cur):
2470 cur.encode_uint64le(self.allocation_size) 2471 cur.encode_uint64le(self.end_of_file) 2472 cur.encode_uint32le(self.number_of_links) 2473 cur.encode_uint8le(self.delete_pending) 2474 cur.encode_uint8le(self.directory) 2475 # Ignore 2-bytes Reserved field 2476 cur.encode_uint16le(0)
2477
2478 -class FileEaInformation(FileInformation):
2479 file_information_class = FILE_EA_INFORMATION 2480
2481 - def __init__(self, parent = None):
2482 FileInformation.__init__(self, parent) 2483 self.ea_size = 0
2484
2485 - def _decode(self, cur):
2486 self.ea_size = cur.decode_uint32le()
2487
2488 2489 -class FileFsSizeInformation(FileSystemInformation):
2490 file_information_class = FILE_FS_SIZE_INFORMATION 2491
2492 - def __init__(self, parent = None):
2493 FileSystemInformation.__init__(self, parent) 2494 self.total_allocation_units = 0 2495 self.available_allocation_units = 0 2496 self.sectors_per_allocation_unit = 0 2497 self.bytes_per_sector = 0
2498
2499 - def _decode(self, cur):
2500 self.total_allocation_units = cur.decode_int64le() 2501 self.available_allocation_units = cur.decode_int64le() 2502 self.sectors_per_allocation_unit = cur.decode_uint32le() 2503 self.bytes_per_sector = cur.decode_uint32le()
2504
2505 2506 -class FileFsFullSizeInformation(FileSystemInformation):
2507 file_information_class = FILE_FS_FULL_SIZE_INFORMATION 2508
2509 - def __init__(self, parent = None):
2510 FileSystemInformation.__init__(self, parent) 2511 self.total_allocation_units = 0 2512 self.caller_available_allocation_units = 0 2513 self.actual_available_allocation_units = 0 2514 self.sectors_per_allocation_unit = 0 2515 self.bytes_per_sector = 0
2516
2517 - def _decode(self, cur):
2518 self.total_allocation_units = cur.decode_uint64le() 2519 self.caller_available_allocation_units = cur.decode_uint64le() 2520 self.actual_available_allocation_units = cur.decode_uint64le() 2521 self.sectors_per_allocation_unit = cur.decode_uint32le() 2522 self.bytes_per_sector = cur.decode_uint32le()
2523
2524 2525 # DeviceType 2526 -class DeviceType(core.ValueEnum):
2527 FILE_DEVICE_CD_ROM = 0x00000002 2528 FILE_DEVICE_DISK = 0x00000007
2529 2530 DeviceType.import_items(globals())
2531 2532 2533 # Volume Characteristics 2534 -class Characteristics(core.FlagEnum):
2535 FILE_REMOVABLE_MEDIA = 0x00000001 2536 FILE_READ_ONLY_DEVICE = 0x00000002 2537 FILE_FLOPPY_DISKETTE = 0x00000004 2538 FILE_WRITE_ONCE_MEDIA = 0x00000008 2539 FILE_REMOTE_DEVICE = 0x00000010 2540 FILE_DEVICE_IS_MOUNTED = 0x00000020 2541 FILE_VIRTUAL_VOLUME = 0x00000040 2542 FILE_DEVICE_SECURE_OPEN = 0x00000100 2543 FILE_CHARACTERISTIC_TS_DEVICE = 0x00001000 2544 FILE_CHARACTERISTIC_WEBDAV_DEVICE = 0x00002000 2545 FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL = 0x00020000
2546 2547 Characteristics.import_items(globals())
2548 2549 2550 -class FileFsDeviceInformation(FileSystemInformation):
2551 file_information_class = FILE_FS_DEVICE_INFORMATION 2552
2553 - def __init__(self, parent = None):
2554 FileSystemInformation.__init__(self, parent) 2555 self.device_type = 0 2556 self.characteristics = 0
2557
2558 - def _decode(self, cur):
2559 self.device_type = DeviceType(cur.decode_uint32le()) 2560 self.characteristics = Characteristics(cur.decode_uint32le())
2561
2562 2563 # File System Attributes 2564 -class FileSystemAtrribute(core.FlagEnum):
2565 FILE_CASE_SENSITIVE_SEARCH = 0x00000001 2566 FILE_CASE_PRESERVED_NAMES = 0x00000002 2567 FILE_UNICODE_ON_DISK = 0x00000004 2568 FILE_PERSISTENT_ACLS = 0x00000008 2569 FILE_FILE_COMPRESSION = 0x00000010 2570 FILE_VOLUME_QUOTAS = 0x00000020 2571 FILE_SUPPORTS_SPARSE_FILES = 0x00000040 2572 FILE_SUPPORTS_REPARSE_POINTS = 0x00000080 2573 FILE_SUPPORTS_REMOTE_STORAGE = 0x00000100 2574 FILE_VOLUME_IS_COMPRESSED = 0x00008000 2575 FILE_SUPPORTS_OBJECT_IDS = 0x00010000 2576 FILE_SUPPORTS_ENCRYPTION = 0x00020000 2577 FILE_NAMED_STREAMS = 0x00040000 2578 FILE_READ_ONLY_VOLUME = 0x00080000 2579 FILE_SEQUENTIAL_WRITE_ONCE = 0x00100000 2580 FILE_SUPPORTS_TRANSACTIONS = 0x00200000 2581 FILE_SUPPORTS_HARD_LINKS = 0x00400000 2582 FILE_SUPPORTS_EXTENDED_ATTRIBUTES = 0x00800000 2583 FILE_SUPPORTS_OPEN_BY_FILE_ID = 0x01000000 2584 FILE_SUPPORTS_USN_JOURNAL = 0x02000000 2585 FILE_SUPPORT_INTEGRITY_STREAMS = 0x04000000
2586 2587 FileSystemAtrribute.import_items(globals())
2588 2589 2590 -class FileFsAttributeInformation(FileSystemInformation):
2591 file_information_class = FILE_FS_ATTRIBUTE_INFORMATION 2592
2593 - def __init__(self, parent = None):
2594 FileSystemInformation.__init__(self, parent) 2595 self.file_system_attibutes = 0 2596 self.maximum_component_name_length = 0 2597 self.file_system_name_length = 0 2598 self.file_system_name = 0
2599
2600 - def _decode(self, cur):
2601 self.file_system_attibutes = cur.decode_uint32le() 2602 self.maximum_component_name_length = cur.decode_int32le() 2603 self.file_system_name_length = cur.decode_uint32le() 2604 self.file_system_name = cur.decode_utf16le(self.file_system_name_length)
2605
2606 2607 -class FileFsVolumeInformation(FileSystemInformation):
2608 file_information_class = FILE_FS_VOLUME_INFORMATION 2609
2610 - def __init__(self, parent = None):
2611 FileSystemInformation.__init__(self, parent) 2612 self.volume_creation_time = 0 2613 self.volume_serial_number = 0 2614 self.volume_label_length = 0 2615 self.supports_objects = 0 2616 self.reserved = 0 2617 self.volume_label = None
2618
2619 - def _decode(self, cur):
2620 self.volume_creation_time = nttime.NtTime(cur.decode_uint64le()) 2621 self.volume_serial_number = cur.decode_uint32le() 2622 self.volume_label_length = cur.decode_uint32le() 2623 self.supports_objects = cur.decode_uint8le() 2624 cur.decode_uint8le() 2625 self.volume_label = cur.decode_utf16le(self.volume_label_length)
2626
2627 2628 # File System Control Flags 2629 -class FileSystemControlFlags(core.FlagEnum):
2630 FILE_VC_QUOTA_TRACK = 0x00000001 2631 FILE_VC_QUOTA_ENFORCE = 0x00000002 2632 FILE_VC_CONTENT_INDEX_DISABLED = 0x00000008 2633 FILE_VC_LOG_QUOTA_THRESHOLD = 0x00000010 2634 FILE_VC_LOG_QUOTA_LIMIT = 0x00000020 2635 FILE_VC_LOG_VOLUME_THRESHOLD = 0x00000040 2636 FILE_VC_LOG_VOLUME_LIMIT = 0x00000080 2637 FILE_VC_QUOTAS_INCOMPLETE = 0x00000100 2638 FILE_VC_QUOTAS_REBUILDING = 0x00000200
2639 2640 FileSystemControlFlags.import_items(globals())
2641 2642 2643 -class FileFsControlInformation(FileSystemInformation):
2644 file_information_class = FILE_FS_CONTROL_INFORMATION 2645
2646 - def __init__(self, parent = None):
2647 FileSystemInformation.__init__(self, parent) 2648 self.free_space_start_filtering = 0 2649 self.free_space_threshold = 0 2650 self.free_space_stop_filtering = 0 2651 self.default_quota_threshold = 0 2652 self.default_quota_limit = 0 2653 self.file_system_control_flags = None 2654 self.padding = 0
2655
2656 - def _encode(self, cur):
2657 cur.encode_int64le(self.free_space_start_filtering) 2658 cur.encode_int64le(self.free_space_threshold) 2659 cur.encode_int64le(self.free_space_stop_filtering) 2660 cur.encode_uint64le(self.default_quota_threshold) 2661 cur.encode_uint64le(self.default_quota_limit) 2662 cur.encode_uint32le(self.file_system_control_flags) 2663 cur.encode_uint32le(self.padding)
2664
2665 - def _decode(self, cur):
2666 self.free_space_start_filtering = cur.decode_int64le() 2667 self.free_space_threshold = cur.decode_int64le() 2668 self.free_space_stop_filtering = cur.decode_int64le() 2669 self.default_quota_threshold = cur.decode_uint64le() 2670 self.default_quota_limit = cur.decode_uint64le() 2671 self.file_system_control_flags = FileSystemControlFlags(cur.decode_uint32le()) 2672 self.padding = cur.decode_uint32le()
2673
2674 2675 -class FileFsObjectIdInformation(FileSystemInformation):
2676 file_information_class = FILE_FS_OBJECTID_INFORMATION 2677
2678 - def __init__(self, parent = None):
2679 FileSystemInformation.__init__(self, parent) 2680 self.objectid = "" 2681 self.extended_info = ""
2682
2683 - def _decode(self, cur):
2684 for count in xrange(2): 2685 self.objectid += str(cur.decode_uint64le()) 2686 for count in xrange(6): 2687 self.extended_info += str(cur.decode_uint64le())
2688
2689 -class CompletionFilter(core.FlagEnum):
2690 SMB2_NOTIFY_CHANGE_FILE_NAME = 0x001 2691 SMB2_NOTIFY_CHANGE_DIR_NAME = 0x002 2692 SMB2_NOTIFY_CHANGE_ATTRIBUTES = 0x004 2693 SMB2_NOTIFY_CHANGE_SIZE = 0x008 2694 SMB2_NOTIFY_CHANGE_LAST_WRITE = 0x010 2695 SMB2_NOTIFY_CHANGE_LAST_ACCESS = 0x020 2696 SMB2_NOTIFY_CHANGE_CREATION = 0x040 2697 SMB2_NOTIFY_CHANGE_EA = 0x080 2698 SMB2_NOTIFY_CHANGE_SECURITY = 0x100 2699 SMB2_NOTIFY_CHANGE_STREAM_NAME = 0x200 2700 SMB2_NOTIFY_CHANGE_STREAM_SIZE = 0x400 2701 SMB2_NOTIFY_CHANGE_STREAM_WRITE = 0x800
2702 2703 CompletionFilter.import_items(globals())
2704 2705 -class ChangeNotifyFlags(core.FlagEnum):
2706 SMB2_WATCH_TREE = 0x01
2707 2708 ChangeNotifyFlags.import_items(globals())
2709 2710 -class FileNotifyInfoAction(core.ValueEnum):
2711 SMB2_ACTION_ADDED = 0x001 2712 SMB2_ACTION_REMOVED = 0x002 2713 SMB2_ACTION_MODIFIED = 0x003 2714 SMB2_ACTION_RENAMED_OLD_NAME = 0x004 2715 SMB2_ACTION_RENAMED_NEW_NAME = 0x005 2716 SMB2_ACTION_ADDED_STREAM = 0x006 2717 SMB2_ACTION_REMOVED_STREAM = 0x007 2718 SMB2_ACTION_MODIFIED_STREAM = 0x008 2719 SMB2_ACTION_REMOVED_BY_DELETE = 0x009
2720 2721 FileNotifyInfoAction.import_items(globals())
2722 2723 -class FileNotifyInformation(core.Frame):
2724 - def __init__(self, parent = None):
2725 core.Frame.__init__(self, parent) 2726 self.action = 0 2727 self.filename = None 2728 if parent is not None: 2729 parent.append(self)
2730
2731 - def _decode(self, cur):
2732 startoffset = cur.offset 2733 neo = cur.decode_uint32le() 2734 self.action = FileNotifyInfoAction(cur.decode_uint32le()) 2735 filenamelength = cur.decode_uint32le() 2736 self.filename = cur.decode_utf16le(filenamelength) 2737 cur.offset = startoffset + neo 2738 return neo
2739 - def __repr__(self):
2740 return "<{0} {1} '{2}'>".format(self.__class__.__name__, 2741 self.action, 2742 self.filename)
2743
2744 -class ChangeNotifyResponse(Response):
2745 command_id = SMB2_CHANGE_NOTIFY 2746 structure_size = 9 2747
2748 - def __init__(self, parent):
2749 Response.__init__(self, parent) 2750 self.notifications = []
2751
2752 - def append(self, child):
2753 self.notifications.append(child)
2754
2755 - def _decode(self, cur):
2756 self.offset = cur.decode_uint16le() 2757 self.buffer_length = cur.decode_uint32le() 2758 if self.buffer_length > 0: 2759 while True: 2760 neo = FileNotifyInformation(self)._decode(cur) 2761 if neo == 0: 2762 break
2763
2764 -class ChangeNotifyRequest(Request):
2765 command_id = SMB2_CHANGE_NOTIFY 2766 structure_size = 32 2767
2768 - def __init__(self, parent):
2769 Request.__init__(self, parent) 2770 self.flags = 0 2771 self.file_id = None 2772 self.buffer_length = 4096 2773 self.completion_filter = 0
2774
2775 - def _encode(self, cur):
2776 cur.encode_uint16le(self.flags) 2777 cur.encode_uint32le(self.buffer_length) 2778 cur.encode_uint64le(self.file_id[0]) 2779 cur.encode_uint64le(self.file_id[1]) 2780 cur.encode_uint32le(self.completion_filter) 2781 # Reserved 2782 cur.encode_uint32le(0)
2783
2784 -class BreakLeaseFlags(core.FlagEnum):
2785 SMB2_NOTIFY_BREAK_LEASE_FLAG_NONE = 0x00 2786 SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED = 0x01
2787 2788 BreakLeaseFlags.import_items(globals())
2789 2790 -class OplockBreakNotification(Notification):
2791 command_id = SMB2_OPLOCK_BREAK 2792 structure_size = 24 2793
2794 - def __init__(self, parent):
2795 Notification.__init__(self, parent) 2796 self.oplock_level = 0 2797 self.file_id = None
2798
2799 - def _decode(self, cur):
2800 self.oplock_level = OplockLevel(cur.decode_uint8le()) 2801 self.reserved1 = cur.decode_uint8le() 2802 self.reserved2 = cur.decode_uint32le() 2803 self.file_id = (cur.decode_uint64le(), cur.decode_uint64le())
2804
2805 -class LeaseBreakNotification(Notification):
2806 command_id = SMB2_OPLOCK_BREAK 2807 structure_size = 44 2808
2809 - def __init__(self, parent):
2810 Notification.__init__(self, parent) 2811 self.new_epoch = 0 2812 self.flags = 0 2813 self.lease_key = 0 2814 self.current_lease_state = 0 2815 self.new_lease_state = 0
2816
2817 - def _decode(self, cur):
2818 self.new_epoch = cur.decode_uint16le() 2819 self.flags = BreakLeaseFlags(cur.decode_uint32le()) 2820 self.lease_key = cur.decode_bytes(16) 2821 self.current_lease_state = LeaseState(cur.decode_uint32le()) 2822 self.new_lease_state = LeaseState(cur.decode_uint32le()) 2823 self.break_reason = cur.decode_uint32le() 2824 self.access_mask_hint = cur.decode_uint32le() 2825 self.share_mask_hint = cur.decode_uint32le()
2826
2827 -class OplockBreakAcknowledgement(Request):
2828 command_id = SMB2_OPLOCK_BREAK 2829 structure_size = 24 2830
2831 - def __init__(self, parent):
2832 Request.__init__(self, parent) 2833 self.oplock_level = 0 2834 self.file_id = None
2835
2836 - def _encode(self, cur):
2837 cur.encode_uint8le(self.oplock_level) 2838 # Reserved 2839 cur.encode_uint8le(0) 2840 # Reserved2 2841 cur.encode_uint32le(0) 2842 cur.encode_uint64le(self.file_id[0]) 2843 cur.encode_uint64le(self.file_id[1])
2844
2845 -class LeaseBreakAcknowledgement(Request):
2846 command_id = SMB2_OPLOCK_BREAK 2847 structure_size = 36 2848
2849 - def __init__(self, parent):
2850 Request.__init__(self, parent) 2851 self.flags = 0 2852 self.lease_key = 0 2853 self.lease_state = 0
2854
2855 - def _encode(self, cur):
2856 # Reserved 2857 cur.encode_uint16le(0) 2858 cur.encode_uint32le(self.flags) 2859 cur.encode_bytes(self.lease_key) 2860 cur.encode_uint32le(self.lease_state) 2861 # LeaseDuration is reserved 2862 cur.encode_uint64le(0)
2863
2864 -class OplockBreakResponse(Response):
2865 command_id = SMB2_OPLOCK_BREAK 2866 structure_size = 24 2867
2868 - def __init__(self, parent):
2869 Response.__init__(self, parent) 2870 self.oplock_level = 0 2871 self.file_id = 0
2872
2873 - def _decode(self, cur):
2874 self.oplock_level = OplockLevel(cur.decode_uint8le()) 2875 self.reserved1 = cur.decode_uint8le() 2876 self.reserved2 = cur.decode_uint32le() 2877 self.file_id = (cur.decode_uint64le(), cur.decode_uint64le())
2878
2879 -class LeaseBreakResponse(Response):
2880 command_id = SMB2_OPLOCK_BREAK 2881 structure_size = 36 2882
2883 - def __init__(self, parent):
2884 Response.__init__(self, parent) 2885 self.flags = 0 2886 self.lease_key = 0 2887 self.lease_state = 0
2888
2889 - def _decode(self, cur):
2890 self.reserved = cur.decode_uint16le() 2891 self.flags = BreakLeaseFlags(cur.decode_uint32le()) 2892 self.lease_key = cur.decode_bytes(16) 2893 self.lease_state = LeaseState(cur.decode_uint32le()) 2894 self.lease_duration = cur.decode_uint64le()
2895
2896 -class ReadRequest(Request):
2897 command_id = SMB2_READ 2898 structure_size = 49 2899
2900 - def __init__(self, parent):
2901 Request.__init__(self, parent) 2902 self.length = 0 2903 self.offset = 0 2904 self.minimum_count = 0 2905 self.remaining_bytes = 0 2906 self.file_id = None 2907 2908 self.padding = 0 2909 self.reserved = 0 2910 self.channel = 0 2911 self.read_channel_info_offset = None 2912 self.read_channel_info_length = None 2913 self.buffer = 0
2914
2915 - def _encode(self, cur):
2916 # Padding 2917 cur.encode_uint8le(self.padding) 2918 # Reserved 2919 cur.encode_uint8le(self.reserved) 2920 cur.encode_uint32le(self.length) 2921 cur.encode_uint64le(self.offset) 2922 cur.encode_uint64le(self.file_id[0]) 2923 cur.encode_uint64le(self.file_id[1]) 2924 cur.encode_uint32le(self.minimum_count) 2925 # Channel 2926 cur.encode_uint32le(self.channel) 2927 2928 cur.encode_uint32le(self.remaining_bytes) 2929 2930 # ReadChannelInfoLength 2931 if self.read_channel_info_offset is None: 2932 self.read_channel_info_offset = 0 2933 cur.encode_uint16le(self.read_channel_info_offset) 2934 2935 # ReadChannelInfoLength 2936 if self.read_channel_info_length is None: 2937 self.read_channel_info_length = 0 2938 cur.encode_uint16le(self.read_channel_info_length) 2939 2940 # Buffer 2941 cur.encode_uint8le(self.buffer)
2942
2943 2944 -class ReadResponse(Response):
2945 command_id = SMB2_READ 2946 structure_size = 17 2947
2948 - def __init__(self, parent):
2949 Response.__init__(self, parent) 2950 self.offset = 0 2951 self.length = 0 2952 self.data = None 2953 self.reserved = 0 2954 self.data_remaining = 0 2955 self.reserved2 = 0
2956
2957 - def _decode(self, cur):
2958 self.offset = cur.decode_uint8le() 2959 self.reserved = cur.decode_uint8le() 2960 self.length = cur.decode_uint32le() 2961 self.data_remaining = cur.decode_uint32le() 2962 self.reserved2 = cur.decode_uint32le() 2963 2964 # Advance to data 2965 cur.advanceto(self.parent.start + self.offset) 2966 2967 self.data = cur.decode_bytes(self.length)
2968
2969 # Flag constants 2970 -class WriteFlags(core.FlagEnum):
2971 SMB2_WRITEFLAG_WRITE_THROUGH = 0x00000001
2972 2973 WriteFlags.import_items(globals())
2974 2975 -class WriteRequest(Request):
2976 command_id = SMB2_WRITE 2977 structure_size = 49 2978
2979 - def __init__(self, parent):
2980 Request.__init__(self, parent) 2981 self.offset = 0 2982 self.file_id = None 2983 self.remaining_bytes = 0 2984 self.flags = 0 2985 self.buffer = None 2986 self.data_offset = None 2987 self.length = None 2988 self.channel = 0 2989 self.write_channel_info_offset = 0 2990 self.write_channel_info_length = 0
2991
2992 - def _encode(self, cur):
2993 # Encode 0 for buffer offset for now 2994 buf_ofs = cur.hole.encode_uint16le(0) 2995 if self.length == None and self.buffer != None: 2996 cur.encode_uint32le(len(self.buffer)) 2997 elif self.buffer == None: 2998 cur.encode_uint32le(0) 2999 else: 3000 cur.encode_uint32le(self.length) 3001 cur.encode_uint64le(self.offset) 3002 cur.encode_uint64le(self.file_id[0]) 3003 cur.encode_uint64le(self.file_id[1]) 3004 # Channel 3005 cur.encode_uint32le(self.channel) 3006 # RemainingBytes 3007 cur.encode_uint32le(self.remaining_bytes) 3008 # WriteChannelInfoOffset 3009 cur.encode_uint16le(self.write_channel_info_offset) 3010 # WriteChannelInfoLength: 3011 cur.encode_uint16le(self.write_channel_info_length) 3012 # Flags 3013 cur.encode_uint32le(self.flags) 3014 # Go back and set buffer offset 3015 3016 if self.data_offset is None: 3017 self.data_offset = cur - self.parent.start 3018 buf_ofs(self.data_offset) 3019 3020 if self.buffer: 3021 cur.encode_bytes(self.buffer)
3022
3023 -class WriteResponse(Response):
3024 command_id = SMB2_WRITE 3025 structure_size = 17 3026
3027 - def __init__(self, parent):
3028 Response.__init__(self, parent) 3029 self.count = 0 3030 self.reserved = 0 3031 self.remaining = 0 3032 self.write_channel_info_offset = 0 3033 self.write_channel_info_length = 0
3034
3035 - def _decode(self, cur):
3036 self.reserved = cur.decode_uint16le() 3037 self.count = cur.decode_uint32le() 3038 self.remaining = cur.decode_uint32le() 3039 self.write_channel_info_offset = cur.decode_uint16le() 3040 self.write_channel_info_length = cur.decode_uint16le()
3041
3042 -class LockFlags(core.FlagEnum):
3043 SMB2_LOCKFLAG_SHARED_LOCK = 0x00000001 3044 SMB2_LOCKFLAG_EXCLUSIVE_LOCK = 0x00000002 3045 SMB2_LOCKFLAG_UN_LOCK = 0x00000004 3046 SMB2_LOCKFLAG_FAIL_IMMEDIATELY = 0x00000010
3047 3048 LockFlags.import_items(globals())
3049 3050 -class LockRequest(Request):
3051 """ 3052 @ivar locks: A list of lock tuples, each of which consists of (offset, length, flags). 3053 """ 3054 command_id = SMB2_LOCK 3055 structure_size = 48 3056
3057 - def __init__(self, parent):
3058 Request.__init__(self, parent) 3059 self.file_id = None 3060 self.lock_sequence = 0 3061 self.locks = [] 3062 self.lock_count = None
3063
3064 - def _encode(self, cur):
3065 if self.lock_count == None: 3066 self.lock_count = len(self.locks) 3067 cur.encode_uint16le(self.lock_count) 3068 cur.encode_uint32le(self.lock_sequence) 3069 cur.encode_uint64le(self.file_id[0]) 3070 cur.encode_uint64le(self.file_id[1]) 3071 3072 for lock in self.locks: 3073 # Offset 3074 cur.encode_uint64le(lock[0]) 3075 # Length 3076 cur.encode_uint64le(lock[1]) 3077 # Flags 3078 cur.encode_uint32le(lock[2]) 3079 # Reserved 3080 cur.encode_uint32le(0)
3081
3082 -class LockResponse(Response):
3083 command_id = SMB2_LOCK 3084 structure_size = 4 3085
3086 - def __init__(self, parent):
3087 Response.__init__(self, parent)
3088
3089 - def _decode(self, cur):
3090 self.reserved = cur.decode_uint16le()
3091
3092 -class IoctlCode(core.ValueEnum):
3093 FSCTL_DFS_GET_REFERRALS = 0x00060194 3094 FSCTL_PIPE_PEEK = 0x0011400C 3095 FSCTL_PIPE_WAIT = 0x00110018 3096 FSCTL_PIPE_TRANSCEIVE = 0x0011C017 3097 FSCTL_SRV_COPYCHUNK = 0x001440F2 3098 FSCTL_SRV_ENUMERATE_SNAPSHOTS = 0x00144064 3099 FSCTL_SRV_REQUEST_RESUME_KEY = 0x00140078 3100 FSCTL_SRV_READ_HASH = 0x001441bb 3101 FSCTL_SRV_COPYCHUNK_WRITE = 0x001480F2 3102 FSCTL_LMR_REQUEST_RESILIENCY = 0x001401D4 3103 FSCTL_QUERY_NETWORK_INTERFACE_INFO = 0x001401FC 3104 FSCTL_SET_REPARSE_POINT = 0x000900A4 3105 FSCTL_GET_REPARSE_POINT = 0x000900A8 3106 FSCTL_DFS_GET_REFERRALS_EX = 0x000601B0 3107 FSCTL_FILE_LEVEL_TRIM = 0x00098208 3108 FSCTL_VALIDATE_NEGOTIATE_INFO = 0x00140204
3109 3110 IoctlCode.import_items(globals())
3111 3112 -class IoctlFlags(core.FlagEnum):
3113 SMB2_0_IOCTL_IS_FSCTL = 0x00000001
3114 3115 IoctlFlags.import_items(globals())
3116 3117 -class IoctlRequest(Request):
3118 command_id = SMB2_IOCTL 3119 structure_size = 57 3120 3121 field_blacklist = ['ioctl_input'] 3122
3123 - def __init__(self, parent):
3124 Request.__init__(self, parent) 3125 self.ctl_code = None 3126 # MS-SMB2 says that the file ID should be set to 0xffffffffffffffff for 3127 # certain IOCTLs. Assuming that means both persistent and volatile. 3128 self.file_id = (0xffffffffffffffff, 0xffffffffffffffff) 3129 self.input_offset = None 3130 self.input_count = None 3131 self.max_input_response = 0 3132 self.output_offset = 0 3133 self.output_count = 0 3134 self.max_output_response = 256 3135 self.flags = 0 3136 self.buffer = None 3137 self.ioctl_input = None
3138
3139 - def _children(self):
3140 return [self.ioctl_input] if self.ioctl_input is not None else []
3141
3142 - def _encode(self, cur):
3143 if not self.ctl_code: 3144 self.ctl_code = self[0].ioctl_ctl_code 3145 3146 # Reserved should be set to 0 3147 cur.encode_uint16le(0) 3148 cur.encode_uint32le(self.ctl_code) 3149 cur.encode_uint64le(self.file_id[0]) 3150 cur.encode_uint64le(self.file_id[1]) 3151 # Create holes where we will fill in offset and count later 3152 input_offset_hole = cur.hole.encode_uint32le(0) 3153 input_count_hole = cur.hole.encode_uint32le(0) 3154 cur.encode_uint32le(self.max_input_response) 3155 #For requests, output offset and count should be 0 3156 cur.encode_uint32le(self.output_offset) 3157 cur.encode_uint32le(self.output_count) 3158 cur.encode_uint32le(self.max_output_response) 3159 cur.encode_uint32le(self.flags) 3160 # Reserved2 should be set to 0 3161 cur.encode_uint32le(0) 3162 3163 buffer_start = cur.copy() 3164 input_offset_hole(buffer_start - self.parent.start) 3165 3166 # Encode the ioctl 3167 self.ioctl_input.encode(cur) 3168 # Set the ioctl count, which is the length in bytes 3169 input_count_hole(cur - buffer_start)
3170
3171 -class IoctlResponse(Response):
3172 command_id = SMB2_IOCTL 3173 structure_size = 49 3174 3175 field_blacklist = ['ioctl_output'] 3176 3177 # Set up a map so that the correct IoctlOutput frame decoder will be called, 3178 # based on the ioctl_ctl_code defined in the IoctlOutput 3179 _ioctl_ctl_code_map = {} 3180 ioctl_ctl_code = core.Register(_ioctl_ctl_code_map, "ioctl_ctl_code") 3181
3182 - def __init__(self, parent):
3183 Response.__init__(self, parent) 3184 self._ioctl_output = None
3185
3186 - def _children(self):
3187 return [self.ioctl_output] if self.ioctl_output is not None else []
3188
3189 - def _decode(self, cur):
3190 self.reserved = cur.decode_uint16le() 3191 self.ctl_code = IoctlCode(cur.decode_uint32le()) 3192 self.file_id = (cur.decode_uint64le(), cur.decode_uint64le()) 3193 self.input_offset = cur.decode_uint32le() 3194 self.input_count = cur.decode_uint32le() 3195 self.output_offset = cur.decode_uint32le() 3196 self.output_count = cur.decode_uint32le() 3197 self.flags = cur.decode_uint32le() 3198 self.reserved2 = cur.decode_uint32le() 3199 3200 cur.advanceto(self.parent.start + self.output_offset) 3201 end = cur + self.output_count 3202 3203 ioctl = self._ioctl_ctl_code_map[self.ctl_code] 3204 with cur.bounded(cur, end): 3205 ioctl(self).decode(cur)
3206
3207 -class IoctlInput(core.Frame):
3208 - def __init__(self, parent):
3209 super(IoctlInput, self).__init__(parent) 3210 if parent is not None: 3211 parent.ioctl_input = self
3212
3213 -class ValidateNegotiateInfoRequest(IoctlInput):
3214 ioctl_ctl_code = FSCTL_VALIDATE_NEGOTIATE_INFO 3215
3216 - def __init__(self, parent):
3217 IoctlInput.__init__(self, parent) 3218 self.capabilities = None 3219 self.client_guid = None 3220 self.security_mode = None 3221 self.dialects_count = None 3222 self.dialects = None
3223
3224 - def _encode(self, cur):
3225 cur.encode_uint32le(self.capabilities) 3226 cur.encode_bytes(self.client_guid) 3227 cur.encode_uint16le(self.security_mode) 3228 3229 # If dialects_count was not set manually, calculate it here. 3230 if self.dialects_count is None: 3231 self.dialects_count = len(self.dialects) 3232 cur.encode_uint16le(self.dialects_count) 3233 3234 for dialect in self.dialects: 3235 cur.encode_uint16le(dialect)
3236
3237 -class RequestResumeKeyRequest(IoctlInput):
3238 ioctl_ctl_code = FSCTL_SRV_REQUEST_RESUME_KEY 3239
3240 - def __init__(self, parent):
3241 IoctlInput.__init__(self, parent) 3242 parent.ioctl_input = self
3243
3244 - def _encode(self, cur):
3245 pass
3246
3247 -class CopyChunkCopyRequest(IoctlInput):
3248 ioctl_ctl_code = FSCTL_SRV_COPYCHUNK 3249
3250 - def __init__(self, parent):
3251 IoctlInput.__init__(self, parent) 3252 self.source_key = 0 3253 self.chunk_count = 0 3254 self._children = []
3255
3256 - def append(self, child):
3257 self._children.append(child)
3258
3259 - def _encode(self, cur):
3260 cur.encode_bytes(self.source_key) 3261 cur.encode_uint32le(self.chunk_count) 3262 cur.encode_uint32le(0) # reserved 3263 #encode the chunks 3264 for chunk in self._children: 3265 chunk.encode(cur)
3266
3267 -class CopyChunk(core.Frame):
3268 - def __init__(self, parent):
3269 core.Frame.__init__(self, parent) 3270 parent.append(self) 3271 self.source_offset = 0 3272 self.target_offset = 0 3273 self.length = 0
3274
3275 - def _encode(self, cur):
3276 cur.encode_uint64le(self.source_offset) 3277 cur.encode_uint64le(self.target_offset) 3278 cur.encode_uint32le(self.length) 3279 cur.encode_uint32le(0)
3280
3281 -class SetReparsePointRequest(IoctlInput):
3282 ioctl_ctl_code = FSCTL_SET_REPARSE_POINT 3283
3284 - def __init__(self, parent):
3285 IoctlInput.__init__(self, parent) 3286 self.reparse_data = None
3287
3288 - def _encode(self, cur):
3289 if self.reparse_data is not None: 3290 self.reparse_data.encode(cur)
3291
3292 -class GetReparsePointRequest(IoctlInput):
3293 ioctl_ctl_code = FSCTL_GET_REPARSE_POINT 3294
3295 - def _encode(self, *args, **kwds):
3296 pass
3297
3298 -class EnumerateSnapshotsRequest(IoctlInput):
3299 ioctl_ctl_code = FSCTL_SRV_ENUMERATE_SNAPSHOTS 3300
3301 - def _encode(self, *args, **kwds):
3302 pass
3303 3304 @IoctlResponse.ioctl_ctl_code
3305 -class IoctlOutput(core.Frame):
3306 - def __init__(self, parent):
3307 super(IoctlOutput, self).__init__(parent) 3308 if parent is not None: 3309 parent.ioctl_output = self
3310
3311 -class ValidateNegotiateInfoResponse(IoctlOutput):
3312 ioctl_ctl_code = FSCTL_VALIDATE_NEGOTIATE_INFO 3313
3314 - def __init__(self, parent):
3315 IoctlOutput.__init__(self, parent) 3316 self.capabilities = None 3317 self.guid = None 3318 self.security_mode = None 3319 self.dialect = None
3320
3321 - def _decode(self, cur):
3322 self.capabilities = GlobalCaps(cur.decode_uint32le()) 3323 self.client_guid = cur.decode_bytes(16) 3324 self.security_mode = SecurityMode(cur.decode_uint16le()) 3325 self.dialect = Dialect(cur.decode_uint16le())
3326
3327 -class RequestResumeKeyResponse(IoctlOutput):
3328 ioctl_ctl_code = FSCTL_SRV_REQUEST_RESUME_KEY 3329
3330 - def __init__(self, parent):
3331 IoctlOutput.__init__(self, parent) 3332 self.resume_key = array.array('B',[0]*24) 3333 self.context_length = 0
3334
3335 - def _decode(self, cur):
3336 self.resume_key = cur.decode_bytes(24) 3337 self.context_length = cur.decode_uint32le()
3338
3339 -class CopyChunkCopyResponse(IoctlOutput):
3340 ioctl_ctl_code = FSCTL_SRV_COPYCHUNK 3341
3342 - def __init__(self, parent):
3343 IoctlOutput.__init__(self, parent) 3344 self.chunks_written = 0 3345 self.chunk_bytes_written = 0 3346 self.total_bytes_written = 0
3347
3348 - def _decode(self, cur):
3349 self.chunks_written = cur.decode_uint32le() 3350 self.chunk_bytes_written = cur.decode_uint32le() 3351 self.total_bytes_written = cur.decode_uint32le()
3352
3353 -class SetReparsePointResponse(IoctlOutput):
3354 ioctl_ctl_code = FSCTL_SET_REPARSE_POINT
3355 - def _decode(self, *args, **kwds):
3356 pass
3357
3358 -class GetReparsePointResponse(IoctlOutput):
3359 ioctl_ctl_code = FSCTL_GET_REPARSE_POINT 3360 3361 field_blacklist = ['reparse_data'] 3362 _reparse_tag_map = {} 3363 reparse_tag = core.Register(_reparse_tag_map, "reparse_tag") 3364
3365 - def __init__(self, parent):
3366 IoctlOutput.__init__(self, parent) 3367 self.tag = 0
3368
3369 - def _children(self):
3370 return [self.reparse_data] if self.reparse_data is not None else []
3371
3372 - def _decode(self, cur):
3373 self.tag = cur.decode_uint32le() 3374 reparse_data = self._reparse_tag_map[self.tag] 3375 reparse_data(self).decode(cur)
3376 3377 @GetReparsePointResponse.reparse_tag
3378 -class ReparseDataBuffer(core.Frame):
3379 - def __init__(self, parent):
3380 super(ReparseDataBuffer, self).__init__(parent) 3381 if parent is not None: 3382 parent.reparse_data = self
3383
3384 -class SymbolicLinkFlags(core.FlagEnum):
3385 SYMLINK_FLAG_ABSOLUTE = 0x0 3386 SYMLINK_FLAG_RELATIVE = 0x1
3387 SymbolicLinkFlags.import_items(globals())
3388 3389 -class SymbolicLinkReparseBuffer(ReparseDataBuffer):
3390 reparse_tag = 0xA000000C 3391
3392 - def __init__(self, parent):
3393 super(SymbolicLinkReparseBuffer, self).__init__(parent) 3394 self.unparsed_path_length = 0 # for ErrorResponse only 3395 self.substitute_name = None 3396 self.substitute_name_length = None 3397 self.substitute_name_offset = 0 3398 self.print_name = None 3399 self.print_name_length = None 3400 self.print_name_offset = None 3401 self.flags = 0
3402
3403 - def _encode(self, cur):
3404 cur.encode_uint32le(self.reparse_tag) 3405 reparse_data_length_hole = cur.hole.encode_uint16le(0) 3406 cur.encode_uint16le(0) # reserved 3407 reparse_data_len_start = cur.copy() 3408 cur.encode_uint16le(self.substitute_name_offset) 3409 sname_len_hole = cur.hole.encode_uint16le(0) 3410 pname_offset_hole = cur.hole.encode_uint16le(0) 3411 pname_len_hole = cur.hole.encode_uint16le(0) 3412 cur.encode_uint32le(self.flags) 3413 3414 sname_start = cur.copy() 3415 cur.encode_utf16le(self.substitute_name) 3416 if self.substitute_name_length is None: 3417 self.substitute_name_length = cur - sname_start 3418 sname_len_hole(self.substitute_name_length) 3419 3420 if self.print_name is None: 3421 self.print_name = self.substitute_name 3422 pname_start = cur.copy() 3423 if self.print_name_offset is None: 3424 self.print_name_offset = self.substitute_name_length 3425 pname_offset_hole(self.print_name_offset) 3426 cur.encode_utf16le(self.print_name) 3427 if self.print_name_length is None: 3428 self.print_name_length = cur - pname_start 3429 pname_len_hole(self.print_name_length) 3430 3431 reparse_data_length_hole(cur - reparse_data_len_start)
3432
3433 - def _decode(self, cur):
3434 reparse_data_length = cur.decode_uint16le() 3435 self.unparsed_path_length = cur.decode_uint16le() 3436 self.substitute_name_offset = cur.decode_uint16le() 3437 self.substitute_name_length = cur.decode_uint16le() 3438 self.print_name_offset = cur.decode_uint16le() 3439 self.print_name_length = cur.decode_uint16le() 3440 self.flags = cur.decode_uint32le() 3441 3442 buf_start = cur.copy() 3443 self.substitute_name = cur.decode_utf16le(self.substitute_name_length) 3444 cur.seekto(buf_start + self.print_name_offset) 3445 self.print_name = cur.decode_utf16le(self.print_name_length)
3446
3447 -class EnumerateSnapshotsResponse(IoctlOutput):
3448 ioctl_ctl_code = FSCTL_SRV_ENUMERATE_SNAPSHOTS 3449
3450 - def __init__(self, parent):
3451 super(EnumerateSnapshotsResponse, self).__init__(parent) 3452 self.number_of_snapshots = 0 3453 self.number_of_snapshots_returns = 0 3454 self.snapshot_array_size = 0 3455 self.snapshots = []
3456
3457 - def _decode(self, cur):
3458 self.number_of_snapshots = cur.decode_uint32le() 3459 self.number_of_snapshots_returned = cur.decode_uint32le() 3460 self.snapshot_array_size = cur.decode_uint32le() 3461 snapshot_buffer = cur.decode_utf16le(self.snapshot_array_size) 3462 # TODO: handle the case where the buffer is too small 3463 self.snapshots = snapshot_buffer.strip("\0").split("\0")
3464