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