@novnc/novnc 1.3.0-g98664c7 → 1.3.0-gbdc0bbb

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.
Files changed (52) hide show
  1. package/core/display.js +12 -0
  2. package/core/rfb.js +275 -77
  3. package/core/util/md5.js +79 -0
  4. package/docs/API.md +61 -0
  5. package/lib/base64.js +20 -35
  6. package/lib/decoders/copyrect.js +1 -12
  7. package/lib/decoders/hextile.js +12 -44
  8. package/lib/decoders/jpeg.js +1 -44
  9. package/lib/decoders/raw.js +5 -22
  10. package/lib/decoders/rre.js +1 -16
  11. package/lib/decoders/tight.js +8 -76
  12. package/lib/decoders/tightpng.js +2 -24
  13. package/lib/decoders/zrle.js +2 -51
  14. package/lib/deflator.js +4 -21
  15. package/lib/des.js +19 -35
  16. package/lib/display.js +57 -105
  17. package/lib/encodings.js +1 -10
  18. package/lib/inflator.js +1 -17
  19. package/lib/input/domkeytable.js +77 -48
  20. package/lib/input/fixedkeys.js +8 -3
  21. package/lib/input/gesturehandler.js +81 -151
  22. package/lib/input/keyboard.js +48 -88
  23. package/lib/input/keysym.js +15 -272
  24. package/lib/input/keysymdef.js +5 -7
  25. package/lib/input/util.js +42 -84
  26. package/lib/input/vkeys.js +0 -3
  27. package/lib/input/xtscancodes.js +2 -170
  28. package/lib/ra2.js +37 -261
  29. package/lib/rfb.js +578 -947
  30. package/lib/util/browser.js +16 -25
  31. package/lib/util/cursor.js +20 -64
  32. package/lib/util/element.js +3 -5
  33. package/lib/util/events.js +23 -30
  34. package/lib/util/eventtarget.js +1 -14
  35. package/lib/util/int.js +1 -2
  36. package/lib/util/logging.js +1 -19
  37. package/lib/util/md5.js +83 -0
  38. package/lib/util/strings.js +3 -5
  39. package/lib/vendor/pako/lib/utils/common.js +8 -17
  40. package/lib/vendor/pako/lib/zlib/adler32.js +3 -7
  41. package/lib/vendor/pako/lib/zlib/constants.js +2 -5
  42. package/lib/vendor/pako/lib/zlib/crc32.js +5 -12
  43. package/lib/vendor/pako/lib/zlib/deflate.js +212 -617
  44. package/lib/vendor/pako/lib/zlib/gzheader.js +1 -13
  45. package/lib/vendor/pako/lib/zlib/inffast.js +60 -176
  46. package/lib/vendor/pako/lib/zlib/inflate.js +397 -887
  47. package/lib/vendor/pako/lib/zlib/inftrees.js +62 -168
  48. package/lib/vendor/pako/lib/zlib/messages.js +1 -11
  49. package/lib/vendor/pako/lib/zlib/trees.js +245 -587
  50. package/lib/vendor/pako/lib/zlib/zstream.js +2 -18
  51. package/lib/websock.js +31 -84
  52. package/package.json +1 -1
package/core/display.js CHANGED
@@ -224,6 +224,18 @@ export default class Display {
224
224
  this.viewportChangePos(0, 0);
225
225
  }
226
226
 
227
+ getImageData() {
228
+ return this._drawCtx.getImageData(0, 0, this.width, this.height);
229
+ }
230
+
231
+ toDataURL(type, encoderOptions) {
232
+ return this._backbuffer.toDataURL(type, encoderOptions);
233
+ }
234
+
235
+ toBlob(callback, type, quality) {
236
+ return this._backbuffer.toBlob(callback, type, quality);
237
+ }
238
+
227
239
  // Track what parts of the visible canvas that need updating
228
240
  _damage(x, y, w, h) {
229
241
  if (x < this._damageBounds.left) {
package/core/rfb.js CHANGED
@@ -26,6 +26,7 @@ import KeyTable from "./input/keysym.js";
26
26
  import XtScancode from "./input/xtscancodes.js";
27
27
  import { encodings } from "./encodings.js";
28
28
  import RSAAESAuthenticationState from "./ra2.js";
29
+ import { MD5 } from "./util/md5.js";
29
30
 
30
31
  import RawDecoder from "./decoders/raw.js";
31
32
  import CopyRectDecoder from "./decoders/copyrect.js";
@@ -53,6 +54,21 @@ const GESTURE_SCRLSENS = 50;
53
54
  const DOUBLE_TAP_TIMEOUT = 1000;
54
55
  const DOUBLE_TAP_THRESHOLD = 50;
55
56
 
57
+ // Security types
58
+ const securityTypeNone = 1;
59
+ const securityTypeVNCAuth = 2;
60
+ const securityTypeRA2ne = 6;
61
+ const securityTypeTight = 16;
62
+ const securityTypeVeNCrypt = 19;
63
+ const securityTypeXVP = 22;
64
+ const securityTypeARD = 30;
65
+
66
+ // Special Tight security types
67
+ const securityTypeUnixLogon = 129;
68
+
69
+ // VeNCrypt security types
70
+ const securityTypePlain = 256;
71
+
56
72
  // Extended clipboard pseudo-encoding formats
57
73
  const extendedClipboardFormatText = 1;
58
74
  /*eslint-disable no-unused-vars */
@@ -78,6 +94,12 @@ export default class RFB extends EventTargetMixin {
78
94
  throw new Error("Must specify URL, WebSocket or RTCDataChannel");
79
95
  }
80
96
 
97
+ // We rely on modern APIs which might not be available in an
98
+ // insecure context
99
+ if (!window.isSecureContext) {
100
+ Log.Error("noVNC requires a secure context (TLS). Expect crashes!");
101
+ }
102
+
81
103
  super();
82
104
 
83
105
  this._target = target;
@@ -395,7 +417,7 @@ export default class RFB extends EventTargetMixin {
395
417
 
396
418
  sendCredentials(creds) {
397
419
  this._rfbCredentials = creds;
398
- setTimeout(this._initMsg.bind(this), 0);
420
+ this._resumeAuthentication();
399
421
  }
400
422
 
401
423
  sendCtrlAltDel() {
@@ -478,6 +500,18 @@ export default class RFB extends EventTargetMixin {
478
500
  }
479
501
  }
480
502
 
503
+ getImageData() {
504
+ return this._display.getImageData();
505
+ }
506
+
507
+ toDataURL(type, encoderOptions) {
508
+ return this._display.toDataURL(type, encoderOptions);
509
+ }
510
+
511
+ toBlob(callback, type, quality) {
512
+ return this._display.toBlob(callback, type, quality);
513
+ }
514
+
481
515
  // ===== PRIVATE METHODS =====
482
516
 
483
517
  _connect() {
@@ -915,8 +949,15 @@ export default class RFB extends EventTargetMixin {
915
949
  }
916
950
  }
917
951
  break;
952
+ case 'connecting':
953
+ while (this._rfbConnectionState === 'connecting') {
954
+ if (!this._initMsg()) {
955
+ break;
956
+ }
957
+ }
958
+ break;
918
959
  default:
919
- this._initMsg();
960
+ Log.Error("Got data while in an invalid state");
920
961
  break;
921
962
  }
922
963
  }
@@ -1288,13 +1329,13 @@ export default class RFB extends EventTargetMixin {
1288
1329
  break;
1289
1330
  case "003.003":
1290
1331
  case "003.006": // UltraVNC
1291
- case "003.889": // Apple Remote Desktop
1292
1332
  this._rfbVersion = 3.3;
1293
1333
  break;
1294
1334
  case "003.007":
1295
1335
  this._rfbVersion = 3.7;
1296
1336
  break;
1297
1337
  case "003.008":
1338
+ case "003.889": // Apple Remote Desktop
1298
1339
  case "004.000": // Intel AMT KVM
1299
1340
  case "004.001": // RealVNC 4.6
1300
1341
  case "005.000": // RealVNC 5.3
@@ -1325,6 +1366,21 @@ export default class RFB extends EventTargetMixin {
1325
1366
  this._rfbInitState = 'Security';
1326
1367
  }
1327
1368
 
1369
+ _isSupportedSecurityType(type) {
1370
+ const clientTypes = [
1371
+ securityTypeNone,
1372
+ securityTypeVNCAuth,
1373
+ securityTypeRA2ne,
1374
+ securityTypeTight,
1375
+ securityTypeVeNCrypt,
1376
+ securityTypeXVP,
1377
+ securityTypeARD,
1378
+ securityTypePlain,
1379
+ ];
1380
+
1381
+ return clientTypes.includes(type);
1382
+ }
1383
+
1328
1384
  _negotiateSecurity() {
1329
1385
  if (this._rfbVersion >= 3.7) {
1330
1386
  // Server sends supported list, client decides
@@ -1335,26 +1391,23 @@ export default class RFB extends EventTargetMixin {
1335
1391
  this._rfbInitState = "SecurityReason";
1336
1392
  this._securityContext = "no security types";
1337
1393
  this._securityStatus = 1;
1338
- return this._initMsg();
1394
+ return true;
1339
1395
  }
1340
1396
 
1341
1397
  const types = this._sock.rQshiftBytes(numTypes);
1342
1398
  Log.Debug("Server security types: " + types);
1343
1399
 
1344
- // Look for each auth in preferred order
1345
- if (types.includes(1)) {
1346
- this._rfbAuthScheme = 1; // None
1347
- } else if (types.includes(22)) {
1348
- this._rfbAuthScheme = 22; // XVP
1349
- } else if (types.includes(16)) {
1350
- this._rfbAuthScheme = 16; // Tight
1351
- } else if (types.includes(6)) {
1352
- this._rfbAuthScheme = 6; // RA2ne Auth
1353
- } else if (types.includes(2)) {
1354
- this._rfbAuthScheme = 2; // VNC Auth
1355
- } else if (types.includes(19)) {
1356
- this._rfbAuthScheme = 19; // VeNCrypt Auth
1357
- } else {
1400
+ // Look for a matching security type in the order that the
1401
+ // server prefers
1402
+ this._rfbAuthScheme = -1;
1403
+ for (let type of types) {
1404
+ if (this._isSupportedSecurityType(type)) {
1405
+ this._rfbAuthScheme = type;
1406
+ break;
1407
+ }
1408
+ }
1409
+
1410
+ if (this._rfbAuthScheme === -1) {
1358
1411
  return this._fail("Unsupported security types (types: " + types + ")");
1359
1412
  }
1360
1413
 
@@ -1368,14 +1421,14 @@ export default class RFB extends EventTargetMixin {
1368
1421
  this._rfbInitState = "SecurityReason";
1369
1422
  this._securityContext = "authentication scheme";
1370
1423
  this._securityStatus = 1;
1371
- return this._initMsg();
1424
+ return true;
1372
1425
  }
1373
1426
  }
1374
1427
 
1375
1428
  this._rfbInitState = 'Authentication';
1376
1429
  Log.Debug('Authenticating using scheme: ' + this._rfbAuthScheme);
1377
1430
 
1378
- return this._initMsg(); // jump to authentication
1431
+ return true;
1379
1432
  }
1380
1433
 
1381
1434
  _handleSecurityReason() {
@@ -1425,7 +1478,7 @@ export default class RFB extends EventTargetMixin {
1425
1478
  this._rfbCredentials.username +
1426
1479
  this._rfbCredentials.target;
1427
1480
  this._sock.sendString(xvpAuthStr);
1428
- this._rfbAuthScheme = 2;
1481
+ this._rfbAuthScheme = securityTypeVNCAuth;
1429
1482
  return this._negotiateAuthentication();
1430
1483
  }
1431
1484
 
@@ -1483,49 +1536,66 @@ export default class RFB extends EventTargetMixin {
1483
1536
  subtypes.push(this._sock.rQshift32());
1484
1537
  }
1485
1538
 
1486
- // 256 = Plain subtype
1487
- if (subtypes.indexOf(256) != -1) {
1488
- // 0x100 = 256
1489
- this._sock.send([0, 0, 1, 0]);
1490
- this._rfbVeNCryptState = 4;
1491
- } else {
1492
- return this._fail("VeNCrypt Plain subtype not offered by server");
1539
+ // Look for a matching security type in the order that the
1540
+ // server prefers
1541
+ this._rfbAuthScheme = -1;
1542
+ for (let type of subtypes) {
1543
+ // Avoid getting in to a loop
1544
+ if (type === securityTypeVeNCrypt) {
1545
+ continue;
1546
+ }
1547
+
1548
+ if (this._isSupportedSecurityType(type)) {
1549
+ this._rfbAuthScheme = type;
1550
+ break;
1551
+ }
1493
1552
  }
1494
- }
1495
1553
 
1496
- // negotiated Plain subtype, server waits for password
1497
- if (this._rfbVeNCryptState == 4) {
1498
- if (this._rfbCredentials.username === undefined ||
1499
- this._rfbCredentials.password === undefined) {
1500
- this.dispatchEvent(new CustomEvent(
1501
- "credentialsrequired",
1502
- { detail: { types: ["username", "password"] } }));
1503
- return false;
1554
+ if (this._rfbAuthScheme === -1) {
1555
+ return this._fail("Unsupported security types (types: " + subtypes + ")");
1504
1556
  }
1505
1557
 
1506
- const user = encodeUTF8(this._rfbCredentials.username);
1507
- const pass = encodeUTF8(this._rfbCredentials.password);
1508
-
1509
- this._sock.send([
1510
- (user.length >> 24) & 0xFF,
1511
- (user.length >> 16) & 0xFF,
1512
- (user.length >> 8) & 0xFF,
1513
- user.length & 0xFF
1514
- ]);
1515
- this._sock.send([
1516
- (pass.length >> 24) & 0xFF,
1517
- (pass.length >> 16) & 0xFF,
1518
- (pass.length >> 8) & 0xFF,
1519
- pass.length & 0xFF
1520
- ]);
1521
- this._sock.sendString(user);
1522
- this._sock.sendString(pass);
1558
+ this._sock.send([this._rfbAuthScheme >> 24,
1559
+ this._rfbAuthScheme >> 16,
1560
+ this._rfbAuthScheme >> 8,
1561
+ this._rfbAuthScheme]);
1523
1562
 
1524
- this._rfbInitState = "SecurityResult";
1563
+ this._rfbVeNCryptState == 4;
1525
1564
  return true;
1526
1565
  }
1527
1566
  }
1528
1567
 
1568
+ _negotiatePlainAuth() {
1569
+ if (this._rfbCredentials.username === undefined ||
1570
+ this._rfbCredentials.password === undefined) {
1571
+ this.dispatchEvent(new CustomEvent(
1572
+ "credentialsrequired",
1573
+ { detail: { types: ["username", "password"] } }));
1574
+ return false;
1575
+ }
1576
+
1577
+ const user = encodeUTF8(this._rfbCredentials.username);
1578
+ const pass = encodeUTF8(this._rfbCredentials.password);
1579
+
1580
+ this._sock.send([
1581
+ (user.length >> 24) & 0xFF,
1582
+ (user.length >> 16) & 0xFF,
1583
+ (user.length >> 8) & 0xFF,
1584
+ user.length & 0xFF
1585
+ ]);
1586
+ this._sock.send([
1587
+ (pass.length >> 24) & 0xFF,
1588
+ (pass.length >> 16) & 0xFF,
1589
+ (pass.length >> 8) & 0xFF,
1590
+ pass.length & 0xFF
1591
+ ]);
1592
+ this._sock.sendString(user);
1593
+ this._sock.sendString(pass);
1594
+
1595
+ this._rfbInitState = "SecurityResult";
1596
+ return true;
1597
+ }
1598
+
1529
1599
  _negotiateStdVNCAuth() {
1530
1600
  if (this._sock.rQwait("auth challenge", 16)) { return false; }
1531
1601
 
@@ -1544,6 +1614,117 @@ export default class RFB extends EventTargetMixin {
1544
1614
  return true;
1545
1615
  }
1546
1616
 
1617
+ _negotiateARDAuth() {
1618
+
1619
+ if (this._rfbCredentials.username === undefined ||
1620
+ this._rfbCredentials.password === undefined) {
1621
+ this.dispatchEvent(new CustomEvent(
1622
+ "credentialsrequired",
1623
+ { detail: { types: ["username", "password"] } }));
1624
+ return false;
1625
+ }
1626
+
1627
+ if (this._rfbCredentials.ardPublicKey != undefined &&
1628
+ this._rfbCredentials.ardCredentials != undefined) {
1629
+ // if the async web crypto is done return the results
1630
+ this._sock.send(this._rfbCredentials.ardCredentials);
1631
+ this._sock.send(this._rfbCredentials.ardPublicKey);
1632
+ this._rfbCredentials.ardCredentials = null;
1633
+ this._rfbCredentials.ardPublicKey = null;
1634
+ this._rfbInitState = "SecurityResult";
1635
+ return true;
1636
+ }
1637
+
1638
+ if (this._sock.rQwait("read ard", 4)) { return false; }
1639
+
1640
+ let generator = this._sock.rQshiftBytes(2); // DH base generator value
1641
+
1642
+ let keyLength = this._sock.rQshift16();
1643
+
1644
+ if (this._sock.rQwait("read ard keylength", keyLength*2, 4)) { return false; }
1645
+
1646
+ // read the server values
1647
+ let prime = this._sock.rQshiftBytes(keyLength); // predetermined prime modulus
1648
+ let serverPublicKey = this._sock.rQshiftBytes(keyLength); // other party's public key
1649
+
1650
+ let clientPrivateKey = window.crypto.getRandomValues(new Uint8Array(keyLength));
1651
+ let padding = Array.from(window.crypto.getRandomValues(new Uint8Array(64)), byte => String.fromCharCode(65+byte%26)).join('');
1652
+
1653
+ this._negotiateARDAuthAsync(generator, keyLength, prime, serverPublicKey, clientPrivateKey, padding);
1654
+
1655
+ return false;
1656
+ }
1657
+
1658
+ _modPow(base, exponent, modulus) {
1659
+
1660
+ let baseHex = "0x"+Array.from(base, byte => ('0' + (byte & 0xFF).toString(16)).slice(-2)).join('');
1661
+ let exponentHex = "0x"+Array.from(exponent, byte => ('0' + (byte & 0xFF).toString(16)).slice(-2)).join('');
1662
+ let modulusHex = "0x"+Array.from(modulus, byte => ('0' + (byte & 0xFF).toString(16)).slice(-2)).join('');
1663
+
1664
+ let b = BigInt(baseHex);
1665
+ let e = BigInt(exponentHex);
1666
+ let m = BigInt(modulusHex);
1667
+ let r = 1n;
1668
+ b = b % m;
1669
+ while (e > 0) {
1670
+ if (e % 2n === 1n) {
1671
+ r = (r * b) % m;
1672
+ }
1673
+ e = e / 2n;
1674
+ b = (b * b) % m;
1675
+ }
1676
+ let hexResult = r.toString(16);
1677
+
1678
+ while (hexResult.length/2<exponent.length || (hexResult.length%2 != 0)) {
1679
+ hexResult = "0"+hexResult;
1680
+ }
1681
+
1682
+ let bytesResult = [];
1683
+ for (let c = 0; c < hexResult.length; c += 2) {
1684
+ bytesResult.push(parseInt(hexResult.substr(c, 2), 16));
1685
+ }
1686
+ return bytesResult;
1687
+ }
1688
+
1689
+ async _aesEcbEncrypt(string, key) {
1690
+ // perform AES-ECB blocks
1691
+ let keyString = Array.from(key, byte => String.fromCharCode(byte)).join('');
1692
+ let aesKey = await window.crypto.subtle.importKey("raw", MD5(keyString), {name: "AES-CBC"}, false, ["encrypt"]);
1693
+ let data = new Uint8Array(string.length);
1694
+ for (let i = 0; i < string.length; ++i) {
1695
+ data[i] = string.charCodeAt(i);
1696
+ }
1697
+ let encrypted = new Uint8Array(data.length);
1698
+ for (let i=0;i<data.length;i+=16) {
1699
+ let block = data.slice(i, i+16);
1700
+ let encryptedBlock = await window.crypto.subtle.encrypt({name: "AES-CBC", iv: block},
1701
+ aesKey, new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
1702
+ );
1703
+ encrypted.set((new Uint8Array(encryptedBlock)).slice(0, 16), i);
1704
+ }
1705
+ return encrypted;
1706
+ }
1707
+
1708
+ async _negotiateARDAuthAsync(generator, keyLength, prime, serverPublicKey, clientPrivateKey, padding) {
1709
+ // calculate the DH keys
1710
+ let clientPublicKey = this._modPow(generator, clientPrivateKey, prime);
1711
+ let sharedKey = this._modPow(serverPublicKey, clientPrivateKey, prime);
1712
+
1713
+ let username = encodeUTF8(this._rfbCredentials.username).substring(0, 63);
1714
+ let password = encodeUTF8(this._rfbCredentials.password).substring(0, 63);
1715
+
1716
+ let paddedUsername = username + '\0' + padding.substring(0, 63);
1717
+ let paddedPassword = password + '\0' + padding.substring(0, 63);
1718
+ let credentials = paddedUsername.substring(0, 64) + paddedPassword.substring(0, 64);
1719
+
1720
+ let encrypted = await this._aesEcbEncrypt(credentials, sharedKey);
1721
+
1722
+ this._rfbCredentials.ardCredentials = encrypted;
1723
+ this._rfbCredentials.ardPublicKey = clientPublicKey;
1724
+
1725
+ this._resumeAuthentication();
1726
+ }
1727
+
1547
1728
  _negotiateTightUnixAuth() {
1548
1729
  if (this._rfbCredentials.username === undefined ||
1549
1730
  this._rfbCredentials.password === undefined) {
@@ -1651,12 +1832,12 @@ export default class RFB extends EventTargetMixin {
1651
1832
  case 'STDVNOAUTH__': // no auth
1652
1833
  this._rfbInitState = 'SecurityResult';
1653
1834
  return true;
1654
- case 'STDVVNCAUTH_': // VNC auth
1655
- this._rfbAuthScheme = 2;
1656
- return this._initMsg();
1657
- case 'TGHTULGNAUTH': // UNIX auth
1658
- this._rfbAuthScheme = 129;
1659
- return this._initMsg();
1835
+ case 'STDVVNCAUTH_':
1836
+ this._rfbAuthScheme = securityTypeVNCAuth;
1837
+ return true;
1838
+ case 'TGHTULGNAUTH':
1839
+ this._rfbAuthScheme = securityTypeUnixLogon;
1840
+ return true;
1660
1841
  default:
1661
1842
  return this._fail("Unsupported tiny auth scheme " +
1662
1843
  "(scheme: " + authType + ")");
@@ -1693,7 +1874,7 @@ export default class RFB extends EventTargetMixin {
1693
1874
  }).then(() => {
1694
1875
  this.dispatchEvent(new CustomEvent('securityresult'));
1695
1876
  this._rfbInitState = "SecurityResult";
1696
- this._initMsg();
1877
+ return true;
1697
1878
  }).finally(() => {
1698
1879
  this._rfbRSAAESAuthenticationState.removeEventListener(
1699
1880
  "serververification", this._eventHandlers.handleRSAAESServerVerification);
@@ -1707,30 +1888,32 @@ export default class RFB extends EventTargetMixin {
1707
1888
 
1708
1889
  _negotiateAuthentication() {
1709
1890
  switch (this._rfbAuthScheme) {
1710
- case 1: // no auth
1711
- if (this._rfbVersion >= 3.8) {
1712
- this._rfbInitState = 'SecurityResult';
1713
- return true;
1714
- }
1715
- this._rfbInitState = 'ClientInitialisation';
1716
- return this._initMsg();
1891
+ case securityTypeNone:
1892
+ this._rfbInitState = 'SecurityResult';
1893
+ return true;
1717
1894
 
1718
- case 22: // XVP auth
1895
+ case securityTypeXVP:
1719
1896
  return this._negotiateXvpAuth();
1720
1897
 
1721
- case 2: // VNC authentication
1898
+ case securityTypeARD:
1899
+ return this._negotiateARDAuth();
1900
+
1901
+ case securityTypeVNCAuth:
1722
1902
  return this._negotiateStdVNCAuth();
1723
1903
 
1724
- case 16: // TightVNC Security Type
1904
+ case securityTypeTight:
1725
1905
  return this._negotiateTightAuth();
1726
1906
 
1727
- case 19: // VeNCrypt Security Type
1907
+ case securityTypeVeNCrypt:
1728
1908
  return this._negotiateVeNCryptAuth();
1729
1909
 
1730
- case 129: // TightVNC UNIX Security Type
1910
+ case securityTypePlain:
1911
+ return this._negotiatePlainAuth();
1912
+
1913
+ case securityTypeUnixLogon:
1731
1914
  return this._negotiateTightUnixAuth();
1732
1915
 
1733
- case 6: // RA2ne Security Type
1916
+ case securityTypeRA2ne:
1734
1917
  return this._negotiateRA2neAuth();
1735
1918
 
1736
1919
  default:
@@ -1740,6 +1923,13 @@ export default class RFB extends EventTargetMixin {
1740
1923
  }
1741
1924
 
1742
1925
  _handleSecurityResult() {
1926
+ // There is no security choice, and hence no security result
1927
+ // until RFB 3.7
1928
+ if (this._rfbVersion < 3.7) {
1929
+ this._rfbInitState = 'ClientInitialisation';
1930
+ return true;
1931
+ }
1932
+
1743
1933
  if (this._sock.rQwait('VNC auth response ', 4)) { return false; }
1744
1934
 
1745
1935
  const status = this._sock.rQshift32();
@@ -1747,13 +1937,13 @@ export default class RFB extends EventTargetMixin {
1747
1937
  if (status === 0) { // OK
1748
1938
  this._rfbInitState = 'ClientInitialisation';
1749
1939
  Log.Debug('Authentication OK');
1750
- return this._initMsg();
1940
+ return true;
1751
1941
  } else {
1752
1942
  if (this._rfbVersion >= 3.8) {
1753
1943
  this._rfbInitState = "SecurityReason";
1754
1944
  this._securityContext = "security result";
1755
1945
  this._securityStatus = status;
1756
- return this._initMsg();
1946
+ return true;
1757
1947
  } else {
1758
1948
  this.dispatchEvent(new CustomEvent(
1759
1949
  "securityfailure",
@@ -1929,6 +2119,14 @@ export default class RFB extends EventTargetMixin {
1929
2119
  }
1930
2120
  }
1931
2121
 
2122
+ // Resume authentication handshake after it was paused for some
2123
+ // reason, e.g. waiting for a password from the user
2124
+ _resumeAuthentication() {
2125
+ // We use setTimeout() so it's run in its own context, just like
2126
+ // it originally did via the WebSocket's event handler
2127
+ setTimeout(this._initMsg.bind(this), 0);
2128
+ }
2129
+
1932
2130
  _handleSetColourMapMsg() {
1933
2131
  Log.Debug("SetColorMapEntries");
1934
2132
 
@@ -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
+ }