rustssh2 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.bumpversion.cfg +8 -0
- package/.jetbrains +1 -0
- package/LICENSE-2.0.txt +202 -0
- package/README.md +7 -0
- package/lib/agent.d.ts +22 -0
- package/lib/agent.js +85 -0
- package/lib/channel.d.ts +40 -0
- package/lib/channel.js +98 -0
- package/lib/events.d.ts +32 -0
- package/lib/events.js +139 -0
- package/lib/helpers.d.ts +5 -0
- package/lib/helpers.js +20 -0
- package/lib/index.d.ts +102 -0
- package/lib/index.js +242 -0
- package/lib/native.d.ts +143 -0
- package/lib/native.js +25 -0
- package/lib/sftp.d.ts +34 -0
- package/lib/sftp.js +104 -0
- package/package.json +28 -0
- package/russh.darwin-arm64.node +0 -0
- package/russh.darwin-x64.node +0 -0
- package/russh.linux-arm-gnueabihf.node +0 -0
- package/russh.linux-arm64-gnu.node +0 -0
- package/russh.linux-x64-gnu.node +0 -0
- package/russh.win32-arm64-msvc.node +0 -0
- package/russh.win32-x64-msvc.node +0 -0
- package/rust-toolchain.toml +2 -0
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { Observable } from 'rxjs';
|
|
2
|
+
import { Destructible } from './helpers';
|
|
3
|
+
import { SFTP } from './sftp';
|
|
4
|
+
import { Channel, NewChannel } from './channel';
|
|
5
|
+
import { ClientEventInterface } from './events';
|
|
6
|
+
import { SshKeyPair, KeyboardInteractiveAuthenticationPrompt, SshClient, SshPublicKey, SshTransport } from './native';
|
|
7
|
+
import { AgentConnectionSpec } from './agent';
|
|
8
|
+
export declare class KeyPair {
|
|
9
|
+
protected inner: SshKeyPair;
|
|
10
|
+
private constructor();
|
|
11
|
+
get algorithm(): string;
|
|
12
|
+
static parse(data: string, passphrase?: string): Promise<KeyPair>;
|
|
13
|
+
}
|
|
14
|
+
export interface X11ChannelOpenEvent {
|
|
15
|
+
readonly channel: NewChannel;
|
|
16
|
+
readonly clientAddress: string;
|
|
17
|
+
readonly clientPort: number;
|
|
18
|
+
}
|
|
19
|
+
export interface TCPChannelOpenEvent {
|
|
20
|
+
readonly channel: NewChannel;
|
|
21
|
+
readonly targetAddress: string;
|
|
22
|
+
readonly targetPort: number;
|
|
23
|
+
readonly clientAddress: string;
|
|
24
|
+
readonly clientPort: number;
|
|
25
|
+
}
|
|
26
|
+
export type KeyboardInteractiveAuthenticationState = {
|
|
27
|
+
state: 'failure';
|
|
28
|
+
remainingMethods: string[];
|
|
29
|
+
} | {
|
|
30
|
+
state: 'infoRequest';
|
|
31
|
+
name: string;
|
|
32
|
+
instructions: string;
|
|
33
|
+
prompts: () => KeyboardInteractiveAuthenticationPrompt[];
|
|
34
|
+
};
|
|
35
|
+
export interface AuthFailure {
|
|
36
|
+
remainingMethods: string[];
|
|
37
|
+
}
|
|
38
|
+
export interface Config {
|
|
39
|
+
preferred?: {
|
|
40
|
+
ciphers?: string[];
|
|
41
|
+
kex?: string[];
|
|
42
|
+
key?: string[];
|
|
43
|
+
mac?: string[];
|
|
44
|
+
compression?: string[];
|
|
45
|
+
};
|
|
46
|
+
connectionTimeoutSeconds?: number;
|
|
47
|
+
keepaliveIntervalSeconds?: number;
|
|
48
|
+
keepaliveCountMax?: number;
|
|
49
|
+
}
|
|
50
|
+
export declare class SSHClient extends Destructible {
|
|
51
|
+
private client;
|
|
52
|
+
private events;
|
|
53
|
+
readonly disconnect$: Observable<void>;
|
|
54
|
+
readonly banner$: Observable<string>;
|
|
55
|
+
private constructor();
|
|
56
|
+
static connect(transport: SshTransport, serverKeyCallback: (key: SshPublicKey) => Promise<boolean>, config?: Config): Promise<SSHClient>;
|
|
57
|
+
protected destruct(): void;
|
|
58
|
+
authenticateNone(username: string): Promise<AuthenticatedSSHClient | AuthFailure>;
|
|
59
|
+
authenticateWithPassword(username: string, password: string): Promise<AuthenticatedSSHClient | AuthFailure>;
|
|
60
|
+
private _hashAlg;
|
|
61
|
+
authenticateWithKeyPair(username: string, keyPair: KeyPair, hashAlgorithm: 'sha1' | 'sha256' | 'sha512' | null): Promise<AuthenticatedSSHClient | AuthFailure>;
|
|
62
|
+
startKeyboardInteractiveAuthentication(username: string): Promise<KeyboardInteractiveAuthenticationState>;
|
|
63
|
+
continueKeyboardInteractiveAuthentication(responses: string[]): Promise<AuthenticatedSSHClient | KeyboardInteractiveAuthenticationState>;
|
|
64
|
+
authenticateWithAgent(username: string, connection: AgentConnectionSpec): Promise<AuthenticatedSSHClient | AuthFailure>;
|
|
65
|
+
/**
|
|
66
|
+
* Authenticate using SSH agent with a specific public key identity.
|
|
67
|
+
* This is useful when you have multiple keys in the agent and want to use a specific one,
|
|
68
|
+
* avoiding the server's authentication attempt limit.
|
|
69
|
+
* @param username SSH username
|
|
70
|
+
* @param connection Agent connection specification
|
|
71
|
+
* @param publicKey The specific public key to use for authentication
|
|
72
|
+
*/
|
|
73
|
+
authenticateWithAgentIdentity(username: string, connection: AgentConnectionSpec, publicKey: SshPublicKey): Promise<AuthenticatedSSHClient | AuthFailure>;
|
|
74
|
+
disconnect(): Promise<void>;
|
|
75
|
+
private intoAuthenticated;
|
|
76
|
+
}
|
|
77
|
+
export declare class AuthenticatedSSHClient extends Destructible {
|
|
78
|
+
private client;
|
|
79
|
+
private events;
|
|
80
|
+
readonly disconnect$: Observable<void>;
|
|
81
|
+
readonly x11ChannelOpen$: Observable<X11ChannelOpenEvent>;
|
|
82
|
+
readonly tcpChannelOpen$: Observable<TCPChannelOpenEvent>;
|
|
83
|
+
readonly agentChannelOpen$: Observable<NewChannel>;
|
|
84
|
+
constructor(client: SshClient, events: ClientEventInterface);
|
|
85
|
+
openSessionChannel(): Promise<NewChannel>;
|
|
86
|
+
openTCPForwardChannel(options: {
|
|
87
|
+
addressToConnectTo: string;
|
|
88
|
+
portToConnectTo: number;
|
|
89
|
+
originatorAddress: string;
|
|
90
|
+
originatorPort: number;
|
|
91
|
+
}): Promise<NewChannel>;
|
|
92
|
+
forwardTCPPort(addressToBind: string, portToBind: number): Promise<number>;
|
|
93
|
+
stopForwardingTCPPort(addressToBind: string, portToBind: number): Promise<void>;
|
|
94
|
+
disconnect(): Promise<void>;
|
|
95
|
+
activateChannel(ch: NewChannel): Promise<Channel>;
|
|
96
|
+
activateSFTP(ch: NewChannel): Promise<SFTP>;
|
|
97
|
+
private wrapChannel;
|
|
98
|
+
}
|
|
99
|
+
export { KeyboardInteractiveAuthenticationPrompt, SshPublicKey, SshTransport, SshChannel, NewSshChannel, SftpFileType as SFTPFileType, supportedCiphers as getSupportedCiphers, supportedKexAlgorithms as getSupportedKexAlgorithms, supportedMacs as getSupportedMACs, supportedCompressionAlgorithms as getSupportedCompressionAlgorithms, supportedKeyTypes as getSupportedKeyTypes, OPEN_APPEND, OPEN_CREATE, OPEN_READ, OPEN_TRUNCATE, OPEN_WRITE, SftpFile as SFTPFile, isPageantRunning, HashAlgorithm, parsePublicKey, } from './native';
|
|
100
|
+
export { SFTP, SFTPDirectoryEntry, SFTPMetadata, } from './sftp';
|
|
101
|
+
export { AgentConnectionSpec, SSHAgentStream } from './agent';
|
|
102
|
+
export { Channel, NewChannel };
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.NewChannel = exports.Channel = exports.SSHAgentStream = exports.SFTP = exports.parsePublicKey = exports.isPageantRunning = exports.SFTPFile = exports.OPEN_WRITE = exports.OPEN_TRUNCATE = exports.OPEN_READ = exports.OPEN_CREATE = exports.OPEN_APPEND = exports.getSupportedKeyTypes = exports.getSupportedCompressionAlgorithms = exports.getSupportedMACs = exports.getSupportedKexAlgorithms = exports.getSupportedCiphers = exports.NewSshChannel = exports.SshChannel = exports.SshTransport = exports.SshPublicKey = exports.KeyboardInteractiveAuthenticationPrompt = exports.AuthenticatedSSHClient = exports.SSHClient = exports.KeyPair = void 0;
|
|
16
|
+
const rxjs_1 = require("rxjs");
|
|
17
|
+
const helpers_1 = require("./helpers");
|
|
18
|
+
const sftp_1 = require("./sftp");
|
|
19
|
+
const channel_1 = require("./channel");
|
|
20
|
+
Object.defineProperty(exports, "Channel", { enumerable: true, get: function () { return channel_1.Channel; } });
|
|
21
|
+
Object.defineProperty(exports, "NewChannel", { enumerable: true, get: function () { return channel_1.NewChannel; } });
|
|
22
|
+
const events_1 = require("./events");
|
|
23
|
+
const native_1 = __importDefault(require("./native"));
|
|
24
|
+
const agent_1 = require("./agent");
|
|
25
|
+
class KeyPair {
|
|
26
|
+
constructor(inner) {
|
|
27
|
+
this.inner = inner;
|
|
28
|
+
}
|
|
29
|
+
get algorithm() {
|
|
30
|
+
return this.inner.publicKey().algorithm();
|
|
31
|
+
}
|
|
32
|
+
static parse(data, passphrase) {
|
|
33
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
34
|
+
return new KeyPair(yield native_1.default.parseKey(data, passphrase));
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.KeyPair = KeyPair;
|
|
39
|
+
class SSHClient extends helpers_1.Destructible {
|
|
40
|
+
constructor(client, events) {
|
|
41
|
+
super();
|
|
42
|
+
this.client = client;
|
|
43
|
+
this.events = events;
|
|
44
|
+
this.disconnect$ = this.events.disconnect$.asObservable();
|
|
45
|
+
this.banner$ = this.events.banner$.asObservable();
|
|
46
|
+
}
|
|
47
|
+
static connect(transport, serverKeyCallback, config) {
|
|
48
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
49
|
+
var _a, _b, _c, _d, _e, _f;
|
|
50
|
+
const eventInterface = new events_1.ClientEventInterface();
|
|
51
|
+
const russhClient = yield native_1.default.connect(transport, (_a = config === null || config === void 0 ? void 0 : config.preferred) === null || _a === void 0 ? void 0 : _a.ciphers, (_b = config === null || config === void 0 ? void 0 : config.preferred) === null || _b === void 0 ? void 0 : _b.kex, (_c = config === null || config === void 0 ? void 0 : config.preferred) === null || _c === void 0 ? void 0 : _c.key, (_d = config === null || config === void 0 ? void 0 : config.preferred) === null || _d === void 0 ? void 0 : _d.mac, (_e = config === null || config === void 0 ? void 0 : config.preferred) === null || _e === void 0 ? void 0 : _e.compression, config === null || config === void 0 ? void 0 : config.connectionTimeoutSeconds, config === null || config === void 0 ? void 0 : config.keepaliveIntervalSeconds, (_f = config === null || config === void 0 ? void 0 : config.keepaliveCountMax) !== null && _f !== void 0 ? _f : 3, (_, k) => serverKeyCallback(k), eventInterface.dataCallback, eventInterface.extendedDataCallback, eventInterface.eofCallback, eventInterface.closeCallback, eventInterface.disconnectCallback, eventInterface.x11ChannelOpenCallback, eventInterface.tcpChannelOpenCallback, eventInterface.agentChannelOpenCallback, eventInterface.bannerCallback);
|
|
52
|
+
eventInterface.disconnect$.subscribe(() => {
|
|
53
|
+
setTimeout(() => eventInterface.complete());
|
|
54
|
+
});
|
|
55
|
+
return new SSHClient(russhClient, eventInterface);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
destruct() {
|
|
59
|
+
super.destruct();
|
|
60
|
+
}
|
|
61
|
+
authenticateNone(username) {
|
|
62
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
63
|
+
this.assertNotDestructed();
|
|
64
|
+
const result = yield this.client.authenticateNone(username);
|
|
65
|
+
if (result.success) {
|
|
66
|
+
return this.intoAuthenticated();
|
|
67
|
+
}
|
|
68
|
+
return result;
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
authenticateWithPassword(username, password) {
|
|
72
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
73
|
+
this.assertNotDestructed();
|
|
74
|
+
const result = yield this.client.authenticatePassword(username, password);
|
|
75
|
+
if (result.success) {
|
|
76
|
+
return this.intoAuthenticated();
|
|
77
|
+
}
|
|
78
|
+
return result;
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
_hashAlg(hashAlgorithm) {
|
|
82
|
+
return hashAlgorithm ? {
|
|
83
|
+
sha1: 0 /* HashAlgorithm.Sha1 */,
|
|
84
|
+
sha256: 1 /* HashAlgorithm.Sha256 */,
|
|
85
|
+
sha512: 2 /* HashAlgorithm.Sha512 */,
|
|
86
|
+
}[hashAlgorithm] : null;
|
|
87
|
+
}
|
|
88
|
+
authenticateWithKeyPair(username, keyPair, hashAlgorithm) {
|
|
89
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
90
|
+
this.assertNotDestructed();
|
|
91
|
+
const result = yield this.client.authenticatePublickey(username, keyPair['inner'], this._hashAlg(hashAlgorithm));
|
|
92
|
+
if (result.success) {
|
|
93
|
+
return this.intoAuthenticated();
|
|
94
|
+
}
|
|
95
|
+
return result;
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
startKeyboardInteractiveAuthentication(username) {
|
|
99
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
100
|
+
this.assertNotDestructed();
|
|
101
|
+
return yield this.client.startKeyboardInteractiveAuthentication(username);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
continueKeyboardInteractiveAuthentication(responses) {
|
|
105
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
106
|
+
this.assertNotDestructed();
|
|
107
|
+
const result = yield this.client.respondToKeyboardInteractiveAuthentication(responses);
|
|
108
|
+
if (result.state === 'success') {
|
|
109
|
+
return this.intoAuthenticated();
|
|
110
|
+
}
|
|
111
|
+
return result;
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
authenticateWithAgent(username, connection) {
|
|
115
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
116
|
+
this.assertNotDestructed();
|
|
117
|
+
const result = yield this.client.authenticateAgent(username, (0, agent_1.makeRusshAgentConnection)(connection), null);
|
|
118
|
+
if (result.success) {
|
|
119
|
+
return this.intoAuthenticated();
|
|
120
|
+
}
|
|
121
|
+
return result;
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Authenticate using SSH agent with a specific public key identity.
|
|
126
|
+
* This is useful when you have multiple keys in the agent and want to use a specific one,
|
|
127
|
+
* avoiding the server's authentication attempt limit.
|
|
128
|
+
* @param username SSH username
|
|
129
|
+
* @param connection Agent connection specification
|
|
130
|
+
* @param publicKey The specific public key to use for authentication
|
|
131
|
+
*/
|
|
132
|
+
authenticateWithAgentIdentity(username, connection, publicKey) {
|
|
133
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
134
|
+
this.assertNotDestructed();
|
|
135
|
+
const result = yield this.client.authenticateAgent(username, (0, agent_1.makeRusshAgentConnection)(connection), publicKey);
|
|
136
|
+
if (result.success) {
|
|
137
|
+
return this.intoAuthenticated();
|
|
138
|
+
}
|
|
139
|
+
return result;
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
disconnect() {
|
|
143
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
144
|
+
this.destruct();
|
|
145
|
+
yield this.client.disconnect();
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
intoAuthenticated() {
|
|
149
|
+
this.destruct();
|
|
150
|
+
return new AuthenticatedSSHClient(this.client, this.events);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
exports.SSHClient = SSHClient;
|
|
154
|
+
class AuthenticatedSSHClient extends helpers_1.Destructible {
|
|
155
|
+
constructor(client, events) {
|
|
156
|
+
super();
|
|
157
|
+
this.client = client;
|
|
158
|
+
this.events = events;
|
|
159
|
+
this.disconnect$ = this.events.disconnect$;
|
|
160
|
+
this.x11ChannelOpen$ = this.events.x11ChannelOpen$.pipe((0, rxjs_1.map)(([ch, address, port]) => ({
|
|
161
|
+
channel: new channel_1.NewChannel(ch),
|
|
162
|
+
clientAddress: address,
|
|
163
|
+
clientPort: port,
|
|
164
|
+
})));
|
|
165
|
+
this.tcpChannelOpen$ = this.events.tcpChannelOpen$.pipe((0, rxjs_1.map)(([ch, targetAddress, targetPort, clientAddress, clientPort,]) => ({
|
|
166
|
+
channel: new channel_1.NewChannel(ch),
|
|
167
|
+
targetAddress,
|
|
168
|
+
targetPort,
|
|
169
|
+
clientAddress,
|
|
170
|
+
clientPort,
|
|
171
|
+
})));
|
|
172
|
+
this.agentChannelOpen$ = this.events.agentChannelOpen$.pipe((0, rxjs_1.map)(([ch]) => new channel_1.NewChannel(ch)));
|
|
173
|
+
}
|
|
174
|
+
openSessionChannel() {
|
|
175
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
176
|
+
return yield new channel_1.NewChannel(yield this.client.channelOpenSession());
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
openTCPForwardChannel(options) {
|
|
180
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
181
|
+
return new channel_1.NewChannel(yield this.client.channelOpenDirectTcpip(options.addressToConnectTo, options.portToConnectTo, options.originatorAddress, options.originatorPort));
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
forwardTCPPort(addressToBind, portToBind) {
|
|
185
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
186
|
+
return yield this.client.tcpipForward(addressToBind, portToBind);
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
stopForwardingTCPPort(addressToBind, portToBind) {
|
|
190
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
191
|
+
yield this.client.cancelTcpipForward(addressToBind, portToBind);
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
disconnect() {
|
|
195
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
196
|
+
this.destruct();
|
|
197
|
+
yield this.client.disconnect();
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
activateChannel(ch) {
|
|
201
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
202
|
+
let channel = yield ch.take().activate();
|
|
203
|
+
return this.wrapChannel(channel);
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
activateSFTP(ch) {
|
|
207
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
208
|
+
let channel = yield ch.take().activateSftp();
|
|
209
|
+
return new sftp_1.SFTP(channel, this.events);
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
wrapChannel(channel) {
|
|
213
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
214
|
+
let id = yield channel.id();
|
|
215
|
+
return new channel_1.Channel(id, channel, this.events);
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
exports.AuthenticatedSSHClient = AuthenticatedSSHClient;
|
|
220
|
+
var native_2 = require("./native");
|
|
221
|
+
Object.defineProperty(exports, "KeyboardInteractiveAuthenticationPrompt", { enumerable: true, get: function () { return native_2.KeyboardInteractiveAuthenticationPrompt; } });
|
|
222
|
+
Object.defineProperty(exports, "SshPublicKey", { enumerable: true, get: function () { return native_2.SshPublicKey; } });
|
|
223
|
+
Object.defineProperty(exports, "SshTransport", { enumerable: true, get: function () { return native_2.SshTransport; } });
|
|
224
|
+
Object.defineProperty(exports, "SshChannel", { enumerable: true, get: function () { return native_2.SshChannel; } });
|
|
225
|
+
Object.defineProperty(exports, "NewSshChannel", { enumerable: true, get: function () { return native_2.NewSshChannel; } });
|
|
226
|
+
Object.defineProperty(exports, "getSupportedCiphers", { enumerable: true, get: function () { return native_2.supportedCiphers; } });
|
|
227
|
+
Object.defineProperty(exports, "getSupportedKexAlgorithms", { enumerable: true, get: function () { return native_2.supportedKexAlgorithms; } });
|
|
228
|
+
Object.defineProperty(exports, "getSupportedMACs", { enumerable: true, get: function () { return native_2.supportedMacs; } });
|
|
229
|
+
Object.defineProperty(exports, "getSupportedCompressionAlgorithms", { enumerable: true, get: function () { return native_2.supportedCompressionAlgorithms; } });
|
|
230
|
+
Object.defineProperty(exports, "getSupportedKeyTypes", { enumerable: true, get: function () { return native_2.supportedKeyTypes; } });
|
|
231
|
+
Object.defineProperty(exports, "OPEN_APPEND", { enumerable: true, get: function () { return native_2.OPEN_APPEND; } });
|
|
232
|
+
Object.defineProperty(exports, "OPEN_CREATE", { enumerable: true, get: function () { return native_2.OPEN_CREATE; } });
|
|
233
|
+
Object.defineProperty(exports, "OPEN_READ", { enumerable: true, get: function () { return native_2.OPEN_READ; } });
|
|
234
|
+
Object.defineProperty(exports, "OPEN_TRUNCATE", { enumerable: true, get: function () { return native_2.OPEN_TRUNCATE; } });
|
|
235
|
+
Object.defineProperty(exports, "OPEN_WRITE", { enumerable: true, get: function () { return native_2.OPEN_WRITE; } });
|
|
236
|
+
Object.defineProperty(exports, "SFTPFile", { enumerable: true, get: function () { return native_2.SftpFile; } });
|
|
237
|
+
Object.defineProperty(exports, "isPageantRunning", { enumerable: true, get: function () { return native_2.isPageantRunning; } });
|
|
238
|
+
Object.defineProperty(exports, "parsePublicKey", { enumerable: true, get: function () { return native_2.parsePublicKey; } });
|
|
239
|
+
var sftp_2 = require("./sftp");
|
|
240
|
+
Object.defineProperty(exports, "SFTP", { enumerable: true, get: function () { return sftp_2.SFTP; } });
|
|
241
|
+
var agent_2 = require("./agent");
|
|
242
|
+
Object.defineProperty(exports, "SSHAgentStream", { enumerable: true, get: function () { return agent_2.SSHAgentStream; } });
|
package/lib/native.d.ts
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
/* auto-generated by NAPI-RS */
|
|
5
|
+
|
|
6
|
+
export const enum AgentConnectionKind {
|
|
7
|
+
Pageant = 0,
|
|
8
|
+
Pipe = 1,
|
|
9
|
+
Unix = 2
|
|
10
|
+
}
|
|
11
|
+
function connectAgent(connection: AgentConnection, callback: ((err: Error | null, arg: Uint8Array) => any)): Promise<SshAgentStream>
|
|
12
|
+
export const enum HashAlgorithm {
|
|
13
|
+
Sha1 = 0,
|
|
14
|
+
Sha256 = 1,
|
|
15
|
+
Sha512 = 2
|
|
16
|
+
}
|
|
17
|
+
function parseKey(data: string, password?: string | undefined | null): SshKeyPair
|
|
18
|
+
function isPageantRunning(): boolean
|
|
19
|
+
/** Parse a public key from OpenSSH format string (e.g., "ssh-ed25519 AAAA... comment") */
|
|
20
|
+
function parsePublicKey(data: string): SshPublicKey
|
|
21
|
+
export const OPEN_READ: number
|
|
22
|
+
export const OPEN_WRITE: number
|
|
23
|
+
export const OPEN_APPEND: number
|
|
24
|
+
export const OPEN_CREATE: number
|
|
25
|
+
export const OPEN_TRUNCATE: number
|
|
26
|
+
export const enum SftpFileType {
|
|
27
|
+
Directory = 0,
|
|
28
|
+
File = 1,
|
|
29
|
+
Symlink = 2,
|
|
30
|
+
Other = 3
|
|
31
|
+
}
|
|
32
|
+
function supportedCiphers(): Array<string>
|
|
33
|
+
function supportedKexAlgorithms(): Array<string>
|
|
34
|
+
function supportedMacs(): Array<string>
|
|
35
|
+
function supportedCompressionAlgorithms(): Array<string>
|
|
36
|
+
function supportedKeyTypes(): Array<string>
|
|
37
|
+
function connect(transport: SshTransport, cipherAlgos: Array<string> | undefined | null, kexAlgos: Array<string> | undefined | null, keyAlgos: Array<string> | undefined | null, macAlgos: Array<string> | undefined | null, compressionAlgos: Array<string> | undefined | null, connectionTimeoutSeconds: number | undefined | null, keepaliveIntervalSeconds: number | undefined | null, keepaliveMax: number, serverKeyCallback: ((err: Error | null, arg: SshPublicKey) => Promise<boolean>), dataCallback: ((err: Error | null, arg0: number, arg1: Uint8Array) => any), extendedDataCallback: ((err: Error | null, arg0: number, arg1: number, arg2: Uint8Array) => any), eofCallback: ((err: Error | null, arg: number) => any), closeCallback: ((err: Error | null, arg: number) => any), disconnectCallback: ((err: Error | null, arg: Error | undefined | null) => any), x11ChannelOpenCallback: ((err: Error | null, arg0: NewSshChannel, arg1: string, arg2: number) => any), tcpipChannelOpenCallback: ((err: Error | null, arg0: NewSshChannel, arg1: string, arg2: number, arg3: string, arg4: number) => any), agentChannelOpenCallback: ((err: Error | null, arg: NewSshChannel) => any), bannerCallback: ((err: Error | null, arg: string) => any)): Promise<SshClient>
|
|
38
|
+
export class AgentConnection {
|
|
39
|
+
kind: AgentConnectionKind
|
|
40
|
+
path?: string
|
|
41
|
+
static new(kind: AgentConnectionKind, path?: string | undefined | null): AgentConnection
|
|
42
|
+
}
|
|
43
|
+
export class SshAgentStream {
|
|
44
|
+
write(data: Uint8Array): Promise<void>
|
|
45
|
+
close(): Promise<void>
|
|
46
|
+
}
|
|
47
|
+
export class NewSshChannel {
|
|
48
|
+
activate(): Promise<SshChannel>
|
|
49
|
+
activateSftp(): Promise<SftpChannel>
|
|
50
|
+
}
|
|
51
|
+
export class SshChannel {
|
|
52
|
+
id(): Promise<number>
|
|
53
|
+
requestPty(term: string, colWidth: number, rowHeight: number, pixWidth: number, pixHeight: number): Promise<void>
|
|
54
|
+
requestShell(): Promise<void>
|
|
55
|
+
requestExec(command: string): Promise<void>
|
|
56
|
+
requestX11Forwarding(singleConnection: boolean, x11Protocol: string, x11Cookie: string, screen: number): Promise<void>
|
|
57
|
+
requestAgentForwarding(): Promise<void>
|
|
58
|
+
windowChange(colWidth: number, rowHeight: number, pixWidth: number, pixHeight: number): Promise<void>
|
|
59
|
+
data(data: Uint8Array): Promise<void>
|
|
60
|
+
eof(): Promise<void>
|
|
61
|
+
close(): Promise<void>
|
|
62
|
+
}
|
|
63
|
+
export class SshPublicKey {
|
|
64
|
+
algorithm(): string
|
|
65
|
+
fingerprint(): string
|
|
66
|
+
base64(): string
|
|
67
|
+
bytes(): Uint8Array
|
|
68
|
+
}
|
|
69
|
+
export class SshKeyPair {
|
|
70
|
+
publicKey(): SshPublicKey
|
|
71
|
+
}
|
|
72
|
+
export class SftpFileMetadata {
|
|
73
|
+
size: string
|
|
74
|
+
uid?: number
|
|
75
|
+
user?: string
|
|
76
|
+
gid?: number
|
|
77
|
+
group?: string
|
|
78
|
+
permissions?: number
|
|
79
|
+
atime?: number
|
|
80
|
+
mtime?: number
|
|
81
|
+
type(): SftpFileType
|
|
82
|
+
}
|
|
83
|
+
export class SftpDirEntry {
|
|
84
|
+
name: string
|
|
85
|
+
type: SftpFileType
|
|
86
|
+
metadata(): SftpFileMetadata
|
|
87
|
+
}
|
|
88
|
+
export class SftpFile {
|
|
89
|
+
read(n: number): Promise<Uint8Array>
|
|
90
|
+
writeAll(data: Uint8Array): Promise<void>
|
|
91
|
+
flush(): Promise<void>
|
|
92
|
+
shutdown(): Promise<void>
|
|
93
|
+
}
|
|
94
|
+
export class SftpChannel {
|
|
95
|
+
channelId: number
|
|
96
|
+
readDir(path: string): Promise<Array<SftpDirEntry>>
|
|
97
|
+
stat(path: string): Promise<SftpFileMetadata>
|
|
98
|
+
createDir(path: string): Promise<void>
|
|
99
|
+
readlink(path: string): Promise<string>
|
|
100
|
+
rename(src: string, dst: string): Promise<void>
|
|
101
|
+
chmod(path: string, mode: number): Promise<void>
|
|
102
|
+
removeDir(path: string): Promise<void>
|
|
103
|
+
removeFile(path: string): Promise<void>
|
|
104
|
+
close(): Promise<void>
|
|
105
|
+
open(path: string, mode: number): Promise<SftpFile>
|
|
106
|
+
}
|
|
107
|
+
export class SshTransport {
|
|
108
|
+
static newSocket(address: string): Promise<SshTransport>
|
|
109
|
+
static newCommand(command: string, args: Array<string>): Promise<SshTransport>
|
|
110
|
+
static newSshChannel(channel: NewSshChannel): Promise<SshTransport>
|
|
111
|
+
static newSocksProxy(proxyHost: string, proxyPort: number, targetHost: string, targetPort: number): Promise<SshTransport>
|
|
112
|
+
static newHttpProxy(proxyHost: string, proxyPort: number, targetHost: string, targetPort: number): Promise<SshTransport>
|
|
113
|
+
}
|
|
114
|
+
export class KeyboardInteractiveAuthenticationPrompt {
|
|
115
|
+
prompt: string
|
|
116
|
+
echo: boolean
|
|
117
|
+
}
|
|
118
|
+
export class KeyboardInteractiveAuthenticationState {
|
|
119
|
+
state: string
|
|
120
|
+
partialSuccess: boolean
|
|
121
|
+
name?: string
|
|
122
|
+
instructions?: string
|
|
123
|
+
remainingMethods: Array<string>
|
|
124
|
+
prompts(): Array<KeyboardInteractiveAuthenticationPrompt> | null
|
|
125
|
+
}
|
|
126
|
+
export class SshAuthResult {
|
|
127
|
+
success: boolean
|
|
128
|
+
partialSuccess: boolean
|
|
129
|
+
remainingMethods: Array<string>
|
|
130
|
+
}
|
|
131
|
+
export class SshClient {
|
|
132
|
+
authenticateNone(username: string): Promise<SshAuthResult>
|
|
133
|
+
authenticatePassword(username: string, password: string): Promise<SshAuthResult>
|
|
134
|
+
authenticatePublickey(username: string, key: SshKeyPair, hashAlgorithm?: HashAlgorithm | undefined | null): Promise<SshAuthResult>
|
|
135
|
+
startKeyboardInteractiveAuthentication(username: string): Promise<KeyboardInteractiveAuthenticationState>
|
|
136
|
+
respondToKeyboardInteractiveAuthentication(responses: Array<string>): Promise<KeyboardInteractiveAuthenticationState>
|
|
137
|
+
authenticateAgent(username: string, connection: AgentConnection, specificKey?: SshPublicKey | undefined | null): Promise<SshAuthResult>
|
|
138
|
+
channelOpenSession(): Promise<NewSshChannel>
|
|
139
|
+
tcpipForward(address: string, port: number): Promise<number>
|
|
140
|
+
cancelTcpipForward(address: string, port: number): Promise<void>
|
|
141
|
+
channelOpenDirectTcpip(address: string, port: number, originatorAddress: string, originatorPort: number): Promise<NewSshChannel>
|
|
142
|
+
disconnect(): Promise<void>
|
|
143
|
+
}
|
package/lib/native.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
let _russh
|
|
2
|
+
|
|
3
|
+
const nativeModule = process.env.RUST_TARGET_TRIPLE || {
|
|
4
|
+
win32: {
|
|
5
|
+
x64: 'win32-x64-msvc',
|
|
6
|
+
arm64: 'win32-arm64-msvc'
|
|
7
|
+
},
|
|
8
|
+
darwin: {
|
|
9
|
+
x64: 'darwin-x64',
|
|
10
|
+
arm64: 'darwin-arm64'
|
|
11
|
+
},
|
|
12
|
+
linux: {
|
|
13
|
+
x64: 'linux-x64-gnu',
|
|
14
|
+
arm: 'linux-arm-gnueabihf',
|
|
15
|
+
arm64: 'linux-arm64-gnu'
|
|
16
|
+
}
|
|
17
|
+
}[process.platform][process.arch]
|
|
18
|
+
|
|
19
|
+
// try {
|
|
20
|
+
_russh = require(`../russh.${nativeModule}.node`)
|
|
21
|
+
// } catch {
|
|
22
|
+
// _russh = require('../russh.node')
|
|
23
|
+
// }
|
|
24
|
+
|
|
25
|
+
module.exports = _russh
|
package/lib/sftp.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as russh from './native';
|
|
2
|
+
import { ClientEventInterface } from './events';
|
|
3
|
+
import { Destructible } from "./helpers";
|
|
4
|
+
export interface SFTPMetadata {
|
|
5
|
+
size: number;
|
|
6
|
+
type: russh.SftpFileType;
|
|
7
|
+
uid?: number;
|
|
8
|
+
user?: string;
|
|
9
|
+
gid?: number;
|
|
10
|
+
group?: string;
|
|
11
|
+
permissions?: number;
|
|
12
|
+
atime?: number;
|
|
13
|
+
mtime?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface SFTPDirectoryEntry {
|
|
16
|
+
name: string;
|
|
17
|
+
metadata: SFTPMetadata;
|
|
18
|
+
}
|
|
19
|
+
export declare class SFTP extends Destructible {
|
|
20
|
+
private inner;
|
|
21
|
+
private events;
|
|
22
|
+
readonly closed$: import("rxjs").Observable<void>;
|
|
23
|
+
constructor(inner: russh.SftpChannel, events: ClientEventInterface);
|
|
24
|
+
createDirectory(path: string): Promise<void>;
|
|
25
|
+
removeDirectory(path: string): Promise<void>;
|
|
26
|
+
removeFile(path: string): Promise<void>;
|
|
27
|
+
readlink(path: string): Promise<string>;
|
|
28
|
+
rename(src: string, dst: string): Promise<void>;
|
|
29
|
+
stat(path: string): Promise<SFTPMetadata>;
|
|
30
|
+
readDirectory(path: string): Promise<SFTPDirectoryEntry[]>;
|
|
31
|
+
chmod(path: string, mode: string | number): Promise<void>;
|
|
32
|
+
close(): Promise<void>;
|
|
33
|
+
open(path: string, mode: number): Promise<russh.SftpFile>;
|
|
34
|
+
}
|
package/lib/sftp.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.SFTP = void 0;
|
|
13
|
+
const helpers_1 = require("./helpers");
|
|
14
|
+
class SFTP extends helpers_1.Destructible {
|
|
15
|
+
constructor(inner, events) {
|
|
16
|
+
super();
|
|
17
|
+
this.inner = inner;
|
|
18
|
+
this.events = events;
|
|
19
|
+
this.closed$ = this.events.close$.subscribe(this.inner.channelId);
|
|
20
|
+
// Trigger subscriptions to stop buffering data
|
|
21
|
+
this.events.data$.subscribe(this.inner.channelId).subscribe().unsubscribe();
|
|
22
|
+
this.events.extendedData$.subscribe(this.inner.channelId).subscribe().unsubscribe();
|
|
23
|
+
}
|
|
24
|
+
createDirectory(path) {
|
|
25
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
26
|
+
this.assertNotDestructed();
|
|
27
|
+
yield this.inner.createDir(path);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
removeDirectory(path) {
|
|
31
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
32
|
+
this.assertNotDestructed();
|
|
33
|
+
yield this.inner.removeDir(path);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
removeFile(path) {
|
|
37
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
38
|
+
this.assertNotDestructed();
|
|
39
|
+
yield this.inner.removeFile(path);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
readlink(path) {
|
|
43
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
44
|
+
this.assertNotDestructed();
|
|
45
|
+
return this.inner.readlink(path);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
rename(src, dst) {
|
|
49
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
+
this.assertNotDestructed();
|
|
51
|
+
yield this.inner.rename(src, dst);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
stat(path) {
|
|
55
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
56
|
+
this.assertNotDestructed();
|
|
57
|
+
const md = yield this.inner.stat(path);
|
|
58
|
+
return Object.assign(Object.assign({}, md), { type: md.type(), size: parseInt(md.size) });
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
readDirectory(path) {
|
|
62
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
63
|
+
this.assertNotDestructed();
|
|
64
|
+
let entries = yield this.inner.readDir(path);
|
|
65
|
+
return entries.map(e => {
|
|
66
|
+
const md = e.metadata();
|
|
67
|
+
return {
|
|
68
|
+
name: e.name,
|
|
69
|
+
metadata: {
|
|
70
|
+
// Can't just spread a napi object
|
|
71
|
+
type: e.type,
|
|
72
|
+
size: parseInt(md.size),
|
|
73
|
+
atime: md.atime,
|
|
74
|
+
mtime: md.mtime,
|
|
75
|
+
gid: md.gid,
|
|
76
|
+
group: md.group,
|
|
77
|
+
permissions: md.permissions,
|
|
78
|
+
uid: md.uid,
|
|
79
|
+
user: md.user,
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
chmod(path, mode) {
|
|
86
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
87
|
+
this.assertNotDestructed();
|
|
88
|
+
let parsed = typeof mode === 'string' ? parseInt(mode, 8) : mode;
|
|
89
|
+
yield this.inner.chmod(path, parsed);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
close() {
|
|
93
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
94
|
+
yield this.inner.close();
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
open(path, mode) {
|
|
98
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
99
|
+
const f = yield this.inner.open(path, mode);
|
|
100
|
+
return f;
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
exports.SFTP = SFTP;
|