This commit is contained in:
lollipopkit🏳️‍⚧️
2026-01-15 10:10:21 +08:00
parent 35349a90eb
commit 7d30af44d6
2 changed files with 23 additions and 26 deletions

View File

@@ -480,40 +480,34 @@ Future<void> ensureKnownHostKey(
Duration timeout = const Duration(seconds: 5),
SSHUserInfoRequestHandler? onKeyboardInteractive,
}) async {
return _ensureKnownHostKeyInternal(
var cache = _loadKnownHostFingerprints();
final hops = resolveMergedJumpChain(spi);
for (final hop in hops) {
cache = await _ensureKnownHostKeyForSingle(
hop,
cache: cache,
timeout: timeout,
onKeyboardInteractive: onKeyboardInteractive,
);
}
await _ensureKnownHostKeyForSingle(
spi,
cache: cache,
timeout: timeout,
onKeyboardInteractive: onKeyboardInteractive,
visited: <String>{},
);
}
Future<void> _ensureKnownHostKeyInternal(
Future<Map<String, String>> _ensureKnownHostKeyForSingle(
Spi spi, {
required Map<String, String> cache,
Duration timeout = const Duration(seconds: 5),
SSHUserInfoRequestHandler? onKeyboardInteractive,
required Set<String> visited,
}) async {
final identifier = _hostIdentifier(spi);
if (!visited.add(identifier)) {
throw SSHErr(type: SSHErrType.connect, message: 'Jump loop detected at ${spi.name} ($identifier)');
}
final cache = _loadKnownHostFingerprints();
if (_hasKnownHostFingerprintForSpi(spi, cache)) {
return;
}
final jumpSpi = spi.jumpId != null ? Stores.server.box.get(spi.jumpId) : null;
if (jumpSpi != null && !_hasKnownHostFingerprintForSpi(jumpSpi, cache)) {
await _ensureKnownHostKeyInternal(
jumpSpi,
timeout: timeout,
onKeyboardInteractive: onKeyboardInteractive,
visited: visited,
);
cache.addAll(_loadKnownHostFingerprints());
if (_hasKnownHostFingerprintForSpi(spi, cache)) return;
return cache;
}
final client = await genClient(
@@ -528,6 +522,9 @@ Future<void> _ensureKnownHostKeyInternal(
} finally {
client.close();
}
cache.addAll(_loadKnownHostFingerprints());
return cache;
}
bool _hasKnownHostFingerprintForSpi(Spi spi, Map<String, String> cache) {

View File

@@ -35,16 +35,16 @@ extension _JumpChain on _ServerEditPageState {
}
bool containsCycleWithCandidate(String candidateId) {
final visited = <String>{selfId};
final queue = [..._jumpChain.value, candidateId];
final directVisited = <String>{selfId};
for (final hopId in queue) {
if (hopId == selfId) return true;
if (!visited.add(hopId)) return true;
if (!directVisited.add(hopId)) return true;
}
for (final hopId in queue) {
final extra = flattenHopIds(hopId, visited: visited);
final extra = flattenHopIds(hopId, visited: <String>{selfId});
for (final id in extra) {
if (id == selfId) return true;
}