fied 0.2.8 → 0.2.9
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/dist/bin.js +53 -34
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -262,9 +262,13 @@ async function share(options) {
|
|
|
262
262
|
}
|
|
263
263
|
const cols = options.cols ?? process.stdout.columns ?? 80;
|
|
264
264
|
const rows = options.rows ?? process.stdout.rows ?? 24;
|
|
265
|
-
const
|
|
266
|
-
const
|
|
267
|
-
const
|
|
265
|
+
const legacyKey = options.keyBase64Url;
|
|
266
|
+
const readKeyRaw = options.readKeyBase64Url ? fromBase64Url(options.readKeyBase64Url) : legacyKey ? fromBase64Url(legacyKey) : await generateKey();
|
|
267
|
+
const writeKeyRaw = options.writeKeyBase64Url ? fromBase64Url(options.writeKeyBase64Url) : legacyKey ? fromBase64Url(legacyKey) : await generateKey();
|
|
268
|
+
const readKey = await importKey(readKeyRaw);
|
|
269
|
+
const writeKey = await importKey(writeKeyRaw);
|
|
270
|
+
const readKeyFragment = options.readKeyBase64Url ?? legacyKey ?? toBase64Url(readKeyRaw);
|
|
271
|
+
const writeKeyFragment = options.writeKeyBase64Url ?? legacyKey ?? toBase64Url(writeKeyRaw);
|
|
268
272
|
const pty = attachSession(targetSession, cols, rows);
|
|
269
273
|
if (!options.background) {
|
|
270
274
|
console.log("");
|
|
@@ -276,8 +280,10 @@ async function share(options) {
|
|
|
276
280
|
}
|
|
277
281
|
const bridge = new RelayBridge(
|
|
278
282
|
relayTarget,
|
|
279
|
-
|
|
280
|
-
|
|
283
|
+
readKey,
|
|
284
|
+
writeKey,
|
|
285
|
+
readKeyFragment,
|
|
286
|
+
writeKeyFragment,
|
|
281
287
|
pty,
|
|
282
288
|
options.background,
|
|
283
289
|
options.showReadonlyLink,
|
|
@@ -360,24 +366,22 @@ async function createSession(relayHttpBase) {
|
|
|
360
366
|
throw new Error(`Failed to create session: ${res.status} ${res.statusText}`);
|
|
361
367
|
}
|
|
362
368
|
const data = await res.json();
|
|
363
|
-
if (typeof data.sessionId !== "string"
|
|
369
|
+
if (typeof data.sessionId !== "string") {
|
|
364
370
|
throw new Error("Invalid session creation response");
|
|
365
371
|
}
|
|
366
|
-
return
|
|
367
|
-
sessionId: data.sessionId,
|
|
368
|
-
viewerAccessToken: data.viewerAccessToken,
|
|
369
|
-
readonlyAccessToken: data.readonlyAccessToken
|
|
370
|
-
};
|
|
372
|
+
return data.sessionId;
|
|
371
373
|
}
|
|
372
374
|
var WS_CONNECT_TIMEOUT_MS = 1e4;
|
|
373
375
|
function typeAAD(type) {
|
|
374
376
|
return new Uint8Array([type & 255]);
|
|
375
377
|
}
|
|
376
378
|
var RelayBridge = class {
|
|
377
|
-
constructor(relayTarget,
|
|
379
|
+
constructor(relayTarget, readKey, writeKey, readKeyFragment, writeKeyFragment, pty, silent = false, showReadonlyLink = false, sessionId) {
|
|
378
380
|
this.relayTarget = relayTarget;
|
|
379
|
-
this.
|
|
380
|
-
this.
|
|
381
|
+
this.readKey = readKey;
|
|
382
|
+
this.writeKey = writeKey;
|
|
383
|
+
this.readKeyFragment = readKeyFragment;
|
|
384
|
+
this.writeKeyFragment = writeKeyFragment;
|
|
381
385
|
this.pty = pty;
|
|
382
386
|
this.silent = silent;
|
|
383
387
|
this.showReadonlyLink = showReadonlyLink;
|
|
@@ -396,8 +400,6 @@ var RelayBridge = class {
|
|
|
396
400
|
encoder = new TextEncoder();
|
|
397
401
|
decoder = new TextDecoder();
|
|
398
402
|
sessionId = null;
|
|
399
|
-
viewerAccessToken = null;
|
|
400
|
-
readonlyAccessToken = null;
|
|
401
403
|
onUrl = null;
|
|
402
404
|
invalidResizeFrames = 0;
|
|
403
405
|
invalidInputFrames = 0;
|
|
@@ -413,24 +415,16 @@ var RelayBridge = class {
|
|
|
413
415
|
}
|
|
414
416
|
if (!this.sessionId) {
|
|
415
417
|
try {
|
|
416
|
-
|
|
417
|
-
this.sessionId = created.sessionId;
|
|
418
|
-
this.viewerAccessToken = created.viewerAccessToken;
|
|
419
|
-
this.readonlyAccessToken = created.readonlyAccessToken;
|
|
418
|
+
this.sessionId = await createSession(this.relayTarget.httpBase);
|
|
420
419
|
} catch {
|
|
421
420
|
if (!this.silent) console.error(" \x1B[31mRelay unreachable, retrying...\x1B[0m");
|
|
422
421
|
this.scheduleReconnect();
|
|
423
422
|
return;
|
|
424
423
|
}
|
|
425
424
|
const shareUrl = new URL(`s/${this.sessionId}`, this.relayTarget.httpBase);
|
|
426
|
-
|
|
427
|
-
throw new Error("missing access tokens");
|
|
428
|
-
}
|
|
429
|
-
shareUrl.searchParams.set("token", this.viewerAccessToken);
|
|
430
|
-
const interactiveUrl = `${shareUrl.toString()}#${this.keyFragment}`;
|
|
425
|
+
const interactiveUrl = `${shareUrl.toString()}#r=${encodeURIComponent(this.readKeyFragment)}&w=${encodeURIComponent(this.writeKeyFragment)}`;
|
|
431
426
|
const readonlyShareUrl = new URL(`${shareUrl.pathname.replace(/\/$/, "")}/v`, shareUrl);
|
|
432
|
-
readonlyShareUrl.
|
|
433
|
-
const readonlyUrl = `${readonlyShareUrl.toString()}#${this.keyFragment}`;
|
|
427
|
+
const readonlyUrl = `${readonlyShareUrl.toString()}#r=${encodeURIComponent(this.readKeyFragment)}`;
|
|
434
428
|
if (!this.silent) {
|
|
435
429
|
await printShareLinkWithQr("interactive", interactiveUrl);
|
|
436
430
|
if (this.showReadonlyLink) {
|
|
@@ -474,7 +468,7 @@ var RelayBridge = class {
|
|
|
474
468
|
const data = new Uint8Array(raw);
|
|
475
469
|
const frame = parseFrame(data);
|
|
476
470
|
if (frame.type === MSG_TERMINAL_INPUT) {
|
|
477
|
-
const plaintext = await decrypt(this.
|
|
471
|
+
const plaintext = await decrypt(this.writeKey, frame.iv, frame.ciphertext, typeAAD(frame.type));
|
|
478
472
|
const input = parseInputPayload(this.decoder.decode(plaintext));
|
|
479
473
|
if (!input || this.isReplayNonce(input.nonce)) {
|
|
480
474
|
this.invalidInputFrames += 1;
|
|
@@ -487,7 +481,7 @@ var RelayBridge = class {
|
|
|
487
481
|
this.rememberInputNonce(input.nonce);
|
|
488
482
|
this.pty.write(input.data);
|
|
489
483
|
} else if (frame.type === MSG_RESIZE) {
|
|
490
|
-
const plaintext = await decrypt(this.
|
|
484
|
+
const plaintext = await decrypt(this.writeKey, frame.iv, frame.ciphertext, typeAAD(frame.type));
|
|
491
485
|
const resize = parseResizePayload(this.decoder.decode(plaintext));
|
|
492
486
|
if (!resize) {
|
|
493
487
|
this.invalidResizeFrames += 1;
|
|
@@ -546,7 +540,8 @@ var RelayBridge = class {
|
|
|
546
540
|
async sendEncrypted(type, plaintext) {
|
|
547
541
|
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;
|
|
548
542
|
try {
|
|
549
|
-
const
|
|
543
|
+
const key = type === MSG_TERMINAL_OUTPUT ? this.readKey : this.writeKey;
|
|
544
|
+
const { iv, ciphertext } = await encrypt(key, plaintext, typeAAD(type));
|
|
550
545
|
const frame = frameMessage(type, iv, ciphertext);
|
|
551
546
|
this.ws.send(frame);
|
|
552
547
|
} catch (err) {
|
|
@@ -714,6 +709,10 @@ if (args.includes("--__daemon")) {
|
|
|
714
709
|
options.showReadonlyLink = true;
|
|
715
710
|
} else if (args[i] === "--__session-id" && args[i + 1]) {
|
|
716
711
|
options.sessionId = args[++i];
|
|
712
|
+
} else if (args[i] === "--__read-key" && args[i + 1]) {
|
|
713
|
+
options.readKeyBase64Url = args[++i];
|
|
714
|
+
} else if (args[i] === "--__write-key" && args[i + 1]) {
|
|
715
|
+
options.writeKeyBase64Url = args[++i];
|
|
717
716
|
} else if (args[i] === "--__key" && args[i + 1]) {
|
|
718
717
|
options.keyBase64Url = args[++i];
|
|
719
718
|
}
|
|
@@ -819,7 +818,8 @@ async function main() {
|
|
|
819
818
|
relay,
|
|
820
819
|
allowInsecureRelay,
|
|
821
820
|
sessionId: parsed.sessionId,
|
|
822
|
-
|
|
821
|
+
readKeyBase64Url: parsed.readKeyBase64Url,
|
|
822
|
+
writeKeyBase64Url: parsed.writeKeyBase64Url
|
|
823
823
|
});
|
|
824
824
|
console.error("");
|
|
825
825
|
console.error(` \x1B[1m\x1B[32mfied\x1B[0m \u2014 moved to background (PID ${child.pid})`);
|
|
@@ -839,8 +839,10 @@ function spawnBackground(options) {
|
|
|
839
839
|
options.session,
|
|
840
840
|
"--__session-id",
|
|
841
841
|
options.sessionId,
|
|
842
|
-
"--
|
|
843
|
-
options.
|
|
842
|
+
"--__read-key",
|
|
843
|
+
options.readKeyBase64Url,
|
|
844
|
+
"--__write-key",
|
|
845
|
+
options.writeKeyBase64Url
|
|
844
846
|
];
|
|
845
847
|
if (options.relay) childArgs.push("--relay", options.relay);
|
|
846
848
|
if (options.allowInsecureRelay) childArgs.push("--allow-insecure-relay");
|
|
@@ -857,9 +859,26 @@ function parseShareUrl(url) {
|
|
|
857
859
|
if (!match || !parsed.hash) {
|
|
858
860
|
throw new Error("Invalid share URL");
|
|
859
861
|
}
|
|
862
|
+
const hashRaw = parsed.hash.slice(1);
|
|
863
|
+
let readKeyBase64Url = "";
|
|
864
|
+
let writeKeyBase64Url = "";
|
|
865
|
+
if (hashRaw.includes("=") || hashRaw.includes("&")) {
|
|
866
|
+
const params = new URLSearchParams(hashRaw);
|
|
867
|
+
const read = params.get("r");
|
|
868
|
+
const write = params.get("w");
|
|
869
|
+
if (read && write) {
|
|
870
|
+
readKeyBase64Url = read;
|
|
871
|
+
writeKeyBase64Url = write;
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
if (!readKeyBase64Url || !writeKeyBase64Url) {
|
|
875
|
+
readKeyBase64Url = hashRaw;
|
|
876
|
+
writeKeyBase64Url = hashRaw;
|
|
877
|
+
}
|
|
860
878
|
return {
|
|
861
879
|
sessionId: match[1],
|
|
862
|
-
|
|
880
|
+
readKeyBase64Url,
|
|
881
|
+
writeKeyBase64Url
|
|
863
882
|
};
|
|
864
883
|
}
|
|
865
884
|
function timeSince(date) {
|