diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index a77b4113a..3fd8388aa 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -44,6 +44,7 @@ For a detailed view of what has changed, refer to the {uri-repo}/commits/master[ * Fixed `pyrdp-player` on macOS platforms ({uri-issue}362[#362]) * Fixed `pyrdp-convert` pcap processing when victim IP and MITM IP are the same ({uri-issue}366[#366]) * Fixed NLA redirection problems if original target and NLA redirection target are the same ({uri-issue}342[#342], {uri-issue}343[#343]) +* Fixed leak of file descriptors due to missing close on replay file recording ({uri-issue}392[#392], {uri-issue}413[#413]) * Added a missing dependency for the GUI on Ubuntu 20.04 LTS ({uri-issue}348[#348], {uri-issue}351[#351], {uri-issue}355[#355]) * No longer assuming every connection will have VirtualChannels ({uri-issue}375[#375]) * Some minor protocol-level fixes ({uri-issue}408[#408]) diff --git a/pyrdp/mitm/TCPMITM.py b/pyrdp/mitm/TCPMITM.py index dccec31d4..faafc98de 100644 --- a/pyrdp/mitm/TCPMITM.py +++ b/pyrdp/mitm/TCPMITM.py @@ -99,6 +99,7 @@ def onClientDisconnection(self, reason): if self.recorder.recordFilename: self.statCounter.logReport(self.log, {"replayFilename": self.recorder.recordFilename}) + self.recorder.finalize() else: self.statCounter.logReport(self.log) diff --git a/pyrdp/recording/recorder.py b/pyrdp/recording/recorder.py index 579e89505..41d7220d0 100644 --- a/pyrdp/recording/recorder.py +++ b/pyrdp/recording/recorder.py @@ -35,6 +35,7 @@ def __init__(self, transports: List[LayerChainItem]): } self.topLayers = [] + self.openFileLayers = [] self.recordFilename = None for transport in transports: @@ -52,6 +53,9 @@ def addTransport(self, transportLayer: LayerChainItem): player.setPrevious(transportLayer) self.topLayers.append(player) + if isinstance(transportLayer, FileLayer): + self.openFileLayers.append(transportLayer) + def setParser(self, messageType: PlayerPDUType, parser: Parser): """ Set the parser to use for a given message type. @@ -81,6 +85,11 @@ def record(self, pdu: Optional[PDU], messageType: PlayerPDUType): def getCurrentTimeStamp(self) -> int: return PlayerLayer.timeStampFunction() + def finalize(self): + """When the recording is finished""" + for layer in self.openFileLayers: + layer.close() + class FileLayer(LayerChainItem): """ @@ -114,3 +123,7 @@ def sendBytes(self, data: bytes): self.fd.write(data) else: log.error("Recording file handle closed, cannot write message: %(message)s", {"message": data}) + + def close(self): + if self.fd: + self.fd.close() \ No newline at end of file