This commit is contained in:
Max Goedjen
2025-09-06 17:30:05 -07:00
parent 11074999ad
commit 2efba1bc21
6 changed files with 70 additions and 37 deletions

View File

@@ -45,6 +45,8 @@ extension Agent {
response.append(SSHAgent.Response.agentSignResponse.data)
response.append(try await sign(data: context.dataToSign, keyBlob: context.keyBlob, provenance: provenance))
logger.debug("Agent returned \(SSHAgent.Response.agentSignResponse.debugDescription)")
case .unknown(let value):
logger.error("Agent received unknown request of type \(value).")
default:
logger.debug("Agent received valid request of type \(request.debugDescription), but not currently supported.")
throw UnhandledRequestError()

View File

@@ -7,25 +7,25 @@ final class OpenSSHReader {
/// Initialize the reader with an OpenSSH data payload.
/// - Parameter data: The data to read.
public init(data: Data) {
init(data: Data) {
remaining = Data(data)
}
/// Reads the next chunk of data from the playload.
/// - Returns: The next chunk of data.
public func readNextChunk(convertEndianness: Bool = true) throws -> Data {
func readNextChunk(convertEndianness: Bool = true) throws(OpenSSHReaderError) -> Data {
let littleEndianLength = try readNextBytes(as: UInt32.self)
let length = convertEndianness ? Int(littleEndianLength.bigEndian) : Int(littleEndianLength)
guard remaining.count >= length else { throw EndOfData() }
guard remaining.count >= length else { throw .beyondBounds }
let dataRange = 0..<length
let ret = Data(remaining[dataRange])
remaining.removeSubrange(dataRange)
return ret
}
public func readNextBytes<T>(as: T.Type) throws -> T {
func readNextBytes<T>(as: T.Type) throws(OpenSSHReaderError) -> T {
let size = MemoryLayout<T>.size
guard remaining.count >= size else { throw EndOfData() }
guard remaining.count >= size else { throw .beyondBounds }
let lengthRange = 0..<size
let lengthChunk = remaining[lengthRange]
remaining.removeSubrange(lengthRange)
@@ -33,10 +33,12 @@ final class OpenSSHReader {
}
public func readNextChunkAsString() throws -> String {
func readNextChunkAsString() throws -> String {
try String(decoding: readNextChunk(), as: UTF8.self)
}
public struct EndOfData: Error {}
}
public enum OpenSSHReaderError: Error, Codable {
case beyondBounds
}

View File

@@ -16,10 +16,10 @@ public struct SSHAgentInputParser: SSHAgentInputParserProtocol {
}
public func parse(data: Data) throws -> SSHAgent.Request {
public func parse(data: Data) throws(AgentParsingError) -> SSHAgent.Request {
logger.debug("Parsing new data")
guard data.count > 4 else {
throw InvalidDataProvidedError()
throw .invalidData
}
let specifiedLength = (data[0..<4].bytes.unsafeLoad(as: UInt32.self).bigEndian) + 4
let rawRequestInt = data[4]
@@ -29,7 +29,11 @@ public struct SSHAgentInputParser: SSHAgentInputParserProtocol {
case SSHAgent.Request.requestIdentities.protocolID:
return .requestIdentities
case SSHAgent.Request.signRequest(.empty).protocolID:
return .signRequest(try signatureRequestContext(from: body))
do {
return .signRequest(try signatureRequestContext(from: body))
} catch {
throw .openSSHReader(error)
}
case SSHAgent.Request.addIdentity.protocolID:
return .addIdentity
case SSHAgent.Request.removeIdentity.protocolID:
@@ -59,7 +63,7 @@ public struct SSHAgentInputParser: SSHAgentInputParserProtocol {
extension SSHAgentInputParser {
func signatureRequestContext(from data: Data) throws -> SSHAgent.Request.SignatureRequestContext {
func signatureRequestContext(from data: Data) throws(OpenSSHReaderError) -> SSHAgent.Request.SignatureRequestContext {
let reader = OpenSSHReader(data: data)
let rawKeyBlob = try reader.readNextChunk()
let keyBlob = certificatePublicKeyBlob(from: rawKeyBlob) ?? rawKeyBlob
@@ -95,8 +99,11 @@ extension SSHAgentInputParser {
extension SSHAgentInputParser {
struct AgentUnknownRequestError: Error {}
struct AgentUnhandledRequestError: Error {}
struct InvalidDataProvidedError: Error {}
public enum AgentParsingError: Error, Codable {
case unknownRequest
case unhandledRequest
case invalidData
case openSSHReader(OpenSSHReaderError)
}
}