Added TLS support to APF tunnels.
Ylian Saint-Hilaire committed
Oct 13, 2020 at 17:46 UTC
759a7bbaf591a7350f3472d8c28ed4753ab24ea4
6 files changed
+147
-84
agents/modules_meshcore/apfclient.js
+48
-60
@@ -17,7 +17,7 @@ limitations under the License.
17
/**
18
* @description APF/CIRA Client for Duktape
19
* @author Joko Sastriawan & Ylian Saint-Hilaire
20
-* @copyright Intel Corporation 2019
20
+* @copyright Intel Corporation 2020
21
* @license Apache-2.0
22
* @version v0.0.2
23
*/
@@ -139,12 +139,12 @@ function CreateAPFClient(parent, args) {
139
}
140
141
obj.onSecureConnect = function onSecureConnect(resp, ws, head) {
142
- Debug("APF Secure WebSocket connected.");
142
+ //Debug("APF Secure WebSocket connected.");
143
//console.log(JSON.stringify(resp));
144
obj.forwardClient.tag = { accumulator: [] };
145
obj.forwardClient.ws = ws;
146
obj.forwardClient.ws.on('end', function () {
147
- Debug("APF: Connection is closing.");
147
+ //Debug("APF: Connection is closing.");
148
if (obj.timer != null) {
149
clearInterval(obj.timer);
150
obj.timer = null;
@@ -157,11 +157,9 @@ function CreateAPFClient(parent, args) {
157
var len = 0;
158
do {
159
len = ProcessData(obj.forwardClient);
160
- if (len > 0) {
161
- obj.forwardClient.tag.accumulator = obj.forwardClient.tag.accumulator.slice(len);
162
- }
160
+ if (len > 0) { obj.forwardClient.tag.accumulator = obj.forwardClient.tag.accumulator.slice(len); }
161
if (obj.cirastate == CIRASTATE.FAILED) {
164
- Debug("APF: in a failed state, destroying socket.")
162
+ //Debug("APF: in a failed state, destroying socket.");
163
obj.forwardClient.ws.end();
164
}
165
} while (len > 0);
@@ -171,7 +169,7 @@ function CreateAPFClient(parent, args) {
169
});
170
171
obj.forwardClient.ws.on('error', function (e) {
174
- Debug("APF: Connection error, ending connecting.");
172
+ //Debug("APF: Connection error, ending connecting.");
173
if (obj.timer != null) {
174
clearInterval(obj.timer);
175
obj.timer = null;
@@ -187,20 +185,20 @@ function CreateAPFClient(parent, args) {
185
function SendJsonControl(socket, o) {
186
var data = JSON.stringify(o)
187
socket.write(String.fromCharCode(APFProtocol.JSON_CONTROL) + IntToStr(data.length) + data);
190
- Debug("APF: Send JSON control: " + data);
188
+ //Debug("APF: Send JSON control: " + data);
189
}
190
191
function SendProtocolVersion(socket, uuid) {
192
var data = String.fromCharCode(APFProtocol.PROTOCOLVERSION) + IntToStr(1) + IntToStr(0) + IntToStr(0) + hex2rstr(strToGuid(uuid)) + binzerostring(64);
193
socket.write(data);
196
- Debug("APF: Send protocol version 1 0 " + uuid);
194
+ //Debug("APF: Send protocol version 1 0 " + uuid);
195
obj.cirastate = CIRASTATE.PROTOCOL_VERSION_SENT;
196
}
197
198
function SendServiceRequest(socket, service) {
199
var data = String.fromCharCode(APFProtocol.SERVICE_REQUEST) + IntToStr(service.length) + service;
200
socket.write(data);
203
- Debug("APF: Send service request " + service);
201
+ //Debug("APF: Send service request " + service);
202
if (service == 'auth@amt.intel.com') {
203
obj.cirastate = CIRASTATE.AUTH_SERVICE_REQUEST_SENT;
204
} else if (service == 'pfwd@amt.intel.com') {
@@ -215,7 +213,7 @@ function CreateAPFClient(parent, args) {
213
data += IntToStr(8) + 'password';
214
data += binzerostring(1) + IntToStr(pass.length) + pass;
215
socket.write(data);
218
- Debug("APF: Send username password authentication to MPS");
216
+ //Debug("APF: Send username password authentication to MPS");
217
obj.cirastate = CIRASTATE.AUTH_REQUEST_SENT;
218
}
219
@@ -224,20 +222,18 @@ function CreateAPFClient(parent, args) {
222
var data = String.fromCharCode(APFProtocol.GLOBAL_REQUEST) + IntToStr(tcpipfwd.length) + tcpipfwd + binzerostring(1, 1);
223
data += IntToStr(amthostname.length) + amthostname + IntToStr(amtport);
224
socket.write(data);
227
- Debug("APF: Send tcpip-forward " + amthostname + ":" + amtport);
225
+ //Debug("APF: Send tcpip-forward " + amthostname + ":" + amtport);
226
obj.cirastate = CIRASTATE.GLOBAL_REQUEST_SENT;
227
}
228
229
function SendKeepAliveRequest(socket) {
232
- var data = String.fromCharCode(APFProtocol.KEEPALIVE_REQUEST) + IntToStr(255);
233
- socket.write(data);
234
- Debug("APF: Send keepalive request");
230
+ socket.write(String.fromCharCode(APFProtocol.KEEPALIVE_REQUEST) + IntToStr(255));
231
+ //Debug("APF: Send keepalive request");
232
}
233
234
function SendKeepAliveReply(socket, cookie) {
238
- var data = String.fromCharCode(APFProtocol.KEEPALIVE_REPLY) + IntToStr(cookie);
239
- socket.write(data);
240
- Debug("APF: Send keepalive reply");
235
+ socket.write(String.fromCharCode(APFProtocol.KEEPALIVE_REPLY) + IntToStr(cookie));
236
+ //Debug("APF: Send keepalive reply");
237
}
238
239
function ProcessData(socket) {
@@ -249,9 +245,8 @@ function CreateAPFClient(parent, args) {
245
// Respond to MPS according to obj.cirastate
246
switch (cmd) {
247
case APFProtocol.SERVICE_ACCEPT: {
252
- var slen = ReadInt(data, 1);
253
- var service = data.substring(5, 6 + slen);
254
- Debug("APF: Service request to " + service + " accepted.");
248
+ var slen = ReadInt(data, 1), service = data.substring(5, 6 + slen);
249
+ //Debug("APF: Service request to " + service + " accepted.");
250
if (service == 'auth@amt.intel.com') {
251
if (obj.cirastate >= CIRASTATE.AUTH_SERVICE_REQUEST_SENT) {
252
SendUserAuthRequest(socket.ws, obj.args.mpsuser, obj.args.mpspass);
@@ -266,47 +261,47 @@ function CreateAPFClient(parent, args) {
261
case APFProtocol.REQUEST_SUCCESS: {
262
if (len >= 5) {
263
var port = ReadInt(data, 1);
269
- Debug("APF: Request to port forward " + port + " successful.");
264
+ //Debug("APF: Request to port forward " + port + " successful.");
265
// iterate to pending port forward request
266
if (obj.pfwd_idx < pfwd_ports.length) {
267
SendGlobalRequestPfwd(socket.ws, obj.args.clientname, pfwd_ports[obj.pfwd_idx++]);
268
} else {
269
// no more port forward, now setup timer to send keep alive
275
- Debug("APF: Start keep alive for every " + obj.args.mpskeepalive + " ms.");
270
+ //Debug("APF: Start keep alive for every " + obj.args.mpskeepalive + " ms.");
271
obj.timer = setInterval(function () {
272
SendKeepAliveRequest(obj.forwardClient.ws);
273
}, obj.args.mpskeepalive);//
274
}
275
return 5;
276
}
282
- Debug("APF: Request successful.");
277
+ //Debug("APF: Request successful.");
278
return 1;
279
}
280
case APFProtocol.USERAUTH_SUCCESS: {
286
- Debug("APF: User Authentication successful");
281
+ //Debug("APF: User Authentication successful");
282
// Send Pfwd service request
283
SendServiceRequest(socket.ws, 'pfwd@amt.intel.com');
284
return 1;
285
}
286
case APFProtocol.USERAUTH_FAILURE: {
292
- Debug("APF: User Authentication failed");
287
+ //Debug("APF: User Authentication failed");
288
obj.cirastate = CIRASTATE.FAILED;
289
return 14;
290
}
291
case APFProtocol.KEEPALIVE_REQUEST: {
297
- Debug("APF: Keep Alive Request with cookie: " + ReadInt(data, 1));
292
+ //Debug("APF: Keep Alive Request with cookie: " + ReadInt(data, 1));
293
SendKeepAliveReply(socket.ws, ReadInt(data, 1));
294
return 5;
295
}
296
case APFProtocol.KEEPALIVE_REPLY: {
302
- Debug("APF: Keep Alive Reply with cookie: " + ReadInt(data, 1));
297
+ //Debug("APF: Keep Alive Reply with cookie: " + ReadInt(data, 1));
298
return 5;
299
}
300
// Channel management
301
case APFProtocol.CHANNEL_OPEN: {
302
// Parse CHANNEL OPEN request
303
var p_res = parseChannelOpen(data);
309
- Debug("APF: CHANNEL_OPEN request: " + JSON.stringify(p_res));
304
+ //Debug("APF: CHANNEL_OPEN request: " + JSON.stringify(p_res));
305
// Check if target port is in pfwd_ports
306
if (pfwd_ports.indexOf(p_res.target_port) >= 0) {
307
// Connect socket to that port
@@ -323,24 +318,24 @@ function CreateAPFClient(parent, args) {
318
chan.on('data', function (ddata) {
319
// Relay data to fordwardclient
320
// TODO: Implement flow control
326
- SendChannelData(socket.ws, p_res.sender_chan, ddata.length, ddata);
321
+ SendChannelData(socket.ws, p_res.sender_chan, ddata);
322
});
323
324
chan.on('error', function (e) {
330
- Debug("Downlink connection error: " + e);
325
+ //Debug("Downlink connection error: " + e);
326
});
327
328
chan.on('end', function () {
329
var chan = obj.downlinks[p_res.sender_chan];
330
if (chan != null) {
331
try {
337
- Debug("Socket ends.");
332
+ //Debug("Socket ends.");
333
SendChannelClose(socket.ws, p_res.sender_chan);
334
chan.xclosed = 1;
335
// Add some delay before removing... otherwise race condition
336
setTimeout(function () { delete obj.downlinks[p_res.sender_chan]; }, 100);
337
} catch (e) {
343
- Debug("Downlink connection exception: " + e);
338
+ //Debug("Downlink connection exception: " + e);
339
}
340
}
341
});
@@ -353,12 +348,12 @@ function CreateAPFClient(parent, args) {
348
return p_res.len;
349
}
350
case APFProtocol.CHANNEL_OPEN_CONFIRMATION: {
356
- Debug("APF: CHANNEL_OPEN_CONFIRMATION");
351
+ //Debug("APF: CHANNEL_OPEN_CONFIRMATION");
352
return 17;
353
}
354
case APFProtocol.CHANNEL_CLOSE: {
355
var rcpt_chan = ReadInt(data, 1);
361
- Debug("APF: CHANNEL_CLOSE: " + rcpt_chan);
356
+ //Debug("APF: CHANNEL_CLOSE: " + rcpt_chan);
357
var chan = obj.downlinks[rcpt_chan];
358
if ((chan != null) && (chan.xclosed !== 1)) {
359
SendChannelClose(socket.ws, rcpt_chan);
@@ -368,7 +363,7 @@ function CreateAPFClient(parent, args) {
363
return 5;
364
}
365
case APFProtocol.CHANNEL_DATA: {
371
- Debug("APF: CHANNEL_DATA: " + JSON.stringify(rstr2hex(data)));
366
+ //Debug("APF: CHANNEL_DATA: " + JSON.stringify(rstr2hex(data)));
367
var rcpt_chan = ReadInt(data, 1);
368
var chan_data_len = ReadInt(data, 5);
369
var chan_data = data.substring(9, 9 + chan_data_len);
@@ -376,23 +371,23 @@ function CreateAPFClient(parent, args) {
371
if (chan != null) {
372
chan.curInWindow += chan_data_len;
373
try {
379
- chan.write(chan_data, 'binary', function () {
380
- Debug("Write completed.");
374
+ chan.write(Buffer.from(chan_data, 'binary'), function () {
375
+ //Debug("Write completed.");
376
// If the incoming window is over half used, send an adjust.
377
if (this.curInWindow > (this.maxInWindow / 2)) { SendChannelWindowAdjust(socket.ws, rcpt_chan, this.curInWindow); this.curInWindow = 0; }
378
});
379
} catch (e) {
385
- Debug("Cannot forward data to downlink socket.");
380
+ //Debug("Cannot forward data to downlink socket.");
381
}
382
}
383
return 9 + chan_data_len;
384
}
385
case APFProtocol.CHANNEL_WINDOW_ADJUST: {
391
- Debug("APF: CHANNEL_WINDOW_ADJUST ");
386
+ //Debug("APF: CHANNEL_WINDOW_ADJUST ");
387
return 9;
388
}
389
default: {
395
- Debug("CMD: " + cmd + " is not implemented.");
390
+ //Debug("CMD: " + cmd + " is not implemented.");
391
obj.cirastate = CIRASTATE.FAILED;
392
return 0;
393
}
@@ -416,35 +411,28 @@ function CreateAPFClient(parent, args) {
411
}
412
413
function SendChannelOpenFailure(socket, chan_data) {
419
- var data = String.fromCharCode(APFProtocol.CHANNEL_OPEN_FAILURE) + IntToStr(chan_data.sender_chan)
420
- + IntToStr(2) + IntToStr(0) + IntToStr(0);
421
- socket.write(data);
422
- Debug("APF: Send ChannelOpenFailure");
414
+ socket.write(String.fromCharCode(APFProtocol.CHANNEL_OPEN_FAILURE) + IntToStr(chan_data.sender_chan) + IntToStr(2) + IntToStr(0) + IntToStr(0));
415
+ //Debug("APF: Send ChannelOpenFailure");
416
}
417
418
function SendChannelOpenConfirm(socket, chan_data) {
426
- var data = String.fromCharCode(APFProtocol.CHANNEL_OPEN_CONFIRMATION) + IntToStr(chan_data.sender_chan)
427
- + IntToStr(chan_data.sender_chan) + IntToStr(chan_data.window_size) + IntToStr(0xFFFFFFFF);
428
- socket.write(data);
429
- Debug("APF: Send ChannelOpenConfirmation");
419
+ socket.write(String.fromCharCode(APFProtocol.CHANNEL_OPEN_CONFIRMATION) + IntToStr(chan_data.sender_chan) + IntToStr(chan_data.sender_chan) + IntToStr(chan_data.window_size) + IntToStr(0xFFFFFFFF));
420
+ //Debug("APF: Send ChannelOpenConfirmation");
421
}
422
423
function SendChannelWindowAdjust(socket, chan, size) {
433
- var data = String.fromCharCode(APFProtocol.CHANNEL_WINDOW_ADJUST) + IntToStr(chan) + IntToStr(size);
434
- socket.write(data);
435
- Debug("APF: Send ChannelWindowAdjust: " + rstr2hex(data));
424
+ socket.write(String.fromCharCode(APFProtocol.CHANNEL_WINDOW_ADJUST) + IntToStr(chan) + IntToStr(size));
425
+ //Debug("APF: Send ChannelWindowAdjust: " + rstr2hex(data));
426
}
427
438
- function SendChannelData(socket, chan, len, data) {
439
- var buf = String.fromCharCode(APFProtocol.CHANNEL_DATA) + IntToStr(chan) + IntToStr(len) + data;
440
- socket.write(buf);
441
- Debug("APF: Send ChannelData: " + rstr2hex(buf));
428
+ function SendChannelData(socket, chan, data) {
429
+ socket.write(Buffer.concat([Buffer.from(String.fromCharCode(APFProtocol.CHANNEL_DATA) + IntToStr(chan) + IntToStr(data.length), 'binary'), data]));
430
+ //Debug("APF: Send ChannelData: " + rstr2hex(buf));
431
}
432
433
function SendChannelClose(socket, chan) {
445
- var buf = String.fromCharCode(APFProtocol.CHANNEL_CLOSE) + IntToStr(chan);
446
- socket.write(buf);
447
- Debug("APF: Send ChannelClose ");
434
+ socket.write(String.fromCharCode(APFProtocol.CHANNEL_CLOSE) + IntToStr(chan));
435
+ //Debug("APF: Send ChannelClose ");
436
}
437
438
obj.connect = function () {
amt/amt-wsman-comm.js
+81
-10
@@ -51,6 +51,16 @@ var CreateWsmanComm = function (host, port, user, pass, tls, tlsoptions, ciraCon
51
// Private method
52
obj.Debug = function (msg) { console.log(msg); }
53
54
+ // Used to add TLS to a steam
55
+ function SerialTunnel(options) {
56
+ var obj = new require('stream').Duplex(options);
57
+ obj.forwardwrite = null;
58
+ obj.updateBuffer = function (chunk) { this.push(chunk); };
59
+ obj._write = function (chunk, encoding, callback) { if (obj.forwardwrite != null) { obj.forwardwrite(chunk); } else { console.err("Failed to fwd _write."); } if (callback) callback(); }; // Pass data written to forward
60
+ obj._read = function (size) { }; // Push nothing, anything to read should be pushed from updateBuffer()
61
+ return obj;
62
+ }
63
+
64
// Private method
65
// pri = priority, if set to 1, the call is high priority and put on top of the stack.
66
obj.PerformAjax = function (postdata, callback, tag, pri, url, action) {
@@ -167,11 +177,12 @@ var CreateWsmanComm = function (host, port, user, pass, tls, tlsoptions, ciraCon
177
obj.kerberosDone = 0;
178
179
if (obj.ciraConnection != null) {
170
- // Setup a new channel using the CIRA/Relay/LMS connection
171
- obj.socket = obj.ciraConnection.SetupChannel(obj.port);
172
- if (obj.socket == null) {
173
- try { obj.xxOnSocketClosed(); } catch (e) { }
174
- } else {
180
+ if (obj.xtls != 1) {
181
+ // Setup a new channel using the CIRA/Relay/LMS connection
182
+ obj.socket = obj.ciraConnection.SetupChannel(obj.port);
183
+ if (obj.socket == null) { obj.xxOnSocketClosed(); return; }
184
+
185
+ // Connect without TLS
186
obj.socket.onData = function (ccon, data) { obj.xxOnSocketData(data); }
187
obj.socket.onStateChange = function (ccon, state) {
188
if (state == 0) {
@@ -181,12 +192,57 @@ var CreateWsmanComm = function (host, port, user, pass, tls, tlsoptions, ciraCon
192
obj.socketHeader = null;
193
obj.socketData = '';
194
obj.socketState = 0;
184
- try { obj.xxOnSocketClosed(); } catch (e) { }
195
+ obj.xxOnSocketClosed();
196
} else if (state == 2) {
197
// Channel open success
198
obj.xxOnSocketConnected();
199
}
200
}
201
+ } else {
202
+ // Setup a new channel using the CIRA/Relay/LMS connection
203
+ obj.cirasocket = obj.ciraConnection.SetupChannel(obj.port);
204
+ if (obj.cirasocket == null) { obj.xxOnSocketClosed(); return; }
205
+
206
+ // Connect with TLS
207
+ var ser = new SerialTunnel();
208
+
209
+ // let's chain up the TLSSocket <-> SerialTunnel <-> CIRA APF (chnl)
210
+ // Anything that needs to be forwarded by SerialTunnel will be encapsulated by chnl write
211
+ ser.forwardwrite = function (msg) { obj.cirasocket.write(msg); }; // TLS ---> CIRA
212
+
213
+ // When APF tunnel return something, update SerialTunnel buffer
214
+ obj.cirasocket.onData = function (ciraconn, data) { if (data.length > 0) { try { ser.updateBuffer(Buffer.from(data, 'binary')); } catch (e) { } } }; // CIRA ---> TLS
215
+
216
+ // Handle CIRA tunnel state change
217
+ obj.cirasocket.onStateChange = function (ciraconn, state) {
218
+ if (state == 0) { obj.xxOnSocketClosed(); }
219
+ if (state == 2) {
220
+ // TLSSocket to encapsulate TLS communication, which then tunneled via SerialTunnel an then wrapped through CIRA APF
221
+ var options = { socket: ser, ciphers: 'RSA+AES:!aNULL:!MD5:!DSS', secureOptions: obj.constants.SSL_OP_NO_SSLv2 | obj.constants.SSL_OP_NO_SSLv3 | obj.constants.SSL_OP_NO_COMPRESSION | obj.constants.SSL_OP_CIPHER_SERVER_PREFERENCE, rejectUnauthorized: false };
222
+ if (obj.tls1only == 1) { tlsoptions.secureProtocol = 'TLSv1_method'; }
223
+ if (obj.xtlsoptions) {
224
+ if (obj.xtlsoptions.ca) options.ca = obj.xtlsoptions.ca;
225
+ if (obj.xtlsoptions.cert) options.cert = obj.xtlsoptions.cert;
226
+ if (obj.xtlsoptions.key) options.key = obj.xtlsoptions.key;
227
+ }
228
+
229
+ //obj.socket = new TLSSocket(ser, options);
230
+ obj.socket = obj.tls.connect(obj.port, obj.host, options, obj.xxOnSocketConnected);
231
+ obj.socket.setEncoding('binary');
232
+ obj.socket.setTimeout(6000); // Set socket idle timeout
233
+ obj.socket.on('error', function (err) { console.log("CIRA TLS Connection Error ", err); obj.xxOnSocketClosed(); });
234
+ //obj.socket.on('error', function (e) { if (e.message && e.message.indexOf('sslv3 alert bad record mac') >= 0) { obj.xtlsMethod = 1 - obj.xtlsMethod; } });
235
+ obj.socket.on('close', obj.xxOnSocketClosed);
236
+ obj.socket.on('timeout', obj.xxOnSocketTimeout);
237
+
238
+ // Decrypted tunnel from TLS communcation to be forwarded to websocket
239
+ obj.socket.on('data', function (data) { try { obj.xxOnSocketData(data.toString('binary')); } catch (e) { } }); // AMT/TLS ---> WS
240
+
241
+ // If TLS is on, forward it through TLSSocket
242
+ obj.forwardclient = obj.socket;
243
+ obj.forwardclient.xtls = 1;
244
+ }
245
+ };
246
}
247
} else {
248
// Direct connection
@@ -229,7 +285,7 @@ var CreateWsmanComm = function (host, port, user, pass, tls, tlsoptions, ciraCon
285
obj.xxOnSocketConnected = function () {
286
if (obj.socket == null) return;
287
// check TLS certificate for webrelay and direct only
232
- if ((obj.ciraConnection == null) && (obj.xtls == 1)) {
288
+ if (obj.xtls == 1) {
289
obj.xtlsCertificate = obj.socket.getPeerCertificate();
290
291
// ###BEGIN###{Certificates}
@@ -365,8 +421,15 @@ var CreateWsmanComm = function (host, port, user, pass, tls, tlsoptions, ciraCon
421
//obj.Debug("xxOnSocketClosed");
422
obj.socketState = 0;
423
if (obj.socket != null) {
368
- if (obj.ciraConnection == null) { obj.socket.destroy(); } else { obj.socket.close(); }
424
+ try {
425
+ if (obj.ciraConnection == null) {
426
+ obj.socket.destroy();
427
+ } else {
428
+ if (obj.cirasocket != null) { obj.cirasocket.close(); } else { obj.socket.close(); }
429
+ }
430
+ } catch (ex) { }
431
obj.socket = null;
432
+ obj.cirasocket = null;
433
}
434
if (obj.pendingAjaxCall.length > 0) {
435
var r = obj.pendingAjaxCall.shift(), retry = r[5];
@@ -376,14 +439,22 @@ var CreateWsmanComm = function (host, port, user, pass, tls, tlsoptions, ciraCon
439
440
obj.xxOnSocketTimeout = function () {
441
if (obj.socket != null) {
379
- if (obj.ciraConnection == null) { obj.socket.destroy(); } else { obj.socket.close(); }
442
+ try {
443
+ if (obj.ciraConnection == null) {
444
+ obj.socket.destroy();
445
+ } else {
446
+ if (obj.cirasocket != null) { obj.cirasocket.close(); } else { obj.socket.close(); }
447
+ }
448
+ } catch (ex) { }
449
obj.socket = null;
450
+ obj.cirasocket = null;
451
}
452
}
453
454
// NODE.js specific private method
455
obj.xxSend = function (x) {
386
- if (obj.socketState == 2) { obj.socket.write(Buffer.from(x, "binary")); }
456
+ //console.log('xxSend', x);
457
+ if (obj.socketState == 2) { obj.socket.write(Buffer.from(x, 'binary')); }
458
}
459
460
// Cancel all pending queries with given status
amtmanager.js
+3
-2
@@ -49,6 +49,9 @@ module.exports.CreateAmtManager = function(parent) {
49
// If the connection type we are using is not longer valid, remove our managed device.
50
if ((dev != null) && (dev.conntype != null) && ((dev.conntype & event.conn) == 0)) { removeDevice(event.nodeid); dev = null; }
51
52
+ // Debug line, to only manage CIRA/Relay connections
53
+ //if ((event.conn & 10) == 0) return;
54
+
55
// Create or update a managed device
56
if ((event.conn & 14) != 0) { // connectType: Bitmask, 1 = MeshAgent, 2 = Intel AMT CIRA, 4 = Intel AMT local, 8 = Intel AMT Relay, 16 = MQTT
57
// We have an OOB connection to Intel AMT, update our information
@@ -224,7 +227,6 @@ module.exports.CreateAmtManager = function(parent) {
227
// Connect now
228
//console.log('CIRA-Connect', (dotls == 1)?"TLS":"NoTLS", dev.name, dev.host, user, pass);
229
var comm;
227
- dotls = 0; // TODO: We don't support TLS with CIRA/Relay/LMS connections yet. Remove this when we do.
230
if (dotls == 1) {
231
comm = CreateWsmanComm(dev.nodeid, 16993, user, pass, 1, null, ciraconn); // Perform TLS
232
comm.xtlsFingerprint = 0; // Perform no certificate checking
@@ -253,7 +255,6 @@ module.exports.CreateAmtManager = function(parent) {
255
256
// Connect now
257
var comm;
256
- dev.tlsfail = true; // TODO: We don't support TLS with CIRA/Relay/LMS connections yet. Remove this when we do.
258
if (dev.tlsfail !== true) {
259
//console.log('Relay-Connect', "TLS", dev.name, dev.host, user, pass);
260
comm = CreateWsmanComm(dev.nodeid, 16993, user, pass, 1, null, ciraconn); // Perform TLS
mpsserver.js
+13
-11
@@ -854,7 +854,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
854
var cirachannel = socket.tag.channels[RecipientChannel];
855
if (cirachannel == null) { console.log("MPS Error in CHANNEL_DATA: Unable to find channelid " + RecipientChannel); return 9 + LengthOfData; }
856
cirachannel.amtpendingcredits += LengthOfData;
857
- if (cirachannel.onData) cirachannel.onData(cirachannel, data.substring(9, 9 + LengthOfData));
857
+ if (cirachannel.onData) { cirachannel.onData(cirachannel, Buffer.from(data.substring(9, 9 + LengthOfData), 'binary')); }
858
if (cirachannel.amtpendingcredits > (cirachannel.ciraWindow / 2)) {
859
SendChannelWindowAdjust(cirachannel.socket, cirachannel.amtchannelid, cirachannel.amtpendingcredits); // Adjust the buffer window
860
cirachannel.amtpendingcredits = 0;
@@ -960,8 +960,8 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
960
}
961
962
function SendChannelData(socket, channelid, data) {
963
- parent.debug('mpscmddata', '<-- CHANNEL_DATA', channelid, data.length);
964
- Write(socket, String.fromCharCode(APFProtocol.CHANNEL_DATA) + common.IntToStr(channelid) + common.IntToStr(data.length) + data);
963
+ parent.debug('mpscmddata', '<-- CHANNEL_DATA', channelid, data.length, Buffer.from(data, 'binary').toString('hex'));
964
+ Write(socket, String.fromCharCode(APFProtocol.CHANNEL_DATA) + common.IntToStr(channelid) + common.IntToStr(data.length) + ((typeof data == 'string') ? data : data.toString('binary')));
965
}
966
967
function SendChannelWindowAdjust(socket, channelid, bytestoadd) {
@@ -987,14 +987,16 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
987
}
988
989
function Write(socket, data) {
990
- if (args.mpsdebug) {
991
- // Print out sent bytes
992
- var buf = Buffer.from(data, 'binary');
993
- console.log('MPS <-- (' + buf.length + '):' + buf.toString('hex'));
994
- if (socket.websocket == 1) { socket.send(buf); } else { socket.write(buf); }
995
- } else {
996
- if (socket.websocket == 1) { socket.send(Buffer.from(data, 'binary')); } else { socket.write(Buffer.from(data, 'binary')); }
997
- }
990
+ try {
991
+ if (args.mpsdebug) {
992
+ // Print out sent bytes
993
+ var buf = Buffer.from(data, 'binary');
994
+ console.log('MPS <-- (' + buf.length + '):' + buf.toString('hex'));
995
+ if (socket.websocket == 1) { socket.send(buf); } else { socket.write(buf); }
996
+ } else {
997
+ if (socket.websocket == 1) { socket.send(Buffer.from(data, 'binary')); } else { socket.write(Buffer.from(data, 'binary')); }
998
+ }
999
+ } catch (ex) { }
1000
}
1001
1002
// Returns a CIRA/Relay/LMS connection to a nodeid, use the best possible connection, CIRA first, Relay second, LMS third.
public/scripts/amt-wsman-0.2.0-min.js
+1
-1
@@ -1 +1 @@
1
-var WsmanStackCreateService=function(e,s,r,a,o,t){var p={};function l(e){if(!e)return"";var s=" ";for(var r in e)e.hasOwnProperty(r)&&0===r.indexOf("@")&&(s+=r.substring(1)+'="'+e[r]+'" ');return s}function w(e){if(!e)return"";if("string"==typeof e)return e;if(e.InstanceID)return'<w:SelectorSet><w:Selector Name="InstanceID">'+e.InstanceID+"</w:Selector></w:SelectorSet>";var s="<w:SelectorSet>";for(var r in e)if(e.hasOwnProperty(r)){if(s+='<w:Selector Name="'+r+'">',e[r].ReferenceParameters){s+="<a:EndpointReference>",s+="<a:Address>"+e[r].Address+"</a:Address><a:ReferenceParameters><w:ResourceURI>"+e[r].ReferenceParameters.ResourceURI+"</w:ResourceURI><w:SelectorSet>";var a=e[r].ReferenceParameters.SelectorSet.Selector;if(Array.isArray(a))for(var o=0;o<a.length;o++)s+="<w:Selector"+l(a[o])+">"+a[o].Value+"</w:Selector>";else s+="<w:Selector"+l(a)+">"+a.Value+"</w:Selector>";s+="</w:SelectorSet></a:ReferenceParameters></a:EndpointReference>"}else s+=e[r];s+="</w:Selector>"}return s+="</w:SelectorSet>"}return p.NextMessageId=1,p.Address="/wsman",p.comm=CreateWsmanComm(e,s,r,a,o,t),p.PerformAjax=function(e,o,s,r,a){null==a&&(a=""),p.comm.PerformAjax('<?xml version=\"1.0\" encoding=\"utf-8\"?><Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns="http://www.w3.org/2003/05/soap-envelope" '+a+"><Header><a:Action>"+e,function(e,s,r){if(200==s){var a=p.ParseWsman(e);a&&null!=a?o(p,a.Header.ResourceURI,a,200,r):o(p,null,{Header:{HttpError:s}},601,r)}else o(p,null,{Header:{HttpError:s}},s,r)},s,r)},p.CancelAllQueries=function(e){p.comm.CancelAllQueries(e)},p.GetNameFromUrl=function(e){var s=e.lastIndexOf("/");return-1==s?e:e.substring(s+1)},p.ExecSubscribe=function(e,s,r,a,o,t,n,l,d,c){var m="",i="";null!=d&&null!=c&&(m="<t:IssuedTokens><t:RequestSecurityTokenResponse><t:TokenType>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken</t:TokenType><t:RequestedSecurityToken><se:UsernameToken><se:Username>"+d+'</se:Username><se:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd#PasswordText">'+c+"</se:Password></se:UsernameToken></t:RequestedSecurityToken></t:RequestSecurityTokenResponse></t:IssuedTokens>",i='<Auth Profile="http://schemas.xmlsoap.org/ws/2004/08/eventing/DeliveryModes/secprofile/http/digest"/>'),l=null!=l&&null!=l?"<a:ReferenceParameters>"+l+"</a:ReferenceParameters>":"";var u="http://schemas.xmlsoap.org/ws/2004/08/eventing/Subscribe</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo>"+w(n)+m+'</Header><Body><e:Subscribe><e:Delivery Mode="http://schemas.dmtf.org/wbem/wsman/1/wsman/'+s+'"><e:NotifyTo><a:Address>'+r+"</a:Address></e:NotifyTo>"+i+"</e:Delivery><e:Expires>PT0.000000S</e:Expires></e:Subscribe>";p.PerformAjax(u+"</Body></Envelope>",a,o,t,'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing" xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust" xmlns:se="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:m="http://x.com"')},p.ExecUnSubscribe=function(e,s,r,a,o){var t="http://schemas.xmlsoap.org/ws/2004/08/eventing/Unsubscribe</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo>"+w(o)+"</Header><Body><e:Unsubscribe/>";p.PerformAjax(t+"</Body></Envelope>",s,r,a,'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing"')},p.ExecPut=function(e,s,r,a,o,t){var n="http://schemas.xmlsoap.org/ws/2004/09/transfer/Put</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60.000S</w:OperationTimeout>"+w(t)+"</Header><Body>"+function(e,s){if(!e||null==s)return"";var r=p.GetNameFromUrl(e),a="<r:"+r+' xmlns:r="'+e+'">';for(var o in s)if(s.hasOwnProperty(o)&&0!==o.indexOf("__")&&0!==o.indexOf("@")&&void 0!==s[o]&&null!==s[o]&&"function"!=typeof s[o])if("object"==typeof s[o]&&s[o].ReferenceParameters){a+="<r:"+o+"><a:Address>"+s[o].Address+"</a:Address><a:ReferenceParameters><w:ResourceURI>"+s[o].ReferenceParameters.ResourceURI+"</w:ResourceURI><w:SelectorSet>";var t=s[o].ReferenceParameters.SelectorSet.Selector;if(Array.isArray(t))for(var n=0;n<t.length;n++)a+="<w:Selector"+l(t[n])+">"+t[n].Value+"</w:Selector>";else a+="<w:Selector"+l(t)+">"+t.Value+"</w:Selector>";a+="</w:SelectorSet></a:ReferenceParameters></r:"+o+">"}else if(Array.isArray(s[o]))for(n=0;n<s[o].length;n++)a+="<r:"+o+">"+s[o][n].toString()+"</r:"+o+">";else a+="<r:"+o+">"+s[o].toString()+"</r:"+o+">";return a+="</r:"+r+">"}(e,s);p.PerformAjax(n+"</Body></Envelope>",r,a,o)},p.ExecCreate=function(e,s,r,a,o,t){var n=p.GetNameFromUrl(e),l="http://schemas.xmlsoap.org/ws/2004/09/transfer/Create</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>"+w(t)+"</Header><Body><g:"+n+' xmlns:g="'+e+'">';for(var d in s)l+="<g:"+d+">"+s[d]+"</g:"+d+">";p.PerformAjax(l+"</g:"+n+"></Body></Envelope>",r,a,o)},p.ExecCreateXml=function(e,s,r,a,o){var t=p.GetNameFromUrl(e);p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Create</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60.000S</w:OperationTimeout></Header><Body><r:"+t+' xmlns:r="'+e+'">'+s+"</r:"+t+"></Body></Envelope>",r,a,o)},p.ExecDelete=function(e,s,r,a,o){var t="http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>"+w(s)+"</Header><Body /></Envelope>";p.PerformAjax(t,r,a,o)},p.ExecGet=function(e,s,r,a){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Get</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body /></Envelope>",s,r,a)},p.ExecMethod=function(e,s,r,a,o,t,n){var l="";for(var d in r)if(null!=r[d])if(Array.isArray(r[d]))for(var c in r[d])l+="<r:"+d+">"+r[d][c]+"</r:"+d+">";else l+="<r:"+d+">"+r[d]+"</r:"+d+">";p.ExecMethodXml(e,s,l,a,o,t,n)},p.ExecMethodXml=function(e,s,r,a,o,t,n){p.PerformAjax(e+"/"+s+"</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>"+w(n)+"</Header><Body><r:"+s+'_INPUT xmlns:r="'+e+'">'+r+"</r:"+s+"_INPUT></Body></Envelope>",a,o,t)},p.ExecEnum=function(e,s,r,a){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Enumerate</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++'</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body><Enumerate xmlns="http://schemas.xmlsoap.org/ws/2004/09/enumeration" /></Body></Envelope>',s,r,a)},p.ExecPull=function(e,s,r,a,o){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Pull</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++'</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body><Pull xmlns="http://schemas.xmlsoap.org/ws/2004/09/enumeration"><EnumerationContext>'+s+"</EnumerationContext><MaxElements>999</MaxElements><MaxCharacters>99999</MaxCharacters></Pull></Body></Envelope>",r,a,o)},p.ParseWsman=function(s){try{s.childNodes||(s=function(e){{if(window.DOMParser)return(new DOMParser).parseFromString(e,"text/xml");var s=new ActiveXObject("Microsoft.XMLDOM");return s.async=!1,s.loadXML(e),s}}(s));var e,r={Header:{}},a=s.getElementsByTagName("Header")[0];if(!(a=a||s.getElementsByTagName("a:Header")[0]))return null;for(var o=0;o<a.childNodes.length;o++){var t=a.childNodes[o];r.Header[t.localName]=t.textContent}var n=s.getElementsByTagName("Body")[0];if(!(n=n||s.getElementsByTagName("a:Body")[0]))return null;if(0<n.childNodes.length){var l=(e=n.childNodes[0].localName).indexOf("_OUTPUT");-1!=l&&l==e.length-7&&(e=e.substring(0,e.length-7)),r.Header.Method=e,r.Body=function e(s){var r,a={};for(var o=0;o<s.childNodes.length;o++){var t=s.childNodes[o];"true"==(r=0==t.childElementCount?t.textContent:e(t))&&(r=!0),"false"==r&&(r=!1);var n=r;if(0<t.attributes.length){n={Value:r};for(var l=0;l<t.attributes.length;l++)n["@"+t.attributes[l].name]=t.attributes[l].value}a[t.localName]instanceof Array?a[t.localName].push(n):null==a[t.localName]?a[t.localName]=n:a[t.localName]=[a[t.localName],n]}return a}(n.childNodes[0])}return r}catch(e){return console.log("Unable to parse XML: "+s),null}},p}
\ No newline at end of file
1
+var WsmanStackCreateService=function(e,s,r,a,o,t){var p={};function l(e){if(!e)return"";var s=" ";for(var r in e)e.hasOwnProperty(r)&&0===r.indexOf("@")&&(s+=r.substring(1)+'="'+e[r]+'" ');return s}function w(e){if(!e)return"";if("string"==typeof e)return e;if(e.InstanceID)return'<w:SelectorSet><w:Selector Name="InstanceID">'+e.InstanceID+"</w:Selector></w:SelectorSet>";var s="<w:SelectorSet>";for(var r in e)if(e.hasOwnProperty(r)){if(s+='<w:Selector Name="'+r+'">',e[r].ReferenceParameters){s+="<a:EndpointReference>",s+="<a:Address>"+e[r].Address+"</a:Address><a:ReferenceParameters><w:ResourceURI>"+e[r].ReferenceParameters.ResourceURI+"</w:ResourceURI><w:SelectorSet>";var a=e[r].ReferenceParameters.SelectorSet.Selector;if(Array.isArray(a))for(var o=0;o<a.length;o++)s+="<w:Selector"+l(a[o])+">"+a[o].Value+"</w:Selector>";else s+="<w:Selector"+l(a)+">"+a.Value+"</w:Selector>";s+="</w:SelectorSet></a:ReferenceParameters></a:EndpointReference>"}else s+=e[r];s+="</w:Selector>"}return s+="</w:SelectorSet>"}return p.NextMessageId=1,p.Address="/wsman",p.comm=CreateWsmanComm(e,s,r,a,o,t),p.PerformAjax=function(e,o,s,r,a){null==a&&(a=""),p.comm.PerformAjax('<?xml version=\"1.0\" encoding=\"utf-8\"?><Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns="http://www.w3.org/2003/05/soap-envelope" '+a+"><Header><a:Action>"+e,function(e,s,r){if(200==s){var a=p.ParseWsman(e);a&&null!=a?o(p,a.Header.ResourceURI,a,200,r):o(p,null,{Header:{HttpError:s}},601,r)}else o(p,null,{Header:{HttpError:s}},s,r)},s,r)},p.CancelAllQueries=function(e){p.comm.CancelAllQueries(e)},p.GetNameFromUrl=function(e){var s=e.lastIndexOf("/");return-1==s?e:e.substring(s+1)},p.ExecSubscribe=function(e,s,r,a,o,t,n,l,c,d){var m="",i="";null!=c&&null!=d&&(m="<t:IssuedTokens><t:RequestSecurityTokenResponse><t:TokenType>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken</t:TokenType><t:RequestedSecurityToken><se:UsernameToken><se:Username>"+c+'</se:Username><se:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd#PasswordText">'+d+"</se:Password></se:UsernameToken></t:RequestedSecurityToken></t:RequestSecurityTokenResponse></t:IssuedTokens>",i='<Auth Profile="http://schemas.xmlsoap.org/ws/2004/08/eventing/DeliveryModes/secprofile/http/digest"/>'),l=null!=l&&null!=l?"<a:ReferenceParameters>"+l+"</a:ReferenceParameters>":"";var u="http://schemas.xmlsoap.org/ws/2004/08/eventing/Subscribe</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo>"+w(n)+m+'</Header><Body><e:Subscribe><e:Delivery Mode="http://schemas.dmtf.org/wbem/wsman/1/wsman/'+s+'"><e:NotifyTo><a:Address>'+r+"</a:Address></e:NotifyTo>"+i+"</e:Delivery><e:Expires>PT0.000000S</e:Expires></e:Subscribe>";p.PerformAjax(u+"</Body></Envelope>",a,o,t,'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing" xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust" xmlns:se="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:m="http://x.com"')},p.ExecUnSubscribe=function(e,s,r,a,o){var t="http://schemas.xmlsoap.org/ws/2004/08/eventing/Unsubscribe</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo>"+w(o)+"</Header><Body><e:Unsubscribe/>";p.PerformAjax(t+"</Body></Envelope>",s,r,a,'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing"')},p.ExecPut=function(e,s,r,a,o,t){var n="http://schemas.xmlsoap.org/ws/2004/09/transfer/Put</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60.000S</w:OperationTimeout>"+w(t)+"</Header><Body>"+function(e,s){if(!e||null==s)return"";var r=p.GetNameFromUrl(e),a="<r:"+r+' xmlns:r="'+e+'">';for(var o in s)if(s.hasOwnProperty(o)&&0!==o.indexOf("__")&&0!==o.indexOf("@")&&void 0!==s[o]&&null!==s[o]&&"function"!=typeof s[o])if("object"==typeof s[o]&&s[o].ReferenceParameters){a+="<r:"+o+"><a:Address>"+s[o].Address+"</a:Address><a:ReferenceParameters><w:ResourceURI>"+s[o].ReferenceParameters.ResourceURI+"</w:ResourceURI><w:SelectorSet>";var t=s[o].ReferenceParameters.SelectorSet.Selector;if(Array.isArray(t))for(var n=0;n<t.length;n++)a+="<w:Selector"+l(t[n])+">"+t[n].Value+"</w:Selector>";else a+="<w:Selector"+l(t)+">"+t.Value+"</w:Selector>";a+="</w:SelectorSet></a:ReferenceParameters></r:"+o+">"}else if(Array.isArray(s[o]))for(n=0;n<s[o].length;n++)a+="<r:"+o+">"+s[o][n].toString()+"</r:"+o+">";else a+="<r:"+o+">"+s[o].toString()+"</r:"+o+">";return a+="</r:"+r+">"}(e,s);p.PerformAjax(n+"</Body></Envelope>",r,a,o)},p.ExecCreate=function(e,s,r,a,o,t){var n=p.GetNameFromUrl(e),l="http://schemas.xmlsoap.org/ws/2004/09/transfer/Create</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>"+w(t)+"</Header><Body><g:"+n+' xmlns:g="'+e+'">';for(var c in s)l+="<g:"+c+">"+s[c]+"</g:"+c+">";p.PerformAjax(l+"</g:"+n+"></Body></Envelope>",r,a,o)},p.ExecCreateXml=function(e,s,r,a,o){var t=p.GetNameFromUrl(e);p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Create</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60.000S</w:OperationTimeout></Header><Body><r:"+t+' xmlns:r="'+e+'">'+s+"</r:"+t+"></Body></Envelope>",r,a,o)},p.ExecDelete=function(e,s,r,a,o){var t="http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>"+w(s)+"</Header><Body /></Envelope>";p.PerformAjax(t,r,a,o)},p.ExecGet=function(e,s,r,a){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Get</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body /></Envelope>",s,r,a)},p.ExecMethod=function(e,s,r,a,o,t,n){var l="";for(var c in r)if(null!=r[c])if(Array.isArray(r[c]))for(var d in r[c])l+="<r:"+c+">"+r[c][d]+"</r:"+c+">";else l+="<r:"+c+">"+r[c]+"</r:"+c+">";p.ExecMethodXml(e,s,l,a,o,t,n)},p.ExecMethodXml=function(e,s,r,a,o,t,n){p.PerformAjax(e+"/"+s+"</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>"+w(n)+"</Header><Body><r:"+s+'_INPUT xmlns:r="'+e+'">'+r+"</r:"+s+"_INPUT></Body></Envelope>",a,o,t)},p.ExecEnum=function(e,s,r,a){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Enumerate</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++'</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body><Enumerate xmlns="http://schemas.xmlsoap.org/ws/2004/09/enumeration" /></Body></Envelope>',s,r,a)},p.ExecPull=function(e,s,r,a,o){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Pull</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++'</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body><Pull xmlns="http://schemas.xmlsoap.org/ws/2004/09/enumeration"><EnumerationContext>'+s+"</EnumerationContext><MaxElements>999</MaxElements><MaxCharacters>99999</MaxCharacters></Pull></Body></Envelope>",r,a,o)},p.ParseWsman=function(s){try{s.childNodes||(s=function(e){{if(window.DOMParser)return(new DOMParser).parseFromString(e,"text/xml");var s=new ActiveXObject("Microsoft.XMLDOM");return s.async=!1,s.loadXML(e),s}}(s));var e,r={Header:{}},a=s.getElementsByTagName("Header")[0];if(!(a=a||s.getElementsByTagName("a:Header")[0]))return null;for(var o=0;o<a.childNodes.length;o++){var t=a.childNodes[o];r.Header[t.localName]=t.textContent}var n=s.getElementsByTagName("Body")[0];if(!(n=n||s.getElementsByTagName("a:Body")[0]))return null;if(0<n.childNodes.length){var l=(e=n.childNodes[0].localName).indexOf("_OUTPUT");-1!=l&&l==e.length-7&&(e=e.substring(0,e.length-7)),r.Header.Method=e,r.Body=function e(s){var r,a={};for(var o=0;o<s.childNodes.length;o++){var t=s.childNodes[o];"true"==(r=0==t.childElementCount?t.textContent:e(t))&&(r=!0),"false"==r&&(r=!1);var n=r;if(0<t.attributes.length){n={Value:r};for(var l=0;l<t.attributes.length;l++)n["@"+t.attributes[l].name]=t.attributes[l].value}a[t.localName]instanceof Array?a[t.localName].push(n):null==a[t.localName]?a[t.localName]=n:a[t.localName]=[a[t.localName],n]}return a}(n.childNodes[0])}return r}catch(e){return console.log("Unable to parse XML: "+s),null}},p}
\ No newline at end of file
views/default.handlebars
+1
@@ -4895,6 +4895,7 @@
4895
}
4896
}
4897
}
4898
+ putstore('_collapse', JSON.stringify(CollapsedGroups));
4899
mainUpdate(4);
4900
}
4901