@novnc/novnc 1.3.0-beta → 1.3.0-g1075cd8
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 +13 -3
- package/core/decoders/jpeg.js +141 -0
- package/core/decoders/raw.js +1 -1
- package/core/decoders/zrle.js +185 -0
- package/core/encodings.js +4 -0
- package/core/ra2.js +567 -0
- package/core/rfb.js +219 -8
- package/core/util/md5.js +79 -0
- package/docs/API.md +44 -4
- package/lib/base64.js +1 -1
- package/lib/decoders/copyrect.js +1 -1
- package/lib/decoders/hextile.js +2 -2
- package/lib/decoders/jpeg.js +188 -0
- package/lib/decoders/raw.js +2 -2
- package/lib/decoders/rre.js +1 -1
- package/lib/decoders/tight.js +2 -2
- package/lib/decoders/tightpng.js +3 -3
- package/lib/decoders/zrle.js +234 -0
- package/lib/deflator.js +1 -1
- package/lib/des.js +1 -1
- package/lib/display.js +2 -2
- package/lib/encodings.js +8 -0
- package/lib/inflator.js +1 -1
- package/lib/input/gesturehandler.js +1 -1
- package/lib/input/keyboard.js +2 -2
- package/lib/input/util.js +2 -2
- package/lib/ra2.js +1257 -0
- package/lib/rfb.js +373 -27
- package/lib/util/browser.js +10 -6
- package/lib/util/cursor.js +1 -1
- package/lib/util/events.js +2 -2
- package/lib/util/eventtarget.js +1 -1
- package/lib/util/int.js +1 -1
- package/lib/util/logging.js +2 -2
- package/lib/util/md5.js +103 -0
- package/lib/vendor/pako/lib/utils/common.js +2 -2
- package/lib/vendor/pako/lib/zlib/deflate.js +6 -5
- package/lib/vendor/pako/lib/zlib/inffast.js +6 -2
- package/lib/vendor/pako/lib/zlib/inflate.js +41 -18
- package/lib/vendor/pako/lib/zlib/inftrees.js +1 -1
- package/lib/vendor/pako/lib/zlib/trees.js +3 -3
- package/lib/websock.js +2 -2
- package/package.json +2 -7
package/core/rfb.js
CHANGED
|
@@ -25,6 +25,8 @@ import DES from "./des.js";
|
|
|
25
25
|
import KeyTable from "./input/keysym.js";
|
|
26
26
|
import XtScancode from "./input/xtscancodes.js";
|
|
27
27
|
import { encodings } from "./encodings.js";
|
|
28
|
+
import RSAAESAuthenticationState from "./ra2.js";
|
|
29
|
+
import { MD5 } from "./util/md5.js";
|
|
28
30
|
|
|
29
31
|
import RawDecoder from "./decoders/raw.js";
|
|
30
32
|
import CopyRectDecoder from "./decoders/copyrect.js";
|
|
@@ -32,6 +34,8 @@ import RREDecoder from "./decoders/rre.js";
|
|
|
32
34
|
import HextileDecoder from "./decoders/hextile.js";
|
|
33
35
|
import TightDecoder from "./decoders/tight.js";
|
|
34
36
|
import TightPNGDecoder from "./decoders/tightpng.js";
|
|
37
|
+
import ZRLEDecoder from "./decoders/zrle.js";
|
|
38
|
+
import JPEGDecoder from "./decoders/jpeg.js";
|
|
35
39
|
|
|
36
40
|
// How many seconds to wait for a disconnect to finish
|
|
37
41
|
const DISCONNECT_TIMEOUT = 3;
|
|
@@ -98,6 +102,7 @@ export default class RFB extends EventTargetMixin {
|
|
|
98
102
|
this._rfbInitState = '';
|
|
99
103
|
this._rfbAuthScheme = -1;
|
|
100
104
|
this._rfbCleanDisconnect = true;
|
|
105
|
+
this._rfbRSAAESAuthenticationState = null;
|
|
101
106
|
|
|
102
107
|
// Server capabilities
|
|
103
108
|
this._rfbVersion = 0;
|
|
@@ -176,6 +181,8 @@ export default class RFB extends EventTargetMixin {
|
|
|
176
181
|
handleMouse: this._handleMouse.bind(this),
|
|
177
182
|
handleWheel: this._handleWheel.bind(this),
|
|
178
183
|
handleGesture: this._handleGesture.bind(this),
|
|
184
|
+
handleRSAAESCredentialsRequired: this._handleRSAAESCredentialsRequired.bind(this),
|
|
185
|
+
handleRSAAESServerVerification: this._handleRSAAESServerVerification.bind(this),
|
|
179
186
|
};
|
|
180
187
|
|
|
181
188
|
// main setup
|
|
@@ -218,6 +225,8 @@ export default class RFB extends EventTargetMixin {
|
|
|
218
225
|
this._decoders[encodings.encodingHextile] = new HextileDecoder();
|
|
219
226
|
this._decoders[encodings.encodingTight] = new TightDecoder();
|
|
220
227
|
this._decoders[encodings.encodingTightPNG] = new TightPNGDecoder();
|
|
228
|
+
this._decoders[encodings.encodingZRLE] = new ZRLEDecoder();
|
|
229
|
+
this._decoders[encodings.encodingJPEG] = new JPEGDecoder();
|
|
221
230
|
|
|
222
231
|
// NB: nothing that needs explicit teardown should be done
|
|
223
232
|
// before this point, since this can throw an exception
|
|
@@ -240,6 +249,8 @@ export default class RFB extends EventTargetMixin {
|
|
|
240
249
|
this._sock.on('message', this._handleMessage.bind(this));
|
|
241
250
|
this._sock.on('error', this._socketError.bind(this));
|
|
242
251
|
|
|
252
|
+
this._expectedClientWidth = null;
|
|
253
|
+
this._expectedClientHeight = null;
|
|
243
254
|
this._resizeObserver = new ResizeObserver(this._eventHandlers.handleResize);
|
|
244
255
|
|
|
245
256
|
// All prepared, kick off the connection
|
|
@@ -372,6 +383,15 @@ export default class RFB extends EventTargetMixin {
|
|
|
372
383
|
this._sock.off('error');
|
|
373
384
|
this._sock.off('message');
|
|
374
385
|
this._sock.off('open');
|
|
386
|
+
if (this._rfbRSAAESAuthenticationState !== null) {
|
|
387
|
+
this._rfbRSAAESAuthenticationState.disconnect();
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
approveServer() {
|
|
392
|
+
if (this._rfbRSAAESAuthenticationState !== null) {
|
|
393
|
+
this._rfbRSAAESAuthenticationState.approveServer();
|
|
394
|
+
}
|
|
375
395
|
}
|
|
376
396
|
|
|
377
397
|
sendCredentials(creds) {
|
|
@@ -432,8 +452,8 @@ export default class RFB extends EventTargetMixin {
|
|
|
432
452
|
}
|
|
433
453
|
}
|
|
434
454
|
|
|
435
|
-
focus() {
|
|
436
|
-
this._canvas.focus();
|
|
455
|
+
focus(options) {
|
|
456
|
+
this._canvas.focus(options);
|
|
437
457
|
}
|
|
438
458
|
|
|
439
459
|
blur() {
|
|
@@ -609,7 +629,7 @@ export default class RFB extends EventTargetMixin {
|
|
|
609
629
|
return;
|
|
610
630
|
}
|
|
611
631
|
|
|
612
|
-
this.focus();
|
|
632
|
+
this.focus({ preventScroll: true });
|
|
613
633
|
}
|
|
614
634
|
|
|
615
635
|
_setDesktopName(name) {
|
|
@@ -619,7 +639,26 @@ export default class RFB extends EventTargetMixin {
|
|
|
619
639
|
{ detail: { name: this._fbName } }));
|
|
620
640
|
}
|
|
621
641
|
|
|
642
|
+
_saveExpectedClientSize() {
|
|
643
|
+
this._expectedClientWidth = this._screen.clientWidth;
|
|
644
|
+
this._expectedClientHeight = this._screen.clientHeight;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
_currentClientSize() {
|
|
648
|
+
return [this._screen.clientWidth, this._screen.clientHeight];
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
_clientHasExpectedSize() {
|
|
652
|
+
const [currentWidth, currentHeight] = this._currentClientSize();
|
|
653
|
+
return currentWidth == this._expectedClientWidth &&
|
|
654
|
+
currentHeight == this._expectedClientHeight;
|
|
655
|
+
}
|
|
656
|
+
|
|
622
657
|
_handleResize() {
|
|
658
|
+
// Don't change anything if the client size is already as expected
|
|
659
|
+
if (this._clientHasExpectedSize()) {
|
|
660
|
+
return;
|
|
661
|
+
}
|
|
623
662
|
// If the window resized then our screen element might have
|
|
624
663
|
// as well. Update the viewport dimensions.
|
|
625
664
|
window.requestAnimationFrame(() => {
|
|
@@ -660,6 +699,12 @@ export default class RFB extends EventTargetMixin {
|
|
|
660
699
|
this._display.viewportChangeSize(size.w, size.h);
|
|
661
700
|
this._fixScrollbars();
|
|
662
701
|
}
|
|
702
|
+
|
|
703
|
+
// When changing clipping we might show or hide scrollbars.
|
|
704
|
+
// This causes the expected client dimensions to change.
|
|
705
|
+
if (curClip !== newClip) {
|
|
706
|
+
this._saveExpectedClientSize();
|
|
707
|
+
}
|
|
663
708
|
}
|
|
664
709
|
|
|
665
710
|
_updateScale() {
|
|
@@ -684,6 +729,7 @@ export default class RFB extends EventTargetMixin {
|
|
|
684
729
|
}
|
|
685
730
|
|
|
686
731
|
const size = this._screenSize();
|
|
732
|
+
|
|
687
733
|
RFB.messages.setDesktopSize(this._sock,
|
|
688
734
|
Math.floor(size.w), Math.floor(size.h),
|
|
689
735
|
this._screenID, this._screenFlags);
|
|
@@ -699,12 +745,13 @@ export default class RFB extends EventTargetMixin {
|
|
|
699
745
|
}
|
|
700
746
|
|
|
701
747
|
_fixScrollbars() {
|
|
702
|
-
// This is a hack because
|
|
703
|
-
// for when scrollbars are needed.
|
|
704
|
-
//
|
|
748
|
+
// This is a hack because Safari on macOS screws up the calculation
|
|
749
|
+
// for when scrollbars are needed. We get scrollbars when making the
|
|
750
|
+
// browser smaller, despite remote resize being enabled. So to fix it
|
|
751
|
+
// we temporarily toggle them off and on.
|
|
705
752
|
const orig = this._screen.style.overflow;
|
|
706
753
|
this._screen.style.overflow = 'hidden';
|
|
707
|
-
// Force
|
|
754
|
+
// Force Safari to recalculate the layout by asking for
|
|
708
755
|
// an element's dimensions
|
|
709
756
|
this._screen.getBoundingClientRect();
|
|
710
757
|
this._screen.style.overflow = orig;
|
|
@@ -1242,13 +1289,13 @@ export default class RFB extends EventTargetMixin {
|
|
|
1242
1289
|
break;
|
|
1243
1290
|
case "003.003":
|
|
1244
1291
|
case "003.006": // UltraVNC
|
|
1245
|
-
case "003.889": // Apple Remote Desktop
|
|
1246
1292
|
this._rfbVersion = 3.3;
|
|
1247
1293
|
break;
|
|
1248
1294
|
case "003.007":
|
|
1249
1295
|
this._rfbVersion = 3.7;
|
|
1250
1296
|
break;
|
|
1251
1297
|
case "003.008":
|
|
1298
|
+
case "003.889": // Apple Remote Desktop
|
|
1252
1299
|
case "004.000": // Intel AMT KVM
|
|
1253
1300
|
case "004.001": // RealVNC 4.6
|
|
1254
1301
|
case "005.000": // RealVNC 5.3
|
|
@@ -1302,8 +1349,12 @@ export default class RFB extends EventTargetMixin {
|
|
|
1302
1349
|
this._rfbAuthScheme = 22; // XVP
|
|
1303
1350
|
} else if (types.includes(16)) {
|
|
1304
1351
|
this._rfbAuthScheme = 16; // Tight
|
|
1352
|
+
} else if (types.includes(6)) {
|
|
1353
|
+
this._rfbAuthScheme = 6; // RA2ne Auth
|
|
1305
1354
|
} else if (types.includes(2)) {
|
|
1306
1355
|
this._rfbAuthScheme = 2; // VNC Auth
|
|
1356
|
+
} else if (types.includes(30)) {
|
|
1357
|
+
this._rfbAuthScheme = 30; // ARD Auth
|
|
1307
1358
|
} else if (types.includes(19)) {
|
|
1308
1359
|
this._rfbAuthScheme = 19; // VeNCrypt Auth
|
|
1309
1360
|
} else {
|
|
@@ -1496,6 +1547,117 @@ export default class RFB extends EventTargetMixin {
|
|
|
1496
1547
|
return true;
|
|
1497
1548
|
}
|
|
1498
1549
|
|
|
1550
|
+
_negotiateARDAuth() {
|
|
1551
|
+
|
|
1552
|
+
if (this._rfbCredentials.username === undefined ||
|
|
1553
|
+
this._rfbCredentials.password === undefined) {
|
|
1554
|
+
this.dispatchEvent(new CustomEvent(
|
|
1555
|
+
"credentialsrequired",
|
|
1556
|
+
{ detail: { types: ["username", "password"] } }));
|
|
1557
|
+
return false;
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1560
|
+
if (this._rfbCredentials.ardPublicKey != undefined &&
|
|
1561
|
+
this._rfbCredentials.ardCredentials != undefined) {
|
|
1562
|
+
// if the async web crypto is done return the results
|
|
1563
|
+
this._sock.send(this._rfbCredentials.ardCredentials);
|
|
1564
|
+
this._sock.send(this._rfbCredentials.ardPublicKey);
|
|
1565
|
+
this._rfbCredentials.ardCredentials = null;
|
|
1566
|
+
this._rfbCredentials.ardPublicKey = null;
|
|
1567
|
+
this._rfbInitState = "SecurityResult";
|
|
1568
|
+
return true;
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
if (this._sock.rQwait("read ard", 4)) { return false; }
|
|
1572
|
+
|
|
1573
|
+
let generator = this._sock.rQshiftBytes(2); // DH base generator value
|
|
1574
|
+
|
|
1575
|
+
let keyLength = this._sock.rQshift16();
|
|
1576
|
+
|
|
1577
|
+
if (this._sock.rQwait("read ard keylength", keyLength*2, 4)) { return false; }
|
|
1578
|
+
|
|
1579
|
+
// read the server values
|
|
1580
|
+
let prime = this._sock.rQshiftBytes(keyLength); // predetermined prime modulus
|
|
1581
|
+
let serverPublicKey = this._sock.rQshiftBytes(keyLength); // other party's public key
|
|
1582
|
+
|
|
1583
|
+
let clientPrivateKey = window.crypto.getRandomValues(new Uint8Array(keyLength));
|
|
1584
|
+
let padding = Array.from(window.crypto.getRandomValues(new Uint8Array(64)), byte => String.fromCharCode(65+byte%26)).join('');
|
|
1585
|
+
|
|
1586
|
+
this._negotiateARDAuthAsync(generator, keyLength, prime, serverPublicKey, clientPrivateKey, padding);
|
|
1587
|
+
|
|
1588
|
+
return false;
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
_modPow(base, exponent, modulus) {
|
|
1592
|
+
|
|
1593
|
+
let baseHex = "0x"+Array.from(base, byte => ('0' + (byte & 0xFF).toString(16)).slice(-2)).join('');
|
|
1594
|
+
let exponentHex = "0x"+Array.from(exponent, byte => ('0' + (byte & 0xFF).toString(16)).slice(-2)).join('');
|
|
1595
|
+
let modulusHex = "0x"+Array.from(modulus, byte => ('0' + (byte & 0xFF).toString(16)).slice(-2)).join('');
|
|
1596
|
+
|
|
1597
|
+
let b = BigInt(baseHex);
|
|
1598
|
+
let e = BigInt(exponentHex);
|
|
1599
|
+
let m = BigInt(modulusHex);
|
|
1600
|
+
let r = 1n;
|
|
1601
|
+
b = b % m;
|
|
1602
|
+
while (e > 0) {
|
|
1603
|
+
if (e % 2n === 1n) {
|
|
1604
|
+
r = (r * b) % m;
|
|
1605
|
+
}
|
|
1606
|
+
e = e / 2n;
|
|
1607
|
+
b = (b * b) % m;
|
|
1608
|
+
}
|
|
1609
|
+
let hexResult = r.toString(16);
|
|
1610
|
+
|
|
1611
|
+
while (hexResult.length/2<exponent.length || (hexResult.length%2 != 0)) {
|
|
1612
|
+
hexResult = "0"+hexResult;
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
let bytesResult = [];
|
|
1616
|
+
for (let c = 0; c < hexResult.length; c += 2) {
|
|
1617
|
+
bytesResult.push(parseInt(hexResult.substr(c, 2), 16));
|
|
1618
|
+
}
|
|
1619
|
+
return bytesResult;
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
async _aesEcbEncrypt(string, key) {
|
|
1623
|
+
// perform AES-ECB blocks
|
|
1624
|
+
let keyString = Array.from(key, byte => String.fromCharCode(byte)).join('');
|
|
1625
|
+
let aesKey = await window.crypto.subtle.importKey("raw", MD5(keyString), {name: "AES-CBC"}, false, ["encrypt"]);
|
|
1626
|
+
let data = new Uint8Array(string.length);
|
|
1627
|
+
for (let i = 0; i < string.length; ++i) {
|
|
1628
|
+
data[i] = string.charCodeAt(i);
|
|
1629
|
+
}
|
|
1630
|
+
let encrypted = new Uint8Array(data.length);
|
|
1631
|
+
for (let i=0;i<data.length;i+=16) {
|
|
1632
|
+
let block = data.slice(i, i+16);
|
|
1633
|
+
let encryptedBlock = await window.crypto.subtle.encrypt({name: "AES-CBC", iv: block},
|
|
1634
|
+
aesKey, new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
|
|
1635
|
+
);
|
|
1636
|
+
encrypted.set((new Uint8Array(encryptedBlock)).slice(0, 16), i);
|
|
1637
|
+
}
|
|
1638
|
+
return encrypted;
|
|
1639
|
+
}
|
|
1640
|
+
|
|
1641
|
+
async _negotiateARDAuthAsync(generator, keyLength, prime, serverPublicKey, clientPrivateKey, padding) {
|
|
1642
|
+
// calculate the DH keys
|
|
1643
|
+
let clientPublicKey = this._modPow(generator, clientPrivateKey, prime);
|
|
1644
|
+
let sharedKey = this._modPow(serverPublicKey, clientPrivateKey, prime);
|
|
1645
|
+
|
|
1646
|
+
let username = encodeUTF8(this._rfbCredentials.username).substring(0, 63);
|
|
1647
|
+
let password = encodeUTF8(this._rfbCredentials.password).substring(0, 63);
|
|
1648
|
+
|
|
1649
|
+
let paddedUsername = username + '\0' + padding.substring(0, 63);
|
|
1650
|
+
let paddedPassword = password + '\0' + padding.substring(0, 63);
|
|
1651
|
+
let credentials = paddedUsername.substring(0, 64) + paddedPassword.substring(0, 64);
|
|
1652
|
+
|
|
1653
|
+
let encrypted = await this._aesEcbEncrypt(credentials, sharedKey);
|
|
1654
|
+
|
|
1655
|
+
this._rfbCredentials.ardCredentials = encrypted;
|
|
1656
|
+
this._rfbCredentials.ardPublicKey = clientPublicKey;
|
|
1657
|
+
|
|
1658
|
+
setTimeout(this._initMsg.bind(this), 0);
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1499
1661
|
_negotiateTightUnixAuth() {
|
|
1500
1662
|
if (this._rfbCredentials.username === undefined ||
|
|
1501
1663
|
this._rfbCredentials.password === undefined) {
|
|
@@ -1619,6 +1781,44 @@ export default class RFB extends EventTargetMixin {
|
|
|
1619
1781
|
return this._fail("No supported sub-auth types!");
|
|
1620
1782
|
}
|
|
1621
1783
|
|
|
1784
|
+
_handleRSAAESCredentialsRequired(event) {
|
|
1785
|
+
this.dispatchEvent(event);
|
|
1786
|
+
}
|
|
1787
|
+
|
|
1788
|
+
_handleRSAAESServerVerification(event) {
|
|
1789
|
+
this.dispatchEvent(event);
|
|
1790
|
+
}
|
|
1791
|
+
|
|
1792
|
+
_negotiateRA2neAuth() {
|
|
1793
|
+
if (this._rfbRSAAESAuthenticationState === null) {
|
|
1794
|
+
this._rfbRSAAESAuthenticationState = new RSAAESAuthenticationState(this._sock, () => this._rfbCredentials);
|
|
1795
|
+
this._rfbRSAAESAuthenticationState.addEventListener(
|
|
1796
|
+
"serververification", this._eventHandlers.handleRSAAESServerVerification);
|
|
1797
|
+
this._rfbRSAAESAuthenticationState.addEventListener(
|
|
1798
|
+
"credentialsrequired", this._eventHandlers.handleRSAAESCredentialsRequired);
|
|
1799
|
+
}
|
|
1800
|
+
this._rfbRSAAESAuthenticationState.checkInternalEvents();
|
|
1801
|
+
if (!this._rfbRSAAESAuthenticationState.hasStarted) {
|
|
1802
|
+
this._rfbRSAAESAuthenticationState.negotiateRA2neAuthAsync()
|
|
1803
|
+
.catch((e) => {
|
|
1804
|
+
if (e.message !== "disconnect normally") {
|
|
1805
|
+
this._fail(e.message);
|
|
1806
|
+
}
|
|
1807
|
+
}).then(() => {
|
|
1808
|
+
this.dispatchEvent(new CustomEvent('securityresult'));
|
|
1809
|
+
this._rfbInitState = "SecurityResult";
|
|
1810
|
+
this._initMsg();
|
|
1811
|
+
}).finally(() => {
|
|
1812
|
+
this._rfbRSAAESAuthenticationState.removeEventListener(
|
|
1813
|
+
"serververification", this._eventHandlers.handleRSAAESServerVerification);
|
|
1814
|
+
this._rfbRSAAESAuthenticationState.removeEventListener(
|
|
1815
|
+
"credentialsrequired", this._eventHandlers.handleRSAAESCredentialsRequired);
|
|
1816
|
+
this._rfbRSAAESAuthenticationState = null;
|
|
1817
|
+
});
|
|
1818
|
+
}
|
|
1819
|
+
return false;
|
|
1820
|
+
}
|
|
1821
|
+
|
|
1622
1822
|
_negotiateAuthentication() {
|
|
1623
1823
|
switch (this._rfbAuthScheme) {
|
|
1624
1824
|
case 1: // no auth
|
|
@@ -1632,6 +1832,9 @@ export default class RFB extends EventTargetMixin {
|
|
|
1632
1832
|
case 22: // XVP auth
|
|
1633
1833
|
return this._negotiateXvpAuth();
|
|
1634
1834
|
|
|
1835
|
+
case 30: // ARD auth
|
|
1836
|
+
return this._negotiateARDAuth();
|
|
1837
|
+
|
|
1635
1838
|
case 2: // VNC authentication
|
|
1636
1839
|
return this._negotiateStdVNCAuth();
|
|
1637
1840
|
|
|
@@ -1644,6 +1847,9 @@ export default class RFB extends EventTargetMixin {
|
|
|
1644
1847
|
case 129: // TightVNC UNIX Security Type
|
|
1645
1848
|
return this._negotiateTightUnixAuth();
|
|
1646
1849
|
|
|
1850
|
+
case 6: // RA2ne Security Type
|
|
1851
|
+
return this._negotiateRA2neAuth();
|
|
1852
|
+
|
|
1647
1853
|
default:
|
|
1648
1854
|
return this._fail("Unsupported auth scheme (scheme: " +
|
|
1649
1855
|
this._rfbAuthScheme + ")");
|
|
@@ -1772,6 +1978,8 @@ export default class RFB extends EventTargetMixin {
|
|
|
1772
1978
|
if (this._fbDepth == 24) {
|
|
1773
1979
|
encs.push(encodings.encodingTight);
|
|
1774
1980
|
encs.push(encodings.encodingTightPNG);
|
|
1981
|
+
encs.push(encodings.encodingZRLE);
|
|
1982
|
+
encs.push(encodings.encodingJPEG);
|
|
1775
1983
|
encs.push(encodings.encodingHextile);
|
|
1776
1984
|
encs.push(encodings.encodingRRE);
|
|
1777
1985
|
}
|
|
@@ -2500,6 +2708,9 @@ export default class RFB extends EventTargetMixin {
|
|
|
2500
2708
|
this._updateScale();
|
|
2501
2709
|
|
|
2502
2710
|
this._updateContinuousUpdates();
|
|
2711
|
+
|
|
2712
|
+
// Keep this size until browser client size changes
|
|
2713
|
+
this._saveExpectedClientSize();
|
|
2503
2714
|
}
|
|
2504
2715
|
|
|
2505
2716
|
_xvpOp(ver, op) {
|
package/core/util/md5.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* noVNC: HTML5 VNC client
|
|
3
|
+
* Copyright (C) 2021 The noVNC Authors
|
|
4
|
+
* Licensed under MPL 2.0 (see LICENSE.txt)
|
|
5
|
+
*
|
|
6
|
+
* See README.md for usage and integration instructions.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
* Performs MD5 hashing on a string of binary characters, returns an array of bytes
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export function MD5(d) {
|
|
14
|
+
let r = M(V(Y(X(d), 8 * d.length)));
|
|
15
|
+
return r;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function M(d) {
|
|
19
|
+
let f = new Uint8Array(d.length);
|
|
20
|
+
for (let i=0;i<d.length;i++) {
|
|
21
|
+
f[i] = d.charCodeAt(i);
|
|
22
|
+
}
|
|
23
|
+
return f;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function X(d) {
|
|
27
|
+
let r = Array(d.length >> 2);
|
|
28
|
+
for (let m = 0; m < r.length; m++) r[m] = 0;
|
|
29
|
+
for (let m = 0; m < 8 * d.length; m += 8) r[m >> 5] |= (255 & d.charCodeAt(m / 8)) << m % 32;
|
|
30
|
+
return r;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function V(d) {
|
|
34
|
+
let r = "";
|
|
35
|
+
for (let m = 0; m < 32 * d.length; m += 8) r += String.fromCharCode(d[m >> 5] >>> m % 32 & 255);
|
|
36
|
+
return r;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function Y(d, g) {
|
|
40
|
+
d[g >> 5] |= 128 << g % 32, d[14 + (g + 64 >>> 9 << 4)] = g;
|
|
41
|
+
let m = 1732584193, f = -271733879, r = -1732584194, i = 271733878;
|
|
42
|
+
for (let n = 0; n < d.length; n += 16) {
|
|
43
|
+
let h = m,
|
|
44
|
+
t = f,
|
|
45
|
+
g = r,
|
|
46
|
+
e = i;
|
|
47
|
+
f = ii(f = ii(f = ii(f = ii(f = hh(f = hh(f = hh(f = hh(f = gg(f = gg(f = gg(f = gg(f = ff(f = ff(f = ff(f = ff(f, r = ff(r, i = ff(i, m = ff(m, f, r, i, d[n + 0], 7, -680876936), f, r, d[n + 1], 12, -389564586), m, f, d[n + 2], 17, 606105819), i, m, d[n + 3], 22, -1044525330), r = ff(r, i = ff(i, m = ff(m, f, r, i, d[n + 4], 7, -176418897), f, r, d[n + 5], 12, 1200080426), m, f, d[n + 6], 17, -1473231341), i, m, d[n + 7], 22, -45705983), r = ff(r, i = ff(i, m = ff(m, f, r, i, d[n + 8], 7, 1770035416), f, r, d[n + 9], 12, -1958414417), m, f, d[n + 10], 17, -42063), i, m, d[n + 11], 22, -1990404162), r = ff(r, i = ff(i, m = ff(m, f, r, i, d[n + 12], 7, 1804603682), f, r, d[n + 13], 12, -40341101), m, f, d[n + 14], 17, -1502002290), i, m, d[n + 15], 22, 1236535329), r = gg(r, i = gg(i, m = gg(m, f, r, i, d[n + 1], 5, -165796510), f, r, d[n + 6], 9, -1069501632), m, f, d[n + 11], 14, 643717713), i, m, d[n + 0], 20, -373897302), r = gg(r, i = gg(i, m = gg(m, f, r, i, d[n + 5], 5, -701558691), f, r, d[n + 10], 9, 38016083), m, f, d[n + 15], 14, -660478335), i, m, d[n + 4], 20, -405537848), r = gg(r, i = gg(i, m = gg(m, f, r, i, d[n + 9], 5, 568446438), f, r, d[n + 14], 9, -1019803690), m, f, d[n + 3], 14, -187363961), i, m, d[n + 8], 20, 1163531501), r = gg(r, i = gg(i, m = gg(m, f, r, i, d[n + 13], 5, -1444681467), f, r, d[n + 2], 9, -51403784), m, f, d[n + 7], 14, 1735328473), i, m, d[n + 12], 20, -1926607734), r = hh(r, i = hh(i, m = hh(m, f, r, i, d[n + 5], 4, -378558), f, r, d[n + 8], 11, -2022574463), m, f, d[n + 11], 16, 1839030562), i, m, d[n + 14], 23, -35309556), r = hh(r, i = hh(i, m = hh(m, f, r, i, d[n + 1], 4, -1530992060), f, r, d[n + 4], 11, 1272893353), m, f, d[n + 7], 16, -155497632), i, m, d[n + 10], 23, -1094730640), r = hh(r, i = hh(i, m = hh(m, f, r, i, d[n + 13], 4, 681279174), f, r, d[n + 0], 11, -358537222), m, f, d[n + 3], 16, -722521979), i, m, d[n + 6], 23, 76029189), r = hh(r, i = hh(i, m = hh(m, f, r, i, d[n + 9], 4, -640364487), f, r, d[n + 12], 11, -421815835), m, f, d[n + 15], 16, 530742520), i, m, d[n + 2], 23, -995338651), r = ii(r, i = ii(i, m = ii(m, f, r, i, d[n + 0], 6, -198630844), f, r, d[n + 7], 10, 1126891415), m, f, d[n + 14], 15, -1416354905), i, m, d[n + 5], 21, -57434055), r = ii(r, i = ii(i, m = ii(m, f, r, i, d[n + 12], 6, 1700485571), f, r, d[n + 3], 10, -1894986606), m, f, d[n + 10], 15, -1051523), i, m, d[n + 1], 21, -2054922799), r = ii(r, i = ii(i, m = ii(m, f, r, i, d[n + 8], 6, 1873313359), f, r, d[n + 15], 10, -30611744), m, f, d[n + 6], 15, -1560198380), i, m, d[n + 13], 21, 1309151649), r = ii(r, i = ii(i, m = ii(m, f, r, i, d[n + 4], 6, -145523070), f, r, d[n + 11], 10, -1120210379), m, f, d[n + 2], 15, 718787259), i, m, d[n + 9], 21, -343485551), m = add(m, h), f = add(f, t), r = add(r, g), i = add(i, e);
|
|
48
|
+
}
|
|
49
|
+
return Array(m, f, r, i);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function cmn(d, g, m, f, r, i) {
|
|
53
|
+
return add(rol(add(add(g, d), add(f, i)), r), m);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function ff(d, g, m, f, r, i, n) {
|
|
57
|
+
return cmn(g & m | ~g & f, d, g, r, i, n);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function gg(d, g, m, f, r, i, n) {
|
|
61
|
+
return cmn(g & f | m & ~f, d, g, r, i, n);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function hh(d, g, m, f, r, i, n) {
|
|
65
|
+
return cmn(g ^ m ^ f, d, g, r, i, n);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function ii(d, g, m, f, r, i, n) {
|
|
69
|
+
return cmn(m ^ (g | ~f), d, g, r, i, n);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function add(d, g) {
|
|
73
|
+
let m = (65535 & d) + (65535 & g);
|
|
74
|
+
return (d >> 16) + (g >> 16) + (m >> 16) << 16 | 65535 & m;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function rol(d, g) {
|
|
78
|
+
return d << g | d >>> 32 - g;
|
|
79
|
+
}
|
package/docs/API.md
CHANGED
|
@@ -86,9 +86,13 @@ protocol stream.
|
|
|
86
86
|
- The `connect` event is fired when the `RFB` object has completed
|
|
87
87
|
the connection and handshaking with the server.
|
|
88
88
|
|
|
89
|
-
[`disconnect`](#
|
|
89
|
+
[`disconnect`](#disconnect)
|
|
90
90
|
- The `disconnect` event is fired when the `RFB` object disconnects.
|
|
91
91
|
|
|
92
|
+
[`serververification`](#serververification)
|
|
93
|
+
- The `serververification` event is fired when the server identity
|
|
94
|
+
must be confirmed by the user.
|
|
95
|
+
|
|
92
96
|
[`credentialsrequired`](#credentialsrequired)
|
|
93
97
|
- The `credentialsrequired` event is fired when more credentials must
|
|
94
98
|
be given to continue.
|
|
@@ -118,11 +122,16 @@ protocol stream.
|
|
|
118
122
|
[`RFB.disconnect()`](#rfbdisconnect)
|
|
119
123
|
- Disconnect from the server.
|
|
120
124
|
|
|
125
|
+
[`RFB.approveServer()`](#rfbapproveserver)
|
|
126
|
+
- Proceed connecting to the server. Should be called after the
|
|
127
|
+
[`serververification`](#serververification) event has fired and the
|
|
128
|
+
user has verified the identity of the server.
|
|
129
|
+
|
|
121
130
|
[`RFB.sendCredentials()`](#rfbsendcredentials)
|
|
122
131
|
- Send credentials to server. Should be called after the
|
|
123
132
|
[`credentialsrequired`](#credentialsrequired) event has fired.
|
|
124
133
|
|
|
125
|
-
[`RFB.sendKey()`](#
|
|
134
|
+
[`RFB.sendKey()`](#rfbsendkey)
|
|
126
135
|
- Send a key event.
|
|
127
136
|
|
|
128
137
|
[`RFB.sendCtrlAltDel()`](#rfbsendctrlaltdel)
|
|
@@ -143,7 +152,7 @@ protocol stream.
|
|
|
143
152
|
[`RFB.machineReset()`](#rfbmachinereset)
|
|
144
153
|
- Request a reset of the remote machine.
|
|
145
154
|
|
|
146
|
-
[`RFB.clipboardPasteFrom()`](#
|
|
155
|
+
[`RFB.clipboardPasteFrom()`](#rfbclipboardpastefrom)
|
|
147
156
|
- Send clipboard contents to server.
|
|
148
157
|
|
|
149
158
|
### Details
|
|
@@ -212,6 +221,20 @@ property `clean`. `clean` is a `boolean` indicating if the termination
|
|
|
212
221
|
was clean or not. In the event of an unexpected termination or an error
|
|
213
222
|
`clean` will be set to false.
|
|
214
223
|
|
|
224
|
+
#### serververification
|
|
225
|
+
|
|
226
|
+
The `serververification` event is fired when the server provides
|
|
227
|
+
information that allows the user to verify that it is the correct server
|
|
228
|
+
and protect against a man-in-the-middle attack. The `detail` property is
|
|
229
|
+
an `Object` containing the property `type` which is a `DOMString`
|
|
230
|
+
specifying which type of information the server has provided. Other
|
|
231
|
+
properties are also available, depending on the value of `type`:
|
|
232
|
+
|
|
233
|
+
`"RSA"`
|
|
234
|
+
- The server identity is verified using just a RSA key. The property
|
|
235
|
+
`publickey` is a `Uint8Array` containing the public key in a unsigned
|
|
236
|
+
big endian representation.
|
|
237
|
+
|
|
215
238
|
#### credentialsrequired
|
|
216
239
|
|
|
217
240
|
The `credentialsrequired` event is fired when the server requests more
|
|
@@ -271,6 +294,16 @@ connected server.
|
|
|
271
294
|
|
|
272
295
|
RFB.disconnect( );
|
|
273
296
|
|
|
297
|
+
#### RFB.approveServer()
|
|
298
|
+
|
|
299
|
+
The `RFB.approveServer()` method is used to signal that the user has
|
|
300
|
+
verified the server identity provided in a `serververification` event
|
|
301
|
+
and that the connection can continue.
|
|
302
|
+
|
|
303
|
+
##### Syntax
|
|
304
|
+
|
|
305
|
+
RFB.approveServer( );
|
|
306
|
+
|
|
274
307
|
#### RFB.sendCredentials()
|
|
275
308
|
|
|
276
309
|
The `RFB.sendCredentials()` method is used to provide the missing
|
|
@@ -328,7 +361,14 @@ Keyboard events will be sent to the remote server after this point.
|
|
|
328
361
|
|
|
329
362
|
##### Syntax
|
|
330
363
|
|
|
331
|
-
RFB.focus( );
|
|
364
|
+
RFB.focus( [options] );
|
|
365
|
+
|
|
366
|
+
###### Parameters
|
|
367
|
+
|
|
368
|
+
**`options`** *Optional*
|
|
369
|
+
- A `object` providing options to control how the focus will be
|
|
370
|
+
performed. Please see [`HTMLElement.focus()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus)
|
|
371
|
+
for available options.
|
|
332
372
|
|
|
333
373
|
#### RFB.blur()
|
|
334
374
|
|
package/lib/base64.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
function _typeof(obj) { "@babel/helpers - typeof";
|
|
3
|
+
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
|
|
4
4
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", {
|
|
6
6
|
value: true
|
package/lib/decoders/copyrect.js
CHANGED
|
@@ -9,7 +9,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
|
|
|
9
9
|
|
|
10
10
|
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
|
11
11
|
|
|
12
|
-
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
|
|
12
|
+
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
13
13
|
|
|
14
14
|
/*
|
|
15
15
|
* noVNC: HTML5 VNC client
|
package/lib/decoders/hextile.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
function _typeof(obj) { "@babel/helpers - typeof";
|
|
3
|
+
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
|
|
4
4
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", {
|
|
6
6
|
value: true
|
|
@@ -17,7 +17,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
|
|
|
17
17
|
|
|
18
18
|
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
|
19
19
|
|
|
20
|
-
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
|
|
20
|
+
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
21
21
|
|
|
22
22
|
var HextileDecoder = /*#__PURE__*/function () {
|
|
23
23
|
function HextileDecoder() {
|