//***************************************************************************** //* //* (c) Copyright 2002. Glub Tech, Incorporated. All Rights Reserved. //* //* $Id: OpenCommand.java 37 2009-05-11 22:46:15Z gary $ //* //***************************************************************************** package com.glub.secureftp.client.cli; import com.glub.secureftp.bean.*; import com.glub.util.*; import com.glub.secureftp.client.framework.*; import java.io.*; import java.net.*; import java.util.*; public class OpenCommand extends LocalCommand { private static boolean displayedConnectionWarning = false; private boolean secModeSet = false; public OpenCommand() { super("open", CommandID.OPEN_COMMAND_ID, 0, 3, "[secmode:implicit_ssl|explicit_ssl|none] host [port]", "connect to remote tftp"); } public void verifyArgs() throws IllegalArgumentException { PrintStream out = SecureFTP.getFTPSession().getPrintStream(); if ( getArgs().size() < getMinNumOfArgs() || getArgs().size() > getMaxNumOfArgs() ) { throw new IllegalArgumentException( getCommandName() + " " + getUsage() ); } else if (getArgs().size() >= 1) { String modeCheck = (String)getArgs().get(0); secModeSet = modeCheck.toLowerCase().startsWith("secmode:"); if (secModeSet) { getArgs().remove(0); FTPSession session = SecureFTP.getFTPSession(); String mode = modeCheck.substring("secmode:".length(), modeCheck.length()); if (mode != null) mode = mode.toLowerCase().trim(); if (mode.equals("implicit_ssl")) { session.setSecurityMode( FTPSession.IMPLICIT_SSL ); } else if (mode.equals("explicit_ssl")) { session.setSecurityMode( FTPSession.EXPLICIT_SSL ); } else if (mode.equals("none")) { session.setSecurityMode( FTPSession.NO_SECURITY ); } else { out.println("Security mode unknown... using defaults."); } } } if ( getArgs().size() == 2 ) { try { Integer.parseInt((String)getArgs().get(1)); } catch ( NumberFormatException nfe ) { out.println("Error: Bad port number - " + getArgs().get(1)); throw new IllegalArgumentException( getCommandName() + " " + getUsage() ); } } } public SecureFTPError doIt() throws CommandException { SecureFTPError result = super.doIt(); FTPSession session = SecureFTP.getFTPSession(); PrintStream out = session.getPrintStream(); FTP ftp = session.getFTPBean(); if ( ftp != null && ftp.isConnected() ) { out.println("Already connected to " + session.getHostName() + ", use close first."); return result; } int numberOfArgs = getArgs().size(); if ( 0 == numberOfArgs ) { if ( session.getHostName() != null ) { ArrayList args = new ArrayList(1); args.add( session.getHostName() ); setArgs( args ); } else { BufferedReader stdin = SecureFTP.getInput(); out.print("(to) "); try { String input = stdin.readLine(); StringTokenizer tok = new StringTokenizer(input); ArrayList args = new ArrayList(1); while( tok.hasMoreTokens() ) { args.add(tok.nextToken()); } setArgs(args); } catch ( IOException ioe ) { throw new CommandException( ioe.getMessage() ); } catch ( IllegalArgumentException iae ) { out.println("Usage: " + getCommandName() + " " + iae.getMessage()); throw new CommandException("open arg verification failed"); } } } boolean weSetDefaultPort = false; if ( getArgs().size() > 0 ) { session.setHostName( (String)getArgs().get(0) ); if ( getArgs().size() == 1 && session.getPort() == 0 ) { if ( SecureFTP.explicitSSLOnly || secModeSet && (session.getSecurityMode() == FTPSession.EXPLICIT_SSL || session.getSecurityMode() == FTPSession.NO_SECURITY) ) { session.setPort( SecureFTP.getDefaultExplicitSSLPort() ); } else { session.setPort( SecureFTP.getDefaultImplicitSSLPort() ); } weSetDefaultPort = true; } else if ( getArgs().size() == 2 ) { try { session.setPort( Integer.parseInt((String)getArgs().get(1)) ); } catch ( NumberFormatException nfe ) { // at this point, we're okay (passed verification earlier). } } } if ( !displayedConnectionWarning && FTPSession.NO_SECURITY != session.getSecurityMode() && SecureFTP.getDefaultExplicitSSLPort() != session.getPort() && SecureFTP.getDefaultImplicitSSLPort() != session.getPort() ) { out.println(""); out.println("!!! WARNING !!!: " + "This is a non-standard port for FTP over SSL."); if ( 22 == session.getPort() ) { out.println(" " + "This client does not support FTP over SSH."); } out.println(""); out.println("Continuing connection attempt..."); displayedConnectionWarning = true; } else if ( !displayedConnectionWarning && SecureFTP.explicitSSLOnly && SecureFTP.getDefaultImplicitSSLPort() == session.getPort() ) { out.println(""); out.println("!!! WARNING !!!: This is a non-standard " + "port for an explicit SSL connection."); out.println(""); out.println("Continuing connection attempt..."); displayedConnectionWarning = true; } if ( secModeSet ) { // don't touch it, it was set by the user } // by default we try and make an implicit ssl connection first (unless // otherwise overriden by a system property... else if ( SecureFTP.explicitSSLOnly && session.getSecurityMode() != FTPSession.NO_SECURITY ) { session.setSecurityMode( FTPSession.EXPLICIT_SSL ); } // but... if we are trying to connect to port 21, nix the implicit // attempt else if ( FTPSession.IMPLICIT_SSL == session.getSecurityMode() && SecureFTP.getDefaultExplicitSSLPort() == session.getPort() ) { session.setSecurityMode( FTPSession.EXPLICIT_SSL ); } try { FTP bean = null; boolean isSecure = session.isSecure(); OutputStream outputStream = session.getOutputStream(); if ( FTPSession.IMPLICIT_SSL == session.getSecurityMode() ) { bean = new SSLFTP(session.getCertHandler(), session.getHostName(), session.getPort(), session.getKeyStoreFile(), null, SSLFTP.IMPLICIT_CONNECTION, outputStream, outputStream); setClientAuth( (SSLFTP)bean, session ); isSecure = true; } else if ( FTPSession.EXPLICIT_SSL == session.getSecurityMode() ) { bean = new SSLFTP(session.getCertHandler(), session.getHostName(), session.getPort(), session.getKeyStoreFile(), null, SSLFTP.EXPLICIT_CONNECTION, outputStream, outputStream); setClientAuth( (SSLFTP)bean, session ); isSecure = true; } else { bean = new FTP(session.getHostName(), session.getPort(), outputStream, outputStream); isSecure = false; } session.setFTPBean( bean ); session.setIsSecure( isSecure ); String securityType = " an insecure "; if ( isSecure ) { if ( FTPSession.IMPLICIT_SSL == session.getSecurityMode() ) { securityType = " an implicit SSL "; } else { securityType = " an explicit SSL "; } } out.println("Attempting to make" + securityType + "connection to " + session.getHostName() + " on port " + session.getPort() + "."); boolean connectionAborted = false; try { if ( isSecure ) { ((SSLFTP)bean).connect( true ); if ( !bean.isConnected() ) { out.println("Connection lost."); throw new FTPAuthNotSupportedException(); } } else { bean.connect(); } } catch ( FTPPolicyRestrictionException fpre ) { //tryInsecureConnection( session ); try { bean.logout(); tryAuthSSL( bean, session ); } catch ( FTPPolicyRestrictionException fpre2 ) { connectionAborted = tryInsecureConnection( session ); } catch ( FTPAuthNotSupportedException fce2 ) { connectionAborted = tryInsecureConnection( session ); } } catch ( FTPAuthNotSupportedException fce ) { try { bean.logout(); tryAuthSSL( bean, session ); } catch ( FTPPolicyRestrictionException fpre2 ) { connectionAborted = tryInsecureConnection( session ); } catch ( FTPAuthNotSupportedException fce2 ) { connectionAborted = tryInsecureConnection( session ); } } if ( bean.isConnected() ) { boolean force = GTOverride.getBoolean("forcePasvToUseControlIP"); bean.forcePasvToUseControlIP( force ); if ( !SecureFTP.scripted ) result = SecureFTP.getCommandDispatcher().fireCommand(this, new LoginCommand()); if ( result.getCode() == SecureFTPError.LOGIN_FAILED ) { session.setUserName(null); session.setPassword(null); session.setAccount(null); } } else if ( !connectionAborted ) { out.println("A connection error has occured."); } } catch ( UnknownHostException uhe ) { out.println(uhe.getMessage() + ": unknown host"); session.clearSession(); } catch ( IOException ioe ) { out.println("Connection failed: " + ioe.getMessage()); tryAgain( session, weSetDefaultPort ); } catch ( FTPConnectException ce ) { out.println(ce.getMessage()); //if ( ! SecureFTP.explicitSSLOnly ) { tryAgain( session, weSetDefaultPort ); //} } catch ( FTPException fe ) { out.println(fe.getMessage()); session.clearSession(); } displayedConnectionWarning = false; return result; } public void setClientAuth( SSLFTP ftp, FTPSession session ) { PrintStream out = session.getPrintStream(); File[] certChain = null; String privateKey = GTOverride.getString("client.private_key"); String publicCert = GTOverride.getString("client.public_cert"); String ca = GTOverride.getString("client.ca"); String pass = GTOverride.getString("client.cert.pass"); if ( null == privateKey || null == publicCert ) { try { ftp.clearClientAuthentication(); } catch ( Exception e ) {} return; } File privateFile = new File( privateKey ); if ( null == ca ) { certChain = new File[1]; certChain[0] = new File( publicCert ); } else { certChain = new File[2]; certChain[0] = new File( publicCert ); certChain[1] = new File( ca ); } try { ftp.setClientAuthentication( privateFile, certChain, pass ); } catch ( Exception e ) { try { ftp.clearClientAuthentication(); } catch ( Exception cca ) {} out.println("There was a problem setting the client authentication: " + e.getMessage()); } } public void tryAgain( FTPSession session, boolean resetPort ) { PrintStream out = SecureFTP.getFTPSession().getPrintStream(); if ( !secModeSet && FTPSession.IMPLICIT_SSL == session.getSecurityMode() ) { session.setSecurityMode( FTPSession.EXPLICIT_SSL ); } else if ( !secModeSet && FTPSession.EXPLICIT_SSL == session.getSecurityMode() ) { session.setSecurityMode( FTPSession.NO_SECURITY ); } else { if (!secModeSet) out.println("Giving up."); session.clearSession(); return; } // if we set the port to the default implicit port and we are here, // set the port to the default explicit port and try again if ( resetPort ) { session.setPort( SecureFTP.getDefaultExplicitSSLPort() ); } SecureFTP.getCommandDispatcher().fireCommand(this, this); } private void tryAuthSSL( FTP bean, FTPSession session ) throws FTPException, IOException { PrintStream out = session.getPrintStream(); OutputStream outputStream = session.getOutputStream(); out.println("AUTH TLS not suppoted. Trying AUTH SSL..."); ((SSLFTP)bean).setAuthType("SSL"); ((SSLFTP)bean).connect( true ); if ( !bean.isConnected() ) { out.println("Connection lost."); bean.logout(); bean = new FTP(session.getHostName(), session.getPort(), outputStream, outputStream); session.setFTPBean( bean ); bean.connect(); throw new FTPAuthNotSupportedException(); } } private boolean tryInsecureConnection( FTPSession session ) { boolean connectionAborted = false; PrintStream out = session.getPrintStream(); String msg = "A secure connection could not be established."; boolean continueWithoutSecurity = SecureFTP.securityDisabled; if ( !secModeSet && !SecureFTP.securityDisabled && !SecureFTP.scripted ) { continueWithoutSecurity = CLIUtil.yesNoPrompt(msg + " Continue anyway?"); } else { out.println( msg ); } if ( continueWithoutSecurity ) { // let it go... session.setIsSecure( false ); session.setSecurityMode( FTPSession.NO_SECURITY ); } else { out.println("Connection aborted."); SecureFTP.getCommandDispatcher().fireCommand(this, new CloseCommand()); connectionAborted = true; } return connectionAborted; } }