'Internal SSH' should allows users to check remote host key.

"Atsuhiko Yamanaka" <[email protected]> Sat, 18 Mar 2006 00:17:40 +0900
Newsgroups gmane.comp.java.netbeans.modules.javacvs.devel
Message-ID <[email protected]>
------=_Part_3380_31880525.1142608660167
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Hi,

The current implementation of 'Internal SSH client' included in javacvs mod=
ule
does not allow users to check the remote host key.  It just accepts the giv=
en
host key and does not do any check for it.  It is terrible for
man-in-the-middle attack, isn't it?
The attached patch will change this behavior, as follows,
  - referring to ~/.ssh/known_hosts file and storing accepted host key into=
 it.
  - showing a warning window if remote host key is not included in
known_hosts file.

Sincerely,
--
Atsuhiko Yamanaka
JCraft,Inc.
1-14-20 HONCHO AOBA-KU,
SENDAI, MIYAGI 980-0014 Japan.
Tel +81-22-723-2150
    +1-415-578-3454
Fax +81-22-224-8773
Skype callto://jcraft/

------=_Part_3380_31880525.1142608660167
Content-Type: text/plain; name=SSHConnection.java.1.7.3.patch; 
	charset=us-ascii
Content-Transfer-Encoding: 7bit
X-Attachment-Id: f_ekwnm1bk
Content-Disposition: attachment; filename="SSHConnection.java.1.7.3.patch"

# This patch file was generated by NetBeans IDE
# Following Index: paths are relative to: C:\Documents and Settings\ymnk\nb_all\javacvs\cvsmodule
# This patch can be applied using context Tools: Patch action on respective folder.
# It uses platform neutral UTF-8 encoding and \n newlines.
# Above lines and this line are ignored by the patching process.
Index: src/org/netbeans/modules/versioning/system/cvss/SSHConnection.java
*** C:\Documents and Settings\ymnk\nb_all\javacvs\cvsmodule\src\org\netbeans\modules\versioning\system\cvss\SSHConnection.java Base (1.7)
--- C:\Documents and Settings\ymnk\nb_all\javacvs\cvsmodule\src\org\netbeans\modules\versioning\system\cvss\SSHConnection.java Locally Modified (Based On 1.7)
***************
*** 25,30 ****
--- 25,31 ----
  import java.util.*;
  import java.net.Socket;
  import java.net.UnknownHostException;
+ import javax.swing.*;
  
  import com.jcraft.jsch.*;
  import org.openide.util.NbBundle;
***************
*** 44,50 ****
      private final String username;
      private final String password;
      
!     private Session session;
      private ChannelExec channel;
  
      /**
--- 45,52 ----
      private final String username;
      private final String password;
      
!     private JSch jsch;
!     private static Hashtable session_pool=new Hashtable();
      private ChannelExec channel;
  
      /**
***************
*** 65,86 ****
      }
  
      public void open() throws AuthenticationException, CommandAbortedException {
  
-         Properties props = new Properties();
-         props.put("StrictHostKeyChecking", "no"); // NOI18N
-         
-         JSch jsch = new JSch();
          try {
-             session = jsch.getSession(username, host, port);
-             session.setSocketFactory(new SocketFactoryBridge());
-             session.setConfig(props);
-             session.setUserInfo(new SSHUserInfo());
-             session.connect();
-         } catch (JSchException e) {
-             throw new AuthenticationException(e, NbBundle.getMessage(SSHConnection.class, "BK3001"));
-         }
-         
-         try {
              channel = (ChannelExec) session.openChannel("exec"); // NOI18N
              channel.setCommand(CVS_SERVER_COMMAND);
              setInputStream(new LoggedDataInputStream(new SshChannelInputStream(channel)));
--- 67,78 ----
      }
  
      public void open() throws AuthenticationException, CommandAbortedException {    
+         Session session=getSession();
  
          try {
              channel = (ChannelExec) session.openChannel("exec"); // NOI18N
              channel.setCommand(CVS_SERVER_COMMAND);
***************
*** 122,128 ****
      }
  
      private void reset() {
-         session = null;
          channel = null;
          setInputStream(null);
          setOutputStream(null);
--- 111,116 ----
***************
*** 130,136 ****
      
      public void close() throws IOException {
          if (channel != null) channel.disconnect();
-         if (session != null) session.disconnect();
          reset();
      }
  
--- 118,123 ----
***************
*** 155,161 ****
       */ 
      private class SSHUserInfo implements UserInfo, UIKeyboardInteractive {
          public String getPassphrase() {
!             return null;
          }
  
          public String getPassword() {
--- 142,148 ----
       */ 
      private class SSHUserInfo implements UserInfo, UIKeyboardInteractive {
          public String getPassphrase() {
!             return password;
          }
  
          public String getPassword() {
***************
*** 171,183 ****
          }
  
          public boolean promptYesNo(String message) {
!             return false;
          }
  
          public void showMessage(String message) {
          }
  
--- 158,175 ----
          }
  
          public boolean promptYesNo(String message) {            
!             Object[] options={ "yes", "no" };
!             int foo=JOptionPane.showOptionDialog(null,
!                                                     message,
!                                                     "Warning",
!                                                     JOptionPane.DEFAULT_OPTION, 
!                                                     JOptionPane.WARNING_MESSAGE,
!                                                     null, options, options[0]);
!             return foo==0;
          }
  
          public void showMessage(String message) {
+             JOptionPane.showMessageDialog(null, message);
          }
  
          public String[] promptKeyboardInteractive(String destination,
***************
*** 182,197 ****
                                                    String instruction,
                                                    String[] prompt,
                                                    boolean[] echo){
            String[] response=new String[prompt.length];
-           if(prompt.length==1){
              response[0]=password;
-           }
            return response;                                                
          }
      }
      
      /**
--- 177,191 ----
                                                    String instruction,
                                                    String[] prompt,
                                                    boolean[] echo){
+ 
+             if(password!=null && password.length()>0 && prompt.length==1){
                  String[] response=new String[prompt.length];
                  response[0]=password; 
                  return response;
              }
+             return null;  // cancel
          }
+     }
      
      /**
       * Bridges com.jcraft.jsch.SocketFactory and javax.net.SocketFactory. 
***************
*** 228,234 ****
--- 225,282 ----
              if (exitStatus == 0 || channel.isEOF()) throw new EOFException(NbBundle.getMessage(SSHConnection.class, "BK3007"));
          }
      }
+     
+     private Session getSession() throws AuthenticationException{
+         String key=username+":"+host+":"+port;
+         Session session=null;
+         synchronized(session_pool){
+             session=(Session) session_pool.get(key);
+             if(session!=null && !session.isConnected()){
+                 session_pool.remove(key);
+                 session=null;
              }
+             if(session==null){
+                 if(jsch==null){
+                     jsch = new JSch();
+                     String ssh_home=System.getProperty("user.home")+java.io.File.separator + ".ssh";
+                     String[] pkey={"id_rsa", "id_dsa"};
+                      for(int i=0;i<pkey.length;i++){
+                         java.io.File file = new java.io.File(ssh_home, pkey[i]);
+                         if (file.exists()){
+                             try{
+                                 jsch.addIdentity(file.getPath());
+                             }
+                             catch(JSchException ee){
+                             }
+                         }
+                     }
+                     try {
+                         java.io.File file;
+                         file=new java.io.File(ssh_home, "known_hosts");
+                         jsch.setKnownHosts(file.getPath());
+                     } 
+                     catch (Exception e) {
+                     }
+ 		}
+              
+                 try {
+                     session = jsch.getSession(username, host, port);
+                     session.setSocketFactory(new SocketFactoryBridge());
+                     if(password!=null && password.length()>0){
+                         session.setPassword(password);                       
+                     }
+                     session.setUserInfo(new SSHUserInfo());
+                     session.connect();
+                 } catch (JSchException e) {
+                     throw new AuthenticationException(e, NbBundle.getMessage(SSHConnection.class, "BK3001"));
+                 }
+             }
+             session_pool.put(key, session);
+         }
+         return session;
+     }
+ }


------=_Part_3380_31880525.1142608660167
Content-Type: text/plain; charset=us-ascii

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
------=_Part_3380_31880525.1142608660167--