From fbb44264c2cfe8da3e4a4bc53b5ae654e0ea0988 Mon Sep 17 00:00:00 2001 From: echicken <> Date: Sat, 31 Mar 2018 05:41:58 +0000 Subject: [PATCH] These are no longer needed and will only cause confusion alongside other websocket scripts. --- exec/load/websocket-proxy.js | 522 ------------------------------- exec/websocket-rlogin-service.js | 453 --------------------------- exec/websocket-telnet-service.js | 284 ----------------- 3 files changed, 1259 deletions(-) delete mode 100644 exec/load/websocket-proxy.js delete mode 100644 exec/websocket-rlogin-service.js delete mode 100644 exec/websocket-telnet-service.js diff --git a/exec/load/websocket-proxy.js b/exec/load/websocket-proxy.js deleted file mode 100644 index 0d0d34e1ea..0000000000 --- a/exec/load/websocket-proxy.js +++ /dev/null @@ -1,522 +0,0 @@ -load('sha1.js'); - -var WebSocketProxy = function(client) { - - var WEBSOCKET_NEED_PACKET_START = 0; - var WEBSOCKET_NEED_PAYLOAD_LENGTH = 1; - var WEBSOCKET_NEED_MASKING_KEY = 2; - var WEBSOCKET_DATA = 3; - - var FFrameMask = []; - var FFrameOpCode = 0; - var FFramePayloadLength = 0; - var FFramePayloadReceived = 0; - var FWebSocketState = WEBSOCKET_NEED_PACKET_START; - - var self = this; - this.headers = []; - - var ClientDataBuffer = []; // From client - var ServerDataBuffer = []; // From server - - function CalculateWebSocketKey(InLine) { - var Digits = ''; - var Spaces = 0; - for (var i = 0; i < InLine.length; i++) { - if (InLine.charAt(i) == ' ') { - Spaces++; - } else if (!isNaN(InLine.charAt(i))) { - Digits += InLine.charAt(i); - } - } - return Digits / Spaces; - } - - function GetFromWebSocketClient() { - switch (self.headers['Version']) { - case 0: return GetFromWebSocketClientDraft0(); - case 7: - case 8: - case 13: - return GetFromWebSocketClientVersion7(); - } - } - - function GetFromWebSocketClientDraft0() { - var Result = []; - var InByte = 0; - var InByte2 = 0; - var InByte3 = 0; - - while (client.socket.data_waiting) { - InByte = client.socket.recvBin(1); - - // Check what the client packet state is - switch (FWebSocketState) { - case WEBSOCKET_NEED_PACKET_START: - // Check for 0x00 to indicate the start of a data packet - if (InByte === 0x00) { - FWebSocketState = WEBSOCKET_DATA; - } - break; - case WEBSOCKET_DATA: - // We're in a data packet, so check for 0xFF, which - // indicates the data packet is done - if (InByte == 0xFF) { - FWebSocketState = WEBSOCKET_NEED_PACKET_START; - } else { - // Check if the byte needs to be UTF-8 decoded - if (InByte < 128) { - Result.push(InByte); - } else if ((InByte > 191) && (InByte < 224)) { - // Handle UTF-8 decode - InByte2 = client.socket.recvBin(1); - Result.push(((InByte & 31) << 6) | (InByte2 & 63)); - } else { - // Handle UTF-8 decode (should never need this, but - // included anyway) - InByte2 = client.socket.recvBin(1); - InByte3 = client.socket.recvBin(1); - Result.push( - ((InByte&15)<<12)|((InByte2&63)<<6)|(InByte3&63) - ); - } - } - break; - } - } - - return Result; - } - - function GetFromWebSocketClientVersion7() { - var Result = []; - var InByte = 0; - var InByte2 = 0; - var InByte3 = 0; - - while (client.socket.data_waiting) { - // Check what the client packet state is - switch (FWebSocketState) { - case WEBSOCKET_NEED_PACKET_START: - // Next byte will give us the opcode, and also tell is if - // the message is fragmented - FFrameMask = []; - FFrameOpCode = client.socket.recvBin(1); - FFramePayloadLength = 0; - FFramePayloadReceived = 0; - FWebSocketState = WEBSOCKET_NEED_PAYLOAD_LENGTH; - break; - case WEBSOCKET_NEED_PAYLOAD_LENGTH: - FFramePayloadLength = (client.socket.recvBin(1) & 0x7F); - if (FFramePayloadLength === 126) { - FFramePayloadLength = client.socket.recvBin(2); - } else if (FFramePayloadLength === 127) { - FFramePayloadLength = client.socket.recvBin(8); - } - FWebSocketState = WEBSOCKET_NEED_MASKING_KEY; - break; - case WEBSOCKET_NEED_MASKING_KEY: - InByte = client.socket.recvBin(4); - FFrameMask[0] = (InByte & 0xFF000000) >> 24; - FFrameMask[1] = (InByte & 0x00FF0000) >> 16; - FFrameMask[2] = (InByte & 0x0000FF00) >> 8; - FFrameMask[3] = InByte & 0x000000FF; - FWebSocketState = WEBSOCKET_DATA; - break; - case WEBSOCKET_DATA: - InByte = ( - client.socket.recvBin(1)^FFrameMask[ - FFramePayloadReceived++ % 4 - ] - ); - - // Check if the byte needs to be UTF-8 decoded - if ((InByte & 0x80) === 0) { - Result.push(InByte); - } else if ((InByte & 0xE0) === 0xC0) { - // Handle UTF-8 decode - InByte2 = ( - client.socket.recvBin(1)^FFrameMask[ - FFramePayloadReceived++ % 4 - ] - ); - Result.push(((InByte & 31) << 6) | (InByte2 & 63)); - } else { - log(LOG_NOTICE, 'Byte out of range: ' + InByte); - } - - // Check if we've received the full payload - if (FFramePayloadReceived === FFramePayloadLength) { - FWebSocketState = WEBSOCKET_NEED_PACKET_START; - } - break; - } - } - - return Result; - } - - function SendToWebSocketClient(AData) { - switch (self.headers['Version']) { - case 0: - SendToWebSocketClientDraft0(AData); - break; - case 7: - case 8: - case 13: - SendToWebSocketClientVersion7(AData); - break; - } - } - - function SendToWebSocketClientDraft0(AData) { - // Send 0x00 to indicate the start of a data packet - client.socket.sendBin(0x00, 1); - - for (var i = 0; i < AData.length; i++) { - // Check if the byte needs to be UTF-8 encoded - if ((AData[i] & 0xFF) <= 127) { - client.socket.sendBin(AData[i], 1); - } else if ((AData[i] & 0xFF) <= 2047) { - // Handle UTF-8 encode - client.socket.sendBin((AData[i] >> 6) | 192, 1); - client.socket.sendBin((AData[i] & 63) | 128, 1); - } else { - log(LOG_NOTICE, 'Byte out of range: ' + AData[i]); - } - } - - // Send 0xFF to indicate the end of a data packet - client.socket.sendBin(0xFF, 1); - } - - function SendToWebSocketClientVersion7(AData) { - if (AData.length > 0) { - var ToSend = []; - - for (var i = 0; i < AData.length; i++) { - // Check if the byte needs to be UTF-8 encoded - if ((AData[i] & 0xFF) <= 127) { - ToSend.push(AData[i]); - } else if ( - ((AData[i] & 0xFF) >= 128) && ((AData[i] & 0xFF) <= 2047) - ) { - // Handle UTF-8 encode - ToSend.push((AData[i] >> 6) | 192); - ToSend.push((AData[i] & 63) | 128); - } else { - log(LOG_NOTICE, 'Byte out of range: ' + AData[i]); - } - } - - client.socket.sendBin(0x81, 1); - if (ToSend.length <= 125) { - client.socket.sendBin(ToSend.length, 1); - } else if (ToSend.length <= 65535) { - client.socket.sendBin(126, 1); - client.socket.sendBin(ToSend.length, 2); - } else { - // NOTE: client.socket.sendBin(ToSend.length, 8); didn't work, - // so this modification limits the send to 2^32 bytes (probably - // not an issue). Probably should look into a proper fix at - // some point though - client.socket.sendBin(127, 1); - client.socket.sendBin(0, 4); - client.socket.sendBin(ToSend.length, 4); - } - - for (var i = 0; i < ToSend.length; i++) { - client.socket.sendBin(ToSend[i] & 0xFF, 1); - } - } - } - - function ShakeHands() { - self.headers['Version'] = 0; - - try { - // Keep reading header data until we get all the data we want - while (true) { - // Read another line, abort if we don't get one in 5 seconds - var InLine = client.socket.recvline(1024, 5); - if (InLine === null) { - log(LOG_ERR, - 'Timeout exceeded while waiting for complete handshake' - ); - return false; - } - - log(LOG_DEBUG, 'Handshake Line: ' + InLine); - - // Check for blank line (indicates we have most of the header, - // and only the last 8 bytes remain - if (InLine === '') { - switch (self.headers['Version']) { - case 0: - return ShakeHandsDraft0(); - case 7: - case 8: - case 13: - return ShakeHandsVersion7(); - default: - // TODO If this version does not match a version - // understood by the server, the server MUST abort - // the websocket handshake described in this section - // and instead send an appropriate HTTP error code - // (such as 426 Upgrade Required), and a - // |Sec-WebSocket-Version| header indicating the - // version(s) the server is capable of - // understanding. - break; - } - break; - } else if (InLine.indexOf('Connection:') === 0) { - // Example: "Connection: Upgrade" - self.headers['Connection'] = InLine.replace( - /Connection:\s?/i, - '' - ); - } else if (InLine.indexOf('GET') === 0) { - // Example: "GET /demo HTTP/1.1" - var GET = InLine.split(' '); - self.headers['Path'] = GET[1]; - } else if (InLine.indexOf('Host:') === 0) { - // Example: "Host: example.com" - self.headers['Host'] = InLine.replace(/Host:\s?/i, ''); - } else if (InLine.indexOf('Origin:') === 0) { - // Example: "Origin: http://example.com" - self.headers['Origin'] = InLine.replace(/Origin:\s?/i, ''); - } else if (InLine.indexOf('Sec-WebSocket-Key:') === 0) { - // Example: "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" - self.headers['Key'] = InLine.replace( - /Sec-WebSocket-Key:\s?/i, - '' - ); - } else if (InLine.indexOf('Sec-WebSocket-Key1:') === 0) { - // Example: "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5" - self.headers['Key1'] = CalculateWebSocketKey( - InLine.replace(/Sec-WebSocket-Key1:\s?/i, '') - ); - } else if (InLine.indexOf('Sec-WebSocket-Key2:') === 0) { - // Example: "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00" - self.headers['Key2'] = CalculateWebSocketKey( - InLine.replace(/Sec-WebSocket-Key2:\s?/i, '') - ); - } else if (InLine.indexOf('Sec-WebSocket-Origin:') === 0) { - // Example: "Sec-WebSocket-Origin: http://example.com" - self.headers['Origin'] = InLine.replace( - /Sec-WebSocket-Origin:\s?/i, - '' - ); - } else if (InLine.indexOf('Sec-WebSocket-Protocol:') === 0) { - // Example: "Sec-WebSocket-Protocol: sample" - self.headers['SubProtocol'] = InLine.replace( - /Sec-WebSocket-Protocol:\s?/i, - '' - ); - } else if (InLine.indexOf('Sec-WebSocket-Draft') === 0) { - // Example: "Sec-WebSocket-Draft: 2" - try { - self.headers['Version'] = parseInt( - InLine.replace(/Sec-WebSocket-Draft:\s?/i, '') - ); - } catch (err) { - self.headers['Version'] = 0; - } - } else if (InLine.indexOf('Sec-WebSocket-Version') === 0) { - // Example: "Sec-WebSocket-Version: 8" - try { - self.headers['Version'] = parseInt( - InLine.replace(/Sec-WebSocket-Version:\s?/i, '') - ); - } catch (err) { - self.headers['Version'] = 0; - } - } else if (InLine.indexOf('Upgrade:') === 0) { - // Example: "Upgrade: websocket" - self.headers['Upgrade'] = InLine.replace(/Upgrade:\s?/i,''); - } else if (InLine.indexOf('Cookie:') === 0) { - self.headers['Cookie'] = InLine.replace(/Cookie:\s?/i, ''); - } - } - } catch (err) { - log(LOG_ERR, 'ShakeHands() error: ' + err.toString()); - } - - return false; - } - - function ShakeHandsDraft0() { - // Ensure we have all the data we need - if (('Key1' in self.headers) && - ('Key2' in self.headers) && - ('Host' in self.headers) && - ('Origin' in self.headers !== '') && - ('Path' in self.headers) - ) { - // Combine Key1, Key2, and the last 8 bytes into a string that we - // will later hash - var ToHash = '' - ToHash += String.fromCharCode( - (self.headers['Key1'] & 0xFF000000) >> 24 - ); - ToHash += String.fromCharCode( - (self.headers['Key1'] & 0x00FF0000) >> 16 - ); - ToHash += String.fromCharCode( - (self.headers['Key1'] & 0x0000FF00) >> 8 - ); - ToHash += String.fromCharCode( - (self.headers['Key1'] & 0x000000FF) >> 0 - ); - ToHash += String.fromCharCode( - (self.headers['Key2'] & 0xFF000000) >> 24 - ); - ToHash += String.fromCharCode( - (self.headers['Key2'] & 0x00FF0000) >> 16 - ); - ToHash += String.fromCharCode( - (self.headers['Key2'] & 0x0000FF00) >> 8 - ); - ToHash += String.fromCharCode( - (self.headers['Key2'] & 0x000000FF) >> 0 - ); - for (var i = 0; i < 8; i++) { - ToHash += String.fromCharCode(client.socket.recvBin(1)); - } - - // Hash the string - var Hashed = md5_calc(ToHash, true); - - // Setup the handshake response - var Response = 'HTTP/1.1 101 Web Socket Protocol Handshake\r\n' + - 'Upgrade: WebSocket\r\n' + - 'Connection: Upgrade\r\n' + - 'Sec-WebSocket-Origin: ' + self.headers['Origin'] + - '\r\n' + - 'Sec-WebSocket-Location: ws://' + - self.headers['Host'] + - self.headers['Path'] + - '\r\n'; - if ('SubProtocol' in self.headers) { - Response += - 'Sec-WebSocket-Protocol: ' + - self.headers['SubProtocol'] + - '\r\n'; - } - Response += '\r\n'; - - // Loop through the hash string (which is hex encoded) and append - // the individual bytes to the response - for (var i = 0; i < Hashed.length; i += 2) { - Response += String.fromCharCode( - parseInt(Hashed.charAt(i) + Hashed.charAt(i + 1), 16) - ); - } - - // Send the response and return - client.socket.send(Response); - return true; - } else { - // We're missing some pice of data, log what we do have - log(LOG_ERR, - 'Missing some piece of handshake data. Here\'s what we have:' - ); - for(var x in self.headers) { - log(LOG_ERR, x + ' => ' + self.headers[x]); - } - return false; - } - } - - function ShakeHandsVersion7() { - // Ensure we have all the data we need - if (('Key' in self.headers) && - ('Host' in self.headers) && - ('Origin' in self.headers !== '') && - ('Path' in self.headers) - ) { - var AcceptGUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'; - - // Combine Key and GUID - var ToHash = self.headers['Key'] + AcceptGUID; - - // Hash the string - var Hashed = Sha1.hash(ToHash, false); - - // Encode the hash - var ToEncode = ''; - for (var i = 0; i <= 38; i += 2) { - ToEncode += String.fromCharCode( - parseInt(Hashed.substr(i, 2), 16) - ); - } - var Encoded = base64_encode(ToEncode); - - // Setup the handshake response - var Response = 'HTTP/1.1 101 Switching Protocols\r\n' + - 'Upgrade: websocket\r\n' + - 'Connection: Upgrade\r\n' + - 'Sec-WebSocket-Accept: ' + Encoded + '\r\n'; - if ('SubProtocol' in self.headers) { - // Only sub-protocol we support - Response += 'Sec-WebSocket-Protocol: plain\r\n'; - } - Response += '\r\n'; - - // Send the response and return - client.socket.send(Response); - return true; - } else { - log(LOG_ERR, - 'Missing some piece of handshake data. Here\'s what we have:' - ); - for(var x in self.headers) { - log(LOG_ERR, x + ' => ' + self.headers[x]); - } - return false; - } - } - - this.__defineGetter__( - 'data_waiting', - function() { - return (ClientDataBuffer.length > 0); - } - ); - - this.send = function(data) { - if (typeof data === 'string') { - data = data.split('').map( - function (d) { - return ascii(d); - } - ); - } - ServerDataBuffer = ServerDataBuffer.concat(data); - } - - this.receive = function() { - var data = ''; - while (ClientDataBuffer.length > 0) { - data += ascii(ClientDataBuffer.shift()); - } - return data; - } - - this.receiveArray = function(len) { - return ClientDataBuffer.splice( - 0, - (typeof len === 'number' ? len : ClientDataBuffer.length) - ); - } - - this.cycle = function() { - ClientDataBuffer = ClientDataBuffer.concat(GetFromWebSocketClient()); - SendToWebSocketClient(ServerDataBuffer.splice(0, 4096)); - } - - if(!ShakeHands()) throw 'ShakeHands() failed'; - -} \ No newline at end of file diff --git a/exec/websocket-rlogin-service.js b/exec/websocket-rlogin-service.js deleted file mode 100644 index 172446e01d..0000000000 --- a/exec/websocket-rlogin-service.js +++ /dev/null @@ -1,453 +0,0 @@ -load('sbbsdefs.js'); -load('websocket-proxy.js'); - -function err(msg) { - log(LOG_DEBUG, msg); - client.socket.close(); - exit(); -} - -function getSession(un) { - var fn = format('%suser/%04d.web', system.data_dir, un); - if (!file_exists(fn)) return false; - var f = new File(fn); - if (!f.open('r')) return false; - var session = f.iniGetObject(); - f.close(); - return session; -} - -var RLoginClient = function(options) { - - var self = this; - - const CAN = 0x18, - CR = 0x0D, - DC1 = 0x11, - DC3 = 0x13, - DOT = 0x2E, - EOM = 0x19, - EOT = 0x04, - LF = 0x0A, - SUB = 0x1A, - DISCARD = 0x02, - RAW = 0x10, - COOKED = 0x20, - WINDOW = 0x80; - - var serverBuffer = []; // From server - var clientBuffer = []; // From client - - var state = { - connected : false, - cooked : true, - suspendInput : false, - suspendOutput : false, - watchForClientEscape : true, - clientHasEscaped : false - }; - - var properties = { - rows : 24, - columns : 80, - pixelsX : 640, - pixelsY : 480, - clientEscape : '~' - }; - - // As suggested by RFC1282 - var clientEscapes = { - DOT : self.disconnect, - EOT : self.disconnect, - SUB : function() { - state.suspendInput = (state.suspendInput) ? false : true; - state.suspendOutput = state.suspendInput; - }, - EOM : function() { - state.suspendInput = (state.suspendInput) ? false : true; - state.suspendOutput = false; - } - }; - - this.__defineGetter__('connected', function () { return state.connected; }); - - this.__defineSetter__( - 'connected', - function (value) { - if (typeof value === 'boolean' && !value) self.disconnect(); - } - ); - - this.__defineGetter__('rows', function () { return properties.rows; }); - - this.__defineSetter__( - 'rows', - function(value) { - if (typeof value === 'number' && value > 0) { - properties.rows = value; - } else { - throw 'RLogin: Invalid \'rows\' setting ' + value; - } - } - ); - - this.__defineGetter__( - 'columns', - function () { return properties.columns; } - ); - - this.__defineSetter__( - 'columns', - function (value) { - if (typeof value === 'number' && value > 0) { - properties.columns = value; - } else { - throw 'RLogin: Invalid \'columns\' setting ' + value; - } - } - ); - - this.__defineGetter__( - 'pixelsX', - function () { return properties.pixelsX; } - ); - - this.__defineSetter__( - 'pixelsX', - function (value) { - if (typeof value === 'number' && value > 0) { - properties.pixelsX = value; - } else { - throw 'RLogin: Invalid \'pixelsX\' setting ' + value; - } - } - ); - - this.__defineGetter__( - 'pixelsY', - function () { return properties.pixelsY; } - ); - - this.__defineSetter__( - 'pixelsY', - function (value) { - if (typeof value === 'number' && value > 0) { - properties.pixelsY = value; - } else { - throw 'RLogin: Invalid \'pixelsY\' setting ' + value; - } - } - ); - - this.__defineGetter__( - 'clientEscape', - function() { return properties.clientEscape; } - ); - - this.__defineSetter__( - 'clientEscape', - function (value) { - if (typeof value === 'string' && value.length === 1) { - properties.clientEscape = value; - } else { - throw 'RLogin: Invalid \'clientEscape\' setting ' + value; - } - } - ); - - var handle = new Socket(); - - function getServerData() { - - if (handle.nread < 1) return; - - var data = []; - while (handle.nread > 0) { - data.push(handle.recvBin(1)); - } - - if (!state.connected) { - if (data[0] === 0) { - state.connected = true; - if (data.length > 1) { - data = data.slice(1); - } else { - return; - } - } else { - self.disconnect(); - } - } - - // If I could tell if the TCP urgent-data pointer had been set, - // I would uncomment (and complete) this block. We'll settle - // for a partial implementation for the time being. - // We would need something to tell us if urgent data was sent, - // eg. var lookingForControlCode = urgentDataPointerIsSet(); - /* - var temp = []; - for (var d = 0; d < data.length; d++) { - if (!lookingForControlCode) { - temp.push(data[d]); - continue; - } - switch (data[d]) { - case DISCARD: - temp = []; - // We found our control code - lookingForControlCode = false; - break; - case RAW: - state.cooked = false; - lookingForControlCode = false; - break; - case COOKED: - state.cooked = true; - lookingForControlCode = false; - break; - case WINDOW: - self.sendWCCS(); - lookingForControlCode = false; - break; - default: - temp.push(data[d]); - break; - } - } - if (!state.suspendOutput) self.emit('data', new Buffer(temp)); - */ - if (!state.suspendOutput) serverBuffer = serverBuffer.concat(data); - } - - // Send a Window Change Control Sequence - // this.sendWCCS = function() { - // var magicCookie = [0xFF, 0xFF, 0x73, 0x73]; - // var rcxy = new Buffer(8); - // rcxy.writeUInt16LE(properties.rows, 0); - // rcxy.writeUInt16LE(properties.columns, 2); - // rcxy.writeUInt16LE(properties.pixelsX, 4); - // rcxy.writeUInt16LE(properties.pixelsY, 6); - // if(state.connected) - // handle.write(Buffer.concat([magicCookie, rcxy])); - // } - - // Send 'data' (String or Buffer) to the rlogin server - this.send = function (data) { - - if (!state.connected) throw 'RLogin.send: not connected.'; - if (state.suspendInput) throw 'RLogin.send: input has been suspended.'; - - if (typeof data === 'string') { - data = data.split('').map(function (d) { return ascii(d); }); - } - - var temp = []; - for (var d = 0; d < data.length; d++) { - if (state.watchForClientEscape && - data[d] == properties.clientEscape.charCodeAt(0) - ) { - state.watchForClientEscape = false; - state.clientHasEscaped = true; - continue; - } - if (state.clientHasEscaped) { - state.clientHasEscaped = false; - if (typeof clientEscapes[data[d]] !== 'undefined') { - clientEscapes[data[d]](); - } - continue; - } - if (state.cooked && (data[d] === DC1 || data[d] === DC3)) { - state.suspendOutput = (data[d] === DC3); - continue; - } - if ((d > 0 && data[d - 1] === CR && data[d] === LF) || - data[d] == CAN - ) { - state.watchForClientEscape = true; - } - temp.push(data[d]); - } - clientBuffer = clientBuffer.concat(temp); - - } - - this.receive = function () { - return serverBuffer.splice(0, serverBuffer.length); - } - - /* If 'ch' is found in client input immediately after the - 'this.clientEscape' character when: - - this is the first input after connection establishment or - - these are the first characters on a new line or - - these are the first characters after a line-cancel character - then the function 'callback' will be called. Use this to allow - client input to trigger a particular action. */ - this.addClientEscape = function (ch, callback) { - if( (typeof ch !== 'string' && typeof ch !== 'number') || - (typeof ch === 'string' && ch.length > 1) || - typeof callback !== 'function' - ) { - throw 'RLogin.addClientEscape: invalid arguments.'; - } - clientEscapes[ch.charCodeAt(0)] = callback; - } - - this.connect = function () { - - if (typeof options.port !== 'number' || - typeof options.host != 'string' - ) { - throw 'RLogin: invalid host or port argument.'; - } - - if (typeof options.clientUsername !== 'string') { - throw 'RLogin: invalid clientUsername argument.'; - } - - if (typeof options.serverUsername !== 'string') { - throw 'RLogin: invalid serverUsername argument.'; - } - - if (typeof options.terminalType !== 'string') { - throw 'RLogin: invalid terminalType argument.'; - } - - if (typeof options.terminalSpeed !== 'number') { - throw 'RLogin: invalid terminalSpeed argument.'; - } - - if (handle.connect(options.host, options.port)) { - handle.sendBin(0, 1); - handle.send(options.clientUsername); - handle.sendBin(0, 1); - handle.send(options.serverUsername); - handle.sendBin(0, 1); - handle.send(options.terminalType + '/' + options.terminalSpeed); - handle.sendBin(0, 1); - while (handle.is_connected && handle.nread < 1) { - mswait(5); - } - getServerData(); - } else { - throw 'RLogin: Unable to connect to server.'; - } - - } - - this.cycle = function () { - - if (!handle.is_connected) { - state.connected = false; - return; - } - - getServerData(); - - if (state.suspendInput || clientBuffer.length < 1) return; - - while (clientBuffer.length > 0) { - handle.sendBin(clientBuffer.shift(), 1); - } - - } - - this.disconnect = function () { - handle.close(); - state.connected = false; - } - -} - -try { - - wss = new WebSocketProxy(client); - - if (typeof wss.headers['Cookie'] == 'undefined') { - err('No cookie from WebSocket client.'); - } - - var cookie = null; - wss.headers['Cookie'].split(';').some( - function (e) { - if (e.search(/^\s*synchronet\=/) == 0) { - cookie = e; - return true; - } else { - return false; - } - } - ); - if (cookie === null) err('Invalid cookie from WebSocket client.'); - cookie = cookie.replace(/^\s*synchronet\=/, '').split(','); - - cookie[0] = parseInt(cookie[0]); - if (cookie.length < 2 || isNaN(cookie[0]) || cookie[0] < 1 || cookie[0] > system.lastuser) { - log('cookie ' + JSON.stringify(cookie)); - err('Invalid cookie from WebSocket client.'); - } - - var usr = new User(cookie[0]); - var session = getSession(usr.number); - if (!session) { - err('Unable to read web session file for user #' + usr.number); - } - if (cookie[1] != session.key) { - err('Session key mismatch for user #' + usr.number); - } - if (typeof session.xtrn !== 'string' || - typeof xtrn_area.prog[session.xtrn] === 'undefined' - ) { - err('Invalid external program code.'); - } - - var f = new File(file_cfgname(system.ctrl_dir, 'sbbs.ini')); - if (!f.open('r')) err('Unable to open sbbs.ini.'); - var ini = f.iniGetObject('BBS'); - f.close(); - - if (typeof ini.RLoginInterface === 'undefined') { - var rlogin_addr = '127.0.0.1'; - } else { - var rlogin_addr = ini.RLoginInterface.split(/,/)[0]; - var ra = parseInt(rlogin_addr.replace(/[^\d]/g, '')); - if (isNaN(ra) || ra == 0) rlogin_addr = '127.0.0.1'; - } - - rlogin = new RLoginClient( - { host : rlogin_addr, - port : ini.RLoginPort, - clientUsername : usr.security.password, - serverUsername : usr.alias, - terminalType : 'xtrn=' + session.xtrn, - terminalSpeed : 115200 - } - ); - rlogin.connect(); - log(LOG_DEBUG, usr.alias + ' logged on via RLogin for ' + session.xtrn); - - while (client.socket.is_connected && rlogin.connected) { - - wss.cycle(); - rlogin.cycle(); - - var send = rlogin.receive(); - if (send.length > 0) wss.send(send); - - while (wss.data_waiting) { - var data = wss.receiveArray(); - rlogin.send(data); - } - - mswait(5); - - } - -} catch (er) { - - log(LOG_ERR, er); - -} finally { - rlogin.disconnect(); - client.socket.close(); -} diff --git a/exec/websocket-telnet-service.js b/exec/websocket-telnet-service.js deleted file mode 100644 index 83b1cd5ed8..0000000000 --- a/exec/websocket-telnet-service.js +++ /dev/null @@ -1,284 +0,0 @@ -load('sbbsdefs.js'); -load('websocket-proxy.js'); -load('modopts.js'); - -function log_err(msg) { - log(LOG_DEBUG, msg); - client.socket.close(); - exit(); -} - -var TelnetClient = function(host, port) { - - var MAX_BUFFER = 32767; - - var TELNET_DATA = 0; - var TELNET_IAC = 1; - var TELNET_SUBNEGOTIATE = 2; - var TELNET_SUBNEGOTIATE_IAC = 3; - var TELNET_WILL = 4; - var TELNET_WONT = 5; - var TELNET_DO = 6; - var TELNET_DONT = 7; - - var TELNET_CMD_TTYLOC = 28; - - var state = TELNET_DATA; - - var buffers = { - rx : [], // From server - tx : [] // To server - }; - - var socket = new Socket(); - socket.connect(host, port); - - this.__defineGetter__( - 'connected', - function () { - return socket.is_connected; - } - ); - - this.__defineSetter__( - 'connected', - function (bool) { - if (!bool && socket.is_connected) { - socket.close(); - } else if (bool && !socket.is_connected) { - socket.connect(host, port); - } - } - ); - - this.__defineGetter__( - 'data_waiting', - function () { - return (buffers.rx.length > 0); - } - ); - - function receive() { - - var rx = []; - - while (socket.data_waiting && rx.length < MAX_BUFFER) { - var nr = (socket.nread >= 4 ? 4 : (socket.nread >= 2 ? 2 : 1)); - var bin = socket.recvBin(nr); - if (nr === 4) { - rx.push((bin&(255<<24))>>>24); - rx.push((bin&(255<<16))>>>16); - } - if (nr >= 2) rx.push((bin&(255<<8))>>>8); - rx.push(bin&255); - } - - while (rx.length > 0) { - var b = rx.shift(); - switch (state) { - case TELNET_DATA: - if (b == 0xFF) { - state = TELNET_IAC; - } else { - buffers.rx.push(b); - } - break; - case TELNET_IAC: - switch (b) { - case 0xF1: // NOP: No operation. - case 0xF2: // Data Mark: The data stream portion of a Synch. This should always be accompanied by a TCP Urgent notification. - case 0xF3: // Break: NVT character BRK. - case 0xF4: // Interrupt Process: The function IP. - case 0xF5: // Abort output: The function AO. - case 0xF6: // Are You There: The function AYT. - case 0xF7: // Erase character: The function EC. - case 0xF8: // Erase Line: The function EL. - case 0xF9: // Go ahead: The GA signal - // Ignore these single byte commands - state = TELNET_DATA; - break; - case 0xFA: // Subnegotiation - state = TELNET_SUBNEGOTIATE; - break; - case 0xFB: // Will - state = TELNET_WILL; - break; - case 0xFC: // Wont - state = TELNET_WONT; - break; - case 0xFD: // Do - state = TELNET_DO; - break; - case 0xFE: // Dont - state = TELNET_DONT; - break; - case 0xFF: - buffers.rx.push(0xFF); - state = TELNET_DATA; - break; - } - break; - case TELNET_SUBNEGOTIATE: - if (b == 0xFF) state = TELNET_SUBNEGOTIATE_IAC; - break; - case TELNET_SUBNEGOTIATE_IAC: - if (b == 0xFF) { - state = TELNET_SUBNEGOTIATE; - } else if (b == 0xF0) { - state = TELNET_DATA; - } else { - // Unexpected - state = TELNET_DATA; - } - break; - case TELNET_DO: - switch (b) { - // This will bork with IPV6 - case TELNET_CMD_TTYLOC: - socket.sendBin(255, 1); - socket.sendBin(250, 1); - socket.sendBin(28, 1); - socket.sendBin(0, 1); - client.ip_address.split('.').forEach( - function (e) { - e = parseInt(e); - socket.sendBin(e, 1); - if (e === 255) socket.sendBin(e, 1); - } - ); - client.ip_address.split('.').forEach( - function (e) { - e = parseInt(e); - socket.sendBin(e, 1); - if (e === 255) socket.sendBin(e, 1); - } - ); - socket.sendBin(255, 1); - socket.sendBin(240, 1); - break; - default: - break; - } - state = TELNET_DATA; - break; - case TELNET_WILL: - case TELNET_WONT: - case TELNET_DONT: - state = TELNET_DATA; - break; - default: - break; - } - } - - } - - function transmit() { - - if (!socket.is_connected || buffers.tx.length < 1) return; - - while (buffers.tx.length >= 4) { - var chunk = (buffers.tx.shift()<<24); - chunk |= (buffers.tx.shift()<<16); - chunk |= (buffers.tx.shift()<<8); - chunk |= buffers.tx.shift(); - socket.sendBin(chunk, 4); - } - - if (buffers.tx.length >= 2) { - var chunk = (buffers.tx.shift()<<8); - chunk |= buffers.tx.shift(); - socket.sendBin(chunk, 2); - } - - if (buffers.tx.length > 0) { - socket.sendBin(buffers.tx.shift(), 1); - } - - } - - this.receive = function () { - return buffers.rx.splice(0, buffers.rx.length); - } - - this.send = function (arr) { - - if (typeof arr === 'string') { - var arr = arr.map( - function (e) { - return ascii(e); - } - ); - } - - buffers.tx = buffers.tx.concat(arr); - - } - - this.cycle = function () { - receive(); - transmit(); - } - -} - -try { - - var f = new File(file_cfgname(system.ctrl_dir, 'sbbs.ini')); - if (!f.open('r')) log_err('Unable to open sbbs.ini.'); - var ini = f.iniGetObject('BBS'); - f.close(); - - if (typeof ini.TelnetInterface === 'undefined') { - var telnet_addr = '127.0.0.1'; - } else { - var telnet_addr = ini.TelnetInterface.split(/,/)[0]; - var ta = parseInt(telnet_addr.replace(/[^\d]/g, '') == 0); - if (isNaN(ta) || ta == 0) telnet_addr = '127.0.0.1'; - } - - var wss = new WebSocketProxy(client); - var wsspath = wss.headers.Path.split('/'); - if (wsspath.length < 3 || isNaN(parseInt(wsspath[2]))) { - var telnet = new TelnetClient(telnet_addr, ini.TelnetPort); - } else { - var _settings = get_mod_options('web'); - if (typeof _settings.allowed_ftelnet_targets !== 'string') { - throw 'Client supplied Path but no allowed_ftelnet_targets supplied in modopts.ini [web] section.'; - } - var targets = _settings.allowed_ftelnet_targets.split(','); - if (!targets.some(function (e) { var target = e.split(':'); return target[0] === wsspath[1] && target[1] === wsspath[2]; })) { - throw 'Client supplied Path is not in allowed_ftelnet_targets list.'; - } - log('Using client-supplied target ' + wsspath[1] + ':' + wsspath[2]); - var telnet = new TelnetClient(wsspath[1], parseInt(wsspath[2])); - } - - while (client.socket.is_connected && telnet.connected) { - - wss.cycle(); - telnet.cycle(); - - if (telnet.data_waiting) { - var data = telnet.receive(); - wss.send(data); - } - - while (wss.data_waiting) { - var data = wss.receiveArray(); - telnet.send(data); - } - - mswait(5); - - } - -} catch (err) { - - log(LOG_ERR, 'Caught: ' + err); - -} finally { - - client.socket.close(); - -} -- GitLab