Improved RDP error handling, #4022
Ylian Saint-Hilaire committed
May 20, 2022 at 21:52 UTC
783ff4be0c10f5cfeb29b610989c158aa934debc
6 files changed
+339
-309
apprelays.js
+2
-1
@@ -207,7 +207,8 @@ module.exports.CreateMstscRelay = function (parent, db, ws, req, args, domain) {
207
}).on('close', function () {
208
send(['rdp-close']);
209
}).on('error', function (err) {
210
- send(['rdp-error', err]);
210
+ if (typeof err == 'string') { send(['rdp-error', err]); }
211
+ if ((typeof err == 'object') && (err.err) && (err.code)) { send(['rdp-error', err.err, err.code]); }
212
}).connect('localhost', obj.tcpServerPort);
213
} catch (ex) {
214
console.log('startRdpException', ex);
public/scripts/agent-rdp-0.0.1.js
+23
-2
@@ -16,6 +16,7 @@ var CreateRDPDesktop = function (canvasid) {
16
obj.ScreenWidth = obj.width = 1280;
17
obj.ScreenHeight = obj.height = 1024;
18
obj.m.onClipboardChanged = null;
19
+ obj.onConsoleMessageChange = null;
20
21
function mouseButtonMap(button) {
22
// Swap mouse buttons if needed
@@ -79,8 +80,28 @@ var CreateRDPDesktop = function (canvasid) {
80
break;
81
}
82
case 'rdp-error': {
82
- var err = msg[1];
83
- console.log('[mstsc.js] error : ' + err.code + '(' + err.message + ')');
83
+ obj.consoleMessageTimeout = 5; // Seconds
84
+ obj.consoleMessage = msg[1];
85
+ delete obj.consoleMessageArgs;
86
+ if (msg.length > 2) { obj.consoleMessageArgs = [ msg[2] ]; }
87
+ switch (msg[1]) {
88
+ case 'NODE_RDP_PROTOCOL_X224_NEG_FAILURE':
89
+ if (msg[2] == 1) { obj.consoleMessageId = 9; } // "SSL required by server";
90
+ else if (msg[2] == 2) { obj.consoleMessageId = 10; } // "SSL not allowed by server";
91
+ else if (msg[2] == 3) { obj.consoleMessageId = 11; } // "SSL certificate not on server";
92
+ else if (msg[2] == 4) { obj.consoleMessageId = 12; } // "Inconsistent flags";
93
+ else if (msg[2] == 5) { obj.consoleMessageId = 13; } // "Hybrid required by server";
94
+ else if (msg[2] == 6) { obj.consoleMessageId = 14; } // "SSL with user auth required by server";
95
+ else obj.consoleMessageId = 7; // "Protocol negotiation failed";
96
+ break;
97
+ case 'NODE_RDP_PROTOCOL_X224_NLA_NOT_SUPPORTED':
98
+ obj.consoleMessageId = 8; // "NLA not supported";
99
+ break;
100
+ default:
101
+ obj.consoleMessageId = null;
102
+ break;
103
+ }
104
+ if (obj.onConsoleMessageChange) { obj.onConsoleMessageChange(); }
105
obj.Stop();
106
break;
107
}
rdp/protocol/pdu/cliprdr.js
+296
-296
@@ -12,14 +12,14 @@ const data = require('./data');
12
*/
13
class Cliprdr extends EventEmitter {
14
15
- constructor(transport) {
16
- super();
17
- this.transport = transport;
18
- // must be init via connect event
19
- this.userId = 0;
20
- this.serverCapabilities = [];
21
- this.clientCapabilities = [];
22
- }
15
+ constructor(transport) {
16
+ super();
17
+ this.transport = transport;
18
+ // must be init via connect event
19
+ this.userId = 0;
20
+ this.serverCapabilities = [];
21
+ this.clientCapabilities = [];
22
+ }
23
24
}
25
@@ -30,298 +30,298 @@ class Cliprdr extends EventEmitter {
30
*/
31
class Client extends Cliprdr {
32
33
- constructor(transport, fastPathTransport) {
34
-
35
- super(transport, fastPathTransport);
36
-
37
- this.transport.once('connect', (gccCore, userId, channelId) => {
38
- this.connect(gccCore, userId, channelId);
39
- }).on('close', () => {
40
- this.emit('close');
41
- }).on('error', (err) => {
42
- this.emit('error', err);
43
- });
44
-
45
- this.content = '';
46
-
47
- }
48
-
49
- /**
50
- * connect function
51
- * @param gccCore {type.Component(clientCoreData)}
52
- */
53
- connect(gccCore, userId, channelId) {
54
- this.gccCore = gccCore;
55
- this.userId = userId;
56
- this.channelId = channelId;
57
- this.transport.once('cliprdr', (s) => {
58
- this.recv(s);
59
- });
60
- }
61
-
62
-
63
- send(message) {
64
- this.transport.send('cliprdr', new type.Component([
65
- // Channel PDU Header
66
- new type.UInt32Le(message.size()),
67
- // CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST | CHANNEL_FLAG_SHOW_PROTOCOL
68
- new type.UInt32Le(0x13),
69
- message
70
- ]));
71
- };
72
-
73
- recv(s) {
74
- s.offset = 18;
75
- const pdu = data.clipPDU().read(s), type = data.ClipPDUMsgType;
76
-
77
- switch (pdu.obj.header.obj.msgType.value) {
78
- case type.CB_MONITOR_READY:
79
- this.recvMonitorReadyPDU(s);
80
- break;
81
- case type.CB_FORMAT_LIST:
82
- this.recvFormatListPDU(s);
83
- break;
84
- case type.CB_FORMAT_LIST_RESPONSE:
85
- this.recvFormatListResponsePDU(s);
86
- break;
87
- case type.CB_FORMAT_DATA_REQUEST:
88
- this.recvFormatDataRequestPDU(s);
89
- break;
90
- case type.CB_FORMAT_DATA_RESPONSE:
91
- this.recvFormatDataResponsePDU(s);
92
- break;
93
- case type.CB_TEMP_DIRECTORY:
94
- break;
95
- case type.CB_CLIP_CAPS:
96
- this.recvClipboardCapsPDU(s);
97
- break;
98
- case type.CB_FILECONTENTS_REQUEST:
33
+ constructor(transport, fastPathTransport) {
34
+
35
+ super(transport, fastPathTransport);
36
+
37
+ this.transport.once('connect', (gccCore, userId, channelId) => {
38
+ this.connect(gccCore, userId, channelId);
39
+ }).on('close', function () {
40
+ //this.emit('close');
41
+ }).on('error', function (err) {
42
+ //this.emit('error', err);
43
+ });
44
+
45
+ this.content = '';
46
+
47
+ }
48
+
49
+ /**
50
+ * connect function
51
+ * @param gccCore {type.Component(clientCoreData)}
52
+ */
53
+ connect(gccCore, userId, channelId) {
54
+ this.gccCore = gccCore;
55
+ this.userId = userId;
56
+ this.channelId = channelId;
57
+ this.transport.once('cliprdr', (s) => {
58
+ this.recv(s);
59
+ });
60
+ }
61
+
62
+
63
+ send(message) {
64
+ this.transport.send('cliprdr', new type.Component([
65
+ // Channel PDU Header
66
+ new type.UInt32Le(message.size()),
67
+ // CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST | CHANNEL_FLAG_SHOW_PROTOCOL
68
+ new type.UInt32Le(0x13),
69
+ message
70
+ ]));
71
+ };
72
+
73
+ recv(s) {
74
+ s.offset = 18;
75
+ const pdu = data.clipPDU().read(s), type = data.ClipPDUMsgType;
76
+
77
+ switch (pdu.obj.header.obj.msgType.value) {
78
+ case type.CB_MONITOR_READY:
79
+ this.recvMonitorReadyPDU(s);
80
+ break;
81
+ case type.CB_FORMAT_LIST:
82
+ this.recvFormatListPDU(s);
83
+ break;
84
+ case type.CB_FORMAT_LIST_RESPONSE:
85
+ this.recvFormatListResponsePDU(s);
86
+ break;
87
+ case type.CB_FORMAT_DATA_REQUEST:
88
+ this.recvFormatDataRequestPDU(s);
89
+ break;
90
+ case type.CB_FORMAT_DATA_RESPONSE:
91
+ this.recvFormatDataResponsePDU(s);
92
+ break;
93
+ case type.CB_TEMP_DIRECTORY:
94
+ break;
95
+ case type.CB_CLIP_CAPS:
96
+ this.recvClipboardCapsPDU(s);
97
+ break;
98
+ case type.CB_FILECONTENTS_REQUEST:
99
+ }
100
+
101
+ this.transport.once('cliprdr', (s) => {
102
+ this.recv(s);
103
+ });
104
+ }
105
+
106
+ /**
107
+ * Receive capabilities from server
108
+ * @param s {type.Stream}
109
+ */
110
+ recvClipboardCapsPDU(s) {
111
+ // Start at 18
112
+ s.offset = 18;
113
+ // const pdu = data.clipPDU().read(s);
114
+ // console.log('recvClipboardCapsPDU', s);
115
}
116
101
- this.transport.once('cliprdr', (s) => {
102
- this.recv(s);
103
- });
104
- }
105
-
106
- /**
107
- * Receive capabilities from server
108
- * @param s {type.Stream}
109
- */
110
- recvClipboardCapsPDU(s) {
111
- // Start at 18
112
- s.offset = 18;
113
- // const pdu = data.clipPDU().read(s);
114
- // console.log('recvClipboardCapsPDU', s);
115
- }
116
-
117
-
118
- /**
119
- * Receive monitor ready from server
120
- * @param s {type.Stream}
121
- */
122
- recvMonitorReadyPDU(s) {
123
- s.offset = 18;
124
- // const pdu = data.clipPDU().read(s);
125
- // console.log('recvMonitorReadyPDU', s);
126
-
127
- this.sendClipboardCapsPDU();
128
- // this.sendClientTemporaryDirectoryPDU();
129
- this.sendFormatListPDU();
130
- }
131
-
132
-
133
- /**
134
- * Send clipboard capabilities PDU
135
- */
136
- sendClipboardCapsPDU() {
137
- this.send(new type.Component({
138
- msgType: new type.UInt16Le(data.ClipPDUMsgType.CB_CLIP_CAPS),
139
- msgFlags: new type.UInt16Le(0x00),
140
- dataLen: new type.UInt32Le(0x10),
141
- cCapabilitiesSets: new type.UInt16Le(0x01),
142
- pad1: new type.UInt16Le(0x00),
143
- capabilitySetType: new type.UInt16Le(0x01),
144
- lengthCapability: new type.UInt16Le(0x0c),
145
- version: new type.UInt32Le(0x02),
146
- capabilityFlags: new type.UInt32Le(0x02)
147
- }));
148
- }
149
-
150
-
151
- /**
152
- * Send client temporary directory PDU
153
- */
154
- sendClientTemporaryDirectoryPDU(path = '') {
155
- // TODO
156
- this.send(new type.Component({
157
- msgType: new type.UInt16Le(data.ClipPDUMsgType.CB_TEMP_DIRECTORY),
158
- msgFlags: new type.UInt16Le(0x00),
159
- dataLen: new type.UInt32Le(0x0208),
160
- wszTempDir: new type.BinaryString(Buffer.from('D:\\Vectors' + Array(251).join('\x00'), 'ucs2'), { readLength : new type.CallableValue(520)})
161
- }));
162
- }
163
-
164
-
165
- /**
166
- * Send format list PDU
167
- */
168
- sendFormatListPDU() {
169
- this.send(new type.Component({
170
- msgType: new type.UInt16Le(data.ClipPDUMsgType.CB_FORMAT_LIST),
171
- msgFlags: new type.UInt16Le(0x00),
172
-
173
- dataLen: new type.UInt32Le(0x24),
174
-
175
- formatId6: new type.UInt32Le(0xc004),
176
- formatName6: new type.BinaryString(Buffer.from('Native\x00' , 'ucs2'), { readLength : new type.CallableValue(14)}),
177
-
178
- formatId8: new type.UInt32Le(0x0d),
179
- formatName8: new type.UInt16Le(0x00),
180
-
181
- formatId9: new type.UInt32Le(0x10),
182
- formatName9: new type.UInt16Le(0x00),
183
-
184
- formatId0: new type.UInt32Le(0x01),
185
- formatName0: new type.UInt16Le(0x00),
186
-
187
- // dataLen: new type.UInt32Le(0xe0),
188
-
189
- // formatId1: new type.UInt32Le(0xc08a),
190
- // formatName1: new type.BinaryString(Buffer.from('Rich Text Format\x00' , 'ucs2'), { readLength : new type.CallableValue(34)}),
191
-
192
- // formatId2: new type.UInt32Le(0xc145),
193
- // formatName2: new type.BinaryString(Buffer.from('Rich Text Format Without Objects\x00' , 'ucs2'), { readLength : new type.CallableValue(66)}),
194
-
195
- // formatId3: new type.UInt32Le(0xc143),
196
- // formatName3: new type.BinaryString(Buffer.from('RTF As Text\x00' , 'ucs2'), { readLength : new type.CallableValue(24)}),
197
-
198
- // formatId4: new type.UInt32Le(0x01),
199
- // formatName4: new type.BinaryString(0x00),
200
-
201
- formatId5: new type.UInt32Le(0x07),
202
- formatName5: new type.UInt16Le(0x00),
203
-
204
- // formatId6: new type.UInt32Le(0xc004),
205
- // formatName6: new type.BinaryString(Buffer.from('Native\x00' , 'ucs2'), { readLength : new type.CallableValue(14)}),
206
-
207
- // formatId7: new type.UInt32Le(0xc00e),
208
- // formatName7: new type.BinaryString(Buffer.from('Object Descriptor\x00' , 'ucs2'), { readLength : new type.CallableValue(36)}),
209
-
210
- // formatId8: new type.UInt32Le(0x03),
211
- // formatName8: new type.UInt16Le(0x00),
212
-
213
- // formatId9: new type.UInt32Le(0x10),
214
- // formatName9: new type.UInt16Le(0x00),
215
-
216
- // formatId0: new type.UInt32Le(0x07),
217
- // formatName0: new type.UInt16Le(0x00),
218
- }));
219
-
220
- }
221
-
222
- /**
223
- * Recvie format list PDU from server
224
- * @param {type.Stream} s
225
- */
226
- recvFormatListPDU(s) {
227
- s.offset = 18;
228
- // const pdu = data.clipPDU().read(s);
229
- // console.log('recvFormatListPDU', s);
230
- this.sendFormatListResponsePDU();
231
- }
232
-
233
-
234
- /**
235
- * Send format list reesponse
236
- */
237
- sendFormatListResponsePDU() {
238
- this.send(new type.Component({
239
- msgType: new type.UInt16Le(data.ClipPDUMsgType.CB_FORMAT_LIST_RESPONSE),
240
- msgFlags: new type.UInt16Le(0x01),
241
- dataLen: new type.UInt32Le(0x00),
242
- }));
243
-
244
- this.sendFormatDataRequestPDU();
245
- }
246
-
247
-
248
- /**
249
- * Receive format list response from server
250
- * @param s {type.Stream}
251
- */
252
- recvFormatListResponsePDU(s) {
253
- s.offset = 18;
254
- // const pdu = data.clipPDU().read(s);
255
- // console.log('recvFormatListResponsePDU', s);
256
- // this.sendFormatDataRequestPDU();
257
- }
258
-
259
-
260
- /**
261
- * Send format data request PDU
262
- */
263
- sendFormatDataRequestPDU(formartId = 0x0d) {
264
- this.send(new type.Component({
265
- msgType: new type.UInt16Le(data.ClipPDUMsgType.CB_FORMAT_DATA_REQUEST),
266
- msgFlags: new type.UInt16Le(0x00),
267
- dataLen: new type.UInt32Le(0x04),
268
- requestedFormatId: new type.UInt32Le(formartId),
269
- }));
270
- }
271
-
272
-
273
- /**
274
- * Receive format data request PDU from server
275
- * @param s {type.Stream}
276
- */
277
- recvFormatDataRequestPDU(s) {
278
- s.offset = 18;
279
- // const pdu = data.clipPDU().read(s);
280
- // console.log('recvFormatDataRequestPDU', s);
281
- this.sendFormatDataResponsePDU();
282
- }
283
-
284
-
285
- /**
286
- * Send format data reesponse PDU
287
- */
288
- sendFormatDataResponsePDU() {
289
-
290
- const bufs = Buffer.from(this.content + '\x00' , 'ucs2');
291
-
292
- this.send(new type.Component({
293
- msgType: new type.UInt16Le(data.ClipPDUMsgType.CB_FORMAT_DATA_RESPONSE),
294
- msgFlags: new type.UInt16Le(0x01),
295
- dataLen: new type.UInt32Le(bufs.length),
296
- requestedFormatData: new type.BinaryString(bufs, { readLength : new type.CallableValue(bufs.length)})
297
- }));
298
-
299
- }
300
-
301
-
302
- /**
303
- * Receive format data response PDU from server
304
- * @param s {type.Stream}
305
- */
306
- recvFormatDataResponsePDU(s) {
307
- s.offset = 18;
308
- // const pdu = data.clipPDU().read(s);
309
- const str = s.buffer.toString('ucs2', 26, s.buffer.length-2);
310
- // console.log('recvFormatDataResponsePDU', str);
311
- this.content = str;
312
- this.emit('clipboard', str)
313
- }
314
-
315
-
316
-// =====================================================================================
317
- setClipboardData(content) {
318
- this.content = content;
319
- this.sendFormatListPDU();
320
- }
117
+
118
+ /**
119
+ * Receive monitor ready from server
120
+ * @param s {type.Stream}
121
+ */
122
+ recvMonitorReadyPDU(s) {
123
+ s.offset = 18;
124
+ // const pdu = data.clipPDU().read(s);
125
+ // console.log('recvMonitorReadyPDU', s);
126
+
127
+ this.sendClipboardCapsPDU();
128
+ // this.sendClientTemporaryDirectoryPDU();
129
+ this.sendFormatListPDU();
130
+ }
131
+
132
+
133
+ /**
134
+ * Send clipboard capabilities PDU
135
+ */
136
+ sendClipboardCapsPDU() {
137
+ this.send(new type.Component({
138
+ msgType: new type.UInt16Le(data.ClipPDUMsgType.CB_CLIP_CAPS),
139
+ msgFlags: new type.UInt16Le(0x00),
140
+ dataLen: new type.UInt32Le(0x10),
141
+ cCapabilitiesSets: new type.UInt16Le(0x01),
142
+ pad1: new type.UInt16Le(0x00),
143
+ capabilitySetType: new type.UInt16Le(0x01),
144
+ lengthCapability: new type.UInt16Le(0x0c),
145
+ version: new type.UInt32Le(0x02),
146
+ capabilityFlags: new type.UInt32Le(0x02)
147
+ }));
148
+ }
149
+
150
+
151
+ /**
152
+ * Send client temporary directory PDU
153
+ */
154
+ sendClientTemporaryDirectoryPDU(path = '') {
155
+ // TODO
156
+ this.send(new type.Component({
157
+ msgType: new type.UInt16Le(data.ClipPDUMsgType.CB_TEMP_DIRECTORY),
158
+ msgFlags: new type.UInt16Le(0x00),
159
+ dataLen: new type.UInt32Le(0x0208),
160
+ wszTempDir: new type.BinaryString(Buffer.from('D:\\Vectors' + Array(251).join('\x00'), 'ucs2'), { readLength: new type.CallableValue(520) })
161
+ }));
162
+ }
163
+
164
+
165
+ /**
166
+ * Send format list PDU
167
+ */
168
+ sendFormatListPDU() {
169
+ this.send(new type.Component({
170
+ msgType: new type.UInt16Le(data.ClipPDUMsgType.CB_FORMAT_LIST),
171
+ msgFlags: new type.UInt16Le(0x00),
172
+
173
+ dataLen: new type.UInt32Le(0x24),
174
+
175
+ formatId6: new type.UInt32Le(0xc004),
176
+ formatName6: new type.BinaryString(Buffer.from('Native\x00', 'ucs2'), { readLength: new type.CallableValue(14) }),
177
+
178
+ formatId8: new type.UInt32Le(0x0d),
179
+ formatName8: new type.UInt16Le(0x00),
180
+
181
+ formatId9: new type.UInt32Le(0x10),
182
+ formatName9: new type.UInt16Le(0x00),
183
+
184
+ formatId0: new type.UInt32Le(0x01),
185
+ formatName0: new type.UInt16Le(0x00),
186
+
187
+ // dataLen: new type.UInt32Le(0xe0),
188
+
189
+ // formatId1: new type.UInt32Le(0xc08a),
190
+ // formatName1: new type.BinaryString(Buffer.from('Rich Text Format\x00' , 'ucs2'), { readLength : new type.CallableValue(34)}),
191
+
192
+ // formatId2: new type.UInt32Le(0xc145),
193
+ // formatName2: new type.BinaryString(Buffer.from('Rich Text Format Without Objects\x00' , 'ucs2'), { readLength : new type.CallableValue(66)}),
194
+
195
+ // formatId3: new type.UInt32Le(0xc143),
196
+ // formatName3: new type.BinaryString(Buffer.from('RTF As Text\x00' , 'ucs2'), { readLength : new type.CallableValue(24)}),
197
+
198
+ // formatId4: new type.UInt32Le(0x01),
199
+ // formatName4: new type.BinaryString(0x00),
200
+
201
+ formatId5: new type.UInt32Le(0x07),
202
+ formatName5: new type.UInt16Le(0x00),
203
+
204
+ // formatId6: new type.UInt32Le(0xc004),
205
+ // formatName6: new type.BinaryString(Buffer.from('Native\x00' , 'ucs2'), { readLength : new type.CallableValue(14)}),
206
+
207
+ // formatId7: new type.UInt32Le(0xc00e),
208
+ // formatName7: new type.BinaryString(Buffer.from('Object Descriptor\x00' , 'ucs2'), { readLength : new type.CallableValue(36)}),
209
+
210
+ // formatId8: new type.UInt32Le(0x03),
211
+ // formatName8: new type.UInt16Le(0x00),
212
+
213
+ // formatId9: new type.UInt32Le(0x10),
214
+ // formatName9: new type.UInt16Le(0x00),
215
+
216
+ // formatId0: new type.UInt32Le(0x07),
217
+ // formatName0: new type.UInt16Le(0x00),
218
+ }));
219
+
220
+ }
221
+
222
+ /**
223
+ * Recvie format list PDU from server
224
+ * @param {type.Stream} s
225
+ */
226
+ recvFormatListPDU(s) {
227
+ s.offset = 18;
228
+ // const pdu = data.clipPDU().read(s);
229
+ // console.log('recvFormatListPDU', s);
230
+ this.sendFormatListResponsePDU();
231
+ }
232
+
233
+
234
+ /**
235
+ * Send format list reesponse
236
+ */
237
+ sendFormatListResponsePDU() {
238
+ this.send(new type.Component({
239
+ msgType: new type.UInt16Le(data.ClipPDUMsgType.CB_FORMAT_LIST_RESPONSE),
240
+ msgFlags: new type.UInt16Le(0x01),
241
+ dataLen: new type.UInt32Le(0x00),
242
+ }));
243
+
244
+ this.sendFormatDataRequestPDU();
245
+ }
246
+
247
+
248
+ /**
249
+ * Receive format list response from server
250
+ * @param s {type.Stream}
251
+ */
252
+ recvFormatListResponsePDU(s) {
253
+ s.offset = 18;
254
+ // const pdu = data.clipPDU().read(s);
255
+ // console.log('recvFormatListResponsePDU', s);
256
+ // this.sendFormatDataRequestPDU();
257
+ }
258
+
259
+
260
+ /**
261
+ * Send format data request PDU
262
+ */
263
+ sendFormatDataRequestPDU(formartId = 0x0d) {
264
+ this.send(new type.Component({
265
+ msgType: new type.UInt16Le(data.ClipPDUMsgType.CB_FORMAT_DATA_REQUEST),
266
+ msgFlags: new type.UInt16Le(0x00),
267
+ dataLen: new type.UInt32Le(0x04),
268
+ requestedFormatId: new type.UInt32Le(formartId),
269
+ }));
270
+ }
271
+
272
+
273
+ /**
274
+ * Receive format data request PDU from server
275
+ * @param s {type.Stream}
276
+ */
277
+ recvFormatDataRequestPDU(s) {
278
+ s.offset = 18;
279
+ // const pdu = data.clipPDU().read(s);
280
+ // console.log('recvFormatDataRequestPDU', s);
281
+ this.sendFormatDataResponsePDU();
282
+ }
283
+
284
+
285
+ /**
286
+ * Send format data reesponse PDU
287
+ */
288
+ sendFormatDataResponsePDU() {
289
+
290
+ const bufs = Buffer.from(this.content + '\x00', 'ucs2');
291
+
292
+ this.send(new type.Component({
293
+ msgType: new type.UInt16Le(data.ClipPDUMsgType.CB_FORMAT_DATA_RESPONSE),
294
+ msgFlags: new type.UInt16Le(0x01),
295
+ dataLen: new type.UInt32Le(bufs.length),
296
+ requestedFormatData: new type.BinaryString(bufs, { readLength: new type.CallableValue(bufs.length) })
297
+ }));
298
+
299
+ }
300
+
301
+
302
+ /**
303
+ * Receive format data response PDU from server
304
+ * @param s {type.Stream}
305
+ */
306
+ recvFormatDataResponsePDU(s) {
307
+ s.offset = 18;
308
+ // const pdu = data.clipPDU().read(s);
309
+ const str = s.buffer.toString('ucs2', 26, s.buffer.length - 2);
310
+ // console.log('recvFormatDataResponsePDU', str);
311
+ this.content = str;
312
+ this.emit('clipboard', str)
313
+ }
314
+
315
+
316
+ // =====================================================================================
317
+ setClipboardData(content) {
318
+ this.content = content;
319
+ this.sendFormatListPDU();
320
+ }
321
322
}
323
-
323
+
324
325
module.exports = {
326
- Client
326
+ Client
327
}
rdp/protocol/rdp.js
+1
-6
@@ -184,12 +184,7 @@ function RdpClient(config) {
184
}
185
}).on('error', function (err) {
186
log.warn(err.code + '(' + err.message + ')\n' + err.stack);
187
- if (err instanceof error.FatalError) {
188
- throw err;
189
- }
190
- else {
191
- self.emit('error', err);
192
- }
187
+ if (err instanceof error.FatalError) { throw err; } else { self.emit('error', err); }
188
});
189
}
190
rdp/protocol/x224.js
+6
-3
@@ -218,8 +218,9 @@ Client.prototype.recvConnectionConfirm = function(s) {
218
var message = serverConnectionConfirm().read(s);
219
220
if (message.obj.protocolNeg.obj.type.value == NegotiationType.TYPE_RDP_NEG_FAILURE) {
221
- throw new error.ProtocolError('NODE_RDP_PROTOCOL_X224_NEG_FAILURE',
222
- 'Failure code:' + message.obj.protocolNeg.obj.result.value + " (see https://msdn.microsoft.com/en-us/library/cc240507.aspx)");
221
+ this.emit('error', { err: 'NODE_RDP_PROTOCOL_X224_NEG_FAILURE', code: message.obj.protocolNeg.obj.result.value });
222
+ return;
223
+ //throw new error.ProtocolError('NODE_RDP_PROTOCOL_X224_NEG_FAILURE', 'Failure code:' + message.obj.protocolNeg.obj.result.value + " (see https://msdn.microsoft.com/en-us/library/cc240507.aspx)");
224
}
225
226
if (message.obj.protocolNeg.obj.type.value == NegotiationType.TYPE_RDP_NEG_RSP) {
@@ -227,7 +228,9 @@ Client.prototype.recvConnectionConfirm = function(s) {
228
}
229
230
if ([Protocols.PROTOCOL_HYBRID_EX].indexOf(this.selectedProtocol) !== -1) {
230
- throw new error.ProtocolError('NODE_RDP_PROTOCOL_X224_NLA_NOT_SUPPORTED');
231
+ this.emit('error', 'NODE_RDP_PROTOCOL_X224_NLA_NOT_SUPPORTED');
232
+ return;
233
+ //throw new error.ProtocolError('NODE_RDP_PROTOCOL_X224_NLA_NOT_SUPPORTED');
234
}
235
236
if (this.selectedProtocol == Protocols.PROTOCOL_RDP) {
views/default.handlebars
+11
-1
@@ -8414,7 +8414,7 @@
8414
function autoConnectDesktop(e) { if (autoConnectDesktopTimer == null) { autoConnectDesktopTimer = setInterval(function() { connectDesktop(null, 1) }, 1000); } else { clearInterval(autoConnectDesktopTimer); autoConnectDesktopTimer = null; } }
8415
8416
// Used to translate incoming agent console messages
8417
- var agentConsoleMessages = [ '', "Waiting for user to grant access...", "Denied", "Failed to start remote terminal session, {0} ({1})", "Timeout", "Received invalid network data", "Unable to capture display" ];
8417
+ var agentConsoleMessages = [ '', "Waiting for user to grant access...", "Denied", "Failed to start remote terminal session, {0} ({1})", "Timeout", "Received invalid network data", "Unable to capture display", "Protocol negotiation failed ({0})", "NLA not supported", "SSL required by server", "SSL not allowed by server", "SSL certificate not on server", "Inconsistent flags", "Hybrid required by server", "SSL with user auth required by server" ];
8418
function formatAgentConsoleMessage(msg, msgid, msgargs) {
8419
var r;
8420
if (msgargs == null) { msgargs = []; }
@@ -8569,6 +8569,16 @@
8569
if (desktopsettings.rdpsmb) { desktop.m.SwapMouse = desktopsettings.rdpsmb; }
8570
desktop.Start(desktopNode._id, currentNode.rdpport ? currentNode.rdpport : 3389, tsid);
8571
desktop.contype = 4;
8572
+ desktop.onConsoleMessageChange = function () {
8573
+ if (desktop.consoleMessage) {
8574
+ Q('p11DeskConsoleMsg').innerHTML += formatAgentConsoleMessage(desktop.consoleMessage, desktop.consoleMessageId, desktop.consoleMessageArgs);
8575
+ QV('p11DeskConsoleMsg', true);
8576
+ if (p11DeskConsoleMsgTimer != null) { clearTimeout(p11DeskConsoleMsgTimer); }
8577
+ if (desktop.consoleMessageTimeout) { p11DeskConsoleMsgTimer = setTimeout(p11clearConsoleMsg, desktop.consoleMessageTimeout * 1000); }
8578
+ } else {
8579
+ p11clearConsoleMsg();
8580
+ }
8581
+ }
8582
}
8583
} else {
8584
// Disconnect and clean up the remote desktop