ai-remote 0.4.7 → 0.4.8
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/README.md +84 -2
- package/SKILL.md +49 -1
- package/dist/apple-dh.d.ts +27 -0
- package/dist/apple-dh.js +1 -0
- package/dist/cli.mjs +2978 -210
- package/dist/protocols/rdp/buffer.d.ts +38 -0
- package/dist/protocols/rdp/caps.d.ts +49 -0
- package/dist/protocols/rdp/cert.d.ts +18 -0
- package/dist/protocols/rdp/client.d.ts +56 -0
- package/dist/protocols/rdp/cliprdr.d.ts +27 -0
- package/dist/protocols/rdp/credssp.d.ts +34 -0
- package/dist/protocols/rdp/crypto.d.ts +63 -0
- package/dist/protocols/rdp/display.d.ts +38 -0
- package/dist/protocols/rdp/gcc.d.ts +23 -0
- package/dist/protocols/rdp/keymap.d.ts +9 -0
- package/dist/protocols/rdp/mcs.d.ts +40 -0
- package/dist/protocols/rdp/ntlm.d.ts +61 -0
- package/dist/protocols/rdp/pdu.d.ts +155 -0
- package/dist/protocols/rdp/rail.d.ts +119 -0
- package/dist/protocols/rdp/rle.d.ts +13 -0
- package/dist/protocols/rdp/sec.d.ts +59 -0
- package/dist/protocols/rdp/session.d.ts +62 -0
- package/dist/protocols/rdp/tls.d.ts +18 -0
- package/dist/protocols/rdp/vchannel.d.ts +28 -0
- package/dist/protocols/rdp/x224.d.ts +40 -0
- package/dist/protocols/ssh/identity.d.ts +39 -0
- package/dist/protocols/ssh/kex.d.ts +97 -0
- package/dist/protocols/ssh/messages.d.ts +52 -0
- package/dist/protocols/ssh/session.d.ts +67 -0
- package/dist/protocols/ssh/terminal.d.ts +46 -0
- package/dist/protocols/ssh/transport.d.ts +62 -0
- package/dist/protocols/ssh/wire.d.ts +52 -0
- package/dist/protocols/types.d.ts +127 -0
- package/dist/protocols/vnc/des.d.ts +25 -0
- package/dist/protocols/vnc/input.d.ts +5 -0
- package/dist/protocols/vnc/keysyms.d.ts +16 -0
- package/dist/protocols/vnc/rfb.d.ts +64 -0
- package/dist/protocols/vnc/session.d.ts +12 -0
- package/dist/protocols.js +13 -13
- package/dist/shared/connection.d.ts +81 -0
- package/dist/shared/device.d.ts +26 -0
- package/dist/shared/hosts.d.ts +63 -0
- package/dist/shared/icons.d.ts +46 -0
- package/dist/shared/protocol.d.ts +32 -0
- package/dist/shared/signals.d.ts +37 -0
- package/package.json +8 -3
- /package/dist/{protocols.d.ts → protocols/index.d.ts} +0 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { Reader } from './buffer';
|
|
2
|
+
export declare const RAIL_ORDER: {
|
|
3
|
+
EXEC: number;
|
|
4
|
+
ACTIVATE: number;
|
|
5
|
+
SYSPARAM: number;
|
|
6
|
+
SYSCOMMAND: number;
|
|
7
|
+
HANDSHAKE: number;
|
|
8
|
+
WINDOW_MOVE: number;
|
|
9
|
+
CLIENT_STATUS: number;
|
|
10
|
+
EXEC_RESULT: number;
|
|
11
|
+
HANDSHAKE_EX: number;
|
|
12
|
+
};
|
|
13
|
+
export declare const RAIL_EXEC_RESULT: {
|
|
14
|
+
0: string;
|
|
15
|
+
1: string;
|
|
16
|
+
2: string;
|
|
17
|
+
3: string;
|
|
18
|
+
5: string;
|
|
19
|
+
6: string;
|
|
20
|
+
7: string;
|
|
21
|
+
};
|
|
22
|
+
/** WM_SYSCOMMAND values a RAIL client may ask the host to apply to a window. */
|
|
23
|
+
export declare const SYS_COMMAND: {
|
|
24
|
+
MINIMIZE: number;
|
|
25
|
+
MAXIMIZE: number;
|
|
26
|
+
CLOSE: number;
|
|
27
|
+
RESTORE: number;
|
|
28
|
+
};
|
|
29
|
+
/** SW_* show states reported by a window order's ShowState field. */
|
|
30
|
+
export declare const SHOW_STATE: {
|
|
31
|
+
HIDDEN: number;
|
|
32
|
+
MINIMIZED: number;
|
|
33
|
+
MAXIMIZED: number;
|
|
34
|
+
NORMAL: number;
|
|
35
|
+
};
|
|
36
|
+
export declare const WINDOW_ORDER: {
|
|
37
|
+
TYPE_WINDOW: number;
|
|
38
|
+
STATE_NEW: number;
|
|
39
|
+
STATE_DELETED: number;
|
|
40
|
+
ICON: number;
|
|
41
|
+
CACHED_ICON: number;
|
|
42
|
+
};
|
|
43
|
+
export declare function railHandshake(buildNumber?: number): Uint8Array<ArrayBufferLike>;
|
|
44
|
+
export declare function railClientStatus(flags?: number): Uint8Array<ArrayBufferLike>;
|
|
45
|
+
/**
|
|
46
|
+
* SPI_SETWORKAREA. This is how a RAIL client tells the host how much room it
|
|
47
|
+
* has, and the host maximizes remote windows into it. Sending it again during
|
|
48
|
+
* the session is what keeps a maximized window matched to the browser window.
|
|
49
|
+
*/
|
|
50
|
+
export declare function railWorkArea(width: number, height: number): Uint8Array<ArrayBufferLike>;
|
|
51
|
+
export declare function railSystemParameters(width: number, height: number): Uint8Array<ArrayBufferLike>[];
|
|
52
|
+
/** TS_RAIL_ORDER_ACTIVATE: give (or take) input focus for one remote window. */
|
|
53
|
+
export declare function railActivate(windowId: number, enabled?: boolean): Uint8Array<ArrayBufferLike>;
|
|
54
|
+
/** TS_RAIL_ORDER_SYSCOMMAND: minimize, maximize, restore or close a window. */
|
|
55
|
+
export declare function railSysCommand(windowId: number, command: string): Uint8Array<ArrayBufferLike>;
|
|
56
|
+
/**
|
|
57
|
+
* TS_RAIL_ORDER_WINDOWMOVE. A client that draws remote windows itself sends
|
|
58
|
+
* this when the user finishes moving or resizing one; the host then applies
|
|
59
|
+
* the rectangle to the real window. It is the only way to give a remote window
|
|
60
|
+
* an exact size, which is what fitting one to the browser viewport needs.
|
|
61
|
+
*/
|
|
62
|
+
export declare function railWindowMove(windowId: number, { left, top, right, bottom }: {
|
|
63
|
+
bottom: any;
|
|
64
|
+
left: any;
|
|
65
|
+
right: any;
|
|
66
|
+
top: any;
|
|
67
|
+
}): Uint8Array<ArrayBufferLike>;
|
|
68
|
+
/** Build TS_RAIL_ORDER_EXEC. Strings are UTF-16LE and are not terminated. */
|
|
69
|
+
export declare function railExecute({ program, workingDir, arguments: args }: {
|
|
70
|
+
arguments?: string;
|
|
71
|
+
program: any;
|
|
72
|
+
workingDir?: string;
|
|
73
|
+
}): Uint8Array<ArrayBufferLike>;
|
|
74
|
+
/**
|
|
75
|
+
* True for a window the session exists to show: not a child, not a tool
|
|
76
|
+
* window, and not one of the never-activated popups a Chromium or Electron
|
|
77
|
+
* application creates for menus, tooltips and drag images.
|
|
78
|
+
*/
|
|
79
|
+
export declare function isPrimaryWindow(candidate: any): boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Parse the window lifecycle subset of TS_UPDATE_ORDERS_PDU_DATA.
|
|
82
|
+
*
|
|
83
|
+
* RemoteApp window orders are Alternate Secondary orders and, unlike ordinary
|
|
84
|
+
* drawing orders, carry their total size in every header. That lets the parser
|
|
85
|
+
* read the fields it understands and then seek to the next order, rather than
|
|
86
|
+
* having to understand every icon, notification and desktop order to stay in
|
|
87
|
+
* sync with the stream.
|
|
88
|
+
*/
|
|
89
|
+
export declare function parseRemoteAppWindowOrders(reader: Reader): any[];
|
|
90
|
+
/** Parse one or more complete RAIL PDUs delivered in a channel message. */
|
|
91
|
+
export declare function parseRailPdus(bytes: Uint8Array): any[];
|
|
92
|
+
/**
|
|
93
|
+
* Minimal RAIL endpoint for the browser client. It deliberately suppresses
|
|
94
|
+
* icon orders because the browser currently presents the RemoteApp session in
|
|
95
|
+
* one canvas rather than creating a local OS window per remote window.
|
|
96
|
+
*/
|
|
97
|
+
export declare class RailChannel {
|
|
98
|
+
private readonly application;
|
|
99
|
+
private width;
|
|
100
|
+
private height;
|
|
101
|
+
private readonly send;
|
|
102
|
+
private readonly onReady;
|
|
103
|
+
private readonly onResult;
|
|
104
|
+
private started;
|
|
105
|
+
constructor({ application, width, height, send, onReady, onResult }: {
|
|
106
|
+
application: any;
|
|
107
|
+
height: any;
|
|
108
|
+
onReady: any;
|
|
109
|
+
onResult: any;
|
|
110
|
+
send: any;
|
|
111
|
+
width: any;
|
|
112
|
+
});
|
|
113
|
+
receive(bytes: Uint8Array): void;
|
|
114
|
+
/** Republish the client's work area, which is what maximize resizes into. */
|
|
115
|
+
setWorkArea(width: number, height: number): boolean;
|
|
116
|
+
activate(windowId: number): boolean;
|
|
117
|
+
sysCommand(windowId: number, command: string): boolean;
|
|
118
|
+
moveWindow(windowId: number, rectangle: any): boolean;
|
|
119
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare function rleDecompress(src: Uint8Array, width: number, height: number, bytesPerPixel: number): Uint32Array<ArrayBuffer>;
|
|
2
|
+
/**
|
|
3
|
+
* Reverse the row order of a decoded rectangle. RDP stores bitmaps bottom-up
|
|
4
|
+
* and a canvas expects top-down, so without this every rectangle is painted
|
|
5
|
+
* upside down.
|
|
6
|
+
*/
|
|
7
|
+
export declare function flipRows(pixels: Uint8Array, width: number): Uint32Array<ArrayBuffer> | Uint8Array<ArrayBufferLike>;
|
|
8
|
+
/** Read uncompressed bitmap data, which RDP stores bottom-up. */
|
|
9
|
+
export declare function readUncompressed(src: Uint8Array, width: number, height: number, bytesPerPixel: number): Uint32Array<ArrayBuffer>;
|
|
10
|
+
/** Expand raw pixel values into RGBA for putImageData. */
|
|
11
|
+
export declare function pixelsToRgba(pixels: Uint8Array, bitsPerPixel: number, palette: Uint32Array): Uint8ClampedArray<ArrayBuffer>;
|
|
12
|
+
/** Decode one TS_BITMAP_DATA rectangle to RGBA. */
|
|
13
|
+
export declare function decodeBitmapRect(rect: BitmapRect, palette: Uint32Array): Uint8ClampedArray<ArrayBuffer>;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { concatBytes } from './buffer';
|
|
2
|
+
export declare const SEC_FLAG: {
|
|
3
|
+
EXCHANGE_PKT: number;
|
|
4
|
+
TRANSPORT_REQ: number;
|
|
5
|
+
ENCRYPT: number;
|
|
6
|
+
RESET_SEQNO: number;
|
|
7
|
+
IGNORE_SEQNO: number;
|
|
8
|
+
INFO_PKT: number;
|
|
9
|
+
LICENSE_PKT: number;
|
|
10
|
+
LICENSE_ENCRYPT_CS: number;
|
|
11
|
+
REDIRECTION_PKT: number;
|
|
12
|
+
SECURE_CHECKSUM: number;
|
|
13
|
+
AUTODETECT_REQ: number;
|
|
14
|
+
AUTODETECT_RSP: number;
|
|
15
|
+
HEARTBEAT: number;
|
|
16
|
+
};
|
|
17
|
+
export declare class SecurityLayer {
|
|
18
|
+
#private;
|
|
19
|
+
private encryptionMethod;
|
|
20
|
+
private encryptionLevel;
|
|
21
|
+
private keys;
|
|
22
|
+
private encryptState;
|
|
23
|
+
private decryptState;
|
|
24
|
+
private encryptedPdus;
|
|
25
|
+
private decryptedPdus;
|
|
26
|
+
constructor();
|
|
27
|
+
/** True when data PDUs carry a basic security header at all. */
|
|
28
|
+
get headerPresent(): boolean;
|
|
29
|
+
get encryptionEnabled(): boolean;
|
|
30
|
+
configure(encryptionMethod: number, encryptionLevel: number, clientRandom: Uint8Array, serverRandom: Uint8Array): void;
|
|
31
|
+
/**
|
|
32
|
+
* Prefix a payload with the basic security header, signing and encrypting it
|
|
33
|
+
* when the negotiated level asks for that.
|
|
34
|
+
*
|
|
35
|
+
* `flags` carries the PDU-kind bits (SEC_INFO_PKT and friends). A payload with
|
|
36
|
+
* no flags and no encryption needs no header at all.
|
|
37
|
+
*/
|
|
38
|
+
wrap(payload: Uint8Array, flags?: number): Uint8Array<ArrayBufferLike>;
|
|
39
|
+
/**
|
|
40
|
+
* Strip (and if needed decrypt) the basic security header from a host PDU.
|
|
41
|
+
* `headerMandatory` forces the header to be read even when the host reported
|
|
42
|
+
* no encryption, which licensing PDUs require.
|
|
43
|
+
*/
|
|
44
|
+
unwrap(bytes: Uint8Array, headerMandatory?: boolean): {
|
|
45
|
+
flags: number;
|
|
46
|
+
payload: Uint8Array<ArrayBufferLike>;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Fast-path output carries the same signature and RC4 stream as a slow-path
|
|
50
|
+
* PDU, but without the basic security header in front of it.
|
|
51
|
+
*/
|
|
52
|
+
decryptFastPath(payload: Uint8Array): Uint8Array<ArrayBufferLike>;
|
|
53
|
+
/**
|
|
54
|
+
* Security Exchange PDU (MS-RDPBCGR 2.2.1.10): the client random encrypted
|
|
55
|
+
* with the host public key, followed by eight bytes of padding.
|
|
56
|
+
*/
|
|
57
|
+
static securityExchange(encryptedClientRandom: any): Uint8Array<ArrayBufferLike>;
|
|
58
|
+
}
|
|
59
|
+
export { concatBytes };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { ProtocolDriver } from '../types';
|
|
2
|
+
export declare class RdpSession extends EventTarget {
|
|
3
|
+
#private;
|
|
4
|
+
readonly protocol: 'rdp';
|
|
5
|
+
constructor(container: any, url: string, options?: {});
|
|
6
|
+
/**
|
|
7
|
+
* Ask the host to size the remote application's window to the room this
|
|
8
|
+
* session has on the page. Full-desktop sessions have nothing to do here:
|
|
9
|
+
* their size is fixed when the connection is negotiated.
|
|
10
|
+
*/
|
|
11
|
+
fitToViewport(): any;
|
|
12
|
+
get connected(): boolean;
|
|
13
|
+
get canvas(): HTMLCanvasElement | null;
|
|
14
|
+
/** The workspace instruments this socket for byte counters and keepalives. */
|
|
15
|
+
get socket(): WebSocket | null;
|
|
16
|
+
get _sock(): {
|
|
17
|
+
_websocket: any;
|
|
18
|
+
};
|
|
19
|
+
get scaleViewport(): any;
|
|
20
|
+
set scaleViewport(enabled: any);
|
|
21
|
+
get viewOnly(): any;
|
|
22
|
+
set viewOnly(enabled: any);
|
|
23
|
+
/**
|
|
24
|
+
* The on-screen keyboard and the special-keys dialog call this with an X11
|
|
25
|
+
* keysym and a DOM code. RDP wants a scancode, so the code decides; the
|
|
26
|
+
* keysym is only a fallback for characters with no key of their own.
|
|
27
|
+
*/
|
|
28
|
+
sendKey(keysym: any, code: number, pressed: boolean): void;
|
|
29
|
+
sendCtrlAltDel(): void;
|
|
30
|
+
/** Desktop pixels. Returns false when the session cannot accept input. */
|
|
31
|
+
movePointer(x: number, y: number): boolean;
|
|
32
|
+
clickPointer(x: number, y: number, button?: number): boolean;
|
|
33
|
+
pointerButton(x: number, y: number, button?: number, pressed?: boolean): boolean;
|
|
34
|
+
scrollPointer(x: number, y: number, delta: {
|
|
35
|
+
x: number;
|
|
36
|
+
y: number;
|
|
37
|
+
}): boolean;
|
|
38
|
+
/** Type a run of characters, which RDP carries as Unicode rather than keys. */
|
|
39
|
+
typeText(text: string): boolean;
|
|
40
|
+
/** What the canvas is showing, for a screen capture or a coordinate check. */
|
|
41
|
+
get screenGeometry(): {
|
|
42
|
+
width: any;
|
|
43
|
+
height: any;
|
|
44
|
+
viewport: any;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Hand text to the host's clipboard, falling back to typing it when the host
|
|
48
|
+
* declined the clipboard channel -- xrdp builds often do.
|
|
49
|
+
*/
|
|
50
|
+
clipboardPasteFrom(text: string): void;
|
|
51
|
+
/**
|
|
52
|
+
* Deliver text into the session, which is what the clipboard drawer's button
|
|
53
|
+
* has always visibly done. `clipboardPasteFrom` only loads the clipboard, the
|
|
54
|
+
* way noVNC's method of that name does.
|
|
55
|
+
*/
|
|
56
|
+
pasteText(text: string): any;
|
|
57
|
+
releaseKeyboard(): void;
|
|
58
|
+
/** True once the host has agreed to share its clipboard. */
|
|
59
|
+
get clipboardShared(): any;
|
|
60
|
+
disconnect(): void;
|
|
61
|
+
}
|
|
62
|
+
export declare const rdpDriver: ProtocolDriver;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare class Tls12Client {
|
|
2
|
+
#private;
|
|
3
|
+
/**
|
|
4
|
+
* @param {(bytes: Uint8Array) => void} send write raw bytes to the transport
|
|
5
|
+
* @param {(bytes: Uint8Array) => void} onData decrypted application data
|
|
6
|
+
* @param {(error: Error) => void} onError fatal protocol failure
|
|
7
|
+
*/
|
|
8
|
+
constructor({ send, onData, onError }: {
|
|
9
|
+
onData: any;
|
|
10
|
+
onError: any;
|
|
11
|
+
send: any;
|
|
12
|
+
});
|
|
13
|
+
start(): Promise<any>;
|
|
14
|
+
/** Feed transport bytes. Calls are serialized, so order is preserved. */
|
|
15
|
+
receive(bytes: Uint8Array): any;
|
|
16
|
+
/** Send application data once the handshake has completed. */
|
|
17
|
+
write(plaintext: Uint8Array): any;
|
|
18
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** Channel option bits used when the channel is declared in Client Network Data. */
|
|
2
|
+
export declare const CHANNEL_OPTION: {
|
|
3
|
+
INITIALIZED: number;
|
|
4
|
+
ENCRYPT_RDP: number;
|
|
5
|
+
COMPRESS_RDP: number;
|
|
6
|
+
SHOW_PROTOCOL: number;
|
|
7
|
+
};
|
|
8
|
+
export declare const CHANNEL_FLAG_SHOW_PROTOCOL = 16;
|
|
9
|
+
/** What RDP itself uses; a host may accept more, but never needs to. */
|
|
10
|
+
export declare const CHANNEL_CHUNK_LENGTH = 1600;
|
|
11
|
+
/**
|
|
12
|
+
* Split one logical channel message into wire chunks, each already carrying its
|
|
13
|
+
* CHANNEL_PDU_HEADER. An empty message still produces one chunk, because the
|
|
14
|
+
* header is what tells the host anything happened at all.
|
|
15
|
+
*/
|
|
16
|
+
export declare function chunkChannelData(data: Uint8Array, chunkSize?: number, extraFlags?: number): any[];
|
|
17
|
+
/**
|
|
18
|
+
* Reassemble inbound chunks into whole messages. A chunk that arrives without a
|
|
19
|
+
* preceding FIRST is treated as its own message rather than dropped: some hosts
|
|
20
|
+
* send small PDUs with both flags set and others with neither.
|
|
21
|
+
*/
|
|
22
|
+
export declare class ChannelReassembler {
|
|
23
|
+
private parts;
|
|
24
|
+
private expectedLength;
|
|
25
|
+
constructor();
|
|
26
|
+
/** Returns the completed message, or null while more chunks are pending. */
|
|
27
|
+
push(bytes: Uint8Array): Uint8Array<ArrayBufferLike>;
|
|
28
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export declare const TPKT_VERSION = 3;
|
|
2
|
+
export declare const TPKT_HEADER_LENGTH = 4;
|
|
3
|
+
export declare const NEG_FAILURE: {
|
|
4
|
+
SSL_REQUIRED: number;
|
|
5
|
+
SSL_NOT_ALLOWED: number;
|
|
6
|
+
SSL_CERT_NOT_ON_SERVER: number;
|
|
7
|
+
INCONSISTENT_FLAGS: number;
|
|
8
|
+
HYBRID_REQUIRED: number;
|
|
9
|
+
SSL_WITH_USER_AUTH_REQUIRED: number;
|
|
10
|
+
};
|
|
11
|
+
export declare const NEG_PROTOCOL: {
|
|
12
|
+
RDP: number;
|
|
13
|
+
SSL: number;
|
|
14
|
+
HYBRID: number;
|
|
15
|
+
RDSTLS: number;
|
|
16
|
+
HYBRID_EX: number;
|
|
17
|
+
};
|
|
18
|
+
/** X.224 Connection Request, carrying the protocols this client will accept. */
|
|
19
|
+
export declare function connectionRequest(requestedProtocols: number): Uint8Array<ArrayBufferLike>;
|
|
20
|
+
/**
|
|
21
|
+
* Read the X.224 Connection Confirm. Throws with the host's own explanation
|
|
22
|
+
* when it refuses the requested protocol.
|
|
23
|
+
*/
|
|
24
|
+
export declare function parseConnectionConfirm(frame: Uint8Array): {
|
|
25
|
+
selectedProtocol: number;
|
|
26
|
+
negotiated: boolean;
|
|
27
|
+
};
|
|
28
|
+
/** Wrap a payload in TPKT + X.224 Data. */
|
|
29
|
+
export declare function dataFrame(payload: Uint8Array): Uint8Array<ArrayBufferLike>;
|
|
30
|
+
/** Strip TPKT + X.224 Data headers from a complete frame. */
|
|
31
|
+
export declare function dataPayload(frame: Uint8Array): Uint8Array<ArrayBufferLike>;
|
|
32
|
+
/**
|
|
33
|
+
* Split a byte stream into whole frames. RDP interleaves two framings on one
|
|
34
|
+
* connection: TPKT (first byte 0x03) and fast-path output (any other value),
|
|
35
|
+
* each with its own length encoding.
|
|
36
|
+
*/
|
|
37
|
+
export declare function splitFrames(buffer: Uint8Array): {
|
|
38
|
+
frames: any[];
|
|
39
|
+
rest: Uint8Array<ArrayBufferLike>;
|
|
40
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signing in with a key instead of a password.
|
|
3
|
+
*
|
|
4
|
+
* An identity is a public key blob, the algorithm name that goes with it, and
|
|
5
|
+
* something that can sign. What does the signing is deliberately behind a
|
|
6
|
+
* function: a key read off disk signs with Web Crypto, and a key held by
|
|
7
|
+
* ssh-agent signs by asking the agent -- the session cannot tell the two apart
|
|
8
|
+
* and does not need to.
|
|
9
|
+
*
|
|
10
|
+
* The parser here reads the format `ssh-keygen` writes by default, which no
|
|
11
|
+
* runtime can parse on its own: OpenSSH's own container rather than PKCS#8.
|
|
12
|
+
* Only unencrypted keys are read. A key with a passphrase would need bcrypt
|
|
13
|
+
* and a prompt, and the answer to a passphrase is ssh-agent, which is already
|
|
14
|
+
* holding the decrypted key.
|
|
15
|
+
*/
|
|
16
|
+
/** One key that can sign for a user, however it happens to be held. */
|
|
17
|
+
export interface SshIdentity {
|
|
18
|
+
/** The public key type, e.g. `ssh-ed25519`. */
|
|
19
|
+
readonly keyType: string;
|
|
20
|
+
/** The public key, in the wire format the host expects. */
|
|
21
|
+
readonly keyBlob: Uint8Array;
|
|
22
|
+
/** Where it came from, for logs and error messages. */
|
|
23
|
+
readonly comment: string;
|
|
24
|
+
/**
|
|
25
|
+
* Signature algorithms to offer, best first. RSA keys sign under several,
|
|
26
|
+
* and a host will say which of them it is willing to take.
|
|
27
|
+
*/
|
|
28
|
+
readonly algorithms: readonly string[];
|
|
29
|
+
/** The full signature blob (algorithm name and signature) over `data`. */
|
|
30
|
+
sign(data: Uint8Array, algorithm: string): Promise<Uint8Array>;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Read a private key file.
|
|
34
|
+
*
|
|
35
|
+
* Returns one identity, or throws with the reason a human can act on -- which
|
|
36
|
+
* for the common failure is "this key has a passphrase, so let ssh-agent hold
|
|
37
|
+
* it" rather than a decoder error.
|
|
38
|
+
*/
|
|
39
|
+
export declare function parsePrivateKey(text: string, comment?: string): Promise<SshIdentity>;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/** Key exchange methods, best first. All of them hash with SHA-256. */
|
|
2
|
+
export declare const KEX_ALGORITHMS: {
|
|
3
|
+
'curve25519-sha256': {
|
|
4
|
+
type: string;
|
|
5
|
+
hash: string;
|
|
6
|
+
};
|
|
7
|
+
'curve25519-sha256@libssh.org': {
|
|
8
|
+
type: string;
|
|
9
|
+
hash: string;
|
|
10
|
+
};
|
|
11
|
+
'ecdh-sha2-nistp256': {
|
|
12
|
+
type: string;
|
|
13
|
+
curve: string;
|
|
14
|
+
hash: string;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Host key signature algorithms. `keyType` is what appears inside the key blob;
|
|
19
|
+
* a modern RSA key is signed with SHA-256 or SHA-512 but still calls itself
|
|
20
|
+
* ssh-rsa, so the two names differ there.
|
|
21
|
+
*/
|
|
22
|
+
export declare const HOST_KEY_ALGORITHMS: {
|
|
23
|
+
'ssh-ed25519': {
|
|
24
|
+
keyType: string;
|
|
25
|
+
kind: string;
|
|
26
|
+
};
|
|
27
|
+
'rsa-sha2-512': {
|
|
28
|
+
keyType: string;
|
|
29
|
+
kind: string;
|
|
30
|
+
hash: string;
|
|
31
|
+
};
|
|
32
|
+
'rsa-sha2-256': {
|
|
33
|
+
keyType: string;
|
|
34
|
+
kind: string;
|
|
35
|
+
hash: string;
|
|
36
|
+
};
|
|
37
|
+
'ecdsa-sha2-nistp256': {
|
|
38
|
+
keyType: string;
|
|
39
|
+
kind: string;
|
|
40
|
+
curve: string;
|
|
41
|
+
hash: string;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* What this browser can actually do. X25519 and Ed25519 are recent additions to
|
|
46
|
+
* Web Crypto, so they are probed rather than assumed; the NIST curve and RSA
|
|
47
|
+
* have been there all along and always keep the session possible.
|
|
48
|
+
*/
|
|
49
|
+
export declare function negotiableAlgorithms(): Promise<any>;
|
|
50
|
+
/** The client half of one key exchange. */
|
|
51
|
+
export declare function createKexClient(algorithmName: string): Promise<{
|
|
52
|
+
hash: any;
|
|
53
|
+
publicKey: Uint8Array<ArrayBuffer>;
|
|
54
|
+
sharedSecret(serverPublicKey: any): Promise<Uint8Array<ArrayBuffer>>;
|
|
55
|
+
}>;
|
|
56
|
+
/** The key type named inside a host key blob, which the algorithm must match. */
|
|
57
|
+
export declare function hostKeyType(keyBlob: Uint8Array): string;
|
|
58
|
+
/** The SHA256:… fingerprint OpenSSH prints, so a user can compare it. */
|
|
59
|
+
export declare function hostKeyFingerprint(keyBlob: Uint8Array): Promise<string>;
|
|
60
|
+
/**
|
|
61
|
+
* Check that the host owns the key it presented, by verifying its signature
|
|
62
|
+
* over the exchange hash. A failure here is fatal: it is what stands between
|
|
63
|
+
* the session and a machine in the middle of it.
|
|
64
|
+
*/
|
|
65
|
+
export declare function verifyHostKeySignature({ algorithm, keyBlob, signatureBlob, exchangeHash }: {
|
|
66
|
+
algorithm: any;
|
|
67
|
+
exchangeHash: any;
|
|
68
|
+
keyBlob: any;
|
|
69
|
+
signatureBlob: any;
|
|
70
|
+
}): Promise<boolean>;
|
|
71
|
+
/**
|
|
72
|
+
* The exchange hash H (RFC 4253 section 8), which both sides compute from the
|
|
73
|
+
* same inputs and the host signs.
|
|
74
|
+
*/
|
|
75
|
+
export declare function exchangeHash({ hash, clientVersion, serverVersion, clientKexInit, serverKexInit, hostKeyBlob, clientPublicKey, serverPublicKey, sharedSecret, }: {
|
|
76
|
+
clientKexInit: any;
|
|
77
|
+
clientPublicKey: any;
|
|
78
|
+
clientVersion: any;
|
|
79
|
+
hash: any;
|
|
80
|
+
hostKeyBlob: any;
|
|
81
|
+
serverKexInit: any;
|
|
82
|
+
serverPublicKey: any;
|
|
83
|
+
serverVersion: any;
|
|
84
|
+
sharedSecret: any;
|
|
85
|
+
}): Promise<Uint8Array<ArrayBuffer>>;
|
|
86
|
+
/**
|
|
87
|
+
* Derive one key from the exchange (RFC 4253 section 7.2), extending it with
|
|
88
|
+
* further hash rounds when the cipher wants more bytes than one digest.
|
|
89
|
+
*/
|
|
90
|
+
export declare function deriveKey({ hash, sharedSecret, exchangeHash: h, letter, sessionId, length }: {
|
|
91
|
+
exchangeHash: any;
|
|
92
|
+
hash: any;
|
|
93
|
+
length: any;
|
|
94
|
+
letter: any;
|
|
95
|
+
sessionId: any;
|
|
96
|
+
sharedSecret: any;
|
|
97
|
+
}): Promise<Uint8Array<ArrayBuffer>>;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export declare const MSG: {
|
|
2
|
+
DISCONNECT: number;
|
|
3
|
+
IGNORE: number;
|
|
4
|
+
UNIMPLEMENTED: number;
|
|
5
|
+
DEBUG: number;
|
|
6
|
+
SERVICE_REQUEST: number;
|
|
7
|
+
SERVICE_ACCEPT: number;
|
|
8
|
+
EXT_INFO: number;
|
|
9
|
+
KEXINIT: number;
|
|
10
|
+
NEWKEYS: number;
|
|
11
|
+
KEX_ECDH_INIT: number;
|
|
12
|
+
KEX_ECDH_REPLY: number;
|
|
13
|
+
USERAUTH_REQUEST: number;
|
|
14
|
+
USERAUTH_FAILURE: number;
|
|
15
|
+
USERAUTH_SUCCESS: number;
|
|
16
|
+
USERAUTH_BANNER: number;
|
|
17
|
+
USERAUTH_INFO_REQUEST: number;
|
|
18
|
+
/** The same number, in a publickey exchange: "that key would be accepted". */
|
|
19
|
+
USERAUTH_PK_OK: number;
|
|
20
|
+
USERAUTH_INFO_RESPONSE: number;
|
|
21
|
+
GLOBAL_REQUEST: number;
|
|
22
|
+
REQUEST_SUCCESS: number;
|
|
23
|
+
REQUEST_FAILURE: number;
|
|
24
|
+
CHANNEL_OPEN: number;
|
|
25
|
+
CHANNEL_OPEN_CONFIRMATION: number;
|
|
26
|
+
CHANNEL_OPEN_FAILURE: number;
|
|
27
|
+
CHANNEL_WINDOW_ADJUST: number;
|
|
28
|
+
CHANNEL_DATA: number;
|
|
29
|
+
CHANNEL_EXTENDED_DATA: number;
|
|
30
|
+
CHANNEL_EOF: number;
|
|
31
|
+
CHANNEL_CLOSE: number;
|
|
32
|
+
CHANNEL_REQUEST: number;
|
|
33
|
+
CHANNEL_SUCCESS: number;
|
|
34
|
+
CHANNEL_FAILURE: number;
|
|
35
|
+
};
|
|
36
|
+
/** SSH_EXTENDED_DATA_STDERR. */
|
|
37
|
+
export declare const EXTENDED_DATA_STDERR = 1;
|
|
38
|
+
export declare const DISCONNECT_REASON: {
|
|
39
|
+
1: string;
|
|
40
|
+
2: string;
|
|
41
|
+
3: string;
|
|
42
|
+
5: string;
|
|
43
|
+
6: string;
|
|
44
|
+
7: string;
|
|
45
|
+
8: string;
|
|
46
|
+
9: string;
|
|
47
|
+
10: string;
|
|
48
|
+
11: string;
|
|
49
|
+
12: string;
|
|
50
|
+
14: string;
|
|
51
|
+
15: string;
|
|
52
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
export declare const DEFAULT_PORT = 22;
|
|
2
|
+
/**
|
|
3
|
+
* How patient `runCommand` is, in three different senses.
|
|
4
|
+
*
|
|
5
|
+
* A single deadline cannot tell "the shell ignored me" apart from "the
|
|
6
|
+
* installer is three minutes into a download", and a short one turns every
|
|
7
|
+
* real piece of work -- a package install, a build, a large copy -- into a
|
|
8
|
+
* false failure that also leaves the command running on the far side.
|
|
9
|
+
*
|
|
10
|
+
* So the wait is judged by what the shell is doing. It has START_MS to
|
|
11
|
+
* acknowledge the command at all; after that it may take as long as it likes
|
|
12
|
+
* as long as it keeps printing, and only silence longer than IDLE_MS, or a run
|
|
13
|
+
* longer than MAX_MS, is treated as stuck.
|
|
14
|
+
*/
|
|
15
|
+
export declare const COMMAND_START_MS = 20000;
|
|
16
|
+
export declare const COMMAND_IDLE_MS: number;
|
|
17
|
+
export declare const COMMAND_MAX_MS: number;
|
|
18
|
+
/**
|
|
19
|
+
* The one line that runs `command` and marks where its output starts and ends.
|
|
20
|
+
*
|
|
21
|
+
* Each shell gets its own, because none of the three agree on how to print a
|
|
22
|
+
* string, run a command and read back its exit status.
|
|
23
|
+
*/
|
|
24
|
+
export declare function frameCommand(family: any, command: string, id: any): string;
|
|
25
|
+
export declare class SshSession extends EventTarget {
|
|
26
|
+
#private;
|
|
27
|
+
/**
|
|
28
|
+
* @param {string} url gateway WebSocket URL
|
|
29
|
+
* @param {object} options
|
|
30
|
+
* @param {string} options.username
|
|
31
|
+
* @param {string} [options.password]
|
|
32
|
+
* @param {SshIdentity[] | (() => Promise<SshIdentity[]>)} [options.identities]
|
|
33
|
+
* @param {'powershell'} [options.preferredShell]
|
|
34
|
+
* @param {(info: object) => Promise<boolean>} [options.verifyHost]
|
|
35
|
+
* @param {(prompt: object) => Promise<string>} [options.requestInput]
|
|
36
|
+
*/
|
|
37
|
+
constructor(url: string, options?: {});
|
|
38
|
+
connect(): void;
|
|
39
|
+
disconnect(): void;
|
|
40
|
+
/** Send keystrokes, or anything else the terminal produces, to the shell. */
|
|
41
|
+
write(data: Uint8Array): void;
|
|
42
|
+
/**
|
|
43
|
+
* Run one command in this shell and return what it printed.
|
|
44
|
+
*
|
|
45
|
+
* Deliberately the *same* shell the user is looking at, not a second channel:
|
|
46
|
+
* a command the assistant runs inherits the working directory, the
|
|
47
|
+
* environment and the login the user already has, and it appears in their
|
|
48
|
+
* terminal as it happens. An agent acting on a machine invisibly is worse
|
|
49
|
+
* than an agent that is slower to read.
|
|
50
|
+
*
|
|
51
|
+
* The output is framed by markers rather than measured, because an
|
|
52
|
+
* interactive shell echoes its input and prints a prompt around it. The
|
|
53
|
+
* markers are assembled by the shell from two pieces, so the echoed command
|
|
54
|
+
* line -- which contains the pieces but not the joined marker -- never looks
|
|
55
|
+
* like the real boundary.
|
|
56
|
+
*
|
|
57
|
+
* A `command` event brackets the run so the terminal can label it, and the
|
|
58
|
+
* three deadlines above decide when a command is stuck rather than slow.
|
|
59
|
+
*/
|
|
60
|
+
runCommand(command: string, { startMs, idleMs, maxMs, }?: {
|
|
61
|
+
idleMs?: number;
|
|
62
|
+
maxMs?: number;
|
|
63
|
+
startMs?: number;
|
|
64
|
+
}): Promise<unknown>;
|
|
65
|
+
/** Tell the shell its window changed, so full-screen programs redraw. */
|
|
66
|
+
resize(columns: number, rows: number): void;
|
|
67
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export declare class SshTerminal {
|
|
2
|
+
constructor(container: any);
|
|
3
|
+
get columns(): any;
|
|
4
|
+
get rows(): any;
|
|
5
|
+
onData(handler: any): void;
|
|
6
|
+
onResize(handler: any): void;
|
|
7
|
+
write(data: Uint8Array): void;
|
|
8
|
+
/** Gateway-side notices, kept visually apart from what the host prints. */
|
|
9
|
+
notice(text: string, tone?: string): void;
|
|
10
|
+
clear(): void;
|
|
11
|
+
focus(): void;
|
|
12
|
+
/**
|
|
13
|
+
* Size the terminal to the panel, choosing the font so MIN_COLUMNS fit.
|
|
14
|
+
*
|
|
15
|
+
* The columns matter more than the type size here: the commands people run in
|
|
16
|
+
* a side panel -- `ls -l`, `top`, anything in PowerShell that prints a table
|
|
17
|
+
* -- are laid out for 80 columns, and a narrower grid wraps every row into an
|
|
18
|
+
* unreadable stack.
|
|
19
|
+
*
|
|
20
|
+
* `proposeDimensions()` reports the grid the current font size yields, and a
|
|
21
|
+
* monospace cell's width scales with its font size, so `fontSize * cols /
|
|
22
|
+
* MIN_COLUMNS` lands close to the size that gives MIN_COLUMNS. It is measured
|
|
23
|
+
* rather than assumed because the cell-width-to-font-size ratio belongs to
|
|
24
|
+
* whichever font the platform picked. A second pass settles the rounding.
|
|
25
|
+
* Changing the font resizes the element, which the ResizeObserver sees, so
|
|
26
|
+
* the guard keeps that from recursing.
|
|
27
|
+
*/
|
|
28
|
+
fit(): void;
|
|
29
|
+
/** The grid the host is being told about, for a status line or a log. */
|
|
30
|
+
get geometry(): {
|
|
31
|
+
columns: any;
|
|
32
|
+
rows: any;
|
|
33
|
+
fontSize: any;
|
|
34
|
+
};
|
|
35
|
+
get selection(): any;
|
|
36
|
+
/**
|
|
37
|
+
* Read one line from the user, for a password or a one-time code the host
|
|
38
|
+
* asked for during authentication. The shell is not open yet, so the
|
|
39
|
+
* terminal is free to be a prompt.
|
|
40
|
+
*/
|
|
41
|
+
readLine({ prompt, echo }?: {
|
|
42
|
+
echo?: boolean;
|
|
43
|
+
prompt?: string;
|
|
44
|
+
}): Promise<unknown>;
|
|
45
|
+
destroy(): void;
|
|
46
|
+
}
|