Skip to content

Commit

Permalink
Use Super agent as Super instead of delegate
Browse files Browse the repository at this point in the history
- In the agent's chain the original idea was that the Super would be called
first. That would allow the Default Agent to get priority over the Host agent.
We did not implement it this way because for most cases, it is more efficient to
go with the host, but it was breaking what the user expected #1823.
- Clean ups as adding a key to the ring cannot fail.
- Implements #1849
  • Loading branch information
Carlos Cabanero committed Sep 7, 2023
1 parent 6c41dcd commit 83328c4
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 32 deletions.
2 changes: 1 addition & 1 deletion Blink/Commands/ssh/SSHConfigProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ extension SSHClientConfigProvider {
if let signer = signer as? BlinkConfig.InputPrompter {
signer.setPromptOnView(device.view)
}
_ = agent.loadKey(signer, aka: name, constraints: consts)
agent.loadKey(signer, aka: name, constraints: consts)
}

// Link to Default Agent
Expand Down
2 changes: 1 addition & 1 deletion Blink/Commands/ssh/ssh.swift
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ public func blink_ssh_main(argc: Int32, argv: Argv) -> Int32 {
let _allIdentities = BKPubKey.all()
for keyName in bkHost.agentForwardKeys {
if let signer = _allIdentities.signerWithID(keyName) {
_ = agent.loadKey(signer, aka: keyName, constraints: constraints)
agent.loadKey(signer, aka: keyName, constraints: constraints)
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions BlinkCode/CodeFileSystemService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -237,12 +237,12 @@ class SSHClientFileProviderConfig {

if let signers = bkConfig.signer(forHost: host) {
signers.forEach { (signer, name) in
_ = agent.loadKey(signer, aka: name, constraints: consts)
agent.loadKey(signer, aka: name, constraints: consts)
}
}

for (signer, name) in bkConfig.defaultSigners() {
_ = agent.loadKey(signer, aka: name, constraints: consts)
agent.loadKey(signer, aka: name, constraints: consts)
}

var availableAuthMethods: [AuthMethod] = [AuthAgent(agent)]
Expand Down
4 changes: 2 additions & 2 deletions BlinkFileProvider/Models/FileTranslatorCache.swift
Original file line number Diff line number Diff line change
Expand Up @@ -196,11 +196,11 @@ class SSHClientConfigProvider {

if let signers = bkConfig.signer(forHost: host) {
signers.forEach { (signer, name) in
_ = agent.loadKey(signer, aka: name, constraints: consts)
agent.loadKey(signer, aka: name, constraints: consts)
}
} else {
for (signer, name) in bkConfig.defaultSigners() {
_ = agent.loadKey(signer, aka: name, constraints: consts)
agent.loadKey(signer, aka: name, constraints: consts)
}
}

Expand Down
50 changes: 24 additions & 26 deletions SSH/Agent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -122,17 +122,16 @@ public class SSHAgent {
ssh_set_agent_callback(client.session, cb, ctxt)
}

public func loadKey(_ key: Signer, aka name: String, constraints: [SSHAgentConstraint]? = nil) -> Bool {
public func loadKey(_ key: Signer, aka name: String, constraints: [SSHAgentConstraint]? = nil) {
let cKey = SSHAgentKey(key, named: name, constraints: constraints)
for (x, k) in ring.enumerated() {
if cKey.name == k.name {
// Replace the key
ring[x] = cKey
break
return
}
}
ring.append(cKey)
return true
}

public func removeKey(_ name: String) -> Signer? {
Expand All @@ -155,9 +154,11 @@ public class SSHAgent {

return ring.reduce(preamble) { $0 + $1 }
case .requestSignature:
let signature = try encodedSignature(message, for: client)
guard let signature = try encodedSignature(message, for: client) else {
throw SSHKeyError.general(title: "Could not find proposed key")
}
var respType = SSHAgentResponseType.responseSignature.rawValue

return Data(bytes: &respType, count: MemoryLayout<CChar>.size)
+ signature
// default:
Expand All @@ -166,38 +167,35 @@ public class SSHAgent {
}

func encodedRing() throws -> [Data] {
(try ring.map { (try $0.signer.publicKey.encode()) + SSHEncode.data(from: $0.name) }) +
(try superAgent?.encodedRing() ?? [])
(try superAgent?.encodedRing() ?? []) +
(try ring.map { (try $0.signer.publicKey.encode()) + SSHEncode.data(from: $0.name) })
}

func encodedSignature(_ message: Data, for client: SSHClient) throws -> Data {
func encodedSignature(_ message: Data, for client: SSHClient) throws -> Data? {

var msg = message
let keyBlob = SSHDecode.bytes(&msg)
let data = SSHDecode.bytes(&msg)
let flags = SSHDecode.uint32(&msg)

do {
guard let key = lookupKey(blob: keyBlob) else {
throw SSHKeyError.general(title: "Could not find proposed key")
}

let algorithm: String? = SigDecodingAlgorithm(rawValue: Int8(flags)).algorithm(for: key.signer)
if let signature = try superAgent?.encodedSignature(message, for: client) {
return signature
}

// Enforce constraints
try key.constraints?.forEach {
if !$0.enforce(useOf: key, by: client) { throw SSHKeyError.general(title: "Denied operation by constraint: \($0.name).") }
}
guard let key = lookupKey(blob: keyBlob) else {
return nil
}

let signature = try key.signer.sign(data, algorithm: algorithm)

return SSHEncode.data(from: signature)
} catch {
guard let superAgent = self.superAgent else {
throw error
}
return try superAgent.encodedSignature(message, for: client)
let algorithm: String? = SigDecodingAlgorithm(rawValue: Int8(flags)).algorithm(for: key.signer)

// Enforce constraints
try key.constraints?.forEach {
if !$0.enforce(useOf: key, by: client) { throw SSHKeyError.general(title: "Denied operation by constraint: \($0.name).") }
}

let signature = try key.signer.sign(data, algorithm: algorithm)

return SSHEncode.data(from: signature)
}

fileprivate func lookupKey(blob: Data) -> SSHAgentKey? {
Expand Down

0 comments on commit 83328c4

Please sign in to comment.