]> source.dussan.org Git - tigervnc.git/commitdiff
Move UserPasswordGetter out of CConn
authorBrian P. Hinz <bphinz@users.sf.net>
Fri, 1 Dec 2017 02:14:25 +0000 (21:14 -0500)
committerBrian P. Hinz <bphinz@users.sf.net>
Fri, 1 Dec 2017 02:18:29 +0000 (21:18 -0500)
java/com/tigervnc/rfb/CSecurity.java
java/com/tigervnc/rfb/CSecurityIdent.java
java/com/tigervnc/rfb/CSecurityPlain.java
java/com/tigervnc/rfb/CSecurityTLS.java
java/com/tigervnc/rfb/CSecurityVeNCrypt.java
java/com/tigervnc/rfb/CSecurityVncAuth.java
java/com/tigervnc/rfb/SecurityClient.java
java/com/tigervnc/rfb/UserPasswdGetter.java
java/com/tigervnc/vncviewer/CConn.java
java/com/tigervnc/vncviewer/UserDialog.java [new file with mode: 0644]
java/com/tigervnc/vncviewer/VncViewer.java

index f67680cd6d9b946d50f4c8fa06c9a62daef60f6c..a99a5f87794cc4220ad3e66590a752dd440c1d2a 100644 (file)
@@ -42,5 +42,5 @@ abstract public class CSecurity {
    * Use variable directly instead of dumb get/set methods.
    * It MUST be set by viewer.
    */
-  static UserPasswdGetter upg;
+  public static UserPasswdGetter upg;
 }
index 9eb6e0b64a17ee57731486a60d9e6e741e0b7b5a..e53432bf7652f3f7754455552c3fa5eaced69ec7 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Brian P. Hinz
+/* Copyright (C) 2011-2017 Brian P. Hinz
  *
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -30,7 +30,7 @@ public class CSecurityIdent extends CSecurity {
 
     StringBuffer username = new StringBuffer();
 
-    CConn.upg.getUserPasswd(username, null);
+    upg.getUserPasswd(username, null);
 
     // Return the response to the server
     os.writeU32(username.length());
@@ -46,9 +46,6 @@ public class CSecurityIdent extends CSecurity {
 
   public int getType() { return Security.secTypeIdent; }
 
-  java.net.Socket sock;
-  UserPasswdGetter upg;
-
   static LogWriter vlog = new LogWriter("Ident");
   public String description() { return "No Encryption"; }
 
index d6f8ffde4838a22451928e7ae71ffb03c3839925..98f6b8cc5177b5d9fc1420dc7d6a7e9be332f2f5 100644 (file)
@@ -1,6 +1,6 @@
 /* Copyright (C) 2005 Martin Koegler
  * Copyright (C) 2010 TigerVNC Team
- * Copyright (C) 2011 Brian P. Hinz
+ * Copyright (C) 2011-2017 Brian P. Hinz
  *
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -34,7 +34,7 @@ public class CSecurityPlain extends CSecurity {
     StringBuffer username = new StringBuffer();
     StringBuffer password = new StringBuffer();
 
-    CConn.upg.getUserPasswd(username, password);
+    upg.getUserPasswd(username, password);
 
     // Return the response to the server
     os.writeU32(username.length());
index 733e97d42d450b25b07f3b1bfc4fa2a2bcb0bac7..c91f36a1e66e01ba00959db502dc1d4c88de61db 100644 (file)
@@ -56,6 +56,8 @@ import com.tigervnc.rdr.*;
 import com.tigervnc.network.*;
 import com.tigervnc.vncviewer.*;
 
+import static javax.swing.JOptionPane.*;
+
 public class CSecurityTLS extends CSecurity {
 
   public static StringParameter X509CA
@@ -64,6 +66,7 @@ public class CSecurityTLS extends CSecurity {
   public static StringParameter X509CRL
   = new StringParameter("X509CRL",
                         "X509 CRL file", "", Configuration.ConfigurationObject.ConfViewer);
+  public static UserMsgBox msg;
 
   private void initGlobal()
   {
@@ -254,6 +257,16 @@ public class CSecurityTLS extends CSecurity {
     {
       Collection<? extends Certificate> certs = null;
       X509Certificate cert = chain[0];
+      try {
+        cert.checkValidity();
+      } catch(CertificateNotYetValidException e) {
+        throw new AuthFailureException("server certificate has not been activated");
+      } catch(CertificateExpiredException e) {
+        if (!msg.showMsgBox(YES_NO_OPTION, "certificate has expired",
+                             "The certificate of the server has expired, "+
+                             "do you want to continue?"))
+          throw new AuthFailureException("server certificate has expired");
+      }
       String thumbprint = getThumbprint(cert);
       File vncDir = new File(FileUtils.getVncHomeDir());
       File certFile = new File(vncDir, "x509_savedcerts.pem");
@@ -270,8 +283,7 @@ public class CSecurityTLS extends CSecurity {
         tm.checkServerTrusted(chain, authType);
       } catch (java.lang.Exception e) {
         if (e.getCause() instanceof CertPathBuilderException) {
-          Object[] answer = {"YES", "NO"};
-          int ret = JOptionPane.showOptionDialog(null,
+          String certinfo =
             "This certificate has been signed by an unknown authority\n"+
             "\n"+
             "  Subject: "+cert.getSubjectX500Principal().getName()+"\n"+
@@ -283,46 +295,38 @@ public class CSecurityTLS extends CSecurity {
             "  Not Valid After: "+cert.getNotAfter()+"\n"+
             "  SHA1 Fingerprint: "+getThumbprint(cert)+"\n"+
             "\n"+
-            "Do you want to save it and continue?",
-            "Certificate Issuer Unknown",
-            JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE,
-            null, answer, answer[0]);
-          if (ret == JOptionPane.YES_OPTION) {
+            "Do you want to save it and continue?";
+          if (!msg.showMsgBox(YES_NO_OPTION, "certificate issuer unknown",
+                certinfo)) {
+            throw new AuthFailureException("certificate issuer unknown");
+          }
+          if (certs == null || !certs.contains(cert)) {
+            byte[] der = cert.getEncoded();
+            String pem = DatatypeConverter.printBase64Binary(der);
+            pem = pem.replaceAll("(.{64})", "$1\n");
+            FileWriter fw = null;
             try {
               if (!vncDir.exists())
                 vncDir.mkdir();
               if (!certFile.exists() && !certFile.createNewFile()) {
                 vlog.error("Certificate save failed.");
-                return;
-              }
-            } catch (java.lang.Exception ioe) {
-              // skip save if security settings prohibit access to filesystem
-              vlog.error("Certificate save failed: "+ioe.getMessage());
-              return;
-            }
-            if (certs == null || !certs.contains(cert)) {
-              byte[] der = cert.getEncoded();
-              String pem = DatatypeConverter.printBase64Binary(der);
-              pem = pem.replaceAll("(.{64})", "$1\n");
-              FileWriter fw = null;
-              try {
+              } else {
                 fw = new FileWriter(certFile.getAbsolutePath(), true);
                 fw.write("-----BEGIN CERTIFICATE-----\n");
                 fw.write(pem+"\n");
                 fw.write("-----END CERTIFICATE-----\n");
-              } catch (IOException ioe) {
-                throw new Exception(ioe.getMessage());
-              } finally {
-                try {
-                  if (fw != null)
-                    fw.close();
-                } catch(IOException ioe2) {
-                  throw new Exception(ioe2.getMessage());
-                }
+              }
+            } catch (IOException ioe) {
+              msg.showMsgBox(OK_OPTION, "certificate save failed",
+                             "Could not save the certificate");
+            } finally {
+              try {
+                if (fw != null)
+                  fw.close();
+              } catch(IOException ioe2) {
+                throw new Exception(ioe2.getMessage());
               }
             }
-          } else {
-            throw new WarningException("Peer certificate verification failed.");
           }
         } else {
           throw new SystemException(e.getMessage());
index 179900a4cec560d90f50fbf855a8c297da59a82b..daf205cda6a2445ebca8f704777a4982e46efc56 100644 (file)
@@ -178,7 +178,13 @@ public class CSecurityVeNCrypt extends CSecurity {
   }
 
   public final int getType() { return chosenType; }
-  public final String description() { return Security.secTypeName(chosenType); }
+  public final String description()
+  {
+    if (csecurity != null)
+      return csecurity.description();
+    return "VeNCrypt";
+  }
+
 
   public static StringParameter secTypesStr;
 
index e053e4109340032f90849a96a393f168a16f9ab0..e8c5686d1cf94ad823505b7709c5167218c18a7b 100644 (file)
@@ -36,7 +36,7 @@ public class CSecurityVncAuth extends CSecurity {
     byte[] challenge = new byte[vncAuthChallengeSize];
     is.readBytes(challenge, 0, vncAuthChallengeSize);
     StringBuffer passwd = new StringBuffer();
-    CConn.upg.getUserPasswd(null, passwd);
+    upg.getUserPasswd(null, passwd);
 
     // Calculate the correct response
     byte[] key = new byte[8];
index ff2433c27fe779bd55be5f373cfd608505f79217..d3557337f1fde489999af3ed4dc0283cc48f72b8 100644 (file)
@@ -1,6 +1,6 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
  * Copyright (C) 2010 TigerVNC Team
- * Copyright (C) 2011-2012 Brian P. Hinz
+ * Copyright (C) 2011-2017 Brian P. Hinz
  *
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 package com.tigervnc.rfb;
 
-import com.tigervnc.vncviewer.CConn;
-
 public class SecurityClient extends Security {
 
   public SecurityClient() { super(secTypes); }
 
   public CSecurity GetCSecurity(int secType)
   {
-    assert (CConn.upg != null); /* (upg == null) means bug in the viewer */
-    assert (msg != null);
+    assert (CSecurity.upg != null); /* (upg == null) means bug in the viewer */
+    assert (CSecurityTLS.msg != null);
 
     if (!IsSupported(secType))
       throw new Exception("Security type not supported");
@@ -75,9 +73,6 @@ public class SecurityClient extends Security {
       CSecurityTLS.setDefaults();
   }
 
-  //UserPasswdGetter upg = null;
-  String msg = null;
-
   public static StringParameter secTypes
   = new StringParameter("SecurityTypes",
                         "Specify which security scheme to use (None, VncAuth, Plain, Ident, TLSNone, TLSVnc, TLSPlain, TLSIdent, X509None, X509Vnc, X509Plain, X509Ident)",
index feb05ed157fd554cf5d734e6c4b1f963ba5d1bae..7390b11a20a6c8207bc552092e8446cbd8a6a5b0 100644 (file)
@@ -23,5 +23,5 @@
 package com.tigervnc.rfb;
 
 public interface UserPasswdGetter {
-  public boolean getUserPasswd(StringBuffer user, StringBuffer password);
+  public void getUserPasswd(StringBuffer user, StringBuffer password);
 }
index d71c307f929e8a3b5d43c37cd2668a51e2825621..3aee46d570fa0935022c24959bce1f520fd64ab7 100644 (file)
@@ -63,7 +63,7 @@ import com.tigervnc.network.TcpSocket;
 import static com.tigervnc.vncviewer.Parameters.*;
 
 public class CConn extends CConnection implements 
-  UserPasswdGetter, FdInStreamBlockCallback, ActionListener {
+  FdInStreamBlockCallback, ActionListener {
 
   // 8 colours (1 bit per component)
   static final PixelFormat verylowColorPF =
@@ -92,8 +92,6 @@ public class CConn extends CConnection implements
     setShared(shared.getValue());
     sock = socket;
 
-    upg = this;
-
     int encNum = Encodings.encodingNum(preferredEncoding.getValue());
     if (encNum != -1)
       currentEncoding = encNum;
@@ -208,58 +206,6 @@ public class CConn extends CConnection implements
     }
   }
 
-  // getUserPasswd() is called by the CSecurity object when it needs us to read
-  // a password from the user.
-
-  public final boolean getUserPasswd(StringBuffer user, StringBuffer passwd) {
-    String title = ("VNC Authentication ["
-                    +csecurity.description() + "]");
-    String passwordFileStr = passwordFile.getValue();
-    PasswdDialog dlg;
-
-    if (user == null && !passwordFileStr.equals("")) {
-      InputStream fp = null;
-      try {
-        fp = new FileInputStream(passwordFileStr);
-      } catch(FileNotFoundException e) {
-        throw new Exception("Opening password file failed");
-      }
-      byte[] obfPwd = new byte[256];
-      try {
-        fp.read(obfPwd);
-        fp.close();
-      } catch(IOException e) {
-        throw new Exception("Failed to read VncPasswd file");
-      }
-      String PlainPasswd = VncAuth.unobfuscatePasswd(obfPwd);
-      passwd.append(PlainPasswd);
-      passwd.setLength(PlainPasswd.length());
-      return true;
-    }
-
-    if (user == null) {
-      dlg = new PasswdDialog(title, (user == null), (passwd == null));
-    } else {
-      if ((passwd == null) && sendLocalUsername.getValue()) {
-         user.append((String)System.getProperties().get("user.name"));
-         return true;
-      }
-      dlg = new PasswdDialog(title, sendLocalUsername.getValue(),
-         (passwd == null));
-    }
-    dlg.showDialog();
-    if (user != null) {
-      if (sendLocalUsername.getValue()) {
-         user.append((String)System.getProperties().get("user.name"));
-      } else {
-         user.append(dlg.userEntry.getText());
-      }
-    }
-    if (passwd != null)
-      passwd.append(new String(dlg.passwdEntry.getPassword()));
-    return true;
-  }
-
   ////////////////////// CConnection callback methods //////////////////////
 
   // serverInit() is called when the serverInit message has been received.  At
@@ -729,8 +675,6 @@ public class CConn extends CConnection implements
 
   // the following need no synchronization:
 
-  public static UserPasswdGetter upg;
-
   // shuttingDown is set by the GUI thread and only ever tested by the RFB
   // thread after the window has been destroyed.
   boolean shuttingDown = false;
diff --git a/java/com/tigervnc/vncviewer/UserDialog.java b/java/com/tigervnc/vncviewer/UserDialog.java
new file mode 100644 (file)
index 0000000..fad836a
--- /dev/null
@@ -0,0 +1,187 @@
+/* Copyright (C) 2017 Brian P. Hinz
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+package com.tigervnc.vncviewer;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.border.*;
+import javax.swing.plaf.LayerUI;
+
+import com.tigervnc.rfb.*;
+import com.tigervnc.rfb.Point;
+import com.tigervnc.rfb.Exception;
+
+import static com.tigervnc.vncviewer.Parameters.*;
+import static javax.swing.GroupLayout.*;
+import static javax.swing.JOptionPane.*;
+
+
+public class UserDialog implements UserPasswdGetter, UserMsgBox
+{
+  private class MyLayerUI extends LayerUI {
+    // Using a JButton for the "?" icon yields the best look, but there
+    // does not seem to be any reasonable way to disable a JButton without
+    // also changing the color.  This wrapper just intercepts any mouse
+    // click events so that the button just looks like an icon.
+    @Override
+    public void eventDispatched(AWTEvent e, JLayer l) {
+      if (e instanceof InputEvent)
+        ((InputEvent) e).consume();
+    }
+
+    @Override
+    public void installUI(JComponent c) {
+      super.installUI(c);
+      if (c instanceof JLayer) {
+        JLayer<?> layer = (JLayer<?>)c;
+        layer.setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK);
+      }
+    }
+
+    @Override
+    protected void processMouseEvent(MouseEvent e, JLayer l) {
+      super.processMouseEvent(e, l);
+    }
+  }
+
+  public final void getUserPasswd(StringBuffer user, StringBuffer password)
+  {
+    String passwordFileStr = passwordFile.getValue();
+
+    if ((password == null) && sendLocalUsername.getValue()) {
+      user.append((String)System.getProperties().get("user.name"));
+      return;
+    }
+
+    if (user == null && !passwordFileStr.equals("")) {
+      InputStream fp = null;
+      try {
+        fp = new FileInputStream(passwordFileStr);
+      } catch(FileNotFoundException e) {
+        throw new Exception("Opening password file failed");
+      }
+      byte[] obfPwd = new byte[256];
+      try {
+        fp.read(obfPwd);
+        fp.close();
+      } catch(IOException e) {
+        throw new Exception("Failed to read VncPasswd file");
+      }
+      String PlainPasswd = VncAuth.unobfuscatePasswd(obfPwd);
+      password.append(PlainPasswd);
+      password.setLength(PlainPasswd.length());
+      return;
+    }
+
+    JDialog win;
+    JTextField username = null;
+    JPasswordField passwd = null;
+    JLayer icon;
+
+    int y;
+
+    JPanel msg = new JPanel(null);
+    msg.setSize(410, 145);
+
+    y = 10;
+
+    JButton iconb = new JButton("?");
+    iconb.setVerticalAlignment(JLabel.CENTER);
+    iconb.setFont(new Font("Times", Font.BOLD, 34));
+    iconb.setForeground(Color.BLUE);
+    LayerUI ui = new MyLayerUI();
+    icon = new JLayer(iconb, ui);
+    icon.setBounds(10, y, 50, 50);
+    msg.add(icon);
+
+    y += 5;
+
+    if (user != null && !sendLocalUsername.getValue()) {
+      JLabel userLabel = new JLabel("Username:");
+      userLabel.setBounds(70, y, msg.getSize().width-70-10, 20);
+      msg.add(userLabel);
+      y += 20 + 5;
+      username = new JTextField(30);
+      username.setBounds(70, y, msg.getSize().width-70-10, 25);
+      msg.add(username);
+      y += 25 + 5;
+    }
+
+    JLabel passwdLabel = new JLabel("Password:");
+    passwdLabel.setBounds(70, y, msg.getSize().width-70-10, 20);
+    msg.add(passwdLabel);
+    y += 20 + 5;
+    passwd = new JPasswordField(30);
+    passwd.setBounds(70, y, msg.getSize().width-70-10, 25);
+    msg.add(passwd);
+    y += 25 + 5;
+
+    msg.setPreferredSize(new Dimension(410, y));
+
+    Object[] options = {"OK  \u21B5", "Cancel"};
+    JOptionPane pane = new JOptionPane(msg,
+                                      PLAIN_MESSAGE,
+                                      OK_CANCEL_OPTION,
+                                      null,       //do not use a custom Icon
+                                      options,    //the titles of buttons
+                                      options[0]);//default button title
+    pane.setBorder(new EmptyBorder(0,0,0,0));
+    Component c = pane.getComponent(pane.getComponentCount()-1);
+    ((JComponent)c).setBorder(new EmptyBorder(0,0,10,10));
+    win = pane.createDialog("VNC Authentication");
+
+    win.setVisible(true);
+
+    if (pane.getValue() == null || pane.getValue().equals("Cancel"))
+      throw new Exception("Authentication cancelled");
+
+    if (user != null)
+      if (sendLocalUsername.getValue())
+         user.append((String)System.getProperties().get("user.name"));
+      else
+         user.append(username.getText());
+    if (password != null)
+      password.append(new String(passwd.getPassword()));
+  }
+
+  public boolean showMsgBox(int flags, String title, String text)
+  {
+    switch (flags & 0xf) {
+    case OK_CANCEL_OPTION:
+      return (showConfirmDialog(null, text, title, OK_CANCEL_OPTION) == OK_OPTION);
+    case YES_NO_OPTION:
+      return (showConfirmDialog(null, text, title, YES_NO_OPTION) == YES_OPTION);
+    default:
+      if (((flags & 0xf0) == ERROR_MESSAGE) ||
+          ((flags & 0xf0) == WARNING_MESSAGE))
+        showMessageDialog(null, text, title, (flags & 0xf0));
+      else
+        showMessageDialog(null, text, title, PLAIN_MESSAGE);
+      return true;
+    }
+  }
+}
index 8786c11d62215e58658677c70f8da72f5293e982..74f2ca37b394678b0e89687a252cdceb319cb3fb 100644 (file)
@@ -486,6 +486,9 @@ public class VncViewer extends javax.swing.JApplet
 
   public void run() {
     cc = null;
+    UserDialog dlg = new UserDialog();
+    CSecurity.upg = dlg;
+    CSecurityTLS.msg = dlg;
     Socket sock = null;
 
     /* Specifying -via and -listen together is nonsense */