Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
88e36fc
Add parameter disableHostkeyVerification
alexander-irion Mar 12, 2025
e32b132
Catch exceptions when sshd terminated
alexander-irion Mar 26, 2025
b0fdd01
Implemented support for server rekey (by default every 1 GB or 1 hour)
May 15, 2025
86805cb
According to RFC, we shouldn't send anything except KEX stuff when do…
May 15, 2025
dcce7af
Improved function to allow critical ssh messages through as well
May 15, 2025
bead8a8
Add support for new MAC mac-sha2-256-96", "hmac-sha2-512-96", "hmac-s…
reinbeumer Jun 18, 2025
81c6905
Corrected the ETM encryptions
reinbeumer Jun 19, 2025
c55e269
Corrected the ETM encryptions
reinbeumer Jun 19, 2025
cd3bc77
Format code
xtyxtyx Jun 22, 2025
40948ea
Merge pull request #123 from alexander-irion/master
xtyxtyx Jun 22, 2025
e29ba65
Merge pull request #125 from MarBazuz/feat/rekey
xtyxtyx Jun 22, 2025
364856d
Add more tests
xtyxtyx Jun 22, 2025
81cf1c5
Format code
xtyxtyx Jun 22, 2025
d9cd523
Merge branch 'master' into pr/reinbeumer/127
xtyxtyx Jun 22, 2025
25429ab
Format code
xtyxtyx Jun 22, 2025
3056782
Merge pull request #127 from reinbeumer/feature/algorithm-corrections
xtyxtyx Jun 22, 2025
dc8607b
Update example
xtyxtyx Jun 22, 2025
c7d6321
Add .vscode to .gitignore
xtyxtyx Jun 22, 2025
df127d7
Bump version
xtyxtyx Jun 22, 2025
1d9613c
Removed Dependabot on package
vicajilau Jul 20, 2025
5cba8d7
Added publish flow
vicajilau Jul 20, 2025
1312766
Renamed file
vicajilau Jul 20, 2025
a4ad5c7
Merge pull request #130 from TerminalStudio/feature/CI-CD-improvements
vicajilau Jul 20, 2025
61600d5
Support SSH-1.99 version
james-thorpe Nov 2, 2025
0d2d288
Propagate underlying exception in SSHAuthAbortError
james-thorpe Nov 2, 2025
1c5a937
feat: Expose SSH ident from ssh_client
Remulic Nov 17, 2025
3aa45a5
Add NaviTerm screenshot to README
jc-hk-1916 Jan 1, 2026
f9d3a1d
add NaviTerm title and repository link
jc-hk-1916 Jan 1, 2026
2bf1ef2
Update App Store link for NaviTerm
jc-hk-1916 Jan 1, 2026
416d74e
add NaviTerm to showcase and refine table structure
jc-hk-1916 Jan 1, 2026
b2e1264
Update image alt text for clarity
jc-hk-1916 Jan 1, 2026
8db2d02
Add SSH agent forwarding support
Wackymax Jan 27, 2026
c51d71d
Honor RSA sign-request flags in agent
Wackymax Jan 27, 2026
96a1d55
Fix agent RSA signing imports and add tests
Wackymax Jan 27, 2026
4499ab6
Introducing domain sockets as forwarding connect destination
isegal Feb 13, 2026
81e88d7
Add example of forwarding to a remote unix domain socket
isegal Feb 14, 2026
963e9f9
Fix potential hang when closing channel while opening
isegal Mar 14, 2026
e7a38ee
register channel
Mar 18, 2026
17ba902
Merge pull request #141 from shihuili1218/master
vicajilau Mar 19, 2026
7b1a439
Bump version to 2.14.0 and update CHANGELOG for SSH connection fix
vicajilau Mar 19, 2026
bcdafd0
Merge pull request #140 from few-sh/domain-sockets
vicajilau Mar 19, 2026
78cf43a
Update GitHub Actions workflow to include pull request triggers and m…
vicajilau Mar 19, 2026
6d49596
Merge branch 'master' into feature/agent-forwarding
vicajilau Mar 19, 2026
e4bb2d8
Merge pull request #138 from jc-hk-1916/master
vicajilau Mar 19, 2026
6ae02d4
Add forwardLocalUnix() function to CHANGELOG for SSH forwarding
vicajilau Mar 19, 2026
98ac20b
chore(deps): update pointycastle to ^4.0.0
vicajilau Mar 20, 2026
743b459
chore: update version to 2.15.0 and modify CHANGELOG for pointycastle…
vicajilau Mar 20, 2026
5b92bb7
Merge pull request #142 from TerminalStudio/chore/update-pointycastle…
vicajilau Mar 20, 2026
7e7f14a
feat: add foundational X11 forwarding support
vicajilau Mar 20, 2026
91908e2
Merge pull request #143 from TerminalStudio/feat/x11-forwarding-issue-1
vicajilau Mar 20, 2026
d48643f
Merge branch 'master' into master
vicajilau Mar 20, 2026
4c50a3d
Merge pull request #135 from Remulic/master
vicajilau Mar 20, 2026
f1c6a02
feat: add SSH identification customization and validation
vicajilau Mar 20, 2026
03acd17
Merge branch 'master' into feat/propogate-SSHAuthAbortError-reason
vicajilau Mar 20, 2026
97d0bdf
fix: keep SSHAuthAbortError reason backward-compatible
vicajilau Mar 20, 2026
8f585c3
refactor: keep SSHAuthAbortError reason typed as SSHError
vicajilau Mar 20, 2026
9a49595
Merge pull request #133 from james-thorpe/feat/propogate-SSHAuthAbort…
vicajilau Mar 20, 2026
03f10c8
Merge branch 'master' into feat/SSH-1.99-support
vicajilau Mar 20, 2026
c73966f
chore: update CHANGELOG to include SSHAuthAbortError reason propagation
vicajilau Mar 20, 2026
e1f37ea
test: add tests for SSHAuthAbortError and SSHClient auth abort reason…
vicajilau Mar 20, 2026
4c0432d
Merge pull request #132 from james-thorpe/feat/SSH-1.99-support
vicajilau Mar 20, 2026
173a899
fix: improve readability of version check in SSHTransport
vicajilau Mar 20, 2026
84a2262
feat: accept SSH-1.99 server banners as SSH-2 compatible and add regr…
vicajilau Mar 20, 2026
54e27e4
Merge PR #139 into integration branch and resolve conflicts
vicajilau Mar 20, 2026
f9dc7b0
feat: add SSH agent forwarding support with in-memory handling and RS…
vicajilau Mar 20, 2026
55c36d0
refactor: format code for better readability in _rsaKeyFrom method
vicajilau Mar 20, 2026
d1341de
feat: enhance SSH agent forwarding with error handling and add tests …
vicajilau Mar 20, 2026
91e1804
test: add tests for SSHAgentChannel handling fragmented and back-to-b…
vicajilau Mar 20, 2026
5ef6bf9
test: add test for SSHAgentChannel to ignore incomplete frames on cha…
vicajilau Mar 20, 2026
8c151ea
Merge pull request #144 from TerminalStudio/integration/pr-139-agent-…
vicajilau Mar 20, 2026
39f672e
test: raise coverage and split unit/integration suites
vicajilau Mar 20, 2026
bf204c0
chore: update CHANGELOG.md with recent fixes for HTTP response parsin…
vicajilau Mar 20, 2026
4750a0f
chore: update actions/checkout and codecov-action versions in CI work…
vicajilau Mar 20, 2026
88b3eb0
Merge pull request #145 from TerminalStudio/feat/testing-coverage-roa…
vicajilau Mar 20, 2026
7bf0a02
Merge upstream v2.15.0
GT-610 Mar 30, 2026
1ce07af
fix: Fixed library declarations and error handling in multiple test f…
GT-610 Mar 30, 2026
9646f04
fix(ssh): Added frame size limit and fixed error handling when the co…
GT-610 Mar 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ doc/api/

.history

.vscode
.vscode

coverage/
28 changes: 24 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
## [2.14.0] - 2026-03-19
- Fixed SSH connections through bastion hosts where the target server sends its version string immediately upon connection (which is standard behavior per RFC 4253) [#141]. Thanks @shihuili1218.
- Adds a new forwardLocalUnix() function, which is an equivalent of ssh -L localPort:remoteSocketPath [#140]. Thanks @isegal.
## [2.15.0] - 2026-03-30
- Updated `pointycastle` dependency to `^4.0.0` [#131]. Thanks [@vicajilau].
- Added foundational X11 forwarding support with session x11-req API, incoming x11 channel handling, and protocol tests [#1]. Thanks [@vicajilau].
- Exposed SSH ident configuration from `SSHClient` [#135]. Thanks [@Remulic] and [@vicajilau].
- Propagated the underlying exception in `SSHAuthAbortError` through `reason` for better diagnostics [#133]. Thanks [@james-thorpe] and [@vicajilau].
- Accepted `SSH-1.99-*` server banners as SSH-2 compatible during version exchange and added regression tests [#132]. Thanks [@james-thorpe] and [@vicajilau].
- Added SSH agent forwarding support (`auth-agent-req@openssh.com`) with in-memory agent handling and RSA sign-request flag support [#139]. Thanks [@Wackymax] and [@vicajilau].
- Normalized HTTP response line parsing in `SSHHttpClientResponse` to handle CRLF endings consistently and avoid trailing line-ending artifacts in parsed status/header fields [#145]. Thanks [@vicajilau].
- Fixed SFTP packet encoding/decoding consistency: `SftpInitPacket.decode` now parses extension pairs correctly and `SftpExtendedReplyPacket.encode` now preserves raw payload bytes [#145]. Thanks [@vicajilau].

## [2.14.0] - 2026-03-19
- Fixed SSH connections through bastion hosts where the target server sends its version string immediately upon connection (which is standard behavior per RFC 4253) [#141]. Thanks [@shihuili1218].
- Adds a new forwardLocalUnix() function, which is an equivalent of ssh -L localPort:remoteSocketPath [#140]. Thanks [@isegal].

## [2.13.0] - 2025-06-22
- docs: Update NoPorts naming [#115]. [@XavierChanth].
Expand Down Expand Up @@ -176,8 +185,13 @@

- Initial release.

[#145]: https://github.com/TerminalStudio/dartssh2/pull/145
[#141]: https://github.com/TerminalStudio/dartssh2/pull/141
[#140]: https://github.com/TerminalStudio/dartssh2/pull/140
[#139]: https://github.com/TerminalStudio/dartssh2/pull/139
[#133]: https://github.com/TerminalStudio/dartssh2/pull/133
[#132]: https://github.com/TerminalStudio/dartssh2/pull/132
[#131]: https://github.com/TerminalStudio/dartssh2/pull/131
[#127]: https://github.com/TerminalStudio/dartssh2/pull/127
[#126]: https://github.com/TerminalStudio/dartssh2/pull/126
[#125]: https://github.com/TerminalStudio/dartssh2/pull/125
Expand All @@ -202,4 +216,10 @@
[@XavierChanth]: https://github.com/XavierChanth
[@MarBazuz]: https://github.com/MarBazuz
[@reinbeumer]: https://github.com/reinbeumer
[@alexander-irion]: https://github.com/alexander-irion
[@alexander-irion]: https://github.com/alexander-irion
[@Remulic]: https://github.com/Remulic
[@james-thorpe]: https://github.com/james-thorpe
[@Wackymax]: https://github.com/Wackymax
[@vicajilau]: https://github.com/vicajilau
[@shihuili1218]: https://github.com/shihuili1218
[@isegal]: https://github.com/isegal
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,24 @@ void main() async {

> `SSHSocket` is an interface and it's possible to implement your own `SSHSocket` if you want to use a different underlying transport rather than standard TCP socket. For example WebSocket or Unix domain socket.

### Customize client SSH identification

If your jump host or SSH gateway restricts client versions, you can customize the
software version part of the identification string (`SSH-2.0-<ident>`):

```dart
void main() async {
final client = SSHClient(
await SSHSocket.connect('localhost', 22),
username: '<username>',
onPasswordRequest: () => '<password>',
ident: 'MyClient_1.0',
);
}
```

`ident` defaults to `DartSSH_2.0`.

### Spawn a shell on remote host

```dart
Expand Down
19 changes: 19 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
coverage:
status:
project:
default:
target: auto
threshold: 5%
flags:
- unittests
patch:
default:
target: auto
threshold: 2%
flags:
- unittests

comment:
layout: "reach,diff,flags,files"
behavior: default
require_changes: true
3 changes: 3 additions & 0 deletions dart_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
tags:
integration:
timeout: 2x
1 change: 1 addition & 0 deletions lib/dartssh2.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export 'src/ssh_algorithm.dart' show SSHAlgorithms;
export 'src/ssh_agent.dart';
export 'src/ssh_client.dart';
export 'src/ssh_errors.dart';
export 'src/ssh_forward.dart';
Expand Down
1 change: 0 additions & 1 deletion lib/src/algorithm/ssh_mac_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ class SSHMacType extends SSHAlgorithm {
macFactory: _hmacSha512Factory,
isEtm: true,
);
// end added by Rein

const SSHMacType._({
required this.name,
Expand Down
32 changes: 17 additions & 15 deletions lib/src/http/http_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -423,8 +423,7 @@ class SSHHttpClientResponse {
var currentChunkSize = 0;

void processLine(String line, int bytesRead, LineDecoder decoder) {
if (finished) return;

final normalizedLine = line.trimRight();
if (inBody) {
if (chunked) {
if (expectingChunkSize) {
Expand Down Expand Up @@ -482,7 +481,7 @@ class SSHHttpClientResponse {
contentRead += bytesRead;
}
} else if (inHeader) {
if (line.trim().isEmpty) {
if (normalizedLine.trim().isEmpty) {
inBody = true;
// Decide body framing
final te = headers[SSHHttpHeaders.transferEncodingHeader]
Expand All @@ -499,15 +498,17 @@ class SSHHttpClientResponse {
}
return;
}
final separator = line.indexOf(':');
final name = line.substring(0, separator).toLowerCase().trim();
final value = line.substring(separator + 1).trim();
if (name == SSHHttpHeaders.transferEncodingHeader) {
// Allow only identity or chunked; others unsupported
final v = value.toLowerCase();
if (!(v == 'identity' || v.contains('chunked'))) {
throw UnsupportedError('unsupported transfer encoding: $value');
}
final separator = normalizedLine.indexOf(':');
if (separator <= 0) {
throw FormatException(
'Invalid header line: "$normalizedLine" - no colon separator found');
}
final name =
normalizedLine.substring(0, separator).toLowerCase().trim();
final value = normalizedLine.substring(separator + 1).trim();
if (name == SSHHttpHeaders.transferEncodingHeader &&
value.toLowerCase() != 'identity') {
throw UnsupportedError('only identity transfer encoding is accepted');
}
if (name == SSHHttpHeaders.contentLengthHeader) {
contentLength = int.parse(value);
Expand All @@ -516,11 +517,12 @@ class SSHHttpClientResponse {
headers[name] = [];
}
headers[name]!.add(value);
} else if (line.startsWith('HTTP/1.1') || line.startsWith('HTTP/1.0')) {
} else if (normalizedLine.startsWith('HTTP/1.1') ||
normalizedLine.startsWith('HTTP/1.0')) {
statusCode = int.parse(
line.substring('HTTP/1.x '.length, 'HTTP/1.x xxx'.length),
normalizedLine.substring('HTTP/1.x '.length, 'HTTP/1.x xxx'.length),
);
reasonPhrase = line.substring('HTTP/1.x xxx '.length);
reasonPhrase = normalizedLine.substring('HTTP/1.x xxx '.length);
inHeader = true;
} else {
throw UnsupportedError('unsupported http response format');
Expand Down
1 change: 1 addition & 0 deletions lib/src/message/msg_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,7 @@ abstract class SSHChannelRequestType {
static const shell = 'shell';
static const exec = 'exec';
static const subsystem = 'subsystem';
static const authAgent = 'auth-agent-req@openssh.com';
static const windowChange = 'window-change';
static const xon = 'xon-xoff';
static const signal = 'signal';
Expand Down
4 changes: 2 additions & 2 deletions lib/src/sftp/sftp_packet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class SftpInitPacket implements SftpPacket {
reader.readUint8(); // packet type
final version = reader.readUint32();
final extensions = <String, String>{};
while (reader.isDone) {
while (!reader.isDone) {
final name = reader.readUtf8();
final value = reader.readUtf8();
extensions[name] = value;
Expand Down Expand Up @@ -1031,7 +1031,7 @@ class SftpExtendedReplyPacket implements SftpResponsePacket {
final writer = SSHMessageWriter();
writer.writeUint8(packetType);
writer.writeUint32(requestId);
writer.writeString(payload);
writer.writeBytes(payload);
return writer.takeBytes();
}

Expand Down
Loading
Loading