Fixed Android black screen issue.
Ylian Saint-Hilaire committed
Mar 12, 2021 at 03:23 UTC
2eebd4a1d474dcb39bb11e8b8aae8bd5d0708fc0
4 files changed
+349
-20
amthelloserver.js
+342
-16
@@ -25,6 +25,9 @@ module.exports.CreateAmtHelloServer = function (parent, config) {
25
const WsmanStackCreateService = require('./amt/amt-wsman');
26
const AmtStackCreateService = require('./amt/amt');
27
28
+ // Check configuration
29
+ if (checkAmtPassword(config.newmebxpassword) == false) { console.log('Invalid MEBx password, must have 1 lower, 1 upper, 1 numeric, 1 non-alpha and be 8 or more in length.'); return null; }
30
+
31
// Start the Intel AMT hello server
32
var port = 9971;
33
if (typeof config.port == 'number') { port = config.port; }
@@ -35,7 +38,6 @@ module.exports.CreateAmtHelloServer = function (parent, config) {
38
socket.on('error', function (err) { })
39
socket.on('close', function () { if (this.data != null) { processHelloData(this.data, this.ra); } delete this.ra; this.removeAllListeners(); })
40
socket.on('data', function (data) {
38
- console.log('indata', data.toString('hex'));
41
if (this.data == null) { this.data = data; } else { Buffer.concat([this.data, data]); }
42
var str = this.data.toString();
43
if (str.startsWith('GET ') && (str.indexOf('\r\n\r\n') >= 0)) {
@@ -49,16 +51,19 @@ module.exports.CreateAmtHelloServer = function (parent, config) {
51
});
52
obj.server.listen(port);
53
console.log('MeshCentral Intel(R) AMT provisioning server running on port ' + port + '.');
54
+ obj.parent = parent;
55
+ obj.rootCertCN = obj.parent.certificateOperations.forge.pki.certificateFromPem(obj.parent.certificates.root.cert).subject.getField('CN').value;
56
+
57
+ // Devices activaly being configured
58
+ obj.devices = {} // Address -> Device
59
60
// Example hello data for testing
61
//setTimeout(function () { processHelloData(Buffer.from('01000300000000004b529b93d413181de4871c697a6b7a2b170220c3846bf24b9e93ca64274c0ec67c1ecc5e024ffcacd2d74019350e81fe546ae4022045140b3247eb9cc8c5b4f0d7b53091f73292089e6e5a63e2749dd3aca9198eda0220d7a7a0fb5d7e2731d771e9484ebcdef71d5f0c3e0a2948782bc83ee0ea699ef402201465fa205397b876faa6f0a9958e5590e40fcc7faa4fb7c2c8677521fb5fb65802202ce1cb0bf9d2f9e102993fbe215152c3b2dd0cabde1c68e5319b839154dbb7f502209acfab7e43c8d880d06b262a94deeee4b4659989c3d0caf19baf6405e41ab7df022016af57a9f676b0ab126095aa5ebadef22ab31119d644ac95cd4b93dbf3f26aeb0220960adf0063e96356750c2965dd0a0867da0b9cbd6e77714aeafb2349ab393da3022068ad50909b04363c605ef13581a939ff2c96372e3f12325b0a6861e1d59f660302206dc47172e01cbcb0bf62580d895fe2b8ac9ad4f873801e0c10b9c837d21eb177022073c176434f1bc6d5adf45b0e76e727287c8de57616c1e6e6141a2b2cbc7d8e4c022043df5774b03e7fef5fe40d931a7bedf1bb2e6b42738c4e6d3841103d3aa7f33902202399561127a57125de8cefea610ddf2fa078b5c8067f4e828290bfb860e84b3c022070a73f7f376b60074248904534b11482d5bf0e698ecc498df52577ebf2e93b9a02204348a0e9444c78cb265e058d5e8944b4d84f9662bd26db257f8934a443c701610220cb3ccbb76031e5e0138f8dd39a23f9de47ffc35e43c1144cea27d46a5ab1cb5f022031ad6648f8104138c738f39ea4320133393e3a18cc02296ef97c2ac9ef6731d00220552f7bdcf1a7af9e6ce672017f4f12abf77240c78e761ac203d1d9d20ac89988022067540a47aa5b9f34570a99723cfefa96a96ee3f0d9b8bf4def9440b8065d665d02207224395222cd588c4f2683716922addb41e39b581ac34fa87b39efa896fbb39e0220cbb522d7b7f127ad6a0113865bdf1cd4102e7d0759af635a7cf4720dc963c53b0220179fbc148a3dd00fd24ea13458cc43bfa7f59c8182d783a513f6ebec100c892402202cabeafe37d06ca22aba7391c0033d25982952c453647349763a3ab5ad6ccf69', 'hex'), '192.168.2.148'); }, 500);
55
- setTimeout(function () { processHelloData(Buffer.from('01000300000000004b529b93d413181de4871c697a6b7a2b180220c3846bf24b9e93ca64274c0ec67c1ecc5e024ffcacd2d74019350e81fe546ae4022045140b3247eb9cc8c5b4f0d7b53091f73292089e6e5a63e2749dd3aca9198eda0220d7a7a0fb5d7e2731d771e9484ebcdef71d5f0c3e0a2948782bc83ee0ea699ef402201465fa205397b876faa6f0a9958e5590e40fcc7faa4fb7c2c8677521fb5fb65802202ce1cb0bf9d2f9e102993fbe215152c3b2dd0cabde1c68e5319b839154dbb7f502209acfab7e43c8d880d06b262a94deeee4b4659989c3d0caf19baf6405e41ab7df022016af57a9f676b0ab126095aa5ebadef22ab31119d644ac95cd4b93dbf3f26aeb0220960adf0063e96356750c2965dd0a0867da0b9cbd6e77714aeafb2349ab393da3022068ad50909b04363c605ef13581a939ff2c96372e3f12325b0a6861e1d59f660302206dc47172e01cbcb0bf62580d895fe2b8ac9ad4f873801e0c10b9c837d21eb177022073c176434f1bc6d5adf45b0e76e727287c8de57616c1e6e6141a2b2cbc7d8e4c022043df5774b03e7fef5fe40d931a7bedf1bb2e6b42738c4e6d3841103d3aa7f33902202399561127a57125de8cefea610ddf2fa078b5c8067f4e828290bfb860e84b3c022070a73f7f376b60074248904534b11482d5bf0e698ecc498df52577ebf2e93b9a02204348a0e9444c78cb265e058d5e8944b4d84f9662bd26db257f8934a443c701610220cb3ccbb76031e5e0138f8dd39a23f9de47ffc35e43c1144cea27d46a5ab1cb5f022031ad6648f8104138c738f39ea4320133393e3a18cc02296ef97c2ac9ef6731d00220552f7bdcf1a7af9e6ce672017f4f12abf77240c78e761ac203d1d9d20ac89988022067540a47aa5b9f34570a99723cfefa96a96ee3f0d9b8bf4def9440b8065d665d0220a267c480b0b29056eb5e8aa7c93add804f5a7df516e969e77bcacafe8d45607902207224395222cd588c4f2683716922addb41e39b581ac34fa87b39efa896fbb39e0220cbb522d7b7f127ad6a0113865bdf1cd4102e7d0759af635a7cf4720dc963c53b0220179fbc148a3dd00fd24ea13458cc43bfa7f59c8182d783a513f6ebec100c892402202cabeafe37d06ca22aba7391c0033d25982952c453647349763a3ab5ad6ccf69', 'hex'), '192.168.2.148'); }, 500);
56
-
62
+ //setTimeout(function () { processHelloData(Buffer.from('01000300000000004b529b93d413181de4871c697a6b7a2b180220c3846bf24b9e93ca64274c0ec67c1ecc5e024ffcacd2d74019350e81fe546ae4022045140b3247eb9cc8c5b4f0d7b53091f73292089e6e5a63e2749dd3aca9198eda0220d7a7a0fb5d7e2731d771e9484ebcdef71d5f0c3e0a2948782bc83ee0ea699ef402201465fa205397b876faa6f0a9958e5590e40fcc7faa4fb7c2c8677521fb5fb65802202ce1cb0bf9d2f9e102993fbe215152c3b2dd0cabde1c68e5319b839154dbb7f502209acfab7e43c8d880d06b262a94deeee4b4659989c3d0caf19baf6405e41ab7df022016af57a9f676b0ab126095aa5ebadef22ab31119d644ac95cd4b93dbf3f26aeb0220960adf0063e96356750c2965dd0a0867da0b9cbd6e77714aeafb2349ab393da3022068ad50909b04363c605ef13581a939ff2c96372e3f12325b0a6861e1d59f660302206dc47172e01cbcb0bf62580d895fe2b8ac9ad4f873801e0c10b9c837d21eb177022073c176434f1bc6d5adf45b0e76e727287c8de57616c1e6e6141a2b2cbc7d8e4c022043df5774b03e7fef5fe40d931a7bedf1bb2e6b42738c4e6d3841103d3aa7f33902202399561127a57125de8cefea610ddf2fa078b5c8067f4e828290bfb860e84b3c022070a73f7f376b60074248904534b11482d5bf0e698ecc498df52577ebf2e93b9a02204348a0e9444c78cb265e058d5e8944b4d84f9662bd26db257f8934a443c701610220cb3ccbb76031e5e0138f8dd39a23f9de47ffc35e43c1144cea27d46a5ab1cb5f022031ad6648f8104138c738f39ea4320133393e3a18cc02296ef97c2ac9ef6731d00220552f7bdcf1a7af9e6ce672017f4f12abf77240c78e761ac203d1d9d20ac89988022067540a47aa5b9f34570a99723cfefa96a96ee3f0d9b8bf4def9440b8065d665d0220a267c480b0b29056eb5e8aa7c93add804f5a7df516e969e77bcacafe8d45607902207224395222cd588c4f2683716922addb41e39b581ac34fa87b39efa896fbb39e0220cbb522d7b7f127ad6a0113865bdf1cd4102e7d0759af635a7cf4720dc963c53b0220179fbc148a3dd00fd24ea13458cc43bfa7f59c8182d783a513f6ebec100c892402202cabeafe37d06ca22aba7391c0033d25982952c453647349763a3ab5ad6ccf69', 'hex'), '192.168.2.148'); }, 500);
63
64
// Parse Intel AMT hello data
65
function parseHelloData(data, addr) {
66
try {
61
- if (addr.startsWith('::ffff:')) { addr = addr.substring(7); }
67
var amtHello = { time: Date.now(), addr: addr };
68
69
// Decode header
@@ -99,15 +104,22 @@ module.exports.CreateAmtHelloServer = function (parent, config) {
104
// Process incoming Intel AMT hello data
105
function processHelloData(data, addr) {
106
// Check if we can parse the incoming data
107
+ if (addr.startsWith('::ffff:')) { addr = addr.substring(7); }
108
+ if (obj.devices[addr] != null) return; // Device on this address already being activated.
109
const dev = parseHelloData(data, addr);
110
if (dev == null) { parent.debug('amtsca', addr, 'Got invalid hello from: ' + addr); return; } // Invalid Intel AMT hello
111
parent.debug('amtsca', 'Got hello from ' + addr);
112
+ obj.devices[addr] = dev;
113
+
114
+ // Set device messages
115
+ dev.consoleMsg = function deviceConsoleMsg(msg) { parent.debug('amtsca', deviceConsoleMsg.dev.hostname ? deviceConsoleMsg.dev.hostname : deviceConsoleMsg.dev.addr, msg); return; }
116
+ dev.consoleMsg.dev = dev;
117
118
// Get assumed trusted FQDN and device group
119
dev.trustedFqdn = config.trustedfqdn;
120
var mesh = parent.webserver.meshes[config.devicegroup];
109
- if ((mesh == null) || (mesh.mtype !== 1) || (typeof mesh.amt !== 'object') || (typeof mesh.amt.type !== 'number')) { parent.debug('amtsca', addr, 'Invalid device group for Intel AMT activation.'); return; }
110
- if ((mesh.amt.type != 3) && (mesh.amt.type != 4)) { parent.debug('amtsca', addr, 'Device group does not have ACM activation policy.'); return; }
121
+ if ((mesh == null) || (mesh.mtype !== 1) || (typeof mesh.amt !== 'object') || (typeof mesh.amt.type !== 'number')) { dev.consoleMsg('Invalid device group for Intel AMT activation.'); return; }
122
+ if ((mesh.amt.type != 3) && (mesh.amt.type != 4)) { dev.consoleMsg('Device group does not have ACM activation policy.'); return; }
123
dev.mesh = mesh;
124
dev.domainid = mesh.domain;
125
@@ -154,36 +166,350 @@ module.exports.CreateAmtHelloServer = function (parent, config) {
166
function processHelloDataEx1(dev) {
167
// Get an activation certificate chain
168
const certinfo = checkAcmActivation(dev);
157
- if (certinfo == null) { parent.debug('amtsca', dev.hostname, 'Unable to find a matching ACM activation certificate.'); destroyDevice(dev); return; }
169
+ if (certinfo == null) { dev.consoleMsg('Unable to find a matching ACM activation certificate.'); destroyDevice(dev); return; }
170
var certchain = parent.certificateOperations.getAcmCertChain(parent.config.domains[dev.domainid], dev.trustedFqdn, certinfo.cert.sha256);
159
- if (certchain == null) { parent.debug('amtsca', dev.hostname, 'Unable to create TLS certificate chain.'); destroyDevice(dev); return; }
171
+ if (certchain == null) { dev.consoleMsg('Unable to create TLS certificate chain.'); destroyDevice(dev); return; }
172
dev.certchain = certchain;
173
174
// Setup a connection to the Intel AMT device
163
- parent.debug('amtsca', dev.hostname, 'Launching TLS connection...');
175
+ dev.consoleMsg('Launching TLS connection...');
176
var comm = CreateWsmanComm(dev.hostname, 16993, 'admin', '', 1, { cert: dev.certchain.certs.reverse().join(''), key: dev.certchain.signkey }); // Perform TLS connection
177
comm.xtlsFingerprint = 0; // No Intel AMT certificate checking.
178
var wsstack = WsmanStackCreateService(comm);
179
dev.amtstack = AmtStackCreateService(wsstack);
180
dev.amtstack.dev = dev;
169
- dev.amtstack.BatchEnum(null, ['*AMT_GeneralSettings', '*IPS_HostBasedSetupService'], processHelloDataEx2);
181
+ dev.amtstack.BatchEnum(null, ['*AMT_GeneralSettings', 'CIM_SoftwareIdentity', '*AMT_SetupAndConfigurationService'], processHelloDataEx2);
182
}
183
184
function processHelloDataEx2(stack, name, responses, status) {
185
const dev = stack.dev;
174
- if (status != 200) { parent.debug('amtsca', dev.hostname, 'Failed TLS connection, status=' + status + '.'); destroyDevice(dev); return; }
175
- parent.debug('amtsca', dev.hostname, 'Succesful TLS connection.');
186
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
187
+ if (status != 200) { dev.consoleMsg('Failed TLS connection, status=' + status + '.'); destroyDevice(dev); return; }
188
177
- //console.log(JSON.stringify(dev.certinfo, null, 2));
178
- console.log('processHelloDataEx2', status, responses);
189
+ // Fetch the Intel AMT version from WSMAN
190
+ if ((responses != null) && (responses['CIM_SoftwareIdentity'] != null) && (responses['CIM_SoftwareIdentity'].responses != null)) {
191
+ var amtlogicalelements = [];
192
+ amtlogicalelements = responses['CIM_SoftwareIdentity'].responses;
193
+ if (responses['AMT_SetupAndConfigurationService'] != null && responses['AMT_SetupAndConfigurationService'].response != null) {
194
+ amtlogicalelements.push(responses['AMT_SetupAndConfigurationService'].response);
195
+ }
196
+ if (amtlogicalelements.length > 0) {
197
+ var vs = getInstance(amtlogicalelements, 'AMT')['VersionString'];
198
+ if (vs != null) {
199
+ dev.amtversionstr = vs;
200
+ dev.amtversion = parseInt(dev.amtversionstr.split('.')[0]);
201
+ dev.amtversionmin = parseInt(dev.amtversionstr.split('.')[1]);
202
+ }
203
+ }
204
+ }
205
180
- // TODO: Perform ACM activation
206
+ // Fetch the Intel AMT version from HTTP stack
207
+ if ((dev.amtversionstr == null) && (stack.wsman.comm.amtVersion != null)) {
208
+ var s = stack.wsman.comm.amtVersion.split('.');
209
+ if (s.length >= 3) {
210
+ dev.amtversionstr = s[0] + '.' + s[1] + '.' + s[2];
211
+ dev.amtversion = parseInt(s[0]);
212
+ dev.amtversionmin = parseInt(s[1]);
213
+ }
214
+ }
215
+
216
+ // If we can't get the Intel AMT version, stop here.
217
+ if (dev.amtversionstr == null) { parent.debug('amtsca', dev.hostname, 'Could not get Intel AMT version.'); destroyDevice(dev); return; } // Could not get Intel AMT version, disconnect();
218
+
219
+ // Get the digest realm
220
+ if (responses['AMT_GeneralSettings'] && responses['AMT_GeneralSettings'].response && (typeof responses['AMT_GeneralSettings'].response['DigestRealm'] == 'string')) {
221
+ dev.realm = responses['AMT_GeneralSettings'].response['DigestRealm'];
222
+ } else {
223
+ dev.consoleMsg('Could not get Intel AMT digest realm.'); destroyDevice(dev); return;
224
+ }
225
+
226
+ // Looks like we are doing well.
227
+ parent.debug('amtsca', dev.hostname, 'Succesful TLS connection, Intel AMT v' + dev.amtversionstr);
228
+
229
+ // Set the new MEBx password
230
+ dev.consoleMsg('Setting MEBx password...');
231
+ dev.amtstack.AMT_SetupAndConfigurationService_SetMEBxPassword(config.newmebxpassword, processHelloDataEx3);
232
+ }
233
+
234
+ // Response from setting MEBx password
235
+ function processHelloDataEx3(stack, name, responses, status) {
236
+ const dev = stack.dev;
237
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
238
+ if (status != 200) { dev.consoleMsg('Failed to set MEBx password, status=' + status + '.'); destroyDevice(dev); return; }
239
+ parent.debug('amtsca', dev.hostname, 'MEBx password set. Setting admin password...');
240
+
241
+ // See what admin password to use
242
+ dev.pass = dev.mesh.amt.password;
243
+ if (dev.pass == null) { dev.pass = getRandomAmtPassword(); }
244
+
245
+ // Set the admin password
246
+ dev.amtstack.AMT_AuthorizationService_SetAdminAclEntryEx('admin', hex_md5('admin:' + dev.realm + ':' + dev.pass), processHelloDataEx4);
247
+ }
248
+
249
+ // Response from setting admin password
250
+ function processHelloDataEx4(stack, name, responses, status) {
251
+ const dev = stack.dev;
252
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
253
+ if (status != 200) { parent.debug('amtsca', dev.hostname, 'Failed to set admin password, status=' + status + '.'); destroyDevice(dev); return; }
254
+ parent.debug('amtsca', dev.hostname, 'Admin password set.');
255
+
256
+ // Setup TLS and commit.
257
+ dev.intelamt = {};
258
+ dev.aquired = {};
259
+ attemptTlsSync(dev, function (dev) {
260
+ destroyDevice(dev)
261
+ dev.consoleMsg('Intel AMT ACM activation completed.');
262
+ });
263
+ }
264
+
265
+ // Check if Intel AMT TLS state is correct
266
+ function attemptTlsSync(dev, func) {
267
+ dev.taskCount = 1;
268
+ dev.taskCompleted = func;
269
+ // TODO: We only deal with certificates starting with Intel AMT 6 and beyond
270
+ dev.amtstack.BatchEnum(null, ['AMT_PublicKeyCertificate', 'AMT_PublicPrivateKeyPair', 'AMT_TLSSettingData', 'AMT_TLSCredentialContext'], attemptTlsSyncEx);
271
+ }
272
+
273
+ function attemptTlsSyncEx(stack, name, responses, status) {
274
+ const dev = stack.dev;
275
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
276
+ if (status != 200) { dev.consoleMsg("Failed to get security information (" + status + ")."); destroyDevice(dev); return; }
277
+
278
+ // Setup the certificates
279
+ dev.policy = {};
280
+ dev.policy.certPrivateKeys = responses['AMT_PublicPrivateKeyPair'].responses;
281
+ dev.policy.tlsSettings = responses['AMT_TLSSettingData'].responses;
282
+ dev.policy.tlsCredentialContext = responses['AMT_TLSCredentialContext'].responses;
283
+ var xxCertificates = responses['AMT_PublicKeyCertificate'].responses;
284
+ for (var i in xxCertificates) {
285
+ xxCertificates[i].TrustedRootCertficate = (xxCertificates[i]['TrustedRootCertficate'] == true);
286
+ xxCertificates[i].X509CertificateBin = Buffer.from(xxCertificates[i]['X509Certificate'], 'base64').toString('binary');
287
+ xxCertificates[i].XIssuer = parseCertName(xxCertificates[i]['Issuer']);
288
+ xxCertificates[i].XSubject = parseCertName(xxCertificates[i]['Subject']);
289
+ }
290
+ amtcert_linkCertPrivateKey(xxCertificates, dev.policy.certPrivateKeys);
291
+ dev.policy.certificates = xxCertificates;
292
+ dev.consoleMsg("Intel AMT has " + xxCertificates.length + " certificate(s) and " + dev.policy.certPrivateKeys.length + " private keys(s).");
293
+
294
+ // Find the current TLS certificate & MeshCentral root certificate
295
+ var xxTlsCurrentCert = null;
296
+ if (dev.policy.tlsCredentialContext.length > 0) {
297
+ var certInstanceId = dev.policy.tlsCredentialContext[0]['ElementInContext']['ReferenceParameters']['SelectorSet']['Selector']['Value'];
298
+ for (var i in dev.policy.certificates) { if (dev.policy.certificates[i]['InstanceID'] == certInstanceId) { xxTlsCurrentCert = i; } }
299
+ }
300
+
301
+ // This is a managed device and TLS is not enabled, turn it on.
302
+ /*
303
+ if (xxTlsCurrentCert === null) {
304
+ // Start by generating a key pair
305
+ dev.consoleMsg("No TLS certificate. Generating key pair...");
306
+ dev.amtstack.AMT_PublicKeyManagementService_GenerateKeyPair(0, 2048, function (stack, name, responses, status) {
307
+ const dev = stack.dev;
308
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
309
+ if (status != 200) { dev.consoleMsg("Failed to generate a key pair (" + status + ")."); removeAmtDevice(dev, 20); return; }
310
+
311
+ // Check that we get a key pair reference
312
+ var x = null;
313
+ try { x = responses.Body['KeyPair']['ReferenceParameters']['SelectorSet']['Selector']['Value']; } catch (ex) { }
314
+ if (x == null) { dev.consoleMsg("Unable to get key pair reference."); removeAmtDevice(dev, 21); return; }
315
+
316
+ // Get the new key pair
317
+ dev.consoleMsg("Fetching key pair...");
318
+ dev.amtstack.Enum('AMT_PublicPrivateKeyPair', function (stack, name, responses, status, tag) {
319
+ const dev = stack.dev;
320
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
321
+ if (status != 200) { dev.consoleMsg("Failed to get a key pair list (" + status + ")."); removeAmtDevice(dev, 22); return; }
322
+
323
+ // Get the new DER key
324
+ var DERKey = null;
325
+ for (var i in responses) { if (responses[i]['InstanceID'] == tag) { DERKey = responses[i]['DERKey']; } }
326
+
327
+ // Get certificate values
328
+ const commonName = 'IntelAMT-' + Buffer.from(parent.crypto.randomBytes(6), 'binary').toString('hex');
329
+ const domain = parent.config.domains[dev.domainid];
330
+ var serverName = 'MeshCentral';
331
+ if ((domain != null) && (domain.title != null)) { serverName = domain.title; }
332
+ const certattributes = { 'CN': commonName, 'O': serverName, 'ST': 'MC', 'C': 'MC' };
333
+
334
+ // See what root certificate to use to sign the TLS cert
335
+ var xxCaPrivateKey = parent.webserver.certificates.root.key; // Use our own root by default
336
+ var issuerattributes = { 'CN': obj.rootCertCN };
337
+ if (domain.amtmanager.tlsrootcert2 != null) {
338
+ xxCaPrivateKey = domain.amtmanager.tlsrootcert2.key;
339
+ issuerattributes = domain.amtmanager.tlsrootcert2.attributes;
340
+ // TODO: We should change the start and end dates of our issued certificate to at least match the root.
341
+ // TODO: We could do one better and auto-renew TLS certificates as needed.
342
+ }
343
+
344
+ // Set the extended key usages
345
+ var extKeyUsage = { name: 'extKeyUsage', serverAuth: true, clientAuth: true }
346
+
347
+ // Sign the key pair using the CA certifiate
348
+ dev.consoleMsg("Signing certificate...");
349
+ const cert = parent.amtManager.amtcert_createCertificate(certattributes, xxCaPrivateKey, DERKey, issuerattributes, extKeyUsage);
350
+ if (cert == null) { dev.consoleMsg("Failed to sign the TLS certificate."); removeAmtDevice(dev, 23); return; }
351
+
352
+ // Place the resulting signed certificate back into AMT
353
+ var pem = obj.parent.certificateOperations.forge.pki.certificateToPem(cert).replace(/(\r\n|\n|\r)/gm, '');
354
+
355
+ // Set the certificate finderprint (SHA1)
356
+ var md = obj.parent.certificateOperations.forge.md.sha1.create();
357
+ md.update(obj.parent.certificateOperations.forge.asn1.toDer(obj.parent.certificateOperations.forge.pki.certificateToAsn1(cert)).getBytes());
358
+ dev.aquired.xhash = md.digest().toHex();
359
+
360
+ dev.consoleMsg("Adding certificate...");
361
+ dev.amtstack.AMT_PublicKeyManagementService_AddCertificate(pem.substring(27, pem.length - 25), function (stack, name, responses, status) {
362
+ const dev = stack.dev;
363
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
364
+ if (status != 200) { dev.consoleMsg("Failed to add TLS certificate (" + status + ")."); removeAmtDevice(dev, 24); return; }
365
+ var certInstanceId = null;
366
+ try { certInstanceId = responses.Body['CreatedCertificate']['ReferenceParameters']['SelectorSet']['Selector']['Value']; } catch (ex) { }
367
+ if (certInstanceId == null) { dev.consoleMsg("Failed to get TLS certificate identifier."); removeAmtDevice(dev, 25); return; }
368
+
369
+ // Set the TLS certificate
370
+ dev.setTlsSecurityPendingCalls = 3;
371
+ if (dev.policy.tlsCredentialContext.length > 0) {
372
+ // Modify the current context
373
+ var newTLSCredentialContext = Clone(dev.policy.tlsCredentialContext[0]);
374
+ newTLSCredentialContext['ElementInContext']['ReferenceParameters']['SelectorSet']['Selector']['Value'] = certInstanceId;
375
+ dev.amtstack.Put('AMT_TLSCredentialContext', newTLSCredentialContext, amtSwitchToTls, 0, 1);
376
+ } else {
377
+ // Add a new security context
378
+ dev.amtstack.Create('AMT_TLSCredentialContext', {
379
+ 'ElementInContext': '<a:Address>/wsman</a:Address><a:ReferenceParameters><w:ResourceURI>' + dev.amtstack.CompleteName('AMT_PublicKeyCertificate') + '</w:ResourceURI><w:SelectorSet><w:Selector Name="InstanceID">' + certInstanceId + '</w:Selector></w:SelectorSet></a:ReferenceParameters>',
380
+ 'ElementProvidingContext': '<a:Address>/wsman</a:Address><a:ReferenceParameters><w:ResourceURI>' + dev.amtstack.CompleteName('AMT_TLSProtocolEndpointCollection') + '</w:ResourceURI><w:SelectorSet><w:Selector Name="ElementName">TLSProtocolEndpointInstances Collection</w:Selector></w:SelectorSet></a:ReferenceParameters>'
381
+ }, amtSwitchToTls);
382
+ }
383
+
384
+ // Figure out what index is local & remote
385
+ var localNdx = ((dev.policy.tlsSettings[0]['InstanceID'] == 'Intel(r) AMT LMS TLS Settings')) ? 0 : 1, remoteNdx = (1 - localNdx);
386
+
387
+ // Remote TLS settings
388
+ var xxTlsSettings2 = Clone(dev.policy.tlsSettings);
389
+ xxTlsSettings2[remoteNdx]['Enabled'] = true;
390
+ xxTlsSettings2[remoteNdx]['MutualAuthentication'] = false;
391
+ xxTlsSettings2[remoteNdx]['AcceptNonSecureConnections'] = true;
392
+ delete xxTlsSettings2[remoteNdx]['TrustedCN'];
393
+
394
+ // Local TLS settings
395
+ xxTlsSettings2[localNdx]['Enabled'] = true;
396
+ delete xxTlsSettings2[localNdx]['TrustedCN'];
397
+
398
+ // Update TLS settings
399
+ dev.consoleMsg("Enabling TLS...");
400
+ dev.amtstack.Put('AMT_TLSSettingData', xxTlsSettings2[0], amtSwitchToTls, 0, 1, xxTlsSettings2[0]);
401
+ dev.amtstack.Put('AMT_TLSSettingData', xxTlsSettings2[1], amtSwitchToTls, 0, 1, xxTlsSettings2[1]);
402
+ });
403
+
404
+ }, responses.Body['KeyPair']['ReferenceParameters']['SelectorSet']['Selector']['Value']);
405
+ });
406
+ } else {
407
+ */
408
+ // TLS already enabled, update device in the database
409
+ dev.consoleMsg("Intel AMT has TLS already enabled.");
410
+ dev.intelamt.tls = dev.aquired.tls = 1;
411
+ UpdateDevice(dev);
412
+
413
+ // Perform commit
414
+ dev.taskCount = 1;
415
+ amtPerformCommit(dev);
416
+ //}
417
+ }
418
+
419
+ function amtSwitchToTls(stack, name, responses, status) {
420
+ const dev = stack.dev;
421
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
422
+ if (status != 200) { dev.consoleMsg("Failed setup TLS (" + status + ")."); removeAmtDevice(dev, 26); return; }
423
+ dev.consoleMsg("Switched to TLS.");
424
+
425
+ // Check if all the calls are done & perform a commit
426
+ if ((--dev.setTlsSecurityPendingCalls) == 0) {
427
+ dev.consoleMsg("Calling Commit...");
428
+ amtPerformCommit(dev);
429
+ }
430
+ }
431
+
432
+ function amtPerformCommit(dev) {
433
+ dev.consoleMsg("Performing commit...");
434
+ dev.amtstack.AMT_SetupAndConfigurationService_CommitChanges(null, function (stack, name, responses, status) {
435
+ const dev = stack.dev;
436
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
437
+ if (status != 200) { dev.consoleMsg("Failed perform commit (" + status + ")."); removeAmtDevice(dev, 27); return; }
438
+ dev.consoleMsg("Commited, holding 5 seconds...");
439
+
440
+ // Update device in the database
441
+ dev.intelamt.tls = dev.aquired.tls = 1;
442
+ dev.intelamt.hash = dev.aquired.hash = dev.aquired.xhash;
443
+ delete dev.aquired.xhash;
444
+ UpdateDevice(dev);
445
+
446
+ // Switch our communications to TLS (Restart our management of this node)
447
+ dev.switchToTls = 1;
448
+ delete dev.tlsfail;
449
+
450
+ // Wait 5 seconds before attempting to manage this device some more
451
+ var f = function doManage() { if (isAmtDeviceValid(dev)) { devTaskCompleted(doManage.dev); } }
452
+ f.dev = dev;
453
+ setTimeout(f, 5000);
454
+ });
455
+ }
456
+
457
+ // Update the device in the database
458
+ function UpdateDevice(dev) {
459
+ console.log('UpdateDevice', dev.intelamt);
460
}
461
462
// Do aggressive cleanup on the device
463
function destroyDevice(dev) {
464
+ delete obj.devices[dev.addr];
465
if (dev.amtstack != null) { delete dev.amtstack.dev; delete dev.amtstack; }
186
- delete dev.certinfo;
466
+ delete dev.certchain;
467
+ delete dev.amtversionstr;
468
+ delete dev.amtversion;
469
+ delete dev.amtversionmin;
470
+ delete dev.realm;
471
+ }
472
+
473
+ //
474
+ // General Methods
475
+ //
476
+
477
+ // Called this when a task is completed, when all tasks are completed the call back function will be called.
478
+ function devTaskCompleted(dev) {
479
+ dev.taskCount--;
480
+ if (dev.taskCount == 0) { var f = dev.taskCompleted; delete dev.taskCount; delete dev.taskCompleted; if (f != null) { f(dev); } }
481
+ }
482
+
483
+ // Check which key pair matches the public key in the certificate
484
+ function amtcert_linkCertPrivateKey(certs, keys) {
485
+ for (var i in certs) {
486
+ var cert = certs[i];
487
+ try {
488
+ if (keys.length == 0) return;
489
+ var b = obj.parent.certificateOperations.forge.asn1.fromDer(cert.X509CertificateBin);
490
+ var a = obj.parent.certificateOperations.forge.pki.certificateFromAsn1(b).publicKey;
491
+ var publicKeyPEM = obj.parent.certificateOperations.forge.pki.publicKeyToPem(a).substring(28 + 32).replace(/(\r\n|\n|\r)/gm, "");
492
+ for (var j = 0; j < keys.length; j++) {
493
+ if (publicKeyPEM === (keys[j]['DERKey'] + '-----END PUBLIC KEY-----')) {
494
+ keys[j].XCert = cert; // Link the key pair to the certificate
495
+ cert.XPrivateKey = keys[j]; // Link the certificate to the key pair
496
+ }
497
+ }
498
+ } catch (e) { console.log(e); }
499
+ }
500
+ }
501
+
502
+ function isAmtDeviceValid(dev) { return (obj.devices[dev.addr] != null); }
503
+ function getInstance(x, y) { for (var i in x) { if (x[i]['InstanceID'] == y) return x[i]; } return null; }
504
+ function checkAmtPassword(p) { return (p.length > 7) && (/\d/.test(p)) && (/[a-z]/.test(p)) && (/[A-Z]/.test(p)) && (/\W/.test(p)); }
505
+ function getRandomAmtPassword() { var p; do { p = Buffer.from(obj.crypto.randomBytes(9), 'binary').toString('base64').split('/').join('@'); } while (checkAmtPassword(p) == false); return p; }
506
+ function hex_md5(str) { return parent.crypto.createHash('md5').update(str).digest('hex'); }
507
+ function Clone(v) { return JSON.parse(JSON.stringify(v)); }
508
+
509
+ function parseCertName(x) {
510
+ var j, r = {}, xx = x.split(',');
511
+ for (var i in xx) { j = xx[i].indexOf('='); r[xx[i].substring(0, j)] = xx[i].substring(j + 1); }
512
+ return r;
513
}
514
515
return obj;
amtmanager.js
+3
-3
@@ -930,7 +930,7 @@ module.exports.CreateAmtManager = function (parent) {
930
var extKeyUsage = { name: 'extKeyUsage', serverAuth: true, clientAuth: true }
931
932
// Sign the key pair using the CA certifiate
933
- const cert = amtcert_createCertificate(certattributes, xxCaPrivateKey, DERKey, issuerattributes, extKeyUsage);
933
+ const cert = obj.amtcert_createCertificate(certattributes, xxCaPrivateKey, DERKey, issuerattributes, extKeyUsage);
934
if (cert == null) { dev.consoleMsg("Failed to sign the TLS certificate."); removeAmtDevice(dev, 23); return; }
935
936
// Place the resulting signed certificate back into AMT
@@ -2080,7 +2080,7 @@ module.exports.CreateAmtManager = function (parent) {
2080
2081
/*
2082
function amtcert_signWithCaKey(DERKey, caPrivateKey, certAttributes, issuerAttributes, extKeyUsage) {
2083
- return amtcert_createCertificate(certAttributes, caPrivateKey, DERKey, issuerAttributes, extKeyUsage);
2083
+ return obj.amtcert_createCertificate(certAttributes, caPrivateKey, DERKey, issuerAttributes, extKeyUsage);
2084
}
2085
*/
2086
@@ -2092,7 +2092,7 @@ module.exports.CreateAmtManager = function (parent) {
2092
// 2.16.840.1.113741.1.2.3 = Intel AMT Client Setup Certificate (Zero-Touch)
2093
2094
// Generate a certificate with a set of attributes signed by a rootCert. If the rootCert is obmitted, the generated certificate is self-signed.
2095
- function amtcert_createCertificate(certAttributes, caPrivateKey, DERKey, issuerAttributes, extKeyUsage) {
2095
+ obj.amtcert_createCertificate = function(certAttributes, caPrivateKey, DERKey, issuerAttributes, extKeyUsage) {
2096
// Generate a keypair and create an X.509v3 certificate
2097
var keys, cert = obj.parent.certificateOperations.forge.pki.createCertificate();
2098
cert.publicKey = obj.parent.certificateOperations.forge.pki.publicKeyFromPem('-----BEGIN PUBLIC KEY-----' + DERKey + '-----END PUBLIC KEY-----');
public/scripts/agent-redir-ws-0.1.1-min.js
+1
-1
@@ -1 +1 @@
1
-var CreateAgentRedirect=function(e,t,n,o,a,c){var s={};function l(){1==s.webSwitchOk&&1==s.webRtcActive&&(s.latency.current=-1,s.sendCtrlMsg('{"ctrlChannel":"102938","type":"webrtc0"}'),s.sendCtrlMsg('{"ctrlChannel":"102938","type":"webrtc1"}'),null!=s.onStateChanged&&s.onStateChanged(s,s.State))}((s.m=t).parent=s).meshserver=e,s.authCookie=o,s.rauthCookie=a,s.State=0,s.nodeid=null,s.options=null,s.socket=null,s.connectstate=-1,s.tunnelid=Math.random().toString(36).substring(2),s.protocol=t.protocol,s.onStateChanged=null,s.ctrlMsgAllowed=!0,s.attemptWebRTC=!1,s.webRtcActive=!1,s.webSwitchOk=!1,s.webchannel=null,s.webrtc=null,s.debugmode=0,s.serverIsRecording=!1,s.latency={lastSend:null,current:-1,callback:null},null==c&&(c="/"),s.consoleMessage=null,s.onConsoleMessageChange=null,s.metadata=null,s.onMetadataChange=null,s.Start=function(e){var t=window.location.protocol.replace("http","ws")+"//"+window.location.host+window.location.pathname.substring(0,window.location.pathname.lastIndexOf("/"))+"/meshrelay.ashx?browser=1&p="+s.protocol+(e?"&nodeid="+e:"")+"&id="+s.tunnelid;null!=o&&""!=o&&(t+="&auth="+o),null!=urlargs&&null!=urlargs.slowrelay&&(t+="&slowrelay="+urlargs.slowrelay),s.nodeid=e,s.connectstate=0,s.socket=new WebSocket(t),s.socket.binaryType="arraybuffer",s.socket.onopen=s.xxOnSocketConnected,s.socket.onmessage=s.xxOnMessage,s.socket.onerror=function(e){},s.socket.onclose=s.xxOnSocketClosed,s.xxStateChange(1),null!=s.meshserver&&(e="*"+c+"meshrelay.ashx?p="+s.protocol+"&nodeid="+e+"&id="+s.tunnelid,null!=a&&""!=a&&(e+="&rauth="+a),s.meshserver.send({action:"msg",type:"tunnel",nodeid:s.nodeid,value:e,usage:s.protocol}))},s.xxOnSocketConnected=function(){1==s.debugmode&&console.log("onSocketConnected"),s.xxStateChange(2)},s.xxOnControlCommand=function(e){var t;try{t=JSON.parse(e)}catch(e){return}"102938"==t.ctrlChannel?("undefined"!=typeof args&&args.redirtrace&&console.log("RedirRecv",t),"console"==t.type?s.setConsoleMessage(t.msg,t.msgid,t.msgargs,t.timeout):"metadata"==t.type?(s.metadata=t,s.onMetadataChange&&s.onMetadataChange(s.metadata)):"rtt"==t.type&&"number"==typeof t.time?(s.latency.current=(new Date).getTime()-t.time,null!=s.latency.callbacks&&s.latency.callback(s.latency.current)):null!=s.webrtc&&("answer"==t.type?s.webrtc.setRemoteDescription(new RTCSessionDescription(t),function(){},s.xxCloseWebRTC):"webrtc0"==t.type?(s.webSwitchOk=!0,l()):"webrtc1"==t.type?s.sendCtrlMsg('{"ctrlChannel":"102938","type":"webrtc2"}'):t.type)):s.m.ProcessData(e)},s.setConsoleMessage=function(e,t,n,o){s.consoleMessage!=e&&(s.consoleMessage=e,s.consoleMessageId=t,s.consoleMessageArgs=n,s.consoleMessageTimeout=o,s.onConsoleMessageChange&&s.onConsoleMessageChange(s,s.consoleMessage,s.consoleMessageId))},s.sendCtrlMsg=function(e){if(1==s.ctrlMsgAllowed){"undefined"!=typeof args&&args.redirtrace&&console.log("RedirSend",typeof e,e);try{s.socket.send(e)}catch(e){}}},s.xxOnMessage=function(e){if(s.State<3&&("c"==e.data||"cr"==e.data)){if("cr"==e.data&&(s.serverIsRecording=!0),null!=s.options){delete s.options.action,s.options.type="options";try{s.sendCtrlMsg(JSON.stringify(s.options))}catch(e){}}try{s.socket.send(s.protocol)}catch(e){}return s.xxStateChange(3),void(1==s.attemptWebRTC&&(r=null,"undefined"!=typeof RTCPeerConnection?s.webrtc=new RTCPeerConnection(r):"undefined"!=typeof webkitRTCPeerConnection&&(s.webrtc=new webkitRTCPeerConnection(r)),null!=s.webrtc&&s.webrtc.createDataChannel&&(s.webchannel=s.webrtc.createDataChannel("DataChannel",{}),s.webchannel.binaryType="arraybuffer",s.webchannel.onmessage=s.xxOnMessage,s.webchannel.onopen=function(){s.webRtcActive=!0,l()},s.webchannel.onclose=function(e){s.webRtcActive&&s.Stop()},s.webrtc.onicecandidate=function(e){if(null==e.candidate)try{s.sendCtrlMsg(JSON.stringify(s.webrtcoffer))}catch(e){}else s.webrtcoffer.sdp+="a="+e.candidate.candidate+"\r\n"},s.webrtc.oniceconnectionstatechange=function(){null!=s.webrtc&&("disconnected"==s.webrtc.iceConnectionState?1==s.webRtcActive?s.Stop():s.xxCloseWebRTC():"failed"==s.webrtc.iceConnectionState&&s.xxCloseWebRTC())},s.webrtc.createOffer(function(e){s.webrtcoffer=e,s.webrtc.setLocalDescription(e,function(){},s.xxCloseWebRTC)},s.xxCloseWebRTC,{mandatory:{OfferToReceiveAudio:!1,OfferToReceiveVideo:!1}}))))}if("string"==typeof e.data)s.xxOnControlCommand(e.data);else if(s.m.ProcessBinaryCommand)if(0!=u){var t=new Uint8Array(e.data);if(g.push(t),u+=t.byteLength,d<=u){var n,o=new Uint8Array(u),a=0;for(n in g)o.set(g[n],a),a+=g[n].byteLength;s.m.ProcessBinaryCommand(i,d,o),u=d=i=0,g=[]}}else{var c=((t=new Uint8Array(e.data))[0]<<8)+t[1],r=(t[2]<<8)+t[3];27==c&&8==r&&(c=(t[8]<<8)+t[9],r=(t[5]<<16)+(t[6]<<8)+t[7],t=t.slice(8)),r!=t.byteLength?(i=c,d=r,u=t.byteLength,g=[t]):s.m.ProcessBinaryCommand(c,r,t)}else s.m.ProcessBinaryData?s.m.ProcessBinaryData(new Uint8Array(e.data)):e.data.byteLength<16e3?s.m.ProcessData(String.fromCharCode.apply(null,new Uint8Array(e.data))):(t=new Blob([new Uint8Array(e.data)]),(e=new FileReader).onload=function(e){s.m.ProcessData(e.target.result)},e.readAsText(t))};var i=0,d=0,u=0,g=[];return s.sendText=function(e){"string"!=typeof e&&(e=JSON.stringify(e)),s.send(encode_utf8(e))},s.send=function(e){"undefined"!=typeof args&&args.redirtrace&&console.log("RedirSend",typeof e,e.length,"{"==e[0]?e:rstr2hex(e).substring(0,64));try{if(null!=s.socket&&s.socket.readyState==WebSocket.OPEN)if("string"==typeof e)if(1==s.debugmode){for(var t=new Uint8Array(e.length),n=[],o=0;o<e.length;++o)t[o]=e.charCodeAt(o),n.push(e.charCodeAt(o));(1==s.webRtcActive?s.webchannel:s.socket).send(t.buffer)}else{for(t=new Uint8Array(e.length),o=0;o<e.length;++o)t[o]=e.charCodeAt(o);(1==s.webRtcActive?s.webchannel:s.socket).send(t.buffer)}else(1==s.webRtcActive?s.webchannel:s.socket).send(e)}catch(e){}},s.xxOnSocketClosed=function(){s.Stop(1)},s.xxStateChange=function(e){s.State!=e&&(s.State=e,s.m.xxStateChange(s.State),null!=s.onStateChanged&&s.onStateChanged(s,s.State))},s.xxCloseWebRTC=function(){if(null!=s.webchannel){try{s.webchannel.close()}catch(e){}s.webchannel=null}if(null!=s.webrtc){try{s.webrtc.close()}catch(e){}s.webrtc=null}s.webRtcActive=!1},s.Stop=function(e){if(1==s.debugmode&&console.log("stop",e),s.xxCloseWebRTC(),s.connectstate=-1,null!=s.socket){try{1==s.socket.readyState&&(s.sendCtrlMsg('{"ctrlChannel":"102938","type":"close"}'),s.socket.close())}catch(e){}s.socket=null}s.xxStateChange(0)},s}
\ No newline at end of file
1
+var CreateAgentRedirect=function(e,t,n,o,a,c){var s={};function l(){1==s.webSwitchOk&&1==s.webRtcActive&&(s.latency.current=-1,s.sendCtrlMsg('{"ctrlChannel":"102938","type":"webrtc0"}'),s.sendCtrlMsg('{"ctrlChannel":"102938","type":"webrtc1"}'),null!=s.onStateChanged&&s.onStateChanged(s,s.State))}((s.m=t).parent=s).meshserver=e,s.authCookie=o,s.rauthCookie=a,s.State=0,s.nodeid=null,s.options=null,s.socket=null,s.connectstate=-1,s.tunnelid=Math.random().toString(36).substring(2),s.protocol=t.protocol,s.onStateChanged=null,s.ctrlMsgAllowed=!0,s.attemptWebRTC=!1,s.webRtcActive=!1,s.webSwitchOk=!1,s.webchannel=null,s.webrtc=null,s.debugmode=0,s.serverIsRecording=!1,s.latency={lastSend:null,current:-1,callback:null},null==c&&(c="/"),s.consoleMessage=null,s.onConsoleMessageChange=null,s.metadata=null,s.onMetadataChange=null,s.Start=function(e){var t=window.location.protocol.replace("http","ws")+"//"+window.location.host+window.location.pathname.substring(0,window.location.pathname.lastIndexOf("/"))+"/meshrelay.ashx?browser=1&p="+s.protocol+(e?"&nodeid="+e:"")+"&id="+s.tunnelid;null!=o&&""!=o&&(t+="&auth="+o),null!=urlargs&&null!=urlargs.slowrelay&&(t+="&slowrelay="+urlargs.slowrelay),s.nodeid=e,s.connectstate=0,s.socket=new WebSocket(t),s.socket.binaryType="arraybuffer",s.socket.onopen=s.xxOnSocketConnected,s.socket.onmessage=s.xxOnMessage,s.socket.onerror=function(e){},s.socket.onclose=s.xxOnSocketClosed,s.xxStateChange(1),null!=s.meshserver&&(e="*"+c+"meshrelay.ashx?p="+s.protocol+"&nodeid="+e+"&id="+s.tunnelid,null!=a&&""!=a&&(e+="&rauth="+a),s.meshserver.send({action:"msg",type:"tunnel",nodeid:s.nodeid,value:e,usage:s.protocol}))},s.xxOnSocketConnected=function(){1==s.debugmode&&console.log("onSocketConnected"),s.xxStateChange(2)},s.xxOnControlCommand=function(e){var t;try{t=JSON.parse(e)}catch(e){return}"102938"==t.ctrlChannel?("undefined"!=typeof args&&args.redirtrace&&console.log("RedirRecv",t),"console"==t.type?s.setConsoleMessage(t.msg,t.msgid,t.msgargs,t.timeout):"metadata"==t.type?(s.metadata=t,s.onMetadataChange&&s.onMetadataChange(s.metadata)):"rtt"==t.type&&"number"==typeof t.time?(s.latency.current=(new Date).getTime()-t.time,null!=s.latency.callbacks&&s.latency.callback(s.latency.current)):null!=s.webrtc&&("answer"==t.type?s.webrtc.setRemoteDescription(new RTCSessionDescription(t),function(){},s.xxCloseWebRTC):"webrtc0"==t.type?(s.webSwitchOk=!0,l()):"webrtc1"==t.type?s.sendCtrlMsg('{"ctrlChannel":"102938","type":"webrtc2"}'):t.type)):s.m.ProcessData(e)},s.setConsoleMessage=function(e,t,n,o){s.consoleMessage!=e&&(s.consoleMessage=e,s.consoleMessageId=t,s.consoleMessageArgs=n,s.consoleMessageTimeout=o,s.onConsoleMessageChange&&s.onConsoleMessageChange(s,s.consoleMessage,s.consoleMessageId))},s.sendCtrlMsg=function(e){if(1==s.ctrlMsgAllowed){"undefined"!=typeof args&&args.redirtrace&&console.log("RedirSend",typeof e,e);try{s.socket.send(e)}catch(e){}}},s.xxOnMessage=function(e){if(s.State<3&&("c"==e.data||"cr"==e.data)){if("cr"==e.data&&(s.serverIsRecording=!0),null!=s.options){delete s.options.action,s.options.type="options";try{s.sendCtrlMsg(JSON.stringify(s.options))}catch(e){}}try{s.socket.send(s.protocol)}catch(e){}return s.xxStateChange(3),void(1==s.attemptWebRTC&&(r=null,"undefined"!=typeof RTCPeerConnection?s.webrtc=new RTCPeerConnection(r):"undefined"!=typeof webkitRTCPeerConnection&&(s.webrtc=new webkitRTCPeerConnection(r)),null!=s.webrtc&&s.webrtc.createDataChannel&&(s.webchannel=s.webrtc.createDataChannel("DataChannel",{}),s.webchannel.binaryType="arraybuffer",s.webchannel.onmessage=s.xxOnMessage,s.webchannel.onopen=function(){s.webRtcActive=!0,l()},s.webchannel.onclose=function(e){s.webRtcActive&&s.Stop()},s.webrtc.onicecandidate=function(e){if(null==e.candidate)try{s.sendCtrlMsg(JSON.stringify(s.webrtcoffer))}catch(e){}else s.webrtcoffer.sdp+="a="+e.candidate.candidate+"\r\n"},s.webrtc.oniceconnectionstatechange=function(){null!=s.webrtc&&("disconnected"==s.webrtc.iceConnectionState?1==s.webRtcActive?s.Stop():s.xxCloseWebRTC():"failed"==s.webrtc.iceConnectionState&&s.xxCloseWebRTC())},s.webrtc.createOffer(function(e){s.webrtcoffer=e,s.webrtc.setLocalDescription(e,function(){},s.xxCloseWebRTC)},s.xxCloseWebRTC,{mandatory:{OfferToReceiveAudio:!1,OfferToReceiveVideo:!1}}))))}if("string"==typeof e.data)s.xxOnControlCommand(e.data);else if(0!=u||1!=e.data.byteLength)if(s.m.ProcessBinaryCommand)if(0!=u){var t=new Uint8Array(e.data);if(g.push(t),u+=t.byteLength,d<=u){var n,o=new Uint8Array(u),a=0;for(n in g)o.set(g[n],a),a+=g[n].byteLength;s.m.ProcessBinaryCommand(i,d,o),u=d=i=0,g=[]}}else{var c=((t=new Uint8Array(e.data))[0]<<8)+t[1],r=(t[2]<<8)+t[3];27==c&&8==r&&(c=(t[8]<<8)+t[9],r=(t[5]<<16)+(t[6]<<8)+t[7],t=t.slice(8)),r!=t.byteLength?(i=c,d=r,u=t.byteLength,g=[t]):s.m.ProcessBinaryCommand(c,r,t)}else s.m.ProcessBinaryData?s.m.ProcessBinaryData(new Uint8Array(e.data)):e.data.byteLength<16e3?s.m.ProcessData(String.fromCharCode.apply(null,new Uint8Array(e.data))):(t=new Blob([new Uint8Array(e.data)]),(e=new FileReader).onload=function(e){s.m.ProcessData(e.target.result)},e.readAsText(t))};var i=0,d=0,u=0,g=[];return s.sendText=function(e){"string"!=typeof e&&(e=JSON.stringify(e)),s.send(encode_utf8(e))},s.send=function(e){"undefined"!=typeof args&&args.redirtrace&&console.log("RedirSend",typeof e,e.length,"{"==e[0]?e:rstr2hex(e).substring(0,64));try{if(null!=s.socket&&s.socket.readyState==WebSocket.OPEN)if("string"==typeof e)if(1==s.debugmode){for(var t=new Uint8Array(e.length),n=[],o=0;o<e.length;++o)t[o]=e.charCodeAt(o),n.push(e.charCodeAt(o));(1==s.webRtcActive?s.webchannel:s.socket).send(t.buffer)}else{for(t=new Uint8Array(e.length),o=0;o<e.length;++o)t[o]=e.charCodeAt(o);(1==s.webRtcActive?s.webchannel:s.socket).send(t.buffer)}else(1==s.webRtcActive?s.webchannel:s.socket).send(e)}catch(e){}},s.xxOnSocketClosed=function(){s.Stop(1)},s.xxStateChange=function(e){s.State!=e&&(s.State=e,s.m.xxStateChange(s.State),null!=s.onStateChanged&&s.onStateChanged(s,s.State))},s.xxCloseWebRTC=function(){if(null!=s.webchannel){try{s.webchannel.close()}catch(e){}s.webchannel=null}if(null!=s.webrtc){try{s.webrtc.close()}catch(e){}s.webrtc=null}s.webRtcActive=!1},s.Stop=function(e){if(1==s.debugmode&&console.log("stop",e),s.xxCloseWebRTC(),s.connectstate=-1,null!=s.socket){try{1==s.socket.readyState&&(s.sendCtrlMsg('{"ctrlChannel":"102938","type":"close"}'),s.socket.close())}catch(e){}s.socket=null}s.xxStateChange(0)},s}
\ No newline at end of file
public/scripts/agent-redir-ws-0.1.1.js
+3
@@ -172,6 +172,9 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort, au
172
if (typeof e.data == 'string') {
173
obj.xxOnControlCommand(e.data);
174
} else {
175
+ // If only 1 byte
176
+ if ((cmdAccLen == 0) && (e.data.byteLength == 1)) return; // Ignore single byte data, this is a keep alive.
177
+
178
// Send the data to the module
179
if (obj.m.ProcessBinaryCommand) {
180
// Send as Binary Command