From b1d5d5801e90ef0d4e282a78543f1435b8b7d223 Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Sat, 7 May 2016 19:57:10 +0300 Subject: STARTTLS --- .../java/com/juick/xmpp/s2s/ConnectionOut.java | 186 +++++++++++---------- 1 file changed, 102 insertions(+), 84 deletions(-) (limited to 'src/main/java/com/juick/xmpp/s2s/ConnectionOut.java') diff --git a/src/main/java/com/juick/xmpp/s2s/ConnectionOut.java b/src/main/java/com/juick/xmpp/s2s/ConnectionOut.java index 59fdfb60..4ebeffb6 100644 --- a/src/main/java/com/juick/xmpp/s2s/ConnectionOut.java +++ b/src/main/java/com/juick/xmpp/s2s/ConnectionOut.java @@ -1,140 +1,158 @@ package com.juick.xmpp.s2s; +import com.juick.xmpp.extensions.StreamFeatures; import com.juick.xmpp.utils.XmlUtils; import java.io.EOFException; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import java.nio.channels.AsynchronousSocketChannel; import java.nio.channels.Channels; import java.nio.channels.CompletionHandler; +import java.util.concurrent.ExecutionException; import java.util.logging.Level; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLSocket; + /** - * * @author ugnich */ -public class ConnectionOut extends Connection { +public class ConnectionOut extends Connection implements Runnable { public boolean streamReady = false; public String to; String checkSID = null; String dbKey = null; - public ConnectionOut(String hostname) { + public ConnectionOut(String hostname) throws Exception { super(); to = hostname; } - public ConnectionOut(String hostname, String checkSID, String dbKey) { + public ConnectionOut(String hostname, String checkSID, String dbKey) throws Exception { super(); to = hostname; this.checkSID = checkSID; this.dbKey = dbKey; } - public void parseStream() { - LOGGER.info("STREAM TO " + to + " START"); + void sendOpenStream() throws IOException { + sendStanza(""); + } + + void processDialback() throws Exception { + if (checkSID != null) { + sendDialbackVerify(checkSID, dbKey); + } + sendStanza("" + + generateDialbackKey(to, XMPPComponent.HOSTNAME, streamID) + ""); + } + @Override + public void run() { + LOGGER.info("STREAM TO " + to + " START"); try { HostnamePort addr = DNSQueries.getServerAddress(to); - socket = AsynchronousSocketChannel.open(); - socket.connect(new InetSocketAddress(addr.hostname, addr.port), socket, new CompletionHandler() { - @Override - public void completed(Void result, AsynchronousSocketChannel attachment) { - try { - parser.setInput(new InputStreamReader(Channels.newInputStream(socket))); + socket = new Socket(InetAddress.getByName(addr.hostname), addr.port); + parser.setInput(new InputStreamReader(socket.getInputStream())); - writer = new OutputStreamWriter(Channels.newOutputStream(socket)); + writer = new OutputStreamWriter(socket.getOutputStream()); - sendStanza(""); + sendOpenStream(); - parser.next(); // stream:stream - streamID = parser.getAttributeValue(null, "id"); - if (streamID == null || streamID.isEmpty()) { - throw new Exception("STREAM TO " + to + " INVALID FIRST PACKET"); - } + parser.next(); // stream:stream + streamID = parser.getAttributeValue(null, "id"); + if (streamID == null || streamID.isEmpty()) { + throw new Exception("STREAM TO " + to + " INVALID FIRST PACKET"); + } - LOGGER.info("STREAM TO " + to + " " + streamID + " OPEN"); - XMPPComponent.addConnectionOut(ConnectionOut.this); + LOGGER.info("STREAM TO " + to + " " + streamID + " OPEN"); + XMPPComponent.addConnectionOut(ConnectionOut.this); - if (checkSID != null) { - sendDialbackVerify(checkSID, dbKey); + while (parser.next() != XmlPullParser.END_DOCUMENT) { + if (parser.getEventType() != XmlPullParser.START_TAG) { + continue; + } + logParser(); + + String tag = parser.getName(); + if (tag.equals("result") && parser.getNamespace().equals(NS_DB)) { + String type = parser.getAttributeValue(null, "type"); + if (type != null && type.equals("valid")) { + streamReady = true; + LOGGER.info("STREAM TO " + to + " " + streamID + " READY"); + + String cache = XMPPComponent.getFromCache(to); + if (cache != null) { + LOGGER.info("STREAM TO " + to + " " + streamID + " SENDING CACHE"); + sendStanza(cache); } - sendStanza("" + generateDialbackKey(to, XMPPComponent.HOSTNAME, streamID) + ""); - - while (parser.next() != XmlPullParser.END_DOCUMENT) { - if (parser.getEventType() != XmlPullParser.START_TAG) { - continue; - } - logParser(); - - String tag = parser.getName(); - if (tag.equals("db:result")) { - String type = parser.getAttributeValue(null, "type"); - if (type != null && type.equals("valid")) { - streamReady = true; - LOGGER.info("STREAM TO " + to + " " + streamID + " READY"); - - String cache = XMPPComponent.getFromCache(to); - if (cache != null) { - LOGGER.info("STREAM TO " + to + " " + streamID + " SENDING CACHE"); - sendStanza(cache); - } - - } else { - LOGGER.info("STREAM TO " + to + " " + streamID + " DIALBACK FAIL"); - } - XmlUtils.skip(parser); - } else if (tag.equals("db:verify")) { - String from = parser.getAttributeValue(null, "from"); - String type = parser.getAttributeValue(null, "type"); - String sid = parser.getAttributeValue(null, "id"); - if (from != null && from.equals(to) && sid != null && !sid.isEmpty() && type != null) { - ConnectionIn c = XMPPComponent.getConnectionIn(sid); - if (c != null) { - c.sendDialbackResult(from, type); - } - } - XmlUtils.skip(parser); - } else { - LOGGER.info("STREAM TO " + to + " " + streamID + ": " + XmlUtils.parseToString(parser, true)); - } + } else { + LOGGER.info("STREAM TO " + to + " " + streamID + " DIALBACK FAIL"); + } + XmlUtils.skip(parser); + } else if (tag.equals("verify") && parser.getNamespace().equals(NS_DB)) { + String from = parser.getAttributeValue(null, "from"); + String type = parser.getAttributeValue(null, "type"); + String sid = parser.getAttributeValue(null, "id"); + if (from != null && from.equals(to) && sid != null && !sid.isEmpty() && type != null) { + ConnectionIn c = XMPPComponent.getConnectionIn(sid); + if (c != null) { + c.sendDialbackResult(from, type); } - - LOGGER.warning("STREAM TO " + to + " " + streamID + " FINISHED"); - XMPPComponent.removeConnectionOut(ConnectionOut.this); - closeConnection(); - } catch (EOFException eofex) { - LOGGER.info(String.format("STREAM %s %s CLOSED (dirty)", to, streamID)); - XMPPComponent.removeConnectionOut(ConnectionOut.this); - closeConnection(); - } catch (Exception e) { - LOGGER.log(Level.SEVERE, "s2s out exception", e); - XMPPComponent.removeConnectionOut(ConnectionOut.this); + } + XmlUtils.skip(parser); + } else if (tag.equals("features") && parser.getNamespace().equals(NS_STREAM)) { + StreamFeatures features = StreamFeatures.parse(parser); + if (!isSecured() && features.STARTTLS >= 0) { + System.out.println("STREAM TO " + to + " " + streamID + " SECURING"); + sendStanza(""); + } else { + processDialback(); + } + } else if (tag.equals("proceed") && parser.getNamespace().equals(NS_TLS)) { + try { + socket = sc.getSocketFactory().createSocket(socket, socket.getInetAddress().getHostAddress(), + socket.getPort(), true); + ((SSLSocket) socket).startHandshake(); + setSecured(true); + System.out.println("STREAM " + streamID + " SECURED"); + restartParser(); + sendOpenStream(); + } catch (SSLException sex) { + System.err.println("STREAM " + streamID + " SSL ERROR"); + sendStanza(""); + XMPPComponent.removeConnectionOut(this); closeConnection(); } + } else if (isSecured() && tag.equals("stream") && parser.getNamespace().equals(NS_STREAM)) { + streamID = parser.getAttributeValue(null, "id"); + } else { + LOGGER.info("STREAM TO " + to + " " + streamID + ": " + XmlUtils.parseToString(parser, true)); } + } - @Override - public void failed(Throwable exc, AsynchronousSocketChannel attachment) { - LOGGER.log(Level.WARNING, "s2s out failed", exc); - XMPPComponent.removeConnectionOut(ConnectionOut.this); - closeConnection(); - } - }); + LOGGER.warning("STREAM TO " + to + " " + streamID + " FINISHED"); + XMPPComponent.removeConnectionOut(ConnectionOut.this); + closeConnection(); + } catch (EOFException eofex) { + LOGGER.info(String.format("STREAM %s %s CLOSED (dirty)", to, streamID)); + XMPPComponent.removeConnectionOut(ConnectionOut.this); + closeConnection(); } catch (Exception e) { - LOGGER.warning(e.toString()); - XMPPComponent.removeConnectionOut(this); + LOGGER.log(Level.SEVERE, "s2s out exception", e); + XMPPComponent.removeConnectionOut(ConnectionOut.this); closeConnection(); } } -- cgit v1.2.3