Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update session id logic #293

Merged
merged 1 commit into from
Oct 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## 1.14.1 - TBD

* Add workaround for Impackets logoff response not setting the session id for message verification
* Update session id lookup logic to comply with MS-SMB2 spec
* Remove connection from global connection cache even if failing to close it

## 1.14.0 - 2024-08-26
Expand Down
16 changes: 7 additions & 9 deletions src/smbprotocol/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -1356,16 +1356,14 @@
message_id = header["message_id"].get_value()
request = self.outstanding_requests[message_id]

# Typically you want to get the Session Id from the first message in a compound request but that is
# unreliable for async responses. Instead get the Session Id from the original request object if
# the Session Id is 0xFFFFFFFFFFFFFFFF.
# https://social.msdn.microsoft.com/Forums/en-US/a580f7bc-6746-4876-83db-6ac209b202c4/mssmb2-change-notify-response-sessionid?forum=os_fileservices
# Impacket also sets session id to 0 on the logoff response
# so fallback to the request for that one
# https://github.com/jborean93/smbprotocol/issues/289#issuecomment-2396040117.
# For SMB2 SESSION_SETUP, the client MUST retrieve SessionId
# from SMB2 header of the response. For all other messages,
# the client MUST retrieve SessionId from the corresponding
# Request.Message.
command = header["command"].get_value()
session_id = header["session_id"].get_value()
if session_id == 0xFFFFFFFFFFFFFFFF or (session_id == 0 and command == Commands.SMB2_LOGOFF):
if command == Commands.SMB2_SESSION_SETUP:
session_id = header["session_id"].get_value()

Check warning on line 1365 in src/smbprotocol/connection.py

View check run for this annotation

Codecov / codecov/patch

src/smbprotocol/connection.py#L1364-L1365

Added lines #L1364 - L1365 were not covered by tests
else:
session_id = request.session_id

# No need to waste CPU cycles to verify the signature if we already decrypted the header.
Expand Down
1 change: 1 addition & 0 deletions src/smbprotocol/header.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class NtStatus:
STATUS_STOPPED_ON_SYMLINK = 0x8000002D
STATUS_INVALID_INFO_CLASS = 0xC0000003
STATUS_INFO_LENGTH_MISMATCH = 0xC0000004
STATUS_INVALID_HANDLE = 0xC0000008
STATUS_INVALID_PARAMETER = 0xC000000D
STATUS_NO_SUCH_FILE = 0xC000000F
STATUS_INVALID_DEVICE_REQUEST = 0xC0000010
Expand Down
26 changes: 26 additions & 0 deletions tests/test_file_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from smbprotocol.file_info import (
FileAllInformation,
FileBasicInformation,
FileBothDirectoryInformation,
FileDirectoryInformation,
FileDispositionInformation,
Expand All @@ -27,6 +28,31 @@
from smbprotocol.structure import DateTimeField


class TestFileBasicInformation:

def test_parse_message(self):
data = (
b"\x00\xf2\xc4\x22\x2d\x1c\xdb\x01"
b"\x00\xf2\xc4\x22\x2d\x1c\xdb\x01"
b"\x00\xf2\xc4\x22\x2d\x1c\xdb\x01"
b"\x00\xf2\xc4\x22\x2d\x1c\xdb\x01"
b"\x10\x00\x00\x00"
b"\x00\x00\x00\x00"
)

actual = FileBasicInformation()
data = actual.unpack(data)
assert data == b""
assert len(actual) == 40

assert actual["creation_time"].get_value() == 133731594120000000
assert actual["last_access_time"].get_value() == 133731594120000000
assert actual["last_write_time"].get_value() == 133731594120000000
assert actual["change_time"].get_value() == 133731594120000000
assert actual["file_attributes"].get_value() == 0x10
assert actual["reserved"].get_value() == 0


class TestFileNameInformation:
DATA = b"\x08\x00\x00\x00" b"\x63\x00\x61\x00\x66\x00\xe9\x00"

Expand Down