cscg24-guacamole

CSCG 2024 Challenge 'Guacamole Mashup'
git clone https://git.sinitax.com/sinitax/cscg24-guacamole
Log | Files | Refs | sfeed.txt

App.js (5497B)


      1import React from 'react';
      2import Guacamole from 'guacamole-common-js';
      3import crypto from "crypto";
      4import { Buffer } from 'buffer';
      5import './App.css';
      6
      7const CIPHER = 'aes-256-cbc';
      8//const KEY = 'x9h9Ab3Bhz0LTleMygDVQQvkqWocr5EV';
      9const KEY = 'https://en.wikipedia.org/wiki/Se';
     10
     11
     12function encryptToken(value) {
     13  const iv = crypto.randomBytes(16);
     14  const cipher = crypto.createCipheriv(CIPHER, Buffer.from(KEY), iv);
     15
     16  let encrypted = cipher.update(JSON.stringify(value), 'utf8', 'base64');
     17  encrypted += cipher.final('base64');
     18
     19  const data = {
     20    iv: iv.toString('base64'),
     21    value: encrypted
     22  };
     23
     24  const json = JSON.stringify(data);
     25  return Buffer.from(json).toString('base64');
     26}
     27
     28
     29const GuacamoleApp = () => {
     30  var guac_backend_host = process.env.REACT_APP_GUAC_BACKEND_HOSTNAME;
     31  var win_server_host = process.env.REACT_APP_WIN_SERVER_HOSTNAME;
     32
     33  const handleSelectSSH = (event) => {
     34    document.getElementById("port").value = "50022";
     35    document.getElementById("ssh").checked = true;
     36  }
     37
     38  const handleSelectRDP = (event) => {
     39    document.getElementById("port").value = "3389";
     40    document.getElementById("rdp").checked = true;
     41  }
     42
     43  const handleSelectVNC = (event) => {
     44    document.getElementById("port").value = "5900";
     45    document.getElementById("vnc").checked = true;
     46  }
     47
     48  const openGc = async () => {
     49    window.Buffer = Buffer;
     50    try {
     51      var ele = document.getElementsByTagName('input');
     52      var protocol_type = "";
     53      var port = document.getElementById("port").value;
     54      for (var i = 0; i < ele.length; i++) {
     55        if (ele[i].type === "radio") {
     56          if (ele[i].checked)
     57            protocol_type = ele[i].value;
     58        }
     59      }
     60      const tokenObject = {
     61        connection: {
     62          type: protocol_type,
     63          settings: {
     64            "hostname": win_server_host,
     65            "port": port,
     66            "username": "Administrator",
     67            "password": "vagrant",
     68            "security": "any",
     69            "ignore-cert": true,
     70            "enable-wallpaper": true,
     71            "enable-drive": true,
     72            "drive-name": "root",
     73            "drive-path": "/",
     74            "disable-download": false,
     75            "disable-upload": false,
     76            "create-drive-path": false,
     77          }
     78        }
     79      };
     80
     81      const token = encryptToken(tokenObject);
     82      var wsurl = guac_backend_host;
     83
     84      console.log(tokenObject);
     85      console.log(wsurl);
     86      const gc = await new Guacamole.Client(new Guacamole.WebSocketTunnel(wsurl));
     87      const display = document.getElementById('gcdisplay');
     88      const element = gc.getDisplay().getElement();
     89
     90      if (display) {
     91        display?.appendChild(element);
     92      }
     93
     94      // gc.onfile = function(stream, mimetype, filename) {
     95      //   console.log("ONFILE", stream, mimetype, filename);
     96      // };
     97
     98      // gc.onfilesystem = function(stream, mimetype, filename) {
     99      //   console.log("ONFILESYSTEM", stream, mimetype, filename);
    100      //   stream.requestInputStream("/flag.txt", function(stream, mimetype) {
    101      //     console.log("INPUTSTREAM", stream, mimetype);
    102      //     stream.onblob = function(data) {
    103      //       console.log("ONBLOB", data);
    104      //       stream.sendAck("OK", 0);
    105      //     }
    106      //     stream.onend = function() {
    107      //       console.log("ONEND");
    108      //     }
    109      //     stream.sendAck("OK", 0);
    110      //   });
    111
    112      // };
    113
    114    gc.onerror = function(status) {
    115        console.log("ONERROR", status);
    116    }
    117
    118      gc.connect(`token=${token}&height=800&width=` + document.getElementById("gcdisplay").offsetWidth.toString());
    119
    120      // Error handler
    121      gc.onerror = (error) => console.log(error.message);
    122      window.onunload = () => gc.disconnect();
    123
    124      global.client = gc;
    125
    126      // Mouse
    127      const mouse = new Guacamole.Mouse(gc.getDisplay().getElement());
    128
    129
    130      // Forward all mouse interaction over Guacamole connection
    131      mouse.onEach(['mousedown', 'mousemove', 'mouseup'], function sendMouseEvent(e) {
    132        gc.sendMouseState(e.state, true);
    133      });
    134
    135
    136      // Hide software cursor when mouse leaves display
    137      mouse.on('mouseout', function hideCursor() {
    138        gc.getDisplay().showCursor(false);
    139      });
    140      const keyboard = new Guacamole.Keyboard(document);
    141      keyboard.onkeydown = (keysym) => gc.sendKeyEvent(1, keysym);
    142      keyboard.onkeyup = (keysym) => gc.sendKeyEvent(0, keysym);
    143
    144    } catch (error) {
    145      console.log("GC Error", error);
    146    }
    147  }
    148  return <div style={{ width: '100%' }}>
    149    <h1>Guacamole Connect RDP/SSH/VNC</h1>
    150    <fieldset width="100px">
    151      <legend>Select your connection method</legend>
    152
    153      <div>
    154        <input type="radio" id="ssh" name="connection_type" value="ssh" onChange={handleSelectSSH} />
    155        <label htmlFor="SSH">SSH</label>
    156      </div>
    157
    158      <div>
    159        <input type="radio" id="rdp" name="connection_type" value="rdp" onChange={handleSelectRDP} />
    160        <label htmlFor="RDP">RDP</label>
    161      </div>
    162
    163      <div>
    164        <input type="radio" id="vnc" name="connection_type" value="vnc" onChange={handleSelectVNC} />
    165        <label htmlFor="VNC">VNC</label>
    166      </div>
    167
    168    </fieldset>
    169    <div>
    170      Port:
    171      <input type="text" id="port" name="port" defaultValue="3389" />
    172    </div>
    173    <br></br>
    174    <button onClick={openGc}>Open Guacamole</button>
    175    <br />
    176    <div className="box">
    177      <div id='gcdisplay' className="content"><p>content</p></div>
    178    </div>
    179  </div>
    180}
    181export default GuacamoleApp;
    182