From a92929f178ff0d2d4fc55bd30f93ea7a64462dd5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Mon, 29 Aug 2022 00:01:24 +0200 Subject: [PATCH] Fix UI WebSocket server protocol parsing at connection MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- .../ui-server/UIHttpServer.ts | 2 +- .../ui-server/UIWebSocketServer.ts | 16 +++++++---- .../ui-server/ui-services/UIServiceUtils.ts | 28 +++++++++++++------ 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/charging-station/ui-server/UIHttpServer.ts b/src/charging-station/ui-server/UIHttpServer.ts index 9f423ce4..de406110 100644 --- a/src/charging-station/ui-server/UIHttpServer.ts +++ b/src/charging-station/ui-server/UIHttpServer.ts @@ -80,7 +80,7 @@ export default class UIHttpServer extends AbstractUIServer { const uuid = Utils.generateUUID(); this.responseHandlers.set(uuid, { procedureName, res }); try { - if (UIServiceUtils.isProtocolSupported(protocol, version) === false) { + if (UIServiceUtils.isProtocolAndVersionSupported(protocol, version) === false) { throw new BaseError(`Unsupported UI protocol version: '/${protocol}/${version}'`); } req.on('error', (error) => { diff --git a/src/charging-station/ui-server/UIWebSocketServer.ts b/src/charging-station/ui-server/UIWebSocketServer.ts index e928f9ff..9cec37da 100644 --- a/src/charging-station/ui-server/UIWebSocketServer.ts +++ b/src/charging-station/ui-server/UIWebSocketServer.ts @@ -3,12 +3,12 @@ import type { IncomingMessage } from 'http'; import WebSocket from 'ws'; import type { ServerOptions } from '../../types/ConfigurationData'; -import { Protocol, ProtocolVersion } from '../../types/UIProtocol'; import Configuration from '../../utils/Configuration'; import logger from '../../utils/Logger'; import Utils from '../../utils/Utils'; import { AbstractUIServer } from './AbstractUIServer'; import UIServiceFactory from './ui-services/UIServiceFactory'; +import { UIServiceUtils } from './ui-services/UIServiceUtils'; const moduleName = 'UIWebSocketServer'; @@ -20,10 +20,16 @@ export default class UIWebSocketServer extends AbstractUIServer { public start(): void { this.server.on('connection', (socket: WebSocket, request: IncomingMessage): void => { - const protocolIndex = socket.protocol.indexOf(Protocol.UI); - const version = socket.protocol.substring( - protocolIndex + Protocol.UI.length - ) as ProtocolVersion; + const [protocol, version] = UIServiceUtils.getProtocolAndVersion(socket.protocol); + if (UIServiceUtils.isProtocolAndVersionSupported(protocol, version) === false) { + logger.error( + `${this.logPrefix( + moduleName, + 'start.server.onconnection' + )} Unsupported UI protocol version: '${protocol}${version}'` + ); + socket.close(); + } if (!this.uiServices.has(version)) { this.uiServices.set(version, UIServiceFactory.getUIServiceImplementation(version, this)); } diff --git a/src/charging-station/ui-server/ui-services/UIServiceUtils.ts b/src/charging-station/ui-server/ui-services/UIServiceUtils.ts index a824adaf..c0199828 100644 --- a/src/charging-station/ui-server/ui-services/UIServiceUtils.ts +++ b/src/charging-station/ui-server/ui-services/UIServiceUtils.ts @@ -13,17 +13,14 @@ export class UIServiceUtils { protocols: Set, request: IncomingMessage ): string | false => { - let protocolIndex: number; let protocol: Protocol; let version: ProtocolVersion; + if (protocols.size === 0) { + return false; + } for (const fullProtocol of protocols) { - protocolIndex = fullProtocol.indexOf(Protocol.UI); - protocol = fullProtocol.substring( - protocolIndex, - protocolIndex + Protocol.UI.length - ) as Protocol; - version = fullProtocol.substring(protocolIndex + Protocol.UI.length) as ProtocolVersion; - if (UIServiceUtils.isProtocolSupported(protocol, version) === true) { + [protocol, version] = UIServiceUtils.getProtocolAndVersion(fullProtocol); + if (UIServiceUtils.isProtocolAndVersionSupported(protocol, version) === true) { return fullProtocol; } } @@ -35,9 +32,22 @@ export class UIServiceUtils { return false; }; - public static isProtocolSupported = (protocol: Protocol, version: ProtocolVersion): boolean => + public static isProtocolAndVersionSupported = ( + protocol: Protocol, + version: ProtocolVersion + ): boolean => Object.values(Protocol).includes(protocol) && Object.values(ProtocolVersion).includes(version); + public static getProtocolAndVersion = (protocolStr: string): [Protocol, ProtocolVersion] => { + const protocolIndex = protocolStr.indexOf(Protocol.UI); + const protocol = protocolStr.substring( + protocolIndex, + protocolIndex + Protocol.UI.length + ) as Protocol; + const version = protocolStr.substring(protocolIndex + Protocol.UI.length) as ProtocolVersion; + return [protocol, version]; + }; + public static isLoopback(address: string): boolean { const isLoopbackRegExp = new RegExp( // eslint-disable-next-line no-useless-escape -- 2.34.1