/* * Jeti, a Java Jabber client, Copyright (C) 2003 E.S. de Boer * * This program 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 program 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 program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For questions, comments etc, * use the website at http://jeti.jabberstudio.org * or mail/im me at jeti@jabber.org */ package nu.fw.jeti.backend; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; import java.security.KeyManagementException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateNotYetValidException; import java.security.cert.X509Certificate; import java.text.MessageFormat; import java.util.Iterator; import javax.net.ssl.HandshakeCompletedEvent; import javax.net.ssl.HandshakeCompletedListener; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPasswordField; import javax.swing.JTextField; import javax.swing.border.EmptyBorder; import nu.fw.jeti.events.DiscoveryListener; import nu.fw.jeti.events.LoginListener; import nu.fw.jeti.jabber.Backend; import nu.fw.jeti.jabber.JID; import nu.fw.jeti.jabber.elements.DiscoveryInfo; import nu.fw.jeti.jabber.elements.DiscoveryItem; import nu.fw.jeti.jabber.elements.IQAuth; import nu.fw.jeti.jabber.elements.IQAuthBuilder; import nu.fw.jeti.jabber.elements.IQExtension; import nu.fw.jeti.jabber.elements.IQPrivate; import nu.fw.jeti.jabber.elements.IQXRoster; import nu.fw.jeti.jabber.elements.InfoQuery; import nu.fw.jeti.jabber.elements.JetiPrivateExtension; import nu.fw.jeti.jabber.elements.JetiPrivateRosterExtension; import nu.fw.jeti.jabber.elements.Packet; import nu.fw.jeti.jabber.elements.Presence; import nu.fw.jeti.jabber.elements.PresenceBuilder; import nu.fw.jeti.jabber.elements.StreamError; import nu.fw.jeti.plugins.PluginsInfo; import nu.fw.jeti.plugins.XMPP; import nu.fw.jeti.util.Digest; import nu.fw.jeti.util.I18N; import nu.fw.jeti.util.Log; import nu.fw.jeti.util.Utils; /** * @author E.S. de Boer */ //TODO stop packet start spul en de andere dingen in aparte class?? //TODO improve error reporting, make it translatable //class voor connectie public class Connect implements ConnectionPacketReceiver { private Output output; private Input input; private String authenticationId="yytr"; private JabberHandler jabberHandler; private LoginInfo loginInfo; private Backend backend; private static JID myJID = new JID("test","test","test"); private boolean authenticated = false; private boolean reconnecting = false; private long latestConnected=0; private int show; private String status; private String connectionID; private Discovery discovery; private OwnCapabilities capabilities; private Socket socket;//socket needed to close if abort private Thread connectThread;//login thread private volatile boolean abort = false;//abort login private IQTimerQueue iqTimerQueue; private Handlers handlers; private XMPP xmpp; // windowProxy private JButton buttonCancel; private JButton buttonOk; private JDialog dialog; private JLabel infoLabel; private JLabel lblUsername; private JLabel lblPassword; private JPanel buttonPanel; private JPanel panelMain; private JPasswordField txtPassword; private JOptionPane optionPane; private JTextField txtUsername; public Connect(Backend backend,IQTimerQueue timerQueue,Handlers handlers) { this.backend = backend; iqTimerQueue = timerQueue; this.handlers = handlers; discovery = new Discovery(backend) ; capabilities = new OwnCapabilities(backend); } public void addCapability(String capability,String feature) { capabilities.addCapability(capability, feature); } public void removeCapability(String capability,String feature) { capabilities.removeCapability(capability, feature); } public int getStatus() { return show; } public void getItems(JID jid, DiscoveryListener listener, boolean useCache) { discovery.getItems(jid,listener,useCache); } public void getItems(JID jid, DiscoveryListener listener) { discovery.getItems(jid,listener); } public void getInfo(JID jid, DiscoveryListener listener) { discovery.getInfo(jid,listener); } public void getItems(JID jid,String node, DiscoveryListener listener) { discovery.getItems(jid,node,listener); } public void getInfo(JID jid,String node, DiscoveryListener listener) { discovery.getInfo(jid,node,listener); } public boolean isLoggedIn() { return authenticated; } public boolean isPasswordValid(String password) { return loginInfo.getPassword().equals(password); } public void login(LoginInfo info) { autoLogin(info,2); } public void autoLogin(LoginInfo info,final int tries) { abort = false; loginInfo = info; connectThread = new Thread() { int tel = 0; public void run() { boolean connected = false; int triesc = 0; int posIn = 0; int posFi = 0; String hosts = loginInfo.getHost(); if( hosts.indexOf(" ") != -1 ) { hosts = hosts + " "; for( int i = 0; i < hosts.length(); i++ ) { String w = String.valueOf(hosts.charAt(i)); if( w.equals(" ") ) { posIn = posFi; posFi = i; String hostConnect = hosts.substring(posIn, posFi).trim(); while( tel < tries ) { if( tel == 0) { connected = connect( hostConnect, false ); } else { connected = connect( hostConnect, true ); } if( connected ) { i = hosts.length(); break; } try { Thread.sleep(600);} catch (InterruptedException e){} tel++; } tel = 0; } } } else { while( tel < tries ) { if( tel == 0) { connected = connect( hosts, false ); } else { connected = connect( hosts, true ); } if( connected ) { break; } try { Thread.sleep(600);} catch (InterruptedException e){} tel++; } } if( !connected ) { interrupt(); loginInfo.setProxyUsername(null); loginInfo.setProxyPassword(null); System.out.println("***** Login Failed *****"); } } }; connectThread.start(); } public void abort() { abort = true; if( socket != null ) { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } connectThread.interrupt(); disconnect(); } public boolean isAborted() { return abort; } synchronized private boolean connect( String host, boolean proxy ) { latestConnected = System.currentTimeMillis(); if( loginInfo == null ) return true; if( authenticated ) disconnect();//clear old connection jabberHandler = new JabberHandler(this,handlers); if( xmpp == null && PluginsInfo.isPluginLoaded("xmpp") ) { xmpp = (XMPP)PluginsInfo.newPluginInstance("xmpp"); handlers.loadExtraHandlers(xmpp.getXMPPHandlers()); } try { if (host == null || host.length() == 0) { if(loginInfo.useProxy(LoginInfo.NO_PROXY) && PluginsInfo.isPluginLoaded("xmpp")) { host = xmpp.resolveXMPPDomain(loginInfo.getServer()); } else host = loginInfo.getServer(); } if( loginInfo.isSSl() ) { if( proxy ) { //System.out.println("CONNECT COM PROXY - SEGURA : " + host); Socket tunnel = createHTTPTunel(host); socket = new DummySSLSocketFactory().createSocket(tunnel, host, loginInfo.getPort(),true); } else { //System.out.println("CONNECT SEM PROXY - SEGURA : " + host); socket = new DummySSLSocketFactory().createSocket(host,loginInfo.getPort()); } } else { if( proxy ) { //System.out.println("CONNECT COM PROXY - NÃO SEGURA : " + host); socket = createHTTPTunel(host); } else { //System.out.println("CONNECT SEM PROXY - NÃO SEGURA : " + host); socket = new Socket( host,loginInfo.getPort() ); } } } catch (UnknownHostException ex){ return false; } catch (IOException ex){ return false; } if( abort ) return false; try { input = new Input(socket.getInputStream(), this, jabberHandler); } catch (IOException ex){ return false; } if( abort ) return false; try { output = new Output(socket, loginInfo.getServer(), this, socket.getOutputStream()); } catch (IOException ex){ return false; } return true; } String host; public boolean startTls(ConnectionPacketReceiver cpr) { if(abort) return false; try { //TODO stop output output.disconnect(false); input.disconnect(); socket = new DummySSLSocketFactory().createSocket(socket,host,loginInfo.getPort(),true); jabberHandler = new JabberHandler(cpr,handlers); try { input = new Input(socket.getInputStream(),this,jabberHandler); } catch (IOException ex) { return false; } try { output = new Output(socket,loginInfo.getServer(),this,socket.getOutputStream()); } catch (IOException ex) { //sendLoginError(I18N.gettext("main.loginstatus.Could_not_open_output_because") + " " +ex.getMessage()); return false; } if(abort) return false; } catch(IOException e){} return true; } //used by compression plugin public Socket getSocket() { return socket; } public boolean startCompressed(ConnectionPacketReceiver cpr,InputStream inputStream,OutputStream outputStream) { jabberHandler = new JabberHandler(cpr,handlers); if ( abort ) return false; output.disconnect(false); Input input2 = input; input = new Input(inputStream,this,jabberHandler); try { output = new Output(socket,loginInfo.getServer(),this,outputStream); } catch (IOException ex) { sendLoginError(I18N.gettext("main.loginstatus.Could_not_open_output_because") + " " +ex.getMessage()); ex.printStackTrace(); return false; } if ( abort ) return false; input2.disconnect(); //FIXME Using thread.stop because throwing an exception to stop the sax parser in the input thread fails input2.stop(); //throw new RuntimeException(); return true; } public void startSasl(ConnectionPacketReceiver cpr) { if( abort ) return; //kill old input and send new stream //input.disconnect(); jabberHandler = new JabberHandler(cpr,handlers); try { input = new Input(socket.getInputStream(),this,jabberHandler); } catch (IOException e) { e.printStackTrace(); } try { output.writeHeader(); } catch (IOException e) { e.printStackTrace(); } throw new UnsupportedOperationException("end xmlparser"); } private Socket createHTTPTunel(String host) throws IOException { String tunnelHost = loginInfo.getProxyServer(); int tunnelPort = Integer.valueOf(loginInfo.getProxyPort()).intValue(); String typeProxy = typeProxy(tunnelHost, tunnelPort, host, loginInfo.getPort()); if( typeProxy.indexOf("Proxy-Authenticate: Digest") != -1 ) { // Proxy Username and Password if( loginInfo.getProxyPassword() == null && loginInfo.getProxyPassword() == null) windowProxy(tunnelHost); return doTunnelHandshakeDigest(host, loginInfo.getPort()); } else if( typeProxy.indexOf("Proxy-Authenticate: Basic") != -1 ) { // Proxy Username and Password if( loginInfo.getProxyPassword() == null && loginInfo.getProxyPassword() == null) windowProxy(tunnelHost); Socket tunnel = new Socket(tunnelHost, tunnelPort); doTunnelHandshake(tunnel, host, loginInfo.getPort()); return tunnel; } else if( typeProxy.indexOf("HTTP/1.0 200") != -1 ) { Socket tunnel = new Socket(tunnelHost, tunnelPort); PrintWriter writeConnection = new PrintWriter( tunnel.getOutputStream(), true ); BufferedReader readConnection = new BufferedReader(new InputStreamReader(tunnel.getInputStream())); String msg = "CONNECT " + host + ":" + loginInfo.getPort() + " HTTP/1.1\r\n" + "User-Agent: " + sun.net.www.protocol.http.HttpURLConnection.userAgent + "\r\n" + "Proxy-Connection: Keep-Alive\r\n"; writeConnection.println(msg); String line = ""; while((line = readConnection.readLine()) != null ) { if( line.indexOf("HTTP/1.0 200") != -1 ) break; } return tunnel; } return new Socket(); } private void windowProxy(String tunnelHost) { panelMain = new JPanel(); panelMain.setBackground(Color.ORANGE); panelMain.setPreferredSize(new Dimension(400,120)); panelMain.setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); // Espaco entre elementos; gbc.insets = new Insets(2, 2, 2, 2); gbc.gridy = 0; // row gbc.gridx = 0; // col gbc.gridwidth = 2; gbc.anchor = GridBagConstraints.WEST; infoLabel = new JLabel(I18N.gettext("main.connect.proxy.Authentication_for") + " " + tunnelHost + " :"); infoLabel.setFont(new Font("SansSerif",Font.BOLD, 14)); infoLabel.setBorder(new EmptyBorder(0, 0, 5, 0)); panelMain.add(infoLabel, gbc); // Label Username gbc.gridy = 1; // row gbc.gridx = 0; // col gbc.gridwidth = 1; lblUsername = new JLabel(I18N.gettext("main.connect.proxy.Username")+":"); panelMain.add(lblUsername, gbc); // JTextField do Username gbc.gridy = 1; // row gbc.gridx = 1; // col txtUsername = new JTextField(20); panelMain.add(txtUsername, gbc); // Label Password gbc.gridy = 2; // row gbc.gridx = 0; // col lblPassword = new JLabel(I18N.gettext("main.connect.proxy.Password")+":"); panelMain.add(lblPassword, gbc); // JPasswordField gbc.gridy = 2; // row gbc.gridx = 1; // col txtPassword = new JPasswordField(20); panelMain.add(txtPassword, gbc); // Buttons gbc.gridy = 3; // linha gbc.gridx = 1; // coluna gbc.gridwidth = 2; // duas células na linha gbc.anchor = GridBagConstraints.WEST; buttonPanel = new JPanel(); buttonCancel = new JButton(I18N.gettext("main.connect.proxy.Cancel")); buttonOk = new JButton(I18N.gettext("main.connect.proxy.Ok")); // Event click Ok buttonOk.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { String Username = txtUsername.getText().toString(); String Password = txtPassword.getText().toString(); if( !Username.trim().equals("") && !Password.trim().equals("") ) { loginInfo.setProxyUsername(Username); loginInfo.setProxyPassword(Password); dialog.setVisible(false); } } }); // Event click Cancel buttonCancel.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { loginInfo.setProxyUsername(null); loginInfo.setProxyPassword(null); dialog.setVisible(false); } }); buttonPanel.setBackground(Color.ORANGE); buttonPanel.add(buttonOk); buttonPanel.add(buttonCancel); panelMain.add(buttonPanel, gbc); optionPane = new JOptionPane(); optionPane.setMessage(I18N.gettext("main.connect.proxy.The_proxy_is_requesting_a_username_and_password") + "!"); optionPane.setMessageType(JOptionPane.INFORMATION_MESSAGE); optionPane.setOptions(new Object[] {panelMain}); dialog = optionPane.createDialog(null, I18N.gettext("main.connect.proxy.Authentication_required")); dialog.setVisible(true); } private String typeProxy(String proxyServer, int proxyPort, String host, int port) throws IOException { Socket connection = new Socket(proxyServer, proxyPort); PrintWriter writeConnection = new PrintWriter( connection.getOutputStream(), true ); BufferedReader readConnection = new BufferedReader(new InputStreamReader(connection.getInputStream())); String _return = ""; String line = ""; int count = 0; String msg = "CONNECT " + host + ":" + port + " HTTP/1.1\r\n" + "User-Agent: " + sun.net.www.protocol.http.HttpURLConnection.userAgent + "\r\n" + "Proxy-Connection: Keep-Alive\r\n"; writeConnection.println(msg); while((line = readConnection.readLine()) != null ) { if( line.indexOf("Proxy") != -1 ) _return += line + "\n"; if( line.indexOf("Proxy-Connection: close") != -1 || count == 12 ) break; if( line.indexOf("HTTP/1.0 200") != -1 ) { _return += line + "\n"; break; } count++; } writeConnection.close(); readConnection.close(); connection.close(); return _return; } // Proxy Authorization: Basic private void doTunnelHandshake(Socket tunnel, String host, int port) throws IOException { OutputStream out = tunnel.getOutputStream(); String msg = "CONNECT " + host + ":" + port + " HTTP/1.0\n" + "User-Agent: " + sun.net.www.protocol.http.HttpURLConnection.userAgent; if ( loginInfo.getProxyUsername() != null && loginInfo.getProxyPassword() != null ) { //add basic authentication header for the proxy sun.misc.BASE64Encoder enc = new sun.misc.BASE64Encoder(); String encodedPassword = enc.encode((loginInfo.getProxyUsername() + ":" + loginInfo.getProxyPassword()).getBytes()); msg = msg + "\nProxy-Authorization: Basic " + encodedPassword; } msg = msg + "\nContent-Length: 0" + "\nPragma: no-cache" + "\r\n\r\n"; byte b[]; try { /* * We really do want ASCII7 -- the http protocol doesn't change * with locale. */ b = msg.getBytes("ASCII7"); } catch (UnsupportedEncodingException ignored) { /* * If ASCII7 isn't there, something serious is wrong, but * Paranoia Is Good (tm) */ b = msg.getBytes(); } out.write(b); out.flush(); /* * We need to store the reply so we can create a detailed error * message to the user. */ byte reply[] = new byte[200]; int replyLen = 0; int newlinesSeen = 0; boolean headerDone = false; /* Done on first newline */ InputStream in = tunnel.getInputStream(); while ( newlinesSeen < 2 ) { int i = in.read(); if (i < 0) { throw new IOException("Unexpected EOF from proxy"); } if (i == '\n') { headerDone = true; ++newlinesSeen; } else if (i != '\r') { newlinesSeen = 0; if (!headerDone && replyLen < reply.length) { reply[replyLen++] = (byte) i; } } } /* * Converting the byte array to a string is slightly wasteful in the * case where the connection was successful, but it's insignificant * compared to the network overhead. */ String replyStr; try { replyStr = new String(reply, 0, replyLen, "ASCII7"); } catch (UnsupportedEncodingException ignored) { replyStr = new String(reply, 0, replyLen); } /* * We check for Connection Established because our proxy returns * HTTP/1.1 instead of 1.0 */ // if (!replyStr.startsWith("HTTP/1.0 200")) { if (replyStr.toLowerCase().indexOf("200 connection established") == -1) { String tunnelHost = System.getProperty("http.proxyHost"); String tunnelPort = System.getProperty("http.proxyPort"); throw new IOException("Unable to tunnel through " + tunnelHost + ":" + tunnelPort + ". Proxy returns \"" + replyStr + "\""); } /* tunneling Handshake was successful! */ } //Proxy-Authenticate Digest private Socket doTunnelHandshakeDigest(String host, int port) throws IOException { Digest hashProxy = new Digest(); String response = ""; String nonce = ""; String cnonce = "ALEC290908" + String.valueOf(System.currentTimeMillis()); String qop = ""; String uri = "/"; String username = loginInfo.getProxyUsername(); String password = loginInfo.getProxyPassword(); String realm = ""; String line = ""; // Dados Proxy String proxyServer = loginInfo.getProxyServer(); int proxyPort = Integer.valueOf(loginInfo.getProxyPort()).intValue(); // PRIMEIRA PARTE Socket tunnel = new Socket(proxyServer, proxyPort); PrintWriter writeTunnel = new PrintWriter(tunnel.getOutputStream(), true); BufferedReader readTunnel = new BufferedReader(new InputStreamReader(tunnel.getInputStream())); String msg = "CONNECT " + host + ":" + port + " HTTP/1.1\r\n" + "User-Agent: " + sun.net.www.protocol.http.HttpURLConnection.userAgent + "\r\n" + "Proxy-Connection: Keep-Alive\r\n"; writeTunnel.println(msg); while((line = readTunnel.readLine()) != null ) { // Get nonce; if ( line.indexOf("nonce=\"") != -1 ) { nonce = line.substring(line.indexOf("nonce=\"") + 7); nonce = nonce.substring(0,nonce.indexOf("\",")); } // Get realm; if ( line.indexOf("realm=\"") != -1 ) { realm = line.substring(line.indexOf("realm=\"") + 7); realm = realm.substring(0,realm.indexOf("\",")); } // Get qop; if ( line.indexOf("qop=\"") != -1 ) { qop = line.substring(line.indexOf("qop=\"") + 5); qop = qop.substring(0,qop.indexOf("\",")); } } writeTunnel.close(); readTunnel.close(); tunnel.close(); response = hashProxy.hashMD5(nonce, cnonce, qop, "CONNECT:"+uri, username, password, realm); line = ""; // SEGUNDA PARTE tunnel = new Socket(proxyServer, proxyPort); writeTunnel = new PrintWriter(tunnel.getOutputStream(), true); readTunnel = new BufferedReader(new InputStreamReader(tunnel.getInputStream())); msg = "CONNECT " + host + ":" + port + " HTTP/1.1\r\n" + "Proxy-Authorization: Digest username=\""+username+"\", "+ "realm=\""+realm+"\", nonce=\""+nonce+"\", uri=\""+uri+"\", " + "cnonce=\""+cnonce+"\", nc=00000001, qop=\""+qop+"\", response=\""+response+"\"\r\n" + "User-Agent: " + sun.net.www.protocol.http.HttpURLConnection.userAgent + "\r\n" + "Proxy-Connection: Keep-Alive\r\n"; int count = 0; writeTunnel.println(msg); while((line = readTunnel.readLine().trim()) != null ) { if( line.indexOf("HTTP/1.0 200 OK") != -1 ) break; if( line.indexOf("HTTP/1.0 503") != -1 ) break; if( count == 1 ) break; count++; } /* tunneling Handshake was successful! */ return tunnel; } private void sendLoginMessage(String message) { for(Iterator j = backend.getListeners(LoginListener.class);j.hasNext();) { ((LoginListener)j.next()).loginMessage(message); } } private void sendLoginStatus(int count) { /*for(Iterator j = backend.getListeners(LoginListener.class);j.hasNext();) { ((LoginListener)j.next()).loginStatus(count); }*/ } public void sendLoginError(String message) { for(Iterator j = backend.getListeners(LoginListener.class);j.hasNext();) { ((LoginListener)j.next()).loginError(message); } } public void sendUnauthorized() { for(Iterator j = backend.getListeners(LoginListener.class);j.hasNext();) { ((LoginListener)j.next()).unauthorized(); } } synchronized public void connected(String connectionID,String xmppVersion) { if(!abort) { if(xmppVersion!=null && PluginsInfo.isPluginLoaded("xmpp")) { ConnectionPacketReceiver cpr = xmpp.getConnectionPacketReceiver(loginInfo,this); jabberHandler.changePacketReceiver(cpr); cpr.connected(connectionID, xmppVersion); } else { jabberHandler.changePacketReceiver(this); socket = null; //clear socket reference this.connectionID = connectionID; // TODO remove lowercase if filetransfer bug fixed output.send(new InfoQuery(null,"get",new IQAuth(loginInfo.getUsername().toLowerCase(),null,null))); } } } public void authenticate(IQAuth iqAuth) { if(!abort) { authenticationId = "Jeti_Auth_" + new java.util.Date().getTime(); if(iqAuth.hasDigest()) { MessageDigest sha = null; try { sha = MessageDigest.getInstance("SHA"); } catch (Exception ex){ Log.error(I18N.gettext("main.loginstatus.Could_not_login_with_SHA")); // TODO remove lowercase if filetransfer bug fixed output.send(new InfoQuery(null,"set",authenticationId,new IQAuth(loginInfo.getUsername().toLowerCase(),loginInfo.getPassword() ,loginInfo.getResource()))); return; } sha.update(connectionID.getBytes()); String digest = Utils.toString(sha.digest(loginInfo.getPassword().getBytes())); IQAuthBuilder iqab = new IQAuthBuilder(); iqab.digest = digest; // TODO remove lowercase if filetransfer bug fixed iqab.username = loginInfo.getUsername().toLowerCase(); iqab.resource = loginInfo.getResource(); output.send(new InfoQuery(null,"set",authenticationId,(IQExtension)iqab.build())); } else { if(!loginInfo.isSSl()) { int option = JOptionPane.showConfirmDialog(null, I18N.gettext("main.loginstatus.Sending_password_as_plain_text_over_an_unencrypted_connection,_continue?"),"Plain text",JOptionPane.YES_NO_OPTION); if (option == JOptionPane.NO_OPTION) { sendLoginError("Sending password in plain not allowed"); return; } } // TODO remove lowercase if filetransfer bug fixed output.send(new InfoQuery(null,"set",authenticationId,new IQAuth(loginInfo.getUsername().toLowerCase(),loginInfo.getPassword() ,loginInfo.getResource()))); } } } public void authenticated(InfoQuery infoQuery) { if(!abort) { if(infoQuery.getType().equals("error")) { if(infoQuery.getErrorCode() == 401) { sendUnauthorized(); } else { sendLoginError(I18N.gettext("main.loginstatus.Not_logged_in_because") + " " + infoQuery.getErrorDescription()); } return; } //TODO remove lowercase if filetransfer bug fixed JID jid = new JID(loginInfo.getUsername().toLowerCase(),loginInfo.getServer() ,loginInfo.getResource()); authenticated(jid); } } public void authenticated(JID jid) { myJID = jid; iqTimerQueue.clear();//remove iqs from previous connections jabberHandler.changePacketReceiver(new Jabber(backend,capabilities,discovery,iqTimerQueue)); authenticated = true; reconnecting = false; output.setAuthenticated(); //TODO increase timeout getItems(new JID(loginInfo.getServer()), new DiscoveryListener() { public void discoveryItemResult(JID jid, DiscoveryItem item) { //cache disco items for this server if (item.hasItems()) { for(Iterator i = item.getItems();i.hasNext();) { DiscoveryItem di = (DiscoveryItem)i.next(); backend.getInfo(di.getJID(),null); } } } public void discoveryInfoResult(JID jid, DiscoveryInfo info) {} }); output.send(new InfoQuery("get",new IQPrivate(new JetiPrivateExtension()))); output.send(new InfoQuery("get",new IQXRoster())); if(show == Presence.NONE) { show = Presence.AVAILABLE; } latestConnected = System.currentTimeMillis(); } public void connected() { sendStatus(); send(new InfoQuery("get",new IQPrivate(new JetiPrivateRosterExtension()))); for( Iterator j = backend.getListeners(nu.fw.jeti.events.StatusChangeListener.class) ; j.hasNext(); ) { //online ((nu.fw.jeti.events.StatusChangeListener)j.next()).connectionChanged(true); } } public void receivePackets(Packet packet) { if (packet instanceof StreamError) streamError((StreamError)packet); else if(authenticationId.equals(packet.getID())) authenticated((InfoQuery)packet); else if(packet instanceof InfoQuery) { IQExtension extension = packet.getIQExtension(); if(extension instanceof IQAuth) { if(((InfoQuery)packet).getType().equals("error")) { sendLoginError(packet.getErrorDescription()); } else authenticate((IQAuth) extension); } } } public void inputDeath() { try { if( socket != null ) socket.close(); } catch (IOException e) { e.printStackTrace(); } if((authenticated || reconnecting)) { authenticated = false; if (reconnecting) { try { Thread.sleep(10000); } catch (InterruptedException e) {}; } reconnecting = true; output.disconnect(true); for(Iterator j = backend.getListeners(nu.fw.jeti.events.StatusChangeListener.class);j.hasNext();) { //offline ((nu.fw.jeti.events.StatusChangeListener)j.next()).connectionChanged(false); } } } public void streamError(StreamError error) { //only when logging in if(authenticated) { authenticated = false; output.disconnect(true); for(Iterator j = backend.getListeners(nu.fw.jeti.events.StatusChangeListener.class);j.hasNext();) { //offline ((nu.fw.jeti.events.StatusChangeListener)j.next()).connectionChanged(false); } } sendLoginError(error.getErrorDescription()); } public void outputDeath() { authenticated = false; for(Iterator j = backend.getListeners(nu.fw.jeti.events.StatusChangeListener.class);j.hasNext();) { //offline ((nu.fw.jeti.events.StatusChangeListener)j.next()).connectionChanged(false); } } public static JID getMyJID() { return myJID; } public boolean getOnline() { return authenticated; } public void disconnect() { if( authenticated ) { send(new Presence(myJID, "unavailable")); authenticated = false; output.disconnect(true); } output = null; for(Iterator j = backend.getListeners(nu.fw.jeti.events.StatusChangeListener.class);j.hasNext();) { //offline ((nu.fw.jeti.events.StatusChangeListener)j.next()).connectionChanged(false); } } public void exit() { if(authenticated) { send(new nu.fw.jeti.jabber.elements.Presence(myJID,"unavailable")); authenticated = false; output.disconnect(true); } output = null; for(Iterator j = backend.getListeners(nu.fw.jeti.events.StatusChangeListener.class);j.hasNext();) {//exit ((nu.fw.jeti.events.StatusChangeListener)j.next()).exit(); } } public void send(Packet packet) { if(authenticated) output.send(packet); else nu.fw.jeti.util.Log.notSend(packet.toString()); } public void sendWhileConnecting(Packet packet) { output.send(packet); } public String getAccountInfo() { return MessageFormat.format(I18N.gettext("main.popup.logged_in_as_{0}_on_server_{1}_with_resource_{2}"),new Object[]{loginInfo.getUsername(),loginInfo.getServer(),loginInfo.getResource()}); } public void sendStatus() { if( authenticated ) { PresenceBuilder pb = new PresenceBuilder(); pb.show = show; pb.status = status; pb.priority = loginInfo.getPriority(); pb.addExtension(capabilities.getCaps()); try { send(pb.build()); } catch (InstantiationException e) { e.printStackTrace(); } for(Iterator j = backend.getListeners(nu.fw.jeti.events.StatusChangeListener.class);j.hasNext();) { ((nu.fw.jeti.events.StatusChangeListener)j.next()).ownPresenceChanged(show,status); } } } public void changeStatus(int show,String status) { this.show = show; this.status = status; sendStatus(); } public static class DummySSLSocketFactory extends SSLSocketFactory { private SSLSocketFactory factory; public DummySSLSocketFactory() { try { SSLContext sslcontent = SSLContext.getInstance("TLS"); sslcontent.init(null, // KeyManager not required new TrustManager[] {new DummyTrustManager()}, new java.security.SecureRandom()); factory = sslcontent.getSocketFactory(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (KeyManagementException e) { e.printStackTrace(); } } public Socket createSocket(Socket socket, String s, int i,boolean flag) throws IOException { return factory.createSocket(socket, s, i, flag); } public Socket createSocket(InetAddress inaddr, int i,InetAddress inaddr2, int j) throws IOException { return factory.createSocket(inaddr, i, inaddr2, j); } public Socket createSocket(InetAddress inaddr, int i) throws IOException { return factory.createSocket(inaddr, i); } public Socket createSocket(String s, int i, InetAddress inaddr, int j) throws IOException { return factory.createSocket(s, i, inaddr, j); } public Socket createSocket(String s, int i) throws IOException { /** * register a callback for handshaking completion event */ Socket so = factory.createSocket(s, i); ((SSLSocket)so).addHandshakeCompletedListener(new HandshakeCompletedListener() { public void handshakeCompleted(HandshakeCompletedEvent event) { System.out.println("** Handshake finished! **"); //System.out.println("\t CipherSuite:" + event.getCipherSuite()); //System.out.println("\t SessionId " + event.getSession()); //System.out.println("\t PeerHost " + event.getSession().getPeerHost()); } } ); return so; } public String[] getDefaultCipherSuites() { return factory.getSupportedCipherSuites(); } public String[] getSupportedCipherSuites() { return factory.getSupportedCipherSuites(); } } /** * Trust manager which accepts certificates without any validation * except date validation. */ private static class DummyTrustManager implements X509TrustManager { public void checkClientTrusted(X509Certificate[] chain, String authType) { } public void checkServerTrusted(X509Certificate[] chain, String authType) { try { chain[0].checkValidity(); } catch (CertificateExpiredException e){} catch (CertificateNotYetValidException e){} } public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } } } /* * Overrides for emacs * Local variables: * tab-width: 4 * End: */