Skip to content

Commit ba5565c

Browse files
committed
feat: use shell stdout, stderr streams
1 parent a26b4cd commit ba5565c

File tree

2 files changed

+53
-55
lines changed

2 files changed

+53
-55
lines changed

src/channels/Session/Shell.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Readable, Writable } from "stream"
22
import SessionChannel from "../SessionChannel.js"
33
import ChannelData from "../../packets/ChannelData.js"
44
import assert from "assert"
5+
import ChannelExtendedData from "../../packets/ChannelExtendedData.js"
56

67
export default class Shell {
78
channel: SessionChannel
@@ -43,8 +44,9 @@ export default class Shell {
4344
assert(Buffer.isBuffer(chunk))
4445

4546
this.channel.client.sendPacket(
46-
new ChannelData({
47+
new ChannelExtendedData({
4748
recipient_channel_id: this.channel.remoteId!,
49+
data_type_code: 1,
4850
data: chunk,
4951
}),
5052
)

src/index_server.ts

Lines changed: 50 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import PrivateKey from "./utils/PrivateKey.js"
55
import { readFileSync } from "node:fs"
66
import { homedir } from "node:os"
77
import SessionChannel from "./channels/SessionChannel.js"
8-
import ChannelData from "./packets/ChannelData.js"
98

109
const server = new Server({
1110
hostKeys: [
@@ -15,6 +14,54 @@ const server = new Server({
1514
],
1615
})
1716

17+
const allowedPublicKeys = PublicKey.parseAuthorizedKeysFile(`
18+
# ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICcSFk1WeyZZyOV/W5oFXldpVvLssFZNZVyURUsSz6tU thomiz@vitc.org
19+
# ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJS6a664HMOKoLXZU0NTI/v9psSjaYye6GUsab62uvg3 manafralli@gmail.com
20+
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG1QB7MrCW2ZmvlGgADPkm61EBkds4AI8kpXo7vvNDTl manaf@2221.ch
21+
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDKNMME9pqRzPV2Gn6LB3erVXpvkzi1OtYLGkjTRSupQg9sN+17iTQIx3dCEudWRWLXBOtlL1lg1UH9TbnnCYjY+ns7KlFa8ibLeAy9D8NPTZ/4yMapDhZM8ThQseqKMbr9D9XfSryCpj9bPNCg2+OY2FPhArVyOBRcT9byHXPJYPES82pH8EepCDnr/D7NSM1TsrIzXc0d8JLZJxr+f6OMdrf8646cLmM0iJuEelyt+2sBxrJZRsu0Y0pHMwVoN+2U1xOjshxLCAZrIJGK7LOLCDR/AFljNzQlTFkQOSFDghBkz/R4CDtsoT6D0/GA8ZMDb7hgrCgu93C7ZFDfzOZKDzN4l80nuxdUbcEdtMVc36Aj2IzMoFxWauGGmnOBu1zujnSvU2azK/f1RT1UNKqMfwq8hn5T7OC9CGX6cTKGOnHwIzv1igMDi2Wghgarj79jH4xdcF//wAkyaipPZSW9LAX4CRauLW3hKZ/Afeq15Bm6H39zLH4cdtonX0rDPvk= manaf@cooper.home
22+
`)
23+
24+
server.hooker.hook("publicKeyAuthentication", (_, context, controller) => {
25+
console.debug(
26+
`PublicKeyAuthentication request for user ${context.username} and key ${context.publicKey.hash("sha256")}`,
27+
)
28+
// only allow user "manaf"
29+
if (context.username != "manaf") return
30+
31+
const publicKey = allowedPublicKeys.find((key) => key.equals(context.publicKey))
32+
// public key is not in the keys file
33+
if (!publicKey) return
34+
35+
// when using password managers or keychains,
36+
// the server needs to explicitely tell the
37+
// client to sign the auth request.
38+
if (!context.signature) {
39+
controller.requestSignature = true
40+
return
41+
}
42+
43+
// If the signature is not valid, do not allow login.
44+
if (!context.publicKey.verifySignature(context.signatureMessage, context.signature)) return
45+
46+
controller.allowLogin = true
47+
})
48+
49+
server.hooker.hook("passwordAuthentication", (_, context, controller) => {
50+
console.debug(
51+
`PasswordAuthentication request for user ${context.username} and password ${context.password}`,
52+
)
53+
54+
if (context.password !== "test") return
55+
56+
controller.allowLogin = true
57+
})
58+
59+
server.hooker.hook("channelOpenRequest", (_, channel, controller) => {
60+
if (!(channel instanceof SessionChannel)) return
61+
62+
controller.allowOpen = true
63+
})
64+
1865
server.listen(3022, () => {
1966
server.debug("Server listening on port", 3022)
2067
})
@@ -42,64 +89,13 @@ server.on("connection", (client) => {
4289
})
4390

4491
channel.events.on("shell", (shell) => {
45-
process.stdin.resume()
46-
process.stdin.setRawMode(true)
47-
process.stdin.setEncoding("utf8")
48-
process.stdin.pipe(shell.stdout)
49-
50-
client.sendPacket(
51-
new ChannelData({
52-
recipient_channel_id: channel.remoteId!,
53-
data: Buffer.from("Hello World !\n\nEnvironment Variables:\n", "utf8"),
54-
}),
55-
)
92+
shell.stderr.write(`Hello World !\n\nEnvironment Variables:\n`)
5693

5794
for (const [key, value] of channel.env.entries()) {
58-
client.sendPacket(
59-
new ChannelData({
60-
recipient_channel_id: channel.remoteId!,
61-
data: Buffer.from(`${key}=${value}\n`, "utf8"),
62-
}),
63-
)
95+
shell.stderr.write(`${key}=${value}\n`)
6496
}
6597

6698
// channel.close()
6799
})
68100
})
69101
})
70-
71-
const allowedUser = "manaf"
72-
const allowedPublicKeys = PublicKey.parseAuthorizedKeysFile(`
73-
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICcSFk1WeyZZyOV/W5oFXldpVvLssFZNZVyURUsSz6tU thomiz@vitc.org
74-
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJS6a664HMOKoLXZU0NTI/v9psSjaYye6GUsab62uvg3 manafralli@gmail.com
75-
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG1QB7MrCW2ZmvlGgADPkm61EBkds4AI8kpXo7vvNDTl manaf@2221.ch
76-
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDKNMME9pqRzPV2Gn6LB3erVXpvkzi1OtYLGkjTRSupQg9sN+17iTQIx3dCEudWRWLXBOtlL1lg1UH9TbnnCYjY+ns7KlFa8ibLeAy9D8NPTZ/4yMapDhZM8ThQseqKMbr9D9XfSryCpj9bPNCg2+OY2FPhArVyOBRcT9byHXPJYPES82pH8EepCDnr/D7NSM1TsrIzXc0d8JLZJxr+f6OMdrf8646cLmM0iJuEelyt+2sBxrJZRsu0Y0pHMwVoN+2U1xOjshxLCAZrIJGK7LOLCDR/AFljNzQlTFkQOSFDghBkz/R4CDtsoT6D0/GA8ZMDb7hgrCgu93C7ZFDfzOZKDzN4l80nuxdUbcEdtMVc36Aj2IzMoFxWauGGmnOBu1zujnSvU2azK/f1RT1UNKqMfwq8hn5T7OC9CGX6cTKGOnHwIzv1igMDi2Wghgarj79jH4xdcF//wAkyaipPZSW9LAX4CRauLW3hKZ/Afeq15Bm6H39zLH4cdtonX0rDPvk= manaf@cooper.home
77-
`)
78-
79-
server.hooker.hook("publicKeyAuthentication", (_, context, controller) => {
80-
// only allow user "manaf"
81-
if (context.username != allowedUser) return
82-
83-
const publicKey = allowedPublicKeys.find((key) => key.equals(context.publicKey))
84-
// public key is not in the keys file
85-
if (!publicKey) return
86-
87-
// when using password managers or keychains,
88-
// the server needs to explicitely tell the
89-
// client to sign the auth request.
90-
if (!context.signature) {
91-
controller.requestSignature = true
92-
return
93-
}
94-
95-
// If the signature is not valid, do not allow login.
96-
if (!context.publicKey.verifySignature(context.signatureMessage, context.signature)) return
97-
98-
controller.allowLogin = true
99-
})
100-
101-
server.hooker.hook("channelOpenRequest", (_, channel, controller) => {
102-
if (!(channel instanceof SessionChannel)) return
103-
104-
controller.allowOpen = true
105-
})

0 commit comments

Comments
 (0)