mirror of
https://github.com/maxgoedjen/secretive.git
synced 2025-08-31 01:20:57 +00:00
fix: partial data read issue
This commit is contained in:
parent
b5f2dfd153
commit
575cf7658f
@ -37,16 +37,24 @@ extension Agent {
|
|||||||
/// - Boolean if data could be read
|
/// - Boolean if data could be read
|
||||||
@discardableResult public func handle(reader: FileHandleReader, writer: FileHandleWriter) async -> Bool {
|
@discardableResult public func handle(reader: FileHandleReader, writer: FileHandleWriter) async -> Bool {
|
||||||
logger.debug("Agent handling new data")
|
logger.debug("Agent handling new data")
|
||||||
let data = Data(reader.availableData)
|
let newData = reader.availableData
|
||||||
guard data.count > 4 else { return false}
|
|
||||||
let requestTypeInt = data[4]
|
// If client closed the connection, availableData will be empty
|
||||||
|
guard !newData.isEmpty else { return false }
|
||||||
|
|
||||||
|
guard let message = reader.appendAndParseMessage(from: newData) else {
|
||||||
|
return true // only return true if we received something
|
||||||
|
}
|
||||||
|
|
||||||
|
guard message.count >= 1 else { return false }
|
||||||
|
let requestTypeInt = message[0]
|
||||||
guard let requestType = SSHAgent.RequestType(rawValue: requestTypeInt) else {
|
guard let requestType = SSHAgent.RequestType(rawValue: requestTypeInt) else {
|
||||||
writer.write(OpenSSHKeyWriter().lengthAndData(of: SSHAgent.ResponseType.agentFailure.data))
|
writer.write(OpenSSHKeyWriter().lengthAndData(of: SSHAgent.ResponseType.agentFailure.data))
|
||||||
logger.debug("Agent returned \(SSHAgent.ResponseType.agentFailure.debugDescription)")
|
logger.debug("Agent returned \(SSHAgent.ResponseType.agentFailure.debugDescription)")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
logger.debug("Agent handling request of type \(requestType.debugDescription)")
|
logger.debug("Agent handling request of type \(requestType.debugDescription)")
|
||||||
let subData = Data(data[5...])
|
let subData = Data(message.dropFirst())
|
||||||
let response = await handle(requestType: requestType, data: subData, reader: reader)
|
let response = await handle(requestType: requestType, data: subData, reader: reader)
|
||||||
writer.write(response)
|
writer.write(response)
|
||||||
return true
|
return true
|
||||||
|
@ -9,6 +9,8 @@ public protocol FileHandleReader: Sendable {
|
|||||||
var fileDescriptor: Int32 { get }
|
var fileDescriptor: Int32 { get }
|
||||||
/// The process ID of the process coonnected to the other end of the FileHandle.
|
/// The process ID of the process coonnected to the other end of the FileHandle.
|
||||||
var pidOfConnectedProcess: Int32 { get }
|
var pidOfConnectedProcess: Int32 { get }
|
||||||
|
/// Append data to a buffer and extract the next SSH message if available.
|
||||||
|
func appendAndParseMessage(from newData: Data) -> Data?
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,6 +22,23 @@ public protocol FileHandleWriter: Sendable {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SSHMessageBuffer for reassembly
|
||||||
|
final class SSHMessageBuffer {
|
||||||
|
private var buffer = Data()
|
||||||
|
func append(_ newData: Data) {
|
||||||
|
buffer.append(newData)
|
||||||
|
}
|
||||||
|
func nextMessage() -> Data? {
|
||||||
|
guard buffer.count >= 4 else { return nil }
|
||||||
|
let length = buffer.prefix(4).withUnsafeBytes { $0.load(as: UInt32.self).bigEndian }
|
||||||
|
guard length < 1_000_000 else { return nil }
|
||||||
|
guard buffer.count >= 4 + Int(length) else { return nil }
|
||||||
|
let message = buffer.subdata(in: 4..<4+Int(length))
|
||||||
|
buffer.removeSubrange(0..<4+Int(length))
|
||||||
|
return message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extension FileHandle: FileHandleReader, FileHandleWriter {
|
extension FileHandle: FileHandleReader, FileHandleWriter {
|
||||||
|
|
||||||
public var pidOfConnectedProcess: Int32 {
|
public var pidOfConnectedProcess: Int32 {
|
||||||
@ -29,4 +48,15 @@ extension FileHandle: FileHandleReader, FileHandleWriter {
|
|||||||
return pidPointer.load(as: Int32.self)
|
return pidPointer.load(as: Int32.self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static var messageBuffers = [Int32: SSHMessageBuffer]()
|
||||||
|
private static let messageBuffersLock = NSLock()
|
||||||
|
public func appendAndParseMessage(from newData: Data) -> Data? {
|
||||||
|
let fd = self.fileDescriptor
|
||||||
|
FileHandle.messageBuffersLock.lock()
|
||||||
|
let buffer = FileHandle.messageBuffers[fd] ?? SSHMessageBuffer()
|
||||||
|
FileHandle.messageBuffers[fd] = buffer
|
||||||
|
FileHandle.messageBuffersLock.unlock()
|
||||||
|
buffer.append(newData)
|
||||||
|
return buffer.nextMessage()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user