You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by GitBox <gi...@apache.org> on 2022/12/22 14:27:34 UTC

[GitHub] [cloudstack] nvazquez commented on a diff in pull request #7015: Secure KVM VNC Console Access Using the CA Framework

nvazquez commented on code in PR #7015:
URL: https://github.com/apache/cloudstack/pull/7015#discussion_r1055519078


##########
services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/NoVncClient.java:
##########
@@ -239,16 +273,349 @@ public byte[] encodePassword(byte[] challenge, String password) throws Exception
         return response;
     }
 
+    /**
+     * Decide the RFB protocol version with the VNC server
+     * Reference: https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst#711protocolversion
+     */
+    protected String handshakeProtocolVersion(RemoteEndpoint clientRemote) throws IOException {
+        // Read protocol version
+        byte[] buf = new byte[12];
+        tunnelInputStream.readFully(buf);
+        String rfbProtocol = new String(buf);
+
+        // Server should use RFB protocol 3.x
+        if (!rfbProtocol.contains(RfbConstants.RFB_PROTOCOL_VERSION_MAJOR)) {
+            s_logger.error("Cannot handshake with VNC server. Unsupported protocol version: \"" + rfbProtocol + "\".");
+            throw new RuntimeException(
+                    "Cannot handshake with VNC server. Unsupported protocol version: \"" + rfbProtocol + "\".");
+        }
+        tunnelOutputStream.write(buf);
+        return RfbConstants.RFB_PROTOCOL_VERSION + "\n";
+    }
+
+    /**
+     * Agree on the security type with the VNC server
+     * Reference: https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst#712security
+     * @return list of the security types to be processed
+     */
+    protected List<VncSecurity> handshakeSecurityTypes(RemoteEndpoint clientRemote, String vmPassword,
+                                                       String host, int port) throws IOException {
+        int securityType = selectFromTheServerOfferedSecurityTypes();
+
+        // Inform the server about our decision
+        this.tunnelOutputStream.writeByte(securityType);
+
+        byte[] numberTypesToClient = new byte[] { 1, (byte) securityType };
+        clientRemote.sendBytes(ByteBuffer.wrap(numberTypesToClient, 0, 2));
+
+        if (securityType == RfbConstants.V_ENCRYPT) {
+            securityType = getVEncryptSecuritySubtype();
+        }
+        return VncSecurity.getSecurityStack(securityType, vmPassword, host, port);
+    }
+
+    /**
+     * Obtain the VEncrypt subtype from the VNC server
+     *
+     * Reference: https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst#724vencrypt
+     */
+    protected int getVEncryptSecuritySubtype() throws IOException {
+        int majorVEncryptVersion = socketConnection.readUnsignedInteger(8);
+        int minorVEncryptVersion = socketConnection.readUnsignedInteger(8);
+        int vEncryptVersion = (majorVEncryptVersion << 8) | minorVEncryptVersion;
+        s_logger.debug("VEncrypt version: " + vEncryptVersion);
+        socketConnection.writeUnsignedInteger(8, majorVEncryptVersion);
+        if (vEncryptVersion >= 0x0002) {
+            socketConnection.writeUnsignedInteger(8, 2);
+            socketConnection.flushWriteBuffer();
+        } else {
+            socketConnection.writeUnsignedInteger(8, 0);
+            socketConnection.flushWriteBuffer();
+            throw new CloudRuntimeException("Server reported an unsupported VeNCrypt version");
+        }
+        int ack = socketConnection.readUnsignedInteger(8);
+        if (ack != 0) {
+            throw new IOException("The VNC server did not agree on the VEncrypt version");
+        }
+
+        int numberOfSubtypes = socketConnection.readUnsignedInteger(8);
+        if (numberOfSubtypes <= 0) {
+            throw new CloudRuntimeException("The server reported no VeNCrypt sub-types");
+        }
+        int selectedSubtype = 0;
+        for (int i = 0; i < numberOfSubtypes; i++) {
+            while (!socketConnection.checkIfBytesAreAvailableForReading(4)) {
+                s_logger.trace("Waiting for vEncrypt subtype");
+            }
+            int subtype = socketConnection.readUnsignedInteger(32);
+            if (subtype == RfbConstants.V_ENCRYPT_X509_VNC) {
+                selectedSubtype = subtype;
+                break;
+            }
+        }
+
+        s_logger.info("Selected VEncrypt subtype " + selectedSubtype);
+        socketConnection.writeUnsignedInteger(32, selectedSubtype);
+        socketConnection.flushWriteBuffer();
+
+        return selectedSubtype;
+    }
+
+    private int selectFromTheServerOfferedSecurityTypes() throws IOException {
+        int numberOfSecurityTypes = tunnelInputStream.readByte();
+        if (numberOfSecurityTypes == 0) {
+            int reasonLength = tunnelInputStream.readInt();
+            byte[] reasonBuffer = new byte[reasonLength];
+            tunnelInputStream.readFully(reasonBuffer);
+            String reason = new String(reasonBuffer);
+            String errMsg = "No security type provided by the VNC server, reason: " + reason;
+            s_logger.error(errMsg);
+            throw new IOException(errMsg);
+        }
+
+        for (int i = 0; i < numberOfSecurityTypes; i++) {
+            int securityType = tunnelInputStream.readByte();
+            if (securityType != 0 && VncSecurity.supportedSecurityTypes.contains(securityType)) {
+                s_logger.info("Selected the security type: " + securityType);
+                return securityType;
+            }
+        }
+        throw new IOException("Could not select a supported or valid security type from the offered by the server");
+    }
+
+    /**
+     * VNC authentication.
+     */
+    public void processSecurityResult(String password)

Review Comment:
   Thanks, removed



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org