private static LocalOutgoingServerSession attemptDialbackOverTLS( Connection connection, XMPPPacketReader reader, String domain, String hostname, String id) { final Logger log = LoggerFactory.getLogger( LocalOutgoingServerSession.class.getName() + "['" + hostname + "']"); if (ServerDialback.isEnabled() || ServerDialback.isEnabledForSelfSigned()) { log.debug("Trying to connecting using dialback over TLS."); ServerDialback method = new ServerDialback(connection, domain); OutgoingServerSocketReader newSocketReader = new OutgoingServerSocketReader(reader); if (method.authenticateDomain(newSocketReader, domain, hostname, id)) { log.debug("Dialback over TLS was successful."); StreamID streamID = new BasicStreamIDFactory().createStreamID(id); LocalOutgoingServerSession session = new LocalOutgoingServerSession(domain, connection, newSocketReader, streamID); connection.init(session); // Set the hostname as the address of the session session.setAddress(new JID(null, hostname, null)); return session; } else { log.debug("Dialback over TLS failed"); return null; } } else { log.debug("Skipping server dialback attempt as it has been disabled by local configuration."); return null; } }
private static LocalOutgoingServerSession attemptSASLexternal( SocketConnection connection, MXParser xpp, XMPPPacketReader reader, String domain, String hostname, String id, StringBuilder openingStream) throws DocumentException, IOException, XmlPullParserException { final Logger log = LoggerFactory.getLogger( LocalOutgoingServerSession.class.getName() + "['" + hostname + "']"); log.debug("Starting EXTERNAL SASL."); if (doExternalAuthentication(domain, connection, reader)) { log.debug("EXTERNAL SASL was successful."); // SASL was successful so initiate a new stream connection.deliverRawText(openingStream.toString()); // Reset the parser // xpp.resetInput(); // // Reset the parser to use the new secured reader xpp.setInput( new InputStreamReader( connection.getTLSStreamHandler().getInputStream(), StandardCharsets.UTF_8)); // Skip the opening stream sent by the server for (int eventType = xpp.getEventType(); eventType != XmlPullParser.START_TAG; ) { eventType = xpp.next(); } // SASL authentication was successful so create new OutgoingServerSession id = xpp.getAttributeValue("", "id"); StreamID streamID = new BasicStreamIDFactory().createStreamID(id); LocalOutgoingServerSession session = new LocalOutgoingServerSession( domain, connection, new OutgoingServerSocketReader(reader), streamID); connection.init(session); // Set the hostname as the address of the session session.setAddress(new JID(null, hostname, null)); // Set that the session was created using TLS+SASL (no server dialback) session.usingServerDialback = false; return session; } else { log.debug("EXTERNAL SASL failed."); return null; } }
/** * Establishes a new outgoing session to a remote server. If the remote server supports TLS and * SASL then the new outgoing connection will be secured with TLS and authenticated using SASL. * However, if TLS or SASL is not supported by the remote server or if an error occured while * securing or authenticating the connection using SASL then server dialback method will be used. * * @param domain the local domain to authenticate with the remote server. * @param hostname the hostname of the remote server. * @param port default port to use to establish the connection. * @return new outgoing session to a remote server. */ private static LocalOutgoingServerSession createOutgoingSession( String domain, String hostname, int port) { String localDomainName = XMPPServer.getInstance().getServerInfo().getXMPPDomain(); boolean useTLS = JiveGlobals.getBooleanProperty(ConnectionSettings.Server.TLS_ENABLED, true); RemoteServerConfiguration configuration = RemoteServerManager.getConfiguration(hostname); if (configuration != null) { // TODO Use the specific TLS configuration for this remote server // useTLS = configuration.isTLSEnabled(); } // Connect to remote server using XMPP 1.0 (TLS + SASL EXTERNAL or TLS + server dialback or // server dialback) String realHostname = null; int realPort = port; Socket socket = null; // Get a list of real hostnames to connect to using DNS lookup of the specified hostname List<DNSUtil.HostAddress> hosts = DNSUtil.resolveXMPPDomain(hostname, port); for (Iterator<DNSUtil.HostAddress> it = hosts.iterator(); it.hasNext(); ) { try { socket = new Socket(); DNSUtil.HostAddress address = it.next(); realHostname = address.getHost(); realPort = address.getPort(); Log.debug( "LocalOutgoingServerSession: OS - Trying to connect to " + hostname + ":" + port + "(DNS lookup: " + realHostname + ":" + realPort + ")"); // Establish a TCP connection to the Receiving Server socket.connect( new InetSocketAddress(realHostname, realPort), RemoteServerManager.getSocketTimeout()); Log.debug( "LocalOutgoingServerSession: OS - Plain connection to " + hostname + ":" + port + " successful"); break; } catch (Exception e) { Log.warn( "Error trying to connect to remote server: " + hostname + "(DNS lookup: " + realHostname + ":" + realPort + "): " + e.toString()); try { if (socket != null) { socket.close(); } } catch (IOException ex) { Log.debug( "Additional exception while trying to close socket when connection to remote server failed: " + ex.toString()); } } } if (!socket.isConnected()) { return null; } SocketConnection connection = null; try { connection = new SocketConnection(XMPPServer.getInstance().getPacketDeliverer(), socket, false); // Send the stream header StringBuilder openingStream = new StringBuilder(); openingStream.append("<stream:stream"); openingStream.append(" xmlns:db=\"jabber:server:dialback\""); openingStream.append(" xmlns:stream=\"http://etherx.jabber.org/streams\""); openingStream.append(" xmlns=\"jabber:server\""); openingStream.append(" from=\"").append(localDomainName).append("\""); // OF-673 openingStream.append(" to=\"").append(hostname).append("\""); openingStream.append(" version=\"1.0\">"); connection.deliverRawText(openingStream.toString()); // Set a read timeout (of 5 seconds) so we don't keep waiting forever int soTimeout = socket.getSoTimeout(); socket.setSoTimeout(5000); XMPPPacketReader reader = new XMPPPacketReader(); reader .getXPPParser() .setInput(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8)); // Get the answer from the Receiving Server XmlPullParser xpp = reader.getXPPParser(); for (int eventType = xpp.getEventType(); eventType != XmlPullParser.START_TAG; ) { eventType = xpp.next(); } String serverVersion = xpp.getAttributeValue("", "version"); String id = xpp.getAttributeValue("", "id"); // Check if the remote server is XMPP 1.0 compliant if (serverVersion != null && decodeVersion(serverVersion)[0] >= 1) { // Restore default timeout socket.setSoTimeout(soTimeout); // Get the stream features Element features = reader.parseDocument().getRootElement(); if (features != null) { // Check if TLS is enabled if (useTLS && features.element("starttls") != null) { // Secure the connection with TLS and authenticate using SASL LocalOutgoingServerSession answer; answer = secureAndAuthenticate(hostname, connection, reader, openingStream, domain); if (answer != null) { // Everything went fine so return the secured and // authenticated connection return answer; } } // Check if we are going to try server dialback (XMPP 1.0) else if (ServerDialback.isEnabled() && features.element("dialback") != null) { Log.debug( "LocalOutgoingServerSession: OS - About to try connecting using server dialback XMPP 1.0 with: " + hostname); ServerDialback method = new ServerDialback(connection, domain); OutgoingServerSocketReader newSocketReader = new OutgoingServerSocketReader(reader); if (method.authenticateDomain(newSocketReader, domain, hostname, id)) { Log.debug( "LocalOutgoingServerSession: OS - SERVER DIALBACK XMPP 1.0 with " + hostname + " was successful"); StreamID streamID = new BasicStreamIDFactory().createStreamID(id); LocalOutgoingServerSession session = new LocalOutgoingServerSession(domain, connection, newSocketReader, streamID); connection.init(session); // Set the hostname as the address of the session session.setAddress(new JID(null, hostname, null)); return session; } else { Log.debug( "LocalOutgoingServerSession: OS - Error, SERVER DIALBACK with " + hostname + " failed"); } } } else { Log.debug("LocalOutgoingServerSession: OS - Error, <starttls> was not received"); } } // Something went wrong so close the connection and try server dialback over // a plain connection if (connection != null) { connection.close(); } } catch (SSLHandshakeException e) { Log.debug( "LocalOutgoingServerSession: Handshake error while creating secured outgoing session to remote " + "server: " + hostname + "(DNS lookup: " + realHostname + ":" + realPort + "):", e); // Close the connection if (connection != null) { connection.close(); } } catch (Exception e) { Log.error( "Error creating secured outgoing session to remote server: " + hostname + "(DNS lookup: " + realHostname + ":" + realPort + ")", e); // Close the connection if (connection != null) { connection.close(); } } if (ServerDialback.isEnabled()) { Log.debug( "LocalOutgoingServerSession: OS - Going to try connecting using server dialback with: " + hostname); // Use server dialback (pre XMPP 1.0) over a plain connection return new ServerDialback().createOutgoingSession(domain, hostname, port); } return null; }