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

Fixed licensing issue and added licensing boilerplate #118

Merged
merged 2 commits into from
Jul 2, 2019
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
4 changes: 3 additions & 1 deletion pyrdp/layer/rdp/security.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,9 @@ def __init__(self, parser = BasicSecurityParser()):
self.securityHeaderExpected = False

def recv(self, data: bytes):
if not self.securityHeaderExpected:
# Licensing happens in the security layer
licensingBytes = b"\x80\x00"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that correspond to a flag?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is, but since this isn't parsed data, it is not in the correct format. Would it be better if I refer to this flag, and parse the 0x80\x00 and compare to the flag?

In pyrdp/enum/rdp.py - line 43
SEC_LICENSE_PKT = 0x0080

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah for that @xshill would have a better idea than me. I have an idea but i’m really not sure if its good

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The licensingBytes you're looking for IS part of a security header. You shouldn't need to check for that if securityHeaderExpected is set properly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Licensing is an optional part of the protocol, and the boolean "securityHeaderExpected" is false when receiving a licensing PDU. securityHeaderExpected is only used to redirect traffic to the securityLayer when we know we are expecting it in the handshake

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh right, since this is TLS it starts at false.

if not self.securityHeaderExpected and data[0:2] != licensingBytes:
if self.next is not None:
self.next.recv(data)
else:
Expand Down
18 changes: 15 additions & 3 deletions pyrdp/mitm/SecurityMITM.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,13 @@ def __init__(self, client: SecurityLayer, server: SecurityLayer, log: LoggerAdap
self.recorder = recorder

self.client.createObserver(
onLicensingDataReceived = self.onClientLicensingData,
onSecurityExchangeReceived = self.onSecurityExchange,
onClientInfoReceived=self.onClientInfo,
)

self.server.createObserver(
onLicensingDataReceived = self.onLicensingData
onLicensingDataReceived = self.onServerLicensingData,
)

def onSecurityExchange(self, pdu: SecurityExchangePDU):
Expand Down Expand Up @@ -94,7 +95,7 @@ def onClientInfo(self, data: bytes):
self.log.debug("Sending %(pdu)s", {"pdu": pdu})
self.server.sendClientInfo(pdu)

def onLicensingData(self, data: bytes):
def onServerLicensingData(self, data: bytes):
"""
Forward licensing data to the client and disable security headers if TLS is in use.
:param data: the licensing data
Expand All @@ -103,4 +104,15 @@ def onLicensingData(self, data: bytes):
self.client.securityHeaderExpected = False
self.server.securityHeaderExpected = False

self.client.sendLicensing(data)
self.client.sendLicensing(data)

def onClientLicensingData(self, data: bytes):
"""
Forward licensing data to the server and disable security headers if TLS is in use.
:param data: the licensing data
"""
if self.state.useTLS:
self.client.securityHeaderExpected = False
self.server.securityHeaderExpected = False

self.server.sendLicensing(data)
36 changes: 36 additions & 0 deletions pyrdp/parser/rdp/licensing.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,15 @@ class LicensingParser(Parser):

def __init__(self):
super().__init__()

self.parsers = {
LicensingPDUType.LICENSE_REQUEST: self.parseLicenseRequest,
LicensingPDUType.PLATFORM_CHALLENGE: self.parsePlatformChallenge,
LicensingPDUType.NEW_LICENSE: self.parseNewLicense,
LicensingPDUType.UPGRADE_LICENSE: self.parseUpgradeLicense,
LicensingPDUType.LICENSE_INFO: self.parseLicenseInfo,
LicensingPDUType.NEW_LICENSE_REQUEST: self.parseNewLicenseRequest,
LicensingPDUType.PLATFORM_CHALLENGE_RESPONSE: self.parsePlatformChallengeResponse,
LicensingPDUType.ERROR_ALERT: self.parseErrorAlert,
}

Expand Down Expand Up @@ -52,6 +60,34 @@ def parseLicenseBlob(self, stream):
data = stream.read(length)
return LicenseBinaryBlob(type, data)

def parseLicenseRequest(self, stream, flags):
# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpele/a870d76a-639b-4757-9370-a9bdfbfd6961
raise ("parseLicenseRequest isn't implemented yet")

def parsePlatformChallenge(self, stream, flags):
# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpele/3e78e067-83a8-42b5-b5b3-054679ade7c7
raise ("parsePlatformChallenge isn't implemented yet")

def parseNewLicense(self, stream, flags):
# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpele/73c596f1-9550-4649-b880-2947c36c1bb6
raise ("parseNewLicense isn't implemented yet")

def parseUpgradeLicense(self, stream, flags):
# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpele/94f9f260-fe9d-4429-b3b5-228bef28bc5d
raise ("parseUpgradeLicense isn't implemented yet")

def parseLicenseInfo(self, stream, flags):
# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpele/9fea482b-f9e5-4175-9350-ac540a804eba
raise ("parseLicenseInfo isn't implemented yet")

def parseNewLicenseRequest(self, stream, flags):
# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpele/9b4e7ee7-9e85-46f0-9583-77cfd397864e
raise ("parseNewLicenseRequest isn't implemented yet")

def parsePlatformChallengeResponse(self, stream, flags):
# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpele/58e79794-58f8-4607-a510-c0b5fef49c40
raise ("parsePlatformChallengeResponse isn't implemented yet")

def parseErrorAlert(self, stream, flags):
"""
Parse the provided byte stream and return the corresponding RDPLicenseErrorAlertPDU
Expand Down