Fix UI WebSocket server protocol parsing at connection
authorJérôme Benoit <jerome.benoit@sap.com>
Sun, 28 Aug 2022 22:01:24 +0000 (00:01 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Sun, 28 Aug 2022 22:01:24 +0000 (00:01 +0200)
Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
src/charging-station/ui-server/UIHttpServer.ts
src/charging-station/ui-server/UIWebSocketServer.ts
src/charging-station/ui-server/ui-services/UIServiceUtils.ts

index 9f423ce4157a61d5aa89f25e417dbf34765ad930..de4061106619d4985365d778ee959547fa080c6b 100644 (file)
@@ -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) => {
index e928f9ffae685e9efcf56aeb8d49a88bb7e109d0..9cec37da847f98362e64765c297e9496463082b0 100644 (file)
@@ -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));
       }
index a824adaf2b052415f8980be108d1424fad8a7e10..c019982854c22d73bcc446ca3a2ecc56caa1aca1 100644 (file)
@@ -13,17 +13,14 @@ export class UIServiceUtils {
     protocols: Set<string>,
     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