1 19 20 package com.sslexplorer.agent.client; 21 22 import java.io.File ; 23 import java.io.FileInputStream ; 24 import java.io.FileOutputStream ; 25 import java.io.IOException ; 26 import java.io.InputStream ; 27 import java.io.InterruptedIOException ; 28 import java.io.PrintStream ; 29 import java.net.URL ; 30 import java.text.MessageFormat ; 31 import java.text.SimpleDateFormat ; 32 import java.util.Date ; 33 import java.util.Enumeration ; 34 import java.util.Hashtable ; 35 import java.util.Locale ; 36 import java.util.Properties ; 37 import java.util.StringTokenizer ; 38 import java.util.Vector ; 39 40 import com.maverick.http.AuthenticationCancelledException; 41 import com.maverick.http.AuthenticationPrompt; 42 import com.maverick.http.GetMethod; 43 import com.maverick.http.HttpAuthenticator; 44 import com.maverick.http.HttpAuthenticatorFactory; 45 import com.maverick.http.HttpClient; 46 import com.maverick.http.HttpConnection; 47 import com.maverick.http.HttpException; 48 import com.maverick.http.HttpResponse; 49 import com.maverick.http.PasswordCredentials; 50 import com.maverick.http.URLDecoder; 51 import com.maverick.http.UnsupportedAuthenticationException; 52 import com.maverick.multiplex.MultiplexedConnection; 53 import com.maverick.multiplex.MultiplexedConnectionListener; 54 import com.maverick.multiplex.Request; 55 import com.maverick.multiplex.RequestHandler; 56 import com.maverick.ssl.SSLIOException; 57 import com.maverick.ssl.https.HttpsURLStreamHandlerFactory; 58 import com.maverick.util.ByteArrayReader; 59 import com.maverick.util.ByteArrayWriter; 60 import com.sslexplorer.agent.client.applications.ApplicationManager; 61 import com.sslexplorer.agent.client.networkplaces.NetworkPlaceManager; 62 import com.sslexplorer.agent.client.tunneling.DefaultTunnel; 63 import com.sslexplorer.agent.client.tunneling.LocalTunnelServer; 64 import com.sslexplorer.agent.client.tunneling.TunnelInactivityMonitor; 65 import com.sslexplorer.agent.client.tunneling.TunnelManager; 66 import com.sslexplorer.agent.client.util.BrowserLauncher; 67 import com.sslexplorer.agent.client.util.IOStreamConnectorListener; 68 import com.sslexplorer.agent.client.util.TunnelConfiguration; 69 import com.sslexplorer.agent.client.util.URI; 70 import com.sslexplorer.agent.client.util.Utils; 71 import com.sslexplorer.agent.client.util.URI.MalformedURIException; 72 import com.sslexplorer.agent.client.webforwards.WebForwardManager; 73 74 85 public class Agent implements RequestHandler, MultiplexedConnectionListener { 86 87 90 public final static String AGENT_VERSION = "999.999.999"; 91 92 93 protected String sslexplorerHostname; 94 95 96 protected int sslexplorerPort; 97 98 99 protected String username; 100 101 102 protected String ticket; 103 104 105 protected URI localProxyURL; 106 107 108 protected static Hashtable proxiesIE = new Hashtable (); 109 110 111 protected static Vector proxyBypassIE = new Vector (); 112 113 protected static Hashtable proxiesFF = new Hashtable (); 114 115 protected static Vector proxyBypassFF = new Vector (); 116 117 118 119 protected AgentConfiguration agentConfiguration; 120 121 protected String serverVersion; 122 123 protected HttpClient client; 124 125 protected String defaultProxyHost; 126 127 protected int defaultProxyPort = 80; 128 129 protected PasswordCredentials defaultProxyCredentials; 130 131 protected String defaultProxyPreferredAuthentication; 132 133 protected boolean autoDetectProxies = true; 134 135 protected AuthenticationPrompt defaultProxyAuthenticationPrompt; 136 137 protected int defaultProxyType = HttpClient.PROXY_HTTP; 138 139 protected ApplicationManager applicationManager; 140 141 protected TunnelManager tunnelManager; 142 143 protected WebForwardManager webForwardManager; 144 145 protected NetworkPlaceManager networkPlaceManager; 146 147 boolean ticketIsPassword; 148 149 151 154 public final static int STATE_CONNECTED = 1; 155 156 159 public final static int STATE_DISCONNECTED = 2; 160 161 163 private int currentState = STATE_DISCONNECTED; 164 165 private TXRXMonitor txm; 166 167 private AgentClientGUI gui; 168 169 private Vector extensions = new Vector (); 170 171 private TunnelInactivityMonitor inactivityMonitor; 172 173 private KeepAliveThread keepAlive; 174 175 177 MultiplexedConnection con = null; 178 179 HttpConnection httpConnection = null; 180 181 public static final String SHUTDOWN_REQUEST = "shutdown@3sp.com"; 182 183 public static final String OPEN_URL_REQUEST = "openURL@3sp.com"; 184 185 public static final String MESSAGE_REQUEST = "agentMessage@3sp.com"; 186 187 public static final String UPDATE_RESOURCES_REQUEST = "updateResources@3sp.com"; 188 189 public static final String SYNCHRONIZED_REQUEST = "synchronized@3sp.com"; 190 191 static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory 193 .getLog(Agent.class); 194 196 static { 197 HttpClient.setUserAgent("SSL-Explorer/Agent"); } 199 200 207 public void setLocalProxyURL(String localProxyURL) 208 throws URI.MalformedURIException { 209 this.localProxyURL = new URI(localProxyURL); 210 211 } 213 214 219 public ApplicationManager getApplicationManager() { 220 return applicationManager; 221 } 222 223 228 public TunnelManager getTunnelManager() { 229 return tunnelManager; 230 } 231 232 237 public NetworkPlaceManager getNetworkPlaceManager() { 238 return networkPlaceManager; 239 } 240 241 247 public String getServerVersion() { 248 return serverVersion; 249 } 250 251 258 public String getClientVersion() { 259 return AGENT_VERSION; 260 } 261 262 public MultiplexedConnection getConnection() { 263 return con; 264 } 265 266 271 public String getSSLExplorerHost() { 272 return sslexplorerHostname; 273 } 274 275 public String getTicket() { 276 return ticket; 277 } 278 279 284 public int getSSLExplorerPort() { 285 return sslexplorerPort; 286 } 287 288 293 public String getUsername() { 294 return username; 295 } 296 297 public void onConnectionClose() { 298 currentState = STATE_DISCONNECTED; 299 if (getConfiguration().isSystemExitOnDisconnect()) { 300 startShutdownProcedure(); 301 } else { 302 getGUI().showDisconnected(); 303 } 304 } 305 306 public void onConnectionOpen() { 307 currentState = STATE_CONNECTED; 308 } 309 310 314 public void configureProxy() { 315 316 if (localProxyURL != null && !localProxyURL.equals("")) { log.info("Configuring HTTP proxy to " 320 + obfuscateURL(localProxyURL.toString())); 321 String userInfo = localProxyURL.getUserinfo(); 323 String user = ""; String password = ""; if (userInfo != null && !userInfo.equals("")) { int idx = userInfo.indexOf(':'); 327 user = URLDecoder.decode(userInfo); 328 if (idx != -1) { 329 password = URLDecoder.decode(userInfo.substring(idx + 1)); 330 user = URLDecoder.decode(userInfo.substring(0, idx)); 331 } 332 } 333 int port = localProxyURL.getPort(); 334 setDefaultProxyType(localProxyURL.getScheme().equals("https") ? HttpClient.PROXY_HTTPS : HttpClient.PROXY_HTTP); setDefaultProxyHost(localProxyURL.getHost()); 336 setDefaultProxyPort(port == -1 ? 80 : port); 337 if (!user.equals("")) { setDefaultProxyCredentials(new PasswordCredentials(user, 339 password)); 340 } 341 if (localProxyURL.getQueryString() != null) { 342 setDefaultProxyPreferredAuthentication(localProxyURL 343 .getQueryString()); 344 } 345 } 346 if (localProxyURL != null && !localProxyURL.equals("")) { setDefaultProxyAuthenticationPrompt(gui); 348 } 349 350 } 351 352 358 private synchronized HttpClient getHttpClient() { 359 if (client == null) { 360 log.info("Creating HttpClient instance"); client = new HttpClient(sslexplorerHostname, sslexplorerPort, true); 364 client.setAuthenticationPrompt(getGUI()); 365 if (defaultProxyHost != null && !defaultProxyHost.equals("")) { log.info("Configuring proxies for HttpClient instance"); client 370 .setProxyAuthenticationPrompt(defaultProxyAuthenticationPrompt); 371 client.setProxyHost(defaultProxyHost); 372 client.setProxyPort(defaultProxyPort); 373 client.setProxyType(defaultProxyType); 374 375 if (defaultProxyCredentials != null 376 && defaultProxyCredentials.getUsername() != null 377 && !defaultProxyCredentials.getUsername().equals("")) { 382 client.setProxyCredentials(defaultProxyCredentials); 383 384 389 if ("BASIC" 390 .equalsIgnoreCase(defaultProxyPreferredAuthentication)) { 391 client.setProxyPreemptiveAuthentication(true); 392 } 393 } 394 client 395 .setProxyPreferedAuthentication("AUTO".equalsIgnoreCase(defaultProxyPreferredAuthentication) ? null : defaultProxyPreferredAuthentication); 397 } 398 } 399 400 return client; 401 } 402 403 406 public Agent(AgentConfiguration agentConfiguration) { 407 this.agentConfiguration = agentConfiguration; 408 409 if (getConfiguration().getGUIClass() != null) { 411 try { 412 gui = (AgentClientGUI) Class.forName( 413 getConfiguration().getGUIClass()).newInstance(); 414 } catch (Exception e) { 415 log.error("Failed to create GUI", e); 417 } 419 420 } 421 422 if (gui == null) { 424 425 try { 427 Class.forName("org.eclipse.swt.widgets.Display"); 428 gui = (AgentClientGUI) Class 429 .forName( 430 "com.sslexplorer.agent.client.gui.swt.SWTSystemTrayGUI") 431 .newInstance(); 432 } catch (Exception e) { 433 log.debug("Failed to create SWT GUI", e); 435 } 437 438 if (gui == null) { 440 441 if (Utils.checkVersion("1.6")) { try { 444 gui = (AgentClientGUI) Class 446 .forName( 447 "com.sslexplorer.agent.client.gui.awt.JDK6SystemTrayGUI") 448 .newInstance(); 449 } catch (Exception e) { 450 log.debug("Failed to create JDK6 GUI", e); 452 } 454 } 455 456 if (gui == null 458 && Utils.checkVersion("1.2") && System.getProperty("os.name").startsWith("Windows") && !System 460 .getProperty("os.name").startsWith("Windows 98") && !System 462 .getProperty("os.name").startsWith("Windows 95") && !System 464 .getProperty("os.name").startsWith("Windows ME")) { try { 466 gui = (AgentClientGUI) Class 467 .forName( 468 "com.sslexplorer.agent.client.gui.awt.SystemTrayGUI") 469 .newInstance(); 470 } catch (Exception e) { 471 log.debug("Failed to create JDIC GUI", e); 473 } 475 } 476 477 if (gui == null) { 479 try { 480 gui = (AgentClientGUI) Class 481 .forName( 482 "com.sslexplorer.agent.client.gui.awt.BasicFrameGUI") 483 .newInstance(); 484 } catch (Exception e) { 485 log.debug("Failed to create basic GUI", e); 487 } 489 490 if (gui == null) { 492 gui = new DummyGUI(); 493 } 494 } 495 } 496 } 497 } 498 499 511 517 public int getState() { 518 return currentState; 519 } 520 521 526 public AgentConfiguration getConfiguration() { 527 return agentConfiguration; 528 } 529 530 536 public void init() throws SecurityException , IOException { 537 538 log.info("Allow untrusted hosts is set to " + System.getProperty("com.maverick.ssl.allowUntrustedCertificates", "false")); log.info("Cache directory is " + getConfiguration().getCacheDir()); 541 543 log.info("Initialising GUI"); gui.init(this); 547 disconnected(); 548 549 log.info("Installing Maverick SSL support for HTTPSURLStreamHandler"); 554 try { 555 HttpsURLStreamHandlerFactory.addHTTPSSupport(); 556 configureProxy(); 557 } catch (SecurityException se) { 558 disconnected(); 559 throw se; 560 } catch (IOException ioe) { 561 disconnected(); 562 throw ioe; 563 } 564 } 565 566 public void connect(String sslexplorerHostname, int sslexplorerPort, 567 String username, String ticket, boolean ticketIsPassword) 568 throws IOException , HttpException, 569 UnsupportedAuthenticationException, 570 AuthenticationCancelledException { 571 572 this.sslexplorerHostname = sslexplorerHostname; 573 this.sslexplorerPort = sslexplorerPort; 574 this.username = username; 575 this.ticket = ticket; 576 this.ticketIsPassword = ticketIsPassword; 577 578 inactivityMonitor = new TunnelInactivityMonitor(this); 579 keepAlive = new KeepAliveThread(); 580 581 gui.showTxRx(); 582 583 connectAgent(); 584 585 txm = new TXRXMonitor(this); 587 txm.start(); 588 589 gui.showIdle(); 590 updateInformation(); 591 592 inactivityMonitor.start(); 593 594 if (getConfiguration().getKeepAlivePeriod() > 0) 595 keepAlive.start(); 596 597 if (getConfiguration().isDisplayInformationPopups()) { 598 getGUI().popup(null, Messages.getString("VPNClient.nowRunning"), Messages.getString("VPNClient.title"), "popup-agent", -1); } 601 602 } 603 604 public boolean processRequest(Request request, MultiplexedConnection con) { 605 606 if (request.getRequestName().equals(SHUTDOWN_REQUEST)) { 607 disconnectAgent(); 608 return true; 609 } else if (request.getRequestName().equals(MESSAGE_REQUEST)) { 610 displayMessage(request); 611 return true; 612 } else if (request.getRequestName().equals(UPDATE_RESOURCES_REQUEST)) { 613 final ByteArrayReader bar = new ByteArrayReader(request.getRequestData()); 614 Thread t = new Thread () { 615 public void run() { 616 try { 617 updateResources((int)bar.readInt()); 618 } 619 catch(IOException e) { 620 } 621 } 622 }; 623 t.start(); 624 return true; 625 } else if (request.getRequestName().equals(OPEN_URL_REQUEST) 626 && request.getRequestData() != null) { 627 try { 628 ByteArrayReader msg = new ByteArrayReader(request 629 .getRequestData()); 630 openURL(msg.readString(), msg.readString(), request); 631 return true; 632 } catch (IOException e) { 633 log.error("Failed to process openURL request", e); 635 return false; 637 } 638 } else 639 return false; 640 } 641 642 public void postReply(MultiplexedConnection connection) { 643 } 644 645 private void displayMessage(Request request) { 646 647 try { 648 if (request.getRequestData() != null) { 649 ByteArrayReader msg = new ByteArrayReader(request 650 .getRequestData()); 651 String title = msg.readString(); 652 msg.readInt(); String message = msg.readString(); 654 655 getGUI().popup( 656 null, 657 MessageFormat.format(Messages 658 .getString("Agent.received"), new Object [] { 659 SimpleDateFormat.getDateTimeInstance().format( 660 new Date ()), message }), 661 title.equals("") ? Messages 662 .getString("Agent.promptTitle") : title, 663 "popup-mail", 0); 664 } 665 } catch (IOException e) { 666 log.error("Failed to read message data from popup message request", 668 e); 669 } 671 672 } 673 674 private boolean openURL(String link, String launchId, Request request) { 675 676 log.info("Request to open " + link + " via a temporary tunnel"); 680 try { 683 URI url = new URI(link); 684 String linkHost = url.getHost(); 685 int linkPort = url.getPort() == -1 ? (url.getScheme() 686 .equalsIgnoreCase("https") ? 443 : 80) : url.getPort(); 688 690 DefaultTunnel t = new DefaultTunnel(-1, 691 TunnelConfiguration.LOCAL_TUNNEL, 692 TunnelConfiguration.TCP_TUNNEL, null, 0, linkPort, 693 linkHost, false, false, linkHost + ":" + linkPort, launchId); 694 695 LocalTunnelServer listener = getTunnelManager().startLocalTunnel(t); 696 697 log.info("Tunneled web forward listener started on port " 699 + listener.getLocalPort()); 700 702 ByteArrayWriter w = new ByteArrayWriter(); 703 w.writeInt(listener.getLocalPort()); 704 request.setRequestData(w.toByteArray()); 705 return true; 706 } catch (Exception e) { 707 log.error("Failed to process openURL request", e); 709 } 711 return false; 712 } 713 714 719 public AgentClientGUI getGUI() { 720 return gui; 721 } 722 723 public void updateInformation() { 724 725 } 764 765 770 public IOStreamConnectorListener getTXIOListener() { 771 return txm != null ? txm.getTxListener() : null; 772 } 773 774 public IOStreamConnectorListener getRXIOListener() { 775 return txm != null ? txm.getRxListener() : null; 776 } 777 778 786 protected String getRedirectUrl(String path) { 787 try { 788 new URL (path); 789 return path; 790 } catch (Exception e) { 791 return "https://" + getSSLExplorerHost() + ":" + getSSLExplorerPort() + path; } 793 } 794 795 private void startExtensions(String extensionClasses) { 796 StringTokenizer classes = new StringTokenizer (extensionClasses, ","); while (classes.hasMoreTokens()) { 798 String cls = classes.nextToken(); 799 try { 800 Class agent = Class.forName(cls); 801 AgentExtension ext = (AgentExtension) agent.newInstance(); 802 log.info("Starting " + ext.getName()); 804 ext.init(this); 806 extensions.addElement(ext); 807 } catch (Exception e1) { 808 log.info("Unable to start extension " + cls, e1); 810 continue; 812 } 813 } 814 } 815 816 private void connectAgent() throws IOException , HttpException, 817 UnsupportedAuthenticationException, 818 AuthenticationCancelledException { 819 820 HttpResponse response = null; 821 822 try { 823 for (int i = 0; i < 3; i++) { 824 825 log.info("Registering with the SSL-Explorer server"); log.info("Server is " + getSSLExplorerHost() + ":" + getSSLExplorerPort()); 831 HttpClient client = getHttpClient(); 832 GetMethod post = new GetMethod("/agent"); 834 if (ticketIsPassword) { 835 client.setCredentials(new PasswordCredentials(username, 836 ticket)); 837 client.setPreferredAuthentication("Basic"); 838 client.setPreemtiveAuthentication(true); 839 } else { 840 if (ticket != null) { 841 post.setParameter("ticket", ticket); } 843 } 844 845 post.setParameter( 846 "agentType", getConfiguration().getAgentType()); post.setParameter("locale", Locale.getDefault().toString()); 849 response = client.execute(post); 850 851 if (response.getStatus() == 302) { 852 this.client = null; 854 855 URL url = new URL (response.getHeaderField("Location")); sslexplorerHostname = url.getHost(); 857 if (url.getPort() > 0) 858 sslexplorerPort = url.getPort(); 859 continue; 860 } else if (response.getStatus() == 200) { 861 con = new MultiplexedConnection(new AgentChannelFactory( 862 this)); 863 con.addListener(this); 864 httpConnection = response.getConnection(); con.registerRequestHandler(MESSAGE_REQUEST, this); 867 con.registerRequestHandler(SHUTDOWN_REQUEST, this); 868 con.registerRequestHandler(OPEN_URL_REQUEST, this); 869 con.registerRequestHandler(UPDATE_RESOURCES_REQUEST, this); 870 871 873 con.startProtocol( 874 response.getConnection().getInputStream(), response 875 .getConnection().getOutputStream(), true); 876 877 Request syncRequest = new Request(SYNCHRONIZED_REQUEST); 879 con.sendRequest(syncRequest, true); 880 if (syncRequest.getRequestData() == null) 881 throw new IOException ( 882 "Server failed to return version data"); 883 884 ByteArrayReader reader = new ByteArrayReader(syncRequest 885 .getRequestData()); 886 serverVersion = reader.readString(); 887 888 894 tunnelManager = new TunnelManager(this); 895 applicationManager = new ApplicationManager(this); 896 webForwardManager = new WebForwardManager(this); 897 networkPlaceManager = new NetworkPlaceManager(this); 898 updateResources(-1); 899 return; 900 } else if (response.getStatus() == 401) { 901 HttpAuthenticator authenticator = HttpAuthenticatorFactory 902 .createAuthenticator( 903 response.getConnection(), 904 response 905 .getHeaderFields("WWW-Authenticate"), 906 "WWW-Authenticate", "Authorization", 907 HttpAuthenticatorFactory.BASIC, post 908 .getURI()); 909 if (authenticator.wantsPrompt()) { 910 if (!getGUI() 911 .promptForCredentials(false, authenticator)) { 912 throw new AuthenticationCancelledException(); 913 } 914 } 915 } else { 916 917 919 throw new IOException (MessageFormat.format(Messages 920 .getString("VPNClient.register.failed"), 921 new Object [] { 922 String.valueOf(response.getStatus()), 923 response.getReason() })); 924 } 925 } 926 927 throw new IOException (Messages 928 .getString("VPNClient.register.tooManyRedirects")); } catch (IOException ioe) { 930 disconnected(); 931 throw ioe; 932 } catch (HttpException httpe) { 933 disconnected(); 934 throw httpe; 935 } catch (UnsupportedAuthenticationException uae) { 936 disconnected(); 937 throw uae; 938 } catch (AuthenticationCancelledException ace) { 939 disconnected(); 940 throw ace; 941 } 942 943 } 944 945 public boolean isConnected() { 946 return con != null && con.isRunning(); 947 } 948 949 public void disconnect() { 950 if (isConnected()) { 951 disconnectAgent(); 952 } 953 } 954 955 963 public void startShutdownProcedure() { 964 log.info("Starting agent shutdown procedure."); 968 if (getConfiguration().isDisplayInformationPopups()) { 969 getGUI() 970 .popup( 971 null, 972 Messages.getString("VPNClient.shutdown.popupText"), Messages.getString("VPNClient.title"), "popup-agent", -1); } 974 975 AgentExtension ext; 976 for (Enumeration e = extensions.elements(); e.hasMoreElements();) { 977 ext = (AgentExtension) e.nextElement(); 978 979 log.info("Stopping extension " + ext.getName()); ext.exit(); 983 } 984 985 getGUI().showDisconnected(); 986 987 if (getConfiguration().isCleanOnExit()) { 988 if (Utils.isSupportedPlatform("Windows")) { 989 cleanupWindowsAgent(); 990 } else if (Utils.isSupportedPlatform("Linux")) { 991 cleanupLinuxAgent(); 992 } else { 993 log 995 .info("Agent cleanOnExit is not supported on this platform."); 998 } 999 } 1000 1001 if (getConfiguration().isSystemExitOnDisconnect()) { 1002 scheduleExit(); 1003 } else { 1004 gui.dispose(); 1005 } 1006 } 1007 1008 1014 public PasswordCredentials getDefaultProxyCredentials() { 1015 return defaultProxyCredentials; 1016 } 1017 1018 1024 public void setDefaultProxyCredentials( 1025 PasswordCredentials defaultProxyCredentials) { 1026 this.defaultProxyCredentials = defaultProxyCredentials; 1027 } 1028 1029 1035 public String getDefaultProxyHost() { 1036 return defaultProxyHost; 1037 } 1038 1039 1046 public void setDefaultProxyHost(String defaultProxyHost) { 1047 this.defaultProxyHost = defaultProxyHost; 1048 } 1049 1050 1057 public int getDefaultProxyPort() { 1058 return defaultProxyPort; 1059 } 1060 1061 1069 public void setDefaultProxyPort(int defaultProxyPort) { 1070 this.defaultProxyPort = defaultProxyPort; 1071 } 1072 1073 1081 public int getDefaultProxyType() { 1082 return defaultProxyType; 1083 } 1084 1085 1094 public void setDefaultProxyType(int defaultProxyType) { 1095 this.defaultProxyType = defaultProxyType; 1096 } 1097 1098 1108 public String getDefaultProxyPreferredAuthentication() { 1109 return defaultProxyPreferredAuthentication; 1110 } 1111 1112 1123 public void setDefaultProxyPreferredAuthentication( 1124 String defaultProxyPreferredAuthentication) { 1125 this.defaultProxyPreferredAuthentication = defaultProxyPreferredAuthentication; 1126 } 1127 1128 1143 public AuthenticationPrompt getDefaultProxyAuthenticationPrompt() { 1144 return defaultProxyAuthenticationPrompt; 1145 } 1146 1147 1163 public void setDefaultProxyAuthenticationPrompt( 1164 AuthenticationPrompt defaultProxyAuthenticationPrompt) { 1165 this.defaultProxyAuthenticationPrompt = defaultProxyAuthenticationPrompt; 1166 } 1167 1168 1176 public static String obfuscateURL(String originalUrl) { 1177 try { 1178 URI url = new URI(originalUrl); 1179 String userInfo = url.getUserinfo(); 1180 String user = ""; if (userInfo != null && !userInfo.equals("")) { int idx = userInfo.indexOf(':'); 1183 user = userInfo; 1184 if (idx != -1) { 1185 user = userInfo.substring(0, idx); 1186 } 1187 return url.getScheme() 1188 + "://" + user + ":***@" + url.getHost() + ":" + url.getPort() + (url.getQueryString() != null ? ("?" + url.getQueryString()) : ""); } else { 1191 return originalUrl; 1192 } 1193 1194 } catch (URI.MalformedURIException e) { 1195 return originalUrl; 1196 } 1197 } 1198 1199 1207 public static Properties getSystemPropertiesToSend() { 1208 Properties p = new Properties (); 1209 setIfNotEmpty("java.version", p); setIfNotEmpty("java.vendor", p); setIfNotEmpty("sun.os.patch.level", p); setIfNotEmpty("os.name", p); setIfNotEmpty("os.version", p); setIfNotEmpty("os.arch", p); return p; 1216 } 1217 1218 protected static void setIfNotEmpty(String name, Properties p) { 1219 String v = System.getProperty(name); 1220 if (v != null && !v.equals("")) { p.put(name, v); 1222 } 1223 } 1224 1225 private static String getCommandLineValue(String arg) { 1226 int idx = arg.indexOf('='); 1227 if (idx > -1) 1228 return arg.substring(idx + 1); 1229 else 1230 return arg; 1231 } 1232 1233 1239 public static void main(String [] args) throws Throwable { 1240 1241 try { 1242 org.apache.log4j.BasicConfigurator.configure(); 1244 1246 String hostname = null; 1247 int port = 443; 1248 String username = null; 1249 String password = null; 1250 String ticket = null; 1251 String logProperties = null; 1252 int shutdown = -1; 1253 int webforwardInactivity = 300000; 1254 int tunnelInactivity = 600000; 1255 String browserCommand = null; 1256 String localProxyURL = null; 1257 String pluginProxyURL = null; 1258 String userAgent = null; 1259 String extensionClasses = null; 1260 String localeName = Locale.getDefault().toString(); 1261 1262 AgentConfiguration configuration = new AgentConfiguration(); 1263 1264 for (int i = 0; i < args.length; i++) { 1265 if (args[i].startsWith("hostname")) { hostname = getCommandLineValue(args[i]); 1267 } else if (args[i].startsWith("port")) { try { 1269 port = Integer.parseInt(getCommandLineValue(args[i])); 1270 } catch (NumberFormatException ex) { 1271 } 1272 } else if (args[i].startsWith("username")) { username = getCommandLineValue(args[i]); 1274 } else if (args[i].startsWith("password")) { password = getCommandLineValue(args[i]); 1276 } else if (args[i].startsWith("localProxyURL")) { localProxyURL = getCommandLineValue(args[i]); 1278 } else if (args[i].startsWith("pluginProxyURL")) { pluginProxyURL = getCommandLineValue(args[i]); 1280 } else if (args[i].startsWith("ticket")) { ticket = getCommandLineValue(args[i]); 1282 } else if (args[i].startsWith("browserCommand")) { browserCommand = getCommandLineValue(args[i]); 1284 } else if (args[i].startsWith("userAgent")) { userAgent = getCommandLineValue(args[i]); 1286 HttpClient.setUserAgent(userAgent); 1287 } else if (args[i].startsWith("locale")) { localeName = getCommandLineValue(args[i]); 1289 } else if (args[i].startsWith("webforward.inactivity")) { try { 1291 webforwardInactivity = Integer 1292 .parseInt(getCommandLineValue(args[i])); 1293 } catch (NumberFormatException ex) { 1294 } 1295 } else if (args[i].startsWith("tunnel.inactivity")) { try { 1297 tunnelInactivity = Integer 1298 .parseInt(getCommandLineValue(args[i])); 1299 } catch (NumberFormatException ex) { 1300 } 1301 } else if (args[i].startsWith("shutdown")) { try { 1303 shutdown = Integer 1304 .parseInt(getCommandLineValue(args[i])); 1305 } catch (NumberFormatException ex) { 1306 } 1307 } else if (args[i].startsWith("log4j")) { logProperties = getCommandLineValue(args[i]); 1309 } else if (args[i].startsWith("extensionClasses")) { extensionClasses = getCommandLineValue(args[i]); 1311 } else if (args[i].startsWith("ignoreCertWarnings")) { 1312 System.getProperties().put( 1313 "com.maverick.ssl.allowUntrustedCertificates", 1314 "true"); 1315 System.getProperties() 1316 .put("com.maverick.ssl.allowInvalidCertificates", 1317 "true"); 1318 } else if (args[i].startsWith("forceBasicUI")) { 1319 configuration 1320 .setGUIClass("com.sslexplorer.agent.client.gui.BasicFrameGUI"); 1321 } else if (args[i].startsWith("displayInformationPopups")) { 1322 configuration 1323 .setDisplayInformationPopups(getCommandLineValue( 1324 args[i]).equalsIgnoreCase("true")); 1325 } else if (args[i] 1326 .startsWith("remoteTunnelsRequireConfirmation")) { 1327 configuration 1328 .setRemoteTunnelsRequireConfirmation(getCommandLineValue( 1329 args[i]).equalsIgnoreCase("true")); 1330 } else if (args[i].startsWith("cleanOnExit")) { 1331 configuration.setCleanOnExit(getCommandLineValue(args[i]) 1332 .equalsIgnoreCase("true")); 1333 } else if (args[i].startsWith("localhostAddress")) { 1334 configuration.setLocalhostAddress(getCommandLineValue(args[i])); 1335 } else if (args[i].startsWith("dir")) { 1336 configuration.setCacheDir(new File ( 1337 Utils.getHomeDirectory(), 1338 getCommandLineValue(args[i]))); 1339 } else if (args[i].startsWith("removeFiles")) { 1340 StringTokenizer files = new StringTokenizer ( 1341 getCommandLineValue(args[i]), File.pathSeparator); 1342 while (files.hasMoreTokens()) { 1343 configuration.removeFileOnExit(new File (files 1344 .nextToken())); 1345 } 1346 } else if (args[i].startsWith("keepAlivePeriod")) { 1347 configuration.setKeepAlivePeriod(Integer 1348 .parseInt(getCommandLineValue(args[i]))); 1349 } 1350 } 1351 1352 if(isWindows64()) { 1353 configuration.setGUIClass("com.sslexplorer.agent.client.gui.BasicFrameGUI"); 1354 } 1355 1356 1359 Locale.setDefault(Utils.createLocale(localeName)); 1360 1361 if (logProperties == null) { 1362 System.out.println(Messages 1363 .getString("VPNClient.main.debugModeWarning")); } 1365 1366 if (port == -1 || hostname == null || username == null 1367 || (ticket == null && password == null)) 1368 throw new IOException ( 1369 Messages 1370 .getString("VPNClient.main.missingCommandLineArguments")); 1372 if (shutdown > -1) 1373 configuration.setShutdownPeriod(shutdown); 1374 configuration.setSystemExitOnDisconnect(true); 1375 configuration.setWebForwardInactivity(webforwardInactivity); 1376 configuration.setTunnelInactivity(tunnelInactivity); 1377 1378 Agent agent = new Agent(configuration); 1379 1380 PrintStream consolePrintStream = new PrintStream (agent.getGUI() 1382 .getConsole()); 1383 System.setErr(consolePrintStream); 1384 System.setOut(consolePrintStream); 1385 1386 System.out.println("Java version " 1387 + System.getProperty("java.version")); 1388 System.out.println("OS version " + System.getProperty("os.name")); 1389 1390 if (logProperties != null) { 1392 File f = new File (logProperties); 1393 InputStream in = new FileInputStream (f); 1394 try { 1395 Properties props = new Properties (); 1396 props.load(in); 1397 File logfile = new File (f.getParent(), "agent.log"); props 1399 .put( 1400 "log4j.appender.logfile.File", logfile.getAbsolutePath()); org.apache.log4j.PropertyConfigurator.configure(props); 1402 log = org.apache.commons.logging.LogFactory 1403 .getLog(Agent.class); 1404 log.info("Configured logging"); } finally { 1406 in.close(); 1407 } 1408 } 1409 1410 Properties systemProperties = System.getProperties(); 1411 String key; 1412 log.info("System properties:"); 1413 for(Enumeration e = systemProperties.keys(); e.hasMoreElements();) { 1414 key = (String )e.nextElement(); 1415 log.info(" " + key + ": " + systemProperties.getProperty(key)); 1416 } 1417 1418 1420 agent.setupProxy(localProxyURL, userAgent, pluginProxyURL); 1421 1422 if (browserCommand != null && !browserCommand.equals("")) { 1424 log.info("Setting browser to " + browserCommand); BrowserLauncher.setBrowserCommand(browserCommand); 1428 } 1429 1430 agent.initMain(hostname, port, username, password, ticket); 1431 1432 if (extensionClasses != null) 1433 agent.startExtensions(extensionClasses); 1434 } catch (Throwable t) { 1435 if (log != null) { 1438 log.error("Critical error, shutting down.", t); } else { 1440 System.err.println("Critical error, shutting down."); 1441 t.printStackTrace(); 1442 } 1443 throw t; 1445 } 1446 1447 } 1448 1449 private static boolean isWindows64() { 1450 1451 String prop = System.getProperty("os.name"); 1452 if (prop == null || prop.startsWith("Windows") == false) 1453 return false; 1454 1455 prop = System.getProperty("os.arch"); 1456 if (prop != null && prop.equalsIgnoreCase("amd64")) 1457 return true; 1458 1459 prop = System.getProperty("java.vm.name"); 1460 if (prop != null && prop.indexOf("64-Bit") != -1) 1461 return true; 1462 1463 prop = System.getProperty("sun.arch.data.model"); 1464 if (prop != null && prop.equals("64")) 1465 return true; 1466 1467 return false; 1468 } 1469 1470 private static boolean isWindowsVista() { 1471 return System.getProperty("os.name").startsWith("Windows Vista"); 1472 } 1473 1474 void initMain(String hostname, int port, String username, String password, 1475 String ticket) { 1476 try { 1477 init(); 1478 connect(hostname, port, username, ticket == null ? password 1479 : ticket, ticket == null); 1480 } catch (SSLIOException ex) { 1481 log.info("An unexpected error has occured.", ex.getRealException()); log.info("SSL-Explorer Agent must now exit"); gui.showDisconnected(); 1486 gui.error(Messages.getString("VPNClient.close"), null, Messages.getString("VPNClient.error"), Messages.getString("VPNClient.failedToConnect"), ex); System.exit(4); 1490 } catch (IOException ex) { 1491 log.info("An unexpected error has occured.", ex); log.info("SSL-Explorer Agent must now exit"); gui.error(Messages.getString("VPNClient.close"), null, Messages.getString("VPNClient.error"), Messages.getString("VPNClient.failedToConnect"), ex); gui.showDisconnected(); 1499 System.exit(4); 1500 } catch (Throwable t) { 1501 gui.error(Messages.getString("VPNClient.close"), null, Messages.getString("VPNClient.error"), Messages.getString("VPNClient.failedToConnect"), t); log.info("Critical failure", t); gui.showDisconnected(); 1508 System.exit(4); 1509 } 1510 } 1511 1512 public void setupProxy(String localProxyURL, String userAgent, 1513 String pluginProxyURL) throws MalformedURIException { 1514 if (localProxyURL != null 1515 && !localProxyURL.equals("") && !localProxyURL.startsWith("browser://")) { 1518 log.info("Setting user specified local proxy URL to " + obfuscateURL(localProxyURL)); setLocalProxyURL(localProxyURL); 1522 } else { 1523 log.info("Attempting to detect proxy settings using platform specific methods"); 1527 if (localProxyURL != null && localProxyURL.startsWith("browser://")) { 1529 URI uri = new URI(localProxyURL); 1530 1531 1539 String proxyURL = null; 1540 if (userAgent != null) { 1541 1542 1544 BrowserProxySettings proxySettings = null; 1545 if (userAgent.indexOf("MSIE") != -1) { try { 1547 log.info("Looking for IE"); proxySettings = ProxyUtil.lookupIEProxySettings(); 1551 } catch (Throwable t) { 1552 log 1554 .error( 1555 "Failed to get IE proxy settings, trying Firefox.", t); } 1558 } 1559 1560 if (proxySettings == null 1561 && userAgent.indexOf("Firefox") != -1) { try { 1563 log.info("Looking for Firefox"); proxySettings = ProxyUtil 1567 .lookupFirefoxProxySettings(); 1568 } catch (Throwable t) { 1569 log.error( 1571 "Failed to get Firefox proxy settings.", t); } 1574 } 1575 if (proxySettings != null) { 1576 log.info("Found some proxy settings."); ProxyInfo[] proxyInfo = proxySettings.getProxies(); 1580 for (int i = 0; proxyInfo != null 1581 && i < proxyInfo.length; i++) { 1582 log 1584 .info("Checking if " + obfuscateURL(proxyInfo[i].toUri()) + " is suitable."); if (proxyInfo[i].getProtocol().equals("ssl") || proxyInfo[i].getProtocol().equals("https") || proxyInfo[i].getProtocol().equals("all")) { StringBuffer buf = new StringBuffer ("http://"); if (proxyInfo[i].getUsername() != null 1590 && !proxyInfo[i].getUsername().equals( 1591 "")) { buf.append(proxyInfo[i].getUsername()); 1593 if (proxyInfo[i].getPassword() != null 1594 && !proxyInfo[i].getPassword() 1595 .equals("")) { buf.append(":"); buf.append(proxyInfo[i].getPassword()); 1598 } 1599 buf.append("@"); } 1601 buf.append(proxyInfo[i].getHostname()); 1602 if (proxyInfo[i].getPort() != 0) { 1603 buf.append(":"); buf.append(proxyInfo[i].getPort()); 1605 } 1606 if (uri.getHost() != null) { 1607 buf.append("?"); buf.append(uri.getHost()); 1609 } 1610 proxyURL = buf.toString(); 1611 break; 1612 } 1613 } 1614 } else { 1615 log 1617 .warn("No useragent supplied, automatic proxy could not check for browse type."); } 1620 1621 if (proxyURL == null && pluginProxyURL != null 1624 && !pluginProxyURL.equals("")) { log.info("Using plugin supplied proxy settings."); proxyURL = pluginProxyURL; 1629 } 1630 } 1631 1632 if (proxyURL != null) { 1633 log 1635 .info("Setting local proxy URL to " + obfuscateURL(proxyURL) + "."); setLocalProxyURL(proxyURL); 1638 } 1639 } 1640 } 1641 } 1642 1643 private void cleanupWindowsAgent() { 1644 1645 log.info("Clearing Windows agent cache"); 1649 try { 1650 String [] cmds = null; 1651 1652 String homeDir = Utils.getHomeDirectory(); 1653 1654 File cwd = getConfiguration().getCacheDir(); 1655 log.info("Will remove " + cwd.getAbsolutePath()); File scriptFile = new File (homeDir, "sslexplorer-agent-cleanup.bat"); 1659 File launchFile = new File (homeDir, 1660 "sslexplorer-agent-cleanup-launch.bat"); 1661 String scriptContents = "@echo off\r\n" 1662 + "echo SSL-Explorer Agent is removing all downloaded files\r\n" 1663 + ":Repeat\r\n" + "rd /S /Q \"" + cwd.getAbsolutePath() 1664 + "\" > NUL 2>&1\r\n" + "if exist \"" 1665 + cwd.getAbsolutePath() + "\" > NUL 2>&1 goto Repeat\r\n"; 1666 1667 File toRemove; 1668 for (Enumeration e = getConfiguration().getFilesToRemove(); e 1669 .hasMoreElements();) { 1670 toRemove = (File ) e.nextElement(); 1671 if (toRemove.exists()) { 1672 if (toRemove.isDirectory()) { 1673 scriptContents += "rd /S /Q \"" 1674 + toRemove.getAbsolutePath() 1675 + "\" > NUL 2>&1\r\n"; 1676 } else { 1677 scriptContents += "del \"" + toRemove.getAbsolutePath() 1678 + "\" > NUL 2>&1\r\n"; 1679 } 1680 } 1681 } 1682 scriptContents += "del \"" + scriptFile.getAbsolutePath() 1683 + "\" > NUL 2>&1 && exit\r\n"; 1684 1685 String launchScript = "start \"SSL-Explorer Agent Cleanup\" /MIN \"" 1686 + scriptFile.getAbsolutePath() 1687 + "\"\r\n" 1688 + "del \"" 1689 + launchFile.getAbsolutePath() + "\" > NUL 2>&1\r\n"; 1690 1691 cmds = new String [3]; 1692 cmds[0] = "cmd.exe"; 1693 cmds[1] = "/C"; 1694 cmds[2] = "\"" + launchFile.getAbsolutePath() + "\""; 1695 1696 FileOutputStream out = new FileOutputStream (scriptFile); 1697 out.write(scriptContents.getBytes()); 1698 out.close(); 1699 1700 out = new FileOutputStream (launchFile); 1701 out.write(launchScript.getBytes()); 1702 out.close(); 1703 1704 final Process proc = Runtime.getRuntime().exec(cmds); 1705 1706 Thread t1 = new Thread (new Runnable () { 1707 public void run() { 1708 try { 1709 InputStream in = proc.getInputStream(); 1710 while (in.read() > -1) 1711 ; 1712 } catch (IOException e) { 1713 } 1714 } 1715 }, "CleanupAgentInput"); 1716 Thread t2 = new Thread (new Runnable () { 1717 public void run() { 1718 try { 1719 InputStream in = proc.getErrorStream(); 1720 while (in.read() > -1) 1721 ; 1722 } catch (IOException e) { 1723 } 1724 } 1725 }, "CleanupAgentOutput"); 1726 1727 t1.start(); 1728 t2.start(); 1729 1730 } catch (Exception e) { 1731 1732 } 1733 } 1734 1735 1739 public void scheduleExit() { 1740 Thread t = new Thread ("ScheduledExit") { 1741 public void run() { 1742 try { 1743 Thread.sleep(getConfiguration().getShutdownPeriod()); 1744 } catch (InterruptedException ex) { 1745 } 1746 gui.dispose(); 1747 log.info("Exiting JVM."); System.exit(0); 1751 } 1752 }; 1753 t.start(); 1754 } 1755 1756 private void disconnected() { 1757 currentState = STATE_DISCONNECTED; 1758 getGUI().showDisconnected(); 1759 } 1760 1761 private void disconnectAgent() { 1762 1763 log.info("Disconnecting Agent"); keepAlive.stopThread(); 1768 con.disconnect("The agent is shutting down"); 1769 httpConnection.close(); 1771 } 1772 1773 private void cleanupLinuxAgent() { 1774 1775 log.info("Clearing Linux agent cache"); 1779 try { 1780 String [] cmds = null; 1781 String homeDir = Utils.getHomeDirectory(); 1782 File cacheDir = getConfiguration().getCacheDir(); 1783 log.info("Will remove " + cacheDir.getAbsolutePath()); File scriptFile = new File (homeDir, "sslexplorer-agent-cleanup.sh"); 1787 File launchFile = new File (homeDir, 1788 "sslexplorer-agent-cleanup-launch.sh"); 1789 1790 StringBuffer scriptContents = new StringBuffer (); 1792 scriptContents.append("#!/bin/sh\n"); 1793 scriptContents.append("sleep 3\n"); 1794 scriptContents.append("rm -fr \""); 1795 scriptContents.append(cacheDir.getAbsolutePath()); 1796 scriptContents.append("\" \""); 1797 1798 File toRemove; 1799 for (Enumeration e = getConfiguration().getFilesToRemove(); e 1800 .hasMoreElements();) { 1801 toRemove = (File ) e.nextElement(); 1802 scriptContents.append(toRemove.getAbsolutePath()); 1803 scriptContents.append("\" \""); 1804 } 1805 1806 scriptContents.append(scriptFile.getAbsolutePath()); 1807 scriptContents.append("\" \""); 1808 scriptContents.append(launchFile.getAbsolutePath()); 1809 scriptContents.append("\"\n"); 1810 1811 StringBuffer launchScript = new StringBuffer (); 1813 launchScript.append("#!/bin/sh\n"); 1814 launchScript.append("nohup sh \""); 1815 launchScript.append(scriptFile.getAbsolutePath()); 1816 launchScript.append("\" &\n"); 1817 1818 cmds = new String [2]; 1819 cmds[0] = "sh"; 1820 cmds[1] = launchFile.getAbsolutePath(); 1821 1822 FileOutputStream out = new FileOutputStream (scriptFile); 1823 out.write(scriptContents.toString().getBytes()); 1824 out.close(); 1825 1826 out = new FileOutputStream (launchFile); 1827 out.write(launchScript.toString().getBytes()); 1828 out.close(); 1829 1830 final Process proc = Runtime.getRuntime().exec(cmds); 1831 1832 Thread t1 = new Thread (new Runnable () { 1833 public void run() { 1834 try { 1835 InputStream in = proc.getInputStream(); 1836 while (in.read() > -1) 1837 ; 1838 } catch (IOException e) { 1839 } 1840 } 1841 }); 1842 Thread t2 = new Thread (new Runnable () { 1843 public void run() { 1844 try { 1845 InputStream in = proc.getErrorStream(); 1846 while (in.read() > -1) 1847 ; 1848 } catch (IOException e) { 1849 } 1850 } 1851 }); 1852 1853 t1.start(); 1854 t2.start(); 1855 1856 } catch (Exception e) { 1857 1858 } 1859 } 1860 1861 protected void updateResources(int resourceTypeId) { 1862 if (getConfiguration().isGetResources()) { 1863 1867 1868 if(resourceTypeId == -1 || resourceTypeId == ApplicationManager.APPLICATION_SHORTCUT_RESOURCE_TYPE_ID) 1870 applicationManager.getApplicationResources(); 1871 1872 if(resourceTypeId == -1 || resourceTypeId == TunnelManager.TUNNEL_RESOURCE_TYPE_ID) 1874 tunnelManager.getTunnelResources(); 1875 1876 if(resourceTypeId == -1 || resourceTypeId == WebForwardManager.WEBFORWARD_RESOURCE_TYPE_ID) 1878 webForwardManager.getWebForwardResources(); 1879 1880 if(resourceTypeId == -1 || resourceTypeId == NetworkPlaceManager.NETWORK_PLACE_RESOURCE_TYPE_ID) 1882 networkPlaceManager.getNetworkPlaceResources(); 1883 } 1884 } 1885 1886 class KeepAliveThread extends Thread { 1887 1888 boolean running = true; 1889 1890 Request keepAlive = new Request("keepalive@3sp.com"); 1891 1892 public void run() { 1893 1894 long period = getConfiguration().getKeepAlivePeriod(); 1895 1896 while (running && con.isRunning()) { 1897 try { 1898 Thread.sleep(period); 1899 } catch (InterruptedException e) { 1900 } 1901 1902 if (!running || !con.isRunning()) { 1903 break; 1904 } 1905 1906 try { 1907 con.sendRequest(keepAlive, true, getConfiguration() 1908 .getKeepAliveTimeout()); 1909 } catch (InterruptedIOException ex) { 1910 log.error("Keepalive packet timed out!! Agent connection is no longer operational", ex); 1912 if (getConfiguration().isDisplayInformationPopups()) { 1914 getGUI().popup( 1915 null, 1916 Messages.getString("VPNClient.keepalive.timeout"), Messages.getString("VPNClient.title"), "popup-error", -1); } 1918 try { 1919 Thread.sleep(10000); 1920 } catch (InterruptedException e) { 1921 } 1922 Agent.this.startShutdownProcedure(); 1923 } catch (IOException e) { 1924 log.error("Keepalive IO error!! Agent connection is no longer operational", e); 1926 if (getConfiguration().isDisplayInformationPopups()) { 1928 getGUI().popup( 1929 null, 1930 Messages.getString("VPNClient.keepalive.error"), Messages.getString("VPNClient.title"), "popup-error", -1); } 1932 try { 1933 Thread.sleep(10000); 1934 } catch (InterruptedException e2) { 1935 } 1936 Agent.this.startShutdownProcedure(); 1937 } 1938 } 1939 1940 } 1941 1942 public void stopThread() { 1943 running = false; 1944 interrupt(); 1945 } 1946 } 1947} 1948 | Popular Tags |